[med-svn] [gatk] 01/02: Imported Upstream version 3.3

Andreas Tille tille at debian.org
Thu Mar 26 12:39:07 UTC 2015


This is an automated email from the git hooks/post-receive script.

tille pushed a commit to branch master
in repository gatk.

commit a61d1aa040794805beba16bfb288a4d27a82a393
Author: Andreas Tille <tille at debian.org>
Date:   Thu Mar 26 13:34:37 2015 +0100

    Imported Upstream version 3.3
---
 .gitignore                                         |    29 +
 README.md                                          |     3 +
 ant-bridge.sh                                      |   173 +
 intellij_example.tar.bz2                           |   Bin 0 -> 7520 bytes
 licensing/private_license.txt                      |    48 +
 licensing/protected_license.txt                    |    48 +
 licensing/public_license.txt                       |    22 +
 pom.xml                                            |   756 +
 public/VectorPairHMM/README.md                     |    72 +
 public/VectorPairHMM/pom.xml                       |   122 +
 public/VectorPairHMM/src/main/c++/.gitignore       |    16 +
 .../src/main/c++/LoadTimeInitializer.cc            |   205 +
 .../src/main/c++/LoadTimeInitializer.h             |    86 +
 public/VectorPairHMM/src/main/c++/Makefile         |   126 +
 public/VectorPairHMM/src/main/c++/Sandbox.cc       |   106 +
 public/VectorPairHMM/src/main/c++/Sandbox.h        |    96 +
 public/VectorPairHMM/src/main/c++/Sandbox.java     |   306 +
 .../main/c++/Sandbox_JNIHaplotypeDataHolderClass.h |    13 +
 .../src/main/c++/Sandbox_JNIReadDataHolderClass.h  |    13 +
 .../src/main/c++/avx_function_instantiations.cc    |    45 +
 public/VectorPairHMM/src/main/c++/baseline.cc      |   157 +
 .../src/main/c++/common_data_structure.h           |   215 +
 public/VectorPairHMM/src/main/c++/define-double.h  |   205 +
 public/VectorPairHMM/src/main/c++/define-float.h   |   206 +
 .../VectorPairHMM/src/main/c++/define-sse-double.h |   173 +
 .../VectorPairHMM/src/main/c++/define-sse-float.h  |   173 +
 public/VectorPairHMM/src/main/c++/headers.h        |    71 +
 public/VectorPairHMM/src/main/c++/jni_common.h     |    60 +
 public/VectorPairHMM/src/main/c++/jnidebug.h       |   191 +
 ...te_gatk_utils_pairhmm_DebugJNILoglessPairHMM.cc |   175 +
 ...ute_gatk_utils_pairhmm_DebugJNILoglessPairHMM.h |    86 +
 ...tute_gatk_utils_pairhmm_VectorLoglessPairHMM.cc |   416 +
 ...itute_gatk_utils_pairhmm_VectorLoglessPairHMM.h |    96 +
 .../VectorPairHMM/src/main/c++/pairhmm-1-base.cc   |    65 +
 .../src/main/c++/pairhmm-template-kernel.cc        |   380 +
 .../src/main/c++/pairhmm-template-main.cc          |   113 +
 public/VectorPairHMM/src/main/c++/run.sh           |    32 +
 public/VectorPairHMM/src/main/c++/shift_template.c |   113 +
 .../src/main/c++/sse_function_instantiations.cc    |    44 +
 public/VectorPairHMM/src/main/c++/template.h       |   119 +
 public/VectorPairHMM/src/main/c++/utils.cc         |   567 +
 public/VectorPairHMM/src/main/c++/utils.h          |    85 +
 public/c/SeparateQltout.cc                         |    70 +
 public/c/libenvironhack/Makefile                   |    10 +
 public/c/libenvironhack/libenvironhack.c           |    37 +
 public/c/libenvironhack/libenvironhack.dylib       |   Bin 0 -> 28904 bytes
 public/chainFiles/b36tob37.chain                   | 30854 ++++++++++++
 public/chainFiles/b37tob36.chain                   | 12268 +++++
 public/chainFiles/b37tohg18.chain                  | 49040 +++++++++++++++++++
 public/chainFiles/b37tohg19.chain                  |    75 +
 public/chainFiles/hg18tob37.chain                  | 30854 ++++++++++++
 public/chainFiles/hg19toHg18.chain                 | 49040 +++++++++++++++++++
 public/chainFiles/makeChains.py                    |    50 +
 public/doc/Ant_Help.tex                            |     9 +
 public/doc/GATK_Coding_Standards.pdf               |   Bin 0 -> 133046 bytes
 public/doc/GATK_Coding_Standards.tex               |   288 +
 public/doc/README                                  |    86 +
 public/external-example/pom.xml                    |   272 +
 .../java/org/mycompany/app/MyExampleWalker.java    |    56 +
 .../app/MyExampleWalkerIntegrationTest.java        |    54 +
 .../org/mycompany/app/MyExampleWalkerUnitTest.java |    41 +
 public/gatk-engine/pom.xml                         |    94 +
 .../src/main/assembly/example-resources.xml        |    37 +
 .../broadinstitute/gatk/engine/ReadMetrics.java    |   121 +
 .../broadinstitute/gatk/engine/package-info.java   |    26 +
 .../gatk-engine/src/test/resources/exampleBAM.bam  |   Bin 0 -> 3635 bytes
 .../src/test/resources/exampleBAM.bam.bai          |   Bin 0 -> 232 bytes
 .../src/test/resources/exampleBAM.simple.bai       |   Bin 0 -> 232 bytes
 .../src/test/resources/exampleBAM.simple.bam       |   Bin 0 -> 3595 bytes
 .../src/test/resources/exampleDBSNP.vcf            |   282 +
 .../src/test/resources/exampleDBSNP.vcf.idx        |   Bin 0 -> 330 bytes
 .../src/test/resources/exampleFASTA-3contigs.fasta |    24 +
 .../src/test/resources/exampleFASTA-combined.fasta |  1675 +
 .../src/test/resources/exampleFASTA-windows.fasta  |     7 +
 .../src/test/resources/exampleFASTA.dict           |     2 +
 .../src/test/resources/exampleFASTA.fasta          |  1668 +
 .../src/test/resources/exampleFASTA.fasta.amb      |     1 +
 .../src/test/resources/exampleFASTA.fasta.ann      |     3 +
 .../src/test/resources/exampleFASTA.fasta.bwt      |   Bin 0 -> 37548 bytes
 .../src/test/resources/exampleFASTA.fasta.fai      |     1 +
 .../src/test/resources/exampleFASTA.fasta.pac      |   Bin 0 -> 25002 bytes
 .../src/test/resources/exampleFASTA.fasta.rbwt     |   Bin 0 -> 37548 bytes
 .../src/test/resources/exampleFASTA.fasta.rpac     |   Bin 0 -> 25002 bytes
 .../src/test/resources/exampleFASTA.fasta.rsa      |   Bin 0 -> 12528 bytes
 .../src/test/resources/exampleFASTA.fasta.sa       |   Bin 0 -> 12528 bytes
 .../src/test/resources/exampleGATKReport.eval      |    36 +
 .../src/test/resources/exampleGATKReportv1.tbl     |    36 +
 .../src/test/resources/exampleGATKReportv2.tbl     |    36 +
 .../gatk-engine/src/test/resources/exampleGRP.grp  |  1118 +
 .../src/test/resources/exampleINTERVAL.intervals   |     3 +
 .../gatk-engine/src/test/resources/exampleNORG.bam |   Bin 0 -> 3586 bytes
 .../src/test/resources/exampleNORG.bam.bai         |   Bin 0 -> 232 bytes
 .../test/resources/forAlleleFractionSimulation.vcf |    29 +
 .../resources/forAlleleFractionSimulation.vcf.idx  |   Bin 0 -> 2074 bytes
 .../src/test/resources/forLongInsert.vcf           |    16 +
 .../src/test/resources/forLongInsert.vcf.idx       |   Bin 0 -> 2019 bytes
 .../src/test/resources/forSimulation.vcf           |     8 +
 .../src/test/resources/forSimulation.vcf.idx       |   Bin 0 -> 2067 bytes
 public/gatk-engine/src/test/resources/testfile.sam |   450 +
 public/gatk-queue-extensions-generator/pom.xml     |    29 +
 .../extensions/gatk/ArgumentDefinitionField.java   |   558 +
 .../gatk/queue/extensions/gatk/ArgumentField.java  |   250 +
 .../extensions/gatk/GATKExtensionsGenerator.java   |   399 +
 .../queue/extensions/gatk/ReadFilterField.java     |    48 +
 public/gatk-queue-extensions-public/pom.xml        |   168 +
 .../src/main/assembly/example-resources.xml        |    20 +
 .../gatk/queue/qscripts/CNV/xhmmCNVpipeline.scala  |   615 +
 .../gatk/queue/qscripts/GATKResourcesBundle.scala  |   426 +
 .../queue/qscripts/examples/ExampleCountLoci.scala |    56 +
 .../qscripts/examples/ExampleCountReads.scala      |    87 +
 .../qscripts/examples/ExampleCustomWalker.scala    |    73 +
 .../qscripts/examples/ExamplePrintReads.scala      |    53 +
 .../qscripts/examples/ExampleReadFilter.scala      |    48 +
 .../examples/ExampleRetryMemoryLimit.scala         |    53 +
 .../gatk/queue/qscripts/examples/HelloWorld.scala  |    36 +
 .../gatk/queue/qscripts/lib/ChunkVCF.scala         |   115 +
 .../gatk/queue/qscripts/lib/Vcf2Table.scala        |    55 +
 .../gatk/queue/qscripts/lib/VcfToPed.scala         |   225 +
 .../gatk/queue/extensions/cancer/MuTect.scala      |   420 +
 .../queue/extensions/gatk/BamGatherFunction.scala  |    57 +
 .../extensions/gatk/CatVariantsGatherer.scala      |    59 +
 .../extensions/gatk/ContigScatterFunction.scala    |    50 +
 .../gatk/DistributedScatterFunction.scala          |    52 +
 .../gatk/queue/extensions/gatk/DoC/package.scala   |   242 +
 .../gatk/queue/extensions/gatk/GATKIntervals.scala |    98 +
 .../extensions/gatk/GATKScatterFunction.scala      |   111 +
 .../extensions/gatk/IntervalScatterFunction.scala  |    46 +
 .../extensions/gatk/LocusScatterFunction.scala     |    43 +
 .../extensions/gatk/ReadScatterFunction.scala      |    57 +
 .../gatk/queue/extensions/gatk/TaggedFile.scala    |    58 +
 .../queue/extensions/gatk/VcfGatherFunction.scala  |    53 +
 .../gatk/WriteFlankingIntervalsFunction.scala      |    49 +
 .../extensions/picard/AddOrReplaceReadGroups.scala |    90 +
 .../extensions/picard/CalculateHsMetrics.scala     |    68 +
 .../extensions/picard/CollectGcBiasMetrics.scala   |    57 +
 .../extensions/picard/CollectMultipleMetrics.scala |    61 +
 .../gatk/queue/extensions/picard/FastqToSam.scala  |   104 +
 .../queue/extensions/picard/MarkDuplicates.scala   |    79 +
 .../queue/extensions/picard/MergeSamFiles.scala    |    74 +
 .../extensions/picard/PicardBamFunction.scala      |    63 +
 .../extensions/picard/PicardMetricsFunction.scala  |    54 +
 .../gatk/queue/extensions/picard/ReorderSam.scala  |    73 +
 .../gatk/queue/extensions/picard/RevertSam.scala   |    86 +
 .../gatk/queue/extensions/picard/SamToFastq.scala  |   107 +
 .../gatk/queue/extensions/picard/SortSam.scala     |    63 +
 .../queue/extensions/picard/ValidateSamFile.scala  |    85 +
 .../samtools/SamtoolsCommandLineFunction.scala     |    37 +
 .../samtools/SamtoolsIndexFunction.scala           |    56 +
 .../samtools/SamtoolsMergeFunction.scala           |    64 +
 .../gatk/queue/extensions/snpeff/SnpEff.scala      |    68 +
 .../extensions/gatk/GATKIntervalsUnitTest.scala    |   154 +
 .../examples/ExampleCountLociQueueTest.scala       |    46 +
 .../examples/ExampleCountReadsQueueTest.scala      |    43 +
 .../examples/ExamplePrintReadsQueueTest.scala      |    83 +
 .../examples/ExampleReadFilterQueueTest.scala      |    91 +
 .../ExampleRetryMemoryLimitQueueTest.scala         |    47 +
 .../pipeline/examples/HelloWorldQueueTest.scala    |   152 +
 public/gatk-queue/pom.xml                          |   107 +
 .../broadinstitute/gatk/queue/QueueVersion.java    |    32 +
 .../broadinstitute/gatk/queue/package-info.java    |    26 +
 .../gatk/queue/util/queueJobReport.R               |   240 +
 .../broadinstitute/gatk/queue/QCommandLine.scala   |   295 +
 .../broadinstitute/gatk/queue/QCommandPlugin.scala |    36 +
 .../org/broadinstitute/gatk/queue/QException.scala |    31 +
 .../org/broadinstitute/gatk/queue/QScript.scala    |   184 +
 .../broadinstitute/gatk/queue/QScriptManager.scala |   168 +
 .../org/broadinstitute/gatk/queue/QSettings.scala  |   101 +
 .../gatk/queue/engine/CommandLineJobManager.scala  |    35 +
 .../gatk/queue/engine/CommandLineJobRunner.scala   |   107 +
 .../queue/engine/CommandLinePluginManager.scala    |    33 +
 .../gatk/queue/engine/FunctionEdge.scala           |   211 +
 .../gatk/queue/engine/InProcessJobManager.scala    |    34 +
 .../gatk/queue/engine/InProcessRunner.scala        |    66 +
 .../gatk/queue/engine/JobManager.scala             |    60 +
 .../gatk/queue/engine/JobRunInfo.scala             |    79 +
 .../gatk/queue/engine/JobRunner.scala              |    89 +
 .../gatk/queue/engine/MappingEdge.scala            |    39 +
 .../broadinstitute/gatk/queue/engine/QEdge.scala   |    57 +
 .../broadinstitute/gatk/queue/engine/QGraph.scala  |  1228 +
 .../gatk/queue/engine/QGraphSettings.scala         |    85 +
 .../broadinstitute/gatk/queue/engine/QNode.scala   |    45 +
 .../gatk/queue/engine/QStatusMessenger.scala       |    41 +
 .../gatk/queue/engine/RunnerStatus.scala           |    34 +
 .../gatk/queue/engine/drmaa/DrmaaJobManager.scala  |    62 +
 .../gatk/queue/engine/drmaa/DrmaaJobRunner.scala   |   169 +
 .../engine/gridengine/GridEngineJobManager.scala   |    33 +
 .../engine/gridengine/GridEngineJobRunner.scala    |    88 +
 .../gatk/queue/engine/lsf/Lsf706JobManager.scala   |    40 +
 .../gatk/queue/engine/lsf/Lsf706JobRunner.scala    |   421 +
 .../engine/pbsengine/PbsEngineJobManager.scala     |    33 +
 .../engine/pbsengine/PbsEngineJobRunner.scala      |    98 +
 .../gatk/queue/engine/shell/ShellJobManager.scala  |    35 +
 .../gatk/queue/engine/shell/ShellJobRunner.scala   |    91 +
 .../gatk/queue/function/CommandLineFunction.scala  |   341 +
 .../gatk/queue/function/InProcessFunction.scala    |    48 +
 .../queue/function/JavaCommandLineFunction.scala   |   139 +
 .../gatk/queue/function/ListWriterFunction.scala   |    60 +
 .../gatk/queue/function/QFunction.scala            |   517 +
 .../gatk/queue/function/RetryMemoryLimit.scala     |   103 +
 .../function/scattergather/CloneFunction.scala     |   111 +
 .../scattergather/ConcatenateLogsFunction.scala    |    56 +
 .../function/scattergather/GatherFunction.scala    |    72 +
 .../function/scattergather/GathererFunction.scala  |    44 +
 .../function/scattergather/ScatterFunction.scala   |    78 +
 .../scattergather/ScatterGatherableFunction.scala  |   376 +
 .../scattergather/SimpleTextGatherFunction.scala   |    89 +
 .../library/clf/vcf/VCFExtractIntervals.scala      |    46 +
 .../queue/library/clf/vcf/VCFExtractSamples.scala  |    58 +
 .../gatk/queue/library/ipf/SortByRef.scala         |    82 +
 .../library/ipf/vcf/VCFExtractIntervals.scala      |    85 +
 .../queue/library/ipf/vcf/VCFExtractSamples.scala  |    62 +
 .../queue/library/ipf/vcf/VCFExtractSites.scala    |    99 +
 .../queue/library/ipf/vcf/VCFSimpleMerge.scala     |   107 +
 .../gatk/queue/util/ClassFieldCache.scala          |   219 +
 .../gatk/queue/util/CollectionUtils.scala          |   116 +
 .../gatk/queue/util/EmailMessage.scala             |   140 +
 .../gatk/queue/util/EmailSettings.scala            |    55 +
 .../broadinstitute/gatk/queue/util/Logging.scala   |    62 +
 .../queue/util/PrimitiveOptionConversions.scala    |   142 +
 .../gatk/queue/util/QJobReport.scala               |   110 +
 .../gatk/queue/util/QJobsReporter.scala            |   122 +
 .../gatk/queue/util/QScriptUtils.scala             |   101 +
 .../gatk/queue/util/ReflectionUtils.scala          |   170 +
 .../gatk/queue/util/RemoteFile.scala               |    42 +
 .../gatk/queue/util/RemoteFileConverter.scala      |    46 +
 .../org/broadinstitute/gatk/queue/util/Retry.scala |    70 +
 .../gatk/queue/util/RetryException.scala           |    34 +
 .../util/ScalaCompoundArgumentTypeDescriptor.scala |   114 +
 .../gatk/queue/util/ShellUtils.scala               |    61 +
 .../gatk/queue/util/StringFileConversions.scala    |   113 +
 .../gatk/queue/util/SystemUtils.scala              |    67 +
 .../gatk/queue/util/TextFormatUtils.scala          |    56 +
 .../gatk/queue/util/VCF_BAM_utilities.scala        |    79 +
 .../function/CommandLineFunctionUnitTest.scala     |   196 +
 .../gatk/queue/pipeline/QueueTest.scala            |   265 +
 .../gatk/queue/pipeline/QueueTestEvalSpec.scala    |    59 +
 .../gatk/queue/pipeline/QueueTestSpec.scala        |    68 +
 .../gatk/queue/util/ShellUtilsUnitTest.scala       |    82 +
 .../queue/util/StringFileConversionsUnitTest.scala |   128 +
 .../gatk/queue/util/SystemUtilsUnitTest.scala      |    44 +
 public/gatk-root/pom.xml                           |   717 +
 public/gatk-tools-public/pom.xml                   |    81 +
 .../main/java/htsjdk/samtools/GATKBAMFileSpan.java |   308 +
 .../src/main/java/htsjdk/samtools/GATKBin.java     |   135 +
 .../src/main/java/htsjdk/samtools/GATKChunk.java   |   116 +
 .../java/htsjdk/samtools/PicardNamespaceUtils.java |    40 +
 .../gatk/engine/CommandLineExecutable.java         |   229 +
 .../gatk/engine/CommandLineGATK.java               |   385 +
 .../gatk/engine/GenomeAnalysisEngine.java          |  1280 +
 .../broadinstitute/gatk/engine/ReadProperties.java |   198 +
 .../broadinstitute/gatk/engine/WalkerManager.java  |   431 +
 .../gatk/engine/alignment/Aligner.java             |    74 +
 .../gatk/engine/alignment/Alignment.java           |   246 +
 .../gatk/engine/alignment/bwa/BWAAligner.java      |    63 +
 .../engine/alignment/bwa/BWAConfiguration.java     |    79 +
 .../gatk/engine/alignment/bwa/BWTFiles.java        |   259 +
 .../alignment/bwa/java/AlignerTestHarness.java     |   189 +
 .../alignment/bwa/java/AlignmentMatchSequence.java |   175 +
 .../engine/alignment/bwa/java/AlignmentState.java  |    38 +
 .../engine/alignment/bwa/java/BWAAlignment.java    |   215 +
 .../engine/alignment/bwa/java/BWAJavaAligner.java  |   418 +
 .../gatk/engine/alignment/bwa/java/LowerBound.java |   113 +
 .../gatk/engine/alignment/package-info.java        |    26 +
 .../engine/alignment/reference/bwt/AMBWriter.java  |    93 +
 .../engine/alignment/reference/bwt/ANNWriter.java  |   120 +
 .../gatk/engine/alignment/reference/bwt/BWT.java   |   197 +
 .../engine/alignment/reference/bwt/BWTReader.java  |   114 +
 .../bwt/BWTSupplementaryFileGenerator.java         |    85 +
 .../engine/alignment/reference/bwt/BWTWriter.java  |    96 +
 .../gatk/engine/alignment/reference/bwt/Bases.java |   133 +
 .../engine/alignment/reference/bwt/Counts.java     |   176 +
 .../reference/bwt/CreateBWTFromReference.java      |   200 +
 .../alignment/reference/bwt/SequenceBlock.java     |    66 +
 .../alignment/reference/bwt/SuffixArray.java       |   183 +
 .../alignment/reference/bwt/SuffixArrayReader.java |   110 +
 .../alignment/reference/bwt/SuffixArrayWriter.java |    92 +
 .../reference/packing/BasePackedInputStream.java   |   120 +
 .../reference/packing/BasePackedOutputStream.java  |   165 +
 .../reference/packing/CreatePACFromReference.java  |    64 +
 .../alignment/reference/packing/PackUtils.java     |   160 +
 .../packing/UnsignedIntPackedInputStream.java      |   129 +
 .../packing/UnsignedIntPackedOutputStream.java     |   121 +
 .../engine/arguments/DbsnpArgumentCollection.java  |    46 +
 .../engine/arguments/GATKArgumentCollection.java   |   628 +
 ...ndardVariantContextInputArgumentCollection.java |    48 +
 .../gatk/engine/arguments/ValidationExclusion.java |    67 +
 .../gatk/engine/contexts/AlignmentContext.java     |   154 +
 .../engine/contexts/AlignmentContextUtils.java     |   150 +
 .../gatk/engine/contexts/ReferenceContext.java     |   217 +
 .../gatk/engine/datasources/package-info.java      |    26 +
 .../engine/datasources/providers/AllLocusView.java |   169 +
 .../datasources/providers/CoveredLocusView.java    |    63 +
 .../IntervalOverlappingRODsFromStream.java         |   168 +
 .../providers/IntervalReferenceOrderedView.java    |   184 +
 .../providers/InvalidPositionException.java        |    46 +
 .../datasources/providers/LocusReferenceView.java  |   236 +
 .../providers/LocusShardDataProvider.java          |   100 +
 .../engine/datasources/providers/LocusView.java    |   220 +
 .../providers/ManagingReferenceOrderedView.java    |   117 +
 .../providers/RODMetaDataContainer.java            |    83 +
 .../providers/ReadBasedReferenceOrderedView.java   |    69 +
 .../datasources/providers/ReadReferenceView.java   |   102 +
 .../providers/ReadShardDataProvider.java           |    82 +
 .../engine/datasources/providers/ReadView.java     |    88 +
 .../providers/ReferenceOrderedView.java            |    33 +
 .../datasources/providers/ReferenceView.java       |   131 +
 .../engine/datasources/providers/RodLocusView.java |   197 +
 .../datasources/providers/ShardDataProvider.java   |   197 +
 .../gatk/engine/datasources/providers/View.java    |    55 +
 .../engine/datasources/providers/package-info.java |    26 +
 .../reads/ActiveRegionShardBalancer.java           |    85 +
 .../engine/datasources/reads/BAMAccessPlan.java    |   170 +
 .../gatk/engine/datasources/reads/BAMSchedule.java |   530 +
 .../engine/datasources/reads/BAMScheduler.java     |   320 +
 .../reads/BGZFBlockLoadingDispatcher.java          |    86 +
 .../engine/datasources/reads/BlockInputStream.java |   450 +
 .../gatk/engine/datasources/reads/BlockLoader.java |   189 +
 .../engine/datasources/reads/FileHandleCache.java  |   232 +
 .../gatk/engine/datasources/reads/FilePointer.java |   436 +
 .../engine/datasources/reads/GATKBAMIndex.java     |   468 +
 .../engine/datasources/reads/GATKBAMIndexData.java |   121 +
 .../reads/IntervalOverlapFilteringIterator.java    |   205 +
 .../engine/datasources/reads/IntervalSharder.java  |    93 +
 .../gatk/engine/datasources/reads/LocusShard.java  |    60 +
 .../datasources/reads/LocusShardBalancer.java      |    58 +
 .../gatk/engine/datasources/reads/ReadShard.java   |   271 +
 .../datasources/reads/ReadShardBalancer.java       |   231 +
 .../engine/datasources/reads/SAMDataSource.java    |  1179 +
 .../gatk/engine/datasources/reads/SAMReaderID.java |   125 +
 .../gatk/engine/datasources/reads/Shard.java       |   253 +
 .../engine/datasources/reads/ShardBalancer.java    |    49 +
 .../engine/datasources/reads/package-info.java     |    26 +
 .../datasources/reads/utilities/BAMFileStat.java   |   185 +
 .../datasources/reads/utilities/BAMTagRenamer.java |   100 +
 .../reads/utilities/FindLargeShards.java           |   192 +
 .../reads/utilities/PrintBAMRegion.java            |   113 +
 .../reads/utilities/PrintBGZFBounds.java           |   137 +
 .../reads/utilities/UnzipSingleBlock.java          |    89 +
 .../datasources/reads/utilities/package-info.java  |    26 +
 .../datasources/reference/ReferenceDataSource.java |   199 +
 .../engine/datasources/reference/package-info.java |    26 +
 .../engine/datasources/rmd/DataStreamSegment.java  |    32 +
 .../gatk/engine/datasources/rmd/EntireStream.java  |    32 +
 .../datasources/rmd/MappedStreamSegment.java       |    48 +
 .../datasources/rmd/ReferenceOrderedDataPool.java  |   153 +
 .../rmd/ReferenceOrderedDataSource.java            |   256 +
 .../gatk/engine/datasources/rmd/ResourcePool.java  |   188 +
 .../gatk/engine/datasources/rmd/package-info.java  |    26 +
 .../AlleleBiasedDownsamplingUtils.java             |   369 +
 .../gatk/engine/downsampling/DownsampleType.java   |    39 +
 .../gatk/engine/downsampling/Downsampler.java      |   161 +
 .../engine/downsampling/DownsamplingMethod.java    |   142 +
 .../downsampling/DownsamplingReadsIterator.java    |   116 +
 .../engine/downsampling/DownsamplingUtils.java     |   107 +
 .../engine/downsampling/FractionalDownsampler.java |   129 +
 .../downsampling/FractionalDownsamplerFactory.java |    46 +
 .../engine/downsampling/LevelingDownsampler.java   |   242 +
 .../downsampling/PassThroughDownsampler.java       |   111 +
 .../PerSampleDownsamplingReadsIterator.java        |   207 +
 .../gatk/engine/downsampling/ReadsDownsampler.java |    56 +
 .../downsampling/ReadsDownsamplerFactory.java      |    38 +
 .../engine/downsampling/ReservoirDownsampler.java  |   219 +
 .../downsampling/ReservoirDownsamplerFactory.java  |    46 +
 .../downsampling/SimplePositionalDownsampler.java  |   171 +
 .../SimplePositionalDownsamplerFactory.java        |    46 +
 .../gatk/engine/executive/Accumulator.java         |   211 +
 .../executive/HierarchicalMicroScheduler.java      |   495 +
 .../executive/HierarchicalMicroSchedulerMBean.java |    86 +
 .../engine/executive/LinearMicroScheduler.java     |   130 +
 .../gatk/engine/executive/MicroScheduler.java      |   463 +
 .../gatk/engine/executive/MicroSchedulerMBean.java |    37 +
 .../gatk/engine/executive/OutputMergeTask.java     |   102 +
 .../gatk/engine/executive/ReduceTree.java          |   187 +
 .../gatk/engine/executive/ShardTraverser.java      |   163 +
 .../gatk/engine/executive/TreeReducer.java         |   127 +
 .../gatk/engine/executive/WindowMaker.java         |   217 +
 .../gatk/engine/executive/package-info.java        |    26 +
 .../gatk/engine/filters/BadCigarFilter.java        |   122 +
 .../gatk/engine/filters/BadMateFilter.java         |    47 +
 .../engine/filters/CountingFilteringIterator.java  |   150 +
 .../gatk/engine/filters/DuplicateReadFilter.java   |    66 +
 .../filters/FailsVendorQualityCheckFilter.java     |    41 +
 .../gatk/engine/filters/FilterManager.java         |    95 +
 .../gatk/engine/filters/LibraryReadFilter.java     |    49 +
 .../gatk/engine/filters/MalformedReadFilter.java   |   260 +
 .../gatk/engine/filters/MappingQualityFilter.java  |    46 +
 .../filters/MappingQualityUnavailableFilter.java   |    43 +
 .../engine/filters/MappingQualityZeroFilter.java   |    42 +
 .../gatk/engine/filters/MateSameStrandFilter.java  |    42 +
 .../gatk/engine/filters/MaxInsertSizeFilter.java   |    44 +
 .../engine/filters/MissingReadGroupFilter.java     |    41 +
 .../engine/filters/NDNCigarReadTransformer.java    |   118 +
 .../filters/NoOriginalQualityScoresFilter.java     |    65 +
 .../engine/filters/NotPrimaryAlignmentFilter.java  |    41 +
 .../gatk/engine/filters/Platform454Filter.java     |    43 +
 .../gatk/engine/filters/PlatformFilter.java        |    49 +
 .../gatk/engine/filters/PlatformUnitFilter.java    |    86 +
 .../engine/filters/PlatformUnitFilterHelper.java   |    87 +
 .../gatk/engine/filters/ReadFilter.java            |    60 +
 .../engine/filters/ReadGroupBlackListFilter.java   |   120 +
 .../gatk/engine/filters/ReadLengthFilter.java      |    48 +
 .../gatk/engine/filters/ReadNameFilter.java        |    44 +
 .../gatk/engine/filters/ReadStrandFilter.java      |    46 +
 .../filters/ReassignMappingQualityFilter.java      |    86 +
 .../filters/ReassignOneMappingQualityFilter.java   |    87 +
 .../gatk/engine/filters/SampleFilter.java          |    45 +
 .../gatk/engine/filters/SingleReadGroupFilter.java |    48 +
 .../gatk/engine/filters/UnmappedReadFilter.java    |    41 +
 .../gatk/engine/filters/package-info.java          |    26 +
 .../gatk/engine/io/DirectOutputTracker.java        |    48 +
 .../gatk/engine/io/FastqFileWriter.java            |    77 +
 .../gatk/engine/io/GATKSAMFileWriter.java          |    56 +
 .../gatk/engine/io/OutputTracker.java              |   178 +
 .../gatk/engine/io/ThreadGroupOutputTracker.java   |   170 +
 .../engine/io/storage/OutputStreamStorage.java     |   144 +
 .../engine/io/storage/SAMFileWriterStorage.java    |   157 +
 .../gatk/engine/io/storage/Storage.java            |    45 +
 .../gatk/engine/io/storage/StorageFactory.java     |    92 +
 .../io/storage/VariantContextWriterStorage.java    |   228 +
 .../stubs/OutputStreamArgumentTypeDescriptor.java  |   134 +
 .../gatk/engine/io/stubs/OutputStreamStub.java     |   142 +
 .../stubs/SAMFileReaderArgumentTypeDescriptor.java |    77 +
 .../stubs/SAMFileWriterArgumentTypeDescriptor.java |   106 +
 .../gatk/engine/io/stubs/SAMFileWriterStub.java    |   336 +
 .../broadinstitute/gatk/engine/io/stubs/Stub.java  |    69 +
 .../io/stubs/VCFWriterArgumentTypeDescriptor.java  |   148 +
 .../engine/io/stubs/VariantContextWriterStub.java  |   301 +
 .../gatk/engine/iterators/BoundedReadIterator.java |   159 +
 .../gatk/engine/iterators/GATKSAMIterator.java     |    56 +
 .../engine/iterators/GATKSAMIteratorAdapter.java   |   136 +
 .../engine/iterators/GATKSAMRecordIterator.java    |    57 +
 .../gatk/engine/iterators/GenomeLocusIterator.java |   100 +
 .../gatk/engine/iterators/IterableIterator.java    |    40 +
 .../MalformedBAMErrorReformatingIterator.java      |    69 +
 .../gatk/engine/iterators/NullSAMIterator.java     |    57 +
 .../gatk/engine/iterators/PeekingIterator.java     |    65 +
 .../engine/iterators/PositionTrackingIterator.java |   105 +
 .../gatk/engine/iterators/PushbackIterator.java    |    82 +
 .../gatk/engine/iterators/RNAReadTransformer.java  |    37 +
 .../engine/iterators/ReadFormattingIterator.java   |   140 +
 .../gatk/engine/iterators/ReadTransformer.java     |   205 +
 .../engine/iterators/ReadTransformersMode.java     |    53 +
 .../engine/iterators/VerifyingSamIterator.java     |    90 +
 .../gatk/engine/iterators/package-info.java        |    26 +
 .../gatk/engine/phonehome/GATKRunReport.java       |   786 +
 .../engine/phonehome/GATKRunReportException.java   |    99 +
 .../gatk/engine/refdata/RODRecordListImpl.java     |   129 +
 .../gatk/engine/refdata/RefMetaDataTracker.java    |   497 +
 .../refdata/ReferenceDependentFeatureCodec.java    |    43 +
 .../gatk/engine/refdata/ReferenceOrderedDatum.java |    66 +
 .../gatk/engine/refdata/SeekableRODIterator.java   |   412 +
 .../engine/refdata/VariantContextAdaptors.java     |   399 +
 .../gatk/engine/refdata/package-info.java          |    26 +
 .../gatk/engine/refdata/tracks/FeatureManager.java |   280 +
 .../refdata/tracks/IndexDictionaryUtils.java       |   114 +
 .../gatk/engine/refdata/tracks/RMDTrack.java       |   147 +
 .../engine/refdata/tracks/RMDTrackBuilder.java     |   430 +
 .../utils/FeatureToGATKFeatureIterator.java        |    74 +
 .../engine/refdata/utils/FlashBackIterator.java    |   221 +
 .../gatk/engine/refdata/utils/GATKFeature.java     |   109 +
 .../utils/LocationAwareSeekableRODIterator.java    |    49 +
 .../gatk/engine/refdata/utils/RMDTriplet.java      |    92 +
 .../gatk/engine/refdata/utils/RODRecordList.java   |    45 +
 .../gatk/engine/report/GATKReport.java             |   376 +
 .../gatk/engine/report/GATKReportColumn.java       |   147 +
 .../gatk/engine/report/GATKReportColumnFormat.java |    63 +
 .../gatk/engine/report/GATKReportDataType.java     |   236 +
 .../gatk/engine/report/GATKReportGatherer.java     |    62 +
 .../gatk/engine/report/GATKReportTable.java        |   779 +
 .../gatk/engine/report/GATKReportVersion.java      |   101 +
 .../resourcemanagement/ThreadAllocation.java       |   116 +
 .../gatk/engine/samples/Affection.java             |    47 +
 .../broadinstitute/gatk/engine/samples/Gender.java |    35 +
 .../gatk/engine/samples/PedReader.java             |   311 +
 .../engine/samples/PedigreeValidationType.java     |    42 +
 .../broadinstitute/gatk/engine/samples/Sample.java |   259 +
 .../gatk/engine/samples/SampleDB.java              |   338 +
 .../gatk/engine/samples/SampleDBBuilder.java       |   161 +
 .../broadinstitute/gatk/engine/samples/Trio.java   |    70 +
 .../engine/traversals/TAROrderedReadCache.java     |   168 +
 .../gatk/engine/traversals/TraversalEngine.java    |   124 +
 .../engine/traversals/TraverseActiveRegions.java   |   719 +
 .../gatk/engine/traversals/TraverseDuplicates.java |   205 +
 .../gatk/engine/traversals/TraverseLociNano.java   |   304 +
 .../gatk/engine/traversals/TraverseReadPairs.java  |   129 +
 .../gatk/engine/traversals/TraverseReadsNano.java  |   256 +
 .../gatk/engine/traversals/package-info.java       |    26 +
 .../walkers/ActiveRegionTraversalParameters.java   |    97 +
 .../gatk/engine/walkers/ActiveRegionWalker.java    |   196 +
 .../broadinstitute/gatk/engine/walkers/Allows.java |    51 +
 .../gatk/engine/walkers/Attribution.java           |    39 +
 .../gatk/engine/walkers/BAQMode.java               |    56 +
 .../org/broadinstitute/gatk/engine/walkers/By.java |    53 +
 .../gatk/engine/walkers/DataSource.java            |    58 +
 .../gatk/engine/walkers/Downsample.java            |    47 +
 .../gatk/engine/walkers/DuplicateWalker.java       |    57 +
 .../gatk/engine/walkers/LocusWalker.java           |    58 +
 .../gatk/engine/walkers/Multiplex.java             |    44 +
 .../gatk/engine/walkers/Multiplexer.java           |    52 +
 .../gatk/engine/walkers/NanoSchedulable.java       |    34 +
 .../gatk/engine/walkers/PartitionBy.java           |    39 +
 .../gatk/engine/walkers/PartitionType.java         |    61 +
 .../broadinstitute/gatk/engine/walkers/RMD.java    |    56 +
 .../gatk/engine/walkers/ReadFilters.java           |    45 +
 .../gatk/engine/walkers/ReadPairWalker.java        |    63 +
 .../gatk/engine/walkers/ReadWalker.java            |    55 +
 .../gatk/engine/walkers/RefWalker.java             |    39 +
 .../gatk/engine/walkers/Reference.java             |    47 +
 .../gatk/engine/walkers/RemoveProgramRecords.java  |    46 +
 .../gatk/engine/walkers/Requires.java              |    52 +
 .../gatk/engine/walkers/RodWalker.java             |    39 +
 .../gatk/engine/walkers/TreeReducible.java         |    49 +
 .../broadinstitute/gatk/engine/walkers/Walker.java |   177 +
 .../gatk/engine/walkers/WalkerName.java            |    42 +
 .../broadinstitute/gatk/engine/walkers/Window.java |    57 +
 .../walkers/diffengine/BAMDiffableReader.java      |   119 +
 .../engine/walkers/diffengine/DiffElement.java     |   125 +
 .../gatk/engine/walkers/diffengine/DiffEngine.java |   437 +
 .../gatk/engine/walkers/diffengine/DiffNode.java   |   249 +
 .../engine/walkers/diffengine/DiffObjects.java     |   276 +
 .../gatk/engine/walkers/diffengine/DiffValue.java  |    90 +
 .../engine/walkers/diffengine/DiffableReader.java  |    66 +
 .../gatk/engine/walkers/diffengine/Difference.java |   137 +
 .../diffengine/GATKReportDiffableReader.java       |   104 +
 .../walkers/diffengine/VCFDiffableReader.java      |   145 +
 .../org/broadinstitute/gatk/tools/CatVariants.java |   338 +
 .../broadinstitute/gatk/tools/ListAnnotations.java |    85 +
 .../tools/walkers/annotator/AlleleBalance.java     |   218 +
 .../walkers/annotator/AlleleBalanceBySample.java   |   181 +
 .../gatk/tools/walkers/annotator/BaseCounts.java   |    91 +
 .../annotator/ChromosomeCountConstants.java        |    44 +
 .../gatk/tools/walkers/annotator/LowMQ.java        |    91 +
 .../annotator/MappingQualityZeroBySample.java      |    86 +
 .../gatk/tools/walkers/annotator/NBaseCount.java   |    89 +
 .../gatk/tools/walkers/annotator/SnpEff.java       |   586 +
 .../gatk/tools/walkers/annotator/SnpEffUtil.java   |   154 +
 .../tools/walkers/annotator/VariantAnnotator.java  |   336 +
 .../walkers/annotator/VariantAnnotatorEngine.java  |   304 +
 .../walkers/annotator/VariantOverlapAnnotator.java |   224 +
 .../interfaces/ActiveRegionBasedAnnotation.java    |    42 +
 .../interfaces/AnnotationInterfaceManager.java     |   140 +
 .../annotator/interfaces/AnnotationType.java       |    28 +
 .../annotator/interfaces/AnnotatorCompatible.java  |    41 +
 .../interfaces/ExperimentalAnnotation.java         |    28 +
 .../annotator/interfaces/GenotypeAnnotation.java   |    54 +
 .../annotator/interfaces/InfoFieldAnnotation.java  |    62 +
 .../interfaces/RodRequiringAnnotation.java         |    28 +
 .../annotator/interfaces/StandardAnnotation.java   |    28 +
 .../interfaces/VariantAnnotatorAnnotation.java     |    43 +
 .../interfaces/WorkInProgressAnnotation.java       |    28 +
 .../tools/walkers/beagle/BeagleOutputToVCF.java    |   392 +
 .../tools/walkers/beagle/ProduceBeagleInput.java   |   463 +
 .../walkers/beagle/VariantsToBeagleUnphased.java   |   184 +
 .../gatk/tools/walkers/coverage/CallableLoci.java  |   396 +
 .../walkers/coverage/CompareCallableLoci.java      |   143 +
 .../gatk/tools/walkers/coverage/CoverageUtils.java |   241 +
 .../tools/walkers/coverage/DepthOfCoverage.java    |  1110 +
 .../walkers/coverage/DepthOfCoverageStats.java     |   352 +
 .../gatk/tools/walkers/coverage/DoCOutputType.java |    89 +
 .../walkers/coverage/GCContentByInterval.java      |   106 +
 .../diagnostics/CoveredByNSamplesSites.java        |   154 +
 .../walkers/diagnostics/ErrorRatePerCycle.java     |   215 +
 .../walkers/diagnostics/ReadGroupProperties.java   |   229 +
 .../diagnostics/ReadLengthDistribution.java        |   180 +
 .../tools/walkers/examples/GATKDocsExample.java    |    83 +
 .../tools/walkers/examples/GATKPaperGenotyper.java |   273 +
 .../fasta/FastaAlternateReferenceMaker.java        |   187 +
 .../tools/walkers/fasta/FastaReferenceMaker.java   |   127 +
 .../gatk/tools/walkers/fasta/FastaSequence.java    |   101 +
 .../gatk/tools/walkers/fasta/FastaStats.java       |    93 +
 .../gatk/tools/walkers/filters/ClusteredSnps.java  |    81 +
 .../tools/walkers/filters/FiltrationContext.java   |    47 +
 .../walkers/filters/FiltrationContextWindow.java   |   104 +
 .../tools/walkers/filters/VariantFiltration.java   |   400 +
 .../gatk/tools/walkers/genotyper/AlleleList.java   |    41 +
 .../walkers/genotyper/AlleleListPermutation.java   |    35 +
 .../tools/walkers/genotyper/AlleleListUtils.java   |   334 +
 .../tools/walkers/genotyper/IndexedAlleleList.java |    95 +
 .../tools/walkers/genotyper/IndexedSampleList.java |    96 +
 .../gatk/tools/walkers/genotyper/SampleList.java   |    42 +
 .../tools/walkers/genotyper/SampleListUtils.java   |   224 +
 .../haplotypecaller/HCMappingQualityFilter.java    |    54 +
 .../gatk/tools/walkers/package-info.java           |    26 +
 .../gatk/tools/walkers/qc/CheckPileup.java         |   258 +
 .../gatk/tools/walkers/qc/CountBases.java          |    74 +
 .../gatk/tools/walkers/qc/CountIntervals.java      |   128 +
 .../gatk/tools/walkers/qc/CountLoci.java           |    96 +
 .../gatk/tools/walkers/qc/CountMales.java          |    85 +
 .../gatk/tools/walkers/qc/CountRODs.java           |   214 +
 .../gatk/tools/walkers/qc/CountRODsByRef.java      |   112 +
 .../gatk/tools/walkers/qc/CountReadEvents.java     |   121 +
 .../gatk/tools/walkers/qc/CountReads.java          |    81 +
 .../gatk/tools/walkers/qc/CountTerminusEvent.java  |   104 +
 .../gatk/tools/walkers/qc/DocumentationTest.java   |   117 +
 .../gatk/tools/walkers/qc/ErrorThrowing.java       |   110 +
 .../gatk/tools/walkers/qc/FlagStat.java            |   225 +
 .../gatk/tools/walkers/qc/Pileup.java              |   217 +
 .../gatk/tools/walkers/qc/PrintRODs.java           |    91 +
 .../gatk/tools/walkers/qc/QCRef.java               |   142 +
 .../gatk/tools/walkers/qc/ReadClippingStats.java   |   157 +
 .../gatk/tools/walkers/qc/RodSystemValidation.java |   182 +
 .../gatk/tools/walkers/readutils/ClipReads.java    |   607 +
 .../gatk/tools/walkers/readutils/PrintReads.java   |   316 +
 .../walkers/readutils/ReadAdaptorTrimmer.java      |   395 +
 .../gatk/tools/walkers/readutils/SplitSamFile.java |   151 +
 .../tools/walkers/varianteval/VariantEval.java     |   666 +
 .../varianteval/VariantEvalReportWriter.java       |   203 +
 .../varianteval/evaluators/CompOverlap.java        |   109 +
 .../varianteval/evaluators/CountVariants.java      |   219 +
 .../evaluators/IndelLengthHistogram.java           |   123 +
 .../varianteval/evaluators/IndelSummary.java       |   259 +
 .../evaluators/MendelianViolationEvaluator.java    |   187 +
 .../evaluators/MultiallelicSummary.java            |   164 +
 .../varianteval/evaluators/PrintMissingComp.java   |    57 +
 .../varianteval/evaluators/StandardEval.java       |    28 +
 .../evaluators/ThetaVariantEvaluator.java          |   143 +
 .../evaluators/TiTvVariantEvaluator.java           |   100 +
 .../varianteval/evaluators/ValidationReport.java   |   183 +
 .../varianteval/evaluators/VariantEvaluator.java   |   133 +
 .../varianteval/evaluators/VariantSummary.java     |   277 +
 .../varianteval/stratifications/AlleleCount.java   |   114 +
 .../stratifications/AlleleFrequency.java           |    61 +
 .../varianteval/stratifications/CompRod.java       |    51 +
 .../varianteval/stratifications/Contig.java        |    54 +
 .../walkers/varianteval/stratifications/CpG.java   |    76 +
 .../varianteval/stratifications/Degeneracy.java    |   158 +
 .../stratifications/DynamicStratification.java     |    66 +
 .../varianteval/stratifications/EvalRod.java       |    52 +
 .../varianteval/stratifications/Filter.java        |    56 +
 .../stratifications/FunctionalClass.java           |   110 +
 .../varianteval/stratifications/IndelSize.java     |    78 +
 .../stratifications/IntervalStratification.java    |    92 +
 .../stratifications/JexlExpression.java            |    69 +
 .../varianteval/stratifications/Novelty.java       |    64 +
 .../varianteval/stratifications/OneBPIndel.java    |    59 +
 .../stratifications/RequiredStratification.java    |    28 +
 .../varianteval/stratifications/Sample.java        |    57 +
 .../stratifications/SnpEffPositionModifier.java    |    86 +
 .../stratifications/StandardStratification.java    |    29 +
 .../varianteval/stratifications/TandemRepeat.java  |    67 +
 .../stratifications/VariantStratifier.java         |   110 +
 .../varianteval/stratifications/VariantType.java   |    49 +
 .../stratifications/manager/StratNode.java         |   166 +
 .../stratifications/manager/StratNodeIterator.java |    69 +
 .../manager/StratificationManager.java             |   426 +
 .../stratifications/manager/Stratifier.java        |    41 +
 .../tools/walkers/varianteval/util/Analysis.java   |    36 +
 .../varianteval/util/AnalysisModuleScanner.java    |   154 +
 .../tools/walkers/varianteval/util/DataPoint.java  |    35 +
 .../varianteval/util/EvaluationContext.java        |   115 +
 .../tools/walkers/varianteval/util/Molten.java     |    64 +
 .../varianteval/util/SortableJexlVCMatchExp.java   |    45 +
 .../walkers/varianteval/util/VariantEvalUtils.java |   311 +
 .../variantrecalibration/VQSRCalibrationCurve.java |   160 +
 .../walkers/variantutils/CombineVariants.java      |   371 +
 .../walkers/variantutils/ConcordanceMetrics.java   |   369 +
 .../walkers/variantutils/FilterLiftedVariants.java |   136 +
 .../walkers/variantutils/GenotypeConcordance.java  |   675 +
 .../variantutils/LeftAlignAndTrimVariants.java     |   303 +
 .../walkers/variantutils/LiftoverVariants.java     |   179 +
 .../variantutils/RandomlySplitVariants.java        |   165 +
 .../tools/walkers/variantutils/SelectHeaders.java  |   278 +
 .../tools/walkers/variantutils/SelectVariants.java |   801 +
 .../walkers/variantutils/ValidateVariants.java     |   301 +
 .../variantutils/VariantValidationAssessor.java    |   304 +
 .../variantutils/VariantsToAllelicPrimitives.java  |   140 +
 .../walkers/variantutils/VariantsToBinaryPed.java  |   550 +
 .../walkers/variantutils/VariantsToTable.java      |   460 +
 .../tools/walkers/variantutils/VariantsToVCF.java  |   271 +
 .../gatk/utils/AutoFormattingTime.java             |   185 +
 .../org/broadinstitute/gatk/utils/BaseUtils.java   |   672 +
 .../org/broadinstitute/gatk/utils/BitSetUtils.java |   134 +
 .../gatk/utils/ContigComparator.java               |    80 +
 .../gatk/utils/DeprecatedToolChecks.java           |    96 +
 .../broadinstitute/gatk/utils/GenomeLocParser.java |   622 +
 .../gatk/utils/GenomeLocSortedSet.java             |   476 +
 .../broadinstitute/gatk/utils/HeapSizeMonitor.java |   107 +
 .../org/broadinstitute/gatk/utils/IndelUtils.java  |   262 +
 .../org/broadinstitute/gatk/utils/LRUCache.java    |    45 +
 .../utils/MRUCachingSAMSequenceDictionary.java     |   186 +
 .../broadinstitute/gatk/utils/MannWhitneyU.java    |   508 +
 .../org/broadinstitute/gatk/utils/MathUtils.java   |  1690 +
 .../java/org/broadinstitute/gatk/utils/Median.java |    94 +
 .../gatk/utils/MendelianViolation.java             |   460 +
 .../gatk/utils/MultiThreadedErrorTracker.java      |   105 +
 .../org/broadinstitute/gatk/utils/NGSPlatform.java |   136 +
 .../org/broadinstitute/gatk/utils/PathUtils.java   |   195 +
 .../broadinstitute/gatk/utils/QualityUtils.java    |   397 +
 .../gatk/utils/R/RScriptExecutor.java              |   191 +
 .../gatk/utils/R/RScriptExecutorException.java     |    34 +
 .../gatk/utils/R/RScriptLibrary.java               |    66 +
 .../org/broadinstitute/gatk/utils/R/RUtils.java    |    91 +
 .../org/broadinstitute/gatk/utils/SampleUtils.java |   290 +
 .../gatk/utils/SequenceDictionaryUtils.java        |   527 +
 .../gatk/utils/UnvalidatingGenomeLoc.java          |    50 +
 .../java/org/broadinstitute/gatk/utils/Utils.java  |  1186 +
 .../gatk/utils/activeregion/ActiveRegion.java      |   500 +
 .../utils/activeregion/ActiveRegionReadState.java  |    40 +
 .../gatk/utils/activeregion/ActivityProfile.java   |   520 +
 .../utils/activeregion/ActivityProfileState.java   |   112 +
 .../activeregion/BandPassActivityProfile.java      |   194 +
 .../gatk/utils/analysis/AminoAcid.java             |   114 +
 .../gatk/utils/analysis/AminoAcidTable.java        |    94 +
 .../gatk/utils/analysis/AminoAcidUtils.java        |    77 +
 .../org/broadinstitute/gatk/utils/baq/BAQ.java     |   713 +
 .../gatk/utils/baq/BAQReadTransformer.java         |    74 +
 .../gatk/utils/baq/ReadTransformingIterator.java   |    69 +
 .../gatk/utils/classloader/JVMUtils.java           |   309 +
 .../gatk/utils/classloader/PluginManager.java      |   355 +
 .../utils/classloader/ProtectedPackageSource.java  |    28 +
 .../utils/classloader/PublicPackageSource.java     |    28 +
 .../gatk/utils/clipping/ClippingOp.java            |   617 +
 .../utils/clipping/ClippingRepresentation.java     |    63 +
 .../gatk/utils/clipping/ReadClipper.java           |   568 +
 .../gatk/utils/codecs/beagle/BeagleCodec.java      |   276 +
 .../gatk/utils/codecs/beagle/BeagleFeature.java    |   111 +
 .../gatk/utils/codecs/hapmap/RawHapMapCodec.java   |   125 +
 .../gatk/utils/codecs/hapmap/RawHapMapFeature.java |   196 +
 .../gatk/utils/codecs/refseq/RefSeqCodec.java      |   171 +
 .../gatk/utils/codecs/refseq/RefSeqFeature.java    |   323 +
 .../gatk/utils/codecs/refseq/Transcript.java       |    78 +
 .../utils/codecs/sampileup/SAMPileupCodec.java     |   354 +
 .../utils/codecs/sampileup/SAMPileupFeature.java   |   276 +
 .../gatk/utils/codecs/samread/SAMReadCodec.java    |   123 +
 .../gatk/utils/codecs/samread/SAMReadFeature.java  |   199 +
 .../gatk/utils/codecs/table/BedTableCodec.java     |    59 +
 .../gatk/utils/codecs/table/TableCodec.java        |   126 +
 .../gatk/utils/codecs/table/TableFeature.java      |    99 +
 .../gatk/utils/collections/DefaultHashMap.java     |    56 +
 .../gatk/utils/collections/ExpandingArrayList.java |    69 +
 .../gatk/utils/collections/IndexedSet.java         |   342 +
 .../collections/LoggingNestedIntegerArray.java     |   120 +
 .../gatk/utils/collections/NestedIntegerArray.java |   221 +
 .../gatk/utils/collections/Pair.java               |    93 +
 .../gatk/utils/collections/Permutation.java        |   103 +
 .../gatk/utils/collections/PrimitivePair.java      |   200 +
 .../gatk/utils/collections/RODMergingIterator.java |   160 +
 .../gatk/utils/commandline/Advanced.java           |    41 +
 .../gatk/utils/commandline/Argument.java           |   125 +
 .../gatk/utils/commandline/ArgumentCollection.java |    45 +
 .../gatk/utils/commandline/ArgumentDefinition.java |   297 +
 .../utils/commandline/ArgumentDefinitionGroup.java |    99 +
 .../utils/commandline/ArgumentDefinitions.java     |   195 +
 .../gatk/utils/commandline/ArgumentException.java  |    38 +
 .../gatk/utils/commandline/ArgumentIOType.java     |    52 +
 .../gatk/utils/commandline/ArgumentMatch.java      |   294 +
 .../utils/commandline/ArgumentMatchFileValue.java  |    52 +
 .../gatk/utils/commandline/ArgumentMatchSite.java  |    77 +
 .../utils/commandline/ArgumentMatchSource.java     |    97 +
 .../utils/commandline/ArgumentMatchSourceType.java |    33 +
 .../commandline/ArgumentMatchStringValue.java      |    49 +
 .../gatk/utils/commandline/ArgumentMatchValue.java |    43 +
 .../gatk/utils/commandline/ArgumentMatches.java    |   211 +
 .../gatk/utils/commandline/ArgumentSource.java     |   243 +
 .../utils/commandline/ArgumentTypeDescriptor.java  |  1030 +
 .../gatk/utils/commandline/ClassType.java          |    40 +
 .../gatk/utils/commandline/CommandLineProgram.java |   447 +
 .../gatk/utils/commandline/CommandLineUtils.java   |   192 +
 .../commandline/EnumerationArgumentDefault.java    |    65 +
 .../gatk/utils/commandline/Gather.java             |    41 +
 .../gatk/utils/commandline/Gatherer.java           |    47 +
 .../gatk/utils/commandline/Hidden.java             |    41 +
 .../gatk/utils/commandline/Input.java              |    83 +
 .../commandline/IntervalArgumentCollection.java    |    88 +
 .../gatk/utils/commandline/IntervalBinding.java    |   106 +
 .../commandline/MissingArgumentValueException.java |    50 +
 .../gatk/utils/commandline/Output.java             |    90 +
 .../gatk/utils/commandline/ParsedArgs.java         |    38 +
 .../gatk/utils/commandline/ParsedListArgs.java     |    55 +
 .../gatk/utils/commandline/ParsingEngine.java      |   829 +
 .../commandline/ParsingEngineArgumentFiles.java    |    55 +
 .../commandline/ParsingEngineArgumentProvider.java |    37 +
 .../gatk/utils/commandline/ParsingMethod.java      |   127 +
 .../gatk/utils/commandline/RodBinding.java         |   197 +
 .../utils/commandline/RodBindingCollection.java    |    89 +
 .../gatk/utils/commandline/Tags.java               |   112 +
 .../gatk/utils/commandline/package-info.java       |    26 +
 .../gatk/utils/crypt/CryptUtils.java               |   391 +
 .../broadinstitute/gatk/utils/crypt/GATKKey.java   |   350 +
 .../gatk/utils/duplicates/DupUtils.java            |   142 +
 .../gatk/utils/duplicates/DuplicateComp.java       |    66 +
 .../DynamicClassResolutionException.java           |    54 +
 .../gatk/utils/exceptions/UserException.java       |   485 +
 .../gatk/utils/fasta/ArtificialFastaUtils.java     |   154 +
 .../fasta/CachingIndexedFastaSequenceFile.java     |   311 +
 .../gatk/utils/fasta/package-info.java             |    26 +
 .../gatk/utils/file/FSLockWithShared.java          |   293 +
 .../gatk/utils/fragments/FragmentCollection.java   |    67 +
 .../gatk/utils/fragments/FragmentUtils.java        |   377 +
 .../gatk/utils/genotyper/DiploidGenotype.java      |   125 +
 .../gatk/utils/genotyper/MostLikelyAllele.java     |   134 +
 .../genotyper/PerReadAlleleLikelihoodMap.java      |   413 +
 .../gatk/utils/genotyper/ReadLikelihoods.java      |  1587 +
 .../gatk/utils/haplotype/EventMap.java             |   423 +
 .../gatk/utils/haplotype/Haplotype.java            |   343 +
 .../utils/haplotype/HaplotypeBaseComparator.java   |    42 +
 .../utils/haplotype/HaplotypeScoreComparator.java  |    39 +
 .../haplotype/HaplotypeSizeAndBaseComparator.java  |    47 +
 .../gatk/utils/help/ApplicationDetails.java        |    95 +
 .../gatk/utils/help/DocletUtils.java               |    76 +
 .../gatk/utils/help/DocumentedGATKFeature.java     |    50 +
 .../utils/help/DocumentedGATKFeatureHandler.java   |    99 +
 .../utils/help/DocumentedGATKFeatureObject.java    |    61 +
 .../gatk/utils/help/ForumAPIUtils.java             |   173 +
 .../gatk/utils/help/ForumDiscussion.java           |    84 +
 .../gatk/utils/help/GATKDocUtils.java              |    71 +
 .../gatk/utils/help/GATKDocWorkUnit.java           |   127 +
 .../broadinstitute/gatk/utils/help/GATKDoclet.java |   576 +
 .../gatk/utils/help/GSONArgument.java              |    83 +
 .../gatk/utils/help/GSONWorkUnit.java              |    86 +
 .../utils/help/GenericDocumentationHandler.java    |  1008 +
 .../gatk/utils/help/HelpConstants.java             |    83 +
 .../gatk/utils/help/HelpFormatter.java             |   336 +
 .../broadinstitute/gatk/utils/help/HelpUtils.java  |    64 +
 .../utils/help/ResourceBundleExtractorDoclet.java  |   228 +
 .../gatk/utils/instrumentation/Sizeof.java         |   146 +
 .../gatk/utils/interval/IntervalMergingRule.java   |    35 +
 .../gatk/utils/interval/IntervalSetRule.java       |    36 +
 .../gatk/utils/interval/IntervalUtils.java         |   890 +
 .../gatk/utils/io/FileExtension.java               |    37 +
 .../utils/io/HardThresholdingOutputStream.java     |    56 +
 .../org/broadinstitute/gatk/utils/io/IOUtils.java  |   575 +
 .../org/broadinstitute/gatk/utils/io/Resource.java |    91 +
 .../gatk/utils/jna/clibrary/JNAUtils.java          |    59 +
 .../gatk/utils/jna/clibrary/LibC.java              |   200 +
 .../gatk/utils/jna/drmaa/v1_0/JnaJobInfo.java      |   101 +
 .../gatk/utils/jna/drmaa/v1_0/JnaJobTemplate.java  |   316 +
 .../gatk/utils/jna/drmaa/v1_0/JnaSession.java      |   461 +
 .../utils/jna/drmaa/v1_0/JnaSessionFactory.java    |    40 +
 .../gatk/utils/jna/drmaa/v1_0/LibDrmaa.java        |   723 +
 .../gatk/utils/jna/lsf/v7_0_6/LibBat.java          | 20014 ++++++++
 .../gatk/utils/jna/lsf/v7_0_6/LibLsf.java          |  1780 +
 .../utils/locusiterator/AlignmentStateMachine.java |   370 +
 .../utils/locusiterator/LIBSDownsamplingInfo.java  |    51 +
 .../gatk/utils/locusiterator/LIBSPerformance.java  |   198 +
 .../gatk/utils/locusiterator/LocusIterator.java    |    62 +
 .../utils/locusiterator/LocusIteratorByState.java  |   454 +
 .../locusiterator/PerSampleReadStateManager.java   |   261 +
 .../gatk/utils/locusiterator/ReadStateManager.java |   289 +
 .../utils/locusiterator/SamplePartitioner.java     |   172 +
 .../gatk/utils/nanoScheduler/EOFMarkedValue.java   |   105 +
 .../gatk/utils/nanoScheduler/InputProducer.java    |   217 +
 .../gatk/utils/nanoScheduler/MapResult.java        |    75 +
 .../gatk/utils/nanoScheduler/MapResultsQueue.java  |   116 +
 .../gatk/utils/nanoScheduler/NSMapFunction.java    |    44 +
 .../utils/nanoScheduler/NSProgressFunction.java    |    37 +
 .../gatk/utils/nanoScheduler/NSReduceFunction.java |    43 +
 .../gatk/utils/nanoScheduler/NanoScheduler.java    |   494 +
 .../gatk/utils/nanoScheduler/Reducer.java          |   169 +
 .../gatk/utils/pairhmm/BatchPairHMM.java           |    41 +
 .../gatk/utils/pairhmm/Log10PairHMM.java           |   220 +
 .../gatk/utils/pairhmm/N2MemoryPairHMM.java        |    98 +
 .../broadinstitute/gatk/utils/pairhmm/PairHMM.java |   357 +
 .../gatk/utils/pairhmm/PairHMMModel.java           |   435 +
 .../gatk/utils/pairhmm/PairHMMReadyHaplotypes.java |   182 +
 .../utils/pileup/MergingPileupElementIterator.java |    76 +
 .../gatk/utils/pileup/PileupElement.java           |   539 +
 .../gatk/utils/pileup/PileupElementFilter.java     |    36 +
 .../gatk/utils/pileup/PileupElementTracker.java    |   154 +
 .../gatk/utils/pileup/ReadBackedPileup.java        |   295 +
 .../gatk/utils/pileup/ReadBackedPileupImpl.java    |  1040 +
 .../org/broadinstitute/gatk/utils/pileup2/Notes    |    34 +
 .../gatk/utils/progressmeter/ProgressMeter.java    |   465 +
 .../utils/progressmeter/ProgressMeterDaemon.java   |   111 +
 .../utils/progressmeter/ProgressMeterData.java     |    79 +
 .../gatk/utils/recalibration/BQSRArgumentSet.java  |    85 +
 .../gatk/utils/recalibration/BQSRMode.java         |    55 +
 .../gatk/utils/recalibration/EventType.java        |    72 +
 .../gatk/utils/runtime/CapturedStreamOutput.java   |   134 +
 .../gatk/utils/runtime/InputStreamSettings.java    |   116 +
 .../gatk/utils/runtime/OutputStreamSettings.java   |   127 +
 .../gatk/utils/runtime/ProcessController.java      |   387 +
 .../gatk/utils/runtime/ProcessOutput.java          |    57 +
 .../gatk/utils/runtime/ProcessSettings.java        |   140 +
 .../gatk/utils/runtime/RuntimeUtils.java           |    77 +
 .../gatk/utils/runtime/StreamLocation.java         |    33 +
 .../gatk/utils/runtime/StreamOutput.java           |    69 +
 .../gatk/utils/sam/AlignmentStartComparator.java   |    50 +
 .../sam/AlignmentStartWithNoTiesComparator.java    |    73 +
 .../gatk/utils/sam/AlignmentUtils.java             |  1337 +
 .../gatk/utils/sam/ArtificialBAMBuilder.java       |   242 +
 .../utils/sam/ArtificialGATKSAMFileWriter.java     |   130 +
 .../utils/sam/ArtificialMultiSampleReadStream.java |    87 +
 .../utils/sam/ArtificialPatternedSAMIterator.java  |   172 +
 .../gatk/utils/sam/ArtificialReadsTraversal.java   |   140 +
 .../gatk/utils/sam/ArtificialSAMFileReader.java    |   156 +
 .../gatk/utils/sam/ArtificialSAMIterator.java      |   212 +
 .../gatk/utils/sam/ArtificialSAMQueryIterator.java |   259 +
 .../gatk/utils/sam/ArtificialSAMUtils.java         |   484 +
 .../sam/ArtificialSingleSampleReadStream.java      |   213 +
 .../ArtificialSingleSampleReadStreamAnalyzer.java  |   282 +
 .../gatk/utils/sam/BySampleSAMFileWriter.java      |    70 +
 .../broadinstitute/gatk/utils/sam/CigarUtils.java  |   273 +
 .../gatk/utils/sam/GATKSAMReadGroupRecord.java     |   116 +
 .../gatk/utils/sam/GATKSAMRecord.java              |   631 +
 .../gatk/utils/sam/GATKSamRecordFactory.java       |    75 +
 .../sam/MisencodedBaseQualityReadTransformer.java  |    94 +
 .../gatk/utils/sam/NWaySAMFileWriter.java          |   185 +
 .../ReadUnclippedStartWithNoTiesComparator.java    |    73 +
 .../broadinstitute/gatk/utils/sam/ReadUtils.java   |   964 +
 .../gatk/utils/sam/SAMFileReaderBuilder.java       |    84 +
 .../gatk/utils/sam/SimplifyingSAMFileWriter.java   |    86 +
 .../gatk/utils/sam/package-info.java               |    26 +
 .../GlobalEdgeGreedySWPairwiseAlignment.java       |   208 +
 .../gatk/utils/smithwaterman/Parameters.java       |    62 +
 .../utils/smithwaterman/SWPairwiseAlignment.java   |   599 +
 .../smithwaterman/SWPairwiseAlignmentMain.java     |   221 +
 .../gatk/utils/smithwaterman/SWParameterSet.java   |    51 +
 .../gatk/utils/smithwaterman/SmithWaterman.java    |    57 +
 .../gatk/utils/text/ListFileUtils.java             |   344 +
 .../gatk/utils/text/TextFormattingUtils.java       |   172 +
 .../broadinstitute/gatk/utils/text/XReadLines.java |   208 +
 .../EfficiencyMonitoringThreadFactory.java         |   160 +
 .../gatk/utils/threading/NamedThreadFactory.java   |    51 +
 .../utils/threading/ThreadEfficiencyMonitor.java   |   232 +
 .../gatk/utils/threading/ThreadLocalArray.java     |    65 +
 .../gatk/utils/threading/ThreadPoolMonitor.java    |    77 +
 .../gatk/utils/threading/package-info.java         |    26 +
 .../gatk/utils/variant/GATKVCFIndexType.java       |    39 +
 .../gatk/utils/variant/GATKVCFUtils.java           |   316 +
 .../utils/variant/GATKVariantContextUtils.java     |  1960 +
 .../gatk/utils/variant/HomoSapiensConstants.java   |    51 +
 .../gatk/utils/wiggle/WiggleHeader.java            |    56 +
 .../gatk/utils/wiggle/WiggleWriter.java            |   117 +
 .../src/main/resources/GATK_public.key             |   Bin 0 -> 294 bytes
 .../engine/phonehome/resources/GATK_AWS_access.key |   Bin 0 -> 256 bytes
 .../engine/phonehome/resources/GATK_AWS_secret.key |   Bin 0 -> 256 bytes
 .../walkers/variantrecalibration/plot_Tranches.R   |    93 +
 .../broadinstitute/gatk/utils/recalibration/BQSR.R |   159 +
 .../htsjdk/samtools/GATKBAMFileSpanUnitTest.java   |   254 +
 .../java/htsjdk/samtools/GATKChunkUnitTest.java    |    71 +
 .../gatk/engine/CommandLineGATKUnitTest.java       |    68 +
 .../gatk/engine/EngineFeaturesIntegrationTest.java |   736 +
 .../gatk/engine/GenomeAnalysisEngineUnitTest.java  |   273 +
 .../gatk/engine/MaxRuntimeIntegrationTest.java     |   151 +
 .../gatk/engine/ReadMetricsUnitTest.java           |   371 +
 .../gatk/engine/WalkerManagerUnitTest.java         |    71 +
 .../providers/AllLocusViewUnitTest.java            |    90 +
 .../providers/CoveredLocusViewUnitTest.java        |   103 +
 .../IntervalReferenceOrderedViewUnitTest.java      |   366 +
 .../providers/LocusReferenceViewUnitTest.java      |   143 +
 .../datasources/providers/LocusViewTemplate.java   |   405 +
 .../providers/ReadReferenceViewUnitTest.java       |   160 +
 .../providers/ReferenceOrderedViewUnitTest.java    |   157 +
 .../providers/ReferenceViewTemplate.java           |   122 +
 .../providers/ShardDataProviderUnitTest.java       |   152 +
 .../reads/ActiveRegionShardBalancerUnitTest.java   |   102 +
 .../datasources/reads/DownsamplerBenchmark.java    |    94 +
 .../datasources/reads/FilePointerUnitTest.java     |   129 +
 .../datasources/reads/GATKBAMIndexUnitTest.java    |   108 +
 .../datasources/reads/GATKWalkerBenchmark.java     |   141 +
 .../IntervalOverlapFilteringIteratorUnitTest.java  |   150 +
 .../engine/datasources/reads/MockLocusShard.java   |    51 +
 .../datasources/reads/PicardBaselineBenchmark.java |   101 +
 .../datasources/reads/ReadProcessingBenchmark.java |    83 +
 .../reads/ReadShardBalancerUnitTest.java           |   195 +
 .../datasources/reads/SAMDataSourceUnitTest.java   |   253 +
 .../datasources/reads/SAMReaderIDUnitTest.java     |    49 +
 .../reads/SeekableBufferedStreamUnitTest.java      |   101 +
 .../reads/TheoreticalMinimaBenchmark.java          |   114 +
 .../ReferenceDataSourceIntegrationTest.java        |    75 +
 .../rmd/ReferenceOrderedDataPoolUnitTest.java      |   208 +
 .../rmd/ReferenceOrderedQueryDataPoolUnitTest.java |    89 +
 .../AlleleBiasedDownsamplingUtilsUnitTest.java     |   219 +
 .../downsampling/DownsamplingIntegrationTest.java  |    44 +
 .../DownsamplingReadsIteratorUnitTest.java         |   139 +
 .../FractionalDownsamplerUnitTest.java             |   158 +
 .../downsampling/LevelingDownsamplerUnitTest.java  |   163 +
 ...PerSampleDownsamplingReadsIteratorUnitTest.java |   299 +
 ...edArtificialSingleSampleReadStreamAnalyzer.java |   127 +
 .../downsampling/ReservoirDownsamplerUnitTest.java |   131 +
 .../SimplePositionalDownsamplerUnitTest.java       |   331 +
 .../gatk/engine/executive/ReduceTreeUnitTest.java  |   254 +
 .../AllowNCigarMalformedReadFilterUnitTest.java    |    77 +
 .../engine/filters/BadCigarFilterUnitTest.java     |    91 +
 .../filters/BadReadGroupsIntegrationTest.java      |    52 +
 .../filters/MalformedReadFilterUnitTest.java       |   246 +
 .../filters/NDNCigarReadTransformerUnitTest.java   |    70 +
 .../gatk/engine/filters/ReadFilterTest.java        |   370 +
 .../filters/ReadGroupBlackListFilterUnitTest.java  |   247 +
 .../filters/UnsafeMalformedReadFilterUnitTest.java |    50 +
 .../gatk/engine/io/OutputTrackerUnitTest.java      |    84 +
 .../iterators/BoundedReadIteratorUnitTest.java     |   145 +
 .../iterators/GATKSAMIteratorAdapterUnitTest.java  |   176 +
 .../iterators/ReadFormattingIteratorUnitTest.java  |    50 +
 .../iterators/VerifyingSamIteratorUnitTest.java    |   128 +
 .../engine/phonehome/GATKRunReportUnitTest.java    |   310 +
 .../engine/refdata/RefMetaDataTrackerUnitTest.java |   290 +
 .../refdata/tracks/FeatureManagerUnitTest.java     |   163 +
 .../refdata/tracks/RMDTrackBuilderUnitTest.java    |   190 +
 .../utils/CheckableCloseableTribbleIterator.java   |    90 +
 .../FeatureToGATKFeatureIteratorUnitTest.java      |    61 +
 .../refdata/utils/FlashBackIteratorUnitTest.java   |   364 +
 .../engine/refdata/utils/TestFeatureReader.java    |    53 +
 .../engine/refdata/utils/TestRMDTrackBuilder.java  |    71 +
 .../gatk/engine/report/GATKReportUnitTest.java     |   285 +
 .../gatk/engine/samples/PedReaderUnitTest.java     |   354 +
 .../gatk/engine/samples/SampleDBUnitTest.java      |   251 +
 .../gatk/engine/samples/SampleUnitTest.java        |    89 +
 .../engine/traversals/DummyActiveRegionWalker.java |   116 +
 .../traversals/TAROrderedReadCacheUnitTest.java    |   111 +
 .../traversals/TraverseActiveRegionsUnitTest.java  |   679 +
 .../traversals/TraverseDuplicatesUnitTest.java     |   162 +
 .../engine/traversals/TraverseReadsUnitTest.java   |   166 +
 .../gatk/engine/walkers/WalkerTest.java            |   455 +
 .../gatk/tools/CatVariantsIntegrationTest.java     |   145 +
 .../gatk/tools/walkers/BAQIntegrationTest.java     |    55 +
 .../CNV/SymbolicAllelesIntegrationTest.java        |    63 +
 .../walkers/annotator/SnpEffUtilUnitTest.java      |   111 +
 .../coverage/CallableLociIntegrationTest.java      |    69 +
 .../CompareCallableLociWalkerIntegrationTest.java  |    42 +
 .../DepthOfCoverageB36IntegrationTest.java         |   111 +
 .../coverage/DepthOfCoverageIntegrationTest.java   |   181 +
 .../walkers/qc/CheckPileupIntegrationTest.java     |    70 +
 .../gatk/tools/walkers/qc/CountReadsUnitTest.java  |    51 +
 .../qc/DictionaryConsistencyIntegrationTest.java   |    82 +
 .../tools/walkers/qc/FlagStatIntegrationTest.java  |    45 +
 .../walkers/qc/PileupWalkerIntegrationTest.java    |   123 +
 .../readutils/ClipReadsWalkersIntegrationTest.java |    80 +
 .../readutils/PrintReadsIntegrationTest.java       |   136 +
 .../readutils/PrintReadsLargeScaleTest.java        |    45 +
 .../walkers/readutils/PrintReadsUnitTest.java      |   123 +
 .../ReadAdaptorTrimmerIntegrationTest.java         |    60 +
 .../variantutils/FilterLiftedVariantsUnitTest.java |    54 +
 .../variantutils/SelectVariantsUnitTest.java       |    88 +
 .../gatk/utils/AutoFormattingTimeUnitTest.java     |   118 +
 .../org/broadinstitute/gatk/utils/BaseTest.java    |   568 +
 .../gatk/utils/BaseUtilsUnitTest.java              |   179 +
 .../gatk/utils/BitSetUtilsUnitTest.java            |    85 +
 .../gatk/utils/ExampleToCopyUnitTest.java          |   241 +
 .../gatk/utils/GATKTextReporter.java               |    41 +
 .../gatk/utils/GenomeLocParserBenchmark.java       |    81 +
 .../gatk/utils/GenomeLocParserUnitTest.java        |   509 +
 .../gatk/utils/GenomeLocSortedSetUnitTest.java     |   405 +
 .../gatk/utils/GenomeLocUnitTest.java              |   386 +
 .../java/org/broadinstitute/gatk/utils/MD5DB.java  |   312 +
 .../org/broadinstitute/gatk/utils/MD5Mismatch.java |    67 +
 .../MRUCachingSAMSequencingDictionaryUnitTest.java |    97 +
 .../org/broadinstitute/gatk/utils/MWUnitTest.java  |   131 +
 .../gatk/utils/MathUtilsUnitTest.java              |   913 +
 .../broadinstitute/gatk/utils/MedianUnitTest.java  |   115 +
 .../gatk/utils/NGSPlatformUnitTest.java            |   167 +
 .../gatk/utils/PathUtilsUnitTest.java              |    65 +
 .../gatk/utils/QualityUtilsUnitTest.java           |   189 +
 .../gatk/utils/R/RScriptExecutorUnitTest.java      |   110 +
 .../gatk/utils/R/RScriptLibraryUnitTest.java       |    47 +
 .../gatk/utils/R/RUtilsUnitTest.java               |    65 +
 .../gatk/utils/SampleUtilsUnitTest.java            |    52 +
 .../utils/SequenceDictionaryUtilsUnitTest.java     |   241 +
 .../gatk/utils/SimpleTimerUnitTest.java            |   179 +
 .../gatk/utils/TestNGTestTransformer.java          |    62 +
 .../broadinstitute/gatk/utils/UtilsUnitTest.java   |   363 +
 .../utils/activeregion/ActiveRegionUnitTest.java   |   395 +
 .../activeregion/ActivityProfileStateUnitTest.java |    92 +
 .../activeregion/ActivityProfileUnitTest.java      |   491 +
 .../BandPassActivityProfileUnitTest.java           |   339 +
 .../broadinstitute/gatk/utils/baq/BAQUnitTest.java |   257 +
 .../gatk/utils/classloader/JVMUtilsUnitTest.java   |    75 +
 .../gatk/utils/clipping/ReadClipperTestUtils.java  |   144 +
 .../gatk/utils/clipping/ReadClipperUnitTest.java   |   421 +
 .../gatk/utils/codecs/hapmap/HapMapUnitTest.java   |   164 +
 .../utils/collections/DefaultHashMapUnitTest.java  |   159 +
 .../collections/ExpandingArrayListUnitTest.java    |   177 +
 .../commandline/ArgumentMatchSiteUnitTest.java     |    80 +
 .../commandline/ArgumentMatchSourceUnitTest.java   |    99 +
 .../ArgumentTypeDescriptorUnitTest.java            |   233 +
 .../InvalidArgumentIntegrationTest.java            |    66 +
 .../utils/commandline/LoggingIntegrationTest.java  |   117 +
 .../utils/commandline/ParsingEngineUnitTest.java   |  1140 +
 .../commandline/RodBindingCollectionUnitTest.java  |   133 +
 .../gatk/utils/commandline/RodBindingUnitTest.java |    82 +
 .../gatk/utils/crypt/CryptUtilsUnitTest.java       |   199 +
 .../gatk/utils/crypt/GATKKeyIntegrationTest.java   |   157 +
 .../gatk/utils/crypt/GATKKeyUnitTest.java          |   129 +
 .../CachingIndexedFastaSequenceFileUnitTest.java   |   264 +
 .../gatk/utils/file/FSLockWithSharedUnitTest.java  |    60 +
 .../utils/fragments/FragmentUtilsBenchmark.java    |    81 +
 .../utils/fragments/FragmentUtilsUnitTest.java     |   390 +
 .../gatk/utils/haplotype/EventMapUnitTest.java     |   203 +
 .../gatk/utils/haplotype/HaplotypeUnitTest.java    |   249 +
 .../utils/interval/IntervalIntegrationTest.java    |   304 +
 .../gatk/utils/interval/IntervalUtilsUnitTest.java |  1110 +
 .../gatk/utils/io/IOUtilsUnitTest.java             |   326 +
 .../gatk/utils/jna/clibrary/LibCUnitTest.java      |    70 +
 .../utils/jna/drmaa/v1_0/JnaSessionQueueTest.java  |   165 +
 .../utils/jna/drmaa/v1_0/LibDrmaaQueueTest.java    |   257 +
 .../gatk/utils/jna/lsf/v7_0_6/LibBatQueueTest.java |   162 +
 .../AlignmentStateMachineUnitTest.java             |   110 +
 .../gatk/utils/locusiterator/LIBS_position.java    |   155 +
 .../locusiterator/LocusIteratorBenchmark.java      |   142 +
 .../LocusIteratorByStateBaseTest.java              |   252 +
 .../LocusIteratorByStateUnitTest.java              |   753 +
 .../PerSampleReadStateManagerUnitTest.java         |   188 +
 .../utils/nanoScheduler/InputProducerUnitTest.java |    94 +
 .../utils/nanoScheduler/MapResultUnitTest.java     |    65 +
 .../utils/nanoScheduler/NanoSchedulerUnitTest.java |   343 +
 .../gatk/utils/nanoScheduler/ReducerUnitTest.java  |   236 +
 .../gatk/utils/pileup/PileupElementUnitTest.java   |   189 +
 .../utils/pileup/ReadBackedPileupUnitTest.java     |   328 +
 .../progressmeter/ProgressMeterDaemonUnitTest.java |   121 +
 .../progressmeter/ProgressMeterDataUnitTest.java   |    86 +
 .../utils/recalibration/EventTypeUnitTest.java     |    61 +
 .../utils/report/ReportMarshallerUnitTest.java     |    64 +
 .../utils/runtime/ProcessControllerUnitTest.java   |   518 +
 .../gatk/utils/runtime/RuntimeUtilsUnitTest.java   |    42 +
 .../gatk/utils/sam/AlignmentUtilsUnitTest.java     |  1044 +
 .../utils/sam/ArtificialBAMBuilderUnitTest.java    |   121 +
 .../ArtificialPatternedSAMIteratorUnitTest.java    |   122 +
 .../utils/sam/ArtificialSAMFileWriterUnitTest.java |   120 +
 .../sam/ArtificialSAMQueryIteratorUnitTest.java    |   138 +
 .../gatk/utils/sam/ArtificialSAMUtilsUnitTest.java |   108 +
 .../ArtificialSingleSampleReadStreamUnitTest.java  |   186 +
 .../gatk/utils/sam/GATKSAMRecordUnitTest.java      |    78 +
 .../utils/sam/MisencodedBaseQualityUnitTest.java   |    96 +
 .../gatk/utils/sam/ReadUtilsUnitTest.java          |   340 +
 .../smithwaterman/SmithWatermanBenchmark.java      |    87 +
 .../gatk/utils/text/ListFileUtilsUnitTest.java     |   159 +
 .../utils/text/TextFormattingUtilsUnitTest.java    |    89 +
 .../EfficiencyMonitoringThreadFactoryUnitTest.java |   189 +
 .../utils/threading/ThreadPoolMonitorUnitTest.java |    64 +
 .../gatk/utils/variant/GATKVCFUtilsUnitTest.java   |   138 +
 .../variant/GATKVariantContextUtilsUnitTest.java   |  1612 +
 .../gatk/utils/variant/VCFIntegrationTest.java     |   377 +
 .../utils/variant/VariantContextBenchmark.java     |   377 +
 .../src/test/resources/testProperties.properties   |     2 +
 public/gatk-utils/pom.xml                          |   192 +
 .../gatk/utils/help/log4j.properties               |     7 +
 .../org/broadinstitute/gatk/utils/GenomeLoc.java   |   657 +
 .../gatk/utils/HasGenomeLocation.java              |    36 +
 .../org/broadinstitute/gatk/utils/SimpleTimer.java |   261 +
 .../gatk/utils/exceptions/GATKException.java       |    64 +
 .../utils/exceptions/ReviewedGATKException.java    |    42 +
 .../broadinstitute/gatk/utils/package-info.java    |    26 +
 .../gatk/utils/pairhmm/libVectorLoglessPairHMM.so  |   Bin 0 -> 479380 bytes
 public/gsalib/pom.xml                              |    45 +
 public/gsalib/src/R/DESCRIPTION                    |    13 +
 public/gsalib/src/R/LICENSE                        |     2 +
 public/gsalib/src/R/NAMESPACE                      |     1 +
 public/gsalib/src/R/R/gsa.error.R                  |    12 +
 public/gsalib/src/R/R/gsa.getargs.R                |   116 +
 public/gsalib/src/R/R/gsa.message.R                |     3 +
 public/gsalib/src/R/R/gsa.plot.venn.R              |    50 +
 public/gsalib/src/R/R/gsa.read.eval.R              |    83 +
 public/gsalib/src/R/R/gsa.read.gatkreport.R        |   196 +
 public/gsalib/src/R/R/gsa.read.squidmetrics.R      |    28 +
 public/gsalib/src/R/R/gsa.read.vcf.R               |    23 +
 public/gsalib/src/R/R/gsa.variantqc.utils.R        |   246 +
 public/gsalib/src/R/R/gsa.warn.R                   |     3 +
 public/gsalib/src/R/Read-and-delete-me             |     9 +
 public/gsalib/src/R/man/gsa.error.Rd               |    49 +
 public/gsalib/src/R/man/gsa.getargs.Rd             |    57 +
 public/gsalib/src/R/man/gsa.message.Rd             |    44 +
 public/gsalib/src/R/man/gsa.plot.venn.Rd           |    75 +
 public/gsalib/src/R/man/gsa.read.eval.Rd           |   111 +
 public/gsalib/src/R/man/gsa.read.gatkreport.Rd     |    55 +
 public/gsalib/src/R/man/gsa.read.squidmetrics.Rd   |    48 +
 public/gsalib/src/R/man/gsa.read.vcf.Rd            |    53 +
 public/gsalib/src/R/man/gsa.warn.Rd                |    46 +
 public/gsalib/src/R/man/gsalib-package.Rd          |    70 +
 public/gsalib/src/assembly/gsalib.xml              |    13 +
 public/java/config/log4j.properties                |    10 +
 public/package-tests/pom.xml                       |   199 +
 public/perl/liftOverVCF.pl                         |    83 +
 public/perl/sortByRef.pl                           |   127 +
 public/pom.xml                                     |    47 +
 .../cofoja/cofoja/1.0-r139/cofoja-1.0-r139.jar     |   Bin 0 -> 378205 bytes
 .../cofoja/cofoja/1.0-r139/cofoja-1.0-r139.pom     |     9 +
 .../net/sf/snpeff/snpeff/2.0.5/snpeff-2.0.5.jar    |   Bin 0 -> 4178339 bytes
 .../net/sf/snpeff/snpeff/2.0.5/snpeff-2.0.5.pom    |     9 +
 .../picard/picard/1.120.1579/picard-1.120.1579.jar |   Bin 0 -> 1380569 bytes
 .../picard/picard/1.120.1579/picard-1.120.1579.pom |    34 +
 .../htsjdk/1.120.1620/htsjdk-1.120.1620.jar        |   Bin 0 -> 2185840 bytes
 .../htsjdk/1.120.1620/htsjdk-1.120.1620.pom        |    27 +
 .../sysinternals/junction/1.04/junction-1.04.exe   |   Bin 0 -> 40960 bytes
 .../junction/1.04/junction-1.04.exe.md5            |     1 +
 .../sysinternals/junction/1.04/junction-1.04.pom   |    15 +
 .../junction/1.04/junction-1.04.pom.md5            |     1 +
 .../src/main/scripts/shell/delete_maven_links.sh   |    13 +
 settings/helpTemplates/common.html                 |    88 +
 settings/helpTemplates/generic.index.template.html |    93 +
 settings/helpTemplates/generic.template.html       |   327 +
 1181 files changed, 390633 insertions(+)

diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..819c120
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,29 @@
+/*.bam
+/*.bai
+/*.bed
+*~
+/*.vcf
+/*.txt
+/*.csh
+/.*
+/*.pdf
+/*.eval
+*.ipr
+*.iws
+*.iml
+*.pyc
+.DS_Store
+queueScatterGather
+/foo*
+/bar*
+integrationtests/
+public/testdata/onTheFlyOutputTest.vcf
+build/
+dist/
+dump/
+lib/
+out/
+/atlassian-ide-plugin.xml
+maven-metadata-local.xml
+dependency-reduced-pom.xml
+public/external-example/target/
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..2c245a2
--- /dev/null
+++ b/README.md
@@ -0,0 +1,3 @@
+The Genome Analysis Toolkit
+============
+See http://www.broadinstitute.org/gatk/
diff --git a/ant-bridge.sh b/ant-bridge.sh
new file mode 100755
index 0000000..a2f6865
--- /dev/null
+++ b/ant-bridge.sh
@@ -0,0 +1,173 @@
+#!/bin/sh
+
+mvn_args="verify"
+mvn_properties=
+mvn_clean=
+unknown_args=
+property_regex='-D(.*)=(.*)'
+unit_test_regex='.*UnitTest'
+post_script=
+run_type="run"
+
+for arg in "${@}" ; do
+    if [[ "${arg}" == "dry" ]] ; then
+        run_type="dry"
+
+    elif [[ "${arg}" == "clean" ]] ; then
+        mvn_clean="clean"
+        mvn_args=
+
+    elif [[ "${arg}" =~ ${property_regex} ]] ; then
+        property_name=${BASH_REMATCH[1]}
+        property_value=${BASH_REMATCH[2]}
+
+        if [[ "${property_name}" == "single" ]] ; then
+            test_property="test"
+            test_disabled="it.test"
+            if [[ ! "${property_value}" =~ ${unit_test_regex} ]] ; then
+                test_property="it.test"
+                test_disabled="test"
+            fi
+
+            mvn_properties="${mvn_properties} -D${test_disabled}=disabled -D${test_property}=${property_value}"
+
+        elif [[ "${property_name}" == "test.debug.port" ]] ; then
+            mvn_properties="${mvn_properties} -Dmaven.surefire.debug=\"-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=${property_value}\""
+            mvn_properties="${mvn_properties} -Dmaven.failsafe.debug=\"-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=${property_value}\""
+
+        elif [[ "${property_name}" == "test.default.maxmemory" ]] ; then
+            mvn_properties="${mvn_properties} -Dtest.maxmemory=${property_value}"
+
+        else
+            unknown_args="${unknown_args} \"${arg}\""
+
+        fi
+
+    else
+        if [[ "${arg}" != "dist" && "${mvn_args}" != "" && "${mvn_args}" != "verify" ]] ; then
+            echo "Sorry, this script does not currently support mixing targets." >&2
+            exit 1
+
+        elif [[ "${arg}" == "dist" ]] ; then
+            mvn_args="verify"
+
+        elif [[ "${arg}" == "gatk" ]] ; then
+            mvn_args="verify '-P!queue'"
+
+        elif [[ "${arg}" == "test.compile" ]] ; then
+            mvn_args="test-compile"
+
+        elif [[ "${arg}" == "gatkdocs" ]] ; then
+            local_repo="sitetemprepo"
+            mvn_args="install -Dmaven.repo.local=${local_repo} -Ddisable.queue && mvn site -Dmaven.repo.local=${local_repo} -Ddisable.queue"
+
+        elif [[ "${arg}" == "package.gatk.full" ]] ; then
+            mvn_args="package '-P!private,!queue'"
+
+        elif [[ "${arg}" == "package.gatk.all" ]] ; then
+            mvn_args="package '-P!queue'"
+
+        elif [[ "${arg}" == "package.queue.full" ]] ; then
+            mvn_args="package '-P!private'"
+
+        elif [[ "${arg}" == "package.queue.all" ]] ; then
+            mvn_args="package"
+
+#        elif [[ "${arg}" == "release.gatk.full" ]] ; then
+#            mvn_args="package '-P!private,!queue'"
+#            post_script=" && private/src/main/scripts/shell/copy_release.sh public/gatk-package/target/GenomeAnalysisTK-*.tar.bz2"
+
+#        elif [[ "${arg}" == "release.queue.full" ]] ; then
+#            mvn_args="package '-P!private'"
+#            post_script=" && private/src/main/scripts/shell/copy_release.sh public/queue-package/target/Queue-*.tar.bz2"
+
+        elif [[ "${arg}" == "build-picard-private" ]] ; then
+            mvn_args="mvn install -f private/picard-maven/pom.xml"
+
+        # TODO: clover support
+        # see ant and maven docs for clover:
+        #  https://confluence.atlassian.com/display/CLOVER/1.+QuickStart+Guide
+        #  https://confluence.atlassian.com/display/CLOVER/Clover-for-Maven+2+and+3+User%27s+Guide
+        #
+        #elif [[ "${arg}" == "clover.report" ]] ; then
+        #    mvn_args=...
+        #
+        #elif [[ "${arg}" == "with.clover" ]] ; then
+        #    mvn_args=...
+
+        # TODO: This runs *all* commit tests, including the few on Queue.
+        elif [[ "${arg}" == "gatkfull.binary.release.tests" ]] ; then
+            local_repo="sitetemprepo"
+            mvn_args="install -Dmaven.repo.local=${local_repo} && mvn verify"
+            mvn_args="${mvn_args} -Dmaven.repo.local=${local_repo}"
+            mvn_args="${mvn_args} -Dgatk.packagetests.enabled=true"
+            mvn_args="${mvn_args} -Dgatk.packagecommittests.skipped=false"
+
+        # TODO: This runs only the queue tests (full, non-dry run), but not the commit tests for Queue.
+        elif [[ "${arg}" == "queuefull.binary.release.tests" ]] ; then
+            local_repo="sitetemprepo"
+            mvn_args="install -Dmaven.repo.local=${local_repo} && mvn verify"
+            mvn_args="${mvn_args} -Dmaven.repo.local=${local_repo}"
+            mvn_args="${mvn_args} -Dgatk.packagetests.enabled=true"
+            mvn_args="${mvn_args} -Dgatk.packagequeuetests.skipped=false"
+            mvn_args="${mvn_args} -Dgatk.queuetests.run=true"
+
+        elif [[ "${arg}" == "committests" ]] ; then
+            mvn_args="verify -Dgatk.committests.skipped=false"
+
+        elif [[ "${arg}" == "test" ]] ; then
+            mvn_args="test -Dgatk.unittests.skipped=false"
+
+        elif [[ "${arg}" == "unittest" ]] ; then
+            mvn_args="test -Dgatk.unittests.skipped=false"
+
+        elif [[ "${arg}" == "integrationtest" ]] ; then
+            mvn_args="verify -Dgatk.integrationtests.skipped=false"
+
+        elif [[ "${arg}" == "largescaletest" ]] ; then
+            mvn_args="verify -Dgatk.largescaletests.skipped=false"
+
+        elif [[ "${arg}" == "knowledgebasetest" ]] ; then
+            mvn_args="verify -Dgatk.knowledgebasetests.skipped=false"
+
+        elif [[ "${arg}" == "queuetest" ]] ; then
+            mvn_args="verify -Dgatk.queuetests.skipped=false"
+
+        elif [[ "${arg}" == "queuetestrun" ]] ; then
+            mvn_args="verify -Dgatk.queuetests.skipped=false -Dgatk.queuetests.run=true"
+
+        elif [[ "${arg}" == "fasttest" ]] ; then
+            mvn_args="verify -Dgatk.committests.skipped=false -pl private/gatk-tools-private -am -Dresource.bundle.skip=true"
+
+        else
+            unknown_args="${unknown_args} \"${arg}\""
+
+        fi
+
+    fi
+
+done
+
+mvn_cmd=
+if [[ "${mvn_clean}" != "" ]] ; then
+    if [[ "${mvn_args}" != "" ]] ; then
+      mvn_cmd="mvn ${mvn_clean} && mvn ${mvn_args}"
+    else
+      mvn_cmd="mvn ${mvn_clean}"
+    fi
+else
+    mvn_cmd="mvn ${mvn_args}"
+fi
+
+if [[ "${unknown_args}" != "" ]] ; then
+    echo "Unrecognized arguments:${unknown_args}" >&2
+
+else
+    echo "Equivalent maven command"
+    echo "${mvn_cmd}${mvn_properties}${post_script}"
+
+    if [[ "${run_type}" != "dry" ]] ; then
+        sh -c "${mvn_cmd}${mvn_properties}${post_script}"
+    fi
+
+fi
diff --git a/intellij_example.tar.bz2 b/intellij_example.tar.bz2
new file mode 100644
index 0000000..bce1604
Binary files /dev/null and b/intellij_example.tar.bz2 differ
diff --git a/licensing/private_license.txt b/licensing/private_license.txt
new file mode 100644
index 0000000..a9d3904
--- /dev/null
+++ b/licensing/private_license.txt
@@ -0,0 +1,48 @@
+By downloading the PROGRAM you agree to the following terms of use:
+
+BROAD INSTITUTE
+SOFTWARE LICENSE AGREEMENT
+FOR ACADEMIC NON-COMMERCIAL RESEARCH PURPOSES ONLY
+
+This Agreement is made between the Broad Institute, Inc. with a principal address at 415 Main Street, Cambridge, MA 02142 (“BROAD”) and the LICENSEE and is effective at the date the downloading is completed (“EFFECTIVE DATE”).
+
+WHEREAS, LICENSEE desires to license the PROGRAM, as defined hereinafter, and BROAD wishes to have this PROGRAM utilized in the public interest, subject only to the royalty-free, nonexclusive, nontransferable license rights of the United States Government pursuant to 48 CFR 52.227-14; and
+WHEREAS, LICENSEE desires to license the PROGRAM and BROAD desires to grant a license on the following terms and conditions.
+NOW, THEREFORE, in consideration of the promises and covenants made herein, the parties hereto agree as follows:
+
+1. DEFINITIONS
+1.1 PROGRAM shall mean copyright in the object code and source code known as GATK3 and related documentation, if any, as they exist on the EFFECTIVE DATE and can be downloaded from http://www.broadinstitute.org/gatk on the EFFECTIVE DATE.
+
+2. LICENSE
+2.1 Grant. Subject to the terms of this Agreement, BROAD hereby grants to LICENSEE, solely for academic non-commercial research purposes, a non-exclusive, non-transferable license to: (a) download, execute and display the PROGRAM and (b) create bug fixes and modify the PROGRAM. LICENSEE hereby automatically grants to BROAD a non-exclusive, royalty-free, irrevocable license to any LICENSEE bug fixes or modifications to the PROGRAM with unlimited rights to sublicense and/or distribute.  LI [...]
+The LICENSEE may apply the PROGRAM in a pipeline to data owned by users other than the LICENSEE and provide these users the results of the PROGRAM provided LICENSEE does so for academic non-commercial purposes only. For clarification purposes, academic sponsored research is not a commercial use under the terms of this Agreement.
+2.2 No Sublicensing or Additional Rights. LICENSEE shall not sublicense or distribute the PROGRAM, in whole or in part, without prior written permission from BROAD. LICENSEE shall ensure that all of its users agree to the terms of this Agreement. LICENSEE further agrees that it shall not put the PROGRAM on a network, server, or other similar technology that may be accessed by anyone other than the LICENSEE and its employees and users who have agreed to the terms of this agreement.
+2.3 License Limitations. Nothing in this Agreement shall be construed to confer any rights upon LICENSEE by implication, estoppel, or otherwise to any computer software, trademark, intellectual property, or patent rights of BROAD, or of any other entity, except as expressly granted herein. LICENSEE agrees that the PROGRAM, in whole or part, shall not be used for any commercial purpose, including without limitation, as the basis of a commercial software or hardware product or to provide s [...]
+
+3. PHONE-HOME FEATURE
+LICENSEE expressly acknowledges that the PROGRAM contains an embedded automatic reporting system (“PHONE-HOME”) which is enabled by default upon download. Unless LICENSEE requests disablement of PHONE-HOME, LICENSEE agrees that BROAD may collect limited information transmitted by PHONE-HOME regarding LICENSEE and its use of the PROGRAM.  Such information shall include LICENSEE’S user identification, version number of the PROGRAM and tools being run, mode of analysis employed, and any err [...]
+
+4. OWNERSHIP OF INTELLECTUAL PROPERTY
+LICENSEE acknowledges that title to the PROGRAM shall remain with BROAD. The PROGRAM is marked with the following BROAD copyright notice and notice of attribution to contributors. LICENSEE shall retain such notice on all copies. LICENSEE agrees to include appropriate attribution if any results obtained from use of the PROGRAM are included in any publication.
+Copyright 2012-2014 Broad Institute, Inc.
+Notice of attribution: The GATK3 program was made available through the generosity of Medical and Population Genetics program at the Broad Institute, Inc.
+LICENSEE shall not use any trademark or trade name of BROAD, or any variation, adaptation, or abbreviation, of such marks or trade names, or any names of officers, faculty, students, employees, or agents of BROAD except as states above for attribution purposes.
+
+5. INDEMNIFICATION
+LICENSEE shall indemnify, defend, and hold harmless BROAD, and their respective officers, faculty, students, employees, associated investigators and agents, and their respective successors, heirs and assigns, (Indemnitees), against any liability, damage, loss, or expense (including reasonable attorneys fees and expenses) incurred by or imposed upon any of the Indemnitees in connection with any claims, suits, actions, demands or judgments arising out of any theory of liability (including, [...]
+
+6. NO REPRESENTATIONS OR WARRANTIES
+THE PROGRAM IS DELIVERED AS IS. BROAD MAKES NO REPRESENTATIONS OR WARRANTIES OF ANY KIND CONCERNING THE PROGRAM OR THE COPYRIGHT, EXPRESS OR IMPLIED, INCLUDING, WITHOUT LIMITATION, WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, NONINFRINGEMENT, OR THE ABSENCE OF LATENT OR OTHER DEFECTS, WHETHER OR NOT DISCOVERABLE. BROAD EXTENDS NO WARRANTIES OF ANY KIND AS TO PROGRAM CONFORMITY WITH WHATEVER USER MANUALS OR OTHER LITERATURE MAY BE ISSUED FROM TIME TO TIME.
+IN NO EVENT SHALL BROAD OR ITS RESPECTIVE DIRECTORS, OFFICERS, EMPLOYEES, AFFILIATED INVESTIGATORS AND AFFILIATES BE LIABLE FOR INCIDENTAL OR CONSEQUENTIAL DAMAGES OF ANY KIND, INCLUDING, WITHOUT LIMITATION, ECONOMIC DAMAGES OR INJURY TO PROPERTY AND LOST PROFITS, REGARDLESS OF WHETHER BROAD SHALL BE ADVISED, SHALL HAVE OTHER REASON TO KNOW, OR IN FACT SHALL KNOW OF THE POSSIBILITY OF THE FOREGOING.
+
+7. ASSIGNMENT
+This Agreement is personal to LICENSEE and any rights or obligations assigned by LICENSEE without the prior written consent of BROAD shall be null and void.
+
+8. MISCELLANEOUS
+8.1 Export Control. LICENSEE gives assurance that it will comply with all United States export control laws and regulations controlling the export of the PROGRAM, including, without limitation, all Export Administration Regulations of the United States Department of Commerce. Among other things, these laws and regulations prohibit, or require a license for, the export of certain types of software to specified countries.
+8.2 Termination. LICENSEE shall have the right to terminate this Agreement for any reason upon prior written notice to BROAD. If LICENSEE breaches any provision hereunder, and fails to cure such breach within thirty (30) days, BROAD may terminate this Agreement immediately. Upon termination, LICENSEE shall provide BROAD with written assurance that the original and all copies of the PROGRAM have been destroyed, except that, upon prior written authorization from BROAD, LICENSEE may retain  [...]
+8.3 Survival. The following provisions shall survive the expiration or termination of this Agreement: Articles 1, 3, 4, 5 and Sections 2.2, 2.3, 7.3, and 7.4.
+8.4 Notice. Any notices under this Agreement shall be in writing, shall specifically refer to this Agreement, and shall be sent by hand, recognized national overnight courier, confirmed facsimile transmission, confirmed electronic mail, or registered or certified mail, postage prepaid, return receipt requested. All notices under this Agreement shall be deemed effective upon receipt.
+8.5 Amendment and Waiver; Entire Agreement. This Agreement may be amended, supplemented, or otherwise modified only by means of a written instrument signed by all parties. Any waiver of any rights or failure to act in a specific instance shall relate only to such instance and shall not be construed as an agreement to waive any rights or fail to act in any other instance, whether or not similar. This Agreement constitutes the entire agreement among the parties with respect to its subject  [...]
+8.6 Binding Effect; Headings. This Agreement shall be binding upon and inure to the benefit of the parties and their respective permitted successors and assigns. All headings are for convenience only and shall not affect the meaning of any provision of this Agreement.
+8.7 Governing Law. This Agreement shall be construed, governed, interpreted and applied in accordance with the internal laws of the Commonwealth of Massachusetts, U.S.A., without regard to conflict of laws principles.
diff --git a/licensing/protected_license.txt b/licensing/protected_license.txt
new file mode 100644
index 0000000..a9d3904
--- /dev/null
+++ b/licensing/protected_license.txt
@@ -0,0 +1,48 @@
+By downloading the PROGRAM you agree to the following terms of use:
+
+BROAD INSTITUTE
+SOFTWARE LICENSE AGREEMENT
+FOR ACADEMIC NON-COMMERCIAL RESEARCH PURPOSES ONLY
+
+This Agreement is made between the Broad Institute, Inc. with a principal address at 415 Main Street, Cambridge, MA 02142 (“BROAD”) and the LICENSEE and is effective at the date the downloading is completed (“EFFECTIVE DATE”).
+
+WHEREAS, LICENSEE desires to license the PROGRAM, as defined hereinafter, and BROAD wishes to have this PROGRAM utilized in the public interest, subject only to the royalty-free, nonexclusive, nontransferable license rights of the United States Government pursuant to 48 CFR 52.227-14; and
+WHEREAS, LICENSEE desires to license the PROGRAM and BROAD desires to grant a license on the following terms and conditions.
+NOW, THEREFORE, in consideration of the promises and covenants made herein, the parties hereto agree as follows:
+
+1. DEFINITIONS
+1.1 PROGRAM shall mean copyright in the object code and source code known as GATK3 and related documentation, if any, as they exist on the EFFECTIVE DATE and can be downloaded from http://www.broadinstitute.org/gatk on the EFFECTIVE DATE.
+
+2. LICENSE
+2.1 Grant. Subject to the terms of this Agreement, BROAD hereby grants to LICENSEE, solely for academic non-commercial research purposes, a non-exclusive, non-transferable license to: (a) download, execute and display the PROGRAM and (b) create bug fixes and modify the PROGRAM. LICENSEE hereby automatically grants to BROAD a non-exclusive, royalty-free, irrevocable license to any LICENSEE bug fixes or modifications to the PROGRAM with unlimited rights to sublicense and/or distribute.  LI [...]
+The LICENSEE may apply the PROGRAM in a pipeline to data owned by users other than the LICENSEE and provide these users the results of the PROGRAM provided LICENSEE does so for academic non-commercial purposes only. For clarification purposes, academic sponsored research is not a commercial use under the terms of this Agreement.
+2.2 No Sublicensing or Additional Rights. LICENSEE shall not sublicense or distribute the PROGRAM, in whole or in part, without prior written permission from BROAD. LICENSEE shall ensure that all of its users agree to the terms of this Agreement. LICENSEE further agrees that it shall not put the PROGRAM on a network, server, or other similar technology that may be accessed by anyone other than the LICENSEE and its employees and users who have agreed to the terms of this agreement.
+2.3 License Limitations. Nothing in this Agreement shall be construed to confer any rights upon LICENSEE by implication, estoppel, or otherwise to any computer software, trademark, intellectual property, or patent rights of BROAD, or of any other entity, except as expressly granted herein. LICENSEE agrees that the PROGRAM, in whole or part, shall not be used for any commercial purpose, including without limitation, as the basis of a commercial software or hardware product or to provide s [...]
+
+3. PHONE-HOME FEATURE
+LICENSEE expressly acknowledges that the PROGRAM contains an embedded automatic reporting system (“PHONE-HOME”) which is enabled by default upon download. Unless LICENSEE requests disablement of PHONE-HOME, LICENSEE agrees that BROAD may collect limited information transmitted by PHONE-HOME regarding LICENSEE and its use of the PROGRAM.  Such information shall include LICENSEE’S user identification, version number of the PROGRAM and tools being run, mode of analysis employed, and any err [...]
+
+4. OWNERSHIP OF INTELLECTUAL PROPERTY
+LICENSEE acknowledges that title to the PROGRAM shall remain with BROAD. The PROGRAM is marked with the following BROAD copyright notice and notice of attribution to contributors. LICENSEE shall retain such notice on all copies. LICENSEE agrees to include appropriate attribution if any results obtained from use of the PROGRAM are included in any publication.
+Copyright 2012-2014 Broad Institute, Inc.
+Notice of attribution: The GATK3 program was made available through the generosity of Medical and Population Genetics program at the Broad Institute, Inc.
+LICENSEE shall not use any trademark or trade name of BROAD, or any variation, adaptation, or abbreviation, of such marks or trade names, or any names of officers, faculty, students, employees, or agents of BROAD except as states above for attribution purposes.
+
+5. INDEMNIFICATION
+LICENSEE shall indemnify, defend, and hold harmless BROAD, and their respective officers, faculty, students, employees, associated investigators and agents, and their respective successors, heirs and assigns, (Indemnitees), against any liability, damage, loss, or expense (including reasonable attorneys fees and expenses) incurred by or imposed upon any of the Indemnitees in connection with any claims, suits, actions, demands or judgments arising out of any theory of liability (including, [...]
+
+6. NO REPRESENTATIONS OR WARRANTIES
+THE PROGRAM IS DELIVERED AS IS. BROAD MAKES NO REPRESENTATIONS OR WARRANTIES OF ANY KIND CONCERNING THE PROGRAM OR THE COPYRIGHT, EXPRESS OR IMPLIED, INCLUDING, WITHOUT LIMITATION, WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, NONINFRINGEMENT, OR THE ABSENCE OF LATENT OR OTHER DEFECTS, WHETHER OR NOT DISCOVERABLE. BROAD EXTENDS NO WARRANTIES OF ANY KIND AS TO PROGRAM CONFORMITY WITH WHATEVER USER MANUALS OR OTHER LITERATURE MAY BE ISSUED FROM TIME TO TIME.
+IN NO EVENT SHALL BROAD OR ITS RESPECTIVE DIRECTORS, OFFICERS, EMPLOYEES, AFFILIATED INVESTIGATORS AND AFFILIATES BE LIABLE FOR INCIDENTAL OR CONSEQUENTIAL DAMAGES OF ANY KIND, INCLUDING, WITHOUT LIMITATION, ECONOMIC DAMAGES OR INJURY TO PROPERTY AND LOST PROFITS, REGARDLESS OF WHETHER BROAD SHALL BE ADVISED, SHALL HAVE OTHER REASON TO KNOW, OR IN FACT SHALL KNOW OF THE POSSIBILITY OF THE FOREGOING.
+
+7. ASSIGNMENT
+This Agreement is personal to LICENSEE and any rights or obligations assigned by LICENSEE without the prior written consent of BROAD shall be null and void.
+
+8. MISCELLANEOUS
+8.1 Export Control. LICENSEE gives assurance that it will comply with all United States export control laws and regulations controlling the export of the PROGRAM, including, without limitation, all Export Administration Regulations of the United States Department of Commerce. Among other things, these laws and regulations prohibit, or require a license for, the export of certain types of software to specified countries.
+8.2 Termination. LICENSEE shall have the right to terminate this Agreement for any reason upon prior written notice to BROAD. If LICENSEE breaches any provision hereunder, and fails to cure such breach within thirty (30) days, BROAD may terminate this Agreement immediately. Upon termination, LICENSEE shall provide BROAD with written assurance that the original and all copies of the PROGRAM have been destroyed, except that, upon prior written authorization from BROAD, LICENSEE may retain  [...]
+8.3 Survival. The following provisions shall survive the expiration or termination of this Agreement: Articles 1, 3, 4, 5 and Sections 2.2, 2.3, 7.3, and 7.4.
+8.4 Notice. Any notices under this Agreement shall be in writing, shall specifically refer to this Agreement, and shall be sent by hand, recognized national overnight courier, confirmed facsimile transmission, confirmed electronic mail, or registered or certified mail, postage prepaid, return receipt requested. All notices under this Agreement shall be deemed effective upon receipt.
+8.5 Amendment and Waiver; Entire Agreement. This Agreement may be amended, supplemented, or otherwise modified only by means of a written instrument signed by all parties. Any waiver of any rights or failure to act in a specific instance shall relate only to such instance and shall not be construed as an agreement to waive any rights or fail to act in any other instance, whether or not similar. This Agreement constitutes the entire agreement among the parties with respect to its subject  [...]
+8.6 Binding Effect; Headings. This Agreement shall be binding upon and inure to the benefit of the parties and their respective permitted successors and assigns. All headings are for convenience only and shall not affect the meaning of any provision of this Agreement.
+8.7 Governing Law. This Agreement shall be construed, governed, interpreted and applied in accordance with the internal laws of the Commonwealth of Massachusetts, U.S.A., without regard to conflict of laws principles.
diff --git a/licensing/public_license.txt b/licensing/public_license.txt
new file mode 100644
index 0000000..648ec8f
--- /dev/null
+++ b/licensing/public_license.txt
@@ -0,0 +1,22 @@
+Copyright (c) 2012 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.
diff --git a/pom.xml b/pom.xml
new file mode 100644
index 0000000..8488cf8
--- /dev/null
+++ b/pom.xml
@@ -0,0 +1,756 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+    <modelVersion>4.0.0</modelVersion>
+
+    <!--
+    This pom is the aggregator for all gatk poms
+    See also:
+      http://maven.apache.org/pom.html#Inheritance_v
+      http://maven.apache.org/guides/introduction/introduction-to-the-pom.html#Project_Inheritance_vs_Project_Aggregation
+      http://stackoverflow.com/questions/1992213/maven-parent-pom-vs-modules-pom
+    -->
+
+    <parent>
+        <groupId>org.broadinstitute.gatk</groupId>
+        <artifactId>gatk-root</artifactId>
+        <version>3.3</version>
+        <relativePath>public/gatk-root</relativePath>
+    </parent>
+
+    <artifactId>gatk-aggregator</artifactId>
+    <packaging>pom</packaging>
+    <name>GATK Aggregator</name>
+
+    <modules>
+        <module>public</module>
+        <!-- private & protected optionally enabled as profiles -->
+    </modules>
+
+    <properties>
+        <gatk.basedir>${project.basedir}</gatk.basedir>
+        <resource.bundle.path>GATKText.properties</resource.bundle.path>
+        <resource.bundle.skip>false</resource.bundle.skip>
+        <!-- TODO: Need a better a way to say "don't include hidden" by default -->
+        <gatkdocs.include.hidden>-build-timestamp "${maven.build.timestamp}"</gatkdocs.include.hidden>
+
+        <!--
+        Phases of the build that may be disabled to speed up compilation.
+        -->
+        <gatk.jar.phase>package</gatk.jar.phase>
+        <gatk.generate-resources.phase>generate-resources</gatk.generate-resources.phase>
+        <gatk.process-resources.phase>process-resources</gatk.process-resources.phase>
+        <gatk.process-test-resources.phase>process-test-resources</gatk.process-test-resources.phase>
+
+        <!--
+        Package tests ensure the consistency of the packaged / shaded jars.
+        It runs the tests where the monolithic jar is the only dependency on the classpath.
+        -->
+        <gatk.packagecommittests.skipped>true</gatk.packagecommittests.skipped>
+        <gatk.packageunittests.skipped>${gatk.packagecommittests.skipped}</gatk.packageunittests.skipped>
+        <gatk.packageintegrationtests.skipped>${gatk.packagecommittests.skipped}</gatk.packageintegrationtests.skipped>
+        <gatk.packagequeuetests.skipped>${gatk.packagecommittests.skipped}</gatk.packagequeuetests.skipped>
+        <gatk.packagelargescaletests.skipped>true</gatk.packagelargescaletests.skipped>
+        <gatk.packageknowledgebasetests.skipped>true</gatk.packageknowledgebasetests.skipped>
+
+        <!--
+        Serial tests use the test jars to run tests, such that all tests are run from a single TestNG invocation.
+        This is different that the invoker, that runs the test classes from the filesystem, but pointing at the packaged JAR files.
+        TODO: Currently, all tests run within each package, since packages already collect dependencies for shading an uber jar.
+        TODO: Should there be another level up of tests, possibly running "all tests" via this aggregator level?
+        TODO: If that require the aggregator to be dependent on the child dependencies, perhaps a better approach might be another monolithic test project.
+        -->
+        <gatk.serialcommittests.skipped>true</gatk.serialcommittests.skipped>
+        <gatk.serialunittests.skipped>${gatk.serialcommittests.skipped}</gatk.serialunittests.skipped>
+        <gatk.serialintegrationtests.skipped>${gatk.serialcommittests.skipped}</gatk.serialintegrationtests.skipped>
+        <gatk.serialqueuetests.skipped>${gatk.serialcommittests.skipped}</gatk.serialqueuetests.skipped>
+        <gatk.seriallargescaletests.skipped>true</gatk.seriallargescaletests.skipped>
+        <gatk.serialknowledgebasetests.skipped>true</gatk.serialknowledgebasetests.skipped>
+    </properties>
+
+    <dependencies>
+        <dependency>
+            <groupId>com.sun</groupId>
+            <artifactId>tools</artifactId>
+        </dependency>
+    </dependencies>
+
+    <build>
+        <!-- Plugin configuration -->
+        <pluginManagement>
+            <plugins>
+                <plugin>
+                    <groupId>org.apache.maven.plugins</groupId>
+                    <artifactId>maven-clean-plugin</artifactId>
+                    <configuration>
+                        <filesets>
+                            <!--
+                            TODO: Once GATKDoclet stops hard coding paths, we remove this and leave
+                            TODO: it to the standard maven conventions to clean up for us
+                            -->
+                            <fileset>
+                                <directory>gatkdocs</directory>
+                            </fileset>
+                            <fileset>
+                                <directory>${basedir}</directory>
+                                <includes>
+                                    <include>javadoc.sh</include>
+                                    <include>options</include>
+                                    <include>packages</include>
+                                </includes>
+                            </fileset>
+                            <!--
+                            Shade dumps this temp file in basedir, with no good way to reconfigure.
+                            https://jira.codehaus.org/browse/MSHADE-145
+                            -->
+                            <fileset>
+                                <directory>${basedir}</directory>
+                                <includes>
+                                    <include>dependency-reduced-pom.xml</include>
+                                </includes>
+                            </fileset>
+                        </filesets>
+                    </configuration>
+                </plugin>
+                <plugin>
+                    <groupId>org.apache.maven.plugins</groupId>
+                    <artifactId>maven-dependency-plugin</artifactId>
+                    <executions>
+                        <execution>
+                            <id>unpack-direct-dependencies</id>
+                            <goals>
+                                <goal>unpack-dependencies</goal>
+                            </goals>
+                            <phase>none</phase>
+                            <!--
+                            NOTE: Shade include filters do NOT include transient dependencies, only the class directly listed.
+
+                            Thus to fully include all the classes in packages, we must:
+                                1) List the artifacts we want shaded as direct dependencies
+                                2) Run the unpack direct dependencies into the classes directory
+                                3) Shade the classes directory as we normally would.
+                            -->
+                            <configuration>
+                                <excludeTransitive>true</excludeTransitive>
+                                <outputDirectory>${project.build.outputDirectory}</outputDirectory>
+                                <includeTypes>jar</includeTypes>
+                                <includeScope>runtime</includeScope>
+                                <!-- Don't unjar the resource bundle, so that shade's AppendingTransformer can merge -->
+                                <excludes>${resource.bundle.path}</excludes>
+                            </configuration>
+                        </execution>
+                    </executions>
+                </plugin>
+                <!-- TODO: Change the ResourceBundleExtractorDoclet to not require log4j.properties file -->
+                <plugin>
+                    <groupId>org.apache.maven.plugins</groupId>
+                    <artifactId>maven-resources-plugin</artifactId>
+                    <executions>
+                        <execution>
+                            <id>default-resources</id>
+                            <goals>
+                                <goal>resources</goal>
+                            </goals>
+                            <phase>${gatk.process-resources.phase}</phase>
+                        </execution>
+                        <execution>
+                            <id>default-testResources</id>
+                            <goals>
+                                <goal>testResources</goal>
+                            </goals>
+                            <phase>${gatk.process-test-resources.phase}</phase>
+                        </execution>
+                        <execution>
+                            <id>copy-resource-bundle-log4j</id>
+                            <goals>
+                                <goal>copy-resources</goal>
+                            </goals>
+                            <phase>none</phase>
+                            <configuration>
+                                <!--
+                                Just before running the resource bundle generation, copy a simple log4j
+                                config file to the apidocs execution directory, so that logging prints out.
+                                -->
+                                <outputDirectory>${project.reporting.outputDirectory}/apidocs</outputDirectory>
+                                <resources>
+                                    <resource>
+                                        <directory>${gatk.basedir}/gatk-utils/src/main/config/org/broadinstitute/gatk/utils/help</directory>
+                                    </resource>
+                                </resources>
+                            </configuration>
+                        </execution>
+                    </executions>
+                </plugin>
+                <plugin>
+                    <groupId>org.apache.maven.plugins</groupId>
+                    <artifactId>maven-javadoc-plugin</artifactId>
+                    <executions>
+                        <execution>
+                            <id>extract-resource-bundle</id>
+                            <goals>
+                                <goal>javadoc</goal>
+                            </goals>
+                            <phase>none</phase>
+                            <configuration>
+                                <!-- Allow skipping for "fasttest" -->
+                                <skip>${resource.bundle.skip}</skip>
+                                <doclet>org.broadinstitute.gatk.utils.help.ResourceBundleExtractorDoclet</doclet>
+                                <!-- Required as doclet uses reflection to access classes for documentation, instead of source java-->
+                                <docletPath>${project.build.outputDirectory}</docletPath>
+                                <docletArtifact>
+                                    <groupId>${project.groupId}</groupId>
+                                    <!-- TODO: THIS IS SUPPOSED TO BE GATK-UTILS! -->
+                                    <artifactId>gatk-tools-public</artifactId>
+                                    <version>${project.version}</version>
+                                </docletArtifact>
+                                <maxmemory>2g</maxmemory>
+                                <useStandardDocletOptions>false</useStandardDocletOptions>
+                                <quiet>true</quiet>
+                                <additionalparam>-build-timestamp "${maven.build.timestamp}" -absolute-version ${build.version} -out "${project.build.outputDirectory}/${resource.bundle.path}"</additionalparam>
+                            </configuration>
+                        </execution>
+                    </executions>
+                </plugin>
+
+                <plugin>
+                    <groupId>org.apache.maven.plugins</groupId>
+                    <artifactId>maven-compiler-plugin</artifactId>
+                    <configuration>
+                        <proc>none</proc>
+                        <annotationProcessors>
+                            <annotationProcessor>com.google.java.contract.core.apt.AnnotationProcessor</annotationProcessor>
+                        </annotationProcessors>
+                    </configuration>
+                    <executions>
+                        <execution>
+                            <id>default-compile</id>
+                            <phase>none</phase>
+                        </execution>
+                        <execution>
+                            <id>default-testCompile</id>
+                            <phase>none</phase>
+                        </execution>
+                        <!--
+                        Explicit package-info creation to match existing ant output.
+                        -->
+                        <execution>
+                            <id>compile-package-info</id>
+                            <goals>
+                                <goal>compile</goal>
+                            </goals>
+                            <phase>compile</phase>
+                            <configuration>
+                                <compilerArgs>
+                                    <arg>-Xpkginfo:always</arg>
+                                </compilerArgs>
+                                <includes>
+                                    <include>**/package-info.java</include>
+                                </includes>
+                            </configuration>
+                        </execution>
+                        <!--
+                        TODO: Currently disabled in build.xml. Here as well.
+                        <execution>
+                            <id>compile-annotations</id>
+                            <phase>compile</phase>
+                            <goals>
+                                <goal>compile</goal>
+                            </goals>
+                            <configuration>
+                                <proc>only</proc>
+                            </configuration>
+                        </execution>
+                        -->
+                        <execution>
+                            <id>compile-java</id>
+                            <goals>
+                                <goal>compile</goal>
+                            </goals>
+                            <phase>compile</phase>
+                            <configuration>
+                                <!--
+                                Package info is supposed to be in source:
+                                    http://maven.apache.org/plugins/maven-javadoc-plugin/examples/javadoc-resources.html
+                                But maven-compile-plugin doesn't auto exclude these:
+                                    https://jira.codehaus.org/browse/MCOMPILER-205?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=326505#comment-326505
+                                So, explicitly exclude them
+                                -->
+                                <excludes>
+                                    <exclude>**/package-info.java</exclude>
+                                </excludes>
+                            </configuration>
+                        </execution>
+                        <!--
+                        TODO: Currently disabled in build.xml. Here as well.
+                        <execution>
+                            <id>testCompile-annotations</id>
+                            <phase>test-compile</phase>
+                            <goals>
+                                <goal>testCompile</goal>
+                            </goals>
+                            <configuration>
+                                <proc>only</proc>
+                            </configuration>
+                        </execution>
+                        -->
+                        <execution>
+                            <id>testCompile-java</id>
+                            <goals>
+                                <goal>testCompile</goal>
+                            </goals>
+                            <phase>test-compile</phase>
+                        </execution>
+                    </executions>
+                </plugin>
+
+                <plugin>
+                    <groupId>org.scala-tools</groupId>
+                    <artifactId>maven-scala-plugin</artifactId>
+                    <executions>
+                        <execution>
+                            <goals>
+                                <goal>compile</goal>
+                                <goal>testCompile</goal>
+                            </goals>
+                        </execution>
+                    </executions>
+                </plugin>
+
+                <plugin>
+                    <groupId>org.apache.maven.plugins</groupId>
+                    <artifactId>maven-jar-plugin</artifactId>
+                    <executions>
+                        <execution>
+                            <id>default-jar</id>
+                            <phase>${gatk.jar.phase}</phase>
+                        </execution>
+                        <execution>
+                            <id>test-jar</id>
+                            <goals>
+                                <goal>test-jar</goal>
+                            </goals>
+                            <phase>${gatk.jar.phase}</phase>
+                            <configuration>
+                                <skipIfEmpty>true</skipIfEmpty>
+                            </configuration>
+                        </execution>
+                    </executions>
+                </plugin>
+
+                <plugin>
+                    <groupId>org.apache.maven.plugins</groupId>
+                    <artifactId>maven-shade-plugin</artifactId>
+                    <executions>
+                        <execution>
+                            <id>gatk-executable</id>
+                            <goals>
+                                <goal>shade</goal>
+                            </goals>
+                            <phase>none</phase>
+                            <configuration>
+                                <minimizeJar>true</minimizeJar>
+                                <artifactSet>
+                                    <excludes>
+                                        <exclude>org.broadinstitute.gatk:gsalib:tar.gz:*</exclude>
+                                        <exclude>org.broadinstitute.gatk:*:tar.bz2:example-resources</exclude>
+                                    </excludes>
+                                </artifactSet>
+                                <filters>
+                                    <!--
+                                    NOTE: Removing cofoja's annotation service to allow "javac -cp GenomeAnalysisTK.jar ..." without
+                                    needing an additional -proc:none argument. Using *:* to catch shaded GATK in Queue package.
+                                    -->
+                                    <filter>
+                                        <artifact>*:*</artifact>
+                                        <excludes>
+                                            <exclude>META-INF/services/javax.annotation.processing.Processor</exclude>
+                                        </excludes>
+                                    </filter>
+                                </filters>
+                                <transformers>
+                                    <transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
+                                        <manifestEntries>
+                                            <Main-Class>${app.main.class}</Main-Class>
+                                        </manifestEntries>
+                                    </transformer>
+                                    <transformer implementation="org.apache.maven.plugins.shade.resource.AppendingTransformer">
+                                        <resource>${resource.bundle.path}</resource>
+                                    </transformer>
+                                </transformers>
+                            </configuration>
+                        </execution>
+                    </executions>
+                </plugin>
+
+                <plugin>
+                    <groupId>org.apache.maven.plugins</groupId>
+                    <artifactId>maven-assembly-plugin</artifactId>
+                    <executions>
+                        <execution>
+                            <id>example-resources</id>
+                            <goals>
+                                <goal>single</goal>
+                            </goals>
+                            <phase>none</phase>
+                            <configuration>
+                                <descriptors>
+                                    <descriptor>src/main/assembly/example-resources.xml</descriptor>
+                                </descriptors>
+                            </configuration>
+                        </execution>
+                        <execution>
+                            <id>binary-dist</id>
+                            <goals>
+                                <goal>single</goal>
+                            </goals>
+                            <phase>none</phase>
+                            <configuration>
+                                <descriptors>
+                                    <descriptor>src/main/assembly/binary-dist.xml</descriptor>
+                                </descriptors>
+                            </configuration>
+                        </execution>
+                    </executions>
+                </plugin>
+
+                <plugin>
+                    <groupId>com.pyx4j</groupId>
+                    <artifactId>maven-junction-plugin</artifactId>
+                    <executions>
+                        <!--
+                        HACK: Adding the source directory via build-helper-maven-plugin doesn't work with IntelliJ.
+                        Add compatibility link from public's extensions source code to target/generated-sources.
+                        see: http://wiki.jetbrains.net/intellij/Maven_FAQ
+                        -->
+                        <execution>
+                            <id>link-extensions-sources</id>
+                            <goals>
+                                <goal>link</goal>
+                            </goals>
+                            <phase>none</phase>
+                            <configuration>
+                                <links>
+                                    <link>
+                                        <dst>${project.build.directory}/generated-sources/gatk-queue-extensions-public-src-main-scala</dst>
+                                        <src>${gatk.basedir}/public/gatk-queue-extensions-public/src/main/scala</src>
+                                    </link>
+                                </links>
+                            </configuration>
+                        </execution>
+                        <execution>
+                            <id>link-binary-jar</id>
+                            <goals>
+                                <goal>link</goal>
+                            </goals>
+                            <phase>none</phase>
+                            <configuration>
+                                <links>
+                                    <link>
+                                        <dst>${gatk.basedir}/target/${gatk.binary-dist.name}.${project.packaging}</dst>
+                                        <src>${project.build.directory}/${project.build.finalName}.${project.packaging}</src>
+                                    </link>
+                                </links>
+                            </configuration>
+                        </execution>
+                        <execution>
+                            <id>link-git-release</id>
+                            <goals>
+                                <goal>link</goal>
+                            </goals>
+                            <phase>none</phase>
+                            <configuration>
+                                <links>
+                                    <link>
+                                        <dst>${project.build.directory}/${gatk.binary-dist.name}-${build.version}.tar.bz2</dst>
+                                        <src>${project.build.directory}/${project.build.finalName}-binary-dist.tar.bz2</src>
+                                    </link>
+                                </links>
+                            </configuration>
+                        </execution>
+                    </executions>
+                </plugin>
+                <plugin>
+                    <groupId>org.apache.maven.plugins</groupId>
+                    <artifactId>maven-invoker-plugin</artifactId>
+                    <configuration>
+                        <skipInvocation>true</skipInvocation>
+                        <debug>false</debug>
+                        <pom>${gatk.basedir}/public/package-tests/pom.xml</pom>
+                        <noLog>true</noLog>
+                        <streamLogs>true</streamLogs>
+                        <localRepositoryPath>${gatk.basedir}/${maven.repo.local}</localRepositoryPath>
+                        <properties>
+                            <test>${test}</test>
+                            <it.test>${it.test}</it.test>
+                            <skip>false</skip>
+                            <maven.test.skip>false</maven.test.skip>
+                            <gatk.packagetests.artifactId>${gatk.packagetests.artifactId}</gatk.packagetests.artifactId>
+                            <gatk.packagetests.testClasses>${project.build.testOutputDirectory}</gatk.packagetests.testClasses>
+                            <gatk.packagetests.basedir>${project.basedir}</gatk.packagetests.basedir>
+                            <gatk.queuetests.run>${gatk.queuetests.run}</gatk.queuetests.run>
+                            <maven.surefire.debug>${maven.surefire.debug}</maven.surefire.debug>
+                            <maven.failsafe.debug>${maven.failsafe.debug}</maven.failsafe.debug>
+                        </properties>
+                        <!--
+                        To allow using separated integration-test and verify, each execution must use a separate reportsDirectory.
+
+                        Otherwise, when an empty "pipeline test" later runs on an IntegrationTest class,
+                        it overwrites the results of the previous invocation always with a zero exit status.
+
+                        Mixing in the test name into the reportsDirectory also avoids collisions, when different maven jobs run tests in parallel.
+
+                        Similarly generating unique failsafe summary reports to avoid collisions.
+                        -->
+                    </configuration>
+                    <executions>
+                        <execution>
+                            <id>package-unittests</id>
+                            <goals>
+                                <goal>run</goal>
+                            </goals>
+                            <configuration>
+                                <goals>
+                                    <goal>test</goal>
+                                </goals>
+                                <reportsDirectory>${project.build.directory}/invoker-reports/unit/${test}</reportsDirectory>
+                                <skipInvocation>${gatk.packageunittests.skipped}</skipInvocation>
+                                <properties>
+                                    <unittests.profile.enabled>true</unittests.profile.enabled>
+                                    <gatk.packageunittests.skipped>${gatk.packageunittests.skipped}</gatk.packageunittests.skipped>
+                                </properties>
+                            </configuration>
+                        </execution>
+                        <execution>
+                            <id>package-integrationtests</id>
+                            <goals>
+                                <goal>integration-test</goal>
+                                <goal>verify</goal>
+                            </goals>
+                            <configuration>
+                                <goals>
+                                    <goal>verify</goal>
+                                </goals>
+                                <reportsDirectory>${project.build.directory}/invoker-reports/integration/${it.test}</reportsDirectory>
+                                <skipInvocation>${gatk.packageintegrationtests.skipped}</skipInvocation>
+                                <properties>
+                                    <integrationtests.profile.enabled>true</integrationtests.profile.enabled>
+                                    <gatk.packageintegrationtests.skipped>${gatk.packageintegrationtests.skipped}</gatk.packageintegrationtests.skipped>
+                                </properties>
+                            </configuration>
+                        </execution>
+                        <execution>
+                            <id>package-queuetests</id>
+                            <goals>
+                                <goal>integration-test</goal>
+                                <goal>verify</goal>
+                            </goals>
+                            <configuration>
+                                <goals>
+                                    <goal>verify</goal>
+                                </goals>
+                                <reportsDirectory>${project.build.directory}/invoker-reports/queuetest/${it.test}</reportsDirectory>
+                                <skipInvocation>${gatk.packagequeuetests.skipped}</skipInvocation>
+                                <properties>
+                                    <integrationtests.profile.enabled>true</integrationtests.profile.enabled>
+                                    <gatk.packagequeuetests.skipped>${gatk.packagequeuetests.skipped}</gatk.packagequeuetests.skipped>
+                                </properties>
+                            </configuration>
+                        </execution>
+                        <execution>
+                            <id>package-largescaletests</id>
+                            <goals>
+                                <goal>integration-test</goal>
+                                <goal>verify</goal>
+                            </goals>
+                            <configuration>
+                                <goals>
+                                    <goal>verify</goal>
+                                </goals>
+                                <reportsDirectory>${project.build.directory}/invoker-reports/largescale/${it.test}</reportsDirectory>
+                                <skipInvocation>${gatk.packagelargescaletests.skipped}</skipInvocation>
+                                <properties>
+                                    <integrationtests.profile.enabled>true</integrationtests.profile.enabled>
+                                    <gatk.packagelargescaletests.skipped>${gatk.packagelargescaletests.skipped}</gatk.packagelargescaletests.skipped>
+                                </properties>
+                            </configuration>
+                        </execution>
+                        <execution>
+                            <id>package-knowledgebasetests</id>
+                            <goals>
+                                <goal>integration-test</goal>
+                                <goal>verify</goal>
+                            </goals>
+                            <configuration>
+                                <goals>
+                                    <goal>verify</goal>
+                                </goals>
+                                <reportsDirectory>${project.build.directory}/invoker-reports/knowledgebase/${it.test}</reportsDirectory>
+                                <skipInvocation>${gatk.packageknowledgebasetests.skipped}</skipInvocation>
+                                <properties>
+                                    <integrationtests.profile.enabled>true</integrationtests.profile.enabled>
+                                    <gatk.packageknowledgebasetests.skipped>${gatk.packageknowledgebasetests.skipped}</gatk.packageknowledgebasetests.skipped>
+                                </properties>
+                            </configuration>
+                        </execution>
+                    </executions>
+                </plugin>
+                <plugin>
+                    <groupId>org.apache.maven.plugins</groupId>
+                    <artifactId>maven-install-plugin</artifactId>
+                    <version>2.5</version>
+                    <executions>
+                        <execution>
+                            <id>install-package</id>
+                            <goals>
+                                <goal>install-file</goal>
+                            </goals>
+                            <phase>none</phase>
+                            <configuration>
+                                <generatePom>true</generatePom>
+                                <groupId>${project.groupId}</groupId>
+                                <artifactId>${project.artifactId}</artifactId>
+                                <version>${project.version}</version>
+                                <packaging>${project.packaging}</packaging>
+                                <file>${project.build.directory}/${project.build.finalName}.${project.packaging}</file>
+                            </configuration>
+                        </execution>
+                    </executions>
+                </plugin>
+            </plugins>
+        </pluginManagement>
+
+        <!-- Invoke plugins that always run -->
+        <plugins>
+            <plugin>
+                <groupId>org.codehaus.mojo</groupId>
+                <artifactId>exec-maven-plugin</artifactId>
+                <executions>
+                    <execution>
+                        <!--
+                        TODO: Remove after 3.3+ release.
+                        Until then, will clean out symbolic links from users who download public/protected.
+                        Perhaps leave the script even longer.
+                        -->
+                        <id>delete-mavens-links</id>
+                        <goals>
+                            <goal>exec</goal>
+                        </goals>
+                        <phase>process-test-resources</phase>
+                        <inherited>false</inherited>
+                        <configuration>
+                            <executable>${gatk.basedir}/public/src/main/scripts/shell/delete_maven_links.sh</executable>
+                        </configuration>
+                    </execution>
+                </executions>
+            </plugin>
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-failsafe-plugin</artifactId>
+            </plugin>
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-clean-plugin</artifactId>
+            </plugin>
+            <plugin>
+                <groupId>com.google.code.sortpom</groupId>
+                <artifactId>maven-sortpom-plugin</artifactId>
+                <executions>
+                    <execution>
+                        <id>package-tests</id>
+                        <goals>
+                            <goal>sort</goal>
+                        </goals>
+                        <phase>verify</phase>
+                        <inherited>false</inherited>
+                        <configuration>
+                            <pomFile>public/package-tests/pom.xml</pomFile>
+                        </configuration>
+                    </execution>
+                </executions>
+            </plugin>
+        </plugins>
+    </build>
+
+    <reporting>
+        <plugins>
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-javadoc-plugin</artifactId>
+                <version>2.9.1</version>
+                <reportSets>
+                    <!-- By not specifying an id, shut off all default javadocs from mvn site -->
+                    <reportSet>
+                        <reports />
+                    </reportSet>
+                    <reportSet>
+                        <id>generate-gatk-docs</id>
+                        <reports>
+                            <report>aggregate</report>
+                        </reports>
+                        <!-- Only generate the GATK Docs across the parent aggregation, not the children too. -->
+                        <inherited>false</inherited>
+                        <configuration>
+                            <doclet>org.broadinstitute.gatk.utils.help.GATKDoclet</doclet>
+                            <docletArtifact>
+                                <groupId>${project.groupId}</groupId>
+                                <artifactId>gatk-package-distribution</artifactId>
+                                <version>${project.version}</version>
+                            </docletArtifact>
+                            <useStandardDocletOptions>false</useStandardDocletOptions>
+                            <quiet>true</quiet>
+                            <show>private</show>
+                            <additionalparam>-build-timestamp "${maven.build.timestamp}" -absolute-version ${build.version} ${gatkdocs.include.hidden} -settings-dir ${gatk.basedir}/settings/helpTemplates -destination-dir ${project.build.directory}/gatkdocs</additionalparam>
+                        </configuration>
+                    </reportSet>
+                </reportSets>
+            </plugin>
+        </plugins>
+    </reporting>
+
+    <profiles>
+        <!-- Optionally include protected -->
+        <profile>
+            <id>protected</id>
+            <activation>
+                <file>
+                    <exists>${basedir}/protected/pom.xml</exists>
+                </file>
+            </activation>
+            <modules>
+                <module>protected</module>
+            </modules>
+        </profile>
+
+        <!-- Optionally include private -->
+        <profile>
+            <id>private</id>
+            <activation>
+                <file>
+                    <exists>${basedir}/private/pom.xml</exists>
+                </file>
+            </activation>
+            <modules>
+                <module>private</module>
+            </modules>
+        </profile>
+
+        <!-- Collection of properties for use during package testing -->
+        <profile>
+            <id>packagetests-enabled</id>
+            <activation>
+                <property>
+                    <name>gatk.packagetests.enabled</name>
+                    <value>true</value>
+                </property>
+            </activation>
+            <properties>
+                <maven.javadoc.skip>true</maven.javadoc.skip>
+                <gatk.generate-gatk-extensions.skipped>true</gatk.generate-gatk-extensions.skipped>
+                <gatk.jar.phase>none</gatk.jar.phase>
+                <gatk.generate-resources.phase>none</gatk.generate-resources.phase>
+                <gatk.process-resources.phase>none</gatk.process-resources.phase>
+                <gatk.process-test-resources.phase>none</gatk.process-test-resources.phase>
+            </properties>
+        </profile>
+    </profiles>
+
+</project>
diff --git a/public/VectorPairHMM/README.md b/public/VectorPairHMM/README.md
new file mode 100644
index 0000000..ad40055
--- /dev/null
+++ b/public/VectorPairHMM/README.md
@@ -0,0 +1,72 @@
+Implementation overview:
+Created a new Java class called VectorLoglessPairHMM which extends LoglessPairHMM and 
+overrides functions from both LoglessPairHMM and PairHMM.
+1. Constructor: Call base class constructors. Then, load the native library located in this 
+directory and call an init function (with suffix 'jniInitializeClassFieldsAndMachineMask') in the 
+library to determine fields ids for the members of classes JNIReadDataHolder and 
+JNIHaplotypeDataHolders. The native code stores the field ids (struct offsets) for the classes and 
+re-uses them for subsequent computations. Optionally, the user can disable the vector 
+implementation, by using the 'mask' argument (see comments for a more detailed explanation).
+2. When the library is loaded, it invokes the constructor of the class LoadTimeInitializer (because 
+a global variable g_load_time_initializer is declared in the library).  This constructor 
+(LoadTimeInitializer.cc) can be used to perform various initializations.  Currently, it initializes 
+two global function pointers to point to the function implementation that is supported on the 
+machine (AVX/SSE/un-vectorized) on which the program is being run. The two pointers are for float 
+and double respectively.  The global function pointers are declared in utils.cc and are assigned in 
+the function initialize_function_pointers() defined in utils.cc and invoked from the constructor of 
+LoadTimeInitializer.
+Other initializations in LoadTimeInitializer:
+* ConvertChar::init - sets some masks for the vector implementation
+* FTZ for performance
+* stat counters = 0
+* debug structs (which are never used in non-debug mode)
+This initialization is done only once for the whole program.
+3. initialize(): To initialize the region for PairHMM. Pass haplotype bases to native code through 
+the JNIHaplotypeDataHolder class.  Since the haplotype list is common across multiple samples in 
+computeReadLikelihoods(), we can pass the haplotype bases to the native code once and re-use across 
+multiple samples.
+4. computeLikelihoods(): Copies array references for readBases/quals etc to array of 
+JNIReadDataHolder objects.  Invokes the JNI function to perform the computation and updates the 
+likelihoodMap.
+The JNI function copies the byte array references into an array of testcase structs and invokes the 
+compute_full_prob function through the function pointers initialized earlier.
+The primary native function called is 
+Java_org_broadinstitute_sting_utils_pairhmm_VectorLoglessPairHMM_jniComputeLikelihoods. It uses 
+standard JNI calls to get and return data from/to the Java class VectorLoglessPairHMM.  The last 
+argument to the function is the maximum number of OpenMP threads to use while computing PairHMM in 
+C++. This option is set when the native function call is made from JNILoglessPairHMM 
+computeLikelihoods - currently it is set to 12 (no logical reason).
+Note: OpenMP has been disabled for now - insufficient #testcases per call to computeLikelihoods() to 
+justify multi-threading.
+5. finalizeRegion(): Releases the haplotype arrays initialized in step 3 - should be called at the 
+end of every region (line 351 in PairHMMLikelihoodCalculationEngine).
+
+Note: Debug code has been moved to a separate class DebugJNILoglessPairHMM.java.
+
+Compiling:
+The native library (called libVectorLoglessPairHMM.so) can be compiled with icc (Intel C compiler) 
+or gcc versions >= 4.8.1 that support AVX intrinsics. By default, the make process tries to invoke 
+icc. To use gcc, edit the file 'pom.xml' (in this directory) and enable the environment variables 
+USE_GCC,C_COMPILER and CPP_COMPILER (edit and uncomment lines 60-62).
+Using Maven:
+Type 'mvn install' in this directory - this will build the library (by invoking 'make') and copy the 
+native library to the directory 
+${sting-utils.basedir}/src/main/resources/org/broadinstitute/sting/utils/pairhmm
+The GATK maven build process (when run) will bundle the library into the StingUtils jar file from 
+the copied directory.
+Simple build:
+cd src/main/c++
+make  
+
+Running:
+The default implementation of PairHMM is now VECTOR_LOGLESS_CACHING in HaplotypeCaller.java. To use 
+the Java version, use the command line argument "--pair_hmm_implementation LOGLESS_CACHING". (see 
+run.sh in src/main/c++).
+The native library is bundled with the StingUtils jar file. When HaplotypeCaller is invoked, then 
+the library is unpacked from the jar file, copied to the /tmp directory (with a unique id) and 
+loaded by the Java class VectorLoglessPairHMM in the constructor (if it has not been loaded 
+already).
+The default library can be overridden by using the -Djava.library.path argument (see 
+src/main/c++/run.sh for an example) for the JVM to pass the path to the library. If the library 
+libVectorLoglessPairHMM.so can be found in java.library.path, then it is loaded and the 'packed' 
+library is not used.
diff --git a/public/VectorPairHMM/pom.xml b/public/VectorPairHMM/pom.xml
new file mode 100644
index 0000000..ca08087
--- /dev/null
+++ b/public/VectorPairHMM/pom.xml
@@ -0,0 +1,122 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+    <modelVersion>4.0.0</modelVersion>
+
+    <parent>
+        <groupId>org.broadinstitute.gatk</groupId>
+        <artifactId>gatk-root</artifactId>
+        <version>3.3</version>
+        <relativePath>../../public/gatk-root</relativePath>
+    </parent>
+
+    <artifactId>VectorPairHMM</artifactId>
+    <packaging>pom</packaging>
+    <name>Vectorized PairHMM native libraries</name>
+
+    <description>Builds a GNU/Linux x86_64 library of VectorPairHMM using icc (Intel C++ compiler). During install, copies it into gatk-utils. Neither tested nor expected to work on any other platform.</description>
+
+    <properties>
+        <sourceEncoding>UTF-8</sourceEncoding>
+        <project.build.sourceEncoding>${sourceEncoding}</project.build.sourceEncoding>
+        <project.reporting.outputEncoding>${sourceEncoding}</project.reporting.outputEncoding>
+        <gatk.basedir>${project.basedir}/../..</gatk.basedir>
+        <gatk-utils.basedir>${gatk.basedir}/public/gatk-utils</gatk-utils.basedir>
+        <!-- Where to place the library in gatk-utils -->
+        <pairhmm.resources.directory>${gatk-utils.basedir}/src/main/resources/org/broadinstitute/gatk/utils/pairhmm</pairhmm.resources.directory>
+    </properties>
+    <build>
+        <plugins>
+            <!-- Print out the architecture - works only on GNU/Linux x86_64 systems -->
+            <!-- Neither tested nor expected to work on any other platform. -->
+            <!-- Requires icc (Intel C++ compiler) to be in your PATH. -->
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-enforcer-plugin</artifactId>
+                <executions>
+                    <execution>
+                        <goals>
+                            <goal>display-info</goal>
+                        </goals>
+                        <phase>validate</phase>
+                    </execution>
+                </executions>
+            </plugin>
+
+            <!-- Run make -->
+            <plugin>
+                <groupId>org.codehaus.mojo</groupId>
+                <artifactId>exec-maven-plugin</artifactId>
+                <executions>
+                    <execution>
+                        <goals>
+                            <goal>exec</goal>
+                        </goals>
+                        <phase>compile</phase>
+                        <configuration>
+                            <executable>make</executable>
+                            <workingDirectory>src/main/c++</workingDirectory>
+                            <environmentVariables>
+                                <JRE_HOME>${java.home}</JRE_HOME>
+                                <!--<USE_GCC>1</USE_GCC>-->
+                                <!--<C_COMPILER>/opt/gcc-4.8.2/bin/gcc</C_COMPILER>-->
+                                <!--<CPP_COMPILER>/opt/gcc-4.8.2/bin/g++</CPP_COMPILER>-->
+                                <OUTPUT_DIR>${project.build.directory}</OUTPUT_DIR>
+                            </environmentVariables>
+                        </configuration>
+                    </execution>
+                </executions>
+            </plugin>
+
+            <!-- Don't actually install this artifact into the user's repo -->
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-install-plugin</artifactId>
+                <configuration>
+                    <skip>true</skip>
+                </configuration>
+            </plugin>
+
+            <!-- Copy the built library into gatk-utils -->
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-resources-plugin</artifactId>
+                <executions>
+                    <execution>
+                        <id>default-install</id>
+                        <goals>
+                            <goal>copy-resources</goal>
+                        </goals>
+                        <phase>install</phase>
+                        <configuration>
+                            <outputDirectory>${pairhmm.resources.directory}</outputDirectory>
+                            <resources>
+                                <resource>
+                                    <directory>${project.build.directory}</directory>
+                                    <includes>
+                                        <include>**/*</include>
+                                    </includes>
+                                </resource>
+                            </resources>
+                        </configuration>
+                    </execution>
+                </executions>
+            </plugin>
+
+            <!-- pom.xml cleanup, always sort according to the definitions in gatk-root -->
+            <plugin>
+                <groupId>com.google.code.sortpom</groupId>
+                <artifactId>maven-sortpom-plugin</artifactId>
+                <configuration>
+                    <createBackupFile>false</createBackupFile>
+                    <predefinedSortOrder>custom_1</predefinedSortOrder>
+                    <lineSeparator>\n</lineSeparator>
+                    <encoding>${sourceEncoding}</encoding>
+                    <keepBlankLines>true</keepBlankLines>
+                    <sortDependencies>scope</sortDependencies>
+                    <nrOfIndentSpace>4</nrOfIndentSpace>
+                    <expandEmptyElements>false</expandEmptyElements>
+                </configuration>
+            </plugin>
+        </plugins>
+    </build>
+</project>
diff --git a/public/VectorPairHMM/src/main/c++/.gitignore b/public/VectorPairHMM/src/main/c++/.gitignore
new file mode 100644
index 0000000..d791ffd
--- /dev/null
+++ b/public/VectorPairHMM/src/main/c++/.gitignore
@@ -0,0 +1,16 @@
+.svn
+*.o
+*.so
+tests
+.deps
+hmm_Mohammad
+pairhmm-template-main
+*.swp
+*.class
+checker
+reformat
+subdir_checkout.sh
+avx/
+sse/
+triplicate.sh
+
diff --git a/public/VectorPairHMM/src/main/c++/LoadTimeInitializer.cc b/public/VectorPairHMM/src/main/c++/LoadTimeInitializer.cc
new file mode 100644
index 0000000..f6cdbab
--- /dev/null
+++ b/public/VectorPairHMM/src/main/c++/LoadTimeInitializer.cc
@@ -0,0 +1,205 @@
+/*Copyright (c) 2012 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.
+*/
+
+
+#include "utils.h"
+#include "LoadTimeInitializer.h"
+using namespace std;
+char* LoadTimeInitializerStatsNames[] = 
+{
+  "num_regions",
+  "num_reads",
+  "num_haplotypes",
+  "num_testcases",
+  "num_double_invocations",
+  "haplotype_length",
+  "readlength",
+  "product_read_length_haplotype_length",
+  "dummy"
+};
+
+LoadTimeInitializer g_load_time_initializer;
+
+LoadTimeInitializer::LoadTimeInitializer()		//will be called when library is loaded
+{
+#if (defined(__GNUC__) || defined(__GNUG__)) && !defined(__INTEL_COMPILER)
+  //compiles only with gcc >= 4.8
+  __builtin_cpu_init();
+#endif
+  ConvertChar::init();
+#ifndef DISABLE_FTZ
+  //Very important to get good performance on Intel processors
+  //Function: enabling FTZ converts denormals to 0 in hardware
+  //Denormals cause microcode to insert uops into the core causing big slowdown
+  _MM_SET_FLUSH_ZERO_MODE(_MM_FLUSH_ZERO_ON);
+  //cout << "FTZ enabled - may decrease accuracy if denormal numbers encountered\n";
+#else
+  cout << "FTZ is not set - may slow down performance if denormal numbers encountered\n";
+#endif
+  //Profiling: times for compute and transfer (either bytes copied or pointers copied)
+  m_compute_time = 0;
+  m_data_transfer_time = 0;
+  m_bytes_copied = 0;
+
+  //Initialize profiling counters
+  for(unsigned i=0;i<TOTAL_NUMBER_STATS;++i)
+  {
+    m_sum_stats[i] = 0;
+    m_sum_square_stats[i] = 0;
+    m_max_stats[i] = 0;
+    m_min_stats[i] = 0xFFFFFFFFFFFFFFFFull;
+  }
+
+  //for debug dump
+  m_filename_to_fptr.clear();
+  m_written_files_set.clear();
+
+  initialize_function_pointers();
+
+  //Initialize static members of class
+  Context<float>::initializeStaticMembers();
+  Context<double>::initializeStaticMembers();
+
+  cout.flush();
+}
+
+void LoadTimeInitializer::print_profiling()
+{
+  double mean = 0;
+  double variance = 0;
+  uint64_t denominator = 1;
+  cout << "Time spent in compute_testcases "<<m_compute_time*1e-9<<"\n";
+  cout << "Time spent in data transfer (Java <--> C++) "<<m_data_transfer_time*1e-9<<"\n";
+
+  cout << "\nHC input stats\nstat_name,sum,sum_square,mean,variance,min,max\n";
+  for(unsigned i=0;i<TOTAL_NUMBER_STATS;++i)
+  {
+    cout << LoadTimeInitializerStatsNames[i];
+    cout << "," << m_sum_stats[i];
+    cout << "," << std::scientific << m_sum_square_stats[i];
+    denominator = 1;
+    switch(i)
+    {
+      case NUM_READS_IDX:
+      case NUM_HAPLOTYPES_IDX:
+      case NUM_TESTCASES_IDX:
+        denominator = m_sum_stats[NUM_REGIONS_IDX];
+        break;
+      case HAPLOTYPE_LENGTH_IDX:
+        denominator = m_sum_stats[NUM_HAPLOTYPES_IDX];
+        break;
+      case READ_LENGTH_IDX:
+        denominator = m_sum_stats[NUM_READS_IDX];
+        break;
+      case PRODUCT_READ_LENGTH_HAPLOTYPE_LENGTH_IDX:
+        denominator = m_sum_stats[NUM_TESTCASES_IDX];
+        break;
+      default:
+        denominator = 1;
+        break;
+    }
+    mean = ((double)m_sum_stats[i])/denominator;
+    cout << "," << std::scientific << mean;
+    variance = (m_sum_square_stats[i]/denominator) - (mean*mean);       //E(X^2)-(E(X))^2
+    cout << "," << std::scientific << variance;
+    cout << "," << m_min_stats[i];
+    cout << "," << m_max_stats[i];
+    cout << "\n";
+  }
+  cout << "\n";
+  cout.flush();
+}
+
+void LoadTimeInitializer::debug_dump(string filename, string s, bool to_append, bool add_newline)
+{
+  map<string, ofstream*>::iterator mI = m_filename_to_fptr.find(filename);
+  ofstream* fptr = 0;
+  if(mI == m_filename_to_fptr.end())
+  {
+    m_filename_to_fptr[filename] = new ofstream();
+    fptr = m_filename_to_fptr[filename];
+    //File never seen before
+    if(m_written_files_set.find(filename) == m_written_files_set.end())
+    {
+      to_append = false;
+      m_written_files_set.insert(filename);
+    }
+    fptr->open(filename.c_str(), to_append ? ios::app : ios::out);
+    assert(fptr->is_open());
+  }
+  else
+    fptr = (*mI).second;
+  //ofstream fptr;
+  //fptr.open(filename.c_str(), to_append ? ofstream::app : ofstream::out);
+  (*fptr) << s;
+  if(add_newline)
+    (*fptr) << "\n";
+  //fptr.close();
+}
+void LoadTimeInitializer::debug_close()
+{
+  for(map<string,ofstream*>::iterator mB = m_filename_to_fptr.begin(), mE = m_filename_to_fptr.end();
+      mB != mE;mB++)
+  {
+    (*mB).second->close();
+    delete (*mB).second;
+  }
+  m_filename_to_fptr.clear();
+}
+
+void LoadTimeInitializer::dump_sandbox(testcase& tc, unsigned tc_idx, unsigned numReads, unsigned numHaplotypes)
+{
+  unsigned haplotypeLength = tc.haplen;
+  unsigned readLength = tc.rslen;
+  ofstream& dumpFptr = m_sandbox_fptr;
+  for(unsigned k=0;k<haplotypeLength;++k)
+    dumpFptr<<(char)(tc.hap[k]);
+  dumpFptr<<" ";
+  for(unsigned k=0;k<readLength;++k)
+    dumpFptr<<(char)(tc.rs[k]);
+  dumpFptr<<" ";
+  for(unsigned k=0;k<readLength;++k)
+    dumpFptr<<(char)(tc.q[k]+33);
+  dumpFptr<<" ";
+  for(unsigned k=0;k<readLength;++k)
+    dumpFptr<<(char)(tc.i[k]+33);
+  dumpFptr<<" ";
+  for(unsigned k=0;k<readLength;++k)
+    dumpFptr<<(char)(tc.d[k]+33);
+  dumpFptr<<" ";
+  for(unsigned k=0;k<readLength;++k)
+    dumpFptr<<(char)(tc.c[k]+33);
+  if(tc_idx == 0)       //new region
+    dumpFptr << " "<< numReads << " "<<numHaplotypes; 
+  dumpFptr<<"\n";
+}
+
+void LoadTimeInitializer::update_stat(LoadTimeInitializerStatsEnum stat_idx, uint64_t value)
+{
+  m_sum_stats[stat_idx] += value;
+  double v = value;
+  m_sum_square_stats[stat_idx] += (v*v);
+  m_max_stats[stat_idx] = std::max(m_max_stats[stat_idx], value);
+  m_min_stats[stat_idx] = std::min(m_min_stats[stat_idx], value);
+}
diff --git a/public/VectorPairHMM/src/main/c++/LoadTimeInitializer.h b/public/VectorPairHMM/src/main/c++/LoadTimeInitializer.h
new file mode 100644
index 0000000..d8e9aee
--- /dev/null
+++ b/public/VectorPairHMM/src/main/c++/LoadTimeInitializer.h
@@ -0,0 +1,86 @@
+/*Copyright (c) 2012 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.
+*/
+
+
+#ifndef LOAD_TIME_INITIALIZER_H
+#define LOAD_TIME_INITIALIZER_H
+#include "headers.h"
+#include <jni.h>
+/*#include "template.h"*/
+
+enum LoadTimeInitializerStatsEnum
+{
+  NUM_REGIONS_IDX=0,
+  NUM_READS_IDX,
+  NUM_HAPLOTYPES_IDX,
+  NUM_TESTCASES_IDX,
+  NUM_DOUBLE_INVOCATIONS_IDX,
+  HAPLOTYPE_LENGTH_IDX,
+  READ_LENGTH_IDX,
+  PRODUCT_READ_LENGTH_HAPLOTYPE_LENGTH_IDX,
+  TOTAL_NUMBER_STATS
+};
+extern char* LoadTimeInitializerStatsNames[];
+
+class LoadTimeInitializer
+{
+  public:
+    LoadTimeInitializer();		//will be called when library is loaded
+    void print_profiling();
+    void debug_dump(std::string filename, std::string s, bool to_append, bool add_newline=true);
+    void debug_close();
+    
+    void dump_sandbox(testcase& tc, unsigned tc_idx, unsigned numReads, unsigned numHaplotypes);
+    void open_sandbox() { m_sandbox_fptr.open("sandbox.txt", std::ios::app); }
+    void close_sandbox() { m_sandbox_fptr.close(); }
+    
+    jfieldID m_readBasesFID;
+    jfieldID m_readQualsFID;
+    jfieldID m_insertionGOPFID;
+    jfieldID m_deletionGOPFID;
+    jfieldID m_overallGCPFID;
+    jfieldID m_haplotypeBasesFID;
+    //profiling - update stats
+    void update_stat(LoadTimeInitializerStatsEnum stat_idx, uint64_t value);
+    //timing in nanoseconds
+    uint64_t m_compute_time;
+    uint64_t m_data_transfer_time;
+    //bytes copied
+    uint64_t m_bytes_copied;
+  private:
+    std::map<std::string, std::ofstream*> m_filename_to_fptr;
+    std::set<std::string> m_written_files_set;
+    std::ofstream m_sandbox_fptr;
+    //used to compute various stats
+    uint64_t m_sum_stats[TOTAL_NUMBER_STATS];
+    double m_sum_square_stats[TOTAL_NUMBER_STATS];
+    uint64_t m_min_stats[TOTAL_NUMBER_STATS];
+    uint64_t m_max_stats[TOTAL_NUMBER_STATS];
+};
+extern LoadTimeInitializer g_load_time_initializer;
+
+#define SIZE_PER_TESTCASE 6*10000
+#define SIZE_PER_BUFFER 10000
+
+#endif
diff --git a/public/VectorPairHMM/src/main/c++/Makefile b/public/VectorPairHMM/src/main/c++/Makefile
new file mode 100644
index 0000000..0fae1e8
--- /dev/null
+++ b/public/VectorPairHMM/src/main/c++/Makefile
@@ -0,0 +1,126 @@
+#Copyright (c) 2012 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.
+#
+
+
+#OMPCFLAGS=-fopenmp
+#OMPLFLAGS=-fopenmp #-openmp-link static
+
+#CFLAGS=-O2 -std=c++11 -W -Wall -march=corei7-avx -Wa,-q            -pedantic $(OMPCFLAGS) -Wno-unknown-pragmas
+#CFLAGS=-O2             -W -Wall -march=corei7 -mfpmath=sse -msse4.2 -pedantic $(OMPCFLAGS) -Wno-unknown-pragmas
+
+JRE_HOME?=/opt/jdk1.7.0_25/jre
+JNI_COMPILATION_FLAGS=-D_REENTRANT -fPIC -I${JRE_HOME}/../include -I${JRE_HOME}/../include/linux
+
+#COMMON_COMPILATION_FLAGS=$(JNI_COMPILATION_FLAGS) -O3 -W -Wall -pedantic $(OMPCFLAGS) -Wno-unknown-pragmas
+COMMON_COMPILATION_FLAGS=$(JNI_COMPILATION_FLAGS) -O3 -Wall $(OMPCFLAGS) -Wno-unknown-pragmas -Wno-write-strings -Wno-unused-variable -Wno-unused-but-set-variable
+ifdef DISABLE_FTZ
+  COMMON_COMPILATION_FLAGS+=-DDISABLE_FTZ
+endif
+
+ifdef USE_GCC
+  C_COMPILER?=gcc
+  CPP_COMPILER?=g++
+  AVX_FLAGS=-mavx
+  SSE41_FLAGS=-msse4.1
+  COMMON_COMPILATION_FLAGS+=-Wno-char-subscripts
+else
+  C_COMPILER?=icc
+  CPP_COMPILER?=icc
+  AVX_FLAGS=-xAVX
+  SSE41_FLAGS=-xSSE4.1
+  LIBFLAGS=-static-intel
+  ifdef DISABLE_FTZ
+    COMMON_COMPILATION_FLAGS+=-no-ftz
+  endif
+endif
+
+LDFLAGS=-lm -lrt $(OMPLDFLAGS)
+
+PAPI_DIR=/home/karthikg/softwares/papi-5.3.0
+ifdef USE_PAPI
+  ifeq ($(USE_PAPI),1)
+    COMMON_COMPILATION_FLAGS+=-I$(PAPI_DIR)/include -DUSE_PAPI
+    LDFLAGS+=-L$(PAPI_DIR)/lib -lpapi
+  endif
+endif
+
+BIN=libVectorLoglessPairHMM.so pairhmm-template-main checker
+#BIN=checker
+
+DEPDIR=.deps
+DF=$(DEPDIR)/$(*).d
+
+#Common across libJNI and sandbox
+COMMON_SOURCES=utils.cc avx_function_instantiations.cc baseline.cc sse_function_instantiations.cc LoadTimeInitializer.cc
+#Part of libJNI
+LIBSOURCES=org_broadinstitute_gatk_utils_pairhmm_VectorLoglessPairHMM.cc org_broadinstitute_gatk_utils_pairhmm_DebugJNILoglessPairHMM.cc Sandbox.cc $(COMMON_SOURCES)
+SOURCES=$(LIBSOURCES) pairhmm-template-main.cc pairhmm-1-base.cc
+LIBOBJECTS=$(LIBSOURCES:.cc=.o)
+COMMON_OBJECTS=$(COMMON_SOURCES:.cc=.o)
+
+
+#No vectorization for these files
+NO_VECTOR_SOURCES=org_broadinstitute_gatk_utils_pairhmm_VectorLoglessPairHMM.cc org_broadinstitute_gatk_utils_pairhmm_DebugJNILoglessPairHMM.cc pairhmm-template-main.cc pairhmm-1-base.cc utils.cc baseline.cc LoadTimeInitializer.cc Sandbox.cc
+#Use -xAVX for these files
+AVX_SOURCES=avx_function_instantiations.cc
+#Use -xSSE4.2 for these files
+SSE_SOURCES=sse_function_instantiations.cc
+
+NO_VECTOR_OBJECTS=$(NO_VECTOR_SOURCES:.cc=.o)
+AVX_OBJECTS=$(AVX_SOURCES:.cc=.o)
+SSE_OBJECTS=$(SSE_SOURCES:.cc=.o)
+$(NO_VECTOR_OBJECTS): CXXFLAGS=$(COMMON_COMPILATION_FLAGS)
+$(AVX_OBJECTS): CXXFLAGS=$(COMMON_COMPILATION_FLAGS) $(AVX_FLAGS)
+$(SSE_OBJECTS): CXXFLAGS=$(COMMON_COMPILATION_FLAGS) $(SSE41_FLAGS)
+OBJECTS=$(NO_VECTOR_OBJECTS) $(AVX_OBJECTS) $(SSE_OBJECTS)
+
+all: $(BIN) Sandbox.class copied_lib
+
+-include $(addprefix $(DEPDIR)/,$(SOURCES:.cc=.d))
+
+checker: pairhmm-1-base.o $(COMMON_OBJECTS)
+	$(CPP_COMPILER) $(OMPLFLAGS) -o $@ $^ $(LDFLAGS)
+
+pairhmm-template-main:	pairhmm-template-main.o $(COMMON_OBJECTS)
+	$(CPP_COMPILER) $(OMPLFLAGS) -o $@ $^ $(LDFLAGS)
+
+libVectorLoglessPairHMM.so: $(LIBOBJECTS) 
+	$(CPP_COMPILER) $(OMPLFLAGS) -shared $(LIBFLAGS) -o $@ $(LIBOBJECTS) ${LDFLAGS}
+
+
+$(OBJECTS): %.o: %.cc
+	@mkdir -p $(DEPDIR)
+	$(CPP_COMPILER) -c -MMD -MF $(DF) $(CXXFLAGS) $(OUTPUT_OPTION) $<
+
+Sandbox.class: Sandbox.java
+	javac Sandbox.java
+
+copied_lib: libVectorLoglessPairHMM.so
+ifdef OUTPUT_DIR
+	mkdir -p $(OUTPUT_DIR)
+	rsync -a libVectorLoglessPairHMM.so $(OUTPUT_DIR)/
+endif
+
+clean:
+	rm -rf $(BIN) *.o $(DEPDIR) *.class
diff --git a/public/VectorPairHMM/src/main/c++/Sandbox.cc b/public/VectorPairHMM/src/main/c++/Sandbox.cc
new file mode 100644
index 0000000..a4c2b73
--- /dev/null
+++ b/public/VectorPairHMM/src/main/c++/Sandbox.cc
@@ -0,0 +1,106 @@
+/*Copyright (c) 2012 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.
+*/
+
+
+#include "Sandbox.h"
+#include "org_broadinstitute_gatk_utils_pairhmm_VectorLoglessPairHMM.h"
+#include "utils.h"
+#include "jni_common.h"
+/*
+ * Class:     Sandbox
+ * Method:    jniGetMachineType
+ * Signature: ()J
+ */
+JNIEXPORT jlong JNICALL Java_Sandbox_jniGetMachineType
+  (JNIEnv * env, jobject thisObj)
+{
+  return 0;
+}
+
+/*
+ * Class:     Sandbox
+ * Method:    jniInitializeClassFieldsAndMachineMask
+ * Signature: (Ljava/lang/Class;Ljava/lang/Class;J)V
+ */
+JNIEXPORT void JNICALL Java_Sandbox_jniInitializeClassFieldsAndMachineMask
+  (JNIEnv* env, jobject thisObject, jclass readDataHolderClass, jclass haplotypeDataHolderClass, jlong mask)
+{
+  Java_org_broadinstitute_gatk_utils_pairhmm_VectorLoglessPairHMM_jniInitializeClassFieldsAndMachineMask(env, thisObject, readDataHolderClass,
+      haplotypeDataHolderClass, mask);
+}
+
+/*
+ * Class:     Sandbox
+ * Method:    jniInitializeHaplotypes
+ * Signature: (I[LSandbox/JNIHaplotypeDataHolderClass;)V
+ */
+JNIEXPORT void JNICALL Java_Sandbox_jniInitializeHaplotypes
+  (JNIEnv * env, jobject thisObject, jint numHaplotypes, jobjectArray haplotypeDataArray)
+{
+  Java_org_broadinstitute_gatk_utils_pairhmm_VectorLoglessPairHMM_jniInitializeHaplotypes(env, thisObject, numHaplotypes, haplotypeDataArray);
+}
+
+/*
+ * Class:     Sandbox
+ * Method:    jniFinalizeRegion
+ * Signature: ()V
+ */
+JNIEXPORT void JNICALL Java_Sandbox_jniFinalizeRegion
+  (JNIEnv * env, jobject thisObject)
+{
+  Java_org_broadinstitute_gatk_utils_pairhmm_VectorLoglessPairHMM_jniFinalizeRegion(env, thisObject);
+}
+
+
+/*
+ * Class:     Sandbox
+ * Method:    jniComputeLikelihoods
+ * Signature: (II[LSandbox/JNIReadDataHolderClass;[LSandbox/JNIHaplotypeDataHolderClass;[DI)V
+ */
+JNIEXPORT void JNICALL Java_Sandbox_jniComputeLikelihoods
+  (JNIEnv* env, jobject thisObject, jint numReads, jint numHaplotypes, 
+   jobjectArray readDataArray, jobjectArray haplotypeDataArray, jdoubleArray likelihoodArray, jint maxNumThreadsToUse)
+{
+  Java_org_broadinstitute_gatk_utils_pairhmm_VectorLoglessPairHMM_jniComputeLikelihoods(env, thisObject,
+      numReads, numHaplotypes, readDataArray, haplotypeDataArray, likelihoodArray, maxNumThreadsToUse);
+}
+/*
+ * Class:     Sandbox
+ * Method:    jniClose
+ * Signature: ()V
+ */
+JNIEXPORT void JNICALL Java_Sandbox_jniClose
+  (JNIEnv* env, jobject thisObject)
+{ Java_org_broadinstitute_gatk_utils_pairhmm_VectorLoglessPairHMM_jniClose(env, thisObject); } 
+
+JNIEXPORT void JNICALL Java_Sandbox_doEverythingNative
+  (JNIEnv* env, jobject thisObject, jstring fileNameString)
+{
+  const char* fileName = env->GetStringUTFChars(fileNameString, 0);
+  char local_array[800];
+  strncpy(local_array, fileName, 200);
+  env->ReleaseStringUTFChars(fileNameString, fileName);
+  do_compute(local_array, true, 10000, false);
+}
+
diff --git a/public/VectorPairHMM/src/main/c++/Sandbox.h b/public/VectorPairHMM/src/main/c++/Sandbox.h
new file mode 100644
index 0000000..486a1c0
--- /dev/null
+++ b/public/VectorPairHMM/src/main/c++/Sandbox.h
@@ -0,0 +1,96 @@
+/*Copyright (c) 2012 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.
+*/
+
+
+/* DO NOT EDIT THIS FILE - it is machine generated */
+#include <jni.h>
+/* Header for class Sandbox */
+
+#ifndef _Included_Sandbox
+#define _Included_Sandbox
+#ifdef __cplusplus
+extern "C" {
+#endif
+#undef Sandbox_enableAll
+#define Sandbox_enableAll -1LL
+/*
+ * Class:     Sandbox
+ * Method:    jniGetMachineType
+ * Signature: ()J
+ */
+JNIEXPORT jlong JNICALL Java_Sandbox_jniGetMachineType
+  (JNIEnv *, jobject);
+
+/*
+ * Class:     Sandbox
+ * Method:    jniInitializeClassFieldsAndMachineMask
+ * Signature: (Ljava/lang/Class;Ljava/lang/Class;J)V
+ */
+JNIEXPORT void JNICALL Java_Sandbox_jniInitializeClassFieldsAndMachineMask
+  (JNIEnv *, jobject, jclass, jclass, jlong);
+
+/*
+ * Class:     Sandbox
+ * Method:    jniInitializeHaplotypes
+ * Signature: (I[LSandbox/JNIHaplotypeDataHolderClass;)V
+ */
+JNIEXPORT void JNICALL Java_Sandbox_jniInitializeHaplotypes
+  (JNIEnv *, jobject, jint, jobjectArray);
+
+/*
+ * Class:     Sandbox
+ * Method:    jniFinalizeRegion
+ * Signature: ()V
+ */
+JNIEXPORT void JNICALL Java_Sandbox_jniFinalizeRegion
+  (JNIEnv *, jobject);
+
+/*
+ * Class:     Sandbox
+ * Method:    jniComputeLikelihoods
+ * Signature: (II[LSandbox/JNIReadDataHolderClass;[LSandbox/JNIHaplotypeDataHolderClass;[DI)V
+ */
+JNIEXPORT void JNICALL Java_Sandbox_jniComputeLikelihoods
+  (JNIEnv *, jobject, jint, jint, jobjectArray, jobjectArray, jdoubleArray, jint);
+
+/*
+ * Class:     Sandbox
+ * Method:    jniClose
+ * Signature: ()V
+ */
+JNIEXPORT void JNICALL Java_Sandbox_jniClose
+  (JNIEnv *, jobject);
+
+/*
+ * Class:     Sandbox
+ * Method:    doEverythingNative
+ * Signature: ([B)V
+ */
+JNIEXPORT void JNICALL Java_Sandbox_doEverythingNative
+  (JNIEnv *, jobject, jstring);
+
+#ifdef __cplusplus
+}
+#endif
+#endif
diff --git a/public/VectorPairHMM/src/main/c++/Sandbox.java b/public/VectorPairHMM/src/main/c++/Sandbox.java
new file mode 100644
index 0000000..605c5f5
--- /dev/null
+++ b/public/VectorPairHMM/src/main/c++/Sandbox.java
@@ -0,0 +1,306 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.utils.vectorpairhmm;
+
+import java.util.List;
+import java.util.LinkedList;
+import java.util.Map;
+import java.util.HashMap;
+import java.io.File;
+import java.util.Scanner;
+import java.io.IOException;
+import java.io.FileNotFoundException;
+import java.io.InputStreamReader;
+
+public class Sandbox {
+
+    private long setupTime = 0;
+    private long computeTime = 0;
+    //Used to copy references to byteArrays to JNI from reads
+    protected class JNIReadDataHolderClass {
+        public byte[] readBases = null;
+        public byte[] readQuals = null;
+        public byte[] insertionGOP = null;
+        public byte[] deletionGOP = null;
+        public byte[] overallGCP = null;
+    }
+
+    //Used to copy references to byteArrays to JNI from haplotypes
+    protected class JNIHaplotypeDataHolderClass {
+        public byte[] haplotypeBases = null;
+    }
+
+    /**
+     * Return 64-bit mask representing machine capabilities
+     * Bit 0 is LSB, bit 63 MSB
+     * Bit 0 represents sse4.2 availability
+     * Bit 1 represents AVX availability
+     */
+    public native long jniGetMachineType();
+    public static final long enableAll = 0xFFFFFFFFFFFFFFFFl;
+
+    
+    /**
+     * Function to initialize the fields of JNIReadDataHolderClass and JNIHaplotypeDataHolderClass from JVM.
+     * C++ codegets FieldIDs for these classes once and re-uses these IDs for the remainder of the program. Field IDs do not
+     * change per JVM session
+     * @param readDataHolderClass class type of JNIReadDataHolderClass
+     * @param haplotypeDataHolderClass class type of JNIHaplotypeDataHolderClass
+     * @param mask mask is a 64 bit integer identical to the one received from jniGetMachineType(). Users can disable usage of some hardware features by zeroing some bits in the mask
+     * */
+    private native void jniInitializeClassFieldsAndMachineMask(Class<?> readDataHolderClass, Class<?> haplotypeDataHolderClass, long mask);
+
+    private static Boolean isVectorLoglessPairHMMLibraryLoaded = false;
+    //The constructor is called only once inside PairHMMLikelihoodCalculationEngine
+    public Sandbox() {
+        synchronized(isVectorLoglessPairHMMLibraryLoaded) {
+            //Load the library and initialize the FieldIDs
+            if(!isVectorLoglessPairHMMLibraryLoaded) {
+                System.loadLibrary("VectorLoglessPairHMM");
+                isVectorLoglessPairHMMLibraryLoaded = true;
+                jniInitializeClassFieldsAndMachineMask(JNIReadDataHolderClass.class, JNIHaplotypeDataHolderClass.class, enableAll);        //need to do this only once
+            }
+        }
+    }
+
+    private native void jniInitializeHaplotypes(final int numHaplotypes,  JNIHaplotypeDataHolderClass[] haplotypeDataArray);
+    private JNIHaplotypeDataHolderClass[] mHaplotypeDataArray = null;
+    
+    //Used to transfer data to JNI
+    //Since the haplotypes are the same for all calls to computeLikelihoods within a region, transfer the haplotypes only once to the JNI per region
+    public void initialize(final List<JNIHaplotypeDataHolderClass> haplotypes) {
+        int numHaplotypes = haplotypes.size();
+        mHaplotypeDataArray = new JNIHaplotypeDataHolderClass[numHaplotypes];
+        int idx = 0;
+        for(final JNIHaplotypeDataHolderClass currHaplotype : haplotypes)
+        {
+            mHaplotypeDataArray[idx] = new JNIHaplotypeDataHolderClass();
+            mHaplotypeDataArray[idx].haplotypeBases = currHaplotype.haplotypeBases;
+            ++idx;
+        }
+        jniInitializeHaplotypes(numHaplotypes, mHaplotypeDataArray);
+    }
+    /**
+     * Tell JNI to release arrays - really important if native code is directly accessing Java memory, if not
+     * accessing Java memory directly, still important to release memory from C++
+     */
+    private native void jniFinalizeRegion();
+
+    
+    public void finalizeRegion()
+    {
+        jniFinalizeRegion();
+    }
+
+    /**
+     * Real compute kernel
+     */
+    private native void jniComputeLikelihoods(int numReads, int numHaplotypes, JNIReadDataHolderClass[] readDataArray,
+            JNIHaplotypeDataHolderClass[] haplotypeDataArray, double[] likelihoodArray, int maxNumThreadsToUse);
+    
+    public void computeLikelihoods(final List<JNIReadDataHolderClass> reads, final List<JNIHaplotypeDataHolderClass> haplotypes) {
+      //System.out.println("Region : "+reads.size()+" x "+haplotypes.size());
+      long startTime = System.nanoTime();
+      int readListSize = reads.size();
+      int numHaplotypes = haplotypes.size();
+      int numTestcases = readListSize*numHaplotypes;
+      JNIReadDataHolderClass[] readDataArray = new JNIReadDataHolderClass[readListSize];
+      int idx = 0;
+      for(JNIReadDataHolderClass read : reads)
+      {
+        readDataArray[idx] = new JNIReadDataHolderClass();
+        readDataArray[idx].readBases    = read.readBases; 
+        readDataArray[idx].readQuals    = read.readQuals;
+        readDataArray[idx].insertionGOP = read.insertionGOP;
+        readDataArray[idx].deletionGOP  = read.deletionGOP;
+        readDataArray[idx].overallGCP   = read.overallGCP;
+        ++idx;
+      }
+
+      double[] mLikelihoodArray = new double[readListSize*numHaplotypes];      //to store results
+      setupTime += (System.nanoTime() - startTime);
+      //for(reads)
+      //   for(haplotypes)
+      //       compute_full_prob()
+      jniComputeLikelihoods(readListSize, numHaplotypes, readDataArray, mHaplotypeDataArray, mLikelihoodArray, 12);
+
+      computeTime += (System.nanoTime() - startTime);
+    }
+    
+    /**
+     * Print final profiling information from native code
+     */
+    public native void jniClose();
+    public void close()
+    {
+        System.out.println("Time spent in setup for JNI call : "+(setupTime*1e-9)+" compute time : "+(computeTime*1e-9));
+        jniClose();
+    }
+
+    public void parseSandboxFile(String filename)
+    {
+      File file = new File(filename);
+      Scanner input = null;
+      try
+      {
+        input = new Scanner(file); 
+      }
+      catch(FileNotFoundException e)
+      {
+        System.err.println("File "+filename+" cannot be found/read");
+        return;
+      }
+      int idx = 0;
+      int numReads = 0;
+      int numHaplotypes = 0;
+      int readIdx = 0, testCaseIdx = 0, haplotypeIdx = 0;
+      LinkedList<JNIHaplotypeDataHolderClass> haplotypeList = new LinkedList<JNIHaplotypeDataHolderClass>();
+      LinkedList<JNIReadDataHolderClass> readList = new LinkedList<JNIReadDataHolderClass>();
+      
+      byte[][] byteArray = new byte[6][];
+      boolean firstLine = true;
+      String[] currTokens = new String[8];
+      while(input.hasNextLine())
+      {
+        String line = input.nextLine();
+        Scanner lineScanner = new Scanner(line);
+        idx = 0;
+        while(lineScanner.hasNext())
+          currTokens[idx++] = lineScanner.next();
+        if(idx == 0)
+          break;
+        assert(idx >= 6);
+        //start of new region
+        if(idx == 8)
+        {
+          if(!firstLine)
+          {
+            initialize(haplotypeList);
+            computeLikelihoods(readList, haplotypeList);
+            finalizeRegion();
+          }
+          try
+          {
+            numReads = Integer.parseInt(currTokens[6]);
+          }
+          catch(NumberFormatException e)
+          {
+            numReads = 1;
+          }
+          try
+          {
+            numHaplotypes = Integer.parseInt(currTokens[7]);
+          }
+          catch(NumberFormatException e)
+          {
+            numHaplotypes = 1;
+          }
+          haplotypeIdx = readIdx = testCaseIdx = 0;
+          readList.clear();
+          haplotypeList.clear();
+        }
+        if(haplotypeIdx < numHaplotypes)
+        {
+          JNIHaplotypeDataHolderClass X = new JNIHaplotypeDataHolderClass();
+          X.haplotypeBases = currTokens[0].getBytes();
+          haplotypeList.add(X);
+        }
+        if(testCaseIdx%numHaplotypes == 0)
+        {
+          JNIReadDataHolderClass X = new JNIReadDataHolderClass();
+          X.readBases = currTokens[1].getBytes();
+          for(int i=2;i<6;++i)
+          {
+            byteArray[i] = currTokens[i].getBytes();
+            for(int j=0;j<byteArray[i].length;++j)
+              byteArray[i][j] -= 33;       //normalize
+          }
+          X.readQuals = byteArray[2];
+          X.insertionGOP = byteArray[3];
+          X.deletionGOP = byteArray[4];
+          X.overallGCP = byteArray[5];
+          readList.add(X);
+        }
+        ++testCaseIdx;
+        ++haplotypeIdx;
+
+        lineScanner.close();
+        firstLine = false;
+      }
+      if(haplotypeList.size() > 0 && readList.size() > 0)
+      {
+        initialize(haplotypeList);
+        computeLikelihoods(readList, haplotypeList);
+        finalizeRegion();
+      }
+
+      close();
+      input.close();
+    }
+
+    private native void doEverythingNative(String filename);
+
+    public static void main(String[] args)
+    {
+      if(args.length <= 0)
+      {
+        System.err.println("Needs 1 argument - <filename>");
+        System.exit(-1);
+      }
+      //// Get runtime
+      //java.lang.Runtime rt = java.lang.Runtime.getRuntime();
+      //// Start a new process: UNIX command ls
+      //String cmd = "/home/karthikg/broad/gsa-unstable/public/c++/VectorPairHMM/checker "+args[0];
+      //try
+      //{
+        //System.out.println(cmd);
+        //java.lang.Process p = rt.exec(cmd);
+        //try
+        //{
+          //p.waitFor();
+          //java.io.InputStream is = p.getInputStream();
+          //java.io.BufferedReader reader = new java.io.BufferedReader(new InputStreamReader(is));
+          //// And print each line
+          //String s = null;
+          //while ((s = reader.readLine()) != null) {
+            //System.out.println(s);
+          //}
+          //is.close();
+        //}
+        //catch(InterruptedException e)
+        //{
+          //System.err.println(e);
+        //}
+      //}
+      //catch(IOException e)
+      //{
+        //System.err.println(e);
+      //}
+      Sandbox t = new Sandbox();
+      //t.doEverythingNative(args[0]);
+      t.parseSandboxFile(args[0]);
+    }
+}
diff --git a/public/VectorPairHMM/src/main/c++/Sandbox_JNIHaplotypeDataHolderClass.h b/public/VectorPairHMM/src/main/c++/Sandbox_JNIHaplotypeDataHolderClass.h
new file mode 100644
index 0000000..7f78f01
--- /dev/null
+++ b/public/VectorPairHMM/src/main/c++/Sandbox_JNIHaplotypeDataHolderClass.h
@@ -0,0 +1,13 @@
+/* DO NOT EDIT THIS FILE - it is machine generated */
+#include <jni.h>
+/* Header for class Sandbox_JNIHaplotypeDataHolderClass */
+
+#ifndef _Included_Sandbox_JNIHaplotypeDataHolderClass
+#define _Included_Sandbox_JNIHaplotypeDataHolderClass
+#ifdef __cplusplus
+extern "C" {
+#endif
+#ifdef __cplusplus
+}
+#endif
+#endif
diff --git a/public/VectorPairHMM/src/main/c++/Sandbox_JNIReadDataHolderClass.h b/public/VectorPairHMM/src/main/c++/Sandbox_JNIReadDataHolderClass.h
new file mode 100644
index 0000000..a9312ff
--- /dev/null
+++ b/public/VectorPairHMM/src/main/c++/Sandbox_JNIReadDataHolderClass.h
@@ -0,0 +1,13 @@
+/* DO NOT EDIT THIS FILE - it is machine generated */
+#include <jni.h>
+/* Header for class Sandbox_JNIReadDataHolderClass */
+
+#ifndef _Included_Sandbox_JNIReadDataHolderClass
+#define _Included_Sandbox_JNIReadDataHolderClass
+#ifdef __cplusplus
+extern "C" {
+#endif
+#ifdef __cplusplus
+}
+#endif
+#endif
diff --git a/public/VectorPairHMM/src/main/c++/avx_function_instantiations.cc b/public/VectorPairHMM/src/main/c++/avx_function_instantiations.cc
new file mode 100644
index 0000000..1a6b593
--- /dev/null
+++ b/public/VectorPairHMM/src/main/c++/avx_function_instantiations.cc
@@ -0,0 +1,45 @@
+/*Copyright (c) 2012 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.
+*/
+
+
+
+#undef SIMD_ENGINE
+#undef SIMD_ENGINE_SSE
+
+#define SIMD_ENGINE avx
+#define SIMD_ENGINE_AVX
+
+#include "template.h"
+
+#include "define-float.h"
+#include "shift_template.c"
+#include "pairhmm-template-kernel.cc"
+
+#include "define-double.h"
+#include "shift_template.c"
+#include "pairhmm-template-kernel.cc"
+
+template double compute_full_prob_avxd<double>(testcase* tc, double* nextlog);
+template float compute_full_prob_avxs<float>(testcase* tc, float* nextlog);
+
diff --git a/public/VectorPairHMM/src/main/c++/baseline.cc b/public/VectorPairHMM/src/main/c++/baseline.cc
new file mode 100644
index 0000000..17d2c27
--- /dev/null
+++ b/public/VectorPairHMM/src/main/c++/baseline.cc
@@ -0,0 +1,157 @@
+/*Copyright (c) 2012 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.
+*/
+
+
+#include "headers.h"
+#include "common_data_structure.h"
+#include "utils.h"
+#include "LoadTimeInitializer.h"
+using namespace std;
+
+template<class NUMBER>
+NUMBER compute_full_prob(testcase *tc, NUMBER *before_last_log)
+{
+  int r, c;
+  int ROWS = tc->rslen + 1;
+  int COLS = tc->haplen + 1;
+
+  Context<NUMBER> ctx;
+  //#define USE_STACK_ALLOCATION 1
+#ifdef USE_STACK_ALLOCATION
+  NUMBER M[ROWS][COLS];
+  NUMBER X[ROWS][COLS];
+  NUMBER Y[ROWS][COLS];
+  NUMBER p[ROWS][6];
+#else
+  //allocate on heap in way that simulates a 2D array. Having a 2D array instead of
+  //a straightforward array of pointers ensures that all data lies 'close' in memory, increasing
+  //the chance of being stored together in the cache. Also, prefetchers can learn memory access
+  //patterns for 2D arrays, not possible for array of pointers
+  //NUMBER* common_buffer = 0;
+  NUMBER* common_buffer = new NUMBER[3*ROWS*COLS + ROWS*6];
+  //pointers to within the allocated buffer
+  NUMBER** common_pointer_buffer = new NUMBER*[4*ROWS];
+  NUMBER* ptr = common_buffer;
+  unsigned i = 0;
+  for(i=0;i<3*ROWS;++i, ptr+=COLS)
+    common_pointer_buffer[i] = ptr;
+  for(;i<4*ROWS;++i, ptr+=6)
+    common_pointer_buffer[i] = ptr;
+
+  NUMBER** M = common_pointer_buffer;
+  NUMBER** X = M + ROWS;
+  NUMBER** Y = X + ROWS;
+  NUMBER** p = Y + ROWS;
+#endif
+
+
+  p[0][MM] = ctx._(0.0);
+  p[0][GapM] = ctx._(0.0);
+  p[0][MX] = ctx._(0.0);
+  p[0][XX] = ctx._(0.0);
+  p[0][MY] = ctx._(0.0);
+  p[0][YY] = ctx._(0.0);
+
+  for (r = 1; r < ROWS; r++)
+  {
+    int _i = tc->i[r-1] & 127;
+    int _d = tc->d[r-1] & 127;
+    int _c = tc->c[r-1] & 127;
+    //p[r][MM] = ctx._(1.0) - ctx.ph2pr[(_i + _d) & 127];
+    SET_MATCH_TO_MATCH_PROB(p[r][MM], _i, _d);
+    p[r][GapM] = ctx._(1.0) - ctx.ph2pr[_c];
+    p[r][MX] = ctx.ph2pr[_i];
+    p[r][XX] = ctx.ph2pr[_c];
+    p[r][MY] = ctx.ph2pr[_d];
+    p[r][YY] = ctx.ph2pr[_c];
+    //p[r][MY] = (r == ROWS - 1) ? ctx._(1.0) : ctx.ph2pr[_d];
+    //p[r][YY] = (r == ROWS - 1) ? ctx._(1.0) : ctx.ph2pr[_c];
+  }
+  for (c = 0; c < COLS; c++)
+  {
+    M[0][c] = ctx._(0.0);
+    X[0][c] = ctx._(0.0);
+    Y[0][c] = ctx.INITIAL_CONSTANT / (tc->haplen);
+  }
+
+  for (r = 1; r < ROWS; r++)
+  {
+    M[r][0] = ctx._(0.0);
+    X[r][0] = X[r-1][0] * p[r][XX];
+    Y[r][0] = ctx._(0.0);
+  }
+
+  NUMBER result = ctx._(0.0);
+
+  for (r = 1; r < ROWS; r++)
+    for (c = 1; c < COLS; c++)
+    {
+      fexcept_t flagp;
+      char _rs = tc->rs[r-1];
+      char _hap = tc->hap[c-1];
+      int _q = tc->q[r-1] & 127;
+      NUMBER distm = ctx.ph2pr[_q];
+      if (_rs == _hap || _rs == 'N' || _hap == 'N')
+        distm = ctx._(1.0) - distm;
+      else
+        distm = distm/3;
+
+
+      //feclearexcept(FE_ALL_EXCEPT);
+      M[r][c] = distm * (M[r-1][c-1] * p[r][MM] + X[r-1][c-1] * p[r][GapM] + Y[r-1][c-1] * p[r][GapM]);
+      //STORE_FP_EXCEPTIONS(flagp, exceptions_array);
+
+      //feclearexcept(FE_ALL_EXCEPT);
+      X[r][c] = M[r-1][c] * p[r][MX] + X[r-1][c] * p[r][XX];
+      //STORE_FP_EXCEPTIONS(flagp, exceptions_array);
+
+      //feclearexcept(FE_ALL_EXCEPT);
+      Y[r][c] = M[r][c-1] * p[r][MY] + Y[r][c-1] * p[r][YY];
+      //STORE_FP_EXCEPTIONS(flagp, exceptions_array);
+
+      //CONVERT_AND_PRINT(M[r][c]);
+      //CONVERT_AND_PRINT(X[r][c]);
+      //CONVERT_AND_PRINT(Y[r][c]);
+
+    }
+  for (c = 0; c < COLS; c++)
+  {
+    result += M[ROWS-1][c] + X[ROWS-1][c];
+  }
+
+  if (before_last_log != NULL)
+    *before_last_log = result;
+
+#ifndef USE_STACK_ALLOCATION
+  delete[] common_pointer_buffer;
+  delete[] common_buffer;
+#endif
+
+  return result;
+  //return ctx.LOG10(result) - ctx.LOG10_INITIAL_CONSTANT;
+}
+
+template double compute_full_prob<double>(testcase* tc, double* nextbuf);
+template float compute_full_prob<float>(testcase* tc, float* nextbuf);
+
diff --git a/public/VectorPairHMM/src/main/c++/common_data_structure.h b/public/VectorPairHMM/src/main/c++/common_data_structure.h
new file mode 100644
index 0000000..4b5f034
--- /dev/null
+++ b/public/VectorPairHMM/src/main/c++/common_data_structure.h
@@ -0,0 +1,215 @@
+#ifndef COMMON_DATA_STRUCTURE_H
+#define COMMON_DATA_STRUCTURE_H
+
+#include "headers.h"
+
+#define CAT(X,Y) X####Y
+#define CONCAT(X,Y) CAT(X,Y)
+
+#define MM 0
+#define GapM 1
+#define MX 2
+#define XX 3
+#define MY 4
+#define YY 5
+
+//#define MROWS  500
+//#define MCOLS  1000
+
+
+#define MAX_QUAL 254
+#define MAX_JACOBIAN_TOLERANCE 8.0
+#define JACOBIAN_LOG_TABLE_STEP 0.0001
+#define JACOBIAN_LOG_TABLE_INV_STEP (1.0 / JACOBIAN_LOG_TABLE_STEP)
+#define MAXN 70000
+#define LOG10_CACHE_SIZE  (4*MAXN)  // we need to be able to go up to 2*(2N) when calculating some of the coefficients
+#define JACOBIAN_LOG_TABLE_SIZE ((int) (MAX_JACOBIAN_TOLERANCE / JACOBIAN_LOG_TABLE_STEP) + 1)
+
+template<class NUMBER>
+struct ContextBase
+{
+  public:
+    NUMBER ph2pr[128];
+    NUMBER INITIAL_CONSTANT;
+    NUMBER LOG10_INITIAL_CONSTANT;
+    NUMBER RESULT_THRESHOLD; 
+
+    static bool staticMembersInitializedFlag;
+    static NUMBER jacobianLogTable[JACOBIAN_LOG_TABLE_SIZE];
+    static NUMBER matchToMatchProb[((MAX_QUAL + 1) * (MAX_QUAL + 2)) >> 1];
+
+    static void initializeStaticMembers()
+    {
+      if(!staticMembersInitializedFlag)
+      {
+        //Order of calls important - Jacobian first, then MatchToMatch
+        initializeJacobianLogTable();
+        initializeMatchToMatchProb();
+        staticMembersInitializedFlag = true;
+      }
+    }
+
+    static void deleteStaticMembers()
+    {
+      if(staticMembersInitializedFlag)
+      {
+        staticMembersInitializedFlag = false;
+      }
+    }
+
+    //Called only once during library load - don't bother to optimize with single precision fp
+    static void initializeJacobianLogTable()
+    {
+      for (int k = 0; k < JACOBIAN_LOG_TABLE_SIZE; k++) {
+        jacobianLogTable[k] = (NUMBER)(log10(1.0 + pow(10.0, -((double) k) * JACOBIAN_LOG_TABLE_STEP)));
+      }
+    }
+
+    //Called only once per library load - don't bother optimizing with single fp
+    static void initializeMatchToMatchProb()
+    {
+      double LN10 = log(10);
+      double INV_LN10 = 1.0/LN10;
+      for (int i = 0, offset = 0; i <= MAX_QUAL; offset += ++i)
+        for (int j = 0; j <= i; j++) {
+          double log10Sum = approximateLog10SumLog10(-0.1*i, -0.1*j);
+          double matchToMatchLog10 =
+            log1p(-std::min(1.0,pow(10,log10Sum))) * INV_LN10;
+          matchToMatchProb[offset + j] = (NUMBER)(pow(10,matchToMatchLog10));
+        }
+    }
+    //Called during computation - use single precision where possible
+    static int fastRound(NUMBER d) {
+      return (d > ((NUMBER)0.0)) ? (int) (d + ((NUMBER)0.5)) : (int) (d - ((NUMBER)0.5));
+    }
+    //Called during computation - use single precision where possible
+    static NUMBER approximateLog10SumLog10(NUMBER small, NUMBER big) {
+      // make sure small is really the smaller value
+      if (small > big) {
+        NUMBER t = big;
+        big = small;
+        small = t;
+      }
+
+      if (isinf(small) == -1 || isinf(big) == -1)
+        return big;
+
+      NUMBER diff = big - small;
+      if (diff >= ((NUMBER)MAX_JACOBIAN_TOLERANCE))
+        return big;
+
+      // OK, so |y-x| < tol: we use the following identity then:
+      // we need to compute log10(10^x + 10^y)
+      // By Jacobian logarithm identity, this is equal to
+      // max(x,y) + log10(1+10^-abs(x-y))
+      // we compute the second term as a table lookup with integer quantization
+      // we have pre-stored correction for 0,0.1,0.2,... 10.0
+      int ind = fastRound((NUMBER)(diff * ((NUMBER)JACOBIAN_LOG_TABLE_INV_STEP))); // hard rounding
+      return big + jacobianLogTable[ind];
+    }
+};
+
+template<class NUMBER>
+struct Context : public ContextBase<NUMBER>
+{};
+
+template<>
+struct Context<double> : public ContextBase<double>
+{
+  Context():ContextBase<double>()
+  {
+    for (int x = 0; x < 128; x++)
+      ph2pr[x] = pow(10.0, -((double)x) / 10.0);
+
+    INITIAL_CONSTANT = ldexp(1.0, 1020.0);
+    LOG10_INITIAL_CONSTANT = log10(INITIAL_CONSTANT);
+    RESULT_THRESHOLD = 0.0;
+  }
+
+  double LOG10(double v){ return log10(v); }
+  inline double POW(double b, double e) { return pow(b,e); }
+
+  static double _(double n){ return n; }
+  static double _(float n){ return ((double) n); }
+};
+
+template<>
+struct Context<float> : public ContextBase<float>
+{
+  Context() : ContextBase<float>()
+  {
+    for (int x = 0; x < 128; x++)
+    {
+      ph2pr[x] = powf(10.f, -((float)x) / 10.f);
+    }
+
+    INITIAL_CONSTANT = ldexpf(1.f, 120.f);
+    LOG10_INITIAL_CONSTANT = log10f(INITIAL_CONSTANT);
+    RESULT_THRESHOLD = ldexpf(1.f, -110.f);
+  }
+
+  float LOG10(float v){ return log10f(v); }
+  inline float POW(float b, float e) { return powf(b,e); }
+
+  static float _(double n){ return ((float) n); }
+  static float _(float n){ return n; }
+};
+
+#define SET_MATCH_TO_MATCH_PROB(output, insQual, delQual)                       \
+{                                                                               \
+  int minQual = delQual;                                                        \
+  int maxQual = insQual;                                                        \
+  if (insQual <= delQual)                                                       \
+  {                                                                             \
+    minQual = insQual;                                                          \
+    maxQual = delQual;                                                          \
+  }                                                                             \
+  (output) = (MAX_QUAL < maxQual) ?                                             \
+  ((NUMBER)1.0) - ctx.POW(((NUMBER)10), ctx.approximateLog10SumLog10(((NUMBER)-0.1)*minQual, ((NUMBER)-0.1)*maxQual))       \
+  : ctx.matchToMatchProb[((maxQual * (maxQual + 1)) >> 1) + minQual];           \
+}
+
+
+
+typedef struct
+{
+        int rslen, haplen;
+	/*int *q, *i, *d, *c;*/
+	/*int q[MROWS], i[MROWS], d[MROWS], c[MROWS];*/
+	char *q, *i, *d, *c;
+        char *hap, *rs;
+	int *ihap;
+	int *irs;
+} testcase;
+
+#define MIN_ACCEPTED 1e-28f
+#define NUM_DISTINCT_CHARS 5
+#define AMBIG_CHAR 4
+
+class ConvertChar {
+
+  static uint8_t conversionTable[255] ;
+
+public:
+
+  static void init() {
+    assert (NUM_DISTINCT_CHARS == 5) ;
+    assert (AMBIG_CHAR == 4) ;
+
+    conversionTable['A'] = 0 ;
+    conversionTable['C'] = 1 ;
+    conversionTable['T'] = 2 ;
+    conversionTable['G'] = 3 ;
+    conversionTable['N'] = 4 ;
+  }
+
+  static inline uint8_t get(uint8_t input) {
+    return conversionTable[input] ;
+  }
+
+};
+
+int normalize(char c);
+int read_testcase(testcase *tc, FILE* ifp=0);
+
+#endif
diff --git a/public/VectorPairHMM/src/main/c++/define-double.h b/public/VectorPairHMM/src/main/c++/define-double.h
new file mode 100644
index 0000000..96fc274
--- /dev/null
+++ b/public/VectorPairHMM/src/main/c++/define-double.h
@@ -0,0 +1,205 @@
+/*Copyright (c) 2012 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.
+*/
+
+
+#include <iostream>
+
+#ifdef PRECISION
+#undef PRECISION
+#undef MAIN_TYPE
+#undef MAIN_TYPE_SIZE
+#undef UNION_TYPE
+#undef IF_128
+#undef IF_MAIN_TYPE
+#undef SHIFT_CONST1
+#undef SHIFT_CONST2
+#undef SHIFT_CONST3
+#undef _128_TYPE
+#undef SIMD_TYPE
+#undef AVX_LENGTH
+#undef HAP_TYPE
+#undef MASK_TYPE
+#undef MASK_ALL_ONES
+
+#undef SET_VEC_ZERO
+#undef VEC_OR
+#undef VEC_ADD
+#undef VEC_SUB
+#undef VEC_MUL
+#undef VEC_DIV
+#undef VEC_BLEND
+#undef VEC_BLENDV
+#undef VEC_CAST_256_128
+#undef VEC_EXTRACT_128
+#undef VEC_EXTRACT_UNIT
+#undef VEC_SET1_VAL128
+#undef VEC_MOVE
+#undef VEC_CAST_128_256
+#undef VEC_INSERT_VAL
+#undef VEC_CVT_128_256
+#undef VEC_SET1_VAL
+#undef VEC_POPCVT_CHAR
+#undef VEC_LDPOPCVT_CHAR
+#undef VEC_CMP_EQ
+#undef VEC_SET_LSE
+#undef SHIFT_HAP
+#undef MASK_VEC
+#undef VEC_SSE_TO_AVX
+#undef VEC_SHIFT_LEFT_1BIT
+#undef MASK_ALL_ONES
+#undef COMPARE_VECS
+#undef _256_INT_TYPE
+#undef BITMASK_VEC
+#endif
+
+#define PRECISION d
+#define MAIN_TYPE double
+#define MAIN_TYPE_SIZE 64
+#define UNION_TYPE mix_D
+#define IF_128 IF_128d
+#define IF_MAIN_TYPE IF_64
+#define SHIFT_CONST1 8
+#define SHIFT_CONST2 1
+#define SHIFT_CONST3 8
+#define _128_TYPE __m128d
+#define SIMD_TYPE __m256d
+#define _256_INT_TYPE __m256i
+#define AVX_LENGTH 4
+#define HAP_TYPE __m128i
+#define MASK_TYPE uint64_t
+#define MASK_ALL_ONES 0xFFFFFFFFFFFFFFFF
+#define MASK_VEC MaskVec_D
+
+#define SET_VEC_ZERO(__vec)                     \
+    __vec= _mm256_setzero_pd()
+
+#define VEC_OR(__v1, __v2)                      \
+    _mm256_or_pd(__v1, __v2)
+
+#define VEC_ADD(__v1, __v2)                     \
+    _mm256_add_pd(__v1, __v2)
+
+#define VEC_SUB(__v1, __v2)                     \
+    _mm256_sub_pd(__v1, __v2)
+
+#define VEC_MUL(__v1, __v2)                     \
+    _mm256_mul_pd(__v1, __v2)
+
+#define VEC_DIV(__v1, __v2)                     \
+    _mm256_div_pd(__v1, __v2)
+
+#define VEC_BLEND(__v1, __v2, __mask)           \
+    _mm256_blend_pd(__v1, __v2, __mask)
+
+#define VEC_BLENDV(__v1, __v2, __maskV)         \
+    _mm256_blendv_pd(__v1, __v2, __maskV)
+
+#define VEC_CAST_256_128(__v1)                  \
+    _mm256_castpd256_pd128 (__v1)
+
+#define VEC_EXTRACT_128(__v1, __im)             \
+    _mm256_extractf128_pd (__v1, __im)
+
+#define VEC_EXTRACT_UNIT(__v1, __im)            \
+    _mm_extract_epi64(__v1, __im)
+
+#define VEC_SET1_VAL128(__val)                  \
+    _mm_set1_pd(__val)
+
+#define VEC_MOVE(__v1, __val)                   \
+    _mm_move_sd(__v1, __val)
+
+#define VEC_CAST_128_256(__v1)                  \
+    _mm256_castpd128_pd256(__v1)
+
+#define VEC_INSERT_VAL(__v1, __val, __pos)      \
+    _mm256_insertf128_pd(__v1, __val, __pos)
+
+#define VEC_CVT_128_256(__v1)                   \
+    _mm256_cvtepi32_pd(__v1)
+
+#define VEC_SET1_VAL(__val)                     \
+    _mm256_set1_pd(__val)
+
+#define VEC_POPCVT_CHAR(__ch)                   \
+    _mm256_cvtepi32_pd(_mm_set1_epi32(__ch))
+
+#define VEC_LDPOPCVT_CHAR(__addr)               \
+    _mm256_cvtepi32_pd(_mm_load_si128((__m128i const *)__addr))
+
+#define VEC_CMP_EQ(__v1, __v2)                  \
+    _mm256_cmp_pd(__v1, __v2, _CMP_EQ_OQ)
+
+#define VEC_SET_LSE(__val)                      \
+    _mm256_set_pd(zero, zero, zero, __val);
+
+#define SHIFT_HAP(__v1, __val)                  \
+    __v1 = _mm_insert_epi32(_mm_slli_si128(__v1, 4), __val.i, 0)
+
+#define VEC_SSE_TO_AVX(__vsLow, __vsHigh, __vdst)       \
+    __vdst = _mm256_castpd128_pd256(__vsLow) ;            \
+__vdst = _mm256_insertf128_pd(__vdst, __vsHigh, 1) ;
+
+#define VEC_SHIFT_LEFT_1BIT(__vs)               \
+    __vs = _mm_slli_epi64(__vs, 1)
+
+
+#define COMPARE_VECS(__v1, __v2, __first, __last) {                     \
+    double* ptr1 = (double*) (&__v1) ;                                  \
+    double* ptr2 = (double*) (&__v2) ;                                  \
+    for (int ei=__first; ei <= __last; ++ei) {                          \
+        if (ptr1[ei] != ptr2[ei]) {                                       \
+            std::cout << "Double Mismatch at " << ei << ": "                \
+            << ptr1[ei] << " vs. " << ptr2[ei] << std::endl ;     \
+            exit(0) ;                                                       \
+        }                                                                 \
+    }                                                                   \
+}
+
+class BitMaskVec_double {
+
+    MASK_VEC low_, high_ ;
+    SIMD_TYPE combined_ ;
+
+    public:
+    inline MASK_TYPE& getLowEntry(int index) {
+        return low_.masks[index] ;
+    }
+    inline MASK_TYPE& getHighEntry(int index) {
+        return high_.masks[index] ;
+    }
+
+    inline const SIMD_TYPE& getCombinedMask() {
+        VEC_SSE_TO_AVX(low_.vecf, high_.vecf, combined_) ;
+        return combined_ ;
+    }
+
+    inline void shift_left_1bit() {
+        VEC_SHIFT_LEFT_1BIT(low_.vec) ;
+        VEC_SHIFT_LEFT_1BIT(high_.vec) ;
+    }
+
+} ;
+
+#define BITMASK_VEC BitMaskVec_double
diff --git a/public/VectorPairHMM/src/main/c++/define-float.h b/public/VectorPairHMM/src/main/c++/define-float.h
new file mode 100644
index 0000000..056bd53
--- /dev/null
+++ b/public/VectorPairHMM/src/main/c++/define-float.h
@@ -0,0 +1,206 @@
+/*Copyright (c) 2012 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.
+*/
+
+
+#include <iostream>
+
+#ifdef PRECISION
+#undef PRECISION
+#undef MAIN_TYPE
+#undef MAIN_TYPE_SIZE
+#undef UNION_TYPE
+#undef IF_128
+#undef IF_MAIN_TYPE
+#undef SHIFT_CONST1
+#undef SHIFT_CONST2
+#undef SHIFT_CONST3
+#undef _128_TYPE
+#undef SIMD_TYPE
+#undef AVX_LENGTH
+#undef HAP_TYPE
+#undef MASK_TYPE
+#undef MASK_ALL_ONES
+
+#undef SET_VEC_ZERO
+#undef VEC_OR
+#undef VEC_ADD
+#undef VEC_SUB
+#undef VEC_MUL
+#undef VEC_DIV
+#undef VEC_BLEND
+#undef VEC_BLENDV
+#undef VEC_CAST_256_128
+#undef VEC_EXTRACT_128
+#undef VEC_EXTRACT_UNIT
+#undef VEC_SET1_VAL128
+#undef VEC_MOVE
+#undef VEC_CAST_128_256
+#undef VEC_INSERT_VAL
+#undef VEC_CVT_128_256
+#undef VEC_SET1_VAL
+#undef VEC_POPCVT_CHAR
+#undef VEC_LDPOPCVT_CHAR
+#undef VEC_CMP_EQ
+#undef VEC_SET_LSE
+#undef SHIFT_HAP
+#undef MASK_VEC
+#undef VEC_SSE_TO_AVX
+#undef VEC_SHIFT_LEFT_1BIT
+#undef MASK_ALL_ONES
+#undef COMPARE_VECS
+#undef _256_INT_TYPE
+#undef BITMASK_VEC
+#endif
+
+#define PRECISION s
+
+#define MAIN_TYPE float
+#define MAIN_TYPE_SIZE 32
+#define UNION_TYPE mix_F
+#define IF_128 IF_128f
+#define IF_MAIN_TYPE IF_32
+#define SHIFT_CONST1 12
+#define SHIFT_CONST2 3
+#define SHIFT_CONST3 4
+#define _128_TYPE __m128
+#define SIMD_TYPE __m256
+#define _256_INT_TYPE __m256i
+#define AVX_LENGTH 8
+#define HAP_TYPE UNION_TYPE
+#define MASK_TYPE uint32_t
+#define MASK_ALL_ONES 0xFFFFFFFF
+#define MASK_VEC MaskVec_F
+
+#define SET_VEC_ZERO(__vec)                     \
+    __vec= _mm256_setzero_ps()
+
+#define VEC_OR(__v1, __v2)                      \
+    _mm256_or_ps(__v1, __v2)
+
+#define VEC_ADD(__v1, __v2)                     \
+    _mm256_add_ps(__v1, __v2)
+
+#define VEC_SUB(__v1, __v2)                     \
+    _mm256_sub_ps(__v1, __v2)
+
+#define VEC_MUL(__v1, __v2)                     \
+    _mm256_mul_ps(__v1, __v2)
+
+#define VEC_DIV(__v1, __v2)                     \
+    _mm256_div_ps(__v1, __v2)
+
+#define VEC_BLEND(__v1, __v2, __mask)           \
+    _mm256_blend_ps(__v1, __v2, __mask)
+
+#define VEC_BLENDV(__v1, __v2, __maskV)         \
+    _mm256_blendv_ps(__v1, __v2, __maskV)
+
+#define VEC_CAST_256_128(__v1)                  \
+    _mm256_castps256_ps128 (__v1)
+
+#define VEC_EXTRACT_128(__v1, __im)             \
+    _mm256_extractf128_ps (__v1, __im)
+
+#define VEC_EXTRACT_UNIT(__v1, __im)            \
+    _mm_extract_epi32(__v1, __im)
+
+#define VEC_SET1_VAL128(__val)                  \
+    _mm_set1_ps(__val)
+
+#define VEC_MOVE(__v1, __val)                   \
+    _mm_move_ss(__v1, __val)
+
+#define VEC_CAST_128_256(__v1)                  \
+    _mm256_castps128_ps256(__v1)
+
+#define VEC_INSERT_VAL(__v1, __val, __pos)      \
+    _mm256_insertf128_ps(__v1, __val, __pos)
+
+#define VEC_CVT_128_256(__v1)                   \
+    _mm256_cvtepi32_ps(__v1.i)
+
+#define VEC_SET1_VAL(__val)                     \
+    _mm256_set1_ps(__val)
+
+#define VEC_POPCVT_CHAR(__ch)                   \
+    _mm256_cvtepi32_ps(_mm256_set1_epi32(__ch))
+
+#define VEC_LDPOPCVT_CHAR(__addr)               \
+    _mm256_cvtepi32_ps(_mm256_loadu_si256((__m256i const *)__addr))
+
+#define VEC_CMP_EQ(__v1, __v2)                  \
+    _mm256_cmp_ps(__v1, __v2, _CMP_EQ_OQ)
+
+#define VEC_SET_LSE(__val)                      \
+    _mm256_set_ps(zero, zero, zero, zero, zero, zero, zero, __val);
+
+#define SHIFT_HAP(__v1, __val)                  \
+    _vector_shift_lastavxs(__v1, __val.f);
+
+#define VEC_SSE_TO_AVX(__vsLow, __vsHigh, __vdst)       \
+    __vdst = _mm256_castps128_ps256(__vsLow) ;            \
+__vdst = _mm256_insertf128_ps(__vdst, __vsHigh, 1) ;
+
+#define VEC_SHIFT_LEFT_1BIT(__vs)               \
+    __vs = _mm_slli_epi32(__vs, 1)
+
+#define COMPARE_VECS(__v1, __v2, __first, __last) {                     \
+    float* ptr1 = (float*) (&__v1) ;                                    \
+    float* ptr2 = (float*) (&__v2) ;                                    \
+    for (int ei=__first; ei <= __last; ++ei) {                          \
+        if (ptr1[ei] != ptr2[ei]) {                                       \
+            std::cout << "Float Mismatch at " << ei << ": "                 \
+            << ptr1[ei] << " vs. " << ptr2[ei] << std::endl ;     \
+            exit(0) ;                                                       \
+        }                                                                 \
+    }                                                                   \
+}
+
+class BitMaskVec_float {
+
+    MASK_VEC low_, high_ ;
+    SIMD_TYPE combined_ ;
+
+    public:
+
+    inline MASK_TYPE& getLowEntry(int index) {
+        return low_.masks[index] ;
+    }
+    inline MASK_TYPE& getHighEntry(int index) {
+        return high_.masks[index] ;
+    }
+
+    inline const SIMD_TYPE& getCombinedMask() {
+        VEC_SSE_TO_AVX(low_.vecf, high_.vecf, combined_) ;
+        return combined_ ;
+    }
+
+    inline void shift_left_1bit() {
+        VEC_SHIFT_LEFT_1BIT(low_.vec) ;
+        VEC_SHIFT_LEFT_1BIT(high_.vec) ;
+    }
+
+} ;
+
+#define BITMASK_VEC BitMaskVec_float
diff --git a/public/VectorPairHMM/src/main/c++/define-sse-double.h b/public/VectorPairHMM/src/main/c++/define-sse-double.h
new file mode 100644
index 0000000..9456e14
--- /dev/null
+++ b/public/VectorPairHMM/src/main/c++/define-sse-double.h
@@ -0,0 +1,173 @@
+/*Copyright (c) 2012 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.
+*/
+
+
+#ifdef PRECISION
+#undef PRECISION
+#undef MAIN_TYPE
+#undef MAIN_TYPE_SIZE
+#undef UNION_TYPE
+#undef IF_128
+#undef IF_MAIN_TYPE
+#undef SHIFT_CONST1
+#undef SHIFT_CONST2
+#undef SHIFT_CONST3
+#undef _128_TYPE
+#undef SIMD_TYPE
+#undef AVX_LENGTH
+#undef HAP_TYPE
+#undef MASK_TYPE
+#undef MASK_ALL_ONES
+
+#undef VEC_EXTRACT_UNIT
+#undef VEC_INSERT_UNIT
+#undef SET_VEC_ZERO
+#undef VEC_OR
+#undef VEC_ADD
+#undef VEC_SUB
+#undef VEC_MUL
+#undef VEC_DIV
+#undef VEC_BLEND
+#undef VEC_BLENDV
+#undef VEC_CAST_256_128
+#undef VEC_EXTRACT_128
+#undef VEC_EXTRACT_UNIT
+#undef VEC_SET1_VAL128
+#undef VEC_MOVE
+#undef VEC_CAST_128_256
+#undef VEC_INSERT_VAL
+#undef VEC_CVT_128_256
+#undef VEC_SET1_VAL
+#undef VEC_POPCVT_CHAR
+#undef VEC_LDPOPCVT_CHAR
+#undef VEC_CMP_EQ
+#undef VEC_SET_LSE
+#undef SHIFT_HAP
+#undef MASK_VEC
+#undef VEC_SSE_TO_AVX
+#undef VEC_SHIFT_LEFT_1BIT
+#undef MASK_ALL_ONES
+#undef COMPARE_VECS
+#undef _256_INT_TYPE
+#undef BITMASK_VEC
+#endif
+
+#define SSE
+#define PRECISION d
+
+#define MAIN_TYPE double
+#define MAIN_TYPE_SIZE 64
+#define UNION_TYPE mix_D128
+#define IF_128 IF_128d
+#define IF_MAIN_TYPE IF_64
+#define SHIFT_CONST1 1
+#define SHIFT_CONST2 8
+#define SHIFT_CONST3 0
+#define _128_TYPE __m128d
+#define SIMD_TYPE __m128d
+#define _256_INT_TYPE __m128i
+#define AVX_LENGTH 2
+#define HAP_TYPE __m128i
+#define MASK_TYPE uint64_t
+#define MASK_ALL_ONES 0xFFFFFFFFFFFFFFFFL
+#define MASK_VEC MaskVec_D
+
+#define VEC_EXTRACT_UNIT(__v1, __im)            \
+    _mm_extract_epi64(__v1, __im)
+
+#define VEC_INSERT_UNIT(__v1,__ins,__im)        \
+    _mm_insert_epi64(__v1,__ins,__im)
+
+#define VEC_OR(__v1, __v2)                      \
+    _mm_or_pd(__v1, __v2)
+
+#define VEC_ADD(__v1, __v2)                     \
+    _mm_add_pd(__v1, __v2)
+
+#define VEC_SUB(__v1, __v2)                     \
+    _mm_sub_pd(__v1, __v2)
+
+#define VEC_MUL(__v1, __v2)                     \
+    _mm_mul_pd(__v1, __v2)
+
+#define VEC_DIV(__v1, __v2)                     \
+    _mm_div_pd(__v1, __v2)
+
+#define VEC_CMP_EQ(__v1, __v2)                  \
+    _mm_cmpeq_pd(__v1, __v2)
+
+#define VEC_BLEND(__v1, __v2, __mask)           \
+    _mm_blend_pd(__v1, __v2, __mask)
+
+#define VEC_BLENDV(__v1, __v2, __maskV)         \
+    _mm_blendv_pd(__v1, __v2, __maskV)
+
+#define SHIFT_HAP(__v1, __val)                  \
+    __v1 = _mm_insert_epi32(_mm_slli_si128(__v1, 4), __val.i, 0)
+
+#define VEC_CVT_128_256(__v1)                   \
+    _mm_cvtepi32_pd(__v1)
+
+#define VEC_SET1_VAL(__val)                     \
+    _mm_set1_pd(__val)
+
+#define VEC_POPCVT_CHAR(__ch)                   \
+    _mm_cvtepi32_pd(_mm_set1_epi32(__ch))
+
+#define VEC_SET_LSE(__val)                      \
+    _mm_set_pd(zero, __val);
+
+#define VEC_LDPOPCVT_CHAR(__addr)               \
+    _mm_cvtepi32_pd(_mm_loadu_si128((__m128i const *)__addr))
+
+#define VEC_SSE_TO_AVX(__vsLow, __vsHigh, __vdst)       \
+    __vdst = _mm_castsi128_pd(_mm_set_epi64(__vsHigh, __vsLow))
+
+#define VEC_SHIFT_LEFT_1BIT(__vs)               \
+    __vs = _mm_slli_epi64(__vs, 1)
+
+
+class BitMaskVec_sse_double {
+
+    MASK_VEC combined_ ;
+    public:
+    inline MASK_TYPE& getLowEntry(int index) {
+        return combined_.masks[index] ;
+    }
+    inline MASK_TYPE& getHighEntry(int index) {
+        return combined_.masks[AVX_LENGTH/2+index] ;
+    }
+
+    inline const SIMD_TYPE& getCombinedMask() {
+        return combined_.vecf ;
+    }
+
+    inline void shift_left_1bit() {
+        VEC_SHIFT_LEFT_1BIT(combined_.vec) ;
+    }
+
+} ;
+
+#define BITMASK_VEC BitMaskVec_sse_double
+
diff --git a/public/VectorPairHMM/src/main/c++/define-sse-float.h b/public/VectorPairHMM/src/main/c++/define-sse-float.h
new file mode 100644
index 0000000..e9371c0
--- /dev/null
+++ b/public/VectorPairHMM/src/main/c++/define-sse-float.h
@@ -0,0 +1,173 @@
+/*Copyright (c) 2012 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.
+*/
+
+
+#ifdef PRECISION
+#undef PRECISION
+#undef MAIN_TYPE
+#undef MAIN_TYPE_SIZE
+#undef UNION_TYPE
+#undef IF_128
+#undef IF_MAIN_TYPE
+#undef SHIFT_CONST1
+#undef SHIFT_CONST2
+#undef SHIFT_CONST3
+#undef _128_TYPE
+#undef SIMD_TYPE
+#undef AVX_LENGTH
+#undef HAP_TYPE
+#undef MASK_TYPE
+#undef MASK_ALL_ONES
+
+#undef VEC_EXTRACT_UNIT
+#undef VEC_INSERT_UNIT
+#undef SET_VEC_ZERO
+#undef VEC_OR
+#undef VEC_ADD
+#undef VEC_SUB
+#undef VEC_MUL
+#undef VEC_DIV
+#undef VEC_BLEND
+#undef VEC_BLENDV
+#undef VEC_CAST_256_128
+#undef VEC_EXTRACT_128
+#undef VEC_EXTRACT_UNIT
+#undef VEC_SET1_VAL128
+#undef VEC_MOVE
+#undef VEC_CAST_128_256
+#undef VEC_INSERT_VAL
+#undef VEC_CVT_128_256
+#undef VEC_SET1_VAL
+#undef VEC_POPCVT_CHAR
+#undef VEC_LDPOPCVT_CHAR
+#undef VEC_CMP_EQ
+#undef VEC_SET_LSE
+#undef SHIFT_HAP
+#undef MASK_VEC
+#undef VEC_SSE_TO_AVX
+#undef VEC_SHIFT_LEFT_1BIT
+#undef MASK_ALL_ONES
+#undef COMPARE_VECS
+#undef _256_INT_TYPE
+#undef BITMASK_VEC
+#endif
+
+#define SSE
+#define PRECISION s
+
+#define MAIN_TYPE float
+#define MAIN_TYPE_SIZE 32
+#define UNION_TYPE mix_F128
+#define IF_128 IF_128f
+#define IF_MAIN_TYPE IF_32
+#define SHIFT_CONST1 3
+#define SHIFT_CONST2 4
+#define SHIFT_CONST3 0
+#define _128_TYPE __m128
+#define SIMD_TYPE __m128
+#define _256_INT_TYPE __m128i
+#define AVX_LENGTH 4
+//#define MAVX_COUNT  (MROWS+3)/AVX_LENGTH
+#define HAP_TYPE UNION_TYPE
+#define MASK_TYPE uint32_t
+#define MASK_ALL_ONES 0xFFFFFFFF
+#define MASK_VEC MaskVec_F
+
+#define VEC_EXTRACT_UNIT(__v1, __im)            \
+    _mm_extract_epi32(__v1, __im)
+
+#define VEC_INSERT_UNIT(__v1,__ins,__im)        \
+    _mm_insert_epi32(__v1,__ins,__im)
+
+#define VEC_OR(__v1, __v2)                      \
+    _mm_or_ps(__v1, __v2)
+
+#define VEC_ADD(__v1, __v2)                     \
+    _mm_add_ps(__v1, __v2)
+
+#define VEC_SUB(__v1, __v2)                     \
+    _mm_sub_ps(__v1, __v2)
+
+#define VEC_MUL(__v1, __v2)                     \
+    _mm_mul_ps(__v1, __v2)
+
+#define VEC_DIV(__v1, __v2)                     \
+    _mm_div_ps(__v1, __v2)
+
+#define VEC_CMP_EQ(__v1, __v2)                  \
+    _mm_cmpeq_ps(__v1, __v2)
+
+#define VEC_BLEND(__v1, __v2, __mask)           \
+    _mm_blend_ps(__v1, __v2, __mask)
+
+#define VEC_BLENDV(__v1, __v2, __maskV)         \
+    _mm_blendv_ps(__v1, __v2, __maskV)
+
+#define SHIFT_HAP(__v1, __val)                  \
+    _vector_shift_lastsses(__v1, __val.f)
+
+#define VEC_CVT_128_256(__v1)                   \
+    _mm_cvtepi32_ps(__v1.i)
+
+#define VEC_SET1_VAL(__val)                     \
+    _mm_set1_ps(__val)
+
+#define VEC_POPCVT_CHAR(__ch)                   \
+    _mm_cvtepi32_ps(_mm_set1_epi32(__ch))
+
+#define VEC_SET_LSE(__val)                      \
+    _mm_set_ps(zero, zero, zero, __val);
+
+#define VEC_LDPOPCVT_CHAR(__addr)               \
+    _mm_cvtepi32_ps(_mm_loadu_si128((__m128i const *)__addr))
+
+#define VEC_SSE_TO_AVX(__vsLow, __vsHigh, __vdst)       \
+    __vdst = _mm_cvtpi32x2_ps(__vsLow, __vsHigh)
+
+#define VEC_SHIFT_LEFT_1BIT(__vs)               \
+    __vs = _mm_slli_epi32(__vs, 1)
+
+class BitMaskVec_sse_float {
+
+    MASK_VEC combined_ ;
+
+    public:
+    inline MASK_TYPE& getLowEntry(int index) {
+        return combined_.masks[index] ;
+    }
+    inline MASK_TYPE& getHighEntry(int index) {
+        return combined_.masks[AVX_LENGTH/2+index] ;
+    }
+
+    inline const SIMD_TYPE& getCombinedMask() {
+        return combined_.vecf ;
+    }
+
+    inline void shift_left_1bit() {
+        VEC_SHIFT_LEFT_1BIT(combined_.vec) ;
+    }
+
+} ;
+
+#define BITMASK_VEC BitMaskVec_sse_float
diff --git a/public/VectorPairHMM/src/main/c++/headers.h b/public/VectorPairHMM/src/main/c++/headers.h
new file mode 100644
index 0000000..4a0d89b
--- /dev/null
+++ b/public/VectorPairHMM/src/main/c++/headers.h
@@ -0,0 +1,71 @@
+/*Copyright (c) 2012 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.
+*/
+
+
+#ifndef COMMON_HEADERS_H
+#define COMMON_HEADERS_H
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <math.h>
+#include <stdint.h>
+#include <assert.h>
+#include <ctype.h>
+
+#include <sys/time.h>
+
+#include <immintrin.h>
+#include <emmintrin.h>
+#include <omp.h>
+
+#include <string>
+#include <iostream>
+#include <sstream>
+#include <fstream>
+#include <vector>
+#include <map>
+#include <set>
+#include <cstdio>
+#include <cstring>
+#include <cstdlib>
+#include <cmath>
+#include <fenv.h>
+
+extern uint64_t exceptions_array[128];
+extern FILE* g_debug_fptr;
+#define STORE_FP_EXCEPTIONS(flagp, exceptions_array)                                    \
+  fegetexceptflag(&flagp, FE_ALL_EXCEPT | __FE_DENORM);                                 \
+  exceptions_array[FE_INVALID] += ((flagp & FE_INVALID));                               \
+  exceptions_array[__FE_DENORM] += ((flagp & __FE_DENORM) >> 1);                        \
+  exceptions_array[FE_DIVBYZERO] += ((flagp & FE_DIVBYZERO) >> 2);                      \
+  exceptions_array[FE_OVERFLOW] += ((flagp & FE_OVERFLOW) >> 3);                        \
+  exceptions_array[FE_UNDERFLOW] += ((flagp & FE_UNDERFLOW) >> 4);                      \
+  feclearexcept(FE_ALL_EXCEPT | __FE_DENORM);                 
+
+#define CONVERT_AND_PRINT(X)                    \
+  g_converter.f = (X);                          \
+  fwrite(&(g_converter.i),4,1,g_debug_fptr);    \
+
+#endif
diff --git a/public/VectorPairHMM/src/main/c++/jni_common.h b/public/VectorPairHMM/src/main/c++/jni_common.h
new file mode 100644
index 0000000..b3139d4
--- /dev/null
+++ b/public/VectorPairHMM/src/main/c++/jni_common.h
@@ -0,0 +1,60 @@
+/*Copyright (c) 2012 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.
+*/
+
+
+#ifndef JNI_COMMON_H
+#define JNI_COMMON_H
+
+/*#define SINGLE_THREADED_ONLY 1*/
+#include <jni.h>
+/*#define ENABLE_ASSERTIONS 1*/
+#ifdef SINGLE_THREADED_ONLY
+#define DO_PROFILING 1
+#endif
+/*#define DEBUG0_1 1*/
+/*#define DEBUG3 1*/
+/*#define DUMP_TO_SANDBOX 1*/
+
+
+/*#define DIRECT_ACCESS_TO_JAVA_HEAP_MEMORY 1*/
+
+#ifdef DIRECT_ACCESS_TO_JAVA_HEAP_MEMORY
+//Gets direct access to Java arrays
+#define GET_BYTE_ARRAY_ELEMENTS env->GetPrimitiveArrayCritical
+#define RELEASE_BYTE_ARRAY_ELEMENTS env->ReleasePrimitiveArrayCritical
+#define JNI_RO_RELEASE_MODE JNI_ABORT
+#define GET_DOUBLE_ARRAY_ELEMENTS env->GetPrimitiveArrayCritical
+#define RELEASE_DOUBLE_ARRAY_ELEMENTS env->ReleasePrimitiveArrayCritical
+
+#else
+//Likely makes copy of Java arrays to JNI C++ space
+#define GET_BYTE_ARRAY_ELEMENTS env->GetByteArrayElements
+#define RELEASE_BYTE_ARRAY_ELEMENTS env->ReleaseByteArrayElements
+#define JNI_RO_RELEASE_MODE JNI_ABORT
+#define GET_DOUBLE_ARRAY_ELEMENTS env->GetDoubleArrayElements
+#define RELEASE_DOUBLE_ARRAY_ELEMENTS env->ReleaseDoubleArrayElements
+
+#endif		//ifdef DIRECT_ACCESS_TO_JAVA_HEAP_MEMORY
+
+#endif  //ifndef JNI_COMMON_H
diff --git a/public/VectorPairHMM/src/main/c++/jnidebug.h b/public/VectorPairHMM/src/main/c++/jnidebug.h
new file mode 100644
index 0000000..df2e207
--- /dev/null
+++ b/public/VectorPairHMM/src/main/c++/jnidebug.h
@@ -0,0 +1,191 @@
+/*Copyright (c) 2012 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.
+*/
+
+
+#ifndef JNI_DEBUG_H
+#define JNI_DEBUG_H
+
+template<class NUMBER>
+class DataHolder
+{
+#define INIT_MATRIX(X)								\
+  X = new NUMBER*[m_paddedMaxReadLength];					\
+  for(int i=0;i<m_paddedMaxReadLength;++i)					\
+  {										\
+    X[i] = new NUMBER[m_paddedMaxHaplotypeLength];					\
+    for(int j=0;j<m_paddedMaxHaplotypeLength;++j)				\
+      X[i][j] = (NUMBER)0; 							\
+  }
+
+#define FREE_MATRIX(X)								\
+  for(int i=0;i<m_paddedMaxReadLength;++i)					\
+    delete[] X[i];								\
+  delete[] X;
+
+  public:
+    DataHolder() { m_is_initialized = false; }
+    void initialize(int readMaxLength, int haplotypeMaxLength)
+    {
+      if(m_is_initialized)
+      {
+	FREE_MATRIX(m_matchMatrix); 
+	FREE_MATRIX(m_insertionMatrix); 
+	FREE_MATRIX(m_deletionMatrix); 
+	FREE_MATRIX(m_prior);
+	delete[] m_transition;
+      }
+      
+      m_readMaxLength = readMaxLength;
+      m_haplotypeMaxLength = haplotypeMaxLength;
+      m_paddedMaxReadLength = readMaxLength + 1;
+      m_paddedMaxHaplotypeLength = haplotypeMaxLength + 1;
+           
+      INIT_MATRIX(m_matchMatrix); 
+      INIT_MATRIX(m_insertionMatrix); 
+      INIT_MATRIX(m_deletionMatrix); 
+      INIT_MATRIX(m_prior); 
+      m_transition = new NUMBER[m_paddedMaxReadLength][6];
+      for(int i=0;i<m_paddedMaxReadLength;++i)
+	for(int j=0;j<6;++j)
+	  m_transition[i][j] = (NUMBER)0;
+      m_is_initialized = true;
+    }
+
+    //Corresponds to initializeProbabilities
+    void initializeProbabilities(jint length, jbyte* insertionGOP, jbyte* deletionGOP, jbyte* overallGCP)
+    {
+      static unsigned g_num_prob_init = 0;
+      Context<NUMBER> ctx;
+      for (int r = 1; r <= length;r++)	//in original code, r < ROWS (where ROWS = paddedReadLength)
+      {
+	int _i = insertionGOP[r-1];	//insertionGOP
+	int _d = deletionGOP[r-1];	//deletionGOP
+	int _c = overallGCP[r-1];	//overallGCP
+	m_transition[r][MM] = ctx._(1.0) - ctx.ph2pr[(_i + _d) & 127];	//lines 161-162
+	m_transition[r][GapM] = ctx._(1.0) - ctx.ph2pr[_c];	//line 163
+	m_transition[r][MX] = ctx.ph2pr[_i];	//164
+	m_transition[r][XX] = ctx.ph2pr[_c];	//165
+	m_transition[r][MY] =  ctx.ph2pr[_d];//last row seems different, compared to line 166
+	m_transition[r][YY] = ctx.ph2pr[_c];//same as above for line 167
+	//m_transition[r][MY] = (r == length) ? ctx._(1.0) : ctx.ph2pr[_d];//last row seems different, compared to line 166
+	//m_transition[r][YY] = (r == length) ? ctx._(1.0) : ctx.ph2pr[_c];//same as above for line 167
+#ifdef DEBUG3
+	for(int j=0;j<6;++j)
+	  debug_dump("transitions_jni.txt", to_string(m_transition[r][j]),true);
+#endif
+      }
+      ++g_num_prob_init;
+    }
+    bool m_is_initialized;
+    int m_readMaxLength;
+    int m_haplotypeMaxLength;
+    int m_paddedMaxReadLength;
+    int m_paddedMaxHaplotypeLength;
+    NUMBER** m_matchMatrix;
+    NUMBER** m_insertionMatrix;
+    NUMBER** m_deletionMatrix;
+    NUMBER** m_prior; 
+    NUMBER (*m_transition)[6];
+};
+extern DataHolder<double> g_double_dataholder;
+
+template<class NUMBER>
+NUMBER compute_full_prob(testcase *tc, NUMBER** M, NUMBER** X, NUMBER** Y, NUMBER (*p)[6], 
+    bool do_initialization, jint hapStartIndex, NUMBER *before_last_log = NULL)
+{
+	int r, c;
+	int ROWS = tc->rslen + 1;	//ROWS = paddedReadLength
+	int COLS = tc->haplen + 1;	//COLS = paddedHaplotypeLength
+
+	Context<NUMBER> ctx;
+	//////NOTES
+	////ctx.ph2pr[quality]; 	//This quantity is QualityUtils.qualToErrorProb(quality)
+	////1-ctx.ph2pr[quality]; //This corresponds to QualityUtils.qualToProb(quality);
+
+	//Initialization
+	if(do_initialization)
+	{
+	  for (c = 0; c < COLS; c++)
+	  {
+	    M[0][c] = ctx._(0.0);
+	    X[0][c] = ctx._(0.0);
+	    Y[0][c] = ctx.INITIAL_CONSTANT / (tc->haplen);	//code from 87-90 in LoglessPairHMM
+	  }
+
+	  for (r = 1; r < ROWS; r++)
+	  {
+	    M[r][0] = ctx._(0.0);
+	    //deletionMatrix row 0 in above nest is initialized in the Java code
+	    //However, insertionMatrix column 0 is not initialized in Java code, could it be that
+	    //values are re-used from a previous iteration?
+	    //Why even do this, X[0][0] = 0 from above loop nest, X[idx][0] = 0 from this computation
+	    X[r][0] = X[r-1][0] * p[r][XX];
+	    Y[r][0] = ctx._(0.0);
+	  }
+	}
+
+	for (r = 1; r < ROWS; r++)
+		for (c = hapStartIndex+1; c < COLS; c++)
+		{
+		  	//The following lines correspond to initializePriors()
+			char _rs = tc->rs[r-1];		//line 137
+			char _hap = tc->hap[c-1];	//line 140
+			//int _q = tc->q[r-1] & 127;	//line 138 - q is the quality (qual), should be byte hence int ANDed with 0xFF
+			int _q = tc->q[r-1];	//line 138 - q is the quality (qual), should be byte hence int ANDed with 0xFF
+			NUMBER distm = ctx.ph2pr[_q]; 	//This quantity is QualityUtils.qualToErrorProb(_q)
+			//The assumption here is that doNotUseTristateCorrection is true	
+			//TOASK
+			if (_rs == _hap || _rs == 'N' || _hap == 'N')
+				distm = ctx._(1.0) - distm; //This is the quantity QualityUtils.qualToProb(qual)
+			else
+			  distm = distm/3;
+#ifdef DEBUG3
+			debug_dump("priors_jni.txt",to_string(distm),true);
+#endif
+
+			//Computation inside updateCell
+			M[r][c] = distm * (M[r-1][c-1] * p[r][MM] + X[r-1][c-1] * p[r][GapM] + Y[r-1][c-1] * p[r][GapM]);
+			X[r][c] = M[r-1][c] * p[r][MX] + X[r-1][c] * p[r][XX];
+			Y[r][c] = M[r][c-1] * p[r][MY] + Y[r][c-1] * p[r][YY];
+#ifdef DEBUG3
+			debug_dump("matrices_jni.txt",to_string(M[r][c]),true);
+			debug_dump("matrices_jni.txt",to_string(X[r][c]),true);
+			debug_dump("matrices_jni.txt",to_string(Y[r][c]),true);
+#endif
+		}
+
+	NUMBER result = ctx._(0.0);
+	for (c = 0; c < COLS; c++)
+		result += M[ROWS-1][c] + X[ROWS-1][c];
+
+	if (before_last_log != NULL)
+		*before_last_log = result;	
+
+#ifdef DEBUG
+	debug_dump("return_values_jni.txt",to_string(ctx.LOG10(result) - ctx.LOG10_INITIAL_CONSTANT),true);
+#endif
+	return ctx.LOG10(result) - ctx.LOG10_INITIAL_CONSTANT;
+}
+
+#endif
diff --git a/public/VectorPairHMM/src/main/c++/org_broadinstitute_gatk_utils_pairhmm_DebugJNILoglessPairHMM.cc b/public/VectorPairHMM/src/main/c++/org_broadinstitute_gatk_utils_pairhmm_DebugJNILoglessPairHMM.cc
new file mode 100644
index 0000000..42a9237
--- /dev/null
+++ b/public/VectorPairHMM/src/main/c++/org_broadinstitute_gatk_utils_pairhmm_DebugJNILoglessPairHMM.cc
@@ -0,0 +1,175 @@
+/*Copyright (c) 2012 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.
+*/
+
+
+#include "headers.h"
+#include "jni_common.h"
+#include "org_broadinstitute_gatk_utils_pairhmm_DebugJNILoglessPairHMM.h"
+#include "utils.h"
+#include "LoadTimeInitializer.h"
+#include "jnidebug.h"
+DataHolder<double> g_double_dataholder;
+
+using namespace std;
+
+JNIEXPORT void JNICALL Java_org_broadinstitute_gatk_utils_pairhmm_DebugJNILoglessPairHMM_jniInitialize
+(JNIEnv* env, jobject thisObject,
+ jint readMaxLength, jint haplotypeMaxLength)
+{
+  static int g_num_init_calls = 0;
+#ifdef DEBUG3
+  cout << "Entered alloc initialized .. readMaxLength "<<readMaxLength<<" haplotypeMaxLength "<<haplotypeMaxLength<<"\n";
+#endif
+  g_double_dataholder.initialize(readMaxLength, haplotypeMaxLength);
+#ifdef DEBUG3
+  debug_dump("lengths_jni.txt", to_string(readMaxLength)+" "+to_string(haplotypeMaxLength),true);
+#endif
+  ++g_num_init_calls;
+}
+
+JNIEXPORT void JNICALL Java_org_broadinstitute_gatk_utils_pairhmm_DebugJNILoglessPairHMM_jniInitializeProbabilities
+(JNIEnv* env, jclass thisObject,
+ jobjectArray transition, jbyteArray insertionGOP, jbyteArray deletionGOP, jbyteArray overallGCP
+ )
+{
+  jboolean is_copy = JNI_FALSE;
+  jsize length = (env)->GetArrayLength(insertionGOP);
+#ifdef DEBUG3
+  cout << "Entered initializeProbabilities .. length "<<length<<"\n";
+#endif
+  jbyte* insertionGOPArray = (env)->GetByteArrayElements(insertionGOP, &is_copy);
+  jbyte* deletionGOPArray = (env)->GetByteArrayElements(deletionGOP, &is_copy);
+  jbyte* overallGCPArray = (env)->GetByteArrayElements(overallGCP, &is_copy);
+#ifdef DEBUG
+  if(insertionGOPArray == 0)
+    cerr << "insertionGOP array not initialized in JNI\n";
+  ////assert(insertionGOPArray && "insertionGOP array not initialized in JNI");
+  if(deletionGOPArray == 0)
+    cerr << "deletionGOP array not initialized in JNI\n";
+  ////assert(deletionGOPArray && "deletionGOP array not initialized in JNI");
+  assert(overallGCPArray && "OverallGCP array not initialized in JNI");
+#endif
+
+  g_double_dataholder.initializeProbabilities(length, insertionGOPArray, deletionGOPArray, overallGCPArray);
+
+  env->ReleaseByteArrayElements(overallGCP, overallGCPArray, JNI_ABORT);
+  env->ReleaseByteArrayElements(deletionGOP, deletionGOPArray, JNI_ABORT);
+  env->ReleaseByteArrayElements(insertionGOP, insertionGOPArray, JNI_ABORT);
+}
+
+JNIEXPORT jdouble JNICALL 
+Java_org_broadinstitute_gatk_utils_pairhmm_DebugJNILoglessPairHMM_jniInitializePriorsAndUpdateCells( 
+    JNIEnv* env, jobject thisObject,
+    jboolean doInitialization, jint paddedReadLength, jint paddedHaplotypeLength,
+    jbyteArray readBases, jbyteArray haplotypeBases, jbyteArray readQuals,
+    jint hapStartIndex
+    )
+{
+#ifdef DEBUG3
+  cout << "Entered mainCompute .. doInitialization "<<(doInitialization == JNI_TRUE)<<" hapStartIndex "<<hapStartIndex<<"\n";
+  cout << "mainCompute padded lengths "<< paddedReadLength << " " << paddedHaplotypeLength <<"\n";
+#endif
+  jboolean is_copy = JNI_FALSE;
+  jbyte* readBasesArray = (env)->GetByteArrayElements(readBases, &is_copy);
+  jbyte* haplotypeBasesArray = (env)->GetByteArrayElements(haplotypeBases, &is_copy);
+  jbyte* readQualsArray = (env)->GetByteArrayElements(readQuals, &is_copy);
+#ifdef DEBUG
+  assert(readBasesArray && "readBasesArray not initialized in JNI"); 
+  assert(haplotypeBasesArray && "haplotypeBasesArray not initialized in JNI"); 
+  assert(readQualsArray && "readQualsArray not initialized in JNI"); 
+#endif
+  testcase tc;
+
+  tc.rslen = paddedReadLength-1;
+  tc.haplen = paddedHaplotypeLength-1;
+
+  tc.rs = (char*)readBasesArray;
+  tc.hap = (char*)haplotypeBasesArray;
+  tc.q = (char*)readQualsArray; //TOASK - q is now char*
+
+  compute_full_prob<double>(&tc, g_double_dataholder.m_matchMatrix, g_double_dataholder.m_insertionMatrix,
+      g_double_dataholder.m_deletionMatrix, g_double_dataholder.m_transition, 
+    doInitialization == JNI_TRUE, hapStartIndex, NULL);
+
+  env->ReleaseByteArrayElements(readBases, readBasesArray, JNI_ABORT);
+  env->ReleaseByteArrayElements(haplotypeBases, haplotypeBasesArray, JNI_ABORT);
+  env->ReleaseByteArrayElements(readQuals, readQualsArray, JNI_ABORT);
+  return 0.0;
+}
+
+JNIEXPORT jdouble JNICALL 
+Java_org_broadinstitute_gatk_utils_pairhmm_DebugJNILoglessPairHMM_jniSubComputeReadLikelihoodGivenHaplotypeLog10( 
+    JNIEnv* env, jobject thisObject,
+    jint readLength, jint haplotypeLength,
+    jbyteArray readBases, jbyteArray haplotypeBases, jbyteArray readQuals,
+    jbyteArray insertionGOP, jbyteArray deletionGOP, jbyteArray overallGCP,
+    jint hapStartIndex
+    )
+{
+  jboolean is_copy = JNI_FALSE;
+  jbyte* readBasesArray =   (jbyte*)GET_BYTE_ARRAY_ELEMENTS(readBases, &is_copy);
+  jbyte* haplotypeBasesArray = (jbyte*)GET_BYTE_ARRAY_ELEMENTS(haplotypeBases, &is_copy);
+  jbyte* readQualsArray = (jbyte*)GET_BYTE_ARRAY_ELEMENTS(readQuals, &is_copy);
+  jbyte* insertionGOPArray = (jbyte*)GET_BYTE_ARRAY_ELEMENTS(insertionGOP, &is_copy);
+  jbyte* deletionGOPArray = (jbyte*)GET_BYTE_ARRAY_ELEMENTS(deletionGOP, &is_copy);
+  jbyte* overallGCPArray = (jbyte*)GET_BYTE_ARRAY_ELEMENTS(overallGCP, &is_copy);
+#ifdef DEBUG
+  assert(readBasesArray && "readBasesArray not initialized in JNI"); 
+  assert(haplotypeBasesArray && "haplotypeBasesArray not initialized in JNI"); 
+  assert(readQualsArray && "readQualsArray not initialized in JNI"); 
+  assert(insertionGOPArray && "insertionGOP array not initialized in JNI");
+  assert(deletionGOPArray && "deletionGOP array not initialized in JNI");
+  assert(overallGCPArray && "OverallGCP array not initialized in JNI");
+  //assert(readLength < MROWS);
+#endif
+  testcase tc;
+  tc.rslen = readLength;
+  tc.haplen = haplotypeLength;
+  tc.rs = (char*)readBasesArray;
+  tc.hap = (char*)haplotypeBasesArray;
+  for(unsigned i=0;i<readLength;++i)
+  {
+    tc.q[i] = (int)readQualsArray[i];
+    tc.i[i] = (int)insertionGOPArray[i];
+    tc.d[i] = (int)deletionGOPArray[i];
+    tc.c[i] = (int)overallGCPArray[i];
+  }
+
+  double result_avxd = g_compute_full_prob_double(&tc, 0);
+  double result = log10(result_avxd) - log10(ldexp(1.0, 1020));
+#ifdef DEBUG
+  g_load_time_initializer.debug_dump("return_values_jni.txt",to_string(result),true);
+#endif
+
+
+  RELEASE_BYTE_ARRAY_ELEMENTS(overallGCP, overallGCPArray, JNI_RO_RELEASE_MODE);
+  RELEASE_BYTE_ARRAY_ELEMENTS(deletionGOP, deletionGOPArray, JNI_RO_RELEASE_MODE);
+  RELEASE_BYTE_ARRAY_ELEMENTS(insertionGOP, insertionGOPArray, JNI_RO_RELEASE_MODE);
+  RELEASE_BYTE_ARRAY_ELEMENTS(readQuals, readQualsArray, JNI_RO_RELEASE_MODE);
+  RELEASE_BYTE_ARRAY_ELEMENTS(haplotypeBases, haplotypeBasesArray, JNI_RO_RELEASE_MODE);
+  RELEASE_BYTE_ARRAY_ELEMENTS(readBases, readBasesArray, JNI_RO_RELEASE_MODE);
+
+  return 0.0;
+}
+
diff --git a/public/VectorPairHMM/src/main/c++/org_broadinstitute_gatk_utils_pairhmm_DebugJNILoglessPairHMM.h b/public/VectorPairHMM/src/main/c++/org_broadinstitute_gatk_utils_pairhmm_DebugJNILoglessPairHMM.h
new file mode 100644
index 0000000..6fb440c
--- /dev/null
+++ b/public/VectorPairHMM/src/main/c++/org_broadinstitute_gatk_utils_pairhmm_DebugJNILoglessPairHMM.h
@@ -0,0 +1,86 @@
+/*Copyright (c) 2012 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.
+*/
+
+
+/* DO NOT EDIT THIS FILE - it is machine generated */
+#include <jni.h>
+/* Header for class org_broadinstitute_gatk_utils_pairhmm_DebugJNILoglessPairHMM */
+
+#ifndef _Included_org_broadinstitute_gatk_utils_pairhmm_DebugJNILoglessPairHMM
+#define _Included_org_broadinstitute_gatk_utils_pairhmm_DebugJNILoglessPairHMM
+#ifdef __cplusplus
+extern "C" {
+#endif
+#undef org_broadinstitute_gatk_utils_pairhmm_DebugJNILoglessPairHMM_TRISTATE_CORRECTION
+#define org_broadinstitute_gatk_utils_pairhmm_DebugJNILoglessPairHMM_TRISTATE_CORRECTION 3.0
+#undef org_broadinstitute_gatk_utils_pairhmm_DebugJNILoglessPairHMM_dumpSandboxOnly
+#define org_broadinstitute_gatk_utils_pairhmm_DebugJNILoglessPairHMM_dumpSandboxOnly 0L
+#undef org_broadinstitute_gatk_utils_pairhmm_DebugJNILoglessPairHMM_debug
+#define org_broadinstitute_gatk_utils_pairhmm_DebugJNILoglessPairHMM_debug 0L
+#undef org_broadinstitute_gatk_utils_pairhmm_DebugJNILoglessPairHMM_verify
+#define org_broadinstitute_gatk_utils_pairhmm_DebugJNILoglessPairHMM_verify 1L
+#undef org_broadinstitute_gatk_utils_pairhmm_DebugJNILoglessPairHMM_debug0_1
+#define org_broadinstitute_gatk_utils_pairhmm_DebugJNILoglessPairHMM_debug0_1 0L
+#undef org_broadinstitute_gatk_utils_pairhmm_DebugJNILoglessPairHMM_debug1
+#define org_broadinstitute_gatk_utils_pairhmm_DebugJNILoglessPairHMM_debug1 0L
+#undef org_broadinstitute_gatk_utils_pairhmm_DebugJNILoglessPairHMM_debug2
+#define org_broadinstitute_gatk_utils_pairhmm_DebugJNILoglessPairHMM_debug2 0L
+#undef org_broadinstitute_gatk_utils_pairhmm_DebugJNILoglessPairHMM_debug3
+#define org_broadinstitute_gatk_utils_pairhmm_DebugJNILoglessPairHMM_debug3 0L
+/*
+ * Class:     org_broadinstitute_gatk_utils_pairhmm_DebugJNILoglessPairHMM
+ * Method:    jniInitialize
+ * Signature: (II)V
+ */
+JNIEXPORT void JNICALL Java_org_broadinstitute_gatk_utils_pairhmm_DebugJNILoglessPairHMM_jniInitialize
+  (JNIEnv *, jobject, jint, jint);
+
+/*
+ * Class:     org_broadinstitute_gatk_utils_pairhmm_DebugJNILoglessPairHMM
+ * Method:    jniInitializeProbabilities
+ * Signature: ([[D[B[B[B)V
+ */
+JNIEXPORT void JNICALL Java_org_broadinstitute_gatk_utils_pairhmm_DebugJNILoglessPairHMM_jniInitializeProbabilities
+  (JNIEnv *, jclass, jobjectArray, jbyteArray, jbyteArray, jbyteArray);
+
+/*
+ * Class:     org_broadinstitute_gatk_utils_pairhmm_DebugJNILoglessPairHMM
+ * Method:    jniInitializePriorsAndUpdateCells
+ * Signature: (ZII[B[B[BI)D
+ */
+JNIEXPORT jdouble JNICALL Java_org_broadinstitute_gatk_utils_pairhmm_DebugJNILoglessPairHMM_jniInitializePriorsAndUpdateCells
+  (JNIEnv *, jobject, jboolean, jint, jint, jbyteArray, jbyteArray, jbyteArray, jint);
+
+/*
+ * Class:     org_broadinstitute_gatk_utils_pairhmm_DebugJNILoglessPairHMM
+ * Method:    jniSubComputeReadLikelihoodGivenHaplotypeLog10
+ * Signature: (II[B[B[B[B[B[BI)D
+ */
+JNIEXPORT jdouble JNICALL Java_org_broadinstitute_gatk_utils_pairhmm_DebugJNILoglessPairHMM_jniSubComputeReadLikelihoodGivenHaplotypeLog10
+  (JNIEnv *, jobject, jint, jint, jbyteArray, jbyteArray, jbyteArray, jbyteArray, jbyteArray, jbyteArray, jint);
+
+#ifdef __cplusplus
+}
+#endif
+#endif
diff --git a/public/VectorPairHMM/src/main/c++/org_broadinstitute_gatk_utils_pairhmm_VectorLoglessPairHMM.cc b/public/VectorPairHMM/src/main/c++/org_broadinstitute_gatk_utils_pairhmm_VectorLoglessPairHMM.cc
new file mode 100644
index 0000000..d9d2684
--- /dev/null
+++ b/public/VectorPairHMM/src/main/c++/org_broadinstitute_gatk_utils_pairhmm_VectorLoglessPairHMM.cc
@@ -0,0 +1,416 @@
+/*Copyright (c) 2012 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.
+*/
+
+
+#include "headers.h"
+#include "jni_common.h"
+#include "org_broadinstitute_gatk_utils_pairhmm_VectorLoglessPairHMM.h"
+//#include "template.h"
+#include "utils.h"
+#include "LoadTimeInitializer.h"
+
+using namespace std;
+
+JNIEXPORT jlong JNICALL Java_org_broadinstitute_gatk_utils_pairhmm_VectorLoglessPairHMM_jniGetMachineType
+  (JNIEnv* env, jobject thisObject)
+{
+  return (jlong)get_machine_capabilities(); 
+}
+
+//Should be called only once for the whole Java process - initializes field ids for the classes JNIReadDataHolderClass
+//and JNIHaplotypeDataHolderClass
+JNIEXPORT void JNICALL Java_org_broadinstitute_gatk_utils_pairhmm_VectorLoglessPairHMM_jniInitializeClassFieldsAndMachineMask
+  (JNIEnv* env, jobject thisObject, jclass readDataHolderClass, jclass haplotypeDataHolderClass, jlong mask)
+{
+  assert(readDataHolderClass);
+  assert(haplotypeDataHolderClass);
+  jfieldID fid;
+  fid = env->GetFieldID(readDataHolderClass, "readBases", "[B");
+  assert(fid && "JNI pairHMM: Could not get FID for readBases");
+  g_load_time_initializer.m_readBasesFID = fid;
+  fid = env->GetFieldID(readDataHolderClass, "readQuals", "[B");
+  assert(fid && "JNI pairHMM: Could not get FID for readQuals");
+  g_load_time_initializer.m_readQualsFID = fid;
+  fid = env->GetFieldID(readDataHolderClass, "insertionGOP", "[B");
+  assert(fid && "JNI pairHMM: Could not get FID for insertionGOP");
+  g_load_time_initializer.m_insertionGOPFID = fid;
+  fid = env->GetFieldID(readDataHolderClass, "deletionGOP", "[B");
+  assert(fid && "JNI pairHMM: Could not get FID for deletionGOP");
+  g_load_time_initializer.m_deletionGOPFID = fid;
+  fid = env->GetFieldID(readDataHolderClass, "overallGCP", "[B");
+  assert(fid && "JNI pairHMM: Could not get FID for overallGCP");
+  g_load_time_initializer.m_overallGCPFID = fid;
+
+  fid = env->GetFieldID(haplotypeDataHolderClass, "haplotypeBases", "[B");
+  assert(fid && "JNI pairHMM: Could not get FID for haplotypeBases");
+  g_load_time_initializer.m_haplotypeBasesFID = fid;
+  if(mask != ENABLE_ALL_HARDWARE_FEATURES)
+  {
+    cout << "Using user supplied hardware mask to re-initialize function pointers for PairHMM\n";
+    initialize_function_pointers((uint64_t)mask);
+    cout.flush();
+  }
+}
+
+JNIEXPORT void JNICALL initializeHaplotypes
+  (JNIEnv * env, jobject& thisObject, jint numHaplotypes, jobjectArray& haplotypeDataArray,
+   vector<pair<jbyteArray, jbyte*> >& haplotypeBasesArrayVector, vector<unsigned>& haplotypeBasesLengths)
+{
+  jboolean is_copy = JNI_FALSE;
+  haplotypeBasesArrayVector.clear();
+  haplotypeBasesLengths.clear();
+  haplotypeBasesArrayVector.resize(numHaplotypes);
+  haplotypeBasesLengths.resize(numHaplotypes);
+  jsize haplotypeBasesLength = 0;
+  for(unsigned j=0;j<numHaplotypes;++j)
+  {
+    jobject haplotypeObject = env->GetObjectArrayElement(haplotypeDataArray, j);
+    jbyteArray haplotypeBases = (jbyteArray)env->GetObjectField(haplotypeObject, g_load_time_initializer.m_haplotypeBasesFID);
+#ifdef ENABLE_ASSERTIONS
+    assert(haplotypeBases && ("haplotypeBases is NULL at index : "+to_string(j)+"\n").c_str());
+#endif
+    //Need a global reference as this will be accessed across multiple JNI calls to JNIComputeLikelihoods()
+    jbyteArray haplotypeBasesGlobalRef = (jbyteArray)env->NewGlobalRef(haplotypeBases);
+#ifdef ENABLE_ASSERTIONS
+    assert(haplotypeBasesGlobalRef && ("Could not get global ref to haplotypeBases at index : "+to_string(j)+"\n").c_str());
+#endif
+    env->DeleteLocalRef(haplotypeBases);	//free the local reference
+    jbyte* haplotypeBasesArray = (jbyte*)GET_BYTE_ARRAY_ELEMENTS(haplotypeBasesGlobalRef, &is_copy);
+    haplotypeBasesLength = env->GetArrayLength(haplotypeBasesGlobalRef);
+#ifdef ENABLE_ASSERTIONS
+    assert(haplotypeBasesArray && "haplotypeBasesArray not initialized in JNI"); 
+    //assert(haplotypeBasesLength < MCOLS);
+#endif
+#ifdef DEBUG0_1
+    cout << "JNI haplotype length "<<haplotypeBasesLength<<"\n";
+#endif
+    haplotypeBasesArrayVector[j] = make_pair(haplotypeBasesGlobalRef, haplotypeBasesArray);
+    haplotypeBasesLengths[j] = haplotypeBasesLength;
+#ifdef DEBUG3
+    for(unsigned k=0;k<haplotypeBasesLength;++k)
+      g_load_time_initializer.debug_dump("haplotype_bases_jni.txt",to_string((int)haplotypeBasesArray[k]),true);
+#endif
+#ifdef DO_PROFILING
+    g_load_time_initializer.update_stat(HAPLOTYPE_LENGTH_IDX, haplotypeBasesLength);
+    g_load_time_initializer.m_bytes_copied += (is_copy ? haplotypeBasesLength : 0);
+#endif
+  }
+}
+
+JNIEXPORT void JNICALL releaseHaplotypes(JNIEnv * env, jobject thisObject,
+    vector<pair<jbyteArray, jbyte*> >& haplotypeBasesArrayVector, vector<unsigned>& haplotypeBasesLengths
+    )
+{
+  //Now release haplotype arrays
+  for(int j=haplotypeBasesArrayVector.size()-1;j>=0;--j)	//note the order - reverse of GET
+  {
+    RELEASE_BYTE_ARRAY_ELEMENTS(haplotypeBasesArrayVector[j].first, haplotypeBasesArrayVector[j].second, JNI_RO_RELEASE_MODE);
+    env->DeleteGlobalRef(haplotypeBasesArrayVector[j].first);	//free the global reference
+  }
+  haplotypeBasesArrayVector.clear();
+  haplotypeBasesLengths.clear(); 
+}
+
+
+vector<pair<jbyteArray, jbyte*> > g_haplotypeBasesArrayVector;
+vector<unsigned> g_haplotypeBasesLengths;
+//Since the list of haplotypes against which the reads are evaluated in PairHMM is the same for a region,
+//transfer the list only once
+//Works only for ST case as the haplotype data is stored in global variables
+JNIEXPORT void JNICALL Java_org_broadinstitute_gatk_utils_pairhmm_VectorLoglessPairHMM_jniInitializeHaplotypes
+  (JNIEnv * env, jobject thisObject, jint numHaplotypes, jobjectArray haplotypeDataArray)
+{
+#ifdef SINGLE_THREADED_ONLY
+  //To ensure, GET_BYTE_ARRAY_ELEMENTS is invoked only once for each haplotype, store bytearrays in a vector
+  initializeHaplotypes(env, thisObject, numHaplotypes, haplotypeDataArray, g_haplotypeBasesArrayVector, g_haplotypeBasesLengths);
+#endif
+}
+
+
+//Create a vector of testcases for computation - copy the references to bytearrays read/readQuals etc into the appropriate
+//testcase struct
+inline JNIEXPORT void JNICALL Java_org_broadinstitute_gatk_utils_pairhmm_VectorLoglessPairHMM_jniInitializeTestcasesVector
+  (JNIEnv* env, jint numReads, jint numHaplotypes, jobjectArray& readDataArray,
+   vector<vector<pair<jbyteArray,jbyte*> > >& readBasesArrayVector,
+   vector<pair<jbyteArray, jbyte*> >& haplotypeBasesArrayVector, vector<unsigned>& haplotypeBasesLengths,
+   vector<testcase>& tc_array)
+{
+  jboolean is_copy = JNI_FALSE;
+  unsigned tc_idx = 0;
+  for(unsigned i=0;i<numReads;++i)
+  {
+    //Get bytearray fields from read
+    jobject readObject = env->GetObjectArrayElement(readDataArray, i);
+    jbyteArray readBases = (jbyteArray)env->GetObjectField(readObject, g_load_time_initializer.m_readBasesFID);
+    jbyteArray insertionGOP = (jbyteArray)env->GetObjectField(readObject, g_load_time_initializer.m_insertionGOPFID);
+    jbyteArray deletionGOP = (jbyteArray)env->GetObjectField(readObject, g_load_time_initializer.m_deletionGOPFID);
+    jbyteArray overallGCP = (jbyteArray)env->GetObjectField(readObject, g_load_time_initializer.m_overallGCPFID);
+    jbyteArray readQuals = (jbyteArray)env->GetObjectField(readObject, g_load_time_initializer.m_readQualsFID);
+
+#ifdef ENABLE_ASSERTIONS
+    assert(readBases && ("readBases is NULL at index : "+to_string(i)+"\n").c_str());
+    assert(insertionGOP && ("insertionGOP is NULL at index : "+to_string(i)+"\n").c_str());
+    assert(deletionGOP && ("deletionGOP is NULL at index : "+to_string(i)+"\n").c_str());
+    assert(overallGCP && ("overallGCP is NULL at index : "+to_string(i)+"\n").c_str());
+    assert(readQuals && ("readQuals is NULL at index : "+to_string(i)+"\n").c_str());
+#endif
+    jsize readLength = env->GetArrayLength(readBases);
+
+    jbyte* readBasesArray = (jbyte*)GET_BYTE_ARRAY_ELEMENTS(readBases, &is_copy);	//order of GET-RELEASE is important
+    jbyte* readQualsArray = (jbyte*)GET_BYTE_ARRAY_ELEMENTS(readQuals, &is_copy);
+    jbyte* insertionGOPArray = (jbyte*)GET_BYTE_ARRAY_ELEMENTS(insertionGOP, &is_copy);
+    jbyte* deletionGOPArray = (jbyte*)GET_BYTE_ARRAY_ELEMENTS(deletionGOP, &is_copy);
+    jbyte* overallGCPArray = (jbyte*)GET_BYTE_ARRAY_ELEMENTS(overallGCP, &is_copy);
+#ifdef DO_PROFILING
+    g_load_time_initializer.m_bytes_copied += (is_copy ? readLength*5 : 0);
+    g_load_time_initializer.update_stat(READ_LENGTH_IDX, readLength);
+#endif
+#ifdef ENABLE_ASSERTIONS
+    assert(readBasesArray && "readBasesArray not initialized in JNI"); 
+    assert(readQualsArray && "readQualsArray not initialized in JNI"); 
+    assert(insertionGOPArray && "insertionGOP array not initialized in JNI");
+    assert(deletionGOPArray && "deletionGOP array not initialized in JNI");
+    assert(overallGCPArray && "overallGCP array not initialized in JNI");
+    //assert(readLength < MROWS); 
+    assert(readLength == env->GetArrayLength(readQuals));
+    assert(readLength == env->GetArrayLength(insertionGOP));
+    assert(readLength == env->GetArrayLength(deletionGOP));
+    assert(readLength == env->GetArrayLength(overallGCP));
+#endif
+#ifdef DEBUG0_1
+    cout << "JNI read length "<<readLength<<"\n";
+#endif
+#ifdef DEBUG3
+    for(unsigned j=0;j<readLength;++j)
+    {
+      g_load_time_initializer.debug_dump("reads_jni.txt",to_string((int)readBasesArray[j]),true);
+      g_load_time_initializer.debug_dump("reads_jni.txt",to_string((int)readQualsArray[j]),true);
+      g_load_time_initializer.debug_dump("reads_jni.txt",to_string((int)insertionGOPArray[j]),true);
+      g_load_time_initializer.debug_dump("reads_jni.txt",to_string((int)deletionGOPArray[j]),true);
+      g_load_time_initializer.debug_dump("reads_jni.txt",to_string((int)overallGCPArray[j]),true);
+    }
+#endif
+    for(unsigned j=0;j<numHaplotypes;++j)
+    {
+      jsize haplotypeLength = (jsize)haplotypeBasesLengths[j];
+      jbyte* haplotypeBasesArray = haplotypeBasesArrayVector[j].second;
+      tc_array[tc_idx].rslen = (int)readLength;
+      tc_array[tc_idx].haplen = (int)haplotypeLength;
+      tc_array[tc_idx].hap = (char*)haplotypeBasesArray;
+      tc_array[tc_idx].rs = (char*)readBasesArray;
+      tc_array[tc_idx].q = (char*)readQualsArray;
+      tc_array[tc_idx].i = (char*)insertionGOPArray;
+      tc_array[tc_idx].d = (char*)deletionGOPArray;
+      tc_array[tc_idx].c = (char*)overallGCPArray;
+#ifdef DO_PROFILING
+      g_load_time_initializer.update_stat(PRODUCT_READ_LENGTH_HAPLOTYPE_LENGTH_IDX, ((uint64_t)readLength)*((uint64_t)haplotypeLength));
+#endif
+#ifdef DUMP_TO_SANDBOX
+      g_load_time_initializer.dump_sandbox(tc_array[tc_idx], tc_idx, numReads, numHaplotypes);
+#endif
+      ++tc_idx;  
+    }
+    //Store the read array references and release them at the end because they are used by compute_full_prob
+    //Maintain order in which GET_BYTE_ARRAY_ELEMENTS called
+    readBasesArrayVector[i].clear();
+    readBasesArrayVector[i].resize(5);
+    readBasesArrayVector[i][0] = make_pair(readBases, readBasesArray);
+    readBasesArrayVector[i][1] = make_pair(readQuals, readQualsArray);
+    readBasesArrayVector[i][2] = make_pair(insertionGOP, insertionGOPArray);
+    readBasesArrayVector[i][3] = make_pair(deletionGOP, deletionGOPArray);
+    readBasesArrayVector[i][4] = make_pair(overallGCP, overallGCPArray);
+  }
+}
+
+//Do compute over vector of testcase structs
+inline void compute_testcases(vector<testcase>& tc_array, unsigned numTestCases, double* likelihoodDoubleArray,
+    unsigned maxNumThreadsToUse)
+{
+#ifdef DO_REPEAT_PROFILING
+  for(unsigned i=0;i<10;++i)
+#endif
+  {
+#pragma omp parallel for schedule (dynamic,10000) num_threads(maxNumThreadsToUse)
+    for(unsigned tc_idx=0;tc_idx<numTestCases;++tc_idx)
+    {
+      float result_avxf = g_compute_full_prob_float(&(tc_array[tc_idx]), 0);
+      double result = 0;
+      if (result_avxf < MIN_ACCEPTED) {
+        double result_avxd = g_compute_full_prob_double(&(tc_array[tc_idx]), 0);
+        result = log10(result_avxd) - log10(ldexp(1.0, 1020.0));
+#ifdef DO_PROFILING
+        g_load_time_initializer.update_stat(NUM_DOUBLE_INVOCATIONS_IDX, 1);
+#endif
+      }
+      else
+        result = (double)(log10f(result_avxf) - log10f(ldexpf(1.f, 120.f)));
+      likelihoodDoubleArray[tc_idx] = result;
+    }
+  }
+}
+
+//Inform the Java VM that we no longer need access to the read arrays (and free memory)
+inline JNIEXPORT void JNICALL Java_org_broadinstitute_gatk_utils_pairhmm_VectorLoglessPairHMM_jniReleaseReadArrays
+  (JNIEnv* env, vector<vector<pair<jbyteArray,jbyte*> > >& readBasesArrayVector)
+{
+  //Release read arrays first
+  for(int i=readBasesArrayVector.size()-1;i>=0;--i)//note the order - reverse of GET
+  {
+    for(int j=readBasesArrayVector[i].size()-1;j>=0;--j)
+      RELEASE_BYTE_ARRAY_ELEMENTS(readBasesArrayVector[i][j].first, readBasesArrayVector[i][j].second, JNI_RO_RELEASE_MODE);
+    readBasesArrayVector[i].clear();
+  }
+  readBasesArrayVector.clear();
+}
+
+
+#ifdef DO_WARMUP
+uint64_t g_sum = 0;
+#endif
+//JNI function to invoke compute_full_prob_avx
+//readDataArray - array of JNIReadDataHolderClass objects which contain the readBases, readQuals etc
+//haplotypeDataArray - array of JNIHaplotypeDataHolderClass objects which contain the haplotypeBases
+//likelihoodArray - array of doubles to return results back to Java. Memory allocated by Java prior to JNI call
+//maxNumThreadsToUse - Max number of threads that OpenMP can use for the HMM computation
+JNIEXPORT void JNICALL Java_org_broadinstitute_gatk_utils_pairhmm_VectorLoglessPairHMM_jniComputeLikelihoods
+  (JNIEnv* env, jobject thisObject, jint numReads, jint numHaplotypes, 
+   jobjectArray readDataArray, jobjectArray haplotypeDataArray, jdoubleArray likelihoodArray, jint maxNumThreadsToUse)
+{
+#ifdef DEBUG0_1
+  cout << "JNI numReads "<<numReads<<" numHaplotypes "<<numHaplotypes<<"\n";
+#endif
+  jboolean is_copy = JNI_FALSE;
+  struct timespec start_time;
+  unsigned numTestCases = numReads*numHaplotypes;
+  //vector to store testcases
+  vector<testcase> tc_array;
+  tc_array.clear();
+  tc_array.resize(numTestCases);
+  //Store read arrays for release later
+  vector<vector<pair<jbyteArray,jbyte*> > > readBasesArrayVector;
+  readBasesArrayVector.clear();
+  readBasesArrayVector.resize(numReads);
+#ifdef DUMP_TO_SANDBOX
+  g_load_time_initializer.open_sandbox();
+#endif
+#ifdef DO_PROFILING
+  get_time(&start_time);
+#endif
+
+#ifdef SINGLE_THREADED_ONLY
+  vector<pair<jbyteArray, jbyte*> >& haplotypeBasesArrayVector = g_haplotypeBasesArrayVector;
+  vector<unsigned>& haplotypeBasesLengths = g_haplotypeBasesLengths;
+#else
+  vector<pair<jbyteArray, jbyte*> > l_haplotypeBasesArrayVector;
+  vector<pair<jbyteArray, jbyte*> >& haplotypeBasesArrayVector = l_haplotypeBasesArrayVector;
+  vector<unsigned> l_haplotypeBasesLengths;
+  vector<unsigned>& haplotypeBasesLengths = l_haplotypeBasesLengths;
+  initializeHaplotypes(env, thisObject, numHaplotypes, haplotypeDataArray, haplotypeBasesArrayVector, haplotypeBasesLengths);
+#endif
+  //Copy byte array references from Java memory into vector of testcase structs
+  Java_org_broadinstitute_gatk_utils_pairhmm_VectorLoglessPairHMM_jniInitializeTestcasesVector(env,
+      numReads, numHaplotypes, readDataArray, readBasesArrayVector, haplotypeBasesArrayVector, haplotypeBasesLengths, tc_array);
+
+#ifdef DO_PROFILING
+  g_load_time_initializer.m_data_transfer_time += diff_time(start_time);
+#endif
+
+  //Get double array where results are stored (to pass back to java)
+  jdouble* likelihoodDoubleArray = (jdouble*)GET_DOUBLE_ARRAY_ELEMENTS(likelihoodArray, &is_copy);
+#ifdef ENABLE_ASSERTIONS
+  assert(likelihoodDoubleArray && "likelihoodArray is NULL");
+  assert(env->GetArrayLength(likelihoodArray) == numTestCases);
+#endif
+#ifdef DO_WARMUP        //ignore - only for crazy profiling
+  for(unsigned i=0;i<haplotypeBasesArrayVector.size();++i)
+  {
+    unsigned curr_size = env->GetArrayLength(haplotypeBasesArrayVector[i].first);
+    for(unsigned j=0;j<curr_size;++j)
+      g_sum += ((uint64_t)((haplotypeBasesArrayVector[i].second)[j]));
+  }
+  for(unsigned i=0;i<readBasesArrayVector.size();++i)
+  {
+    for(unsigned j=0;j<readBasesArrayVector[i].size();++j)
+    {
+      unsigned curr_size = env->GetArrayLength(readBasesArrayVector[i][j].first);
+      for(unsigned k=0;k<curr_size;++k)
+        g_sum += ((uint64_t)((readBasesArrayVector[i][j].second)[k]));
+    }
+  }
+#endif
+#ifdef DO_PROFILING
+  g_load_time_initializer.m_bytes_copied += (is_copy ? numTestCases*sizeof(double) : 0);
+  get_time(&start_time);
+#endif
+  compute_testcases(tc_array, numTestCases, likelihoodDoubleArray, maxNumThreadsToUse); //actual computation
+#ifdef DO_PROFILING
+  g_load_time_initializer.m_compute_time += diff_time(start_time);
+#endif
+#ifdef DUMP_COMPUTE_VALUES
+  for(unsigned tc_idx=0;tc_idx<numTestCases;++tc_idx)
+    g_load_time_initializer.debug_dump("return_values_jni.txt",to_string(likelihoodDoubleArray[tc_idx]),true);
+#endif
+#ifdef DO_PROFILING
+  get_time(&start_time);
+#endif
+  RELEASE_DOUBLE_ARRAY_ELEMENTS(likelihoodArray, likelihoodDoubleArray, 0); //release mode 0, copy back results to Java memory (if copy made)
+  Java_org_broadinstitute_gatk_utils_pairhmm_VectorLoglessPairHMM_jniReleaseReadArrays(env, readBasesArrayVector);
+#ifndef SINGLE_THREADED_ONLY
+  releaseHaplotypes(env, thisObject, haplotypeBasesArrayVector, haplotypeBasesLengths);
+#endif
+
+#ifdef DO_PROFILING
+  g_load_time_initializer.m_data_transfer_time += diff_time(start_time);
+  g_load_time_initializer.update_stat(NUM_REGIONS_IDX, 1);
+  g_load_time_initializer.update_stat(NUM_READS_IDX, numReads);
+  g_load_time_initializer.update_stat(NUM_HAPLOTYPES_IDX, numHaplotypes);
+  g_load_time_initializer.update_stat(NUM_TESTCASES_IDX, numTestCases);
+#endif
+  tc_array.clear();
+#ifdef DUMP_TO_SANDBOX
+  g_load_time_initializer.close_sandbox();
+#endif
+}
+
+//If single threaded, release haplotypes at the end of a region
+JNIEXPORT void JNICALL Java_org_broadinstitute_gatk_utils_pairhmm_VectorLoglessPairHMM_jniFinalizeRegion
+  (JNIEnv * env, jobject thisObject)
+{
+#ifdef SINGLE_THREADED_ONLY
+  releaseHaplotypes(env, thisObject, g_haplotypeBasesArrayVector, g_haplotypeBasesLengths);
+#endif
+}
+
+
+JNIEXPORT void JNICALL Java_org_broadinstitute_gatk_utils_pairhmm_VectorLoglessPairHMM_jniClose
+  (JNIEnv* env, jobject thisObject)
+{
+#ifdef DO_PROFILING
+  g_load_time_initializer.print_profiling();
+#endif
+#ifdef DUMP_COMPUTE_VALUES
+  g_load_time_initializer.debug_close();
+#endif
+}
+
diff --git a/public/VectorPairHMM/src/main/c++/org_broadinstitute_gatk_utils_pairhmm_VectorLoglessPairHMM.h b/public/VectorPairHMM/src/main/c++/org_broadinstitute_gatk_utils_pairhmm_VectorLoglessPairHMM.h
new file mode 100644
index 0000000..6172da5
--- /dev/null
+++ b/public/VectorPairHMM/src/main/c++/org_broadinstitute_gatk_utils_pairhmm_VectorLoglessPairHMM.h
@@ -0,0 +1,96 @@
+/*Copyright (c) 2012 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.
+*/
+
+
+/* DO NOT EDIT THIS FILE - it is machine generated */
+#include <jni.h>
+/* Header for class org_broadinstitute_gatk_utils_pairhmm_VectorLoglessPairHMM */
+
+#ifndef _Included_org_broadinstitute_gatk_utils_pairhmm_VectorLoglessPairHMM
+#define _Included_org_broadinstitute_gatk_utils_pairhmm_VectorLoglessPairHMM
+#ifdef __cplusplus
+extern "C" {
+#endif
+#undef org_broadinstitute_gatk_utils_pairhmm_VectorLoglessPairHMM_TRISTATE_CORRECTION
+#define org_broadinstitute_gatk_utils_pairhmm_VectorLoglessPairHMM_TRISTATE_CORRECTION 3.0
+#undef org_broadinstitute_gatk_utils_pairhmm_VectorLoglessPairHMM_sse41Mask
+#define org_broadinstitute_gatk_utils_pairhmm_VectorLoglessPairHMM_sse41Mask 1LL
+#undef org_broadinstitute_gatk_utils_pairhmm_VectorLoglessPairHMM_sse42Mask
+#define org_broadinstitute_gatk_utils_pairhmm_VectorLoglessPairHMM_sse42Mask 2LL
+#undef org_broadinstitute_gatk_utils_pairhmm_VectorLoglessPairHMM_avxMask
+#define org_broadinstitute_gatk_utils_pairhmm_VectorLoglessPairHMM_avxMask 4LL
+#undef org_broadinstitute_gatk_utils_pairhmm_VectorLoglessPairHMM_enableAll
+#define org_broadinstitute_gatk_utils_pairhmm_VectorLoglessPairHMM_enableAll -1LL
+/*
+ * Class:     org_broadinstitute_gatk_utils_pairhmm_VectorLoglessPairHMM
+ * Method:    jniGetMachineType
+ * Signature: ()J
+ */
+JNIEXPORT jlong JNICALL Java_org_broadinstitute_gatk_utils_pairhmm_VectorLoglessPairHMM_jniGetMachineType
+  (JNIEnv *, jobject);
+
+/*
+ * Class:     org_broadinstitute_gatk_utils_pairhmm_VectorLoglessPairHMM
+ * Method:    jniInitializeClassFieldsAndMachineMask
+ * Signature: (Ljava/lang/Class;Ljava/lang/Class;J)V
+ */
+JNIEXPORT void JNICALL Java_org_broadinstitute_gatk_utils_pairhmm_VectorLoglessPairHMM_jniInitializeClassFieldsAndMachineMask
+  (JNIEnv *, jobject, jclass, jclass, jlong);
+
+/*
+ * Class:     org_broadinstitute_gatk_utils_pairhmm_VectorLoglessPairHMM
+ * Method:    jniInitializeHaplotypes
+ * Signature: (I[Lorg/broadinstitute/gatk/utils/pairhmm/VectorLoglessPairHMM/JNIHaplotypeDataHolderClass;)V
+ */
+JNIEXPORT void JNICALL Java_org_broadinstitute_gatk_utils_pairhmm_VectorLoglessPairHMM_jniInitializeHaplotypes
+  (JNIEnv *, jobject, jint, jobjectArray);
+
+/*
+ * Class:     org_broadinstitute_gatk_utils_pairhmm_VectorLoglessPairHMM
+ * Method:    jniFinalizeRegion
+ * Signature: ()V
+ */
+JNIEXPORT void JNICALL Java_org_broadinstitute_gatk_utils_pairhmm_VectorLoglessPairHMM_jniFinalizeRegion
+  (JNIEnv *, jobject);
+
+/*
+ * Class:     org_broadinstitute_gatk_utils_pairhmm_VectorLoglessPairHMM
+ * Method:    jniComputeLikelihoods
+ * Signature: (II[Lorg/broadinstitute/gatk/utils/pairhmm/VectorLoglessPairHMM/JNIReadDataHolderClass;[Lorg/broadinstitute/gatk/utils/pairhmm/VectorLoglessPairHMM/JNIHaplotypeDataHolderClass;[DI)V
+ */
+JNIEXPORT void JNICALL Java_org_broadinstitute_gatk_utils_pairhmm_VectorLoglessPairHMM_jniComputeLikelihoods
+  (JNIEnv *, jobject, jint, jint, jobjectArray, jobjectArray, jdoubleArray, jint);
+
+/*
+ * Class:     org_broadinstitute_gatk_utils_pairhmm_VectorLoglessPairHMM
+ * Method:    jniClose
+ * Signature: ()V
+ */
+JNIEXPORT void JNICALL Java_org_broadinstitute_gatk_utils_pairhmm_VectorLoglessPairHMM_jniClose
+  (JNIEnv *, jobject);
+
+#ifdef __cplusplus
+}
+#endif
+#endif
diff --git a/public/VectorPairHMM/src/main/c++/pairhmm-1-base.cc b/public/VectorPairHMM/src/main/c++/pairhmm-1-base.cc
new file mode 100644
index 0000000..20e9910
--- /dev/null
+++ b/public/VectorPairHMM/src/main/c++/pairhmm-1-base.cc
@@ -0,0 +1,65 @@
+/*Copyright (c) 2012 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.
+*/
+
+#include "headers.h"
+#include "utils.h"
+#include "LoadTimeInitializer.h"
+using namespace std;
+
+int main(int argc, char** argv)
+{
+  if(argc < 2)
+  {
+    cerr << "Needs path to input file as argument\n";
+    exit(0);
+  }
+  bool use_old_read_testcase = false;
+  if(argc >= 3 && string(argv[2]) == "1")
+    use_old_read_testcase = true;
+  unsigned chunk_size = 10000;
+  bool do_check = true;
+  uint64_t mask = ~(0ull);
+  for(int i=3;i<argc;++i)
+  {
+    if(strncmp(argv[i], "-chunk_size", 15) == 0)
+    {
+      ++i;
+      chunk_size = strtol(argv[i],0,10);
+    }
+    else
+      if(strncmp(argv[i], "-mask", 15) == 0)
+      {
+        ++i;
+        mask = strtoll(argv[i],0,16);
+      }
+      else
+        if(strncmp(argv[i], "-no-check", 15) == 0)
+          do_check = false;
+  }
+  if(mask != (~0ull))
+    initialize_function_pointers(mask);
+  do_compute(argv[1], use_old_read_testcase, chunk_size, do_check); 
+  return 0;  
+}
+
diff --git a/public/VectorPairHMM/src/main/c++/pairhmm-template-kernel.cc b/public/VectorPairHMM/src/main/c++/pairhmm-template-kernel.cc
new file mode 100644
index 0000000..8c62b3c
--- /dev/null
+++ b/public/VectorPairHMM/src/main/c++/pairhmm-template-kernel.cc
@@ -0,0 +1,380 @@
+/*Copyright (c) 2012 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.
+*/
+
+
+#ifdef PRECISION
+
+#include <stdint.h>
+#include <assert.h>
+#include <stdlib.h>
+
+
+void CONCAT(CONCAT(precompute_masks_,SIMD_ENGINE), PRECISION)(const testcase& tc, int COLS, int numMaskVecs, MASK_TYPE (*maskArr)[NUM_DISTINCT_CHARS]) {
+
+    const int maskBitCnt = MAIN_TYPE_SIZE ;
+
+    for (int vi=0; vi < numMaskVecs; ++vi) {
+        for (int rs=0; rs < NUM_DISTINCT_CHARS; ++rs) {
+            maskArr[vi][rs] = 0 ;
+        }
+        maskArr[vi][AMBIG_CHAR] = MASK_ALL_ONES ;
+    }
+
+    for (int col=1; col < COLS; ++col) {
+        int mIndex = (col-1) / maskBitCnt ;
+        int mOffset = (col-1) % maskBitCnt ;
+        MASK_TYPE bitMask = ((MASK_TYPE)0x1) << (maskBitCnt-1-mOffset) ;
+
+        char hapChar = ConvertChar::get(tc.hap[col-1]);
+
+        if (hapChar == AMBIG_CHAR) {
+            for (int ci=0; ci < NUM_DISTINCT_CHARS; ++ci)
+                maskArr[mIndex][ci] |= bitMask ;
+        }
+
+        maskArr[mIndex][hapChar] |= bitMask ;
+        // bit corresponding to col 1 will be the MSB of the mask 0
+        // bit corresponding to col 2 will be the MSB-1 of the mask 0
+        // ...
+        // bit corresponding to col 32 will be the LSB of the mask 0
+        // bit corresponding to col 33 will be the MSB of the mask 1
+        // ...
+    }
+
+}
+
+void CONCAT(CONCAT(init_masks_for_row_,SIMD_ENGINE), PRECISION)(const testcase& tc, char* rsArr, MASK_TYPE* lastMaskShiftOut, int beginRowIndex, int numRowsToProcess) {
+
+    for (int ri=0; ri < numRowsToProcess; ++ri) {
+        rsArr[ri] = ConvertChar::get(tc.rs[ri+beginRowIndex-1]) ;
+    }
+
+    for (int ei=0; ei < AVX_LENGTH; ++ei) {
+        lastMaskShiftOut[ei] = 0 ;
+    }
+}
+
+#define SET_MASK_WORD(__dstMask, __srcMask, __lastShiftOut, __shiftBy, __maskBitCnt){ \
+    MASK_TYPE __bitMask = (((MASK_TYPE)0x1) << __shiftBy) - 1 ;            \
+    MASK_TYPE __nextShiftOut = (__srcMask & __bitMask) << (__maskBitCnt - __shiftBy) ; \
+    __dstMask = (__srcMask >> __shiftBy) | __lastShiftOut ;        \
+    __lastShiftOut = __nextShiftOut ;                    \
+}
+
+
+void CONCAT(CONCAT(update_masks_for_cols_,SIMD_ENGINE), PRECISION)(int maskIndex, BITMASK_VEC& bitMaskVec, MASK_TYPE (*maskArr) [NUM_DISTINCT_CHARS], char* rsArr, MASK_TYPE* lastMaskShiftOut, int maskBitCnt) {
+
+    for (int ei=0; ei < AVX_LENGTH/2; ++ei) {
+        SET_MASK_WORD(bitMaskVec.getLowEntry(ei), maskArr[maskIndex][rsArr[ei]],
+                lastMaskShiftOut[ei], ei, maskBitCnt) ;
+
+        int ei2 = ei + AVX_LENGTH/2 ; // the second entry index
+        SET_MASK_WORD(bitMaskVec.getHighEntry(ei), maskArr[maskIndex][rsArr[ei2]],
+                lastMaskShiftOut[ei2], ei2, maskBitCnt) ;
+    }
+
+}
+
+
+inline void CONCAT(CONCAT(computeDistVec,SIMD_ENGINE), PRECISION) (BITMASK_VEC& bitMaskVec, SIMD_TYPE& distm, SIMD_TYPE& _1_distm, SIMD_TYPE& distmChosen) {
+
+    distmChosen = VEC_BLENDV(distm, _1_distm, bitMaskVec.getCombinedMask()) ;
+
+    bitMaskVec.shift_left_1bit() ;
+}
+
+/*
+ * This function:
+ * 1- Intializes probability values p_MM, p_XX, P_YY, p_MX, p_GAPM and pack them into vectors (SSE or AVX)
+ * 2- Precompute parts of "distm" which only depeneds on a row number and pack it into vector
+ */
+ 
+template<class NUMBER> void CONCAT(CONCAT(initializeVectors,SIMD_ENGINE), PRECISION)(int ROWS, int COLS, NUMBER* shiftOutM, NUMBER *shiftOutX, NUMBER *shiftOutY, Context<NUMBER> ctx, testcase *tc,  SIMD_TYPE *p_MM, SIMD_TYPE *p_GAPM, SIMD_TYPE *p_MX, SIMD_TYPE *p_XX, SIMD_TYPE *p_MY, SIMD_TYPE *p_YY, SIMD_TYPE *distm1D)
+{
+    NUMBER zero = ctx._(0.0);
+    NUMBER init_Y = ctx.INITIAL_CONSTANT / (tc->haplen);
+    for (int s=0;s<ROWS+COLS+AVX_LENGTH;s++)
+    {
+        shiftOutM[s] = zero;
+        shiftOutX[s] = zero;
+        shiftOutY[s] = init_Y;
+    }
+
+    NUMBER *ptr_p_MM = (NUMBER *)p_MM;
+    NUMBER *ptr_p_XX = (NUMBER *)p_XX;
+    NUMBER *ptr_p_YY = (NUMBER *)p_YY;
+    NUMBER *ptr_p_MX = (NUMBER *)p_MX;
+    NUMBER *ptr_p_MY = (NUMBER *)p_MY;
+    NUMBER *ptr_p_GAPM = (NUMBER *)p_GAPM;
+
+    *ptr_p_MM = ctx._(0.0);
+    *ptr_p_XX = ctx._(0.0);
+    *ptr_p_YY = ctx._(0.0);
+    *ptr_p_MX = ctx._(0.0);
+    *ptr_p_MY = ctx._(0.0);
+    *ptr_p_GAPM = ctx._(0.0);
+
+    for (int r = 1; r < ROWS; r++)
+    {
+        int _i = tc->i[r-1] & 127;
+        int _d = tc->d[r-1] & 127;
+        int _c = tc->c[r-1] & 127;
+
+        //*(ptr_p_MM+r-1) = ctx._(1.0) - ctx.ph2pr[(_i + _d) & 127];
+        SET_MATCH_TO_MATCH_PROB(*(ptr_p_MM+r-1), _i, _d);
+        *(ptr_p_GAPM+r-1) = ctx._(1.0) - ctx.ph2pr[_c];
+        *(ptr_p_MX+r-1) = ctx.ph2pr[_i];
+        *(ptr_p_XX+r-1) = ctx.ph2pr[_c];
+        *(ptr_p_MY+r-1) = ctx.ph2pr[_d];
+        *(ptr_p_YY+r-1) = ctx.ph2pr[_c];
+    }
+
+    NUMBER *ptr_distm1D = (NUMBER *)distm1D;
+    for (int r = 1; r < ROWS; r++)
+    {
+        int _q = tc->q[r-1] & 127;
+        ptr_distm1D[r-1] = ctx.ph2pr[_q];
+    }
+}
+
+/*
+ * This function handles pre-stripe computation:
+ * 1- Retrieve probaility vectors from memory 
+ * 2- Initialize M, X, Y vectors with all 0's (for the first stripe) and shifting the last row from previous stripe for the rest 
+ */
+
+template<class NUMBER> inline void CONCAT(CONCAT(stripeINITIALIZATION,SIMD_ENGINE), PRECISION)(
+        int stripeIdx, Context<NUMBER> ctx, testcase *tc, SIMD_TYPE &pGAPM, SIMD_TYPE &pMM, SIMD_TYPE &pMX, SIMD_TYPE &pXX, SIMD_TYPE &pMY, SIMD_TYPE &pYY,
+        SIMD_TYPE &rs, UNION_TYPE &rsN, SIMD_TYPE &distm, SIMD_TYPE &_1_distm,  SIMD_TYPE *distm1D, SIMD_TYPE N_packed256, SIMD_TYPE *p_MM , SIMD_TYPE *p_GAPM ,
+        SIMD_TYPE *p_MX, SIMD_TYPE *p_XX , SIMD_TYPE *p_MY, SIMD_TYPE *p_YY, UNION_TYPE &M_t_2, UNION_TYPE &X_t_2, UNION_TYPE &M_t_1, UNION_TYPE &X_t_1,
+        UNION_TYPE &Y_t_2, UNION_TYPE &Y_t_1, UNION_TYPE &M_t_1_y, NUMBER* shiftOutX, NUMBER* shiftOutM)
+{
+    int i = stripeIdx;
+    pGAPM = p_GAPM[i];
+    pMM   = p_MM[i];
+    pMX   = p_MX[i];
+    pXX   = p_XX[i];
+    pMY   = p_MY[i];
+    pYY   = p_YY[i];
+
+    NUMBER zero = ctx._(0.0);
+    NUMBER init_Y = ctx.INITIAL_CONSTANT / (tc->haplen);
+    UNION_TYPE packed1;  packed1.d = VEC_SET1_VAL(1.0);
+    UNION_TYPE packed3;  packed3.d = VEC_SET1_VAL(3.0);
+
+    distm = distm1D[i];
+    _1_distm = VEC_SUB(packed1.d, distm);
+
+    distm = VEC_DIV(distm, packed3.d);
+
+    /* initialize M_t_2, M_t_1, X_t_2, X_t_1, Y_t_2, Y_t_1 */
+    M_t_2.d = VEC_SET1_VAL(zero);
+    X_t_2.d = VEC_SET1_VAL(zero);
+
+    if (i==0) {
+        M_t_1.d = VEC_SET1_VAL(zero);
+        X_t_1.d = VEC_SET1_VAL(zero);
+        Y_t_2.d = VEC_SET_LSE(init_Y);
+        Y_t_1.d = VEC_SET1_VAL(zero);
+    }
+    else {
+        X_t_1.d = VEC_SET_LSE(shiftOutX[AVX_LENGTH]);
+        M_t_1.d = VEC_SET_LSE(shiftOutM[AVX_LENGTH]);
+        Y_t_2.d = VEC_SET1_VAL(zero);
+        Y_t_1.d = VEC_SET1_VAL(zero);
+    }
+    M_t_1_y = M_t_1;
+}
+
+/*
+ *  This function is the main compute kernel to compute M, X and Y
+ */
+
+inline void CONCAT(CONCAT(computeMXY,SIMD_ENGINE), PRECISION)(UNION_TYPE &M_t, UNION_TYPE &X_t, UNION_TYPE &Y_t, UNION_TYPE &M_t_y,
+        UNION_TYPE M_t_2, UNION_TYPE X_t_2, UNION_TYPE Y_t_2, UNION_TYPE M_t_1, UNION_TYPE X_t_1, UNION_TYPE M_t_1_y, UNION_TYPE Y_t_1,
+        SIMD_TYPE pMM, SIMD_TYPE pGAPM, SIMD_TYPE pMX, SIMD_TYPE pXX, SIMD_TYPE pMY, SIMD_TYPE pYY, SIMD_TYPE distmSel)
+{
+    /* Compute M_t <= distm * (p_MM*M_t_2 + p_GAPM*X_t_2 + p_GAPM*Y_t_2) */
+    M_t.d = VEC_MUL(VEC_ADD(VEC_ADD(VEC_MUL(M_t_2.d, pMM), VEC_MUL(X_t_2.d, pGAPM)), VEC_MUL(Y_t_2.d, pGAPM)), distmSel);
+    //M_t.d = VEC_MUL( VEC_ADD(VEC_MUL(M_t_2.d, pMM), VEC_MUL(VEC_ADD(X_t_2.d, Y_t_2.d), pGAPM)), distmSel);
+
+    M_t_y = M_t;
+
+    /* Compute X_t */
+    X_t.d = VEC_ADD(VEC_MUL(M_t_1.d, pMX) , VEC_MUL(X_t_1.d, pXX));
+
+    /* Compute Y_t */
+    Y_t.d = VEC_ADD(VEC_MUL(M_t_1_y.d, pMY) , VEC_MUL(Y_t_1.d, pYY));
+}
+
+/*
+ * This is the main compute function. It operates on the matrix in s stripe manner.
+ * The stripe height is determined by the SIMD engine type. 
+ * Stripe height: "AVX float": 8, "AVX double": 4, "SSE float": 4, "SSE double": 2
+ * For each stripe the operations are anti-diagonal based. 
+ * Each anti-diagonal (M_t, Y_t, X_t) depends on the two previous anti-diagonals (M_t_2, X_t_2, Y_t_2, M_t_1, X_t_1, Y_t_1).
+ * Each stripe (except the fist one) depends on the last row of the previous stripe.
+ * The last stripe computation handles the addition of the last row of M and X, that's the reason for loop spliting.
+ */
+
+template<class NUMBER> NUMBER CONCAT(CONCAT(compute_full_prob_,SIMD_ENGINE), PRECISION) (testcase *tc, NUMBER *before_last_log = NULL)
+{
+    int ROWS = tc->rslen + 1;
+    int COLS = tc->haplen + 1;
+    int MAVX_COUNT = (ROWS+AVX_LENGTH-1)/AVX_LENGTH;
+
+    /* Probaility arrays */
+    SIMD_TYPE p_MM   [MAVX_COUNT], p_GAPM [MAVX_COUNT], p_MX   [MAVX_COUNT];
+    SIMD_TYPE p_XX   [MAVX_COUNT], p_MY   [MAVX_COUNT], p_YY   [MAVX_COUNT];
+
+    /* For distm precomputation */
+    SIMD_TYPE distm1D[MAVX_COUNT];
+
+    /* Carries the values from each stripe to the next stripe */
+    NUMBER shiftOutM[ROWS+COLS+AVX_LENGTH], shiftOutX[ROWS+COLS+AVX_LENGTH], shiftOutY[ROWS+COLS+AVX_LENGTH];
+
+    /* The vector to keep the anti-diagonals of M, X, Y*/
+    /* Current: M_t, X_t, Y_t */
+    /* Previous: M_t_1, X_t_1, Y_t_1 */
+    /* Previous to previous: M_t_2, X_t_2, Y_t_2 */ 
+    UNION_TYPE  M_t, M_t_1, M_t_2, X_t, X_t_1, X_t_2, Y_t, Y_t_1, Y_t_2, M_t_y, M_t_1_y;
+
+    /* Probality vectors */
+    SIMD_TYPE pGAPM, pMM, pMX, pXX, pMY, pYY;
+
+    struct timeval start, end;
+    NUMBER result_avx2;
+    Context<NUMBER> ctx;
+    UNION_TYPE rs , rsN;
+    HAP_TYPE hap;
+    SIMD_TYPE distmSel, distmChosen ;
+    SIMD_TYPE distm, _1_distm;
+
+    int r, c;
+    NUMBER zero = ctx._(0.0);
+    UNION_TYPE packed1;  packed1.d = VEC_SET1_VAL(1.0);
+    SIMD_TYPE N_packed256 = VEC_POPCVT_CHAR('N');
+    NUMBER init_Y = ctx.INITIAL_CONSTANT / (tc->haplen);
+    int remainingRows = (ROWS-1) % AVX_LENGTH;
+    int stripe_cnt = ((ROWS-1) / AVX_LENGTH) + (remainingRows!=0);
+
+    const int maskBitCnt = MAIN_TYPE_SIZE ;
+    const int numMaskVecs = (COLS+ROWS+maskBitCnt-1)/maskBitCnt ; // ceil function
+
+    /* Mask precomputation for distm*/
+    MASK_TYPE maskArr[numMaskVecs][NUM_DISTINCT_CHARS] ;
+    CONCAT(CONCAT(precompute_masks_,SIMD_ENGINE), PRECISION)(*tc, COLS, numMaskVecs, maskArr) ;
+
+    char rsArr[AVX_LENGTH] ;
+    MASK_TYPE lastMaskShiftOut[AVX_LENGTH] ;
+
+    /* Precompute initialization for probabilities and shift vector*/
+    CONCAT(CONCAT(initializeVectors,SIMD_ENGINE), PRECISION)<NUMBER>(ROWS, COLS, shiftOutM, shiftOutX, shiftOutY,
+            ctx, tc, p_MM, p_GAPM, p_MX, p_XX, p_MY, p_YY, distm1D);
+
+    for (int i=0;i<stripe_cnt-1;i++)
+    {
+        //STRIPE_INITIALIZATION
+        CONCAT(CONCAT(stripeINITIALIZATION,SIMD_ENGINE), PRECISION)(i, ctx, tc, pGAPM, pMM, pMX, pXX, pMY, pYY, rs.d, rsN, distm, _1_distm, distm1D, N_packed256, p_MM , p_GAPM ,
+                p_MX, p_XX , p_MY, p_YY, M_t_2, X_t_2, M_t_1, X_t_1, Y_t_2, Y_t_1, M_t_1_y, shiftOutX, shiftOutM);
+        CONCAT(CONCAT(init_masks_for_row_,SIMD_ENGINE), PRECISION)(*tc, rsArr, lastMaskShiftOut, i*AVX_LENGTH+1, AVX_LENGTH) ;
+        // Since there are no shift intrinsics in AVX, keep the masks in 2 SSE vectors
+
+        BITMASK_VEC bitMaskVec ;
+
+        for (int begin_d=1;begin_d<COLS+AVX_LENGTH;begin_d+=MAIN_TYPE_SIZE)
+        {
+            int numMaskBitsToProcess = std::min(MAIN_TYPE_SIZE, COLS+AVX_LENGTH-begin_d) ;
+            CONCAT(CONCAT(update_masks_for_cols_,SIMD_ENGINE), PRECISION)((begin_d-1)/MAIN_TYPE_SIZE, bitMaskVec, maskArr, rsArr, lastMaskShiftOut, maskBitCnt) ;
+
+            for (int mbi=0; mbi < numMaskBitsToProcess; ++mbi) {
+                CONCAT(CONCAT(computeDistVec,SIMD_ENGINE), PRECISION) (bitMaskVec, distm, _1_distm, distmChosen) ;
+                int ShiftIdx = begin_d + mbi + AVX_LENGTH;
+
+                CONCAT(CONCAT(computeMXY,SIMD_ENGINE), PRECISION)(M_t, X_t, Y_t, M_t_y, M_t_2, X_t_2, Y_t_2, M_t_1, X_t_1, M_t_1_y, Y_t_1,
+                        pMM, pGAPM, pMX, pXX, pMY, pYY, distmChosen);
+
+                CONCAT(CONCAT(_vector_shift,SIMD_ENGINE), PRECISION)(M_t, shiftOutM[ShiftIdx], shiftOutM[begin_d+mbi]);
+
+                CONCAT(CONCAT(_vector_shift,SIMD_ENGINE), PRECISION)(X_t, shiftOutX[ShiftIdx], shiftOutX[begin_d+mbi]);
+
+                CONCAT(CONCAT(_vector_shift,SIMD_ENGINE), PRECISION)(Y_t_1, shiftOutY[ShiftIdx], shiftOutY[begin_d+mbi]);
+
+                M_t_2 = M_t_1; M_t_1 = M_t; X_t_2 = X_t_1; X_t_1 = X_t;
+                Y_t_2 = Y_t_1; Y_t_1 = Y_t; M_t_1_y = M_t_y;
+            }
+        }
+    }
+
+    int i = stripe_cnt-1;
+    {
+        //STRIPE_INITIALIZATION
+        CONCAT(CONCAT(stripeINITIALIZATION,SIMD_ENGINE), PRECISION)(i, ctx, tc, pGAPM, pMM, pMX, pXX, pMY, pYY, rs.d, rsN, distm, _1_distm, distm1D, N_packed256, p_MM , p_GAPM ,
+                p_MX, p_XX , p_MY, p_YY, M_t_2, X_t_2, M_t_1, X_t_1, Y_t_2, Y_t_1, M_t_1_y, shiftOutX, shiftOutM);
+
+        if (remainingRows==0) remainingRows=AVX_LENGTH;
+        CONCAT(CONCAT(init_masks_for_row_,SIMD_ENGINE), PRECISION)(*tc, rsArr, lastMaskShiftOut, i*AVX_LENGTH+1, remainingRows) ;
+
+        SIMD_TYPE sumM, sumX;
+        sumM = VEC_SET1_VAL(zero);
+        sumX = VEC_SET1_VAL(zero);
+
+        // Since there are no shift intrinsics in AVX, keep the masks in 2 SSE vectors
+        BITMASK_VEC bitMaskVec ;
+
+        for (int begin_d=1;begin_d<COLS+remainingRows-1;begin_d+=MAIN_TYPE_SIZE)
+        {
+            int numMaskBitsToProcess = std::min(MAIN_TYPE_SIZE, COLS+remainingRows-1-begin_d) ;
+            CONCAT(CONCAT(update_masks_for_cols_,SIMD_ENGINE),PRECISION)((begin_d-1)/MAIN_TYPE_SIZE, bitMaskVec, maskArr, rsArr, lastMaskShiftOut, maskBitCnt) ;
+
+            for (int mbi=0; mbi < numMaskBitsToProcess; ++mbi) {
+
+                CONCAT(CONCAT(computeDistVec,SIMD_ENGINE), PRECISION) (bitMaskVec, distm, _1_distm, distmChosen) ;
+                int ShiftIdx = begin_d + mbi +AVX_LENGTH;
+
+                CONCAT(CONCAT(computeMXY,SIMD_ENGINE), PRECISION)(M_t, X_t, Y_t, M_t_y, M_t_2, X_t_2, Y_t_2, M_t_1, X_t_1, M_t_1_y, Y_t_1,
+                        pMM, pGAPM, pMX, pXX, pMY, pYY, distmChosen);
+
+                sumM  = VEC_ADD(sumM, M_t.d);
+                CONCAT(CONCAT(_vector_shift_last,SIMD_ENGINE), PRECISION)(M_t, shiftOutM[ShiftIdx]);
+
+                sumX  = VEC_ADD(sumX, X_t.d);
+                CONCAT(CONCAT(_vector_shift_last,SIMD_ENGINE), PRECISION)(X_t, shiftOutX[ShiftIdx]);
+
+                CONCAT(CONCAT(_vector_shift_last,SIMD_ENGINE), PRECISION)(Y_t_1, shiftOutY[ShiftIdx]);
+
+                M_t_2 = M_t_1; M_t_1 = M_t; X_t_2 = X_t_1; X_t_1 = X_t;
+                Y_t_2 = Y_t_1; Y_t_1 = Y_t; M_t_1_y = M_t_y;
+
+            }
+        }
+        UNION_TYPE sumMX;
+        sumMX.d = VEC_ADD(sumM, sumX);
+        result_avx2 = sumMX.f[remainingRows-1];
+    }
+    return result_avx2;
+}
+
+#endif
+
diff --git a/public/VectorPairHMM/src/main/c++/pairhmm-template-main.cc b/public/VectorPairHMM/src/main/c++/pairhmm-template-main.cc
new file mode 100644
index 0000000..4f83046
--- /dev/null
+++ b/public/VectorPairHMM/src/main/c++/pairhmm-template-main.cc
@@ -0,0 +1,113 @@
+/*Copyright (c) 2012 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.
+*/
+
+
+#include "headers.h"
+
+#define SIMD_ENGINE avx
+#define SIMD_ENGINE_AVX
+
+#include "utils.h"
+
+#define BATCH_SIZE  10000
+#define RUN_HYBRID
+
+double getCurrClk();
+int thread_level_parallelism_enabled = false ;
+
+
+int main()
+{
+    testcase* tc = new testcase[BATCH_SIZE];
+    float result[BATCH_SIZE], result_avxf;
+    double result_avxd;
+    double lastClk = 0.0 ;
+    double aggregateTimeRead = 0.0;
+    double aggregateTimeCompute = 0.0;
+    double aggregateTimeWrite = 0.0;
+
+    // Need to call it once to initialize the static array
+    ConvertChar::init() ;
+
+    //      char* ompEnvVar = getenv("OMP_NUM_THREADS") ;
+    //      if (ompEnvVar != NULL && ompEnvVar != "" && ompEnvVar != "1" ) {
+    //        thread_level_parallelism_enabled = true ;
+    //      }
+
+    bool noMoreData = false;
+    int count =0;
+    while (!noMoreData)
+    {
+        int read_count = BATCH_SIZE;
+
+        lastClk = getCurrClk() ;
+        for (int b=0;b<BATCH_SIZE;b++)
+            if (read_testcase(&tc[b])==-1)
+            {
+                read_count = b;
+                noMoreData = true;
+                break;
+            }
+        aggregateTimeRead += (getCurrClk() - lastClk) ;
+        lastClk = getCurrClk() ;
+
+        //#pragma omp parallel for schedule(dynamic) if(thread_level_parallelism_enabled)
+        for (int b=0;b<read_count;b++)
+        {
+            result_avxf = CONCAT(CONCAT(compute_full_prob_,SIMD_ENGINE), s)<float>(&tc[b]);
+
+#ifdef RUN_HYBRID
+#define MIN_ACCEPTED 1e-28f
+            if (result_avxf < MIN_ACCEPTED) {
+                count++;
+                result_avxd = CONCAT(CONCAT(compute_full_prob_,SIMD_ENGINE), d)<double>(&tc[b]);
+                result[b] = log10(result_avxd) - log10(ldexp(1.0, 1020.f));
+            }
+            else
+                result[b] = log10f(result_avxf) - log10f(ldexpf(1.f, 120.f));
+#endif
+
+#ifndef RUN_HYBRID
+            result[b] = log10f(result_avxf) - log10f(ldexpf(1.f, 120.f));
+#endif
+        }
+        aggregateTimeCompute += (getCurrClk() - lastClk) ;
+        lastClk = getCurrClk() ;
+        for (int b=0;b<read_count;b++)
+            printf("%E\n", result[b]);
+        aggregateTimeWrite += (getCurrClk() - lastClk) ;
+    }
+
+    delete[] tc;
+    printf("AVX Read Time: %.2f\n", aggregateTimeRead);
+    printf("AVX Compute Time: %.2f\n", aggregateTimeCompute);
+    printf("AVX Write Time: %.2f\n", aggregateTimeWrite);
+    printf("AVX Total Time: %.2f\n", aggregateTimeRead + aggregateTimeCompute + aggregateTimeWrite);
+    printf("# Double called: %d\n", count);
+
+    return 0;
+}
+
+
+
diff --git a/public/VectorPairHMM/src/main/c++/run.sh b/public/VectorPairHMM/src/main/c++/run.sh
new file mode 100755
index 0000000..e821497
--- /dev/null
+++ b/public/VectorPairHMM/src/main/c++/run.sh
@@ -0,0 +1,32 @@
+#!/bin/bash
+rm -f *.txt *.log
+GSA_ROOT_DIR=/home/karthikg/broad/gsa-unstable
+pair_hmm_implementation="VECTOR_LOGLESS_CACHING";
+if [ "$#" -ge 1 ];
+then
+  pair_hmm_implementation=$1;
+fi
+
+#-Djava.library.path is needed if you wish to override the default 'packed' library
+#java -jar $GSA_ROOT_DIR/target/GenomeAnalysisTK.jar   -T HaplotypeCaller \
+java  -Djava.library.path=${GSA_ROOT_DIR}/public/VectorPairHMM/src/main/c++ -jar $GSA_ROOT_DIR/target/GenomeAnalysisTK.jar   -T HaplotypeCaller \
+--dbsnp /data/broad/samples/joint_variant_calling/dbSNP/00-All.vcf \
+-R /opt/Genomics/ohsu/dnapipeline/humanrefgenome/human_g1k_v37.fasta \
+-I /data/simulated/sim1M_pairs_final.bam \
+-stand_call_conf 50.0 \
+-stand_emit_conf 10.0 \
+--pair_hmm_implementation $pair_hmm_implementation \
+-o output.raw.snps.indels.vcf 
+
+#--pair_hmm_implementation JNI_LOGLESS_CACHING \
+#-XL unmapped	\
+#-I /data/simulated/sim1M_pairs_final.bam \
+#-I /data/broad/samples/joint_variant_calling/NA12878_low_coverage_alignment/NA12878.chrom11.ILLUMINA.bwa.CEU.low_coverage.20121211.bam \
+#-I /data/broad/samples/joint_variant_calling/NA12878_high_coverage_alignment/NA12878.mapped.ILLUMINA.bwa.CEU.high_coverage_pcr_free.20130906.bam \
+#-R /data/broad/samples/joint_variant_calling/broad_reference/Homo_sapiens_assembly18.fasta \
+#-R /data/broad/samples/joint_variant_calling/broad_reference/Homo_sapiens_assembly19.fasta \
+#-R /data/broad/samples/joint_variant_calling/broad_reference/ucsc.hg19.fasta \
+#-R /opt/Genomics/ohsu/dnapipeline/humanrefgenome/human_g1k_v37.fasta \
+#-R /data/broad/samples/joint_variant_calling/broad_reference/human_g1k_v37_decoy.fasta \
+#--dbsnp /data/broad/samples/joint_variant_calling/dbSNP/00-All.vcf \
+#--dbsnp /data/broad/samples/joint_variant_calling/dbSNP/dbsnp_138.hg19.vcf \
diff --git a/public/VectorPairHMM/src/main/c++/shift_template.c b/public/VectorPairHMM/src/main/c++/shift_template.c
new file mode 100644
index 0000000..c591c68
--- /dev/null
+++ b/public/VectorPairHMM/src/main/c++/shift_template.c
@@ -0,0 +1,113 @@
+/*Copyright (c) 2012 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.
+*/
+
+
+#ifdef PRECISION
+
+#ifdef SIMD_ENGINE_AVX
+
+inline void CONCAT(CONCAT(_vector_shift,SIMD_ENGINE), PRECISION) (UNION_TYPE &x, MAIN_TYPE shiftIn, MAIN_TYPE &shiftOut)
+{
+    IF_128 xlow , xhigh;
+    /* cast x to xlow */
+    xlow.f = VEC_CAST_256_128(x.d);
+    /* extract x,1 to xhigh */
+    xhigh.f = VEC_EXTRACT_128(x.d, 1);
+    /* extract xlow[3] */
+    IF_128 shiftOutL128;
+    shiftOutL128.i = _mm_srli_si128(xlow.i, SHIFT_CONST1);
+    /* extract xhigh[3] */
+    IF_MAIN_TYPE shiftOutH;
+    shiftOutH.i = VEC_EXTRACT_UNIT(xhigh.i, SHIFT_CONST2);
+    shiftOut = shiftOutH.f;
+    /* shift xlow */
+    xlow.i = _mm_slli_si128 (xlow.i, SHIFT_CONST3);
+    /* shift xhigh */
+    xhigh.i = _mm_slli_si128 (xhigh.i, SHIFT_CONST3);
+    /*movss shiftIn to xlow[0] */
+    _128_TYPE shiftIn128 = VEC_SET1_VAL128(shiftIn);
+    xlow.f = VEC_MOVE(xlow.f , shiftIn128);
+    /*movss xlow[3] to xhigh[0] */
+    xhigh.f = VEC_MOVE(xhigh.f, shiftOutL128.f);
+    /* cast xlow to x */
+    x.d = VEC_CAST_128_256(xlow.f);
+    /* insert xhigh to x,1 */
+    x.d = VEC_INSERT_VAL(x.d, xhigh.f, 1);
+}
+
+
+inline void CONCAT(CONCAT(_vector_shift_last,SIMD_ENGINE), PRECISION) (UNION_TYPE &x, MAIN_TYPE shiftIn)
+{
+    IF_128 xlow , xhigh;
+    /* cast x to xlow */
+    xlow.f = VEC_CAST_256_128(x.d);
+    /* extract x,1 to xhigh */
+    xhigh.f = VEC_EXTRACT_128(x.d, 1);
+    /* extract xlow[3] */
+    IF_128 shiftOutL128;
+    shiftOutL128.i = _mm_srli_si128(xlow.i, SHIFT_CONST1);
+    /* shift xlow */
+    xlow.i = _mm_slli_si128 (xlow.i, SHIFT_CONST3);
+    /* shift xhigh */
+    xhigh.i = _mm_slli_si128 (xhigh.i, SHIFT_CONST3);
+    /*movss shiftIn to xlow[0] */
+    _128_TYPE shiftIn128 = VEC_SET1_VAL128(shiftIn);
+    xlow.f = VEC_MOVE(xlow.f , shiftIn128);
+    /*movss xlow[3] to xhigh[0] */
+    xhigh.f = VEC_MOVE(xhigh.f, shiftOutL128.f);
+    /* cast xlow to x */
+    x.d = VEC_CAST_128_256(xlow.f);
+    /* insert xhigh to x,1 */
+    x.d = VEC_INSERT_VAL(x.d, xhigh.f, 1);
+}
+
+#endif
+
+#ifdef SIMD_ENGINE_SSE
+
+inline void CONCAT(CONCAT(_vector_shift,SIMD_ENGINE), PRECISION) (UNION_TYPE &x, MAIN_TYPE shiftIn, MAIN_TYPE &shiftOut)
+{
+    IF_MAIN_TYPE tempIn, tempOut;
+    tempIn.f = shiftIn;
+    /* extratc H */
+    tempOut.i = VEC_EXTRACT_UNIT(x.i, SHIFT_CONST1);
+    shiftOut = tempOut.f;
+    /* shift     */
+    x.i = _mm_slli_si128(x.i, SHIFT_CONST2);
+    /* insert  L */
+    x.i = VEC_INSERT_UNIT(x.i , tempIn.i, SHIFT_CONST3);
+}
+
+inline void CONCAT(CONCAT(_vector_shift_last,SIMD_ENGINE), PRECISION) (UNION_TYPE &x, MAIN_TYPE shiftIn)
+{
+    IF_MAIN_TYPE temp; temp.f = shiftIn;
+    /* shift     */
+    x.i = _mm_slli_si128(x.i, SHIFT_CONST2);
+    /* insert  L */
+    x.i = VEC_INSERT_UNIT(x.i , temp.i, SHIFT_CONST3);
+}
+
+#endif
+
+#endif
diff --git a/public/VectorPairHMM/src/main/c++/sse_function_instantiations.cc b/public/VectorPairHMM/src/main/c++/sse_function_instantiations.cc
new file mode 100644
index 0000000..a8b88f6
--- /dev/null
+++ b/public/VectorPairHMM/src/main/c++/sse_function_instantiations.cc
@@ -0,0 +1,44 @@
+/*Copyright (c) 2012 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.
+*/
+
+
+
+#undef SIMD_ENGINE
+#undef SIMD_ENGINE_AVX
+
+#define SIMD_ENGINE sse
+#define SIMD_ENGINE_SSE
+
+#include "template.h"
+
+#include "define-sse-float.h"
+#include "shift_template.c"
+#include "pairhmm-template-kernel.cc"
+
+#include "define-sse-double.h"
+#include "shift_template.c"
+#include "pairhmm-template-kernel.cc"
+
+template double compute_full_prob_ssed<double>(testcase* tc, double* nextlog);
+template float compute_full_prob_sses<float>(testcase* tc, float* nextlog);
diff --git a/public/VectorPairHMM/src/main/c++/template.h b/public/VectorPairHMM/src/main/c++/template.h
new file mode 100644
index 0000000..550e763
--- /dev/null
+++ b/public/VectorPairHMM/src/main/c++/template.h
@@ -0,0 +1,119 @@
+/*Copyright (c) 2012 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.
+*/
+
+
+#ifndef TEMPLATES_H_
+#define TEMPLATES_H_
+
+#include "headers.h"
+
+
+#define ALIGNED __attribute__((aligned(32)))
+
+#ifdef SIMD_ENGINE_AVX
+typedef union __attribute__((aligned(32))) {
+        ALIGNED __m256 ALIGNED d;
+        ALIGNED __m128i ALIGNED s[2];
+        ALIGNED float  ALIGNED f[8];
+        ALIGNED __m256i ALIGNED i;
+} ALIGNED mix_F ALIGNED;
+#endif
+
+typedef union __attribute__((aligned(32))) {
+        ALIGNED __m128 ALIGNED d;
+        ALIGNED __m64 ALIGNED s[2];
+        ALIGNED float  ALIGNED f[4];
+        ALIGNED __m128i ALIGNED i;
+} ALIGNED mix_F128 ALIGNED;
+
+typedef union ALIGNED {
+  __m128i vec ;
+  __m128 vecf ;
+  uint32_t masks[4] ;
+} MaskVec_F ;
+
+typedef union ALIGNED {
+  __m64 vec ;
+  __m64 vecf ;
+  uint32_t masks[2] ;
+} MaskVec_F128 ;
+
+typedef union ALIGNED
+{
+        ALIGNED __m128i ALIGNED i;
+        ALIGNED __m128 ALIGNED f;
+} ALIGNED IF_128f ALIGNED;
+
+typedef union ALIGNED
+{
+        ALIGNED int    ALIGNED i;
+        ALIGNED float  ALIGNED f;
+} ALIGNED IF_32 ALIGNED;
+
+#ifdef SIMD_ENGINE_AVX
+typedef union __attribute__((aligned(32))) {
+        ALIGNED __m256d ALIGNED d;
+        ALIGNED __m128i ALIGNED s[2];
+        ALIGNED double  ALIGNED f[4];
+        ALIGNED __m256i ALIGNED i;
+} ALIGNED mix_D ALIGNED;
+#endif
+
+typedef union __attribute__((aligned(32))) {
+        ALIGNED __m128d ALIGNED d;
+        ALIGNED __m64 ALIGNED s[2];
+        ALIGNED double  ALIGNED f[2];
+        ALIGNED __m128i ALIGNED i;
+} ALIGNED mix_D128 ALIGNED;
+
+typedef union ALIGNED {
+  __m128i vec ;
+  __m128d vecf ;
+  uint64_t masks[2] ;
+} MaskVec_D ;
+
+typedef union ALIGNED {
+  __m64 vec ;
+  __m64 vecf ;
+  uint64_t masks[1] ;
+} MaskVec_D128 ;
+
+typedef union ALIGNED
+{
+        ALIGNED __m128i ALIGNED i;
+        ALIGNED __m128d ALIGNED f;
+} ALIGNED IF_128d ALIGNED;
+
+typedef union ALIGNED
+{
+        ALIGNED int64_t ALIGNED i;
+        ALIGNED double  ALIGNED f;
+} ALIGNED IF_64 ALIGNED;
+
+
+#include "common_data_structure.h"
+
+#endif
+
+
diff --git a/public/VectorPairHMM/src/main/c++/utils.cc b/public/VectorPairHMM/src/main/c++/utils.cc
new file mode 100644
index 0000000..3b0ce35
--- /dev/null
+++ b/public/VectorPairHMM/src/main/c++/utils.cc
@@ -0,0 +1,567 @@
+/*Copyright (c) 2012 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.
+*/
+
+#include "headers.h"
+#include "utils.h"
+#include "LoadTimeInitializer.h"
+using namespace std;
+
+//static members from ConvertChar
+uint8_t ConvertChar::conversionTable[255];
+//Global function pointers in utils.h
+float (*g_compute_full_prob_float)(testcase *tc, float* before_last_log) = 0;
+double (*g_compute_full_prob_double)(testcase *tc, double* before_last_log) = 0;
+//Static members in ContextBase
+template<>
+bool ContextBase<double>::staticMembersInitializedFlag = false;
+template<>
+double ContextBase<double>::jacobianLogTable[JACOBIAN_LOG_TABLE_SIZE] = { };
+template<>
+double ContextBase<double>::matchToMatchProb[((MAX_QUAL + 1) * (MAX_QUAL + 2)) >> 1] = { };
+template<>
+bool ContextBase<float>::staticMembersInitializedFlag = false;
+template<>
+float ContextBase<float>::jacobianLogTable[JACOBIAN_LOG_TABLE_SIZE] = { };
+template<>
+float ContextBase<float>::matchToMatchProb[((MAX_QUAL + 1) * (MAX_QUAL + 2)) >> 1] = { };
+
+
+bool search_file_for_string(string filename, string search_string)
+{
+  ifstream fptr;
+  fptr.open(filename.c_str(),ios::in);
+  if(fptr.is_open())
+  {
+    string buffer;
+    buffer.clear();
+    buffer.resize(4096);
+    bool retvalue = false;
+    while(!fptr.eof())
+    {
+      fptr.getline(&(buffer[0]), 4096);
+      if(buffer.find(search_string) != string::npos)    //found string
+      {
+        retvalue = true;
+        break;
+      }
+    }
+    buffer.clear();
+    fptr.close();
+    return retvalue;
+  }
+  else
+    return false;
+}
+
+bool is_cpuid_ecx_bit_set(int eax, int bitidx)
+{
+  int ecx = 0, edx = 0, ebx = 0;
+  __asm__ ("cpuid"
+      :"=b" (ebx),
+      "=c" (ecx),
+      "=d" (edx)
+      :"a" (eax)
+      );
+  return (((ecx >> bitidx)&1) == 1);
+}
+
+bool is_avx_supported()
+{
+#ifdef __INTEL_COMPILER
+  bool use_avx = _may_i_use_cpu_feature(_FEATURE_AVX);
+  if(use_avx)
+    return true;
+  else
+  {
+    //check if core supports AVX, but kernel does not and print info message
+    if(!is_cpuid_ecx_bit_set(1, 28))  //core does not support AVX
+      return false;
+    //else fall through to end of function
+  }
+#else
+  if(!__builtin_cpu_supports("avx"))  //core does not support AVX
+    return false;
+  else
+  {
+    //core supports AVX, check if kernel supports
+    if(search_file_for_string("/proc/cpuinfo","avx"))
+      return true;
+    //else fall through to end of function
+
+  }
+#endif  //__INTEL_COMPILER
+  clog << "INFO: Your CPU supports AVX vector instructions, but your kernel does not. Try upgrading to a kernel that supports AVX.\n";
+  clog << "INFO: Your program will run correctly, but slower than the AVX version\n";
+  return false;
+}
+
+bool is_sse41_supported()
+{
+#ifdef __INTEL_COMPILER
+  return  (_may_i_use_cpu_feature(_FEATURE_SSE4_1) > 0);
+#else
+  return  __builtin_cpu_supports("sse4.1");
+#endif
+  //return is_cpuid_ecx_bit_set(1, 19);
+}
+
+bool is_sse42_supported()
+{
+#ifdef __INTEL_COMPILER
+  return  (_may_i_use_cpu_feature(_FEATURE_SSE4_2) > 0);
+#else
+  return  __builtin_cpu_supports("sse4.2");
+#endif
+  //return is_cpuid_ecx_bit_set(1, 20);
+}
+
+uint64_t get_machine_capabilities()
+{
+  uint64_t machine_mask = 0ull;
+  if(is_avx_supported())
+    machine_mask |= (1 << AVX_CUSTOM_IDX);
+  if(is_sse42_supported())
+    machine_mask |= (1 << SSE42_CUSTOM_IDX);
+  if(is_sse41_supported())
+    machine_mask |= (1 << SSE41_CUSTOM_IDX);
+  return machine_mask;
+}
+
+void initialize_function_pointers(uint64_t mask)
+{
+  //mask = 0ull;
+  //mask = (1 << SSE41_CUSTOM_IDX);
+  if(is_avx_supported() && (mask & (1<< AVX_CUSTOM_IDX)))
+  {
+    cout << "Using AVX accelerated implementation of PairHMM\n";
+    g_compute_full_prob_float = compute_full_prob_avxs<float>;
+    g_compute_full_prob_double = compute_full_prob_avxd<double>;
+  }
+  else
+    if(is_sse41_supported() && (mask & ((1<< SSE41_CUSTOM_IDX) | (1<<SSE42_CUSTOM_IDX))))
+    {
+      cout << "Using SSE4.1 accelerated implementation of PairHMM\n";
+      g_compute_full_prob_float = compute_full_prob_sses<float>;
+      g_compute_full_prob_double = compute_full_prob_ssed<double>;
+    }
+    else
+    {
+      cout << "Using un-vectorized C++ implementation of PairHMM\n";
+      g_compute_full_prob_float = compute_full_prob<float>;
+      g_compute_full_prob_double = compute_full_prob<double>;
+    }
+}
+
+int normalize(char c)
+{
+	return ((int) (c - 33));
+}
+
+int read_testcase(testcase *tc, FILE* ifp)
+{
+	char *q, *i, *d, *c, *line = NULL;
+	int _q, _i, _d, _c;
+	int x, size = 0;
+	ssize_t read;
+
+
+        read = getline(&line, (size_t *) &size, ifp == 0 ? stdin : ifp);
+	if (read == -1)
+        {
+          free(line);
+          return -1;
+        }
+
+
+	tc->hap = (char *) malloc(size);
+	tc->rs = (char *) malloc(size);
+	q = (char *) malloc(size);
+	i = (char *) malloc(size);
+	d = (char *) malloc(size);
+	c = (char *) malloc(size);
+
+	if (sscanf(line, "%s %s %s %s %s %s\n", tc->hap, tc->rs, q, i, d, c) != 6)
+		return -1;
+
+
+	tc->haplen = strlen(tc->hap);
+	tc->rslen = strlen(tc->rs);
+        assert(strlen(q) == (size_t)tc->rslen);
+        assert(strlen(i) == (size_t)tc->rslen);
+        assert(strlen(d) == (size_t)tc->rslen);
+        assert(strlen(c) == (size_t)tc->rslen);
+
+        g_load_time_initializer.update_stat(READ_LENGTH_IDX, tc->rslen); 
+        g_load_time_initializer.update_stat(HAPLOTYPE_LENGTH_IDX, tc->haplen);
+        g_load_time_initializer.update_stat(PRODUCT_READ_LENGTH_HAPLOTYPE_LENGTH_IDX, tc->haplen*tc->rslen);
+	//assert(tc->rslen < MROWS);
+        //tc->ihap = (int *) malloc(tc->haplen*sizeof(int));
+        //tc->irs = (int *) malloc(tc->rslen*sizeof(int));
+
+	tc->q = (char *) malloc(sizeof(char) * tc->rslen);
+	tc->i = (char *) malloc(sizeof(char) * tc->rslen);
+	tc->d = (char *) malloc(sizeof(char) * tc->rslen);
+	tc->c = (char *) malloc(sizeof(char) * tc->rslen);
+
+	for (x = 0; x < tc->rslen; x++)
+	{
+		_q = normalize(q[x]);
+		_i = normalize(i[x]);
+		_d = normalize(d[x]);
+		_c = normalize(c[x]);
+                tc->q[x] = (_q < 6) ? 6 : _q;
+                //tc->q[x] = _q;
+		tc->i[x] = _i;
+		tc->d[x] = _d;
+		tc->c[x] = _c;
+                //tc->irs[x] = tc->rs[x];
+	}
+        //for (x = 0; x < tc->haplen; x++)
+        //tc->ihap[x] = tc->hap[x];
+        
+	free(q);
+	free(i);
+	free(d);
+	free(c);
+	free(line);
+
+
+
+	return 0;
+}
+
+unsigned MAX_LINE_LENGTH = 65536;
+int convToInt(std::string s)
+{
+  int i;
+  std::istringstream strin(s);
+  strin >> i;
+  return i;
+}
+
+void tokenize(std::ifstream& fptr, std::vector<std::string>& tokens)
+{
+  int i = 0;
+  std::string tmp;
+  std::vector<std::string> myVec;
+  vector<char> line;
+  line.clear();
+  line.resize(MAX_LINE_LENGTH);
+  vector<char> tmpline;
+  tmpline.clear();
+  tmpline.resize(MAX_LINE_LENGTH);
+  myVec.clear();
+
+  while(!fptr.eof())
+  {
+    i = 0;
+    bool still_read_line = true;
+    unsigned line_position = 0;
+    while(still_read_line)
+    {
+      fptr.getline(&(tmpline[0]), MAX_LINE_LENGTH);
+      if(line_position + MAX_LINE_LENGTH > line.size())
+	line.resize(2*line.size());
+      for(unsigned i=0;i<MAX_LINE_LENGTH && tmpline[i] != '\0';++i,++line_position)
+	line[line_position] = tmpline[i];
+      if(fptr.eof() || !fptr.fail()) 
+      {
+	still_read_line = false;
+	line[line_position++] = '\0';
+      }
+    }
+    std::istringstream kap(&(line[0]));
+
+    while(!kap.eof())
+    {
+      kap >> std::skipws >> tmp;
+      if(tmp != "")
+      {
+	myVec.push_back(tmp);
+	++i;
+	//std::cout <<tmp <<"#";
+      }
+      tmp = "";
+    }
+    //std::cout << "\n";
+    if(myVec.size() > 0)
+      break;
+  }
+  tokens.clear();
+  //std::cout << "Why "<<myVec.size()<<"\n";
+  tokens.resize(myVec.size());
+  for(i=0;i<(int)myVec.size();++i)
+    tokens[i] = myVec[i];
+  line.clear();
+  tmpline.clear();
+}
+
+int read_mod_testcase(ifstream& fptr, testcase* tc, bool reformat)
+{
+  static bool first_call = true;
+  vector<string> tokens;
+  tokens.clear();
+  tokenize(fptr, tokens);
+  if(tokens.size() == 0)
+    return -1;
+  tc->hap = new char[tokens[0].size()+2];
+  tc->haplen = tokens[0].size();
+  memcpy(tc->hap, tokens[0].c_str(), tokens[0].size());
+  tc->rs = new char[tokens[1].size()+2];
+  tc->rslen = tokens[1].size();
+  tc->q = new char[tc->rslen];
+  tc->i = new char[tc->rslen];
+  tc->d = new char[tc->rslen];
+  tc->c = new char[tc->rslen];
+  //cout << "Lengths "<<tc->haplen <<" "<<tc->rslen<<"\n";
+  memcpy(tc->rs, tokens[1].c_str(),tokens[1].size());
+  assert(tokens.size() == (size_t)(2 + 4*(tc->rslen)));
+  //assert(tc->rslen < MROWS);
+  for(int j=0;j<tc->rslen;++j)
+    tc->q[j] = (char)convToInt(tokens[2+0*tc->rslen+j]);
+  for(int j=0;j<tc->rslen;++j)
+    tc->i[j] = (char)convToInt(tokens[2+1*tc->rslen+j]);
+  for(int j=0;j<tc->rslen;++j)
+    tc->d[j] = (char)convToInt(tokens[2+2*tc->rslen+j]);
+  for(int j=0;j<tc->rslen;++j)
+    tc->c[j] = (char)convToInt(tokens[2+3*tc->rslen+j]);
+ 
+  if(reformat)
+  {
+    ofstream ofptr;
+    ofptr.open("reformat/debug_dump.txt",first_call ? ios::out : ios::app);
+    assert(ofptr.is_open());
+    ofptr << tokens[0] << " ";
+    ofptr << tokens[1] << " ";
+    for(int j=0;j<tc->rslen;++j)
+      ofptr << ((char)(tc->q[j]+33));
+    ofptr << " ";
+    for(int j=0;j<tc->rslen;++j)
+      ofptr << ((char)(tc->i[j]+33));
+    ofptr << " ";
+    for(int j=0;j<tc->rslen;++j)
+      ofptr << ((char)(tc->d[j]+33));
+    ofptr << " ";
+    for(int j=0;j<tc->rslen;++j)
+      ofptr << ((char)(tc->c[j]+33));
+    ofptr << " 0 false\n";
+
+    ofptr.close();
+    first_call = false;
+  }
+
+
+  return tokens.size();
+}
+
+double getCurrClk() {
+  struct timeval tv ;
+  gettimeofday(&tv, NULL);
+  return (double)tv.tv_sec + (double)tv.tv_usec / 1000000.0;
+}
+
+inline unsigned long long rdtsc(void)
+{
+  unsigned hi, lo;
+  __asm__ __volatile__ ("rdtsc" : "=a"(lo), "=d"(hi));
+  return ( (unsigned long long)lo)|( ((unsigned long long)hi)<<32 );
+}
+
+void get_time(struct timespec* store_struct)
+{
+  clock_gettime(CLOCK_REALTIME, store_struct);
+}
+
+uint64_t diff_time(struct timespec& prev_time)
+{
+  struct timespec curr_time;
+  clock_gettime(CLOCK_REALTIME, &curr_time);
+  return (uint64_t)((curr_time.tv_sec-prev_time.tv_sec)*1000000000+(curr_time.tv_nsec-prev_time.tv_nsec));
+}
+
+
+#ifdef USE_PAPI
+#include "papi.h"
+#define NUM_PAPI_COUNTERS 4
+#endif
+
+void do_compute(char* filename, bool use_old_read_testcase, unsigned chunk_size, bool do_check)
+{
+  FILE* fptr = 0;
+  ifstream ifptr;
+  if(use_old_read_testcase)
+  {
+    fptr = fopen(filename,"r");
+    assert(fptr);
+  }
+  else
+  {
+    ifptr.open(filename);
+    assert(ifptr.is_open());
+  }
+#ifdef PRINT_PER_INTERVAL_TIMINGS
+  ofstream times_fptr;
+  times_fptr.open("native_timed_intervals.csv",ios::out);
+#endif
+  vector<testcase> tc_vector;
+  tc_vector.clear();
+  testcase tc;
+  uint64_t vector_compute_time = 0;
+  uint64_t baseline_compute_time = 0;
+  uint64_t num_double_calls = 0;
+  unsigned num_testcases = 0;
+  bool all_ok = do_check ? true : false;
+#ifdef USE_PAPI
+  uint32_t all_mask = (0);
+  uint32_t no_usr_mask = (1 << 16);    //bit 16 user mode, bit 17 kernel mode
+  uint32_t no_kernel_mask = (1 << 17);    //bit 16 user mode, bit 17 kernel mode
+  PAPI_num_counters();
+  int events[NUM_PAPI_COUNTERS] = { 0, 0, 0, 0 };
+  char* eventnames[NUM_PAPI_COUNTERS]=  { "cycles", "l1_pending_miss", "lfb_hit", "l2_hit" };
+  assert(PAPI_event_name_to_code("UNHALTED_REFERENCE_CYCLES:u=1:k=1",&(events[0])) == PAPI_OK);
+  assert(PAPI_event_name_to_code("L1D_PEND_MISS:OCCURRENCES",   &(events[1])) == PAPI_OK);
+  assert(PAPI_event_name_to_code("MEM_LOAD_UOPS_RETIRED:HIT_LFB",   &(events[2])) == PAPI_OK);
+  assert(PAPI_event_name_to_code("MEM_LOAD_UOPS_RETIRED:L2_HIT",   &(events[3])) == PAPI_OK);
+  long long values[NUM_PAPI_COUNTERS] = { 0, 0, 0, 0 };
+  long long accum_values[NUM_PAPI_COUNTERS] = { 0, 0, 0, 0 };
+#endif
+  while(1)
+  {
+    int break_value = use_old_read_testcase ? read_testcase(&tc, fptr) : read_mod_testcase(ifptr,&tc,true);
+    if(break_value >= 0)
+      tc_vector.push_back(tc);
+    if(tc_vector.size() == BATCH_SIZE || (break_value < 0 && tc_vector.size() > 0))
+    {
+      vector<double> results_vec;
+      vector<double> baseline_results_vec;
+      results_vec.clear();
+      baseline_results_vec.clear();
+      results_vec.resize(tc_vector.size());
+      baseline_results_vec.resize(tc_vector.size());
+      g_load_time_initializer.update_stat(NUM_TESTCASES_IDX, tc_vector.size()); 
+      g_load_time_initializer.update_stat(NUM_READS_IDX, tc_vector.size()); 
+      g_load_time_initializer.update_stat(NUM_HAPLOTYPES_IDX, tc_vector.size()); 
+      struct timespec start_time;
+#ifdef USE_PAPI
+      assert(PAPI_start_counters(events, NUM_PAPI_COUNTERS) == PAPI_OK);
+#endif
+      get_time(&start_time);
+#pragma omp parallel for schedule(dynamic,chunk_size)  num_threads(12)
+#ifdef DO_REPEAT_PROFILING
+      for(unsigned z=0;z<10;++z)
+#endif
+      {
+        for(unsigned i=0;i<tc_vector.size();++i)
+        {
+          testcase& tc = tc_vector[i];
+          float result_avxf = g_compute_full_prob_float(&tc, 0);
+          double result = 0;
+          if (result_avxf < MIN_ACCEPTED) {
+            double result_avxd = g_compute_full_prob_double(&tc, 0);
+            result = log10(result_avxd) - log10(ldexp(1.0, 1020.0));
+            ++num_double_calls;
+          }
+          else
+            result = (double)(log10f(result_avxf) - log10f(ldexpf(1.f, 120.f)));
+#ifdef DUMP_COMPUTE_VALUES
+          g_load_time_initializer.debug_dump("return_values_vector.txt",to_string(result),true);
+#endif
+          results_vec[i] = result;
+        }
+      }
+#ifdef USE_PAPI
+      assert(PAPI_stop_counters(values, NUM_PAPI_COUNTERS) == PAPI_OK);
+#endif
+      uint64_t curr_interval = diff_time(start_time);
+#ifdef PRINT_PER_INTERVAL_TIMINGS
+      times_fptr << curr_interval << "\n";
+#endif
+      vector_compute_time +=  curr_interval;
+#ifdef USE_PAPI
+      for(unsigned k=0;k<NUM_PAPI_COUNTERS;++k)
+        accum_values[k] += values[k];
+#endif
+      num_testcases += tc_vector.size();
+      if(do_check)
+      {
+        get_time(&start_time);
+#pragma omp parallel for schedule(dynamic,chunk_size)
+        for(unsigned i=0;i<tc_vector.size();++i)
+        {
+          testcase& tc = tc_vector[i];
+          double baseline_result = compute_full_prob<double>(&tc);
+          baseline_result = log10(baseline_result) - log10(ldexp(1.0, 1020.0));
+          baseline_results_vec[i] = baseline_result;
+        }
+        baseline_compute_time += diff_time(start_time);
+        for(unsigned i=0;i<tc_vector.size();++i)
+        {
+          double baseline_result = baseline_results_vec[i];
+          double abs_error = fabs(baseline_result-results_vec[i]);
+          double rel_error = (baseline_result != 0) ? fabs(abs_error/baseline_result) : 0;
+          if(abs_error > 1e-5 && rel_error > 1e-5)
+          {
+            cout << std::scientific << baseline_result << " "<<results_vec[i]<<"\n";
+            all_ok = false;
+          }
+        }
+      }
+      for(unsigned i=0;i<tc_vector.size();++i)
+      {
+	delete[] tc_vector[i].rs;
+	delete[] tc_vector[i].hap;
+	delete[] tc_vector[i].q;
+	delete[] tc_vector[i].i;
+	delete[] tc_vector[i].d;
+	delete[] tc_vector[i].c;
+      }
+      results_vec.clear();
+      tc_vector.clear();
+    }
+    if(break_value < 0)
+      break;
+  }
+#ifdef DUMP_COMPUTE_VALUES
+  g_load_time_initializer.debug_close();
+#endif
+  if(all_ok)
+  {
+    cout << "All output values within acceptable error\n";
+    cout << "Baseline double precision compute time "<<baseline_compute_time*1e-9<<"\n";
+  }
+  cout << "Num testcase "<<num_testcases<< " num double invocations "<<num_double_calls<<"\n";
+  cout << "Vector compute time "<< vector_compute_time*1e-9 << "\n";
+#ifdef USE_PAPI
+  for(unsigned i=0;i<NUM_PAPI_COUNTERS;++i)
+    cout << eventnames[i] << " : "<<accum_values[i]<<"\n";
+#endif
+#ifdef PRINT_PER_INTERVAL_TIMINGS
+  times_fptr.close();
+#endif
+  if(use_old_read_testcase)
+    fclose(fptr);
+  else
+    ifptr.close();
+  g_load_time_initializer.print_profiling();
+}
diff --git a/public/VectorPairHMM/src/main/c++/utils.h b/public/VectorPairHMM/src/main/c++/utils.h
new file mode 100644
index 0000000..3b10a58
--- /dev/null
+++ b/public/VectorPairHMM/src/main/c++/utils.h
@@ -0,0 +1,85 @@
+/*Copyright (c) 2012 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.
+*/
+
+
+#ifndef PAIRHMM_UTIL_H
+#define PAIRHMM_UTIL_H
+
+#include "common_data_structure.h"
+
+template<class T>
+std::string to_string(T obj)
+{
+  std::stringstream ss;
+  std::string ret_string;
+  ss.clear();
+  ss << std::scientific << obj;
+  ss >> ret_string;
+  ss.clear();
+  return ret_string;
+}
+void debug_dump(std::string filename, std::string s, bool to_append, bool add_newline=true);
+
+int read_mod_testcase(std::ifstream& fptr, testcase* tc, bool reformat=false);
+
+bool is_avx_supported();
+bool is_sse42_supported();
+extern float (*g_compute_full_prob_float)(testcase *tc, float *before_last_log);
+extern double (*g_compute_full_prob_double)(testcase *tc, double* before_last_log);
+void debug_dump(std::string filename, std::string s, bool to_append, bool add_newline);
+template<class NUMBER>
+NUMBER compute_full_prob(testcase *tc, NUMBER *before_last_log=0);
+template<class NUMBER>
+NUMBER compute_full_prob_avxd(testcase *tc, NUMBER *before_last_log=0);
+template<class NUMBER>
+NUMBER compute_full_prob_avxs(testcase *tc, NUMBER *before_last_log=0);
+template<class NUMBER>
+NUMBER compute_full_prob_ssed(testcase *tc, NUMBER *before_last_log=0);
+template<class NUMBER>
+NUMBER compute_full_prob_sses(testcase *tc, NUMBER *before_last_log=0);
+
+double getCurrClk();
+void get_time(struct timespec* x);
+uint64_t diff_time(struct timespec& prev_time);
+
+//bit 0 is sse4.2, bit 1 is AVX
+enum ProcessorCapabilitiesEnum
+{
+  SSE41_CUSTOM_IDX=0,
+  SSE42_CUSTOM_IDX,
+  AVX_CUSTOM_IDX
+};
+#define ENABLE_ALL_HARDWARE_FEATURES 0xFFFFFFFFFFFFFFFFull
+uint64_t get_machine_capabilities();
+void initialize_function_pointers(uint64_t mask=ENABLE_ALL_HARDWARE_FEATURES);
+void do_compute(char* filename, bool use_old_read_testcase=true, unsigned chunk_size=10000, bool do_check=true);
+
+//#define DO_WARMUP
+//#define DO_REPEAT_PROFILING
+/*#define DUMP_COMPUTE_VALUES 1*/
+#define BATCH_SIZE  10000
+#define RUN_HYBRID
+/*#define PRINT_PER_INTERVAL_TIMINGS 1*/
+
+#endif
diff --git a/public/c/SeparateQltout.cc b/public/c/SeparateQltout.cc
new file mode 100644
index 0000000..7644c96
--- /dev/null
+++ b/public/c/SeparateQltout.cc
@@ -0,0 +1,70 @@
+#include "MainTools.h"
+#include "Basevector.h"
+#include "lookup/LookAlign.h"
+#include "lookup/SerialQltout.h"
+
+unsigned int MatchingEnd(look_align &la, vecbasevector &candidates, vecbasevector &ref) {
+    //la.PrintParseable(cout);
+
+    for (int i = 0; i < candidates.size(); i++) {
+        look_align newla = la;
+
+        if (newla.rc1) { candidates[i].ReverseComplement(); }
+        newla.ResetFromAlign(newla.a, candidates[i], ref[la.target_id]);
+
+        //newla.PrintParseable(cout, &candidates[i], &ref[newla.target_id]);
+        //cout << newla.Errors() << " " << la.Errors() << endl;
+
+        if (newla.Errors() == la.Errors()) {
+            return i;
+        }
+    }
+
+    //FatalErr("Query id " + ToString(la.query_id) + " had no matches.");
+
+    return candidates.size() + 1;
+}
+
+int main(int argc, char **argv) {
+    RunTime();
+
+    BeginCommandArguments;
+    CommandArgument_String(ALIGNS);
+    CommandArgument_String(FASTB_END_1);
+    CommandArgument_String(FASTB_END_2);
+    CommandArgument_String(REFERENCE);
+
+    CommandArgument_String(ALIGNS_END_1_OUT);
+    CommandArgument_String(ALIGNS_END_2_OUT);
+    EndCommandArguments;
+
+    vecbasevector ref(REFERENCE);
+    vecbasevector reads1(FASTB_END_1);
+    vecbasevector reads2(FASTB_END_2);
+
+    ofstream aligns1stream(ALIGNS_END_1_OUT.c_str());
+    ofstream aligns2stream(ALIGNS_END_2_OUT.c_str());
+
+    basevector bv;
+
+    SerialQltout sqltout(ALIGNS);
+    look_align la;
+    while (sqltout.Next(la)) {
+        vecbasevector candidates(2);
+        candidates[0] = reads1[la.query_id];
+        candidates[1] = reads2[la.query_id];
+
+        unsigned int matchingend = MatchingEnd(la, candidates, ref);
+        if (matchingend < 2) {
+            bv = (matchingend == 0) ? reads1[la.query_id] : reads2[la.query_id];
+
+            //la.PrintParseable(cout, &bv, &ref[la.target_id]);
+            la.PrintParseable(((matchingend == 0) ? aligns1stream : aligns2stream), &bv, &ref[la.target_id]);
+        }
+    }
+
+    aligns1stream.close();
+    aligns2stream.close();
+
+    return 0;
+}
diff --git a/public/c/libenvironhack/Makefile b/public/c/libenvironhack/Makefile
new file mode 100644
index 0000000..302ff8e
--- /dev/null
+++ b/public/c/libenvironhack/Makefile
@@ -0,0 +1,10 @@
+CC=gcc
+CCFLAGS=-Wall -dynamiclib -arch i386 -arch x86_64
+
+libenvironhack.dylib: libenvironhack.c
+	$(CC) $(CCFLAGS) -init _init_environ $< -o $@
+
+all: libenvironhack.dylib
+
+clean:
+	rm -f libenvironhack.dylib
diff --git a/public/c/libenvironhack/libenvironhack.c b/public/c/libenvironhack/libenvironhack.c
new file mode 100644
index 0000000..8b2a264
--- /dev/null
+++ b/public/c/libenvironhack/libenvironhack.c
@@ -0,0 +1,37 @@
+/*
+ * Copyright (c) 2010, 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.
+ */
+
+/*
+LSF 7.0.6 on the mac is missing the unsatisfied exported symbol for environ which was removed on MacOS X 10.5+.
+nm $LSF_LIBDIR/liblsf.dylib | grep environ
+See "man environ" for more info, along with http://lists.apple.com/archives/java-dev/2007/Dec/msg00096.html
+*/
+
+#include <crt_externs.h>
+
+char **environ = (char **)0;
+
+void init_environ(void) {
+  environ = (*_NSGetEnviron());
+}
diff --git a/public/c/libenvironhack/libenvironhack.dylib b/public/c/libenvironhack/libenvironhack.dylib
new file mode 100755
index 0000000..a45e038
Binary files /dev/null and b/public/c/libenvironhack/libenvironhack.dylib differ
diff --git a/public/chainFiles/b36tob37.chain b/public/chainFiles/b36tob37.chain
new file mode 100644
index 0000000..f1de2b8
--- /dev/null
+++ b/public/chainFiles/b36tob37.chain
@@ -0,0 +1,30854 @@
+chain	1574309	MT	16571	+	0	16571	MT	16569	+	0	16569	1567
+302	1	0
+8	1	0
+2796	0	1
+13086	1	0
+376
+
+chain	21270159960	1	247249719	+	0	247199719	1	249250621	+	10000	249233096	2
+616	0	137
+166664	50000	50000
+40302	50000	50000
+153649	50000	50000
+1098446	269	272
+773	1	1
+43	1	1
+864369	2	2
+51	0	3
+104	13694	13694
+104	3	0
+51	2	2
+134936	50000	50000
+1161048	60000	150000
+1440092	50000	27273
+7590365	50000	50000
+116914	50088	100088
+237162	50000	50000
+3518496	50000	50000
+12702424	50000	150000
+16145012	1	0
+7772	0	1
+4705841	1	0
+52977198	50000	50000
+157344	50000	21065
+16604841	50000	50000
+189539	50000	150000
+398739	20290000	21050000
+195588	50000	50000
+186739	50000	150000
+175055	50000	50000
+201709	50000	100000
+126477	50000	130183
+381	3	0
+315	2	0
+62	1	1
+73	1	1
+1158	0	1
+314	1	0
+11	1	1
+2849	0	3
+5615	1	1
+37	1	1
+3172	4	6
+190	1	1
+34	1	1
+380	1	0
+2099	0	3
+1135	4	0
+970	5	5
+209	0	1
+460	1	0
+1242	28	28
+574	1	1
+21	1	1
+2268	0	3
+239	1	0
+970	11	11
+2365	1	1
+21	1	1
+384	8	8
+996	0	2
+10383	0	2
+713	1	0
+5188	1	1
+30	1	1
+1233	0	1
+132	1	1
+44	1	1
+2955	0	1
+512	1	1
+39	1	1
+1096	16	0
+743	0	1
+9028	1	0
+2506	6	0
+8446	0	2
+5505	3	0
+7541	0	1
+109864	50000	50000
+78698	50000	50000
+127263	50000	50000
+170669	50000	50000
+38311	100000	100000
+1022394	50000	50000
+281532	50000	294733
+1687	1	1
+39	0	1
+1018	1	1
+26	1	1
+1722	0	2
+158	0	4
+1602	6	0
+1384	0	1
+2066	1	1
+32	3	1
+1556908	50000	150000
+185320	50000	150000
+172789	50000	50000
+220313	50000	50000
+455185	50000	50000
+22047237	0	1
+34365824	50000	150000
+259514	50000	150000
+17265625	50000	50000
+11394365	50000	50000
+13665999	50000	150000
+174886
+
+chain	989083	1	247249719	+	2475290	2488984	1	249250621	-	246751494	246765188	1383
+13694
+
+chain	5421	1	247249719	+	1609759	1609849	1	249250621	+	1672838	1672928	2227793
+90
+
+chain	3303	1	247249719	+	13192499	13192587	1	249250621	-	236203315	236203403	109
+88
+
+chain	467	1	247249719	+	142633259	142633287	1	249250621	-	128420441	128420469	123
+28
+
+chain	12431961244	10	135374737	+	50000	135374737	10	135534747	+	60000	135524747	10
+5577107	50006	0
+12337568	50000	50000
+20794160	50000	50000
+286100	2480000	3200000
+191752	50000	50000
+3830277	150000	50000
+952205	150000	100000
+263307	150000	100000
+163231	150000	50000
+989829	150000	100000
+1941874	50000	50000
+211435	50000	50000
+30112515	319974	0
+13249156	10	0
+31058956	50000	50000
+2696597	50000	150000
+4615335	10000	50000
+246123	50000	50000
+1327328	1	1
+47	1	1
+1312	1	0
+56	1	1
+190	1	1
+31	1	1
+20182	0	1
+448068
+
+chain	8134587	10	135374737	+	81444609	81551340	10	135534747	+	88976631	89083503	218
+369	41	41
+149	6	6
+83	71	71
+548	9	9
+391	9	9
+334	42	42
+81	1	2
+954	1	0
+441	0	4
+922	37	37
+343	253	253
+278	59	58
+404	13	13
+90	39	37
+70	132	123
+145	4	4
+392	9	9
+58	29	29
+166	51	50
+78	14	14
+455	61	65
+243	41	41
+1183	17	17
+163	57	57
+169	51	51
+912	5	5
+667	12	12
+250	20	20
+506	8	8
+292	8	8
+266	17	17
+69	27	27
+131	22	22
+668	46	47
+270	13	13
+128	7	7
+300	48	48
+818	32	32
+667	67	67
+402	24	36
+293	18	18
+423	68	68
+113	9	9
+630	42	42
+269	51	51
+165	0	1
+645	52	52
+76	91	90
+505	13	13
+143	31	31
+319	68	70
+245	126	126
+145	35	37
+90	57	57
+378	41	38
+193	13	13
+333	51	30
+51	6	6
+821	56	56
+547	18	18
+343	9	9
+270	47	47
+706	1	0
+120	21	22
+371	35	35
+530	13	13
+51	36	36
+611	48	48
+587	18	18
+499	9	9
+183	26	26
+847	7	7
+134	5	4
+64	34	34
+120	66	66
+173	147	147
+126	19	16
+53	44	49
+69	1	0
+153	89	90
+81	16	16
+52	32	36
+72	28	28
+86	68	68
+56	51	51
+120	17	17
+181	5	5
+86	17	18
+68	36	36
+356	101	101
+90	3	11
+226	26	28
+70	19	19
+95	9	9
+88	16	16
+272	33	33
+216	71	71
+394	83	83
+853	14	15
+90	23	23
+130	0	3
+52	11	11
+192	49	49
+407	13	13
+122	71	34
+179	28	28
+102	10	10
+299	36	36
+268	4	4
+123	36	36
+112	41	41
+233	77	75
+73	88	92
+519	43	43
+118	101	101
+78	33	43
+117	31	31
+83	37	37
+86	3	0
+468	0	2
+791	55	55
+268	97	97
+111	55	59
+164	38	38
+176	0	3
+116	67	74
+269	0	3
+92	66	67
+205	50	55
+1339	33	34
+86	9	9
+310	34	34
+217	42	42
+194	18	17
+191	4	4
+250	0	3
+148	79	79
+77	3	0
+199	57	57
+200	53	53
+331	52	53
+136	32	42
+69	60	60
+169	0	1
+594	88	88
+174	70	70
+135	48	48
+53	9	9
+862	25	25
+1106	33	33
+974	76	76
+368	17	17
+369	43	43
+263	49	49
+143	8	8
+228	57	57
+74	3	0
+914	2	0
+137	77	74
+243	32	32
+166	53	53
+646	87	87
+71	0	1
+661	45	45
+142	76	76
+851	17	17
+56	60	60
+52	59	58
+80	60	60
+602	13	13
+617	76	78
+51	152	152
+77	38	38
+150	0	4
+386	45	45
+585	40	33
+108	12	12
+219	99	99
+1376	58	58
+517	27	27
+124	20	20
+566	58	58
+235	47	47
+72	26	26
+157	43	43
+208	31	31
+578	122	84
+259	15	15
+1141	119	119
+141	13	13
+817	14	14
+188	0	5
+323	62	75
+447	0	5
+64	161	161
+945	23	23
+66	35	35
+104	125	125
+613	186	184
+102	205	203
+767	27	27
+111	13	13
+107	80	83
+272	0	1
+438	4	4
+127	68	68
+564	44	44
+141	14	14
+137	13	17
+167	18	0
+241	25	25
+586	30	30
+178	44	44
+310	90	87
+1277	35	35
+646	32	32
+704	56	56
+367	93	101
+241	15	14
+340	64	64
+1000	23	26
+163	81	81
+895	12	12
+345	2	0
+117	48	49
+491	32	32
+206	17	17
+439	109	109
+202	6	7
+756	24	24
+380	63	62
+144	48	48
+608	80	80
+154	71	71
+232	16	16
+1809	40	40
+346	53	52
+117	10	0
+383	10	10
+1973	19	19
+879	42	42
+91	50	50
+1147	2	1
+210	68	88
+189	7	7
+595	50	49
+248	104	126
+265	106	106
+167	0	7
+141	93	62
+825	1	0
+348	47	46
+211	3	0
+114	52	56
+66	7	7
+759	48	48
+269	0	1
+106	109	114
+114	38	39
+282	20	20
+504	0	1
+174	14	7
+123	45	46
+82	58	58
+203	12	13
+153	44	44
+121	74	74
+805	43	43
+120	67	68
+171	6	6
+329	20	20
+151	33	33
+71	46	46
+195	25	21
+65	23	42
+96	78	78
+58	0	4
+389	0	3
+214	137	138
+111	2	3
+116	10	10
+128	0	3
+52	8	8
+62	43	43
+142	6	6
+214	0	112
+179	0	1
+234	4	0
+75	116	117
+119	63	67
+286	72	42
+73	150	150
+206	214	220
+73	2	0
+82	48	48
+135	40	67
+115	109	114
+185	49	49
+99	63	63
+52	204	205
+121
+
+chain	2724232	10	135374737	+	81309951	81339951	10	135534747	+	81320000	81350000	983
+22137	957	957
+46	77	77
+38	83	83
+51	54	54
+984	53	53
+5520
+
+chain	1898345	10	135374737	+	81349952	81369946	10	135534747	+	81360000	81380000	1327
+15902	21	27
+4071
+
+chain	946327	10	135374737	+	81339951	81349952	10	135534747	+	81350000	81360000	2894
+6692	1	0
+3308
+
+chain	939763	10	135374737	+	81430217	81440202	10	135534747	+	81440000	81450000	3159
+163	3	0
+518	0	16
+972	42	43
+5149	0	1
+3138
+
+chain	928169	10	135374737	+	81379935	81389948	10	135534747	+	81390000	81400000	3587
+1970	7	8
+141	10	0
+413	39	39
+622	4	0
+574	42	42
+2153	0	2
+1520	5	3
+2513
+
+chain	922636	10	135374737	+	81300280	81309951	10	135534747	+	81310330	81320000	2721
+2989	1	0
+6681
+
+chain	885793	10	135374737	+	81369946	81379851	10	135534747	+	81380000	81389916	4570
+507	30	32
+880	91	91
+1155	82	82
+784	10	10
+907	16	28
+1265	50	50
+859	0	3
+1375	1	2
+165	27	27
+124	29	29
+275	8	8
+308	6	0
+79	1	0
+871
+
+chain	839370	10	135374737	+	81389948	81399836	10	135534747	+	81400000	81409799	4960
+446	1	0
+639	0	1
+112	140	59
+198	24	22
+98	162	137
+63	10	10
+97	180	192
+71	31	33
+322	38	38
+431	0	1
+741	45	46
+229	1	3
+186	1	4
+3019	14	14
+131	1	0
+722	16	16
+1530	92	92
+32	2	1
+63
+
+chain	788625	10	135374737	+	81241464	81249852	10	135534747	+	81251575	81259959	6147
+783	1	0
+883	23	33
+3247	1	0
+143	31	31
+957	15	3
+2304
+
+chain	781678	10	135374737	+	81280054	81289770	10	135534747	+	81290109	81299824	3334
+65	841	841
+84	228	228
+27	240	240
+1767	0	10
+186	66	54
+976	0	3
+1495	0	7
+899	0	1
+376	7	7
+2156	10	0
+196	50	50
+47
+
+chain	778944	10	135374737	+	81250813	81551219	10	135534747	-	53516479	54101824	544
+53	63	72
+96	209	213
+193	44	44
+202	331	335
+149	28	28
+100	125	123
+56	238	272
+60	91	93
+123	9	11
+66	147	144
+82	210	211
+77	17	17
+196	31	31
+379	27	27
+954	71	71
+69	4431	3721
+746	66	66
+502	12	12
+282	28	28
+224	59	59
+52	35	35
+448	12	0
+474	42	42
+260	11	11
+83	38	44
+160	152	149
+284	76	76
+110	73	73
+284	9	9
+478	110	110
+95	5	5
+583	122	122
+116	1	1
+67	1	1
+118	1	1
+38	1	1
+566	1	1
+35	1	1
+287	1	0
+481	1	1
+42	1	1
+198	1	1
+22	1	1
+54	1	1
+25	1	1
+50	1	1
+50	1	1
+294	4	0
+158	1	1
+31	1	1
+255	8	8
+291	12	12
+171	2	2
+21	1	1
+685	77	77
+817	20	20
+312	39	39
+181	1	0
+249	50	47
+75	7	7
+86	4	4
+54	8	8
+518	134	134
+376	24	26
+189	17	27
+143	13	13
+93	16	16
+192	24	24
+992	140	132
+828	1	1
+40	1	1
+410	1	1
+25	0	2
+13	1	1
+83	8	8
+143	1	1
+20	1	1
+421	1	1
+49	1	1
+107	1	1
+28	1	1
+77	1	1
+32	0	2
+44	2	2
+348	1	1
+53	0	4
+58	1	1
+97	1	1
+125	56	53
+526	1	1
+46	1	1
+209	9	9
+76	1	1
+37	1	1
+53	1	1
+24	1	1
+141	1	1
+26	1	1
+304	1	1
+60	1	1
+199	1	1
+47	1	1
+92	6	0
+138	64	64
+299	65	65
+186	24	24
+631	84	84
+100	20	20
+108	27	27
+240	8134	8243
+50	47	45
+107	11	11
+750	5	5
+230	25	25
+221	62	62
+106	32	32
+106	52	52
+270	56	56
+166	31	31
+89	77	77
+127	666	662
+56	22	22
+55	95	83
+51	30	30
+77	35	35
+189	16	16
+130	53	53
+131	5	5
+158	140	131
+170	21	21
+55	79	79
+207	200	199
+152	11	11
+105	50	50
+104	34	34
+56	402	402
+69	0	1
+61	150	150
+181	10	10
+130	22	22
+180	5	0
+73	161	161
+77	151	151
+68	128	128
+330	138	126
+116	1211	328
+252	4	4
+102	8	8
+72	23	23
+51	51	51
+608	31808	287592
+56	14	14
+161	9	9
+717	46	50
+77	38	30
+83	51	51
+54	984	987
+53	65700	95386
+47	559	556
+99	119	119
+193	38	38
+164	12	7
+59	38	38
+58	9	5
+57	34	34
+68	30	30
+59	28	28
+51	82	87
+142	7	7
+67	162	152
+248	1	2
+114	34	34
+140	22	22
+58	119	118
+143	50	50
+255	69	65
+53	18	18
+127	11	13
+446	39	39
+134	24	24
+143	42	42
+123	65	65
+57	0	3
+199	73	73
+271	17	17
+113	24	24
+203	40	40
+51	38	38
+119	50	50
+81	60	60
+239	85	70
+79	219	219
+64	149	150
+29	211	211
+91	319	310
+76	40	40
+59	596	591
+34	579	579
+51	90	90
+169	336	329
+146	226	226
+50	480	479
+23	66	66
+95	447	447
+49	298	298
+29	180	180
+45	1186	1169
+53	2222	2217
+11	116	116
+33	313	313
+63	75	75
+14	257	258
+31	122	122
+73	311	316
+238	46	46
+130	81	78
+103	262	266
+56	168	163
+29	861	857
+61	655	666
+18	40	40
+436	1	1
+8	4	0
+35	1	1
+417	21	18
+51	2	0
+54	1	1
+126	10	9
+72	5	5
+377	1	1
+18	2	0
+35	2	2
+78	1	2
+18	2	2
+82	1	0
+99	1	1
+82	0	4
+99	1	1
+50	0	4
+50	7	7
+225	11	11
+135	2	0
+326	26	989
+2646	0	1
+560	10	0
+347	114	114
+284	118541	118621
+43	120	120
+65	1	0
+1	677	677
+33	71	71
+46	404	404
+78	661	663
+137	489	492
+43	854	846
+116	119	119
+63	286	286
+72	73	73
+150	206	206
+17	1	1
+85	1	1
+110	157	157
+48	135	135
+36	0	4
+4	115	115
+73	2	0
+19	1	1
+14	185	185
+49	99	99
+22	1	1
+40	79	80
+177
+
+chain	662550	10	135374737	+	81399647	81430169	10	135534747	-	46431029	46458544	512
+92	103	101
+125	0	2222
+53	53	50
+58	48	48
+298	191	189
+69	6167	5
+118	101	101
+128	111	111
+207	48	43
+55	175	169
+212	93	89
+159	23	23
+109	34	34
+150	21	20
+258	30	30
+120	51	54
+90	171	171
+268	224	219
+202	62	62
+480	237	237
+394	49	49
+100	28	28
+93	25	25
+52	29	29
+180	45	45
+141	47	47
+56	49	49
+169	39	42
+60	102	113
+53	1	13
+151	105	105
+58	33	30
+88	246	246
+334	116	116
+63	83	84
+268	115	113
+70	43	43
+252	2	1
+62	97	97
+88	6	0
+61	23	23
+84	75	75
+75	2	3
+83	8	8
+53	160	162
+312	153	152
+192	96	98
+122	95	100
+94	793	791
+61	1	5
+154	140	135
+130	32	33
+121	21	21
+82	6	6
+171	34	34
+110	52	49
+129	193	194
+64	26	29
+72	18	18
+286	75	58
+114	6596	7638
+114	284	172
+558	8	9
+111	5	5
+55	2	2
+80	0	1
+27	1	1
+72	1	1
+45	1	1
+516	1	1
+66	1	1
+106	23	42
+64	4	0
+21	1	1
+312	2	2
+30	1	1
+151	20	20
+193	1	1
+38	1	1
+96	6	6
+171	0	3
+27	0	2
+34	2	2
+120	3	3
+39	1	1
+752
+
+chain	650336	10	135374737	+	81249915	81259740	10	135534747	+	81260018	81269841	3195
+898	53	53
+63	96	96
+209	193	193
+44	202	202
+331	149	149
+28	100	100
+125	56	56
+238	60	60
+91	198	198
+147	82	82
+210	290	290
+31	1360	1360
+71	69	69
+196	1	0
+454	16	15
+3764
+
+chain	462746	10	135374737	+	81440202	81450008	10	135534747	+	81450000	81459803	2861
+1116	4	4
+801	3	0
+2483	369	369
+41	238	238
+71	1291	1291
+42	2400	2400
+37	343	343
+253	278	278
+36
+
+chain	389885	10	135374737	+	81290873	81299672	10	135534747	+	81300927	81309722	2802
+25	221	221
+62	106	106
+32	106	106
+52	270	270
+56	166	166
+31	89	89
+77	127	127
+666	133	133
+95	51	51
+30	77	77
+35	335	335
+53	294	294
+103	4	0
+33	246	246
+79	207	207
+200	268	268
+50	104	104
+34	56	56
+402	130	130
+150	601	601
+161	77	77
+151	68	68
+128	330	330
+138	116	116
+1211	512	512
+51
+
+chain	178315	10	135374737	+	81400041	81409702	10	135534747	+	81410003	81419664	4252
+32	404	404
+191	168	168
+119	193	193
+38	235	235
+38	124	124
+34	68	68
+30	59	59
+28	51	51
+82	216	216
+162	363	363
+34	220	220
+21	9	9
+89	143	143
+50	255	255
+69	995	995
+42	123	123
+65	256	256
+73	628	628
+40	208	208
+50	94	94
+47	239	239
+85	79	79
+219	64	64
+31	147	147
+72	625	625
+40	271	271
+93	754	754
+30	700	700
+66
+
+chain	157388	10	135374737	+	81410627	81419292	10	135534747	+	81420589	81429247	5183
+66	95	95
+53	1136	1136
+46	81	81
+25	268	268
+38	269	263
+105	58	58
+6	0	1
+27	88	88
+34	53	53
+81	32	32
+46	334	334
+116	63	63
+83	268	266
+115	429	428
+97	262	262
+75	757	757
+75	230	232
+41	343	343
+69	47	47
+78	238	238
+46	130	131
+17	36	34
+28	319	319
+46	56	56
+38	707	707
+52	129	129
+132	125	125
+26	376	376
+75
+
+chain	142913	10	135374737	+	81466547	81535718	10	135534747	-	46275769	46344990	569
+44	2128	2133
+24	2535	2533
+31	2379	2381
+34	143	143
+43	270	270
+50	1045	1058
+51	494	498
+36	2085	2105
+60	1979	1981
+71	1197	1197
+41	1594	1601
+37	2856	2871
+66	205	205
+50	1339	1339
+33	656	663
+42	805	805
+79	280	275
+56	200	200
+22	18	18
+13	1443	1450
+44	2526	2526
+33	974	974
+75	1489	1489
+47	1658	1653
+53	1652	1653
+41	1071	1071
+59	10705	10669
+57	6434	6441
+25	586	586
+30	178	178
+44	310	310
+74	7	1
+9	1277	1277
+35	5735	5751
+32	2139	2139
+63	3162	3162
+40	346	345
+53	3391	3390
+41	92	92
+50
+
+chain	97392	10	135374737	+	81500632	81510012	10	135534747	+	81510451	81519840	3573
+60	191	191
+60	1232	1232
+76	51	51
+152	77	77
+38	536	540
+45	585	586
+39	340	340
+99	1376	1373
+58	517	517
+27	710	710
+58	235	235
+47	72	72
+26	157	157
+43	208	208
+31	630	637
+70	1415	1415
+119
+
+chain	87386	10	135374737	+	81512081	81517268	10	135534747	+	81521923	81527111	3288
+161	1034	1034
+35	104	104
+125	613	613
+186	102	102
+205	767	767
+27	231	232
+80	841	841
+68	564	564
+44
+
+chain	81916	10	135374737	+	81260486	81269831	10	135534747	+	81270587	81279924	3410
+66	796	796
+28	224	224
+59	52	52
+35	934	925
+42	354	354
+1	0	2
+37	160	160
+121	19	18
+12	284	284
+76	110	110
+73	771	771
+110	683	683
+8	36	35
+78	4099	4100
+77
+
+chain	75208	10	135374737	+	81450008	81464865	10	135534747	+	81597933	81612795	1746
+23	1356	1354
+29	166	166
+51	547	547
+30	274	278
+40	1364	1363
+57	169	169
+51	3032	3032
+27	1585	1586
+48	818	818
+32	667	667
+67	1160	1160
+68	752	752
+42	269	269
+51	810	813
+52	76	76
+91	661	661
+31	319	319
+42
+
+chain	71596	10	135374737	+	81480667	81490183	10	135534747	+	81490477	81500000	3725
+36	395	395
+36	536	535
+88	519	519
+43	139	139
+80	78	78
+33	117	134
+31	1468	1468
+55	268	268
+97	111	111
+30	6	0
+19	164	164
+38	292	292
+67	2459	2459
+34	2063	2060
+52	136	136
+26
+
+chain	65913	10	135374737	+	81470614	81479436	10	135534747	+	81480422	81489246	3085
+36	1955	1955
+26	1450	1450
+97	248	248
+44	223	223
+89	149	149
+32	72	72
+28	86	86
+68	993	993
+49	0	1
+52	319	320
+26	569	569
+33	216	216
+71	1842	1842
+49
+
+chain	63808	10	135374737	+	81521220	81529648	10	135534747	+	81531068	81539504	3362
+32	704	704
+56	367	367
+93	596	601
+64	1186	1189
+81	1371	1371
+48	1185	1185
+109	1575	1575
+48	608	608
+80	154	154
+71
+
+chain	58084	10	135374737	+	81490258	81499708	10	135534747	+	81500075	81509527	2957
+60	807	808
+44	174	174
+70	135	135
+48	924	924
+25	2943	2943
+43	263	263
+49	1566	1566
+77	243	243
+32	865	865
+87	732	733
+45	183	183
+35
+
+chain	41373	10	135374737	+	81540284	81544136	10	135534747	+	81550136	81553982	6087
+47	328	324
+52	832	831
+48	375	375
+79	0	1
+30	114	114
+38	1117	1115
+45	82	82
+58	368	368
+44	121	121
+74
+
+chain	34777	10	135374737	+	81464865	81470020	10	135534747	+	81474671	81479828	3724
+26	245	245
+34	44	44
+48	145	145
+12	0	2
+23	90	90
+57	378	378
+41	1468	1468
+56	2453	2453
+35
+
+chain	34249	10	135374737	+	81270980	81279755	10	135534747	+	81281073	81289810	4510
+39	431	431
+50	752	752
+134	2175	2167
+44	3025	2995
+35	14	9
+7	2005	2010
+64
+
+chain	29298	10	135374737	+	81537077	81539110	10	135534747	+	81546931	81548963	3702
+68	791	797
+50	617	605
+33	0	2
+73	308	311
+93
+
+chain	18939	10	135374737	+	81450538	81452241	10	135534747	+	81460333	81462036	3255
+39	70	70
+132	1431	1431
+31
+
+chain	6030	10	135374737	+	81422413	81430217	10	135534747	+	81432363	81440000	5582
+26	7730	7563
+48
+
+chain	5154	10	135374737	+	81371363	81371422	10	135534747	-	72572913	72572972	4033525
+2	1	1
+56
+
+chain	1569	10	135374737	+	81371422	81371454	X	155270560	+	63278348	63278380	8657459
+32
+
+chain	1063	10	135374737	+	81231366	81231464	10	135534747	-	54101945	54102043	901
+98
+
+chain	4275918	10_random	113275	+	18676	65432	5	180915260	+	138864813	138909803	707
+204	2	0
+4653	4	0
+2427	0	1
+5957	0	1
+1558	1	0
+780	1794	33
+29376
+
+chain	870863	10_random	113275	+	9144	18556	10	135534747	-	46779061	46789268	4835
+301	2	0
+564	3	0
+802	1	0
+2624	0	112
+142	0	2
+128	100	787
+4745
+
+chain	637317	10_random	113275	+	102183	113228	10	135534747	+	88758795	88768050	8258
+1205	22	22
+793	0	1
+914	1	1
+9	0	1
+45	0	1
+9	2477	1631
+132	1562	615
+2006	1	1
+36	1	1
+557	24	23
+885	0	2
+194	1	0
+171
+
+chain	383436	10_random	113275	+	97894	101991	10	135534747	+	88848068	88852165	132306
+2932	0	1
+697	4	3
+464
+
+chain	312568	10_random	113275	+	0	3305	10	135534747	+	88861095	88864401	225266
+2905	0	1
+400
+
+chain	263395	10_random	113275	+	91858	94672	10	135534747	+	88776474	88779288	339622
+1683	3	3
+130	11	11
+987
+
+chain	254817	10_random	113275	+	83066	85798	10	135534747	-	46749813	46752549	368581
+201	0	6
+798	0	1
+403	4	0
+841	14	15
+471
+
+chain	244215	10_random	113275	+	5995	97779	10	135534747	+	88818267	88897264	4711
+966	0	1
+2072	66256	15486
+2428	10567	42513
+197	0	1
+820	6	6
+18	1	0
+21	0	1
+20	2	1
+1685	0	2
+703	3020	9053
+1156	0	1
+1846
+
+chain	216530	10_random	113275	+	72868	75170	10	135534747	-	93082016	93084318	524441
+2302
+
+chain	211663	10_random	113275	+	85898	88144	10	135534747	+	88832831	88835078	546276
+536	0	1
+1710
+
+chain	171789	10_random	113275	+	70706	72761	10	135534747	-	93140436	93143121	737133
+50	1	1
+68	85	4
+15	15	34
+17	7	53
+13	1	647
+81	1	1
+50	21	21
+1630
+
+chain	129924	10_random	113275	+	67807	109229	10	135534747	-	46627912	46728083	8515
+467	0	1
+256	0	1
+42	1	1
+1352	0	2
+308	10219	43352
+227	1	1
+22	1	1
+2232	22395	48006
+1581	0	2
+518	1	1
+30	1	0
+197	132	132
+1439
+
+chain	125160	10_random	113275	+	4561	5895	10	135534747	-	46655374	46656707	1028939
+94	1	0
+1239
+
+chain	104003	10_random	113275	+	65554	66651	10	135534747	-	93176760	93177857	1232247
+1097
+
+chain	92361	10_random	113275	+	66732	67707	10	135534747	-	93158718	93159693	1382147
+975
+
+chain	89191	10_random	113275	+	3509	4486	10	135534747	-	129898314	129899289	1428933
+69	1	1
+35	1	0
+336	1	0
+401	1	1
+44	1	1
+87
+
+chain	29685	10_random	113275	+	34270	80352	10	135534747	-	46758431	46763489	186939
+210	0	6
+1251	4	4
+73	42015	985
+1249	1	1
+46	1	1
+1232
+
+chain	4572	10_random	113275	+	70436	70610	10	135534747	-	93144449	93144623	2904410
+51	50	50
+73
+
+chain	3114	10_random	113275	+	70610	70643	10	135534747	-	93147281	93147314	29780913
+33
+
+chain	12415599352	11	134452384	+	50000	134451920	11	135006516	+	60000	134946516	11
+1102759	16576	50000
+49571094	207000	307000
+503352	3000000	3100000
+14395596	2605	50000
+488471	34	102
+26	0	176
+30213	141	350
+27914	1	0
+20009	1	0
+19	1	0
+39	1	0
+17	3	1
+10	1	0
+1008	1	0
+95	1	0
+5127	15	0
+302	1	0
+975	0	4
+1548	0	1
+190	20	0
+41	1	0
+29	1	1
+44	0	1
+101	1	0
+25	0	1
+6178	0	1
+1875	21437	52561
+468	1	1
+81	1	1
+2620	1	0
+1640	4	0
+3305	0	1
+3342	1	0
+17899663	12000	50000
+8549206	15562	150000
+38507165	2	0
+1327	174	0
+392	18	0
+48
+
+chain	188276	11	134452384	+	69433462	69437111	GL000202.1	40103	+	7212	10860	1247
+1868	1	0
+1780
+
+chain	38178	11	134452384	+	134451288	134452384	5	180915260	-	180902450	180903869	1901368
+174	458	926
+1	8	0
+63	136	1
+64	2	0
+190
+
+chain	6040	11	134452384	+	134451996	134452128	1	249250621	-	249240179	249240388	3449013
+89	36	113
+7
+
+chain	2221	11	134452384	+	134452085	134452111	Y	59373566	+	59362903	59362929	5436109
+26
+
+chain	4284950	11_random	215294	+	0	215294	11	135006516	-	65191297	65289033	706
+40524	167558	50000
+7212
+
+chain	3340892	11_random	215294	+	90524	125679	11	135006516	+	69689619	69724695	863
+1003	62	0
+3019	1	0
+695	1	1
+26	1	1
+1133	0	1
+1374	2	2
+20	1	1
+729	11	11
+269	0	1
+1091	14	14
+969	21	21
+532	5	5
+2677	18	0
+21481
+
+chain	3051979	11_random	215294	+	175679	208082	GL000202.1	40103	-	0	32891	790
+17546	11	51
+27	523	35
+32	6	6
+6712	100	1036
+7446
+
+chain	10612	11_random	215294	+	193466	193615	GL000202.1	40103	-	18116	18265	21504297
+59	27	27
+63
+
+chain	5102	11_random	215294	+	91527	91580	11	135006516	+	69690684	69690737	20979070
+53
+
+chain	12330181372	12	132349534	+	16000	132289534	12	133851895	+	145739	133779461	12
+7035083	0	4
+544	0	1
+3777	0	1
+3889	73000	52114
+6014	1	0
+6524	168	34
+20974	0	2
+3965	3	0
+444	0	11
+464	1	0
+27577110	1395000	3000000
+38631945	0	1
+14541	0	4
+1703	1	0
+789	250000	12128
+1783	1	0
+1075	0	2
+1042	1	0
+1526	1	1
+27	1	1
+2320	0	1
+166	1	0
+564	0	1
+2856	0	2
+900	0	1
+1387	1	1
+33	1	1
+2139	1	1
+48	1	1
+1305	0	2
+1533	1	2
+879	0	1
+744	26	26
+855	0	4
+1092	6	0
+1114	12	0
+817	1	1
+18	1	0
+217	1	1
+36	1	1
+2002	1	0
+1025	0	1
+450	1	1
+43	1	1
+919	1	0
+18	1	1
+3207	42	42
+1440	0	8
+148	4	0
+3655	2	0
+3403	1	1
+47	1	1
+1524	1	1
+28	1	1
+5561	0	2
+44	0	1
+676	8	8
+810	16	16
+536	2	0
+236	4	0
+167	0	4
+1419	49	53
+4688	1	1
+38	1	1
+18577	5	0
+5284	0	2
+1577	34	34
+4875	1	1
+25	1	1
+4340	0	14
+2663	5	0
+1170	1	0
+4268	0	4
+1036	0	1
+2117	0	8
+5917	1	0
+3239	0	4
+2619	1	1
+21	1	1
+937	1	1
+38	1	1
+2412	0	2
+38	17	0
+2732	0	2
+9314	2	0
+1986	2	2
+16	1	1
+229	1	1
+93	1	1
+895	12	0
+415	1	5
+27	1	1
+78	14	14
+185	8	9
+458	0	2
+89	1	1
+42	1	1
+2034	0	1
+1545	0	2
+280	0	4
+97	14	14
+231	0	2
+2816	5	0
+537	50	50
+1090	1	1
+27	1	1
+25758689	0	1
+6536665	0	1
+377270	57000	96749
+668	1	1
+20	1	0
+3348	1	1
+33	1	1
+648	1	1
+29	1	1
+3732	4	0
+977	46	46
+785	4	0
+34	1	0
+1688	0	10
+4248	1	0
+1167	1	0
+985	9	9
+2897	1	0
+1630	9	0
+1096	0	1
+1356	0	8
+13065723	150011	68363
+799	2	0
+343	0	1
+1771	0	1
+2702	7	6
+1900	1	0
+705	6	0
+303	1	0
+727	1	1
+43	1	0
+3	2	0
+490	1	1
+59	1	1
+226	1	1
+52	3	0
+465	0	8
+194	1	1
+25	1	0
+139	1	1
+15	1	1
+1833	1	0
+81	1	1
+39	1	1
+453	1	0
+719	1	1
+47	1	1
+558	1	0
+838	8	1
+288	10	9
+741	5	2
+465	1	1
+48	1	1
+268	1	1
+26	1	0
+1337	30	48
+84	2	85
+917	1	0
+110	31	31
+1580	1	1
+40	1	1
+683	1	1
+24	1	1
+247	1	1
+36	1	1
+1574	0	1
+10091386	0	3
+296	0	5
+220	45000	100872
+972469
+
+chain	2523	12	132349534	+	107924339	107924385	20	63025520	-	54448952	54448998	196257
+46
+
+chain	9007877316	13	114142980	+	17918000	114127980	13	115169878	+	19020000	115109878	14
+26987167	1	0
+40753157	50000	150000
+25443670	400000	150000
+1821999	384108	414007
+369878
+
+chain	17589560	13	114142980	+	113473994	113658050	13	115169878	-	529930	713796	162
+174857	2	0
+1328	144	0
+1156	1	1
+27	1	1
+2159	2	0
+49	1	1
+175	2	0
+20	4	0
+590	30	0
+163	8	4
+2905	2	0
+430
+
+chain	8677	13	114142980	+	113650223	113650314	13	115169878	-	706193	706284	25436870
+91
+
+chain	17750502	13_random	186858	+	0	186858	GL000212.1	186858	+	0	186858	156
+186858
+
+chain	8359013040	14	106368585	+	18070000	106360585	14	107349540	+	19000000	107289540	15
+1081285	1	1
+43	1	1
+76	2	0
+437	1	1
+19	1	1
+440	12	13
+59	15	15
+63	12	12
+70	0	1
+734	1	1
+165	1	4
+96	1	1
+46	1	0
+83	1	1
+149	4	4
+164	1	1
+18	1	1
+63	15	16
+359	1	1
+39	1	1
+103	1	1
+76	1	1
+139	1	1
+38	1	1
+344	1	1
+65	0	1
+166	5	5
+88	1	1
+66	0	287
+50	1	1
+317	0	1
+52	1	1
+92	4	0
+651	4	4
+82	1	1
+93	1	1
+64	1	1
+24	1	1
+856	1	1
+35	1	1
+258	1	1
+17	1	1
+478	1	0
+1048	70	70
+1279	1	1
+37	1	1
+1115	3	4
+72	1	1
+126	1	1
+102	1	1
+413	10	10
+132	6	6
+89	0	2
+209	15	4
+77	5	5
+427	1	1
+41	1	1
+949	1	1
+16	1	1
+732	1	1
+44	2	0
+128	0	1
+91	1	1
+180	6	6
+388	6	6
+50	13	12
+275	1	1
+33	1	1
+142	1	1
+61	1	1
+560	1	1
+20	1	1
+1327	6	13
+729	37	37
+284	1	1
+44	1	1
+205	0	4
+40	1	1
+352	10	10
+261	1	1
+39	1	1
+940	12	0
+1677	36	0
+159	1	1
+32	8	1
+818	0	6
+580	1	0
+931	1	0
+276	2	0
+3298	45	45
+169	14	0
+46	1	1
+882	2	0
+94	1	1
+49	1	1
+859	4	0
+45	1	1
+807	16	15
+416	0	3
+3345	15	15
+92	30	29
+80	1	1
+48	1	1
+2459	0	1
+646	1	1
+31	1	1
+392	1	1
+29	54	0
+1875	3	0
+141696	1	1
+32	1	1
+8201115	1	0
+107	1	0
+2137	1	1
+39	1	1
+8848	0	1
+4806	1	0
+2075	1	0
+16619	41	40
+2338	3	0
+11507	8	0
+1352	0	1
+4596	0	1
+2073	2	1
+28	1	1
+2311	1	1
+44	1	1
+10440	0	4
+894	0	1
+1641	0	96
+38	9	0
+20	1	1
+2706	6	0
+351	1	1
+25	1	1
+742	0	1
+1048	2	18
+12085977	0	1
+14871228	3	0
+29067652	1	1
+47	1	1
+20174307	1292	0
+2548043
+
+chain	14855	14	106368585	+	19159713	19190443	14	107349540	-	87865807	87904514	64
+20	0	6
+50	9933	9915
+37	16916	24930
+30	3690	3692
+25	27	0
+2
+
+chain	6432	14	106368585	+	19179765	19190441	22	51304566	+	16377620	16388301	97
+45	10604	10609
+27
+
+chain	7700812247	15	100338915	+	18260008	100338915	15	102531392	+	20000000	102521392	16
+8448	6	2
+4086	1	0
+9569	1	1
+40	0	5
+56	7	1
+872419	40441	40448
+553	4	4
+876	0	1
+38	1	1
+139	1	1
+23	1	1
+1881	1	1
+17	1	0
+499	8	8
+310	2	2
+25	11	5
+46	1	1
+78	1	1
+22	0	3
+181	5	6
+569	11	11
+539	1	1
+23	0	4
+261	1	1
+19	0	2
+776	13	15
+62	13	13
+860	1	0
+719	26	0
+1346	1	1
+134	0	1
+30	1	1
+1070	1	1
+21	1	1
+398	0	1
+177	5	21
+534	4	0
+770	0	6
+17	1	1
+606	1	1
+31	1	1
+1861	1	1
+53	1	1
+2169	3	0
+558	1	0
+18	1	1
+227	2	0
+13	1	1
+329	5	5
+430	1	1
+17	2	0
+620	0	1
+1112	2	0
+641	0	4
+476	1	1
+45	1	1
+1285	0	1
+1139	1	1
+47	1	1
+183	4	0
+1435	20	0
+176	0	1
+219	0	1
+607	1	1
+42	1	1
+371	2	8
+507	2	0
+66	1	0
+41	1	1
+999	4	4
+318	15	15
+1092	1	1
+72	1	1
+808	5	5
+54	2	2
+52	1	1
+40	1	1
+109	3	3
+47	1	1
+1535	14	0
+14012	4	0
+7954	4	1
+1350	1	0
+318	1	1
+25	1	1
+600	0	4
+442	0	1
+1396	1	1
+36	1	1
+1107	0	3
+1441	0	5
+360	1	1
+47	1	1
+228	10	0
+37	1	1
+497	1	1
+37	1	1
+2129	4	0
+1242	2	0
+478	4	0
+708	1	1
+90	1	1
+154	10	10
+1583	1	1
+31	1	1
+1302	0	37
+101	14	14
+1138	1	1
+83	10	0
+11	7	0
+111	1	1
+29	1	1
+2917	1	1
+32	1	1
+1762	1	1
+46	1	1
+449	1	0
+2458	9	1
+869	1	0
+534	1	1
+47	1	1
+309	1	0
+6358	22	0
+564	0	1
+1845	1	0
+660	1	1
+25	1	1
+68	1	0
+182	0	9
+54	3	18
+1519	1	1
+32	1	1
+559	1	1
+30	1	1
+3851	1	0
+265	8	7
+240	4474	0
+428	1	0
+1651	11	10
+297	1	0
+665	21	0
+48	1	1
+1763	2	0
+245	1	1
+39	1	1
+519	1	1
+31	1	1
+2398	0	6
+749	49	1
+2074	4	0
+701	5	5
+337	1	0
+470	1	1
+43	1	1
+1163	3	0
+1342	1	1
+43	1	1
+140	0	1
+83	1	1
+24	1	2
+37	1	1
+723	1	1
+36	1	1
+99	3	0
+27	1	1
+92	1	0
+80	43	43
+1095	0	13
+384	0	2
+292	1	1
+39	1	1
+101	12	12
+576	0	2
+1907	1	1
+19	1	1
+318	1	0
+1973	1	1
+32	1	1
+689	1	1
+49	1	1
+357	8	8
+2081	13	13
+260	15	15
+2295	1	1
+24	1	1
+2558	1	1
+26	1	1
+571	16	23
+323	0	1
+36	0	1
+5353	111	0
+1711	38	70
+272	13	13
+1284	0	1
+1128	4	4
+2189	1	0
+474	2	0
+1284	61	67
+643	1	1
+37	1	1
+381	0	2
+56	1	0
+2591	1	1
+55	1	1
+160	4	4
+116	1	1
+89	2	0
+316	0	1
+785	20	0
+152	1	1
+21	1	1
+600	0	6
+568	1	0
+278	1	1
+29	1	1
+89	0	4
+1737	1	1
+58	1	1
+368	24	24
+2113	20	24
+218	0	2
+18	1	1
+684	4	4
+3200	1	1
+31	1	1
+58	18	18
+164	1	1
+37	1	1
+296	6	6
+431	1	1
+35	1	1
+431	1	1
+45	1	1
+93	1	1
+24	1	1
+216	1	1
+46	1	1
+2773	0	17
+751	2	1
+104	1	1
+59	1	1
+445	1	1
+26	1	1
+356	1	0
+1484	1	2
+436	25	25
+306	1	1
+55	1	1
+230	4	4
+892	1	0
+364	7	7
+796	1	1
+26	1	1
+663	0	2
+80	0	15
+4391	1	0
+133	1	1
+25	0	4
+41	0	2
+164	1	1
+61	4	4
+925	3	0
+1882	13	13
+4513	1	0
+111	1	1
+76	1	1
+202	6	0
+680	0	1
+200	3	0
+429	0	2
+736	1	1
+18	1	1
+1573	0	1
+119	1	1
+245	0	9
+11	1	1
+1656	54	22
+616	2	1
+158	0	1
+587	1	1
+39	4	1
+1053	6	6
+1116	1	1
+34	1	1
+152	10	7
+448	0	1
+269024	100000	863295
+334079	100000	50000
+180553	0	74
+66	73	3
+40	1	0
+28	156	73
+202	1	1
+17	0	1
+156	1	1
+55	1	1
+111	0	1
+144	1	1
+57	0	1
+687074	50000	50000
+120647	0	348
+45586	0	1
+6994	1	0
+3398063	44008	12354
+7672	0	2
+1809	1	0
+428524	101014	10165
+43170	4	4
+1064959	128966	5086
+1021	0	1
+1710	1	0
+931	0	2
+4505	0	1
+686	525	2
+432	33	0
+58	20	20
+12369	1014	0
+6233	0	1
+359485	100000	111749
+33855821	0	239
+2852113	1	0
+7040367	0	1
+2815738	3	1
+7055922	60000	50000
+363827	32	32
+104991	0	1
+203136	0	6050
+2271	47	47
+1424473	60000	50000
+13510190	22012	5553
+9194	0	3
+109	0	4
+40	0	1
+43	0	7
+2352	0	13
+5027	0	2
+534	1	0
+794	0	2
+4233	0	2
+5769	1	0
+381	1	0
+2524	0	2
+547	0	5
+1967	0	1
+1207	105	0
+1027	0	6
+3935380
+
+chain	4143271	15	100338915	+	19154641	19368514	15	102531392	+	21901264	22115049	110
+40441	8593	8593
+26	89965	89965
+4257	1	1
+30	1	1
+185	16464	16391
+43	29947	29883
+25	1	1
+34	23835	23884
+25
+
+chain	390135	15	100338915	+	26478746	26483022	15	102531392	+	28681030	28685306	6048
+1039	22	22
+3215
+
+chain	187810	15	100338915	+	26483022	26517556	15	102531392	-	73809068	73843318	79
+41	12	0
+36	1	1
+490	5	5
+285	1	1
+71	1	1
+215	1	1
+53	0	12
+8114	1	0
+10796	15	15
+2483	0	1
+20	1	1
+2048	8856	8847
+163	792	517
+33
+
+chain	51529	15	100338915	+	26530390	26530949	15	102531392	+	28731348	28731907	2473877
+450	8	8
+101
+
+chain	17522	15	100338915	+	26516748	26516957	15	102531392	+	22658399	22658608	1968
+209
+
+chain	14035	15	100338915	+	20378176	20378474	15	102531392	+	22829101	22829399	772378
+73	69	69
+156
+
+chain	12347	15	100338915	+	26530060	26530390	15	102531392	+	22671289	22671619	3189077
+244	4	4
+82
+
+chain	5537	15	100338915	+	96402403	96402461	15	102531392	+	98585049	98585107	22350382
+58
+
+chain	4486	15	100338915	+	96402461	96402508	15	102531392	+	98585002	98585049	16761199
+47
+
+chain	2874	15	100338915	+	26517060	26517091	15	102531392	+	28719096	28719127	6634083
+31
+
+chain	2874	15	100338915	+	26517029	26517060	15	102531392	+	28719096	28719127	6634084
+31
+
+chain	2874	15	100338915	+	26516998	26517029	15	102531392	+	28719096	28719127	6634085
+31
+
+chain	2874	15	100338915	+	26516967	26516998	15	102531392	+	28719096	28719127	6634086
+31
+
+chain	2314	15	100338915	+	26530003	26530033	15	102531392	+	22671232	22671262	5236
+30
+
+chain	12940492	15_random	784346	+	189260	358080	15	102531392	+	28561246	28726591	233
+2522	0	1
+3762	1	1
+40	1	1
+2427	6472	2
+1744	0	1
+263	0	7
+2963	4	4
+1889	1	0
+2501	0	1
+3377	6	6
+5238	0	1
+1277	5	5
+38	1	1
+8232	12	8
+5507	0	18
+155	1	0
+379	14	14
+363	7	13
+336	1	1
+46	1	1
+218	8	8
+1074	0	4
+101	12	13
+178	1	1
+93	1	1
+156	10	11
+398	0	20
+45	1	1
+255	9	10
+2661	0	1
+17	1	1
+82	1	1
+14	1	1
+227	64	64
+1154	1	0
+493	1	1
+39	1	1
+369	1	0
+21	1	1
+322	2	7
+222	0	2
+171	15	0
+81	1	1
+47	1	1
+159	9	9
+154	1	0
+272	4	4
+26	1	1
+121	8	7
+659	1	0
+440	1	1
+35	1	0
+1419	15	0
+181	0	2
+292	0	15
+1767	1	1
+44	1	1
+59	0	1
+910	0	1
+290	1	0
+288	1	0
+567	2	0
+1088	0	1
+1758	1	0
+72	1	1
+21	1	1
+5748	17	17
+800	0	1
+2037	13	13
+113	5	5
+2832	1	1
+44	1	1
+3581	2	0
+33	1	1
+812	5	5
+33	0	1
+257	17	17
+1932	0	14
+168	0	1
+424	5	0
+24	1	1
+67	14	14
+90	1	5
+124	1	1
+34	1	1
+48	0	9
+460	0	8
+294	7	0
+813	1	3
+240	1	0
+511	0	9
+190	1	0
+267	1	1
+38	1	1
+1082	7	57
+21	15	0
+28	0	1
+5	1	1
+123	0	5
+781	1	1
+21	1	1
+390	1	1
+36	1	1
+287	1	1
+90	0	3
+6	2	2
+189	9	9
+263	2	1
+724	13	14
+308	2	0
+1752	1	1
+114	1	1
+236	4	0
+46	1	1
+72	5	0
+1039	1	1
+25	1	1
+403	1	1
+22	1	1
+231	6	6
+834	15	15
+617	1	1
+53	1	1
+243	1	1
+154	3	5
+571	11	16
+231	1	1
+47	1	1
+910	1	1
+45	1	1
+1510	1	1
+79	1	1
+2053	1	1
+48	1	1
+768	8	8
+546	1	1
+19	1	5702
+784	6	0
+275	20	13
+131	114	114
+363	1	1
+46	1	1
+396	1	1
+39	1	1
+75	15	15
+1875	1	0
+332	1	1
+49	1	1
+265	3	2
+55	1	1
+96	1	1
+136	1	0
+305	8	8
+297	0	2
+255	2	2
+23	1	1
+181	19	6
+151	0	1
+707	667	9324
+284	5	3
+73	1	1
+208	26	25
+34	0	773
+80	20	0
+2003	400	125
+163	2	0
+2630	9	1
+19	1	1
+100	12	0
+2421	0	2
+47	21227	0
+853	1	0
+1238	0	12
+3571	1	1
+20	0	1
+2483	15	15
+8803	287	9594
+5992
+
+chain	8627768	15_random	784346	+	422939	629603	15	102531392	-	19338638	19927596	385
+168	56	59
+73	4	4
+378	23	23
+868	29	29
+85	1	0
+528	119	5106
+152	31	31
+184	8	7
+322	0	1
+62	46	45
+77	37	46
+80	22	22
+201	45	47
+175	31	33
+1923	82	77
+546	7051	32690
+7810	209	153340
+1308	1	0
+9826	1	0
+1486	1	1
+148	1	0
+76	6	6
+53	36	34
+178	5447	565
+14	14505	121
+72	13	16
+57	1	1
+157	0	2
+11	1	1
+74	1	1
+24	3	3
+220	1	1
+54	1	1
+142	1	1
+82	2	0
+60	4	0
+99	1	1
+106	1	1
+98	1	1
+402	1	1
+79	4	7
+78	1	9
+5	0	1
+31	7	7
+65	1	1
+105	0	1
+22	6	8
+76	10	8
+47	0	1
+39	3	0
+5	1	3
+108	2	2
+61	16307	40121
+676	26	26
+7087	25	25
+20818	7	7
+2750	60358	90388
+69	54	53
+165	166	516
+42	0	42
+81	4	151
+18	0	42
+148	111	112
+73	4	4
+378	23	23
+868	29	29
+85	1	0
+528	8	8
+280	32	34
+426	78	79
+81	648	334
+181	8	7
+485	0	2
+1404	24	24
+101	36	38
+240	8	8
+77	53	54
+347	18	18
+72	9	9
+94	82	82
+384	8	8
+250	108	151474
+1152	0	1
+633	226	12498
+3255	4	0
+58	32	32
+6209	1	1
+30	1	0
+1060	2	0
+3747	4	4
+173	5	5
+2548	0	22
+2275	0	20
+606	41	41
+4653	12	12
+6138	0	1
+148	5	0
+244
+
+chain	3986761	15_random	784346	+	0	334816	15	102531392	-	78891064	79878228	248
+30328	8040	15984
+3015	1	0
+70	44499	160931
+52	0	5
+1038	1	1
+29	1	1
+1001	0	18
+680	0	329
+181	1	1
+32	1	1
+839	2	0
+440	0	3
+547	1	0
+278	1	0
+410	1	1
+26	3	0
+101	1	1
+24	1	1
+149	0	9
+179	2	1
+29	1	1
+226	3	0
+21	1	1
+473	10	0
+717	2	0
+1044	1	1
+23	1	1
+625	1	1
+41	1	0
+150	1	1
+62	1	1
+145	59	59
+242	12	12
+179	1	1
+64	1	1
+1405	1	1
+35	0	2
+469	5	0
+401	0	1
+25	0	10
+17	1	1
+55	1	1
+165	1	1
+1966	15	23
+839	0	18
+969	1	1
+44	1	1
+1905	1	1
+47	1	1
+1037	128	128
+486	5	0
+1086	2	1
+199	4	4
+59	2	0
+243	84	0
+410	1	1
+39	1	1
+70	0	324
+77	1	187
+42	4	151
+897	135051	676116
+64	54092	52483
+25	1	1
+88	9286	18277
+201	26614	5202
+33	1	0
+1
+
+chain	2185345	15_random	784346	+	423107	689458	15	102531392	+	82637661	83186296	482
+30	0	5
+26	1346	1346
+29	885	5865
+31	576	577
+46	77	77
+5	0	1
+32	303	304
+45	175	176
+31	1923	1923
+66	1943	144683
+715	0	1
+548	13	13
+1907	1	1
+16	1	1
+66	3	0
+1219	5	1
+1066	34012	198199
+7204	2446	2446
+2762	100	7680
+5162	1	0
+2782	1	1
+26	7	4
+49	1	1
+3627	3	0
+1686	133598	65296
+3109	1	1
+21	1	1
+1430	63	63
+335	3	3
+14	4	0
+203	1	1
+23	5	5
+1262	4	4
+323	1	1
+47	1	1
+417	0	1
+537	19	1
+1913	2	0
+1685	6	0
+1740	1	1
+49	1	1
+120	1	1
+30	0	3
+920	4	0
+479	30	30
+1207	1	1
+182	4	0
+72	3	1
+78	1	1
+150	1	1
+46	1	1
+222	1	1
+24	1	1
+74	1	1
+44	1	1
+391	1	1
+33	1	1
+149	9	8
+56	1	1
+30	1	0
+52	1	1
+298	6	0
+22	1	0
+29	1	1
+393	35	0
+145	36	36
+226	15	15
+185	7	7
+692	1	1
+34	1	1
+1291	0	2
+1824	5	5
+1119	1	1
+49	1	2
+1025	25013	44930
+835	88	11347
+692	0	2
+2551	3	0
+1144	82	77
+1939	26	28
+164	1	1
+44	0	2
+201	1	1
+133	5	14
+77	1	1
+44	1	0
+92	1	0
+293	8	7
+184	31	31
+381	8	8
+384	1	1
+80	1	1
+94	9	9
+57
+
+chain	1845967	15_random	784346	+	61569	84889	15	102531392	-	73695594	73766494	782
+153	33	33
+49	1	0
+197	15	15
+67	62	62
+241	12	9
+185	41	44
+64	23	23
+559	50	50
+333	46	46
+397	6	6
+141	4	0
+660	50	50
+315	38	38
+282	309	47864
+57	7	7
+85	39	39
+340	62	62
+43	0	1
+77	0	1
+768	0	12
+71	70	69
+102	17	17
+58	45	50
+676	2	0
+430	21	22
+112	0	1
+401	4	0
+617	95	95
+168	50	50
+442	4	0
+91	114	114
+463	0	1
+94	28	28
+1577	16	16
+572	0	1
+1451	55	55
+2327	51	51
+394	1	0
+109	21	24
+660	50	54
+703	1	0
+93	22	22
+94	48	48
+219	46	46
+352	22	22
+150	155	161
+173	19	19
+162	6	12
+1201	48	49
+119	17	17
+435	4	4
+146	38	38
+946	10	10
+98	37	37
+60	47	47
+579
+
+chain	1297748	15_random	784346	+	203918	328028	15	102531392	-	73698913	73856126	264
+567	109104	118059
+369	106	23997
+700	2	0
+40	0	248
+320	0	33
+130	1	1
+18	1	1
+138	20	20
+1341	8	0
+863	1	1
+48	1	1
+240	1	1
+34	20	0
+3218	1	1
+20	1	1
+2062	46	46
+285	14	14
+937	1	1
+25	3	3
+305	1	1
+42	1	1
+706	2	0
+232	1	1
+67	1	1
+88	4	5
+844	1	1
+82	1	1
+430	0	7
+78	1	1
+458	27	27
+52
+
+chain	898399	15_random	784346	+	457589	504019	15	102531392	-	19636589	19905366	626
+5344	14	14
+7167	26767	249114
+26	7087	7087
+25
+
+chain	844102	15_random	784346	+	95554	784338	15	102531392	+	22730405	27183335	411
+59	9906	9932
+128	2128	2090
+42	1792	637909
+89	10	10
+71	198	198
+122	137	141
+341	29	29
+104	103	103
+395	11	14
+667	6	7
+74	7	0
+178	1	5
+203	9	4
+172	55	55
+791	25	25
+714	19	22
+597	133	133
+142	2	0
+252	0	4
+260	67	67
+41	6	0
+860	29	30
+258	93	95
+1793	11	11
+358	71	70
+242	1	1
+20	1	1
+1308	0	3
+468	0	2
+755	1	1
+81	2	2
+72	3	0
+597	4	4
+492	25	7
+1459	10	9
+674	16	16
+711	1	1
+49	1	1
+1525	1	1
+45	1	1
+2919	1	1
+36	1	1
+493	1	1
+21	1	1
+830	16	0
+3	7	0
+644	17	17
+479	0	1
+2343	0	315
+307	8	311
+87	0	3
+330	42	0
+520	7	6
+72	2	1
+745	6	6
+324	6	0
+398	22	22
+118	27	27
+68	600887	3728395
+44872
+
+chain	555121	15_random	784346	+	634265	679702	15	102531392	+	82723475	82991213	602
+20	1	1
+41	24204	246463
+2085	6	6
+667	14	14
+596	0	24
+1743	415	422
+870	1	0
+3572	1	1
+1152	8	0
+498	0	1
+3239	1	1
+34	1	1
+1283	1	1
+41	1	0
+676	0	2
+2078	0	1
+1283	0	18
+681	1	0
+223
+
+chain	530253	15_random	784346	+	409131	430676	15	102531392	-	19567939	19581201	1716
+786	8	0
+171	8918	159
+2113	8268	8752
+1281
+
+chain	417534	15_random	784346	+	35735	80744	15	102531392	+	23413134	23608954	1095
+840	0	54
+916	0	2
+777	3337	13583
+637	50	57
+858	0	4
+779	0	14
+171	1	2
+927	4	0
+1753	2	0
+814	35	35
+1073	14	14
+81	99	101
+66	42	42
+1291	66	66
+240	45	48
+68	36	36
+98	38	38
+1141	5	5
+70	14	15
+150	46	46
+650	13461	153954
+62	1206	1201
+45	3148	3138
+46	6617	6616
+50	2415	2415
+46	615	621
+64
+
+chain	169648	15_random	784346	+	417136	418914	5	180915260	+	131590649	131592427	748288
+1778
+
+chain	152639	15_random	784346	+	200201	201828	15	102531392	+	28662778	28664407	841936
+970	0	1
+468	5	6
+184
+
+chain	151945	15_random	784346	+	110737	203590	15	102531392	-	73700255	73867708	1083
+74	87238	121334
+88	426	14673
+942	2	0
+567	1880	28137
+86	1	1
+62	1	1
+716	14	14
+212	0	1
+468	0	1
+76
+
+chain	142059	15_random	784346	+	583198	664057	15	102531392	-	16763491	17663089	651
+176	7	7
+242	7	7
+1002	1	1
+61	1	1
+286	10	10
+1697	57790	716388
+17	1	1
+12	3589	70884
+35	145	145
+36	6576	99374
+431	11	1
+19	0	4
+96	2	0
+98	1	1
+62	1	1
+1047	10	15
+223	1	0
+575	2	0
+465	1	0
+8	1	1
+140	1	4
+65	1	1
+381	5111	5164
+145	1	1
+29	1	6
+32	8	2
+199
+
+chain	140486	15_random	784346	+	414032	415531	5	180915260	+	131627050	131628561	916856
+486	0	13
+290	2	1
+721
+
+chain	136843	15_random	784346	+	411466	412886	5	180915260	-	49283520	49284940	941594
+1420
+
+chain	113176	15_random	784346	+	577887	601700	15	102531392	+	85729223	85793813	754
+51	12	12
+630	1	1
+27	5	5
+51	41	41
+249	505	29710
+148	24	24
+110	0	2
+145	12	11
+646	54	53
+291	404	700
+590	7	0
+154	1	1
+36	5	3
+106	1	1
+42	1	1
+517	181	27
+164	18572	30011
+30
+
+chain	110898	15_random	784346	+	410214	411366	5	180915260	-	49350156	49351308	1158024
+1152
+
+chain	90718	15_random	784346	+	415631	422839	5	180915260	-	49281425	49321173	523505
+1405	4191	36723
+57	0	4
+785	0	4
+770
+
+chain	87628	15_random	784346	+	412986	413908	15	102531392	+	82958289	82959211	1453275
+922
+
+chain	78489	15_random	784346	+	408080	408895	5	180915260	+	131628738	131629553	1616335
+815
+
+chain	75848	15_random	784346	+	328894	334289	15	102531392	+	28663807	28669202	22165
+415	0	1
+219	14	14
+716	1	1
+62	1	1
+1820	1	0
+432	1	1
+21	1	1
+549	1	1
+42	1	1
+1098
+
+chain	55946	15_random	784346	+	579203	582900	15	102531392	-	19568187	19572180	874
+256	1085	1091
+54	291	291
+49	100	396
+255	1464	1453
+62	1	6
+80
+
+chain	50039	15_random	784346	+	328288	328894	15	102531392	-	73792653	73793260	1678654
+449	99	100
+58
+
+chain	41737	15_random	784346	+	53223	55079	15	102531392	-	79138743	79140590	1899
+987	5	0
+378	4	0
+30	1	1
+324	1	1
+36	1	1
+89
+
+chain	40184	15_random	784346	+	35650	52319	15	102531392	+	23578289	23604839	1865
+85	6507	16388
+50	5309	5309
+35	1168	1168
+99	66	66
+42	1291	1291
+66	240	240
+45	68	68
+36	98	98
+38	1380	1380
+46
+
+chain	36402	15_random	784346	+	63654	139260	15	102531392	+	20712328	20743651	996
+46	46877	2371
+29	5894	5886
+28	261	261
+55	0	3
+35	2163	2163
+70	17110	17298
+32	0	42
+10	2220	2218
+27	68	68
+335	31	31
+315
+
+chain	33407	15_random	784346	+	63271	84310	15	102531392	+	28567817	28636450	784
+50	2730	50298
+39	1361	1355
+70	2485	2497
+95	168	168
+50	618	618
+33	8782	8789
+48	4472	4485
+38
+
+chain	26884	15_random	784346	+	71527	84203	15	102531392	+	23434933	23447596	1313
+28	3628	3632
+43	3563	3545
+38	1762	1762
+91	1625	1625
+17	1	1
+30	721	722
+38	1054	1054
+37
+
+chain	17994	15_random	784346	+	577754	595591	15	102531392	+	82746005	82941680	2345
+133	777	777
+41	8083	152910
+1120	114	33023
+47	1	1
+5	265	681
+66	293	293
+111	2277	2277
+32	585	587
+5	0	1
+25	0	1
+6	1	0
+11	3164	2847
+53	540	540
+82
+
+chain	17584	15_random	784346	+	334305	334490	15	102531392	-	73868107	73868292	12488910
+185
+
+chain	16638	15_random	784346	+	334590	334767	15	102531392	+	28693782	28693959	13398527
+177
+
+chain	15574	15_random	784346	+	203754	203918	15	102531392	+	20713399	20713563	2884965
+164
+
+chain	11941	15_random	784346	+	112567	138945	15	102531392	+	28572611	28599524	1070
+24	791	791
+25	2119	2124
+57	23331	23861
+31
+
+chain	10106	15_random	784346	+	307857	307966	15	102531392	-	73812018	73812127	6634519
+109
+
+chain	9879	15_random	784346	+	198177	198415	15	102531392	+	28709863	28710101	596395
+238
+
+chain	5493	15_random	784346	+	34234	34291	Y	59373566	+	27644447	27644504	32044688
+57
+
+chain	4133	15_random	784346	+	323293	323339	15	102531392	+	22666870	22666916	2166
+46
+
+chain	4016	15_random	784346	+	328237	328288	15	102531392	+	28668851	28668902	1790991
+51
+
+chain	3958	15_random	784346	+	107733	107775	15	102531392	-	78958306	78958348	1193
+42
+
+chain	3427	15_random	784346	+	198013	198049	15	102531392	+	20714128	20714164	4212128
+36
+
+chain	3014	15_random	784346	+	591545	685196	15	102531392	-	19431434	19585695	819
+47	89045	149655
+87	4422	4422
+50
+
+chain	2874	15_random	784346	+	307826	307857	15	102531392	-	73812018	73812049	6634520
+31
+
+chain	2855	15_random	784346	+	198147	198177	15	102531392	+	28831982	28832012	6776371
+30
+
+chain	2097	15_random	784346	+	200178	200201	15	102531392	-	79852957	79852980	911500
+23
+
+chain	1855	15_random	784346	+	307785	307816	15	102531392	+	28688468	28688499	5960032
+31
+
+chain	1291	15_random	784346	+	110710	110736	15	102531392	-	73822377	73822403	1552683
+26
+
+chain	1093	15_random	784346	+	687136	688443	15	102531392	-	19508634	19509938	742
+25	1251	1248
+31
+
+chain	7474990131	16	88827254	+	0	88822254	16	90354753	+	60000	90294753	17
+172342	0	1
+112	1	0
+5627	2	1
+8398838	17500	50000
+25336229	100000	150000
+1112651	9800000	11100000
+42003582	20000	50000
+1855370
+
+chain	9963354	16_random	105485	+	0	105485	16	90354753	+	29712462	29819360	326
+5589	7	8
+6783	0	218
+41	1	3
+38	1	1
+234	9	9
+219	46	0
+15	0	50
+3818	0	1
+1090	1	1
+45	1	1
+308	1	0
+524	0	4
+984	1	1
+24	1	0
+970	0	2
+106	1	1
+25	2	1
+436	0	5
+296	1	1
+23	2	0
+813	0	1
+1173	1	0
+5500	1	0
+1193	16	16
+1329	0	1
+2727	0	1
+3622	0	13
+3844	3	0
+5076	0	1
+4157	2	0
+178	0	2
+126	1	1
+344	5	6
+497	1	0
+620	7	7
+378	0	1
+669	24	25
+211	1	5
+453	0	11
+176	0	1
+486	0	8
+326	1	0
+2143	40	9
+2337	0	1
+866	1	0
+10	2	2
+1366	1	1
+44	1	1
+831	1	1
+45	1	1
+1612	6	5
+3801	0	1
+910	0	2
+486	0	1
+2775	1	0
+1083	1	0
+1793	1	1
+50	0	1
+1339	0	2
+145	17	17
+651	10	10
+1140	0	1
+724	1	1
+39	1	1
+3261	1	0
+1513	0	9
+606	22	0
+2027	27	19
+3470	11	0
+4100	3	0
+2045	0	4
+1047	0	1
+6647	78	1279
+748
+
+chain	7369813928	17	78774742	+	0	78653129	17	81195210	+	0	81060000	18
+252627	1	1
+24	1	1
+33	0	29
+566	87	0
+116	58	0
+92	29	0
+79	8	37
+485	1	59
+28	1	1
+76	233	1
+27	29	0
+2764	17	20
+2220	18	18
+837	1	1
+39	1	1
+564	1	1
+14	1	1
+2523	39	9
+1824	0	56
+76	29	0
+1681	0	1
+414	0	3
+256	0	68
+119	10	10
+290	0	4
+3193	1	0
+2562	0	4
+1809	3	0
+84	1	1
+62	1	1
+3703	0	27
+2041	16	0
+911	0	2
+696	4	4
+1428	15	15
+290	1	0
+1779	0	1
+60	1	1
+216	0	1
+375	1	1
+41	0	1
+9221	46522	100000
+3080543	0	1
+1208216	0	2
+1370	2	0
+1279	0	4
+322	0	5
+5661	210	0
+307	21	22
+973	8	0
+2901	1	0
+8479	0	1
+4122	7	0
+3187	4	0
+571	0	1
+167	0	1
+10174	7	7
+856	2	1
+1630	1	0
+4258	3	1
+1688	1	0
+264	0	304
+796	1	0
+8494	0	10
+2273	1	0
+8297	1	0
+1500	1	4
+733	2	2
+40	1	0
+4	0	1
+15	19	1
+64	1	253
+22	0	34
+18	1	205
+2070	2	0
+2981	14	13
+1309	0	1
+3991	3	0
+1939	0	3
+887	0	2
+463	18	0
+64	0	3
+2104	0	20
+556	0	4
+121	0	1
+3670	2	0
+4345	0	5394
+5334	0	1
+2505	4	10
+6776	14	11
+9573	0	1
+1136	0	2
+3754	1	0
+4588	1	0
+637	17	17
+1285	8	0
+369	0	1
+2084	1	0
+492	2	0
+517	0	4
+954	0	2
+1517	1	0
+958	9	0
+807	14	14
+357	0	10
+3611	0	2
+3191	0	39
+742	1	0
+646	2	0
+2211	1	0
+14829	1	0
+3465	11	0
+31	0	33
+833	16	16
+1345	0	1
+6443	5	4
+2627353	1	0
+11581979	0	43
+25	0	89
+238783	0	1
+1830653	1	0
+419873	100008	116477
+5587	6	0
+11056	0	2
+3240	1	0
+1237	0	2
+373	1	1
+43	1	1
+558379	100000	3000000
+1823446	0	1
+2728383	0	1
+29	0	1
+138	1	0
+144	6	8
+38	0	2
+7	0	1
+18	1	1
+70935	10	13
+52	28	31
+189	0	1
+41	2	2
+750363	44	44
+4038953	100000	50000
+1524006	1	1
+47	1	1
+231	2	0
+1175	1	0
+555	1	1
+49	1	1
+568	7	0
+605	2	0
+4954	1	1
+18	6	7
+567	0	1
+421	2	0
+943	75	67
+777	0	3
+925	3	0
+5	4	0
+318	1	0
+230	20	13
+244	1	1
+13	0	1
+42	1	1
+220	1	1
+56	1	1
+101	225	0
+1113	1	0
+17	1	1
+2614	4	0
+3186	50	50
+3872	0	2
+617	14	0
+5674	0	2
+1852	1	1
+63	1	1
+56	1	1
+25	1	1
+332	0	6
+423	5	5
+61	4	0
+108	1	1
+46	1	1
+160	2	2
+72	1	1
+162	1	1
+20	1	1
+53	1	1
+63	1	1
+112	1	1
+59	1	1
+5885	2	0
+255	36	36
+6246	1	1
+114	1	1
+255	1	1
+49	1	1
+210	1	1
+138	157793	28603
+927	5	0
+212	7	7
+641	17	17
+1296	46	46
+2513	71	69
+76	1	2
+61	50226	0
+1959	18	18
+2727	22	22
+6616	1	0
+5109	68	86
+2450	7	7
+50	10	0
+3439	0	4
+4179	0	4
+2749	0	1
+1124	8	0
+56	1	1
+1840	14	14
+624	8	0
+1743	4	0
+3689	0	4
+2051	0	1
+751	0	1
+2111	10	11
+3110	1	0
+682	1	0
+2795	5	2
+241	0	1
+165	1	3
+1258	0	1
+1602	5	0
+3715	0	1
+1308	0	1
+2058	1	0
+1624	0	1
+478	4	0
+9	6	0
+35	3	1
+47	0	1
+2425	1	0
+1178	0	4
+33	1	1
+415	5	5
+887	1	3
+946	29	29
+630	15	0
+259	2	0
+78	0	1
+4570	0	1
+322	1	0
+1801	2	0
+836	3	0
+1509	0	1
+1732	0	1
+935	0	6
+1372	1	0
+625	2	12
+5009	1	1
+75	0	1
+20	1	0
+153	20	21
+489	4	326
+1375	1	0
+774	1	1
+16	1	1
+3642	5	0
+497	4	0
+174	9	0
+1317	0	3
+508	0	1
+1126	1	0
+1952	0	2
+565	2	0
+871	0	1
+1460	6	0
+55	0	1
+420	6	0
+57	1	1
+119	1	1
+427	1	0
+459	14	11
+448	0	1
+1275	7	7
+360	1	0
+73	1	1
+48	1	1
+4920	3	0
+713	41	34
+691	1	1
+44	1	1
+1642	9	10
+566	0	1
+173	0	4
+798	0	10
+810	1	0
+78	18	17
+1531	0	2
+1274	1	1
+39	1	1
+53	3	1
+202	0	1
+707	17	17
+1733	0	1
+14053	3	0
+286	3	1
+5600	4	0
+6458	0	1
+4866371	102000	0
+1870113	257	0
+590050	6	18
+2095	12	12
+24846	1	0
+5154	22	22
+1561	0	4
+5946	1	0
+2317	0	4
+1643	1	1
+27	1	1
+1237	1	0
+2698	1	1
+140	1	1
+1689	0	2
+836	29	30
+5333	1	0
+509	1	0
+5216	6	0
+10782	47	47
+1095	13	3
+1039	0	1
+11605	1	0
+22064	0	1
+16612	8	0
+902	1	0
+757	1	0
+619	0	1
+10979	1	1
+18	1	1
+1517	1	0
+4576	1	0
+12559	4	0
+2725	0	1
+5291	2	0
+8706	0	1
+83	1	0
+424	0	7
+72	38	0
+5528	1	0
+23971	1	0
+7855	54	22
+4095	0	1
+803	5	5
+6382	6	0
+3545	0	28
+4265	0	2
+13194	6	6
+6463	1	0
+26075	1	1
+59	1	1
+10791	17	7
+707	0	1
+210	1	0
+1655	0	2
+5301	1	0
+1930	1	0
+14632	2	0
+1043	1	0
+3607	3	0
+312	0	1
+5953	2	0
+170	0	17
+489	0	1
+5260	0	28
+888	10	0
+2461	10	10
+237	2	0
+1716	3	1
+10691	0	4
+3757	1	0
+6173	0	1
+8017	1	2
+3594	0	4
+5439	0	1
+4138	28	57
+6418	0	1
+1267	1	0
+720	0	6
+1083	2	0
+3878	0	1
+3310	23	23
+4349	1	1
+44	1	1
+3135	0	1
+174853	1	2
+2008	7	7
+5657	0	1
+6496	0	3
+89	0	5
+665	0	1
+954	46	46
+375	7	8
+1248	28	28
+2041	0	2
+2753	1	0
+1863	0	3
+3228	1	0
+3575	0	4
+40	1	1
+6488	0	2
+8612	11	11
+3795	0	16
+2105	0	1
+268	1	1
+22	3	0
+7889	4	0
+701	4	0
+2411	28	34
+2943	2	3
+8420	1	0
+926	0	324
+6732	1	0
+543	4	3
+4028	2	0
+51	52	40
+3000	1	0
+530	1	0
+2083	0	2
+1173	0	17
+119	16	16
+2727	1	0
+543	0	1
+783	1	0
+1372	0	4
+8624	20	0
+278	44	44
+4364	51	50
+2856	0	1
+5399	0	1
+1506	1	0
+919	0	6
+7229	10	0
+3225	1	0
+435	1	0
+2814	47	47
+1577	0	132
+9785	0	1
+2035	6	0
+7655	1	0
+198207	0	132
+11704	0	5
+7648	1	0
+9062	4	0
+8778	0	2
+7014	1	0
+1613	0	2
+790	7	5
+7433	1	0
+6482	12	12
+6798	0	1
+1422	1	0
+3454	1	1
+43	1	1
+3097	0	2
+334	0	18
+1444	1	0
+2400	3	0
+3272	0	1
+9106	1	0
+1573	0	1
+4742	1	0
+3366	1	0
+5484	0	1
+2444	0	5
+5448	8	8
+2539	0	1
+1471	0	1
+238	1	1
+16	1	1
+288	5	5
+2995	0	2
+951	1	1
+35	1	1
+279	16	15
+3534	6	0
+3513	0	1
+163	0	1
+6173	0	1
+1074	1	0
+2818	1	0
+2868	0	1
+3796	1	0
+1118	1	167
+1278267	25	25
+10747172	0	217
+3504877	0	1053
+10844	13	11
+18805	1	0
+1960834	126729	50000
+3065	1	0
+3601036	90008	8833
+34292	1	0
+1834	0	44
+3083	1	1
+43	1	1
+789	1	0
+11432680	153000	50000
+1902015	0	4098
+99	0	21
+3183	6	6
+877	1	1
+49	1	1
+296	0	1
+1375	1	1
+21	1	1
+607	5	5
+98	0	22
+6811	1	1
+17	0	11
+3804	1	0
+1356	1	1
+29	1	1
+297	1	0
+9543	0	2
+3130	0	4
+861	0	1
+27346	1	0
+7547	8	6
+2834	0	2
+394	4	0
+6524	1	0
+405	11	8
+1128	7	0
+271	1	1
+21	0	28
+507	6	0
+1211	44	31
+384	0	3
+521	18	18
+395	11	0
+799	1	1
+25	3	2
+51	1	49
+49	1	1
+558	0	1
+351	1	0
+2779	13	13
+114398	65008	82124
+7795	0	1
+18	1	1
+4140	1	0
+28048	1	1
+32	1	1
+4630	1	0
+4573	3	0
+357	2	0
+4812	1	0
+14372	0	3
+203	0	1
+26257	1	0
+2734	0	2
+19262	5	5
+5022	0	1
+25471	0	1
+1114538	0	53
+82	126	0
+1416	16	16
+629	57	0
+463	1	0
+148	1	1
+24	1	1
+2322	1	1
+23	1	0
+725	0	16
+24	16	0
+95	9	9
+1277	0	1
+2498	0	1
+354	49	0
+41	0	50
+17	0	49
+37	0	49
+65	8	152
+906	0	47
+234
+
+chain	3352932	17	78774742	+	33364384	33585329	17	81195210	-	44852585	44945131	363
+36	7017	7017
+2072	1	1
+16	1	1
+2167	2	0
+2513	1	1
+44	1	1
+1296	17	17
+860	5	0
+1482	0	11
+3433	1	1
+18	1	1
+393	0	3
+198	19	18
+1850	4	5
+267	1	0
+1125	6	7
+1255	1	0
+1502	0	1
+37	0	1
+26	0	1
+302	0	1
+1164	4	2
+1145	8	8
+1170	0	1
+298	1	2
+330	1	0
+2433	13	13
+79	0	2
+5343	1	1
+26	1	1
+994	1	3
+943	0	3
+2485	1	1
+22	1	1
+1574	129212	0
+265	54	54
+5225	26	26
+995	36	36
+240	1	0
+5900	61	61
+112	65	65
+53	14	14
+150	95	95
+160	48	48
+108	70	66
+401	0	6
+354	27	27
+56	65	65
+716	5	3
+1097	4	0
+518	27	27
+944	11	11
+579	37	37
+614	1	0
+2967	12	0
+601	1	10
+1307	35	35
+1719	0	889
+1973	0	3
+709	2	0
+496	5	1
+185	11	11
+98	1	0
+724	3	0
+2103	0	5
+1038	0	1
+257	7	0
+231	1	0
+312	0	2
+423	6	6
+520	10	13
+294	1	0
+17	1	1
+413	4	0
+1698	1	1
+46	1	1
+597	1	1
+21	1	1
+1182	0	2
+50	1	1
+44	0	2
+34	66	3
+3318	3	0
+624	7	0
+507	0	1
+60	1	1
+49	1	1
+332	1	1
+38	1	1
+77	1	1
+19	1	1
+65	1	0
+1174	5	0
+76
+
+chain	1309281	17	78774742	+	33410392	33424757	17	81195210	+	36336024	36350387	1779
+203	116	116
+6522	2	0
+5195	584	584
+1743
+
+chain	421642	17	78774742	+	33424760	33429230	17	81195210	-	44789041	44793512	103557
+258	1	0
+320	0	1
+3477	0	1
+414
+
+chain	288364	17	78774742	+	33534894	33553104	17	81195210	+	60335980	60353933	1564
+39	403	82
+124	31	31
+264	17	18
+283	79	89
+146	36	36
+392	27	27
+75	32	32
+295	106	106
+170	1	0
+69	35	35
+148	57	57
+152	23	23
+96	16	16
+594	57	58
+172	87	87
+108	39	39
+156	68	68
+148	63	63
+54	9	9
+39	289	289
+30	13136	13189
+45
+
+chain	141893	17	78774742	+	38701721	38703214	17	81195210	+	41346194	41347687	907641
+1493
+
+chain	138910	17	78774742	+	59795041	59797994	3	198022430	+	46191235	46194190	927459
+65	140	139
+77	32	32
+50	53	53
+51	108	111
+72	86	86
+65	76	76
+109	74	74
+120	2	0
+121	111	111
+69	23	23
+101	39	39
+56	40	40
+294	20	20
+65	100	100
+105	124	124
+147	116	116
+64	108	110
+70
+
+chain	73899	17	78774742	+	33536708	33552896	17	81195210	+	36333128	36349315	1571
+27	75	75
+32	306	306
+95	240	240
+35	148	148
+57	881	881
+57	172	172
+87	108	108
+39	156	156
+68	148	148
+63	6667	6667
+36	6153	6152
+49	112	112
+64	239	239
+74
+
+chain	29385	17	78774742	+	33422514	33422962	17	81195210	+	60352539	60352987	2653
+73	72	72
+133	53	53
+117
+
+chain	28843	17	78774742	+	33535172	33536316	17	81195210	+	34740000	34741144	3516
+164	124	124
+31	564	564
+79	146	146
+36
+
+chain	23419	17	78774742	+	40573363	40573608	17	81195210	-	37977034	37977279	7093437
+245
+
+chain	22267	17	78774742	+	59795106	59797450	15	102531392	+	100960318	100962666	927477
+74	509	513
+86	250	250
+74	1061	1061
+100	108	108
+82
+
+chain	19110	17	78774742	+	33422430	33422845	17	81195210	+	34807497	34807912	5737
+84	73	73
+72	133	133
+53
+
+chain	15302	17	78774742	+	59872221	59872543	X	155270560	+	133327972	133328295	14745200
+91	145	146
+86
+
+chain	15089	17	78774742	+	33553212	33554185	17	81195210	+	34758015	34758988	3454
+70	755	755
+27	56	56
+65
+
+chain	12559	17	78774742	+	41846587	41875489	17	81195210	+	44708735	44737620	783
+44	4372	4365
+43	24396	24386
+47
+
+chain	12028	17	78774742	+	253252	253513	17	81195210	+	253455	253745	1186280
+87	116	116
+26	30	59
+2
+
+chain	9840	17	78774742	+	59850421	59850563	12	133851895	-	30785452	30785594	23191844
+56	27	27
+59
+
+chain	8117	17	78774742	+	33410595	33410681	17	81195210	+	34744635	34744721	10477
+86
+
+chain	7470	17	78774742	+	59872141	59872220	8	146364022	-	25940938	25941017	21166303
+79
+
+chain	6548	17	78774742	+	59823421	59823489	9	141213431	+	108396482	108396550	29214974
+68
+
+chain	6212	17	78774742	+	33601781	33601849	17	81195210	+	34807429	34807497	5781
+68
+
+chain	6147	17	78774742	+	33578902	33578968	17	81195210	+	34784578	34784649	3380
+29	0	5
+37
+
+chain	5883	17	78774742	+	33556525	33558123	17	81195210	+	34761324	34762919	3874
+27	1534	1531
+37
+
+chain	5739	17	78774742	+	59862459	59862519	13	115169878	+	43436593	43436653	31343618
+60
+
+chain	5729	17	78774742	+	59852430	59852489	7	159138663	-	42785228	42785287	31366016
+59
+
+chain	5493	17	78774742	+	254397	254454	17	81195210	+	254136	254193	32044913
+57
+
+chain	5493	17	78774742	+	254339	254396	17	81195210	+	254136	254193	32044914
+57
+
+chain	4633	17	78774742	+	59795405	59797489	7	159138663	+	22571262	22573349	985966
+53	1992	1995
+39
+
+chain	3684	17	78774742	+	59871978	59872017	5	180915260	+	67132991	67133030	32368210
+39
+
+chain	3604	17	78774742	+	59872312	59872350	6	171115067	+	73766967	73767005	18649321
+38
+
+chain	3578	17	78774742	+	59797823	59797921	9	141213431	-	46000791	46000889	1219359
+98
+
+chain	3496	17	78774742	+	59872079	59872141	X	155270560	-	52661918	52661980	17303862
+62
+
+chain	3063	17	78774742	+	59796390	59796453	18	78077248	+	3738092	3738155	1007405
+63
+
+chain	2832	17	78774742	+	78651772	78651801	17	81195210	+	81058451	81058480	35013371
+29
+
+chain	2507	17	78774742	+	254312	254338	17	81195210	+	254167	254193	28153285
+26
+
+chain	2327	17	78774742	+	253481	253511	17	81195210	+	253858	253888	2965414
+30
+
+chain	2229	17	78774742	+	59795509	59795562	9	141213431	+	99971007	99971060	1163412
+53
+
+chain	2158	17	78774742	+	59871912	59871978	10	135534747	-	7120285	7120351	17475521
+66
+
+chain	2116	17	78774742	+	41755737	41755765	17	81195210	-	18330211	18330239	723
+28
+
+chain	2038	17	78774742	+	59872018	59872072	12	133851895	-	60047857	60047911	21673207
+54
+
+chain	1971	17	78774742	+	33410681	33410711	17	81195210	+	58084086	58084116	2335
+30
+
+chain	1910	17	78774742	+	59797697	59797752	7	159138663	-	95523915	95523970	1276958
+55
+
+chain	1797	17	78774742	+	59795569	59795617	8	146364022	-	39560190	39560238	1234503
+48
+
+chain	1764	17	78774742	+	59795840	59795881	17	81195210	-	78142303	78142344	1077161
+41
+
+chain	1713	17	78774742	+	59797636	59797671	10	135534747	-	112842234	112842269	1000659
+35
+
+chain	1680	17	78774742	+	59795180	59795214	3	198022430	+	108471362	108471396	1315432
+34
+
+chain	1591	17	78774742	+	59795881	59795916	X	155270560	-	139019545	139019580	1025236
+35
+
+chain	1456	17	78774742	+	59796656	59796685	6	171115067	+	121488440	121488469	989186
+29
+
+chain	1332	17	78774742	+	33532356	33535172	17	81195210	+	34572150	34574966	5130
+25	2722	2722
+69
+
+chain	1250	17	78774742	+	59795215	59795246	11	135006516	-	104930893	104930924	1222490
+31
+
+chain	1089	17	78774742	+	59795324	59795355	X	155270560	-	141145732	141145763	1311664
+31
+
+chain	1006	17	78774742	+	59797671	59797695	X	155270560	+	72606434	72606458	1154867
+24
+
+chain	622	17	78774742	+	33334125	33344374	17	81195210	-	46414201	46424210	397
+69	10130	9890
+50
+
+chain	20335446	17_random	2617613	+	224588	1377183	17	81195210	-	41910550	46712950	133
+1433	3	0
+976	0	1
+281	0	1
+1231	0	14
+2584	0	15
+2816	1	0
+3815	1	0
+122	1	1
+25	1	1
+335	0	1
+4687	29	0
+68	0	1
+1769	32	0
+616	3	0
+1017	1	1
+35	1	1
+864	17	17
+321	4	4
+47	1	1
+6467	8	10
+746	1	0
+188	30	0
+179	14	14
+120	1	1
+19	1	1
+477	1	1
+25	1	1
+300	5	5
+33	4	4
+968	6	6
+1546	1	1
+39	1	1
+66	1	1
+92	1	1
+349	12	12
+839	3	3
+36	1	1
+654	1	1
+88	1	1
+647	3	0
+993	10	8
+296	0	12
+183	4	4
+385	1	1
+25	1	1
+405	1	1
+29	1	1
+108	1	1
+36	1	1
+57	1	1
+88	2	1
+78	4	4
+39	1	1
+133	1	1
+133	1	1
+162	1	8
+398	14	14
+52	16	16
+122	1	1
+56	1	1
+98	1	1
+25	1	1
+332	1	1
+48	1	1
+83	0	1
+25	1	1
+71	1	1
+71	1	1
+79	4	0
+87	1	1
+207	1	1
+70	1	1
+263	16	16
+143	1	1
+72	1	1
+198	0	1
+1062	104	0
+6	61	0
+278	8	8
+454	49	49
+297	0	1
+1271	1	1
+48	1	1
+85	1	1
+66	1	1
+89	1	0
+327	1	1
+61	1	1
+51	1	1
+25	2	2
+72	1	1
+80	1	1
+132	1	1
+136	4	4
+63	1	1
+47	1	1
+134	1	1
+28	1	1
+1004	1	1
+45	1	1
+2017	1	1
+22	1	1
+778	8	0
+3805	0	4
+3884	1	0
+1082	1	1
+39	1	1
+926	1	0
+12182	105	0
+19079	4	0
+108	0	6
+81968	13	12
+5894	126	0
+5069	696334	2698100
+65	1	1
+31	0	1
+165	15	0
+2504	0	2
+1155	0	10
+463	1	0
+2422	0	1
+90	10	0
+75	0	1
+397	0	1
+64	31	32
+1531	4	0
+2064	0	1
+1305	1	0
+1045	0	1
+1972	0	1
+3554	0	2
+428	1	0
+1541	10	12
+1808	1	0
+1758	0	1
+500	1	0
+737	1	0
+218	0	1
+2132	0	1
+744	0	1
+7456	2	0
+45	0	2
+2311	23	23
+727	0	2
+916	1	0
+360	5	5
+2956	0	1
+3263	3	0
+1460	1	1
+34	1	1
+117	1	0
+1852	10	0
+50	7	7
+3949	42	42
+528	40	40
+736	100	17954
+680	119199	29667
+516	22	22
+2397	100	1694896
+1291	0	4
+232	1	1
+32	1	1
+1529	0	4
+20	2	0
+42	0	2
+94	0	10
+402	1	1
+16	1	1
+1099	1	1
+49	1	1
+2223	32	32
+1530	36	36
+1563	57608	84063
+160	94	94
+164	108	108
+123	61	61
+136	449	449
+3509	28	28
+1092	1	0
+611	1	1
+28	1	1
+2932	1	1
+52	49	45
+64	1	1
+27	1	1
+1320	1074	0
+6819	0	1
+4716
+
+chain	16836081	17_random	2617613	+	2022361	2536424	17	81195210	+	77630507	81150656	169
+143	0	4
+116	4	4
+74	12	10
+298	1	0
+533	1	0
+340	27	27
+130	16	16
+184	15	14
+699	1	0
+68	1	0
+153	1	0
+1835	1	0
+5	2	0
+95	1	0
+105	6	4
+14	1	0
+10	1	0
+88	1	0
+63	1	0
+27	1	0
+37	1	0
+18	1	0
+75	1	0
+49	2	0
+366	1	0
+206	1	0
+114	1	0
+237	1	0
+265	16	12
+223	1	0
+182	1	0
+26	1	0
+34	1	0
+138	1	0
+170	1	0
+26	1	0
+16	1	0
+53	4	2
+85	1	0
+188	1	0
+107	1	0
+31	1	0
+180	1	0
+4	2	1
+4	1	0
+16	1	0
+21	1	0
+324	1	0
+106	2	0
+46	1	0
+74	1	0
+12	1	0
+557	2	0
+194	5	2
+23	1	0
+67	6	3
+7	1	0
+50	1	0
+143	1	0
+190	1	0
+24	1	0
+310	1	0
+204	1	0
+108	1	0
+15	1	0
+212	1	0
+3	1	0
+57	4	2
+44	1	0
+298	1	0
+38	1	0
+54	1	0
+112	1	0
+20	2	0
+79	1	0
+10	6	3
+12	1	0
+59	1	0
+51	1	0
+234	2	0
+43	1	0
+194	1	0
+5	1	0
+96	9	4
+67	2	0
+270	1	0
+13	1	0
+59	1	0
+54	1	0
+57	1	0
+375	1	0
+50	1	0
+87	1	0
+83	4	2
+234	4	2
+44	1	0
+24	7	4
+25	1	0
+44	1	0
+139	1	0
+201	12	9
+215	1	0
+5	1	0
+30	1	0
+43	1	1
+54	16	13
+210	1	0
+109	2	0
+55	1	0
+14	1	0
+126	1	0
+79	1	0
+326	1	0
+18	1	0
+150	1	0
+13	1	0
+85	1	0
+47	1	0
+16	1	0
+41	1	0
+43	5	3
+56	1	0
+62	1	0
+164	1	0
+108	1	0
+20	2	0
+137	1	0
+214	1	0
+14	1	0
+5	2	0
+60	5	3
+24	1	0
+72	2	0
+25	1	0
+23	1	0
+60	1	0
+53	1	0
+15	1	0
+145	1	0
+337	1	0
+112	1	0
+39	1	0
+234	1	0
+7	2	0
+108	1	0
+19	1	0
+150	1	0
+22	5	3
+221	1	0
+30	1	0
+195	1	0
+126	1	0
+116	1	0
+189	1	0
+231	1	0
+87	2	0
+136	2	0
+69	1	0
+350	1	1
+29	1	0
+76	1	0
+42	1	0
+10	3	1
+63	1	0
+168	1	0
+97	1	0
+11	1	0
+291	1	0
+150	1	0
+10	1	0
+141	15	12
+9	1	0
+35	1	1
+57	1	0
+9	2	0
+211	1	0
+193	1	0
+51	1	0
+337	1	0
+94	1	0
+9	1	0
+58	1	0
+152	1	0
+58	1	0
+127	1	0
+6	1	0
+65	1	0
+379	1	0
+93	1	0
+11	1	0
+106	1	0
+545	1	0
+11	1	0
+66	2	0
+28	1	0
+242	4	2
+32	8	5
+373	10	9
+242	1	0
+207	1	0
+51	1	0
+132	1	0
+118	1	0
+19	2	0
+116	1	0
+16	1	0
+23	1	0
+54	1	0
+67	1	0
+62	1	0
+52	10	7
+15	2	0
+33	1	0
+248	1	1
+27	1	0
+122	1	0
+25	1	0
+55	1	0
+141	1	0
+57	1	0
+45	1	0
+21	1	0
+66	4	2
+23	1	1
+234	1	1
+25	2	2
+56	1	0
+34	1	0
+12	1	0
+11	1	0
+5	1	0
+54	1	0
+16	1	0
+64	1	0
+361	1	1
+24	1	0
+111	1	0
+12	1	0
+74	1	0
+56	1	0
+43	1	0
+21	1	0
+8	1	0
+13	2	0
+34	1	0
+59	1	0
+79	1	0
+159	1	0
+69	2	0
+15	2	0
+8	1	0
+142	19	17
+302	1	0
+49	1	0
+114	1	0
+72	1	0
+38	1	0
+16	1	0
+39	1	0
+106	1	0
+16	3	1
+31	1	0
+5	1	0
+43	1	0
+120	1	0
+16	1	0
+82	1	0
+47	4	1
+10	6	3
+59	1	0
+10	1	0
+258	1	0
+97	14	13
+72	1	0
+126	1	0
+14	1	0
+92	1	0
+406	1	0
+194	1	0
+43	1	0
+30	1	0
+50	1	0
+8	1	0
+161	6	4
+39	1	0
+12	1	1
+60	1	0
+61	1	0
+23	1	0
+13	1	0
+41	2	0
+260	1	0
+144	1	0
+38	1	0
+45	1	0
+17	1	0
+73	1	0
+64	20	13
+25	1	0
+84	1	0
+42	11	6
+180	1	0
+32	2	0
+172	0	1
+65	1	0
+53	1	0
+39	3	1
+203	1	0
+16	3	1
+42	3	2
+27	6	4
+13	1	0
+99	1	0
+34	4	2
+511	1	0
+182	1	0
+230	8	3
+42	1	0
+16	1	1
+270	5	4
+13	1	0
+141	1	0
+100	1	0
+144	1	0
+146	1	0
+356	1	0
+99	1	0
+69	2	0
+146	1	0
+55	18	14
+54	7	4
+18	1	0
+170	2	0
+45	1	0
+13	1	0
+628	1	0
+93	1	0
+46	1	0
+131	1	0
+20	1	0
+98	1	0
+20	1	1
+355	0	2
+88	1	0
+121	1	0
+31	1	0
+27	1	0
+132	1	0
+64	1	0
+43	1	0
+30	1	0
+95	1	0
+22	1	0
+44	6	3
+20	1	0
+138	1	0
+198	1	0
+100	1	0
+163	1	0
+6	1	0
+155	1	0
+79	1	0
+34	1	0
+193	1	0
+159	1	0
+50	5	3
+30	1	0
+9	1	0
+115	1	0
+93	1	0
+54	1	0
+91	1	0
+336	1	0
+134	18	13
+126	1	0
+61	1	0
+133	1	0
+613	4	2
+244	1	0
+586	1	0
+5	1	0
+93	19	16
+148	6	3
+12	2	1
+20	1	1
+138	102	11399
+572	8	6
+529	1	0
+659	1	1
+35	1	0
+191	2	0
+56	1	0
+105	1	0
+18	1	0
+226	1	0
+59	15	16
+275	1	0
+87	1	0
+5	1	0
+85	1	0
+21	1	0
+71	1	0
+507	1	0
+21	3	1
+82	1	0
+32	1	0
+39	1	1
+312	1	0
+263	1	0
+196	5	3
+23	5	3
+275	1	0
+46	2	0
+154	0	6
+229	1	0
+27	1	0
+87	1	0
+5	2	0
+502	1	0
+97	105	101
+162	1	0
+114	1	0
+65	1	1
+43	1	0
+217	1	0
+14	1	0
+172	1	0
+326	1	0
+9	1	0
+446	1	0
+73	1	0
+245	2	0
+114	1	0
+237	1	0
+35	22	13
+318	1	0
+320	1	0
+76	1	1
+54	1	0
+44	1	1
+100	1	0
+30	0	1
+462	1	0
+22	1	1
+72	1	1
+121	1	0
+37	1	0
+22	5	0
+23	1	1
+154	1	0
+63	1	1
+87	1	0
+278	1	0
+36	1	1
+230	1	0
+182	3	1
+51	1	0
+7	1	0
+101	1	0
+39	1	0
+17	1	0
+55	1	0
+13	1	0
+114	1	0
+13	1	0
+24	1	1
+69	10	9
+171	1	0
+60	1	1
+77	1	1
+8	2	1
+25	1	0
+51	1	0
+327	1	0
+105	2	0
+133	0	1
+28	1	0
+67	1	0
+119	4	2
+334	1	0
+37	2	1
+47	1	0
+165	1	0
+29	1	0
+35	1	0
+46	1	0
+9	1	0
+657	1	0
+62	1	0
+171	1	0
+17	1	0
+113	1	0
+15	1	1
+123	1	1
+62	1	0
+4	1	1
+288	21	0
+809	0	1
+22	1	0
+61	1	0
+52	1	0
+25	2	0
+263	3	1
+35	1	0
+192	238701	2061422
+87	1	0
+6	1	0
+1080	1	0
+76	1	0
+1007	1	0
+98	1	0
+35	1	0
+134	1	0
+285	1	0
+33	0	1
+225	1	0
+281	1	0
+108	1	0
+55	1	0
+107	1	0
+202	15	12
+111	1	0
+36	2	0
+25	1	0
+202	1	0
+97	1	0
+143	1	1
+21	1	0
+222	1	0
+41	1	0
+492	0	4
+594	1	0
+181	1	0
+410	1	0
+37	1	0
+13	1	0
+34	1	0
+76	38	37
+204	27	27
+204	40	32
+432	1	0
+143	1	0
+271	1	0
+224	96	91
+385	1	0
+337	1	0
+375	1	0
+139	22	17
+297	1	0
+72	1	0
+5	2	0
+193	1	0
+8	1	0
+28	1	0
+17	1	0
+17	1	0
+445	1	0
+169	1	36
+35	3	1
+425	1	0
+41	1	0
+37	1	0
+79	1	0
+100	1	0
+130	1	0
+419	1	0
+17	1	1
+284	3	1
+56	1	0
+9	2	1
+655	1	0
+158	2	0
+8	1	0
+34	1	1
+519	1	0
+39	1	0
+78	1	0
+216	1	0
+3	1	0
+68	1	0
+56	1	0
+70	1	0
+290	0	4
+46	0	2
+108	0	2
+23	0	114
+830	1	0
+136	76	98
+63	65	64
+380	1	0
+106	1	1
+358	1	0
+64	1	1
+17	1	0
+171	5	3
+27	1	1
+130	13	10
+131	1	0
+415	1	0
+5	1	0
+37	1	0
+29	1	0
+27	1	0
+750	1	0
+249	1	0
+221	1	0
+109	1	0
+50	1	0
+323	1	0
+296	1	0
+383	1	0
+67	1	0
+239	2	0
+248	1	0
+9	1	0
+180	1	0
+241	1	0
+40	3	1
+6	1	0
+19	1	0
+27	1	0
+166	1	0
+80	1	0
+163	1	0
+33	1	0
+9	1	0
+172	1	0
+261	1	0
+200	1	0
+14	6	2
+121	1	0
+37	4	2
+74	1	0
+97	5	3
+10	2	1
+51	1	0
+642	1	0
+317	14	11
+163	3	1
+25	2	0
+875	1	0
+128	1	0
+211	8	4
+409	1	0
+233	1	0
+263	1	0
+12	1	0
+73	1	0
+188	1	0
+96	1	0
+183	1	0
+126	1	0
+235	1	1
+68	0	1
+618	1	0
+13	1	0
+73	1	0
+1315	883	57
+78	2	2
+774	1	0
+21	1	0
+13	1	0
+9	2	0
+168	1	0
+214	1	0
+84	3	1
+645	1	0
+150	1	0
+72	1	0
+8	1	0
+108	1	0
+120	1	0
+1469	1	0
+38	1	0
+697	1	0
+44	1	0
+345	1	0
+126	1	0
+46	1	0
+110	1	0
+972	1	0
+104	23	22
+93	2	2
+38	1	0
+34	3	1
+730	1	0
+151	1	0
+124	1	0
+210	1	0
+60	1	0
+227	1	0
+122	1	0
+225	2	0
+26	1	0
+85	1	0
+84	6	3
+408	1	0
+5	3	1
+18	1	0
+69	1	0
+76	1	0
+122	1	0
+288	1	0
+10	1	0
+55	1	0
+22	2	0
+455	1	0
+246	1	0
+37	1	0
+153	1	0
+27	1	0
+101	1	0
+158	1	0
+107	1	0
+437	1	0
+31	1	0
+149	1	0
+121	1	0
+5	1	0
+175	1	0
+76	1	0
+75	1	0
+26	2	0
+98	1	0
+169	1	0
+82	1	0
+20	1	0
+326	1	0
+274	1	0
+78	1	0
+42	1	0
+64	1	0
+11	7	4
+39	1	0
+91	1	0
+140	1	0
+397	14	12
+500	7	4
+879	5	2
+448	1	0
+42	1	0
+522	1	0
+247	1	0
+484	1	0
+689	1	0
+66	1	0
+198	1	0
+441	1	0
+143	1	0
+35	1	0
+84	1	0
+9	1	0
+445	1	0
+110	1	0
+204	1	0
+31	1	0
+77	1	0
+54	1	0
+213	1	0
+601	1	0
+25	1	0
+239	2	2
+42	1	0
+29	2	0
+15	1	0
+175	1	0
+611	1	0
+418	1	0
+191	1	0
+295	1	0
+30	8	5
+609	1	0
+372	1	0
+154	2	0
+117	1	0
+282	1	0
+360	1	0
+750	1	0
+402	1	0
+45	1	0
+678	1	0
+17	1	0
+117	1	0
+148	1	0
+164	3	1
+51	1	0
+65	1	0
+452	1	0
+1443	1	0
+142	1	0
+509	1	0
+92	10	6
+264	1	0
+69	1	0
+78	1	0
+43	1	0
+164	1	0
+349	1	0
+117	1	0
+373	1	0
+235	1	0
+160	1	0
+8	1	0
+263	1	0
+15	1	0
+23	1	0
+151	1	0
+100	1	0
+204	1	0
+250	1	0
+33	3	1
+272	1	0
+262	1	0
+55	1	0
+519	1	0
+251	1	0
+189	1	0
+459	1	0
+183	1	0
+295	1	0
+552	1	0
+94	16	12
+259	1	0
+30	1	0
+396	1	0
+17	1	0
+72	1	0
+56	1	0
+90	1	0
+106	1	0
+19	2	0
+271	1	0
+448	1	0
+628	497	497
+254	26	26
+391	1	0
+32	1	0
+171	1	0
+126	20	17
+94	1	0
+446	1	0
+30	1	0
+96	1	0
+17	1	0
+159	1	0
+390	1	0
+105	1	0
+94	1	0
+5	2	0
+21	1	0
+22	1	0
+380	1	0
+12	1	0
+211	1	0
+377	1	0
+3	1	0
+63	1	0
+37	2	2
+1596	1	0
+638	1	0
+30	1	0
+665	13	10
+32	1	0
+102	1	0
+361	1	0
+609	1	0
+590	1	0
+1189	29	29
+345	1	0
+732	1	0
+544	1	0
+272	1	0
+725	1	0
+198	1	0
+8	1	0
+275	1	0
+95	1	0
+101	1	0
+626	1	0
+154	1	0
+242	1	0
+937	1	0
+142	1	0
+236	1	0
+456	12	9
+77	1	0
+189	1	0
+172	1	0
+201	1	0
+417	1	0
+179	1	0
+141	1	0
+219	1	0
+164	1	0
+138	1	0
+500	2	0
+263	1	0
+48	1	0
+17	1	0
+91	1	0
+169	1	0
+8	1	0
+185	1	0
+48	1	0
+345	1	0
+546	2	2
+229	2	2
+614	1	0
+73	2	2
+129	1	0
+91	1	0
+287	3	1
+504	2	0
+264	22	22
+508	1	0
+1324	1	0
+1313	1	0
+36	1	0
+346	1	0
+285	5	2
+31	1	0
+6	1	0
+133	1	0
+27	1	0
+101	1	0
+249	1	0
+68	5	3
+34	1	0
+31	1	0
+140	1	0
+350	1	0
+312	1	0
+139	1	0
+66	1	0
+24	1	0
+37	1	0
+16	1	0
+32	1	0
+204	1	0
+21	1	0
+11	1	0
+120	2	0
+161	1	0
+13	1	0
+143	1	0
+46	1	0
+136	3	1
+75	1	0
+176	1	0
+23	1	0
+30	1	0
+34	1	0
+307	1	0
+27	1	0
+261	1	0
+39	1	0
+995	1	0
+556	1	0
+211	1	0
+278	1	0
+850	1	0
+285	1	0
+207	1	0
+154	1	0
+51	1	0
+237	1	0
+204	1	0
+11	1	0
+348	2	0
+41	1	0
+75	2	0
+47	1	0
+49	1	0
+253	1	0
+171	10	6
+106	1	0
+83	1	0
+86	1	0
+30	1	0
+166	1	0
+297	1	0
+480	1	0
+285	1	0
+339	1	0
+30	1	0
+74	1	0
+15	1	0
+310	1	0
+88	1	0
+111	1	0
+104	1	0
+644	1	0
+29	1	0
+413	2	0
+33	3	1
+19	1	0
+321	1	0
+318	1	0
+131	1	0
+111	1	0
+89	1	0
+751	120	120
+314	1	0
+613	2	0
+991	3	1
+44	1	0
+42	1	0
+57	1	0
+102	1	0
+318	1	0
+47	2	0
+186	1	0
+550	1	0
+504	1	0
+76	1	0
+336	1	0
+505	1	0
+34	2	0
+61	1	0
+257	1	0
+439	1	0
+94	1	0
+18	1	0
+6	1	0
+86	1	0
+18	1	0
+179	1	0
+52	1	0
+635	1	0
+535	1	0
+90	1	0
+531	2	0
+59	1	0
+132	1	0
+122	1	0
+17	1	0
+96	1	0
+281	1	0
+145	1	0
+342	1	0
+132	1	0
+95	16	12
+417	1	0
+143	1	0
+135	1	0
+11	1	0
+486	1	0
+224	1	0
+277	1	0
+449	1	0
+321	34	30
+96	1	0
+20	1	0
+358	1	0
+146	1	0
+176	1	0
+37	1	0
+92	1	0
+115	1	0
+245	1	0
+72	1	0
+65	1	0
+108	1	0
+41	13	10
+121	65	54
+54	1	0
+359	1	0
+53	1	0
+55	1	0
+10	1	0
+5	1	0
+6	2	1
+43	1	0
+9	1	0
+223	1	0
+90	1	0
+157	1	0
+686	1	0
+250	1	0
+160	1	0
+264	50363	1224780
+4948	0	1
+1850	60	67
+3859	0	1
+456	4	5
+1605	21	21
+1281	7	13
+5090	456	0
+1543	1	1
+37	1	1
+2825	1	1
+64	1	1
+1075	0	1
+721	0	1
+5566	22	5
+1136	1	0
+2390	0	3
+1347	0	2
+4617
+
+chain	16543266	17_random	2617613	+	0	174588	GL000205.1	174588	+	0	174588	172
+174588
+
+chain	10747371	17_random	2617613	+	1609852	1757206	17	81195210	-	15050606	15196423	297
+3573	1	0
+1031	1	0
+4890	10	7
+318	0	1
+667	1	0
+168	0	2
+974	2	0
+143	2	0
+208	4	0
+2621	10	10
+634	2	0
+1898	0	2
+99	21	21
+6731	1	1
+49	1	1
+345	2	0
+210	1	1
+1621	1	0
+1077	0	2
+371	6	0
+4548	5769	26131
+1148	0	1
+1283	1	1
+24	1	0
+2931	0	6
+38	22	0
+682	0	1
+1267	0	2
+470	9	19
+2335	0	9
+720	8	0
+2859	26315	4346
+4414	0	1
+777	1	4
+894	4	0
+3207	0	3
+3071	0	1
+1338	1	0
+869	1	0
+2072	0	1
+395	1	0
+1060	8	8
+1138	1	1
+6	2	0
+40	1	1
+473	0	1
+748	2	0
+306	8	0
+81	6	0
+748	4	0
+158	0	22
+6454	0	2
+145	1	1
+49	1	1
+619	0	1
+1579	14	14
+455	1	0
+5224	1	1
+31	1	0
+31	0	57
+3855	0	2
+2164	11	21
+1491	0	4
+213	16	4
+4589	6	6
+1564	0	6
+325	0	1
+2241	0	1
+149	0	1
+4150	0	4
+4768	0	12
+411	0	6
+804	2	0
+124	19	19
+937	2	0
+997	27	29
+685	37	37
+5	2	0
+35	37	48
+29	1	1
+237	2	0
+333	0	1
+1296	31	23
+472	4	0
+34	1	1
+683
+
+chain	7797784	17_random	2617613	+	2131554	2212864	GL000204.1	81310	+	0	81310	420
+81310
+
+chain	5191141	17_random	2617613	+	986480	1282720	17	81195210	+	34482891	34744119	309
+118	29	29
+73	435	3450
+113	9	9
+74	44	43
+109	53	55
+147	361	38
+603	128	128
+69	8	8
+278	22	22
+1262	20	20
+83	37	44
+478	1	1
+32	1	1
+54	1	1
+81	1	1
+57	0	1
+71	4	4
+83	1	1
+103	1	1
+80	1	1
+15	1	1
+312	15	15
+185	1	1
+24	1	1
+720	1	1
+19	1	1
+185	1	1
+35	1	1
+144	7	7
+238	1	1
+62	3	3
+196	10	10
+123	1	1
+99	1	1
+1997	1	1
+27	1	1
+64	49	45
+19	1	1
+547	1	1
+16	1	1
+796	0	2
+213	0	1
+1353	0	5
+59	1	1
+604	1	0
+1099	28	28
+2219	0	1
+1732	6	6
+115	1	1
+80	1	1
+123	1	1
+106	1	1
+164	1	1
+92	1	1
+160	34984	45270
+79	5	5
+348	149	150
+73	23	23
+322	46	46
+284	35	28
+1307	16	16
+515	89	89
+62	9	9
+203	3	0
+65	10	9
+188	33	32
+342	1	0
+100	0	1
+67	48	52
+69	1	0
+2330	39	42
+356	2	0
+767	5	9
+69	4	0
+373	29	30
+138	1	0
+571	0	1
+273	13	13
+140	25	24
+457	39	39
+204	19	19
+137	49	49
+178	59	59
+220	38	38
+66	23	22
+315	1	0
+399	30	30
+345	62	62
+200	36	36
+1097	33	35
+255	5	0
+61	4	0
+371	48	33
+119	30	30
+52	0	2
+236	0	2
+81	13	13
+168	12	12
+174	0	1
+250	81	81
+185	35	35
+343	27	35
+271	232	235
+79	116	119
+288	61	61
+869	9	8
+282	7	0
+6366	1	0
+2033	112	1128
+417	0	1
+64	145492	5631
+587	0	2
+184	392	14227
+792	0	4
+408	2	1
+1608	0	1
+1287	0	2
+676	1	1
+31	1	1
+112	1	1
+91	1	1
+173	1	0
+42	1	14
+784	11	11
+3219	0	13521
+8127	24	23
+7132	0	12
+9450	0	4
+3351	28	28
+5832	3	0
+100	0	1
+67	0	5
+31	6	5
+10	1	1
+69	2	0
+2314	1	0
+11507	0	1
+742	0	63471
+5695	0	1
+731	1	0
+3536
+
+chain	4342758	17_random	2617613	+	615163	663282	17	81195210	-	81146986	81195210	699
+117	89	88
+430	1	1
+8	7	3
+19	1	1
+521	14	7
+577	1	0
+4	1	0
+284	1	1
+19	12	6
+55	3	0
+193	1	0
+383	16	13
+508	5	0
+404	6	1
+1326	31	25
+723	84	3
+41	75	0
+21	1	0
+303	27	0
+65	81	27
+94	1	1
+40	1	1
+118	746	87
+30	2	1
+37	1	1
+179	2	0
+43	1	1
+46	27	0
+35	32	0
+278	1	0
+353	8	10
+363	13	1
+106	4	0
+188	34	34
+206	1	0
+3	1	0
+1339	1	0
+632	1	1
+21	0	4
+248	1	0
+655	1	0
+258	1	0
+777	1	0
+1440	16	16
+124	1	1
+36	1	0
+33	1	1
+89	1	0
+165	1	0
+86	1	1
+47	1	1
+319	8	4
+506	4	2
+537	16	12
+2310	1	0
+7	2	0
+922	9	0
+294	1	0
+145	1	0
+1890	2	0
+15	1	0
+38	1	0
+2030	12	6
+1208	2	0
+107	1	0
+438	2	0
+492	2	0
+184	1	0
+42	1	1
+646	1	35
+28	4	4
+62	4	36
+43	0	32
+54	1	1
+8	2	0
+23	1	1
+77	0	32
+34	0	32
+52	1	167
+69	70	6
+61	0	36
+99	0	64
+605	22	22
+133	1	0
+296	1	1
+42	1	0
+361	10	6
+225	14	14
+387	1	97
+405	0	480
+101	1	0
+24	2	2
+339	0	336
+1176	1	0
+192	1	0
+553	1	0
+114	4	1
+544	18	12
+575	3	0
+85	1	0
+934	1	0
+667	13	7
+28	18	12
+770	10	6
+149	1	0
+884	22	20
+214	0	1
+607	1	0
+129	1	0
+14	6	4
+27	6	3
+10	1	0
+4	2	0
+155	39	28
+214	2	0
+43	1	1
+1236	44	27
+1759	2	0
+472	6	2
+342	8	5
+970	6	0
+227	1	0
+691	1	0
+359	2	0
+141	1	0
+5	1	0
+2008	1	0
+302
+
+chain	3923033	17_random	2617613	+	864624	922266	17	81195210	+	81075742	81117538	762
+924	1	0
+428	1	0
+763	1	0
+19745	32	32
+637	15873	36
+186	1	0
+2389	1	0
+616	1	0
+1932	12	12
+10081	18	18
+2216	1	0
+92	1	0
+271	4	4
+67	5	5
+698	83	82
+473	27	27
+62
+
+chain	3905383	17_random	2617613	+	460666	565054	17	81195210	+	41343520	41406910	763
+9362	3	1
+1313	0	1
+344	1	0
+2289	0	2
+14919	0	1
+1393	6	4
+1047	1	0
+21	0	1
+31	5511	0
+28	783	8
+978	3	4
+213	0	2
+2198	0	702
+75	4479	3549
+723	0	13
+165	1	1
+19	3	3
+113	0	4
+88	1	1
+41	1	0
+38	7	7
+98	17	17
+152	50743	16221
+115	169	185
+169	0	4
+278	1	1
+48	1	1
+6399
+
+chain	3524656	17_random	2617613	+	1876393	1913891	GL000203.1	37498	+	0	37498	830
+37498
+
+chain	3296870	17_random	2617613	+	1963891	2002673	GL000204.1	81310	+	42877	81310	872
+560	1	0
+101	2	0
+296	42	39
+438	2	0
+256	1	0
+136	1	0
+109	1	0
+101	2	0
+234	64	62
+405	37	35
+61	1	0
+366	5	3
+501	39	37
+142	1	0
+191	27	24
+59	6	4
+53	67	62
+91	1	0
+159	1	0
+74	40	38
+164	1	0
+57	28	26
+75	1	0
+46	1	0
+61	45	43
+117	1	0
+360	45	43
+204	1	0
+180	61	58
+589	1	0
+212	1	0
+88	1	0
+53	1	0
+492	1	0
+75	26	24
+273	1	0
+701	1	0
+444	1	0
+75	1	0
+393	11	9
+105	59	56
+72	42	40
+79	1	0
+79	1	0
+95	153	144
+127	1	0
+85	4	2
+175	3	0
+222	1	0
+121	1	0
+48	1	0
+50	1	0
+61	1	0
+213	1	0
+73	1	0
+180	2	0
+83	1	0
+58	1	0
+192	11	5
+57	140	125
+101	1	0
+91	38	34
+190	1	0
+73	1	0
+116	6	4
+275	16	14
+200	1	0
+201	3	1
+632	1	0
+60	1	0
+198	9	1
+254	2	0
+89	1	0
+60	38	36
+326	32	28
+306	1	0
+55	1	0
+100	18	16
+127	36	32
+67	1	0
+78	1	0
+90	1	0
+63	35	31
+120	150	141
+103	9	7
+406	88	85
+54	15	13
+142	9	7
+112	32	30
+237	1	0
+114	27	18
+157	40	38
+145	1	0
+380	20	18
+73	109	104
+57	1	0
+83	68	65
+567	1	0
+378	0	4
+282	29	27
+725	1	0
+204	1	0
+246	1	0
+295	17	15
+243	1	0
+187	46	44
+56	1	0
+244	1	0
+303	1	0
+121	16	15
+253	1	0
+273	44	44
+427	10	0
+403	2	0
+219	1	0
+151	1	0
+115	14	13
+193	1	0
+63	1	0
+63	38	36
+609	1	0
+81	42	40
+297	1	0
+455	17	14
+278	3	1
+691	1	0
+417	104	101
+57	1	0
+93	5	3
+309	48	47
+303	1	0
+324	1	0
+126	41	37
+138	2	0
+233	1	0
+100	50	47
+86	9	7
+256	1	0
+208	1	0
+486	3	1
+118	1	0
+70	69	64
+455	8	6
+149	1	0
+175	5	2
+115	1	0
+159	1	0
+109	12	9
+135	33	31
+53	1	0
+256	5	3
+82	41	38
+268	70	67
+600	1	0
+128	18	16
+114	1	0
+149	62	58
+99	57	54
+158	42	38
+88	1	0
+75	46	43
+300	50	47
+71	13	11
+118	1	0
+177	1	0
+120	1	0
+275	1	0
+74	13	11
+230	1	0
+117	6	4
+113	39	37
+71	1	0
+597	9	8
+82	10	6
+195	10	8
+361	1	0
+53	1	0
+291	0	1
+149	1	0
+164
+
+chain	2935078	17_random	2617613	+	1427191	1457644	17	81195210	+	81045288	81075743	955
+1667	2	0
+1156	0	2
+25	0	2
+27603
+
+chain	2199778	17_random	2617613	+	671651	748529	11	135006516	-	134809692	134880676	533
+53	3	0
+176	68	0
+22	38	1
+38	43	16
+122	41	249
+34	4	16
+5	1	0
+6	1	0
+68	0	37
+1042	1	1
+35	1	1
+27	326	0
+359	1	0
+3	2	0
+176	16	5
+44	5	1
+224	1	0
+432	1	1
+35	1	1
+266	21	16
+109	14	10
+806	0	34
+465	56	0
+57	4	0
+787	1	0
+283	1	1
+27	1	1
+1090	1	1
+81	1	0
+1354	1	0
+40	1	1
+305	1	0
+89	1	1
+63	1	1
+48	1	1
+167	11	11
+83	8	4
+45	5	3
+343	1	1
+47	49	0
+56	0	294
+17	49	0
+79	5	103
+162	49	0
+442	10	10
+438	3	0
+50	1	1
+676	1	1
+39	1	1
+66	1	1
+7	1	0
+35	1	1
+547	7	2
+549	2393	0
+3	2913	0
+65	1	0
+60	1	1
+69	1	1
+42	0	1
+175	5	4
+100	1	0
+402	1	0
+39	1	0
+10	1	0
+10	1	0
+14	1	1
+95	4	2
+120	0	5
+126	1	1
+32	2	1
+72	1	1
+335	1	1
+45	1	0
+403	4	1
+54	1	0
+108	1	0
+289	1	1
+40	1	0
+164	12	12
+169	1	1
+76	1	1
+71	3	3
+34	1	1
+65	72	72
+84	64	1
+55	190	1
+52	1	1
+42	5	5
+138	1	1
+39	1	1
+311	6	7
+300	1	0
+597	17	17
+187	1	1
+32	100	2817
+24	203	202
+36	1	1
+115	4	0
+139	25	24
+1050	1	0
+56	1	0
+90	1	0
+33	1	0
+35	3	0
+114	1	1
+19	1	1
+215	1	0
+431	1	1
+23	1	0
+421	14	11
+292	1	1
+22	1	1
+49	2741	2490
+33	4095	4075
+9	0	3
+18	1474	1474
+3	6	1
+11	3	0
+38	14404	14348
+27	15613	15513
+5	5	5
+21	1	2
+13	19	20
+34	104	104
+44	214	216
+8	3	0
+27	2800	929
+60	1	1
+29	4270	3383
+30	49	0
+26	1	1
+40	2712	2960
+33	1	1
+7
+
+chain	2173268	17_random	2617613	+	699498	748919	1	249250621	-	248538148	248591008	468
+685	3	3
+36	4	4
+73	9	5
+59	70	63
+42	285	48
+44	1	1
+96	74	80
+321	1	1
+49	1	1
+107	1	1
+47	11	2
+85	3	0
+67	1	0
+179	19	16
+220	9	0
+138	33	33
+136	1	1
+26	1	1
+545	1	0
+8	14	10
+42	1	1
+64	1	1
+28	1	1
+119	1	1
+49	1	1
+54	1	1
+32	1	1
+960	1	1
+41	1	1
+731	16	16
+57	1	1
+19	1	1
+118	1	0
+196	1	1
+50	1	1
+263	1	1
+52	1	1
+171	1	1
+26	1	1
+181	25	16
+51	27	0
+56	1	1
+139	0	4
+33	1	1
+236	1	1
+17	1	1
+192	15	13
+186	1	1
+30	7	7
+280	1	1
+80	1	0
+196	62	54
+290	1	1
+38	1	1
+772	10	10
+123	1	1
+28	1	0
+20	34	22
+81	0	4
+45	1	1
+806	1	1
+31	1	0
+35	1	1
+101	17	15
+89	1	1
+34	1	0
+8	1	1
+290	13	9
+284	1	0
+53	7	0
+26	6	0
+605	4	0
+531	35	35
+704	1	1
+66	1	1
+168	1	1
+34	1	1
+527	1	1
+30	1	1
+249	16	7
+414	1	1
+27	1	1
+344	1	1
+43	1	1
+117	1	1
+30	1	1
+862	0	1
+229	1	1
+48	1	1
+197	14	14
+972	19	31
+924	1	1
+42	1	1
+123	1	1
+56	1	1
+77	1	1
+23	1	1
+119	1	1
+53	18	11
+382	1	1
+17	1	1
+116	5	2
+37	1	1
+38	2	0
+223	1	1
+21	6	1
+583	1	0
+400	0	4
+1574	27	27
+54	4	1
+158	10	7
+336	6	7
+492	1	0
+14	1	1
+843	1	2
+247	1	1
+41	1	1
+50	6	6
+513	17	13
+615	12	12
+585	32	23
+161	6	6
+515	9	5
+43	5	3
+460	5	5
+158	11	11
+252	1	1
+22	3	0
+135	12	12
+556	0	1
+542	3	0
+298	4	1
+24	4	0
+117	9	5
+151	0	1
+291	0	1
+360	15	15
+962	20	17
+231	1	0
+293	1	0
+33	32	0
+40	15	10
+213	23	23
+458	1	1
+51	1	1
+437	1	0
+394	1	1
+25	2	0
+117	10	4
+50	1	1
+40	1	1
+626	8	5
+492	1	0
+383	1	0
+672	1	1
+136	1	1
+203	2	2
+88	1	1
+261	1	1
+45	1	1
+189	15	15
+78	1	1
+49	1	1
+93	1	0
+35	13	10
+21	1	1
+527	99	94
+103	44	44
+79	24	26
+111	39	36
+235	24	27
+117	7	7
+127	222	1777
+58	167	165
+59	75	75
+203	12	12
+55	56	44
+269	34	32
+87	24	24
+250	35	29
+682	91	91
+312	4	3
+583	124	2653
+132	399	398
+134	1	1
+33	1	1
+179	1	1
+27	1	1
+245	4	4
+93	1	1
+940	1	1
+20	1	1
+271	1	1
+16	0	1
+353	24	17
+369	146	0
+83	1	1
+34	1	1
+1103	1	1
+26	1	1
+112	1	0
+3	1	0
+370	32	27
+410	170	174
+51	1	1
+310	42	41
+66	5	2
+319
+
+chain	2047886	17_random	2617613	+	532224	554093	17	81195210	-	39794017	39815907	1262
+682	50	50
+270	0	4
+316	0	1
+691	1	0
+678	1	2
+601	1	0
+383	1	0
+20	1	1
+1048	2	0
+1884	0	6
+690	0	5
+1205	1	1
+43	0	2
+891	19	19
+1916	7	6
+2354	0	3
+2253	10	0
+2406	0	13
+1972	6	6
+595	0	4
+148	100	100
+356	20	20
+109	4	4
+73	2	0
+59
+
+chain	1863993	17_random	2617613	+	1011919	1106715	17	81195210	+	34578530	36287451	432
+1027	148	148
+295	18	18
+204	37	37
+144	7	7
+238	38	38
+357	101	101
+125	64	64
+712	21	22
+181	126	1729
+702	0	2
+184	29	30
+236	37	37
+1080	60	65
+606	1	0
+328	63	63
+556	20	20
+94	37	37
+172	0	1
+1430	0	1
+151	53	53
+605	36	36
+292	1	0
+84	17921	60667
+87	11034	74480
+38	804	804
+30	345	345
+62	200	200
+36	1097	1097
+33	696	696
+48	119	119
+30	986	986
+81	185	185
+35	641	641
+232	79	79
+116	288	288
+61	11306	1517682
+155	7	0
+427	5	5
+742	2	0
+85	1	1
+401	1	1
+97	1	1
+566	1	0
+607	1	0
+1318	0	24
+1995	71	3
+34	0	2
+44	1	1
+39	0	1
+3518	0	4
+469	1	0
+294	10	13
+520	6	6
+403	0	3
+331	1	0
+231	7	0
+255	0	1
+3122	0	1
+729	0	1
+117	11	11
+186	4	0
+84	1	0
+412	2	0
+19	1	1
+1642	6	0
+628	1	1
+21	1	1
+377	50	50
+151	0	9
+2370	1	1
+35	1	1
+1328	1	10
+586	14	0
+789	12	13
+1397	0	1
+1521	0	2
+382	0	1
+866	1	1
+20	1	1
+710	2	0
+1259	161	161
+387	28	28
+53	24	24
+3626	1	0
+1718
+
+chain	1732426	17_random	2617613	+	2586433	2605017	17	81195210	-	39776940	39795500	1439
+1157	1	1
+31	0	5
+2053	8	8
+691	1	1
+30	1	1
+1212	3	0
+3864	1	0
+3	1	0
+56	15	0
+860	1	1
+30	1	1
+6532	4	4
+147	13	13
+1042	17	17
+319	7	0
+181	10	10
+68	42	42
+51	16	14
+115
+
+chain	1719393	17_random	2617613	+	1323861	1343929	17	81195210	+	45650033	45670000	1446
+76	1	1
+94	1	1
+84	9	9
+70	1	1
+43	1	0
+40	0	2
+126	1	1
+38	1	1
+391	1	1
+43	1	1
+100	0	1
+66	12	12
+65	1	1
+39	2	0
+9	4	0
+25	1	1
+99	1	1
+27	0	4
+362	22	4
+659	2	0
+433	0	20
+16	1	1
+117	1	1
+248	1	1
+200	1	1
+23	1	1
+248	6	0
+120	1	1
+930	1	1
+14	1	1
+76	1	1
+11	1	0
+23	2	0
+23	1	1
+236	1	1
+48	1	1
+108	1	1
+141	7	5
+50	1	1
+27	1	1
+306	0	3
+290	1	1
+20	0	1
+31	1	1
+618	5	6
+350	14	6
+55	0	2
+112	4	0
+50	1	1
+263	1	0
+51	1	1
+527	1	1
+47	1	1
+247	1	1
+34	3	3
+169	0	2
+33	3	0
+165	12	0
+163	1	1
+77	1	0
+56	26	26
+54	6	6
+338	2	0
+185	73	73
+336	0	3
+89	1	1
+19	1	1
+65	18	18
+89	0	1
+178	1	1
+45	1	1
+67	8	0
+347	0	1
+22	1	1
+192	1	1
+73	1	4
+38	0	1
+61	1	1
+164	1	1
+74	3	3
+260	5	0
+89	9	9
+142	1	1
+49	1	1
+71	0	1
+62	1	1
+391	1	1
+78	1	1
+100	1	1
+32	1	1
+155	11	12
+304	8	0
+79	1	1
+115	1	1
+29	1	1
+97	19	0
+168	1	1
+19	4	4
+359	2	0
+18	1	1
+358	1	1
+38	1	1
+83	1	1
+31	1	1
+389	1	1
+32	1	1
+128	1	1
+39	1	1
+54	1	1
+11	2	0
+165	4	0
+34	1	1
+58	1	1
+68	3	0
+230	1	1
+44	1	1
+276	16	16
+170	6	6
+104	1	1
+61	1	1
+107	6	6
+177	1	1
+66	5	0
+60	1	1
+14	1	1
+50	4	4
+15	1	1
+62	1	1
+194	1	1
+72	22	1
+39	1	1
+70	1	1
+42	1	1
+58	1	1
+36	1	1
+329	1	0
+136	1	1
+192	9	10
+682	24	21
+81	0	1
+367	12	12
+81
+
+chain	1570588	17_random	2617613	+	1644335	1687876	17	81195210	+	66068832	66112387	1087
+1168	16352	16361
+2197	2	0
+1554	1	0
+6339	0	4
+1936	0	7
+2357	2	0
+7231	1	0
+4401
+
+chain	1476469	17_random	2617613	+	2303443	2319476	17	81195210	+	79885696	79901628	1655
+880	1	0
+298	1	0
+60	43	40
+227	40	38
+326	1	0
+77	1	0
+148	1	0
+199	21	19
+60	1	0
+224	1	0
+173	1	0
+317	88	84
+84	1	0
+96	48	45
+432	1	0
+107	1	0
+505	1	0
+88	1	0
+551	1	0
+107	1	0
+176	1	0
+79	2	0
+127	1	0
+56	1	0
+239	1	0
+218	1	0
+11	1	0
+27	1	0
+256	1	0
+130	1	0
+60	1	0
+586	1	0
+96	1	0
+58	1	0
+80	1	0
+135	1	0
+55	1	0
+219	5	2
+11	4	2
+30	4	1
+368	1	0
+106	1	0
+119	18	13
+146	1	0
+636	1	0
+156	1	0
+541	1	0
+107	1	0
+97	1	0
+61	1	0
+66	1	0
+7	1	0
+238	1	0
+105	1	0
+13	1	0
+667	1	0
+85	1	0
+70	1	0
+642	1	0
+635	1	0
+57	1	0
+249	1	0
+237	1	0
+162	1	0
+166	1	0
+380	1	0
+271	1	0
+215	2	0
+260	1	0
+160	1	0
+62	1	0
+6	1	0
+185	1	0
+48	1	0
+265	5	2
+87	1	0
+186	1	0
+62	1	0
+20	1	0
+135
+
+chain	1260177	17_random	2617613	+	853052	928106	17	81195210	-	43628	125104	962
+949	1	0
+3976	1	0
+155	1	0
+1382	1	0
+174	1	0
+249	1	0
+3481	16	14
+138	196	313
+72	88	86
+491	22816	3210
+803	32	32
+116	1	0
+346	10	9
+779	1	0
+620	1	0
+336	1	0
+2035	1	0
+1010	1	0
+1029	22	20
+97	39	114
+77	79	0
+5135	26	26
+535	1	0
+2026	21	19
+206	2	0
+254	19578	45525
+174	1	1
+34	1	1
+97	25	25
+137	6	5
+2443	14	9
+445	1	0
+116	1	0
+2150
+
+chain	1227372	17_random	2617613	+	986700	1051441	17	81195210	+	34570816	36317431	617
+294	0	3023
+141	196	196
+44	109	109
+53	147	147
+19	33	32
+101	42	42
+166	603	602
+128	1742	1742
+37	15134	15157
+88	7169	151654
+89	3878	5468
+37	1080	1080
+60	1668	1668
+37	1753	1753
+53	605	605
+36	506	39138
+695	47	47
+375	59	59
+312	20	20
+185	37	37
+144	7	7
+238	38	38
+357	101	101
+125	64	64
+712	185	184
+2677	120	1494235
+1055	15	15
+700	4	4
+1174	24	24
+888	9	3
+1590	0	3
+913	18	20
+1011	1	1
+26	1	1
+2545	1	1
+35	1	1
+1283	87	87
+45	432	432
+149	418	418
+46	284	284
+2	3	3
+30	1838	1839
+89	540	540
+32	511	512
+48	2400	2403
+39	3223	3228
+39	360	360
+49	178	178
+59
+
+chain	1028733	17_random	2617613	+	2262901	2274699	17	81195210	-	1281214	1293541	2373
+276	161	161
+1171	1	0
+181	1	0
+943	1	0
+423	1	0
+384	47	47
+111	466	1042
+106	31	31
+75	4	4
+63	20	16
+142	1	0
+59	1	0
+607	1	0
+135	1	0
+31	1	0
+82	1	0
+266	1	0
+76	1	0
+5	4	2
+41	1	0
+52	1	0
+985	1	0
+87	1	0
+4	1	0
+114	1	0
+175	1	0
+30	1	0
+140	2	0
+22	1	0
+130	1	0
+239	1	0
+766	1	0
+203	1	0
+68	2	0
+252	1	0
+300	4	2
+377	1	0
+735	1	0
+279	5	2
+91	1	0
+66	1	0
+159	1	0
+7	1	0
+562
+
+chain	931587	17_random	2617613	+	978106	1010959	17	81195210	+	36277154	36406169	991
+1048	10	12
+382	0	1
+199	22	22
+381	8	8
+56	66	66
+80	176	176
+73	27	27
+90	32	32
+166	31	209
+634	0	4
+1199	65	65
+56	27	27
+255	27	27
+50	1	7
+422	5	5
+61	4	0
+80	311	311
+40	144	144
+53	3450	47979
+41	18030	69497
+201	21	0
+219	1	0
+310	0	1
+3136	0	1
+510	50	52
+321	3	0
+279
+
+chain	813092	17_random	2617613	+	1807252	1826317	17	81195210	+	22246129	22262163	2589
+338	20	20
+223	15	15
+164	162	162
+54	59	60
+73	230	230
+52	48	48
+50	66	66
+54	49	49
+257	14	14
+103	22	22
+96	5	5
+357	121	121
+100	88	88
+108	94	94
+490	34	34
+81	27	27
+54	82	82
+80	138	138
+128	12	12
+262	24	21
+199	35	35
+263	80	80
+84	52	52
+185	16	16
+75	113	113
+160	99	99
+70	27	27
+84	49	49
+59	25	25
+133	30	30
+64	45	45
+304	25	25
+986	74	74
+160	13	13
+209	22	22
+54	43	43
+61	156	156
+54	6	6
+77	5	5
+86	85	85
+117	48	165
+381	74	74
+262	32	32
+165	71	71
+57	95	95
+89	31	31
+114	140	140
+117	216	216
+77	5	5
+52	442	441
+185	60	60
+363	22	22
+179	11	11
+259	197	197
+118	35	35
+108	60	60
+61	61	61
+137	50	50
+53	56	56
+269	161	161
+106	103	105
+56	8	8
+368	41	41
+47	3145	0
+401	42	42
+90	23	23
+151	73	73
+81	148	146
+351
+
+chain	788653	17_random	2617613	+	1298766	1307227	17	81195210	-	44798207	44806654	6145
+463	1	0
+2422	0	1
+90	14	0
+75	0	1
+397	0	1
+64	1	1
+30	0	1
+202	1	0
+1329	2	0
+1396	1	0
+668	0	1
+280	45	45
+980
+
+chain	597412	17_random	2617613	+	807879	2303216	17	81195210	-	0	1281216	430
+180	1676	138
+25553	1	0
+149	14	14
+1938	1	0
+350	32	32
+1230	1	0
+3	1	0
+6237	1	0
+45	2	2
+6514	1	0
+228	662945	0
+7897	0	1
+2396	1	0
+1101	17	0
+41	1	1
+355	0	52
+50	18	1
+41	0	68
+84	34	0
+4918	0	1
+717	0	1
+313	1	1
+42	1	1
+73	29	31
+205	58	0
+414	1	1
+64	1	1
+959	1	1
+17	1	1
+2276	1	0
+739	0	1
+418	11	49
+1541	0	1
+3494	7	13
+1281	21	21
+1738	1	191
+26	0	38
+40	0	77
+67	5	5
+11	1	75
+55	2266	0
+112	47	9
+78	38	0
+24	1	1
+80	5	5
+551	0	5
+87	1	1
+35	1	1
+54	119	195
+74	1	1
+957	15	15
+64	1277	306
+91	1	1
+35	1	1
+820	48	67
+330	0	1
+2794	1	0
+1127	1	1
+19	0	5
+1483	715858	1169096
+78	1	0
+529	1	0
+25	1	0
+200	1	0
+643	2	0
+450	2	0
+211	1	0
+380	2	2
+180	2	1
+32	1	0
+246	1	0
+61	1	0
+5	1	0
+351	1	0
+37	1	0
+304	1	0
+18	1	0
+109	1	0
+16	1	0
+200	1	0
+105	1	0
+37	1	0
+376	1	0
+108	1	0
+91	1	0
+394	1	0
+20	1	0
+1014	32	30
+21	2	1
+34	1	0
+230	26	26
+941	1	0
+188	1	0
+610	1	0
+555	1	0
+303	1	0
+509	157	157
+169	22	22
+101	1	0
+501	1	0
+140	1	0
+78	2	1
+22	1	0
+39	6	5
+62	94	94
+593	114	111
+260	120	120
+362	1	0
+697	0	1
+123	28	28
+402	36	36
+904	1	0
+50	1	0
+379	1	0
+256	25	25
+23	17	17
+53	27	27
+556	1	0
+409	1	0
+106	1	0
+276	24	24
+35	2	0
+252	32	32
+213	4	4
+70	2	0
+27	4	2
+82	1	0
+17	1	0
+639	1	0
+172	11	7
+10	1	0
+76	1	0
+1582	1	0
+275	1	0
+21	1	0
+17	4	2
+66	1	0
+1653	1	0
+19	3	3
+139	179	179
+76	2	2
+60	1	0
+226	1	0
+538	1	0
+346	4	4
+42	25	25
+1319	1	0
+261	1	0
+512	1	0
+69	1	0
+480	2	0
+388	8	7
+305	5	5
+64	2	2
+846
+
+chain	590397	17_random	2617613	+	1317586	1323861	17	81195210	-	44817018	44823295	6400
+2259	1	0
+955	0	1
+2132	0	1
+744	0	1
+184
+
+chain	365975	17_random	2617613	+	1296053	1313819	17	81195210	+	45621804	45639993	6832
+81	12	44
+148	0	6
+401	61	62
+589	32	30
+259	39	57
+53	103	103
+231	127	131
+59	7954	7632
+45	980	978
+16	142	143
+82	46	46
+363	247	934
+159	50	48
+341	33	34
+57	16	16
+304	65	65
+69	9	9
+136	66	66
+138	57	57
+70	10	10
+70	123	120
+143	52	52
+152	15	19
+320	53	52
+121	0	1
+161	98	108
+97	59	59
+205	127	125
+55	11	11
+56	30	30
+88	43	43
+512	45	43
+125	143	136
+165	48	48
+56	24	24
+161	114	115
+364	40	40
+240
+
+chain	323854	17_random	2617613	+	753664	757726	11	135006516	+	51394886	51398944	206195
+84	571	570
+807	3	1
+2082	1	0
+514
+
+chain	193433	17_random	2617613	+	495545	497612	17	81195210	+	41377728	41379794	617459
+55	1	0
+1306	28	28
+677
+
+chain	170984	17_random	2617613	+	1315777	1317585	17	81195210	-	44815210	44817018	741311
+1808
+
+chain	158566	17_random	2617613	+	1808012	1818883	17	81195210	+	22251644	22262630	5258
+162	209	210
+87	88	88
+32	270	270
+48	855	855
+36	185	185
+88	888	888
+37	888	888
+35	263	263
+80	85	85
+51	276	276
+47	20	20
+46	329	329
+27	350	350
+4	5	5
+21	413	412
+25	986	986
+74	458	458
+43	137	137
+80	228	228
+85	546	663
+9	10	10
+55	262	262
+32	293	293
+68	116	116
+25	120	120
+109	148	148
+60	1	1
+67	6	4
+74	1	1
+7	134	134
+220	1	1
+65	1	1
+91	1	1
+62	186	186
+60
+
+chain	150869	17_random	2617613	+	749022	751008	11	135006516	+	51475668	51477652	852441
+306	379	377
+1301
+
+chain	148651	17_random	2617613	+	808184	809735	17	81195210	+	81137722	81139272	865111
+940	1	0
+610
+
+chain	145464	17_random	2617613	+	1314230	1315767	17	81195210	-	44813661	44815198	885049
+1537
+
+chain	120518	17_random	2617613	+	1343929	1345208	17	81195210	-	44843364	44844643	723183
+1279
+
+chain	116919	17_random	2617613	+	1353036	1364922	17	81195210	-	44845210	44857111	1380
+449	299	299
+31	164	164
+55	373	373
+449	9718	9733
+348
+
+chain	115845	17_random	2617613	+	508518	509981	17	81195210	-	39794017	39795500	1110103
+682	50	50
+270	0	4
+177	169	185
+115
+
+chain	114042	17_random	2617613	+	516500	517961	17	81195210	-	39794017	39795500	1127130
+682	50	50
+210	5	6
+54	0	6
+175	170	185
+115
+
+chain	113591	17_random	2617613	+	521388	522849	17	81195210	-	39794017	39795500	1131524
+58	0	1
+623	50	50
+210	5	6
+54	0	6
+175	171	185
+115
+
+chain	112548	17_random	2617613	+	503499	505329	17	81195210	-	39794017	39795500	1141710
+27	370	0
+655	50	50
+210	5	6
+54	0	7
+174	170	185
+115
+
+chain	92910	17_random	2617613	+	1642194	1643169	17	81195210	-	1314977	1315952	1374174
+975
+
+chain	86438	17_random	2617613	+	1345275	1346182	17	81195210	-	44844700	44845607	1472746
+907
+
+chain	80313	17_random	2617613	+	2609695	2610598	17	81195210	-	39794017	39794920	1580802
+682	50	50
+171
+
+chain	78741	17_random	2617613	+	1643269	1644095	17	81195210	+	79874782	79875608	1611354
+826
+
+chain	75472	17_random	2617613	+	1310578	1313579	17	81195210	-	44810007	44813007	188419
+53	282	282
+98	97	97
+59	205	205
+127	122	122
+30	88	88
+43	512	512
+45	125	125
+72	1	0
+70	165	165
+48	241	241
+114	364	364
+40
+
+chain	74354	17_random	2617613	+	1547620	1548395	8	146364022	-	2302524	2303299	1703290
+775
+
+chain	61189	17_random	2617613	+	1546707	1547351	8	146364022	+	144057273	144057917	2067192
+644
+
+chain	59362	17_random	2617613	+	751149	753548	1	249250621	-	248579195	248581575	182656
+35	2	1
+152	1	0
+15	1	0
+107	3	2
+74	1	0
+10	1	0
+19	1	0
+57	1	1
+48	3	1
+6	1	0
+107	12	330
+61	1	1
+51	357	35
+388	110	110
+84	38	38
+62	227	223
+116	106	105
+141
+
+chain	56858	17_random	2617613	+	1298104	1298766	17	81195210	-	44797535	44798197	1968612
+85	59	59
+518
+
+chain	56536	17_random	2617613	+	501286	502149	17	81195210	-	39794614	39795500	2243684
+85	50	50
+210	5	6
+54	0	7
+174	170	185
+115
+
+chain	55411	17_random	2617613	+	688273	689806	7	159138663	-	159114165	159114723	7844
+88	175	0
+148	458	0
+103	231	3
+111	117	3
+102
+
+chain	52941	17_random	2617613	+	1822234	1824166	17	81195210	-	58941545	58943477	1155
+887	1	1
+77	1	1
+300	1	1
+20	9	9
+133	1	1
+23	1	1
+59	1	1
+158	1	1
+91	1	1
+54	1	1
+112
+
+chain	52559	17_random	2617613	+	983839	1162005	17	81195210	-	44845659	46605886	726
+299	65	65
+117	68	68
+1986	9723	54270
+49	72036	1500609
+1027	6412	6412
+71	13528	13528
+50	11447	11447
+132	60546	169487
+42	528	528
+40
+
+chain	51097	17_random	2617613	+	1023443	1026449	17	81195210	+	34744258	34747264	8774
+47	375	375
+59	517	517
+37	389	389
+38	357	357
+101	125	125
+64	712	712
+185
+
+chain	49537	17_random	2617613	+	686221	687340	7	159138663	-	159114165	159114714	2581538
+393	570	0
+156
+
+chain	49422	17_random	2617613	+	2502237	2515076	GL000206.1	41001	+	6806	19645	760
+60	12323	12323
+456
+
+chain	46461	17_random	2617613	+	530697	531391	17	81195210	+	41399710	41400427	2769983
+115	170	185
+151	0	7
+77	5	6
+176
+
+chain	44819	17_random	2617613	+	1346282	1352646	17	81195210	+	36399842	36406169	117269
+158	113	113
+546	19	0
+337	0	1
+343	21	0
+219	1	0
+310	0	1
+3136	0	1
+510	1	1
+49	0	2
+321	1	0
+279
+
+chain	42351	17_random	2617613	+	1308282	1310091	17	81195210	-	44807710	44809519	659295
+50	341	341
+33	377	377
+65	214	214
+66	138	138
+57	150	150
+123	143	143
+52
+
+chain	41114	17_random	2617613	+	1307243	1308123	17	81195210	-	44806671	44807550	1295496
+142	82	82
+46	363	362
+247
+
+chain	38415	17_random	2617613	+	980212	983216	17	81195210	-	46382593	46436652	7347
+66	80	80
+176	73	73
+27	90	90
+32	166	166
+31	1833	52888
+65	56	56
+27	255	255
+27
+
+chain	37708	17_random	2617613	+	1313819	1314225	17	81195210	-	44813251	44813657	3332998
+406
+
+chain	34385	17_random	2617613	+	689365	745709	16	90354753	+	90179685	90235100	655
+111	4456	3661
+64	55	55
+25	28	28
+47	0	945
+90	45591	45393
+56	269	269
+34	5469	4540
+13	2	2
+32	0	48
+2
+
+chain	29758	17_random	2617613	+	1820296	1826385	17	81195210	+	22249775	22252718	80336
+37	643	643
+77	136	133
+51	3143	0
+44	74	74
+224	80	80
+64	79	79
+9	741	741
+39	82	82
+59	25	25
+56	358	358
+68
+
+chain	29219	17_random	2617613	+	1551349	1551651	17	81195210	+	81144397	81144699	5017519
+302
+
+chain	28762	17_random	2617613	+	686677	687796	7	159138663	-	159114165	159114714	2625478
+282	456	0
+111	3	3
+57	114	0
+96
+
+chain	26027	17_random	2617613	+	1296695	1298103	17	81195210	-	44796117	44797535	630440
+61	589	589
+32	259	269
+39	53	53
+103	231	231
+41
+
+chain	25589	17_random	2617613	+	1810180	1822057	17	81195210	+	22246679	22258671	5893
+31	6949	7063
+28	2666	2666
+60	580	580
+49	73	73
+37	1172	1173
+232
+
+chain	22463	17_random	2617613	+	503557	503790	17	81195210	-	39794076	39794309	8690008
+233
+
+chain	21299	17_random	2617613	+	1013035	1014722	17	81195210	+	34795732	34797419	1064
+59	517	517
+37	389	389
+38	357	357
+101	125	125
+64
+
+chain	20434	17_random	2617613	+	685587	686087	7	159138663	-	159114215	159114487	2822651
+209	248	20
+43
+
+chain	19692	17_random	2617613	+	2611651	2612116	17	81195210	-	39813091	39813524	10717347
+67	163	137
+78	68	62
+89
+
+chain	19589	17_random	2617613	+	2616810	2617276	17	81195210	+	41381686	41382119	10803726
+89	68	62
+77	165	138
+67
+
+chain	17762	17_random	2617613	+	852036	852257	5	180915260	-	51646	51969	938
+13	1	1
+60	1	1
+29	1	1
+13	0	102
+103
+
+chain	17600	17_random	2617613	+	1364922	1365125	17	81195210	-	46397651	46397854	1833
+172	1	1
+30
+
+chain	17149	17_random	2617613	+	1514626	1514877	1	249250621	+	547399	547650	3354419
+131	1	3
+101	2	0
+16
+
+chain	16567	17_random	2617613	+	2610699	2610873	17	81195210	-	39795026	39795200	13468304
+174
+
+chain	16365	17_random	2617613	+	1812948	1813633	17	81195210	+	22258959	22259644	44227
+99	181	181
+49	59	59
+25	227	227
+45
+
+chain	16348	17_random	2617613	+	525487	525673	11	135006516	+	62609095	62609281	13688187
+75	4	4
+107
+
+chain	14733	17_random	2617613	+	2605728	2605963	17	81195210	-	39813295	39813524	15353144
+78	68	62
+89
+
+chain	14711	17_random	2617613	+	556093	556262	11	135006516	-	72397235	72397404	15378622
+107	4	4
+58
+
+chain	14711	17_random	2617613	+	527846	528015	11	135006516	-	72397235	72397404	15378623
+107	4	4
+58
+
+chain	14711	17_random	2617613	+	512402	512571	11	135006516	-	72397235	72397404	15378624
+107	4	4
+58
+
+chain	14711	17_random	2617613	+	510910	511079	11	135006516	-	72397235	72397404	15378625
+107	4	4
+58
+
+chain	14711	17_random	2617613	+	494247	494416	11	135006516	-	72397235	72397404	15378626
+107	4	4
+58
+
+chain	14711	17_random	2617613	+	492878	493047	11	135006516	-	72397235	72397404	15378627
+107	4	4
+58
+
+chain	14711	17_random	2617613	+	519356	519525	11	135006516	+	62609112	62609281	15378630
+58	4	4
+107
+
+chain	14711	17_random	2617613	+	514467	514636	11	135006516	+	62609112	62609281	15378631
+58	4	4
+107
+
+chain	14711	17_random	2617613	+	492408	492577	11	135006516	+	62609112	62609281	15378632
+58	4	4
+107
+
+chain	13395	17_random	2617613	+	685879	686024	7	159138663	-	159114165	159114310	16961745
+145
+
+chain	12350	17_random	2617613	+	554102	554230	17	81195210	+	41401065	41401193	18472361
+128
+
+chain	11140	17_random	2617613	+	2611055	2611170	17	81195210	-	39795385	39795500	20498301
+115
+
+chain	11115	17_random	2617613	+	1365516	1365648	17	81195210	-	46613257	46613389	1914
+132
+
+chain	10814	17_random	2617613	+	689806	689963	7	159138663	-	159114495	159114652	3160720
+43	20	20
+94
+
+chain	10716	17_random	2617613	+	690046	690160	11	135006516	-	134823089	134823203	21297817
+114
+
+chain	10594	17_random	2617613	+	686107	686221	11	135006516	-	134823089	134823203	21541329
+114
+
+chain	10432	17_random	2617613	+	752965	753084	3	198022430	+	197944313	197944432	1419040
+26	27	27
+66
+
+chain	10233	17_random	2617613	+	751962	752152	1	249250621	-	25108929	25109119	2449036
+190
+
+chain	10215	17_random	2617613	+	298300	298405	17	81195210	-	41991981	41992086	2272776
+105
+
+chain	10088	17_random	2617613	+	2614941	2615048	11	135006516	-	72397235	72397342	22628945
+107
+
+chain	9967	17_random	2617613	+	687027	687133	7	159138663	-	159114173	159114279	19905170
+106
+
+chain	9953	17_random	2617613	+	1352829	1353036	17	81195210	-	44845003	44845210	3604154
+38	53	53
+37	50	50
+29
+
+chain	9937	17_random	2617613	+	2607755	2608553	17	81195210	+	41464708	41466209	22969163
+59	661	1364
+78
+
+chain	9782	17_random	2617613	+	685310	686656	7	159138663	-	159114165	159114714	2594423
+225	1079	282
+42
+
+chain	9490	17_random	2617613	+	268561	268666	17	81195210	+	39296306	39296411	8067183
+50	6	6
+49
+
+chain	9384	17_random	2617613	+	1808529	1810797	17	81195210	+	22256920	22261566	263516
+29	104	104
+28	50	50
+48	1976	4354
+33
+
+chain	9278	17_random	2617613	+	1333217	1333901	17	81195210	-	44832655	44833339	2515
+26	585	585
+73
+
+chain	9162	17_random	2617613	+	1819790	1824781	17	81195210	+	22261160	22263006	131478
+64	322	322
+59	818	816
+30	3642	499
+56
+
+chain	8930	17_random	2617613	+	507298	507390	17	81195210	+	41466131	41466223	25058540
+92
+
+chain	8739	17_random	2617613	+	1294354	1363161	17	81195210	-	46388680	46446941	1280
+36	59095	48559
+76	160	160
+63	250	250
+52	124	124
+61	4094	4092
+28	4719	4711
+49
+
+chain	7495	17_random	2617613	+	1514877	1514981	17	81195210	-	42613	42717	4053350
+104
+
+chain	7310	17_random	2617613	+	1352662	1353007	17	81195210	-	20840434	20840778	292042
+167	38	37
+53	37	37
+50
+
+chain	6706	17_random	2617613	+	687825	687939	7	159138663	-	159114173	159114287	10506562
+114
+
+chain	6456	17_random	2617613	+	673480	673547	11	135006516	-	134811854	134811921	22781013
+67
+
+chain	5049	17_random	2617613	+	752664	753185	1	249250621	-	248584104	248584621	921258
+110	84	84
+38	62	62
+7	119	119
+72	7	3
+22
+
+chain	5012	17_random	2617613	+	557502	557555	17	81195210	+	41382227	41382280	33565948
+53
+
+chain	4802	17_random	2617613	+	1345218	1345268	17	81195210	-	44844643	44844693	34312672
+50
+
+chain	4547	17_random	2617613	+	688053	688156	7	159138663	-	159114401	159114504	10358404
+103
+
+chain	4503	17_random	2617613	+	690214	690262	7	159138663	-	159114675	159114723	34814023
+48
+
+chain	4408	17_random	2617613	+	1808470	1808528	17	81195210	+	22261618	22261676	11976838
+58
+
+chain	4236	17_random	2617613	+	269418	269467	17	81195210	-	41933979	41934028	1349427
+49
+
+chain	3906	17_random	2617613	+	1365126	1365187	17	81195210	-	23109543	23109604	10221956
+61
+
+chain	3852	17_random	2617613	+	685196	685310	7	159138663	-	159114165	159114279	3139829
+114
+
+chain	3804	17_random	2617613	+	676798	676843	11	135006516	-	134814627	134814666	26257176
+33	6	0
+6
+
+chain	3734	17_random	2617613	+	1819749	1824493	17	81195210	+	22251604	22253205	550639
+41	1133	1133
+53	3451	308
+4	6	6
+56
+
+chain	3666	17_random	2617613	+	689649	689704	3	198022430	+	197891166	197891221	670
+55
+
+chain	3459	17_random	2617613	+	687133	687184	7	159138663	-	159114165	159114216	4526522
+51
+
+chain	3336	17_random	2617613	+	1365188	1365250	17	81195210	-	20853025	20853087	9938797
+62
+
+chain	3079	17_random	2617613	+	681792	681827	11	135006516	-	134820249	134820284	24010224
+35
+
+chain	2916	17_random	2617613	+	690160	690191	7	159138663	-	159114621	159114652	25187800
+31
+
+chain	2901	17_random	2617613	+	1010962	1011819	17	81195210	-	44844823	44845680	205824
+857
+
+chain	2668	17_random	2617613	+	837741	837773	8	146364022	+	31195	31227	1221
+32
+
+chain	2659	17_random	2617613	+	747955	747987	5	180915260	+	180755757	180755789	880
+32
+
+chain	2649	17_random	2617613	+	622962	622989	17	81195210	-	81153206	81153233	29165068
+27
+
+chain	2631	17_random	2617613	+	1252044	1252072	17	81195210	+	34548405	34548433	469
+28
+
+chain	2530	17_random	2617613	+	1100849	1100878	17	81195210	-	46384734	46384763	4689
+29
+
+chain	2422	17_random	2617613	+	621448	621568	17	81195210	-	81152835	81152952	7235512
+27	65	62
+28
+
+chain	2158	17_random	2617613	+	688361	688384	16	90354753	+	90179770	90179793	21906636
+23
+
+chain	2073	17_random	2617613	+	690420	690442	7	159138663	-	159114653	159114675	31315602
+22
+
+chain	1877	17_random	2617613	+	1533316	1533338	GL000206.1	41001	-	16469	16491	815
+22
+
+chain	1804	17_random	2617613	+	687361	687825	7	159138663	-	159114165	159114515	2659234
+54	381	267
+29
+
+chain	1771	17_random	2617613	+	742259	742283	1	249250621	-	248585388	248585412	123201
+24
+
+chain	1698	17_random	2617613	+	268509	268561	17	81195210	-	41933055	41933107	4387515
+52
+
+chain	1694	17_random	2617613	+	747513	747535	1	249250621	-	249115973	249115995	773
+22
+
+chain	1343	17_random	2617613	+	555358	555450	17	81195210	-	39728987	39729079	19263806
+92
+
+chain	1343	17_random	2617613	+	511667	511759	17	81195210	-	39728987	39729079	19263807
+92
+
+chain	1343	17_random	2617613	+	526316	526408	17	81195210	+	41466131	41466223	19263808
+92
+
+chain	1343	17_random	2617613	+	520168	520260	17	81195210	+	41466131	41466223	19263809
+92
+
+chain	1129	17_random	2617613	+	1019025	1019068	17	81195210	+	60348267	60348310	2834
+43
+
+chain	1082	17_random	2617613	+	686959	687027	7	159138663	-	159114561	159114629	2979122
+68
+
+chain	594	17_random	2617613	+	1548943	1548990	GL000206.1	41001	-	30268	30353	3713456
+4	9	47
+34
+
+chain	7055976638	18	76117153	+	0	76117153	18	78077248	+	10000	78016181	19
+15400898	1363998	3100000
+28218587	15	15
+5329636	47000	150000
+3667309	0	18
+16406890	28008	50000
+3388467	22000	50000
+2103304	3	0
+136125	7	9
+647	0	1
+1543	0	1
+25	0	1
+6	2	7
+19	0	2
+10	4	7
+9	2	4
+656	0	1
+358	0	1
+1625
+
+chain	404699	18_random	4262	+	0	4262	GL000207.1	4262	+	0	4262	116011
+4262
+
+chain	5307789368	19	63811651	+	11000	63806651	19	59128983	+	60000	59114839	21
+7286004	5000	50000
+1291194	5000	50000
+11767057	0	69160
+4058367	8000000	3100000
+20129228	0	2
+701	3	0
+347	1	1
+31	1	1
+1833	3	0
+1984	1	1
+47	1	1
+190	1	1
+34	1	1
+889	0	2
+1413	0	7
+2680	0	4
+375	0	1
+328	0	4
+15	0	1
+69	1	0
+3881	1	1
+36	0	12
+296	0	14
+1480	0	1
+233	1	1
+45	1	1
+1049	0	1
+1766	44	7
+220	3	0
+536	0	7
+352	8	8
+3603	1	1
+17	3	0
+697	1	0
+269	3	0
+974	6	5
+96	0	10
+1096	10	10
+1177	14	12
+110	3	3
+1028	12	9
+1090	1	0
+173	0	16
+1066	4	0
+4779	1	1
+42	1	1
+722	1	0
+548	2	2
+44	1	1
+424	54	54
+61	1	1
+59	1	1
+2086	0	15
+1500	1	0
+1754	2	0
+11209362
+
+chain	15150451	19_random	301858	+	142689	301858	GL000209.1	159169	+	0	159169	196
+159169
+
+chain	8748871	19_random	301858	+	0	92689	GL000208.1	92689	+	0	92689	377
+92689
+
+chain	14432273	1_random	1663265	+	444114	915337	1	249250621	-	104328377	105379619	206
+1802	63331	510
+7296	6958	14784
+7961	0	2
+631	19782	48350
+2466	1	1
+72	1	1
+281	2	2
+18	1	1
+2234	1	1
+23	2	1
+1869	0	2
+890	0	1
+2816	0	3
+59	12	12
+1298	1	1
+11	1	1
+294	214294	820733
+136815
+
+chain	10693564	1_random	1663265	+	965337	1079393	1	249250621	+	199645090	199759149	300
+3537	0	2
+1755	1	1
+38	1	1
+15918	1	0
+2372	0	1
+1251	34	34
+7007	1	6
+3552	1	1
+44	1	1
+799	1	1
+42	1	1
+3907	2	0
+1780	1	1
+49	1	1
+1586	2	0
+197	1	1
+37	1	1
+292	1	1
+47	1	1
+927	0	2
+549	1	1
+27	1	1
+595	1	1
+18	1	1
+291	0	2
+6685	1	0
+2369	1	0
+6503	13	13
+639	1	1
+70	1	1
+477	1	0
+1001	0	2
+1967	2	0
+3454	1	1
+26	1	1
+3144	0	4
+89	1	0
+6546	14	15
+6194	1	0
+5390	13	13
+196	1	0
+7401	1	9
+1242	1	0
+1702	1	0
+477	1	1
+61	0	1
+1487	1	0
+1276	1	0
+1950	9	0
+4681	0	2
+1332	1	0
+956
+
+chain	10110185	1_random	1663265	+	1464329	1570762	GL000191.1	106433	+	0	106433	317
+106433
+
+chain	6680210	1_random	1663265	+	198768	359123	1	249250621	+	1257620	1436018	467
+467	0	1
+41	0	1
+10	4	4
+930	2	3
+122	3	4
+138	66071	6986
+47	0	1
+945	0	1
+279	1	2
+508	0	1
+482	0	1
+1285	1	1
+40	1	1
+199	0	1
+207	1	1
+29	1	1
+1021	0	1
+1168	0	2
+388	0	1
+69	15	17
+195	4	4
+52	1	1
+9	1	3
+23	0	1
+284	0	1
+1485	15	16
+138	9	9
+27	44	5
+35	46	46
+97	0	1
+5	0	1
+734	0	3
+257	1	1
+18	1	1
+442	0	2
+51	4	0
+424	0	1
+134	1	1
+39	0	1
+22	1	1
+564	15	17
+469	0	3
+39	0	1
+22	2	2
+1076	0	1
+210	14	14
+166	0	1
+3264	1	0
+111	0	1
+309	19898	50666
+91	0	1
+116	0	1
+56	0	1
+152	0	1
+46	0	1
+51	0	1
+63	0	2
+420	4	5
+697	0	1
+2269	7	0
+48	1	1
+4086	0	2
+317	0	1
+49	0	1
+1795	0	1
+1147	1	1
+39	1	1
+1378	0	17
+477	2	0
+4457	1	1
+105	0	1
+1003	0	1
+232	1	2
+147	277	46717
+169	0	1
+37	1	1
+227	0	2
+651	1	0
+1805	1	1
+45	1	1
+498	1	0
+233	1	1
+29	1	1
+231	12	20
+2015	0	1
+20	1	1
+653	0	1
+12	0	1
+17	1	1
+139	0	1
+10	0	1
+22	0	1
+37	16	19
+38	0	5
+54	0	1
+437	0	1
+539	2	0
+1067	0	1
+1042	1	0
+2434	10	0
+256	133	0
+839	0	1
+267	0	1
+640	1	1
+35	1	1
+1351	15	15
+1316	1	1
+31	0	1
+1986	5	5
+1179	0	1
+3153	1	0
+1165	0	1
+22	0	1
+56	1	1
+27	1	1
+77	0	1
+81	15	17
+111	1	1
+44	0	1
+2254	1	0
+320	1	0
+2368	0	1
+26	0	1
+407	5	6
+2982	0	4
+852	0	5
+703	1	0
+191	2	3
+73	5	5
+72
+
+chain	4901563	1_random	1663265	+	676697	728522	1	249250621	-	205721991	205773795	637
+1664	1	0
+299	1	0
+1113	4	0
+100	1	0
+1522	1	1
+46	1	1
+83	1	1
+30	1	1
+62	1	1
+46	1	1
+1990	1	1
+41	1	1
+1403	0	4
+1148	0	5
+10134	1	1
+21	1	1
+1479	1	0
+1499	9	9
+3057	0	2
+137	6	0
+1251	2	0
+21	1	1
+897	5	4
+2851	1	0
+399	0	2
+624	6	5
+440	1	0
+5	1	0
+2953	1	0
+480	9	0
+2793	36	35
+6791	1	0
+4870	1	0
+1478
+
+chain	4504833	1_random	1663265	+	1205412	1353281	1	249250621	-	133273039	133340206	679
+3980	0	1
+79	1	1
+34	1	1
+916	4	6
+1818	34	28
+51	21	16
+5	1	0
+5	1	0
+4	1	0
+11	1	0
+28	1	0
+8	1	0
+8	1	0
+1366	1	1
+38	0	1
+7507	0	1
+3084	2	0
+2569	1	0
+20	1	0
+8	1	0
+10	21	16
+51	10	10
+3979	6	5
+2086	1	0
+5466	0	1
+27	1	1
+1117	1	0
+66	1	0
+23	1	0
+2070	0	1
+67	1	0
+2611	1	0
+9	1	0
+23	23	18
+577	97925	17254
+5929	0	1
+1948	1	0
+72	0	1
+1365	60	62
+706
+
+chain	3984524	1_random	1663265	+	1620762	1663230	X	155270560	-	27920664	27963158	751
+107	0	1
+696	27	12
+658	0	12
+1440	0	2
+671	0	2
+506	0	3
+806	0	1
+4759	0	12
+131	1	0
+848	1	0
+213	0	8
+2046	1	0
+4979	0	1
+2482	1	0
+1502	1	0
+3474	0	4
+782	0	1
+12366	1	0
+3969
+
+chain	2698055	1_random	1663265	+	6164	122978	1	249250621	-	139553697	139584554	1020
+486	1	1
+19	9	9
+297	1	1
+73	1	1
+341	1	0
+105	1	0
+286	47997	0
+689	1	1
+48	1	1
+53	0	2
+1870	1	1
+39	1	1
+1682	0	39
+470	8	9
+691	1	0
+370	1	1
+24	1	1
+356	0	1
+1496	9599	84
+28	0	1
+7	4	0
+131	0	1
+66	932	181
+88	9	11
+10	7	0
+10	8	5
+5	0	3
+76	27759	26
+44	3	0
+26	0	2
+6	1	1
+59	3	1
+121	2	4
+4990	1	0
+672	0	1
+1487	1	1
+39	1	1
+1691	0	1
+36	10	10
+3503	1	1
+46	1	1
+4128	0	1
+1818	0	5
+1107	16	16
+841
+
+chain	2474973	1_random	1663265	+	1129393	1155387	1	249250621	+	229232478	229258468	1104
+3505	1	1
+44	1	1
+5232	4	0
+17207
+
+chain	2468882	1_random	1663265	+	1280682	1387454	1	249250621	-	133163307	133238928	735
+149	0	1
+7073	122	124
+1799	1	1
+43	1	1
+5594	24	23
+60	12182	28596
+3279	1	0
+571	21	21
+1080	1	0
+10	0	2
+1138	1	0
+3484	1	0
+1689	0	8
+810	42350	1
+1088	1	1
+21	1	0
+78	30	29
+746	0	2
+2729	1	0
+2088	0	3
+1949	966	174
+31	9	0
+12	16	16
+29	0	4
+13	100	98
+53	1884	0
+16	1	0
+5	0	1
+18	3916	1388
+1729	0	1
+1373	1	0
+102	1	0
+21	1	0
+4	1	0
+7	1	0
+38	2	0
+48	1	0
+525	5	4
+645	5	5
+1189	1	0
+1911	4	0
+69	8	8
+24	5	4
+284	1	0
+1481
+
+chain	2064841	1_random	1663265	+	247141	392880	1	249250621	-	247850669	247948213	608
+351	1	0
+965	0	1
+35	0	1
+248	0	1
+122	0	1
+1194	11	11
+580	3	5
+969	0	1
+425	5	5
+25	1	1
+586	1	1
+77	1	1
+1895	1	1
+37	1	2
+253	0	1
+560	1	1
+62	1	1
+74	1	1
+27	1	1
+90	31631	11346
+887	0	40
+759	32	0
+2596	0	1
+308	1	0
+37	0	1
+40	0	1
+346	17	19
+89	2	2
+34	1	2
+44	0	2
+35	0	1
+20	0	1
+260	0	1
+3009	1	1
+30	0	1
+5	10	12
+104	1	1
+48	0	1
+67	13	15
+1226	0	1
+111	7	7
+31	0	1
+47	1	3
+13	3	5
+38	7	10
+7	0	2
+48	0	1
+110	1	0
+623	0	2
+241	1	1
+47	1	1
+1601	0	1
+582	13	21
+1128	2	0
+348	4	4
+28	22	23
+481	0	2
+30	1	1
+628	0	1
+96	0	1
+30	0	1
+78	17	173
+64	55865	28961
+69	13	14
+498	0	1
+1593	0	4
+183	26	27
+337	1	0
+1433	0	1
+6191	0	2
+2435	0	1
+3451	540	0
+83	695	0
+1318	5	5
+21	1	1
+526	0	1
+833	0	1
+144	0	1
+427	8	8
+235	1	2
+297	1	1
+34	0	1
+250	0	3
+1007	0	1
+1403	1	1
+37	1	1
+355	1	1
+6	0	2
+94	1	1
+278	2	2
+5	0	1
+20	1	1
+667	24	24
+1858	10	12
+146	8	7
+2002	0	1
+284	0	1
+1233	0	1
+840	11	0
+914	2	0
+122	1	1
+26	0	2
+118
+
+chain	1850028	1_random	1663265	+	76914	101906	1	249250621	-	139621990	139717568	1363
+3916	0	1
+77	20	20
+26	0	856
+764	17	16
+12	1	0
+295	1	0
+2648	2870	23264
+250	997	50331
+2203	0	5
+797	1	0
+2197	1	1
+117	7	8
+429	1	0
+7345
+
+chain	1707631	1_random	1663265	+	501749	626697	1	249250621	+	144188000	145316961	852
+223	42	42
+236	22	22
+242	91	103
+199	8	8
+102	112	112
+50	126	126
+290	32	32
+213	45	45
+125	1	1
+56	1	1
+82	1	1
+27	13	13
+71	5	5
+493	3	3
+15	1	1
+248	1	1
+44	1	1
+65	1	1
+52	1	1
+169	1	1
+82	1	1
+292	1	1
+83	0	1580
+458	1	1
+16	1	1
+478	5	5
+568	23	17
+634	1	1
+46	1	1
+50	14	14
+864	31	61
+55	23320	364967
+85	1	1
+107	1	1
+376	1	1
+20	0	1
+195	10	10
+150	1	1
+35	1	1
+274	5	5
+143	1	0
+862	7	0
+20	1	0
+504	1	1
+25	1	1
+238	1	1
+36	1	1
+139	0	1
+25	1	1
+157	8	8
+60	16	16
+59	17	17
+285	0	1
+120	1	1
+69	1	1
+509	1	1
+59	1	1
+162	0	322
+70	5	5
+2169	1	1
+31	1	1
+224	1	1
+36	1	1
+76	1	0
+5	5	0
+109	6	6
+139	5	3
+65	0	20
+360	47	48
+86	18	17
+149	44	44
+76	54	55
+196	38	38
+139	139	6280
+107	1	1
+95	0	1
+46	1	1
+91	1	1
+18	1	1
+62	11	11
+511	0	1
+106	1	0
+505	0	2
+443	9	9
+519	112	112
+396	1	1
+26	1	1
+225	1	1
+57	1	1
+502	1	0
+485	1	1
+105	0	2
+146	1	1
+41	1	1
+203	1	1
+45	1	1
+62	5	5
+850	1	1
+55	2	2
+215	1	1
+45	1	1
+474	0	3
+19	1	1
+2337	1	1
+34	1	1
+148	1	0
+159	1	1
+32	1	1
+64	0	4
+849	1	1
+34	1	1
+126	38816	272842
+32	0	140
+3176	18	17
+6689	1	0
+274	0	1
+1449	0	1
+1312	1	0
+1861	8888	417910
+92	172	6531
+148	0	2
+213	1	1
+30	1	1
+227	1	1
+62	6	0
+276	1	1
+35	1	1
+94	14	14
+325	5	5
+118	1	1
+81	1	1
+234	4	0
+15	1	1
+243	1	1
+39	1	1
+117	1	1
+35	1	1
+83	1	1
+64	5	5
+55	13	13
+61	11	11
+175	1	1
+27	1	1
+134	1	1
+60	1	1
+64	1	1
+87	1	1
+615	1	1
+22	1	1
+201	5	5
+48	1	1
+117	1	1
+23	3	3
+319	6	6
+156	0	1
+25	1	1
+215	13	13
+97	14	14
+113	0	3
+35	1	1
+65	15	15
+480	0	1
+636	1	1
+107	1	1
+753	1	1
+43	1	1
+861	17	16
+470	1	1
+38	1	1
+579	1	1
+25	1	1
+224	1	1
+71	1	1
+266	36	36
+167	88	88
+400	53	53
+131	6	5
+220	22	19
+317	23	23
+109	95	101
+73	0	4726
+208	28	28
+293
+
+chain	1680348	1_random	1663265	+	1245440	1263421	1	249250621	+	116101959	116120000	1475
+441	0	14
+728	0	2
+1146	2	0
+1829	6	6
+93	3	2
+2916	0	6
+2013	0	47
+369	1	1
+27	9	0
+37	1	1
+200	1	0
+2285	0	2
+3527	1	1
+24	0	1
+1001	0	1
+1195	1	1
+39	1	1
+85
+
+chain	1335863	1_random	1663265	+	231796	246037	4	191154276	-	30408128	30422371	1784
+3391	6	6
+562	7	7
+5976	2	3
+4144	10	11
+143
+
+chain	1170727	1_random	1663265	+	577933	590476	1	249250621	+	144898104	144910646	2036
+1896	48	48
+2779	1	0
+7128	45	45
+646
+
+chain	1143882	1_random	1663265	+	1330802	1343100	1	249250621	-	133251270	133263558	2093
+1050	1	1
+51	1	1
+237	1	1
+35	1	1
+514	16	12
+76	9	1
+1642	12	12
+53	0	1
+3766	0	1
+40	1	1
+1513	0	1
+195	11	11
+135	26	26
+2627	1	0
+284
+
+chain	988809	1_random	1663265	+	564355	574807	1	249250621	-	104390169	104400621	2516
+59	1	2
+5994	1	1
+45	1	1
+3985	3	3
+42	1	0
+320
+
+chain	957971	1_random	1663265	+	256162	266426	1	249250621	+	1291904	1302191	2686
+83	0	1
+585	0	1
+1018	0	1
+18	1	1
+59	16	16
+1569	0	1
+69	1	0
+35	0	1
+36	1	1
+176	0	1
+48	0	1
+56	2	3
+41	0	1
+160	17	1
+461	13	21
+174	0	4
+517	7	7
+141	4	4
+89	0	1
+1155	1	0
+370	7	7
+143	1	0
+1019	22	22
+1177	0	1
+607	0	16
+86	0	3
+279
+
+chain	895962	1_random	1663265	+	196343	223209	1	249250621	-	247894293	247990621	2587
+108	25	24
+131	0	1
+299	0	1
+137	44	45
+51	0	1
+572	0	1
+406	36	37
+508	2162	63455
+80	5	8
+86	0	1
+61	0	1
+31	1	0
+165	14	15
+78	75	78
+234	0	1
+152	13	15
+849	0	1
+1798	12505	20653
+3495	0	1
+43	0	1
+1944	1	1
+26	1	1
+169	0	1
+365	0	1
+196
+
+chain	884318	1_random	1663265	+	4444	145186	1	249250621	+	109546538	109651856	1047
+123	47	1183
+818	1	1
+75	1	0
+22	1	1
+455	18927	20784
+855	1	0
+74	12001	11300
+2581	2	2
+31	0	1
+81	1	0
+24	1	1
+123	1	0
+147	0	1
+45	0	1
+26	0	1
+9	1	0
+12	2330	786
+22	41	53
+127	1706	714
+3729	74524	39329
+68	5	7
+3088	2	2
+15	5	6
+14	0	2
+657	1	1
+37	1	1
+2140	1	0
+3034	1	0
+42	1	1
+446	0	1
+55	2	2
+30	1	1
+391	1	1
+35	1	1
+982	3	0
+123	1	1
+28	0	4
+1503	1	0
+1159	0	3
+1464	0	1
+838	1	1
+47	1	3
+162	1	0
+139	1	1
+10	0	1
+2424	6	6
+448	1	0
+846	5	0
+1509
+
+chain	739113	1_random	1663265	+	68329	76740	1	249250621	+	109654512	109662863	6250
+254	1	0
+27	1	1
+746	1	0
+315	19	19
+163	42	2
+51	3	1
+44	1	1
+592	0	1
+216	1	1
+34	1	1
+2323	10	0
+10	236	236
+125	1	0
+806	213	213
+828	6	0
+82	6	6
+1253
+
+chain	688441	1_random	1663265	+	605533	614556	1	249250621	+	144612760	144812114	1498
+76	1	1
+70	1	1
+73	4	2
+40	0	2
+159	1	1
+56	2	0
+911	1	1
+63	1	1
+84	9	1
+149	1	1
+21	1	0
+606	1	1
+21	3	3
+132	12	10
+368	1	1
+26	1	1
+50	1	1
+65	1	1
+57	1	1
+44	1	1
+279	0	1
+34	0	4
+7	1	1
+308	0	32
+331	1	1
+84	1	1
+286	1	1
+35	1	1
+59	8	8
+146	1	1
+237	1	1
+52	1	1
+35	2	0
+40	1	1
+53	3	3
+103	1	1
+397	1	1
+59	1	0
+33	1	1
+587	11	11
+219	10	10
+71	5	5
+62	1	1
+38	1	1
+240	1	1
+70	1	1
+85	12	12
+86	413	190724
+207	1	0
+825	186	186
+172
+
+chain	590572	1_random	1663265	+	516651	523401	1	249250621	-	104651805	104658532	8996
+157	1	1
+17	1	1
+395	1	1
+65	1	1
+187	0	9
+21	1	1
+62	16	16
+110	2	0
+205	1	0
+43	1	1
+248	1	1
+59	4	2
+725	1	1
+49	1	1
+455	1	1
+106	1	1
+450	1	1
+133	0	2
+383	1	1
+37	1	1
+178	4	4
+70	1	1
+85	2	2
+43	1	1
+56	1	1
+22	24	0
+30	1	1
+64	1	1
+21	1	1
+198	1	1
+67	1	1
+58	1	0
+79	7	6
+74	1	1
+79	1	0
+26	1	1
+202	15	15
+352	2	2
+16	1	1
+51	22	19
+574	0	1
+87	1	1
+46	1	1
+88	1	1
+27	1	1
+120
+
+chain	526301	1_random	1663265	+	1264935	1361969	1	249250621	+	116056429	116101915	1232
+69	0	1
+30	1	1
+2663	2	0
+4185	1	0
+229	1	0
+25	1	1
+1104	1	0
+604	4	0
+1264	1	0
+2613	1	1
+21	1	0
+12	1	13
+2785	72844	21309
+397	19	2
+2203	1	1
+31	1	1
+658	1	1
+27	1	1
+923	9	9
+168	1	1
+46	0	2
+2502	43	43
+879	17	17
+644
+
+chain	506365	1_random	1663265	+	1399143	1404500	1	249250621	-	133194419	133199775	28136
+3175	1	0
+1447	0	1
+512	1	0
+221
+
+chain	482769	1_random	1663265	+	211415	216543	1	249250621	-	247889067	247894197	45886
+70	2	3
+905	2	3
+1091	1	1
+23	1	1
+302	15	14
+393	1	1
+24	1	1
+1961	0	1
+336
+
+chain	474976	1_random	1663265	+	1295676	1399043	1	249250621	+	115999419	116093083	1267
+571	10	10
+627	7	6
+46	1	1
+3095	0	1
+960	0	1
+608	11	10
+426	39	35
+2035	1	1
+23	1	1
+1866	17	18
+79	1	1
+1530	63368	32589
+866	110	110
+100	53	53
+1884	40	40
+3775	15606	36683
+2322	14	14
+145	49	49
+296	96	96
+297	0	2
+465	58	58
+262	22	22
+182	0	1
+638	1	0
+764
+
+chain	456897	1_random	1663265	+	1317	37745	1	249250621	+	109592282	109609521	6704
+1178	0	1
+16	1	0
+10	0	1
+4	1	1
+245	7763	188
+27	1	1
+1155	1	1
+91	4156	3450
+1810	51	51
+50	9	10
+567	3839	4491
+37	6346	0
+128	0	2
+29	50	48
+45	1519	155
+6	2	0
+9	10	6
+246	1806	0
+18	1	0
+5	2068	31
+2018	2	2
+20	3	3
+833	1	0
+101	1	0
+149
+
+chain	426748	1_random	1663265	+	63710	68210	1	249250621	-	139547929	139552428	99412
+1542	1	0
+2957
+
+chain	353264	1_random	1663265	+	462791	467071	1	249250621	+	144608404	144612698	156569
+71	50	50
+33	29	29
+226	10	10
+526	66	67
+55	50	50
+414	5	5
+57	46	58
+57	12	12
+254	1	1
+25	1	1
+52	13	13
+638	16	16
+579	1	1
+60	1	1
+178	1	1
+79	1	0
+35	0	3
+111	1	1
+43	1	1
+264	1	0
+119	1	1
+15	0	1
+76	1	0
+5
+
+chain	327229	1_random	1663265	+	1409275	1412904	1	249250621	+	115977641	115981270	200837
+2640	156	155
+473	0	1
+360
+
+chain	312923	1_random	1663265	+	1319916	1393318	1	249250621	+	115926067	115986980	1722
+1418	1	0
+1389	1	0
+1620	0	1
+374	1	0
+1361	0	1
+1994	1	0
+827	0	6
+1784	56909	44431
+253	1	0
+12	2	0
+8	24	14
+5344	2	0
+76
+
+chain	244562	1_random	1663265	+	478502	503782	1	249250621	-	100680024	100953393	1328
+106	13	13
+478	55	55
+310	1	1
+23	1	1
+376	1	1
+61	1	1
+1100	10	10
+810	5	0
+53	1	1
+119	1	1
+44	1	0
+94	100	32051
+60	5	5
+744	1	1
+87	1	1
+44	2	0
+53	11	5
+584	2	2
+30	0	17
+73	1	1
+49	1	1
+456	8	8
+796	19	19
+166	1	1
+42	1	1
+105	1	1
+38	1	1
+55	1	1
+80	1	1
+293	2	2
+19	1	1
+550	5637	9366
+68	24	22
+103	1	1
+35	0	1
+102	1	1
+39	6	0
+388	9	9
+21	1	1
+338	27	27
+500	4	0
+117	5	5
+271	1	1
+38	1	1
+273	3	3
+16	3	3
+80	1	1
+63	1	1
+130	1	1
+18	1	1
+204	1	1
+45	1	1
+141	1	1
+112	1	1
+75	1	0
+75	4	4
+83	2	0
+854	5	5
+104	0	4
+12	1	1
+351	1	1
+40	1	1
+102	4779	217183
+40	502	502
+31	0	12
+58	311	311
+110	52	52
+78	1	1
+46	535	535
+45
+
+chain	239113	1_random	1663265	+	455713	471283	1	249250621	+	144877306	144889304	5703
+73	1	0
+944	0	1
+2741	1	1
+77	1770	1206
+12	1449	338
+10	71	1301
+14	10	145
+26	4281	1018
+2672	0	1
+1418
+
+chain	228041	1_random	1663265	+	450807	453388	GL000192.1	547496	+	525635	528523	474030
+521	25	26
+256	4	316
+195	1	0
+183	4	0
+249	48	48
+915	19	18
+161
+
+chain	219405	1_random	1663265	+	8071	23476	1	249250621	+	109602419	109665881	23204
+1669	2217	48069
+1950	5	1
+213	6609	8813
+681	1	0
+580	0	1
+296	37	38
+248	0	4
+301	31	31
+143	38	38
+386
+
+chain	219231	1_random	1663265	+	32127	34517	1	249250621	-	139682423	139684814	491274
+85	27	27
+14	0	1
+204	5	5
+63	24	24
+1968
+
+chain	210320	1_random	1663265	+	459650	474308	GL000192.1	547496	+	522489	531711	22108
+267	0	10
+1175	5	1
+48	0	2
+16	3	3
+119	0	12
+37	12	12
+1340	8711	3256
+34	0	2
+58	1	0
+38	1	0
+351	5	5
+486	17	15
+158	81	81
+76	1	1
+36	1	1
+69	12	13
+1500
+
+chain	207966	1_random	1663265	+	29704	55292	1	249250621	+	109529352	109557857	7568
+742	273	273
+560	0	1
+232	17541	20458
+729	2	2
+97	3	3
+89	1	1
+68	0	1
+28	1	1
+2575	2	0
+59	1	1
+2585
+
+chain	202325	1_random	1663265	+	27243	45056	1	249250621	-	139669260	139678536	8944
+1432	157	157
+50	45	45
+677	2608	49
+27	8791	867
+266	9	9
+169	1	1
+62	1	1
+67	7	5
+28	1	1
+1619	22	22
+41	127	127
+21	1	1
+40	2	1
+32	1	1
+362	0	1949
+1147
+
+chain	199687	1_random	1663265	+	18553	20627	1	249250621	+	109595202	109597276	600797
+2074
+
+chain	171508	1_random	1663265	+	447628	491985	1	249250621	+	148535207	148566609	6481
+121	14	14
+517	0	4
+507	1	0
+74	1	1
+41	0	1
+61	4541	11291
+1073	1	0
+718	70	44
+66	31371	11607
+690	1	1
+115	1	1
+61	1	1
+70	1	1
+57	0	4
+54	1	1
+41	2	6
+28	5	77
+73	1	1
+34	5	5
+887	1	0
+427	1	1
+7	0	5
+40	1	1
+59	1	1
+47	1	1
+121	9	9
+57	2	0
+362	1	1
+48	4	4
+429	1	1
+28	1	1
+160	1	1
+92	5	0
+15	0	5
+15	1	1
+139	5	5
+37	1	1
+87	1	1
+40	1	1
+253	1	1
+35	1	1
+197	1	1
+69	1	1
+114	1	1
+79	1	1
+51
+
+chain	170629	1_random	1663265	+	474420	479154	1	249250621	-	104365477	104643040	2652
+3982	697	273526
+55
+
+chain	143194	1_random	1663265	+	449166	450695	1	249250621	-	104373413	104374943	899312
+167	0	1
+362	11	11
+989
+
+chain	141808	1_random	1663265	+	195186	230464	1	249250621	+	1361949	1390000	8100
+66	0	1
+865	27548	20313
+75	1	1
+163	2	2
+2267	0	2
+1549	0	2
+37	1	1
+597	1	1
+28	1	1
+269	14	19
+59	1	1
+20	1	1
+734	2	0
+977
+
+chain	137395	1_random	1663265	+	446016	447466	1	249250621	+	144922370	144923820	937713
+1450
+
+chain	120082	1_random	1663265	+	1413004	1414278	1	249250621	+	115908963	115910237	1071399
+1274
+
+chain	110577	1_random	1663265	+	0	1193	5	180915260	+	33390295	33391489	1161255
+153	0	1
+942	4	4
+94
+
+chain	101176	1_random	1663265	+	442945	444014	1	249250621	-	104338746	104339815	1265508
+1069
+
+chain	61431	1_random	1663265	+	9891	10535	1	249250621	+	109697165	109697809	2020878
+644
+
+chain	48091	1_random	1663265	+	497444	501649	1	249250621	+	144842054	144846259	8551
+4205
+
+chain	31572	1_random	1663265	+	576223	577747	4	191154276	+	100714665	100716180	4375428
+114	20	20
+105	460	462
+56	375	378
+65	263	249
+66
+
+chain	28915	1_random	1663265	+	230464	231387	1	249250621	+	1420670	1421247	4712368
+191	574	228
+67	38	38
+53
+
+chain	27385	1_random	1663265	+	205390	205833	1	249250621	-	247799065	247799507	5896168
+141	86	86
+106	47	46
+63
+
+chain	25670	1_random	1663265	+	87811	88395	7	159138663	-	51241913	51242744	3648322
+121	405	652
+58
+
+chain	21035	1_random	1663265	+	376636	377171	1	249250621	-	247932544	247932844	3872256
+107	118	0
+61	93	15
+49	39	0
+68
+
+chain	18694	1_random	1663265	+	540390	626404	1	249250621	+	148529505	148589817	1111
+44	254	254
+43	76	73
+54	196	196
+37	240	6477
+31	4	4
+4	2528	2531
+8	1	1
+42	1	1
+60	70185	38258
+94	10137	10136
+31	1	1
+3	167	167
+88	400	400
+52	829	828
+33	10	0
+52	281	281
+28
+
+chain	18305	1_random	1663265	+	612752	613165	1	249250621	+	146400208	146400621	434456
+18	31	31
+215	97	97
+52
+
+chain	18205	1_random	1663265	+	210123	210768	1	249250621	+	1400633	1401273	11939617
+55	410	403
+82	10	12
+88
+
+chain	16211	1_random	1663265	+	84691	84862	5	180915260	+	68593902	68594073	10696361
+171
+
+chain	14543	1_random	1663265	+	375983	376437	1	249250621	-	247932585	247932921	12601411
+13	231	153
+56	101	61
+53
+
+chain	11766	1_random	1663265	+	209234	209374	6	171115067	+	48765751	48765891	19406706
+84	4	4
+52
+
+chain	10899	1_random	1663265	+	1264583	1264729	4	191154276	-	96228610	96228756	20935897
+69	19	19
+58
+
+chain	9779	1_random	1663265	+	575439	575892	5	180915260	-	127861600	127862049	19918678
+60	389	385
+4
+
+chain	9449	1_random	1663265	+	206282	206576	1	249250621	-	247814999	247815293	24134146
+64	179	179
+51
+
+chain	9080	1_random	1663265	+	376922	377270	1	249250621	-	247932789	247932982	12922008
+42	39	0
+12	156	79
+8	39	0
+52
+
+chain	7488	1_random	1663265	+	375996	376227	1	249250621	-	247932827	247932944	24096271
+39	178	64
+14
+
+chain	7272	1_random	1663265	+	492183	493450	GL000192.1	547496	+	517200	518462	5534
+104	1136	1131
+27
+
+chain	7258	1_random	1663265	+	576783	577499	14	107349540	-	76512188	76512903	4928952
+56	262	262
+101	216	215
+81
+
+chain	7167	1_random	1663265	+	376446	376521	1	249250621	-	247932507	247932582	27908410
+75
+
+chain	6857	1_random	1663265	+	87342	87413	4	191154276	-	48731804	48731875	28524152
+71
+
+chain	6426	1_random	1663265	+	508964	509092	1	249250621	+	144828390	144828518	146082
+13	51	51
+64
+
+chain	6204	1_random	1663265	+	211009	211075	1	249250621	+	1467491	1467557	30075428
+66
+
+chain	6008	1_random	1663265	+	376783	376999	1	249250621	-	247932727	247932982	14593768
+49	132	171
+35
+
+chain	5855	1_random	1663265	+	576112	576191	20	63025520	+	560198	560277	14627950
+79
+
+chain	5539	1_random	1663265	+	247082	247140	16	90354753	-	36623787	36623845	31913042
+58
+
+chain	5517	1_random	1663265	+	575499	575571	1	249250621	-	135388947	135389019	22575370
+19	14	14
+39
+
+chain	5153	1_random	1663265	+	463736	463802	1	249250621	-	100897669	100897735	496173
+66
+
+chain	4331	1_random	1663265	+	576997	577043	4	191154276	+	125192159	125192205	31588172
+46
+
+chain	4269	1_random	1663265	+	508977	509028	1	249250621	-	101245694	101245744	11082093
+11	1	0
+24	1	1
+14
+
+chain	3392	1_random	1663265	+	1264741	1264777	1	249250621	+	103601716	103601752	22855599
+36
+
+chain	2584	1_random	1663265	+	472532	472613	1	249250621	-	104701386	104701467	60543
+81
+
+chain	2530	1_random	1663265	+	576576	576677	2	243199373	+	18874674	18874775	4960893
+101
+
+chain	2443	1_random	1663265	+	508878	508906	1	249250621	+	145358788	145358816	8460
+28
+
+chain	2298	1_random	1663265	+	376035	376059	1	249250621	-	247932520	247932544	25650669
+24
+
+chain	2200	1_random	1663265	+	377179	377218	1	249250621	-	247932814	247932853	18046603
+39
+
+chain	2078	1_random	1663265	+	576191	576213	2	243199373	-	87184513	87184535	19810119
+22
+
+chain	1902	1_random	1663265	+	462945	462974	1	249250621	+	146388727	146388756	1440299
+29
+
+chain	1597	1_random	1663265	+	87932	87955	1	249250621	+	203810737	203810760	8954286
+23
+
+chain	1582	1_random	1663265	+	576728	576783	12	133851895	+	80469819	80469874	8882774
+55
+
+chain	1575	1_random	1663265	+	377270	377295	1	249250621	-	247932789	247932814	25950613
+25
+
+chain	1557	1_random	1663265	+	376743	376767	1	249250621	-	247932958	247932982	25686497
+24
+
+chain	1423	1_random	1663265	+	577528	577578	3	198022430	+	24122600	24122650	5633229
+50
+
+chain	1401	1_random	1663265	+	208964	209027	19	59128983	+	53692979	53693042	24768107
+63
+
+chain	1269	1_random	1663265	+	577058	577101	X	155270560	-	54470903	54470946	5438939
+43
+
+chain	1137	1_random	1663265	+	88481	88531	X	155270560	-	107394638	107394688	10193603
+50
+
+chain	1096	1_random	1663265	+	88429	88481	1	249250621	-	213837318	213837370	14790649
+52
+
+chain	963	1_random	1663265	+	575892	575970	1	249250621	-	198864223	198864301	11419759
+78
+
+chain	917	1_random	1663265	+	455298	455327	GL000192.1	547496	-	58673	58702	411262
+29
+
+chain	870	1_random	1663265	+	577218	577269	6	171115067	-	89553434	89553485	24911812
+51
+
+chain	794	1_random	1663265	+	88312	88337	4	191154276	+	171087862	171087887	6635553
+25
+
+chain	649	1_random	1663265	+	576545	576576	15	102531392	-	5321440	5321471	7251364
+31
+
+chain	622	1_random	1663265	+	576462	576495	11	135006516	+	114505284	114505317	6564387
+33
+
+chain	546	1_random	1663265	+	88531	88556	6	171115067	+	144792007	144792032	10415340
+25
+
+chain	398	1_random	1663265	+	575763	575814	14	107349540	+	34662629	34662680	24063646
+51
+
+chain	22466167312	2	242951149	+	0	242751149	2	243199373	+	10000	243102476	1
+1201236	1	0
+2057	1	1
+26	1	1
+4043	0	22
+82	101	7
+33	0	74
+36	13	1
+67	0	48
+152	0	418
+50	2	0
+6	6	0
+76	74	0
+20	6	0
+22	118	0
+374	0	2446
+836	0	2310
+21	0	2444
+21507	1	1
+50	0	4
+2041	4	0
+9052	0	2
+81	8	0
+10	42	0
+1078	1	0
+4122	0	1
+1608	1	28
+4029	9	0
+967	1000	4547
+414	0	27
+2237132	1	0
+2458	17	17
+3915	47	47
+633	0	4
+3531	14	14
+3954	50000	51129
+1426129	100025	160449
+11087286	3	0
+773	50000	103977
+1576	1	0
+240	1	0
+318	0	2
+258	16	0
+2848	10	10
+1404	1	1
+27	1	1
+703	0	13
+375	1	0
+4783388	25000	35000
+848	2	0
+1225	2	0
+391	0	1
+3445	24	24
+184	1	1
+28	1	1
+49	4	0
+4514	9	0
+9628	9	1
+1483	7	7
+1990	1	0
+1949	0	1
+2716230	0	1
+46732767	9	5
+9477928	3	0
+7520813	0	72396
+1900436	150000	294073
+17672	0	1
+5792	0	1
+9019	266	0
+2942	1	0
+9388	0	2
+37826	0	4
+23440	4	0
+290929	1000000	1273578
+731068	3000000	3000000
+2558421	1	0
+1196	0	10
+686	1	0
+26	3	0
+15	1	1
+2309	1	0
+1332	23	22
+344	1	0
+1645	4	4
+6564	0	1
+6329	0	1
+769	1	0
+873	0	7
+1299	1	0
+8250	15	15
+4291	12548	10626
+1054	0	103
+84	218	0
+5897	1	1
+33	1	1
+9905	37	51
+1645	113	113
+1597	4	4
+61	1	1
+866	0	13
+2830	0	3
+2819	2	0
+156	436	88
+100	54	0
+4753	8	0
+4903	6	6
+3847	2	0
+108126	145	0
+3542	0	1
+10276	1	0
+402	1	1
+47	1	1
+63	0	2
+583	1	1
+34	1	1
+8975	46	0
+378	1	1
+70	1	1
+2476	102	0
+1754	1	0
+8426	1	0
+11986570	142000	151150
+14207	1	1
+49	1	1
+1784	12	0
+406	0	1
+1874	1	1
+33	1	1
+4795	0	2
+3686	1	1
+15	1	1
+164	0	2
+7287	5	5
+702023	150000	72796
+69	0	1
+1598	1	0
+1340	1	0
+1030	4	0
+1166	10	10
+629	27	27
+5750	1	1
+34	1	1
+3283	4	2
+496	21	1
+25	1	9
+41	1	1
+329	4	4
+9955	41	41
+10953	1	2
+1417	44	0
+911	0	17
+18270	0	1
+178429	281526	0
+34455	406	0
+58863	2	1
+1843	2	0
+14994	1	0
+12992	0	2
+2571146	0	1
+35688061	100000	108224
+29671719	0	1
+39665349	0	1
+14876089	20000	64197
+401	3	0
+1831	1	1
+61	1	1
+654	1	11
+138	28	0
+105	1	1
+25	4	0
+73	9	9
+3247	0	2
+1355	0	1
+816	21	25
+526	1	1
+60	1	1
+773	0	1
+1494	0	1
+448	44	44
+1191	0	1
+21	1	1
+596	0	1
+1582	0	1
+425	3	0
+1141	8	0
+136	744	80
+18	1	0
+4	1	0
+8	4	2
+32	1	0
+71	0	1
+385747	1	1
+110	1	1
+51	7	7
+54	15205	15205
+54	7	7
+51	1	1
+110	1	1
+5198249	1	0
+108	0	40
+65	0	80
+100	2	82
+442	1	1
+35	1	1
+119	129	9
+33	40	0
+42	1	1
+86	40	0
+1330	1	0
+1194	2	0
+11	1	1
+1773	5	0
+1623	1	1
+25	1	1
+2422	1	1
+20	1	0
+2315	1	0
+31	1	1
+1508	3	0
+50	4	0
+970	6	6
+7234	0	4
+1228	0	1
+1233	1	8
+744	16	16
+3447	1	1
+41	1	1
+3297	2	0
+1714	0	2
+2299	0	2
+2143	1	1
+18	1	1
+917	0	1
+1082	1	1
+49	1	1
+9098	4	0
+5529	1	0
+3266	8	0
+894	0	6
+3536	0	2
+4179	13	18
+1785	1	0
+1675	6	0
+1216	33000	32348
+287	109	573
+12548	30000	30000
+952154	25000	41011
+1914	0	1
+225	1	1
+57	1	1
+2910	1	0
+471	0	1
+1956	1	1
+43	1	1
+1000	92	0
+2854	0	3
+1837	0	306
+1007	0	30
+206	35	32
+217	17	17
+1525	0	8
+413	1	1
+32	2	2
+1573	12	12
+2258676
+
+chain	1437141	2	242951149	+	234136066	234151271	2	243199373	-	8712841	8728046	1459
+15205
+
+chain	1229376	2	242951149	+	110524471	111016063	2	243199373	-	132402743	134718956	53
+41	12371	12350
+33	0	23
+11	197610	197512
+5295	5	5
+190	69	19
+2195	1	0
+285	34	34
+1682	1	0
+182	11	6
+291	0	1
+1506	15	16
+146	5	5
+2050	51	51
+186	8	7
+68	7	6
+41	1	0
+306	0	1
+1545	1	0
+1334	25	24
+543	0	2
+224	17	21
+615	1	0
+208	2	0
+158	27	21
+3320	0	1
+576	0	2
+4562	0	6
+1023	0	1
+977	0	1
+3904	1	0
+827	415	28
+1508	14	13
+9571	36	36
+1393	1	1
+42	1	1
+2205	0	2
+5258	36	0
+42	2	0
+4437	2	0
+3357	1	0
+6289	0	9
+1996	1	0
+3228	0	1
+202	0	1
+2743	7	0
+24	0	5
+549	3	1
+942	0	6
+1815	8	0
+874	0	3
+4737	0	2
+852	14	18
+518	14	14
+4377	1	1
+49	1	1
+3270	1	0
+753	0	4
+240	1	0
+2391	0	1
+4745	4	0
+5752	0	2
+880	0	1
+397	1	0
+1407	0	3
+120	1	1
+89	1	1
+7011	3	0
+188	8	8
+834	5	0
+94	18	18
+3711	150112	1975291
+345	52	52
+100	8	8
+52	6	6
+650	6	6
+273	91	95
+88	90	90
+331	116	116
+66	35	35
+145	13	15
+95	6	6
+301	43	47
+444	12	12
+645	116	119
+215	31	31
+748	58	57
+212	71	71
+420	38	38
+190	4	4
+51	32	32
+65	32	32
+182	69	69
+161	17	17
+74	36	36
+170	25	25
+124	19	15
+230
+
+chain	33206	2	242951149	+	111008548	111015495	2	243199373	+	113147044	113153995	310
+112	345	345
+52	1095	1095
+15	0	4
+76	88	88
+90	331	331
+116	66	66
+35	560	560
+43	1101	1101
+116	215	215
+31	748	748
+58	212	212
+71	420	420
+38	245	245
+32	65	65
+32	182	182
+69	252	252
+36
+
+chain	15095	2	242951149	+	97284299	97473552	2	243199373	-	145080546	145267103	122
+48	13638	11732
+218	15837	15837
+37	1645	1645
+113	8336	8336
+436	100	100
+54	121645	121635
+3	25	0
+101	26915	26159
+9	0	1
+93
+
+chain	10366	2	242951149	+	110742577	110753868	2	243199373	+	113162562	113173850	1257
+34	5889	5884
+51	5290	5292
+27
+
+chain	3994	2	242951149	+	111050518	111050561	2	243199373	-	132647167	132647210	483
+43
+
+chain	3626	2	242951149	+	1208025	1208063	2	243199373	+	1217618	1217656	30090800
+38
+
+chain	3098	2	242951149	+	110780566	110780602	2	243199373	+	100698198	100698234	394442
+36
+
+chain	2548	2	242951149	+	89594034	89594300	2	243199373	-	153635204	153635700	103
+90	9	107
+22	9	0
+32	3	0
+5	0	125
+21	15	30
+5	1	0
+25	0	5
+29
+
+chain	2507	2	242951149	+	1207989	1208025	2	243199373	+	1217656	1217692	7254147
+36
+
+chain	2306	2	242951149	+	97446409	97446434	2	243199373	+	98080299	98080324	1844703
+25
+
+chain	5644665978	20	62435964	+	8000	62435964	20	63025520	+	60000	62965520	20
+26259569	1765661	3100000
+234339	1000000	150000
+4004088	0	1
+6459	0	244
+37810	0	2
+1044573	20000	50000
+9411883	2	8
+362	0	1
+11607353	0	1
+1301304	1	0
+31033	0	9
+1154	0	2
+1088	1	1
+29	1	1
+2509	0	2
+407	1	0
+40	1	1
+3787164	27050	50000
+71932	110000	50000
+694117	0	1
+1008033
+
+chain	3228730713	21	46944323	+	9719767	46944323	21	48129895	+	10697896	48119895	23
+490233	3050000	3150000
+19828060	0	1
+8789369	1199	50000
+243783	1500	1500
+1381822	1359	50000
+3437231
+
+chain	42537850	21_random	1679693	+	281005	1255172	21	48129895	+	9411193	10647896	88
+184355	50000	489372
+131056	458754	281918
+150002
+
+chain	21600281	21_random	1679693	+	876305	1679693	21	48129895	-	37585054	38304458	99
+178865	280890	346005
+315	2	2
+38	1	1
+261	1	1
+24	1	1
+157	0	325
+16	1	1
+85	1	1
+66	1	1
+330	11	11
+235	1	1
+51	1	1
+405	1	1
+26	1	1
+130	5	5
+80	1	1
+91	1	1
+20	1	1
+244	0	1
+478	1	1
+5	1	0
+13	0	1
+49	1	1
+197	10	10
+158	1	1
+57	0	1
+829	1	1
+60	1	1
+51	0	1
+584	1	0
+21	2	0
+151	20	20
+316	1	1
+16	1	1
+100	7	7
+102	1	1
+49	1	1
+125	1	0
+102	13	13
+153	20	20
+199	1	0
+35	1	1
+367	1	1
+51	1	1
+344	1	1
+101	1	1
+243	1	1
+27	1	1
+338	0	4
+166	15	15
+73	1	1
+44	1	1
+282	4	4
+67	1	1
+54	1	1
+216	1	1
+48	1	1
+76	1	1
+70	1	1
+392	1	1
+44	1	1
+65	8	9
+362	0	4
+34	1	1
+68	1	1
+57	1	0
+120	1	1
+374	1	1
+21	1	1
+121	1	1
+34	1	1
+80	1	0
+64	2	0
+162	8	8
+184	1	1
+34	1	1
+658	2	2
+52	0	4
+297	1	0
+136	1	1
+20	1	1
+905	0	1
+250	7	8
+138	0	3
+104	1	0
+42	1	1
+539	0	1
+43	4	0
+633	0	20
+353	17	17
+969	4	0
+39	3	3
+210	3	1
+188	7	7
+459	2	2
+25	1	1
+207	1	1
+55	1	1
+375	1	1
+66	1	1
+599	0	2
+395	1	1
+33	1	1
+73	1	1
+35	2	0
+275	9999	10000
+353	1	1
+26	1	1
+423	1	1
+32	1	1
+86	7	7
+197	1	1
+44	1	1
+96	1	1
+77	7	0
+247	0	2
+77	1	1
+425	13	1
+32	1	1
+65	1	1
+217	3	2
+115	1	1
+33	1	1
+268	1	0
+959	1	1
+63	1	1
+93	5	5
+185	1	1
+31	1	1
+944	12	12
+413	1	1
+92	1	1
+276	1	1
+35	1	1
+500	1	1
+31	149436	9
+158069
+
+chain	14432948	21_random	1679693	+	78709	231005	21	48129895	+	9882623	10034920	205
+77296	0	1
+75000
+
+chain	7807601	21_random	1679693	+	1362161	1471624	1	249250621	-	105758025	105867745	293
+77	11427	11419
+174	5	5
+857	64	64
+2170	0	2
+621	1	1
+26	1	1
+4365	0	1
+155	0	1
+452	0	4
+941	0	4
+403	1	1
+45	1	1
+534	86	86
+2198	0	1
+303	2	0
+5470	6	6
+845	1	1
+45	1	1
+221	6	0
+321	1	1
+44	1	1
+354	1	0
+374	131	130
+577	6	5
+263	17	16
+207	0	2
+1746	14	14
+3223	1	1
+46	4	4
+1479	1	1
+46	1	1
+383	0	3
+44	1	1
+2724	67	67
+47	145	145
+350	116	116
+138	0	1
+1	65	65
+796	17	17
+645	1	0
+24	1	1
+1318	1	0
+687	1	1
+41	1	1
+2292	1	1
+37	1	1
+589	1	1
+37	1	0
+670	13	13
+357	4	0
+2667	3	0
+1941	1	1
+31	1	1
+1538	54	54
+64	166	166
+120	226	226
+46	14	0
+14	155	155
+92	54	54
+26	55	55
+98	131	131
+36	1	1
+76	391	391
+44	294	294
+37	813	813
+35	219	219
+898	1	1
+19	1	1
+213	12	12
+1926	1	1
+21	1	1
+4561	1	1
+28	1	1
+8361	1	1
+43	1	1
+429	211	492
+3095	0	1
+3873	1	1
+43	5	5
+3785	171	171
+65	122	122
+70	116	116
+29	459	459
+36	352	352
+39	93	93
+39	190	190
+41	1783	1784
+35	509	509
+27	394	394
+57	834	834
+58	10	10
+17	758	760
+41	0	4
+82	194	194
+60	543	543
+31	58	58
+46	607	607
+34	98	98
+31	1	1
+38	563	562
+135	1980	1976
+48	370	370
+42	515	515
+49	456	456
+3137	0	1
+2483	1	0
+357	1	1
+49	1	1
+1181	1	0
+885	1	0
+86
+
+chain	3630496	21_random	1679693	+	696416	1463441	21	48129895	+	9645548	10215976	235
+129889	481231	310631
+225	46	51
+383	6	6
+73	18	18
+200	18	39
+236	63	68
+123	340	365
+57	300	259
+51	138	138
+71	55	55
+60	152	152
+51	100	103
+61	358	357
+85	1906	236
+88	157	153
+56	39	39
+73	20146	20047
+67	1	0
+57	154	154
+59	940	953
+61	205	205
+60	46	46
+122	149	149
+53	64	56
+210	16	16
+209	1	0
+214	29	29
+71	69616	76139
+67	47	47
+145	350	354
+116	139	135
+65	13718	10425
+54	64	64
+166	120	120
+225	75	75
+74	14	13
+67	92	92
+54	26	26
+55	98	98
+127	117	117
+173	16	15
+202	44	44
+198	21	17
+75	37	37
+442	18	18
+353	35	35
+219	27532	0
+105	0	3
+66	65	65
+122	70	70
+116	29	29
+459	36	36
+278	17	17
+57	39	40
+93	39	39
+190	41	41
+285	16	20
+859	22	37
+176	4	4
+183	32	32
+206	35	36
+509	27	27
+394	57	56
+116	5	5
+596	1	0
+116	85	85
+54	0	1
+119	0	2
+585	124	127
+74	10	11
+109	60	60
+82	22	22
+439	31	31
+58	46	46
+106	21	22
+186	15	14
+279	34	34
+98	70	67
+166	1	0
+396	135	135
+1551	12	12
+90	0	3
+69	4	4
+48	3	0
+203	48	48
+370	42	42
+139	14	53
+362	49	49
+456
+
+chain	2630212	21_random	1679693	+	936	28709	21	48129895	+	44682664	44710462	1048
+3985	6	7
+8941	0	30
+3327	1	1
+74	1	1
+859	22	22
+89	70	70
+489	14	3
+11	2	1
+10	10	0
+10	0	1
+31	1	27
+556	3	0
+128	0	1
+358	1	1
+45	1	1
+1712	8	0
+6545	32	31
+431
+
+chain	517534	21_random	1679693	+	1332563	1373665	GL000194.1	191469	-	21469	62943	261
+130	2	2
+53	1	1
+139	1	1
+60	1	1
+321	125	125
+72	1	1
+81	59	59
+248	22	23
+250	13	13
+407	61	61
+205	60	60
+46	122	122
+149	53	53
+14	0	8
+50	650	650
+29	19697	20073
+100	1	4
+106	2	2
+158	1	1
+89	1	1
+10	1	1
+65	1	1
+48	1	1
+156	1	1
+61	1	1
+156	1	1
+81	1	1
+522	16	16
+377	22	22
+358	1	1
+17	1	1
+141	1	0
+29	0	1
+16	1	1
+105	1	1
+49	2	1
+63	1	1
+32	1	0
+7	1	1
+349	1	2
+102	1	1
+146	1	0
+93	3	0
+149	1	1
+86	1	1
+220	1	1
+111	1	1
+195	19	19
+108	1	1
+79	6	1
+98	0	1
+29	2	2
+98	1	1
+125	1	1
+196	1	1
+52	1	1
+767	1	1
+68	3	3
+70	1	1
+66	1	1
+331	1	1
+22	1	1
+60	77	77
+437	1	1
+61	1	1
+134	1	1
+48	4	2
+26	0	2
+79	1	1
+16	1	1
+77	1	1
+24	1	1
+176	1	1
+33	1	1
+61	0	4
+141	1	1
+17	1	1
+232	1	1
+42	1	1
+439	2	1
+31	1	1
+55	1	0
+181	1	1
+77	4	4
+145	4	5
+22	1	1
+159	1	6
+53	1	1
+63	1	1
+67	6	6
+71	1	1
+25	1	1
+103	6	6
+303	6513	6492
+211	1	1
+87	1	1
+170	2	2
+36	0	6
+361	1	1
+58	1	1
+292	10	10
+201	1	1
+35
+
+chain	353583	21_random	1679693	+	1323386	1332563	GL000218.1	161147	-	0	9198	304
+693	1	1
+28	4	0
+425	51	51
+874	2	4
+421	1	1
+23	1	1
+299	2	1
+20	3	3
+88	1	1
+35	1	1
+283	4	4
+42	4	4
+719	14	14
+181	1	1
+41	1	1
+1010	1	1
+59	1	1
+478	1	1
+45	1	0
+78	1	1
+315	1	1
+22	1	1
+342	1	1
+27	1	1
+716	0	25
+83	1	1
+44	1	1
+218	6	6
+142	1	1
+178	1	1
+220	1	1
+35	1	1
+55	1	1
+44	1	1
+143	1	1
+80	1	1
+85	1	1
+46	1	1
+169	1	1
+56	1	1
+94	1	1
+51	1	1
+48
+
+chain	153763	21_random	1679693	+	1307498	1317523	1	249250621	+	142541121	142549427	248494
+38	225	225
+46	934	934
+63	240	230
+50	653	627
+57	559	562
+4	186	183
+51	101	101
+16	235	235
+70	1848	174
+58	193	194
+3	255	257
+97	40	40
+164	35	35
+167	27	27
+82	213	218
+106	172	171
+55	274	274
+125	214	209
+158	123	124
+94	169	169
+69	430	425
+66	871	864
+95	213	213
+81
+
+chain	88175	21_random	1679693	+	0	28278	GL000210.1	27682	-	0	27251	1050
+107	675	0
+154	27310	26958
+32
+
+chain	46308	21_random	1679693	+	1305249	1307368	21	48129895	-	38147885	38150014	728191
+46	171	171
+69	165	166
+32	292	292
+34	184	184
+26	73	73
+23	117	117
+57	54	54
+7	16	25
+68	78	78
+23	242	242
+53	230	230
+59
+
+chain	40072	21_random	1679693	+	1311066	1311528	3	198022430	+	38430454	38430916	3283349
+95	1	1
+47	1	1
+177	1	1
+41	1	1
+98
+
+chain	25551	21_random	1679693	+	1316263	1317134	21	48129895	+	10022171	10023044	3443865
+97	94	94
+87	148	147
+94	340	343
+11
+
+chain	20886	21_random	1679693	+	1305172	1307309	Y	59373566	-	45989384	45991522	2022
+77	46	46
+64	50	50
+57	69	70
+165	32	32
+86	11	11
+195	34	34
+184	122	122
+117	57	57
+54	91	91
+50	51	51
+242	61	61
+68	9	9
+145
+
+chain	10360	21_random	1679693	+	1384481	1394861	21	48129895	-	38158677	38169079	831
+56	10224	10246
+100
+
+chain	9106	21_random	1679693	+	1316541	1317639	2	243199373	+	56015784	56016880	4408555
+45	37	37
+66	97	95
+66	672	672
+115
+
+chain	7814	21_random	1679693	+	1312477	1312593	8	146364022	+	34952530	34952621	21041862
+26	37	12
+53
+
+chain	6987	21_random	1679693	+	1305359	1306761	1	249250621	-	105769657	105771059	738748
+38	5	5
+7	1324	1324
+28
+
+chain	3478	21_random	1679693	+	1309705	1309742	X	155270560	-	92499801	92499838	30075241
+37
+
+chain	2939	21_random	1679693	+	1312274	1312311	1	249250621	-	217601682	217601719	16037052
+37
+
+chain	2906	21_random	1679693	+	1394861	1394892	GL000247.1	36422	-	2105	2136	848
+31
+
+chain	2805	21_random	1679693	+	1309675	1309705	4	191154276	-	16268024	16268054	28769751
+30
+
+chain	2788	21_random	1679693	+	1374701	1374765	GL000194.1	191469	-	63980	64044	1175
+9	36	36
+19
+
+chain	2571	21_random	1679693	+	1317411	1317442	20	63025520	-	39738360	39738391	24462467
+31
+
+chain	2324	21_random	1679693	+	1311588	1311646	2	243199373	+	3637936	3637994	8156424
+58
+
+chain	1980	21_random	1679693	+	1440240	1440313	1	249250621	+	142677559	142677632	922
+73
+
+chain	1679	21_random	1679693	+	1316387	1316422	13	115169878	+	41439086	41439121	11997585
+35
+
+chain	1437	21_random	1679693	+	1316422	1316454	3	198022430	+	119282439	119282471	8460363
+32
+
+chain	1151	21_random	1679693	+	1312216	1312274	13	115169878	+	46060123	46060181	10002138
+58
+
+chain	1007	21_random	1679693	+	1312144	1312195	17	81195210	+	33522637	33522688	8813060
+51
+
+chain	810	21_random	1679693	+	1306268	1306301	4	191154276	-	63157613	63157646	21715000
+33
+
+chain	762	21_random	1679693	+	1312422	1312477	7	159138663	+	153013126	153013181	10840208
+55
+
+chain	732	21_random	1679693	+	1312000	1312066	7	159138663	-	102920653	102920719	25474729
+66
+
+chain	561	21_random	1679693	+	18264	18311	21	48129895	+	44700101	44700148	25859698
+47
+
+chain	3320960322	22	49691432	+	14430000	49591432	22	51304566	+	16050000	51244566	22
+647850	150000	150000
+3661581	50000	100000
+15278435	0	18
+293	0	36
+1410	1	1
+46	1	1
+6626947	2	4
+1759	1	1
+43	1	1
+1367363	12000	10615
+7856	4	0
+809336	0	20
+6307	20	0
+6702	50000	2669
+4247727	10618	0
+1558	0	2719
+35231	0	131
+12647	4	0
+45594	85	9
+19562	0	506
+165501	5	7
+1103946	16700	60575
+644	0	2
+319796	1600	1155
+17927	19763	15469
+464566
+
+chain	6025887	22_h2_hap1	63661	+	0	63661	22	51304566	+	42594964	42658568	527
+748	1	0
+260	4	0
+675	1	0
+4844	0	2
+10592	8	0
+3276	29	0
+2384	10	0
+2795	0	2
+464	1	0
+3865	1	0
+1777	1	0
+1286	0	2
+875	1	0
+2336	1	0
+4337	1	0
+2724	0	3
+1087	6	0
+7154	0	1
+1045	2	0
+11070
+
+chain	15737781	22_random	257318	+	90752	257318	GL000211.1	166566	+	0	166566	187
+166566
+
+chain	3641362	22_random	257318	+	7	38789	11	135006516	-	18284691	18323344	804
+2900	3	1
+66	1	1
+55	1	1
+3449	0	1
+1785	1	1
+37	1	1
+178	1	0
+852	0	1
+2329	2	0
+4939	1	0
+1557	1	1
+30	1	1
+1005	1	0
+622	16	0
+39	0	1
+42	0	22
+755	1	1
+30	1	1
+952	1	1
+26	1	1
+141	18	17
+1110	2	0
+1529	1	1
+22	1	1
+399	1	1
+33	1	1
+1369	20	30
+3959	0	4
+1144	1	0
+1032	27	25
+8	23	0
+56	24	0
+51	0	9
+11	1	57
+34	4	4
+7	134	0
+296	26	0
+25	1	1
+2452	0	5
+19	1	1
+231	1	0
+327	1	0
+962	1	1
+22	1	1
+1571
+
+chain	109494	22_random	257318	+	39517	40750	22	51304566	-	30977735	30979001	1172425
+166	5	5
+133	3	3
+48	1	1
+297	0	33
+234	1	1
+58	4	4
+283
+
+chain	19094	22_random	257318	+	39007	39213	22	51304566	-	29625864	29626070	11204980
+206
+
+chain	8587	22_random	257318	+	39415	39517	22	51304566	-	29782769	29782871	2027258
+50	48	48
+4
+
+chain	3763	22_random	257318	+	39465	39513	22	51304566	-	30978529	30978577	2726523
+48
+
+chain	17719073	2_random	185571	+	0	185498	2	243199373	+	242522204	242710000	158
+43034	21	22
+16724	1	0
+52199	0	669
+3059	0	4
+14500	1	0
+409	1	1
+22	1	1
+2039	1	0
+809	0	1
+2041	0	4
+2258	6	6
+4179	12	13
+1973	1	1
+21	1	1
+1855	1	1
+37	2	2
+4315	0	1
+1584	14	0
+281	0	2
+78	1	1
+1497	9	0
+237	2	1
+826	4	0
+21273	4	0
+6716	0	1650
+3449
+
+chain	18404389309	3	199501827	+	35000	199446827	3	198022430	+	60000	197962430	3
+13552792	1	0
+585083	1	0
+2092	74	72
+31067262	1	0
+90	0	1
+5628461	15	0
+788	0	1
+3676	2	0
+35	1	1
+4682	0	1
+1295	5	0
+437	42	53
+326	2	0
+3309	1	1
+40	1	1
+998	3	0
+3584	0	5
+930	7	5
+845	1	1
+28	1	2
+303	1	0
+509	5	0
+2291	6	6
+2789	0	1
+2541	9692	9690
+949	4	4
+35	1	1
+2874	1	0
+6717	1	0
+2823	0	1
+704	4	0
+5142	0	1
+2490	10	10
+162	7	7
+6308	15	0
+15177535	260003	152352
+2532	0	1
+24209179	4400000	3000000
+60453438	4	0
+40076811	20000	20999
+8195	1	1
+44	1	1
+1408	1	1
+33	1	1
+172	4	3
+25	1	1
+538	13	13
+173	1	1
+27	1	1
+636	1	1
+28	1	1
+470	3	3
+112	1	1
+375	1	1
+26	0	26
+106	0	78
+72	9	6
+12	3	29
+79	5	262
+56	1	1
+20	1	1
+815	43	43
+457	1	1
+49	0	18
+509	3	4
+23	1	1
+391	1	1
+44	1	1
+1270	4	0
+40	1	1
+264	27	31
+2416	2	0
+4377	13	13
+736	1	1
+47	1	1
+1416	1	1
+20	1	1
+1020	1	1
+25	1	1
+482	0	5
+716	0	1
+1697	1	1
+29	1	1
+1270261	27000	23108
+40930	0	1
+17455	1	1
+28	4	4
+45	491	0
+1669	58	0
+18	3	61
+54863	16	53
+7653	6	0
+3	99	0
+170	30	0
+25	0	30
+210	0	45
+359	0	915
+5980	256	640
+1363	1	1
+37	1	1
+7958	1	0
+372	1	0
+2442058
+
+chain	572461	3	199501827	+	50900356	50910048	3	198022430	-	147087402	147097092	2111
+52	1	6
+5886	1	0
+2586	6	0
+1160
+
+chain	14997	3	199501827	+	196923229	196923617	3	198022430	+	195437554	195437811	3659243
+77	131	0
+180
+
+chain	6146	3	199501827	+	196987930	196988205	3	198022430	+	195502296	195502751	2529960
+74	171	141
+23	2	212
+5
+
+chain	4201	3	199501827	+	196923126	196923228	3	198022430	+	195438036	195438138	6236935
+102
+
+chain	2082	3	199501827	+	196994845	196994975	3	198022430	+	195509346	195509572	2249717
+55	18	114
+57
+
+chain	20970321	3_random	749256	+	196010	556188	3	198022430	-	121623404	130096441	129
+131258	0	1
+41217	50000	8162858
+137703
+
+chain	13779918	3_random	749256	+	0	146010	3	198022430	-	77602115	77748060	219
+64144	1	0
+1191	0	1
+633	0	1
+4651	29	21
+5147	0	1
+947	14	0
+64	56	0
+55	0	2
+2421	0	15
+741	9	0
+371	6	4
+554	1	0
+5424	0	1
+4074	1	1
+44	1	1
+3065	0	1
+2772	1	1
+36	1	1
+15950	1	0
+2351	0	2
+5999	1	0
+17825	0	13
+74	1	1
+367	1	1
+47	1	1
+2084	2	0
+288	0	3
+744	1	0
+131	0	1
+465	1	1
+29	1	1
+659	10	0
+830	0	3
+262	3	0
+1428
+
+chain	13528802	3_random	749256	+	606188	749256	3	198022430	+	46352896	46495976	221
+8517	0	10
+20860	0	6
+16120	0	1
+4148	7	6
+745	7	6
+517	6	0
+907	5	5
+1382	4	0
+2730	0	1
+1143	36	36
+457	13	17
+1748	1	1
+48	1	1
+954	0	2
+767	1	4
+7353	0	8
+4950	0	12
+13338	0	1
+4685	1	1
+21	1	1
+1414	3	0
+4158	23	23
+5081	0	1
+14097	1	1
+49	1	1
+770	16	16
+424	1	1
+17	1	1
+244	1	1
+23	1	1
+1462	12	0
+2048	14	0
+4573	1	0
+3856	2	0
+754	0	8
+7304	1	0
+5243
+
+chain	17653370240	4	191273063	+	0	191263063	4	191154276	+	10000	191029082	4
+1413146	51000	71672
+5369	5	6
+65	1	1
+67	1	1
+425	1	1
+32	1	1
+175	1	1
+34	1	1
+5092	1	1
+46	1	1
+1396	15	15
+1446	0	1
+5135	1	0
+586	1	1
+38	1	1
+10	0	21
+1587	0	6
+205	0	3
+97	6	0
+177	0	9
+4059	1	1
+71	1	1
+1413	83	1
+51	7	7
+105	7	7
+67	41	0
+67	42	1
+55	41	0
+25	41	0
+3244	558	0
+64	93	0
+93	558	0
+907	0	2
+1101	55	0
+3473	15	15
+1167	3	0
+25	0	29
+135	29	0
+5074	1	1
+42	1	1
+1825	14	14
+1992	0	3
+23	1	1
+4171	6	6
+796	0	165
+196	0	99
+87	0	33
+190	6	8
+107	2	2
+21	0	2
+62	1	68
+32	14	15
+81	18	18
+55	0	100
+17	1	1
+222	2	169
+51	0	35
+3289	18	18
+298	0	1
+373	0	1
+2965	1	1
+28	0	23
+1704	0	38
+114	0	38
+53	7	44
+119	77	0
+269	1	1
+70	1	1
+2000	23	33
+2400	1	1
+94	1	1
+6002	18	18
+776	1	0
+369	16	16
+418	51	0
+53	1	27
+2181	1	4
+57	1	1
+1973	10	0
+4184	11	11
+1594	0	18
+2038	0	109
+4332	0	7
+49	0	4
+1465	3	1
+4156	2	0
+5455	3	2
+129	4	4
+9082	0	1
+786	20	20
+1506	0	1
+252	8	7
+17512	50	1
+56	1	0
+2474	69	52
+69	0	30
+60	16	0
+19	15	0
+40	1	1
+138	16	0
+74	5	51
+3386	0	1
+968	0	4
+1624	11	11
+1065	0	3
+2935	8	0
+2312	0	181
+2300	1	0
+1641	6	1
+1955	0	1
+68	1	1
+347	1	1
+40	1	1
+1553	6	0
+678	16	16
+92	0	33
+390	4	0
+1147	0	1
+1948	4	4
+4296	18	18
+955	1	1
+47	1	1
+1555	1	0
+2251535	81122	0
+145	1	1
+48	1	1
+718	1	0
+2789	1	1
+27	1	1
+1601	4	0
+1048	39	39
+820	0	2
+20	6	0
+28	2	0
+76	12	18
+28	1	0
+11	9	3
+1772	0	6
+22	1	1
+946	1	1
+24	1	1
+1245	1	0
+3231	1	1
+41	1	1
+1652	20	20
+11270	3	0
+2704	1	1
+41	1	1
+1812	5	6
+1477	0	11
+3790	4	0
+2187	1	1
+48	1	1
+1704	1	1
+73	1	1
+2265	1	1
+10	1	1
+553	1	1
+49	1	1
+67	1	1
+33	1	1
+3932	5	0
+18	1	0
+780	0	1
+1260	0	1
+4203	0	25
+863	14	14
+7114	1	1
+70	1	1
+169	0	1
+43	1	1
+145	1	1
+39	0	3
+8	1	1
+753	0	1
+2255	1	1
+21	1	1
+1605	1	1
+19	2	1
+392	1	1
+29	1	0
+3673	1	0
+145	14	14
+39	0	1
+1246	0	1
+2302	1	0
+1554	9	9
+4537	0	1
+1064	2	0
+2051	1	0
+1130	0	2
+164	1	0
+1972	0	1
+18	3	3
+2597	1	1
+46	3	3
+196	1	1
+17	1	1
+60	4	4
+187	4	4
+46	1	1
+692	1	0
+3920	3	3
+15	1	1
+486	14	14
+1709	8	0
+169	1	0
+597	1	1
+18	0	7
+3423937	0	1
+1295496	1	1
+26	1	1
+760	150000	591802
+22468468	1	1
+27	1	1
+2592	0	2
+33	1	1
+2065	3	0
+1050	11	11
+1046	3	9
+52	11	11
+3200	1	0
+906	1	0
+1644	6	0
+1180	0	1
+475	0	5
+2556	26	22
+351	0	1
+1716	71000	36200
+976586	59000	26528
+7701	0	4
+9296	0	1
+1862	1	0
+3316	7	3
+1131	0	1
+1795	1	0
+569	1	0
+2895	44	44
+458	3	0
+5371	1	0
+6774	0	2
+2504	0	2
+1247	1	1
+45	1	1
+2415	17	17
+8215	1	1
+18	1	1
+272	10	10
+420	1	1
+34	1	1
+7961	4	0
+1973	1	1
+45	1	0
+529	1	0
+603	0	1
+18	1	1
+621	4	12
+67	2	0
+18	34	0
+516	0	1
+1400	38	41
+3786	0	1
+228	3	0
+1026	1	1
+49	1	1
+3336	0	3
+951	1	1
+77	2	1
+441	1	2
+1833	9	9
+301	5	5
+2787	17	17
+1747	1	0
+3040	2	9
+81	10	10
+86	2	0
+7354949	20000	1606
+1681	16	30
+13957	0	8
+1947	0	3
+1255	1	1
+38	0	1
+1788	12	17
+1045	6	0
+1327	0	1
+5775	1	1
+18	1	1
+1933	1	0
+1716	13	13
+255	1	0
+124	0	3
+792	0	5
+1521	1	1
+64	1	1
+9005617	150000	150000
+171176	3000000	3000000
+7074452	53320	65431
+1937	0	1
+2845	2	0
+1387	0	1
+114	1	0
+2382	0	4
+68	6	6
+60	4	0
+20	0	1
+93	0	51
+9781584	351994	0
+1909446	184275	0
+3919546	13	13
+435	23	23
+838	0	1
+807	6	6
+74	1	1
+43	1	1
+652	30000	29839
+13847966	0	1
+14069801	2	0
+8504	0	1
+32266	8	0
+12729	0	2
+35327	12	14
+1503	1	0
+1334	1	0
+759	0	1
+7479	34	34
+2523	7	1
+9912	18	17
+2523	1	0
+1321	0	1
+3684	18	18
+5282	2	0
+5505	20	20
+9694	6	6
+22003	9	0
+578	0	1
+5166	2	0
+92208	2	5
+8	1	0
+5	0	2
+113	4	0
+845	6	7
+2247	3	1
+3770	0	1
+5719	0	2
+2511	0	1
+1557	0	1
+5812	0	1
+3607	0	1
+7405	1	0
+11075	0	1
+2794	1	0
+2340	1	0
+429	0	1
+522	2	0
+2397	5	0
+371	11	0
+1376	1	0
+2416	8	0
+210	1	1
+20	1	1
+5104	1	1
+20	1	1
+525	2	0
+836	0	1
+2094	1	0
+2213	3	0
+327	9	6
+2593	1	1
+57	1	1
+1618	0	1
+1400	4	0
+254	0	2
+93	10	0
+754	0	6
+193	0	1
+2378	0	1
+1753	3	0
+1903	0	4
+29	1	1
+1136	14	14
+2452	4	0
+3622	31	3
+456	14	14
+1076	7	8
+68	1	1
+20	1	1
+145	1	1
+68	1	0
+12	0	1
+10	0	1
+11	1	0
+35	1	0
+5	0	1
+11	1	2
+32	6	7
+35	1	0
+8722	1	0
+888	0	4
+456	3	0
+45	0	1
+151	13	13
+756	0	1
+203	8	7
+140	1	1
+20	1	1
+308	5	0
+1020	0	1
+1258	0	1
+160	0	2
+1411	1	1
+22	1	1
+1180	12	12
+4521	0	2
+1155	27	0
+4954	3	0
+1392	1	1
+47	1	1
+3854	2	1
+130	1	0
+2633	2	0
+3053	12	13
+2308	0	1
+1747	0	45
+732	2	0
+1336	9	11
+3898	0	6
+437	1	0
+981	0	1
+1326	0	1
+382	4	0
+1081	10	0
+81	1	1
+142	0	2
+5452	29	29
+495	1	1
+26	1	1
+485	0	1
+525	0	4
+36	0	6
+3945	347	0
+1034	1	1
+27	1	1
+60	2	0
+2581	3	0
+3880	0	4
+1792	0	1
+20	1	1
+356	1	0
+4244	5	5
+36	1	1
+2232	2	2
+42	1	1
+4462	0	2
+1611	1	0
+1290	0	2
+110	1	0
+1466	0	1
+357	3	0
+850	12	0
+13547766	0	1
+3724943	2	0
+46473408	0	1
+1696	1	1
+28	1	1
+1629	0	4
+666	4	0
+13464	30000	12874
+8520008	2	0
+1107	1	1
+15	1	1
+1892	0	4
+6798	0	2
+1793	1	1
+25	0	3
+422	389	0
+786	2	0
+545	0	2
+54	1	0
+143	1	1
+39	1	1
+89	1	1
+29	1	0
+171	1	1
+46	1	0
+192	1	1
+33	1	1
+2580	0	1
+107	1	1
+29	1	1
+218	1	0
+175	6	5
+1407	1	1
+52	1	1
+8851	1	0
+14427	4	0
+1737	22	0
+5806	1	0
+1115	1	1
+29	0	2
+3395	0	1
+3164	0	2
+522	1	0
+24	1	1
+658	4	0
+5724	9	9
+1209	0	1
+5380	1	0
+97	1	0
+854	4	0
+78	5	11
+2728	6	7
+3754	17	13
+1363	1	0
+1025	1	0
+1811	0	1
+7507	0	4
+1184	3	0
+763	1	0
+797	3	0
+293	2	0
+2488	0	1
+335	0	1
+9959	1	0
+3255	1	0
+1322	0	1
+8118	2	0
+2908	49	49
+369	2	0
+632	1	0
+63	0	5
+3008	0	1
+9582	0	1
+14742673	0	3013
+39686
+
+chain	945825	4	191273063	+	69381892	69391896	4	191154276	+	69230000	69240000	2911
+2225	1	0
+4917	1	0
+2807	2	0
+51
+
+chain	941684	4	191273063	+	69471941	69481941	4	191154276	+	69320000	69330000	3076
+3521	0	1
+4784	1	0
+1694
+
+chain	941274	4	191273063	+	69614595	69624595	4	191154276	+	69580000	69590000	3093
+10000
+
+chain	940419	4	191273063	+	69564606	69574607	4	191154276	+	69530000	69540000	3129
+3216	5	5
+134	0	1
+5676	2	0
+968
+
+chain	939146	4	191273063	+	69534617	69544617	4	191154276	+	69500000	69510000	3182
+387	6	6
+9607
+
+chain	939091	4	191273063	+	69481941	69491934	4	191154276	+	69330000	69340000	3184
+8138	0	4
+1546	0	3
+309
+
+chain	938726	4	191273063	+	69461942	69471941	4	191154276	+	69310000	69320000	3193
+130	0	1
+9869
+
+chain	936769	4	191273063	+	69604595	69614595	4	191154276	+	69570000	69580000	3285
+2900	25	25
+7075
+
+chain	936653	4	191273063	+	69421914	69431904	4	191154276	+	69270000	69280000	3293
+6388	14	14
+338	29	29
+266	0	1
+2309	1	3
+55	1	0
+83	0	8
+506
+
+chain	936357	4	191273063	+	69391896	69401898	4	191154276	+	69240000	69250000	3304
+2367	1	0
+2329	0	1
+795	23	23
+2819	2	0
+1666
+
+chain	935200	4	191273063	+	69441943	69451948	4	191154276	+	69290000	69300000	3343
+1203	4	0
+488	57	57
+7133	2	1
+310	1	0
+551	0	1
+256
+
+chain	934799	4	191273063	+	69544617	69554606	4	191154276	+	69510000	69520000	3366
+1296	39	39
+1112	1	0
+204	1	0
+2340	0	12
+1710	0	1
+3286
+
+chain	933839	4	191273063	+	69584607	69594595	4	191154276	+	69550000	69560000	3402
+417	3	0
+966	1	0
+2053	0	1
+1784	5	8
+284	0	12
+4475
+
+chain	932655	4	191273063	+	69594595	69604545	4	191154276	+	69560000	69569950	3440
+8695	26	26
+1229
+
+chain	930772	4	191273063	+	69451948	69461942	4	191154276	+	69300000	69310000	3507
+1068	0	1
+1437	25	27
+806	0	4
+5337	50	50
+300	1	0
+970
+
+chain	928519	4	191273063	+	69411919	69421914	4	191154276	+	69260000	69270000	3571
+62	32	32
+801	11	11
+3595	38	38
+941	54	59
+4461
+
+chain	928371	4	191273063	+	69511937	69521941	4	191154276	+	69360000	69370000	3579
+6433	60	60
+335	10	6
+239	10	10
+2917
+
+chain	925594	4	191273063	+	69554606	69564602	4	191154276	+	69520000	69529997	3671
+2109	0	1
+4421	81	81
+1599	22	22
+1764
+
+chain	922960	4	191273063	+	69501928	69511937	4	191154276	+	69350000	69360000	3756
+714	8	8
+423	18	18
+882	33	33
+952	22	22
+607	1	0
+196	64	64
+495	3	0
+2055	2	0
+548	3	0
+2983
+
+chain	915200	4	191273063	+	69491934	69501928	4	191154276	+	69340000	69350000	3933
+1036	10	10
+2821	5	0
+53	40	40
+209	3	0
+3718	11	0
+421	0	23
+332	11	11
+292	0	2
+432	23	23
+159	20	20
+115	20	20
+263
+
+chain	911203	4	191273063	+	69431904	69441943	4	191154276	+	69280000	69290000	4026
+364	6	5
+212	4	0
+2445	40	15
+377	30	30
+1126	60	60
+262	8	6
+3222	145	138
+1738
+
+chain	903419	4	191273063	+	69401898	69411919	4	191154276	+	69250000	69260000	4208
+1051	52	52
+1007	0	1
+319	27	26
+154	98	97
+145	40	40
+512	23	0
+355	5	5
+126	19	19
+128	49	49
+67	0	1
+3337	0	2
+1729	5	5
+773
+
+chain	895926	4	191273063	+	69574644	69584607	4	191154276	+	69540037	69550000	4357
+3368	220	220
+1524	84	84
+1558	19	19
+889	41	41
+1592	43	43
+625
+
+chain	866339	4	191273063	+	69524748	69534617	4	191154276	+	69490119	69500000	4930
+190	50	50
+59	111	111
+51	7	7
+78	59	59
+58	121	121
+57	39	39
+70	0	1
+1558	108	108
+737	24	24
+3582	0	1
+84	0	10
+2826
+
+chain	659008	4	191273063	+	71711854	71718864	4	191154276	+	71492990	71500000	7936
+7010
+
+chain	608986	4	191273063	+	69375441	69381892	4	191154276	+	69223549	69230000	8701
+135	1	0
+2166	0	1
+4149
+
+chain	248590	4	191273063	+	69521941	69527313	4	191154276	+	69370000	69375377	111030
+2807	190	190
+50	59	59
+111	136	136
+59	58	58
+121	57	57
+39	1628	1633
+57
+
+chain	214386	4	191273063	+	71534589	71536854	4	191154276	+	71500000	71502265	534073
+2265
+
+chain	96900	4	191273063	+	3963456	3964475	4	191154276	+	3912520	3913539	1319679
+1019
+
+chain	52181	4	191273063	+	69624595	69625143	4	191154276	+	69590000	69590548	2441389
+548
+
+chain	20814	4	191273063	+	1495708	1495926	4	191154276	+	1526075	1526293	9826122
+218
+
+chain	8858	4	191273063	+	1496845	1496937	4	191154276	+	1526189	1526281	25171661
+92
+
+chain	8858	4	191273063	+	1496752	1496844	4	191154276	+	1526189	1526281	25171662
+92
+
+chain	8858	4	191273063	+	1496566	1496658	4	191154276	+	1526189	1526281	25171663
+92
+
+chain	7802	4	191273063	+	1492030	1492276	4	191154276	+	1522531	1522736	2805154
+25	83	42
+23	15	15
+4	55	55
+41
+
+chain	7606	4	191273063	+	69578098	69578232	12	133851895	+	88986938	88987072	9526361
+134
+
+chain	7510	4	191273063	+	1496208	1496286	4	191154276	+	1526203	1526281	25171660
+78
+
+chain	7439	4	191273063	+	1527942	1528019	4	191154276	+	1557568	1557645	18158883
+77
+
+chain	7376	4	191273063	+	1496452	1496529	4	191154276	+	1526075	1526152	27495831
+77
+
+chain	6986	4	191273063	+	59479326	59479400	7	159138663	+	119297971	119298045	28268313
+74
+
+chain	6131	4	191273063	+	1496080	1496144	4	191154276	+	1526075	1526139	27495827
+64
+
+chain	5599	4	191273063	+	1495650	1495708	4	191154276	+	1526203	1526261	27226300
+58
+
+chain	5460	4	191273063	+	1496658	1496715	4	191154276	+	1526095	1526152	27495830
+57
+
+chain	4356	4	191273063	+	1498960	1499009	4	191154276	+	1528103	1528152	18458745
+49
+
+chain	4121	4	191273063	+	69578012	69578069	3	198022430	-	95182224	95182281	17792812
+57
+
+chain	3000	4	191273063	+	1495929	1496022	4	191154276	+	1526110	1526203	11256589
+93
+
+chain	2961	4	191273063	+	69443663	69443695	4	191154276	-	68628109	68628141	14494983
+32
+
+chain	2485	4	191273063	+	1503833	1503862	4	191154276	+	1532970	1532999	23156792
+29
+
+chain	2401	4	191273063	+	1492301	1492331	4	191154276	+	1522679	1522709	5335388
+30
+
+chain	2012	4	191273063	+	1496731	1496752	4	191154276	+	1526075	1526096	27495829
+21
+
+chain	1744	4	191273063	+	1597414	1597448	4	191154276	+	1627062	1627096	3575887
+34
+
+chain	1461	4	191273063	+	69579763	69579840	5	180915260	+	121968423	121968500	3935628
+77
+
+chain	1332	4	191273063	+	69545913	69545943	11	135006516	-	130984886	130984916	21069914
+30
+
+chain	909	4	191273063	+	69582306	69582346	3	198022430	-	10790236	10790276	7796945
+40
+
+chain	18169122	4_random	842648	+	440032	631501	GL000194.1	191469	+	0	191469	150
+191469
+
+chain	18001815	4_random	842648	+	0	189789	GL000193.1	189789	+	0	189789	151
+189789
+
+chain	15268007	4_random	842648	+	681501	842648	GL000218.1	161147	+	0	161147	194
+161147
+
+chain	9245037	4_random	842648	+	239789	336038	4	191154276	+	8829368	8925617	353
+96249
+
+chain	137712	4_random	842648	+	388580	390032	4	191154276	+	9620000	9621452	935614
+1452
+
+chain	10386	4_random	842648	+	388312	388420	11	135006516	-	91778086	91778194	21974850
+108
+
+chain	3377	4_random	842648	+	388277	388312	11	135006516	-	84847900	84847935	23649965
+35
+
+chain	2456	4_random	842648	+	388184	388235	X	155270560	-	93144339	93144390	24160146
+51
+
+chain	16791974256	5	180857866	+	63000	180837866	5	180915260	+	10000	180905260	5
+17520657	24032	50000
+1688	3435	1
+37	1399	0
+27	2	1
+8	1	1
+3983	3434	0
+103	1	1
+32	1	1
+67	1	1
+35	1	1
+752	1669	0
+43	1	1
+1207	0	1
+46	0	1
+5	0	1
+19	1	1
+70	3434	0
+962	16	16
+1905	44	44
+85	41	41
+332	49	49
+1675	23	23
+1185	11	11
+124	35	35
+713	105	105
+408	4	4
+113	16	16
+1835	1	2
+26	7	8
+18	2730	25
+3103	1	0
+7858	718	10488
+307	1	636
+7461	0	1
+23772	51	0
+4031	0	1
+20571	0	1
+9135	0	2
+6885	2	3
+110	3	0
+816	2	3
+2295	0	34
+3936	28	28
+3536	0	2
+2917	0	1
+652	1	1
+37	1	1
+657	1	1
+22	1	1
+419	3	4
+3580	1	1
+29	1	1
+274	11	35
+835	3036	0
+1907	1	0
+10504	30	28
+784	0	6
+127	10	0
+668	1	1
+28	1	1
+2467	4	0
+179	0	2
+1650	1	1
+39	1	1
+2433	1	0
+720	1	1
+40	1	1
+772	1	1
+32	1	1
+353	1	1
+17	1	1
+1776	0	1
+6082	3	0
+2669	12	10
+2857	1	1
+35	1	1
+722	60	60
+200	1	1
+240	1	1
+4048	1	1
+49	1	1
+702	1	1
+33	1	1
+2927	1	2
+1487	17	0
+276	16	16
+1039	1	1
+35	1	1
+2068	1	1
+40	1	1
+828	1	1
+36	2	0
+317	8	0
+893	1	1
+33	1	0
+8143	0	4
+28632199	3000000	3000000
+12470071	0	1
+29760415	40000	50000
+5878002	23000	20845
+4521	1	0
+676	6	6
+5928	0	1
+372	1	1
+47	1	1
+6801	3	2
+639	0	1
+871	3	4
+11530	0	4
+22966	0	1
+15447	0	1
+53856	0	2
+15988	0	2
+906887	10	11
+40152817	5000	52715
+3521239	0	1
+1604	10	0
+12778810	4100	51715
+15152692	27	0
+1852096	1	0
+8710030
+
+chain	924655	5	180857866	+	17585088	17611949	5	180915260	-	163333152	163394435	1227
+14	409	52001
+494	3435	1
+24	1	1
+1487	10	10
+682	13	13
+132	3449	15
+306	1	1
+74	1	1
+967	3434	0
+1285	3434	0
+68	4569	1135
+2087	50	50
+435
+
+chain	315813	5	180857866	+	17584685	17618655	5	180915260	+	17581691	17599590	1580
+403	14	14
+237	1475	75
+628	25	25
+51	89	89
+304	24	24
+70	33	33
+37	698	698
+667	3506	72
+1354	96	96
+75	4	4
+752	1710	41
+450	382	382
+51	14129	7264
+237	12	12
+614	37	37
+134	16	16
+422	31	31
+796	4345	1642
+62
+
+chain	312488	5	180857866	+	17597387	17639380	5	180915260	+	17580657	17599710	1454
+373	70	70
+1245	2263	863
+1184	3434	0
+1733	3775	2106
+50	9111	2246
+1078	993	993
+1363	8015	1147
+44	85	85
+41	332	332
+49	6299	3596
+341	45	44
+70
+
+chain	265075	5	180857866	+	17745718	17748537	5	180915260	+	17713035	17715853	333767
+1906	1	0
+912
+
+chain	207388	5	180857866	+	17584033	17596937	5	180915260	+	17583073	17597745	2201
+51	557	557
+14	17	17
+13	654	654
+172	494	494
+219	23	23
+567	4975	6743
+176	6	6
+865	14	14
+96	1354	1354
+26	2261	2261
+350
+
+chain	193008	5	180857866	+	17583668	17629078	5	180915260	+	17580674	17599710	1465
+356	84	84
+533	3434	0
+698	5562	728
+51	4689	1255
+946	4787	1353
+543	8	8
+167	12743	7643
+324	5466	2032
+306	3553	850
+1045	45	44
+70
+
+chain	130263	5	180857866	+	17639380	17641654	5	180915260	+	17592112	17594386	19200
+936	23	23
+116	16	16
+1183
+
+chain	123401	5	180857866	+	17602522	17620625	5	180915260	+	17589594	17593961	2306
+159	16	16
+1763	19	19
+54	14448	712
+1644
+
+chain	53192	5	180857866	+	17626966	17629142	5	180915260	+	17590000	17592176	2614
+952	1045	1045
+45	70	70
+64
+
+chain	42492	5	180857866	+	17625757	17626966	5	180915260	-	163394507	163395716	9006
+1209
+
+chain	23743	5	180857866	+	17605548	17605956	5	180915260	+	17596054	17596462	38000
+290	9	9
+109
+
+chain	20601	5	180857866	+	17748538	17748754	5	180915260	+	17712817	17713033	9842237
+216
+
+chain	11635	5	180857866	+	17618762	17618981	5	180915260	+	17595532	17595751	149283
+219
+
+chain	9108	5	180857866	+	17618655	17618762	5	180915260	+	17583355	17583462	1340460
+107
+
+chain	7916	5	180857866	+	17587442	17604673	5	180915260	-	163387098	163397461	2244
+25	61	61
+79	398	398
+33	16608	9740
+27
+
+chain	7204	5	180857866	+	17604533	17604646	5	180915260	+	17599204	17599317	3499
+113
+
+chain	4292	5	180857866	+	17639265	17639310	5	180915260	+	17595431	17595476	67944
+45
+
+chain	2558	5	180857866	+	17604673	17604706	5	180915260	+	17591745	17591778	3790746
+33
+
+chain	2511	5	180857866	+	170275712	170275739	5	180915260	+	170343161	170343188	11152528
+27
+
+chain	2447	5	180857866	+	17635643	17636496	5	180915260	-	163394091	163394944	8841
+35	713	713
+105
+
+chain	2252	5	180857866	+	17601306	17601338	5	180915260	+	17595246	17595278	11344
+32
+
+chain	2027	5	180857866	+	17785693	17785748	18	78077248	-	45596607	45596662	524022
+55
+
+chain	1518	5	180857866	+	17629142	17629191	5	180915260	-	163394458	163394507	205933
+49
+
+chain	1109	5	180857866	+	17613421	17613452	5	180915260	-	163395907	163395938	8647
+31
+
+chain	143977943	5_h2_hap1	1794870	+	0	1794870	5	180915260	+	68505249	71134051	52
+5440	1	0
+1785	0	1
+12373	0	2
+7216	0	1
+714	2	0
+4360	0	1
+11179	1	0
+2027	1	0
+6969	0	2
+3779	1	0
+634	4	3
+1384	0	9
+378	0	2
+1153	3	0
+1246	0	6
+1427	0	2
+608	1	1
+23	1	1
+1981	44	44
+3998	1	1
+33	5	0
+148	1	1
+18	1	0
+331	2	0
+162	1	0
+333	0	1
+644	1	0
+2053	1	0
+1896	0	1
+2096	1	1
+32	1	1
+265	0	14
+1061	0	1
+7303	6	6
+1313	1	0
+3225	0	2
+65	1	1
+220	1	1
+1422	0	1
+248	1	1
+21	2	0
+641	0	1
+163	3	0
+522	1	0
+1685	0	1
+299	1	1
+16	1	0
+3259	1	0
+6492	9	9
+700	0	2
+379	1	0
+186	0	16
+21	0	27
+242	21	19
+156	0	3
+2040	1	0
+7852	0	2
+1267	0	4
+8016	0	1
+2057	85	0
+449	0	1
+2797	0	1
+3858	0	1
+2129	1	0
+234	1	1
+28	1	1
+2923	0	3
+4346	1	0
+2467	1	0
+11093	1	0
+3932	0	3
+2223	1	1
+22	0	1
+25	0	6
+1909	2	0
+1136	1	0
+658	2	0
+32	8	0
+9	2	0
+14	15	11
+22	14	0
+20	51	1
+34	2	0
+43	0	2
+38	127	19
+15	14	0
+41	0	5
+9200	1	0
+2655	1	0
+38	1	1
+237	1	1
+28	1	1
+1065	1	0
+2979	3	0
+13	1	1
+653	4	0
+1950	1	0
+2320	2	0
+817	3	0
+524	8	0
+417	1	0
+873	1	0
+352	1	0
+152	2	0
+651	1	0
+285	1	0
+1830	0	1
+1271	0	1
+957	0	1
+1506	2	0
+2454	4	0
+6	4	0
+300	1	1
+68	1	1
+1648	0	1
+10725	10	10
+1308	2	1
+48	1	1
+1242	15	0
+1869	1	0
+26	0	452
+1178	0	3
+43	0	4
+3567	0	1
+2289	0	1
+695	0	6
+721	13	14
+192	0	2
+1190	1	1
+36	1	1
+451	0	1
+4137	1	0
+809	23	0
+1624	0	4
+453	4	0
+983	0	1
+188	0	5
+489	0	1
+299	11	11
+1923	1	0
+168	0	1
+891	1	1
+54	0	1
+908	0	28
+1224	2	0
+175	0	1
+459	2	0
+119	133	153
+50	13	13
+4001	0	1
+4764	3	0
+90	1	1
+117	92	0
+325	0	27
+19	1	1
+92	1	67
+21	1	28
+15	1	28
+9013	0	1
+1376	0	1
+674	10	0
+87	0	1
+1317	43	35
+260	1	0
+1518	11	12
+232	0	1
+1093	0	1
+737	0	2
+176	10	10
+664	1	1
+33	1	1
+2816	3	0
+4679	0	2
+3212	0	2
+2383	14	16
+3049	0	1
+146	1	0
+721	1	1
+35	1	1
+2260	2	0
+1228	0	1
+682	1	0
+8927	1	0
+795	2	0
+5278	0	2
+5578	13	0
+3665	20	0
+1852	9	0
+4564	1	1
+20	4	0
+111	1	1
+1065	37	37
+2979	1	0
+820	0	1
+9147	0	1
+411	0	1
+745	2	0
+144	3	3
+27	2	0
+734	1	1
+38	1	1
+105	0	4
+554	1	0
+35	1	1
+226	2	0
+254	1	1
+39	1	1
+3302	0	2
+16	1	1
+1276	1	1
+57	1	1
+122	5	0
+178	0	1
+29	1	1
+89	1	1
+32	1	1
+1743	1	0
+294	1	1
+27	1	1
+1925	1	1
+48	1	1
+116	1	1
+20	1	1
+163	4	4
+821	4	3
+46	1	1
+247	1	1
+27	2	2
+613	1	1
+44	1	1
+181	9	7
+1220	1	1
+53	0	3
+596	1	0
+1052	12	12
+130	1	0
+1524	0	1
+1878	1	4
+76	0	1
+6	0	5
+895	0	1
+290	9	5
+783	1	1
+45	1	1
+1910	1	1
+48	1	1
+409	1	1
+30	1	1
+158	2	0
+69	6	0
+428	1	1
+136	1	1
+418	44	44
+767	35	27
+711	1	1
+28	1	1
+1137	1	0
+585	1	0
+433	13	0
+3034	1	0
+961	0	3
+950	1	1
+15	1	1
+948	0	5
+153	21	20
+181	38	38
+765	8	10
+207	13	15
+3092	4	0
+202	5	5
+1406	0	5
+205	1	1
+44	1	1
+2719	1	1
+36	1	1
+1050	0	9
+108	0	2
+1177	4	0
+115	1	1
+2051	15	0
+520	8	8
+1072	0	1
+595	2	0
+4576	73	73
+6176	1	0
+1299	1	1
+29	1	0
+496	0	4
+379	2024	0
+7	3663	0
+82	4	0
+79	6	1
+556	11	0
+598	9	9
+138	77	73
+1651	3	9
+3302	0	8
+429	1	0
+163	0	3
+60	3	0
+132	1	1
+23	1	0
+1660	1	16
+2124	0	1
+1601	9	0
+35	525	6
+38	1	1
+235	1	30
+497	1	1
+37	1	0
+79	0	1
+1239	1	1
+31	1	1
+135	1	0
+5	2	0
+669	0	1
+1158	1595	0
+21	3	0
+5	126998	500121
+730	31	27
+278	0	2
+352	0	12
+363	13	21
+366	1	0
+378	3	0
+61	1	0
+105	17	68
+1480	32	32
+640	1	1
+52	1	1
+482	1	0
+638	1	1
+20	1	0
+21	1	1
+326	1	1
+37	1	1
+995	0	7
+1685	0	1
+1607	9	8
+633	1	1
+37	1	1
+697	6	6
+1363	8	8
+234	1	1
+44	1	1
+3022	5	6
+96	12	11
+674	4	0
+768	0	1
+169	3	0
+2083	0	1
+1098	20	20
+5586	1	0
+174	28	13
+366	2	0
+202	1	1
+69	1	1
+682	5	5
+3457	1	0
+232	1	0
+305	10	0
+1770	40	40
+349	38	38
+401	0	1
+441	7	3
+547	11	10
+210	4	0
+779	4	0
+193	4	0
+576	0	4
+514	48	48
+789	23	16
+2496	25	25
+874	25	11
+2776	19	19
+2824	4	0
+440	0	2
+876	14	14
+1198	39	39
+521	6	0
+126	40	40
+315	29	29
+616	94	99
+285	35	35
+175	12	12
+320	17	1
+3339	0	1
+260	49	49
+109	11	11
+586	0	1
+133	19	13
+8202	0	1
+307	0	1
+1366	1	0
+1073	9	12
+1385	0	1
+321	106	108
+1101	28	28
+483	42	42
+1752	58	58
+166	37	36
+748	16	16
+52	1	0
+1679	0	2
+455	9	17
+484	1	10
+74	33	33
+155	0	1
+62	0	8
+424	23	23
+491	8	9
+450	0	2
+63	1	0
+410	5	0
+1131	165	170
+254	39	39
+1162	0	272664
+1919	1	1
+82	1	1
+740	4	4
+261	1	1
+83	1	1
+52	1	1
+49	1	1
+231	6	6
+244	1	1
+21	1	1
+52	44	44
+114	20	20
+87	32	32
+149	0	6
+202	50	50
+115	44	44
+114	65	65
+50	111	111
+61	52	52
+101	42	45
+250	15	15
+208	1	0
+2259	3	0
+239	64	66
+168	10	10
+2393	1	1
+38	1	1
+674	1	1
+29	1	1
+469	22	25
+827	1	0
+1679	0	1
+463	9	13
+232	1	0
+248	1	5
+325	0	7
+1389	0	4
+63	1	0
+410	6	0
+685	3	0
+35	1	1
+407	166	168
+253	39	39
+71	0	4
+1288	35	35
+1697	32	32
+243	22	22
+395	51	51
+259	49	49
+108	6	6
+54	168	168
+464	45	45
+81	20	20
+84	21	21
+240	25	25
+584	0	810
+126	4	4
+42	6	6
+101	0	3
+41	1	1
+473	1	0
+373	1	1
+41	1	1
+614	1	1
+41	1	18042
+857	50	50
+279	2	0
+246	67	69
+160	10	10
+199	0	1
+154	1	0
+276	28	28
+124	29	28
+105	7	7
+355	1	1
+45	1	1
+299	1	1
+25	1	1
+283	30	35
+594	2	0
+1401	1	1
+46	1	1
+123	4	0
+830	1	0
+100	1	1
+61	1	1
+737	2	7
+285	1	1
+58	1	1
+143	18	0
+19	1	1
+575	1	1
+91	1	1
+318	2	0
+4090	4	0
+702	0	1
+2007	0	2
+901	0	1
+79	9	9
+31	3	3
+1203	1	0
+16	1	1
+574	1	1
+28	1	1
+346	6	0
+25	1	3
+22	2	0
+34	4	0
+7	1	0
+20	18	22
+511	0	5
+5088	0	1
+1065	0	4
+51	2	0
+2714	25	25
+81	8	8
+56	788	18
+22	1	1
+4702	0	1
+536	6	6
+3900	1	0
+1063	0	8
+4095	1	0
+1841	1	3
+1015	0	1
+2808	1	1
+17	1	1
+340	1	1
+39	1	1
+1548	1	1
+73	1	1
+291	1	0
+236	72	43
+104	0	1
+1843	4	0
+80	15	15
+1140	29	1
+45	1	1
+1245	3	0
+194	1	0
+816	11	1
+25	1	11
+47	1	1
+508	0	1
+255	1	1
+24	1	0
+319	13	13
+1846	397	398
+803	0	37
+509	0	12
+130	0	4
+609	0	3
+6495	1251	1253
+1091	11	11
+384	2	0
+1657	31	30
+109	31	31
+2815	63	63
+85	0	13
+589	48	48
+194	25	25
+1068	16	16
+209	2	0
+215	47	47
+1775	127	77
+533	188	0
+1164	1	0
+1863	1	1
+29	1	1
+1993	1	1
+19	1	1
+782	2	0
+3224	2	0
+22	1	11
+473	332	0
+604	1	1
+28	1	1
+223	1	1
+28	1	1
+2870	0	1
+38	1	1
+313	1	0
+768	0	1
+1039	9	9
+886	0	4
+243	0	1
+172	17	17
+2721	1	1
+71	0	1
+607	105	117
+54	46	44
+2057	1	1
+32	1	1
+452	1	1
+49	1	1
+169	322	6
+26	1	0
+567	3	0
+2324	1	0
+825	4	0
+1251	4	4
+2651	0	4
+703	14	19
+10731	13	0
+741	2	0
+1659	0	12
+7683	0	6
+838	1	0
+2905	12	326
+1714	1	0
+1172	90	100
+619	2	0
+263	0	59
+730	1	0
+56	4	0
+1746	17	17
+377	1	1
+27	4	0
+836	1	1
+67	1	1
+1022	0	1
+1096	1	1
+40	0	1
+8	1	1
+1864	1	0
+56	5	1
+6	0	10
+114	1	1
+34	1	1
+631	19	19
+139	13	13
+1330	1	11
+22	2	0
+2846	1	0
+358	0	2
+798	11	11
+3004	1	1
+30	1	1
+2032	1	16
+752	16	0
+40	0	6
+3211	0	1
+965	0	14
+2978	1	1
+29	1	1
+138	0	2
+1646	2	0
+375	1	1
+31	1	1
+6235	0	2
+2598	0	3
+592	0	4
+135	0	12
+3892	1	0
+840	0	12
+5528	9	5
+5400	0	1
+181	0	1
+836	0	3
+3087	1	1
+46	1	1
+2796	11	9
+6282	1	1
+25	1	1
+2009	1	1
+56	0	2
+209	15	15
+2433	1	1
+50	1	1
+366	1	0
+3233	0	1
+5144	0	2
+811	53	22
+23	1	0
+6	1	3
+43	0	2
+13	2	0
+5	0	14
+634	8	8
+1663	10	12
+433	1	1
+43	1	1
+397	2	0
+638	1	1
+42	1	1
+285	1	1
+28	1	1
+516	1288	2
+424	4	0
+660	1	1
+49	1	1
+816	0	12
+1015	1	1
+47	1	1
+988	0	3
+1000	14	32
+330	1	1
+38	1	1
+124	7	2
+43	1	1
+693	1	1
+61	1	1
+94	0	1
+963	1	1
+46	1	1
+1393	0	2
+139	2	0
+113	1	1
+20	1	1
+323	6	0
+34	0	1
+978	1	1
+38	1	1
+105	1	1
+18	1	2
+43	1	1
+381	0	1
+811	15	8
+2537	0	2436
+2642	1	1
+42	4	0
+92	10	10
+1363	1	1
+37	1	1
+252	5	0
+165	1	1
+329	1	1
+77	1	1
+705	0	6
+258	6	6
+155	0	1
+57	2	0
+1380	5	0
+348	2	0
+489	9	5
+448	1	0
+1681	0	1
+835	29	25
+1359	36	36
+223	0	1
+399	15	15
+466	4	4
+75	10559	200741
+1150	1	0
+682	12	15
+802	53	53
+535	1	0
+65	62	63
+497	30	1
+1458	1	0
+683	0	1
+1449	1	0
+977	15	0
+1636	0	4
+216	3	0
+587	0	10
+4302	1	1
+28	1	1
+733	0	4
+138	9	9
+595	0	11
+249	1	1
+65	1	1
+242	1	6
+74	0	4
+87	6	5694
+363	4	0
+513	0	1
+29	1	1
+1297	0	1
+415	1	3
+1947	0	2
+978	0	1
+3121	1	1
+17	1	1
+872	1	1
+31	1	1
+602	8	8
+238	1	1
+36	1	1
+930	1	1
+36	1	1
+1073	22	0
+494	0	1
+66	1	5
+60	1	1
+15	1	1
+452	1	0
+1587	0	7
+1465	1	1
+27	1	1
+76	1	1
+44	1	1
+143	16	14
+323	23	23
+685	1	1
+15	1	1
+136	6	0
+400	0	2
+109	3	0
+50	1	1
+18	1	1
+985	1	1
+38	1	1
+1034	12	12
+247	1	1
+91	2	1
+1383	1	1
+44	1	1
+164	15	16
+292	1	1
+47	1	1
+73	1	1
+43	1	1
+203	1	0
+420	1	1
+37	1	1
+449	0	2
+25	0	4
+415	4	6
+155	1	1
+26	1	1
+199	1	1
+41	0	32
+20	1	1
+68	1	1
+28	1	1
+2097	13	15
+207	8	10
+984	21	20
+134	5	0
+967	10	10
+956	3	0
+4424	5	6
+595	0	1
+1140	1	1
+28	1	1
+733	7	16
+1218	149	149
+429	0	4
+59	0	2
+2568	1	1
+45	1	1
+784	5	8
+289	1	0
+877	5	0
+34	1	0
+68	4	1
+735	1	1
+35	1	1
+1094	4	4
+1519	5	6
+138	12	12
+1044	0	1
+91	80	80
+369	1	1
+53	2	0
+63	1	1
+1220	7	9
+181	1	1
+44	1	1
+134	0	3
+476	2	2
+27	1	1
+205	1	1
+88	2	2
+822	4	4
+163	22	22
+116	1	1
+48	1	1
+3849	1	1
+21	1	1
+120	1	1
+32	1	1
+89	1	1
+29	1	0
+178	3	6
+1452	19	17
+5455	1	0
+10333	1	0
+784	0	1
+55	8	0
+468	0	1
+539	12	0
+98	1	1
+24	1	1
+77	1	1
+81	1	1
+4604	17	19
+7803	7	7
+807	0	1
+2260	7	5
+980	0	1
+2105	0	1
+4083	0	1
+836	0	2
+5612	1	0
+519	0	1
+1334	0	1
+2401	0	9
+1823	1	0
+159	0	2
+484	2	0
+14815	1	1
+36	1	1
+2512	4	0
+58	3	0
+3277	1	0
+559	0	1
+4024	1	0
+4383	22	13
+4131	1	1
+35	1	1
+290	1	1
+29	3	0
+533	1	0
+305	0	1
+2608	0	1
+443	3	1
+2322	0	20
+514	1	1
+46	1	1
+791	19	30
+3206	3	0
+6272	0	2
+1789	8	0
+291	39	39
+521	6	0
+126	40	40
+315	29	29
+616	94	99
+206	114	109
+506	0	14
+2370	0	2
+4709	1	1
+36	1	1
+5588	0	11
+299	1	0
+1366	1	0
+1644	1	1
+28	1	0
+4859	16	21
+1992	0	10
+505	0	1
+448	8	12
+721	40973	60417
+3484	1	1
+40	1	1
+2152	0	2
+5298	39	40
+141	25	25
+427	0	11
+1543	1	0
+3707	0	1
+1056	292	8656
+1768	2	0
+717	1	0
+14041	0	1
+4167	0	2
+7403	5	0
+7673	0	1
+3630	67	67
+74	129	129
+226	1	0
+1720	138	136
+1185	1	0
+878	46874	0
+862	1	1
+31	1	1
+9409	1	1
+37	1	1
+2231	0	2
+1682	0	1
+13767	0	1
+9473	0	1
+7168	2	0
+12384	1	0
+1188	0	4
+2044	1	0
+3076	1	0
+796	0	1
+5477	0	2
+5780	1	0
+6338	1	0
+2680	0	4
+2033	0	1
+9452	0	12
+402983
+
+chain	13752336	5_h2_hap1	1794870	+	324513	1282806	5	180915260	-	110525721	111977366	61
+37	39926	39909
+44	767	767
+34	9178	9179
+38	20004	20004
+27	1	1
+44	8383	8384
+1071	3	3
+511	0	1
+439	7	7
+3663	1483	1482
+77	11199	11214
+525	4132	4132
+704	1	0
+729	3	0
+158	29	29
+653	0	3
+154	0	2
+7041	8	0
+2068	0	7
+166	1	0
+812	6	7
+25	1	1
+1423	0	8
+438	0	1
+4783	0	1
+31	1	1
+1269	1	0
+926	3	0
+2542	2	0
+112	1	1
+2183	1	1
+59	1	1
+1605	2	2
+4515	0	1
+4368	1	0
+382	0	34
+60	1	1
+86	0	1
+552	6	6
+892	1	1
+33	1	1
+6705	0	1
+934	0	2
+8985	2	1
+445	6	0
+6283	0	1
+456	0	1
+1101	0	5
+696	0	1
+2973	6	0
+158	0	3
+449	0	3
+657	12	12
+151	0	1
+406	1	1
+55	1	1
+163	1	1
+72	1	1
+1955	1	0
+713	0	1
+3050	1	1
+35	1	1
+3127	1	0
+233	1	0
+1343	17	7
+1250	3	0
+322	1	0
+2081	0	1
+2413	5	0
+818	0	1
+18	1	1
+268	0	1
+271	1	1
+35	1	0
+586	2	0
+1192	0	1
+494	2	0
+4657	1	1
+30	5	0
+2172	0	334
+1981	5	0
+33	321	0
+2633	2	0
+142	1	0
+1597	7	0
+248	1	0
+317	1	1
+21	1	1
+441	0	1
+600	6	4
+35	1	1
+1593	2	6
+9303	1	0
+2781	0	2
+6052	0	4
+771	1	0
+1500	14	0
+1544	730	730
+31	3419	3419
+30	30394	30395
+40	349	349
+38	3691	3690
+48	3308	3306
+25	874	880
+25	8151	8151
+39	653	653
+40	315	315
+29	616	616
+94	285	285
+35	4123	4120
+49	13570	13573
+58	30899	10440
+165	1652	1655
+35	1697	1697
+32	660	660
+51	259	259
+49	168	168
+168	464	464
+45	446	446
+25	3886	3879
+67	800	800
+28	124	124
+29	1123	1123
+30	24987	23723
+2	1	1
+21	146	146
+2	1	1
+785	22543	22552
+67	3192	3170
+28	5357	5348
+397	8546	8565
+1251	3145	3145
+31	110	110
+29	2816	2816
+63	674	688
+48	195	195
+23	1511	1509
+47	1810	1786
+37	14	0
+41	533	533
+182	1	16
+5	20555	20281
+49	1	21
+55	54	52
+46	2763	2762
+37	5	2
+280	124045	123118
+495	0	1
+703	3	0
+87	27183	48462
+36	1182	1182
+389	16	16
+257	1	0
+118	3	3
+547	1	1
+25	1	1
+126	0	2
+3598	810	0
+148	0	6
+483	1	1
+34	1	1
+266	6	6
+350	2	2
+30	1	1
+297	4	4
+666	1	1
+89	1	1
+52	15	15
+2220	2647	2651
+53	53651	53634
+149	9850	9843
+39	1	1
+39	116984	481498
+39	653	653
+40	315	315
+29	616	616
+94	206	206
+114	65101	68610
+358	27	27
+588	11156	11155
+25	56460	137674
+105	1	0
+2251	13	13
+319	25	26
+826	25	25
+370	7	7
+439	0	1
+192	7	1
+250	0	13
+1302	1	8
+866	91	94
+91	14	14
+501	1	0
+1238	1	0
+113	475	60006
+212	8	10
+907	0	4
+350	1	0
+486	9	17
+448	0	2
+515	0	10
+788	13213	230
+199	16	16
+645	0	2
+112	37	25
+634
+
+chain	283844	5_h2_hap1	1794870	+	1261701	1280951	5	180915260	+	69698102	69815360	1487
+91	6326	96869
+318	0	10
+505	0	1
+204	64	64
+440	1	0
+235	0	1
+1269	0	1
+945	1	0
+670	242	551
+75	3	0
+1233	50	50
+199	4900	12045
+409	59	59
+310	37	40
+664
+
+chain	206667	5_h2_hap1	1794870	+	1287039	1295912	17	81195210	+	76583705	76597262	568754
+558	4	0
+365	2	2
+40	0	1
+253	1	1
+31	1	1
+522	6316	11003
+780
+
+chain	184822	5_h2_hap1	1794870	+	1284679	1286632	17	81195210	-	4506444	4508397	671275
+1953
+
+chain	128717	5_h2_hap1	1794870	+	1283006	1284382	5	180915260	+	70517839	70519212	1000883
+791	20	17
+565
+
+chain	128621	5_h2_hap1	1794870	+	1291852	1293214	17	81195210	+	76573863	76575225	1001637
+1362
+
+chain	122147	5_h2_hap1	1794870	+	627399	939358	5	180915260	-	110828619	111993762	93
+42	1752	1753
+58	6978	6974
+165	255	254
+37	4915	4915
+44	4384	4378
+64	19819	875253
+39	1	1
+9	264030	261784
+58	0	6
+56	6	6
+105	3	3
+98	1	1
+483	7968	7968
+62	497	497
+30
+
+chain	118081	5_h2_hap1	1794870	+	1290357	1291631	4	191154276	-	20442500	20443774	1089300
+230	18	18
+1026
+
+chain	112391	5_h2_hap1	1794870	+	1288972	1290160	17	81195210	-	4580707	4581894	1143267
+1134	1	0
+53
+
+chain	92982	5_h2_hap1	1794870	+	1293593	1294614	4	191154276	+	170627590	170628611	1373141
+72	1	1
+129	1	1
+818
+
+chain	75482	5_h2_hap1	1794870	+	1274745	1276419	5	180915260	-	111410923	111412615	820
+271	0	10
+350	0	6
+499	9	9
+444	0	2
+101
+
+chain	68300	5_h2_hap1	1794870	+	1276804	1279228	5	180915260	-	110416917	110419341	216
+2424
+
+chain	29652	5_h2_hap1	1794870	+	524804	525112	3	198022430	+	8519605	8519913	4781887
+308
+
+chain	29428	5_h2_hap1	1794870	+	756919	757240	2	243199373	+	16251117	16251431	4913030
+177	7	0
+137
+
+chain	27649	5_h2_hap1	1794870	+	641866	1186473	5	180915260	+	68929706	69564604	89
+32	351	351
+50	115	115
+44	114	114
+65	50	50
+111	61	61
+52	101	101
+42	14056	14883
+33	529303	618767
+27
+
+chain	20581	5_h2_hap1	1794870	+	1249367	1254462	5	180915260	-	111122604	111127700	1762
+2153	24	24
+85	8	8
+1086	0	1
+1739
+
+chain	5516	5_h2_hap1	1794870	+	253548	253608	5	180915260	+	68759177	68759237	7759123
+60
+
+chain	5218	5_h2_hap1	1794870	+	1244675	1244945	5	180915260	-	159621198	159621468	493
+30	1	1
+36	122	122
+81
+
+chain	4702	5_h2_hap1	1794870	+	1279881	1280287	5	180915260	+	70518261	70518663	9283
+59	311	307
+36
+
+chain	4436	5_h2_hap1	1794870	+	1274323	1274373	5	180915260	+	70526833	70526883	9273
+50
+
+chain	4277	5_h2_hap1	1794870	+	625682	625728	5	180915260	-	111701952	111701998	814
+46
+
+chain	3978	5_h2_hap1	1794870	+	1276419	1276466	5	180915260	+	70082181	70082228	137301
+47
+
+chain	3805	5_h2_hap1	1794870	+	1244816	1244863	5	180915260	+	69926901	69926948	475
+47
+
+chain	2924	5_h2_hap1	1794870	+	253608	253640	5	180915260	+	68759034	68759066	4803455
+32
+
+chain	943	5_h2_hap1	1794870	+	1282135	1282172	5	180915260	-	111121871	111121900	54522
+21	8	0
+8
+
+chain	692	5_h2_hap1	1794870	+	1276691	1276804	5	180915260	+	21496928	21497041	821
+113
+
+chain	13519395	5_random	143687	+	0	143687	5	180915260	+	180261930	180405660	222
+5859	0	4
+460	1	1
+23	0	2
+42	1	3
+42	1	1
+1633	55	55
+2271	0	10
+1279	2	0
+761	2	0
+25	1	1
+150	13	13
+4989	0	1
+1174	1	1
+23	1	1
+495	16	16
+2709	1	4
+349	0	4
+466	0	1
+292	2	0
+184	0	5
+621	13	13
+1788	2	0
+21	1	1
+731	12	12
+149	0	3
+5100	1	0
+1059	0	3
+1724	2	0
+4111	1	0
+890	4	4
+47	1	1
+1137	0	1
+147	17	19
+72	1	1
+22	1	1
+365	1	1
+19	2	2
+1360	0	1
+1476	1	1
+43	1	1
+1141	1	0
+2615	18	18
+4308	0	4
+135	0	2
+1484	8	6
+7384	0	11
+284	1	1
+69	1	1
+232	6	0
+1064	0	2
+4530	0	1
+4542	6	6
+10543	1	0
+4051	2	0
+11340	5	6
+4936	1	0
+12029	3	3
+43	1	1
+2955	27	27
+775	0	10
+822	1	0
+2057	1	0
+733	0	1
+4016	0	1
+4514	1	1
+49	1	1
+4484	1	0
+784	1	1
+25	1	1
+5707	2	0
+1274	1	0
+289	1	1
+34	1	0
+80
+
+chain	15799018021	6	170899992	+	5000	170896992	6	171115067	+	60000	171055067	6
+1297281	0	1
+7806978	162987	0
+4013144	0	9
+261	15	13
+18786172	17	17
+439	16	16
+59	4	5
+32202	17	17
+439	16	16
+59	5	4
+15403	0	1
+13914166	0	4
+115	1	1
+17	1	1
+415	0	12
+105	3	6
+12160281	50000	50000
+642507	3050000	3100000
+248423	50000	50000
+2918791	0	1238
+9427508	4	4
+162	12	12
+2193	22	22
+293	1	1
+30	1	1
+845	0	1
+45	1	1
+9769	0	2
+6058	1	1
+24	1	1
+2223	1	1
+24	1	1
+182	12	12
+284	1	1
+20	1	1
+970	1	1
+64	36	7
+575	43	43
+389	1	1
+27	1	1
+3279	1	1
+44	1	0
+3012	0	1
+545	17	17
+2562	1	0
+251	1	0
+943	0	8
+29	1	1
+566	0	6
+1483	0	2
+1960	0	1
+4564	1	1
+25	1	1
+832	1	0
+801	8	8
+1131	1	1
+58	1	5
+6177	1	0
+3712	0	1
+2185	1	1
+35	1	1
+710	2	2
+78	1	1
+2201	1	1
+30	1	1
+283	1	1
+30	1	1
+448	0	1
+75012	0	8
+2508457	0	1
+4641788	5	5
+37	1	1
+8503609	2	0
+5363169	200000	150000
+6040303	1	1
+36	0	1
+2020	1	1
+46	1	1
+1559	1	1
+72	1	1
+1098	1	1
+29	1	1
+264	7	7
+580	1	0
+30	1	1
+536	1	1
+41	1	1
+5663	0	1
+423	0	2
+372	1	1
+18	1	1
+9612	0	1
+1414	0	1
+176	2	0
+2742	0	1
+1968	1	0
+754	0	1
+4237	1	0
+2388	1	1
+31	0	1
+3385	1	0
+2004	0	8
+3395	3	0
+32	1	1
+4109	1	0
+1055	0	20
+1611	0	1
+17198424	26	17
+7835	1	0
+11119	1	1
+5197	0	11
+4791	1486	66479
+6787989	1	0
+149	0	4
+947	0	4
+244	1	0
+28418215	1	1
+21	0	1
+3116903	50000	171704
+1939305	1	1
+19	2	0
+8192274	4	4
+122	2	0
+1127	0	1
+1104	1	102
+18	0	29
+40	0	3
+22	1	4
+50	0	26
+56	18125	195105
+950946	1	157
+51	1	1
+104	0	255
+610	0	408
+104	0	105
+1285158	150028	50028
+725067
+
+chain	8374990	6	170899992	+	9109557	9199728	6	171115067	+	9164559	9254607	394
+3887	2	0
+1509	45	45
+888	7	8
+372	0	1
+4746	3	0
+1114	31	31
+140	35	35
+2111	13	13
+445	248	137
+1437	38	38
+55	25	25
+739	19	19
+2479	70	58
+1297	0	4
+7065	24	24
+542	31	31
+531	22	22
+824	0	1
+2286	40	39
+1209	48	48
+1435	6	0
+4096	4	0
+495	41	42
+6884	0	1
+3177	0	1
+2843	0	1
+904	5	5
+830	18	18
+1997	0	1
+942	4	0
+122	33	33
+1012	0	10
+3751	0	1
+5959	49	49
+4503	0	20
+7514	8	8
+4012	15	15
+673	16	0
+83	4	0
+424	3	0
+3932
+
+chain	892181	6	170899992	+	9258019	9267980	6	171115067	+	9150000	9160000	4430
+970	53	55
+802	16	17
+389	27	27
+73	5	4
+118	9	5
+615	0	2
+69	17	15
+578	0	1
+114	22	22
+888	130	130
+252	3	9
+564	0	1
+211	5	0
+90	4	0
+1846	21	21
+1832	0	42
+238
+
+chain	763150	6	170899992	+	9249728	9258019	6	171115067	+	9141295	9150000	6494
+566	0	1
+140	8	0
+205	47	47
+145	18	12
+46	1	0
+3841	0	56
+172	0	372
+444	18	18
+2447	20	20
+173
+
+chain	369937	6	170899992	+	9267980	9272102	6	171115067	+	9160000	9164126	144773
+1134	49	45
+1420	38	38
+203	0	4
+144	0	3
+115	54	55
+965
+
+chain	4624	6	170899992	+	9129966	9130015	6	171115067	+	165872977	165873026	28640892
+49
+
+chain	1407	6	170899992	+	74606704	74606747	X	155270560	+	149588561	149588604	701656
+6	11	11
+26
+
+chain	414456960	6_cox_hap1	4731698	+	0	4731698	6	171115067	+	28541283	33351542	27
+3409	1	0
+3526	0	1
+2940	0	4
+981	0	1
+4053	0	2
+1433	0	1
+3153	2	0
+369	0	1
+1090	0	1
+884	1	4
+363	1	0
+1969	0	1
+994	5	0
+58	1	1
+131	1	0
+4080	1	0
+680	0	1
+978	0	1
+1062	1	0
+2669	19	19
+7247	1	2
+1704	0	4
+1513	0	2
+49	2	0
+2160	0	5
+672	1	1
+38	1	1
+1384	1	0
+1685	1	1
+30	1	1
+2421	1	1
+42	1	1
+830	1	1
+41	1	1
+1630	0	1
+7458	1	0
+691	0	1
+525	0	1
+79	1	1
+29	1	1
+2055	1	1
+16	0	24
+1867	5	7
+786	0	2
+280	0	1
+227	2	0
+6678	1	0
+4401	1	0
+210	1	0
+3193	2	0
+3619	0	1
+2414	0	2
+5387	0	3
+2927	0	1
+3304	0	1
+440	0	5
+415	0	9
+3597	1	1
+48	1	1
+3412	1	1
+46	1	1
+3604	4	4
+1063	1	1
+36	1	1
+3511	6	6
+2797	32	41
+393	0	1
+477	1	1
+37	1	1
+2459	2	0
+517	0	12
+318	0	1
+1010	7	6
+2103	0	1
+5171	0	8
+1483	1	0
+3813	888	0
+4675	0	2
+5620	1	0
+2017	1	0
+3363	0	5
+1197	0	3
+3208	1	0
+1928	1	0
+174	6	0
+780	1	3
+443	14	0
+3079	0	5
+1993	0	3
+1089	1	1
+58	1	1
+80	0	8
+256	2	0
+2473	37	43
+752	0	2
+33	0	2
+825	0	1
+787	1	1
+37	1	1
+1168	16	0
+377	5	1
+27	1	1
+2161	2	0
+636	25	25
+1663	1	0
+1757	6	6
+205	4	0
+203	7	7
+107	1	1
+28	1	1
+100	4	4
+258	5	0
+659	1	0
+3805	5	8
+1486	4	4
+213	39	43
+4429	0	2
+1199	13	13
+5803	12	0
+2987	0	1
+813	0	17
+920	2	0
+3820	1	3
+130	21	9
+1913	0	14
+1800	0	1
+1255	2	0
+1466	4	0
+747	0	1
+124	2	0
+2108	1	0
+169	0	26
+593	1	0
+632	5	0
+2711	0	4
+1042	0	1
+34	1	1
+1025	2	0
+27	4	18
+81	1	33
+33	0	1
+6	0	76
+3950	1	0
+86	1	1
+12	1	1
+2947	0	1
+1160	1	0
+2046	3	0
+720	1	0
+1341	1	0
+10205	0	5
+1265	1	0
+10	1	1
+1278	5	6
+399	0	32
+96	16	18
+605	4	0
+1072	12	12
+950	11	7
+5128	9	10
+2711	1	0
+676	0	1
+2904	1	1
+30	1	1
+851	0	1
+1410	0	1
+394	1	1
+57	1	1
+1561	0	2
+11062	1	1
+58	1	1
+3238	1	1
+42	1	1
+269	1	0
+284	3	3
+24	1	0
+2796	0	5
+2451	28	0
+2251	1	1
+32	1	0
+10	0	4
+24	1	1
+694	0	2
+3475	0	1
+2008	1	1
+49	1	1
+475	1	1
+28	1	1
+259	160	0
+1858	1	0
+1621	3	0
+1791	1	0
+316	0	2
+1169	0	1
+2549	1	0
+2941	1	1
+34	1	1
+243	9	0
+5157	0	2
+1748	0	8
+472	4	0
+2470	0	4
+402	1	0
+643	2	0
+748	0	2
+859	1	0
+409	2	0
+267	0	2
+322	0	4
+155	1	0
+9957	0	4
+1440	4	4
+127	1	0
+1085	1	0
+131	1	0
+767	1	0
+1160	21	21
+1294	1	0
+712	1	0
+1819	2	1
+464	1	0
+6944	0	4261
+55	0	7
+1235	0	3
+702	0	24
+2847	0	1
+2428	3	0
+7517	0	1
+3204	1	0
+611	1	0
+7104	1	0
+4959	14	14
+2827	1	0
+9421	82	25
+4428	8	0
+5987	41	41
+2108	0	2
+344	1	0
+4216	1	0
+810	0	5
+4443	1	0
+10291	10	0
+7265	5	0
+7041	1	0
+6007	1	0
+8185	4	0
+4961	0	3
+13564	0	1
+1475	0	2
+105	0	10
+10104	2	0
+3073	1	0
+3715	8	0
+2246	24	24
+11461	0	2
+837	61	1
+7660	39	39
+1705	0	1
+6068	7	0
+916	0	4
+569	1	1
+72	1	1
+2260	0	2
+7036	4	0
+3591	0	3
+713	4	0
+7058	11	11
+3319	0	2
+8475	0	1
+1324	0	2
+5438	5	0
+156	1	1
+44	0	1
+21501	7	7
+3359	16	16
+2138	0	5
+4406	11	11
+1525	1	1
+28	1	1
+2159	16	0
+48	4	0
+3030	0	1
+5717	10	0
+6594	2	0
+648	31	31
+1275	1	0
+4	1	0
+3599	1	0
+7515	4	0
+979	0	2
+1990	0	10
+123	1	1
+27	1	1
+1255	0	2
+2769	5	5
+727	1	1
+26	3	3
+785	0	1
+8871	29	29
+15459	1	0
+5978	5	5
+66	1	1
+46	1	1
+18539	1	0
+7732	2	0
+652	0	1
+861	0	1
+10658	17	17
+1313	0	1
+3515	3	0
+19	18	0
+539	0	1
+655	2	0
+10586	2	0
+2385	0	1
+7589	1	0
+29834	1	1
+27	1	1
+1216	1	0
+1323	1	0
+673	0	3
+20031	0	3
+2841	13	0
+1841	4	0
+6446	1	0
+11727	0	1
+8427	17	17
+2864	0	143
+4107	0	8
+748	0	2
+3417	1	1
+32	1	1
+18799	0	2
+21810	1	1
+34	1	1
+2784	2	0
+7864	2	0
+4498	0	1
+49089	1	1
+32	1	1
+509	1	1
+37	1	1
+5371	22	16
+389	1	1
+21	1	1
+806	1	0
+1638	6	6
+228	1	1
+45	1	1
+2068	6	3
+441	1	0
+2338	1	0
+1948	1	1
+26	1	1
+214	0	1
+6118	1	1
+31	1	1
+2382	5	5
+4335	1	1
+39	1	1
+4561	1	1
+38	1	1
+2199	1	1
+49	1	1
+243	19	6
+2779	1	1
+37	2	0
+24	1	1
+1966	3	0
+233	1	1
+29	1	1
+13756	0	4
+3956	4	1
+33765	46	46
+12758	1	0
+18985	0	8
+1384	3	1
+85	1	0
+3539	1	1
+32	1	1
+145	1	0
+1245	2	0
+1736	80	80
+1607	1	5
+712	10	11
+502	0	1
+3670	1	0
+740	0	1
+1693	0	1
+6497	0	2
+2898	1	3
+141	0	1
+1108	0	2
+1448	1	0
+1340	0	1
+7616	74	66
+2882	1	2
+30	8	0
+896	21	3
+395	1	1
+37	3	0
+23	1	2
+1210	18	0
+65	1	1
+20	1	1
+791	0	4
+389	1	0
+809	1	1
+55	0	7
+428	1	1
+17	1	1
+239	1	1
+20	1	1
+69	1	1
+37	1	1
+955	1	0
+839	0	1
+165	1	0
+3867	0	5
+70	1	1
+27	1	1
+899	1	2
+107	1	0
+1457	1	0
+763	12	5
+35	1	1
+1417	10	10
+121	1	1
+38	0	3
+377	1	0
+325	2	2
+178	1	0
+11	4	0
+297	0	24
+337	11	0
+134	1	1
+694	3	0
+72	1	1
+144	1	1
+96	1	1
+199	2	0
+1011	1	0
+107	1	1
+1280	1	1
+73	1	1
+84	25	25
+287	1	1
+26	1	1
+139	1	1
+41	1	1
+440	4	0
+130	12	12
+435	21	0
+85	1	1
+28	1	1
+73	1	1
+61	1	1
+53	5	1
+70	1	2
+52	2	0
+157	30	30
+554	2	2
+128	1	5
+68	1	1
+44	1	1
+125	0	1
+57	1	1
+308	0	7
+15	1	1
+725	9	0
+60	1	1
+180	1	1
+55	1	1
+61	1	1
+23	1	0
+5	1	2
+88	1	1
+56	1	1
+433	2	0
+84	68	68
+182	12	12
+216	1	1
+94	1	1
+561	1	1
+16	1	1
+113	1	1
+86	1	1
+148	2	0
+75	2	0
+77	1	21
+209	3	8
+374	1	0
+173	4	3
+201	1	1
+42	1	1
+56	1	1
+115	1	0
+327	1	1
+54	5	5
+929	1	1
+21	1	1
+97	1	1
+28	0	3
+830	0	2
+68	1	1
+525	0	1
+2081	1	1
+41	1	1
+165	3	3
+46	1	0
+378	1	1
+49	1	1
+352	0	1
+142	1	1
+30	1	1
+95	1	1
+45	1	1
+227	1	1
+53	1	1
+130	1	1
+18	1	1
+138	1	1
+90	1	1
+129	41	41
+50	1	1
+79	1	1
+117	1	1
+31	1	1
+240	5	5
+57	1	1
+152	1	1
+30	1	1
+177	5	5
+321	1	1
+63	1	1
+504	18	18
+662	1	1
+74	1	1
+248	1	1
+34	1	1
+1507	0	10
+1051	0	2611
+560	3	3
+23	1	1
+1631	0	15
+78	4	0
+160	0	21
+3764	0	4
+1358	0	1
+1773	1	1
+43	1	1
+1263	1	1
+39	1	1
+183	0	16
+4097	10	0
+1261	1	1
+20	1	1
+137	1	0
+2351	1	1
+43	1	1
+1010	0	4
+536	1	1
+38	1	1
+381	0	1
+888	19	19
+1521	1	1
+27	1	1
+161	1	1
+46	1	1
+2659	2	0
+533	10	0
+441	1	12
+1684	1	1
+26	3	4
+879	16	16
+514	0	2
+58	1	1
+117	1	1
+24	1	1
+207	1	0
+38	1	1
+730	1	1
+39	1	1
+429	10	10
+134	0	4
+37	1	1
+144	8	8
+1036	2	0
+262	2	2
+38	0	1
+70	18	18
+84	11	13
+317	0	3
+1256	0	2
+332	1	1
+21	1	1
+193	8	28
+30	1	1
+79	1	1
+29	1	1
+536	1	0
+611	1	1
+25	1	1
+399	4	4
+118	0	32
+23	1	1
+116	1	1
+30	1	1
+503	1	1
+22	0	3
+136	1	1
+48	1	1
+330	9	9
+1108	1	1
+98	1	1
+582	0	4
+711	7	7
+89	1	0
+293	7	6
+159	1	1
+24	1	1
+167	6	6
+171	17	17
+681	1	1
+43	1	1
+538	1	1
+44	1	1
+537	16	16
+180	6	6
+778	2	2
+44	1	1
+168	0	7
+211	1	1
+42	1	1
+1253	1	1
+29	1	1
+320	1	1
+36	2	2
+55	1	2
+460	1	1
+35	1	1
+553	8	8
+386	1	1
+26	1	1
+540	1	1
+31	1	1
+65	0	1
+625	12	12
+313	0	1
+52	1	1
+22	1	1
+583	1	1
+49	1	1
+678	37	37
+784	3	0
+770	1	1
+87	11	0
+1129	1	1
+36	1	1
+553	8	8
+997	16	15
+157	1	1
+31	2	2
+204	18	19
+487	1	1
+29	1	1
+374	1	1
+67	1	1
+720	13	13
+266	10	10
+330	16	14
+413	1	1
+44	1	1
+78	6	6
+181	2	2
+36	1	1
+397	1	1
+20	1	1
+311	1	1
+48	2	2
+1298	11	11
+437	4	4
+35	1	1
+194	10	10
+310	1	1
+51	1	1
+136	1	1
+49	1	1
+521	1	1
+23	1	1
+220	1	1
+71	1	1
+1046	15	15
+216	1	1
+21	1	1
+51	1	1
+49	1	1
+527	17	17
+340	12	11
+1025	1	0
+2572	1	1
+29	1	1
+397	2	5
+668	13	13
+541	1	1
+59	0	2
+6	1	1
+122	14	14
+51	1	1
+46	1	1
+72	5	5
+352	0	21
+136	1	1
+12	1	1
+66	16	16
+456	37	34
+371	7	7
+48	1	1
+194	10	10
+108	1	1
+60	1	1
+122	0	1
+48	1	1
+238	1	1
+32	0	1
+100	1	0
+72	1	0
+390	1	1
+38	1	1
+144	1	1
+27	0	4
+184	21	228
+49	1	1
+608	0	1
+152	1	1
+31	1	1
+281	8	8
+337	1	1
+45	1	1
+222	1	1
+20	1	1
+380	1	0
+44	1	1
+368	1	1
+72	1	1
+502	36	18
+63	1	1
+43	0	4
+136	1	1
+42	1	1
+80	4	4
+35	1	0
+89	1	1
+24	0	5
+829	13	13
+102	14	0
+233	1	1
+42	0	3
+85	0	1
+400	1	1
+40	1	1
+538	25	25
+174	1	1
+20	1	1
+705	1	1
+26	2	2
+614	1	1
+44	1	1
+509	1	1
+32	1	1
+224	1	1
+42	1	1
+747	5	5
+804	1	1
+29	1	1
+166	1	1
+43	1	1
+233	1	1
+44	1	1
+620	8	8
+133	1	1
+31	1	1
+165	1	1
+29	1	1
+1249	1	1
+26	4	0
+56	1	1
+67	1	1
+716	1	1
+46	0	1
+16	1	1
+174	1	1
+96	1	1
+141	1	1
+39	0	4
+263	1	1
+18	1	1
+259	4	4
+38	1	1
+104	1	1
+40	1	0
+248	1	1
+18	1	1
+238	1	1
+32	1	1
+70	0	2
+16	1	1
+818	1	1
+22	4	4
+1641	1	1
+46	1	1
+53	1	0
+38	1	1
+373	1	1
+60	1	1
+1149	0	2
+19	1	1
+1653	4	4
+42	1	1
+218	12	12
+363	1	1
+24	1	1
+457	10	10
+414	13	13
+825	1	1
+41	1	1
+492	0	8
+1370	1	1
+18	1	1
+808	2	2
+335	6	4
+880	1	1
+35	1	1
+236	1	1
+67	1	1
+298	0	1
+147	4	4
+322	11	11
+613	1	1
+62	1	1
+340	1	1
+22	1	1
+1057	1	1
+57	1	1
+358	1	1
+128	1	1
+146	10	10
+490	1	1
+20	1	1
+62	1	1
+88	1	1
+293	1	1
+28	1	0
+20	1	1
+83	0	1
+90	1	1
+312	1	1
+44	1	1
+1213	1	1
+51	1	1
+467	1	1
+39	1	1
+122	14	0
+35	1	1
+485	14	14
+110	13	0
+127	1	1
+7150	9	13
+3278	0	2
+28	1	1
+2211	1	0
+1325	18	18
+1304	3727	0
+299	0	248
+2603	2	0
+160	1	1
+34	1	1
+631	1	1
+40	1	3
+38	1	1
+332	17	17
+231	14	14
+202	1	1
+199	1	1
+71	1	1
+42	1	0
+53	11	10
+82	34	34
+135	1	1
+50	3	0
+32	1	1
+194	1	1
+45	1	1
+143	1	1
+78	1	1
+193	6	0
+40	1	1
+432	1	1
+17	1	1
+429	3	6
+58	1	1
+85	1	1
+62	1	1
+85	1	1
+57	1	1
+51	2	2
+278	1	1
+49	1	1
+77	11	11
+120	0	4
+139	1	1
+30	2	2
+205	4	4
+131	1	1
+22	1	1
+251	1	1
+34	1	1
+175	1	1
+36	1	1
+239	1	1
+32	5	5
+63	1	1
+27	1	1
+78	1	1
+19	1	1
+209	1	1
+143	1	13
+176	0	1
+7	0	8
+375	0	1
+62	1	1
+129	2	2
+135	1	1
+88	8	0
+90	6	8
+796	2	0
+1219	1	1
+34	1	1
+833	1	1
+46	1	1
+74	1	1
+45	1	1
+95	1	1
+29	1	1
+298	0	3
+47	1	1
+311	1	1
+58	1	1
+349	15	15
+208	1	1
+37	3	0
+413	11	11
+54	1	1
+97	1	1
+137	0	2
+95	1	1
+257	3	0
+35	1	1
+66	1	1
+47	1	1
+104	7	7
+220	17	17
+228	4	4
+432	1	1
+34	3	3
+175	4	4
+26	1	2
+116	7	7
+60	13	13
+137	1	1
+44	1	1
+744	1	1
+29	1	1
+148	0	5
+30	1	1
+387	1	1
+22	1	1
+309	1	1
+82	1	1
+52	1	1
+32	1	1
+121	1	1
+37	1	1
+396	3	2
+324	1	1
+92	1	1
+51	9	9
+71	7	7
+24	1	1
+115	1	1
+101	1	1
+799	12	12
+197	1	1
+146	1	1
+103	1	1
+134	1	1
+16	1	1
+378	1	1
+85	1	1
+134	1	1
+25	1	1
+54	3	3
+55	1	1
+67	1	1
+22	1	1
+54	13	13
+55	11	11
+120	1	1
+23	1	1
+51	1	1
+22	1	1
+369	1	1
+273	1	1
+119	6	6
+229	34511	40178
+78	1	1
+22	1	1
+180	1	1
+33	1	2
+26	6	6
+474	1	1
+36	1	1
+151	1	1
+29	1	1
+120	1	1
+23	1	1
+865	1	1
+39	1	1
+330	1	1
+24	1	1
+197	1	1
+69	1	1
+116	3	0
+161	1	1
+38	1	1
+753	1	1
+57	3	3
+145	1	1
+121	1	1
+300	1	1
+147	1	1
+379	1	1
+55	2	2
+65	1	1
+32	1	1
+1008	1	1
+24	1	1
+159	18	18
+659	1	1
+76	0	2
+77	1	3
+65	1	1
+84	1	0
+119	1	1
+15	1	1
+247	4	0
+372	1	0
+1633	1	1
+16	1	1
+221	9772	11561
+315	1	1
+53	1	1
+67	1	1
+91	1	0
+23	1	0
+27	2	2
+66	2	2
+80	0	41
+12	1	1
+158	1	0
+92	2	0
+254	1	1
+43	1	1
+846	6	149
+84	1	1
+29	3	3
+315	17	17
+482	1	1
+29	3	3
+278	1	1
+73	1	1
+2767	1	1
+34	1	1
+192	1	1
+33	1	0
+168	6	0
+276	10	10
+344	1	1
+49	1	1
+109	1	1
+35	3	3
+561	24	27
+923	1	1
+102	1	1
+75	14	14
+266	1	1
+80	2	2
+185	1	0
+1035	1	1
+23	1	1
+417	10	10
+97	1	1
+94	1	1
+492	1	1
+37	5	5
+1429	1	1
+19	1	1
+839	1	1
+96	1	1
+1279	4	0
+683	1	1
+49	1	1
+514	1	1
+28	4	4
+2302	1	1
+42	1	1
+537	2	21
+1555	1	1
+42	0	1
+14	4	4
+86	1	1
+62	1	1
+515	5	1
+330	0	1
+159	0	22
+3841	1	0
+5065	12	12
+97	0	3
+772	1	1
+21	2	1
+1058	0	2
+349	2	0
+1080	6	0
+11	1	3
+53	0	2
+14	1	1
+1035	1	1
+85	1	1
+69	1	1
+27	1	1
+547	7	7
+195	1	1
+41	1	1
+395	1	1
+35	1	1
+73	0	1
+71	1	1
+557	3	3
+30	1	1
+66	49	49
+1310	0	2
+26	2	0
+10	1	15
+36	1	1
+196	1	1
+40	1	1
+141	1	1
+76	1	1
+1480	1	3
+347	1	1
+26	1	1
+231	1	1
+82	3	3
+69	3	0
+441	16	16
+147	1	1
+21	1	1
+3565	0	3
+877	2	0
+1036	1	1
+47	2	1
+3761	12	0
+5345	1	0
+11541	1	0
+1843	0	4
+1157	16	16
+7354	19	0
+736	0	1
+8058	1	0
+4449	21	21
+649	1	0
+2913	0	1
+381	331	0
+6066	0	1
+1968	7	0
+3198	1	0
+667	1	0
+3870	0	1
+36	13	0
+1894	1	1
+40	0	4
+1137	6	0
+211	2	0
+345	1	0
+592	4	4
+1043	4	0
+686	14	0
+1032	0	1
+9035	0	4
+167	0	2
+19472	35	35
+4457	0	3
+1470	0	1
+289	3	0
+3780	41	41
+522	1	0
+2026	8	0
+430	0	1
+631	1	1
+21	1	1
+479	0	1
+697	4	0
+1779	1	1
+27	1	1
+196	4	0
+58	8	0
+2881	1	1
+39	1	1
+120	44	45
+538	1	0
+393	6	6
+3090	1	1
+43	1	1
+1246	1	0
+294	1	1
+27	1	1
+374	3	3
+144	1	1
+190	1	6
+750	1	0
+695	2	0
+1003	11	0
+1185	8	8
+763	0	4
+2737	11	11
+453	1	0
+536	1	1
+43	1	1
+57	1	0
+21	7	0
+3892	0	1
+3177	0	1
+8990	0	2
+2303	1	0
+2850	4	0
+1273	0	2
+5863	1	0
+9593	1	1
+81	1	1
+2777	0	2
+4564	34	34
+674	0	8
+11548	2	0
+6086	0	1
+109	1	1
+2286	0	1
+997	0	18
+3344	1	1
+40	1	1
+842	28	24
+1584	1	0
+1582	0	1
+1670	3	25
+17	0	4
+16	2	0
+6	12	0
+49	1	1
+538	1	1
+26	1	1
+5879	2	4
+2513	0	1
+346	8	8
+222	16	16
+103	1	0
+198	1	3
+539	1	1
+47	1	1
+1154	0	1
+3737	1	2
+370	2	0
+1178	1	1
+78	1	1
+47	0	1
+518	6	0
+646	13	13
+469	1	0
+1072	1	4
+858	1	0
+3674	1	0
+282	1	0
+597	0	6
+505	4	4
+183	1	1
+43	1	1
+1294	1	1
+40	1	1
+572	0	4
+464	0	4
+757	40	40
+1089	2	0
+548	1	0
+1300	0	3
+1839	2	0
+189	1	1
+49	1	1
+1253	1	1
+43	1	0
+498	1	1
+45	4	0
+3538	0	1
+1989	14	14
+1332	2	0
+3586	1	0
+989	1	2
+447	0	4
+40	1	1
+2445	16	17
+291	1	3
+7	1	0
+11	0	1
+41	1	1
+94	1	1
+49	1	1
+1515	6	0
+603	13	13
+163	1	1
+45	1	1
+2050	11	11
+1126	1	1
+16	1	1
+391	1	1
+19	0	1
+932	1	0
+42	1	1
+751	1	0
+287	1	1
+42	1	1
+464	0	4
+4069	5	5
+153	1	0
+514	2	0
+1093	1	1
+41	1	1
+1746	4	4
+1351	1	1
+38	1	1
+682	12	12
+519	0	72
+168	18	18
+146	7	7
+293	1	1
+61	0	1
+43	1	1
+236	1	0
+35	1	1
+152	14	14
+776	0	4
+809	4	0
+155	1	1
+44	1	1
+1068	1	1
+93	1	1
+209	15	15
+1331	0	3
+3912	0	1
+6624	0	4
+375	0	1
+7255	5	0
+419	2	0
+293	1	0
+10397	5	24
+11095	0	1
+1770	4	0
+374	0	4
+7714	1	0
+1229	7	6
+3055	1	0
+5818	1	0
+2415	11	9
+2056	0	1
+955	4	0
+3907	0	2
+16936	0	1
+1044	1	0
+2392	0	1
+158	2	1
+199	0	1
+75	6	6
+2094	8	0
+649	2	0
+373	75	75
+2253	1	0
+15	1	0
+1995	0	2
+818	4	0
+676	0	1
+3171	8	0
+170	0	3
+459	1	1
+37	1	1
+336	1	0
+206	1	1
+26	1	1
+224	15	15
+308	2	1
+82	1	1
+23	1	1
+562	1	1
+80	1	1
+241	0	8
+1530	1	1
+20	1	1
+1372	1	1
+44	1	1
+427	1	1
+20	1	1
+651	105	81
+221	1	1
+45	1	1
+1747	1	1
+27	1	1
+179	1	1
+70	1	1
+173	1	1
+84	0	36
+1864	1	1
+41	1	1
+44	9	0
+1028	1	0
+85	1	1
+21	1	1
+475	0	2
+256	1	1
+31	1	1
+653	1	1
+18	1	1
+62	1	1
+19	1	1
+997	1	1
+22	1	1
+326	1	0
+505	5	4
+386	0	7
+466	13	13
+870	11	12
+134	15	15
+248	0	2
+2281	1	1
+79	1	1
+56	9	6
+498	100	100
+802	1	0
+290	1	1
+38	1	1
+185	1	1
+61	1	1
+944	1	1
+22	1	1
+835	1	1
+66	1	1
+890	0	1
+3503	6	6
+231	0	1
+2136	1	0
+999	1	0
+5220	3	4
+830	1	1
+24	1	1
+1209	1	1
+38	1	1
+7077	1	0
+2939	1	0
+3959	0	2
+3746	0	2
+1011	1	1
+34	1	1
+7443	0	1
+688	2	0
+574	1	1
+29	1	1
+1785	2	0
+16	20	0
+4073	2	0
+136	1	1
+77	1	1
+528	27	0
+253	0	1
+204	1	0
+129	2	0
+811	1	1
+38	1	1
+2347	52	0
+4634	1	0
+856	14	14
+1052	1	1
+28	1	1
+1255	1	1
+36	1	1
+97	0	1
+58	1	1
+1708	1	1
+48	1	1
+958	13	0
+3371	1	1
+37	1	1
+4267	0	15
+1059	0	1
+272	0	20
+168	2	0
+26	4	32
+4090	0	2
+3269	1	1
+17	1	2
+1378	1	0
+1443	0	1
+6206	1	0
+2318	0	1
+7695	2	0
+396	22	12
+918	0	1
+1818	0	1
+28	1	1
+492	1	1
+33	1	1
+326	1	1
+80	1	1
+288	8	17
+2671	0	1
+1099	0	1
+144	1	1
+29	0	1
+2098	0	2
+24	4	0
+1207	4	4
+45	1	1
+757	0	5
+1926	1	1
+40	1	1
+2657	0	1
+414	1	0
+61	0	1
+235	0	2
+2087	0	1
+713	0	4
+58	1	0
+1041	3	0
+36	1	1
+377	1	1
+17	1	1
+948	1	1
+41	1	1
+458	1	1
+21	1	1
+1055	0	1
+8189	4	5
+36	1	1
+102	2	0
+14	1	1
+682	0	6
+147	0	1
+750	0	3
+40	1	1
+2428	0	1
+750	2	0
+473	0	2
+2032	1	0
+3841	1	0
+560	1	0
+1108	1	0
+8087	1	0
+11881	1	1
+30	1	1
+4383	2	0
+6883	49	49
+3146	0	1
+906	2	0
+887	1	1
+80	1	1
+2210	1	0
+905	0	1
+1037	1	0
+5866	0	2
+18	1	1
+582	0	5
+2828	1	0
+847	1	0
+1996	4	0
+3170	1	0
+1751	0	1
+910	2	0
+691	0	1
+32873	0	1
+1722	0	1
+17559	16	24
+1369	29	0
+494	2	0
+4432	0	1
+23680	26	26
+10911	0	1
+920	0	1
+4586	0	2
+2232	1	0
+5718	0	1
+12415	1	1
+51	0	1
+7997	0	2
+1700	1	0
+2697	1	0
+2561	2	0
+1544	0	6
+1613	3	7
+37	9	1
+2113	1	0
+7174	0	34
+7914	1	1
+35	1	1
+5308	1	0
+2303	2	1
+423	7	7
+590	1	0
+24	1	1
+165	6	0
+2848	13	13
+64	0	1
+28	1	1
+723	0	4
+2868	0	1
+731	1	1
+60	1	1
+1012	3	0
+490	29	29
+1225	1	1
+78	1	1
+61	1	0
+2362	11	11
+399	1	0
+1494	16	16
+128	24	24
+530	1	1
+35	1	1
+5276	1	0
+415	0	1
+580	1	2
+1450	22	23
+816	1	0
+1953	1	0
+881	10	1
+885	8	14
+183	14	14
+1139	25	25
+155	1	1
+94	1	1
+419	3	3
+26	1	1
+56	1	0
+69	1	0
+117	1	1
+120	1	1
+42	1	1
+825	0	2
+108	1	1
+24	1	1
+956	3	0
+664	1	1
+41	1	1
+716	4	0
+1731	8	8
+4228	0	1
+5694	3	0
+4493	0	1
+2656	1	0
+3029	4	0
+5688	1	0
+170	2	0
+5972	0	2
+840	0	2
+55	1	1
+28	1	1
+2954	0	1
+4343	6	0
+1663	4	0
+150	1	0
+3128	1	0
+1449	3	0
+1534	1	0
+489	1	0
+431	0	4
+299	2	0
+5082	9	0
+413	0	1
+989	0	2
+4941	0	1
+6655	1	0
+349	8	7
+762	1	1
+29	0	3
+1434	0	1
+1267	0	1
+587	1	1
+22	0	1
+894	28	0
+1343	2	0
+2256	0	1
+4332	0	4
+22	1	1
+12415	12	10
+10485	0	1
+1429	0	12
+625	1	7
+1224	0	10
+1680	4	0
+5169	14	14
+3878	0	8
+2544	0	140
+9238	0	1
+1575	0	3
+1775	1	1
+31	1	1
+1200	1	0
+32	0	3
+797	0	8
+35	0	2
+599	1	1
+22	1	1
+5338	2	0
+1998	0	5
+146	0	4
+12031	0	1
+1993	0	1
+706	2	0
+2735	0	1
+3859	0	4
+4845	0	2
+268	2	0
+827	4	4
+1063	6	6
+7834	2	0
+3195	0	1
+4012	10	0
+6429	0	2
+308	0	1
+808	1	0
+17	8	0
+5472	19	2
+2436	0	14
+820	9	9
+2643	1	1
+32	1	1
+1189	1	0
+5710	0	3
+308	1	0
+4930	0	1
+4308	1	0
+946	82	0
+1790	0	2
+1218	25	0
+52	0	1
+1271	1	1
+33	1	1
+4760	1	0
+4924	0	1
+4817	4	4
+39	1	0
+1116	3715	901
+205	1	0
+1591	5	2
+138	2	2
+16	1	1
+802	0	89
+1600	0	6
+2175	0	5
+606	14	14
+519	1	0
+540	1	1
+40	1	1
+568	2	0
+458	1	1
+41	1	1
+1106	24	62
+818	1	1
+42	1	1
+2266	1	0
+14059	0	4
+5030	1	0
+12630	0	3
+84	9	9
+129	13	18
+564	10	15
+154	1	0
+438	10	10
+38	0	5
+98	11	9
+2034	1	1
+25	1	1
+73	10	10
+70	5	5
+132	1	1
+52	1	1
+599	1	1
+46	1	1
+279	1	1
+18	1	1
+239	3	0
+383	6	0
+224	0	1
+321	15	0
+1783	1	1
+18	3	0
+108	1	1
+60	1	1
+405	16	16
+60	1	1
+16	1	1
+970	1	1
+24	1	1
+424	3	0
+41	1	1
+57	8	8
+285	2	0
+672	1	1
+44	1	4
+103	0	1
+148	1	1
+49	3	0
+146	5	11
+91	1	1
+79	1	1
+94	1	1
+101	1	1
+88	16	16
+117	1	1
+15	1	1
+58	1	1
+93	1	1
+466	1	1
+44	1	1
+160	1	1
+23	1	1
+481	14	14
+181	4	4
+72	1	1
+25	1	1
+82	7	12
+4	0	1
+11	1	4
+20	0	5
+92	1	1
+56	10	0
+80	1	1
+141	2	0
+60	1	1
+372	0	2
+784	1	1
+85	1	1
+109	1	1
+16	1	1
+57	1	1
+92	3	1
+23	1	0
+26	1	1
+74	1	1
+33	1	1
+176	1	1
+25	2	2
+193	1	1
+35	0	1
+383	0	5
+249	1	1
+69	1	1
+98	1	1
+70	1	1
+55	1	1
+143	1	1
+438	1	1
+64	1	1
+53	4	0
+127	3	0
+75	5	5
+45	1	1
+197	1	1
+27	1	1
+116	13	13
+218	15	20
+1107	16	19
+73	1	1
+101	1	1
+123	1	1
+60	1	1
+994	1	1
+43	0	1
+18	1	1
+1215	18	18
+340	1	1
+34	1	1
+1350	16	16
+1417	1	1
+29	1	1
+475	1	1
+48	1	1
+198	10	10
+87	1	1
+18	1	1
+171	7	7
+427	1	1
+21	1	1
+2011	0	3
+17	1	1
+1412	1	1
+24	1	1
+214	8	4
+228	1	1
+34	1	1
+410	16	16
+185	1	1
+24	1	0
+164	0	1
+222	1	1
+25	1	1
+297	10	10
+1171	1	0
+569	19	19
+2755	1	0
+11	1	1
+2502	1	1
+23	1	1
+44	12	0
+2856	0	1
+148	1	1
+36	1	1
+993	2	0
+1251	2	0
+6619	14	14
+1014	4	0
+134	2	9
+818	1	0
+61	1	7
+563	46	0
+78	5	5
+1677	1	1
+49	1	1
+399	1	1
+32	1	1
+790	27	27
+104	1	1
+75	1	1
+1638	1	1
+16	1	1
+92	1	1
+44	1	1
+276	0	13
+1020	1	1
+35	1	1
+389	14	14
+256	1	0
+38	1	3
+631	1	1
+40	1	1
+2356	85	83
+1300	0	5
+511	0	2
+605	1	1
+17	1	1
+880	12	0
+1689	4	0
+2492	1	1
+39	1	1
+641	16	16
+682	0	5
+669	1	1
+25	1	1
+1926	1	1
+39	4	3
+1037	1	1
+40	2	0
+890	6	0
+41	2	0
+498	3	0
+321	0	1
+281	3	0
+450	1	1
+34	1	1
+498	1	1
+28	2	1
+280	0	2
+648	1	1
+47	1	1
+1002	4	0
+120	1	1
+1538	0	1
+75	1	1
+37	1	1
+510	91	91
+60	18	18
+2075	1	1
+19	1	1
+2429	1	1
+21	1	1
+107	1	0
+2786	0	2
+31	5	5
+1973	12	0
+3118	1	0
+246	0	1
+33	1	1
+6752	1	0
+822	2	9
+606	1	1
+18	1	1
+3920	1	1
+37	0	2
+4497	10	13
+301	20	20
+2130	1	1
+16	3	0
+1843	0	4
+3780	3	0
+850	0	1
+2774	0	3
+2065	0	1
+20	1	1
+1400	1	0
+3243	0	15
+1336	5	0
+448	49	49
+121	7	7
+1507	8	7
+422	1	0
+2184	0	1
+304	0	2
+19	0	1
+101	1	1
+417	3	3
+22	1	1
+672	4	4
+31	1	1
+150	1	1
+38	1	1
+161	5	0
+17	1	1
+72	1	0
+106	1	1
+463	1	1
+94	1	1
+138	3	4
+185	1	1
+29	1	1
+220	15	15
+167	1	1
+32	1	1
+93	1	3
+217	1	1
+23	1	1
+137	9	9
+62	0	3
+353	1	1
+27	1	1
+117	9	9
+421	1	1
+47	1	1
+124	0	1
+997	6	0
+54	5	5
+764	1	1
+45	1	1
+1431	7	7
+387	6	6
+1103	0	36
+767	1	1
+31	1	3
+208	5	5
+1610	1	1
+23	1	1
+779	0	8
+324	0	2
+45	1	1
+264	0	3
+45	1	1
+250	1	1
+18	1	1
+517	33	0
+117	1	1
+42	1	1
+550	1	1
+20	1	1
+671	1	1
+68	1	1
+89	1	1
+104	1	1
+172	0	1
+124	0	1
+522	0	1500
+466	5	5
+32	1	0
+171	1	1
+19	1	1
+67	1	1
+22	1	1
+654	1	1
+25	1	1
+68	1	1
+21	4	0
+1588	1	1
+66	1	1
+401	0	1
+186	1	1
+21	1	1
+168	0	1
+686	3	0
+19	1	1
+127	1	1
+29	1	1
+234	1	1
+30	1	1
+141	0	2
+33	1	1
+673	1	1
+89	1	1
+161	16	16
+504	20149	20139
+1269	1	1
+40	1	1
+327	1	1
+24	1	1
+172	2	2
+27	11	15
+381	10	11
+376	1	1
+45	1	1
+121	1	1
+62	1	1
+289	1	1
+26	1	1
+191	1	1
+20	11	11
+425	1	1
+37	1	1
+296	1	1
+149	1	1
+284	1	1
+37	1	1
+705	1	12
+106	12	12
+306	1	1
+24	1	1
+1299	1	1
+47	1	1
+2026	1	1
+20	1	1
+133	1	0
+9803	0	4
+15871	3	0
+2464	1	1
+24	1	1
+879	1	1
+73	1	1
+89	1	1
+42	1	1
+108	1	1
+43	0	1
+26	1	1
+511	5	6
+605	19531	20105
+55	1	1
+37	0	2
+89	1	1
+51	1	1
+85	1	1
+78	1	1
+173	1	1
+51	1	1
+90	3	3
+95	1	1
+32	1	1
+53	1	1
+231	1	0
+82	2	0
+27	0	1
+44	1	0
+96	10	7
+132	1	1
+233	1	1
+257	1	1
+56	5	5
+237	1	1
+141	1	1
+92	1	1
+154	7	7
+3208	1	1
+33	1	1
+671	1	1
+21	1	1
+955	0	3
+130	1	1
+26	1	1
+288	8	8
+218	0	3
+1076	8	0
+609	10041	10021
+240	2	2
+66	1	1
+228	1	1
+23	1	1
+1612	1	1
+21	1	1
+261	1	1
+99	1	1
+128	1	1
+15	1	1
+77	9	9
+618	8	8
+84	4	6
+438	1	1
+140	1	1
+158	4	3
+277	12	12
+165	4	4
+36	1	1
+253	1	1
+59	1	1
+910	0	1
+915	4	5
+276	15	15
+682	1	1
+28	1	1
+1483	13	13
+203	1	0
+52	1	1
+48	1	1
+229	12	12
+68	15	15
+83	1	1
+39	1	1
+194	1	1
+24	1	1
+251	8	8
+619	0	4
+15	1	1
+690	1	1
+28	1	1
+54	0	1
+463	1	1
+30	1	1
+449	1	1
+54	1	1
+58	5	5
+979	1	0
+318	1	1
+28	1	1
+898	10	10
+100	1	1
+22	1	1
+446	1	1
+74	1	1
+273	1	1
+19	1	1
+333	1	1
+44	1	1
+220	1	1
+56	2	0
+209	1	1
+70	1	1
+223	0	20
+220	1	1
+31	1	1
+56	1	1
+111	1	1
+220	1	1
+89	1	1
+119	1	1
+113	2	0
+195	1	1
+46	1	1
+184	1	1
+60	0	4
+76	0	4
+53	3	1
+43	1	1
+153	1	1
+53	1	1
+195	6	0
+60	1	1
+278	1	0
+42	1	1
+124	10014	10005
+302	1	1
+24	1	1
+135	20	19
+55	1	1
+40	1	1
+175	1	1
+46	1	1
+52	1	1
+19	1	1
+277	1	1
+88	1	1
+172	1	1
+26	1	1
+129	1	1
+35	1	1
+55	9	9
+318	3	3
+46	1	1
+101	8	8
+4653	1	1
+38	1	1
+817	2	0
+256	1	1
+27	1	1
+339	1	1
+48	1	1
+54	10	10
+1393	3	0
+1491	2	0
+1983	16	0
+167	0	4
+3886	7	8
+535	1	1
+16	1	1
+1555	3	0
+3131	1	1
+17	1	1
+4196	1	0
+14974	0	1
+3514	0	4
+29	1	1
+123	0	2
+51	33	0
+121	0	133
+80	1	10
+26	60	4
+52	13	0
+20	0	2
+19	2	0
+22	4	156
+57	156	3
+61	0	2
+29	20	0
+42	11	0
+21	2	0
+50	4	6
+31	1	3
+23	1	53
+25	0	32
+66	1	55
+11	0	2
+13	0	41
+68	1	42
+23	1	3
+12	2	0
+17	1	29
+51	17	13
+18	2	0
+28	2	0
+26	2	0
+158	1	25
+102	0	82
+99	280	0
+53	21	0
+5064	0	2
+7569	2	0
+2189	0	1
+85	1	1
+31	0	4
+399	14	14
+408	0	1
+681	0	5
+184	1	1
+20	1	1
+64	1	1
+29	1	0
+9	2	0
+442	4	0
+342	1	1
+24	1	1
+131	1	1
+198	1	1
+370	0	1
+34	1	1
+447	21	20
+259	1	1
+23	0	1
+121	2	0
+2257	1	1
+22	1	1
+811	1	1
+27	1	1
+95	18	18
+631	0	5
+843	0	2889
+55	0	88
+1189	0	2
+2274	1	0
+752	4	0
+164	1	1
+55	1	1
+1033	10	10
+683	1	1
+57	1	1
+3578	1	1
+34	1	1
+1446	1	0
+460	1	1
+31	0	1
+6	1	1
+163	1	1
+22	1	1
+81	1	1
+27	1	1
+548	1	1
+61	1	1
+1169	1	1
+41	1	1
+1568	14	14
+4889	1	1
+62	1	1
+530	17	17
+394	1	1
+40	7	0
+57	12	12
+69	2	2
+39	1	1
+70	1	1
+22	0	3
+2307	1	1
+30	1	1
+411	1	1
+104	1	1
+375	26	27
+1218	1	1
+35	1	1
+85	1	1
+20	6	0
+687	1	1
+34	1	1
+268	13	13
+74	1	1
+47	2	0
+69	1	1
+49	1	1
+73	1	1
+48	1	1
+218	1	1
+42	1	1
+197	1	1
+41	1	1
+313	1	1
+40	1	1
+476	1	1
+29	1	1
+185	1	1
+35	1	1
+594	1	1
+24	1	1
+220	26	0
+245	0	1
+261	13	13
+89	1	1
+90	1	1
+224	1	1
+201	1	1
+306	1	1
+29	5	5
+121	1	1
+31	1	1
+109	1	1
+25	1	1
+168	1	1
+19	1	1
+93	12	11
+132	1	0
+113	1	1
+30	1	1
+56	9	9
+300	1	1
+50	2	2
+96	1	1
+43	1	1
+76	1	1
+44	1	1
+197	1	1
+91	7	1
+119	0	9
+392	5	5
+89	1	1
+428	11	11
+260	1	1
+23	1	0
+10	1	1
+70	1	1
+65	2	0
+16	0	19
+28	1	1
+208	1	1
+70	1	1
+149	0	3
+51	29	29
+163	1	1
+55	1	1
+63	17	17
+1208	1	1
+98	1	1
+162	1	1
+45	1	1
+148	14	14
+51	5	5
+209	4	4
+1242	1	1
+42	5	0
+87	1	1
+522	0	3
+305	0	1
+1379	0	2
+390	0	15
+72	1	1
+16	1	1
+270	1	0
+280	7	7
+2763	20	20
+674	10	10
+1375	14	0
+327	2	0
+107	1	1
+629	16	16
+54	4	4
+680	16	16
+395	1	1
+42	1	1
+1763	1	1
+46	1	1
+282	1	1
+39	1	1
+860	1	1
+26	1	1
+745	0	2
+2081	2	0
+817	4	4
+202	1	1
+48	1	1
+168	1	1
+53	1	1
+379	10	10
+1178	14	14
+132	5	0
+555	1	1
+65	1	1
+550	1	1
+21	1	1
+462	1	1
+43	1	1
+121	1	1
+48	0	3
+15	1	5
+1404	0	1
+450	4	0
+626	1	0
+304	1	1
+39	1	1
+564	1	1
+45	1	1
+303	2	0
+409	1	1
+18	1	0
+858	2	0
+2168	0	1
+54	1	1
+20	1	1
+524	0	1
+410	10	10
+106	1	14
+2419	18	14
+64	1	1
+31	1	1
+185	0	5
+1646	1	1
+20	1	1
+227	1	1
+37	1	1
+500	1	0
+136	3	4
+8239	1	1
+23	1	1
+1114	0	2
+688	0	1
+901	18	18
+4781	0	4
+815	0	1
+5069	0	5
+415	0	2
+352	0	1
+1085	11	11
+1099	0	1
+991	0	1
+845	1	1
+32	0	2
+5751	0	3
+1553	1	1
+60	1	1
+278	0	1
+30	1	1
+1855	0	2
+958	0	1
+66	0	16
+2109	0	2
+1265	0	1
+17312	0	4
+1875	0	1
+2157	1	0
+915	0	6
+4940	1	0
+2649	0	1
+3331	2	0
+2276	14	0
+3128	0	4
+3496	1	0
+966	0	1
+3597	1	0
+1647	0	3
+1182	1	0
+654	0	3
+2049	1	0
+6838	1	1
+39	1	1
+186	1	0
+2718	1	1
+30	1	1
+160	11	11
+4954	0	1
+420	1	1
+123	1	1
+156	0	4
+219	4	0
+195	1	0
+4402	2	0
+4295	1	0
+4207	20	20
+468	0	1
+30	1	1
+6025	1	0
+4179	1	0
+19834	0	1
+11605	0	1
+4121	2	0
+2863	0	2
+4890	1	0
+5576	0	6
+4104	4	0
+19858	4	0
+1616	0	3
+1647	4	1
+36	0	12
+2213	0	14
+414	0	1
+458	20	20
+2860	0	3
+678	3	4
+292	2	0
+1922	0	1
+913	0	1
+2720	1	0
+1111	3	0
+2589	0	8
+9425	1	0
+1403	0	2
+1964	0	12
+4433	0	1
+1569	0	1
+7209	1	1
+41	1	1
+2257	1	0
+3001	0	1
+1845	1	0
+1593	0	1
+497	0	2
+6109	0	1
+2019	2	0
+921	0	1
+241	1	0
+5473	1	0
+2213	2	0
+1974	8	0
+4952	0	1
+6146	2	0
+953	1	0
+4141	0	1
+4244	5	0
+152	0	2
+209	0	1
+2400	0	10
+785	2	0
+1733	0	1
+554	1	0
+128	0	2
+3051	0	1
+8577	0	1
+1503	0	1
+1705	0	3
+2052	17	17
+998	177	0
+2804	1	0
+1925	1	0
+9215	0	1
+971	8	0
+36021	1	0
+8016	29	27
+3890	0	1
+67913	1	1
+18	1	6368
+73	1	32739
+14676	1	1
+19	1	1
+22867	1	1
+20	1	1
+5638	5	0
+47	12	0
+11313	0	1
+1769	0	1
+8355	0	3
+4114	0	2
+1403	1	0
+5140	0	1
+490	0	1
+219	1	0
+3483	1	0
+8939	1	1
+44	1	1
+10813	0	2
+7480	2	0
+617	1	0
+1464	0	1
+500	0	2
+1466	1	0
+527	5	0
+3593	0	1
+374	0	1
+2946	22	22
+698	0	1
+2149	1	0
+311	2	0
+6570	1	0
+962	1	0
+23	1	1
+2647	4	0
+588	1	1
+21	1	1
+3256	28	20
+870	0	1
+644	1	0
+602	2	1
+3730	1	1
+45	1	1
+12848	7	7
+7306	0	3
+6647	45	45
+1365	1	1
+63	1	1
+4166	1	0
+1887	10	0
+2949	1	1
+31	0	1
+669	1	0
+2190	2	0
+2081	0	2
+373	0	6
+421	4	4
+1460	0	1
+1699	0	8
+2882	2	0
+147	0	1
+1656	1	1
+27	1	1
+1828	0	2
+4066	35	38
+361	17	17
+1254	6	0
+1643	0	2
+2542	0	1
+848	2	1
+2117	0	2
+119	1	1
+44	1	1
+1104	0	1
+415	0	12
+634	18	1
+377	6	7
+227	6	0
+449	13	13
+895	0	17
+457	18	18
+663	0	3
+382	1	1
+26	1	1
+135	0	1
+105	1	1
+25	1	1
+620	2	0
+290	5	5
+375	1	1
+30	0	4
+98	1	0
+20	17	4
+3824	28	0
+39	4	0
+28	4	0
+44	4	0
+1898	9	9
+221	0	2
+10522	30	0
+783	1	1
+59	1	1
+94	1	1
+21	1	1
+491	1	1
+49	1	1
+289	2	0
+120	0	1
+37	1	1
+112	1	1
+21	1	1
+183	16	16
+73	2	0
+1007	1	1
+38	0	1
+79	1	1
+48	1	1
+561	1	1
+29	1	1
+145	5	5
+576	12	12
+834	1	0
+846	5	7
+34	1	1
+417	10	11
+55	1	1
+40	1	1
+110	1	1
+47	1	1
+351	1	1
+69	1	1
+53	1	1
+91	1	1
+260	1	1
+36	0	1
+604	1	0
+169	0	1
+2118	1	1
+34	1	1
+147	1	1
+213	1	1
+67	1	1
+31	1	1
+566	1	0
+17	1	1
+763	1	1
+34	1	1
+671	5	0
+41	2	2
+98	0	1
+449	0	2
+61	1	1
+38	1	1
+202	1	1
+44	1	1
+190	1	0
+46	4	4
+51	0	4
+476	1	1
+17	1	1
+212	1	1
+26	1	1
+485	1	1
+25	1	1
+263	1	1
+26	1	1
+1327	4	0
+44	1	0
+2397	1	1
+44	1	1
+4146	14	14
+901	0	1
+1769	14	14
+1721	1	0
+1125	1	0
+254	1	0
+427	0	1
+30	1	1
+111	0	2
+52	0	8
+528	44	0
+969	1	1
+10	1	0
+28	1	1
+140	1	1
+43	1	1
+1989	2	1
+598	1	1
+87	0	4
+124	1	0
+4840	1	1
+28	7	4
+505	0	2
+24	1	1
+5134	4	0
+543	1	0
+18	1	1
+97	1	1
+29	1	3
+101	6	0
+148	13	7
+1346	0	1
+128	7	0
+49	0	1
+876	2	0
+286	5	5
+184	0	1
+84	5	5
+365	9	9
+981	1	1
+11	1	1
+734	4	0
+563	4	0
+244	9	9
+379	1	1
+17	1	1
+49	2	0
+95	1	1
+30	1	1
+147	1	1
+37	0	6
+340	1	2
+58	1	1
+332	0	2
+233	6	9
+156	0	1
+26	1	1
+439	4	0
+34	0	2
+508	5	0
+96	1	1
+34	1	1
+1267	63	63
+590	1	1
+24	4	5
+1055	13	13
+135	0	1
+194	1	1
+61	1	1
+384	6	6
+2756	1	1
+19	1	1
+99	15	15
+1754	2	3
+2238	1	1
+31	1	1
+3002	4	0
+2156	15	15
+855	14	13
+442	5	5
+2022	6	6
+506	0	2
+1110	0	1
+2578	0	2
+4864	1	1
+36	1	0
+3187	1	1
+16	1	1
+184	1	1
+18	1	1
+1636	0	7
+23	1	1
+527	1	1
+39	1	1
+653	3	0
+227	1	1
+18	1	1
+102	7	7
+109	0	323
+91	1	0
+124	0	15
+621	0	4
+553	12	12
+463	1	1
+40	1	1
+372	1	1
+25	1	1
+188	12	12
+357	0	1
+250	0	5
+4193	0	4
+967	1	1
+76	1	1
+3236	4	4
+529	7	7
+246	4	0
+160	1	1
+34	0	3
+1469	0	2
+499	1	0
+937	1	1
+45	1	1
+356	71	65
+2127	0	1
+491	1	0
+80	1	1
+72	2	0
+255	6	6
+728	14	11
+702	3	0
+290	0	2
+210	19	1
+473	1	1
+42	4	0
+219	0	1
+348	1	1
+83	1	1
+851	0	16
+72	13	0
+246	1	1
+47	4	0
+410	1	0
+93	0	12
+225	0	16
+428	1	0
+4	6	0
+324	0	1
+3060	0	16
+1305	1	1
+29	1	1
+3094	0	7
+600	0	2
+5495	1	1
+47	1	1
+1247	49	55
+4351	1	1
+15	1	1
+2011	6	14
+8378	2	0
+295	0	17
+4583	1	0
+4132	0	4
+924	4	3
+1751	0	2
+1060	12	12
+380	0	2
+425	8	0
+84	0	1
+244	1	1
+28	1	1
+221	4	0
+348	1	1
+37	11	11
+50	1	1
+180	1	1
+348	1	1
+20	1	1
+1714	1	1
+79	1	1
+729	1	1
+44	1	0
+78	1	1
+112	1	1
+23	1	1
+55	9	9
+1044	1	1
+27	1	1
+494	1	1
+32	1	1
+237	1	1
+27	1	1
+1422	4	4
+413	7	1
+710	8	0
+185	0	2
+966	1	0
+13	15	1
+251	1	1
+47	1	1
+285	1	1
+103	1	1
+977	1	1
+41	1	0
+97	1	1
+131	1	0
+307	1	1
+47	1	1
+1070	1	1
+69	1	1
+382	0	1
+167	1	1
+35	1	1
+161	1	1
+30	1	1
+1068	18	0
+1173	1	1
+32	1	1
+59	1	1
+12	1	0
+18	1	1
+55	0	22
+72	1	1
+2806	1	1
+15	1	1
+1395	1	0
+157	13	0
+536	8	8
+101	1	1
+21	1	1
+147	8	8
+638	1	1
+18	1	1
+183	15	15
+990	0	12
+21	1	1
+145	0	1
+332	1	1
+31	1	1
+231	22	5
+39	1	1
+414	9	9
+93	1	1
+63	1	1
+739	0	2
+632	1	1
+74	1	1
+138	5	5
+128	0	1
+294	1	1
+45	1	1
+679	6	6
+1756	0	34
+560	27	27
+1608	5	0
+219	1	1
+134	0	3
+81	1	1
+82	0	1
+357	1	1
+28	1	1
+670	7	9
+270	0	1
+891	13	33
+257	4	0
+80	0	4
+130	2	0
+2504	42	42
+1226	1	1
+44	1	1
+2256	0	1
+80	12	0
+5544	1	0
+428	13	13
+77	4	4
+63	1	1
+64	13	19
+178	10023	10000
+157	3	3
+109	1	1
+180	1	1
+56	1	1
+169	1	0
+93	1	1
+33	2	2
+72	1	1
+30	1	1
+267	25	25
+65	1	1
+19	2	0
+108	27	27
+218	1	1
+37	1	1
+477	11	11
+93	1	1
+30	7	5
+242	0	1
+171	1	1
+29	1	1
+218	0	9
+241	1	1
+55	4	4
+88	1	1
+99	1	1
+57	0	1
+523	12	16
+399	1	1
+50	1	1
+389	1	1
+71	4	4
+173	12	12
+92	1	1
+20	1	1
+132	0	5
+15	1	1
+75	1	1
+26	5	5
+119	11	11
+542	1	1
+23	2	2
+254	1	1
+34	1	1
+172	1	1
+45	1	1
+95	11	11
+127	23	23
+64	1	1
+95	1	1
+390	1	1
+52	1	1
+170	1	1
+16	5	0
+30	1	1
+599	1	1
+119	1	1
+85	1	1
+75	1	1
+286	4	4
+61	1	1
+286	9	9
+429	1	1
+21	1	1
+53	1	1
+44	1	1
+77	165084	190027
+5156	0	1
+1680	1	1
+88	1	1
+4502	0	1
+46	1	1
+800	4	4
+23	1	1
+1305	2	0
+136	0	1
+4941	0	1
+547	0	1
+70	8	8
+293	1	1
+35	1	1
+1165	4	0
+6662	1	1
+121	1	1
+92	0	8
+214	1	1
+35	1	1
+108	1	0
+1063	0	1
+1017	1	1
+20	0	6
+1725	0	1
+150	5	5
+33	1	0
+12	1	1
+349	1	1
+24	0	1
+1562	1	1
+31	1	1
+2513	0	1
+73	36	36
+305	1	1
+27	1	1
+543	1	1
+47	4	28
+4874	0	3
+599	10	10
+137	1	0
+7	0	4
+54	1	1
+2497	1	1
+166	1	1
+637	3	3
+46	1	1
+74	4	4
+414	1	1
+48	1	1
+75	4	4
+153	0	26
+93	1	1
+39	1	0
+58	1	1
+51	1	1
+145	9	9
+29	1	1
+55	1	1
+427	1	0
+141	1	1
+87	1	1
+20	1	1
+89	3	3
+141	18	5
+48	1	1
+87	14	14
+173	1	1
+68	1	1
+54	1	1
+51	4	0
+22	1	0
+52	1	1
+171	1	1
+109	3	1
+6	0	2
+205	1	1
+54	10064	10083
+76	3	1
+197	15	15
+77	1	1
+70	1	1
+178	1	1
+60	1	1
+210	1	1
+28	1	1
+62	1	1
+33	1	1
+70	0	1
+202	1	1
+60	1	1
+106	2	0
+176	1	1
+79	0	1
+50	1	1
+50	3	3
+207	1	1
+272	5	5
+243	1	1
+84	1	1
+98	1	1
+50	5	5
+77	1	1
+74	1	1
+20	0	1
+143	1	1
+45	0	1
+4	1	1
+1088	1	1
+35	1	1
+320	1	1
+22	1	1
+275	1	1
+47	1	1
+370	19	19
+119	1	6
+51	1	1
+21	1	1
+244	0	1
+345	1	1
+24	1	1
+181	1	1
+61	3	3
+542	1	1
+16	1	1
+312	1	0
+353	4	3
+279	323	0
+86	1	1
+49	1	1
+342	1	1
+44	0	2
+222	1	1
+37	1	1
+588	8	8
+593	47	47
+359	1	1
+25	1	1
+2054	1	0
+2510	1	0
+5040	11	12
+1489	9	9
+3292	1	0
+1449	1	1
+21	1	1
+6768	1	0
+706	2	0
+7107	1	1
+38	1	1
+1163	1	1
+35	1	1
+435	1	1
+60	1	1
+325	0	1
+254	1	1
+43	1	1
+210	1	1
+7	1	0
+47	1	1
+130	4	4
+34	1	1
+208	1	1
+39	2	2
+526	1	1
+36	1	1
+99	9	7
+20	1	1
+73	1	1
+62	1	1
+425	1	1
+43	1	1
+811	1	1
+38	1	1
+362	1	1
+49	1	1
+109	1	1
+19	1	1
+79	1	1
+29	0	1
+26	1	1
+252	1	1
+75	1	1
+441	1	1
+66	1	1
+389	13	13
+67	7	7
+1185	0	311
+64	6	6
+389	31	31
+247	1	1
+38	1	1
+79	1	0
+553	1	1
+30	1	1
+433	1	1
+16	3	0
+1133	12	12
+262	5	5
+276	1	0
+960	14	14
+272	1	1
+41	1	1
+196	1	0
+1424	18	19
+314	1	1
+22	1	1
+345	1	1
+23	3	0
+245	1	1
+78	1	1
+77	1	1
+779	1	1
+32	1	1
+247	1	1
+48	1	1
+778	2	0
+226	1	1
+61	1	1
+867	0	1
+53	1	1
+397	1	1
+12	4	0
+46	1	1
+602	1	1
+35	1	1
+422	1	1
+49	1	1
+789	1	1
+37	1	1
+268	0	2
+589	8	8
+366	12	20
+1651	2	7
+19	1	1
+417	1	1
+37	1	1
+812	1	1
+33	3	0
+1351	18	18
+2186	1	1
+86	1	1
+1433	1	1
+39	1	1
+83	0	1
+238	0	1
+171	1	1
+7	2	1
+67	1	1
+596	1	1
+29	1	1
+144	4	6
+417	1	0
+88	1	1
+24	1	1
+390	18	18
+496	14	21
+145	1	1
+46	1	1
+310	1	1
+35	1	1
+214	1	1
+38	1	1
+206	1	1
+37	1	0
+240	1	1
+32	1	1
+469	1	1
+32	1	1
+208	1	1
+21	1	1
+343	1	1
+17	1	1
+88	1	1
+58	6	0
+169	1	1
+22	1	1
+162	0	1
+196	0	2
+500	6	5
+108	1	1
+40	2	0
+50	1	1
+111	1	0
+21	0	1066
+175	5	5
+155	1	1
+44	1	1
+11005	0	1
+6280	1	1
+48	1	1
+1173	1	1
+19	1	1
+2664	0	1
+351	1	0
+1059	14	14
+593	0	1
+869	16	16
+23065	2	0
+2197	0	1
+949	0	1
+15048	0	1
+606	1	0
+7820	0	4
+14669	1	0
+14708	0	1
+16326	0	1
+304	18	18
+388	2	0
+194	1	1
+49	1	1
+262	0	1
+92	1	1
+10677	2	0
+4856	3	0
+7447	6	6
+421	1	0
+884	6	0
+17	1	0
+3075	1	0
+1610	12	12
+13049	3	1
+3762	2	0
+601	2	0
+2461	0	2
+5154	1	0
+1604	0	16
+3338	26	26
+225	0	1
+1488	1	0
+1196	0	2
+683	0	1
+1218	1	0
+221	1	1
+22	1	1
+296	4	4
+1456	23	41
+880	1	12
+2490	1	0
+151	1	1
+33	1	1
+2809	4	4
+3645	1	1
+17	1	1
+3496	2	0
+154	1	1
+29	1	1
+158	0	1
+5981	1	1
+32	1	1
+1041	0	2
+174	9	0
+1383	0	1
+389	1	2
+1570	2	0
+3993	4	0
+4576	87	87
+142	8	8
+2203	20	24
+2009	1	1
+39	1	1
+489	1	1
+17	1	1
+628	1	1
+124	1	1
+1607	1	1
+23	1	1
+1021	0	8
+1249	0	20
+46	0	32
+46	6	0
+24	0	10
+7679	1	1
+44	1	1
+580	1	1
+28	1	1
+264	1	1
+65	0	1
+15	1	1
+1513	28	28
+830	19	19
+57	1	1
+21	1	1
+231	1	1
+94	1	1
+105	1	1
+208	5	5
+124	1	1
+112	3	3
+207	1	1
+38	1	1
+244	1	1
+60	1	1
+98	1	1
+50	1	1
+256	29	29
+157	1	1
+33	1	1
+143	1	1
+59	1	1
+51	1	1
+45	1	0
+73	1	1
+81	1	1
+270	1	1
+272	1	1
+232	1	1
+94	1	1
+3189	0	176
+834	0	35
+303	0	51
+321	1	0
+17170	0	1
+321	1	1
+25	1	1
+679	1	1
+33	1	1
+990	11	11
+131	8	8
+79	9	9
+1284	9945	10022
+2039	8	23
+491	1	1
+32	1	1
+85	1	1
+41	1	1
+480	1	1
+74	2	2
+1108	59	0
+70	10	10
+325	11	11
+879	1	1
+34	1	1
+524	1	1
+25	1	1
+202	17	17
+1154	1	1
+26	1	1
+89	17	17
+87	1	1
+39	1	1
+950	1	1
+15	2	2
+51	1	1
+81	1	1
+180	1	0
+187	1	1
+37	1	1
+467	1	1
+19	1	1
+755	0	2
+81	3	1
+16	1	1
+67	6	6
+84	1	1
+37	2	0
+31	0	28
+15	0	37
+266	14	14
+372	1	1
+68	1	1
+462	1	1
+46	1	1
+563	19	0
+217	9	9
+363	1	1
+22	1	1
+884	1	1
+40	1	1
+179	1	1
+42	1	1
+94	6	6
+922	1	1
+30	1	1
+481	0	3
+7925	15	11
+333	5	0
+1235	6	6
+355	1	1
+27	1	1
+515	1	0
+1077	11	0
+1521	1	0
+38	1	1
+119	1	1
+58	1	1
+63	4	3
+385	1	1
+49	1	1
+77	44	46
+87	11	11
+190	2	2
+45	1	1
+373	1	1
+47	1	1
+77	10	10
+186	1	1
+24	1	1
+1140	1	0
+214	1	1
+34	1	1
+89	1	1
+36	1	1
+288	0	1
+544	0	331
+320	1	0
+199	1	1
+16	1	1
+112	1	1
+29	1	1
+783	0	3
+311	1	1
+38	1	1
+59	1	1
+68	1	1
+52	1	1
+98	1	1
+166	7	7
+698	1	1
+68	1	1
+165	0	1
+114	1	1
+92	0	1
+14	1	1
+215	1	1
+81	1	1
+792	1	1
+31	1	1
+54	1	1
+44	1	1
+179	1	1
+26	1	1
+200	1	1
+30	1	1
+639	7	7
+505	40	42
+549	12	0
+19	1	1
+2184	1	0
+840	1	1
+69	1	1
+966	21	21
+33	12	0
+56	1	1
+94	1	1
+237	11	9
+189	1	1
+47	1	1
+318	3	0
+80	1	1
+94	5	1
+32	1	1
+126	16	16
+83	1	1
+47	1	1
+104	6	5
+56	1	1
+68	1	1
+417	12	13
+636	0	2
+30	1	1
+694	0	4
+95	1	1
+28	1	1
+1358	1	1
+19	1	1
+68	1	1
+97	1	1
+155	15	15
+323	1	7
+158	2	0
+42	6	0
+59	1	1
+314	14	14
+94	1	1
+64	1	1
+637	1	1
+21	1	1
+144	2	1
+229	11	5
+410	1	1
+96	1	1
+272	1	1
+22	1	1
+118	1	1
+44	1	1
+96	1	1
+48	1	1
+414	22	22
+373	13	13
+554	1	1
+87	10	0
+313	1	1
+37	1	1
+122	17	18
+179	1	1
+40	1	1
+591	8	8
+129	1	0
+70	1	1
+71	1	0
+73	10	6
+12	1	1
+203	0	6
+24	2	0
+45	4	0
+46	1	1
+186	9	9
+87	1	1
+28	1	1
+3625	0	1
+71	1	1
+126	1	1
+34	1	1
+532	0	2
+696	2	0
+555	1	7
+287	1	1
+30	0	3
+946	0	1
+88	1	1
+60	12	0
+12546	1	1
+37	1	0
+2071	0	1
+1253	9	9
+2003	0	1
+24677	0	2
+6212	1	1
+26	1	1
+816	0	4
+13602	18	15
+2375	2	0
+1957	2	0
+2394	6	0
+1561	0	1
+2805	4	0
+12333	8	0
+835	0	1
+426	0	27
+12156	0	18
+6903	2	0
+21807	3	0
+1588	1	0
+2605	1	1
+23	1	1
+11252	8	0
+298	6	7
+946	2	0
+232	0	1
+501	1	0
+4748	0	4
+770	0	7
+914	0	1
+295	1	0
+214	3	0
+121	0	1
+784	0	1
+2512	0	1
+4476	3	0
+926	0	1
+189	2	0
+3543	2	0
+893	1	1
+46	1	1
+1296	0	1
+153	0	1
+336	5	0
+228	1	1
+45	1	1
+207	3	0
+322	0	1
+658	1	0
+1516	3	0
+1025	0	13
+1518	0	1
+591	10	10
+3384	0	2
+182	12	0
+328	1	0
+301	0	1
+994	1	1
+18	0	6
+1743	0	1
+2350	22	23
+1548	0	7
+1976	1	0
+199	0	1
+5922	12	12
+873	0	3
+3080	12	8
+322	1	0
+490	1	0
+3602	1	0
+482	1	0
+3178	1	0
+5157	0	10
+753	0	1
+885	20	0
+1746	10	0
+4045	6	1
+3520	5	13
+2048	0	1
+3529
+
+chain	323865	6_cox_hap1	4731698	+	1267152	1270823	12	133851895	-	763369	785145	206180
+2772	0	815
+201	0	17291
+643	1	0
+54
+
+chain	65284	6_cox_hap1	4731698	+	2460102	2460796	6	171115067	-	140105134	140105832	1936071
+178	0	4
+516
+
+chain	59092	6_cox_hap1	4731698	+	4004481	4005101	4	191154276	+	48364786	48365406	2142970
+620
+
+chain	52987	6_cox_hap1	4731698	+	2674042	2675969	3	198022430	-	151830192	151832103	2402006
+102	557	556
+77	395	393
+169	221	221
+81	15	15
+81	35	35
+55	44	31
+95
+
+chain	40067	6_cox_hap1	4731698	+	3843208	3843655	1	249250621	-	189436883	189437330	3283815
+379	3	3
+65
+
+chain	34258	6_cox_hap1	4731698	+	2746095	2746514	X	155270560	-	17905933	17906346	3956727
+73	15	15
+155	1	1
+20	6	0
+17	1	1
+131
+
+chain	30865	6_cox_hap1	4731698	+	3996373	3996892	6	171115067	+	32713281	32713770	4500603
+73	89	59
+184	77	77
+96
+
+chain	30808	6_cox_hap1	4731698	+	1446736	1447059	11	135006516	-	73898390	73898713	4511271
+323
+
+chain	29563	6_cox_hap1	4731698	+	4089902	4090211	1	249250621	-	75305559	75305868	4853755
+309
+
+chain	29490	6_cox_hap1	4731698	+	3888227	3888535	20	63025520	-	21266962	21267270	4884719
+308
+
+chain	23990	6_cox_hap1	4731698	+	1313393	1314169	7	159138663	-	51241795	51242737	7706852
+178	101	101
+72	385	551
+40
+
+chain	19279	6_cox_hap1	4731698	+	2759716	2759948	5	180915260	+	25289600	25289832	11061062
+91	17	17
+124
+
+chain	18106	6_cox_hap1	4731698	+	3844292	3845362	7	159138663	+	50640514	50641583	3599691
+33	446	444
+74	250	251
+5	55	55
+48	69	69
+90
+
+chain	17763	6_cox_hap1	4731698	+	3840247	3840451	6	171115067	-	2083149	2083361	12325354
+52	0	8
+26	2	2
+124
+
+chain	17263	6_cox_hap1	4731698	+	3890221	3890428	4	191154276	+	3927369	3927573	12785973
+50	3	0
+26	4	4
+124
+
+chain	16283	6_cox_hap1	4731698	+	3267732	3267909	2	243199373	+	128545205	128545381	580296
+28	2	1
+147
+
+chain	16000	6_cox_hap1	4731698	+	3842640	3845155	5	180915260	-	144997615	145000132	3598025
+127	1430	1431
+95	205	207
+98	29	29
+57	419	418
+55
+
+chain	15874	6_cox_hap1	4731698	+	2744265	2744697	6	171115067	+	31304784	31305225	14156555
+58	158	158
+72	76	85
+68
+
+chain	15671	6_cox_hap1	4731698	+	1306242	1307477	6	171115067	-	139875690	139876935	14366990
+56	408	416
+54	620	622
+97
+
+chain	15351	6_cox_hap1	4731698	+	2791400	2791601	11	135006516	+	74748600	74748801	14697621
+99	26	26
+76
+
+chain	14920	6_cox_hap1	4731698	+	2791114	2791352	12	133851895	+	56894984	56895263	15150280
+65	69	110
+104
+
+chain	14203	6_cox_hap1	4731698	+	4000567	4000717	6	171115067	-	148948255	148948405	15963295
+150
+
+chain	14065	6_cox_hap1	4731698	+	3901987	3902139	6	171115067	-	138602057	138602209	16122340
+152
+
+chain	13939	6_cox_hap1	4731698	+	2790912	2791061	15	102531392	-	60147333	60147482	16276423
+149
+
+chain	13590	6_cox_hap1	4731698	+	4000399	4000543	2	243199373	+	178345068	178345212	16711221
+144
+
+chain	13240	6_cox_hap1	4731698	+	3909742	3911000	6	171115067	+	32548108	32549235	17164167
+52	422	421
+78	652	522
+54
+
+chain	12556	6_cox_hap1	4731698	+	1348680	1348819	2	243199373	-	184149574	184149713	18162971
+139
+
+chain	12225	6_cox_hap1	4731698	+	3890501	3890631	13	115169878	-	44980182	44980312	18662730
+130
+
+chain	12178	6_cox_hap1	4731698	+	3972449	3972615	14	107349540	-	58393926	58394091	18734378
+55	26	25
+85
+
+chain	12008	6_cox_hap1	4731698	+	3896810	3896939	8	146364022	+	49154427	49154556	18990652
+129
+
+chain	11746	6_cox_hap1	4731698	+	1299553	1299701	7	159138663	-	7702899	7703047	19437477
+54	14	14
+80
+
+chain	11718	6_cox_hap1	4731698	+	299537	299697	13	115169878	+	54026210	54026329	7331663
+62	41	0
+40	13	13
+4
+
+chain	11503	6_cox_hap1	4731698	+	3894886	3895312	11	135006516	-	111045874	111046295	19852909
+57	287	282
+82
+
+chain	11377	6_cox_hap1	4731698	+	3840583	3840825	11	135006516	+	57049649	57049891	20071170
+62	107	107
+73
+
+chain	10960	6_cox_hap1	4731698	+	3841022	3841165	12	133851895	-	49356794	49356937	20822626
+50	15	15
+78
+
+chain	10867	6_cox_hap1	4731698	+	2681465	2681622	6	171115067	-	132617434	132617597	20998653
+55	29	35
+73
+
+chain	10738	6_cox_hap1	4731698	+	3896518	3896639	10	135534747	+	59600699	59600817	21255898
+61	3	0
+57
+
+chain	10496	6_cox_hap1	4731698	+	3892569	3892679	1	249250621	-	174039531	174039641	21744607
+110
+
+chain	10328	6_cox_hap1	4731698	+	3840451	3840892	4	191154276	-	114078209	114078650	18698120
+15	372	372
+54
+
+chain	9881	6_cox_hap1	4731698	+	2734004	2734554	6	171115067	+	31205448	31206008	23100546
+72	423	433
+55
+
+chain	9755	6_cox_hap1	4731698	+	4021493	4021793	6	171115067	+	162490109	162490409	23390927
+65	181	181
+54
+
+chain	9560	6_cox_hap1	4731698	+	1301303	1301404	6	171115067	-	141323187	141323288	23857061
+101
+
+chain	9455	6_cox_hap1	4731698	+	3891953	3892158	6	171115067	+	32468923	32469135	24116909
+54	91	98
+60
+
+chain	9090	6_cox_hap1	4731698	+	2680711	2680821	3	198022430	-	94212956	94213066	24807216
+53	4	4
+53
+
+chain	7297	6_cox_hap1	4731698	+	3844000	3844124	8	146364022	+	96809146	96809270	3974525
+124
+
+chain	7162	6_cox_hap1	4731698	+	2675969	2676329	17	81195210	-	22005566	22005927	2836104
+7	302	303
+51
+
+chain	7031	6_cox_hap1	4731698	+	2673410	2673921	5	180915260	+	106108094	106108601	3265511
+58	376	372
+77
+
+chain	6840	6_cox_hap1	4731698	+	3971466	3971538	11	135006516	+	40011829	40011901	28544257
+72
+
+chain	6473	6_cox_hap1	4731698	+	3890669	3890742	1	249250621	-	102907635	102907704	21815173
+11	4	0
+58
+
+chain	6422	6_cox_hap1	4731698	+	4013834	4013902	6	171115067	+	32728707	32728775	29535230
+68
+
+chain	5921	6_cox_hap1	4731698	+	2681183	2681245	4	191154276	-	94306644	94306706	30842389
+62
+
+chain	5676	6_cox_hap1	4731698	+	2671999	2672059	3	198022430	+	95260601	95260661	31509897
+60
+
+chain	5595	6_cox_hap1	4731698	+	3972615	3972674	14	107349540	-	80191032	80191091	27115653
+59
+
+chain	5576	6_cox_hap1	4731698	+	1302171	1302230	18	78077248	-	3698437	3698496	31796878
+59
+
+chain	5517	6_cox_hap1	4731698	+	3842389	3842453	20	63025520	-	5368566	5368630	20848663
+64
+
+chain	5458	6_cox_hap1	4731698	+	3985007	3985065	2	243199373	+	112827415	112827473	32167738
+58
+
+chain	5421	6_cox_hap1	4731698	+	2677334	2677391	19	59128983	-	38462903	38462960	32247802
+57
+
+chain	5403	6_cox_hap1	4731698	+	3897499	3897556	12	133851895	+	59864980	59865037	32286341
+57
+
+chain	5339	6_cox_hap1	4731698	+	4081817	4081873	17	81195210	+	16805661	16805717	32499905
+56
+
+chain	5266	6_cox_hap1	4731698	+	4021149	4021204	3	198022430	+	6923000	6923055	32744278
+55
+
+chain	5103	6_cox_hap1	4731698	+	2743431	2743485	3	198022430	+	27241143	27241197	33231446
+54
+
+chain	5094	6_cox_hap1	4731698	+	3984745	3984799	6	171115067	+	67966752	67966806	33279729
+54
+
+chain	5089	6_cox_hap1	4731698	+	2674314	2675775	1	249250621	+	7474130	7475590	2473669
+98	975	974
+58	295	295
+35
+
+chain	5076	6_cox_hap1	4731698	+	1300901	1300955	11	135006516	+	101518151	101518205	33343005
+54
+
+chain	5067	6_cox_hap1	4731698	+	2741303	2741357	19	59128983	-	37393851	37393905	33368570
+54
+
+chain	5058	6_cox_hap1	4731698	+	3967166	3967220	1	249250621	-	172942963	172943017	33379585
+54
+
+chain	5020	6_cox_hap1	4731698	+	1345886	1345938	6	171115067	+	29692684	29692736	33527644
+52
+
+chain	4959	6_cox_hap1	4731698	+	3892516	3892569	18	78077248	+	5090594	5090647	22176918
+53
+
+chain	4957	6_cox_hap1	4731698	+	2678048	2678100	9	141213431	-	31846047	31846099	33735026
+52
+
+chain	4957	6_cox_hap1	4731698	+	3946024	3946076	6	171115067	+	32439356	32439408	33735182
+52
+
+chain	4930	6_cox_hap1	4731698	+	3894496	3894548	X	155270560	-	4541772	4541824	33815607
+52
+
+chain	4914	6_cox_hap1	4731698	+	2673741	2673793	X	155270560	+	7935883	7935935	17711968
+52
+
+chain	4885	6_cox_hap1	4731698	+	2740950	2741002	5	180915260	-	163072859	163072911	33995114
+52
+
+chain	4884	6_cox_hap1	4731698	+	2760326	2760379	7	159138663	+	8699184	8699237	23141527
+53
+
+chain	4821	6_cox_hap1	4731698	+	3935381	3935432	6	171115067	-	11031703	11031754	34213824
+51
+
+chain	4685	6_cox_hap1	4731698	+	3915703	3915753	12	133851895	+	112261417	112261467	34690968
+50
+
+chain	4613	6_cox_hap1	4731698	+	2844682	2846505	13	115169878	-	41386504	41386960	3856143
+33	479	279
+7	46	0
+24	11	0
+33	1097	0
+24	13	0
+56
+
+chain	4221	6_cox_hap1	4731698	+	2437589	2437671	14	107349540	+	75461679	75461839	4623812
+28	0	78
+54
+
+chain	4202	6_cox_hap1	4731698	+	2673968	2674023	3	198022430	+	156309398	156309453	19139889
+55
+
+chain	4186	6_cox_hap1	4731698	+	3955813	3955860	5	180915260	-	113986983	113987030	34971958
+47
+
+chain	4136	6_cox_hap1	4731698	+	2672610	2672662	13	115169878	+	42049101	42049153	23521137
+52
+
+chain	3978	6_cox_hap1	4731698	+	2673481	2673609	X	155270560	-	130914483	130914611	4485241
+128
+
+chain	3891	6_cox_hap1	4731698	+	2760039	2760115	16	90354753	-	58442153	58442229	17002345
+76
+
+chain	3877	6_cox_hap1	4731698	+	2672485	2672526	15	102531392	+	40275232	40275273	21164310
+41
+
+chain	3776	6_cox_hap1	4731698	+	2759549	2759589	1	249250621	-	143888892	143888932	33598889
+40
+
+chain	3639	6_cox_hap1	4731698	+	3890631	3890669	3	198022430	+	101411146	101411184	20382394
+38
+
+chain	3574	6_cox_hap1	4731698	+	2673146	2673184	3	198022430	-	173409162	173409200	29596627
+38
+
+chain	3573	6_cox_hap1	4731698	+	2790788	2791088	16	90354753	+	31183111	31183406	18086604
+58	215	210
+27
+
+chain	3489	6_cox_hap1	4731698	+	3842885	3842952	X	155270560	-	48144545	48144612	19043441
+67
+
+chain	3394	6_cox_hap1	4731698	+	3896482	3896518	X	155270560	-	4545757	4545793	28280414
+36
+
+chain	3393	6_cox_hap1	4731698	+	3840688	3840752	8	146364022	+	7016797	7016861	21522443
+64
+
+chain	3345	6_cox_hap1	4731698	+	1313572	1313633	X	155270560	-	101738888	101738949	11083842
+61
+
+chain	3209	6_cox_hap1	4731698	+	3842526	3842560	4	191154276	+	80147803	80147837	32673071
+34
+
+chain	3189	6_cox_hap1	4731698	+	2790872	2790912	11	135006516	-	131957088	131957128	22905486
+40
+
+chain	3053	6_cox_hap1	4731698	+	4021558	4021590	2	243199373	+	38182694	38182726	24706669
+32
+
+chain	3045	6_cox_hap1	4731698	+	2677533	2677565	11	135006516	-	20509488	20509520	33762261
+32
+
+chain	3033	6_cox_hap1	4731698	+	3842991	3843062	1	249250621	-	90164672	90164743	11203780
+71
+
+chain	2997	6_cox_hap1	4731698	+	2759644	2759694	16	90354753	+	47212776	47212826	11278440
+50
+
+chain	2984	6_cox_hap1	4731698	+	3842575	3842625	X	155270560	+	76422698	76422748	20248077
+50
+
+chain	2960	6_cox_hap1	4731698	+	3896779	3896810	21	48129895	+	18677639	18677670	32477029
+31
+
+chain	2845	6_cox_hap1	4731698	+	2673184	2673214	3	198022430	-	156603737	156603767	26791325
+30
+
+chain	2761	6_cox_hap1	4731698	+	3844406	3844465	6	171115067	+	18547856	18547915	4276868
+59
+
+chain	2745	6_cox_hap1	4731698	+	3842326	3844197	11	135006516	-	48638733	48640605	3968835
+61	675	676
+53	1015	1015
+67
+
+chain	2739	6_cox_hap1	4731698	+	2673924	2673968	8	146364022	+	90457478	90457522	20607564
+44
+
+chain	2729	6_cox_hap1	4731698	+	1302230	1302259	14	107349540	+	79349511	79349540	33029767
+29
+
+chain	2723	6_cox_hap1	4731698	+	2673793	2673825	5	180915260	-	70673106	70673138	18877917
+32
+
+chain	2561	6_cox_hap1	4731698	+	299599	299640	6	171115067	+	20244702	20244743	12574490
+41
+
+chain	2518	6_cox_hap1	4731698	+	4021649	4021704	16	90354753	-	20685134	20685189	24272036
+55
+
+chain	2470	6_cox_hap1	4731698	+	2745980	2746030	1	249250621	+	111776293	111776343	7607561
+50
+
+chain	2373	6_cox_hap1	4731698	+	2760156	2760181	17	81195210	-	66761411	66761436	17362234
+25
+
+chain	2319	6_cox_hap1	4731698	+	2900811	2900837	6	171115067	+	31357660	31357686	3303778
+26
+
+chain	2312	6_cox_hap1	4731698	+	2759490	2759549	4	191154276	+	98204882	98204941	18366184
+59
+
+chain	2209	6_cox_hap1	4731698	+	3843799	3843896	12	133851895	+	60159606	60159703	5400255
+97
+
+chain	2146	6_cox_hap1	4731698	+	1299766	1299827	12	133851895	+	105697047	105697108	23835468
+61
+
+chain	2140	6_cox_hap1	4731698	+	3840491	3840558	6	171115067	-	96829007	96829074	20827044
+67
+
+chain	2000	6_cox_hap1	4731698	+	1313744	1313777	4	191154276	+	153686345	153686378	8134925
+33
+
+chain	1995	6_cox_hap1	4731698	+	3842817	3842864	4	191154276	-	47817470	47817517	17212566
+47
+
+chain	1991	6_cox_hap1	4731698	+	2845315	2845345	4	191154276	-	30046978	30047008	15284842
+30
+
+chain	1990	6_cox_hap1	4731698	+	4008195	4011710	6	171115067	+	32722816	32726965	28700009
+61	2506	2690
+85	515	965
+52	103	103
+193
+
+chain	1943	6_cox_hap1	4731698	+	3844851	3845272	11	135006516	+	83226111	83226530	3906185
+58	323	321
+40
+
+chain	1927	6_cox_hap1	4731698	+	2759609	2759644	7	159138663	-	110094552	110094587	24531071
+35
+
+chain	1727	6_cox_hap1	4731698	+	2674522	2674583	20	63025520	-	53185733	53185794	4777998
+61
+
+chain	1671	6_cox_hap1	4731698	+	3843897	3843947	9	141213431	+	78317603	78317653	4355881
+50
+
+chain	1637	6_cox_hap1	4731698	+	2760272	2760326	2	243199373	+	119859185	119859239	11695157
+54
+
+chain	1632	6_cox_hap1	4731698	+	2673214	2673313	4	191154276	-	69486891	69486990	2834158
+99
+
+chain	1628	6_cox_hap1	4731698	+	3842952	3842991	2	243199373	-	116273698	116273737	14990340
+39
+
+chain	1584	6_cox_hap1	4731698	+	1313851	1313915	1	249250621	-	24961912	24961976	17607390
+64
+
+chain	1548	6_cox_hap1	4731698	+	2672923	2673038	2	243199373	-	193655574	193655689	3516324
+115
+
+chain	1509	6_cox_hap1	4731698	+	2674838	2674895	5	180915260	+	165569524	165569581	2491813
+57
+
+chain	1508	6_cox_hap1	4731698	+	2675985	2676708	6	171115067	-	141365359	141366083	3289535
+50	615	616
+58
+
+chain	1507	6_cox_hap1	4731698	+	2673661	2673741	4	191154276	+	138835824	138835904	16168846
+80
+
+chain	1489	6_cox_hap1	4731698	+	2845209	2846585	X	155270560	-	102215688	102216455	6549884
+27	1297	452
+2	0	236
+50
+
+chain	1467	6_cox_hap1	4731698	+	2760221	2760272	7	159138663	+	122232756	122232807	13147168
+51
+
+chain	1456	6_cox_hap1	4731698	+	3844931	3844983	14	107349540	+	48881293	48881345	9320615
+52
+
+chain	1452	6_cox_hap1	4731698	+	2673321	2674838	X	155270560	-	1098426	1099942	3000529
+51	1428	1427
+38
+
+chain	1354	6_cox_hap1	4731698	+	1313967	1314021	4	191154276	+	544307	544361	14282164
+54
+
+chain	1310	6_cox_hap1	4731698	+	3843714	3843782	X	155270560	+	17249549	17249617	3972308
+68
+
+chain	1307	6_cox_hap1	4731698	+	1498573	1498607	5	180915260	-	156542608	156542642	2089959
+34
+
+chain	1294	6_cox_hap1	4731698	+	2760418	2760473	4	191154276	+	147516497	147516552	12285122
+55
+
+chain	1278	6_cox_hap1	4731698	+	3845015	3845082	15	102531392	+	92125438	92125505	4023305
+67
+
+chain	1247	6_cox_hap1	4731698	+	3844702	3844748	2	243199373	-	7511493	7511539	13743690
+46
+
+chain	1194	6_cox_hap1	4731698	+	2676043	2676103	1	249250621	+	94380187	94380247	20995710
+60
+
+chain	1160	6_cox_hap1	4731698	+	2676209	2676237	X	155270560	+	56836392	56836420	21177535
+28
+
+chain	1125	6_cox_hap1	4731698	+	3890818	3890886	8	146364022	-	86779351	86779419	20749389
+68
+
+chain	1106	6_cox_hap1	4731698	+	2760181	2760221	9	141213431	+	74027839	74027879	13331514
+40
+
+chain	1039	6_cox_hap1	4731698	+	2674441	2674507	3	198022430	-	71498815	71498881	4421669
+66
+
+chain	1033	6_cox_hap1	4731698	+	2676372	2676431	5	180915260	-	20894072	20894131	3124143
+59
+
+chain	1014	6_cox_hap1	4731698	+	2759961	2759990	10	135534747	+	69125589	69125618	23828230
+29
+
+chain	1005	6_cox_hap1	4731698	+	2760005	2760039	10	135534747	+	5299750	5299784	23898321
+34
+
+chain	982	6_cox_hap1	4731698	+	2759426	2759479	13	115169878	+	111326976	111327029	14386536
+53
+
+chain	977	6_cox_hap1	4731698	+	3845410	3845467	X	155270560	-	144584413	144584470	4043690
+57
+
+chain	963	6_cox_hap1	4731698	+	2674253	2676589	9	141213431	-	119032541	119034846	4479982
+47	2231	2200
+58
+
+chain	919	6_cox_hap1	4731698	+	2677255	2677315	4	191154276	+	45112377	45112437	22402156
+60
+
+chain	883	6_cox_hap1	4731698	+	3843656	3843714	18	78077248	+	28929278	28929336	6530663
+58
+
+chain	881	6_cox_hap1	4731698	+	2675038	2675098	5	180915260	-	79225133	79225193	14536118
+60
+
+chain	858	6_cox_hap1	4731698	+	2676338	2676372	7	159138663	-	148564023	148564057	6699557
+34
+
+chain	857	6_cox_hap1	4731698	+	2676103	2677646	4	191154276	+	171430336	171431860	18546235
+50	1412	1393
+81
+
+chain	838	6_cox_hap1	4731698	+	3843947	3843980	18	78077248	-	28720814	28720847	7914761
+33
+
+chain	819	6_cox_hap1	4731698	+	2673062	2673118	2	243199373	+	149156283	149156339	14209631
+56
+
+chain	796	6_cox_hap1	4731698	+	1314021	1314060	X	155270560	-	10752795	10752834	16687246
+39
+
+chain	747	6_cox_hap1	4731698	+	1314275	1314339	12	133851895	+	57178267	57178331	20664563
+64
+
+chain	731	6_cox_hap1	4731698	+	1638596	1638636	15	102531392	+	55738847	55738887	18753864
+40
+
+chain	704	6_cox_hap1	4731698	+	3842767	3842817	9	141213431	+	32212289	32212339	4117535
+50
+
+chain	701	6_cox_hap1	4731698	+	2674653	2674701	16	90354753	-	23821388	23821436	3556080
+48
+
+chain	679	6_cox_hap1	4731698	+	1313640	1313672	21	48129895	-	2887431	2887463	13569070
+32
+
+chain	672	6_cox_hap1	4731698	+	3844325	3844357	10	135534747	-	103351577	103351609	5595826
+32
+
+chain	661	6_cox_hap1	4731698	+	2676159	2676209	9	141213431	+	85388422	85388472	5334226
+50
+
+chain	661	6_cox_hap1	4731698	+	3844987	3845015	2	243199373	+	98215178	98215206	5611311
+28
+
+chain	650	6_cox_hap1	4731698	+	2672375	2672435	7	159138663	-	140047518	140047578	22707410
+60
+
+chain	643	6_cox_hap1	4731698	+	2677085	2677144	6	171115067	+	74793831	74793890	5895430
+59
+
+chain	604	6_cox_hap1	4731698	+	1314169	1314195	X	155270560	-	101522169	101522195	11588450
+26
+
+chain	595	6_cox_hap1	4731698	+	2675343	2675387	12	133851895	-	110550302	110550346	3606052
+44
+
+chain	571	6_cox_hap1	4731698	+	2672827	2672901	3	198022430	+	50956018	50956092	15278850
+74
+
+chain	525	6_cox_hap1	4731698	+	3902955	3903021	6	171115067	+	32474022	32474088	26162225
+66
+
+chain	485	6_cox_hap1	4731698	+	2671938	2671998	1	249250621	-	193322919	193322979	8312425
+60
+
+chain	412	6_cox_hap1	4731698	+	2672740	2672827	8	146364022	-	113140827	113140914	13566503
+87
+
+chain	395	6_cox_hap1	4731698	+	2846505	2846533	X	155270560	-	102216470	102216498	6380381
+28
+
+chain	395	6_cox_hap1	4731698	+	2675098	2675125	12	133851895	+	9999203	9999230	23891782
+27
+
+chain	347	6_cox_hap1	4731698	+	2671704	2671754	15	102531392	-	65978487	65978537	12839282
+50
+
+chain	251	6_cox_hap1	4731698	+	2671761	2671812	9	141213431	+	17677697	17677748	27279073
+51
+
+chain	184	6_cox_hap1	4731698	+	2672526	2672587	X	155270560	-	91681431	91681492	16167874
+61
+
+chain	369716150	6_qbl_hap2	4565931	+	0	4565931	6	171115067	+	28742641	33379750	32
+2350	0	1
+1750	0	2
+3815	1	0
+9743	0	2
+3960	0	4
+2109	0	2
+33	2	0
+9000	0	2
+16647	0	2
+38786	1	0
+80529	0	1
+14475	0	1
+6819	1	0
+6845	1	3
+6188	0	1
+6397	0	1
+345	1	0
+68374	2	0
+39133	39	39
+7774	7	0
+1489	1	1
+72	1	1
+2260	0	2
+10629	0	1
+1249	1	1
+195	1	1
+18132	0	1
+1324	0	2
+5438	5	0
+2061	1	0
+3982	6	6
+1725	0	1
+3153	1	0
+18	1	0
+18	1	0
+2026	1	0
+4175	10	10
+4235	18	18
+493	9	9
+4767	7	7
+1225	1	0
+8	1	1
+151	1	2
+5079	1	1
+28	1	1
+281	11	11
+1178	0	4
+685	8	0
+48	4	0
+1701	1	1
+43	5	5
+862	18	18
+58	1	1
+66	1	1
+420	1	1
+44	1	1
+680	4	4
+1675	1	1
+83	1	1
+3082	4	0
+5467	1	1
+27	0	1
+1099	16	0
+627	51	51
+1278	6	1
+129	1	1
+25	1	1
+1397	15	15
+810	1	1
+27	1	1
+1192	2	0
+7515	4	0
+979	0	3
+3406	0	2
+2340	1	1
+20	1	1
+1139	1	1
+26	1	1
+787	0	1
+1416	3	1
+22815	4	4
+126	1	0
+38	1	1
+140	1	0
+999	0	17
+56	0	15
+11759	161391	161513
+11155	0	2
+5376	0	1
+19253	1	0
+4212	1	1
+3671	1	0
+21	0	6
+4451	1	0
+27910	1	0
+9946	0	1
+11233	1	1
+32	1	1
+2238	1	1
+20	1	1
+3659	22	16
+1218	1	0
+1638	6	6
+228	1	1
+45	1	1
+2048	0	3
+461	1	0
+20759	1	0
+3778	2	1
+1268	1	0
+1511	1	1
+42	2	0
+24	1	1
+4119	22	0
+1757	1	0
+1527	1	1
+29	1	1
+1886	1	0
+10628	12	0
+46568	1	0
+18985	0	10
+1825	3	4
+5288	0	9
+1071	50	50
+1607	1	5
+722	0	1
+502	0	1
+1025	0	1
+134	14	0
+4944	0	1
+319	1	0
+6178	0	1
+2898	0	2
+143	0	1
+1775	1	0
+2123	0	1
+2715	1	0
+4901	70	66
+2884	1	0
+1362	1	0
+1233	0	8
+2134	0	1
+1042	0	1
+163	1	1
+45	1	1
+50	2	0
+64	1	1
+48	1	1
+380	0	1
+30	1	0
+30	1	1
+61	1	1
+22	1	1
+368	4	4
+319	5	7
+310	1	1
+37	3	1
+162	1	1
+194	2	0
+36	1	1
+242	9	9
+1932	1	1
+16	1	1
+528	1	1
+20	1	1
+509	0	5
+76	1	1
+21	1	1
+439	15	15
+2779	1	0
+1597	24	28
+59	12	12
+307	1	0
+516	1	0
+286	11	33
+339	5	0
+570	1	1
+37	1	1
+220	1	0
+72	1	1
+144	1	1
+48	1	1
+247	2	0
+174	9	10
+816	1	0
+940	1	1
+45	1	1
+91	3	3
+71	1	1
+291	14	14
+100	1	1
+23	1	1
+452	3	3
+85	1	1
+65	1	1
+77	1	1
+252	0	1
+129	15	15
+432	10	0
+85	1	1
+28	1	1
+189	2	1
+71	1	1
+52	8	0
+810	2	2
+63	1	1
+378	1	1
+26	1	1
+187	31	36
+966	1	1
+25	1	1
+91	12	12
+125	1	1
+38	1	1
+433	2	0
+596	1	1
+48	1	1
+465	4	4
+64	1	1
+20	1	1
+525	5	5
+237	3	8
+183	11	0
+364	4	3
+201	1	1
+42	1	1
+56	1	1
+115	1	0
+67	16	16
+244	1	1
+54	5	5
+929	1	1
+21	1	1
+126	0	3
+830	1	11
+59	1	1
+537	0	2
+24	1	1
+745	15	15
+810	1	0
+425	1	1
+89	1	1
+592	1	1
+49	1	1
+352	0	1
+142	1	1
+30	1	1
+95	1	1
+45	1	1
+227	1	1
+53	1	1
+130	1	1
+18	1	1
+138	1	1
+90	1	1
+129	41	41
+50	1	1
+79	1	1
+117	1	1
+31	1	1
+155	155	0
+34	1	1
+50	5	5
+57	1	1
+152	1	1
+30	1	1
+177	5	5
+345	1	1
+39	1	1
+504	18	18
+596	12	12
+54	1	1
+158	1	1
+164	1	1
+34	1	1
+626	15	15
+866	0	10
+1051	0	2611
+680	0	1
+1537	0	18
+75	1	0
+147	52	1
+119	0	12
+23	1	1
+1927	13	13
+1702	2	0
+3694	1	1
+18	1	1
+958	43	47
+246	2	0
+146	1	1
+49	1	1
+410	1	0
+667	1	1
+38	1	1
+362	7	1
+159	2	0
+515	2	0
+1026	1	1
+29	1	1
+249	0	6
+129	1	1
+33	4	0
+10	1	5
+1236	1	1
+20	1	1
+138	10	9
+448	0	3
+660	1	1
+28	1	1
+83	1	1
+51	1	1
+2659	1	1
+38	1	1
+424	0	1
+70	1	1
+820	1	1
+26	1	1
+1472	1	1
+21	1	1
+491	5	5
+2372	2	0
+533	6	0
+441	1	7
+1689	1	1
+26	3	4
+879	16	16
+514	0	2
+58	1	1
+350	1	0
+769	1	1
+39	1	1
+429	10	10
+134	0	4
+37	1	1
+144	8	8
+668	1	1
+22	1	1
+344	2	0
+262	2	2
+38	0	1
+70	18	18
+84	11	13
+198	0	1
+32	1	1
+74	11	15
+1255	0	2
+332	1	1
+21	1	1
+193	8	24
+34	1	1
+79	1	1
+29	1	1
+536	1	0
+308	0	1
+850	0	32
+23	1	1
+651	1	1
+22	0	3
+136	1	1
+48	1	1
+330	9	9
+1108	1	1
+98	1	1
+582	0	2
+713	7	7
+89	1	0
+293	9	8
+125	1	1
+31	1	1
+192	6	6
+171	17	17
+681	1	1
+43	1	1
+514	1	1
+68	1	1
+537	1	1
+35	1	1
+159	6	6
+778	2	2
+44	1	1
+168	0	7
+211	1	1
+42	1	1
+1253	1	1
+29	1	1
+320	1	1
+36	2	2
+55	1	2
+108	1	1
+33	1	1
+317	1	1
+35	1	1
+553	8	8
+386	1	1
+26	1	1
+540	1	1
+31	1	1
+65	0	1
+625	12	12
+313	0	1
+52	1	1
+22	1	1
+583	1	1
+49	1	1
+678	37	37
+784	3	0
+838	1	1
+19	12	0
+1129	1	1
+36	1	1
+553	8	8
+109	1	1
+45	1	1
+841	16	15
+157	1	1
+31	2	2
+204	18	19
+487	1	1
+29	1	1
+374	1	1
+67	1	1
+720	13	13
+266	10	10
+330	16	14
+413	1	1
+44	1	1
+78	6	6
+181	2	2
+36	1	1
+397	1	1
+20	1	1
+311	1	1
+48	2	2
+1298	11	11
+186	1	1
+33	1	1
+216	4	4
+35	1	1
+194	10	10
+310	1	1
+51	1	1
+136	1	1
+49	1	1
+521	1	1
+23	1	1
+242	1	1
+49	1	1
+600	1	1
+31	1	1
+413	15	15
+290	1	1
+49	1	1
+527	17	17
+340	12	11
+1025	1	0
+2572	1	1
+29	1	1
+397	2	5
+668	13	13
+541	1	1
+59	0	2
+6	1	1
+122	14	14
+51	1	1
+46	1	1
+72	5	5
+110	1	1
+76	1	1
+164	0	21
+136	1	1
+12	1	1
+66	16	16
+456	37	34
+371	7	7
+48	1	1
+194	10	10
+108	1	1
+60	1	1
+122	0	1
+48	1	1
+238	1	1
+32	0	1
+100	1	0
+72	1	0
+390	1	1
+38	1	1
+144	1	1
+27	0	4
+184	21	228
+49	1	1
+608	0	1
+152	1	1
+31	1	1
+281	8	8
+337	1	1
+45	1	1
+222	1	1
+54	1	1
+346	1	0
+44	1	1
+368	1	1
+72	1	1
+502	36	18
+63	1	1
+43	0	4
+136	1	1
+42	1	1
+80	4	4
+35	1	0
+89	1	1
+24	0	5
+829	13	13
+73	1	1
+28	14	0
+233	1	1
+42	0	3
+85	0	1
+400	1	1
+40	1	1
+538	25	25
+174	1	1
+20	1	1
+705	1	1
+26	2	2
+614	1	1
+44	1	1
+793	1	1
+16	1	1
+747	5	5
+804	1	1
+29	1	1
+166	1	1
+43	1	1
+233	1	1
+44	1	1
+507	0	3
+110	8	8
+133	1	1
+31	1	1
+165	1	1
+29	1	1
+1249	1	1
+26	4	0
+56	1	1
+67	1	1
+716	1	1
+46	0	1
+16	1	1
+174	1	1
+96	1	1
+141	1	1
+39	0	4
+263	1	1
+18	1	1
+259	4	4
+38	1	1
+104	1	1
+40	1	0
+248	1	1
+18	1	1
+238	1	1
+32	1	1
+70	0	2
+16	1	1
+818	1	1
+22	4	4
+492	4	4
+1145	1	1
+46	1	1
+53	1	0
+38	1	1
+373	1	1
+60	1	1
+1149	0	1
+20	1	1
+1294	1	1
+41	1	1
+316	4	4
+42	1	1
+218	12	12
+363	1	1
+24	1	1
+457	10	10
+414	13	13
+825	1	1
+41	1	1
+492	0	4
+1374	1	1
+18	1	1
+808	2	2
+335	6	4
+880	1	1
+35	1	1
+236	1	1
+67	1	1
+298	0	1
+147	4	4
+322	11	11
+613	1	1
+62	1	1
+340	1	1
+22	1	1
+1057	1	1
+57	1	1
+358	1	1
+128	1	1
+146	10	10
+490	1	1
+20	1	1
+62	1	1
+88	1	1
+293	1	1
+28	1	0
+20	1	1
+83	0	1
+90	1	1
+312	1	1
+44	1	1
+1213	1	1
+51	1	1
+467	1	1
+39	1	1
+122	14	0
+35	1	1
+485	14	14
+110	12	0
+127	1	1
+5450	0	5
+1699	9	9
+3278	0	2
+28	1	1
+2211	2	0
+521	1	1
+18	1	1
+784	18	18
+1603	0	248
+4769	47	47
+4486	4	4
+103	0	2
+88	1	1
+95	1	1
+2174	1	1
+22	0	1
+1244	7	7
+922	2	0
+1507	1	1
+44	1	1
+208	6	1
+1946	2	2
+85	0	1
+133	1	1
+666	1	0
+52	1	1
+29	1	1
+148	0	5
+30	1	1
+790	14	14
+52	1	1
+32	1	1
+121	1	1
+37	1	1
+396	3	2
+324	1	1
+152	1	1
+71	4	4
+27	1	1
+115	1	1
+101	1	1
+423	10	10
+294	1	1
+101	1	0
+4	0	1
+174	1	1
+146	1	1
+103	1	1
+134	1	1
+16	1	1
+378	1	1
+85	1	1
+134	1	1
+25	1	1
+54	3	3
+55	1	1
+67	1	1
+22	1	1
+54	13	13
+55	11	11
+120	1	1
+23	1	1
+51	1	1
+22	1	1
+364	1	1
+278	1	1
+354	34448	40149
+311	1	1
+33	1	2
+26	6	6
+474	1	1
+36	1	1
+151	1	1
+29	1	1
+120	1	1
+23	1	1
+865	1	1
+39	1	1
+553	1	1
+69	1	1
+116	1	0
+1618	9	9
+820	11	11
+173	0	8
+405	9	9
+196	1	1
+26	1	1
+173	1	1
+27	5	1
+42	1	1
+676	17	19
+77	1	3
+65	16	16
+69	1	0
+277	1	1
+44	1	1
+72	0	3
+70	1	1
+54	1	1
+240	1	0
+31	1	1
+1192	18	19
+454	28	28
+373	1	1
+46	1	1
+1565	1	1
+53	2	2
+543	1	1
+38	1	1
+985	1	1
+27	0	1
+8	1	1
+158	0	38
+656	1	1
+104	1	1
+771	1	1
+21	1	1
+398	1	1
+16	1	2
+163	4	3
+94	1	1
+44	1	1
+172	1	0
+122	5	5
+193	16	16
+535	2	2
+17	1	0
+93	1	1
+580	1	1
+91	1	1
+141	1	1
+79	1	1
+80	13	13
+165	1	1
+129	1	1
+114	1	1
+30	1	1
+83	1	1
+35	1	1
+126	16	16
+270	0	1
+111	9	9
+151	1	1
+118	1	1
+253	1	1
+45	18468	20220
+102	1	1
+20	1	1
+111	1	1
+97	1	0
+86	1	1
+70	0	4
+69	1	1
+52	0	1
+219	3	3
+76	1	5
+209	4	4
+22	1	1
+61	1	1
+91	1	1
+194	0	21
+15	0	1
+229	1	1
+185	0	1
+113	5	5
+45	1	1
+53	1	1
+37	1	1
+157	1	1
+279	1	1
+233	1	1
+19	0	8
+67	2	0
+41	1	1
+102	12	12
+275	14	14
+70	1	1
+82	2	2
+224	5	1
+490	0	22
+3841	1	0
+3216	1	1
+42	1	1
+1914	0	3
+616	11	12
+144	1	1
+21	2	1
+775	1	1
+50	1	1
+50	2	2
+96	2	2
+1522	4	0
+58	0	2
+1099	1	1
+42	1	1
+3502	0	6
+255	1	1
+40	1	1
+150	0	4
+18	1	1
+589	1	1
+37	1	1
+539	5	5
+354	1	3
+128	1	1
+58	1	1
+159	1	1
+5	2	0
+21	1	1
+231	1	1
+82	3	3
+69	3	0
+549	1	1
+69	1	1
+74	9	9
+126	1	1
+47	1	1
+614	9	9
+138	1	1
+29	1	1
+681	1	1
+49	1	1
+67	1	1
+19	4	9
+234	1	1
+93	1	1
+60	4	4
+96	4	4
+76	1	1
+169	1	1
+418	1	1
+130	1	1
+44	1	1
+69	1	1
+80	1	1
+76	1	1
+41	1	1
+129	6	11
+363	1	1
+42	1	1
+295	1	1
+43	1	1
+83	6	0
+52	0	2
+1228	1	1
+34	1	1
+3527	20	0
+1768	2	1
+2467	0	2
+101	10	0
+129	1	1
+37	1	1
+121	1	1
+25	1	1
+161	1	0
+97	1	1
+124	1	0
+178	1	1
+34	1	1
+54	1	1
+38	1	2
+634	83	83
+874	1	1
+40	1	1
+59	0	1
+59	4	4
+316	1	1
+178	1	1
+103	1	1
+61	1	1
+220	1	1
+61	1	1
+296	1	1
+33	1	1
+185	12	12
+269	1	1
+84	1	1
+864	15	15
+241	1	0
+79	3	3
+161	1	1
+48	1	1
+539	1	1
+44	1	1
+357	1	1
+37	1	1
+436	1	1
+59	1	1
+71	1	1
+261	1	1
+289	1	1
+47	1	1
+95	12	12
+97	4	4
+27	1	1
+100	1	1
+16	1	1
+101	1	1
+33	1	2
+481	1	1
+42	1	1
+206	7	7
+56	12	12
+179	10	10
+80	1	1
+41	1	1
+251	1	1
+306	1	1
+80	2	0
+4	94	0
+433	1	1
+23	1	1
+107	1	0
+265	1	1
+49	1	1
+282	72	72
+838	7	7
+60	1	0
+108	1	1
+24	1	1
+134	1	1
+32	1	0
+158	0	2
+1040	1	1
+42	1	1
+737	1	0
+790	1	1
+9	2	1
+11	1	1
+129	1	1
+23	1	1
+894	1	1
+43	3	3
+854	1	1
+23	0	1
+23	2	0
+26	1	1
+395	0	15
+403	5	5
+14	1	1
+2454	1	1
+76	1	1
+170	1	1
+18	1	1
+574	4	0
+291	1	1
+47	1	1
+786	19	0
+88	10	11
+48	1	1
+58	1	1
+28	1	1
+500	0	2
+1280	1	1
+28	1	1
+975	1	0
+3231	1	0
+865	1	1
+39	1	1
+1561	109	100
+1037	0	1
+510	1	1
+49	1	1
+1253	1	1
+19	1	1
+1078	3	0
+221	1	1
+21	1	0
+899	0	4
+466	1	1
+38	1	1
+297	0	3
+730	19	6
+1043	1	1
+49	1	1
+273	0	1
+708	1	0
+364	14	13
+58	1	1
+74	1	1
+614	60	60
+1889	4	0
+531	1	1
+19	1	1
+1944	5	0
+163	6	7
+1206	0	2
+718	1	1
+41	7	0
+1795	13	13
+1390	1	0
+2933	0	16
+540	1	1
+14	1	1
+167	1	0
+897	17	4
+1208	1	0
+1307	1	1
+20	1	1
+540	0	10
+203	2	0
+44	1	1
+298	1	0
+87	11	10
+491	14	8
+991	1	1
+74	6	0
+179	1	1
+34	1	1
+448	10	0
+1688	1	1
+38	21	0
+173	1	1
+49	2	1
+2161	30	30
+203	1	0
+89	1	0
+492	1	1
+30	1	1
+1212	3	0
+990	1	1
+38	1	1
+780	1	0
+191	1	1
+47	6	6
+393	1	1
+41	1	1
+259	1	0
+941	1	1
+20	1	1
+185	0	6
+165	0	16
+420	3	1
+130	1	1
+31	1	1
+253	18	18
+720	16	18
+1257	3	0
+986	0	4
+3311	1	1
+26	1	1
+556	0	4
+120	0	1
+1273	1	1
+20	1	1
+338	8	8
+3965	0	3
+15	1	1
+2531	17	17
+3334	5	5
+121	13	13
+161	1	1
+45	1	1
+94	14	14
+63	9	10
+2108	1	1
+34	1	1
+1436	1	1
+47	1	1
+273	7	0
+153	0	5
+283	12	12
+619	1	1
+36	0	4
+225	1	1
+23	1	1
+553	5	0
+2334	1	1
+49	1	1
+350	1	1
+31	1	1
+1012	2	2
+422	1	1
+46	1	1
+91	4	19
+468	0	1
+46	1	1
+1491	0	4
+426	0	1
+1144	1	2
+1131	1	1
+20	1	1
+1533	16	0
+3103	44	45
+4016	12	12
+346	0	1
+943	1	0
+524	1	1
+20	1	1
+151	3	3
+144	1	1
+189	1	7
+750	1	0
+695	1	0
+1003	0	2
+7819	1	1
+78	1	1
+1811	0	1
+3177	0	1
+8990	0	1
+2268	1	1
+35	0	10
+8205	1	0
+3193	1	1
+76	1	1
+10955	0	1
+22875	0	20
+2417	1	0
+998	0	13
+4236	8	0
+4845	0	2
+64	40	34
+10941	1	1
+40	1	1
+4759	0	6
+12084	0	3
+3052	0	4
+2989	1	0
+13523	1	3
+16170	1	0
+11761	0	3
+3912	3	0
+6620	0	7
+7633	3	0
+419	2	0
+10690	5	24
+10798	0	1
+296	0	1
+1770	4	0
+374	0	4
+230	16	16
+7468	1	0
+1229	1	0
+3061	1	0
+5818	1	0
+2415	12	9
+2056	0	1
+955	4	0
+20022	0	1
+4418	2	1
+2375	0	4
+2086	1	1
+32	1	1
+1225	1	0
+857	2	0
+1154	0	1
+4667	1	0
+170	0	3
+2376	0	1
+2799	10	10
+1512	4	0
+68	9	1
+2170	1	1
+47	1	1
+318	2	0
+19	0	6
+14527	1	1
+33	1	1
+3080	1	1
+23	1	1
+1645	6	6
+231	0	1
+2136	2	0
+6222	0	1
+830	1	1
+24	1	1
+8326	1	0
+2939	1	0
+3959	0	2
+3746	0	2
+1011	1	1
+34	1	1
+7443	0	1
+688	2	0
+574	1	1
+29	1	1
+1799	13	1
+4074	2	0
+136	1	1
+77	1	1
+528	19	0
+253	0	1
+204	1	0
+129	2	0
+811	1	1
+38	1	1
+2347	52	0
+4634	1	0
+856	14	14
+193	0	4
+855	1	1
+28	1	1
+1255	1	1
+36	1	1
+97	0	1
+58	1	1
+1708	1	1
+48	1	1
+958	15	0
+3371	1	1
+37	1	1
+4267	0	13
+1061	0	1
+272	0	26
+8	1	15
+25	0	2
+112	2	0
+26	4	32
+4090	0	1
+3270	1	1
+17	1	1
+2822	0	1
+6206	1	0
+2318	0	2
+1504	0	1
+6189	3	0
+396	22	12
+918	0	1
+2340	1	1
+33	1	1
+326	1	1
+80	1	1
+205	3	2
+81	8	17
+2671	0	1
+1099	0	1
+144	1	1
+29	0	1
+2097	0	3
+24	3	0
+1207	4	4
+45	1	1
+757	0	5
+1926	1	1
+40	1	1
+2657	0	1
+414	1	0
+61	0	1
+235	0	2
+2087	0	1
+713	0	4
+58	3	0
+1027	3	0
+428	1	1
+17	1	1
+948	1	1
+41	1	1
+458	1	1
+21	1	1
+1055	0	1
+6611	0	3
+1575	4	5
+36	1	1
+99	2	0
+700	0	2
+151	0	1
+467	11	11
+272	0	3
+40	1	1
+2428	0	1
+750	2	0
+473	0	2
+421	1	1
+34	1	1
+1575	1	0
+3841	1	0
+560	1	0
+1108	1	0
+8087	1	0
+11881	1	1
+30	1	1
+4383	2	0
+6883	49	49
+3146	0	1
+906	3	0
+887	1	1
+80	1	1
+3115	0	1
+1037	1	0
+5866	0	2
+18	1	1
+582	0	5
+2828	1	0
+847	1	0
+1996	3	0
+3170	1	0
+1751	0	1
+910	3	0
+691	0	1
+5793	0	1
+26407	1	0
+672	0	1
+19269	29	35
+1371	29	0
+494	2	0
+20417	1	0
+18633	0	1
+601	1	0
+319	0	1
+6820	1	0
+5718	0	2
+17894	1	0
+4272	1	0
+4967	3	1
+290	1	0
+2447	1	0
+740	1	9
+9299	0	18
+7427	1	0
+8151	2	1
+673	1	0
+3453	0	1
+149	0	1
+611	0	4
+4662	0	4
+1752	1	1
+78	1	1
+1581	0	1
+1092	2	0
+159	1	0
+4480	0	2
+4019	0	1
+1451	22	23
+816	1	0
+8701	1	1
+23	1	1
+1796	2	0
+5015	6	1
+1383	8	0
+2368	1	1
+31	1	0
+1883	3	0
+335	0	1
+4157	0	1
+561	4	0
+1538	1	1
+61	0	1
+159	0	2
+3362	4	0
+3333	1	1
+46	1	1
+2307	1	0
+170	1	0
+5972	0	2
+840	0	2
+55	1	1
+28	1	1
+1154	0	2
+650	0	4
+30	0	4
+1100	10	11
+4343	6	0
+1663	4	0
+150	1	0
+3128	1	0
+1449	1	0
+2023	0	1
+428	3	6
+299	2	0
+427	7	7
+1914	14	14
+1273	7	7
+1444	72	0
+423	0	4
+954	1	0
+2467	1	0
+190	8	8
+2034	3	1
+6396	1	1
+34	1	1
+485	1	0
+348	7	0
+770	1	1
+29	0	13
+65	1	1
+1358	0	1
+302	0	1
+659	12	12
+293	0	1
+610	0	1
+906	12	0
+1331	0	6
+1786	0	1
+463	0	1
+4305	0	4
+1041	1	0
+11424	3	1
+13797	0	8
+166	0	1
+1510	5	0
+9069	0	8
+25	1	1
+332	5	3
+76	0	1
+1306	1	1
+46	1	1
+134	19	23
+1467	1	1
+32	1	1
+449	17	0
+367	9	9
+3525	12	10
+91	3	0
+1430	1	1
+24	1	1
+1156	9	13
+843	1	1
+28	1	1
+515	0	17
+1559	0	4
+1045	9	9
+1953	1	0
+31	1	1
+843	0	1
+2174	1	0
+3788	1	0
+2001	0	1
+2400	0	1
+1614	1	0
+8167	0	1
+2700	2	0
+2735	0	1
+8508	1	1
+57	1	1
+141	0	3
+448	1	1
+22	1	1
+2215	1	1
+32	1	1
+1714	32	32
+667	14	14
+142	1	0
+789	1	1
+45	1	1
+84	1	1
+95	1	1
+465	1	1
+45	6	4
+541	1	1
+42	1	1
+1339	5	6
+391	1	1
+20	0	1
+251	1	1
+22	1	1
+561	0	2
+78	3	0
+1718	1	1
+12	1	1
+1042	1	1
+38	1	1
+301	14	0
+222	10	10
+436	10	10
+556	55	55
+953	1	1
+17	1	1
+1752	20	0
+1561	135	0
+58	0	45
+245	101	11
+46	90	0
+150	0	270
+54	180	0
+2130	12	12
+1630	1	1
+26	1	1
+189	0	14
+296	2	0
+809	2	0
+17	20	0
+665	0	40
+236	1	1
+44	1	1
+352	1	1
+25	1	1
+554	6	6
+850	1	1
+33	1	1
+809	3	13
+1832	7	9
+468	1	1
+21	1	1
+951	1	1
+22	1	1
+219	17	18
+733	0	14
+215	2	2
+36	1	1
+301	1	1
+22	1	1
+241	1	1
+52	0	1
+47	1	1
+72	1	1
+109	1	1
+129	1	1
+28	1	1
+174	8	8
+683	3	0
+1190	285	0
+48	1	1
+1330	12	0
+557	17	17
+932	3	1
+27	1	1
+166	1	1
+19	1	1
+406	1	1
+48	3	3
+137	1	0
+161	6	6
+884	2	0
+58	1	1
+107	1	1
+150	14	14
+522	1	1
+28	1	1
+945	4	4
+34	1	1
+472	0	2
+203	0	1
+281	1	1
+46	1	1
+1130	1	0
+232	17	17
+510	1	1
+33	1	1
+62	10	10
+1501	1	1
+20	1	1
+573	1	1
+29	1	1
+928	0	3
+304	1	1
+41	1	1
+160	1	1
+58	1	1
+656	1	1
+40	4	0
+108	6	6
+321	1	1
+14	0	16
+91	1	1
+184	1	1
+43	8	3
+180	1	1
+68	1	1
+144	1	1
+27	1	0
+17	1	1
+212	0	1
+212	1	1
+34	1	1
+115	1	1
+41	1	1
+407	10	10
+200	1	1
+44	2	0
+187	2	0
+146	1	1
+17	1	1
+122	4	4
+73	1	0
+56	1	1
+155	1	17
+80	15	15
+458	1	1
+16	3	3
+343	1	1
+111	1	1
+160	55	55
+157	12	12
+346	0	2
+382	4	0
+35	1	1
+937	0	1
+246	25	0
+52	0	1
+419	0	1
+165	1	0
+75	24	3
+297	1	1
+38	1	1
+5066	1	0
+4922	7	9
+2488	14	14
+2241	1	1
+67	4	4
+39	1	0
+547	1	1
+43	1	1
+524	3715	901
+1796	4	2
+138	2	2
+16	1	1
+415	1	1
+18	1	1
+367	0	89
+1600	0	6
+2175	0	5
+606	14	14
+519	1	0
+540	1	1
+40	1	1
+568	2	0
+165	1	2
+31	1	1
+259	1	1
+41	1	1
+452	31	31
+623	40	62
+818	1	1
+42	1	1
+565	1	1
+44	1	1
+571	10	8
+61	1	1
+28	1	1
+233	2	0
+33	28	0
+53	1	1
+37	1	1
+75	0	396
+156	1	0
+473	0	4
+421	1	1
+35	1	1
+2132	1	1
+80	0	2
+544	9	9
+152	2	1
+33	1	1
+2932	1	1
+44	0	1
+164	22	0
+149	1	0
+534	1	1
+36	1	1
+113	1	1
+15	1	1
+661	1	1
+48	1	1
+1987	1	0
+34	1	1
+444	1	1
+45	1	1
+65	1	1
+67	1	1
+210	1	1
+68	1	1
+55	1	1
+47	1	1
+169	1	1
+64	1	1
+109	0	6
+77	2	32
+6	0	5
+67	0	1
+7	16	0
+51	12	0
+36	0	12
+700	1	1
+33	1	0
+49	0	2
+450	0	1
+98	4	0
+489	32	0
+63	5	1
+78	7	7
+538	17	17
+1269	1	0
+841	1	1
+43	1	1
+2004	1	1
+41	1	1
+86	0	4
+5	1	0
+36	1	1
+573	2	1
+297	1	0
+85	1	1
+30	1	1
+1041	1	0
+12	1	1
+392	33	12
+515	5	6
+583	1	1
+33	1	1
+616	16	16
+1052	0	11
+39	1	1
+184	1	1
+67	1	1
+102	7	7
+58	0	1
+307	1	1
+56	0	3
+930	21	19
+1264	0	1
+832	1	1
+28	1	1
+272	1	1
+82	1	1
+56	1	0
+976	6	6
+2015	0	3
+84	9	9
+130	13	17
+564	10	15
+154	1	0
+438	10	10
+38	0	5
+2141	1	1
+25	1	1
+73	10	10
+70	5	5
+132	1	1
+52	1	1
+599	1	1
+46	1	1
+279	1	1
+18	1	1
+239	2	0
+383	6	0
+224	0	1
+321	3	0
+8	16	0
+1775	1	1
+18	2	0
+575	16	16
+60	1	1
+16	1	1
+1247	2	0
+173	3	0
+41	1	1
+57	8	8
+285	2	0
+672	1	1
+44	1	1
+106	0	1
+148	1	1
+49	3	0
+146	5	11
+91	1	1
+79	1	1
+94	1	1
+101	1	1
+88	16	16
+117	1	1
+15	1	1
+58	1	1
+93	1	1
+140	1	0
+326	1	1
+44	1	1
+160	1	1
+23	1	1
+481	14	14
+181	4	4
+72	1	1
+25	1	1
+88	1	3
+36	0	12
+92	1	1
+56	10	0
+13	0	1
+66	1	1
+141	2	0
+65	1	1
+367	0	2
+610	1	1
+22	1	1
+150	1	1
+85	1	1
+109	1	1
+167	3	1
+23	1	0
+26	1	1
+74	1	1
+33	1	1
+176	1	1
+25	2	2
+193	1	1
+35	0	1
+383	0	5
+249	1	1
+69	1	1
+98	1	1
+62	1	1
+62	1	2
+74	0	1
+68	1	1
+438	1	1
+64	1	1
+47	0	8
+125	3	0
+75	5	5
+45	1	1
+197	1	1
+27	1	1
+116	13	13
+218	15	20
+1107	16	19
+73	1	1
+25	1	1
+199	1	1
+60	1	1
+994	1	1
+43	0	1
+18	1	1
+1215	18	18
+340	1	1
+34	1	1
+1350	16	16
+1726	4	4
+193	1	1
+48	1	1
+295	1	1
+18	1	1
+411	19	19
+175	1	1
+49	1	1
+146	1	1
+61	1	1
+116	1	1
+41	1	1
+137	1	1
+30	1	1
+158	9	9
+136	10	13
+349	8	8
+468	1	1
+44	1	1
+862	17	17
+813	1	1
+24	1	1
+214	10	4
+228	1	1
+34	1	1
+101	12	12
+242	1	1
+69	1	1
+185	1	1
+24	1	0
+164	0	1
+222	1	1
+25	1	1
+297	10	10
+1171	1	0
+182	1	1
+35	1	1
+350	19	19
+1966	1	1
+24	1	1
+548	7	7
+208	13	12
+298	1	1
+65	1	1
+193	2	2
+28	1	1
+125	4	4
+95	7	7
+566	1	1
+40	1	1
+118	0	1
+318	1	0
+374	1	1
+58	1	1
+143	1	1
+74	1	1
+53	21	0
+81	1	1
+45	1	1
+138	15	16
+180	1	1
+62	1	1
+661	1	1
+48	1	1
+1463	1	0
+156	0	1
+148	1	1
+19	1	0
+17	1	1
+1927	4	0
+1469	14	14
+466	0	1
+3098	0	1
+1141	2	3
+743	14	14
+79	1	1
+22	1	1
+362	0	1
+682	16	9
+275	0	4
+539	1	0
+61	0	7
+331	0	4
+130	1	1
+31	0	3
+1554	1	1
+43	1	1
+224	1	1
+49	1	1
+159	3	0
+1064	27	27
+104	1	1
+21	1	1
+222	2	2
+49	1	1
+1397	1	1
+37	1	1
+414	0	2
+695	1	1
+31	1	1
+742	1	1
+21	1	1
+230	3	2
+42	1	1
+68	1	1
+37	1	1
+703	0	3
+2216	84	83
+1430	1	1
+23	1	1
+1867	13	0
+35	1	1
+137	16	16
+1500	4	0
+4546	1	1
+25	1	1
+358	19	19
+1549	1	1
+39	4	3
+1037	1	1
+40	2	0
+890	6	0
+41	2	0
+498	3	0
+321	0	1
+281	3	0
+414	1	1
+70	1	1
+284	1	0
+214	1	1
+28	1	1
+280	1	0
+650	1	1
+47	1	1
+1030	1	1
+91	1	1
+6520	5	5
+462	1	0
+2864	0	3
+1930	0	4
+2915	1	1
+20	1	1
+413	1	0
+1844	11	11
+133	0	6
+569	10	10
+110	12	12
+184	0	3
+228	1	1
+43	2	2
+51	14	13
+1499	1	0
+12	1	1
+378	1	1
+49	1	1
+424	1	0
+1069	1	1
+142	0	1
+821	2	9
+311	1	6
+247	1	1
+86	1	1
+1850	1	1
+26	1	1
+498	1	1
+34	1	1
+688	5	9
+44	1	1
+369	1	1
+69	1	1
+156	2	0
+83	1	1
+128	1	1
+50	9	9
+249	1	1
+70	0	1
+624	2	0
+74	2	1
+300	1	1
+26	1	1
+240	4	0
+1705	1	1
+52	1	1
+231	29	24
+378	2	0
+236	1	1
+76	1	1
+116	9	12
+301	20	20
+59	0	6
+43	1	1
+384	15	15
+1414	5	0
+225	0	2
+1234	1	0
+29	1	1
+235	10	10
+227	1	1
+77	4	0
+43	5	9
+485	7	7
+380	10	0
+46	1	0
+90	1	1
+161	1	1
+401	1	1
+58	1	1
+2127	3	0
+186	20	20
+323	5	5
+47	1	1
+236	1	1
+31	0	2
+1568	1	1
+136	0	1
+202	0	3
+77	1	1
+44	1	1
+411	12	11
+317	0	2
+599	1	1
+37	1	1
+391	1	0
+273	1	0
+744	0	4
+703	1	1
+20	1	1
+198	3	0
+158	19	15
+27	12	0
+282	1	1
+32	4	0
+740	1	0
+327	1	1
+105	1	1
+146	16	16
+101	1	0
+21	1	1
+232	1	1
+33	2	0
+12	1	1
+189	1	1
+30	2	2
+544	1	1
+153	1	1
+586	5	0
+1351	21	0
+446	49	49
+121	7	7
+1147	12	12
+777	1	0
+701	1	1
+29	2	2
+154	12	12
+191	1	1
+55	1	1
+113	0	1142
+87	0	2
+15	0	1
+525	1	1
+22	1	1
+355	10	10
+50	0	8
+252	1	1
+31	1	1
+354	6	5
+148	15	15
+407	1	1
+42	1	1
+275	0	1
+737	5	9
+1432	1	1
+39	1	1
+84	0	2
+77	7	7
+514	20	20
+385	7	1
+815	1	1
+45	1	1
+487	1	1
+66	1	1
+2379	0	24
+779	1	1
+18	1	0
+2653	4	0
+34	1	1
+191	1	1
+35	1	1
+1174	12	0
+2497	1	1
+24	0	1500
+447	8	0
+3268	1	0
+946	1	0
+2223	20044	20060
+119	1	1
+71	0	3
+53	0	5
+40	1	1
+309	1	1
+57	1	1
+101	1	1
+47	2	2
+67	1	1
+47	1	1
+74	0	1
+28	1	1
+167	1	1
+33	1	1
+543	1	1
+27	11	34
+33	1	1
+149	7	7
+61	1	1
+120	1	1
+366	1	1
+55	1	1
+121	1	1
+62	1	1
+78	1	1
+48	1	1
+161	1	1
+26	1	1
+191	1	1
+20	11	11
+550	1	1
+76	1	0
+20	1	1
+112	1	1
+149	1	1
+284	1	1
+37	1	1
+705	1	12
+106	12	12
+83	1	1
+46	1	1
+1500	1	1
+81	1	1
+210	1	1
+26	1	1
+713	1	1
+48	1	1
+723	0	3
+196	6	6
+62	2	2
+32	1	1
+606	1	2
+357	1	1
+38	292	0
+589	1	1
+30	1	1
+714	8	8
+639	1	1
+20	1	1
+1068	0	1
+571	1	1
+49	1	1
+436	0	1
+609	0	2
+30	1	1
+66	0	1
+349	11	11
+65	1	1
+40	1	1
+717	0	3
+299	1	1
+29	1	1
+724	1	0
+275	1	1
+33	1	1
+318	0	3
+279	1	1
+28	1	1
+389	1	0
+548	0	8
+330	1	1
+47	1	1
+170	1	1
+47	1	1
+519	14	14
+841	24	24
+732	1	1
+29	3	3
+688	2	2
+23	0	1
+94	14	14
+726	13	13
+508	0	12
+21	6	0
+69	1	1
+37	1	1
+590	1	1
+59	1	1
+89	11	11
+164	1	1
+58	1	1
+1709	18	18
+520	1	1
+27	1	1
+683	10	10
+814	1	1
+26	1	1
+350	1	1
+39	1	1
+132	6	6
+439	10092	10075
+78	15	15
+3352	1	1
+23	1	1
+873	4	4
+887	1	0
+1827	1	0
+216	6	6
+805	2	0
+874	0	8
+2266	1	1
+47	1	1
+761	0	4
+86	1	1
+19	1	1
+1794	9	9
+271	0	1
+2266	1	1
+34	1	1
+916	0	1
+21	1	1
+108	21	21
+141	1	1
+27	1	1
+406	3	0
+3950	1	1
+38	1	1
+128	2	2
+56	1	1
+72	0	1
+96	1	1
+22	1	1
+169	7	7
+511	1	1
+38	1	1
+1070	1	1
+90	1	1
+50	1	1
+41	1	0
+30	1	1
+659	12	12
+701	1	1
+33	1	1
+569	15	15
+70	1	1
+38	1	1
+955	0	3
+130	1	1
+63	1	1
+251	8	8
+191	1	1
+26	0	3
+187	1	0
+916	5	1
+70	13	13
+498	20061	20021
+160	1	1
+76	1	1
+95	1	1
+76	1	1
+275	1	0
+101	1	1
+79	1	1
+100	7	7
+159	1	1
+75	0	8
+87	1	1
+76	1	1
+44	1	1
+71	32	32
+89	11	12
+196	1	1
+55	0	2
+61	1	1
+83	0	1
+944	1	1
+126	1	1
+81	6	6
+41	3	0
+641	1	1
+92	1	0
+113	1	1
+39	1	1
+671	1	1
+28	1	1
+123	1	1
+59	1	1
+210	1	1
+17	1	1
+168	15	14
+494	1	0
+22	1	1
+484	18	18
+376	1	1
+114	2	0
+67	1	1
+10	1	1
+109	1	1
+165	1	1
+149	6	6
+234	1	1
+19	5	5
+64	1	1
+111	1	1
+220	1	1
+89	1	1
+119	1	1
+113	2	0
+168	1	1
+73	1	1
+194	1	1
+50	0	4
+37	1	1
+95	3	1
+43	1	1
+153	1	1
+83	1	1
+55	1	1
+39	1	1
+70	7	0
+59	7	7
+75	1	1
+84	2	2
+110	1	0
+42	1	1
+129	9978	10000
+438	1	1
+43	1	0
+55	1	1
+40	1	1
+175	1	1
+46	1	1
+52	1	1
+19	1	1
+277	1	1
+60	1	1
+98	1	1
+24	1	1
+333	4	4
+1047	2	0
+4080	1	1
+38	1	1
+837	0	64
+172	1	1
+55	1	1
+1818	2	0
+1143	13	13
+335	1	0
+1944	5	0
+39	6	0
+4057	3	8
+9465	5	4
+301	19	1
+191	84	0
+427	1	1
+29	0	4
+157	4	5
+296	21	18
+158	2	2
+36	1	1
+539	13	13
+399	1	1
+46	1	1
+348	1	1
+49	1	1
+268	1	0
+66	0	4
+178	2	2
+107	1	1
+133	5	5
+355	1	1
+30	1	1
+346	1	1
+29	1	1
+161	1	1
+38	1	1
+121	4	4
+55	8	8
+67	7	7
+318	17	17
+259	1	1
+94	1	1
+80	1	1
+35	1	1
+260	1	1
+81	1	1
+106	1	1
+58	1	2
+301	3	0
+2052	1	1
+40	1	1
+174	20	22
+574	0	2
+414	1	0
+234	0	1
+425	51224	51060
+1568	14	14
+11956	0	1
+2667	0	2
+884	1	1
+19	1	1
+676	1	1
+63	1	1
+3138	0	3
+3038	5	2
+132	10	6
+136	18	13
+363	1	1
+89	1	1
+382	1	1
+29	1	1
+58	8	7
+297	4	0
+66	1	1
+93	2	0
+145	1	1
+31	5	5
+576	1	1
+89	1	1
+1256	0	12
+67	1	1
+193	2	2
+23	1	1
+51	1	0
+727	1	0
+1148	12	12
+837	1	1
+77	1	1
+941	10	10
+776	19	19
+300	1	1
+24	1	1
+256	1	7
+93	1	1
+224	2	0
+138	1	1
+563	1	1
+104	4	4
+2898	1	1
+46	1	1
+282	1	1
+39	1	1
+204	2	2
+22	1	1
+469	1	1
+20	1	1
+140	1	1
+26	1	1
+745	0	2
+539	0	6
+1536	1	0
+817	4	4
+202	1	1
+48	1	1
+168	1	1
+53	1	1
+379	10	10
+1178	14	14
+132	5	0
+555	1	1
+42	1	1
+573	1	1
+21	1	1
+462	1	1
+43	1	1
+121	1	1
+48	0	3
+15	1	5
+1404	0	1
+934	1	1
+49	1	1
+1350	1	0
+384	1	1
+24	1	1
+4169	0	15
+244	10	10
+2167	18	14
+64	1	1
+31	1	1
+185	0	4
+1647	1	1
+20	1	1
+227	1	1
+37	1	1
+636	3	4
+5590	1	1
+39	1	1
+461	0	2
+2145	1	1
+23	1	1
+1114	0	2
+688	0	1
+901	18	18
+4781	0	4
+815	0	1
+5027	42	47
+415	0	1
+2743	1	1
+78	1	1
+390	1	0
+328	0	1
+878	0	1
+5752	0	2
+1554	1	1
+60	1	1
+278	0	1
+19	1	1
+1164	11	11
+691	0	2
+960	1	0
+62	0	20
+2108	0	2
+1265	0	1
+1642	2	0
+3584	2	0
+12086	2	0
+3766	0	2
+1209	1	7
+3466	1	0
+1448	1	0
+1943	0	1
+698	0	8
+1166	135	135
+2030	2	0
+540	1	0
+1736	14	0
+3128	0	2
+4464	0	1
+3597	1	0
+378	1	0
+1269	0	3
+1182	1	0
+654	0	3
+2049	1	0
+6838	1	1
+69	0	3
+154	1	0
+2718	1	1
+30	1	1
+160	11	11
+4954	0	1
+420	1	1
+123	1	1
+156	0	4
+219	4	0
+195	1	0
+4402	3	0
+3045	0	1
+1249	1	0
+3522	0	10
+675	20	20
+117	8	0
+346	0	1
+8538	5	0
+455	1	0
+119	0	1
+355	48	48
+724	1	0
+9254	22	22
+1672	1	0
+833	0	1
+4251	1	0
+8	1	1
+2079	0	1
+1735	8	12
+1612	0	1
+1373	5	0
+8585	7	0
+64	1	1
+3799	1	0
+258	2	0
+899	1	0
+1362	8	9
+593	0	2
+3351	2	0
+618	0	4
+905	2	15
+2797	1	0
+2776	2	0
+4110	0	6
+4466	18	18
+1783	9	9
+475	0	4
+134	1	0
+12963	8	0
+1616	0	2
+1685	2	0
+2225	2	0
+428	0	1
+458	20	20
+2860	0	3
+677	4	6
+325	11	1
+1887	0	1
+913	0	1
+997	5	5
+2814	17	15
+1389	1	0
+1200	0	4
+2495	1	0
+3921	26431	26426
+2419	0	1
+6110	0	1
+1370	0	1
+3085	1	0
+3568	1	1
+24	0	9
+597	1	0
+2642	1	0
+1545	10	0
+4952	0	1
+6146	2	0
+1452	1	0
+2967	1	0
+4920	5	0
+147	4	5
+850	1	0
+1875	1	0
+695	3	1
+1719	0	1
+259	0	1
+294	1	0
+128	0	2
+3051	0	1
+908	0	4
+3399	0	1
+4673	1	0
+3179	1	0
+411	1	1
+44	1	1
+174	1	0
+1047	17	17
+998	178	0
+671	0	40
+2093	1	0
+313	0	1
+7581	1	0
+3245	1	0
+972	0	4
+4085	2	0
+346	1	1
+45	1	1
+368	1	0
+26	1	1
+8444	0	1
+17044	1	0
+2795	2	0
+2860	1	0
+622	0	1
+167	0	5
+1968	0	2
+259	2	0
+4992	29	27
+170	1	0
+3528	0	1
+191	1	2
+117	2	0
+2275	1	0
+12676	1	1
+20	1	1
+9972	1	0
+13955	0	5
+19867	1	0
+9612	1	0
+14233	0	32737
+6316	1	1
+19	1	1
+970	8	8
+2685	16	16
+18093	0	1
+6799	0	16
+3350	0	1
+7574	0	12
+2132	0	1
+7228	52793	52800
+1955	22	22
+698	0	1
+2149	1	0
+6880	0	2
+960	0	1
+23	1	1
+2646	2	0
+3867	5	0
+26077	0	3
+3174	1	0
+8183	0	1
+2817	10	0
+5841	1	0
+2081	0	1
+374	0	2
+3589	0	4
+10625	28	28
+3275	3	0
+773	7	7
+175	1	1
+79	1	1
+400	12	12
+1096	0	4
+717	7	7
+52	1	1
+68	5	1
+2117	0	3
+130	14	14
+1124	0	3
+413	0	4
+643	3	0
+58	1	1
+127	1	1
+196	0	2
+226	3	0
+136	3	4
+293	1	1
+25	0	3
+63	1	1
+417	0	2
+412	0	16
+737	4	0
+402	2	0
+654	1	1
+42	1	1
+75	1	1
+64	1	1
+2980	4	0
+576	0	1
+29	2	2
+715	1	1
+36	1	1
+511	38	38
+218	4	40
+44	1	5
+43	49	5
+709	21	21
+1147	9	9
+22	1	1
+195	7	4
+659	3	0
+27	1	1
+637	1	1
+42	1	1
+531	1	1
+67	1	1
+39	1	0
+717	11	11
+53	1	1
+61	1	1
+1535	1	1
+89	0	1
+49	1	0
+102	1	1
+67	1	1
+76	1	1
+129	1	1
+85	1	1
+607	10	0
+12	137	1
+41	1	1
+1043	1	1
+22	1	1
+203	3	0
+480	14	21
+91	23	23
+1345	2	1
+435	15	17
+1188	30	0
+1778	1	0
+120	0	3
+3797	1	0
+3211	0	1
+2456	4	0
+954	0	4
+1847	0	1
+5929	20	20
+984	14	0
+2112	1	0
+2013	1	0
+1770	14	14
+3100	1	0
+1160	16	0
+733	7	7
+238	3	2
+2203	2	1
+5654	1	1
+28	5	10
+482	0	1
+2970	0	4
+2892	0	1
+251	1	7
+1346	1	0
+877	0	4
+3583	0	1
+1178	0	1
+1293	0	2
+491	2	0
+6803	1	1
+22	1	1
+2218	1	1
+44	1	1
+4780	4	0
+3026	14	13
+442	5	5
+2022	6	6
+506	2	0
+8557	1	1
+36	1	0
+1575	1	0
+1329	1	1
+35	1	0
+247	1	1
+16	1	1
+184	1	1
+18	1	1
+1636	0	7
+23	1	1
+527	1	1
+39	1	1
+653	3	0
+227	1	1
+18	1	1
+218	0	323
+91	1	0
+124	0	15
+621	0	2
+555	8	8
+467	1	1
+40	1	1
+372	1	1
+25	1	1
+188	12	12
+357	0	2
+2389	1	1
+22	1	1
+2579	0	5
+461	1	1
+36	1	1
+1584	1	1
+26	1	0
+429	1	0
+33	1	1
+1071	0	4
+1068	9	0
+1472	0	2
+1839	94	92
+337	1	1
+46	1	1
+416	1	1
+42	1	1
+1255	0	2
+628	17	15
+587	15	15
+398	3	0
+623	1	1
+78	0	3
+287	10	0
+191	0	2
+493	1	1
+42	4	0
+219	0	1
+408	1	1
+23	1	1
+283	1	1
+21	1	1
+633	2	0
+241	6	6
+457	1	0
+330	0	16
+428	1	0
+4	6	0
+324	0	1
+3060	0	2
+9953	0	1
+1899	0	6
+6431	0	1
+8674	0	4
+4595	11	0
+5064	2	0
+2813	12	12
+1391	5	0
+3690	1	1
+64	1	1
+2635	1	1
+49	1	1
+69	1	1
+15	1	1
+605	4	4
+400	8	0
+735	0	20
+3074	2	0
+1879	0	1
+572	0	8
+576	1	1
+42	1	1
+265	24	0
+209	11	11
+953	1	1
+42	0	5
+58	1	0
+95	1	0
+1121	1	1
+17	1	1
+751	0	1
+24	1	1
+351	1	1
+43	3	3
+565	1	1
+15	1	1
+271	1	0
+323	1	1
+23	1	1
+221	7	7
+705	9	0
+631	2	0
+64	1	1
+1577	1	1
+21	0	1
+371	7	21
+160	0	1
+283	1	1
+48	1	1
+227	1	1
+40	0	1
+1359	0	2
+836	13	13
+722	7	7
+1153	1	1
+93	1	1
+797	14	14
+433	8	0
+108	11	11
+140	1	1
+40	1	1
+470	1	1
+42	1	1
+1106	0	1
+85	4	4
+129	1	1
+123	1	0
+95	1	1
+104	6	1
+641	1	1
+77	1	1
+57	1	1
+62	1	1
+473	2	0
+262	6	0
+45	1	1
+63	2	0
+39	1	1
+267	0	1
+197	2	104
+189	107	3
+112	0	4
+108	5	0
+563	14	14
+324	1	0
+205	1	1
+17	1	1
+495	0	1
+201	4	0
+14	1	1
+667	42	42
+178	1	1
+58	1	1
+133	1	1
+24	1	1
+91	24	24
+342	1	1
+32	1	1
+121	1	1
+62	1	1
+2371	2	0
+164	8	1
+655	1	1
+30	1	1
+271	1	1
+47	1	1
+609	1	0
+1780	2	0
+742	1	1
+40	1	1
+2014	1	0
+1741	3	0
+3833	0	1
+14622	161198	190000
+5156	0	1
+1680	1	1
+88	1	1
+4502	0	1
+46	1	1
+800	4	4
+23	1	1
+1305	2	0
+136	0	1
+4941	0	1
+547	0	1
+70	8	8
+293	1	1
+35	1	1
+1165	4	0
+6662	1	1
+46	1	1
+167	0	8
+214	1	1
+35	1	1
+108	1	0
+1063	0	1
+1017	1	1
+20	0	6
+1725	0	1
+150	5	5
+33	1	0
+12	1	1
+349	1	1
+24	0	1
+1562	1	1
+31	1	1
+2513	0	1
+73	36	36
+305	1	1
+27	1	1
+543	1	1
+47	4	28
+5476	10	10
+531	1	1
+37	1	1
+776	1	1
+44	2	2
+115	22	20
+181	1	1
+125	3	3
+466	1	1
+76	1	1
+144	5	5
+32	1	1
+225	1	1
+41	1	1
+707	24	24
+66	4	4
+414	1	1
+42	1	1
+81	1	1
+63	1	1
+76	28	46
+187	1	1
+97	1	1
+99	9	9
+85	14	14
+81	6	6
+62	1	1
+109	4	5
+150	1	0
+44	4	4
+93	11	11
+188	3	3
+73	1	1
+52	1	1
+19	13	0
+48	1	1
+62	0	7
+205	1	1
+68	9	9
+99	4	0
+21	1	0
+52	1	1
+171	1	1
+109	3	1
+6	0	2
+190	1	1
+69	10078	10069
+90	3	1
+197	1	1
+157	0	6
+137	1	1
+101	2	2
+233	6	6
+62	1	1
+104	0	1
+143	1	1
+119	1	1
+106	2	0
+176	1	1
+79	0	1
+50	1	1
+50	3	3
+179	1	1
+159	1	1
+36	1	1
+107	1	1
+176	1	1
+154	0	5
+91	1	1
+54	1	1
+77	1	1
+238	2	2
+50	1	1
+1421	1	1
+23	1	1
+216	1	1
+122	1	1
+86	1	1
+41	3	1
+336	7	7
+41	9	0
+107	1	1
+90	1	3
+6	1	0
+84	1	1
+213	1	1
+26	1	1
+138	1	1
+25	1	1
+206	1	1
+36	3	3
+37	7	0
+500	1	1
+52	1	1
+52	1	1
+48	1	1
+395	1	1
+66	6	6
+72	1	0
+69	1	1
+100	10	10
+160	1	0
+64	7	7
+89	1	1
+123	1	1
+128	1	1
+36	1	1
+231	1	1
+61	1	1
+564	8	8
+593	47	47
+163	1	0
+196	8	8
+174	5	5
+37	1	1
+67	0	1
+192	1	1
+60	3	0
+19	1	1
+1149	1	1
+18	1	1
+77	1	1
+32	2	0
+32	1	1
+136	1	1
+78	2	0
+162	4	0
+41	1	1
+351	13	13
+1634	2	0
+229	8	8
+57	13	2
+410	1	1
+76	1	1
+180	1	1
+92	1	1
+270	1	1
+40	1	1
+92	1	1
+53	1	1
+227	1	1
+42	1	1
+357	4	4
+23	1	1
+94	1	0
+200	6	0
+201	7	7
+70	5	13
+57	4	0
+35	1	1
+206	1	1
+76	2	2
+651	1	1
+68	4	0
+73	1	1
+49	4	0
+37	1	1
+145	2	2
+78	2	2
+108	12	12
+52	1	1
+35	1	1
+242	1	3
+76	2	2
+50	12	12
+70	1	1
+33	0	2
+57	1	1
+64	15	15
+168	1	1
+22	1	1
+63	36	37
+73	0	2
+64	1	1
+177	2	0
+19	4	0
+55	1	0
+33	1	1
+51	1	1
+122	1	1
+296	1	1
+85	1	1
+109	1	1
+64	1	1
+155	1	1
+58	0	2
+72	1	1
+25	1	1
+128	1	1
+45	2	0
+444	1	1
+25	1	1
+64	1	1
+21	1	1
+368	15	15
+734	2	0
+701	15	15
+71	1	1
+41	1	1
+77	1	1
+56	1	1
+478	2	0
+714	8	7
+95	2	2
+50	4	3
+1129	1	1
+34	1	1
+1715	1	1
+87	1	1
+692	1	1
+47	0	1
+75	1	1
+541	12	12
+1602	10	10
+1265	1	1
+46	1	1
+298	1	1
+22	1	1
+186	1	1
+34	1	1
+202	1	1
+61	1	0
+185	1	1
+24	1	0
+98	0	2
+258	8	14
+967	1	1
+15	1	1
+625	1	0
+1362	0	4
+23365	4	0
+246	26975	26986
+3307	0	1
+13671	3	3
+52	1	1
+1308	2	0
+942	0	1
+17790	1	0
+4586	0	1
+949	0	2
+15047	0	1
+606	2	0
+7820	0	4
+22313	16	0
+10539	8	0
+4836	0	1
+8320	18	18
+388	2	0
+194	1	1
+49	1	1
+320	1	1
+34	1	1
+6813	0	1
+8719	3	0
+7037	1	0
+721	0	1
+999	6	0
+17	1	0
+3075	5	0
+593	13	11
+1006	12	12
+3487	1	0
+9535	0	4
+23	0	2
+23	2	0
+513	0	3
+377	1	0
+2627	0	2
+16	0	1
+211	18	18
+571	2	0
+7617	0	1
+1607	1	0
+69	1	1
+66	1	1
+275	1	1
+67	7	0
+25	1	1
+1206	1	0
+136	8	7
+612	1	1
+61	1	1
+740	0	2
+78	26	26
+129	15	15
+69	12	16
+1483	13	28
+1062	1	0
+108	4	0
+685	0	2
+1566	1	0
+192	4	4
+1452	9	45
+1514	1	1
+46	1	1
+1969	0	1
+35	1	1
+1094	1	0
+618	1	1
+43	1	1
+6580	1	0
+1636	5	0
+6325	1	1
+32	1	1
+1041	0	2
+174	9	0
+11983	18	18
+142	8	8
+2203	10	8
+2025	1	1
+39	1	1
+907	4	4
+225	1	1
+124	1	1
+3928	0	22
+38	2	0
+44	18	0
+46	0	6
+61	0	1
+3653	6	0
+34	1	1
+4559	1	1
+28	1	1
+283	5	5
+1572	28	28
+351	1	1
+34	1	1
+443	19	19
+57	1	1
+21	1	1
+231	1	1
+94	1	1
+105	1	1
+208	5	5
+124	1	1
+112	3	3
+207	1	1
+38	1	1
+244	1	1
+60	1	1
+98	1	1
+50	1	1
+256	5	5
+23	1	1
+157	1	1
+33	1	1
+143	1	1
+59	1	1
+51	1	1
+45	1	0
+73	1	1
+81	1	1
+339	1	1
+56	0	5
+142	1	1
+232	1	1
+43	1	1
+332	1	1
+47	1	1
+479	1	0
+137	0	3
+1456	10	13
+63	1	1
+37	1	1
+261	0	2
+109	1	1
+50	1	1
+56	129	1
+88	1	0
+44	1	1
+54	1	1
+56	1	50
+58	50	1
+54	277	1
+44	1	1
+297	0	39
+142	1	1
+85	1	1
+124	16	16
+58	3	15
+677	1	0
+1333	2	0
+13591	6	0
+989	1	1
+107	1	1
+678	1	1
+31	1	1
+2571	5	5
+56	2	2
+39	1	1
+3986	0	4
+18351	32	30
+10811	1	1
+25	0	1
+417	1	1
+40	1	1
+159	4	4
+37	4	4
+179	1	1
+51	1	1
+103	2	0
+108	1	1
+79	1	1
+25	1	1
+58	1	1
+12	1	1
+275	14	0
+80	1	1
+83	1	1
+24	1	1
+59	1	0
+91	1	1
+65	1	1
+67	1	1
+136	4	0
+68	8	0
+331	5	0
+40	1	1
+110	10	6
+64	1	1
+368	1	1
+22	1	1
+509	1	1
+89	1	1
+926	1	0
+959	1	1
+44	1	1
+72	11	0
+47	1	1
+361	1	1
+37	1	1
+2204	2	2
+45	1	1
+1117	18	18
+141	1	1
+47	1	1
+148	1	1
+75	1	1
+104	1	0
+205	3	2
+249	1	1
+146	1	1
+94	1	1
+34	1	1
+700	0	331
+21	1	1
+73	1	1
+49	1	1
+356	1	1
+16	1	1
+112	1	1
+36	9	0
+515	1	1
+27	2	2
+192	1	1
+53	0	14
+82	1	1
+302	1	1
+68	1	1
+52	12	12
+52	1	1
+34	1	1
+166	7	7
+384	1	1
+31	1	1
+281	1	1
+57	1	1
+176	0	1
+1625	1	1
+26	1	1
+369	1	1
+21	1	1
+86	1	1
+134	1	1
+215	1	1
+214	15	1
+50	2	2
+26	1	1
+78	0	19
+64	1	1
+118	53	53
+433	1	1
+76	0	1
+6	12	0
+52	1	1
+108	1	1
+87	1	1
+62	1	1
+26	1	1
+291	2	1
+143	1	1
+29	1	1
+56	12	12
+230	1	1
+153	4	4
+87	32	32
+584	12	12
+227	1	0
+1931	4	0
+836	1	1
+68	1	1
+205	24	19
+816	1	2
+1932	0	7
+1732	13	0
+257	4	0
+1423	1	0
+129	6	0
+1505	1	1
+42	0	1
+373	13	13
+565	1	1
+76	1	0
+1881	0	4
+68	4	0
+43	0	4
+2201	8	8
+3726	3	0
+339	15	11
+249	1	1
+35	1	1
+250	1	1
+38	1	1
+359	11	12
+109	1	1
+43	18	0
+822	1	1
+53	1	1
+325	15	15
+123	1	1
+42	6	6
+240	1	1
+44	1	1
+438	7	7
+142	2	0
+1004	0	1
+9275	1	1
+37	1	0
+2071	0	1
+1253	9	9
+9137	0	1
+12513	2	1
+11243	1	1
+26	1	1
+816	4	0
+15996	2	0
+1594	1	0
+363	5	0
+6757	47	41
+2700	1	0
+841	0	1
+1807	0	2
+2565	11	0
+2089	0	2
+477	1	0
+657	0	1
+776	0	20
+365	82	49
+779	0	1
+401	25	63
+441	0	2
+1152	0	2
+1315	1	0
+5352	6	8
+902	0	1
+2154	1	1
+36	1	1
+109	0	1
+668	6	0
+1923	0	1
+91	3	2
+3560	1	0
+1235	1	0
+139	26	0
+7381	1	0
+155	0	14
+2393	1	1
+33	1	1
+507	4	0
+1337	0	1
+9954	3	0
+1588	1	0
+2605	1	1
+23	1	1
+3000	0	3
+8249	8	0
+912	0	1
+338	2	0
+734	1	0
+4332	1	0
+416	0	4
+1691	0	1
+295	1	0
+214	2	0
+121	0	1
+784	0	1
+2512	0	1
+4465	12	11
+926	1	0
+190	1	0
+5780	0	1
+490	5	0
+228	1	1
+45	1	1
+207	3	0
+322	0	1
+633	1	1
+24	1	0
+1516	5	0
+1025	0	13
+1518	0	1
+591	10	10
+1061	1	0
+1371	1	1
+22	1	1
+928	0	2
+182	8	0
+328	1	0
+301	0	1
+994	1	1
+18	0	6
+1743	0	1
+2350	22	23
+1548	0	2
+1498	8	6
+7484	0	3
+2988	7	7
+93	2	0
+322	1	0
+280	1	1
+49	1	1
+2114	16	17
+617	0	1
+1012	0	1
+495	1	0
+29	1	1
+3134	1	0
+1837	0	4
+4079	0	1
+905	8	0
+5764	0	1
+3493	0	20
+1174	0	1
+900	0	1
+1006	1	0
+1699	0	1
+1682	1	0
+688	1	1
+21	1	1
+3349	0	1
+384	3	1
+3616	3	0
+748	0	1
+3001	0	10
+541	1	0
+286	1	1
+22	0	1
+250	1	1
+27	1	1
+898	1	0
+1161	0	2
+2067	0	1
+8000	0	12
+857	29	0
+1399
+
+chain	72788	6_qbl_hap2	4565931	+	3808375	3809175	11	135006516	+	118201008	118201901	1739030
+615	13	107
+119	2	1
+51
+
+chain	65509	6_qbl_hap2	4565931	+	2258974	2259668	6	171115067	-	140105134	140105832	1929446
+178	0	4
+516
+
+chain	50097	6_qbl_hap2	4565931	+	2471491	2473781	6	171115067	+	44553942	44556234	2550079
+125	147	147
+81	297	298
+77	380	378
+160	345	343
+82	181	182
+60	299	303
+56
+
+chain	30865	6_qbl_hap2	4565931	+	3800272	3800791	6	171115067	+	32713281	32713770	4500604
+73	89	59
+184	77	77
+96
+
+chain	26769	6_qbl_hap2	4565931	+	2218659	2218944	1	249250621	-	83463584	83463869	6084938
+285
+
+chain	25453	6_qbl_hap2	4565931	+	1111775	1112573	8	146364022	+	94982474	94983353	6804147
+181	108	108
+72	385	466
+52
+
+chain	18586	6_qbl_hap2	4565931	+	2472758	2473366	3	198022430	-	151831455	151832050	2830221
+34	221	221
+81	91	91
+5	35	35
+55	44	31
+42
+
+chain	18520	6_qbl_hap2	4565931	+	2558133	2558568	13	115169878	-	5075411	5075846	11677159
+71	220	220
+144
+
+chain	17263	6_qbl_hap2	4565931	+	3694162	3694369	4	191154276	+	3927369	3927573	12785974
+50	3	0
+26	4	4
+124
+
+chain	16745	6_qbl_hap2	4565931	+	2589692	2589893	11	135006516	+	74748600	74748801	13289219
+113	12	12
+76
+
+chain	15761	6_qbl_hap2	4565931	+	3069257	3069435	19	59128983	-	18504215	18504393	607285
+59	1	1
+45	1	1
+72
+
+chain	15688	6_qbl_hap2	4565931	+	3804298	3804527	11	135006516	-	109492289	109492518	14350697
+129	50	50
+50
+
+chain	14458	6_qbl_hap2	4565931	+	3751685	3752808	6	171115067	+	32441118	32442245	15662572
+59	270	268
+88	656	662
+50
+
+chain	14065	6_qbl_hap2	4565931	+	3705931	3706083	6	171115067	-	138602057	138602209	16122341
+152
+
+chain	13955	6_qbl_hap2	4565931	+	2589304	2589471	9	141213431	-	10269188	10269355	16251226
+93	11	11
+63
+
+chain	13115	6_qbl_hap2	4565931	+	937718	937855	7	159138663	+	102343613	102343750	17340123
+137
+
+chain	12452	6_qbl_hap2	4565931	+	4213437	4214179	12	133851895	+	124586233	124586652	1913233
+57	408	105
+14	32	63
+45	0	78
+44	129	0
+13
+
+chain	12361	6_qbl_hap2	4565931	+	1150685	1150815	1	249250621	+	48985442	48985572	18455294
+130
+
+chain	12272	6_qbl_hap2	4565931	+	2479004	2479160	X	155270560	+	155194421	155194569	18587559
+71	1	1
+25	8	0
+51
+
+chain	12201	6_qbl_hap2	4565931	+	1105096	1105867	6	171115067	-	139876162	139876935	18699321
+54	620	622
+97
+
+chain	12178	6_qbl_hap2	4565931	+	3776349	3776515	14	107349540	-	58393926	58394091	18734379
+55	26	25
+85
+
+chain	12008	6_qbl_hap2	4565931	+	3700751	3700880	8	146364022	+	49154427	49154556	18990653
+129
+
+chain	11752	6_qbl_hap2	4565931	+	3745259	3747655	6	171115067	+	32491461	32493852	19428924
+56	676	682
+61	1516	1505
+87
+
+chain	11746	6_qbl_hap2	4565931	+	1097944	1098092	7	159138663	-	7702899	7703047	19437479
+54	14	14
+80
+
+chain	11503	6_qbl_hap2	4565931	+	3698827	3699253	11	135006516	-	111045874	111046295	19852910
+57	287	282
+82
+
+chain	10738	6_qbl_hap2	4565931	+	3700459	3700580	10	135534747	+	59600699	59600817	21255899
+61	3	0
+57
+
+chain	10686	6_qbl_hap2	4565931	+	2478152	2478673	18	78077248	+	11342173	11342695	21355061
+80	388	389
+53
+
+chain	10496	6_qbl_hap2	4565931	+	3696510	3696620	1	249250621	-	174039531	174039641	21744609
+110
+
+chain	10342	6_qbl_hap2	4565931	+	3714159	3714889	6	171115067	+	32548581	32549235	22073729
+78	598	522
+54
+
+chain	9560	6_qbl_hap2	4565931	+	1152614	1152715	6	171115067	-	141323187	141323288	23857063
+101
+
+chain	9560	6_qbl_hap2	4565931	+	1099695	1099796	6	171115067	-	141323187	141323288	23857064
+101
+
+chain	9385	6_qbl_hap2	4565931	+	3825573	3825778	16	90354753	-	20685009	20685189	24272037
+58	92	67
+55
+
+chain	9214	6_qbl_hap2	4565931	+	1102327	1102424	6	171115067	+	29758158	29758255	24607529
+97
+
+chain	9048	6_qbl_hap2	4565931	+	3694493	3695083	16	90354753	-	14504923	14505798	16016601
+79	460	745
+51
+
+chain	8993	6_qbl_hap2	4565931	+	2558568	2558745	2	243199373	+	116390976	116391155	17783325
+1	102	104
+74
+
+chain	8702	6_qbl_hap2	4565931	+	3686082	3686238	6	171115067	+	32439449	32439606	25393693
+54	51	52
+51
+
+chain	8427	6_qbl_hap2	4565931	+	3804527	3804616	6	171115067	-	148948316	148948405	15963296
+89
+
+chain	7704	6_qbl_hap2	4565931	+	3688237	3688318	6	171115067	+	32557831	32557912	26927503
+81
+
+chain	6794	6_qbl_hap2	4565931	+	3775350	3775421	3	198022430	-	94748615	94748686	28659148
+71
+
+chain	6473	6_qbl_hap2	4565931	+	3694610	3694683	1	249250621	-	102907635	102907704	21815174
+11	4	0
+58
+
+chain	6457	6_qbl_hap2	4565931	+	1158502	1158569	6	171115067	+	30228837	30228904	29438118
+67
+
+chain	6422	6_qbl_hap2	4565931	+	3817908	3817976	6	171115067	+	32728707	32728775	29535243
+68
+
+chain	6368	6_qbl_hap2	4565931	+	2478912	2479004	6	171115067	-	132617434	132617532	20998654
+55	29	35
+8
+
+chain	5830	6_qbl_hap2	4565931	+	1098157	1098218	7	159138663	-	104622057	104622118	31091038
+61
+
+chain	5757	6_qbl_hap2	4565931	+	3825218	3825278	14	107349540	-	70017731	70017791	31292281
+60
+
+chain	5558	6_qbl_hap2	4565931	+	2472407	2472466	15	102531392	+	37673660	37673719	31870719
+59
+
+chain	5479	6_qbl_hap2	4565931	+	1111956	1112025	9	141213431	-	103321949	103322018	11235972
+69
+
+chain	5339	6_qbl_hap2	4565931	+	3885926	3885982	X	155270560	+	55718242	55718298	32499987
+56
+
+chain	5185	6_qbl_hap2	4565931	+	3788909	3788964	14	107349540	+	22827226	22827281	32987373
+55
+
+chain	5179	6_qbl_hap2	4565931	+	1150896	1150960	19	59128983	-	37357346	37357410	20742827
+53	10	10
+1
+
+chain	5176	6_qbl_hap2	4565931	+	1100596	1100651	14	107349540	+	79349485	79349540	33029769
+55
+
+chain	5058	6_qbl_hap2	4565931	+	3771065	3771119	1	249250621	-	172942963	172943017	33379587
+54
+
+chain	5039	6_qbl_hap2	4565931	+	2475495	2475548	7	159138663	-	94193358	94193411	33438564
+53
+
+chain	5038	6_qbl_hap2	4565931	+	1148806	1148858	6	171115067	+	29856463	29856515	33456716
+52
+
+chain	4959	6_qbl_hap2	4565931	+	3696457	3696510	18	78077248	+	5090594	5090647	22176919
+53
+
+chain	4949	6_qbl_hap2	4565931	+	3825516	3825569	X	155270560	-	91231208	91231261	33742123
+53
+
+chain	4829	6_qbl_hap2	4565931	+	1159026	1159076	6	171115067	+	30459319	30459369	34177698
+50
+
+chain	4685	6_qbl_hap2	4565931	+	3719592	3719642	12	133851895	+	112261417	112261467	34690970
+50
+
+chain	4391	6_qbl_hap2	4565931	+	4214058	4214103	X	155270560	-	99494613	99494658	30227326
+45
+
+chain	4348	6_qbl_hap2	4565931	+	3739277	3739323	7	159138663	-	76863668	76863714	34891433
+46
+
+chain	4338	6_qbl_hap2	4565931	+	2201356	2201401	6	171115067	+	30954494	30954539	34909104
+45
+
+chain	4061	6_qbl_hap2	4565931	+	2201872	2201914	6	171115067	+	30955145	30955187	31149648
+42
+
+chain	4003	6_qbl_hap2	4565931	+	2470663	2474155	12	133851895	+	104783555	104787047	2981748
+99	961	960
+40	481	480
+76	473	472
+44	1256	1259
+62
+
+chain	3775	6_qbl_hap2	4565931	+	2471376	2471416	10	135534747	-	90944157	90944197	25967017
+40
+
+chain	3639	6_qbl_hap2	4565931	+	3694572	3694610	3	198022430	+	101411146	101411184	20382400
+38
+
+chain	3574	6_qbl_hap2	4565931	+	2470595	2470633	3	198022430	-	173409162	173409200	29596632
+38
+
+chain	3494	6_qbl_hap2	4565931	+	3700422	3700459	X	155270560	+	104134375	104134412	29536090
+37
+
+chain	3491	6_qbl_hap2	4565931	+	2471293	2472133	8	146364022	-	12751685	12752521	3617865
+79	701	697
+60
+
+chain	3436	6_qbl_hap2	4565931	+	2471844	2473225	1	249250621	+	7474211	7475590	2872741
+34	959	957
+58	295	295
+35
+
+chain	3220	6_qbl_hap2	4565931	+	3776529	3776563	12	133851895	+	85826623	85826657	35349035
+34
+
+chain	3148	6_qbl_hap2	4565931	+	3825631	3825664	2	243199373	+	38182693	38182726	24706670
+33
+
+chain	2975	6_qbl_hap2	4565931	+	2478232	2478268	3	198022430	-	94213030	94213066	24807218
+36
+
+chain	2972	6_qbl_hap2	4565931	+	1105868	1105908	6	171115067	+	30459045	30459085	20759384
+40
+
+chain	2845	6_qbl_hap2	4565931	+	2470633	2470663	3	198022430	-	156603737	156603767	26791326
+30
+
+chain	2838	6_qbl_hap2	4565931	+	2474990	2475020	4	191154276	+	92075174	92075204	21730347
+30
+
+chain	2761	6_qbl_hap2	4565931	+	3804625	3804685	4	191154276	+	37278694	37278754	22658556
+60
+
+chain	2671	6_qbl_hap2	4565931	+	2478852	2478911	9	141213431	-	60456470	60456529	21094091
+59
+
+chain	2604	6_qbl_hap2	4565931	+	1151032	1151059	17	81195210	+	6784720	6784747	30920849
+27
+
+chain	2579	6_qbl_hap2	4565931	+	3700720	3700751	21	48129895	+	18677639	18677670	26190064
+31
+
+chain	2574	6_qbl_hap2	4565931	+	1150960	1151032	X	155270560	+	72544773	72544845	18935818
+72
+
+chain	2481	6_qbl_hap2	4565931	+	3804442	3804477	3	198022430	-	58737971	58738006	17138123
+35
+
+chain	2394	6_qbl_hap2	4565931	+	2478673	2478698	11	135006516	-	67345781	67345806	29321362
+25
+
+chain	2363	6_qbl_hap2	4565931	+	2473435	2473485	3	198022430	-	59783725	59783775	3613581
+50
+
+chain	2322	6_qbl_hap2	4565931	+	2470859	2470989	15	102531392	-	72822940	72823070	3150079
+130
+
+chain	2266	6_qbl_hap2	4565931	+	2470989	2471957	9	141213431	-	114376815	114377769	4168715
+45	845	831
+78
+
+chain	2263	6_qbl_hap2	4565931	+	2471123	2471268	12	133851895	+	84401354	84401499	4041581
+145
+
+chain	2209	6_qbl_hap2	4565931	+	2470765	2470818	3	198022430	+	182918728	182918781	9563966
+53
+
+chain	2087	6_qbl_hap2	4565931	+	2558317	2558369	X	155270560	-	89201309	89201361	22578016
+52
+
+chain	2078	6_qbl_hap2	4565931	+	1112026	1112064	3	198022430	+	120909358	120909396	13027265
+38
+
+chain	2035	6_qbl_hap2	4565931	+	2557888	2557938	16	90354753	+	47212776	47212826	17692575
+50
+
+chain	1978	6_qbl_hap2	4565931	+	4213820	4213948	15	102531392	-	61555806	61555934	2051418
+28	68	68
+32
+
+chain	1899	6_qbl_hap2	4565931	+	2558399	2558424	X	155270560	+	94068150	94068175	17734181
+25
+
+chain	1860	6_qbl_hap2	4565931	+	1112180	1112230	8	146364022	+	68079613	68079663	13479327
+50
+
+chain	1860	6_qbl_hap2	4565931	+	3812269	3815784	6	171115067	+	32722816	32726965	29521084
+61	2506	2690
+85	515	965
+52	103	103
+193
+
+chain	1828	6_qbl_hap2	4565931	+	2473656	2473684	14	107349540	-	54723100	54723128	20222699
+28
+
+chain	1658	6_qbl_hap2	4565931	+	1112136	1112169	4	191154276	+	153686345	153686378	11053932
+33
+
+chain	1514	6_qbl_hap2	4565931	+	1112233	1112291	13	115169878	-	5205835	5205893	10260311
+58
+
+chain	1396	6_qbl_hap2	4565931	+	2473606	2473656	1	249250621	+	83820278	83820328	4577579
+50
+
+chain	1388	6_qbl_hap2	4565931	+	4214123	4214166	19	59128983	-	43654778	43654821	2801865
+43
+
+chain	1329	6_qbl_hap2	4565931	+	2557727	2557778	7	159138663	-	55106997	55107048	20610784
+51
+
+chain	1304	6_qbl_hap2	4565931	+	4213365	4213389	1	249250621	+	182710286	182710310	2078906
+24
+
+chain	1296	6_qbl_hap2	4565931	+	4213389	4213424	8	146364022	+	99694	99728	9829550
+12	1	0
+22
+
+chain	1233	6_qbl_hap2	4565931	+	2558102	2558133	5	180915260	+	67992831	67992862	12309329
+31
+
+chain	1171	6_qbl_hap2	4565931	+	2473569	2473606	X	155270560	-	90928252	90928289	23413190
+37
+
+chain	1170	6_qbl_hap2	4565931	+	2471983	2472043	9	141213431	+	232427	232487	4190853
+60
+
+chain	1144	6_qbl_hap2	4565931	+	2469449	2469508	2	243199373	+	81796678	81796737	21594602
+59
+
+chain	1125	6_qbl_hap2	4565931	+	3694759	3694827	8	146364022	-	86779351	86779419	20749390
+68
+
+chain	1106	6_qbl_hap2	4565931	+	1112362	1112413	1	249250621	-	17660691	17660742	13643228
+51
+
+chain	1071	6_qbl_hap2	4565931	+	2470508	2470575	12	133851895	+	78891507	78891574	9444392
+67
+
+chain	1040	6_qbl_hap2	4565931	+	2470400	2470457	5	180915260	-	146134722	146134779	6672758
+57
+
+chain	1023	6_qbl_hap2	4565931	+	2471416	2471471	2	243199373	+	162554783	162554838	24613681
+55
+
+chain	935	6_qbl_hap2	4565931	+	2558067	2558102	4	191154276	+	31205	31240	16972854
+35
+
+chain	919	6_qbl_hap2	4565931	+	2474702	2474762	4	191154276	+	45112377	45112437	22402157
+60
+
+chain	902	6_qbl_hap2	4565931	+	2474552	2474612	5	180915260	-	23766246	23766306	4704228
+60
+
+chain	884	6_qbl_hap2	4565931	+	2473696	2473725	1	249250621	-	199045131	199045160	12500824
+29
+
+chain	825	6_qbl_hap2	4565931	+	1112413	1112452	1	249250621	-	184583816	184583855	16072417
+39
+
+chain	801	6_qbl_hap2	4565931	+	2470111	2470156	1	249250621	-	71436588	71436633	19248116
+45
+
+chain	789	6_qbl_hap2	4565931	+	3698600	3699777	19	59128983	+	8446620	8447803	26630175
+58	1059	1065
+60
+
+chain	788	6_qbl_hap2	4565931	+	2470239	2470322	6	171115067	+	137168270	137168353	4512040
+83
+
+chain	740	6_qbl_hap2	4565931	+	1112667	1112731	12	133851895	+	57178267	57178331	20850792
+64
+
+chain	718	6_qbl_hap2	4565931	+	2474782	2474837	9	141213431	-	49469911	49469966	23568604
+55
+
+chain	694	6_qbl_hap2	4565931	+	2469923	2469992	X	155270560	-	140437581	140437650	5405913
+69
+
+chain	584	6_qbl_hap2	4565931	+	2474349	2474405	15	102531392	+	67105223	67105279	15249534
+56
+
+chain	562	6_qbl_hap2	4565931	+	2557778	2557819	X	155270560	+	91975692	91975733	21019876
+41
+
+chain	562	6_qbl_hap2	4565931	+	2469824	2469884	2	243199373	-	169790362	169790422	25410177
+60
+
+chain	552	6_qbl_hap2	4565931	+	2237356	2237383	17	81195210	-	14890828	14890855	11066346
+27
+
+chain	523	6_qbl_hap2	4565931	+	2470057	2470111	13	115169878	+	42049099	42049153	16964924
+54
+
+chain	489	6_qbl_hap2	4565931	+	2469992	2470048	14	107349540	+	79003493	79003549	5260265
+56
+
+chain	481	6_qbl_hap2	4565931	+	2470189	2470239	8	146364022	+	50441810	50441860	5267091
+50
+
+chain	481	6_qbl_hap2	4565931	+	2469386	2469447	1	249250621	-	193322918	193322979	8728434
+61
+
+chain	455	6_qbl_hap2	4565931	+	2472488	2472547	6	171115067	-	85200236	85200295	17778688
+59
+
+chain	445	6_qbl_hap2	4565931	+	2469210	2469265	X	155270560	-	127487766	127487821	16318369
+55
+
+chain	358	6_qbl_hap2	4565931	+	2475020	2475084	4	191154276	+	74158363	74158427	16300933
+64
+
+chain	347	6_qbl_hap2	4565931	+	2469153	2469203	15	102531392	-	65978487	65978537	12839283
+50
+
+chain	246	6_qbl_hap2	4565931	+	3697415	3697467	12	133851895	-	104314075	104314127	28162397
+52
+
+chain	47340388	6_random	1875562	+	1357431	1875562	6	171115067	+	157393490	158069469	78
+906	2	2
+193	1	0
+29	1	0
+8	10	8
+11	2	1
+842	41	40
+754	2304	72101
+91082	5628	50000
+31833	338	50000
+42477	272	0
+39	168	66
+53	1	1
+15	1	103
+64	2	172
+23	1	103
+14474	4	0
+30198	0	8
+1391	2	0
+1319	4	0
+142	0	3
+3412	9	7
+372	1	1
+22	1	1
+5871	0	1
+237	26	25
+3020	1	1
+83	1	1
+141	7	7
+201	2	1
+403	1	0
+3638	1	0
+20	1	0
+552	32	32
+1386	0	1
+4174	1	1
+37	1	1
+3912	5	5
+4160	2	0
+6561	0	1
+3879	0	1
+8665	0	1
+2170	0	3
+895	1	0
+1812	0	1
+36	0	4
+133	1	0
+165	0	9
+427	0	1
+917	1	0
+3166	0	1
+16647	1	0
+6161	10	10
+833	4	0
+1934	1	1
+56	1	1
+2622	9	9
+749	1	0
+482	0	2
+344	1	1
+32	1	1
+868	2	0
+444	0	3
+1096	12	0
+709	0	1
+113	1	1
+35	1	1
+2349	20	0
+175	0	1
+1675	0	2
+1206	0	3
+345	0	5
+4695	1	0
+6715	1	1
+35	1	1
+2131	0	1
+4220	8	0
+2065	1	0
+1986	0	1
+484	0	1
+1543	4	4
+52	22	0
+5090	0	1
+2768	9	2
+12577	0	5
+13727	9	9
+51	4	4
+26	2	3
+11	0	1
+735	1	1
+35	0	1
+12	1	1
+2616	1	0
+327	1	1
+35	1	1
+345	0	20
+50	98	187
+975	1	0
+7329	0	1
+3241	0	35
+583	5	5
+278	1	1
+40	1	1
+123	12	12
+1208	17	0
+477	0	1
+163	1	1
+28	1	1
+3307	1	0
+66	1	1
+25	4	0
+2459	0	1
+1326	1	0
+700	1	0
+2316	6067	13
+725	3	0
+42	1	1
+8162	0	2
+2147	0	2
+79	1	1
+25	1	1
+313	1	0
+2194	1	0
+709	1	1
+33	1	1
+934	4	4
+543	1	1
+37	1	1
+2581	1	0
+606	1	0
+666	1	1
+34	2	2
+250	9	8
+652	1	0
+2306	22	0
+38	0	24
+946	1	0
+3766	1	1
+57	1	1
+3591	2	0
+128	1	1
+1414	7	1
+435	1	1
+29	1	0
+529	0	1
+3649	1	1
+32	0	1
+9760	0	18
+6470	1	1
+49	1	1
+488	0	1
+304	2	0
+1780	0	5
+2759	1	0
+48	1	1
+380	1	1
+33	1	1
+5102	1	1
+33	1	1
+192	0	1
+1103	1	1
+29	1	1
+12912	0	1
+9445	2	0
+2949	1	1
+28	1	1
+826	1	1
+19	1	1
+404	1	1
+49	1	1
+1408	8	0
+1625	10	0
+2962	0	1
+1824
+
+chain	37689909	6_random	1875562	+	884671	1286589	5	180915260	-	167715260	168127349	92
+6889	0	1
+34829	1	0
+4156	0	2
+4477	0	8
+7827	0	415
+37	9	9
+207	0	1
+272	7	7
+7925	1	0
+75982	0	1
+11336	0	1
+4233	14	14
+362	10	10
+4607	4	0
+1310	0	3
+1741	4	0
+499	1	1
+69	1	1
+509	15	15
+166	12	8
+145	0	2
+66	1	1
+16	1	1
+325	1	1
+31	1	1
+804	1	1
+109	1	1
+1071	0	106
+73	38	121
+1998	1	1
+37	1	1
+500	0	5
+625	3	0
+2354	1	1
+42	1	1
+1652	0	1
+92	1	1
+68	1	1
+1023	1	1
+16	1	1
+849	2	1
+28	1	1
+1793	4	2
+850	26	26
+251	0	2
+794	1	1
+26	1	1
+798	1	1
+80	1	1
+211	20	12
+153	1	3
+373	6	6
+231	0	4
+302	1	1
+26	1	1
+305	0	4
+3735	1	0
+342	0	2
+2211	0	1
+1969	2	0
+2834	0	10
+1054	0	14
+2176	0	2
+10517	0	2
+3071	6	0
+5697	21	21
+2458	0	5
+1335	3	0
+411	1	5
+2718	10	11
+3652	1	0
+785	1	0
+777	1	0
+2088	0	1
+24	1	1
+1005	16	16
+5426	18	0
+378	1	0
+19	1	1
+5303	0	14
+19	18	0
+2125	1	0
+936	0	5
+29	1	1
+893	19	19
+312	0	2
+32151	1	0
+14548	1	0
+109	0	1
+1481	1	0
+6537	0	2
+3390	1	0
+7479	6	0
+29963	4	0
+3972	9	5
+1637	0	9
+7977	1	0
+1973	0	3
+1212	0	5
+372	29	19
+1216	0	50
+628	0	4
+8388	0	1
+1429	1	0
+3029	2	4
+785	1	0
+291	10	9516
+1642	0	1
+5042	1	0
+1117	1	0
+1558	8	7
+1475	4	0
+1859	0	1
+9528	0	1
+877
+
+chain	31999718	6_random	1875562	+	165017	507468	6	171115067	-	55532370	55875067	101
+42954	0	1
+24905	1	0
+579	0	6
+612	0	1
+1128	0	2
+5541	1	1
+30	1	1
+2064	1	0
+505	0	1
+1974	0	1
+5299	1	1
+16	1	1
+368	1	1
+28	1	1
+7024	1	0
+19574	8	9
+6646	4	0
+6060	0	1
+2290	0	1
+22638	6	58
+1402	0	1
+502	0	1
+218	0	1
+5768	0	1
+178	0	3
+659	1	1
+33	0	8
+92	4	0
+693	0	2
+1190	0	3
+375	5	0
+422	3	0
+2215	1	0
+7271	1	1
+33	1	1
+817	1	1
+67	1	1
+2442	1	1
+62	16	0
+165	1	0
+1535	1	1
+32	1	1
+596	4	4
+627	1	1
+22	1	2
+201	5	5
+35	1	1
+232	5	0
+651	4	4
+26	1	1
+105	1	1
+45	1	1
+325	1	1
+34	1	1
+265	1	1
+91	2	0
+1383	1	1
+35	1	1
+1469	19	19
+295	0	1
+644	0	1
+3324	1	1
+44	1	1
+1797	1	5
+21	2	0
+10	11	1
+58	2	0
+61	1	9
+715	0	1
+388	1	1
+47	1	1
+774	1	0
+571	0	3
+2308	0	1
+103	15	15
+1339	1	1
+19	1	1
+348	0	1
+372	1	1
+31	0	1
+4	4	0
+14	1	5
+14	1	25
+4634	1	1
+16	2	2
+305	27	24
+2252	10	217
+1695	0	2
+2541	0	7
+741	2	0
+1401	0	2
+202	2	13
+3853	1	0
+3037	36	0
+18	2	0
+25	94	0
+14	0	4
+487	0	1
+5889	0	1
+572	1	1
+17	1	1
+806	1	1
+24	1	1
+723	0	2
+1640	1	0
+2023	1	1
+21	1	1
+192	15	1
+994	0	106
+1362	2	0
+324	1	1
+19	1	1
+683	1	1
+39	1	0
+771	1	0
+1211	13	0
+1728	1	1
+23	1	1
+911	0	2
+1042	6	6
+206	5	0
+17	1	1
+3351	14	19
+783	1	1
+48	1	1
+673	0	4
+137	1	1
+23	1	0
+1357	4	0
+254	0	1
+1408	0	7
+564	1	1
+49	1	1
+319	13	13
+721	12	12
+821	2	0
+912	4	4
+47	1	1
+148	1	1
+61	1	1
+267	1	1
+46	1	1
+421	1	1
+36	1	1
+577	1	1
+35	1	1
+122	1	1
+95	1	1
+241	1	1
+40	1	1
+585	10	1
+1286	0	1
+97	2	0
+22	1	1
+969	0	1
+1448	14	20
+2000	1	0
+1448	0	1
+2390	1	1
+18	5	5
+1421	1	0
+412	0	1
+1867	2	1
+179	3	0
+852	1	0
+1426	20	18
+151	1	1
+26	1	1
+581	1	1
+86	2	1
+2659	1	0
+12163	2	0
+1149	13	13
+818	16	16
+113	1	1
+51	1	1
+343	1	1
+91	0	4
+7	2	0
+8	0	2
+914	1	1
+28	1	1
+670	1	0
+151	7	7
+1887	18	18
+119	0	5
+2395	2	0
+4395	0	6
+380	6	1
+423	17	17
+531	1	0
+23	0	6
+592	1	1
+23	1	0
+844	4	0
+1497	6	0
+407	17	17
+341	19	17
+1020	0	6
+178	1	0
+1233	0	1
+1861	0	1
+2007	2	0
+6480	1	1
+36	1	1
+6817	17	20
+3356	7	5
+1788	1	1
+83	0	1
+7678	18	18
+2095	1	1
+19	1	1
+4934
+
+chain	25195472	6_random	1875562	+	615192	884135	6	171115067	+	167833423	168297434	120
+2006	1	0
+2654	1	1
+28	1	1
+3139	1	1
+85	1	1
+690	0	1
+639	0	2
+1589	4	4
+122	2	0
+1127	0	1
+1104	1	102
+18	0	29
+40	0	3
+22	1	4
+50	0	26
+56	124	195105
+10440	18	25
+3042	0	24
+72	0	8
+206	4	0
+146	4	0
+2483	0	4
+702	0	1
+1035	0	8
+85	3	1
+2710	1	1
+84	1	1
+3774	1	1
+58	1	1
+20613	15	53
+14	32	0
+52	0	4
+1883	4	0
+52	3	0
+44036	171	0
+2224	2	2
+57	1	1
+7263	0	64
+5311	0	2
+24677	8	8
+1972	1	0
+3543	2	2
+46	1	0
+11768	1	0
+494	47	19
+36447	1	1
+67	1	1
+11347	8	0
+4230	1	3
+591	5	5
+1020	0	8
+680	1	1
+60	1	1
+4536	0	1
+1417	0	2
+2471	1	1
+22	1	1
+6781	0	5
+4943	5	0
+1067	2	0
+2588	2	0
+523	34	35
+9266	0	2
+3897	0	2
+1404	0	1
+3120	0	1
+2566	1	0
+1825	0	8
+5342
+
+chain	9830417	6_random	1875562	+	510011	615192	5	180915260	-	108917398	109022458	335
+331	57	57
+1247	1	0
+4094	15	15
+6775	12	0
+6148	1	0
+30	1	1
+251	0	1
+26	26	1
+238	1	1
+29	1	1
+148	1	1
+41	1	1
+5831	6	7
+2439	1	0
+4247	12	42
+2333	1	9
+3039	5	0
+476	2	2
+4359	0	1
+1237	11	11
+1223	12	0
+2800	2	0
+2660	0	1
+4531	1	1
+24	1	1
+7407	0	1
+395	2	0
+1841	391	0
+410	50	26
+321	1	1
+27	1	1
+226	9	9
+157	6	6
+80	1	1
+70	1	1
+5158	10	10
+1385	4	0
+991	0	2
+48	1	1
+1083	0	2
+751	0	1
+4266	1	1
+48	1	1
+1557	0	304
+1552	1	1
+21	1	1
+2652	1	0
+598	0	8
+115	15	16
+1277	1	1
+38	1	1
+898	1	1
+27	1	1
+699	0	1
+34	1	1
+279	4	0
+12	1	1
+2863	1	1
+25	1	1
+2484	12	15
+1447	1	0
+8689
+
+chain	8736931	6_random	1875562	+	25094	155092	6	171115067	-	3172994	3267843	378
+3079	5	5
+1125	2	0
+1270	7	14
+1955	1	1
+47	1	1
+4538	38	38
+1300	25	26
+67	7	8
+176	3	0
+1132	3	0
+906	103	48
+5311	0	16
+133	1	0
+94	153	987
+142	13	13
+2453	2	0
+238	2	0
+960	13	13
+4697	1	1
+26	1	1
+3575	36650	734
+4434	0	1
+5190	138	107
+33	1	1
+5998	4	0
+1660	1	0
+4740	1	1
+29	1	1
+7196	0	12
+17519	30	29
+12768
+
+chain	553807	6_random	1875562	+	1768811	1774813	4	191154276	-	111879139	111885141	10762
+1294	2	2
+109	1	1
+242	1	1
+106	1	1
+2122	1	1
+17	1	1
+200	1	1
+40	1	1
+1071	1	1
+24	1	1
+284	1	1
+77	1	1
+403
+
+chain	255982	6_random	1875562	+	1456339	1459136	6	171115067	+	157377507	157380303	364419
+1101	4	4
+21	1	0
+70	43	44
+1490	1	0
+66
+
+chain	238316	6_random	1875562	+	1453720	1456237	6	171115067	-	13762873	13765390	431401
+2517
+
+chain	190390	6_random	1875562	+	1355230	1357270	6	171115067	-	13765611	13767650	644275
+875	0	1
+30	1	0
+7	0	1
+32	2	0
+1093
+
+chain	147846	6_random	1875562	+	163259	164828	10	135534747	-	86648034	86649603	870502
+1569
+
+chain	66179	6_random	1875562	+	509035	509994	6	171115067	-	55868072	55869030	1909901
+52	241	240
+666
+
+chain	39557	6_random	1875562	+	507468	508471	14	107349540	-	76514262	76515265	2447482
+67	13	13
+252	48	48
+70	43	43
+73	340	340
+97
+
+chain	15445	6_random	1875562	+	574580	574743	6	171115067	+	168277787	168277950	14597733
+163
+
+chain	11899	6_random	1875562	+	508034	508258	7	159138663	-	61729371	61729595	2527246
+50	119	119
+55
+
+chain	6795	6_random	1875562	+	508264	508336	5	180915260	+	74550099	74550171	28643390
+72
+
+chain	5830	6_random	1875562	+	884328	884389	6	171115067	-	37135398	37135459	31091070
+61
+
+chain	5767	6_random	1875562	+	508601	508846	8	146364022	+	54253304	54253548	3655159
+50	103	102
+92
+
+chain	4821	6_random	1875562	+	16131	16182	10	135534747	-	59552661	59552712	34213212
+51
+
+chain	3598	6_random	1875562	+	720272	720329	6	171115067	+	168133749	168133806	2857460
+57
+
+chain	3185	6_random	1875562	+	1768774	1768810	2	243199373	+	130168617	130168653	16948
+36
+
+chain	2982	6_random	1875562	+	508896	508970	12	133851895	-	4327021	4327095	12758815
+74
+
+chain	2685	6_random	1875562	+	509240	510388	3	198022430	-	97729559	97730704	3388749
+33	1069	1066
+46
+
+chain	2530	6_random	1875562	+	720329	720365	6	171115067	+	168133920	168133956	3810246
+36
+
+chain	2208	6_random	1875562	+	720386	720422	6	171115067	+	168133692	168133728	3917950
+36
+
+chain	1957	6_random	1875562	+	507800	507848	1	249250621	-	36684504	36684552	2679811
+48
+
+chain	1423	6_random	1875562	+	508846	508894	2	243199373	-	143356177	143356225	7803118
+48
+
+chain	1172	6_random	1875562	+	508537	508601	X	155270560	+	123719418	123719482	4007841
+64
+
+chain	1047	6_random	1875562	+	509273	509328	20	63025520	+	3479096	3479151	2808508
+55
+
+chain	560	6_random	1875562	+	508669	508719	5	180915260	-	128392227	128392277	20287927
+50
+
+chain	14618906734	7	158821424	+	102995	158821424	7	159138663	+	10238	159128663	7
+973	5	0
+3912	0	2
+1234	4	0
+51	0	6
+70	1	1
+24	1	0
+143	8	0
+16	170	1
+47	1	1
+243	0	6
+913	3	0
+2538	980	0
+63	1610	0
+1362	0	1
+2104	0	456
+1158	0	1
+791	1	1
+49	0	1
+4175	8	0
+17	1	1
+4845	12	0
+2509	0	1
+1697	6	6
+192827	150000	278557
+5682472	0	1
+42007910	40000	35970
+4371	7	16
+17699	0	4
+5249	4	0
+2088410	1	1
+47	1	1
+4565	0	1
+7116	0	1
+2706	40000	43050
+6577293	50000	13552
+1052855	3000000	3000000
+256182	50000	416507
+190137	50000	50000
+5722629	24	25
+239	1	1
+59	2	2
+138	1	1
+34	1	1
+206	1	3
+18	1	0
+410	1	1
+72	1	1
+199	1	1
+62	5	5
+120	1	0
+468	1	1
+32	1	1
+264	1	1
+23	1	1
+1459	4	4
+107	1	1
+42	1	0
+14	1	1
+201	1	1
+46	1	1
+268	20	20
+303	2	1
+866	0	4
+76	3	3
+63	1	1
+74	1	0
+25	1	1
+66	1	1
+34	0	2
+180	35	36
+93	1	1
+41	1	1
+70	1	1
+49	1	1
+63	1	1
+57	1	1
+383	1	1
+133	1	1
+87	1	1
+38	4	4
+50	0	1
+46	5	6
+136	11	11
+200	1	1
+63	4	0
+6	9	0
+263	1	1
+32	3	3
+152	16	16
+567	1	0
+322	3	0
+1258	0	1
+505	4	0
+1141	11	10
+537	12	12
+1418	1	1
+47	0	1
+164	7	7
+90	5	0
+156	1	1
+20	1	1
+380	3	3
+41	3	0
+5	2	2
+921	1	1
+34	1	1
+1607	2	2
+73	66	0
+46	14	0
+168	1	1
+53	1	1
+3195	1	1
+23	1	1
+2115	0	14
+9872	1	0
+1204	13	13
+416	1	0
+2311	319	0
+6906	0	10
+184	24	0
+2933	4	0
+1392	0	12
+1856	5	0
+3439	0	1
+469	3	0
+771	15	12
+497	1	1
+65	1	1
+1210	0	2
+4131	10	10
+1198	1	0
+718	1	1
+21	1	1
+3668	1	0
+874	1	1
+25	1	1
+2444	0	1
+1867	1	1
+29	1	1
+1660	0	1
+1232	0	6
+784	1	0
+705	0	3
+3577	1	0
+365	1	0
+3389	8	4
+2652	0	3
+664	0	1
+169	1	0
+8	1	1
+138	0	1
+8037	0	56
+112	196	0
+495	0	35
+3028	1	1
+40	1	1
+1068	4	0
+631	0	33
+29	2	0
+86	9	1
+3081	2	0
+806	0	1
+21	1	1
+3901	26	27
+843	0	1
+6916420	250000	50000
+25789103	0	51216
+1399994	1	0
+3623	0	212
+38	1	1
+210	1	0
+5	1	0
+6	1	0
+18	1	0
+1321	16	0
+2187	1	0
+145	0	1
+1388	7	7
+2240	14	14
+771	1	1
+34	1	1
+92	1	1
+39	1	1
+505	1	0
+66	1	1
+49	1	1
+159	1	0
+78	3	0
+15	2	0
+7	1	0
+28	1	0
+27	468	5
+2022	1	0
+1796	7	7
+61	1	1
+20	1	1
+4560	3	0
+157730	1	0
+194	14	14
+650	0	12
+717	26	26
+819	0	5
+278	60	32
+69	0	5
+1345	8	0
+652	84	0
+118	0	4
+498	0	1
+3187	1	1
+43	1	1
+1476	0	3
+2101	5	0
+788	6	6
+872	0	6
+893	3	0
+155	33	33
+4610	5	7
+521	10	0
+2773	40	40
+627	43	43
+1424	0	1
+2554	8	8
+44	0	7
+615	1	1
+32	3	0
+2693	0	1
+1029	0	2
+151	0	1
+1753	0	21
+370	2	3
+969	0	1
+452	1	0
+3035	1	1
+40	1	1
+704	0	2
+2472	0	6
+238	1	0
+1442	1	1
+37	5	5
+126	0	1
+795	0	1
+1191	1	0
+171	17	16
+724	6	5
+2988	40	42
+359	2	0
+199	19	19
+1969	1	0
+251	0	1
+729	0	1
+992	27	27
+205	4	0
+3209	0	2
+1006	8	10
+1571	10	10
+756	0	1
+36	1	1
+433	0	1
+672	0	3
+4430	157	0
+5606	5	1
+17	1	1
+942	10	9
+3433	2	1
+24	1	1
+4262	13	0
+661	2	0
+167	8	0
+3474	6	11
+217	0	2
+778	34	34
+158	0	1
+1167	0	1
+684	0	1
+878	39	39
+2012	0	1
+345	52	52
+640	0	2
+27874045	0	136705
+2519	0	2
+1000	8	0
+14695	1	0
+4456	1	0
+2977	1	0
+9065130	25000	29055
+2369	1	0
+12174	18	20
+877	0	4
+5247	0	12
+3483	2	0
+6766	0	1
+2469878	0	1
+734	2	2
+99	0	1
+2471	1	1
+11	1	1
+758	8	0
+2234	13	14
+8394	1	0
+47	1	1
+903	0	1
+5537	0	1
+269	1	0
+7114	1	1
+30	1	1
+2412	0	1
+2442	21	21
+91	1	1
+37	1	1
+96	1	1
+22	1	1
+246	1	1
+23	1	1
+254	12	12
+569	1	1
+27	1	1
+1624	1	0
+112	3	3
+45	1	1
+384	13	13
+70	1	0
+658	1	1
+20	1	1
+176	1	0
+307	19	19
+428	1	1
+19	1	1
+87	1	1
+30	1	1
+140	1	0
+292	2	0
+1492	1	0
+302	0	2
+364	1	1
+35	1	1
+1956	0	1
+728	12	12
+6522	2	2
+1531	1	0
+488	1	0
+2056	18	8
+1286	1	1
+27	1	1
+731	1	0
+1423	0	7
+2010	1	1
+19	1	1
+6423	0	4
+57	1	1
+4505	13	0
+933	0	12
+1250	0	1
+1313	1	0
+2610	0	1
+2398	0	1
+453	1	0
+346	1	1
+12	1	1
+83	25	25
+83	12	12
+277	0	1
+45	1	0
+811	2	0
+164	0	1
+104	0	1
+32	1	1
+1386	0	14
+306	1	1
+43	1	1
+2765	0	1
+1819	0	1
+1480	1	1
+24	1	1
+276	0	1
+21	0	1
+119	2	0
+12	26	0
+541	1	1
+63	1	1
+180	0	1
+2456	1	0
+1055	1	0
+1166	2	0
+784	0	4
+170	1	0
+939	6	0
+5597	15	15
+1253	0	1
+3336	0	18
+1851	9	0
+45	1	1
+657	38	38
+4099	0	1
+1387	2	0
+1460	1	0
+204	0	5
+1506	0	1
+2621	1	0
+6620	0	1
+34	1	1
+249	1	0
+1440	0	10
+245	0	1
+368	1	9
+257	4	0
+1589	6	0
+1543	0	1
+4189	120	0
+354	312446	278046
+3734	24	25
+3097	1	0
+8	1	1
+4861	0	4
+5649	1	0
+2011	0	1
+4344	24	24
+10546	42	1467
+20955	0	1
+2075	2	1
+5546	1	0
+2168	4	0
+1266	1	0
+4124	1	1
+46	1	1
+54	1	1
+43	15	0
+780	1	1
+25	1	1
+497	0	1
+46	1	1
+810	0	1
+5701	0	1
+6998	0	1
+2002	0	3
+7160	1	1
+24	1	1
+479	2	0
+1872	0	1
+1192	1	0
+371	2	0
+31	1	1
+572	16	16
+1725	16	16
+588	1	1
+90	1	1
+2483	3	19
+187	0	1
+20	1	1
+3673	1	1
+27	4	0
+3021	1	0
+1323	19	6
+498	13	13
+1618	2	0
+5282	0	1
+719	0	8
+2994	1	0
+2822	0	2
+1396	1	1
+48	1	1
+8723	5	0
+291	1	1
+25	1	1
+116	0	1
+2809	1	1
+27	1	1
+224	1	1
+48	1	1
+292	0	2
+400	0	1
+754	1	1
+19	1	1
+4225	1	1
+28	1	1
+801	1	0
+671	1	1
+17	1	1
+390	1	1
+28	1	1
+84	7	7
+568	1	1
+56	1	1
+499	7	8
+266	1	1
+31	1	1
+518	18	18
+164	1	1
+50	1	1
+162	1	1
+60	1	1
+702	1	1
+28	1	1
+146	18	17
+517	1	1
+24	1	1
+686	12	12
+101	1	1
+22	5	5
+107	5	5
+277	9	9
+272	1	1
+48	1	1
+77	1	1
+67	1	1
+1548	1	1
+40	1	1
+763	1	1
+42	1	1
+541	8	8
+88	1	1
+77	1	1
+233	11	11
+311	1	1
+22	1	1
+147	1	8
+504	1	1
+26	1	1
+987	20433	0
+3090	1	0
+405	5	5
+1811	1	0
+1174	0	1
+70	1	1
+1100	10143	18
+2722	0	1
+2957	1	1
+32	1	1
+9585	0	1
+1350	0	1
+473	0	1
+675	0	1
+1435	0	1
+805423	0	79189
+10872737	100000	100000
+721570	1	1
+19	1	1
+816	1	1
+44	1	1
+572	8	6
+2021	0	4
+1001	2	0
+3757	1	0
+5942	2	2
+70	1	1
+100	7	7
+395	80000	17188
+1010	1	1
+45	1	1
+1486	18	18
+173	1	17
+15	1	17
+158	0	192
+33	0	368
+50	50	2
+40	1	1
+95	4	52
+60	39	8
+15	16	0
+92	16	0
+1589	0	1
+897	13	13
+28	3	3
+2454	1	1
+44	1	1
+301	0	468
+2030	1	1
+45	1	1
+1277	8	0
+1716	1	0
+1579	11	15
+2439	36	0
+39	37	1
+349	21	92
+2096	13	11
+192	1	1
+48	1	1
+130	1	1
+22	1	1
+970	1	1
+23	4	0
+64	0	14
+129	17	11
+154	13	14
+53	15	5
+48	1	1
+47	0	2
+114	18	16
+363	1	1
+43	1	1
+559	1	1
+32	1	1
+3980007
+
+chain	16701236	7	158821424	+	141723881	141902219	7	159138663	-	16862466	17040468	171
+1662	1	1
+69	1	1
+887	1	1
+16	1	1
+115	339	1
+1512	0	1
+3597	0	1
+309	2	0
+34	1	1
+623	0	2
+1746	2	0
+816	4	0
+7868	1	0
+22	0	4
+593	0	1
+2757	0	1
+1147	7	7
+134	1	1
+42	1	1
+669	1	1
+25	1	1
+539	1	1
+49	1	1
+1387	1	1
+53	0	1
+19	1	1
+878	1	1
+27	1	1
+9739	1	1
+15	1	1
+2064	0	1
+1069	1	1
+31	1	1
+612	0	1
+21	1	1
+821	2	0
+1002	2	0
+3478	4	0
+1394	1	1
+25	1	0
+60	1	0
+4	1	0
+10	1	0
+23	0	1
+12	0	1
+2396	1	1
+25	1	1
+401	0	2
+1918	0	2
+43	1	1
+806	1	1
+36	1	1
+126	1	1
+53	1	1
+411	5	5
+524	13	13
+2896	1	1
+62	1	1
+4194	2	0
+8269	2	0
+368	11	10
+546	1	0
+1040	2	0
+45	1	1
+234	1	1
+29	1	1
+1218	16	16
+206	11	11
+584	13	13
+334	4	4
+167	3	3
+31	1	1
+973	9	9
+142	81	81
+58	1	0
+74	1	0
+1707	19	19
+2413	1	1
+57	1	1
+160	1	1
+23	1	1
+2380	0	1
+5561	0	4
+2790	14	14
+76	3	0
+1823	1	1
+11	0	9
+6	2	0
+5	3	0
+9	5	0
+28	1	1
+727	1	1
+37	1	1
+2678	0	3
+1497	1	0
+3414	1	0
+1171	6	6
+4018	7	7
+269	1	1
+36	1	1
+366	1	1
+22	1	1
+916	0	9
+2431	1	1
+68	1	1
+855	4	4
+1052	2	2
+81	0	2
+45	7	7
+648	1	1
+27	1	1
+402	1	0
+791	1	1
+41	1	1
+1041	20	20
+1094	1	1
+29	4	0
+364	1	1
+40	0	1
+22	0	1
+124	0	1
+205	0	1
+720	0	1
+59	1	1
+1063	2	0
+112	2	0
+3106	15	15
+2542	1	1
+64	1	1
+3052	1	1
+73	1	1
+3722	1	1
+31	1	1
+3476	1	0
+229	1	1
+40	1	1
+1321	0	5
+1845	1	0
+558	5	5
+3811	19	19
+125	1	1
+25	1	1
+3387	1	0
+1781	4	4
+2191	0	1
+1201	0	1
+260	1	1
+17	7	7
+137	0	1
+38	1	1
+732	0	1
+1626	1	0
+1987	2	0
+45	1	1
+763	0	1
+1978	0	1
+135	1	0
+6209	1	0
+24	1	1
+4867	0	1
+171	0	1
+6299
+
+chain	6490016	7	158821424	+	34000	116005	16	90354753	-	90001	171511	354
+591	11	11
+383	0	4
+1364	1	0
+430	12	13
+1431	1	1
+21	1	1
+490	12	12
+509	1	1
+97	1	1
+604	2	0
+1188	1	3
+665	1	1
+22	6	0
+499	1	1
+19	1	1
+402	1	1
+51	1	1
+1193	0	4
+245	1	0
+688	0	1
+975	2	0
+463	0	23
+73	24	0
+32	7	0
+165	1	0
+1593	1	1
+20	1	1
+1203	1	1
+31	1	1
+740	2	0
+47	1	1
+485	1	1
+63	1	1
+381	5	0
+28	1	1
+254	1	1
+22	1	1
+306	0	1
+34	1	1
+283	0	2
+627	10	10
+74	1	1
+50	1	1
+1053	0	1
+54	1	1
+77	1	1
+210	1	1
+70	0	3
+1957	0	4
+2154	1	1
+69	1	1
+147	67	67
+69	1	1
+74	1	1
+242	1	1
+41	1	1
+63	5	5
+155	3	1
+101	1	1
+53	1	1
+877	1	1
+21	1	1
+60	1	1
+49	1	1
+167	1	1
+21	1	1
+623	15	15
+202	0	97
+86	0	49
+9	2	2
+84	5	248
+56	1	98
+40	0	1
+48	1	0
+87	1	1
+55	99	1
+50	50	0
+23	1	1
+81	0	194
+78	1	1
+55	3	3
+53	6	344
+15	1	1
+262	1	1
+80	1	1
+455	1	1
+108	3	3
+431	1	1
+101	1	1
+158	1	0
+9	1	1
+323	3	0
+85	1	1
+19	1	1
+345	32	0
+24	1	1
+342	1	1
+65	1	1
+90	8	8
+545	1	1
+130	2	2
+87	4	3
+62	3	3
+34	2	2
+77	1	1
+47	1	1
+61	1	1
+27	1	1
+224	7	7
+117	2	0
+17	1	1
+242	1	1
+34	1	1
+107	1	1
+36	1	1
+100	15	15
+154	0	8
+13	1	0
+34	5	5
+100	27	27
+263	11	11
+116	1	1
+41	1	1
+117	1	1
+49	1	1
+116	2	0
+70	1	1
+174	1	1
+125	1	1
+70	1	1
+30	1	1
+74	1	1
+32	1	1
+337	1	1
+49	1	1
+2127	1	1
+35	1	1
+538	1	1
+32	1	1
+744	10	10
+471	53	17
+2001	7	7
+453	1	0
+2656	0	1
+1785	1	0
+1454	1	1
+33	1	1
+419	1	1
+49	1	1
+4610	1	1
+36	1	1
+905	1	1
+13	0	2
+5128	17	17
+519	0	3
+613	7	0
+660	0	4
+2632	1	2
+278	21	21
+969	1	0
+2852	14	14
+149	1	1
+21	1	1
+198	1	1
+29	1	1
+801	6442	6416
+125	6	0
+39	3745	3755
+814	162	1
+4	63	63
+74	63	0
+47	1056	13
+370
+
+chain	227647	7	158821424	+	141707499	141716076	7	159138663	+	142043811	142047809	475649
+53	484	465
+55	51	51
+78	242	220
+60	274	271
+51	13	13
+51	37	37
+229	4	4
+228	16	16
+108	47	47
+50	4583	49
+498	131	130
+945	36	36
+253
+
+chain	87685	7	158821424	+	58756	115635	3	198022430	-	71488	126874	406
+67	3328	3375
+28	1	1
+29	2	2
+39	50	50
+7	2	2
+41	2708	1663
+32	2831	2828
+27	46647	46820
+96	378	0
+152	47	12
+72	252	0
+43
+
+chain	48969	7	158821424	+	142175391	142175904	7	159138663	+	142475439	142475952	2613549
+513
+
+chain	47803	7	158821424	+	141911444	141913842	7	159138663	-	17029555	17031946	2683091
+78	139	139
+57	226	225
+124	92	92
+56	135	135
+72	193	193
+53	23	23
+133	958	952
+59
+
+chain	43189	7	158821424	+	142199519	142199970	7	159138663	+	142498738	142499189	3009311
+451
+
+chain	30396	7	158821424	+	67364377	67364696	15	102531392	-	56463077	56463396	4465114
+319
+
+chain	30094	7	158821424	+	141700053	141707301	7	159138663	+	142042846	142043613	4669748
+89	15	15
+68	6585	104
+66	129	129
+62	35	35
+199
+
+chain	30060	7	158821424	+	141963578	141964737	11	135006516	+	33264685	33266127	4680203
+91	398	397
+87	228	512
+77	163	163
+115
+
+chain	28591	7	158821424	+	141910578	141910878	7	159138663	-	17028690	17028990	5361712
+300
+
+chain	21822	7	158821424	+	141716123	141716468	7	159138663	+	142047850	142048195	9124304
+170	99	99
+76
+
+chain	20144	7	158821424	+	142166403	142167075	9	141213431	+	33792981	33793662	10344618
+82	380	389
+66	18	18
+51	19	19
+56
+
+chain	16654	7	158821424	+	101805867	101806156	7	159138663	-	92369277	92369565	11127744
+33	12	11
+63	91	91
+90
+
+chain	14923	7	158821424	+	102039289	102039446	7	159138663	+	102153090	102153247	2823
+157
+
+chain	10542	7	158821424	+	115456	115592	16	90354753	-	170836	170972	2672410
+136
+
+chain	10012	7	158821424	+	114469	115025	9	141213431	-	90660	90901	550
+63	395	80
+98
+
+chain	9195	7	158821424	+	141943788	141943884	7	159138663	-	16914722	16914818	24637833
+96
+
+chain	8667	7	158821424	+	142177809	142178136	7	159138663	+	142477851	142478180	25450135
+54	219	221
+54
+
+chain	7349	7	158821424	+	142180607	142180684	7	159138663	+	142480664	142480741	27551182
+77
+
+chain	7340	7	158821424	+	142180197	142180274	7	159138663	+	142480253	142480330	27565643
+77
+
+chain	6886	7	158821424	+	141960844	141960917	8	146364022	-	77913390	77913463	28463282
+73
+
+chain	6730	7	158821424	+	102059075	102062034	7	159138663	+	102172727	102175692	3338
+34	2887	2893
+38
+
+chain	6431	7	158821424	+	142166514	142166582	7	159138663	+	142454997	142455065	29498865
+68
+
+chain	6414	7	158821424	+	114166	115456	9	141213431	-	90644	91234	1816570
+68	791	378
+44	328	41
+59
+
+chain	6276	7	158821424	+	142176939	142177005	7	159138663	+	142476982	142477048	29891950
+66
+
+chain	6166	7	158821424	+	142179945	142180009	7	159138663	+	142480002	142480066	30171758
+64
+
+chain	5761	7	158821424	+	141963726	141963989	14	107349540	-	25420241	25420503	6848073
+68	130	129
+65
+
+chain	5666	7	158821424	+	142179798	142179857	7	159138663	+	142479855	142479914	31548103
+59
+
+chain	5608	7	158821424	+	101977370	101977454	7	159138663	+	44036096	44036185	7960
+10	0	5
+74
+
+chain	5430	7	158821424	+	142178562	142178619	7	159138663	+	142478613	142478670	32231795
+57
+
+chain	5139	7	158821424	+	142176520	142176574	7	159138663	+	142476565	142476619	33117712
+54
+
+chain	5020	7	158821424	+	141966623	141966675	12	133851895	+	53762512	53762564	33527602
+52
+
+chain	4939	7	158821424	+	142176195	142176247	7	159138663	+	142476241	142476293	33775264
+52
+
+chain	4778	7	158821424	+	73598	73651	5	180915260	-	172444	172497	587
+53
+
+chain	4039	7	158821424	+	101996220	101996263	7	159138663	+	102308194	102308237	1871
+43
+
+chain	3908	7	158821424	+	142167123	142167183	7	159138663	+	142455620	142455680	17639294
+60
+
+chain	3217	7	158821424	+	141963833	141963883	6	171115067	-	41704900	41704950	22743877
+50
+
+chain	2759	7	158821424	+	67423135	67423165	7	159138663	+	67785172	67785202	11329361
+30
+
+chain	2575	7	158821424	+	67423107	67423135	7	159138663	+	67785172	67785200	11329362
+28
+
+chain	2575	7	158821424	+	67423079	67423107	7	159138663	+	67785172	67785200	11329363
+28
+
+chain	2575	7	158821424	+	67423051	67423079	7	159138663	+	67785172	67785200	11329364
+28
+
+chain	2575	7	158821424	+	67423023	67423051	7	159138663	+	67785172	67785200	11329365
+28
+
+chain	2575	7	158821424	+	67422995	67423023	7	159138663	+	67785172	67785200	11329366
+28
+
+chain	2457	7	158821424	+	114257	114311	16	90354753	-	170806	170860	17475755
+54
+
+chain	2391	7	158821424	+	67422969	67422995	7	159138663	+	67785202	67785228	13667102
+26
+
+chain	2359	7	158821424	+	101974113	101974139	7	159138663	+	102286210	102286236	158723
+26
+
+chain	1502	7	158821424	+	141709533	141709580	7	159138663	+	142013474	142013521	12917072
+47
+
+chain	721	7	158821424	+	141963699	141963726	17	81195210	+	19853796	19853823	7983736
+27
+
+chain	615	7	158821424	+	141964154	141964190	19	59128983	-	28688778	28688814	21921932
+36
+
+chain	362	7	158821424	+	101987601	101987634	7	159138663	-	57149003	57149036	1101
+33
+
+chain	17312866	7_random	549659	+	162804	345700	GL000195.1	182896	+	0	182896	164
+182896
+
+chain	10142542	7_random	549659	+	0	112804	7	159138663	+	158928464	159038297	315
+4073	0	1
+5056	1	0
+1766	1	1
+63	5	5
+2422	1	0
+1297	1	0
+1967	196	0
+230	28	0
+2331	5	0
+47	1	1
+345	1	0
+41	1	1
+807	1	1
+31	1	1
+238	3	0
+100	1	0
+281	1	1
+43	1	1
+359	27	26
+59	1	1
+43	1	1
+1385	1	0
+161	1	0
+45	1	1
+1693	1	0
+93	1	0
+5	1	0
+805	0	3
+649	0	49
+1400	1	1
+4	1	0
+28	0	1
+7	0	1
+157	1	1
+117	0	31
+166	13	12
+138	1	0
+556	1	1
+46	1	1
+204	1	1
+21	1	1
+511	2	0
+390	1	1
+29	1	1
+60	1	1
+68	0	3
+27	1	1
+71	0	1
+37	5	0
+18	0	6
+56	3	3
+89	2	0
+103	6	15
+43	5	0
+7	0	11
+55	0	4
+456	46	45
+1286	1	1
+46	1	0
+36	2	0
+57	1	0
+396	1	1
+38	1	1
+298	1	1
+16	1	1
+602	224	0
+82	1	56
+1115	1	74
+17	3	3
+88	1	74
+98	158	12
+90	3	3
+70	3	3
+117	1	1
+43	1	1
+53	1	1
+21	1	1
+53	229	10
+120	81	8
+59	8	10
+411	1	0
+47	1	1
+723	0	9
+8142	6	6
+1297	1	1
+22	0	1
+7799	12	11
+1878	1	0
+70	5	5
+592	1	1
+28	1	1
+2251	1	0
+1474	1	0
+1975	0	1
+2577	0	1
+612	15	15
+93	1	0
+3	1	0
+149	1	0
+61	3	3
+34	1	0
+11	2101	0
+63	73	3
+67	106	1
+57	83	13
+60	70	0
+79	561	1
+321	70	0
+262	0	35
+83	183	8
+2406	0	549
+85	32	0
+27	0	26
+72	0	35
+22	3	0
+24	0	93
+74	2	0
+17	28	0
+63	1	0
+6	1	0
+1451	44	4
+23	1	1
+38	0	40
+80	1	121
+34	1	1
+58	0	82
+839	1	0
+31	1	1
+2861	0	4
+1376	1	1
+20	0	1
+78	2	0
+24	2	2
+2760	3	1
+585	8	0
+761	1	0
+6449	4	1
+259	1	1
+22	1	1
+717	0	1
+887	7	8
+2174	3	0
+970	1	0
+1768	12	0
+4378	0	1
+5	0	1
+13	1	0
+1637	5	10
+312	0	1
+2167	11	0
+164	10	10
+1517	1	1
+42	0	3
+698	0	4
+90	1	1
+20	1	1
+167	1	1
+16	1	1
+860	0	1
+1719
+
+chain	9633059	7_random	549659	+	402818	549659	7	159138663	+	514489	666751	345
+3766	22099	5004
+26	4	4
+11014	7	5
+17	1	0
+8	21	0
+3389	1	1
+54	1	1
+55	1	1
+66	1	1
+165	1	1
+38	1	1
+52	22350	21842
+816	4	4
+10432	15	15
+20532	1	1
+29	9	9
+13871	157	23205
+37837
+
+chain	2073422	7_random	549659	+	444161	465736	7	159138663	-	158510053	158531628	1246
+21575
+
+chain	1225579	7_random	549659	+	415456	428202	7	159138663	+	537499	550245	1943
+12746
+
+chain	745495	7_random	549659	+	406711	414469	7	159138663	-	158580384	158588142	6708
+215	11	11
+2423	4	4
+5105
+
+chain	224185	7_random	549659	+	399770	402202	7	159138663	+	518876	521308	490490
+367	50	50
+1609	1	1
+53	3	3
+304	1	1
+44
+
+chain	25943	7_random	549659	+	67571	70764	7	159138663	+	158995434	158996421	1881723
+67	73	3
+55	13	153
+17	71	0
+159	183	8
+119	21	21
+154	1960	0
+64	35	0
+105	35	0
+62
+
+chain	21070	7_random	549659	+	68795	70055	7	159138663	+	158995572	158996097	2684005
+86	98	63
+43	35	0
+76	455	0
+18	248	38
+61	57	57
+83
+
+chain	19298	7_random	549659	+	67796	68209	7	159138663	+	158995799	158996246	2040899
+35	195	229
+183
+
+chain	8295	7_random	549659	+	70341	70449	7	159138663	+	158996348	158996421	13908836
+11	35	0
+62
+
+chain	8007	7_random	549659	+	70264	70825	7	159138663	+	158995746	158996237	2373081
+77	186	46
+35	218	288
+45
+
+chain	7010	7_random	549659	+	69669	69742	7	159138663	+	158996026	158996099	13809421
+73
+
+chain	6757	7_random	549659	+	71674	71744	7	159138663	+	158996246	158996316	26425870
+70
+
+chain	6582	7_random	549659	+	16740	16849	7	159138663	+	158945342	158945395	9902405
+48	56	0
+5
+
+chain	5793	7_random	549659	+	36845	36905	7	159138663	+	158964922	158964982	31172491
+60
+
+chain	5504	7_random	549659	+	68645	69446	7	159138663	+	158995947	158996153	2767372
+68	176	1
+63	420	0
+74
+
+chain	5075	7_random	549659	+	34499	34552	7	159138663	+	158962931	158962984	33354772
+53
+
+chain	4386	7_random	549659	+	36139	36193	7	159138663	+	158964435	158964489	9901820
+54
+
+chain	4359	7_random	549659	+	69809	69854	7	159138663	+	158996061	158996106	24027999
+45
+
+chain	3345	7_random	549659	+	71561	71653	7	159138663	+	158995923	158996015	5823696
+92
+
+chain	3242	7_random	549659	+	36212	36249	7	159138663	+	158964435	158964472	7647561
+37
+
+chain	3169	7_random	549659	+	68713	69336	7	159138663	+	158995385	158995658	13517397
+46	500	150
+77
+
+chain	2856	7_random	549659	+	36091	36138	7	159138663	+	158964168	158964215	3415068
+47
+
+chain	2508	7_random	549659	+	74235	74267	7	159138663	+	158999705	158999737	11181217
+32
+
+chain	2422	7_random	549659	+	16701	16740	7	159138663	+	158944995	158945034	20425801
+39
+
+chain	2296	7_random	549659	+	76078	76102	7	159138663	+	159001472	159001496	26237556
+24
+
+chain	1888	7_random	549659	+	68772	68795	7	159138663	+	158995829	158995852	23967691
+23
+
+chain	1646	7_random	549659	+	16653	16684	7	159138663	+	158945171	158945202	6593972
+31
+
+chain	1510	7_random	549659	+	34573	34664	7	159138663	+	158962893	158962984	9181320
+91
+
+chain	1319	7_random	549659	+	70142	70185	7	159138663	+	158996289	158996332	23051286
+43
+
+chain	1065	7_random	549659	+	69520	69582	7	159138663	+	158996297	158996359	18766264
+62
+
+chain	13483752813	8	146274826	+	0	146274826	8	146364022	+	10000	146304022	9
+930417	1	1243
+52	10	10
+44	0	972
+100	0	54
+162	0	324
+409	0	1
+2323216	1	0
+3352649	2	0
+854996	100000	50000
+3399023	1	1
+46	1	1
+13965	1	1
+30	1	1
+121189	1	1
+35	1	1
+283700	0	1
+719291	100016	93054
+1155	0	2
+755	26	26
+980	21	21
+1479	54	54
+3597	1	0
+1937	19	19
+322	1	0
+1758	2	0
+1141	0	1
+956	48	48
+739	21	21
+1005	0	1
+543	1734	1734
+5338	15	15
+1029	1	1
+28	1	1
+305	57	57
+164	27	27
+5130707	0	1
+1288	0	1
+446	1	1
+80	1	1
+2123	4	4
+2514	3	0
+545	9	0
+527	1	1
+18	1	1
+256	9	9
+79	1	1
+40	1	1
+148	0	2
+2231	0	27
+958	1	1
+20	1	1
+2487	1	1
+113	1	1
+73	13	13
+365	10	10
+151	1	1
+32	3	0
+26	1	1
+1480	1	1
+29	1	1
+621	1	1
+28	1	1
+701	9	9
+362	1	1
+19	1	1
+691	1	1
+44	6	0
+47	1	1
+513	12	11
+382	1	1
+22	1	1
+111	1	1
+36	1	1
+337	1	1
+42	1	1
+602	2	0
+36	1	1
+475	1	1
+23	0	1
+32	4	3
+65	1	1
+59	1	1
+688	1	1
+22	1	1
+1473	1	1
+36	1	1
+372	1	1
+16	6	6
+1605	1	1
+38	1	1
+816	1	1
+17	1	0
+374	1	1
+17	1	1
+48	1	0
+82	1	1
+45	1	1
+263	1	1
+23	1	1
+204	1	1
+39	1	1
+2341	0	1
+2989	9	11
+811	8	8
+741	0	2
+337	1	1
+25	4	4
+763	1	1
+19	1	1
+343	1	1
+31	1	1
+1953	1	1
+74	1	1
+67	1	1
+18	4	4
+73	1	1
+31	1	1
+114	11	1
+87	1	1
+65	1	1
+125	9	9
+378	49	48
+90	1	1
+99	1	0
+173	13	7
+696	0	1
+6184	13	13
+830	13	13
+128	1	1
+37	1	1
+136	1	0
+66	5	6
+870	1	0
+4877	0	1
+585	3	7
+1728	1	0
+33	1	1
+465	1	1
+68	1	1
+581	6	0
+2088	1	0
+304	0	1
+2674	1	1
+28	1	0
+54	8	8
+846	0	1
+1409	16	16
+559	0	1
+407	0	5
+11	5	1
+29	1	1
+4051	1	1
+10	0	1
+43	1	1
+385	1	1
+35	1	1
+101	11	11
+602	1	0
+491	14	16
+1366	19	19
+321	1	1
+49	1	1
+546	1	1
+25	1	1
+2568	1	1
+51	4	0
+119	1	1
+39	0	1
+1040	0	1
+1682	0	4
+39	8	0
+862	1	1
+17	1	1
+587	1	1
+21	1	1
+904	0	1
+261	0	1
+1151	0	2
+2325	5	5
+5415	0	3
+1545	1	0
+428	4	4
+1950	2	0
+1073	0	1
+3653	0	86
+1283	1	1
+79	1	1
+6656	12	12
+1550	0	18
+5832	1	0
+4835	10	10
+1719	1	1
+84	1	1
+848	0	2
+236	1	1
+42	1	1
+1272	12	0
+49	1	1
+820	1	1
+22	1	0
+58	0	22
+510	8	8
+983	6	0
+539	14	14
+863	0	2
+27	1	1
+204	14	14
+163	4	4
+290	1	1
+59	1	1
+842	0	2
+2044	1	1
+90	0	1
+3434	0	3
+356	0	1
+873	0	1
+864	25	1
+630	12	7
+62	10	10
+156	11	11
+1364	19	19
+156	4	4
+244	4	18
+505	1	0
+109	1	1
+230	1	1
+107	4	3
+150	1	1
+83	5	5
+70	1	1
+33	1	0
+142	1	1
+626	5	6
+274	10	10
+128	1	1
+35	1	1
+216	1	1
+44	1	1
+312	1	1
+16	1	1
+1496	8	7
+451	0	1
+855	1	1
+20	1	1
+350	1	1
+62	1	1
+617	10	10
+845	1	1
+58	1	1
+2189	1	1
+147	1	1
+475	1	1
+27	1	1
+278	1	1
+17	1	1
+994	1	1
+40	1	1
+219	5	5
+26	1	1
+900	1	1
+29	1	0
+26	1	1
+484	15	16
+61	9	9
+114	21	26
+801	1	1
+33	1	1
+560	1	1
+37	1	1
+80	14	14
+211	1	1
+43	1	1
+156	1	1
+20	1	1
+685	1	1
+18	1	1
+48	4	0
+711	1	1
+38	1	1
+402	7	7
+1045	1	1
+37	1	1
+4035	9	9
+247	4	0
+4146274	17400	5734
+330366	0	1
+2346742	0	55
+413177	3	0
+450	1	0
+9436	3	1
+7044	4	0
+2886	1	0
+635	1	0
+16567	1	0
+6926	29	28
+9249	1	0
+14916	8	0
+12872	2	0
+3330	2	0
+2673376	2	0
+2603	1	1
+78	1	1
+2170491	7	7
+29817	66108	2485
+6473782	5	5
+39	1	1
+9574	0	2
+5879	1	1
+29	1	1
+6139	1	0
+2354	1	1
+28	1	1
+91	88	87
+142	16	15
+54	1	1
+22	3	3
+1479	4	4
+221	4	4
+132	1	0
+574	11	11
+23	1	0
+604	1	1
+44	1	1
+899	1	0
+70	1	0
+10	1	0
+13561	1	1
+44	1	1
+4476	4	4
+799	26	25
+1466	18	18
+17897	4	0
+1667	1	0
+4250	1	1
+44	1	3
+14	1	1
+4956	1	1
+18	1	0
+39	3	2
+4990	1	1
+47	13	13
+69	4	0
+9729	1	0
+355	0	1
+2186	1	1
+37	1	1
+6111	3	3
+100	4	4
+68	1	1
+43	1	1
+1126	5	7
+5520	8	8
+2316	1	1
+181	6	6
+50	1	1
+29	1	0
+83	1	1
+1073	245	639
+150	1	1
+25272	0	1
+2132	0	4
+2522	1	1
+48	1	1
+1498528	0	1
+6044582	3000008	3000000
+1291113	60074	16691
+3837	3	0
+811	1	0
+2567	1	0
+7375465	11	11
+42062	1	0
+19604621	1	0
+10692667	1	0
+110	0	1
+3577	0	3
+907	1	1
+18	1	1
+897	1	1
+64	535	251
+21	0	1
+140	0	1
+70	1	0
+77	9	10
+149	4	0
+5	1	5
+68	1	0
+142	5	5
+57	14	14
+43	1	1
+31034	124100	99683
+2301	0	2
+44	2	0
+568015	87325	183549
+330	5	5
+114	0	3088
+1776	0	3085
+949	0	4
+514	37	37
+963	15	14
+1351	71	71
+56	15	15
+405	713	713
+651	1	1
+41	1	1
+837	1	0
+658	0	1
+794	0	1
+73	1	1
+30	1	1
+817	51	51
+566	72	72
+195	0	12193
+1599	0	3085
+217	43	43
+247	29	29
+4148	1	0
+158	266	266
+696	20	20
+58	69	69
+100	13	13
+326	137	137
+151	35	35
+1804	151	151
+1341	289	289
+154	23	23
+1932	17	17
+111	47	47
+128	16	16
+78	30	30
+1022	6	10
+78	1	0
+342	31	31
+86	23	23
+1601	41	41
+144	49	49
+170	10	10
+398	23	23
+419	20	20
+955	55	55
+1139	11	11
+1925	0	276
+223	58	58
+702	25	25
+1030	23	23
+363	164	164
+653	16	16
+78	13	13
+1035	0	4
+514	37	37
+1069	10	10
+321	15	15
+603	68	68
+789	20	20
+56	25	25
+1007	5	5
+1198	24	24
+689	3	0
+743	32	32
+817	43	43
+574	11	11
+123	19	19
+618	28	28
+1270	15	15
+289	29	29
+106	11	11
+1395	46	46
+850	4	4
+777	62	62
+86	36	36
+374	97	97
+2072	31	31
+195	56	56
+379	80	80
+64	11	11
+191	18	18
+1051	13	13
+52	163	169
+1297	1	1
+25	1	1
+3451	0	188
+3097	0	9
+2715	1	0
+11829	0	3
+6001	28	0
+10728	0	1
+3770769	1	0
+62	1	0
+22	1	0
+827	1	0
+1485	1	0
+242	0	1
+7142	1	0
+4029	3	3
+69	1	1
+15865	1	0
+83463	4	0
+5976	9	0
+2661	1	0
+1483	1	0
+15868	4	0
+17798	1	0
+2649	1	0
+3627	1	0
+4789	1	0
+9541	1	0
+6844	1	0
+3187	2	0
+411	14	0
+3056	4	0
+19776	3	0
+29085	0	1
+745	2	0
+11453	2	0
+16739	1	0
+14697	1	0
+8539	1	0
+25514443	1	0
+17680	0	1
+55359	0	1
+58	57	59
+1515	1	0
+1111	1	0
+5736	6	6
+66213	1	0
+68	1	1
+24	6	7
+43	1	1
+33414	7	7
+22	1	1
+19312	0	1
+8588	1	1
+31	1	1
+15969	1	1
+32	1	1
+27034	1	1
+42	1	1
+3352	0	1
+15009	1	0
+20433	18	18
+32141	9	8
+116	41	41
+4920	1	0
+33364	1	0
+11160	15	17
+28423	1	0
+43835	1	1
+24	4	2
+269244	4	4
+37	1	1
+17193	4	3
+53	12	11
+23	2	1
+7	1	1
+37978	9	9
+37743	1	1
+35	3	3
+26636	1	1
+17	1	1
+8728292	1	0
+16734742	0	71275
+27	1	1
+657033	0	2
+2911	0	2
+1941	1	1
+35	1	1
+835	1	1
+116	1	1
+399	1	1
+101	1	0
+194	1	2
+450	1	0
+825	1	1
+73	1	1
+156	1	1
+58	1	1
+50	5	5
+153	11	11
+189	5	5
+233	1	1
+83	1	1
+642	0	1
+1380	1	1
+17	1	1
+315	1	1
+26	1	1
+786	0	901
+76	1	1
+45	1	1
+535	1	1
+34	1	1
+2007	7	7
+159	1	1
+26	1	1
+6362	13	13
+504325	100008	25635
+420771	0	232
+287680	0	104
+73	0	364
+181	0	55
+95	1	1
+46	1	1
+4002	1	1
+24	1	1
+183	49	0
+72	1	2
+8	1	0
+39	688	1
+306	0	50
+1939	0	1
+615	684	0
+254	0	1
+572035	7362	108542
+480202	1	0
+11866	6	6
+26917	0	1
+6097	15	15
+3074	0	1
+12292	0	1
+2209	0	1
+7358	0	1
+321393
+
+chain	161719	8	146274826	+	12213564	12217654	8	146364022	+	11922619	11926713	3890
+48	2333	2337
+1544	26	26
+139
+
+chain	94297	8	146274826	+	86864948	86909782	8	146364022	+	86767902	86816113	712
+43	4583	4586
+51	23	23
+69	22	22
+81	3466	3466
+114	1460	1461
+170	2237	2237
+47	3442	3445
+24	161	161
+49	1995	1995
+32	5554	5830
+116	4	4
+12	2309	5394
+37	2018	2018
+68	865	865
+25	3669	3669
+32	817	817
+42	1346	1346
+28	1574	1574
+29	1512	1515
+46	1652	1652
+41	2665	2665
+30	2224	2230
+50
+
+chain	49697	8	146274826	+	86036864	86037399	8	146364022	+	85964814	85965349	932809
+535
+
+chain	26725	8	146274826	+	86857851	86907733	8	146364022	+	86754632	86786590	1026
+491	49362	31438
+29
+
+chain	24621	8	146274826	+	145396034	145396288	8	146364022	+	145493131	145493385	2960834
+254
+
+chain	18039	8	146274826	+	144819613	144819801	8	146364022	+	144748845	144749033	12082915
+188
+
+chain	14890	8	146274826	+	86857082	86862299	8	146364022	-	59611598	59616815	1124
+71	476	476
+222	4397	4397
+51
+
+chain	13243	8	146274826	+	144819801	144819938	8	146364022	+	144748593	144748730	12136518
+137
+
+chain	9530	8	146274826	+	144823061	144823289	8	146364022	+	144751680	144751756	18947814
+3	152	0
+73
+
+chain	9463	8	146274826	+	144819938	144820036	8	146364022	+	144748632	144748730	13619337
+98
+
+chain	8087	8	146274826	+	86874741	86874834	8	146364022	+	86817360	86817453	1088
+93
+
+chain	7965	8	146274826	+	86865238	86879045	8	146364022	+	86780387	86797281	766
+29	7982	7984
+37	5729	8814
+30
+
+chain	7439	8	146274826	+	12201270	12203830	8	146364022	+	11910337	11912897	3584
+26	2480	2480
+54
+
+chain	6315	8	146274826	+	86909619	86909690	8	146364022	+	86556151	86556222	765064
+71
+
+chain	6303	8	146274826	+	144823559	144823625	8	146364022	+	144751722	144751788	29838951
+66
+
+chain	5756	8	146274826	+	86854716	86862896	8	146364022	+	86782059	86817706	1940
+37	8112	35579
+31
+
+chain	5521	8	146274826	+	144823643	144823701	8	146364022	+	144751730	144751788	31959915
+58
+
+chain	5339	8	146274826	+	144823077	144823133	8	146364022	+	144751620	144751676	32492605
+56
+
+chain	4702	8	146274826	+	144819343	144819392	8	146364022	+	144748967	144749016	12082914
+49
+
+chain	4684	8	146274826	+	144823154	144823323	8	146364022	+	144751621	144751752	19314390
+33	102	64
+34
+
+chain	4385	8	146274826	+	144820066	144820134	8	146364022	+	144748613	144748681	20813384
+68
+
+chain	3959	8	146274826	+	144820160	144820201	8	146364022	+	144748560	144748601	13619336
+41
+
+chain	3959	8	146274826	+	144819572	144819613	8	146364022	+	144748560	144748601	13619338
+41
+
+chain	3270	8	146274826	+	86905368	86905406	8	146364022	-	59611399	59611437	120315
+38
+
+chain	3190	8	146274826	+	144819513	144819546	8	146364022	+	144748697	144748730	12136519
+33
+
+chain	2525	8	146274826	+	144823339	144823377	8	146364022	+	144751692	144751730	23202086
+38
+
+chain	2511	8	146274826	+	144819546	144819572	8	146364022	+	144748632	144748658	13619339
+26
+
+chain	2509	8	146274826	+	144820134	144820160	8	146364022	+	144748632	144748658	22535050
+26
+
+chain	2395	8	146274826	+	144820036	144820061	8	146364022	+	144748974	144748999	15328526
+25
+
+chain	2146	8	146274826	+	86862896	86862937	8	146364022	-	59626667	59626708	2042
+38	1	1
+2
+
+chain	2013	8	146274826	+	12224371	12224395	8	146364022	+	11933433	11933457	5802
+24
+
+chain	928	8	146274826	+	86871422	86871445	8	146364022	+	86566156	86566179	4371
+23
+
+chain	19961283	8_random	943810	+	732172	943810	5	180915260	+	69954173	70165811	138
+211638
+
+chain	4772201	8_random	943810	+	62854	113804	8	146364022	+	16274686	16325603	650
+4146	9	9
+1642	5	9
+541	4	0
+1197	1	1
+27	1	1
+2498	0	1
+20171	4	0
+2761	3	0
+1978	0	1
+628	10	0
+5533	3	0
+2428	24	0
+47	5	9
+197	11	11
+687	0	2
+642	1	1
+17	1	1
+2228	0	4
+1978	1	0
+1521
+
+chain	4401722	8_random	943810	+	396973	443039	8	146364022	-	801667	847519	685
+2079	1	0
+22818	62	9
+50	57	0
+25	0	8
+40	91	0
+5953	32	0
+1937	0	2
+803	13	14
+786	0	5
+3908	2	0
+783	0	1
+854	1	0
+142	1	0
+1521	1	0
+114	0	1
+498	4	4
+591	2	0
+2750	0	9
+147
+
+chain	3680035	8_random	943810	+	643258	682172	GL000196.1	38914	+	0	38914	797
+38914
+
+chain	3554032	8_random	943810	+	493047	530222	GL000197.1	37175	+	0	37175	825
+37175
+
+chain	1222443	8_random	943810	+	0	12854	8	146364022	-	108556772	108569616	1946
+5765	0	1
+2843	2	0
+279	0	1
+299	1	0
+1113	9	0
+2543
+
+chain	995258	8_random	943810	+	250482	297042	8	146364022	+	46838897	46856230	2491
+52	5	5
+72	1882	0
+246	1888	0
+158	79	78
+59	82	81
+53	46	46
+76	18	18
+100	1942	59
+231	1	0
+84	1	0
+49	23	22
+65	25	25
+312	49	47
+118	1	0
+169	645	640
+71	18	18
+202	15	15
+74	114	112
+65	1444	30
+86	2249	34
+216	9	8
+173	33	30
+63	81	79
+265	87	84
+103	11	10
+122	1	1
+47	1	1
+165	858	0
+14	1027	0
+88	1879	0
+148	7	6
+166	1	0
+288	1888	1
+62	1	1
+90	1	0
+35	1890	1
+280	3	3
+23	1	0
+109	1	1
+283	4	4
+88	1	1
+67	1	1
+23	1	1
+109	680	0
+89	1876	0
+41	1	0
+45	1898	0
+107	18	18
+18	1	0
+28	1	1
+50	1	0
+35	1	1
+50	7	4
+54	1	0
+37	1	1
+298	11	10
+94	1	0
+17	1	0
+36	1	0
+55	1	0
+12	1	1
+148	1	1
+79	11	9
+78	1	1
+140	5	4
+54	3	0
+97	1	0
+138	6	4
+73	1	0
+59	19	19
+207	1	1
+45	1	1
+76	1	0
+8	3	1
+60	2	2
+56	1	1
+70	1	0
+45	1	1
+136	131	128
+86	17	16
+75	7	7
+53	483	144
+75	26	26
+230	135	132
+110	15	15
+61	25	23
+76	43	42
+120	1	0
+78	1735	1728
+192	42	41
+61	82	82
+190	37	37
+90	1911	30
+168	56	56
+56	10	10
+83	26	26
+230	1927	49
+224	1937	52
+244	41	41
+125	36	36
+96	26	26
+83	81	78
+272	2019	139
+59	236	231
+103	71	70
+183	31	31
+58	119	117
+131	1	0
+167	25	25
+72	97	96
+91	6	6
+75	10	9
+219
+
+chain	895028	8_random	943810	+	298039	346176	8	146364022	-	99507152	99525054	4376
+63	126	463
+229	1883	1
+104	25	25
+58	6	6
+155	36	35
+84	10	10
+88	23	23
+53	1	0
+164	5	5
+68	56	55
+231	24	24
+149	409	408
+53	1	0
+69	1	0
+134	6	6
+201	318	315
+27	1885	0
+105	1	0
+82	82	82
+144	27	27
+56	238	235
+130	24	23
+109	1	0
+77	2	1
+100	31	30
+102	14	14
+63	11	10
+108	91	91
+72	94	93
+169	149	148
+198	238	234
+86	2	0
+169	3	1
+72	11	11
+66	1	0
+247	18	17
+392	540	533
+186	7	7
+121	1	0
+254	1977	89
+53	7	7
+193	483	475
+93	50	47
+198	28	28
+76	1883	8
+61	130	129
+123	29	29
+112	201	199
+138	12	11
+21	1873	0
+107	33	33
+53	1880	1
+118	40	38
+141	1943	53
+168	137	134
+81	16	16
+115	2216	0
+103	32	29
+71	128	127
+104	54	53
+121	128	127
+66	99	96
+80	75	74
+128	1924	40
+53	2	1
+288	1910	24
+53	1907	23
+56	40	40
+72	111	111
+62	127	127
+122	65	65
+80	210	206
+115	0	1
+146	5663	0
+183	40	40
+53	34	33
+229	28	28
+92	83	83
+234	1983	101
+57	1885	0
+44	11	11
+62	1	0
+69	28	28
+126	1	0
+148	147	144
+58	14	12
+53	1	0
+66	1	0
+105	34	33
+71	39	38
+69	17	17
+56	6	5
+79	48	46
+53	6	6
+57	38	35
+77	78	75
+111	649	644
+110	45	43
+235
+
+chain	604051	8_random	943810	+	178170	281976	8	146364022	+	46838954	46856867	5476
+212	1875	0
+272	566	562
+114	1	0
+143	1	0
+55	74	74
+65	25	25
+63	62	62
+61	31	31
+102	23	23
+215	1	0
+63	67	68
+68	373	34
+158	64	63
+53	46	46
+105	67	67
+55	2294	38
+202	15	15
+63	51	51
+246	23	23
+71	1	0
+271	103	102
+427	6	5
+51	25	22
+54	1878	0
+36	10	10
+122	26	26
+134	1886	0
+121	93	92
+51	1	2
+246	54742	0
+134	1884	0
+129	33	31
+147	39	38
+116	65	61
+66	43	41
+62	1982	95
+213	196	193
+339	260	254
+187	89	88
+10	2292	403
+57	5123	1343
+293	24	22
+61	1	0
+73	7	7
+53	1877	144
+91	4270	499
+59	2463	581
+37	339	671
+59	342	0
+110	266	261
+150	6	6
+92	244	241
+51	62	62
+51	3119	1229
+91	761	80
+60	48	47
+137	1876	0
+136	12	10
+131	12	11
+290	1	0
+45	4005	2083
+59	88	424
+59
+
+chain	496223	8_random	943810	+	580222	593236	8	146364022	-	59615387	59795086	34662
+2144	4634	17818
+237	1	1
+31	1	1
+194	35	40
+1575	162	153603
+534	0	55
+995	64	64
+1343	58	58
+112	1	1
+38	1	1
+70	1	1
+41	1	1
+81	1	1
+34	1	1
+624
+
+chain	279595	8_random	943810	+	199376	329223	8	146364022	-	99506514	99525054	6095
+67	50	47
+55	631	967
+63	1082	0
+177	61	58
+147	6	6
+143	1	0
+42	1882	0
+74	31	30
+83	23	23
+13	1879	0
+204	5	5
+58	69	69
+227	1933	51
+152	123	122
+83	1	0
+118	72	72
+159	17	17
+119	34	34
+230	36	36
+134	1929	32
+189	3017	0
+24	83	83
+121	1	0
+49	5680	1
+325	136	129
+277	30	30
+335	1436	53
+51	63	62
+99	867	859
+154	860	855
+269	32	31
+112	1	0
+50	1877	0
+99	58	58
+108	1	0
+96	2221	0
+37	1546	0
+136	2648	89
+52	7	8
+278	1	0
+202	139	136
+145	65	63
+51	44	42
+62	143	139
+61	156	155
+243	214	215
+20	1872	0
+194	74	75
+337	25	25
+145	15	15
+71	65	65
+84	1878	0
+60	1	0
+244	227	225
+226	53	53
+62	42	41
+66	63	61
+120	35	34
+64	56110	1
+98	41	40
+53	2795	914
+65	10	10
+57	8290	755
+67	63	61
+66	17	16
+53	1	0
+58	36	36
+92	3924	162
+40	61	61
+58	4119	368
+133	2082	185
+58	42	42
+167	2235	21
+50	4401	627
+71	40	39
+147	360	353
+60	174	173
+446
+
+chain	208078	8_random	943810	+	170910	242131	8	146364022	-	99506628	99524507	6380
+55	632	967
+69	73	73
+115	28	28
+146	4836	20
+75	1	0
+54	58	58
+87	10	10
+294	22105	209
+184	59	59
+53	209	208
+64	1388	305
+56	340	338
+60	50	50
+134	32	32
+108	2	0
+106	83	82
+108	1884	0
+62	68	68
+216	1	0
+55	20	20
+107	3862	104
+61	311	311
+29	2182	2154
+53	1	0
+93	1388	251
+108	3	2
+129	159	158
+109	1	0
+31	114	113
+51	60	60
+78	14	14
+99	14	13
+152	64	62
+60	13	12
+120	98	98
+138	115	114
+56	6	4
+26	438	436
+213	183	182
+53	1	0
+81	2318	428
+71	25	25
+145	15	15
+71	65	65
+109	1956	43
+69	112	108
+33	397	392
+58	1466	80
+62	46	46
+401	64	64
+45	51	51
+56	1	0
+6	99	99
+54	146	144
+187	67	67
+166	52	49
+51	9	8
+63	11	10
+61	186	186
+68	38	38
+168	105	102
+125	3	2
+113	17	17
+186	2	0
+3	6394	747
+113	762	83
+102	4015	254
+238	102	101
+91	6	6
+85	1999	129
+12	9	9
+44	2322	442
+90	319	318
+42
+
+chain	110041	8_random	943810	+	584910	586860	8	146364022	-	59525621	59532924	58275
+151	1	1
+64	1	1
+158	1	1
+137	0	5353
+14	3	3
+73	8	8
+52	11	11
+57	9	9
+54	15	15
+289	15	15
+837
+
+chain	81230	8_random	943810	+	228410	243660	8	146364022	-	99515272	99524158	121868
+53	818	813
+113	55	55
+76	1036	1025
+78	1	0
+115	1280	591
+98	36	34
+79	25	25
+73	189	188
+120	2622	738
+79	145	145
+8	21	19
+36	157	155
+27	18	14
+98	82	81
+130	280	280
+78	83	83
+21	20	20
+27	51	51
+134	238	238
+10	39	39
+53	216	215
+252	5175	1418
+73	6	6
+146	231	228
+111	1	0
+201	35	35
+101
+
+chain	78595	8_random	943810	+	271315	287023	8	146364022	+	46844767	46855610	13381
+177	7	6
+61	49	46
+54	86	84
+62	24	23
+151	92	91
+73	109	107
+108	1	0
+51	8	6
+97	2409	1723
+29	1995	118
+92	64	63
+24	701	695
+42	7	7
+53	90	89
+54	403	392
+25	6360	4099
+70	192	192
+26	77	76
+63	336	336
+129	125	126
+143	878	869
+27	23	23
+61
+
+chain	70241	8_random	943810	+	583972	584708	8	146364022	-	2327498	2328234	1800744
+736
+
+chain	67060	8_random	943810	+	583131	583834	8	146364022	+	144032710	144033413	1885205
+703
+
+chain	60161	8_random	943810	+	163863	193392	8	146364022	+	46840361	46854926	51951
+69	30	30
+79	155	153
+22	224	224
+36	635	633
+54	78	77
+53	1660	61
+55	408	405
+36	32	32
+40	163	161
+29	96	89
+5	85	85
+4	108	106
+193	10362	0
+211	23	23
+164	214	212
+108	41	40
+217	35	35
+85	25	25
+266	2366	490
+48	600	260
+32	3507	4987
+74	590	587
+105	2319	2307
+66	2880	990
+102	1	0
+89	507	168
+143
+
+chain	59106	8_random	943810	+	169718	174718	8	146364022	-	99507650	99524666	884317
+69	73	73
+53	107	105
+145	323	5927
+57	45	43
+58	51	49
+65	130	129
+16	74	74
+175	49	49
+53	423	422
+53	2360	8782
+34	55	55
+95	1	0
+28	1	0
+2	113	113
+292
+
+chain	53138	8_random	943810	+	171392	346403	8	146364022	-	102525263	102570806	8603
+57	57	57
+79	626	627
+64	1139	91
+72	32	32
+61	1	0
+192	55	53
+253	233	231
+113	1894	10
+151	18218	118
+161	39	39
+89	168	167
+68	174	168
+68	7236	473
+76	2229	347
+40	124	120
+50	21	21
+55	1906	29
+98	2	0
+51	3928	158
+113	3230	214
+58	5760	82
+62	113	112
+39	7442	4152
+122	13	12
+149	90	90
+56	48	47
+71	400	397
+133	1910	21
+97	23	23
+92	2561	0
+54	15	13
+67	70	69
+90	95	94
+59	72	72
+139	45	45
+101	71659	2394
+62	72	72
+84	1	0
+9	2000	117
+95	39	39
+65	70	68
+87	2031	150
+103	1949	61
+106	17	17
+136	75	74
+53	5662	38
+58	1936	41
+42	168	168
+108	95	95
+66	243	241
+50	5018	908
+53	4282	513
+74	1906	30
+83	2078	26035
+107	1947	59
+57	500	483
+160	1936	53
+185	1897	12
+119	3972	202
+29	14	14
+79	61	61
+44
+
+chain	52733	8_random	943810	+	164218	295513	8	146364022	+	43821028	43838759	7574
+63	20	20
+141	36	36
+153	32	31
+103	40	40
+53	86	85
+99	1658	59
+83	265	263
+110	21	21
+51	29	27
+160	108	108
+51	1	0
+49	1	0
+61	130	123
+85	12281	44
+69	272	272
+118	62	62
+75	7995	1645
+102	45	45
+59	32	32
+14	328	328
+126	2372	483
+86	58668	153
+40	4323	551
+31	1938	56
+58	2392	511
+58	234	222
+51	1403	0
+51	91	91
+50	218	218
+83	67	66
+75	77	77
+110	391	53
+2	2678	792
+147	104	101
+59	1917	33
+92	1958	75
+54	5899	1442
+11	105	104
+132	1	0
+50	2212	332
+66	5506	1369
+60	189	189
+173	223	221
+222	1874	0
+87	23	23
+54	108	108
+109	29	28
+94	64	63
+70	91	86
+97	164	161
+112	123	123
+78	1942	66
+145	118	118
+69	1917	31
+51	10	10
+113	235	231
+193	327	327
+41	392	391
+51	363	361
+123	1977	94
+57
+
+chain	48120	8_random	943810	+	172087	205615	8	146364022	-	99508140	99525054	275640
+50	1136	89
+81	56	55
+4	1876	5603
+199	577	570
+71	144	141
+39	17920	1690
+56	276	276
+117	289	289
+64	172	170
+10	18	18
+76	284	279
+308	237	229
+64	1904	0
+33	2094	204
+40	43	43
+63	3	2
+59	12	12
+306	15	15
+33	1146	61
+49	757	4487
+37	62	62
+83	46	46
+112	178	174
+95	1	0
+29	1956	73
+248
+
+chain	37837	8_random	943810	+	253130	272078	8	146364022	+	46839659	46847391	87472
+42	44	44
+61	2771	880
+109	37	36
+171	1	0
+120	209	204
+98	56	55
+61	10	9
+23	187	186
+75	18	18
+17	5316	1682
+9	145	143
+53	1	0
+29	137	137
+73	132	128
+65	14	14
+79	6214	2430
+95	70	70
+83	2232	342
+91
+
+chain	33662	8_random	943810	+	209837	215530	8	146364022	-	99514311	99520696	710844
+71	67	65
+87	1	0
+118	10	8
+19	543	533
+53	11	11
+89	4	2
+68	143	138
+148	1307	167
+110	627	624
+30	2103	3960
+84
+
+chain	32940	8_random	943810	+	226035	229035	8	146364022	-	102534454	102537445	203694
+68	23	23
+49	847	842
+50	91	91
+134	57	57
+61	1290	1287
+37	113	113
+86	41	40
+53
+
+chain	31024	8_random	943810	+	206449	211988	8	146364022	-	99514678	99520173	701886
+8	43	43
+64	6	5
+58	14	12
+82	340	0
+49	416	749
+81	59	59
+117	75	75
+207	1422	3285
+36	2428	531
+34
+
+chain	29825	8_random	943810	+	245532	246838	8	146364022	+	46839602	46840894	3893579
+57	560	553
+119	226	222
+5	184	184
+21	75	72
+59
+
+chain	28513	8_random	943810	+	169082	170209	8	146364022	-	99514495	99515614	2995290
+72	337	330
+70	17	17
+84	143	144
+53	81	80
+64	162	161
+44
+
+chain	28403	8_random	943810	+	244271	247583	8	146364022	+	46840215	46841632	1514192
+150	21	21
+65	247	246
+61	60	60
+144	37	36
+68	1	0
+56	146	144
+158	1945	55
+153
+
+chain	27366	8_random	943810	+	305024	329400	8	146364022	-	99508828	99514021	185326
+30	144	144
+27	1950	69
+57	1	0
+69	4733	954
+80	7	7
+60	2015	139
+144	51	51
+17	50	48
+20	2199	324
+179	83	83
+149	1	0
+45	50	50
+29	198	197
+38	56	56
+36	163	162
+27	2035	153
+71	157	157
+56	6099	109
+62	47	47
+93	104	100
+75	1	0
+39	342	0
+49	1641	94
+81	539	539
+177
+
+chain	25161	8_random	943810	+	165410	166073	8	146364022	+	46840031	46840686	5084847
+51	107	104
+69	107	106
+77	51	48
+53	79	78
+69
+
+chain	23498	8_random	943810	+	275598	276538	8	146364022	+	46848347	46849285	1106774
+150	39	39
+58	1	0
+156	159	160
+43	237	235
+97
+
+chain	22556	8_random	943810	+	221873	233787	8	146364022	-	102535430	102541485	264178
+56	92	91
+134	1524	140
+26	9348	4879
+77	298	294
+159	126	126
+55	8	7
+11
+
+chain	21554	8_random	943810	+	211856	229563	8	146364022	-	102534119	102541711	230838
+98	1283	144
+76	1760	1749
+25	1	0
+80	1889	12
+87	80	79
+50	14	14
+51	55	50
+59	207	201
+52	31	30
+212	2303	390
+120	3503	2102
+43	5590	1830
+38
+
+chain	21378	8_random	943810	+	315539	346866	8	146364022	-	99515536	99522005	182294
+65	7	7
+59	1872	0
+52	1	0
+110	59	59
+145	1929	47
+157	4107	0
+50	19	19
+76	11	11
+9	218	215
+20	69	68
+27	104	104
+38	3941	169
+93	9868	446
+40	53	53
+33	350	349
+83	1915	34
+228	2	1
+71	4993	3080
+80	103	101
+58	162	162
+50
+
+chain	20133	8_random	943810	+	187153	190961	8	146364022	+	46839718	46841635	711123
+27	2490	610
+70	193	186
+75	6	6
+22	81	81
+48	1	0
+41	200	200
+10	13	12
+78	103	101
+193	10	10
+147
+
+chain	19851	8_random	943810	+	184692	274845	8	146364022	+	46839508	46849467	34309
+59	20	20
+103	2903	645
+204	29	27
+122	5	4
+251	1	1
+19	1	1
+370	102	102
+45	59	59
+32	2407	520
+35	53082	226
+207	6009	346
+163	6	4
+101	79	79
+50	419	416
+33	1900	15
+227	6	6
+48	1	0
+53	22	21
+65	58	57
+59	43	42
+133	81	80
+20	44	42
+50	14	12
+53	37	36
+104	2375	490
+62	1340	1334
+14	1	0
+183	3854	228
+49	6055	405
+35	6036	1578
+80	25	25
+89	8	7
+13
+
+chain	19146	8_random	943810	+	175023	175290	8	146364022	-	99508150	99508416	4025470
+88	58	57
+65	25	25
+31
+
+chain	17870	8_random	943810	+	167013	193249	8	146364022	+	46840039	46851047	112211
+37	407	404
+31	233	231
+41	10382	13
+26	802	800
+40	282	279
+41	6132	1660
+77	3954	2070
+28	510	4239
+81	90	89
+50	30	30
+120	2083	201
+60	192	191
+51	338	0
+118
+
+chain	17758	8_random	943810	+	265412	266607	8	146364022	+	43830436	43831619	676151
+58	100	98
+16	14	14
+59	946	936
+2
+
+chain	17102	8_random	943810	+	196211	212812	8	146364022	-	102534634	102539542	315778
+4	176	169
+110	677	661
+101	229	222
+63	12	11
+71	2311	416
+66	5	5
+3	2545	1456
+25	7	5
+52	21	20
+3	9994	1320
+61	8	7
+57
+
+chain	16958	8_random	943810	+	303736	319647	8	146364022	-	99509421	99514022	288375
+62	1	0
+115	55	55
+12	6716	1059
+173	60	58
+5	238	238
+27	142	138
+80	1	0
+32	1181	1170
+56	95	93
+15	6818	1186
+27
+
+chain	16519	8_random	943810	+	191041	191237	8	146364022	+	46841712	46841907	5194781
+138	7	6
+51
+
+chain	16395	8_random	943810	+	250196	250458	8	146364022	+	46842349	46842610	5706058
+109	63	63
+38	1	0
+51
+
+chain	16284	8_random	943810	+	248826	295566	8	146364022	+	43821313	43835075	8983
+38	3114	1217
+58	3878	108
+134	2320	436
+35	2074	180
+90	6230	729
+53	51	51
+165	2138	257
+18	1	0
+14	9087	4604
+68	26	23
+70	26	25
+165	4726	2469
+31	113	113
+45	6358	726
+53	323	321
+29	3160	1272
+53	1943	60
+1	1	0
+51
+
+chain	16072	8_random	943810	+	313809	340982	8	146364022	-	102527896	102533983	267291
+28	5309	1547
+73	15383	1858
+110	23	22
+51	120	119
+75	171	167
+144	2405	509
+56	2087	199
+104	240	238
+93	367	364
+59	113	109
+162
+
+chain	15849	8_random	943810	+	261982	295288	8	146364022	+	43821759	43829198	76114
+110	412	75
+52	237	234
+137	1904	21
+61	17	17
+88	8048	505
+97	1212	533
+118	1	0
+62	80	80
+12	643	644
+105	9123	1231
+153	113	112
+50	1019	1018
+55	3899	142
+89	478	475
+43	4836	1068
+52
+
+chain	15670	8_random	943810	+	194296	345941	8	146364022	-	102525263	102540770	8834
+113	3789	1
+79	5134	279
+81	25039	3655
+36	72	71
+66	2073	189
+82	66	62
+87	280	277
+20	23	23
+59	87	84
+72	49	48
+51	7	7
+82	1014	334
+62	79983	3178
+76	18	17
+68	2382	504
+43	42	41
+108	10477	733
+134	2033	147
+59	5650	11
+88	3846	65
+64	297	293
+50	3779	12
+69	123	122
+120	121	120
+68	15	15
+57	136	135
+139	239	237
+72	1	0
+63	4	3
+53	59	59
+8	490	488
+28	84	81
+35	298	293
+34	805	799
+67	1	0
+53	69	67
+100	14	14
+81	134	132
+53	38	38
+39	110	109
+45
+
+chain	14986	8_random	943810	+	225882	226349	8	146364022	-	99518359	99518822	2174986
+18	53	51
+56	166	164
+73	33	33
+68
+
+chain	14834	8_random	943810	+	243014	243551	8	146364022	-	99519780	99520313	2299338
+16	162	159
+19	313	312
+27
+
+chain	14491	8_random	943810	+	298927	299279	8	146364022	-	102541139	102541484	3650546
+95	253	246
+4
+
+chain	13927	8_random	943810	+	330425	330634	8	146364022	-	99513165	99513373	16289681
+108	47	46
+54
+
+chain	13708	8_random	943810	+	204114	204446	8	146364022	-	99514221	99514551	7956244
+38	2	1
+51	137	136
+104
+
+chain	13201	8_random	943810	+	267894	296641	8	146364022	+	46841376	46846486	149880
+47	8325	118
+153	12619	975
+124	10	10
+59	1933	45
+415	178	178
+62	103	99
+67	193	193
+45	34	34
+4	542	542
+26	2853	963
+60	194	194
+31	632	628
+38
+
+chain	12234	8_random	943810	+	261803	269960	8	146364022	+	46841266	46843423	172872
+35	2890	667
+1	24	24
+60	15	15
+6	166	166
+32	2034	149
+193	134	132
+81	69	68
+116	2096	211
+21	87	83
+97
+
+chain	10617	8_random	943810	+	337138	337293	8	146364022	-	99523571	99523724	21494273
+69	29	27
+57
+
+chain	10554	8_random	943810	+	261774	276161	8	146364022	+	46850579	46856384	287750
+26	3379	1156
+30	20	20
+51	4844	1067
+12	16	15
+65	51	50
+53	361	357
+85	102	101
+13	51	51
+26	87	87
+46	4988	2413
+81
+
+chain	10039	8_random	943810	+	325665	325968	8	146364022	-	99512180	99512483	3203386
+32	146	146
+51	12	12
+62
+
+chain	9889	8_random	943810	+	299929	343052	8	146364022	-	99507161	99512618	194143
+54	125	463
+172	6011	368
+29	4240	471
+68	8003	490
+69	47	47
+10	133	133
+55	45	44
+46	4488	379
+66	1908	22
+82	7833	307
+63	2043	161
+90	115	115
+101	1	0
+97	2144	241
+32	4543	773
+83	294	293
+33
+
+chain	9887	8_random	943810	+	315022	315154	8	146364022	-	99513153	99513284	7544872
+79	1	0
+52
+
+chain	9860	8_random	943810	+	311200	311307	8	146364022	-	99513093	99513199	8991129
+52	1	0
+54
+
+chain	9817	8_random	943810	+	331048	331155	8	146364022	-	99513786	99513892	13428201
+64	1	0
+42
+
+chain	9446	8_random	943810	+	266857	296082	8	146364022	+	43794817	43828117	103381
+44	9743	27369
+146	121	120
+47	983	976
+79	10221	2331
+165	112	112
+51	81	80
+39	1877	0
+66	2043	157
+36	3318	1429
+53
+
+chain	9082	8_random	943810	+	283227	283503	8	146364022	+	46855567	46855841	3572014
+72	39	38
+7	101	100
+57
+
+chain	9078	8_random	943810	+	266179	266275	8	146364022	+	46841541	46841637	24832874
+96
+
+chain	9056	8_random	943810	+	234327	343102	8	146364022	-	102532678	102541696	177988
+49	2060	180
+83	4311	566
+60	72559	3258
+278	110	111
+124	380	378
+51	246	244
+21	14	13
+37	2147	273
+83	195	193
+50	29	28
+5	2000	121
+73	4435	328
+132	3864	97
+47	5706	63
+45	54	54
+151	1883	5
+99	3796	15
+99	63	61
+64	1	0
+58	1881	0
+137	76	74
+53	53	48
+27	312	310
+85	17	16
+19	140	140
+52	244	244
+62	105	104
+50
+
+chain	8907	8_random	943810	+	174718	174972	8	146364022	-	99514987	99515577	3222521
+12	195	531
+47
+
+chain	8843	8_random	943810	+	329461	329557	8	146364022	-	99512211	99512306	12312646
+78	1	0
+17
+
+chain	8728	8_random	943810	+	244822	248433	8	146364022	+	46838897	46840609	1548241
+52	2949	1051
+100	1	0
+231	55	55
+65	34	34
+124
+
+chain	8619	8_random	943810	+	294534	295111	8	146364022	+	46855606	46856180	1696895
+31	25	25
+71	52	51
+46	97	97
+58	132	130
+65
+
+chain	8428	8_random	943810	+	281982	282213	8	146364022	+	46854328	46854560	448042
+60	97	98
+56	17	17
+1
+
+chain	8419	8_random	943810	+	261190	261281	8	146364022	+	43820969	43821060	10860311
+91
+
+chain	8395	8_random	943810	+	294914	295046	8	146364022	+	46848509	46848640	12873675
+58	69	68
+5
+
+chain	8358	8_random	943810	+	183391	183662	8	146364022	+	46851295	46851565	1204104
+177	39	38
+55
+
+chain	8235	8_random	943810	+	303417	303563	8	146364022	-	99516580	99516725	5721277
+92	1	0
+53
+
+chain	8187	8_random	943810	+	330253	330340	8	146364022	-	99512994	99513081	26147162
+87
+
+chain	7754	8_random	943810	+	175981	176066	8	146364022	-	99524049	99524133	15930227
+61	1	0
+23
+
+chain	7677	8_random	943810	+	237294	312035	8	146364022	-	99517817	99525125	210590
+33	254	254
+156	1	0
+142	25	25
+70	127	127
+226	1925	53
+62	55	55
+112	29	28
+91	36	36
+139	46	43
+7	796	791
+54	65384	1748
+45	3060	1165
+46	839	833
+119	535	529
+77	214	206
+36
+
+chain	7632	8_random	943810	+	192816	192897	8	146364022	+	46850614	46850695	27043702
+81
+
+chain	7605	8_random	943810	+	285785	290878	8	146364022	+	46850643	46851974	486318
+50	2571	689
+13	4	4
+73	73	73
+25	2038	160
+132	56	54
+58
+
+chain	7406	8_random	943810	+	221929	222203	8	146364022	-	99519540	99519813	598559
+62	1	0
+29	134	134
+48
+
+chain	7383	8_random	943810	+	294257	294361	8	146364022	+	43837510	43837614	4128881
+70	9	9
+25
+
+chain	7298	8_random	943810	+	168270	168367	8	146364022	+	46839414	46839508	6543284
+4	56	53
+37
+
+chain	7295	8_random	943810	+	336620	336697	8	146364022	-	99513722	99513799	27625946
+77
+
+chain	7211	8_random	943810	+	261472	261549	8	146364022	+	46839068	46839145	24666501
+77
+
+chain	7186	8_random	943810	+	330047	330123	8	146364022	-	99512791	99512867	27853996
+76
+
+chain	7178	8_random	943810	+	316571	316677	8	146364022	-	102541857	102541963	5712191
+106
+
+chain	7102	8_random	943810	+	318170	320971	8	146364022	-	99520028	99520932	765669
+72	19	19
+135	121	121
+72	13	12
+29	2280	384
+60
+
+chain	7077	8_random	943810	+	192950	193025	8	146364022	+	46850748	46850823	28082919
+75
+
+chain	7057	8_random	943810	+	203108	206189	8	146364022	-	99515093	99516287	1156085
+30	91	89
+53	2333	448
+35	503	503
+36
+
+chain	6980	8_random	943810	+	332337	335152	8	146364022	-	99522544	99523471	1124480
+50	412	409
+6	79	79
+50	126	126
+65	1978	93
+49
+
+chain	6922	8_random	943810	+	183305	183378	8	146364022	+	46840000	46840073	28376594
+73
+
+chain	6904	8_random	943810	+	266355	266429	8	146364022	+	46841714	46841788	28413782
+74
+
+chain	6731	8_random	943810	+	303313	303384	8	146364022	-	99509001	99509072	28774708
+71
+
+chain	6664	8_random	943810	+	303981	314057	8	146364022	-	99517140	99519668	641395
+51	3	2
+55	1	0
+72	170	168
+30	7422	1761
+7	12	11
+54	1882	0
+68	153	153
+96
+
+chain	6603	8_random	943810	+	322619	327380	8	146364022	-	99513231	99513884	1344743
+127	337	0
+120	9	8
+78	1963	78
+31	1885	0
+211
+
+chain	6584	8_random	943810	+	197737	202982	8	146364022	-	102536127	102540259	775939
+91	1155	1137
+22	12	11
+57	3876	2782
+32
+
+chain	6449	8_random	943810	+	218412	233428	8	146364022	-	99516080	99519573	697985
+27	8506	1438
+73	54	54
+91	295	295
+235	28	28
+6	100	100
+56	5516	1061
+29
+
+chain	6331	8_random	943810	+	327023	327090	8	146364022	-	99511661	99511728	29751334
+67
+
+chain	6250	8_random	943810	+	208146	208242	8	146364022	-	99508890	99508983	12204367
+15	70	67
+11
+
+chain	6212	8_random	943810	+	207786	207861	8	146364022	-	99514136	99514211	3829743
+75
+
+chain	6150	8_random	943810	+	203513	205795	8	146364022	-	102537045	102537445	1909663
+16	3	2
+125	118	117
+8	1955	75
+57
+
+chain	6094	8_random	943810	+	299279	299402	8	146364022	-	99508718	99508841	2977078
+68	21	21
+34
+
+chain	6085	8_random	943810	+	250101	250166	8	146364022	+	46842254	46842319	30387783
+65
+
+chain	6067	8_random	943810	+	293889	294038	8	146364022	+	46845620	46845767	4301892
+66	21	19
+62
+
+chain	6049	8_random	943810	+	230044	230135	8	146364022	-	102569888	102569979	10345810
+91
+
+chain	5962	8_random	943810	+	207380	207446	8	146364022	-	99509995	99510061	8394857
+66
+
+chain	5949	8_random	943810	+	272784	272847	8	146364022	+	46853694	46853757	30762472
+63
+
+chain	5823	8_random	943810	+	299452	300023	8	146364022	-	99514497	99515068	1422380
+470	61	61
+40
+
+chain	5814	8_random	943810	+	289476	289952	8	146364022	+	46839369	46839842	2257769
+77	110	110
+124	92	90
+42	1	0
+30
+
+chain	5753	8_random	943810	+	192024	192086	8	146364022	+	46838954	46839016	21955899
+62
+
+chain	5749	8_random	943810	+	233271	233333	8	146364022	-	102570546	102570608	31315232
+62
+
+chain	5681	8_random	943810	+	341821	341883	8	146364022	-	99511396	99511458	7040566
+62
+
+chain	5649	8_random	943810	+	174777	174837	8	146364022	-	99507908	99507968	31588023
+60
+
+chain	5623	8_random	943810	+	175706	175950	8	146364022	-	102534119	102534360	3287579
+59	23	22
+63	22	20
+77
+
+chain	5394	8_random	943810	+	322313	322370	8	146364022	-	99511057	99511114	32316179
+57
+
+chain	5303	8_random	943810	+	187437	187493	8	146364022	+	46840000	46840056	32583273
+56
+
+chain	5285	8_random	943810	+	290446	290502	8	146364022	+	43794807	43794863	32673339
+56
+
+chain	5276	8_random	943810	+	336755	336811	8	146364022	-	99513853	99513909	32693850
+56
+
+chain	5265	8_random	943810	+	208344	208568	8	146364022	-	99514691	99514915	3842595
+38	152	152
+34
+
+chain	5263	8_random	943810	+	587464	592229	8	146364022	+	86573610	86746488	37343
+35	3283	168311
+47	1343	1343
+20	1	3086
+36
+
+chain	5194	8_random	943810	+	184072	184128	8	146364022	+	46838897	46838953	32965865
+56
+
+chain	5184	8_random	943810	+	329855	329911	8	146364022	-	99512600	99512656	19420929
+56
+
+chain	5176	8_random	943810	+	177599	177656	8	146364022	-	99506628	99506685	33029925
+57
+
+chain	5155	8_random	943810	+	281730	289038	8	146364022	+	46843205	46844537	960143
+32	6927	953
+200	103	101
+46
+
+chain	5093	8_random	943810	+	184617	184671	8	146364022	+	43793908	43793962	23494272
+54
+
+chain	5050	8_random	943810	+	326962	327016	8	146364022	-	102542496	102542550	23236949
+54
+
+chain	5030	8_random	943810	+	212164	212217	8	146364022	-	99524079	99524132	33461083
+53
+
+chain	5021	8_random	943810	+	265903	265956	8	146364022	+	46841267	46841320	33516233
+53
+
+chain	5010	8_random	943810	+	325697	333370	8	146364022	-	99519686	99521704	323579
+146	5416	1638
+176	1905	28
+30
+
+chain	4963	8_random	943810	+	195042	195095	8	146364022	-	99525006	99525059	2910708
+53
+
+chain	4923	8_random	943810	+	294759	294811	8	146364022	+	46846486	46846538	24481170
+52
+
+chain	4775	8_random	943810	+	300049	300108	8	146364022	-	99511357	99511416	2287019
+59
+
+chain	4729	8_random	943810	+	323590	341586	8	146364022	-	99508256	99511164	508733
+81	188	186
+45	5653	0
+76	6291	651
+50	2125	222
+31	36	36
+21	50	50
+1	57	52
+62	3121	1237
+18	5	4
+85
+
+chain	4516	8_random	943810	+	291820	291870	8	146364022	+	46839826	46839876	19135311
+50
+
+chain	4460	8_random	943810	+	340307	340812	8	146364022	-	99522970	99523472	2799007
+59	396	393
+50
+
+chain	4363	8_random	943810	+	169662	169718	8	146364022	-	99524410	99524466	15024078
+25	20	20
+11
+
+chain	4245	8_random	943810	+	323934	340633	8	146364022	-	102539490	102542980	824111
+57	5415	1637
+55	4265	507
+46	6509	840
+13	129	125
+132	10	10
+68
+
+chain	4191	8_random	943810	+	346770	346816	8	146364022	-	99523777	99523823	32415009
+46
+
+chain	4157	8_random	943810	+	182640	182685	8	146364022	+	46841541	46841586	34989719
+45
+
+chain	4075	8_random	943810	+	287206	294116	8	146364022	+	46853923	46857394	507901
+58	44	43
+3	6754	3316
+51
+
+chain	4035	8_random	943810	+	210210	231774	8	146364022	-	99509073	99511132	504053
+68	1	0
+87	1	0
+47	151	148
+33	3084	58
+60	3981	215
+31	2075	179
+62	11852	1040
+31
+
+chain	3902	8_random	943810	+	322746	322788	8	146364022	-	99511490	99511532	25070576
+42
+
+chain	3842	8_random	943810	+	326212	339029	8	146364022	-	99518333	99519833	259270
+47	312	308
+17	60	57
+117	12236	926
+28
+
+chain	3793	8_random	943810	+	191943	191984	8	146364022	+	43793349	43793390	19585042
+41
+
+chain	3728	8_random	943810	+	267941	270995	8	146364022	+	46845159	46846318	991534
+57	2323	433
+41	406	402
+51	140	139
+36
+
+chain	3715	8_random	943810	+	252408	255104	8	146364022	+	46840810	46841615	879027
+44	1	0
+30	2575	685
+46
+
+chain	3689	8_random	943810	+	281829	281916	8	146364022	+	46850779	46850864	2001274
+26	3	1
+58
+
+chain	3667	8_random	943810	+	254324	254368	8	146364022	+	46840842	46840884	6647423
+30	11	9
+3
+
+chain	3646	8_random	943810	+	267998	268037	8	146364022	+	46850823	46850862	21797624
+39
+
+chain	3562	8_random	943810	+	168212	168270	8	146364022	+	43793831	43793889	3070871
+58
+
+chain	3504	8_random	943810	+	293480	293517	8	146364022	+	46839611	46839648	25642059
+37
+
+chain	3471	8_random	943810	+	337522	337596	8	146364022	-	99523948	99524022	18137430
+74
+
+chain	3448	8_random	943810	+	276204	276644	8	146364022	+	46854559	46854996	1897606
+49	365	362
+26
+
+chain	3411	8_random	943810	+	253189	255402	8	146364022	+	46850929	46853124	621337
+27	1269	1253
+37	776	774
+2	49	49
+53
+
+chain	3373	8_random	943810	+	338130	338166	8	146364022	-	99513335	99513371	20995505
+36
+
+chain	3359	8_random	943810	+	165298	184945	8	146364022	+	43823972	43836890	282023
+56	2595	8459
+64	12771	2404
+3	8	8
+69	4024	1798
+57
+
+chain	3297	8_random	943810	+	194502	225687	8	146364022	-	102525468	102530377	366001
+70	4347	545
+64	92	91
+87	8182	1452
+36	9798	1128
+56	8421	1348
+32
+
+chain	3286	8_random	943810	+	278118	290566	8	146364022	+	43833036	43837583	504233
+53	11	9
+65	12260	4361
+59
+
+chain	3257	8_random	943810	+	218922	219219	8	146364022	-	99516581	99516875	4722847
+56	32	30
+58	32	31
+119
+
+chain	3241	8_random	943810	+	233589	233706	8	146364022	-	102539417	102539534	832166
+52	16	16
+49
+
+chain	3212	8_random	943810	+	266430	268559	8	146364022	+	46841788	46842035	1348744
+53	1890	10
+128	11	9
+47
+
+chain	3157	8_random	943810	+	327996	328036	8	146364022	-	99512626	99512665	16621225
+16	15	14
+9
+
+chain	3082	8_random	943810	+	310645	310683	8	146364022	-	99512541	99512579	16551162
+38
+
+chain	3062	8_random	943810	+	163933	165245	8	146364022	+	46851641	46852949	942341
+29	1223	1219
+60
+
+chain	3030	8_random	943810	+	262108	262298	8	146364022	+	43831228	43834818	1405601
+67	13	3413
+110
+
+chain	2982	8_random	943810	+	183568	183600	8	146364022	+	46840262	46840294	9991965
+32
+
+chain	2745	8_random	943810	+	335974	336003	8	146364022	-	99513082	99513111	33185960
+29
+
+chain	2672	8_random	943810	+	298503	298547	8	146364022	-	99522900	99522944	24221385
+44
+
+chain	2671	8_random	943810	+	332183	346560	8	146364022	-	102528996	102533910	187401
+51	6123	457
+105	6796	3008
+38	249	246
+57	891	885
+67
+
+chain	2639	8_random	943810	+	219413	219441	8	146364022	-	99507721	99507749	35294427
+28
+
+chain	2612	8_random	943810	+	200816	200846	8	146364022	-	99525102	99525132	4075609
+30
+
+chain	2604	8_random	943810	+	240329	240369	8	146364022	-	99522715	99522755	8959532
+40
+
+chain	2556	8_random	943810	+	216929	216957	8	146364022	-	99514612	99514640	10325210
+28
+
+chain	2552	8_random	943810	+	191384	191411	8	146364022	+	46840185	46840212	15340406
+27
+
+chain	2552	8_random	943810	+	304972	304999	8	146364022	-	99516251	99516278	22571486
+27
+
+chain	2523	8_random	943810	+	327142	327169	8	146364022	-	99524856	99524883	11689776
+27
+
+chain	2451	8_random	943810	+	317909	318170	8	146364022	-	99521638	99521896	1452880
+31	226	223
+4
+
+chain	2447	8_random	943810	+	313295	313321	8	146364022	-	99513300	99513326	34910154
+26
+
+chain	2433	8_random	943810	+	230135	233158	8	146364022	-	99507638	99508095	1270471
+81	73	73
+21	37	37
+40	18	18
+82	2643	77
+28
+
+chain	2394	8_random	943810	+	309803	310102	8	146364022	-	102570308	102570605	11245020
+97	185	183
+17
+
+chain	2370	8_random	943810	+	237880	237905	8	146364022	-	99520270	99520295	11943708
+25
+
+chain	2370	8_random	943810	+	302899	302924	8	146364022	-	99512327	99512352	35222469
+25
+
+chain	2330	8_random	943810	+	274710	274735	8	146364022	+	46843727	46843752	26272760
+25
+
+chain	2188	8_random	943810	+	303139	303300	8	146364022	-	99512566	99512727	1325340
+161
+
+chain	2164	8_random	943810	+	254246	254269	8	146364022	+	46840765	46840788	24904248
+23
+
+chain	2146	8_random	943810	+	166073	166100	8	146364022	+	43793293	43793320	16498497
+27
+
+chain	2129	8_random	943810	+	171463	171506	8	146364022	-	99524332	99524375	3948851
+43
+
+chain	2094	8_random	943810	+	256486	256530	8	146364022	+	46856070	46856114	4878843
+44
+
+chain	2067	8_random	943810	+	182380	182437	8	146364022	+	46850625	46850682	3805032
+57
+
+chain	2054	8_random	943810	+	318711	318733	8	146364022	-	99511225	99511247	10715405
+22
+
+chain	1964	8_random	943810	+	202805	202867	8	146364022	-	99509184	99509246	3143072
+62
+
+chain	1962	8_random	943810	+	187357	187601	8	146364022	+	46841788	46842031	9057308
+62	87	86
+95
+
+chain	1941	8_random	943810	+	278085	278118	8	146364022	+	46854559	46854592	1239137
+33
+
+chain	1922	8_random	943810	+	294361	294534	8	146364022	+	46849827	46850000	1057760
+173
+
+chain	1907	8_random	943810	+	166115	166177	8	146364022	+	46850070	46850132	2756260
+62
+
+chain	1904	8_random	943810	+	294565	294590	8	146364022	+	46846293	46846318	7797359
+25
+
+chain	1899	8_random	943810	+	239038	239062	8	146364022	-	99519559	99519583	3632092
+24
+
+chain	1874	8_random	943810	+	311858	316542	8	146364022	-	99523087	99524010	1127459
+40	4555	794
+89
+
+chain	1842	8_random	943810	+	208242	208344	8	146364022	-	99510852	99510954	1122309
+102
+
+chain	1826	8_random	943810	+	333370	333404	8	146364022	-	102528310	102528344	12860155
+34
+
+chain	1699	8_random	943810	+	189740	189801	8	146364022	+	43830083	43830143	11700756
+13	1	0
+47
+
+chain	1671	8_random	943810	+	586860	586891	8	146364022	-	59596972	59597003	79385
+31
+
+chain	1671	8_random	943810	+	582366	582405	8	146364022	+	86778164	86778203	135745
+39
+
+chain	1614	8_random	943810	+	174855	174917	8	146364022	-	102535142	102535204	7562660
+62
+
+chain	1604	8_random	943810	+	210485	210541	8	146364022	-	99516819	99516875	24689779
+56
+
+chain	1577	8_random	943810	+	165529	165568	8	146364022	+	43833540	43833579	5487018
+39
+
+chain	1529	8_random	943810	+	199844	199893	8	146364022	-	99524132	99524181	16599934
+49
+
+chain	1430	8_random	943810	+	204007	204051	8	146364022	-	102535667	102535711	2444362
+44
+
+chain	1384	8_random	943810	+	331973	334317	8	146364022	-	99510969	99511436	2459541
+88	2124	247
+132
+
+chain	1361	8_random	943810	+	178432	178456	8	146364022	+	43821398	43821422	13532386
+24
+
+chain	1349	8_random	943810	+	282101	282136	8	146364022	+	43834762	43834797	3301014
+35
+
+chain	1325	8_random	943810	+	330748	334904	8	146364022	-	99513486	99513886	3761248
+39	3999	243
+118
+
+chain	1299	8_random	943810	+	216700	216875	8	146364022	-	99512515	99512690	2121346
+175
+
+chain	1278	8_random	943810	+	275077	288204	8	146364022	+	46842223	46845574	199410
+48	13052	3276
+27
+
+chain	1258	8_random	943810	+	272883	272996	8	146364022	+	43835974	43836087	2232086
+113
+
+chain	1256	8_random	943810	+	324880	325008	8	146364022	-	99513272	99513400	5381670
+128
+
+chain	1237	8_random	943810	+	196535	196612	8	146364022	-	99507792	99507869	15310375
+77
+
+chain	1235	8_random	943810	+	284286	284429	8	146364022	+	46839806	46839949	2930992
+143
+
+chain	1191	8_random	943810	+	293574	293786	8	146364022	+	46839704	46839915	1788603
+62	1	0
+149
+
+chain	1161	8_random	943810	+	294116	294212	8	146364022	+	43829899	43829995	1318655
+4	39	39
+53
+
+chain	1160	8_random	943810	+	183897	184027	8	146364022	+	43793197	43793327	2884372
+130
+
+chain	1130	8_random	943810	+	241032	308421	8	146364022	-	102539359	102541234	585349
+125	60736	871
+57	75	74
+53	2150	266
+105	4036	272
+52
+
+chain	1119	8_random	943810	+	229190	229281	8	146364022	-	99508572	99508663	1537143
+73	17	17
+1
+
+chain	1018	8_random	943810	+	315759	315867	8	146364022	-	102570622	102570730	1907772
+108
+
+chain	1013	8_random	943810	+	274298	274330	8	146364022	+	46839580	46839612	3252033
+32
+
+chain	968	8_random	943810	+	209695	209807	8	146364022	-	102537590	102537702	976902
+112
+
+chain	955	8_random	943810	+	319692	319755	8	146364022	-	102541225	102541288	3356813
+63
+
+chain	920	8_random	943810	+	258623	258775	8	146364022	+	46839508	46839659	980562
+59	25	24
+68
+
+chain	912	8_random	943810	+	192332	192490	8	146364022	+	46839260	46839417	3759652
+73	1	0
+84
+
+chain	891	8_random	943810	+	282553	282623	8	146364022	+	46843688	46843758	5243973
+70
+
+chain	873	8_random	943810	+	329911	329999	8	146364022	-	99523866	99523954	8492095
+88
+
+chain	847	8_random	943810	+	202393	202429	8	146364022	-	99516251	99516287	1768031
+36
+
+chain	808	8_random	943810	+	208103	208146	8	146364022	-	99506642	99506685	12166401
+43
+
+chain	772	8_random	943810	+	215530	215581	8	146364022	-	102536642	102536693	4621463
+51
+
+chain	770	8_random	943810	+	298794	298927	8	146364022	-	102529795	102529928	1833110
+38	53	53
+42
+
+chain	762	8_random	943810	+	250305	250368	8	146364022	+	43793197	43793260	2202736
+63
+
+chain	756	8_random	943810	+	175550	175595	8	146364022	-	102569149	102569194	15473865
+45
+
+chain	725	8_random	943810	+	227416	227458	8	146364022	-	102569147	102569189	2128584
+42
+
+chain	715	8_random	943810	+	237975	238010	8	146364022	-	99524101	99524136	9984625
+35
+
+chain	713	8_random	943810	+	336818	336983	8	146364022	-	102542943	102543107	12287033
+51	32	31
+82
+
+chain	659	8_random	943810	+	178382	178432	8	146364022	+	43825088	43825138	1126561
+50
+
+chain	630	8_random	943810	+	343296	343350	8	146364022	-	102532544	102532598	1087222
+54
+
+chain	622	8_random	943810	+	284683	284767	8	146364022	+	46845804	46845888	4299331
+84
+
+chain	618	8_random	943810	+	240201	240253	8	146364022	-	99520719	99520771	5790991
+52
+
+chain	609	8_random	943810	+	323290	333340	8	146364022	-	99511696	99512332	2037608
+32	1962	77
+33	7985	456
+38
+
+chain	511	8_random	943810	+	216312	216456	8	146364022	-	99508390	99508534	2116227
+83	23	23
+38
+
+chain	484	8_random	943810	+	208068	208103	8	146364022	-	102535970	102536005	2214348
+35
+
+chain	473	8_random	943810	+	323389	323449	8	146364022	-	102540821	102540881	1734527
+60
+
+chain	468	8_random	943810	+	200282	202177	8	146364022	-	99515228	99517906	493558
+37	1827	2610
+31
+
+chain	468	8_random	943810	+	309496	309560	8	146364022	-	99509535	99509598	902510
+13	1	0
+50
+
+chain	464	8_random	943810	+	238361	238411	8	146364022	-	102570011	102570061	2549299
+50
+
+chain	406	8_random	943810	+	336390	336452	8	146364022	-	99513496	99513558	3227798
+62
+
+chain	400	8_random	943810	+	198171	198198	8	146364022	-	99524348	99524375	19170252
+27
+
+chain	389	8_random	943810	+	239467	298039	8	146364022	-	99516251	99516834	914933
+36	19	19
+76	58363	374
+78
+
+chain	383	8_random	943810	+	268230	268298	8	146364022	+	43829500	43829568	7647204
+68
+
+chain	371	8_random	943810	+	289553	289594	8	146364022	+	43829105	43829146	1419836
+41
+
+chain	325	8_random	943810	+	171359	194889	8	146364022	-	102534570	102537063	1177879
+33	23458	2421
+39
+
+chain	321	8_random	943810	+	245198	245253	8	146364022	+	46850481	46850536	16403329
+55
+
+chain	316	8_random	943810	+	336558	336619	8	146364022	-	99513661	99513722	9588463
+61
+
+chain	316	8_random	943810	+	215939	215982	8	146364022	-	102570362	102570405	11794790
+43
+
+chain	307	8_random	943810	+	268331	268373	8	146364022	+	46843677	46843719	14936951
+42
+
+chain	302	8_random	943810	+	246654	246683	8	146364022	+	46846317	46846346	2597963
+29
+
+chain	277	8_random	943810	+	330681	336249	8	146364022	-	99513081	99513355	13257215
+37	5476	182
+55
+
+chain	224	8_random	943810	+	233016	233053	8	146364022	-	102535110	102535147	5909193
+37
+
+chain	219	8_random	943810	+	216875	216929	8	146364022	-	99508952	99509006	1250703
+54
+
+chain	217	8_random	943810	+	192086	192136	8	146364022	+	43793491	43793541	12267504
+50
+
+chain	176	8_random	943810	+	230251	230289	8	146364022	-	99522702	99522740	26486914
+38
+
+chain	171	8_random	943810	+	301863	301893	8	146364022	-	99524375	99524405	2607431
+30
+
+chain	128	8_random	943810	+	303580	303689	8	146364022	-	102542031	102542140	1606173
+109
+
+chain	117	8_random	943810	+	213542	213590	8	146364022	-	102569848	102569896	24793283
+48
+
+chain	107	8_random	943810	+	265719	265758	8	146364022	+	43793691	43793730	32387625
+39
+
+chain	103	8_random	943810	+	302985	303114	8	146364022	-	99516149	99516278	2070053
+129
+
+chain	102	8_random	943810	+	266041	266087	8	146364022	+	43794012	43794058	15664471
+46
+
+chain	87	8_random	943810	+	266314	266347	8	146364022	+	46839806	46839839	33038660
+33
+
+chain	11336435868	9	140273252	+	0	140273252	9	141213431	+	10000	141153431	13
+189075	1	1
+14	2	2
+39464594	50000	50000
+261110	50000	50000
+208233	50000	50000
+142805	50000	50000
+464507	50000	50000
+152873	50000	50000
+172579	50000	50000
+799200	0	4
+398958	50000	50000
+549743	50000	100000
+632871	50000	50000
+680077	50000	50000
+181647	50000	50000
+291910	50000	100000
+465318	50000	50000
+350909	50000	50000
+194609	50000	100000
+370335	0	176
+128583	50000	100000
+157546	18100000	18150000
+450681	50000	50000
+223855	50000	50000
+162441	50000	50000
+159539	50000	50000
+199148	50000	50000
+194491	50000	100000
+158462	50000	150000
+471702	50000	150000
+376183	50000	150000
+174765	50000	150000
+289439	50000	50000
+682157	50000	50000
+158187	50000	100000
+187806	50000	50000
+178933	50000	100000
+21507948	50000	100000
+85380	50000	150000
+834971	1	0
+39559293	100000	150000
+3818133	200000	50000
+2075804	30000	50000
+1936434
+
+chain	19053295	9_random	1146434	+	140076	853151	9	141213431	+	43822338	44639038	145
+1110	1	1
+47	1	0
+215	1	0
+468	9	9
+1934	0	1
+953	14319	26012
+970	11	11
+117	1	1
+57	1	1
+127	0	1
+1035	1	1
+123	1	1
+1418	29455	36221
+965	1	1
+33	5	5
+816	1	1
+38	1	1
+87	8	8
+588	6	6
+286	13	13
+967	6	6
+911	125	14857
+67	1	1
+18	1	1
+472	11	11
+269	7	0
+869	1	1
+23	1	1
+240	1	0
+456	1	1
+96	1	1
+247	22	22
+225	1	1
+13	0	4
+40	1	1
+211	13	29
+582	1	1
+22	4	0
+453	1	1
+37	1	1
+251	11	11
+87	1	1
+49	1	1
+95	11	11
+149	1	1
+31	1	1
+205	5	0
+1090	5	5
+89	1	1
+74	14	14
+83	1	1
+51	1	1
+594	1	3
+462	85	85
+635	50621	3293
+88	0	1
+148	18	18
+428	2	0
+5	2	0
+19	0	1
+43	1	1
+529	1	6
+77	1	1
+31	1	1
+39	0	5
+124	15	15
+51	1	1
+80	1	1
+103	1	1
+77	1	1
+147	1	1
+72	1	1
+95	10	10
+657	1	1
+57	1	1
+69	1	1
+32	1	1
+587	4	4
+298	14	14
+1505	10	8
+560	0	4
+171	1	1
+44	1	1
+211	1	1
+22	1	1
+649	1	1
+42	0	2
+96	8	8
+45	1	0
+195	402195	519766
+38949	0	176
+45847	1	0
+46124	1	0
+3889	0	1
+52224
+
+chain	10363290	9_random	1146434	+	903151	1075657	GL000199.1	169874	+	0	130000	308
+35955	882	0
+20	1020	0
+32	3062	0
+106	14	15
+100	9	7
+334	16	18
+121	1	0
+84	3469	73
+179	1193	0
+255	3064	0
+235	844	167
+325	2720	0
+211	25	25
+216	3639	67
+100	681	1
+58	5271	0
+71	36	36
+155	11817	855
+1017	1	0
+10599	1	1
+42	0	1
+8519	112	112
+9882	0	680
+263	8	8
+56	30	30
+206	865	183
+1131	1	0
+12309	16295	0
+37	2637	0
+463	15	15
+739	1	1
+64	1	1
+2323	1	0
+743	202	202
+245	2	0
+10307	33	32
+8496	15	15
+1065	3	3
+49	1	1
+67	1	1
+24	1	1
+150	15	15
+81	1112	7412
+104	5	5
+160	48	48
+156	31	31
+109	29	29
+32	0	337
+118	36	36
+108	21	21
+69	163	165
+105	29	29
+255	32	32
+176	46	46
+97	54	54
+158	110	5213
+54	5	5
+61	1	0
+12	66	578
+49	0	1
+256	0	1
+5	1	0
+110	0	507
+39	59	227
+44	1	0
+5	1	2
+13	268	611
+32	340	0
+2169	5	5
+109
+
+chain	8496666	9_random	1146434	+	526031	616031	GL000198.1	90085	+	0	90000	391
+90000
+
+chain	3482851	9_random	1146434	+	0	36148	GL000201.1	36148	+	0	36148	837
+36148
+
+chain	3114479	9_random	1146434	+	350153	383343	7	159138663	+	58020084	58054331	923
+5741	0	1
+5176	1	1
+36	1	1
+8401	0	3
+180	1	0
+1283	1	371
+2015	11	695
+10343
+
+chain	2652717	9_random	1146434	+	939453	971857	GL000199.1	169874	+	50544	169869	966
+78	104	103
+57	43	43
+41	0	1193
+212	20	20
+112	51	51
+93	1	0
+763	32	32
+929	0	85729
+2133	785	785
+1551	1	1
+38	0	1
+29	1	1
+1849	179	179
+1081	14	14
+98	255	255
+3064	235	235
+844	325	325
+2000	1	1
+55	1	1
+663	211	211
+25	216	216
+3639	100	100
+681	58	58
+5271	71	71
+36	155	155
+4203
+
+chain	864673	9_random	1146434	+	1126594	1146123	9	141213431	-	1097613	1113419	4959
+1953	6	5
+978	2409	6373
+1991	1	1
+30	1	1
+1102	7741	55
+57	1	1
+3259
+
+chain	850211	9_random	1146434	+	1025598	1042157	GL000199.1	169874	+	85137	125159	1202
+223	15	15
+69	106	782
+56	4	4
+103	0	1190
+57	51	51
+154	11	11
+103	0	1190
+303	94	5704
+122	20	700
+283	11	11
+564	0	6798
+68	31	31
+85	0	1
+80	48	48
+422	49	50
+604	27	3091
+147	0	4594
+563	468	470
+104	1	1
+65	1	1
+786	1	1
+26	4	4
+3436	346	0
+2356	158	158
+2985	37	37
+170	167	170
+910	11	11
+54
+
+chain	769263	9_random	1146434	+	86461	232520	9	141213431	+	40031497	40507253	306
+1287	1	1
+39	9090	8469
+1482	3	0
+72	22972	39210
+845	1	5
+1628	100	33581
+19	1	1
+708	1	1
+40	1	1
+1672	2596	163229
+3012	1	1
+27	1	0
+759	0	1
+98	72164	49914
+85	17764	159979
+3474	1	1
+50	1	1
+6064
+
+chain	759449	9_random	1146434	+	205961	214049	9	141213431	+	40301888	40309971	6546
+2149	0	1
+2715	38	32
+3186
+
+chain	584316	9_random	1146434	+	1135427	1141773	9	141213431	+	140095418	140108346	9081
+578	0	1
+958	0	1
+3002	120	6700
+1688
+
+chain	406492	9_random	1146434	+	174973	187473	9	141213431	-	97329171	97382324	1352
+1045	1	0
+610	3	3
+25	1	1
+707	0	1
+949	1	0
+476	1	1
+37	0	2
+115	22	0
+99	2	0
+19	0	1
+85	84	84
+391	0	2
+2020	102	40820
+178	0	5
+70	1	1
+108	1	0
+1683	56	22
+203	4	0
+53	0	3
+1920	1	0
+25	15	0
+171	0	4
+991	1	0
+102	1	1
+39	1	0
+81
+
+chain	392431	9_random	1146434	+	102229	150933	9	141213431	-	100800050	101111299	1649
+1200	31	31
+61	100	87
+1550	13066	115954
+174	1	7
+2845	28138	189099
+40	1462	165
+36
+
+chain	384690	9_random	1146434	+	98535	256322	9	141213431	-	100787713	101169878	613
+1160	1	0
+743	100	2055
+1590	33793	2374
+3943	1	0
+110	10986	2654
+28	3892	11
+65	38	37
+101	8010	603
+1627	0	1
+4154	127	18597
+1903	17	17
+1098	1	0
+907	16	6
+635	1	0
+110	11	10
+1170	39276	55950
+254	1	1
+16	1	1
+222	1	1
+23	0	3
+11	1	1
+963	0	1
+1311	1	1
+22	1	1
+1083	0	2
+4770	9790	219711
+142	1	1
+35	1	1
+191	1	1
+48	1	1
+4295	1	0
+1323	1	1
+26	1	0
+2991	1	0
+1653	100	28511
+184	1	1
+25	1	1
+2332	2	0
+2424	1	1
+18	1	1
+1612	0	2
+1973	2	0
+4314
+
+chain	222862	9_random	1146434	+	974475	976909	GL000199.1	169874	-	29206	35723	496317
+103	0	512
+103	0	2379
+1951	0	1192
+277
+
+chain	216950	9_random	1146434	+	179171	191499	9	141213431	-	75591738	75613431	4354
+84	8327	17685
+315	1	1
+43	1	1
+565	1	1
+45	1	1
+144	1	1
+47	3	3
+216	4	8
+856	15	15
+173	1	1
+23	0	1
+306	1	1
+34	1	2
+855	1	1
+41	1	1
+59	0	1
+60	1	1
+46	1	1
+55
+
+chain	213582	9_random	1146434	+	1129631	1131840	9	141213431	-	1091833	1094042	537694
+2209
+
+chain	165378	9_random	1146434	+	971957	973731	X	155270560	+	21244335	21246110	770883
+1088	0	1
+111	1	1
+46	3	3
+525
+
+chain	132596	9_random	1146434	+	92033	271291	9	141213431	-	75460140	75627580	890
+687	15	5
+714	42447	12782
+26	11947	6649
+27	11	12
+38	1490	2
+104	2	0
+98	117515	142147
+548	14	14
+760	1	1
+15	5	5
+244	0	8
+225	1	1
+25	1	1
+184	1	1
+24	1	1
+112	1	1
+49	1	1
+657	0	4
+26	1	1
+142	1	1
+117	1	1
+521	1	1
+30	1	1
+427
+
+chain	126182	9_random	1146434	+	264182	265594	9	141213431	+	41417376	41418784	8289
+408	11	11
+453	3	0
+470	1	0
+66
+
+chain	121265	9_random	1146434	+	153981	183865	9	141213431	+	40369543	40485128	5651
+820	1	0
+80	65	65
+38	101	101
+1814	1	1
+19	1	1
+2113	24775	110477
+56
+
+chain	112452	9_random	1146434	+	977951	979143	9	141213431	+	41554070	41555262	1142654
+1192
+
+chain	111666	9_random	1146434	+	115028	116206	9	141213431	+	38976673	38977851	1144814
+1178
+
+chain	91839	9_random	1146434	+	95026	96000	9	141213431	-	97340505	97341479	1389514
+974
+
+chain	86695	9_random	1146434	+	89274	94894	9	141213431	+	40421854	40482922	755289
+656	0	1
+294	1	0
+357	1	1
+58	1	1
+181	2726	58174
+1345
+
+chain	85848	9_random	1146434	+	116324	118085	9	141213431	+	40126032	40127795	187229
+1300	0	2
+247	1	1
+31	1	1
+181
+
+chain	83527	9_random	1146434	+	105271	111078	9	141213431	+	43838264	43842306	8535
+1025	1	1
+44	1	1
+374	2077	318
+609	3	0
+643	18	19
+121	15	16
+135	5	0
+736
+
+chain	82351	9_random	1146434	+	265594	267154	9	141213431	-	97363431	97364991	1727
+341	2	2
+20	1	1
+738	1	1
+34	1	1
+206	1	1
+40	1	1
+174
+
+chain	74906	9_random	1146434	+	107880	108681	9	141213431	+	40288016	40288817	1344818
+46	1	0
+553	0	1
+201
+
+chain	73427	9_random	1146434	+	106816	115028	9	141213431	-	93902441	93905998	1707
+229	0	1
+500	19	19
+145	5760	1098
+49	0	1
+9	0	1
+188	1	1
+43	1	1
+243	1	1
+41	1	1
+206	1	1
+25	1	1
+443	0	1
+171	0	3
+135
+
+chain	72594	9_random	1146434	+	977068	977842	9	141213431	-	99740263	99741035	1743552
+651	1	0
+45	1	0
+76
+
+chain	68316	9_random	1146434	+	87923	91873	9	141213431	-	101134923	101183249	1049825
+372	0	1
+115	1	1
+37	1	1
+725	1749	46124
+950
+
+chain	61838	9_random	1146434	+	1042331	1042988	GL000199.1	169874	-	40496	41153	2045151
+657
+
+chain	55013	9_random	1146434	+	1075993	1076574	2	243199373	-	242829160	242829741	2308873
+581
+
+chain	54512	9_random	1146434	+	144930	149178	9	141213431	-	75605255	75609502	8620
+250	1	1
+26	1	1
+262	14	19
+1397	10	9
+876	1	0
+98	79	75
+65	1	1
+772	1	1
+31	1	1
+235	1	1
+74	1	1
+51
+
+chain	52053	9_random	1146434	+	149316	153855	9	141213431	+	40375457	40380000	99648
+79	244	244
+76	2437	2440
+75	10	10
+247	0	1
+19	1304	1304
+48
+
+chain	51431	9_random	1146434	+	126523	128919	9	141213431	-	101152632	101155028	6098
+2396
+
+chain	48062	9_random	1146434	+	390785	391322	5	180915260	-	163073999	163074536	2667488
+241	1	1
+201	3	3
+91
+
+chain	43629	9_random	1146434	+	1073062	1075987	GL000199.1	169874	+	35053	37976	298767
+312	2456	2456
+1	2	0
+78	21	21
+55
+
+chain	37453	9_random	1146434	+	1024767	1030521	GL000199.1	169874	+	88172	123905	8301
+52	0	3738
+40	1994	12406
+94	1068	11110
+31	165	2038
+48	1933	5847
+329
+
+chain	33524	9_random	1146434	+	133017	135796	9	141213431	+	39163384	39166153	115831
+53	1	1
+307	5	4
+44	1	1
+406	1	1
+21	5	0
+43	1	1
+177	1	1
+25	1	0
+31	1	1
+137	5	5
+20	1	1
+52	1	1
+27	1	1
+233	1	1
+20	1	1
+394	3	0
+363	1	1
+24	1	1
+370
+
+chain	29196	9_random	1146434	+	343146	344485	3	198022430	+	156000638	156001989	5034584
+50	1	0
+56	1	1
+104	128	140
+64	838	839
+97
+
+chain	28265	9_random	1146434	+	96095	96747	9	141213431	-	93903474	93904131	1828707
+74	0	10
+511	4	0
+47	1	0
+15
+
+chain	26156	9_random	1146434	+	111189	113362	9	141213431	-	102220148	102222323	47568
+1400	0	1
+94	5	6
+674
+
+chain	25868	9_random	1146434	+	149715	153807	9	141213431	-	93950637	93954729	91748
+181	1	1
+57	1	1
+353	15	15
+330	1	0
+22	1	1
+220	93	93
+114	0	17
+104	9	9
+290	2	0
+293	1	1
+20	1	1
+328	351	343
+127	1	1
+76	1	1
+331	4	0
+52	1	1
+17	1	1
+106	5	0
+146	1	1
+38	0	3
+7	1	0
+116	3	3
+16	1	1
+168	0	1
+85
+
+chain	25003	9_random	1146434	+	1069304	1075830	GL000199.1	169874	+	56286	59580	21268
+305	7	7
+77	487	487
+25	288	288
+36	198	198
+163	105	105
+29	463	463
+46	1256	67
+82	36	36
+95	32	32
+28	2595	552
+103	9	9
+61
+
+chain	23281	9_random	1146434	+	1028681	1035309	GL000199.1	169874	+	97567	114227	7110
+30	1360	6799
+121	342	0
+5	4424	9363
+103	237	233
+6
+
+chain	21805	9_random	1146434	+	1135081	1135321	9	141213431	+	140101239	140101479	9135145
+197	1	1
+42
+
+chain	21533	9_random	1146434	+	1010735	1043373	GL000199.1	169874	+	61213	69988	6310
+337	14018	4703
+439	42	42
+27	307	307
+106	220	220
+51	16938	2390
+153
+
+chain	19014	9_random	1146434	+	335566	335883	16	90354753	-	56512811	56513131	11268597
+170	97	100
+50
+
+chain	18803	9_random	1146434	+	86148	86348	9	141213431	-	100705477	100705677	11441237
+200
+
+chain	13349	9_random	1146434	+	1068589	1070018	GL000199.1	169874	+	79052	79803	7749
+23	14	14
+253	37	37
+60	717	39
+8	269	269
+48
+
+chain	13149	9_random	1146434	+	410938	411078	8	146364022	+	38639711	38639851	17290853
+140
+
+chain	12972	9_random	1146434	+	332343	332481	7	159138663	+	61759398	61759536	17535033
+138
+
+chain	12821	9_random	1146434	+	388858	389014	15	102531392	+	80798356	80798512	17757829
+81	12	12
+63
+
+chain	11442	9_random	1146434	+	388166	388417	12	133851895	+	34836761	34837526	19956621
+81	109	623
+61
+
+chain	11149	9_random	1146434	+	343358	343713	3	198022430	-	62479553	62479920	5356830
+1	103	115
+24	134	134
+93
+
+chain	11085	9_random	1146434	+	468603	468722	9	141213431	+	42720405	42720524	20596057
+119
+
+chain	9550	9_random	1146434	+	389696	390760	X	155270560	+	61752907	61753125	23891795
+65	939	93
+60
+
+chain	9178	9_random	1146434	+	345818	345932	16	90354753	+	32819577	32819691	24666411
+52	7	7
+55
+
+chain	9128	9_random	1146434	+	321692	322933	7	159138663	+	61799163	61799701	24755828
+61	1115	412
+65
+
+chain	9086	9_random	1146434	+	338884	339289	16	90354753	+	32789437	32789842	24819157
+53	289	289
+63
+
+chain	9023	9_random	1146434	+	387021	388166	7	159138663	+	61404533	61405164	23790101
+52	1085	571
+8
+
+chain	7872	9_random	1146434	+	1069035	1072121	GL000199.1	169874	+	119465	157584	536281
+72	46	46
+97	2835	37868
+36
+
+chain	7579	9_random	1146434	+	402601	403961	3	198022430	-	107545066	107546932	27123369
+31	1026	0
+52	201	1733
+50
+
+chain	7458	9_random	1146434	+	343360	343449	6	171115067	+	69499143	69499232	6836024
+89
+
+chain	6713	9_random	1146434	+	425056	425127	16	90354753	+	46455806	46455877	28826250
+71
+
+chain	6541	9_random	1146434	+	468921	468991	7	159138663	+	61361207	61361277	29216706
+70
+
+chain	6486	9_random	1146434	+	330636	330705	10	135534747	+	42383267	42383336	29375264
+69
+
+chain	6456	9_random	1146434	+	411427	412083	11	135006516	+	48877623	48879132	29439180
+48	554	1407
+54
+
+chain	6295	9_random	1146434	+	404771	404838	8	146364022	+	43770407	43770474	29850106
+67
+
+chain	6049	9_random	1146434	+	414120	414184	7	159138663	-	101095351	101095415	30492982
+64
+
+chain	6040	9_random	1146434	+	465963	466027	6	171115067	+	83274875	83274939	30512451
+64
+
+chain	5969	9_random	1146434	+	389015	389089	Y	59373566	-	43064540	43064609	20514560
+61	5	0
+8
+
+chain	5636	9_random	1146434	+	406636	407740	8	146364022	+	43770397	43770476	31630565
+28	1025	0
+51
+
+chain	5631	9_random	1146434	+	426803	426863	10	135534747	+	42387748	42387808	31636152
+60
+
+chain	5540	9_random	1146434	+	419067	419126	7	159138663	+	61079182	61079241	31906304
+59
+
+chain	5476	9_random	1146434	+	398987	399045	12	133851895	+	34839855	34839913	32105830
+58
+
+chain	5376	9_random	1146434	+	415322	415379	11	135006516	-	86268315	86268372	32415872
+57
+
+chain	5358	9_random	1146434	+	413960	414017	Y	59373566	-	49305277	49305334	32458256
+57
+
+chain	5349	9_random	1146434	+	411179	411236	7	159138663	+	91218545	91218602	32466470
+57
+
+chain	5349	9_random	1146434	+	417041	417098	11	135006516	-	84295010	84295067	32466776
+57
+
+chain	5305	9_random	1146434	+	979284	979471	GL000199.1	169874	+	100510	100697	1541
+187
+
+chain	5294	9_random	1146434	+	393589	393645	GL000208.1	92689	-	78786	78842	32648958
+56
+
+chain	5285	9_random	1146434	+	407829	407885	16	90354753	+	34022252	34022308	32672407
+56
+
+chain	5248	9_random	1146434	+	345095	345150	3	198022430	+	72765342	72765397	32777800
+55
+
+chain	5194	9_random	1146434	+	325928	325983	16	90354753	+	46454212	46454267	32965981
+55
+
+chain	5076	9_random	1146434	+	385523	385577	9	141213431	-	74211269	74211323	33342253
+54
+
+chain	5012	9_random	1146434	+	398477	398530	3	198022430	-	107545544	107545597	33565319
+53
+
+chain	4985	9_random	1146434	+	417987	418040	8	146364022	+	43776134	43776187	33649135
+53
+
+chain	4821	9_random	1146434	+	397137	397188	X	155270560	+	61817502	61817553	34214385
+51
+
+chain	4794	9_random	1146434	+	414576	414627	11	135006516	+	50778923	50778974	34325073
+51
+
+chain	4794	9_random	1146434	+	397714	397765	GL000208.1	92689	-	71810	71861	34325191
+51
+
+chain	4730	9_random	1146434	+	411917	411967	21	48129895	-	33764186	33764236	34527656
+50
+
+chain	4709	9_random	1146434	+	107713	107880	9	141213431	+	40326898	40327067	460940
+64	0	2
+103
+
+chain	4703	9_random	1146434	+	396620	396670	11	135006516	+	50701175	50701225	34648839
+50
+
+chain	4594	9_random	1146434	+	460317	460366	1	249250621	+	72586197	72586246	34758860
+49
+
+chain	4154	9_random	1146434	+	389765	389825	X	155270560	+	61859291	61859351	24051909
+60
+
+chain	4125	9_random	1146434	+	1047887	1048034	GL000199.1	169874	+	145761	145908	266403
+21	18	18
+108
+
+chain	4032	9_random	1146434	+	1010207	1010501	GL000199.1	169874	+	46738	47032	105345
+133	51	51
+110
+
+chain	3744	9_random	1146434	+	974418	974475	GL000199.1	169874	-	111819	111876	792102
+57
+
+chain	3426	9_random	1146434	+	939387	939437	GL000199.1	169874	+	161370	161420	23133078
+50
+
+chain	3397	9_random	1146434	+	1069115	1069304	GL000199.1	169874	+	57287	57476	721888
+38	97	97
+54
+
+chain	3297	9_random	1146434	+	1037665	1037723	GL000199.1	169874	+	108413	108471	1099981
+5	32	32
+21
+
+chain	2900	9_random	1146434	+	210827	210859	9	141213431	+	43889710	43889742	6957
+32
+
+chain	2688	9_random	1146434	+	1042157	1042279	GL000199.1	169874	+	112227	112349	8300
+65	9	9
+48
+
+chain	2652	9_random	1146434	+	999650	1043482	GL000199.1	169874	+	41812	46278	8409
+112	43376	4009
+54	0	1
+28	153	153
+109
+
+chain	2438	9_random	1146434	+	1025529	1025571	GL000199.1	169874	+	134052	134094	269933
+42
+
+chain	2404	9_random	1146434	+	153855	153881	9	141213431	+	40071265	40071291	103174
+26
+
+chain	2298	9_random	1146434	+	1010672	1010735	GL000199.1	169874	+	66766	66829	8935
+63
+
+chain	2164	9_random	1146434	+	1010368	1010391	9	141213431	-	71502272	71502295	32168220
+23
+
+chain	2160	9_random	1146434	+	388789	388840	7	159138663	-	101569537	101569588	23945255
+51
+
+chain	2026	9_random	1146434	+	343746	343819	10	135534747	+	18324071	18324144	14357746
+73
+
+chain	1834	9_random	1146434	+	1010501	1010672	GL000199.1	169874	+	60299	60470	7461
+171
+
+chain	1808	9_random	1146434	+	391322	391360	7	159138663	-	47529927	47529965	6263864
+38
+
+chain	1777	9_random	1146434	+	343550	344817	22	51304566	+	35077657	35078810	5733588
+48	1167	1053
+52
+
+chain	1529	9_random	1146434	+	263922	264091	9	141213431	+	65673675	65673833	515
+62	10	0
+17	1	0
+14	2	2
+63
+
+chain	1325	9_random	1146434	+	1037723	1037780	GL000199.1	169874	+	96057	96114	245438
+57
+
+chain	1237	9_random	1146434	+	1024624	1024767	GL000199.1	169874	+	49580	49723	8604
+143
+
+chain	1217	9_random	1146434	+	1071842	1072151	GL000199.1	169874	+	48108	48417	165690
+30	6	6
+74	169	169
+30
+
+chain	897	9_random	1146434	+	1035274	1035303	GL000199.1	169874	+	108574	108603	711169
+29
+
+chain	881	9_random	1146434	+	345308	345393	X	155270560	-	77826120	77826205	8910963
+85
+
+chain	812	9_random	1146434	+	344331	344387	9	141213431	+	18649465	18649521	20542621
+56
+
+chain	538	9_random	1146434	+	1029334	1029359	GL000199.1	169874	+	75943	75968	9317
+25
+
+chain	480	9_random	1146434	+	344828	344880	4	191154276	-	62643619	62643671	15050009
+52
+
+chain	461	9_random	1146434	+	96747	96777	9	141213431	+	38980922	38980952	1279
+30
+
+chain	364	9_random	1146434	+	1025018	1025062	GL000199.1	169874	+	64308	64352	115390
+44
+
+chain	296	9_random	1146434	+	1009971	1010001	GL000199.1	169874	+	44634	44664	18919
+30
+
+chain	288	9_random	1146434	+	974120	974172	GL000199.1	169874	+	44920	44972	1936043
+52
+
+chain	260	9_random	1146434	+	394227	394279	11	135006516	+	50701175	50701227	28339537
+52
+
+chain	210	9_random	1146434	+	1025062	1025090	GL000199.1	169874	+	71670	71699	216729
+6	0	1
+22
+
+chain	209	9_random	1146434	+	388033	388083	11	135006516	-	84294197	84294247	27927923
+50
+
+chain	152	9_random	1146434	+	393023	393074	20	63025520	+	26259164	26259215	28112557
+51
+
+chain	86	9_random	1146434	+	405210	405252	3	198022430	-	107550280	107550322	32195393
+42
+
+chain	79	9_random	1146434	+	392892	392941	11	135006516	+	50661000	50661049	27948217
+49
+
+chain	14267288654	X	154913754	+	0	154913754	X	155270560	+	60000	155260560	8
+34821	50000	50000
+86563	30000	50000
+766173	50000	50000
+36556	50000	50000
+80121	90000	50000
+754004	100000	50000
+5505644	0	50000
+3064785	0	50079
+26309510	25000	50000
+201175	0	8
+7417	2	0
+53136	0	8
+3076	12	0
+21092	2	0
+60831	0	2
+57728	20	0
+54336	1	0
+31676	4	0
+9986	0	4
+12109	4	0
+11227342	2000	0
+354815	50000	50000
+77401	1	1
+17	1	1
+94	3	0
+266	10	10
+113	1	1
+21	1	1
+5401	5	0
+4970	2	0
+33	6	0
+3221	1	5
+6456	0	1
+1476	5	5
+2100	1	1
+40	1	1
+1316	1	0
+2446	0	1
+1589	17	15
+11171	0	1
+2639	0	1
+5190	4	0
+78	0	8
+5087	1	0
+2663	0	1
+9149	8	7
+1851	1	0
+9081	1	0
+7249	0	25
+199	2	0
+12	2	0
+16	0	209
+37	0	20
+2536	1	0
+1394	6	0
+12550	42	0
+821	0	4
+30579	0	1
+3710	0	4
+3638	0	1
+11945	1	0
+20204	1	0
+4171	0	8
+5680	0	1
+23827	2	0
+54817	1	0
+657	1	0
+342931	180000	50000
+2052068	1	27
+5375	0	2
+46	2	0
+6489	1	0
+7175	0	2
+1239	0	2
+4302	4	0
+27253	1	0
+4244	2	0
+717	2	0
+261	6	0
+26074	0	1
+236464	50000	50000
+6136098	3000000	3100000
+13518993	0	1
+449	0	1
+4533	0	4
+757	0	1
+1102	25	26
+107	0	2
+3470	1	0
+1108	0	1
+4775	0	1
+8628	1	1
+46	1	1
+1072	1	1
+44	1	1
+292	5	4
+9091	4	4
+2218	4	4
+705	1	5
+452	1	0
+88	32	32
+212	1	0
+1801	1	7
+3960	0	1
+2007	0	1
+1979	38	38
+1320	0	1
+2093	0	1
+403	0	310
+6134	1	1
+36	1	1
+1697	0	1
+97	0	13
+7624	1	1
+19	1	1
+6933	0	1
+779	7	7
+721	1	1
+43	1	1
+1626	1	0
+6146	2	0
+150	1	1
+47	1	1
+2172	2	0
+398	1	1
+31	1	1
+1149	2	2
+183	16	16
+1663	1	1
+18	1	1
+2105	10	11
+1409	1	1
+33	1	1
+1753	0	1
+408	1	0
+1916	0	1
+477	37	37
+1415	12	0
+3799	17	17
+2921	1	0
+1811	33	33
+2753	2	0
+486	0	6
+1388	1	1
+44	1	1
+186	1	1
+46	1	1
+3037	1	0
+2301	3	0
+3876	1	1
+22	1	1
+1724	0	1
+3733	0	1
+627	0	1
+250	1	0
+194	1	1
+26	1	1
+20797	10	10
+2445	1	0
+1733	0	2
+1001	12	0
+4394	9	9
+4052	10	9
+670	1	1
+97	6	0
+25	1486	1188
+10	3	2
+28	41	41
+28	2	3
+10	126	1058
+11	1051	417
+25	0	6
+18	1	1
+62	17	17
+77	0	1
+1009	41	41
+3899	10	10
+4690	0	1
+7343	1	0
+1248	1	0
+1259	1	0
+1345	0	4
+1534	1	0
+3797	16	16
+807	1	0
+2427	1	0
+48	0	1
+287	1	0
+611353	0	1
+1041	6	0
+371	0	1
+227	0	1
+2806	1	0
+36	1	1
+234	1	1
+23	1	1
+584	1	0
+22241	1	1
+65	1	1
+4605	0	1
+2326	0	20
+2130	0	1
+6170	9	13
+10665	0	1
+14631	1	0
+5359	4	0
+4004	1	0
+3182	11	0
+3897	14	16
+2551	1	0
+1824	1	0
+5274	1	1
+41	1	1
+4309	0	1
+3827	0	1
+4594	0	1
+65	1	1
+1170	1	1
+42	4	4
+214	0	1
+5228	0	1
+553	1	0
+5528	7	7
+735	14	14
+2861	1	0
+156	0	2
+6183	42	42
+2595	1	1
+41	1	1
+472	1	1
+65	0	1
+8	1	1
+1162	1	0
+565	1	1
+48	1	1
+536	2	1
+766	0	2
+4520	0	1
+1574	1	0
+503	0	1
+2558	0	1
+250061	7	7
+9650	18	18
+3208	1	1
+25	0	1
+744	2	0
+2994	1	1
+33	1	1
+1331	1	0
+2042	6	17
+1292	1	1
+35	1	1
+2485	1	1
+35	1	1
+17284	1	0
+7	7	1
+670	0	4
+429	0	1
+4736	1	0
+3849	0	1
+6745	16	16
+2344	1	1
+41	1	1
+4459	9	9
+3449	0	1
+3876	1	1
+75	1	1
+1429	7	7
+11126	26	26
+781	1	1
+28	1	1
+409	12	13
+1223	12	12
+5354	0	1
+1255	0	6
+851	65	65
+126	1	1
+47	5	5
+5931	4	0
+420	0	1
+2949	0	6
+193	324	324
+6740	1	3
+1074	1	0
+2465	1	1
+40	1	1
+640	2	0
+550	1	1
+32	1	1
+4096	1	1
+29	1	1
+949	6	6
+6258	1	0
+3957	1	0
+19608	1	1
+48	1	1
+234	0	1
+13246	13	13
+4651	321	0
+2617	1	0
+4553	0	3
+491	0	6
+7496	1	1
+9	0	10
+77	0	4
+3314	1	1
+32	1	1
+5217	1	0
+1500	17	17
+2023	1	0
+2425	0	18
+3110	8	8
+3248	1	0
+1946	1	1
+48	1	1
+9620	0	2
+31242	20000	50000
+36075685	3	0
+36004	1	1
+27	1	1
+5196	0	1
+293	0	2
+13307	0	3
+2420	6	0
+1863	0	2
+2911	0	1
+3233	2	0
+66	1	0
+2376	10	0
+4893	1	0
+745	1	0
+3897	0	13
+3835	1	1
+55	1	1
+538	1	1
+48	4	1
+20	0	2
+279	0	2
+33	1	1
+48	1	0
+387	8	8
+692	0	1
+375	3	0
+383	1	1
+18	1	1
+1289	1	1
+29	1	1
+12332	0	331
+856	4	0
+48	0	4
+8716	0	5
+130	2	0
+3001	0	1
+1332	8	5
+23273	0	1
+30174	27	39
+337	0	3
+2838	1	0
+1614	0	9
+313	0	1
+83	4	0
+172	1	1
+25	1	1
+4912	0	39
+1863	0	1
+2931	1	0
+3134	0	3
+390880	0	1
+7199	1	0
+305	2	0
+1811	2	0
+5449	0	3
+7443	0	2
+2171	1	1
+27	1	1
+2668	0	2
+2180	0	1
+1170	0	9
+1450	16	16
+3080	1	0
+920	18	18
+10219	1	0
+678	1	1
+28	1	1
+698	1	0
+112	1	0
+1831	3	0
+14327	2	0
+2087	10	10
+150	0	3
+380	1	1
+28	1	1
+1265	19	21
+7184	3	2
+4225	9	14
+1002	0	1
+3855	4	0
+2534	1	1
+30	1	1
+794	1	0
+25	1	1
+76140	70000	50000
+1432750	4799	0
+8	2973	0
+681864	20000	50000
+4278742	0	56347
+12021233	9	9
+1775	1	0
+1468	1	1
+51	16	14
+6	0	1
+6	0	1
+11	4	5
+7	0	1
+4	0	1
+75	1	2
+26	1	0
+16	0	1
+9	0	1
+19	0	2
+22	1	0
+9	0	1
+5	1	3
+14	6	7
+38	1	0
+26	1	1
+62	0	1
+38	1	1
+1687	0	1
+54	0	1
+8528	0	1
+2722	0	1
+6240	0	1
+33	0	1
+121285	1	0
+6	0	1
+35	1	0
+1381	0	1
+5368	1	0
+3079	0	1
+10863441	0	4
+1799	1	1
+24	1	1
+334	1	0
+4960	17	0
+1160	1	1
+34	1	1
+6153	3	0
+1346	4	0
+103	4	0
+2835	12	12
+304	0	16
+719	0	1
+3286	1	0
+10182	0	9
+804	1	1
+28	1	1
+749	0	1
+3387	1	1
+47	1	1
+482	0	1
+455	15	15
+719	1	1
+18	1	1
+2074	0	1
+1348	0	4
+3928	1	1
+18	1	1
+907	0	1
+2972	2	0
+115	1	1
+37	1	1
+4428	1	0
+1120	1	0
+4055	5	0
+2753	18	18
+158	3	0
+3590	1	1
+47	1	1
+62	1	0
+947	1	1
+45	1	1
+1639	1	1
+32	1	1
+1076	0	1
+3996	4	0
+7965	1	0
+1733	1	0
+1451	0	2
+617	1	0
+4375	0	1
+2194	64	63
+301	1	1
+27	1	1
+6661	1	1
+79	1	1
+1495	1	0
+499	1	1
+37	2	2
+968	1	0
+34	1	1
+6337	1	1
+18	1	1
+8162	1	1
+22	5	0
+9274	1	0
+6017	5	5
+3872	8	0
+5421	1	0
+532	6	7
+5673	0	4
+1542	4	0
+890	3	1
+2561	1	0
+1692	1	0
+1142	1	1
+32	1	1
+503	2	1
+123	1	1
+75	1	1
+2322	1	0
+201	1	0
+40	3	3
+149	3	0
+1441	1	1
+40	1	1
+159	2	0
+1278	1	1
+33	1	1
+221	0	1
+31	1	1
+161	9	10
+1890	0	1
+132	1	1
+37	1	1
+514	17	23
+1373	4	0
+907	1	1
+15	1	1
+714	1	1
+18	0	1
+10	1	1
+55	1	1
+24	1	1
+1038	2	0
+95	1	5
+1094	1	1
+170	1	1
+844	0	3
+369	1	1
+39	1	1
+650	1	1
+41	1	1
+176	12	12
+688	1	0
+7640	4	0
+2650	1	1
+28	0	4
+44	1	1
+728	8	0
+2196	0	1
+13466	0	1
+3510	0	2
+2147	1	1
+44	0	3
+1320	11	11
+210	0	4
+105	1	0
+3239	0	1
+1496	142	153
+2391	1	1
+39	0	2
+438	4	0
+2272	8	0
+6865	0	3
+7183	0	1
+5104	0	3
+182	1	0
+3131	1	1
+31	1	0
+14	1	1
+59	1	0
+373	1	1
+42	1	1
+235	13	13
+1608	0	5
+152	1	1
+106	1	1
+783	34	34
+1633	1	1
+29	3	0
+821	1	1
+24	1	1
+1178	1	1
+33	1	1
+328	1	1
+27	1	1
+5682	16	13
+146398	30000	50000
+59809	0	2
+3389	1	1
+37	1	1
+11606	0	1
+1597	0	1
+618	1	1
+47	1	1
+2698	0	1
+826	5	5
+33	0	2
+2560	0	14
+98	0	3
+1287	0	1
+7600	0	1
+9894	0	8
+7160	0	1
+32	1	1
+1698	0	1
+754	2	0
+6787	0	1
+584	0	2
+1107	1	1
+40	1	1
+365	1	1
+35	1	1
+399	0	8
+11444	0	1
+1973	0	1
+1200	0	1
+716	1	1
+25	1	1
+1570	0	2
+433	2	0
+905	0	2
+94	1	1
+28	1	1
+2490	18	18
+5054	9	1
+2184	0	2
+2955	23	21
+431	49	49
+314	1	0
+1563	1	1
+20	1	1
+1632	11	0
+1671	2	0
+1527	0	1
+676	1	1
+29	1	1
+1245	1	1
+34	0	1
+1203	22	30
+1934	1	0
+3421	0	2
+17	1	1
+774	0	30
+97	6	6
+59	12	26
+840	1	1
+19	1	1
+2036	27	53
+683	30	30
+401	0	1
+25	1	1
+381	16	0
+159	1	1
+17	1	1
+1150	0	4
+700	1	0
+29	0	2
+409	1	1
+49	1	1
+1240	1	1
+37	3	3
+2248	0	1
+1828	0	1
+1997	1	5
+4640	4	4
+4555	2	0
+150	52	0
+618	2	2
+16	1	1
+83	0	22
+56	1	57
+2531	8	0
+4250	17	17
+2203	4	0
+1665	10	0
+415	0	2
+393	0	1
+15728	1	0
+158	0	4
+82	0	14
+543	1	1
+42	1	1
+3261	18	18
+139	1	1
+37	1	1
+410	1	1
+18	1	1
+5405	0	1
+1104	1	1
+53	1	1
+392	1	1
+55	3	3
+3352	0	9
+692	106	52
+27	4	0
+13	1	3
+14	88	0
+61	2	0
+8931	0	1
+6692	2	1
+253	19	19
+869	2	0
+196	0	2
+389	1	1
+30	1	1
+949	1	0
+6057	3	0
+4741	0	1
+7689	0	2
+2046	18	18
+215	1	0
+46885	0	2
+24138	0	2
+4037	0	1
+4047693	0	1
+9545	2	0
+11590	0	4
+1698	3	1
+18923	0	4
+1806	1	1
+44	1	1
+2581	2	0
+10620	1	0
+3804	1	0
+339	2	0
+476	1	0
+5861	5	8
+109	14	0
+901	1	1
+19	1	1
+45	0	2
+1736	0	1
+6625	0	2
+7812	0	4
+7678	0	2
+5086	3	8
+4170	1	0
+1671	0	6
+6333	16	0
+902	1	1
+44	1	1
+384	6	0
+23181	4	4
+214	0	2
+8958	4	0
+220	1	1
+49	1	1
+2783	1	0
+2641	1	0
+136	20	20
+1279	1	0
+3924	6	6
+13054	0	6
+8954	13	0
+4128	0	2
+2269	0	1
+16258	2	0
+30076	1	1
+49	1	1
+102	0	1
+8824	27	27
+1730	1	1
+47	1	1
+3339	1	0
+132	16	0
+81	0	16
+89	0	6
+6369	0	1
+541	0	1
+6288	4	0
+3814	0	2
+7260	1	0
+802	0	68
+1166	1	0
+2230	0	1
+1109	1	0
+1106	0	2
+12396	1	0
+26207	1	1
+21	1	1
+4087	16	0
+1323	7	7
+525	1	0
+4198	1	0
+4682	13	13
+890	2	0
+816	2	0
+1961	4	0
+24586	1	1
+19	1	1
+4403	0	1
+1342	0	1
+57	11	12
+2229	30	31
+1979	35	0
+10541	1	0
+9725	6	0
+2536	1	2
+20	1	1
+1541	12	0
+1130	1	1
+34	1	1
+927	1	0
+4003	1	0
+966	0	1
+149	1	0
+842	0	8
+4326	1	1
+25	1	1
+569	6	7
+664	2	2
+5695	0	1
+3074	1	0
+1539	9	3
+634	1	1
+39	1	1
+8610	1	1
+11	0	1
+345	43	43
+372	0	2
+4311	6	0
+3122	2	0
+369	0	1
+9963	10	10
+2191	1	1
+23	1	1
+1060	1	1
+19	1	1
+240	12	12
+1748	1	1
+45	1	1
+1040	1	1
+31	1	1
+7446	1	1
+25	1	1
+8379	7	7
+7325	0	3
+357	1	0
+1313	1	0
+11624	0	4
+5865	0	1
+9750	0	1
+3540	16	0
+5671	13	13
+2885	4	0
+8179	0	1
+753	1	0
+2289	49	49
+1979	2	0
+1318	0	1
+957	1	0
+825	12	12
+1110	16	0
+3735	17	17
+9997	223	53
+149	22	24
+636	1	1
+22	0	1
+42	1	1
+1634	4	4
+3380	3	0
+979	0	2
+3429	1	0
+7138	14	0
+1727	1	1
+38	1	0
+88	0	1
+630	20	20
+476	0	5
+21	0	1
+94	0	1
+42	1	0
+17	0	1
+27	0	1
+172	1	1
+37	1	1
+191	1	1
+66	1	1
+630	0	1
+261	1	1
+28	1	1
+1282	17	18
+429	0	1
+1588	1	1
+20	1	1
+1416	1	1
+33	1	1
+529	0	1
+25	0	1
+1863	0	4
+1651	1	1
+28	1	1
+11815	0	1
+26	0	1
+19	1	1
+3105	0	1
+700	0	1
+150	0	1
+68	0	1
+1420	0	6
+568	14	16
+2415	0	1
+41	1	1
+415	1	1
+33	1	1
+4521	1	1
+33	1	1
+307	1	0
+176	1	0
+3790	1	1
+86	1	1
+67	1	1
+65	0	1
+7439	1	1
+18	1	1
+16805	0	1
+1764	1	0
+3104	35	35
+3845	0	1
+3384	0	2
+17	0	18
+156	1	1
+30	1	1
+165	0	2
+1087	1	0
+953	1	0
+483	0	1
+632	1	0
+652	1	0
+8563	9	7
+1860	1	0
+398	1	0
+2219	1	1
+53	1	1
+756	1	1
+66	1	1
+69	1	1
+48	1	1
+63	1	1
+28	3	0
+1057	3	0
+63	0	3
+55	1	1
+74	3	2
+159	0	3
+92	1	1
+29	1	1
+58	3	0
+1210	9	9
+54	1	1
+27	1	1
+1374	0	2
+1775	17	2
+764	14	14
+331	16	16
+2291	3	4
+1687	1	1
+26	1	1
+2469	1	0
+3243	0	1
+3636	1	1
+24	1	1
+615	1	0
+2566	0	1
+275	5	0
+695	7	0
+9686	32	32
+3416	0	1
+1452	4	0
+214	13	13
+49	0	124
+1393	9	9
+5812	1	1
+24	1	1
+5703	0	1
+4006	1	0
+1462	3	0
+5199	2	0
+1554	0	2
+715	10	12
+1966	0	2
+2801	0	16
+618	0	1
+413	18	0
+730	1	1
+31	1	1
+4372	5	0
+10789	1	0
+2399	1	0
+6750	0	2
+1363	6	0
+6736	2	0
+4457	0	4
+7867	1	0
+3495	2	1
+7584	0	1
+2652	1	0
+1771	0	1
+14808	41015	41008
+19235	0	1
+9638	0	1
+2994	0	1
+469	3	1
+499	0	1
+12074	13	13
+2807	10	11
+715	0	2
+1627	6	6
+5099	1	0
+488	1	5
+975	0	2
+1761	0	1
+1794	5	0
+8254	3	3
+18	1	1
+3737	9	9
+1442	13	13
+212	0	10
+7712	1	1
+44	1	1
+4480	40	40
+1751	1	0
+1316	1	1
+49	1	1
+9050	4	0
+143	0	2
+2813	13	13
+1286	2857	49999
+75638	40000	50000
+1583473	0	2
+1564099	1	97463
+2933461
+
+chain	1621142	X	154913754	+	148570601	148611616	X	155270560	-	6466757	6507765	175
+13140	0	1
+20345	6	0
+3704	1	0
+1517	1	0
+2301
+
+chain	259772	X	154913754	+	75282398	75286444	X	155270560	-	79901776	79905823	6183
+1486	41	41
+41	40	40
+126	11	11
+1051	1209	1210
+41
+
+chain	192506	X	154913754	+	114908114	114911060	X	155270560	+	114997023	115000000	3054
+63	528	528
+60	0	16
+630	28	44
+689	16	16
+436	1	0
+495
+
+chain	188216	X	154913754	+	114908656	114914454	X	155270560	+	115000574	115005488	36116
+49	2721	1850
+47	8	8
+197	704	696
+2	16	0
+1155	42	43
+455	2	12
+400
+
+chain	119665	X	154913754	+	114906873	114908114	X	155270560	+	115003848	115005094	1024208
+1216	0	5
+25
+
+chain	29390	X	154913754	+	76491035	76491342	1	249250621	-	136684922	136685229	4932608
+307
+
+chain	25643	X	154913754	+	114911150	114911426	X	155270560	+	115005157	115005433	246321
+276
+
+chain	19821	X	154913754	+	114908177	114911739	X	155270560	+	114982173	114982762	1997
+479	3022	49
+61
+
+chain	15998	X	154913754	+	114911743	114912382	X	155270560	+	114967843	114968482	6239
+639
+
+chain	9708	X	154913754	+	148714470	148714905	5	180915260	-	8837105	8837560	23506322
+56	313	333
+66
+
+chain	9294	X	154913754	+	114906712	114906808	X	155270560	+	115005518	115005614	24447825
+96
+
+chain	6266	X	154913754	+	114906808	114906873	X	155270560	+	114962882	114962947	1027613
+65
+
+chain	6215	X	154913754	+	76426104	76426191	X	155270560	+	29934095	29934182	9535161
+87
+
+chain	5894	X	154913754	+	143027611	143027675	2	243199373	-	154977524	154977591	249
+15	0	3
+49
+
+chain	3277	X	154913754	+	76426069	76426104	1	249250621	-	60612464	60612499	19993171
+35
+
+chain	2407	X	154913754	+	148714814	148714839	2	243199373	+	100113459	100113484	27784968
+25
+
+chain	1984	X	154913754	+	76426191	76426234	8	146364022	-	27059036	27059079	21505033
+43
+
+chain	1549	X	154913754	+	114911087	114911150	X	155270560	+	114976136	114976199	336010
+63
+
+chain	1443	X	154913754	+	114913555	114913597	X	155270560	+	114984570	114984612	98822
+42
+
+chain	1245	X	154913754	+	148714288	148714366	4	191154276	-	133575330	133575408	22672116
+78
+
+chain	1030	X	154913754	+	114911060	114911082	X	155270560	+	114988042	114988064	7002
+22
+
+chain	733	X	154913754	+	148715982	148716070	X	155270560	-	110405878	110405966	21525610
+88
+
+chain	469	X	154913754	+	76426248	76426375	8	146364022	-	18567958	18568085	6841016
+127
+
+chain	293	X	154913754	+	148716634	148716684	2	243199373	-	107635751	107635801	26436223
+50
+
+chain	50554324	X_random	1719168	+	610279	1452044	X	155270560	+	76412035	77367385	75
+7124	5	6
+4742	1	1
+31	1	1
+1606	21	28
+3800	1	1
+23	1	1
+6209	1	1
+4	1	0
+22	1	0
+13	1	0
+1193	1	1
+32	1	1
+2218	0	1
+7608	6	1
+670	0	2
+1396	0	2
+1207	20	20
+5098	1	0
+1294	1	0
+119	0	1
+6626	16	16
+8221	1	0
+3722	4	0
+169	0	4
+1754	11	13
+58	0	1
+239	1	1
+75	1	1
+910	0	1
+518	7	7
+6771	0	1
+4354	26	26
+781	1	1
+28	1	1
+406	16	16
+4353	1	0
+22	100	24
+930	1	0
+33	1	1
+1226	0	1
+1278	660	1078
+3884	2	2
+22	1	1
+2022	4	0
+2593	1	0
+777	0	3
+4596	153	64
+2593	1	10
+1074	1	0
+3147	1	0
+2227	1	0
+9697	1	0
+3957	1	0
+3098	0	186786
+22519	1	0
+204	1	0
+22	1	0
+63	17	18
+9565	0	6
+6660	129	0
+58	1	0
+17671	100	83
+39	1	1
+9798	2	1
+5	0	1
+19	100	237
+1127	0	1
+4928	133	164
+8370	115	394
+3028	259	91
+9555	100	1670
+18018	6	0
+3818	1	0
+72	1	0
+15	1	0
+11	1	0
+4	1	0
+10	100	30
+18171	0	1
+18316	0	28
+22590	0	1
+2592	2	0
+8265	0	2
+4335	4	3
+14218	100	218
+8896	0	2
+5422	18	17
+1347	4	4
+83	166	0
+5120	101	153
+3114	126	148
+4567	1	0
+2511	0	1
+1289	2	0
+3129	124	175
+5332	1	0
+20	1	0
+15993	0	4
+9940	115	1562
+10856	1	1
+18	0	1
+2379	1	1
+32	74	72
+41	1	1
+3148	155	3622
+2876	621	0
+31	1	1
+2212	81729	108028
+557	0	1
+4283	1	0
+148	0	457
+722	1	1
+49	113	176
+33	2	2
+2654	1	0
+25	188	415
+1394	12	0
+5398	0	1
+28	100	19
+5509	151745	28754
+87	102	102
+66	5	5
+53	70	72
+56	201	601
+7819	256	150
+16	0	1
+6	0	1
+8001	4	0
+8135	0	1
+528	12	0
+797	100	193
+2857	496	0
+5822	153	0
+8578	1	0
+10594	1	0
+6352	3	3
+35	6	7
+50	55655	72028
+890	0	1
+72	0	1
+2125	1	1
+64	1	0
+15	1	0
+5	22	19
+12	129	67
+11	1	0
+8	0	1
+4	1	0
+16	2	2
+3637	1	1
+36	1	0
+28	1	0
+942	0	1
+231	1	1
+109	101	336
+18	11	294
+14959	0	2
+22656	3	1
+1280
+
+chain	6857177	X_random	1719168	+	1212241	1285856	X	155270560	+	76337041	76411192	460
+53	4	4
+3247	0	6
+51	2	0
+2014	2	0
+45	4	0
+20	4	0
+48	1	0
+5158	1	1
+29	1	1
+394	16	13
+1410	1	0
+12	1	0
+14	1	0
+7	1	0
+5	1	0
+13	1	0
+36	106	188
+1195	0	31
+133	0	4
+28	1	1
+1388	1	1
+18	1	1
+2790	0	1
+767	4	4
+49	0	1
+10	110	385
+52	0	1
+56	0	1
+4004	182	11
+23	1	1
+767	1	1
+66	1	1
+3217	2	0
+25	1	1
+4309	1	0
+26	0	1
+820	2	2
+4450	0	1
+1391	1	1
+33	0	1
+31	0	8
+3634	1	0
+1669	111	432
+10524	1	2
+8620	1	0
+2158	1	0
+1513	7	7
+4600	4	4
+2111
+
+chain	5479158	X_random	1719168	+	19684	169644	X	155270560	+	3753512	3953553	578
+1162	21228	9243
+742	1	0
+2200	7659	14347
+948	1	0
+4152	211	33421
+819	48	49
+92	22	22
+544	44	42
+175	0	1
+63	102	104
+246	37	37
+203	6	5
+279	27	27
+206	54	54
+394	39	40
+260	2	0
+311	16	16
+208	57	57
+349	6	6
+262	134	134
+481	0	6
+56	1	1
+868	0	5
+1387	18095	3193
+790	8	6
+1718	0	2
+3436	13	13
+241	40033	77157
+63	10	10
+425	63	0
+38963
+
+chain	5155611	X_random	1719168	+	1349115	1404263	X	155270560	-	77841540	77897663	609
+4514	1	1
+4	1	0
+15	0	1
+1714	142	0
+26953	1	1
+31	100	192
+4795	129	41
+2612	4	0
+3389	4	0
+5037	1	1
+22	101	1223
+13	9	8
+34	2	2
+5520
+
+chain	4548442	X_random	1719168	+	595876	1601165	X	155270560	-	77827311	79038577	141
+3039	114	45
+9150	2	0
+1995	422998	109473
+19795	1	0
+23	1	0
+12	111	343
+20	5	4
+13	1	1
+2240	1980	60
+2381	1	3
+44	1	0
+37	0	1
+24	100	79
+2445	100	136
+5050	0	1
+8804	4	0
+4444	704	262
+34	2	2
+12610	100	395
+4803	1	1
+22	1	1
+4171	128	46
+569	0	1
+2902	29308	112180
+236	1	0
+659	1	0
+711	1	0
+104	0	6764
+3212	4	2485
+1198	1	0
+8224	110	1
+4	0	1
+8	0	1
+21	0	1
+23	4	4
+5939	0	1
+182	101	1162
+2127	1	0
+28	100	77
+5048	2	0
+2345	1	0
+3616	100	211
+11	10	11
+1378	0	44
+1405	0	1
+1238	0	1
+575	0	20
+9423	100	122
+20	1	1
+7723	0	1
+431	0	1
+181	2	0
+5386	16	0
+866	105	61
+1365	0	1
+11613	318206	1966
+13	1	2
+40	1	1
+781	0	2
+5976	121	213
+3371	0	1
+693	1	0
+169	2337	746790
+586	1	0
+2072	1	1
+34	1	1
+58	13	13
+211	1	1
+28	1	1
+332	1	1
+31	1	1
+179	11	0
+2785	0	5
+1418	1	0
+12774	0	1
+3561	1	0
+4305	1	1
+120	1	1
+377	1	1
+68	1	1
+208	9	9
+998	15	15
+2146	0	1
+693	101	90
+36	1	1
+1743	1	1
+18	1	1
+2412	15	15
+1943	29	30
+3136	0	3
+12327	3	4
+2517
+
+chain	4126434	X_random	1719168	+	1485975	1530227	X	155270560	+	76291305	76335950	725
+1188	0	2
+717	1	1
+34	1	1
+1032	1	1
+42	1	1
+974	1	0
+5479	16	16
+2476	1	1
+35	1	1
+1212	3	0
+152	1	1
+46	1	1
+77	7	6
+912	1	1
+38	1	1
+4230	17	17
+617	146	545
+27	3	3
+374	1	1
+18	1	1
+3639	1	1
+122	1	1
+435	4	4
+1916	16	16
+2739	1	0
+622	16	16
+6383	2	0
+2520	35	35
+5915
+
+chain	3853214	X_random	1719168	+	170863	1715347	X	155270560	-	151357158	154150181	220
+101	0	61
+11	0	2
+38	0	155
+54	0	1
+34100	0	1
+12001	158233	27287
+105	0	1
+847	4191	3311
+101	25049	633
+4294	18781	8391
+120	26	27
+1173	0	1
+2374	87	87
+206	41	40
+40	7493	0
+1552	0	1
+194	0	1
+6613	4	3
+492	13807	11516
+2651	0	2
+1724	0	2
+2453	0	1
+3866	165	10497
+2912	8	0
+2305	93	94
+6287	1	0
+3225	7	7
+393	1	1
+18	1	1
+298	495	25877
+271	0	138
+31886	6	0
+14613	3	0
+9199	1105799	2318225
+448	0	73
+215	36	2
+248	14	15
+1012	1	0
+110	1	1
+211	15	16
+87	3	0
+268	10	6
+108	12	12
+74	1	1
+27	1	1
+178	1	1
+18	1	1
+1429	0	10
+168	1	1
+36	1	1
+64	1	1
+62	0	1
+129	2	0
+80	13	10
+11	3	0
+19	823	1702
+36	1	0
+605	17	17
+193	1	0
+215	12	13
+271	1	1
+18	1	1
+91	1	0
+178	4	4
+39	1	1
+233	1	1
+31	1	1
+500	1	1
+68	1	1
+325	9	9
+244	0	1
+843	1	1
+46	1	1
+202	0	1
+957	0	1
+150	1	1
+81	1	0
+6	1	1
+303	8540	16182
+59	4	0
+415	4	7
+127	38	38
+333	0	44
+16	0	252
+226	27	26
+64	4	0
+91	0	4
+56	32	32
+977	0	16
+701	1	1
+29	1	1
+1743	1	0
+676	0	2
+2780	0	16
+85	0	11
+22	1	1
+952	3	0
+470	1	0
+840	4	0
+146	0	4
+131	0	34
+39	4	0
+99	1	1
+26	0	4
+80	1	1
+1476	0	13
+977	0	2
+480	0	800
+1133	4	5
+532	1	1
+37	1	1
+207	0	117633
+2070	1	1
+30	2	0
+524	2	0
+484	0	1
+446	1	0
+1642	2	0
+63	1	1
+43	1	1
+148	12	12
+2115	0	1
+116	1	1
+182	10	10
+88	1	1
+65	0	320
+107	0	2
+2083	295	0
+1170	10932	59997
+1792	0	1
+292	6	7
+677	8	11
+1932
+
+chain	2670012	X_random	1719168	+	22277	129533	X	155270560	-	151420019	151525192	697
+318	0	8
+1212	7792	0
+1334	4590	634
+3132	4549	4298
+403	12	12
+889	7	7
+393	20	20
+2070	17932	14002
+179	0	1
+1042	0	1
+4330	476	475
+66	0	1
+1653	797	0
+2278	8	0
+5943	18846	26826
+69	77	81
+86	822	824
+287	1	0
+7796	1771	9789
+1118	1349	0
+2572	2	0
+4177	1	0
+2904	5	0
+881	1	1
+56	6	0
+590	1	1
+23	1	1
+262	6	6
+349	1	1
+55	1	1
+208	16	16
+311	0	2
+260	1	0
+34	5	5
+394	54	54
+206	27	27
+199
+
+chain	2529127	X_random	1719168	+	1458959	1485875	X	155270560	+	77160344	77187173	1079
+634	0	1
+9184	1	0
+59	1	0
+14	100	16
+21	1	0
+53	2	2
+11087	2	0
+2487	0	2
+2602	1	0
+667
+
+chain	902700	X_random	1719168	+	269161	291745	Y	59373566	-	58967799	59197152	4215
+4053	3	0
+293	1	1
+26	0	1
+791	0	165863
+51	243	5
+66	134	1
+42	388	5
+141	0	15
+35	2	2
+42	361	0
+256	1	0
+341	3	36
+453	301	1
+147	0	1
+278	4	4
+15	0	3
+29	1	1
+122	2	0
+148	430	0
+222	151	0
+55	0	2
+149	1	0
+687	6309	50121
+61	1	1
+43	1	1
+408	80	0
+147	11	11
+228	1	1
+48	2	2
+1372	1	1
+31	1	1
+75	1	1
+28	97	0
+263	0	1
+495	98	1
+51	1	33
+52	1	1
+51	33	1
+226	1	1
+20	4	0
+211	340	0
+179	1	0
+10	1	1
+236	341	1
+555
+
+chain	569801	X_random	1719168	+	1106858	1112877	X	155270560	-	78234537	78240560	9279
+4787	0	4
+1232
+
+chain	569444	X_random	1719168	+	1452563	1458801	X	155270560	-	78136578	78142679	9342
+609	3	13
+1692	0	8
+1539	155	0
+30	3	3
+254	9	9
+1944
+
+chain	534458	X_random	1719168	+	90245	170863	X	155270560	-	151402385	151465977	943
+12303	69	69
+77	86	86
+822	66146	49119
+57	3	4
+1055
+
+chain	494413	X_random	1719168	+	391508	439759	X	155270560	-	151446976	151536655	1213
+50	57	60
+3938	36909	78166
+87	206	206
+41	40	40
+6143	240	408
+340	6	6
+194
+
+chain	379298	X_random	1719168	+	415243	419212	X	155270560	-	151507548	151511517	135808
+663	12	12
+3294
+
+chain	372919	X_random	1719168	+	1663885	1667930	X	155270560	-	153907181	153911269	141765
+802	0	3
+83	1	1
+47	1	1
+767	17	17
+1585	0	73
+215	36	2
+248	14	15
+229
+
+chain	274258	X_random	1719168	+	1667930	1671196	X	155270560	-	154066175	154070218	305212
+2034	1	281
+24	1	1
+190	0	200
+632	326	623
+58
+
+chain	267510	X_random	1719168	+	422339	428025	X	155270560	-	151460048	151465730	1055
+1034	4	3
+2317	3	0
+2328
+
+chain	266050	X_random	1719168	+	27992	75212	X	155270560	-	151430977	151495459	1091
+2648	315	25719
+644	9056	5097
+1296	30530	26348
+164	1	0
+310	1720	1720
+536
+
+chain	247472	X_random	1719168	+	49544	52383	X	155270560	+	3800594	3803433	7089
+2766	6	6
+67
+
+chain	247318	X_random	1719168	+	58807	462399	X	155270560	+	3743706	3828677	987
+48	658	658
+44	238	238
+102	246	246
+37	488	488
+27	206	206
+54	394	394
+39	797	797
+57	617	617
+134	287931	26427
+60	1338	0
+1419	8746	13247
+2214	50	50
+51	31242	578
+263	4	4
+5180	1349	0
+1121	24105	7962
+467	20820	8687
+32	2	2
+3992	2	0
+898	48	49
+92	22	22
+544	44	42
+175	0	1
+63	102	104
+246	37	37
+203	6	5
+279	27	27
+206	54	54
+394	39	40
+260	2	0
+311	16	16
+208	57	57
+349	6	6
+262	25	25
+590	57	63
+881	1017	1022
+1498
+
+chain	203629	X_random	1719168	+	419791	421950	X	155270560	-	151464996	151467156	582605
+2107	0	1
+52
+
+chain	199106	X_random	1719168	+	1699808	1701947	X	155270560	-	153935858	153937997	603481
+61	1	1
+57	1	1
+1588	4	4
+59	7	7
+361
+
+chain	199089	X_random	1719168	+	378452	380544	X	155270560	+	3796616	3798707	602253
+1586	1	0
+505
+
+chain	187776	X_random	1719168	+	376353	378301	X	155270560	+	3798256	3800203	654951
+729	1	0
+1218
+
+chain	174234	X_random	1719168	+	1285969	1288372	X	155270560	+	77019422	77021825	343560
+1763	87	87
+102	124	124
+70	56	56
+201
+
+chain	157788	X_random	1719168	+	111815	113457	X	155270560	+	3753462	3755104	810742
+1642
+
+chain	154415	X_random	1719168	+	1055747	1057376	X	155270560	+	77369279	77370908	822932
+1629
+
+chain	134293	X_random	1719168	+	1708912	1710376	X	155270560	+	1185231	1187137	959481
+129	1	1
+82	1	1
+350	2	297
+68	0	147
+831
+
+chain	132265	X_random	1719168	+	403961	405553	X	155270560	-	151477034	151478628	31377
+436	0	2
+1156
+
+chain	90853	X_random	1719168	+	1707707	1708693	X	155270560	+	1353464	1354449	1404000
+164	1	0
+46	1	1
+620	1	1
+37	1	1
+115
+
+chain	74037	X_random	1719168	+	267762	268693	Y	59373566	-	59139189	59140054	1710353
+79	97	0
+220	1	0
+317	27	60
+128	1	0
+61
+
+chain	63811	X_random	1719168	+	410390	415127	X	155270560	+	3822705	3827447	11885
+2487	0	6
+1981	48	47
+221
+
+chain	61116	X_random	1719168	+	346359	347004	X	155270560	+	3777922	3778567	2069731
+645
+
+chain	55813	X_random	1719168	+	2787	3496	X	155270560	-	151499719	151505905	2274078
+50	6	6
+412	0	5477
+241
+
+chain	38577	X_random	1719168	+	1651263	1651671	X	155270560	-	153943757	153944164	3434500
+271	1	0
+136
+
+chain	34659	X_random	1719168	+	1707297	1707664	X	155270560	+	1118849	1119216	3901406
+367
+
+chain	33830	X_random	1719168	+	267400	267758	X	155270560	-	154819600	154819959	4017435
+54	0	1
+304
+
+chain	33594	X_random	1719168	+	347004	347356	X	155270560	-	151523309	151523661	4010211
+352
+
+chain	33500	X_random	1719168	+	290273	291150	X	155270560	-	155043354	155044230	1935940
+149	427	427
+91	1	0
+137	17	17
+55
+
+chain	33229	X_random	1719168	+	1452213	1452563	X	155270560	-	78136229	78136579	3954656
+350
+
+chain	31748	X_random	1719168	+	1656832	1657169	X	155270560	-	154080972	154081310	4345014
+118	0	1
+219
+
+chain	31047	X_random	1719168	+	364702	460901	X	155270560	+	3752840	3788747	1318
+48	54	53
+80	31133	470
+26	58237	28604
+46	660	660
+40	242	241
+78	0	2
+22	248	248
+33	492	491
+25	208	208
+52	400	400
+34	798	798
+56	1232	1232
+21	1	1
+34	882	887
+1017
+
+chain	26366	X_random	1719168	+	1717468	1717765	X	155270560	-	154599490	154599787	6355797
+65	8	8
+224
+
+chain	20775	X_random	1719168	+	1657225	1657446	Y	59373566	+	1138227	1138450	9855403
+101	0	2
+120
+
+chain	20767	X_random	1719168	+	4453	4700	X	155270560	-	151332163	151332410	9860775
+174	10	10
+63
+
+chain	20271	X_random	1719168	+	1698243	1698467	X	155270560	-	154161726	154161950	2868
+224
+
+chain	20189	X_random	1719168	+	22064	22277	X	155270560	+	3752676	3752889	10232162
+213
+
+chain	20092	X_random	1719168	+	410218	414905	X	155270560	+	3784106	3788794	77876
+172	4468	4469
+47
+
+chain	19894	X_random	1719168	+	365127	367414	X	155270560	+	3744796	3747084	92469
+246	37	37
+203	5	6
+279	27	27
+206	54	54
+394	41	39
+260	0	2
+535
+
+chain	19881	X_random	1719168	+	217168	217385	X	155270560	+	3913712	3913929	10410664
+217
+
+chain	19372	X_random	1719168	+	1704190	1704597	2	243199373	+	106598364	106598785	10983407
+91	100	114
+81	74	74
+61
+
+chain	17351	X_random	1719168	+	365104	366619	X	155270560	+	3783188	3784703	560009
+23	246	246
+37	487	487
+27	206	206
+54	394	394
+41
+
+chain	16176	X_random	1719168	+	3557	21469	X	155270560	+	3768043	3793719	20345
+896	16406	24170
+326	33	33
+130	29	29
+92
+
+chain	15865	X_random	1719168	+	276938	277188	Y	59373566	-	59140528	59140772	2014767
+82	6	0
+162
+
+chain	15331	X_random	1719168	+	367414	367617	X	155270560	+	3823924	3824127	647220
+203
+
+chain	13713	X_random	1719168	+	489399	489544	X	155270560	+	3712149	3712294	16431967
+145
+
+chain	12918	X_random	1719168	+	274951	275159	Y	59373566	-	59139058	59139278	8720139
+52	0	12
+156
+
+chain	12632	X_random	1719168	+	1705530	1705970	X	155270560	+	145057484	145057926	18056495
+78	288	290
+74
+
+chain	12447	X_random	1719168	+	1030429	1030575	5	180915260	-	168461964	168462110	18325086
+146
+
+chain	12016	X_random	1719168	+	1317064	1317191	X	155270560	+	77214259	77214386	18979178
+127
+
+chain	11687	X_random	1719168	+	278072	278210	X	155270560	-	154988343	154988492	4329206
+112	25	36
+1
+
+chain	11514	X_random	1719168	+	278210	278346	Y	59373566	-	59141204	59141340	4138572
+136
+
+chain	10224	X_random	1719168	+	1704620	1704728	19	59128983	-	37939031	37939139	22329028
+108
+
+chain	10213	X_random	1719168	+	277934	278654	Y	59373566	-	59141065	59141499	2702219
+138	514	228
+68
+
+chain	9983	X_random	1719168	+	290082	290229	X	155270560	-	155043503	155043650	2501552
+48	40	40
+59
+
+chain	9686	X_random	1719168	+	1671544	1671645	X	155270560	+	1359785	1359886	23561825
+101
+
+chain	8627	X_random	1719168	+	274506	274913	X	155270560	-	154985996	154986278	9490470
+54	20	20
+32	0	8
+10	242	109
+49
+
+chain	7400	X_random	1719168	+	1030281	1030397	9	141213431	+	129760930	129761046	27439238
+59	26	26
+31
+
+chain	7194	X_random	1719168	+	274704	274779	Y	59373566	-	59139208	59139283	27842833
+75
+
+chain	7041	X_random	1719168	+	129047	129334	X	155270560	-	151486292	151486579	1717
+54	206	206
+27
+
+chain	6777	X_random	1719168	+	275159	275252	X	155270560	-	154986140	154986238	15049098
+1	37	42
+55
+
+chain	6125	X_random	1719168	+	479075	479168	X	155270560	-	151461082	151461175	898
+93
+
+chain	5720	X_random	1719168	+	1705205	1705283	3	198022430	-	36255828	36255906	21764861
+52	21	21
+5
+
+chain	5699	X_random	1719168	+	57777	57859	X	155270560	+	3747892	3747974	156364
+82
+
+chain	5684	X_random	1719168	+	275730	275789	X	155270560	-	154985991	154986050	31480070
+59
+
+chain	5671	X_random	1719168	+	278678	278737	X	155270560	-	154987944	154988003	7684992
+59
+
+chain	5648	X_random	1719168	+	288487	288546	Y	59373566	-	59194675	59194734	31602153
+59
+
+chain	5292	X_random	1719168	+	1698467	1698538	X	155270560	-	154160180	154160251	1242775
+71
+
+chain	4986	X_random	1719168	+	1705613	1705672	7	159138663	+	43857891	43857950	19004666
+59
+
+chain	4456	X_random	1719168	+	1030620	1030666	X	155270560	+	76367481	76367527	34837220
+46
+
+chain	4200	X_random	1719168	+	65786	66804	X	155270560	+	3789104	3790122	1705
+1018
+
+chain	4147	X_random	1719168	+	1704281	1704341	4	191154276	-	52750556	52750615	11058024
+1	2	1
+57
+
+chain	4142	X_random	1719168	+	276887	276938	Y	59373566	-	59140619	59140670	3855343
+51
+
+chain	3859	X_random	1719168	+	291150	291190	Y	59373566	-	59196218	59196258	16097861
+40
+
+chain	3722	X_random	1719168	+	1703633	1706063	17	81195210	-	47362086	47364493	15646977
+109	441	439
+7	1805	1784
+68
+
+chain	3009	X_random	1719168	+	1705804	1705856	X	155270560	+	62632912	62632964	24180689
+52
+
+chain	2509	X_random	1719168	+	1708877	1708912	X	155270560	+	1109247	1109282	2078841
+35
+
+chain	2078	X_random	1719168	+	1706063	1706085	1	249250621	+	114909259	114909281	21967653
+22
+
+chain	1700	X_random	1719168	+	274379	274412	Y	59373566	-	59139235	59139268	19436247
+33
+
+chain	990	X_random	1719168	+	1705283	1705342	X	155270560	+	119232530	119232589	19658805
+59
+
+chain	463	X_random	1719168	+	1703519	1703583	X	155270560	+	65440530	65440594	26501250
+64
+
+chain	2373402471	Y	57772954	+	0	27228749	Y	59373566	+	10000	28819361	24
+34821	50000	50000
+86563	30000	50000
+766173	50000	50000
+36556	50000	50000
+80121	90000	50000
+754004	100000	50000
+6846717	50000	50000
+276367	600000	50000
+813231	500000	3000000
+39401	400000	50000
+554624	100000	50000
+535761	1	0
+32919	1	0
+10	1	1
+12811	5	0
+18899	1	1
+121	5	4
+230478	1	0
+750	24	24
+14340	1	1
+43	1	1
+2095	1	0
+14635	9	0
+2781	1	0
+45022	6	5
+7151	1	0
+9343	0	628
+5417477	0	50006
+2175794	0	50000
+1481749	50000	50000
+4867933
+
+chain	46617811	Y	57772954	+	57228749	57772954	Y	59373566	+	58819361	59363566	80
+98295	50000	50000
+395910
+
diff --git a/public/chainFiles/b37tob36.chain b/public/chainFiles/b37tob36.chain
new file mode 100644
index 0000000..e808435
--- /dev/null
+++ b/public/chainFiles/b37tob36.chain
@@ -0,0 +1,12268 @@
+chain 21270171362 1 249250621 + 10000 249233096 1 247249719 + 0 247199719 2
+619	137	0
+166661	50000	50000
+40302	50000	50000
+153649	50000	50000
+1098479	1	1
+47	1	1
+73	117	114
+773	1	1
+43	1	1
+864369	2	2
+51	3	0
+104	13694	13694
+104	0	3
+51	2	2
+134936	50000	50000
+1161048	150000	60000
+1440092	27273	50000
+7590365	50000	50000
+116914	100000	50000
+237250	50000	50000
+3518496	50000	50000
+12702424	150000	50000
+16145012	0	1
+7772	1	0
+4705841	0	1
+52977198	50000	50000
+157344	21065	50000
+16604841	50000	50000
+189539	150000	50000
+398739	21050000	20290000
+195588	50000	50000
+186739	150000	50000
+175055	50000	50000
+201709	100000	50000
+126477	130183	50000
+381	0	3
+315	0	2
+62	1	1
+45	1	0
+19	0	1
+8	1	1
+1158	1	0
+314	12	13
+2849	3	0
+5615	1	1
+37	1	1
+3172	6	4
+190	1	1
+34	1	1
+380	0	1
+2099	3	0
+765	2	2
+366	0	4
+1186	1	0
+460	0	1
+1242	28	28
+574	1	1
+21	1	1
+1460	1	1
+105	1	1
+701	3	0
+239	0	1
+970	11	11
+2365	1	1
+21	1	1
+384	8	8
+996	2	0
+10383	2	0
+713	0	1
+5188	1	1
+30	1	1
+1233	1	0
+132	1	1
+44	1	1
+1123	22	22
+1810	1	0
+512	1	1
+39	1	1
+1096	0	16
+743	1	0
+9028	0	1
+2506	0	6
+8446	2	0
+5505	0	3
+7541	1	0
+109864	50000	50000
+78698	50000	50000
+127263	50000	50000
+170669	50000	50000
+38311	100000	100000
+1022394	50000	50000
+281532	289973	50000
+1648	1539	0
+76	3225	3
+1018	34	34
+1716	2	0
+159	4	0
+1600	0	6
+1385	1	0
+2066	1	1
+32	1	3
+1556908	150000	50000
+185320	150000	50000
+172789	50000	50000
+220313	50000	50000
+455185	50000	50000
+22047237	1	0
+34365824	150000	50000
+259514	150000	50000
+17265625	50000	50000
+11394365	50000	50000
+13665999	150000	50000
+174886
+
+chain 3264727 1 249250621 + 146303299 146341166 16 88827254 - 19388358 19424466 890
+577	1	1
+25	1	1
+63	19	19
+840	1	1
+60	1	1
+146	8	8
+874	1	1
+17	1	1
+386	1	1
+27	1	1
+931	1	1
+19	1	1
+200	1	1
+26	1	1
+72	1	0
+39	1	1
+107	2	1
+26	1	0
+25	1	1
+146	1	1
+45	1	1
+49	0	1
+434	0	4
+21	1	1
+572	0	2
+464	1	1
+50	1	1
+628	1	1
+48	1	1
+184	1	1
+25	1	1
+330	0	3
+308	14	14
+289	1	1
+57	1	1
+709	107	107
+247	1	1
+72	1	1
+470	1	1
+36	1	1
+353	1	0
+27	1	1
+92	12	12
+1001	1	1
+39	1	1
+650	1	1
+22	1	1
+171	1	1
+21	1	1
+88	0	9
+107	36	11
+23	0	1
+29	0	26
+20	3	79
+161	11	11
+134	1	1
+89	1	1
+547	1	1
+15	1	1
+409	1	1
+36	1	1
+376	11	10
+1545	1	0
+4	0	1
+36	1	1
+373	0	1
+326	1	1
+42	17	0
+97	1	0
+187	2	0
+503	1	1
+57	1	1
+443	1	1
+35	1	1
+633	1	0
+2044	3	13
+299	1	1
+37	1	1
+1159	1	1
+39	1	1
+124	1	1
+74	1	1
+103	1	1
+55	1	1
+280	10	9
+474	0	1
+382	1	1
+31	1	1
+1812	1	1
+76	1681	0
+25	1	1
+145	1	1
+18	1	1
+1228	1	1
+31	1	1
+126	9	9
+186	2	0
+142	1	1
+25	1	0
+442	10	0
+339	0	1
+89	1	1
+21	2	0
+21	151	4
+15	1	1
+489	9	9
+311	1	1
+75	1	1
+75	1	0
+124	1	1
+114	1	1
+23	1	1
+1489	0	3
+391	1	0
+2141	10	10
+460	11	11
+422	1	1
+30	1	1
+296	8	8
+638	1	1
+38	1	1
+341
+
+chain 2374970 1 249250621 + 146214652 146460889 1 247249719 - 102316553 102503720 74
+488	1	1
+24	1	1
+971	6293	0
+994	2	0
+183	2	0
+1408	1	0
+1360	1541	0
+211	0	12
+1506	111528	93105
+421	5	6
+2973	8	8
+118	12	12
+157	10	10
+706	0	18
+26	2884	0
+127	4	1
+1518	1	1
+33	1	1
+934	9	9
+908	0	1
+126	1	0
+695	20	20
+2250	5	5
+1662	179	172
+975	1	1
+53	1	1
+62	2	2
+40	1	1
+1561	1	1
+34	1	1
+668	1	0
+1671	2	0
+480	1	1
+17	4	4
+103	0	1
+50	6	6
+230	1	1
+71	1	1
+139	1	0
+975	5	0
+180	1	1
+37	1	1
+1888	3	2
+1101	1	0
+354	64	9327
+654	1	1
+36	1	1
+888	0	2
+18	1	1
+74	1	1
+25	1	1
+81	2	0
+779	1	1
+41	0	12
+22	1	1
+436	1	6
+293	1	1
+31	1	1
+83	4	0
+694	1	1
+42	1	1
+913	0	9
+472	0	1
+253	12	12
+148	89	1
+41	89	1
+342	1	1
+72	1	1
+97	1	1
+41	1	1
+108	13	16
+280	12	12
+61	1	1
+30	0	1
+71	1	1
+42	2	2
+139	0	3
+85	5	5
+90	1	1
+39	0	1
+366	13	14
+332	0	3744
+123	1	1
+19	1	1
+264	2	0
+47	1	1
+381	3	5
+109	0	1
+521	0	1
+503	1	1
+42	0	1
+739	1	1
+77	1	1
+883	0	2
+220	0	3
+93	4	0
+12	4	0
+39	5	0
+91	1	1
+34	1	1
+562	1	1
+30	1	1
+660	13	0
+1172	16	16
+69	1	1
+32	1	1
+310	1	1
+33	1	1
+97	0	1
+38	1	1
+295	0	2
+499	1	1
+57	31	14
+607	10	10
+145	1	1
+101	1	1
+346	1	1
+30	1	1
+74	1	1
+16	1	1
+203	1	1
+36	12	0
+483	16	0
+977	1	1
+86	1	1
+66	1	1
+35	1	1
+692	16	13
+402	34	34
+287	0	5
+523	0	18
+350	4	0
+32	0	2
+108	39	45
+66	30	0
+969	0	5
+1749	5	5
+95	2	0
+5	1	0
+4	0	1
+79	0	2
+65	8	11
+63	1	1
+49	1	1
+1381	0	1
+870	17	0
+139	1	1
+89	1	1
+270	3	3
+97	1	1
+66	1	1
+50	1	1
+126	1	0
+182	1	1
+83	0	4
+125	1	1
+35	1	1
+263	1	1
+32	4	4
+202	1	0
+94	1	1
+46	1	1
+206	1	1
+56	1	1
+50	1	1
+49	1	1
+188	16	16
+589	1	1
+38	1	1
+178	0	4
+67	1	1
+421	51	0
+117	1	1
+36	1	1
+71	1	1
+74	1	1
+68	10	10
+131	3	3
+56	1	0
+52	1	1
+207	4	4
+30	1	1
+283	14	14
+93	0	4
+66	1	1
+89	7	5
+36	1	1
+79	1	1
+46	21	0
+99	1	1
+229	10	10
+100	5	0
+19	8	8
+78	1	1
+87	1	1
+125	5	5
+65	1	1
+74	3	3
+344	1	1
+24	1	1
+683	1	1
+43	6287	0
+250	15	15
+798	13	12
+267	2	1
+881	1	0
+374	10	10
+1237	1	1
+40	1	1
+620	1	1
+43	1	1
+1491	1	1
+28	1	1
+68	5	5
+413	1	2
+183	5	5
+42	1	1
+363	1	1
+26	23	0
+53	1	0
+1011	15	15
+173	4	4
+15	1	1
+801	4	4
+1197	0	10
+432	22154	19
+283	4702	22
+850	9524	0
+78	76	76
+568	10	10
+775	40	32
+274	4	0
+1120	17	17
+195
+
+chain 990444 1 249250621 + 2485433 2499127 1 247249719 - 244760735 244774429 1366
+13694
+
+chain 614409 1 249250621 + 249233096 249240448 21 46944323 + 46937133 46944296 2013
+2867	16	16
+420	9	9
+176	0	1
+1252	6	0
+1275	1	1
+25	0	344
+76	0	58
+545	484	7
+40	109	0
+51
+
+chain 498595 1 249250621 + 146216137 146242853 1 247249719 - 104315183 104389677 383
+30	657	657
+196	19	18
+134	27	27
+445	20	20
+101	9	9
+169	62	62
+116	10	10
+70	62	62
+54	26	26
+70	0	22267
+240	1539	0
+91	20	24
+246	22	22
+270	112	112
+118	143	143
+86	24	24
+184	81	81
+67	47	46
+110	83	95
+335	59	59
+139	4179	2633
+241	27	27
+273	109	109
+185	76	76
+86	24	24
+184	81	81
+26	1717	1732
+80	85	53
+151	37	37
+99	37	37
+113	20	20
+101	9	9
+169	62	62
+89	37	37
+70	62	62
+54	33	33
+382	279	5055
+291	112	112
+125	147	147
+256	382	24225
+58	106	106
+51	29	29
+422	19	19
+221	84	84
+156	29	29
+162	33	33
+80	4	4
+79	11	11
+209	29	29
+183	34	34
+116	44	44
+122	5	5
+554	41	41
+140	8	8
+161	0	1
+67	58	51
+138	10	10
+246	60	60
+124	59	60
+101	138	138
+109	161	161
+56	31	28
+163	74	74
+136	7	7
+303	34	34
+119	10	10
+339	30	30
+141	91	91
+222	107	93
+237	205	205
+134	49	49
+87	22	22
+128	87	87
+105	33	33
+52	58	58
+52	87	87
+198	158	162
+125	44	44
+82	42	42
+54	10	9
+72	27	27
+154	18	18
+186	39	39
+61	87	86
+71	38	38
+116	43	43
+268	50	50
+58	120	120
+152
+
+chain 376931 1 249250621 + 143880003 143901185 1 247249719 - 126576077 126597249 122
+127	70	71
+181	31	31
+3325	1	1
+49	1	1
+820	1	1
+75	1	1
+393	1	1
+21	1	1
+2956	3	0
+232	0	5
+77	4	4
+531	1	1
+42	5	3
+183	1	1
+19	1	1
+644	1	1
+25	1	1
+701	1	1
+21	1	1
+954	1	1
+31	1	1
+129	24	14
+650	1	1
+25	1	1
+560	0	2
+1372	1	1
+46	1	1
+1547	3	1
+883	1	0
+22	1	1
+818	1	1
+30	1	1
+1231	1	1
+34	1	1
+1758	1	1
+35	1	1
+468
+
+chain 360128 1 249250621 + 146427813 146438983 1 247249719 + 144926007 144932406 9045
+138	252	252
+1258	1540	0
+76	3256	30
+81	283	283
+87	185	185
+109	273	273
+7	19	19
+155	43	43
+91	1	0
+1185	11	11
+212	2	0
+158	2	0
+1336	64	64
+346
+
+chain 260187 1 249250621 + 146226436 146443808 1 247249719 - 100391956 100589719 716
+173	5526	775
+60	400	391
+120	18	17
+164	81	83
+26	45	45
+35	1589	1589
+29	2518	2516
+7	17	17
+56	30	30
+51	56	53
+31	163	163
+74	446	446
+34	468	468
+30	141	141
+33	624	609
+8	133	133
+64	134	134
+49	237	237
+71	316	316
+58	1199	1203
+39	219	219
+38	6697	424
+97	18	18
+77	219	219
+114	64	64
+138	183	187
+118	99	99
+89	25	31
+69	24	24
+100	30	30
+69	49	49
+54	125	125
+182	197	197
+107	156930	137139
+140	175	171
+75	164	162
+157	49	49
+69	45	45
+61	48	48
+51	61	60
+71	70	70
+108	10955	10956
+84	24	24
+75	87	87
+185	109	109
+273	22	22
+246	20	24
+49	494	19550
+70	10	10
+116	62	9592
+169	9	9
+324	83	83
+151	87	77
+90	22	22
+196	68	68
+95	5	5
+57	71	71
+196	17	17
+75	73	73
+563	83	87
+110	1555	14
+45	7990	0
+54	81	81
+184	24	24
+75	87	87
+185	109	109
+273	3222	27
+64	1605	35
+142	1567	44
+37	1539	0
+281
+
+chain 257136 1 249250621 + 146423276 146434218 1 247249719 + 144926235 144932406 9046
+68	157	157
+71	288	288
+73	563	563
+83	4962	196
+1052	19	19
+155	43	43
+91	1	0
+99	76	76
+1010	11	11
+212	2	0
+158	2	0
+1746
+
+chain 252664 1 249250621 + 146424776 146427813 1 247249719 + 144927734 144930766 96654
+1055	16	16
+124	74	74
+74	224	223
+979	11	11
+212	2	0
+158	2	0
+106
+
+chain 244411 1 249250621 + 146449863 146457732 1 247249719 + 144926007 144929115 8960
+1648	1539	0
+76	3225	3
+265	45	45
+708	34	34
+329
+
+chain 149837 1 249250621 + 146221841 146454623 1 247249719 + 146043049 146859300 923
+56	335	335
+59	4859	3299
+109	185	185
+76	5018	258
+57	409	426
+45	777	777
+84	1850	1850
+41	841	820
+47	125	126
+58	101	101
+138	2026	2026
+51	4	2
+52	297	297
+81	786	786
+33	347	347
+90	23	23
+35	125	125
+44	82	81
+42	634	634
+74	225	224
+43	268	267
+50	58	58
+120	152	152
+515	62	62
+68	41	41
+432	0	18
+180	46	46
+67	26	28
+192	26	26
+231	107	107
+67	72	67
+53	67	67
+151	171	168
+59	46	47
+86	57	54
+51	138	138
+397	18	18
+114	3	2
+182	20	20
+86	167	167
+51	48	48
+233	42	42
+89	55	55
+163	43	44
+112	70	70
+355	154	154
+174	157	641342
+145	228	228
+152	366	366
+64	1134	1135
+35	269	265
+46	15	14
+137	8	8
+70	11	11
+73	29	29
+55	63	63
+62	262	247
+77	100	100
+155	39	39
+215	72	72
+178	20	20
+64	13	13
+123	12	12
+124	127	127
+100	135495	128258
+34	14433	8189
+138	64	64
+114	219	219
+77	19	19
+96	17464	11155
+185	22232	98
+69	26	26
+54	62	62
+70	10	10
+116	62	62
+169	32	32
+211	37	37
+99	9482	37
+161	23	13
+130
+
+chain 121346 1 249250621 + 146403114 146428203 1 247249719 - 230466401 230485108 1747
+70	156	156
+17	25	25
+22	146	146
+152	249	249
+94	2285	2290
+63	34	34
+79	80	80
+89	48	42
+85	127	127
+68	502	495
+87	61	61
+136	127	126
+4	272	272
+43	396	396
+49	175	175
+48	183	187
+40	11298	11284
+59	5488	723
+50	98	104
+107	63	63
+54	1608	4
+83	9	9
+160
+
+chain 97594 1 249250621 + 146218654 146221704 1 247249719 - 102320562 102322071 123803
+154	24	24
+174	6	6
+1045	1614	73
+33
+
+chain 76810 1 249250621 + 146441138 146441951 1 247249719 - 102499725 102500538 1571454
+813
+
+chain 54094 1 249250621 + 146439071 146449863 1 247249719 + 144927734 144930766 9063
+156	32	32
+864	3151	76
+253	432	432
+62	196	196
+62	169	169
+32	211	211
+37	99	99
+87	4753	70
+88	2	0
+106
+
+chain 51170 1 249250621 + 146420674 146422968 1 247249719 + 144928397 144930686 91522
+82	822	821
+37	60	60
+212	196	196
+62	502	502
+83	151	149
+59	2	0
+26
+
+chain 47243 1 249250621 + 146249630 146253102 1 247249719 + 146058248 146061700 347899
+23	176	176
+41	89	89
+25	420	420
+79	245	245
+20	78	78
+29	495	490
+29	72	72
+46	158	145
+143	628	627
+53	534	533
+17	5	5
+67
+
+chain 34253 1 249250621 + 146404045 146461111 1 247249719 - 100757623 100773572 2307
+96	91	95
+87	237	237
+54	39	39
+166	170	170
+93	270	264
+54	177	172
+56	15121	8830
+27	23096	966
+26	9686	241
+71	62	62
+168	10	10
+112	7057	3813
+40
+
+chain 33489 1 249250621 + 146442066 146462163 1 247249719 + 144023055 144028915 8758
+86	162	162
+20	322	322
+153	82	82
+116	7	7
+260	4934	262
+352	142	142
+79	60	60
+57	99	99
+135	6	6
+234	31	31
+264	6949	535
+45	4229	1077
+134	1105	1106
+34
+
+chain 33218 1 249250621 + 146446746 146453724 1 247249719 + 144927655 144929867 162700
+76	4	3
+532	5285	520
+407	76	76
+465	71	71
+62
+
+chain 32794 1 249250621 + 146404432 146406255 1 247249719 - 230461418 230463242 176920
+104	280	280
+90	172	172
+62	25	26
+120	135	135
+128	18	18
+13	515	515
+161
+
+chain 26745 1 249250621 + 146451818 146452101 1 247249719 - 102499420 102499703 6165314
+283
+
+chain 22423 1 249250621 + 146216204 146248536 1 247249719 + 146043705 146710884 2213
+65	5	5
+58	95	95
+44	58	58
+67	1348	1339
+20	10	10
+32	196	196
+62	2594	1055
+96	153	153
+108	10232	605314
+55	16610	57923
+59	315	315
+50
+
+chain 21816 1 249250621 + 146442152 146442891 1 247249719 + 144927740 144928479 1347746
+148	509	509
+82
+
+chain 20351 1 249250621 + 146356780 146459279 1 247249719 - 101132456 101205064 466
+178	42398	55179
+51	39820	14441
+32	3075	0
+39	16869	2651
+37
+
+chain 17175 1 249250621 + 249240118 249240599 1 247249719 - 247249264 247249719 6645750
+53	7	10
+47	109	0
+21	6	0
+36	51	102
+5	22	73
+56	16	0
+52
+
+chain 16391 1 249250621 + 146446357 146448997 1 247249719 + 144928805 144929904 1203759
+155	2048	507
+109	112	112
+60	57	57
+99
+
+chain 14917 1 249250621 + 146407068 146408474 1 247249719 + 144010187 144011603 12383
+76	149	159
+73	240	240
+47	136	136
+39	587	587
+59
+
+chain 14732 1 249250621 + 104074421 104074580 20 62435964 - 41767962 41768121 15357748
+159
+
+chain 13179 1 249250621 + 146404319 146408384 1 247249719 + 146846894 147006750 8455
+113	104	104
+20	54	54
+39	1744	1736
+34	1903	157702
+54
+
+chain 12360 1 249250621 + 146216167 146250305 1 247249719 - 103194351 103244298 1211
+37	128	128
+95	44	44
+58	67	67
+60	5	5
+51	3345	6525
+128	0	9435
+8	6200	4617
+43	3518	3485
+37	13507	18215
+40	613	636
+46	716	718
+72	53	53
+30	240	240
+72	1522	1531
+48	233	233
+42	89	89
+36	14	14
+5	804	801
+66	696	696
+34	1307	1378
+29
+
+chain 11952 1 249250621 + 146445104 146445575 1 247249719 - 100776503 100776974 637661
+94	18	18
+359
+
+chain 11854 1 249250621 + 146229744 146232010 1 247249719 + 144747607 144749863 153009
+21	19	9
+19	736	736
+20	10	10
+32	196	196
+62	54	54
+33	556	556
+43	383	383
+82
+
+chain 10753 1 249250621 + 146408065 146408192 1 247249719 - 101190210 101190337 3832842
+127
+
+chain 10394 1 249250621 + 104091245 104091359 5 180857866 + 153305659 153305773 21933263
+114
+
+chain 10333 1 249250621 + 104091131 104091240 X 154913754 + 74963065 74963174 22062861
+109
+
+chain 9815 1 249250621 + 146403058 146404974 1 247249719 - 101191494 101193412 750328
+43	256	256
+25	136	136
+32	152	152
+35	1179	1181
+58
+
+chain 9804 1 249250621 + 146245618 146249581 1 247249719 + 16785678 16789645 248382
+32	19	19
+6	51	51
+11	80	80
+47	3688	3692
+29
+
+chain 8504 1 249250621 + 146408954 146409155 1 247249719 - 101191099 101191300 2114480
+61	111	111
+29
+
+chain 8318 1 249250621 + 146407418 146407505 1 247249719 - 102486621 102486708 14753827
+87
+
+chain 7171 1 249250621 + 1619987 1620086 1 247249719 + 1662789 1662888 1670813
+99
+
+chain 7168 1 249250621 + 146247532 146247756 1 247249719 + 144759088 144759312 2272140
+43	123	123
+58
+
+chain 6908 1 249250621 + 146440123 146445030 1 247249719 - 101203201 101205034 129817
+119	142	142
+69	4461	1387
+116
+
+chain 6650 1 249250621 + 146406255 146406330 1 247249719 - 101188413 101188487 10133477
+21	3	2
+51
+
+chain 6566 1 249250621 + 146445881 146445977 1 247249719 + 144059904 144060000 2107997
+23	21	21
+52
+
+chain 6380 1 249250621 + 10629 10716 Y 57772954 - 1612 1699 6955
+87
+
+chain 5940 1 249250621 + 146231384 146231447 1 247249719 - 102320696 102320759 393064
+63
+
+chain 5684 1 249250621 + 146407187 146407246 1 247249719 - 101189341 101189400 31412390
+59
+
+chain 5266 1 249250621 + 249240022 249240077 1 247249719 - 247249582 247249637 32667083
+55
+
+chain 5203 1 249250621 + 146446237 146446668 1 247249719 - 102500144 102500575 1674615
+120	155	155
+156
+
+chain 4958 1 249250621 + 146451766 146451818 1 247249719 + 142879884 142879936 20619966
+52
+
+chain 4944 1 249250621 + 104074593 104074659 8 146274826 - 121738108 121738174 21132898
+66
+
+chain 4456 1 249250621 + 146406808 146406855 1 247249719 - 101188965 101189012 6127414
+47
+
+chain 4404 1 249250621 + 146406008 146406074 1 247249719 - 100540708 100540774 1844606
+66
+
+chain 4255 1 249250621 + 146230090 146231384 1 247249719 - 103181490 103211127 6721
+37	1201	29544
+56
+
+chain 4244 1 249250621 + 146216712 146216757 1 247249719 - 102323372 102323417 831523
+45
+
+chain 4123 1 249250621 + 146421615 146421675 1 247249719 + 143536766 143536826 34723
+60
+
+chain 3877 1 249250621 + 146435532 146435575 1 247249719 - 101203375 101203418 141544
+43
+
+chain 3825 1 249250621 + 146430767 146430810 1 247249719 - 101203375 101203418 118474
+43
+
+chain 3528 1 249250621 + 146454014 146454173 1 247249719 - 100628659 100628818 205230
+159
+
+chain 3185 1 249250621 + 146406525 146406559 1 247249719 - 101188682 101188716 16359386
+34
+
+chain 3178 1 249250621 + 104074770 104074842 7 158821424 + 21042162 21042234 21615733
+72
+
+chain 3121 1 249250621 + 146445079 146445768 1 247249719 + 144930661 144931350 792159
+25	471	471
+193
+
+chain 3050 1 249250621 + 146407036 146407068 1 247249719 - 101189190 101189222 23011976
+32
+
+chain 2960 1 249250621 + 146249122 146249154 1 247249719 + 144760680 144760712 1406096
+32
+
+chain 2741 1 249250621 + 146231545 146231601 1 247249719 - 104345036 104345092 8679
+56
+
+chain 2464 1 249250621 + 146424736 146424776 1 247249719 + 144037261 144037301 21508852
+40
+
+chain 2405 1 249250621 + 249239910 249239972 1 247249719 - 247249327 247249389 7681464
+62
+
+chain 2390 1 249250621 + 249240288 249240334 1 247249719 - 247249596 247249642 26481552
+46
+
+chain 2344 1 249250621 + 146216757 146250883 1 247249719 - 103711249 103726499 1396
+67	32948	14063
+57	892	901
+7	127	127
+28
+
+chain 2164 1 249250621 + 146237300 146252192 1 247249719 + 16771061 16779662 20592
+30	14825	8534
+37
+
+chain 1926 1 249250621 + 10623 10756 15 100338915 - 932 978 361
+6	87	0
+40
+
+chain 1909 1 249250621 + 146251590 146251644 1 247249719 - 103917507 103917561 1304306
+54
+
+chain 1317 1 249250621 + 146445768 146445881 1 247249719 + 142919887 142920000 1148922
+113
+
+chain 1215 1 249250621 + 146245082 146245105 1 247249719 + 144762924 144762947 79987
+23
+
+chain 1154 1 249250621 + 146232196 146232260 1 247249719 + 16765963 16766027 137025
+64
+
+chain 1035 1 249250621 + 146367698 146367747 1 247249719 - 99837677 99837726 4094688
+49
+
+chain 827 1 249250621 + 146445037 146445075 1 247249719 - 102502075 102502113 153232
+38
+
+chain 691 1 249250621 + 146454173 146454226 1 247249719 - 100557283 100557336 435331
+53
+
+chain 604 1 249250621 + 146429501 146429541 1 247249719 + 147018285 147018325 1335641
+40
+
+chain 424 1 249250621 + 146449372 146449403 1 247249719 - 100776122 100776153 793932
+31
+
+chain 395 1 249250621 + 146448669 146448702 1 247249719 + 144078479 144078512 164120
+33
+
+chain 88 1 249250621 + 146452351 146452395 1 247249719 - 99890656 99890700 12702616
+44
+
+chain 71 1 249250621 + 146451564 146451618 1 247249719 - 102499166 102499220 29039078
+54
+
+chain 12431961244 10 135534747 + 60000 135524747 10 135374737 + 50000 135374737 10
+5577104	0	50006
+12337571	50000	50000
+20794160	50000	50000
+286100	3200000	2480000
+191752	50000	50000
+3830277	50000	150000
+952205	100000	150000
+263307	100000	150000
+163231	50000	150000
+989829	100000	150000
+1941874	50000	50000
+211435	50000	50000
+30112515	0	319974
+13249156	0	10
+31058956	50000	50000
+2696597	150000	50000
+4615335	50000	10000
+246123	50000	50000
+1327328	1	1
+47	1	1
+1312	0	1
+56	1	1
+190	1	1
+31	1	1
+20182	1	0
+448068
+
+chain 12415603391 11 135006516 + 60000 134946516 11 134452384 + 50000 134451988 11
+1102759	50000	16576
+49571094	307000	207000
+503352	3100000	3000000
+14395596	47395	0
+491076	304	60
+30213	182	114
+26	142	1
+27914	0	1
+20009	0	1
+19	0	1
+39	0	1
+17	1	3
+10	0	1
+1008	0	1
+95	0	1
+5126	0	15
+303	0	1
+975	4	0
+1548	1	0
+191	0	20
+40	0	1
+74	1	0
+101	0	1
+25	1	0
+6178	1	0
+1875	52561	21437
+468	1	1
+81	1	1
+2620	0	1
+1640	0	4
+3305	1	0
+3342	0	1
+17899663	50000	12000
+8549206	150000	15562
+38507167	37	39
+1282	0	174
+387	0	86
+59
+
+chain 12330185447 12 133851895 + 145739 133779461 12 132349534 + 16000 132289534 12
+7035084	4	0
+543	1	0
+3777	1	0
+3889	52114	73000
+6014	0	1
+6524	5	126
+29	0	13
+20974	2	0
+3965	0	3
+444	11	0
+464	0	1
+27577110	3000000	1395000
+38631945	1	0
+14544	4	0
+1700	0	1
+789	12128	250000
+1783	0	1
+1075	2	0
+1042	0	1
+1526	1	1
+27	1	1
+2320	1	0
+166	0	1
+564	1	0
+2856	2	0
+900	1	0
+1387	1	1
+33	1	1
+2139	1	1
+48	1	1
+1305	2	0
+1533	2	1
+879	1	0
+744	26	26
+858	4	0
+1089	0	6
+1113	0	12
+818	1	1
+18	0	1
+217	1	1
+36	1	1
+2002	0	1
+1025	1	0
+450	48	48
+916	0	1
+18	1	1
+4694	8	0
+142	0	4
+3656	0	2
+3403	1	1
+47	1	1
+1524	1	1
+28	1	1
+5560	48	45
+676	8	8
+810	16	16
+536	0	2
+236	0	4
+167	4	0
+1419	53	49
+4688	1	1
+38	1	1
+18576	0	5
+5285	2	0
+6486	1	1
+25	1	1
+4341	14	0
+2662	0	5
+1170	0	1
+4268	4	0
+1036	1	0
+2117	8	0
+5917	0	1
+3239	4	0
+2619	1	1
+21	1	1
+937	1	1
+38	1	1
+2412	124	139
+2648	2	0
+9314	0	2
+1986	2	2
+16	1	1
+229	1	1
+93	1	1
+895	0	12
+415	5	1
+119	1	1
+185	9	8
+458	2	0
+89	1	1
+42	1	1
+2034	1	0
+1545	2	0
+280	4	0
+97	14	14
+231	2	0
+2814	0	5
+1679	1	1
+27	1	1
+25758689	1	0
+6536665	1	0
+377270	96749	57000
+668	1	1
+20	0	1
+3348	1	1
+33	1	1
+648	1	1
+29	1	1
+3731	0	4
+1834	9	14
+1688	10	0
+3103	5	5
+1140	0	1
+1167	0	1
+985	9	9
+2897	0	1
+1625	0	9
+1101	1	0
+1358	8	0
+13065721	68352	150000
+810	0	2
+343	1	0
+1771	1	0
+2702	6	7
+1900	0	1
+705	0	6
+303	0	1
+727	1	1
+43	3	6
+490	1	1
+59	1	1
+226	1	1
+52	0	3
+465	8	0
+194	1	1
+25	0	1
+139	17	17
+1833	0	1
+81	1	1
+39	1	1
+453	0	1
+719	1	1
+47	1	1
+558	0	1
+838	1	8
+288	9	10
+741	2	5
+465	1	1
+48	1	1
+268	1	1
+26	0	1
+1337	17	0
+12	2	1
+16	1	1
+84	85	2
+917	0	1
+110	1	1
+29	1	1
+1580	1	1
+40	1	1
+683	1	1
+24	1	1
+247	1	1
+36	1	1
+1411	14	14
+149	1	0
+10091386	3	0
+296	5	0
+220	100872	45000
+972469
+
+chain 2067120 12 133851895 + 60245 88108 2 242951149 + 114046160 114069967 1234
+334	1	1
+47	1	1
+111	1	1
+20	0	13
+84	1	1
+84	7	15
+55	1	1
+28	1	1
+77	1	1
+49	1	1
+99	10	10
+345	1	1
+48	0	4
+16	2	2
+168	1	1
+160	1	1
+68	1	0
+62	1	1
+23	1	1
+144	7	7
+94	2128	0
+762	12	12
+305	1	1
+40	1	1
+385	196	196
+207	0	1
+267	1	1
+53	1	1
+58	0	12
+43	1	1
+55	4	4
+38	1	0
+361	1	0
+53	1	1
+27	1	1
+448	1	1
+18	1	1
+309	4	0
+104	1	1
+35	1	1
+394	1	1
+16	1	1
+159	1	1
+38	1	1
+413	14	14
+82	5	7
+699	0	1
+52	23	24
+1077	9	9
+492	1	0
+144	18	19
+69	1	1
+26	1	1
+689	2	0
+34	5	6
+34	1	1
+187	1	1
+65	1	1
+181	9	9
+82	1	1
+55	0	2
+310	1	1
+25	1	1
+71	1	1
+74	3	3
+64	6	6
+216	5	5
+62	1	1
+35	8	3
+803	1	0
+23	1	1
+124	1	1
+90	1	1
+300	4	0
+48	0	4
+28	1	0
+85	7	4
+63	2	0
+7	3	0
+49	1	1
+255	31	31
+462	1	1
+38	1	1
+414	1	1
+37	1	1
+304	1	1
+36	1	1
+119	16	19
+62	1	1
+26	1	1
+306	1	1
+93	1	1
+114	1	1
+141	1	1
+464	1	1
+25	1	1
+145	1	1
+21	1	1
+196	1	1
+46	1	1
+295	11	11
+255	1	1
+21	1	1
+280	1	1
+90	1	1
+413	8	8
+1039	24	24
+761	1	0
+53	1	1
+94	1	0
+25	1	1
+63	1	1
+71	2070	1
+21	2	47
+228	3	0
+17	1	1
+133	11	0
+137	1	1
+43	1	1
+90	3	3
+23	2	0
+144	1	1
+99	1	1
+349	3	3
+29	5	5
+60	0	70
+93	1	1
+21	1	1
+138	0	2
+83	1	1
+68	1	1
+166	1	1
+49	1	1
+461	1	1
+18	0	17
+26	1	1
+50	1	1
+14	0	1
+34	1	1
+370	1	1
+32	1	1
+68	14	14
+98
+
+chain 484774 12 133851895 + 88108 95739 X 154913754 + 154905409 154913416 8417
+2	1	1
+34	1	1
+80	1	1
+32	1	1
+415	1	1
+48	1	1
+73	1	1
+44	1	1
+149	13	13
+211	1	1
+26	1	1
+271	0	3
+528	1	1
+96	1	1
+507	1	1
+100	1	1
+121	37	37
+520	1	1
+34	1	1
+166	1	1
+45	1	1
+96	1	1
+87	1	1
+82	4	4
+71	1	1
+34	1	1
+132	1	1
+23	1	1
+97	1	1
+30	2	2
+109	3	3
+36	1	1
+134	2135	2017
+245	454	1029
+82	84	0
+113
+
+chain 233388 12 133851895 + 133837240 133840071 7 158821424 + 158817351 158819960 454901
+564	1	1
+52	1	0
+36	1	1
+470	1	1
+28	1	1
+359	1	1
+38	1	1
+130	5	0
+3	216	0
+97	3	2
+46	1	1
+559	1	1
+43	0	1
+78	1	1
+94
+
+chain 194103 12 133851895 + 62428 64518 14 106368585 + 64430621 64433205 634790
+748	40	40
+140	0	1
+167	0	373
+27	0	120
+968
+
+chain 49263 12 133851895 + 133825767 133827148 11 134452384 + 74280352 74281733 2582033
+188	22	24
+55	110	110
+117	297	297
+62	252	253
+116	101	98
+61
+
+chain 35717 12 133851895 + 133841521 133841895 5 180857866 - 180793287 180793661 3746803
+374
+
+chain 32957 12 133851895 + 133823831 133824928 X 154913754 - 110744397 110745491 4131553
+102	47	47
+104	308	309
+61	155	155
+59	173	169
+88
+
+chain 18331 12 133851895 + 133822513 133823307 7 158821424 + 35158939 35159735 11829157
+110	151	152
+60	413	414
+60
+
+chain 16856 12 133851895 + 66036 76221 19 63811651 - 63781390 63791585 1292
+70	1	1
+57	16	16
+51	9959	9969
+31
+
+chain 16157 12 133851895 + 109428208 109428485 2 242951149 - 225002676 225002954 13880737
+71	91	92
+115
+
+chain 11750 12 133851895 + 60000 60122 12 132349534 - 132324140 132324262 19413804
+122
+
+chain 9037 12 133851895 + 133826997 133827421 2 242951149 + 160701141 160701565 3717783
+90	61	61
+34	175	175
+64
+
+chain 8057 12 133851895 + 133826086 133826759 3 199501827 - 98694913 98695583 3241421
+56	127	126
+50	305	303
+135
+
+chain 4873 12 133851895 + 133822983 133823177 6 170899992 + 146924403 146924597 15743780
+57	73	73
+64
+
+chain 4427 12 133851895 + 133827536 133827658 3 199501827 - 37386916 37387038 7696734
+122
+
+chain 4266 12 133851895 + 109428325 109428370 8 146274826 + 102422247 102422292 23131068
+45
+
+chain 4036 12 133851895 + 133826320 133826456 X 154913754 + 144352164 144352300 4124454
+136
+
+chain 3880 12 133851895 + 95312 95362 1 247249719 - 247249339 247249389 25961870
+50
+
+chain 3693 12 133851895 + 63176 63216 6 170899992 - 141104715 141104755 640206
+40
+
+chain 3673 12 133851895 + 133827423 133827506 2 242951149 - 104106513 104106596 10382380
+83
+
+chain 3091 12 133851895 + 133826496 133826821 11 134452384 - 91473718 91474043 4183905
+58	205	205
+62
+
+chain 3057 12 133851895 + 133822699 133822767 2 242951149 + 211079534 211079602 19980130
+68
+
+chain 2758 12 133851895 + 133827507 133827536 3 199501827 - 112531647 112531676 15775673
+29
+
+chain 2377 12 133851895 + 133825725 133826065 1 247249719 + 157351310 157351652 3309912
+42	265	267
+33
+
+chain 2375 12 133851895 + 95368 95419 1 247249719 - 247249256 247249307 12772530
+51
+
+chain 2223 12 133851895 + 133827262 133827357 6 170899992 + 81976496 81976591 4176034
+95
+
+chain 2091 12 133851895 + 109428279 109428301 20 62435964 + 39979396 39979418 21613404
+22
+
+chain 1955 12 133851895 + 133822880 133822953 4 191273063 - 60412182 60412255 19166211
+73
+
+chain 1569 12 133851895 + 133823330 133823447 5 180857866 + 90128366 90128483 9408356
+117
+
+chain 1532 12 133851895 + 133822199 133822253 12 132349534 + 77527067 77527121 12101346
+54
+
+chain 1265 12 133851895 + 133825609 133825680 2 242951149 + 183532658 183532729 7750866
+71
+
+chain 1251 12 133851895 + 95185 95235 18 76117153 - 76117025 76117075 24929113
+50
+
+chain 1165 12 133851895 + 133826456 133826496 X 154913754 - 53085075 53085115 5993397
+40
+
+chain 1153 12 133851895 + 133824667 133824711 10 135374737 - 97414674 97414718 8388000
+44
+
+chain 852 12 133851895 + 133822443 133822508 5 180857866 + 49699275 49699340 23831787
+65
+
+chain 636 12 133851895 + 133823040 133823067 6 170899992 + 127619395 127619422 20859432
+27
+
+chain 615 12 133851895 + 133823498 133823556 14 106368585 - 76653675 76653733 3589163
+58
+
+chain 440 12 133851895 + 133827198 133827224 1 247249719 - 50786620 50786646 7302157
+26
+
+chain 9007882413 13 115169878 + 19020000 115109878 13 114142980 + 17918000 114127980 14
+26987167	0	1
+40753157	150000	50000
+25443670	150000	400000
+1821999	413955	384056
+369930
+
+chain 17589438 13 115169878 + 114456082 114639948 13 114142980 - 484930 668986 160
+430	0	2
+2905	4	8
+143	0	30
+612	0	4
+18	0	2
+175	1	1
+49	0	2
+2159	1	1
+27	1	1
+979	0	144
+1492	0	2
+174870
+
+chain 8359015315 14 107349540 + 19000000 107289540 14 106368585 + 18070000 106360585 15
+1081285	1	1
+43	1	1
+76	0	2
+437	1	1
+19	1	1
+440	1	0
+11	1	1
+59	15	15
+63	12	12
+70	1	0
+734	1	1
+165	4	1
+96	1	1
+46	0	1
+83	1	1
+149	4	4
+164	20	20
+63	16	15
+359	1	1
+39	1	1
+103	1	1
+76	1	1
+139	1	1
+38	1	1
+344	1	1
+65	1	0
+166	5	5
+88	1	1
+57	287	0
+59	1	1
+317	1	0
+52	1	1
+92	0	4
+651	4	4
+82	1	1
+93	1	1
+64	1	1
+24	1	1
+856	1	1
+35	1	1
+258	1	1
+17	1	1
+478	0	1
+1335	33	33
+1029	1	1
+37	1	1
+1115	4	3
+72	1	1
+643	10	10
+132	6	6
+89	2	0
+209	4	15
+77	5	5
+427	1	1
+41	1	1
+949	1	1
+16	1	1
+732	1	1
+44	0	2
+128	1	0
+91	1	1
+180	6	6
+388	6	6
+50	12	13
+275	1	1
+33	1	1
+142	1	1
+61	1	1
+560	1	1
+20	1	1
+1327	13	6
+1013	83	83
+202	4	0
+43	1	1
+352	10	10
+261	1	1
+39	1	1
+939	0	12
+1678	0	36
+159	1	1
+32	1	8
+818	6	0
+580	0	1
+931	0	1
+276	0	2
+3513	46	60
+882	0	2
+94	1	1
+49	1	1
+864	0	4
+40	1	1
+807	15	16
+416	3	0
+3345	15	15
+92	29	30
+80	1	1
+48	1	1
+2459	1	0
+646	66	66
+359	1	1
+29	0	54
+1875	0	3
+141696	1	1
+32	1	1
+8201115	0	1
+107	0	1
+2137	1	1
+39	1	1
+8848	1	0
+4806	0	1
+2075	0	1
+16612	0	1
+2385	0	3
+11506	0	8
+1353	1	0
+4596	1	0
+2073	1	2
+28	1	1
+2311	1	1
+44	1	1
+10440	4	0
+894	1	0
+1638	96	0
+41	0	9
+20	1	1
+2705	0	6
+352	1	1
+25	1	1
+742	1	0
+1048	18	2
+12085977	1	0
+14871228	0	3
+29067652	1	1
+47	1	1
+20173856	0	1292
+2548494
+
+chain 25802 14 107349540 + 20085579 20085848 8 146274826 + 118781991 118782260 6606813
+269
+
+chain 9908 14 107349540 + 20110215 20120217 22 49691432 + 14757849 14767860 97
+45	9891	9900
+66
+
+chain 8901 14 107349540 + 20090287 20100367 14 106368585 - 87815145 87825210 65
+33	9964	9949
+83
+
+chain 7700563179 15 102531392 + 20000000 102521392 15 100338915 + 18260008 100338915 16
+8448	2	6
+4086	0	1
+9569	1	1
+40	5	0
+56	1	7
+872354	40513	40506
+553	4	4
+876	40	39
+139	25	25
+1881	18	19
+499	8	8
+310	79	85
+78	26	23
+181	6	5
+569	11	11
+539	28	24
+261	22	20
+776	15	13
+62	13	13
+860	0	1
+716	0	26
+1349	167	166
+1070	23	23
+398	1	0
+177	21	5
+534	0	4
+770	24	18
+606	33	33
+1861	55	55
+2169	0	3
+558	19	20
+227	14	16
+329	5	5
+430	18	20
+620	1	0
+1112	0	2
+641	4	0
+476	47	47
+1285	1	0
+1139	49	49
+183	0	4
+1425	0	20
+186	1	0
+219	1	0
+607	44	44
+371	8	2
+507	0	2
+66	42	43
+999	4	4
+318	15	15
+1092	74	74
+808	61	61
+52	42	42
+109	51	51
+1535	0	14
+14011	0	4
+7955	1	4
+1350	0	1
+318	27	27
+600	4	0
+442	1	0
+1396	38	38
+1107	3	0
+1441	5	0
+360	49	49
+256	10	20
+497	39	39
+2129	0	4
+1242	0	2
+478	0	4
+708	92	92
+154	10	10
+1583	33	33
+1303	37	0
+100	14	14
+1138	92	109
+114	31	31
+2917	34	34
+1762	48	48
+449	0	1
+2458	1	9
+869	0	1
+534	49	49
+309	0	1
+2627	1	1
+3729	0	22
+565	1	0
+1845	0	1
+660	27	27
+68	0	1
+217	46	22
+1519	34	34
+559	32	32
+3851	0	1
+265	7	8
+224	0	4474
+444	0	1
+1651	10	11
+297	0	1
+665	0	21
+48	1	1
+1763	0	2
+245	1	1
+39	1	1
+519	1	1
+31	1	1
+2398	6	0
+749	1	49
+2072	0	4
+703	5	5
+337	0	1
+470	45	45
+1163	0	3
+1342	45	45
+140	1	0
+83	65	64
+723	38	38
+99	28	31
+92	0	1
+1218	13	0
+384	2	0
+292	41	41
+101	12	12
+576	2	0
+1907	21	21
+318	0	1
+1973	34	34
+689	51	51
+357	8	8
+2354	15	15
+2295	26	26
+2558	28	28
+571	2	0
+16	5	0
+323	1	0
+36	1	0
+5342	0	111
+1722	70	38
+272	13	13
+1284	1	0
+1128	4	4
+2189	0	1
+474	0	2
+1284	27	27
+36	6	0
+641	39	39
+381	2	0
+56	0	1
+2591	57	57
+160	121	121
+89	0	2
+316	1	0
+782	0	20
+155	1	1
+21	1	1
+601	6	0
+567	0	1
+278	1	1
+29	1	1
+89	4	0
+1737	1	1
+58	1	1
+368	24	24
+2113	24	20
+218	2	0
+18	1	1
+684	4	4
+3200	33	33
+58	18	18
+164	39	39
+296	6	6
+431	37	37
+431	47	47
+93	26	26
+216	48	48
+2779	17	0
+745	1	2
+104	61	61
+445	28	28
+356	0	1
+1484	2	1
+436	25	25
+306	57	57
+230	4	4
+843	49	50
+364	7	7
+796	28	28
+663	2	0
+93	15	0
+4378	0	1
+133	30	26
+41	2	0
+80	150	150
+925	0	3
+1882	13	13
+4513	0	1
+111	78	78
+200	0	6
+682	1	0
+200	0	3
+429	2	0
+736	20	20
+1573	121	120
+245	21	12
+1656	22	54
+616	1	2
+158	1	0
+587	41	44
+1053	6	6
+1116	36	36
+152	7	10
+448	1	0
+269024	863295	100000
+334079	50000	100000
+180557	74	0
+62	0	107
+7	2	1
+26	3	4
+4	0	1
+19	3	4
+10	42	87
+27	1	1
+202	1	1
+17	1	0
+156	1	1
+55	1	1
+111	1	0
+144	1	1
+57	1	0
+687074	50000	50000
+120648	348	0
+45585	1	0
+6994	0	1
+3398063	12354	44008
+7672	2	0
+1809	0	1
+428524	10165	101014
+43170	4	4
+1064959	5086	128966
+1021	1	0
+1710	0	1
+931	2	0
+4505	1	0
+686	2	525
+360	0	33
+130	1	1
+18	1	1
+12369	0	1014
+6233	1	0
+359485	111749	100000
+33855822	239	0
+2852112	0	1
+7040367	1	0
+2815738	1	3
+7055922	50000	60000
+363827	32	32
+104991	1	0
+203136	6050	0
+1426791	50000	60000
+13510190	5553	22012
+9194	3	0
+108	4	0
+41	1	0
+45	7	0
+2350	13	0
+5027	2	0
+534	0	1
+794	2	0
+4227	8	6
+5769	0	1
+381	0	1
+2524	2	0
+547	5	0
+1967	1	0
+1192	0	105
+1042	6	0
+3935380
+
+chain 22529558 15 102531392 + 21901199 22210800 15 100338915 + 19154576 19464222 111
+143347	1	1
+30	1	1
+2265	10	11
+297	0	1
+665	49	70
+240	39	39
+1731	41	41
+519	33	33
+339	22	22
+2037	4	0
+749	1	49
+910	38	38
+1831	3	9
+333	0	1
+470	1	1
+43	1	1
+1518	1	1
+51	1	1
+1122	1	0
+2351	19	6
+376	2	0
+1022	2	0
+1907	1	1
+19	1	1
+318	0	1
+3104	8	8
+179	1	1
+29	1	1
+3162	2	0
+2854	1	1
+26	1	1
+482	1	0
+512	1	1
+26	1	1
+571	27	16
+323	37	36
+5342	0	111
+542	40	39
+1141	64	35
+275	13	13
+503	26	26
+130	44	44
+581	4	0
+1128	4	4
+749	0	1
+1439	0	1
+474	0	16
+1270	1	1
+25	1	1
+54	11	0
+623	1	1
+37	1	1
+381	20	0
+56	0	1
+2591	1	1
+55	1	1
+160	4	4
+75	14	14
+1217	0	15
+742	59	53
+955	3	0
+1737	60	60
+391	43	43
+2071	24	20
+218	21	19
+684	4	4
+1195	4	4
+2001	1	1
+31	1	1
+58	18	18
+499	6	6
+431	1	1
+35	1	1
+431	1	1
+45	1	1
+3158	17	0
+983	0	1
+773	16	16
+1457	4	1
+767	1	1
+55	1	1
+338	10	10
+650	0	2
+123	3	4
+261	1	1
+48	1	1
+53	7	7
+776	1	1
+46	1	1
+663	2	0
+377	13	13
+4081	0	1
+159	5	0
+41	1	0
+164	1	1
+61	4	4
+925	0	3
+934	18	18
+1971	0	5
+3592	1	1
+76	1	1
+200	0	6
+682	1	0
+632	2	0
+2338	1	0
+110	1	1
+231	10	0
+1682	42	54
+616	1	2
+171	2	1
+543	1	1
+45	0	12
+2837	1	0
+441	2	0
+4958	5	5
+455	37	37
+330	22	22
+711	46	46
+184	49	49
+153	61	62
+392	11	11
+1266	8	7
+241	42	41
+198	31	31
+1064	78	78
+528	0	4
+431	1	0
+108	64	53
+358	5	5
+566	35	33
+168	1	0
+251	41	41
+880	33	33
+248	7	9
+583	3	4
+217	41	41
+117	13	14
+203	78	78
+133	44	45
+59	43	43
+129	19	19
+887	1	0
+264	30	30
+352	16	16
+719	36	35
+196	49	49
+425	4	0
+358	15	15
+151	22	22
+714	0	3
+165	41	0
+199	134	134
+504	47	47
+526	12	16
+206	39	39
+372	6	6
+224	25	25
+304	7	7
+186	90	90
+1872	0	3
+1066	7	7
+180	85	75
+63	37	37
+157	65	65
+331	3	0
+302	3	6
+213	42	45
+350	45	49
+580	42	45
+252	43	43
+337	4	0
+667	10	7
+94	9	9
+441	18	18
+124	0	1
+277	42	42
+1729	37	37
+1562	3	1
+546	15	13
+409	22	22
+312	45	45
+46	0	2
+268	14	14
+1166	35	38
+460	0	2
+74	0	1
+323	27	26
+2747	24	28
+322	10	0
+592	23	21
+161	45	45
+207	50	50
+409	22	23
+188	50	49
+396	152	151
+343	26	28
+3430	49	49
+2161	72	72
+1696	5	0
+389	50	50
+340	23	23
+169	0	3
+70	0	4
+392	0	1
+106	32	32
+2476	23	23
+1397	53	54
+2187	18	18
+489	9	9
+2018	4	0
+108	17	14
+836	5	5
+417	48	48
+358	34	34
+481	55	56
+277	48	48
+180	25	21
+356	3	0
+66	66	66
+407	28	27
+603	36	36
+1239	0	3
+194	8	8
+444	0	1
+204	35	35
+162	15	15
+418	6	5
+236	9	9
+55	52	52
+105	145	146
+57	143	143
+52
+
+chain 868538 15 102531392 + 21886534 21896633 15 100338915 + 19140000 19150000 4870
+1208	1	0
+245	165	68
+494	89	89
+824	15	15
+196	0	1
+197	50	50
+274	0	1
+1127	15	15
+230	4	0
+76	48	49
+671	0	1
+352	24	19
+117	11	11
+288	5	4
+122	0	3
+135	37	37
+265	0	2
+62	2	0
+656	0	2
+792	69	69
+142	73	73
+307	2	0
+331	0	2
+378
+
+chain 566185 15 102531392 + 83551634 83557670 8 146274826 + 129534406 129540446 9431
+549	1	1
+105	1	1
+1154	0	4
+273	6	6
+3947
+
+chain 334937 15 102531392 + 21896662 21900709 15 100338915 + 19150028 19154088 190582
+86	46	44
+567	11	9
+733	23	25
+212	2	0
+100	40	40
+155	1	0
+189	34	34
+165	42	42
+219	56	68
+259	61	62
+380	3	8
+242	13	13
+408
+
+chain 246244 15 102531392 + 22183221 22212114 15 100338915 + 19767012 19795905 936
+45	207	207
+50	619	619
+50	396	396
+152	343	343
+26	3430	3430
+49	2161	2161
+72	2090	2090
+50	1100	1100
+32	3896	3896
+53	6108	6108
+48	358	358
+34	481	481
+55	277	277
+48	180	180
+25	425	425
+66	407	407
+28	603	603
+36	2089	2089
+35	901	901
+52	105	105
+145	57	57
+143	52	52
+1314
+
+chain 136774 15 102531392 + 21885000 21886534 15 100338915 + 19138465 19140000 942717
+402	49	49
+445	0	1
+638
+
+chain 38827 15 102531392 + 28705151 28710237 15 100338915 - 73838719 73843805 82
+5086
+
+chain 9597 15 102531392 + 29116154 29116267 19 63811651 - 22308947 22309060 23761910
+59	4	4
+50
+
+chain 6273 15 102531392 + 23685556 23685849 15 100338915 + 21236652 21236834 12713809
+67	205	94
+21
+
+chain 4893 15 102531392 + 29111049 29111100 21 46944323 + 41885809 41885860 33898070
+51
+
+chain 3039 15 102531392 + 22178426 22178458 8 146274826 + 6100529 6100561 34349851
+32
+
+chain 2975 15 102531392 + 22826750 22826789 15 100338915 + 20381852 20381891 2718765
+39
+
+chain 2542 15 102531392 + 21049663 21065195 18 76117153 + 14510749 14526638 994
+38	2128	2130
+28	13310	13665
+28
+
+chain 1826 15 102531392 + 20950735 20950759 19 63811651 - 51273213 51273237 15159639
+24
+
+chain 1062 15 102531392 + 21028626 21028659 21 46944323 - 32992576 32992609 1118
+33
+
+chain 912 15 102531392 + 22826789 22826824 15 100338915 + 20377303 20377338 985154
+35
+
+chain 7474990131 16 90354753 + 60000 90294753 16 88827254 + 0 88822254 17
+172343	1	0
+111	0	1
+5627	1	2
+8398838	50000	17500
+25336229	150000	100000
+1112651	11100000	9800000
+42003582	50000	20000
+1855370
+
+chain 7369719958 17 81195210 + 0 81060651 17 78774742 + 0 78654742 18
+252627	1	1
+24	1	1
+41	29	0
+295	0	29
+261	0	58
+116	0	58
+94	0	29
+79	37	8
+485	59	1
+28	1	1
+76	1	233
+26	0	29
+2765	1	0
+17	2	0
+2220	18	18
+343	37	37
+457	1	1
+39	1	1
+564	16	16
+2523	9	39
+1878	56	0
+22	0	29
+1681	1	0
+414	3	0
+282	68	0
+93	10	10
+293	4	0
+3190	0	1
+2562	4	0
+1809	0	3
+84	1	1
+62	1	1
+3775	27	0
+1968	0	16
+912	2	0
+696	4	4
+1428	15	15
+290	0	1
+1779	1	0
+60	1	1
+216	1	0
+375	1	1
+41	1	0
+9221	100000	46522
+3080543	1	0
+1208216	2	0
+1370	0	2
+1279	4	0
+322	5	0
+5660	0	210
+308	22	21
+973	0	8
+2901	0	1
+8479	1	0
+4122	0	7
+3187	0	4
+571	1	0
+167	1	0
+10174	7	7
+856	1	2
+1630	0	1
+4258	1	3
+1688	0	1
+388	304	0
+672	0	1
+8495	10	0
+2272	0	1
+8297	0	1
+1500	4	1
+733	2	37
+57	17	0
+51	532	42
+2085	0	2
+52	1	1
+2913	13	14
+1309	1	0
+3991	0	3
+1939	3	0
+887	2	0
+463	0	18
+64	3	0
+2104	20	0
+557	4	0
+120	1	0
+3670	0	2
+4347	5394	0
+5332	1	0
+2505	10	4
+6776	11	14
+9573	1	0
+1136	2	0
+3754	0	1
+4588	0	1
+637	17	17
+1283	0	8
+371	1	0
+2084	0	1
+492	0	2
+519	4	0
+952	2	0
+1517	0	1
+987	0	9
+1152	10	0
+3608	2	0
+3199	39	0
+734	0	1
+646	0	2
+2211	0	1
+14829	0	1
+3473	34	1
+22	0	11
+2194	1	0
+6443	4	5
+2627353	0	1
+11581974	43	0
+31	89	0
+238782	1	0
+1830653	0	1
+419873	116477	100008
+5586	0	6
+11057	2	0
+3240	0	1
+1237	2	0
+373	1	1
+43	1	1
+558379	3000000	100000
+1823446	1	0
+2728383	1	0
+29	1	0
+138	0	1
+144	8	6
+38	2	0
+7	1	0
+18	1	1
+70935	1	0
+10	2	0
+52	31	28
+189	1	0
+41	2	2
+750363	44	44
+4038953	50039	100039
+1523967	1	1
+47	1	1
+231	0	2
+1175	0	1
+555	1	1
+49	1	1
+566	0	7
+607	0	2
+4954	1	1
+18	7	6
+567	1	0
+421	0	2
+1010	0	8
+777	3	0
+925	5	12
+318	0	1
+230	13	20
+244	1	1
+13	1	0
+42	1	1
+220	1	1
+56	1	1
+101	0	225
+1113	0	1
+17	1	1
+2614	0	4
+7108	2	0
+617	0	14
+5674	2	0
+1852	1	1
+63	1	1
+56	1	1
+25	1	1
+332	6	0
+423	5	5
+61	0	4
+108	1	1
+46	1	1
+160	2	2
+72	1	1
+162	1	1
+20	1	1
+53	1	1
+63	1	1
+112	1	1
+59	1	1
+5885	0	2
+5871	30040	159230
+925	0	5
+214	7	7
+641	17	17
+1296	46	46
+2513	69	71
+76	2	1
+57	0	50226
+1963	18	18
+2694	55	55
+6616	0	1
+5106	18	0
+2521	7	7
+49	0	10
+3440	4	0
+4179	4	0
+2749	1	0
+1125	0	8
+55	1	1
+1840	14	14
+624	0	8
+1742	0	4
+3690	4	0
+2051	1	0
+751	1	0
+2111	11	10
+3110	0	1
+682	0	1
+2795	2	5
+241	1	0
+165	3	1
+1258	1	0
+1601	0	5
+3716	1	0
+1308	1	0
+2058	0	1
+1624	1	0
+478	0	4
+9	0	6
+35	1	3
+47	1	0
+2425	0	1
+1178	4	0
+33	1	1
+415	5	5
+887	3	1
+1605	0	15
+259	0	2
+78	1	0
+4570	1	0
+322	0	1
+1801	0	2
+836	0	3
+1509	1	0
+1732	1	0
+936	6	0
+1371	0	1
+625	12	2
+5009	1	1
+75	1	0
+20	0	1
+139	1	0
+523	3	0
+11	319	0
+1368	0	1
+774	1	1
+16	1	1
+3523	119	124
+497	0	4
+174	0	9
+1317	3	0
+508	1	0
+1126	0	1
+1952	2	0
+565	0	2
+871	1	0
+1460	0	6
+55	1	0
+420	0	6
+57	1	1
+119	1	1
+427	0	1
+459	11	14
+448	1	0
+1275	7	7
+360	0	1
+73	1	1
+48	1	1
+4920	0	3
+713	1	1
+21	0	3
+6	0	3
+6	0	1
+691	1	1
+44	1	1
+1158	38	38
+446	10	9
+566	1	0
+175	4	0
+796	10	0
+810	0	1
+78	17	18
+1531	2	0
+1274	1	1
+39	1	1
+53	1	3
+202	1	0
+707	17	17
+1733	1	0
+1540	42	42
+12471	0	3
+286	1	3
+5600	0	4
+6458	1	0
+4866328	0	102000
+1870126	0	257
+590080	18	6
+26953	0	1
+6737	4	0
+5946	0	1
+2319	4	0
+1641	1	1
+27	1	1
+1237	0	1
+2698	1	1
+140	1	1
+1689	2	0
+836	30	29
+5333	0	1
+509	0	1
+224	9	9
+4983	0	6
+4981	30	30
+6913	3	13
+1039	1	0
+11605	0	1
+22064	1	0
+16612	0	8
+902	0	1
+757	0	1
+84	46	46
+489	1	0
+10979	1	1
+18	1	1
+1517	0	1
+4576	0	1
+12558	0	4
+2726	1	0
+5291	0	2
+8706	1	0
+83	0	1
+406	7	0
+87	0	38
+5531	0	1
+23971	0	1
+7855	22	54
+4095	1	0
+803	5	5
+6382	0	6
+3546	28	0
+4264	2	0
+13194	6	6
+6463	0	1
+26075	1	1
+59	1	1
+10791	7	17
+707	1	0
+210	0	1
+1655	2	0
+5301	0	1
+1930	0	1
+14632	0	2
+1043	0	1
+3607	0	3
+312	1	0
+5953	0	2
+170	17	0
+489	1	0
+5260	28	0
+888	0	10
+2461	10	10
+237	0	2
+1716	1	3
+10694	4	0
+3754	0	1
+6173	1	0
+8017	2	1
+3594	4	0
+5439	1	0
+4137	14	0
+29	15	0
+6418	1	0
+1267	0	1
+723	6	0
+1080	0	2
+3878	1	0
+7682	1	1
+44	1	1
+3135	1	0
+174853	2	1
+2008	7	7
+5657	1	0
+6496	3	0
+89	5	0
+665	1	0
+954	1	1
+44	1	1
+375	8	7
+3317	2	0
+2753	0	1
+1863	3	0
+3228	0	1
+3571	49	45
+6488	2	0
+8451	172	172
+3797	16	0
+2103	1	0
+268	23	26
+7888	0	4
+701	0	4
+2402	6	0
+37	1	1
+2943	3	2
+8420	0	1
+932	324	0
+6726	0	1
+543	3	4
+4028	0	18
+88	4	0
+2999	0	1
+530	0	1
+1153	11	11
+919	2	0
+1174	17	0
+118	16	16
+2727	0	1
+543	1	0
+783	0	1
+1374	4	0
+8619	0	20
+281	44	44
+4364	50	51
+2856	1	0
+5399	1	0
+1506	0	1
+919	6	0
+7228	0	10
+3226	0	1
+435	0	1
+4463	132	0
+9760	1	0
+2034	0	6
+7656	0	1
+198212	132	0
+11700	5	0
+7647	0	1
+9062	0	4
+8778	2	0
+7014	0	1
+1613	2	0
+790	5	7
+7433	0	1
+6482	12	12
+6798	1	0
+1422	0	1
+3454	1	1
+43	1	1
+3097	2	0
+334	18	0
+1444	0	1
+2400	0	3
+3272	1	0
+9106	0	1
+1573	1	0
+4742	0	1
+3366	0	1
+5484	1	0
+2445	5	0
+5447	8	8
+2539	1	0
+1471	1	0
+238	1	1
+16	1	1
+288	5	5
+2995	2	0
+951	1	1
+35	1	1
+279	15	16
+3534	0	6
+3513	1	0
+163	1	0
+6173	1	0
+1074	0	1
+2818	0	1
+2868	1	0
+3796	0	1
+1118	167	1
+1278267	25	25
+10747175	217	0
+3504874	1053	0
+10844	11	13
+18805	0	1
+1960834	50000	126729
+3065	0	1
+3601036	8833	90008
+34292	0	1
+376	14	14
+1447	44	0
+3080	1	1
+43	1	1
+789	0	1
+11432680	50000	153000
+1902016	4098	0
+102	21	0
+3179	6	6
+877	1	1
+49	1	1
+296	1	0
+1375	1	1
+21	1	1
+607	5	5
+98	22	0
+6811	1	1
+17	11	0
+3804	0	1
+1356	1	1
+29	1	1
+297	0	1
+9543	2	0
+3131	4	0
+860	1	0
+27346	0	1
+7553	0	2
+2834	2	0
+394	0	4
+6322	44	44
+158	0	1
+405	8	11
+1128	0	7
+271	1	1
+21	28	0
+504	0	6
+1214	31	44
+384	3	0
+521	18	18
+392	0	11
+802	1	1
+25	2	3
+51	49	1
+49	1	1
+558	1	0
+351	0	1
+2779	13	13
+114398	82124	65008
+7795	1	0
+18	1	1
+4140	0	1
+28048	1	1
+32	1	1
+4630	0	1
+4573	0	3
+357	0	2
+4812	0	1
+14372	3	0
+203	1	0
+26257	0	1
+2734	2	0
+19262	5	5
+5022	1	0
+25471	1	0
+1114538	53	0
+82	0	126
+1416	16	16
+610	0	57
+482	0	1
+148	1	1
+24	1	1
+2322	1	1
+23	0	1
+719	16	0
+20	0	16
+105	9	9
+1277	1	0
+2498	1	0
+352	0	49
+50	50	0
+21	49	0
+28	49	0
+60	47	0
+17	97	0
+901	47	0
+272	14	1104
+279	1	0
+37	12	11
+65	32	0
+18	94	0
+60
+
+chain 2732964 17 81195210 + 36295616 36336227 17 78774742 - 45363365 45403960 362
+666	1	1
+114	1	1
+1777	1	1
+22	1	1
+2481	3	0
+947	3	1
+994	1	1
+26	1	1
+5327	2	0
+95	13	13
+2424	0	1
+339	2	1
+288	1	0
+1180	8	8
+1145	2	4
+1144	1	0
+322	1	0
+28	1	0
+35	1	0
+1499	0	1
+1258	7	6
+1123	0	1
+269	5	4
+1850	18	19
+188	3	0
+403	1	1
+18	1	1
+3148	1	1
+160	1	1
+105	11	0
+573	10538	10545
+33
+
+chain 30167 17 81195210 + 44458173 44458487 2 242951149 - 34181426 34181740 4632506
+314
+
+chain 29586 17 81195210 + 36420504 36420817 7 158821424 - 10371995 10372309 4828537
+136	0	1
+177
+
+chain 20882 17 81195210 + 56914122 56914339 X 154913754 + 31643322 31643539 5151267
+217
+
+chain 16484 17 81195210 + 44491151 44521781 17 78774742 + 42064051 42094670 662
+44	30454	30443
+132
+
+chain 14999 17 81195210 + 44428451 44428612 17 78774742 + 42001706 42001867 887
+161
+
+chain 12695 17 81195210 + 44739444 44739576 17 78774742 + 41877181 41877313 13974721
+132
+
+chain 12494 17 81195210 + 19077136 19077299 17 78774742 - 59726399 59726562 431
+43	31	31
+89
+
+chain 7858 17 81195210 + 253568 254148 17 78774742 + 253365 253974 1160836
+37	486	515
+57
+
+chain 5202 17 81195210 + 79704633 79704687 Y 57772954 - 54321400 54321454 32857515
+54
+
+chain 5149 17 81195210 + 36426505 36456524 17 78774742 - 35824084 35853324 896
+73	1	1
+45	29858	29079
+42
+
+chain 3754 17 81195210 + 60419213 60419252 8 146274826 - 11845696 11845735 33181261
+39
+
+chain 3753 17 81195210 + 44413461 44413510 17 78774742 - 18492830 18492879 715
+49
+
+chain 2637 17 81195210 + 252694 252723 17 78774742 + 252810 252839 1426666
+29
+
+chain 2581 17 81195210 + 81166856 81166888 1 247249719 + 441705 441737 997
+32
+
+chain 1872 17 81195210 + 79585571 79585619 11 134452384 + 72960908 72960956 2849402
+48
+
+chain 7055977505 18 78077248 + 10000 78016181 18 76117153 + 0 76117153 19
+15400898	3100000	1363998
+28218587	15	15
+5329636	150000	47000
+3667310	18	0
+16406889	50000	28008
+3388467	50000	22000
+2103304	0	3
+136125	1	0
+7	1	0
+647	1	0
+1543	1	0
+25	14	8
+19	2	0
+10	7	4
+9	4	2
+663	1	0
+359	1	0
+1617
+
+chain 5307806876 19 59128983 + 60000 59114839 19 63811651 + 11000 63806651 21
+7286004	50000	5000
+1291194	45000	0
+11772188	69160	0
+4058236	3100000	8000000
+20129228	2	0
+701	0	3
+347	1	1
+31	1	1
+1833	0	3
+1984	1	1
+47	1	1
+190	1	1
+34	1	1
+889	2	0
+1413	7	0
+2680	4	0
+375	1	0
+314	4	0
+29	1	0
+69	0	1
+3881	1	1
+40	12	0
+293	14	0
+1479	1	0
+233	1	1
+45	1	1
+1049	1	0
+1766	7	44
+220	0	3
+537	7	0
+351	8	8
+3603	1	1
+17	0	3
+697	0	1
+269	0	3
+974	5	6
+96	10	0
+1096	10	10
+1177	12	14
+1141	9	12
+1090	0	1
+175	16	0
+1063	0	4
+4780	44	44
+722	0	1
+548	2	2
+44	1	1
+424	2	2
+26	1	0
+4	0	1
+82	1	1
+59	1	1
+2087	15	0
+1499	0	1
+1754	0	2
+11209362
+
+chain 1655749 19 59128983 + 20505321 20523415 19 63811651 + 20366320 20387252 1476
+2041	4	4
+5604	0	2
+363	0	1
+2655	5	2857
+153	46	46
+705	79	83
+370	6	1
+1668	27	26
+347	21	0
+191	6	6
+369	0	2
+393	68	67
+328	0	6
+2049	1	0
+464	35	35
+96
+
+chain 207934 19 59128983 + 59114839 59117224 22 49691432 + 49588728 49591432 1471
+992	1	1
+63	1	1
+125	152	154
+174	1	1
+47	3	0
+214	5	5
+254	1	1
+67	1	1
+55	1	321
+72	14	14
+142
+
+chain 126422 19 59128983 + 59117224 59118680 10 135374737 + 135372723 135373917 1944
+177	13	13
+165	1	1
+156	1	1
+205	4	4
+93	1	1
+14	5	0
+88	1	1
+110	1	1
+52	2	1
+28	2	1
+14	255	0
+68
+
+chain 13558 19 59128983 + 59116021 59116173 2 242951149 - 128870722 128870873 1493
+33	1	0
+24	1	1
+57	1	1
+35
+
+chain 7358 19 59128983 + 59118906 59118983 21 46944323 + 46944213 46944290 27502546
+77
+
+chain 3811 19 59128983 + 20573506 20573546 19 63811651 - 43994109 43994149 26416662
+40
+
+chain 174 19 59128983 + 47898161 47898204 18 76117153 + 27836426 27836469 20429401
+43
+
+chain 22466185064 2 243199373 + 10000 243102476 2 242951149 + 0 242751149 1
+1201236	0	1
+2057	1	1
+26	1	1
+4043	22	0
+82	7	101
+33	84	0
+26	1	23
+67	48	0
+176	318	0
+40	92	0
+33	0	74
+62	0	6
+22	0	118
+387	2446	0
+843	2450	0
+167	2304	0
+21342	1	1
+50	4	0
+2040	0	4
+9053	2	0
+88	3	53
+1078	0	1
+4122	1	0
+1608	28	1
+4029	0	9
+967	4547	1000
+420	27	0
+2237126	0	1
+2458	17	17
+4595	4	0
+3531	14	14
+3954	51129	50000
+1426129	160449	100025
+11087286	0	3
+773	103977	50000
+1576	0	1
+240	0	1
+318	2	0
+255	0	16
+2851	10	10
+1404	1	1
+27	1	1
+703	13	0
+375	0	1
+4783388	35000	25000
+848	0	2
+1225	0	2
+391	1	0
+3653	1	1
+28	1	1
+49	0	4
+4514	0	9
+9628	1	9
+1483	7	7
+1990	0	1
+1949	1	0
+2716230	1	0
+7799848	851	851
+38932068	5	9
+9477928	0	3
+7529698	72396	0
+1891551	294073	150000
+17672	1	0
+5792	1	0
+9017	0	266
+2944	0	1
+9388	2	0
+37828	4	0
+23436	0	4
+290931	1273578	1000000
+731068	3000000	3000000
+2558421	0	1
+1197	10	0
+685	42	46
+2309	0	1
+1332	22	23
+344	0	1
+1645	4	4
+4093	25	25
+2446	1	0
+6329	1	0
+769	0	1
+873	7	0
+1299	0	1
+8250	15	15
+4291	10626	12548
+1063	103	0
+75	0	218
+5897	1	1
+33	1	1
+9905	51	37
+1711	1	1
+45	1	1
+1597	4	4
+61	1	1
+869	13	0
+1633	15	15
+1179	3	0
+2819	0	2
+156	88	465
+100	0	25
+4753	0	8
+4903	6	6
+3847	0	2
+108126	0	145
+3542	1	0
+10276	0	1
+402	1	1
+47	1	1
+63	2	0
+583	1	1
+34	1	1
+8974	0	46
+379	1	1
+70	1	1
+2474	0	102
+1756	0	1
+8426	0	1
+11986570	151150	142000
+14207	1	1
+49	1	1
+1781	0	12
+409	1	0
+1874	1	1
+33	1	1
+4795	2	0
+3686	1	1
+15	1	1
+164	2	0
+7287	5	5
+702023	72796	150000
+69	1	0
+1598	0	1
+1340	0	1
+1030	0	4
+1166	10	10
+6406	1	1
+34	1	1
+3283	2	4
+496	1	23
+25	10	0
+40	1	1
+21282	2	1
+1406	0	44
+937	17	0
+18255	1	0
+172366	0	281526
+40517	0	406
+58864	1	2
+1843	0	2
+14994	0	1
+12992	2	0
+2571146	1	0
+35688061	108224	100000
+29671719	1	0
+39665349	1	0
+14876089	64197	20000
+401	0	3
+1831	1	1
+61	1	1
+654	11	1
+127	0	28
+116	25	29
+74	9	9
+3247	2	0
+1355	1	0
+816	1	0
+21	3	0
+526	1	1
+60	1	1
+773	1	0
+1494	1	0
+1683	1	0
+21	1	1
+596	1	0
+1582	1	0
+425	0	3
+1139	0	8
+138	144	813
+71	1	0
+385638	1	1
+219	1	1
+51	7	7
+54	15205	15205
+54	7	7
+51	1	1
+110	1	1
+5198249	0	1
+115	80	0
+60	40	0
+80	100	20
+442	1	1
+35	1	1
+119	9	129
+14	0	40
+61	1	1
+85	0	40
+1331	0	1
+1194	12	14
+1773	0	5
+1623	1	1
+25	1	1
+2422	21	22
+2315	0	1
+31	1	1
+1508	0	3
+50	0	4
+970	6	6
+7234	4	0
+1228	1	0
+1233	8	1
+4207	1	1
+41	1	1
+1715	50	50
+1532	0	2
+1714	2	0
+2299	2	0
+2143	1	1
+18	1	1
+917	1	0
+1082	1	1
+49	1	1
+9098	0	4
+5529	0	1
+3266	0	8
+894	6	0
+1440	1	1
+2095	2	0
+4179	18	13
+1785	0	1
+1674	0	6
+1217	32348	33000
+287	17	23
+40	173	0
+20	161	0
+13	66	0
+12	71	1
+12548	30000	30000
+952154	41011	25000
+1914	1	0
+225	1	1
+57	1	1
+2910	0	1
+471	1	0
+1956	1	1
+43	1	1
+991	0	92
+2863	3	0
+1838	306	0
+1006	30	0
+206	1	1
+27	0	3
+221	17	17
+1525	8	0
+413	1	1
+32	2	2
+1573	12	12
+2258676
+
+chain 8298836 2 243199373 + 90373613 90527957 2 242951149 + 90958828 91114560 236
+29837	32	32
+212	25	25
+508	90	90
+1291	33	33
+2574	1	0
+833	28	28
+2712	0	1
+805	10	5
+565	68	68
+75	69	57
+176	58	513
+63	105	105
+336	33	33
+69	1	0
+280	4	4
+111	12	12
+523	1	0
+136	55	56
+198	0	1
+630	0	1
+362	42	42
+405	30	30
+78	5	0
+125	5	0
+75	140	0
+166	49	49
+1653	30	30
+3790	5	5
+500	21	21
+577	23	23
+180	0	1
+1105	1	0
+231	4	4
+333	33	33
+852	2	0
+2709	16	16
+476	28	28
+53	33	57
+256	0	3
+900	0	1
+227	0	2
+718	0	2
+244	42	42
+302	30	30
+211	21	21
+1809	16	17
+204	33	32
+341	9	9
+176	0	5
+180	67	67
+73	39	39
+369	49	49
+52	9	15
+699	9	13
+142	0	4
+184	0	4
+248	27	26
+306	10	10
+63	20	20
+533	22	22
+432	86	85
+97	19	19
+383	19	23
+642	10	9
+156	88	88
+217	0	6
+1798	9	7
+425	0	4
+1191	0	4
+465	40	37
+671	7	7
+450	0	1
+714	31	32
+682	38	15
+230	28	1076
+95	220	261
+80	1967	0
+118	383	158
+81	28	2
+247	0	1
+181	0	1
+702	47	47
+361	39	39
+300	50	50
+195	9	9
+179	35	35
+228	0	10
+321	65	65
+233	20	20
+368	35	35
+1436	37	37
+985	5	5
+140	73	73
+1031	25	25
+957	51	51
+690	23	48
+1047	49	49
+186	1	0
+244	4	4
+166	16	16
+173	1	0
+387	51	51
+122	59	58
+141	1	0
+72	102	84
+75	203	201
+276	30	30
+367	20	20
+105	67	68
+82	0	1
+386	7	7
+68	61	61
+514	56	56
+92	91	91
+268	89	89
+200	4	4
+526	33	36
+370	10	10
+366	20	26
+1107	0	2
+130	74	74
+101	0	1
+542	32	34
+179	43	43
+151	84	84
+421	25	25
+332	1	0
+561	64	65
+1406	10	10
+161	97	88
+564	27	30
+123	29	33
+170	0	1
+183	94	94
+52	4	0
+379	83	83
+237	32	31
+187	46	46
+236	728	703
+50	1494	1865
+72	67	32
+25	1732	6535
+52	52	52
+104	647	648
+27	494	471
+23	0	137
+1	1884	302
+115	8	8
+76	3078	388
+26	200	44
+59	2295	2292
+40	1854	1861
+54	2541	2546
+27	28	27
+57	56	56
+26	2212	2216
+181	494	652
+42	2237	2213
+40	2572	2562
+36	1791	1791
+34	2776	2807
+23	7115	7113
+44	509	509
+36	664	665
+43	1891	2219
+36	256	256
+31	276	289
+42	881	1734
+67	149	144
+49	190	190
+73	357	345
+30	1074	1075
+42	1850	1850
+47	469	481
+24	2460	2482
+41	3325	3319
+32	306	296
+26
+
+chain 2305993 2 243199373 + 243162866 243189340 16 88827254 - 5000 31222 1142
+136	9	9
+870	16	16
+229	1	1
+44	1	1
+330	10	14
+243	1	1
+93	1	1
+58	1	1
+144	1	1
+62	95	95
+333	1	1
+77	1	1
+494	9	11
+230	8	8
+61	12	13
+128	14	14
+123	1	1
+68	1	1
+4208	5	1
+1989	71	0
+121	1	1
+35	1	1
+1498	59	0
+443	69	69
+237	1	1
+45	1	1
+75	1	1
+32	2	1
+20	1	1
+152	1	1
+129	0	1
+1040	1	1
+70	2	0
+128	1	1
+50	1	1
+605	9	8
+62	1	1
+155	1	1
+50	11	6
+94	1	1
+409	1	1
+34	1	1
+217	1	1
+39	1	1
+287	0	9
+102	1	1
+56	30	26
+64	108	0
+127	1	0
+373	1	1
+18	1	1
+194	1	1
+10	1	1
+98	1	1
+67	1	1
+184	1	1
+21	1	1
+86	0	1
+44	1	1
+50	15	15
+177	1	1
+72	1	1
+222	1	1
+44	1	1
+50	1	1
+46	1	1
+449	1	1
+118	1	1
+127	0	1
+242	1	1
+36	1	1
+710	4	4
+69	1	1
+87	1	1
+115	1	1
+68	17	0
+12	2	1
+14	0	12
+36	4	0
+102	1	1
+105	24	24
+131	18	18
+64	19	19
+293	1	1
+43	1	1
+134	25	25
+77	14	14
+225	1	0
+93	1	1
+363	11	11
+271	25	25
+136	1	1
+36	1	1
+102	4	4
+29	1	1
+51	2	0
+162	0	4
+61	1	0
+65	1	1
+26	4	4
+140	17	17
+336	1	1
+25	1	1
+408	16	16
+311	27	27
+90	7	7
+449	1	1
+47	1	1
+133	1	1
+62	7	7
+194	1	1
+13	3	0
+54	2	0
+28	1	1
+72	1	1
+45	1	1
+65	1	1
+23	1	1
+279	1	1
+61	1	1
+55
+
+chain 1358560 2 243199373 + 89890737 90543561 2 242951149 - 153539598 155537136 99
+8973	0	1
+939	0	1
+4351	0	2
+2413	1	1
+37	1	1
+515	1	0
+224	1	1
+22	1	1
+203	1	1
+18	1	1
+249	8	7
+830	4	0
+177	1	0
+30	1	1
+224	1	1
+75	1	1
+243	1	1
+20	0	5
+2724	0	137
+439	1	1
+35	1	1
+444	0	2
+1484	1	1
+41	1	1
+395	1	1
+40	1	1
+417	1	1
+44	1	1
+909	1	1
+32	24	14
+1057	2	2
+46	1	1
+306	1	1
+32	3	0
+269	10	10
+535	10	10
+615	1	1
+42	1	1
+1295	1	1
+21	1	1
+84	1	1
+30	0	1
+19	1	1
+434	57	57
+283	15	15
+304	12	12
+149	17	17
+1413	1	1
+32	1	1
+66	550910	1890523
+54	205	14
+64	147	86
+119	57	8
+71	27	96
+100	1265	73
+307	7	9
+182	31	30
+128	15	15
+95	61	59
+92	20	296
+50	77	75
+255	261	3338
+95	264	262
+204	53	55
+136	81	81
+173	62	57
+130	77	76
+241	35	35
+424	0	154
+42	3	3
+109	0	434
+68	0	59
+215	1	1
+47	1	1
+109	0	180
+10	4	0
+21	7	104
+33	31	37
+62	17	17
+114	1	1
+50	0	9
+117	9	0
+63	1	1
+92	1	1
+37	146	0
+49	956	0
+32	163	4
+37	619	0
+42	1	1
+108	973	20
+91	1	18
+215	19	19
+20	26	0
+124	56	0
+14	65	0
+65	1	1
+465	1	1
+45	1	0
+126	1	1
+46	1	1
+1501	1	1
+41	40	0
+58	2	5
+574	8	0
+830	0	5
+121	0	3
+26	0	2
+52	0	2
+183	54	0
+1069	1	1
+62	4	0
+23	1	1
+62	0	3
+233	0	2
+32	3	0
+1051	112	112
+56	26	26
+59	7	7
+588	17	18
+401	18	18
+472	1	0
+398	2	3
+249	181	22
+397	0	158
+97	42	42
+1302	24	2
+162	9	9
+740	40	40
+554	0	1
+1362	23	19
+249	12	12
+372	36	36
+987	1	0
+221	10	8
+394	9	9
+169	34	36
+170	1	1
+27	1	1
+61	1	0
+396	0	120
+152	1	13
+60	0	5
+12	1	1
+145	1	1
+51	1	1
+847	6	6
+420	1	1
+46	1	0
+43	1	1
+145	1	1
+41	1	1
+142	25	24
+332	14	14
+310	1	1
+91	1	1
+605	1	1
+47	1	1
+361	10	10
+183	0	5
+672	8	8
+76	17	20
+227	1	1
+86	1	1
+60	1	0
+30	5	5
+2399	1	1
+29	1	1
+547	10	17
+195	3	0
+609	3	0
+175	44	44
+292	8	8
+209	36	37
+543	39	39
+82	43	43
+235	38	38
+760	20	20
+502	8	0
+108	7	18
+66	2	0
+57	0	3
+88	36	36
+77	0	15
+94	24	24
+61	31	1532
+146	38	41
+92	82	77
+151	0	2606
+94	93	1000
+189	50	50
+234	100	94
+146	49	49
+189	74	74
+62	37	17
+258	30	30
+114	47	47
+494	96	98
+323	42	43
+106	20	20
+142	250	250
+161	7	7
+651	21	21
+492	237	249
+144	23	23
+88	48	48
+52	15	15
+201	6	0
+105	29	29
+68	18	18
+87	50	50
+227	147	147
+176	17	17
+404	9	9
+457	0	23
+392	41	41
+196	18	18
+99	77	80
+219	52	53
+156	0	7
+323	28	28
+99	43	42
+229	27	27
+156	107	103
+95	1	0
+1118	0	1
+282	41	41
+172	21	3
+104	26	0
+21	1	71
+54	6	76
+63	1	1
+58	1	1
+84	1	1
+285	1	1
+46	1	1
+320	15	15
+326	7	7
+170	1	1
+73	1	1
+214	1	1
+40	1	1
+613	1	0
+772	0	2
+424	1	1
+34	1	1
+423	1	1
+33	1	1
+1157	1	1
+43	2	2
+82	1	1
+21	1	1
+65	1	1
+62	1	1
+250	1	1
+79	1	1
+88	2	2
+79	1	1
+68	11	11
+115	1	1
+38	1	1
+63	9	0
+39	1	1
+73	1	1
+77	3	3
+55	1	1
+46	1	1
+157	1	1
+58	0	2
+92	1	1
+67	1	1
+48	1	1
+289	1	1
+40	1	0
+398	1	1
+31	1	1
+729	1	1
+72	1	1
+575	1	1
+86	1	1
+495	3	0
+472	1	1
+34	1	1
+87	1	0
+28	1	1
+441	20	0
+31	1	1
+61	1	1
+152	5	5
+774	0	1
+114	2	0
+355	0	3
+415	5	0
+76	1	1
+18	1	1
+308	1	1
+18	1	1
+226	4	4
+490	0	3
+104	1	1
+47	1	1
+542	6	6
+131	8	0
+152	49	1
+68	9	9
+198	1	1
+40	0	10
+78	1	1
+108	1	1
+73	1	1
+50
+
+chain 1317324 2 243199373 + 234472598 234486532 2 242951149 - 8801149 8815083 1658
+13934
+
+chain 1182591 2 243199373 + 111018489 111031067 2 242951149 - 132350497 132363075 1985
+750	1	0
+155	1	0
+2029	0	1
+2687	0	1
+2417	3	0
+3105	1	3
+965	35	36
+238	6	6
+185
+
+chain 907761 2 243199373 + 111000659 111010676 2 242951149 + 110060000 110070000 4064
+3405	66	54
+839	0	1
+854	33	33
+1502	180	174
+250	88	88
+1904	40	40
+856
+
+chain 864618 2 243199373 + 110991361 111000659 2 242951149 + 110050705 110060000 3488
+3987	37	37
+135	34	34
+2446	4	0
+1497	0	1
+1158
+
+chain 730598 2 243199373 + 111010676 111018489 2 242951149 + 110070000 110077815 3339
+976	16	15
+4855	0	3
+320	26	26
+1620
+
+chain 247895 2 243199373 + 111031067 111033745 2 242951149 - 131778891 131781575 150672
+814	1	1
+73	1	1
+148	0	6
+1211	4	4
+426
+
+chain 233678 2 243199373 + 87718206 87726480 2 242951149 - 151887377 151890935 691
+139	0	3
+233	4	2
+36	0	1
+291	21	13
+104	28	28
+303	26	26
+314	134	82
+86	0	1
+53	4314	721
+22	22	0
+50	389	652
+54	1133	0
+17	214	6
+79	34	60
+62	59	67
+53
+
+chain 228678 2 243199373 + 243159401 243162866 1 247249719 + 217390 220668 1312
+57	88	88
+22	186	0
+101	49	49
+417	53	54
+61	3	0
+141	0	1
+198	8	8
+852	39	39
+405	56	56
+61	27	27
+589	1	1
+51
+
+chain 207578 2 243199373 + 243152688 243155284 10 135374737 - 346 2792 2690
+533	150	0
+105	1	1
+49	1	1
+260	1	1
+69	1	1
+262	1	1
+29	1	1
+1133
+
+chain 148868 2 243199373 + 243155284 243160374 5 180857866 - 20000 25834 2103
+547	1	1
+38	1	1
+431	1	1
+24	1	1
+1389	1	1
+36	1	1
+1646	57	57
+82	0	744
+6	22	22
+186	101	101
+49	417	417
+53
+
+chain 147892 2 243199373 + 97920581 97932373 2 242951149 - 145465890 145477699 123
+1513	0	1
+2596	1	1
+36	1	1
+1383	5	1
+46	4	0
+550	1	4
+1798	7	8
+158	1	29
+18	1	1
+110	1	1
+48	1	1
+1617	7	0
+723	1063	1063
+93	1	0
+9
+
+chain 133880 2 243199373 + 87666489 111064157 2 242951149 - 130965951 132771520 53
+624	23366717	1774574
+2397	0	12
+14288	0	1
+1427	1	1
+24	1	1
+1756	10	10
+83	69	69
+698	0	21
+1910	1	1
+61	1	1
+3754	0	8
+243	1	1
+33	1	1
+320	0	1
+163	1	1
+36	1	1
+809	0	1
+1762	1	1
+49	1	1
+425
+
+chain 127176 2 243199373 + 5140970 5146585 2 242951149 - 235014747 235020583 1011815
+158	1545	1830
+107	308	308
+50	129	129
+85	163	165
+62	65	65
+282	81	63
+147	650	624
+67	138	138
+59	285	285
+76	61	62
+92	72	72
+76	266	249
+70	129	128
+83	107	102
+202
+
+chain 104115 2 243199373 + 87667113 87668206 2 242951149 + 87520624 87521717 786265
+1093
+
+chain 95484 2 243199373 + 87729232 87738885 2 242951149 + 87510347 87520000 5761
+9653
+
+chain 84057 2 243199373 + 90492917 90545103 2 242951149 - 152993866 153046874 435
+28	21223	21222
+38	2087	2087
+38	134	134
+40	246	246
+45	0	255
+13	0	572
+34	189	189
+50	234	234
+30	1029	1029
+47	494	494
+96	633	633
+250	1379	1379
+190	682	682
+29	173	173
+50	227	227
+147	1809	1804
+77	219	219
+52	479	479
+28	99	99
+43	229	229
+27	156	156
+107	16787	16788
+49	628	628
+1542
+
+chain 73315 2 243199373 + 87720014 87720774 2 242951149 - 155450797 155451557 1717423
+760
+
+chain 66981 2 243199373 + 1219529 1222202 2 242951149 + 1208584 1209647 1299817
+61	279	0
+275	1051	0
+115	843	563
+49
+
+chain 64603 2 243199373 + 90371566 90373613 2 242951149 + 90963202 90965490 370989
+76	46	46
+165	47	47
+460	75	75
+51	403	393
+63	64	364
+66	168	168
+56	68	19
+69	135	135
+35
+
+chain 46427 2 243199373 + 1223650 1226709 2 242951149 + 1208645 1209604 1438302
+140	630	0
+183	167	167
+210	1050	0
+171	420	0
+88
+
+chain 36623 2 243199373 + 89847430 89848295 5 180857866 + 153976522 153977390 3635252
+54	96	96
+262	346	349
+107
+
+chain 34396 2 243199373 + 87721616 87729232 2 242951149 + 87502993 87507825 13964
+67	36	543
+1013	77	25
+569	4	4
+189	715	6
+6	94	94
+389	54	54
+542	2531	33
+70	11	11
+68	21	21
+129	10	10
+126	0	22
+162	9	0
+89	28	26
+108	298	307
+116	64	12
+21
+
+chain 31906 2 243199373 + 90476997 90485104 2 242951149 - 155439923 155448722 818134
+65	4692	1587
+31	1167	442
+62	157	183
+65	24	24
+92	31	191
+67	10	184
+32	72	0
+76	105	36
+60	4	0
+97	52	697
+66	9	0
+169	1	23
+85	272	2102
+131	95	43
+149	89	1960
+80
+
+chain 31233 2 243199373 + 239788914 239789423 2 242951149 + 239454423 239454932 2214253
+173	20	20
+161	13	13
+66	12	12
+64
+
+chain 27639 2 243199373 + 243165116 243187640 8 146274826 + 470 67316 1215
+95	9992	9923
+69	4222	48594
+49	1	1
+58	4967	4926
+25	3019	3079
+27
+
+chain 25982 2 243199373 + 16340754 16341023 3 199501827 - 118072788 118073057 6523537
+269
+
+chain 25898 2 243199373 + 1220683 1220990 2 242951149 + 1208828 1209135 2249524
+307
+
+chain 25826 2 243199373 + 87728597 87729031 2 242951149 + 87491002 87491436 712257
+28	108	108
+298
+
+chain 25128 2 243199373 + 5141270 5144398 1 247249719 + 207689145 207692170 1456022
+66	87	87
+79	23	23
+95	979	893
+74	119	119
+116	487	487
+54	893	876
+56
+
+chain 24661 2 243199373 + 16273805 16274100 4 191273063 - 182882474 182882769 7289877
+128	26	26
+141
+
+chain 19295 2 243199373 + 90372486 90373577 2 242951149 + 90976555 90977646 1336226
+61	57	57
+56	292	292
+41	202	202
+55	193	193
+134
+
+chain 19158 2 243199373 + 1225400 1225680 2 242951149 + 1208855 1209065 11144872
+180	70	0
+30
+
+chain 18303 2 243199373 + 1219198 1219473 2 242951149 + 1208603 1208808 11853376
+134	73	3
+68
+
+chain 13465 2 243199373 + 16354747 16354888 5 180857866 + 167726962 167727103 16868271
+141
+
+chain 13298 2 243199373 + 89875086 89876327 20 62435964 + 29293186 29293377 17078580
+57	350	0
+39	320	0
+36	155	0
+6	225	0
+53
+
+chain 13261 2 243199373 + 1224140 1224280 2 242951149 + 1208645 1208785 17127371
+140
+
+chain 12749 2 243199373 + 5141660 5146147 5 180857866 - 44949635 44952639 1949230
+55	641	482
+80	490	492
+69	238	238
+34	2813	1487
+67
+
+chain 11727 2 243199373 + 240838559 240838726 2 242951149 + 240487433 240487623 18443158
+86	35	58
+46
+
+chain 11295 2 243199373 + 1226909 1227026 2 242951149 + 1209530 1209647 20202652
+117
+
+chain 11288 2 243199373 + 1223295 1223413 2 242951149 + 1208990 1209108 3139804
+118
+
+chain 10759 2 243199373 + 90430195 90457119 2 242951149 - 151338126 151363320 2584
+28	2775	2822
+30	11958	12016
+40	1843	1850
+30	5080	3227
+47	361	361
+39	312	312
+38	383	383
+35	2707	2718
+36	1130	1130
+52
+
+chain 9553 2 243199373 + 89869741 89871237 Y 57772954 + 11913136 11913399 23867669
+64	1367	134
+65
+
+chain 9489 2 243199373 + 110253717 110253937 2 242951149 + 106303434 106303606 24025084
+58	106	58
+56
+
+chain 9445 2 243199373 + 1223971 1224070 2 242951149 + 1208756 1208855 24130758
+99
+
+chain 8720 2 243199373 + 1222223 1225291 2 242951149 + 1208828 1209516 2041184
+278	99	99
+79	2535	155
+77
+
+chain 8428 2 243199373 + 90482794 90485288 2 242951149 - 155439240 155441007 1572933
+56	44	44
+58	400	417
+31	1832	1088
+73
+
+chain 8213 2 243199373 + 87720809 87720895 2 242951149 + 87507349 87507434 5227216
+41	1	0
+44
+
+chain 8069 2 243199373 + 90483014 90484786 2 242951149 - 155448229 155461339 1164914
+45	110	127
+2	735	1564
+52	750	11246
+68	4	0
+6
+
+chain 7776 2 243199373 + 1217508 1217592 2 242951149 + 1207753 1207837 7243988
+84
+
+chain 7421 2 243199373 + 1226334 1226411 2 242951149 + 1209439 1209516 27381596
+77
+
+chain 7358 2 243199373 + 89880461 89880538 22 49691432 - 33895115 33895192 27502443
+77
+
+chain 7257 2 243199373 + 1219025 1219100 2 242951149 + 1208570 1208645 27695248
+75
+
+chain 7028 2 243199373 + 1220317 1225128 2 242951149 + 1208603 1209423 1749868
+42	70	0
+111	1961	0
+99	2380	420
+148
+
+chain 6973 2 243199373 + 1223223 1223295 2 242951149 + 1208568 1208640 27324023
+72
+
+chain 6924 2 243199373 + 1220268 1221195 2 242951149 + 1208974 1209200 2111755
+49	743	42
+135
+
+chain 6823 2 243199373 + 243161637 243162225 6 170899992 - 4262 4850 1512
+39	405	405
+56	61	61
+27
+
+chain 6757 2 243199373 + 1224280 1224350 2 242951149 + 1209065 1209135 28694341
+70
+
+chain 6747 2 243199373 + 1219799 1219869 2 242951149 + 1208645 1208715 25148698
+70
+
+chain 6633 2 243199373 + 89847849 89847926 14 106368585 - 28607150 28607227 5517613
+77
+
+chain 6601 2 243199373 + 239685120 239685200 2 242951149 + 239350340 239350540 24829287
+66	1	121
+13
+
+chain 6531 2 243199373 + 89865276 89865345 16 88827254 - 55053025 55053094 29215386
+69
+
+chain 6312 2 243199373 + 111004064 111004130 2 242951149 - 132336069 132336135 211650
+66
+
+chain 6255 2 243199373 + 1226201 1226267 2 242951149 + 1209586 1209652 12280449
+66
+
+chain 6049 2 243199373 + 89847131 89847195 1 247249719 + 184405152 184405216 30439720
+64
+
+chain 6014 2 243199373 + 89850535 89853562 10 135374737 - 96209116 96209251 30527518
+57	2911	19
+59
+
+chain 5970 2 243199373 + 87721480 87727902 2 242951149 + 87501266 87503920 375724
+136	1955	628
+417	2657	546
+67	36	27
+57	474	105
+64	294	290
+36	0	52
+229
+
+chain 5911 2 243199373 + 87725643 87726005 2 242951149 + 87495962 87496324 1452475
+79	29	29
+211	17	17
+26
+
+chain 5902 2 243199373 + 90476920 90476981 2 242951149 - 155440689 155440750 30819911
+61
+
+chain 5764 2 243199373 + 1219128 1219198 2 242951149 + 1208603 1208673 13156733
+70
+
+chain 5625 2 243199373 + 87727023 87727089 2 242951149 + 87494216 87494282 1840679
+66
+
+chain 5449 2 243199373 + 1221033 1223650 2 242951149 + 1208828 1209415 2333010
+27	2353	323
+237
+
+chain 5435 2 243199373 + 87725371 87725531 2 242951149 + 87487864 87488024 3394118
+65	44	44
+51
+
+chain 5351 2 243199373 + 243152496 243152579 21 46944323 - 27 110 6622
+83
+
+chain 5348 2 243199373 + 5153354 5153410 2 242951149 + 239297362 239297418 32407088
+56
+
+chain 5167 2 243199373 + 89830753 89830808 16 88827254 - 55048203 55048258 32968623
+55
+
+chain 5034 2 243199373 + 90484935 90484987 2 242951149 - 155462101 155462153 29809699
+52
+
+chain 5012 2 243199373 + 89872838 89872891 4 191273063 + 48825877 48825930 33453820
+53
+
+chain 4920 2 243199373 + 89890558 89890609 2 242951149 + 89623647 89623698 33788797
+51
+
+chain 4886 2 243199373 + 90477063 90477242 2 242951149 - 155440771 155441314 25803008
+53	75	439
+51
+
+chain 4812 2 243199373 + 89870406 89870457 4 191273063 + 48802771 48802822 34140093
+51
+
+chain 4757 2 243199373 + 234058786 234058836 13 114142980 + 90951015 90951065 34330265
+50
+
+chain 4737 2 243199373 + 5145834 5145884 3 199501827 - 155139362 155139412 33407240
+50
+
+chain 4647 2 243199373 + 1226779 1226827 2 242951149 + 1209604 1209652 34630462
+48
+
+chain 4644 2 243199373 + 111007822 111007876 2 242951149 - 132339823 132339877 533729
+54
+
+chain 4607 2 243199373 + 5145066 5145350 3 199501827 + 191348934 191349218 1967131
+93	45	45
+57	39	39
+50
+
+chain 4552 2 243199373 + 1219473 1219520 2 242951149 + 1208598 1208645 27324024
+47
+
+chain 4467 2 243199373 + 5146638 5146689 8 146274826 + 70047993 70048044 10546953
+51
+
+chain 4382 2 243199373 + 239685380 239685447 2 242951149 + 239350400 239350507 10821439
+47	0	40
+20
+
+chain 4286 2 243199373 + 89847926 89848007 18 76117153 + 56250573 56250654 7293717
+81
+
+chain 4166 2 243199373 + 90482850 90482893 2 242951149 - 155471295 155471338 33373631
+43
+
+chain 4069 2 243199373 + 90483640 90483682 2 242951149 - 155471279 155471321 32448532
+42
+
+chain 4027 2 243199373 + 89848079 89848577 11 134452384 - 130303828 130304326 4308822
+70	372	372
+56
+
+chain 3915 2 243199373 + 89847485 89847537 4 191273063 - 120181520 120181572 9841777
+52
+
+chain 3887 2 243199373 + 1222921 1225400 2 242951149 + 1208756 1209205 3355598
+176	2233	203
+70
+
+chain 3870 2 243199373 + 5146741 5146807 4 191273063 - 106282745 106282811 8233254
+2	4	4
+60
+
+chain 3851 2 243199373 + 243174715 243174760 1 247249719 + 80163 80208 1584
+45
+
+chain 3776 2 243199373 + 1223932 1223971 2 242951149 + 1208577 1208616 29100476
+39
+
+chain 3766 2 243199373 + 1225991 1226030 2 242951149 + 1209516 1209555 18014514
+39
+
+chain 3567 2 243199373 + 89848026 89848188 6 170899992 - 102513053 102513215 4544108
+53	70	70
+39
+
+chain 3456 2 243199373 + 87720895 87724286 2 242951149 + 87506634 87508855 332559
+59	4	143
+126	0	22
+162	9	0
+89	28	26
+108	1252	650
+77	1179	461
+298
+
+chain 3166 2 243199373 + 90482349 90482483 2 242951149 - 155440886 155440924 3921176
+20	96	0
+18
+
+chain 3114 2 243199373 + 1223097 1223130 2 242951149 + 1209002 1209035 21012522
+33
+
+chain 3110 2 243199373 + 1225750 1225960 2 242951149 + 1209065 1209275 3693305
+210
+
+chain 2962 2 243199373 + 16340723 16340754 16 88827254 + 56242121 56242152 7757072
+31
+
+chain 2946 2 243199373 + 1225580 1225611 2 242951149 + 1209315 1209346 16952082
+31
+
+chain 2859 2 243199373 + 243189340 243189373 2 242951149 - 213544 213577 2192
+33
+
+chain 2638 2 243199373 + 5146355 5146383 9 140273252 + 31324189 31324217 27516381
+28
+
+chain 2632 2 243199373 + 87721683 87721719 2 242951149 + 87489021 87489057 886310
+36
+
+chain 2630 2 243199373 + 5144933 5144985 19 63811651 + 23161927 23161979 24515130
+52
+
+chain 2538 2 243199373 + 16338477 16338504 3 199501827 - 154040818 154040845 35425972
+27
+
+chain 2527 2 243199373 + 111053817 111053884 2 242951149 + 110544305 110544372 1691975
+67
+
+chain 2476 2 243199373 + 5146689 5146741 2 242951149 - 88851718 88851770 6471285
+52
+
+chain 2465 2 243199373 + 16260450 16260476 14 106368585 - 56125663 56125689 35442474
+26
+
+chain 2448 2 243199373 + 90475509 90477186 2 242951149 - 155452726 155455668 5069202
+50	704	1477
+39	832	1324
+52
+
+chain 2256 2 243199373 + 89865421 89865445 4 191273063 + 48820096 48820120 35487368
+24
+
+chain 2132 2 243199373 + 90371525 90371566 2 242951149 + 90975643 90975684 3405316
+41
+
+chain 2046 2 243199373 + 87729180 87729211 2 242951149 + 87489147 87489178 2812396
+31
+
+chain 2012 2 243199373 + 16273933 16273955 11 134452384 + 22938127 22938149 7662326
+22
+
+chain 1994 2 243199373 + 5144152 5145822 11 134452384 + 133004933 133006812 2924035
+46	1530	1739
+23	20	20
+51
+
+chain 1907 2 243199373 + 5146585 5146633 1 247249719 - 174030724 174030772 3467396
+48
+
+chain 1894 2 243199373 + 1220990 1221013 2 242951149 + 1208785 1208808 13156732
+23
+
+chain 1847 2 243199373 + 87729147 87729180 2 242951149 + 87508312 87508345 2784752
+33
+
+chain 1616 2 243199373 + 5141194 5141259 4 191273063 + 140068684 140068749 14298254
+65
+
+chain 1606 2 243199373 + 89847307 89847375 6 170899992 + 54305106 54305174 19190580
+68
+
+chain 1373 2 243199373 + 243172974 243173045 8 146274826 + 8401 8472 3798112
+71
+
+chain 1350 2 243199373 + 87719705 87727637 2 242951149 + 87486442 87489057 666335
+5	4	8
+60	6231	0
+175	909	1819
+190	64	64
+294
+
+chain 1237 2 243199373 + 5143151 5144336 3 199501827 - 33955506 33956705 3724972
+50	1070	1084
+65
+
+chain 1182 2 243199373 + 1222834 1225214 2 242951149 + 1208599 1208809 9180420
+46	2248	78
+86
+
+chain 1157 2 243199373 + 87726368 87726988 2 242951149 + 87492753 87493373 434529
+59	53	53
+165	67	67
+36	57	57
+183
+
+chain 1107 2 243199373 + 5141765 5144570 1 247249719 + 5005582 5008225 2100127
+50	2701	2539
+54
+
+chain 1007 2 243199373 + 5142524 5142584 7 158821424 - 115940368 115940428 3379044
+60
+
+chain 998 2 243199373 + 234471343 234471369 18 76117153 + 53315026 53315052 2684166
+26
+
+chain 997 2 243199373 + 1223799 1223839 2 242951149 + 1209424 1209464 2284434
+40
+
+chain 932 2 243199373 + 87725722 87725751 2 242951149 + 87499077 87499106 1733344
+29
+
+chain 867 2 243199373 + 1226560 1226598 2 242951149 + 1209385 1209423 17548334
+38
+
+chain 822 2 243199373 + 5144726 5144801 2 242951149 - 76674151 76674226 3649555
+75
+
+chain 767 2 243199373 + 5141372 5141411 7 158821424 + 51905543 51905582 3310848
+39
+
+chain 651 2 243199373 + 5141336 5141372 5 180857866 - 59015526 59015562 2717102
+36
+
+chain 561 2 243199373 + 5140901 5140953 6 170899992 + 131686128 131686180 4225085
+52
+
+chain 545 2 243199373 + 90414124 90414152 7 158821424 - 94210194 94210222 18407154
+28
+
+chain 270 2 243199373 + 89868258 89868320 Y 57772954 + 11916008 11916070 28746465
+62
+
+chain 5644665978 20 63025520 + 60000 62965520 20 62435964 + 8000 62435964 20
+26259569	3100000	1765661
+234339	150000	1000000
+4004088	1	0
+6459	244	0
+37810	2	0
+1044573	50000	20000
+9411883	8	2
+362	1	0
+11607353	1	0
+1301304	0	1
+31036	9	0
+1151	2	0
+1088	1	1
+29	1	1
+2509	2	0
+407	0	1
+40	1	1
+3787164	50000	27050
+71932	50000	110000
+694117	1	0
+1008033
+
+chain 3228736998 21 48129895 + 10697896 48119895 21 46944323 + 9719767 46944323 23
+490233	3150000	3050000
+19828060	1	0
+8789369	48801	0
+222468	500	500
+22014	1500	1500
+1381822	48641	0
+3438590
+
+chain 2365142 21 48129895 + 9686364 9760752 1 247249719 - 105115380 105189719 169
+453	1	1
+62	1	1
+312	9	9
+152	1	1
+34	1	1
+205	1	1
+109	44	0
+14	7	65
+203	5	5
+26	1	1
+70	1	1
+17	1	1
+847	1	1
+49	1	1
+99	1	1
+87	1	1
+51	1	1
+26	1	1
+374	1	1
+43	0	6
+139	1	1
+128	1	1
+54	1	1
+45	2	0
+17	1	1
+75	1	1
+59	1	1
+210	1	1
+70	1	1
+158	43	43
+56	12	12
+109	1	1
+48	5	5
+116	1	1
+49	1	1
+307	1	1
+45	1	1
+440	5	5
+106	9	9
+784	1	1
+42	1	1
+228	0	1
+114	17	17
+88	11	11
+161	1	1
+38	1	1
+825	2	2
+38	1	1
+105	22	22
+81	1	1
+29	1	1
+300	23	23
+147	1	1
+26	1	1
+164	1	1
+35	1	1
+227	6	6
+56	2	2
+109	1	1
+25	4	0
+116	15	23
+172	1	1
+40	1	1
+68	15	15
+158	7	7
+349	14	14
+133	1	1
+39	1	1
+145	12	12
+60	1	1
+43	1	1
+101	21	21
+307	1	1
+42	1	1
+93	1	1
+162	1	1
+143	1	1
+40	1	1
+54	1	1
+107	9	10
+319	1	1
+43	4	4
+200	1	1
+18	1	1
+127	1	1
+90	1	1
+250	3	3
+93	148	1
+443	0	1
+77	9	9
+295	1	1
+59	1	1
+438	31	31
+127	3	0
+88	1	1
+109	7	8
+79	14	14
+112	10	8
+114	1	1
+94	1	1
+150	10	7
+69	1	1
+110	1	1
+17	1	0
+222	0	1
+195	1	1
+16	1	0
+89	1	1
+123	38	0
+43	1	1
+83	1	1
+47	3	4
+64	0	3
+38	1	1
+268	1	1
+27	1	1
+230	17	17
+252	1	1
+24	0	3
+168	1	1
+41	5	0
+50	1	1
+212	9	9
+40	29	0
+271	1	1
+48	1	1
+124	1	1
+57	1	1
+125	16	16
+136	29	29
+157	1	1
+27	7	0
+482	10	4
+158	1	1
+62	1	1
+371	1	1
+83	1	1
+120	1	1
+45	1	1
+189	0	1
+84	1	1
+103	18	18
+494	1	1
+55	3	0
+139	1	1
+264	18	18
+75	2	3
+130	1	1
+97	1	1
+193	1	1
+25	1	1
+167	1	1
+49	1	1
+62	16	16
+65	13	13
+62	1	1
+101	1	1
+60	1	1
+50	1	1
+307	9	9
+131	13	13
+94	1	1
+78	1	1
+132	1	1
+27	1	1
+358	1	1
+21	1	1
+466	14	14
+590	1	1
+34	1	1
+242	1	1
+29	1	1
+116	1	1
+44	1	1
+117	1	1
+67	2	1
+71	1	1
+32	1	1
+506	18	18
+88	1	1
+27	1	1
+78	0	11
+215	1	1
+77	1	1
+291	1	1
+56	3	3
+126	1	1
+42	1	1
+332	9	9
+280	6	9
+641	15	15
+59	6	10
+31	1	1
+62	1	1
+40	1	1
+298	1	1
+40	1	1
+146	1	1
+66	1	0
+757	2	0
+169	1	1
+65	1	0
+285	1	1
+20	1	1
+109	1	1
+67	1	1
+68	1	1
+32	1	1
+93	4	4
+147	0	14
+646	0	1
+544	8	8
+47	1	0
+141	14	14
+678	1	0
+154	0	1
+346	1	1
+73	1	1
+232	5	5
+113	1	1
+32	2	0
+23	1	1
+92	10	10
+1121	1	1
+143	1	1
+300	1	1
+49	1	1
+392	5	5
+242	1	1
+21	1	1
+369	1	1
+67	1	1
+47	0	1
+618	23	23
+565	1	1
+140	1	1
+247	1	1
+41	1	1
+50	1	1
+18	1	1
+65	1	1
+66	1	1
+108	0	4
+158	1	1
+105	1	1
+70	1	1
+25	6	8
+77	1	1
+323	1	1
+28	1	1
+258	1	1
+47	1	1
+393	1	1
+72	1	1
+149	13	13
+142	1	0
+60	0	1
+78	4	4
+100	1	1
+51	1	1
+156	1	1
+20	1	1
+510	1	1
+22	1	0
+67	1	1
+54	1	1
+45	1	1
+133	1	1
+23	1	1
+63	1	1
+32	1	1
+349	1	1
+15	1	1
+103	1	1
+36	1	1
+119	1	1
+47	1	1
+312	4	4
+66	13	13
+357	0	76
+20	1	1
+177	1	1
+91	1	1
+52	1	1
+36	1	1
+141	10060	10099
+90	1	1
+49	1	1
+212	1	1
+20	1	1
+286	1	1
+48	2	1
+50	1	1
+67	8	8
+63	1	1
+30	1	1
+93	1	1
+48	1	1
+129	1	1
+46	1	1
+455	1	1
+46	3	0
+84	1	1
+39	0	1
+229	2	11
+79	4	4
+731	17	16
+725	8	8
+249	1	1
+78	1	1
+1065	3	0
+735	0	1
+124	10	10
+51	1	1
+35	1	1
+315	25	25
+749	6	6
+343	1	1
+29	1	1
+386	1	1
+24	1	1
+407	1	0
+73	1	1
+708	1	1
+71	0	1
+16	1	1
+92	1	1
+25	1	1
+447	14	14
+190	85	85
+60	1	1
+66	1	1
+238	1	1
+87	5	5
+118	7	7
+696	0	12
+49	1	1
+823	1	1
+77	1	1
+154	0	3
+102	12	12
+698	1	1
+21	1	1
+591	1	1
+16	1	1
+59	1	1
+27	1	1
+114	1	0
+593	1	1
+30	1	1
+1351	1	1
+17	1	1
+77	6	0
+647	1	1
+23	1	1
+235	1	1
+39	1	1
+141	1	1
+80	5	5
+181	10	11
+1091	1	1
+58	0	1
+19	1	1
+305	0	1
+429	17	17
+107	1	1
+25	1	1
+156	5	5
+22	1	1
+188
+
+chain 3320966530 22 51304566 + 16050000 51244566 22 49691432 + 14430000 49591432 22
+647850	150000	150000
+3661581	100000	50000
+15278437	18	0
+294	36	0
+1407	1	1
+46	1	1
+6626947	4	2
+1759	1	1
+43	1	1
+1367363	10613	11998
+7858	0	4
+809337	20	0
+6305	0	20
+6703	2669	50000
+4247674	0	10618
+1611	2719	0
+35235	131	0
+12642	0	4
+45595	9	85
+19564	506	0
+165499	7	5
+1103946	60575	16700
+644	2	0
+319796	1155	1600
+17927	15406	19700
+464629
+
+chain 11044 22 51304566 + 50772606 50772840 1 247249719 + 28744016 28744317 20648865
+55	103	170
+76
+
+chain 18404394637 3 198022430 + 60000 197962430 3 199501827 + 35000 199446827 3
+13552792	0	1
+585083	0	1
+2092	1	2
+71	0	1
+31067262	0	1
+90	1	0
+5628461	0	15
+788	1	0
+3676	0	2
+35	1	1
+4682	1	0
+1295	0	5
+437	53	42
+326	0	2
+3309	1	1
+40	1	1
+998	0	3
+3584	5	0
+930	5	7
+845	1	1
+28	2	1
+303	0	1
+507	0	5
+5088	1	0
+2185	10046	10048
+949	4	4
+35	1	1
+2874	0	1
+6717	0	1
+2823	1	0
+703	0	4
+5143	1	0
+2490	10	10
+162	7	7
+6308	0	15
+15177535	152352	260003
+2532	1	0
+1633	2	2
+24207544	3000000	4400000
+60453436	0	4
+40076813	20999	20000
+8195	1	1
+44	1	1
+1408	1	1
+33	1	1
+172	3	4
+25	1	1
+538	13	13
+173	1	1
+27	1	1
+636	1	1
+28	1	1
+470	3	3
+112	1	1
+375	1	1
+26	26	0
+115	78	0
+52	23	0
+104	26	0
+15	231	0
+56	1	1
+20	1	1
+815	16	16
+484	1	1
+49	18	0
+509	4	3
+23	1	1
+391	1	1
+44	1	1
+1278	0	4
+32	1	1
+263	4	0
+27	1	1
+2416	0	2
+3184	43	43
+1150	13	13
+736	1	1
+47	1	1
+1416	1	1
+20	1	1
+1020	1	1
+25	1	1
+482	5	0
+716	1	0
+1697	1	1
+29	1	1
+1270261	23108	27000
+40930	1	0
+17455	1	1
+28	4	4
+43	0	491
+1679	1	1
+33	7	5
+29	1	3
+54863	53	16
+7653	2	2
+29	2	2
+15	0	30
+180	0	75
+215	45	0
+360	915	0
+6188	96	0
+17	288	0
+1388	1	1
+37	1	1
+7956	0	1
+374	0	1
+2442058
+
+chain 905554 3 198022430 + 50925386 50935027 3 199501827 - 148591827 148601470 3167
+1111	0	6
+2584	0	1
+5889	6	1
+51
+
+chain 274603 3 198022430 + 195356374 195379482 3 199501827 - 629997 657219 690
+621	1	1
+42	1	1
+893	1	121
+66	1	1
+693	1	1
+27	1	1
+761	1	1
+79	2	2
+297	1	1
+40	1	1
+643	1	1
+22	1	1
+410	8	9
+110	1	1
+16	0	5
+314	3	0
+1846	4	7
+39	1	1
+420	10	9
+335	6	0
+238	0	1
+76	1	0
+310	1	2
+175	1	1
+17	1	1
+268	1	1
+46	1	1
+114	1	1
+19	1	1
+127	8	8
+30	1	1
+207	6	6
+62	9	9
+505	22	22
+160	1	1
+34	1	1
+187	1	1
+138	0	1
+844	1	1
+103	0	1
+65	3459	3402
+90	4	4
+90	42	794
+52	478	4
+78	154	154
+28	235	0
+59	1501	5454
+143	19	19
+425	7	54
+39	46	0
+75	8	8
+73	1	95
+58	1	1
+51	16	63
+140	1	1
+33	1	1
+682	1	1
+68	1	1
+147	1	1
+82	1	1
+119	33	0
+262	0	1
+54	1	0
+13	56	0
+111	5	5
+722	1	1
+19	1	1
+60	1	1
+33	1	0
+7	1	1
+108	0	2
+302	1	1
+68	1	0
+42	1	1
+50	1	1
+80	1	0
+95	1	1
+19	1	1
+119	0	1
+493	16	16
+316
+
+chain 30227 3 198022430 + 66156466 66156782 5 180857866 - 15729243 15729559 4617547
+316
+
+chain 25764 3 198022430 + 195503126 195503723 3 199501827 + 196988790 196989012 1952307
+75	360	0
+127	20	5
+15
+
+chain 19039 3 198022430 + 195503723 195504023 3 199501827 + 196988637 196988937 1894839
+300
+
+chain 11786 3 198022430 + 195373997 195374119 3 199501827 - 651916 652038 19355983
+122
+
+chain 9624 3 198022430 + 195503246 195503561 3 199501827 + 196988205 196988400 2003832
+53	137	2
+73	4	19
+48
+
+chain 7908 3 198022430 + 195510214 195510615 3 199501827 + 196993313 196993714 919394
+96	17	17
+288
+
+chain 6921 3 198022430 + 66275488 66275560 6 170899992 + 144236219 144236291 28346484
+72
+
+chain 6012 3 198022430 + 66274973 66275036 15 100338915 - 38411650 38411713 30540003
+63
+
+chain 5039 3 198022430 + 66276813 66276866 9 140273252 + 71084115 71084168 33364454
+53
+
+chain 4902 3 198022430 + 66152713 66152764 11 134452384 + 5803379 5803430 33869306
+51
+
+chain 3381 3 198022430 + 195371524 195371562 3 199501827 - 645118 645156 13662757
+38
+
+chain 3356 3 198022430 + 50925108 50925187 3 199501827 - 92152745 92152824 20266108
+79
+
+chain 2109 3 198022430 + 195371614 195371638 3 199501827 - 645161 645185 16027164
+24
+
+chain 1800 3 198022430 + 195503201 195503246 3 199501827 + 196989165 196989195 4219824
+23	17	2
+5
+
+chain 1295 3 198022430 + 195372257 195372308 3 199501827 - 2286585 2286636 21843906
+51
+
+chain 17653654354 4 191154276 + 10000 191029082 4 191273063 + 0 191263063 4
+1413146	71672	51000
+5369	6	5
+65	1	1
+67	1	1
+425	1	1
+32	1	1
+175	1	1
+34	1	1
+5092	1	1
+46	1	1
+1396	15	15
+1446	1	0
+1679	13	13
+3443	0	1
+586	1	1
+38	1	1
+18	21	0
+1582	6	0
+202	3	0
+92	0	6
+187	9	0
+4054	1	1
+71	1	1
+1413	1	83
+51	7	7
+105	7	7
+53	0	41
+81	1	42
+41	0	41
+37	0	41
+3274	1	94
+114	0	1116
+921	2	0
+935	0	55
+3639	15	15
+1167	0	3
+44	29	0
+44	0	29
+5146	1	1
+42	1	1
+3831	3	0
+23	1	1
+4171	6	6
+796	165	0
+196	99	0
+94	33	0
+183	8	6
+107	2	2
+21	2	0
+62	68	1
+32	15	14
+81	18	18
+55	1	0
+17	67	1
+188	133	0
+44	67	0
+43	35	0
+3289	18	18
+298	1	0
+373	1	0
+2965	1	1
+30	23	0
+1718	38	0
+98	38	0
+53	44	7
+116	0	77
+272	1	1
+70	1	1
+1591	49	49
+360	33	23
+2400	1	1
+94	1	1
+6002	1	1
+16	1	1
+776	0	1
+324	46	46
+433	0	51
+53	27	1
+2181	4	1
+57	1	1
+1969	0	10
+4188	11	11
+1595	18	0
+2050	109	0
+4319	7	0
+50	4	0
+1464	1	3
+4156	0	2
+5455	2	3
+129	4	4
+9082	1	0
+786	20	20
+1506	1	0
+252	7	8
+17512	1	50
+56	0	1
+2474	52	69
+75	30	0
+61	0	16
+11	0	15
+41	1	1
+133	0	16
+79	17	0
+16	29	0
+3375	1	0
+969	4	0
+1623	11	11
+1065	3	0
+2934	0	8
+2323	181	0
+2290	0	1
+1641	1	6
+1955	1	0
+68	1	1
+347	1	1
+40	1	1
+1553	0	6
+678	16	16
+92	33	0
+390	0	4
+1147	1	0
+1948	4	4
+4296	1	1
+16	1	1
+955	1	1
+47	1	1
+1555	0	1
+2251509	0	81122
+171	1	1
+48	1	1
+718	0	1
+2789	1	1
+27	1	1
+1601	0	4
+1907	2	0
+31	1	5
+16	0	4
+76	2	0
+13	4	0
+27	1	0
+12	1	9
+1772	6	0
+22	1	1
+946	1	1
+24	1	1
+1245	0	1
+3231	1	1
+41	1	1
+736	4	4
+912	1	1
+18	1	1
+11270	0	3
+2704	1	1
+41	1	1
+1812	6	5
+1477	11	0
+1744	6	6
+2039	0	4
+2188	1	1
+48	1	1
+1704	1	1
+73	1	1
+2265	12	12
+553	1	1
+49	1	1
+67	1	1
+33	1	1
+3935	0	5
+15	0	1
+780	1	0
+1260	1	0
+4204	25	0
+862	14	14
+7114	1	1
+70	1	1
+169	1	0
+43	1	1
+145	1	1
+39	3	0
+8	1	1
+753	1	0
+1535	41	41
+679	1	1
+21	1	1
+1605	1	1
+19	1	2
+392	1	1
+29	0	1
+3673	0	1
+145	14	14
+39	1	0
+1246	1	0
+2302	0	1
+1554	9	9
+4537	1	0
+1064	0	2
+2051	0	1
+1130	2	0
+164	0	1
+1972	1	0
+18	3	3
+2597	1	1
+46	3	3
+196	1	1
+17	1	1
+60	4	4
+187	4	4
+46	1	1
+692	0	1
+3382	41	41
+497	3	3
+15	1	1
+486	14	14
+1709	0	8
+169	0	1
+597	1	1
+18	7	0
+3423937	1	0
+1295496	1	1
+26	1	1
+760	591802	150000
+22468468	1	1
+27	1	1
+2592	2	0
+33	1	1
+2065	0	3
+1050	11	11
+1046	9	3
+3263	0	1
+906	0	1
+1643	0	6
+1181	1	0
+475	5	0
+2522	0	4
+407	1	0
+517	77	77
+1122	36199	70999
+976587	26528	59000
+7703	4	0
+4545	9	9
+4740	1	0
+1862	0	1
+3316	3	7
+51	14	14
+1066	1	0
+1795	0	1
+569	0	1
+2895	1	1
+39	1	1
+461	0	3
+3168	6	6
+2197	0	1
+6774	2	0
+2504	2	0
+1247	1	1
+45	1	1
+2415	17	17
+4792	36	36
+3387	20	20
+272	10	10
+420	1	1
+34	1	1
+7961	0	4
+1973	1	1
+45	0	1
+529	0	1
+603	1	0
+18	1	1
+606	4	0
+65	1	25
+41	0	8
+517	1	0
+1400	41	38
+3786	1	0
+228	0	3
+1026	1	1
+49	1	1
+3336	3	0
+951	1	1
+77	1	2
+441	2	1
+1833	9	9
+301	5	5
+2787	17	17
+1747	0	1
+3040	9	2
+81	10	10
+86	0	2
+2113	45	45
+7352791	1606	20000
+1651	0	2
+45	16	0
+13956	8	0
+1947	3	0
+1255	1	1
+38	1	0
+1778	4	0
+22	1	0
+1045	0	6
+1327	1	0
+5775	1	1
+18	1	1
+1933	0	1
+1716	13	13
+255	0	1
+124	3	0
+792	5	0
+1521	1	1
+64	1	1
+9005617	150000	150000
+171176	3000000	3000000
+7074452	62111	50000
+5257	1	0
+2845	0	2
+1387	1	0
+114	0	1
+2385	4	0
+65	6	6
+62	0	4
+18	1	0
+100	51	0
+9781577	0	351994
+1903288	0	184275
+3925704	13	13
+435	1	1
+21	1	1
+838	1	0
+281	35	35
+491	6	6
+74	1	1
+43	1	1
+652	29839	30000
+13847966	1	0
+14069801	0	2
+8504	1	0
+32265	0	8
+12730	2	0
+35327	14	12
+1503	0	1
+1334	0	1
+759	1	0
+10036	1	7
+9912	17	18
+2523	0	1
+1321	1	0
+8984	0	2
+5505	20	20
+9694	6	6
+22003	0	9
+578	1	0
+5166	0	2
+92208	5	2
+8	0	1
+5	2	0
+110	0	4
+848	7	6
+2247	1	3
+3770	1	0
+5719	2	0
+2511	1	0
+1557	1	0
+5812	1	0
+3607	1	0
+7405	0	1
+11075	1	0
+2794	0	1
+2340	0	1
+429	1	0
+233	27	27
+262	0	2
+2397	0	5
+371	0	11
+1376	0	1
+2416	0	8
+210	1	1
+20	1	1
+5104	1	1
+20	1	1
+525	0	2
+836	1	0
+2094	0	1
+2213	0	3
+327	6	9
+1711	45	45
+837	1	1
+57	1	1
+1618	1	0
+1400	0	4
+254	2	0
+93	0	10
+755	6	0
+192	1	0
+2378	1	0
+1753	0	3
+644	14	14
+1244	4	0
+30	1	1
+1136	14	14
+2450	0	4
+3624	3	31
+456	14	14
+1076	8	7
+68	1	1
+20	1	1
+145	1	1
+68	0	1
+12	1	0
+10	1	0
+11	0	1
+35	0	1
+5	1	0
+11	2	1
+32	7	6
+35	0	1
+8722	0	1
+888	4	0
+456	0	3
+45	1	0
+151	13	13
+756	1	0
+203	7	8
+140	1	1
+20	1	1
+308	0	5
+1020	1	0
+1258	1	0
+160	2	0
+1411	1	1
+22	1	1
+1180	12	12
+4521	2	0
+1153	0	27
+4956	0	3
+1392	1	1
+47	1	1
+3854	1	2
+130	0	1
+2633	0	2
+3030	1	0
+2343	1	0
+1748	45	0
+731	0	2
+1336	11	9
+3899	6	0
+436	0	1
+981	1	0
+1326	1	0
+382	0	4
+1081	0	10
+81	1	1
+142	2	0
+5976	1	1
+26	1	1
+377	22	22
+86	1	0
+55	1	1
+93	1	1
+374	4	0
+38	6	0
+3944	0	347
+1034	1	1
+27	1	1
+60	0	2
+2581	0	3
+3882	4	0
+1790	1	0
+20	1	1
+356	0	1
+4244	5	5
+36	1	1
+2232	2	2
+42	1	1
+4462	2	0
+1611	0	1
+1290	2	0
+110	0	1
+1466	1	0
+357	0	3
+850	0	12
+13547766	1	0
+3724943	0	2
+46473408	1	0
+1696	1	1
+28	1	1
+1629	4	0
+666	0	4
+13464	12874	30000
+8520008	0	2
+1107	1	1
+15	1	1
+1892	4	0
+6798	2	0
+1793	1	1
+25	3	0
+421	0	389
+787	0	2
+545	2	0
+54	0	1
+143	1	1
+39	1	1
+89	1	1
+29	0	1
+171	1	1
+46	0	1
+192	1	1
+33	1	1
+336	18	18
+2226	1	0
+107	1	1
+29	1	1
+218	0	1
+175	5	6
+1407	1	1
+52	1	1
+8851	0	1
+14427	0	4
+1737	0	22
+5806	0	1
+1115	1	1
+29	2	0
+3395	1	0
+386	38	38
+2740	2	0
+522	0	1
+24	1	1
+658	0	4
+5724	9	9
+1209	1	0
+5380	0	1
+97	0	1
+853	0	4
+79	11	5
+2728	7	6
+3754	13	17
+1363	0	1
+1025	0	1
+1811	1	0
+7507	4	0
+1184	0	3
+763	0	1
+797	0	3
+293	0	2
+2488	1	0
+335	1	0
+9959	0	1
+3255	0	1
+1322	1	0
+8118	0	2
+3326	0	2
+632	0	1
+63	5	0
+1886	12	12
+1110	1	0
+9582	1	0
+14742673	3013	0
+39686
+
+chain 1255876 4 191154276 + 9214880 9257600 4 191273063 + 8933741 8943231 721
+156	22	22
+1030	14	14
+303	27	27
+166	4935	184
+220	23	24
+72	54	54
+771	13	13
+270	4744	0
+2627	17	17
+289	4743	0
+890	4745	0
+772	9500	0
+268	4749	1
+266	11	11
+1023
+
+chain 912330 4 191154276 + 9211690 9265763 4 191273063 + 8940042 8979863 947
+75	220	220
+51	122	122
+54	54	54
+51	167	167
+180	47	47
+70	24	24
+94	37	37
+257	59	59
+316	11	11
+163	60	60
+53	61	61
+95	21	21
+109	24	24
+217	32	32
+186	47	47
+233	1926	1924
+88	13	13
+123	125	126
+1453	4747	0
+2227	0	1
+278	535	535
+213	87	87
+92	7	7
+755	18715	9222
+268	6439	6434
+1089	14	14
+243	9	9
+78	4	4
+157	214	209
+200	23	24
+72	5972	5972
+655	413	413
+1441	14	14
+243	9	9
+78	4	4
+157	213	209
+200	23	24
+72	54	54
+771	13	13
+119	17	17
+221
+
+chain 676976 4 191154276 + 191033807 191044200 4 191273063 - 191263147 191273063 1558
+68	4	0
+34	1	1
+323	3	3
+31	1	1
+807	1	1
+26	1	1
+526	2	3
+34	1	0
+704	1	0
+6	1	0
+240	1	0
+237	2	0
+8	1	1
+371	10	0
+264	1	0
+205	1	1
+57	1	0
+601	1	1
+15	1	1
+1214	4	8
+1661	3	0
+94	1	1
+50	1	1
+355	15	15
+638	1	1
+54	1	1
+54	8	9
+323	67	9
+85	0	1
+96	1	1
+58	1	1
+35	1	0
+31	1	1
+86	1	1
+30	1	1
+76	1	1
+40	1	1
+121	282	27
+49	53	0
+63	92	0
+52
+
+chain 512088 4 191154276 + 8956990 9037962 4 191273063 + 9100119 9179836 26299
+71	118	113
+60	152	152
+88	33	33
+136	71	71
+85	43	43
+87	66	66
+92	87	87
+88	187	185
+156	1	81
+67	128	129
+76	143	143
+50	44	44
+212	52	52
+64	13	16
+267	79	79
+284	58	58
+51	76	76
+51	94	91
+55	77	77
+95	15	15
+74	251	251
+116	107	28
+64	188	188
+77	4	4
+113	11	11
+62	44	44
+102	237	237
+154	79	79
+58	86	86
+53	39	39
+50	36	35
+412	36	36
+75	225	225
+313	30	30
+54	84	83
+69	156	147
+104	89	77
+54	162	162
+226	16	16
+95	26	26
+60	14	14
+59	8	8
+120	7	7
+162	67	67
+65	210	210
+112	204	203
+63	53	53
+50	140	139
+127	143	143
+149	97	97
+88	61282	60044
+56	370	381
+50	56	56
+84	370	368
+52	288	288
+54	25	25
+72	923	933
+55	768	765
+68	70	70
+52	196	196
+62	305	305
+50	43	43
+129	114	114
+53	66	65
+116	411	423
+58	314	324
+68	0	1
+123	0	1
+53	58	59
+116	401	399
+539	6	0
+397	18	18
+60	211	211
+55	175	175
+63	553	556
+55	10	10
+53	1024	1003
+58	34	34
+81	43	43
+75	9	9
+51	1	0
+69
+
+chain 476298 4 191154276 + 9230645 9271936 4 191273063 + 8940012 8967053 893
+192	87	88
+429	187	187
+754	4750	6
+744	23	25
+2003	14	14
+246	42	42
+74	48	48
+71	104	104
+291	226	226
+81	4533	4529
+47	562	562
+111	285	285
+89	35	35
+2637	17	17
+240	9	9
+78	4	4
+157	215	209
+179	17	17
+100	4802	54
+343	13	13
+785	10920	6171
+1114	17	17
+243	6	6
+58	2	1
+272	1	0
+404	10	10
+1194	31	31
+266	11	11
+770	21	21
+327
+
+chain 377656 4 191154276 + 9257600 9267189 4 191273063 + 8933740 8938580 708
+1209	17	17
+571	1	0
+1617	4779	31
+1395
+
+chain 310844 4 191154276 + 9241835 9252105 4 191273063 + 8941714 8947231 850
+2726	14	14
+243	9	9
+78	4	4
+157	213	211
+265	85	85
+524	4751	0
+379	283	283
+539
+
+chain 275688 4 191154276 + 190986479 190989396 4 191273063 + 191223755 191226674 1129
+58	2	0
+265	1	0
+205	0	1
+208	4	5
+205	1	0
+122	55	53
+54	0	1
+411	25	25
+282	1	0
+419	14	20
+585
+
+chain 164691 4 191154276 + 9225860 9240813 4 191273063 + 8954210 8973910 1376
+232	87	87
+216	5946	5946
+93	12	12
+116	46	46
+231	32	32
+884	2511	7257
+718	3769	3770
+60
+
+chain 136190 4 191154276 + 9219745 9221340 4 191273063 + 8971822 8973417 7780
+1090	14	14
+243	9	9
+78	80	80
+81
+
+chain 127110 4 191154276 + 9223074 9241806 4 191273063 + 8960913 8979648 1585
+266	11	11
+4	10400	10401
+206	20	21
+668	26	27
+395	17	17
+14	6682	6682
+23
+
+chain 113888 4 191154276 + 59794841 59796661 7 158821424 + 43068053 43069865 1124766
+203	13	13
+161	140	141
+116	42	42
+240	178	178
+142	63	63
+254	11	11
+90	67	58
+100
+
+chain 91306 4 191154276 + 9218608 9227700 4 191273063 + 8961194 8975031 2525
+1019	3329	8072
+118	4492	4494
+89	35	35
+10
+
+chain 70288 4 191154276 + 9018276 9021043 11 134452384 - 130908986 130911761 1790585
+117	359	362
+150	330	330
+55	237	237
+99	73	73
+100	253	253
+70	73	78
+137	311	312
+72	249	248
+82
+
+chain 69967 4 191154276 + 8969559 8971297 11 134452384 - 66940622 66942298 1798470
+59	244	176
+78	49	49
+76	0	4
+72	217	218
+85	102	102
+264	12	12
+52	246	247
+66	24	24
+92
+
+chain 66013 4 191154276 + 9271936 9272654 4 191273063 + 8948073 8948792 572417
+692	0	1
+26
+
+chain 45624 4 191154276 + 9079872 9084019 4 191273063 - 187198263 187202501 2810559
+137	1640	1673
+114	79	83
+52	281	281
+64	700	698
+99	226	253
+83	576	605
+96
+
+chain 42774 4 191154276 + 9272654 9274373 4 191273063 + 8958282 8960000 1428
+395	17	17
+243	6	6
+329	3	2
+726
+
+chain 41852 4 191154276 + 9086638 9087081 1 247249719 - 105679719 105680162 3102182
+443
+
+chain 32596 4 191154276 + 9003477 9005348 8 146274826 + 6937943 6939835 4188535
+92	357	358
+96	443	443
+52	521	541
+122	129	129
+59
+
+chain 27953 4 191154276 + 9001038 9001387 11 134452384 - 130891915 130892264 5650797
+153	24	24
+85	11	11
+76
+
+chain 25460 4 191154276 + 1547039 1548332 4 191273063 + 1517808 1518962 1406869
+132	196	194
+8	33	0
+58	94	94
+33	400	430
+53	219	85
+67
+
+chain 23919 4 191154276 + 9060276 9060815 X 154913754 - 61464264 61464816 7738233
+150	249	262
+51	8	8
+81
+
+chain 23663 4 191154276 + 9250380 9252971 4 191273063 + 8954996 8957588 1596
+343	1382	1382
+494	21	21
+330	20	21
+1
+
+chain 23348 4 191154276 + 8954155 8955149 13 114142980 + 67377165 67378170 8084807
+108	119	119
+58	448	459
+78	128	128
+55
+
+chain 23051 4 191154276 + 9178657 9179321 8 146274826 - 138181840 138182484 8260527
+67	301	281
+58	86	86
+152
+
+chain 21854 4 191154276 + 9064978 9065877 1 247249719 + 159299736 159300622 9096955
+140	389	376
+61	239	239
+70
+
+chain 20302 4 191154276 + 59794670 59795934 19 63811651 - 51831683 51832948 1313667
+101	447	447
+6	69	70
+65	116	116
+17	4	4
+21	351	351
+67
+
+chain 19591 4 191154276 + 9123525 9124535 8 146274826 - 133912952 133913964 10789494
+68	696	699
+88	66	65
+92
+
+chain 17609 4 191154276 + 9152849 9153208 8 146274826 - 133934464 133934826 12466518
+149	157	160
+53
+
+chain 17420 4 191154276 + 9097653 9099623 11 134452384 - 51628045 51630034 12637575
+61	831	818
+58	894	926
+126
+
+chain 17154 4 191154276 + 8944061 8944687 3 199501827 - 68270290 68270918 12891537
+94	361	363
+56	52	52
+63
+
+chain 16449 4 191154276 + 9179756 9180625 8 146274826 + 7630543 7631403 13585678
+50	232	222
+54	427	428
+106
+
+chain 16159 4 191154276 + 9066614 9068459 16 88827254 - 83675354 83677175 13878826
+62	1020	1018
+99	597	575
+67
+
+chain 16115 4 191154276 + 9109381 9109952 21 46944323 + 28460282 28460853 13923553
+84	119	119
+62	249	249
+57
+
+chain 15306 4 191154276 + 8980490 8981996 4 191273063 - 187061282 187061823 14745791
+66	1267	302
+72	36	36
+65
+
+chain 15299 4 191154276 + 9056645 9056806 7 158821424 - 61471183 61471344 14752363
+161
+
+chain 14776 4 191154276 + 8950227 8950452 10 135374737 - 120304145 120304370 15312555
+84	55	55
+86
+
+chain 14403 4 191154276 + 9126194 9127408 5 180857866 - 26856190 26857401 15732261
+94	264	256
+54	752	757
+50
+
+chain 14224 4 191154276 + 8969618 8970298 11 134452384 - 67220551 67221216 1931088
+4	94	93
+78	397	383
+107
+
+chain 14155 4 191154276 + 9145781 9146043 X 154913754 - 45908091 45908403 16013758
+81	98	148
+83
+
+chain 14099 4 191154276 + 9060197 9060675 3 199501827 + 53477967 53478452 7798477
+58	172	171
+90	137	145
+21
+
+chain 13997 4 191154276 + 9005833 9006439 8 146274826 - 139204211 139204817 16201090
+60	438	438
+108
+
+chain 13823 4 191154276 + 8945988 8946280 4 191273063 + 9373057 9373350 16411372
+60	133	134
+99
+
+chain 13439 4 191154276 + 8975637 8975779 3 199501827 + 126919507 126919649 16900342
+142
+
+chain 12765 4 191154276 + 9077064 9077200 1 247249719 - 177698311 177698447 17836871
+136
+
+chain 12497 4 191154276 + 8950452 8951505 4 191273063 - 187091946 187092996 17010995
+3	953	950
+97
+
+chain 12348 4 191154276 + 8983189 8983604 8 146274826 - 138673776 138674197 18460871
+61	268	274
+86
+
+chain 11880 4 191154276 + 8972496 8973020 14 106368585 - 55089898 55090495 19186930
+61	378	451
+85
+
+chain 11818 4 191154276 + 9096126 9096305 11 134452384 - 67086036 67086266 19295429
+55	42	93
+82
+
+chain 11496 4 191154276 + 8948423 8949198 12 132349534 + 50778185 50778960 19846856
+94	629	629
+52
+
+chain 11391 4 191154276 + 8947143 8947401 8 146274826 - 134472454 134472711 20027902
+53	123	122
+82
+
+chain 11111 4 191154276 + 9107828 9107946 16 88827254 + 2897686 2897804 20531108
+118
+
+chain 10916 4 191154276 + 9261701 9262066 4 191273063 + 8952078 8952443 1072
+365
+
+chain 10832 4 191154276 + 8994164 8994326 6 170899992 - 100664994 100665156 21051510
+55	36	36
+71
+
+chain 10756 4 191154276 + 8943247 8943361 4 191273063 + 9116977 9117091 21193988
+114
+
+chain 10679 4 191154276 + 191030273 191030443 3 199501827 + 127002379 127002551 21342971
+68	44	46
+58
+
+chain 10668 4 191154276 + 1582572 1582681 4 191273063 + 1552756 1552865 12282737
+109
+
+chain 10529 4 191154276 + 191032229 191032410 11 134452384 + 3430296 3430477 21654608
+64	55	55
+62
+
+chain 10273 4 191154276 + 9096703 9097008 3 199501827 + 187858881 187859186 22199926
+64	181	181
+60
+
+chain 10137 4 191154276 + 9099965 9100095 6 170899992 - 166526436 166526567 22497437
+61	12	13
+57
+
+chain 10052 4 191154276 + 9066676 9066805 10 135374737 - 108696851 108696974 16846521
+41	9	9
+20	6	0
+53
+
+chain 9949 4 191154276 + 8999157 8999260 6 170899992 + 1823421 1823524 22925909
+103
+
+chain 9823 4 191154276 + 9071238 9072065 19 63811651 - 22299002 22299820 23218142
+65	697	688
+65
+
+chain 9746 4 191154276 + 8950613 8951219 7 158821424 - 151976579 151977185 23399634
+66	481	481
+59
+
+chain 9713 4 191154276 + 9012936 9013126 X 154913754 + 119487462 119487653 23485630
+58	74	75
+58
+
+chain 9679 4 191154276 + 9083038 9083589 12 132349534 + 77527128 77527707 10056562
+24	185	212
+17	262	263
+63
+
+chain 9579 4 191154276 + 9105290 9105637 8 146274826 - 6609 6954 23801877
+63	229	227
+55
+
+chain 9552 4 191154276 + 8956536 8957179 8 146274826 - 139187457 139188099 13944787
+92	234	234
+51	240	239
+26
+
+chain 9532 4 191154276 + 8978497 8978597 21 46944323 - 3695413 3695513 23932747
+100
+
+chain 9412 4 191154276 + 9108273 9108605 2 242951149 + 34780701 34781033 24211634
+61	216	216
+55
+
+chain 9361 4 191154276 + 9207159 9207725 7 158821424 + 92958588 92959148 24306771
+65	445	439
+56
+
+chain 9304 4 191154276 + 8946418 8946780 13 114142980 + 45938942 45939304 24422281
+63	247	247
+52
+
+chain 9136 4 191154276 + 9129485 9129655 1 247249719 - 82404984 82405154 24736407
+59	59	59
+52
+
+chain 9105 4 191154276 + 8982741 8983189 10 135374737 - 120304868 120305301 22041837
+59	380	365
+9
+
+chain 8777 4 191154276 + 9118310 9118402 11 134452384 - 67092191 67092283 25280535
+92
+
+chain 8617 4 191154276 + 59794359 59794524 X 154913754 + 69736929 69737094 2995761
+75	86	86
+4
+
+chain 8389 4 191154276 + 9219628 9219725 4 191273063 + 8933741 8933838 871949
+97
+
+chain 8260 4 191154276 + 8989895 8989983 4 191273063 + 9362532 9362620 26013719
+88
+
+chain 8131 4 191154276 + 9102626 9102711 4 191273063 - 187087880 187087965 26219988
+85
+
+chain 7754 4 191154276 + 190986383 190986479 10 135374737 + 135327923 135328019 562
+96
+
+chain 7688 4 191154276 + 8999849 9001530 8 146274826 + 7459813 7461495 7287525
+76	15	15
+50	236	236
+59	1157	1158
+88
+
+chain 7445 4 191154276 + 1642823 1642928 4 191273063 + 1612696 1612801 10569689
+105
+
+chain 7390 4 191154276 + 9235101 9235376 4 191273063 + 8934980 8935255 884
+275
+
+chain 6985 4 191154276 + 9132536 9132609 10 135374737 + 82556085 82556158 28236044
+73
+
+chain 6957 4 191154276 + 9079830 9084724 8 146274826 - 133860764 133864463 3584848
+42	1125	1126
+68	534	536
+50	1109	1111
+56	1741	541
+169
+
+chain 6924 4 191154276 + 9086283 9086357 3 199501827 + 28200221 28200295 17749225
+74
+
+chain 6522 4 191154276 + 59794524 59794670 4 191273063 + 131104023 131104168 2551460
+51	42	41
+53
+
+chain 6459 4 191154276 + 191029213 191029282 11 134452384 - 63299390 63299459 29377341
+69
+
+chain 6349 4 191154276 + 8971797 8971864 9 140273252 + 68477506 68477573 29649127
+67
+
+chain 6310 4 191154276 + 1548554 1548645 4 191273063 + 1518821 1518912 10939184
+91
+
+chain 6297 4 191154276 + 59793454 59794143 3 199501827 - 40571037 40571724 2330420
+79	562	560
+48
+
+chain 6221 4 191154276 + 9064020 9064085 16 88827254 - 83673859 83673924 29990023
+65
+
+chain 6094 4 191154276 + 9110081 9110145 1 247249719 + 181849295 181849359 30306899
+64
+
+chain 6086 4 191154276 + 191030472 191030537 11 134452384 - 75925756 75925821 30317869
+65
+
+chain 5966 4 191154276 + 9104473 9104535 11 134452384 + 71003965 71004027 30644952
+62
+
+chain 5912 4 191154276 + 8947661 8947723 9 140273252 - 2802727 2802789 30796182
+62
+
+chain 5903 4 191154276 + 9101296 9101358 4 191273063 + 9087606 9087668 30814689
+62
+
+chain 5842 4 191154276 + 9036574 9036668 4 191273063 - 85960898 85960992 17872768
+94
+
+chain 5712 4 191154276 + 9132160 9132220 12 132349534 + 8264132 8264192 31330015
+60
+
+chain 5710 4 191154276 + 191042876 191042934 4 191273063 - 191272139 191272197 15878613
+58
+
+chain 5622 4 191154276 + 9070424 9070484 3 199501827 - 68123367 68123427 31584493
+60
+
+chain 5594 4 191154276 + 1547006 1547408 4 191273063 + 1517841 1518435 2949224
+33	336	530
+7	8	6
+18
+
+chain 5494 4 191154276 + 8989383 8989441 10 135374737 + 82555871 82555929 31956576
+58
+
+chain 5493 4 191154276 + 9123841 9123899 3 199501827 - 55547554 55547612 22296298
+58
+
+chain 5485 4 191154276 + 9108193 9108251 17 78774742 + 49845783 49845841 31992260
+58
+
+chain 5354 4 191154276 + 9123785 9123841 19 63811651 + 46743056 46743112 26997396
+56
+
+chain 5287 4 191154276 + 191044097 191044231 11 134452384 + 134452193 134452328 8509115
+51	52	53
+31
+
+chain 5247 4 191154276 + 1642928 1642982 4 191273063 + 1612682 1612736 32710536
+54
+
+chain 5146 4 191154276 + 9109529 9109584 3 199501827 + 191350023 191350078 20827932
+55
+
+chain 5102 4 191154276 + 9012475 9012528 7 158821424 - 61434988 61435041 33179954
+53
+
+chain 4979 4 191154276 + 59793133 59793454 14 106368585 + 47992116 47992437 1636209
+52	1	1
+72	116	116
+45	1	1
+34
+
+chain 4919 4 191154276 + 59793533 59793585 1 247249719 + 177132715 177132767 25644257
+52
+
+chain 4894 4 191154276 + 8980336 8980388 8 146274826 - 134343460 134343512 33871905
+52
+
+chain 4776 4 191154276 + 59793593 59793649 8 146274826 + 78720544 78720600 25267381
+56
+
+chain 4646 4 191154276 + 9032086 9032149 11 134452384 - 67001981 67002044 11075042
+63
+
+chain 4523 4 191154276 + 9083642 9083690 4 191273063 + 9229696 9229744 33561479
+48
+
+chain 4481 4 191154276 + 9110034 9110081 1 247249719 + 117212387 117212434 31311635
+47
+
+chain 4466 4 191154276 + 8975249 8975296 4 191273063 + 9087559 9087606 34734206
+47
+
+chain 4380 4 191154276 + 9065601 9065685 14 106368585 - 65288844 65288928 12690014
+84
+
+chain 4316 4 191154276 + 8994219 8994386 9 140273252 - 20618312 20618467 21123765
+25	83	71
+59
+
+chain 4224 4 191154276 + 1548697 1548764 4 191273063 + 1518798 1518831 14337246
+14	34	0
+19
+
+chain 4196 4 191154276 + 59793649 59793759 3 199501827 - 110817223 110817333 10064550
+110
+
+chain 4174 4 191154276 + 9006462 9006529 3 199501827 - 68301162 68301229 17546615
+67
+
+chain 4160 4 191154276 + 9087190 9087234 3 199501827 + 69469088 69469132 19451262
+44
+
+chain 4035 4 191154276 + 59793991 59794095 4 191273063 - 43511377 43511481 1601554
+104
+
+chain 3949 4 191154276 + 59793891 59793960 7 158821424 - 5091499 5091568 15707336
+69
+
+chain 3917 4 191154276 + 59794575 59794617 19 63811651 + 46686810 46686852 11955254
+42
+
+chain 3916 4 191154276 + 9180332 9180405 8 146274826 + 7130141 7130214 14314247
+73
+
+chain 3790 4 191154276 + 9231440 9231540 4 191273063 + 8950300 8950400 218917
+92	7	7
+1
+
+chain 3686 4 191154276 + 59793772 59793811 15 100338915 + 77825223 77825262 17426618
+39
+
+chain 3659 4 191154276 + 9096554 9096861 3 199501827 - 6400721 6401028 23757316
+67	190	190
+50
+
+chain 3657 4 191154276 + 59794470 59794516 6 170899992 - 3232006 3232052 26376367
+46
+
+chain 3647 4 191154276 + 1557695 1557733 4 191273063 + 1527878 1527916 12331685
+38
+
+chain 3642 4 191154276 + 9109808 9109863 6 170899992 - 83529676 83529731 23755843
+55
+
+chain 3437 4 191154276 + 9178724 9179540 12 132349534 + 34224690 34225504 10931865
+32	667	665
+117
+
+chain 3342 4 191154276 + 9274373 9274605 4 191273063 + 8969490 8969722 4902
+232
+
+chain 3310 4 191154276 + 8971045 8971455 9 140273252 - 10330739 10331149 20511421
+70	288	288
+52
+
+chain 3302 4 191154276 + 1548711 1548745 4 191273063 + 1518614 1518648 32145222
+34
+
+chain 3283 4 191154276 + 9102560 9102594 10 135374737 - 120311822 120311856 35225233
+34
+
+chain 3261 4 191154276 + 8994091 8994458 8 146274826 + 9742146 9742512 23065618
+62	246	245
+59
+
+chain 3172 4 191154276 + 59794789 59794841 3 199501827 - 24852035 24852087 14612523
+52
+
+chain 3108 4 191154276 + 9060565 9060615 13 114142980 - 41995201 41995251 9632166
+50
+
+chain 3078 4 191154276 + 1548520 1548554 4 191273063 + 1518360 1518394 5794973
+34
+
+chain 3017 4 191154276 + 9065206 9065807 10 135374737 + 117208692 117209275 9578047
+65	480	462
+56
+
+chain 2924 4 191154276 + 59795756 59795800 5 180857866 + 175080369 175080413 1478283
+44
+
+chain 2887 4 191154276 + 59793960 59793991 2 242951149 - 7484272 7484303 15380677
+31
+
+chain 2846 4 191154276 + 9001603 9001654 8 146274826 - 133764474 133764525 19750221
+51
+
+chain 2767 4 191154276 + 8957324 8957381 4 191273063 + 9129618 9129675 15542671
+57
+
+chain 2754 4 191154276 + 9087109 9087190 6 170899992 + 92706078 92706159 16313416
+81
+
+chain 2673 4 191154276 + 9065350 9065411 1 247249719 - 53009045 53009106 13821618
+61
+
+chain 2622 4 191154276 + 59793258 59793374 14 106368585 + 42536813 42536929 1616879
+116
+
+chain 2598 4 191154276 + 59795229 59795281 6 170899992 + 57310821 57310873 1524793
+52
+
+chain 2565 4 191154276 + 190987578 190987605 4 191273063 + 191231440 191231467 2372
+27
+
+chain 2557 4 191154276 + 9066521 9067027 12 132349534 + 72855206 72855711 22561893
+55	378	377
+73
+
+chain 2500 4 191154276 + 9083457 9083524 8 146274826 + 32149594 32149661 28386486
+67
+
+chain 2474 4 191154276 + 1651689 1651722 4 191273063 + 1621541 1621574 19254204
+33
+
+chain 2389 4 191154276 + 9036810 9036873 2 242951149 - 1691358 1691421 23135357
+63
+
+chain 2338 4 191154276 + 59796505 59796540 17 78774742 + 47057876 47057911 2877115
+35
+
+chain 2291 4 191154276 + 9216761 9217155 8 146274826 - 133997030 133997425 4114277
+45	320	321
+29
+
+chain 2265 4 191154276 + 9065418 9065482 9 140273252 + 44106224 44106288 9767431
+64
+
+chain 2116 4 191154276 + 8944155 8944177 3 199501827 + 126918676 126918698 25172225
+22
+
+chain 2099 4 191154276 + 9099268 9099290 2 242951149 + 169698626 169698648 26708137
+22
+
+chain 2025 4 191154276 + 9097343 9097409 3 199501827 + 179409375 179409441 24047564
+66
+
+chain 2003 4 191154276 + 9108252 9108273 2 242951149 - 190846639 190846660 24998179
+21
+
+chain 1997 4 191154276 + 9146164 9146218 15 100338915 - 2487154 2487208 24249848
+54
+
+chain 1870 4 191154276 + 190988070 190988095 10 135374737 + 135329605 135329630 1377
+25
+
+chain 1826 4 191154276 + 8957935 8957992 4 191273063 + 9362404 9362461 11066413
+57
+
+chain 1826 4 191154276 + 9097476 9098043 12 132349534 - 122338357 122338925 15828070
+57	424	425
+86
+
+chain 1767 4 191154276 + 8990059 8990106 1 247249719 + 148949220 148949267 26452494
+47
+
+chain 1744 4 191154276 + 59793037 59793133 3 199501827 + 30427927 30428023 1883621
+96
+
+chain 1736 4 191154276 + 9086392 9087109 4 191273063 - 127153063 127153784 14070511
+50	639	643
+28
+
+chain 1668 4 191154276 + 9124660 9124729 4 191273063 + 9269820 9269889 23245150
+69
+
+chain 1556 4 191154276 + 9060815 9060839 10 135374737 - 108080722 108080746 12503169
+24
+
+chain 1546 4 191154276 + 9180153 9180207 8 146274826 - 138844855 138844909 16808195
+54
+
+chain 1517 4 191154276 + 59794322 59794359 11 134452384 - 119842384 119842421 16271509
+37
+
+chain 1488 4 191154276 + 59796097 59796124 9 140273252 + 9925299 9925326 2265670
+27
+
+chain 1436 4 191154276 + 191043722 191043759 1 247249719 - 247249574 247249611 18645625
+37
+
+chain 1374 4 191154276 + 9065276 9065337 1 247249719 - 201083821 201083882 10540800
+61
+
+chain 1348 4 191154276 + 9109064 9109144 2 242951149 - 126292213 126292293 15140626
+80
+
+chain 1343 4 191154276 + 9146043 9146068 18 76117153 + 30068723 30068748 16305066
+25
+
+chain 1292 4 191154276 + 9123899 9123951 4 191273063 - 148574019 148574071 20863102
+52
+
+chain 1290 4 191154276 + 9179321 9179368 11 134452384 + 3426025 3426072 10983647
+47
+
+chain 1231 4 191154276 + 59794434 59794461 5 180857866 + 147382264 147382291 9387523
+27
+
+chain 1177 4 191154276 + 9065884 9065939 9 140273252 - 70318092 70318147 10006368
+55
+
+chain 1097 4 191154276 + 9086357 9086392 1 247249719 - 129588705 129588740 16923174
+35
+
+chain 1085 4 191154276 + 9066380 9066450 13 114142980 + 68490318 68490388 22728993
+70
+
+chain 1083 4 191154276 + 9032737 9032804 13 114142980 + 26049760 26049827 24893033
+67
+
+chain 1011 4 191154276 + 9067073 9067124 10 135374737 - 108679092 108679143 23379890
+51
+
+chain 996 4 191154276 + 8971509 8971561 12 132349534 + 31168410 31168462 23661941
+52
+
+chain 963 4 191154276 + 9066836 9066890 1 247249719 - 151454542 151454596 25048936
+54
+
+chain 958 4 191154276 + 9145173 9145232 1 247249719 - 217919030 217919089 20381976
+59
+
+chain 937 4 191154276 + 8958092 8958125 11 134452384 + 67446107 67446140 12651114
+33
+
+chain 917 4 191154276 + 9146455 9146505 8 146274826 + 19957787 19957837 24577235
+50
+
+chain 910 4 191154276 + 9097602 9098317 2 242951149 - 190844271 190844995 14887788
+50	595	604
+70
+
+chain 894 4 191154276 + 9109146 9109219 X 154913754 - 13573867 13573940 23078019
+73
+
+chain 878 4 191154276 + 9178986 9179012 2 242951149 - 137542666 137542692 11507142
+26
+
+chain 871 4 191154276 + 9082368 9082425 3 199501827 - 78731030 78731087 22332859
+57
+
+chain 858 4 191154276 + 9098043 9099355 5 180857866 - 58871729 58873086 24126323
+56	1191	1236
+65
+
+chain 777 4 191154276 + 8955354 8955423 3 199501827 - 68281758 68281827 15856837
+69
+
+chain 715 4 191154276 + 191033511 191033568 7 158821424 + 30724536 30724593 23744345
+57
+
+chain 650 4 191154276 + 9126884 9126934 3 199501827 + 102896742 102896792 23688110
+50
+
+chain 507 4 191154276 + 59793857 59793890 8 146274826 + 107120151 107120184 20878932
+33
+
+chain 468 4 191154276 + 40297344 40297404 4 191273063 + 39972706 39972766 25333266
+60
+
+chain 438 4 191154276 + 9098988 9099041 4 191273063 - 56600577 56600630 25949595
+53
+
+chain 368 4 191154276 + 191031439 191031496 19 63811651 - 43557899 43557956 26568315
+57
+
+chain 315 4 191154276 + 8972631 8972682 12 132349534 - 123858147 123858198 26303923
+51
+
+chain 268 4 191154276 + 59793813 59793857 13 114142980 - 20847506 20847550 12435901
+44
+
+chain 209 4 191154276 + 9096427 9096486 3 199501827 - 25140168 25140227 30710814
+59
+
+chain 16792065298 5 180915260 + 10000 180905260 5 180857866 + 63000 180837866 5
+17520657	50017	11
+356	84	84
+496	0	3434
+735	75	1475
+628	25	3459
+51	50	3484
+3427	1	1
+39	3	3437
+577	8	8
+167	44	1713
+23	0	3434
+1184	1	0
+46	1	0
+5	1	0
+266	1	1
+21	1	1
+763	16	16
+422	1	1
+29	1	1
+5243	1	1
+37	1	1
+978	1	1
+21	1	1
+116	16	3450
+1792	146	16585
+3079	0	1
+7857	9770	0
+1026	636	1
+7461	1	0
+23769	0	51
+4034	1	0
+20571	1	0
+9135	2	0
+6885	3	2
+110	0	3
+816	3	2
+2296	34	0
+7499	2	0
+2917	1	0
+652	1	1
+37	1	1
+657	1	1
+22	1	1
+419	4	3
+3580	1	1
+29	1	1
+274	35	11
+833	1	0
+1908	0	3038
+10504	1	1
+27	0	2
+784	6	0
+127	0	10
+668	1	1
+28	1	1
+2464	0	4
+182	2	0
+1650	1	1
+39	1	1
+2433	0	1
+720	1	1
+40	1	1
+772	1	1
+32	1	1
+353	1	1
+17	1	1
+1776	1	0
+6082	0	3
+2669	10	12
+2857	1	1
+35	1	1
+982	1	1
+173	1	1
+4115	1	1
+49	1	1
+702	1	1
+33	1	1
+2927	2	1
+1472	0	17
+1346	1	1
+35	1	1
+2068	1	1
+40	1	1
+828	1	1
+36	0	2
+317	0	8
+893	1	1
+33	0	1
+8145	4	0
+28632197	3000000	3000000
+12470071	1	0
+29760415	50000	40000
+5878002	20845	23000
+4521	0	1
+676	6	6
+5928	1	0
+372	1	1
+47	1	1
+6801	2	3
+639	1	0
+871	4	3
+11530	4	0
+22966	1	0
+15447	1	0
+53856	2	0
+15988	2	0
+906887	1	0
+8	2	2
+40152828	47715	0
+3526228	1	0
+1604	0	10
+12778810	51715	4100
+15152690	0	27
+1852098	0	1
+8710030
+
+chain 78758 5 180915260 + 17610410 17613099 5 180857866 + 17647305 17649997 1601642
+85	49	49
+57	201	201
+189	17	17
+78	77	77
+75	178	181
+116	179	179
+91	8	8
+51	298	300
+51	664	662
+64	26	26
+135
+
+chain 31383 5 180915260 + 97574240 97575427 4 191273063 - 170991967 170993160 4391624
+188	108	110
+89	705	709
+97
+
+chain 22831 5 180915260 + 97580590 97581374 2 242951149 - 86243998 86244777 8407693
+68	180	179
+95	326	322
+115
+
+chain 16108 5 180915260 + 97571166 97571372 3 199501827 + 12403992 12404198 13932022
+51	22	22
+133
+
+chain 10260 5 180915260 + 97573380 97573866 X 154913754 + 72466087 72466572 22227065
+67	357	356
+62
+
+chain 9281 5 180915260 + 97573916 97574127 3 199501827 - 17931346 17931561 24462523
+61	98	102
+52
+
+chain 8534 5 180915260 + 17581030 17583073 5 180857866 + 17608062 17614939 1974
+70	1948	6782
+25
+
+chain 7377 5 180915260 + 17614165 17614243 8 146274826 + 118652818 118652896 27454171
+78
+
+chain 7140 5 180915260 + 97574682 97574775 9 140273252 + 18188007 18188100 13076039
+11	6	6
+76
+
+chain 6854 5 180915260 + 97574980 97575063 2 242951149 + 163688921 163689004 19449593
+83
+
+chain 6104 5 180915260 + 97573580 97573645 X 154913754 + 86697567 86697632 30283885
+65
+
+chain 5931 5 180915260 + 97571838 97571901 11 134452384 + 21528921 21528984 30747470
+63
+
+chain 5358 5 180915260 + 97565266 97565323 3 199501827 + 123413571 123413628 32371600
+57
+
+chain 5211 5 180915260 + 97574626 97575600 2 242951149 - 205065194 205066172 4657168
+56	746	750
+172
+
+chain 4836 5 180915260 + 97570927 97570987 12 132349534 + 79028695 79028755 21429371
+60
+
+chain 3976 5 180915260 + 97580463 97580554 X 154913754 + 120621333 120621424 19038460
+91
+
+chain 3896 5 180915260 + 17583124 17583167 5 180857866 + 17601254 17601297 1526
+43
+
+chain 3528 5 180915260 + 97573879 97573916 4 191273063 - 42047288 42047325 31874217
+37
+
+chain 3107 5 180915260 + 97574479 97575651 2 242951149 + 88874356 88875531 4418505
+53	767	770
+31	271	271
+50
+
+chain 3026 5 180915260 + 97580178 97580228 15 100338915 - 8217824 8217874 19735797
+50
+
+chain 2922 5 180915260 + 97575231 97575262 5 180857866 - 151978291 151978322 11789776
+31
+
+chain 2640 5 180915260 + 97575132 97575230 6 170899992 - 85176442 85176540 6161475
+98
+
+chain 2605 5 180915260 + 97580235 97580338 6 170899992 - 161277959 161278062 12089137
+103
+
+chain 2572 5 180915260 + 97580955 97581020 4 191273063 + 75087136 75087201 9159879
+65
+
+chain 2511 5 180915260 + 97573039 97573123 5 180857866 + 96582581 96582665 20564544
+84
+
+chain 2425 5 180915260 + 97580778 97580807 7 158821424 + 56235832 56235861 15947917
+29
+
+chain 2390 5 180915260 + 97580658 97580706 6 170899992 + 77924350 77924398 14557662
+48
+
+chain 2360 5 180915260 + 97575070 97575127 15 100338915 - 65496060 65496117 11267266
+57
+
+chain 2316 5 180915260 + 97574862 97574967 5 180857866 + 122822031 122822136 6403532
+105
+
+chain 2262 5 180915260 + 97575262 97575299 5 180857866 + 117084659 117084696 9926189
+37
+
+chain 2258 5 180915260 + 97570996 97571059 6 170899992 + 98788934 98788997 20073703
+63
+
+chain 2234 5 180915260 + 97575771 97575825 15 100338915 + 19192799 19192853 13777203
+54
+
+chain 2112 5 180915260 + 17598551 17598575 5 180857866 + 17621050 17621074 2441
+24
+
+chain 2082 5 180915260 + 97581410 97581440 5 180857866 - 81177483 81177513 18145628
+30
+
+chain 2013 5 180915260 + 97574428 97574456 6 170899992 + 12662047 12662075 5707452
+28
+
+chain 1804 5 180915260 + 97574815 97574862 7 158821424 + 102470537 102470584 21213680
+47
+
+chain 1676 5 180915260 + 97571668 97571723 9 140273252 - 49451145 49451200 15925569
+55
+
+chain 1630 5 180915260 + 97575847 97575921 14 106368585 + 65599248 65599322 16554081
+74
+
+chain 1394 5 180915260 + 17611593 17611672 5 180857866 - 163271537 163271616 20711197
+79
+
+chain 1250 5 180915260 + 97570872 97570926 X 154913754 + 128632888 128632942 22138126
+54
+
+chain 1212 5 180915260 + 17598429 17598472 5 180857866 - 163276581 163276624 866388
+43
+
+chain 683 5 180915260 + 97570493 97570549 4 191273063 + 125149085 125149141 22694892
+56
+
+chain 625 5 180915260 + 97572119 97572183 5 180857866 - 153619225 153619289 25061319
+64
+
+chain 466 5 180915260 + 97569261 97569351 7 158821424 - 120247996 120248086 22482305
+90
+
+chain 395 5 180915260 + 97572751 97572804 2 242951149 - 47300723 47300776 19687839
+53
+
+chain 15799169383 6 171115067 + 60000 171055067 6 170899992 + 5000 170896992 6
+1297281	1	0
+7806968	0	162987
+4013154	9	0
+261	13	15
+18786172	17	17
+439	16	16
+59	5	4
+32202	17	17
+439	16	16
+59	4	5
+15403	1	0
+13914169	4	0
+112	1	1
+17	1	1
+415	12	0
+105	6	3
+12160281	50000	50000
+642507	3100000	3050000
+248423	50000	50000
+2918791	1238	0
+9427508	4	4
+162	12	12
+2193	22	22
+293	1	1
+30	1	1
+845	1	0
+45	1	1
+9769	2	0
+6058	1	1
+24	1	1
+2223	1	1
+24	1	1
+182	12	12
+284	1	1
+20	1	1
+1035	7	36
+1007	1	1
+27	1	1
+3279	1	1
+44	0	1
+3012	1	0
+545	17	17
+2562	0	1
+251	0	1
+935	8	0
+37	1	1
+566	6	0
+1483	2	0
+1960	1	0
+4564	1	1
+25	1	1
+832	0	1
+801	8	8
+1131	1	1
+58	5	1
+6177	0	1
+3712	1	0
+2185	1	1
+35	1	1
+710	2	2
+78	1	1
+2201	1	1
+30	1	1
+283	1	1
+30	1	1
+448	1	0
+74814	2	2
+197	8	0
+2508456	1	0
+4641788	5	5
+37	1	1
+8503609	0	2
+5363169	150000	200000
+6040303	1	1
+36	1	0
+2020	1	1
+46	1	1
+1559	1	1
+72	1	1
+1098	1	1
+29	1	1
+264	7	7
+580	0	1
+30	1	1
+536	1	1
+41	1	1
+5663	1	0
+438	5	3
+354	1	1
+18	1	1
+9613	14	13
+1400	1	0
+176	0	2
+2742	1	0
+1968	0	1
+754	1	0
+4237	0	1
+2388	1	1
+31	1	0
+3385	0	1
+2004	8	0
+3395	0	3
+32	1	1
+4109	0	1
+1058	20	0
+1608	1	0
+17198424	17	26
+7835	0	1
+16317	11	0
+6277	64993	0
+6787989	0	1
+149	4	0
+949	4	0
+242	0	1
+28418215	1	1
+21	1	0
+3116903	171704	50000
+1939305	1	1
+19	0	2
+8192274	4	4
+122	0	2
+1127	1	0
+1102	75	0
+21	8	5
+30	29	0
+27	6	3
+62	52	0
+42	195105	18125
+950946	1	1
+51	157	1
+107	255	0
+714	513	0
+1285155	50000	150000
+725095
+
+chain 27931 6 171115067 + 168993335 168994451 6 170899992 + 168736232 168737615 1527785
+96	36	36
+16	0	51
+107	739	901
+51	0	54
+71
+
+chain 17101 6 171115067 + 119158013 119159004 8 146274826 + 76280127 76281098 12940826
+78	146	105
+78	622	643
+67
+
+chain 14766 6 171115067 + 119189669 119190286 7 158821424 - 68703788 68704409 15321990
+54	439	443
+124
+
+chain 13062 6 171115067 + 168994482 168994817 6 170899992 + 168736716 168737003 1274096
+205	50	2
+80
+
+chain 12205 6 171115067 + 119155128 119155329 8 146274826 - 70047959 70048173 18676577
+72	59	72
+70
+
+chain 11124 6 171115067 + 168993071 168993228 6 170899992 + 168736229 168736638 2160304
+29	1	52
+50	25	226
+52
+
+chain 10673 6 171115067 + 119159180 119160231 10 135374737 - 59595554 59596042 21356650
+62	913	350
+76
+
+chain 10669 6 171115067 + 119157022 119157134 14 106368585 + 59942933 59943045 21369163
+112
+
+chain 9554 6 171115067 + 119189632 119189818 X 154913754 + 133155010 133155200 16872824
+37	54	54
+12	31	35
+52
+
+chain 7241 6 171115067 + 119190390 119190581 13 114142980 + 101174758 101174949 23777400
+2	136	136
+53
+
+chain 6904 6 171115067 + 119156272 119156345 11 134452384 - 108078565 108078638 28375374
+73
+
+chain 6531 6 171115067 + 119159999 119160068 4 191273063 - 87162214 87162283 29199925
+69
+
+chain 5948 6 171115067 + 119160915 119160977 X 154913754 - 59556739 59556801 30709264
+62
+
+chain 5818 6 171115067 + 119158407 119158509 18 76117153 + 30261305 30261403 24322730
+1	51	47
+50
+
+chain 5749 6 171115067 + 119155939 119156000 6 170899992 + 92063509 92063570 31228902
+61
+
+chain 5103 6 171115067 + 119189831 119189885 X 154913754 - 76833525 76833579 33162260
+54
+
+chain 5032 6 171115067 + 119156645 119156719 X 154913754 + 87420725 87420799 20704812
+74
+
+chain 5002 6 171115067 + 119160862 119160914 X 154913754 + 56955255 56955307 33524497
+52
+
+chain 4995 6 171115067 + 168994451 168994737 6 170899992 + 168737201 168737385 2349016
+31	205	103
+50
+
+chain 4921 6 171115067 + 119156041 119156093 9 140273252 + 81227536 81227588 33775667
+52
+
+chain 4912 6 171115067 + 119160087 119160139 5 180857866 + 63815067 63815119 33803556
+52
+
+chain 3597 6 171115067 + 119157136 119157361 2 242951149 + 31758724 31758949 14786968
+84	78	78
+63
+
+chain 3223 6 171115067 + 119156854 119156913 15 100338915 - 54365651 54365710 24573102
+59
+
+chain 3204 6 171115067 + 119155364 119155420 6 170899992 - 73613724 73613780 24603360
+56
+
+chain 2966 6 171115067 + 119156499 119156577 X 154913754 - 137505405 137505483 21485501
+78
+
+chain 2728 6 171115067 + 119159004 119159033 3 199501827 - 198198433 198198462 28454448
+29
+
+chain 2528 6 171115067 + 119156618 119156645 11 134452384 + 82352593 82352620 34284540
+27
+
+chain 2454 6 171115067 + 119155233 119155259 9 140273252 + 122001720 122001746 35057240
+26
+
+chain 2315 6 171115067 + 119156723 119156806 4 191273063 + 116661391 116661474 16361102
+83
+
+chain 2146 6 171115067 + 119158341 119158407 6 170899992 + 115819766 115819832 17078055
+66
+
+chain 1866 6 171115067 + 119190053 119190120 5 180857866 + 56063062 56063129 22879278
+67
+
+chain 1656 6 171115067 + 119158523 119158602 11 134452384 + 2473635 2473714 18654554
+79
+
+chain 1624 6 171115067 + 119189898 119189948 4 191273063 - 66123378 66123428 24040914
+50
+
+chain 1451 6 171115067 + 119158163 119158229 15 100338915 - 64161282 64161348 22109122
+66
+
+chain 1209 6 171115067 + 168994304 168994329 6 170899992 + 168736283 168736308 2117199
+25
+
+chain 1198 6 171115067 + 119156176 119156250 5 180857866 + 3717928 3718002 22194292
+74
+
+chain 980 6 171115067 + 119158602 119158634 8 146274826 + 104450758 104450790 18747323
+32
+
+chain 943 6 171115067 + 119157563 119157614 2 242951149 + 163020248 163020299 23359839
+51
+
+chain 785 6 171115067 + 119156425 119156485 17 78774742 - 29484860 29484920 22136428
+60
+
+chain 779 6 171115067 + 119190333 119190390 3 199501827 - 104453282 104453339 22453017
+57
+
+chain 696 6 171115067 + 119158674 119158726 6 170899992 - 83894386 83894438 23403881
+52
+
+chain 689 6 171115067 + 119157650 119157707 X 154913754 + 101935638 101935695 24716105
+57
+
+chain 360 6 171115067 + 119160319 119160372 3 199501827 - 158113258 158113311 26359861
+53
+
+chain 282 6 171115067 + 119159242 119159272 19 63811651 + 46835118 46835148 25343818
+30
+
+chain 14618488008 7 159138663 + 10238 159128663 7 158821424 + 102995 158821424 7
+973	0	5
+3912	2	0
+1234	0	4
+51	6	0
+70	1	1
+24	0	1
+147	0	8
+12	1	170
+47	1	1
+246	6	0
+99	4	4
+807	0	3
+2546	0	63
+44	0	2527
+1373	1	0
+2109	456	0
+1153	1	0
+791	1	1
+49	1	0
+4175	18	26
+4318	11	11
+514	0	12
+2511	1	0
+1697	6	6
+192827	278557	150000
+5682433	40	39
+42007910	35970	40000
+2048	3	3
+2320	16	7
+17699	4	0
+5248	0	4
+2088411	1	1
+47	1	1
+4565	1	0
+7116	1	0
+2706	43050	40000
+6577293	13552	50000
+1052855	3000000	3000000
+256182	416507	50000
+190137	50000	50000
+5722629	1	0
+23	1	1
+239	1	1
+59	2	2
+138	1	1
+34	1	1
+206	3	1
+18	0	1
+410	1	1
+72	1	1
+199	1	1
+62	5	5
+120	0	1
+468	1	1
+32	1	1
+264	1	1
+23	1	1
+1459	4	4
+107	1	1
+42	0	1
+14	1	1
+201	1	1
+46	1	1
+268	20	20
+303	1	2
+866	4	0
+76	3	3
+63	1	1
+74	0	1
+25	1	1
+66	1	1
+34	2	0
+180	36	35
+93	1	1
+41	1	1
+70	1	1
+49	1	1
+63	1	1
+57	1	1
+383	1	1
+133	1	1
+87	1	1
+38	4	4
+50	1	0
+46	6	5
+136	11	11
+200	1	1
+64	5	18
+263	1	1
+32	3	3
+152	16	16
+567	0	1
+322	0	3
+1258	1	0
+504	0	4
+1142	10	11
+537	12	12
+1418	1	1
+47	1	0
+164	7	7
+113	0	5
+59	2	2
+72	1	1
+20	1	1
+380	3	3
+41	0	3
+5	2	2
+921	1	1
+34	1	1
+1607	2	2
+73	0	66
+45	0	14
+169	1	1
+53	1	1
+3195	1	1
+23	1	1
+2115	14	0
+9872	0	1
+1204	13	13
+416	0	1
+2298	0	319
+6918	10	0
+184	0	24
+2932	0	4
+1394	12	0
+1853	0	5
+3442	1	0
+469	0	3
+771	12	15
+497	1	1
+65	1	1
+1210	2	0
+4131	10	10
+1198	0	1
+718	1	1
+21	1	1
+3668	0	1
+874	1	1
+25	1	1
+2444	1	0
+1867	1	1
+29	1	1
+1660	1	0
+1233	6	0
+783	0	1
+705	3	0
+3577	0	1
+365	0	1
+3389	4	8
+2652	3	0
+664	1	0
+169	9	10
+138	1	0
+8038	56	0
+109	0	196
+522	35	0
+3003	1	1
+40	1	1
+1065	0	4
+634	1	0
+51	30	0
+66	1	9
+3081	0	2
+806	1	0
+21	1	1
+3901	27	26
+843	1	0
+6916420	50000	250000
+25789109	51216	0
+1399988	0	1
+3623	212	0
+38	1	1
+210	29	33
+1318	0	16
+2190	0	1
+145	1	0
+1388	7	7
+2240	14	14
+771	1	1
+34	1	1
+92	1	1
+39	1	1
+505	0	1
+66	1	1
+49	1	1
+159	0	1
+78	0	2
+2	0	1
+13	0	2
+7	0	1
+28	0	1
+27	5	468
+2022	0	1
+1796	7	7
+61	1	1
+20	1	1
+4560	0	3
+157730	0	1
+194	14	14
+650	12	0
+669	74	74
+820	5	0
+277	32	60
+69	5	0
+1345	0	8
+652	0	84
+118	4	0
+498	1	0
+3187	1	1
+43	1	1
+1476	3	0
+2101	0	5
+788	6	6
+872	6	0
+691	202	205
+155	33	33
+4610	7	5
+521	0	10
+2773	1	1
+38	1	1
+627	1	1
+41	1	1
+1424	1	0
+2554	8	8
+45	7	0
+614	1	1
+32	0	3
+2693	1	0
+1029	2	0
+151	1	0
+1753	21	0
+370	3	2
+969	1	0
+452	0	1
+3035	42	42
+704	2	0
+2472	6	0
+238	0	1
+1442	43	43
+126	1	0
+795	1	0
+1191	0	1
+171	16	17
+724	27	28
+2966	1	1
+38	3	1
+359	0	2
+199	1	1
+17	1	1
+1969	0	1
+251	1	0
+729	1	0
+992	1	1
+25	1	1
+203	0	4
+3211	2	0
+1006	10	8
+1571	10	10
+756	38	37
+433	1	0
+672	3	0
+4460	25	182
+5551	19	23
+942	9	10
+3433	1	2
+24	1	1
+4262	0	13
+661	0	2
+167	0	8
+3474	66	61
+162	2	0
+778	34	34
+158	1	0
+1167	1	0
+684	1	0
+878	39	39
+2012	1	0
+345	1	1
+50	1	1
+626	2	0
+27874083	136705	0
+2495	2	0
+1000	0	8
+14695	0	1
+4456	0	1
+2977	0	1
+9065130	29055	25000
+2369	0	1
+12174	20	18
+878	4	0
+5247	12	0
+3482	0	2
+6766	1	0
+2469878	1	0
+835	1	0
+2471	13	13
+751	0	8
+2241	1	0
+12	1	1
+8394	0	1
+47	1	1
+903	1	0
+5537	1	0
+269	0	1
+7114	1	1
+30	1	1
+2412	1	0
+2442	21	21
+91	1	1
+37	1	1
+96	1	1
+22	1	1
+246	1	1
+23	1	1
+241	25	25
+569	1	1
+27	1	1
+1624	0	1
+112	3	3
+45	1	1
+384	13	13
+70	0	1
+658	1	1
+20	1	1
+176	0	1
+307	19	19
+428	1	1
+19	1	1
+87	1	1
+30	1	1
+140	0	1
+292	0	2
+1492	0	1
+302	2	0
+364	1	1
+35	1	1
+1956	1	0
+728	57	57
+8010	0	1
+488	0	1
+2056	8	18
+1286	1	1
+27	1	1
+731	0	1
+1423	7	0
+2010	1	1
+19	1	1
+3925	37	37
+2438	4	0
+80	1	1
+4505	0	13
+933	12	0
+1250	1	0
+1313	0	1
+2610	1	0
+2398	1	0
+453	0	1
+346	14	14
+83	0	1
+24	1	0
+83	12	12
+277	1	0
+45	0	1
+811	0	2
+164	1	0
+104	1	0
+32	1	1
+1386	14	0
+306	1	1
+43	1	1
+2765	1	0
+1819	1	0
+1480	1	1
+24	1	1
+276	1	0
+21	1	0
+119	11	39
+542	1	1
+63	1	1
+180	1	0
+2456	0	1
+392	62	62
+601	0	1
+1166	0	2
+784	4	0
+170	0	1
+939	0	6
+5597	15	15
+1253	1	0
+3336	18	0
+1851	0	9
+45	1	1
+4794	1	0
+1387	0	2
+1460	0	1
+204	5	0
+1506	1	0
+2621	0	1
+6620	1	0
+34	1	1
+249	0	1
+1443	10	0
+242	1	0
+368	9	1
+257	0	4
+1588	0	6
+1544	1	0
+4189	0	120
+354	278046	312446
+3728	1	0
+3127	9	10
+4861	4	0
+5649	0	1
+2011	1	0
+14914	1467	42
+20955	1	0
+2075	1	2
+5546	0	1
+2168	0	4
+1266	0	1
+4124	1	1
+46	1	1
+54	1	1
+43	0	15
+780	1	1
+25	1	1
+497	1	0
+46	1	1
+770	41	40
+5701	1	0
+4251	8	8
+2739	1	0
+2002	3	0
+7160	1	1
+24	1	1
+479	0	2
+1872	1	0
+1192	0	1
+371	0	2
+31	1	1
+572	16	16
+1725	16	16
+588	1	1
+90	1	1
+2483	19	3
+187	1	0
+20	1	1
+3673	1	1
+27	0	4
+3021	0	1
+1323	6	19
+498	13	13
+1618	0	2
+5282	1	0
+720	8	0
+2993	0	1
+2822	2	0
+1396	1	1
+48	1	1
+8723	0	5
+291	1	1
+25	1	1
+116	1	0
+2809	1	1
+27	1	1
+224	1	1
+48	1	1
+292	2	0
+400	1	0
+754	1	1
+19	1	1
+4225	1	1
+28	1	1
+801	0	1
+671	1	1
+17	1	1
+390	1	1
+28	1	1
+84	7	7
+568	1	1
+56	1	1
+499	8	7
+266	1	1
+31	1	1
+518	18	18
+164	1	1
+50	1	1
+162	1	1
+60	1	1
+702	1	1
+28	1	1
+146	17	18
+517	1	1
+24	1	1
+799	1	1
+22	5	5
+107	5	5
+277	9	9
+272	1	1
+48	1	1
+77	1	1
+67	1	1
+1548	1	1
+40	1	1
+763	1	1
+42	1	1
+541	8	8
+88	1	1
+77	1	1
+233	11	11
+311	1	1
+22	1	1
+147	8	1
+504	1	1
+26	1	1
+996	3615	24049
+1687	0	1
+1174	1	0
+70	1	1
+1100	18	10143
+2722	1	0
+2957	1	1
+32	1	1
+9585	1	0
+1350	1	0
+473	1	0
+675	1	0
+1435	1	0
+805463	79189	0
+10872697	100000	100000
+721570	1	1
+19	1	1
+816	1	1
+44	1	1
+572	6	8
+2021	4	0
+1001	0	2
+3757	0	1
+5942	2	2
+70	1	1
+100	7	7
+395	17188	80000
+1010	1	1
+45	1	1
+1486	18	18
+173	145	1
+139	65	1
+41	16	0
+32	368	0
+44	2	50
+40	1	1
+95	52	4
+60	8	39
+12	0	16
+93	0	16
+1591	1	0
+897	13	13
+28	3	3
+2454	1	1
+44	1	1
+305	468	0
+2026	1	1
+45	1	1
+1273	3	11
+1717	0	1
+1575	4	0
+14	1	1
+2428	0	36
+50	10	154
+247	185	6
+2096	11	13
+192	1	1
+48	1	1
+130	1	1
+22	1	1
+970	1	1
+22	0	4
+76	14	0
+118	58	64
+107	1	0
+12	1	1
+53	5	15
+48	1	1
+47	2	0
+114	16	18
+363	1	1
+43	1	1
+559	1	1
+32	1	1
+3980007
+
+chain 16700437 7 159138663 + 142098195 142276197 7 158821424 - 16919205 17097543 171
+6297	1	0
+171	1	0
+4869	1	1
+24	0	1
+6208	0	1
+135	1	0
+1978	1	0
+764	1	1
+45	0	2
+1984	0	1
+1628	1	0
+733	1	1
+38	1	0
+137	7	7
+17	1	1
+259	1	0
+1200	1	0
+2193	4	4
+1781	0	1
+3387	1	1
+25	1	1
+125	1	1
+17	1	1
+3811	5	5
+556	0	1
+1846	5	0
+1322	1	1
+40	1	1
+228	0	1
+3477	1	1
+31	1	1
+3722	1	1
+73	1	1
+3052	66	66
+2542	15	15
+3103	0	2
+112	0	2
+1066	1	1
+59	1	0
+719	1	0
+203	1	0
+127	1	0
+30	1	0
+32	1	1
+366	0	4
+27	1	1
+2155	1	1
+41	1	1
+790	0	1
+403	1	1
+27	1	1
+648	7	7
+48	2	0
+78	2	2
+1052	4	4
+855	1	1
+68	1	1
+2428	9	0
+919	1	1
+22	1	1
+366	1	1
+36	1	1
+269	7	7
+4018	6	6
+1168	0	1
+3409	0	1
+1503	3	0
+2680	1	1
+37	1	1
+727	1	1
+28	0	5
+9	0	3
+5	0	2
+4	9	0
+13	1	1
+1801	0	3
+98	14	14
+2789	4	0
+5562	1	0
+2380	1	1
+23	1	1
+160	1	1
+57	1	1
+2413	19	19
+1704	0	1
+67	0	1
+68	1	1
+45	1	1
+176	9	9
+973	1	1
+31	3	3
+167	4	4
+334	13	13
+584	11	11
+206	16	16
+1218	1	1
+29	1	1
+234	1	1
+45	0	2
+1027	0	1
+559	10	11
+367	0	2
+8269	0	2
+4195	1	1
+62	1	1
+2896	13	13
+524	5	5
+411	1	1
+53	1	1
+126	1	1
+36	1	1
+806	1	1
+43	2	0
+1905	2	0
+414	1	1
+25	1	1
+2396	1	0
+12	1	0
+23	0	1
+10	0	1
+4	0	1
+60	0	1
+25	1	1
+1387	0	4
+3461	0	2
+1026	0	2
+821	1	1
+21	1	0
+612	1	1
+31	1	1
+1053	1	0
+2080	17	17
+9739	5	12
+17	7	0
+878	1	1
+19	1	0
+53	1	1
+839	26	26
+522	1	1
+49	1	1
+539	1	1
+25	1	1
+669	1	1
+42	1	1
+134	7	7
+1145	1	0
+2731	1	0
+590	4	0
+41	0	1
+7853	0	4
+830	0	2
+1742	2	0
+640	1	1
+34	0	2
+298	1	0
+3598	1	0
+1522	1	339
+115	18	18
+887	1	1
+69	1	1
+1662
+
+chain 1755125 7 159138663 + 143318748 143347897 7 158821424 - 15657394 15686558 532
+923	0	15
+1431	698	698
+3421	10	12
+405	1	1
+16	1	1
+5116	1	1
+27	1	1
+334	1	1
+15	1	0
+724	13	13
+109	0	2
+1784	1	0
+1588	1	1
+43	1	1
+908	9684	9682
+464	445	445
+982
+
+chain 939937 7 159138663 + 61402791 61412791 7 158821424 + 61280000 61290000 3137
+10000
+
+chain 921443 7 159138663 + 61382791 61392786 7 158821424 + 61260000 61269994 3741
+1722	1	0
+433	30	30
+1603	4	4
+4846	27	27
+478	19	19
+584	36	36
+212
+
+chain 898631 7 159138663 + 61392792 61402791 7 158821424 + 61270000 61280000 4251
+316	76	76
+3924	49	49
+2708	28	28
+1134	174	174
+156	40	41
+1394
+
+chain 896117 7 159138663 + 61422788 61432614 7 158821424 + 61300000 61310000 4294
+1207	50	50
+1637	22	22
+347	30	30
+983	48	48
+2562	0	172
+1941	14	14
+487	39	41
+459
+
+chain 881174 7 159138663 + 61412791 61422788 7 158821424 + 61290000 61300000 4600
+2588	34	34
+299	23	23
+1680	4	6
+286	395	396
+256	39	39
+220	18	18
+675	16	16
+3464
+
+chain 807485 7 159138663 + 61372814 61382791 7 158821424 + 61250000 61260000 5800
+91	75	75
+308	91	91
+99	88	88
+175	43	43
+577	65	65
+289	17	17
+186	21	21
+119	72	72
+80	98	98
+114	2	1
+115	51	51
+319	90	97
+54	49	50
+590	135	136
+749	1	0
+467	41	41
+153	21	21
+97	102	118
+935	19	19
+3186	43	43
+150
+
+chain 475263 7 159138663 + 143336322 143346915 7 158821424 - 15765291 15775883 242
+2017	14	14
+1214	1	1
+32	1	1
+3171	0	8
+760	1	1
+49	1	1
+68	10	10
+1210	1	1
+39	1	1
+60	18	9
+568	4	4
+357	12	12
+75	512	512
+397
+
+chain 413572 7 159138663 + 61432614 61437066 7 158821424 + 61310000 61314455 110492
+105	12	12
+1311	18	21
+3006
+
+chain 327362 7 159138663 + 130261501 130267755 7 158821424 - 80118425 80124354 202501
+81	547	220
+108	98	98
+188	35	35
+305	168	168
+59	47	46
+67	25	25
+301	6	6
+107	44	44
+133	23	23
+174	0	4
+110	27	27
+188	31	31
+86	62	62
+284	66	66
+205	34	34
+171	16	16
+85	35	35
+152	206	205
+64	33	33
+71	76	76
+129	26	26
+52	79	80
+203	92	92
+193	64	64
+113	490	490
+131	98	97
+66
+
+chain 116757 7 159138663 + 56987924 57001476 7 158821424 - 96066875 96080423 71
+182	4	0
+366	2	0
+47	6	0
+1290	7	1
+317	25	25
+90	14	15
+195	1	6
+96	1	1
+280	1	1
+59	1	1
+435	1	1
+51	1	1
+1067	22	22
+3594	0	1
+645	0	1
+507	7	7
+1383	0	6
+531	0	1
+1396	1	0
+927
+
+chain 94083 7 159138663 + 61667110 61669673 9 140273252 - 71180528 71183093 1349166
+123	22	22
+57	154	154
+93	530	532
+407	16	16
+95	28	28
+72	290	290
+83	43	43
+61	266	266
+77	77	77
+69
+
+chain 75094 7 159138663 + 433321 434167 14 106368585 - 82907729 82908574 1677524
+115	1	1
+30	1	0
+335	22	22
+342
+
+chain 74694 7 159138663 + 61674373 61676412 2 242951149 + 91627954 91629996 1686429
+59	154	155
+210	438	438
+221	259	259
+81	77	77
+52	201	203
+222	15	15
+50
+
+chain 54428 7 159138663 + 61360568 61361523 9 140273252 + 69464390 69465353 2322078
+76	100	105
+56	176	179
+432	51	51
+64
+
+chain 45723 7 159138663 + 100554977 100556023 7 158821424 + 100392913 100393963 2803709
+153	225	232
+246	8	8
+74	288	285
+52
+
+chain 42415 7 159138663 + 130262863 130266857 20 62435964 + 18530662 18534660 203154
+65	162	162
+47	67	67
+25	425	425
+33	1127	1130
+57	206	206
+33	274	274
+33	152	152
+121	149	149
+33	83	83
+64	129	129
+26	335	336
+91	194	194
+63
+
+chain 34286 7 159138663 + 61670163 61670988 1 247249719 - 187008143 187008914 3936433
+177	89	89
+59	338	284
+162
+
+chain 30309 7 159138663 + 61417768 61418394 15 100338915 + 53005912 53006538 319980
+332	256	256
+38
+
+chain 29619 7 159138663 + 130261638 130262129 18 76117153 - 20889181 20889344 211760
+82	389	61
+20
+
+chain 28749 7 159138663 + 102187071 102200348 7 158821424 + 102073398 102086671 912
+74	1102	1102
+32	11867	11863
+202
+
+chain 27540 7 159138663 + 61526936 61527567 17 78774742 - 13987513 13988140 5824140
+131	255	251
+90	52	52
+103
+
+chain 25455 7 159138663 + 61658206 61658677 21 46944323 + 31224827 31225297 6797318
+187	186	185
+98
+
+chain 25398 7 159138663 + 130275431 130276578 X 154913754 + 99697151 99697788 219009
+66	77	207
+69	353	1
+53	369	81
+54	49	49
+57
+
+chain 24368 7 159138663 + 61663982 61664383 7 158821424 - 97410910 97411311 7475570
+54	99	99
+67	16	16
+165
+
+chain 23018 7 159138663 + 61372081 61372809 7 158821424 + 61249436 61249995 8282044
+79	92	92
+52	313	144
+58	34	34
+100
+
+chain 22330 7 159138663 + 61674796 61675234 16 88827254 - 56087354 56087792 5126597
+69	100	100
+51	129	129
+89
+
+chain 22048 7 159138663 + 61583753 61648197 7 158821424 - 97506969 97571424 1587
+3024	0	1
+5860	1	1
+34	1	1
+1210	1	1
+46	1	1
+1360	1	1
+20	1	1
+6247	7	7
+2011	22	23
+15979	1	1
+20	0	1
+39	1	1
+156	1	1
+79	1	1
+1227	1	1
+26	1	1
+201	17	17
+6321	11	11
+106	2	2
+66	33	33
+316	6	6
+832	1	1
+17	1	1
+478	1	1
+25	1	1
+4306	14	0
+14	1	1
+525	4	4
+1603	1	1
+28	1	1
+433	1	0
+1365	1	1
+35	1	1
+3699	1	1
+17	1	1
+962	0	16
+124	1	1
+221	1	1
+50	1	1
+446	1	0
+788	0	1
+38	1	1
+470	14	14
+173	1	1
+48	0	1
+54	1	1
+71	0	7
+17	1	1
+319	1	1
+49	1	1
+115	2	1
+167	1	1
+41	3	3
+80	1	1
+70	1	1
+119	1	1
+19	1	1
+186	17	17
+347	7	7
+549	1	1
+69	1	1
+175	1	1
+55	1	1
+101	1	1
+118	2	2
+307	1	1
+73	1	1
+91
+
+chain 20717 7 159138663 + 61531674 61531894 Y 57772954 + 23149505 23149725 9889131
+220
+
+chain 20603 7 159138663 + 61525953 61526232 8 146274826 + 92437703 92437982 9974457
+114	48	48
+117
+
+chain 20209 7 159138663 + 61534129 61534693 5 180857866 - 39454690 39455254 10284708
+41	129	129
+72	189	189
+133
+
+chain 19256 7 159138663 + 10000 10238 11 134452384 - 108 510 10867298
+115	1	145
+57	3	0
+12	3	26
+47
+
+chain 17549 7 159138663 + 23954 24387 3 199501827 - 125819 126212 1017
+61	27	17
+87	27	17
+87	27	17
+87	27	17
+3
+
+chain 17511 7 159138663 + 61459516 61459775 3 199501827 + 156410667 156410926 12559831
+104	60	60
+95
+
+chain 17423 7 159138663 + 130286013 130286315 3 199501827 + 134941335 134941641 12635149
+64	74	78
+72	18	18
+74
+
+chain 17216 7 159138663 + 61561042 61561226 18 76117153 + 1344411 1344595 12834816
+184
+
+chain 15818 7 159138663 + 130258842 130259235 20 62435964 - 56174662 56175052 14212289
+60	144	139
+68	52	54
+69
+
+chain 15803 7 159138663 + 434188 434399 9 140273252 - 53303336 53303547 1693631
+211
+
+chain 15460 7 159138663 + 61363520 61363685 14 106368585 + 46013452 46013617 14586403
+165
+
+chain 15455 7 159138663 + 61533249 61533413 10 135374737 - 122138066 122138230 14591550
+164
+
+chain 14801 7 159138663 + 61526597 61527118 11 134452384 + 128715236 128715756 6490404
+89	98	98
+58	225	224
+51
+
+chain 14577 7 159138663 + 61459836 61459991 2 242951149 - 172428837 172428992 15528208
+155
+
+chain 14381 7 159138663 + 61532809 61533249 5 180857866 - 128913075 128913510 15277847
+110	278	273
+52
+
+chain 14182 7 159138663 + 61362349 61362804 1 247249719 - 101935287 101935742 15983329
+55	287	287
+113
+
+chain 13384 7 159138663 + 130261760 130262050 18 76117153 - 65538588 65538878 302793
+128	17	17
+145
+
+chain 12863 7 159138663 + 61659684 61659821 18 76117153 + 15161457 15161594 17682773
+137
+
+chain 12713 7 159138663 + 130268588 130270221 7 158821424 - 62883278 62884905 17912238
+74	1316	1311
+67	121	120
+55
+
+chain 12498 7 159138663 + 61527567 61527825 2 242951149 - 136022598 136022856 13034573
+7	155	155
+96
+
+chain 12424 7 159138663 + 61560835 61560980 21 46944323 - 5411573 5411718 18347201
+82	1	1
+62
+
+chain 11917 7 159138663 + 130274671 130277102 2 242951149 + 85567844 85569506 1111973
+198	73	73
+65	403	530
+21	111	209
+32	1149	157
+77	81	81
+50	6	4
+165
+
+chain 11414 7 159138663 + 61446485 61446604 8 146274826 - 97728756 97728875 19987436
+119
+
+chain 11204 7 159138663 + 323186 323319 13 114142980 - 47557127 47557260 20361650
+67	7	7
+59
+
+chain 11191 7 159138663 + 61533547 61533688 10 135374737 + 121736617 121736758 14568606
+63	20	20
+58
+
+chain 11162 7 159138663 + 143321102 143321761 7 158821424 + 143031254 143031913 1465
+659
+
+chain 11033 7 159138663 + 155133717 155133867 7 158821424 + 154826660 154826810 3228542
+150
+
+chain 10743 7 159138663 + 130272956 130273070 20 62435964 - 54784771 54784885 21217928
+114
+
+chain 10697 7 159138663 + 61363082 61363210 8 146274826 + 114533399 114533527 21308454
+63	1	1
+64
+
+chain 10686 7 159138663 + 130276049 130276418 5 180857866 - 110000669 110000947 1711166
+8	218	161
+54	34	0
+55
+
+chain 10550 7 159138663 + 61534371 61534497 2 242951149 - 102597516 102597642 13706867
+22	1	1
+103
+
+chain 10502 7 159138663 + 61658058 61658206 3 199501827 - 100394760 100394909 7999945
+74	51	52
+23
+
+chain 9908 7 159138663 + 155127373 155127651 7 158821424 + 154820991 154821604 23020589
+62	155	490
+61
+
+chain 9705 7 159138663 + 130254993 130255333 5 180857866 - 86134908 86135248 23505792
+58	220	220
+62
+
+chain 9691 7 159138663 + 61363878 61364175 6 170899992 - 83481581 83481894 23533804
+52	178	194
+67
+
+chain 9557 7 159138663 + 130275060 130277190 4 191273063 + 57733996 57734920 1639272
+2	161	201
+75	1804	558
+40	10	10
+38
+
+chain 9406 7 159138663 + 61531909 61532009 3 199501827 - 114948547 114948647 24221847
+100
+
+chain 9378 7 159138663 + 61670488 61670618 1 247249719 + 166585217 166585347 4198164
+130
+
+chain 9215 7 159138663 + 61369893 61370445 20 62435964 + 26207014 26207215 24594255
+60	436	85
+56
+
+chain 8793 7 159138663 + 61533688 61534015 8 146274826 + 132629025 132629349 11801047
+54	54	51
+58	97	97
+64
+
+chain 8578 7 159138663 + 61650566 61651111 20 62435964 - 36228749 36228943 25570183
+56	436	85
+53
+
+chain 8304 7 159138663 + 61532721 61532809 5 180857866 - 33354116 33354204 19653256
+88
+
+chain 8273 7 159138663 + 61375213 61375308 10 135374737 - 99567310 99567405 2885342
+95
+
+chain 7707 7 159138663 + 61670340 61670429 11 134452384 + 5653851 5653940 4693035
+89
+
+chain 7687 7 159138663 + 61362996 61363078 1 247249719 - 62796192 62796274 26921084
+82
+
+chain 7328 7 159138663 + 130260449 130260631 6 170899992 + 18975635 18975819 23797357
+8	121	123
+53
+
+chain 7084 7 159138663 + 155107000 155107125 8 146274826 + 127792382 127792507 21399384
+5	63	63
+57
+
+chain 6750 7 159138663 + 130268276 130268348 9 140273252 + 6309168 6309240 28699203
+72
+
+chain 6727 7 159138663 + 61364306 61364811 19 63811651 + 24391898 24393602 28746452
+47	400	1599
+58
+
+chain 6689 7 159138663 + 130262523 130267689 14 106368585 - 15396362 15401535 205901
+35	1928	1932
+35	3110	3113
+58
+
+chain 6657 7 159138663 + 130262248 130266269 20 62435964 - 53906684 53910704 204336
+68	3910	3909
+43
+
+chain 6632 7 159138663 + 61362621 61362691 14 106368585 - 25756639 25756709 18227251
+70
+
+chain 6604 7 159138663 + 61516196 61516266 14 106368585 + 18700177 18700247 29040667
+70
+
+chain 6561 7 159138663 + 61362487 61362621 5 180857866 - 77495083 77495217 25581093
+60	70	70
+4
+
+chain 6504 7 159138663 + 61563734 61563803 14 106368585 + 18700333 18700402 29292943
+69
+
+chain 6504 7 159138663 + 61457014 61457083 14 106368585 + 19014991 19015060 29292944
+69
+
+chain 6486 7 159138663 + 61439583 61439652 7 158821424 + 61677724 61677793 29330266
+69
+
+chain 6486 7 159138663 + 61453269 61453338 11 134452384 + 54672038 54672107 29330599
+69
+
+chain 6415 7 159138663 + 130266970 130267081 2 242951149 - 44689835 44689946 206027
+111
+
+chain 6395 7 159138663 + 61581171 61581239 12 132349534 + 36481345 36481413 29552558
+68
+
+chain 6295 7 159138663 + 130268491 130268558 12 132349534 - 16670768 16670835 29797454
+67
+
+chain 6222 7 159138663 + 61516757 61516823 7 158821424 - 100865546 100865612 29971261
+66
+
+chain 6149 7 159138663 + 61518444 61518509 9 140273252 - 73547747 73547812 30146556
+65
+
+chain 6147 7 159138663 + 61360661 61361459 1 247249719 - 99965931 99966729 2490905
+65	694	694
+39
+
+chain 6131 7 159138663 + 61545392 61545457 9 140273252 - 71283139 71283204 30224431
+65
+
+chain 6031 7 159138663 + 61649702 61649766 8 146274826 - 102385209 102385273 30479392
+64
+
+chain 5940 7 159138663 + 61567501 61567564 11 134452384 - 79723078 79723141 30715303
+63
+
+chain 5895 7 159138663 + 130261352 130261415 12 132349534 - 16670326 16670389 30822868
+63
+
+chain 5890 7 159138663 + 130272150 130272376 5 180857866 - 150003108 150003332 287879
+73	71	69
+82
+
+chain 5831 7 159138663 + 61540614 61540676 20 62435964 + 26207004 26207066 31016062
+62
+
+chain 5822 7 159138663 + 61534741 61534803 2 242951149 + 182601389 182601451 31037299
+62
+
+chain 5767 7 159138663 + 61657263 61657324 X 154913754 + 145511099 145511160 31173265
+61
+
+chain 5740 7 159138663 + 61561871 61561932 X 154913754 + 61825831 61825892 31255925
+61
+
+chain 5707 7 159138663 + 155133639 155133717 7 158821424 + 154826660 154826738 3248987
+78
+
+chain 5671 7 159138663 + 130267178 130267274 3 199501827 + 136865539 136865635 212140
+96
+
+chain 5649 7 159138663 + 61510793 61510853 14 106368585 + 18700200 18700260 31523979
+60
+
+chain 5614 7 159138663 + 61459620 61459680 8 146274826 + 85828676 85828736 12834914
+60
+
+chain 5505 7 159138663 + 130286091 130286151 11 134452384 + 126327988 126328048 18815467
+60
+
+chain 5376 7 159138663 + 61368713 61368770 5 180857866 - 134492854 134492911 32331066
+57
+
+chain 5358 7 159138663 + 130272706 130272763 4 191273063 - 62601703 62601760 32378845
+57
+
+chain 5239 7 159138663 + 61375927 61375982 3 199501827 + 176568366 176568421 32719676
+55
+
+chain 5238 7 159138663 + 155133561 155133639 7 158821424 + 154826660 154826738 3316763
+78
+
+chain 5212 7 159138663 + 48202742 48202797 Y 57772954 + 8140437 8140492 32786933
+55
+
+chain 5203 7 159138663 + 61362897 61362952 2 242951149 - 204521553 204521608 32840726
+55
+
+chain 5203 7 159138663 + 61514738 61514793 3 199501827 - 109094736 109094791 32841435
+55
+
+chain 5196 7 159138663 + 102270836 102270891 7 158821424 + 101958735 101958790 2864
+55
+
+chain 5085 7 159138663 + 61522548 61522602 11 134452384 - 85760698 85760752 33224588
+54
+
+chain 5081 7 159138663 + 61542952 61543361 X 154913754 - 96402533 96402599 33252017
+22	343	0
+44
+
+chain 5076 7 159138663 + 61566776 61566830 X 154913754 + 58536057 58536111 33266851
+54
+
+chain 5003 7 159138663 + 321166 321219 9 140273252 + 26769862 26769915 33490833
+53
+
+chain 4985 7 159138663 + 61511756 61511809 X 154913754 + 58510881 58510934 33583214
+53
+
+chain 4976 7 159138663 + 61453966 61454019 11 134452384 + 48695047 48695100 33600288
+53
+
+chain 4976 7 159138663 + 61579973 61580026 12 132349534 + 36420396 36420449 33600992
+53
+
+chain 4967 7 159138663 + 61528283 61528336 2 242951149 - 102597577 102597630 33622422
+53
+
+chain 4930 7 159138663 + 61528065 61528117 11 134452384 - 85701922 85701974 33735561
+52
+
+chain 4921 7 159138663 + 61566142 61566194 3 199501827 - 104503080 104503132 33762259
+52
+
+chain 4903 7 159138663 + 61364673 61364725 9 140273252 + 69253479 69253531 33844300
+52
+
+chain 4894 7 159138663 + 61535225 61535277 X 154913754 + 61822223 61822275 33894839
+52
+
+chain 4894 7 159138663 + 61555289 61555341 X 154913754 - 93093366 93093418 33894887
+52
+
+chain 4894 7 159138663 + 61367691 61367743 11 134452384 + 48824621 48824673 33895037
+52
+
+chain 4876 7 159138663 + 61446263 61446315 11 134452384 + 54670005 54670057 33929755
+52
+
+chain 4860 7 159138663 + 61671055 61671121 6 170899992 - 77150208 77150274 16663217
+66
+
+chain 4803 7 159138663 + 61582505 61582556 5 180857866 + 46128392 46128443 34201035
+51
+
+chain 4803 7 159138663 + 61548133 61548184 5 180857866 - 134730739 134730790 34201101
+51
+
+chain 4803 7 159138663 + 61656299 61656350 8 146274826 - 102385679 102385730 34201707
+51
+
+chain 4803 7 159138663 + 61371246 61371297 20 62435964 + 26207164 26207215 34201851
+51
+
+chain 4803 7 159138663 + 61538491 61538542 X 154913754 + 61822744 61822795 34202106
+51
+
+chain 4803 7 159138663 + 61550591 61550642 X 154913754 - 96402828 96402879 34202170
+51
+
+chain 4794 7 159138663 + 61568385 61568436 12 132349534 - 30627763 30627814 34229426
+51
+
+chain 4794 7 159138663 + 61560404 61560455 X 154913754 + 58511165 58511216 34229878
+51
+
+chain 4785 7 159138663 + 61555628 61555679 5 180857866 + 49580248 49580299 34261015
+51
+
+chain 4757 7 159138663 + 155127495 155127545 7 158821424 + 154820841 154820891 34330191
+50
+
+chain 4745 7 159138663 + 61527127 61527200 1 247249719 - 196249350 196249423 12580328
+73
+
+chain 4730 7 159138663 + 61454627 61454677 X 154913754 - 93091546 93091596 34451023
+50
+
+chain 4721 7 159138663 + 61547785 61547835 14 106368585 + 19015139 19015189 34474345
+50
+
+chain 4712 7 159138663 + 61542078 61542128 7 158821424 - 97143221 97143271 34536293
+50
+
+chain 4712 7 159138663 + 61650232 61650282 7 158821424 + 61292872 61292922 34536325
+50
+
+chain 4712 7 159138663 + 61447406 61447456 12 132349534 - 95867613 95867663 34536696
+50
+
+chain 4712 7 159138663 + 61573362 61573412 11 134452384 - 79778078 79778128 34537090
+50
+
+chain 4694 7 159138663 + 61361784 61361834 20 62435964 + 26208957 26209007 34582417
+50
+
+chain 4533 7 159138663 + 61657325 61657373 14 106368585 - 60354968 60355016 14458107
+48
+
+chain 4330 7 159138663 + 61571756 61571802 X 154913754 + 58511174 58511220 34815702
+46
+
+chain 4322 7 159138663 + 61527200 61527268 1 247249719 + 66112503 66112571 10645536
+68
+
+chain 4309 7 159138663 + 130262963 130263031 20 62435964 + 59813 59881 233275
+68
+
+chain 4243 7 159138663 + 130267293 130267390 15 100338915 - 46124324 46124421 430805
+97
+
+chain 4225 7 159138663 + 130272413 130272571 3 199501827 - 60665919 60666077 310359
+158
+
+chain 4225 7 159138663 + 130275130 130275387 10 135374737 + 61126513 61126771 1703431
+71	112	113
+74
+
+chain 4135 7 159138663 + 61657814 61657864 4 191273063 - 103880681 103880731 24177091
+50
+
+chain 4106 7 159138663 + 130265690 130265763 2 242951149 + 45160326 45160399 259070
+73
+
+chain 4049 7 159138663 + 61417706 61417751 19 63811651 + 35324192 35324237 995629
+45
+
+chain 4036 7 159138663 + 102224324 102224366 7 158821424 + 102110621 102110663 1050243
+42
+
+chain 3993 7 159138663 + 130270112 130270163 3 199501827 - 142320121 142320172 24066397
+51
+
+chain 3975 7 159138663 + 130269077 130269119 8 146274826 + 76339197 76339239 33761016
+42
+
+chain 3839 7 159138663 + 61659187 61659228 7 158821424 - 97183039 97183080 35036445
+41
+
+chain 3820 7 159138663 + 143397897 143397937 7 158821424 - 15657354 15657394 1380183
+40
+
+chain 3770 7 159138663 + 130272223 130272265 7 158821424 - 144399150 144399192 18136384
+42
+
+chain 3724 7 159138663 + 61669828 61671669 18 76117153 - 60916397 60916965 5934170
+170	1399	126
+50	156	156
+66
+
+chain 3694 7 159138663 + 130276177 130276253 X 154913754 + 40955942 40956018 2422661
+76
+
+chain 3685 7 159138663 + 102274757 102274796 7 158821424 + 101962659 101962698 2923
+39
+
+chain 3592 7 159138663 + 102246649 102246687 7 158821424 + 101934491 101934529 2920
+38
+
+chain 3540 7 159138663 + 61670988 61671026 1 247249719 - 1293349 1293387 6950988
+38
+
+chain 3536 7 159138663 + 155127890 155127927 7 158821424 + 154820516 154820553 31559480
+37
+
+chain 3321 7 159138663 + 130259738 130259803 5 180857866 + 117134963 117135028 22545496
+65
+
+chain 3254 7 159138663 + 155127171 155127205 7 158821424 + 154821284 154821318 30495954
+34
+
+chain 3179 7 159138663 + 61671122 61671197 3 199501827 + 3741295 3741370 21259213
+75
+
+chain 3139 7 159138663 + 61669998 61670032 7 158821424 - 73313700 73313734 35261607
+34
+
+chain 3136 7 159138663 + 155133873 155133906 7 158821424 + 154826660 154826693 3164897
+33
+
+chain 3128 7 159138663 + 61657490 61657523 14 106368585 + 19500965 19500998 15505654
+33
+
+chain 3124 7 159138663 + 61362864 61362897 13 114142980 - 56785908 56785941 33122705
+33
+
+chain 3114 7 159138663 + 61363362 61363395 11 134452384 + 38920746 38920779 30450202
+33
+
+chain 3035 7 159138663 + 130267390 130267459 5 180857866 + 148307658 148307727 349562
+69
+
+chain 3005 7 159138663 + 130258675 130258738 3 199501827 - 66319298 66319361 23438786
+63
+
+chain 2998 7 159138663 + 61670741 61670826 2 242951149 - 144372974 144373059 5019535
+68	11	11
+6
+
+chain 2929 7 159138663 + 61366904 61366935 9 140273252 + 69000834 69000865 35330365
+31
+
+chain 2883 7 159138663 + 130274908 130276723 12 132349534 - 84232022 84233270 1810563
+34	1716	687
+63	1	463
+1
+
+chain 2844 7 159138663 + 61525923 61525953 11 134452384 + 42874872 42874902 16620335
+30
+
+chain 2837 7 159138663 + 155133483 155133522 7 158821424 + 154826738 154826777 5314872
+39
+
+chain 2752 7 159138663 + 130270309 130270363 15 100338915 - 53351487 53351541 22720352
+54
+
+chain 2749 7 159138663 + 61657932 61657999 9 140273252 + 120725102 120725169 13790105
+67
+
+chain 2677 7 159138663 + 61657615 61657668 2 242951149 - 80490248 80490301 14907722
+53
+
+chain 2675 7 159138663 + 61657868 61657928 14 106368585 - 67199431 67199491 8049700
+60
+
+chain 2656 7 159138663 + 61658132 61658174 14 106368585 - 39618235 39618277 11504442
+42
+
+chain 2625 7 159138663 + 61376053 61376101 2 242951149 - 165273826 165273874 3000213
+48
+
+chain 2574 7 159138663 + 130285941 130286005 3 199501827 + 177805790 177805854 20115306
+64
+
+chain 2555 7 159138663 + 61657373 61657490 10 135374737 + 110991454 110991571 9489838
+117
+
+chain 2533 7 159138663 + 130255333 130255360 5 180857866 + 110504974 110505001 34260994
+27
+
+chain 2525 7 159138663 + 155133522 155133561 7 158821424 + 154826699 154826738 3760022
+39
+
+chain 2511 7 159138663 + 130261431 130261481 6 170899992 - 80902268 80902318 240832
+50
+
+chain 2491 7 159138663 + 130275062 130277276 7 158821424 + 139777825 139778654 1647744
+34	1723	339
+29	404	403
+24
+
+chain 2465 7 159138663 + 102229230 102229256 7 158821424 + 101917063 101917089 2852
+26
+
+chain 2367 7 159138663 + 61656836 61656861 8 146274826 - 114798799 114798824 27799318
+25
+
+chain 2262 7 159138663 + 61363303 61363362 15 100338915 - 25052381 25052440 19971588
+59
+
+chain 2184 7 159138663 + 61360913 61360944 16 88827254 + 45047397 45047428 3009512
+31
+
+chain 2183 7 159138663 + 61655805 61655828 8 146274826 - 102376418 102376441 35497387
+23
+
+chain 2181 7 159138663 + 61362804 61362827 8 146274826 - 64142945 64142968 28339747
+23
+
+chain 2177 7 159138663 + 61363497 61363520 15 100338915 - 57516283 57516306 24810342
+23
+
+chain 2111 7 159138663 + 102252256 102252279 7 158821424 + 101940282 101940305 3979
+23
+
+chain 2085 7 159138663 + 61668033 61668084 9 140273252 + 42719058 42719109 1926685
+51
+
+chain 2073 7 159138663 + 130274605 130277252 2 242951149 - 168073547 168075372 1534321
+53	350	351
+52	688	693
+76	1025	208
+32	309	298
+62
+
+chain 2067 7 159138663 + 155127207 155127236 7 158821424 + 154821033 154821062 24052540
+29
+
+chain 2049 7 159138663 + 130259609 130260449 2 242951149 + 217320568 217321411 19749334
+52	691	694
+97
+
+chain 1867 7 159138663 + 61360944 61360976 1 247249719 + 146935382 146935414 2538402
+32
+
+chain 1866 7 159138663 + 130286570 130286642 8 146274826 + 120193638 120193710 13784733
+72
+
+chain 1860 7 159138663 + 130271889 130271917 3 199501827 + 158050218 158050246 8145167
+28
+
+chain 1834 7 159138663 + 130267107 130267162 2 242951149 - 74722759 74722814 2183237
+55
+
+chain 1810 7 159138663 + 434399 434426 8 146274826 + 50019771 50019798 1840028
+27
+
+chain 1807 7 159138663 + 61459483 61459516 20 62435964 - 10907955 10907988 13772492
+33
+
+chain 1749 7 159138663 + 61534521 61534560 8 146274826 - 57707270 57707309 18613209
+39
+
+chain 1741 7 159138663 + 130275927 130275994 3 199501827 - 85253648 85253715 1907688
+67
+
+chain 1725 7 159138663 + 130286346 130286404 5 180857866 - 156929708 156929766 24410167
+58
+
+chain 1675 7 159138663 + 61360800 61360833 2 242951149 - 151940057 151940090 10244640
+33
+
+chain 1649 7 159138663 + 61527639 61527689 10 135374737 - 21832678 21832728 15020107
+50
+
+chain 1626 7 159138663 + 61525699 61525759 5 180857866 + 119849560 119849620 22270263
+60
+
+chain 1538 7 159138663 + 130271917 130271979 X 154913754 + 106499092 106499154 335529
+62
+
+chain 1512 7 159138663 + 130270436 130270487 7 158821424 + 123638895 123638946 23964536
+51
+
+chain 1449 7 159138663 + 61671198 61671257 11 134452384 + 48551200 48551259 6005368
+59
+
+chain 1444 7 159138663 + 130272046 130272150 5 180857866 - 107650838 107650942 1109190
+41	46	46
+17
+
+chain 1406 7 159138663 + 130268385 130269191 13 114142980 + 104373808 104374629 24734362
+65	682	697
+59
+
+chain 1391 7 159138663 + 130271979 130272046 12 132349534 + 128856107 128856174 572332
+67
+
+chain 1342 7 159138663 + 130255652 130255716 6 170899992 - 118498216 118498280 24733557
+64
+
+chain 1277 7 159138663 + 61525407 61525458 14 106368585 - 54569941 54569992 25208354
+51
+
+chain 1239 7 159138663 + 61657050 61657132 1 247249719 + 60704689 60704771 10216239
+82
+
+chain 1222 7 159138663 + 24387 24410 9 140273252 - 34976 34999 792
+23
+
+chain 1201 7 159138663 + 130267591 130267617 3 199501827 - 22519451 22519477 371093
+26
+
+chain 1176 7 159138663 + 61533413 61533439 9 140273252 + 78066621 78066647 21815254
+26
+
+chain 1159 7 159138663 + 130255953 130256003 18 76117153 + 30232927 30232977 26680295
+50
+
+chain 1143 7 159138663 + 130272637 130272705 4 191273063 - 164951872 164951940 23193314
+68
+
+chain 1120 7 159138663 + 130267081 130267107 4 191273063 + 53894987 53895013 453066
+26
+
+chain 1090 7 159138663 + 61375539 61375583 16 88827254 - 2017000 2017044 2867569
+44
+
+chain 967 7 159138663 + 61363930 61363960 5 180857866 - 77417997 77418027 26429199
+30
+
+chain 922 7 159138663 + 130269744 130269794 6 170899992 - 168370205 168370255 24919326
+50
+
+chain 916 7 159138663 + 130272376 130272413 7 158821424 - 119807072 119807109 361270
+37
+
+chain 903 7 159138663 + 130274518 130274571 18 76117153 + 7087852 7087905 2747041
+53
+
+chain 875 7 159138663 + 61656861 61656912 1 247249719 - 3737712 3737763 19994037
+51
+
+chain 825 7 159138663 + 130276127 130276177 9 140273252 + 78760365 78760415 3856900
+50
+
+chain 821 7 159138663 + 61657151 61657205 18 76117153 - 50729761 50729815 10763263
+54
+
+chain 764 7 159138663 + 155106965 155107000 2 242951149 - 97843675 97843710 19287766
+35
+
+chain 760 7 159138663 + 130260179 130260244 15 100338915 - 29035916 29035981 5017751
+65
+
+chain 738 7 159138663 + 61528144 61528186 5 180857866 + 37689556 37689598 26578239
+42
+
+chain 665 7 159138663 + 61657587 61657615 4 191273063 - 56344538 56344566 26451583
+28
+
+chain 506 7 159138663 + 130259438 130259491 7 158821424 - 81365049 81365102 23441660
+53
+
+chain 492 7 159138663 + 130276335 130276363 8 146274826 - 17074751 17074779 8865204
+28
+
+chain 466 7 159138663 + 130268939 130269012 2 242951149 - 225017173 225017246 26097376
+73
+
+chain 388 7 159138663 + 130271813 130271889 3 199501827 + 120370918 120370994 4694596
+76
+
+chain 379 7 159138663 + 130275097 130275130 3 199501827 + 9586745 9586778 4580558
+33
+
+chain 379 7 159138663 + 61363702 61363740 5 180857866 - 91082220 91082258 29303651
+38
+
+chain 348 7 159138663 + 102200504 102200535 7 158821424 - 57045045 57045076 1079
+31
+
+chain 13484003737 8 146364022 + 10000 146304022 8 146274826 + 0 146274826 9
+930417	1243	1
+52	10	10
+91	972	0
+54	54	0
+281	324	0
+289	1	0
+2323216	0	1
+3352649	0	2
+854996	50000	100000
+3399023	1	1
+46	1	1
+13965	1	1
+30	1	1
+121189	1	1
+35	1	1
+283700	1	0
+719291	93054	100016
+1155	2	0
+755	26	26
+980	21	21
+1479	422	422
+3229	0	1
+1937	1	1
+17	1	1
+322	0	1
+1758	0	2
+1141	1	0
+956	48	48
+1765	1	0
+543	25	25
+7047	15	15
+1029	1	1
+28	1	1
+314	1	1
+46	1	1
+164	1	1
+25	1	1
+5130707	1	0
+1288	1	0
+446	1	1
+80	1	1
+2123	4	4
+2514	0	3
+545	0	9
+527	1	1
+18	1	1
+256	9	9
+79	1	1
+40	1	1
+148	2	0
+2236	27	0
+953	1	1
+20	1	1
+2487	1	1
+113	1	1
+73	13	13
+365	10	10
+151	1	1
+32	0	3
+26	1	1
+1480	1	1
+29	1	1
+621	1	1
+28	1	1
+701	9	9
+362	1	1
+19	1	1
+691	1	1
+45	0	6
+46	1	1
+513	11	12
+382	1	1
+22	1	1
+111	1	1
+36	1	1
+337	1	1
+42	1	1
+602	0	2
+36	1	1
+475	1	1
+23	1	0
+32	3	4
+65	1	1
+59	1	1
+688	1	1
+22	1	1
+1473	1	1
+36	1	1
+372	1	1
+16	6	6
+640	25	25
+940	1	1
+38	1	1
+816	1	1
+17	0	1
+374	1	1
+17	1	1
+48	0	1
+82	1	1
+45	1	1
+263	1	1
+23	1	1
+204	1	1
+39	1	1
+2341	1	0
+2989	1	0
+9	1	0
+811	8	8
+741	2	0
+337	1	1
+25	4	4
+763	1	1
+19	1	1
+343	1	1
+31	1	1
+1953	1	1
+74	1	1
+67	1	1
+18	4	4
+73	1	1
+31	1	1
+114	1	11
+87	1	1
+65	1	1
+125	9	9
+378	0	1
+47	1	1
+90	1	1
+96	0	1
+176	7	13
+696	1	0
+6184	13	13
+830	13	13
+128	1	1
+37	1	1
+136	0	1
+66	6	5
+870	0	1
+4877	1	0
+585	7	3
+1728	0	1
+33	1	1
+465	1	1
+68	1	1
+581	0	6
+2088	0	1
+304	1	0
+2674	1	1
+28	0	1
+54	8	8
+846	1	0
+1409	16	16
+559	1	0
+401	5	0
+17	1	5
+29	1	1
+4051	1	1
+10	1	0
+43	1	1
+385	1	1
+35	1	1
+101	11	11
+602	0	1
+491	16	14
+1366	19	19
+321	1	1
+49	1	1
+546	1	1
+25	1	1
+1333	28	28
+1207	1	1
+51	0	4
+159	1	0
+1040	1	0
+1682	4	0
+34	0	8
+867	1	1
+17	1	1
+587	1	1
+21	1	1
+904	1	0
+261	1	0
+1151	2	0
+2325	5	5
+5415	3	0
+1545	0	1
+428	4	4
+1950	0	2
+1073	1	0
+3658	86	0
+1278	1	1
+79	1	1
+6656	12	12
+1550	18	0
+5832	0	1
+4835	10	10
+1719	1	1
+84	1	1
+848	2	0
+236	1	1
+42	1	1
+1286	0	12
+35	1	1
+820	1	1
+22	0	1
+63	22	0
+167	23	23
+315	8	8
+983	0	6
+539	14	14
+863	2	0
+27	1	1
+204	14	14
+163	4	4
+290	1	1
+59	1	1
+842	2	0
+2044	1	1
+90	1	0
+3434	3	0
+356	1	0
+873	1	0
+864	1	25
+630	7	12
+62	1	1
+88	1	1
+76	11	11
+1366	17	17
+156	4	4
+244	18	4
+505	0	1
+109	1	1
+230	1	1
+107	3	4
+150	1	1
+83	5	5
+70	1	1
+33	0	1
+142	1	1
+626	6	5
+274	10	10
+128	1	1
+35	1	1
+216	1	1
+44	1	1
+312	18	18
+1496	7	8
+451	1	0
+212	14	14
+629	1	1
+20	1	1
+350	1	1
+62	1	1
+617	10	10
+845	1	1
+58	1	1
+2189	1	1
+147	1	1
+475	1	1
+27	1	1
+278	1	1
+17	1	1
+994	1	1
+40	1	1
+219	5	5
+26	1	1
+900	1	1
+29	0	1
+26	1	1
+484	16	15
+61	9	9
+114	26	21
+801	1	1
+33	1	1
+465	32	32
+63	1	1
+37	1	1
+80	14	14
+211	1	1
+43	1	1
+156	1	1
+20	1	1
+685	1	1
+67	0	4
+711	1	1
+38	1	1
+402	7	7
+1045	1	1
+37	1	1
+4035	9	9
+247	0	4
+4146274	5734	17400
+330366	1	0
+2346742	55	0
+413177	0	3
+450	0	1
+9436	1	3
+7044	0	4
+2886	0	1
+635	0	1
+16567	0	1
+6918	0	1
+9285	0	1
+14909	0	8
+12879	0	2
+3330	0	2
+2673376	0	2
+2173174	7	7
+29817	2485	66108
+6473782	5	5
+39	1	1
+9574	2	0
+5879	1	1
+29	1	1
+6139	0	1
+2354	1	1
+28	1	1
+91	1	1
+23	0	1
+62	1	1
+142	15	16
+54	1	1
+22	3	3
+1479	4	4
+221	4	4
+132	0	1
+574	11	11
+23	0	1
+604	1	1
+44	1	1
+899	0	1
+70	10	12
+13561	1	1
+44	1	1
+4476	4	4
+799	25	26
+1466	18	18
+17896	0	4
+1668	0	1
+4250	1	1
+44	1	0
+4	1	0
+11	1	1
+4956	1	1
+18	0	1
+39	2	3
+4990	1	1
+47	13	13
+68	0	4
+9730	0	1
+355	1	0
+2186	1	1
+37	1	1
+6111	3	3
+100	4	4
+68	1	1
+43	1	1
+1126	7	5
+5520	8	8
+2316	1	1
+181	6	6
+50	1	1
+29	0	1
+83	1	1
+1073	150	154
+100	398	0
+141	1	1
+25272	1	0
+2132	4	0
+2522	1	1
+48	1	1
+1498528	1	0
+6044582	3000000	3000008
+1291149	16655	60038
+3837	0	3
+811	0	1
+2567	0	1
+7375465	1	0
+10	0	1
+42062	0	1
+19604621	0	1
+10692667	0	1
+110	1	0
+3577	3	0
+907	1	1
+18	1	1
+528	1	1
+50	1	1
+317	1	1
+64	251	535
+21	1	0
+140	1	0
+70	0	1
+77	10	9
+227	0	1
+142	5	5
+57	14	14
+43	1	1
+31034	99683	124100
+2301	2	0
+44	0	2
+568015	186612	87300
+355	5	5
+1916	3085	0
+924	4	0
+339	211	211
+963	14	15
+1157	12194	0
+242	23	23
+56	15	15
+405	20	20
+955	49	49
+1347	1	1
+2289	51	51
+555	253	253
+1723	77	77
+396	13	13
+112	3085	0
+3945	0	1
+209	23	23
+69	22	22
+81	20	20
+696	20	20
+58	69	69
+100	13	13
+326	137	137
+151	35	35
+1804	37	37
+1548	26	26
+324	23	23
+1932	17	17
+111	47	47
+128	16	16
+78	30	30
+1022	10	6
+78	0	1
+342	31	31
+86	23	23
+1580	255	255
+170	10	10
+398	23	23
+419	20	20
+955	55	55
+1139	11	11
+1925	276	0
+223	1	1
+56	1	1
+702	5	5
+17	3	3
+1030	1	1
+21	1	1
+363	1	1
+30	1	1
+785	16	16
+78	13	13
+1036	4	0
+482	68	68
+1069	10	10
+321	200	200
+434	43	43
+798	20	20
+56	25	25
+1007	5	5
+1198	24	24
+689	0	3
+743	32	32
+817	43	43
+574	11	11
+760	69	69
+1229	32	32
+272	29	29
+106	97	97
+1309	46	46
+850	4	4
+777	62	62
+86	36	36
+374	93	93
+2076	31	31
+195	56	56
+379	80	80
+64	11	11
+191	18	18
+1051	13	13
+52	119	113
+1347	1	1
+25	1	1
+3451	188	0
+3097	9	0
+2715	0	1
+11829	3	0
+6000	0	28
+10729	1	0
+3770769	0	1
+62	0	1
+22	0	1
+827	0	1
+1485	0	1
+242	1	0
+7142	0	1
+4029	3	3
+69	1	1
+15865	0	1
+83461	0	4
+5978	0	9
+2661	0	1
+1483	0	1
+15868	0	4
+17798	0	1
+2649	0	1
+3627	0	1
+4789	0	1
+9541	0	1
+6844	0	1
+3187	0	2
+411	0	14
+3056	0	4
+19776	0	3
+29085	1	0
+745	0	2
+11453	0	2
+16739	0	1
+14697	0	1
+8539	0	1
+25514443	0	1
+17680	1	0
+55359	1	0
+58	13	11
+5	1	0
+6	1	0
+5	1	0
+22	0	1
+4	1	3
+1515	0	1
+1111	0	1
+5736	6	6
+66213	0	1
+68	1	1
+24	7	6
+43	1	1
+33414	7	7
+22	1	1
+12288	22	22
+7002	1	0
+8588	1	1
+31	1	1
+15969	1	1
+32	1	1
+27034	1	1
+42	1	1
+3352	1	0
+15009	0	1
+20433	18	18
+32141	8	9
+116	41	41
+4920	0	1
+33364	0	1
+11160	1	0
+15	1	0
+28423	0	1
+43835	1	1
+24	2	4
+269244	4	4
+37	1	1
+17193	3	4
+53	11	12
+23	1	2
+7	1	1
+37978	9	9
+37743	1	1
+35	3	3
+26636	1	1
+17	1	1
+8728292	0	1
+16734777	71275	0
+657026	2	0
+2911	2	0
+1941	1	1
+35	1	1
+835	1	1
+116	1	1
+399	1	1
+101	0	1
+194	2	1
+450	0	1
+825	1	1
+73	1	1
+156	1	1
+58	1	1
+50	5	5
+153	11	11
+189	5	5
+233	1	1
+83	1	1
+642	1	0
+1380	1	1
+17	1	1
+315	1	1
+26	1	1
+789	901	0
+73	1	1
+45	1	1
+535	1	1
+34	1	1
+2007	7	7
+159	1	1
+26	1	1
+6362	13	13
+504325	25635	100008
+420771	232	0
+287688	104	0
+65	364	0
+183	55	0
+93	1	1
+46	1	1
+4002	1	1
+24	1	1
+190	0	147
+65	2	1
+8	0	1
+39	2	591
+306	50	0
+1938	1	0
+578	0	684
+291	1	0
+572289	108288	7108
+480202	0	1
+11866	6	6
+26917	1	0
+6097	15	15
+3074	1	0
+12292	1	0
+2209	1	0
+7358	1	0
+321393
+
+chain 2607822 8 146364022 + 12061935 12091854 8 146274826 + 12348580 12378713 990
+895	20	0
+1391	22	21
+53	88	0
+99	36	0
+9	0	346
+255	0	44
+496	1	0
+1013	0	4
+1698	1	0
+1054	37	37
+915	52	54
+2295	9	9
+123	1	0
+1295	162	162
+2903	50	50
+913	24	24
+2382	1	0
+299	85	85
+61	27	16
+1351	37	37
+974	4	4
+571	1	0
+530	11	0
+572	18	18
+76	4	4
+398	0	2
+54	31	31
+115	37	37
+125	364	364
+70	47	47
+56	8	8
+979	57	57
+248	50	50
+65	100	100
+82	1	0
+428	34	34
+51	6	0
+156	66	66
+257	132	132
+56	49	49
+91	19	19
+67	38	37
+142	6	6
+249	17	17
+123	104	104
+190	36	37
+355	5	1
+161	1	0
+89	48	48
+62	38	38
+136	67	67
+839
+
+chain 2498503 8 146364022 + 86726531 86754632 8 146274826 - 59364826 59419953 1092
+268	2	2
+114	6	0
+49	13	13
+1051	18	18
+117	8	3
+81	1	1
+64	4	4
+73	3	3
+379	1	1
+54	1	1
+183	13	13
+374	1	1
+43	1	1
+874	2	2
+22	1	1
+56	20	20
+712	1	1
+91	1	1
+374	1	1
+73	1	1
+88	21	21
+83	1	1
+27	1	1
+302	29	29
+1591	1	1
+27	4	0
+1250	1	1
+20	1	1
+2246	10	9115
+1002	49	49
+314	4	4
+116	32	32
+363	23	23
+1050	13	13
+119	0	8829
+1050	16	16
+1869	31	31
+119	0	9106
+593	13	13
+396	77	77
+1017	32	32
+888	39	39
+2895	1	1
+964	43	43
+1769	15	15
+292	35	35
+97	5	5
+313	13	13
+248	40	40
+435	10	11
+129	6	6
+712
+
+chain 1152177 8 146364022 + 142754466 142766515 8 146274826 + 142956164 142968213 2035
+12049
+
+chain 1081960 8 146364022 + 86772301 86823828 8 146274826 + 86857153 86905309 683
+56	15	15
+405	21	21
+1003	383	383
+837	0	1
+126	1	1
+531	1	0
+794	1	0
+73	32	32
+817	43	43
+214	432	432
+212	114	114
+373	28	28
+159	32	32
+832	44	44
+217	192	192
+330	927	923
+88	39	40
+1839	279	279
+283	13	13
+143	1716	1717
+49	3637	3637
+51	555	555
+97	1	1
+21	1	1
+133	1723	1723
+13	16	16
+48	8749	5664
+69	439	439
+62	43	43
+32	151	151
+35	1804	1804
+37	1548	1272
+26	2407	2407
+32	1719	1716
+31	1784	1784
+160	1995	1995
+55	3075	3075
+276	4870	4866
+68	1429	1429
+83	21	21
+67	434	434
+36
+
+chain 801068 8 146364022 + 145324300 145332588 8 146274826 + 145464193 145472508 5275
+3979	8	0
+2057	0	35
+2244
+
+chain 744541 8 146364022 + 86754632 86807992 8 146274826 + 86857851 86901670 688
+637	20	20
+440	88	88
+964	1	1
+2289	52	52
+554	1	1
+37	1	1
+1606	46	43
+288	6565	395
+203	3612	3608
+265	1500	1501
+278	1	1
+104	3213	3212
+43	214	214
+138	26	26
+268	212	212
+80	594	594
+32	832	832
+34	227	227
+16	27	27
+149	330	330
+33	21	21
+873	88	85
+39	1839	1839
+229	17	17
+33	9021	8745
+425	14725	11640
+30
+
+chain 657279 8 146364022 + 12141854 12149156 8 146274826 + 11932698 11940000 7963
+232	8	8
+466	34	34
+801	48	48
+815	68	68
+1203	29	29
+407	31	31
+467	26	26
+1146	18	18
+1503
+
+chain 521724 8 146364022 + 12149156 12156927 8 146274826 + 11940000 11947772 4417
+2168	0	1
+503	25	25
+153	202	202
+106	107	107
+851	39	39
+1679	1912	1912
+26
+
+chain 511532 8 146364022 + 142816515 142822092 8 146274826 + 142814667 142820000 26584
+2797	244	0
+2536
+
+chain 345755 8 146364022 + 142822092 142825705 8 146274826 + 142820000 142823612 174979
+3531	1	0
+81
+
+chain 305790 8 146364022 + 86765339 86795897 8 146274826 + 86865470 86901765 930
+477	0	9106
+123	31	31
+1705	14	14
+503	14	14
+15	1470	1466
+91	31	31
+52	35	35
+2	7890	7613
+26	560	560
+34	16750	13662
+405	127	127
+203
+
+chain 137107 8 146364022 + 85964683 85966170 8 146274826 + 86036733 86038220 940425
+1283	19	19
+185
+
+chain 118247 8 146364022 + 86759071 86769900 8 146274826 + 86874481 86903237 1649
+52	2533	2530
+13	16	16
+1046	0	8829
+123	13	13
+196	2878	11983
+29	3812	3808
+31	52	52
+35
+
+chain 97713 8 146364022 + 86793362 86840444 8 146274826 + 86862935 86885634 1255
+1752	44	44
+4	38618	14235
+46	1631	1631
+62	86	86
+36	374	374
+93	2302	2302
+56	379	379
+80	1400	1400
+119
+
+chain 85095 8 146364022 + 85924850 85927320 2 242951149 - 28701067 28703532 1485529
+52	143	142
+173	208	208
+107	181	181
+68	70	66
+129	101	101
+183	373	373
+87	163	163
+164	198	198
+70
+
+chain 47407 8 146364022 + 85907218 85908847 10 135374737 - 19950497 19952126 2691979
+115	531	531
+182	240	240
+64	202	202
+122	22	22
+52	45	45
+54
+
+chain 45318 8 146364022 + 85909407 85911400 3 199501827 - 58732681 58734687 2832173
+138	151	157
+53	129	125
+171	674	685
+80	116	116
+82	347	347
+52
+
+chain 43260 8 146364022 + 12069066 12090712 8 146274826 - 138168279 138189929 1162
+37	915	915
+52	6789	6802
+48	3620	3620
+85	61	59
+27	1351	1348
+5	1	1
+30	3223	3218
+22	115	115
+37	465	465
+24	3764	3760
+90	837	842
+48
+
+chain 38958 8 146364022 + 12159413 12159829 8 146274826 + 11950258 11950674 3228
+416
+
+chain 38127 8 146364022 + 86726451 86753339 8 146274826 - 59376930 59524482 1121
+80	11856	20676
+48	435	435
+32	4503	13609
+31	1121	10227
+77	1017	94649
+32	888	888
+39	3860	3860
+15	1	1
+26	2078	2078
+33	678	678
+38
+
+chain 31437 8 146364022 + 85955665 85955994 3 199501827 - 6162711 6163040 4382021
+329
+
+chain 30755 8 146364022 + 85915208 85915710 8 146274826 - 4216734 4217241 4503764
+255	160	165
+87
+
+chain 27896 8 146364022 + 940417 941596 8 146274826 + 930633 930948 5586021
+100	54	0
+108	810	0
+107
+
+chain 26413 8 146364022 + 85978864 85981144 9 140273252 - 40203469 40205589 6324943
+79	1134	635
+70	83	416
+56	207	205
+56	22	22
+63	455	463
+55
+
+chain 25390 8 146364022 + 85975200 85975766 6 170899992 - 89617888 89618457 6830715
+67	141	143
+50	38	39
+54	78	78
+138
+
+chain 20285 8 146364022 + 85975766 85977415 3 199501827 - 82189783 82191451 9116338
+8	700	763
+50	465	465
+54	309	265
+63
+
+chain 20226 8 146364022 + 85979170 85979799 3 199501827 - 161413320 161413963 10270718
+61	394	408
+174
+
+chain 20141 8 146364022 + 12151827 12152420 8 146274826 + 11902715 11903309 638255
+25	153	154
+202	106	106
+107
+
+chain 19400 8 146364022 + 85925267 85925628 10 135374737 + 135080720 135081080 3597149
+102	2	1
+54	131	131
+72
+
+chain 18915 8 146364022 + 942460 942893 8 146274826 + 930516 930733 3835109
+63	162	0
+46	108	54
+54
+
+chain 18062 8 146364022 + 942088 942460 8 146274826 + 930684 930948 5250846
+157	108	0
+107
+
+chain 17886 8 146364022 + 943174 943431 8 146274826 + 930690 930893 4105167
+149	55	1
+53
+
+chain 15443 8 146364022 + 941596 942029 8 146274826 + 930516 930841 4827909
+64	207	153
+65	54	0
+43
+
+chain 14855 8 146364022 + 85924497 85927134 X 154913754 + 50874366 50877002 1910511
+90	57	57
+50	108	108
+48	52	52
+79	801	801
+50	953	952
+50	236	236
+63
+
+chain 12854 8 146364022 + 144743895 144744094 8 146274826 + 144814885 144815084 3961669
+199
+
+chain 12042 8 146364022 + 85907589 85907864 4 191273063 + 22500316 22500591 2841396
+81	177	177
+17
+
+chain 11713 8 146364022 + 36265496 36265620 7 158821424 - 150143040 150143164 19315609
+124
+
+chain 10744 8 146364022 + 85909592 85910073 4 191273063 - 317022 317498 3271263
+71	86	86
+68	232	227
+24
+
+chain 10295 8 146364022 + 85917935 85918395 16 88827254 - 19324120 19324578 22152835
+60	331	329
+69
+
+chain 9964 8 146364022 + 85927135 85927250 3 199501827 - 159900532 159900647 3087651
+115
+
+chain 9833 8 146364022 + 85908046 85908504 8 146274826 - 114124165 114124623 2795681
+56	59	59
+58	162	162
+123
+
+chain 9709 8 146364022 + 943330 943485 8 146274826 + 930684 930839 15332741
+48	53	53
+54
+
+chain 9657 8 146364022 + 86004292 86004501 X 154913754 + 27575363 27575573 23616431
+52	93	94
+64
+
+chain 9406 8 146364022 + 85945093 85945452 12 132349534 + 8944725 8945099 24220725
+61	243	258
+55
+
+chain 9151 8 146364022 + 85910121 85910218 10 135374737 - 38564811 38564908 24713323
+97
+
+chain 8406 8 146364022 + 85924386 85924476 5 180857866 + 127114677 127114767 25803856
+90
+
+chain 7367 8 146364022 + 85911400 85911623 X 154913754 - 44623158 44623382 4824008
+72	91	92
+60
+
+chain 7214 8 146364022 + 85983029 85983106 3 199501827 + 182981094 182981171 27755476
+77
+
+chain 7178 8 146364022 + 85926461 85926638 7 158821424 + 131250991 131251168 8959140
+97	79	79
+1
+
+chain 6913 8 146364022 + 85946010 85946083 5 180857866 - 76444763 76444836 28360557
+73
+
+chain 6866 8 146364022 + 85981016 85981089 3 199501827 - 137848275 137848348 18929141
+73
+
+chain 6722 8 146364022 + 85915749 85915820 6 170899992 - 41858720 41858791 28750065
+71
+
+chain 6523 8 146364022 + 85874468 85874538 6 170899992 + 80165568 80165638 29222062
+70
+
+chain 6284 8 146364022 + 48138290 48138355 12 132349534 - 99530740 99530805 29826800
+65
+
+chain 6255 8 146364022 + 86830665 86832268 8 146274826 + 86851473 86853076 5870
+41	1533	1533
+29
+
+chain 6230 8 146364022 + 143494784 143494849 8 146274826 + 143492621 143492686 29969115
+65
+
+chain 5949 8 146364022 + 85946624 85946687 7 158821424 - 150469376 150469439 30705065
+63
+
+chain 5930 8 146364022 + 86000088 86000150 4 191273063 - 114595117 114595179 30759641
+62
+
+chain 5722 8 146364022 + 85909210 85909271 4 191273063 - 32715229 32715290 31306692
+61
+
+chain 5681 8 146364022 + 85907187 85907519 7 158821424 - 141596962 141597294 3108677
+31	137	137
+3	85	85
+76
+
+chain 5594 8 146364022 + 85966181 85966240 2 242951149 + 129692100 129692159 31643052
+59
+
+chain 5348 8 146364022 + 85946168 85946224 X 154913754 + 22697258 22697314 32405249
+56
+
+chain 5330 8 146364022 + 85945000 85945056 X 154913754 - 56717679 56717735 32442268
+56
+
+chain 5292 8 146364022 + 85926370 85926785 12 132349534 + 42776733 42777148 2271290
+75	280	280
+14	27	27
+19
+
+chain 5161 8 146364022 + 941932 941986 8 146274826 + 930312 930366 21107216
+54
+
+chain 5012 8 146364022 + 85946286 85946339 1 247249719 - 150482359 150482412 33477745
+53
+
+chain 4929 8 146364022 + 941384 941435 8 146274826 + 930304 930355 33748771
+51
+
+chain 4927 8 146364022 + 85874401 85874458 12 132349534 + 21319375 21319432 33750711
+57
+
+chain 4920 8 146364022 + 85945525 85945576 10 135374737 + 87468307 87468358 33788347
+51
+
+chain 4810 8 146364022 + 942523 942621 8 146274826 + 930741 930839 7547023
+98
+
+chain 4803 8 146364022 + 85970009 85970060 11 134452384 + 10157776 10157827 34198727
+51
+
+chain 4793 8 146364022 + 85975065 85975115 21 46944323 - 30257577 30257627 34245350
+50
+
+chain 4738 8 146364022 + 942303 942352 8 146274826 + 930521 930570 34412340
+49
+
+chain 4461 8 146364022 + 85910862 85910919 X 154913754 + 151305652 151305709 4935543
+57
+
+chain 4271 8 146364022 + 86793237 86793293 8 146274826 + 86902190 86902246 1452514
+56
+
+chain 4178 8 146364022 + 85915489 85915539 3 199501827 + 132299011 132299061 5319224
+50
+
+chain 4079 8 146364022 + 85926268 85926343 2 242951149 - 211437807 211437882 2547607
+75
+
+chain 3965 8 146364022 + 85910617 85910659 5 180857866 + 105218926 105218968 18292131
+42
+
+chain 3826 8 146364022 + 85911256 85911310 7 158821424 + 49570162 49570216 23840400
+54
+
+chain 3809 8 146364022 + 86829249 86829292 8 146274826 + 86874439 86874482 7328
+43
+
+chain 3796 8 146364022 + 85928889 85929141 X 154913754 + 121492736 121492988 2565989
+99	40	40
+113
+
+chain 3755 8 146364022 + 85925629 85925714 5 180857866 + 141403818 141403903 2005326
+54	23	23
+8
+
+chain 3680 8 146364022 + 36265255 36265294 21 46944323 - 8931342 8931381 34138292
+39
+
+chain 3466 8 146364022 + 85917822 85917882 11 134452384 - 107659023 107659083 22827264
+60
+
+chain 3460 8 146364022 + 85925991 85926082 19 63811651 + 46688677 46688768 2544872
+91
+
+chain 3412 8 146364022 + 85981195 85981250 12 132349534 - 23016451 23016506 20760996
+55
+
+chain 3378 8 146364022 + 144744318 144744353 8 146274826 + 144814727 144814762 26884487
+35
+
+chain 3372 8 146364022 + 12064503 12064539 8 146274826 + 12351001 12351037 28926895
+36
+
+chain 3336 8 146364022 + 85910527 85910617 6 170899992 + 121091189 121091279 5885029
+90
+
+chain 3306 8 146364022 + 85975140 85975200 5 180857866 - 14200316 14200376 14215921
+60
+
+chain 3123 8 146364022 + 144455804 144455869 8 146274826 + 144526757 144526822 16634618
+65
+
+chain 3122 8 146364022 + 85910073 85910106 10 135374737 + 91515201 91515234 27999029
+33
+
+chain 2973 8 146364022 + 85975297 85975339 11 134452384 + 70894433 70894475 12515399
+42
+
+chain 2846 8 146364022 + 85980398 85980477 6 170899992 + 12780268 12780347 14041671
+79
+
+chain 2664 8 146364022 + 85980653 85980843 13 114142980 + 79661332 79661527 13462115
+54	70	75
+66
+
+chain 2542 8 146364022 + 86811232 86811259 8 146274826 + 86750599 86750626 581042
+27
+
+chain 2408 8 146364022 + 86780113 86780140 8 146274826 + 86901259 86901286 3284
+27
+
+chain 2314 8 146364022 + 85909329 85909403 5 180857866 - 126448590 126448664 8133335
+74
+
+chain 2312 8 146364022 + 85964546 85964619 5 180857866 - 22206487 22206560 13216855
+73
+
+chain 2306 8 146364022 + 85909062 85909878 5 180857866 - 76491094 76491924 7171448
+57	726	740
+33
+
+chain 2277 8 146364022 + 85945069 85945093 2 242951149 - 76417863 76417887 30610067
+24
+
+chain 2276 8 146364022 + 85915156 85915196 9 140273252 + 96271703 96271743 9134049
+40
+
+chain 2255 8 146364022 + 12171549 12171574 8 146274826 + 11962388 11962413 4339
+25
+
+chain 2213 8 146364022 + 85976678 85976734 10 135374737 + 107478570 107478626 23840391
+56
+
+chain 2193 8 146364022 + 85909817 85909844 1 247249719 - 204777828 204777855 6141044
+27
+
+chain 2188 8 146364022 + 85915463 85915489 4 191273063 + 117566433 117566459 5547542
+26
+
+chain 2086 8 146364022 + 85907670 85907692 9 140273252 + 84577624 84577646 25068333
+22
+
+chain 2042 8 146364022 + 85906786 85906876 1 247249719 - 187757137 187757227 3120497
+90
+
+chain 2008 8 146364022 + 85975339 85978010 12 132349534 - 60955403 60957663 7657094
+69	2448	2037
+58	20	20
+76
+
+chain 1976 8 146364022 + 85910386 85910476 11 134452384 + 108691426 108691516 10944711
+90
+
+chain 1915 8 146364022 + 85915895 85915946 2 242951149 - 57258601 57258652 18793758
+51
+
+chain 1706 8 146364022 + 85926558 85926608 20 62435964 + 52983902 52983952 9284939
+50
+
+chain 1666 8 146364022 + 85915539 85915568 3 199501827 - 58686941 58686970 11643280
+29
+
+chain 1625 8 146364022 + 85977632 85977856 3 199501827 - 45071352 45071581 10048168
+62	161	166
+1
+
+chain 1603 8 146364022 + 36265620 36265653 4 191273063 + 189716401 189716434 1596951
+33
+
+chain 1585 8 146364022 + 85907040 85907092 7 158821424 + 38674874 38674926 25744726
+52
+
+chain 1584 8 146364022 + 85964393 85964443 1 247249719 - 57954630 57954680 20174423
+50
+
+chain 1470 8 146364022 + 85911121 85911160 15 100338915 + 92120615 92120654 21684489
+39
+
+chain 1463 8 146364022 + 942731 942785 8 146274826 + 930679 930733 5019737
+54
+
+chain 1440 8 146364022 + 85911043 85911098 1 247249719 - 141715465 141715520 4313974
+55
+
+chain 1426 8 146364022 + 85978253 85978320 2 242951149 - 208172805 208172872 22624190
+67
+
+chain 1403 8 146364022 + 85928837 85929028 18 76117153 + 39707440 39707631 2816562
+52	99	99
+40
+
+chain 1344 8 146364022 + 85907124 85907170 12 132349534 + 45103963 45104009 16171151
+46
+
+chain 1332 8 146364022 + 85927450 85927503 1 247249719 - 29234742 29234795 3133635
+53
+
+chain 1287 8 146364022 + 85907361 85907411 1 247249719 - 78547145 78547195 4245040
+50
+
+chain 1276 8 146364022 + 85927323 85927376 4 191273063 - 93337200 93337253 2720957
+53
+
+chain 1269 8 146364022 + 85908257 85908286 9 140273252 - 124490379 124490408 3695355
+29
+
+chain 1238 8 146364022 + 85978601 85978678 9 140273252 - 23294193 23294270 19053025
+77
+
+chain 1193 8 146364022 + 144455743 144455792 8 146274826 + 144526504 144526553 26679478
+49
+
+chain 1175 8 146364022 + 12087452 12087488 11 134452384 - 63301652 63301688 1994288
+36
+
+chain 1137 8 146364022 + 85909119 85909164 2 242951149 + 35848313 35848358 13461114
+45
+
+chain 1048 8 146364022 + 86824709 86824734 8 146274826 + 86857705 86857730 2636
+25
+
+chain 1045 8 146364022 + 85911001 85911043 15 100338915 - 40210675 40210717 4055996
+42
+
+chain 1028 8 146364022 + 85910323 85910373 4 191273063 + 26203887 26203937 5050480
+50
+
+chain 1020 8 146364022 + 85924694 85924736 3 199501827 + 1701599 1701641 4262142
+42
+
+chain 1005 8 146364022 + 85977261 85977320 10 135374737 + 45388722 45388781 14596230
+59
+
+chain 998 8 146364022 + 85908847 85908872 4 191273063 + 183519567 183519592 8543079
+25
+
+chain 985 8 146364022 + 85918576 85918627 3 199501827 - 21820872 21820923 24828426
+51
+
+chain 981 8 146364022 + 144744094 144744133 8 146274826 + 144814821 144814860 14840226
+39
+
+chain 922 8 146364022 + 85918981 85919046 X 154913754 - 100261670 100261735 22334691
+65
+
+chain 912 8 146364022 + 85964449 85964513 6 170899992 + 131272389 131272453 24950513
+64
+
+chain 888 8 146364022 + 85915710 85915739 9 140273252 + 12069456 12069485 13568361
+29
+
+chain 867 8 146364022 + 85976220 85976271 X 154913754 - 36573362 36573413 23586363
+51
+
+chain 857 8 146364022 + 86832445 86832471 8 146274826 + 86747431 86747457 7742
+26
+
+chain 802 8 146364022 + 85978516 85978572 3 199501827 + 80520031 80520087 22639668
+56
+
+chain 801 8 146364022 + 85911160 85911249 16 88827254 + 31611661 31611750 16482423
+89
+
+chain 785 8 146364022 + 85917259 85917324 5 180857866 - 163179499 163179564 25049793
+65
+
+chain 721 8 146364022 + 85926739 85926765 18 76117153 + 15364211 15364237 2792298
+26
+
+chain 647 8 146364022 + 85918645 85918703 11 134452384 - 90657004 90657062 25582649
+58
+
+chain 612 8 146364022 + 941818 941867 8 146274826 + 930360 930409 12502809
+49
+
+chain 596 8 146364022 + 85976593 85979111 X 154913754 - 42670843 42673368 13030869
+53	2388	2395
+77
+
+chain 568 8 146364022 + 85966335 85966385 X 154913754 + 36275879 36275929 27751459
+50
+
+chain 474 8 146364022 + 85917714 85917772 1 247249719 + 62707004 62707062 26279221
+58
+
+chain 396 8 146364022 + 85977502 85977572 X 154913754 - 138803117 138803187 17501406
+70
+
+chain 369 8 146364022 + 85976646 85976678 7 158821424 + 51906674 51906706 15299893
+32
+
+chain 360 8 146364022 + 85980297 85980349 12 132349534 - 124024481 124024533 24774043
+52
+
+chain 337 8 146364022 + 85981293 85981372 1 247249719 - 152445011 152445090 12777550
+79
+
+chain 328 8 146364022 + 85976447 85976474 2 242951149 - 99982783 99982810 22051776
+27
+
+chain 310 8 146364022 + 85976849 85976905 3 199501827 - 69459686 69459742 25770085
+56
+
+chain 286 8 146364022 + 85979114 85979170 7 158821424 - 11181572 11181628 19756881
+56
+
+chain 232 8 146364022 + 85978010 85978057 1 247249719 + 108819891 108819938 19586297
+47
+
+chain 11336430536 9 141213431 + 10000 141153431 9 140273252 + 0 140273252 13
+189075	17	17
+39464594	50000	50000
+261110	50000	50000
+208233	50000	50000
+142805	50000	50000
+464507	50000	50000
+152873	50000	50000
+172579	50000	50000
+799200	4	0
+398958	50000	50000
+549743	100000	50000
+632871	50000	50000
+680077	50000	50000
+181647	50000	50000
+291910	100000	50000
+465318	50000	50000
+350909	50000	50000
+194609	100000	50000
+370337	176	0
+128581	100047	50047
+157499	18150000	18100000
+450681	50000	50000
+223855	50000	50000
+162441	50000	50000
+159539	50000	50000
+199148	50000	50000
+194491	100000	50000
+158462	150000	50000
+471702	150000	50000
+376183	150000	50000
+174765	150000	50000
+289439	50000	50000
+682157	50000	50000
+158187	100000	50000
+187806	50000	50000
+178933	100000	50000
+21507948	100000	50000
+85380	150000	50000
+834971	0	1
+39559293	150000	100000
+3818133	50000	200000
+2075804	50000	30000
+1936434
+
+chain 1179 9 141213431 + 46931376 46931552 9 140273252 - 98415895 98416071 50
+176
+
+chain 443 9 141213431 + 47160133 47160180 9 140273252 - 72994158 72994205 112
+47
+
+chain 1574309 MT 16571 + 0 16571 MT 16571 + 0 16571 1542
+16571
+
+chain 14267284136 X 155270560 + 60000 155260560 X 154913754 + 0 154913754 8
+34821	50000	50000
+86563	50000	30000
+766173	50000	50000
+36556	50000	50000
+80121	50000	90000
+754004	50000	100000
+5505644	50000	0
+3064790	50079	0
+26309505	50000	25000
+201176	8	0
+7416	0	2
+53134	8	0
+3073	0	12
+21097	0	2
+60831	2	0
+57728	0	20
+54336	0	1
+31675	0	4
+9987	4	0
+12108	0	4
+11225906	0	2000
+356252	50059	50059
+77342	1	1
+17	1	1
+94	0	3
+266	10	10
+113	1	1
+21	1	1
+5400	0	5
+4996	7	15
+3222	5	1
+6456	1	0
+1476	5	5
+2100	1	1
+40	1	1
+1316	0	1
+2446	1	0
+1555	0	2
+11220	1	0
+2639	1	0
+5190	0	4
+79	8	0
+5086	0	1
+2663	1	0
+9149	7	8
+1851	0	1
+9081	0	1
+7248	25	0
+208	28	0
+25	2	0
+15	83	0
+17	116	4
+2536	0	1
+1394	0	6
+12550	0	42
+822	4	0
+30578	1	0
+3711	4	0
+3637	1	0
+11945	0	1
+20204	0	1
+4172	8	0
+5679	1	0
+23827	0	2
+54817	0	1
+657	0	1
+342931	50000	180000
+2052068	27	1
+5375	2	0
+46	0	2
+6489	0	1
+7175	2	0
+1239	2	0
+4301	0	4
+27254	0	1
+4244	0	2
+717	0	2
+260	0	6
+26075	1	0
+236464	50000	50000
+6136098	3100000	3000000
+13518993	1	0
+449	1	0
+4535	4	0
+755	1	0
+1102	1	0
+24	1	1
+107	2	0
+3470	0	1
+1108	1	0
+4775	1	0
+8628	1	1
+46	1	1
+1072	1	1
+44	1	1
+292	4	5
+9091	4	4
+2218	4	4
+705	5	1
+452	0	1
+332	0	1
+1801	7	1
+3960	1	0
+2007	1	0
+3337	1	0
+2093	1	0
+407	310	0
+6130	1	1
+36	1	1
+1697	1	0
+97	13	0
+7624	1	1
+19	1	1
+3806	24	24
+3103	1	0
+779	7	7
+721	1	1
+43	1	1
+1626	0	1
+6146	0	2
+150	1	1
+47	1	1
+2172	0	2
+398	1	1
+31	1	1
+1334	16	16
+1663	1	1
+18	1	1
+2105	1	0
+9	1	1
+1409	1	1
+33	1	1
+1753	1	0
+408	0	1
+1916	1	0
+1928	0	12
+3800	1	1
+15	1	1
+2921	0	1
+4597	0	2
+486	6	0
+308	24	24
+1056	1	1
+44	1	1
+186	1	1
+46	1	1
+3037	0	1
+2301	0	3
+3876	1	1
+22	1	1
+1724	1	0
+3733	1	0
+627	1	0
+250	0	1
+194	1	1
+26	1	1
+20797	10	10
+2445	0	1
+1733	2	0
+1001	0	12
+4394	9	9
+4052	9	10
+670	1	1
+96	0	6
+26	1269	1568
+28	3	2
+10	1486	1188
+25	6	0
+18	1	1
+62	17	17
+77	1	0
+4949	10	10
+4690	1	0
+7343	0	1
+1248	0	1
+1259	0	1
+1347	4	0
+1532	0	1
+3797	16	16
+807	0	1
+2427	0	1
+48	1	0
+287	0	1
+611353	1	0
+1041	0	6
+371	1	0
+227	1	0
+2806	0	1
+36	1	1
+234	1	1
+23	1	1
+584	0	1
+22241	1	1
+65	1	1
+4605	1	0
+2337	20	0
+2119	1	0
+6170	13	9
+10665	1	0
+14631	0	1
+5359	0	4
+4004	0	1
+3182	0	11
+3897	16	14
+2551	0	1
+1824	0	1
+5274	1	1
+41	1	1
+4309	1	0
+3827	1	0
+4594	1	0
+65	1	1
+1170	1	1
+42	4	4
+214	1	0
+5228	1	0
+553	0	1
+6270	1	1
+12	1	1
+2849	12	13
+156	2	0
+8820	1	1
+41	1	1
+472	1	1
+65	1	0
+8	1	1
+1162	0	1
+565	1	1
+48	1	1
+536	1	2
+766	2	0
+4520	1	0
+1574	0	1
+503	1	0
+2558	1	0
+250061	7	7
+9650	18	18
+3208	1	1
+25	1	0
+744	0	2
+2994	1	1
+33	1	1
+1331	0	1
+87	19	19
+1935	5	0
+7	6	0
+1292	1	1
+35	1	1
+2485	1	1
+35	1	1
+4184	23	23
+13077	8	15
+671	4	0
+428	1	0
+4736	0	1
+3849	1	0
+6745	16	16
+2344	1	1
+41	1	1
+7917	1	0
+3876	1	1
+75	1	1
+1429	7	7
+11933	1	1
+28	1	1
+409	1	0
+11	1	1
+1223	12	12
+5354	1	0
+1255	6	0
+851	1	1
+45	1	1
+144	1	1
+47	5	5
+5929	0	4
+422	1	0
+2949	6	0
+193	1	1
+319	4	4
+3592	33	33
+3115	3	1
+1074	0	1
+2465	1	1
+40	1	1
+640	0	2
+550	1	1
+32	1	1
+4096	1	1
+29	1	1
+949	6	6
+6258	0	1
+3957	0	1
+19608	1	1
+48	1	1
+234	1	0
+16874	11	11
+1018	0	321
+2624	0	1
+4553	3	0
+491	6	0
+7496	1	1
+10	10	0
+76	4	0
+3314	1	1
+32	1	1
+5217	0	1
+3540	0	1
+1254	48	48
+1124	18	0
+3109	8	8
+3248	0	1
+1946	1	1
+48	1	1
+9620	2	0
+31242	50000	20000
+36075685	0	3
+36004	1	1
+27	1	1
+5196	1	0
+293	2	0
+13307	3	0
+2420	0	6
+1863	2	0
+2911	1	0
+3233	0	2
+66	0	1
+2375	0	10
+4894	0	1
+745	0	1
+3897	13	0
+4430	1	1
+48	1	4
+20	2	0
+279	2	0
+33	1	1
+48	0	1
+387	8	8
+692	1	0
+375	0	3
+380	23	23
+1289	1	1
+29	1	1
+12336	331	0
+852	0	4
+48	4	0
+4350	1	1
+59	1	1
+4306	5	0
+129	0	2
+3001	1	0
+1332	5	8
+23273	1	0
+30174	39	27
+337	3	0
+2838	0	1
+1614	9	0
+313	1	0
+82	0	4
+173	1	1
+25	1	1
+4912	39	0
+1863	1	0
+2931	0	1
+3134	3	0
+390880	1	0
+7199	0	1
+305	0	2
+1811	0	2
+5449	3	0
+7443	2	0
+2171	1	1
+27	1	1
+2668	2	0
+2180	1	0
+1170	9	0
+1450	16	16
+3080	0	1
+11157	0	1
+678	1	1
+28	1	1
+698	0	1
+112	0	1
+1831	0	3
+14327	0	2
+2247	3	0
+380	1	1
+28	1	1
+1265	21	19
+7184	2	3
+4225	14	9
+1002	1	0
+3854	0	4
+2535	1	1
+30	1	1
+794	0	1
+25	1	1
+76140	50000	70000
+1432750	0	7772
+681872	50000	20000
+4278742	56347	0
+12021233	1	0
+8	0	1
+1775	0	1
+1468	1	1
+51	14	16
+6	1	0
+6	1	0
+11	5	4
+7	1	0
+4	1	0
+75	2	1
+26	0	1
+16	1	0
+9	1	0
+19	2	0
+22	0	1
+9	1	0
+5	3	1
+14	7	6
+38	0	1
+26	1	1
+62	40	39
+1687	1	0
+54	1	0
+8528	1	0
+2722	1	0
+6240	1	0
+33	1	0
+121285	0	1
+6	1	0
+35	0	1
+1381	1	0
+5368	0	1
+3079	1	0
+10863441	4	0
+1799	1	1
+24	1	1
+334	0	1
+4960	0	17
+1160	1	1
+34	1	1
+6153	0	3
+1346	0	4
+103	0	4
+168	27	27
+2640	12	12
+304	16	0
+719	1	0
+3286	0	1
+10182	9	0
+804	1	1
+28	1	1
+749	1	0
+3387	1	1
+47	1	1
+482	1	0
+455	15	15
+719	1	1
+18	1	1
+2074	1	0
+1349	4	0
+3927	1	1
+18	1	1
+907	1	0
+2972	0	2
+115	1	1
+37	1	1
+4428	0	1
+1120	0	1
+4055	0	5
+2929	0	3
+3590	1	1
+47	1	1
+62	0	1
+947	1	1
+45	1	1
+1639	1	1
+32	1	1
+1076	1	0
+3996	0	4
+686	41	41
+7238	0	1
+1733	0	1
+1451	2	0
+617	0	1
+4375	1	0
+2194	15	16
+349	1	1
+27	1	1
+8237	0	1
+499	1	1
+37	2	2
+968	0	1
+34	1	1
+6337	1	1
+18	1	1
+8162	1	1
+21	0	5
+7668	45	45
+1562	0	1
+6017	5	5
+3872	0	8
+5421	0	1
+532	7	6
+5673	4	0
+1542	0	4
+890	1	3
+2561	0	1
+1692	0	1
+1142	1	1
+32	1	1
+503	1	2
+123	1	1
+75	1	1
+2322	0	1
+201	0	1
+40	3	3
+149	0	3
+1441	1	1
+40	1	1
+159	0	2
+1278	1	1
+33	1	1
+221	1	0
+31	1	1
+161	10	9
+1890	1	0
+132	1	1
+37	1	1
+514	23	17
+1373	0	4
+907	17	17
+714	31	30
+55	1	1
+24	1	1
+1038	0	2
+95	5	1
+1094	1	1
+170	1	1
+844	3	0
+369	1	1
+39	1	1
+650	1	1
+41	1	1
+176	1	1
+10	1	1
+688	0	1
+7637	0	4
+2653	1	1
+26	4	0
+46	1	1
+727	0	8
+2197	1	0
+13466	1	0
+3510	2	0
+2147	1	1
+44	3	0
+1320	11	11
+213	4	0
+102	0	1
+3239	1	0
+1492	0	3
+107	1	1
+35	14	0
+2391	1	1
+39	2	0
+436	0	4
+2271	0	8
+6868	3	0
+7183	1	0
+5104	3	0
+182	0	1
+3131	1	1
+31	0	1
+14	1	1
+59	0	1
+373	1	1
+42	1	1
+235	13	13
+1608	5	0
+152	1	1
+106	1	1
+783	34	34
+1633	1	1
+29	0	3
+821	1	1
+24	1	1
+1178	1	1
+33	1	1
+328	1	1
+27	1	1
+5682	1	0
+11	1	5
+146398	50000	30000
+59809	2	0
+3389	1	1
+37	1	1
+11606	1	0
+1597	1	0
+618	1	1
+47	1	1
+2698	1	0
+826	5	5
+33	2	0
+2560	14	0
+98	3	0
+1287	1	0
+7600	1	0
+9897	8	0
+7157	1	0
+32	1	1
+1698	1	0
+754	0	2
+6787	1	0
+584	2	0
+1107	1	1
+40	1	1
+365	1	1
+35	1	1
+400	8	0
+11443	1	0
+1973	1	0
+497	46	46
+657	1	0
+716	1	1
+25	1	1
+1570	2	0
+433	0	2
+905	2	0
+94	1	1
+28	1	1
+2490	1	1
+16	1	1
+5054	1	9
+2184	2	0
+2955	21	23
+794	0	1
+1563	1	1
+20	1	1
+1627	0	11
+1676	0	2
+1527	1	0
+676	1	1
+29	1	1
+1245	1	1
+34	1	0
+1192	7	0
+27	1	0
+1940	0	1
+3421	2	0
+17	1	1
+774	30	0
+97	6	6
+59	26	12
+840	1	1
+19	1	1
+2036	13	1
+26	14	0
+1114	1	0
+25	1	1
+380	0	16
+160	1	1
+17	1	1
+1151	4	0
+699	0	1
+29	2	0
+409	1	1
+49	1	1
+1240	1	1
+37	3	3
+2248	1	0
+1828	1	0
+1997	5	1
+4640	4	4
+4555	0	2
+149	0	52
+619	2	2
+16	1	1
+83	22	0
+56	57	1
+2531	0	8
+4250	1	1
+15	1	1
+2203	0	4
+1665	0	10
+415	2	0
+395	19	18
+15708	0	1
+161	4	0
+79	14	0
+543	1	1
+42	1	1
+3261	18	18
+139	46	46
+403	1	1
+18	1	1
+5405	1	0
+1104	1	1
+53	1	1
+392	1	1
+55	3	3
+3352	9	0
+692	1	9
+8	4	0
+27	3	97
+39	3	1
+21	3	51
+61	0	2
+8931	1	0
+6692	1	2
+1141	0	2
+196	2	0
+389	1	1
+30	1	1
+949	0	1
+6057	0	3
+4741	1	0
+7689	2	0
+2046	18	18
+215	0	1
+46885	2	0
+24138	2	0
+4037	1	0
+4047693	1	0
+9545	0	2
+11590	4	0
+1698	1	3
+13506	37	37
+5380	4	0
+1806	1	1
+44	1	1
+2581	0	2
+10620	0	1
+3804	0	1
+339	0	2
+476	0	1
+5861	8	5
+109	0	14
+901	1	1
+19	1	1
+45	2	0
+1736	1	0
+6625	2	0
+7812	4	0
+7678	2	0
+5068	4	0
+21	1	0
+4170	0	1
+1671	6	0
+6333	0	16
+902	1	1
+44	1	1
+384	0	6
+23418	2	0
+36	1	1
+8900	0	4
+222	1	1
+49	1	1
+2783	0	1
+2641	0	1
+136	20	20
+1279	0	1
+3924	6	6
+13054	6	0
+8965	23	36
+4094	2	0
+2269	1	0
+13621	16	16
+2621	0	2
+30076	1	1
+49	1	1
+102	1	0
+8824	1	1
+25	1	1
+1730	1	1
+47	1	1
+3339	0	1
+131	0	16
+83	16	0
+89	6	0
+2826	33	33
+3509	1	0
+541	1	0
+6288	0	4
+3814	2	0
+7260	0	1
+806	68	0
+1162	0	1
+2230	1	0
+1109	0	1
+1106	2	0
+12396	0	1
+26207	1	1
+21	1	1
+3541	18	18
+525	0	16
+1326	7	7
+525	0	1
+4198	0	1
+4682	13	13
+890	0	2
+816	0	2
+1961	0	4
+24586	1	1
+19	1	1
+4403	1	0
+1342	1	0
+57	12	11
+2225	1	0
+2011	0	35
+10543	0	1
+9766	6	12
+2489	2	1
+20	1	1
+1541	0	12
+1130	1	1
+34	1	1
+927	0	1
+4003	0	1
+966	1	0
+149	0	1
+844	8	0
+4324	1	1
+25	1	1
+569	7	6
+6361	1	0
+3074	0	1
+1539	3	9
+634	1	1
+39	1	1
+8610	13	12
+760	2	0
+4311	0	6
+3122	0	2
+369	1	0
+9963	10	10
+2191	1	1
+23	1	1
+1060	1	1
+19	1	1
+240	12	12
+1748	1	1
+45	1	1
+1040	1	1
+31	1	1
+7446	1	1
+25	1	1
+8379	7	7
+7325	3	0
+357	0	1
+1313	0	1
+11627	4	0
+5862	1	0
+9750	1	0
+3539	0	16
+5672	13	13
+2885	0	4
+8179	1	0
+753	0	1
+4317	0	2
+1318	1	0
+957	0	1
+825	12	12
+1109	0	16
+3736	17	17
+2236	8	8
+7791	15	185
+149	1	1
+21	2	0
+636	1	1
+22	1	0
+42	1	1
+1634	4	4
+3380	0	3
+979	2	0
+3429	0	1
+7132	0	14
+1733	1	1
+38	0	1
+88	1	0
+630	6	6
+489	5	0
+22	1	0
+94	1	0
+42	0	1
+17	1	0
+27	1	0
+172	1	1
+37	1	1
+191	1	1
+66	1	1
+630	1	0
+261	30	30
+1282	1	0
+16	1	1
+429	1	0
+1588	1	1
+20	1	1
+1416	1	1
+33	1	1
+529	1	0
+25	1	0
+1863	4	0
+1651	1	1
+28	1	1
+11815	1	0
+26	1	0
+19	1	1
+3105	1	0
+700	1	0
+150	1	0
+68	1	0
+1421	6	0
+567	1	0
+14	1	0
+2415	1	0
+41	1	1
+415	1	1
+33	1	1
+4521	1	1
+33	1	1
+307	0	1
+176	0	1
+3790	1	1
+86	1	1
+67	1	1
+65	1	0
+7439	1	1
+18	1	1
+16805	1	0
+1764	0	1
+6984	1	0
+3401	20	0
+156	1	1
+30	1	1
+165	2	0
+1087	0	1
+953	0	1
+483	1	0
+632	0	1
+652	0	1
+8559	0	2
+1871	0	1
+398	0	1
+2219	1	1
+53	1	1
+756	1	1
+66	1	1
+69	1	1
+48	1	1
+63	1	1
+28	0	3
+1057	0	3
+63	3	0
+55	1	1
+74	2	3
+159	3	0
+92	1	1
+29	1	1
+58	0	3
+1210	9	9
+54	1	1
+27	1	1
+1374	2	0
+1775	2	17
+764	14	14
+331	16	16
+2291	4	3
+1687	1	1
+26	1	1
+2469	0	1
+3243	1	0
+3636	1	1
+24	1	1
+615	0	1
+2566	1	0
+275	0	5
+690	0	7
+13139	1	0
+1452	0	4
+214	13	13
+61	124	0
+1381	9	9
+5812	1	1
+24	1	1
+5703	1	0
+3992	14	15
+1462	0	3
+5199	0	2
+1554	2	0
+715	12	10
+1966	2	0
+2808	16	0
+611	1	0
+406	0	18
+737	1	1
+31	1	1
+4372	0	5
+10789	0	1
+2399	0	1
+6750	2	0
+96	48	48
+1219	0	6
+6736	0	2
+4457	4	0
+7867	0	1
+3495	1	2
+6215	12	12
+1357	1	0
+2652	0	1
+1771	1	0
+14207	41609	41616
+18338	46	46
+851	1	0
+9638	1	0
+2994	1	0
+469	1	3
+499	1	0
+12074	13	13
+2807	11	10
+715	2	0
+1627	6	6
+5099	0	1
+488	5	1
+975	2	0
+1730	32	31
+1791	0	5
+8135	38	38
+84	3	3
+18	1	1
+3737	9	9
+1442	13	13
+212	10	0
+7712	1	1
+44	1	1
+6271	0	1
+1316	1	1
+49	1	1
+9052	28	32
+113	2	0
+2813	13	13
+1285	50000	2858
+75638	50000	40000
+1583473	2	0
+1564100	97462	0
+2933461
+
+chain 4369679 X 155270560 + 152229637 152277099 X 154913754 + 151980294 152116665 696
+7131	26	26
+1319	1	0
+10288	0	88910
+2852	19	19
+3721	0	1
+13270	1	0
+8834
+
+chain 2629454 X 155270560 + 120011032 120067379 X 154913754 + 119895063 119899921 647
+714	51489	0
+4144
+
+chain 1494650 X 155270560 + 148762194 148872193 X 154913754 - 6301537 6445444 168
+2899	0	1
+1499	0	1
+3725	0	6
+20333	1	0
+13152	18338	18338
+46	40010	73911
+32	9926	9926
+38
+
+chain 260907 X 155270560 + 75365988 75368784 X 154913754 - 79628560 79631356 2215
+1269	41	41
+1486
+
+chain 138004 X 155270560 + 120011746 120013199 X 154913754 + 119920102 119921555 138939
+1453
+
+chain 29712 X 155270560 + 112877029 112877338 12 132349534 + 121720730 121721039 4776951
+309
+
+chain 29117 X 155270560 + 75253866 75254170 12 132349534 - 49782819 49783123 5064709
+304
+
+chain 10575 X 155270560 + 143182285 143275757 2 242951149 - 154930543 155024664 254
+41	49992	50582
+45	43365	43424
+29
+
+chain 3572 X 155270560 + 148224541 148224579 X 154913754 + 148032219 148032257 5503764
+38
+
+chain 3404 X 155270560 + 120013199 120013235 X 154913754 + 119931276 119931312 297576
+36
+
+chain 3363 X 155270560 + 49293018 49293056 X 154913754 + 49218184 49218222 1450
+38
+
+chain 2275 X 155270560 + 152236768 152236794 X 154913754 - 2913071 2913097 1916
+26
+
+chain 2111 X 155270560 + 143122309 143122332 17 78774742 - 16413594 16413617 6765736
+23
+
+chain 2063 X 155270560 + 148224511 148224541 X 154913754 + 148032257 148032287 9904071
+30
+
+chain 1275 X 155270560 + 148522048 148522077 11 134452384 + 59964168 59964197 432609
+29
+
+chain 391 X 155270560 + 112955240 112955279 3 199501827 - 80088461 80088500 4668596
+20	4	4
+15
+
+chain 2373403023 Y 59373566 + 10000 28819361 Y 57772954 + 0 27228749 24
+34821	50000	50000
+86563	50000	30000
+766173	50000	50000
+36556	50000	50000
+80121	50000	90000
+754004	50000	100000
+6846717	50000	50000
+276367	50000	600000
+813231	3000000	500000
+39401	50000	400000
+554624	50000	100000
+535761	0	1
+32919	11	12
+12810	0	5
+18900	1	1
+121	4	5
+230478	0	1
+750	1	1
+22	1	1
+14340	1	1
+43	1	1
+2095	0	1
+14635	0	9
+2781	0	1
+45022	5	6
+7151	0	1
+9344	628	0
+5417479	50006	0
+2175791	50000	0
+1481749	50000	50000
+4867933
+
+chain 46617811 Y 59373566 + 58819361 59363566 Y 57772954 + 57228749 57772954 80
+98295	50000	50000
+395910
+
+chain 9624 Y 59373566 + 14725909 14726162 X 154913754 + 99410441 99410697 23695076
+50	136	139
+67
+
diff --git a/public/chainFiles/b37tohg18.chain b/public/chainFiles/b37tohg18.chain
new file mode 100644
index 0000000..37c2264
--- /dev/null
+++ b/public/chainFiles/b37tohg18.chain
@@ -0,0 +1,49040 @@
+chain	21270171362	1	249250621	+	10000	249233096	chr1	247249719	+	0	247199719	2
+619	137	0
+166661	50000	50000
+40302	50000	50000
+153649	50000	50000
+1098479	1	1
+47	1	1
+73	117	114
+773	1	1
+43	1	1
+864369	2	2
+51	3	0
+104	13694	13694
+104	0	3
+51	2	2
+134936	50000	50000
+1161048	150000	60000
+1440092	27273	50000
+7590365	50000	50000
+116914	100000	50000
+237250	50000	50000
+3518496	50000	50000
+12702424	150000	50000
+16145012	0	1
+7772	1	0
+4705841	0	1
+52977198	50000	50000
+157344	21065	50000
+16604841	50000	50000
+189539	150000	50000
+398739	21050000	20290000
+195588	50000	50000
+186739	150000	50000
+175055	50000	50000
+201709	100000	50000
+126477	130183	50000
+381	0	3
+315	0	2
+62	1	1
+45	1	0
+19	0	1
+8	1	1
+1158	1	0
+314	12	13
+2849	3	0
+5615	1	1
+37	1	1
+3172	6	4
+190	1	1
+34	1	1
+380	0	1
+2099	3	0
+765	2	2
+366	0	4
+1186	1	0
+460	0	1
+1242	28	28
+574	1	1
+21	1	1
+1460	1	1
+105	1	1
+701	3	0
+239	0	1
+970	11	11
+2365	1	1
+21	1	1
+384	8	8
+996	2	0
+10383	2	0
+713	0	1
+5188	1	1
+30	1	1
+1233	1	0
+132	1	1
+44	1	1
+1123	22	22
+1810	1	0
+512	1	1
+39	1	1
+1096	0	16
+743	1	0
+9028	0	1
+2506	0	6
+8446	2	0
+5505	0	3
+7541	1	0
+109864	50000	50000
+78698	50000	50000
+127263	50000	50000
+170669	50000	50000
+38311	100000	100000
+1022394	50000	50000
+281532	289973	50000
+1648	1539	0
+76	3225	3
+1018	34	34
+1716	2	0
+159	4	0
+1600	0	6
+1385	1	0
+2066	1	1
+32	1	3
+1556908	150000	50000
+185320	150000	50000
+172789	50000	50000
+220313	50000	50000
+455185	50000	50000
+22047237	1	0
+34365824	150000	50000
+259514	150000	50000
+17265625	50000	50000
+11394365	50000	50000
+13665999	150000	50000
+174886
+
+chain	3264727	1	249250621	+	146303299	146341166	chr16	88827254	-	19388358	19424466	890
+577	1	1
+25	1	1
+63	19	19
+840	1	1
+60	1	1
+146	8	8
+874	1	1
+17	1	1
+386	1	1
+27	1	1
+931	1	1
+19	1	1
+200	1	1
+26	1	1
+72	1	0
+39	1	1
+107	2	1
+26	1	0
+25	1	1
+146	1	1
+45	1	1
+49	0	1
+434	0	4
+21	1	1
+572	0	2
+464	1	1
+50	1	1
+628	1	1
+48	1	1
+184	1	1
+25	1	1
+330	0	3
+308	14	14
+289	1	1
+57	1	1
+709	107	107
+247	1	1
+72	1	1
+470	1	1
+36	1	1
+353	1	0
+27	1	1
+92	12	12
+1001	1	1
+39	1	1
+650	1	1
+22	1	1
+171	1	1
+21	1	1
+88	0	9
+107	36	11
+23	0	1
+29	0	26
+20	3	79
+161	11	11
+134	1	1
+89	1	1
+547	1	1
+15	1	1
+409	1	1
+36	1	1
+376	11	10
+1545	1	0
+4	0	1
+36	1	1
+373	0	1
+326	1	1
+42	17	0
+97	1	0
+187	2	0
+503	1	1
+57	1	1
+443	1	1
+35	1	1
+633	1	0
+2044	3	13
+299	1	1
+37	1	1
+1159	1	1
+39	1	1
+124	1	1
+74	1	1
+103	1	1
+55	1	1
+280	10	9
+474	0	1
+382	1	1
+31	1	1
+1812	1	1
+76	1681	0
+25	1	1
+145	1	1
+18	1	1
+1228	1	1
+31	1	1
+126	9	9
+186	2	0
+142	1	1
+25	1	0
+442	10	0
+339	0	1
+89	1	1
+21	2	0
+21	151	4
+15	1	1
+489	9	9
+311	1	1
+75	1	1
+75	1	0
+124	1	1
+114	1	1
+23	1	1
+1489	0	3
+391	1	0
+2141	10	10
+460	11	11
+422	1	1
+30	1	1
+296	8	8
+638	1	1
+38	1	1
+341
+
+chain	2374970	1	249250621	+	146214652	146460889	chr1	247249719	-	102316553	102503720	74
+488	1	1
+24	1	1
+971	6293	0
+994	2	0
+183	2	0
+1408	1	0
+1360	1541	0
+211	0	12
+1506	111528	93105
+421	5	6
+2973	8	8
+118	12	12
+157	10	10
+706	0	18
+26	2884	0
+127	4	1
+1518	1	1
+33	1	1
+934	9	9
+908	0	1
+126	1	0
+695	20	20
+2250	5	5
+1662	179	172
+975	1	1
+53	1	1
+62	2	2
+40	1	1
+1561	1	1
+34	1	1
+668	1	0
+1671	2	0
+480	1	1
+17	4	4
+103	0	1
+50	6	6
+230	1	1
+71	1	1
+139	1	0
+975	5	0
+180	1	1
+37	1	1
+1888	3	2
+1101	1	0
+354	64	9327
+654	1	1
+36	1	1
+888	0	2
+18	1	1
+74	1	1
+25	1	1
+81	2	0
+779	1	1
+41	0	12
+22	1	1
+436	1	6
+293	1	1
+31	1	1
+83	4	0
+694	1	1
+42	1	1
+913	0	9
+472	0	1
+253	12	12
+148	89	1
+41	89	1
+342	1	1
+72	1	1
+97	1	1
+41	1	1
+108	13	16
+280	12	12
+61	1	1
+30	0	1
+71	1	1
+42	2	2
+139	0	3
+85	5	5
+90	1	1
+39	0	1
+366	13	14
+332	0	3744
+123	1	1
+19	1	1
+264	2	0
+47	1	1
+381	3	5
+109	0	1
+521	0	1
+503	1	1
+42	0	1
+739	1	1
+77	1	1
+883	0	2
+220	0	3
+93	4	0
+12	4	0
+39	5	0
+91	1	1
+34	1	1
+562	1	1
+30	1	1
+660	13	0
+1172	16	16
+69	1	1
+32	1	1
+310	1	1
+33	1	1
+97	0	1
+38	1	1
+295	0	2
+499	1	1
+57	31	14
+607	10	10
+145	1	1
+101	1	1
+346	1	1
+30	1	1
+74	1	1
+16	1	1
+203	1	1
+36	12	0
+483	16	0
+977	1	1
+86	1	1
+66	1	1
+35	1	1
+692	16	13
+402	34	34
+287	0	5
+523	0	18
+350	4	0
+32	0	2
+108	39	45
+66	30	0
+969	0	5
+1749	5	5
+95	2	0
+5	1	0
+4	0	1
+79	0	2
+65	8	11
+63	1	1
+49	1	1
+1381	0	1
+870	17	0
+139	1	1
+89	1	1
+270	3	3
+97	1	1
+66	1	1
+50	1	1
+126	1	0
+182	1	1
+83	0	4
+125	1	1
+35	1	1
+263	1	1
+32	4	4
+202	1	0
+94	1	1
+46	1	1
+206	1	1
+56	1	1
+50	1	1
+49	1	1
+188	16	16
+589	1	1
+38	1	1
+178	0	4
+67	1	1
+421	51	0
+117	1	1
+36	1	1
+71	1	1
+74	1	1
+68	10	10
+131	3	3
+56	1	0
+52	1	1
+207	4	4
+30	1	1
+283	14	14
+93	0	4
+66	1	1
+89	7	5
+36	1	1
+79	1	1
+46	21	0
+99	1	1
+229	10	10
+100	5	0
+19	8	8
+78	1	1
+87	1	1
+125	5	5
+65	1	1
+74	3	3
+344	1	1
+24	1	1
+683	1	1
+43	6287	0
+250	15	15
+798	13	12
+267	2	1
+881	1	0
+374	10	10
+1237	1	1
+40	1	1
+620	1	1
+43	1	1
+1491	1	1
+28	1	1
+68	5	5
+413	1	2
+183	5	5
+42	1	1
+363	1	1
+26	23	0
+53	1	0
+1011	15	15
+173	4	4
+15	1	1
+801	4	4
+1197	0	10
+432	22154	19
+283	4702	22
+850	9524	0
+78	76	76
+568	10	10
+775	40	32
+274	4	0
+1120	17	17
+195
+
+chain	990444	1	249250621	+	2485433	2499127	chr1	247249719	-	244760735	244774429	1366
+13694
+
+chain	614409	1	249250621	+	249233096	249240448	chr21	46944323	+	46937133	46944296	2013
+2867	16	16
+420	9	9
+176	0	1
+1252	6	0
+1275	1	1
+25	0	344
+76	0	58
+545	484	7
+40	109	0
+51
+
+chain	498595	1	249250621	+	146216137	146242853	chr1	247249719	-	104315183	104389677	383
+30	657	657
+196	19	18
+134	27	27
+445	20	20
+101	9	9
+169	62	62
+116	10	10
+70	62	62
+54	26	26
+70	0	22267
+240	1539	0
+91	20	24
+246	22	22
+270	112	112
+118	143	143
+86	24	24
+184	81	81
+67	47	46
+110	83	95
+335	59	59
+139	4179	2633
+241	27	27
+273	109	109
+185	76	76
+86	24	24
+184	81	81
+26	1717	1732
+80	85	53
+151	37	37
+99	37	37
+113	20	20
+101	9	9
+169	62	62
+89	37	37
+70	62	62
+54	33	33
+382	279	5055
+291	112	112
+125	147	147
+256	382	24225
+58	106	106
+51	29	29
+422	19	19
+221	84	84
+156	29	29
+162	33	33
+80	4	4
+79	11	11
+209	29	29
+183	34	34
+116	44	44
+122	5	5
+554	41	41
+140	8	8
+161	0	1
+67	58	51
+138	10	10
+246	60	60
+124	59	60
+101	138	138
+109	161	161
+56	31	28
+163	74	74
+136	7	7
+303	34	34
+119	10	10
+339	30	30
+141	91	91
+222	107	93
+237	205	205
+134	49	49
+87	22	22
+128	87	87
+105	33	33
+52	58	58
+52	87	87
+198	158	162
+125	44	44
+82	42	42
+54	10	9
+72	27	27
+154	18	18
+186	39	39
+61	87	86
+71	38	38
+116	43	43
+268	50	50
+58	120	120
+152
+
+chain	376931	1	249250621	+	143880003	143901185	chr1	247249719	-	126576077	126597249	122
+127	70	71
+181	31	31
+3325	1	1
+49	1	1
+820	1	1
+75	1	1
+393	1	1
+21	1	1
+2956	3	0
+232	0	5
+77	4	4
+531	1	1
+42	5	3
+183	1	1
+19	1	1
+644	1	1
+25	1	1
+701	1	1
+21	1	1
+954	1	1
+31	1	1
+129	24	14
+650	1	1
+25	1	1
+560	0	2
+1372	1	1
+46	1	1
+1547	3	1
+883	1	0
+22	1	1
+818	1	1
+30	1	1
+1231	1	1
+34	1	1
+1758	1	1
+35	1	1
+468
+
+chain	360128	1	249250621	+	146427813	146438983	chr1	247249719	+	144926007	144932406	9045
+138	252	252
+1258	1540	0
+76	3256	30
+81	283	283
+87	185	185
+109	273	273
+7	19	19
+155	43	43
+91	1	0
+1185	11	11
+212	2	0
+158	2	0
+1336	64	64
+346
+
+chain	260187	1	249250621	+	146226436	146443808	chr1	247249719	-	100391956	100589719	716
+173	5526	775
+60	400	391
+120	18	17
+164	81	83
+26	45	45
+35	1589	1589
+29	2518	2516
+7	17	17
+56	30	30
+51	56	53
+31	163	163
+74	446	446
+34	468	468
+30	141	141
+33	624	609
+8	133	133
+64	134	134
+49	237	237
+71	316	316
+58	1199	1203
+39	219	219
+38	6697	424
+97	18	18
+77	219	219
+114	64	64
+138	183	187
+118	99	99
+89	25	31
+69	24	24
+100	30	30
+69	49	49
+54	125	125
+182	197	197
+107	156930	137139
+140	175	171
+75	164	162
+157	49	49
+69	45	45
+61	48	48
+51	61	60
+71	70	70
+108	10955	10956
+84	24	24
+75	87	87
+185	109	109
+273	22	22
+246	20	24
+49	494	19550
+70	10	10
+116	62	9592
+169	9	9
+324	83	83
+151	87	77
+90	22	22
+196	68	68
+95	5	5
+57	71	71
+196	17	17
+75	73	73
+563	83	87
+110	1555	14
+45	7990	0
+54	81	81
+184	24	24
+75	87	87
+185	109	109
+273	3222	27
+64	1605	35
+142	1567	44
+37	1539	0
+281
+
+chain	257136	1	249250621	+	146423276	146434218	chr1	247249719	+	144926235	144932406	9046
+68	157	157
+71	288	288
+73	563	563
+83	4962	196
+1052	19	19
+155	43	43
+91	1	0
+99	76	76
+1010	11	11
+212	2	0
+158	2	0
+1746
+
+chain	252664	1	249250621	+	146424776	146427813	chr1	247249719	+	144927734	144930766	96654
+1055	16	16
+124	74	74
+74	224	223
+979	11	11
+212	2	0
+158	2	0
+106
+
+chain	244411	1	249250621	+	146449863	146457732	chr1	247249719	+	144926007	144929115	8960
+1648	1539	0
+76	3225	3
+265	45	45
+708	34	34
+329
+
+chain	149837	1	249250621	+	146221841	146454623	chr1	247249719	+	146043049	146859300	923
+56	335	335
+59	4859	3299
+109	185	185
+76	5018	258
+57	409	426
+45	777	777
+84	1850	1850
+41	841	820
+47	125	126
+58	101	101
+138	2026	2026
+51	4	2
+52	297	297
+81	786	786
+33	347	347
+90	23	23
+35	125	125
+44	82	81
+42	634	634
+74	225	224
+43	268	267
+50	58	58
+120	152	152
+515	62	62
+68	41	41
+432	0	18
+180	46	46
+67	26	28
+192	26	26
+231	107	107
+67	72	67
+53	67	67
+151	171	168
+59	46	47
+86	57	54
+51	138	138
+397	18	18
+114	3	2
+182	20	20
+86	167	167
+51	48	48
+233	42	42
+89	55	55
+163	43	44
+112	70	70
+355	154	154
+174	157	641342
+145	228	228
+152	366	366
+64	1134	1135
+35	269	265
+46	15	14
+137	8	8
+70	11	11
+73	29	29
+55	63	63
+62	262	247
+77	100	100
+155	39	39
+215	72	72
+178	20	20
+64	13	13
+123	12	12
+124	127	127
+100	135495	128258
+34	14433	8189
+138	64	64
+114	219	219
+77	19	19
+96	17464	11155
+185	22232	98
+69	26	26
+54	62	62
+70	10	10
+116	62	62
+169	32	32
+211	37	37
+99	9482	37
+161	23	13
+130
+
+chain	124274	chr1	249250621	+	143871002	143921945	chr1_random	1663265	-	747928	798871	209
+9001	127	127
+70	181	181
+31	41505	41505
+28
+
+chain	121346	1	249250621	+	146403114	146428203	chr1	247249719	-	230466401	230485108	1747
+70	156	156
+17	25	25
+22	146	146
+152	249	249
+94	2285	2290
+63	34	34
+79	80	80
+89	48	42
+85	127	127
+68	502	495
+87	61	61
+136	127	126
+4	272	272
+43	396	396
+49	175	175
+48	183	187
+40	11298	11284
+59	5488	723
+50	98	104
+107	63	63
+54	1608	4
+83	9	9
+160
+
+chain	97594	1	249250621	+	146218654	146221704	chr1	247249719	-	102320562	102322071	123803
+154	24	24
+174	6	6
+1045	1614	73
+33
+
+chain	76810	1	249250621	+	146441138	146441951	chr1	247249719	-	102499725	102500538	1571454
+813
+
+chain	54094	1	249250621	+	146439071	146449863	chr1	247249719	+	144927734	144930766	9063
+156	32	32
+864	3151	76
+253	432	432
+62	196	196
+62	169	169
+32	211	211
+37	99	99
+87	4753	70
+88	2	0
+106
+
+chain	51170	1	249250621	+	146420674	146422968	chr1	247249719	+	144928397	144930686	91522
+82	822	821
+37	60	60
+212	196	196
+62	502	502
+83	151	149
+59	2	0
+26
+
+chain	47243	1	249250621	+	146249630	146253102	chr1	247249719	+	146058248	146061700	347899
+23	176	176
+41	89	89
+25	420	420
+79	245	245
+20	78	78
+29	495	490
+29	72	72
+46	158	145
+143	628	627
+53	534	533
+17	5	5
+67
+
+chain	34253	1	249250621	+	146404045	146461111	chr1	247249719	-	100757623	100773572	2307
+96	91	95
+87	237	237
+54	39	39
+166	170	170
+93	270	264
+54	177	172
+56	15121	8830
+27	23096	966
+26	9686	241
+71	62	62
+168	10	10
+112	7057	3813
+40
+
+chain	33489	1	249250621	+	146442066	146462163	chr1	247249719	+	144023055	144028915	8758
+86	162	162
+20	322	322
+153	82	82
+116	7	7
+260	4934	262
+352	142	142
+79	60	60
+57	99	99
+135	6	6
+234	31	31
+264	6949	535
+45	4229	1077
+134	1105	1106
+34
+
+chain	33218	1	249250621	+	146446746	146453724	chr1	247249719	+	144927655	144929867	162700
+76	4	3
+532	5285	520
+407	76	76
+465	71	71
+62
+
+chain	32794	1	249250621	+	146404432	146406255	chr1	247249719	-	230461418	230463242	176920
+104	280	280
+90	172	172
+62	25	26
+120	135	135
+128	18	18
+13	515	515
+161
+
+chain	26745	1	249250621	+	146451818	146452101	chr1	247249719	-	102499420	102499703	6165314
+283
+
+chain	24305	chr1	249250621	+	146405140	146406723	chr1_random	1663265	+	611385	612968	836039
+25	120	120
+23	14	14
+26	287	287
+50	8	8
+128	685	685
+19	35	35
+26	105	105
+32
+
+chain	22423	1	249250621	+	146216204	146248536	chr1	247249719	+	146043705	146710884	2213
+65	5	5
+58	95	95
+44	58	58
+67	1348	1339
+20	10	10
+32	196	196
+62	2594	1055
+96	153	153
+108	10232	605314
+55	16610	57923
+59	315	315
+50
+
+chain	21816	1	249250621	+	146442152	146442891	chr1	247249719	+	144927740	144928479	1347746
+148	509	509
+82
+
+chain	20351	1	249250621	+	146356780	146459279	chr1	247249719	-	101132456	101205064	466
+178	42398	55179
+51	39820	14441
+32	3075	0
+39	16869	2651
+37
+
+chain	17175	1	249250621	+	249240118	249240599	chr1	247249719	-	247249264	247249719	6645750
+53	7	10
+47	109	0
+21	6	0
+36	51	102
+5	22	73
+56	16	0
+52
+
+chain	16391	1	249250621	+	146446357	146448997	chr1	247249719	+	144928805	144929904	1203759
+155	2048	507
+109	112	112
+60	57	57
+99
+
+chain	14917	1	249250621	+	146407068	146408474	chr1	247249719	+	144010187	144011603	12383
+76	149	159
+73	240	240
+47	136	136
+39	587	587
+59
+
+chain	14732	1	249250621	+	104074421	104074580	chr20	62435964	-	41767962	41768121	15357748
+159
+
+chain	13179	1	249250621	+	146404319	146408384	chr1	247249719	+	146846894	147006750	8455
+113	104	104
+20	54	54
+39	1744	1736
+34	1903	157702
+54
+
+chain	12360	1	249250621	+	146216167	146250305	chr1	247249719	-	103194351	103244298	1211
+37	128	128
+95	44	44
+58	67	67
+60	5	5
+51	3345	6525
+128	0	9435
+8	6200	4617
+43	3518	3485
+37	13507	18215
+40	613	636
+46	716	718
+72	53	53
+30	240	240
+72	1522	1531
+48	233	233
+42	89	89
+36	14	14
+5	804	801
+66	696	696
+34	1307	1378
+29
+
+chain	11952	1	249250621	+	146445104	146445575	chr1	247249719	-	100776503	100776974	637661
+94	18	18
+359
+
+chain	11854	1	249250621	+	146229744	146232010	chr1	247249719	+	144747607	144749863	153009
+21	19	9
+19	736	736
+20	10	10
+32	196	196
+62	54	54
+33	556	556
+43	383	383
+82
+
+chain	10753	1	249250621	+	146408065	146408192	chr1	247249719	-	101190210	101190337	3832842
+127
+
+chain	10394	1	249250621	+	104091245	104091359	chr5	180857866	+	153305659	153305773	21933263
+114
+
+chain	10333	1	249250621	+	104091131	104091240	chrX	154913754	+	74963065	74963174	22062861
+109
+
+chain	9815	1	249250621	+	146403058	146404974	chr1	247249719	-	101191494	101193412	750328
+43	256	256
+25	136	136
+32	152	152
+35	1179	1181
+58
+
+chain	9804	1	249250621	+	146245618	146249581	chr1	247249719	+	16785678	16789645	248382
+32	19	19
+6	51	51
+11	80	80
+47	3688	3692
+29
+
+chain	8504	1	249250621	+	146408954	146409155	chr1	247249719	-	101191099	101191300	2114480
+61	111	111
+29
+
+chain	8318	1	249250621	+	146407418	146407505	chr1	247249719	-	102486621	102486708	14753827
+87
+
+chain	7171	1	249250621	+	1619987	1620086	chr1	247249719	+	1662789	1662888	1670813
+99
+
+chain	7168	1	249250621	+	146247532	146247756	chr1	247249719	+	144759088	144759312	2272140
+43	123	123
+58
+
+chain	6908	1	249250621	+	146440123	146445030	chr1	247249719	-	101203201	101205034	129817
+119	142	142
+69	4461	1387
+116
+
+chain	6650	1	249250621	+	146406255	146406330	chr1	247249719	-	101188413	101188487	10133477
+21	3	2
+51
+
+chain	6566	1	249250621	+	146445881	146445977	chr1	247249719	+	144059904	144060000	2107997
+23	21	21
+52
+
+chain	6380	1	249250621	+	10629	10716	chrY	57772954	-	1612	1699	6955
+87
+
+chain	5940	1	249250621	+	146231384	146231447	chr1	247249719	-	102320696	102320759	393064
+63
+
+chain	5684	1	249250621	+	146407187	146407246	chr1	247249719	-	101189341	101189400	31412390
+59
+
+chain	5452	chr1	249250621	+	146243368	146248596	chr1_random	1663265	-	1047698	1052949	2624
+34	4838	4857
+26	270	274
+60
+
+chain	5266	1	249250621	+	249240022	249240077	chr1	247249719	-	247249582	247249637	32667083
+55
+
+chain	5203	1	249250621	+	146446237	146446668	chr1	247249719	-	102500144	102500575	1674615
+120	155	155
+156
+
+chain	4958	1	249250621	+	146451766	146451818	chr1	247249719	+	142879884	142879936	20619966
+52
+
+chain	4944	1	249250621	+	104074593	104074659	chr8	146274826	-	121738108	121738174	21132898
+66
+
+chain	4456	1	249250621	+	146406808	146406855	chr1	247249719	-	101188965	101189012	6127414
+47
+
+chain	4404	1	249250621	+	146406008	146406074	chr1	247249719	-	100540708	100540774	1844606
+66
+
+chain	4255	1	249250621	+	146230090	146231384	chr1	247249719	-	103181490	103211127	6721
+37	1201	29544
+56
+
+chain	4244	1	249250621	+	146216712	146216757	chr1	247249719	-	102323372	102323417	831523
+45
+
+chain	4123	1	249250621	+	146421615	146421675	chr1	247249719	+	143536766	143536826	34723
+60
+
+chain	3877	1	249250621	+	146435532	146435575	chr1	247249719	-	101203375	101203418	141544
+43
+
+chain	3825	1	249250621	+	146430767	146430810	chr1	247249719	-	101203375	101203418	118474
+43
+
+chain	3528	1	249250621	+	146454014	146454173	chr1	247249719	-	100628659	100628818	205230
+159
+
+chain	3185	1	249250621	+	146406525	146406559	chr1	247249719	-	101188682	101188716	16359386
+34
+
+chain	3178	1	249250621	+	104074770	104074842	chr7	158821424	+	21042162	21042234	21615733
+72
+
+chain	3121	1	249250621	+	146445079	146445768	chr1	247249719	+	144930661	144931350	792159
+25	471	471
+193
+
+chain	3050	1	249250621	+	146407036	146407068	chr1	247249719	-	101189190	101189222	23011976
+32
+
+chain	2960	1	249250621	+	146249122	146249154	chr1	247249719	+	144760680	144760712	1406096
+32
+
+chain	2741	1	249250621	+	146231545	146231601	chr1	247249719	-	104345036	104345092	8679
+56
+
+chain	2464	1	249250621	+	146424736	146424776	chr1	247249719	+	144037261	144037301	21508852
+40
+
+chain	2405	1	249250621	+	249239910	249239972	chr1	247249719	-	247249327	247249389	7681464
+62
+
+chain	2390	1	249250621	+	249240288	249240334	chr1	247249719	-	247249596	247249642	26481552
+46
+
+chain	2344	1	249250621	+	146216757	146250883	chr1	247249719	-	103711249	103726499	1396
+67	32948	14063
+57	892	901
+7	127	127
+28
+
+chain	2164	1	249250621	+	146237300	146252192	chr1	247249719	+	16771061	16779662	20592
+30	14825	8534
+37
+
+chain	1926	1	249250621	+	10623	10756	chr15	100338915	-	932	978	361
+6	87	0
+40
+
+chain	1909	1	249250621	+	146251590	146251644	chr1	247249719	-	103917507	103917561	1304306
+54
+
+chain	1317	1	249250621	+	146445768	146445881	chr1	247249719	+	142919887	142920000	1148922
+113
+
+chain	1215	1	249250621	+	146245082	146245105	chr1	247249719	+	144762924	144762947	79987
+23
+
+chain	1154	1	249250621	+	146232196	146232260	chr1	247249719	+	16765963	16766027	137025
+64
+
+chain	1035	1	249250621	+	146367698	146367747	chr1	247249719	-	99837677	99837726	4094688
+49
+
+chain	827	1	249250621	+	146445037	146445075	chr1	247249719	-	102502075	102502113	153232
+38
+
+chain	691	1	249250621	+	146454173	146454226	chr1	247249719	-	100557283	100557336	435331
+53
+
+chain	604	1	249250621	+	146429501	146429541	chr1	247249719	+	147018285	147018325	1335641
+40
+
+chain	424	1	249250621	+	146449372	146449403	chr1	247249719	-	100776122	100776153	793932
+31
+
+chain	395	1	249250621	+	146448669	146448702	chr1	247249719	+	144078479	144078512	164120
+33
+
+chain	88	1	249250621	+	146452351	146452395	chr1	247249719	-	99890656	99890700	12702616
+44
+
+chain	71	1	249250621	+	146451564	146451618	chr1	247249719	-	102499166	102499220	29039078
+54
+
+chain	12431961244	10	135534747	+	60000	135524747	chr10	135374737	+	50000	135374737	10
+5577104	0	50006
+12337571	50000	50000
+20794160	50000	50000
+286100	3200000	2480000
+191752	50000	50000
+3830277	50000	150000
+952205	100000	150000
+263307	100000	150000
+163231	50000	150000
+989829	100000	150000
+1941874	50000	50000
+211435	50000	50000
+30112515	0	319974
+13249156	0	10
+31058956	50000	50000
+2696597	150000	50000
+4615335	50000	10000
+246123	50000	50000
+1327328	1	1
+47	1	1
+1312	0	1
+56	1	1
+190	1	1
+31	1	1
+20182	1	0
+448068
+
+chain	12415603391	11	135006516	+	60000	134946516	chr11	134452384	+	50000	134451988	11
+1102759	50000	16576
+49571094	307000	207000
+503352	3100000	3000000
+14395596	47395	0
+491076	304	60
+30213	182	114
+26	142	1
+27914	0	1
+20009	0	1
+19	0	1
+39	0	1
+17	1	3
+10	0	1
+1008	0	1
+95	0	1
+5126	0	15
+303	0	1
+975	4	0
+1548	1	0
+191	0	20
+40	0	1
+74	1	0
+101	0	1
+25	1	0
+6178	1	0
+1875	52561	21437
+468	1	1
+81	1	1
+2620	0	1
+1640	0	4
+3305	1	0
+3342	0	1
+17899663	50000	12000
+8549206	150000	15562
+38507167	37	39
+1282	0	174
+387	0	86
+59
+
+chain	112280	chr11	135006516	+	69774695	69777256	chr11_random	215294	-	174770	177331	705
+2561
+
+chain	3731264	chr11_gl000202_random	40103	+	0	40103	chr11_random	215294	-	0	39615	791
+14658	1036	100
+6712	6	6
+32	35	523
+27	51	11
+17546
+
+chain	12330185447	12	133851895	+	145739	133779461	chr12	132349534	+	16000	132289534	12
+7035084	4	0
+543	1	0
+3777	1	0
+3889	52114	73000
+6014	0	1
+6524	5	126
+29	0	13
+20974	2	0
+3965	0	3
+444	11	0
+464	0	1
+27577110	3000000	1395000
+38631945	1	0
+14544	4	0
+1700	0	1
+789	12128	250000
+1783	0	1
+1075	2	0
+1042	0	1
+1526	1	1
+27	1	1
+2320	1	0
+166	0	1
+564	1	0
+2856	2	0
+900	1	0
+1387	1	1
+33	1	1
+2139	1	1
+48	1	1
+1305	2	0
+1533	2	1
+879	1	0
+744	26	26
+858	4	0
+1089	0	6
+1113	0	12
+818	1	1
+18	0	1
+217	1	1
+36	1	1
+2002	0	1
+1025	1	0
+450	48	48
+916	0	1
+18	1	1
+4694	8	0
+142	0	4
+3656	0	2
+3403	1	1
+47	1	1
+1524	1	1
+28	1	1
+5560	48	45
+676	8	8
+810	16	16
+536	0	2
+236	0	4
+167	4	0
+1419	53	49
+4688	1	1
+38	1	1
+18576	0	5
+5285	2	0
+6486	1	1
+25	1	1
+4341	14	0
+2662	0	5
+1170	0	1
+4268	4	0
+1036	1	0
+2117	8	0
+5917	0	1
+3239	4	0
+2619	1	1
+21	1	1
+937	1	1
+38	1	1
+2412	124	139
+2648	2	0
+9314	0	2
+1986	2	2
+16	1	1
+229	1	1
+93	1	1
+895	0	12
+415	5	1
+119	1	1
+185	9	8
+458	2	0
+89	1	1
+42	1	1
+2034	1	0
+1545	2	0
+280	4	0
+97	14	14
+231	2	0
+2814	0	5
+1679	1	1
+27	1	1
+25758689	1	0
+6536665	1	0
+377270	96749	57000
+668	1	1
+20	0	1
+3348	1	1
+33	1	1
+648	1	1
+29	1	1
+3731	0	4
+1834	9	14
+1688	10	0
+3103	5	5
+1140	0	1
+1167	0	1
+985	9	9
+2897	0	1
+1625	0	9
+1101	1	0
+1358	8	0
+13065721	68352	150000
+810	0	2
+343	1	0
+1771	1	0
+2702	6	7
+1900	0	1
+705	0	6
+303	0	1
+727	1	1
+43	3	6
+490	1	1
+59	1	1
+226	1	1
+52	0	3
+465	8	0
+194	1	1
+25	0	1
+139	17	17
+1833	0	1
+81	1	1
+39	1	1
+453	0	1
+719	1	1
+47	1	1
+558	0	1
+838	1	8
+288	9	10
+741	2	5
+465	1	1
+48	1	1
+268	1	1
+26	0	1
+1337	17	0
+12	2	1
+16	1	1
+84	85	2
+917	0	1
+110	1	1
+29	1	1
+1580	1	1
+40	1	1
+683	1	1
+24	1	1
+247	1	1
+36	1	1
+1411	14	14
+149	1	0
+10091386	3	0
+296	5	0
+220	100872	45000
+972469
+
+chain	2067120	12	133851895	+	60245	88108	chr2	242951149	+	114046160	114069967	1234
+334	1	1
+47	1	1
+111	1	1
+20	0	13
+84	1	1
+84	7	15
+55	1	1
+28	1	1
+77	1	1
+49	1	1
+99	10	10
+345	1	1
+48	0	4
+16	2	2
+168	1	1
+160	1	1
+68	1	0
+62	1	1
+23	1	1
+144	7	7
+94	2128	0
+762	12	12
+305	1	1
+40	1	1
+385	196	196
+207	0	1
+267	1	1
+53	1	1
+58	0	12
+43	1	1
+55	4	4
+38	1	0
+361	1	0
+53	1	1
+27	1	1
+448	1	1
+18	1	1
+309	4	0
+104	1	1
+35	1	1
+394	1	1
+16	1	1
+159	1	1
+38	1	1
+413	14	14
+82	5	7
+699	0	1
+52	23	24
+1077	9	9
+492	1	0
+144	18	19
+69	1	1
+26	1	1
+689	2	0
+34	5	6
+34	1	1
+187	1	1
+65	1	1
+181	9	9
+82	1	1
+55	0	2
+310	1	1
+25	1	1
+71	1	1
+74	3	3
+64	6	6
+216	5	5
+62	1	1
+35	8	3
+803	1	0
+23	1	1
+124	1	1
+90	1	1
+300	4	0
+48	0	4
+28	1	0
+85	7	4
+63	2	0
+7	3	0
+49	1	1
+255	31	31
+462	1	1
+38	1	1
+414	1	1
+37	1	1
+304	1	1
+36	1	1
+119	16	19
+62	1	1
+26	1	1
+306	1	1
+93	1	1
+114	1	1
+141	1	1
+464	1	1
+25	1	1
+145	1	1
+21	1	1
+196	1	1
+46	1	1
+295	11	11
+255	1	1
+21	1	1
+280	1	1
+90	1	1
+413	8	8
+1039	24	24
+761	1	0
+53	1	1
+94	1	0
+25	1	1
+63	1	1
+71	2070	1
+21	2	47
+228	3	0
+17	1	1
+133	11	0
+137	1	1
+43	1	1
+90	3	3
+23	2	0
+144	1	1
+99	1	1
+349	3	3
+29	5	5
+60	0	70
+93	1	1
+21	1	1
+138	0	2
+83	1	1
+68	1	1
+166	1	1
+49	1	1
+461	1	1
+18	0	17
+26	1	1
+50	1	1
+14	0	1
+34	1	1
+370	1	1
+32	1	1
+68	14	14
+98
+
+chain	484774	12	133851895	+	88108	95739	chrX	154913754	+	154905409	154913416	8417
+2	1	1
+34	1	1
+80	1	1
+32	1	1
+415	1	1
+48	1	1
+73	1	1
+44	1	1
+149	13	13
+211	1	1
+26	1	1
+271	0	3
+528	1	1
+96	1	1
+507	1	1
+100	1	1
+121	37	37
+520	1	1
+34	1	1
+166	1	1
+45	1	1
+96	1	1
+87	1	1
+82	4	4
+71	1	1
+34	1	1
+132	1	1
+23	1	1
+97	1	1
+30	2	2
+109	3	3
+36	1	1
+134	2135	2017
+245	454	1029
+82	84	0
+113
+
+chain	233388	12	133851895	+	133837240	133840071	chr7	158821424	+	158817351	158819960	454901
+564	1	1
+52	1	0
+36	1	1
+470	1	1
+28	1	1
+359	1	1
+38	1	1
+130	5	0
+3	216	0
+97	3	2
+46	1	1
+559	1	1
+43	0	1
+78	1	1
+94
+
+chain	194103	12	133851895	+	62428	64518	chr14	106368585	+	64430621	64433205	634790
+748	40	40
+140	0	1
+167	0	373
+27	0	120
+968
+
+chain	49263	12	133851895	+	133825767	133827148	chr11	134452384	+	74280352	74281733	2582033
+188	22	24
+55	110	110
+117	297	297
+62	252	253
+116	101	98
+61
+
+chain	35717	12	133851895	+	133841521	133841895	chr5	180857866	-	180793287	180793661	3746803
+374
+
+chain	32957	12	133851895	+	133823831	133824928	chrX	154913754	-	110744397	110745491	4131553
+102	47	47
+104	308	309
+61	155	155
+59	173	169
+88
+
+chain	18331	12	133851895	+	133822513	133823307	chr7	158821424	+	35158939	35159735	11829157
+110	151	152
+60	413	414
+60
+
+chain	16856	12	133851895	+	66036	76221	chr19	63811651	-	63781390	63791585	1292
+70	1	1
+57	16	16
+51	9959	9969
+31
+
+chain	16157	12	133851895	+	109428208	109428485	chr2	242951149	-	225002676	225002954	13880737
+71	91	92
+115
+
+chain	11750	12	133851895	+	60000	60122	chr12	132349534	-	132324140	132324262	19413804
+122
+
+chain	9037	12	133851895	+	133826997	133827421	chr2	242951149	+	160701141	160701565	3717783
+90	61	61
+34	175	175
+64
+
+chain	8057	12	133851895	+	133826086	133826759	chr3	199501827	-	98694913	98695583	3241421
+56	127	126
+50	305	303
+135
+
+chain	4873	12	133851895	+	133822983	133823177	chr6	170899992	+	146924403	146924597	15743780
+57	73	73
+64
+
+chain	4427	12	133851895	+	133827536	133827658	chr3	199501827	-	37386916	37387038	7696734
+122
+
+chain	4266	12	133851895	+	109428325	109428370	chr8	146274826	+	102422247	102422292	23131068
+45
+
+chain	4036	12	133851895	+	133826320	133826456	chrX	154913754	+	144352164	144352300	4124454
+136
+
+chain	3880	12	133851895	+	95312	95362	chr1	247249719	-	247249339	247249389	25961870
+50
+
+chain	3693	12	133851895	+	63176	63216	chr6	170899992	-	141104715	141104755	640206
+40
+
+chain	3673	12	133851895	+	133827423	133827506	chr2	242951149	-	104106513	104106596	10382380
+83
+
+chain	3091	12	133851895	+	133826496	133826821	chr11	134452384	-	91473718	91474043	4183905
+58	205	205
+62
+
+chain	3057	12	133851895	+	133822699	133822767	chr2	242951149	+	211079534	211079602	19980130
+68
+
+chain	2758	12	133851895	+	133827507	133827536	chr3	199501827	-	112531647	112531676	15775673
+29
+
+chain	2377	12	133851895	+	133825725	133826065	chr1	247249719	+	157351310	157351652	3309912
+42	265	267
+33
+
+chain	2375	12	133851895	+	95368	95419	chr1	247249719	-	247249256	247249307	12772530
+51
+
+chain	2223	12	133851895	+	133827262	133827357	chr6	170899992	+	81976496	81976591	4176034
+95
+
+chain	2091	12	133851895	+	109428279	109428301	chr20	62435964	+	39979396	39979418	21613404
+22
+
+chain	1955	12	133851895	+	133822880	133822953	chr4	191273063	-	60412182	60412255	19166211
+73
+
+chain	1569	12	133851895	+	133823330	133823447	chr5	180857866	+	90128366	90128483	9408356
+117
+
+chain	1532	12	133851895	+	133822199	133822253	chr12	132349534	+	77527067	77527121	12101346
+54
+
+chain	1265	12	133851895	+	133825609	133825680	chr2	242951149	+	183532658	183532729	7750866
+71
+
+chain	1251	12	133851895	+	95185	95235	chr18	76117153	-	76117025	76117075	24929113
+50
+
+chain	1165	12	133851895	+	133826456	133826496	chrX	154913754	-	53085075	53085115	5993397
+40
+
+chain	1153	12	133851895	+	133824667	133824711	chr10	135374737	-	97414674	97414718	8388000
+44
+
+chain	852	12	133851895	+	133822443	133822508	chr5	180857866	+	49699275	49699340	23831787
+65
+
+chain	636	12	133851895	+	133823040	133823067	chr6	170899992	+	127619395	127619422	20859432
+27
+
+chain	615	12	133851895	+	133823498	133823556	chr14	106368585	-	76653675	76653733	3589163
+58
+
+chain	440	12	133851895	+	133827198	133827224	chr1	247249719	-	50786620	50786646	7302157
+26
+
+chain	9007882413	13	115169878	+	19020000	115109878	chr13	114142980	+	17918000	114127980	14
+26987167	0	1
+40753157	150000	50000
+25443670	150000	400000
+1821999	413955	384056
+369930
+
+chain	17589438	13	115169878	+	114456082	114639948	chr13	114142980	-	484930	668986	160
+430	0	2
+2905	4	8
+143	0	30
+612	0	4
+18	0	2
+175	1	1
+49	0	2
+2159	1	1
+27	1	1
+979	0	144
+1492	0	2
+174870
+
+chain	8359015315	14	107349540	+	19000000	107289540	chr14	106368585	+	18070000	106360585	15
+1081285	1	1
+43	1	1
+76	0	2
+437	1	1
+19	1	1
+440	1	0
+11	1	1
+59	15	15
+63	12	12
+70	1	0
+734	1	1
+165	4	1
+96	1	1
+46	0	1
+83	1	1
+149	4	4
+164	20	20
+63	16	15
+359	1	1
+39	1	1
+103	1	1
+76	1	1
+139	1	1
+38	1	1
+344	1	1
+65	1	0
+166	5	5
+88	1	1
+57	287	0
+59	1	1
+317	1	0
+52	1	1
+92	0	4
+651	4	4
+82	1	1
+93	1	1
+64	1	1
+24	1	1
+856	1	1
+35	1	1
+258	1	1
+17	1	1
+478	0	1
+1335	33	33
+1029	1	1
+37	1	1
+1115	4	3
+72	1	1
+643	10	10
+132	6	6
+89	2	0
+209	4	15
+77	5	5
+427	1	1
+41	1	1
+949	1	1
+16	1	1
+732	1	1
+44	0	2
+128	1	0
+91	1	1
+180	6	6
+388	6	6
+50	12	13
+275	1	1
+33	1	1
+142	1	1
+61	1	1
+560	1	1
+20	1	1
+1327	13	6
+1013	83	83
+202	4	0
+43	1	1
+352	10	10
+261	1	1
+39	1	1
+939	0	12
+1678	0	36
+159	1	1
+32	1	8
+818	6	0
+580	0	1
+931	0	1
+276	0	2
+3513	46	60
+882	0	2
+94	1	1
+49	1	1
+864	0	4
+40	1	1
+807	15	16
+416	3	0
+3345	15	15
+92	29	30
+80	1	1
+48	1	1
+2459	1	0
+646	66	66
+359	1	1
+29	0	54
+1875	0	3
+141696	1	1
+32	1	1
+8201115	0	1
+107	0	1
+2137	1	1
+39	1	1
+8848	1	0
+4806	0	1
+2075	0	1
+16612	0	1
+2385	0	3
+11506	0	8
+1353	1	0
+4596	1	0
+2073	1	2
+28	1	1
+2311	1	1
+44	1	1
+10440	4	0
+894	1	0
+1638	96	0
+41	0	9
+20	1	1
+2705	0	6
+352	1	1
+25	1	1
+742	1	0
+1048	18	2
+12085977	1	0
+14871228	0	3
+29067652	1	1
+47	1	1
+20173856	0	1292
+2548494
+
+chain	25802	14	107349540	+	20085579	20085848	chr8	146274826	+	118781991	118782260	6606813
+269
+
+chain	9908	14	107349540	+	20110215	20120217	chr22	49691432	+	14757849	14767860	97
+45	9891	9900
+66
+
+chain	8901	14	107349540	+	20090287	20100367	chr14	106368585	-	87815145	87825210	65
+33	9964	9949
+83
+
+chain	7700563179	15	102531392	+	20000000	102521392	chr15	100338915	+	18260008	100338915	16
+8448	2	6
+4086	0	1
+9569	1	1
+40	5	0
+56	1	7
+872354	40513	40506
+553	4	4
+876	40	39
+139	25	25
+1881	18	19
+499	8	8
+310	79	85
+78	26	23
+181	6	5
+569	11	11
+539	28	24
+261	22	20
+776	15	13
+62	13	13
+860	0	1
+716	0	26
+1349	167	166
+1070	23	23
+398	1	0
+177	21	5
+534	0	4
+770	24	18
+606	33	33
+1861	55	55
+2169	0	3
+558	19	20
+227	14	16
+329	5	5
+430	18	20
+620	1	0
+1112	0	2
+641	4	0
+476	47	47
+1285	1	0
+1139	49	49
+183	0	4
+1425	0	20
+186	1	0
+219	1	0
+607	44	44
+371	8	2
+507	0	2
+66	42	43
+999	4	4
+318	15	15
+1092	74	74
+808	61	61
+52	42	42
+109	51	51
+1535	0	14
+14011	0	4
+7955	1	4
+1350	0	1
+318	27	27
+600	4	0
+442	1	0
+1396	38	38
+1107	3	0
+1441	5	0
+360	49	49
+256	10	20
+497	39	39
+2129	0	4
+1242	0	2
+478	0	4
+708	92	92
+154	10	10
+1583	33	33
+1303	37	0
+100	14	14
+1138	92	109
+114	31	31
+2917	34	34
+1762	48	48
+449	0	1
+2458	1	9
+869	0	1
+534	49	49
+309	0	1
+2627	1	1
+3729	0	22
+565	1	0
+1845	0	1
+660	27	27
+68	0	1
+217	46	22
+1519	34	34
+559	32	32
+3851	0	1
+265	7	8
+224	0	4474
+444	0	1
+1651	10	11
+297	0	1
+665	0	21
+48	1	1
+1763	0	2
+245	1	1
+39	1	1
+519	1	1
+31	1	1
+2398	6	0
+749	1	49
+2072	0	4
+703	5	5
+337	0	1
+470	45	45
+1163	0	3
+1342	45	45
+140	1	0
+83	65	64
+723	38	38
+99	28	31
+92	0	1
+1218	13	0
+384	2	0
+292	41	41
+101	12	12
+576	2	0
+1907	21	21
+318	0	1
+1973	34	34
+689	51	51
+357	8	8
+2354	15	15
+2295	26	26
+2558	28	28
+571	2	0
+16	5	0
+323	1	0
+36	1	0
+5342	0	111
+1722	70	38
+272	13	13
+1284	1	0
+1128	4	4
+2189	0	1
+474	0	2
+1284	27	27
+36	6	0
+641	39	39
+381	2	0
+56	0	1
+2591	57	57
+160	121	121
+89	0	2
+316	1	0
+782	0	20
+155	1	1
+21	1	1
+601	6	0
+567	0	1
+278	1	1
+29	1	1
+89	4	0
+1737	1	1
+58	1	1
+368	24	24
+2113	24	20
+218	2	0
+18	1	1
+684	4	4
+3200	33	33
+58	18	18
+164	39	39
+296	6	6
+431	37	37
+431	47	47
+93	26	26
+216	48	48
+2779	17	0
+745	1	2
+104	61	61
+445	28	28
+356	0	1
+1484	2	1
+436	25	25
+306	57	57
+230	4	4
+843	49	50
+364	7	7
+796	28	28
+663	2	0
+93	15	0
+4378	0	1
+133	30	26
+41	2	0
+80	150	150
+925	0	3
+1882	13	13
+4513	0	1
+111	78	78
+200	0	6
+682	1	0
+200	0	3
+429	2	0
+736	20	20
+1573	121	120
+245	21	12
+1656	22	54
+616	1	2
+158	1	0
+587	41	44
+1053	6	6
+1116	36	36
+152	7	10
+448	1	0
+269024	863295	100000
+334079	50000	100000
+180557	74	0
+62	0	107
+7	2	1
+26	3	4
+4	0	1
+19	3	4
+10	42	87
+27	1	1
+202	1	1
+17	1	0
+156	1	1
+55	1	1
+111	1	0
+144	1	1
+57	1	0
+687074	50000	50000
+120648	348	0
+45585	1	0
+6994	0	1
+3398063	12354	44008
+7672	2	0
+1809	0	1
+428524	10165	101014
+43170	4	4
+1064959	5086	128966
+1021	1	0
+1710	0	1
+931	2	0
+4505	1	0
+686	2	525
+360	0	33
+130	1	1
+18	1	1
+12369	0	1014
+6233	1	0
+359485	111749	100000
+33855822	239	0
+2852112	0	1
+7040367	1	0
+2815738	1	3
+7055922	50000	60000
+363827	32	32
+104991	1	0
+203136	6050	0
+1426791	50000	60000
+13510190	5553	22012
+9194	3	0
+108	4	0
+41	1	0
+45	7	0
+2350	13	0
+5027	2	0
+534	0	1
+794	2	0
+4227	8	6
+5769	0	1
+381	0	1
+2524	2	0
+547	5	0
+1967	1	0
+1192	0	105
+1042	6	0
+3935380
+
+chain	22529558	15	102531392	+	21901199	22210800	chr15	100338915	+	19154576	19464222	111
+143347	1	1
+30	1	1
+2265	10	11
+297	0	1
+665	49	70
+240	39	39
+1731	41	41
+519	33	33
+339	22	22
+2037	4	0
+749	1	49
+910	38	38
+1831	3	9
+333	0	1
+470	1	1
+43	1	1
+1518	1	1
+51	1	1
+1122	1	0
+2351	19	6
+376	2	0
+1022	2	0
+1907	1	1
+19	1	1
+318	0	1
+3104	8	8
+179	1	1
+29	1	1
+3162	2	0
+2854	1	1
+26	1	1
+482	1	0
+512	1	1
+26	1	1
+571	27	16
+323	37	36
+5342	0	111
+542	40	39
+1141	64	35
+275	13	13
+503	26	26
+130	44	44
+581	4	0
+1128	4	4
+749	0	1
+1439	0	1
+474	0	16
+1270	1	1
+25	1	1
+54	11	0
+623	1	1
+37	1	1
+381	20	0
+56	0	1
+2591	1	1
+55	1	1
+160	4	4
+75	14	14
+1217	0	15
+742	59	53
+955	3	0
+1737	60	60
+391	43	43
+2071	24	20
+218	21	19
+684	4	4
+1195	4	4
+2001	1	1
+31	1	1
+58	18	18
+499	6	6
+431	1	1
+35	1	1
+431	1	1
+45	1	1
+3158	17	0
+983	0	1
+773	16	16
+1457	4	1
+767	1	1
+55	1	1
+338	10	10
+650	0	2
+123	3	4
+261	1	1
+48	1	1
+53	7	7
+776	1	1
+46	1	1
+663	2	0
+377	13	13
+4081	0	1
+159	5	0
+41	1	0
+164	1	1
+61	4	4
+925	0	3
+934	18	18
+1971	0	5
+3592	1	1
+76	1	1
+200	0	6
+682	1	0
+632	2	0
+2338	1	0
+110	1	1
+231	10	0
+1682	42	54
+616	1	2
+171	2	1
+543	1	1
+45	0	12
+2837	1	0
+441	2	0
+4958	5	5
+455	37	37
+330	22	22
+711	46	46
+184	49	49
+153	61	62
+392	11	11
+1266	8	7
+241	42	41
+198	31	31
+1064	78	78
+528	0	4
+431	1	0
+108	64	53
+358	5	5
+566	35	33
+168	1	0
+251	41	41
+880	33	33
+248	7	9
+583	3	4
+217	41	41
+117	13	14
+203	78	78
+133	44	45
+59	43	43
+129	19	19
+887	1	0
+264	30	30
+352	16	16
+719	36	35
+196	49	49
+425	4	0
+358	15	15
+151	22	22
+714	0	3
+165	41	0
+199	134	134
+504	47	47
+526	12	16
+206	39	39
+372	6	6
+224	25	25
+304	7	7
+186	90	90
+1872	0	3
+1066	7	7
+180	85	75
+63	37	37
+157	65	65
+331	3	0
+302	3	6
+213	42	45
+350	45	49
+580	42	45
+252	43	43
+337	4	0
+667	10	7
+94	9	9
+441	18	18
+124	0	1
+277	42	42
+1729	37	37
+1562	3	1
+546	15	13
+409	22	22
+312	45	45
+46	0	2
+268	14	14
+1166	35	38
+460	0	2
+74	0	1
+323	27	26
+2747	24	28
+322	10	0
+592	23	21
+161	45	45
+207	50	50
+409	22	23
+188	50	49
+396	152	151
+343	26	28
+3430	49	49
+2161	72	72
+1696	5	0
+389	50	50
+340	23	23
+169	0	3
+70	0	4
+392	0	1
+106	32	32
+2476	23	23
+1397	53	54
+2187	18	18
+489	9	9
+2018	4	0
+108	17	14
+836	5	5
+417	48	48
+358	34	34
+481	55	56
+277	48	48
+180	25	21
+356	3	0
+66	66	66
+407	28	27
+603	36	36
+1239	0	3
+194	8	8
+444	0	1
+204	35	35
+162	15	15
+418	6	5
+236	9	9
+55	52	52
+105	145	146
+57	143	143
+52
+
+chain	868538	15	102531392	+	21886534	21896633	chr15	100338915	+	19140000	19150000	4870
+1208	1	0
+245	165	68
+494	89	89
+824	15	15
+196	0	1
+197	50	50
+274	0	1
+1127	15	15
+230	4	0
+76	48	49
+671	0	1
+352	24	19
+117	11	11
+288	5	4
+122	0	3
+135	37	37
+265	0	2
+62	2	0
+656	0	2
+792	69	69
+142	73	73
+307	2	0
+331	0	2
+378
+
+chain	566185	15	102531392	+	83551634	83557670	chr8	146274826	+	129534406	129540446	9431
+549	1	1
+105	1	1
+1154	0	4
+273	6	6
+3947
+
+chain	334937	15	102531392	+	21896662	21900709	chr15	100338915	+	19150028	19154088	190582
+86	46	44
+567	11	9
+733	23	25
+212	2	0
+100	40	40
+155	1	0
+189	34	34
+165	42	42
+219	56	68
+259	61	62
+380	3	8
+242	13	13
+408
+
+chain	246244	15	102531392	+	22183221	22212114	chr15	100338915	+	19767012	19795905	936
+45	207	207
+50	619	619
+50	396	396
+152	343	343
+26	3430	3430
+49	2161	2161
+72	2090	2090
+50	1100	1100
+32	3896	3896
+53	6108	6108
+48	358	358
+34	481	481
+55	277	277
+48	180	180
+25	425	425
+66	407	407
+28	603	603
+36	2089	2089
+35	901	901
+52	105	105
+145	57	57
+143	52	52
+1314
+
+chain	136774	15	102531392	+	21885000	21886534	chr15	100338915	+	19138465	19140000	942717
+402	49	49
+445	0	1
+638
+
+chain	38827	15	102531392	+	28705151	28710237	chr15	100338915	-	73838719	73843805	82
+5086
+
+chain	19525	chr15	102531392	+	27138463	27148846	chr15_random	784346	+	739466	749849	392
+10383
+
+chain	9597	15	102531392	+	29116154	29116267	chr19	63811651	-	22308947	22309060	23761910
+59	4	4
+50
+
+chain	6273	15	102531392	+	23685556	23685849	chr15	100338915	+	21236652	21236834	12713809
+67	205	94
+21
+
+chain	4893	15	102531392	+	29111049	29111100	chr21	46944323	+	41885809	41885860	33898070
+51
+
+chain	3039	15	102531392	+	22178426	22178458	chr8	146274826	+	6100529	6100561	34349851
+32
+
+chain	2975	15	102531392	+	22826750	22826789	chr15	100338915	+	20381852	20381891	2718765
+39
+
+chain	2542	15	102531392	+	21049663	21065195	chr18	76117153	+	14510749	14526638	994
+38	2128	2130
+28	13310	13665
+28
+
+chain	1826	15	102531392	+	20950735	20950759	chr19	63811651	-	51273213	51273237	15159639
+24
+
+chain	1062	15	102531392	+	21028626	21028659	chr21	46944323	-	32992576	32992609	1118
+33
+
+chain	912	15	102531392	+	22826789	22826824	chr15	100338915	+	20377303	20377338	985154
+35
+
+chain	7474990131	16	90354753	+	60000	90294753	chr16	88827254	+	0	88822254	17
+172343	1	0
+111	0	1
+5627	1	2
+8398838	50000	17500
+25336229	150000	100000
+1112651	11100000	9800000
+42003582	50000	20000
+1855370
+
+chain	7369719958	17	81195210	+	0	81060651	chr17	78774742	+	0	78654742	18
+252627	1	1
+24	1	1
+41	29	0
+295	0	29
+261	0	58
+116	0	58
+94	0	29
+79	37	8
+485	59	1
+28	1	1
+76	1	233
+26	0	29
+2765	1	0
+17	2	0
+2220	18	18
+343	37	37
+457	1	1
+39	1	1
+564	16	16
+2523	9	39
+1878	56	0
+22	0	29
+1681	1	0
+414	3	0
+282	68	0
+93	10	10
+293	4	0
+3190	0	1
+2562	4	0
+1809	0	3
+84	1	1
+62	1	1
+3775	27	0
+1968	0	16
+912	2	0
+696	4	4
+1428	15	15
+290	0	1
+1779	1	0
+60	1	1
+216	1	0
+375	1	1
+41	1	0
+9221	100000	46522
+3080543	1	0
+1208216	2	0
+1370	0	2
+1279	4	0
+322	5	0
+5660	0	210
+308	22	21
+973	0	8
+2901	0	1
+8479	1	0
+4122	0	7
+3187	0	4
+571	1	0
+167	1	0
+10174	7	7
+856	1	2
+1630	0	1
+4258	1	3
+1688	0	1
+388	304	0
+672	0	1
+8495	10	0
+2272	0	1
+8297	0	1
+1500	4	1
+733	2	37
+57	17	0
+51	532	42
+2085	0	2
+52	1	1
+2913	13	14
+1309	1	0
+3991	0	3
+1939	3	0
+887	2	0
+463	0	18
+64	3	0
+2104	20	0
+557	4	0
+120	1	0
+3670	0	2
+4347	5394	0
+5332	1	0
+2505	10	4
+6776	11	14
+9573	1	0
+1136	2	0
+3754	0	1
+4588	0	1
+637	17	17
+1283	0	8
+371	1	0
+2084	0	1
+492	0	2
+519	4	0
+952	2	0
+1517	0	1
+987	0	9
+1152	10	0
+3608	2	0
+3199	39	0
+734	0	1
+646	0	2
+2211	0	1
+14829	0	1
+3473	34	1
+22	0	11
+2194	1	0
+6443	4	5
+2627353	0	1
+11581974	43	0
+31	89	0
+238782	1	0
+1830653	0	1
+419873	116477	100008
+5586	0	6
+11057	2	0
+3240	0	1
+1237	2	0
+373	1	1
+43	1	1
+558379	3000000	100000
+1823446	1	0
+2728383	1	0
+29	1	0
+138	0	1
+144	8	6
+38	2	0
+7	1	0
+18	1	1
+70935	1	0
+10	2	0
+52	31	28
+189	1	0
+41	2	2
+750363	44	44
+4038953	50039	100039
+1523967	1	1
+47	1	1
+231	0	2
+1175	0	1
+555	1	1
+49	1	1
+566	0	7
+607	0	2
+4954	1	1
+18	7	6
+567	1	0
+421	0	2
+1010	0	8
+777	3	0
+925	5	12
+318	0	1
+230	13	20
+244	1	1
+13	1	0
+42	1	1
+220	1	1
+56	1	1
+101	0	225
+1113	0	1
+17	1	1
+2614	0	4
+7108	2	0
+617	0	14
+5674	2	0
+1852	1	1
+63	1	1
+56	1	1
+25	1	1
+332	6	0
+423	5	5
+61	0	4
+108	1	1
+46	1	1
+160	2	2
+72	1	1
+162	1	1
+20	1	1
+53	1	1
+63	1	1
+112	1	1
+59	1	1
+5885	0	2
+5871	30040	159230
+925	0	5
+214	7	7
+641	17	17
+1296	46	46
+2513	69	71
+76	2	1
+57	0	50226
+1963	18	18
+2694	55	55
+6616	0	1
+5106	18	0
+2521	7	7
+49	0	10
+3440	4	0
+4179	4	0
+2749	1	0
+1125	0	8
+55	1	1
+1840	14	14
+624	0	8
+1742	0	4
+3690	4	0
+2051	1	0
+751	1	0
+2111	11	10
+3110	0	1
+682	0	1
+2795	2	5
+241	1	0
+165	3	1
+1258	1	0
+1601	0	5
+3716	1	0
+1308	1	0
+2058	0	1
+1624	1	0
+478	0	4
+9	0	6
+35	1	3
+47	1	0
+2425	0	1
+1178	4	0
+33	1	1
+415	5	5
+887	3	1
+1605	0	15
+259	0	2
+78	1	0
+4570	1	0
+322	0	1
+1801	0	2
+836	0	3
+1509	1	0
+1732	1	0
+936	6	0
+1371	0	1
+625	12	2
+5009	1	1
+75	1	0
+20	0	1
+139	1	0
+523	3	0
+11	319	0
+1368	0	1
+774	1	1
+16	1	1
+3523	119	124
+497	0	4
+174	0	9
+1317	3	0
+508	1	0
+1126	0	1
+1952	2	0
+565	0	2
+871	1	0
+1460	0	6
+55	1	0
+420	0	6
+57	1	1
+119	1	1
+427	0	1
+459	11	14
+448	1	0
+1275	7	7
+360	0	1
+73	1	1
+48	1	1
+4920	0	3
+713	1	1
+21	0	3
+6	0	3
+6	0	1
+691	1	1
+44	1	1
+1158	38	38
+446	10	9
+566	1	0
+175	4	0
+796	10	0
+810	0	1
+78	17	18
+1531	2	0
+1274	1	1
+39	1	1
+53	1	3
+202	1	0
+707	17	17
+1733	1	0
+1540	42	42
+12471	0	3
+286	1	3
+5600	0	4
+6458	1	0
+4866328	0	102000
+1870126	0	257
+590080	18	6
+26953	0	1
+6737	4	0
+5946	0	1
+2319	4	0
+1641	1	1
+27	1	1
+1237	0	1
+2698	1	1
+140	1	1
+1689	2	0
+836	30	29
+5333	0	1
+509	0	1
+224	9	9
+4983	0	6
+4981	30	30
+6913	3	13
+1039	1	0
+11605	0	1
+22064	1	0
+16612	0	8
+902	0	1
+757	0	1
+84	46	46
+489	1	0
+10979	1	1
+18	1	1
+1517	0	1
+4576	0	1
+12558	0	4
+2726	1	0
+5291	0	2
+8706	1	0
+83	0	1
+406	7	0
+87	0	38
+5531	0	1
+23971	0	1
+7855	22	54
+4095	1	0
+803	5	5
+6382	0	6
+3546	28	0
+4264	2	0
+13194	6	6
+6463	0	1
+26075	1	1
+59	1	1
+10791	7	17
+707	1	0
+210	0	1
+1655	2	0
+5301	0	1
+1930	0	1
+14632	0	2
+1043	0	1
+3607	0	3
+312	1	0
+5953	0	2
+170	17	0
+489	1	0
+5260	28	0
+888	0	10
+2461	10	10
+237	0	2
+1716	1	3
+10694	4	0
+3754	0	1
+6173	1	0
+8017	2	1
+3594	4	0
+5439	1	0
+4137	14	0
+29	15	0
+6418	1	0
+1267	0	1
+723	6	0
+1080	0	2
+3878	1	0
+7682	1	1
+44	1	1
+3135	1	0
+174853	2	1
+2008	7	7
+5657	1	0
+6496	3	0
+89	5	0
+665	1	0
+954	1	1
+44	1	1
+375	8	7
+3317	2	0
+2753	0	1
+1863	3	0
+3228	0	1
+3571	49	45
+6488	2	0
+8451	172	172
+3797	16	0
+2103	1	0
+268	23	26
+7888	0	4
+701	0	4
+2402	6	0
+37	1	1
+2943	3	2
+8420	0	1
+932	324	0
+6726	0	1
+543	3	4
+4028	0	18
+88	4	0
+2999	0	1
+530	0	1
+1153	11	11
+919	2	0
+1174	17	0
+118	16	16
+2727	0	1
+543	1	0
+783	0	1
+1374	4	0
+8619	0	20
+281	44	44
+4364	50	51
+2856	1	0
+5399	1	0
+1506	0	1
+919	6	0
+7228	0	10
+3226	0	1
+435	0	1
+4463	132	0
+9760	1	0
+2034	0	6
+7656	0	1
+198212	132	0
+11700	5	0
+7647	0	1
+9062	0	4
+8778	2	0
+7014	0	1
+1613	2	0
+790	5	7
+7433	0	1
+6482	12	12
+6798	1	0
+1422	0	1
+3454	1	1
+43	1	1
+3097	2	0
+334	18	0
+1444	0	1
+2400	0	3
+3272	1	0
+9106	0	1
+1573	1	0
+4742	0	1
+3366	0	1
+5484	1	0
+2445	5	0
+5447	8	8
+2539	1	0
+1471	1	0
+238	1	1
+16	1	1
+288	5	5
+2995	2	0
+951	1	1
+35	1	1
+279	15	16
+3534	0	6
+3513	1	0
+163	1	0
+6173	1	0
+1074	0	1
+2818	0	1
+2868	1	0
+3796	0	1
+1118	167	1
+1278267	25	25
+10747175	217	0
+3504874	1053	0
+10844	11	13
+18805	0	1
+1960834	50000	126729
+3065	0	1
+3601036	8833	90008
+34292	0	1
+376	14	14
+1447	44	0
+3080	1	1
+43	1	1
+789	0	1
+11432680	50000	153000
+1902016	4098	0
+102	21	0
+3179	6	6
+877	1	1
+49	1	1
+296	1	0
+1375	1	1
+21	1	1
+607	5	5
+98	22	0
+6811	1	1
+17	11	0
+3804	0	1
+1356	1	1
+29	1	1
+297	0	1
+9543	2	0
+3131	4	0
+860	1	0
+27346	0	1
+7553	0	2
+2834	2	0
+394	0	4
+6322	44	44
+158	0	1
+405	8	11
+1128	0	7
+271	1	1
+21	28	0
+504	0	6
+1214	31	44
+384	3	0
+521	18	18
+392	0	11
+802	1	1
+25	2	3
+51	49	1
+49	1	1
+558	1	0
+351	0	1
+2779	13	13
+114398	82124	65008
+7795	1	0
+18	1	1
+4140	0	1
+28048	1	1
+32	1	1
+4630	0	1
+4573	0	3
+357	0	2
+4812	0	1
+14372	3	0
+203	1	0
+26257	0	1
+2734	2	0
+19262	5	5
+5022	1	0
+25471	1	0
+1114538	53	0
+82	0	126
+1416	16	16
+610	0	57
+482	0	1
+148	1	1
+24	1	1
+2322	1	1
+23	0	1
+719	16	0
+20	0	16
+105	9	9
+1277	1	0
+2498	1	0
+352	0	49
+50	50	0
+21	49	0
+28	49	0
+60	47	0
+17	97	0
+901	47	0
+272	14	1104
+279	1	0
+37	12	11
+65	32	0
+18	94	0
+60
+
+chain	3227650	chr17	81195210	+	81075742	81110122	chr17_random	2617613	+	864624	914847	755
+922	0	1
+430	0	1
+763	0	1
+19745	32	32
+637	36	15873
+186	0	1
+2389	0	1
+616	0	1
+1932	12	12
+6680
+
+chain	2732964	17	81195210	+	36295616	36336227	chr17	78774742	-	45363365	45403960	362
+666	1	1
+114	1	1
+1777	1	1
+22	1	1
+2481	3	0
+947	3	1
+994	1	1
+26	1	1
+5327	2	0
+95	13	13
+2424	0	1
+339	2	1
+288	1	0
+1180	8	8
+1145	2	4
+1144	1	0
+322	1	0
+28	1	0
+35	1	0
+1499	0	1
+1258	7	6
+1123	0	1
+269	5	4
+1850	18	19
+188	3	0
+403	1	1
+18	1	1
+3148	1	1
+160	1	1
+105	11	0
+573	10538	10545
+33
+
+chain	1501094	chr17	81195210	+	81048174	81075742	chr17_random	2617613	+	1430075	1457643	965
+53	10174	10174
+50	21	21
+49	28	28
+49	60	60
+47	17	17
+97	901	901
+47	680	680
+32	18	18
+94	60	60
+15091
+
+chain	1197294	chr17	81195210	+	21670280	21683085	chr17_random	2617613	-	711226	724030	995
+6335	1	0
+1486	0	2
+2024	2	0
+2957
+
+chain	653269	chr17	81195210	+	66064861	66073694	chr17_random	2617613	-	926391	957193	299
+3246	4346	26315
+1241
+
+chain	307142	chr17	81195210	+	79761820	81150656	chr17_random	2617613	+	2320255	2536424	170
+87	6	8
+1077	0	1
+77	0	1
+1009	0	1
+98	0	1
+35	0	1
+131	0	1
+288	0	1
+33	1	0
+225	0	1
+279	0	1
+110	0	1
+55	0	1
+107	0	1
+202	12	15
+111	0	1
+36	0	2
+25	0	1
+202	0	1
+95	0	1
+145	1	1
+21	0	1
+222	0	1
+41	0	1
+492	4	0
+594	0	1
+179	0	1
+412	0	1
+37	0	1
+13	0	1
+34	0	1
+76	37	38
+204	27	27
+204	1	3
+8	0	5
+23	0	1
+430	0	1
+145	0	1
+271	0	1
+222	0	1
+51	0	1
+17	0	1
+23	2	4
+385	0	1
+337	0	1
+374	0	1
+140	17	22
+297	0	1
+72	5	8
+193	0	1
+8	0	1
+28	0	1
+17	0	1
+17	0	1
+445	0	1
+169	0	1
+35	37	3
+425	0	1
+41	0	1
+37	0	1
+79	0	1
+100	0	1
+127	0	1
+422	0	1
+17	1	1
+284	1	3
+56	10	12
+650	0	1
+163	0	2
+6	0	1
+36	1	1
+519	0	1
+39	0	1
+78	0	1
+216	3	5
+66	0	1
+58	0	1
+68	0	1
+292	4	0
+46	2	0
+108	2	0
+23	114	0
+830	0	1
+136	43	43
+23	32	10
+63	64	65
+380	0	1
+22	1	1
+440	0	1
+66	1	1
+17	0	1
+171	3	5
+27	1	1
+130	10	13
+128	0	1
+418	0	1
+4	1	2
+37	0	1
+29	0	1
+27	0	1
+748	0	1
+251	0	1
+219	0	1
+111	0	1
+48	0	1
+325	0	1
+296	0	1
+383	0	1
+62	0	1
+244	0	2
+248	9	11
+180	0	1
+241	0	1
+40	1	3
+6	0	1
+19	0	1
+27	0	1
+166	0	1
+78	0	1
+165	0	1
+33	0	1
+9	0	1
+172	0	1
+261	0	1
+200	16	21
+121	0	1
+37	2	4
+74	0	1
+97	3	5
+11	0	1
+51	0	1
+642	0	1
+317	11	14
+138	1324229	151143
+4948	1	0
+1850	67	60
+3859	1	0
+456	5	4
+1605	21	21
+1281	13	7
+5085	0	456
+1548	1	1
+37	1	1
+2825	1	1
+64	1	1
+1075	1	0
+721	1	0
+5566	5	22
+1136	0	1
+2390	3	0
+1347	2	0
+4617
+
+chain	266741	chr17	81195210	+	81150656	81195210	chr17_random	2617613	-	1100691	1809734	427
+1871	0	662945
+298	0	1
+6514	2	2
+45	0	1
+6237	3	5
+1230	32	32
+347	0	1
+1941	14	14
+149	0	1
+25553	59	1621
+16	63	39
+180
+
+chain	215840	chr17	81195210	+	66068832	66109867	chr17_random	2617613	+	1644335	1685356	1023
+3394	37597	37583
+44
+
+chain	30167	17	81195210	+	44458173	44458487	chr2	242951149	-	34181426	34181740	4632506
+314
+
+chain	29586	17	81195210	+	36420504	36420817	chr7	158821424	-	10371995	10372309	4828537
+136	0	1
+177
+
+chain	20882	17	81195210	+	56914122	56914339	chrX	154913754	+	31643322	31643539	5151267
+217
+
+chain	16484	17	81195210	+	44491151	44521781	chr17	78774742	+	42064051	42094670	662
+44	30454	30443
+132
+
+chain	14999	17	81195210	+	44428451	44428612	chr17	78774742	+	42001706	42001867	887
+161
+
+chain	12695	17	81195210	+	44739444	44739576	chr17	78774742	+	41877181	41877313	13974721
+132
+
+chain	12494	17	81195210	+	19077136	19077299	chr17	78774742	-	59726399	59726562	431
+43	31	31
+89
+
+chain	7858	17	81195210	+	253568	254148	chr17	78774742	+	253365	253974	1160836
+37	486	515
+57
+
+chain	5202	17	81195210	+	79704633	79704687	chrY	57772954	-	54321400	54321454	32857515
+54
+
+chain	5149	17	81195210	+	36426505	36456524	chr17	78774742	-	35824084	35853324	896
+73	1	1
+45	29858	29079
+42
+
+chain	3754	17	81195210	+	60419213	60419252	chr8	146274826	-	11845696	11845735	33181261
+39
+
+chain	3753	17	81195210	+	44413461	44413510	chr17	78774742	-	18492830	18492879	715
+49
+
+chain	3637	chr17	81195210	+	79776689	79776727	chr17_random	2617613	+	2335092	2335130	5614693
+38
+
+chain	3637	chr17	81195210	+	79776651	79776689	chr17_random	2617613	+	2335092	2335130	5614694
+38
+
+chain	3636	chr17	81195210	+	79776613	79776651	chr17_random	2617613	+	2335130	2335168	7454076
+38
+
+chain	2637	17	81195210	+	252694	252723	chr17	78774742	+	252810	252839	1426666
+29
+
+chain	2581	17	81195210	+	81166856	81166888	chr1	247249719	+	441705	441737	997
+32
+
+chain	2427	chr17	81195210	+	79772596	79772621	chr17_random	2617613	+	2331168	2331193	24392944
+25
+
+chain	1872	17	81195210	+	79585571	79585619	chr11	134452384	+	72960908	72960956	2849402
+48
+
+chain	790	chr17	81195210	+	36328756	36331384	chr17_random	2617613	-	1242589	1245215	133
+46	2513	2511
+69
+
+chain	170	chr17	81195210	+	34725848	34725887	chr17_random	2617613	+	1051433	1051472	428
+39
+
+chain	94559897	chr17_ctg5_hap1	1680828	+	188271	1499222	chr17	78774742	-	36776984	37845687	55
+188	30	30
+348	14	15
+235	24	24
+194	3	0
+334	40	40
+270	54	54
+61	87	84
+948	4	3
+1658	2	0
+1730	0	2
+285	0	1
+2885	1	1
+38	1	1
+2933	0	1
+1942	10	0
+375	0	1
+5094	0	1
+814	1	1
+18	1	1
+4676	8	0
+578	10	7
+467	0	1
+892	1	0
+479	48	48
+132	0	6
+61	13	15
+66	38	38
+1901	35	35
+862	7	0
+3895	1	0
+740	44	44
+313	7	6
+4916	4	4
+507	0	1
+2214	1	1
+25	0	3
+106	2	0
+40	1	1
+146	1	1
+30	1	1
+63	0	1
+192	5	5
+3242	0	2
+385	33	33
+972	12	0
+93	1	1
+3332	2	2
+71	1	1
+57	1	1
+149	0	2
+91	1	1
+219	14	14
+606	1	1
+53	1	1
+1068	0	12
+3191	29	29
+7028	1	0
+478	1	0
+2064	0	1
+408	17	21
+675	1	1
+17	1	0
+4	1	1
+3445	0	1
+158	0	2
+312	0	14
+1801	0	1
+1424	4	0
+1894	2	0
+364	6	6
+54	2	0
+47	1	1
+1105	10	1
+3088	0	1
+1176	6	0
+4141	1	1
+24	0	1
+169	71	71
+1596	1	1
+37	1	1
+2758	5	0
+2986	1	1
+20	1	1
+206	4	0
+11154	0	17
+583	0	8
+1703	0	10
+1675	1	0
+392	1	0
+6851	37	37
+2872	132	0
+446	9	0
+3437	5	5
+995	0	2
+898	1	1
+18	1	1
+128	0	1
+2151	2	0
+6413	1	1
+48	1	1
+786	0	1
+939	0	1
+258	0	4
+1247	2	0
+4742	0	1
+3520	54	51
+1220	1	1
+30	1	1
+638	1	0
+2474	1	1
+42	1	1
+266	0	16
+106	1	1
+19	1	1
+3806	328	0
+1161	1	0
+4896	0	1
+779	0	2
+543	1	0
+4979	11	11
+1670	1	0
+889	3	0
+2126	2	0
+87	0	18
+193	1	0
+3840	12	0
+3234	4	0
+2802	0	1
+873	1	0
+1288	1	5
+2202	1	1
+21	1	0
+1366	0	1
+4830	4	0
+48	1	1
+2894	1	1
+7	14	0
+43	0	4
+1003	1	1
+28	1	1
+102	3	0
+370	50	50
+830	1	3
+674	3	7
+2759	2	0
+4559	14	12
+862	1	0
+245	49	49
+1367	0	3
+428	13	41
+77	0	9
+701	1	0
+528	1	1
+31	1	1
+1397	0	2
+832	1	1
+34	2	0
+404	1	0
+142	1	1
+30	1	1
+272	2	0
+783	0	2
+4039	1	0
+449	8	0
+2647	1	0
+1730	7	1
+38	80	0
+160	5	0
+492	0	12
+1920	1	1
+117	1	1
+350	1	1
+38	1	1
+279	1	1
+40	1	1
+1367	4	0
+427	35	35
+141	46	46
+399	1	0
+1786	35	35
+697	0	1
+1104	20	20
+290	28	28
+1774	0	5
+1339	5	0
+527	1	0
+312	62	62
+199	1	1
+239	42	42
+629	1	1
+41	1	1
+298	3	3
+26	1	1
+642	1	1
+52	1	1
+206	8	0
+1930	0	1
+806	19	12
+578	10	7
+375	1	1
+44	1	1
+939	2	0
+679	10	0
+56	0	2
+73	13	13
+556	1	1
+18	1	1
+1386	1	1
+35	281	0
+106	1	1
+435	13	0
+686	2	0
+1401	0	8
+1799	1	0
+1566	0	3
+692	21	21
+1368	5	5
+150	28	28
+53	6	11
+54	50	50
+129	4	4
+550	15	0
+160	13	13
+1640	1	0
+170	31	31
+1087	124	123
+249	12	12
+407	1	1
+18	1	1
+637	13	13
+450	1	1
+30	1	1
+100	1	1
+37	1	1
+407	0	2
+2327	8	1
+107	1	1
+37	1	1
+885	1	1
+20	1	1
+134	18	18
+168	1	0
+161	6	6
+497	1	1
+16	1	1
+2755	29	29
+102	242	244
+58	8	8
+153	14	14
+711	41	41
+76	35	35
+287	93	93
+472	14	21
+608	7	8
+171	34873	0
+117	7	7
+68	10	0
+31	1	1
+95	11	11
+267	1	1
+19	1	1
+494	1	1
+26	1	1
+135	1	0
+302	1	1
+26	1	1
+349	0	1
+37	1	1
+254	1	1
+24	1	1
+550	1	0
+170	1	1
+38	1	1
+100	1	1
+31	0	1
+305	6	8
+370	0	3
+162	7	0
+39	4	4
+112	6	6
+318	1	1
+49	1	1
+135	1	1
+34	1	1
+129	1	1
+49	1	1
+620	0	1
+98	1	1
+43	1	1
+252	1	1
+37	1	1
+824	5	5
+131	9	10
+247	1	1
+20	1	1
+303	1	0
+668	1	1
+45	1	1
+316	14	14
+657	1	1
+93	1	1
+290	0	3
+148	1	1
+29	5	5
+74	1	1
+40	1	1
+1516	1	1
+57	1	1
+132	3	0
+178	1	1
+131	1	1
+127	1	1
+103	0	1
+61	1	1
+460	5	7
+90	1	1
+22	1	1
+87	1	1
+44	1	1
+85	1	3
+767	0	7
+60	1	1
+79	1	1
+31	1	1
+258	1	1
+26	0	1
+11	2	2
+140	1	1
+31	1	1
+110	1	0
+12	9	0
+776	8	8
+50	1	0
+445	1	1
+34	1	1
+278	15	15
+125	1	0
+635	18	19
+183	0	1
+75	10	10
+200	19	21
+832	14	14
+2247	6	0
+318	0	2
+180	10	0
+167	1	1
+43	1	1
+60	1	1
+43	1	1
+268	0	11
+1220	1	1
+46	5	5
+1001	16	16
+218	7	7
+142	17	0
+74	1	1
+130	1	1
+30	2	0
+588	1	1
+83	2	2
+58	25	25
+65	50	50
+873	23	23
+277	21	20
+237	3	0
+66	0	51
+145	0	1
+133	1	1
+23	1	1
+1087	3	2
+295	4	5
+57	10	8
+347	1	1
+18	1	1
+350	3	5
+259	0	1
+771	3	4
+85	1	1
+62	8	8
+224	1	1
+40	1	1
+50	0	3
+137	1	1
+199	3	3
+21	1	1
+272	0	10
+66	12	0
+27	1	1
+138	6	5
+762	1	1
+20	1	1
+324	9	9
+71	0	4
+174	5	12
+237	6	6
+57	1	6
+21	1	1
+156	0	2
+89	1	1
+140	1	1
+69	11	0
+407	0	2
+20	1	1
+131	0	2
+162	1	1
+29	1	1
+65	7	7
+1199	1	1
+68	1	1
+75	12	12
+78	3	3
+37	1	1
+499	1	1
+44	1	0
+397	1	1
+116	1	1
+147	1	0
+286	4	0
+122	31	0
+436	1	1
+27	1	1
+137	11	0
+448	40	0
+174	5	5
+148	1	0
+42	40	0
+506	850	23
+509	1	1
+61	1	1
+113	1	1
+83	1	0
+90	1	1
+229	0	1
+366	0	6
+625	0	1
+160	1	1
+43	1	1
+174	1	1
+53	1	1
+129	10	10
+205	1	1
+18	1	1
+386	1	1
+36	1	1
+775	1	1
+49	0	2
+118	10	10
+238	4	0
+801	0	5
+164	73	73
+1003	22	15
+181	1	1
+62	1	1
+1006	1	1
+25	1	1
+361	1	1
+76	21	0
+386	9	0
+224	25	34
+1276	0	4
+157	4	4
+450	1	1
+15	1	0
+36	1	1
+402	15	0
+1572	8	9
+272	3	0
+319	9	9
+673	0	724
+177	23	26
+230	2	0
+107	1	1
+80	99	99
+319	1	0
+711	0	1
+18	1	1
+674	3	0
+826	0	2
+503	1	1
+25	32	0
+42	1	1
+67	1	0
+395	19	14
+328	1	1
+69	1	1
+520	1	1
+31	1	1
+1063	1	1
+67	2	2
+55	4	0
+477	4	0
+69	0	1
+807	4	3
+26	1	1
+400	2	0
+707	5	0
+41	1	1
+200	1	1
+33	1	1
+744	1	1
+25	1	1
+224	2	0
+121	9	4
+44	1	1
+266	78	94
+522	0	1
+81	1	1
+3286	0	1
+341	1	1
+17	2	1
+445	1	1
+23	1	1
+1029	2	0
+169	1	1
+30	1	1
+577	1	0
+754	2	2
+43	1	1
+170	20	14
+365	1	1
+88	0	1
+1312	0	1
+354	1	4
+526	4	2
+1931	3	0
+650	17	17
+454	1	1
+59	2	3
+167	3	0
+1448	13	13
+69	1	1
+48	1	1
+398	1	1
+89	5	0
+33	1	1
+422	1	1
+39	0	1
+250	86	15
+1631	0	1
+20	1	1
+69	1	1
+38	1	1
+104	0	2
+30	1	1
+420	1	1
+70	1	0
+497	1	0
+68	0	14
+1402	1	1
+28	1	1
+385	4	0
+42	1	1
+245	1	1
+31	2	1
+1110	1	1
+44	1	1
+1784	1	1
+42	1	1
+194	0	1
+181	0	4
+278	14	13
+800	1	0
+160	0	2
+259	1	1
+48	1	1
+336	5	0
+49	12	0
+814	1	1
+39	1	1
+144	4	0
+618	0	4
+159	0	3
+30	1	1
+443	2	0
+140	1	1
+49	1	1
+510	1	1
+22	1	1
+1186	1	1
+45	1	1
+2488	9	0
+226	12	8
+769	1	1
+36	3	0
+1785	1	1
+40	1	1
+570	5	0
+122	7	7
+181	11	11
+539	0	8
+1090	7	7
+128	0	1
+918	0	1
+314	43	43
+173	26	25
+374	0	1
+267	43	49
+69	16	15
+531	16	16
+179	0	6
+604	2	0
+646	28	35
+276	0	1
+1116	21	21
+257	1	0
+165	56	57
+85	41	41
+939	52	52
+134	6	6
+966	5	0
+1657	1	0
+142	22	23
+301	14	0
+280	35	35
+304	3	0
+1345	4	0
+219	1	1
+93	1	1
+646	1	1
+70	1	1
+115	1	1
+25	0	2
+6	1	1
+876	0	1
+750	1	0
+1106	1	1
+44	1	1
+1136	0	1
+2705	1	1
+29	1	1
+474	1	0
+24	1	1
+517	18	17
+283	45	35
+190	6	3
+714	102	102
+1046	0	2
+2521	29	29
+123	1	0
+171	0	8
+504	5	6
+2380	0	1
+1479	53	42
+159	5	5
+248	1	1
+34	1	1
+643	2	0
+586	0	4
+1216	1	1
+30	1	1
+1308	1	1
+25	1	1
+244	0	4
+1092	11	11
+297	0	4
+776	22	22
+62	1	0
+222	0	1
+38	1	1
+808	0	7
+45	1	1
+42	2	0
+313	5	0
+1028	2	3
+366	0	2
+298	41	355
+1457	37	37
+356	49	49
+849	140	128
+155	0	4
+92	6	6
+2333	1	0
+546	1	0
+612	68	68
+259	1	0
+304	3	0
+1246	1	0
+351	22	21
+1110	14	14
+364	0	3
+349	1	1
+39	1	1
+76	0	8
+152	9	0
+283	1	0
+117	1	2
+304	1	0
+1958	19	0
+278	1	1
+109	1	1
+1942	1	1
+31	2	0
+13	1	1
+312	18	0
+151	7	0
+62	1	1
+694	1	1
+18	1	1
+163	1	1
+17	1	0
+1103	2	0
+218	1	0
+21	1	1
+372	11	11
+434	3	4
+440	4	0
+45	1	0
+402	1	1
+46	1	1
+757	1	1
+43	1	1
+96	27	81
+499	1	1
+21	1	1
+184	14	14
+307	15	16
+1265	1	1
+62	1	1
+1051	1	0
+1157	1	1
+28	2	0
+349	3	0
+606	1	1
+22	1	1
+107	0	1
+36	1	1
+499	1	1
+27	1	1
+505	0	1
+1698	6	0
+38	1	1
+924	1	1
+33	1	1
+108	0	2
+196	1	1
+25	1	0
+24	1	1
+824	6	0
+725	0	1
+917	17	0
+185	1	1
+51	4	4
+93	0	1
+351	1	1
+34	1	1
+608	10	10
+82	2	0
+27	1	1
+2343	1	1
+48	1	1
+188	9	9
+623	4	3
+603	0	6
+11	1	1
+379	1	1
+52	1	1
+157	37	20
+879	51	58
+229	14	2
+83	1	1
+70	1	0
+1849	1	1
+42	1	1
+961	1	1
+22	1	1
+219	1	1
+25	1	1
+551	0	3
+26	1	7
+250	1	1
+44	1	1
+1028	9	2
+471	1	1
+31	0	1
+574	0	323
+192	1	1
+44	1	1
+1934	168	168
+186	1	0
+197	25	0
+161	1	0
+15	6	0
+806	1	1
+18	1	1
+184	1	0
+86	1	1
+16	1	1
+183	0	1
+641	12	12
+687	0	2
+735	2	0
+45	0	6
+308	11	11
+153	1	1
+23	1	1
+143	1	1
+59	1	1
+178	28	0
+899	0	3
+1351	2	0
+168	3	0
+407	1	0
+290	2	1
+227	1	1
+48	1	1
+704	1	1
+48	1	1
+866	93	93
+536	1	5
+1481	8	11
+180	16	16
+88	6	0
+249	0	44
+37	1	1
+294	1	1
+32	0	20
+1368	1	1
+93	1	1
+1638	11	11
+303	0	1
+55	1	1
+24	1	1
+1188	1	0
+227	2	2
+45	3	0
+205	0	4
+34	0	1
+159	1	1
+24	1	1
+398	0	1
+1259	16	16
+64	2336	0
+59	1	1
+44	0	3
+25	1	1
+209	1	1
+18	1	1
+348	1	1
+30	1	1
+413	27	0
+53	1	1
+23	2	0
+25	0	4
+532	0	12
+184	1	0
+278	1	1
+29	1	1
+1186	1	1
+15	1	1
+300	12	12
+570	1	1
+43	1	1
+183	5	6
+134	1	0
+508	1	1
+30	1	1
+1074	1	1
+24	1	1
+162	8	8
+1046	1	1
+20	1	1
+817	0	3
+1128	1	1
+41	1	1
+166	27	27
+667	15	15
+967	2	0
+10	2	0
+261	1	0
+792	1	8
+153	0	3
+1788	13	22
+1089	1	0
+994	2	0
+368	0	18
+207	1	1
+39	1	1
+332	0	3
+298	5	3
+68	1	1
+44	1	1
+958	1	1
+41	1	1
+1009	0	24
+12	1	0
+118	0	1
+171	16	16
+229	8	8
+233	21	21
+71	1	1
+38	1	1
+185	1	0
+544	1	1
+64	2	0
+614	1	1
+62	1	1
+536	1	1
+143	1	1
+679	0	5
+169	0	3
+597	1	0
+654	1	0
+1270	0	11
+174	0	2
+606	1	1
+59	2	0
+153	3	4
+1186	10	11
+92	1	4
+956	4	0
+302	0	9
+199	1	1
+31	1	1
+878	31	0
+452	10	10
+988	20	15
+1054	0	1
+131	0	4
+652	2	0
+37	1	1
+142	1	1
+36	0	5
+29	0	8
+4136	1	1
+32	1	1
+701	11	11
+258	0	1
+133	7	7
+170	1	0
+372	0	1
+26	4	3
+31	1	1
+131	1	0
+29	1	0
+2657	10	10
+2046	7	0
+870	1	0
+101	16	18
+163	0	1
+526	4	3
+281	0	3
+1907	0	1
+30	0	3
+164	0	3
+132	0	1
+352	1	0
+455	1	0
+726	0	2
+107	1	1
+33	1	1
+156	2	0
+576	1	1
+16	1	0
+76	1	0
+862	11	11
+1049	1	0
+47	1	1
+69	0	3
+607	1	1
+46	1	1
+1700	0	1
+825	13	13
+813	0	1
+213	1	0
+46	1	1
+630	1	0
+683	51	52
+118	1	1
+28	1	1
+1162	1	1
+66	0	3
+472	14	0
+16	1	1
+134	1	1
+119	1	1
+1129	5	5
+149	1	1
+57	1	1
+918	1	1
+36	1	1
+752	12	12
+1962	0	238
+2372	0	15
+175	7	7
+833	1	1
+25	1	1
+315	1	1
+16	1	0
+436	15	15
+67	15	15
+1207	6	5
+732	6	0
+79	1	1
+53	1	1
+1521	5	6
+140	1	0
+3576	12	12
+479	1	1
+37	1	1
+1518	1	1
+77	1	1
+102	1	1
+26	1	1
+812	1	1
+23	1	1
+1740	0	1
+1077	1	1
+17	1	1
+885	6	6
+441	17	17
+284	1	1
+37	1	1
+107	1	1
+17	1	1
+335	1	1
+50	1	1
+120	8	7
+588	0	8
+1512	38	1
+550	45	45
+376	1	1
+63	1	1
+2111	0	1
+574	14	14
+1622	3	1
+683	23	26
+673	1	1
+45	12	0
+98	3	4
+93	20	0
+2130	10	10
+941	1	1
+24	1	1
+1362	2	0
+1696	1	1
+22	2	2
+737	1	1
+26	1	1
+922	1	1
+32	1	1
+923	7	8
+432	0	1
+152	1	1
+26	1	1
+841	0	4
+441	0	103
+1348	10	11
+589	1	1
+44	1	1
+775	8	8
+1051	0	2
+152	13	13
+572	6	6
+543	1	1
+45	1	1
+663	7	7
+802	1	0
+888	1	1
+44	1	1
+210	1	0
+111	1	1
+34	1	1
+459	0	1
+323	1	0
+1116	1	0
+27	1	1
+142	1	1
+21	1	1
+784	1	1
+37	0	4
+40	1	1
+813	1	3
+371	1	1
+25	1	1
+257	1	1
+88	1	1
+276	47	47
+192	5	9
+445	1	1
+19	1	1
+66	8	8
+205	1	1
+79	11	0
+106	1	1
+122	1	1
+2478	0	6
+89	1	1
+47	1	0
+68	1	1
+680	0	4
+1040	0	1
+424	1	1
+33	1	1
+170	0	1
+456	1	1
+66	1	1
+820	18	18
+146	11	11
+642	2	0
+28	1	1
+242	1	0
+50	0	3
+7	1	1
+301	13	13
+126	1	1
+40	1	1
+98	0	2
+202	11	11
+564	23	0
+145	10	7
+1202	1	1
+103	1	1
+459	1	1
+24	1	1
+298	1	1
+44	1	1
+1384	1	1
+31	1	1
+569	1	1
+68	1	1
+535	5	45
+575	1	1
+30	1	1
+1885	1	0
+426	3	0
+19	1	1
+136	1	0
+556	1	1
+17	1	1
+463	6	8
+803	35	35
+170	1	0
+28	1	1
+454	9	9
+450	1	1
+34	1	1
+728	12	13
+1023	0	3
+204	1	1
+33	1	1
+322	1	1
+35	5	0
+147	1	1
+6	1	0
+107	1	1
+442	1	1
+44	1	1
+407	1	0
+1683	1	5
+53	1	1
+1265	1	0
+209	1	1
+28	1	1
+92	1	1
+44	1	1
+671	1	1
+42	0	2
+39	1	1
+74	1	1
+67	1	1
+854	0	30
+676	2	0
+33	0	1
+145	1	1
+48	1	1
+261	3	0
+166	1	1
+24	0	1
+311	1	1
+76	1	1
+893	1	1
+39	1	1
+65	1	0
+1321	1	1
+31	1	1
+316	0	14
+78	9	9
+2264	1	1
+20	1	1
+777	1	2
+274	0	1
+1285	0	11
+500	1	1
+24	1	1
+107	0	3
+77	1	1
+76	1	1
+1414	5	5
+54	37	0
+421	8	8
+150	1	1
+71	1	1
+128	0	1
+514	75	0
+116	1	0
+201	1	1
+17	0	1
+1181	1	1
+30	1	1
+131	12	12
+386	0	1
+351	3	3
+6	4	0
+14	0	1
+48	1	1
+1034	0	4
+789	2	0
+76	1	1
+29	1	1
+691	1	1
+65	1	1
+1723	4	4
+22	1	1
+2576	1	3
+235	1	1
+35	1	1
+52	70	144
+15	1	3
+5	1	0
+51	1	3
+6	3	0
+6	1	0
+4	1	0
+8	0	2
+15	1	0
+8	2	1
+20	1	0
+7	130	13
+22	2	0
+22	2	0
+17	43	281
+23	6	0
+1593	1	1
+35	1	1
+171	0	1
+670	1	1
+20	1	1
+283	1	1
+24	1	1
+448	1	1
+18	1	1
+78	11	0
+46	1	1
+652	1	1
+30	1	1
+333	1	1
+56	1	1
+1209	22	44
+88	1	1
+21	1	1
+908	7	10
+114	26	26
+791	6	6
+286	1	1
+40	1	1
+623	4	0
+430	0	1
+423	8	8
+115	1	1
+23	1	1
+215	11	0
+27	0	5
+797	4	0
+95	15	15
+148	1	1
+141	2	0
+60	1	1
+692	1	0
+91	1	1
+31	1	1
+116	1	1
+24	1	1
+56	1	1
+99	3	0
+101	8	0
+273	1	1
+47	1	1
+1276	14	13
+169	1	1
+40	3	0
+119	1	1
+45	1	1
+466	1	1
+21	1	1
+572	8	8
+247	0	1
+290	0	1
+573	1	1
+27	1	1
+333	47	47
+2439	23	25
+654	1	1
+46	1	1
+78	8	8
+569	1	1
+57	1	1
+666	0	1
+502	1	1
+20	1	1
+347	9	9
+358	0	2
+13	1	1
+148	2	0
+134	1	1
+809	1	1
+47	1	1
+442	1	1
+43	1	1
+308	1	1
+54	1	1
+48	0	2
+152	5	0
+1137	1	1
+27	0	11
+575	1	0
+189	18	18
+490	25	25
+165	1	1
+26	1	1
+241	0	6
+75	1	1
+162	1	1
+1156	0	7
+248	0	4
+972	8	7
+177	0	1
+50	1	1
+1385	1	1
+30	1	1
+1048	1	1
+44	1	17
+690	6	7
+295	1	1
+36	1	1
+519	1	1
+26	1	1
+352	8	8
+204	1	1
+38	1	1
+580	7	7
+888	54	54
+183	18	18
+2465	16	16
+1454	10	10
+352	1	1
+49	1	1
+176	1	1
+32	11	11
+1717	1	1
+37	1	1
+127	1	1
+44	1	1
+275	1	1
+21	1	1
+349	9	9
+1977	1	1
+78	0	1
+8	0	1
+144	0	1
+335	46	46
+79	0	6
+10	1	1
+137	12	0
+99	1	1
+44	5	13
+31	1	1
+416	0	1
+177	0	6
+19	1	1
+372	2	2
+55	1	1
+256	0	6
+313	1	1
+43	1	1
+79	1	1
+20	1	1
+120	1	1
+38	0	8
+880	1	1
+24	1	1
+921	1	1
+40	1	1
+1358	0	4
+56	1	1
+1282	1	1
+34	1	1
+262	1	1
+43	1	1
+158	1	1
+33	1	1
+637	0	4
+1310	1	1
+26	1	1
+544	32	32
+496	1	1
+48	1	1
+3097	2	0
+145	1	1
+32	1	1
+152	0	3
+1117	1	1
+31	6	6
+416	1	1
+37	1	1
+293	0	14
+66	1	1
+48	1	1
+371	1	1
+41	1	1
+639	1	1
+49	1	1
+2092	10	13
+381	1	1
+39	5	5
+995	15	15
+165	0	12
+536	1	1
+43	1	1
+295	1	1
+35	1	1
+171	9	8
+831	20	20
+1980	12	0
+31	1	1
+389	1	1
+32	1	1
+414	20	0
+97	0	1
+835	6	0
+4305	1	1
+37	1	1
+191	1	1
+16	1	1
+227	1	1
+61	1	1
+257	1	1
+35	1	1
+946	1	1
+29	1	1
+710	1	1
+56	1	1
+534	2	0
+439	1	1
+58	1	1
+69	3	3
+43	1	1
+193	1	1
+15	1	1
+1032	1	4
+884	1	1
+30	1	1
+202	1	1
+43	1	1
+171	0	4
+163	0	1
+128	1	1
+43	1	1
+52	1	1
+20	1	1
+818	1	1
+45	1	1
+54	1	1
+42	1	1
+122	1	1
+28	1	1
+329	1	0
+163	1	1
+17	1	1
+442	1	1
+61	1	0
+695	0	1
+13	1	7
+54	1	1
+553	0	14
+360	5	5
+11641	3	7
+7822	1	0
+4105	0	8
+5193	0	1
+516	1	0
+3576	3	0
+825	1	1
+40	1	1
+738	1	1
+18	1	1
+989	0	5
+579	1	1
+19	1	1
+337	1	1
+42	55	0
+726	1	1
+99	1	2
+32	1	1
+932	1	1
+33	1	1
+234	33	33
+1101	1	1
+23	1	1
+345	0	1
+30	1	1
+111	17	17
+1395	1	0
+243	1	1
+29	4	5
+881	2	0
+465	0	1
+165	1	1
+87	1	1
+565	1	1
+10	1	1
+102	9	10
+176	1	1
+48	1	1
+499	1	1
+43	1	1
+263	0	8
+427	2	0
+75	1	1
+2053	1	1
+63	1	1
+744	32	32
+1706	1	1
+31	1	1
+829	12	0
+258	0	2
+433	1	1
+70	1	1
+137	2	0
+45	1	1
+664	11	11
+844	0	1
+440	1	1
+41	1	1
+760	1	6
+39	15	0
+757	1	1
+23	1	1
+137	1	1
+32	1	1
+246	9	9
+549	3	0
+1242	6	1
+200	1	0
+2306	1	1
+29	1	1
+197	2	0
+24	1	1
+1224	0	124
+61	1	1
+64	1	1
+3131	1	1
+116	1	1
+146	1	1
+34	1	1
+51	0	1
+805	1	1
+45	1	1
+579	15	15
+134	9	9
+1033	1	5
+147	1	1
+33	1	1
+118	29	29
+311	10	10
+1107	4	4
+3165	0	1
+122	1	1
+64	0	2
+29	1	1
+437	1	1
+39	1	1
+215	1	1
+78	1	1
+1953	3	3
+49	1	1
+745	1	1
+38	1	1
+881	0	4
+562	0	1
+956	1	1
+44	1	1
+685	1	1
+84	1	1
+380	1	1
+40	1	1
+182	0	4
+40	1	1
+877	13	13
+157	1	1
+50	1	1
+1282	0	1
+1612	17	37
+772	1	1
+70	1	1
+1866	0	2
+1406	16	15
+1398	1	0
+1112	1	1
+77	1	1
+1374	7	7
+751	5	5
+14	1	1
+239	6	6
+12	1	1
+189	0	1
+38	1	1
+144	1	1
+40	1	1
+1200	0	1
+758	0	1
+338	18	0
+15	10	0
+187	1	1
+90	1	1
+76	0	6
+611	6	131
+44	1	1
+221	5	0
+460	64	64
+488	15	15
+262	1	1
+45	1	1
+848	4	0
+75	8	8
+52	1	1
+31	1	1
+226	10	10
+437	1	1
+67	1	1
+115	1	1
+62	1	1
+60	13	13
+721	2	0
+164	1	1
+44	1	1
+395	1	1
+33	1	1
+260	13	13
+283	10	18
+600	1	1
+28	1	1
+100	18	18
+229	1	1
+47	1	1
+1672	1	1
+21	1	1
+1571	12	9
+101	1	1
+58	1	1
+706	11	11
+627	1	1
+16	1	1
+864	16	16
+200	1	1
+36	1	1
+676	1	1
+51	5	0
+2069	1	1
+32	1	1
+584	7	0
+271	1	1
+15	1	1
+435	0	1
+312	1	1
+38	0	3
+80	1	1
+32	0	12
+91	1	1
+34	1	1
+131	1	1
+35	1	1
+754	1	1
+44	2	2
+132	2	9
+174	3	1
+53	1	1
+213	2	0
+937	0	3
+720	1	1
+48	0	2
+32	12	0
+155	38	42
+692	9	2
+399	1	1
+54	0	1
+2625	1	1
+26	1	1
+584	0	5
+505	1	1
+43	1	1
+549	1	1
+23	1	1
+69	8	9
+123	1	1
+33	1	1
+651	1	1
+41	1	1
+141	4	4
+408	1	1
+30	1	1
+690	2	1
+78	4	4
+2106	8	4
+245	0	16
+802	1	1
+38	1	1
+607	1	1
+56	1	1
+358	0	1
+192	1	1
+45	1	1
+373	1	1
+82	1	1
+720	0	1
+161	1	1
+21	1	1
+187	7	6
+184	8	8
+760	6	6
+527	14	14
+94	4	4
+44	1	1
+455	7	0
+48	1	1
+89	1	1
+27	0	4
+38	1	1
+1571	1	1
+47	1	1
+81	1	1
+35	1	1
+161	4	0
+1244	0	2
+82	1	1
+67	0	4
+202	8	8
+351	9	9
+2130	1	0
+82	11	0
+397	0	1
+37	1	0
+315	1	1
+22	1	1
+1212	1	1
+60	1	1
+1847	1	1
+54	1	1
+362	7	7
+1065	3	0
+422	0	1
+3143	1	1
+33	1	1
+552	0	1
+822	1	0
+493	0	4
+26	1	1
+2435	1	1
+48	1	1
+3350	1	1
+17	1	1
+953	86	87
+509	0	1
+1811	1	1
+58	1	1
+1200	1	1
+55	4	0
+863	0	1
+284	1	1
+47	1	1
+2795	15	15
+2326	31	30
+2510	0	8
+1829	1	1
+40	1	1
+3584	58	90
+1937	29	28
+3805	14	14
+477	1	1
+25	1	1
+529	0	1
+918	1	2
+461	5	5
+102	9	10
+3603	18	18
+790	1	0
+797	881	2
+226	10	10
+52	4	4
+40	1	1
+128	5	5
+28	1	1
+50	14	11
+53	2	1
+1451	2	1
+119	1	1
+68	1	1
+164	0	2
+1257	1	1
+12	1	0
+42	1	1
+882	1	1
+47	1	1
+274	16	16
+82	1	1
+63	1	1
+100	11	11
+581	0	1
+60	1	1
+464	1	1
+29	1	0
+5	13	0
+23	1	1
+286	1	1
+38	0	2
+17	0	5
+108	6	0
+73	7	6
+105	1	1
+72	1	1
+115	1	1
+37	1	1
+86	1	1
+34	1	1
+143	28	25
+572	4	1
+114	3	0
+134	57	56
+836	0	1
+39	1	1
+1284	0	3
+858	2	1
+42	1	1
+795	1	0
+105	1	0
+343	3	0
+1040	0	3
+548	1	1
+67	1	1
+206	6	14
+830	0	1
+1490	10	10
+139	1	1
+29	0	1
+236	6	4
+217	1	1
+48	1	1
+578	0	1
+165	1	0
+59	9	9
+113	1	2
+294	0	3
+41	0	2
+126	1	1
+29	1	1
+393	7	7
+791	1	1
+51	1	0
+30	1	1
+110	21	11
+57	1	1
+64	1	1
+68	3	3
+58	1	1
+52	9	9
+63	1	1
+85	1	1
+72	1	1
+32	1	1
+315	13	13
+138	1	0
+1106	8	4
+923	12	12
+1310	1	0
+20	1	1
+307	18	15
+995	9	9
+71	1	1
+71	1	1
+85	6	1
+202	1	1
+57	1	1
+483	1	1
+57	1	2
+185	1	1
+17	1	1
+129	1	1
+34	0	2
+179	8	10
+175	1	1
+102	1	1
+154	220	220
+71	1	1
+62	1	1
+60	1	1
+164	7	7
+126	1	1
+19	1	1
+118	13	13
+126	1	1
+53	1	1
+67	4	4
+42	7	7
+54	1	1
+51	1	1
+139	13	14
+96	1	1
+19	1	1
+163	1	1
+33	1	1
+309	0	18
+38	1	1
+318	3	0
+70	4	0
+203	3	3
+30	1	1
+606	1	1
+22	1	0
+209	0	1
+520	1	0
+415	1	1
+51	1	1
+367	5	1
+16	0	8
+137	6	3
+290	0	4
+157	1	1
+79	1	1
+275	1	1
+14	4	0
+69	1	1
+215	1	1
+7	1	0
+7	1	4
+33	1	1
+169	1	1
+101	1	1
+78	1	1
+41	3	3
+364	0	2
+577	34	29
+268	60	60
+60	47	47
+133	8	8
+68	2	0
+172	2	3
+162	30	30
+186	3	8
+235	58	58
+64	16	12
+138	24	17
+112	246	235
+51	56	56
+146	18	18
+206	49	49
+267	18	18
+152	1	1
+18	1	1
+63	13	1
+235	6	5
+209	1	1
+24	4	0
+53	1	1
+73	29409	0
+126	1	1
+85	1	1
+76	3	3
+159	1	0
+29	11	11
+72	8	8
+496	9	9
+202	1	1
+90	1	1
+692	1	1
+27	1	1
+111	0	10
+89	1	1
+33	1	1
+153	3268	0
+205	0	3
+50	3	0
+605	6	6
+59	16	16
+136	1	1
+28	1	1
+417	1	1
+17	1	1
+70	10	10
+259	1	1
+37	0	1
+352	1	1
+40	1	1
+814	1	1
+80	1	1
+125	11	11
+137	1	1
+82	1	1
+408	1	1
+56	1	1
+367	1	0
+26	1	1
+390	185277	11600
+75	2	0
+81	1	1
+175	1	1
+23	1	1
+56	1	1
+37	3	0
+55	1	1
+248	3	0
+74	2	0
+139	1	1
+26	1	1
+131	1	1
+32	5	9
+246	3	5
+53	0	4
+22	5	0
+71	0	1
+255	1	1
+189	1	1
+121	1	1
+149	1	1
+65	1	1
+322	1	1
+36	17	5
+27	4	0
+39	1	1
+346	15	1
+48	0	1
+148	1	1
+57	1	1
+38	1	1
+653	1	0
+213	1	1
+35	1	1
+60	1	1
+72	1	1
+71	6	6
+76	1	1
+73	5	5
+114	1	1
+92	1	1
+145	1	1
+108	1	1
+54	0	2
+82	11	11
+303	0	4
+149	23	23
+57	1	1
+57	1	1
+485	1	1
+64	1	1
+112	1	1
+19	1	1
+226	1	1
+70	0	1
+83	1	1
+60	1	0
+28	1	1
+1629	34	1
+5621	0	12
+37	1	1
+1691	14	14
+151	10	10
+58	1	1
+91	0	2
+149	1	1
+57	1	1
+72	1	1
+932	1	1
+21	1	1
+732	1	1
+24	1	1
+438	1	1
+17	1	1
+1100	146	145
+189	18	18
+1079	1	1
+37	1	1
+69	10	1
+241	1	1
+23	1	1
+247	1	1
+48	1	1
+3441	1	1
+18	1	1
+491	0	1
+250	12	8
+108	1	1
+37	1	2
+339	1	1
+36	1	1
+1289	4	4
+406	9	9
+579	1	1
+37	1	1
+282	2	0
+6	12	0
+42	1	1
+55	1	1
+36	1	1
+396	54	54
+1355	2	0
+101	0	1
+149	1	1
+25	1	1
+611	1	1
+60	1	1
+224	20	0
+60	1	1
+398	0	2
+819	1	1
+48	1	1
+233	1	0
+459	6	6
+1131	10	10
+129	791	450
+41	119	117
+102	14	24
+16	1	1
+379	11	10
+240	1	1
+49	1	1
+203	1	1
+96	1	1
+50	896	15
+110	1	1
+59	1	1
+387	10	10
+157	1	1
+126	1	1
+60	1	1
+86	1	1
+124	1	1
+118	1	1
+160	3	1
+82	1	1
+64	0	1
+59	1	1
+235	1	1
+43	1	1
+126	45	34
+50	0	27
+37	0	2
+74	1	1
+69	13484	10061
+60	44	44
+112	244	248
+256	4076	10878
+54	1	1
+18	0	1
+10	1	1
+76	1	1
+36	1	1
+130	1	1
+25	1	1
+85	2	2
+21	1	0
+67	1	1
+32	1	1
+162	1	1
+23	1	1
+453	10	10
+396	5	0
+82	1	1
+397	0	1
+89	3	0
+40	1	1
+157	1	1
+43	0	8
+146	1	1
+38	1	1
+101	1	1
+33	7	1
+53	1	1
+41	1	1
+60	25	18
+60	1	1
+25	1	1
+80	1	1
+31	1	1
+88	8	7
+24	1	1
+417	0	1
+42	1	1
+122	1	1
+72	5	5
+88	1	1
+36	1	1
+495	14	14
+278	3	3
+48	1	1
+50	11	0
+147	1	1
+87	1	1
+67	1	1
+788	8	0
+51	1	1
+37	1	1
+107	1	1
+22	1	1
+290	1	0
+58	3	3
+804	12	12
+133	5	0
+34	0	8
+116	1	1
+592	112	115
+93	0	1
+84	1	1
+22	1	1
+188	1	1
+46	1	0
+10	1	0
+375	6	6
+117
+
+chain	13264711	chr17_ctg5_hap1	1680828	+	0	1680828	chr17	78774742	+	40740646	42268630	76
+1491	0	1
+105829	1	0
+7	1	0
+38	1	0
+39	0	3
+1127	2	0
+399	1	1
+36	1	1
+1284	2	0
+96	1	1
+18	1	1
+402	0	1
+1243	1	17
+1187	1	1
+93	2	2
+135	1	0
+1300	1	0
+970	1	1
+33	1	1
+1390	1	1
+32	0	1
+1238	11	11
+1231	1	0
+4784	7	7
+1610	0	43
+312	0	20
+4544	1	1
+80	1	1
+5233	1	1
+31	1	1
+1582	0	4
+606	1	0
+1781	1	0
+183	14	16
+1226	6	0
+3095	1	1
+81	1	1
+4769	1	0
+4452	3	3
+41	1	1
+1401	1	1
+34	1	1
+1154	1	1
+28	1	1
+2549	12	12
+2173	2	0
+2280	1	1
+38	1	3
+2217	0	1
+498	0	1
+93	1	1
+22	1	1
+1950	0	2
+66	0	2
+1228	8	5
+1593	0	1
+468	1	1
+21	0	1
+170	10	0
+794	0	8
+1870	8	2
+3575	2	2
+43	1	1
+244	13	13
+611	5	5
+4057	4	1
+721	0	1
+1373	0	3
+28	1	1
+1422	1	0
+788	2	0
+584	188	188
+30	1152	1152
+40	270	270
+53	62	62
+87	227791	12647
+23	8319	12304
+52	449	449
+41	17972	13320
+26	114	119
+50	2682	2667
+31	1087	1088
+42	10911	10903
+41	76	76
+35	287	287
+93	1272	1285
+4834	34	1
+1629	1	1
+28	0	1
+59	1	1
+83	0	1
+25	1	1
+271	1	1
+19	1	1
+112	1	1
+64	1	1
+485	1	1
+57	1	1
+57	23	23
+144	0	4
+308	11	11
+82	0	2
+54	1	1
+70	1	1
+37	1	1
+145	1	1
+92	1	1
+114	5	5
+73	1	1
+76	6	6
+71	1	1
+72	1	1
+60	1	1
+35	1	1
+208	1	0
+658	1	1
+38	1	1
+57	1	1
+148	0	1
+48	14	1
+238	1	1
+34	1	1
+72	1	1
+39	4	0
+27	17	5
+36	1	1
+322	1	1
+65	1	1
+149	1	1
+121	1	1
+189	14	14
+54	1	1
+187	0	1
+71	5	0
+22	0	4
+53	3	5
+246	5	9
+32	1	1
+131	1	1
+26	1	1
+139	2	0
+74	3	0
+248	1	1
+70	3	0
+22	1	1
+56	1	1
+23	1	1
+175	1	1
+81	2	0
+75	32	32
+220	14	13
+196	178	178
+126	28	22
+332	8	8
+98	35	35
+82	0	1
+246	10	10
+80	24	21
+105	4	4
+104	18	20
+52	22	22
+224	6	6
+62	174	173
+149	6	9
+188	4	0
+164	0	1
+157	1	1
+264	8	0
+51	0	1
+5	0	1
+5	1	0
+32	1	1
+262	1	1
+42	1	1
+59	1	1
+68	1	1
+277	1	1
+48	1	1
+52	1	1
+30	4	4
+92	1	1
+40	1	1
+164	1	1
+34	1	1
+249	5	5
+70	5	5
+145	1	1
+55	1	1
+56	0	1
+38	1	1
+96	0	3
+143	1	1
+146	1	1
+158	15	15
+775	8	0
+80	1	1
+38	1	1
+556	1	1
+44	1	1
+79	1	0
+44	1	1
+86	4	4
+121	1	1
+13	0	1
+13	1	1
+203	1	1
+44	1	1
+567	1	0
+384	1	1
+43	1	1
+576	0	2
+167	1	1
+698	1	1
+41	1	1
+207	2	0
+342	0	1
+113	1	1
+595	13	13
+666	1	1
+19	1	1
+471	1	1
+25	1	1
+327	1	1
+36	1	1
+549	0	16
+83	17	17
+149	1	1
+40	1	1
+206	1	1
+48	1	1
+96	0	1
+87	1	1
+83	1	1
+130	1	1
+350	1	1
+17	1	1
+141	1	1
+45	1	0
+210	0	4
+428	13	13
+135	1	0
+555	8	0
+29	1	1
+108	1	1
+67	1	1
+481	2	0
+575	4	4
+10	0	3
+28	1	1
+55	4	4
+125	0	9
+59	3	3
+73	8	8
+146	1	1
+203	1	1
+132	1	1
+71	48592	13305
+71	3382	3374
+25	5834	5854
+89	1	1
+9	10000	10418
+20	1	1
+40	0	4
+13	1	1
+3	602540	600615
+450	1	1
+71	1	1
+126	4	0
+131	2	2
+95	7526	7516
+28	827	819
+39	10	10
+8	19785	19984
+220	7353	7908
+33	269	269
+60	61	61
+46	547	550
+30	424	423
+57	355	353
+45	1	1
+108	46	38
+46	51	51
+56	371	371
+48	1139	1133
+154	7	7
+118	1	1
+28	1	1
+69	1	1
+80	2	1
+56	0	3
+50	1	1
+40	1	1
+47	0	1
+176	8	8
+35	1	1
+86	1	1
+19	0	7
+57	1	1
+179	1	1
+53	1	1
+64	1	1
+39	1	1
+93	2	2
+138	0	2
+402	3	5
+350	1	1
+18	1	1
+413	8	4
+297	7	0
+273	5	0
+96	1	1
+17	1	1
+241	0	1
+593	4	0
+50	1	1
+179	30	0
+8	0	2
+6	0	1
+27	6	0
+7	1	15
+77	51	25
+119	16	15
+89	1	1
+36	5	5
+156	23	23
+66	1	1
+20	1	1
+785	62	62
+118	1	1
+97	1	1
+84	1	1
+53	2	2
+141	0	12
+60	1	1
+47	1	1
+67	1	1
+61	1	1
+61	2	0
+64	1	1
+160	1	12
+1118	3	3
+54	9	31
+96	1	1
+20	1	1
+55	1	1
+23	1	1
+260	12	12
+134	13	13
+447	5	5
+659	1	1
+76	1	1
+57	1	1
+30	1	1
+150	11	0
+11	3	0
+85	1	1
+82	0	3
+128	1	1
+83	1	1
+35	0	2
+17	1	1
+157	0	1
+5	0	2
+14	3	3
+177	1	1
+32	1	1
+355	1	1
+25	1	0
+26	0	2
+77	1	1
+31	1	1
+190	1	1
+34	1	1
+77	15	15
+79	12	14
+200	17	17
+721	1	1
+35	1	1
+247	1	1
+44	1	1
+107	1	1
+52	1	1
+391	19	23
+467	18	19
+535	1	1
+30	1	1
+54	1	2
+55	3	3
+22	2	2
+348	1	1
+34	1	1
+429	4	0
+66	8	8
+298	1	1
+56	1	1
+316	5	5
+71	1	1
+11	10	0
+31	12	0
+90	1	1
+16	1	4457
+76	1	1
+48	1	1
+66	4	5
+164	1	0
+354	1	1
+46	1	1
+779	19	19
+189	1	1
+45	1	1
+477	9	9
+180	1	0
+305	1	1
+20	1	1
+247	9	10
+131	5	5
+1115	1	1
+43	1	1
+98	0	1
+27	1	1
+152	15	15
+295	1	1
+18	1	1
+110	1	1
+49	1	1
+129	1	1
+34	1	1
+93	1	1
+91	1	1
+318	6	6
+112	4	4
+31	7	0
+150	0	2
+130	1	1
+19	1	1
+747	8	8
+708	9	9
+295	0	1
+25	1	1
+320	1	1
+26	1	1
+302	1	0
+45	15	0
+14	1	1
+75	1	1
+26	1	1
+494	1	1
+19	1	1
+267	11	11
+95	1	1
+15	4	0
+84	7	7
+87	206984	212276
+34	11226	11239
+62	1	1
+82	9866	9856
+54	5848	5823
+791	41	41
+31	1	1
+47	1	1
+39	1165	1166
+864	1	1
+31	2021	2021
+8	0	8
+37	259	273
+434	1	0
+1376	9	7
+578	14	5
+814	6	5
+638	0	1
+416	1	1
+49	1	1
+5436	0	6
+3224	0	1
+352	1	1
+31	10	0
+65	60	60
+44	112	112
+244	256	256
+1152	1	0
+773	0	5
+2150	2914	2914
+7	0	1
+18	5377	5375
+112	946	946
+2705	0	2
+1072	1	1
+30	1	1
+126	0	1
+1278	0	2
+1963	1	0
+706	0	9
+89	1	29
+428	0	3
+306	0	14
+149	1	1
+22	1	1
+1153	1	0
+877	14	12
+1014	1	1
+49	1	1
+3485	1	0
+2740	1	1
+27	4	0
+238	1	1
+48	1	1
+385	6	0
+1355	1	1
+27	2	2
+1020	10	0
+2311	0	2
+646	0	2
+8446	1	0
+1582	3	4
+2031	1	0
+1347	0	4
+939	1	1
+82	1	1
+2216	0	12
+806	0	4
+3009	7	0
+73	1	1
+37	1	1
+88	79	85
+2100	2	0
+804	1	1
+31	1	1
+56	1	0
+531	0	1
+3255	0	17
+119	16	16
+2727	0	5
+1516	1	0
+88	1	1
+31	1	1
+2085	0	1
+2381	3	0
+988	0	1
+1138	2	2
+37	1	1
+3015	12	0
+3465	1	1
+30	1	1
+1220	54	43
+3519	0	1
+4735	1	0
+1246	0	4
+257	1	0
+919	0	5
+811	53	53
+5990	0	1
+369	0	4
+1080	50000	139273
+41860
+
+chain	2227376	chr17_ctg5_hap1	1680828	+	1397503	1425444	chr17	78774742	+	41665512	41694673	1168
+810	6	0
+20	1	0
+396	1	0
+77	1	1
+160	1	1
+198	18	18
+170	1	0
+835	7	0
+178	0	1
+512	1	1
+18	0	1
+91	1	1
+41	5	4
+205	1	1
+46	1	1
+313	1	0
+195	1	1
+34	1	1
+81	114	114
+158	1	1
+29	5	0
+216	7	0
+202	0	724
+357	0	2
+36	1	1
+281	25	26
+94	1	1
+45	1	0
+56	1	1
+102	5	0
+286	8	9
+1295	1	1
+110	1	1
+117	0	5
+157	16	16
+272	1	1
+26	2	0
+277	6	6
+193	4	4
+153	1	9
+20	1	1
+1068	8	4
+216	2	0
+224	9	0
+383	21	0
+79	1	1
+361	1	1
+25	1	1
+1006	1	1
+62	1	1
+60	15	15
+107	12	14
+73	0	3
+33	0	4
+890	73	73
+139	0	5
+826	5	0
+366	0	2
+187	0	2
+175	146	146
+739	20	20
+205	13	13
+355	45	45
+160	0	1
+617	0	15
+366	28	27
+202	111	110
+154	52	52
+368	997	1615
+183	2	2
+449	4	0
+108	17	0
+162	0	2
+93	1	1
+31	0	1
+149	9	9
+69	11	11
+275	1	1
+14	0	4
+120	1	1
+115	1	1
+76	2	1
+121	1	1
+72	1	1
+88	3	3
+68	1	1
+96	57	1
+229	1	1
+21	0	1
+25	2	0
+112	2	2
+84	5	0
+75	3	3
+171	66	65
+113	18	18
+348	81	73
+67	44	44
+67	16	19
+149	0	3
+72	36	36
+123	92	91
+67	297	297
+178	433	428
+365	20	20
+130	51	51
+302	17	17
+62	20	20
+316	1	0
+138	37	25
+75	5	9
+267	7	7
+118	30	30
+69	92	92
+99	42	42
+47	0	1
+113
+
+chain	1902497	chr17_ctg5_hap1	1680828	+	1349157	1369929	chr17	78774742	-	37173234	37193985	1316
+1852	2	0
+9	8	8
+283	11	0
+34	0	1
+190	1	0
+3	2	0
+457	2	0
+106	1	1
+28	1	1
+144	4	0
+2112	6	6
+1530	1	1
+27	1	1
+123	1	0
+171	0	8
+504	5	6
+2360	1	1
+19	1	0
+1463	10	0
+471	36	36
+785	32	32
+412	0	3
+1217	32	32
+1308	28	26
+1339	13	13
+311	29	33
+733	22	22
+62	2	0
+251	11	11
+799	0	7
+97	3	0
+324	4	0
+473	46	46
+459
+
+chain	1776951	chr17_ctg5_hap1	1680828	+	1329556	1349123	chr17	78774742	-	37153638	37173199	1401
+128	0	1
+918	0	1
+530	2	0
+20	1	1
+129	1	0
+249	0	1
+279	4	0
+12	4	0
+26	4	0
+614	16	16
+179	4	0
+610	2	0
+646	28	35
+276	0	1
+1341	1	0
+360	1	1
+39	1	1
+467	1	1
+23	1	1
+633	6	6
+309	1	1
+27	0	2
+627	5	0
+1032	8	8
+226	1	1
+17	1	1
+385	5	4
+125	22	23
+301	14	0
+199	1	1
+26	1	1
+53	1	1
+33	1	1
+304	3	0
+1345	0	16
+944	72	72
+115	82	91
+248	14	14
+558	0	1
+750	1	0
+1083	69	69
+1136	0	2
+82	22	16
+836	0	4
+926
+
+chain	893264	chr17_ctg5_hap1	1680828	+	1372124	1381789	chr17	78774742	-	37196506	37206183	4351
+35	1	1
+343	27	25
+861	0	10
+298	0	4
+92	6	6
+784	0	5
+2089	1	0
+940	1	0
+304	2	0
+1246	1	0
+168	2	0
+171	1	0
+32	1	1
+1110	14	14
+833	0	4
+155	1	0
+146
+
+chain	666279	chr17_ctg5_hap1	1680828	+	1381822	1393172	chr17	78774742	+	60348942	60360296	7820
+119	36	36
+84	52	49
+205	29	29
+190	52	58
+180	57	57
+51	14	14
+312	54	54
+55	16	16
+52	88	88
+203	0	5
+250	22	25
+110	147	149
+328	217	214
+84	88	88
+79	39	39
+231	67	53
+89	16	17
+62	15	15
+187	47	51
+315	45	45
+78	214	214
+360	182	184
+116	67	67
+75	70	75
+106	18	20
+98	95	95
+54	19	19
+292	76	76
+171	87	87
+338	28	28
+98	78	75
+53	77	77
+51	62	62
+118	32	32
+192	39	39
+52	62	62
+175	44	44
+195	97	97
+75	173	173
+154	50	50
+125	17	17
+71	57	59
+92	12	12
+303	164	166
+258	424	419
+69	123	123
+345	40	39
+240	14	14
+128	87	86
+73
+
+chain	416007	chr17_ctg5_hap1	1680828	+	1245181	1252036	chr17	78774742	+	60351908	60358760	108741
+51	63	63
+229	10	10
+151	43	37
+58	47	48
+62	20	20
+152	91	97
+163	9	9
+305	11	11
+75	57	57
+75	6	6
+295	59	59
+64	15	17
+160	30	30
+112	70	75
+96	28	30
+98	95	95
+54	63	63
+249	75	75
+324	49	49
+113	42	41
+69	28	28
+98	78	75
+53	77	77
+51	62	62
+342	39	39
+52	62	62
+173	28	28
+82	49	49
+82	94	94
+78	209	203
+52	122	122
+206	100	102
+341	71	71
+53	44	44
+82	29	24
+180
+
+chain	246453	chr17_ctg5_hap1	1680828	+	1237068	1240267	chr9	140273252	+	109577466	109580401	401240
+805	41	1
+100	1	1
+90	49	0
+45	176	0
+349	1	1
+67	1	50
+65	127	0
+114	1	1
+48	1	1
+139	98	1
+58	1	0
+53	1	1
+94	1	178
+186	1	1
+21	2	2
+463
+
+chain	239377	chr17_ctg5_hap1	1680828	+	1312949	1315506	chr17	78774742	-	37137002	37139560	429566
+798	1	0
+565	0	1
+1034	0	1
+159
+
+chain	228096	chr17_ctg5_hap1	1680828	+	1321688	1324178	chr17	78774742	-	37145748	37148235	477585
+1787	39	36
+563	23	23
+78
+
+chain	196783	chr17_ctg5_hap1	1680828	+	1369959	1372123	chr17	78774742	-	37194027	37196505	622087
+666	41	355
+857	1	1
+25	1	1
+573
+
+chain	176658	chr17_ctg5_hap1	1680828	+	1325052	1326989	chr17	78774742	-	37149126	37151061	719570
+150	2	0
+143	37	37
+1605
+
+chain	168141	chr17_ctg5_hap1	1680828	+	711752	714062	chr16	88827254	+	28616023	28618285	762738
+361	1	1
+33	1	1
+130	127	0
+96	1	0
+50	19	19
+119	49	0
+110	1	2
+9	48	0
+90	98	0
+72	11	325
+56	14	14
+246	40	0
+212	17	17
+299
+
+chain	154508	chr17_ctg5_hap1	1680828	+	1307063	1308700	chr17	78774742	-	37131110	37132746	835029
+145	1	0
+1491
+
+chain	148102	chr17_ctg5_hap1	1680828	+	1232106	1430374	chr17	78774742	-	18425735	18434371	621
+4	1	1
+60	1	1
+112	0	1
+97	1	1
+125	2	0
+21	2	2
+61	1	1
+74	1	1
+73	1	1
+34	1	1
+300	1	1
+38	1	1
+80	12	12
+97	8	0
+29	2	2
+185	4	0
+515	2	0
+42	4	4
+430	190939	1320
+75	1	1
+18	1	1
+338	6	6
+61	1	0
+467	12	12
+451	1	0
+100	1	1
+50	1	1
+27	1	1
+132	0	2
+233	1	1
+37	1	1
+50	0	3
+469	1	1
+37	1	1
+94	1	1
+36	1	1
+125	4	4
+132	0	2
+39	1	1
+213	12	12
+184	3	0
+52	1	1
+16	1	1
+159	1	1
+19	2	2
+686	10	10
+230	15	15
+296
+
+chain	145367	chr17_ctg5_hap1	1680828	+	1327932	1329549	chr17	78774742	-	37151994	37153631	887940
+554	56	76
+1007
+
+chain	137569	chr17_ctg5_hap1	1680828	+	1309956	1311426	chr17	78774742	-	37134002	37135486	937317
+68	0	14
+1402
+
+chain	110156	chr17_ctg5_hap1	1680828	+	1320345	1321641	chr17	78774742	-	37144406	37145701	1161060
+640	31	31
+224	12	12
+204	52	51
+133
+
+chain	108079	chr17_ctg5_hap1	1680828	+	1315884	1317028	chr17	78774742	-	37139952	37141098	1182036
+885	0	2
+259
+
+chain	107213	chr17_ctg5_hap1	1680828	+	216004	477608	chr17	78774742	-	36300720	36848371	128
+48	7751	7515
+31	3	3
+10	52129	338773
+71	29976	29992
+37	2872	2872
+132	77377	77001
+50	9950	9939
+49	15970	16004
+80	5205	5206
+35	2373	2374
+35	2111	2102
+28	13945	13928
+281	29828	29826
+34	8713	8715
+32	430	430
+178	126	126
+28	438	438
+35	1039	1039
+174
+
+chain	88256	chr17_ctg5_hap1	1680828	+	1254762	1255800	chr17	78774742	-	37066345	37067387	1434130
+467	19	23
+391	54	54
+107
+
+chain	84535	chr17_ctg5_hap1	1680828	+	1416653	1417623	chr17	78774742	-	37747883	37748853	1275488
+209	0	1
+520	1	0
+240
+
+chain	83787	chr17_ctg5_hap1	1680828	+	1255846	1256794	chr17	78774742	-	37067433	37068381	1508032
+247	37	37
+664
+
+chain	81881	chr17_ctg5_hap1	1680828	+	1394662	1395623	chr17	78774742	-	37062220	37063176	1542051
+178	0	4
+127	43	43
+207	27	18
+379
+
+chain	78522	chr17_ctg5_hap1	1680828	+	1324178	1325052	chr17	78774742	-	37148244	37149121	1606324
+554	0	3
+200	43	43
+77
+
+chain	75262	chr17_ctg5_hap1	1680828	+	1317476	1318285	chr17	78774742	-	37141533	37142347	1673849
+255	0	5
+554
+
+chain	72597	chr17_ctg5_hap1	1680828	+	1318474	1319252	chr17	78774742	-	37142532	37143313	1734349
+618	0	3
+160
+
+chain	68786	chr17_ctg5_hap1	1680828	+	1312168	1312905	chr17	78774742	-	37136222	37136958	1829107
+216	1	0
+520
+
+chain	66138	chr17_ctg5_hap1	1680828	+	458426	496420	chr17	78774742	+	60323662	60348977	381
+29	102	102
+150	0	2
+92	35229	22555
+47	1	1
+72	0	3
+361	0	1
+361	1	1
+59	1	1
+79	1	1
+12	4	0
+22	8	0
+164	1	1
+29	8	0
+22	1	1
+166	1	1
+38	1	1
+167	0	3
+68	1	1
+61	1	1
+34	0	19
+130	1	1
+61	2	2
+22	7	0
+118	7	0
+90	0	1
+162
+
+chain	63091	chr17_ctg5_hap1	1680828	+	1252401	1253149	chr17	78774742	-	37063986	37064734	1993873
+71	5	5
+316	58	58
+298
+
+chain	58162	chr17_ctg5_hap1	1680828	+	1254067	1254744	chr17	78774742	-	37065648	37066326	2166241
+55	1	2
+54	32	32
+535
+
+chain	54716	chr17_ctg5_hap1	1680828	+	1319283	1319868	chr17	78774742	-	37143347	37143930	2309300
+443	2	0
+140
+
+chain	54428	chr17_ctg5_hap1	1680828	+	1396409	1397035	chr17	78774742	-	37063962	37064589	2322100
+416	38	39
+172
+
+chain	53306	chr17_ctg5_hap1	1680828	+	1327031	1327602	chr17	78774742	-	37151103	37151673	2373745
+61	1	0
+509
+
+chain	45719	chr17_ctg5_hap1	1680828	+	1253157	1253656	chr17	78774742	-	37064742	37065237	2803981
+63	4	0
+432
+
+chain	44822	chr17_ctg5_hap1	1680828	+	1308965	1309441	chr17	78774742	-	37133014	37133490	2867866
+476
+
+chain	44716	chr17_ctg5_hap1	1680828	+	1309483	1309955	chr17	78774742	-	37133530	37134002	2875759
+472
+
+chain	42970	chr17_ctg5_hap1	1680828	+	1249019	1250432	chr17	78774742	-	37056169	37057582	957875
+28	98	98
+37	9	10
+32	53	53
+77	51	51
+55	349	348
+39	52	52
+47	9	9
+6	173	173
+28	82	82
+49	82	82
+57
+
+chain	39900	chr17_ctg5_hap1	1680828	+	1311434	1311858	chr17	78774742	-	37135495	37135919	3282293
+424
+
+chain	36548	chr17_ctg5_hap1	1680828	+	1397076	1397503	chr17	78774742	-	37727818	37728245	1867431
+351	31	31
+45
+
+chain	35186	chr17_ctg5_hap1	1680828	+	1319971	1320341	chr17	78774742	-	37144033	37144403	3815477
+370
+
+chain	32846	chr17_ctg5_hap1	1680828	+	1253692	1254040	chr17	78774742	-	37065273	37065621	4148877
+348
+
+chain	32058	chr17_ctg5_hap1	1680828	+	1394126	1394519	chr17	78774742	-	37061682	37062075	4275850
+85	42	42
+266
+
+chain	30381	chr17_ctg5_hap1	1680828	+	343779	344098	chr13	114142980	+	60207729	60208048	4580555
+319
+
+chain	29004	chr17_ctg5_hap1	1680828	+	1317078	1317414	chr17	78774742	-	37141148	37141484	5128137
+110	17	17
+209
+
+chain	28739	chr17_ctg5_hap1	1680828	+	1393298	1393613	chr17	78774742	-	37060859	37061169	5278988
+151	5	0
+159
+
+chain	28608	chr17_ctg5_hap1	1680828	+	1381941	1384110	chr17	78774742	-	37049506	37051670	737272
+33	87	87
+3	16	17
+33	205	205
+29	190	190
+52	180	180
+57	377	361
+54	123	123
+34	639	649
+57
+
+chain	27290	chr17_ctg5_hap1	1680828	+	1250687	1251236	chr17	78774742	-	37057837	37058386	1723424
+69	52	52
+122	206	206
+100
+
+chain	23334	chr17_ctg5_hap1	1680828	+	1315561	1315806	chr17	78774742	-	37139619	37139864	8092879
+245
+
+chain	22172	chr17_ctg5_hap1	1680828	+	1247931	1248795	chr17	78774742	-	37055081	37055945	1359053
+50	54	54
+63	249	249
+75	324	324
+49
+
+chain	21861	chr17_ctg5_hap1	1680828	+	1311933	1312163	chr17	78774742	-	37135987	37136217	9092092
+230
+
+chain	20267	chr17_ctg5_hap1	1680828	+	1388625	1389065	chr17	78774742	-	37056169	37056610	1819714
+28	98	98
+37	9	10
+32	53	53
+77	51	51
+55
+
+chain	19257	chr17_ctg5_hap1	1680828	+	1251577	1252102	chr17	78774742	-	37058727	37059253	2345365
+71	53	53
+44	82	82
+24	1	0
+4	180	182
+66
+
+chain	18858	chr17_ctg5_hap1	1680828	+	1395798	1396023	chr17	78774742	-	37063364	37063589	11391766
+69	17	17
+139
+
+chain	17539	chr17_ctg5_hap1	1680828	+	1306794	1306981	chr17	78774742	-	37130913	37131100	12530835
+187
+
+chain	17362	chr17_ctg5_hap1	1680828	+	1327740	1327921	chr17	78774742	-	37151802	37151983	12688794
+181
+
+chain	16114	chr17_ctg5_hap1	1680828	+	1386775	1387126	chr17	78774742	-	37054317	37054668	3847861
+129	155	155
+67
+
+chain	14712	chr17_ctg5_hap1	1680828	+	1471572	1581528	chr17	78774742	+	41752645	41862594	227
+27	72594	72528
+20	0	36
+59	37204	37227
+3	1	1
+48
+
+chain	14021	chr17_ctg5_hap1	1680828	+	1391766	1393099	chr17	78774742	-	37059329	37060660	1551546
+50	88	88
+58	1094	1092
+43
+
+chain	13718	chr17_ctg5_hap1	1680828	+	1245232	1246117	chr17	78774742	-	37052388	37053271	1534336
+63	390	390
+37	2	0
+4	339	339
+50
+
+chain	13678	chr17_ctg5_hap1	1680828	+	1387543	1388241	chr17	78774742	-	37055086	37055784	1538578
+45	365	365
+76	171	171
+41
+
+chain	13678	chr17_ctg5_hap1	1680828	+	1386064	1386301	chr17	78774742	-	37053606	37053843	4358174
+45	78	78
+49	4	4
+61
+
+chain	12960	chr17_ctg5_hap1	1680828	+	1390153	1390290	chr17	78774742	-	37057697	37057834	10954124
+137
+
+chain	12859	chr17_ctg5_hap1	1680828	+	712690	713529	chr13	114142980	-	94890835	94891950	786174
+26	1	277
+22	258	82
+37	49	0
+12	399	624
+35
+
+chain	11529	chr17_ctg5_hap1	1680828	+	1327611	1327733	chr17	78774742	-	37151673	37151795	19785711
+122
+
+chain	11334	chr17_ctg5_hap1	1680828	+	1238199	1238375	chr13	114142980	+	19251561	19251738	585429
+101	4	5
+56	1	1
+14
+
+chain	11041	chr17_ctg5_hap1	1680828	+	1384528	1384669	chr17	78774742	-	37052089	37052230	4204331
+1	58	58
+82
+
+chain	10878	chr17_ctg5_hap1	1680828	+	1393633	1393747	chr17	78774742	-	37061189	37061303	20959654
+114
+
+chain	10460	chr17_ctg5_hap1	1680828	+	1396115	1396225	chr17	78774742	-	37063682	37063792	21801362
+110
+
+chain	10352	chr17_ctg5_hap1	1680828	+	1391207	1391342	chr17	78774742	-	37058757	37058894	7784932
+37	10	12
+88
+
+chain	9842	chr17_ctg5_hap1	1680828	+	1308830	1308934	chr17	78774742	-	37132877	37132981	23170572
+104
+
+chain	9287	chr17_ctg5_hap1	1680828	+	1318326	1318424	chr17	78774742	-	37142388	37142486	24449821
+98
+
+chain	8968	chr17_ctg5_hap1	1680828	+	1389414	1389567	chr17	78774742	-	37056958	37057111	4148137
+39	52	52
+47	9	9
+6
+
+chain	8877	chr17_ctg5_hap1	1680828	+	1252246	1252339	chr17	78774742	-	37063853	37063946	25134532
+93
+
+chain	8768	chr17_ctg5_hap1	1680828	+	1393172	1393264	chr17	78774742	-	37060733	37060825	25011976
+92
+
+chain	8158	chr17_ctg5_hap1	1680828	+	1393848	1393933	chr17	78774742	-	37061404	37061489	26172124
+85
+
+chain	7594	chr17_ctg5_hap1	1680828	+	1416023	1416258	chr17	78774742	-	37747254	37747489	2219812
+29	154	154
+52
+
+chain	7515	chr17_ctg5_hap1	1680828	+	1389981	1390060	chr17	78774742	-	37057525	37057604	6485868
+79
+
+chain	7285	chr17_ctg5_hap1	1680828	+	1252152	1252228	chr17	78774742	-	37059303	37059379	27632598
+76
+
+chain	6684	chr17_ctg5_hap1	1680828	+	1308721	1308790	chr17	78774742	-	37132768	37132837	28870693
+69
+
+chain	6515	chr17_ctg5_hap1	1680828	+	1247168	1247482	chr17	78774742	-	37054317	37054631	3599890
+45	239	239
+30
+
+chain	6497	chr17_ctg5_hap1	1680828	+	1387201	1387271	chr17	78774742	-	37054743	37054813	5969263
+70
+
+chain	6494	chr17_ctg5_hap1	1680828	+	1396307	1396375	chr17	78774742	-	37063872	37063940	29322189
+68
+
+chain	6058	chr17_ctg5_hap1	1680828	+	1315820	1315884	chr17	78774742	-	37139877	37139941	30402031
+64
+
+chain	5566	chr17_ctg5_hap1	1680828	+	218263	246046	chr17	78774742	+	60300789	60329221	713
+35	27719	28368
+29
+
+chain	5502	chr17_ctg5_hap1	1680828	+	1238858	1238932	chr5	180857866	-	146515862	146515936	441292
+74
+
+chain	5265	chr17_ctg5_hap1	1680828	+	1247608	1247664	chr17	78774742	-	37054757	37054813	15861596
+56
+
+chain	5130	chr17_ctg5_hap1	1680828	+	1393995	1394049	chr17	78774742	-	37061551	37061605	33050310
+54
+
+chain	4602	chr17_ctg5_hap1	1680828	+	1415941	1415989	chr17	78774742	-	37747172	37747220	10895303
+48
+
+chain	4584	chr17_ctg5_hap1	1680828	+	1237882	1239358	chr3	199501827	+	130155920	130156866	476764
+32	1412	882
+32
+
+chain	4558	chr17_ctg5_hap1	1680828	+	1317419	1317468	chr17	78774742	-	37141484	37141533	34680290
+49
+
+chain	4268	chr17_ctg5_hap1	1680828	+	1385266	1385319	chr17	78774742	-	37052825	37052878	8381466
+53
+
+chain	4260	chr17_ctg5_hap1	1680828	+	1246721	1246766	chr17	78774742	-	37053870	37053915	4651304
+45
+
+chain	4113	chr17_ctg5_hap1	1680828	+	1390480	1390530	chr17	78774742	-	37058030	37058080	2324449
+50
+
+chain	4082	chr17_ctg5_hap1	1680828	+	1239288	1239381	chr3	199501827	+	42815100	42815194	539611
+38	32	33
+23
+
+chain	4047	chr17_ctg5_hap1	1680828	+	833483	833530	chr2	242951149	+	222576128	222576175	5745276
+47
+
+chain	4004	chr17_ctg5_hap1	1680828	+	1413149	1413191	chr17	78774742	-	37744368	37744410	15417978
+42
+
+chain	3932	chr17_ctg5_hap1	1680828	+	1246117	1246158	chr17	78774742	-	37053273	37053314	13638111
+41
+
+chain	3773	chr17_ctg5_hap1	1680828	+	1250577	1250669	chr2	242951149	+	55360621	55360713	11417907
+92
+
+chain	3751	chr17_ctg5_hap1	1680828	+	1385702	1385742	chr17	78774742	-	37053251	37053291	3400438
+40
+
+chain	3702	chr17_ctg5_hap1	1680828	+	712859	712906	chr3	199501827	-	151273341	151273388	853543
+47
+
+chain	3381	chr17_ctg5_hap1	1680828	+	713034	713083	chr1	247249719	-	160795106	160795155	805231
+49
+
+chain	3244	chr17_ctg5_hap1	1680828	+	1389742	1389776	chrX	154913754	-	110129876	110129910	25281679
+34
+
+chain	2964	chr17_ctg5_hap1	1680828	+	236048	236081	chr17	78774742	-	37041849	37041882	635
+33
+
+chain	2912	chr17_ctg5_hap1	1680828	+	448843	448913	chr17	78774742	-	36315447	36315517	1328
+70
+
+chain	2802	chr17_ctg5_hap1	1680828	+	1237022	1237068	chr18	76117153	+	50122791	50122837	616904
+46
+
+chain	2574	chr17_ctg5_hap1	1680828	+	1384829	1384856	chr17	78774742	-	37052388	37052415	20977188
+27
+
+chain	2078	chr17_ctg5_hap1	1680828	+	1250433	1250469	chr3	199501827	-	96596057	96596093	10950065
+36
+
+chain	1744	chr17_ctg5_hap1	1680828	+	1238128	1238154	chr10	135374737	+	101842906	101842932	538799
+26
+
+chain	1504	chr17_ctg5_hap1	1680828	+	1238956	1238985	chr16	88827254	+	28335851	28335880	780320
+29
+
+chain	1483	chr17_ctg5_hap1	1680828	+	1250547	1250577	chr19	63811651	+	22556112	22556142	10358829
+30
+
+chain	1204	chr17_ctg5_hap1	1680828	+	1386904	1386940	chr7	158821424	-	133749629	133749665	22723933
+36
+
+chain	996	chr17_ctg5_hap1	1680828	+	535350	535379	chr20	62435964	+	35074223	35074252	2591094
+29
+
+chain	372	chr17_ctg5_hap1	1680828	+	1421954	1423021	chr17	78774742	-	37753177	37754232	1257025
+92	67	67
+4	0	5
+235	1	1
+56	179	175
+23	17	0
+223	1	1
+102	1	5
+66
+
+chain	3524656	chr17_gl000203_random	37498	+	0	37498	chr17_random	2617613	+	1876393	1913891	829
+37498
+
+chain	7797784	chr17_gl000204_random	81310	+	0	81310	chr17_random	2617613	+	2131554	2212864	420
+81310
+
+chain	16543266	chr17_gl000205_random	174588	+	0	174588	chr17_random	2617613	+	0	174588	173
+174588
+
+chain	3927003	chr17_gl000206_random	41001	+	0	41001	chr17_random	2617613	+	2495431	2536432	754
+41001
+
+chain	7055977505	18	78077248	+	10000	78016181	chr18	76117153	+	0	76117153	19
+15400898	3100000	1363998
+28218587	15	15
+5329636	150000	47000
+3667310	18	0
+16406889	50000	28008
+3388467	50000	22000
+2103304	0	3
+136125	1	0
+7	1	0
+647	1	0
+1543	1	0
+25	14	8
+19	2	0
+10	7	4
+9	4	2
+663	1	0
+359	1	0
+1617
+
+chain	404699	chr18_gl000207_random	4262	+	0	4262	chr18_random	4262	+	0	4262	116705
+4262
+
+chain	5307806876	19	59128983	+	60000	59114839	chr19	63811651	+	11000	63806651	21
+7286004	50000	5000
+1291194	45000	0
+11772188	69160	0
+4058236	3100000	8000000
+20129228	2	0
+701	0	3
+347	1	1
+31	1	1
+1833	0	3
+1984	1	1
+47	1	1
+190	1	1
+34	1	1
+889	2	0
+1413	7	0
+2680	4	0
+375	1	0
+314	4	0
+29	1	0
+69	0	1
+3881	1	1
+40	12	0
+293	14	0
+1479	1	0
+233	1	1
+45	1	1
+1049	1	0
+1766	7	44
+220	0	3
+537	7	0
+351	8	8
+3603	1	1
+17	0	3
+697	0	1
+269	0	3
+974	5	6
+96	10	0
+1096	10	10
+1177	12	14
+1141	9	12
+1090	0	1
+175	16	0
+1063	0	4
+4780	44	44
+722	0	1
+548	2	2
+44	1	1
+424	2	2
+26	1	0
+4	0	1
+82	1	1
+59	1	1
+2087	15	0
+1499	0	1
+1754	0	2
+11209362
+
+chain	1655749	19	59128983	+	20505321	20523415	chr19	63811651	+	20366320	20387252	1476
+2041	4	4
+5604	0	2
+363	0	1
+2655	5	2857
+153	46	46
+705	79	83
+370	6	1
+1668	27	26
+347	21	0
+191	6	6
+369	0	2
+393	68	67
+328	0	6
+2049	1	0
+464	35	35
+96
+
+chain	207934	19	59128983	+	59114839	59117224	chr22	49691432	+	49588728	49591432	1471
+992	1	1
+63	1	1
+125	152	154
+174	1	1
+47	3	0
+214	5	5
+254	1	1
+67	1	1
+55	1	321
+72	14	14
+142
+
+chain	126422	19	59128983	+	59117224	59118680	chr10	135374737	+	135372723	135373917	1944
+177	13	13
+165	1	1
+156	1	1
+205	4	4
+93	1	1
+14	5	0
+88	1	1
+110	1	1
+52	2	1
+28	2	1
+14	255	0
+68
+
+chain	13558	19	59128983	+	59116021	59116173	chr2	242951149	-	128870722	128870873	1493
+33	1	0
+24	1	1
+57	1	1
+35
+
+chain	7358	19	59128983	+	59118906	59118983	chr21	46944323	+	46944213	46944290	27502546
+77
+
+chain	3811	19	59128983	+	20573506	20573546	chr19	63811651	-	43994109	43994149	26416662
+40
+
+chain	174	19	59128983	+	47898161	47898204	chr18	76117153	+	27836426	27836469	20429401
+43
+
+chain	8748871	chr19_gl000208_random	92689	+	0	92689	chr19_random	301858	+	0	92689	377
+92689
+
+chain	15150451	chr19_gl000209_random	159169	+	0	159169	chr19_random	301858	+	142689	301858	196
+159169
+
+chain	10110185	chr1_gl000191_random	106433	+	0	106433	chr1_random	1663265	+	1464329	1570762	316
+106433
+
+chain	32373596	chr1_gl000192_random	547496	+	48723	413485	chr16	88827254	+	69402787	69760000	100
+342	1	1
+38	1	1
+638	8	8
+750	11	11
+240	11	11
+1444	1	1
+23	1	1
+1265	0	3
+1506	1	1
+23	1	1
+114	1	1
+80	1	1
+118	1	1
+75	1	1
+311	9	9
+489	1	1
+27	168	14
+109	0	1
+340	5	0
+442	1	0
+25	1	1
+336	0	2
+672	1	1
+21	1	1
+691	1	1
+18	1	1
+144	2	2
+22	1681	0
+79	1	1
+1812	1	1
+31	1	1
+382	0	1
+474	10	9
+280	1	1
+39	0	2
+14	1	1
+103	1	1
+74	1	1
+124	1	1
+39	1	1
+471	1	1
+33	1	1
+653	1	1
+37	1	1
+94	9	10
+195	1	13
+2039	1	0
+1635	1	1
+27	1	0
+301	17	0
+42	1	1
+315	0	1
+384	1	1
+36	0	1
+8	2	0
+1541	11	10
+376	1	1
+36	1	1
+409	1	1
+15	1	1
+547	1	1
+89	1	1
+134	11	11
+161	3	79
+23	0	26
+39	0	1
+6	25	0
+14	1	1
+101	0	9
+94	1	1
+21	1	1
+171	1	1
+81	1	1
+1737	1	1
+27	1	0
+353	1	1
+36	1	1
+470	1	1
+72	1	1
+247	107	107
+709	1	1
+57	1	1
+289	14	14
+296	0	3
+342	1	1
+25	1	1
+184	1	1
+48	1	1
+628	1	1
+50	1	1
+457	0	2
+579	1	1
+21	0	4
+431	0	1
+52	1	1
+45	1	1
+146	1	1
+25	1	0
+26	2	1
+107	1	1
+39	1	0
+72	1	1
+26	1	1
+200	1	1
+19	1	1
+931	1	1
+27	1	1
+386	1	1
+17	1	1
+874	8	8
+146	1	1
+60	1	1
+840	19	19
+63	1	1
+25	1	1
+704	0	1
+721	1	1
+23	1	1
+673	29	14
+370	2	0
+25	1	1
+53	10	10
+591	1	1
+17	1	1
+124	0	1
+373	11	11
+234	12	12
+230	1	1
+31	1	1
+63	0	3
+903	27	28
+874	1	0
+290	11	12
+275	15	15
+290	3	0
+140	1	1
+36	1	1
+99	1	1
+38	1	1
+291	7	7
+1388	8	8
+1013	0	1
+2046	1	2
+423	1	1
+51	1	1
+1534	1	1
+78	1	1
+345	1	1
+37	1	1
+673	16	17
+742	1	1
+41	1	1
+545	1	1
+21	4	4
+387	5	0
+36	1	1
+420	0	28
+640	1	1
+23	1	1
+109	10	10
+1286	1	1
+37	2	2
+294	0	1
+24	1	1
+235	5	8
+223	1	1
+17	1	1
+673	1	1
+22	1	1
+685	10	10
+1762	1	0
+560	1	1
+37	1	1
+279	1	1
+73	1	3
+124	7	8
+495	0	1
+361	0	12
+63	4	0
+127	0	3
+129	0	8
+96	1	1
+34	4	0
+2212	3	0
+954	8	9
+1081	1	1
+45	1	1
+1449	62	57
+910	1	1
+33	1	1
+627	4	0
+933	1	1
+65	0	4
+196	1	1
+198	5	1
+268	1	1
+27	1	1
+994	1	1
+93	1	1
+839	1	1
+31	1	1
+798	0	25
+1007	1	1
+27	0	1
+1076	1	0
+216	0	8
+865	1	1
+61	1	1
+627	9	9
+98	1	1
+25	1	1
+1211	1	1
+61	1	1
+1142	1	1
+37	1	2
+25	1	1
+1594	1	1
+57	1	1
+310	1	1
+21	1	1
+324	3	0
+648	1	1
+44	1	1
+128	1	1
+65	1	1
+1411	1	1
+49	2	2
+563	1	1
+109	1	1
+95	1	1
+16	4	0
+869	1	1
+68	1	1
+178	1	1
+16	1	1
+952	3	0
+206	14	6
+916	10	10
+591	0	1
+240	0	8
+189	0	14
+383	10	10
+242	27	22
+393	310	0
+472	0	1
+364	0	18
+58	1	1
+27	1	1
+40	0	1
+1533	1	24
+460	1	1
+31	1	1
+637	0	5
+63	1	1
+440	8	9
+997	1	1
+25	1	1
+1009	12	12
+317	68	68
+1117	12	8
+97	1	1
+24	1	1
+413	0	1
+1417	1	1
+28	1	1
+165	1	1
+40	1	1
+1132	1	1
+22	1	1
+193	1	1
+124	1	1
+812	1	0
+3002	1	1
+48	1	1
+1345	48	48
+673	4	0
+1213	1	1
+17	1	1
+118	2	2
+33	1	1
+84	13	28
+55	1	1
+34	1	1
+105	1	1
+29	1	1
+348	0	6
+39	0	8
+826	1	1
+26	1	1
+489	25	28
+655	0	1
+179	7	13
+51	1	1
+81	1	1
+24	0	1
+1169	0	1
+178	14	15
+410	1	1
+98	1	1
+90	0	1
+81	1	1
+120	1	1
+57	1	1
+101	11	11
+98	1	1
+16	1	1
+1379	1	1
+106	1	1
+82	1	1
+30	1	1
+85	3	20
+1047	17	17
+780	1	1
+33	1	1
+431	1	1
+62	1	1
+272	1	1
+45	1	1
+363	1	1
+50	1	1
+121	8	1
+188	1	1
+56	1	1
+358	1	1
+36	1	0
+158	0	3
+44	1	0
+253	16	16
+829	1	1
+17	1	1
+78	6	6
+473	1	1
+39	1	1
+92	1	0
+87	1	1
+2589	1	0
+85	13	13
+499	16	20
+512	7	0
+47	1	1
+257	1	1
+32	1	1
+272	14	15
+559	1	1
+25	1	1
+3126	7	4
+461	1	1
+26	1	1
+323	1	1
+30	1	1
+695	0	1
+61	1	1
+178	1	1
+100	0	2095
+496	1	1
+23	1	1
+907	1	1
+35	1	1
+300	1	1
+30	1	1
+215	1	1
+43	1	1
+542	58	58
+88	1	1
+19	1	1
+327	1	1
+61	418	1
+335	0	1
+318	1	1
+45	0	3
+922	15	15
+370	1	1
+20	1	1
+69	0	20
+25	0	4
+32	1	1
+77	7	0
+45	1	1
+3019	34	0
+111	13	13
+514	11	11
+278	1	1
+35	1	1
+462	10	10
+354	0	3
+82	5	1
+366	1	1
+43	1	1
+728	1	1
+51	1	1
+609	1	1
+21	1	1
+428	28	28
+1350	5	5
+737	1	1
+23	1	1
+499	1	1
+21	1	1
+957	3	7
+324	1	2
+466	14	14
+90	8	8
+2017	1	1
+41	1	1
+58	0	2
+498	5	5
+899	1	1
+40	1	1
+62	16	16
+422	0	1
+38	1	1
+264	2	0
+67	1	1
+988	41	41
+267	1	1
+19	1	1
+1598	61	0
+309	1	1
+35	1	1
+469	0	2
+751	0	3
+2839	1	1
+42	1	1
+1760	0	2
+330	1	1
+34	1	1
+561	1	1
+30	1	1
+664	1	1
+79	1	1
+194	67	67
+518	1	1
+29	1	1
+68	1	1
+29	1	1
+615	22	21
+389	0	1
+197	30	0
+271	1	0
+448	1	1
+33	1	1
+839	14	13
+78	1	1
+20	1	1
+331	4	0
+1237	1	1
+40	1	1
+489	1	1
+44	1	0
+303	1	1
+40	1	1
+196	0	1
+129	9	8
+424	1	1
+35	1	1
+852	5	0
+105	1	1
+2114	30	30
+513	1	1
+22	1	1
+56	2	0
+704	1	1
+35	1	1
+427	1	1
+34	0	10
+42	1	0
+294	1	0
+153	9	8
+84	1	1
+45	4	4
+1521	1	1
+29	1	1
+530	1	1
+43	1	1
+894	6127	21
+161	0	4
+175	17	17
+636	12	12
+79	11	11
+69	0	1
+76	1	1
+359	1	1
+31	0	4
+67	1	1
+439	14	14
+343	0	3
+254	0	1
+189	0	1
+35	1	1
+1458	48	48
+1591	14	14
+708	8	8
+976	6	17
+637	1	1
+33	0	1
+956	1	1
+54	1	1
+135	1	1
+23	1	1
+467	1	1
+22	1	1
+87	1	0
+11	1	1
+94	4	0
+684	17	17
+344	1	1
+23	1	1
+1534	1	1
+32	4	0
+245	1	1
+44	1	1
+880	0	5
+105	1	1
+48	1	1
+2535	9	9
+129	0	12
+287	1	1
+46	1	1
+121	1	5
+158	13	14
+80	6	6
+698	5	6
+75	1	1
+43	1	1
+123	1	1
+24	2	7
+58	7	0
+2751	8	8
+528	1	1
+39	1	1
+223	1	0
+912	1	1
+39	0	1
+1215	30	30
+874	1	1
+31	1	1
+113	0	1
+511	1	1
+28	1	1
+291	1	3
+81	1	1
+109	1	1
+152	1	1
+39	10	5
+361	1	1
+31	2	0
+20	1	1
+180	1	1
+109	1	1
+324	1	1
+25	1	1
+539	1	1
+5	2	0
+61	1	1
+395	1	0
+1146	1	1
+45	1	1
+804	1	1
+95	1	1
+856	15	15
+541	322	0
+256	1	1
+23	1	1
+347	1	1
+21	1	1
+332	1	1
+71	1	1
+531	1	0
+488	1	1
+21	0	1
+74	20	19
+517	1	1
+35	1	1
+738	1	1
+41	1	1
+91	3	3
+117	1	1
+85	9	10
+200	6	0
+489	1	1
+271	10	0
+208	1	1
+46	2	2
+708	11	11
+70	1	1
+61	1	0
+88	1	1
+45	1	1
+1206	3	0
+19	1	1
+521	1	1
+25	1	1
+1518	1	1
+42	6	6
+1124	7	8
+53	1	1
+42	1	1
+825	17	17
+825	0	3
+568	1	1
+66	1	1
+394	17	17
+126	1	1
+41	1	1
+577	26	28
+367	12	11
+489	1	1
+65	1	1
+457	1	1
+16	1	1
+350	8	8
+18	4	4
+402	1	0
+103	1	0
+648	1	1
+36	1	1
+446	0	3
+61	16	16
+823	1	1
+32	1	1
+516	1	1
+111	1	1
+1091	1	1
+38	1	1
+49	1	0
+635	0	3
+14	1	1
+153	1	1
+40	1	1
+359	1	1
+35	4	4
+283	2	0
+557	1	1
+19	1	1
+293	3	4
+454	1	1
+70	1	1
+405	0	4
+1613	1	1
+26	13	15
+44	1	1
+458	13	13
+253	0	1
+1200	0	2
+244	1	4
+247	1	1
+38	1	1
+102	0	14
+710	1	1
+20	1	1
+1098	0	4
+200	2	0
+386	0	3
+683	1	1
+26	1	1
+327	4	0
+172	1	1
+311	1	1
+18	1	1
+338	28	28
+420	1	1
+29	1	1
+352	12	12
+301	1	1
+75	1	1
+205	1	0
+250	1	1
+20	1	1
+990	1	1
+20	1	1
+233	0	6
+342	5	9
+156	1	1
+30	1	1
+321	16	16
+420	11	11
+968	3	3
+15	1	1
+162	1	1
+68	1	1
+825	18	18
+153	1	1
+42	1	1
+711	1	1
+20	1	1
+269	1	0
+1414	4	3
+641	9	9
+1000	1	1
+29	1	1
+437	0	6
+45	1	1
+261	1	1
+31	0	2
+168	1	1
+26	1	1
+73	15	7
+29	4	0
+56	1	1
+126	1	1
+32	1	1
+463	6	6
+388	14	14
+1024	1	1
+54	1	1
+1019	1	1
+27	1	1
+428	3	3
+40	1	1
+86	1	1
+29	1	0
+610	6	10
+492	1	1
+28	3	3
+1202	11	11
+981	1	1
+28	1	1
+306	1	1
+39	1	1
+696	1	0
+157	1	1
+38	1	1
+170	1	1
+44	1	1
+2005	1	1
+26	1	1
+473	4	4
+491	0	1
+331	12	12
+1430	3	3
+11	0	5
+662	2	1
+494	12	13
+673	1	1
+76	1	1
+584	1	1
+36	1	1
+872	12	12
+123	1	1
+24	1	1
+540	15	15
+1309	1	1
+22	1	1
+71	15	15
+289	1	1
+38	1	1
+145	0	4
+731	3	0
+44	1	1
+2057	6	0
+446	4	0
+156	9	9
+55	0	1
+503	0	5
+38	1	1
+341	15	15
+493	1	1
+29	5	5
+1796	2	0
+1039	7	7
+444	8	8
+37	1	1
+205	0	1
+106	1	1
+386	1	1
+20	0	6
+2818	12	12
+498	15	15
+593	1	0
+203	1	1
+49	1	1
+313	1	2
+666	1	1
+46	0	2
+1360	1	0
+954	1	1
+65	1	1
+67	1	1
+33	1	1
+1062	1	1
+48	4	4
+600	16	16
+139	1	1
+29	1	1
+150	103	103
+813	1	1
+23	1	1
+775	1	1
+28	2	0
+55	13	0
+39	2	0
+17	0	1
+23	0	1
+7	11	1
+94	74	0
+163	1	1
+27	1	1
+2843	7	7
+73	4	0
+151	1	1
+22	0	1
+90	1	1
+316	15	15
+787	0	1
+405	1	1
+36	1	1
+833	2	0
+18	1	1
+1716	12	12
+78	0	1
+1860	0	1
+696	0	4
+16	1	1
+2116	3	4
+1554	1	1
+53	1	1
+1460	1	1
+25	1	1
+427	1	1
+37	1	1
+554	1	1
+36	1	1
+1626	40	40
+1079	1	1
+26	1	1
+427	2	0
+344	6	333
+1112	1	1
+19	1	1
+796	6	0
+373	1	1
+22	1	1
+787	1	0
+34	1	1
+1007	1	1
+36	2	0
+52	1	1
+945	1	0
+11	1	1
+743	1	1
+28	2	0
+1105	5	0
+45	2	0
+17	0	2
+49	1	1
+832	1	1
+33	1	1
+176	1	1
+48	0	4
+83	1	1
+91	1	1
+47	1	1
+256	1	1
+32	1	1
+1635	3	0
+175	5	1
+30	1	1
+1026	1	0
+13	1	1
+2090	20	20
+655	0	3
+628	1	1
+63	1	1
+380	1	1
+47	1	1
+2190	24	24
+149	0	2
+747	1	1
+17	0	7
+238	1048	0
+904	1	1
+78	1	1
+433	14	14
+153	1	1
+19	1	1
+561	1	1
+35	1	1
+271	2	0
+699	1	1
+53	1	1
+1273	0	1
+3111	11	11
+235	16	16
+490	3	0
+190	32	0
+83	18	19
+182	4	5
+78	0	4
+1098	1	1
+43	2	1
+1431	1	1
+35	4	4
+1822	0	6
+198	1	1
+41	1	1
+683	15	15
+1327	0	2
+18	1	1
+324	4	7
+1392	14	14
+1447
+
+chain	5080406	chr1_gl000192_random	547496	+	490457	547496	chr1	247249719	-	103949739	104006714	618
+285	2	1
+83	1	1
+1165	5	5
+59	1	1
+331	3	3
+32	1	1
+159	9	8
+140	1	1
+34	1	1
+111	1	1
+56	1	1
+419	1	1
+30	0	1
+231	16	16
+720	1	1
+47	1	1
+992	14	14
+147	1	1
+35	1	1
+270	2	2
+55	1	1
+204	1	1
+35	1	1
+189	12	12
+393	2	0
+504	2	0
+443	0	1
+181	0	6
+45	1	1
+719	1	1
+26	1	1
+723	9	9
+295	1	1
+56	1	1
+384	0	1
+516	1	0
+24	1	1
+81	0	1
+748	1	1
+47	1	1
+110	1	1
+38	82	0
+28	1	1
+526	1	1
+27	5	5
+166	8	7
+1312	0	4
+31	1	1
+230	1	1
+87	1	1
+309	13	0
+405	1	1
+33	1	0
+100	1	1
+59	1	1
+39	1	9
+184	0	4
+50	1	1
+211	4	4
+435	1	1
+55	1	1
+160	1	1
+39	1	1
+1986	1	1
+16	1	1
+117	0	1
+55	1	1
+357	0	1
+50	1	0
+368	0	20
+62	2	0
+4	2	0
+97	1	1
+121	0	1
+29	3	0
+857	36	36
+1724	0	322
+1221	1	1
+15	1	1
+135	8	8
+157	1	1
+25	0	1
+139	1	1
+36	1	1
+722	1	1
+46	1	0
+20	7	0
+862	1	0
+143	5	5
+274	1	1
+35	1	1
+355	0	1
+20	1	1
+376	1	1
+63	1	1
+199	1	1
+31	1	1
+261	0	1
+155	20	21
+52	0	1
+56	3	0
+151	23	23
+214	16	16
+105	1	1
+9	0	4
+41	1	1
+155	1	1
+77	1	1
+487	4	0
+82	1	1
+34	1	1
+275	1	1
+38	1	1
+334	1	1
+45	1	0
+4	0	4
+455	1	1
+47	1	1
+282	3	0
+74	14	14
+82	7	0
+717	1	1
+39	1	1
+197	0	4
+12	1	1
+50	17	17
+76	1	1
+38	1	1
+148	1	1
+60	1	1
+245	1	1
+18	1	1
+380	10	0
+348	1	1
+17	1	1
+515	1	1
+24	1	1
+267	5	7
+44	2	0
+25	1	1
+111	18	0
+162	1	1
+66	0	4
+109	1	1
+39	1	1
+676	16	16
+256	1	1
+48	1	1
+791	2	1
+61	1	1
+55	312	0
+281	7	7
+98	0	4
+66	1	1
+115	9	9
+678	1	1
+37	1	1
+304	1	1
+23	1	1
+283	1	1
+19	1	1
+164	10	10
+252	0	2
+131	4	4
+36	5	5
+83	1	1
+40	1	1
+361	27	20
+303	1	1
+69	1	1
+324	40	40
+72	12	0
+397	1	1
+23	1	1
+467	0	1
+418	6	6
+77	0	1
+21	1	1
+98	0	1
+21	1	1
+282	1	2
+107	22	22
+74	3	3
+47	1	1
+193	1	1
+46	1	1
+334	0	1
+78	0	1
+355	11	12
+823	1	1
+20	1	1
+173	1	1
+65	1	1
+335	0	4
+599	12	12
+143	1	1
+25	1	1
+1136	1	1
+38	1	1
+247	0	4
+30	1	1
+86	1	1
+19	1	1
+735	8	8
+679	15	15
+456	1	1
+43	1	1
+312	1	1
+94	1	1
+1047	1	1
+40	1	1
+1645	1	1
+37	1	1
+267	1	1
+55	1	1
+187	8	18
+480	1	1
+85	1	1
+537	1	1
+80	1	0
+80	0	11
+249	1	1
+24	1	1
+134	1	1
+36	1	1
+62	1	1
+81	0	2
+93	5	5
+46	1	1
+158	1	1
+36	1	1
+148	1	1
+67	1	1
+595	1	1
+30	1	1
+946	14	14
+58	1	1
+15	1	1
+321
+
+chain	2388490	chr1_gl000192_random	547496	+	0	480547	chr1	247249719	+	146071331	146197786	328
+299	0	14
+547	0	5
+291	3	3
+30	1	1
+1107	1	1
+35	1	1
+66	1	1
+86	1	1
+975	16	0
+485	12	0
+240	1	1
+16	1	1
+452	1	1
+26	2	2
+219	10	10
+607	31	14
+57	1	1
+397	1	1
+27	1	1
+69	0	2
+299	1	1
+38	0	1
+97	1	1
+33	1	1
+310	1	1
+63	1	1
+1214	11	0
+672	1	1
+30	1	1
+562	1	1
+34	1	1
+86	5	0
+36	52	0
+40	36	0
+73	0	3
+218	0	2
+885	1	1
+77	1	1
+153	1	1
+46	1	1
+538	0	1
+42	1	1
+495	0	1
+618	0	1
+406	1	1
+47	2	0
+264	1	1
+19	1	1
+112	0	3744
+343	13	14
+366	0	1
+39	1	1
+90	5	5
+72	0	3
+152	2	2
+42	1	1
+71	0	1
+30	1	1
+61	12	12
+280	0	3
+12	1	1
+101	1	1
+48	1	1
+97	1	1
+115	1	1
+299	1	1
+41	89	1
+148	7	7
+250	0	1
+1402	1	1
+69	1	0
+239	1	1
+38	1	1
+376	2	0
+96	1	1
+31	1	1
+273	0	4
+458	1	1
+22	0	12
+149	1	1
+38	0	2
+18	1	1
+443	1	0
+252	1	1
+25	1	1
+74	1	1
+18	0	1
+1535	108	9368
+354	1	0
+37	1	1
+1063	3	2
+3079	1	0
+142	1	1
+71	1	1
+230	6	6
+41	0	1
+112	4	4
+17	1	1
+478	2	0
+242	1	1
+21	1	1
+1407	1	0
+669	1	1
+34	1	1
+1561	1	1
+40	2	2
+62	1	1
+53	1	1
+975	1	1
+119	1	1
+1713	5	5
+132	0	3
+2570	1	0
+1294	9	9
+934	1	1
+33	1	1
+1518	4	1
+125	2889	0
+28	0	18
+706	10	10
+156	13	13
+1659	13	14
+1183	1	1
+49	1	1
+173	23	25
+420	364833	841
+3162	1	1
+44	1	1
+3579	1	1
+17	2	1
+30	3	0
+56	13	14
+298	1	1
+45	1	1
+388	1	1
+85	1	3
+162	2	0
+3397	3	5
+143	1	1
+19	1	1
+1299	1	1
+27	1	1
+10915	0	1
+4994	8	0
+1610	0	1
+3783	7	7
+606	4	0
+304	0	15
+143	12	14
+390	1	1
+43	0	2
+16	1	1
+231	5	0
+127	0	2
+222	2	0
+218	1	1
+45	1	1
+331	1	1
+23	1	1
+216	1	1
+21	1	1
+999	5	0
+563	1	1
+23	1	1
+305	1	1
+44	1	1
+466	2	0
+20	0	4
+234	16	21
+104	1	1
+28	1	1
+465	0	6
+137	1	3
+115	1	1
+23	1	1
+409	1	2
+762	1	1
+34	1	1
+133	1	1
+67	1	1
+1539	1	1
+24	1	1
+1362	9	2
+1632	1	1
+28	1	1
+1531	2	0
+26	1	1
+1909	10	2
+1605	1	1
+26	0	1
+834	0	1
+393	1	0
+40	1	1
+1724	1	1
+46	1	1
+588	8	8
+61	16	16
+669	1	1
+39	1	0
+1028	1	0
+21	1	1
+320	8	4
+1618	13	13
+569	18	15
+151	76	46
+2055	1	1
+35	1	1
+232	2	2
+26	1	1
+244	23	21
+54	16	16
+162	9	9
+61	1	1
+45	1	1
+72	1	1
+81	1	1
+197	1	1
+39	1	1
+300	1	1
+19	1	1
+370	9	9
+1433	1	0
+76	1	1
+21	1	1
+415	1	1
+26	1	1
+175	1	1
+9	2	0
+25	1	1
+413	1	1
+32	1	1
+299
+
+chain	551976	chr1_gl000192_random	547496	+	231797	237825	chr6	170899992	-	168530959	168536987	11545
+330	1	1
+17	2	2
+622	1	1
+19	1	1
+487	6	6
+662	1	1
+28	1	1
+1141	1	1
+84	1	1
+122	1	1
+29	1	1
+938	1	1
+49	1	1
+234	1	1
+107	1	1
+1138
+
+chain	488033	chr1_gl000192_random	547496	+	485075	510500	chr1	247249719	-	100429719	100455173	784
+56	1	1
+59	1	1
+88	1	0
+166	1	1
+42	1	1
+157	3	0
+1500	0	4
+24	1	1
+173	13	13
+537	1	1
+71	1	1
+274	1	1
+48	2	0
+29	1	1
+419	1	1
+75	1	1
+714	1	0
+919	11263	11275
+82	8662	8682
+36
+
+chain	29331	chr1_gl000192_random	547496	+	141011	141318	chr6	170899992	+	18853789	18854096	4814875
+307
+
+chain	25541	chr1_gl000192_random	547496	+	270161	270431	chr1	247249719	-	64213918	64214188	6752530
+270
+
+chain	18946	chr1_gl000192_random	547496	+	186298	186626	chr3	199501827	+	41796165	41796493	1046918
+124	44	44
+160
+
+chain	12970	chr1_gl000192_random	547496	+	526591	526726	chr14	106368585	+	78475097	78475232	7622843
+135
+
+chain	5617	chr1_gl000192_random	547496	+	185742	186466	chr4	191273063	-	143160847	143161571	1095905
+58	622	622
+44
+
+chain	2480	chr1_gl000192_random	547496	+	270431	270457	chr18	76117153	+	32169444	32169470	11367132
+26
+
+chain	2357	chr1_gl000192_random	547496	+	186676	186702	chr16	88827254	+	78288031	78288057	25120671
+26
+
+chain	2224	chr1_gl000192_random	547496	+	530486	530526	chr1_random	1663265	+	473083	473123	25958
+40
+
+chain	22466185064	2	243199373	+	10000	243102476	chr2	242951149	+	0	242751149	1
+1201236	0	1
+2057	1	1
+26	1	1
+4043	22	0
+82	7	101
+33	84	0
+26	1	23
+67	48	0
+176	318	0
+40	92	0
+33	0	74
+62	0	6
+22	0	118
+387	2446	0
+843	2450	0
+167	2304	0
+21342	1	1
+50	4	0
+2040	0	4
+9053	2	0
+88	3	53
+1078	0	1
+4122	1	0
+1608	28	1
+4029	0	9
+967	4547	1000
+420	27	0
+2237126	0	1
+2458	17	17
+4595	4	0
+3531	14	14
+3954	51129	50000
+1426129	160449	100025
+11087286	0	3
+773	103977	50000
+1576	0	1
+240	0	1
+318	2	0
+255	0	16
+2851	10	10
+1404	1	1
+27	1	1
+703	13	0
+375	0	1
+4783388	35000	25000
+848	0	2
+1225	0	2
+391	1	0
+3653	1	1
+28	1	1
+49	0	4
+4514	0	9
+9628	1	9
+1483	7	7
+1990	0	1
+1949	1	0
+2716230	1	0
+7799848	851	851
+38932068	5	9
+9477928	0	3
+7529698	72396	0
+1891551	294073	150000
+17672	1	0
+5792	1	0
+9017	0	266
+2944	0	1
+9388	2	0
+37828	4	0
+23436	0	4
+290931	1273578	1000000
+731068	3000000	3000000
+2558421	0	1
+1197	10	0
+685	42	46
+2309	0	1
+1332	22	23
+344	0	1
+1645	4	4
+4093	25	25
+2446	1	0
+6329	1	0
+769	0	1
+873	7	0
+1299	0	1
+8250	15	15
+4291	10626	12548
+1063	103	0
+75	0	218
+5897	1	1
+33	1	1
+9905	51	37
+1711	1	1
+45	1	1
+1597	4	4
+61	1	1
+869	13	0
+1633	15	15
+1179	3	0
+2819	0	2
+156	88	465
+100	0	25
+4753	0	8
+4903	6	6
+3847	0	2
+108126	0	145
+3542	1	0
+10276	0	1
+402	1	1
+47	1	1
+63	2	0
+583	1	1
+34	1	1
+8974	0	46
+379	1	1
+70	1	1
+2474	0	102
+1756	0	1
+8426	0	1
+11986570	151150	142000
+14207	1	1
+49	1	1
+1781	0	12
+409	1	0
+1874	1	1
+33	1	1
+4795	2	0
+3686	1	1
+15	1	1
+164	2	0
+7287	5	5
+702023	72796	150000
+69	1	0
+1598	0	1
+1340	0	1
+1030	0	4
+1166	10	10
+6406	1	1
+34	1	1
+3283	2	4
+496	1	23
+25	10	0
+40	1	1
+21282	2	1
+1406	0	44
+937	17	0
+18255	1	0
+172366	0	281526
+40517	0	406
+58864	1	2
+1843	0	2
+14994	0	1
+12992	2	0
+2571146	1	0
+35688061	108224	100000
+29671719	1	0
+39665349	1	0
+14876089	64197	20000
+401	0	3
+1831	1	1
+61	1	1
+654	11	1
+127	0	28
+116	25	29
+74	9	9
+3247	2	0
+1355	1	0
+816	1	0
+21	3	0
+526	1	1
+60	1	1
+773	1	0
+1494	1	0
+1683	1	0
+21	1	1
+596	1	0
+1582	1	0
+425	0	3
+1139	0	8
+138	144	813
+71	1	0
+385638	1	1
+219	1	1
+51	7	7
+54	15205	15205
+54	7	7
+51	1	1
+110	1	1
+5198249	0	1
+115	80	0
+60	40	0
+80	100	20
+442	1	1
+35	1	1
+119	9	129
+14	0	40
+61	1	1
+85	0	40
+1331	0	1
+1194	12	14
+1773	0	5
+1623	1	1
+25	1	1
+2422	21	22
+2315	0	1
+31	1	1
+1508	0	3
+50	0	4
+970	6	6
+7234	4	0
+1228	1	0
+1233	8	1
+4207	1	1
+41	1	1
+1715	50	50
+1532	0	2
+1714	2	0
+2299	2	0
+2143	1	1
+18	1	1
+917	1	0
+1082	1	1
+49	1	1
+9098	0	4
+5529	0	1
+3266	0	8
+894	6	0
+1440	1	1
+2095	2	0
+4179	18	13
+1785	0	1
+1674	0	6
+1217	32348	33000
+287	17	23
+40	173	0
+20	161	0
+13	66	0
+12	71	1
+12548	30000	30000
+952154	41011	25000
+1914	1	0
+225	1	1
+57	1	1
+2910	0	1
+471	1	0
+1956	1	1
+43	1	1
+991	0	92
+2863	3	0
+1838	306	0
+1006	30	0
+206	1	1
+27	0	3
+221	17	17
+1525	8	0
+413	1	1
+32	2	2
+1573	12	12
+2258676
+
+chain	8298836	2	243199373	+	90373613	90527957	chr2	242951149	+	90958828	91114560	236
+29837	32	32
+212	25	25
+508	90	90
+1291	33	33
+2574	1	0
+833	28	28
+2712	0	1
+805	10	5
+565	68	68
+75	69	57
+176	58	513
+63	105	105
+336	33	33
+69	1	0
+280	4	4
+111	12	12
+523	1	0
+136	55	56
+198	0	1
+630	0	1
+362	42	42
+405	30	30
+78	5	0
+125	5	0
+75	140	0
+166	49	49
+1653	30	30
+3790	5	5
+500	21	21
+577	23	23
+180	0	1
+1105	1	0
+231	4	4
+333	33	33
+852	2	0
+2709	16	16
+476	28	28
+53	33	57
+256	0	3
+900	0	1
+227	0	2
+718	0	2
+244	42	42
+302	30	30
+211	21	21
+1809	16	17
+204	33	32
+341	9	9
+176	0	5
+180	67	67
+73	39	39
+369	49	49
+52	9	15
+699	9	13
+142	0	4
+184	0	4
+248	27	26
+306	10	10
+63	20	20
+533	22	22
+432	86	85
+97	19	19
+383	19	23
+642	10	9
+156	88	88
+217	0	6
+1798	9	7
+425	0	4
+1191	0	4
+465	40	37
+671	7	7
+450	0	1
+714	31	32
+682	38	15
+230	28	1076
+95	220	261
+80	1967	0
+118	383	158
+81	28	2
+247	0	1
+181	0	1
+702	47	47
+361	39	39
+300	50	50
+195	9	9
+179	35	35
+228	0	10
+321	65	65
+233	20	20
+368	35	35
+1436	37	37
+985	5	5
+140	73	73
+1031	25	25
+957	51	51
+690	23	48
+1047	49	49
+186	1	0
+244	4	4
+166	16	16
+173	1	0
+387	51	51
+122	59	58
+141	1	0
+72	102	84
+75	203	201
+276	30	30
+367	20	20
+105	67	68
+82	0	1
+386	7	7
+68	61	61
+514	56	56
+92	91	91
+268	89	89
+200	4	4
+526	33	36
+370	10	10
+366	20	26
+1107	0	2
+130	74	74
+101	0	1
+542	32	34
+179	43	43
+151	84	84
+421	25	25
+332	1	0
+561	64	65
+1406	10	10
+161	97	88
+564	27	30
+123	29	33
+170	0	1
+183	94	94
+52	4	0
+379	83	83
+237	32	31
+187	46	46
+236	728	703
+50	1494	1865
+72	67	32
+25	1732	6535
+52	52	52
+104	647	648
+27	494	471
+23	0	137
+1	1884	302
+115	8	8
+76	3078	388
+26	200	44
+59	2295	2292
+40	1854	1861
+54	2541	2546
+27	28	27
+57	56	56
+26	2212	2216
+181	494	652
+42	2237	2213
+40	2572	2562
+36	1791	1791
+34	2776	2807
+23	7115	7113
+44	509	509
+36	664	665
+43	1891	2219
+36	256	256
+31	276	289
+42	881	1734
+67	149	144
+49	190	190
+73	357	345
+30	1074	1075
+42	1850	1850
+47	469	481
+24	2460	2482
+41	3325	3319
+32	306	296
+26
+
+chain	2305993	2	243199373	+	243162866	243189340	chr16	88827254	-	5000	31222	1142
+136	9	9
+870	16	16
+229	1	1
+44	1	1
+330	10	14
+243	1	1
+93	1	1
+58	1	1
+144	1	1
+62	95	95
+333	1	1
+77	1	1
+494	9	11
+230	8	8
+61	12	13
+128	14	14
+123	1	1
+68	1	1
+4208	5	1
+1989	71	0
+121	1	1
+35	1	1
+1498	59	0
+443	69	69
+237	1	1
+45	1	1
+75	1	1
+32	2	1
+20	1	1
+152	1	1
+129	0	1
+1040	1	1
+70	2	0
+128	1	1
+50	1	1
+605	9	8
+62	1	1
+155	1	1
+50	11	6
+94	1	1
+409	1	1
+34	1	1
+217	1	1
+39	1	1
+287	0	9
+102	1	1
+56	30	26
+64	108	0
+127	1	0
+373	1	1
+18	1	1
+194	1	1
+10	1	1
+98	1	1
+67	1	1
+184	1	1
+21	1	1
+86	0	1
+44	1	1
+50	15	15
+177	1	1
+72	1	1
+222	1	1
+44	1	1
+50	1	1
+46	1	1
+449	1	1
+118	1	1
+127	0	1
+242	1	1
+36	1	1
+710	4	4
+69	1	1
+87	1	1
+115	1	1
+68	17	0
+12	2	1
+14	0	12
+36	4	0
+102	1	1
+105	24	24
+131	18	18
+64	19	19
+293	1	1
+43	1	1
+134	25	25
+77	14	14
+225	1	0
+93	1	1
+363	11	11
+271	25	25
+136	1	1
+36	1	1
+102	4	4
+29	1	1
+51	2	0
+162	0	4
+61	1	0
+65	1	1
+26	4	4
+140	17	17
+336	1	1
+25	1	1
+408	16	16
+311	27	27
+90	7	7
+449	1	1
+47	1	1
+133	1	1
+62	7	7
+194	1	1
+13	3	0
+54	2	0
+28	1	1
+72	1	1
+45	1	1
+65	1	1
+23	1	1
+279	1	1
+61	1	1
+55
+
+chain	1358560	2	243199373	+	89890737	90543561	chr2	242951149	-	153539598	155537136	99
+8973	0	1
+939	0	1
+4351	0	2
+2413	1	1
+37	1	1
+515	1	0
+224	1	1
+22	1	1
+203	1	1
+18	1	1
+249	8	7
+830	4	0
+177	1	0
+30	1	1
+224	1	1
+75	1	1
+243	1	1
+20	0	5
+2724	0	137
+439	1	1
+35	1	1
+444	0	2
+1484	1	1
+41	1	1
+395	1	1
+40	1	1
+417	1	1
+44	1	1
+909	1	1
+32	24	14
+1057	2	2
+46	1	1
+306	1	1
+32	3	0
+269	10	10
+535	10	10
+615	1	1
+42	1	1
+1295	1	1
+21	1	1
+84	1	1
+30	0	1
+19	1	1
+434	57	57
+283	15	15
+304	12	12
+149	17	17
+1413	1	1
+32	1	1
+66	550910	1890523
+54	205	14
+64	147	86
+119	57	8
+71	27	96
+100	1265	73
+307	7	9
+182	31	30
+128	15	15
+95	61	59
+92	20	296
+50	77	75
+255	261	3338
+95	264	262
+204	53	55
+136	81	81
+173	62	57
+130	77	76
+241	35	35
+424	0	154
+42	3	3
+109	0	434
+68	0	59
+215	1	1
+47	1	1
+109	0	180
+10	4	0
+21	7	104
+33	31	37
+62	17	17
+114	1	1
+50	0	9
+117	9	0
+63	1	1
+92	1	1
+37	146	0
+49	956	0
+32	163	4
+37	619	0
+42	1	1
+108	973	20
+91	1	18
+215	19	19
+20	26	0
+124	56	0
+14	65	0
+65	1	1
+465	1	1
+45	1	0
+126	1	1
+46	1	1
+1501	1	1
+41	40	0
+58	2	5
+574	8	0
+830	0	5
+121	0	3
+26	0	2
+52	0	2
+183	54	0
+1069	1	1
+62	4	0
+23	1	1
+62	0	3
+233	0	2
+32	3	0
+1051	112	112
+56	26	26
+59	7	7
+588	17	18
+401	18	18
+472	1	0
+398	2	3
+249	181	22
+397	0	158
+97	42	42
+1302	24	2
+162	9	9
+740	40	40
+554	0	1
+1362	23	19
+249	12	12
+372	36	36
+987	1	0
+221	10	8
+394	9	9
+169	34	36
+170	1	1
+27	1	1
+61	1	0
+396	0	120
+152	1	13
+60	0	5
+12	1	1
+145	1	1
+51	1	1
+847	6	6
+420	1	1
+46	1	0
+43	1	1
+145	1	1
+41	1	1
+142	25	24
+332	14	14
+310	1	1
+91	1	1
+605	1	1
+47	1	1
+361	10	10
+183	0	5
+672	8	8
+76	17	20
+227	1	1
+86	1	1
+60	1	0
+30	5	5
+2399	1	1
+29	1	1
+547	10	17
+195	3	0
+609	3	0
+175	44	44
+292	8	8
+209	36	37
+543	39	39
+82	43	43
+235	38	38
+760	20	20
+502	8	0
+108	7	18
+66	2	0
+57	0	3
+88	36	36
+77	0	15
+94	24	24
+61	31	1532
+146	38	41
+92	82	77
+151	0	2606
+94	93	1000
+189	50	50
+234	100	94
+146	49	49
+189	74	74
+62	37	17
+258	30	30
+114	47	47
+494	96	98
+323	42	43
+106	20	20
+142	250	250
+161	7	7
+651	21	21
+492	237	249
+144	23	23
+88	48	48
+52	15	15
+201	6	0
+105	29	29
+68	18	18
+87	50	50
+227	147	147
+176	17	17
+404	9	9
+457	0	23
+392	41	41
+196	18	18
+99	77	80
+219	52	53
+156	0	7
+323	28	28
+99	43	42
+229	27	27
+156	107	103
+95	1	0
+1118	0	1
+282	41	41
+172	21	3
+104	26	0
+21	1	71
+54	6	76
+63	1	1
+58	1	1
+84	1	1
+285	1	1
+46	1	1
+320	15	15
+326	7	7
+170	1	1
+73	1	1
+214	1	1
+40	1	1
+613	1	0
+772	0	2
+424	1	1
+34	1	1
+423	1	1
+33	1	1
+1157	1	1
+43	2	2
+82	1	1
+21	1	1
+65	1	1
+62	1	1
+250	1	1
+79	1	1
+88	2	2
+79	1	1
+68	11	11
+115	1	1
+38	1	1
+63	9	0
+39	1	1
+73	1	1
+77	3	3
+55	1	1
+46	1	1
+157	1	1
+58	0	2
+92	1	1
+67	1	1
+48	1	1
+289	1	1
+40	1	0
+398	1	1
+31	1	1
+729	1	1
+72	1	1
+575	1	1
+86	1	1
+495	3	0
+472	1	1
+34	1	1
+87	1	0
+28	1	1
+441	20	0
+31	1	1
+61	1	1
+152	5	5
+774	0	1
+114	2	0
+355	0	3
+415	5	0
+76	1	1
+18	1	1
+308	1	1
+18	1	1
+226	4	4
+490	0	3
+104	1	1
+47	1	1
+542	6	6
+131	8	0
+152	49	1
+68	9	9
+198	1	1
+40	0	10
+78	1	1
+108	1	1
+73	1	1
+50
+
+chain	1317324	2	243199373	+	234472598	234486532	chr2	242951149	-	8801149	8815083	1658
+13934
+
+chain	1182591	2	243199373	+	111018489	111031067	chr2	242951149	-	132350497	132363075	1985
+750	1	0
+155	1	0
+2029	0	1
+2687	0	1
+2417	3	0
+3105	1	3
+965	35	36
+238	6	6
+185
+
+chain	907761	2	243199373	+	111000659	111010676	chr2	242951149	+	110060000	110070000	4064
+3405	66	54
+839	0	1
+854	33	33
+1502	180	174
+250	88	88
+1904	40	40
+856
+
+chain	864618	2	243199373	+	110991361	111000659	chr2	242951149	+	110050705	110060000	3488
+3987	37	37
+135	34	34
+2446	4	0
+1497	0	1
+1158
+
+chain	730598	2	243199373	+	111010676	111018489	chr2	242951149	+	110070000	110077815	3339
+976	16	15
+4855	0	3
+320	26	26
+1620
+
+chain	247895	2	243199373	+	111031067	111033745	chr2	242951149	-	131778891	131781575	150672
+814	1	1
+73	1	1
+148	0	6
+1211	4	4
+426
+
+chain	233678	2	243199373	+	87718206	87726480	chr2	242951149	-	151887377	151890935	691
+139	0	3
+233	4	2
+36	0	1
+291	21	13
+104	28	28
+303	26	26
+314	134	82
+86	0	1
+53	4314	721
+22	22	0
+50	389	652
+54	1133	0
+17	214	6
+79	34	60
+62	59	67
+53
+
+chain	228678	2	243199373	+	243159401	243162866	chr1	247249719	+	217390	220668	1312
+57	88	88
+22	186	0
+101	49	49
+417	53	54
+61	3	0
+141	0	1
+198	8	8
+852	39	39
+405	56	56
+61	27	27
+589	1	1
+51
+
+chain	207578	2	243199373	+	243152688	243155284	chr10	135374737	-	346	2792	2690
+533	150	0
+105	1	1
+49	1	1
+260	1	1
+69	1	1
+262	1	1
+29	1	1
+1133
+
+chain	148868	2	243199373	+	243155284	243160374	chr5	180857866	-	20000	25834	2103
+547	1	1
+38	1	1
+431	1	1
+24	1	1
+1389	1	1
+36	1	1
+1646	57	57
+82	0	744
+6	22	22
+186	101	101
+49	417	417
+53
+
+chain	147892	2	243199373	+	97920581	97932373	chr2	242951149	-	145465890	145477699	123
+1513	0	1
+2596	1	1
+36	1	1
+1383	5	1
+46	4	0
+550	1	4
+1798	7	8
+158	1	29
+18	1	1
+110	1	1
+48	1	1
+1617	7	0
+723	1063	1063
+93	1	0
+9
+
+chain	133880	2	243199373	+	87666489	111064157	chr2	242951149	-	130965951	132771520	53
+624	23366717	1774574
+2397	0	12
+14288	0	1
+1427	1	1
+24	1	1
+1756	10	10
+83	69	69
+698	0	21
+1910	1	1
+61	1	1
+3754	0	8
+243	1	1
+33	1	1
+320	0	1
+163	1	1
+36	1	1
+809	0	1
+1762	1	1
+49	1	1
+425
+
+chain	127176	2	243199373	+	5140970	5146585	chr2	242951149	-	235014747	235020583	1011815
+158	1545	1830
+107	308	308
+50	129	129
+85	163	165
+62	65	65
+282	81	63
+147	650	624
+67	138	138
+59	285	285
+76	61	62
+92	72	72
+76	266	249
+70	129	128
+83	107	102
+202
+
+chain	104115	2	243199373	+	87667113	87668206	chr2	242951149	+	87520624	87521717	786265
+1093
+
+chain	95484	2	243199373	+	87729232	87738885	chr2	242951149	+	87510347	87520000	5761
+9653
+
+chain	84057	2	243199373	+	90492917	90545103	chr2	242951149	-	152993866	153046874	435
+28	21223	21222
+38	2087	2087
+38	134	134
+40	246	246
+45	0	255
+13	0	572
+34	189	189
+50	234	234
+30	1029	1029
+47	494	494
+96	633	633
+250	1379	1379
+190	682	682
+29	173	173
+50	227	227
+147	1809	1804
+77	219	219
+52	479	479
+28	99	99
+43	229	229
+27	156	156
+107	16787	16788
+49	628	628
+1542
+
+chain	73315	2	243199373	+	87720014	87720774	chr2	242951149	-	155450797	155451557	1717423
+760
+
+chain	66981	2	243199373	+	1219529	1222202	chr2	242951149	+	1208584	1209647	1299817
+61	279	0
+275	1051	0
+115	843	563
+49
+
+chain	64603	2	243199373	+	90371566	90373613	chr2	242951149	+	90963202	90965490	370989
+76	46	46
+165	47	47
+460	75	75
+51	403	393
+63	64	364
+66	168	168
+56	68	19
+69	135	135
+35
+
+chain	46427	2	243199373	+	1223650	1226709	chr2	242951149	+	1208645	1209604	1438302
+140	630	0
+183	167	167
+210	1050	0
+171	420	0
+88
+
+chain	36623	2	243199373	+	89847430	89848295	chr5	180857866	+	153976522	153977390	3635252
+54	96	96
+262	346	349
+107
+
+chain	34396	2	243199373	+	87721616	87729232	chr2	242951149	+	87502993	87507825	13964
+67	36	543
+1013	77	25
+569	4	4
+189	715	6
+6	94	94
+389	54	54
+542	2531	33
+70	11	11
+68	21	21
+129	10	10
+126	0	22
+162	9	0
+89	28	26
+108	298	307
+116	64	12
+21
+
+chain	31906	2	243199373	+	90476997	90485104	chr2	242951149	-	155439923	155448722	818134
+65	4692	1587
+31	1167	442
+62	157	183
+65	24	24
+92	31	191
+67	10	184
+32	72	0
+76	105	36
+60	4	0
+97	52	697
+66	9	0
+169	1	23
+85	272	2102
+131	95	43
+149	89	1960
+80
+
+chain	31233	2	243199373	+	239788914	239789423	chr2	242951149	+	239454423	239454932	2214253
+173	20	20
+161	13	13
+66	12	12
+64
+
+chain	27639	2	243199373	+	243165116	243187640	chr8	146274826	+	470	67316	1215
+95	9992	9923
+69	4222	48594
+49	1	1
+58	4967	4926
+25	3019	3079
+27
+
+chain	25982	2	243199373	+	16340754	16341023	chr3	199501827	-	118072788	118073057	6523537
+269
+
+chain	25898	2	243199373	+	1220683	1220990	chr2	242951149	+	1208828	1209135	2249524
+307
+
+chain	25826	2	243199373	+	87728597	87729031	chr2	242951149	+	87491002	87491436	712257
+28	108	108
+298
+
+chain	25128	2	243199373	+	5141270	5144398	chr1	247249719	+	207689145	207692170	1456022
+66	87	87
+79	23	23
+95	979	893
+74	119	119
+116	487	487
+54	893	876
+56
+
+chain	24661	2	243199373	+	16273805	16274100	chr4	191273063	-	182882474	182882769	7289877
+128	26	26
+141
+
+chain	19295	2	243199373	+	90372486	90373577	chr2	242951149	+	90976555	90977646	1336226
+61	57	57
+56	292	292
+41	202	202
+55	193	193
+134
+
+chain	19158	2	243199373	+	1225400	1225680	chr2	242951149	+	1208855	1209065	11144872
+180	70	0
+30
+
+chain	18303	2	243199373	+	1219198	1219473	chr2	242951149	+	1208603	1208808	11853376
+134	73	3
+68
+
+chain	13465	2	243199373	+	16354747	16354888	chr5	180857866	+	167726962	167727103	16868271
+141
+
+chain	13298	2	243199373	+	89875086	89876327	chr20	62435964	+	29293186	29293377	17078580
+57	350	0
+39	320	0
+36	155	0
+6	225	0
+53
+
+chain	13261	2	243199373	+	1224140	1224280	chr2	242951149	+	1208645	1208785	17127371
+140
+
+chain	12749	2	243199373	+	5141660	5146147	chr5	180857866	-	44949635	44952639	1949230
+55	641	482
+80	490	492
+69	238	238
+34	2813	1487
+67
+
+chain	11727	2	243199373	+	240838559	240838726	chr2	242951149	+	240487433	240487623	18443158
+86	35	58
+46
+
+chain	11295	2	243199373	+	1226909	1227026	chr2	242951149	+	1209530	1209647	20202652
+117
+
+chain	11288	2	243199373	+	1223295	1223413	chr2	242951149	+	1208990	1209108	3139804
+118
+
+chain	10759	2	243199373	+	90430195	90457119	chr2	242951149	-	151338126	151363320	2584
+28	2775	2822
+30	11958	12016
+40	1843	1850
+30	5080	3227
+47	361	361
+39	312	312
+38	383	383
+35	2707	2718
+36	1130	1130
+52
+
+chain	9553	2	243199373	+	89869741	89871237	chrY	57772954	+	11913136	11913399	23867669
+64	1367	134
+65
+
+chain	9489	2	243199373	+	110253717	110253937	chr2	242951149	+	106303434	106303606	24025084
+58	106	58
+56
+
+chain	9445	2	243199373	+	1223971	1224070	chr2	242951149	+	1208756	1208855	24130758
+99
+
+chain	8720	2	243199373	+	1222223	1225291	chr2	242951149	+	1208828	1209516	2041184
+278	99	99
+79	2535	155
+77
+
+chain	8428	2	243199373	+	90482794	90485288	chr2	242951149	-	155439240	155441007	1572933
+56	44	44
+58	400	417
+31	1832	1088
+73
+
+chain	8213	2	243199373	+	87720809	87720895	chr2	242951149	+	87507349	87507434	5227216
+41	1	0
+44
+
+chain	8069	2	243199373	+	90483014	90484786	chr2	242951149	-	155448229	155461339	1164914
+45	110	127
+2	735	1564
+52	750	11246
+68	4	0
+6
+
+chain	7776	2	243199373	+	1217508	1217592	chr2	242951149	+	1207753	1207837	7243988
+84
+
+chain	7421	2	243199373	+	1226334	1226411	chr2	242951149	+	1209439	1209516	27381596
+77
+
+chain	7358	2	243199373	+	89880461	89880538	chr22	49691432	-	33895115	33895192	27502443
+77
+
+chain	7257	2	243199373	+	1219025	1219100	chr2	242951149	+	1208570	1208645	27695248
+75
+
+chain	7028	2	243199373	+	1220317	1225128	chr2	242951149	+	1208603	1209423	1749868
+42	70	0
+111	1961	0
+99	2380	420
+148
+
+chain	6973	2	243199373	+	1223223	1223295	chr2	242951149	+	1208568	1208640	27324023
+72
+
+chain	6924	2	243199373	+	1220268	1221195	chr2	242951149	+	1208974	1209200	2111755
+49	743	42
+135
+
+chain	6823	2	243199373	+	243161637	243162225	chr6	170899992	-	4262	4850	1512
+39	405	405
+56	61	61
+27
+
+chain	6757	2	243199373	+	1224280	1224350	chr2	242951149	+	1209065	1209135	28694341
+70
+
+chain	6747	2	243199373	+	1219799	1219869	chr2	242951149	+	1208645	1208715	25148698
+70
+
+chain	6633	2	243199373	+	89847849	89847926	chr14	106368585	-	28607150	28607227	5517613
+77
+
+chain	6601	2	243199373	+	239685120	239685200	chr2	242951149	+	239350340	239350540	24829287
+66	1	121
+13
+
+chain	6531	2	243199373	+	89865276	89865345	chr16	88827254	-	55053025	55053094	29215386
+69
+
+chain	6312	2	243199373	+	111004064	111004130	chr2	242951149	-	132336069	132336135	211650
+66
+
+chain	6255	2	243199373	+	1226201	1226267	chr2	242951149	+	1209586	1209652	12280449
+66
+
+chain	6049	2	243199373	+	89847131	89847195	chr1	247249719	+	184405152	184405216	30439720
+64
+
+chain	6014	2	243199373	+	89850535	89853562	chr10	135374737	-	96209116	96209251	30527518
+57	2911	19
+59
+
+chain	5970	2	243199373	+	87721480	87727902	chr2	242951149	+	87501266	87503920	375724
+136	1955	628
+417	2657	546
+67	36	27
+57	474	105
+64	294	290
+36	0	52
+229
+
+chain	5911	2	243199373	+	87725643	87726005	chr2	242951149	+	87495962	87496324	1452475
+79	29	29
+211	17	17
+26
+
+chain	5902	2	243199373	+	90476920	90476981	chr2	242951149	-	155440689	155440750	30819911
+61
+
+chain	5764	2	243199373	+	1219128	1219198	chr2	242951149	+	1208603	1208673	13156733
+70
+
+chain	5625	2	243199373	+	87727023	87727089	chr2	242951149	+	87494216	87494282	1840679
+66
+
+chain	5449	2	243199373	+	1221033	1223650	chr2	242951149	+	1208828	1209415	2333010
+27	2353	323
+237
+
+chain	5435	2	243199373	+	87725371	87725531	chr2	242951149	+	87487864	87488024	3394118
+65	44	44
+51
+
+chain	5351	2	243199373	+	243152496	243152579	chr21	46944323	-	27	110	6622
+83
+
+chain	5348	2	243199373	+	5153354	5153410	chr2	242951149	+	239297362	239297418	32407088
+56
+
+chain	5167	2	243199373	+	89830753	89830808	chr16	88827254	-	55048203	55048258	32968623
+55
+
+chain	5034	2	243199373	+	90484935	90484987	chr2	242951149	-	155462101	155462153	29809699
+52
+
+chain	5012	2	243199373	+	89872838	89872891	chr4	191273063	+	48825877	48825930	33453820
+53
+
+chain	4920	2	243199373	+	89890558	89890609	chr2	242951149	+	89623647	89623698	33788797
+51
+
+chain	4886	2	243199373	+	90477063	90477242	chr2	242951149	-	155440771	155441314	25803008
+53	75	439
+51
+
+chain	4812	2	243199373	+	89870406	89870457	chr4	191273063	+	48802771	48802822	34140093
+51
+
+chain	4757	2	243199373	+	234058786	234058836	chr13	114142980	+	90951015	90951065	34330265
+50
+
+chain	4737	2	243199373	+	5145834	5145884	chr3	199501827	-	155139362	155139412	33407240
+50
+
+chain	4647	2	243199373	+	1226779	1226827	chr2	242951149	+	1209604	1209652	34630462
+48
+
+chain	4644	2	243199373	+	111007822	111007876	chr2	242951149	-	132339823	132339877	533729
+54
+
+chain	4607	2	243199373	+	5145066	5145350	chr3	199501827	+	191348934	191349218	1967131
+93	45	45
+57	39	39
+50
+
+chain	4552	2	243199373	+	1219473	1219520	chr2	242951149	+	1208598	1208645	27324024
+47
+
+chain	4467	2	243199373	+	5146638	5146689	chr8	146274826	+	70047993	70048044	10546953
+51
+
+chain	4382	2	243199373	+	239685380	239685447	chr2	242951149	+	239350400	239350507	10821439
+47	0	40
+20
+
+chain	4286	2	243199373	+	89847926	89848007	chr18	76117153	+	56250573	56250654	7293717
+81
+
+chain	4166	2	243199373	+	90482850	90482893	chr2	242951149	-	155471295	155471338	33373631
+43
+
+chain	4069	2	243199373	+	90483640	90483682	chr2	242951149	-	155471279	155471321	32448532
+42
+
+chain	4027	2	243199373	+	89848079	89848577	chr11	134452384	-	130303828	130304326	4308822
+70	372	372
+56
+
+chain	3915	2	243199373	+	89847485	89847537	chr4	191273063	-	120181520	120181572	9841777
+52
+
+chain	3887	2	243199373	+	1222921	1225400	chr2	242951149	+	1208756	1209205	3355598
+176	2233	203
+70
+
+chain	3870	2	243199373	+	5146741	5146807	chr4	191273063	-	106282745	106282811	8233254
+2	4	4
+60
+
+chain	3851	2	243199373	+	243174715	243174760	chr1	247249719	+	80163	80208	1584
+45
+
+chain	3776	2	243199373	+	1223932	1223971	chr2	242951149	+	1208577	1208616	29100476
+39
+
+chain	3766	2	243199373	+	1225991	1226030	chr2	242951149	+	1209516	1209555	18014514
+39
+
+chain	3567	2	243199373	+	89848026	89848188	chr6	170899992	-	102513053	102513215	4544108
+53	70	70
+39
+
+chain	3456	2	243199373	+	87720895	87724286	chr2	242951149	+	87506634	87508855	332559
+59	4	143
+126	0	22
+162	9	0
+89	28	26
+108	1252	650
+77	1179	461
+298
+
+chain	3166	2	243199373	+	90482349	90482483	chr2	242951149	-	155440886	155440924	3921176
+20	96	0
+18
+
+chain	3114	2	243199373	+	1223097	1223130	chr2	242951149	+	1209002	1209035	21012522
+33
+
+chain	3110	2	243199373	+	1225750	1225960	chr2	242951149	+	1209065	1209275	3693305
+210
+
+chain	2962	2	243199373	+	16340723	16340754	chr16	88827254	+	56242121	56242152	7757072
+31
+
+chain	2946	2	243199373	+	1225580	1225611	chr2	242951149	+	1209315	1209346	16952082
+31
+
+chain	2859	2	243199373	+	243189340	243189373	chr2	242951149	-	213544	213577	2192
+33
+
+chain	2638	2	243199373	+	5146355	5146383	chr9	140273252	+	31324189	31324217	27516381
+28
+
+chain	2632	2	243199373	+	87721683	87721719	chr2	242951149	+	87489021	87489057	886310
+36
+
+chain	2630	2	243199373	+	5144933	5144985	chr19	63811651	+	23161927	23161979	24515130
+52
+
+chain	2538	2	243199373	+	16338477	16338504	chr3	199501827	-	154040818	154040845	35425972
+27
+
+chain	2527	2	243199373	+	111053817	111053884	chr2	242951149	+	110544305	110544372	1691975
+67
+
+chain	2476	2	243199373	+	5146689	5146741	chr2	242951149	-	88851718	88851770	6471285
+52
+
+chain	2465	2	243199373	+	16260450	16260476	chr14	106368585	-	56125663	56125689	35442474
+26
+
+chain	2448	2	243199373	+	90475509	90477186	chr2	242951149	-	155452726	155455668	5069202
+50	704	1477
+39	832	1324
+52
+
+chain	2256	2	243199373	+	89865421	89865445	chr4	191273063	+	48820096	48820120	35487368
+24
+
+chain	2132	2	243199373	+	90371525	90371566	chr2	242951149	+	90975643	90975684	3405316
+41
+
+chain	2046	2	243199373	+	87729180	87729211	chr2	242951149	+	87489147	87489178	2812396
+31
+
+chain	2012	2	243199373	+	16273933	16273955	chr11	134452384	+	22938127	22938149	7662326
+22
+
+chain	1994	2	243199373	+	5144152	5145822	chr11	134452384	+	133004933	133006812	2924035
+46	1530	1739
+23	20	20
+51
+
+chain	1907	2	243199373	+	5146585	5146633	chr1	247249719	-	174030724	174030772	3467396
+48
+
+chain	1894	2	243199373	+	1220990	1221013	chr2	242951149	+	1208785	1208808	13156732
+23
+
+chain	1847	2	243199373	+	87729147	87729180	chr2	242951149	+	87508312	87508345	2784752
+33
+
+chain	1616	2	243199373	+	5141194	5141259	chr4	191273063	+	140068684	140068749	14298254
+65
+
+chain	1606	2	243199373	+	89847307	89847375	chr6	170899992	+	54305106	54305174	19190580
+68
+
+chain	1373	2	243199373	+	243172974	243173045	chr8	146274826	+	8401	8472	3798112
+71
+
+chain	1350	2	243199373	+	87719705	87727637	chr2	242951149	+	87486442	87489057	666335
+5	4	8
+60	6231	0
+175	909	1819
+190	64	64
+294
+
+chain	1237	2	243199373	+	5143151	5144336	chr3	199501827	-	33955506	33956705	3724972
+50	1070	1084
+65
+
+chain	1182	2	243199373	+	1222834	1225214	chr2	242951149	+	1208599	1208809	9180420
+46	2248	78
+86
+
+chain	1157	2	243199373	+	87726368	87726988	chr2	242951149	+	87492753	87493373	434529
+59	53	53
+165	67	67
+36	57	57
+183
+
+chain	1107	2	243199373	+	5141765	5144570	chr1	247249719	+	5005582	5008225	2100127
+50	2701	2539
+54
+
+chain	1007	2	243199373	+	5142524	5142584	chr7	158821424	-	115940368	115940428	3379044
+60
+
+chain	998	2	243199373	+	234471343	234471369	chr18	76117153	+	53315026	53315052	2684166
+26
+
+chain	997	2	243199373	+	1223799	1223839	chr2	242951149	+	1209424	1209464	2284434
+40
+
+chain	932	2	243199373	+	87725722	87725751	chr2	242951149	+	87499077	87499106	1733344
+29
+
+chain	867	2	243199373	+	1226560	1226598	chr2	242951149	+	1209385	1209423	17548334
+38
+
+chain	822	2	243199373	+	5144726	5144801	chr2	242951149	-	76674151	76674226	3649555
+75
+
+chain	767	2	243199373	+	5141372	5141411	chr7	158821424	+	51905543	51905582	3310848
+39
+
+chain	651	2	243199373	+	5141336	5141372	chr5	180857866	-	59015526	59015562	2717102
+36
+
+chain	561	2	243199373	+	5140901	5140953	chr6	170899992	+	131686128	131686180	4225085
+52
+
+chain	545	2	243199373	+	90414124	90414152	chr7	158821424	-	94210194	94210222	18407154
+28
+
+chain	270	2	243199373	+	89868258	89868320	chrY	57772954	+	11916008	11916070	28746465
+62
+
+chain	5644665978	20	63025520	+	60000	62965520	chr20	62435964	+	8000	62435964	20
+26259569	3100000	1765661
+234339	150000	1000000
+4004088	1	0
+6459	244	0
+37810	2	0
+1044573	50000	20000
+9411883	8	2
+362	1	0
+11607353	1	0
+1301304	0	1
+31036	9	0
+1151	2	0
+1088	1	1
+29	1	1
+2509	2	0
+407	0	1
+40	1	1
+3787164	50000	27050
+71932	50000	110000
+694117	1	0
+1008033
+
+chain	3228736998	21	48129895	+	10697896	48119895	chr21	46944323	+	9719767	46944323	23
+490233	3150000	3050000
+19828060	1	0
+8789369	48801	0
+222468	500	500
+22014	1500	1500
+1381822	48641	0
+3438590
+
+chain	42537850	chr21	48129895	+	9411193	10647896	chr21_random	1679693	+	281005	1255172	87
+184355	489372	50000
+131056	281918	458754
+150002
+
+chain	16006699	chr21	48129895	+	9825437	10497894	chr21_random	1679693	-	0	756441	94
+158053	0	149427
+56	1	1
+500	1	1
+35	1	1
+276	1	1
+92	1	1
+413	12	12
+944	1	1
+31	1	1
+185	5	5
+93	1	1
+63	1	1
+959	0	1
+268	1	1
+33	1	1
+115	1	0
+12	0	2
+56	1	1
+99	1	1
+49	1	1
+65	1	1
+32	1	13
+425	1	1
+77	2	0
+252	0	7
+72	1	1
+96	1	1
+44	1	1
+197	7	7
+86	1	1
+32	1	1
+423	1	1
+26	1	1
+758	1	1
+77	1	1
+217	3	0
+50	1	1
+290	1	1
+112	1	1
+66	14	14
+116	18	22
+727	19	19
+140	4	0
+393	1	1
+28	1	1
+50	2	0
+38	6	1
+21	1	1
+80	1	1
+71	1	1
+179	1	1
+35	1	1
+69	1	1
+20	1	1
+216	1	1
+31	1	1
+182	1	1
+43	1	1
+97	1	1
+22	1	1
+87	1	1
+66	1	1
+72	1	1
+68	1	1
+312	1	1
+28	1	1
+478	1	1
+111	1	1
+191	1	1
+18	1	1
+98	1	2
+29	2	1
+57	1	1
+44	1	6
+74	1	1
+79	77	78
+186	1	1
+107	1	1
+202	2	2
+135	1	1
+95	0	3
+93	1	0
+48	5	0
+170	1	1
+43	1	0
+260	1	1
+23	1	1
+312	1	0
+26	1	0
+28	0	1
+87	0	10
+157	8	8
+900	1	1
+56	1	1
+235	1	1
+81	1	1
+156	1	1
+61	1	1
+156	1	1
+48	1	1
+65	12	12
+89	1	1
+158	2	2
+106	3	1
+375	0	2
+35	1	1
+73	1	1
+33	1	1
+392	2	0
+602	1	1
+66	1	1
+375	1	1
+55	1	1
+207	1	1
+25	2	2
+459	7	7
+188	1	3
+210	3	3
+28	0	4
+980	1	1
+15	1	1
+350	20	0
+636	0	4
+43	1	0
+539	63	64
+80	3	0
+142	8	7
+247	1	0
+908	1	1
+20	1	1
+128	0	1
+301	4	0
+56	2	2
+658	1	1
+34	1	1
+184	8	8
+162	0	2
+64	0	1
+80	1	1
+34	1	1
+121	1	1
+21	1	1
+374	1	1
+130	0	1
+47	1	1
+68	1	1
+35	4	0
+361	1	0
+73	1	1
+44	1	1
+392	1	1
+70	1	1
+76	1	1
+48	1	1
+216	1	1
+54	1	1
+67	4	4
+282	1	1
+44	1	1
+73	15	15
+166	4	0
+338	1	1
+27	1	1
+243	1	1
+101	1	1
+344	1	1
+51	1	1
+367	1	1
+35	0	1
+199	1	1
+18	1	1
+153	13	13
+102	0	1
+125	1	1
+49	1	1
+102	7	7
+100	18	18
+316	20	20
+151	0	2
+21	0	1
+575	1	0
+60	1	1
+60	1	1
+441	24	24
+364	1	0
+57	1	1
+158	10	10
+197	1	1
+49	1	0
+13	0	1
+5	1	1
+478	1	0
+244	22	22
+91	1	1
+80	5	5
+130	1	1
+26	1	1
+405	1	1
+51	1	1
+235	11	11
+330	1	1
+66	1	1
+85	342	17
+157	26	26
+261	1	1
+38	2	2
+824	20	20
+252	12	0
+119	1	1
+42	1	1
+1237	23	22
+103	1	1
+70	1	1
+155	1	1
+26	0	1
+80	1	1
+468	1	1
+60	1	1
+139	1	1
+53	2	2
+194	1	1
+35	1	1
+94	1	1
+56	1	1
+128	1	1
+40	1	1
+124	0	1
+54	1	1
+75	1	1
+79	1	1
+66	1	1
+82	0	1
+88	1	1
+146	0	3
+60	1	1
+67	2	2
+36	5	5
+147	1	1
+32	1	1
+185	1	1
+44	1	1
+68	40	15
+201	1	1
+37	1	1
+387	1	1
+18	1	1
+103	339913	274830
+131918
+
+chain	2365142	21	48129895	+	9686364	9760752	chr1	247249719	-	105115380	105189719	169
+453	1	1
+62	1	1
+312	9	9
+152	1	1
+34	1	1
+205	1	1
+109	44	0
+14	7	65
+203	5	5
+26	1	1
+70	1	1
+17	1	1
+847	1	1
+49	1	1
+99	1	1
+87	1	1
+51	1	1
+26	1	1
+374	1	1
+43	0	6
+139	1	1
+128	1	1
+54	1	1
+45	2	0
+17	1	1
+75	1	1
+59	1	1
+210	1	1
+70	1	1
+158	43	43
+56	12	12
+109	1	1
+48	5	5
+116	1	1
+49	1	1
+307	1	1
+45	1	1
+440	5	5
+106	9	9
+784	1	1
+42	1	1
+228	0	1
+114	17	17
+88	11	11
+161	1	1
+38	1	1
+825	2	2
+38	1	1
+105	22	22
+81	1	1
+29	1	1
+300	23	23
+147	1	1
+26	1	1
+164	1	1
+35	1	1
+227	6	6
+56	2	2
+109	1	1
+25	4	0
+116	15	23
+172	1	1
+40	1	1
+68	15	15
+158	7	7
+349	14	14
+133	1	1
+39	1	1
+145	12	12
+60	1	1
+43	1	1
+101	21	21
+307	1	1
+42	1	1
+93	1	1
+162	1	1
+143	1	1
+40	1	1
+54	1	1
+107	9	10
+319	1	1
+43	4	4
+200	1	1
+18	1	1
+127	1	1
+90	1	1
+250	3	3
+93	148	1
+443	0	1
+77	9	9
+295	1	1
+59	1	1
+438	31	31
+127	3	0
+88	1	1
+109	7	8
+79	14	14
+112	10	8
+114	1	1
+94	1	1
+150	10	7
+69	1	1
+110	1	1
+17	1	0
+222	0	1
+195	1	1
+16	1	0
+89	1	1
+123	38	0
+43	1	1
+83	1	1
+47	3	4
+64	0	3
+38	1	1
+268	1	1
+27	1	1
+230	17	17
+252	1	1
+24	0	3
+168	1	1
+41	5	0
+50	1	1
+212	9	9
+40	29	0
+271	1	1
+48	1	1
+124	1	1
+57	1	1
+125	16	16
+136	29	29
+157	1	1
+27	7	0
+482	10	4
+158	1	1
+62	1	1
+371	1	1
+83	1	1
+120	1	1
+45	1	1
+189	0	1
+84	1	1
+103	18	18
+494	1	1
+55	3	0
+139	1	1
+264	18	18
+75	2	3
+130	1	1
+97	1	1
+193	1	1
+25	1	1
+167	1	1
+49	1	1
+62	16	16
+65	13	13
+62	1	1
+101	1	1
+60	1	1
+50	1	1
+307	9	9
+131	13	13
+94	1	1
+78	1	1
+132	1	1
+27	1	1
+358	1	1
+21	1	1
+466	14	14
+590	1	1
+34	1	1
+242	1	1
+29	1	1
+116	1	1
+44	1	1
+117	1	1
+67	2	1
+71	1	1
+32	1	1
+506	18	18
+88	1	1
+27	1	1
+78	0	11
+215	1	1
+77	1	1
+291	1	1
+56	3	3
+126	1	1
+42	1	1
+332	9	9
+280	6	9
+641	15	15
+59	6	10
+31	1	1
+62	1	1
+40	1	1
+298	1	1
+40	1	1
+146	1	1
+66	1	0
+757	2	0
+169	1	1
+65	1	0
+285	1	1
+20	1	1
+109	1	1
+67	1	1
+68	1	1
+32	1	1
+93	4	4
+147	0	14
+646	0	1
+544	8	8
+47	1	0
+141	14	14
+678	1	0
+154	0	1
+346	1	1
+73	1	1
+232	5	5
+113	1	1
+32	2	0
+23	1	1
+92	10	10
+1121	1	1
+143	1	1
+300	1	1
+49	1	1
+392	5	5
+242	1	1
+21	1	1
+369	1	1
+67	1	1
+47	0	1
+618	23	23
+565	1	1
+140	1	1
+247	1	1
+41	1	1
+50	1	1
+18	1	1
+65	1	1
+66	1	1
+108	0	4
+158	1	1
+105	1	1
+70	1	1
+25	6	8
+77	1	1
+323	1	1
+28	1	1
+258	1	1
+47	1	1
+393	1	1
+72	1	1
+149	13	13
+142	1	0
+60	0	1
+78	4	4
+100	1	1
+51	1	1
+156	1	1
+20	1	1
+510	1	1
+22	1	0
+67	1	1
+54	1	1
+45	1	1
+133	1	1
+23	1	1
+63	1	1
+32	1	1
+349	1	1
+15	1	1
+103	1	1
+36	1	1
+119	1	1
+47	1	1
+312	4	4
+66	13	13
+357	0	76
+20	1	1
+177	1	1
+91	1	1
+52	1	1
+36	1	1
+141	10060	10099
+90	1	1
+49	1	1
+212	1	1
+20	1	1
+286	1	1
+48	2	1
+50	1	1
+67	8	8
+63	1	1
+30	1	1
+93	1	1
+48	1	1
+129	1	1
+46	1	1
+455	1	1
+46	3	0
+84	1	1
+39	0	1
+229	2	11
+79	4	4
+731	17	16
+725	8	8
+249	1	1
+78	1	1
+1065	3	0
+735	0	1
+124	10	10
+51	1	1
+35	1	1
+315	25	25
+749	6	6
+343	1	1
+29	1	1
+386	1	1
+24	1	1
+407	1	0
+73	1	1
+708	1	1
+71	0	1
+16	1	1
+92	1	1
+25	1	1
+447	14	14
+190	85	85
+60	1	1
+66	1	1
+238	1	1
+87	5	5
+118	7	7
+696	0	12
+49	1	1
+823	1	1
+77	1	1
+154	0	3
+102	12	12
+698	1	1
+21	1	1
+591	1	1
+16	1	1
+59	1	1
+27	1	1
+114	1	0
+593	1	1
+30	1	1
+1351	1	1
+17	1	1
+77	6	0
+647	1	1
+23	1	1
+235	1	1
+39	1	1
+141	1	1
+80	5	5
+181	10	11
+1091	1	1
+58	0	1
+19	1	1
+305	0	1
+429	17	17
+107	1	1
+25	1	1
+156	5	5
+22	1	1
+188
+
+chain	1441791	chr21	48129895	+	9645548	9775437	chr21_random	1679693	+	696416	826305	252
+40816	1341	1341
+44	2893	2893
+43	8663	8663
+148	1323	1323
+31	1767	1767
+38	1629	1629
+29	781	781
+29	25619	25619
+10060	6346	6346
+25	3590	3590
+85	9904	9904
+14685
+
+chain	891297	chr21	48129895	+	9995689	10034920	chr21_random	1679693	+	191774	231005	206
+77	9866	9866
+63	13134	13134
+342	157	157
+26	5919	5919
+40	750	750
+8857
+
+chain	2615495	chr21_gl000210_random	27682	+	0	27682	chr21_random	1679693	-	1650984	1679693	1058
+9933	367	719
+17272	0	675
+110
+
+chain	25569	chr21_gl000210_random	27682	+	10033	10300	chr21_random	1679693	-	1660317	1660584	5767478
+267
+
+chain	3320966530	22	51304566	+	16050000	51244566	chr22	49691432	+	14430000	49591432	22
+647850	150000	150000
+3661581	100000	50000
+15278437	18	0
+294	36	0
+1407	1	1
+46	1	1
+6626947	4	2
+1759	1	1
+43	1	1
+1367363	10613	11998
+7858	0	4
+809337	20	0
+6305	0	20
+6703	2669	50000
+4247674	0	10618
+1611	2719	0
+35235	131	0
+12642	0	4
+45595	9	85
+19564	506	0
+165499	7	5
+1103946	60575	16700
+644	2	0
+319796	1155	1600
+17927	15406	19700
+464629
+
+chain	11044	22	51304566	+	50772606	50772840	chr1	247249719	+	28744016	28744317	20648865
+55	103	170
+76
+
+chain	18404394637	3	198022430	+	60000	197962430	chr3	199501827	+	35000	199446827	3
+13552792	0	1
+585083	0	1
+2092	1	2
+71	0	1
+31067262	0	1
+90	1	0
+5628461	0	15
+788	1	0
+3676	0	2
+35	1	1
+4682	1	0
+1295	0	5
+437	53	42
+326	0	2
+3309	1	1
+40	1	1
+998	0	3
+3584	5	0
+930	5	7
+845	1	1
+28	2	1
+303	0	1
+507	0	5
+5088	1	0
+2185	10046	10048
+949	4	4
+35	1	1
+2874	0	1
+6717	0	1
+2823	1	0
+703	0	4
+5143	1	0
+2490	10	10
+162	7	7
+6308	0	15
+15177535	152352	260003
+2532	1	0
+1633	2	2
+24207544	3000000	4400000
+60453436	0	4
+40076813	20999	20000
+8195	1	1
+44	1	1
+1408	1	1
+33	1	1
+172	3	4
+25	1	1
+538	13	13
+173	1	1
+27	1	1
+636	1	1
+28	1	1
+470	3	3
+112	1	1
+375	1	1
+26	26	0
+115	78	0
+52	23	0
+104	26	0
+15	231	0
+56	1	1
+20	1	1
+815	16	16
+484	1	1
+49	18	0
+509	4	3
+23	1	1
+391	1	1
+44	1	1
+1278	0	4
+32	1	1
+263	4	0
+27	1	1
+2416	0	2
+3184	43	43
+1150	13	13
+736	1	1
+47	1	1
+1416	1	1
+20	1	1
+1020	1	1
+25	1	1
+482	5	0
+716	1	0
+1697	1	1
+29	1	1
+1270261	23108	27000
+40930	1	0
+17455	1	1
+28	4	4
+43	0	491
+1679	1	1
+33	7	5
+29	1	3
+54863	53	16
+7653	2	2
+29	2	2
+15	0	30
+180	0	75
+215	45	0
+360	915	0
+6188	96	0
+17	288	0
+1388	1	1
+37	1	1
+7956	0	1
+374	0	1
+2442058
+
+chain	905554	3	198022430	+	50925386	50935027	chr3	199501827	-	148591827	148601470	3167
+1111	0	6
+2584	0	1
+5889	6	1
+51
+
+chain	274603	3	198022430	+	195356374	195379482	chr3	199501827	-	629997	657219	690
+621	1	1
+42	1	1
+893	1	121
+66	1	1
+693	1	1
+27	1	1
+761	1	1
+79	2	2
+297	1	1
+40	1	1
+643	1	1
+22	1	1
+410	8	9
+110	1	1
+16	0	5
+314	3	0
+1846	4	7
+39	1	1
+420	10	9
+335	6	0
+238	0	1
+76	1	0
+310	1	2
+175	1	1
+17	1	1
+268	1	1
+46	1	1
+114	1	1
+19	1	1
+127	8	8
+30	1	1
+207	6	6
+62	9	9
+505	22	22
+160	1	1
+34	1	1
+187	1	1
+138	0	1
+844	1	1
+103	0	1
+65	3459	3402
+90	4	4
+90	42	794
+52	478	4
+78	154	154
+28	235	0
+59	1501	5454
+143	19	19
+425	7	54
+39	46	0
+75	8	8
+73	1	95
+58	1	1
+51	16	63
+140	1	1
+33	1	1
+682	1	1
+68	1	1
+147	1	1
+82	1	1
+119	33	0
+262	0	1
+54	1	0
+13	56	0
+111	5	5
+722	1	1
+19	1	1
+60	1	1
+33	1	0
+7	1	1
+108	0	2
+302	1	1
+68	1	0
+42	1	1
+50	1	1
+80	1	0
+95	1	1
+19	1	1
+119	0	1
+493	16	16
+316
+
+chain	30227	3	198022430	+	66156466	66156782	chr5	180857866	-	15729243	15729559	4617547
+316
+
+chain	25764	3	198022430	+	195503126	195503723	chr3	199501827	+	196988790	196989012	1952307
+75	360	0
+127	20	5
+15
+
+chain	19039	3	198022430	+	195503723	195504023	chr3	199501827	+	196988637	196988937	1894839
+300
+
+chain	11786	3	198022430	+	195373997	195374119	chr3	199501827	-	651916	652038	19355983
+122
+
+chain	9624	3	198022430	+	195503246	195503561	chr3	199501827	+	196988205	196988400	2003832
+53	137	2
+73	4	19
+48
+
+chain	7908	3	198022430	+	195510214	195510615	chr3	199501827	+	196993313	196993714	919394
+96	17	17
+288
+
+chain	6921	3	198022430	+	66275488	66275560	chr6	170899992	+	144236219	144236291	28346484
+72
+
+chain	6012	3	198022430	+	66274973	66275036	chr15	100338915	-	38411650	38411713	30540003
+63
+
+chain	5039	3	198022430	+	66276813	66276866	chr9	140273252	+	71084115	71084168	33364454
+53
+
+chain	4902	3	198022430	+	66152713	66152764	chr11	134452384	+	5803379	5803430	33869306
+51
+
+chain	3381	3	198022430	+	195371524	195371562	chr3	199501827	-	645118	645156	13662757
+38
+
+chain	3356	3	198022430	+	50925108	50925187	chr3	199501827	-	92152745	92152824	20266108
+79
+
+chain	2109	3	198022430	+	195371614	195371638	chr3	199501827	-	645161	645185	16027164
+24
+
+chain	1800	3	198022430	+	195503201	195503246	chr3	199501827	+	196989165	196989195	4219824
+23	17	2
+5
+
+chain	1295	3	198022430	+	195372257	195372308	chr3	199501827	-	2286585	2286636	21843906
+51
+
+chain	17653654354	4	191154276	+	10000	191029082	chr4	191273063	+	0	191263063	4
+1413146	71672	51000
+5369	6	5
+65	1	1
+67	1	1
+425	1	1
+32	1	1
+175	1	1
+34	1	1
+5092	1	1
+46	1	1
+1396	15	15
+1446	1	0
+1679	13	13
+3443	0	1
+586	1	1
+38	1	1
+18	21	0
+1582	6	0
+202	3	0
+92	0	6
+187	9	0
+4054	1	1
+71	1	1
+1413	1	83
+51	7	7
+105	7	7
+53	0	41
+81	1	42
+41	0	41
+37	0	41
+3274	1	94
+114	0	1116
+921	2	0
+935	0	55
+3639	15	15
+1167	0	3
+44	29	0
+44	0	29
+5146	1	1
+42	1	1
+3831	3	0
+23	1	1
+4171	6	6
+796	165	0
+196	99	0
+94	33	0
+183	8	6
+107	2	2
+21	2	0
+62	68	1
+32	15	14
+81	18	18
+55	1	0
+17	67	1
+188	133	0
+44	67	0
+43	35	0
+3289	18	18
+298	1	0
+373	1	0
+2965	1	1
+30	23	0
+1718	38	0
+98	38	0
+53	44	7
+116	0	77
+272	1	1
+70	1	1
+1591	49	49
+360	33	23
+2400	1	1
+94	1	1
+6002	1	1
+16	1	1
+776	0	1
+324	46	46
+433	0	51
+53	27	1
+2181	4	1
+57	1	1
+1969	0	10
+4188	11	11
+1595	18	0
+2050	109	0
+4319	7	0
+50	4	0
+1464	1	3
+4156	0	2
+5455	2	3
+129	4	4
+9082	1	0
+786	20	20
+1506	1	0
+252	7	8
+17512	1	50
+56	0	1
+2474	52	69
+75	30	0
+61	0	16
+11	0	15
+41	1	1
+133	0	16
+79	17	0
+16	29	0
+3375	1	0
+969	4	0
+1623	11	11
+1065	3	0
+2934	0	8
+2323	181	0
+2290	0	1
+1641	1	6
+1955	1	0
+68	1	1
+347	1	1
+40	1	1
+1553	0	6
+678	16	16
+92	33	0
+390	0	4
+1147	1	0
+1948	4	4
+4296	1	1
+16	1	1
+955	1	1
+47	1	1
+1555	0	1
+2251509	0	81122
+171	1	1
+48	1	1
+718	0	1
+2789	1	1
+27	1	1
+1601	0	4
+1907	2	0
+31	1	5
+16	0	4
+76	2	0
+13	4	0
+27	1	0
+12	1	9
+1772	6	0
+22	1	1
+946	1	1
+24	1	1
+1245	0	1
+3231	1	1
+41	1	1
+736	4	4
+912	1	1
+18	1	1
+11270	0	3
+2704	1	1
+41	1	1
+1812	6	5
+1477	11	0
+1744	6	6
+2039	0	4
+2188	1	1
+48	1	1
+1704	1	1
+73	1	1
+2265	12	12
+553	1	1
+49	1	1
+67	1	1
+33	1	1
+3935	0	5
+15	0	1
+780	1	0
+1260	1	0
+4204	25	0
+862	14	14
+7114	1	1
+70	1	1
+169	1	0
+43	1	1
+145	1	1
+39	3	0
+8	1	1
+753	1	0
+1535	41	41
+679	1	1
+21	1	1
+1605	1	1
+19	1	2
+392	1	1
+29	0	1
+3673	0	1
+145	14	14
+39	1	0
+1246	1	0
+2302	0	1
+1554	9	9
+4537	1	0
+1064	0	2
+2051	0	1
+1130	2	0
+164	0	1
+1972	1	0
+18	3	3
+2597	1	1
+46	3	3
+196	1	1
+17	1	1
+60	4	4
+187	4	4
+46	1	1
+692	0	1
+3382	41	41
+497	3	3
+15	1	1
+486	14	14
+1709	0	8
+169	0	1
+597	1	1
+18	7	0
+3423937	1	0
+1295496	1	1
+26	1	1
+760	591802	150000
+22468468	1	1
+27	1	1
+2592	2	0
+33	1	1
+2065	0	3
+1050	11	11
+1046	9	3
+3263	0	1
+906	0	1
+1643	0	6
+1181	1	0
+475	5	0
+2522	0	4
+407	1	0
+517	77	77
+1122	36199	70999
+976587	26528	59000
+7703	4	0
+4545	9	9
+4740	1	0
+1862	0	1
+3316	3	7
+51	14	14
+1066	1	0
+1795	0	1
+569	0	1
+2895	1	1
+39	1	1
+461	0	3
+3168	6	6
+2197	0	1
+6774	2	0
+2504	2	0
+1247	1	1
+45	1	1
+2415	17	17
+4792	36	36
+3387	20	20
+272	10	10
+420	1	1
+34	1	1
+7961	0	4
+1973	1	1
+45	0	1
+529	0	1
+603	1	0
+18	1	1
+606	4	0
+65	1	25
+41	0	8
+517	1	0
+1400	41	38
+3786	1	0
+228	0	3
+1026	1	1
+49	1	1
+3336	3	0
+951	1	1
+77	1	2
+441	2	1
+1833	9	9
+301	5	5
+2787	17	17
+1747	0	1
+3040	9	2
+81	10	10
+86	0	2
+2113	45	45
+7352791	1606	20000
+1651	0	2
+45	16	0
+13956	8	0
+1947	3	0
+1255	1	1
+38	1	0
+1778	4	0
+22	1	0
+1045	0	6
+1327	1	0
+5775	1	1
+18	1	1
+1933	0	1
+1716	13	13
+255	0	1
+124	3	0
+792	5	0
+1521	1	1
+64	1	1
+9005617	150000	150000
+171176	3000000	3000000
+7074452	62111	50000
+5257	1	0
+2845	0	2
+1387	1	0
+114	0	1
+2385	4	0
+65	6	6
+62	0	4
+18	1	0
+100	51	0
+9781577	0	351994
+1903288	0	184275
+3925704	13	13
+435	1	1
+21	1	1
+838	1	0
+281	35	35
+491	6	6
+74	1	1
+43	1	1
+652	29839	30000
+13847966	1	0
+14069801	0	2
+8504	1	0
+32265	0	8
+12730	2	0
+35327	14	12
+1503	0	1
+1334	0	1
+759	1	0
+10036	1	7
+9912	17	18
+2523	0	1
+1321	1	0
+8984	0	2
+5505	20	20
+9694	6	6
+22003	0	9
+578	1	0
+5166	0	2
+92208	5	2
+8	0	1
+5	2	0
+110	0	4
+848	7	6
+2247	1	3
+3770	1	0
+5719	2	0
+2511	1	0
+1557	1	0
+5812	1	0
+3607	1	0
+7405	0	1
+11075	1	0
+2794	0	1
+2340	0	1
+429	1	0
+233	27	27
+262	0	2
+2397	0	5
+371	0	11
+1376	0	1
+2416	0	8
+210	1	1
+20	1	1
+5104	1	1
+20	1	1
+525	0	2
+836	1	0
+2094	0	1
+2213	0	3
+327	6	9
+1711	45	45
+837	1	1
+57	1	1
+1618	1	0
+1400	0	4
+254	2	0
+93	0	10
+755	6	0
+192	1	0
+2378	1	0
+1753	0	3
+644	14	14
+1244	4	0
+30	1	1
+1136	14	14
+2450	0	4
+3624	3	31
+456	14	14
+1076	8	7
+68	1	1
+20	1	1
+145	1	1
+68	0	1
+12	1	0
+10	1	0
+11	0	1
+35	0	1
+5	1	0
+11	2	1
+32	7	6
+35	0	1
+8722	0	1
+888	4	0
+456	0	3
+45	1	0
+151	13	13
+756	1	0
+203	7	8
+140	1	1
+20	1	1
+308	0	5
+1020	1	0
+1258	1	0
+160	2	0
+1411	1	1
+22	1	1
+1180	12	12
+4521	2	0
+1153	0	27
+4956	0	3
+1392	1	1
+47	1	1
+3854	1	2
+130	0	1
+2633	0	2
+3030	1	0
+2343	1	0
+1748	45	0
+731	0	2
+1336	11	9
+3899	6	0
+436	0	1
+981	1	0
+1326	1	0
+382	0	4
+1081	0	10
+81	1	1
+142	2	0
+5976	1	1
+26	1	1
+377	22	22
+86	1	0
+55	1	1
+93	1	1
+374	4	0
+38	6	0
+3944	0	347
+1034	1	1
+27	1	1
+60	0	2
+2581	0	3
+3882	4	0
+1790	1	0
+20	1	1
+356	0	1
+4244	5	5
+36	1	1
+2232	2	2
+42	1	1
+4462	2	0
+1611	0	1
+1290	2	0
+110	0	1
+1466	1	0
+357	0	3
+850	0	12
+13547766	1	0
+3724943	0	2
+46473408	1	0
+1696	1	1
+28	1	1
+1629	4	0
+666	0	4
+13464	12874	30000
+8520008	0	2
+1107	1	1
+15	1	1
+1892	4	0
+6798	2	0
+1793	1	1
+25	3	0
+421	0	389
+787	0	2
+545	2	0
+54	0	1
+143	1	1
+39	1	1
+89	1	1
+29	0	1
+171	1	1
+46	0	1
+192	1	1
+33	1	1
+336	18	18
+2226	1	0
+107	1	1
+29	1	1
+218	0	1
+175	5	6
+1407	1	1
+52	1	1
+8851	0	1
+14427	0	4
+1737	0	22
+5806	0	1
+1115	1	1
+29	2	0
+3395	1	0
+386	38	38
+2740	2	0
+522	0	1
+24	1	1
+658	0	4
+5724	9	9
+1209	1	0
+5380	0	1
+97	0	1
+853	0	4
+79	11	5
+2728	7	6
+3754	13	17
+1363	0	1
+1025	0	1
+1811	1	0
+7507	4	0
+1184	0	3
+763	0	1
+797	0	3
+293	0	2
+2488	1	0
+335	1	0
+9959	0	1
+3255	0	1
+1322	1	0
+8118	0	2
+3326	0	2
+632	0	1
+63	5	0
+1886	12	12
+1110	1	0
+9582	1	0
+14742673	3013	0
+39686
+
+chain	9245037	chr4	191154276	+	8829368	8925617	chr4_random	842648	+	239789	336038	353
+96249
+
+chain	1255876	4	191154276	+	9214880	9257600	chr4	191273063	+	8933741	8943231	721
+156	22	22
+1030	14	14
+303	27	27
+166	4935	184
+220	23	24
+72	54	54
+771	13	13
+270	4744	0
+2627	17	17
+289	4743	0
+890	4745	0
+772	9500	0
+268	4749	1
+266	11	11
+1023
+
+chain	912330	4	191154276	+	9211690	9265763	chr4	191273063	+	8940042	8979863	947
+75	220	220
+51	122	122
+54	54	54
+51	167	167
+180	47	47
+70	24	24
+94	37	37
+257	59	59
+316	11	11
+163	60	60
+53	61	61
+95	21	21
+109	24	24
+217	32	32
+186	47	47
+233	1926	1924
+88	13	13
+123	125	126
+1453	4747	0
+2227	0	1
+278	535	535
+213	87	87
+92	7	7
+755	18715	9222
+268	6439	6434
+1089	14	14
+243	9	9
+78	4	4
+157	214	209
+200	23	24
+72	5972	5972
+655	413	413
+1441	14	14
+243	9	9
+78	4	4
+157	213	209
+200	23	24
+72	54	54
+771	13	13
+119	17	17
+221
+
+chain	676976	4	191154276	+	191033807	191044200	chr4	191273063	-	191263147	191273063	1558
+68	4	0
+34	1	1
+323	3	3
+31	1	1
+807	1	1
+26	1	1
+526	2	3
+34	1	0
+704	1	0
+6	1	0
+240	1	0
+237	2	0
+8	1	1
+371	10	0
+264	1	0
+205	1	1
+57	1	0
+601	1	1
+15	1	1
+1214	4	8
+1661	3	0
+94	1	1
+50	1	1
+355	15	15
+638	1	1
+54	1	1
+54	8	9
+323	67	9
+85	0	1
+96	1	1
+58	1	1
+35	1	0
+31	1	1
+86	1	1
+30	1	1
+76	1	1
+40	1	1
+121	282	27
+49	53	0
+63	92	0
+52
+
+chain	512088	4	191154276	+	8956990	9037962	chr4	191273063	+	9100119	9179836	26299
+71	118	113
+60	152	152
+88	33	33
+136	71	71
+85	43	43
+87	66	66
+92	87	87
+88	187	185
+156	1	81
+67	128	129
+76	143	143
+50	44	44
+212	52	52
+64	13	16
+267	79	79
+284	58	58
+51	76	76
+51	94	91
+55	77	77
+95	15	15
+74	251	251
+116	107	28
+64	188	188
+77	4	4
+113	11	11
+62	44	44
+102	237	237
+154	79	79
+58	86	86
+53	39	39
+50	36	35
+412	36	36
+75	225	225
+313	30	30
+54	84	83
+69	156	147
+104	89	77
+54	162	162
+226	16	16
+95	26	26
+60	14	14
+59	8	8
+120	7	7
+162	67	67
+65	210	210
+112	204	203
+63	53	53
+50	140	139
+127	143	143
+149	97	97
+88	61282	60044
+56	370	381
+50	56	56
+84	370	368
+52	288	288
+54	25	25
+72	923	933
+55	768	765
+68	70	70
+52	196	196
+62	305	305
+50	43	43
+129	114	114
+53	66	65
+116	411	423
+58	314	324
+68	0	1
+123	0	1
+53	58	59
+116	401	399
+539	6	0
+397	18	18
+60	211	211
+55	175	175
+63	553	556
+55	10	10
+53	1024	1003
+58	34	34
+81	43	43
+75	9	9
+51	1	0
+69
+
+chain	476298	4	191154276	+	9230645	9271936	chr4	191273063	+	8940012	8967053	893
+192	87	88
+429	187	187
+754	4750	6
+744	23	25
+2003	14	14
+246	42	42
+74	48	48
+71	104	104
+291	226	226
+81	4533	4529
+47	562	562
+111	285	285
+89	35	35
+2637	17	17
+240	9	9
+78	4	4
+157	215	209
+179	17	17
+100	4802	54
+343	13	13
+785	10920	6171
+1114	17	17
+243	6	6
+58	2	1
+272	1	0
+404	10	10
+1194	31	31
+266	11	11
+770	21	21
+327
+
+chain	377656	4	191154276	+	9257600	9267189	chr4	191273063	+	8933740	8938580	708
+1209	17	17
+571	1	0
+1617	4779	31
+1395
+
+chain	310844	4	191154276	+	9241835	9252105	chr4	191273063	+	8941714	8947231	850
+2726	14	14
+243	9	9
+78	4	4
+157	213	211
+265	85	85
+524	4751	0
+379	283	283
+539
+
+chain	275688	4	191154276	+	190986479	190989396	chr4	191273063	+	191223755	191226674	1129
+58	2	0
+265	1	0
+205	0	1
+208	4	5
+205	1	0
+122	55	53
+54	0	1
+411	25	25
+282	1	0
+419	14	20
+585
+
+chain	164691	4	191154276	+	9225860	9240813	chr4	191273063	+	8954210	8973910	1376
+232	87	87
+216	5946	5946
+93	12	12
+116	46	46
+231	32	32
+884	2511	7257
+718	3769	3770
+60
+
+chain	136190	4	191154276	+	9219745	9221340	chr4	191273063	+	8971822	8973417	7780
+1090	14	14
+243	9	9
+78	80	80
+81
+
+chain	127110	4	191154276	+	9223074	9241806	chr4	191273063	+	8960913	8979648	1585
+266	11	11
+4	10400	10401
+206	20	21
+668	26	27
+395	17	17
+14	6682	6682
+23
+
+chain	113888	4	191154276	+	59794841	59796661	chr7	158821424	+	43068053	43069865	1124766
+203	13	13
+161	140	141
+116	42	42
+240	178	178
+142	63	63
+254	11	11
+90	67	58
+100
+
+chain	91306	4	191154276	+	9218608	9227700	chr4	191273063	+	8961194	8975031	2525
+1019	3329	8072
+118	4492	4494
+89	35	35
+10
+
+chain	70288	4	191154276	+	9018276	9021043	chr11	134452384	-	130908986	130911761	1790585
+117	359	362
+150	330	330
+55	237	237
+99	73	73
+100	253	253
+70	73	78
+137	311	312
+72	249	248
+82
+
+chain	69967	4	191154276	+	8969559	8971297	chr11	134452384	-	66940622	66942298	1798470
+59	244	176
+78	49	49
+76	0	4
+72	217	218
+85	102	102
+264	12	12
+52	246	247
+66	24	24
+92
+
+chain	66013	4	191154276	+	9271936	9272654	chr4	191273063	+	8948073	8948792	572417
+692	0	1
+26
+
+chain	45624	4	191154276	+	9079872	9084019	chr4	191273063	-	187198263	187202501	2810559
+137	1640	1673
+114	79	83
+52	281	281
+64	700	698
+99	226	253
+83	576	605
+96
+
+chain	42774	4	191154276	+	9272654	9274373	chr4	191273063	+	8958282	8960000	1428
+395	17	17
+243	6	6
+329	3	2
+726
+
+chain	41852	4	191154276	+	9086638	9087081	chr1	247249719	-	105679719	105680162	3102182
+443
+
+chain	32596	4	191154276	+	9003477	9005348	chr8	146274826	+	6937943	6939835	4188535
+92	357	358
+96	443	443
+52	521	541
+122	129	129
+59
+
+chain	27953	4	191154276	+	9001038	9001387	chr11	134452384	-	130891915	130892264	5650797
+153	24	24
+85	11	11
+76
+
+chain	25460	4	191154276	+	1547039	1548332	chr4	191273063	+	1517808	1518962	1406869
+132	196	194
+8	33	0
+58	94	94
+33	400	430
+53	219	85
+67
+
+chain	23919	4	191154276	+	9060276	9060815	chrX	154913754	-	61464264	61464816	7738233
+150	249	262
+51	8	8
+81
+
+chain	23663	4	191154276	+	9250380	9252971	chr4	191273063	+	8954996	8957588	1596
+343	1382	1382
+494	21	21
+330	20	21
+1
+
+chain	23348	4	191154276	+	8954155	8955149	chr13	114142980	+	67377165	67378170	8084807
+108	119	119
+58	448	459
+78	128	128
+55
+
+chain	23051	4	191154276	+	9178657	9179321	chr8	146274826	-	138181840	138182484	8260527
+67	301	281
+58	86	86
+152
+
+chain	21854	4	191154276	+	9064978	9065877	chr1	247249719	+	159299736	159300622	9096955
+140	389	376
+61	239	239
+70
+
+chain	20302	4	191154276	+	59794670	59795934	chr19	63811651	-	51831683	51832948	1313667
+101	447	447
+6	69	70
+65	116	116
+17	4	4
+21	351	351
+67
+
+chain	19591	4	191154276	+	9123525	9124535	chr8	146274826	-	133912952	133913964	10789494
+68	696	699
+88	66	65
+92
+
+chain	17609	4	191154276	+	9152849	9153208	chr8	146274826	-	133934464	133934826	12466518
+149	157	160
+53
+
+chain	17420	4	191154276	+	9097653	9099623	chr11	134452384	-	51628045	51630034	12637575
+61	831	818
+58	894	926
+126
+
+chain	17154	4	191154276	+	8944061	8944687	chr3	199501827	-	68270290	68270918	12891537
+94	361	363
+56	52	52
+63
+
+chain	16449	4	191154276	+	9179756	9180625	chr8	146274826	+	7630543	7631403	13585678
+50	232	222
+54	427	428
+106
+
+chain	16159	4	191154276	+	9066614	9068459	chr16	88827254	-	83675354	83677175	13878826
+62	1020	1018
+99	597	575
+67
+
+chain	16115	4	191154276	+	9109381	9109952	chr21	46944323	+	28460282	28460853	13923553
+84	119	119
+62	249	249
+57
+
+chain	15306	4	191154276	+	8980490	8981996	chr4	191273063	-	187061282	187061823	14745791
+66	1267	302
+72	36	36
+65
+
+chain	15299	4	191154276	+	9056645	9056806	chr7	158821424	-	61471183	61471344	14752363
+161
+
+chain	14776	4	191154276	+	8950227	8950452	chr10	135374737	-	120304145	120304370	15312555
+84	55	55
+86
+
+chain	14403	4	191154276	+	9126194	9127408	chr5	180857866	-	26856190	26857401	15732261
+94	264	256
+54	752	757
+50
+
+chain	14224	4	191154276	+	8969618	8970298	chr11	134452384	-	67220551	67221216	1931088
+4	94	93
+78	397	383
+107
+
+chain	14155	4	191154276	+	9145781	9146043	chrX	154913754	-	45908091	45908403	16013758
+81	98	148
+83
+
+chain	14099	4	191154276	+	9060197	9060675	chr3	199501827	+	53477967	53478452	7798477
+58	172	171
+90	137	145
+21
+
+chain	13997	4	191154276	+	9005833	9006439	chr8	146274826	-	139204211	139204817	16201090
+60	438	438
+108
+
+chain	13823	4	191154276	+	8945988	8946280	chr4	191273063	+	9373057	9373350	16411372
+60	133	134
+99
+
+chain	13439	4	191154276	+	8975637	8975779	chr3	199501827	+	126919507	126919649	16900342
+142
+
+chain	12765	4	191154276	+	9077064	9077200	chr1	247249719	-	177698311	177698447	17836871
+136
+
+chain	12497	4	191154276	+	8950452	8951505	chr4	191273063	-	187091946	187092996	17010995
+3	953	950
+97
+
+chain	12348	4	191154276	+	8983189	8983604	chr8	146274826	-	138673776	138674197	18460871
+61	268	274
+86
+
+chain	11880	4	191154276	+	8972496	8973020	chr14	106368585	-	55089898	55090495	19186930
+61	378	451
+85
+
+chain	11818	4	191154276	+	9096126	9096305	chr11	134452384	-	67086036	67086266	19295429
+55	42	93
+82
+
+chain	11496	4	191154276	+	8948423	8949198	chr12	132349534	+	50778185	50778960	19846856
+94	629	629
+52
+
+chain	11391	4	191154276	+	8947143	8947401	chr8	146274826	-	134472454	134472711	20027902
+53	123	122
+82
+
+chain	11111	4	191154276	+	9107828	9107946	chr16	88827254	+	2897686	2897804	20531108
+118
+
+chain	10916	4	191154276	+	9261701	9262066	chr4	191273063	+	8952078	8952443	1072
+365
+
+chain	10832	4	191154276	+	8994164	8994326	chr6	170899992	-	100664994	100665156	21051510
+55	36	36
+71
+
+chain	10756	4	191154276	+	8943247	8943361	chr4	191273063	+	9116977	9117091	21193988
+114
+
+chain	10679	4	191154276	+	191030273	191030443	chr3	199501827	+	127002379	127002551	21342971
+68	44	46
+58
+
+chain	10668	4	191154276	+	1582572	1582681	chr4	191273063	+	1552756	1552865	12282737
+109
+
+chain	10529	4	191154276	+	191032229	191032410	chr11	134452384	+	3430296	3430477	21654608
+64	55	55
+62
+
+chain	10273	4	191154276	+	9096703	9097008	chr3	199501827	+	187858881	187859186	22199926
+64	181	181
+60
+
+chain	10137	4	191154276	+	9099965	9100095	chr6	170899992	-	166526436	166526567	22497437
+61	12	13
+57
+
+chain	10052	4	191154276	+	9066676	9066805	chr10	135374737	-	108696851	108696974	16846521
+41	9	9
+20	6	0
+53
+
+chain	9949	4	191154276	+	8999157	8999260	chr6	170899992	+	1823421	1823524	22925909
+103
+
+chain	9823	4	191154276	+	9071238	9072065	chr19	63811651	-	22299002	22299820	23218142
+65	697	688
+65
+
+chain	9746	4	191154276	+	8950613	8951219	chr7	158821424	-	151976579	151977185	23399634
+66	481	481
+59
+
+chain	9713	4	191154276	+	9012936	9013126	chrX	154913754	+	119487462	119487653	23485630
+58	74	75
+58
+
+chain	9679	4	191154276	+	9083038	9083589	chr12	132349534	+	77527128	77527707	10056562
+24	185	212
+17	262	263
+63
+
+chain	9579	4	191154276	+	9105290	9105637	chr8	146274826	-	6609	6954	23801877
+63	229	227
+55
+
+chain	9552	4	191154276	+	8956536	8957179	chr8	146274826	-	139187457	139188099	13944787
+92	234	234
+51	240	239
+26
+
+chain	9532	4	191154276	+	8978497	8978597	chr21	46944323	-	3695413	3695513	23932747
+100
+
+chain	9412	4	191154276	+	9108273	9108605	chr2	242951149	+	34780701	34781033	24211634
+61	216	216
+55
+
+chain	9361	4	191154276	+	9207159	9207725	chr7	158821424	+	92958588	92959148	24306771
+65	445	439
+56
+
+chain	9304	4	191154276	+	8946418	8946780	chr13	114142980	+	45938942	45939304	24422281
+63	247	247
+52
+
+chain	9136	4	191154276	+	9129485	9129655	chr1	247249719	-	82404984	82405154	24736407
+59	59	59
+52
+
+chain	9105	4	191154276	+	8982741	8983189	chr10	135374737	-	120304868	120305301	22041837
+59	380	365
+9
+
+chain	8777	4	191154276	+	9118310	9118402	chr11	134452384	-	67092191	67092283	25280535
+92
+
+chain	8617	4	191154276	+	59794359	59794524	chrX	154913754	+	69736929	69737094	2995761
+75	86	86
+4
+
+chain	8389	4	191154276	+	9219628	9219725	chr4	191273063	+	8933741	8933838	871949
+97
+
+chain	8260	4	191154276	+	8989895	8989983	chr4	191273063	+	9362532	9362620	26013719
+88
+
+chain	8131	4	191154276	+	9102626	9102711	chr4	191273063	-	187087880	187087965	26219988
+85
+
+chain	7754	4	191154276	+	190986383	190986479	chr10	135374737	+	135327923	135328019	562
+96
+
+chain	7688	4	191154276	+	8999849	9001530	chr8	146274826	+	7459813	7461495	7287525
+76	15	15
+50	236	236
+59	1157	1158
+88
+
+chain	7445	4	191154276	+	1642823	1642928	chr4	191273063	+	1612696	1612801	10569689
+105
+
+chain	7390	4	191154276	+	9235101	9235376	chr4	191273063	+	8934980	8935255	884
+275
+
+chain	6985	4	191154276	+	9132536	9132609	chr10	135374737	+	82556085	82556158	28236044
+73
+
+chain	6957	4	191154276	+	9079830	9084724	chr8	146274826	-	133860764	133864463	3584848
+42	1125	1126
+68	534	536
+50	1109	1111
+56	1741	541
+169
+
+chain	6924	4	191154276	+	9086283	9086357	chr3	199501827	+	28200221	28200295	17749225
+74
+
+chain	6522	4	191154276	+	59794524	59794670	chr4	191273063	+	131104023	131104168	2551460
+51	42	41
+53
+
+chain	6459	4	191154276	+	191029213	191029282	chr11	134452384	-	63299390	63299459	29377341
+69
+
+chain	6349	4	191154276	+	8971797	8971864	chr9	140273252	+	68477506	68477573	29649127
+67
+
+chain	6310	4	191154276	+	1548554	1548645	chr4	191273063	+	1518821	1518912	10939184
+91
+
+chain	6297	4	191154276	+	59793454	59794143	chr3	199501827	-	40571037	40571724	2330420
+79	562	560
+48
+
+chain	6221	4	191154276	+	9064020	9064085	chr16	88827254	-	83673859	83673924	29990023
+65
+
+chain	6094	4	191154276	+	9110081	9110145	chr1	247249719	+	181849295	181849359	30306899
+64
+
+chain	6086	4	191154276	+	191030472	191030537	chr11	134452384	-	75925756	75925821	30317869
+65
+
+chain	5966	4	191154276	+	9104473	9104535	chr11	134452384	+	71003965	71004027	30644952
+62
+
+chain	5912	4	191154276	+	8947661	8947723	chr9	140273252	-	2802727	2802789	30796182
+62
+
+chain	5903	4	191154276	+	9101296	9101358	chr4	191273063	+	9087606	9087668	30814689
+62
+
+chain	5842	4	191154276	+	9036574	9036668	chr4	191273063	-	85960898	85960992	17872768
+94
+
+chain	5712	4	191154276	+	9132160	9132220	chr12	132349534	+	8264132	8264192	31330015
+60
+
+chain	5710	4	191154276	+	191042876	191042934	chr4	191273063	-	191272139	191272197	15878613
+58
+
+chain	5622	4	191154276	+	9070424	9070484	chr3	199501827	-	68123367	68123427	31584493
+60
+
+chain	5594	4	191154276	+	1547006	1547408	chr4	191273063	+	1517841	1518435	2949224
+33	336	530
+7	8	6
+18
+
+chain	5494	4	191154276	+	8989383	8989441	chr10	135374737	+	82555871	82555929	31956576
+58
+
+chain	5493	4	191154276	+	9123841	9123899	chr3	199501827	-	55547554	55547612	22296298
+58
+
+chain	5485	4	191154276	+	9108193	9108251	chr17	78774742	+	49845783	49845841	31992260
+58
+
+chain	5354	4	191154276	+	9123785	9123841	chr19	63811651	+	46743056	46743112	26997396
+56
+
+chain	5287	4	191154276	+	191044097	191044231	chr11	134452384	+	134452193	134452328	8509115
+51	52	53
+31
+
+chain	5247	4	191154276	+	1642928	1642982	chr4	191273063	+	1612682	1612736	32710536
+54
+
+chain	5146	4	191154276	+	9109529	9109584	chr3	199501827	+	191350023	191350078	20827932
+55
+
+chain	5102	4	191154276	+	9012475	9012528	chr7	158821424	-	61434988	61435041	33179954
+53
+
+chain	4979	4	191154276	+	59793133	59793454	chr14	106368585	+	47992116	47992437	1636209
+52	1	1
+72	116	116
+45	1	1
+34
+
+chain	4919	4	191154276	+	59793533	59793585	chr1	247249719	+	177132715	177132767	25644257
+52
+
+chain	4894	4	191154276	+	8980336	8980388	chr8	146274826	-	134343460	134343512	33871905
+52
+
+chain	4776	4	191154276	+	59793593	59793649	chr8	146274826	+	78720544	78720600	25267381
+56
+
+chain	4646	4	191154276	+	9032086	9032149	chr11	134452384	-	67001981	67002044	11075042
+63
+
+chain	4523	4	191154276	+	9083642	9083690	chr4	191273063	+	9229696	9229744	33561479
+48
+
+chain	4481	4	191154276	+	9110034	9110081	chr1	247249719	+	117212387	117212434	31311635
+47
+
+chain	4466	4	191154276	+	8975249	8975296	chr4	191273063	+	9087559	9087606	34734206
+47
+
+chain	4380	4	191154276	+	9065601	9065685	chr14	106368585	-	65288844	65288928	12690014
+84
+
+chain	4316	4	191154276	+	8994219	8994386	chr9	140273252	-	20618312	20618467	21123765
+25	83	71
+59
+
+chain	4224	4	191154276	+	1548697	1548764	chr4	191273063	+	1518798	1518831	14337246
+14	34	0
+19
+
+chain	4196	4	191154276	+	59793649	59793759	chr3	199501827	-	110817223	110817333	10064550
+110
+
+chain	4174	4	191154276	+	9006462	9006529	chr3	199501827	-	68301162	68301229	17546615
+67
+
+chain	4160	4	191154276	+	9087190	9087234	chr3	199501827	+	69469088	69469132	19451262
+44
+
+chain	4035	4	191154276	+	59793991	59794095	chr4	191273063	-	43511377	43511481	1601554
+104
+
+chain	3949	4	191154276	+	59793891	59793960	chr7	158821424	-	5091499	5091568	15707336
+69
+
+chain	3917	4	191154276	+	59794575	59794617	chr19	63811651	+	46686810	46686852	11955254
+42
+
+chain	3916	4	191154276	+	9180332	9180405	chr8	146274826	+	7130141	7130214	14314247
+73
+
+chain	3790	4	191154276	+	9231440	9231540	chr4	191273063	+	8950300	8950400	218917
+92	7	7
+1
+
+chain	3686	4	191154276	+	59793772	59793811	chr15	100338915	+	77825223	77825262	17426618
+39
+
+chain	3659	4	191154276	+	9096554	9096861	chr3	199501827	-	6400721	6401028	23757316
+67	190	190
+50
+
+chain	3657	4	191154276	+	59794470	59794516	chr6	170899992	-	3232006	3232052	26376367
+46
+
+chain	3647	4	191154276	+	1557695	1557733	chr4	191273063	+	1527878	1527916	12331685
+38
+
+chain	3642	4	191154276	+	9109808	9109863	chr6	170899992	-	83529676	83529731	23755843
+55
+
+chain	3437	4	191154276	+	9178724	9179540	chr12	132349534	+	34224690	34225504	10931865
+32	667	665
+117
+
+chain	3342	4	191154276	+	9274373	9274605	chr4	191273063	+	8969490	8969722	4902
+232
+
+chain	3310	4	191154276	+	8971045	8971455	chr9	140273252	-	10330739	10331149	20511421
+70	288	288
+52
+
+chain	3302	4	191154276	+	1548711	1548745	chr4	191273063	+	1518614	1518648	32145222
+34
+
+chain	3283	4	191154276	+	9102560	9102594	chr10	135374737	-	120311822	120311856	35225233
+34
+
+chain	3261	4	191154276	+	8994091	8994458	chr8	146274826	+	9742146	9742512	23065618
+62	246	245
+59
+
+chain	3172	4	191154276	+	59794789	59794841	chr3	199501827	-	24852035	24852087	14612523
+52
+
+chain	3108	4	191154276	+	9060565	9060615	chr13	114142980	-	41995201	41995251	9632166
+50
+
+chain	3078	4	191154276	+	1548520	1548554	chr4	191273063	+	1518360	1518394	5794973
+34
+
+chain	3017	4	191154276	+	9065206	9065807	chr10	135374737	+	117208692	117209275	9578047
+65	480	462
+56
+
+chain	2924	4	191154276	+	59795756	59795800	chr5	180857866	+	175080369	175080413	1478283
+44
+
+chain	2887	4	191154276	+	59793960	59793991	chr2	242951149	-	7484272	7484303	15380677
+31
+
+chain	2846	4	191154276	+	9001603	9001654	chr8	146274826	-	133764474	133764525	19750221
+51
+
+chain	2767	4	191154276	+	8957324	8957381	chr4	191273063	+	9129618	9129675	15542671
+57
+
+chain	2754	4	191154276	+	9087109	9087190	chr6	170899992	+	92706078	92706159	16313416
+81
+
+chain	2673	4	191154276	+	9065350	9065411	chr1	247249719	-	53009045	53009106	13821618
+61
+
+chain	2622	4	191154276	+	59793258	59793374	chr14	106368585	+	42536813	42536929	1616879
+116
+
+chain	2598	4	191154276	+	59795229	59795281	chr6	170899992	+	57310821	57310873	1524793
+52
+
+chain	2565	4	191154276	+	190987578	190987605	chr4	191273063	+	191231440	191231467	2372
+27
+
+chain	2557	4	191154276	+	9066521	9067027	chr12	132349534	+	72855206	72855711	22561893
+55	378	377
+73
+
+chain	2500	4	191154276	+	9083457	9083524	chr8	146274826	+	32149594	32149661	28386486
+67
+
+chain	2474	4	191154276	+	1651689	1651722	chr4	191273063	+	1621541	1621574	19254204
+33
+
+chain	2389	4	191154276	+	9036810	9036873	chr2	242951149	-	1691358	1691421	23135357
+63
+
+chain	2338	4	191154276	+	59796505	59796540	chr17	78774742	+	47057876	47057911	2877115
+35
+
+chain	2291	4	191154276	+	9216761	9217155	chr8	146274826	-	133997030	133997425	4114277
+45	320	321
+29
+
+chain	2265	4	191154276	+	9065418	9065482	chr9	140273252	+	44106224	44106288	9767431
+64
+
+chain	2116	4	191154276	+	8944155	8944177	chr3	199501827	+	126918676	126918698	25172225
+22
+
+chain	2099	4	191154276	+	9099268	9099290	chr2	242951149	+	169698626	169698648	26708137
+22
+
+chain	2025	4	191154276	+	9097343	9097409	chr3	199501827	+	179409375	179409441	24047564
+66
+
+chain	2003	4	191154276	+	9108252	9108273	chr2	242951149	-	190846639	190846660	24998179
+21
+
+chain	1997	4	191154276	+	9146164	9146218	chr15	100338915	-	2487154	2487208	24249848
+54
+
+chain	1870	4	191154276	+	190988070	190988095	chr10	135374737	+	135329605	135329630	1377
+25
+
+chain	1826	4	191154276	+	8957935	8957992	chr4	191273063	+	9362404	9362461	11066413
+57
+
+chain	1826	4	191154276	+	9097476	9098043	chr12	132349534	-	122338357	122338925	15828070
+57	424	425
+86
+
+chain	1767	4	191154276	+	8990059	8990106	chr1	247249719	+	148949220	148949267	26452494
+47
+
+chain	1744	4	191154276	+	59793037	59793133	chr3	199501827	+	30427927	30428023	1883621
+96
+
+chain	1736	4	191154276	+	9086392	9087109	chr4	191273063	-	127153063	127153784	14070511
+50	639	643
+28
+
+chain	1668	4	191154276	+	9124660	9124729	chr4	191273063	+	9269820	9269889	23245150
+69
+
+chain	1556	4	191154276	+	9060815	9060839	chr10	135374737	-	108080722	108080746	12503169
+24
+
+chain	1546	4	191154276	+	9180153	9180207	chr8	146274826	-	138844855	138844909	16808195
+54
+
+chain	1517	4	191154276	+	59794322	59794359	chr11	134452384	-	119842384	119842421	16271509
+37
+
+chain	1488	4	191154276	+	59796097	59796124	chr9	140273252	+	9925299	9925326	2265670
+27
+
+chain	1436	4	191154276	+	191043722	191043759	chr1	247249719	-	247249574	247249611	18645625
+37
+
+chain	1374	4	191154276	+	9065276	9065337	chr1	247249719	-	201083821	201083882	10540800
+61
+
+chain	1348	4	191154276	+	9109064	9109144	chr2	242951149	-	126292213	126292293	15140626
+80
+
+chain	1343	4	191154276	+	9146043	9146068	chr18	76117153	+	30068723	30068748	16305066
+25
+
+chain	1292	4	191154276	+	9123899	9123951	chr4	191273063	-	148574019	148574071	20863102
+52
+
+chain	1290	4	191154276	+	9179321	9179368	chr11	134452384	+	3426025	3426072	10983647
+47
+
+chain	1231	4	191154276	+	59794434	59794461	chr5	180857866	+	147382264	147382291	9387523
+27
+
+chain	1177	4	191154276	+	9065884	9065939	chr9	140273252	-	70318092	70318147	10006368
+55
+
+chain	1097	4	191154276	+	9086357	9086392	chr1	247249719	-	129588705	129588740	16923174
+35
+
+chain	1085	4	191154276	+	9066380	9066450	chr13	114142980	+	68490318	68490388	22728993
+70
+
+chain	1083	4	191154276	+	9032737	9032804	chr13	114142980	+	26049760	26049827	24893033
+67
+
+chain	1011	4	191154276	+	9067073	9067124	chr10	135374737	-	108679092	108679143	23379890
+51
+
+chain	996	4	191154276	+	8971509	8971561	chr12	132349534	+	31168410	31168462	23661941
+52
+
+chain	963	4	191154276	+	9066836	9066890	chr1	247249719	-	151454542	151454596	25048936
+54
+
+chain	958	4	191154276	+	9145173	9145232	chr1	247249719	-	217919030	217919089	20381976
+59
+
+chain	937	4	191154276	+	8958092	8958125	chr11	134452384	+	67446107	67446140	12651114
+33
+
+chain	917	4	191154276	+	9146455	9146505	chr8	146274826	+	19957787	19957837	24577235
+50
+
+chain	910	4	191154276	+	9097602	9098317	chr2	242951149	-	190844271	190844995	14887788
+50	595	604
+70
+
+chain	894	4	191154276	+	9109146	9109219	chrX	154913754	-	13573867	13573940	23078019
+73
+
+chain	878	4	191154276	+	9178986	9179012	chr2	242951149	-	137542666	137542692	11507142
+26
+
+chain	871	4	191154276	+	9082368	9082425	chr3	199501827	-	78731030	78731087	22332859
+57
+
+chain	858	4	191154276	+	9098043	9099355	chr5	180857866	-	58871729	58873086	24126323
+56	1191	1236
+65
+
+chain	777	4	191154276	+	8955354	8955423	chr3	199501827	-	68281758	68281827	15856837
+69
+
+chain	715	4	191154276	+	191033511	191033568	chr7	158821424	+	30724536	30724593	23744345
+57
+
+chain	650	4	191154276	+	9126884	9126934	chr3	199501827	+	102896742	102896792	23688110
+50
+
+chain	507	4	191154276	+	59793857	59793890	chr8	146274826	+	107120151	107120184	20878932
+33
+
+chain	468	4	191154276	+	40297344	40297404	chr4	191273063	+	39972706	39972766	25333266
+60
+
+chain	438	4	191154276	+	9098988	9099041	chr4	191273063	-	56600577	56600630	25949595
+53
+
+chain	368	4	191154276	+	191031439	191031496	chr19	63811651	-	43557899	43557956	26568315
+57
+
+chain	315	4	191154276	+	8972631	8972682	chr12	132349534	-	123858147	123858198	26303923
+51
+
+chain	268	4	191154276	+	59793813	59793857	chr13	114142980	-	20847506	20847550	12435901
+44
+
+chain	209	4	191154276	+	9096427	9096486	chr3	199501827	-	25140168	25140227	30710814
+59
+
+chain	54948874	chr4_ctg9_hap1	590426	+	0	590426	chr4	191273063	+	68852671	69912764	73
+1837	0	2
+151607	0	469345
+122242	3	1
+4137	1	1
+70	1	1
+5254	0	2
+2782	48	48
+1074	0	2
+2825	0	5
+2047	2	0
+6949	1	1
+41	1	1
+232	0	1
+1965	12	0
+694	1	1
+22	1	0
+945	14	14
+416	1	1
+36	2	0
+75	1	1
+21	1	0
+52	1	1
+41	1	1
+144	1	1
+87	1	1
+71	1	1
+35	1	1
+145	0	1
+503	1	1
+88	1	1
+99	1	1
+30	1	1
+293	0	5
+360	19	19
+380	1	1
+23	1	1
+209	36	36
+557	10	10
+820	1	1
+38	1	1
+868	0	2
+227	0	353
+5432	0	1
+1459	1	0
+210	20	20
+125	8	0
+5	32	0
+65	0	2
+10	23	5
+240	0	1
+233	14	14
+1076	14	14
+100	1	1
+28	1	1
+199	0	1
+287	1	1
+36	1	0
+17	1	1
+132	1	1
+25	1	1
+193	1	0
+305	0	28
+50	0	1
+544	1	1
+40	4	0
+794	15	15
+179	1	1
+72	1	1
+142	1	1
+65	1	1
+364	0	1
+335	0	1
+52	4	4
+48	1	1
+934	1	1
+50	0	1
+44	1	1
+1074	1	1
+22	1	1
+286	4	0
+33	1	1
+303	1	1
+5	0	1
+63	1	1
+972	1	1
+69	1	1
+602	1	1
+25	1	1
+2469	5	5
+1033	1	1
+63	1	1
+233	0	3
+311	1	1
+29	1	1
+881	6	6
+123	15	16
+283	1	1
+39	1	1
+57	5	0
+613	1	1
+42	1	1
+1598	0	2
+730	1	1
+47	1	1
+459	1	1
+25	1	1
+775	7	7
+534	0	1
+1090	5	5
+375	1	1
+62	1	1
+133	15	15
+700	1	1
+36	4	0
+365	9	9
+468	1	1
+45	1	1
+1356	16	16
+422	1	0
+55	0	2
+7890	1	1
+30	1	1
+1445	1	1
+27	1	1
+96	4	0
+2114	10	11
+1940	2	0
+1687	1	1
+40	1	1
+1679	1	0
+734	0	1
+480	1	0
+7344	1	0
+3930	17	17
+1001	0	8
+216373
+
+chain	4430	chr4_ctg9_hap1	590426	+	287934	287982	chr4	191273063	+	69257952	69258000	221
+48
+
+chain	18001815	chr4_gl000193_random	189789	+	0	189789	chr4_random	842648	+	0	189789	149
+189789
+
+chain	18169122	chr4_gl000194_random	191469	+	0	191469	chr4_random	842648	+	440032	631501	148
+191469
+
+chain	16792065298	5	180915260	+	10000	180905260	chr5	180857866	+	63000	180837866	5
+17520657	50017	11
+356	84	84
+496	0	3434
+735	75	1475
+628	25	3459
+51	50	3484
+3427	1	1
+39	3	3437
+577	8	8
+167	44	1713
+23	0	3434
+1184	1	0
+46	1	0
+5	1	0
+266	1	1
+21	1	1
+763	16	16
+422	1	1
+29	1	1
+5243	1	1
+37	1	1
+978	1	1
+21	1	1
+116	16	3450
+1792	146	16585
+3079	0	1
+7857	9770	0
+1026	636	1
+7461	1	0
+23769	0	51
+4034	1	0
+20571	1	0
+9135	2	0
+6885	3	2
+110	0	3
+816	3	2
+2296	34	0
+7499	2	0
+2917	1	0
+652	1	1
+37	1	1
+657	1	1
+22	1	1
+419	4	3
+3580	1	1
+29	1	1
+274	35	11
+833	1	0
+1908	0	3038
+10504	1	1
+27	0	2
+784	6	0
+127	0	10
+668	1	1
+28	1	1
+2464	0	4
+182	2	0
+1650	1	1
+39	1	1
+2433	0	1
+720	1	1
+40	1	1
+772	1	1
+32	1	1
+353	1	1
+17	1	1
+1776	1	0
+6082	0	3
+2669	10	12
+2857	1	1
+35	1	1
+982	1	1
+173	1	1
+4115	1	1
+49	1	1
+702	1	1
+33	1	1
+2927	2	1
+1472	0	17
+1346	1	1
+35	1	1
+2068	1	1
+40	1	1
+828	1	1
+36	0	2
+317	0	8
+893	1	1
+33	0	1
+8145	4	0
+28632197	3000000	3000000
+12470071	1	0
+29760415	50000	40000
+5878002	20845	23000
+4521	0	1
+676	6	6
+5928	1	0
+372	1	1
+47	1	1
+6801	2	3
+639	1	0
+871	4	3
+11530	4	0
+22966	1	0
+15447	1	0
+53856	2	0
+15988	2	0
+906887	1	0
+8	2	2
+40152828	47715	0
+3526228	1	0
+1604	0	10
+12778810	51715	4100
+15152690	0	27
+1852098	0	1
+8710030
+
+chain	78758	5	180915260	+	17610410	17613099	chr5	180857866	+	17647305	17649997	1601642
+85	49	49
+57	201	201
+189	17	17
+78	77	77
+75	178	181
+116	179	179
+91	8	8
+51	298	300
+51	664	662
+64	26	26
+135
+
+chain	31383	5	180915260	+	97574240	97575427	chr4	191273063	-	170991967	170993160	4391624
+188	108	110
+89	705	709
+97
+
+chain	22831	5	180915260	+	97580590	97581374	chr2	242951149	-	86243998	86244777	8407693
+68	180	179
+95	326	322
+115
+
+chain	16108	5	180915260	+	97571166	97571372	chr3	199501827	+	12403992	12404198	13932022
+51	22	22
+133
+
+chain	10260	5	180915260	+	97573380	97573866	chrX	154913754	+	72466087	72466572	22227065
+67	357	356
+62
+
+chain	9281	5	180915260	+	97573916	97574127	chr3	199501827	-	17931346	17931561	24462523
+61	98	102
+52
+
+chain	8534	5	180915260	+	17581030	17583073	chr5	180857866	+	17608062	17614939	1974
+70	1948	6782
+25
+
+chain	7377	5	180915260	+	17614165	17614243	chr8	146274826	+	118652818	118652896	27454171
+78
+
+chain	7140	5	180915260	+	97574682	97574775	chr9	140273252	+	18188007	18188100	13076039
+11	6	6
+76
+
+chain	6854	5	180915260	+	97574980	97575063	chr2	242951149	+	163688921	163689004	19449593
+83
+
+chain	6104	5	180915260	+	97573580	97573645	chrX	154913754	+	86697567	86697632	30283885
+65
+
+chain	5931	5	180915260	+	97571838	97571901	chr11	134452384	+	21528921	21528984	30747470
+63
+
+chain	5358	5	180915260	+	97565266	97565323	chr3	199501827	+	123413571	123413628	32371600
+57
+
+chain	5211	5	180915260	+	97574626	97575600	chr2	242951149	-	205065194	205066172	4657168
+56	746	750
+172
+
+chain	4836	5	180915260	+	97570927	97570987	chr12	132349534	+	79028695	79028755	21429371
+60
+
+chain	3976	5	180915260	+	97580463	97580554	chrX	154913754	+	120621333	120621424	19038460
+91
+
+chain	3896	5	180915260	+	17583124	17583167	chr5	180857866	+	17601254	17601297	1526
+43
+
+chain	3528	5	180915260	+	97573879	97573916	chr4	191273063	-	42047288	42047325	31874217
+37
+
+chain	3107	5	180915260	+	97574479	97575651	chr2	242951149	+	88874356	88875531	4418505
+53	767	770
+31	271	271
+50
+
+chain	3026	5	180915260	+	97580178	97580228	chr15	100338915	-	8217824	8217874	19735797
+50
+
+chain	2922	5	180915260	+	97575231	97575262	chr5	180857866	-	151978291	151978322	11789776
+31
+
+chain	2640	5	180915260	+	97575132	97575230	chr6	170899992	-	85176442	85176540	6161475
+98
+
+chain	2605	5	180915260	+	97580235	97580338	chr6	170899992	-	161277959	161278062	12089137
+103
+
+chain	2572	5	180915260	+	97580955	97581020	chr4	191273063	+	75087136	75087201	9159879
+65
+
+chain	2511	5	180915260	+	97573039	97573123	chr5	180857866	+	96582581	96582665	20564544
+84
+
+chain	2425	5	180915260	+	97580778	97580807	chr7	158821424	+	56235832	56235861	15947917
+29
+
+chain	2390	5	180915260	+	97580658	97580706	chr6	170899992	+	77924350	77924398	14557662
+48
+
+chain	2360	5	180915260	+	97575070	97575127	chr15	100338915	-	65496060	65496117	11267266
+57
+
+chain	2316	5	180915260	+	97574862	97574967	chr5	180857866	+	122822031	122822136	6403532
+105
+
+chain	2262	5	180915260	+	97575262	97575299	chr5	180857866	+	117084659	117084696	9926189
+37
+
+chain	2258	5	180915260	+	97570996	97571059	chr6	170899992	+	98788934	98788997	20073703
+63
+
+chain	2234	5	180915260	+	97575771	97575825	chr15	100338915	+	19192799	19192853	13777203
+54
+
+chain	2112	5	180915260	+	17598551	17598575	chr5	180857866	+	17621050	17621074	2441
+24
+
+chain	2082	5	180915260	+	97581410	97581440	chr5	180857866	-	81177483	81177513	18145628
+30
+
+chain	2013	5	180915260	+	97574428	97574456	chr6	170899992	+	12662047	12662075	5707452
+28
+
+chain	1804	5	180915260	+	97574815	97574862	chr7	158821424	+	102470537	102470584	21213680
+47
+
+chain	1676	5	180915260	+	97571668	97571723	chr9	140273252	-	49451145	49451200	15925569
+55
+
+chain	1630	5	180915260	+	97575847	97575921	chr14	106368585	+	65599248	65599322	16554081
+74
+
+chain	1394	5	180915260	+	17611593	17611672	chr5	180857866	-	163271537	163271616	20711197
+79
+
+chain	1250	5	180915260	+	97570872	97570926	chrX	154913754	+	128632888	128632942	22138126
+54
+
+chain	1212	5	180915260	+	17598429	17598472	chr5	180857866	-	163276581	163276624	866388
+43
+
+chain	683	5	180915260	+	97570493	97570549	chr4	191273063	+	125149085	125149141	22694892
+56
+
+chain	625	5	180915260	+	97572119	97572183	chr5	180857866	-	153619225	153619289	25061319
+64
+
+chain	466	5	180915260	+	97569261	97569351	chr7	158821424	-	120247996	120248086	22482305
+90
+
+chain	395	5	180915260	+	97572751	97572804	chr2	242951149	-	47300723	47300776	19687839
+53
+
+chain	15799169383	6	171115067	+	60000	171055067	chr6	170899992	+	5000	170896992	6
+1297281	1	0
+7806968	0	162987
+4013154	9	0
+261	13	15
+18786172	17	17
+439	16	16
+59	5	4
+32202	17	17
+439	16	16
+59	4	5
+15403	1	0
+13914169	4	0
+112	1	1
+17	1	1
+415	12	0
+105	6	3
+12160281	50000	50000
+642507	3100000	3050000
+248423	50000	50000
+2918791	1238	0
+9427508	4	4
+162	12	12
+2193	22	22
+293	1	1
+30	1	1
+845	1	0
+45	1	1
+9769	2	0
+6058	1	1
+24	1	1
+2223	1	1
+24	1	1
+182	12	12
+284	1	1
+20	1	1
+1035	7	36
+1007	1	1
+27	1	1
+3279	1	1
+44	0	1
+3012	1	0
+545	17	17
+2562	0	1
+251	0	1
+935	8	0
+37	1	1
+566	6	0
+1483	2	0
+1960	1	0
+4564	1	1
+25	1	1
+832	0	1
+801	8	8
+1131	1	1
+58	5	1
+6177	0	1
+3712	1	0
+2185	1	1
+35	1	1
+710	2	2
+78	1	1
+2201	1	1
+30	1	1
+283	1	1
+30	1	1
+448	1	0
+74814	2	2
+197	8	0
+2508456	1	0
+4641788	5	5
+37	1	1
+8503609	0	2
+5363169	150000	200000
+6040303	1	1
+36	1	0
+2020	1	1
+46	1	1
+1559	1	1
+72	1	1
+1098	1	1
+29	1	1
+264	7	7
+580	0	1
+30	1	1
+536	1	1
+41	1	1
+5663	1	0
+438	5	3
+354	1	1
+18	1	1
+9613	14	13
+1400	1	0
+176	0	2
+2742	1	0
+1968	0	1
+754	1	0
+4237	0	1
+2388	1	1
+31	1	0
+3385	0	1
+2004	8	0
+3395	0	3
+32	1	1
+4109	0	1
+1058	20	0
+1608	1	0
+17198424	17	26
+7835	0	1
+16317	11	0
+6277	64993	0
+6787989	0	1
+149	4	0
+949	4	0
+242	0	1
+28418215	1	1
+21	1	0
+3116903	171704	50000
+1939305	1	1
+19	0	2
+8192274	4	4
+122	0	2
+1127	1	0
+1102	75	0
+21	8	5
+30	29	0
+27	6	3
+62	52	0
+42	195105	18125
+950946	1	1
+51	157	1
+107	255	0
+714	513	0
+1285155	50000	150000
+725095
+
+chain	12021668	chr6	171115067	+	157540957	157712661	chr6_random	1875562	+	1435107	1512777	78
+18510	50000	5628
+31833	50000	338
+21361
+
+chain	8743144	chr6	171115067	+	167847224	167942073	chr6_random	1875562	-	1720470	1850468	378
+12768	1	1
+28	0	1
+17496	12	0
+7219	1	1
+29	1	1
+4716	0	1
+1645	0	4
+6037	1	1
+33	94	125
+10	3	3
+5171	1	0
+4453	734	36650
+3575	1	1
+26	1	1
+4697	13	13
+958	0	2
+228	0	2
+2465	13	13
+142	1	1
+15	1	0
+33	937	104
+94	0	1
+125	16	0
+5319	48	103
+897	0	3
+1130	0	3
+187	8	7
+67	26	25
+5876	1	1
+47	1	1
+1955	14	7
+575	36	36
+641	0	2
+1143	5	5
+3079
+
+chain	27931	6	171115067	+	168993335	168994451	chr6	170899992	+	168736232	168737615	1527785
+96	36	36
+16	0	51
+107	739	901
+51	0	54
+71
+
+chain	17101	6	171115067	+	119158013	119159004	chr8	146274826	+	76280127	76281098	12940826
+78	146	105
+78	622	643
+67
+
+chain	14766	6	171115067	+	119189669	119190286	chr7	158821424	-	68703788	68704409	15321990
+54	439	443
+124
+
+chain	13062	6	171115067	+	168994482	168994817	chr6	170899992	+	168736716	168737003	1274096
+205	50	2
+80
+
+chain	12205	6	171115067	+	119155128	119155329	chr8	146274826	-	70047959	70048173	18676577
+72	59	72
+70
+
+chain	11124	6	171115067	+	168993071	168993228	chr6	170899992	+	168736229	168736638	2160304
+29	1	52
+50	25	226
+52
+
+chain	10673	6	171115067	+	119159180	119160231	chr10	135374737	-	59595554	59596042	21356650
+62	913	350
+76
+
+chain	10669	6	171115067	+	119157022	119157134	chr14	106368585	+	59942933	59943045	21369163
+112
+
+chain	9554	6	171115067	+	119189632	119189818	chrX	154913754	+	133155010	133155200	16872824
+37	54	54
+12	31	35
+52
+
+chain	7928	chr6	171115067	+	167846995	167847141	chr6_random	1875562	+	628575	628698	120
+41	26	0
+57	0	3
+22
+
+chain	7384	chr6	171115067	+	167920474	167920550	chr6_random	1875562	-	1829156	1829232	27447594
+76
+
+chain	7241	6	171115067	+	119190390	119190581	chr13	114142980	+	101174758	101174949	23777400
+2	136	136
+53
+
+chain	6904	6	171115067	+	119156272	119156345	chr11	134452384	-	108078565	108078638	28375374
+73
+
+chain	6531	6	171115067	+	119159999	119160068	chr4	191273063	-	87162214	87162283	29199925
+69
+
+chain	5948	6	171115067	+	119160915	119160977	chrX	154913754	-	59556739	59556801	30709264
+62
+
+chain	5818	6	171115067	+	119158407	119158509	chr18	76117153	+	30261305	30261403	24322730
+1	51	47
+50
+
+chain	5749	6	171115067	+	119155939	119156000	chr6	170899992	+	92063509	92063570	31228902
+61
+
+chain	5103	6	171115067	+	119189831	119189885	chrX	154913754	-	76833525	76833579	33162260
+54
+
+chain	5032	6	171115067	+	119156645	119156719	chrX	154913754	+	87420725	87420799	20704812
+74
+
+chain	5002	6	171115067	+	119160862	119160914	chrX	154913754	+	56955255	56955307	33524497
+52
+
+chain	4995	6	171115067	+	168994451	168994737	chr6	170899992	+	168737201	168737385	2349016
+31	205	103
+50
+
+chain	4921	6	171115067	+	119156041	119156093	chr9	140273252	+	81227536	81227588	33775667
+52
+
+chain	4912	6	171115067	+	119160087	119160139	chr5	180857866	+	63815067	63815119	33803556
+52
+
+chain	3597	6	171115067	+	119157136	119157361	chr2	242951149	+	31758724	31758949	14786968
+84	78	78
+63
+
+chain	3223	6	171115067	+	119156854	119156913	chr15	100338915	-	54365651	54365710	24573102
+59
+
+chain	3204	6	171115067	+	119155364	119155420	chr6	170899992	-	73613724	73613780	24603360
+56
+
+chain	2966	6	171115067	+	119156499	119156577	chrX	154913754	-	137505405	137505483	21485501
+78
+
+chain	2728	6	171115067	+	119159004	119159033	chr3	199501827	-	198198433	198198462	28454448
+29
+
+chain	2528	6	171115067	+	119156618	119156645	chr11	134452384	+	82352593	82352620	34284540
+27
+
+chain	2454	6	171115067	+	119155233	119155259	chr9	140273252	+	122001720	122001746	35057240
+26
+
+chain	2315	6	171115067	+	119156723	119156806	chr4	191273063	+	116661391	116661474	16361102
+83
+
+chain	2146	6	171115067	+	119158341	119158407	chr6	170899992	+	115819766	115819832	17078055
+66
+
+chain	1866	6	171115067	+	119190053	119190120	chr5	180857866	+	56063062	56063129	22879278
+67
+
+chain	1656	6	171115067	+	119158523	119158602	chr11	134452384	+	2473635	2473714	18654554
+79
+
+chain	1624	6	171115067	+	119189898	119189948	chr4	191273063	-	66123378	66123428	24040914
+50
+
+chain	1451	6	171115067	+	119158163	119158229	chr15	100338915	-	64161282	64161348	22109122
+66
+
+chain	1209	6	171115067	+	168994304	168994329	chr6	170899992	+	168736283	168736308	2117199
+25
+
+chain	1198	6	171115067	+	119156176	119156250	chr5	180857866	+	3717928	3718002	22194292
+74
+
+chain	980	6	171115067	+	119158602	119158634	chr8	146274826	+	104450758	104450790	18747323
+32
+
+chain	943	6	171115067	+	119157563	119157614	chr2	242951149	+	163020248	163020299	23359839
+51
+
+chain	785	6	171115067	+	119156425	119156485	chr17	78774742	-	29484860	29484920	22136428
+60
+
+chain	779	6	171115067	+	119190333	119190390	chr3	199501827	-	104453282	104453339	22453017
+57
+
+chain	696	6	171115067	+	119158674	119158726	chr6	170899992	-	83894386	83894438	23403881
+52
+
+chain	689	6	171115067	+	119157650	119157707	chrX	154913754	+	101935638	101935695	24716105
+57
+
+chain	360	6	171115067	+	119160319	119160372	chr3	199501827	-	158113258	158113311	26359861
+53
+
+chain	282	6	171115067	+	119159242	119159272	chr19	63811651	+	46835118	46835148	25343818
+30
+
+chain	202629822	chr6_apd_hap1	4622290	+	0	4622290	chr6	170899992	+	28804582	33443471	49
+932	3	0
+804	0	1
+2406	2	0
+178370	1	0
+25289	44253	44253
+3450	0	1
+345	1	0
+3096	39	0
+16669	1	0
+48609	0	2
+2804	29384	29384
+14756	7	0
+1489	1	1
+72	1	1
+2260	0	2
+7033	0	8
+3588	0	1
+9760	32	32
+9786	0	1
+1324	0	2
+5438	5	0
+2061	2	0
+3982	6	6
+1725	0	1
+3153	1	0
+18	1	0
+18	1	0
+2026	1	0
+4175	10	10
+4746	9	9
+4767	7	7
+1225	1	0
+8	1	1
+151	1	2
+5079	1	1
+28	1	1
+249	43	43
+1178	0	4
+685	8	0
+48	4	0
+1144	87598	87598
+5106	2	0
+1514	0	1
+3116	0	1
+3278	1	1
+21	1	1
+1738	0	1
+8576	19	0
+8020	1	0
+2049	1	0
+518	13	11
+1704	1	1
+117	1	1
+1448	10	0
+4403	9	9
+2265	1	0
+8656	104192	104192
+1686	0	2
+5376	0	1
+19253	1	0
+7884	1	0
+21	0	6
+4451	1	0
+27910	1	0
+9946	0	1
+11233	1	1
+32	1	1
+2238	1	1
+20	1	1
+3659	22	16
+1218	1	0
+1638	6	6
+228	1	1
+45	1	1
+2048	0	2
+462	1	0
+20759	1	0
+3778	2	1
+1268	1	0
+1511	1	1
+42	2	0
+24	1	1
+4119	22	0
+1757	1	0
+1527	1	1
+29	1	1
+1886	1	0
+6666	0	4
+1349	0	4
+1102	10	8
+1463	34	31
+168	1	1
+21	1	1
+304	1	1
+31	1	1
+549	1	0
+5745	1	0
+5097	0	1
+534	1	1
+17	1	1
+2233	1	1
+37	1	1
+3328	0	1
+4783	6	0
+3323	0	3
+965	1	0
+1234	28	0
+1194	1	0
+1855	18	18
+1024	0	1
+5932	1	0
+5395	9	9
+2759	0	10
+618	5	0
+667	0	8
+580	0	1
+109	1	1
+326	1	0
+9436	5	0
+6164	0	1
+1064	0	6
+1374	2	0
+3637	1	1
+32	1	1
+145	1	0
+1245	2	0
+1736	1	1
+29	1	1
+1656	1	5
+712	10	11
+502	0	1
+3670	1	0
+740	0	1
+1693	0	1
+6497	0	2
+2700	1	0
+198	1	3
+141	0	1
+1108	0	2
+1448	1	0
+947	31	31
+8047	4	0
+842	19167	19167
+101	1	0
+11	4	0
+297	0	24
+337	11	0
+134	1	1
+694	3	0
+72	1	1
+144	128	128
+169	2	0
+1011	1	0
+107	1	1
+1280	1	1
+73	1	1
+84	25	25
+287	1	1
+26	1	1
+139	1	1
+41	1	1
+440	4	0
+130	12	12
+435	18	0
+85	1	1
+28	1	1
+73	59397	59260
+107	0	32
+23	1	1
+116	1	1
+30	1	1
+503	1	1
+22	0	3
+136	1	1
+48	1	1
+330	9	9
+1108	1	1
+98	1	1
+582	0	4
+711	7	7
+89	1	0
+291	1	0
+167	1	1
+24	1	1
+167	6	6
+171	17	17
+681	1	1
+43	1	1
+538	1	1
+44	1	1
+537	16	16
+180	6	6
+778	2	2
+44	1	1
+168	0	7
+211	1	1
+42	1	1
+1253	1	1
+29	1	1
+320	1	1
+36	2	2
+55	1	2
+228	1	1
+17	1	1
+213	1	1
+35	1	1
+553	8	8
+386	1	1
+26	1	1
+540	1	1
+31	1	1
+65	0	1
+625	12	12
+313	0	1
+52	1	1
+22	1	1
+583	1	1
+49	1	1
+1499	3	0
+729	1	1
+40	1	1
+67	1	1
+19	11	0
+323	19	19
+787	1	1
+36	1	1
+553	8	8
+997	16	15
+157	1	1
+31	2	2
+204	18	19
+487	1	1
+29	1	1
+374	1	1
+67	1	1
+720	13	13
+266	10	10
+330	16	14
+413	1	1
+44	1	1
+78	6	6
+181	2	2
+36	1	1
+397	1	1
+20	1	1
+311	1	1
+48	2	2
+1746	4	4
+35	1	1
+194	10	10
+310	1	1
+51	1	1
+84	1	1
+101	1	1
+521	1	1
+23	1	1
+220	73	73
+1046	15	15
+216	1	1
+21	1	1
+51	1	1
+49	1	1
+527	17	17
+340	12	11
+1025	1	0
+2572	1	1
+29	1	1
+397	2	5
+668	13	13
+541	1	1
+59	0	2
+6	1	1
+122	14	14
+51	1	1
+46	1	1
+429	0	21
+136	1	1
+12	1	1
+66	16	16
+456	37	34
+371	7	7
+48	1	1
+194	10	10
+108	1	1
+60	1	1
+122	49	50
+238	1	1
+32	0	1
+100	1	0
+72	1	0
+390	1	1
+38	1	1
+144	1	1
+27	0	4
+184	21	228
+49	1	1
+608	0	1
+152	1	1
+31	1	1
+281	8	8
+337	1	1
+45	1	1
+222	1	1
+20	1	1
+380	1	0
+44	1	1
+368	1	1
+72	1	1
+502	36	18
+63	1	1
+43	0	4
+136	1	1
+42	1	1
+80	4	4
+35	1	0
+89	1	1
+24	0	5
+829	13	13
+102	14	0
+233	1	1
+42	0	3
+85	0	1
+400	1	1
+40	1	1
+538	25	25
+174	1	1
+20	1	1
+705	1	1
+26	2	2
+614	1	1
+44	1	1
+509	1	1
+32	1	1
+224	1	1
+42	1	1
+99	38	38
+610	5	5
+804	1	1
+29	1	1
+166	1	1
+43	1	1
+233	1	1
+44	1	1
+620	8	8
+133	1	1
+31	1	1
+165	1	1
+29	1	1
+1249	1	1
+26	4	0
+56	1	1
+67	1	1
+716	1	1
+46	0	1
+16	1	1
+174	1	1
+96	1	1
+141	1	1
+39	0	4
+263	1	1
+18	1	1
+259	4	4
+38	1	1
+104	1	1
+40	1	0
+248	1	1
+18	1	1
+238	1	1
+32	1	1
+70	0	2
+16	1	1
+818	1	1
+22	4	4
+1641	1	1
+46	1	1
+53	1	0
+38	1	1
+373	38443	100035
+112	1	1
+39	1	1
+330	1	1
+24	1	1
+197	1	1
+69	1	1
+116	3	0
+161	1	1
+38	1	1
+753	1	1
+57	3	3
+145	1	1
+121	1	1
+300	1	1
+147	1	1
+379	1	1
+55	2	2
+65	1	1
+32	1	1
+1008	1	1
+24	1	1
+159	18	18
+659	1	1
+76	0	2
+77	1	3
+65	1	1
+84	1	0
+119	1	1
+15	1	1
+247	4	0
+372	1	0
+1633	1	1
+16	1	1
+456	7	7
+114	1	1
+102	1	1
+109	4	0
+61	2	2
+80	1	1
+47	1	1
+168	1	1
+31	1	1
+269	2	2
+42	1	1
+626	2	2
+14	1	1
+76	8356	10147
+66	2	2
+80	0	41
+12	1	1
+158	1	0
+92	1	0
+254	1	1
+43	1	1
+846	6	149
+84	1	1
+29	3	3
+315	17	17
+482	1	1
+29	3	3
+278	1	1
+73	1	1
+2767	1	1
+34	1	1
+192	1	1
+33	1	0
+168	6	0
+276	10	10
+344	1	1
+49	1	1
+109	1	1
+35	3	3
+561	24	27
+923	1	1
+102	1	1
+75	14	14
+266	1	1
+80	2	2
+185	1	0
+1035	1	1
+23	1	1
+417	10	10
+97	1	1
+94	1	1
+492	1	1
+37	5	5
+1429	1	1
+19	1	1
+839	1	1
+96	1	1
+1279	4	0
+683	1	1
+49	1	1
+514	1	1
+28	4	4
+2302	1	1
+42	1	1
+537	2	21
+1555	1	1
+42	0	1
+14	4	4
+86	1	1
+62	1	1
+515	5	1
+330	0	1
+159	0	22
+3841	1	0
+3862	16	16
+1187	12	12
+97	0	3
+748	24594	24594
+686	1	0
+11541	1	0
+1843	0	4
+1157	16	16
+7354	19	0
+741	0	1
+8053	1	0
+4449	21	21
+649	1	0
+2913	0	1
+381	332	0
+3533	31	31
+2502	0	1
+1968	7	0
+3198	1	0
+667	1	0
+3870	0	1
+36	13	0
+1894	1	1
+40	0	4
+1137	2	0
+211	2	0
+345	1	0
+592	4	4
+1043	4	0
+686	14	0
+1032	0	1
+9035	0	4
+167	0	2
+23964	0	3
+1760	3	0
+3371	1	1
+23	1	1
+321	5	0
+644	8	0
+47	1	1
+322	1	1
+145	1	1
+1551	11	15
+355	0	1
+1831	4	0
+1779	1	1
+27	1	1
+199	43	55
+767	9786	9786
+338	0	1
+1002	0	1
+7912	4	0
+4977	0	1
+9275	2953	2950
+21511	0	1
+4385	0	7
+881	0	8
+17594	0	20
+2417	1	0
+998	0	10
+4239	7	0
+4845	0	2
+95	28	23
+10921	1	1
+40	1	1
+4759	0	6
+12084	0	3
+3052	0	4
+2989	1	0
+13523	1	3
+3050	104591	33135
+2281	0	7
+377	3	0
+7256	3	0
+419	2	0
+10674	0	17
+5362	16440	16440
+408	1	0
+3061	2	0
+5818	1	0
+2415	11	9
+2056	0	1
+955	4	0
+17260	1	0
+9557	0	2
+5358	0	1
+11548	13	13
+2604	2	0
+57496	1	1
+29	1	1
+6617	19	0
+12369	49753	49753
+608	0	5
+1926	1	1
+40	1	1
+330	3	0
+2327	0	1
+414	1	0
+61	0	1
+235	0	2
+2087	0	1
+713	0	8
+54	3	0
+1027	3	0
+428	1	1
+17	1	1
+948	1	1
+41	1	1
+458	1	1
+21	1	1
+1055	0	1
+8189	4	5
+36	1	1
+99	2	0
+700	0	3
+150	0	1
+750	0	3
+40	1	1
+3179	2	0
+473	0	2
+2032	1	0
+3841	1	0
+560	1	0
+1108	1	0
+8087	1	0
+5394	103872	103871
+16267	1	0
+18633	0	1
+920	0	1
+6820	1	0
+1376	1	2
+1931	33	33
+2376	0	1
+12415	1	1
+51	0	1
+9375	0	1
+323	1	0
+1715	154558	154558
+4522	85167	85167
+6234	0	3
+4009	0	5
+6425	2	0
+1119	2	0
+17	8	0
+2256	0	1
+3209	15	8
+2436	0	14
+1040	1	1
+52	1	1
+6972	1	0
+2357	0	1
+29	1	1
+262	1	0
+72	1	1
+45	1	1
+57	17	17
+1390	0	16
+328	312	0
+65	1	1
+217	10	10
+925	0	33
+1490	1	0
+35	1	1
+226	0	3
+805	1	1
+46	1	1
+192	1	1
+56	1	1
+245	1	1
+61	1	1
+198	4	0
+82	2	2
+29	1	1
+57	0	2
+320	1	1
+22	1	1
+267	5	0
+427	1	0
+17	1	1
+425	1	1
+34	1	1
+565	10	10
+432	9	0
+55	1	1
+90	1	1
+140	1	1
+83	1	1
+1035	1	1
+33	1	1
+144	4	4
+38	1	1
+171	1	1
+35	3	3
+161	6	6
+731	7	3
+1216	25	0
+52	0	1
+419	2	0
+87	1	1
+54	1	1
+4713	30	0
+791	3	0
+2849	1	1
+33	1	1
+6790	1	1
+67	4	4
+39	2	0
+251	1	1
+37	1	1
+826	3715	901
+205	2	0
+946	1	1
+30	1	1
+613	5	2
+128	29	29
+802	0	89
+1600	0	6
+2155	1	0
+1164	1	0
+1310	1	0
+2327	1	1
+42	1	1
+2266	1	0
+21451	401282	401282
+2475	1	1
+58	1	1
+375	25	27
+9941	0	1
+6798	0	19
+5779	11	10
+21042	0	1
+13887	36782	36752
+28930	1	1
+19	1	1
+1494	7	0
+148	15	0
+2797	0	2
+329	10	0
+2475	142825	142825
+382	4	0
+707	0	1
+12092	0	1
+2431	1	0
+158	0	1
+281	1	0
+1573	0	1
+11079	1	0
+6938	0	1
+14766	1	0
+4187	10	0
+11099	3	0
+9487	0	6
+467	1	0
+2143	1	0
+697	1	1
+25	0	6
+58	8	8
+1733	0	1
+259	2	0
+295	1	0
+128	0	1
+3052	0	1
+1419	13507	13507
+201	13	12
+15310	1	1
+26	1	1
+461	1	1
+33	0	2
+16	1	1
+649	1	1
+48	1	1
+818	1	1
+21	1	1
+424	1	1
+25	1	1
+632	1	1
+39	1	1
+310	1	1
+27	1	1
+616	1	0
+17240	4	0
+3936	3	0
+2976	174972	174972
+5315	0	20
+2124	0	1
+7445	45267	45267
+361	0	2
+1466	1	0
+6628	1	1
+110	0	1
+1422	0	1
+324	1	0
+1825	1	0
+311	0	1
+6568	1	0
+5228	1	0
+2273	2	1
+6123	1	0
+18640	29	29
+1283	0	3
+11560	6	6
+708	15	14
+1887	10	0
+509	1	0
+1581	1	1
+46	1	1
+811	1	1
+31	0	1
+1557	43	43
+1172	1	1
+18	1	1
+67	1	0
+2081	0	2
+373	0	4
+538	103035	103035
+2665	46	46
+554	0	21
+4473	2	3
+921	1	1
+47	1	1
+2605	9	3
+50	1	1
+178	1	1
+26	1	1
+316	0	2
+1120	4	0
+177	1	2
+960	1	1
+65	1	1
+964	4	4
+783	8	8
+61	34	13
+121	1	1
+22	1	0
+118	1	1
+49	4	4
+281	1	1
+27	1	1
+958	0	1
+107	1	1
+31	1	1
+171	14	14
+302	0	13
+33	1	1
+108	0	4
+98	1	1
+53	1	1
+986	1	1
+37	2	0
+1829	1	1
+38	1	1
+440	1	1
+82	3	4
+647	45	45
+660	1	1
+28	1	1
+1993	0	1
+373	19	19
+835	1	1
+42	1	1
+635	0	5
+307	1	1
+36	1	0
+1055	1	1
+43	1	1
+475	1	0
+60	1	1
+127	1	1
+509	1	1
+71	1	1
+485	1	0
+26	1	1
+531	1	1
+18	1	1
+551	1	1
+18	1	1
+884	5	5
+147	53	60
+527	1	1
+26	2	2
+322	0	17
+32	2	2
+85	1	1
+45	1	1
+625	0	323
+540	0	1
+43	1	1
+266	0	2
+228	1	1
+42	1	1
+283	1	1
+92	1	1
+381	1	1
+40	1	1
+1906	0	4
+3495	0	4
+561	36	36
+370	1	1
+76	1	1
+1824	3653	3651
+214	0	2
+499	1	0
+937	1	1
+45	1	1
+421	6	0
+87	22	22
+1254	1	1
+36	0	1
+357	18	18
+391	0	1
+451	1	0
+105	1	1
+47	1	0
+255	6	6
+739	3	0
+386	1	1
+33	1	1
+281	4	0
+481	2	0
+495	1	1
+42	4	0
+219	0	1
+408	1	1
+23	1	1
+283	1	1
+25	0	1
+541	1	0
+88	2	0
+216	1	1
+29	1	1
+457	1	0
+331	7	19
+181	15	15
+228	1	0
+4	2	0
+324	0	1
+3063	0	2
+11850	0	12
+839	0	1
+14260	0	2
+9658	4	3
+2813	12	12
+782	39571	39571
+1619	2	0
+164	8	1
+655	1	1
+30	1	1
+271	1	1
+47	1	1
+609	1	0
+516	1	1
+19	1	1
+1243	2	0
+742	1	1
+40	1	1
+3755	3	0
+13	1	1
+3819	0	1
+10010	1	0
+3051	1	1
+46	3322	3320
+1751	1	1
+103	1	2
+74	1	1
+93	1	0
+22	1	1
+149	4	0
+94	1	1
+31	7	0
+74	1	1
+275	1	0
+99	221094	247530
+272	5	5
+243	1	1
+84	1	1
+98	1	1
+50	5	5
+77	1	1
+74	1	1
+20	0	1
+143	1	1
+45	0	1
+4	1	1
+1088	1	1
+35	1	1
+320	1	1
+22	1	1
+275	1	1
+47	1	1
+370	19	19
+119	1	6
+51	1	1
+21	1	1
+244	0	1
+345	1	1
+24	1	1
+181	1	1
+61	3	3
+542	1	1
+16	1	1
+312	1	0
+353	4	3
+279	323	0
+86	1	1
+49	1	1
+342	1	1
+44	0	2
+222	1	1
+37	1	1
+588	8	8
+593	2	2
+44	1	1
+359	1	1
+25	1	1
+1612	14	14
+428	1	0
+2510	1	0
+5051	0	1
+1489	9	9
+3292	1	0
+1449	1	1
+21	1	1
+6768	1	0
+706	2	0
+6662	1	1
+30	1	1
+228	1	1
+28	0	2
+300	5	5
+887	1	1
+23	1	1
+104	9625	10000
+107	1	1
+47	0	1
+63	1	1
+114	1	1
+219	1	1
+63	9	9
+35	1	1
+290	0	4
+45	0	1
+54	0	1
+40	1	3
+21	6	6
+54	1	1
+41	1	1
+155	1	1
+29	1	1
+220	1	1
+27	1	1
+611	1	1
+163	1	1
+134	1	1
+16	1	0
+5	1	1
+151	15	15
+138	2	2
+27	1	1
+73	2	2
+97	1	1
+204	1	1
+47	1	1
+84	1	1
+74	2	2
+381	20	20
+425	1	1
+21	1	1
+71	1	1
+28	1	1
+245	25	22
+71	1	1
+93	1	0
+82	1	1
+129	1	1
+26	1	1
+294	16	16
+1139	0	1
+1588	0	1
+51	9	9
+60	26	25
+312	15	11
+1008	17	17
+85	1	1
+49	1	1
+702	1	0
+87	1	1
+37	1	1
+859	8	8
+296	4	4
+105	0	4
+43	1	1
+67	10	7
+2839	3	0
+1283	1	1
+67	0	1
+32	2	0
+61	1	1
+140	15	15
+1047	1	1
+38	1	1
+87	1	1
+24	5	4
+1291	1	1
+49	1	1
+421	0	1
+75	1	1
+78	1	1
+243	1	0
+33	1	1
+116	19	19
+65	0	1
+238	0	1
+179	2	1
+67	1	1
+60	1	1
+32	1	1
+677	4	6
+83	314	0
+334	1	0
+1018	5	5
+127	1	1
+83	1	1
+347	0	2
+111	1	1
+30	1	1
+66	1	1
+38	1	1
+218	8	8
+754	1	1
+65	1	1
+182	1	1
+21	1	1
+285	1	1
+75	1	1
+147	6	0
+65	1	1
+42	1	1
+380	1	1
+84	2	0
+88	1	1
+25	1	1
+210	1	1
+17	1	1
+136	6	5
+108	1	1
+40	1	0
+50	1	1
+111	1	0
+21	0	1066
+119	0	1
+2641	1	1
+22	1	1
+689	1	1
+41	1	1
+1415	1	1
+29	1	1
+2252	1	1
+19	1	1
+1524	0	10
+2104	0	1
+511	2	0
+1696	26	8
+2593	0	177
+338	1	1
+37	2	2
+395	10	0
+67	1	1
+131	1	1
+31	1	1
+386	1	1
+42	1	1
+372	1	1
+48	1	1
+8705	0	3
+330	9	9
+600	2	0
+261	8	8
+9909	0	2
+2337	2	0
+2567	1	1
+26	1	1
+561	1	1
+48	1	1
+2440	1	1
+30	1	1
+1289	0	1
+162	1	0
+730	0	3
+658	1	0
+25	1	1
+1027	1	1
+43	1	1
+472	0	1
+219	1	1
+20	1	1
+495	1	0
+6	2	0
+1007	0	1
+169	0	10
+33	1	1
+266	11	11
+752	1	1
+30	1	1
+438	1	1
+39	1	1
+511	0	1
+1247	1	0
+1055	1	0
+491	1	0
+108	1	1
+48	1	1
+1324	0	1
+143	1	1
+40	1	1
+679	1	1
+45	1	1
+1036	0	2
+58	1	1
+46	1	1
+229	16	16
+149	10	10
+94	1	1
+63	1	1
+222	1	0
+55	1	1
+115	5	1
+219	15	15
+692	28	28
+159	1	1
+41	1	1
+211	1	0
+20	1	1
+1099	0	4
+155	6	0
+178	13	15
+32	1	1
+953	1	1
+47	1	1
+174	1	1
+22	1	1
+401	0	13
+588	5	21
+130	1	1
+157	4	4
+86	1	1
+29	0	2
+67	3	0
+641	0	1
+571	0	1
+250	1	1
+34	1	1
+255	0	2
+572	12	12
+275	6	1
+974	0	1
+578	12	12
+612	1	1
+43	1	1
+56	0	7
+1170	0	1
+1236	0	4
+2118	5	0
+1090	0	2
+4424	1	1
+34	1	1
+4897	8	0
+2112	0	1
+2874	1	1
+21	1	1
+442	22	22
+805	0	1
+3476	16	0
+7063	0	1
+65	3	0
+4293	0	1
+3181	0	4
+9515	5	1
+172	1	1
+49	1	1
+320	1	1
+34	1	1
+10677	2	0
+4856	3	0
+6082	1	0
+955	0	1
+1720	6	0
+17	1	0
+8156	53709	53709
+819	9	0
+1244	1	1
+32	5	5
+2063	14	0
+357	3	0
+321	46	46
+873	1	1
+47	1	1
+1156	10	9
+1180	29	25
+247	9	9
+1870	0	1
+17	1	0
+366	7	7
+101	0	1
+134	8	8
+1654	0	4
+8741	1	1
+24	1	1
+991	0	210
+20	2	0
+906	13	13
+478	1	1
+21	1	1
+812	88	88
+2215	16	16
+1485	1	1
+18	1	1
+883	1	1
+20	1	1
+1354	1	1
+28	1	1
+283	5	5
+640	1	1
+40	1	1
+560	1	1
+42	1	1
+1144	19	19
+57	1	1
+21	1	1
+216	1	1
+109	1	1
+105	1	1
+208	5	5
+124	1	1
+112	3	3
+207	40	40
+244	1	1
+60	1	1
+98	1	1
+50	1	1
+256	5	5
+23	1	1
+157	1	1
+33	1	1
+143	1	1
+59	1	1
+51	1	1
+45	1	0
+73	1	1
+81	1	1
+427	1	1
+115	1	1
+232	1	1
+94	1	1
+809	1	0
+2261	16	15
+1824	1	0
+1990	1	0
+9965	0	18
+2951	6	0
+798	1	1
+30	1	1
+159	1	1
+124	1	1
+661	1	1
+31	1	1
+2632	4	4
+4024	0	16
+9373	7	7
+8626	0	1
+316	0	26
+10715	6	6
+110	1	1
+25	0	1
+7753	1	1
+30	0	1
+4078	0	2
+5144	1	1
+36	1	1
+69	1	1
+21	1	1
+135	1	1
+85	1	1
+125	3	4
+128	5	5
+24	1	1
+91	1	1
+61	15	0
+69	1	1
+78	0	19
+64	1	1
+138	1	1
+31	1	1
+510	18	7
+161	1	1
+30	1	1
+119	1	1
+26	1	1
+291	2	1
+143	1	1
+29	1	1
+293	1	1
+158	4	4
+87	32	32
+778	1	1
+58	0	1
+127	1	1
+75	28	0
+26	0	2
+204	207869	207869
+1739	1	0
+702	0	1
+5133	0	2
+3096	1	0
+315	1	0
+490	0	1
+2588	3	0
+1013	0	1
+3659	1	0
+2412	1	2
+2723	4	0
+523
+
+chain	80965	chr6_apd_hap1	4622290	+	2323391	2324248	chr6	170899992	-	139781917	139782778	1559018
+341	0	4
+516
+
+chain	30899	chr6_apd_hap1	4622290	+	1238363	1238687	chr13	114142980	+	81787211	81787535	4477038
+324
+
+chain	29563	chr6_apd_hap1	4622290	+	3995951	3996260	chr1	247249719	-	75038034	75038343	4838475
+309
+
+chain	28633	chr6_apd_hap1	4622290	+	2292529	2292831	chr7	158821424	-	147037095	147037398	5180885
+171	0	1
+131
+
+chain	28481	chr6_apd_hap1	4622290	+	4061349	4061647	chr17	78774742	+	29063769	29064067	5407270
+298
+
+chain	23990	chr6_apd_hap1	4622290	+	1105022	1105798	chr7	158821424	-	51137320	51138262	7695539
+178	101	101
+72	385	551
+40
+
+chain	15671	chr6_apd_hap1	4622290	+	1097871	1099106	chr6	170899992	-	139552636	139553881	14365447
+56	408	416
+54	620	622
+97
+
+chain	15338	chr6_apd_hap1	4622290	+	4034892	4035065	chr1	247249719	-	181871461	181871634	14713407
+25	1	0
+58	0	1
+89
+
+chain	13894	chr6_apd_hap1	4622290	+	1139363	1141753	chr6	170899992	+	30021566	30022999	16323533
+75	1920	964
+70	255	254
+70
+
+chain	11891	chr6_apd_hap1	4622290	+	3988844	3989392	chrX	154913754	+	64750681	64751228	19168306
+89	401	400
+58
+
+chain	11819	chr6_apd_hap1	4622290	+	1140317	1140448	chr19	63811651	+	15986621	15986752	19293908
+131
+
+chain	11746	chr6_apd_hap1	4622290	+	1091182	1091330	chr7	158821424	-	7754727	7754875	19419742
+54	14	14
+80
+
+chain	9888	chr6_apd_hap1	4622290	+	4031953	4032128	chr8	146274826	+	50466266	50466441	23070160
+60	56	56
+59
+
+chain	9560	chr6_apd_hap1	4622290	+	1092932	1093033	chr6	170899992	-	141000133	141000234	23851264
+101
+
+chain	7776	chr6_apd_hap1	4622290	+	4298814	4298901	chr8	146274826	+	14484871	14484958	2851549
+87
+
+chain	6175	chr6_apd_hap1	4622290	+	1094444	1094508	chr6	170899992	+	30079296	30079360	30094026
+64
+
+chain	6113	chr6_apd_hap1	4622290	+	3989871	3989936	chrX	154913754	-	39339630	39339695	30268027
+65
+
+chain	5831	chr6_apd_hap1	4622290	+	3989150	3989212	chr2	242951149	+	73586935	73586997	31012834
+62
+
+chain	5731	chr6_apd_hap1	4622290	+	1104489	1104550	chr6	170899992	+	29872087	29872148	31286972
+61
+
+chain	5730	chr6_apd_hap1	4622290	+	1107647	1107707	chr6	170899992	+	29878483	29878543	31293431
+60
+
+chain	5676	chr6_apd_hap1	4622290	+	1093802	1093862	chr8	146274826	-	42258664	42258724	31433499
+60
+
+chain	5492	chr6_apd_hap1	4622290	+	4034227	4034285	chr22	49691432	-	27111287	27111345	17799541
+58
+
+chain	5339	chr6_apd_hap1	4622290	+	3987866	3987922	chr2	242951149	+	186720203	186720259	32420506
+56
+
+chain	5203	chr6_apd_hap1	4622290	+	3989590	3989645	chr5	180857866	+	19136434	19136489	32834289
+55
+
+chain	4712	chr6_apd_hap1	4622290	+	4038649	4038699	chr4	191273063	+	53804403	53804453	34512110
+50
+
+chain	4392	chr6_apd_hap1	4622290	+	1105241	1105300	chr7	158821424	-	126060926	126060985	9905437
+59
+
+chain	2852	chr6_apd_hap1	4622290	+	4034783	4034846	chr15	100338915	+	44177073	44177136	17837211
+63
+
+chain	2740	chr6_apd_hap1	4622290	+	3988933	3988962	chr7	158821424	+	83092272	83092301	22772951
+29
+
+chain	2440	chr6_apd_hap1	4622290	+	3988349	3988416	chr3	199501827	+	102678562	102678629	22367094
+67
+
+chain	2360	chr6_apd_hap1	4622290	+	4034867	4034892	chr4	191273063	-	72949130	72949155	34483441
+25
+
+chain	2247	chr6_apd_hap1	4622290	+	4033024	4033048	chr20	62435964	-	19518135	19518159	35490184
+24
+
+chain	2194	chr6_apd_hap1	4622290	+	1105201	1105241	chrX	154913754	-	101365357	101365397	11073770
+40
+
+chain	2146	chr6_apd_hap1	4622290	+	1091395	1091456	chr12	132349534	+	104221177	104221238	23825288
+61
+
+chain	2000	chr6_apd_hap1	4622290	+	1105373	1105406	chr4	191273063	+	153905795	153905828	8127683
+33
+
+chain	1977	chr6_apd_hap1	4622290	+	3989088	3989138	chr18	76117153	-	10057795	10057845	19617710
+50
+
+chain	1946	chr6_apd_hap1	4622290	+	1105615	1105690	chr1	247249719	-	137852311	137852386	12720712
+75
+
+chain	1584	chr6_apd_hap1	4622290	+	1105480	1105544	chr1	247249719	-	24894387	24894451	17598706
+64
+
+chain	1098	chr6_apd_hap1	4622290	+	4034150	4034227	chr3	199501827	+	101474041	101474118	17425868
+77
+
+chain	917	chr6_apd_hap1	4622290	+	4034367	4034423	chr8	146274826	+	48207051	48207107	19960483
+56
+
+chain	847	chr6_apd_hap1	4622290	+	3988270	3988330	chr20	62435964	-	51574691	51574751	25106564
+60
+
+chain	754	chr6_apd_hap1	4622290	+	3988131	3988185	chr6	170899992	+	30241568	30241622	20370721
+54
+
+chain	747	chr6_apd_hap1	4622290	+	1105904	1105968	chr12	132349534	+	55464534	55464598	20643869
+64
+
+chain	716	chr6_apd_hap1	4622290	+	3989517	3989569	chr16	88827254	-	38714794	38714846	22851158
+52
+
+chain	604	chr6_apd_hap1	4622290	+	1105798	1105824	chrX	154913754	-	101148638	101148664	11583040
+26
+
+chain	420574415	chr6_cox_hap2	4795371	+	0	4795371	chr6	170899992	+	28585775	33459520	26
+95659	1	0
+2669	19	19
+7247	1	2
+1704	0	4
+1513	0	2
+49	2	0
+2160	0	5
+672	1	1
+38	1	1
+1384	1	0
+1685	1	1
+30	1	1
+2421	1	1
+42	1	1
+830	1	1
+41	1	1
+1630	0	1
+7458	1	0
+691	0	1
+525	0	1
+79	1	1
+29	1	1
+2055	1	1
+16	0	24
+1867	5	7
+786	0	2
+280	0	1
+227	2	0
+6678	1	0
+4401	1	0
+210	1	0
+3193	2	0
+3619	0	1
+2414	0	2
+5387	0	3
+2927	0	1
+3304	0	1
+440	0	5
+415	0	9
+3597	1	1
+48	1	1
+3412	1	1
+46	1	1
+3604	4	4
+1063	1	1
+36	1	1
+6311	0	1
+35	0	8
+393	0	1
+477	1	1
+37	1	1
+2459	2	0
+517	0	12
+318	0	1
+1010	7	6
+2103	0	1
+5171	0	8
+1483	1	0
+3813	888	0
+4675	0	2
+5620	1	0
+2017	1	0
+3363	0	5
+1197	0	3
+3208	1	0
+1928	1	0
+174	6	0
+780	1	3
+443	14	0
+3079	0	5
+1993	0	3
+1089	1	1
+58	1	1
+80	0	8
+256	2	0
+2473	37	43
+752	0	2
+33	0	2
+825	0	1
+787	1	1
+37	1	1
+1168	16	0
+377	5	1
+27	1	1
+2161	2	0
+2324	1	0
+1757	6	6
+205	4	0
+203	7	7
+107	1	1
+28	1	1
+100	4	4
+258	5	0
+659	1	0
+3805	5	8
+1486	4	4
+213	39	43
+4429	0	2
+1199	13	13
+5814	18	6
+2970	0	1
+813	0	17
+920	2	0
+3820	1	3
+130	21	9
+1913	0	14
+1800	0	1
+1255	2	0
+1466	4	0
+747	0	1
+124	2	0
+2108	1	0
+169	0	26
+593	1	0
+632	5	0
+2711	0	4
+1042	0	1
+34	1	1
+1025	2	0
+27	4	18
+81	1	33
+33	0	1
+6	0	76
+3950	1	0
+86	1	1
+12	1	1
+2947	0	1
+1160	1	0
+2046	3	0
+720	1	0
+1341	1	0
+10205	0	5
+1265	1	0
+10	1	1
+1278	5	6
+340	9	9
+50	0	32
+96	16	18
+605	4	0
+1072	12	12
+950	11	7
+5137	0	1
+2711	1	0
+676	0	1
+2904	1	1
+30	1	1
+851	0	1
+1410	0	1
+394	1	1
+57	1	1
+1561	0	2
+14360	1	1
+42	1	1
+269	1	0
+284	3	3
+24	1	0
+2796	0	5
+2451	28	0
+2251	1	1
+32	1	0
+10	0	4
+24	1	1
+694	0	2
+3475	0	1
+2008	1	1
+49	1	1
+475	1	1
+28	1	1
+259	160	0
+1854	5	4
+1621	3	0
+1791	1	0
+316	0	2
+1169	0	1
+2549	1	0
+2941	1	1
+34	1	1
+243	9	0
+5157	0	2
+1748	0	8
+472	4	0
+2470	0	4
+402	1	0
+643	2	0
+748	0	2
+859	1	0
+409	2	0
+267	0	2
+322	0	4
+155	1	0
+9957	0	4
+1440	4	4
+127	1	0
+1085	1	0
+131	1	0
+767	1	0
+1160	21	21
+1294	1	0
+712	1	0
+1819	2	1
+464	1	0
+6944	0	4261
+55	0	7
+1235	0	3
+702	0	24
+2847	0	1
+2428	3	0
+7517	0	1
+3204	1	0
+611	1	0
+7104	1	0
+4959	14	14
+2827	1	0
+9421	82	25
+2434	43	43
+1951	8	0
+8136	0	2
+344	1	0
+4216	1	0
+810	0	5
+4443	1	0
+10291	10	0
+7265	5	0
+7041	1	0
+6007	1	0
+8185	4	0
+4961	0	3
+13564	0	1
+1475	0	2
+105	0	10
+10104	2	0
+3073	1	0
+3715	8	0
+13731	0	2
+837	61	1
+9404	0	1
+6068	7	0
+916	0	4
+569	1	1
+72	1	1
+2260	0	2
+7036	4	0
+3591	0	3
+713	4	0
+10388	0	2
+8475	0	1
+1324	0	2
+5438	5	0
+156	1	1
+44	0	1
+21501	7	7
+3359	16	16
+2138	0	5
+4406	11	11
+1525	1	1
+28	1	1
+2159	16	0
+48	4	0
+3030	0	1
+5717	10	0
+6594	2	0
+1954	1	0
+4	1	0
+3599	1	0
+7515	4	0
+979	0	2
+1990	0	10
+123	1	1
+27	1	1
+1255	0	2
+2769	5	5
+727	1	1
+26	3	3
+785	0	1
+24359	1	0
+5978	5	5
+66	1	1
+46	1	1
+18539	1	0
+7732	2	0
+652	0	1
+861	0	1
+11988	0	1
+3515	3	0
+19	18	0
+539	0	1
+655	2	0
+10586	2	0
+2385	0	1
+2979	10	10
+4600	1	0
+29834	1	1
+27	1	1
+1216	1	0
+1323	1	0
+673	0	3
+20031	0	3
+2841	13	0
+1841	4	0
+6446	1	0
+11727	0	1
+8427	17	17
+2864	0	143
+4107	0	8
+748	0	2
+3417	1	1
+32	1	1
+18799	0	2
+21810	1	1
+34	1	1
+2784	2	0
+7864	2	0
+4498	0	1
+49089	1	1
+32	1	1
+509	1	1
+37	1	1
+5371	22	16
+389	1	1
+21	1	1
+806	1	0
+1638	6	6
+228	1	1
+45	1	1
+2068	6	3
+441	1	0
+2338	1	0
+1948	1	1
+26	1	1
+214	0	1
+6118	1	1
+31	1	1
+2382	5	5
+4335	1	1
+39	1	1
+4561	1	1
+38	1	1
+2199	1	1
+49	1	1
+243	19	6
+2779	1	1
+37	2	0
+24	1	1
+1966	3	0
+233	1	1
+29	1	1
+13756	0	4
+3956	4	1
+46569	1	0
+18985	0	8
+1384	3	1
+85	1	0
+3539	1	1
+32	1	1
+145	1	0
+1245	2	0
+1736	1	1
+29	1	1
+1656	1	5
+712	10	11
+502	0	1
+3670	1	0
+740	0	1
+1693	0	1
+6497	0	2
+2898	1	3
+141	0	1
+1108	0	2
+1448	1	0
+947	31	31
+362	0	1
+7684	8	0
+2880	1	2
+30	8	0
+896	21	3
+395	1	1
+37	3	0
+23	1	2
+1210	18	0
+65	1	1
+20	1	1
+791	0	4
+389	1	0
+809	1	1
+55	0	7
+428	1	1
+17	1	1
+239	1	1
+20	1	1
+69	1	1
+37	1	1
+955	1	0
+839	0	1
+165	1	0
+3867	0	5
+70	1	1
+27	1	1
+899	1	2
+107	1	0
+1457	1	0
+763	12	5
+35	1	1
+1417	10	10
+121	1	1
+38	0	3
+377	1	0
+505	1	0
+11	4	0
+297	0	24
+337	11	0
+134	1	1
+694	3	0
+72	1	1
+144	128	128
+169	2	0
+1011	1	0
+107	1	1
+1280	1	1
+73	1	1
+84	25	25
+287	1	1
+26	1	1
+139	1	1
+41	1	1
+440	4	0
+130	12	12
+435	21	0
+85	1	1
+28	1	1
+73	1	1
+115	5	1
+70	1	2
+52	2	0
+157	30	30
+554	2	2
+128	1	5
+68	1	1
+44	1	1
+125	0	1
+57	1	1
+308	0	7
+15	1	1
+725	9	0
+60	1	1
+180	1	1
+55	1	1
+61	1	1
+23	1	0
+5	1	2
+88	1	1
+56	1	1
+433	2	0
+84	1	1
+66	1	1
+182	12	12
+216	1	1
+94	1	1
+561	1	1
+16	1	1
+113	1	1
+86	1	1
+148	2	0
+75	2	0
+77	1	21
+209	3	8
+99	31	31
+244	1	0
+173	4	3
+201	1	1
+42	1	1
+56	1	1
+115	1	0
+327	1	1
+54	5	5
+929	1	1
+21	1	1
+97	1	1
+28	0	3
+830	0	2
+68	1	1
+525	0	1
+2081	1	1
+41	1	1
+165	3	3
+46	1	0
+378	1	1
+49	1	1
+352	0	1
+142	1	1
+30	1	1
+95	1	1
+45	1	1
+227	1	1
+53	1	1
+130	1	1
+18	1	1
+138	1	1
+90	1	1
+129	1	1
+39	1	1
+50	1	1
+79	1	1
+117	1	1
+31	1	1
+240	5	5
+57	1	1
+152	1	1
+30	1	1
+177	5	5
+321	1	1
+63	1	1
+504	18	18
+662	1	1
+74	1	1
+248	1	1
+34	1	1
+1507	0	10
+1051	0	2611
+560	3	3
+23	1	1
+1631	0	15
+78	4	0
+160	0	21
+3764	0	4
+1358	0	1
+1773	1	1
+43	1	1
+1263	1	1
+39	1	1
+183	0	16
+3001	40	40
+1056	10	0
+1261	1	1
+20	1	1
+137	1	0
+2351	1	1
+43	1	1
+1010	0	4
+536	1	1
+38	1	1
+381	0	1
+888	19	19
+1521	1	1
+27	1	1
+161	1	1
+46	1	1
+2659	2	0
+533	10	0
+441	1	12
+1684	1	1
+26	3	4
+879	16	16
+514	0	2
+58	1	1
+117	1	1
+24	1	1
+207	1	0
+38	1	1
+730	1	1
+39	1	1
+573	0	4
+37	1	1
+144	8	8
+1036	2	0
+262	2	2
+38	0	1
+70	18	18
+84	11	13
+317	0	3
+1256	0	2
+332	1	1
+21	1	1
+193	8	28
+30	1	1
+79	1	1
+29	1	1
+536	1	0
+611	1	1
+25	1	1
+399	4	4
+118	0	32
+23	1	1
+116	1	1
+30	1	1
+503	1	1
+22	0	3
+136	1	1
+48	1	1
+330	9	9
+1108	1	1
+98	1	1
+582	0	4
+711	7	7
+89	1	0
+291	1	0
+167	1	1
+24	1	1
+167	6	6
+171	17	17
+681	1	1
+43	1	1
+538	1	1
+44	1	1
+537	16	16
+180	6	6
+778	2	2
+44	1	1
+168	0	7
+211	1	1
+42	1	1
+1253	1	1
+29	1	1
+320	1	1
+36	2	2
+55	1	2
+460	1	1
+35	1	1
+553	8	8
+386	1	1
+26	1	1
+540	1	1
+31	1	1
+65	0	1
+625	12	12
+313	0	1
+52	1	1
+22	1	1
+583	1	1
+49	1	1
+1499	3	0
+770	1	1
+87	11	0
+323	19	19
+787	1	1
+36	1	1
+553	8	8
+997	16	15
+157	1	1
+31	2	2
+204	18	19
+487	1	1
+29	1	1
+374	1	1
+67	1	1
+720	13	13
+266	10	10
+330	16	14
+413	1	1
+44	1	1
+78	6	6
+181	2	2
+36	1	1
+397	1	1
+20	1	1
+311	1	1
+48	2	2
+1746	4	4
+35	1	1
+194	10	10
+310	1	1
+51	1	1
+136	1	1
+49	1	1
+521	1	1
+23	1	1
+220	73	73
+735	3	3
+123	1	1
+184	15	15
+216	1	1
+21	1	1
+51	1	1
+49	1	1
+527	17	17
+340	12	11
+1025	1	0
+2572	1	1
+29	1	1
+397	2	5
+668	13	13
+541	1	1
+59	0	2
+6	1	1
+122	14	14
+51	1	1
+46	1	1
+429	0	21
+136	1	1
+12	1	1
+66	16	16
+456	37	34
+371	7	7
+48	1	1
+194	10	10
+108	1	1
+60	1	1
+122	49	50
+238	1	1
+32	0	1
+100	1	0
+72	1	0
+390	1	1
+38	1	1
+144	1	1
+27	0	4
+184	21	228
+49	1	1
+608	0	1
+152	1	1
+31	1	1
+281	8	8
+337	1	1
+45	1	1
+222	1	1
+20	1	1
+380	1	0
+44	1	1
+368	1	1
+72	1	1
+502	36	18
+63	1	1
+43	0	4
+136	1	1
+42	1	1
+80	4	4
+35	1	0
+89	1	1
+24	0	5
+829	13	13
+102	14	0
+233	1	1
+42	0	3
+85	0	1
+400	1	1
+40	1	1
+538	25	25
+174	1	1
+20	1	1
+705	1	1
+26	2	2
+614	1	1
+44	1	1
+509	1	1
+32	1	1
+224	1	1
+42	1	1
+99	38	38
+610	5	5
+804	1	1
+29	1	1
+166	1	1
+43	1	1
+233	1	1
+44	1	1
+620	8	8
+133	1	1
+31	1	1
+165	1	1
+29	1	1
+1249	1	1
+26	4	0
+56	1	1
+67	1	1
+716	1	1
+46	0	1
+16	1	1
+174	1	1
+96	1	1
+141	1	1
+39	0	4
+263	1	1
+18	1	1
+259	4	4
+38	1	1
+104	1	1
+40	1	0
+248	1	1
+18	1	1
+238	1	1
+32	1	1
+70	0	2
+16	1	1
+818	1	1
+22	4	4
+1641	1	1
+46	1	1
+53	1	0
+38	1	1
+373	62	62
+1149	0	2
+19	1	1
+1653	4	4
+42	1	1
+218	12	12
+363	1	1
+24	1	1
+457	10	10
+414	13	13
+825	1	1
+41	1	1
+492	0	8
+1370	1	1
+18	1	1
+1145	6	4
+880	1	1
+35	1	1
+236	1	1
+67	1	1
+298	0	1
+147	14	14
+312	11	11
+613	1	1
+62	1	1
+340	1	1
+22	1	1
+1057	1	1
+57	1	1
+358	1	1
+128	1	1
+146	10	10
+490	1	1
+20	1	1
+62	1	1
+88	1	1
+293	1	1
+28	1	0
+20	1	1
+83	0	1
+90	1	1
+312	1	1
+44	1	1
+1213	1	1
+51	1	1
+467	1	1
+39	1	1
+122	14	0
+35	1	1
+485	14	14
+110	13	0
+127	1	1
+7112	0	8
+45	4	0
+3276	0	2
+28	1	1
+2195	17	16
+1325	18	18
+1304	3727	0
+299	0	248
+2603	2	0
+160	1	1
+34	1	1
+631	1	1
+40	1	3
+38	1	1
+332	17	17
+231	14	14
+202	1	1
+199	1	1
+71	1	1
+42	1	0
+53	11	10
+83	1	1
+31	1	1
+135	1	1
+50	3	0
+32	1	1
+194	1	1
+45	1	1
+143	1	1
+78	1	1
+193	6	0
+40	1	1
+432	1	1
+17	1	1
+429	3	6
+58	236	236
+57	1	1
+51	2	2
+278	1	1
+49	1	1
+77	11	11
+120	0	4
+139	1	1
+30	2	2
+205	4	4
+131	1	1
+22	1	1
+251	1	1
+34	1	1
+175	1	1
+36	1	1
+239	1	1
+32	5	5
+63	1	1
+27	1	1
+78	1	1
+19	1	1
+209	1	1
+143	1	13
+176	0	1
+7	0	8
+375	0	1
+62	1	1
+129	2	2
+135	1	1
+88	8	0
+90	6	8
+796	2	0
+1219	1	1
+34	1	1
+833	1	1
+46	1	1
+74	1	1
+45	1	1
+95	1	1
+29	1	1
+298	0	3
+47	1	1
+311	1	1
+58	1	1
+349	9	9
+214	1	1
+37	3	0
+413	11	11
+54	1	1
+97	1	1
+137	0	2
+95	1	1
+257	3	0
+35	1	1
+66	1	1
+47	1	1
+104	7	7
+220	17	17
+207	44327	50000
+112	1	1
+39	1	1
+330	1	1
+24	1	1
+197	1	1
+69	1	1
+116	3	0
+161	1	1
+38	1	1
+753	1	1
+57	3	3
+145	1	1
+121	1	1
+300	1	1
+147	1	1
+379	1	1
+55	2	2
+65	1	1
+32	1	1
+1008	1	1
+24	1	1
+159	18	18
+659	1	1
+76	0	2
+77	1	3
+65	1	1
+84	1	0
+119	1	1
+15	1	1
+247	4	0
+372	1	0
+1633	1	1
+16	1	1
+456	7	7
+114	1	1
+102	1	1
+109	4	0
+61	2	2
+80	1	1
+47	1	1
+168	1	1
+31	1	1
+269	2	2
+42	1	1
+626	2	2
+14	1	1
+76	8356	10147
+66	2	2
+80	0	41
+12	1	1
+158	1	0
+92	2	0
+254	1	1
+43	1	1
+846	6	149
+84	1	1
+29	3	3
+315	17	17
+482	1	1
+29	3	3
+278	1	1
+73	1	1
+2767	1	1
+34	1	1
+192	1	1
+33	1	0
+168	6	0
+276	10	10
+344	1	1
+49	1	1
+109	1	1
+35	3	3
+561	24	27
+923	1	1
+102	1	1
+75	14	14
+266	1	1
+80	2	2
+185	1	0
+1035	1	1
+23	1	1
+417	10	10
+97	1	1
+94	1	1
+492	1	1
+37	5	5
+1429	1	1
+19	1	1
+839	1	1
+96	1	1
+1279	4	0
+683	1	1
+49	1	1
+514	1	1
+28	4	4
+2302	1	1
+42	1	1
+537	2	21
+1555	1	1
+42	0	1
+14	4	4
+86	1	1
+62	1	1
+515	5	1
+330	0	1
+159	0	22
+3841	1	0
+3862	16	16
+1187	12	12
+97	0	3
+772	1	1
+21	2	1
+1058	0	2
+349	2	0
+1080	6	0
+11	1	3
+53	0	2
+14	1	1
+1035	1	1
+85	1	1
+69	1	1
+27	1	1
+547	7	7
+195	1	1
+41	1	1
+395	1	1
+35	1	1
+73	0	1
+71	1	1
+557	3	3
+30	1	1
+66	1	1
+25	1	1
+1332	0	2
+26	2	0
+10	1	15
+36	1	1
+196	1	1
+40	1	1
+141	1	1
+76	1	1
+1480	1	3
+347	1	1
+26	1	1
+231	1	1
+82	3	3
+69	3	0
+441	16	16
+147	1	1
+21	1	1
+3565	0	3
+877	2	0
+1036	1	1
+47	2	1
+3761	12	0
+5345	1	0
+11541	1	0
+1843	0	4
+1157	16	16
+7354	19	0
+741	0	1
+8053	1	0
+4449	21	21
+649	1	0
+2913	0	1
+381	331	0
+3533	31	31
+2502	0	1
+1968	7	0
+3198	1	0
+667	1	0
+3870	0	1
+36	13	0
+1894	1	1
+40	0	4
+1137	6	0
+211	2	0
+345	1	0
+592	4	4
+1043	4	0
+686	14	0
+1032	0	1
+9035	0	4
+167	0	2
+23964	0	3
+1470	0	1
+289	3	0
+4343	1	0
+2026	8	0
+430	0	1
+631	1	1
+21	1	1
+479	0	1
+697	4	0
+1779	1	1
+27	1	1
+196	4	0
+58	8	0
+2881	1	1
+39	1	1
+120	1	2
+24	1	1
+556	1	0
+393	6	6
+3090	1	1
+43	1	1
+1246	1	0
+294	1	1
+27	1	1
+374	3	3
+144	1	1
+190	1	6
+750	1	0
+695	2	0
+1003	11	0
+1956	0	4
+1235	19	19
+1483	11	11
+453	1	0
+536	1	1
+43	1	1
+57	1	0
+21	7	0
+3892	0	1
+3177	0	1
+8990	0	2
+2267	1	1
+35	1	0
+2850	4	0
+1273	0	2
+5863	1	0
+9593	1	1
+81	1	1
+2777	0	2
+5272	0	8
+11548	2	0
+6086	0	1
+109	1	1
+2286	0	1
+997	0	18
+3344	1	1
+40	1	1
+842	28	24
+1584	1	0
+1582	0	1
+1670	3	25
+17	0	4
+16	2	0
+6	12	0
+49	1	1
+538	1	1
+26	1	1
+5879	2	4
+2513	0	1
+346	8	8
+222	16	16
+103	1	0
+198	1	3
+539	1	1
+47	1	1
+1154	0	1
+3737	1	2
+370	2	0
+1178	1	1
+78	1	1
+47	0	1
+518	6	0
+646	13	13
+469	1	0
+1072	1	4
+858	1	0
+3674	1	0
+282	1	0
+597	0	6
+505	4	4
+183	1	1
+43	1	1
+1294	1	1
+40	1	1
+572	0	4
+464	0	4
+1886	2	0
+548	1	0
+1300	0	3
+1839	2	0
+189	1	1
+49	1	1
+1253	1	1
+43	1	0
+498	1	1
+45	4	0
+3538	0	1
+1582	31	31
+376	14	14
+1332	2	0
+3586	1	0
+989	1	2
+447	0	4
+40	1	1
+2445	16	17
+291	1	3
+7	1	0
+11	0	1
+41	1	1
+94	1	1
+49	1	1
+1515	6	0
+603	13	13
+163	1	1
+45	1	1
+2050	11	11
+1126	1	1
+16	1	1
+391	1	1
+19	0	1
+932	1	0
+42	1	1
+751	1	0
+287	1	1
+42	1	1
+464	0	4
+4069	5	5
+153	1	0
+514	2	0
+1093	1	1
+41	1	1
+1746	4	4
+1351	1	1
+38	1	1
+1213	0	72
+168	18	18
+146	7	7
+293	1	1
+61	0	1
+43	1	1
+236	1	0
+35	1	1
+152	14	14
+240	13	13
+523	0	4
+809	4	0
+155	1	1
+44	1	1
+1068	1	1
+93	1	1
+209	15	15
+1331	0	3
+3912	0	1
+6624	0	4
+375	0	1
+7255	5	0
+419	2	0
+293	1	0
+10397	5	24
+11095	0	1
+1770	4	0
+374	0	4
+7714	1	0
+1229	7	6
+3055	1	0
+5818	1	0
+2415	11	9
+2056	0	1
+955	4	0
+3907	0	2
+16936	0	1
+1044	1	0
+2392	0	1
+158	2	1
+199	0	1
+75	6	6
+2094	8	0
+649	2	0
+373	1	1
+39	1	1
+2287	1	0
+15	1	0
+1995	0	2
+818	4	0
+676	0	1
+3171	8	0
+170	0	3
+459	1	1
+37	1	1
+336	1	0
+206	1	1
+26	1	1
+224	15	15
+308	2	1
+82	1	1
+23	1	1
+562	1	1
+80	1	1
+241	0	8
+1530	1	1
+20	1	1
+1372	1	1
+44	1	1
+427	1	1
+20	1	1
+651	105	81
+221	1	1
+45	1	1
+1747	1	1
+27	1	1
+179	1	1
+70	1	1
+173	1	1
+84	0	36
+1864	1	1
+41	1	1
+44	9	0
+1028	1	0
+85	1	1
+21	1	1
+474	1	3
+256	1	1
+31	1	1
+653	1	1
+18	1	1
+62	1	1
+19	1	1
+997	1	1
+22	1	1
+326	1	0
+505	5	4
+386	0	7
+466	13	13
+870	11	12
+134	15	15
+248	0	2
+2281	1	1
+79	1	1
+56	9	6
+528	1	1
+68	1	1
+802	1	0
+290	1	1
+38	1	1
+185	1	1
+61	1	1
+944	1	1
+22	1	1
+835	1	1
+66	1	1
+890	0	1
+3503	6	6
+231	0	1
+2136	1	0
+999	1	0
+5220	3	4
+830	1	1
+24	1	1
+1209	1	1
+38	1	1
+7077	1	0
+2939	1	0
+3511	47	47
+401	0	2
+3746	0	2
+1011	1	1
+34	1	1
+7443	0	1
+688	2	0
+574	1	1
+29	1	1
+1785	2	0
+16	20	0
+4073	2	0
+136	79	79
+528	27	0
+253	0	1
+204	1	0
+129	2	0
+811	1	1
+38	1	1
+2347	52	0
+4634	1	0
+856	14	14
+1052	1	1
+28	1	1
+1255	1	1
+36	1	1
+97	0	1
+58	1	1
+1708	1	1
+48	1	1
+958	13	0
+3371	1	1
+37	1	1
+4267	0	15
+1059	0	1
+272	0	20
+168	2	0
+26	4	32
+4090	0	2
+3269	1	1
+17	1	2
+1378	1	0
+1443	0	1
+6206	1	0
+2318	0	1
+7695	2	0
+396	22	12
+918	0	1
+1818	0	1
+28	1	1
+492	1	1
+33	1	1
+326	1	1
+80	1	1
+288	8	17
+2671	0	1
+1099	0	1
+144	1	1
+29	0	1
+2098	0	2
+24	4	0
+1207	4	4
+45	1	1
+757	0	5
+1926	1	1
+40	1	1
+2657	0	1
+414	1	0
+61	0	1
+235	0	2
+2087	0	1
+713	0	4
+58	1	0
+1027	3	0
+428	1	1
+17	1	1
+948	1	1
+41	1	1
+458	1	1
+21	1	1
+1055	0	1
+8189	4	5
+36	1	1
+102	2	0
+14	1	1
+682	0	6
+147	0	1
+750	0	3
+40	1	1
+2428	0	1
+750	2	0
+473	0	2
+2032	1	0
+3841	1	0
+560	1	0
+1108	1	0
+8087	1	0
+11881	1	1
+30	1	1
+4383	2	0
+10078	0	1
+906	2	0
+887	1	1
+80	1	1
+2210	1	0
+905	0	1
+1037	1	0
+5866	0	2
+18	1	1
+582	0	5
+2828	1	0
+847	1	0
+1996	4	0
+700	1	1
+2469	1	0
+1751	0	1
+910	2	0
+691	0	1
+32873	0	1
+1722	0	1
+17575	0	8
+1369	29	0
+494	2	0
+4432	0	1
+34617	0	1
+920	0	1
+4586	0	2
+2232	1	0
+5718	0	1
+12415	1	1
+51	0	1
+7997	0	2
+1700	1	0
+2697	1	0
+2561	2	0
+1544	0	6
+1613	3	7
+37	9	1
+2113	1	0
+7174	0	34
+7914	1	1
+35	1	1
+5308	1	0
+2303	2	1
+423	7	7
+590	1	0
+24	1	1
+165	6	0
+896	33	33
+1919	13	13
+64	0	1
+28	1	1
+723	0	4
+2868	0	1
+731	1	1
+60	1	1
+1012	3	0
+1744	1	1
+78	1	1
+61	1	0
+2362	11	11
+399	1	0
+1494	16	16
+128	24	24
+530	1	1
+35	1	1
+5276	1	0
+415	0	1
+580	1	2
+1450	22	23
+816	1	0
+1953	1	0
+881	10	1
+885	8	14
+183	14	14
+1319	1	1
+94	1	1
+419	3	3
+26	1	1
+56	1	0
+69	1	0
+117	1	1
+120	1	1
+42	1	1
+834	125	127
+956	3	0
+664	1	1
+41	1	1
+716	4	0
+1731	8	8
+4228	0	1
+5694	3	0
+4493	0	1
+1373	20	20
+1263	1	0
+3029	4	0
+5702	7	6
+150	2	0
+5972	0	2
+840	0	2
+55	1	1
+28	1	1
+2949	5	6
+4343	6	0
+1663	4	0
+150	1	0
+3128	1	0
+1449	3	0
+1534	1	0
+489	1	0
+431	0	4
+299	2	0
+5082	9	0
+156	1	1
+256	0	1
+992	14	16
+4924	0	1
+6655	1	0
+349	8	7
+762	1	1
+29	0	3
+1434	0	1
+1267	0	1
+587	1	1
+22	0	1
+894	28	0
+1343	2	0
+2256	0	1
+4332	0	4
+22	1	1
+5069	33	33
+7313	12	10
+10485	0	1
+1429	0	12
+625	1	7
+1224	0	10
+1680	4	0
+9061	0	8
+2544	0	140
+5451	33	33
+3754	0	1
+1575	0	3
+1775	1	1
+31	1	1
+1200	1	0
+32	0	3
+790	0	8
+42	0	2
+599	1	1
+22	1	1
+5338	2	0
+1998	0	5
+146	0	4
+12031	0	1
+1993	0	1
+706	2	0
+2735	0	1
+3859	0	4
+1304	47	47
+3494	0	2
+268	2	0
+827	4	4
+1063	6	6
+7834	2	0
+3195	0	1
+4012	10	0
+6429	0	2
+308	0	1
+808	1	0
+17	8	0
+5472	19	2
+2436	0	14
+820	9	9
+2643	1	1
+32	1	1
+1189	1	0
+5710	0	3
+308	1	0
+3028	14	14
+1888	0	1
+4308	1	0
+946	82	0
+1790	0	2
+1218	25	0
+52	0	1
+1271	1	1
+33	1	1
+4760	1	0
+4924	0	1
+4817	4	4
+39	1	0
+1116	3715	901
+205	1	0
+1591	5	2
+128	29	29
+802	0	89
+1600	0	6
+2175	0	5
+606	14	14
+519	1	0
+540	1	1
+40	1	1
+568	2	0
+458	1	1
+41	1	1
+1106	24	62
+818	1	1
+42	1	1
+2266	1	0
+14059	0	4
+5030	1	0
+12630	0	3
+84	9	9
+129	13	18
+564	10	15
+154	1	0
+438	10	10
+38	0	5
+98	11	9
+2034	1	1
+25	1	1
+73	10	10
+70	5	5
+132	1	1
+52	1	1
+599	1	1
+46	1	1
+279	1	1
+18	1	1
+239	3	0
+383	6	0
+224	0	1
+321	15	0
+1783	1	1
+18	3	0
+575	16	16
+60	1	1
+16	1	1
+970	1	1
+24	1	1
+424	3	0
+41	1	1
+57	8	8
+285	2	0
+672	1	1
+44	1	4
+103	0	1
+148	1	1
+49	3	0
+146	5	11
+91	1	1
+79	1	1
+94	1	1
+101	1	1
+88	16	16
+117	1	1
+15	1	1
+58	1	1
+93	1	1
+466	1	1
+44	1	1
+160	1	1
+23	1	1
+481	14	14
+181	4	4
+72	1	1
+25	1	1
+82	7	12
+4	0	1
+11	1	4
+20	0	5
+92	1	1
+56	10	0
+80	1	1
+141	2	0
+60	1	1
+372	0	2
+784	1	1
+85	1	1
+109	1	1
+16	1	1
+57	1	1
+92	3	1
+23	1	0
+26	1	1
+74	1	1
+33	1	1
+176	1	1
+25	2	2
+193	42	43
+377	0	5
+249	1	1
+69	1	1
+98	1	1
+70	1	1
+55	1	1
+143	1	1
+438	1	1
+64	1	1
+53	4	0
+127	3	0
+75	5	5
+45	1	1
+197	1	1
+27	1	1
+116	13	13
+218	15	20
+1107	16	19
+73	1	1
+25	1	1
+199	1	1
+60	1	1
+994	1	1
+43	0	1
+18	1	1
+1215	18	18
+340	1	1
+34	1	1
+2783	1	1
+29	1	1
+475	82	82
+166	10	10
+87	1	1
+18	1	1
+171	7	7
+427	1	1
+21	1	1
+2011	0	3
+17	1	1
+1412	1	1
+24	1	1
+214	8	4
+228	1	1
+34	1	1
+410	16	16
+185	1	1
+24	1	0
+164	0	1
+222	1	1
+25	1	1
+297	10	10
+1171	1	0
+3343	1	0
+11	1	1
+2502	1	1
+23	1	1
+44	12	0
+2856	0	1
+148	1	1
+36	1	1
+993	2	0
+1251	2	0
+6619	14	14
+1014	4	0
+134	2	9
+818	1	0
+61	1	7
+563	46	0
+78	5	5
+1677	1	1
+49	1	1
+399	1	1
+32	1	1
+790	27	27
+104	1	1
+75	1	1
+1638	1	1
+16	1	1
+92	1	1
+44	1	1
+276	0	13
+1020	1	1
+35	1	1
+389	14	14
+256	1	0
+38	1	3
+631	1	1
+40	1	1
+2356	1	1
+82	2	0
+1300	0	5
+511	0	2
+605	1	1
+17	1	1
+880	12	0
+1689	4	0
+2492	1	1
+39	1	1
+641	16	16
+682	0	5
+669	1	1
+25	1	1
+1926	1	1
+39	4	3
+1037	1	1
+40	2	0
+890	6	0
+41	2	0
+498	3	0
+321	0	1
+281	3	0
+450	1	1
+34	1	1
+498	1	1
+28	2	1
+280	0	2
+648	1	1
+47	1	1
+1002	4	0
+120	1	1
+1538	0	1
+75	1	1
+37	1	1
+517	1	1
+79	4	4
+60	18	18
+2075	1	1
+19	1	1
+2429	1	1
+21	1	1
+107	1	0
+2786	0	2
+31	5	5
+1973	12	0
+3118	1	0
+246	0	1
+33	1	1
+6752	1	0
+822	2	9
+606	1	1
+18	1	1
+3920	1	1
+37	0	2
+4497	10	13
+2451	1	1
+16	3	0
+1843	0	4
+3780	3	0
+850	0	1
+2774	0	3
+2065	0	1
+20	1	1
+1400	1	0
+3243	0	15
+1336	5	0
+618	7	7
+1507	8	7
+379	44	43
+2184	0	1
+304	0	2
+19	0	1
+101	1	1
+417	3	3
+22	1	1
+672	4	4
+221	1	1
+161	5	0
+17	1	1
+72	1	0
+106	1	1
+463	1	1
+94	1	1
+138	3	4
+185	1	1
+29	1	1
+220	15	15
+167	1	1
+32	1	1
+93	1	3
+217	1	1
+23	1	1
+137	9	9
+62	0	3
+353	1	1
+27	1	1
+117	9	9
+421	1	1
+47	1	1
+124	0	1
+997	6	0
+54	5	5
+764	1	1
+45	1	1
+1431	7	7
+387	6	6
+1103	0	36
+767	1	1
+31	1	3
+208	5	5
+1610	1	1
+23	1	1
+779	0	8
+324	0	2
+45	1	1
+264	0	3
+45	1	1
+250	1	1
+18	1	1
+517	33	0
+117	1	1
+42	1	1
+550	1	1
+20	1	1
+671	1	1
+68	1	1
+89	1	1
+104	1	1
+172	0	1
+124	0	1
+524	0	1500
+464	5	5
+32	1	0
+171	1	1
+19	1	1
+67	1	1
+22	1	1
+654	1	1
+25	1	1
+68	1	1
+21	4	0
+1588	1	1
+66	1	1
+401	0	1
+186	1	1
+21	1	1
+168	0	1
+686	3	0
+19	1	1
+127	1	1
+29	1	1
+234	1	1
+30	1	1
+141	0	2
+33	1	1
+673	1	1
+89	1	1
+161	16	16
+504	1	1
+192	0	3
+105	1	1
+286	1	1
+101	15	16
+158	8	0
+57	1	1
+332	2	2
+35	1	1
+371	1	1
+55	1	1
+86	1	1
+29	1	1
+196	1	1
+44	1	0
+52	10019	10030
+89	1	1
+35	1	1
+153	1	0
+37	35	6
+68	1	1
+69	3	3
+78	28	28
+85	1	1
+148	1	1
+248	1	1
+77	1	1
+61	1	1
+55	1	1
+82	1	1
+41	2	2
+113	1	1
+59	1	1
+417	5	5
+65	1	1
+55	1	1
+212	0	14
+40	1	1
+112	1	1
+22	0	2
+47	1	1
+75	1	1
+208	5	5
+55	1	1
+78	1	1
+136	13	13
+93	3	0
+140	1	2
+46	1	1
+78	6	6
+52	1	1
+51	1	1
+97	1	1
+107	1	1
+5453	1	1
+40	1	1
+327	1	1
+24	1	1
+172	2	2
+27	11	15
+381	10	11
+376	1	1
+45	1	1
+121	1	1
+62	1	1
+289	1	1
+26	1	1
+191	1	1
+20	11	11
+425	1	1
+37	1	1
+296	1	1
+149	1	1
+284	1	1
+37	1	1
+705	1	12
+106	12	12
+306	1	1
+24	1	1
+1299	1	1
+47	1	1
+2026	1	1
+20	1	1
+133	1	0
+9803	0	4
+15871	3	0
+2464	1	1
+24	1	1
+879	1	1
+73	1	1
+89	1	1
+42	1	1
+108	1	1
+43	0	1
+26	1	1
+511	5	6
+605	1	1
+47	1	1
+73	1	1
+62	1	1
+1928	19438	20008
+56	5	5
+237	1	1
+141	1	1
+92	1	1
+154	7	7
+3208	1	1
+33	1	1
+671	1	1
+21	1	1
+955	0	3
+130	1	1
+26	1	1
+288	8	8
+218	0	3
+1076	8	0
+609	1	0
+55	2	1
+242	1	1
+23	1	1
+834	1	1
+112	1	1
+67	1	1
+43	1	1
+86	1	1
+30	1	1
+73	13	13
+88	11	11
+145	13	13
+63	1	1
+62	1	1
+59	51	50
+432	1	1
+45	1	1
+68	1	1
+48	1	1
+64	9	9
+299	14	14
+169	10	10
+69	2	2
+85	1	1
+207	6	6
+85	1	1
+44	3	3
+181	11	11
+55	13	13
+258	1	1
+103	1	1
+298	7	7
+268	1	1
+16	1	1
+66	1	1
+97	16	0
+322	1	1
+58	1	1
+55	1	1
+77	1	1
+186	1	1
+55	1	1
+218	1	1
+153	1	1
+53	1	1
+98	1	1
+371	1	1
+303	3	3
+63	1	1
+303	1	1
+121	0	2
+55	8	8
+208	1	1
+26	1	1
+447	6	6
+76	1	1
+46	1	1
+782	12	12
+230	1	1
+67	1	1
+60	1	1
+80	1	1
+170	3	0
+53	1	1
+31	1	1
+317	2	2
+66	1	1
+228	1	1
+23	1	1
+1612	1	1
+21	1	1
+261	1	1
+99	1	1
+128	1	1
+15	1	1
+77	9	9
+618	8	8
+84	4	6
+438	1	1
+140	1	1
+158	4	3
+277	12	12
+165	4	4
+36	1	1
+253	1	1
+59	1	1
+910	0	1
+915	4	5
+276	15	15
+682	1	1
+28	1	1
+1483	13	13
+203	1	0
+52	1	1
+48	1	1
+229	12	12
+166	1	1
+39	1	1
+194	1	1
+24	1	1
+251	8	8
+619	0	4
+15	1	1
+690	84	85
+463	1	1
+30	1	1
+449	1	1
+54	1	1
+58	5	5
+979	1	0
+318	1	1
+28	1	1
+898	10	10
+100	1	1
+22	1	1
+446	1	1
+74	1	1
+273	1	1
+19	1	1
+333	1	1
+44	1	1
+220	1	1
+56	2	0
+209	1	1
+70	1	1
+223	0	20
+220	1	1
+31	1	1
+56	1	1
+111	1	1
+220	1	1
+89	1	1
+119	1	1
+113	2	0
+195	1	1
+46	1	1
+184	1	1
+60	0	4
+76	0	4
+53	3	1
+43	1	1
+153	1	1
+53	1	1
+195	6	0
+60	1	1
+278	1	0
+42	1	1
+341	13	13
+262	4	4
+67	1	1
+32	1	0
+28	1	1
+287	7	7
+318	1	1
+78	1	1
+157	1	1
+19	1	1
+64	1	2
+31	1	1
+52	1	1
+51	1	1
+77	10280	10270
+101	8	8
+4653	1	1
+38	1	1
+817	2	0
+256	1	1
+27	1	1
+339	1	1
+48	1	1
+54	10	10
+1393	3	0
+1491	2	0
+1983	16	0
+167	0	4
+3886	7	8
+535	1	1
+16	1	1
+1555	3	0
+3131	1	1
+17	1	1
+4196	1	0
+14974	0	1
+3514	0	4
+29	1	1
+123	0	2
+27	11	0
+35	0	50
+43	2	0
+55	6	100
+96	11	0
+22	67	0
+49	13	0
+20	0	2
+19	2	0
+22	4	156
+57	156	3
+61	0	2
+29	20	0
+42	11	0
+21	2	0
+50	4	6
+31	1	3
+23	1	53
+25	0	32
+66	1	55
+11	0	2
+13	0	41
+68	1	42
+23	1	3
+12	2	0
+17	1	29
+51	17	13
+18	2	0
+28	2	0
+26	2	0
+158	1	25
+96	0	28
+51	1	29
+79	254	0
+53	21	0
+5064	0	2
+7569	2	0
+2189	0	1
+85	1	1
+31	0	4
+399	14	14
+408	0	1
+681	0	5
+184	1	1
+20	1	1
+64	1	1
+29	1	0
+9	2	0
+442	4	0
+342	1	1
+24	1	1
+131	1	1
+198	1	1
+370	0	1
+34	1	1
+447	21	20
+259	1	1
+23	0	1
+121	2	0
+2257	1	1
+22	1	1
+811	1	1
+27	1	1
+744	0	5
+843	0	2889
+55	0	88
+1189	0	2
+2274	1	0
+752	4	0
+164	1	1
+55	1	1
+1726	1	1
+57	1	1
+3578	1	1
+34	1	1
+1446	1	0
+460	1	1
+31	0	1
+6	1	1
+163	1	1
+22	1	1
+81	1	1
+27	1	1
+548	1	1
+61	1	1
+1169	1	1
+41	1	1
+6471	1	1
+62	1	1
+530	17	17
+394	1	1
+40	7	0
+57	12	12
+69	2	2
+39	1	1
+70	1	1
+22	0	3
+2307	1	1
+30	1	1
+411	1	1
+104	1	1
+375	26	27
+1218	1	1
+35	1	1
+85	1	1
+20	6	0
+687	1	1
+34	1	1
+268	13	13
+74	1	1
+47	2	0
+51	69	69
+73	1	1
+48	1	1
+218	1	1
+42	1	1
+197	1	1
+41	1	1
+313	1	1
+40	1	1
+476	1	1
+29	1	1
+185	1	1
+35	1	1
+594	1	1
+24	1	1
+220	26	0
+245	0	1
+261	13	13
+89	1	1
+90	1	1
+224	1	1
+201	1	1
+306	1	1
+29	5	5
+121	1	1
+31	1	1
+109	1	1
+25	1	1
+168	1	1
+19	1	1
+93	12	11
+132	1	0
+113	1	1
+30	1	1
+56	9	9
+300	1	1
+50	2	2
+96	1	1
+43	1	1
+76	1	1
+44	1	1
+197	1	1
+91	7	1
+119	0	9
+392	5	5
+89	1	1
+428	11	11
+260	1	1
+23	1	0
+10	1	1
+70	1	1
+65	2	0
+16	0	19
+28	1	1
+208	1	1
+70	1	1
+149	0	3
+243	1	1
+55	1	1
+63	17	17
+1208	1	1
+98	1	1
+162	1	1
+45	1	1
+148	70	70
+209	4	4
+1242	1	1
+42	5	0
+87	1	1
+522	0	3
+305	0	1
+1379	0	2
+390	0	15
+72	1	1
+16	1	1
+270	1	0
+280	7	7
+2763	20	20
+674	10	10
+1375	14	0
+294	143	141
+629	16	16
+54	4	4
+680	16	16
+395	1	1
+42	1	1
+1763	1	1
+46	1	1
+282	1	1
+39	1	1
+860	1	1
+26	1	1
+745	0	2
+2081	2	0
+817	4	4
+202	1	1
+48	1	1
+168	1	1
+53	1	1
+379	10	10
+1178	14	14
+132	5	0
+555	1	1
+65	1	1
+550	1	1
+21	1	1
+462	1	1
+43	1	1
+121	1	1
+48	0	3
+15	1	5
+1404	0	1
+450	4	0
+626	1	0
+304	1	1
+39	1	1
+564	1	1
+45	1	1
+303	2	0
+409	1	1
+18	1	0
+858	2	0
+2168	0	1
+54	22	22
+524	0	1
+410	10	10
+106	1	14
+2419	18	14
+64	1	1
+31	1	1
+185	0	5
+1646	1	1
+20	1	1
+227	1	1
+37	1	1
+500	1	0
+136	3	4
+8239	1	1
+23	1	1
+1114	0	2
+688	0	1
+901	18	18
+4781	0	4
+815	0	1
+5069	0	5
+415	0	2
+352	0	1
+1085	11	11
+1099	0	1
+991	0	1
+845	1	1
+32	0	2
+5751	0	3
+1553	1	1
+60	1	1
+278	0	1
+30	1	1
+1855	0	2
+958	0	1
+66	0	16
+2109	0	2
+1265	0	1
+17312	0	4
+1875	0	1
+2157	1	0
+915	0	6
+4940	1	0
+2649	0	1
+3322	11	9
+2276	14	0
+3128	0	4
+3496	1	0
+966	0	1
+120	4	4
+3473	1	0
+1647	0	3
+1182	1	0
+654	0	3
+2049	1	0
+6838	1	1
+39	1	1
+186	1	0
+2718	1	1
+30	1	1
+160	11	11
+4954	0	1
+420	1	1
+123	1	1
+156	0	4
+219	4	0
+195	1	0
+4402	2	0
+4295	1	0
+4695	0	1
+30	1	1
+6025	1	0
+4179	1	0
+19834	0	1
+11605	0	1
+4121	2	0
+2863	0	2
+4890	1	0
+5576	0	6
+4104	4	0
+19858	4	0
+1616	0	3
+1647	4	1
+36	0	12
+2213	0	14
+414	0	1
+3338	0	3
+678	3	4
+292	2	0
+1922	0	1
+913	0	1
+2720	1	0
+1111	3	0
+2589	0	8
+9425	1	0
+1403	0	2
+1964	0	12
+4433	0	1
+1569	0	1
+89	46	46
+7074	1	1
+41	1	1
+2257	1	0
+3001	0	1
+1845	1	0
+1593	0	1
+497	0	2
+6109	0	1
+2019	2	0
+921	0	1
+241	1	0
+4348	72	72
+1053	1	0
+2213	2	0
+1974	8	0
+4952	0	1
+6146	2	0
+953	1	0
+4141	0	1
+4244	5	0
+152	0	2
+209	0	1
+2400	0	10
+785	2	0
+1733	0	1
+554	1	0
+128	0	2
+3051	0	1
+5221	17	17
+3339	0	1
+1503	0	1
+1705	0	3
+2052	17	17
+998	177	0
+2804	1	0
+1925	1	0
+5635	17	17
+3563	0	1
+971	8	0
+36021	1	0
+8016	29	27
+3890	0	1
+67913	1	1
+18	1	6368
+73	1	1
+3119	23	23
+7239	0	32738
+4295	1	1
+19	1	1
+6198	1	0
+16668	1	1
+20	1	1
+5638	5	0
+47	12	0
+11313	0	1
+1769	0	1
+8355	0	3
+4114	0	2
+1403	1	0
+5140	0	1
+490	0	1
+219	1	0
+3483	1	0
+8939	1	1
+44	1	1
+10813	0	2
+7480	2	0
+617	1	0
+1464	0	1
+500	0	2
+1466	1	0
+527	5	0
+3593	0	1
+374	0	1
+3666	0	1
+2149	1	0
+311	2	0
+6570	1	0
+962	1	0
+23	1	1
+2647	4	0
+588	1	1
+21	1	1
+3256	28	20
+870	0	1
+644	1	0
+602	2	1
+3730	1	1
+45	1	1
+12848	7	7
+5994	29	29
+1283	0	3
+8057	1	1
+63	1	1
+4166	1	0
+1887	10	0
+2949	1	1
+31	0	1
+669	1	0
+888	43	43
+1259	2	0
+2081	0	2
+373	0	6
+421	4	4
+1460	0	1
+1699	0	8
+2882	2	0
+147	0	1
+1656	1	1
+27	1	1
+1828	0	2
+4066	0	3
+34	1	1
+361	17	17
+1254	6	0
+1643	0	2
+2542	0	1
+848	2	1
+2117	0	2
+119	1	1
+44	1	1
+1104	0	1
+415	0	12
+634	18	1
+377	6	7
+227	6	0
+449	13	13
+895	0	17
+457	18	18
+663	0	3
+382	1	1
+26	1	1
+135	0	1
+105	1	1
+25	1	1
+620	2	0
+290	5	5
+375	1	1
+30	0	4
+98	1	0
+20	17	4
+3824	28	0
+39	4	0
+28	4	0
+44	4	0
+1898	9	9
+221	0	2
+10522	30	0
+783	1	1
+59	1	1
+94	1	1
+21	1	1
+491	1	1
+49	1	1
+289	2	0
+120	0	1
+37	1	1
+112	1	1
+21	1	1
+183	16	16
+73	2	0
+1007	1	1
+38	0	1
+79	1	1
+48	1	1
+561	1	1
+29	1	1
+145	5	5
+576	12	12
+834	1	0
+846	5	7
+34	1	1
+417	0	1
+65	1	1
+40	1	1
+110	1	1
+47	1	1
+351	1	1
+69	1	1
+53	1	1
+91	1	1
+260	1	1
+36	0	1
+604	1	0
+169	0	1
+2118	1	1
+34	1	1
+147	1	1
+213	1	1
+67	1	1
+31	1	1
+566	1	0
+17	1	1
+763	1	1
+34	1	1
+671	5	0
+41	2	2
+98	0	1
+449	0	2
+61	1	1
+38	1	1
+202	1	1
+44	1	1
+190	1	0
+46	4	4
+51	0	4
+476	1	1
+17	1	1
+212	1	1
+26	1	1
+485	1	1
+25	1	1
+263	1	1
+26	1	1
+1327	4	0
+44	1	0
+2397	1	1
+44	1	1
+4146	14	14
+901	0	1
+3504	1	0
+1125	1	0
+254	1	0
+427	0	1
+30	1	1
+111	0	2
+52	0	8
+528	44	0
+969	1	1
+10	1	0
+28	1	1
+140	1	1
+43	1	1
+1989	2	1
+598	1	1
+87	0	4
+124	1	0
+4840	1	1
+28	7	4
+505	0	2
+24	1	1
+5134	4	0
+543	1	0
+18	1	1
+97	1	1
+29	1	3
+101	6	0
+148	13	7
+1346	0	1
+128	7	0
+49	0	1
+876	2	0
+286	5	5
+184	0	1
+84	5	5
+365	9	9
+981	1	1
+11	1	1
+734	4	0
+563	4	0
+244	9	9
+379	1	1
+17	1	1
+49	2	0
+95	1	1
+30	1	1
+147	1	1
+37	0	6
+340	1	2
+58	1	1
+332	0	2
+233	6	9
+156	0	1
+26	1	1
+439	4	0
+34	0	2
+508	5	0
+96	1	1
+34	1	1
+1267	15	15
+638	1	1
+24	4	5
+1055	13	13
+135	0	1
+194	63	63
+384	6	6
+2756	1	1
+19	1	1
+99	15	15
+1754	2	3
+2238	1	1
+31	1	1
+3002	4	0
+2156	15	15
+855	14	13
+442	5	5
+2022	6	6
+506	0	2
+1110	0	1
+2578	0	2
+4864	1	1
+36	1	0
+3187	1	1
+16	1	1
+184	1	1
+18	1	1
+1607	53	60
+527	1	1
+39	1	1
+653	3	0
+227	1	1
+18	1	1
+102	7	7
+109	0	323
+91	1	0
+124	0	15
+621	0	4
+553	12	12
+463	1	1
+40	1	1
+372	1	1
+25	1	1
+188	12	12
+357	0	1
+250	0	5
+4193	0	4
+967	1	1
+76	1	1
+3236	4	4
+529	7	7
+246	4	0
+160	1	1
+34	0	3
+1469	0	2
+499	1	0
+937	1	1
+45	1	1
+421	6	0
+2127	0	1
+491	1	0
+80	1	1
+72	2	0
+255	6	6
+728	14	11
+702	3	0
+290	0	2
+210	19	1
+473	1	1
+42	4	0
+219	0	1
+348	1	1
+83	1	1
+851	0	16
+72	13	0
+246	1	1
+47	4	0
+410	1	0
+93	0	12
+225	0	16
+428	1	0
+4	6	0
+324	0	1
+3060	0	16
+1305	1	1
+29	1	1
+3094	0	7
+600	0	2
+5495	1	1
+47	1	1
+1247	9	21
+35	6	0
+4350	1	1
+15	1	1
+2011	6	14
+8378	2	0
+295	0	17
+4583	1	0
+4132	0	4
+924	4	3
+1751	0	2
+1060	12	12
+380	0	2
+425	8	0
+84	0	1
+244	1	1
+28	1	1
+221	4	0
+348	1	1
+37	11	11
+50	1	1
+180	1	1
+348	1	1
+20	1	1
+1714	1	1
+79	1	1
+729	1	1
+44	1	0
+78	1	1
+112	1	1
+23	1	1
+55	9	9
+1044	1	1
+27	1	1
+494	1	1
+32	1	1
+237	1	1
+27	1	1
+1839	7	1
+710	8	0
+185	0	2
+966	1	0
+13	15	1
+251	1	1
+47	1	1
+285	1	1
+103	1	1
+977	1	1
+41	1	0
+97	1	1
+131	1	0
+307	1	1
+47	1	1
+1070	1	1
+69	1	1
+382	0	1
+167	1	1
+35	1	1
+161	1	1
+30	1	1
+1068	18	0
+1173	1	1
+32	1	1
+59	1	1
+12	1	0
+18	1	1
+55	0	22
+72	1	1
+2806	1	1
+15	1	1
+1395	1	0
+157	13	0
+536	8	8
+101	1	1
+21	1	1
+147	8	8
+638	1	1
+18	1	1
+183	15	15
+990	0	12
+21	1	1
+145	0	1
+332	1	1
+31	1	1
+231	22	5
+39	1	1
+414	9	9
+93	1	1
+63	1	1
+739	0	2
+632	1	1
+74	1	1
+138	5	5
+128	0	1
+294	1	1
+45	1	1
+679	6	6
+1773	0	34
+543	27	27
+1608	5	0
+219	1	1
+134	0	3
+164	0	1
+357	1	1
+28	1	1
+670	7	9
+270	0	1
+891	13	33
+257	4	0
+80	0	4
+130	2	0
+3772	1	1
+44	1	1
+2256	0	1
+80	12	0
+5544	1	0
+428	13	13
+77	4	4
+63	1	1
+64	13	19
+906	1	1
+84	1	1
+290	1	1
+41	1	1
+144	15	15
+238	3	0
+61	1	1
+31	1	1
+189	10245	10222
+107	11	11
+93	1	1
+30	7	5
+242	0	1
+171	1	1
+29	1	1
+218	0	9
+241	1	1
+55	4	4
+88	1	1
+99	1	1
+57	0	1
+523	12	16
+399	1	1
+50	1	1
+389	1	1
+71	4	4
+173	12	12
+92	1	1
+20	1	1
+132	0	5
+15	1	1
+75	1	1
+26	5	5
+119	11	11
+542	1	1
+23	2	2
+254	1	1
+34	1	1
+172	1	1
+45	1	1
+95	11	11
+127	23	23
+64	1	1
+95	1	1
+390	1	1
+52	1	1
+170	1	1
+16	5	0
+30	1	1
+599	1	1
+119	1	1
+85	1	1
+75	1	1
+286	4	4
+61	1	1
+286	9	9
+429	1	1
+21	1	1
+53	1	1
+44	1	1
+130	1	1
+30	1	1
+190	2	2
+127	1	1
+96	4	4
+112	1	1
+105	5	5
+19	3659	4
+244	10	11
+69	1	1
+29	1	1
+281	1	1
+38	1	1
+212	1	1
+36	1	1
+79	1	1
+29	3	3
+125	161746	190163
+3115	0	1
+152	1	1
+1518	1	1
+88	1	1
+4502	0	1
+46	1	1
+800	4	4
+23	1	1
+1305	2	0
+136	0	1
+4941	0	1
+547	0	1
+70	8	8
+293	1	1
+35	1	1
+1165	4	0
+6662	1	1
+121	1	1
+92	0	8
+214	1	1
+35	1	1
+108	1	0
+1063	0	1
+1017	1	1
+20	0	6
+1725	0	1
+134	68	67
+349	1	1
+24	0	1
+1562	1	1
+31	1	1
+2513	0	1
+73	36	36
+305	1	1
+27	1	1
+543	1	1
+47	4	28
+4387	20057	20086
+272	5	5
+243	1	1
+84	1	1
+98	1	1
+50	5	5
+77	1	1
+74	1	1
+20	0	1
+143	1	1
+45	0	1
+4	1	1
+1088	1	1
+35	1	1
+320	1	1
+22	1	1
+275	1	1
+47	1	1
+370	19	19
+119	1	6
+51	1	1
+21	1	1
+244	0	1
+345	1	1
+24	1	1
+181	1	1
+61	3	3
+542	1	1
+16	1	1
+312	1	0
+353	4	3
+279	323	0
+86	1	1
+49	1	1
+342	1	1
+44	0	2
+222	1	1
+37	1	1
+588	8	8
+593	2	2
+44	1	1
+359	1	1
+25	1	1
+2054	1	0
+2510	1	0
+5051	0	1
+1489	9	9
+3292	1	0
+1449	1	1
+21	1	1
+6768	1	0
+706	2	0
+7107	1	1
+38	1	1
+1127	73	73
+435	1	1
+60	1	1
+325	0	1
+254	1	1
+43	1	1
+210	1	1
+7	1	0
+47	1	1
+130	4	4
+34	1	1
+208	1	1
+39	2	2
+526	1	1
+36	1	1
+99	9	7
+20	1	1
+73	1	1
+62	1	1
+425	1	1
+43	1	1
+811	1	1
+38	1	1
+362	1	1
+49	1	1
+109	1	1
+19	1	1
+79	1	1
+29	0	1
+26	1	1
+252	1	1
+75	1	1
+441	1	1
+66	1	1
+389	13	13
+67	7	7
+1185	0	311
+64	6	6
+667	1	1
+38	1	1
+79	1	0
+553	1	1
+30	1	1
+433	1	1
+16	3	0
+1133	12	12
+262	5	5
+276	1	0
+960	14	14
+272	1	1
+41	1	1
+196	1	0
+1424	18	19
+314	1	1
+22	1	1
+345	1	1
+23	3	0
+245	1	1
+78	1	1
+77	1	1
+779	1	1
+32	1	1
+247	1	1
+48	1	1
+778	2	0
+226	1	1
+61	1	1
+861	0	1
+51	9	9
+397	1	1
+12	4	0
+46	1	1
+602	1	1
+35	1	1
+422	1	1
+49	1	1
+789	1	1
+37	1	1
+268	0	2
+589	8	8
+366	1	1
+6	0	7
+5	0	1
+66	1	1
+1584	2	7
+19	1	1
+417	1	1
+37	1	1
+812	1	1
+33	3	0
+1351	18	18
+2186	1	1
+86	1	1
+1433	59	59
+65	0	1
+238	0	1
+171	1	1
+7	2	1
+67	1	1
+596	1	1
+29	1	1
+144	4	6
+417	1	0
+88	1	1
+24	1	1
+390	18	18
+496	14	21
+145	1	1
+46	1	1
+310	1	1
+35	1	1
+214	1	1
+38	1	1
+206	1	1
+37	1	0
+240	1	1
+32	1	1
+469	1	1
+32	1	1
+208	1	1
+21	1	1
+343	1	1
+17	1	1
+88	1	1
+58	6	0
+169	1	1
+22	1	1
+162	0	1
+196	0	2
+500	6	5
+108	1	1
+40	2	0
+50	1	1
+111	1	0
+21	0	1066
+335	1	1
+44	1	1
+11005	0	1
+6280	1	1
+48	1	1
+1173	1	1
+19	1	1
+2664	0	1
+351	1	0
+1059	14	14
+593	0	1
+869	16	16
+23065	2	0
+2197	0	1
+949	0	1
+15048	0	1
+606	1	0
+7820	0	4
+14669	1	0
+14708	0	1
+16326	0	1
+710	2	0
+194	1	1
+49	1	1
+262	0	1
+92	1	1
+10677	2	0
+4856	3	0
+7447	6	6
+421	1	0
+884	6	0
+17	1	0
+3075	1	0
+14671	3	1
+3762	2	0
+601	2	0
+2461	0	2
+5154	1	0
+1604	0	16
+3589	0	1
+1488	1	0
+1196	0	2
+683	0	1
+1218	1	0
+221	1	1
+22	1	1
+296	4	4
+1456	23	41
+880	1	12
+2490	1	0
+151	1	1
+33	1	1
+2809	4	4
+3645	1	1
+17	1	1
+3496	2	0
+154	1	1
+29	1	1
+158	0	1
+5981	1	1
+32	1	1
+1041	0	2
+174	9	0
+1383	0	1
+389	1	2
+1570	2	0
+3993	4	0
+4576	1	1
+45	1	1
+182	8	8
+2203	20	24
+2009	1	1
+39	1	1
+489	1	1
+17	1	1
+628	1	1
+124	1	1
+1607	1	1
+23	1	1
+1021	0	8
+1249	0	20
+46	0	32
+46	6	0
+24	0	10
+7679	1	1
+44	1	1
+580	1	1
+28	1	1
+264	1	1
+65	0	1
+15	1	1
+2371	19	19
+57	1	1
+21	1	1
+231	1	1
+94	1	1
+105	1	1
+208	5	5
+124	1	1
+112	3	3
+207	40	40
+244	1	1
+60	1	1
+98	1	1
+50	1	1
+256	29	29
+157	1	1
+33	1	1
+143	1	1
+59	1	1
+51	1	1
+45	1	0
+73	1	1
+81	1	1
+270	1	1
+272	1	1
+232	1	1
+94	1	1
+3189	0	176
+834	0	35
+303	0	51
+321	1	0
+17170	0	1
+321	1	1
+25	1	1
+679	1	1
+33	1	1
+990	11	11
+131	8	8
+79	9	9
+1284	5	5
+537	6	6
+127	1	1
+28	1	1
+145	1	1
+47	1	1
+399	4	4
+35	1	1
+143	1	1
+39	1	1
+53	9	9
+61	1	1
+95	12	22
+86	1	0
+71	5	0
+11	1	1
+58	8490	8674
+113	1403	1307
+491	1	1
+32	1	1
+85	1	1
+41	1	1
+480	1	1
+74	2	2
+1108	59	0
+70	10	10
+325	11	11
+879	1	1
+34	1	1
+524	1	1
+25	1	1
+202	17	17
+1154	1	1
+26	1	1
+89	17	17
+87	1	1
+39	1	1
+950	1	1
+15	2	2
+51	1	1
+81	1	1
+180	1	0
+187	1	1
+37	1	1
+467	1	1
+19	1	1
+755	0	2
+81	3	1
+16	1	1
+67	6	6
+84	1	1
+37	2	0
+31	0	28
+15	0	37
+266	14	14
+372	1	1
+68	1	1
+205	40	40
+217	1	1
+46	1	1
+563	19	0
+217	9	9
+363	1	1
+22	1	1
+884	1	1
+40	1	1
+179	1	1
+42	1	1
+94	6	6
+922	1	1
+30	1	1
+481	0	3
+7925	15	11
+333	5	0
+1235	6	6
+355	1	1
+27	1	1
+515	1	0
+1077	11	0
+1521	1	0
+38	1	1
+119	1	1
+58	1	1
+63	4	3
+385	1	1
+49	1	1
+77	20	22
+111	11	11
+190	2	2
+45	1	1
+373	1	1
+47	1	1
+77	10	10
+186	1	1
+24	1	1
+965	27	27
+148	1	0
+214	1	1
+34	1	1
+89	1	1
+36	1	1
+288	0	1
+544	0	331
+320	1	0
+199	1	1
+16	1	1
+112	1	1
+29	1	1
+808	0	3
+45	1	1
+240	1	1
+38	1	1
+59	1	1
+68	1	1
+52	1	1
+98	1	1
+166	7	7
+698	1	1
+68	1	1
+165	0	1
+114	1	1
+92	0	1
+14	1	1
+215	1	1
+81	1	1
+792	1	1
+31	1	1
+54	1	1
+44	1	1
+179	1	1
+26	1	1
+200	1	1
+30	1	1
+639	7	7
+505	0	1
+18	0	1
+21	1	1
+549	12	0
+19	1	1
+1413	19	19
+752	1	0
+840	1	1
+69	1	1
+966	21	21
+33	12	0
+56	1	1
+94	1	1
+237	11	9
+189	1	1
+47	1	1
+318	3	0
+80	16	16
+67	1	2
+11	5	0
+32	1	1
+126	1	1
+146	1	1
+104	6	5
+56	1	1
+68	1	1
+417	12	13
+636	0	2
+30	1	1
+694	0	4
+95	1	1
+28	1	1
+1358	1	1
+19	1	1
+68	1	1
+97	1	1
+493	1	7
+158	2	0
+42	6	0
+59	1	1
+314	14	14
+94	1	1
+64	1	1
+637	1	1
+21	1	1
+144	2	1
+229	11	5
+410	1	1
+96	1	1
+272	1	1
+22	1	1
+118	1	1
+44	1	1
+96	1	1
+48	1	1
+414	22	22
+373	13	13
+554	1	1
+87	10	0
+313	1	1
+37	1	1
+122	17	18
+179	1	1
+40	1	1
+591	8	8
+129	1	0
+70	1	1
+71	1	0
+73	10	6
+12	1	1
+203	0	6
+24	2	0
+45	4	0
+46	1	1
+186	9	9
+87	1	1
+28	1	1
+3625	0	1
+233	1	1
+532	0	2
+696	2	0
+555	1	7
+287	1	1
+30	0	3
+946	0	1
+88	1	1
+60	12	0
+12546	1	1
+37	1	0
+2071	0	1
+3270	4	5
+24668	0	2
+6212	1	1
+26	1	1
+816	0	4
+8244	26	26
+5332	18	15
+2375	2	0
+1957	2	0
+2394	6	0
+1561	0	1
+2805	4	0
+12333	8	0
+835	0	1
+391	35	62
+12156	0	18
+6903	2	0
+21807	3	0
+1588	1	0
+2605	1	1
+23	1	1
+11252	8	0
+298	6	7
+946	2	0
+232	0	1
+501	1	0
+4748	0	4
+770	0	7
+914	0	1
+295	1	0
+214	3	0
+121	0	1
+784	0	1
+2512	0	1
+1205	21	21
+3250	3	0
+926	0	1
+189	2	0
+3543	2	0
+893	1	1
+46	1	1
+1296	0	1
+153	0	1
+336	5	0
+228	1	1
+45	1	1
+207	3	0
+322	0	1
+658	1	0
+1516	3	0
+1025	0	13
+1518	0	1
+591	10	10
+3384	0	2
+182	12	0
+328	1	0
+301	0	1
+994	1	1
+18	0	6
+1743	0	1
+2350	22	23
+1548	0	7
+1976	1	0
+199	0	1
+5922	12	12
+873	0	3
+3080	12	8
+322	1	0
+490	1	0
+3602	1	0
+482	1	0
+3178	1	0
+5157	0	10
+753	0	1
+885	20	0
+1746	10	0
+4045	6	1
+3520	5	13
+2048	0	1
+3529
+
+chain	323865	chr6_cox_hap2	4795371	+	1330645	1334316	chr12	132349534	-	750935	772711	208090
+2772	0	815
+201	0	17291
+643	1	0
+54
+
+chain	80740	chr6_cox_hap2	4795371	+	2523432	2524289	chr6	170899992	-	139781917	139782778	1563239
+341	0	4
+516
+
+chain	70254	chr6_cox_hap2	4795371	+	4067974	4068737	chr9	140273252	+	98508948	98509710	1791394
+611	16	15
+136
+
+chain	49863	chr6_cox_hap2	4795371	+	2736707	2740201	chr12	132349534	+	103307685	103311177	2548369
+99	961	960
+121	35	35
+77	287	287
+76	473	472
+80	230	229
+64	37	37
+96	796	797
+62
+
+chain	42593	chr6_cox_hap2	4795371	+	3906996	3908960	chrX	154913754	-	144265701	144267664	3039954
+86	125	125
+67	358	358
+186	154	154
+98	734	733
+51	48	48
+57
+
+chain	34258	chr6_cox_hap2	4795371	+	2809588	2810007	chrX	154913754	-	17721461	17721874	3940368
+73	15	15
+155	1	1
+20	6	0
+17	1	1
+131
+
+chain	30865	chr6_cox_hap2	4795371	+	4059866	4060385	chr6	170899992	+	32821259	32821748	4483190
+73	89	59
+184	77	77
+96
+
+chain	30808	chr6_cox_hap2	4795371	+	1510229	1510552	chr13	114142980	+	81787211	81787534	4493802
+323
+
+chain	29563	chr6_cox_hap2	4795371	+	4153575	4153884	chr1	247249719	-	75038034	75038343	4838476
+309
+
+chain	29490	chr6_cox_hap2	4795371	+	3951720	3952028	chr20	62435964	-	21243992	21244300	4870682
+308
+
+chain	27083	chr6_cox_hap2	4795371	+	3906819	3907206	chr15	100338915	-	11358130	11358517	3142845
+177	86	86
+124
+
+chain	23990	chr6_cox_hap2	4795371	+	1376886	1377662	chr7	158821424	-	51137320	51138262	7695540
+178	101	101
+72	385	551
+40
+
+chain	17935	chr6_cox_hap2	4795371	+	3928197	3929285	chr6	170899992	+	32648139	32649803	12171469
+63	855	1431
+170
+
+chain	17763	chr6_cox_hap2	4795371	+	3903740	3903944	chr6	170899992	-	2126149	2126361	12324873
+52	0	8
+26	2	2
+124
+
+chain	17461	chr6_cox_hap2	4795371	+	3908117	3908804	chr7	158821424	+	50608340	50609026	3099178
+57	90	88
+74	250	251
+108	69	69
+39
+
+chain	17263	chr6_cox_hap2	4795371	+	3953714	3953921	chr4	191273063	+	3978296	3978500	12788147
+50	3	0
+26	4	4
+124
+
+chain	16515	chr6_cox_hap2	4795371	+	3904181	3904724	chr8	146274826	-	138245724	138246268	13519146
+75	324	325
+78	15	15
+51
+
+chain	16283	chr6_cox_hap2	4795371	+	3331225	3331402	chr2	242951149	+	128261675	128261851	587006
+28	2	1
+147
+
+chain	15874	chr6_cox_hap2	4795371	+	2807758	2808190	chr6	170899992	+	31412763	31413204	14155918
+58	158	158
+72	76	85
+68
+
+chain	15671	chr6_cox_hap2	4795371	+	1369735	1370970	chr6	170899992	-	139552636	139553881	14365445
+56	408	416
+54	620	622
+97
+
+chain	15351	chr6_cox_hap2	4795371	+	2854893	2855094	chr11	134452384	+	74426248	74426449	14701290
+99	26	26
+76
+
+chain	15299	chr6_cox_hap2	4795371	+	2737173	2739469	chr4	191273063	+	161293453	161295747	2664175
+134	30	30
+77	352	352
+1	899	896
+68	663	664
+72
+
+chain	15059	chr6_cox_hap2	4795371	+	3958379	3959329	chr11	134452384	-	110535166	110536123	15004208
+57	287	282
+82	464	476
+60
+
+chain	14920	chr6_cox_hap2	4795371	+	2854607	2854845	chr12	132349534	+	55181251	55181530	15152322
+65	69	110
+104
+
+chain	14553	chr6_cox_hap2	4795371	+	4145755	4147026	chr20	62435964	-	45982841	45983887	15553025
+59	654	439
+82	417	407
+59
+
+chain	14203	chr6_cox_hap2	4795371	+	4064060	4064210	chr6	170899992	-	148625201	148625351	15961753
+150
+
+chain	14065	chr6_cox_hap2	4795371	+	3965480	3965632	chr6	170899992	-	138279004	138279156	16120854
+152
+
+chain	13894	chr6_cox_hap2	4795371	+	1411227	1413617	chr6	170899992	+	30021566	30022999	16323534
+75	1920	964
+70	255	254
+70
+
+chain	13590	chr6_cox_hap2	4795371	+	4063892	4064036	chr2	242951149	+	178053314	178053458	16703151
+144
+
+chain	13480	chr6_cox_hap2	4795371	+	1351610	1352327	chr6	170899992	+	29984509	29985227	16847522
+104	551	552
+62
+
+chain	13240	chr6_cox_hap2	4795371	+	3973235	3974493	chr6	170899992	+	32656086	32657213	17156367
+52	422	421
+78	652	522
+54
+
+chain	12556	chr6_cox_hap2	4795371	+	1412173	1412312	chr2	242951149	-	184047846	184047985	18149165
+139
+
+chain	12225	chr6_cox_hap2	4795371	+	3953994	3954124	chr13	114142980	-	45055283	45055413	18644548
+130
+
+chain	12178	chr6_cox_hap2	4795371	+	4035942	4036108	chr14	106368585	-	58343221	58343386	18718227
+55	26	25
+85
+
+chain	11746	chr6_cox_hap2	4795371	+	1363046	1363194	chr7	158821424	-	7754727	7754875	19419744
+54	14	14
+80
+
+chain	11718	chr6_cox_hap2	4795371	+	363030	363190	chr13	114142980	+	52924211	52924330	7321463
+62	41	0
+40	13	13
+4
+
+chain	11256	chr6_cox_hap2	4795371	+	4009517	4011696	chr6	170899992	+	32547334	32549511	20265569
+52	1710	1710
+59	270	268
+88
+
+chain	11034	chr6_cox_hap2	4795371	+	3906701	3906819	chr11	134452384	-	106076910	106077028	5031217
+118
+
+chain	10867	chr6_cox_hap2	4795371	+	2744958	2745115	chr6	170899992	-	132294381	132294544	20980270
+55	29	35
+73
+
+chain	10852	chr6_cox_hap2	4795371	+	2854438	2854554	chr15	100338915	-	60167597	60167713	16273329
+116
+
+chain	10738	chr6_cox_hap2	4795371	+	3960011	3960132	chr10	135374737	+	59270705	59270823	21232182
+61	3	0
+57
+
+chain	10631	chr6_cox_hap2	4795371	+	4504746	4504857	chr6	170899992	+	33168511	33168622	21069572
+111
+
+chain	10496	chr6_cox_hap2	4795371	+	3956062	3956172	chr1	247249719	-	172266041	172266151	21720779
+110
+
+chain	10389	chr6_cox_hap2	4795371	+	2738194	2739397	chr3	199501827	-	153335243	153336431	2813504
+77	463	461
+101	221	221
+81	230	217
+30
+
+chain	9881	chr6_cox_hap2	4795371	+	2797497	2798047	chr6	170899992	+	31313427	31313987	23083507
+72	423	433
+55
+
+chain	9755	chr6_cox_hap2	4795371	+	4085166	4085466	chr6	170899992	+	162410099	162410399	23379361
+65	181	181
+54
+
+chain	9455	chr6_cox_hap2	4795371	+	3955446	3955651	chr6	170899992	+	32576901	32577113	24108453
+54	91	98
+60
+
+chain	9090	chr6_cox_hap2	4795371	+	2744204	2744314	chr3	199501827	-	94209663	94209773	24799752
+53	4	4
+53
+
+chain	9032	chr6_cox_hap2	4795371	+	4005585	4007249	chr6	170899992	+	32600177	32601830	24897713
+61	1516	1505
+87
+
+chain	8805	chr6_cox_hap2	4795371	+	4070123	4070583	chr6	170899992	+	32730844	32731277	25222810
+56	347	320
+57
+
+chain	8241	chr6_cox_hap2	4795371	+	4030549	4030636	chr6	170899992	+	65319659	65319746	26041488
+87
+
+chain	7395	chr6_cox_hap2	4795371	+	3960355	3960433	chr12	132349534	+	58155129	58155207	27414638
+78
+
+chain	7276	chr6_cox_hap2	4795371	+	4034939	4035015	chr6	170899992	-	67344251	67344327	27653179
+76
+
+chain	7068	chr6_cox_hap2	4795371	+	3976155	3976230	chr3	199501827	-	153055114	153055189	28061906
+75
+
+chain	6977	chr6_cox_hap2	4795371	+	3979195	3979269	chr3	199501827	-	153056804	153056878	28244736
+74
+
+chain	6795	chr6_cox_hap2	4795371	+	2799999	2800071	chr6	170899992	+	31318116	31318188	28604513
+72
+
+chain	6742	chr6_cox_hap2	4795371	+	3906310	3906388	chr13	114142980	-	44754607	44754685	6636725
+47	2	2
+29
+
+chain	6584	chr6_cox_hap2	4795371	+	3989668	3989736	chr6	170899992	+	32559900	32559968	29100412
+68
+
+chain	6522	chr6_cox_hap2	4795371	+	4087338	4087407	chr15	100338915	+	41279078	41279147	29241043
+69
+
+chain	6495	chr6_cox_hap2	4795371	+	4147491	4147560	chr3	199501827	+	170919021	170919090	29304086
+69
+
+chain	6422	chr6_cox_hap2	4795371	+	4077507	4077575	chr6	170899992	+	32836685	32836753	29490822
+68
+
+chain	6368	chr6_cox_hap2	4795371	+	4147386	4147454	chr14	106368585	+	45132269	45132337	29601986
+68
+
+chain	6249	chr6_cox_hap2	4795371	+	2736394	2736460	chr4	191273063	-	25496702	25496768	29900240
+66
+
+chain	5885	chr6_cox_hap2	4795371	+	4087248	4087310	chr1	247249719	-	180983801	180983863	30853903
+62
+
+chain	5792	chr6_cox_hap2	4795371	+	4036108	4036169	chr10	135374737	-	103149812	103149873	26755013
+61
+
+chain	5767	chr6_cox_hap2	4795371	+	4085838	4085899	chr6	170899992	+	75566512	75566573	31174158
+61
+
+chain	5767	chr6_cox_hap2	4795371	+	4147632	4147693	chr2	242951149	-	84322530	84322591	31176268
+61
+
+chain	5731	chr6_cox_hap2	4795371	+	1376353	1376414	chr6	170899992	+	29872087	29872148	31286976
+61
+
+chain	5730	chr6_cox_hap2	4795371	+	1379511	1379571	chr6	170899992	+	29878483	29878543	31293433
+60
+
+chain	5576	chr6_cox_hap2	4795371	+	1365664	1365723	chr18	76117153	-	3609354	3609413	31727123
+59
+
+chain	5458	chr6_cox_hap2	4795371	+	4048500	4048558	chr16	88827254	+	47978524	47978582	32101537
+58
+
+chain	5403	chr6_cox_hap2	4795371	+	3960992	3961049	chr8	146274826	-	83195522	83195579	32234296
+57
+
+chain	5339	chr6_cox_hap2	4795371	+	4145490	4145546	chr3	199501827	+	495644	495700	32419958
+56
+
+chain	5275	chr6_cox_hap2	4795371	+	4086549	4086604	chr8	146274826	-	2308124	2308179	32643336
+55
+
+chain	5206	chr6_cox_hap2	4795371	+	3904515	3904580	chr1	247249719	-	87949826	87949891	19914856
+50	10	10
+5
+
+chain	5193	chr6_cox_hap2	4795371	+	4086093	4086147	chr5	180857866	+	130110350	130110404	32896485
+54
+
+chain	5184	chr6_cox_hap2	4795371	+	4084818	4084872	chrX	154913754	+	10188597	10188651	32929250
+54
+
+chain	5094	chr6_cox_hap2	4795371	+	4048238	4048292	chr6	170899992	+	68023473	68023527	33192695
+54
+
+chain	5067	chr6_cox_hap2	4795371	+	2804796	2804850	chr19	63811651	-	42284679	42284733	33279532
+54
+
+chain	5066	chr6_cox_hap2	4795371	+	1412096	1412149	chr21	46944323	-	1867343	1867396	33290791
+53
+
+chain	5020	chr6_cox_hap2	4795371	+	1409379	1409431	chr6	170899992	+	29800663	29800715	33444450
+52
+
+chain	4959	chr6_cox_hap2	4795371	+	3956009	3956062	chr18	76117153	+	5080594	5080647	22154822
+53
+
+chain	4930	chr6_cox_hap2	4795371	+	3957989	3958041	chrX	154913754	-	4434310	4434362	33717677
+52
+
+chain	4885	chr6_cox_hap2	4795371	+	2804443	2804495	chr5	180857866	-	162979708	162979760	33920646
+52
+
+chain	4847	chr6_cox_hap2	4795371	+	4047956	4048006	chr8	146274826	+	123332061	123332111	34011268
+50
+
+chain	4821	chr6_cox_hap2	4795371	+	3998874	3998925	chr6	170899992	-	10896638	10896689	34121637
+51
+
+chain	4712	chr6_cox_hap2	4795371	+	1364779	1364829	chr8	146274826	+	57925971	57926021	34511278
+50
+
+chain	4712	chr6_cox_hap2	4795371	+	4048918	4048968	chrX	154913754	+	54878538	54878588	34513604
+50
+
+chain	4392	chr6_cox_hap2	4795371	+	1377105	1377164	chr7	158821424	-	126060926	126060985	9905438
+59
+
+chain	4221	chr6_cox_hap2	4795371	+	2501082	2501164	chr14	106368585	+	74531432	74531592	4607333
+28	0	78
+54
+
+chain	4156	chr6_cox_hap2	4795371	+	3908195	3908241	chr2	242951149	-	7598530	7598576	17599965
+46
+
+chain	3903	chr6_cox_hap2	4795371	+	2908687	2909998	chr13	114142980	-	41461917	41462061	3840414
+7	46	0
+24	11	0
+33	1102	5
+19	13	0
+56
+
+chain	3865	chr6_cox_hap2	4795371	+	3903984	3904315	chr6	170899992	-	96557211	96557546	20806006
+67	210	214
+54
+
+chain	3734	chr6_cox_hap2	4795371	+	4145889	4145954	chr6	170899992	+	80018577	80018642	19955866
+65
+
+chain	3639	chr6_cox_hap2	4795371	+	3954124	3954162	chr3	199501827	+	102893836	102893874	20360982
+38
+
+chain	3394	chr6_cox_hap2	4795371	+	3959975	3960011	chrX	154913754	-	4438295	4438331	28244218
+36
+
+chain	3053	chr6_cox_hap2	4795371	+	4085231	4085263	chr2	242951149	+	38036198	38036230	24698963
+32
+
+chain	2845	chr6_cox_hap2	4795371	+	2736677	2736707	chr3	199501827	-	158108130	158108160	26771662
+30
+
+chain	2771	chr6_cox_hap2	4795371	+	2403948	2403980	chr16	88827254	+	61371572	61371604	11881973
+32
+
+chain	2645	chr6_cox_hap2	4795371	+	3954296	3954371	chr19	63811651	-	40112981	40113056	21687958
+75
+
+chain	2587	chr6_cox_hap2	4795371	+	2737535	2737662	chr15	100338915	+	91973389	91973516	3332233
+127
+
+chain	2561	chr6_cox_hap2	4795371	+	363092	363133	chr6	170899992	+	20352681	20352722	12577879
+41
+
+chain	2518	chr6_cox_hap2	4795371	+	4085322	4085377	chr16	88827254	-	20600134	20600189	24262923
+55
+
+chain	2470	chr6_cox_hap2	4795371	+	2809473	2809523	chr1	247249719	+	111577816	111577866	7596664
+50
+
+chain	2411	chr6_cox_hap2	4795371	+	3932607	3932633	chr1	247249719	-	51484714	51484740	35456234
+26
+
+chain	2403	chr6_cox_hap2	4795371	+	3907493	3907603	chr2	242951149	+	38214752	38214862	4277847
+110
+
+chain	2400	chr6_cox_hap2	4795371	+	2741593	2741618	chr4	191273063	+	159509242	159509267	32929303
+25
+
+chain	2393	chr6_cox_hap2	4795371	+	4068737	4068764	chrX	154913754	-	92588093	92588120	1797125
+27
+
+chain	2375	chr6_cox_hap2	4795371	+	3904076	3904137	chr11	134452384	-	60265228	60265289	23423532
+61
+
+chain	2319	chr6_cox_hap2	4795371	+	2964304	2964330	chr6	170899992	+	31465639	31465665	3286069
+26
+
+chain	2194	chr6_cox_hap2	4795371	+	1377065	1377105	chrX	154913754	-	101365357	101365397	11073776
+40
+
+chain	2146	chr6_cox_hap2	4795371	+	1363259	1363320	chr12	132349534	+	104221177	104221238	23825280
+61
+
+chain	2104	chr6_cox_hap2	4795371	+	4036001	4036023	chr6	170899992	-	77175689	77175711	26219289
+22
+
+chain	2011	chr6_cox_hap2	4795371	+	4029977	4029999	chrX	154913754	+	85587943	85587965	35529089
+22
+
+chain	2000	chr6_cox_hap2	4795371	+	1377237	1377270	chr4	191273063	+	153905795	153905828	8127681
+33
+
+chain	1991	chr6_cox_hap2	4795371	+	2908808	2908838	chr4	191273063	-	29946315	29946345	15287751
+30
+
+chain	1988	chr6_cox_hap2	4795371	+	3958152	3958211	chr1	247249719	+	152912877	152912936	23823437
+59
+
+chain	1918	chr6_cox_hap2	4795371	+	2736976	2737099	chr5	180857866	+	51070203	51070326	3385212
+123
+
+chain	1873	chr6_cox_hap2	4795371	+	3906133	3906260	chr5	180857866	-	144904464	144904591	3580450
+127
+
+chain	1857	chr6_cox_hap2	4795371	+	4071868	4075383	chr6	170899992	+	32830794	32834943	29519981
+61	2506	2690
+85	515	965
+52	103	103
+193
+
+chain	1825	chr6_cox_hap2	4795371	+	3906512	3906555	chr4	191273063	-	47717007	47717050	17204973
+43
+
+chain	1793	chr6_cox_hap2	4795371	+	3907342	3908508	chr2	242951149	+	97580469	97581638	5600825
+48	1090	1093
+28
+
+chain	1708	chr6_cox_hap2	4795371	+	3906388	3906482	chr7	158821424	+	109077307	109077401	4717797
+94
+
+chain	1690	chr6_cox_hap2	4795371	+	4147205	4147262	chr11	134452384	-	120264308	120264365	24918209
+57
+
+chain	1584	chr6_cox_hap2	4795371	+	1377344	1377408	chr1	247249719	-	24894387	24894451	17598707
+64
+
+chain	1503	chr6_cox_hap2	4795371	+	2736094	2736140	chr13	114142980	-	72925076	72925122	23344710
+46
+
+chain	1489	chr6_cox_hap2	4795371	+	2908702	2910078	chrX	154913754	-	101842157	101842924	6540871
+27	1297	452
+2	0	236
+50
+
+chain	1456	chr6_cox_hap2	4795371	+	3908424	3908476	chr14	106368585	+	47951043	47951095	9313420
+52
+
+chain	1455	chr6_cox_hap2	4795371	+	2738121	2739528	chr6	170899992	-	65542196	65543586	3697883
+64	1285	1268
+58
+
+chain	1368	chr6_cox_hap2	4795371	+	1377482	1377548	chr11	134452384	+	118435255	118435321	13435147
+66
+
+chain	1368	chr6_cox_hap2	4795371	+	4145973	4146044	chr5	180857866	-	127160909	127160980	20267229
+71
+
+chain	1324	chr6_cox_hap2	4795371	+	3907899	3907958	chr1	247249719	+	29601245	29601304	5732716
+59
+
+chain	1278	chr6_cox_hap2	4795371	+	3908508	3908575	chr15	100338915	+	89926442	89926509	4006770
+67
+
+chain	1265	chr6_cox_hap2	4795371	+	3904331	3904385	chr4	191273063	-	113978359	113978413	18680359
+54
+
+chain	1224	chr6_cox_hap2	4795371	+	2740399	2740456	chr4	191273063	-	135903806	135903863	24465805
+57
+
+chain	1167	chr6_cox_hap2	4795371	+	3908344	3908402	chr4	191273063	+	111464967	111465025	3502724
+58
+
+chain	1054	chr6_cox_hap2	4795371	+	3907390	3907440	chr10	135374737	+	6453196	6453246	3643427
+50
+
+chain	1002	chr6_cox_hap2	4795371	+	2736140	2736200	chr1	247249719	-	71169048	71169108	10800621
+60
+
+chain	988	chr6_cox_hap2	4795371	+	2739771	2739829	chr15	100338915	-	47558730	47558788	2837698
+58
+
+chain	983	chr6_cox_hap2	4795371	+	2737443	2737516	chr11	134452384	-	130067201	130067274	24083146
+73
+
+chain	952	chr6_cox_hap2	4795371	+	2735975	2736093	chr12	132349534	-	67686596	67686714	8250173
+118
+
+chain	919	chr6_cox_hap2	4795371	+	2740748	2740808	chr4	191273063	+	44807134	44807194	22381054
+60
+
+chain	915	chr6_cox_hap2	4795371	+	2736903	2736961	chr18	76117153	+	57868323	57868381	3224910
+58
+
+chain	912	chr6_cox_hap2	4795371	+	2740082	2740112	chr7	158821424	+	107644178	107644208	21981894
+30
+
+chain	876	chr6_cox_hap2	4795371	+	2739742	2739771	chr1	247249719	-	197271642	197271671	12596898
+29
+
+chain	869	chr6_cox_hap2	4795371	+	3907293	3907342	chr10	135374737	+	5116762	5116811	5781535
+49
+
+chain	859	chr6_cox_hap2	4795371	+	2736813	2741147	chr15	100338915	+	18498519	18502823	4451069
+52	4214	4184
+68
+
+chain	858	chr6_cox_hap2	4795371	+	2739831	2739865	chr7	158821424	-	148280259	148280293	6691657
+34
+
+chain	832	chr6_cox_hap2	4795371	+	3906555	3906608	chr11	134452384	-	48407690	48407743	4638931
+53
+
+chain	819	chr6_cox_hap2	4795371	+	3906260	3906310	chr9	140273252	+	32202289	32202339	4057214
+50
+
+chain	781	chr6_cox_hap2	4795371	+	2736320	2736393	chr5	180857866	-	50968960	50969033	9780107
+73
+
+chain	771	chr6_cox_hap2	4795371	+	3907818	3907850	chr10	135374737	-	103151561	103151593	7179825
+32
+
+chain	761	chr6_cox_hap2	4795371	+	2736552	2736619	chr2	242951149	-	140069145	140069212	14744509
+67
+
+chain	747	chr6_cox_hap2	4795371	+	1377768	1377832	chr12	132349534	+	55464534	55464598	20643860
+64
+
+chain	734	chr6_cox_hap2	4795371	+	2739880	2739936	chr3	199501827	-	145206053	145206109	3741906
+56
+
+chain	734	chr6_cox_hap2	4795371	+	2735396	2736320	chr8	146274826	-	112931559	112932176	13565225
+68	769	462
+87
+
+chain	718	chr6_cox_hap2	4795371	+	2740828	2740883	chr9	140273252	-	49339912	49339967	23555332
+55
+
+chain	716	chr6_cox_hap2	4795371	+	4147141	4147193	chr16	88827254	-	38714794	38714846	22851159
+52
+
+chain	709	chr6_cox_hap2	4795371	+	2739652	2739702	chr11	134452384	-	107252690	107252740	6149448
+50
+
+chain	685	chr6_cox_hap2	4795371	+	2738531	2738584	chrX	154913754	-	2978832	2978885	8357317
+53
+
+chain	604	chr6_cox_hap2	4795371	+	1377662	1377688	chrX	154913754	-	101148638	101148664	11583046
+26
+
+chain	566	chr6_cox_hap2	4795371	+	2740606	2740665	chr2	242951149	+	168011719	168011778	5902375
+59
+
+chain	547	chr6_cox_hap2	4795371	+	2740492	2740542	chr11	134452384	-	79794459	79794509	15991276
+50
+
+chain	544	chr6_cox_hap2	4795371	+	2738003	2738054	chr13	114142980	+	104410064	104410115	4879951
+51
+
+chain	541	chr6_cox_hap2	4795371	+	2738408	2738434	chr2	242951149	-	229173591	229173617	17449766
+26
+
+chain	532	chr6_cox_hap2	4795371	+	2740024	2740082	chr9	140273252	-	118104609	118104667	4462652
+58
+
+chain	525	chr6_cox_hap2	4795371	+	3966448	3966514	chr6	170899992	+	32582000	32582066	26144539
+66
+
+chain	497	chr6_cox_hap2	4795371	+	2738584	2738618	chr12	132349534	+	9890463	9890497	23880878
+34
+
+chain	493	chr6_cox_hap2	4795371	+	2739023	2739056	chr22	49691432	+	27063354	27063387	3888752
+33
+
+chain	395	chr6_cox_hap2	4795371	+	2909998	2910026	chrX	154913754	-	101842939	101842967	6370567
+28
+
+chain	367	chr6_cox_hap2	4795371	+	2735248	2735298	chrX	154913754	+	118995097	118995147	25845816
+50
+
+chain	290	chr6_cox_hap2	4795371	+	2741541	2741593	chr1	247249719	-	204952078	204952130	18508596
+52
+
+chain	288	chr6_cox_hap2	4795371	+	3906008	3906069	chr4	191273063	-	55159498	55159559	26293742
+61
+
+chain	182	chr6_cox_hap2	4795371	+	3905895	3905941	chr9	140273252	+	29711555	29711601	32244349
+46
+
+chain	172	chr6_cox_hap2	4795371	+	4087589	4087640	chr1	247249719	-	204983626	204983677	25877235
+51
+
+chain	361837920	chr6_dbb_hap3	4610396	+	0	4610396	chr6	170899992	+	28804582	33437054	36
+932	3	0
+804	0	1
+2406	2	0
+9637	0	1
+2736	6	0
+4013	2	0
+6498	4	0
+6886	0	4
+15284	1	0
+937	0	8
+13552	0	2
+3960	0	2
+2111	0	2
+41	19	0
+8992	0	4
+59229	107905	107904
+87624	0	1
+5902	0	1
+31697	7	0
+1489	1	1
+72	1	1
+2260	0	2
+7033	0	4
+3592	0	1
+19578	0	1
+1324	0	2
+5438	5	0
+2061	1	0
+3982	6	6
+1725	0	1
+3153	1	0
+18	1	0
+18	1	0
+2026	1	0
+4175	10	10
+4746	9	9
+4767	7	7
+1225	1	0
+8	1	1
+151	1	2
+5079	1	1
+28	1	1
+249	43	43
+1178	0	4
+685	8	0
+48	4	0
+1701	1	1
+43	5	5
+862	18	18
+58	1	1
+66	1	1
+420	1	1
+44	1	1
+680	4	4
+1675	1	1
+83	1	1
+3082	4	0
+5467	1	1
+27	0	1
+1099	12	0
+627	12	12
+1317	6	1
+129	1	1
+25	1	1
+1397	15	15
+810	1	1
+27	1	1
+1192	3	0
+7515	4	0
+979	0	3
+3406	0	2
+3501	1	1
+26	1	1
+787	0	1
+1416	3	1
+22815	4	4
+126	1	0
+38	1	1
+140	1	0
+999	0	17
+56	0	15
+15438	4	0
+6165	0	1
+1768	1	0
+7727	1	0
+1514	0	1
+3116	0	1
+3278	1	1
+21	1	1
+1738	0	1
+8576	19	0
+8020	1	0
+2049	1	0
+518	13	11
+1704	1	1
+117	1	1
+1448	10	0
+4403	9	9
+2265	1	0
+25400	9	9
+4420	1	1
+32	1	1
+2539	1	0
+9981	17923	17922
+148	1	1
+25	1	1
+1461	4	1
+1402	0	1
+3961	0	3
+58	1	1
+112	1	1
+1419	1	1
+34	0	1
+2697	0	2
+40	1	1
+2168	0	1
+1019	0	2
+1099	0	4
+40	1	1
+1374	11	0
+31	1	1
+189	1	1
+26	1	1
+327	1	1
+38	1	1
+177	11	11
+303	1	1
+34	1	1
+1438	1	1
+46	1	1
+727	1	1
+26	1	1
+2373	5	0
+321	1	0
+933	17	17
+82	9	9
+2773	0	143
+80	1	1
+25	1	1
+467	1	1
+27	1	1
+143	1	1
+47	4	4
+1194	10	10
+1455	1	1
+33	1	1
+601	1	1
+46	0	4
+694	1	3
+91	1	1
+59	1	1
+167	6	6
+113	1	1
+31	1	1
+1181	0	1
+422	15	0
+36	1	1
+2219	1	1
+35	1	1
+2116	0	1
+8249	0	3
+1120	1	0
+870	16	0
+5547	0	2
+5376	0	6
+2275	1	1
+43	1	1
+78	4	4
+24710	1	0
+64762	6	3
+441	1	0
+2338	1	0
+1948	1	1
+26	1	1
+214	0	1
+6118	1	1
+31	1	1
+2382	5	5
+4335	1	1
+39	1	1
+4561	1	1
+38	1	1
+2199	1	1
+49	1	1
+243	17	6
+2779	1	1
+37	2	0
+24	1	1
+1966	3	0
+233	1	1
+29	1	1
+17718	6	0
+46568	1	0
+18985	0	2
+1833	3	4
+5288	0	9
+2728	1	5
+722	0	1
+502	0	1
+1025	0	1
+134	14	0
+4944	0	1
+319	1	0
+6178	0	1
+2880	1	1
+17	0	2
+143	0	1
+1775	1	0
+2123	0	1
+2715	1	0
+4921	1	1
+47	4	0
+2882	1	0
+1362	1	0
+1233	0	8
+2134	0	1
+1042	0	1
+163	1	1
+45	1	1
+50	2	0
+64	1	1
+48	1	1
+380	0	1
+30	1	0
+30	1	1
+61	1	1
+22	1	1
+691	0	2
+84	1	1
+230	1	1
+37	3	1
+162	1	1
+194	2	0
+36	1	1
+242	9	9
+697	33	33
+1202	1	1
+16	1	1
+528	1	1
+20	1	1
+131	9	9
+369	0	5
+76	1	1
+21	1	1
+439	15	15
+2779	1	0
+1597	24	28
+59	12	12
+307	1	0
+516	1	0
+286	11	33
+339	5	0
+570	1	1
+37	1	1
+220	1	0
+72	1	1
+144	1	1
+48	1	1
+247	2	0
+174	9	10
+816	1	0
+940	1	1
+45	1	1
+91	3	3
+71	1	1
+291	14	14
+100	1	1
+23	1	1
+452	3	3
+229	1	1
+252	0	1
+129	15	15
+432	10	0
+85	1	1
+28	1	1
+189	2	1
+71	1	1
+52	8	0
+810	2	2
+63	1	1
+378	1	1
+26	1	1
+187	31	36
+966	1	1
+25	1	1
+91	12	12
+125	1	1
+38	1	1
+433	2	0
+596	1	1
+48	1	1
+465	4	4
+64	1	1
+20	1	1
+525	5	5
+237	3	8
+99	31	31
+53	11	0
+364	4	3
+201	1	1
+42	1	1
+56	1	1
+115	1	0
+67	16	16
+244	1	1
+54	5	5
+929	1	1
+21	1	1
+126	0	3
+830	1	11
+59	1	1
+537	0	2
+24	1	1
+745	15	15
+810	1	0
+425	1	1
+89	1	1
+592	1	1
+49	1	1
+352	0	1
+142	1	1
+30	1	1
+95	1	1
+45	1	1
+227	1	1
+53	1	1
+130	1	1
+18	1	1
+138	1	1
+90	1	1
+129	1	1
+39	1	1
+50	1	1
+79	1	1
+117	1	1
+31	1	1
+155	156	0
+34	1	1
+50	5	5
+57	1	1
+152	1	1
+30	1	1
+177	5	5
+345	1	1
+39	1	1
+504	18	18
+596	12	12
+54	1	1
+158	1	1
+164	1	1
+34	1	1
+626	15	15
+866	0	10
+1051	0	2611
+680	0	1
+1537	0	18
+75	1	0
+145	6	0
+9	39	0
+107	0	18
+23	1	1
+1927	13	13
+1702	2	0
+3694	1	1
+18	1	1
+958	39	47
+246	2	0
+146	1	1
+49	1	1
+410	1	0
+667	1	1
+38	1	1
+362	7	1
+159	2	0
+515	2	0
+1026	1	1
+29	1	1
+249	0	6
+129	1	1
+33	4	0
+10	1	5
+1236	1	1
+20	1	1
+138	10	9
+448	0	3
+660	1	1
+28	1	1
+83	1	1
+51	1	1
+2659	1	1
+38	1	1
+424	0	1
+70	1	1
+694	1	1
+19	1	1
+105	1	1
+26	1	1
+1472	1	1
+21	1	1
+491	5	5
+163	15	15
+2194	2	0
+533	2	0
+441	1	7
+1689	1	1
+26	3	4
+879	16	16
+514	0	2
+58	1	1
+350	1	0
+769	1	1
+39	1	1
+573	0	4
+37	1	1
+144	8	8
+1036	2	0
+262	2	2
+38	0	1
+70	18	18
+84	11	13
+169	62	63
+74	11	15
+1255	0	2
+332	1	1
+21	1	1
+193	8	24
+34	1	1
+79	1	1
+29	1	1
+536	1	0
+308	0	1
+850	0	32
+23	1	1
+651	1	1
+22	0	3
+136	1	1
+48	1	1
+330	9	9
+1108	1	1
+98	1	1
+582	0	2
+713	7	7
+89	1	0
+293	9	8
+125	1	1
+31	1	1
+192	6	6
+171	17	17
+681	1	1
+43	1	1
+514	1	1
+68	1	1
+537	1	1
+35	1	1
+159	6	6
+778	17	17
+198	0	7
+105	1	1
+40	1	1
+95	13	13
+247	1	1
+19	1	1
+2044	7	8
+2512	0	15
+2982	4	0
+3135	1	2
+1698	13	13
+15862	0	1
+925	0	183
+36	16	1
+18	0	1
+25	1	1
+7717	1	1
+40	1	1
+758	1	1
+46	1	1
+5530	11	9
+3326	1	1
+37	1	1
+6743	0	4
+7923	1	1
+26	5	5
+3475	26	0
+8	1	1
+566	4	0
+141	0	1
+2078	24	24
+2759	0	4
+1659	4	0
+52	4	0
+3265	0	2
+2235	17	16
+2946	0	372
+2644	31	31
+92	1	1
+35	1	1
+705	323	0
+3157	40	40
+718	0	4
+787	1	1
+34	1	1
+927	4	4
+72	1	1
+2414	0	1
+993	1	1
+31	1	1
+1514	1	1
+29	1	1
+1109	1	1
+44	1	1
+208	4	1
+1022	11767	11699
+85	98	98
+60	2515	8169
+103	11	11
+41	1	1
+72	4	4
+76	1	1
+70	5	5
+83	1	1
+117	1	1
+130	1	1
+44	1	1
+414	1	1
+152	1	0
+218	1	1
+161	1	0
+120	14	14
+145	1	1
+49	4	4
+72	1	1
+53	19	19
+111	2	2
+32	3	3
+553	0	2
+336	12	12
+54	24	24
+171	0	6
+90	1	1
+28	1	1
+142	16	16
+36	1	1
+428	1	1
+16	1	1
+338	1	1
+31	1	1
+294	1	1
+92	0	1
+129	13	14
+602	1	1
+112	1	1
+247	1	1
+80	1	1
+173	1	1
+44	1	5
+497	1	1
+38	1	1
+98	1	1
+130	1	1
+319	1	1
+16	1	1
+59	1	1
+82	1	1
+141	1	1
+23	1	1
+241	1	1
+26	1	1
+184	0	3
+19	1	1
+510	1	1
+36	1	1
+162	2	2
+15	1	1
+145	1	1
+28	1	1
+120	0	3
+93	1	2
+24	0	9
+169	12	0
+292	9911	10000
+401	1	1
+27	1	1
+296	1	1
+120	1	1
+357	1	1
+107	2	0
+31	1	1
+83	89	0
+194	1	1
+33	1	1
+230	1	1
+142	5	5
+108	1	1
+36	1	1
+287	1	1
+19	1	1
+104	1	1
+31	1	1
+144	1	1
+212	1	1
+452	5	6
+148	1	1
+70	1	1
+137	3	3
+67	1	1
+73	22	22
+115	12	12
+142	5	5
+269	15	15
+102	6	6
+93	1	1
+82	1	1
+170	1	1
+22	1	1
+504	2	2
+60	1	1
+150	1	1
+31	1	1
+90	1	1
+15	1	0
+258	6	7
+85	1	1
+77	1	1
+123	2	2
+67	0	1
+56	2	2
+25	1	1
+71	1	1
+28	2	2
+50	1	1
+85	2	2
+66	6	6
+186	1	1
+20	1	1
+67	1	1
+25	1	1
+227	2	2
+155	1	1
+777	1	1
+33	1	2
+26	6	6
+474	1	1
+36	1	1
+151	1	1
+29	1	1
+120	1	1
+23	1	1
+736	17	17
+112	1	1
+39	1	1
+553	1	1
+69	1	1
+116	2	0
+161	1	1
+86	1	1
+705	1	1
+57	3	3
+145	1	1
+204	1	1
+88	1	1
+35	1	1
+92	1	1
+147	1	1
+149	20	20
+210	1	1
+55	2	2
+65	1	1
+32	1	1
+1008	1	1
+24	1	1
+159	18	18
+391	0	1
+327	17	19
+77	1	3
+65	1	1
+84	1	0
+392	2	0
+363	1	0
+1024	0	1
+480	9	9
+119	1	1
+72	1	1
+400	1	1
+46	1	1
+288	11	7
+53	1	1
+80	1	1
+37	1	1
+129	1	1
+80	1	1
+252	4	4
+86	0	1
+129	3	3
+67	1	1
+123	9	9
+199	2	2
+80	1	1
+114	28369	30000
+51	5	5
+45	1	1
+53	1	1
+37	1	1
+81	1	1
+369	1	1
+72	15	15
+98	1	1
+53	0	8
+67	2	0
+41	1	1
+92	1	1
+20	1	1
+283	6	6
+70	7	7
+50	1	1
+25	1	1
+225	5	1
+31	1	1
+449	2	1
+10	1	23
+64	4	4
+3770	1	0
+3862	16	16
+1187	12	12
+97	0	3
+772	1	1
+21	2	1
+1058	0	2
+349	2	0
+1080	18	14
+53	15	17
+1035	1	1
+85	1	1
+69	1	1
+27	1	1
+547	7	7
+195	1	1
+41	1	1
+395	1	1
+35	1	1
+73	0	1
+71	1	1
+557	3	3
+30	1	1
+66	1	1
+25	1	1
+1332	0	2
+26	2	0
+10	1	15
+36	1	1
+196	1	1
+40	1	1
+141	1	1
+76	1	1
+1480	1	3
+347	1	1
+26	1	1
+231	1	1
+82	3	3
+69	3	0
+441	16	16
+147	1	1
+21	1	1
+3565	0	6
+874	2	0
+1036	1	1
+47	3	1
+3761	12	0
+5345	1	0
+11541	1	0
+1843	0	4
+1157	16	16
+7354	19	0
+741	0	1
+8053	1	0
+4449	21	21
+649	1	0
+2913	0	1
+381	332	0
+3533	31	31
+2502	0	1
+1968	7	0
+3198	1	0
+667	1	0
+3870	0	1
+36	13	0
+1894	1	1
+40	0	4
+1348	2	0
+345	1	0
+592	4	4
+1043	4	0
+686	14	0
+1032	0	1
+9035	0	4
+167	0	2
+13644	6258	6257
+4063	0	3
+1760	3	0
+3371	1	1
+23	1	1
+321	5	0
+644	8	0
+47	1	1
+322	1	1
+145	1	1
+1551	11	15
+355	0	1
+1831	4	0
+1779	1	1
+27	1	1
+199	43	55
+2881	1	1
+39	1	1
+120	1	2
+24	1	1
+556	1	0
+393	6	6
+4381	1	0
+524	1	1
+20	1	1
+151	3	3
+144	1	1
+189	1	7
+1445	0	1
+1002	0	1
+7912	4	0
+4977	0	1
+10485	1	1
+48	1	1
+724	1	1
+51	5	0
+39	1	1
+6830	0	1
+15554	0	1
+4385	0	7
+881	0	8
+17594	0	20
+2417	1	0
+998	0	10
+4239	7	0
+4845	0	2
+95	28	23
+10921	1	1
+40	1	1
+4759	0	6
+12084	0	3
+3052	0	4
+2989	1	0
+13523	1	3
+16170	1	0
+11761	0	6
+1158	3	0
+2751	0	6
+1294	1	1
+43	1	1
+5275	0	7
+377	3	0
+7256	3	0
+419	2	0
+10674	0	17
+10821	0	1
+296	0	1
+1770	2	0
+374	0	3
+7469	0	4
+1471	1	0
+3061	2	0
+5818	1	0
+2415	11	9
+2056	0	1
+955	4	0
+17260	1	0
+9557	0	2
+5358	0	1
+11538	4	0
+2627	2	0
+57496	1	1
+29	1	1
+6617	19	0
+254	0	1
+14267	2	0
+9045	3	1
+174	2	0
+4155	1	0
+1153	1	0
+1289	0	40
+12155	0	4
+7692	2	0
+396	22	12
+918	0	1
+1818	0	1
+28	1	1
+492	1	1
+33	1	1
+326	1	1
+80	1	1
+288	8	17
+2671	0	1
+1099	0	1
+144	1	1
+29	0	1
+2098	0	2
+24	3	0
+1207	4	4
+45	1	1
+757	0	5
+1926	1	1
+40	1	1
+330	3	0
+340	1	1
+43	1	1
+1942	0	1
+414	1	0
+61	0	1
+235	0	2
+2087	0	1
+754	0	4
+17	3	0
+1027	3	0
+428	1	1
+17	1	1
+948	1	1
+41	1	1
+458	1	1
+21	1	1
+1055	0	1
+8189	4	5
+36	1	1
+99	2	0
+700	0	4
+149	0	1
+750	0	3
+40	1	1
+3179	2	0
+473	0	2
+2032	1	0
+3841	1	0
+560	1	0
+1108	1	0
+8087	1	0
+11881	1	1
+30	1	1
+4383	3	0
+9930	1	1
+56	510	509
+518	8	5
+853	1	1
+80	1	1
+2210	1	0
+905	0	1
+1037	2	0
+5866	0	2
+18	1	1
+582	0	5
+2828	1	0
+847	1	0
+1996	2	0
+700	1	1
+1970	0	1
+498	1	0
+1751	0	1
+910	2	0
+691	0	1
+32873	0	1
+19298	0	6
+1371	29	0
+494	2	0
+39050	0	1
+920	0	1
+6820	1	0
+1376	1	2
+1931	33	33
+2376	0	1
+12415	1	1
+51	0	1
+9375	0	1
+323	1	0
+2697	1	0
+15090	120	0
+7116	1	0
+2469	1	0
+5977	2	1
+4888	0	4
+4674	1	0
+2044	1	0
+2153	0	1
+1964	5	5
+2153	1	1
+41	1	1
+774	0	2
+2623	1	1
+81	1	1
+335	2	2
+59	1	1
+335	0	3
+533	2	0
+45	4	0
+986	2	0
+13	1	1
+450	28	27
+295	1	0
+202	1	1
+27	1	1
+70	312	0
+218	1	0
+51	1	1
+31	1	1
+428	0	1
+28	1	1
+118	1	1
+24	1	18
+34	1	1
+75	1	1
+43	2	2
+73	1	1
+29	1	1
+246	1	1
+42	1	1
+409	4	4
+1168	10	1
+310	1	1
+49	1	1
+3002	1	1
+38	1	1
+789	0	1
+63	9	9
+2434	0	8
+980	0	2
+749	8	8
+528	1	1
+24	1	1
+1646	15	15
+528	1	1
+16	1	1
+1402	1	1
+23	1	1
+67	7	0
+35	2	0
+7	0	2
+221	1	1
+45	1	1
+259	1	1
+47	1	1
+384	1	1
+47	1	1
+330	0	4
+490	1	1
+33	1	1
+1841	1	1
+52	0	2
+6	11	0
+193	1	1
+47	1	1
+164	3	7
+31	0	1
+291	1	1
+15	1	1
+877	4	0
+30	1	1
+194	6	0
+93	4	4
+1004	1	1
+20	1	1
+345	1	1
+43	1	1
+365	0	1
+388	1	1
+27	1	1
+253	9	9
+390	1	0
+118	0	1
+170	4	0
+915	1	0
+352	0	4
+520	1	1
+29	20	0
+1167	1	1
+45	1	1
+213	8	0
+51	1	1
+107	10	11
+134	2	0
+228	103	1
+51	2	1
+68	1	1
+59	1	1
+195	1	161
+13	1	1
+553	2	2
+36	1	1
+143	1	0
+1874	4	0
+519	0	1
+476	1	0
+1530	0	1
+1126	2	0
+831	1	1
+40	1	1
+1131	88	87
+2063	0	2
+1950	1	1
+32	1	1
+2217	2	1
+661	0	2
+1239	0	1
+64	1	1
+33	1	1
+13968	0	1
+1222	2	0
+5082	10	0
+413	0	1
+986	23	22
+1194	2527	2526
+12324	0	2
+893	8	0
+1343	2	0
+5784	9	9
+770	12	0
+1044	2	0
+2231	1	1
+48	1	1
+557	0	1
+7497	8	8
+1051	16	0
+49	1	1
+10474	0	3
+1427	1	0
+670	1	3
+766	1	1
+32	1	1
+395	0	9
+170	1	0
+792	2	0
+286	1	0
+117	11	12
+283	26	21
+277	0	2
+48	1	1
+124	1	1
+34	2	1
+316	1	1
+41	1	1
+8214	0	8
+368	2	0
+4	4	0
+3535	17	0
+4228	33	33
+945	0	1
+562	0	1
+1440	0	1
+804	0	11
+1565	0	3
+3008	1	0
+31	1	1
+800	21	17
+650	1	1
+30	1	1
+82	13	13
+5212	1	0
+2003	1	2
+12179	0	1
+2700	2	0
+2735	0	1
+4202	0	3
+4503	1	0
+270	1	0
+12929	0	3
+4009	0	5
+6425	2	0
+310	1	0
+809	2	0
+17	8	0
+2256	0	1
+3207	17	10
+2436	0	14
+1040	1	1
+52	1	1
+6972	1	0
+2357	0	1
+29	1	1
+262	1	0
+72	1	1
+45	1	1
+57	17	17
+1390	0	16
+328	312	0
+65	1	1
+217	10	10
+925	0	33
+1490	1	0
+35	1	1
+226	0	3
+805	1	1
+46	1	1
+192	1	1
+56	1	1
+245	1	1
+61	1	1
+198	4	0
+82	2	2
+29	1	1
+57	0	2
+320	1	1
+22	1	1
+267	5	0
+427	1	0
+17	1	1
+425	1	1
+34	1	1
+565	10	10
+432	10	0
+55	1	1
+90	1	1
+140	1	1
+83	1	1
+1035	1	1
+33	1	1
+144	4	4
+38	1	1
+171	1	1
+35	3	3
+161	6	6
+731	7	3
+1216	25	0
+52	0	1
+419	2	0
+87	8	8
+757	1	1
+67	1	1
+3935	30	0
+791	3	0
+2849	1	1
+33	1	1
+6790	1	1
+67	4	4
+39	2	0
+251	1	1
+37	1	1
+826	3715	901
+205	2	0
+946	1	1
+30	1	1
+613	5	2
+128	29	29
+802	0	89
+1600	0	6
+2112	1	1
+42	1	0
+1164	1	0
+1310	1	0
+1501	0	4
+822	1	1
+42	1	1
+2266	1	0
+25235	0	1
+6697	1	0
+766	1	0
+4188	0	2
+2710	1	1
+17	1	1
+1924	0	7
+5868	1	1
+22	1	1
+2394	0	4
+125	3	0
+718	1	0
+8414	1	1
+49	1	1
+146	1	1
+61	1	1
+116	1	1
+41	1	1
+137	1	1
+30	1	1
+158	9	9
+136	10	13
+1733	17	17
+1053	4	4
+228	1	1
+34	1	1
+355	1	1
+113	1	1
+330	0	1
+222	1	1
+25	1	1
+267	1	1
+38	1	1
+709	2	0
+1448	0	1
+152	1	1
+46	1	1
+237	1	1
+20	1	1
+195	21	21
+88	1	1
+33	1	1
+211	1	1
+65	1	1
+516	58	58
+491	7	7
+208	13	12
+558	2	2
+28	1	1
+125	4	4
+634	1	1
+33	1	1
+159	0	1
+318	1	0
+370	5	5
+80	1	1
+250	0	3
+78	1	1
+45	1	1
+130	3	1
+22	0	1
+180	1	1
+90	1	1
+633	1	1
+36	0	1
+388	0	1
+861	1	1
+103	1	1
+274	16	18
+170	30	30
+796	0	1
+167	0	1
+871	1	1
+27	1	1
+32	0	8
+831	0	13
+90	1	1
+527	1	1
+125	1	1
+1050	10	10
+624	16	16
+1093	5	5
+48	1	0
+168	30	34
+1315	1	1
+33	1	1
+303	1	1
+36	1	1
+601	14	14
+1014	4	0
+134	2	9
+818	1	0
+61	1	7
+641	5	5
+1677	1	1
+49	1	1
+346	87	87
+790	27	27
+104	1	1
+75	1	1
+1638	1	1
+16	1	1
+92	1	1
+44	1	1
+276	0	13
+1020	1	1
+35	1	1
+389	14	14
+256	1	0
+38	1	3
+106	1	1
+21	1	1
+502	1	1
+40	1	1
+2356	1	1
+82	2	0
+1300	0	5
+511	0	2
+605	1	1
+17	1	1
+880	13	0
+1689	4	0
+2492	1	1
+39	1	1
+641	16	16
+682	0	5
+669	1	1
+25	1	1
+1926	1	1
+39	4	3
+1037	1	1
+40	2	0
+890	6	0
+41	2	0
+501	4	1
+317	0	1
+281	3	0
+450	1	1
+34	1	1
+498	1	1
+28	2	1
+280	0	2
+648	1	1
+47	1	1
+1002	4	0
+120	1	1
+1538	0	1
+75	1	1
+37	1	1
+517	1	1
+79	4	4
+60	18	18
+2075	1	1
+19	1	1
+2429	1	1
+21	1	1
+107	1	0
+2786	0	2
+33	3	3
+1973	8	0
+3118	1	0
+246	0	1
+33	1	1
+1333	9	9
+5410	1	0
+822	2	9
+606	1	1
+18	1	1
+3920	1	1
+37	0	2
+4497	10	13
+2468	2	0
+1510	1	1
+23	1	1
+308	0	4
+3780	3	0
+850	0	1
+2774	0	3
+3487	1	0
+3243	0	15
+1336	5	0
+618	7	7
+1507	8	7
+379	44	43
+2184	0	1
+304	0	2
+19	0	1
+101	1	1
+417	3	3
+22	1	1
+672	4	4
+31	1	1
+150	1	1
+38	1	1
+161	5	0
+17	1	1
+72	1	0
+106	1	1
+463	1	1
+236	0	2
+184	1	1
+29	1	1
+220	15	15
+167	1	1
+32	1	1
+93	1	3
+217	1	1
+23	1	1
+137	9	9
+62	0	3
+353	1	1
+27	1	1
+117	9	9
+421	1	1
+47	1	1
+124	0	1
+997	6	0
+54	5	5
+764	1	1
+45	1	1
+1431	7	7
+387	6	6
+1103	0	44
+759	1	1
+31	1	3
+208	5	5
+1610	1	1
+23	1	1
+779	0	8
+311	0	3
+322	0	3
+45	1	1
+250	1	1
+18	1	1
+517	29	0
+117	1	1
+42	1	1
+550	1	1
+20	1	1
+671	1	1
+68	1	1
+89	1	1
+104	1	1
+172	0	1
+124	0	1
+522	0	1500
+466	5	5
+32	1	0
+171	1	1
+19	1	1
+67	1	1
+22	1	1
+654	1	1
+25	1	1
+68	1	1
+21	4	0
+1588	1	1
+66	1	1
+401	0	1
+186	1	1
+21	1	1
+168	0	1
+686	3	0
+19	1	1
+127	1	1
+29	1	1
+234	1	1
+30	1	1
+141	0	2
+33	1	1
+673	1	1
+89	1	1
+161	16	16
+504	1	1
+192	0	3
+105	1	1
+286	1	1
+101	15	16
+158	8	0
+57	1	1
+332	2	2
+35	1	1
+371	1	1
+55	1	1
+86	1	1
+29	1	1
+196	1	1
+44	1	0
+52	19995	20030
+60	8	8
+50	0	3
+129	1	1
+281	1	1
+30	1	1
+109	1	1
+35	1	1
+113	1	1
+34	1	1
+734	1	1
+44	1	1
+106	1	1
+62	1	1
+140	1	1
+76	1	0
+34	1	1
+98	1	1
+149	1	1
+284	1	1
+37	1	1
+705	1	12
+106	1	1
+55	1	1
+1470	0	7
+258	1	1
+48	1	1
+1807	6	6
+63	1	1
+32	1	1
+346	18	18
+9596	12	0
+3853	9	9
+317	4	4
+30	1	1
+71	1	1
+60	1	1
+103	10	10
+71	2	0
+30	1	1
+312	5	0
+170	13	13
+55	2	2
+58	1	0
+30	1	1
+189	37	38
+827	0	17
+26	1	1
+1461	1	1
+24	1	1
+2968	22	22
+137	12	14
+889	11	11
+4010	0	6
+1377	1	1
+34	1	1
+312	1	1
+16	1	1
+715	1	1
+24	1	1
+930	1	1
+22	1	1
+89	1	1
+42	1	1
+108	44	45
+228	149088	159295
+108	1	1
+41	1	1
+11025	4	4
+1194	1	1
+59	1	1
+128	1	0
+1177	82	82
+60	1	1
+48	1	1
+501	19	19
+336	1	1
+42	1	1
+176	4	4
+469	1	1
+35	1	1
+270	1	1
+33	1	1
+289	1	1
+24	1	1
+226	64	0
+42	1	1
+651	1	1
+39	1	1
+123	1	1
+35	1	0
+294	1	1
+32	18	4
+351	1	1
+39	1	1
+135	1	1
+46	1	1
+121	1	1
+19	1	1
+755	4	4
+70	1	1
+456	39	36
+82	1	1
+48	1	1
+441	1	1
+70	1	1
+381	1	1
+46	1	1
+239	1	1
+30	1	1
+87	1	1
+102	3	4
+34	1	1
+488	12	12
+1059	1	1
+45	1	1
+705	1	1
+21	1	1
+107	111	111
+432	3	0
+460	4	4
+1212	0	2
+306	0	1
+1446	19	19
+299	7	33
+78	195	6
+66	1	1
+135	12	12
+778	1	0
+773	1	1
+45	1	1
+253	6	6
+823	1	1
+22	1	1
+2476	10	0
+294	28	10
+307	3	11
+65	0	4
+40	1	1
+4535	1	1
+26	1	1
+371	0	2
+3510	1	1
+16	1	1
+189	1	1
+19	1	1
+814	0	1
+2785	6	1
+1424	0	1
+934	1	1
+49	1	1
+1350	1	0
+384	1	1
+24	1	1
+3117	10	10
+518	0	1
+523	0	16
+243	10	10
+2167	18	14
+64	1	1
+31	1	1
+185	0	4
+1647	1	1
+20	1	1
+227	1	1
+37	1	1
+636	3	4
+8239	1	1
+23	1	1
+1114	0	2
+1590	18	18
+4781	0	4
+815	0	1
+5069	0	5
+415	0	1
+3541	0	1
+878	0	1
+5752	0	2
+1502	0	1
+51	1	1
+60	1	1
+278	0	1
+19	1	1
+1164	11	11
+691	0	2
+960	1	0
+63	0	18
+2109	0	2
+1265	0	1
+1642	2	0
+10831	4	2
+188	0	1
+1650	1	0
+40	1	1
+2962	2	0
+48	1	1
+4899	6	0
+4945	1	0
+60	4	0
+964	0	1
+918	1	0
+706	0	3
+349	1	0
+1673	0	1
+1909	11	11
+1662	15	0
+720	0	1
+2076	0	2
+329	14	0
+3605	0	3
+853	5	6
+3597	1	0
+378	0	1
+969	2	0
+299	0	1
+874	0	4
+663	6	0
+297	0	3
+2049	0	3
+878	11	11
+93	43	43
+13912	0	1
+398	1	1
+145	1	1
+512	16	16
+3139	0	4
+1305	7	0
+3045	1	0
+4179	1	1
+37	1	1
+1336	4	0
+13736	1	0
+11145	1	0
+3867	1	0
+1713	0	1
+2721	0	9
+8875	0	2
+4120	2	0
+13331	0	2
+15149	0	1
+8815	2	0
+1617	0	1
+1686	4	0
+2225	4	0
+7008	1	0
+4374	0	1
+2620	4	0
+43394	1	0
+10823	4	0
+25730	0	1
+554	1	0
+128	0	1
+8274	17	17
+22100	0	4
+40775	1	0
+5693	29	27
+170	1	0
+3528	0	1
+191	1	2
+117	2	0
+2275	1	0
+12676	1	1
+20	1	1
+5364	1	0
+1275	0	2
+3331	1	0
+310	1	0
+13645	0	5
+14860	1	1
+38	1	1
+3605	0	1
+2898	0	1
+10662	1	0
+8241	17	17
+439	16	16
+59	5	4
+7707	1	0
+3007	1	1
+40	1	1
+1569	1	1
+30	1	1
+163	11	11
+8253	35	6402
+5016	17	17
+439	16	16
+59	4	5
+9184	1	1
+19	1	1
+2941	1	1
+105	1	1
+803	5	4
+1011	1	1
+43	1	1
+705	8	8
+574	1	0
+7691	1	0
+5183	0	2
+9452	5	0
+45	0	8
+4438	1	0
+6869	1	0
+1770	0	1
+4094	0	12
+4249	0	3
+4114	0	1
+1404	0	1
+1229	0	2
+3129	0	10
+769	0	2
+709	1	0
+161	0	1
+969	0	1
+1492	0	7
+655	8	8
+251	0	2
+234	1	0
+19500	0	2
+8097	1	0
+1243	0	4
+718	0	2
+1466	1	0
+527	1	0
+3294	1	0
+299	0	1
+374	1	0
+107	1	1
+21	1	1
+2114	0	1
+1422	0	1
+2149	1	0
+311	2	0
+2025	1	1
+36	1	1
+4504	2	0
+3636	10	0
+588	1	1
+21	1	1
+3237	15	0
+39	6	0
+547	74304	74303
+1020	0	3
+747	0	1
+1011	1	1
+43	1	1
+3164	1	0
+1681	0	2
+473	1	5
+107	4	0
+719	0	1
+1154	9	9
+221	0	2
+9332	1	0
+1190	30	0
+783	1	1
+59	1	1
+94	1	1
+21	1	1
+430	11	11
+50	1	1
+49	1	1
+289	3	0
+120	0	1
+37	1	1
+112	1	1
+21	1	1
+183	16	16
+73	2	0
+1007	1	1
+38	0	1
+79	1	1
+48	1	1
+561	1	1
+29	1	1
+145	5	5
+576	12	12
+834	1	0
+846	5	7
+34	1	1
+483	1	1
+40	1	1
+110	7	7
+393	1	1
+215	1	1
+260	1	1
+36	0	1
+604	1	0
+169	0	1
+2118	1	1
+34	1	1
+147	1	1
+213	1	1
+67	1	1
+31	1	1
+566	1	0
+17	1	1
+210	0	2
+551	1	1
+34	1	1
+685	0	3
+24	2	2
+98	0	1
+449	0	2
+61	1	1
+38	1	1
+202	1	1
+44	1	1
+190	1	0
+46	4	4
+51	0	4
+476	1	1
+17	1	1
+82	1	1
+46	1	1
+82	1	1
+26	1	1
+485	1	1
+25	1	1
+263	1	1
+26	1	1
+1327	4	0
+44	1	0
+2397	1	1
+44	1	1
+928	4	0
+3218	14	14
+4406	1	0
+1125	1	0
+254	1	0
+427	0	1
+30	1	1
+111	0	2
+586	17	1
+970	1	1
+10	1	0
+28	1	1
+140	1	1
+43	1	1
+1327	1	1
+24	1	1
+636	2	1
+598	1	1
+44	1	1
+170	1	0
+4840	1	1
+28	11	7
+485	0	1
+263	0	2
+4912	4	0
+543	1	0
+18	1	1
+127	1	2
+102	6	0
+148	16	7
+1346	0	1
+128	7	0
+49	0	1
+876	1	0
+286	5	5
+184	0	1
+84	5	5
+365	9	9
+981	1	1
+11	1	1
+734	4	0
+563	4	0
+632	1	1
+17	1	1
+49	1	0
+95	1	1
+30	1	1
+147	1	1
+37	0	6
+340	1	2
+58	1	1
+112	0	1
+219	0	2
+231	0	3
+164	0	1
+26	1	1
+439	4	0
+34	0	2
+508	3	0
+96	1	1
+34	1	1
+829	1	1
+31	1	1
+405	15	15
+663	4	5
+1055	13	13
+135	0	1
+194	63	63
+384	6	6
+2756	1	1
+19	1	1
+1868	2	3
+2238	1	1
+31	1	1
+3002	4	0
+1116	1	1
+22	1	1
+1016	15	15
+855	15	13
+442	5	5
+2022	6	6
+506	0	2
+1110	0	1
+7396	1	1
+84	1	0
+3187	1	1
+16	1	1
+184	1	1
+18	1	1
+1607	53	60
+527	1	1
+39	1	1
+288	0	1
+364	3	0
+227	1	1
+18	1	1
+218	0	323
+91	1	0
+124	0	15
+621	0	4
+553	8	8
+467	1	1
+40	1	1
+372	1	1
+25	1	1
+188	12	12
+357	0	1
+250	0	5
+4193	0	4
+597	49	49
+321	1	1
+76	1	1
+2040	11	10
+1137	1	1
+48	4	4
+529	7	7
+246	4	0
+160	1	1
+34	0	3
+1469	0	2
+241	1	1
+17	1	1
+239	1	0
+937	1	1
+45	1	1
+421	6	0
+2127	0	1
+491	1	0
+80	1	1
+72	2	0
+255	6	6
+739	3	0
+702	5	0
+290	0	2
+210	5	1
+473	1	1
+42	4	0
+219	0	1
+348	1	1
+83	1	1
+851	0	16
+72	14	0
+246	1	1
+47	4	0
+410	1	0
+93	0	12
+225	0	14
+430	1	0
+4	6	0
+324	0	1
+939	1	1
+27	1	1
+142	1	1
+37	1	1
+1246	1	1
+44	1	1
+445	0	4
+173	0	2
+10545	1	1
+47	1	1
+1247	37	55
+805	1	0
+3789	1	1
+35	1	1
+1731	30	30
+2105	1	1
+30	1	1
+6075	1	0
+462	0	15
+4585	1	0
+3297	1	1
+49	1	1
+606	1	1
+48	1	1
+123	5	9
+109	1	31
+44	10	781
+77	2	0
+114	1	1
+62	1	1
+106	1	1
+268	18	4
+1079	0	2
+381	4	4
+106	1	1
+376	1	0
+1011	8	0
+584	5	0
+7537	7	0
+736	13	3
+2095	1	1
+45	1	1
+12786	0	11
+43	1	1
+720	5	7
+1358	0	2
+3813	19986	20000
+486	1	1
+46	1	1
+412	1	1
+23	1	0
+174	1	1
+24	1	1
+83	15	15
+363	1	1
+91	1	1
+51	17	17
+315	20	20
+199	13	13
+976	1	1
+39	0	3
+161	14	15
+127	16	16
+517	1	1
+81	1	1
+218	28	28
+124	1	1
+68	0	22
+252	1	1
+36	1	1
+784	0	1
+175	1	0
+148	1	1
+83	1	1
+469	1	1
+69	1	1
+245	1	1
+90	4	4
+1034	15	15
+69	1	1
+33	1	1
+174	1	1
+56	1	1
+169	1	0
+201	1	1
+30	1	1
+58	1	1
+38	1	1
+91	1	1
+98	4	4
+65	1	1
+19	2	0
+104	6	5
+25	1	1
+218	1	1
+37	1	1
+343	153809	150023
+66	8	8
+36	0	11
+62	1	1
+107	1	1
+68	3	130
+66	4	4
+50	21	21
+98	1	1
+127	1	0
+192	1	1
+71	1	1
+52	1	1
+200	1	1
+97	4	4
+85	5	5
+448	1	1
+97	11	11
+171	1	1
+61	1	1
+37	1	1
+156	3	0
+63	0	3
+155	3	0
+32	2	0
+232	1	1
+33	1	1
+175	2	0
+131	6	6
+1409	0	3
+222	1	1
+23	0	1
+1470	1	1
+21	1	1
+460	1	1
+71	1	1
+394	2	8
+37	1	1
+90	1	1
+43	1	1
+650	1	1
+34	1	1
+839	0	1
+431	1	1
+36	1	1
+284	60066	60160
+93	1	1
+75	808	0
+46	1	1
+221	1	1
+213	8	0
+63	1	1
+60	17	17
+53	1	1
+29	1	1
+68	8	8
+62	9	9
+51	1	1
+85	1	1
+101	1	1
+54	2	2
+116	1	1
+66	1	1
+182	1	0
+37	1	1
+134	14	14
+117	1	1
+45	1	1
+120	1	1
+47	1	1
+342	1	1
+46	1	1
+237	12	12
+107	8	8
+754	1	0
+880	1	1
+16	1	1
+741	1	1
+47	0	1
+19	2	2
+165	0	21
+26	1	1
+183	13	13
+72	1	1
+23	1	0
+268	14	14
+320	1	1
+55	1	1
+414	5	5
+172	0	1
+620	1	1
+18	1	1
+190	1	1
+20	0	8
+849	1	1
+29	1	1
+978	30213	30058
+159	1	1
+36	1	1
+107	1	1
+176	1	1
+154	0	5
+91	1	1
+54	1	1
+77	1	1
+239	1	1
+50	1	1
+128	1	1
+40	1	1
+62	1	0
+111	11	11
+734	1	1
+31	1	1
+215	1	1
+108	1	1
+259	1	1
+79	1	1
+80	1	1
+47	3	1
+40	1	1
+54	1	1
+46	1	1
+118	9	9
+98	1	0
+5	11	4
+23	0	7
+84	1	1
+84	2	2
+6	0	1
+6	1	0
+110	0	7
+537	1	1
+96	1	1
+441	1	1
+101	1	1
+242	14	14
+255	16	16
+142	1	0
+345	10	10
+54	1	1
+26	1	1
+108	1	1
+83	1	1
+128	1	1
+36	1	1
+231	1	1
+37	1	1
+534	1	1
+60	1	1
+804	0	3
+43	1	1
+148	1	1
+25	1	1
+69	10	10
+76	5	5
+37	1	1
+66	0	2
+192	1	1
+60	3	0
+19	1	1
+1149	1	1
+18	1	1
+77	1	1
+22	3	0
+42	1	1
+136	1	1
+78	2	0
+1712	8	9
+548	1	1
+50	1	1
+177	1	0
+410	1	1
+42	1	1
+422	10	10
+963	4	4
+329	1	9
+648	5	1
+117	1	1
+27	1	1
+574	1	0
+507	1	1
+39	1	1
+294	3	2
+549	1	1
+22	1	1
+74	0	1
+98	1	1
+65	3	3
+230	1	1
+18	1	0
+33	1	1
+51	1	1
+24	1	1
+811	1	1
+59	0	2
+8	1	1
+80	9	9
+437	14	14
+57	4	4
+588	15	15
+305	1	1
+17	1	1
+135	1	1
+50	1	1
+59	16	16
+129	1	1
+25	2	0
+12	1	1
+106	1	1
+31	1	1
+350	1	1
+47	1	1
+340	1	1
+65	1	1
+478	2	0
+714	8	7
+95	2	2
+52	2	1
+1129	1	1
+34	1	1
+1715	1	1
+87	1	1
+692	1	1
+47	0	1
+75	1	1
+2155	10	10
+1407	0	2
+202	1	1
+22	1	1
+186	1	1
+34	1	1
+264	1	0
+185	1	1
+24	1	0
+98	0	2
+258	8	14
+967	1	1
+37	3	3
+502	1	1
+22	1	1
+75	0	3
+163	1	1
+40	1	1
+638	0	3
+150	1	1
+11	0	1
+29	1	1
+125	1	1
+78	1	1
+115	8	0
+195	14	14
+1413	18	19
+1471	1	1
+30	1	1
+228	1	1
+28	0	2
+1142	1	1
+73	1	1
+104	73	73
+435	1	1
+37	1	3
+601	1	1
+43	1	1
+181	14	0
+37	1	0
+52	1	1
+125	4	4
+34	1	1
+208	1	1
+39	2	2
+418	1	1
+25	1	1
+81	1	1
+36	1	1
+99	6	7
+20	1	1
+73	1	1
+62	1	1
+103	1	1
+34	1	1
+772	0	1
+369	1	1
+29	0	2
+220	1	1
+89	1	1
+58	2	2
+103	1	1
+55	1	1
+19	1	1
+79	1	1
+29	0	1
+26	1	1
+252	1	1
+75	1	1
+467	1	1
+40	1	1
+389	13	13
+67	7	7
+1185	0	311
+64	6	6
+667	1	1
+38	1	1
+79	1	0
+517	1	1
+66	1	1
+450	3	0
+1133	12	12
+543	2	0
+960	14	14
+272	1	1
+41	1	1
+196	1	0
+1424	18	19
+271	1	1
+65	1	1
+345	1	1
+23	3	0
+116	3	3
+86	1	1
+39	1	1
+129	1	1
+26	1	1
+779	1	1
+32	1	1
+247	1	1
+48	1	1
+379	1	1
+18	1	1
+379	1	0
+226	1	1
+61	1	1
+861	0	1
+51	9	9
+397	1	1
+12	4	0
+46	1	1
+602	1	1
+35	1	1
+422	1	1
+49	1	1
+789	1	1
+37	1	1
+859	8	8
+378	0	4
+703	0	4
+2277	3	0
+1334	1	1
+10	0	1
+38	2	0
+61	1	1
+140	15	15
+1047	1	1
+38	1	1
+87	1	1
+24	5	4
+1291	1	1
+49	1	1
+307	14	14
+100	0	1
+75	1	1
+78	1	1
+243	1	0
+33	1	1
+116	19	19
+65	0	1
+238	0	1
+179	2	1
+67	1	1
+60	1	1
+32	1	1
+677	4	6
+83	318	0
+334	1	0
+1018	5	5
+559	0	2
+111	1	1
+30	1	1
+66	1	1
+38	1	1
+218	8	8
+754	1	1
+65	1	1
+182	1	1
+21	1	1
+285	1	1
+75	1	1
+147	6	0
+65	1	1
+42	1	1
+380	1	1
+84	6	0
+88	1	1
+25	1	1
+365	6	5
+108	1	1
+40	1	0
+50	1	1
+111	1	0
+21	0	1066
+119	0	1
+2641	1	1
+22	1	1
+2147	1	1
+29	1	1
+2252	1	1
+19	1	1
+1650	6	6
+1982	0	2
+2213	23	1
+2593	0	177
+338	1	1
+37	2	2
+395	10	0
+67	1	1
+131	1	1
+31	1	1
+386	1	1
+42	1	1
+372	1	1
+48	1	1
+3858	0	1
+351	1	0
+2536	16	16
+253	1	1
+16	1	1
+308	3	3
+52	1	1
+1308	0	3
+330	9	9
+600	2	0
+261	8	8
+9909	0	2
+2337	2	0
+3769	1	0
+1505	0	1
+4327	1	1
+15	1	1
+241	0	1
+230	1	0
+5263	1	0
+1386	0	41
+119	1	0
+4323	0	1
+54	1	1
+116	0	4
+1354	1	0
+1161	20	21
+1946	0	1
+584	0	2
+3100	1	0
+3491	1	0
+461	1	0
+762	0	8
+14669	1	0
+7644	6	0
+10539	4	0
+24841	1	0
+4856	3	0
+6082	2	0
+955	0	2
+1622	20422	20421
+76	0	3
+1724	2	0
+1173	1	0
+1783	1	1
+41	1	1
+4618	1	0
+232	0	2
+4975	2	0
+1487	15	14
+1184	2	0
+342	16	15
+328	0	3
+570	1	0
+995	1	0
+192	4	4
+1434	4	0
+62	1	1
+3531	2	3
+2846	1	1
+17	1	1
+704	0	1
+4801	1	0
+1417	0	4
+50	3	0
+165	0	1
+7575	9	0
+7359	11	0
+14219	0	2
+50	24	10
+38	2	0
+42	0	24
+24	0	18
+8297	1	1
+28	1	1
+264	1	1
+65	0	1
+15	1	1
+2371	19	19
+57	1	1
+21	1	1
+231	1	1
+94	1	1
+105	1	1
+208	5	5
+124	1	1
+112	3	3
+207	40	40
+244	1	1
+60	1	1
+98	1	1
+50	1	1
+256	5	5
+23	1	1
+157	1	1
+33	1	1
+143	1	1
+59	1	1
+51	1	1
+45	1	0
+73	1	1
+81	1	1
+427	1	1
+115	1	1
+28630	0	8
+18331	0	26
+1830	22668	22667
+16645	4	0
+4458	0	2
+2318	1	1
+24	1	1
+2089	0	1
+68717	1	0
+8718	4	0
+12333	12	0
+835	0	1
+391	58	61
+12157	1	0
+5577	1	0
+23151	3	0
+1588	1	0
+2605	1	1
+23	1	1
+11252	8	0
+298	6	7
+946	2	0
+232	0	1
+501	1	0
+4748	0	4
+770	0	7
+914	0	1
+295	1	0
+214	2	0
+121	0	1
+784	0	1
+2512	0	1
+1205	21	21
+3250	1	0
+926	0	1
+189	2	0
+3543	2	0
+893	1	1
+46	1	1
+1296	0	1
+153	0	2
+335	5	0
+187	1	1
+86	1	1
+207	3	0
+322	0	1
+658	1	0
+1516	3	0
+1025	0	13
+1518	0	1
+591	10	10
+3384	0	2
+182	12	0
+328	1	0
+301	0	1
+994	1	1
+18	0	6
+1743	0	1
+2350	22	23
+1548	0	7
+1976	1	0
+199	0	1
+3290	1	1
+28	1	1
+2602	12	12
+873	0	3
+3080	12	8
+322	1	0
+490	1	0
+4084	1	0
+2421
+
+chain	584308	chr6_dbb_hap3	4610396	+	3832023	3871403	chr5	180857866	-	25428915	25436336	9077
+107	1	1
+69	1	1
+306	1	1
+71	1	1
+121	1	1
+88	1	1
+96	12	1
+257	1	1
+92	32139	188
+68	1	0
+39	1	1
+136	4	4
+14	1	1
+82	1	1
+80	1	1
+217	1	1
+28	0	4
+34	1	1
+114	1	1
+29	2	2
+1703	4	4
+315	13	13
+184	1	1
+31	1	1
+789	1	1
+47	5	5
+415	8	8
+85	13	13
+985	1	1
+142	1	1
+205	1	1
+35	1	1
+174
+
+chain	148040	chr6_dbb_hap3	4610396	+	3896754	3898327	chr9	140273252	+	114315581	114318014	872071
+803	1	1
+32	0	453
+67	2	409
+668
+
+chain	80965	chr6_dbb_hap3	4610396	+	2305865	2306722	chr6	170899992	-	139781917	139782778	1559016
+341	0	4
+516
+
+chain	59035	chr6_dbb_hap3	4610396	+	3814253	3815703	chr1	247249719	+	235898881	235900160	2133080
+173	33	33
+70	99	102
+68	14	14
+66	427	253
+104	96	96
+78	80	80
+142
+
+chain	56303	chr6_dbb_hap3	4610396	+	3895098	3898571	chr8	146274826	-	53671532	53672205	16841
+99	13	14
+38	12	0
+6	3	15
+341	2802	1
+101	1	1
+57
+
+chain	51533	chr6_dbb_hap3	4610396	+	2519888	2521822	chr1	247249719	+	7396445	7398379	2460894
+102	170	170
+98	761	760
+135	79	79
+58	214	214
+173	73	74
+71
+
+chain	35778	chr6_dbb_hap3	4610396	+	1195644	1199573	chr6	170899992	+	29950082	29959351	3739128
+53	1042	1027
+90	511	191
+90	460	6138
+153	336	337
+77	683	679
+78	267	267
+89
+
+chain	29930	chr6_dbb_hap3	4610396	+	1291857	1292168	chr10	135374737	+	129836562	129836873	4701711
+311
+
+chain	29904	chr6_dbb_hap3	4610396	+	1119153	1119465	chr7	158821424	+	38479558	38479870	4710596
+312
+
+chain	29422	chr6_dbb_hap3	4610396	+	2048496	2048802	chr6	170899992	+	69396184	69396490	4710630
+306
+
+chain	29265	chr6_dbb_hap3	4610396	+	2582091	2582592	chr2	242951149	+	112146990	112147493	4980566
+65	94	96
+54	27	27
+152	33	33
+76
+
+chain	28976	chr6_dbb_hap3	4610396	+	4055704	4056006	chr2	242951149	-	177193633	177193935	5141771
+302
+
+chain	28679	chr6_dbb_hap3	4610396	+	2275002	2275314	chr3	199501827	-	86469460	86469765	4692119
+171	7	0
+134
+
+chain	26875	chr6_dbb_hap3	4610396	+	2605062	2605840	chr6	170899992	+	31342625	31343398	6110200
+75	247	243
+74	12	16
+72	194	189
+104
+
+chain	23264	chr6_dbb_hap3	4610396	+	3891437	3892382	chr6	170899992	+	32821586	32822354	8135396
+218	677	500
+50
+
+chain	23054	chr6_dbb_hap3	4610396	+	3970815	3971054	chr3	199501827	-	39984613	39984852	8258949
+239
+
+chain	22312	chr6_dbb_hap3	4610396	+	1158170	1158946	chr7	158821424	-	51137320	51138262	8787332
+90	9	9
+79	101	101
+72	385	551
+40
+
+chain	21919	chr6_dbb_hap3	4610396	+	3896060	3896302	chrX	154913754	-	82335943	82336185	9052373
+242
+
+chain	19800	chr6_dbb_hap3	4610396	+	3895610	3895845	chr7	158821424	-	34919795	34920030	7485763
+5	1	1
+87	3	3
+71	1	1
+67
+
+chain	19015	chr6_dbb_hap3	4610396	+	3943955	3944187	chr11	134452384	+	111558067	111558299	11259777
+149	20	20
+63
+
+chain	18237	chr6_dbb_hap3	4610396	+	2595793	2596391	chr13	114142980	+	51183720	51184326	11909510
+52	119	119
+108	253	261
+66
+
+chain	17641	chr6_dbb_hap3	4610396	+	3836782	3837025	chrX	154913754	+	35042287	35042530	12436913
+99	43	43
+101
+
+chain	17270	chr6_dbb_hap3	4610396	+	3918499	3918707	chr10	135374737	-	70196080	70196288	12781659
+86	2	2
+48	5	5
+67
+
+chain	16865	chr6_dbb_hap3	4610396	+	3983463	3983966	chrX	154913754	+	8861421	8861925	13172813
+68	216	217
+63	77	77
+79
+
+chain	16634	chr6_dbb_hap3	4610396	+	3895901	3896503	chr2	242951149	+	35312811	35313413	7601022
+134	363	363
+105
+
+chain	13803	chr6_dbb_hap3	4610396	+	3796429	3796972	chr2	242951149	-	211383777	211384322	16433564
+114	376	378
+53
+
+chain	13479	chr6_dbb_hap3	4610396	+	1132829	1133547	chr6	170899992	+	29984509	29985227	16848878
+104	552	552
+62
+
+chain	13400	chr6_dbb_hap3	4610396	+	3837061	3837652	chr1	247249719	+	76199329	76199914	13528533
+72	466	460
+53
+
+chain	13024	chr6_dbb_hap3	4610396	+	983805	983941	chr11	134452384	-	45905925	45906061	17454496
+136
+
+chain	12671	chr6_dbb_hap3	4610396	+	3940526	3940660	chrX	154913754	-	65797896	65798030	17982412
+134
+
+chain	12198	chr6_dbb_hap3	4610396	+	3795847	3796096	chr7	158821424	+	40936078	40936329	18688113
+94	105	107
+50
+
+chain	11398	chr6_dbb_hap3	4610396	+	2592168	2592321	chr6	170899992	-	161606914	161607067	20013435
+64	22	22
+67
+
+chain	11324	chr6_dbb_hap3	4610396	+	3938144	3938291	chr6	170899992	-	138135992	138136139	20148164
+68	15	15
+64
+
+chain	10873	chr6_dbb_hap3	4610396	+	1193470	1193591	chr19	63811651	+	15986631	15986752	20965589
+121
+
+chain	10867	chr6_dbb_hap3	4610396	+	2527311	2527468	chr6	170899992	-	132294381	132294544	20980273
+55	29	35
+73
+
+chain	10755	chr6_dbb_hap3	4610396	+	2751799	2751912	chrX	154913754	-	134479310	134479423	11323978
+113
+
+chain	10634	chr6_dbb_hap3	4610396	+	3919991	3920105	chr5	180857866	+	34801263	34801377	21438493
+114
+
+chain	10332	chr6_dbb_hap3	4610396	+	3984189	3984438	chr18	76117153	-	27021129	27021380	22068171
+57	124	126
+68
+
+chain	10015	chr6_dbb_hap3	4610396	+	3921148	3921283	chr14	106368585	+	84133812	84133947	22772205
+59	19	19
+57
+
+chain	9987	chr6_dbb_hap3	4610396	+	3796659	3796919	chr12	132349534	+	56701652	56701911	19406222
+70	165	164
+25
+
+chain	9750	chr6_dbb_hap3	4610396	+	2598300	2598402	chr6	170899992	+	31328563	31328665	23393690
+102
+
+chain	9528	chr6_dbb_hap3	4610396	+	1160418	1160855	chr6	170899992	+	29878108	29878543	23937745
+59	318	316
+60
+
+chain	9496	chr6_dbb_hap3	4610396	+	3698327	3698427	chr11	134452384	-	102104468	102104568	24009659
+100
+
+chain	9090	chr6_dbb_hap3	4610396	+	2526557	2526667	chr3	199501827	-	94209663	94209773	24799755
+53	4	4
+53
+
+chain	9042	chr6_dbb_hap3	4610396	+	3982887	3983463	chrX	154913754	-	39105241	39105605	22912000
+59	507	295
+10
+
+chain	8509	chr6_dbb_hap3	4610396	+	3919900	3919991	chr9	140273252	-	54900636	54900727	21580039
+91
+
+chain	7414	chr6_dbb_hap3	4610396	+	3922665	3922744	chr6	170899992	-	151548315	151548394	27385131
+79
+
+chain	7276	chr6_dbb_hap3	4610396	+	3860392	3860468	chr6	170899992	-	67344251	67344327	27653182
+76
+
+chain	7202	chr6_dbb_hap3	4610396	+	3830969	3832020	chr3	199501827	+	106790123	106791174	346924
+69	5	5
+109	2	2
+142	1	1
+77	1	1
+51	1	0
+194	0	1
+399
+
+chain	6804	chr6_dbb_hap3	4610396	+	3735469	3735541	chr6	170899992	+	32582474	32582546	28581342
+72
+
+chain	6776	chr6_dbb_hap3	4610396	+	3900841	3908708	chr6	170899992	+	32827127	32834907	28655646
+50	4318	3617
+61	2532	2695
+93	658	1109
+155
+
+chain	6739	chr6_dbb_hap3	4610396	+	3920547	3920617	chr6	170899992	+	53525586	53525656	28727012
+70
+
+chain	6718	chr6_dbb_hap3	4610396	+	3983858	3984010	chr15	100338915	-	66378648	66378800	16209113
+29	79	79
+44
+
+chain	6712	chr6_dbb_hap3	4610396	+	2536742	2536812	chr6	170899992	-	140565854	140565924	28801697
+70
+
+chain	6657	chr6_dbb_hap3	4610396	+	3814584	3815561	chr4	191273063	-	103136563	103137365	2286737
+44	251	76
+51	551	551
+20	37	37
+23
+
+chain	6566	chr6_dbb_hap3	4610396	+	1190938	1191006	chr6	170899992	+	30567038	30567106	29137401
+68
+
+chain	6566	chr6_dbb_hap3	4610396	+	3835601	3835669	chr6	170899992	+	32665461	32665529	29137402
+68
+
+chain	6459	chr6_dbb_hap3	4610396	+	3795625	3795694	chr11	134452384	+	89638894	89638963	29378141
+69
+
+chain	6457	chr6_dbb_hap3	4610396	+	1205138	1205205	chr6	170899992	+	30336816	30336883	29393793
+67
+
+chain	6404	chr6_dbb_hap3	4610396	+	3984475	3984543	chr7	158821424	+	141217888	141217956	29535627
+68
+
+chain	6112	chr6_dbb_hap3	4610396	+	3700406	3700470	chr18	76117153	-	19156586	19156650	30278938
+64
+
+chain	6077	chr6_dbb_hap3	4610396	+	3828852	3828917	chr6	170899992	+	32661358	32661423	30333820
+65
+
+chain	6003	chr6_dbb_hap3	4610396	+	2599299	2599362	chr6	170899992	+	31329552	31329615	30561641
+63
+
+chain	5676	chr6_dbb_hap3	4610396	+	2522554	2523018	chr1	247249719	+	71360098	71360557	7933597
+8	394	389
+62
+
+chain	5420	chr6_dbb_hap3	4610396	+	1191387	1191443	chr6	170899992	+	29965652	29965708	32189291
+56
+
+chain	5384	chr6_dbb_hap3	4610396	+	3920366	3920422	chr5	180857866	+	130110350	130110406	32314816
+56
+
+chain	5365	chr6_dbb_hap3	4610396	+	1189212	1189267	chr6	170899992	+	30335396	30335451	32370613
+55
+
+chain	5349	chr6_dbb_hap3	4610396	+	1146055	1146112	chr1	247249719	+	172045890	172045947	32394662
+57
+
+chain	5348	chr6_dbb_hap3	4610396	+	3704305	3704361	chr13	114142980	-	61076835	61076891	32406029
+56
+
+chain	5312	chr6_dbb_hap3	4610396	+	3955463	3955519	chr2	242951149	-	134958526	134958582	32494768
+56
+
+chain	5202	chr6_dbb_hap3	4610396	+	3920808	3920862	chr12	132349534	+	102926992	102927046	32856661
+54
+
+chain	5194	chr6_dbb_hap3	4610396	+	2522678	2522733	chr2	242951149	+	136412357	136412412	32870828
+55
+
+chain	5157	chr6_dbb_hap3	4610396	+	3919474	3919528	chr18	76117153	-	75578306	75578360	33003263
+54
+
+chain	5129	chr6_dbb_hap3	4610396	+	3699000	3699053	chr5	180857866	+	132341386	132341439	33069683
+53
+
+chain	5112	chr6_dbb_hap3	4610396	+	3702291	3702345	chr21	46944323	-	8455162	8455216	33113520
+54
+
+chain	5085	chr6_dbb_hap3	4610396	+	3943091	3943145	chrX	154913754	-	38541067	38541121	33235366
+54
+
+chain	5066	chr6_dbb_hap3	4610396	+	1193375	1193428	chr21	46944323	-	1867343	1867396	33290795
+53
+
+chain	5058	chr6_dbb_hap3	4610396	+	3934514	3934568	chr11	134452384	+	35678810	35678864	33301897
+54
+
+chain	4994	chr6_dbb_hap3	4610396	+	3795260	3795313	chr12	132349534	+	29061661	29061714	33541955
+53
+
+chain	4994	chr6_dbb_hap3	4610396	+	3796133	3796186	chr4	191273063	+	58121526	58121579	33542099
+53
+
+chain	4976	chr6_dbb_hap3	4610396	+	3794848	3794901	chrX	154913754	-	55960756	55960809	33594824
+53
+
+chain	4966	chr6_dbb_hap3	4610396	+	3797697	3797749	chr2	242951149	-	82237285	82237337	33630342
+52
+
+chain	4930	chr6_dbb_hap3	4610396	+	3702504	3702556	chr9	140273252	+	93086155	93086207	33718599
+52
+
+chain	4923	chr6_dbb_hap3	4610396	+	1158348	1158410	chr9	140273252	-	102391777	102391839	11227004
+62
+
+chain	4922	chr6_dbb_hap3	4610396	+	3834682	3834735	chr6	170899992	+	32548301	32548354	33750858
+53
+
+chain	4921	chr6_dbb_hap3	4610396	+	3919158	3919210	chrX	154913754	-	85139489	85139541	33755277
+52
+
+chain	4914	chr6_dbb_hap3	4610396	+	2519587	2519639	chrX	154913754	+	7895883	7895935	17698100
+52
+
+chain	4895	chr6_dbb_hap3	4610396	+	3971054	3971105	chr9	140273252	+	7362065	7362116	8474619
+51
+
+chain	4839	chr6_dbb_hap3	4610396	+	2523181	2523232	chr1	247249719	-	83322643	83322694	34042185
+51
+
+chain	4829	chr6_dbb_hap3	4610396	+	1205662	1205712	chr6	170899992	+	30567298	30567348	34088050
+50
+
+chain	4821	chr6_dbb_hap3	4610396	+	3921606	3921657	chr19	63811651	+	44797095	44797146	34119671
+51
+
+chain	4821	chr6_dbb_hap3	4610396	+	3795725	3795776	chr6	170899992	-	89445109	89445160	34121660
+51
+
+chain	4812	chr6_dbb_hap3	4610396	+	3797020	3797071	chr9	140273252	-	60383600	60383651	34150921
+51
+
+chain	4802	chr6_dbb_hap3	4610396	+	3704401	3704451	chr4	191273063	-	155219143	155219193	34221295
+50
+
+chain	4766	chr6_dbb_hap3	4610396	+	3700117	3700167	chr9	140273252	+	86874856	86874906	34319112
+50
+
+chain	4694	chr6_dbb_hap3	4610396	+	3910535	3910585	chr6	170899992	+	32836714	32836764	34581613
+50
+
+chain	4630	chr6_dbb_hap3	4610396	+	2519306	2519455	chrX	154913754	-	130647735	130647884	4467919
+8	13	13
+128
+
+chain	4435	chr6_dbb_hap3	4610396	+	2521889	2521945	chr1	247249719	+	68329905	68329961	24341076
+56
+
+chain	4406	chr6_dbb_hap3	4610396	+	3836685	3836748	chr12	132349534	+	83019068	83019131	17889506
+63
+
+chain	4295	chr6_dbb_hap3	4610396	+	2518454	2518508	chr13	114142980	+	40947099	40947153	23509760
+54
+
+chain	4259	chr6_dbb_hap3	4610396	+	2520658	2522182	chr1	247249719	+	175639486	175641011	2690506
+58	695	694
+59	250	251
+31	373	374
+58
+
+chain	4202	chr6_dbb_hap3	4610396	+	2519814	2519869	chr3	199501827	+	157792092	157792147	19123443
+55
+
+chain	4148	chr6_dbb_hap3	4610396	+	2596230	2596277	chr7	158821424	-	75232531	75232578	15855534
+47
+
+chain	3884	chr6_dbb_hap3	4610396	+	2596391	2596432	chr8	146274826	+	74136425	74136466	15736555
+41
+
+chain	3783	chr6_dbb_hap3	4610396	+	2595924	2595964	chr2	242951149	-	166645324	166645364	18114608
+40
+
+chain	3633	chr6_dbb_hap3	4610396	+	2595546	2596150	chr14	106368585	-	51104394	51104979	12640292
+71	478	459
+55
+
+chain	3600	chr6_dbb_hap3	4610396	+	3984599	3984637	chr2	242951149	+	129304609	129304647	25766382
+38
+
+chain	3466	chr6_dbb_hap3	4610396	+	3944209	3944269	chr5	180857866	-	165236686	165236746	13055377
+60
+
+chain	3427	chr6_dbb_hap3	4610396	+	2595867	2595923	chrX	154913754	-	74451128	74451184	24425971
+56
+
+chain	3366	chr6_dbb_hap3	4610396	+	3697430	3697469	chr7	158821424	-	31427441	31427480	35195573
+39
+
+chain	3356	chr6_dbb_hap3	4610396	+	2596277	2596325	chr6	170899992	+	67193869	67193917	14667051
+48
+
+chain	3333	chr6_dbb_hap3	4610396	+	3796616	3796658	chr6	170899992	+	112361298	112361340	25801948
+42
+
+chain	3275	chr6_dbb_hap3	4610396	+	1138782	1138817	chr6	170899992	+	29990315	29990350	35226052
+35
+
+chain	3219	chr6_dbb_hap3	4610396	+	2595512	2595546	chr15	100338915	+	54012038	54012072	22943633
+34
+
+chain	3113	chr6_dbb_hap3	4610396	+	2519060	2522554	chr12	132349534	+	103307685	103311177	2899166
+99	961	960
+40	1029	1028
+44	1259	1259
+62
+
+chain	2845	chr6_dbb_hap3	4610396	+	2519030	2519060	chr3	199501827	-	158108130	158108160	26771667
+30
+
+chain	2771	chr6_dbb_hap3	4610396	+	2186148	2186180	chr16	88827254	+	61371572	61371604	11881974
+32
+
+chain	2656	chr6_dbb_hap3	4610396	+	3920105	3920152	chr1	247249719	+	97086811	97086858	21929674
+47
+
+chain	2634	chr6_dbb_hap3	4610396	+	3702345	3702373	chr4	191273063	-	9754971	9754999	34558482
+28
+
+chain	2599	chr6_dbb_hap3	4610396	+	1158410	1158448	chr7	158821424	-	126060947	126060985	11258553
+38
+
+chain	2560	chr6_dbb_hap3	4610396	+	3796543	3796570	chr9	140273252	+	82550760	82550787	23127746
+27
+
+chain	2433	chr6_dbb_hap3	4610396	+	3814163	3814213	chr5	180857866	-	58683848	58683898	14264874
+50
+
+chain	2422	chr6_dbb_hap3	4610396	+	3815331	3815377	chr6	170899992	+	32052376	32052422	9201222
+46
+
+chain	2386	chr6_dbb_hap3	4610396	+	3944336	3944393	chr4	191273063	+	105171966	105172023	11828581
+57
+
+chain	2350	chr6_dbb_hap3	4610396	+	1144323	1144351	chr9	140273252	+	98495373	98495401	22648902
+28
+
+chain	2334	chr6_dbb_hap3	4610396	+	1197501	1197553	chr1	247249719	+	48751712	48751764	24363112
+52
+
+chain	2326	chr6_dbb_hap3	4610396	+	3944285	3944315	chr5	180857866	-	104226614	104226644	17910212
+30
+
+chain	2262	chr6_dbb_hap3	4610396	+	1158146	1158170	chr19	63811651	-	5696072	5696096	21221760
+24
+
+chain	2258	chr6_dbb_hap3	4610396	+	2582592	2582621	chr10	135374737	-	49445077	49445106	7325456
+29
+
+chain	2252	chr6_dbb_hap3	4610396	+	3944437	3944463	chr1	247249719	-	9396437	9396463	17746619
+26
+
+chain	2238	chr6_dbb_hap3	4610396	+	3984543	3984572	chr8	146274826	+	40415013	40415042	30916283
+1	3	0
+5	0	3
+20
+
+chain	2198	chr6_dbb_hap3	4610396	+	3591295	3591318	chrX	154913754	-	138619630	138619653	32682302
+23
+
+chain	2171	chr6_dbb_hap3	4610396	+	3944636	3944659	chr5	180857866	-	116975655	116975678	23231315
+23
+
+chain	2164	chr6_dbb_hap3	4610396	+	2581904	2581960	chr15	100338915	+	41094361	41094417	6236685
+56
+
+chain	2136	chr6_dbb_hap3	4610396	+	2582305	2582331	chrX	154913754	+	74544454	74544480	5553867
+24	1	1
+1
+
+chain	2131	chr6_dbb_hap3	4610396	+	3895846	3896559	chr7	158821424	+	107074762	107075475	8294701
+30	628	628
+55
+
+chain	2073	chr6_dbb_hap3	4610396	+	1158564	1158618	chr1	247249719	+	222604152	222604206	12884992
+54
+
+chain	2063	chr6_dbb_hap3	4610396	+	2527468	2527490	chr10	135374737	+	5170837	5170859	26024714
+22
+
+chain	2035	chr6_dbb_hap3	4610396	+	3944660	3944732	chr8	146274826	+	40414891	40414930	35524999
+20	2	0
+3	8	0
+5	23	0
+11
+
+chain	1939	chr6_dbb_hap3	4610396	+	1197585	1197647	chr4_random	842648	+	579429	579491	24056746
+62
+
+chain	1911	chr6_dbb_hap3	4610396	+	3796202	3796275	chr20	62435964	-	40308436	40308509	20356789
+73
+
+chain	1856	chr6_dbb_hap3	4610396	+	1158521	1158554	chr4	191273063	+	153905795	153905828	9266240
+33
+
+chain	1843	chr6_dbb_hap3	4610396	+	2520547	2520624	chr3	199501827	-	153335243	153335320	2775919
+77
+
+chain	1791	chr6_dbb_hap3	4610396	+	3814944	3814997	chr2	242951149	+	15669060	15669113	2773805
+53
+
+chain	1791	chr6_dbb_hap3	4610396	+	3896327	3896371	chr3	199501827	-	21590873	21590917	16297046
+44
+
+chain	1748	chr6_dbb_hap3	4610396	+	3896647	3898412	chr12	132349534	+	37486950	37487098	8651766
+20	2	0
+53	1616	1
+74
+
+chain	1729	chr6_dbb_hap3	4610396	+	2592021	2592074	chr14	106368585	-	49465840	49465893	23309002
+53
+
+chain	1667	chr6_dbb_hap3	4610396	+	2519690	2519769	chr4	191273063	+	150810923	150811002	4477040
+79
+
+chain	1644	chr6_dbb_hap3	4610396	+	3795469	3795533	chr5	180857866	-	17624826	17624890	19426880
+64
+
+chain	1588	chr6_dbb_hap3	4610396	+	2519256	2520761	chr7	158821424	+	116147190	116148689	3019444
+50	1410	1404
+45
+
+chain	1514	chr6_dbb_hap3	4610396	+	1158618	1158676	chr13	114142980	-	5380936	5380994	10250152
+58
+
+chain	1507	chr6_dbb_hap3	4610396	+	2519507	2519587	chr4	191273063	+	139055274	139055354	16166689
+80
+
+chain	1497	chr6_dbb_hap3	4610396	+	2596436	2596504	chr13	114142980	-	63160902	63160970	14379683
+68
+
+chain	1378	chr6_dbb_hap3	4610396	+	2518320	2518446	chr9	140273252	+	106017756	106017882	9913209
+126
+
+chain	1359	chr6_dbb_hap3	4610396	+	1158766	1158832	chr11	134452384	+	118435255	118435321	13536573
+66
+
+chain	1326	chr6_dbb_hap3	4610396	+	2518769	2518884	chr2	242951149	-	193553846	193553961	4392729
+115
+
+chain	1279	chr6_dbb_hap3	4610396	+	3895876	3895901	chr5	180857866	-	141473608	141473633	7934834
+25
+
+chain	1261	chr6_dbb_hap3	4610396	+	2595748	2595793	chr7	158821424	-	113148258	113148303	12073479
+45
+
+chain	1252	chr6_dbb_hap3	4610396	+	3944555	3944605	chr10	135374737	+	81711914	81711964	14060366
+50
+
+chain	1247	chr6_dbb_hap3	4610396	+	3837297	3837358	chrY	57772954	+	10103368	10103429	19375318
+61
+
+chain	1238	chr6_dbb_hap3	4610396	+	1193115	1193174	chr8	146274826	-	84904941	84905000	22834115
+59
+
+chain	1229	chr6_dbb_hap3	4610396	+	3797090	3797164	chr7	158821424	-	63976160	63976234	19674520
+74
+
+chain	1211	chr6_dbb_hap3	4610396	+	2596569	2596648	chr11	134452384	+	125240934	125241013	21730841
+79
+
+chain	1198	chr6_dbb_hap3	4610396	+	3983120	3983171	chrX	154913754	-	112657474	112657525	22999394
+51
+
+chain	1198	chr6_dbb_hap3	4610396	+	2520259	2520315	chr1	247249719	-	41799264	41799320	23684518
+56
+
+chain	1160	chr6_dbb_hap3	4610396	+	2522055	2522083	chrX	154913754	+	56853117	56853145	21155197
+28
+
+chain	1156	chr6_dbb_hap3	4610396	+	3814529	3814567	chr1	247249719	-	95427068	95427106	3236426
+38
+
+chain	1115	chr6_dbb_hap3	4610396	+	2519770	2519814	chr17	78774742	-	18978582	18978626	19145840
+44
+
+chain	1092	chr6_dbb_hap3	4610396	+	3815720	3815773	chr6	170899992	+	33136473	33136526	4404150
+53
+
+chain	1080	chr6_dbb_hap3	4610396	+	3982965	3983026	chr4	191273063	+	91007246	91007307	23248893
+61
+
+chain	1070	chr6_dbb_hap3	4610396	+	3983531	3983571	chr13	114142980	+	78421238	78421278	18216872
+40
+
+chain	1033	chr6_dbb_hap3	4610396	+	3797495	3797589	chr2	242951149	-	222175668	222175762	18472154
+94
+
+chain	1021	chr6_dbb_hap3	4610396	+	3944605	3944636	chr3	199501827	+	41781985	41782016	21488147
+31
+
+chain	961	chr6_dbb_hap3	4610396	+	2591988	2592021	chr6	170899992	+	31311499	31311532	23940424
+33
+
+chain	912	chr6_dbb_hap3	4610396	+	2522218	2522277	chr5	180857866	-	20904100	20904159	3597825
+59
+
+chain	912	chr6_dbb_hap3	4610396	+	2522435	2522465	chr7	158821424	+	107644178	107644208	21981895
+30
+
+chain	892	chr6_dbb_hap3	4610396	+	3815177	3815203	chr1	247249719	-	223546777	223546803	2552155
+26
+
+chain	886	chr6_dbb_hap3	4610396	+	2518921	2518972	chrX	154913754	-	65002049	65002100	8335918
+51
+
+chain	881	chr6_dbb_hap3	4610396	+	2521831	2521881	chr4	191273063	+	5547185	5547235	3823174
+50
+
+chain	876	chr6_dbb_hap3	4610396	+	2522095	2522124	chr1	247249719	-	197271642	197271671	12596899
+29
+
+chain	858	chr6_dbb_hap3	4610396	+	2522184	2522218	chr7	158821424	-	148280259	148280293	6691658
+34
+
+chain	850	chr6_dbb_hap3	4610396	+	3815307	3815331	chr11	134452384	+	75267105	75267129	2466745
+24
+
+chain	846	chr6_dbb_hap3	4610396	+	3896560	3896615	chr1	247249719	-	102242947	102243002	13724822
+55
+
+chain	818	chr6_dbb_hap3	4610396	+	3815047	3815103	chr9	140273252	-	13362556	13362612	11609524
+56
+
+chain	787	chr6_dbb_hap3	4610396	+	2522005	2522055	chr2	242951149	+	76860552	76860602	3963281
+50
+
+chain	742	chr6_dbb_hap3	4610396	+	2520888	2520940	chr10	135374737	+	51611354	51611406	20534291
+52
+
+chain	740	chr6_dbb_hap3	4610396	+	1159052	1159116	chr12	132349534	+	55464534	55464598	20832677
+64
+
+chain	734	chr6_dbb_hap3	4610396	+	2517749	2518673	chr8	146274826	-	112931559	112932176	13565224
+68	769	462
+87
+
+chain	717	chr6_dbb_hap3	4610396	+	3984125	3984177	chr16	88827254	-	38714794	38714846	22849175
+52
+
+chain	688	chr6_dbb_hap3	4610396	+	2519167	2519218	chr12	132349534	-	101137563	101137614	3748471
+51
+
+chain	684	chr6_dbb_hap3	4610396	+	2522743	2522826	chr1	247249719	+	68246247	68246330	16550290
+83
+
+chain	681	chr6_dbb_hap3	4610396	+	3982752	3982809	chr8	146274826	-	64029404	64029461	24731945
+57
+
+chain	668	chr6_dbb_hap3	4610396	+	3714611	3714639	chr13	114142980	+	25366313	25366341	2606938
+28
+
+chain	661	chr6_dbb_hap3	4610396	+	2523098	2523163	chr5	180857866	+	99923773	99923838	9614006
+65
+
+chain	654	chr6_dbb_hap3	4610396	+	1158946	1158972	chr4	191273063	-	137719796	137719822	10317120
+26
+
+chain	638	chr6_dbb_hap3	4610396	+	3795059	3795115	chr1	247249719	-	190736869	190736925	22996754
+56
+
+chain	603	chr6_dbb_hap3	4610396	+	3896371	3896398	chr6	170899992	+	38375889	38375916	7901672
+27
+
+chain	602	chr6_dbb_hap3	4610396	+	2519990	2520031	chr6	170899992	-	100068900	100068941	3263990
+41
+
+chain	571	chr6_dbb_hap3	4610396	+	2518673	2518747	chr3	199501827	+	50931043	50931117	15282719
+74
+
+chain	547	chr6_dbb_hap3	4610396	+	2522845	2522895	chr11	134452384	-	79794459	79794509	15991277
+50
+
+chain	544	chr6_dbb_hap3	4610396	+	2520356	2520407	chr13	114142980	+	104410064	104410115	4879952
+51
+
+chain	461	chr6_dbb_hap3	4610396	+	2522377	2522435	chr9	140273252	-	118104609	118104667	6129577
+58
+
+chain	447	chr6_dbb_hap3	4610396	+	2517845	2517905	chr8	146274826	-	66271750	66271810	23464585
+60
+
+chain	423	chr6_dbb_hap3	4610396	+	2520499	2520535	chr16	88827254	-	23736388	23736424	4641188
+36
+
+chain	407	chr6_dbb_hap3	4610396	+	3833249	3833277	chr11	134452384	+	92791982	92792010	9335
+28
+
+chain	395	chr6_dbb_hap3	4610396	+	3896615	3896647	chr10	135374737	-	43610926	43610958	15449290
+32
+
+chain	363	chr6_dbb_hap3	4610396	+	2522305	2522360	chr2	242951149	+	137419466	137419521	26505689
+55
+
+chain	350	chr6_dbb_hap3	4610396	+	2523417	2523489	chr15	100338915	+	97778900	97778972	9309023
+72
+
+chain	312	chr6_dbb_hap3	4610396	+	2520407	2520446	chr10	135374737	-	80033072	80033111	12533916
+39
+
+chain	290	chr6_dbb_hap3	4610396	+	2523894	2523946	chr1	247249719	-	204952078	204952130	18508597
+52
+
+chain	258	chr6_dbb_hap3	4610396	+	2518973	2519027	chr2	242951149	+	129418481	129418535	12872927
+54
+
+chain	235	chr6_dbb_hap3	4610396	+	3982484	3982540	chr21	46944323	+	15992125	15992181	26051708
+56
+
+chain	337820870	chr6_mann_hap4	4683263	+	0	4683263	chr6	170899992	+	28804582	33333955	39
+932	3	0
+804	0	1
+2406	2	0
+141275	1	0
+429	38391	38391
+17722	4	0
+12815	0	1
+28140	1	3
+12586	0	1
+9819	0	1
+69013	0	1
+22684	1	0
+14147	7	0
+1489	1	1
+72	1	1
+2260	0	2
+7033	0	4
+13929	13	14
+9228	0	1
+1324	0	3
+5437	5	0
+2061	1	0
+3982	6	6
+1725	0	1
+3153	1	0
+18	1	0
+18	1	0
+2026	1	0
+4175	10	10
+4746	9	9
+4767	7	7
+1169	1	1
+55	1	0
+8	1	1
+151	1	2
+5079	1	1
+28	1	1
+249	43	43
+1178	0	4
+685	8	0
+48	8	0
+1701	1	1
+43	5	5
+862	18	18
+58	1	1
+66	1	1
+420	1	1
+44	1	1
+680	4	4
+1675	1	1
+83	1	1
+3082	4	0
+5467	1	1
+27	0	1
+1099	16	0
+627	12	12
+1317	6	1
+129	1	1
+25	1	1
+1397	15	15
+810	1	1
+27	1	1
+1192	2	0
+7515	4	0
+979	0	4
+3405	0	2
+3501	1	1
+26	1	1
+787	0	1
+1416	3	1
+22815	4	4
+126	1	0
+38	1	1
+140	1	0
+999	0	17
+56	0	15
+15438	4	0
+6165	0	1
+1768	1	0
+7727	2	0
+1514	0	1
+3116	0	1
+3278	1	1
+21	1	1
+1738	0	1
+8576	19	0
+1877	15	15
+6128	1	0
+2049	1	0
+518	13	11
+1704	1	1
+117	1	1
+1448	10	0
+1521	0	4
+2878	9	9
+2265	1	0
+25400	9	9
+4420	1	1
+32	1	1
+2539	1	0
+18012	1	1
+42	1	1
+2651	0	3
+2544	0	318
+1507	1	0
+313	4	0
+2659	1	1
+25	1	1
+1461	4	1
+1402	0	1
+3961	0	3
+58	1	1
+112	1	1
+1419	1	1
+34	0	1
+2697	0	2
+40	1	1
+2168	0	1
+1019	0	2
+1099	0	4
+40	1	1
+1374	11	0
+31	1	1
+189	1	1
+26	1	1
+327	1	1
+38	1	1
+177	11	11
+303	1	1
+34	1	1
+5868	17	17
+2864	0	143
+4107	0	4
+752	0	2
+10360	0	1
+37	1	1
+11851	0	2
+5376	0	1
+19253	0	6
+7878	1	0
+21	0	6
+4451	1	0
+27910	1	0
+9946	0	1
+11233	1	1
+32	1	1
+366	1	1
+38	1	1
+1832	1	1
+20	1	1
+3659	22	16
+1218	1	0
+1638	6	6
+228	1	1
+45	1	1
+2048	0	2
+462	1	0
+20759	1	0
+3778	2	1
+1268	1	0
+1511	1	1
+42	2	0
+24	1	1
+4119	22	0
+1757	1	0
+1527	1	1
+29	1	1
+1886	1	0
+6666	0	4
+2358	1	1
+23	1	1
+1549	12	0
+36	12	0
+484	1	1
+31	1	1
+549	3	0
+5745	1	0
+19358	0	3
+12224	1	0
+34	1	1
+3228	11	16
+250	1	1
+17	1	1
+1482	0	1
+1280	1	0
+103	1	1
+29	1	1
+68	4	4
+1493	1	1
+49	1	1
+102	4	0
+287	1	1
+21	3	0
+273	1	1
+43	9	1
+667	0	8
+138	1	1
+20	1	1
+255	0	2
+67	1	1
+33	1	1
+62	1	0
+118	0	5
+313	0	3
+2354	0	28
+1203	0	3
+3975	1	1
+44	1	1
+4899	3	0
+2101	2	0
+363	1	1
+49	1	1
+1639	0	30
+248	46	46
+1068	4	1
+85	1	0
+357	3	4
+5288	0	9
+2728	1	5
+722	0	1
+502	0	1
+1025	0	1
+134	12	0
+4944	0	1
+319	1	0
+1314	5	6
+4858	0	1
+2923	1	3
+117	0	1
+1775	1	0
+2123	0	1
+2715	1	0
+4921	1	1
+17	1	1
+4273	1	0
+1233	0	8
+2134	0	1
+1042	0	1
+163	1	1
+45	1	1
+50	2	0
+64	1	1
+48	1	1
+379	0	3
+29	1	0
+30	1	1
+61	1	1
+22	1	1
+691	5	7
+310	1	1
+37	3	1
+225	1	1
+131	2	0
+36	1	1
+242	9	9
+697	33	33
+1202	1	1
+16	1	1
+528	1	1
+20	1	1
+509	0	5
+76	1	1
+21	1	1
+439	15	15
+2778	2	1
+1597	24	28
+59	12	12
+307	1	0
+516	1	0
+286	11	33
+339	5	0
+570	1	1
+37	1	1
+220	1	0
+72	1	1
+144	1	1
+48	1	1
+247	2	0
+174	9	10
+816	1	0
+940	1	1
+45	1	1
+91	3	3
+71	1	1
+291	14	14
+100	1	1
+23	1	1
+452	3	3
+85	1	1
+65	1	1
+77	1	1
+252	0	1
+129	15	15
+432	14	0
+85	1	1
+28	1	1
+189	2	1
+71	1	1
+52	8	0
+810	2	2
+63	1	1
+378	1	1
+26	1	1
+187	31	36
+966	1	1
+25	1	1
+72	1	1
+29	1	1
+125	1	1
+38	1	1
+433	2	0
+596	1	1
+48	1	1
+465	4	4
+64	1	1
+20	1	1
+525	5	5
+237	3	8
+99	31	31
+53	11	0
+364	4	3
+201	1	1
+42	1	1
+56	1	1
+115	1	0
+67	16	16
+244	1	1
+54	5	5
+929	1	1
+21	1	1
+126	0	3
+830	1	11
+59	1	1
+537	0	2
+24	1	1
+745	15	15
+810	1	0
+425	1	1
+89	1	1
+592	1	1
+49	1	1
+352	0	1
+142	1	1
+30	1	1
+95	1	1
+45	1	1
+227	1	1
+53	1	1
+130	1	1
+18	1	1
+138	1	1
+90	1	1
+129	1	1
+39	1	1
+50	1	1
+79	1	1
+117	1	1
+31	1	1
+155	154	0
+34	1	1
+50	5	5
+57	1	1
+152	1	1
+30	1	1
+177	5	5
+345	1	1
+39	1	1
+504	18	18
+596	12	12
+54	1	1
+158	1	1
+164	1	1
+34	1	1
+626	15	15
+866	0	10
+1051	0	2611
+680	0	1
+1537	0	18
+75	1	0
+145	60	0
+122	0	12
+23	1	1
+1927	13	13
+1702	2	0
+3694	1	1
+18	1	1
+958	43	47
+246	2	0
+146	1	1
+49	1	1
+410	1	0
+667	1	1
+38	1	1
+362	7	1
+159	3	0
+515	2	0
+1026	1	1
+29	1	1
+249	0	6
+129	1	1
+33	4	0
+9	0	6
+1236	1	1
+20	1	1
+138	10	9
+448	0	3
+660	1	1
+28	1	1
+83	1	1
+51	1	1
+2659	1	1
+38	1	1
+424	0	1
+70	1	1
+820	1	1
+26	1	1
+1472	1	1
+21	1	1
+491	5	5
+163	15	15
+2194	2	0
+533	6	0
+441	1	7
+1689	1	1
+26	3	4
+879	16	16
+75	10	10
+429	0	2
+58	1	1
+350	1	0
+769	1	1
+39	1	1
+573	0	4
+37	1	1
+144	8	8
+1036	2	0
+262	2	2
+38	0	1
+70	18	18
+84	11	13
+169	147	153
+1254	0	2
+332	1	1
+21	1	1
+193	8	24
+34	1	1
+79	1	1
+29	1	1
+536	1	0
+308	0	1
+850	0	32
+23	1	1
+651	1	1
+22	0	3
+136	1	1
+48	1	1
+330	9	9
+1108	1	1
+98	1	1
+582	0	1
+714	7	7
+89	1	0
+293	9	8
+125	1	1
+31	1	1
+192	6	6
+171	17	17
+681	1	1
+43	1	1
+514	1	1
+68	1	1
+537	1	1
+35	1	1
+159	6	6
+179	1	1
+37	1	1
+560	17	17
+198	0	7
+105	1	1
+40	1	1
+95	13	13
+247	1	1
+19	1	1
+2044	7	8
+2512	0	15
+2982	4	0
+342	41	41
+2752	1	2
+1698	13	13
+4264	0	4
+12512	105	53
+7	0	5
+29	5	129
+49	1	1
+7717	1	1
+40	1	1
+4564	1	1
+45	1	1
+2289	1	1
+41	1	1
+1994	0	1
+733	1	1
+37	1	1
+5170	1	1
+22	1	1
+718	0	3
+828	0	8
+2128	11	11
+5142	0	1
+4144	18	0
+8	1	1
+4824	12	12
+727	6	16
+1705	4	0
+3265	0	2
+2235	18	16
+2946	0	372
+2644	31	31
+3991	40	40
+559	1	1
+28	1	1
+129	0	4
+787	1	1
+34	1	1
+927	4	4
+123	0	4
+6	1	1
+2353	0	1
+331	1	1
+27	1	1
+633	1	1
+31	1	1
+1147	1	0
+1507	1	1
+44	1	1
+166	1	1
+41	3	1
+1022	34253	40039
+275	1	1
+38	1	1
+1307	1	1
+26	1	1
+1467	1	1
+27	1	1
+568	11	11
+693	1	1
+26	1	1
+297	11	11
+183	1	1
+40	1	1
+589	1	1
+26	1	1
+838	1	1
+44	0	1
+877	1	1
+39	1	1
+347	1	1
+36	1	1
+1288	10	10
+731	2	1
+75	3	3
+91	171	171
+553	1	1
+61	1	1
+70	1	1
+53	0	2
+315	1	1
+29	1	1
+581	1	1
+82	1	1
+605	9	9
+691	2	2
+72	1	1
+55	1	1
+45	1	1
+196	4	4
+123	0	1
+40	1	1
+183	23	23
+183	1	1
+67	1	1
+304	1	1
+108	1	1
+165	1	1
+72	1	1
+167	1	1
+59	0	1
+10	3	1
+21	82	2
+58	0	2
+69	1	1
+25	1	1
+57	2	1
+107	2	2
+93	1	1
+194	0	3
+120	7	4
+431	1	1
+78	1	1
+84	0	1
+74	1	1
+52	13	13
+158	5	7
+434	0	1
+295	16	16
+290	1	1
+26	1	1
+373	1	1
+46	1	1
+94	1	1
+81	1	1
+109	4	0
+61	2	2
+80	1	1
+47	1	1
+168	1	1
+31	1	1
+269	2	2
+42	1	1
+322	2	2
+36	1	1
+265	2	2
+14	1	1
+76	7762	9566
+315	55	55
+67	36167	30035
+308	1	1
+49	1	1
+219	0	1
+87	7	5
+223	10	8
+235	11	11
+772	0	2
+187	2	1
+1058	0	2
+349	0	1
+264	1	1
+43	1	1
+781	3	1
+55	0	2
+13	0	4
+1077	1	1
+48	1	1
+62	1	1
+27	1	1
+1270	1	1
+44	1	1
+2070	3	1
+27	1	7
+251	1	1
+40	1	1
+130	1	1
+41	4	4
+478	1	1
+30	1	1
+162	11	11
+209	10	0
+150	1	1
+36	0	2
+31	1	1
+55	1	1
+51	1	1
+221	8	13
+418	1	1
+26	1	1
+386	3	0
+549	1	1
+76	1	1
+67	1	1
+25	3	3
+777	1	1
+17	1	1
+970	3	8
+714	1	1
+25	1	1
+192	1	1
+236	1	1
+524	0	12
+51	10	9
+664	1	1
+29	1	1
+62	1	1
+50	2	0
+119	1	1
+10	0	2
+19	4	6
+117	1	1
+69	1	1
+731	1	0
+3768	9	1
+1328	0	1
+6188	1	1
+43	1	1
+7157	4	0
+2168	1	0
+10374	19	0
+742	2	3
+4846	0	1
+3203	1	0
+2662	1	1
+27	1	1
+3920	1	1
+47	1	1
+2081	1	0
+377	1	0
+172	0	1
+5189	0	1
+1968	7	0
+3198	1	0
+667	1	0
+3902	17	4
+310	0	5
+2762	0	10
+201	2	0
+345	1	0
+594	0	2
+1043	10	0
+1426	0	9
+17	1	1
+265	0	1
+6069	0	3
+2963	0	3
+168	0	3
+194	2	1
+4260	1	0
+19508	0	1
+1762	0	3
+4356	0	4
+401	1	0
+1148	1	1
+28	0	11
+847	0	1
+1133	0	1
+1143	1	1
+20	1	1
+1533	0	8
+128	0	4
+2963	0	1
+25	1	1
+5336	1	0
+322	6	6
+196	1	1
+20	1	1
+151	3	3
+87	1	1
+246	1	7
+368	1	1
+26	1	1
+1049	0	1
+1002	0	1
+7912	4	0
+3532	50004	0
+1445	0	1
+10485	1	1
+48	1	1
+724	1	1
+51	5	0
+39	1	1
+22385	0	1
+4385	0	7
+881	0	12
+11532	13	12
+409	0	1
+3492	0	2
+2158	0	25
+109	1	1
+3284	0	19
+2586	2	0
+757	1	1
+22	1	1
+860	29	24
+1584	1	0
+1598	1	2
+1653	3	25
+17	0	4
+16	2	0
+6	10	0
+40	1	0
+10	6	0
+6448	0	1
+2513	0	1
+576	16	16
+103	1	0
+198	1	3
+539	1	1
+47	1	1
+158	2	0
+996	0	1
+3736	1	3
+371	1	3
+1174	1	1
+56	1	1
+69	0	1
+518	6	0
+646	13	13
+469	1	0
+1072	1	4
+911	1	1
+16	1	1
+3603	1	0
+282	1	0
+597	0	6
+496	13	13
+183	1	1
+43	1	1
+1294	1	1
+40	1	1
+572	0	5
+463	0	4
+1886	1	0
+548	1	0
+1300	0	3
+1839	2	0
+189	1	1
+49	1	1
+1253	1	1
+43	1	0
+498	1	1
+45	4	0
+3538	0	1
+1582	31	31
+376	14	14
+867	3	4
+253	1	1
+34	1	1
+172	2	0
+1094	0	1
+281	1	1
+49	1	1
+397	1	1
+43	1	1
+1082	1	1
+26	1	1
+1030	1	1
+24	0	419
+125	2	0
+709	1	1
+36	1	1
+393	1	1
+21	1	1
+1773	16	17
+181	12	12
+98	1	4
+6	1	0
+53	1	1
+94	1	1
+49	1	1
+1495	10	0
+623	13	13
+163	1	1
+45	1	1
+2050	11	11
+2452	1	1
+42	1	0
+35	1	1
+751	1	0
+287	1	1
+60	1	1
+446	0	4
+2620	8	7
+1442	5	5
+153	1	0
+514	2	0
+3349	1	1
+23	0	1
+12	1	1
+296	8	9
+291	1	1
+21	1	0
+245	2	2
+24	1	1
+150	1	1
+46	1	1
+325	1	1
+38	1	1
+52	6	9
+154	1	1
+42	1	1
+942	1	1
+36	1	1
+5168	0	3
+2172	1	0
+1740	0	8
+4919	1	0
+1388	4	0
+310	0	9
+370	22	0
+503	0	3
+6750	8	0
+419	2	0
+945	0	4
+3485	5	1
+789	0	1
+1882	45	44
+1047	1	1
+60	1	1
+2432	0	15
+16	1	1
+5898	0	1
+2260	1	0
+2629	0	5
+55	1	1
+28	1	1
+1978	1	0
+374	0	5
+7713	1	0
+1229	1	0
+708	2	0
+84	5	0
+2071	1	1
+23	1	0
+174	5	0
+1776	0	9
+15	6	11
+4007	1	0
+2414	12	10
+2056	0	1
+955	4	0
+9566	1	0
+1267	2	0
+1646	2	2
+30	1	1
+4770	7	6
+150	14	14
+9365	0	2
+5358	0	1
+4837	1	0
+6701	4	0
+66771	0	2
+54634	0	2
+8292	0	4
+7941	0	8
+7495	1	0
+5591	4	0
+4127	1	0
+473	1	0
+6435	1	0
+53744	1	0
+6522	0	1
+48591	18	23
+4935	29	0
+40465	0	1
+12538	0	1
+24928	8701	8701
+6291	0	10
+15586	2	1
+56398	4	0
+5858	1	0
+5972	0	2
+2081	0	1
+12533	1	0
+25305	0	1
+2237	0	2
+18999	0	4
+13824	0	2
+11096	2	0
+10773	0	1
+804	1	0
+5431	31	34
+598	1	1
+22	1	1
+2240	24813	24813
+1765	0	4
+4845	0	3
+448	1	1
+22	1	1
+2215	1	1
+32	1	1
+2413	14	14
+142	1	0
+789	1	1
+45	1	1
+154	1	1
+25	1	1
+465	1	1
+45	6	4
+541	1	1
+42	1	1
+1339	5	6
+391	1	1
+20	0	1
+251	1	1
+22	1	1
+561	0	2
+78	3	0
+1718	1	1
+12	1	1
+1042	1	1
+38	0	1
+301	14	0
+222	10	10
+436	10	10
+1564	1	1
+17	1	1
+1752	5	0
+1561	135	0
+58	0	45
+212	90	0
+42	2	2
+43	1	1
+152	0	270
+54	180	0
+2130	12	12
+1630	1	1
+26	1	1
+189	0	14
+296	2	0
+809	2	0
+17	16	0
+665	0	40
+236	1	1
+44	1	1
+352	1	1
+25	1	1
+316	14442	14257
+51	2	0
+58	1	1
+107	1	1
+150	14	14
+522	1	1
+28	1	1
+945	4	4
+34	1	1
+472	0	2
+203	0	1
+281	1	1
+46	1	1
+1130	1	0
+232	17	17
+510	1	1
+33	1	1
+62	10	10
+1501	1	1
+20	1	1
+573	1	1
+29	1	1
+928	0	3
+304	1	1
+41	1	1
+160	1	1
+58	1	1
+656	1	1
+40	4	0
+108	6	6
+321	1	1
+14	0	16
+91	1	1
+184	1	1
+43	8	3
+180	1	1
+68	1	1
+144	1	1
+27	1	0
+17	1	1
+212	0	1
+212	1	1
+34	1	1
+115	1	1
+41	1	1
+407	10	10
+200	1	1
+44	2	0
+187	3	0
+146	1	1
+17	1	1
+122	4	4
+73	1	0
+56	1	1
+155	1	17
+80	15	15
+458	1	1
+16	3	3
+343	1	1
+111	1	1
+201	14	14
+157	12	12
+346	0	2
+382	4	0
+35	1	1
+937	0	1
+246	25	0
+52	0	1
+419	0	1
+165	1	0
+75	24	3
+297	1	1
+38	1	1
+271	1	1
+33	1	1
+4777	4	2
+43	3	0
+1254	0	1
+16	1	1
+1411	0	4
+424	1	1
+51	1	1
+113	1	1
+34	1	1
+344	9	9
+15845	1	0
+2814	1	5
+2389	0	4
+3883	0	1
+10926	0	4
+17866	4	10
+744	1	0
+564	2	0
+16701	3	0
+7721	11	0
+1411	1	1
+49	1	1
+146	1	1
+61	1	1
+116	1	1
+41	1	1
+137	1	1
+30	1	1
+158	9	9
+136	10	13
+973	6	6
+547	1	1
+41	1	1
+164	17	17
+137	1	1
+68	1	1
+846	4	4
+228	1	1
+34	1	1
+355	1	1
+113	1	1
+330	0	1
+222	1	1
+25	1	1
+267	1	1
+38	1	1
+716	2	0
+23	1	1
+1417	0	1
+152	1	1
+46	1	1
+237	1	1
+20	1	1
+211	5	5
+88	1	1
+33	1	1
+211	1	1
+65	1	1
+516	58	58
+491	7	7
+208	13	12
+558	2	2
+28	1	1
+125	4	4
+1853	12	0
+845	6	6
+2005	0	1
+148	1	1
+36	1	1
+993	1	0
+3580	10	10
+1203	1	0
+530	5	5
+216	1	1
+32	1	1
+312	1	1
+44	1	1
+1934	14	14
+1149	0	8
+835	1	1
+29	0	2
+2323	1	1
+18	1	1
+1273	27	27
+104	1	1
+21	1	1
+1520	1	1
+23	1	1
+147	1	1
+16	1	1
+429	8	16
+1419	23	23
+256	1	0
+39	1	2
+106	1	1
+21	1	1
+501	2	2
+40	1	1
+2249	1	1
+19	1	1
+86	1	1
+82	0	1
+180	14	1
+1272	17	17
+345	0	2
+1504	14	0
+1689	4	0
+3174	16	16
+607	4	34
+41	0	5
+669	1	1
+25	1	1
+1926	1	1
+39	4	3
+1037	1	1
+40	2	0
+890	6	0
+41	2	0
+466	1	1
+31	3	0
+321	0	1
+281	3	0
+450	1	1
+34	1	1
+498	1	1
+28	2	1
+280	0	1
+649	1	1
+47	1	1
+1002	4	0
+120	1	1
+533	7	7
+998	0	1
+75	1	1
+37	1	1
+473	1	0
+44	1	1
+64	19	19
+60	18	18
+2075	1	1
+51	1	1
+779	0	1
+1286	0	2
+271	1	1
+57	1	1
+129	4	0
+87	1	1
+160	1	1
+49	1	1
+147	18	14
+128	4	4
+34	1	1
+865	4	0
+160	1	1
+35	1	1
+1119	1	1
+13	0	3
+242	1	1
+23	1	1
+1705	0	4
+103	0	1
+1117	2	0
+67	1	1
+1825	0	1
+855	8	0
+1368	3	0
+320	1	1
+19	1	1
+100	1	1
+28	1	1
+97	1	1
+15	1	1
+442	1	1
+189	0	2
+5	1	1
+1520	1	1
+28	1	1
+367	4	0
+267	13	13
+175	1	0
+225	1	1
+45	1	1
+859	1	1
+80	2	0
+38	0	2
+318	8	7
+50	1	1
+29	1	1
+376	4	9
+548	1	1
+57	1	1
+665	4	0
+146	30562	30549
+225	2	2
+49	1	1
+129	1	1
+20	1	1
+757	9	9
+151	1	1
+49	1	1
+282	0	2
+128	0	1
+174	15	18
+175	1	1
+16	1	1
+332	1	1
+22	1	1
+554	0	1
+120	1	1
+31	1	1
+351	5	0
+80	1	0
+76	1	1
+39	1	1
+1447	1	0
+1072	1	1
+43	0	4
+43	1	1
+393	0	1
+1820	6	6
+457	1	1
+18	1	1
+87	1	1
+30	1	1
+861	1	1
+20	1	1
+1057	23	23
+416	0	16
+787	1	1
+17	1	2
+37	1	1
+1675	1	1
+27	1	1
+901	0	8
+47	1	1
+274	0	3
+75	0	1
+234	0	3
+45	1	1
+250	1	1
+18	1	1
+517	33	0
+117	1	1
+55	1	1
+537	1	1
+20	1	1
+671	1	1
+68	1	1
+89	1	1
+104	1	1
+172	0	1
+124	0	1
+522	0	1500
+466	5	5
+32	1	0
+171	1	1
+19	1	1
+67	1	1
+22	1	1
+654	1	1
+25	1	1
+68	1	1
+21	4	0
+1588	1	1
+66	1	1
+401	0	1
+186	1	1
+21	1	1
+168	0	1
+601	1	1
+29	1	1
+36	4	0
+37	1	1
+127	1	1
+29	1	1
+404	0	2
+710	1	1
+89	1	1
+161	16	16
+405	1	1
+39	3	3
+56	1	1
+192	0	4
+104	1	1
+89	1	1
+64	1	1
+102	1	1
+130	15	16
+158	8	0
+57	1	1
+731	1	1
+57	1	1
+321	1	1
+44	3	0
+52	19987	20030
+60	8	8
+133	1	1
+48	1	1
+287	1	1
+24	1	1
+1273	1	1
+24	1	1
+86	1	1
+76	1	0
+20	1	1
+112	1	1
+149	1	1
+284	1	1
+37	1	1
+559	10	10
+136	1	12
+106	12	12
+3153	1	1
+34	1	1
+453	1	1
+63	1	1
+645	0	2
+50	1	0
+712	1	1
+35	1	1
+158	1	1
+52	1	1
+123	1	1
+45	0	1
+32	1	1
+253	1	1
+48	1	1
+101	16	16
+64	1	1
+124	1	1
+1429	13	13
+196	0	1
+1629	1	1
+39	0	1
+30	1	1
+514	1	1
+32	0	3
+3600	1	13
+1047	1	1
+43	1	1
+55	14	14
+853	12	12
+2313	13	13
+537	6	0
+1430	1	1
+48	1	1
+400	1	1
+100	1	1
+148	19	19
+152	1	1
+25	1	1
+70	1	1
+102	1	1
+158	1	1
+56	2	2
+57	1	1
+10	5	10
+24	2	0
+71	1	1
+54	1	1
+73	1	1
+85	1	1
+105	1	1
+117	2	2
+29	1	1
+92	2	2
+42	0	1
+154	1	1
+10	1	0
+47	4	5
+35	1	1
+56	1	1
+64	3	3
+67	5	5
+72	1	1
+60	1	1
+45	1	1
+82	1	1
+95	2	2
+161	1	1
+301	1	1
+67	1	0
+430	1	1
+105	10	10
+38	0	4
+386	11	11
+101	3	2
+117	0	2
+77	1	1
+481	0	1
+68	1	1
+81	1	1
+467	1	1
+34	1	1
+359	1	1
+35	1	1
+2283	1	1
+26	1	1
+506	19	0
+51	0	1
+166	1	1
+65	1	0
+211	0	17
+410	3	0
+622	0	1
+143	1	1
+22	1	1
+150	2	2
+49	1	1
+312	1	1
+16	1	1
+715	1	1
+24	1	1
+896	1	1
+33	1	1
+308	22	28
+78	1	1
+144	1	1
+733	0	1
+212	1	1
+40	1	1
+1233	1	1
+48	1	1
+741	49699	50070
+885	1	1
+113	1	1
+141	2	0
+842	1	0
+1507	1	1
+40	1	1
+279	0	1
+724	1	1
+15	1	1
+252	1	1
+29	2	0
+229	1	1
+50	3	3
+221	7	7
+216	1	1
+36	5	5
+64	1	1
+111	1	1
+220	1	1
+89	1	1
+119	1	1
+113	2	0
+195	1	1
+46	1	1
+245	0	4
+70	1	1
+62	4	1
+43	1	1
+153	1	1
+93	1	1
+85	1	1
+68	5	0
+47	2	2
+291	1	0
+42	1	1
+341	13	13
+262	4	4
+67	1	1
+32	1	0
+28	1	1
+612	1	1
+123	1	1
+112	1	1
+19	1	4
+61	1	2
+136	1	1
+83	1	1
+78	1	1
+61	288	288
+119	1	1
+158	1	1
+146	1	1
+28	1	1
+372	1	1
+18	0	4
+44	1	1
+120	7	7
+73	1	4
+42	1	1
+52	1	1
+24	1	1
+143	1	1
+34	1	1
+376	1	1
+26	1	1
+243	1	1
+41	1	1
+53	1	1
+35	5	5
+101	1	1
+20	1	1
+114	1	1
+43	1	1
+184	4	8
+650	23	23
+192	1	1
+44	1	0
+103	1	1
+202	2	2
+33	1	1
+51	1	1
+26	1	1
+277	3	0
+19	1	1
+263	2	2
+49	1	1
+63	1	1
+200	1	1
+320	4	12
+10	2	0
+11	8	1
+26	1	1
+86	13	13
+15	1	1
+3255	1	1
+52	1	1
+159	1	1
+88	1	0
+118	1	1
+172	1	1
+26	1	1
+69	1	1
+95	1	1
+124	1	1
+30	1	1
+216	41	41
+51	5	5
+123	1	1
+53	1	1
+110	1	1
+307	1	1
+101	1	1
+53	15	15
+127	2	2
+65	1	1
+553	1	1
+45	1	1
+52	0	1
+99	4	4
+1538	1	1
+31	1	1
+930	7	3
+472	13	13
+606	1	1
+38	1	1
+230	10	0
+30	6	0
+35	0	22
+168	1	1
+55	1	1
+309	2	3
+58	1	1
+44	1	1
+333	1	1
+81	3	3
+77	1	1
+140	1	1
+136	1	1
+40	5	5
+160	1	1
+21	5	5
+253	1	1
+37	1	1
+104	3	0
+867	14	15
+178	1	1
+94	1	1
+254	0	1
+101	0	5
+17	1	1
+528	1	1
+42	1	1
+261	1	1
+19	3	3
+83	10	10
+114	1	1
+194	1	1
+19	1	1
+286	1	1
+38	1	1
+295	0	4
+35	10	0
+205	0	2
+29	1	1
+178	1	1
+31	1	1
+57	1	1
+76	1	1
+228	1	1
+28	1	1
+101	1	1
+109	0	1
+93	0	2
+46	1	1
+109	1	1
+33	1	1
+932	12	12
+1047	1	1
+26	1	1
+699	0	8
+35	1	1
+472	1	1
+43	1	1
+242	1	1
+28	1	1
+385	1	1
+91	1	1
+805	0	2
+4744	3	2
+1144	0	1
+1453	0	1
+934	1	1
+28	3	7
+155	0	1
+840	18	18
+346	1	1
+25	1	1
+1020	2	0
+260	1	1
+26	1	1
+357	1	1
+44	1	1
+639	1	1
+26	1	1
+3965	1	1
+40	1	1
+194	1	0
+279	1	1
+18	1	1
+277	0	2
+1883	0	1
+31	1	1
+1925	1	0
+2650	16	16
+2463	117	0
+67	8	17
+77	0	2
+55	17	17
+60	24	0
+126	0	64
+26	0	7
+19	0	7
+38	18	0
+40	40	0
+49	0	124
+32	15	8
+22	43	4
+36	1	614
+68	1	1
+7	0	2
+17	2	0
+7	0	2
+17	2	0
+20	0	2
+76	41	13
+71	60	21
+122	0	73
+72	28	0
+117	11	35
+24	13	0
+56	19	0
+3413	6	0
+9102	0	1
+87	0	2
+2219	0	1
+85	1	1
+31	0	4
+399	14	14
+408	0	1
+148	0	1
+807	1	1
+28	1	0
+452	4	0
+499	1	1
+25	1	1
+1037	1	0
+1066	1	1
+102	1	1
+1111	1	1
+47	1	1
+291	1	1
+49	1	1
+1195	1	1
+46	1	1
+370	1	1
+56	1	1
+142	1	1
+54	1	1
+538	0	1
+46	1	2890
+74	9	97
+1161	0	1
+1161	1	1
+23	1	1
+189	1	1
+43	1	1
+855	1	0
+353	8	0
+751	42950	42933
+383	0	4
+40	1	1
+3304	1	1
+46	1	1
+282	1	1
+39	1	1
+698	1	1
+20	1	1
+140	1	1
+26	1	1
+745	0	2
+2081	1	0
+817	4	4
+206	1	1
+44	1	1
+168	1	1
+20	1	1
+164	1	0
+21	1	1
+648	1	0
+912	6	0
+55	0	1
+1116	1	1
+21	1	1
+462	1	1
+43	1	1
+121	1	1
+48	0	3
+16	1	4
+1404	0	1
+450	4	0
+612	15	14
+304	1	1
+39	1	1
+564	1	1
+45	1	1
+303	2	0
+409	1	1
+18	1	0
+858	2	0
+2168	0	1
+54	22	22
+524	0	1
+523	0	12
+2424	18	14
+64	1	1
+31	1	1
+185	0	4
+657	10	10
+980	1	1
+20	1	1
+227	1	1
+37	1	1
+636	3	4
+3780	0	1
+4458	1	1
+23	1	1
+1114	1	3
+696	16	32
+861	18	18
+4781	0	4
+815	0	1
+9910	0	1
+10538	0	6
+25675	0	6
+10912	9	10
+824	0	1
+1450	11	0
+403	0	1
+154	1	1
+34	1	1
+146	1	0
+26	1	1
+2361	0	2
+775	8460	8460
+474	0	1
+1838	0	3
+2049	3	0
+14940	0	1
+398	17	17
+3797	0	4
+1305	10	0
+15047	1	0
+20201	1	0
+3812	0	1
+11605	0	1
+4121	2	0
+7755	1	0
+2661	3	1
+138	1	0
+2776	0	2
+4108	0	4
+8944	1	0
+10910	4	0
+1616	0	1
+1645	4	5
+36	0	2
+2223	0	16
+4729	10	0
+1921	0	1
+913	0	1
+2531	89346	89346
+3450	17	17
+3339	0	1
+3130	0	1
+2106	1	1
+42	1	1
+382	1	0
+616	178	0
+9555	52932	52932
+383	0	1
+2529	19	19
+10441	0	1
+24	1	1
+246	0	4
+1724	1	1
+37	1	1
+141	11	11
+103	1	128
+292	1	1
+20	1	1
+67	0	117
+30	1	1
+2771	0	3
+1487	0	3
+251	1	0
+1263	18	12
+888	1	1
+20	1	1
+2423	10	0
+1337	10	10
+6619	2	0
+982	113131	113131
+3241	16	0
+10939	12	0
+2143	0	1
+8355	0	3
+4114	0	1
+1404	0	1
+5850	1	0
+1691	38609	38609
+338	6	6
+2331	0	1
+2149	1	0
+10496	17	35
+3831	1	0
+8737	0	3
+16043	29	29
+1283	0	3
+8057	1	1
+63	1	1
+6053	5	0
+4539	43	43
+1259	2	0
+1628	5	5
+448	0	1
+374	0	1
+3431	1	0
+3049	32	0
+147	0	1
+1181	10	15
+206	3	4
+613	0	1
+1815	1	1
+18	1	1
+3726	0	3
+34	1	1
+361	17	17
+1252	0	3
+1642	1	0
+374	1	1
+19	1	1
+316	1	0
+13	2	0
+712	12	12
+204	1	1
+60	1	1
+843	1	3
+705	7	7
+72	1	1
+29	0	2
+332	0	1
+136	1	1
+1071	3	0
+548	1	1
+45	3	0
+121	1	1
+24	1	1
+262	16	16
+846	0	4
+412	0	2
+644	0	1
+26	1	1
+75	1	1
+32	1	1
+247	0	1
+174	1	2
+77	3	0
+113	0	1
+79	44	44
+186	0	14
+80	1	1
+813	0	9
+465	1	1
+60	1	1
+217	0	2
+400	0	3
+367	1	1
+37	1	1
+245	1	1
+25	1	1
+469	0	8
+857	17	18
+278	0	1
+1507	3	0
+1681	0	2
+429	4	0
+148	17	5
+278	4362	4362
+3670	16	16
+108	1	2
+197	1	1
+20	1	1
+367	20	19
+488	0	4
+1457	2	1
+205	5	5
+11	1	1
+213	20	15
+1190	30	0
+35	1	1
+1742	1	0
+123	1	0
+4678	0	2
+5739	0	1
+1167	0	1
+1767	1	0
+253	15	15
+5582	1	21
+8987	1	0
+2138	3	2
+2203	2	1
+5654	1	1
+24	3	3
+3229	0	1
+3385	4	4
+6989	1	0
+1294	4	0
+9088	2	3
+2270	1	1
+32	1	1
+6293	1	1
+26	1	1
+2668	4	0
+7792	1	0
+7099	2	0
+1639	1	0
+13217	0	2
+6668	0	2
+2319	1	0
+1034	0	6
+430	1	0
+1276	1	1
+27	1	1
+142	3	3
+35	1	1
+1211	1	1
+34	1	1
+664	0	10
+59	1	1
+78	1	1
+1519	1	1
+27	1	1
+154	14	14
+2525	0	4
+79	1	1
+145	1	1
+63	1	1
+70	1	1
+21	1	1
+695	1	1
+41	2	2
+564	1	1
+46	1	1
+279	4	0
+38	5	5
+201	22	22
+1020	1	1
+25	1	1
+2253	32	32
+545	1	1
+27	1	0
+54	15	16
+363	0	1
+845	0	2
+60	7	0
+787	2	0
+3691	1	0
+1843	1	1
+45	1	0
+11	1	2
+3499	1	1
+27	1	1
+970	0	1
+76	0	2
+1804	2	0
+1079	1	1
+17	1	1
+639	3	5
+73	1	1
+13	13	0
+66	1	1
+96	0	1
+294	14	0
+4554	0	1
+53	9	6
+691	0	1
+989	1	1
+143	1	1
+223	0	2
+95	1	1
+1136	1	1
+49	1	1
+606	1	1
+48	1	1
+128	0	4
+109	1	31
+44	10	781
+62	4	0
+129	1	1
+62	1	1
+106	1	1
+268	18	4
+125	1	1
+43	1	1
+909	0	2
+381	4	4
+74	1	1
+408	1	0
+1011	8	0
+8833	1	1
+23	6	19
+6628	1	1
+28	1	1
+4872	20	20
+692	1	0
+2650	0	4
+194	0	1
+596	5	6
+1359	0	1
+1572	7	7
+299	1	1
+49	1	1
+803	1	1
+93	1	1
+797	14	14
+433	8	0
+108	11	11
+140	1	1
+40	1	1
+470	1	1
+42	1	1
+1192	4	4
+129	1	1
+123	2	0
+95	1	1
+82	3	0
+664	1	1
+77	1	1
+57	1	1
+62	1	1
+473	2	0
+262	6	0
+45	1	1
+63	2	0
+39	1	1
+267	0	1
+197	2	104
+87	111	0
+122	0	7
+88	0	4
+86	1	1
+21	6	0
+563	14	14
+324	1	0
+205	1	1
+17	1	1
+426	17	17
+52	0	1
+201	4	0
+14	1	1
+1080	1	1
+24	1	1
+91	24	24
+279	9	8
+55	1	1
+32	1	1
+121	1	1
+62	1	1
+80	1	1
+72	1	1
+2217	2	0
+820	1	1
+30	1	1
+271	1	1
+47	1	1
+609	1	0
+1780	2	0
+742	1	1
+40	1	1
+272	1	1
+52	1	1
+1187	1	1
+23	1	1
+254	1	1
+60	1	1
+176	3	6
+463	1	1
+36	1	1
+797	1	1
+22	1	1
+395	5	2
+61	1	1
+31	3	3
+226	1	1
+59	1	1
+581	1	1
+46	1	1
+412	1	1
+23	1	0
+174	1	1
+24	1	1
+83	15	15
+363	1	1
+91	1	1
+383	20	20
+90	1	1
+44	1	1
+63	13	13
+976	1	1
+29	1	0
+10	0	3
+161	14	15
+127	16	16
+517	1	1
+81	1	1
+218	28	28
+124	1	1
+68	0	22
+399	7	7
+668	0	1
+175	1	0
+1018	1	1
+90	4	4
+1034	15	15
+69	1	1
+33	1	1
+174	1	1
+56	1	1
+169	1	0
+201	1	1
+30	1	1
+58	1	1
+38	1	1
+91	1	1
+98	4	4
+65	1	1
+19	2	0
+104	6	5
+25	1	1
+218	1	1
+37	1	1
+343	264243	150023
+66	8	8
+36	0	11
+62	1	1
+107	1	1
+68	3	130
+66	4	4
+50	21	21
+98	1	1
+127	1	0
+192	1	1
+71	1	1
+52	1	1
+200	1	1
+97	4	4
+85	5	5
+448	1	1
+97	11	11
+171	1	1
+61	1	1
+37	1	1
+156	3	0
+63	0	3
+155	3	0
+32	2	0
+232	1	1
+33	1	1
+175	2	0
+131	6	6
+1409	0	3
+222	1	1
+23	0	1
+1470	1	1
+21	1	1
+460	1	1
+71	1	1
+394	2	8
+37	1	1
+90	1	1
+43	1	1
+650	1	1
+34	1	1
+839	0	1
+431	1	1
+36	1	1
+284	51277	50054
+255	1	1
+80	5	5
+71	1	1
+48	3	3
+65	1	1
+83	1	1
+292	1	1
+33	1	1
+421	1	1
+74	1	0
+151	8	0
+65	1	1
+70	0	2
+58	0	8
+157	1	1
+64	1	1
+66	2	1
+97	1	1
+54	1	1
+46	0	1
+20	1	1
+210	16	16
+270	1	1
+46	1	1
+202	1	1
+22	1	1
+309	1	1
+25	0	1
+174	10	10
+305	1	1
+40	1	1
+75	32	30
+150	1	0
+17	1	1
+69	2	2
+27	1	1
+38	6	0
+49	5	3
+255	1	1
+43	1	1
+90	1	1
+74	1	1
+364	1	1
+23	3	3
+69	1	1
+22	2	0
+78	1	1
+29	1	0
+96	1	1
+56	8	0
+87	5	10
+85	2	2
+39	1	1
+87	314	0
+364	1	1
+64	1	1
+201	0	4
+42	0	1
+56	5	9
+62	0	5
+45	1	1
+109	25	25
+314	1	2
+16	0	2
+45	1	1
+103	17	17
+84	8	8
+294	17	17
+527	10	10
+435	4	0
+91	0	4
+387	10	10
+312	1	1
+43	1	1
+181	1	0
+1737	2	3
+50	1	1
+140	1	1
+33	1	0
+113	7	7
+353	6	6
+794	8	8
+510	1	1
+18	1	1
+124	1	1
+19	8	4
+76	1	0
+880	1	1
+16	1	1
+491	1	1
+49	1	1
+239	1	1
+7	0	1
+67	1	1
+114	0	25
+26	1	1
+183	13	13
+72	1	1
+26	1	0
+42	1	1
+222	14	14
+320	1	1
+55	1	1
+414	6	5
+1003	1	1
+20	0	8
+849	1	1
+29	1	1
+978	29539	30058
+159	1	1
+36	1	1
+107	1	1
+176	1	1
+154	0	5
+91	1	1
+54	1	1
+77	1	1
+238	2	2
+50	1	1
+1421	1	1
+23	1	1
+216	1	1
+122	1	1
+86	1	1
+41	3	1
+336	7	7
+41	9	0
+107	1	1
+90	1	3
+6	1	0
+84	1	1
+213	1	1
+26	1	1
+138	1	1
+25	1	1
+206	1	1
+36	3	3
+37	7	0
+500	1	1
+52	1	1
+52	1	1
+48	1	1
+186	1	1
+66	1	1
+141	1	1
+66	6	6
+72	1	0
+69	1	1
+100	10	10
+160	1	0
+64	7	7
+89	1	1
+123	1	1
+128	1	1
+36	1	1
+231	1	1
+61	1	1
+564	8	8
+593	1	1
+45	1	1
+163	1	0
+196	8	8
+97	1	1
+118	1	1
+67	0	1
+192	1	1
+60	3	0
+19	1	1
+1149	1	1
+18	1	1
+77	1	1
+32	2	0
+32	1	1
+136	1	1
+78	2	0
+162	4	0
+41	1	1
+351	13	13
+1634	2	0
+229	8	8
+59	11	0
+410	1	1
+76	1	1
+180	1	1
+92	1	1
+270	1	1
+40	1	1
+92	1	1
+53	1	1
+227	1	1
+42	1	1
+357	4	4
+23	1	1
+94	1	0
+200	6	0
+201	7	7
+70	5	13
+57	4	0
+35	1	1
+206	1	1
+76	2	2
+651	1	1
+68	4	0
+73	1	1
+49	4	0
+37	1	1
+145	2	2
+78	2	2
+108	12	12
+52	1	1
+35	1	1
+242	1	3
+76	2	2
+50	12	12
+70	1	1
+33	0	2
+57	1	1
+64	15	15
+168	1	1
+22	1	1
+66	2	2
+6	0	1
+24	1	1
+73	0	2
+64	1	1
+177	2	0
+19	4	0
+55	1	0
+33	1	1
+51	1	1
+122	1	1
+296	1	1
+85	1	1
+109	1	1
+64	1	1
+155	1	1
+58	0	2
+72	1	1
+25	1	1
+128	1	1
+45	2	0
+334	4	4
+106	1	1
+25	1	1
+64	1	1
+21	1	1
+368	15	15
+734	2	0
+701	15	15
+71	1	1
+41	1	1
+77	1	1
+56	1	1
+478	2	0
+714	8	7
+95	2	2
+52	2	1
+1129	1	1
+34	1	1
+1715	1	1
+87	1	1
+692	1	1
+47	0	1
+75	1	1
+2155	10	10
+1265	1	1
+46	1	1
+298	1	1
+22	1	1
+186	1	1
+34	1	1
+202	1	1
+61	1	0
+185	1	1
+24	1	0
+98	0	2
+258	8	14
+967	1	1
+15	1	1
+625	1	0
+1362	0	4
+23365	4	0
+6220	3	0
+1351	18	18
+11498	8145	8145
+3307	0	1
+13671	3	3
+52	1	1
+1308	2	0
+942	0	1
+17790	1	0
+4586	0	1
+949	0	2
+15047	0	1
+606	3	0
+7820	0	4
+22313	6	0
+10539	12	0
+4836	0	1
+8726	2	0
+194	1	1
+49	1	1
+15889	3	0
+2693	0	2
+2787	56	56
+544	0	1
+2673	26	19
+3075	2	0
+4230	8	0
+879	0	1
+9534	0	4
+23	1	1
+599	0	1
+317	1	0
+2844	27	31
+571	2	0
+3158	0	4
+4455	2	0
+1609	0	7
+61	1	1
+66	1	1
+343	7	0
+25	1	1
+246	0	1
+15	1	1
+943	2	0
+136	8	7
+589	1	1
+84	1	1
+280	17	15
+680	15	15
+81	0	3
+1484	12	28
+1016	1	1
+45	1	0
+108	0	10
+675	4	0
+1568	0	1
+191	4	4
+1484	9	13
+3530	2	4
+2846	1	1
+17	1	1
+704	0	1
+4801	1	0
+1417	0	4
+50	3	0
+165	0	1
+4044	39283	39283
+854	1	1
+47	1	1
+479	1	0
+137	0	3
+1456	10	13
+63	1	1
+37	1	1
+261	0	2
+109	1	1
+50	1	1
+56	129	1
+88	1	0
+44	1	1
+54	1	1
+56	1	50
+58	50	1
+54	277	1
+44	1	1
+297	0	39
+142	1	1
+85	1	1
+124	16	16
+58	3	15
+677	1	0
+1333	2	0
+13591	6	0
+1050	1	1
+46	1	1
+678	1	1
+31	1	1
+2632	4	4
+37	1	1
+22341	32	30
+10811	1	1
+25	0	1
+129	62	62
+226	1	1
+40	1	1
+159	4	4
+37	4	4
+179	1	1
+51	1	1
+103	2	0
+108	1	1
+79	1	1
+25	1	1
+58	1	1
+12	1	1
+275	14	0
+80	1	1
+83	1	1
+24	1	1
+59	1	0
+91	1	1
+65	1	1
+67	1	1
+136	4	0
+68	8	0
+331	5	0
+40	1	1
+110	10	6
+64	1	1
+368	1	1
+22	1	1
+509	1	1
+89	1	1
+926	1	0
+959	1	1
+44	1	1
+72	11	0
+47	1	1
+361	1	1
+37	1	1
+2204	2	2
+45	1	1
+1117	18	18
+141	1	1
+47	1	1
+148	1	1
+75	1	1
+107	57	56
+146	3	2
+249	1	1
+146	1	1
+94	1	1
+34	1	1
+700	0	331
+21	1	1
+73	1	1
+49	1	1
+356	1	1
+16	1	1
+112	1	1
+36	9	0
+515	1	1
+27	2	2
+192	1	1
+53	0	14
+82	1	1
+302	1	1
+68	1	1
+52	12	12
+52	1	1
+34	1	1
+166	7	7
+384	1	1
+31	1	1
+281	1	1
+57	1	1
+176	0	1
+1625	1	1
+26	1	1
+369	1	1
+21	1	1
+86	1	1
+134	1	1
+215	1	1
+214	15	1
+50	2	2
+26	1	1
+78	0	19
+64	1	1
+126	1	1
+43	1	1
+433	1	1
+76	0	1
+6	12	0
+52	1	1
+108	1	1
+87	1	1
+62	1	1
+26	1	1
+291	2	1
+143	1	1
+29	1	1
+56	12	12
+230	1	1
+153	4	4
+87	32	32
+584	12	12
+227	1	0
+1931	4	0
+836	1	1
+68	1	1
+205	24	19
+816	1	2
+1932	0	7
+1732	13	0
+257	4	0
+1441	1	0
+111	6	0
+1505	1	1
+42	0	1
+373	13	13
+565	1	1
+76	1	0
+1881	0	4
+68	4	0
+43	0	4
+2201	8	8
+3726	3	0
+339	15	11
+249	1	1
+35	1	1
+250	1	1
+38	1	1
+359	11	12
+109	1	1
+43	18	0
+822	1	1
+53	1	1
+325	15	15
+123	1	1
+42	6	6
+240	1	1
+44	1	1
+438	7	7
+142	2	0
+1004	0	1
+9275	1	1
+37	1	0
+2071	0	1
+10399	0	1
+12513	2	1
+11243	1	1
+26	1	1
+816	4	0
+8248	26	26
+7722	2	0
+1594	1	0
+363	5	0
+2394	0	2
+4361	43	41
+12296	4	0
+835	0	1
+391	34	61
+12157	0	18
+1719
+
+chain	576814	chr6_mann_hap4	4683263	+	1212600	1230600	chr10	135374737	-	28241612	28250801	9180
+481	1	1
+46	1	1
+3015	1	1
+93	1	1
+2394	11402	2623
+68	26	25
+5	0	2
+124	0	1
+62	39	3
+39	3	5
+199
+
+chain	536760	chr6_mann_hap4	4683263	+	4039899	4045825	chr5	180857866	+	39823592	39829519	16844
+294	1	1
+54	1	1
+302	0	1
+93	1	1
+29	2	2
+134	1	1
+55	1	1
+603	13	13
+1215	13	13
+1780	1	1
+42	1	1
+233	1	1
+94	1	1
+485	1	1
+173	1	1
+76	1	1
+24	1	1
+71	1	1
+44	1	1
+82
+
+chain	146874	chr6_mann_hap4	4683263	+	4071169	4072762	chr6	170899992	+	134026872	134029045	878977
+503	1	1
+42	1	1
+274	1	1
+24	0	1
+48	1	0
+10	0	1
+42	0	579
+646
+
+chain	102870	chr6_mann_hap4	4683263	+	3889360	3891944	chr7	158821424	+	116952571	116956379	1238703
+117	2	2
+40	1	1
+56	1	1
+110	1	1
+92	1	1
+113	2	2
+63	1	1
+85	102	1326
+64	26	26
+95	124	124
+108	355	355
+211	690	690
+124
+
+chain	88220	chr6_mann_hap4	4683263	+	4099145	4105339	chr12	132349534	-	75332582	75341961	1434691
+65	33	33
+177	10	15
+106	4900	8080
+86	4	4
+267	1	1
+40	1	1
+504
+
+chain	82095	chr6_mann_hap4	4683263	+	3946479	3947465	chr2	242951149	-	63941857	63946734	1538129
+173	0	3890
+317	1	1
+39	1	1
+234	0	4
+116	1	1
+18	3	0
+83
+
+chain	77658	chr6_mann_hap4	4683263	+	3855504	3856400	chrX	154913754	+	120225651	120226547	1623639
+896
+
+chain	47748	chr6_mann_hap4	4683263	+	3888321	3890147	chrX	154913754	+	47530376	47536125	1299062
+73	10	10
+52	18	17
+100	64	64
+53	6	6
+131	99	99
+213	51	51
+144	732	4656
+80
+
+chain	47213	chr6_mann_hap4	4683263	+	3989872	3990794	chr5	180857866	+	134244858	134245983	2704506
+144	28	28
+67	90	94
+193	60	61
+52	141	339
+53	41	41
+53
+
+chain	46978	chr6_mann_hap4	4683263	+	2571063	2572874	chr3	199501827	-	190558999	190560805	2719824
+64	48	48
+112	161	161
+89	220	218
+60	475	474
+84	303	301
+99	9	9
+87
+
+chain	44341	chr6_mann_hap4	4683263	+	3927110	3927612	chrX	154913754	-	52960373	52960875	2903522
+147	1	1
+78	1	1
+160	1	1
+114
+
+chain	44107	chr6_mann_hap4	4683263	+	3835941	3836978	chr5	180857866	+	173373371	173375321	2921175
+63	100	100
+147	427	1340
+300
+
+chain	39461	chr6_mann_hap4	4683263	+	4070547	4070992	chr9	140273252	+	112733643	112734088	3326103
+238	2	2
+149	1	1
+55
+
+chain	35818	chr6_mann_hap4	4683263	+	3871024	3871462	chr17	78774742	-	29841443	29841854	3734139
+50	1	1
+51	12	0
+240	15	0
+69
+
+chain	30934	chr6_mann_hap4	4683263	+	2643294	2643706	chr7	158821424	+	2168309	2168721	4470814
+207	3	3
+37	1	1
+54	50	50
+60
+
+chain	26090	chr6_mann_hap4	4683263	+	1150980	1153720	chr6	170899992	+	30003398	30007118	6475487
+62	70	70
+76	766	798
+93	658	655
+52	786	1737
+53	61	61
+63
+
+chain	23990	chr6_mann_hap4	4683263	+	1157427	1158203	chr7	158821424	-	51137320	51138262	7695541
+178	101	101
+72	385	551
+40
+
+chain	23264	chr6_mann_hap4	4683263	+	4065870	4066815	chr6	170899992	+	32821586	32822354	8135397
+218	677	500
+50
+
+chain	21807	chr6_mann_hap4	4683263	+	2512201	2512573	chrX	154913754	-	34520894	34521266	9125800
+131	125	125
+116
+
+chain	20350	chr6_mann_hap4	4683263	+	2657077	2657501	chr7	158821424	-	21000102	21000525	10170609
+90	41	41
+55	140	139
+98
+
+chain	20145	chr6_mann_hap4	4683263	+	4080253	4081781	chr7	158821424	+	28844408	28845333	2477233
+50	75	74
+83	106	109
+74	174	246
+103	816	139
+47
+
+chain	19089	chr6_mann_hap4	4683263	+	3856636	3856946	chr6	170899992	-	57258123	57258433	11200200
+55	51	51
+66	32	32
+106
+
+chain	17641	chr6_mann_hap4	4683263	+	4011215	4011458	chrX	154913754	+	35042287	35042530	12436915
+99	43	43
+101
+
+chain	16962	chr6_mann_hap4	4683263	+	2570543	2573577	chr6	170899992	-	142198254	142201285	2740643
+52	14	14
+92	178	178
+78	1931	1927
+60	60	61
+102	387	387
+80
+
+chain	16215	chr6_mann_hap4	4683263	+	3951844	3952907	chr6	170899992	+	32656500	32657559	13820716
+58	826	822
+72	27	27
+80
+
+chain	16190	chr6_mann_hap4	4683263	+	3164538	3164716	chr2	242951149	+	128261675	128261851	597537
+28	10	8
+140
+
+chain	16086	chr6_mann_hap4	4683263	+	4006818	4007634	chr1	247249719	-	180906629	180907434	2580692
+2	123	123
+47	104	104
+70	400	389
+70
+
+chain	15557	chr6_mann_hap4	4683263	+	4157319	4158144	chr7	158821424	+	130132312	130132930	14485178
+71	636	429
+118
+
+chain	15452	chr6_mann_hap4	4683263	+	3929430	3929596	chrX	154913754	+	67920599	67920765	14594392
+166
+
+chain	14605	chr6_mann_hap4	4683263	+	4069695	4069910	chr5	180857866	+	98319067	98319283	15498993
+64	48	49
+103
+
+chain	14320	chr6_mann_hap4	4683263	+	3970754	3970920	chr5	180857866	+	46013667	46013833	15829593
+166
+
+chain	13359	chr6_mann_hap4	4683263	+	4006581	4006818	chr5	180857866	-	39455571	39455808	2075146
+237
+
+chain	13048	chr6_mann_hap4	4683263	+	3971467	3971895	chr2	242951149	+	206984071	206984490	17422560
+94	272	263
+62
+
+chain	13024	chr6_mann_hap4	4683263	+	983409	983545	chr11	134452384	-	45905925	45906061	17454497
+136
+
+chain	12983	chr6_mann_hap4	4683263	+	3892428	3892585	chr15	100338915	+	59852230	59852387	17511267
+67	7	7
+83
+
+chain	12686	chr6_mann_hap4	4683263	+	3839048	3839184	chr6	170899992	-	138278996	138279132	17957207
+136
+
+chain	12556	chr6_mann_hap4	4683263	+	1192697	1192836	chr2	242951149	-	184047846	184047985	18149168
+139
+
+chain	12476	chr6_mann_hap4	4683263	+	3826791	3826924	chr6	170899992	+	32549390	32549523	18269668
+133
+
+chain	12434	chr6_mann_hap4	4683263	+	3808825	3809130	chr7	158821424	-	76714202	76714512	18331176
+70	158	163
+77
+
+chain	12179	chr6_mann_hap4	4683263	+	3831748	3831876	chr6	170899992	+	32566069	32566197	18716372
+128
+
+chain	12137	chr6_mann_hap4	4683263	+	3872720	3873131	chr7	158821424	+	90920405	90920810	18779045
+54	266	260
+91
+
+chain	12051	chr6_mann_hap4	4683263	+	1151414	1151573	chr6	170899992	+	30566919	30567079	18913589
+81	23	24
+55
+
+chain	11900	chr6_mann_hap4	4683263	+	3926391	3926689	chr5	180857866	-	150002482	150002780	2916742
+72	52	52
+94	24	24
+56
+
+chain	11872	chr6_mann_hap4	4683263	+	1146859	1148064	chr6	170899992	+	29900614	29901492	19205041
+65	1050	723
+90
+
+chain	11746	chr6_mann_hap4	4683263	+	1143598	1143746	chr7	158821424	-	7754727	7754875	19419747
+54	14	14
+80
+
+chain	11745	chr6_mann_hap4	4683263	+	1218680	1218806	chr10	135374737	-	135314271	135314397	19420295
+126
+
+chain	11699	chr6_mann_hap4	4683263	+	1229899	1230035	chr10	135374737	+	90412720	90412856	14918390
+117	3	3
+16
+
+chain	11593	chr6_mann_hap4	4683263	+	3807962	3808085	chr1	247249719	-	238369051	238369174	19677684
+123
+
+chain	11428	chr6_mann_hap4	4683263	+	3972086	3972349	chr9	140273252	+	73803510	73803773	19960546
+86	127	127
+50
+
+chain	11397	chr6_mann_hap4	4683263	+	3965743	3966049	chr6	170899992	+	32661358	32661660	20018576
+64	168	164
+74
+
+chain	11122	chr6_mann_hap4	4683263	+	1203623	1204440	chr6	170899992	-	139553083	139553887	20511870
+77	676	663
+64
+
+chain	11075	chr6_mann_hap4	4683263	+	3824678	3824943	chrX	154913754	-	91757488	91757751	20592182
+66	132	130
+67
+
+chain	11034	chr6_mann_hap4	4683263	+	2653282	2653431	chr6	170899992	-	161606914	161607063	20670487
+64	22	22
+63
+
+chain	10867	chr6_mann_hap4	4683263	+	2578599	2578756	chr6	170899992	-	132294381	132294544	20980274
+55	29	35
+73
+
+chain	10661	chr6_mann_hap4	4683263	+	4070344	4070547	chr9	140273252	+	21133799	21134002	3998059
+43	83	83
+77
+
+chain	10522	chr6_mann_hap4	4683263	+	3881310	3881592	chr6	170899992	+	32650612	32650898	21668160
+51	155	159
+76
+
+chain	10446	chr6_mann_hap4	4683263	+	3833364	3833476	chr10	135374737	+	116791472	116791584	21828222
+112
+
+chain	10440	chr6_mann_hap4	4683263	+	3811691	3811821	chr3	199501827	-	53390365	53390495	21843018
+67	9	9
+54
+
+chain	10424	chr6_mann_hap4	4683263	+	1196400	1196662	chr1	247249719	-	93388912	93389184	21873906
+71	137	147
+54
+
+chain	10120	chr6_mann_hap4	4683263	+	4070282	4070470	chr7	158821424	-	148539669	148539857	3454343
+62	43	43
+83
+
+chain	10097	chr6_mann_hap4	4683263	+	3811321	3811557	chr6	170899992	-	10896454	10896689	22596969
+52	115	114
+69
+
+chain	10000	chr6_mann_hap4	4683263	+	4096293	4096805	chr2	242951149	-	75663422	75663931	22813441
+66	387	384
+59
+
+chain	9988	chr6_mann_hap4	4683263	+	3809787	3810216	chr10	135374737	-	44216709	44217139	22840112
+60	305	306
+64
+
+chain	9977	chr6_mann_hap4	4683263	+	4081621	4081734	chr6	170899992	-	39392888	39393001	3205407
+113
+
+chain	9923	chr6_mann_hap4	4683263	+	1132190	1132294	chr6	170899992	+	29984509	29984613	22990369
+104
+
+chain	9759	chr6_mann_hap4	4683263	+	3834344	3834498	chr10	135374737	+	105999092	105999246	23372649
+62	39	39
+53
+
+chain	9755	chr6_mann_hap4	4683263	+	3833117	3833361	chrX	154913754	-	4438295	4438540	23379344
+56	126	127
+62
+
+chain	9686	chr6_mann_hap4	4683263	+	3810435	3810616	chr18	76117153	-	71040520	71040702	23549061
+65	65	66
+51
+
+chain	9627	chr6_mann_hap4	4683263	+	3972992	3973194	chr2	242951149	+	230690248	230690450	23687186
+65	86	86
+51
+
+chain	9614	chr6_mann_hap4	4683263	+	2669709	2670446	chr6	170899992	-	140934793	140935541	23727233
+66	613	624
+58
+
+chain	9599	chr6_mann_hap4	4683263	+	4070139	4070248	chr11	134452384	+	56073710	56073819	11992436
+109
+
+chain	9564	chr6_mann_hap4	4683263	+	3827056	3827221	chr6	170899992	+	32549657	32549823	23841399
+59	50	51
+56
+
+chain	9528	chr6_mann_hap4	4683263	+	1159675	1160112	chr6	170899992	+	29878108	29878543	23937749
+59	318	316
+60
+
+chain	9459	chr6_mann_hap4	4683263	+	4095177	4095476	chr6	170899992	+	162410099	162410399	24103461
+60	183	184
+56
+
+chain	9368	chr6_mann_hap4	4683263	+	3972521	3972756	chr12	132349534	-	95011118	95011354	24299159
+63	120	121
+52
+
+chain	9354	chr6_mann_hap4	4683263	+	3870808	3870942	chr6	170899992	+	119226702	119226836	9825430
+89	20	20
+25
+
+chain	9352	chr6_mann_hap4	4683263	+	3873416	3873994	chr1	247249719	-	127730766	127731350	24325058
+63	457	463
+58
+
+chain	9220	chr6_mann_hap4	4683263	+	3811888	3812097	chr14	106368585	-	26360313	26360419	24589598
+77	103	0
+29
+
+chain	9090	chr6_mann_hap4	4683263	+	2577845	2577955	chr3	199501827	-	94209663	94209773	24799757
+53	4	4
+53
+
+chain	8867	chr6_mann_hap4	4683263	+	2303270	2303362	chr6	170899992	+	31062348	31062440	25148412
+92
+
+chain	8658	chr6_mann_hap4	4683263	+	3940022	3940112	chr6	170899992	+	32624355	32624445	25451087
+90
+
+chain	8423	chr6_mann_hap4	4683263	+	4072785	4072907	chr8	146274826	-	73050790	73050912	14363914
+122
+
+chain	8057	chr6_mann_hap4	4683263	+	3926870	3927000	chr16	88827254	+	18531944	18532074	3198196
+130
+
+chain	7759	chr6_mann_hap4	4683263	+	2673921	2674003	chr6	170899992	+	31350450	31350532	26801069
+82
+
+chain	7673	chr6_mann_hap4	4683263	+	2657501	2657610	chr6	170899992	+	83069844	83069953	14556403
+4	44	44
+61
+
+chain	7642	chr6_mann_hap4	4683263	+	3888828	3890773	chr8	146274826	-	66025745	66026665	1359052
+97	215	215
+31	1	1
+19	1532	507
+50
+
+chain	7574	chr6_mann_hap4	4683263	+	4484512	4485183	chr20	62435964	+	45587686	45587880	2535008
+51	481	51
+16	61	14
+62
+
+chain	7541	chr6_mann_hap4	4683263	+	2688373	2688460	chr9	140273252	-	10289268	10289355	15645101
+13	6	6
+68
+
+chain	7487	chr6_mann_hap4	4683263	+	2574042	2574244	chr12	132349534	-	40641236	40641438	23940543
+56	141	141
+5
+
+chain	7440	chr6_mann_hap4	4683263	+	3850580	3850658	chrX	154913754	-	39741290	39741368	27355538
+78
+
+chain	7404	chr6_mann_hap4	4683263	+	3850662	3850740	chr11	134452384	+	35675434	35675512	27404541
+78
+
+chain	7364	chr6_mann_hap4	4683263	+	4081165	4082062	chr1	247249719	+	33290703	33291601	1419850
+50	1	0
+53	86	88
+56	370	370
+160	42	42
+79
+
+chain	7276	chr6_mann_hap4	4683263	+	4034825	4034901	chr6	170899992	-	67344251	67344327	27653184
+76
+
+chain	7232	chr6_mann_hap4	4683263	+	3936821	3936898	chr6	170899992	+	32620027	32620104	27728489
+77
+
+chain	7204	chr6_mann_hap4	4683263	+	3963650	3963727	chr13	114142980	+	48271341	48271418	27789281
+77
+
+chain	7199	chr6_mann_hap4	4683263	+	4005404	4006455	chr3	199501827	+	106790123	106791174	347314
+69	5	5
+109	2	2
+142	1	1
+77	1	1
+51	1	0
+194	0	1
+399
+
+chain	7168	chr6_mann_hap4	4683263	+	4101507	4101583	chr12	132349534	+	30936505	30936581	27864404
+76
+
+chain	7077	chr6_mann_hap4	4683263	+	3870942	3871024	chr3	199501827	-	45186978	45187059	5450943
+68	1	0
+13
+
+chain	7012	chr6_mann_hap4	4683263	+	4115371	4115645	chr5	180857866	-	50439772	50440046	4370271
+130	8	8
+64	1	1
+71
+
+chain	6949	chr6_mann_hap4	4683263	+	3795791	3795864	chr6	170899992	+	32549387	32549460	28300222
+73
+
+chain	6804	chr6_mann_hap4	4683263	+	3799462	3799534	chr6	170899992	+	32582474	32582546	28581367
+72
+
+chain	6732	chr6_mann_hap4	4683263	+	2675578	2675667	chr18	76117153	-	11487790	11487879	28728624
+29	7	7
+53
+
+chain	6712	chr6_mann_hap4	4683263	+	2588030	2588100	chr6	170899992	-	140565854	140565924	28801698
+70
+
+chain	6680	chr6_mann_hap4	4683263	+	4075286	4087765	chr6	170899992	+	32827127	32836923	21175981
+50	4327	3617
+61	4734	2690
+85	515	965
+52	119	119
+177	2121	1742
+68	118	118
+52
+
+chain	6622	chr6_mann_hap4	4683263	+	3824747	3824817	chr11	134452384	+	57802002	57802072	28988414
+70
+
+chain	6586	chr6_mann_hap4	4683263	+	2674213	2674283	chr6	170899992	-	140567268	140567338	29088341
+70
+
+chain	6584	chr6_mann_hap4	4683263	+	3990111	3990185	chr18	76117153	-	4274607	4274681	4481991
+74
+
+chain	6566	chr6_mann_hap4	4683263	+	4010034	4010102	chr6	170899992	+	32665461	32665529	29137405
+68
+
+chain	6513	chr6_mann_hap4	4683263	+	4099018	4099087	chr12	132349534	+	47073126	47073195	29262419
+69
+
+chain	6495	chr6_mann_hap4	4683263	+	4159049	4159118	chr5	180857866	+	76445848	76445917	29303918
+69
+
+chain	6436	chr6_mann_hap4	4683263	+	3871527	3871805	chr7	158821424	+	110932926	110933204	10468972
+57	171	171
+50
+
+chain	6411	chr6_mann_hap4	4683263	+	4039821	4039893	chr7	158821424	+	30445389	30445461	17285
+72
+
+chain	6359	chr6_mann_hap4	4683263	+	3869372	3869440	chr6	170899992	+	32566306	32566374	29618338
+68
+
+chain	6271	chr6_mann_hap4	4683263	+	3932457	3932523	chr18	76117153	+	11207587	11207653	29843873
+66
+
+chain	6221	chr6_mann_hap4	4683263	+	4094828	4094893	chr13	114142980	+	50378597	50378662	29991830
+65
+
+chain	6213	chr6_mann_hap4	4683263	+	1229662	1229728	chrX	154913754	+	137911239	137911305	30001477
+66
+
+chain	6203	chr6_mann_hap4	4683263	+	3873624	3873689	chr10	135374737	+	5090148	5090213	30033078
+65
+
+chain	6176	chr6_mann_hap4	4683263	+	4099536	4099611	chr11	134452384	-	71399807	71399882	3438338
+75
+
+chain	6158	chr6_mann_hap4	4683263	+	3877219	3877284	chr8	146274826	+	95080661	95080726	30127968
+65
+
+chain	6140	chr6_mann_hap4	4683263	+	4095848	4095913	chr6	170899992	-	34774251	34774316	30199403
+65
+
+chain	6109	chr6_mann_hap4	4683263	+	3890332	3891494	chr3	199501827	-	173189040	173190202	2018297
+14	5	5
+73	23	23
+9	985	985
+53
+
+chain	6085	chr6_mann_hap4	4683263	+	3815553	3815617	chr6	170899992	-	55240220	55240284	30326057
+64
+
+chain	6021	chr6_mann_hap4	4683263	+	4094914	4094977	chr10	135374737	-	117721859	117721922	30522771
+63
+
+chain	5976	chr6_mann_hap4	4683263	+	2676901	2676964	chr6	170899992	+	31358648	31358711	30614230
+63
+
+chain	5949	chr6_mann_hap4	4683263	+	3824409	3824472	chr7	158821424	+	26639264	26639327	30690415
+63
+
+chain	5940	chr6_mann_hap4	4683263	+	3886792	3886855	chr2	242951149	-	15301589	15301652	30719367
+63
+
+chain	5911	chr6_mann_hap4	4683263	+	3951381	3951442	chrX	154913754	-	11371530	11371591	30799839
+61
+
+chain	5847	chr6_mann_hap4	4683263	+	4105339	4105404	chr17	78774742	-	73855979	73856044	1451430
+65
+
+chain	5813	chr6_mann_hap4	4683263	+	3850423	3850485	chr1	247249719	+	47323960	47324022	31053357
+62
+
+chain	5712	chr6_mann_hap4	4683263	+	3809370	3809430	chr12	132349534	-	114271713	114271773	31330278
+60
+
+chain	5702	chr6_mann_hap4	4683263	+	3970106	3970165	chr6	170899992	+	32605878	32605937	31357679
+59
+
+chain	5680	chr6_mann_hap4	4683263	+	2302831	2302921	chr6	170899992	+	31062944	31063124	23617653
+33	39	129
+18
+
+chain	5655	chr6_mann_hap4	4683263	+	3855204	3855371	chrX	154913754	+	81246238	81246422	14247867
+57	109	126
+1
+
+chain	5594	chr6_mann_hap4	4683263	+	3796059	3796118	chr6	170899992	+	32549657	32549716	31663072
+59
+
+chain	5594	chr6_mann_hap4	4683263	+	3893458	3893517	chr1	247249719	-	146336256	146336315	31665010
+59
+
+chain	5512	chr6_mann_hap4	4683263	+	3824164	3824222	chr7	158821424	+	45670922	45670980	31905208
+58
+
+chain	5502	chr6_mann_hap4	4683263	+	3808491	3808548	chr1	247249719	-	79348621	79348678	31943034
+57
+
+chain	5494	chr6_mann_hap4	4683263	+	4130703	4130761	chr5	180857866	-	119300515	119300573	31945207
+58
+
+chain	5494	chr6_mann_hap4	4683263	+	3808247	3808305	chr4	191273063	-	5377020	5377078	31946828
+58
+
+chain	5476	chr6_mann_hap4	4683263	+	2311526	2311584	chrX	154913754	+	154691014	154691072	32018635
+58
+
+chain	5448	chr6_mann_hap4	4683263	+	1152324	1152381	chr6	170899992	+	29906136	29906193	32122349
+57
+
+chain	5435	chr6_mann_hap4	4683263	+	4007164	4007322	chr6	170899992	-	63943483	63943641	1906371
+158
+
+chain	5402	chr6_mann_hap4	4683263	+	1156066	1156122	chr10	135374737	+	63402064	63402120	32243879
+56
+
+chain	5394	chr6_mann_hap4	4683263	+	3972634	3972691	chr9	140273252	-	60383594	60383651	32250416
+57
+
+chain	5385	chr6_mann_hap4	4683263	+	4130844	4130901	chr6	170899992	-	83909587	83909644	32298057
+57
+
+chain	5367	chr6_mann_hap4	4683263	+	2578199	2578256	chr18	76117153	+	1134159	1134216	32358571
+57
+
+chain	5330	chr6_mann_hap4	4683263	+	3931278	3931334	chr6	170899992	+	32568311	32568367	32437916
+56
+
+chain	5276	chr6_mann_hap4	4683263	+	4098513	4098569	chr12	132349534	+	40414598	40414654	32640380
+56
+
+chain	5229	chr6_mann_hap4	4683263	+	2586412	2586466	chr6	170899992	-	140897459	140897513	32754405
+54
+
+chain	5211	chr6_mann_hap4	4683263	+	3836033	3836093	chr18	76117153	-	36956615	36956675	5572697
+38	15	15
+7
+
+chain	5158	chr6_mann_hap4	4683263	+	3970466	3970521	chr10	135374737	-	40576729	40576784	32990090
+55
+
+chain	5146	chr6_mann_hap4	4683263	+	3856405	3856719	chr8	146274826	+	48564292	48564606	15853984
+85	201	201
+28
+
+chain	5121	chr6_mann_hap4	4683263	+	3811628	3811682	chr10	135374737	-	125001214	125001268	33093899
+54
+
+chain	5103	chr6_mann_hap4	4683263	+	1145020	1145074	chr6	170899992	+	76955761	76955815	33170027
+54
+
+chain	5103	chr6_mann_hap4	4683263	+	2640619	2640673	chr4	191273063	+	102542252	102542306	33171908
+54
+
+chain	5085	chr6_mann_hap4	4683263	+	4098430	4098484	chrX	154913754	-	140611616	140611670	33235342
+54
+
+chain	5066	chr6_mann_hap4	4683263	+	1192620	1192673	chr21	46944323	-	1867343	1867396	33290792
+53
+
+chain	5062	chr6_mann_hap4	4683263	+	2570759	2570813	chr8	146274826	-	12544502	12544556	11634211
+54
+
+chain	5031	chr6_mann_hap4	4683263	+	3825550	3825604	chr11	134452384	+	134387408	134387462	33376435
+54
+
+chain	5030	chr6_mann_hap4	4683263	+	4130785	4130838	chr15	100338915	+	69519076	69519129	33389328
+53
+
+chain	5021	chr6_mann_hap4	4683263	+	2574130	2574183	chrX	154913754	+	36345885	36345938	33439867
+53
+
+chain	5020	chr6_mann_hap4	4683263	+	4060907	4060959	chr3	199501827	+	48220698	48220750	33444406
+52
+
+chain	5012	chr6_mann_hap4	4683263	+	3951677	3951730	chr6	170899992	+	32629462	32629515	33454256
+53
+
+chain	5003	chr6_mann_hap4	4683263	+	4102005	4102058	chr5	180857866	+	152654188	152654241	33499797
+53
+
+chain	5003	chr6_mann_hap4	4683263	+	1229462	1229515	chr19	63811651	-	15372469	15372522	33501003
+53
+
+chain	4985	chr6_mann_hap4	4683263	+	2640409	2640462	chr16	88827254	-	40848691	40848744	33578669
+53
+
+chain	4971	chr6_mann_hap4	4683263	+	2512062	2512133	chr4	191273063	-	56892114	56892185	10839773
+71
+
+chain	4967	chr6_mann_hap4	4683263	+	3825268	3825321	chr3	199501827	+	186460138	186460191	33617850
+53
+
+chain	4957	chr6_mann_hap4	4683263	+	3885923	3885975	chrX	154913754	+	147065533	147065585	33651269
+52
+
+chain	4957	chr6_mann_hap4	4683263	+	2575182	2575234	chr9	140273252	-	31866047	31866099	33651494
+52
+
+chain	4948	chr6_mann_hap4	4683263	+	4100717	4100769	chr1	247249719	-	35792193	35792245	33679191
+52
+
+chain	4948	chr6_mann_hap4	4683263	+	2574667	2574719	chr8	146274826	-	9857366	9857418	33680602
+52
+
+chain	4922	chr6_mann_hap4	4683263	+	4009115	4009168	chr6	170899992	+	32548301	32548354	33750859
+53
+
+chain	4903	chr6_mann_hap4	4683263	+	3850504	3850556	chr10	135374737	-	57466002	57466054	33851105
+52
+
+chain	4903	chr6_mann_hap4	4683263	+	4012033	4012085	chr10	135374737	+	117209347	117209399	33851122
+52
+
+chain	4863	chr6_mann_hap4	4683263	+	4069590	4069643	chr17	78774742	+	14392768	14392821	28434808
+53
+
+chain	4829	chr6_mann_hap4	4683263	+	1204441	1204491	chr6	170899992	+	29800923	29800973	34088054
+50
+
+chain	4821	chr6_mann_hap4	4683263	+	4157686	4157737	chrX	154913754	-	88293005	88293056	34119905
+51
+
+chain	4821	chr6_mann_hap4	4683263	+	3816946	3816997	chrX	154913754	+	135859174	135859225	34119936
+51
+
+chain	4812	chr6_mann_hap4	4683263	+	1190701	1190752	chr6	170899992	+	30567861	30567912	34152526
+51
+
+chain	4784	chr6_mann_hap4	4683263	+	3932557	3932607	chr3	199501827	+	84648995	84649045	34278095
+50
+
+chain	4758	chr6_mann_hap4	4683263	+	4095126	4095177	chr11	134452384	+	59226474	59226525	34323839
+51
+
+chain	4757	chr6_mann_hap4	4683263	+	2310474	2310524	chr11	134452384	+	7692440	7692490	34342561
+50
+
+chain	4739	chr6_mann_hap4	4683263	+	2310303	2310353	chr18	76117153	+	71840104	71840154	34400727
+50
+
+chain	4730	chr6_mann_hap4	4683263	+	3787434	3787484	chr4	191273063	-	37377714	37377764	34442427
+50
+
+chain	4712	chr6_mann_hap4	4683263	+	1146218	1146268	chr14	106368585	-	81295539	81295589	34510763
+50
+
+chain	4703	chr6_mann_hap4	4683263	+	2675065	2675115	chr8	146274826	+	89610032	89610082	34558303
+50
+
+chain	4685	chr6_mann_hap4	4683263	+	1229409	1229459	chrX	154913754	-	17497814	17497864	34590611
+50
+
+chain	4676	chr6_mann_hap4	4683263	+	3971574	3971624	chr8	146274826	+	69479304	69479354	34603338
+50
+
+chain	4606	chr6_mann_hap4	4683263	+	4016520	4016570	chr5	180857866	-	14463729	14463779	34659648
+50
+
+chain	4600	chr6_mann_hap4	4683263	+	2569984	2570033	chr12	132349534	-	4862576	4862625	22913313
+49
+
+chain	4530	chr6_mann_hap4	4683263	+	3886656	3886704	chr13	114142980	-	22170853	22170901	34701009
+48
+
+chain	4406	chr6_mann_hap4	4683263	+	4011118	4011181	chr12	132349534	+	83019068	83019131	17889504
+63
+
+chain	4392	chr6_mann_hap4	4683263	+	1157646	1157705	chr7	158821424	-	126060926	126060985	9905440
+59
+
+chain	4358	chr6_mann_hap4	4683263	+	3963545	3963592	chr4	191273063	+	98116240	98116287	34788627
+47
+
+chain	4338	chr6_mann_hap4	4683263	+	2302495	2302540	chr6	170899992	+	31062473	31062518	34812241
+45
+
+chain	4205	chr6_mann_hap4	4683263	+	2570813	2571448	chr4	191273063	+	161293453	161294088	2765734
+66	98	98
+77	6	6
+3	343	343
+42
+
+chain	4169	chr6_mann_hap4	4683263	+	4069643	4069694	chrX	154913754	+	84821116	84821167	24393818
+51
+
+chain	4167	chr6_mann_hap4	4683263	+	3838733	3838778	chr16	88827254	-	62536028	62536073	34880256
+45
+
+chain	4152	chr6_mann_hap4	4683263	+	3836004	3836104	chr19	63811651	+	19808105	19808205	3095372
+29	60	60
+11
+
+chain	4047	chr6_mann_hap4	4683263	+	3972236	3972287	chr6	170899992	+	112361298	112361349	25801950
+42	5	5
+4
+
+chain	3949	chr6_mann_hap4	4683263	+	2688555	2688633	chr19	63811651	+	60123016	60123094	19419643
+78
+
+chain	3938	chr6_mann_hap4	4683263	+	3812129	3812170	chr12	132349534	+	106783136	106783177	34996469
+41
+
+chain	3933	chr6_mann_hap4	4683263	+	2511488	2511645	chr1	247249719	-	10334654	10334811	9926759
+99	7	7
+51
+
+chain	3926	chr6_mann_hap4	4683263	+	4006888	4006943	chr9	140273252	-	21404336	21404391	4875740
+55
+
+chain	3812	chr6_mann_hap4	4683263	+	4007464	4007564	chr3	199501827	+	15208966	15209066	3047556
+56	42	42
+2
+
+chain	3783	chr6_mann_hap4	4683263	+	2657037	2657077	chr2	242951149	-	166645324	166645364	18114610
+40
+
+chain	3746	chr6_mann_hap4	4683263	+	3833193	3833245	chr3	199501827	+	114553026	114553078	23981702
+52
+
+chain	3734	chr6_mann_hap4	4683263	+	4157453	4157518	chr6	170899992	+	80018577	80018642	19955867
+65
+
+chain	3720	chr6_mann_hap4	4683263	+	4102548	4102587	chr5	180857866	-	28755460	28755499	35075682
+39
+
+chain	3600	chr6_mann_hap4	4683263	+	4159173	4159211	chr2	242951149	+	129304609	129304647	25766361
+38
+
+chain	3592	chr6_mann_hap4	4683263	+	3870724	3870762	chr3	199501827	-	38712743	38712781	26080747
+38
+
+chain	3526	chr6_mann_hap4	4683263	+	1196363	1196400	chr3	199501827	+	179624737	179624774	21949405
+37
+
+chain	3503	chr6_mann_hap4	4683263	+	3972049	3972086	chrX	154913754	+	6516305	6516342	20940830
+37
+
+chain	3405	chr6_mann_hap4	4683263	+	3888574	3888637	chr12	132349534	-	63727404	63727467	1360984
+63
+
+chain	3368	chr6_mann_hap4	4683263	+	3807881	3807940	chr10	135374737	-	122033518	122033577	24304357
+59
+
+chain	3334	chr6_mann_hap4	4683263	+	3942243	3942283	chr16	88827254	-	56809950	56809989	35201127
+19	1	0
+20
+
+chain	3303	chr6_mann_hap4	4683263	+	3972756	3972791	chr1	247249719	+	73729369	73729404	27153556
+35
+
+chain	3293	chr6_mann_hap4	4683263	+	4158373	4158408	chr7	158821424	-	26273345	26273380	30505739
+35
+
+chain	3293	chr6_mann_hap4	4683263	+	3825694	3825729	chr16	88827254	-	56536304	56536339	35220873
+35
+
+chain	3290	chr6_mann_hap4	4683263	+	2574386	2574448	chr8	146274826	+	34715687	34715749	20565863
+62
+
+chain	3284	chr6_mann_hap4	4683263	+	3962434	3962469	chr7	158821424	-	75715212	75715247	35222192
+35
+
+chain	3275	chr6_mann_hap4	4683263	+	1138144	1138179	chr6	170899992	+	29990315	29990350	35226053
+35
+
+chain	3266	chr6_mann_hap4	4683263	+	3971216	3971273	chr3	199501827	-	22333077	22333134	22107564
+57
+
+chain	3253	chr6_mann_hap4	4683263	+	4099622	4099676	chr19	63811651	+	42514641	42514695	4288250
+54
+
+chain	3205	chr6_mann_hap4	4683263	+	4070992	4071055	chr1	247249719	+	196464086	196464149	10251011
+63
+
+chain	3203	chr6_mann_hap4	4683263	+	3824817	3824851	chr3	199501827	-	28583100	28583134	30999626
+34
+
+chain	3180	chr6_mann_hap4	4683263	+	3893634	3893669	chr18	76117153	-	75290002	75290037	35254886
+35
+
+chain	3155	chr6_mann_hap4	4683263	+	4006480	4006566	chr8	146274826	-	94420792	94420878	3680803
+86
+
+chain	3107	chr6_mann_hap4	4683263	+	3887907	3887940	chr2	242951149	+	18209140	18209173	23522185
+33
+
+chain	3079	chr6_mann_hap4	4683263	+	2571537	2573841	chr6	170899992	+	126959071	126961365	3502977
+2	117	114
+67	2060	2053
+58
+
+chain	3064	chr6_mann_hap4	4683263	+	2303363	2303395	chr6	170899992	+	31062756	31062788	33922186
+32
+
+chain	3031	chr6_mann_hap4	4683263	+	3886413	3886445	chr2	242951149	+	186256011	186256043	29433855
+32
+
+chain	3016	chr6_mann_hap4	4683263	+	2311494	2311526	chrX	154913754	+	79124038	79124070	32077336
+32
+
+chain	2979	chr6_mann_hap4	4683263	+	3855470	3855504	chr3	199501827	+	4042271	4042305	1799588
+34
+
+chain	2964	chr6_mann_hap4	4683263	+	1196678	1196709	chrX	154913754	+	72461549	72461580	26677785
+31
+
+chain	2956	chr6_mann_hap4	4683263	+	3866093	3866129	chr1	247249719	-	141171387	141171423	35318155
+36
+
+chain	2906	chr6_mann_hap4	4683263	+	3932526	3932557	chr9	140273252	+	22587602	22587633	35284164
+31
+
+chain	2906	chr6_mann_hap4	4683263	+	3886745	3886778	chr8	146274826	-	118435747	118435780	35339754
+33
+
+chain	2872	chr6_mann_hap4	4683263	+	3971341	3971392	chr12	132349534	+	117591668	117591719	18400010
+51
+
+chain	2863	chr6_mann_hap4	4683263	+	2569913	2569984	chrX	154913754	+	15788619	15788690	15376547
+71
+
+chain	2850	chr6_mann_hap4	4683263	+	3872455	3872908	chr4	191273063	+	173531459	173531912	22440020
+66	326	326
+61
+
+chain	2847	chr6_mann_hap4	4683263	+	3886091	3886121	chr14	106368585	+	78698582	78698612	35350318
+30
+
+chain	2843	chr6_mann_hap4	4683263	+	4080743	4081595	chr9	140273252	+	76002383	76002587	2839818
+50	737	89
+65
+
+chain	2810	chr6_mann_hap4	4683263	+	3944503	3944532	chr1	247249719	-	39748406	39748435	35362931
+29
+
+chain	2797	chr6_mann_hap4	4683263	+	4484961	4485121	chr19	63811651	-	12967948	12968184	2658963
+29	70	70
+17	13	89
+31
+
+chain	2786	chr6_mann_hap4	4683263	+	3891682	3891777	chrX	154913754	-	85953788	85953883	2307593
+61	1	1
+33
+
+chain	2782	chr6_mann_hap4	4683263	+	2656861	2656923	chr8	146274826	-	144762871	144762933	15570304
+62
+
+chain	2778	chr6_mann_hap4	4683263	+	4115342	4115371	chr5	180857866	-	91122400	91122429	5117904
+29
+
+chain	2753	chr6_mann_hap4	4683263	+	1196549	1196608	chr12	132349534	+	50414483	50414542	22637630
+59
+
+chain	2740	chr6_mann_hap4	4683263	+	3887725	3887787	chr5	180857866	+	121612373	121612435	20400020
+62
+
+chain	2671	chr6_mann_hap4	4683263	+	2578539	2578598	chr9	140273252	-	60326471	60326530	21074054
+59
+
+chain	2624	chr6_mann_hap4	4683263	+	2643215	2643265	chr12	132349534	-	76880491	76880541	6796930
+50
+
+chain	2617	chr6_mann_hap4	4683263	+	4484579	4484636	chr11	134452384	-	70226060	70226117	2741353
+57
+
+chain	2617	chr6_mann_hap4	4683263	+	3951354	3951381	chrX	154913754	+	30529839	30529866	35092612
+27
+
+chain	2616	chr6_mann_hap4	4683263	+	3927817	3927913	chr6	170899992	-	159168046	159168142	3467812
+96
+
+chain	2596	chr6_mann_hap4	4683263	+	3973087	3973114	chr3	199501827	+	56590732	56590759	32896512
+27
+
+chain	2531	chr6_mann_hap4	4683263	+	3971895	3971925	chr3	199501827	+	180701028	180701058	25637788
+30
+
+chain	2466	chr6_mann_hap4	4683263	+	3824382	3824409	chr3	199501827	-	192093673	192093700	31748081
+27
+
+chain	2451	chr6_mann_hap4	4683263	+	3971666	3971716	chr2	242951149	+	181100921	181100971	18669842
+50
+
+chain	2440	chr6_mann_hap4	4683263	+	2572049	2572075	chr12	132349534	-	35755450	35755476	32394235
+26
+
+chain	2374	chr6_mann_hap4	4683263	+	3950266	3950291	chr1	247249719	-	157289487	157289512	35464629
+25
+
+chain	2364	chr6_mann_hap4	4683263	+	3819663	3819687	chr11	134452384	-	104747367	104747391	35468112
+24
+
+chain	2345	chr6_mann_hap4	4683263	+	2657279	2657339	chr9	140273252	+	101754649	101754709	22265309
+60
+
+chain	2313	chr6_mann_hap4	4683263	+	3890591	3890665	chr6	170899992	+	55285173	55285247	1894941
+74
+
+chain	2296	chr6_mann_hap4	4683263	+	2570274	2570347	chr10	135374737	+	81973802	81973875	17155090
+73
+
+chain	2290	chr6_mann_hap4	4683263	+	1157821	1157878	chr1	247249719	+	222604152	222604209	12152480
+57
+
+chain	2274	chr6_mann_hap4	4683263	+	3934768	3934792	chr3	199501827	+	107081622	107081646	35482673
+24
+
+chain	2265	chr6_mann_hap4	4683263	+	3887959	3887983	chrX	154913754	-	124439583	124439607	35484926
+24
+
+chain	2258	chr6_mann_hap4	4683263	+	3824852	3824876	chrX	154913754	-	132191215	132191239	25992080
+24
+
+chain	2257	chr6_mann_hap4	4683263	+	4006990	4007066	chr6	170899992	-	104582331	104582407	2576654
+76
+
+chain	2255	chr6_mann_hap4	4683263	+	4159118	4159146	chr8	146274826	+	40415014	40415042	30252789
+28
+
+chain	2253	chr6_mann_hap4	4683263	+	2653160	2653184	chr2	242951149	+	186158239	186158263	32681827
+24
+
+chain	2249	chr6_mann_hap4	4683263	+	4006455	4006480	chr5	180857866	-	144759522	144759547	4178637
+25
+
+chain	2214	chr6_mann_hap4	4683263	+	3971284	3971340	chr11	134452384	+	87181255	87181311	21919084
+56
+
+chain	2211	chr6_mann_hap4	4683263	+	3809943	3809993	chr20	62435964	-	30230318	30230368	23880964
+50
+
+chain	2210	chr6_mann_hap4	4683263	+	3835038	3835061	chr1	247249719	+	53077746	53077769	35492698
+23
+
+chain	2194	chr6_mann_hap4	4683263	+	1157606	1157646	chrX	154913754	-	101365357	101365397	11073773
+40
+
+chain	2181	chr6_mann_hap4	4683263	+	4081491	4081530	chrX	154913754	-	85175003	85175042	4116465
+39
+
+chain	2160	chr6_mann_hap4	4683263	+	3942219	3942243	chr1	247249719	-	214605983	214606007	35201144
+24
+
+chain	2156	chr6_mann_hap4	4683263	+	1145077	1145100	chr1	247249719	+	41331153	41331176	35506781
+23
+
+chain	2149	chr6_mann_hap4	4683263	+	4099822	4099870	chr9	140273252	+	102195866	102195914	4118428
+48
+
+chain	2146	chr6_mann_hap4	4683263	+	1143811	1143872	chr12	132349534	+	104221177	104221238	23825289
+61
+
+chain	2141	chr6_mann_hap4	4683263	+	4081286	4081346	chr20	62435964	-	10135341	10135401	5446947
+60
+
+chain	2127	chr6_mann_hap4	4683263	+	4045825	4045849	chr6	170899992	+	156402969	156402993	17746
+24
+
+chain	2123	chr6_mann_hap4	4683263	+	4007634	4007684	chr1	247249719	-	1324986	1325036	2693877
+50
+
+chain	2120	chr6_mann_hap4	4683263	+	3892019	3892104	chr14	106368585	+	35729289	35729374	2483709
+85
+
+chain	2099	chr6_mann_hap4	4683263	+	1196341	1196363	chr8	146274826	+	94956096	94956118	22553599
+22
+
+chain	2075	chr6_mann_hap4	4683263	+	4011497	4011566	chr6	170899992	-	138358121	138358190	21792053
+69
+
+chain	2039	chr6_mann_hap4	4683263	+	2571934	2572049	chr7	158821424	+	116148574	116148689	3252915
+115
+
+chain	2027	chr6_mann_hap4	4683263	+	3809848	3810361	chr5	180857866	-	108598115	108598712	24999557
+55	397	481
+61
+
+chain	2014	chr6_mann_hap4	4683263	+	4099976	4100031	chr3	199501827	+	188094551	188094606	22317615
+55
+
+chain	2010	chr6_mann_hap4	4683263	+	3935813	3935834	chrX	154913754	+	30529615	30529636	35529704
+21
+
+chain	2000	chr6_mann_hap4	4683263	+	1157778	1157811	chr4	191273063	+	153905795	153905828	8127682
+33
+
+chain	2000	chr6_mann_hap4	4683263	+	4158272	4158321	chr6	170899992	-	39092714	39092763	20395916
+49
+
+chain	1976	chr6_mann_hap4	4683263	+	1229873	1229899	chr9	140273252	+	92917708	92917734	26443005
+26
+
+chain	1931	chr6_mann_hap4	4683263	+	3926709	3926764	chr3	199501827	+	181243093	181243148	3766615
+55
+
+chain	1921	chr6_mann_hap4	4683263	+	4158321	4158373	chr11	134452384	+	132133410	132133462	17748702
+52
+
+chain	1919	chr6_mann_hap4	4683263	+	2511945	2511997	chr4	191273063	+	131153712	131153764	15450947
+52
+
+chain	1907	chr6_mann_hap4	4683263	+	2572521	2573169	chr12	132349534	-	49839290	49839926	3124499
+58	540	528
+50
+
+chain	1805	chr6_mann_hap4	4683263	+	3891144	3891220	chrX	154913754	+	107411806	107411882	2933427
+76
+
+chain	1798	chr6_mann_hap4	4683263	+	3870776	3870808	chr5	180857866	+	161128758	161128790	11651368
+32
+
+chain	1772	chr6_mann_hap4	4683263	+	4007367	4007430	chr16	88827254	-	2018363	2018426	2212652
+63
+
+chain	1763	chr6_mann_hap4	4683263	+	4080494	4080567	chr14	106368585	-	71004341	71004414	2917022
+73
+
+chain	1747	chr6_mann_hap4	4683263	+	2573669	2574306	chr1	247249719	+	71359925	71360557	7388765
+54	521	516
+62
+
+chain	1746	chr6_mann_hap4	4683263	+	3990700	3990741	chr6	170899992	+	88517978	88518019	3345644
+17	14	14
+10
+
+chain	1730	chr6_mann_hap4	4683263	+	2653102	2653160	chr15	100338915	+	50804927	50804985	23248991
+58
+
+chain	1696	chr6_mann_hap4	4683263	+	4006820	4006866	chrX	154913754	-	37494215	37494261	4107897
+46
+
+chain	1694	chr6_mann_hap4	4683263	+	4099748	4099799	chr1	247249719	+	46568424	46568475	18602659
+51
+
+chain	1690	chr6_mann_hap4	4683263	+	4158763	4158820	chr11	134452384	-	120264308	120264365	24918211
+57
+
+chain	1684	chr6_mann_hap4	4683263	+	3891607	3891668	chr9	140273252	-	45892574	45892635	2466690
+61
+
+chain	1664	chr6_mann_hap4	4683263	+	2656660	2656721	chr14	106368585	-	51104394	51104455	13584343
+61
+
+chain	1636	chr6_mann_hap4	4683263	+	3926463	3926504	chr15	100338915	-	30465019	30465060	3027934
+41
+
+chain	1600	chr6_mann_hap4	4683263	+	3973114	3973143	chr13	114142980	-	18785120	18785149	24380543
+29
+
+chain	1599	chr6_mann_hap4	4683263	+	3971096	3971159	chr8	146274826	+	126278291	126278354	19925893
+63
+
+chain	1591	chr6_mann_hap4	4683263	+	2511679	2511736	chr12	132349534	+	73083054	73083111	11729778
+57
+
+chain	1570	chr6_mann_hap4	4683263	+	4158461	4158521	chr12	132349534	+	40906087	40906147	15863002
+60
+
+chain	1569	chr6_mann_hap4	4683263	+	2569611	2569737	chr1	247249719	+	93626635	93626761	9616359
+126
+
+chain	1566	chr6_mann_hap4	4683263	+	3927068	3927110	chr4	191273063	-	20598961	20599003	3502725
+42
+
+chain	1557	chr6_mann_hap4	4683263	+	3927759	3927810	chrX	154913754	+	117055564	117055615	4598072
+51
+
+chain	1477	chr6_mann_hap4	4683263	+	3891945	3892006	chr10	135374737	+	87524787	87524848	2722375
+61
+
+chain	1473	chr6_mann_hap4	4683263	+	4080991	4081045	chr17	78774742	+	33000128	33000182	3754636
+54
+
+chain	1460	chr6_mann_hap4	4683263	+	3890832	3890888	chr8	146274826	+	57494812	57494868	2709746
+56
+
+chain	1455	chr6_mann_hap4	4683263	+	4007066	4007094	chr6	170899992	-	11011124	11011152	3343257
+28
+
+chain	1453	chr6_mann_hap4	4683263	+	3891391	3891437	chr8	146274826	+	51746327	51746373	3488858
+46
+
+chain	1424	chr6_mann_hap4	4683263	+	2571563	2571641	chr9	140273252	-	113447512	113447590	4199477
+78
+
+chain	1424	chr6_mann_hap4	4683263	+	3871462	3871507	chr1	247249719	-	200018115	200018160	11574863
+45
+
+chain	1406	chr6_mann_hap4	4683263	+	3890773	3890831	chr4	191273063	+	55621101	55621159	1970745
+58
+
+chain	1406	chr6_mann_hap4	4683263	+	4158521	4158575	chr1	247249719	+	49943386	49943440	15855508
+54
+
+chain	1397	chr6_mann_hap4	4683263	+	3890211	3890236	chr10	135374737	-	71340044	71340069	2299991
+25
+
+chain	1392	chr6_mann_hap4	4683263	+	3971636	3971666	chr3	199501827	-	51819316	51819346	23522768
+30
+
+chain	1373	chr6_mann_hap4	4683263	+	2511768	2511834	chr5	180857866	+	26360477	26360543	20230569
+66
+
+chain	1361	chr6_mann_hap4	4683263	+	4070248	4070282	chr4	191273063	+	53456808	53456842	4749510
+34
+
+chain	1354	chr6_mann_hap4	4683263	+	1158001	1158055	chr4	191273063	+	534307	534361	14280054
+54
+
+chain	1345	chr6_mann_hap4	4683263	+	3855264	3855317	chrX	154913754	+	62583130	62583183	22642552
+53
+
+chain	1311	chr6_mann_hap4	4683263	+	3990016	3990044	chr12	132349534	-	10940806	10940834	3119062
+28
+
+chain	1285	chr6_mann_hap4	4683263	+	2741741	2741814	chrX	154913754	-	101841552	101841726	4764485
+55	2	103
+16
+
+chain	1271	chr6_mann_hap4	4683263	+	4485264	4485308	chr2	242951149	+	42686810	42686854	6287037
+44
+
+chain	1232	chr6_mann_hap4	4683263	+	3891286	3891326	chr4	191273063	+	121886954	121886994	3320472
+40
+
+chain	1228	chr6_mann_hap4	4683263	+	4081088	4081138	chr7	158821424	+	22807318	22807368	2860523
+50
+
+chain	1216	chr6_mann_hap4	4683263	+	3886222	3886374	chr6	170899992	+	81566192	81566344	3344709
+59	17	17
+76
+
+chain	1200	chr6_mann_hap4	4683263	+	4080922	4080972	chrX	154913754	-	78005269	78005319	2937486
+50
+
+chain	1196	chr6_mann_hap4	4683263	+	2642964	2643022	chr13	114142980	-	87864434	87864492	20517842
+58
+
+chain	1192	chr6_mann_hap4	4683263	+	3871650	3871705	chr15	100338915	-	25838674	25838729	13558940
+55
+
+chain	1173	chr6_mann_hap4	4683263	+	3856498	3856532	chr11	134452384	-	32778066	32778100	22709110
+34
+
+chain	1168	chr6_mann_hap4	4683263	+	3891494	3891535	chr15	100338915	+	80079703	80079744	3327446
+41
+
+chain	1163	chr6_mann_hap4	4683263	+	3926838	3926870	chr6	170899992	+	66742660	66742692	3612231
+32
+
+chain	1163	chr6_mann_hap4	4683263	+	3887419	3887473	chrX	154913754	+	89074833	89074887	25104537
+54
+
+chain	1160	chr6_mann_hap4	4683263	+	2573343	2573371	chrX	154913754	+	56853117	56853145	21155199
+28
+
+chain	1149	chr6_mann_hap4	4683263	+	3856532	3856615	chr10	135374737	+	110407978	110408061	14842132
+83
+
+chain	1128	chr6_mann_hap4	4683263	+	2742956	2742992	chr13	114142980	-	41462025	41462061	4150569
+36
+
+chain	1122	chr6_mann_hap4	4683263	+	4080072	4080135	chr19	63811651	+	62685625	62685688	7787530
+63
+
+chain	1120	chr6_mann_hap4	4683263	+	3927728	3927759	chr20	62435964	+	16923180	16923211	7977510
+31
+
+chain	1120	chr6_mann_hap4	4683263	+	3887060	3887131	chr11	134452384	-	72766723	72766794	12188515
+71
+
+chain	1113	chr6_mann_hap4	4683263	+	2570192	2570259	chr2	242951149	-	140069145	140069212	8748780
+67
+
+chain	1096	chr6_mann_hap4	4683263	+	2643706	2643734	chr15	100338915	+	86869156	86869184	12823891
+28
+
+chain	1076	chr6_mann_hap4	4683263	+	3892300	3892346	chr11	134452384	+	14828539	14828585	2361427
+46
+
+chain	1041	chr6_mann_hap4	4683263	+	4080135	4080193	chr6	170899992	-	117620920	117620978	4257272
+58
+
+chain	1023	chr6_mann_hap4	4683263	+	4007334	4007366	chr9	140273252	+	86970417	86970449	7865338
+32
+
+chain	1010	chr6_mann_hap4	4683263	+	4082082	4082129	chr3	199501827	+	184810220	184810267	11973355
+47
+
+chain	998	chr6_mann_hap4	4683263	+	3886377	3886573	chrX	154913754	-	91757557	91757751	5295832
+36	35	33
+55	3	3
+67
+
+chain	990	chr6_mann_hap4	4683263	+	4007430	4007464	chr4	191273063	+	5326352	5326386	2516557
+34
+
+chain	984	chr6_mann_hap4	4683263	+	4072955	4073012	chr5	180857866	-	58582170	58582227	6154457
+57
+
+chain	967	chr6_mann_hap4	4683263	+	2573177	2573236	chr6	170899992	+	103362020	103362079	14394857
+59
+
+chain	965	chr6_mann_hap4	4683263	+	3891326	3891365	chr9	140273252	+	71286813	71286852	2824412
+39
+
+chain	945	chr6_mann_hap4	4683263	+	3694820	3694851	chr14	106368585	-	6650576	6650607	2401116
+31
+
+chain	927	chr6_mann_hap4	4683263	+	2572422	2572476	chr15	100338915	-	47557741	47557795	3382810
+54
+
+chain	920	chr6_mann_hap4	4683263	+	1157878	1157917	chr16	88827254	-	23604715	23604754	19693069
+39
+
+chain	898	chr6_mann_hap4	4683263	+	4081045	4081072	chr22	49691432	-	26647849	26647876	3840718
+27
+
+chain	895	chr6_mann_hap4	4683263	+	3891777	3891813	chr14	106368585	-	61283307	61283343	2761593
+36
+
+chain	893	chr6_mann_hap4	4683263	+	2570451	2570505	chr3	199501827	+	23577885	23577939	11107673
+54
+
+chain	890	chr6_mann_hap4	4683263	+	3892242	3892300	chr1	247249719	-	65356530	65356588	2061731
+58
+
+chain	880	chr6_mann_hap4	4683263	+	2570034	2570140	chr20	62435964	-	37396821	37396927	8091728
+106
+
+chain	869	chr6_mann_hap4	4683263	+	3887839	3887907	chr6	170899992	+	169492007	169492075	20963963
+68
+
+chain	868	chr6_mann_hap4	4683263	+	3891249	3891286	chrX	154913754	-	77282087	77282124	4725533
+37
+
+chain	836	chr6_mann_hap4	4683263	+	3890695	3890723	chrX	154913754	+	120843366	120843394	2304611
+28
+
+chain	836	chr6_mann_hap4	4683263	+	2570399	2570451	chr6	170899992	-	98122344	98122396	3449700
+52
+
+chain	827	chr6_mann_hap4	4683263	+	3855371	3855442	chr15	100338915	-	22701000	22701071	11814601
+71
+
+chain	815	chr6_mann_hap4	4683263	+	2572376	2572422	chr8	146274826	-	36260073	36260119	3779418
+46
+
+chain	812	chr6_mann_hap4	4683263	+	2571127	2571156	chr4	191273063	+	177039024	177039053	12879824
+29
+
+chain	785	chr6_mann_hap4	4683263	+	2569744	2569799	chr10	135374737	-	48892377	48892432	10678423
+55
+
+chain	771	chr6_mann_hap4	4683263	+	2573374	2573466	chr4	191273063	-	179199127	179199219	9189435
+92
+
+chain	767	chr6_mann_hap4	4683263	+	2511738	2511768	chr12	132349534	+	6687829	6687859	23736981
+30
+
+chain	753	chr6_mann_hap4	4683263	+	3873530	3873605	chr13	114142980	+	107345301	107345376	25181199
+75
+
+chain	746	chr6_mann_hap4	4683263	+	2572477	2572521	chrX	154913754	+	101830803	101830847	3498092
+44
+
+chain	715	chr6_mann_hap4	4683263	+	3891220	3891248	chr1	247249719	-	137161636	137161664	4268110
+28
+
+chain	711	chr6_mann_hap4	4683263	+	3892346	3892371	chr5	180857866	-	112926636	112926661	14369717
+25
+
+chain	705	chr6_mann_hap4	4683263	+	3891557	3891590	chr20	62435964	+	38686583	38686616	3341082
+33
+
+chain	701	chr6_mann_hap4	4683263	+	4158699	4158752	chr6	170899992	+	104136271	104136324	24904048
+53
+
+chain	698	chr6_mann_hap4	4683263	+	3885778	3885835	chrX	154913754	-	89052462	89052519	24703469
+57
+
+chain	694	chr6_mann_hap4	4683263	+	3890564	3890590	chr20	62435964	+	53857851	53857877	2569420
+26
+
+chain	686	chr6_mann_hap4	4683263	+	4080461	4080493	chr9	140273252	+	6612523	6612555	3647698
+32
+
+chain	684	chr6_mann_hap4	4683263	+	2569065	2569115	chr10	135374737	+	37248665	37248715	24627179
+50
+
+chain	630	chr6_mann_hap4	4683263	+	3887534	3887605	chr7	158821424	+	132658309	132658380	10507147
+71
+
+chain	626	chr6_mann_hap4	4683263	+	2571287	2571318	chr20	62435964	-	10143997	10144028	3304786
+31
+
+chain	604	chr6_mann_hap4	4683263	+	1158203	1158229	chrX	154913754	-	101148638	101148664	11583043
+26
+
+chain	598	chr6_mann_hap4	4683263	+	2573593	2573648	chr4	191273063	-	105845249	105845304	24500343
+55
+
+chain	587	chr6_mann_hap4	4683263	+	4081958	4081983	chr17	78774742	+	38379379	38379404	3048972
+25
+
+chain	582	chr6_mann_hap4	4683263	+	1229585	1229648	chrX	154913754	-	143767987	143768050	25106055
+63
+
+chain	511	chr6_mann_hap4	4683263	+	1158055	1158090	chr3	199501827	+	56593596	56593631	24560538
+35
+
+chain	500	chr6_mann_hap4	4683263	+	3810617	3810668	chr2	242951149	-	179547194	179547245	25332432
+51
+
+chain	484	chr6_mann_hap4	4683263	+	3874010	3874062	chr2	242951149	-	202196458	202196510	23986516
+52
+
+chain	477	chr6_mann_hap4	4683263	+	4080303	4080328	chr1	247249719	+	23702472	23702497	3860771
+25
+
+chain	433	chr6_mann_hap4	4683263	+	3970685	3970735	chr12	132349534	+	80047789	80047839	27634717
+50
+
+chain	409	chr6_mann_hap4	4683263	+	2572208	2572259	chr12	132349534	+	9890446	9890497	14217469
+51
+
+chain	405	chr6_mann_hap4	4683263	+	3838348	3838386	chr6	170899992	+	85325597	85325635	11867781
+38
+
+chain	400	chr6_mann_hap4	4683263	+	2570347	2570381	chr20	62435964	+	18791073	18791107	4207227
+34
+
+chain	399	chr6_mann_hap4	4683263	+	3891365	3891391	chr14	106368585	-	67199393	67199419	2293377
+26
+
+chain	392	chr6_mann_hap4	4683263	+	2573293	2573343	chr7	158821424	+	83182800	83182850	10714169
+50
+
+chain	389	chr6_mann_hap4	4683263	+	2574727	2574788	chr5	180857866	+	78276420	78276481	6835510
+61
+
+chain	320	chr6_mann_hap4	4683263	+	2572172	2572208	chrX	154913754	-	2978832	2978868	15103888
+36
+
+chain	315	chr6_mann_hap4	4683263	+	2572091	2572150	chr12	132349534	+	56700130	56700189	16626895
+59
+
+chain	314	chr6_mann_hap4	4683263	+	3838291	3838335	chr7	158821424	+	152689672	152689716	19362320
+44
+
+chain	313	chr6_mann_hap4	4683263	+	3838601	3838636	chr8	146274826	+	137657008	137657043	12505292
+35
+
+chain	281	chr6_mann_hap4	4683263	+	2568901	2568956	chr11	134452384	-	27880406	27880461	26521414
+55
+
+chain	157	chr6_mann_hap4	4683263	+	4157054	4157110	chr2	242951149	-	84321569	84321625	30149802
+56
+
+chain	327477534	chr6_mcf_hap5	4833398	+	0	4833398	chr6	170899992	+	28804582	33467620	43
+932	3	0
+804	0	1
+2406	2	0
+88370	0	6
+2011	17	17
+871	93	85
+100	12	14
+2623	33	29
+3737	1	1
+39	1	1
+3903	2	0
+844	0	1
+5198	0	1
+2452	0	1
+14547	0	1
+603	2	0
+4648	0	3
+887	2902	2902
+668	1	0
+3862	0	6
+1025	160	0
+3444	3	0
+1791	1	0
+2207	0	3
+1827	1	0
+3220	9	0
+5157	0	4
+1394	1	0
+279	0	2
+71	0	4
+163	1	1
+31	1	1
+280	8	0
+1059	0	2
+1373	40	40
+402	1	0
+642	1	3
+746	0	2
+1268	2	0
+267	0	1
+1868	1	1
+44	1	1
+8066	7328	7328
+1695	2	1
+4264	0	1
+3195	0	2
+2504	39	38
+70	1	1
+1649	1	0
+953	0	1
+295	1	1
+32	0	6
+661	4	0
+5298	1	0
+1243	1	0
+122	0	1
+6151	2	0
+1123	0	9
+2073	1	0
+611	1	0
+1053	5	5
+71	0	3
+562	11	11
+8681	53599	53599
+1476	0	3
+3442	1	1
+61	1	1
+472	1	0
+1606	1	0
+2825	1	1
+15	1	1
+2498	1	0
+1445	2	0
+3490	0	1
+31	1	1
+4168	1	0
+4249	0	3
+27	0	1
+660	1	3
+1336	2	1
+3805	1	1
+20	1	1
+2330	0	4
+782	0	3
+3397	0	3
+46	1	2
+2599	7	0
+167	0	1
+670	8	0
+686	13	15
+1313	1	1
+41	1	1
+5555	1	1
+31	1	1
+5562	0	11
+82	1	1
+1227	0	1
+1556	1	0
+817	2	0
+22	8	0
+11441	0	4
+2264	0	2
+2164	0	6
+5363	1	1
+20	1	1
+45	1	0
+1351	1	0
+1292	0	2
+6063	8	1
+3826	10	0
+7034	0	8
+1703	6	6
+72	20447	20447
+2264	0	3
+5437	5	0
+3414	35	35
+12896	0	4
+3018	1	1
+24	1	1
+2310	7	7
+11460	1	1
+28	1	1
+2157	0	4
+46	8	0
+8748	6	0
+8539	1	0
+753	1	2
+651	8	8
+7720	1	0
+2972	1	0
+6912	1	1
+26	1	1
+7721	68853	68853
+7209	1	0
+313	21	0
+2014	2	0
+631	1	1
+120	1	1
+1202	1	1
+84	0	1
+1481	10	0
+785	34	0
+493	0	2
+283	11	1
+513	67	67
+212	16	16
+1192	0	1
+3112	1	0
+25400	9	9
+6993	1	0
+675	1	0
+20032	0	3
+2544	0	318
+1507	2	0
+313	4	0
+2659	1	1
+25	1	1
+1461	4	1
+364	1	1
+33	1	1
+1003	0	1
+1656	1	1
+42	1	1
+3874	2	0
+149	0	1
+6897	0	3
+40	1	1
+1374	1	0
+5757	5	0
+1254	17	17
+2864	0	143
+4107	0	6
+5270	8989	8989
+14121	1	0
+19254	2	0
+7864	2	0
+635	1	0
+39010	1	0
+13943	1	1
+32	1	1
+509	1	1
+73	1	1
+5335	22	16
+1218	1	0
+1638	6	6
+228	1	1
+45	1	1
+2048	0	1
+463	1	0
+24243	1	1
+19	1	1
+7240	22	0
+3284	1	1
+29	1	1
+8552	0	4
+3962	7	16
+474	1	1
+31	1	1
+549	2	0
+5745	1	0
+5097	1	0
+34650	0	1
+16931	0	1
+2053	1	7
+1384	3	1
+442	3	4
+1804	1	1
+101	1	1
+1465	2	0
+1230	2	0
+3399	0	8
+743	0	1
+502	0	1
+732	0	1
+5371	0	1
+1633	6	5
+4859	0	1
+3043	0	1
+1108	0	2
+1448	1	0
+2959	10	10
+6054	0	4
+1927	18	24
+890	1	1
+16	1	0
+2617	2	0
+4921	1	0
+570	2	0
+8231	1	1
+25	1	0
+1193	0	11
+350	0	1
+4470	1	1
+41	1	1
+942	4	5
+1892	0	5
+15	1	1
+2144	1	1
+194	1	1
+938	0	1
+141	5	5
+237	3	8
+99	31	31
+53	11	0
+364	4	3
+201	1	1
+42	1	1
+56	1	1
+115	1	0
+67	16	16
+244	1	1
+54	5	5
+929	1	1
+21	1	1
+126	0	3
+830	0	14
+56	1	1
+525	0	2
+782	15	15
+810	1	0
+272	8	8
+145	1	1
+89	1	1
+592	1	1
+49	1	1
+352	0	1
+142	1	1
+30	1	1
+95	1	1
+45	1	1
+227	1	1
+53	1	1
+130	1	1
+18	1	1
+138	1	1
+90	1	1
+129	1	1
+39	1	1
+50	1	1
+79	1	1
+117	1	1
+31	1	1
+240	5	5
+57	1	1
+152	1	1
+30	1	1
+177	5	5
+345	1	1
+39	1	1
+504	18	18
+662	1	1
+74	1	1
+248	1	1
+34	1	1
+1507	0	10
+1051	0	2611
+680	0	1
+1537	0	19
+74	1	0
+137	50	11
+112	0	18
+24	1	1
+1927	13	13
+1082	15046	15046
+185	0	1
+70	1	1
+2835	4	4
+163	15	15
+685	0	1
+1508	1	0
+533	14	0
+441	0	13
+2121	1	1
+40	1	1
+2754	0	4
+37	1	1
+144	8	8
+1040	2	0
+28	1	1
+229	12	12
+201	13	13
+169	19	20
+118	10	12
+1257	0	2
+243	16	16
+73	1	1
+21	1	1
+201	0	14
+116	1	1
+29	1	1
+536	1	0
+1159	0	32
+23	1	1
+674	0	3
+136	1	1
+48	1	1
+330	9	9
+1108	1	1
+98	1	1
+582	0	2
+713	7	7
+89	1	0
+293	9	8
+350	6	6
+145	1	1
+41	1	1
+681	1	1
+43	1	1
+1121	16	16
+964	17	17
+198	0	7
+105	1	1
+40	1	1
+95	13	13
+247	1	1
+19	1	1
+2044	7	8
+2512	0	15
+2982	4	0
+3135	1	2
+1698	13	13
+15862	0	1
+925	0	191
+23	15	1
+23	0	1
+25	1	1
+7717	1	1
+40	1	1
+758	1	1
+46	1	1
+5530	11	9
+3326	1	1
+37	1	1
+2148	2	1
+4594	0	4
+7923	1	1
+26	5	5
+3475	24	0
+8	1	1
+566	4	0
+141	0	1
+2078	24	24
+171	18	18
+2570	0	6
+1709	4	0
+3265	0	2
+2235	17	16
+2946	0	372
+2644	31	31
+92	1	1
+35	1	1
+705	321	0
+3157	40	40
+718	0	4
+787	1	1
+34	1	1
+927	4	4
+103	0	8
+2376	0	1
+993	1	1
+31	1	1
+2654	1	1
+44	1	1
+208	4	1
+1022	11763	11699
+85	98	98
+60	2515	8169
+103	11	11
+41	1	1
+72	4	4
+76	1	1
+70	5	5
+83	1	1
+117	1	1
+130	1	1
+44	1	1
+414	1	1
+152	1	0
+218	1	1
+161	1	0
+120	14	14
+145	1	1
+49	4	4
+72	1	1
+53	19	19
+111	2	2
+32	3	3
+554	0	1
+336	12	12
+54	24	24
+171	0	6
+90	1	1
+28	1	1
+142	16	16
+36	1	1
+428	1	1
+16	1	1
+338	1	1
+31	1	1
+294	1	1
+92	0	1
+129	13	14
+602	1	1
+112	1	1
+247	1	1
+80	1	1
+173	1	1
+44	1	5
+497	1	1
+38	1	1
+98	1	1
+130	1	1
+319	1	1
+16	1	1
+59	1	1
+82	1	1
+141	1	1
+23	1	1
+241	1	1
+26	1	1
+109	3	3
+72	0	3
+19	1	1
+510	1	1
+36	1	1
+162	2	2
+15	1	1
+145	1	1
+28	1	1
+120	0	3
+93	1	2
+24	0	9
+169	12	0
+292	9911	10000
+401	1	1
+27	1	1
+296	1	1
+120	1	1
+357	1	1
+107	2	0
+31	1	1
+83	89	0
+194	1	1
+33	1	1
+230	1	1
+142	5	5
+108	1	1
+36	1	1
+287	1	1
+19	1	1
+104	1	1
+31	1	1
+144	1	1
+212	1	1
+452	5	6
+148	1	1
+70	1	1
+137	3	3
+67	1	1
+73	22	22
+115	12	12
+142	5	5
+269	15	15
+102	6	6
+93	1	1
+82	1	1
+170	1	1
+22	1	1
+504	2	2
+60	1	1
+150	1	1
+31	1	1
+90	1	1
+15	1	0
+258	6	7
+85	1	1
+77	1	1
+123	2	2
+67	0	1
+56	2	2
+25	1	1
+71	1	1
+28	2	2
+50	1	1
+85	2	2
+66	6	6
+186	1	1
+20	1	1
+67	1	1
+25	1	1
+227	2	2
+155	1	1
+777	1	1
+33	1	2
+26	6	6
+474	1	1
+36	1	1
+151	1	1
+29	1	1
+120	1	1
+23	1	1
+736	127279	40017
+51	5	5
+45	1	1
+53	1	1
+37	1	1
+81	1	1
+369	1	1
+72	15	15
+98	1	1
+53	0	8
+67	2	0
+41	1	1
+92	1	1
+20	1	1
+283	6	6
+70	7	7
+50	1	1
+25	1	1
+225	5	1
+31	1	1
+449	2	1
+10	1	23
+64	4	4
+832	1	0
+492	1	0
+587	0	15
+1821	1	1
+22	1	0
+36	1	1
+73	1	1
+38	1	1
+318	1	1
+20	1	1
+176	13	13
+216	1	1
+17	1	1
+515	0	1
+704	0	4
+153	1	1
+44	1	1
+538	1	1
+30	1	1
+411	0	8
+419	1	1
+34	1	1
+66	15	15
+308	1	1
+49	1	1
+484	1	1
+50	10	8
+1019	17	5
+132	1	1
+50	2	1
+38	1	1
+736	0	1
+50	1	1
+50	1	1
+23	2	1
+156	0	1
+385	15	15
+207	1	1
+92	1	1
+415	1	1
+43	1	1
+52	5	5
+223	2	0
+31	4	0
+17	3	27
+88	13	1
+308	1	1
+43	2	2
+186	0	4
+153	1	1
+69	0	3
+14	1	1
+159	1	1
+92	1	1
+62	1	1
+27	1	1
+443	10	10
+77	1	1
+51	1	1
+604	1	1
+35	1	1
+703	1	1
+32	1	1
+1452	4	0
+259	1	1
+40	1	1
+130	1	1
+87	1	1
+164	105	105
+64	14	15
+87	1	1
+30	1	1
+123	2	2
+91	0	3
+95	1	1
+67	10	0
+631	1	3
+315	1	1
+31	1	1
+315	1	1
+25	3	3
+80	3	0
+45	1	1
+511	1	1
+57	1	1
+3565	0	12
+39	0	1
+5674	16	0
+1327	0	1
+7941	1	1
+26	1	1
+13472	1	1
+48	1	1
+4441	19	0
+741	0	1
+8053	0	1
+3976	1	0
+10503	0	1
+5525	0	2
+306	1	0
+3902	17	4
+3077	0	4
+207	2	0
+1984	8	0
+686	2	0
+10068	0	3
+32266	0	2
+428	0	1
+3832	0	12
+8454	1	0
+524	1	1
+59	1	1
+112	3	3
+50	1	1
+267	0	4
+1464	2	0
+1003	0	1
+4062	1	0
+3850	4	0
+4977	0	1
+2718	1	0
+1588	1	1
+30	4	0
+879	0	1
+1332	18	12
+1688	4	4
+88	1	1
+439	2	0
+209	1	0
+1322	54	54
+893	1	1
+49	1	2
+1773	1	1
+24	1	1
+540	1	1
+41	1	1
+460	1	7
+165	1	1
+45	1	1
+903	1	2
+140	0	1
+36	1	1
+2019	0	1
+657	1	1
+48	1	0
+1329	0	1
+268	1	1
+47	1	1
+336	1	1
+25	2	0
+43	1	1
+1484	1	1
+53	1	1
+1151	1	1
+42	1	1
+1870	1	1
+24	5	5
+853	0	3
+23	0	1
+326	9	9
+131	9	9
+623	0	3
+34	1	1
+809	1	1
+36	1	1
+690	2	0
+44	1	1
+285	8	7
+455	1	1
+32	1	1
+102	1	1
+47	1	1
+4338	0	1
+5273	0	4
+11552	1	0
+409	16	17
+3476	0	1
+2160	0	24
+109	1	1
+3284	0	19
+2586	2	0
+757	1	1
+22	1	1
+860	17	24
+1584	1	0
+1582	0	2
+117	1	0
+1552	3	25
+17	0	4
+16	2	0
+6	10	0
+40	9	0
+10	8	0
+10605	1	0
+4733	1	3
+370	2	0
+1305	0	1
+518	6	0
+646	13	13
+469	1	0
+1072	1	4
+404	163747	163747
+942	4	0
+68	13	1
+2539	25	19
+1982	6	0
+5362	0	9
+10293	1	1
+98	1	1
+1006	1	1
+44	1	1
+518	1	1
+26	0	4
+185	0	1
+30	1	0
+19	1	1
+599	1	1
+22	1	1
+218	1	1
+49	1	1
+362	0	1
+852	0	2
+1066	0	2
+811	21	21
+1434	1	1
+27	1	1
+2116	1	1
+25	1	1
+82	7	7
+625	0	1
+1756	4	4
+93	1	1
+26	1	1
+320	0	3
+2150	1	1
+41	1	1
+1091	2	1
+8378	0	1
+2212	0	2
+671	1	0
+4088	1	1
+34	1	1
+2520	0	1
+1933	4	3
+2567	0	5
+1677	1	1
+29	1	1
+1829	12	0
+4788	13	0
+253	2	1
+204	0	1
+128	1	0
+4271	0	1
+6896	0	1
+2766	1	0
+2234	1	1
+52	1	1
+1098	1	1
+37	1	1
+3385	22337	22337
+10967	0	4
+6064	0	1
+10170	0	8
+17213	1	0
+6908	1	0
+328	1	0
+53416	3	2
+4463	1	0
+2057	0	1
+15162	1	0
+25886	3	1
+12500	29	0
+4926	0	1
+9038	0	1
+26499	0	1
+12538	0	1
+34918	97959	97959
+758	4	0
+150	1	0
+3128	1	0
+1300	0	1
+148	1	0
+1534	0	1
+488	0	1
+429	3	5
+299	2	0
+427	7	7
+1914	14	14
+1556	1	1
+28	1	1
+1138	78	0
+409	0	1
+985	22	23
+2430	1	0
+190	8	8
+2034	3	1
+5337	42	42
+1017	1	1
+34	1	1
+485	1	0
+348	7	0
+770	1	1
+8	1	0
+22	0	13
+64	1	1
+1358	0	1
+302	0	1
+964	0	1
+610	0	1
+906	12	0
+1331	0	8
+1784	0	1
+463	0	1
+4305	0	4
+1041	1	0
+11424	3	1
+530	10174	10174
+1857	0	1
+1230	0	8
+1682	5	0
+9069	0	8
+25	1	1
+330	5	5
+76	0	1
+1306	1	1
+46	1	1
+134	19	23
+1467	1	1
+32	1	1
+449	17	0
+367	9	9
+3525	12	10
+105	7	4
+208	33	33
+1171	1	1
+24	1	1
+1156	9	13
+841	3	3
+28	1	1
+515	0	17
+1559	0	4
+1045	9	9
+1953	1	0
+31	1	1
+843	0	1
+2174	1	0
+3788	1	0
+6017	1	0
+5658	4797	4797
+413	2	0
+2735	0	1
+941	4	0
+7767	0	1
+17211	5	0
+7531	0	1
+5505	1	2
+3443	0	2
+24240	1	1
+33	1	1
+4777	4	2
+43	3	0
+1254	0	1
+16	1	1
+1411	0	4
+424	1	1
+51	1	1
+113	1	1
+34	1	1
+344	9	9
+15845	1	0
+1155	1	0
+1648	0	16
+2071	0	9
+25450	1	0
+7543	4	10
+744	1	0
+564	2	0
+16701	3	0
+9132	1	1
+49	1	1
+146	1	1
+61	1	1
+116	1	1
+41	1	1
+137	1	1
+30	1	1
+158	9	9
+136	10	13
+973	6	6
+547	1	1
+41	1	1
+164	17	17
+1053	4	4
+228	1	1
+34	1	1
+355	1	1
+113	1	1
+330	0	1
+222	1	1
+25	1	1
+267	1	1
+38	1	1
+709	2	0
+1448	0	1
+152	1	1
+46	1	1
+237	1	1
+20	1	1
+211	5	5
+88	1	1
+33	1	1
+211	1	1
+65	1	1
+516	58	58
+491	7	7
+208	13	12
+558	2	2
+28	1	1
+125	4	4
+1853	21	0
+845	6	6
+2005	0	1
+148	1	1
+36	1	1
+993	1	0
+3580	10	10
+1203	1	0
+530	5	5
+216	1	1
+32	1	1
+312	1	1
+44	1	1
+1934	14	14
+1149	0	8
+835	1	1
+29	0	1
+2324	1	1
+18	1	1
+1273	27	27
+104	1	1
+21	1	1
+53	8	8
+1631	1	1
+16	1	1
+429	8	16
+1419	23	23
+256	1	0
+40	1	1
+106	1	1
+21	1	1
+501	2	2
+40	1	1
+2249	1	1
+189	0	1
+180	14	1
+1272	17	17
+345	0	2
+1504	14	0
+1689	4	0
+3174	16	16
+607	4	34
+41	0	5
+669	1	1
+25	1	1
+1926	1	1
+39	4	3
+1037	1	1
+40	2	0
+890	6	0
+41	2	0
+466	1	1
+31	3	0
+321	0	1
+281	3	0
+450	1	1
+34	1	1
+498	1	1
+28	2	1
+280	0	1
+649	1	1
+47	1	1
+1002	4	0
+120	1	1
+533	7	7
+998	0	1
+75	1	1
+37	1	1
+582	19	19
+60	18	18
+4194	0	2
+216	1	1
+112	1	1
+129	4	0
+87	1	1
+160	1	1
+49	1	1
+147	18	14
+128	1	1
+37	1	1
+865	4	0
+160	1	1
+35	1	1
+1119	1	1
+13	0	3
+242	1	1
+23	1	1
+1705	0	4
+103	0	1
+1117	2	0
+67	1	1
+1825	0	1
+855	8	0
+1368	3	0
+320	1	1
+149	1	1
+97	1	1
+15	1	1
+371	1	1
+165	1	1
+61	1	1
+32	0	2
+5	1	1
+1520	1	1
+28	1	1
+367	4	0
+267	13	13
+175	1	0
+225	1	1
+45	1	1
+797	1	1
+142	1	0
+38	0	2
+318	8	7
+50	1	1
+29	1	1
+376	4	9
+548	1	1
+57	1	1
+665	4	0
+1690	17	17
+208	6	6
+398	13	13
+63	1	1
+80	1	1
+57	1	1
+61	1	1
+170	1	1
+56	1	1
+93	1	1
+106	1	1
+41	1	1
+68	12	7
+13	4	0
+68	1	1
+76	1	1
+658	11	11
+447	4	4
+385	1	1
+35	1	1
+108	1	1
+37	4	0
+304	1	1
+70	1	0
+1242	12	12
+371	50	8
+386	2	0
+29	1	1
+204	1	1
+80	1	1
+112	12	11
+315	7	7
+97	0	2
+1756	1	1
+38	1	1
+106	23	23
+125	20	0
+1226	1	0
+16	5	0
+21	1	1
+235	10	10
+181	1	1
+72	1	1
+51	5	1
+43	5	7
+485	7	7
+127	1	1
+140	1	1
+105	5	6
+18	1	1
+88	1	1
+190	1	1
+68	10	10
+323	1	1
+59	4	0
+1507	3	0
+123	1	1
+73	1	1
+137	16	16
+132	1	1
+131	2	0
+5	0	3
+76	1	1
+40	1	1
+273	9	10
+172	1	1
+76	1	1
+98	1	1
+57	1	1
+54	1	0
+16	1	1
+66	1	1
+36	1	1
+120	1	1
+77	0	1
+34	1	1
+102	1	1
+41	1	1
+126	6	7
+1059	0	1
+1067	0	12
+1292	1	0
+744	0	4
+990	2	2
+58	1	1
+45	0	1
+308	1	1
+49	0	1
+21	1	1
+700	1	0
+973	2	0
+548	0	2
+982	10	0
+242	1	1
+38	1	1
+1067	3	0
+618	7	7
+1893	44	43
+731	2	2
+49	1	1
+908	9	9
+484	0	2
+128	0	1
+174	15	18
+175	1	1
+16	1	1
+332	1	1
+22	1	1
+554	0	1
+120	1	1
+31	1	1
+351	5	0
+80	1	0
+76	1	1
+39	1	1
+1447	1	0
+1072	1	1
+43	0	4
+43	1	1
+393	0	1
+1820	6	6
+457	1	1
+18	1	1
+87	1	1
+30	1	1
+861	1	1
+20	1	1
+1057	23	23
+416	0	24
+779	1	1
+17	1	2
+37	1	1
+1675	1	1
+27	1	1
+901	0	8
+47	1	1
+262	0	3
+57	1	1
+29	0	1
+234	0	3
+45	1	1
+250	1	1
+18	1	1
+517	33	0
+117	1	1
+55	1	1
+537	1	1
+20	1	1
+671	1	1
+68	1	1
+89	1	1
+104	1	1
+172	0	1
+124	0	1
+522	0	1500
+466	5	5
+32	1	0
+171	1	1
+19	1	1
+67	1	1
+22	1	1
+654	1	1
+25	1	1
+68	1	1
+21	4	0
+1588	1	1
+66	1	1
+401	0	1
+186	1	1
+21	1	1
+168	0	1
+601	1	1
+29	1	1
+36	4	0
+37	1	1
+127	1	1
+29	1	1
+404	0	2
+710	1	1
+89	1	1
+161	16	16
+405	1	1
+39	3	3
+56	1	1
+82	1	1
+71	1	1
+37	0	4
+104	1	1
+89	1	1
+64	1	1
+102	1	1
+130	15	16
+158	8	0
+57	1	1
+731	1	1
+65	1	1
+313	1	1
+44	1	0
+52	20006	20030
+60	8	8
+61	1	1
+120	1	1
+366	1	1
+55	1	1
+121	1	1
+62	1	1
+127	1	1
+18	1	1
+142	1	1
+26	1	1
+149	1	1
+62	11	11
+550	1	1
+76	1	0
+20	1	1
+112	1	1
+149	1	1
+284	1	1
+37	1	1
+705	1	12
+106	12	12
+1631	1	1
+47	1	1
+244	3	3
+22	3	3
+1486	0	3
+196	6	6
+63	1	1
+70	1	1
+325	14	19
+220	0	1
+773	1	1
+35	1	1
+153	1	1
+57	1	1
+123	1	1
+45	0	1
+15	1	1
+270	1	1
+48	1	1
+101	16	16
+64	1	1
+124	1	1
+1429	25	25
+184	0	1
+4315	4	4
+1530	4	0
+1062	1	1
+43	1	1
+55	14	14
+853	12	12
+2313	13	13
+537	9	0
+1430	1	1
+48	1	1
+400	1	1
+100	1	1
+148	19	19
+152	1	1
+25	1	1
+70	1	1
+102	1	1
+158	1	1
+56	2	2
+57	1	1
+10	5	10
+24	2	0
+71	1	1
+54	1	1
+73	1	1
+85	1	1
+105	1	1
+117	2	2
+29	1	1
+92	2	2
+42	0	1
+154	1	1
+10	1	0
+47	4	5
+35	1	1
+56	1	1
+64	3	3
+67	5	5
+72	1	1
+60	1	1
+45	1	1
+82	1	1
+95	2	2
+161	1	1
+301	1	1
+67	1	0
+430	1	1
+105	10	10
+38	0	4
+386	11	11
+101	3	2
+117	0	2
+77	1	1
+481	0	2
+67	1	1
+45	1	1
+503	1	1
+34	1	1
+359	1	1
+35	1	1
+534	11	11
+1738	1	1
+26	1	1
+506	19	0
+356	1	1
+138	0	3
+1403	13	13
+1045	1	1
+24	1	1
+879	1	1
+73	1	1
+89	1	1
+42	1	1
+108	1	1
+19	1	5
+41	0	1
+4	1	1
+511	5	6
+605	1	1
+47	1	1
+73	1	1
+62	1	1
+1912	49303	50027
+638	99452	99452
+4150	1	1
+31	0	1
+6	1	1
+163	1	1
+22	1	1
+81	1	1
+27	1	1
+548	1	1
+61	1	1
+1169	1	1
+41	1	1
+6471	1	1
+62	1	1
+530	17	17
+394	1	1
+40	7	0
+57	12	12
+69	2	2
+39	1	1
+70	1	1
+22	0	3
+2796	1	1
+58	1	1
+375	25	27
+1218	1	1
+35	1	1
+85	1	1
+20	6	0
+687	1	1
+34	1	1
+355	1	1
+47	1	0
+51	69	69
+73	1	1
+48	1	1
+218	1	1
+42	1	1
+197	1	1
+41	1	1
+313	1	1
+40	1	1
+476	1	1
+29	1	1
+185	1	1
+35	1	1
+594	1	1
+24	1	1
+219	2	0
+246	0	1
+261	4	4
+43	1	1
+54	1	1
+130	1	1
+184	1	1
+201	1	1
+306	1	1
+29	5	5
+121	1	1
+31	1	1
+109	1	1
+25	1	1
+168	1	1
+19	1	1
+104	1	0
+132	1	0
+113	1	1
+30	1	1
+56	9	9
+300	1	1
+50	2	2
+96	1	1
+43	1	1
+76	1	1
+44	1	1
+197	1	1
+38	2	1
+52	0	2
+18	1	1
+99	0	9
+392	5	5
+89	1	1
+399	1	1
+35	3	4
+260	1	1
+23	1	0
+10	1	1
+70	1	1
+65	2	0
+17	0	18
+28	1	1
+208	1	1
+70	1	1
+149	0	3
+243	1	1
+55	1	1
+63	17	17
+1208	1	1
+98	1	1
+58	1	1
+43	1	1
+59	1	1
+45	1	1
+148	70	70
+209	4	4
+1242	1	1
+42	5	0
+87	1	1
+522	0	3
+305	0	1
+1379	0	2
+390	0	15
+72	1	1
+16	1	1
+270	1	0
+280	7	7
+2763	20	20
+674	10	10
+1375	8	0
+294	142	141
+145	1	1
+35	1	1
+447	16	16
+54	4	4
+680	16	16
+1123	4	4
+1075	1	1
+46	1	1
+282	1	1
+39	1	1
+860	1	1
+26	1	1
+745	0	2
+2081	2	0
+817	4	4
+202	1	1
+48	1	1
+168	1	1
+53	1	1
+379	10	10
+1178	14	14
+135	5	0
+1169	1	1
+21	1	1
+462	1	1
+43	1	1
+121	1	1
+48	0	3
+16	1	4
+1404	0	1
+450	4	0
+626	1	0
+304	1	1
+39	1	1
+564	1	1
+45	1	1
+303	2	0
+409	1	1
+18	1	0
+858	3	0
+2168	0	1
+54	22	22
+220	1	1
+48	1	1
+254	0	1
+523	0	13
+2423	18	14
+64	1	1
+30	2	2
+185	0	4
+966	16	16
+123	11	11
+531	1	1
+20	1	1
+227	1	1
+37	1	1
+636	3	4
+8239	1	1
+23	1	1
+1114	0	2
+688	0	1
+901	18	18
+4781	0	4
+815	0	1
+5069	0	5
+415	0	1
+353	0	1
+1087	9	9
+108	30	30
+144	1	0
+817	1	0
+194	10	10
+460	0	1
+327	0	1
+878	0	1
+854	0	1
+4897	0	2
+1554	1	1
+60	1	1
+278	0	1
+19	1	1
+1866	0	1
+961	0	3
+60	0	18
+2122	0	2
+19	1	1
+1232	0	2
+1641	2	0
+10831	3	2
+188	0	1
+1650	3	6
+2842	0	4
+146	2	0
+4952	0	2
+4944	1	0
+1024	0	1
+803	11423	11423
+1739	0	4
+852	5	6
+1925	15	15
+1657	1	0
+378	0	2
+968	1	0
+1174	0	4
+663	6	0
+297	0	3
+2049	0	5
+876	11	11
+12081	1	1
+33	1	1
+1932	0	1
+398	1	1
+145	1	1
+3667	0	4
+1305	0	10
+3035	1	0
+5554	6	0
+42067	0	1
+4121	2	0
+13331	4	0
+2404	8	8
+1698	0	2
+19856	4	0
+1616	0	1
+1686	0	2
+2223	0	4
+4741	12	0
+1921	0	1
+913	0	1
+3801	0	1
+2620	8	0
+12800	0	1
+2431	1	0
+158	0	1
+281	1	0
+12653	1	0
+6938	0	1
+14766	1	0
+1654	34221	34221
+3000	17	17
+689	0	3
+62	1	0
+5716	1	0
+456	1	0
+2077	2	0
+616	178	0
+14916	0	4
+672	1	1
+26	1	1
+461	1	1
+33	0	2
+16	1	1
+649	1	1
+48	1	1
+818	1	1
+21	1	1
+424	1	1
+25	1	1
+632	1	1
+39	1	1
+310	1	1
+27	1	1
+616	1	0
+17240	4	0
+3936	3	0
+3834	2	0
+426	1	0
+5704	1	1
+43	1	0
+622	0	1
+167	0	5
+1968	0	3
+258	2	0
+4089	1	0
+903	29	27
+1088	7	6
+290	3	3
+117	13	0
+2194	0	1
+191	0	1
+118	1	0
+2013	1	0
+7453	1	0
+3382	0	1
+1544	0	1
+634	0	49
+5260	0	1
+4607	1	0
+32465	1	0
+1323	1	0
+39	0	1
+5117	27143	27143
+480	9	9
+746	11	11
+29289	0	3
+99	1	1
+19	1	1
+259	1	1
+57	1	1
+105	0	1
+2134	9	9
+2299	1	1
+43	1	1
+1287	1	0
+22328	5	0
+47	8	0
+4444	2	0
+6495	0	16
+2128	0	1
+8355	0	3
+4114	0	1
+1404	0	1
+5139	0	2
+1840	2	0
+1214	6	6
+273	0	7
+653	10	10
+189	1	0
+27280	0	2
+615	1	0
+1600	0	1
+364	0	2
+1466	1	0
+6628	1	1
+110	0	1
+1422	0	1
+324	1	0
+173	0	1
+1651	1	0
+311	0	1
+10202	4	0
+3867	9	7
+19808	0	2
+4947	29	29
+1283	0	3
+14175	10	0
+29	1	1
+4509	43	43
+1259	1	0
+2089	1	2
+365	0	2
+3430	1	0
+159	0	4
+2886	28	0
+147	0	1
+1181	10	15
+206	3	4
+208	1	1
+25	1	1
+2194	1	1
+18	1	1
+3726	0	3
+34	1	1
+361	17	17
+6271	1	0
+4854	0	1
+1587	0	1
+9534	1	1
+50	1	0
+1082	1	1
+42	1	1
+639	1	0
+145	13	15
+557	11	11
+53	1	1
+61	1	1
+454	1	1
+26	1	1
+1053	1	1
+60	1	1
+51	1	1
+26	1	0
+102	1	1
+67	1	1
+71	1	1
+134	1	1
+85	1	1
+607	36	0
+58	1	1
+1266	2	0
+480	14	21
+1459	2	1
+435	15	17
+224	57380	57335
+2665	46	46
+554	0	21
+4473	2	3
+921	1	1
+47	1	1
+2605	9	3
+50	1	1
+178	1	1
+26	1	1
+316	0	2
+1120	4	0
+177	1	2
+1991	4	4
+783	8	8
+61	34	13
+121	1	1
+22	1	0
+118	1	1
+49	4	4
+217	1	1
+91	1	1
+958	0	1
+107	1	1
+31	1	1
+171	14	14
+302	0	13
+33	1	1
+108	0	4
+98	1	1
+53	1	1
+457	2	0
+529	1	1
+37	2	0
+1829	1	1
+38	1	1
+440	1	1
+82	3	4
+647	45	45
+660	1	1
+28	1	1
+1993	0	1
+373	19	19
+835	1	1
+42	1	1
+947	1	1
+36	1	0
+1055	1	1
+43	1	1
+475	1	0
+60	1	1
+127	1	1
+509	1	1
+71	1	1
+485	1	0
+26	1	1
+531	1	1
+18	1	1
+551	1	1
+18	1	1
+884	5	5
+147	53	60
+527	1	1
+26	2	2
+322	0	17
+32	2	2
+85	1	1
+45	1	1
+625	0	323
+540	0	1
+43	1	1
+266	0	2
+228	1	1
+42	1	1
+283	1	1
+92	1	1
+381	1	1
+40	1	1
+1906	0	4
+3495	0	4
+967	1	1
+76	1	1
+3236	4	4
+529	7	7
+246	4	0
+38	1	1
+156	0	6
+1466	0	2
+499	1	0
+937	1	1
+45	1	1
+421	6	0
+87	22	22
+1254	1	1
+36	0	1
+357	18	18
+391	0	1
+451	1	0
+105	1	1
+47	1	0
+255	6	6
+739	3	0
+386	1	1
+33	1	1
+281	5	0
+481	2	0
+495	1	1
+42	4	0
+219	0	1
+408	1	1
+23	1	1
+283	1	1
+25	0	1
+541	1	0
+88	2	0
+216	1	1
+29	1	1
+457	1	0
+331	9	3
+197	15	15
+228	1	0
+4	2	0
+333	0	1
+19	1	1
+1081	3	3
+35	1	1
+1211	1	1
+34	1	1
+667	0	2
+64	1	1
+78	1	1
+1519	1	1
+27	1	1
+154	14	14
+1090	1	1
+40	0	3
+35	1	1
+1355	0	4
+79	1	1
+145	1	1
+63	1	1
+70	1	1
+21	1	1
+695	1	1
+41	2	2
+564	1	1
+46	1	1
+279	4	0
+38	5	5
+3523	32	32
+545	1	1
+27	1	0
+54	15	16
+1212	0	14
+34	0	11
+787	2	0
+3691	1	0
+1843	1	1
+45	1	0
+11	1	2
+3499	1	1
+27	1	1
+1047	0	2
+1804	2	0
+1079	1	1
+17	1	1
+639	3	5
+73	1	1
+13	13	0
+66	1	1
+391	0	7
+4547	0	1
+53	9	6
+691	0	1
+989	1	1
+143	1	1
+223	0	2
+95	1	1
+1000	1	1
+41	1	1
+93	1	1
+49	1	1
+606	1	1
+48	1	1
+128	0	4
+109	1	31
+44	10	781
+62	4	0
+129	1	1
+62	1	1
+106	1	1
+247	1	1
+20	18	4
+125	1	1
+43	1	1
+909	0	2
+381	4	4
+74	1	1
+408	1	0
+1595	5	0
+3690	1	1
+64	1	1
+754	0	4
+1877	1	1
+49	1	1
+1095	11	0
+732	0	27
+3070	2	0
+1879	0	1
+572	0	8
+215	1	1
+58	1	1
+301	1	1
+42	1	1
+265	24	0
+209	11	11
+953	1	1
+42	0	5
+58	1	0
+95	1	0
+210	1	1
+27	1	1
+882	1	1
+17	1	1
+751	0	1
+24	1	1
+351	1	1
+43	3	3
+565	1	1
+15	1	1
+150	27	27
+94	1	0
+323	1	1
+23	1	1
+221	7	7
+705	15	0
+631	2	0
+64	1	1
+1577	1	1
+21	0	1
+354	0	10
+188	0	1
+283	1	1
+48	1	1
+227	1	1
+40	0	3
+1357	0	2
+1571	7	7
+1153	1	1
+93	1	1
+797	14	14
+433	8	0
+108	11	11
+140	1	1
+40	1	1
+470	1	1
+42	1	1
+1106	0	2
+84	4	4
+129	1	1
+123	1	0
+95	1	1
+82	0	3
+661	1	1
+77	1	1
+57	1	1
+62	1	1
+473	2	0
+262	6	0
+45	1	1
+49	3	0
+321	0	1
+197	2	104
+202	0	10
+92	0	4
+108	6	0
+563	14	14
+324	1	0
+205	1	1
+17	1	1
+495	0	1
+201	4	0
+14	1	1
+1080	1	1
+24	1	1
+91	24	24
+279	1	1
+95	1	1
+121	1	1
+62	1	1
+2371	1	0
+164	9	1
+655	1	1
+30	1	1
+271	1	1
+47	1	1
+609	1	0
+1780	2	0
+742	1	1
+40	1	1
+272	1	1
+52	1	1
+1187	1	1
+23	1	1
+254	1	1
+60	1	1
+176	3	6
+463	1	1
+36	1	1
+797	1	1
+22	1	1
+395	5	2
+61	1	1
+31	3	3
+226	1	1
+59	1	1
+581	1	1
+46	1	1
+412	1	1
+23	1	0
+74	1	1
+17	1	1
+81	1	1
+24	1	1
+83	15	15
+363	1	1
+91	1	1
+383	20	20
+199	13	13
+976	1	1
+39	0	3
+161	14	15
+127	16	16
+517	1	1
+132	1	1
+167	28	28
+124	1	1
+68	0	22
+1074	0	1
+175	1	0
+1018	1	1
+90	4	4
+1034	15	15
+69	1	1
+33	1	1
+174	1	1
+56	1	1
+169	1	0
+201	1	1
+30	1	1
+58	1	1
+38	1	1
+91	1	1
+98	4	4
+65	1	1
+19	2	0
+104	6	5
+25	1	1
+218	1	1
+37	1	1
+343	110361	150022
+67	8	8
+36	0	11
+62	1	1
+107	1	1
+68	3	130
+66	4	4
+50	22	21
+98	1	1
+127	1	0
+192	1	1
+71	1	1
+52	1	1
+200	1	1
+307	0	1
+331	1	1
+97	11	11
+171	1	1
+61	1	1
+37	1	1
+156	3	0
+63	0	3
+155	4	1
+31	2	0
+232	1	1
+33	1	1
+175	2	0
+131	6	6
+1409	0	3
+180	1	1
+65	0	1
+703	1	1
+19	1	1
+254	1	1
+22	1	1
+424	1	1
+65	1	1
+532	1	1
+48	1	1
+347	0	12
+578	16	17
+965	1	1
+45	1	1
+893	57505	60106
+93	1	1
+75	808	0
+46	1	1
+221	1	1
+213	8	0
+63	1	1
+60	17	17
+53	1	1
+29	1	1
+68	8	8
+62	9	9
+51	1	1
+85	1	1
+101	1	1
+54	2	2
+116	1	1
+66	1	1
+182	1	0
+37	1	1
+134	14	14
+117	1	1
+45	1	1
+120	1	1
+47	1	1
+342	1	1
+46	1	1
+237	12	12
+107	8	8
+754	1	0
+880	1	1
+16	1	1
+491	1	1
+49	1	1
+192	1	1
+54	0	1
+19	2	2
+165	0	21
+26	1	1
+183	13	13
+72	1	1
+23	1	0
+268	14	14
+320	1	1
+55	1	1
+414	5	5
+172	0	1
+620	1	1
+18	1	1
+190	1	1
+20	0	8
+849	1	1
+29	1	1
+978	30198	30058
+159	1	1
+36	1	1
+107	1	1
+176	1	1
+154	0	5
+91	1	1
+54	1	1
+77	1	1
+239	1	1
+50	1	1
+128	1	1
+40	1	1
+173	11	11
+734	1	1
+31	1	1
+215	1	1
+108	1	1
+259	1	1
+79	1	1
+80	1	1
+47	3	1
+40	1	1
+54	1	1
+46	1	1
+118	9	9
+98	1	0
+5	11	4
+23	0	7
+84	1	1
+84	2	2
+6	0	1
+6	1	0
+110	0	7
+537	1	1
+96	1	1
+441	1	1
+101	1	1
+242	14	14
+255	16	16
+142	1	0
+345	10	10
+54	1	1
+26	1	1
+108	1	1
+83	1	1
+128	1	1
+36	1	1
+231	1	1
+37	1	1
+534	1	1
+60	1	1
+804	0	3
+43	1	1
+148	1	1
+25	1	1
+69	10	10
+76	5	5
+37	1	1
+66	0	2
+192	1	1
+60	3	0
+19	1	1
+1149	1	1
+18	1	1
+77	1	1
+32	2	0
+32	1	1
+136	1	1
+78	2	0
+1680	1	1
+39	0	1
+548	1	1
+50	1	1
+177	2	0
+340	1	1
+112	1	1
+422	10	10
+963	4	4
+329	1	9
+648	5	1
+117	1	1
+27	1	1
+574	1	0
+507	1	1
+39	1	1
+294	3	2
+549	1	1
+22	1	1
+74	0	1
+98	1	1
+65	3	3
+230	1	1
+18	1	0
+33	1	1
+51	1	1
+24	1	1
+811	1	1
+59	0	2
+8	1	1
+80	9	9
+437	14	14
+57	4	4
+588	15	15
+305	1	1
+17	1	1
+135	1	1
+50	1	1
+59	16	16
+129	1	1
+25	2	0
+12	1	1
+106	1	1
+31	1	1
+350	1	1
+47	1	1
+340	1	1
+65	1	1
+478	2	0
+714	8	7
+95	2	2
+52	2	1
+1129	1	1
+34	1	1
+1715	1	1
+87	1	1
+692	1	1
+47	0	1
+75	1	1
+2155	10	10
+1611	1	1
+22	1	1
+186	1	1
+34	1	1
+98	1	1
+47	1	1
+117	1	0
+185	1	1
+24	1	0
+98	0	2
+258	8	14
+967	1	1
+37	3	3
+502	1	1
+22	1	1
+75	0	3
+163	1	1
+40	1	1
+638	0	3
+150	1	1
+11	0	1
+29	1	1
+125	1	1
+78	1	1
+115	8	0
+1622	18	19
+1471	1	1
+30	1	1
+1580	73	73
+435	1	1
+60	1	1
+325	0	1
+254	1	1
+43	1	1
+181	14	0
+37	1	0
+47	1	1
+130	4	4
+34	1	1
+208	1	1
+39	2	2
+526	1	1
+36	1	1
+99	9	7
+20	1	1
+73	1	1
+62	1	1
+425	1	1
+43	1	1
+811	1	1
+38	1	1
+362	1	1
+49	1	1
+109	1	1
+19	1	1
+79	1	1
+29	0	1
+26	1	1
+252	1	1
+75	1	1
+467	1	1
+40	1	1
+389	13	13
+57	17	17
+544	1	1
+42	1	1
+597	0	311
+64	6	6
+568	1	1
+35	1	1
+62	1	1
+38	1	1
+79	1	0
+553	1	1
+30	1	1
+433	1	1
+16	3	0
+1133	12	12
+1503	14	14
+272	1	1
+41	1	1
+196	1	0
+571	1	1
+38	1	1
+813	18	19
+314	1	1
+22	1	1
+345	1	1
+23	3	0
+245	1	1
+129	1	1
+26	1	1
+435	1	1
+16	0	4
+323	1	1
+32	1	1
+247	1	1
+48	1	1
+778	2	0
+226	1	1
+61	1	1
+861	3	0
+471	4	0
+6220	3	0
+1351	18	18
+1560	1	0
+8099	1	0
+7388	0	5
+5386	0	1
+511	0	1
+599	0	6
+10541	11	21
+1909	16	16
+253	1	1
+16	1	1
+308	3	3
+27	1	1
+1333	0	3
+330	9	9
+600	2	0
+261	8	8
+5249	47	47
+4613	0	2
+2337	2	0
+2567	1	1
+26	1	1
+561	1	1
+48	1	1
+2440	1	1
+30	1	1
+1289	0	1
+162	1	0
+730	0	3
+663	1	0
+20	1	1
+1027	1	1
+43	1	1
+472	0	1
+219	1	1
+20	1	1
+495	1	0
+6	2	0
+1007	0	1
+169	0	10
+33	1	1
+1029	1	1
+30	1	1
+438	1	1
+39	1	1
+511	0	1
+1247	1	0
+1055	1	0
+491	1	0
+108	1	1
+48	1	1
+1324	0	1
+143	1	1
+40	1	1
+679	1	1
+45	1	1
+1036	0	1
+59	1	1
+46	1	1
+229	16	16
+149	10	10
+94	1	1
+63	1	1
+222	2	0
+55	1	1
+115	1	1
+219	15	15
+692	28	28
+159	1	1
+41	1	1
+211	1	0
+20	1	1
+1099	0	4
+28	13	12
+32	1	1
+60	1	1
+21	6	0
+178	13	15
+32	1	1
+953	1	1
+47	1	1
+174	1	1
+22	1	1
+401	0	13
+588	5	21
+288	4	4
+86	1	1
+29	0	2
+67	3	0
+641	0	1
+571	0	1
+250	1	1
+34	1	1
+255	0	2
+572	12	12
+275	6	1
+974	0	1
+578	12	12
+612	1	1
+43	1	1
+56	0	7
+1170	0	1
+477	4	3
+282	8	8
+466	0	4
+2118	5	0
+1090	0	2
+4424	1	1
+34	1	1
+4897	8	0
+2112	0	1
+2874	1	1
+21	1	1
+442	22	22
+805	0	1
+3476	10	0
+7129	3	0
+7475	0	4
+9494	2	0
+194	1	1
+49	1	1
+1349	22	22
+9662	2	0
+4856	3	0
+7447	6	6
+421	1	0
+884	6	0
+17	1	0
+3075	1	0
+14671	3	1
+3762	2	0
+601	2	0
+57	17921	17921
+1415	0	8
+42791	2	0
+100	2	0
+50	2	0
+13955	1	1
+272	1	1
+1137	1	0
+2261	16	15
+1824	1	0
+1990	1	0
+9965	0	18
+2951	6	0
+798	1	1
+30	1	1
+159	1	1
+124	1	1
+661	1	1
+31	1	1
+2632	4	4
+4024	0	16
+9373	7	7
+8626	0	1
+316	0	26
+10715	6	6
+110	1	1
+25	0	1
+3506	172081	34208
+1156	1	1
+161	1	1
+532	1	0
+698	2	0
+549	1	13
+287	1	1
+32	1	1
+1073	1	1
+22	6	0
+1829	3	923
+21	1	1
+721	1	1
+16	1	1
+1033	0	1
+10108	0	1
+10399	0	1
+14490	0	2
+3051	0	1
+6213	1	1
+26	1	1
+9064	26	26
+7722	3	0
+1957	2	0
+2288	1	0
+4470	0	4
+2115	1	0
+621	1	0
+563	0	2
+68	13	30
+160	18	19
+1807	0	2
+291	0	1
+2273	7	0
+2089	2	0
+479	1	0
+657	0	1
+772	4	0
+384	98	54
+779	0	2
+390	62	73
+1595	2	0
+1317	2	0
+5358	0	3
+2273	0	1
+597	0	8
+993	0	26
+1897	1	0
+76	0	1
+966	1	0
+2611	2	0
+1374	20	0
+831	33	33
+1574	0	2
+5096	0	3
+2404	1	1
+33	1	1
+507	4	0
+6366	0	25
+1550	0	5
+25133	1	0
+2111	0	1
+630	0	1
+784	0	1
+6989	1	0
+1116	0	1
+6270	0	1
+9520	1	0
+184	2	0
+328	1	0
+1089	1	0
+6600	0	1
+2450	1	0
+702	0	1
+5133	0	2
+3096	1	0
+315	1	0
+490	0	1
+684	9	9
+1895	3	0
+1013	0	1
+3659	1	0
+2412	1	2
+2723	4	0
+761	1	0
+22	0	1
+885	20	0
+5236	1	0
+2186	0	4
+1852	0	12
+991	0	1
+1091	0	1
+1006	1	0
+1699	0	1
+1682	1	0
+3693	1	0
+752	3	1
+497	5	6
+2292
+
+chain	61057	chr6_mcf_hap5	4833398	+	3953063	3953737	chr5	180857866	-	98127116	98127790	2061247
+526	1	1
+147
+
+chain	45613	chr6_mcf_hap5	4833398	+	2604717	2606756	chrX	154913754	+	17160000	17162038	2811400
+57	320	319
+92	373	373
+91	278	277
+94	320	320
+74	118	118
+78	42	43
+102
+
+chain	37022	chr6_mcf_hap5	4833398	+	2676816	2677228	chr7	158821424	+	107683864	107684276	3588094
+68	1	1
+54	1	1
+288
+
+chain	29722	chr6_mcf_hap5	4833398	+	1118803	1119113	chr7	158821424	+	38479558	38479868	4774007
+310
+
+chain	28137	chr6_mcf_hap5	4833398	+	3872548	3872872	chr18	76117153	-	36956533	36956857	5572699
+120	15	15
+189
+
+chain	28017	chr6_mcf_hap5	4833398	+	4025444	4025737	chr3	199501827	-	39984613	39984906	5625287
+293
+
+chain	26200	chr6_mcf_hap5	4833398	+	3998590	3999326	chr11	134452384	+	59999264	60000000	6424852
+154	126	126
+50	51	51
+57	235	235
+63
+
+chain	24804	chr6_mcf_hap5	4833398	+	1157807	1158609	chr7	158821424	-	51137320	51138288	7188387
+90	9	9
+79	101	101
+72	385	551
+66
+
+chain	21727	chr6_mcf_hap5	4833398	+	2690400	2690887	chr7	158821424	+	97232934	97233614	9179962
+159	171	400
+51	53	17
+53
+
+chain	21165	chr6_mcf_hap5	4833398	+	3891845	3892417	chr2	242951149	+	148617877	148618443	9563049
+63	162	156
+73	154	154
+120
+
+chain	20574	chr6_mcf_hap5	4833398	+	3328381	3329672	chr6	170899992	+	32089252	32090543	23930
+1291
+
+chain	19063	chr6_mcf_hap5	4833398	+	3948619	3949559	chr6	170899992	+	32821586	32822354	11222040
+175	715	543
+50
+
+chain	17270	chr6_mcf_hap5	4833398	+	3973147	3973355	chr10	135374737	-	70196080	70196288	12781660
+86	2	2
+48	5	5
+67
+
+chain	16223	chr6_mcf_hap5	4833398	+	3893015	3893224	chrX	154913754	-	4338266	4338475	13813426
+77	26	26
+106
+
+chain	15776	chr6_mcf_hap5	4833398	+	3956381	3966455	chr6	170899992	+	32827127	32836991	14253206
+50	4318	3617
+61	2558	2719
+69	660	1109
+229	767	762
+55	1248	1134
+59
+
+chain	15767	chr6_mcf_hap5	4833398	+	3201357	3201535	chr19	63811651	-	18495043	18495221	597719
+59	1	1
+45	1	1
+72
+
+chain	15397	chr6_mcf_hap5	4833398	+	4023860	4024020	chr7	158821424	+	63574132	63574292	14648759
+160
+
+chain	14519	chr6_mcf_hap5	4833398	+	3953825	3954073	chr3	199501827	+	161525390	161525638	4654449
+168	65	65
+15
+
+chain	14389	chr6_mcf_hap5	4833398	+	3863245	3863650	chr6	170899992	+	32665471	32665876	15746939
+57	86	85
+55	139	140
+68
+
+chain	13989	chr6_mcf_hap5	4833398	+	4038478	4038630	chr15	100338915	-	66378648	66378800	16209114
+152
+
+chain	13654	chr6_mcf_hap5	4833398	+	143599	143759	chr18	76117153	-	3498140	3498418	7857182
+83	1	1
+24	4	122
+48
+
+chain	12613	chr6_mcf_hap5	4833398	+	3848362	3848586	chr7	158821424	+	82112728	82112976	18070517
+51	77	101
+96
+
+chain	12612	chr6_mcf_hap5	4833398	+	3974617	3974791	chr6	170899992	-	53320727	53320901	18071926
+52	29	29
+93
+
+chain	12358	chr6_mcf_hap5	4833398	+	3995163	3995295	chr3	199501827	-	96522027	96522159	18443506
+132
+
+chain	12272	chr6_mcf_hap5	4833398	+	2612337	2612493	chrX	154913754	+	154847615	154847763	18572107
+71	1	1
+25	8	0
+51
+
+chain	12186	chr6_mcf_hap5	4833398	+	4038990	4039164	chr8	146274826	+	100984503	100984677	18706381
+68	32	32
+74
+
+chain	11876	chr6_mcf_hap5	4833398	+	2675238	2675454	chr6	170899992	+	31412979	31413204	19200916
+72	76	85
+68
+
+chain	11593	chr6_mcf_hap5	4833398	+	3844564	3844687	chr1	247249719	-	238369051	238369174	19677685
+123
+
+chain	11398	chr6_mcf_hap5	4833398	+	2686795	2686948	chr6	170899992	-	161606914	161607067	20013430
+64	22	22
+67
+
+chain	11324	chr6_mcf_hap5	4833398	+	3992779	3992926	chr6	170899992	-	138135992	138136139	20148163
+68	15	15
+64
+
+chain	10446	chr6_mcf_hap5	4833398	+	3869965	3870077	chr10	135374737	+	116791472	116791584	21828223
+112
+
+chain	9923	chr6_mcf_hap5	4833398	+	1132469	1132573	chr6	170899992	+	29984509	29984613	22990373
+104
+
+chain	9881	chr6_mcf_hap5	4833398	+	2664761	2665311	chr6	170899992	+	31313427	31313987	23083508
+72	423	433
+55
+
+chain	9817	chr6_mcf_hap5	4833398	+	3847924	3848156	chr8	146274826	+	42542364	42542493	23227154
+51	115	12
+66
+
+chain	9806	chr6_mcf_hap5	4833398	+	3846392	3846808	chr9	140273252	+	87960114	87960526	23254845
+57	294	290
+65
+
+chain	9661	chr6_mcf_hap5	4833398	+	3952556	3954131	chr6	170899992	+	104209491	104209913	3704454
+364	1153	0
+58
+
+chain	9564	chr6_mcf_hap5	4833398	+	3863653	3863818	chr6	170899992	+	32549657	32549823	23841400
+59	50	51
+56
+
+chain	9560	chr6_mcf_hap5	4833398	+	1145708	1145809	chr6	170899992	-	141000133	141000234	23851242
+101
+
+chain	9528	chr6_mcf_hap5	4833398	+	1160055	1160492	chr6	170899992	+	29878108	29878543	23937752
+59	318	316
+60
+
+chain	9472	chr6_mcf_hap5	4833398	+	3845655	3846032	chr1	247249719	-	150861000	150861377	24067468
+58	259	259
+60
+
+chain	9229	chr6_mcf_hap5	4833398	+	1293933	1294239	chr6	170899992	+	30567017	30567348	24575632
+62	194	219
+50
+
+chain	9124	chr6_mcf_hap5	4833398	+	3952955	3953063	chr3	199501827	+	1828344	1828452	9077956
+37	5	5
+66
+
+chain	9090	chr6_mcf_hap5	4833398	+	2611491	2611601	chr3	199501827	-	94209663	94209773	24799758
+53	4	4
+53
+
+chain	8464	chr6_mcf_hap5	4833398	+	2604519	2607426	chr2	242951149	+	56633977	56636883	3022124
+85	222	222
+134	2098	2097
+59	305	305
+4
+
+chain	8278	chr6_mcf_hap5	4833398	+	3861449	3861537	chr6	170899992	+	109538171	109538259	25991766
+88
+
+chain	8104	chr6_mcf_hap5	4833398	+	2618687	2620101	chr6	170899992	-	140880008	140881409	26266194
+74	1287	1274
+53
+
+chain	7774	chr6_mcf_hap5	4833398	+	2606022	2606534	chr1	247249719	+	7397644	7398156	2978583
+66	79	79
+58	214	214
+95
+
+chain	7592	chr6_mcf_hap5	4833398	+	3998745	3998829	chr8	146274826	+	68214220	68214304	9264343
+84
+
+chain	7141	chr6_mcf_hap5	4833398	+	3891766	3891845	chr12	132349534	+	113006300	113006379	12958594
+79
+
+chain	7041	chr6_mcf_hap5	4833398	+	3977312	3977387	chr4	191273063	+	139492368	139492443	28109801
+75
+
+chain	6949	chr6_mcf_hap5	4833398	+	3832393	3832466	chr6	170899992	+	32549387	32549460	28300224
+73
+
+chain	6795	chr6_mcf_hap5	4833398	+	2667263	2667335	chr6	170899992	+	31318116	31318188	28604524
+72
+
+chain	6658	chr6_mcf_hap5	4833398	+	3886931	3887001	chr5	180857866	-	20421148	20421218	28921167
+70
+
+chain	6650	chr6_mcf_hap5	4833398	+	3892813	3892896	chr11	134452384	-	10112929	10113012	19771549
+83
+
+chain	6648	chr6_mcf_hap5	4833398	+	3975186	3975255	chr12	132349534	-	72343253	72343322	28941661
+69
+
+chain	6613	chr6_mcf_hap5	4833398	+	3860999	3861069	chr1	247249719	+	37577726	37577796	29019074
+70
+
+chain	6545	chr6_mcf_hap5	4833398	+	3974547	3974617	chr9	140273252	-	54900636	54900706	21580040
+70
+
+chain	6522	chr6_mcf_hap5	4833398	+	3976253	3976322	chr15	100338915	+	41279078	41279147	29241047
+69
+
+chain	6504	chr6_mcf_hap5	4833398	+	3997726	3997795	chrX	154913754	-	101090292	101090361	29284261
+69
+
+chain	6494	chr6_mcf_hap5	4833398	+	2693655	2693723	chr6	170899992	+	30480336	30480404	29322144
+68
+
+chain	6459	chr6_mcf_hap5	4833398	+	2707667	2707736	chr6	170899992	+	31350859	31350928	29378028
+69
+
+chain	6376	chr6_mcf_hap5	4833398	+	3878588	3878655	chr1	247249719	-	291603	291670	29590708
+67
+
+chain	6368	chr6_mcf_hap5	4833398	+	2612245	2612337	chr6	170899992	-	132294381	132294479	20980271
+55	29	35
+8
+
+chain	6240	chr6_mcf_hap5	4833398	+	3861275	3861341	chr7	158821424	+	89136765	89136831	29917654
+66
+
+chain	6086	chr6_mcf_hap5	4833398	+	3886692	3886757	chr11	134452384	+	38517427	38517492	30319385
+65
+
+chain	5976	chr6_mcf_hap5	4833398	+	2710238	2710301	chr6	170899992	+	31358648	31358711	30614233
+63
+
+chain	5852	chr6_mcf_hap5	4833398	+	3892417	3892480	chr15	100338915	-	42450883	42450946	16059711
+63
+
+chain	5666	chr6_mcf_hap5	4833398	+	2692721	2692780	chr6	170899992	+	31328563	31328622	31482266
+59
+
+chain	5512	chr6_mcf_hap5	4833398	+	3860761	3860819	chr7	158821424	+	45670922	45670980	31905209
+58
+
+chain	5511	chr6_mcf_hap5	4833398	+	3953994	3954057	chr10	135374737	+	9454041	9454104	5673198
+63
+
+chain	5494	chr6_mcf_hap5	4833398	+	4010098	4010156	chr12	132349534	+	106784665	106784723	31946442
+58
+
+chain	5381	chr6_mcf_hap5	4833398	+	3848293	3848360	chr3	199501827	-	53390365	53390432	21843019
+67
+
+chain	5267	chr6_mcf_hap5	4833398	+	3861386	3861442	chr11	134452384	-	52779924	52779980	32661477
+56
+
+chain	5202	chr6_mcf_hap5	4833398	+	3975455	3975509	chr5	180857866	-	172710630	172710684	32856943
+54
+
+chain	5103	chr6_mcf_hap5	4833398	+	1145380	1145434	chr6	170899992	+	76955761	76955815	33170037
+54
+
+chain	5030	chr6_mcf_hap5	4833398	+	4010180	4010233	chr15	100338915	+	69519076	69519129	33389330
+53
+
+chain	5012	chr6_mcf_hap5	4833398	+	2695933	2695986	chr6	170899992	+	30481807	30481860	33454260
+53
+
+chain	4957	chr6_mcf_hap5	4833398	+	2608828	2608880	chr7	158821424	+	132662537	132662589	33651030
+52
+
+chain	4923	chr6_mcf_hap5	4833398	+	1157985	1158047	chr9	140273252	-	102391777	102391839	11227007
+62
+
+chain	4903	chr6_mcf_hap5	4833398	+	3886776	3886828	chrX	154913754	+	93227263	93227315	33852040
+52
+
+chain	4884	chr6_mcf_hap5	4833398	+	2690887	2690940	chr7	158821424	+	8665709	8665762	23124552
+53
+
+chain	4830	chr6_mcf_hap5	4833398	+	3870967	3871018	chr7	158821424	+	82104686	82104737	34087624
+51
+
+chain	4730	chr6_mcf_hap5	4833398	+	4037119	4037169	chr10	135374737	+	93200055	93200105	34443435
+50
+
+chain	4636	chr6_mcf_hap5	4833398	+	3953764	3953825	chr15	100338915	+	36217680	36217741	14854688
+61
+
+chain	4082	chr6_mcf_hap5	4833398	+	3861341	3861384	chr2	242951149	-	201903615	201903658	30854026
+43
+
+chain	3962	chr6_mcf_hap5	4833398	+	2605054	2607488	chr12	132349534	+	103308744	103311177	2987803
+40	116	116
+77	836	835
+44	1259	1259
+62
+
+chain	3938	chr6_mcf_hap5	4833398	+	3848731	3848772	chr12	132349534	+	106783136	106783177	34996470
+41
+
+chain	3860	chr6_mcf_hap5	4833398	+	3952301	3952346	chr3	199501827	+	112943878	112943923	15335435
+45
+
+chain	3596	chr6_mcf_hap5	4833398	+	3844515	3844564	chr19	63811651	+	37876836	37876885	21722630
+49
+
+chain	3519	chr6_mcf_hap5	4833398	+	3892776	3892813	chr10	135374737	+	82581588	82581625	28921113
+37
+
+chain	3457	chr6_mcf_hap5	4833398	+	3892907	3892997	chr5	180857866	+	79763558	79763648	18723404
+90
+
+chain	3302	chr6_mcf_hap5	4833398	+	2677228	2677268	chrX	154913754	-	17721831	17721871	3601717
+40
+
+chain	3266	chr6_mcf_hap5	4833398	+	3862147	3862182	chr9	140273252	+	83968215	83968250	35227644
+35
+
+chain	3215	chr6_mcf_hap5	4833398	+	2690311	2690345	chr13	114142980	-	34852829	34852863	33454154
+34
+
+chain	3191	chr6_mcf_hap5	4833398	+	2608477	2608530	chr16	88827254	+	57584329	57584382	22020535
+53
+
+chain	2914	chr6_mcf_hap5	4833398	+	3891647	3891703	chrX	154913754	+	119403135	119403191	11929641
+56
+
+chain	2795	chr6_mcf_hap5	4833398	+	3892480	3892522	chr15	100338915	+	56426321	56426363	16223719
+42
+
+chain	2771	chr6_mcf_hap5	4833398	+	2273985	2274017	chr16	88827254	+	61371572	61371604	11881975
+32
+
+chain	2705	chr6_mcf_hap5	4833398	+	3974669	3974698	chr5	180857866	+	34801294	34801323	21438495
+29
+
+chain	2671	chr6_mcf_hap5	4833398	+	2612185	2612244	chr9	140273252	-	60326471	60326530	21074056
+59
+
+chain	2599	chr6_mcf_hap5	4833398	+	1158047	1158085	chr7	158821424	-	126060947	126060985	11258554
+38
+
+chain	2590	chr6_mcf_hap5	4833398	+	3892269	3892297	chr5	180857866	-	137356848	137356876	18664742
+28
+
+chain	2589	chr6_mcf_hap5	4833398	+	3891454	3891482	chr11	134452384	-	49993356	49993384	29810036
+28
+
+chain	2555	chr6_mcf_hap5	4833398	+	2690245	2690311	chr18	76117153	+	25734423	25734489	18753960
+66
+
+chain	2509	chr6_mcf_hap5	4833398	+	2605481	2605558	chr3	199501827	-	153335243	153335320	3148850
+77
+
+chain	2466	chr6_mcf_hap5	4833398	+	2605403	2605466	chr2	242951149	+	186971340	186971403	6103613
+63
+
+chain	2459	chr6_mcf_hap5	4833398	+	3974791	3974822	chr14	106368585	+	48563076	48563107	22466897
+31
+
+chain	2459	chr6_mcf_hap5	4833398	+	3780767	3780793	chr17	78774742	-	42818294	42818320	32009757
+26
+
+chain	2427	chr6_mcf_hap5	4833398	+	2690989	2691048	chr3	199501827	-	193383909	193383968	24279045
+59
+
+chain	2365	chr6_mcf_hap5	4833398	+	4038809	4038866	chrX	154913754	+	103588329	103588386	22063660
+57
+
+chain	2350	chr6_mcf_hap5	4833398	+	1143959	1143987	chr9	140273252	+	98495373	98495401	22648903
+28
+
+chain	2348	chr6_mcf_hap5	4833398	+	2602541	2602596	chr7	158821424	+	35337254	35337309	23750584
+55
+
+chain	2343	chr6_mcf_hap5	4833398	+	3952502	3952527	chr11	134452384	-	60697549	60697574	22749508
+25
+
+chain	2320	chr6_mcf_hap5	4833398	+	4019609	4019634	chr19	63811651	-	56872967	56872992	35475512
+25
+
+chain	2317	chr6_mcf_hap5	4833398	+	2604190	2604320	chr15	100338915	-	72843171	72843301	3140919
+130
+
+chain	2262	chr6_mcf_hap5	4833398	+	1157783	1157807	chr19	63811651	-	5696072	5696096	21221761
+24
+
+chain	2188	chr6_mcf_hap5	4833398	+	1158201	1158258	chr1	247249719	+	222604152	222604209	12884993
+57
+
+chain	2183	chr6_mcf_hap5	4833398	+	3892590	3892636	chr7	158821424	+	113918927	113918973	16141801
+46
+
+chain	2172	chr6_mcf_hap5	4833398	+	3845632	3845655	chr3	199501827	+	38460301	38460324	24137330
+23
+
+chain	2171	chr6_mcf_hap5	4833398	+	3892683	3892706	chr13	114142980	-	13381431	13381454	25956368
+23
+
+chain	2132	chr6_mcf_hap5	4833398	+	2603254	2603380	chr1	247249719	+	93626635	93626761	5313263
+126
+
+chain	1996	chr6_mcf_hap5	4833398	+	2607152	2607223	chr3	199501827	+	178864208	178864279	4788720
+71
+
+chain	1952	chr6_mcf_hap5	4833398	+	3999028	3999070	chr2	242951149	-	218681061	218681103	8791220
+42
+
+chain	1946	chr6_mcf_hap5	4833398	+	1158400	1158475	chr1_random	1663265	-	1644029	1644104	12720667
+75
+
+chain	1930	chr6_mcf_hap5	4833398	+	3891482	3891539	chrX	154913754	+	81246238	81246295	14247869
+57
+
+chain	1927	chr6_mcf_hap5	4833398	+	2690365	2690400	chr7	158821424	-	109806767	109806802	24526345
+35
+
+chain	1921	chr6_mcf_hap5	4833398	+	4038367	4038423	chr11	134452384	-	48517870	48517926	18924823
+56
+
+chain	1856	chr6_mcf_hap5	4833398	+	1158158	1158191	chr4	191273063	+	153905795	153905828	9266241
+33
+
+chain	1833	chr6_mcf_hap5	4833398	+	2606939	2606989	chr9	140273252	+	84578242	84578292	7882125
+50
+
+chain	1827	chr6_mcf_hap5	4833398	+	3844483	3844515	chr10	135374737	-	122033518	122033550	24304365
+32
+
+chain	1796	chr6_mcf_hap5	4833398	+	2603994	2604348	chrX	154913754	+	100577502	100577856	3969599
+99	227	227
+28
+
+chain	1766	chr6_mcf_hap5	4833398	+	2690182	2690238	chr4	191273063	-	32209724	32209780	19175813
+56
+
+chain	1695	chr6_mcf_hap5	4833398	+	2604644	2604717	chr5	180857866	+	63682850	63682923	4402620
+59	4	4
+10
+
+chain	1651	chr6_mcf_hap5	4833398	+	3892522	3892590	chr11	134452384	+	18101372	18101440	12538366
+68
+
+chain	1629	chr6_mcf_hap5	4833398	+	4038630	4038657	chr2	242951149	-	84022333	84022360	21351212
+27
+
+chain	1606	chr6_mcf_hap5	4833398	+	3869684	3869743	chr4	191273063	-	166421863	166421922	24717461
+59
+
+chain	1597	chr6_mcf_hap5	4833398	+	3845427	3846126	chrX	154913754	-	128485360	128486059	24583609
+70	578	578
+51
+
+chain	1587	chr6_mcf_hap5	4833398	+	4039212	4039257	chr14	106368585	+	80426596	80426641	23776282
+45
+
+chain	1583	chr6_mcf_hap5	4833398	+	2676737	2676787	chr8	146274826	-	103361273	103361323	22022004
+50
+
+chain	1578	chr6_mcf_hap5	4833398	+	2686639	2686691	chr2	242951149	+	183623425	183623477	24278977
+52
+
+chain	1568	chr6_mcf_hap5	4833398	+	3998920	3998948	chr16	88827254	-	17543433	17543461	11021050
+28
+
+chain	1537	chr6_mcf_hap5	4833398	+	3999190	3999240	chr5	180857866	+	49878691	49878741	10672840
+50
+
+chain	1433	chr6_mcf_hap5	4833398	+	3999082	3999106	chr2	242951149	-	185977428	185977452	16089470
+24
+
+chain	1432	chr6_mcf_hap5	4833398	+	2607885	2607952	chr4	191273063	-	25455517	25455584	19723766
+67
+
+chain	1386	chr6_mcf_hap5	4833398	+	4037584	4037655	chr5	180857866	-	127160909	127160980	20252959
+71
+
+chain	1383	chr6_mcf_hap5	4833398	+	3892706	3892771	chr14	106368585	-	49729815	49729880	20850419
+65
+
+chain	1324	chr6_mcf_hap5	4833398	+	4038089	4038139	chr11	134452384	-	110737438	110737488	16281354
+50
+
+chain	1320	chr6_mcf_hap5	4833398	+	2607682	2607744	chr3	199501827	-	89080446	89080508	24774355
+62
+
+chain	1310	chr6_mcf_hap5	4833398	+	3891543	3891595	chrX	154913754	+	62583131	62583183	22867198
+52
+
+chain	1254	chr6_mcf_hap5	4833398	+	2605313	2605381	chr9	140273252	+	222427	222495	3502715
+68
+
+chain	1253	chr6_mcf_hap5	4833398	+	4038318	4038354	chr6	170899992	-	39092714	39092750	23906153
+36
+
+chain	1143	chr6_mcf_hap5	4833398	+	3998844	3998870	chr1	247249719	+	180123990	180124016	10456151
+26
+
+chain	1071	chr6_mcf_hap5	4833398	+	2603839	2603906	chr12	132349534	+	77415638	77415705	9437719
+67
+
+chain	1059	chr6_mcf_hap5	4833398	+	3952346	3952428	chr17	78774742	-	53522383	53522465	12152498
+82
+
+chain	1040	chr6_mcf_hap5	4833398	+	2603731	2603788	chr5	180857866	-	146041571	146041628	6664547
+57
+
+chain	1025	chr6_mcf_hap5	4833398	+	3892143	3892170	chr2	242951149	-	81435622	81435649	19840221
+27
+
+chain	1003	chr6_mcf_hap5	4833398	+	3731571	3731602	chr2	242951149	-	44758448	44758479	2126761
+31
+
+chain	978	chr6_mcf_hap5	4833398	+	1158258	1158286	chr6	170899992	-	112879191	112879219	17119903
+28
+
+chain	958	chr6_mcf_hap5	4833398	+	2606823	2606882	chr18	76117153	+	12161176	12161235	15243828
+59
+
+chain	919	chr6_mcf_hap5	4833398	+	2608035	2608095	chr4	191273063	+	44807134	44807194	22381057
+60
+
+chain	910	chr6_mcf_hap5	4833398	+	2604348	2604389	chrX	154913754	-	130647843	130647884	6306827
+41
+
+chain	899	chr6_mcf_hap5	4833398	+	3952444	3952502	chr9	140273252	+	66213924	66213982	10448615
+58
+
+chain	889	chr6_mcf_hap5	4833398	+	1158286	1158322	chr1	247249719	-	24894408	24894444	17913365
+36
+
+chain	857	chr6_mcf_hap5	4833398	+	4037505	4037565	chr20	62435964	-	51574691	51574751	25098794
+60
+
+chain	841	chr6_mcf_hap5	4833398	+	2603443	2603495	chr20	62435964	-	59823019	59823071	21526397
+52
+
+chain	825	chr6_mcf_hap5	4833398	+	2604460	2604519	chr7	158821424	+	140056560	140056619	5253720
+59
+
+chain	798	chr6_mcf_hap5	4833398	+	3846536	3846592	chr1	247249719	-	94337351	94337407	25194613
+56
+
+chain	791	chr6_mcf_hap5	4833398	+	2606765	2606815	chr2	242951149	+	171191285	171191335	4492406
+50
+
+chain	774	chr6_mcf_hap5	4833398	+	4038161	4038190	chr13	114142980	+	78421249	78421278	18219143
+29
+
+chain	760	chr6_mcf_hap5	4833398	+	2605737	2605796	chr12	132349534	+	56700130	56700189	25330835
+59
+
+chain	740	chr6_mcf_hap5	4833398	+	1158689	1158753	chr12	132349534	+	55464534	55464598	20832675
+64
+
+chain	725	chr6_mcf_hap5	4833398	+	2603907	2603961	chr2	242951149	+	129418481	129418535	15959343
+54
+
+chain	718	chr6_mcf_hap5	4833398	+	2608115	2608170	chr9	140273252	-	49339912	49339967	23555333
+55
+
+chain	716	chr6_mcf_hap5	4833398	+	4038745	4038797	chr16	88827254	-	38714794	38714846	22851160
+52
+
+chain	700	chr6_mcf_hap5	4833398	+	2604093	2604149	chr1	247249719	+	47033162	47033218	11748494
+56
+
+chain	697	chr6_mcf_hap5	4833398	+	2606088	2606122	chr18	76117153	+	57870219	57870253	3091588
+34
+
+chain	684	chr6_mcf_hap5	4833398	+	2603585	2603653	chrX	154913754	-	140171184	140171252	5395481
+68
+
+chain	681	chr6_mcf_hap5	4833398	+	4037371	4037428	chr8	146274826	-	64029404	64029461	24731946
+57
+
+chain	668	chr6_mcf_hap5	4833398	+	3815206	3815234	chr13	114142980	+	25366313	25366341	2606939
+28
+
+chain	607	chr6_mcf_hap5	4833398	+	2608345	2608426	chr12	132349534	+	61847837	61847918	15157322
+81
+
+chain	554	chr6_mcf_hap5	4833398	+	2607118	2607152	chr6	170899992	+	75108555	75108589	7134095
+34
+
+chain	547	chr6_mcf_hap5	4833398	+	2607779	2607829	chr11	134452384	-	79794459	79794509	15991278
+50
+
+chain	541	chr6_mcf_hap5	4833398	+	2605695	2605721	chr2	242951149	-	229173591	229173617	17449769
+26
+
+chain	537	chr6_mcf_hap5	4833398	+	2602778	2602824	chr20	62435964	+	38578434	38578480	23803873
+46
+
+chain	487	chr6_mcf_hap5	4833398	+	2603535	2603585	chr18	76117153	-	44468395	44468445	11618572
+50
+
+chain	479	chr6_mcf_hap5	4833398	+	3847219	3847270	chr8	146274826	-	91739126	91739177	25862760
+51
+
+chain	461	chr6_mcf_hap5	4833398	+	2607311	2607369	chr9	140273252	-	118104609	118104667	6129578
+58
+
+chain	456	chr6_mcf_hap5	4833398	+	2605822	2605854	chr10	135374737	+	51611354	51611386	20534292
+32
+
+chain	442	chr6_mcf_hap5	4833398	+	2602717	2602778	chr4	191273063	-	135500139	135500200	15116367
+61
+
+chain	412	chr6_mcf_hap5	4833398	+	2605854	2605905	chr12	132349534	+	9890446	9890497	14104676
+51
+
+chain	263	chr6_mcf_hap5	4833398	+	2604406	2604441	chr6	170899992	+	111492261	111492296	25439357
+35
+
+chain	227	chr6_mcf_hap5	4833398	+	2621672	2621728	chr6	170899992	-	140565854	140565910	28646895
+56
+
+chain	373682699	chr6_qbl_hap6	4611984	+	0	4611984	chr6	170899992	+	28804582	33487728	31
+932	3	0
+804	0	1
+2406	2	0
+210632	0	1
+14475	0	1
+6819	1	0
+6845	1	3
+6188	0	1
+6397	0	1
+345	1	0
+68374	2	0
+46946	7	0
+1489	1	1
+72	1	1
+2260	0	2
+10629	0	1
+19578	0	1
+1324	0	2
+5438	5	0
+2061	1	0
+3982	6	6
+1725	0	1
+3153	1	0
+18	1	0
+18	1	0
+2026	1	0
+4175	10	10
+4746	9	9
+4767	7	7
+1169	1	1
+55	1	0
+8	1	1
+151	1	2
+5079	1	1
+28	1	1
+249	43	43
+1178	0	4
+685	8	0
+48	4	0
+1701	1	1
+43	5	5
+862	18	18
+58	1	1
+66	1	1
+420	1	1
+44	1	1
+680	4	4
+1675	1	1
+83	1	1
+3082	4	0
+5467	1	1
+27	0	1
+1099	16	0
+627	12	12
+1317	6	1
+129	1	1
+25	1	1
+1397	15	15
+810	1	1
+27	1	1
+1192	2	0
+7515	4	0
+979	0	3
+3406	0	2
+2340	1	1
+20	1	1
+1139	1	1
+26	1	1
+787	0	1
+1416	3	1
+22815	4	4
+126	1	0
+38	1	1
+140	1	0
+999	0	17
+56	0	15
+11759	163412	163534
+9134	0	2
+5376	0	1
+19253	1	0
+7884	1	0
+21	0	6
+4451	1	0
+27910	1	0
+9946	0	1
+11233	1	1
+32	1	1
+2238	1	1
+20	1	1
+3659	22	16
+1218	1	0
+1638	6	6
+228	1	1
+45	1	1
+2048	0	3
+461	1	0
+20759	1	0
+3778	2	1
+1268	1	0
+1511	1	1
+42	2	0
+24	1	1
+4119	22	0
+1757	1	0
+1527	1	1
+29	1	1
+1886	1	0
+10628	12	0
+46568	1	0
+18985	0	10
+1825	3	4
+5288	0	9
+2728	1	5
+722	0	1
+502	0	1
+1025	0	1
+134	14	0
+4944	0	1
+319	1	0
+6178	0	1
+2898	0	2
+143	0	1
+1775	1	0
+2123	0	1
+2715	1	0
+4921	1	1
+47	4	0
+2882	1	0
+1362	1	0
+1233	0	8
+2134	0	1
+1042	0	1
+163	1	1
+45	1	1
+50	2	0
+64	1	1
+48	1	1
+380	0	1
+30	1	0
+30	1	1
+61	1	1
+22	1	1
+691	5	7
+310	1	1
+37	3	1
+162	1	1
+194	2	0
+36	1	1
+242	9	9
+697	33	33
+1202	1	1
+16	1	1
+528	1	1
+20	1	1
+509	0	5
+76	1	1
+21	1	1
+439	15	15
+2779	1	0
+1597	24	28
+59	12	12
+307	1	0
+516	1	0
+286	11	33
+339	5	0
+570	1	1
+37	1	1
+220	1	0
+72	1	1
+144	1	1
+48	1	1
+247	2	0
+174	9	10
+816	1	0
+940	1	1
+45	1	1
+91	3	3
+71	1	1
+291	14	14
+100	1	1
+23	1	1
+452	3	3
+229	1	1
+252	0	1
+129	15	15
+432	10	0
+85	1	1
+28	1	1
+189	2	1
+71	1	1
+52	8	0
+810	2	2
+63	1	1
+378	1	1
+26	1	1
+187	31	36
+966	1	1
+25	1	1
+91	12	12
+125	1	1
+38	1	1
+433	2	0
+596	1	1
+48	1	1
+465	4	4
+64	1	1
+20	1	1
+525	5	5
+237	3	8
+99	31	31
+53	11	0
+364	4	3
+201	1	1
+42	1	1
+56	1	1
+115	1	0
+67	16	16
+244	1	1
+54	5	5
+929	1	1
+21	1	1
+126	0	3
+830	1	11
+59	1	1
+537	0	2
+24	1	1
+745	15	15
+810	1	0
+425	1	1
+89	1	1
+592	1	1
+49	1	1
+352	0	1
+142	1	1
+30	1	1
+95	1	1
+45	1	1
+227	1	1
+53	1	1
+130	1	1
+18	1	1
+138	1	1
+90	1	1
+129	1	1
+39	1	1
+50	1	1
+79	1	1
+117	1	1
+31	1	1
+155	155	0
+34	1	1
+50	5	5
+57	1	1
+152	1	1
+30	1	1
+177	5	5
+345	1	1
+39	1	1
+504	18	18
+596	12	12
+54	1	1
+158	1	1
+164	1	1
+34	1	1
+626	15	15
+866	0	10
+1051	0	2611
+680	0	1
+1537	0	18
+75	1	0
+147	52	1
+119	0	12
+23	1	1
+1927	13	13
+1702	2	0
+3694	1	1
+18	1	1
+958	43	47
+246	2	0
+146	1	1
+49	1	1
+410	1	0
+667	1	1
+38	1	1
+362	7	1
+159	2	0
+515	2	0
+1026	1	1
+29	1	1
+249	0	6
+129	1	1
+33	4	0
+10	1	5
+1236	1	1
+20	1	1
+138	10	9
+448	0	3
+660	1	1
+28	1	1
+83	1	1
+51	1	1
+2659	1	1
+38	1	1
+424	0	1
+70	1	1
+820	1	1
+26	1	1
+1472	1	1
+21	1	1
+491	5	5
+163	15	15
+2194	2	0
+533	6	0
+441	1	7
+1689	1	1
+26	3	4
+879	16	16
+514	0	2
+58	1	1
+350	1	0
+769	1	1
+39	1	1
+573	0	4
+37	1	1
+144	8	8
+668	1	1
+22	1	1
+344	2	0
+262	2	2
+38	0	1
+70	18	18
+84	11	13
+169	62	63
+74	11	15
+1255	0	2
+332	1	1
+21	1	1
+193	8	24
+34	1	1
+79	1	1
+29	1	1
+536	1	0
+308	0	1
+850	0	32
+23	1	1
+651	1	1
+22	0	3
+136	1	1
+48	1	1
+330	9	9
+1108	1	1
+98	1	1
+582	0	2
+713	7	7
+89	1	0
+293	9	8
+125	1	1
+31	1	1
+192	6	6
+171	17	17
+681	1	1
+43	1	1
+514	1	1
+68	1	1
+537	1	1
+35	1	1
+159	6	6
+778	2	2
+44	1	1
+168	0	7
+211	1	1
+42	1	1
+1253	1	1
+29	1	1
+320	1	1
+36	2	2
+55	1	2
+108	1	1
+33	1	1
+317	1	1
+35	1	1
+553	8	8
+386	1	1
+26	1	1
+540	1	1
+31	1	1
+65	0	1
+625	12	12
+313	0	1
+52	1	1
+22	1	1
+583	1	1
+49	1	1
+1499	3	0
+838	1	1
+19	12	0
+1129	1	1
+36	1	1
+553	8	8
+109	1	1
+45	1	1
+841	16	15
+157	1	1
+31	2	2
+204	18	19
+487	1	1
+29	1	1
+374	1	1
+67	1	1
+720	13	13
+266	10	10
+330	16	14
+413	1	1
+44	1	1
+78	6	6
+181	2	2
+36	1	1
+397	1	1
+20	1	1
+311	1	1
+48	2	2
+1495	1	1
+33	1	1
+216	4	4
+35	1	1
+194	10	10
+310	1	1
+51	1	1
+84	1	1
+101	1	1
+521	1	1
+23	1	1
+242	51	51
+600	1	1
+31	1	1
+413	15	15
+290	1	1
+49	1	1
+527	17	17
+340	12	11
+1025	1	0
+2572	1	1
+29	1	1
+397	2	5
+668	13	13
+541	1	1
+59	0	2
+6	1	1
+122	14	14
+51	1	1
+46	1	1
+187	1	1
+76	1	1
+164	0	21
+136	1	1
+12	1	1
+66	16	16
+456	37	34
+371	7	7
+48	1	1
+194	10	10
+108	1	1
+60	1	1
+122	49	50
+238	1	1
+32	0	1
+100	1	0
+72	1	0
+390	1	1
+38	1	1
+144	1	1
+27	0	4
+184	21	228
+49	1	1
+608	0	1
+152	1	1
+31	1	1
+281	8	8
+337	1	1
+45	1	1
+222	1	1
+54	1	1
+346	1	0
+44	1	1
+368	1	1
+72	1	1
+502	36	18
+63	1	1
+43	0	4
+136	1	1
+42	1	1
+80	4	4
+35	1	0
+89	1	1
+24	0	5
+829	13	13
+73	1	1
+28	14	0
+233	1	1
+42	0	3
+85	0	1
+400	1	1
+40	1	1
+538	25	25
+174	1	1
+20	1	1
+705	1	1
+26	2	2
+614	1	1
+44	1	1
+793	1	1
+16	1	1
+99	38	38
+610	5	5
+804	1	1
+29	1	1
+166	1	1
+43	1	1
+233	1	1
+44	1	1
+507	0	3
+110	8	8
+133	1	1
+31	1	1
+165	1	1
+29	1	1
+1249	1	1
+26	4	0
+56	1	1
+67	1	1
+716	1	1
+46	0	1
+16	1	1
+174	1	1
+96	1	1
+141	1	1
+39	0	4
+263	1	1
+18	1	1
+259	4	4
+38	1	1
+104	1	1
+40	1	0
+248	1	1
+18	1	1
+238	1	1
+32	1	1
+70	0	2
+16	1	1
+818	1	1
+22	4	4
+492	4	4
+1145	1	1
+46	1	1
+53	1	0
+38	1	1
+373	62	62
+1149	0	1
+20	1	1
+1294	1	1
+41	1	1
+316	4	4
+42	1	1
+218	12	12
+363	1	1
+24	1	1
+457	10	10
+414	13	13
+825	1	1
+41	1	1
+492	0	4
+1374	1	1
+18	1	1
+1145	6	4
+880	1	1
+35	1	1
+236	1	1
+67	1	1
+298	0	1
+147	14	14
+312	11	11
+613	1	1
+62	1	1
+340	1	1
+22	1	1
+1057	1	1
+57	1	1
+358	1	1
+128	1	1
+146	10	10
+490	1	1
+20	1	1
+62	1	1
+88	1	1
+293	1	1
+28	1	0
+20	1	1
+83	0	1
+90	1	1
+312	1	1
+44	1	1
+1213	1	1
+51	1	1
+467	1	1
+39	1	1
+122	14	0
+35	1	1
+485	14	14
+110	12	0
+127	1	1
+5450	0	5
+1699	9	9
+3278	0	2
+28	1	1
+2195	18	16
+521	1	1
+18	1	1
+784	18	18
+1603	0	248
+9302	4	4
+72	1	1
+30	0	2
+2359	1	1
+22	0	1
+1244	7	7
+922	2	0
+1507	1	1
+44	1	1
+208	6	1
+1022	34244	40039
+401	1	1
+27	1	1
+369	1	1
+47	1	1
+256	1	1
+27	1	1
+72	1	1
+107	2	0
+21	1	1
+93	89	0
+194	1	1
+33	1	1
+230	1	1
+142	5	5
+108	1	1
+99	1	1
+349	1	1
+31	1	1
+144	1	1
+155	1	1
+56	1	1
+46	1	1
+405	5	6
+148	1	1
+70	1	1
+137	3	3
+67	1	1
+73	22	22
+115	12	12
+142	5	5
+269	15	15
+102	6	6
+93	30	30
+224	1	1
+22	1	1
+459	1	1
+106	1	1
+150	1	1
+50	1	1
+71	1	1
+15	1	0
+258	6	7
+117	1	1
+45	1	1
+123	2	2
+49	1	1
+173	1	1
+28	2	2
+50	1	1
+158	1	1
+186	1	1
+20	1	1
+67	1	1
+25	1	1
+227	2	2
+155	1	1
+777	1	1
+33	1	2
+26	6	6
+474	1	1
+36	1	1
+151	1	1
+29	1	1
+120	1	1
+23	1	1
+736	17	17
+112	1	1
+39	1	1
+553	1	1
+69	1	1
+116	1	0
+1618	9	9
+820	11	11
+173	0	8
+405	9	9
+196	1	1
+26	1	1
+173	1	1
+27	5	1
+42	1	1
+676	17	19
+77	1	3
+65	16	16
+69	1	0
+277	1	1
+44	1	1
+72	0	3
+70	1	1
+54	1	1
+240	1	0
+31	1	1
+1192	18	19
+454	28	28
+373	1	1
+46	1	1
+1565	1	1
+53	2	2
+543	1	1
+38	1	1
+985	1	1
+27	0	1
+8	1	1
+158	0	38
+656	1	1
+104	1	1
+771	1	1
+21	1	1
+398	1	1
+16	1	2
+163	4	3
+94	1	1
+44	1	1
+172	1	0
+122	5	5
+193	16	16
+535	2	2
+17	1	0
+93	1	1
+580	1	1
+91	1	1
+141	1	1
+79	1	1
+80	13	13
+165	1	1
+129	1	1
+114	1	1
+30	1	1
+83	1	1
+35	1	1
+126	16	16
+270	0	1
+111	9	9
+151	1	1
+118	1	1
+253	1	1
+45	20456	22239
+51	5	5
+45	1	1
+53	1	1
+37	1	1
+157	1	1
+279	1	1
+233	1	1
+19	0	8
+67	2	0
+41	1	1
+102	12	12
+275	14	14
+70	1	1
+82	2	2
+224	5	1
+490	0	22
+3841	1	0
+3216	1	1
+42	1	1
+1914	0	3
+616	11	12
+144	1	1
+21	2	1
+775	1	1
+50	1	1
+50	2	2
+96	2	2
+1522	4	0
+58	0	2
+1099	1	1
+42	1	1
+3502	0	6
+255	1	1
+40	1	1
+150	0	4
+18	1	1
+589	1	1
+37	1	1
+539	5	5
+354	1	3
+128	1	1
+58	1	1
+159	1	1
+5	2	0
+21	1	1
+231	1	1
+82	3	3
+69	3	0
+549	1	1
+69	1	1
+74	9	9
+126	1	1
+47	1	1
+614	9	9
+138	1	1
+29	1	1
+681	1	1
+49	1	1
+67	1	1
+19	4	9
+234	1	1
+93	1	1
+60	4	4
+96	4	4
+76	1	1
+169	1	1
+50	1	1
+54	1	1
+312	1	1
+130	1	1
+44	1	1
+69	1	1
+80	1	1
+76	1	1
+41	1	1
+89	0	6
+45	1	0
+363	1	1
+42	1	1
+295	1	1
+43	1	1
+83	6	0
+52	0	2
+1228	1	1
+34	1	1
+3527	20	0
+1768	2	1
+2467	0	2
+101	10	0
+129	1	1
+37	1	1
+121	1	1
+25	1	1
+161	1	0
+97	1	1
+124	1	0
+178	1	1
+34	1	1
+54	1	1
+38	1	2
+670	1	1
+45	1	1
+874	1	1
+40	1	1
+59	0	1
+59	4	4
+316	1	1
+178	1	1
+103	1	1
+61	1	1
+220	63	63
+296	1	1
+33	1	1
+185	12	12
+269	1	1
+84	1	1
+864	15	15
+241	1	0
+79	3	3
+161	1	1
+48	1	1
+539	1	1
+44	1	1
+357	1	1
+37	1	1
+436	1	1
+59	1	1
+71	1	1
+261	1	1
+289	1	1
+47	1	1
+95	12	12
+97	4	4
+27	1	1
+100	1	1
+16	1	1
+101	1	1
+33	1	2
+481	1	1
+42	1	1
+206	7	7
+56	12	12
+179	10	10
+80	1	1
+41	1	1
+251	1	1
+306	1	1
+80	2	0
+4	94	0
+433	1	1
+23	1	1
+107	1	0
+265	1	1
+49	1	1
+282	1	1
+43	1	1
+865	7	7
+60	1	0
+108	1	1
+24	1	1
+134	1	1
+32	1	0
+158	0	2
+1040	1	1
+42	1	1
+737	1	0
+790	1	1
+9	2	1
+11	1	1
+129	1	1
+23	1	1
+894	1	1
+43	3	3
+854	1	1
+23	0	1
+23	2	0
+26	1	1
+395	0	15
+403	5	5
+14	1	1
+2454	1	1
+76	1	1
+170	1	1
+18	1	1
+574	4	0
+291	1	1
+47	1	1
+786	19	0
+88	10	11
+48	1	1
+58	1	1
+28	1	1
+504	0	2
+1276	1	1
+28	1	1
+975	1	0
+3231	1	0
+865	1	1
+39	1	1
+1604	1	1
+56	9	0
+1037	0	1
+510	1	1
+49	1	1
+1253	1	1
+19	1	1
+1078	3	0
+221	1	1
+21	1	0
+899	0	4
+466	1	1
+38	1	1
+297	0	3
+730	19	6
+1043	1	1
+49	1	1
+273	0	1
+708	1	0
+364	14	13
+58	1	1
+74	1	1
+2563	4	0
+531	1	1
+19	1	1
+1944	5	0
+163	6	7
+1206	0	2
+718	1	1
+41	7	0
+1795	13	13
+1390	1	0
+2933	0	16
+540	1	1
+14	1	1
+167	1	0
+897	17	4
+1208	1	0
+1307	1	1
+20	1	1
+540	0	10
+203	2	0
+44	1	1
+298	1	0
+87	11	10
+491	14	8
+991	1	1
+74	6	0
+179	1	1
+34	1	1
+448	10	0
+1688	102	81
+131	1	1
+49	2	1
+2161	30	30
+203	1	0
+89	1	0
+492	1	1
+30	1	1
+1212	3	0
+990	1	1
+38	1	1
+780	1	0
+191	1	1
+47	6	6
+393	1	1
+41	1	1
+259	1	0
+941	1	1
+20	1	1
+185	0	6
+165	0	16
+420	3	1
+130	1	1
+31	1	1
+253	18	18
+720	16	18
+1257	3	0
+986	0	4
+3311	1	1
+26	1	1
+556	0	4
+120	0	1
+1273	1	1
+20	1	1
+4311	0	3
+15	1	1
+2531	17	17
+3334	5	5
+295	1	1
+45	1	1
+94	1	1
+85	0	1
+1603	16	16
+489	1	1
+34	1	1
+1436	1	1
+47	1	1
+273	7	0
+153	0	5
+283	12	12
+619	1	1
+36	0	4
+225	1	1
+23	1	1
+553	5	0
+2334	1	1
+49	1	1
+350	1	1
+31	1	1
+1436	1	1
+46	1	1
+91	4	19
+468	0	1
+46	1	1
+923	37	37
+531	0	4
+426	0	1
+1144	1	2
+1131	1	1
+20	1	1
+1533	16	0
+3103	0	1
+25	1	1
+4034	12	12
+346	0	1
+943	1	0
+524	1	1
+20	1	1
+151	3	3
+144	1	1
+189	1	7
+750	1	0
+695	1	0
+1003	0	2
+9710	0	1
+3177	0	1
+8990	0	1
+2268	1	1
+35	0	10
+8205	1	0
+3193	1	1
+76	1	1
+10955	0	1
+22875	0	20
+2417	1	0
+998	0	13
+4236	8	0
+4845	0	2
+64	40	34
+10941	1	1
+40	1	1
+4759	0	6
+12084	0	3
+3052	0	4
+2989	1	0
+13523	1	3
+16170	1	0
+11761	0	3
+3912	3	0
+6620	0	7
+7633	3	0
+419	2	0
+10690	5	24
+10798	0	1
+296	0	1
+1770	4	0
+374	0	4
+230	16	16
+7468	1	0
+1229	1	0
+3061	1	0
+5818	1	0
+2415	12	9
+2056	0	1
+955	4	0
+20022	0	1
+4418	2	1
+2375	0	4
+2086	1	1
+32	1	1
+1225	1	0
+857	2	0
+1154	0	1
+4667	1	0
+170	0	3
+2376	0	1
+503	37	37
+2259	10	10
+1512	4	0
+68	9	1
+2170	1	1
+47	1	1
+318	2	0
+19	0	6
+14527	1	1
+33	1	1
+3080	1	1
+23	1	1
+1645	6	6
+231	0	1
+2136	2	0
+6222	0	1
+830	1	1
+24	1	1
+8326	1	0
+2939	1	0
+3959	0	2
+3746	0	2
+1011	1	1
+34	1	1
+7443	0	1
+688	2	0
+574	1	1
+29	1	1
+1799	13	1
+4074	2	0
+136	79	79
+528	19	0
+253	0	1
+204	1	0
+129	2	0
+811	1	1
+38	1	1
+2347	52	0
+4634	1	0
+856	14	14
+159	34	38
+855	1	1
+28	1	1
+1255	1	1
+36	1	1
+97	0	1
+58	1	1
+1708	1	1
+48	1	1
+958	15	0
+3371	1	1
+37	1	1
+4267	0	13
+1061	0	1
+272	0	26
+8	1	15
+25	0	2
+112	2	0
+26	4	32
+4090	0	1
+3270	1	1
+17	1	1
+2822	0	1
+6206	1	0
+2318	0	2
+1504	0	1
+6189	3	0
+396	22	12
+918	0	1
+2340	1	1
+33	1	1
+326	1	1
+80	1	1
+205	3	2
+81	8	17
+2671	0	1
+1099	0	1
+144	1	1
+29	0	1
+2097	0	3
+24	3	0
+1207	4	4
+45	1	1
+757	0	5
+1926	1	1
+40	1	1
+2657	0	1
+414	1	0
+61	0	1
+235	0	2
+2087	0	1
+754	0	4
+17	3	0
+1027	3	0
+428	1	1
+17	1	1
+948	1	1
+41	1	1
+458	1	1
+21	1	1
+1055	0	1
+6611	0	3
+1575	4	5
+36	1	1
+99	2	0
+700	0	2
+151	0	1
+467	11	11
+272	0	3
+40	1	1
+2428	0	1
+750	2	0
+473	0	2
+421	1	1
+34	1	1
+1575	1	0
+3841	1	0
+560	1	0
+1108	1	0
+8087	1	0
+11881	1	1
+30	1	1
+4406	2	0
+183	1	1
+9871	0	1
+906	3	0
+887	1	1
+80	1	1
+3115	0	1
+1037	1	0
+5866	0	2
+18	1	1
+582	0	5
+2828	1	0
+847	1	0
+1996	3	0
+700	1	1
+2469	1	0
+1751	0	1
+910	3	0
+691	0	1
+5793	0	1
+26407	1	0
+672	0	1
+19269	1	1
+28	0	6
+1371	29	0
+494	2	0
+20417	1	0
+18633	0	1
+601	1	0
+319	0	1
+6820	1	0
+5718	0	2
+17894	1	0
+4272	1	0
+4967	3	1
+290	1	0
+2447	1	0
+740	1	9
+9299	0	18
+7427	1	0
+8151	2	1
+673	1	0
+3453	0	1
+149	0	1
+611	0	4
+4669	0	4
+176	1	1
+3229	0	1
+1092	2	0
+159	1	0
+4480	0	2
+4019	0	1
+1451	22	23
+816	1	0
+8701	1	1
+23	1	1
+1796	2	0
+5015	6	1
+1383	8	0
+2368	1	1
+31	1	0
+1883	3	0
+335	0	1
+4157	0	1
+561	4	0
+1538	1	1
+61	0	1
+159	0	2
+3362	4	0
+3333	1	1
+46	1	1
+2321	7	6
+150	1	0
+5972	0	2
+840	0	2
+55	1	1
+28	1	1
+1154	0	2
+650	0	4
+30	0	4
+1100	10	11
+4343	6	0
+1663	4	0
+150	1	0
+3128	1	0
+1449	1	0
+2023	0	1
+428	3	6
+299	2	0
+427	7	7
+1914	14	14
+1273	7	7
+1444	72	0
+423	0	4
+969	23	22
+2430	1	0
+190	8	8
+2034	3	1
+5337	42	42
+1017	1	1
+34	1	1
+485	1	0
+348	7	0
+770	1	1
+28	0	13
+1425	0	1
+302	0	1
+659	12	12
+293	0	1
+610	0	1
+906	12	0
+1331	0	6
+1686	26	26
+74	0	1
+463	0	1
+4305	0	4
+1041	1	0
+11424	3	1
+13797	0	8
+166	0	1
+1510	5	0
+9069	0	8
+25	1	1
+332	5	3
+76	0	1
+1306	1	1
+46	1	1
+134	19	23
+1467	1	1
+32	1	1
+449	17	0
+367	9	9
+3525	12	10
+91	3	0
+226	33	33
+1171	1	1
+24	1	1
+1156	9	13
+843	1	1
+28	1	1
+515	0	17
+1559	0	4
+1045	9	9
+1953	1	0
+31	1	1
+843	0	1
+2174	1	0
+3788	1	0
+2001	0	1
+2400	0	1
+1614	1	0
+8167	0	1
+2700	2	0
+2735	0	1
+8708	0	3
+448	1	1
+22	1	1
+2215	1	1
+32	1	1
+2413	14	14
+142	1	0
+789	1	1
+45	1	1
+154	1	1
+25	1	1
+465	1	1
+45	6	4
+541	1	1
+42	1	1
+1339	5	6
+391	1	1
+20	0	1
+251	1	1
+22	1	1
+561	0	2
+78	3	0
+1718	1	1
+12	1	1
+1042	1	1
+38	1	1
+301	14	0
+222	10	10
+436	10	10
+1564	1	1
+17	1	1
+1752	20	0
+1561	135	0
+58	0	45
+245	101	11
+46	90	0
+150	0	270
+54	180	0
+2130	12	12
+1630	1	1
+26	1	1
+189	0	14
+296	2	0
+809	2	0
+17	20	0
+665	0	40
+236	1	1
+44	1	1
+352	1	1
+25	1	1
+554	6	6
+850	1	1
+33	1	1
+809	3	13
+1832	7	9
+468	1	1
+21	1	1
+951	1	1
+22	1	1
+219	17	18
+733	0	14
+215	2	2
+36	1	1
+301	1	1
+22	1	1
+241	1	1
+52	0	1
+47	1	1
+72	1	1
+109	1	1
+129	1	1
+28	1	1
+174	8	8
+683	3	0
+1190	285	0
+439	13	13
+927	12	0
+557	17	17
+932	3	1
+27	1	1
+166	1	1
+19	1	1
+406	1	1
+48	3	3
+137	1	0
+161	6	6
+884	2	0
+58	1	1
+107	1	1
+150	14	14
+522	1	1
+28	1	1
+945	4	4
+34	1	1
+472	0	2
+203	0	1
+281	1	1
+46	1	1
+1130	1	0
+232	17	17
+510	1	1
+33	1	1
+62	10	10
+1501	1	1
+20	1	1
+573	1	1
+29	1	1
+928	0	3
+304	1	1
+41	1	1
+160	1	1
+58	1	1
+656	1	1
+40	4	0
+108	6	6
+321	1	1
+14	0	16
+91	1	1
+184	1	1
+43	8	3
+180	1	1
+68	1	1
+144	1	1
+27	1	0
+17	1	1
+212	0	1
+212	1	1
+34	1	1
+115	1	1
+41	1	1
+407	10	10
+200	1	1
+44	2	0
+187	2	0
+146	1	1
+17	1	1
+122	4	4
+73	1	0
+56	1	1
+155	1	17
+80	15	15
+458	1	1
+16	3	3
+343	1	1
+111	1	1
+201	14	14
+157	12	12
+346	0	2
+382	4	0
+35	1	1
+937	0	1
+246	25	0
+52	0	1
+419	0	1
+165	1	0
+75	24	3
+297	1	1
+38	1	1
+5066	1	0
+4922	7	9
+2488	14	14
+2241	1	1
+67	4	4
+39	1	0
+547	1	1
+43	1	1
+524	3715	901
+1796	4	2
+128	29	29
+415	1	1
+18	1	1
+367	0	89
+1600	0	6
+2175	0	5
+606	14	14
+519	1	0
+540	1	1
+40	1	1
+568	2	0
+165	1	2
+31	1	1
+259	1	1
+41	1	1
+1106	40	62
+818	1	1
+42	1	1
+565	1	1
+44	1	1
+571	10	8
+61	1	1
+28	1	1
+233	2	0
+33	28	0
+53	1	1
+37	1	1
+75	0	396
+156	1	0
+473	0	4
+421	1	1
+35	1	1
+2132	1	1
+80	0	2
+544	9	9
+152	2	1
+33	1	1
+2977	0	1
+164	22	0
+149	1	0
+534	1	1
+36	1	1
+113	1	1
+15	1	1
+661	1	1
+48	1	1
+1987	1	0
+34	1	1
+444	1	1
+45	1	1
+65	1	1
+67	1	1
+210	1	1
+68	1	1
+55	1	1
+47	1	1
+169	1	1
+64	1	1
+109	0	6
+77	2	32
+6	0	5
+67	0	1
+7	16	0
+51	12	0
+36	0	12
+700	1	1
+33	1	0
+49	0	2
+450	0	1
+98	4	0
+489	32	0
+63	5	1
+78	7	7
+538	17	17
+1269	1	0
+841	1	1
+43	1	1
+1257	49	49
+698	1	1
+41	1	1
+86	0	4
+5	1	0
+36	1	1
+573	2	1
+297	1	0
+85	1	1
+30	1	1
+1041	1	0
+12	1	1
+392	33	12
+515	5	6
+583	1	1
+33	1	1
+616	16	16
+1052	0	11
+39	1	1
+184	1	1
+67	1	1
+102	7	7
+58	0	1
+307	1	1
+56	0	3
+918	2	0
+1295	0	1
+832	1	1
+28	1	1
+272	1	1
+82	1	1
+56	1	0
+976	6	6
+2015	0	3
+84	9	9
+130	13	17
+564	10	15
+154	1	0
+438	10	10
+38	0	5
+2141	1	1
+25	1	1
+73	10	10
+70	5	5
+132	1	1
+52	1	1
+599	1	1
+46	1	1
+279	1	1
+18	1	1
+239	2	0
+383	6	0
+224	0	1
+321	3	0
+8	16	0
+1775	1	1
+18	2	0
+575	16	16
+60	1	1
+16	1	1
+1247	2	0
+173	3	0
+41	1	1
+57	8	8
+285	2	0
+672	1	1
+44	1	1
+106	0	1
+148	1	1
+49	3	0
+146	5	11
+91	1	1
+79	1	1
+94	1	1
+101	1	1
+88	16	16
+117	1	1
+15	1	1
+58	1	1
+93	1	1
+140	1	0
+326	1	1
+44	1	1
+160	1	1
+23	1	1
+481	14	14
+181	4	4
+72	1	1
+25	1	1
+88	1	3
+36	0	12
+92	1	1
+56	10	0
+13	0	1
+66	1	1
+141	2	0
+65	1	1
+367	0	2
+610	1	1
+22	1	1
+150	1	1
+85	1	1
+109	1	1
+167	3	1
+23	1	0
+26	1	1
+74	1	1
+33	1	1
+176	1	1
+25	2	2
+193	42	43
+377	0	5
+249	1	1
+69	1	1
+98	1	1
+62	1	1
+62	1	2
+74	0	1
+68	1	1
+438	1	1
+64	1	1
+47	0	8
+125	3	0
+75	5	5
+45	1	1
+197	1	1
+27	1	1
+116	13	13
+218	15	20
+1107	16	19
+73	1	1
+25	1	1
+199	1	1
+60	1	1
+994	1	1
+43	0	1
+18	1	1
+1215	18	18
+340	1	1
+34	1	1
+1358	8	8
+1726	4	4
+193	82	82
+263	1	1
+18	1	1
+411	19	19
+175	1	1
+49	1	1
+146	1	1
+61	1	1
+116	1	1
+41	1	1
+137	1	1
+30	1	1
+158	9	9
+136	10	13
+349	8	8
+468	1	1
+44	1	1
+862	17	17
+813	1	1
+24	1	1
+214	10	4
+228	1	1
+34	1	1
+101	12	12
+242	1	1
+69	1	1
+185	1	1
+24	1	0
+164	0	1
+222	1	1
+25	1	1
+297	10	10
+1171	1	0
+182	1	1
+35	1	1
+2335	83	83
+491	7	7
+208	13	12
+298	1	1
+65	1	1
+193	2	2
+28	1	1
+125	4	4
+95	7	7
+566	1	1
+40	1	1
+118	0	1
+318	1	0
+374	1	1
+58	1	1
+143	1	1
+74	1	1
+53	21	0
+81	1	1
+45	1	1
+138	15	16
+180	1	1
+62	1	1
+661	1	1
+48	1	1
+1463	1	0
+156	0	1
+148	1	1
+19	1	0
+17	1	1
+1927	4	0
+1469	14	14
+466	0	1
+3098	0	1
+1141	2	3
+743	14	14
+79	1	1
+22	1	1
+362	0	1
+682	16	9
+275	0	4
+462	1	1
+76	1	0
+47	1	0
+13	0	8
+331	0	4
+130	1	1
+31	0	3
+1554	1	1
+43	1	1
+224	1	1
+49	1	1
+159	3	0
+1064	27	27
+104	1	1
+21	1	1
+222	2	2
+49	1	1
+1397	1	1
+37	1	1
+414	0	2
+695	1	1
+31	1	1
+742	1	1
+21	1	1
+230	3	2
+42	1	1
+68	1	1
+37	1	1
+703	0	3
+2216	1	1
+82	1	0
+1430	1	1
+23	1	1
+1867	13	0
+35	1	1
+137	16	16
+1500	4	0
+4546	1	1
+25	1	1
+1926	1	1
+39	4	3
+1037	1	1
+40	2	0
+890	6	0
+41	2	0
+498	3	0
+321	0	1
+281	3	0
+414	1	1
+70	1	1
+284	1	0
+214	1	1
+28	1	1
+280	1	0
+650	1	1
+47	1	1
+1030	1	1
+91	1	1
+6520	5	5
+478	1	0
+76	1	1
+2771	0	3
+1930	0	4
+2915	1	1
+20	1	1
+413	1	0
+1844	11	11
+133	0	6
+569	10	10
+110	12	12
+184	0	3
+228	1	1
+43	2	2
+51	14	13
+1499	1	0
+12	1	1
+378	1	1
+49	1	1
+424	1	0
+1131	1	1
+80	0	1
+821	2	9
+311	1	6
+247	1	1
+86	1	1
+1850	1	1
+26	1	1
+498	1	1
+34	1	1
+688	5	9
+44	1	1
+369	1	1
+69	1	1
+156	2	0
+83	1	1
+128	1	1
+50	9	9
+249	1	1
+70	0	1
+624	2	0
+74	2	1
+300	1	1
+26	1	1
+240	4	0
+1705	1	1
+52	1	1
+231	29	24
+378	2	0
+236	1	1
+76	1	1
+116	9	12
+380	0	6
+43	1	1
+384	15	15
+1414	5	0
+225	0	2
+1234	1	0
+29	1	1
+235	10	10
+227	1	1
+77	4	0
+43	5	9
+485	7	7
+380	10	0
+46	1	0
+90	1	1
+161	1	1
+401	1	1
+58	1	1
+2127	3	0
+186	20	20
+323	5	5
+47	1	1
+236	1	1
+31	0	2
+1692	13	14
+202	0	3
+77	1	1
+44	1	1
+411	12	11
+317	0	2
+599	39	39
+391	1	0
+273	1	0
+744	0	4
+703	1	1
+20	1	1
+198	3	0
+158	1	1
+14	4	0
+27	12	0
+282	1	1
+32	4	0
+740	1	0
+327	1	1
+105	1	1
+146	16	16
+101	1	0
+21	1	1
+232	1	1
+33	2	0
+12	1	1
+189	1	1
+30	2	2
+544	1	1
+153	1	1
+586	5	0
+1351	21	0
+446	1	1
+32	1	1
+136	7	7
+1147	12	12
+734	44	43
+701	1	1
+29	2	2
+154	12	12
+191	1	1
+55	1	1
+28	0	1142
+172	15	18
+525	1	1
+22	1	1
+355	10	10
+50	0	8
+252	1	1
+31	1	1
+354	6	5
+148	15	15
+407	1	1
+42	1	1
+275	0	1
+737	5	9
+1432	1	1
+39	1	1
+84	0	2
+77	7	7
+919	7	1
+815	1	1
+45	1	1
+487	1	1
+66	1	1
+2379	0	24
+779	1	1
+18	1	0
+2653	4	0
+34	1	1
+191	1	1
+35	1	1
+1174	12	0
+2497	25	1525
+447	8	0
+3268	1	0
+946	1	0
+2277	0	2
+1446	1	1
+77	1	1
+313	1	1
+44	1	0
+52	19983	20030
+61	7	7
+61	1	1
+120	1	1
+366	1	1
+55	1	1
+121	1	1
+62	1	1
+78	1	1
+48	1	1
+161	1	1
+26	1	1
+191	1	1
+20	11	11
+550	1	1
+76	1	0
+20	1	1
+112	1	1
+149	1	1
+284	1	1
+37	1	1
+705	1	12
+106	12	12
+83	1	1
+46	1	1
+1500	1	1
+81	1	1
+210	1	1
+26	1	1
+713	1	1
+48	1	1
+723	0	3
+196	6	6
+62	2	2
+32	1	1
+606	1	2
+357	1	1
+38	292	0
+589	1	1
+30	1	1
+714	8	8
+639	1	1
+20	1	1
+1068	0	1
+571	1	1
+49	1	1
+436	0	1
+609	0	2
+30	1	1
+66	0	1
+349	11	11
+65	1	1
+40	1	1
+717	0	3
+299	1	1
+29	1	1
+724	1	0
+275	1	1
+33	1	1
+318	0	3
+279	1	1
+28	1	1
+389	1	0
+548	0	8
+330	1	1
+47	1	1
+170	1	1
+47	1	1
+519	14	14
+841	24	24
+732	1	1
+29	3	3
+688	2	2
+23	0	1
+94	14	14
+726	13	13
+508	0	12
+21	6	0
+69	1	1
+37	1	1
+590	1	1
+59	1	1
+89	11	11
+164	1	1
+58	1	1
+1709	18	18
+520	1	1
+27	1	1
+683	10	10
+814	1	1
+26	1	1
+350	1	1
+39	1	1
+132	6	6
+439	1	1
+38	41	6
+15	0	1
+5	4	11
+81	1	1
+19	0	2
+167	1	1
+90	0	2
+85	1	1
+78	1	1
+87	19	2
+53	23	0
+255	0	1
+211	1	1
+54	1	1
+206	0	1
+60	35	33
+279	1	1
+76	179	180
+90	1	1
+119	3	0
+19	1	1
+60	1	1
+347	0	4
+30	2	2
+68	1	1
+78	1	1
+298	5	5
+67	1	1
+99	1	1
+97	1	1
+74	1	1
+52	1	1
+44	1	1
+65	1	4
+349	14	14
+109	1	1
+159	2	2
+214	9	9
+97	1	1
+73	1	1
+58	1	1
+42	1	1
+133	1	1
+99	0	10
+124	12	12
+281	3	0
+940	2	2
+49	1	1
+303	1	1
+25	1	1
+309	15	22
+384	1	1
+24	1	1
+896	1	1
+56	1	1
+168	0	19
+54	0	6
+60	0	1
+13	1	1
+502	1	1
+4	0	1
+23	1	1
+581	1	1
+47	1	1
+122	15	15
+3352	1	1
+23	1	1
+873	4	4
+887	1	0
+1827	1	0
+216	6	6
+805	2	0
+874	0	8
+2266	1	1
+47	1	1
+736	25	29
+86	1	1
+19	1	1
+1794	9	9
+271	0	1
+2266	1	1
+34	1	1
+916	0	1
+21	1	1
+108	21	21
+141	1	1
+27	1	1
+406	3	0
+3830	59	59
+61	1	1
+38	1	1
+128	2	2
+56	1	1
+72	0	1
+96	1	1
+22	1	1
+169	7	7
+511	1	1
+38	1	1
+1070	1	1
+90	1	1
+50	1	1
+41	1	0
+30	1	1
+659	12	12
+701	1	1
+33	1	1
+569	15	15
+70	1	1
+38	1	1
+955	0	3
+130	1	1
+63	1	1
+251	8	8
+191	1	1
+26	0	3
+187	1	0
+916	5	1
+70	13	13
+498	1	0
+55	0	1
+242	25	25
+237	1	1
+20	0	1
+61	1	1
+203	6	6
+262	1	1
+154	1	1
+104	1	1
+20	1	1
+156	1	1
+32	1	1
+88	17	17
+139	13	13
+148	20091	20061
+944	1	1
+126	1	1
+81	6	6
+41	3	0
+641	1	1
+92	1	0
+113	1	1
+39	1	1
+671	1	1
+28	1	1
+123	1	1
+59	1	1
+210	1	1
+17	1	1
+168	15	14
+494	1	0
+22	1	1
+484	18	18
+376	1	1
+114	2	0
+67	1	1
+10	1	1
+109	1	1
+165	1	1
+149	6	6
+234	1	1
+19	5	5
+64	1	1
+111	1	1
+220	1	1
+89	1	1
+119	1	1
+113	2	0
+168	1	1
+73	1	1
+194	1	1
+50	0	4
+37	1	1
+95	3	1
+43	1	1
+153	1	1
+83	1	1
+55	1	1
+39	1	1
+70	7	0
+59	7	7
+75	1	1
+84	2	2
+110	1	0
+42	1	1
+341	13	13
+262	4	4
+67	1	1
+32	1	0
+38	1	1
+277	7	7
+318	1	1
+145	1	1
+90	1	1
+19	4	4
+61	1	2
+31	1	1
+52	1	1
+214	1	1
+61	10083	10104
+701	2	0
+4080	1	1
+38	1	1
+837	0	64
+172	1	1
+55	1	1
+1818	2	0
+1143	13	13
+335	1	0
+1944	5	0
+39	6	0
+4057	3	8
+9465	5	4
+301	19	1
+191	84	0
+427	1	1
+29	0	4
+157	4	5
+296	21	18
+158	2	2
+36	1	1
+539	13	13
+399	1	1
+46	1	1
+348	1	1
+49	1	1
+268	1	0
+66	0	4
+178	2	2
+107	1	1
+133	5	5
+355	1	1
+30	1	1
+346	1	1
+29	1	1
+161	1	1
+38	1	1
+121	4	4
+55	8	8
+67	7	7
+318	17	17
+259	1	1
+94	1	1
+80	1	1
+35	1	1
+260	1	1
+81	1	1
+106	1	1
+58	1	2
+55	1	1
+245	3	0
+2052	1	1
+40	1	1
+174	20	22
+574	0	2
+414	1	0
+234	0	1
+425	51224	51060
+13549	39	40
+2617	0	2
+884	1	1
+19	1	1
+676	1	1
+63	1	1
+3138	0	3
+3038	5	2
+132	10	6
+136	18	13
+363	1	1
+89	1	1
+382	1	1
+29	1	1
+58	8	7
+297	4	0
+66	1	1
+93	2	0
+145	1	1
+31	5	5
+576	1	1
+89	1	1
+1256	0	12
+67	1	1
+193	2	2
+23	1	1
+51	1	0
+727	1	0
+1148	12	12
+837	1	1
+77	1	1
+941	10	10
+776	19	19
+300	1	1
+24	1	1
+256	1	7
+93	1	1
+191	174	172
+563	1	1
+104	4	4
+2898	1	1
+46	1	1
+282	1	1
+39	1	1
+204	2	2
+22	1	1
+469	1	1
+20	1	1
+140	1	1
+26	1	1
+745	0	2
+539	0	6
+1536	1	0
+817	4	4
+202	1	1
+48	1	1
+168	1	1
+53	1	1
+379	10	10
+1178	14	14
+132	5	0
+555	1	1
+42	1	1
+573	1	1
+21	1	1
+462	1	1
+43	1	1
+121	1	1
+48	0	3
+15	1	5
+1404	0	1
+934	1	1
+49	1	1
+1350	1	0
+384	1	1
+24	1	1
+3117	10	10
+1042	0	15
+244	10	10
+2167	18	14
+64	1	1
+31	1	1
+185	0	4
+1647	1	1
+20	1	1
+227	1	1
+37	1	1
+636	3	4
+5590	1	1
+39	1	1
+461	0	2
+2145	1	1
+23	1	1
+1114	0	2
+688	0	1
+901	18	18
+4781	0	4
+815	0	1
+5069	0	5
+415	0	1
+2743	1	1
+78	1	1
+390	1	0
+328	0	1
+878	0	1
+5752	0	2
+1554	1	1
+60	1	1
+278	0	1
+19	1	1
+1164	11	11
+691	0	2
+960	1	0
+62	0	20
+2108	0	2
+1265	0	1
+1642	2	0
+3584	2	0
+12086	2	0
+3766	0	2
+1209	1	7
+3466	1	0
+1448	1	0
+1943	0	1
+698	0	8
+1166	1	1
+34	1	1
+2120	11	9
+540	1	0
+1736	14	0
+3128	0	2
+4464	0	1
+120	4	4
+3473	1	0
+378	1	0
+1269	0	3
+1182	1	0
+654	0	3
+2049	1	0
+6838	1	1
+69	0	3
+154	1	0
+2718	1	1
+30	1	1
+160	11	11
+4954	0	1
+420	1	1
+123	1	1
+156	0	4
+219	4	0
+195	1	0
+4402	3	0
+3045	0	1
+1249	1	0
+3522	0	10
+812	8	0
+346	0	1
+8538	5	0
+455	1	0
+119	0	1
+1127	1	0
+10948	1	0
+833	0	1
+4251	1	0
+8	1	1
+2079	0	1
+1735	8	12
+1612	0	1
+1373	5	0
+8585	7	0
+64	1	1
+3799	1	0
+258	2	0
+899	1	0
+1362	8	9
+593	0	2
+3351	2	0
+618	0	4
+905	2	15
+2797	1	0
+2776	2	0
+4110	0	6
+4466	18	18
+2267	0	4
+134	1	0
+12963	8	0
+1616	0	2
+1685	2	0
+2225	2	0
+428	0	1
+3338	0	3
+677	4	6
+325	11	1
+1887	0	1
+913	0	1
+997	5	5
+2814	17	15
+1389	1	0
+1200	0	4
+2495	1	0
+3921	26431	26426
+2419	0	1
+6110	0	1
+1370	0	1
+3085	1	0
+3568	1	1
+24	0	9
+597	1	0
+2642	1	0
+1545	10	0
+4952	0	1
+6146	2	0
+1452	1	0
+2967	1	0
+4920	5	0
+147	4	5
+850	1	0
+1875	1	0
+695	3	1
+1719	0	1
+259	0	1
+294	1	0
+128	0	2
+3051	0	1
+908	0	4
+3399	0	1
+909	17	17
+3747	1	0
+3179	1	0
+411	1	1
+44	1	1
+174	1	0
+1047	17	17
+998	178	0
+671	0	40
+2093	1	0
+313	0	1
+7168	78	78
+335	1	0
+3245	1	0
+972	0	4
+4085	2	0
+346	1	1
+45	1	1
+368	1	0
+26	1	1
+8444	0	1
+17044	1	0
+2795	2	0
+2860	1	0
+622	0	1
+167	0	5
+1968	0	2
+259	2	0
+4992	29	27
+170	1	0
+3528	0	1
+191	1	2
+117	2	0
+2275	1	0
+12676	1	1
+20	1	1
+9972	1	0
+13955	0	5
+19867	1	0
+5866	0	32737
+3746	1	0
+20549	1	1
+19	1	1
+970	8	8
+5220	1	0
+15573	0	1
+6799	0	16
+3350	0	1
+7574	0	12
+2132	0	1
+7228	52793	52800
+2675	0	1
+2149	1	0
+6880	0	2
+960	0	1
+23	1	1
+2646	2	0
+3867	5	0
+24765	29	29
+1283	0	3
+3174	1	0
+8183	0	1
+2817	10	0
+4539	43	43
+1259	1	0
+2081	0	1
+374	0	2
+3589	0	4
+13928	3	0
+773	7	7
+175	1	1
+79	1	1
+400	12	12
+1096	0	4
+717	7	7
+52	1	1
+68	5	1
+2117	0	3
+130	14	14
+1124	0	3
+413	0	4
+643	3	0
+58	1	1
+127	1	1
+208	0	2
+45	1	1
+168	3	0
+136	3	4
+79	44	44
+170	1	1
+25	0	3
+63	1	1
+417	0	2
+412	0	16
+737	4	0
+402	2	0
+654	1	1
+42	1	1
+75	1	1
+64	1	1
+938	1	1
+53	1	1
+1987	4	0
+576	0	1
+29	2	2
+715	1	1
+36	1	1
+767	4	40
+44	1	5
+43	49	5
+709	21	21
+1147	9	9
+22	1	1
+195	7	4
+659	3	0
+27	1	1
+637	1	1
+42	1	1
+531	1	1
+67	1	1
+39	1	0
+717	11	11
+53	1	1
+61	1	1
+1535	1	1
+89	0	1
+49	1	0
+102	1	1
+67	1	1
+76	1	1
+129	1	1
+85	1	1
+607	10	0
+12	137	1
+41	1	1
+1043	1	1
+22	1	1
+203	3	0
+480	14	21
+1459	2	1
+435	15	17
+1188	30	0
+1778	1	0
+120	0	3
+3797	1	0
+887	1	1
+58	1	1
+2264	0	1
+2456	4	0
+954	0	4
+1847	0	1
+5929	20	20
+984	14	0
+2112	1	0
+2013	1	0
+4884	1	0
+1160	16	0
+733	7	7
+238	3	2
+2203	2	1
+5654	1	1
+28	5	10
+482	0	1
+2970	0	4
+2892	0	1
+251	1	7
+1346	1	0
+877	0	4
+3583	0	1
+1178	0	1
+1293	0	2
+491	2	0
+3501	46	46
+3256	1	1
+22	1	1
+2218	1	1
+44	1	1
+4780	4	0
+3026	14	13
+442	5	5
+2022	6	6
+546	2	0
+31	1	1
+8485	1	1
+36	1	0
+1575	1	0
+1329	1	1
+35	1	0
+247	1	1
+16	1	1
+184	1	1
+18	1	1
+1607	53	60
+527	1	1
+39	1	1
+653	3	0
+227	1	1
+18	1	1
+218	0	323
+91	1	0
+124	0	15
+621	0	2
+555	8	8
+467	1	1
+40	1	1
+372	1	1
+25	1	1
+188	12	12
+357	0	2
+2389	1	1
+22	1	1
+2579	0	5
+461	1	1
+36	1	1
+1584	1	1
+26	1	0
+429	1	0
+33	1	1
+1071	0	4
+1068	9	0
+1472	0	2
+1859	1	1
+61	2	0
+9	1	1
+337	1	1
+46	1	1
+416	1	1
+42	1	1
+1060	25	25
+170	0	2
+628	17	15
+587	15	15
+398	3	0
+696	6	9
+287	10	0
+191	0	2
+493	1	1
+42	4	0
+219	0	1
+408	1	1
+23	1	1
+283	1	1
+21	1	1
+633	2	0
+241	6	6
+457	1	0
+330	0	16
+428	1	0
+4	6	0
+324	0	1
+3063	0	2
+9960	39	40
+1850	0	6
+6431	0	1
+8674	0	4
+4595	11	0
+5064	2	0
+2813	12	12
+1391	5	0
+3690	1	1
+64	1	1
+2635	1	1
+49	1	1
+69	1	1
+15	1	1
+1009	8	0
+735	0	20
+3074	2	0
+1879	0	1
+572	0	8
+576	1	1
+42	1	1
+265	24	0
+209	11	11
+953	1	1
+42	0	5
+58	1	0
+95	1	0
+1121	1	1
+17	1	1
+751	0	1
+24	1	1
+351	1	1
+43	3	3
+565	1	1
+15	1	1
+150	27	27
+94	1	0
+323	1	1
+23	1	1
+221	7	7
+705	9	0
+631	2	0
+64	1	1
+1577	1	1
+21	0	1
+371	7	21
+160	0	1
+283	1	1
+48	1	1
+227	1	1
+40	0	1
+1359	0	2
+836	13	13
+722	7	7
+1153	1	1
+93	1	1
+797	14	14
+433	8	0
+108	11	11
+140	1	1
+40	1	1
+470	1	1
+42	1	1
+1106	0	1
+85	4	4
+129	1	1
+123	1	0
+95	1	1
+104	6	1
+641	1	1
+77	1	1
+57	1	1
+62	1	1
+473	2	0
+262	6	0
+45	1	1
+63	2	0
+39	1	1
+267	0	1
+197	2	104
+87	111	0
+122	0	7
+88	0	4
+108	5	0
+563	14	14
+324	1	0
+205	1	1
+17	1	1
+495	0	1
+201	4	0
+14	1	1
+887	1	1
+58	1	1
+133	1	1
+24	1	1
+91	24	24
+342	1	1
+32	1	1
+121	1	1
+62	1	1
+2371	2	0
+164	8	1
+655	1	1
+30	1	1
+271	1	1
+47	1	1
+609	1	0
+1780	2	0
+742	1	1
+40	1	1
+2014	1	0
+1741	3	0
+3833	0	1
+16381	3	3
+25	1	1
+234	161226	190028
+3106	0	1
+1680	1	1
+88	1	1
+4502	0	1
+46	1	1
+800	4	4
+23	1	1
+1305	2	0
+136	0	1
+4941	0	1
+547	0	1
+70	8	8
+293	1	1
+35	1	1
+1165	4	0
+6662	1	1
+46	1	1
+167	0	8
+214	1	1
+35	1	1
+108	1	0
+1063	0	1
+1017	1	1
+20	0	6
+1725	0	1
+134	68	67
+349	1	1
+24	0	1
+1562	1	1
+31	1	1
+2513	0	1
+73	36	36
+305	1	1
+27	1	1
+543	1	1
+47	4	28
+4387	20058	20058
+159	1	1
+36	1	1
+107	1	1
+176	1	1
+154	0	5
+91	1	1
+54	1	1
+77	1	1
+238	2	2
+50	1	1
+1421	1	1
+23	1	1
+216	1	1
+122	1	1
+86	1	1
+41	3	1
+336	7	7
+41	9	0
+107	1	1
+90	8	9
+53	1	1
+30	1	1
+213	1	1
+26	1	1
+138	1	1
+25	1	1
+206	1	1
+36	3	3
+37	7	0
+500	1	1
+52	1	1
+52	1	1
+48	1	1
+395	1	1
+66	6	6
+72	1	0
+69	1	1
+100	10	10
+160	1	0
+64	7	7
+89	1	1
+123	1	1
+128	1	1
+36	1	1
+231	1	1
+61	1	1
+564	8	8
+593	1	1
+45	1	1
+163	1	0
+196	8	8
+174	5	5
+37	1	1
+67	0	1
+192	1	1
+60	3	0
+19	1	1
+1149	1	1
+18	1	1
+77	1	1
+32	2	0
+32	1	1
+136	1	1
+78	2	0
+162	4	0
+41	1	1
+351	13	13
+1634	2	0
+229	8	8
+57	13	2
+410	1	1
+76	1	1
+180	1	1
+92	1	1
+270	1	1
+40	1	1
+92	1	1
+53	1	1
+227	1	1
+42	1	1
+357	4	4
+23	1	1
+94	1	0
+200	6	0
+201	7	7
+70	5	13
+57	4	0
+35	1	1
+206	1	1
+76	2	2
+651	1	1
+68	4	0
+73	1	1
+49	4	0
+37	1	1
+145	2	2
+78	2	2
+108	12	12
+52	1	1
+35	1	1
+242	1	3
+76	2	2
+50	12	12
+70	1	1
+33	0	2
+57	1	1
+64	15	15
+168	1	1
+22	1	1
+66	2	2
+6	0	1
+24	1	1
+73	0	2
+64	1	1
+177	2	0
+19	4	0
+55	1	0
+33	1	1
+51	1	1
+122	1	1
+296	1	1
+85	1	1
+109	1	1
+64	1	1
+155	1	1
+58	0	2
+72	1	1
+25	1	1
+128	1	1
+45	2	0
+334	4	4
+106	1	1
+25	1	1
+64	1	1
+21	1	1
+368	15	15
+734	2	0
+701	15	15
+71	1	1
+41	1	1
+77	1	1
+56	1	1
+478	2	0
+714	8	7
+95	2	2
+50	4	3
+1129	1	1
+34	1	1
+1715	1	1
+87	1	1
+692	1	1
+47	0	1
+75	1	1
+2155	10	10
+1265	1	1
+46	1	1
+298	1	1
+22	1	1
+186	1	1
+34	1	1
+202	1	1
+61	1	0
+185	1	1
+24	1	0
+98	0	2
+258	8	14
+967	1	1
+15	1	1
+625	1	0
+1362	0	4
+23365	4	0
+246	26975	26986
+3307	0	1
+13671	3	3
+52	1	1
+1308	2	0
+942	0	1
+17790	1	0
+4586	0	1
+949	0	2
+15047	0	1
+606	2	0
+7820	0	4
+22313	16	0
+10539	8	0
+4836	0	1
+8726	2	0
+194	1	1
+49	1	1
+320	1	1
+34	1	1
+6813	0	1
+8719	3	0
+5482	46	46
+1509	1	0
+721	0	1
+999	6	0
+17	1	0
+3075	5	0
+593	13	11
+4505	1	0
+9535	0	4
+23	0	2
+23	2	0
+513	0	3
+377	1	0
+2627	0	2
+16	0	1
+211	18	18
+571	2	0
+7617	0	1
+1607	1	0
+69	1	1
+66	1	1
+275	1	1
+67	7	0
+25	1	1
+1206	1	0
+136	8	7
+612	1	1
+61	1	1
+740	0	2
+233	1	1
+95	0	4
+1483	13	28
+1062	1	0
+108	4	0
+685	0	2
+1566	1	0
+192	4	4
+1452	9	45
+1514	1	1
+46	1	1
+1969	0	1
+35	1	1
+1094	1	0
+618	1	1
+43	1	1
+6580	1	0
+1636	5	0
+6325	1	1
+32	1	1
+1041	0	2
+174	9	0
+4023	14	14
+8106	8	8
+2203	10	8
+2025	1	1
+39	1	1
+907	4	4
+225	1	1
+124	1	1
+3928	0	22
+38	2	0
+44	18	0
+46	0	6
+61	0	1
+3653	6	0
+34	1	1
+4559	1	1
+28	1	1
+283	5	5
+1951	1	1
+34	1	1
+443	19	19
+57	1	1
+21	1	1
+231	1	1
+94	1	1
+105	1	1
+208	5	5
+124	1	1
+112	3	3
+207	40	40
+244	1	1
+60	1	1
+98	1	1
+50	1	1
+256	5	5
+23	1	1
+157	1	1
+33	1	1
+143	1	1
+59	1	1
+51	1	1
+45	1	0
+73	1	1
+81	1	1
+339	1	1
+56	0	5
+142	1	1
+232	1	1
+43	1	1
+332	1	1
+47	1	1
+479	1	0
+137	0	3
+1456	10	13
+63	1	1
+37	1	1
+261	0	2
+109	1	1
+50	1	1
+56	129	1
+88	1	0
+44	1	1
+54	1	1
+56	1	50
+58	50	1
+54	277	1
+44	1	1
+297	0	39
+142	1	1
+85	1	1
+124	16	16
+58	3	15
+677	1	0
+1333	2	0
+13591	6	0
+989	1	1
+107	1	1
+678	1	1
+31	1	1
+2571	5	5
+56	2	2
+39	1	1
+3986	0	4
+18351	32	30
+10811	1	1
+25	0	1
+129	62	62
+226	1	1
+40	1	1
+159	4	4
+37	4	4
+179	1	1
+51	1	1
+103	2	0
+108	1	1
+79	1	1
+25	1	1
+58	1	1
+12	1	1
+275	14	0
+80	1	1
+83	1	1
+24	1	1
+59	1	0
+91	1	1
+65	1	1
+67	1	1
+136	4	0
+68	8	0
+331	5	0
+40	1	1
+110	10	6
+64	1	1
+368	1	1
+22	1	1
+509	1	1
+89	1	1
+926	1	0
+959	1	1
+44	1	1
+72	11	0
+47	1	1
+361	1	1
+37	1	1
+2204	2	2
+45	1	1
+1117	18	18
+141	1	1
+47	1	1
+148	1	1
+75	1	1
+107	57	56
+146	3	2
+249	1	1
+146	1	1
+94	1	1
+34	1	1
+700	0	331
+21	1	1
+73	1	1
+49	1	1
+356	1	1
+16	1	1
+112	1	1
+36	9	0
+515	1	1
+27	2	2
+192	1	1
+53	0	14
+82	1	1
+302	1	1
+68	1	1
+52	12	12
+52	1	1
+34	1	1
+166	7	7
+384	1	1
+31	1	1
+281	1	1
+57	1	1
+176	0	1
+1625	1	1
+26	1	1
+369	1	1
+21	1	1
+86	1	1
+134	1	1
+215	1	1
+214	15	1
+50	2	2
+26	1	1
+78	0	19
+64	1	1
+126	1	1
+43	1	1
+433	1	1
+76	0	1
+6	12	0
+52	1	1
+108	1	1
+87	1	1
+62	1	1
+26	1	1
+291	2	1
+143	1	1
+29	1	1
+56	12	12
+230	1	1
+153	4	4
+87	32	32
+584	12	12
+227	1	0
+1931	4	0
+836	1	1
+68	1	1
+205	24	19
+816	1	2
+1932	0	7
+1732	13	0
+257	4	0
+1441	1	0
+111	6	0
+1505	1	1
+42	0	1
+373	13	13
+565	1	1
+76	1	0
+1881	0	4
+68	4	0
+43	0	4
+2201	8	8
+3726	3	0
+339	15	11
+249	1	1
+35	1	1
+250	1	1
+38	1	1
+359	11	12
+109	1	1
+43	18	0
+822	1	1
+53	1	1
+325	15	15
+123	1	1
+42	6	6
+240	1	1
+44	1	1
+438	7	7
+142	2	0
+1004	0	1
+9275	1	1
+37	1	0
+2071	0	1
+10399	0	1
+12513	2	1
+11243	1	1
+26	1	1
+816	4	0
+8248	26	26
+7722	2	0
+1594	1	0
+363	5	0
+6757	47	41
+2700	1	0
+823	18	19
+1807	0	2
+2565	11	0
+2089	0	2
+477	1	0
+657	0	1
+776	0	20
+365	82	49
+779	0	1
+391	35	73
+441	0	2
+1152	0	2
+1315	1	0
+5352	6	8
+902	0	1
+2154	1	1
+36	1	1
+109	0	1
+668	6	0
+1923	0	1
+91	3	2
+3560	1	0
+1235	1	0
+139	26	0
+831	3	3
+6547	1	0
+155	0	14
+2393	1	1
+33	1	1
+507	4	0
+1337	0	1
+9954	3	0
+1588	1	0
+2605	1	1
+23	1	1
+3000	0	3
+8249	8	0
+912	0	1
+338	2	0
+734	1	0
+4332	1	0
+416	0	4
+1691	0	1
+295	1	0
+214	2	0
+121	0	1
+784	0	1
+2512	0	1
+1205	21	21
+3239	12	11
+926	1	0
+190	1	0
+5780	0	1
+490	5	0
+228	1	1
+45	1	1
+207	3	0
+322	0	1
+633	1	1
+24	1	0
+1516	5	0
+1025	0	13
+1518	0	1
+591	10	10
+1061	1	0
+1371	1	1
+22	1	1
+928	0	2
+182	8	0
+328	1	0
+301	0	1
+994	1	1
+18	0	6
+1743	0	1
+2350	22	23
+1548	0	2
+1498	8	6
+7484	0	3
+2988	7	7
+93	2	0
+322	1	0
+280	1	1
+49	1	1
+2114	16	17
+617	0	1
+1012	0	1
+495	1	0
+29	1	1
+3134	1	0
+1837	0	4
+4079	0	1
+905	8	0
+5764	0	1
+3493	0	20
+1174	0	1
+900	0	1
+1006	1	0
+1699	0	1
+1682	1	0
+688	1	1
+21	1	1
+3349	0	1
+384	3	1
+3616	3	0
+748	0	1
+3001	0	10
+541	1	0
+286	1	1
+22	0	1
+250	1	1
+27	1	1
+898	1	0
+1161	0	2
+2067	0	1
+8000	0	12
+857	29	0
+1399
+
+chain	80965	chr6_qbl_hap6	4611984	+	2304864	2305721	chr6	170899992	-	139781917	139782778	1559017
+341	0	4
+516
+
+chain	72788	chr6_qbl_hap6	4611984	+	3854428	3855228	chr11	134452384	+	117706218	117707111	1729754
+615	13	107
+119	2	1
+51
+
+chain	45972	chr6_qbl_hap6	4611984	+	2517561	2519479	chr10	135374737	+	90380381	90382315	2786707
+110	146	146
+63	324	322
+53	379	396
+81	331	331
+99	110	110
+78	40	41
+104
+
+chain	30865	chr6_qbl_hap6	4611984	+	3846325	3846844	chr6	170899992	+	32821259	32821748	4483191
+73	89	59
+184	77	77
+96
+
+chain	26769	chr6_qbl_hap6	4611984	+	2264712	2264997	chr1	247249719	-	83196058	83196343	6075821
+285
+
+chain	22241	chr6_qbl_hap6	4611984	+	1157838	1158189	chr4	191273063	+	37186911	37187262	8835264
+178	101	101
+72
+
+chain	17263	chr6_qbl_hap6	4611984	+	3740215	3740422	chr4	191273063	+	3978296	3978500	12788148
+50	3	0
+26	4	4
+124
+
+chain	16745	chr6_qbl_hap6	4611984	+	2635745	2635946	chr11	134452384	+	74426248	74426449	13289834
+113	12	12
+76
+
+chain	16124	chr6_qbl_hap6	4611984	+	3115310	3115488	chr2	242951149	+	128261675	128261851	618783
+28	10	8
+140
+
+chain	15557	chr6_qbl_hap6	4611984	+	3932244	3933069	chr7	158821424	+	130132312	130132930	14485186
+71	636	429
+118
+
+chain	14855	chr6_qbl_hap6	4611984	+	3933226	3933509	chr9	140273252	-	14741363	14741645	15225313
+54	109	108
+120
+
+chain	14065	chr6_qbl_hap6	4611984	+	3751984	3752136	chr6	170899992	-	138279004	138279156	16120856
+152
+
+chain	13590	chr6_qbl_hap6	4611984	+	3850351	3850495	chr2	242951149	+	178053314	178053458	16703161
+144
+
+chain	13364	chr6_qbl_hap6	4611984	+	3822393	3822546	chr3	199501827	+	102278307	102278460	16996123
+67	1	1
+85
+
+chain	13024	chr6_qbl_hap6	4611984	+	983771	983907	chr11	134452384	-	45905925	45906061	17454498
+136
+
+chain	12452	chr6_qbl_hap6	4611984	+	4259490	4260232	chr12	132349534	+	123152186	123152605	1903988
+57	408	105
+14	32	63
+45	0	78
+44	129	0
+13
+
+chain	12361	chr6_qbl_hap6	4611984	+	1196738	1196868	chr1	247249719	+	48758029	48758159	18440544
+130
+
+chain	12272	chr6_qbl_hap6	4611984	+	2525057	2525213	chrX	154913754	+	154847615	154847763	18572106
+71	1	1
+25	8	0
+51
+
+chain	12201	chr6_qbl_hap6	4611984	+	1151149	1151920	chr6	170899992	-	139553108	139553881	18681505
+54	620	622
+97
+
+chain	11746	chr6_qbl_hap6	4611984	+	1143997	1144145	chr7	158821424	-	7754727	7754875	19419749
+54	14	14
+80
+
+chain	11418	chr6_qbl_hap6	4611984	+	3733988	3734369	chr6	170899992	+	32605989	32606372	19978843
+55	244	246
+82
+
+chain	11340	chr6_qbl_hap6	4611984	+	3744880	3745292	chr11	134452384	+	42855603	42856006	20116653
+57	275	266
+80
+
+chain	11205	chr6_qbl_hap6	4611984	+	3740546	3740663	chr3	199501827	+	102893757	102893874	20360983
+117
+
+chain	10738	chr6_qbl_hap6	4611984	+	3746512	3746633	chr10	135374737	+	59270705	59270823	21232184
+61	3	0
+57
+
+chain	10686	chr6_qbl_hap6	4611984	+	2524205	2524726	chr18	76117153	+	11332173	11332695	21332094
+80	388	389
+53
+
+chain	10567	chr6_qbl_hap6	4611984	+	3783253	3785836	chr6	170899992	+	32627140	32629242	21577879
+86	1741	1742
+57	646	164
+53
+
+chain	10496	chr6_qbl_hap6	4611984	+	3742563	3742673	chr1	247249719	-	172266041	172266151	21720781
+110
+
+chain	10342	chr6_qbl_hap6	4611984	+	3760212	3760942	chr6	170899992	+	32656559	32657213	22046794
+78	598	522
+54
+
+chain	10139	chr6_qbl_hap6	4611984	+	1198462	1198648	chr16	88827254	+	79406655	79406844	22494560
+65	65	68
+56
+
+chain	9962	chr6_qbl_hap6	4611984	+	3745365	3745830	chr4	191273063	-	17741127	17741604	22894345
+65	340	352
+60
+
+chain	9923	chr6_qbl_hap6	4611984	+	1132589	1132693	chr6	170899992	+	29984509	29984613	22990380
+104
+
+chain	9560	chr6_qbl_hap6	4611984	+	1145748	1145849	chr6	170899992	-	141000133	141000234	23851260
+101
+
+chain	9413	chr6_qbl_hap6	4611984	+	2517880	2518811	chr3	199501827	-	190559447	190560375	2816976
+26	220	218
+60	531	530
+94
+
+chain	9385	chr6_qbl_hap6	4611984	+	3871626	3871831	chr16	88827254	-	20600009	20600189	24262926
+58	92	67
+55
+
+chain	9214	chr6_qbl_hap6	4611984	+	1148380	1148477	chr6	170899992	+	29866137	29866234	24599827
+97
+
+chain	9032	chr6_qbl_hap6	4611984	+	3792044	3793708	chr6	170899992	+	32600177	32601830	24897719
+61	1516	1505
+87
+
+chain	8560	chr6_qbl_hap6	4611984	+	1158286	1158614	chr13	114142980	-	5380936	5381417	10250153
+58	237	390
+33
+
+chain	8241	chr6_qbl_hap6	4611984	+	3817008	3817095	chr6	170899992	+	65319659	65319746	26041518
+87
+
+chain	7487	chr6_qbl_hap6	4611984	+	3850495	3850589	chr16	88827254	+	12353631	12353725	21356530
+23	11	11
+60
+
+chain	7405	chr6_qbl_hap6	4611984	+	3933869	3933948	chr6	170899992	+	125781203	125781282	27398065
+79
+
+chain	7276	chr6_qbl_hap6	4611984	+	3821398	3821474	chr6	170899992	-	67344251	67344327	27653186
+76
+
+chain	7270	chr6_qbl_hap6	4611984	+	2635437	2635524	chr9	140273252	-	10289268	10289355	16248608
+13	11	11
+63
+
+chain	7204	chr6_qbl_hap6	4611984	+	3822572	3822648	chr7	158821424	-	147092048	147092124	27788942
+76
+
+chain	6530	chr6_qbl_hap6	4611984	+	3872997	3873065	chr8	146274826	+	43408268	43408336	29217082
+68
+
+chain	6522	chr6_qbl_hap6	4611984	+	3873792	3873861	chr15	100338915	+	41279078	41279147	29241048
+69
+
+chain	6486	chr6_qbl_hap6	4611984	+	3835377	3835446	chr4	191273063	-	136771275	136771344	29334522
+69
+
+chain	6459	chr6_qbl_hap6	4611984	+	2621390	2621459	chr6	170899992	+	31350859	31350928	29378034
+69
+
+chain	6457	chr6_qbl_hap6	4611984	+	1204555	1204622	chr6	170899992	+	30336816	30336883	29393800
+67
+
+chain	6422	chr6_qbl_hap6	4611984	+	3863961	3864029	chr6	170899992	+	32836685	32836753	29490928
+68
+
+chain	6404	chr6_qbl_hap6	4611984	+	3933974	3934042	chr7	158821424	+	141217888	141217956	29535655
+68
+
+chain	6368	chr6_qbl_hap6	4611984	+	2524965	2525057	chr6	170899992	-	132294381	132294479	20980275
+55	29	35
+8
+
+chain	6276	chr6_qbl_hap6	4611984	+	3873712	3873778	chrX	154913754	+	50967168	50967234	29833134
+66
+
+chain	5979	chr6_qbl_hap6	4611984	+	3850589	3850678	chr7	158821424	+	47749290	47749379	21749072
+4	34	34
+51
+
+chain	5976	chr6_qbl_hap6	4611984	+	2623961	2624024	chr6	170899992	+	31358648	31358711	30614264
+63
+
+chain	5908	chr6_qbl_hap6	4611984	+	1197012	1197085	chr19	63811651	-	42248237	42248310	20723418
+73
+
+chain	5877	chr6_qbl_hap6	4611984	+	3715034	3715097	chr6	170899992	+	32648139	32648202	30861180
+63
+
+chain	5767	chr6_qbl_hap6	4611984	+	3872292	3872353	chr6	170899992	+	75566512	75566573	31174250
+61
+
+chain	5730	chr6_qbl_hap6	4611984	+	1160462	1160522	chr6	170899992	+	29878483	29878543	31293472
+60
+
+chain	5694	chr6_qbl_hap6	4611984	+	3933682	3933742	chr5	180857866	-	92908144	92908204	31375044
+60
+
+chain	5621	chr6_qbl_hap6	4611984	+	1160085	1160144	chr6	170899992	+	29878108	29878167	31597733
+59
+
+chain	5594	chr6_qbl_hap6	4611984	+	2515502	2515561	chrX	154913754	-	63050736	63050795	31662666
+59
+
+chain	5458	chr6_qbl_hap6	4611984	+	3834959	3835017	chr16	88827254	+	47978524	47978582	32101539
+58
+
+chain	5276	chr6_qbl_hap6	4611984	+	3754169	3754225	chr6	170899992	+	32648605	32648661	32642677
+56
+
+chain	5193	chr6_qbl_hap6	4611984	+	3872547	3872601	chr5	180857866	+	130110350	130110404	32896488
+54
+
+chain	5176	chr6_qbl_hap6	4611984	+	1146649	1146704	chr14	106368585	+	78419238	78419293	32952450
+55
+
+chain	5094	chr6_qbl_hap6	4611984	+	3834697	3834751	chr6	170899992	+	68023473	68023527	33192803
+54
+
+chain	4984	chr6_qbl_hap6	4611984	+	3871272	3871324	chr1	247249719	-	76982562	76982614	33591211
+52
+
+chain	4959	chr6_qbl_hap6	4611984	+	3742510	3742563	chr18	76117153	+	5080594	5080647	22154819
+53
+
+chain	4930	chr6_qbl_hap6	4611984	+	3744490	3744542	chrX	154913754	-	4434310	4434362	33717622
+52
+
+chain	4923	chr6_qbl_hap6	4611984	+	1158016	1158078	chr9	140273252	-	102391777	102391839	11227006
+62
+
+chain	4829	chr6_qbl_hap6	4611984	+	1205079	1205129	chr6	170899992	+	30567298	30567348	34088060
+50
+
+chain	4815	chr6_qbl_hap6	4611984	+	2517906	2519257	chr1	247249719	+	7396807	7398156	2855562
+25	959	957
+58	214	214
+95
+
+chain	4391	chr6_qbl_hap6	4611984	+	4260111	4260156	chrX	154913754	-	99121082	99121127	30173418
+45
+
+chain	4349	chr6_qbl_hap6	4611984	+	2517042	2517321	chr5	180857866	+	51070260	51070539	3385343
+66	110	110
+103
+
+chain	4295	chr6_qbl_hap6	4611984	+	2516110	2516164	chr13	114142980	+	40947099	40947153	23509762
+54
+
+chain	3734	chr6_qbl_hap6	4611984	+	3932378	3932443	chr6	170899992	+	80018577	80018642	19955879
+65
+
+chain	3600	chr6_qbl_hap6	4611984	+	3934098	3934136	chr2	242951149	+	129304609	129304647	25766390
+38
+
+chain	3399	chr6_qbl_hap6	4611984	+	1196935	1197002	chr12	132349534	+	50414483	50414550	19205048
+67
+
+chain	3394	chr6_qbl_hap6	4611984	+	3746476	3746512	chrX	154913754	-	4438295	4438331	28244178
+36
+
+chain	3148	chr6_qbl_hap6	4611984	+	3871684	3871717	chr2	242951149	+	38036197	38036230	24698966
+33
+
+chain	2975	chr6_qbl_hap6	4611984	+	2524285	2524321	chr3	199501827	-	94209737	94209773	24799760
+36
+
+chain	2972	chr6_qbl_hap6	4611984	+	1151921	1151961	chr6	170899992	+	30567024	30567064	20739259
+40
+
+chain	2845	chr6_qbl_hap6	4611984	+	2516686	2516716	chr3	199501827	-	158108130	158108160	26771673
+30
+
+chain	2771	chr6_qbl_hap6	4611984	+	2185017	2185049	chr16	88827254	+	61371572	61371604	11881976
+32
+
+chain	2691	chr6_qbl_hap6	4611984	+	3933197	3933226	chr3	199501827	-	121608742	121608771	23862843
+29
+
+chain	2671	chr6_qbl_hap6	4611984	+	2524905	2524964	chr9	140273252	-	60326471	60326530	21074055
+59
+
+chain	2645	chr6_qbl_hap6	4611984	+	3740797	3740872	chr19	63811651	-	40112981	40113056	21687959
+75
+
+chain	2599	chr6_qbl_hap6	4611984	+	1158078	1158116	chr7	158821424	-	126060947	126060985	11258555
+38
+
+chain	2365	chr6_qbl_hap6	4611984	+	3662868	3662893	chr9	140273252	-	56082033	56082058	25372966
+25
+
+chain	2302	chr6_qbl_hap6	4611984	+	2518282	2518373	chrX	154913754	+	17160841	17160932	3083108
+91
+
+chain	2226	chr6_qbl_hap6	4611984	+	2516716	2520208	chr12	132349534	+	103307685	103311177	3426888
+99	961	960
+41	2329	2330
+62
+
+chain	2196	chr6_qbl_hap6	4611984	+	3573229	3573252	chr8	146274826	-	36256974	36256997	29790670
+23
+
+chain	2146	chr6_qbl_hap6	4611984	+	1144210	1144271	chr12	132349534	+	104221177	104221238	23825291
+61
+
+chain	2027	chr6_qbl_hap6	4611984	+	2518845	2519837	chr4	191273063	+	75333400	75334396	3306565
+44	889	893
+59
+
+chain	2011	chr6_qbl_hap6	4611984	+	3750379	3750401	chr12	132349534	-	27555073	27555095	35529087
+22
+
+chain	2003	chr6_qbl_hap6	4611984	+	1715012	1715046	chr6	170899992	+	30558380	30558414	2034666
+34
+
+chain	1988	chr6_qbl_hap6	4611984	+	3744653	3744712	chr1	247249719	+	152912877	152912936	23823439
+59
+
+chain	1906	chr6_qbl_hap6	4611984	+	2517426	2517496	chr17	78774742	-	18978582	18978652	12332136
+70
+
+chain	1860	chr6_qbl_hap6	4611984	+	1158233	1158283	chr8	146274826	+	68242167	68242217	13480681
+50
+
+chain	1860	chr6_qbl_hap6	4611984	+	3858322	3861837	chr6	170899992	+	32830794	32834943	29475612
+61	2506	2690
+85	515	965
+52	103	103
+193
+
+chain	1658	chr6_qbl_hap6	4611984	+	1158189	1158222	chr4	191273063	+	153905795	153905828	11042895
+33
+
+chain	1451	chr6_qbl_hap6	4611984	+	2516912	2518845	chr18	76117153	+	57868323	57870253	3225031
+58	1841	1838
+34
+
+chain	1444	chr6_qbl_hap6	4611984	+	2517346	2518418	chr3	199501827	+	26257399	26258470	3460386
+77	968	967
+27
+
+chain	1437	chr6_qbl_hap6	4611984	+	2517932	2518010	chr9	140273252	-	113447512	113447590	4152331
+78
+
+chain	1395	chr6_qbl_hap6	4611984	+	2517496	2517525	chr4	191273063	+	177039024	177039053	17309502
+29
+
+chain	1388	chr6_qbl_hap6	4611984	+	4260176	4260219	chr19	63811651	-	48476446	48476489	2785288
+43
+
+chain	1332	chr6_qbl_hap6	4611984	+	3612848	3612887	chr2	242951149	-	44758440	44758479	1994605
+39
+
+chain	1326	chr6_qbl_hap6	4611984	+	2516425	2516540	chr2	242951149	-	193553846	193553961	4393012
+115
+
+chain	1313	chr6_qbl_hap6	4611984	+	4259851	4259901	chr1	247249719	-	36229834	36229933	2748513
+7	14	63
+29
+
+chain	1148	chr6_qbl_hap6	4611984	+	4259442	4259473	chr8	146274826	+	89694	89724	9819782
+12	1	0
+18
+
+chain	1111	chr6_qbl_hap6	4611984	+	1158412	1158466	chr19	63811651	-	5696793	5696847	17027637
+54
+
+chain	1071	chr6_qbl_hap6	4611984	+	2516561	2516628	chr12	132349534	+	77415638	77415705	9437720
+67
+
+chain	1001	chr6_qbl_hap6	4611984	+	4259418	4259442	chr1	247249719	+	40151331	40151355	3139135
+24
+
+chain	975	chr6_qbl_hap6	4611984	+	2516971	2517042	chr1	247249719	+	183489007	183489078	3337949
+71
+
+chain	917	chr6_qbl_hap6	4611984	+	2518025	2518086	chr8	146274826	-	9314035	9314096	4594958
+61
+
+chain	884	chr6_qbl_hap6	4611984	+	2519749	2519778	chr1	247249719	-	197271642	197271671	12501548
+29
+
+chain	844	chr6_qbl_hap6	4611984	+	2520091	2520119	chr7	158821424	+	107644180	107644208	22181631
+28
+
+chain	841	chr6_qbl_hap6	4611984	+	2516165	2516217	chr20	62435964	-	59823019	59823071	21526398
+52
+
+chain	836	chr6_qbl_hap6	4611984	+	4259969	4260001	chr3	199501827	+	123981761	123981793	2757122
+32
+
+chain	835	chr6_qbl_hap6	4611984	+	2519837	2519906	chr4	191273063	+	99162526	99162595	6917305
+69
+
+chain	764	chr6_qbl_hap6	4611984	+	1158466	1158505	chr14	106368585	-	57011112	57011151	17388689
+39
+
+chain	760	chr6_qbl_hap6	4611984	+	2520610	2520672	chr1	247249719	+	71360495	71360557	7931067
+62
+
+chain	760	chr6_qbl_hap6	4611984	+	2518460	2518519	chr12	132349534	+	56700130	56700189	25330836
+59
+
+chain	746	chr6_qbl_hap6	4611984	+	2519488	2519538	chr22	49691432	+	27063810	27063860	3889151
+50
+
+chain	745	chr6_qbl_hap6	4611984	+	2516014	2516077	chr6	170899992	+	44660392	44660455	3181879
+63
+
+chain	740	chr6_qbl_hap6	4611984	+	1158720	1158784	chr12	132349534	+	55464534	55464598	20832676
+64
+
+chain	718	chr6_qbl_hap6	4611984	+	2520835	2520890	chr9	140273252	-	49339912	49339967	23555331
+55
+
+chain	716	chr6_qbl_hap6	4611984	+	3933624	3933676	chr16	88827254	-	38714794	38714846	22851161
+52
+
+chain	710	chr6_qbl_hap6	4611984	+	2519659	2519709	chr11	134452384	-	107252690	107252740	6149242
+50
+
+chain	706	chr6_qbl_hap6	4611984	+	2516328	2516399	chr18	76117153	+	57376973	57377044	7676567
+71
+
+chain	700	chr6_qbl_hap6	4611984	+	2516815	2516871	chr1	247249719	+	47033162	47033218	11749470
+56
+
+chain	685	chr6_qbl_hap6	4611984	+	2520397	2520480	chr1	247249719	+	68246247	68246330	16545799
+83
+
+chain	662	chr6_qbl_hap6	4611984	+	2520752	2520817	chr5	180857866	+	99923773	99923838	9608666
+65
+
+chain	654	chr6_qbl_hap6	4611984	+	1158614	1158640	chr4	191273063	-	137719796	137719822	10317123
+26
+
+chain	604	chr6_qbl_hap6	4611984	+	2520031	2520091	chr8	146274826	-	111755913	111755973	4980877
+60
+
+chain	569	chr6_qbl_hap6	4611984	+	2515445	2515500	chr12	132349534	-	4861980	4862035	16127490
+55
+
+chain	521	chr6_qbl_hap6	4611984	+	2517182	2517218	chr15	100338915	-	47556137	47556173	3431041
+36
+
+chain	465	chr6_qbl_hap6	4611984	+	2518541	2518594	chrX	154913754	-	2978832	2978885	15318329
+53
+
+chain	465	chr6_qbl_hap6	4611984	+	2515257	2515307	chr13	114142980	+	94087883	94087933	15752176
+50
+
+chain	431	chr6_qbl_hap6	4611984	+	2516292	2516328	chrX	154913754	+	109116067	109116103	11044816
+36
+
+chain	377	chr6_qbl_hap6	4611984	+	2521082	2521150	chrX	154913754	-	100727898	100727966	10456810
+68
+
+chain	364	chr6_qbl_hap6	4611984	+	2519959	2520014	chr2	242951149	+	137419466	137419521	26497561
+55
+
+chain	357	chr6_qbl_hap6	4611984	+	2516242	2516292	chr3	199501827	+	59182343	59182393	15538406
+50
+
+chain	252	chr6_qbl_hap6	4611984	+	2519906	2519943	chr10	135374737	+	69013226	69013263	15789370
+37
+
+chain	172	chr6_qbl_hap6	4611984	+	3874043	3874094	chr1	247249719	-	204983626	204983677	25877237
+51
+
+chain	126	chr6_qbl_hap6	4611984	+	2521548	2521600	chr16	88827254	-	42325840	42325892	26081164
+52
+
+chain	345833726	chr6_ssto_hap7	4928567	+	0	4928567	chr6	170899992	+	28767121	33556332	37
+43705	3	0
+396	1	1
+36	1	1
+327	0	2
+458	8	0
+6175	1	1
+58	1	1
+80	0	7
+257	2	0
+2504	0	12
+1614	0	1
+1985	6	0
+370	1	0
+2206	2	0
+4292	4	0
+5173	33	8
+1486	4	4
+213	2	2
+71	0	1
+437	0	1
+897	1	1
+34	1	1
+10055	18	6
+2970	0	1
+813	0	15
+922	0	20
+1095	1	1
+43	1	1
+1829	0	1
+2885	0	10
+5273	0	1
+108	2	0
+571	0	3
+2338	1	0
+934	1	0
+2409	0	8
+2132	54	16
+77	1	52
+38	0	59
+40	0	2
+3908	1	0
+3045	2	4
+758	0	1
+174	15	15
+211	1	0
+608	0	4
+1434	2	0
+2061	2	0
+10205	0	6
+2011	17	17
+871	89	85
+91	0	2
+2644	33	29
+3737	1	1
+39	1	1
+1512	1	0
+2391	2	0
+844	0	1
+5198	0	1
+17000	0	1
+603	2	0
+4648	0	3
+2281	1	0
+38	1	1
+334	1	1
+41	1	1
+1760	1	0
+3862	0	6
+1025	160	0
+3444	3	0
+282	0	1
+1508	1	0
+2207	0	3
+1827	1	0
+3220	9	0
+5157	0	4
+1394	1	0
+279	0	2
+71	0	4
+163	1	1
+31	1	1
+280	8	0
+1059	0	2
+1409	0	4
+402	1	0
+643	0	2
+746	0	2
+1268	2	0
+267	0	1
+1868	1	1
+44	1	1
+8525	0	4
+1440	4	4
+127	0	6
+204	1	2
+873	1	0
+131	2	0
+3954	0	1
+1818	2	1
+4264	0	1
+3195	0	2
+2446	1	1
+70	26	25
+70	1	1
+1649	1	0
+953	0	1
+295	1	1
+32	0	6
+661	8	0
+5298	1	0
+1365	0	1
+6151	2	0
+1123	0	9
+2073	1	0
+611	1	0
+1129	0	3
+562	11	11
+9680	4	4
+316	19	19
+831	2	0
+3215	1	0
+1710	0	1
+2693	0	3
+4148	82	25
+807	0	1
+85	1	1
+114	1	1
+489	10	0
+936	43	43
+6001	0	1
+3807	5	0
+191	14	14
+73	0	1
+345	2	0
+3436	3	0
+780	1	0
+6	1	0
+2268	0	1
+569	5	5
+1359	2	1
+1049	3	0
+371	1	0
+5832	1	1
+13	1	1
+4064	0	105
+776	3	2
+1696	1	1
+34	1	1
+5830	0	3
+3442	1	1
+61	1	1
+472	1	0
+22361	20	19
+3288	0	3
+10522	4	0
+16901	2	0
+30045	7	0
+1489	1	1
+72	1	1
+2260	0	2
+7033	0	4
+3592	0	1
+11101	0	1
+8476	0	1
+1324	0	2
+5438	5	0
+2061	1	0
+3982	6	6
+1725	0	1
+3153	1	0
+18	1	0
+18	1	0
+2026	1	0
+4175	10	10
+4746	9	9
+4767	7	7
+1225	1	0
+8	1	1
+151	1	2
+5079	1	1
+28	1	1
+249	43	43
+1178	0	4
+685	12	0
+48	8	0
+1701	1	1
+43	5	5
+862	18	18
+58	1	1
+66	1	1
+420	1	1
+44	1	1
+680	4	4
+1675	1	1
+83	1	1
+3082	4	0
+5467	1	1
+27	0	1
+1099	16	0
+627	12	12
+1317	6	1
+129	1	1
+25	1	1
+1397	15	15
+810	1	1
+27	1	1
+1192	2	0
+7515	4	0
+979	0	3
+3406	0	2
+1730	11	11
+1760	1	1
+26	1	1
+787	0	1
+1416	3	1
+22815	4	4
+126	1	0
+38	1	1
+140	1	0
+1072	0	15
+15438	4	0
+6165	0	1
+1768	1	0
+7727	2	0
+1514	0	1
+3116	0	1
+3278	1	1
+21	1	1
+1738	0	1
+8576	19	0
+8020	1	0
+2049	1	0
+528	3	1
+1704	1	1
+117	1	1
+1448	10	0
+4403	9	9
+1142	9	9
+1114	1	0
+1382	1	1
+32	1	1
+1519	11	11
+2877	0	2
+1221	0	1
+1974	4	0
+71	32	24
+565	1	0
+1447	1	0
+1362	0	4
+4579	0	1
+3278	0	1
+2020	1	1
+31	1	1
+673	1	0
+2321	9	9
+155	1	1
+18	1	1
+1427	1	0
+4008	1	1
+59	2	0
+1998	11	0
+942	1	1
+39	1	1
+2252	1	0
+6944	0	4
+342	1	1
+16	1	1
+4918	1	1
+30	1	1
+1530	0	1
+313	1	1
+59	1	1
+1737	1	1
+34	1	1
+852	9	12
+1814	0	5
+742	0	318
+10	1	1
+484	0	2
+993	0	1
+312	4	0
+23	1	1
+476	0	1
+195	2	0
+1963	1	1
+25	1	1
+1942	1	1
+26	0	1
+13516	0	3
+40	1	1
+1374	20	0
+31	1	1
+189	1	1
+26	1	1
+327	1	1
+38	1	1
+177	11	11
+709	1	1
+38	1	1
+1803	1	1
+26	1	1
+2373	5	0
+321	1	0
+933	17	17
+82	9	9
+2773	0	143
+80	1	1
+25	1	1
+467	1	1
+27	1	1
+143	1	1
+47	1	1
+1197	10	10
+1455	1	1
+33	1	1
+601	1	1
+48	0	2
+694	1	4
+132	1	1
+17	1	1
+167	6	6
+113	1	1
+31	1	1
+1181	0	1
+422	15	0
+36	1	1
+2219	1	1
+35	1	1
+2116	0	1
+15789	0	2
+24630	1	0
+7864	1	0
+13424	0	2
+12333	1	1
+41	1	1
+33759	6	0
+3090	1	1
+41	1	1
+2048	0	2
+462	1	0
+31504	22	0
+880	79442	79440
+1063	1	7
+1384	4	1
+85	1	0
+357	3	4
+9255	0	1
+6104	0	1
+6497	0	1
+713	0	4
+2181	2	0
+145	0	1
+1108	0	2
+1448	1	0
+1835	1	0
+4207	1	0
+5843	0	1
+1398	0	1
+5972	1	0
+7345	4	0
+2841	1	0
+361	1	0
+5438	0	1
+1889	0	3
+1737	2	0
+5252	2	0
+9241	0	10
+575	1	1
+30	2	2
+78	1	1
+49	1	1
+294	1	1
+37	1	2612
+385	17	17
+259	0	1
+107	32	32
+72	1	1
+29	1	1
+123	1	1
+121	1	1
+435	1	0
+32	1	1
+255	1	1
+52	1	1
+201	1	1
+59	0	2
+9	0	21
+72	0	2
+141	5	137
+425	1	1
+42	1	1
+572	1	1
+30	1	1
+560	1	1
+28	1	1
+98	0	12
+18	0	15
+144	13	13
+1410	1	0
+291	0	4
+1637	0	1
+231	1	1
+35	1	1
+2158	1	1
+21	1	1
+581	59	48
+181	4	0
+65	0	4
+603	3	0
+591	1	1
+23	1	1
+51	1	1
+38	1	1
+362	1	1
+44	1	1
+1935	0	2
+165	13	19
+1394	8	7
+450	7	0
+483	1	1
+27	1	1
+264	1	1
+51	1	1
+355	1	1
+45	1	1
+1717	0	4
+80	1	1
+18	1	0
+437	1	1
+38	1	1
+454	1	1
+40	1	1
+2320	1	1
+21	1	1
+161	1	1
+37	1	1
+1424	1	1
+48	1	1
+392	1	1
+35	1	1
+147	4	4
+436	1	1
+28	4	5
+144	3	0
+533	0	4
+437	1	9
+1714	0	1
+31	0	1
+850	16	16
+515	0	1
+58	1	1
+142	1	1
+33	1	1
+173	1	0
+753	1	1
+55	1	1
+573	0	4
+37	1	1
+144	8	8
+1004	0	4
+28	2	0
+153	15	15
+94	12	12
+201	12	13
+169	19	20
+118	10	15
+1254	0	2
+243	16	16
+73	1	1
+21	1	1
+196	0	28
+36	2	0
+18	1	1
+52	1	1
+29	1	1
+162	2	1
+373	1	0
+1159	0	32
+23	1	1
+674	0	3
+136	1	1
+48	1	1
+330	9	9
+1108	1	1
+98	1	1
+582	1	0
+715	7	7
+89	1	0
+115	1	1
+31	1	1
+145	9	8
+350	6	6
+145	1	1
+41	1	1
+681	1	1
+43	1	1
+518	1	1
+19	1	1
+582	16	16
+180	6	6
+993	0	7
+9811	1	1
+27	1	1
+1374	1	0
+1705	13	13
+4591	1	1
+9	1	1
+5418	1	0
+5474	33	33
+1261	74	190
+19692	5	1
+1674	4	4
+42	1	1
+593	1	1
+24	1	1
+457	10	10
+414	13	13
+825	1	1
+41	1	1
+492	0	8
+1196	1	1
+23	1	1
+149	1	1
+18	1	1
+1145	6	4
+880	1	1
+35	1	1
+236	1	1
+67	1	1
+298	0	1
+147	14	14
+312	11	11
+99	1	1
+43	1	1
+469	1	1
+62	1	1
+288	0	1
+51	1	1
+22	1	1
+204	1	1
+39	1	1
+812	1	1
+57	1	1
+358	1	1
+128	1	1
+146	10	10
+490	1	1
+20	1	1
+62	1	1
+88	1	1
+135	1	1
+47	1	1
+109	1	1
+28	1	0
+20	1	1
+83	0	1
+90	1	1
+312	1	1
+44	1	1
+1213	1	1
+51	1	1
+473	1	1
+33	1	1
+122	14	0
+35	1	1
+485	14	14
+110	9	0
+127	1	1
+746	1	1
+40	1	1
+50	1	0
+1765	5	5
+773	1	2
+48	1	0
+1699	1	0
+293	1	1
+33	13	0
+7	7	27
+303	1	1
+16	1	1
+289	1	1
+23	1	1
+217	1	1
+42	1	1
+320	1	1
+44	1	1
+298	1	1
+7	4	0
+32	0	7
+14	1	0
+6	5	37
+272	6	0
+1071	8	8
+143	10	10
+522	8	13
+85	1	1
+49	0	1
+90	1	1
+85	1	1
+89	1	1
+568	1	0
+265	0	2
+501	1	1
+36	1	1
+330	0	1
+1365	23	16
+81	1	1
+36	1	1
+184	0	1
+465	1	1
+26	1	1
+139	1	1
+87	0	3
+298	1	1
+45	1	1
+118	1	1
+44	1	1
+1277	6	4
+129	0	496
+233	1	1
+73	1	1
+1947	0	4
+265	1	1
+25	1	1
+200	6	6
+93	1	1
+34	2	2
+98	3	0
+1010	15	15
+366	1	0
+610	1	1
+21	1	1
+422	6	0
+358	1	1
+51	1	1
+700	40	40
+127	1	1
+51	2	2
+395	13	13
+148	0	5
+119	1	1
+103	1	1
+268	1	1
+22	1	1
+251	1	1
+34	1	1
+175	1	1
+36	1	1
+239	1	1
+32	5	5
+63	1	1
+126	1	1
+209	1	1
+143	1	13
+175	7	17
+393	1	1
+44	1	1
+129	1	1
+84	1	1
+140	8	0
+90	6	8
+450	1	1
+25	1	1
+265	1	1
+35	0	1
+17	2	0
+428	1	1
+92	1	1
+697	1	1
+34	1	1
+955	1	1
+45	1	1
+95	1	1
+29	1	1
+660	1	1
+18	1	1
+389	9	9
+252	3	0
+284	1	1
+38	1	1
+81	9	9
+90	1	1
+71	1	1
+132	0	6
+96	1	1
+257	3	0
+56	1	1
+159	1	1
+44	1	1
+409	34254	40035
+275	1	1
+38	1	1
+1307	1	1
+26	1	1
+1467	1	1
+27	1	1
+568	11	11
+693	1	1
+47	1	1
+276	11	11
+183	1	1
+40	1	1
+589	1	1
+26	1	1
+4216	2	1
+170	17	17
+893	2	0
+24	1	1
+2666	4	4
+545	1	1
+76	1	1
+163	4	0
+141	1	1
+108	1	1
+165	1	1
+72	1	1
+167	1	1
+33	0	1
+42	0	2
+83	0	2
+60	1	1
+84	1	0
+383	2	0
+736	15	15
+770	13	13
+76	14	14
+410	1	1
+43	1	1
+542	1	1
+81	1	1
+111	8	4
+137	1	1
+37	1	1
+127	1	1
+34	0	3
+45	1	1
+269	2	2
+126	1	1
+259	26	26
+257	2	2
+14	1	1
+114	5483	21566
+75	1919	964
+70	30518	17325
+308	1	1
+49	1	1
+285	29	27
+223	10	8
+230	1	2
+69	12	12
+705	0	2
+187	2	1
+402	1	0
+656	0	2
+614	1	1
+43	1	1
+781	3	1
+55	13	19
+1083	5	5
+38	1	1
+62	1	1
+80	1	1
+1217	1	1
+44	1	1
+2070	27	27
+259	1	1
+40	1	1
+115	1	1
+56	4	4
+478	1	1
+30	1	1
+162	11	11
+209	10	0
+150	1	1
+36	0	2
+31	1	1
+55	1	1
+51	1	1
+221	8	13
+386	1	1
+58	1	1
+397	3	0
+45	1	1
+547	1	1
+21	1	1
+4446	4	0
+1282	1	1
+44	1	1
+8862	1	0
+4998	10	10
+6533	1	0
+1116	28	28
+9230	19	0
+741	0	1
+2695	0	1
+5382	1	0
+4424	21	21
+3562	0	1
+381	1072	0
+6066	0	1
+1968	7	0
+3198	1	0
+667	1	0
+3902	17	4
+1895	1	1
+40	0	4
+1137	0	6
+205	2	0
+345	1	0
+1639	8	0
+686	5	0
+1032	0	1
+9206	0	4
+1574	1	0
+22388	1	0
+1656	2	0
+118	1	5
+4748	1	0
+2035	0	1
+1151	5	6
+1120	1	1
+20	1	1
+1533	16	0
+3103	0	1
+25	1	1
+2642	1	1
+43	0	3
+1703	0	1
+409	7	7
+527	1	0
+524	1	1
+59	1	1
+112	3	3
+50	1	1
+267	0	7
+286	14	14
+1161	2	0
+1003	0	1
+4062	1	0
+3850	4	0
+4977	0	1
+2718	1	0
+1588	1	1
+30	4	0
+879	0	1
+1332	18	12
+1688	4	4
+88	1	1
+439	2	0
+209	1	0
+1322	54	54
+893	1	1
+49	1	2
+1773	1	1
+24	1	1
+540	1	1
+41	1	1
+460	1	7
+165	1	1
+45	1	1
+903	1	2
+140	0	1
+36	1	1
+2019	0	1
+657	1	1
+48	1	0
+1329	0	1
+268	1	1
+47	1	1
+336	1	1
+25	2	0
+43	1	1
+1484	1	1
+53	1	1
+1151	1	1
+42	1	1
+1870	1	1
+24	5	5
+853	0	3
+23	0	1
+326	9	9
+131	9	9
+623	0	3
+34	1	1
+809	1	1
+36	1	1
+690	2	0
+44	1	1
+285	8	7
+455	1	1
+32	1	1
+102	1	1
+47	1	1
+4338	0	1
+5275	4	0
+11554	1	0
+409	16	17
+3476	0	1
+2160	0	24
+109	1	1
+3284	0	19
+2586	2	0
+757	1	1
+22	1	1
+860	17	24
+1584	1	0
+1582	0	2
+117	1	0
+1552	3	25
+17	0	4
+20	14	0
+42	9	0
+10	6	0
+10605	1	0
+4733	1	3
+371	4	0
+1177	1	1
+85	1	1
+40	0	1
+518	6	0
+646	13	13
+469	1	0
+1072	1	4
+565	1	1
+44	1	1
+3082	1	0
+839	1	0
+282	1	0
+597	0	6
+505	4	4
+45	1	1
+137	1	1
+43	1	1
+1294	1	1
+40	1	1
+572	0	5
+463	0	4
+1886	1	0
+548	1	0
+1300	0	3
+1839	2	0
+189	1	1
+49	1	1
+1253	1	1
+43	1	0
+498	1	1
+45	4	0
+3538	0	1
+1582	31	31
+376	14	14
+867	3	4
+253	1	1
+34	1	1
+172	2	0
+1094	0	1
+2856	1	1
+82	0	419
+125	3	0
+709	1	1
+36	1	1
+2189	16	17
+181	1	1
+109	0	1
+8	0	1
+53	1	1
+94	1	1
+49	1	1
+1495	15	0
+623	13	13
+163	1	1
+45	1	1
+2050	11	11
+474	1	1
+29	1	1
+1947	1	1
+42	1	0
+35	1	1
+751	1	0
+287	1	1
+60	1	1
+446	0	4
+2620	8	7
+1600	1	0
+11761	0	12
+3903	0	5
+4922	0	1
+1697	9	0
+379	0	1
+16104	1	0
+2244	0	14
+1780	1	1
+32	1	1
+9010	0	1
+296	0	1
+9862	0	1
+10107	1	0
+2415	11	9
+29829	0	12
+5348	0	1
+4837	0	1
+461	1	1
+37	1	1
+6200	4	0
+68	13	1
+2539	25	19
+1982	3	0
+5200	1	0
+162	0	9
+11963	1	1
+26	0	4
+206	1	0
+652	1	1
+27	1	1
+150	1	0
+1774	1	1
+18	1	1
+1410	4	4
+323	1	1
+64	5	5
+126	1	1
+28	1	1
+318	16	16
+579	1	1
+35	1	1
+206	1	1
+32	1	1
+50	1	1
+16	1	1
+279	1	1
+52	1	1
+167	16	16
+135	8	8
+802	1	1
+21	1	1
+278	1	1
+35	1	1
+663	1	1
+57	0	3
+29	1	0
+792	7	7
+111	1	1
+25	1	1
+387	1	1
+37	1	1
+55	1	1
+23	1	1
+623	1	1
+46	1	1
+494	1	1
+84	1	1
+276	0	2
+83	7	8
+114	1	1
+52	1	1
+48	0	1
+440	0	5
+101	1	1
+73	1	1
+329	0	2
+84	1	1
+41	1	1
+162	1	1
+29	1	1
+658	1	1
+28	1	1
+246	1	0
+155	28	28
+263	16	16
+1316	1	1
+29	1	1
+92	1	1
+30	1	1
+517	1	1
+23	1	1
+161	7	7
+668	1	1
+56	1	1
+761	1	1
+29	1	1
+276	16	16
+305	1	0
+546	3	5
+77	2	2
+45	0	2
+76	0	7
+18	1	1
+969	7	7
+84	0	3
+208	1	1
+25	1	1
+670	1	0
+179	0	1
+294	6	6
+578	1	1
+176	1	1
+216	1	1
+19	1	1
+142	4	4
+201	1	1
+34	1	1
+63	1	1
+49	1	1
+136	1	1
+112	0	1
+58	1	1
+46	1	0
+26	1	1
+80	0	3
+142	22576	22570
+400	1	1
+29	1	1
+982	0	2
+559	1	1
+59	1	1
+367	6	6
+288	1	1
+49	1	1
+193	1	1
+45	1	1
+183	16	16
+651	0	1
+136	1	1
+89	1	1
+341	14	14
+90	1	1
+151	1	1
+196	1	1
+66	1	1
+118	1	1
+55	1	1
+305	1	1
+81	1	1
+178	1	1
+18	1	1
+138	1	1
+103	1	1
+161	1	1
+27	1	1
+477	21	21
+417	2	2
+60	1	1
+51	1	1
+25	2	2
+231	1	1
+9	0	1
+24	1	1
+759	14	14
+107	1	1
+99	7	7
+236	1	1
+35	1	1
+121	1	1
+24	1	1
+92	0	2
+43	1	1
+68	1	1
+110	2	2
+52	1	1
+30	1	1
+201	1	1
+70	2	0
+99	1	1
+54	10	10
+125	0	1
+7	1	1
+132	18	25
+235	1	2
+189	1	1
+21	1	1
+278	1	1
+22	1	3
+22	1	1
+801	1	1
+51	1	1
+265	1	1
+84	1	1
+350	15	15
+259	1	0
+5	18	0
+368	1	1
+30	1	1
+840	1	1
+33	1	1
+490	1	1
+64	1	1
+1540	1	1
+37	1	1
+3927	1	1
+22	1	1
+316	0	5
+1069	0	2
+277	0	2
+69	14	0
+19	0	2
+31	2	0
+17	4	92
+2837	1	1
+197	2419	0
+840	1	1
+45	1	1
+176	1	0
+277	1	0
+1541	1	1
+17	1	1
+1434	18	22
+322	1	0
+193	0	1
+366	0	1
+493	1	0
+378	1	0
+1065	0	1
+4782	1	0
+656	13	13
+705	1	1
+49	0	3
+2315	0	3
+7693	2	0
+396	22	12
+918	0	1
+1126	0	4
+1210	1	1
+33	1	1
+326	1	1
+80	1	1
+288	8	17
+2671	0	1
+1244	1	1
+29	0	1
+2098	0	2
+24	4	0
+1207	4	4
+45	1	1
+175	34	34
+548	0	5
+1926	1	1
+40	1	1
+2657	0	1
+414	1	0
+61	0	1
+235	0	2
+2087	0	1
+713	0	4
+58	3	0
+1041	3	0
+36	1	1
+377	1	1
+17	1	1
+948	1	1
+41	1	1
+458	1	1
+21	1	1
+1055	0	1
+8168	1	1
+5	0	2
+18	1	0
+36	1	1
+99	2	0
+700	0	5
+148	0	1
+750	0	3
+40	1	1
+2428	0	1
+750	2	0
+473	0	2
+2032	1	0
+1184	2260	2258
+399	1	0
+560	1	0
+1108	1	0
+8087	1	0
+4298	0	2
+7581	1	1
+30	1	1
+4383	2	0
+10078	0	1
+906	4	0
+887	1	1
+80	1	1
+2210	1	0
+905	0	1
+1037	1	0
+5867	0	1
+18	1	1
+582	0	5
+2828	1	0
+847	1	0
+1996	1	0
+700	1	1
+4220	0	1
+910	2	0
+687	0	1
+32877	1	0
+19299	0	8
+1369	29	0
+494	2	0
+6182	1	0
+12	1	1
+23175	14263	14261
+152	1	0
+8727	0	1
+9606	1	0
+15258	1	0
+5758	8	0
+3591	1	0
+5707	0	28
+6100	34700	34698
+298	0	1
+28	1	1
+118	1	1
+24	1	18
+34	1	1
+75	1	1
+43	2	2
+73	1	1
+29	1	1
+246	1	1
+42	1	1
+409	4	4
+1168	10	1
+310	1	1
+49	1	1
+3002	1	1
+38	1	1
+789	0	1
+63	9	9
+2434	0	8
+980	0	2
+749	8	8
+528	1	1
+24	1	1
+1646	15	15
+528	1	1
+16	1	1
+165	12467	12465
+758	1	1
+45	1	1
+213	8	0
+51	1	1
+107	10	11
+134	2	0
+228	103	1
+51	2	1
+68	1	1
+59	1	1
+195	1	161
+13	1	1
+553	2	2
+36	1	1
+143	1	0
+1874	4	0
+519	0	1
+476	1	0
+1530	0	1
+1126	2	0
+831	1	1
+40	1	1
+1131	88	87
+598	1	1
+41	1	1
+1422	0	2
+1950	1	1
+32	1	1
+2037	0	2
+178	2	1
+7938	164527	164525
+7881	0	3
+162	1	1
+39	0	1
+281	1	1
+46	1	1
+1703	1	0
+1253	1	1
+48	1	1
+538	0	2
+576	1	1
+21	1	1
+561	1	0
+3867	10	10
+200	1	1
+29	1	1
+201	2	0
+508	11	11
+1281	1	1
+35	1	1
+299	0	1
+588	1	0
+1231	25	0
+52	0	1
+419	1	0
+1601	6	6
+4040	2	0
+4924	0	1
+4749	1	1
+67	4	4
+39	1	0
+1116	3715	901
+205	2	0
+1591	5	2
+128	29	29
+802	0	89
+1600	0	6
+2177	0	3
+606	14	14
+519	1	0
+540	1	1
+40	1	1
+568	2	0
+458	1	1
+41	1	1
+1105	5	0
+58	1	5
+30	1	1
+558	1	0
+229	1	1
+42	1	1
+610	1	1
+115	1	1
+214	12	12
+237	9	7
+279	1	1
+49	0	2
+13	5	11
+86	1	1
+627	1	0
+473	0	4
+974	7	7
+717	1	1
+19	1	1
+531	1	1
+47	1	1
+372	0	2
+703	0	1
+35	1	1
+53	1	1
+46	1	1
+1322	0	1
+45	1	1
+148	1	1
+19	1	1
+1293	1	1
+44	0	1
+158	0	2
+153	1	0
+1027	21	21
+315	1	1
+48	1	1
+647	0	1
+104	1	1
+31	1	1
+1332	1	1
+63	5	5
+392	5	5
+127	5	5
+68	8	8
+66	1	1
+172	1	1
+156	1	1
+77	1	1
+192	1	1
+25	0	23
+57	0	24
+39	6	0
+34	1	1
+713	1	1
+33	1	0
+507	2	3
+90	4	0
+489	40	0
+63	5	1
+623	17	17
+353	14	14
+1743	1	1
+43	1	1
+1257	49	49
+698	1	1
+41	1	1
+109	1	0
+22	1	1
+288	1	1
+16	1	1
+267	2	1
+175	0	1
+121	1	0
+1158	2	0
+12	1	1
+392	29	12
+515	5	6
+583	1	1
+33	1	1
+616	16	16
+1050	0	10
+42	1	1
+184	1	1
+67	1	1
+102	7	7
+58	0	1
+307	1	1
+36	4	0
+20	24	0
+921	1	0
+913	1	0
+304	0	1
+77	0	1
+756	106	106
+272	1	1
+82	1	1
+56	2	0
+367	4	7
+602	6	6
+2102	9	9
+96	1	1
+45	0	5
+564	10	15
+154	1	0
+438	10	10
+38	0	5
+94	9	13
+2034	1	1
+25	1	1
+73	10	10
+70	5	5
+132	1	1
+52	1	1
+599	1	1
+46	1	1
+279	1	1
+18	1	1
+622	6	0
+224	0	1
+321	16	0
+1783	1	1
+18	2	0
+575	16	16
+60	1	1
+16	1	1
+609	1	1
+28	1	1
+781	3	0
+41	1	1
+57	8	8
+285	2	0
+717	1	1
+85	1	1
+402	0	4
+23	1	1
+64	1	1
+56	1	1
+1387	0	1
+972	4	1
+2390	1	2
+120	0	4
+11	1	1
+652	2	86
+42	0	1
+85	0	1
+22	1	1
+323	1	1
+39	1	1
+185	1	1
+53	4	0
+127	3	0
+703	2	0
+15	1	0
+619	1	1
+45	1	1
+442	16	19
+73	1	1
+25	1	1
+194	1	1
+65	1	1
+129	1	0
+201	49946	49944
+3358	1	1
+25	1	1
+1926	1	1
+39	4	3
+1037	1	1
+40	2	0
+890	6	0
+41	2	0
+498	3	0
+321	0	1
+281	3	0
+414	1	1
+70	1	1
+284	1	0
+214	1	1
+28	1	1
+930	1	1
+47	1	1
+1030	1	1
+91	1	1
+1538	0	1
+3268	1	0
+2180	1	0
+2256	14	14
+594	0	3
+1930	0	4
+3114	1	0
+3833	1	1
+32	1	1
+1073	0	1
+2092	1	0
+38	1	0
+327	2	0
+460	0	6
+8619	0	1
+463	10	12
+315	7	7
+1903	1	1
+18	5	0
+227	5	0
+162	1	1
+28	1	0
+1043	1	0
+29	1	1
+334	1	1
+37	1	1
+177	4	0
+46	0	1
+4	2	2
+484	7	7
+230	1	1
+37	1	1
+81	0	6
+160	1	1
+206	1	1
+356	6	6
+54	1	0
+1704	1	1
+85	1	1
+51	13	13
+207	1	1
+57	2	0
+20	4	7
+59	1	1
+40	1	1
+80	5	5
+16	1	1
+169	12	12
+125	5	5
+119	1	1
+98	1	1
+458	1	1
+26	1	1
+1064	1	1
+30	1	1
+227	0	14
+264	1	1
+44	1	1
+422	1	0
+317	0	6
+282	9	9
+762	8	8
+237	1	0
+199	0	1
+47	1	1
+496	0	3
+1097	4	0
+188	11	11
+143	5	0
+740	1	0
+558	1	1
+36	1	1
+98	1	1
+23	1	1
+232	1	1
+21	0	1
+244	1	1
+35	1	1
+620	1	1
+56	1	1
+470	1	1
+16	1	1
+540	1	1
+42	1	1
+90	1	1
+32	1	1
+110	2	0
+609	12	6
+17	5	1
+21	1	1
+352	2	0
+56	1	1
+175	1	1
+769	1	1
+78	1	1
+87	6	6
+586	0	1
+51	1	1
+92	1	1
+23	1	1
+195	73	72
+619	1	0
+53	1	1
+29	2	2
+357	1	1
+84	1	0
+516	1	1
+41	1	1
+107	11	11
+323	22	25
+114	1	0
+1881	2	0
+1560	2	0
+5260	6	0
+1103	0	4
+832	2	1
+2627	3	11
+34	1	1
+599	0	3
+65	1	1
+230	1	1
+18	1	1
+484	24	0
+150	1	1
+42	1	1
+184	1	1
+8	0	1
+27	1	1
+320	9	9
+376	1	1
+48	1	1
+266	1	1
+44	1	1
+113	1	1
+104	1	1
+297	0	1
+522	0	1500
+471	4	0
+32	1	0
+124	1	1
+46	1	1
+784	8	8
+68	1	1
+21	4	0
+193	7	7
+457	1	1
+23	1	1
+906	1	1
+78	1	1
+385	4	5
+344	1	1
+32	1	0
+669	6	0
+37	1	1
+127	1	1
+29	1	1
+60	5	5
+48	1	1
+290	0	2
+1482	1	1
+39	1	1
+114	1	1
+37	0	4
+104	1	1
+257	1	1
+130	15	16
+158	8	0
+57	1	1
+332	2	2
+35	1	1
+197	1	1
+44	1	1
+106	1	1
+77	1	1
+313	1	1
+44	1	0
+52	19983	20030
+61	7	7
+61	1	1
+120	1	1
+366	1	1
+55	1	1
+121	1	1
+62	1	1
+78	1	1
+48	1	1
+161	1	1
+26	1	1
+191	1	1
+20	11	11
+550	1	1
+76	1	0
+20	1	1
+112	1	1
+149	1	1
+284	1	1
+37	1	1
+705	1	12
+106	12	12
+83	1	1
+46	1	1
+1500	1	1
+81	1	1
+210	1	1
+26	1	1
+713	1	1
+48	1	1
+723	0	3
+196	6	6
+62	2	2
+32	1	1
+606	1	2
+357	1	1
+38	292	0
+589	1	1
+30	1	1
+714	8	8
+639	1	1
+20	1	1
+1068	0	1
+571	1	1
+49	1	1
+436	0	1
+609	0	2
+30	1	1
+66	0	1
+349	11	11
+65	1	1
+40	1	1
+717	0	3
+299	1	1
+29	1	1
+724	1	0
+275	1	1
+33	1	1
+318	0	3
+279	1	1
+28	1	1
+389	1	0
+548	0	8
+330	1	1
+47	1	1
+170	1	1
+47	1	1
+519	14	14
+841	24	24
+732	1	1
+29	3	3
+688	2	2
+23	0	1
+94	14	14
+726	13	13
+508	0	12
+21	6	0
+69	1	1
+37	1	1
+590	1	1
+59	1	1
+89	11	11
+164	1	1
+58	1	1
+1709	18	18
+520	1	1
+27	1	1
+683	10	10
+814	1	1
+26	1	1
+350	1	1
+39	1	1
+132	6	6
+439	1	1
+38	41	6
+15	0	1
+5	4	11
+81	1	1
+19	0	2
+167	1	1
+90	0	2
+85	1	1
+78	1	1
+87	19	2
+53	23	0
+255	0	1
+211	1	1
+54	1	1
+206	0	1
+60	35	33
+279	1	1
+76	179	180
+90	1	1
+119	3	0
+19	1	1
+60	1	1
+347	0	4
+30	2	2
+68	1	1
+78	1	1
+298	5	5
+67	1	1
+99	1	1
+97	1	1
+74	1	1
+52	1	1
+44	1	1
+65	1	4
+349	14	14
+109	1	1
+159	2	2
+214	9	9
+97	1	1
+73	1	1
+58	1	1
+42	1	1
+133	1	1
+99	0	10
+124	12	12
+281	3	0
+940	2	2
+49	1	1
+303	1	1
+25	1	1
+309	15	22
+384	1	1
+24	1	1
+896	1	1
+56	1	1
+168	0	19
+54	6	14
+66	1	1
+502	1	1
+4	0	1
+23	1	1
+581	1	1
+47	1	1
+122	15	15
+3352	1	1
+23	1	1
+873	4	4
+887	1	0
+1827	1	0
+216	6	6
+805	2	0
+874	8	0
+2274	1	1
+47	1	1
+736	25	29
+86	1	1
+19	1	1
+1794	9	9
+271	0	1
+2266	1	1
+34	1	1
+916	0	1
+21	1	1
+108	21	21
+141	1	1
+27	1	1
+406	3	0
+3830	59	59
+61	1	1
+38	1	1
+128	2	2
+56	1	1
+72	0	1
+96	1	1
+22	1	1
+169	7	7
+511	1	1
+38	1	1
+1070	1	1
+90	1	1
+50	1	1
+41	1	0
+30	1	1
+659	12	12
+701	1	1
+33	1	1
+569	15	15
+70	1	1
+38	1	1
+955	0	3
+130	1	1
+63	1	1
+251	8	8
+191	1	1
+26	0	3
+187	1	0
+916	5	1
+70	13	13
+498	1	0
+55	0	1
+242	25	25
+237	1	1
+20	0	1
+61	1	1
+203	6	6
+262	1	1
+154	1	1
+104	1	1
+20	1	1
+156	1	1
+32	1	1
+88	17	17
+139	13	13
+148	20156	20120
+885	1	1
+113	1	1
+141	2	0
+842	1	0
+1246	1	1
+29	1	1
+898	1	1
+19	1	1
+333	1	1
+44	1	1
+220	1	1
+56	2	0
+209	1	1
+70	1	1
+223	0	20
+182	1	1
+69	1	1
+56	1	1
+111	1	1
+220	1	1
+89	1	1
+119	1	1
+113	2	0
+195	1	1
+46	1	1
+101	8	8
+85	1	1
+50	0	4
+76	0	4
+53	3	1
+43	1	1
+153	1	1
+53	1	1
+195	6	0
+60	1	1
+278	1	0
+42	1	1
+298	1	1
+54	1	1
+262	4	4
+67	1	1
+32	1	0
+28	1	1
+612	1	1
+78	1	1
+157	1	1
+19	1	1
+64	1	2
+31	1	1
+52	1	1
+51	1	1
+77	10295	10251
+91	1	1
+35	1	1
+5232	1	1
+47	1	1
+295	2	0
+2065	2	0
+1143	13	13
+335	2	0
+1944	4	0
+39	6	0
+4057	5	8
+535	1	1
+16	1	1
+1555	0	1
+3130	1	1
+17	1	1
+4196	1	0
+14974	0	1
+3667	2	6
+42	22	0
+63	2	0
+15	2	0
+61	0	160
+66	1	14
+70	2	0
+25	44	4
+49	6	77
+18	0	6
+24	0	2
+57	143	3
+61	0	2
+29	20	0
+37	0	2
+29	0	74
+58	1	29
+34	1	5
+21	31	0
+12	0	65
+62	11	0
+5	0	41
+68	1	42
+23	1	3
+12	2	0
+17	1	29
+51	29	1
+6	2	0
+25	53	1
+52	2	0
+125	19	58
+124	41	0
+51	49	29
+79	89	0
+53	21	0
+5064	0	2
+6897	1	1
+38	1	1
+2821	0	1
+85	1	1
+31	0	4
+399	14	14
+408	0	1
+956	1	1
+29	1	0
+9	2	0
+442	4	0
+342	1	1
+24	1	1
+131	1	1
+198	1	1
+370	0	1
+34	1	1
+447	21	20
+259	1	1
+23	0	1
+121	2	0
+2257	1	1
+22	1	1
+811	1	1
+27	1	1
+484	0	1
+259	0	5
+843	0	2889
+55	0	88
+1189	2	0
+2276	1	0
+353	8	0
+7126	0	1
+798	1	1
+31	0	1
+6	1	1
+268	1	1
+27	1	1
+131	0	2
+47	1	1
+367	1	1
+61	1	1
+84	14	14
+173	15	15
+883	1	1
+41	1	1
+1356	1	1
+134	1	1
+62	1	1
+18	1	1
+644	1	1
+17	1	1
+297	15	14
+1015	26	26
+1532	4	0
+16	1	1
+183	1	0
+2792	12	12
+2660	0	2
+254	1	2
+1369	1	0
+342	0	1
+49	1	1
+733	0	1
+50	82	82
+60	1	1
+48	1	1
+1488	1	0
+97	1	1
+84	6	6
+214	1	1
+37	1	1
+222	1	1
+53	1	1
+220	58	0
+238	0	3
+459	1	1
+39	1	1
+222	1	1
+67	1	1
+280	1	1
+45	0	16
+208	1	1
+39	1	1
+135	1	1
+46	1	1
+121	1	1
+19	1	1
+349	1	1
+30	1	1
+56	1	1
+23	1	1
+283	1	1
+51	2	2
+217	1	1
+44	1	1
+92	1	1
+36	1	1
+67	1	1
+38	3	1
+23	4	0
+598	1	1
+45	1	1
+663	1	1
+59	1	0
+10	1	1
+70	1	1
+65	2	0
+11	0	16
+36	1	1
+342	17	17
+70	0	3
+243	1	1
+55	1	1
+63	17	17
+2165	5	2
+132	10	6
+136	18	13
+363	1	1
+89	1	1
+382	1	1
+29	1	1
+58	8	7
+297	4	0
+66	1	1
+93	1	0
+145	1	1
+31	5	5
+576	1	1
+89	1	1
+811	16	16
+428	0	13
+67	1	1
+193	2	2
+23	1	1
+51	1	0
+727	1	0
+1148	12	12
+837	1	1
+77	1	1
+941	10	10
+776	19	19
+300	1	1
+24	1	1
+256	1	7
+93	1	1
+188	17	13
+117	1	1
+43	1	1
+563	1	1
+104	4	4
+2898	1	1
+46	1	1
+282	1	1
+39	1	1
+698	1	1
+20	1	1
+140	1	1
+26	1	1
+745	0	2
+541	6	0
+1540	1	0
+781	1	1
+35	4	4
+202	1	1
+48	1	1
+168	1	1
+53	1	1
+379	10	10
+1178	14	14
+132	5	0
+555	1	1
+42	1	1
+573	1	1
+21	1	1
+462	1	1
+43	1	1
+121	1	1
+48	0	3
+13	1	7
+8319	1	0
+21899	0	1
+8703	0	1
+1206	0	1
+13954	0	1
+12475	1	0
+6716	0	1
+3072	0	4
+7591	0	1
+3322	9	10
+539	1	0
+1736	14	0
+3128	0	2
+4464	0	1
+120	4	4
+3473	1	0
+378	1	0
+576	5	9
+684	0	3
+1182	1	0
+654	0	3
+2049	1	0
+6838	1	1
+39	1	1
+186	1	0
+2718	1	1
+30	1	1
+160	11	11
+4954	0	1
+420	1	1
+123	1	1
+156	0	4
+219	4	0
+195	1	0
+4402	3	0
+3045	0	1
+1249	1	0
+3522	0	10
+808	5	1
+349	0	1
+8538	5	0
+455	1	0
+119	0	1
+1127	1	0
+276	1	0
+10672	1	0
+833	0	1
+4251	1	0
+8	1	1
+2079	0	1
+1736	8	11
+1612	0	1
+1373	5	0
+2438	4	0
+6147	7	0
+64	1	1
+3799	1	0
+258	2	0
+899	1	0
+1362	8	9
+593	0	2
+3351	2	0
+618	0	4
+917	0	3
+2797	2	0
+2776	2	0
+23968	6	0
+1616	0	1
+1686	0	4
+2221	0	8
+252	14783	14780
+11763	0	1
+2431	1	0
+158	0	1
+281	1	0
+1573	0	1
+11079	1	0
+6938	0	1
+4376	61201	59265
+14552	0	4
+672	1	1
+26	1	1
+461	1	1
+33	0	2
+16	1	1
+649	1	1
+48	1	1
+818	1	1
+21	1	1
+424	1	1
+25	1	1
+632	1	1
+39	1	1
+310	1	1
+27	1	1
+616	1	0
+17043	23170	23168
+104	7	6
+290	3	3
+117	13	0
+2194	0	1
+191	0	1
+118	1	0
+1283	7	7
+723	1	0
+7453	1	0
+3382	0	1
+2179	0	49
+5260	0	1
+4607	1	0
+32465	1	0
+1362	0	1
+20971	5	4
+11765	9	9
+746	11	11
+19671	17	17
+439	16	16
+9146	0	3
+99	1	1
+19	1	1
+259	1	1
+57	1	1
+202	1	1
+27	1	1
+2009	9	9
+2299	1	1
+43	1	1
+1287	1	0
+22328	5	0
+47	12	0
+1295	77056	62052
+228	0	2
+615	1	0
+1965	0	2
+1466	1	0
+3821	0	1
+2806	1	1
+110	0	1
+1422	0	1
+324	1	0
+1825	1	0
+311	0	1
+11796	1	0
+2273	2	1
+6123	1	0
+18640	29	29
+1283	0	3
+167	1	0
+11393	6	6
+708	15	14
+1887	10	0
+509	1	0
+1581	1	1
+46	1	1
+811	1	1
+31	0	1
+1557	43	43
+1172	1	1
+18	1	1
+67	1	0
+2081	0	2
+373	0	4
+1829	1	1
+56	0	1
+1700	0	4
+2886	2	0
+14416	1	0
+2137	1	0
+2717	0	1
+1587	0	1
+7106	8	0
+2428	1	1
+50	1	0
+1082	1	1
+42	1	1
+639	1	0
+717	11	11
+53	1	1
+61	1	1
+454	1	1
+26	1	1
+1053	1	1
+60	1	1
+51	1	1
+26	1	0
+102	1	1
+67	1	1
+71	1	1
+134	1	1
+85	1	1
+607	36	0
+58	1	1
+1266	2	0
+480	14	21
+1459	2	1
+435	15	17
+1204	30	0
+1762	2	0
+123	1	0
+3025	0	1
+771	1	0
+3211	0	1
+3410	13	0
+1260	1	0
+591	0	1
+1107	15	15
+5811	0	22
+4103	0	2
+4882	1	0
+2138	3	2
+2203	2	1
+2338	1	0
+3316	1	1
+27	2	0
+6360	0	1
+251	19	7
+6605	1	1
+23	2	0
+360	0	2
+1292	0	2
+3992	46	46
+554	0	21
+4473	2	3
+921	1	1
+47	1	1
+2605	9	3
+50	1	1
+178	1	1
+26	1	1
+316	0	2
+1120	4	0
+177	1	2
+960	1	1
+65	1	1
+964	4	4
+783	8	8
+61	34	13
+121	1	1
+22	1	0
+118	1	1
+49	4	4
+281	1	1
+27	1	1
+958	0	1
+107	1	1
+31	1	1
+171	14	14
+302	0	13
+33	1	1
+108	0	4
+98	1	1
+53	1	1
+457	2	0
+529	1	1
+37	2	0
+1829	1	1
+38	1	1
+440	1	1
+82	3	4
+647	45	45
+660	1	1
+28	1	1
+1993	0	1
+373	19	19
+835	1	1
+42	1	1
+947	1	1
+36	1	0
+1055	1	1
+43	1	1
+475	1	0
+60	1	1
+127	1	1
+509	1	1
+71	1	1
+485	1	0
+26	1	1
+531	1	1
+18	1	1
+551	1	1
+18	1	1
+884	5	5
+147	53	60
+527	1	1
+26	2	2
+322	0	17
+32	2	2
+85	1	1
+45	1	1
+625	0	323
+540	0	1
+43	1	1
+266	0	2
+228	1	1
+42	1	1
+283	1	1
+92	1	1
+381	1	1
+40	1	1
+1906	0	4
+3495	0	4
+967	1	1
+76	1	1
+3236	4	4
+529	7	7
+246	4	0
+38	1	1
+156	0	6
+1466	0	2
+499	1	0
+937	1	1
+45	1	1
+421	6	0
+87	22	22
+1254	1	1
+36	0	1
+357	18	18
+391	0	1
+451	1	0
+105	1	1
+47	1	0
+255	6	6
+739	3	0
+386	1	1
+33	1	1
+281	4	0
+481	2	0
+495	1	1
+42	4	0
+219	0	1
+408	1	1
+23	1	1
+283	1	1
+25	0	1
+541	1	0
+88	2	0
+216	1	1
+29	1	1
+457	1	0
+331	9	1
+199	15	15
+228	1	0
+4	2	0
+333	0	1
+19	1	1
+910	1	1
+27	1	1
+142	3	3
+35	1	1
+1211	1	1
+34	1	1
+667	0	2
+64	1	1
+78	1	1
+1519	1	1
+27	1	1
+154	14	14
+1090	1	1
+40	0	3
+35	1	1
+1355	0	4
+79	1	1
+145	1	1
+63	1	1
+70	1	1
+21	1	1
+695	1	1
+41	2	2
+564	1	1
+46	1	1
+279	4	0
+38	5	5
+3523	32	32
+545	1	1
+27	1	0
+54	15	16
+1212	0	14
+34	0	11
+787	2	0
+3691	1	0
+1843	1	1
+45	1	0
+11	1	2
+3499	1	1
+27	1	1
+1047	0	2
+1804	2	0
+1079	1	1
+17	1	1
+639	3	5
+73	1	1
+13	13	0
+66	1	1
+391	0	7
+4547	0	1
+53	9	6
+691	0	1
+989	1	1
+143	1	1
+223	0	2
+95	1	1
+1000	1	1
+41	1	1
+93	1	1
+49	1	1
+606	1	1
+48	1	1
+128	0	4
+109	1	31
+44	10	781
+62	4	0
+129	1	1
+62	1	1
+106	1	1
+247	1	1
+20	18	4
+125	1	1
+43	1	1
+909	0	2
+381	4	4
+74	1	1
+408	1	0
+1595	5	0
+3690	1	1
+64	1	1
+754	0	4
+1877	1	1
+49	1	1
+1095	11	0
+734	0	23
+3072	2	0
+1879	0	1
+572	0	8
+215	1	1
+58	1	1
+301	1	1
+42	1	1
+265	24	0
+209	11	11
+953	1	1
+42	0	5
+58	1	0
+95	1	0
+210	1	1
+27	1	1
+882	1	1
+17	1	1
+751	0	1
+24	1	1
+351	1	1
+43	3	3
+565	1	1
+15	1	1
+150	27	27
+94	1	0
+323	1	1
+23	1	1
+221	7	7
+705	15	0
+631	2	0
+64	1	1
+1577	1	1
+21	0	1
+354	0	9
+189	0	1
+283	1	1
+48	1	1
+227	1	1
+40	0	3
+1357	0	2
+1571	7	7
+1153	1	1
+93	1	1
+797	14	14
+433	8	0
+108	11	11
+140	1	1
+40	1	1
+470	1	1
+42	1	1
+1106	0	2
+84	4	4
+129	1	1
+123	1	0
+95	1	1
+82	0	3
+661	1	1
+77	1	1
+57	1	1
+62	1	1
+473	2	0
+262	6	0
+45	1	1
+49	3	0
+321	0	1
+197	2	104
+87	222	0
+115	0	10
+92	0	4
+108	6	0
+563	14	14
+324	1	0
+205	1	1
+17	1	1
+495	0	1
+201	4	0
+14	1	1
+1080	1	1
+24	1	1
+91	24	24
+279	1	1
+95	1	1
+121	1	1
+62	1	1
+2371	1	0
+164	9	1
+655	1	1
+30	1	1
+271	1	1
+47	1	1
+609	1	0
+1780	2	0
+742	1	1
+40	1	1
+272	1	1
+52	1	1
+1187	1	1
+23	1	1
+254	1	1
+60	1	1
+176	3	6
+463	1	1
+36	1	1
+797	1	1
+22	1	1
+395	5	2
+61	1	1
+31	3	3
+226	1	1
+59	1	1
+581	1	1
+46	1	1
+412	1	1
+23	1	0
+74	1	1
+17	1	1
+81	1	1
+24	1	1
+83	15	15
+363	1	1
+91	1	1
+383	20	20
+199	13	13
+976	1	1
+39	0	3
+161	14	15
+127	16	16
+517	1	1
+132	1	1
+167	28	28
+124	1	1
+68	0	22
+1074	0	1
+175	1	0
+1018	1	1
+90	4	4
+1034	15	15
+69	1	1
+33	1	1
+174	1	1
+56	1	1
+169	1	0
+201	1	1
+30	1	1
+58	1	1
+38	1	1
+91	1	1
+98	4	4
+65	1	1
+19	2	0
+104	6	5
+25	1	1
+218	1	1
+37	1	1
+343	236832	150022
+67	8	8
+36	0	11
+62	1	1
+107	1	1
+68	3	130
+66	4	4
+50	21	21
+98	1	1
+127	1	0
+192	1	1
+71	1	1
+52	1	1
+200	1	1
+307	0	1
+331	1	1
+97	11	11
+171	1	1
+61	1	1
+37	1	1
+156	3	0
+63	0	3
+155	4	1
+31	2	0
+232	1	1
+33	1	1
+175	2	0
+131	6	6
+1409	0	3
+180	1	1
+65	0	1
+703	1	1
+19	1	1
+702	1	1
+65	1	1
+532	1	1
+48	1	1
+347	0	12
+578	16	17
+965	1	1
+45	1	1
+893	78201	80000
+406	1	1
+22	1	1
+462	1	1
+139	1	1
+154	1	0
+37	1	9
+11	2	0
+22	2	0
+14	46	22
+320	1	1
+117	1	1
+493	1	1
+129	1	1
+243	27	30
+170	1	1
+125	3	3
+2476	4	0
+27525	1	0
+2162	0	2
+2887	0	1
+17286	4	0
+22898	0	1
+51	9	9
+60	26	25
+312	15	11
+1008	17	17
+85	1	1
+49	1	1
+702	1	0
+87	1	1
+37	1	1
+859	8	8
+296	4	4
+105	0	4
+43	1	1
+67	10	7
+2839	3	0
+1283	1	1
+67	0	1
+32	2	0
+61	1	1
+140	15	15
+1047	1	1
+38	1	1
+87	1	1
+24	5	4
+1291	1	1
+49	1	1
+421	0	1
+75	1	1
+78	1	1
+243	1	0
+33	1	1
+116	19	19
+65	0	1
+238	0	1
+179	2	1
+67	1	1
+60	1	1
+32	1	1
+677	4	6
+83	314	0
+334	1	0
+1018	5	5
+127	1	1
+83	1	1
+347	0	2
+111	1	1
+30	1	1
+66	1	1
+38	1	1
+218	8	8
+754	1	1
+65	1	1
+182	1	1
+21	1	1
+285	1	1
+75	1	1
+147	6	0
+65	1	1
+42	1	1
+380	1	1
+84	2	0
+88	1	1
+25	1	1
+210	1	1
+17	1	1
+136	6	5
+108	1	1
+40	1	0
+50	1	1
+111	1	0
+21	0	1066
+119	0	1
+2641	1	1
+22	1	1
+689	1	1
+41	1	1
+1415	1	1
+29	1	1
+2252	1	1
+19	1	1
+1524	0	10
+2104	0	1
+511	2	0
+1696	26	8
+2593	0	177
+338	1	1
+37	2	2
+395	10	0
+67	1	1
+131	1	1
+31	1	1
+386	1	1
+42	1	1
+372	1	1
+48	1	1
+8705	0	4
+329	9	9
+600	2	0
+261	8	8
+9909	0	2
+2337	2	0
+2567	1	1
+26	1	1
+561	1	1
+48	1	1
+2440	1	1
+30	1	1
+1289	0	1
+162	1	0
+730	0	3
+658	1	0
+25	1	1
+1027	1	1
+43	1	1
+472	0	1
+219	1	1
+20	1	1
+495	1	0
+6	2	0
+1007	0	1
+169	0	10
+33	1	1
+266	11	11
+752	1	1
+30	1	1
+438	1	1
+39	1	1
+511	0	1
+1247	1	0
+1055	1	0
+491	1	0
+108	1	1
+48	1	1
+1324	0	1
+143	1	1
+40	1	1
+679	1	1
+45	1	1
+1036	0	2
+58	1	1
+46	1	1
+229	16	16
+149	10	10
+94	1	1
+63	1	1
+222	2	0
+55	1	1
+115	5	1
+219	15	15
+692	28	28
+159	1	1
+41	1	1
+211	1	0
+20	1	1
+1099	0	4
+155	6	0
+178	13	15
+32	1	1
+953	1	1
+47	1	1
+174	1	1
+22	1	1
+402	0	12
+588	5	21
+288	4	4
+86	1	1
+29	0	2
+67	3	0
+641	0	1
+571	0	1
+250	1	1
+34	1	1
+255	0	2
+572	12	12
+275	6	1
+974	0	1
+578	12	12
+612	1	1
+43	1	1
+56	0	7
+1170	0	1
+1242	0	8
+2108	5	0
+1090	0	2
+4424	1	1
+34	1	1
+4897	8	0
+1998	2	0
+114	0	1
+2874	1	1
+21	1	1
+442	22	22
+805	0	1
+3476	16	0
+7063	0	1
+65	3	0
+7475	0	4
+9515	5	1
+172	1	1
+49	1	1
+1349	22	22
+9662	2	0
+4856	3	0
+7447	6	6
+421	1	0
+884	6	0
+17	1	0
+3075	1	0
+11403	50004	0
+1397	12	12
+1859	3	1
+3762	2	0
+601	2	0
+7617	1	0
+1604	0	16
+3589	0	1
+1487	2	1
+1196	0	20
+2233	1	0
+192	4	4
+1470	9	27
+880	1	12
+2490	1	0
+151	1	1
+33	1	1
+2191	1	1
+47	1	1
+572	1	1
+17	1	1
+512	1	1
+83	1	1
+107	0	1
+4191	1	1
+36	1	1
+1530	1	1
+23	1	1
+311	0	4
+47	1	1
+141	2	0
+73	1	1
+330	1	1
+54	0	1
+32	0	1
+210	4	0
+219	1	0
+24	1	1
+425	1	1
+34	2	2
+1227	11	11
+2454	1	1
+36	1	1
+1368	1	1
+39	1	1
+134	1	1
+28	1	1
+123	1	1
+46	4	4
+839	9	0
+1244	1	1
+32	5	5
+2063	12	0
+357	3	0
+321	46	46
+873	1	1
+47	1	1
+1156	10	9
+1180	9	1
+271	9	9
+1870	0	1
+17	1	0
+366	7	7
+101	0	1
+134	8	8
+1654	0	4
+8741	1	1
+24	1	1
+1003	0	186
+12	0	20
+906	13	13
+1313	241	241
+2062	16	16
+1485	1	1
+18	1	1
+883	1	1
+20	1	1
+1354	1	1
+28	1	1
+283	5	5
+640	1	1
+40	1	1
+560	1	1
+42	1	1
+1144	19	19
+57	1	1
+21	1	1
+216	1	1
+109	1	1
+105	1	1
+208	5	5
+124	1	1
+112	3	3
+207	40	40
+244	1	1
+60	1	1
+98	1	1
+50	1	1
+256	5	5
+23	1	1
+157	1	1
+33	1	1
+143	1	1
+59	1	1
+51	1	1
+45	1	0
+73	1	1
+81	1	1
+5071	0	35
+42407	0	26
+13084	15	11
+333	5	0
+1235	6	6
+899	1	0
+1077	11	0
+1521	1	0
+38	1	1
+135	1	1
+42	1	1
+63	4	3
+385	1	1
+49	1	1
+77	20	22
+111	11	11
+190	2	2
+45	1	1
+373	1	1
+47	1	1
+77	10	10
+186	1	1
+24	1	1
+855	1	0
+23	1	1
+86	27	27
+148	1	0
+249	1	1
+22	1	1
+88	1	1
+31	1	1
+816	0	331
+433	1	1
+31	1	1
+53	1	1
+27	1	1
+101	1	1
+29	1	1
+406	1	1
+43	1	1
+306	1	1
+25	0	5
+68	1	1
+727	7	7
+237	1	1
+65	1	1
+178	1	1
+52	1	1
+667	1	1
+17	1	1
+359	1	1
+22	1	1
+1244	1	1
+36	1	1
+1349	29808	29806
+7637	1	1
+37	1	1
+1019	0	1
+10399	0	1
+10494	21750	21748
+607	26	26
+5347	2	0
+2375	3	0
+1594	1	0
+363	4	0
+2394	2	0
+3590	0	2
+2891	1	0
+621	1	0
+563	0	2
+85	0	13
+160	18	19
+1807	0	2
+291	0	1
+2273	8	0
+2568	1	0
+657	0	1
+772	4	0
+377	8	0
+62	52	0
+778	0	1
+391	62	72
+1596	2	0
+1317	2	0
+5358	0	3
+2273	0	1
+597	0	8
+993	0	26
+1897	1	0
+76	0	1
+966	1	0
+2611	2	0
+1374	18	0
+831	33	33
+1574	0	2
+306	0	1
+4789	0	3
+2404	1	1
+33	1	1
+507	4	0
+1627	50858	50856
+7863	53819	53813
+259	1	0
+752	3	1
+497	5	6
+3113	3	0
+748	1	0
+3002	0	1
+836	1	1
+22	1	0
+251	1	1
+27	1	1
+4128	0	1
+8869	29	0
+4065	0	2
+19869	0	1
+564	1	0
+4734	1	1
+36	1	1
+5630	1	0
+339	0	3
+1029	12	12
+15996	0	3
+1380	6	6
+57	0	1
+6265	14	14
+127	1	1
+21	1	1
+1709	1	1
+131	1	1
+64	9	9
+67	0	2
+290	23	22
+456	1	0
+587	0	1
+1610	0	2
+1243	1	0
+26	1	1
+2049	0	1
+1091	0	21
+357	11	14
+90
+
+chain	125812	chr6_ssto_hap7	4928567	+	3907506	3911494	chr4	191273063	+	128070000	128074446	1022492
+87	39	39
+217	93	93
+54	128	128
+101	185	185
+82	24	24
+306	274	274
+86	19	19
+109	42	42
+79	311	313
+96	87	87
+72	74	530
+57	170	170
+64	268	268
+56	709	709
+99
+
+chain	123442	chr6_ssto_hap7	4928567	+	3929629	3931354	chr2	242951149	-	63927014	63946734	1041108
+108	1	1
+44	0	2
+39	0	554
+170	0	2655
+81	3	3007
+63	15	1052
+119	0	1562
+96	0	5290
+67	9	9
+97	0	3890
+317	1	1
+39	1	1
+234	0	4
+116	1	1
+18	3	0
+83
+
+chain	92865	chr6_ssto_hap7	4928567	+	3892702	3894943	chr5	180857866	-	117045391	117059708	1366079
+75	6	6
+69	60	59
+68	1	0
+272	118	118
+148	29	29
+50	4	4
+75	91	91
+79	11	11
+52	94	94
+155	362	12440
+253	93	93
+76
+
+chain	86945	chr6_ssto_hap7	4928567	+	4078541	4079510	chr17	78774742	-	73855076	73856044	1454888
+79	12	12
+357	1	1
+20	1	1
+121	1	0
+377
+
+chain	80740	chr6_ssto_hap7	4928567	+	2343665	2344522	chr6	170899992	-	139781917	139782778	1563240
+341	0	4
+516
+
+chain	52870	chr6_ssto_hap7	4928567	+	2557772	2559707	chr1	247249719	+	7396445	7398379	2394598
+102	170	170
+115	745	743
+132	82	82
+58	214	214
+173	73	74
+71
+
+chain	47213	chr6_ssto_hap7	4928567	+	3973739	3974661	chr5	180857866	+	134244858	134245983	2704507
+144	28	28
+67	90	94
+193	60	61
+52	141	339
+53	41	41
+53
+
+chain	45302	chr6_ssto_hap7	4928567	+	4047815	4048319	chr5	180857866	-	98127286	98127790	2833261
+202	1	1
+153	1	1
+147
+
+chain	41978	chr6_ssto_hap7	4928567	+	1328154	1328662	chr6	170899992	+	30106460	30106967	3091365
+343	49	48
+116
+
+chain	40676	chr6_ssto_hap7	4928567	+	3875056	3875551	chr11	134452384	-	84966990	84967480	3207740
+246	1	1
+93	33	28
+122
+
+chain	35112	chr6_ssto_hap7	4928567	+	3906419	3911395	chr6	170899992	-	169520190	169525607	1043651
+51	464	464
+53	202	202
+87	154	151
+74	492	483
+28	798	798
+12	65	65
+50	80	80
+67	619	621
+27	1627	2078
+26
+
+chain	32670	chr6_ssto_hap7	4928567	+	3859757	3860527	chrX	154913754	+	119403135	119403904	4176412
+56	142	141
+152	178	178
+66	56	56
+120
+
+chain	29091	chr6_ssto_hap7	4928567	+	3895286	3896158	chr11	134452384	+	7157531	7158401	1526824
+161	614	612
+97
+
+chain	28481	chr6_ssto_hap7	4928567	+	4205119	4205417	chr17	78774742	+	29063769	29064067	5407271
+298
+
+chain	27018	chr6_ssto_hap7	4928567	+	3840659	3840971	chr18	76117153	-	36956533	36956845	6049052
+120	15	15
+177
+
+chain	25604	chr6_ssto_hap7	4928567	+	3994310	3994584	chr15	100338915	-	55375038	55375312	6715162
+274
+
+chain	23990	chr6_ssto_hap7	4928567	+	1194494	1195270	chr7	158821424	-	51137320	51138262	7695545
+178	101	101
+72	385	551
+40
+
+chain	23269	chr6_ssto_hap7	4928567	+	4043201	4044141	chr6	170899992	+	32821586	32822354	8132442
+218	672	500
+50
+
+chain	22259	chr6_ssto_hap7	4928567	+	1328662	1328894	chr10	135374737	+	129836641	129836873	8045146
+232
+
+chain	21089	chr6_ssto_hap7	4928567	+	3982819	3983044	chr14	106368585	+	105956394	105956619	9616367
+225
+
+chain	21066	chr6_ssto_hap7	4928567	+	4492538	4492777	chr8	146274826	+	14484871	14485110	2051461
+239
+
+chain	19470	chr6_ssto_hap7	4928567	+	3875397	3875736	chrX	154913754	-	111580561	111580900	4149836
+32	122	122
+185
+
+chain	19015	chr6_ssto_hap7	4928567	+	4093694	4093926	chr11	134452384	+	111558067	111558299	11259779
+149	20	20
+63
+
+chain	18910	chr6_ssto_hap7	4928567	+	3979875	3980839	chr6	170899992	+	32656485	32657452	11346766
+153	738	741
+73
+
+chain	18705	chr6_ssto_hap7	4928567	+	4047429	4047645	chr3	199501827	+	1828236	1828452	4490189
+145	5	5
+66
+
+chain	15452	chr6_ssto_hap7	4928567	+	3913430	3913596	chrX	154913754	+	67920599	67920765	14594390
+166
+
+chain	15351	chr6_ssto_hap7	4928567	+	2675966	2676167	chr11	134452384	+	74426248	74426449	14701293
+99	26	26
+76
+
+chain	15233	chr6_ssto_hap7	4928567	+	4047645	4047815	chr9	140273252	+	78741245	78741415	2998928
+170
+
+chain	15018	chr6_ssto_hap7	4928567	+	1260636	1260812	chr10	135374737	+	90412720	90412896	15044285
+117	3	3
+56
+
+chain	13654	chr6_ssto_hap7	4928567	+	180964	181124	chr18	76117153	-	3498140	3498418	7857183
+83	1	1
+24	4	122
+48
+
+chain	13627	chr6_ssto_hap7	4928567	+	3831356	3831761	chr6	170899992	+	32665471	32665876	16657612
+57	86	85
+47	147	148
+68
+
+chain	13048	chr6_ssto_hap7	4928567	+	3955374	3955802	chr2	242951149	+	206984071	206984490	17422582
+94	272	263
+62
+
+chain	12923	chr6_ssto_hap7	4928567	+	3954673	3954823	chr18	76117153	-	36956845	36956995	17596042
+150
+
+chain	12671	chr6_ssto_hap7	4928567	+	4090259	4090393	chrX	154913754	-	65797896	65798030	17982401
+134
+
+chain	12395	chr6_ssto_hap7	4928567	+	3983294	3983607	chrX	154913754	-	110185784	110186095	13720297
+4	222	220
+87
+
+chain	12272	chr6_ssto_hap7	4928567	+	2565285	2565441	chrX	154913754	+	154847615	154847763	18572104
+71	1	1
+25	8	0
+51
+
+chain	12207	chr6_ssto_hap7	4928567	+	3955802	3957116	chr4	191273063	-	84720316	84722799	17649000
+5	186	1341
+68	1003	1017
+52
+
+chain	12179	chr6_ssto_hap7	4928567	+	3836462	3836590	chr6	170899992	+	32566069	32566197	18716373
+128
+
+chain	12178	chr6_ssto_hap7	4928567	+	4018814	4018980	chr14	106368585	-	58343221	58343386	18718222
+55	26	25
+85
+
+chain	12137	chr6_ssto_hap7	4928567	+	3877094	3877505	chr7	158821424	+	90920405	90920810	18779047
+54	266	260
+91
+
+chain	11985	chr6_ssto_hap7	4928567	+	3892853	3894867	chr3	199501827	-	92708356	92711059	1441087
+59	394	394
+65	307	307
+90	391	391
+54	622	1311
+32
+
+chain	11952	chr6_ssto_hap7	4928567	+	4105293	4105419	chr4	191273063	-	72853862	72853988	19072608
+126
+
+chain	11593	chr6_ssto_hap7	4928567	+	3812675	3812798	chr1	247249719	-	238369051	238369174	19677686
+123
+
+chain	11535	chr6_ssto_hap7	4928567	+	1260812	1261322	chr1	247249719	-	129350638	129351114	18024798
+7	405	371
+98
+
+chain	11457	chr6_ssto_hap7	4928567	+	3994790	3994923	chr3	199501827	-	53316844	53316977	14718915
+32	6	6
+95
+
+chain	11393	chr6_ssto_hap7	4928567	+	4065042	4065262	chr10	135374737	-	122210308	122210526	20025571
+60	86	84
+74
+
+chain	11122	chr6_ssto_hap7	4928567	+	1240573	1241390	chr6	170899992	-	139553083	139553887	20511868
+77	676	663
+64
+
+chain	10873	chr6_ssto_hap7	4928567	+	1229721	1229842	chr19	63811651	+	15986631	15986752	20965590
+121
+
+chain	10852	chr6_ssto_hap7	4928567	+	2675511	2675627	chr15	100338915	-	60167597	60167713	16273330
+116
+
+chain	10686	chr6_ssto_hap7	4928567	+	2564433	2564954	chr18	76117153	+	11332173	11332695	21332096
+80	388	389
+53
+
+chain	10631	chr6_ssto_hap7	4928567	+	3935233	3935343	chr12	132349534	-	69483966	69484076	21446055
+110
+
+chain	10605	chr6_ssto_hap7	4928567	+	1188476	1188620	chr6	170899992	+	30566919	30567064	21497459
+81	23	24
+40
+
+chain	10522	chr6_ssto_hap7	4928567	+	3885687	3885969	chr6	170899992	+	32650612	32650898	21668161
+51	155	159
+76
+
+chain	10487	chr6_ssto_hap7	4928567	+	3763802	3763912	chr6	170899992	+	32525095	32525205	21738406
+110
+
+chain	10446	chr6_ssto_hap7	4928567	+	3838076	3838188	chr10	135374737	+	116791472	116791584	21828224
+112
+
+chain	10440	chr6_ssto_hap7	4928567	+	3816404	3816534	chr3	199501827	-	53390365	53390495	21843020
+67	9	9
+54
+
+chain	10424	chr6_ssto_hap7	4928567	+	1233358	1233620	chr1	247249719	-	93388912	93389184	21873908
+71	137	147
+54
+
+chain	10414	chr6_ssto_hap7	4928567	+	3814490	3814706	chr20	62435964	-	30230151	30230368	21892854
+65	92	93
+59
+
+chain	10301	chr6_ssto_hap7	4928567	+	3898517	3899557	chr6	170899992	+	32656523	32657565	22135092
+82	902	904
+56
+
+chain	10251	chr6_ssto_hap7	4928567	+	3994584	3994790	chr1	247249719	-	4492483	4492689	9976242
+1	153	153
+52
+
+chain	10098	chr6_ssto_hap7	4928567	+	3860255	3860748	chr12	132349534	-	132021867	132022360	5505364
+30	66	66
+56	251	251
+90
+
+chain	10097	chr6_ssto_hap7	4928567	+	3816034	3816270	chr6	170899992	-	10896454	10896689	22596963
+52	115	114
+69
+
+chain	10009	chr6_ssto_hap7	4928567	+	1180658	1180788	chr7	158821424	-	7754727	7754857	22790797
+54	14	14
+62
+
+chain	9863	chr6_ssto_hap7	4928567	+	4074075	4074200	chr1	247249719	+	10410145	10410270	23122655
+62	11	11
+52
+
+chain	9833	chr6_ssto_hap7	4928567	+	1235234	1235338	chr6	170899992	-	141000130	141000234	23192992
+104
+
+chain	9829	chr6_ssto_hap7	4928567	+	3815276	3815381	chr2	242951149	-	95164602	95164707	23200543
+105
+
+chain	9703	chr6_ssto_hap7	4928567	+	4070399	4070911	chr2	242951149	-	75663422	75663931	23509887
+63	390	387
+59
+
+chain	9614	chr6_ssto_hap7	4928567	+	2657013	2657750	chr6	170899992	-	140934793	140935541	23727231
+66	613	624
+58
+
+chain	9528	chr6_ssto_hap7	4928567	+	1196742	1197179	chr6	170899992	+	29878108	29878543	23937753
+59	318	316
+60
+
+chain	9448	chr6_ssto_hap7	4928567	+	4048489	4048611	chr8	146274826	-	73050790	73050912	12492975
+122
+
+chain	9438	chr6_ssto_hap7	4928567	+	3910395	3911369	chr15	100338915	-	30464954	30465929	1082363
+106	42	42
+63	674	675
+89
+
+chain	9407	chr6_ssto_hap7	4928567	+	3856752	3857141	chr6	170899992	+	32635022	32635416	24217249
+67	271	276
+51
+
+chain	9325	chr6_ssto_hap7	4928567	+	3877913	3878051	chr5	180857866	-	41992384	41992522	24382359
+55	28	28
+55
+
+chain	9223	chr6_ssto_hap7	4928567	+	4072536	4072675	chr3	199501827	+	115197797	115197935	24583947
+54	29	28
+56
+
+chain	8918	chr6_ssto_hap7	4928567	+	3893253	3894424	chr9	140273252	-	41262761	41263931	1574906
+43	979	978
+149
+
+chain	8559	chr6_ssto_hap7	4928567	+	1185037	1185127	chr6	170899992	+	29901402	29901492	25589405
+90
+
+chain	8551	chr6_ssto_hap7	4928567	+	3829560	3829651	chrX	154913754	+	101188135	101188226	25594732
+91
+
+chain	8473	chr6_ssto_hap7	4928567	+	3956061	3956256	chr9	140273252	+	73803578	73803773	19960547
+18	127	127
+50
+
+chain	8431	chr6_ssto_hap7	4928567	+	4017811	4017899	chr6	170899992	-	67344251	67344339	25766641
+88
+
+chain	8320	chr6_ssto_hap7	4928567	+	4046958	4047055	chr3	199501827	+	112943953	112944050	15335436
+35	7	7
+55
+
+chain	8195	chr6_ssto_hap7	4928567	+	1189357	1189443	chr6	170899992	+	29906107	29906193	26123218
+86
+
+chain	7977	chr6_ssto_hap7	4928567	+	3854972	3855056	chr3	199501827	-	65120650	65120734	26447349
+84
+
+chain	7864	chr6_ssto_hap7	4928567	+	3956899	3957064	chr2	242951149	+	230690248	230690413	23687196
+65	86	86
+14
+
+chain	7746	chr6_ssto_hap7	4928567	+	4069960	4070399	chr1	247249719	+	17543299	17543737	25591741
+58	375	374
+6
+
+chain	7672	chr6_ssto_hap7	4928567	+	3894447	3895071	chr11	134452384	+	90348791	90349415	1473761
+74	253	253
+37	159	159
+101
+
+chain	7498	chr6_ssto_hap7	4928567	+	3878051	3879311	chr1	247249719	+	173341048	173342322	26722357
+5	1190	1204
+65
+
+chain	7331	chr6_ssto_hap7	4928567	+	4098258	4098335	chr16	88827254	-	31115279	31115356	27543534
+77
+
+chain	7232	chr6_ssto_hap7	4928567	+	3920814	3920891	chr6	170899992	+	32620027	32620104	27728494
+77
+
+chain	7168	chr6_ssto_hap7	4928567	+	4075613	4075689	chr1	247249719	-	67121697	67121773	27863207
+76
+
+chain	7154	chr6_ssto_hap7	4928567	+	3982483	3982643	chrX	154913754	+	57427313	57427473	11452806
+160
+
+chain	6975	chr6_ssto_hap7	4928567	+	1189014	1189086	chr6	170899992	+	29905761	29905833	28257011
+72
+
+chain	6949	chr6_ssto_hap7	4928567	+	3816604	3816677	chr8	146274826	-	83195506	83195579	28299872
+73
+
+chain	6859	chr6_ssto_hap7	4928567	+	3943496	3943569	chr6	170899992	+	32632193	32632266	28469740
+73
+
+chain	6788	chr6_ssto_hap7	4928567	+	4050963	4058824	chr6	170899992	+	32827127	32834907	28622110
+50	4319	3617
+61	2525	2695
+93	658	1109
+155
+
+chain	6731	chr6_ssto_hap7	4928567	+	1724741	1724812	chrX	154913754	+	77548522	77548593	28736593
+71
+
+chain	6723	chr6_ssto_hap7	4928567	+	3873757	3873829	chr6	170899992	+	32566306	32566378	28747170
+72
+
+chain	6686	chr6_ssto_hap7	4928567	+	1260394	1260465	chr10	135374737	-	59340781	59340852	28859379
+71
+
+chain	6665	chr6_ssto_hap7	4928567	+	3154699	3154769	chr19	63811651	-	18495515	18495585	1124045
+70
+
+chain	6650	chr6_ssto_hap7	4928567	+	3860923	3861067	chr11	134452384	-	10112929	10113073	19771550
+33	61	61
+50
+
+chain	6622	chr6_ssto_hap7	4928567	+	3829455	3829525	chr2	242951149	-	225543946	225544016	28987379
+70
+
+chain	6618	chr6_ssto_hap7	4928567	+	3895820	3896010	chr13	114142980	+	101977588	101977777	1936459
+53	63	62
+74
+
+chain	6613	chr6_ssto_hap7	4928567	+	3829110	3829180	chrX	154913754	+	79202976	79203046	29019460
+70
+
+chain	6584	chr6_ssto_hap7	4928567	+	3973978	3974052	chr18	76117153	-	4274607	4274681	4481992
+74
+
+chain	6521	chr6_ssto_hap7	4928567	+	3924035	3924103	chr6	170899992	+	32624377	32624445	29251175
+68
+
+chain	6513	chr6_ssto_hap7	4928567	+	4073124	4073193	chr12	132349534	+	47073126	47073195	29262428
+69
+
+chain	6459	chr6_ssto_hap7	4928567	+	2661634	2661703	chr6	170899992	+	31350859	31350928	29378029
+69
+
+chain	6412	chr6_ssto_hap7	4928567	+	3941116	3941183	chr5	180857866	-	156512753	156512820	29524988
+67
+
+chain	6368	chr6_ssto_hap7	4928567	+	2565193	2565285	chr6	170899992	-	132294381	132294479	20980272
+55	29	35
+8
+
+chain	6368	chr6_ssto_hap7	4928567	+	4074498	4074566	chr21	46944323	+	22987814	22987882	29601883
+68
+
+chain	6359	chr6_ssto_hap7	4928567	+	3988556	3988624	chr6	170899992	+	32661355	32661423	29618339
+68
+
+chain	6278	chr6_ssto_hap7	4928567	+	3866522	3866590	chr6	170899992	+	32559120	32559188	29828351
+68
+
+chain	6275	chr6_ssto_hap7	4928567	+	1183919	1183984	chr6	170899992	+	29900614	29900679	29842805
+65
+
+chain	6265	chr6_ssto_hap7	4928567	+	3855056	3855122	chr11	134452384	+	35675446	35675512	27404543
+66
+
+chain	6240	chr6_ssto_hap7	4928567	+	3829386	3829452	chr7	158821424	+	89136765	89136831	29917662
+66
+
+chain	6231	chr6_ssto_hap7	4928567	+	4071456	4071522	chr15	100338915	+	41279078	41279144	29959209
+66
+
+chain	6221	chr6_ssto_hap7	4928567	+	4068934	4068999	chr5	180857866	+	81769172	81769237	29991772
+65
+
+chain	6158	chr6_ssto_hap7	4928567	+	3881593	3881658	chr8	146274826	+	95080661	95080726	30127973
+65
+
+chain	6116	chr6_ssto_hap7	4928567	+	3859885	3859954	chr6	170899992	-	133628666	133628735	10717008
+69
+
+chain	6039	chr6_ssto_hap7	4928567	+	3985075	3985138	chr6	170899992	+	32660531	32660594	30469869
+63
+
+chain	5986	chr6_ssto_hap7	4928567	+	4018730	4018794	chr1	247249719	-	129681820	129681884	30582101
+64
+
+chain	5986	chr6_ssto_hap7	4928567	+	3949638	3949702	chr6	170899992	+	32601206	32601270	30582240
+64
+
+chain	5977	chr6_ssto_hap7	4928567	+	3861125	3861202	chrX	154913754	-	4338266	4338343	13813425
+77
+
+chain	5976	chr6_ssto_hap7	4928567	+	2664206	2664269	chr6	170899992	+	31358648	31358711	30614237
+63
+
+chain	5958	chr6_ssto_hap7	4928567	+	3891447	3891510	chr2	242951149	+	38038620	38038683	30678163
+63
+
+chain	5912	chr6_ssto_hap7	4928567	+	3875752	3875836	chr7	158821424	-	35299548	35299632	7605861
+84
+
+chain	5886	chr6_ssto_hap7	4928567	+	1725643	1725706	chr4	191273063	-	86591247	86591310	30840494
+63
+
+chain	5792	chr6_ssto_hap7	4928567	+	4018980	4019041	chr10	135374737	-	103149812	103149873	26755020
+61
+
+chain	5742	chr6_ssto_hap7	4928567	+	3983333	3983412	chr5	180857866	+	128901198	128901277	14868038
+79
+
+chain	5702	chr6_ssto_hap7	4928567	+	3954013	3954072	chr6	170899992	+	32605878	32605937	31357680
+59
+
+chain	5594	chr6_ssto_hap7	4928567	+	4069284	4069343	chr3	199501827	-	15131518	15131577	31663339
+59
+
+chain	5502	chr6_ssto_hap7	4928567	+	3813204	3813261	chr1	247249719	-	79348621	79348678	31943035
+57
+
+chain	5348	chr6_ssto_hap7	4928567	+	4071259	4071315	chr3	199501827	+	160253017	160253073	32406182
+56
+
+chain	5330	chr6_ssto_hap7	4928567	+	3915278	3915334	chr6	170899992	+	32568311	32568367	32437918
+56
+
+chain	5330	chr6_ssto_hap7	4928567	+	2561771	2561827	chr9	140273252	-	28635638	28635694	32438181
+56
+
+chain	5304	chr6_ssto_hap7	4928567	+	4073642	4073717	chr11	134452384	-	71399807	71399882	4131480
+75
+
+chain	5230	chr6_ssto_hap7	4928567	+	3820271	3820326	chrX	154913754	-	97033891	97033946	32742019
+55
+
+chain	5203	chr6_ssto_hap7	4928567	+	4076111	4076166	chr5	180857866	+	152654188	152654243	32834294
+55
+
+chain	5185	chr6_ssto_hap7	4928567	+	4075517	4075572	chr1	247249719	+	155449681	155449736	32900354
+55
+
+chain	5152	chr6_ssto_hap7	4928567	+	3860576	3860657	chr6	170899992	+	32435407	32435488	15981349
+81
+
+chain	5151	chr6_ssto_hap7	4928567	+	3860169	3860251	chr10	135374737	-	104426563	104426645	8666574
+82
+
+chain	5139	chr6_ssto_hap7	4928567	+	4018355	4018409	chr4	191273063	+	178947604	178947658	33042950
+54
+
+chain	5132	chr6_ssto_hap7	4928567	+	3876113	3876181	chr3	199501827	+	30016279	30016347	19245837
+68
+
+chain	5130	chr6_ssto_hap7	4928567	+	3954272	3954326	chr6	170899992	+	32549431	32549485	33050033
+54
+
+chain	5103	chr6_ssto_hap7	4928567	+	1182080	1182134	chr6	170899992	+	76955761	76955815	33170047
+54
+
+chain	5094	chr6_ssto_hap7	4928567	+	1724204	1724258	chr7	158821424	+	103641158	103641212	33192903
+54
+
+chain	5085	chr6_ssto_hap7	4928567	+	1328098	1328151	chr10	135374737	+	129836820	129836873	10408987
+53
+
+chain	5085	chr6_ssto_hap7	4928567	+	4092830	4092884	chrX	154913754	-	38541067	38541121	33235347
+54
+
+chain	5066	chr6_ssto_hap7	4928567	+	1229626	1229679	chr21	46944323	-	1867343	1867396	33290794
+53
+
+chain	5031	chr6_ssto_hap7	4928567	+	3830258	3830312	chr11	134452384	+	134387408	134387462	33376437
+54
+
+chain	5021	chr6_ssto_hap7	4928567	+	3819996	3820049	chr12	132349534	-	47076480	47076533	33436792
+53
+
+chain	5018	chr6_ssto_hap7	4928567	+	4073251	4073642	chr3	199501827	-	85266868	85267256	1587398
+65	97	89
+113	2	7
+114
+
+chain	5003	chr6_ssto_hap7	4928567	+	3830053	3830106	chr1	247249719	-	154726869	154726922	33499615
+53
+
+chain	5003	chr6_ssto_hap7	4928567	+	4072679	4072732	chr16	88827254	+	14169487	14169540	33499780
+53
+
+chain	4994	chr6_ssto_hap7	4928567	+	3891033	3891086	chr21	46944323	-	10747178	10747231	33543756
+53
+
+chain	4967	chr6_ssto_hap7	4928567	+	3832675	3832728	chr6	170899992	+	32558903	32558956	33617414
+53
+
+chain	4965	chr6_ssto_hap7	4928567	+	2731195	2731249	chr6	170899992	+	31505531	31505585	32711054
+54
+
+chain	4948	chr6_ssto_hap7	4928567	+	4074823	4074875	chr4	191273063	-	118568999	118569051	33679640
+52
+
+chain	4921	chr6_ssto_hap7	4928567	+	3956534	3956586	chr1	247249719	+	94607233	94607285	33754873
+52
+
+chain	4903	chr6_ssto_hap7	4928567	+	3854886	3854938	chr7	158821424	+	104157517	104157569	33851522
+52
+
+chain	4893	chr6_ssto_hap7	4928567	+	3982754	3982817	chr22	49691432	+	37111300	37111363	16902914
+63
+
+chain	4873	chr6_ssto_hap7	4928567	+	3911814	3911922	chr18	76117153	-	50730715	50730823	6267534
+108
+
+chain	4830	chr6_ssto_hap7	4928567	+	3900138	3900189	chr6	170899992	+	32631274	32631325	34086153
+51
+
+chain	4830	chr6_ssto_hap7	4928567	+	3839078	3839129	chr7	158821424	+	82104686	82104737	34087626
+51
+
+chain	4829	chr6_ssto_hap7	4928567	+	1241391	1241441	chr6	170899992	+	29800923	29800973	34088055
+50
+
+chain	4821	chr6_ssto_hap7	4928567	+	2662906	2662957	chr3	199501827	-	33183122	33183173	34119642
+51
+
+chain	4775	chr6_ssto_hap7	4928567	+	2648374	2648424	chr6	170899992	+	31537299	31537349	34295026
+50
+
+chain	4758	chr6_ssto_hap7	4928567	+	4069230	4069281	chr12	132349534	+	47071874	47071925	34323771
+51
+
+chain	4757	chr6_ssto_hap7	4928567	+	3952724	3952774	chr6	170899992	+	32548169	32548219	34341756
+50
+
+chain	4730	chr6_ssto_hap7	4928567	+	3994932	3994982	chrX	154913754	+	47978704	47978754	34444069
+50
+
+chain	4716	chr6_ssto_hap7	4928567	+	4048342	4048408	chr3	199501827	-	34165769	34165835	12625077
+66
+
+chain	4703	chr6_ssto_hap7	4928567	+	2662371	2662421	chr19	63811651	+	65370	65420	34557514
+50
+
+chain	4694	chr6_ssto_hap7	4928567	+	4060651	4060701	chr6	170899992	+	32836714	32836764	34581664
+50
+
+chain	4679	chr6_ssto_hap7	4928567	+	3906823	3908410	chr10	135374737	+	93253585	93255039	1065758
+52	974	846
+68	463	458
+30
+
+chain	4568	chr6_ssto_hap7	4928567	+	1261137	1261199	chrX	154913754	-	132036612	132036674	19096001
+62
+
+chain	4552	chr6_ssto_hap7	4928567	+	3860527	3860576	chr15	100338915	-	42450883	42450932	16059710
+49
+
+chain	4547	chr6_ssto_hap7	4928567	+	2556944	2560436	chr12	132349534	+	103307685	103311177	2570686
+99	961	960
+40	481	480
+76	473	472
+44	1256	1259
+62
+
+chain	4462	chr6_ssto_hap7	4928567	+	2729793	2731102	chr13	114142980	-	41461751	41462033	3580573
+3	13	0
+61	0	13
+33	683	3
+44	2	0
+7	414	58
+20	0	11
+29
+
+chain	4428	chr6_ssto_hap7	4928567	+	4094024	4094075	chr14	106368585	+	31457415	31457466	15616811
+28	1	1
+22
+
+chain	4397	chr6_ssto_hap7	4928567	+	4073349	4073413	chr11	134452384	-	124082096	124082160	4425866
+64
+
+chain	4392	chr6_ssto_hap7	4928567	+	1194713	1194772	chr7	158821424	-	126060926	126060985	9905441
+59
+
+chain	4342	chr6_ssto_hap7	4928567	+	4094294	4094398	chr5	180857866	-	116975574	116975678	23231318
+23	58	58
+23
+
+chain	4295	chr6_ssto_hap7	4928567	+	2556338	2556392	chr13	114142980	+	40947099	40947153	23509763
+54
+
+chain	4294	chr6_ssto_hap7	4928567	+	1260590	1260636	chr12	132349534	-	115571292	115571338	21618938
+46
+
+chain	4197	chr6_ssto_hap7	4928567	+	4047303	4047429	chr5	180857866	+	138042715	138042841	4048116
+126
+
+chain	4074	chr6_ssto_hap7	4928567	+	3895452	3896721	chr2	242951149	-	163460907	163462170	1597366
+57	1112	1106
+100
+
+chain	4047	chr6_ssto_hap7	4928567	+	1227212	1227254	chr6	170899992	+	30567064	30567106	34943638
+42
+
+chain	4028	chr6_ssto_hap7	4928567	+	2557654	2557724	chr8	146274826	-	45767632	45767702	6509640
+70
+
+chain	3802	chr6_ssto_hap7	4928567	+	3983413	3983485	chr9	140273252	-	109331781	109331853	15187387
+72
+
+chain	3788	chr6_ssto_hap7	4928567	+	3983607	3983647	chr5	180857866	+	163886600	163886640	18371448
+40
+
+chain	3783	chr6_ssto_hap7	4928567	+	3861067	3861107	chr8	146274826	+	47663219	47663259	26644949
+40
+
+chain	3780	chr6_ssto_hap7	4928567	+	1260148	1260195	chr3	199501827	+	129107515	129107562	25050682
+47
+
+chain	3771	chr6_ssto_hap7	4928567	+	3910850	3910969	chr11	134452384	+	91939775	91939894	1347783
+119
+
+chain	3720	chr6_ssto_hap7	4928567	+	4076654	4076693	chr5	180857866	-	28755460	28755499	35075689
+39
+
+chain	3674	chr6_ssto_hap7	4928567	+	1327942	1328098	chr13	114142980	-	16623521	16623677	9556113
+156
+
+chain	3526	chr6_ssto_hap7	4928567	+	1233321	1233358	chr3	199501827	+	179624737	179624774	21949411
+37
+
+chain	3523	chr6_ssto_hap7	4928567	+	3861357	3861409	chrX	154913754	-	71079157	71079209	23377911
+52
+
+chain	3519	chr6_ssto_hap7	4928567	+	3860886	3860923	chr10	135374737	+	82581588	82581625	28921115
+37
+
+chain	3516	chr6_ssto_hap7	4928567	+	3983122	3983159	chr14	106368585	+	44215304	44215341	21050502
+37
+
+chain	3503	chr6_ssto_hap7	4928567	+	3955956	3955993	chrX	154913754	+	6516305	6516342	20940822
+37
+
+chain	3500	chr6_ssto_hap7	4928567	+	3911536	3911575	chr13	114142980	+	94757263	94757302	7214953
+39
+
+chain	3483	chr6_ssto_hap7	4928567	+	4093962	4094024	chr18	76117153	-	13046880	13046942	11655771
+62
+
+chain	3478	chr6_ssto_hap7	4928567	+	3815148	3815213	chr18	76117153	-	71040520	71040585	23549077
+65
+
+chain	3458	chr6_ssto_hap7	4928567	+	3983209	3983294	chr8	146274826	-	67597789	67597874	12879815
+85
+
+chain	3397	chr6_ssto_hap7	4928567	+	4048453	4048489	chr17	78774742	-	56852494	56852530	15165556
+36
+
+chain	3368	chr6_ssto_hap7	4928567	+	3812594	3812653	chr10	135374737	-	122033518	122033577	24304367
+59
+
+chain	3327	chr6_ssto_hap7	4928567	+	1327907	1327942	chr2	242951149	-	102468165	102468200	11981936
+35
+
+chain	3310	chr6_ssto_hap7	4928567	+	3973883	3974608	chr4	191273063	+	16003477	16004520	2930244
+28	656	974
+41
+
+chain	3301	chr6_ssto_hap7	4928567	+	2558188	2558238	chr3	199501827	+	116399611	116399661	15972636
+50
+
+chain	3279	chr6_ssto_hap7	4928567	+	2675861	2675917	chrX	154913754	+	134744376	134744432	23888160
+56
+
+chain	3275	chr6_ssto_hap7	4928567	+	1175210	1175245	chr6	170899992	+	29990315	29990350	35226054
+35
+
+chain	3266	chr6_ssto_hap7	4928567	+	3955123	3955180	chr3	199501827	-	22333077	22333134	22107567
+57
+
+chain	3198	chr6_ssto_hap7	4928567	+	3983298	3983333	chr9	140273252	-	16426927	16426962	15083539
+35
+
+chain	3194	chr6_ssto_hap7	4928567	+	3955248	3955303	chr12	132349534	+	117591668	117591723	17819023
+55
+
+chain	3180	chr6_ssto_hap7	4928567	+	3983045	3983105	chr5	180857866	-	166783333	166783393	16589034
+60
+
+chain	3166	chr6_ssto_hap7	4928567	+	3843125	3843159	chr4	191273063	+	105842978	105843012	35258022
+34
+
+chain	3121	chr6_ssto_hap7	4928567	+	3896015	3896048	chr12	132349534	+	40503685	40503718	34691345
+33
+
+chain	3047	chr6_ssto_hap7	4928567	+	3816677	3816709	chr10	135374737	-	66254665	66254697	30311304
+32
+
+chain	3032	chr6_ssto_hap7	4928567	+	4105261	4105293	chr8	146274826	-	64365138	64365170	21873611
+32
+
+chain	3023	chr6_ssto_hap7	4928567	+	4076166	4076198	chr7	158821424	-	25244743	25244775	33809340
+32
+
+chain	3020	chr6_ssto_hap7	4928567	+	3860793	3860825	chr14	106368585	-	87125958	87125990	25956389
+32
+
+chain	3015	chr6_ssto_hap7	4928567	+	3983163	3983195	chr3	199501827	+	120260171	120260203	17223389
+32
+
+chain	2990	chr6_ssto_hap7	4928567	+	3896241	3896359	chr13	114142980	+	83437980	83438098	1629523
+118
+
+chain	2988	chr6_ssto_hap7	4928567	+	3982643	3982709	chr1	247249719	+	240403964	240404030	13152492
+66
+
+chain	2975	chr6_ssto_hap7	4928567	+	2564513	2564549	chr3	199501827	-	94209737	94209773	24799761
+36
+
+chain	2970	chr6_ssto_hap7	4928567	+	4070462	4070493	chr3	199501827	-	179622086	179622117	31254285
+31
+
+chain	2964	chr6_ssto_hap7	4928567	+	3891798	3891851	chr5	180857866	+	101832950	101833003	21914612
+53
+
+chain	2888	chr6_ssto_hap7	4928567	+	4065158	4065188	chr19	63811651	-	5427097	5427127	31160360
+30
+
+chain	2845	chr6_ssto_hap7	4928567	+	2556914	2556944	chr3	199501827	-	158108130	158108160	26771676
+30
+
+chain	2753	chr6_ssto_hap7	4928567	+	1233507	1233566	chr12	132349534	+	50414483	50414542	22637631
+59
+
+chain	2740	chr6_ssto_hap7	4928567	+	3892104	3892166	chr5	180857866	+	121612373	121612435	20400021
+62
+
+chain	2698	chr6_ssto_hap7	4928567	+	3907323	3908062	chr7	158821424	+	92810174	92810913	1211789
+52	649	649
+38
+
+chain	2671	chr6_ssto_hap7	4928567	+	2565133	2565192	chr9	140273252	-	60326471	60326530	21074057
+59
+
+chain	2634	chr6_ssto_hap7	4928567	+	3829525	3829553	chr11	134452384	-	52779952	52779980	32661482
+28
+
+chain	2606	chr6_ssto_hap7	4928567	+	4048612	4048640	chr10	135374737	-	125708744	125708772	21482387
+28
+
+chain	2596	chr6_ssto_hap7	4928567	+	3956994	3957021	chr3	199501827	+	56590732	56590759	32896514
+27
+
+chain	2579	chr6_ssto_hap7	4928567	+	2557143	2557298	chr6	170899992	-	49784063	49784218	3056426
+155
+
+chain	2576	chr6_ssto_hap7	4928567	+	3895108	3895185	chr6	170899992	+	169119449	169119526	1708984
+77
+
+chain	2565	chr6_ssto_hap7	4928567	+	3829029	3829056	chr12	132349534	-	5427347	5427374	35416045
+27
+
+chain	2538	chr6_ssto_hap7	4928567	+	4095308	4095335	chrX	154913754	-	17724530	17724557	35428225
+27
+
+chain	2483	chr6_ssto_hap7	4928567	+	2785408	2785434	chr6	170899992	+	31465639	31465665	7427670
+26
+
+chain	2481	chr6_ssto_hap7	4928567	+	2556543	2556631	chr3	199501827	+	50931029	50931117	15954243
+88
+
+chain	2458	chr6_ssto_hap7	4928567	+	3955303	3955329	chr2	242951149	+	162131406	162131432	29918335
+26
+
+chain	2454	chr6_ssto_hap7	4928567	+	4073316	4073349	chr4	191273063	+	122379593	122379626	9286528
+33
+
+chain	2452	chr6_ssto_hap7	4928567	+	3955573	3955623	chr15	100338915	-	6219909	6219959	18667645
+50
+
+chain	2424	chr6_ssto_hap7	4928567	+	235781	235807	chr6	170899992	-	141897118	141897144	13814892
+26
+
+chain	2387	chr6_ssto_hap7	4928567	+	3979548	3981344	chr6	170899992	+	32629287	32631086	11569193
+64	1054	1061
+59	8	8
+33	512	508
+66
+
+chain	2367	chr6_ssto_hap7	4928567	+	3861203	3861228	chr5	180857866	-	25449026	25449051	27433905
+25
+
+chain	2364	chr6_ssto_hap7	4928567	+	3896486	3896567	chr12	132349534	-	118913454	118913535	1891796
+81
+
+chain	2348	chr6_ssto_hap7	4928567	+	2555491	2555546	chr7	158821424	+	35337254	35337309	23750585
+55
+
+chain	2343	chr6_ssto_hap7	4928567	+	3895509	3895593	chr5	180857866	+	145974017	145974101	2481028
+84
+
+chain	2329	chr6_ssto_hap7	4928567	+	3908230	3908283	chr14	106368585	-	66110025	66110078	1963434
+53
+
+chain	2303	chr6_ssto_hap7	4928567	+	3910235	3910298	chr9	140273252	+	106520457	106520520	13548409
+63
+
+chain	2290	chr6_ssto_hap7	4928567	+	1194888	1194945	chr1	247249719	+	222604152	222604209	12152481
+57
+
+chain	2264	chr6_ssto_hap7	4928567	+	4094107	4094165	chr6	170899992	-	103114933	103114991	11782722
+58
+
+chain	2239	chr6_ssto_hap7	4928567	+	3859859	3859885	chr10	135374737	-	31460228	31460254	11102876
+26
+
+chain	2227	chr6_ssto_hap7	4928567	+	3896386	3896483	chr3	199501827	+	28081389	28081486	2734455
+97
+
+chain	2194	chr6_ssto_hap7	4928567	+	1194673	1194713	chrX	154913754	-	101365357	101365397	11073774
+40
+
+chain	2194	chr6_ssto_hap7	4928567	+	3911725	3911783	chr20	62435964	+	16923180	16923238	16666656
+58
+
+chain	2183	chr6_ssto_hap7	4928567	+	3982709	3982750	chrX	154913754	+	100681659	100681700	16994110
+41
+
+chain	2146	chr6_ssto_hap7	4928567	+	1180871	1180932	chr12	132349534	+	104221177	104221238	23825292
+61
+
+chain	2099	chr6_ssto_hap7	4928567	+	1233299	1233321	chr8	146274826	+	94956096	94956118	22553602
+22
+
+chain	2073	chr6_ssto_hap7	4928567	+	3956611	3956663	chr12	132349534	-	95011302	95011354	24299162
+52
+
+chain	2037	chr6_ssto_hap7	4928567	+	3907120	3907174	chr16	88827254	+	61739431	61739485	9206264
+54
+
+chain	1971	chr6_ssto_hap7	4928567	+	1260864	1260916	chr6	170899992	-	43699516	43699568	21479541
+52
+
+chain	1962	chr6_ssto_hap7	4928567	+	3860956	3861008	chr2	242951149	-	71012239	71012291	15891024
+52
+
+chain	1959	chr6_ssto_hap7	4928567	+	4047151	4047237	chr9	140273252	+	88182498	88182584	7672012
+86
+
+chain	1911	chr6_ssto_hap7	4928567	+	4094317	4094375	chr3	199501827	+	41781958	41782016	21488153
+58
+
+chain	1911	chr6_ssto_hap7	4928567	+	1260320	1260381	chr10	135374737	-	106297874	106297935	24479059
+61
+
+chain	1874	chr6_ssto_hap7	4928567	+	2557724	2557753	chr7	158821424	+	91452357	91452386	16326510
+29
+
+chain	1780	chr6_ssto_hap7	4928567	+	3910029	3910068	chr14	106368585	-	82341010	82341049	3087250
+39
+
+chain	1777	chr6_ssto_hap7	4928567	+	2675677	2675732	chr16	88827254	+	88260921	88260976	23365193
+55
+
+chain	1697	chr6_ssto_hap7	4928567	+	2559283	2559636	chr4	191273063	-	69388564	69388918	2817550
+72	250	251
+31
+
+chain	1664	chr6_ssto_hap7	4928567	+	3911192	3911255	chr5	180857866	-	81785123	81785186	3114861
+63
+
+chain	1653	chr6_ssto_hap7	4928567	+	2560066	2560131	chr7	158821424	-	148280259	148280324	6636035
+65
+
+chain	1644	chr6_ssto_hap7	4928567	+	3910172	3910234	chrX	154913754	-	124216188	124216250	1928091
+62
+
+chain	1640	chr6_ssto_hap7	4928567	+	3906670	3906720	chr3	199501827	-	110018776	110018826	1171918
+50
+
+chain	1620	chr6_ssto_hap7	4928567	+	4048655	4048716	chr11	134452384	-	43500788	43500849	9791170
+61
+
+chain	1606	chr6_ssto_hap7	4928567	+	3837795	3837854	chr4	191273063	-	166421863	166421922	24717464
+59
+
+chain	1605	chr6_ssto_hap7	4928567	+	3875836	3875881	chr1	247249719	-	200018115	200018160	9990642
+45
+
+chain	1600	chr6_ssto_hap7	4928567	+	3957021	3957050	chr13	114142980	-	18785120	18785149	24380544
+29
+
+chain	1599	chr6_ssto_hap7	4928567	+	3955003	3955066	chr8	146274826	+	126278291	126278354	19925896
+63
+
+chain	1576	chr6_ssto_hap7	4928567	+	3910706	3910761	chr3	199501827	+	169002538	169002593	7318777
+55
+
+chain	1576	chr6_ssto_hap7	4928567	+	3876008	3876074	chr21	46944323	+	28977016	28977082	11761970
+66
+
+chain	1567	chr6_ssto_hap7	4928567	+	3909838	3909895	chr12	132349534	+	31210742	31210799	2955344
+57
+
+chain	1566	chr6_ssto_hap7	4928567	+	3893961	3894004	chr5	180857866	-	2394787	2394830	2003043
+43
+
+chain	1548	chr6_ssto_hap7	4928567	+	2556653	2556768	chr2	242951149	-	193553846	193553961	3498208
+115
+
+chain	1539	chr6_ssto_hap7	4928567	+	3891177	3891234	chr1	247249719	-	78251618	78251675	24446661
+57
+
+chain	1535	chr6_ssto_hap7	4928567	+	3911107	3911157	chr1	247249719	-	72372939	72372989	9173856
+50
+
+chain	1534	chr6_ssto_hap7	4928567	+	4094211	4094262	chrX	154913754	-	868272	868323	12957412
+51
+
+chain	1513	chr6_ssto_hap7	4928567	+	3906987	3907031	chr5	180857866	-	10434692	10434736	1299581
+44
+
+chain	1493	chr6_ssto_hap7	4928567	+	2556789	2556856	chr13	114142980	+	99769649	99769716	4762882
+67
+
+chain	1490	chr6_ssto_hap7	4928567	+	3814865	3814929	chr10	135374737	-	44217075	44217139	22840138
+64
+
+chain	1482	chr6_ssto_hap7	4928567	+	3909632	3909684	chr11	134452384	+	100031701	100031753	1214591
+52
+
+chain	1453	chr6_ssto_hap7	4928567	+	1327842	1327906	chr7	158821424	+	38479547	38479611	8534629
+64
+
+chain	1406	chr6_ssto_hap7	4928567	+	3909452	3909505	chr2	242951149	-	92980714	92980767	1301647
+53
+
+chain	1403	chr6_ssto_hap7	4928567	+	3860825	3860881	chr2	242951149	+	213976883	213976939	18753925
+56
+
+chain	1392	chr6_ssto_hap7	4928567	+	3955543	3955573	chr3	199501827	-	51819316	51819346	23522770
+30
+
+chain	1378	chr6_ssto_hap7	4928567	+	2556204	2556330	chr9	140273252	+	106017756	106017882	9913210
+126
+
+chain	1352	chr6_ssto_hap7	4928567	+	4047237	4047285	chr4	191273063	-	68812874	68812922	21085894
+48
+
+chain	1344	chr6_ssto_hap7	4928567	+	3893519	3893548	chr4	191273063	+	75333241	75333270	1578953
+29
+
+chain	1342	chr6_ssto_hap7	4928567	+	2557427	2557573	chr1	247249719	+	169787922	169788068	14592994
+146
+
+chain	1328	chr6_ssto_hap7	4928567	+	3895210	3895266	chr1	247249719	-	722390	722446	2029679
+56
+
+chain	1323	chr6_ssto_hap7	4928567	+	3815012	3815074	chrY	57772954	+	15217299	15217361	24773594
+62
+
+chain	1317	chr6_ssto_hap7	4928567	+	2559037	2559074	chr2	242951149	-	160628689	160628726	4907065
+37
+
+chain	1310	chr6_ssto_hap7	4928567	+	3859653	3859705	chrX	154913754	+	62583131	62583183	22867194
+52
+
+chain	1305	chr6_ssto_hap7	4928567	+	1233633	1233684	chr10	135374737	-	7751536	7751587	24635136
+51
+
+chain	1291	chr6_ssto_hap7	4928567	+	3908834	3908875	chr4	191273063	-	115939442	115939483	1333239
+41
+
+chain	1287	chr6_ssto_hap7	4928567	+	3909608	3909632	chr5	180857866	+	103723323	103723347	7290377
+24
+
+chain	1280	chr6_ssto_hap7	4928567	+	3895766	3895816	chr8	146274826	+	51746323	51746373	2903032
+50
+
+chain	1274	chr6_ssto_hap7	4928567	+	2557298	2557339	chrX	154913754	-	130647843	130647884	4467918
+41
+
+chain	1257	chr6_ssto_hap7	4928567	+	2558435	2558509	chr10	135374737	+	60854508	60854582	4145356
+74
+
+chain	1250	chr6_ssto_hap7	4928567	+	4094075	4094107	chr12	132349534	+	74093056	74093088	12787103
+32
+
+chain	1238	chr6_ssto_hap7	4928567	+	1229366	1229425	chr8	146274826	-	84904941	84905000	22834116
+59
+
+chain	1235	chr6_ssto_hap7	4928567	+	3861228	3861334	chr15	100338915	-	22701786	22701892	11814602
+106
+
+chain	1193	chr6_ssto_hap7	4928567	+	3906339	3906392	chr6	170899992	+	117066655	117066708	1525034
+53
+
+chain	1176	chr6_ssto_hap7	4928567	+	3909895	3909925	chr8	146274826	-	24546743	24546773	1399929
+30
+
+chain	1144	chr6_ssto_hap7	4928567	+	3892335	3892388	chrX	154913754	-	80891112	80891165	18462511
+53
+
+chain	1143	chr6_ssto_hap7	4928567	+	3876074	3876097	chr4	191273063	-	150305688	150305711	12943108
+23
+
+chain	1107	chr6_ssto_hap7	4928567	+	3890850	3890949	chr11	134452384	-	72766127	72766226	17974034
+99
+
+chain	1099	chr6_ssto_hap7	4928567	+	2557592	2557651	chr14	106368585	+	52836717	52836776	3332437
+59
+
+chain	1093	chr6_ssto_hap7	4928567	+	2560006	2560065	chr11	134452384	+	32923634	32923693	3048042
+59
+
+chain	1080	chr6_ssto_hap7	4928567	+	4073853	4073903	chr19	63811651	-	3657843	3657893	23666214
+50
+
+chain	1031	chr6_ssto_hap7	4928567	+	3910512	3910543	chr8	146274826	+	76357761	76357792	1122615
+31
+
+chain	1019	chr6_ssto_hap7	4928567	+	3956446	3956499	chr2	242951149	-	47303049	47303102	21955737
+53
+
+chain	1013	chr6_ssto_hap7	4928567	+	3876829	3876895	chr5	180857866	-	104615327	104615393	22955784
+66
+
+chain	1003	chr6_ssto_hap7	4928567	+	3699456	3699487	chr2	242951149	-	44758448	44758479	2126762
+31
+
+chain	980	chr6_ssto_hap7	4928567	+	1260084	1260145	chrX	154913754	-	382349	382410	22927465
+61
+
+chain	926	chr6_ssto_hap7	4928567	+	3896721	3896750	chr5	180857866	-	112926632	112926661	13782082
+29
+
+chain	919	chr6_ssto_hap7	4928567	+	2560983	2561043	chr4	191273063	+	44807134	44807194	22381059
+60
+
+chain	917	chr6_ssto_hap7	4928567	+	3906720	3906770	chr1	247249719	-	157593440	157593490	1436049
+50
+
+chain	909	chr6_ssto_hap7	4928567	+	3909310	3909343	chr3	199501827	+	106500697	106500730	2326646
+33
+
+chain	904	chr6_ssto_hap7	4928567	+	2560317	2560347	chr7	158821424	+	107644178	107644208	22181612
+30
+
+chain	884	chr6_ssto_hap7	4928567	+	2559977	2560006	chr1	247249719	-	197271642	197271671	12501549
+29
+
+chain	879	chr6_ssto_hap7	4928567	+	3814083	3814143	chr2	242951149	+	8957980	8958040	24745704
+60
+
+chain	871	chr6_ssto_hap7	4928567	+	3908354	3908380	chr5	180857866	-	86285693	86285719	1813846
+26
+
+chain	854	chr6_ssto_hap7	4928567	+	2559716	2559766	chr4	191273063	+	5547185	5547235	3968222
+50
+
+chain	842	chr6_ssto_hap7	4928567	+	3909997	3910029	chr12	132349534	+	65262069	65262101	1358106
+32
+
+chain	834	chr6_ssto_hap7	4928567	+	2558357	2558414	chr5	180857866	-	149870489	149870546	4554917
+57
+
+chain	818	chr6_ssto_hap7	4928567	+	3895593	3895627	chr1	247249719	-	137161630	137161664	3053056
+34
+
+chain	805	chr6_ssto_hap7	4928567	+	4046900	4046958	chr3	199501827	-	135889823	135889881	13048217
+58
+
+chain	792	chr6_ssto_hap7	4928567	+	2556476	2556543	chrX	154913754	-	448312	448379	10955677
+67
+
+chain	788	chr6_ssto_hap7	4928567	+	2557050	2557102	chr9	140273252	-	129331917	129331969	3471854
+52
+
+chain	766	chr6_ssto_hap7	4928567	+	3895074	3895108	chrX	154913754	-	143143280	143143314	1988289
+34
+
+chain	764	chr6_ssto_hap7	4928567	+	3911494	3911520	chr5	180857866	-	28611213	28611239	1520834
+26
+
+chain	760	chr6_ssto_hap7	4928567	+	3891913	3891984	chr7	158821424	+	132658309	132658380	7665022
+71
+
+chain	760	chr6_ssto_hap7	4928567	+	2558688	2558747	chr12	132349534	+	56700130	56700189	25330837
+59
+
+chain	751	chr6_ssto_hap7	4928567	+	3908062	3908116	chrX	154913754	-	27278752	27278806	23595528
+54
+
+chain	750	chr6_ssto_hap7	4928567	+	2558241	2558292	chr3	199501827	-	21470788	21470839	4018903
+51
+
+chain	747	chr6_ssto_hap7	4928567	+	1195376	1195440	chr12	132349534	+	55464534	55464598	20643872
+64
+
+chain	741	chr6_ssto_hap7	4928567	+	2558773	2558825	chr10	135374737	+	51611354	51611406	20535555
+52
+
+chain	725	chr6_ssto_hap7	4928567	+	2556857	2556911	chr2	242951149	+	129418481	129418535	15959344
+54
+
+chain	718	chr6_ssto_hap7	4928567	+	3906470	3906504	chr13	114142980	+	74008819	74008853	1439498
+34
+
+chain	683	chr6_ssto_hap7	4928567	+	4094187	4094211	chr12	132349534	-	78902290	78902314	13929920
+24
+
+chain	678	chr6_ssto_hap7	4928567	+	2557391	2557427	chr4	191273063	+	139055274	139055310	16166693
+36
+
+chain	667	chr6_ssto_hap7	4928567	+	2560843	2560917	chr5	180857866	-	57070089	57070163	4646233
+74
+
+chain	646	chr6_ssto_hap7	4928567	+	2558159	2558188	chr1	247249719	-	41799280	41799309	22422429
+29
+
+chain	632	chr6_ssto_hap7	4928567	+	3892229	3892286	chr5	180857866	+	40599364	40599421	14690520
+57
+
+chain	624	chr6_ssto_hap7	4928567	+	2558292	2558324	chr9	140273252	+	222455	222487	4174075
+32
+
+chain	617	chr6_ssto_hap7	4928567	+	3894943	3894969	chr9	140273252	-	67269827	67269853	2340131
+26
+
+chain	612	chr6_ssto_hap7	4928567	+	1195270	1195296	chr2	242951149	+	158875930	158875956	11360379
+26
+
+chain	602	chr6_ssto_hap7	4928567	+	3896359	3896385	chr2	242951149	+	96414192	96414218	2435436
+26
+
+chain	600	chr6_ssto_hap7	4928567	+	2560187	2560242	chr4	191273063	-	105845249	105845304	24497060
+55
+
+chain	588	chr6_ssto_hap7	4928567	+	3911575	3911637	chr9	140273252	+	26038500	26038562	6400007
+62
+
+chain	588	chr6_ssto_hap7	4928567	+	3911157	3911192	chr2	242951149	-	186209425	186209460	7977621
+35
+
+chain	537	chr6_ssto_hap7	4928567	+	3890472	3890554	chr20	62435964	+	39823688	39823770	23049583
+82
+
+chain	533	chr6_ssto_hap7	4928567	+	2560261	2560317	chr7	158821424	+	35749861	35749917	7559420
+56
+
+chain	506	chr6_ssto_hap7	4928567	+	1194845	1194871	chr17	78774742	+	16156064	16156090	14435127
+26
+
+chain	492	chr6_ssto_hap7	4928567	+	2561299	2561367	chr13	114142980	-	65973713	65973781	6503172
+68
+
+chain	482	chr6_ssto_hap7	4928567	+	3909557	3909588	chr4	191273063	+	109100594	109100625	25171244
+31
+
+chain	475	chr6_ssto_hap7	4928567	+	3910969	3910996	chr2	242951149	+	170022712	170022739	3066592
+27
+
+chain	474	chr6_ssto_hap7	4928567	+	2555667	2555728	chr3	199501827	+	34096453	34096514	5935624
+61
+
+chain	454	chr6_ssto_hap7	4928567	+	3783318	3783345	chr7	158821424	+	43780404	43780431	3672784
+27
+
+chain	453	chr6_ssto_hap7	4928567	+	2558825	2558856	chr12	132349534	+	9890466	9890497	23880886
+31
+
+chain	435	chr6_ssto_hap7	4928567	+	3813557	3813608	chrX	154913754	+	70635923	70635974	25591729
+51
+
+chain	433	chr6_ssto_hap7	4928567	+	3954592	3954642	chr12	132349534	+	80047789	80047839	27634718
+50
+
+chain	421	chr6_ssto_hap7	4928567	+	3906299	3906339	chr6	170899992	-	100687874	100687914	2311527
+40
+
+chain	415	chr6_ssto_hap7	4928567	+	4047055	4047086	chr2	242951149	-	64586829	64586860	16220906
+31
+
+chain	395	chr6_ssto_hap7	4928567	+	3877505	3877535	chr2	242951149	-	195767137	195767167	24444969
+30
+
+chain	389	chr6_ssto_hap7	4928567	+	2560634	2560691	chr4	191273063	-	135903806	135903863	10538130
+57
+
+chain	364	chr6_ssto_hap7	4928567	+	3892286	3892319	chr2	242951149	+	18209140	18209173	14942259
+33
+
+chain	312	chr6_ssto_hap7	4928567	+	2559887	2559937	chr6	170899992	+	118230705	118230755	8173852
+50
+
+chain	289	chr6_ssto_hap7	4928567	+	2561063	2561118	chr9	140273252	-	49339912	49339967	9048484
+55
+
+chain	276	chr6_ssto_hap7	4928567	+	3878310	3878371	chr4	191273063	-	5378508	5378569	28215176
+61
+
+chain	273	chr6_ssto_hap7	4928567	+	2560131	2560171	chr10	135374737	+	69013223	69013263	15789387
+40
+
+chain	167	chr6_ssto_hap7	4928567	+	3908301	3908353	chr3	199501827	+	163583012	163583064	2366456
+52
+
+chain	14618488008	7	159138663	+	10238	159128663	chr7	158821424	+	102995	158821424	7
+973	0	5
+3912	2	0
+1234	0	4
+51	6	0
+70	1	1
+24	0	1
+147	0	8
+12	1	170
+47	1	1
+246	6	0
+99	4	4
+807	0	3
+2546	0	63
+44	0	2527
+1373	1	0
+2109	456	0
+1153	1	0
+791	1	1
+49	1	0
+4175	18	26
+4318	11	11
+514	0	12
+2511	1	0
+1697	6	6
+192827	278557	150000
+5682433	40	39
+42007910	35970	40000
+2048	3	3
+2320	16	7
+17699	4	0
+5248	0	4
+2088411	1	1
+47	1	1
+4565	1	0
+7116	1	0
+2706	43050	40000
+6577293	13552	50000
+1052855	3000000	3000000
+256182	416507	50000
+190137	50000	50000
+5722629	1	0
+23	1	1
+239	1	1
+59	2	2
+138	1	1
+34	1	1
+206	3	1
+18	0	1
+410	1	1
+72	1	1
+199	1	1
+62	5	5
+120	0	1
+468	1	1
+32	1	1
+264	1	1
+23	1	1
+1459	4	4
+107	1	1
+42	0	1
+14	1	1
+201	1	1
+46	1	1
+268	20	20
+303	1	2
+866	4	0
+76	3	3
+63	1	1
+74	0	1
+25	1	1
+66	1	1
+34	2	0
+180	36	35
+93	1	1
+41	1	1
+70	1	1
+49	1	1
+63	1	1
+57	1	1
+383	1	1
+133	1	1
+87	1	1
+38	4	4
+50	1	0
+46	6	5
+136	11	11
+200	1	1
+64	5	18
+263	1	1
+32	3	3
+152	16	16
+567	0	1
+322	0	3
+1258	1	0
+504	0	4
+1142	10	11
+537	12	12
+1418	1	1
+47	1	0
+164	7	7
+113	0	5
+59	2	2
+72	1	1
+20	1	1
+380	3	3
+41	0	3
+5	2	2
+921	1	1
+34	1	1
+1607	2	2
+73	0	66
+45	0	14
+169	1	1
+53	1	1
+3195	1	1
+23	1	1
+2115	14	0
+9872	0	1
+1204	13	13
+416	0	1
+2298	0	319
+6918	10	0
+184	0	24
+2932	0	4
+1394	12	0
+1853	0	5
+3442	1	0
+469	0	3
+771	12	15
+497	1	1
+65	1	1
+1210	2	0
+4131	10	10
+1198	0	1
+718	1	1
+21	1	1
+3668	0	1
+874	1	1
+25	1	1
+2444	1	0
+1867	1	1
+29	1	1
+1660	1	0
+1233	6	0
+783	0	1
+705	3	0
+3577	0	1
+365	0	1
+3389	4	8
+2652	3	0
+664	1	0
+169	9	10
+138	1	0
+8038	56	0
+109	0	196
+522	35	0
+3003	1	1
+40	1	1
+1065	0	4
+634	1	0
+51	30	0
+66	1	9
+3081	0	2
+806	1	0
+21	1	1
+3901	27	26
+843	1	0
+6916420	50000	250000
+25789109	51216	0
+1399988	0	1
+3623	212	0
+38	1	1
+210	29	33
+1318	0	16
+2190	0	1
+145	1	0
+1388	7	7
+2240	14	14
+771	1	1
+34	1	1
+92	1	1
+39	1	1
+505	0	1
+66	1	1
+49	1	1
+159	0	1
+78	0	2
+2	0	1
+13	0	2
+7	0	1
+28	0	1
+27	5	468
+2022	0	1
+1796	7	7
+61	1	1
+20	1	1
+4560	0	3
+157730	0	1
+194	14	14
+650	12	0
+669	74	74
+820	5	0
+277	32	60
+69	5	0
+1345	0	8
+652	0	84
+118	4	0
+498	1	0
+3187	1	1
+43	1	1
+1476	3	0
+2101	0	5
+788	6	6
+872	6	0
+691	202	205
+155	33	33
+4610	7	5
+521	0	10
+2773	1	1
+38	1	1
+627	1	1
+41	1	1
+1424	1	0
+2554	8	8
+45	7	0
+614	1	1
+32	0	3
+2693	1	0
+1029	2	0
+151	1	0
+1753	21	0
+370	3	2
+969	1	0
+452	0	1
+3035	42	42
+704	2	0
+2472	6	0
+238	0	1
+1442	43	43
+126	1	0
+795	1	0
+1191	0	1
+171	16	17
+724	27	28
+2966	1	1
+38	3	1
+359	0	2
+199	1	1
+17	1	1
+1969	0	1
+251	1	0
+729	1	0
+992	1	1
+25	1	1
+203	0	4
+3211	2	0
+1006	10	8
+1571	10	10
+756	38	37
+433	1	0
+672	3	0
+4460	25	182
+5551	19	23
+942	9	10
+3433	1	2
+24	1	1
+4262	0	13
+661	0	2
+167	0	8
+3474	66	61
+162	2	0
+778	34	34
+158	1	0
+1167	1	0
+684	1	0
+878	39	39
+2012	1	0
+345	1	1
+50	1	1
+626	2	0
+27874083	136705	0
+2495	2	0
+1000	0	8
+14695	0	1
+4456	0	1
+2977	0	1
+9065130	29055	25000
+2369	0	1
+12174	20	18
+878	4	0
+5247	12	0
+3482	0	2
+6766	1	0
+2469878	1	0
+835	1	0
+2471	13	13
+751	0	8
+2241	1	0
+12	1	1
+8394	0	1
+47	1	1
+903	1	0
+5537	1	0
+269	0	1
+7114	1	1
+30	1	1
+2412	1	0
+2442	21	21
+91	1	1
+37	1	1
+96	1	1
+22	1	1
+246	1	1
+23	1	1
+241	25	25
+569	1	1
+27	1	1
+1624	0	1
+112	3	3
+45	1	1
+384	13	13
+70	0	1
+658	1	1
+20	1	1
+176	0	1
+307	19	19
+428	1	1
+19	1	1
+87	1	1
+30	1	1
+140	0	1
+292	0	2
+1492	0	1
+302	2	0
+364	1	1
+35	1	1
+1956	1	0
+728	57	57
+8010	0	1
+488	0	1
+2056	8	18
+1286	1	1
+27	1	1
+731	0	1
+1423	7	0
+2010	1	1
+19	1	1
+3925	37	37
+2438	4	0
+80	1	1
+4505	0	13
+933	12	0
+1250	1	0
+1313	0	1
+2610	1	0
+2398	1	0
+453	0	1
+346	14	14
+83	0	1
+24	1	0
+83	12	12
+277	1	0
+45	0	1
+811	0	2
+164	1	0
+104	1	0
+32	1	1
+1386	14	0
+306	1	1
+43	1	1
+2765	1	0
+1819	1	0
+1480	1	1
+24	1	1
+276	1	0
+21	1	0
+119	11	39
+542	1	1
+63	1	1
+180	1	0
+2456	0	1
+392	62	62
+601	0	1
+1166	0	2
+784	4	0
+170	0	1
+939	0	6
+5597	15	15
+1253	1	0
+3336	18	0
+1851	0	9
+45	1	1
+4794	1	0
+1387	0	2
+1460	0	1
+204	5	0
+1506	1	0
+2621	0	1
+6620	1	0
+34	1	1
+249	0	1
+1443	10	0
+242	1	0
+368	9	1
+257	0	4
+1588	0	6
+1544	1	0
+4189	0	120
+354	278046	312446
+3728	1	0
+3127	9	10
+4861	4	0
+5649	0	1
+2011	1	0
+14914	1467	42
+20955	1	0
+2075	1	2
+5546	0	1
+2168	0	4
+1266	0	1
+4124	1	1
+46	1	1
+54	1	1
+43	0	15
+780	1	1
+25	1	1
+497	1	0
+46	1	1
+770	41	40
+5701	1	0
+4251	8	8
+2739	1	0
+2002	3	0
+7160	1	1
+24	1	1
+479	0	2
+1872	1	0
+1192	0	1
+371	0	2
+31	1	1
+572	16	16
+1725	16	16
+588	1	1
+90	1	1
+2483	19	3
+187	1	0
+20	1	1
+3673	1	1
+27	0	4
+3021	0	1
+1323	6	19
+498	13	13
+1618	0	2
+5282	1	0
+720	8	0
+2993	0	1
+2822	2	0
+1396	1	1
+48	1	1
+8723	0	5
+291	1	1
+25	1	1
+116	1	0
+2809	1	1
+27	1	1
+224	1	1
+48	1	1
+292	2	0
+400	1	0
+754	1	1
+19	1	1
+4225	1	1
+28	1	1
+801	0	1
+671	1	1
+17	1	1
+390	1	1
+28	1	1
+84	7	7
+568	1	1
+56	1	1
+499	8	7
+266	1	1
+31	1	1
+518	18	18
+164	1	1
+50	1	1
+162	1	1
+60	1	1
+702	1	1
+28	1	1
+146	17	18
+517	1	1
+24	1	1
+799	1	1
+22	5	5
+107	5	5
+277	9	9
+272	1	1
+48	1	1
+77	1	1
+67	1	1
+1548	1	1
+40	1	1
+763	1	1
+42	1	1
+541	8	8
+88	1	1
+77	1	1
+233	11	11
+311	1	1
+22	1	1
+147	8	1
+504	1	1
+26	1	1
+996	3615	24049
+1687	0	1
+1174	1	0
+70	1	1
+1100	18	10143
+2722	1	0
+2957	1	1
+32	1	1
+9585	1	0
+1350	1	0
+473	1	0
+675	1	0
+1435	1	0
+805463	79189	0
+10872697	100000	100000
+721570	1	1
+19	1	1
+816	1	1
+44	1	1
+572	6	8
+2021	4	0
+1001	0	2
+3757	0	1
+5942	2	2
+70	1	1
+100	7	7
+395	17188	80000
+1010	1	1
+45	1	1
+1486	18	18
+173	145	1
+139	65	1
+41	16	0
+32	368	0
+44	2	50
+40	1	1
+95	52	4
+60	8	39
+12	0	16
+93	0	16
+1591	1	0
+897	13	13
+28	3	3
+2454	1	1
+44	1	1
+305	468	0
+2026	1	1
+45	1	1
+1273	3	11
+1717	0	1
+1575	4	0
+14	1	1
+2428	0	36
+50	10	154
+247	185	6
+2096	11	13
+192	1	1
+48	1	1
+130	1	1
+22	1	1
+970	1	1
+22	0	4
+76	14	0
+118	58	64
+107	1	0
+12	1	1
+53	5	15
+48	1	1
+47	2	0
+114	16	18
+363	1	1
+43	1	1
+559	1	1
+32	1	1
+3980007
+
+chain	16700437	7	159138663	+	142098195	142276197	chr7	158821424	-	16919205	17097543	171
+6297	1	0
+171	1	0
+4869	1	1
+24	0	1
+6208	0	1
+135	1	0
+1978	1	0
+764	1	1
+45	0	2
+1984	0	1
+1628	1	0
+733	1	1
+38	1	0
+137	7	7
+17	1	1
+259	1	0
+1200	1	0
+2193	4	4
+1781	0	1
+3387	1	1
+25	1	1
+125	1	1
+17	1	1
+3811	5	5
+556	0	1
+1846	5	0
+1322	1	1
+40	1	1
+228	0	1
+3477	1	1
+31	1	1
+3722	1	1
+73	1	1
+3052	66	66
+2542	15	15
+3103	0	2
+112	0	2
+1066	1	1
+59	1	0
+719	1	0
+203	1	0
+127	1	0
+30	1	0
+32	1	1
+366	0	4
+27	1	1
+2155	1	1
+41	1	1
+790	0	1
+403	1	1
+27	1	1
+648	7	7
+48	2	0
+78	2	2
+1052	4	4
+855	1	1
+68	1	1
+2428	9	0
+919	1	1
+22	1	1
+366	1	1
+36	1	1
+269	7	7
+4018	6	6
+1168	0	1
+3409	0	1
+1503	3	0
+2680	1	1
+37	1	1
+727	1	1
+28	0	5
+9	0	3
+5	0	2
+4	9	0
+13	1	1
+1801	0	3
+98	14	14
+2789	4	0
+5562	1	0
+2380	1	1
+23	1	1
+160	1	1
+57	1	1
+2413	19	19
+1704	0	1
+67	0	1
+68	1	1
+45	1	1
+176	9	9
+973	1	1
+31	3	3
+167	4	4
+334	13	13
+584	11	11
+206	16	16
+1218	1	1
+29	1	1
+234	1	1
+45	0	2
+1027	0	1
+559	10	11
+367	0	2
+8269	0	2
+4195	1	1
+62	1	1
+2896	13	13
+524	5	5
+411	1	1
+53	1	1
+126	1	1
+36	1	1
+806	1	1
+43	2	0
+1905	2	0
+414	1	1
+25	1	1
+2396	1	0
+12	1	0
+23	0	1
+10	0	1
+4	0	1
+60	0	1
+25	1	1
+1387	0	4
+3461	0	2
+1026	0	2
+821	1	1
+21	1	0
+612	1	1
+31	1	1
+1053	1	0
+2080	17	17
+9739	5	12
+17	7	0
+878	1	1
+19	1	0
+53	1	1
+839	26	26
+522	1	1
+49	1	1
+539	1	1
+25	1	1
+669	1	1
+42	1	1
+134	7	7
+1145	1	0
+2731	1	0
+590	4	0
+41	0	1
+7853	0	4
+830	0	2
+1742	2	0
+640	1	1
+34	0	2
+298	1	0
+3598	1	0
+1522	1	339
+115	18	18
+887	1	1
+69	1	1
+1662
+
+chain	1755125	7	159138663	+	143318748	143347897	chr7	158821424	-	15657394	15686558	532
+923	0	15
+1431	698	698
+3421	10	12
+405	1	1
+16	1	1
+5116	1	1
+27	1	1
+334	1	1
+15	1	0
+724	13	13
+109	0	2
+1784	1	0
+1588	1	1
+43	1	1
+908	9684	9682
+464	445	445
+982
+
+chain	939937	7	159138663	+	61402791	61412791	chr7	158821424	+	61280000	61290000	3137
+10000
+
+chain	921443	7	159138663	+	61382791	61392786	chr7	158821424	+	61260000	61269994	3741
+1722	1	0
+433	30	30
+1603	4	4
+4846	27	27
+478	19	19
+584	36	36
+212
+
+chain	898631	7	159138663	+	61392792	61402791	chr7	158821424	+	61270000	61280000	4251
+316	76	76
+3924	49	49
+2708	28	28
+1134	174	174
+156	40	41
+1394
+
+chain	896117	7	159138663	+	61422788	61432614	chr7	158821424	+	61300000	61310000	4294
+1207	50	50
+1637	22	22
+347	30	30
+983	48	48
+2562	0	172
+1941	14	14
+487	39	41
+459
+
+chain	881174	7	159138663	+	61412791	61422788	chr7	158821424	+	61290000	61300000	4600
+2588	34	34
+299	23	23
+1680	4	6
+286	395	396
+256	39	39
+220	18	18
+675	16	16
+3464
+
+chain	807485	7	159138663	+	61372814	61382791	chr7	158821424	+	61250000	61260000	5800
+91	75	75
+308	91	91
+99	88	88
+175	43	43
+577	65	65
+289	17	17
+186	21	21
+119	72	72
+80	98	98
+114	2	1
+115	51	51
+319	90	97
+54	49	50
+590	135	136
+749	1	0
+467	41	41
+153	21	21
+97	102	118
+935	19	19
+3186	43	43
+150
+
+chain	475263	7	159138663	+	143336322	143346915	chr7	158821424	-	15765291	15775883	242
+2017	14	14
+1214	1	1
+32	1	1
+3171	0	8
+760	1	1
+49	1	1
+68	10	10
+1210	1	1
+39	1	1
+60	18	9
+568	4	4
+357	12	12
+75	512	512
+397
+
+chain	413572	7	159138663	+	61432614	61437066	chr7	158821424	+	61310000	61314455	110492
+105	12	12
+1311	18	21
+3006
+
+chain	327362	7	159138663	+	130261501	130267755	chr7	158821424	-	80118425	80124354	202501
+81	547	220
+108	98	98
+188	35	35
+305	168	168
+59	47	46
+67	25	25
+301	6	6
+107	44	44
+133	23	23
+174	0	4
+110	27	27
+188	31	31
+86	62	62
+284	66	66
+205	34	34
+171	16	16
+85	35	35
+152	206	205
+64	33	33
+71	76	76
+129	26	26
+52	79	80
+203	92	92
+193	64	64
+113	490	490
+131	98	97
+66
+
+chain	116757	7	159138663	+	56987924	57001476	chr7	158821424	-	96066875	96080423	71
+182	4	0
+366	2	0
+47	6	0
+1290	7	1
+317	25	25
+90	14	15
+195	1	6
+96	1	1
+280	1	1
+59	1	1
+435	1	1
+51	1	1
+1067	22	22
+3594	0	1
+645	0	1
+507	7	7
+1383	0	6
+531	0	1
+1396	1	0
+927
+
+chain	94083	7	159138663	+	61667110	61669673	chr9	140273252	-	71180528	71183093	1349166
+123	22	22
+57	154	154
+93	530	532
+407	16	16
+95	28	28
+72	290	290
+83	43	43
+61	266	266
+77	77	77
+69
+
+chain	75094	7	159138663	+	433321	434167	chr14	106368585	-	82907729	82908574	1677524
+115	1	1
+30	1	0
+335	22	22
+342
+
+chain	74694	7	159138663	+	61674373	61676412	chr2	242951149	+	91627954	91629996	1686429
+59	154	155
+210	438	438
+221	259	259
+81	77	77
+52	201	203
+222	15	15
+50
+
+chain	54428	7	159138663	+	61360568	61361523	chr9	140273252	+	69464390	69465353	2322078
+76	100	105
+56	176	179
+432	51	51
+64
+
+chain	45723	7	159138663	+	100554977	100556023	chr7	158821424	+	100392913	100393963	2803709
+153	225	232
+246	8	8
+74	288	285
+52
+
+chain	42415	7	159138663	+	130262863	130266857	chr20	62435964	+	18530662	18534660	203154
+65	162	162
+47	67	67
+25	425	425
+33	1127	1130
+57	206	206
+33	274	274
+33	152	152
+121	149	149
+33	83	83
+64	129	129
+26	335	336
+91	194	194
+63
+
+chain	34286	7	159138663	+	61670163	61670988	chr1	247249719	-	187008143	187008914	3936433
+177	89	89
+59	338	284
+162
+
+chain	30309	7	159138663	+	61417768	61418394	chr15	100338915	+	53005912	53006538	319980
+332	256	256
+38
+
+chain	29619	7	159138663	+	130261638	130262129	chr18	76117153	-	20889181	20889344	211760
+82	389	61
+20
+
+chain	28749	7	159138663	+	102187071	102200348	chr7	158821424	+	102073398	102086671	912
+74	1102	1102
+32	11867	11863
+202
+
+chain	27540	7	159138663	+	61526936	61527567	chr17	78774742	-	13987513	13988140	5824140
+131	255	251
+90	52	52
+103
+
+chain	25455	7	159138663	+	61658206	61658677	chr21	46944323	+	31224827	31225297	6797318
+187	186	185
+98
+
+chain	25398	7	159138663	+	130275431	130276578	chrX	154913754	+	99697151	99697788	219009
+66	77	207
+69	353	1
+53	369	81
+54	49	49
+57
+
+chain	24368	7	159138663	+	61663982	61664383	chr7	158821424	-	97410910	97411311	7475570
+54	99	99
+67	16	16
+165
+
+chain	23018	7	159138663	+	61372081	61372809	chr7	158821424	+	61249436	61249995	8282044
+79	92	92
+52	313	144
+58	34	34
+100
+
+chain	22330	7	159138663	+	61674796	61675234	chr16	88827254	-	56087354	56087792	5126597
+69	100	100
+51	129	129
+89
+
+chain	22048	7	159138663	+	61583753	61648197	chr7	158821424	-	97506969	97571424	1587
+3024	0	1
+5860	1	1
+34	1	1
+1210	1	1
+46	1	1
+1360	1	1
+20	1	1
+6247	7	7
+2011	22	23
+15979	1	1
+20	0	1
+39	1	1
+156	1	1
+79	1	1
+1227	1	1
+26	1	1
+201	17	17
+6321	11	11
+106	2	2
+66	33	33
+316	6	6
+832	1	1
+17	1	1
+478	1	1
+25	1	1
+4306	14	0
+14	1	1
+525	4	4
+1603	1	1
+28	1	1
+433	1	0
+1365	1	1
+35	1	1
+3699	1	1
+17	1	1
+962	0	16
+124	1	1
+221	1	1
+50	1	1
+446	1	0
+788	0	1
+38	1	1
+470	14	14
+173	1	1
+48	0	1
+54	1	1
+71	0	7
+17	1	1
+319	1	1
+49	1	1
+115	2	1
+167	1	1
+41	3	3
+80	1	1
+70	1	1
+119	1	1
+19	1	1
+186	17	17
+347	7	7
+549	1	1
+69	1	1
+175	1	1
+55	1	1
+101	1	1
+118	2	2
+307	1	1
+73	1	1
+91
+
+chain	20717	7	159138663	+	61531674	61531894	chrY	57772954	+	23149505	23149725	9889131
+220
+
+chain	20603	7	159138663	+	61525953	61526232	chr8	146274826	+	92437703	92437982	9974457
+114	48	48
+117
+
+chain	20209	7	159138663	+	61534129	61534693	chr5	180857866	-	39454690	39455254	10284708
+41	129	129
+72	189	189
+133
+
+chain	19256	7	159138663	+	10000	10238	chr11	134452384	-	108	510	10867298
+115	1	145
+57	3	0
+12	3	26
+47
+
+chain	17549	7	159138663	+	23954	24387	chr3	199501827	-	125819	126212	1017
+61	27	17
+87	27	17
+87	27	17
+87	27	17
+3
+
+chain	17511	7	159138663	+	61459516	61459775	chr3	199501827	+	156410667	156410926	12559831
+104	60	60
+95
+
+chain	17423	7	159138663	+	130286013	130286315	chr3	199501827	+	134941335	134941641	12635149
+64	74	78
+72	18	18
+74
+
+chain	17216	7	159138663	+	61561042	61561226	chr18	76117153	+	1344411	1344595	12834816
+184
+
+chain	15818	7	159138663	+	130258842	130259235	chr20	62435964	-	56174662	56175052	14212289
+60	144	139
+68	52	54
+69
+
+chain	15803	7	159138663	+	434188	434399	chr9	140273252	-	53303336	53303547	1693631
+211
+
+chain	15460	7	159138663	+	61363520	61363685	chr14	106368585	+	46013452	46013617	14586403
+165
+
+chain	15455	7	159138663	+	61533249	61533413	chr10	135374737	-	122138066	122138230	14591550
+164
+
+chain	14801	7	159138663	+	61526597	61527118	chr11	134452384	+	128715236	128715756	6490404
+89	98	98
+58	225	224
+51
+
+chain	14577	7	159138663	+	61459836	61459991	chr2	242951149	-	172428837	172428992	15528208
+155
+
+chain	14381	7	159138663	+	61532809	61533249	chr5	180857866	-	128913075	128913510	15277847
+110	278	273
+52
+
+chain	14182	7	159138663	+	61362349	61362804	chr1	247249719	-	101935287	101935742	15983329
+55	287	287
+113
+
+chain	13384	7	159138663	+	130261760	130262050	chr18	76117153	-	65538588	65538878	302793
+128	17	17
+145
+
+chain	12863	7	159138663	+	61659684	61659821	chr18	76117153	+	15161457	15161594	17682773
+137
+
+chain	12713	7	159138663	+	130268588	130270221	chr7	158821424	-	62883278	62884905	17912238
+74	1316	1311
+67	121	120
+55
+
+chain	12498	7	159138663	+	61527567	61527825	chr2	242951149	-	136022598	136022856	13034573
+7	155	155
+96
+
+chain	12424	7	159138663	+	61560835	61560980	chr21	46944323	-	5411573	5411718	18347201
+82	1	1
+62
+
+chain	11917	7	159138663	+	130274671	130277102	chr2	242951149	+	85567844	85569506	1111973
+198	73	73
+65	403	530
+21	111	209
+32	1149	157
+77	81	81
+50	6	4
+165
+
+chain	11414	7	159138663	+	61446485	61446604	chr8	146274826	-	97728756	97728875	19987436
+119
+
+chain	11204	7	159138663	+	323186	323319	chr13	114142980	-	47557127	47557260	20361650
+67	7	7
+59
+
+chain	11191	7	159138663	+	61533547	61533688	chr10	135374737	+	121736617	121736758	14568606
+63	20	20
+58
+
+chain	11162	7	159138663	+	143321102	143321761	chr7	158821424	+	143031254	143031913	1465
+659
+
+chain	11033	7	159138663	+	155133717	155133867	chr7	158821424	+	154826660	154826810	3228542
+150
+
+chain	10743	7	159138663	+	130272956	130273070	chr20	62435964	-	54784771	54784885	21217928
+114
+
+chain	10697	7	159138663	+	61363082	61363210	chr8	146274826	+	114533399	114533527	21308454
+63	1	1
+64
+
+chain	10686	7	159138663	+	130276049	130276418	chr5	180857866	-	110000669	110000947	1711166
+8	218	161
+54	34	0
+55
+
+chain	10550	7	159138663	+	61534371	61534497	chr2	242951149	-	102597516	102597642	13706867
+22	1	1
+103
+
+chain	10502	7	159138663	+	61658058	61658206	chr3	199501827	-	100394760	100394909	7999945
+74	51	52
+23
+
+chain	9908	7	159138663	+	155127373	155127651	chr7	158821424	+	154820991	154821604	23020589
+62	155	490
+61
+
+chain	9705	7	159138663	+	130254993	130255333	chr5	180857866	-	86134908	86135248	23505792
+58	220	220
+62
+
+chain	9691	7	159138663	+	61363878	61364175	chr6	170899992	-	83481581	83481894	23533804
+52	178	194
+67
+
+chain	9557	7	159138663	+	130275060	130277190	chr4	191273063	+	57733996	57734920	1639272
+2	161	201
+75	1804	558
+40	10	10
+38
+
+chain	9406	7	159138663	+	61531909	61532009	chr3	199501827	-	114948547	114948647	24221847
+100
+
+chain	9378	7	159138663	+	61670488	61670618	chr1	247249719	+	166585217	166585347	4198164
+130
+
+chain	9215	7	159138663	+	61369893	61370445	chr20	62435964	+	26207014	26207215	24594255
+60	436	85
+56
+
+chain	8793	7	159138663	+	61533688	61534015	chr8	146274826	+	132629025	132629349	11801047
+54	54	51
+58	97	97
+64
+
+chain	8578	7	159138663	+	61650566	61651111	chr20	62435964	-	36228749	36228943	25570183
+56	436	85
+53
+
+chain	8304	7	159138663	+	61532721	61532809	chr5	180857866	-	33354116	33354204	19653256
+88
+
+chain	8273	7	159138663	+	61375213	61375308	chr10	135374737	-	99567310	99567405	2885342
+95
+
+chain	7707	7	159138663	+	61670340	61670429	chr11	134452384	+	5653851	5653940	4693035
+89
+
+chain	7687	7	159138663	+	61362996	61363078	chr1	247249719	-	62796192	62796274	26921084
+82
+
+chain	7328	7	159138663	+	130260449	130260631	chr6	170899992	+	18975635	18975819	23797357
+8	121	123
+53
+
+chain	7084	7	159138663	+	155107000	155107125	chr8	146274826	+	127792382	127792507	21399384
+5	63	63
+57
+
+chain	6750	7	159138663	+	130268276	130268348	chr9	140273252	+	6309168	6309240	28699203
+72
+
+chain	6727	7	159138663	+	61364306	61364811	chr19	63811651	+	24391898	24393602	28746452
+47	400	1599
+58
+
+chain	6689	7	159138663	+	130262523	130267689	chr14	106368585	-	15396362	15401535	205901
+35	1928	1932
+35	3110	3113
+58
+
+chain	6657	7	159138663	+	130262248	130266269	chr20	62435964	-	53906684	53910704	204336
+68	3910	3909
+43
+
+chain	6632	7	159138663	+	61362621	61362691	chr14	106368585	-	25756639	25756709	18227251
+70
+
+chain	6604	7	159138663	+	61516196	61516266	chr14	106368585	+	18700177	18700247	29040667
+70
+
+chain	6561	7	159138663	+	61362487	61362621	chr5	180857866	-	77495083	77495217	25581093
+60	70	70
+4
+
+chain	6504	7	159138663	+	61563734	61563803	chr14	106368585	+	18700333	18700402	29292943
+69
+
+chain	6504	7	159138663	+	61457014	61457083	chr14	106368585	+	19014991	19015060	29292944
+69
+
+chain	6486	7	159138663	+	61439583	61439652	chr7	158821424	+	61677724	61677793	29330266
+69
+
+chain	6486	7	159138663	+	61453269	61453338	chr11	134452384	+	54672038	54672107	29330599
+69
+
+chain	6415	7	159138663	+	130266970	130267081	chr2	242951149	-	44689835	44689946	206027
+111
+
+chain	6395	7	159138663	+	61581171	61581239	chr12	132349534	+	36481345	36481413	29552558
+68
+
+chain	6295	7	159138663	+	130268491	130268558	chr12	132349534	-	16670768	16670835	29797454
+67
+
+chain	6222	7	159138663	+	61516757	61516823	chr7	158821424	-	100865546	100865612	29971261
+66
+
+chain	6149	7	159138663	+	61518444	61518509	chr9	140273252	-	73547747	73547812	30146556
+65
+
+chain	6147	7	159138663	+	61360661	61361459	chr1	247249719	-	99965931	99966729	2490905
+65	694	694
+39
+
+chain	6131	7	159138663	+	61545392	61545457	chr9	140273252	-	71283139	71283204	30224431
+65
+
+chain	6031	7	159138663	+	61649702	61649766	chr8	146274826	-	102385209	102385273	30479392
+64
+
+chain	5940	7	159138663	+	61567501	61567564	chr11	134452384	-	79723078	79723141	30715303
+63
+
+chain	5895	7	159138663	+	130261352	130261415	chr12	132349534	-	16670326	16670389	30822868
+63
+
+chain	5890	7	159138663	+	130272150	130272376	chr5	180857866	-	150003108	150003332	287879
+73	71	69
+82
+
+chain	5831	7	159138663	+	61540614	61540676	chr20	62435964	+	26207004	26207066	31016062
+62
+
+chain	5822	7	159138663	+	61534741	61534803	chr2	242951149	+	182601389	182601451	31037299
+62
+
+chain	5767	7	159138663	+	61657263	61657324	chrX	154913754	+	145511099	145511160	31173265
+61
+
+chain	5740	7	159138663	+	61561871	61561932	chrX	154913754	+	61825831	61825892	31255925
+61
+
+chain	5707	7	159138663	+	155133639	155133717	chr7	158821424	+	154826660	154826738	3248987
+78
+
+chain	5671	7	159138663	+	130267178	130267274	chr3	199501827	+	136865539	136865635	212140
+96
+
+chain	5649	7	159138663	+	61510793	61510853	chr14	106368585	+	18700200	18700260	31523979
+60
+
+chain	5614	7	159138663	+	61459620	61459680	chr8	146274826	+	85828676	85828736	12834914
+60
+
+chain	5505	7	159138663	+	130286091	130286151	chr11	134452384	+	126327988	126328048	18815467
+60
+
+chain	5376	7	159138663	+	61368713	61368770	chr5	180857866	-	134492854	134492911	32331066
+57
+
+chain	5358	7	159138663	+	130272706	130272763	chr4	191273063	-	62601703	62601760	32378845
+57
+
+chain	5239	7	159138663	+	61375927	61375982	chr3	199501827	+	176568366	176568421	32719676
+55
+
+chain	5238	7	159138663	+	155133561	155133639	chr7	158821424	+	154826660	154826738	3316763
+78
+
+chain	5212	7	159138663	+	48202742	48202797	chrY	57772954	+	8140437	8140492	32786933
+55
+
+chain	5203	7	159138663	+	61362897	61362952	chr2	242951149	-	204521553	204521608	32840726
+55
+
+chain	5203	7	159138663	+	61514738	61514793	chr3	199501827	-	109094736	109094791	32841435
+55
+
+chain	5196	7	159138663	+	102270836	102270891	chr7	158821424	+	101958735	101958790	2864
+55
+
+chain	5085	7	159138663	+	61522548	61522602	chr11	134452384	-	85760698	85760752	33224588
+54
+
+chain	5081	7	159138663	+	61542952	61543361	chrX	154913754	-	96402533	96402599	33252017
+22	343	0
+44
+
+chain	5076	7	159138663	+	61566776	61566830	chrX	154913754	+	58536057	58536111	33266851
+54
+
+chain	5003	7	159138663	+	321166	321219	chr9	140273252	+	26769862	26769915	33490833
+53
+
+chain	4985	7	159138663	+	61511756	61511809	chrX	154913754	+	58510881	58510934	33583214
+53
+
+chain	4976	7	159138663	+	61453966	61454019	chr11	134452384	+	48695047	48695100	33600288
+53
+
+chain	4976	7	159138663	+	61579973	61580026	chr12	132349534	+	36420396	36420449	33600992
+53
+
+chain	4967	7	159138663	+	61528283	61528336	chr2	242951149	-	102597577	102597630	33622422
+53
+
+chain	4930	7	159138663	+	61528065	61528117	chr11	134452384	-	85701922	85701974	33735561
+52
+
+chain	4921	7	159138663	+	61566142	61566194	chr3	199501827	-	104503080	104503132	33762259
+52
+
+chain	4903	7	159138663	+	61364673	61364725	chr9	140273252	+	69253479	69253531	33844300
+52
+
+chain	4894	7	159138663	+	61535225	61535277	chrX	154913754	+	61822223	61822275	33894839
+52
+
+chain	4894	7	159138663	+	61555289	61555341	chrX	154913754	-	93093366	93093418	33894887
+52
+
+chain	4894	7	159138663	+	61367691	61367743	chr11	134452384	+	48824621	48824673	33895037
+52
+
+chain	4876	7	159138663	+	61446263	61446315	chr11	134452384	+	54670005	54670057	33929755
+52
+
+chain	4860	7	159138663	+	61671055	61671121	chr6	170899992	-	77150208	77150274	16663217
+66
+
+chain	4803	7	159138663	+	61582505	61582556	chr5	180857866	+	46128392	46128443	34201035
+51
+
+chain	4803	7	159138663	+	61548133	61548184	chr5	180857866	-	134730739	134730790	34201101
+51
+
+chain	4803	7	159138663	+	61656299	61656350	chr8	146274826	-	102385679	102385730	34201707
+51
+
+chain	4803	7	159138663	+	61371246	61371297	chr20	62435964	+	26207164	26207215	34201851
+51
+
+chain	4803	7	159138663	+	61538491	61538542	chrX	154913754	+	61822744	61822795	34202106
+51
+
+chain	4803	7	159138663	+	61550591	61550642	chrX	154913754	-	96402828	96402879	34202170
+51
+
+chain	4794	7	159138663	+	61568385	61568436	chr12	132349534	-	30627763	30627814	34229426
+51
+
+chain	4794	7	159138663	+	61560404	61560455	chrX	154913754	+	58511165	58511216	34229878
+51
+
+chain	4785	7	159138663	+	61555628	61555679	chr5	180857866	+	49580248	49580299	34261015
+51
+
+chain	4757	7	159138663	+	155127495	155127545	chr7	158821424	+	154820841	154820891	34330191
+50
+
+chain	4745	7	159138663	+	61527127	61527200	chr1	247249719	-	196249350	196249423	12580328
+73
+
+chain	4730	7	159138663	+	61454627	61454677	chrX	154913754	-	93091546	93091596	34451023
+50
+
+chain	4721	7	159138663	+	61547785	61547835	chr14	106368585	+	19015139	19015189	34474345
+50
+
+chain	4712	7	159138663	+	61542078	61542128	chr7	158821424	-	97143221	97143271	34536293
+50
+
+chain	4712	7	159138663	+	61650232	61650282	chr7	158821424	+	61292872	61292922	34536325
+50
+
+chain	4712	7	159138663	+	61447406	61447456	chr12	132349534	-	95867613	95867663	34536696
+50
+
+chain	4712	7	159138663	+	61573362	61573412	chr11	134452384	-	79778078	79778128	34537090
+50
+
+chain	4694	7	159138663	+	61361784	61361834	chr20	62435964	+	26208957	26209007	34582417
+50
+
+chain	4533	7	159138663	+	61657325	61657373	chr14	106368585	-	60354968	60355016	14458107
+48
+
+chain	4330	7	159138663	+	61571756	61571802	chrX	154913754	+	58511174	58511220	34815702
+46
+
+chain	4322	7	159138663	+	61527200	61527268	chr1	247249719	+	66112503	66112571	10645536
+68
+
+chain	4309	7	159138663	+	130262963	130263031	chr20	62435964	+	59813	59881	233275
+68
+
+chain	4243	7	159138663	+	130267293	130267390	chr15	100338915	-	46124324	46124421	430805
+97
+
+chain	4225	7	159138663	+	130272413	130272571	chr3	199501827	-	60665919	60666077	310359
+158
+
+chain	4225	7	159138663	+	130275130	130275387	chr10	135374737	+	61126513	61126771	1703431
+71	112	113
+74
+
+chain	4135	7	159138663	+	61657814	61657864	chr4	191273063	-	103880681	103880731	24177091
+50
+
+chain	4106	7	159138663	+	130265690	130265763	chr2	242951149	+	45160326	45160399	259070
+73
+
+chain	4049	7	159138663	+	61417706	61417751	chr19	63811651	+	35324192	35324237	995629
+45
+
+chain	4036	7	159138663	+	102224324	102224366	chr7	158821424	+	102110621	102110663	1050243
+42
+
+chain	3993	7	159138663	+	130270112	130270163	chr3	199501827	-	142320121	142320172	24066397
+51
+
+chain	3975	7	159138663	+	130269077	130269119	chr8	146274826	+	76339197	76339239	33761016
+42
+
+chain	3893	chr7	159138663	+	61535529	61535570	chr9_random	1146434	-	229264	229305	35008771
+41
+
+chain	3839	7	159138663	+	61659187	61659228	chr7	158821424	-	97183039	97183080	35036445
+41
+
+chain	3820	7	159138663	+	143397897	143397937	chr7	158821424	-	15657354	15657394	1380183
+40
+
+chain	3770	7	159138663	+	130272223	130272265	chr7	158821424	-	144399150	144399192	18136384
+42
+
+chain	3724	7	159138663	+	61669828	61671669	chr18	76117153	-	60916397	60916965	5934170
+170	1399	126
+50	156	156
+66
+
+chain	3694	7	159138663	+	130276177	130276253	chrX	154913754	+	40955942	40956018	2422661
+76
+
+chain	3685	7	159138663	+	102274757	102274796	chr7	158821424	+	101962659	101962698	2923
+39
+
+chain	3592	7	159138663	+	102246649	102246687	chr7	158821424	+	101934491	101934529	2920
+38
+
+chain	3540	7	159138663	+	61670988	61671026	chr1	247249719	-	1293349	1293387	6950988
+38
+
+chain	3536	7	159138663	+	155127890	155127927	chr7	158821424	+	154820516	154820553	31559480
+37
+
+chain	3498	chr7	159138663	+	61668816	61668875	chr21_random	1679693	+	339817	339876	2744470
+59
+
+chain	3321	7	159138663	+	130259738	130259803	chr5	180857866	+	117134963	117135028	22545496
+65
+
+chain	3254	7	159138663	+	155127171	155127205	chr7	158821424	+	154821284	154821318	30495954
+34
+
+chain	3179	7	159138663	+	61671122	61671197	chr3	199501827	+	3741295	3741370	21259213
+75
+
+chain	3139	7	159138663	+	61669998	61670032	chr7	158821424	-	73313700	73313734	35261607
+34
+
+chain	3136	7	159138663	+	155133873	155133906	chr7	158821424	+	154826660	154826693	3164897
+33
+
+chain	3128	7	159138663	+	61657490	61657523	chr14	106368585	+	19500965	19500998	15505654
+33
+
+chain	3124	7	159138663	+	61362864	61362897	chr13	114142980	-	56785908	56785941	33122705
+33
+
+chain	3114	7	159138663	+	61363362	61363395	chr11	134452384	+	38920746	38920779	30450202
+33
+
+chain	3035	7	159138663	+	130267390	130267459	chr5	180857866	+	148307658	148307727	349562
+69
+
+chain	3005	7	159138663	+	130258675	130258738	chr3	199501827	-	66319298	66319361	23438786
+63
+
+chain	2998	7	159138663	+	61670741	61670826	chr2	242951149	-	144372974	144373059	5019535
+68	11	11
+6
+
+chain	2929	7	159138663	+	61366904	61366935	chr9	140273252	+	69000834	69000865	35330365
+31
+
+chain	2883	7	159138663	+	130274908	130276723	chr12	132349534	-	84232022	84233270	1810563
+34	1716	687
+63	1	463
+1
+
+chain	2844	7	159138663	+	61525923	61525953	chr11	134452384	+	42874872	42874902	16620335
+30
+
+chain	2837	7	159138663	+	155133483	155133522	chr7	158821424	+	154826738	154826777	5314872
+39
+
+chain	2752	7	159138663	+	130270309	130270363	chr15	100338915	-	53351487	53351541	22720352
+54
+
+chain	2749	7	159138663	+	61657932	61657999	chr9	140273252	+	120725102	120725169	13790105
+67
+
+chain	2677	7	159138663	+	61657615	61657668	chr2	242951149	-	80490248	80490301	14907722
+53
+
+chain	2675	7	159138663	+	61657868	61657928	chr14	106368585	-	67199431	67199491	8049700
+60
+
+chain	2656	7	159138663	+	61658132	61658174	chr14	106368585	-	39618235	39618277	11504442
+42
+
+chain	2625	7	159138663	+	61376053	61376101	chr2	242951149	-	165273826	165273874	3000213
+48
+
+chain	2574	7	159138663	+	130285941	130286005	chr3	199501827	+	177805790	177805854	20115306
+64
+
+chain	2555	7	159138663	+	61657373	61657490	chr10	135374737	+	110991454	110991571	9489838
+117
+
+chain	2533	7	159138663	+	130255333	130255360	chr5	180857866	+	110504974	110505001	34260994
+27
+
+chain	2525	7	159138663	+	155133522	155133561	chr7	158821424	+	154826699	154826738	3760022
+39
+
+chain	2511	7	159138663	+	130261431	130261481	chr6	170899992	-	80902268	80902318	240832
+50
+
+chain	2491	7	159138663	+	130275062	130277276	chr7	158821424	+	139777825	139778654	1647744
+34	1723	339
+29	404	403
+24
+
+chain	2465	7	159138663	+	102229230	102229256	chr7	158821424	+	101917063	101917089	2852
+26
+
+chain	2367	7	159138663	+	61656836	61656861	chr8	146274826	-	114798799	114798824	27799318
+25
+
+chain	2262	7	159138663	+	61363303	61363362	chr15	100338915	-	25052381	25052440	19971588
+59
+
+chain	2184	7	159138663	+	61360913	61360944	chr16	88827254	+	45047397	45047428	3009512
+31
+
+chain	2183	7	159138663	+	61655805	61655828	chr8	146274826	-	102376418	102376441	35497387
+23
+
+chain	2181	7	159138663	+	61362804	61362827	chr8	146274826	-	64142945	64142968	28339747
+23
+
+chain	2177	7	159138663	+	61363497	61363520	chr15	100338915	-	57516283	57516306	24810342
+23
+
+chain	2111	7	159138663	+	102252256	102252279	chr7	158821424	+	101940282	101940305	3979
+23
+
+chain	2085	7	159138663	+	61668033	61668084	chr9	140273252	+	42719058	42719109	1926685
+51
+
+chain	2073	7	159138663	+	130274605	130277252	chr2	242951149	-	168073547	168075372	1534321
+53	350	351
+52	688	693
+76	1025	208
+32	309	298
+62
+
+chain	2067	7	159138663	+	155127207	155127236	chr7	158821424	+	154821033	154821062	24052540
+29
+
+chain	2049	7	159138663	+	130259609	130260449	chr2	242951149	+	217320568	217321411	19749334
+52	691	694
+97
+
+chain	1867	7	159138663	+	61360944	61360976	chr1	247249719	+	146935382	146935414	2538402
+32
+
+chain	1866	7	159138663	+	130286570	130286642	chr8	146274826	+	120193638	120193710	13784733
+72
+
+chain	1860	7	159138663	+	130271889	130271917	chr3	199501827	+	158050218	158050246	8145167
+28
+
+chain	1834	7	159138663	+	130267107	130267162	chr2	242951149	-	74722759	74722814	2183237
+55
+
+chain	1810	7	159138663	+	434399	434426	chr8	146274826	+	50019771	50019798	1840028
+27
+
+chain	1807	7	159138663	+	61459483	61459516	chr20	62435964	-	10907955	10907988	13772492
+33
+
+chain	1749	7	159138663	+	61534521	61534560	chr8	146274826	-	57707270	57707309	18613209
+39
+
+chain	1741	7	159138663	+	130275927	130275994	chr3	199501827	-	85253648	85253715	1907688
+67
+
+chain	1725	7	159138663	+	130286346	130286404	chr5	180857866	-	156929708	156929766	24410167
+58
+
+chain	1675	7	159138663	+	61360800	61360833	chr2	242951149	-	151940057	151940090	10244640
+33
+
+chain	1649	7	159138663	+	61527639	61527689	chr10	135374737	-	21832678	21832728	15020107
+50
+
+chain	1626	7	159138663	+	61525699	61525759	chr5	180857866	+	119849560	119849620	22270263
+60
+
+chain	1538	7	159138663	+	130271917	130271979	chrX	154913754	+	106499092	106499154	335529
+62
+
+chain	1512	7	159138663	+	130270436	130270487	chr7	158821424	+	123638895	123638946	23964536
+51
+
+chain	1449	7	159138663	+	61671198	61671257	chr11	134452384	+	48551200	48551259	6005368
+59
+
+chain	1444	7	159138663	+	130272046	130272150	chr5	180857866	-	107650838	107650942	1109190
+41	46	46
+17
+
+chain	1406	7	159138663	+	130268385	130269191	chr13	114142980	+	104373808	104374629	24734362
+65	682	697
+59
+
+chain	1391	7	159138663	+	130271979	130272046	chr12	132349534	+	128856107	128856174	572332
+67
+
+chain	1342	7	159138663	+	130255652	130255716	chr6	170899992	-	118498216	118498280	24733557
+64
+
+chain	1277	7	159138663	+	61525407	61525458	chr14	106368585	-	54569941	54569992	25208354
+51
+
+chain	1239	7	159138663	+	61657050	61657132	chr1	247249719	+	60704689	60704771	10216239
+82
+
+chain	1222	7	159138663	+	24387	24410	chr9	140273252	-	34976	34999	792
+23
+
+chain	1201	7	159138663	+	130267591	130267617	chr3	199501827	-	22519451	22519477	371093
+26
+
+chain	1176	7	159138663	+	61533413	61533439	chr9	140273252	+	78066621	78066647	21815254
+26
+
+chain	1159	7	159138663	+	130255953	130256003	chr18	76117153	+	30232927	30232977	26680295
+50
+
+chain	1143	7	159138663	+	130272637	130272705	chr4	191273063	-	164951872	164951940	23193314
+68
+
+chain	1120	7	159138663	+	130267081	130267107	chr4	191273063	+	53894987	53895013	453066
+26
+
+chain	1090	7	159138663	+	61375539	61375583	chr16	88827254	-	2017000	2017044	2867569
+44
+
+chain	967	7	159138663	+	61363930	61363960	chr5	180857866	-	77417997	77418027	26429199
+30
+
+chain	922	7	159138663	+	130269744	130269794	chr6	170899992	-	168370205	168370255	24919326
+50
+
+chain	916	7	159138663	+	130272376	130272413	chr7	158821424	-	119807072	119807109	361270
+37
+
+chain	903	7	159138663	+	130274518	130274571	chr18	76117153	+	7087852	7087905	2747041
+53
+
+chain	875	7	159138663	+	61656861	61656912	chr1	247249719	-	3737712	3737763	19994037
+51
+
+chain	825	7	159138663	+	130276127	130276177	chr9	140273252	+	78760365	78760415	3856900
+50
+
+chain	821	7	159138663	+	61657151	61657205	chr18	76117153	-	50729761	50729815	10763263
+54
+
+chain	764	7	159138663	+	155106965	155107000	chr2	242951149	-	97843675	97843710	19287766
+35
+
+chain	760	7	159138663	+	130260179	130260244	chr15	100338915	-	29035916	29035981	5017751
+65
+
+chain	738	7	159138663	+	61528144	61528186	chr5	180857866	+	37689556	37689598	26578239
+42
+
+chain	665	7	159138663	+	61657587	61657615	chr4	191273063	-	56344538	56344566	26451583
+28
+
+chain	506	7	159138663	+	130259438	130259491	chr7	158821424	-	81365049	81365102	23441660
+53
+
+chain	492	7	159138663	+	130276335	130276363	chr8	146274826	-	17074751	17074779	8865204
+28
+
+chain	466	7	159138663	+	130268939	130269012	chr2	242951149	-	225017173	225017246	26097376
+73
+
+chain	388	7	159138663	+	130271813	130271889	chr3	199501827	+	120370918	120370994	4694596
+76
+
+chain	379	7	159138663	+	130275097	130275130	chr3	199501827	+	9586745	9586778	4580558
+33
+
+chain	379	7	159138663	+	61363702	61363740	chr5	180857866	-	91082220	91082258	29303651
+38
+
+chain	348	7	159138663	+	102200504	102200535	chr7	158821424	-	57045045	57045076	1079
+31
+
+chain	17312866	chr7_gl000195_random	182896	+	0	182896	chr7_random	549659	+	162804	345700	162
+182896
+
+chain	13484003737	8	146364022	+	10000	146304022	chr8	146274826	+	0	146274826	9
+930417	1243	1
+52	10	10
+91	972	0
+54	54	0
+281	324	0
+289	1	0
+2323216	0	1
+3352649	0	2
+854996	50000	100000
+3399023	1	1
+46	1	1
+13965	1	1
+30	1	1
+121189	1	1
+35	1	1
+283700	1	0
+719291	93054	100016
+1155	2	0
+755	26	26
+980	21	21
+1479	422	422
+3229	0	1
+1937	1	1
+17	1	1
+322	0	1
+1758	0	2
+1141	1	0
+956	48	48
+1765	1	0
+543	25	25
+7047	15	15
+1029	1	1
+28	1	1
+314	1	1
+46	1	1
+164	1	1
+25	1	1
+5130707	1	0
+1288	1	0
+446	1	1
+80	1	1
+2123	4	4
+2514	0	3
+545	0	9
+527	1	1
+18	1	1
+256	9	9
+79	1	1
+40	1	1
+148	2	0
+2236	27	0
+953	1	1
+20	1	1
+2487	1	1
+113	1	1
+73	13	13
+365	10	10
+151	1	1
+32	0	3
+26	1	1
+1480	1	1
+29	1	1
+621	1	1
+28	1	1
+701	9	9
+362	1	1
+19	1	1
+691	1	1
+45	0	6
+46	1	1
+513	11	12
+382	1	1
+22	1	1
+111	1	1
+36	1	1
+337	1	1
+42	1	1
+602	0	2
+36	1	1
+475	1	1
+23	1	0
+32	3	4
+65	1	1
+59	1	1
+688	1	1
+22	1	1
+1473	1	1
+36	1	1
+372	1	1
+16	6	6
+640	25	25
+940	1	1
+38	1	1
+816	1	1
+17	0	1
+374	1	1
+17	1	1
+48	0	1
+82	1	1
+45	1	1
+263	1	1
+23	1	1
+204	1	1
+39	1	1
+2341	1	0
+2989	1	0
+9	1	0
+811	8	8
+741	2	0
+337	1	1
+25	4	4
+763	1	1
+19	1	1
+343	1	1
+31	1	1
+1953	1	1
+74	1	1
+67	1	1
+18	4	4
+73	1	1
+31	1	1
+114	1	11
+87	1	1
+65	1	1
+125	9	9
+378	0	1
+47	1	1
+90	1	1
+96	0	1
+176	7	13
+696	1	0
+6184	13	13
+830	13	13
+128	1	1
+37	1	1
+136	0	1
+66	6	5
+870	0	1
+4877	1	0
+585	7	3
+1728	0	1
+33	1	1
+465	1	1
+68	1	1
+581	0	6
+2088	0	1
+304	1	0
+2674	1	1
+28	0	1
+54	8	8
+846	1	0
+1409	16	16
+559	1	0
+401	5	0
+17	1	5
+29	1	1
+4051	1	1
+10	1	0
+43	1	1
+385	1	1
+35	1	1
+101	11	11
+602	0	1
+491	16	14
+1366	19	19
+321	1	1
+49	1	1
+546	1	1
+25	1	1
+1333	28	28
+1207	1	1
+51	0	4
+159	1	0
+1040	1	0
+1682	4	0
+34	0	8
+867	1	1
+17	1	1
+587	1	1
+21	1	1
+904	1	0
+261	1	0
+1151	2	0
+2325	5	5
+5415	3	0
+1545	0	1
+428	4	4
+1950	0	2
+1073	1	0
+3658	86	0
+1278	1	1
+79	1	1
+6656	12	12
+1550	18	0
+5832	0	1
+4835	10	10
+1719	1	1
+84	1	1
+848	2	0
+236	1	1
+42	1	1
+1286	0	12
+35	1	1
+820	1	1
+22	0	1
+63	22	0
+167	23	23
+315	8	8
+983	0	6
+539	14	14
+863	2	0
+27	1	1
+204	14	14
+163	4	4
+290	1	1
+59	1	1
+842	2	0
+2044	1	1
+90	1	0
+3434	3	0
+356	1	0
+873	1	0
+864	1	25
+630	7	12
+62	1	1
+88	1	1
+76	11	11
+1366	17	17
+156	4	4
+244	18	4
+505	0	1
+109	1	1
+230	1	1
+107	3	4
+150	1	1
+83	5	5
+70	1	1
+33	0	1
+142	1	1
+626	6	5
+274	10	10
+128	1	1
+35	1	1
+216	1	1
+44	1	1
+312	18	18
+1496	7	8
+451	1	0
+212	14	14
+629	1	1
+20	1	1
+350	1	1
+62	1	1
+617	10	10
+845	1	1
+58	1	1
+2189	1	1
+147	1	1
+475	1	1
+27	1	1
+278	1	1
+17	1	1
+994	1	1
+40	1	1
+219	5	5
+26	1	1
+900	1	1
+29	0	1
+26	1	1
+484	16	15
+61	9	9
+114	26	21
+801	1	1
+33	1	1
+465	32	32
+63	1	1
+37	1	1
+80	14	14
+211	1	1
+43	1	1
+156	1	1
+20	1	1
+685	1	1
+67	0	4
+711	1	1
+38	1	1
+402	7	7
+1045	1	1
+37	1	1
+4035	9	9
+247	0	4
+4146274	5734	17400
+330366	1	0
+2346742	55	0
+413177	0	3
+450	0	1
+9436	1	3
+7044	0	4
+2886	0	1
+635	0	1
+16567	0	1
+6918	0	1
+9285	0	1
+14909	0	8
+12879	0	2
+3330	0	2
+2673376	0	2
+2173174	7	7
+29817	2485	66108
+6473782	5	5
+39	1	1
+9574	2	0
+5879	1	1
+29	1	1
+6139	0	1
+2354	1	1
+28	1	1
+91	1	1
+23	0	1
+62	1	1
+142	15	16
+54	1	1
+22	3	3
+1479	4	4
+221	4	4
+132	0	1
+574	11	11
+23	0	1
+604	1	1
+44	1	1
+899	0	1
+70	10	12
+13561	1	1
+44	1	1
+4476	4	4
+799	25	26
+1466	18	18
+17896	0	4
+1668	0	1
+4250	1	1
+44	1	0
+4	1	0
+11	1	1
+4956	1	1
+18	0	1
+39	2	3
+4990	1	1
+47	13	13
+68	0	4
+9730	0	1
+355	1	0
+2186	1	1
+37	1	1
+6111	3	3
+100	4	4
+68	1	1
+43	1	1
+1126	7	5
+5520	8	8
+2316	1	1
+181	6	6
+50	1	1
+29	0	1
+83	1	1
+1073	150	154
+100	398	0
+141	1	1
+25272	1	0
+2132	4	0
+2522	1	1
+48	1	1
+1498528	1	0
+6044582	3000000	3000008
+1291149	16655	60038
+3837	0	3
+811	0	1
+2567	0	1
+7375465	1	0
+10	0	1
+42062	0	1
+19604621	0	1
+10692667	0	1
+110	1	0
+3577	3	0
+907	1	1
+18	1	1
+528	1	1
+50	1	1
+317	1	1
+64	251	535
+21	1	0
+140	1	0
+70	0	1
+77	10	9
+227	0	1
+142	5	5
+57	14	14
+43	1	1
+31034	99683	124100
+2301	2	0
+44	0	2
+568015	186612	87300
+355	5	5
+1916	3085	0
+924	4	0
+339	211	211
+963	14	15
+1157	12194	0
+242	23	23
+56	15	15
+405	20	20
+955	49	49
+1347	1	1
+2289	51	51
+555	253	253
+1723	77	77
+396	13	13
+112	3085	0
+3945	0	1
+209	23	23
+69	22	22
+81	20	20
+696	20	20
+58	69	69
+100	13	13
+326	137	137
+151	35	35
+1804	37	37
+1548	26	26
+324	23	23
+1932	17	17
+111	47	47
+128	16	16
+78	30	30
+1022	10	6
+78	0	1
+342	31	31
+86	23	23
+1580	255	255
+170	10	10
+398	23	23
+419	20	20
+955	55	55
+1139	11	11
+1925	276	0
+223	1	1
+56	1	1
+702	5	5
+17	3	3
+1030	1	1
+21	1	1
+363	1	1
+30	1	1
+785	16	16
+78	13	13
+1036	4	0
+482	68	68
+1069	10	10
+321	200	200
+434	43	43
+798	20	20
+56	25	25
+1007	5	5
+1198	24	24
+689	0	3
+743	32	32
+817	43	43
+574	11	11
+760	69	69
+1229	32	32
+272	29	29
+106	97	97
+1309	46	46
+850	4	4
+777	62	62
+86	36	36
+374	93	93
+2076	31	31
+195	56	56
+379	80	80
+64	11	11
+191	18	18
+1051	13	13
+52	119	113
+1347	1	1
+25	1	1
+3451	188	0
+3097	9	0
+2715	0	1
+11829	3	0
+6000	0	28
+10729	1	0
+3770769	0	1
+62	0	1
+22	0	1
+827	0	1
+1485	0	1
+242	1	0
+7142	0	1
+4029	3	3
+69	1	1
+15865	0	1
+83461	0	4
+5978	0	9
+2661	0	1
+1483	0	1
+15868	0	4
+17798	0	1
+2649	0	1
+3627	0	1
+4789	0	1
+9541	0	1
+6844	0	1
+3187	0	2
+411	0	14
+3056	0	4
+19776	0	3
+29085	1	0
+745	0	2
+11453	0	2
+16739	0	1
+14697	0	1
+8539	0	1
+25514443	0	1
+17680	1	0
+55359	1	0
+58	13	11
+5	1	0
+6	1	0
+5	1	0
+22	0	1
+4	1	3
+1515	0	1
+1111	0	1
+5736	6	6
+66213	0	1
+68	1	1
+24	7	6
+43	1	1
+33414	7	7
+22	1	1
+12288	22	22
+7002	1	0
+8588	1	1
+31	1	1
+15969	1	1
+32	1	1
+27034	1	1
+42	1	1
+3352	1	0
+15009	0	1
+20433	18	18
+32141	8	9
+116	41	41
+4920	0	1
+33364	0	1
+11160	1	0
+15	1	0
+28423	0	1
+43835	1	1
+24	2	4
+269244	4	4
+37	1	1
+17193	3	4
+53	11	12
+23	1	2
+7	1	1
+37978	9	9
+37743	1	1
+35	3	3
+26636	1	1
+17	1	1
+8728292	0	1
+16734777	71275	0
+657026	2	0
+2911	2	0
+1941	1	1
+35	1	1
+835	1	1
+116	1	1
+399	1	1
+101	0	1
+194	2	1
+450	0	1
+825	1	1
+73	1	1
+156	1	1
+58	1	1
+50	5	5
+153	11	11
+189	5	5
+233	1	1
+83	1	1
+642	1	0
+1380	1	1
+17	1	1
+315	1	1
+26	1	1
+789	901	0
+73	1	1
+45	1	1
+535	1	1
+34	1	1
+2007	7	7
+159	1	1
+26	1	1
+6362	13	13
+504325	25635	100008
+420771	232	0
+287688	104	0
+65	364	0
+183	55	0
+93	1	1
+46	1	1
+4002	1	1
+24	1	1
+190	0	147
+65	2	1
+8	0	1
+39	2	591
+306	50	0
+1938	1	0
+578	0	684
+291	1	0
+572289	108288	7108
+480202	0	1
+11866	6	6
+26917	1	0
+6097	15	15
+3074	1	0
+12292	1	0
+2209	1	0
+7358	1	0
+321393
+
+chain	2607822	8	146364022	+	12061935	12091854	chr8	146274826	+	12348580	12378713	990
+895	20	0
+1391	22	21
+53	88	0
+99	36	0
+9	0	346
+255	0	44
+496	1	0
+1013	0	4
+1698	1	0
+1054	37	37
+915	52	54
+2295	9	9
+123	1	0
+1295	162	162
+2903	50	50
+913	24	24
+2382	1	0
+299	85	85
+61	27	16
+1351	37	37
+974	4	4
+571	1	0
+530	11	0
+572	18	18
+76	4	4
+398	0	2
+54	31	31
+115	37	37
+125	364	364
+70	47	47
+56	8	8
+979	57	57
+248	50	50
+65	100	100
+82	1	0
+428	34	34
+51	6	0
+156	66	66
+257	132	132
+56	49	49
+91	19	19
+67	38	37
+142	6	6
+249	17	17
+123	104	104
+190	36	37
+355	5	1
+161	1	0
+89	48	48
+62	38	38
+136	67	67
+839
+
+chain	2498503	8	146364022	+	86726531	86754632	chr8	146274826	-	59364826	59419953	1092
+268	2	2
+114	6	0
+49	13	13
+1051	18	18
+117	8	3
+81	1	1
+64	4	4
+73	3	3
+379	1	1
+54	1	1
+183	13	13
+374	1	1
+43	1	1
+874	2	2
+22	1	1
+56	20	20
+712	1	1
+91	1	1
+374	1	1
+73	1	1
+88	21	21
+83	1	1
+27	1	1
+302	29	29
+1591	1	1
+27	4	0
+1250	1	1
+20	1	1
+2246	10	9115
+1002	49	49
+314	4	4
+116	32	32
+363	23	23
+1050	13	13
+119	0	8829
+1050	16	16
+1869	31	31
+119	0	9106
+593	13	13
+396	77	77
+1017	32	32
+888	39	39
+2895	1	1
+964	43	43
+1769	15	15
+292	35	35
+97	5	5
+313	13	13
+248	40	40
+435	10	11
+129	6	6
+712
+
+chain	1152177	8	146364022	+	142754466	142766515	chr8	146274826	+	142956164	142968213	2035
+12049
+
+chain	1081960	8	146364022	+	86772301	86823828	chr8	146274826	+	86857153	86905309	683
+56	15	15
+405	21	21
+1003	383	383
+837	0	1
+126	1	1
+531	1	0
+794	1	0
+73	32	32
+817	43	43
+214	432	432
+212	114	114
+373	28	28
+159	32	32
+832	44	44
+217	192	192
+330	927	923
+88	39	40
+1839	279	279
+283	13	13
+143	1716	1717
+49	3637	3637
+51	555	555
+97	1	1
+21	1	1
+133	1723	1723
+13	16	16
+48	8749	5664
+69	439	439
+62	43	43
+32	151	151
+35	1804	1804
+37	1548	1272
+26	2407	2407
+32	1719	1716
+31	1784	1784
+160	1995	1995
+55	3075	3075
+276	4870	4866
+68	1429	1429
+83	21	21
+67	434	434
+36
+
+chain	801068	8	146364022	+	145324300	145332588	chr8	146274826	+	145464193	145472508	5275
+3979	8	0
+2057	0	35
+2244
+
+chain	744541	8	146364022	+	86754632	86807992	chr8	146274826	+	86857851	86901670	688
+637	20	20
+440	88	88
+964	1	1
+2289	52	52
+554	1	1
+37	1	1
+1606	46	43
+288	6565	395
+203	3612	3608
+265	1500	1501
+278	1	1
+104	3213	3212
+43	214	214
+138	26	26
+268	212	212
+80	594	594
+32	832	832
+34	227	227
+16	27	27
+149	330	330
+33	21	21
+873	88	85
+39	1839	1839
+229	17	17
+33	9021	8745
+425	14725	11640
+30
+
+chain	657279	8	146364022	+	12141854	12149156	chr8	146274826	+	11932698	11940000	7963
+232	8	8
+466	34	34
+801	48	48
+815	68	68
+1203	29	29
+407	31	31
+467	26	26
+1146	18	18
+1503
+
+chain	521724	8	146364022	+	12149156	12156927	chr8	146274826	+	11940000	11947772	4417
+2168	0	1
+503	25	25
+153	202	202
+106	107	107
+851	39	39
+1679	1912	1912
+26
+
+chain	511532	8	146364022	+	142816515	142822092	chr8	146274826	+	142814667	142820000	26584
+2797	244	0
+2536
+
+chain	345755	8	146364022	+	142822092	142825705	chr8	146274826	+	142820000	142823612	174979
+3531	1	0
+81
+
+chain	305790	8	146364022	+	86765339	86795897	chr8	146274826	+	86865470	86901765	930
+477	0	9106
+123	31	31
+1705	14	14
+503	14	14
+15	1470	1466
+91	31	31
+52	35	35
+2	7890	7613
+26	560	560
+34	16750	13662
+405	127	127
+203
+
+chain	137107	8	146364022	+	85964683	85966170	chr8	146274826	+	86036733	86038220	940425
+1283	19	19
+185
+
+chain	118247	8	146364022	+	86759071	86769900	chr8	146274826	+	86874481	86903237	1649
+52	2533	2530
+13	16	16
+1046	0	8829
+123	13	13
+196	2878	11983
+29	3812	3808
+31	52	52
+35
+
+chain	109647	chr8	146364022	+	21624541	21625686	chr8_random	943810	+	516200	517342	1758
+687	1	0
+241	2	0
+214
+
+chain	97713	8	146364022	+	86793362	86840444	chr8	146274826	+	86862935	86885634	1255
+1752	44	44
+4	38618	14235
+46	1631	1631
+62	86	86
+36	374	374
+93	2302	2302
+56	379	379
+80	1400	1400
+119
+
+chain	85095	8	146364022	+	85924850	85927320	chr2	242951149	-	28701067	28703532	1485529
+52	143	142
+173	208	208
+107	181	181
+68	70	66
+129	101	101
+183	373	373
+87	163	163
+164	198	198
+70
+
+chain	67060	chr8	146364022	+	144032710	144033413	chr8_random	943810	+	583131	583834	1875893
+703
+
+chain	47407	8	146364022	+	85907218	85908847	chr10	135374737	-	19950497	19952126	2691979
+115	531	531
+182	240	240
+64	202	202
+122	22	22
+52	45	45
+54
+
+chain	45318	8	146364022	+	85909407	85911400	chr3	199501827	-	58732681	58734687	2832173
+138	151	157
+53	129	125
+171	674	685
+80	116	116
+82	347	347
+52
+
+chain	43260	8	146364022	+	12069066	12090712	chr8	146274826	-	138168279	138189929	1162
+37	915	915
+52	6789	6802
+48	3620	3620
+85	61	59
+27	1351	1348
+5	1	1
+30	3223	3218
+22	115	115
+37	465	465
+24	3764	3760
+90	837	842
+48
+
+chain	38958	8	146364022	+	12159413	12159829	chr8	146274826	+	11950258	11950674	3228
+416
+
+chain	38127	8	146364022	+	86726451	86753339	chr8	146274826	-	59376930	59524482	1121
+80	11856	20676
+48	435	435
+32	4503	13609
+31	1121	10227
+77	1017	94649
+32	888	888
+39	3860	3860
+15	1	1
+26	2078	2078
+33	678	678
+38
+
+chain	31437	8	146364022	+	85955665	85955994	chr3	199501827	-	6162711	6163040	4382021
+329
+
+chain	30755	8	146364022	+	85915208	85915710	chr8	146274826	-	4216734	4217241	4503764
+255	160	165
+87
+
+chain	27896	8	146364022	+	940417	941596	chr8	146274826	+	930633	930948	5586021
+100	54	0
+108	810	0
+107
+
+chain	26413	8	146364022	+	85978864	85981144	chr9	140273252	-	40203469	40205589	6324943
+79	1134	635
+70	83	416
+56	207	205
+56	22	22
+63	455	463
+55
+
+chain	25390	8	146364022	+	85975200	85975766	chr6	170899992	-	89617888	89618457	6830715
+67	141	143
+50	38	39
+54	78	78
+138
+
+chain	20285	8	146364022	+	85975766	85977415	chr3	199501827	-	82189783	82191451	9116338
+8	700	763
+50	465	465
+54	309	265
+63
+
+chain	20226	8	146364022	+	85979170	85979799	chr3	199501827	-	161413320	161413963	10270718
+61	394	408
+174
+
+chain	20141	8	146364022	+	12151827	12152420	chr8	146274826	+	11902715	11903309	638255
+25	153	154
+202	106	106
+107
+
+chain	19400	8	146364022	+	85925267	85925628	chr10	135374737	+	135080720	135081080	3597149
+102	2	1
+54	131	131
+72
+
+chain	18915	8	146364022	+	942460	942893	chr8	146274826	+	930516	930733	3835109
+63	162	0
+46	108	54
+54
+
+chain	18062	8	146364022	+	942088	942460	chr8	146274826	+	930684	930948	5250846
+157	108	0
+107
+
+chain	17886	8	146364022	+	943174	943431	chr8	146274826	+	930690	930893	4105167
+149	55	1
+53
+
+chain	15443	8	146364022	+	941596	942029	chr8	146274826	+	930516	930841	4827909
+64	207	153
+65	54	0
+43
+
+chain	14855	8	146364022	+	85924497	85927134	chrX	154913754	+	50874366	50877002	1910511
+90	57	57
+50	108	108
+48	52	52
+79	801	801
+50	953	952
+50	236	236
+63
+
+chain	12854	8	146364022	+	144743895	144744094	chr8	146274826	+	144814885	144815084	3961669
+199
+
+chain	12042	8	146364022	+	85907589	85907864	chr4	191273063	+	22500316	22500591	2841396
+81	177	177
+17
+
+chain	11713	8	146364022	+	36265496	36265620	chr7	158821424	-	150143040	150143164	19315609
+124
+
+chain	10744	8	146364022	+	85909592	85910073	chr4	191273063	-	317022	317498	3271263
+71	86	86
+68	232	227
+24
+
+chain	10295	8	146364022	+	85917935	85918395	chr16	88827254	-	19324120	19324578	22152835
+60	331	329
+69
+
+chain	9964	8	146364022	+	85927135	85927250	chr3	199501827	-	159900532	159900647	3087651
+115
+
+chain	9833	8	146364022	+	85908046	85908504	chr8	146274826	-	114124165	114124623	2795681
+56	59	59
+58	162	162
+123
+
+chain	9709	8	146364022	+	943330	943485	chr8	146274826	+	930684	930839	15332741
+48	53	53
+54
+
+chain	9657	8	146364022	+	86004292	86004501	chrX	154913754	+	27575363	27575573	23616431
+52	93	94
+64
+
+chain	9406	8	146364022	+	85945093	85945452	chr12	132349534	+	8944725	8945099	24220725
+61	243	258
+55
+
+chain	9151	8	146364022	+	85910121	85910218	chr10	135374737	-	38564811	38564908	24713323
+97
+
+chain	8406	8	146364022	+	85924386	85924476	chr5	180857866	+	127114677	127114767	25803856
+90
+
+chain	7367	8	146364022	+	85911400	85911623	chrX	154913754	-	44623158	44623382	4824008
+72	91	92
+60
+
+chain	7214	8	146364022	+	85983029	85983106	chr3	199501827	+	182981094	182981171	27755476
+77
+
+chain	7178	8	146364022	+	85926461	85926638	chr7	158821424	+	131250991	131251168	8959140
+97	79	79
+1
+
+chain	6913	8	146364022	+	85946010	85946083	chr5	180857866	-	76444763	76444836	28360557
+73
+
+chain	6866	8	146364022	+	85981016	85981089	chr3	199501827	-	137848275	137848348	18929141
+73
+
+chain	6722	8	146364022	+	85915749	85915820	chr6	170899992	-	41858720	41858791	28750065
+71
+
+chain	6523	8	146364022	+	85874468	85874538	chr6	170899992	+	80165568	80165638	29222062
+70
+
+chain	6284	8	146364022	+	48138290	48138355	chr12	132349534	-	99530740	99530805	29826800
+65
+
+chain	6255	8	146364022	+	86830665	86832268	chr8	146274826	+	86851473	86853076	5870
+41	1533	1533
+29
+
+chain	6230	8	146364022	+	143494784	143494849	chr8	146274826	+	143492621	143492686	29969115
+65
+
+chain	5949	8	146364022	+	85946624	85946687	chr7	158821424	-	150469376	150469439	30705065
+63
+
+chain	5930	8	146364022	+	86000088	86000150	chr4	191273063	-	114595117	114595179	30759641
+62
+
+chain	5722	8	146364022	+	85909210	85909271	chr4	191273063	-	32715229	32715290	31306692
+61
+
+chain	5681	8	146364022	+	85907187	85907519	chr7	158821424	-	141596962	141597294	3108677
+31	137	137
+3	85	85
+76
+
+chain	5594	8	146364022	+	85966181	85966240	chr2	242951149	+	129692100	129692159	31643052
+59
+
+chain	5348	8	146364022	+	85946168	85946224	chrX	154913754	+	22697258	22697314	32405249
+56
+
+chain	5330	8	146364022	+	85945000	85945056	chrX	154913754	-	56717679	56717735	32442268
+56
+
+chain	5292	8	146364022	+	85926370	85926785	chr12	132349534	+	42776733	42777148	2271290
+75	280	280
+14	27	27
+19
+
+chain	5194	chr8	146364022	+	85992019	85992074	chr17_random	2617613	-	1345968	1346023	32873362
+55
+
+chain	5161	8	146364022	+	941932	941986	chr8	146274826	+	930312	930366	21107216
+54
+
+chain	5012	8	146364022	+	85946286	85946339	chr1	247249719	-	150482359	150482412	33477745
+53
+
+chain	4929	8	146364022	+	941384	941435	chr8	146274826	+	930304	930355	33748771
+51
+
+chain	4927	8	146364022	+	85874401	85874458	chr12	132349534	+	21319375	21319432	33750711
+57
+
+chain	4920	8	146364022	+	85945525	85945576	chr10	135374737	+	87468307	87468358	33788347
+51
+
+chain	4810	8	146364022	+	942523	942621	chr8	146274826	+	930741	930839	7547023
+98
+
+chain	4803	8	146364022	+	85970009	85970060	chr11	134452384	+	10157776	10157827	34198727
+51
+
+chain	4793	8	146364022	+	85975065	85975115	chr21	46944323	-	30257577	30257627	34245350
+50
+
+chain	4738	8	146364022	+	942303	942352	chr8	146274826	+	930521	930570	34412340
+49
+
+chain	4461	8	146364022	+	85910862	85910919	chrX	154913754	+	151305652	151305709	4935543
+57
+
+chain	4271	8	146364022	+	86793237	86793293	chr8	146274826	+	86902190	86902246	1452514
+56
+
+chain	4178	8	146364022	+	85915489	85915539	chr3	199501827	+	132299011	132299061	5319224
+50
+
+chain	4079	8	146364022	+	85926268	85926343	chr2	242951149	-	211437807	211437882	2547607
+75
+
+chain	3965	8	146364022	+	85910617	85910659	chr5	180857866	+	105218926	105218968	18292131
+42
+
+chain	3826	8	146364022	+	85911256	85911310	chr7	158821424	+	49570162	49570216	23840400
+54
+
+chain	3809	8	146364022	+	86829249	86829292	chr8	146274826	+	86874439	86874482	7328
+43
+
+chain	3796	8	146364022	+	85928889	85929141	chrX	154913754	+	121492736	121492988	2565989
+99	40	40
+113
+
+chain	3755	8	146364022	+	85925629	85925714	chr5	180857866	+	141403818	141403903	2005326
+54	23	23
+8
+
+chain	3680	8	146364022	+	36265255	36265294	chr21	46944323	-	8931342	8931381	34138292
+39
+
+chain	3466	8	146364022	+	85917822	85917882	chr11	134452384	-	107659023	107659083	22827264
+60
+
+chain	3460	8	146364022	+	85925991	85926082	chr19	63811651	+	46688677	46688768	2544872
+91
+
+chain	3412	8	146364022	+	85981195	85981250	chr12	132349534	-	23016451	23016506	20760996
+55
+
+chain	3378	8	146364022	+	144744318	144744353	chr8	146274826	+	144814727	144814762	26884487
+35
+
+chain	3372	8	146364022	+	12064503	12064539	chr8	146274826	+	12351001	12351037	28926895
+36
+
+chain	3336	8	146364022	+	85910527	85910617	chr6	170899992	+	121091189	121091279	5885029
+90
+
+chain	3306	8	146364022	+	85975140	85975200	chr5	180857866	-	14200316	14200376	14215921
+60
+
+chain	3123	8	146364022	+	144455804	144455869	chr8	146274826	+	144526757	144526822	16634618
+65
+
+chain	3122	8	146364022	+	85910073	85910106	chr10	135374737	+	91515201	91515234	27999029
+33
+
+chain	2973	8	146364022	+	85975297	85975339	chr11	134452384	+	70894433	70894475	12515399
+42
+
+chain	2846	8	146364022	+	85980398	85980477	chr6	170899992	+	12780268	12780347	14041671
+79
+
+chain	2664	8	146364022	+	85980653	85980843	chr13	114142980	+	79661332	79661527	13462115
+54	70	75
+66
+
+chain	2542	8	146364022	+	86811232	86811259	chr8	146274826	+	86750599	86750626	581042
+27
+
+chain	2408	8	146364022	+	86780113	86780140	chr8	146274826	+	86901259	86901286	3284
+27
+
+chain	2361	chr8	146364022	+	86795114	86795665	chr8_random	943810	-	353250	353801	88303
+34	419	419
+98
+
+chain	2314	8	146364022	+	85909329	85909403	chr5	180857866	-	126448590	126448664	8133335
+74
+
+chain	2312	8	146364022	+	85964546	85964619	chr5	180857866	-	22206487	22206560	13216855
+73
+
+chain	2306	8	146364022	+	85909062	85909878	chr5	180857866	-	76491094	76491924	7171448
+57	726	740
+33
+
+chain	2277	8	146364022	+	85945069	85945093	chr2	242951149	-	76417863	76417887	30610067
+24
+
+chain	2276	8	146364022	+	85915156	85915196	chr9	140273252	+	96271703	96271743	9134049
+40
+
+chain	2255	8	146364022	+	12171549	12171574	chr8	146274826	+	11962388	11962413	4339
+25
+
+chain	2213	8	146364022	+	85976678	85976734	chr10	135374737	+	107478570	107478626	23840391
+56
+
+chain	2193	8	146364022	+	85909817	85909844	chr1	247249719	-	204777828	204777855	6141044
+27
+
+chain	2188	8	146364022	+	85915463	85915489	chr4	191273063	+	117566433	117566459	5547542
+26
+
+chain	2086	8	146364022	+	85907670	85907692	chr9	140273252	+	84577624	84577646	25068333
+22
+
+chain	2042	8	146364022	+	85906786	85906876	chr1	247249719	-	187757137	187757227	3120497
+90
+
+chain	2008	8	146364022	+	85975339	85978010	chr12	132349534	-	60955403	60957663	7657094
+69	2448	2037
+58	20	20
+76
+
+chain	1976	8	146364022	+	85910386	85910476	chr11	134452384	+	108691426	108691516	10944711
+90
+
+chain	1915	8	146364022	+	85915895	85915946	chr2	242951149	-	57258601	57258652	18793758
+51
+
+chain	1706	8	146364022	+	85926558	85926608	chr20	62435964	+	52983902	52983952	9284939
+50
+
+chain	1666	8	146364022	+	85915539	85915568	chr3	199501827	-	58686941	58686970	11643280
+29
+
+chain	1625	8	146364022	+	85977632	85977856	chr3	199501827	-	45071352	45071581	10048168
+62	161	166
+1
+
+chain	1603	8	146364022	+	36265620	36265653	chr4	191273063	+	189716401	189716434	1596951
+33
+
+chain	1586	chr8	146364022	+	86793293	86793362	chr8_random	943810	+	582217	582286	150907
+69
+
+chain	1585	8	146364022	+	85907040	85907092	chr7	158821424	+	38674874	38674926	25744726
+52
+
+chain	1584	8	146364022	+	85964393	85964443	chr1	247249719	-	57954630	57954680	20174423
+50
+
+chain	1470	8	146364022	+	85911121	85911160	chr15	100338915	+	92120615	92120654	21684489
+39
+
+chain	1463	8	146364022	+	942731	942785	chr8	146274826	+	930679	930733	5019737
+54
+
+chain	1440	8	146364022	+	85911043	85911098	chr1	247249719	-	141715465	141715520	4313974
+55
+
+chain	1426	8	146364022	+	85978253	85978320	chr2	242951149	-	208172805	208172872	22624190
+67
+
+chain	1403	8	146364022	+	85928837	85929028	chr18	76117153	+	39707440	39707631	2816562
+52	99	99
+40
+
+chain	1344	8	146364022	+	85907124	85907170	chr12	132349534	+	45103963	45104009	16171151
+46
+
+chain	1332	8	146364022	+	85927450	85927503	chr1	247249719	-	29234742	29234795	3133635
+53
+
+chain	1287	8	146364022	+	85907361	85907411	chr1	247249719	-	78547145	78547195	4245040
+50
+
+chain	1276	8	146364022	+	85927323	85927376	chr4	191273063	-	93337200	93337253	2720957
+53
+
+chain	1269	8	146364022	+	85908257	85908286	chr9	140273252	-	124490379	124490408	3695355
+29
+
+chain	1238	8	146364022	+	85978601	85978678	chr9	140273252	-	23294193	23294270	19053025
+77
+
+chain	1193	8	146364022	+	144455743	144455792	chr8	146274826	+	144526504	144526553	26679478
+49
+
+chain	1175	8	146364022	+	12087452	12087488	chr11	134452384	-	63301652	63301688	1994288
+36
+
+chain	1137	8	146364022	+	85909119	85909164	chr2	242951149	+	35848313	35848358	13461114
+45
+
+chain	1067	chr8	146364022	+	86832385	86832437	chr8_random	943810	-	358237	358289	86749
+52
+
+chain	1048	8	146364022	+	86824709	86824734	chr8	146274826	+	86857705	86857730	2636
+25
+
+chain	1045	8	146364022	+	85911001	85911043	chr15	100338915	-	40210675	40210717	4055996
+42
+
+chain	1028	8	146364022	+	85910323	85910373	chr4	191273063	+	26203887	26203937	5050480
+50
+
+chain	1020	8	146364022	+	85924694	85924736	chr3	199501827	+	1701599	1701641	4262142
+42
+
+chain	1005	8	146364022	+	85977261	85977320	chr10	135374737	+	45388722	45388781	14596230
+59
+
+chain	998	8	146364022	+	85908847	85908872	chr4	191273063	+	183519567	183519592	8543079
+25
+
+chain	985	8	146364022	+	85918576	85918627	chr3	199501827	-	21820872	21820923	24828426
+51
+
+chain	981	8	146364022	+	144744094	144744133	chr8	146274826	+	144814821	144814860	14840226
+39
+
+chain	922	8	146364022	+	85918981	85919046	chrX	154913754	-	100261670	100261735	22334691
+65
+
+chain	912	8	146364022	+	85964449	85964513	chr6	170899992	+	131272389	131272453	24950513
+64
+
+chain	888	8	146364022	+	85915710	85915739	chr9	140273252	+	12069456	12069485	13568361
+29
+
+chain	867	8	146364022	+	85976220	85976271	chrX	154913754	-	36573362	36573413	23586363
+51
+
+chain	857	8	146364022	+	86832445	86832471	chr8	146274826	+	86747431	86747457	7742
+26
+
+chain	802	8	146364022	+	85978516	85978572	chr3	199501827	+	80520031	80520087	22639668
+56
+
+chain	801	8	146364022	+	85911160	85911249	chr16	88827254	+	31611661	31611750	16482423
+89
+
+chain	785	8	146364022	+	85917259	85917324	chr5	180857866	-	163179499	163179564	25049793
+65
+
+chain	721	8	146364022	+	85926739	85926765	chr18	76117153	+	15364211	15364237	2792298
+26
+
+chain	647	8	146364022	+	85918645	85918703	chr11	134452384	-	90657004	90657062	25582649
+58
+
+chain	612	8	146364022	+	941818	941867	chr8	146274826	+	930360	930409	12502809
+49
+
+chain	596	8	146364022	+	85976593	85979111	chrX	154913754	-	42670843	42673368	13030869
+53	2388	2395
+77
+
+chain	568	8	146364022	+	85966335	85966385	chrX	154913754	+	36275879	36275929	27751459
+50
+
+chain	474	8	146364022	+	85917714	85917772	chr1	247249719	+	62707004	62707062	26279221
+58
+
+chain	396	8	146364022	+	85977502	85977572	chrX	154913754	-	138803117	138803187	17501406
+70
+
+chain	369	8	146364022	+	85976646	85976678	chr7	158821424	+	51906674	51906706	15299893
+32
+
+chain	360	8	146364022	+	85980297	85980349	chr12	132349534	-	124024481	124024533	24774043
+52
+
+chain	337	8	146364022	+	85981293	85981372	chr1	247249719	-	152445011	152445090	12777550
+79
+
+chain	328	8	146364022	+	85976447	85976474	chr2	242951149	-	99982783	99982810	22051776
+27
+
+chain	310	8	146364022	+	85976849	85976905	chr3	199501827	-	69459686	69459742	25770085
+56
+
+chain	286	8	146364022	+	85979114	85979170	chr7	158821424	-	11181572	11181628	19756881
+56
+
+chain	232	8	146364022	+	85978010	85978057	chr1	247249719	+	108819891	108819938	19586297
+47
+
+chain	3680035	chr8_gl000196_random	38914	+	0	38914	chr8_random	943810	+	643258	682172	798
+38914
+
+chain	3554032	chr8_gl000197_random	37175	+	0	37175	chr8_random	943810	+	493047	530222	826
+37175
+
+chain	11336430536	9	141213431	+	10000	141153431	chr9	140273252	+	0	140273252	13
+189075	17	17
+39464594	50000	50000
+261110	50000	50000
+208233	50000	50000
+142805	50000	50000
+464507	50000	50000
+152873	50000	50000
+172579	50000	50000
+799200	4	0
+398958	50000	50000
+549743	100000	50000
+632871	50000	50000
+680077	50000	50000
+181647	50000	50000
+291910	100000	50000
+465318	50000	50000
+350909	50000	50000
+194609	100000	50000
+370337	176	0
+128581	100047	50047
+157499	18150000	18100000
+450681	50000	50000
+223855	50000	50000
+162441	50000	50000
+159539	50000	50000
+199148	50000	50000
+194491	100000	50000
+158462	150000	50000
+471702	150000	50000
+376183	150000	50000
+174765	150000	50000
+289439	50000	50000
+682157	50000	50000
+158187	100000	50000
+187806	50000	50000
+178933	100000	50000
+21507948	100000	50000
+85380	150000	50000
+834971	0	1
+39559293	150000	100000
+3818133	50000	200000
+2075804	50000	30000
+1936434
+
+chain	1179	9	141213431	+	46931376	46931552	chr9	140273252	-	98415895	98416071	50
+176
+
+chain	443	9	141213431	+	47160133	47160180	chr9	140273252	-	72994158	72994205	112
+47
+
+chain	8504653	chr9_gl000198_random	90085	+	0	90085	chr9_random	1146434	+	526031	616116	387
+90085
+
+chain	10524551	chr9_gl000199_random	169874	+	0	146316	chr9_random	1146434	+	903151	1075994	305
+35956	981	11726
+149	118	118
+212	21	21
+101	50	50
+98	0	8841
+196	126	126
+211	19	19
+115	44	44
+76	72	72
+100	9	9
+92	107	107
+86	1193	169
+50	168	18105
+488	0	1
+10599	1	1
+42	1	0
+8869	101	101
+10239	51	51
+179	500	502
+1131	0	1
+12346	0	18932
+463	15	15
+739	1	1
+64	1	1
+2323	0	1
+755	1	1
+188	1	1
+245	0	2
+10316	4	5
+18	1	1
+8496	15	15
+1065	3	3
+49	1	1
+67	1	1
+24	1	1
+150	15	15
+2700	5110	0
+46	11735	0
+376	5	5
+2019	342	0
+1220	1192	0
+221	37	37
+60	21	21
+334	6678	50
+235	1381	27
+52	2571	21
+62
+
+chain	3014585	chr9_gl000199_random	169874	+	136786	169869	chr9_random	1146434	+	939452	971857	944
+79	683	6
+4467	235	235
+1381	52	52
+786	1	1
+38	1	0
+29	1	1
+1715	62	62
+1332	14	14
+6821	1	1
+55	1	1
+15329
+
+chain	306268	chr9_gl000199_random	169874	+	114056	136743	chr9_random	1146434	+	1030711	1052467	1210
+785	60	60
+2828	46	46
+527	6	352
+63	378	378
+514	181	181
+824	72	72
+329	1	1
+35	1	1
+68	1	1
+37	1	1
+3228	135	132
+81	325	325
+52	391	391
+60	10252	2341
+243	179	691
+73	42	42
+155	0	1190
+24	0	1871
+442	0	3064
+2	95	95
+151
+
+chain	178734	chr9_gl000199_random	169874	+	38939	136592	chr9_random	1146434	+	940083	990000	1006
+27	31954	13752
+34	77	77
+166	43	43
+110	68	68
+2	41253	31459
+196	349	7
+48	5105	0
+83	14	14
+62	11	11
+208	514	2
+181	824	144
+72	3917	172
+325	52	52
+391	9096	1608
+467	1909	41
+95
+
+chain	108146	chr9_gl000199_random	169874	+	35956	37588	chr9_random	1146434	+	1073965	1075597	311529
+981	149	149
+118	334	334
+50
+
+chain	94079	chr9_gl000199_random	169874	+	125187	127738	chr9_random	1146434	+	934627	937178	173754
+2551
+
+chain	56396	chr9_gl000199_random	169874	+	38488	39821	chr9_random	1146434	+	1072584	1073917	324037
+57	225	225
+83	113	113
+855
+
+chain	37331	chr9_gl000199_random	169874	+	127738	129141	chr9_random	1146434	+	1073395	1074798	197032
+1403
+
+chain	15154	chr9_gl000199_random	169874	+	133472	133633	chr9_random	1146434	-	103942	104103	2035052
+161
+
+chain	14222	chr9_gl000199_random	169874	+	39821	40265	chr9_random	1146434	+	982531	990446	140426
+290	71	7542
+83
+
+chain	13688	chr9_gl000199_random	169874	+	112619	134922	chr9_random	1146434	+	997840	1005340	1760
+54	480	138
+65	48	48
+86	0	1
+62	27	27
+193	20460	5998
+27	467	467
+2	15	15
+59	221	221
+37
+
+chain	12407	chr9_gl000199_random	169874	+	60350	137506	chr9_random	1146434	+	944493	957004	1913
+35	10569	695
+47	196	196
+40	113	113
+68	62256	9695
+367	1799	779
+34	1232	42
+400
+
+chain	5910	chr9_gl000199_random	169874	+	112953	113153	chr9_random	1146434	+	1036251	1036451	100700
+200
+
+chain	4997	chr9_gl000199_random	169874	+	124080	124135	chr9_random	1146434	+	959057	959112	19926960
+55
+
+chain	4162	chr9_gl000199_random	169874	+	113634	113846	chr9_random	1146434	+	995454	995665	201802
+27	40	39
+145
+
+chain	3441	chr9_gl000199_random	169874	+	37915	38008	chr9_random	1146434	+	950621	950714	48386
+93
+
+chain	3360	chr9_gl000199_random	169874	+	129226	129424	chr9_random	1146434	+	996412	996610	9342
+198
+
+chain	3255	chr9_gl000199_random	169874	+	70690	70741	chr9_random	1146434	+	1012726	1012777	23586
+51
+
+chain	3031	chr9_gl000199_random	169874	+	112869	137060	chr9_random	1146434	+	964682	969139	3960
+84	23929	4195
+178
+
+chain	2784	chr9_gl000199_random	169874	+	60406	60450	chr9_random	1146434	+	1000736	1000780	8481
+44
+
+chain	2406	chr9_gl000199_random	169874	+	38361	40328	chr9_random	1146434	+	940183	941126	6867
+36	1868	844
+63
+
+chain	2091	chr9_gl000199_random	169874	+	135580	135759	chr9_random	1146434	+	1043989	1044168	130849
+179
+
+chain	1790	chr9_gl000199_random	169874	+	113899	113969	chr9	140273252	-	71272426	71272496	22178754
+70
+
+chain	1047	chr9_gl000199_random	169874	+	114872	114901	chr9_random	1146434	+	1035274	1035303	118930
+29
+
+chain	1014	chr9_gl000199_random	169874	+	129141	129510	chr9_random	1146434	+	949663	949862	115384
+82	201	31
+86
+
+chain	827	chr9_gl000199_random	169874	+	125159	125187	chr9	140273252	-	71272290	71272318	10194134
+28
+
+chain	754	chr9_gl000199_random	169874	+	136743	136786	chr9_random	1146434	-	170925	170968	528799
+43
+
+chain	683	chr9_gl000199_random	169874	+	134041	134094	chr9_random	1146434	+	1025518	1025571	412663
+53
+
+chain	494	chr9_gl000199_random	169874	+	71001	71031	chr9_random	1146434	+	983095	983125	1059560
+30
+
+chain	444	chr9_gl000199_random	169874	+	133651	133674	chr9_random	1146434	+	1066888	1066911	84972
+23
+
+chain	309	chr9_gl000199_random	169874	+	137506	137547	chr9_random	1146434	+	967717	967758	659942
+41
+
+chain	254	chr9_gl000199_random	169874	+	125119	125159	chr9_random	1146434	+	1071966	1072006	1499804
+40
+
+chain	241	chr9_gl000199_random	169874	+	137060	137086	chr9_random	1146434	+	965055	965081	39489
+26
+
+chain	190	chr9_gl000199_random	169874	+	124136	124176	chr9_random	1146434	+	947206	947246	772655
+40
+
+chain	17692629	chr9_gl000200_random	187035	+	0	187035	chr9_random	1146434	+	666116	853151	157
+187035
+
+chain	3482851	chr9_gl000201_random	36148	+	0	36148	chr9_random	1146434	+	0	36148	835
+36148
+
+chain	1574309	MT	16571	+	0	16571	chrM	16571	+	0	16571	1542
+16571
+
+chain	15737781	chrUn_gl000211	166566	+	0	166566	chr22_random	257318	+	90752	257318	187
+166566
+
+chain	17750502	chrUn_gl000212	186858	+	0	186858	chr13_random	186858	+	0	186858	154
+186858
+
+chain	15269201	chrUn_gl000213	164239	+	0	164239	chr21	46944323	-	32900547	33064909	192
+4659	1	0
+8525	1	0
+592	12	11
+2258	2	0
+942	18	18
+7633	0	33
+6726	1	1
+49	4	4
+119	1	1
+127	6	0
+114	1	1
+1963	1	1
+856	0	1
+2836	1	0
+20	0	1
+262	6	6
+128	1	1
+22	1	1
+8105	14	0
+16	4	0
+1875	0	1
+8447	4	0
+157	10	10
+2207	0	1
+2729	0	2
+9463	1	0
+239	1	0
+17	2	0
+1990	3	0
+7559	3	2
+1342	1	1
+73	1	1
+1095	9	9
+57	1	1
+80	1	1
+290	16	16
+79	9	9
+151	4	4
+728	4	0
+580	4	0
+160	8	8
+184	1	1
+21	1	1
+3074	12	10
+471	6	6
+698	11	11
+338	0	3
+205	0	28
+1909	0	10
+508	1	1
+31	1	1
+847	1	2
+271	0	4
+337	1	1
+31	3	0
+355	1	1
+61	1	1
+237	1	1
+60	24	0
+307	0	4
+941	1	1
+37	5	0
+338	31	24
+563	0	644
+637	12	12
+369	1	1
+26	1	1
+136	630	0
+374	1	1
+31	1	1
+375	1	1
+48	1	1
+2210	1	1
+35	0	1
+1039	19	1
+53	1	1
+270	8	6
+337	1	1
+40	1	1
+2174	6	6
+841	1	1
+29	1	1
+1975	0	10
+37	1	1
+703	0	60
+223	15	15
+1844	0	4
+394	3	0
+63	1	1
+34	1	1
+121	1	1
+25	4	10
+12	12	0
+2694	8	8
+100	2	0
+2952	1	1
+27	1	1
+1508	0	4
+2169	16	16
+48	1	0
+894	9	9
+310	0	1
+2288	0	2
+4522	0	4
+32	1	1
+3231	0	6
+2045	1	1
+44	1	1
+955	9	9
+345	6	6
+129	1	1
+19	1	1
+167	1	0
+333	2	0
+716	22	22
+1384	1	0
+189	1	1
+23	0	28
+1452	1	1
+28	1	1
+1661	1	4
+496	18	17
+141	1	1
+44	1	1
+1971	1	6
+103	1	1
+47	1	1
+662	6	0
+318	0	5
+935	1	1
+47	1	1
+220	1	1
+36	1	1
+815	1	0
+49	1	0
+224	3	4
+86	1	1
+47	1	1
+683	2	2
+42	1	1
+1493	0	1
+373	0	1
+454	0	2
+179	0	12
+639	0	5
+616	66	81
+613	0	1
+198	8	11
+1412	4	0
+604	4	0
+1065	5	0
+3599	1	1
+44	1	1
+311	4	0
+302	1	0
+1762	31	31
+555
+
+chain	19447	chrUn_gl000213	164239	+	98731	98946	chr21	46944323	-	32999281	32999496	6410578
+102	6	6
+107
+
+chain	5115	chrUn_gl000213	164239	+	98535	98731	chr15	100338915	+	19297082	19297917	3190124
+68	49	688
+79
+
+chain	918427	chrUn_gl000214	137718	+	80069	90748	chr1	247249719	-	105489797	105500468	3815
+119	1	1
+25	1	1
+201	5	5
+65	5	5
+139	1	1
+69	1	1
+150	1	1
+67	4	4
+380	6	0
+73	10	10
+167	10	10
+63	1	1
+23	1	1
+369	4	4
+43	1	1
+235	1	1
+83	6	6
+99	1	1
+91	1	1
+116	14	14
+488	3	3
+47	1	0
+11	1	1
+216	1	1
+23	1	1
+84	1	1
+71	1	1
+549	1	1
+22	1	1
+146	1	1
+102	1	1
+104	1	1
+80	1	1
+59	1	1
+19	1	1
+402	1	1
+39	1	1
+284	1	1
+33	1	1
+161	4	4
+34	1	1
+125	1	1
+20	1	1
+472	1	1
+19	1	1
+228	23	23
+425	1	1
+99	1	1
+266	1	1
+42	1	1
+54	1	1
+62	1	1
+228	4	2
+85	6	6
+68	1	1
+242	1	1
+167	1	1
+33	1	1
+133	24	24
+773	7	7
+379	0	1
+218	62	62
+81	1	1
+37	1	1
+364	1	1
+29	1	1
+234
+
+chain	143213	chrUn_gl000214	137718	+	129234	137707	chr4	191273063	-	142244722	142253930	901087
+227	142	142
+52	32	32
+60	159	159
+56	5	5
+135	69	69
+183	83	83
+78	152	152
+70	161	161
+102	13	13
+186	9	9
+127	123	123
+78	241	241
+116	4845	5724
+91	242	98
+110	65	65
+64	13	13
+72	181	181
+131
+
+chain	112581	chrUn_gl000214	137718	+	116800	119267	chr4	191273063	+	48987510	48989977	1137439
+144	225	225
+135	141	141
+87	10	10
+130	173	173
+90	147	147
+57	103	103
+70	22	22
+84	50	50
+113	26	26
+103	37	37
+69	102	102
+127	4	4
+58	73	73
+87
+
+chain	35731	chrUn_gl000214	137718	+	49713	50123	chr21_random	1679693	+	637667	638077	3744988
+55	5	5
+34	1	1
+315
+
+chain	33173	chrUn_gl000214	137718	+	125487	134177	chr1	247249719	-	105123947	105126634	1162767
+65	110	110
+58	32	32
+395	7	7
+90	6069	74
+68	8	0
+64	36	36
+114	56	56
+54	63	63
+58	137	137
+182	277	277
+54	21	21
+122	248	248
+52	190	190
+60
+
+chain	26395	chrUn_gl000214	137718	+	40302	40606	chr1	247249719	-	18749005	18749307	6333362
+57	1	0
+75	1	0
+112	1	1
+57
+
+chain	25884	chrUn_gl000214	137718	+	126321	126850	chr21_random	1679693	+	746615	747120	6569895
+87	97	73
+114	5	5
+50	118	118
+58
+
+chain	25524	chrUn_gl000214	137718	+	41463	41766	chr9	140273252	-	40046622	40046925	6760130
+54	7	7
+122	4	4
+116
+
+chain	25177	chrUn_gl000214	137718	+	122978	125190	chr21_random	1679693	-	928041	930254	1258444
+118	228	229
+72	288	288
+139	44	44
+185	600	600
+136	37	37
+126	58	58
+181
+
+chain	23478	chrUn_gl000214	137718	+	136191	136535	chr4	191273063	+	48976406	48976750	8004925
+183	83	83
+78
+
+chain	20443	chrUn_gl000214	137718	+	41766	42878	chr3	199501827	+	629423	630533	8757399
+9	908	906
+118	25	25
+52
+
+chain	20379	chrUn_gl000214	137718	+	135162	135774	chr21_random	1679693	-	927923	928535	1491304
+50	44	44
+225	152	152
+141
+
+chain	18931	chrUn_gl000214	137718	+	44528	44730	chr10	135374737	-	38544783	38544985	11331455
+202
+
+chain	18826	chrUn_gl000214	137718	+	43343	43562	chr2	242951149	-	53551644	53551863	11416331
+110	1	1
+31	1	1
+76
+
+chain	18670	chrUn_gl000214	137718	+	90865	91063	chr1	247249719	-	105065042	105065240	11545618
+198
+
+chain	17773	chrUn_gl000214	137718	+	131919	132224	chr1	247249719	-	105124387	105124692	2973977
+225	10	10
+70
+
+chain	16259	chrUn_gl000214	137718	+	112825	112997	chr2	242951149	+	132826168	132826340	13778307
+172
+
+chain	16179	chrUn_gl000214	137718	+	117367	119564	chr1	247249719	+	142120582	142122781	1230197
+57	994	995
+43	121	121
+25	103	103
+37	69	69
+76	567	568
+105
+
+chain	14745	chrUn_gl000214	137718	+	40137	40293	chr18	76117153	+	36159000	36159156	15342897
+156
+
+chain	14511	chrUn_gl000214	137718	+	35480	35726	chr21_random	1679693	+	599809	599984	15605110
+107	80	9
+59
+
+chain	13694	chrUn_gl000214	137718	+	21320	21487	chrX	154913754	-	125740203	125740370	16565517
+81	11	11
+75
+
+chain	13486	chrUn_gl000214	137718	+	6106	6250	chr5	180857866	+	84443323	84443467	16839883
+144
+
+chain	13485	chrUn_gl000214	137718	+	18381	18548	chrX	154913754	+	88818181	88818344	16841154
+59	4	0
+49	4	4
+51
+
+chain	12687	chrUn_gl000214	137718	+	41058	41208	chr4	191273063	-	138230980	138231130	9286530
+62	5	5
+83
+
+chain	12516	chrUn_gl000214	137718	+	121124	121344	chr4	191273063	+	48979662	48979882	18214722
+66	74	74
+80
+
+chain	12053	chrUn_gl000214	137718	+	40633	40761	chrX	154913754	+	112045399	112045527	18908316
+128
+
+chain	11633	chrUn_gl000214	137718	+	43977	44114	chr4	191273063	-	11125034	11125171	12115615
+68	9	9
+60
+
+chain	11343	chrUn_gl000214	137718	+	39886	40006	chr13	114142980	+	66998338	66998458	20107936
+120
+
+chain	10884	chrUn_gl000214	137718	+	18108	18254	chr7	158821424	-	131367688	131367833	20945231
+55	19	18
+72
+
+chain	10521	chrUn_gl000214	137718	+	42241	42602	chr8	146274826	-	25959812	25960177	13454333
+84	222	226
+55
+
+chain	10411	chrUn_gl000214	137718	+	45055	45186	chr20	62435964	+	7050253	7050384	21896014
+54	12	12
+65
+
+chain	10343	chrUn_gl000214	137718	+	8804	8914	chrY	57772954	+	22287260	22287370	22043563
+110
+
+chain	9757	chrUn_gl000214	137718	+	19458	19875	chr3	199501827	-	187590477	187590901	23376485
+52	295	302
+70
+
+chain	9700	chrUn_gl000214	137718	+	39692	39809	chrX	154913754	-	41279737	41279854	23514677
+52	4	4
+61
+
+chain	9578	chrUn_gl000214	137718	+	45502	45617	chrX	154913754	+	43420636	43420751	23808291
+55	5	5
+55
+
+chain	7894	chrUn_gl000214	137718	+	124390	125487	chr4	191273063	-	142252912	142254012	6167993
+130	754	757
+69	123	123
+21
+
+chain	7612	chrUn_gl000214	137718	+	129655	137576	chr1	247249719	+	142120436	142122192	1126110
+32	89	89
+59	44	44
+27	862	716
+54	6116	97
+123	138	138
+47	149	149
+97	35	35
+49
+
+chain	7146	chrUn_gl000214	137718	+	43209	43286	chr18	76117153	-	9582204	9582281	16185526
+77
+
+chain	6775	chrUn_gl000214	137718	+	131335	131918	chr4	191273063	-	142062211	142062794	1233528
+62	218	218
+89	189	189
+25
+
+chain	6321	chrUn_gl000214	137718	+	44440	44513	chr1	247249719	+	157810312	157810385	13757396
+56	5	5
+12
+
+chain	5727	chrUn_gl000214	137718	+	119564	119897	chr4	191273063	-	142062730	142063063	7342832
+77	196	196
+60
+
+chain	5584	chrUn_gl000214	137718	+	136603	136661	chr4	191273063	+	48976819	48976877	31707162
+58
+
+chain	5192	chrUn_gl000214	137718	+	41407	41463	chr4	191273063	+	95935104	95935160	21196855
+56
+
+chain	4895	chrUn_gl000214	137718	+	6041	6105	chr11	134452384	+	65843917	65843981	20155275
+64
+
+chain	4869	chrUn_gl000214	137718	+	43083	43135	chr9	140273252	-	106613347	106613399	21934699
+52
+
+chain	4480	chrUn_gl000214	137718	+	42602	42659	chr7	158821424	-	39929511	39929568	12681275
+57
+
+chain	4078	chrUn_gl000214	137718	+	41235	41291	chrX	154913754	-	134405062	134405118	18412789
+56
+
+chain	4015	chrUn_gl000214	137718	+	42902	42960	chr10	135374737	+	54220968	54221026	24474909
+58
+
+chain	3895	chrUn_gl000214	137718	+	40957	41057	chr14	106368585	+	31140172	31140272	6582169
+100
+
+chain	3738	chrUn_gl000214	137718	+	42125	42173	chrX	154913754	+	103679820	103679868	22522957
+48
+
+chain	3537	chrUn_gl000214	137718	+	136028	136122	chr4	191273063	+	48976243	48976337	4189785
+94
+
+chain	3097	chrUn_gl000214	137718	+	17979	18039	chrX	154913754	-	102020287	102020347	24003938
+60
+
+chain	2977	chrUn_gl000214	137718	+	126408	126469	chr1	247249719	-	105124849	105124910	6601664
+61
+
+chain	2968	chrUn_gl000214	137718	+	41775	41809	chr8	146274826	+	100416036	100416070	11606659
+34
+
+chain	2831	chrUn_gl000214	137718	+	137492	137527	chr4	191273063	+	48977417	48977452	2940885
+17	9	9
+9
+
+chain	2572	chrUn_gl000214	137718	+	44291	44369	chr11	134452384	-	117952414	117952492	17845944
+78
+
+chain	2345	chrUn_gl000214	137718	+	42033	42103	chr4	191273063	-	122527078	122527148	13059103
+70
+
+chain	2276	chrUn_gl000214	137718	+	43135	43209	chr1	247249719	+	86869873	86869947	13860931
+74
+
+chain	1770	chrUn_gl000214	137718	+	44144	44227	chr3	199501827	+	24100092	24100175	18271654
+83
+
+chain	1506	chrUn_gl000214	137718	+	36174	36256	chr1	247249719	-	105422371	105422453	16376759
+82
+
+chain	1502	chrUn_gl000214	137718	+	43875	43977	chr9	140273252	+	102510935	102511037	11228177
+102
+
+chain	1456	chrUn_gl000214	137718	+	130737	130768	chr21_random	1679693	-	929809	929840	22601085
+31
+
+chain	1365	chrUn_gl000214	137718	+	125246	125274	chr21_random	1679693	-	930310	930338	15151243
+28
+
+chain	1098	chrUn_gl000214	137718	+	42962	43013	chr6	170899992	-	83239423	83239474	24355258
+51
+
+chain	931	chrUn_gl000214	137718	+	41878	41928	chr11	134452384	-	41659375	41659425	15038916
+50
+
+chain	888	chrUn_gl000214	137718	+	45207	45259	chr11	134452384	+	93610909	93610961	21407350
+52
+
+chain	856	chrUn_gl000214	137718	+	119897	119930	chr19	63811651	-	14205840	14205873	23032647
+33
+
+chain	766	chrUn_gl000214	137718	+	127016	127090	chr19	63811651	-	14200495	14200569	19831992
+74
+
+chain	676	chrUn_gl000214	137718	+	18987	19049	chr11	134452384	+	106173710	106173772	23556763
+62
+
+chain	650	chrUn_gl000214	137718	+	132603	132659	chr21_random	1679693	+	746889	746945	1349757
+56
+
+chain	423	chrUn_gl000214	137718	+	20746	20796	chr2	242951149	-	226029097	226029147	25845790
+50
+
+chain	16237347	chrUn_gl000215	172545	+	28	172526	chr21	46944323	+	13950000	14122426	177
+3255	0	4
+29034	1	0
+5104	4	0
+10299	0	8
+14263	11	11
+94	6	0
+113	107	1
+75	1	1
+91	1	1
+24	1	1
+6681	0	33
+907	41	41
+7674	2	0
+2274	12	11
+563	0	1
+8540	1	0
+12525	1	1
+36	1	1
+25408	0	12
+3782	0	2
+694	85	67
+996	1	3
+1425	12	12
+1827	1	1
+21	1	1
+941	13	13
+2073	0	8
+28	1	1
+506	0	2
+1227	1	0
+1108	2	2
+28	1	1
+396	1	0
+253	14	14
+184	1	1
+49	1	1
+2962	1	1
+45	4	0
+1510	19	19
+2709	25	25
+1068	0	4
+836	1	0
+1871	0	1
+579	4	0
+60	14	14
+2466	27	27
+1450	1	0
+19	1	1
+618	6	6
+2880	1	0
+450	0	2
+27	0	4
+4576	1	1
+20	1	1
+789	0	1
+721	14	14
+1438	35	31
+1381	1	1
+18	1	1
+73	12	12
+195	1	1
+35	1	1
+708
+
+chain	40526	chrUn_gl000216	172294	+	149263	155793	chr18	76117153	-	76016375	76018189	3221814
+113	325	326
+78	431	292
+71	14	14
+107	786	375
+37	69	0
+81	2953	216
+58	1361	0
+46
+
+chain	27660	chrUn_gl000216	172294	+	75671	76099	chr20	62435964	-	33142597	33142960	5774439
+63	0	10
+32	5	0
+14	10	0
+50	35	0
+20	10	0
+56	5	0
+53	21	11
+54
+
+chain	27279	chrUn_gl000216	172294	+	130292	130617	chrX	154913754	+	63390360	63390685	5931924
+69	12	12
+78	1	1
+165
+
+chain	17860	chrUn_gl000216	172294	+	130000	130214	chr4	191273063	+	73778471	73778685	12240737
+58	12	12
+144
+
+chain	16947	chrUn_gl000216	172294	+	147288	147775	chr18	76117153	-	76016450	76016937	13094679
+76	288	288
+123
+
+chain	13816	chrUn_gl000216	172294	+	129031	129176	chr8	146274826	-	38602125	38602270	16419487
+145
+
+chain	12180	chrUn_gl000216	172294	+	145189	145506	chrY	57772954	+	11928279	11928596	18712695
+46	95	95
+51	66	66
+59
+
+chain	11701	chrUn_gl000216	172294	+	158739	158864	chr18	76117153	+	99277	99402	19495084
+125
+
+chain	11637	chrUn_gl000216	172294	+	171754	172194	chrY	57772954	+	11932706	11933147	19600583
+53	299	300
+88
+
+chain	11521	chrUn_gl000216	172294	+	129787	129947	chr6	170899992	+	5983639	5983799	19799726
+64	26	26
+70
+
+chain	10625	chrUn_gl000216	172294	+	164963	165111	chr18	76117153	+	100265	100413	21456050
+73	25	25
+50
+
+chain	10470	chrUn_gl000216	172294	+	131591	131702	chrX	154913754	+	36583233	36583344	21778508
+111
+
+chain	10288	chrUn_gl000216	172294	+	131963	132072	chr3	199501827	-	99262429	99262538	22162166
+109
+
+chain	9778	chrUn_gl000216	172294	+	141853	142019	chr18	76117153	-	76016600	76016834	23327029
+64	49	117
+53
+
+chain	9609	chrUn_gl000216	172294	+	135933	137341	chrY	57772954	+	11926871	11928279	23735609
+56	647	1260
+56	613	0
+36
+
+chain	9489	chrUn_gl000216	172294	+	169302	169609	chrY	57772954	+	11921023	11921330	24024953
+52	191	191
+64
+
+chain	9460	chrUn_gl000216	172294	+	132170	132290	chrY	57772954	+	11935643	11935763	24098583
+50	10	10
+60
+
+chain	9059	chrUn_gl000216	172294	+	169179	169274	chrY	57772954	-	366511	366606	24861253
+95
+
+chain	8863	chrUn_gl000216	172294	+	133271	135681	chrY	57772954	-	372628	372853	25150456
+61	2277	92
+72
+
+chain	8329	chrUn_gl000216	172294	+	1479	1877	chr4	191273063	-	141929935	141931620	25915977
+67	278	1565
+53
+
+chain	8155	chrUn_gl000216	172294	+	150573	151188	chrY	57772954	-	377413	378366	22301630
+51	559	897
+5
+
+chain	8086	chrUn_gl000216	172294	+	168370	168455	chr18	76117153	-	76017788	76017873	26288571
+85
+
+chain	7777	chrUn_gl000216	172294	+	34186	34268	chr1	247249719	-	24981278	24981360	26771397
+82
+
+chain	6822	chrUn_gl000216	172294	+	132393	132465	chrY	57772954	-	376390	376462	28544596
+72
+
+chain	6622	chrUn_gl000216	172294	+	9240	9310	chr10	135374737	+	41683434	41683504	28988878
+70
+
+chain	6573	chrUn_gl000216	172294	+	130631	130733	chr5	180857866	-	72032622	72032724	12023329
+102
+
+chain	6476	chrUn_gl000216	172294	+	146529	146597	chr18	76117153	-	76017808	76017876	29355811
+68
+
+chain	6422	chrUn_gl000216	172294	+	8523	8591	chr4	191273063	+	48829234	48829302	29489285
+68
+
+chain	6384	chrUn_gl000216	172294	+	148442	148586	chrY	57772954	-	378355	378430	29582296
+29	69	0
+46
+
+chain	6003	chrUn_gl000216	172294	+	133483	133546	chrY	57772954	-	370776	370839	30561430
+63
+
+chain	5985	chrUn_gl000216	172294	+	11844	11907	chr4	191273063	+	48811176	48811239	30589131
+63
+
+chain	5885	chrUn_gl000216	172294	+	151788	151850	chrY	57772954	-	366263	366325	30854068
+62
+
+chain	5721	chrUn_gl000216	172294	+	136853	136913	chrY	57772954	-	372235	372295	31317120
+60
+
+chain	5667	chrUn_gl000216	172294	+	19071	19131	chr4	191273063	+	48811263	48811323	31460984
+60
+
+chain	5339	chrUn_gl000216	172294	+	145664	145720	chrY	57772954	+	11941006	11941062	32420221
+56
+
+chain	5322	chrUn_gl000216	172294	+	130963	131035	chr5	180857866	-	36043748	36043820	20305124
+72
+
+chain	5257	chrUn_gl000216	172294	+	158216	158271	chr18	76117153	+	96100	96155	32682417
+55
+
+chain	5221	chrUn_gl000216	172294	+	7155	7210	chr4	191273063	+	48836505	48836560	32772522
+55
+
+chain	5121	chrUn_gl000216	172294	+	15141	15195	chr4	191273063	+	48847759	48847813	33093239
+54
+
+chain	5012	chrUn_gl000216	172294	+	26593	26646	chr21	46944323	-	37095349	37095402	33456608
+53
+
+chain	4930	chrUn_gl000216	172294	+	37276	37328	chr1	247249719	-	24981705	24981757	33717061
+52
+
+chain	4884	chrUn_gl000216	172294	+	137193	137244	chrY	57772954	-	377416	377467	33922210
+51
+
+chain	4821	chrUn_gl000216	172294	+	20849	20900	chr20	62435964	-	33142732	33142783	34122269
+51
+
+chain	4766	chrUn_gl000216	172294	+	152958	153008	chr18	76117153	-	76017195	76017245	34319410
+50
+
+chain	4757	chrUn_gl000216	172294	+	155624	155674	chr18	76117153	-	76018020	76018070	34342345
+50
+
+chain	2863	chrUn_gl000216	172294	+	172194	172224	chrY	57772954	+	11925069	11925099	19922357
+30
+
+chain	2829	chrUn_gl000216	172294	+	131145	131290	chr12	132349534	+	50244945	50245090	12112131
+51	88	88
+6
+
+chain	2529	chrUn_gl000216	172294	+	129176	129203	chr9	140273252	-	119219512	119219539	22134781
+27
+
+chain	2341	chrUn_gl000216	172294	+	131196	131233	chr3	199501827	-	98572452	98572489	18288091
+37
+
+chain	2151	chrUn_gl000216	172294	+	131290	131397	chr7	158821424	-	127191925	127192032	12067691
+107
+
+chain	2108	chrUn_gl000216	172294	+	149377	153105	chrY	57772954	+	11933439	11934497	20496839
+67	3022	286
+50	506	572
+83
+
+chain	1614	chrUn_gl000216	172294	+	130868	130925	chr3	199501827	-	79251115	79251172	16953843
+57
+
+chain	1538	chrUn_gl000216	172294	+	76099	76129	chr21	46944323	-	37102976	37103006	11762953
+30
+
+chain	694	chrUn_gl000216	172294	+	135555	135593	chrY	57772954	-	377637	377675	25976788
+38
+
+chain	532	chrUn_gl000216	172294	+	153980	155370	chrY	57772954	-	378352	378449	22847936
+39	1293	0
+58
+
+chain	454	chrUn_gl000216	172294	+	863	915	chr4	191273063	+	48799453	48799505	31198348
+52
+
+chain	383	chrUn_gl000216	172294	+	153157	153210	chr18	76117153	-	76017394	76017447	29745290
+53
+
+chain	174	chrUn_gl000216	172294	+	138050	138103	chrY	57772954	+	11945950	11946003	28091780
+53
+
+chain	99	chrUn_gl000216	172294	+	11396	11447	chr20	62435964	-	33142766	33142817	31359773
+51
+
+chain	13777792	chrUn_gl000217	172149	+	23665	172149	chr21_random	1679693	-	1239693	1388121	218
+366	17	17
+766	1	0
+21	0	8
+60	2	0
+3460	4	0
+2511	2	0
+113	1	0
+1145	0	1
+931	1	1
+37	1	1
+107	13	13
+4657	1	1
+48	1	1
+2113	0	1
+574	10	0
+111	1	0
+49	1	1
+1025	3	0
+497	0	11
+154	5	0
+640	0	6
+1684	0	16
+300	1	0
+1527	0	6
+147	1	0
+718	18	0
+30	1	1
+1243	1	1
+16	1	1
+162	28	0
+401	0	11
+281	1	1
+27	1	1
+892	1	0
+45	1	1
+2501	0	26
+74	115	11
+2278	8	8
+1028	0	1
+756	7	7
+1386	1	0
+3286	40	0
+504	1	0
+989	1	1
+24	1	1
+123	36	37
+2057	0	26
+72	2	0
+945	1	1
+22	1	1
+1558	1	1
+43	2	0
+2083	22	0
+462	0	1
+86	1	1
+37	1	1
+1415	0	1
+22	0	1
+1139	24	25
+1775	11	11
+2714	1	1
+41	1	1
+4780	0	1
+352	1	1
+25	1	1
+171	1	0
+514	1	0
+2199	1	1
+48	1	1
+262	3	1
+2426	0	1
+502	0	2
+1043	1	1
+49	1	0
+3147	0	3
+4432	1	1
+17	1	1
+2420	1	0
+43	1	1
+1809	1	0
+15	1	1
+1710	0	34
+61	36	0
+119	0	2
+4683	1	1
+44	1	1
+58	23	0
+44	0	104
+50	98	0
+43	1	1
+214	1	41
+29	0	1
+4	6	13
+39	0	105
+122	1	1
+31	17	1
+69	234	6
+48	1	17
+40	1	1
+1306	2	0
+3089	0	1
+2059	1	1
+32	1	1
+137	1	4
+584	1	0
+2518	1	0
+480	0	4
+6	2	0
+22	8	0
+177	1	1
+29	1	1
+6728	0	1
+1945	0	2
+8972	11	11
+806	1	3
+3054	0	3
+649	0	4
+1956	1	3
+795	1	0
+16	1	1
+1498	1	1
+28	1	1
+3012	5	0
+238	0	5
+220	0	5
+441	0	31
+141	10	0
+57	5	0
+1652	1	0
+233	1	0
+855	1	0
+845	38	0
+395	0	38
+182	22	0
+494	0	139
+1699	1	1
+42	0	1
+2261	1	1
+33	1	1
+3400	1	1
+41	1	1
+2247	0	2
+46	4	0
+34	0	14
+1049	1	13
+223	1	1
+49	1	1
+746	1	1
+36	1	1
+3491	0	1
+528
+
+chain	29979	chrUn_gl000217	172149	+	0	388	chr9	140273252	-	70842853	70843241	4686196
+80	39	39
+172	1	1
+24	1	1
+71
+
+chain	18989	chrUn_gl000217	172149	+	8221	8418	chr12	132349534	-	39661230	39661427	11281819
+197
+
+chain	10175	chrUn_gl000217	172149	+	14880	15009	chr19	63811651	+	45504623	45504752	22420709
+57	12	12
+60
+
+chain	3003	chrUn_gl000217	172149	+	63765	63801	chr6	170899992	+	56559189	56559225	3519131
+36
+
+chain	15268007	chrUn_gl000218	161147	+	0	161147	chr4_random	842648	+	681501	842648	193
+161147
+
+chain	274326	chrUn_gl000219	179198	+	111203	114251	chr8	146274826	-	136639851	136643413	309026
+102	1	1
+45	1	1
+484	9	9
+416	19	537
+171	4	0
+45	1	1
+189	7	7
+1328	1	1
+25	1	1
+199
+
+chain	235925	chrUn_gl000219	179198	+	35758	40113	chr15	100338915	-	47328984	47333335	444051
+127	1	1
+284	1	1
+140	1	1
+133	1	1
+73	1	1
+89	1	1
+75	13	8
+90	1	1
+92	1	1
+53	1	1
+73	1	1
+71	137	137
+163	8	8
+63	55	55
+141	31	31
+188	97	97
+60	103	103
+177	192	193
+314	188	188
+58	236	236
+75	260	260
+62	155	155
+105	29	29
+135
+
+chain	46161	chrUn_gl000219	179198	+	66272	68851	chrX	154913754	-	104037210	104039793	2773810
+120	238	238
+52	281	281
+59	653	657
+101	247	247
+106	343	343
+50	27	27
+62	173	173
+67
+
+chain	39536	chrUn_gl000219	179198	+	161917	162706	chr3	199501827	+	46165513	46166302	3318717
+67	218	218
+170	33	33
+104	60	60
+51	4	4
+82
+
+chain	37284	chrUn_gl000219	179198	+	19843	20929	chr8	146274826	+	98123209	98124295	3557690
+51	99	100
+128	134	134
+52	226	225
+160	168	168
+68
+
+chain	28967	chrUn_gl000219	179198	+	161273	161605	chr11	134452384	-	120964606	120964939	5150829
+171	2	3
+60	3	3
+96
+
+chain	28762	chrUn_gl000219	179198	+	6734	7878	chr3	199501827	-	92709198	92710343	5264432
+50	316	316
+83	67	67
+64	228	228
+51	85	86
+50	65	65
+85
+
+chain	21234	chrUn_gl000219	179198	+	175633	175875	chr1	247249719	-	2003467	2003709	9514914
+86	1	1
+40	1	1
+114
+
+chain	19234	chrUn_gl000219	179198	+	161066	161917	chr3	199501827	-	120235323	120237534	3582834
+110	737	2097
+4
+
+chain	14579	chrUn_gl000219	179198	+	21180	21751	chr1	247249719	-	137161846	137162418	6911796
+101	255	256
+2	163	163
+50
+
+chain	14519	chrUn_gl000219	179198	+	21064	21625	chr8	146274826	-	24167411	24167976	5552170
+59	415	419
+87
+
+chain	12254	chrUn_gl000219	179198	+	20707	20861	chr10	135374737	-	130087649	130087801	7386312
+11	3	1
+47	1	0
+4	0	1
+88
+
+chain	9835	chrUn_gl000219	179198	+	175209	175553	chr1	247249719	+	75620763	75621106	11122143
+78	179	178
+87
+
+chain	9013	chrUn_gl000219	179198	+	69512	69754	chr7	158821424	-	49488455	49488697	24923378
+57	133	133
+52
+
+chain	8698	chrUn_gl000219	179198	+	38816	38977	chr2	242951149	+	197483269	197483430	445169
+50	27	27
+84
+
+chain	7558	chrUn_gl000219	179198	+	37648	39844	chr4	191273063	-	67477312	67479509	573905
+31	2054	2055
+111
+
+chain	7043	chrUn_gl000219	179198	+	7883	7996	chrX	154913754	+	69120337	69120450	10599908
+113
+
+chain	6948	chrUn_gl000219	179198	+	21437	21525	chr10	135374737	-	55879531	55879619	9852807
+88
+
+chain	6886	chrUn_gl000219	179198	+	69191	69264	chrX	154913754	-	102980817	102980890	28429791
+73
+
+chain	6839	chrUn_gl000219	179198	+	21356	21436	chr11	134452384	+	41149119	41149199	10517795
+80
+
+chain	6788	chrUn_gl000219	179198	+	67776	67858	chr1	247249719	-	168765537	168765619	14909693
+1	2	2
+79
+
+chain	6785	chrUn_gl000219	179198	+	65376	65449	chr6	170899992	-	64502886	64502959	18163056
+73
+
+chain	6479	chrUn_gl000219	179198	+	35525	35758	chr13	114142980	-	61572553	61572786	1009673
+94	1	1
+129	2	2
+7
+
+chain	6180	chrUn_gl000219	179198	+	161178	161256	chr16	88827254	+	48470284	48470362	9569492
+78
+
+chain	5767	chrUn_gl000219	179198	+	65835	65896	chr1	247249719	+	223356684	223356745	31174397
+61
+
+chain	5622	chrUn_gl000219	179198	+	64700	64760	chr20	62435964	-	34176164	34176224	31585501
+60
+
+chain	4453	chrUn_gl000219	179198	+	175305	175363	chr7	158821424	-	154223466	154223524	19289607
+58
+
+chain	4398	chrUn_gl000219	179198	+	39190	39280	chr3	199501827	-	39205036	39205126	641764
+90
+
+chain	4168	chrUn_gl000219	179198	+	39128	39178	chrX	154913754	+	101254041	101254091	4762602
+50
+
+chain	4142	chrUn_gl000219	179198	+	160731	161020	chr7	158821424	+	108154685	108154975	5568871
+69	147	148
+73
+
+chain	4059	chrUn_gl000219	179198	+	39531	39627	chrY	57772954	+	3377002	3377098	1049766
+96
+
+chain	3905	chrUn_gl000219	179198	+	39425	39515	chr4	191273063	-	20599126	20599216	1025664
+90
+
+chain	3833	chrUn_gl000219	179198	+	19916	19966	chr11	134452384	-	24481539	24481589	14324455
+50
+
+chain	3723	chrUn_gl000219	179198	+	21281	21353	chr8	146274826	+	142341809	142341882	8036105
+11	0	1
+61
+
+chain	3631	chrUn_gl000219	179198	+	7185	7231	chr4	191273063	-	60113302	60113348	10096087
+46
+
+chain	3560	chrUn_gl000219	179198	+	35297	35440	chrX	154913754	+	31459857	31460000	1356163
+59	9	9
+75
+
+chain	3418	chrUn_gl000219	179198	+	74680	74734	chr2	242951149	+	159856161	159856226	35171835
+17	0	12
+9	2	1
+26
+
+chain	3363	chrUn_gl000219	179198	+	65597	65637	chr10	135374737	+	67903510	67903550	17680942
+40
+
+chain	3281	chrUn_gl000219	179198	+	38411	38486	chr18	76117153	+	65271563	65271638	907991
+75
+
+chain	3262	chrUn_gl000219	179198	+	162509	162544	chrX	154913754	-	14195886	14195921	20233062
+35
+
+chain	3092	chrUn_gl000219	179198	+	161605	161689	chr2	242951149	-	35465049	35465133	8792079
+19	6	6
+59
+
+chain	3074	chrUn_gl000219	179198	+	8990	9025	chr5	180857866	-	164468813	164468848	19527162
+35
+
+chain	3012	chrUn_gl000219	179198	+	38101	39406	chr14	106368585	-	62185839	62187145	783679
+26	1240	1241
+39
+
+chain	2934	chrUn_gl000219	179198	+	161840	161913	chr5	180857866	+	13471789	13471862	3866284
+73
+
+chain	2839	chrUn_gl000219	179198	+	34989	35118	chr8	146274826	+	40409778	40409907	1133484
+56	12	12
+61
+
+chain	2727	chrUn_gl000219	179198	+	21634	21700	chr14	106368585	-	78516623	78516689	9118599
+66
+
+chain	2697	chrUn_gl000219	179198	+	68852	68888	chr5	180857866	+	9312654	9312690	14610628
+36
+
+chain	2584	chrUn_gl000219	179198	+	35177	35274	chr3	199501827	+	147129328	147129425	4467916
+97
+
+chain	2547	chrUn_gl000219	179198	+	161690	161789	chr5	180857866	+	112830789	112830888	9276265
+99
+
+chain	2541	chrUn_gl000219	179198	+	162131	162175	chr12	132349534	+	54242993	54243037	9307702
+44
+
+chain	2485	chrUn_gl000219	179198	+	66217	68255	chr3	199501827	-	72358479	72360521	2866668
+55	1368	1372
+35	524	524
+56
+
+chain	2353	chrUn_gl000219	179198	+	38305	38360	chr8	146274826	-	49639359	49639414	1034303
+55
+
+chain	2230	chrUn_gl000219	179198	+	19408	19487	chr7	158821424	-	133365577	133365656	10769161
+79
+
+chain	2205	chrUn_gl000219	179198	+	37167	37218	chr2	242951149	-	113063084	113063135	1010147
+51
+
+chain	2136	chrUn_gl000219	179198	+	65993	67374	chr8	146274826	-	58386388	58387767	6969587
+99	1231	1229
+51
+
+chain	2065	chrUn_gl000219	179198	+	7314	7369	chr14	106368585	+	55554421	55554476	5303485
+55
+
+chain	1985	chrUn_gl000219	179198	+	5703	5757	chr4	191273063	-	94652192	94652246	23958560
+54
+
+chain	1979	chrUn_gl000219	179198	+	66506	66565	chr7	158821424	+	94546370	94546429	13229356
+59
+
+chain	1960	chrUn_gl000219	179198	+	8700	8761	chrY	57772954	+	20614456	20614517	21829859
+61
+
+chain	1888	chrUn_gl000219	179198	+	38366	38411	chr2	242951149	-	129971519	129971564	1057646
+45
+
+chain	1811	chrUn_gl000219	179198	+	160836	160864	chr22	49691432	-	22795768	22795796	23819908
+28
+
+chain	1737	chrUn_gl000219	179198	+	20319	20358	chrX	154913754	+	73928334	73928373	13243726
+39
+
+chain	1736	chrUn_gl000219	179198	+	19558	19630	chr12	132349534	-	63652443	63652515	6467659
+72
+
+chain	1682	chrUn_gl000219	179198	+	39076	39116	chr3	199501827	+	15208154	15208194	1287150
+40
+
+chain	1666	chrUn_gl000219	179198	+	38024	38063	chr1	247249719	-	83040882	83040921	867179
+39
+
+chain	1646	chrUn_gl000219	179198	+	37115	37153	chr15	100338915	-	50839190	50839228	850747
+38
+
+chain	1585	chrUn_gl000219	179198	+	67541	68190	chr8	146274826	-	129698985	129699635	3519578
+54	538	539
+57
+
+chain	1568	chrUn_gl000219	179198	+	21824	21882	chr4	191273063	+	144137347	144137405	18944021
+58
+
+chain	1525	chrUn_gl000219	179198	+	6513	6565	chr8	146274826	-	33560291	33560343	10738256
+52
+
+chain	1509	chrUn_gl000219	179198	+	162035	162086	chr3	199501827	+	35122783	35122834	10573790
+51
+
+chain	1485	chrUn_gl000219	179198	+	160887	160939	chr4	191273063	+	75861307	75861359	9708390
+52
+
+chain	1479	chrUn_gl000219	179198	+	65726	65767	chrX	154913754	-	87810259	87810300	15949912
+41
+
+chain	1467	chrUn_gl000219	179198	+	39689	39722	chrX	154913754	+	69240387	69240420	781473
+33
+
+chain	1461	chrUn_gl000219	179198	+	67280	67323	chr10	135374737	-	66201225	66201268	13894764
+43
+
+chain	1450	chrUn_gl000219	179198	+	67375	67437	chr5	180857866	+	57384861	57384923	6350454
+62
+
+chain	1396	chrUn_gl000219	179198	+	67210	67264	chr9	140273252	-	22551031	22551085	6094817
+54
+
+chain	1389	chrUn_gl000219	179198	+	66392	68784	chr1	247249719	+	65797848	65800245	3034140
+29	2307	2312
+56
+
+chain	1366	chrUn_gl000219	179198	+	20143	20198	chr4	191273063	-	69480908	69480963	5880463
+55
+
+chain	1339	chrUn_gl000219	179198	+	162175	162202	chr1	247249719	-	74777177	74777204	3339890
+27
+
+chain	1337	chrUn_gl000219	179198	+	68329	68386	chr10	135374737	-	97276986	97277043	13905473
+57
+
+chain	1334	chrUn_gl000219	179198	+	39950	39978	chr8	146274826	-	60735711	60735739	964260
+28
+
+chain	1215	chrUn_gl000219	179198	+	19784	19836	chr1	247249719	-	212757024	212757076	9451024
+52
+
+chain	1204	chrUn_gl000219	179198	+	9400	9453	chr2	242951149	-	221538709	221538762	17248558
+53
+
+chain	1196	chrUn_gl000219	179198	+	65543	65596	chrX	154913754	-	74732188	74732241	11122165
+53
+
+chain	1136	chrUn_gl000219	179198	+	160693	160717	chr2	242951149	+	96004141	96004165	19597584
+24
+
+chain	1088	chrUn_gl000219	179198	+	19507	19558	chr9	140273252	+	124212712	124212763	4480835
+51
+
+chain	1079	chrUn_gl000219	179198	+	37482	37507	chr4	191273063	-	92702671	92702696	10491706
+25
+
+chain	1063	chrUn_gl000219	179198	+	6670	6734	chr3	199501827	+	6965033	6965097	10403549
+64
+
+chain	1052	chrUn_gl000219	179198	+	19721	19774	chr1	247249719	+	112545490	112545543	7413376
+53
+
+chain	1038	chrUn_gl000219	179198	+	160800	160824	chrX	154913754	+	84200659	84200683	17773754
+24
+
+chain	979	chrUn_gl000219	179198	+	67437	67498	chr12	132349534	+	127544420	127544481	8975114
+61
+
+chain	882	chrUn_gl000219	179198	+	68888	68940	chr2	242951149	+	41597257	41597309	8629613
+52
+
+chain	862	chrUn_gl000219	179198	+	34692	34749	chr7	158821424	+	91057493	91057550	3914497
+57
+
+chain	862	chrUn_gl000219	179198	+	19258	19321	chr17	78774742	+	11706793	11706856	10608405
+63
+
+chain	836	chrUn_gl000219	179198	+	6404	6488	chrX_random	1719168	-	557556	557640	15714908
+84
+
+chain	826	chrUn_gl000219	179198	+	6064	6121	chr4	191273063	+	114632432	114632489	6389008
+57
+
+chain	786	chrUn_gl000219	179198	+	19327	19383	chr4	191273063	+	95451114	95451170	8391346
+56
+
+chain	781	chrUn_gl000219	179198	+	66882	66938	chr15	100338915	+	35480475	35480531	9740616
+56
+
+chain	780	chrUn_gl000219	179198	+	5491	5548	chr19	63811651	+	45237769	45237826	8205599
+57
+
+chain	773	chrUn_gl000219	179198	+	18906	18956	chr5	180857866	-	161656026	161656076	5757214
+50
+
+chain	756	chrUn_gl000219	179198	+	5561	5620	chr8	146274826	-	76452822	76452881	8679584
+59
+
+chain	744	chrUn_gl000219	179198	+	8892	8945	chr18	76117153	+	27187323	27187376	6534410
+53
+
+chain	702	chrUn_gl000219	179198	+	67866	67921	chr11	134452384	-	45331858	45331913	4032419
+55
+
+chain	658	chrUn_gl000219	179198	+	65665	65726	chr11	134452384	-	71401302	71401363	8693276
+61
+
+chain	610	chrUn_gl000219	179198	+	68611	68641	chr6	170899992	-	104159480	104159510	6224934
+30
+
+chain	600	chrUn_gl000219	179198	+	34306	34379	chr9	140273252	+	67999140	67999213	8057147
+73
+
+chain	566	chrUn_gl000219	179198	+	68393	68455	chr13	114142980	+	104410587	104410649	8663433
+62
+
+chain	556	chrUn_gl000219	179198	+	66682	66718	chr4	191273063	-	23557773	23557809	3204114
+36
+
+chain	543	chrUn_gl000219	179198	+	66718	66743	chr4	191273063	+	67612053	67612078	7944900
+25
+
+chain	543	chrUn_gl000219	179198	+	8373	8450	chr1	247249719	-	76782344	76782421	23880934
+77
+
+chain	532	chrUn_gl000219	179198	+	6121	6161	chr13	114142980	-	84408205	84408245	7620044
+40
+
+chain	531	chrUn_gl000219	179198	+	66743	66797	chr3	199501827	-	142542844	142542898	11924432
+54
+
+chain	522	chrUn_gl000219	179198	+	7996	8024	chr12	132349534	+	73188186	73188214	12754595
+28
+
+chain	500	chrUn_gl000219	179198	+	67110	67168	chr5	180857866	+	134363242	134363300	15867098
+58
+
+chain	485	chrUn_gl000219	179198	+	69293	69355	chr1	247249719	+	99641891	99641953	7463394
+62
+
+chain	483	chrUn_gl000219	179198	+	66186	66217	chrX	154913754	-	138658729	138658760	7191935
+31
+
+chain	477	chrUn_gl000219	179198	+	19687	19721	chr7	158821424	+	45385787	45385821	16982489
+34
+
+chain	474	chrUn_gl000219	179198	+	8598	8650	chrX	154913754	-	113360025	113360077	16003052
+52
+
+chain	421	chrUn_gl000219	179198	+	65449	65511	chr1	247249719	+	187704570	187704632	12170451
+62
+
+chain	402	chrUn_gl000219	179198	+	8487	8537	chr8	146274826	-	79772642	79772692	15615542
+50
+
+chain	400	chrUn_gl000219	179198	+	67611	67640	chr1	247249719	-	149721975	149722004	3673241
+29
+
+chain	357	chrUn_gl000219	179198	+	8945	8990	chr3	199501827	-	164258935	164258980	15296887
+45
+
+chain	325	chrUn_gl000219	179198	+	66571	66608	chr6	170899992	-	28562683	28562720	10433787
+37
+
+chain	267	chrUn_gl000219	179198	+	66437	66493	chr8	146274826	+	91475861	91475917	20384527
+56
+
+chain	259	chrUn_gl000219	179198	+	68682	68710	chr11	134452384	-	28278838	28278866	23153636
+28
+
+chain	207038	chrUn_gl000220	161802	+	151486	153627	chr21_random	1679693	-	0	2145	573346
+1058	0	1
+394	0	4
+106	1	0
+582
+
+chain	207038	chrUn_gl000220	161802	+	107514	109655	chr21_random	1679693	-	0	2145	573347
+1058	0	1
+394	0	4
+106	1	0
+582
+
+chain	69503	chrUn_gl000220	161802	+	67389	69230	chr2	242951149	+	25799043	25800417	1810371
+218	1	1
+72	2	2
+113	1024	551
+85	19	19
+226	0	6
+81
+
+chain	31351	chrUn_gl000220	161802	+	117547	117875	chr1	247249719	-	155624021	155624349	4397311
+328
+
+chain	29427	chrUn_gl000220	161802	+	67361	68249	chr1	247249719	-	87588997	87589612	2331939
+28	406	406
+54	1	1
+64	273	0
+62
+
+chain	27049	chrUn_gl000220	161802	+	161519	161802	chr1	247249719	-	155624021	155624304	6035035
+283
+
+chain	25088	chrUn_gl000220	161802	+	36919	37185	chr1	247249719	-	45093231	45093497	6989949
+266
+
+chain	24729	chrUn_gl000220	161802	+	117030	117449	chrX	154913754	+	108184031	108184449	7237839
+197	142	141
+80
+
+chain	20499	chrUn_gl000220	161802	+	65633	66956	chr8	146274826	-	2314439	2315749	10054888
+157	1045	1032
+53	13	13
+55
+
+chain	20386	chrUn_gl000220	161802	+	75253	75471	chr11	134452384	+	26865999	26866217	10139728
+218
+
+chain	17914	chrUn_gl000220	161802	+	106337	107514	chr20	62435964	-	36297925	36299106	11745937
+55	875	884
+91	103	98
+53
+
+chain	17680	chrUn_gl000220	161802	+	84353	85836	chr15	100338915	+	87980076	87981560	12400789
+131	384	386
+57	861	860
+50
+
+chain	16118	chrUn_gl000220	161802	+	159904	160089	chr5	180857866	+	71182513	71182698	13920446
+124	8	8
+53
+
+chain	16118	chrUn_gl000220	161802	+	115932	116117	chr5	180857866	+	71182513	71182698	13920447
+124	8	8
+53
+
+chain	15578	chrUn_gl000220	161802	+	85289	85786	chr10	135374737	-	97997712	97998207	12517238
+97	354	352
+46
+
+chain	14161	chrUn_gl000220	161802	+	154326	154474	chr12	132349534	+	20595624	20595772	16008128
+148
+
+chain	14161	chrUn_gl000220	161802	+	110354	110502	chr12	132349534	+	20595624	20595772	16008129
+148
+
+chain	13476	chrUn_gl000220	161802	+	149534	149686	chr1	247249719	+	154452993	154453145	16852628
+91	5	5
+56
+
+chain	13476	chrUn_gl000220	161802	+	105562	105714	chr1	247249719	+	154452993	154453145	16852629
+91	5	5
+56
+
+chain	13074	chrUn_gl000220	161802	+	75664	75872	chr5	180857866	+	148307676	148307883	12475568
+65	80	79
+63
+
+chain	12291	chrUn_gl000220	161802	+	109957	110143	chr2	242951149	-	110221779	110221963	18542579
+61	44	42
+81
+
+chain	11141	chrUn_gl000220	161802	+	65790	65916	chr6	170899992	-	125538722	125538849	11778575
+19	0	1
+11	1	1
+95
+
+chain	11117	chrUn_gl000220	161802	+	113673	113902	chr11	134452384	+	84872723	84872926	20519201
+78	99	73
+52
+
+chain	10468	chrUn_gl000220	161802	+	30468	30675	chr1	247249719	+	43344900	43345108	21782937
+53	83	84
+71
+
+chain	10467	chrUn_gl000220	161802	+	122720	122828	chr16	88827254	-	74338770	74338878	21787089
+108
+
+chain	10454	chrUn_gl000220	161802	+	159242	159370	chr19	63811651	+	40758345	40758473	21809803
+64	8	8
+56
+
+chain	10022	chrUn_gl000220	161802	+	109687	109957	chr16	88827254	+	33870609	33870877	21321955
+66	160	158
+44
+
+chain	9617	chrUn_gl000220	161802	+	65083	65225	chr6	170899992	-	64517981	64518123	23713679
+59	28	28
+55
+
+chain	9067	chrUn_gl000220	161802	+	65995	66091	chr5	180857866	-	61890711	61890807	15044279
+96
+
+chain	8090	chrUn_gl000220	161802	+	66643	66751	chrX	154913754	+	93027353	93027460	18331310
+57	8	8
+30	1	0
+12
+
+chain	7895	chrUn_gl000220	161802	+	83808	83891	chr8	146274826	-	74499810	74499893	26574027
+83
+
+chain	7508	chrUn_gl000220	161802	+	130266	131540	chr16	88827254	+	33860661	33862774	27224265
+76	1140	1979
+58
+
+chain	6793	chrUn_gl000220	161802	+	85386	85459	chr4	191273063	-	132701421	132701494	16466620
+73
+
+chain	6622	chrUn_gl000220	161802	+	69230	69303	chr7	158821424	+	72850229	72850302	6119994
+73
+
+chain	6240	chrUn_gl000220	161802	+	117008	117283	chr8	146274826	-	75509656	75509931	8997966
+22	197	197
+56
+
+chain	6018	chrUn_gl000220	161802	+	66770	66835	chr7	158821424	+	124008505	124008570	12829512
+65
+
+chain	5720	chrUn_gl000220	161802	+	75185	75250	chr19	63811651	+	15679634	15679699	12473683
+65
+
+chain	4703	chrUn_gl000220	161802	+	23204	23254	chr5	180857866	+	95719433	95719483	34557350
+50
+
+chain	4701	chrUn_gl000220	161802	+	84689	84759	chr7	158821424	-	101943693	101943763	18053161
+10	42	42
+18
+
+chain	4653	chrUn_gl000220	161802	+	75476	75531	chr2	242951149	+	164831342	164831397	18833276
+55
+
+chain	4071	chrUn_gl000220	161802	+	75577	75664	chr7	158821424	+	127724988	127725075	11086017
+87
+
+chain	3907	chrUn_gl000220	161802	+	84699	84740	chr8	146274826	-	59752347	59752388	23243247
+41
+
+chain	3445	chrUn_gl000220	161802	+	84526	84576	chr7	158821424	-	54802302	54802352	16133139
+50
+
+chain	3298	chrUn_gl000220	161802	+	84484	84519	chr4	191273063	+	150269733	150269768	14985224
+35
+
+chain	3145	chrUn_gl000220	161802	+	68319	68372	chr3	199501827	-	131923719	131923772	22478960
+53
+
+chain	2432	chrUn_gl000220	161802	+	68042	68092	chrX	154913754	-	83094892	83094942	21808406
+50
+
+chain	2258	chrUn_gl000220	161802	+	85510	85565	chr1	247249719	-	82513050	82513105	16301029
+55
+
+chain	1955	chrUn_gl000220	161802	+	67950	68004	chr10	135374737	-	36348792	36348846	20124747
+54
+
+chain	1529	chrUn_gl000220	161802	+	84950	85016	chr15	100338915	+	47627030	47627096	15111622
+66
+
+chain	994	chrUn_gl000220	161802	+	68645	68697	chr6	170899992	-	81185693	81185745	23384366
+52
+
+chain	895	chrUn_gl000220	161802	+	75776	75809	chrX	154913754	-	34420755	34420788	14557377
+33
+
+chain	866	chrUn_gl000220	161802	+	65932	65995	chr12	132349534	-	68316854	68316917	13749883
+63
+
+chain	724	chrUn_gl000220	161802	+	83556	83614	chrX	154913754	-	81676829	81676887	19557019
+58
+
+chain	624	chrUn_gl000220	161802	+	83438	83493	chr11	134452384	+	91542956	91543011	19738951
+55
+
+chain	591	chrUn_gl000220	161802	+	84637	84689	chr12	132349534	-	49421504	49421556	13261533
+52
+
+chain	561	chrUn_gl000220	161802	+	84759	84817	chr6_random	1875562	-	1459651	1459709	15884202
+58
+
+chain	14216718	chrUn_gl000221	155397	+	0	155355	chr1	247249719	+	141752984	141907993	211
+623	1	1
+49	1	1
+619	1	1
+34	1	1
+307	1	1
+31	1	1
+1912	1	1
+41	1	1
+994	1	1
+23	1	1
+1203	0	1
+1157	57	60
+181	1	1
+26	1	1
+643	1	2
+61	1	1
+43	1	1
+300	6	6
+241	11	11
+1194	8	8
+173	1	1
+31	1	1
+1099	13	13
+321	0	3
+456	23	24
+402	1	1
+28	1	1
+533	0	3
+476	2	0
+870	1	1
+47	1	1
+1339	4	4
+25	1	1
+474	0	1
+869	34	34
+615	1	1
+18	1	1
+1449	1	1
+47	1	1
+60	11	11
+465	8	8
+54	6	0
+164	11	11
+546	15	15
+172	1	0
+1686	0	1
+987	1	1
+38	1	1
+2146	1	1
+29	1	1
+645	1	1
+19	1	1
+804	10	10
+2676	0	1
+430	1	1
+48	1	1
+1099	1	1
+39	1	1
+127	0	1
+450	0	1
+22	1	1
+1754	1	1
+38	1	1
+152	3	0
+1066	1	1
+41	1	1
+3598	1	1
+17	1	1
+363	4	4
+63	504	9
+154	1	1
+15	1	1
+574	1	1
+43	1	1
+515	1	1
+31	1	1
+99	0	8
+378	1	1
+25	1	1
+477	1	1
+19	1	1
+466	1	1
+70	5	5
+79	1	1
+108	1	1
+210	1	1
+156	1	1
+265	7	7
+64	1	1
+98	1	1
+114	1	1
+39	1	1
+363	5	5
+28	1	1
+2637	1	1
+35	1	1
+702	1	1
+15	1	1
+122	30	30
+60	20	19
+194	1	1
+44	1	1
+1196	4	3
+141	1	1
+49	1	1
+274	2	0
+235	3	0
+152	9	9
+258	1	1
+34	1	0
+45	1	1
+370	1	1
+27	1	1
+235	10	0
+378	1	1
+17	1	0
+4	7	4
+437	15	16
+291	12	12
+101	1	1
+29	0	1
+219	0	1
+90	0	1
+164	1	1
+35	1	0
+916	1	1
+44	1	1
+54	29	25
+111	1	1
+31	1	1
+199	2	0
+360	2	0
+533	7	7
+281	14	14
+1751	1	1
+16	1	1
+136	1	0
+513	1	0
+216	2	0
+694	1	1
+30	1	1
+136	1	1
+34	1	1
+640	1	0
+17	1	0
+910	5	5
+36	4	4
+1047	1	1
+91	1	1
+1268	1	1
+49	4	4
+2141	1	1
+78	1	1
+309	1	1
+19	1	1
+116	1	1
+51	1	1
+282	4	4
+626	14	14
+2635	2	2
+37	1	1
+1324	1	1
+111	1	1
+332	1	1
+40	1	1
+1585	0	1
+1044	0	1
+456	1	1
+56	1	1
+733	0	37
+398	1	1
+24	1	1
+941	0	1
+533	1	1
+46	1	1
+425	1	1
+29	1	1
+209	1	1
+656	14	14
+2193	0	1
+340	0	1
+1318	1	1
+29	1	1
+734	13	0
+736	2	0
+395	0	1
+543	1	0
+449	2	0
+2005	1	1
+29	1	1
+748	0	1
+1298	1	1
+18	1	1
+1823	1	1
+26	1	1
+735	16	16
+1067	1	1
+20	1	1
+205	1	1
+36	1	1
+1358	0	1
+938	1	1
+87	1	1
+1100	1	1
+30	1	0
+2470	0	16
+317	10	0
+1289	5	5
+78	1	1
+1424	0	2
+656	2	2
+32	2	1
+223	0	1
+71	1	1
+289	1	0
+15	1	1
+104	1	1
+147	0	2
+15	1	1
+187	1	1
+50	1	1
+56	1	1
+31	3	3
+103	1	1
+130	1	1
+58	10	76
+99	3	3
+352	1	1
+72	1	1
+49	1	1
+105	1	1
+71	2	2
+120	1	1
+152	1	1
+87	15	84
+27	1	0
+5	1	1
+779	1	1
+42	1	1
+351	1	1
+45	1	1
+74	1	1
+46	1	1
+583	9	9
+3745	27	27
+500	0	2
+56	8	0
+105	4	4
+54	3	3
+39	1	1
+111	5	5
+2408	0	3
+1986	0	1
+4003	1	1
+38	1	1
+2084	1	1
+88	1	1
+1007	10	0
+1048	0	1
+180	6	6
+1628	0	1
+1953	1	0
+1428	1	1
+44	1	1
+475	11	11
+551	0	3
+702	2	1
+137	0	6
+829	6	6
+1463	1	1
+30	1	1
+155	1	1
+23	1	1
+1026	7	7
+987	1	1
+48	1	1
+94	1	1
+45	1	1
+706	1	1
+28	1	1
+1055	1	1
+26	1	1
+71	1	1
+53	1	1
+2245	1	1
+22	1	1
+328	1	1
+16	1	1
+1264	1	1
+33	1	1
+247	0	1
+2369	11	11
+105	11	11
+665	0	1
+27	1	1
+379	4	0
+1936	4	3
+441	1	1
+28	1	1
+736	0	5
+248	1	1
+55	1	1
+853	1	0
+415	1	1
+63	2	0
+7	1	2
+49	1	1
+324	1	1
+25	1	1
+2107	0	4
+431	9	9
+204	1	1
+25	1	1
+93	1	1
+46	1	1
+425	1	0
+321	12	12
+266
+
+chain	55879	chrUn_gl000221	155397	+	39022	155397	chr21_random	1679693	-	1044434	1160777	269
+504	7942	7889
+30	63609	63627
+27	44221	44224
+42
+
+chain	7421	chrUn_gl000221	155397	+	7003	17005	chr1	247249719	+	142211716	142221729	942
+52	9916	9927
+34
+
+chain	17470138	chrUn_gl000222	186861	+	0	186861	chr3	199501827	-	123616420	123803195	161
+1250	0	4
+3271	1	1
+48	1	1
+748	1	1
+29	1	1
+336	0	1
+397	14	15
+315	1	1
+47	1	1
+76	1	1
+49	1	1
+1417	5	0
+399	2	1
+112	1	1
+20	1	1
+667	0	3
+1357	1	1
+24	1	1
+409	1	0
+9	1	1
+173	0	1
+36	1	1
+1372	1	0
+369	9	10
+484	0	4
+411	21	25
+242	1	0
+833	14	14
+895	0	9
+1067	0	3
+87	1	1
+33	1	1
+52	1	1
+35	1	1
+564	3	2
+80	9	9
+77	3	0
+126	120	0
+626	1	1
+84	0	5
+30	1	1
+337	0	8
+384	1	1
+30	0	1
+153	0	1
+16	1	1
+52	6	0
+185	1	2
+111	4	4
+54	1	1
+29	1	1
+479	1	0
+23	1	1
+1089	1	1
+21	1	1
+194	1	1
+20	1	0
+1217	0	1
+728	1	0
+497	120	0
+130	1	1
+45	1	1
+364	0	3
+2459	4	4
+883	5	4
+785	14	14
+1180	5	0
+420	1	1
+39	0	4
+13	1	1
+60	16	16
+592	11	14
+246	0	1
+520	1	1
+19	1	1
+843	1	1
+33	1	1
+462	0	9
+24	1	1
+661	3	0
+22	1	1
+1102	6	6
+2016	1	0
+106	1	1
+40	0	1
+2177	1	1
+39	1	1
+806	0	4
+412	1	0
+317	0	2
+775	0	4
+289	1	1
+22	1	1
+920	1	1
+72	0	5
+58	1	1
+345	1	1
+22	1	1
+302	2	2
+84	1	1
+210	8	8
+98	3	1
+673	1	1
+33	1	1
+299	4	0
+1477	4	4
+475	1	1
+46	1	1
+369	13	13
+60	1	1
+37	1	1
+260	1	0
+274	6	0
+1598	1	1
+28	1	1
+2138	16	16
+793	1	0
+142	1	1
+18	1	0
+1920	0	1
+164	6	0
+859	1	1
+49	1	0
+333	2	0
+1437	1	1
+32	1	1
+243	4	5
+719	0	1
+39	1	1
+861	1	1
+41	1	1
+812	1	1
+46	9	8
+145	1	1
+50	1	1
+552	2	2
+27	0	3
+477	1	1
+41	1	1
+307	1	1
+67	1	1
+283	1	1
+27	1	1
+151	0	1
+21	1	1
+128	1	0
+42	1	1
+415	0	110
+781	2	2
+44	1	1
+176	2	2
+21	1	1
+181	4	0
+440	47	47
+326	1	1
+27	1	1
+228	1	1
+36	1	1
+138	12	12
+3038	11	11
+3781	0	1
+1856	0	58
+1813	1	0
+3776	21	0
+1096	8	0
+9578	0	4
+924	0	1
+662	1	0
+942	1	0
+1709	8	8
+167	1	0
+6850	0	6
+58	1	1
+5315	1	1
+22	1	1
+2377	1	0
+3702	1	1
+17	1	1
+1405	1	0
+38	3	0
+10654	0	1
+35	1	1
+3464	0	1
+424	12	12
+6848	13	13
+444	0	5
+1121	0	10
+3015	11	10
+5936	1	1
+45	1	1
+134	1	1
+33	1	1
+913	1	1
+33	1	1
+7377	1	1
+26	1	1
+2213	3	0
+1310	19	16
+1028	1	1
+30	1	1
+1346	0	1
+3453	23	23
+2511	0	2
+2170	1	0
+5294	16	17
+1031	0	1
+5779	30	0
+4540
+
+chain	4695	chrUn_gl000222	186861	+	24563	24635	chr3	199501827	-	123640889	123640961	14387967
+72
+
+chain	1361	chrUn_gl000222	186861	+	182291	182321	chr3	199501827	-	123798570	123798600	19416990
+30
+
+chain	17090000	chrUn_gl000223	180455	+	8	180455	chr12	132349534	-	156807	337156	167
+1699	1	0
+921	0	1
+476	0	3
+2781	5	0
+2337	0	4
+2044	1	1
+52	1	1
+99	4	0
+3342	10	10
+76207	0	1
+61652	112	0
+5333	2	15
+2060	0	1
+6964	2	2
+29	1	1
+4046	1	1
+74	0	2
+1140	1	1
+45	1	0
+610	2	0
+5062	1	0
+917	0	3
+2412
+
+chain	149624	chrUn_gl000224	179693	+	16452	19204	chr21_random	1679693	-	927993	930745	862809
+59	44	44
+122	26	26
+66	78	78
+132	53	53
+52	89	89
+402	80	80
+70	427	427
+293	109	109
+159	56	56
+159	73	73
+203
+
+chain	136876	chrUn_gl000224	179693	+	10143	12844	chr21_random	1679693	-	927993	930694	942020
+59	44	44
+122	243	243
+59	53	53
+52	89	89
+402	291	291
+56	138	138
+69	23	23
+293	109	109
+159	56	56
+159	73	73
+152
+
+chain	125386	chrUn_gl000224	179693	+	4608	7033	chr4	191273063	-	142060444	142063015	1025800
+181	62	62
+67	290	436
+77	128	128
+226	170	170
+58	50	50
+165	20	20
+83	29	29
+137	31	31
+189	59	59
+173	72	72
+64	43	43
+51
+
+chain	115319	chrUn_gl000224	179693	+	12844	15391	chr1	247249719	-	105124090	105126655	1054758
+4	101	101
+115	120	120
+83	6	6
+88	7	7
+90	138	143
+213	56	56
+54	27	27
+110	76	76
+135	22	22
+85	408	408
+51	98	112
+51	71	70
+151	97	97
+90
+
+chain	114018	chrUn_gl000224	179693	+	0	2892	chr4	191273063	-	142260101	142263001	1123540
+55	9	9
+211	93	93
+53	8	8
+62	480	490
+69	30	30
+169	1	0
+59	374	374
+170	104	104
+66	127	127
+67	134	134
+53	28	28
+127	117	117
+109	4	4
+55	1	0
+57
+
+chain	36836	chrUn_gl000224	179693	+	6824	7667	chr1	247249719	-	105124398	105125248	1790194
+51	165	165
+90	136	143
+213	56	56
+54	27	27
+51
+
+chain	33992	chrUn_gl000224	179693	+	112940	113352	chrX	154913754	-	88823320	88823732	3977820
+120	1	1
+31	1	1
+187	19	19
+53
+
+chain	18992	chrUn_gl000224	179693	+	17725	19327	chr4	191273063	-	142245973	142247284	981259
+45	153	153
+54	736	445
+17	9	9
+9	181	181
+60	269	269
+69
+
+chain	18703	chrUn_gl000224	179693	+	36684	37079	chr4	191273063	-	141982606	141983001	11515138
+60	182	182
+153
+
+chain	18089	chrUn_gl000224	179693	+	111527	111723	chr9	140273252	-	128738409	128738605	12039465
+196
+
+chain	15842	chrUn_gl000224	179693	+	43681	43852	chr5	180857866	+	121997129	121997300	14188216
+171
+
+chain	14214	chrUn_gl000224	179693	+	491	737	chr4	191273063	-	142062769	142063015	3040816
+16	72	72
+64	43	43
+51
+
+chain	12738	chrUn_gl000224	179693	+	10425	11345	chr1	247249719	+	142120275	142121196	1008989
+81	89	89
+16	667	668
+67
+
+chain	12408	chrUn_gl000224	179693	+	111770	111902	chr13	114142980	+	92814175	92814307	18368674
+132
+
+chain	11212	chrUn_gl000224	179693	+	19478	19617	chr21_random	1679693	+	1399634	1399773	20347362
+79	8	8
+52
+
+chain	11202	chrUn_gl000224	179693	+	112010	112131	chr2	242951149	-	63390730	63390851	20364580
+121
+
+chain	10961	chrUn_gl000224	179693	+	113403	113519	chr15	100338915	+	33416357	33416473	20796127
+116
+
+chain	10599	chrUn_gl000224	179693	+	45499	45614	chr4	191273063	-	16476018	16476133	21505928
+115
+
+chain	10461	chrUn_gl000224	179693	+	5286	5406	chr4	191273063	-	142252631	142253042	21797237
+48	0	291
+72
+
+chain	9625	chrUn_gl000224	179693	+	45086	45377	chr7	158821424	+	147179139	147179431	23689916
+56	173	174
+62
+
+chain	8966	chrUn_gl000224	179693	+	43852	44339	chr6	170899992	-	123605243	123606037	22200679
+5	424	731
+58
+
+chain	8686	chrUn_gl000224	179693	+	150637	150728	chr17_random	2617613	-	2481086	2481177	25413154
+91
+
+chain	8418	chrUn_gl000224	179693	+	113901	114092	chr1	247249719	+	51102379	51102577	12937085
+62	97	104
+32
+
+chain	7836	chrUn_gl000224	179693	+	113729	114060	chr15	100338915	+	29700006	29700343	12648008
+52	182	188
+97
+
+chain	7180	chrUn_gl000224	179693	+	111450	111527	chr20	62435964	+	7228195	7228272	16795381
+77
+
+chain	6302	chrUn_gl000224	179693	+	16769	18129	chr1	247249719	+	142120310	142121524	963429
+46	1235	1089
+79
+
+chain	6103	chrUn_gl000224	179693	+	42952	43016	chr3	199501827	-	123620077	123620141	30294157
+64
+
+chain	5895	chrUn_gl000224	179693	+	2013	2591	chr1	247249719	-	105125890	105126468	2699632
+97	439	439
+42
+
+chain	5875	chrUn_gl000224	179693	+	112823	112897	chr5	180857866	+	101476275	101476349	19139195
+74
+
+chain	5761	chrUn_gl000224	179693	+	112501	112575	chr5	180857866	-	18785409	18785483	18767594
+74
+
+chain	5594	chrUn_gl000224	179693	+	14410	14469	chr2	242951149	+	132757818	132757877	31664825
+59
+
+chain	5426	chrUn_gl000224	179693	+	112319	112377	chrX	154913754	+	51601613	51601671	20663092
+58
+
+chain	5157	chrUn_gl000224	179693	+	36781	36835	chr3	199501827	-	123619604	123619658	33003364
+54
+
+chain	4848	chrUn_gl000224	179693	+	38244	38295	chr17_random	2617613	-	2478551	2478602	33999646
+51
+
+chain	4029	chrUn_gl000224	179693	+	112591	112679	chr5	180857866	+	175637665	175637753	5293308
+88
+
+chain	3738	chrUn_gl000224	179693	+	13809	15505	chr21_random	1679693	+	746889	748597	1305848
+56	1588	1600
+52
+
+chain	3444	chrUn_gl000224	179693	+	17845	17922	chr4	191273063	-	142061190	142061267	1001031
+77
+
+chain	2897	chrUn_gl000224	179693	+	17977	18049	chr4	191273063	-	142253123	142253195	6314050
+72
+
+chain	2788	chrUn_gl000224	179693	+	7479	7535	chr21_random	1679693	+	746889	746945	1938894
+56
+
+chain	2567	chrUn_gl000224	179693	+	112204	112294	chr11	134452384	-	41661604	41661694	17596092
+90
+
+chain	2514	chrUn_gl000224	179693	+	112910	112940	chr7	158821424	-	149074801	149074831	4457011
+30
+
+chain	2362	chrUn_gl000224	179693	+	112294	112319	chr6	170899992	+	161846864	161846889	20635445
+25
+
+chain	2067	chrUn_gl000224	179693	+	113791	113854	chr10	135374737	-	12705669	12705732	4536722
+63
+
+chain	2066	chrUn_gl000224	179693	+	12137	18504	chr4	191273063	+	48989335	49001828	975845
+58	6251	12377
+58
+
+chain	1330	chrUn_gl000224	179693	+	113854	113878	chr5	180857866	-	104048317	104048341	15104584
+24
+
+chain	1281	chrUn_gl000224	179693	+	13065	13119	chr2	242951149	+	132762412	132762466	24130660
+54
+
+chain	1137	chrUn_gl000224	179693	+	4993	5088	chr21_random	1679693	-	929171	929266	9927235
+95
+
+chain	848	chrUn_gl000224	179693	+	1580	1641	chr19	63811651	-	14200495	14200556	15170632
+61
+
+chain	531	chrUn_gl000224	179693	+	111324	111398	chrX	154913754	+	45796753	45796827	23841494
+74
+
+chain	30238	chrUn_gl000225	211173	+	3384	6975	chr18	76117153	-	76016439	76019286	4615508
+88	182	182
+34	2463	1785
+83	385	319
+50	111	111
+195
+
+chain	23455	chrUn_gl000225	211173	+	60973	61217	chr12	132349534	-	101518303	101518547	8018503
+244
+
+chain	20111	chrUn_gl000225	211173	+	166962	167202	chrY	57772954	-	350039	350279	10363809
+137	15	15
+88
+
+chain	18512	chrUn_gl000225	211173	+	25429	25744	chrY	57772954	-	45830615	45830930	11677619
+72	105	105
+138
+
+chain	17348	chrUn_gl000225	211173	+	69995	70696	chr18	76117153	+	100273	101110	12705104
+54	377	445
+95	106	174
+69
+
+chain	16827	chrUn_gl000225	211173	+	145466	146389	chr12	132349534	-	82104353	82105276	13209656
+90	95	95
+78	609	609
+51
+
+chain	16532	chrUn_gl000225	211173	+	6975	7480	chrY	57772954	+	11929182	11929688	9693145
+6	195	195
+56	193	194
+55
+
+chain	14751	chrUn_gl000225	211173	+	146689	146847	chr12	132349534	+	39722955	39723113	15337789
+158
+
+chain	14284	chrUn_gl000225	211173	+	109330	111760	chrY	57772954	+	11933408	11933865	15870073
+76	260	260
+66	1973	0
+55
+
+chain	14255	chrUn_gl000225	211173	+	98785	99342	chr18	76117153	+	100216	100772	15900410
+38	387	386
+132
+
+chain	13725	chrUn_gl000225	211173	+	126918	127062	chr18	76117153	+	100627	100771	16530918
+144
+
+chain	13602	chrUn_gl000225	211173	+	147672	147817	chr8	146274826	+	107672556	107672701	16687743
+145
+
+chain	12515	chrUn_gl000225	211173	+	44909	48118	chrY	57772954	+	11932705	11933485	18215669
+61	2725	295
+67	280	281
+76
+
+chain	11840	chrUn_gl000225	211173	+	21194	21753	chrY	57772954	-	366515	367006	19262147
+78	414	346
+67
+
+chain	11658	chrUn_gl000225	211173	+	205576	205759	chr2	242951149	-	95682635	95682818	19568742
+65	47	47
+71
+
+chain	11142	chrUn_gl000225	211173	+	75498	75615	chrY	57772954	-	45851825	45851942	20475254
+117
+
+chain	10869	chrUn_gl000225	211173	+	51801	51915	chr18	76117153	-	76020289	76020403	20977270
+114
+
+chain	10758	chrUn_gl000225	211173	+	209713	209913	chr4	191273063	+	39081959	39082160	21190890
+74	74	75
+52
+
+chain	10616	chrUn_gl000225	211173	+	146389	146556	chr5	180857866	-	159454687	159454854	16369709
+43	58	58
+66
+
+chain	10035	chrUn_gl000225	211173	+	171673	171813	chr8	146274826	-	67038436	67038576	22726539
+51	22	22
+67
+
+chain	9917	chrUn_gl000225	211173	+	144822	145109	chr5	180857866	+	8336803	8337089	22999312
+67	165	164
+55
+
+chain	9896	chrUn_gl000225	211173	+	62060	62164	chr18	76117153	+	100627	100731	23055661
+104
+
+chain	9807	chrUn_gl000225	211173	+	137863	140640	chrY	57772954	-	45826954	45827260	23254439
+47	2048	0
+54	576	153
+52
+
+chain	8932	chrUn_gl000225	211173	+	69636	69730	chrY	57772954	-	45829605	45829699	25046033
+94
+
+chain	8413	chrUn_gl000225	211173	+	85100	85188	chrY	57772954	-	45832076	45832164	25801593
+88
+
+chain	8359	chrUn_gl000225	211173	+	142638	142726	chrY	57772954	+	57394412	57394500	25874101
+88
+
+chain	8122	chrUn_gl000225	211173	+	119411	119496	chr18	76117153	+	100254	100339	26237196
+85
+
+chain	8086	chrUn_gl000225	211173	+	55593	55678	chr18	76117153	-	76016415	76016500	26288572
+85
+
+chain	7431	chrUn_gl000225	211173	+	23911	23989	chrY	57772954	-	45832097	45832175	27364689
+78
+
+chain	7085	chrUn_gl000225	211173	+	97023	98440	chrY	57772954	-	45830811	45832294	28041027
+71	1296	1362
+50
+
+chain	7083	chrUn_gl000225	211173	+	18039	19438	chrY	57772954	-	366566	367008	28041757
+40	1295	338
+64
+
+chain	6978	chrUn_gl000225	211173	+	146217	146291	chr8	146274826	-	115673008	115673082	20162064
+74
+
+chain	6840	chrUn_gl000225	211173	+	144371	144443	chr18	76117153	+	100407	100479	28513456
+72
+
+chain	6667	chrUn_gl000225	211173	+	66486	66556	chrY	57772954	-	45828773	45828843	28907810
+70
+
+chain	6303	chrUn_gl000225	211173	+	137	203	chrY	57772954	-	45847922	45847988	29790939
+66
+
+chain	6276	chrUn_gl000225	211173	+	106597	106663	chr18	76117153	-	76016724	76016790	29833436
+66
+
+chain	6212	chrUn_gl000225	211173	+	69391	69456	chrY	57772954	-	45832092	45832157	30018585
+65
+
+chain	6148	chrUn_gl000225	211173	+	11132	11196	chrY	57772954	+	11939704	11939768	30172463
+64
+
+chain	6094	chrUn_gl000225	211173	+	68190	68254	chrY	57772954	+	57406356	57406420	30311205
+64
+
+chain	6058	chrUn_gl000225	211173	+	127450	127514	chrY	57772954	-	45844945	45845009	30402909
+64
+
+chain	6003	chrUn_gl000225	211173	+	143303	143366	chrY	57772954	+	57402115	57402178	30561429
+63
+
+chain	5903	chrUn_gl000225	211173	+	139264	139326	chrY	57772954	-	45844705	45844767	30818028
+62
+
+chain	5884	chrUn_gl000225	211173	+	104096	104157	chr18	76117153	+	102216	102277	30859822
+61
+
+chain	5803	chrUn_gl000225	211173	+	103301	103362	chr18	76117153	+	99316	99377	31083648
+61
+
+chain	5794	chrUn_gl000225	211173	+	26451	26512	chrY	57772954	-	45851626	45851687	31099284
+61
+
+chain	5721	chrUn_gl000225	211173	+	139049	139109	chrY	57772954	+	57400659	57400719	31317119
+60
+
+chain	5684	chrUn_gl000225	211173	+	146628	146689	chr1	247249719	-	54812307	54812368	16334743
+61
+
+chain	5630	chrUn_gl000225	211173	+	92437	92496	chr18	76117153	+	98445	98504	31574579
+59
+
+chain	5539	chrUn_gl000225	211173	+	140791	140849	chrY	57772954	+	57392905	57392963	31849395
+58
+
+chain	5539	chrUn_gl000225	211173	+	4266	4324	chrY	57772954	+	11928245	11928303	31849396
+58
+
+chain	5521	chrUn_gl000225	211173	+	40432	40490	chrY	57772954	-	370968	371026	31891738
+58
+
+chain	5438	chrUn_gl000225	211173	+	36214	36270	chrY	57772954	+	11930450	11930506	32145366
+56
+
+chain	5339	chrUn_gl000225	211173	+	74478	74534	chrY	57772954	-	45832726	45832782	32420219
+56
+
+chain	5339	chrUn_gl000225	211173	+	28866	28922	chrY	57772954	-	45832726	45832782	32420220
+56
+
+chain	5321	chrUn_gl000225	211173	+	77215	77271	chrY	57772954	-	45830350	45830406	32462996
+56
+
+chain	5248	chrUn_gl000225	211173	+	101556	101611	chrY	57772954	-	45844698	45844753	32703748
+55
+
+chain	5182	chrUn_gl000225	211173	+	145986	146041	chr9	140273252	+	120936021	120936076	15500236
+55
+
+chain	5139	chrUn_gl000225	211173	+	133143	133197	chrY	57772954	-	45844651	45844705	33042666
+54
+
+chain	5074	chrUn_gl000225	211173	+	44289	44341	chr18	76117153	-	76014945	76014997	33275500
+52
+
+chain	5048	chrUn_gl000225	211173	+	121427	121480	chrY	57772954	-	45831892	45831945	33345462
+53
+
+chain	5048	chrUn_gl000225	211173	+	133955	134008	chr18	76117153	+	100319	100372	33345768
+53
+
+chain	4966	chrUn_gl000225	211173	+	41802	41854	chr18	76117153	-	76019839	76019891	33630431
+52
+
+chain	4957	chrUn_gl000225	211173	+	75225	75277	chrY	57772954	+	57406623	57406675	33650989
+52
+
+chain	4953	chrUn_gl000225	211173	+	145598	145651	chr12	132349534	+	53460575	53460628	18762227
+53
+
+chain	4857	chrUn_gl000225	211173	+	102498	102549	chrY	57772954	-	45844483	45844534	33969906
+51
+
+chain	4802	chrUn_gl000225	211173	+	22297	22347	chr18	76117153	-	76019708	76019758	34221217
+50
+
+chain	4766	chrUn_gl000225	211173	+	81781	81831	chrY	57772954	-	45844484	45844534	34318861
+50
+
+chain	4730	chrUn_gl000225	211173	+	116183	116233	chrY	57772954	-	45830882	45830932	34441464
+50
+
+chain	4684	chrUn_gl000225	211173	+	16126	16175	chr18	76117153	-	76016743	76016792	34599346
+49
+
+chain	4593	chrUn_gl000225	211173	+	106022	106070	chrY	57772954	+	11933099	11933147	34665488
+48
+
+chain	4475	chrUn_gl000225	211173	+	6365	6412	chrY	57772954	-	366519	366566	34731069
+47
+
+chain	4436	chrUn_gl000225	211173	+	146291	146338	chr11	134452384	+	56488704	56488751	17449786
+47
+
+chain	3836	chrUn_gl000225	211173	+	145834	145884	chr5	180857866	+	144814068	144814118	22871561
+50
+
+chain	3811	chrUn_gl000225	211173	+	55287	55327	chrY	57772954	+	11933059	11933099	35041388
+40
+
+chain	3584	chrUn_gl000225	211173	+	145220	145258	chrX	154913754	-	118330483	118330521	21778509
+38
+
+chain	3107	chrUn_gl000225	211173	+	145429	145466	chr16	88827254	+	32289765	32289802	21377803
+37
+
+chain	3086	chrUn_gl000225	211173	+	145167	145986	chr10	135374737	+	122669077	122669897	13514114
+53	666	667
+100
+
+chain	2556	chrUn_gl000225	211173	+	117483	117510	chrY	57772954	-	45844918	45844945	35420092
+27
+
+chain	2529	chrUn_gl000225	211173	+	147645	147672	chr9	140273252	+	21053713	21053740	22333825
+27
+
+chain	2173	chrUn_gl000225	211173	+	146432	146455	chrX	154913754	-	151862289	151862312	20635516
+23
+
+chain	1176	chrUn_gl000225	211173	+	24983	25041	chrY	57772954	+	57406385	57406443	21696161
+58
+
+chain	970	chrUn_gl000225	211173	+	65774	66239	chr10	135374737	-	23380	24256	23288653
+57	372	783
+36
+
+chain	296	chrUn_gl000225	211173	+	124568	124644	chr18	76117153	+	100627	100703	23494333
+76
+
+chain	11961323	chrUn_gl000227	128374	+	0	128374	chr6	170899992	+	19668	147274	264
+1643	0	1
+255	1	1
+40	1	0
+61	4	4
+343	1	1
+168	1	1
+211	1	1
+18	1	1
+525	0	4
+549	1	1
+22	1	1
+440	16	16
+122	14	17
+167	4	4
+205	4	0
+98	1	1
+164	8	9
+585	0	1
+1278	1	1
+26	1	1
+2038	1	1
+17	1	1
+1741	15	15
+917	1	1
+26	1	1
+1021	0	1
+1314	77	0
+306	0	1
+109	0	153
+152	79	2
+199	153	0
+146	1	1
+49	1	1
+144	385	0
+4558	1	0
+5544	4	3
+2373	1	1
+40	1	0
+14638	6	0
+5386	0	1
+1491	2	0
+1835	20	20
+1481	0	4
+5348	0	1
+135	0	2
+2128	35	35
+4707	0	1
+1696	0	1
+893	1	1
+47	1	1
+766	1	1
+49	1	1
+542	1	1
+28	2	0
+334	1	1
+31	1	1
+1092	0	1
+803	1	0
+1815	6	0
+25	134	0
+37	79	0
+7668	1	0
+603	1	1
+28	1	1
+1020	0	1
+3033	0	2
+619	7	7
+1434	1	0
+1954	1	0
+9909	1	0
+1155	1	1
+36	1	1
+327	7	7
+133	4	0
+1499	0	2
+96	1	0
+3257	11	0
+46	1	1
+207	1	1
+20	1	1
+2919	18	18
+765	4	4
+1829	0	1
+1864	5	5
+123	15	15
+13751
+
+chain	49410	chrUn_gl000227	128374	+	14106	15875	chr8	146274826	+	86449	88144	529
+45	569	417
+43	288	289
+64	1	1
+12	362	363
+150	18	18
+153	1	77
+63
+
+chain	13413	chrUn_gl000227	128374	+	14996	15149	chr19	63811651	+	91181	91257	491
+55	77	0
+21
+
+chain	5337	chrUn_gl000227	128374	+	73853	73996	chr1	247249719	+	231	416	19004415
+27	66	108
+50
+
+chain	5015	chrUn_gl000227	128374	+	14074	14797	chr1	247249719	-	246873620	246874345	559
+32	658	660
+33
+
+chain	2271	chrUn_gl000227	128374	+	73917	73946	chr15	100338915	-	29	58	23118832
+29
+
+chain	8904085	chrUn_gl000228	129120	+	0	98333	chr4	191273063	+	191152836	191248399	371
+1288	1	1
+65	1	1
+695	1	1
+24	1	0
+6	1	1
+50	0	312
+260	1	1
+46	1	1
+993	1	0
+2168	1	1
+31	1	1
+3958	0	4
+257	0	18
+9	1	1
+267	3	3
+16	1	1
+1441	0	4
+68	0	1
+1387	0	2
+3469	11	11
+3245	1	0
+777	1	1
+25	1	1
+597	2	0
+30	1	1
+1792	1	1
+34	1	1
+543	0	1
+98	1	1
+25	1	1
+1024	8	0
+2103	1	1
+1898	0	12
+71	10	11
+1335	0	2
+7908	172	0
+4213	0	1
+4548	43	43
+334	0	1
+381	3	3
+46	1	1
+1201	1	1
+25	0	2
+1296	0	1
+526	4	0
+459	1	1
+56	1	1
+2023	2	2
+35	1	1
+1479	0	142
+2019	0	1
+370	8	8
+1586	1	0
+337	0	1
+921	2	0
+84	1	1
+22	1	0
+8	1	2
+206	0	4
+799	1	1
+18	0	1
+223	0	1
+295	1	70
+43	0	1
+72	68	0
+41	1	1
+90	4	4
+1051	1	1
+32	1	1
+182	7	7
+225	3	3
+22	1	1
+1660	0	1
+357	8	8
+101	13	13
+198	7	7
+412	1	0
+4	0	1
+19	1	0
+137	6	7
+361	0	2
+1716	1	0
+511	0	1
+91	0	1
+954	3024	0
+365	13	13
+1256	1	1
+74	1	1
+256	1	1
+68	1	1
+671	5	0
+144	4	0
+2140	1	1
+44	4	0
+223	1	1
+23	1	1
+716	5	0
+144	4	0
+2080	109	105
+223	70	70
+671	5	0
+144	4	0
+2140	16	16
+982	16	14
+148	4	0
+1095	66	60
+945	50	50
+996	2	0
+148	4	0
+2080	109	105
+964	5	0
+144	4	0
+2106	50	50
+996	2	0
+148	4	0
+2106	50	50
+242
+
+chain	2215952	chrUn_gl000228	129120	+	46991	129120	chr10	135374737	+	135304834	135360693	463
+43	23181	23046
+6	90	90
+334	6	0
+395	27	27
+494	145	149
+426	19	19
+480	1	11
+131	1	1
+19	4	0
+120	1	1
+35	1	1
+289	8247	8248
+26	0	8
+78	17650	1111
+121	3307	1
+35	1	1
+1001	6	0
+395	1	1
+25	1	1
+494	1	1
+26	0	8
+78	4	0
+35	1	1
+426	1	1
+17	1	1
+480	1	11
+131	1	1
+19	4	0
+120	1	1
+35	1	1
+1001	6	0
+395	1	1
+25	1	1
+494	1	1
+26	0	8
+78	4	0
+35	1	1
+426	1	1
+17	1	1
+474	10	9
+128	1	1
+19	4	0
+120	1	1
+35	1	1
+1001	6	0
+395	1	1
+25	1	1
+376	3306	0
+74	1	1
+83	1	1
+60	1	1
+52	1	1
+55	1	1
+32	1	1
+360	1	1
+88	1	1
+180	27	27
+1282	2251	0
+30	545	0
+105	1	1
+46	136	0
+1176	1	1
+47	18	0
+18	18	0
+55	18	0
+793	1	1
+28	1	1
+581	1	0
+4074	2	1
+2446
+
+chain	254528	chrUn_gl000228	129120	+	88123	111265	chr4	191273063	+	191234920	191248107	1604
+34	10176	3552
+754	2	0
+148	124	120
+1960	109	105
+964	5	0
+144	4	0
+121	8453	5141
+144
+
+chain	164891	chrUn_gl000228	129120	+	101397	114404	chr4	191273063	+	191238264	191247940	1939
+33	9885	6560
+996	2	0
+148	4	0
+1939
+
+chain	40159	chrUn_gl000228	129120	+	70221	91512	chr4	191273063	+	191223665	191244890	1141
+90	735	735
+27	570	570
+69	10105	10070
+70	5225	5207
+66	4225	4212
+26	50	50
+33
+
+chain	6229	chrUn_gl000228	129120	+	38164	38230	chr4	191273063	+	191191215	191191281	15369017
+66
+
+chain	5671	chrUn_gl000228	129120	+	71567	71627	chr4	191273063	+	191228308	191228368	1250
+60
+
+chain	3930	chrUn_gl000228	129120	+	118712	119504	chr18	76117153	-	76020078	76020393	13741639
+85	601	124
+106
+
+chain	1375	chrUn_gl000228	129120	+	91429	91463	chr4	191273063	+	191234920	191234954	1972
+34
+
+chain	1278	chrUn_gl000228	129120	+	101321	101347	chr4	191273063	+	191244781	191244807	2333
+26
+
+chain	1170	chrUn_gl000228	129120	+	94735	94769	chr4	191273063	+	191234920	191234954	2163
+34
+
+chain	1124	chrUn_gl000228	129120	+	98041	98075	chr4	191273063	+	191234920	191234954	26578
+34
+
+chain	919	chrUn_gl000228	129120	+	101347	101381	chr4	191273063	+	191234920	191234954	6339
+34
+
+chain	827	chrUn_gl000228	129120	+	111265	111299	chr4	191273063	+	191234920	191234954	87434
+34
+
+chain	12702	chrUn_gl000229	19913	+	412	548	chrX	154913754	-	39233529	39233665	17935142
+136
+
+chain	5098	chrUn_gl000229	19913	+	301	375	chr7	158821424	-	9920014	9920088	18279747
+74
+
+chain	15401	chrUn_gl000230	43691	+	29842	30067	chr20	62435964	-	41024366	41024591	14643913
+125	46	46
+54
+
+chain	12153	chrUn_gl000230	43691	+	28959	29088	chr10	135374737	-	34208037	34208166	18757529
+129
+
+chain	12020	chrUn_gl000230	43691	+	8092	8221	chrX	154913754	-	124835983	124836112	18957002
+129
+
+chain	10060	chrUn_gl000230	43691	+	30261	30455	chr3	199501827	-	88301345	88301539	22679433
+66	74	74
+54
+
+chain	7157	chrUn_gl000230	43691	+	30067	30154	chr2	242951149	+	86047836	86047923	19665405
+3	7	7
+77
+
+chain	24015	chrUn_gl000231	27386	+	4654	6337	chr5	180857866	+	70288528	70290201	7680780
+118	1377	1367
+188
+
+chain	18946	chrUn_gl000231	27386	+	6337	7360	chr5	180857866	-	104048753	104049775	8708063
+12	704	704
+72	144	143
+91
+
+chain	16625	chrUn_gl000231	27386	+	2163	2336	chr10	135374737	-	36902825	36902998	13411217
+173
+
+chain	16014	chrUn_gl000231	27386	+	5036	5206	chrX	154913754	+	20633055	20633225	14022851
+170
+
+chain	12702	chrUn_gl000231	27386	+	25798	25934	chrX	154913754	-	39233529	39233665	17935131
+136
+
+chain	12391	chrUn_gl000231	27386	+	23126	23294	chr11	134452384	+	50262817	50262985	18392381
+50	25	25
+93
+
+chain	12273	chrUn_gl000231	27386	+	3627	3759	chr1	247249719	-	155709229	155709361	18571004
+132
+
+chain	11334	chrUn_gl000231	27386	+	4172	4292	chr9	140273252	+	21364524	21364644	20124920
+120
+
+chain	10621	chrUn_gl000231	27386	+	8382	8524	chr4	191273063	+	136252211	136252355	21465956
+54	20	22
+68
+
+chain	10028	chrUn_gl000231	27386	+	22560	22688	chr10	135374737	+	99449647	99449775	22748041
+55	11	11
+62
+
+chain	9550	chrUn_gl000231	27386	+	3054	3241	chr11	134452384	+	46467217	46467406	23880867
+57	73	75
+57
+
+chain	9277	chrUn_gl000231	27386	+	7360	7468	chr2	242951149	-	156204992	156205100	12158462
+56	1	1
+51
+
+chain	8841	chrUn_gl000231	27386	+	25683	25776	chr5	180857866	-	144622856	144622949	25181714
+93
+
+chain	6713	chrUn_gl000231	27386	+	4772	4844	chr5	180857866	+	161861178	161861250	12370362
+72
+
+chain	5312	chrUn_gl000231	27386	+	6933	6989	chr2	242951149	+	51579869	51579925	20211932
+56
+
+chain	5053	chrUn_gl000231	27386	+	6349	6408	chr3	199501827	+	110713055	110713114	8874439
+59
+
+chain	3623	chrUn_gl000231	27386	+	5878	5917	chr8	146274826	-	130943147	130943186	24063221
+39
+
+chain	3087	chrUn_gl000231	27386	+	4499	4564	chr5	180857866	-	151976801	151976866	22766591
+65
+
+chain	2462	chrUn_gl000231	27386	+	23294	23322	chr5	180857866	-	140993746	140993774	21430514
+28
+
+chain	2380	chrUn_gl000231	27386	+	6863	7736	chrX	154913754	+	74323412	74324284	13413701
+70	748	747
+55
+
+chain	1938	chrUn_gl000231	27386	+	6415	7249	chr11	134452384	-	85742217	85743051	12694925
+59	715	715
+60
+
+chain	1209	chrUn_gl000231	27386	+	5917	6017	chr14	106368585	-	47277371	47277471	12257740
+100
+
+chain	575	chrUn_gl000231	27386	+	5818	5878	chr10	135374737	+	22451146	22451206	15305599
+60
+
+chain	354	chrUn_gl000231	27386	+	8607	8658	chr12	132349534	+	50248139	50248190	23666106
+51
+
+chain	55981	chrUn_gl000232	40652	+	2672	3286	chr1	247249719	+	29558771	29559386	2254424
+370	0	4
+68	3	0
+173
+
+chain	30625	chrUn_gl000232	40652	+	2331	2672	chrY	57772954	-	44046862	44047204	2487561
+217	1	1
+106	0	1
+17
+
+chain	14972	chrUn_gl000232	40652	+	34329	34487	chrX	154913754	+	113699598	113699756	15100139
+158
+
+chain	13390	chrUn_gl000232	40652	+	34068	34210	chr20	62435964	+	22916565	22916707	16960157
+142
+
+chain	12645	chrUn_gl000232	40652	+	33771	33906	chr14	106368585	-	63812125	63812260	18020773
+135
+
+chain	10324	chrUn_gl000232	40652	+	33919	34028	chr6	170899992	-	74634926	74635035	22085896
+109
+
+chain	3584	chrUn_gl000232	40652	+	34210	34248	chrX	154913754	-	70416101	70416139	23473516
+38
+
+chain	52638	chrUn_gl000233	45941	+	802	3019	chr12	132349534	+	50244492	50249723	2405861
+98	46	46
+53	1005	4019
+127	111	110
+54	26	26
+50	78	79
+98	98	98
+201	114	114
+58
+
+chain	27263	chrUn_gl000233	45941	+	999	1823	chr10	135374737	-	12704868	12705692	5123253
+41	437	437
+167	94	94
+85
+
+chain	26029	chrUn_gl000233	45941	+	396	699	chr5	180857866	-	24413022	24413325	6500883
+125	1	1
+95	4	4
+78
+
+chain	17811	chrUn_gl000233	45941	+	38826	39439	chr5	180857866	+	131253656	131254277	12283916
+54	333	341
+69	57	57
+100
+
+chain	13316	chrUn_gl000233	45941	+	3397	4215	chr1	247249719	+	164486340	164487158	3912391
+74	253	253
+51	378	378
+62
+
+chain	12153	chrUn_gl000233	45941	+	40193	40322	chr10	135374737	+	101166571	101166700	18757528
+129
+
+chain	10603	chrUn_gl000233	45941	+	723	943	chrX	154913754	-	28357792	28358012	5819450
+79	98	98
+4	1	1
+38
+
+chain	10115	chrUn_gl000233	45941	+	229	336	chr16	88827254	-	77406522	77406629	22552939
+107
+
+chain	10011	chrUn_gl000233	45941	+	39757	39898	chr3	199501827	-	59132119	59132260	22787689
+54	23	23
+64
+
+chain	9607	chrUn_gl000233	45941	+	40007	40142	chr6	170899992	+	77925734	77925869	23736932
+53	22	22
+60
+
+chain	8580	chrUn_gl000233	45941	+	2847	2960	chr3	199501827	+	21585914	21586027	3712717
+12	37	37
+64
+
+chain	8195	chrUn_gl000233	45941	+	1041	1127	chr2	242951149	-	119093538	119093624	26123131
+86
+
+chain	7332	chrUn_gl000233	45941	+	23927	24005	chr21_random	1679693	+	1414162	1414240	27537185
+78
+
+chain	7075	chrUn_gl000233	45941	+	39127	39213	chr2	242951149	-	156903226	156903312	19665406
+77	7	7
+2
+
+chain	6404	chrUn_gl000233	45941	+	24027	24095	chrY	57772954	-	45969314	45969382	29536962
+68
+
+chain	5994	chrUn_gl000233	45941	+	27720	27783	chr21_random	1679693	+	736671	736734	30572390
+63
+
+chain	5521	chrUn_gl000233	45941	+	35462	35520	chr1	247249719	+	141994539	141994597	31891728
+58
+
+chain	5421	chrUn_gl000233	45941	+	28860	28917	chrY	57772954	-	45972382	45972439	32185620
+57
+
+chain	5057	chrUn_gl000233	45941	+	42227	42280	chr21_random	1679693	+	1416441	1416494	33306944
+53
+
+chain	4977	chrUn_gl000233	45941	+	1660	1713	chr4	191273063	+	44000159	44000212	13885847
+53
+
+chain	4794	chrUn_gl000233	45941	+	1831	1882	chr3	199501827	+	28976359	28976410	34225448
+51
+
+chain	4402	chrUn_gl000233	45941	+	1908	1964	chr13	114142980	+	80218714	80218770	15308796
+56
+
+chain	2915	chrUn_gl000233	45941	+	2179	2231	chrX	154913754	-	85677566	85677618	5760053
+52
+
+chain	2427	chrUn_gl000233	45941	+	2296	2322	chr19	63811651	+	22356620	22356646	20880110
+26
+
+chain	2315	chrUn_gl000233	45941	+	3684	3890	chr3	199501827	-	103452931	103453137	5210342
+40	106	106
+60
+
+chain	2208	chrUn_gl000233	45941	+	2131	2646	chr1	247249719	-	90778455	90778971	3568552
+48	399	400
+51	14	14
+3
+
+chain	1953	chrUn_gl000233	45941	+	38960	39031	chr5	180857866	-	170798397	170798468	22477108
+71
+
+chain	1946	chrUn_gl000233	45941	+	39721	39757	chr4	191273063	+	150118550	150118586	24103400
+36
+
+chain	1711	chrUn_gl000233	45941	+	39314	39339	chr20	62435964	+	21411473	21411498	14643912
+25
+
+chain	1675	chrUn_gl000233	45941	+	40142	40172	chr2	242951149	+	189896983	189897013	24596006
+30
+
+chain	1565	chrUn_gl000233	45941	+	363	396	chr12	132349534	+	84953855	84953888	22905876
+33
+
+chain	1086	chrUn_gl000233	45941	+	38662	38716	chr5	180857866	-	112830741	112830795	14413069
+54
+
+chain	921	chrUn_gl000233	45941	+	38880	38926	chr2	242951149	-	186445721	186445767	19984811
+46
+
+chain	665	chrUn_gl000233	45941	+	38435	38508	chr7	158821424	-	45635266	45635339	24997339
+73
+
+chain	567	chrUn_gl000233	45941	+	4533	4589	chr4	191273063	-	120708136	120708192	24665208
+56
+
+chain	30885	chrUn_gl000234	40531	+	20770	21098	chrX	154913754	-	26469860	26470188	4479555
+328
+
+chain	18772	chrUn_gl000234	40531	+	29542	30847	chr2	242951149	+	66700377	66701693	11461281
+64	220	219
+130	836	848
+55
+
+chain	13381	chrUn_gl000234	40531	+	28891	29033	chr18	76117153	-	28506207	28506349	16971585
+142
+
+chain	13011	chrUn_gl000234	40531	+	32848	33004	chr21	46944323	-	3527568	3527724	17471551
+76	8	8
+72
+
+chain	12758	chrUn_gl000234	40531	+	27971	28107	chr9	140273252	+	40275857	40275993	17847477
+136
+
+chain	12298	chrUn_gl000234	40531	+	28202	28332	chr17	78774742	-	28650231	28650361	18533743
+130
+
+chain	9791	chrUn_gl000234	40531	+	31998	32458	chr4	191273063	+	52500251	52500712	23294807
+66	336	337
+58
+
+chain	9445	chrUn_gl000234	40531	+	21230	21331	chr5	180857866	+	160948764	160948865	16866863
+101
+
+chain	9406	chrUn_gl000234	40531	+	8297	8397	chr11	134452384	+	7899462	7899562	24219742
+100
+
+chain	6549	chrUn_gl000234	40531	+	28360	28429	chr3	199501827	-	77716231	77716300	29160148
+69
+
+chain	6432	chrUn_gl000234	40531	+	29956	30025	chr9	140273252	-	130605711	130605780	11645810
+69
+
+chain	5827	chrUn_gl000234	40531	+	29314	29391	chr4	191273063	+	65542826	65542903	22318479
+51	16	16
+10
+
+chain	5276	chrUn_gl000234	40531	+	28653	28709	chr11	134452384	+	42875218	42875274	32641801
+56
+
+chain	4982	chrUn_gl000234	40531	+	30259	30327	chr14	106368585	+	25312855	25312923	19084936
+68
+
+chain	4894	chrUn_gl000234	40531	+	31773	31825	chr12	132349534	+	50249715	50249767	33891551
+52
+
+chain	4820	chrUn_gl000234	40531	+	29245	29296	chr14	106368585	-	60597784	60597835	15880947
+51
+
+chain	4045	chrUn_gl000234	40531	+	29485	29542	chr4	191273063	+	52727852	52727909	20475295
+29	27	27
+1
+
+chain	4004	chrUn_gl000234	40531	+	32772	32822	chr11	134452384	+	25701880	25701930	20350535
+50
+
+chain	3827	chrUn_gl000234	40531	+	28796	28856	chr4	191273063	-	132749043	132749103	24150596
+60
+
+chain	3767	chrUn_gl000234	40531	+	29621	29672	chr4	191273063	+	109408128	109408179	23756830
+51
+
+chain	3326	chrUn_gl000234	40531	+	28132	28194	chr11	134452384	-	79489503	79489565	19687374
+62
+
+chain	3219	chrUn_gl000234	40531	+	21331	21396	chr1	247249719	+	86010808	86010873	5256643
+65
+
+chain	3215	chrUn_gl000234	40531	+	29391	30409	chr8	146274826	+	121721424	121722437	11517523
+94	843	838
+81
+
+chain	2086	chrUn_gl000234	40531	+	20746	20770	chr3	199501827	+	2077213	2077237	10890452
+24
+
+chain	1294	chrUn_gl000234	40531	+	30170	30235	chr5	180857866	+	175635483	175635548	13040504
+65
+
+chain	1179	chrUn_gl000234	40531	+	29160	29245	chr12	132349534	-	94862097	94862182	15299249
+85
+
+chain	30892	chrUn_gl000235	34474	+	10284	10636	chrX	154913754	-	137753964	137754316	4478171
+63	1	1
+187	1	1
+100
+
+chain	28245	chrUn_gl000235	34474	+	6990	7286	chr1	247249719	-	201110718	201111014	5523327
+296
+
+chain	15633	chrUn_gl000235	34474	+	10772	10939	chrX	154913754	+	111228690	111228857	14403755
+167
+
+chain	15123	chrUn_gl000235	34474	+	11327	11488	chr2	242951149	-	221981770	221981931	14935235
+161
+
+chain	15020	chrUn_gl000235	34474	+	8981	9146	chrX	154913754	+	150122103	150122269	15041806
+50	0	1
+115
+
+chain	14740	chrUn_gl000235	34474	+	10108	10284	chr1	247249719	-	105280685	105280865	6177884
+93	11	15
+68	3	3
+1
+
+chain	14088	chrUn_gl000235	34474	+	24168	24356	chrX	154913754	+	151092975	151093164	16094556
+70	28	29
+90
+
+chain	13398	chrUn_gl000235	34474	+	8127	8288	chr19	63811651	+	57248305	57248465	16951668
+53	1	0
+22	4	4
+81
+
+chain	11780	chrUn_gl000235	34474	+	9511	9636	chr4	191273063	-	168773683	168773808	19365753
+125
+
+chain	11069	chrUn_gl000235	34474	+	356	472	chrY	57772954	-	45847823	45847939	20603157
+116
+
+chain	10033	chrUn_gl000235	34474	+	11631	11737	chr1	247249719	+	193278857	193278963	22733668
+106
+
+chain	9778	chrUn_gl000235	34474	+	9888	9991	chr12	132349534	-	43209673	43209776	23326812
+103
+
+chain	8409	chrUn_gl000235	34474	+	11238	11327	chr2	242951149	-	175961361	175961450	14938980
+89
+
+chain	7852	chrUn_gl000235	34474	+	10013	10108	chr6	170899992	-	132065708	132065803	19855689
+76	7	7
+12
+
+chain	6783	chrUn_gl000235	34474	+	11488	11562	chr6	170899992	-	86591617	86591691	15132212
+74
+
+chain	5385	chrUn_gl000235	34474	+	11562	11620	chr5	180857866	+	115696160	115696218	18047359
+58
+
+chain	2922	chrUn_gl000235	34474	+	11207	11238	chrX	154913754	-	92875478	92875509	23049192
+31
+
+chain	2825	chrUn_gl000235	34474	+	10636	10670	chr12	132349534	-	101871456	101871490	12092770
+34
+
+chain	2162	chrUn_gl000235	34474	+	6967	6990	chr2	242951149	-	129587776	129587799	9249038
+23
+
+chain	1547	chrUn_gl000235	34474	+	7820	7881	chr12	132349534	+	82509454	82509515	19217212
+61
+
+chain	923	chrUn_gl000235	34474	+	7388	7458	chr11	134452384	+	54653442	54653512	19210883
+70
+
+chain	719	chrUn_gl000235	34474	+	8037	8087	chr5	180857866	-	7479901	7479951	22691815
+50
+
+chain	508	chrUn_gl000235	34474	+	9360	9418	chr10	135374737	+	96904139	96904197	25463139
+58
+
+chain	3900762	chrUn_gl000236	41934	+	0	41934	chr22	49691432	+	15341912	15383621	761
+910	1	1
+44	1	1
+601	16	16
+51	24	24
+382	118	108
+316	0	158
+302	1	1
+33	1	1
+1588	1	1
+18	1	1
+15101	0	1
+1338	0	39
+4044	417	7
+5600	2	0
+8329	1	0
+2693
+
+chain	39503	chrUn_gl000236	41934	+	24892	25309	chr22	49691432	+	15365763	15366180	3274701
+417
+
+chain	2040494	chrUn_gl000237	45867	+	12002	45867	chr21	46944323	+	10130092	10164119	1248
+88	1	1
+65	1	1
+74	5	15
+34	1	1
+139	1	1
+26	0	1
+241	1	1
+50	0	1
+91	1	1
+194	1	1
+29	1	1
+59	13	13
+54	1	1
+75	1	1
+89	1	1
+230	1	1
+59	3	3
+74	1	1
+199	1	1
+54	1	1
+488	1	16
+78	1	1
+75	1	1
+151	1	1
+93	1	1
+323	18	18
+327	1	1
+52	1	1
+853	1	1
+54	1	1
+409	1	1
+16	1	1
+42	0	1
+336	1	1
+61	1	1
+326	12	12
+295	1	0
+10	1	1
+201	3	1
+316	1	1
+15	1	1
+121	11	11
+574	1	1
+36	0	1
+40	1	1
+80	9	6
+383	4	0
+81	17	17
+172	0	4
+104	2	0
+542	1	0
+249	1	1
+48	1	1
+357	0	20
+81	0	4
+218	0	4
+46	4	0
+31	7	7
+58	4	0
+53	21	21
+2520	14	16
+343	0	1
+641	1	1
+40	0	1
+106	1	1
+353	0	49
+582	1	1
+108	0	3
+12	15	0
+14	3	18
+64	1	1
+37	1	1
+64	1	1
+27	1	1
+239	6	7
+69	2	4
+61	2	2
+29	3	3
+125	1	1
+20	1	1
+164	1	1
+98	1	1
+76	1	1
+33	1	1
+94	84	66
+45	3	0
+14	0	12
+28	3	0
+7	66	0
+56	12	0
+121	1	1
+139	1	1
+253	5	5
+79	3	0
+227	1	1
+115	1	1
+101	0	1
+116	3	3
+33	5	14
+140	1	1
+61	0	3
+70	0	1
+97	0	13
+150	1	1
+50	1	1
+52	3	3
+116	5	5
+114	1	1
+20	1	1
+94	8	8
+82	3	3
+70	1	1
+62	0	1
+20	1	1
+181	1	1
+122	0	130
+79	1	1
+27	103	0
+63	0	104
+146	52	0
+58	1	1
+74	1	1
+54	0	26
+66	3036	1025
+74	6289	8520
+54	654	456
+65	1	1
+25	1	1
+394	10	10
+48	0	1
+244	1	1
+44	1	1
+103	0	1
+74	1	1
+56	4	4
+94	1	1
+452	1	1
+33	1	1
+158	1	1
+63	1	1
+64	7	12
+33	11	11
+295	2	0
+560	1	1
+45	1	1
+1120	4	0
+97
+
+chain	3720276	chrUn_gl000238	39939	+	0	39939	chr22	49691432	-	34115067	34154863	793
+2039	8	12
+1016	5	5
+4821	1	0
+921	2	1
+890	0	1
+423	0	2
+3925	1	1
+72	1	1
+67	1	1
+148	1	1
+74	167	5
+60	1	1
+50	13	13
+3576	1	1
+54	1	1
+575	1	1
+26	1	1
+165	1	1
+46	1	1
+1550	1	1
+35	1	1
+3673	0	14
+2364	11	11
+568	0	3
+2927	4	0
+4923	1	0
+11	1	1
+988	0	1
+81	4	0
+545	1	1
+20	0	1
+1072	0	2
+750	7	7
+640	0	2
+606
+
+chain	2054582	chrUn_gl000239	33824	+	0	33798	chr21	46944323	+	10136554	10170496	1239
+77	1	1
+15	1	1
+121	11	11
+574	1	1
+36	0	1
+40	1	1
+80	9	6
+383	4	0
+81	17	17
+172	0	4
+104	2	0
+542	1	0
+249	1	1
+48	1	1
+357	0	20
+81	0	4
+218	0	4
+46	4	0
+31	7	7
+58	4	0
+53	21	21
+2520	14	16
+343	0	1
+641	1	1
+40	0	1
+106	1	1
+353	0	49
+582	1	1
+108	0	3
+12	15	0
+14	3	18
+64	1	1
+37	1	1
+64	1	1
+27	1	1
+239	6	7
+69	2	4
+61	2	2
+29	3	3
+125	1	1
+20	1	1
+164	1	1
+98	1	1
+76	1	1
+33	1	1
+94	84	66
+45	3	0
+14	0	12
+28	3	0
+7	66	0
+56	18	0
+121	1	1
+139	1	1
+253	5	5
+79	3	0
+227	1	1
+115	1	1
+101	0	1
+116	3	3
+33	5	14
+140	1	1
+61	0	3
+70	0	1
+97	0	13
+150	1	1
+50	1	1
+52	3	3
+116	5	5
+114	1	1
+20	1	1
+94	8	8
+82	3	3
+70	1	1
+62	0	1
+20	1	1
+181	1	1
+122	0	130
+79	1	1
+27	103	0
+63	0	104
+146	52	0
+58	1	1
+74	1	1
+54	0	26
+66	10199	10221
+394	10	10
+48	0	1
+244	1	1
+44	1	1
+103	0	1
+131	4	4
+94	1	1
+452	1	1
+33	1	1
+158	1	1
+63	1	1
+64	7	12
+33	11	11
+295	2	0
+560	1	1
+45	1	1
+1120	4	0
+137	4	0
+672	0	4
+1808	0	14
+3268	1	0
+571
+
+chain	3684438	chrUn_gl000240	41933	+	27	41933	chr4	191273063	-	142375113	142417352	796
+132	1	1
+44	1	1
+295	1	1
+24	1	1
+488	1	1
+52	1	1
+33	0	48
+279	7	7
+772	1	1
+16	1	1
+244	4	4
+486	0	4
+29	1	1
+375	0	48
+45	1	1
+61	0	48
+516	55	7
+557	1	1
+48	1	1
+61	1	1
+33	1	1
+195	1	1
+32	1	1
+304	1	1
+58	1	1
+428	3	0
+350	1	0
+477	15	12
+413	1	1
+46	1	1
+66	19	19
+257	1	1
+80	1	1
+180	1	1
+18	1	1
+92	1	1
+61	1	1
+80	25	25
+574	1	1
+33	1	1
+124	10	10
+1336	7	7
+113	1	1
+170	1	1
+22	0	4
+173	1	1
+21	1	1
+198	1	0
+62	1	1
+269	10	10
+109	1	3
+136	1	1
+38	1	0
+26	1	1
+514	1	1
+68	0	1
+76	0	1
+712	1	0
+9	0	1
+38	1	1
+53	1	1
+21	1	1
+369	1	0
+243	1	1
+28	1	1
+111	0	5
+186	1	1
+117	1	1
+29	0	5
+343	1	0
+77	1	1
+23	1	1
+69	1	1
+41	1	1
+237	11	11
+518	1	1
+79	1	1
+332	1	1
+70	1	1
+610	1	1
+27	1	1
+86	22	24
+793	1	1
+48	1	1
+80	1	1
+85	1	1
+366	38	38
+1127	1	1
+42	1	1
+607	9	9
+69	0	3
+45	0	1
+77	1	1
+30	5	5
+797	1	1
+49	1	1
+152	14	14
+65	13	13
+79	1	1
+37	1	1
+129	4	4
+192	1	1
+28	1	1
+124	17	17
+518	1	1
+99	1	1
+308	16	16
+70	1	1
+134	1	1
+69	1	1
+34	1	1
+162	1	1
+61	1	1
+405	1	1
+45	2	2
+183	1	1
+60	1	1
+227	4	4
+72	1	1
+190	1	1
+30	1	1
+387	1	1
+37	1	1
+553	1	1
+20	0	1
+58	1	1
+23	1	1
+72	5	4
+27	1	1
+322	0	7
+46	1	1
+83	1	1
+16	1	1
+60	1	1
+204	1	1
+895	8	8
+191	1	1
+44	1	1
+378	86	86
+148	9	9
+123	1	1
+48	1	1
+292	7	7
+106	1	1
+16	1	1
+350	15	15
+66	1	1
+43	1	0
+684	1	1
+74	1	1
+97	1	1
+66	1	1
+144	1	1
+45	1	1
+64	1	1
+24	1	1
+131	0	1
+30	1	1
+104	14	14
+228	1	1
+69	1	1
+247	1	0
+50	1	1
+54	1	1
+26	3	0
+73	2	0
+181	1	1
+18	1	1
+185	6	6
+280	1	0
+435	1	1
+40	0	10
+14	1	1
+52	1	1
+85	2	1
+27	1	1
+625	1	1
+15	1	1
+237	1	1
+26	1	1
+349	0	1
+51	1	1
+488	0	175
+143	36	0
+83	0	74
+38	1	1
+58	1	1
+51	2	2
+57	1	1
+144	1	1
+131	17	17
+487	1	1
+83	1	1
+137	12	12
+419	1	1
+24	1	1
+97	12	12
+64	18	18
+310	1	1
+31	1	1
+186	1	1
+36	1	1
+316	10	11
+301	1	1
+176	1	1
+599	4	0
+63	1	1
+511	11	11
+79	1	1
+44	3	3
+51	1	1
+116	1	1
+146	1	1
+135	2	2
+216	1	0
+21	1	1
+227	1	1
+58	1	1
+883	1	1
+62	1	1
+375	0	1
+366
+
+chain	6945	chrUn_gl000240	41933	+	0	3993	chr4	191273063	+	49288042	49296423	8111
+27	3912	8300
+54
+
+chain	3230	chrUn_gl000240	41933	+	27771	27827	chr3_random	749256	-	628862	628918	7525302
+56
+
+chain	28578	chrUn_gl000241	42152	+	7510	7836	chr10	135374737	-	24528620	24528946	5359884
+111	1	1
+117	1	1
+96
+
+chain	20691	chrUn_gl000241	42152	+	6884	7123	chr10	135374737	+	90379126	90379365	9909152
+113	1	1
+27	1	1
+97
+
+chain	19954	chrUn_gl000241	42152	+	8113	8344	chr11	134452384	+	17008798	17009029	10487677
+119	1	1
+24	1	1
+86
+
+chain	18714	chrUn_gl000241	42152	+	6396	7510	chr11	134452384	-	41660838	41661948	7928017
+55	850	846
+81	125	125
+3
+
+chain	18427	chrUn_gl000241	42152	+	6233	6498	chrX	154913754	+	121132265	121132530	8141535
+145	8	8
+10	55	55
+47
+
+chain	15897	chrUn_gl000241	42152	+	8957	9127	chr13	114142980	-	60623878	60624048	14134116
+170
+
+chain	13800	chrUn_gl000241	42152	+	6632	6782	chr2	242951149	+	123256405	123256555	16436015
+150
+
+chain	7239	chrUn_gl000241	42152	+	7836	7932	chr5	180857866	+	56109789	56109885	15641960
+1	26	26
+69
+
+chain	6771	chrUn_gl000241	42152	+	7140	7224	chr3	199501827	-	172585013	172585097	14071569
+84
+
+chain	4980	chrUn_gl000241	42152	+	6505	6564	chr9	140273252	-	115026189	115026248	16703028
+59
+
+chain	4801	chrUn_gl000241	42152	+	8656	8714	chr6	170899992	+	62873357	62873415	24154704
+58
+
+chain	4757	chrUn_gl000241	42152	+	6569	6626	chr3	199501827	-	23594171	23594228	19385889
+57
+
+chain	3592	chrUn_gl000241	42152	+	6075	6113	chr5	180857866	+	41171487	41171525	22768222
+38
+
+chain	2241	chrUn_gl000241	42152	+	6207	6233	chr5	180857866	-	32390164	32390190	11097341
+26
+
+chain	1486	chrUn_gl000241	42152	+	6113	6164	chr12	132349534	-	4193660	4193711	21729418
+51
+
+chain	1297	chrUn_gl000241	42152	+	6024	6075	chr6	170899992	+	73104104	73104155	18904124
+51
+
+chain	1062	chrUn_gl000241	42152	+	8600	8652	chr11	134452384	-	41655227	41655279	14169249
+52
+
+chain	4122233	chrUn_gl000242	43523	+	0	43523	chr22	49691432	+	23741157	23784637	726
+37	0	1
+501	0	1
+108	3	0
+187	0	1
+1121	1	1
+20	1	1
+1027	1	1
+34	1	1
+52	0	1
+765	0	4
+610	1	1
+19	0	1
+4259	1	0
+1146	31	0
+6060	1	1
+22	1	1
+2400	5	0
+8889	3	0
+179	0	1
+1992	0	1
+1767	16	0
+568	0	2
+178	0	2
+2610	4	0
+1173	1	0
+3097	0	2
+1764	0	6
+1838	2	0
+1027
+
+chain	4053524	chrUn_gl000243	43341	+	0	43341	chr21_random	1679693	+	729451	772721	736
+1181	1	1
+44	1	1
+164	1	1
+68	1	1
+111	1	1
+38	0	1
+6062	1	1
+22	3	3
+1372	1	1
+42	14	0
+910	1	1
+31	1	1
+463	28	28
+3921	1	0
+409	1	0
+1228	13	13
+561	1	1
+22	1	1
+527	4	0
+1153	1	1
+35	1	1
+2127	15	15
+1821	1	0
+407	0	1
+391	0	6
+613	1	1
+28	1	1
+191	36	0
+25	0	2
+13	0	2
+41	9	15
+922	16	16
+114	1	0
+479	29	0
+1850	1	0
+1511	0	3
+355	1	1
+48	1	1
+3880	1	1
+29	1	1
+1605	1	1
+47	1	1
+1485	1	1
+34	1	1
+907	8	8
+532	0	1
+1067	1	0
+1245	1	0
+2731	4	4
+31	3	0
+236
+
+chain	2844	chrUn_gl000243	43341	+	25693	25722	chr22_random	257318	+	139119	139148	22581207
+29
+
+chain	3756669	chrUn_gl000244	39929	+	8	39929	chr22	49691432	-	35197541	35237456	785
+890	0	2
+6963	1	0
+6036	101	101
+1666	0	1
+212	0	5
+237	1	0
+873	1	0
+227	3	0
+42	1	1
+4812	1	1
+36	1	1
+6217	2	0
+192	4	0
+249	1	0
+4665	0	5
+662	30	34
+257	12	12
+841	10	0
+4675
+
+chain	11637	chrUn_gl000244	39929	+	13898	34133	chr14	106368585	+	18813314	18833199	821
+26	1	1
+73	20106	19756
+29
+
+chain	3438216	chrUn_gl000245	36651	+	0	36651	chr1	247249719	-	105352682	105389363	845
+12574	2	0
+842	0	2
+6285	0	1
+6019	0	21
+4218	0	3
+2704	0	4
+81	0	1
+1294	1	1
+47	1	1
+1004	1	1
+21	1	1
+73	16	16
+108	1	1
+32	1	1
+1325
+
+chain	3563345	chrUn_gl000246	38154	+	0	38154	chr22	49691432	-	34033100	34071273	824
+1862	1	1
+45	1	1
+3608	0	3
+107	1	15
+848	1	1
+43	1	0
+337	1	1
+35	1	1
+176	0	2
+91	3	4
+2683	0	1
+1321	18	2
+519	1	1
+27	1	1
+472	1	1
+44	1	1
+2452	0	8
+253	1	1
+21	1	1
+48	8	0
+6372	1	1
+38	1	0
+33	1	1
+777	0	1
+139	0	3
+2402	0	2
+3053	1	1
+46	1	1
+198	4	4
+27	1	1
+1883	0	9
+1592	0	4
+320	0	1
+1542	11	11
+412	12	12
+1421	4	0
+2828
+
+chain	3430032	chrUn_gl000247	36422	+	0	36422	chr1	247249719	+	142267104	142303524	847
+151	8	8
+412	1	0
+642	0	1
+3260	12	12
+7577	0	1
+311	3	0
+2665	4	0
+3223	0	1
+437	0	1
+726	0	2
+340	1	0
+1345	1	0
+1511	0	2
+890	1	1
+29	1	1
+2699	1	1
+41	0	2
+1893	1	1
+49	1	1
+5180	1	0
+296	0	4
+573	1	0
+35	1	1
+1170	4	0
+925
+
+chain	3751823	chrUn_gl000248	39786	+	0	39786	chr22	49691432	+	31380700	31420473	786
+9870	4	0
+430	0	3
+13	1	1
+275	3	3
+48	0	1
+149	0	4
+854	1	0
+15	1	0
+1499	1	0
+3772	2	0
+2363	16	16
+1406	10	10
+813	1	0
+269	0	1
+2137	0	3
+379	0	1
+286	1	0
+504	7	0
+2925	1	0
+41	1	1
+1183	25	25
+1285	0	1
+1290	0	1
+93	5	4
+521	1	0
+239	1	0
+304	1	0
+202	1	0
+774	1	0
+3448	1	1
+29	1	1
+565	1	0
+303	2	0
+1412
+
+chain	3662710	chrUn_gl000249	38502	+	0	38502	chr22	49691432	+	26547108	26585613	801
+1207	1	0
+15053	0	12
+44	8	0
+22189
+
+chain	14267284136	X	155270560	+	60000	155260560	chrX	154913754	+	0	154913754	8
+34821	50000	50000
+86563	50000	30000
+766173	50000	50000
+36556	50000	50000
+80121	50000	90000
+754004	50000	100000
+5505644	50000	0
+3064790	50079	0
+26309505	50000	25000
+201176	8	0
+7416	0	2
+53134	8	0
+3073	0	12
+21097	0	2
+60831	2	0
+57728	0	20
+54336	0	1
+31675	0	4
+9987	4	0
+12108	0	4
+11225906	0	2000
+356252	50059	50059
+77342	1	1
+17	1	1
+94	0	3
+266	10	10
+113	1	1
+21	1	1
+5400	0	5
+4996	7	15
+3222	5	1
+6456	1	0
+1476	5	5
+2100	1	1
+40	1	1
+1316	0	1
+2446	1	0
+1555	0	2
+11220	1	0
+2639	1	0
+5190	0	4
+79	8	0
+5086	0	1
+2663	1	0
+9149	7	8
+1851	0	1
+9081	0	1
+7248	25	0
+208	28	0
+25	2	0
+15	83	0
+17	116	4
+2536	0	1
+1394	0	6
+12550	0	42
+822	4	0
+30578	1	0
+3711	4	0
+3637	1	0
+11945	0	1
+20204	0	1
+4172	8	0
+5679	1	0
+23827	0	2
+54817	0	1
+657	0	1
+342931	50000	180000
+2052068	27	1
+5375	2	0
+46	0	2
+6489	0	1
+7175	2	0
+1239	2	0
+4301	0	4
+27254	0	1
+4244	0	2
+717	0	2
+260	0	6
+26075	1	0
+236464	50000	50000
+6136098	3100000	3000000
+13518993	1	0
+449	1	0
+4535	4	0
+755	1	0
+1102	1	0
+24	1	1
+107	2	0
+3470	0	1
+1108	1	0
+4775	1	0
+8628	1	1
+46	1	1
+1072	1	1
+44	1	1
+292	4	5
+9091	4	4
+2218	4	4
+705	5	1
+452	0	1
+332	0	1
+1801	7	1
+3960	1	0
+2007	1	0
+3337	1	0
+2093	1	0
+407	310	0
+6130	1	1
+36	1	1
+1697	1	0
+97	13	0
+7624	1	1
+19	1	1
+3806	24	24
+3103	1	0
+779	7	7
+721	1	1
+43	1	1
+1626	0	1
+6146	0	2
+150	1	1
+47	1	1
+2172	0	2
+398	1	1
+31	1	1
+1334	16	16
+1663	1	1
+18	1	1
+2105	1	0
+9	1	1
+1409	1	1
+33	1	1
+1753	1	0
+408	0	1
+1916	1	0
+1928	0	12
+3800	1	1
+15	1	1
+2921	0	1
+4597	0	2
+486	6	0
+308	24	24
+1056	1	1
+44	1	1
+186	1	1
+46	1	1
+3037	0	1
+2301	0	3
+3876	1	1
+22	1	1
+1724	1	0
+3733	1	0
+627	1	0
+250	0	1
+194	1	1
+26	1	1
+20797	10	10
+2445	0	1
+1733	2	0
+1001	0	12
+4394	9	9
+4052	9	10
+670	1	1
+96	0	6
+26	1269	1568
+28	3	2
+10	1486	1188
+25	6	0
+18	1	1
+62	17	17
+77	1	0
+4949	10	10
+4690	1	0
+7343	0	1
+1248	0	1
+1259	0	1
+1347	4	0
+1532	0	1
+3797	16	16
+807	0	1
+2427	0	1
+48	1	0
+287	0	1
+611353	1	0
+1041	0	6
+371	1	0
+227	1	0
+2806	0	1
+36	1	1
+234	1	1
+23	1	1
+584	0	1
+22241	1	1
+65	1	1
+4605	1	0
+2337	20	0
+2119	1	0
+6170	13	9
+10665	1	0
+14631	0	1
+5359	0	4
+4004	0	1
+3182	0	11
+3897	16	14
+2551	0	1
+1824	0	1
+5274	1	1
+41	1	1
+4309	1	0
+3827	1	0
+4594	1	0
+65	1	1
+1170	1	1
+42	4	4
+214	1	0
+5228	1	0
+553	0	1
+6270	1	1
+12	1	1
+2849	12	13
+156	2	0
+8820	1	1
+41	1	1
+472	1	1
+65	1	0
+8	1	1
+1162	0	1
+565	1	1
+48	1	1
+536	1	2
+766	2	0
+4520	1	0
+1574	0	1
+503	1	0
+2558	1	0
+250061	7	7
+9650	18	18
+3208	1	1
+25	1	0
+744	0	2
+2994	1	1
+33	1	1
+1331	0	1
+87	19	19
+1935	5	0
+7	6	0
+1292	1	1
+35	1	1
+2485	1	1
+35	1	1
+4184	23	23
+13077	8	15
+671	4	0
+428	1	0
+4736	0	1
+3849	1	0
+6745	16	16
+2344	1	1
+41	1	1
+7917	1	0
+3876	1	1
+75	1	1
+1429	7	7
+11933	1	1
+28	1	1
+409	1	0
+11	1	1
+1223	12	12
+5354	1	0
+1255	6	0
+851	1	1
+45	1	1
+144	1	1
+47	5	5
+5929	0	4
+422	1	0
+2949	6	0
+193	1	1
+319	4	4
+3592	33	33
+3115	3	1
+1074	0	1
+2465	1	1
+40	1	1
+640	0	2
+550	1	1
+32	1	1
+4096	1	1
+29	1	1
+949	6	6
+6258	0	1
+3957	0	1
+19608	1	1
+48	1	1
+234	1	0
+16874	11	11
+1018	0	321
+2624	0	1
+4553	3	0
+491	6	0
+7496	1	1
+10	10	0
+76	4	0
+3314	1	1
+32	1	1
+5217	0	1
+3540	0	1
+1254	48	48
+1124	18	0
+3109	8	8
+3248	0	1
+1946	1	1
+48	1	1
+9620	2	0
+31242	50000	20000
+36075685	0	3
+36004	1	1
+27	1	1
+5196	1	0
+293	2	0
+13307	3	0
+2420	0	6
+1863	2	0
+2911	1	0
+3233	0	2
+66	0	1
+2375	0	10
+4894	0	1
+745	0	1
+3897	13	0
+4430	1	1
+48	1	4
+20	2	0
+279	2	0
+33	1	1
+48	0	1
+387	8	8
+692	1	0
+375	0	3
+380	23	23
+1289	1	1
+29	1	1
+12336	331	0
+852	0	4
+48	4	0
+4350	1	1
+59	1	1
+4306	5	0
+129	0	2
+3001	1	0
+1332	5	8
+23273	1	0
+30174	39	27
+337	3	0
+2838	0	1
+1614	9	0
+313	1	0
+82	0	4
+173	1	1
+25	1	1
+4912	39	0
+1863	1	0
+2931	0	1
+3134	3	0
+390880	1	0
+7199	0	1
+305	0	2
+1811	0	2
+5449	3	0
+7443	2	0
+2171	1	1
+27	1	1
+2668	2	0
+2180	1	0
+1170	9	0
+1450	16	16
+3080	0	1
+11157	0	1
+678	1	1
+28	1	1
+698	0	1
+112	0	1
+1831	0	3
+14327	0	2
+2247	3	0
+380	1	1
+28	1	1
+1265	21	19
+7184	2	3
+4225	14	9
+1002	1	0
+3854	0	4
+2535	1	1
+30	1	1
+794	0	1
+25	1	1
+76140	50000	70000
+1432750	0	7772
+681872	50000	20000
+4278742	56347	0
+12021233	1	0
+8	0	1
+1775	0	1
+1468	1	1
+51	14	16
+6	1	0
+6	1	0
+11	5	4
+7	1	0
+4	1	0
+75	2	1
+26	0	1
+16	1	0
+9	1	0
+19	2	0
+22	0	1
+9	1	0
+5	3	1
+14	7	6
+38	0	1
+26	1	1
+62	40	39
+1687	1	0
+54	1	0
+8528	1	0
+2722	1	0
+6240	1	0
+33	1	0
+121285	0	1
+6	1	0
+35	0	1
+1381	1	0
+5368	0	1
+3079	1	0
+10863441	4	0
+1799	1	1
+24	1	1
+334	0	1
+4960	0	17
+1160	1	1
+34	1	1
+6153	0	3
+1346	0	4
+103	0	4
+168	27	27
+2640	12	12
+304	16	0
+719	1	0
+3286	0	1
+10182	9	0
+804	1	1
+28	1	1
+749	1	0
+3387	1	1
+47	1	1
+482	1	0
+455	15	15
+719	1	1
+18	1	1
+2074	1	0
+1349	4	0
+3927	1	1
+18	1	1
+907	1	0
+2972	0	2
+115	1	1
+37	1	1
+4428	0	1
+1120	0	1
+4055	0	5
+2929	0	3
+3590	1	1
+47	1	1
+62	0	1
+947	1	1
+45	1	1
+1639	1	1
+32	1	1
+1076	1	0
+3996	0	4
+686	41	41
+7238	0	1
+1733	0	1
+1451	2	0
+617	0	1
+4375	1	0
+2194	15	16
+349	1	1
+27	1	1
+8237	0	1
+499	1	1
+37	2	2
+968	0	1
+34	1	1
+6337	1	1
+18	1	1
+8162	1	1
+21	0	5
+7668	45	45
+1562	0	1
+6017	5	5
+3872	0	8
+5421	0	1
+532	7	6
+5673	4	0
+1542	0	4
+890	1	3
+2561	0	1
+1692	0	1
+1142	1	1
+32	1	1
+503	1	2
+123	1	1
+75	1	1
+2322	0	1
+201	0	1
+40	3	3
+149	0	3
+1441	1	1
+40	1	1
+159	0	2
+1278	1	1
+33	1	1
+221	1	0
+31	1	1
+161	10	9
+1890	1	0
+132	1	1
+37	1	1
+514	23	17
+1373	0	4
+907	17	17
+714	31	30
+55	1	1
+24	1	1
+1038	0	2
+95	5	1
+1094	1	1
+170	1	1
+844	3	0
+369	1	1
+39	1	1
+650	1	1
+41	1	1
+176	1	1
+10	1	1
+688	0	1
+7637	0	4
+2653	1	1
+26	4	0
+46	1	1
+727	0	8
+2197	1	0
+13466	1	0
+3510	2	0
+2147	1	1
+44	3	0
+1320	11	11
+213	4	0
+102	0	1
+3239	1	0
+1492	0	3
+107	1	1
+35	14	0
+2391	1	1
+39	2	0
+436	0	4
+2271	0	8
+6868	3	0
+7183	1	0
+5104	3	0
+182	0	1
+3131	1	1
+31	0	1
+14	1	1
+59	0	1
+373	1	1
+42	1	1
+235	13	13
+1608	5	0
+152	1	1
+106	1	1
+783	34	34
+1633	1	1
+29	0	3
+821	1	1
+24	1	1
+1178	1	1
+33	1	1
+328	1	1
+27	1	1
+5682	1	0
+11	1	5
+146398	50000	30000
+59809	2	0
+3389	1	1
+37	1	1
+11606	1	0
+1597	1	0
+618	1	1
+47	1	1
+2698	1	0
+826	5	5
+33	2	0
+2560	14	0
+98	3	0
+1287	1	0
+7600	1	0
+9897	8	0
+7157	1	0
+32	1	1
+1698	1	0
+754	0	2
+6787	1	0
+584	2	0
+1107	1	1
+40	1	1
+365	1	1
+35	1	1
+400	8	0
+11443	1	0
+1973	1	0
+497	46	46
+657	1	0
+716	1	1
+25	1	1
+1570	2	0
+433	0	2
+905	2	0
+94	1	1
+28	1	1
+2490	1	1
+16	1	1
+5054	1	9
+2184	2	0
+2955	21	23
+794	0	1
+1563	1	1
+20	1	1
+1627	0	11
+1676	0	2
+1527	1	0
+676	1	1
+29	1	1
+1245	1	1
+34	1	0
+1192	7	0
+27	1	0
+1940	0	1
+3421	2	0
+17	1	1
+774	30	0
+97	6	6
+59	26	12
+840	1	1
+19	1	1
+2036	13	1
+26	14	0
+1114	1	0
+25	1	1
+380	0	16
+160	1	1
+17	1	1
+1151	4	0
+699	0	1
+29	2	0
+409	1	1
+49	1	1
+1240	1	1
+37	3	3
+2248	1	0
+1828	1	0
+1997	5	1
+4640	4	4
+4555	0	2
+149	0	52
+619	2	2
+16	1	1
+83	22	0
+56	57	1
+2531	0	8
+4250	1	1
+15	1	1
+2203	0	4
+1665	0	10
+415	2	0
+395	19	18
+15708	0	1
+161	4	0
+79	14	0
+543	1	1
+42	1	1
+3261	18	18
+139	46	46
+403	1	1
+18	1	1
+5405	1	0
+1104	1	1
+53	1	1
+392	1	1
+55	3	3
+3352	9	0
+692	1	9
+8	4	0
+27	3	97
+39	3	1
+21	3	51
+61	0	2
+8931	1	0
+6692	1	2
+1141	0	2
+196	2	0
+389	1	1
+30	1	1
+949	0	1
+6057	0	3
+4741	1	0
+7689	2	0
+2046	18	18
+215	0	1
+46885	2	0
+24138	2	0
+4037	1	0
+4047693	1	0
+9545	0	2
+11590	4	0
+1698	1	3
+13506	37	37
+5380	4	0
+1806	1	1
+44	1	1
+2581	0	2
+10620	0	1
+3804	0	1
+339	0	2
+476	0	1
+5861	8	5
+109	0	14
+901	1	1
+19	1	1
+45	2	0
+1736	1	0
+6625	2	0
+7812	4	0
+7678	2	0
+5068	4	0
+21	1	0
+4170	0	1
+1671	6	0
+6333	0	16
+902	1	1
+44	1	1
+384	0	6
+23418	2	0
+36	1	1
+8900	0	4
+222	1	1
+49	1	1
+2783	0	1
+2641	0	1
+136	20	20
+1279	0	1
+3924	6	6
+13054	6	0
+8965	23	36
+4094	2	0
+2269	1	0
+13621	16	16
+2621	0	2
+30076	1	1
+49	1	1
+102	1	0
+8824	1	1
+25	1	1
+1730	1	1
+47	1	1
+3339	0	1
+131	0	16
+83	16	0
+89	6	0
+2826	33	33
+3509	1	0
+541	1	0
+6288	0	4
+3814	2	0
+7260	0	1
+806	68	0
+1162	0	1
+2230	1	0
+1109	0	1
+1106	2	0
+12396	0	1
+26207	1	1
+21	1	1
+3541	18	18
+525	0	16
+1326	7	7
+525	0	1
+4198	0	1
+4682	13	13
+890	0	2
+816	0	2
+1961	0	4
+24586	1	1
+19	1	1
+4403	1	0
+1342	1	0
+57	12	11
+2225	1	0
+2011	0	35
+10543	0	1
+9766	6	12
+2489	2	1
+20	1	1
+1541	0	12
+1130	1	1
+34	1	1
+927	0	1
+4003	0	1
+966	1	0
+149	0	1
+844	8	0
+4324	1	1
+25	1	1
+569	7	6
+6361	1	0
+3074	0	1
+1539	3	9
+634	1	1
+39	1	1
+8610	13	12
+760	2	0
+4311	0	6
+3122	0	2
+369	1	0
+9963	10	10
+2191	1	1
+23	1	1
+1060	1	1
+19	1	1
+240	12	12
+1748	1	1
+45	1	1
+1040	1	1
+31	1	1
+7446	1	1
+25	1	1
+8379	7	7
+7325	3	0
+357	0	1
+1313	0	1
+11627	4	0
+5862	1	0
+9750	1	0
+3539	0	16
+5672	13	13
+2885	0	4
+8179	1	0
+753	0	1
+4317	0	2
+1318	1	0
+957	0	1
+825	12	12
+1109	0	16
+3736	17	17
+2236	8	8
+7791	15	185
+149	1	1
+21	2	0
+636	1	1
+22	1	0
+42	1	1
+1634	4	4
+3380	0	3
+979	2	0
+3429	0	1
+7132	0	14
+1733	1	1
+38	0	1
+88	1	0
+630	6	6
+489	5	0
+22	1	0
+94	1	0
+42	0	1
+17	1	0
+27	1	0
+172	1	1
+37	1	1
+191	1	1
+66	1	1
+630	1	0
+261	30	30
+1282	1	0
+16	1	1
+429	1	0
+1588	1	1
+20	1	1
+1416	1	1
+33	1	1
+529	1	0
+25	1	0
+1863	4	0
+1651	1	1
+28	1	1
+11815	1	0
+26	1	0
+19	1	1
+3105	1	0
+700	1	0
+150	1	0
+68	1	0
+1421	6	0
+567	1	0
+14	1	0
+2415	1	0
+41	1	1
+415	1	1
+33	1	1
+4521	1	1
+33	1	1
+307	0	1
+176	0	1
+3790	1	1
+86	1	1
+67	1	1
+65	1	0
+7439	1	1
+18	1	1
+16805	1	0
+1764	0	1
+6984	1	0
+3401	20	0
+156	1	1
+30	1	1
+165	2	0
+1087	0	1
+953	0	1
+483	1	0
+632	0	1
+652	0	1
+8559	0	2
+1871	0	1
+398	0	1
+2219	1	1
+53	1	1
+756	1	1
+66	1	1
+69	1	1
+48	1	1
+63	1	1
+28	0	3
+1057	0	3
+63	3	0
+55	1	1
+74	2	3
+159	3	0
+92	1	1
+29	1	1
+58	0	3
+1210	9	9
+54	1	1
+27	1	1
+1374	2	0
+1775	2	17
+764	14	14
+331	16	16
+2291	4	3
+1687	1	1
+26	1	1
+2469	0	1
+3243	1	0
+3636	1	1
+24	1	1
+615	0	1
+2566	1	0
+275	0	5
+690	0	7
+13139	1	0
+1452	0	4
+214	13	13
+61	124	0
+1381	9	9
+5812	1	1
+24	1	1
+5703	1	0
+3992	14	15
+1462	0	3
+5199	0	2
+1554	2	0
+715	12	10
+1966	2	0
+2808	16	0
+611	1	0
+406	0	18
+737	1	1
+31	1	1
+4372	0	5
+10789	0	1
+2399	0	1
+6750	2	0
+96	48	48
+1219	0	6
+6736	0	2
+4457	4	0
+7867	0	1
+3495	1	2
+6215	12	12
+1357	1	0
+2652	0	1
+1771	1	0
+14207	41609	41616
+18338	46	46
+851	1	0
+9638	1	0
+2994	1	0
+469	1	3
+499	1	0
+12074	13	13
+2807	11	10
+715	2	0
+1627	6	6
+5099	0	1
+488	5	1
+975	2	0
+1730	32	31
+1791	0	5
+8135	38	38
+84	3	3
+18	1	1
+3737	9	9
+1442	13	13
+212	10	0
+7712	1	1
+44	1	1
+6271	0	1
+1316	1	1
+49	1	1
+9052	28	32
+113	2	0
+2813	13	13
+1285	50000	2858
+75638	50000	40000
+1583473	2	0
+1564100	97462	0
+2933461
+
+chain	4369679	X	155270560	+	152229637	152277099	chrX	154913754	+	151980294	152116665	696
+7131	26	26
+1319	1	0
+10288	0	88910
+2852	19	19
+3721	0	1
+13270	1	0
+8834
+
+chain	2629454	X	155270560	+	120011032	120067379	chrX	154913754	+	119895063	119899921	647
+714	51489	0
+4144
+
+chain	1494650	X	155270560	+	148762194	148872193	chrX	154913754	-	6301537	6445444	168
+2899	0	1
+1499	0	1
+3725	0	6
+20333	1	0
+13152	18338	18338
+46	40010	73911
+32	9926	9926
+38
+
+chain	260907	X	155270560	+	75365988	75368784	chrX	154913754	-	79628560	79631356	2215
+1269	41	41
+1486
+
+chain	138004	X	155270560	+	120011746	120013199	chrX	154913754	+	119920102	119921555	138939
+1453
+
+chain	29712	X	155270560	+	112877029	112877338	chr12	132349534	+	121720730	121721039	4776951
+309
+
+chain	29117	X	155270560	+	75253866	75254170	chr12	132349534	-	49782819	49783123	5064709
+304
+
+chain	10575	X	155270560	+	143182285	143275757	chr2	242951149	-	154930543	155024664	254
+41	49992	50582
+45	43365	43424
+29
+
+chain	3572	X	155270560	+	148224541	148224579	chrX	154913754	+	148032219	148032257	5503764
+38
+
+chain	3404	X	155270560	+	120013199	120013235	chrX	154913754	+	119931276	119931312	297576
+36
+
+chain	3363	X	155270560	+	49293018	49293056	chrX	154913754	+	49218184	49218222	1450
+38
+
+chain	2275	X	155270560	+	152236768	152236794	chrX	154913754	-	2913071	2913097	1916
+26
+
+chain	2111	X	155270560	+	143122309	143122332	chr17	78774742	-	16413594	16413617	6765736
+23
+
+chain	2063	X	155270560	+	148224511	148224541	chrX	154913754	+	148032257	148032287	9904071
+30
+
+chain	1738	chrX	155270560	+	76513595	76513628	chrX_random	1719168	+	711492	711525	75
+33
+
+chain	1275	X	155270560	+	148522048	148522077	chr11	134452384	+	59964168	59964197	432609
+29
+
+chain	391	X	155270560	+	112955240	112955279	chr3	199501827	-	80088461	80088500	4668596
+20	4	4
+15
+
+chain	2373403023	Y	59373566	+	10000	28819361	chrY	57772954	+	0	27228749	24
+34821	50000	50000
+86563	50000	30000
+766173	50000	50000
+36556	50000	50000
+80121	50000	90000
+754004	50000	100000
+6846717	50000	50000
+276367	50000	600000
+813231	3000000	500000
+39401	50000	400000
+554624	50000	100000
+535761	0	1
+32919	11	12
+12810	0	5
+18900	1	1
+121	4	5
+230478	0	1
+750	1	1
+22	1	1
+14340	1	1
+43	1	1
+2095	0	1
+14635	0	9
+2781	0	1
+45022	5	6
+7151	0	1
+9344	628	0
+5417479	50006	0
+2175791	50000	0
+1481749	50000	50000
+4867933
+
+chain	46617811	Y	59373566	+	58819361	59363566	chrY	57772954	+	57228749	57772954	80
+98295	50000	50000
+395910
+
+chain	9624	Y	59373566	+	14725909	14726162	chrX	154913754	+	99410441	99410697	23695076
+50	136	139
+67
+
diff --git a/public/chainFiles/b37tohg19.chain b/public/chainFiles/b37tohg19.chain
new file mode 100644
index 0000000..ecc442f
--- /dev/null
+++ b/public/chainFiles/b37tohg19.chain
@@ -0,0 +1,75 @@
+chain	1	1	249250621	+	0	249250621	chr1	249250621	+	0	249250621	1
+249250621
+
+chain	1	2	243199373	+	0	243199373	chr2	243199373	+	0	243199373	2
+243199373
+
+chain	1	3	198022430	+	0	198022430	chr3	198022430	+	0	198022430	3
+198022430
+
+chain	1	4	191154276	+	0	191154276	chr4	191154276	+	0	191154276	4
+191154276
+
+chain	1	5	180915260	+	0	180915260	chr5	180915260	+	0	180915260	5
+180915260
+
+chain	1	6	171115067	+	0	171115067	chr6	171115067	+	0	171115067	6
+171115067
+
+chain	1	7	159138663	+	0	159138663	chr7	159138663	+	0	159138663	7
+159138663
+
+chain	1	8	146364022	+	0	146364022	chr8	146364022	+	0	146364022	8
+146364022
+
+chain	1	9	141213431	+	0	141213431	chr9	141213431	+	0	141213431	9
+141213431
+
+chain	1	10	135534747	+	0	135534747	chr10	135534747	+	0	135534747	10
+135534747
+
+chain	1	11	135006516	+	0	135006516	chr11	135006516	+	0	135006516	11
+135006516
+
+chain	1	12	133851895	+	0	133851895	chr12	133851895	+	0	133851895	12
+133851895
+
+chain	1	13	115169878	+	0	115169878	chr13	115169878	+	0	115169878	13
+115169878
+
+chain	1	14	107349540	+	0	107349540	chr14	107349540	+	0	107349540	14
+107349540
+
+chain	1	15	102531392	+	0	102531392	chr15	102531392	+	0	102531392	15
+102531392
+
+chain	1	16	90354753	+	0	90354753	chr16	90354753	+	0	90354753	16
+90354753
+
+chain	1	17	81195210	+	0	81195210	chr17	81195210	+	0	81195210	17
+81195210
+
+chain	1	18	78077248	+	0	78077248	chr18	78077248	+	0	78077248	18
+78077248
+
+chain	1	19	59128983	+	0	59128983	chr19	59128983	+	0	59128983	19
+59128983
+
+chain	1	20	63025520	+	0	63025520	chr20	63025520	+	0	63025520	20
+63025520
+
+chain	1	21	48129895	+	0	48129895	chr21	48129895	+	0	48129895	21
+48129895
+
+chain	1	22	51304566	+	0	51304566	chr22	51304566	+	0	51304566	22
+51304566
+
+chain	1	X	155270560	+	0	155270560	chrX	155270560	+	0	155270560	23
+155270560
+
+chain	1	Y	59373566	+	0	59373566	chrY	59373566	+	0	59373566	24
+59373566
+
+chain	1	MT	16569	+	0	16569	chrM	16569	+	0	16569	25
+16569
+
diff --git a/public/chainFiles/hg18tob37.chain b/public/chainFiles/hg18tob37.chain
new file mode 100644
index 0000000..6261eae
--- /dev/null
+++ b/public/chainFiles/hg18tob37.chain
@@ -0,0 +1,30854 @@
+chain	21270159960	chr1	247249719	+	0	247199719	1	249250621	+	10000	249233096	2
+616	0	137
+166664	50000	50000
+40302	50000	50000
+153649	50000	50000
+1098446	269	272
+773	1	1
+43	1	1
+864369	2	2
+51	0	3
+104	13694	13694
+104	3	0
+51	2	2
+134936	50000	50000
+1161048	60000	150000
+1440092	50000	27273
+7590365	50000	50000
+116914	50088	100088
+237162	50000	50000
+3518496	50000	50000
+12702424	50000	150000
+16145012	1	0
+7772	0	1
+4705841	1	0
+52977198	50000	50000
+157344	50000	21065
+16604841	50000	50000
+189539	50000	150000
+398739	20290000	21050000
+195588	50000	50000
+186739	50000	150000
+175055	50000	50000
+201709	50000	100000
+126477	50000	130183
+381	3	0
+315	2	0
+62	1	1
+73	1	1
+1158	0	1
+314	1	0
+11	1	1
+2849	0	3
+5615	1	1
+37	1	1
+3172	4	6
+190	1	1
+34	1	1
+380	1	0
+2099	0	3
+1135	4	0
+970	5	5
+209	0	1
+460	1	0
+1242	28	28
+574	1	1
+21	1	1
+2268	0	3
+239	1	0
+970	11	11
+2365	1	1
+21	1	1
+384	8	8
+996	0	2
+10383	0	2
+713	1	0
+5188	1	1
+30	1	1
+1233	0	1
+132	1	1
+44	1	1
+2955	0	1
+512	1	1
+39	1	1
+1096	16	0
+743	0	1
+9028	1	0
+2506	6	0
+8446	0	2
+5505	3	0
+7541	0	1
+109864	50000	50000
+78698	50000	50000
+127263	50000	50000
+170669	50000	50000
+38311	100000	100000
+1022394	50000	50000
+281532	50000	294733
+1687	1	1
+39	0	1
+1018	1	1
+26	1	1
+1722	0	2
+158	0	4
+1602	6	0
+1384	0	1
+2066	1	1
+32	3	1
+1556908	50000	150000
+185320	50000	150000
+172789	50000	50000
+220313	50000	50000
+455185	50000	50000
+22047237	0	1
+34365824	50000	150000
+259514	50000	150000
+17265625	50000	50000
+11394365	50000	50000
+13665999	50000	150000
+174886
+
+chain	989083	chr1	247249719	+	2475290	2488984	1	249250621	-	246751494	246765188	1383
+13694
+
+chain	5421	chr1	247249719	+	1609759	1609849	1	249250621	+	1672838	1672928	2227793
+90
+
+chain	3303	chr1	247249719	+	13192499	13192587	1	249250621	-	236203315	236203403	109
+88
+
+chain	467	chr1	247249719	+	142633259	142633287	1	249250621	-	128420441	128420469	123
+28
+
+chain	12431961244	chr10	135374737	+	50000	135374737	10	135534747	+	60000	135524747	10
+5577107	50006	0
+12337568	50000	50000
+20794160	50000	50000
+286100	2480000	3200000
+191752	50000	50000
+3830277	150000	50000
+952205	150000	100000
+263307	150000	100000
+163231	150000	50000
+989829	150000	100000
+1941874	50000	50000
+211435	50000	50000
+30112515	319974	0
+13249156	10	0
+31058956	50000	50000
+2696597	50000	150000
+4615335	10000	50000
+246123	50000	50000
+1327328	1	1
+47	1	1
+1312	1	0
+56	1	1
+190	1	1
+31	1	1
+20182	0	1
+448068
+
+chain	8134587	chr10	135374737	+	81444609	81551340	10	135534747	+	88976631	89083503	218
+369	41	41
+149	6	6
+83	71	71
+548	9	9
+391	9	9
+334	42	42
+81	1	2
+954	1	0
+441	0	4
+922	37	37
+343	253	253
+278	59	58
+404	13	13
+90	39	37
+70	132	123
+145	4	4
+392	9	9
+58	29	29
+166	51	50
+78	14	14
+455	61	65
+243	41	41
+1183	17	17
+163	57	57
+169	51	51
+912	5	5
+667	12	12
+250	20	20
+506	8	8
+292	8	8
+266	17	17
+69	27	27
+131	22	22
+668	46	47
+270	13	13
+128	7	7
+300	48	48
+818	32	32
+667	67	67
+402	24	36
+293	18	18
+423	68	68
+113	9	9
+630	42	42
+269	51	51
+165	0	1
+645	52	52
+76	91	90
+505	13	13
+143	31	31
+319	68	70
+245	126	126
+145	35	37
+90	57	57
+378	41	38
+193	13	13
+333	51	30
+51	6	6
+821	56	56
+547	18	18
+343	9	9
+270	47	47
+706	1	0
+120	21	22
+371	35	35
+530	13	13
+51	36	36
+611	48	48
+587	18	18
+499	9	9
+183	26	26
+847	7	7
+134	5	4
+64	34	34
+120	66	66
+173	147	147
+126	19	16
+53	44	49
+69	1	0
+153	89	90
+81	16	16
+52	32	36
+72	28	28
+86	68	68
+56	51	51
+120	17	17
+181	5	5
+86	17	18
+68	36	36
+356	101	101
+90	3	11
+226	26	28
+70	19	19
+95	9	9
+88	16	16
+272	33	33
+216	71	71
+394	83	83
+853	14	15
+90	23	23
+130	0	3
+52	11	11
+192	49	49
+407	13	13
+122	71	34
+179	28	28
+102	10	10
+299	36	36
+268	4	4
+123	36	36
+112	41	41
+233	77	75
+73	88	92
+519	43	43
+118	101	101
+78	33	43
+117	31	31
+83	37	37
+86	3	0
+468	0	2
+791	55	55
+268	97	97
+111	55	59
+164	38	38
+176	0	3
+116	67	74
+269	0	3
+92	66	67
+205	50	55
+1339	33	34
+86	9	9
+310	34	34
+217	42	42
+194	18	17
+191	4	4
+250	0	3
+148	79	79
+77	3	0
+199	57	57
+200	53	53
+331	52	53
+136	32	42
+69	60	60
+169	0	1
+594	88	88
+174	70	70
+135	48	48
+53	9	9
+862	25	25
+1106	33	33
+974	76	76
+368	17	17
+369	43	43
+263	49	49
+143	8	8
+228	57	57
+74	3	0
+914	2	0
+137	77	74
+243	32	32
+166	53	53
+646	87	87
+71	0	1
+661	45	45
+142	76	76
+851	17	17
+56	60	60
+52	59	58
+80	60	60
+602	13	13
+617	76	78
+51	152	152
+77	38	38
+150	0	4
+386	45	45
+585	40	33
+108	12	12
+219	99	99
+1376	58	58
+517	27	27
+124	20	20
+566	58	58
+235	47	47
+72	26	26
+157	43	43
+208	31	31
+578	122	84
+259	15	15
+1141	119	119
+141	13	13
+817	14	14
+188	0	5
+323	62	75
+447	0	5
+64	161	161
+945	23	23
+66	35	35
+104	125	125
+613	186	184
+102	205	203
+767	27	27
+111	13	13
+107	80	83
+272	0	1
+438	4	4
+127	68	68
+564	44	44
+141	14	14
+137	13	17
+167	18	0
+241	25	25
+586	30	30
+178	44	44
+310	90	87
+1277	35	35
+646	32	32
+704	56	56
+367	93	101
+241	15	14
+340	64	64
+1000	23	26
+163	81	81
+895	12	12
+345	2	0
+117	48	49
+491	32	32
+206	17	17
+439	109	109
+202	6	7
+756	24	24
+380	63	62
+144	48	48
+608	80	80
+154	71	71
+232	16	16
+1809	40	40
+346	53	52
+117	10	0
+383	10	10
+1973	19	19
+879	42	42
+91	50	50
+1147	2	1
+210	68	88
+189	7	7
+595	50	49
+248	104	126
+265	106	106
+167	0	7
+141	93	62
+825	1	0
+348	47	46
+211	3	0
+114	52	56
+66	7	7
+759	48	48
+269	0	1
+106	109	114
+114	38	39
+282	20	20
+504	0	1
+174	14	7
+123	45	46
+82	58	58
+203	12	13
+153	44	44
+121	74	74
+805	43	43
+120	67	68
+171	6	6
+329	20	20
+151	33	33
+71	46	46
+195	25	21
+65	23	42
+96	78	78
+58	0	4
+389	0	3
+214	137	138
+111	2	3
+116	10	10
+128	0	3
+52	8	8
+62	43	43
+142	6	6
+214	0	112
+179	0	1
+234	4	0
+75	116	117
+119	63	67
+286	72	42
+73	150	150
+206	214	220
+73	2	0
+82	48	48
+135	40	67
+115	109	114
+185	49	49
+99	63	63
+52	204	205
+121
+
+chain	2724232	chr10	135374737	+	81309951	81339951	10	135534747	+	81320000	81350000	983
+22137	957	957
+46	77	77
+38	83	83
+51	54	54
+984	53	53
+5520
+
+chain	1898345	chr10	135374737	+	81349952	81369946	10	135534747	+	81360000	81380000	1327
+15902	21	27
+4071
+
+chain	946327	chr10	135374737	+	81339951	81349952	10	135534747	+	81350000	81360000	2894
+6692	1	0
+3308
+
+chain	939763	chr10	135374737	+	81430217	81440202	10	135534747	+	81440000	81450000	3159
+163	3	0
+518	0	16
+972	42	43
+5149	0	1
+3138
+
+chain	928169	chr10	135374737	+	81379935	81389948	10	135534747	+	81390000	81400000	3587
+1970	7	8
+141	10	0
+413	39	39
+622	4	0
+574	42	42
+2153	0	2
+1520	5	3
+2513
+
+chain	922636	chr10	135374737	+	81300280	81309951	10	135534747	+	81310330	81320000	2721
+2989	1	0
+6681
+
+chain	885793	chr10	135374737	+	81369946	81379851	10	135534747	+	81380000	81389916	4570
+507	30	32
+880	91	91
+1155	82	82
+784	10	10
+907	16	28
+1265	50	50
+859	0	3
+1375	1	2
+165	27	27
+124	29	29
+275	8	8
+308	6	0
+79	1	0
+871
+
+chain	839370	chr10	135374737	+	81389948	81399836	10	135534747	+	81400000	81409799	4960
+446	1	0
+639	0	1
+112	140	59
+198	24	22
+98	162	137
+63	10	10
+97	180	192
+71	31	33
+322	38	38
+431	0	1
+741	45	46
+229	1	3
+186	1	4
+3019	14	14
+131	1	0
+722	16	16
+1530	92	92
+32	2	1
+63
+
+chain	788625	chr10	135374737	+	81241464	81249852	10	135534747	+	81251575	81259959	6147
+783	1	0
+883	23	33
+3247	1	0
+143	31	31
+957	15	3
+2304
+
+chain	781678	chr10	135374737	+	81280054	81289770	10	135534747	+	81290109	81299824	3334
+65	841	841
+84	228	228
+27	240	240
+1767	0	10
+186	66	54
+976	0	3
+1495	0	7
+899	0	1
+376	7	7
+2156	10	0
+196	50	50
+47
+
+chain	778944	chr10	135374737	+	81250813	81551219	10	135534747	-	53516479	54101824	544
+53	63	72
+96	209	213
+193	44	44
+202	331	335
+149	28	28
+100	125	123
+56	238	272
+60	91	93
+123	9	11
+66	147	144
+82	210	211
+77	17	17
+196	31	31
+379	27	27
+954	71	71
+69	4431	3721
+746	66	66
+502	12	12
+282	28	28
+224	59	59
+52	35	35
+448	12	0
+474	42	42
+260	11	11
+83	38	44
+160	152	149
+284	76	76
+110	73	73
+284	9	9
+478	110	110
+95	5	5
+583	122	122
+116	1	1
+67	1	1
+118	1	1
+38	1	1
+566	1	1
+35	1	1
+287	1	0
+481	1	1
+42	1	1
+198	1	1
+22	1	1
+54	1	1
+25	1	1
+50	1	1
+50	1	1
+294	4	0
+158	1	1
+31	1	1
+255	8	8
+291	12	12
+171	2	2
+21	1	1
+685	77	77
+817	20	20
+312	39	39
+181	1	0
+249	50	47
+75	7	7
+86	4	4
+54	8	8
+518	134	134
+376	24	26
+189	17	27
+143	13	13
+93	16	16
+192	24	24
+992	140	132
+828	1	1
+40	1	1
+410	1	1
+25	0	2
+13	1	1
+83	8	8
+143	1	1
+20	1	1
+421	1	1
+49	1	1
+107	1	1
+28	1	1
+77	1	1
+32	0	2
+44	2	2
+348	1	1
+53	0	4
+58	1	1
+97	1	1
+125	56	53
+526	1	1
+46	1	1
+209	9	9
+76	1	1
+37	1	1
+53	1	1
+24	1	1
+141	1	1
+26	1	1
+304	1	1
+60	1	1
+199	1	1
+47	1	1
+92	6	0
+138	64	64
+299	65	65
+186	24	24
+631	84	84
+100	20	20
+108	27	27
+240	8134	8243
+50	47	45
+107	11	11
+750	5	5
+230	25	25
+221	62	62
+106	32	32
+106	52	52
+270	56	56
+166	31	31
+89	77	77
+127	666	662
+56	22	22
+55	95	83
+51	30	30
+77	35	35
+189	16	16
+130	53	53
+131	5	5
+158	140	131
+170	21	21
+55	79	79
+207	200	199
+152	11	11
+105	50	50
+104	34	34
+56	402	402
+69	0	1
+61	150	150
+181	10	10
+130	22	22
+180	5	0
+73	161	161
+77	151	151
+68	128	128
+330	138	126
+116	1211	328
+252	4	4
+102	8	8
+72	23	23
+51	51	51
+608	31808	287592
+56	14	14
+161	9	9
+717	46	50
+77	38	30
+83	51	51
+54	984	987
+53	65700	95386
+47	559	556
+99	119	119
+193	38	38
+164	12	7
+59	38	38
+58	9	5
+57	34	34
+68	30	30
+59	28	28
+51	82	87
+142	7	7
+67	162	152
+248	1	2
+114	34	34
+140	22	22
+58	119	118
+143	50	50
+255	69	65
+53	18	18
+127	11	13
+446	39	39
+134	24	24
+143	42	42
+123	65	65
+57	0	3
+199	73	73
+271	17	17
+113	24	24
+203	40	40
+51	38	38
+119	50	50
+81	60	60
+239	85	70
+79	219	219
+64	149	150
+29	211	211
+91	319	310
+76	40	40
+59	596	591
+34	579	579
+51	90	90
+169	336	329
+146	226	226
+50	480	479
+23	66	66
+95	447	447
+49	298	298
+29	180	180
+45	1186	1169
+53	2222	2217
+11	116	116
+33	313	313
+63	75	75
+14	257	258
+31	122	122
+73	311	316
+238	46	46
+130	81	78
+103	262	266
+56	168	163
+29	861	857
+61	655	666
+18	40	40
+436	1	1
+8	4	0
+35	1	1
+417	21	18
+51	2	0
+54	1	1
+126	10	9
+72	5	5
+377	1	1
+18	2	0
+35	2	2
+78	1	2
+18	2	2
+82	1	0
+99	1	1
+82	0	4
+99	1	1
+50	0	4
+50	7	7
+225	11	11
+135	2	0
+326	26	989
+2646	0	1
+560	10	0
+347	114	114
+284	118541	118621
+43	120	120
+65	1	0
+1	677	677
+33	71	71
+46	404	404
+78	661	663
+137	489	492
+43	854	846
+116	119	119
+63	286	286
+72	73	73
+150	206	206
+17	1	1
+85	1	1
+110	157	157
+48	135	135
+36	0	4
+4	115	115
+73	2	0
+19	1	1
+14	185	185
+49	99	99
+22	1	1
+40	79	80
+177
+
+chain	662550	chr10	135374737	+	81399647	81430169	10	135534747	-	46431029	46458544	512
+92	103	101
+125	0	2222
+53	53	50
+58	48	48
+298	191	189
+69	6167	5
+118	101	101
+128	111	111
+207	48	43
+55	175	169
+212	93	89
+159	23	23
+109	34	34
+150	21	20
+258	30	30
+120	51	54
+90	171	171
+268	224	219
+202	62	62
+480	237	237
+394	49	49
+100	28	28
+93	25	25
+52	29	29
+180	45	45
+141	47	47
+56	49	49
+169	39	42
+60	102	113
+53	1	13
+151	105	105
+58	33	30
+88	246	246
+334	116	116
+63	83	84
+268	115	113
+70	43	43
+252	2	1
+62	97	97
+88	6	0
+61	23	23
+84	75	75
+75	2	3
+83	8	8
+53	160	162
+312	153	152
+192	96	98
+122	95	100
+94	793	791
+61	1	5
+154	140	135
+130	32	33
+121	21	21
+82	6	6
+171	34	34
+110	52	49
+129	193	194
+64	26	29
+72	18	18
+286	75	58
+114	6596	7638
+114	284	172
+558	8	9
+111	5	5
+55	2	2
+80	0	1
+27	1	1
+72	1	1
+45	1	1
+516	1	1
+66	1	1
+106	23	42
+64	4	0
+21	1	1
+312	2	2
+30	1	1
+151	20	20
+193	1	1
+38	1	1
+96	6	6
+171	0	3
+27	0	2
+34	2	2
+120	3	3
+39	1	1
+752
+
+chain	650336	chr10	135374737	+	81249915	81259740	10	135534747	+	81260018	81269841	3195
+898	53	53
+63	96	96
+209	193	193
+44	202	202
+331	149	149
+28	100	100
+125	56	56
+238	60	60
+91	198	198
+147	82	82
+210	290	290
+31	1360	1360
+71	69	69
+196	1	0
+454	16	15
+3764
+
+chain	462746	chr10	135374737	+	81440202	81450008	10	135534747	+	81450000	81459803	2861
+1116	4	4
+801	3	0
+2483	369	369
+41	238	238
+71	1291	1291
+42	2400	2400
+37	343	343
+253	278	278
+36
+
+chain	389885	chr10	135374737	+	81290873	81299672	10	135534747	+	81300927	81309722	2802
+25	221	221
+62	106	106
+32	106	106
+52	270	270
+56	166	166
+31	89	89
+77	127	127
+666	133	133
+95	51	51
+30	77	77
+35	335	335
+53	294	294
+103	4	0
+33	246	246
+79	207	207
+200	268	268
+50	104	104
+34	56	56
+402	130	130
+150	601	601
+161	77	77
+151	68	68
+128	330	330
+138	116	116
+1211	512	512
+51
+
+chain	178315	chr10	135374737	+	81400041	81409702	10	135534747	+	81410003	81419664	4252
+32	404	404
+191	168	168
+119	193	193
+38	235	235
+38	124	124
+34	68	68
+30	59	59
+28	51	51
+82	216	216
+162	363	363
+34	220	220
+21	9	9
+89	143	143
+50	255	255
+69	995	995
+42	123	123
+65	256	256
+73	628	628
+40	208	208
+50	94	94
+47	239	239
+85	79	79
+219	64	64
+31	147	147
+72	625	625
+40	271	271
+93	754	754
+30	700	700
+66
+
+chain	157388	chr10	135374737	+	81410627	81419292	10	135534747	+	81420589	81429247	5183
+66	95	95
+53	1136	1136
+46	81	81
+25	268	268
+38	269	263
+105	58	58
+6	0	1
+27	88	88
+34	53	53
+81	32	32
+46	334	334
+116	63	63
+83	268	266
+115	429	428
+97	262	262
+75	757	757
+75	230	232
+41	343	343
+69	47	47
+78	238	238
+46	130	131
+17	36	34
+28	319	319
+46	56	56
+38	707	707
+52	129	129
+132	125	125
+26	376	376
+75
+
+chain	142913	chr10	135374737	+	81466547	81535718	10	135534747	-	46275769	46344990	569
+44	2128	2133
+24	2535	2533
+31	2379	2381
+34	143	143
+43	270	270
+50	1045	1058
+51	494	498
+36	2085	2105
+60	1979	1981
+71	1197	1197
+41	1594	1601
+37	2856	2871
+66	205	205
+50	1339	1339
+33	656	663
+42	805	805
+79	280	275
+56	200	200
+22	18	18
+13	1443	1450
+44	2526	2526
+33	974	974
+75	1489	1489
+47	1658	1653
+53	1652	1653
+41	1071	1071
+59	10705	10669
+57	6434	6441
+25	586	586
+30	178	178
+44	310	310
+74	7	1
+9	1277	1277
+35	5735	5751
+32	2139	2139
+63	3162	3162
+40	346	345
+53	3391	3390
+41	92	92
+50
+
+chain	97392	chr10	135374737	+	81500632	81510012	10	135534747	+	81510451	81519840	3573
+60	191	191
+60	1232	1232
+76	51	51
+152	77	77
+38	536	540
+45	585	586
+39	340	340
+99	1376	1373
+58	517	517
+27	710	710
+58	235	235
+47	72	72
+26	157	157
+43	208	208
+31	630	637
+70	1415	1415
+119
+
+chain	87386	chr10	135374737	+	81512081	81517268	10	135534747	+	81521923	81527111	3288
+161	1034	1034
+35	104	104
+125	613	613
+186	102	102
+205	767	767
+27	231	232
+80	841	841
+68	564	564
+44
+
+chain	81916	chr10	135374737	+	81260486	81269831	10	135534747	+	81270587	81279924	3410
+66	796	796
+28	224	224
+59	52	52
+35	934	925
+42	354	354
+1	0	2
+37	160	160
+121	19	18
+12	284	284
+76	110	110
+73	771	771
+110	683	683
+8	36	35
+78	4099	4100
+77
+
+chain	75208	chr10	135374737	+	81450008	81464865	10	135534747	+	81597933	81612795	1746
+23	1356	1354
+29	166	166
+51	547	547
+30	274	278
+40	1364	1363
+57	169	169
+51	3032	3032
+27	1585	1586
+48	818	818
+32	667	667
+67	1160	1160
+68	752	752
+42	269	269
+51	810	813
+52	76	76
+91	661	661
+31	319	319
+42
+
+chain	71596	chr10	135374737	+	81480667	81490183	10	135534747	+	81490477	81500000	3725
+36	395	395
+36	536	535
+88	519	519
+43	139	139
+80	78	78
+33	117	134
+31	1468	1468
+55	268	268
+97	111	111
+30	6	0
+19	164	164
+38	292	292
+67	2459	2459
+34	2063	2060
+52	136	136
+26
+
+chain	65913	chr10	135374737	+	81470614	81479436	10	135534747	+	81480422	81489246	3085
+36	1955	1955
+26	1450	1450
+97	248	248
+44	223	223
+89	149	149
+32	72	72
+28	86	86
+68	993	993
+49	0	1
+52	319	320
+26	569	569
+33	216	216
+71	1842	1842
+49
+
+chain	63808	chr10	135374737	+	81521220	81529648	10	135534747	+	81531068	81539504	3362
+32	704	704
+56	367	367
+93	596	601
+64	1186	1189
+81	1371	1371
+48	1185	1185
+109	1575	1575
+48	608	608
+80	154	154
+71
+
+chain	58084	chr10	135374737	+	81490258	81499708	10	135534747	+	81500075	81509527	2957
+60	807	808
+44	174	174
+70	135	135
+48	924	924
+25	2943	2943
+43	263	263
+49	1566	1566
+77	243	243
+32	865	865
+87	732	733
+45	183	183
+35
+
+chain	41373	chr10	135374737	+	81540284	81544136	10	135534747	+	81550136	81553982	6087
+47	328	324
+52	832	831
+48	375	375
+79	0	1
+30	114	114
+38	1117	1115
+45	82	82
+58	368	368
+44	121	121
+74
+
+chain	34777	chr10	135374737	+	81464865	81470020	10	135534747	+	81474671	81479828	3724
+26	245	245
+34	44	44
+48	145	145
+12	0	2
+23	90	90
+57	378	378
+41	1468	1468
+56	2453	2453
+35
+
+chain	34249	chr10	135374737	+	81270980	81279755	10	135534747	+	81281073	81289810	4510
+39	431	431
+50	752	752
+134	2175	2167
+44	3025	2995
+35	14	9
+7	2005	2010
+64
+
+chain	29298	chr10	135374737	+	81537077	81539110	10	135534747	+	81546931	81548963	3702
+68	791	797
+50	617	605
+33	0	2
+73	308	311
+93
+
+chain	18939	chr10	135374737	+	81450538	81452241	10	135534747	+	81460333	81462036	3255
+39	70	70
+132	1431	1431
+31
+
+chain	6030	chr10	135374737	+	81422413	81430217	10	135534747	+	81432363	81440000	5582
+26	7730	7563
+48
+
+chain	5154	chr10	135374737	+	81371363	81371422	10	135534747	-	72572913	72572972	4033525
+2	1	1
+56
+
+chain	1569	chr10	135374737	+	81371422	81371454	X	155270560	+	63278348	63278380	8657459
+32
+
+chain	1063	chr10	135374737	+	81231366	81231464	10	135534747	-	54101945	54102043	901
+98
+
+chain	4275918	chr10_random	113275	+	18676	65432	5	180915260	+	138864813	138909803	707
+204	2	0
+4653	4	0
+2427	0	1
+5957	0	1
+1558	1	0
+780	1794	33
+29376
+
+chain	870863	chr10_random	113275	+	9144	18556	10	135534747	-	46779061	46789268	4835
+301	2	0
+564	3	0
+802	1	0
+2624	0	112
+142	0	2
+128	100	787
+4745
+
+chain	637317	chr10_random	113275	+	102183	113228	10	135534747	+	88758795	88768050	8258
+1205	22	22
+793	0	1
+914	1	1
+9	0	1
+45	0	1
+9	2477	1631
+132	1562	615
+2006	1	1
+36	1	1
+557	24	23
+885	0	2
+194	1	0
+171
+
+chain	383436	chr10_random	113275	+	97894	101991	10	135534747	+	88848068	88852165	132306
+2932	0	1
+697	4	3
+464
+
+chain	312568	chr10_random	113275	+	0	3305	10	135534747	+	88861095	88864401	225266
+2905	0	1
+400
+
+chain	263395	chr10_random	113275	+	91858	94672	10	135534747	+	88776474	88779288	339622
+1683	3	3
+130	11	11
+987
+
+chain	254817	chr10_random	113275	+	83066	85798	10	135534747	-	46749813	46752549	368581
+201	0	6
+798	0	1
+403	4	0
+841	14	15
+471
+
+chain	244215	chr10_random	113275	+	5995	97779	10	135534747	+	88818267	88897264	4711
+966	0	1
+2072	66256	15486
+2428	10567	42513
+197	0	1
+820	6	6
+18	1	0
+21	0	1
+20	2	1
+1685	0	2
+703	3020	9053
+1156	0	1
+1846
+
+chain	216530	chr10_random	113275	+	72868	75170	10	135534747	-	93082016	93084318	524441
+2302
+
+chain	211663	chr10_random	113275	+	85898	88144	10	135534747	+	88832831	88835078	546276
+536	0	1
+1710
+
+chain	171789	chr10_random	113275	+	70706	72761	10	135534747	-	93140436	93143121	737133
+50	1	1
+68	85	4
+15	15	34
+17	7	53
+13	1	647
+81	1	1
+50	21	21
+1630
+
+chain	129924	chr10_random	113275	+	67807	109229	10	135534747	-	46627912	46728083	8515
+467	0	1
+256	0	1
+42	1	1
+1352	0	2
+308	10219	43352
+227	1	1
+22	1	1
+2232	22395	48006
+1581	0	2
+518	1	1
+30	1	0
+197	132	132
+1439
+
+chain	125160	chr10_random	113275	+	4561	5895	10	135534747	-	46655374	46656707	1028939
+94	1	0
+1239
+
+chain	104003	chr10_random	113275	+	65554	66651	10	135534747	-	93176760	93177857	1232247
+1097
+
+chain	92361	chr10_random	113275	+	66732	67707	10	135534747	-	93158718	93159693	1382147
+975
+
+chain	89191	chr10_random	113275	+	3509	4486	10	135534747	-	129898314	129899289	1428933
+69	1	1
+35	1	0
+336	1	0
+401	1	1
+44	1	1
+87
+
+chain	29685	chr10_random	113275	+	34270	80352	10	135534747	-	46758431	46763489	186939
+210	0	6
+1251	4	4
+73	42015	985
+1249	1	1
+46	1	1
+1232
+
+chain	4572	chr10_random	113275	+	70436	70610	10	135534747	-	93144449	93144623	2904410
+51	50	50
+73
+
+chain	3114	chr10_random	113275	+	70610	70643	10	135534747	-	93147281	93147314	29780913
+33
+
+chain	12415599352	chr11	134452384	+	50000	134451920	11	135006516	+	60000	134946516	11
+1102759	16576	50000
+49571094	207000	307000
+503352	3000000	3100000
+14395596	2605	50000
+488471	34	102
+26	0	176
+30213	141	350
+27914	1	0
+20009	1	0
+19	1	0
+39	1	0
+17	3	1
+10	1	0
+1008	1	0
+95	1	0
+5127	15	0
+302	1	0
+975	0	4
+1548	0	1
+190	20	0
+41	1	0
+29	1	1
+44	0	1
+101	1	0
+25	0	1
+6178	0	1
+1875	21437	52561
+468	1	1
+81	1	1
+2620	1	0
+1640	4	0
+3305	0	1
+3342	1	0
+17899663	12000	50000
+8549206	15562	150000
+38507165	2	0
+1327	174	0
+392	18	0
+48
+
+chain	188276	chr11	134452384	+	69433462	69437111	GL000202.1	40103	+	7212	10860	1247
+1868	1	0
+1780
+
+chain	38178	chr11	134452384	+	134451288	134452384	5	180915260	-	180902450	180903869	1901368
+174	458	926
+1	8	0
+63	136	1
+64	2	0
+190
+
+chain	6040	chr11	134452384	+	134451996	134452128	1	249250621	-	249240179	249240388	3449013
+89	36	113
+7
+
+chain	2221	chr11	134452384	+	134452085	134452111	Y	59373566	+	59362903	59362929	5436109
+26
+
+chain	4284950	chr11_random	215294	+	0	215294	11	135006516	-	65191297	65289033	706
+40524	167558	50000
+7212
+
+chain	3340892	chr11_random	215294	+	90524	125679	11	135006516	+	69689619	69724695	863
+1003	62	0
+3019	1	0
+695	1	1
+26	1	1
+1133	0	1
+1374	2	2
+20	1	1
+729	11	11
+269	0	1
+1091	14	14
+969	21	21
+532	5	5
+2677	18	0
+21481
+
+chain	3051979	chr11_random	215294	+	175679	208082	GL000202.1	40103	-	0	32891	790
+17546	11	51
+27	523	35
+32	6	6
+6712	100	1036
+7446
+
+chain	10612	chr11_random	215294	+	193466	193615	GL000202.1	40103	-	18116	18265	21504297
+59	27	27
+63
+
+chain	5102	chr11_random	215294	+	91527	91580	11	135006516	+	69690684	69690737	20979070
+53
+
+chain	12330181372	chr12	132349534	+	16000	132289534	12	133851895	+	145739	133779461	12
+7035083	0	4
+544	0	1
+3777	0	1
+3889	73000	52114
+6014	1	0
+6524	168	34
+20974	0	2
+3965	3	0
+444	0	11
+464	1	0
+27577110	1395000	3000000
+38631945	0	1
+14541	0	4
+1703	1	0
+789	250000	12128
+1783	1	0
+1075	0	2
+1042	1	0
+1526	1	1
+27	1	1
+2320	0	1
+166	1	0
+564	0	1
+2856	0	2
+900	0	1
+1387	1	1
+33	1	1
+2139	1	1
+48	1	1
+1305	0	2
+1533	1	2
+879	0	1
+744	26	26
+855	0	4
+1092	6	0
+1114	12	0
+817	1	1
+18	1	0
+217	1	1
+36	1	1
+2002	1	0
+1025	0	1
+450	1	1
+43	1	1
+919	1	0
+18	1	1
+3207	42	42
+1440	0	8
+148	4	0
+3655	2	0
+3403	1	1
+47	1	1
+1524	1	1
+28	1	1
+5561	0	2
+44	0	1
+676	8	8
+810	16	16
+536	2	0
+236	4	0
+167	0	4
+1419	49	53
+4688	1	1
+38	1	1
+18577	5	0
+5284	0	2
+1577	34	34
+4875	1	1
+25	1	1
+4340	0	14
+2663	5	0
+1170	1	0
+4268	0	4
+1036	0	1
+2117	0	8
+5917	1	0
+3239	0	4
+2619	1	1
+21	1	1
+937	1	1
+38	1	1
+2412	0	2
+38	17	0
+2732	0	2
+9314	2	0
+1986	2	2
+16	1	1
+229	1	1
+93	1	1
+895	12	0
+415	1	5
+27	1	1
+78	14	14
+185	8	9
+458	0	2
+89	1	1
+42	1	1
+2034	0	1
+1545	0	2
+280	0	4
+97	14	14
+231	0	2
+2816	5	0
+537	50	50
+1090	1	1
+27	1	1
+25758689	0	1
+6536665	0	1
+377270	57000	96749
+668	1	1
+20	1	0
+3348	1	1
+33	1	1
+648	1	1
+29	1	1
+3732	4	0
+977	46	46
+785	4	0
+34	1	0
+1688	0	10
+4248	1	0
+1167	1	0
+985	9	9
+2897	1	0
+1630	9	0
+1096	0	1
+1356	0	8
+13065723	150011	68363
+799	2	0
+343	0	1
+1771	0	1
+2702	7	6
+1900	1	0
+705	6	0
+303	1	0
+727	1	1
+43	1	0
+3	2	0
+490	1	1
+59	1	1
+226	1	1
+52	3	0
+465	0	8
+194	1	1
+25	1	0
+139	1	1
+15	1	1
+1833	1	0
+81	1	1
+39	1	1
+453	1	0
+719	1	1
+47	1	1
+558	1	0
+838	8	1
+288	10	9
+741	5	2
+465	1	1
+48	1	1
+268	1	1
+26	1	0
+1337	30	48
+84	2	85
+917	1	0
+110	31	31
+1580	1	1
+40	1	1
+683	1	1
+24	1	1
+247	1	1
+36	1	1
+1574	0	1
+10091386	0	3
+296	0	5
+220	45000	100872
+972469
+
+chain	2523	chr12	132349534	+	107924339	107924385	20	63025520	-	54448952	54448998	196257
+46
+
+chain	9007877316	chr13	114142980	+	17918000	114127980	13	115169878	+	19020000	115109878	14
+26987167	1	0
+40753157	50000	150000
+25443670	400000	150000
+1821999	384108	414007
+369878
+
+chain	17589560	chr13	114142980	+	113473994	113658050	13	115169878	-	529930	713796	162
+174857	2	0
+1328	144	0
+1156	1	1
+27	1	1
+2159	2	0
+49	1	1
+175	2	0
+20	4	0
+590	30	0
+163	8	4
+2905	2	0
+430
+
+chain	8677	chr13	114142980	+	113650223	113650314	13	115169878	-	706193	706284	25436870
+91
+
+chain	17750502	chr13_random	186858	+	0	186858	GL000212.1	186858	+	0	186858	156
+186858
+
+chain	8359013040	chr14	106368585	+	18070000	106360585	14	107349540	+	19000000	107289540	15
+1081285	1	1
+43	1	1
+76	2	0
+437	1	1
+19	1	1
+440	12	13
+59	15	15
+63	12	12
+70	0	1
+734	1	1
+165	1	4
+96	1	1
+46	1	0
+83	1	1
+149	4	4
+164	1	1
+18	1	1
+63	15	16
+359	1	1
+39	1	1
+103	1	1
+76	1	1
+139	1	1
+38	1	1
+344	1	1
+65	0	1
+166	5	5
+88	1	1
+66	0	287
+50	1	1
+317	0	1
+52	1	1
+92	4	0
+651	4	4
+82	1	1
+93	1	1
+64	1	1
+24	1	1
+856	1	1
+35	1	1
+258	1	1
+17	1	1
+478	1	0
+1048	70	70
+1279	1	1
+37	1	1
+1115	3	4
+72	1	1
+126	1	1
+102	1	1
+413	10	10
+132	6	6
+89	0	2
+209	15	4
+77	5	5
+427	1	1
+41	1	1
+949	1	1
+16	1	1
+732	1	1
+44	2	0
+128	0	1
+91	1	1
+180	6	6
+388	6	6
+50	13	12
+275	1	1
+33	1	1
+142	1	1
+61	1	1
+560	1	1
+20	1	1
+1327	6	13
+729	37	37
+284	1	1
+44	1	1
+205	0	4
+40	1	1
+352	10	10
+261	1	1
+39	1	1
+940	12	0
+1677	36	0
+159	1	1
+32	8	1
+818	0	6
+580	1	0
+931	1	0
+276	2	0
+3298	45	45
+169	14	0
+46	1	1
+882	2	0
+94	1	1
+49	1	1
+859	4	0
+45	1	1
+807	16	15
+416	0	3
+3345	15	15
+92	30	29
+80	1	1
+48	1	1
+2459	0	1
+646	1	1
+31	1	1
+392	1	1
+29	54	0
+1875	3	0
+141696	1	1
+32	1	1
+8201115	1	0
+107	1	0
+2137	1	1
+39	1	1
+8848	0	1
+4806	1	0
+2075	1	0
+16619	41	40
+2338	3	0
+11507	8	0
+1352	0	1
+4596	0	1
+2073	2	1
+28	1	1
+2311	1	1
+44	1	1
+10440	0	4
+894	0	1
+1641	0	96
+38	9	0
+20	1	1
+2706	6	0
+351	1	1
+25	1	1
+742	0	1
+1048	2	18
+12085977	0	1
+14871228	3	0
+29067652	1	1
+47	1	1
+20174307	1292	0
+2548043
+
+chain	14855	chr14	106368585	+	19159713	19190443	14	107349540	-	87865807	87904514	64
+20	0	6
+50	9933	9915
+37	16916	24930
+30	3690	3692
+25	27	0
+2
+
+chain	6432	chr14	106368585	+	19179765	19190441	22	51304566	+	16377620	16388301	97
+45	10604	10609
+27
+
+chain	7700812247	chr15	100338915	+	18260008	100338915	15	102531392	+	20000000	102521392	16
+8448	6	2
+4086	1	0
+9569	1	1
+40	0	5
+56	7	1
+872419	40441	40448
+553	4	4
+876	0	1
+38	1	1
+139	1	1
+23	1	1
+1881	1	1
+17	1	0
+499	8	8
+310	2	2
+25	11	5
+46	1	1
+78	1	1
+22	0	3
+181	5	6
+569	11	11
+539	1	1
+23	0	4
+261	1	1
+19	0	2
+776	13	15
+62	13	13
+860	1	0
+719	26	0
+1346	1	1
+134	0	1
+30	1	1
+1070	1	1
+21	1	1
+398	0	1
+177	5	21
+534	4	0
+770	0	6
+17	1	1
+606	1	1
+31	1	1
+1861	1	1
+53	1	1
+2169	3	0
+558	1	0
+18	1	1
+227	2	0
+13	1	1
+329	5	5
+430	1	1
+17	2	0
+620	0	1
+1112	2	0
+641	0	4
+476	1	1
+45	1	1
+1285	0	1
+1139	1	1
+47	1	1
+183	4	0
+1435	20	0
+176	0	1
+219	0	1
+607	1	1
+42	1	1
+371	2	8
+507	2	0
+66	1	0
+41	1	1
+999	4	4
+318	15	15
+1092	1	1
+72	1	1
+808	5	5
+54	2	2
+52	1	1
+40	1	1
+109	3	3
+47	1	1
+1535	14	0
+14012	4	0
+7954	4	1
+1350	1	0
+318	1	1
+25	1	1
+600	0	4
+442	0	1
+1396	1	1
+36	1	1
+1107	0	3
+1441	0	5
+360	1	1
+47	1	1
+228	10	0
+37	1	1
+497	1	1
+37	1	1
+2129	4	0
+1242	2	0
+478	4	0
+708	1	1
+90	1	1
+154	10	10
+1583	1	1
+31	1	1
+1302	0	37
+101	14	14
+1138	1	1
+83	10	0
+11	7	0
+111	1	1
+29	1	1
+2917	1	1
+32	1	1
+1762	1	1
+46	1	1
+449	1	0
+2458	9	1
+869	1	0
+534	1	1
+47	1	1
+309	1	0
+6358	22	0
+564	0	1
+1845	1	0
+660	1	1
+25	1	1
+68	1	0
+182	0	9
+54	3	18
+1519	1	1
+32	1	1
+559	1	1
+30	1	1
+3851	1	0
+265	8	7
+240	4474	0
+428	1	0
+1651	11	10
+297	1	0
+665	21	0
+48	1	1
+1763	2	0
+245	1	1
+39	1	1
+519	1	1
+31	1	1
+2398	0	6
+749	49	1
+2074	4	0
+701	5	5
+337	1	0
+470	1	1
+43	1	1
+1163	3	0
+1342	1	1
+43	1	1
+140	0	1
+83	1	1
+24	1	2
+37	1	1
+723	1	1
+36	1	1
+99	3	0
+27	1	1
+92	1	0
+80	43	43
+1095	0	13
+384	0	2
+292	1	1
+39	1	1
+101	12	12
+576	0	2
+1907	1	1
+19	1	1
+318	1	0
+1973	1	1
+32	1	1
+689	1	1
+49	1	1
+357	8	8
+2081	13	13
+260	15	15
+2295	1	1
+24	1	1
+2558	1	1
+26	1	1
+571	16	23
+323	0	1
+36	0	1
+5353	111	0
+1711	38	70
+272	13	13
+1284	0	1
+1128	4	4
+2189	1	0
+474	2	0
+1284	61	67
+643	1	1
+37	1	1
+381	0	2
+56	1	0
+2591	1	1
+55	1	1
+160	4	4
+116	1	1
+89	2	0
+316	0	1
+785	20	0
+152	1	1
+21	1	1
+600	0	6
+568	1	0
+278	1	1
+29	1	1
+89	0	4
+1737	1	1
+58	1	1
+368	24	24
+2113	20	24
+218	0	2
+18	1	1
+684	4	4
+3200	1	1
+31	1	1
+58	18	18
+164	1	1
+37	1	1
+296	6	6
+431	1	1
+35	1	1
+431	1	1
+45	1	1
+93	1	1
+24	1	1
+216	1	1
+46	1	1
+2773	0	17
+751	2	1
+104	1	1
+59	1	1
+445	1	1
+26	1	1
+356	1	0
+1484	1	2
+436	25	25
+306	1	1
+55	1	1
+230	4	4
+892	1	0
+364	7	7
+796	1	1
+26	1	1
+663	0	2
+80	0	15
+4391	1	0
+133	1	1
+25	0	4
+41	0	2
+164	1	1
+61	4	4
+925	3	0
+1882	13	13
+4513	1	0
+111	1	1
+76	1	1
+202	6	0
+680	0	1
+200	3	0
+429	0	2
+736	1	1
+18	1	1
+1573	0	1
+119	1	1
+245	0	9
+11	1	1
+1656	54	22
+616	2	1
+158	0	1
+587	1	1
+39	4	1
+1053	6	6
+1116	1	1
+34	1	1
+152	10	7
+448	0	1
+269024	100000	863295
+334079	100000	50000
+180553	0	74
+66	73	3
+40	1	0
+28	156	73
+202	1	1
+17	0	1
+156	1	1
+55	1	1
+111	0	1
+144	1	1
+57	0	1
+687074	50000	50000
+120647	0	348
+45586	0	1
+6994	1	0
+3398063	44008	12354
+7672	0	2
+1809	1	0
+428524	101014	10165
+43170	4	4
+1064959	128966	5086
+1021	0	1
+1710	1	0
+931	0	2
+4505	0	1
+686	525	2
+432	33	0
+58	20	20
+12369	1014	0
+6233	0	1
+359485	100000	111749
+33855821	0	239
+2852113	1	0
+7040367	0	1
+2815738	3	1
+7055922	60000	50000
+363827	32	32
+104991	0	1
+203136	0	6050
+2271	47	47
+1424473	60000	50000
+13510190	22012	5553
+9194	0	3
+109	0	4
+40	0	1
+43	0	7
+2352	0	13
+5027	0	2
+534	1	0
+794	0	2
+4233	0	2
+5769	1	0
+381	1	0
+2524	0	2
+547	0	5
+1967	0	1
+1207	105	0
+1027	0	6
+3935380
+
+chain	4143271	chr15	100338915	+	19154641	19368514	15	102531392	+	21901264	22115049	110
+40441	8593	8593
+26	89965	89965
+4257	1	1
+30	1	1
+185	16464	16391
+43	29947	29883
+25	1	1
+34	23835	23884
+25
+
+chain	390135	chr15	100338915	+	26478746	26483022	15	102531392	+	28681030	28685306	6048
+1039	22	22
+3215
+
+chain	187810	chr15	100338915	+	26483022	26517556	15	102531392	-	73809068	73843318	79
+41	12	0
+36	1	1
+490	5	5
+285	1	1
+71	1	1
+215	1	1
+53	0	12
+8114	1	0
+10796	15	15
+2483	0	1
+20	1	1
+2048	8856	8847
+163	792	517
+33
+
+chain	51529	chr15	100338915	+	26530390	26530949	15	102531392	+	28731348	28731907	2473877
+450	8	8
+101
+
+chain	17522	chr15	100338915	+	26516748	26516957	15	102531392	+	22658399	22658608	1968
+209
+
+chain	14035	chr15	100338915	+	20378176	20378474	15	102531392	+	22829101	22829399	772378
+73	69	69
+156
+
+chain	12347	chr15	100338915	+	26530060	26530390	15	102531392	+	22671289	22671619	3189077
+244	4	4
+82
+
+chain	5537	chr15	100338915	+	96402403	96402461	15	102531392	+	98585049	98585107	22350382
+58
+
+chain	4486	chr15	100338915	+	96402461	96402508	15	102531392	+	98585002	98585049	16761199
+47
+
+chain	2874	chr15	100338915	+	26517060	26517091	15	102531392	+	28719096	28719127	6634083
+31
+
+chain	2874	chr15	100338915	+	26517029	26517060	15	102531392	+	28719096	28719127	6634084
+31
+
+chain	2874	chr15	100338915	+	26516998	26517029	15	102531392	+	28719096	28719127	6634085
+31
+
+chain	2874	chr15	100338915	+	26516967	26516998	15	102531392	+	28719096	28719127	6634086
+31
+
+chain	2314	chr15	100338915	+	26530003	26530033	15	102531392	+	22671232	22671262	5236
+30
+
+chain	12940492	chr15_random	784346	+	189260	358080	15	102531392	+	28561246	28726591	233
+2522	0	1
+3762	1	1
+40	1	1
+2427	6472	2
+1744	0	1
+263	0	7
+2963	4	4
+1889	1	0
+2501	0	1
+3377	6	6
+5238	0	1
+1277	5	5
+38	1	1
+8232	12	8
+5507	0	18
+155	1	0
+379	14	14
+363	7	13
+336	1	1
+46	1	1
+218	8	8
+1074	0	4
+101	12	13
+178	1	1
+93	1	1
+156	10	11
+398	0	20
+45	1	1
+255	9	10
+2661	0	1
+17	1	1
+82	1	1
+14	1	1
+227	64	64
+1154	1	0
+493	1	1
+39	1	1
+369	1	0
+21	1	1
+322	2	7
+222	0	2
+171	15	0
+81	1	1
+47	1	1
+159	9	9
+154	1	0
+272	4	4
+26	1	1
+121	8	7
+659	1	0
+440	1	1
+35	1	0
+1419	15	0
+181	0	2
+292	0	15
+1767	1	1
+44	1	1
+59	0	1
+910	0	1
+290	1	0
+288	1	0
+567	2	0
+1088	0	1
+1758	1	0
+72	1	1
+21	1	1
+5748	17	17
+800	0	1
+2037	13	13
+113	5	5
+2832	1	1
+44	1	1
+3581	2	0
+33	1	1
+812	5	5
+33	0	1
+257	17	17
+1932	0	14
+168	0	1
+424	5	0
+24	1	1
+67	14	14
+90	1	5
+124	1	1
+34	1	1
+48	0	9
+460	0	8
+294	7	0
+813	1	3
+240	1	0
+511	0	9
+190	1	0
+267	1	1
+38	1	1
+1082	7	57
+21	15	0
+28	0	1
+5	1	1
+123	0	5
+781	1	1
+21	1	1
+390	1	1
+36	1	1
+287	1	1
+90	0	3
+6	2	2
+189	9	9
+263	2	1
+724	13	14
+308	2	0
+1752	1	1
+114	1	1
+236	4	0
+46	1	1
+72	5	0
+1039	1	1
+25	1	1
+403	1	1
+22	1	1
+231	6	6
+834	15	15
+617	1	1
+53	1	1
+243	1	1
+154	3	5
+571	11	16
+231	1	1
+47	1	1
+910	1	1
+45	1	1
+1510	1	1
+79	1	1
+2053	1	1
+48	1	1
+768	8	8
+546	1	1
+19	1	5702
+784	6	0
+275	20	13
+131	114	114
+363	1	1
+46	1	1
+396	1	1
+39	1	1
+75	15	15
+1875	1	0
+332	1	1
+49	1	1
+265	3	2
+55	1	1
+96	1	1
+136	1	0
+305	8	8
+297	0	2
+255	2	2
+23	1	1
+181	19	6
+151	0	1
+707	667	9324
+284	5	3
+73	1	1
+208	26	25
+34	0	773
+80	20	0
+2003	400	125
+163	2	0
+2630	9	1
+19	1	1
+100	12	0
+2421	0	2
+47	21227	0
+853	1	0
+1238	0	12
+3571	1	1
+20	0	1
+2483	15	15
+8803	287	9594
+5992
+
+chain	8627768	chr15_random	784346	+	422939	629603	15	102531392	-	19338638	19927596	385
+168	56	59
+73	4	4
+378	23	23
+868	29	29
+85	1	0
+528	119	5106
+152	31	31
+184	8	7
+322	0	1
+62	46	45
+77	37	46
+80	22	22
+201	45	47
+175	31	33
+1923	82	77
+546	7051	32690
+7810	209	153340
+1308	1	0
+9826	1	0
+1486	1	1
+148	1	0
+76	6	6
+53	36	34
+178	5447	565
+14	14505	121
+72	13	16
+57	1	1
+157	0	2
+11	1	1
+74	1	1
+24	3	3
+220	1	1
+54	1	1
+142	1	1
+82	2	0
+60	4	0
+99	1	1
+106	1	1
+98	1	1
+402	1	1
+79	4	7
+78	1	9
+5	0	1
+31	7	7
+65	1	1
+105	0	1
+22	6	8
+76	10	8
+47	0	1
+39	3	0
+5	1	3
+108	2	2
+61	16307	40121
+676	26	26
+7087	25	25
+20818	7	7
+2750	60358	90388
+69	54	53
+165	166	516
+42	0	42
+81	4	151
+18	0	42
+148	111	112
+73	4	4
+378	23	23
+868	29	29
+85	1	0
+528	8	8
+280	32	34
+426	78	79
+81	648	334
+181	8	7
+485	0	2
+1404	24	24
+101	36	38
+240	8	8
+77	53	54
+347	18	18
+72	9	9
+94	82	82
+384	8	8
+250	108	151474
+1152	0	1
+633	226	12498
+3255	4	0
+58	32	32
+6209	1	1
+30	1	0
+1060	2	0
+3747	4	4
+173	5	5
+2548	0	22
+2275	0	20
+606	41	41
+4653	12	12
+6138	0	1
+148	5	0
+244
+
+chain	3986761	chr15_random	784346	+	0	334816	15	102531392	-	78891064	79878228	248
+30328	8040	15984
+3015	1	0
+70	44499	160931
+52	0	5
+1038	1	1
+29	1	1
+1001	0	18
+680	0	329
+181	1	1
+32	1	1
+839	2	0
+440	0	3
+547	1	0
+278	1	0
+410	1	1
+26	3	0
+101	1	1
+24	1	1
+149	0	9
+179	2	1
+29	1	1
+226	3	0
+21	1	1
+473	10	0
+717	2	0
+1044	1	1
+23	1	1
+625	1	1
+41	1	0
+150	1	1
+62	1	1
+145	59	59
+242	12	12
+179	1	1
+64	1	1
+1405	1	1
+35	0	2
+469	5	0
+401	0	1
+25	0	10
+17	1	1
+55	1	1
+165	1	1
+1966	15	23
+839	0	18
+969	1	1
+44	1	1
+1905	1	1
+47	1	1
+1037	128	128
+486	5	0
+1086	2	1
+199	4	4
+59	2	0
+243	84	0
+410	1	1
+39	1	1
+70	0	324
+77	1	187
+42	4	151
+897	135051	676116
+64	54092	52483
+25	1	1
+88	9286	18277
+201	26614	5202
+33	1	0
+1
+
+chain	2185345	chr15_random	784346	+	423107	689458	15	102531392	+	82637661	83186296	482
+30	0	5
+26	1346	1346
+29	885	5865
+31	576	577
+46	77	77
+5	0	1
+32	303	304
+45	175	176
+31	1923	1923
+66	1943	144683
+715	0	1
+548	13	13
+1907	1	1
+16	1	1
+66	3	0
+1219	5	1
+1066	34012	198199
+7204	2446	2446
+2762	100	7680
+5162	1	0
+2782	1	1
+26	7	4
+49	1	1
+3627	3	0
+1686	133598	65296
+3109	1	1
+21	1	1
+1430	63	63
+335	3	3
+14	4	0
+203	1	1
+23	5	5
+1262	4	4
+323	1	1
+47	1	1
+417	0	1
+537	19	1
+1913	2	0
+1685	6	0
+1740	1	1
+49	1	1
+120	1	1
+30	0	3
+920	4	0
+479	30	30
+1207	1	1
+182	4	0
+72	3	1
+78	1	1
+150	1	1
+46	1	1
+222	1	1
+24	1	1
+74	1	1
+44	1	1
+391	1	1
+33	1	1
+149	9	8
+56	1	1
+30	1	0
+52	1	1
+298	6	0
+22	1	0
+29	1	1
+393	35	0
+145	36	36
+226	15	15
+185	7	7
+692	1	1
+34	1	1
+1291	0	2
+1824	5	5
+1119	1	1
+49	1	2
+1025	25013	44930
+835	88	11347
+692	0	2
+2551	3	0
+1144	82	77
+1939	26	28
+164	1	1
+44	0	2
+201	1	1
+133	5	14
+77	1	1
+44	1	0
+92	1	0
+293	8	7
+184	31	31
+381	8	8
+384	1	1
+80	1	1
+94	9	9
+57
+
+chain	1845967	chr15_random	784346	+	61569	84889	15	102531392	-	73695594	73766494	782
+153	33	33
+49	1	0
+197	15	15
+67	62	62
+241	12	9
+185	41	44
+64	23	23
+559	50	50
+333	46	46
+397	6	6
+141	4	0
+660	50	50
+315	38	38
+282	309	47864
+57	7	7
+85	39	39
+340	62	62
+43	0	1
+77	0	1
+768	0	12
+71	70	69
+102	17	17
+58	45	50
+676	2	0
+430	21	22
+112	0	1
+401	4	0
+617	95	95
+168	50	50
+442	4	0
+91	114	114
+463	0	1
+94	28	28
+1577	16	16
+572	0	1
+1451	55	55
+2327	51	51
+394	1	0
+109	21	24
+660	50	54
+703	1	0
+93	22	22
+94	48	48
+219	46	46
+352	22	22
+150	155	161
+173	19	19
+162	6	12
+1201	48	49
+119	17	17
+435	4	4
+146	38	38
+946	10	10
+98	37	37
+60	47	47
+579
+
+chain	1297748	chr15_random	784346	+	203918	328028	15	102531392	-	73698913	73856126	264
+567	109104	118059
+369	106	23997
+700	2	0
+40	0	248
+320	0	33
+130	1	1
+18	1	1
+138	20	20
+1341	8	0
+863	1	1
+48	1	1
+240	1	1
+34	20	0
+3218	1	1
+20	1	1
+2062	46	46
+285	14	14
+937	1	1
+25	3	3
+305	1	1
+42	1	1
+706	2	0
+232	1	1
+67	1	1
+88	4	5
+844	1	1
+82	1	1
+430	0	7
+78	1	1
+458	27	27
+52
+
+chain	898399	chr15_random	784346	+	457589	504019	15	102531392	-	19636589	19905366	626
+5344	14	14
+7167	26767	249114
+26	7087	7087
+25
+
+chain	844102	chr15_random	784346	+	95554	784338	15	102531392	+	22730405	27183335	411
+59	9906	9932
+128	2128	2090
+42	1792	637909
+89	10	10
+71	198	198
+122	137	141
+341	29	29
+104	103	103
+395	11	14
+667	6	7
+74	7	0
+178	1	5
+203	9	4
+172	55	55
+791	25	25
+714	19	22
+597	133	133
+142	2	0
+252	0	4
+260	67	67
+41	6	0
+860	29	30
+258	93	95
+1793	11	11
+358	71	70
+242	1	1
+20	1	1
+1308	0	3
+468	0	2
+755	1	1
+81	2	2
+72	3	0
+597	4	4
+492	25	7
+1459	10	9
+674	16	16
+711	1	1
+49	1	1
+1525	1	1
+45	1	1
+2919	1	1
+36	1	1
+493	1	1
+21	1	1
+830	16	0
+3	7	0
+644	17	17
+479	0	1
+2343	0	315
+307	8	311
+87	0	3
+330	42	0
+520	7	6
+72	2	1
+745	6	6
+324	6	0
+398	22	22
+118	27	27
+68	600887	3728395
+44872
+
+chain	555121	chr15_random	784346	+	634265	679702	15	102531392	+	82723475	82991213	602
+20	1	1
+41	24204	246463
+2085	6	6
+667	14	14
+596	0	24
+1743	415	422
+870	1	0
+3572	1	1
+1152	8	0
+498	0	1
+3239	1	1
+34	1	1
+1283	1	1
+41	1	0
+676	0	2
+2078	0	1
+1283	0	18
+681	1	0
+223
+
+chain	530253	chr15_random	784346	+	409131	430676	15	102531392	-	19567939	19581201	1716
+786	8	0
+171	8918	159
+2113	8268	8752
+1281
+
+chain	417534	chr15_random	784346	+	35735	80744	15	102531392	+	23413134	23608954	1095
+840	0	54
+916	0	2
+777	3337	13583
+637	50	57
+858	0	4
+779	0	14
+171	1	2
+927	4	0
+1753	2	0
+814	35	35
+1073	14	14
+81	99	101
+66	42	42
+1291	66	66
+240	45	48
+68	36	36
+98	38	38
+1141	5	5
+70	14	15
+150	46	46
+650	13461	153954
+62	1206	1201
+45	3148	3138
+46	6617	6616
+50	2415	2415
+46	615	621
+64
+
+chain	169648	chr15_random	784346	+	417136	418914	5	180915260	+	131590649	131592427	748288
+1778
+
+chain	152639	chr15_random	784346	+	200201	201828	15	102531392	+	28662778	28664407	841936
+970	0	1
+468	5	6
+184
+
+chain	151945	chr15_random	784346	+	110737	203590	15	102531392	-	73700255	73867708	1083
+74	87238	121334
+88	426	14673
+942	2	0
+567	1880	28137
+86	1	1
+62	1	1
+716	14	14
+212	0	1
+468	0	1
+76
+
+chain	142059	chr15_random	784346	+	583198	664057	15	102531392	-	16763491	17663089	651
+176	7	7
+242	7	7
+1002	1	1
+61	1	1
+286	10	10
+1697	57790	716388
+17	1	1
+12	3589	70884
+35	145	145
+36	6576	99374
+431	11	1
+19	0	4
+96	2	0
+98	1	1
+62	1	1
+1047	10	15
+223	1	0
+575	2	0
+465	1	0
+8	1	1
+140	1	4
+65	1	1
+381	5111	5164
+145	1	1
+29	1	6
+32	8	2
+199
+
+chain	140486	chr15_random	784346	+	414032	415531	5	180915260	+	131627050	131628561	916856
+486	0	13
+290	2	1
+721
+
+chain	136843	chr15_random	784346	+	411466	412886	5	180915260	-	49283520	49284940	941594
+1420
+
+chain	113176	chr15_random	784346	+	577887	601700	15	102531392	+	85729223	85793813	754
+51	12	12
+630	1	1
+27	5	5
+51	41	41
+249	505	29710
+148	24	24
+110	0	2
+145	12	11
+646	54	53
+291	404	700
+590	7	0
+154	1	1
+36	5	3
+106	1	1
+42	1	1
+517	181	27
+164	18572	30011
+30
+
+chain	110898	chr15_random	784346	+	410214	411366	5	180915260	-	49350156	49351308	1158024
+1152
+
+chain	90718	chr15_random	784346	+	415631	422839	5	180915260	-	49281425	49321173	523505
+1405	4191	36723
+57	0	4
+785	0	4
+770
+
+chain	87628	chr15_random	784346	+	412986	413908	15	102531392	+	82958289	82959211	1453275
+922
+
+chain	78489	chr15_random	784346	+	408080	408895	5	180915260	+	131628738	131629553	1616335
+815
+
+chain	75848	chr15_random	784346	+	328894	334289	15	102531392	+	28663807	28669202	22165
+415	0	1
+219	14	14
+716	1	1
+62	1	1
+1820	1	0
+432	1	1
+21	1	1
+549	1	1
+42	1	1
+1098
+
+chain	55946	chr15_random	784346	+	579203	582900	15	102531392	-	19568187	19572180	874
+256	1085	1091
+54	291	291
+49	100	396
+255	1464	1453
+62	1	6
+80
+
+chain	50039	chr15_random	784346	+	328288	328894	15	102531392	-	73792653	73793260	1678654
+449	99	100
+58
+
+chain	41737	chr15_random	784346	+	53223	55079	15	102531392	-	79138743	79140590	1899
+987	5	0
+378	4	0
+30	1	1
+324	1	1
+36	1	1
+89
+
+chain	40184	chr15_random	784346	+	35650	52319	15	102531392	+	23578289	23604839	1865
+85	6507	16388
+50	5309	5309
+35	1168	1168
+99	66	66
+42	1291	1291
+66	240	240
+45	68	68
+36	98	98
+38	1380	1380
+46
+
+chain	36402	chr15_random	784346	+	63654	139260	15	102531392	+	20712328	20743651	996
+46	46877	2371
+29	5894	5886
+28	261	261
+55	0	3
+35	2163	2163
+70	17110	17298
+32	0	42
+10	2220	2218
+27	68	68
+335	31	31
+315
+
+chain	33407	chr15_random	784346	+	63271	84310	15	102531392	+	28567817	28636450	784
+50	2730	50298
+39	1361	1355
+70	2485	2497
+95	168	168
+50	618	618
+33	8782	8789
+48	4472	4485
+38
+
+chain	26884	chr15_random	784346	+	71527	84203	15	102531392	+	23434933	23447596	1313
+28	3628	3632
+43	3563	3545
+38	1762	1762
+91	1625	1625
+17	1	1
+30	721	722
+38	1054	1054
+37
+
+chain	17994	chr15_random	784346	+	577754	595591	15	102531392	+	82746005	82941680	2345
+133	777	777
+41	8083	152910
+1120	114	33023
+47	1	1
+5	265	681
+66	293	293
+111	2277	2277
+32	585	587
+5	0	1
+25	0	1
+6	1	0
+11	3164	2847
+53	540	540
+82
+
+chain	17584	chr15_random	784346	+	334305	334490	15	102531392	-	73868107	73868292	12488910
+185
+
+chain	16638	chr15_random	784346	+	334590	334767	15	102531392	+	28693782	28693959	13398527
+177
+
+chain	15574	chr15_random	784346	+	203754	203918	15	102531392	+	20713399	20713563	2884965
+164
+
+chain	11941	chr15_random	784346	+	112567	138945	15	102531392	+	28572611	28599524	1070
+24	791	791
+25	2119	2124
+57	23331	23861
+31
+
+chain	10106	chr15_random	784346	+	307857	307966	15	102531392	-	73812018	73812127	6634519
+109
+
+chain	9879	chr15_random	784346	+	198177	198415	15	102531392	+	28709863	28710101	596395
+238
+
+chain	5493	chr15_random	784346	+	34234	34291	Y	59373566	+	27644447	27644504	32044688
+57
+
+chain	4133	chr15_random	784346	+	323293	323339	15	102531392	+	22666870	22666916	2166
+46
+
+chain	4016	chr15_random	784346	+	328237	328288	15	102531392	+	28668851	28668902	1790991
+51
+
+chain	3958	chr15_random	784346	+	107733	107775	15	102531392	-	78958306	78958348	1193
+42
+
+chain	3427	chr15_random	784346	+	198013	198049	15	102531392	+	20714128	20714164	4212128
+36
+
+chain	3014	chr15_random	784346	+	591545	685196	15	102531392	-	19431434	19585695	819
+47	89045	149655
+87	4422	4422
+50
+
+chain	2874	chr15_random	784346	+	307826	307857	15	102531392	-	73812018	73812049	6634520
+31
+
+chain	2855	chr15_random	784346	+	198147	198177	15	102531392	+	28831982	28832012	6776371
+30
+
+chain	2097	chr15_random	784346	+	200178	200201	15	102531392	-	79852957	79852980	911500
+23
+
+chain	1855	chr15_random	784346	+	307785	307816	15	102531392	+	28688468	28688499	5960032
+31
+
+chain	1291	chr15_random	784346	+	110710	110736	15	102531392	-	73822377	73822403	1552683
+26
+
+chain	1093	chr15_random	784346	+	687136	688443	15	102531392	-	19508634	19509938	742
+25	1251	1248
+31
+
+chain	7474990131	chr16	88827254	+	0	88822254	16	90354753	+	60000	90294753	17
+172342	0	1
+112	1	0
+5627	2	1
+8398838	17500	50000
+25336229	100000	150000
+1112651	9800000	11100000
+42003582	20000	50000
+1855370
+
+chain	9963354	chr16_random	105485	+	0	105485	16	90354753	+	29712462	29819360	326
+5589	7	8
+6783	0	218
+41	1	3
+38	1	1
+234	9	9
+219	46	0
+15	0	50
+3818	0	1
+1090	1	1
+45	1	1
+308	1	0
+524	0	4
+984	1	1
+24	1	0
+970	0	2
+106	1	1
+25	2	1
+436	0	5
+296	1	1
+23	2	0
+813	0	1
+1173	1	0
+5500	1	0
+1193	16	16
+1329	0	1
+2727	0	1
+3622	0	13
+3844	3	0
+5076	0	1
+4157	2	0
+178	0	2
+126	1	1
+344	5	6
+497	1	0
+620	7	7
+378	0	1
+669	24	25
+211	1	5
+453	0	11
+176	0	1
+486	0	8
+326	1	0
+2143	40	9
+2337	0	1
+866	1	0
+10	2	2
+1366	1	1
+44	1	1
+831	1	1
+45	1	1
+1612	6	5
+3801	0	1
+910	0	2
+486	0	1
+2775	1	0
+1083	1	0
+1793	1	1
+50	0	1
+1339	0	2
+145	17	17
+651	10	10
+1140	0	1
+724	1	1
+39	1	1
+3261	1	0
+1513	0	9
+606	22	0
+2027	27	19
+3470	11	0
+4100	3	0
+2045	0	4
+1047	0	1
+6647	78	1279
+748
+
+chain	7369813928	chr17	78774742	+	0	78653129	17	81195210	+	0	81060000	18
+252627	1	1
+24	1	1
+33	0	29
+566	87	0
+116	58	0
+92	29	0
+79	8	37
+485	1	59
+28	1	1
+76	233	1
+27	29	0
+2764	17	20
+2220	18	18
+837	1	1
+39	1	1
+564	1	1
+14	1	1
+2523	39	9
+1824	0	56
+76	29	0
+1681	0	1
+414	0	3
+256	0	68
+119	10	10
+290	0	4
+3193	1	0
+2562	0	4
+1809	3	0
+84	1	1
+62	1	1
+3703	0	27
+2041	16	0
+911	0	2
+696	4	4
+1428	15	15
+290	1	0
+1779	0	1
+60	1	1
+216	0	1
+375	1	1
+41	0	1
+9221	46522	100000
+3080543	0	1
+1208216	0	2
+1370	2	0
+1279	0	4
+322	0	5
+5661	210	0
+307	21	22
+973	8	0
+2901	1	0
+8479	0	1
+4122	7	0
+3187	4	0
+571	0	1
+167	0	1
+10174	7	7
+856	2	1
+1630	1	0
+4258	3	1
+1688	1	0
+264	0	304
+796	1	0
+8494	0	10
+2273	1	0
+8297	1	0
+1500	1	4
+733	2	2
+40	1	0
+4	0	1
+15	19	1
+64	1	253
+22	0	34
+18	1	205
+2070	2	0
+2981	14	13
+1309	0	1
+3991	3	0
+1939	0	3
+887	0	2
+463	18	0
+64	0	3
+2104	0	20
+556	0	4
+121	0	1
+3670	2	0
+4345	0	5394
+5334	0	1
+2505	4	10
+6776	14	11
+9573	0	1
+1136	0	2
+3754	1	0
+4588	1	0
+637	17	17
+1285	8	0
+369	0	1
+2084	1	0
+492	2	0
+517	0	4
+954	0	2
+1517	1	0
+958	9	0
+807	14	14
+357	0	10
+3611	0	2
+3191	0	39
+742	1	0
+646	2	0
+2211	1	0
+14829	1	0
+3465	11	0
+31	0	33
+833	16	16
+1345	0	1
+6443	5	4
+2627353	1	0
+11581979	0	43
+25	0	89
+238783	0	1
+1830653	1	0
+419873	100008	116477
+5587	6	0
+11056	0	2
+3240	1	0
+1237	0	2
+373	1	1
+43	1	1
+558379	100000	3000000
+1823446	0	1
+2728383	0	1
+29	0	1
+138	1	0
+144	6	8
+38	0	2
+7	0	1
+18	1	1
+70935	10	13
+52	28	31
+189	0	1
+41	2	2
+750363	44	44
+4038953	100000	50000
+1524006	1	1
+47	1	1
+231	2	0
+1175	1	0
+555	1	1
+49	1	1
+568	7	0
+605	2	0
+4954	1	1
+18	6	7
+567	0	1
+421	2	0
+943	75	67
+777	0	3
+925	3	0
+5	4	0
+318	1	0
+230	20	13
+244	1	1
+13	0	1
+42	1	1
+220	1	1
+56	1	1
+101	225	0
+1113	1	0
+17	1	1
+2614	4	0
+3186	50	50
+3872	0	2
+617	14	0
+5674	0	2
+1852	1	1
+63	1	1
+56	1	1
+25	1	1
+332	0	6
+423	5	5
+61	4	0
+108	1	1
+46	1	1
+160	2	2
+72	1	1
+162	1	1
+20	1	1
+53	1	1
+63	1	1
+112	1	1
+59	1	1
+5885	2	0
+255	36	36
+6246	1	1
+114	1	1
+255	1	1
+49	1	1
+210	1	1
+138	157793	28603
+927	5	0
+212	7	7
+641	17	17
+1296	46	46
+2513	71	69
+76	1	2
+61	50226	0
+1959	18	18
+2727	22	22
+6616	1	0
+5109	68	86
+2450	7	7
+50	10	0
+3439	0	4
+4179	0	4
+2749	0	1
+1124	8	0
+56	1	1
+1840	14	14
+624	8	0
+1743	4	0
+3689	0	4
+2051	0	1
+751	0	1
+2111	10	11
+3110	1	0
+682	1	0
+2795	5	2
+241	0	1
+165	1	3
+1258	0	1
+1602	5	0
+3715	0	1
+1308	0	1
+2058	1	0
+1624	0	1
+478	4	0
+9	6	0
+35	3	1
+47	0	1
+2425	1	0
+1178	0	4
+33	1	1
+415	5	5
+887	1	3
+946	29	29
+630	15	0
+259	2	0
+78	0	1
+4570	0	1
+322	1	0
+1801	2	0
+836	3	0
+1509	0	1
+1732	0	1
+935	0	6
+1372	1	0
+625	2	12
+5009	1	1
+75	0	1
+20	1	0
+153	20	21
+489	4	326
+1375	1	0
+774	1	1
+16	1	1
+3642	5	0
+497	4	0
+174	9	0
+1317	0	3
+508	0	1
+1126	1	0
+1952	0	2
+565	2	0
+871	0	1
+1460	6	0
+55	0	1
+420	6	0
+57	1	1
+119	1	1
+427	1	0
+459	14	11
+448	0	1
+1275	7	7
+360	1	0
+73	1	1
+48	1	1
+4920	3	0
+713	41	34
+691	1	1
+44	1	1
+1642	9	10
+566	0	1
+173	0	4
+798	0	10
+810	1	0
+78	18	17
+1531	0	2
+1274	1	1
+39	1	1
+53	3	1
+202	0	1
+707	17	17
+1733	0	1
+14053	3	0
+286	3	1
+5600	4	0
+6458	0	1
+4866371	102000	0
+1870113	257	0
+590050	6	18
+2095	12	12
+24846	1	0
+5154	22	22
+1561	0	4
+5946	1	0
+2317	0	4
+1643	1	1
+27	1	1
+1237	1	0
+2698	1	1
+140	1	1
+1689	0	2
+836	29	30
+5333	1	0
+509	1	0
+5216	6	0
+10782	47	47
+1095	13	3
+1039	0	1
+11605	1	0
+22064	0	1
+16612	8	0
+902	1	0
+757	1	0
+619	0	1
+10979	1	1
+18	1	1
+1517	1	0
+4576	1	0
+12559	4	0
+2725	0	1
+5291	2	0
+8706	0	1
+83	1	0
+424	0	7
+72	38	0
+5528	1	0
+23971	1	0
+7855	54	22
+4095	0	1
+803	5	5
+6382	6	0
+3545	0	28
+4265	0	2
+13194	6	6
+6463	1	0
+26075	1	1
+59	1	1
+10791	17	7
+707	0	1
+210	1	0
+1655	0	2
+5301	1	0
+1930	1	0
+14632	2	0
+1043	1	0
+3607	3	0
+312	0	1
+5953	2	0
+170	0	17
+489	0	1
+5260	0	28
+888	10	0
+2461	10	10
+237	2	0
+1716	3	1
+10691	0	4
+3757	1	0
+6173	0	1
+8017	1	2
+3594	0	4
+5439	0	1
+4138	28	57
+6418	0	1
+1267	1	0
+720	0	6
+1083	2	0
+3878	0	1
+3310	23	23
+4349	1	1
+44	1	1
+3135	0	1
+174853	1	2
+2008	7	7
+5657	0	1
+6496	0	3
+89	0	5
+665	0	1
+954	46	46
+375	7	8
+1248	28	28
+2041	0	2
+2753	1	0
+1863	0	3
+3228	1	0
+3575	0	4
+40	1	1
+6488	0	2
+8612	11	11
+3795	0	16
+2105	0	1
+268	1	1
+22	3	0
+7889	4	0
+701	4	0
+2411	28	34
+2943	2	3
+8420	1	0
+926	0	324
+6732	1	0
+543	4	3
+4028	2	0
+51	52	40
+3000	1	0
+530	1	0
+2083	0	2
+1173	0	17
+119	16	16
+2727	1	0
+543	0	1
+783	1	0
+1372	0	4
+8624	20	0
+278	44	44
+4364	51	50
+2856	0	1
+5399	0	1
+1506	1	0
+919	0	6
+7229	10	0
+3225	1	0
+435	1	0
+2814	47	47
+1577	0	132
+9785	0	1
+2035	6	0
+7655	1	0
+198207	0	132
+11704	0	5
+7648	1	0
+9062	4	0
+8778	0	2
+7014	1	0
+1613	0	2
+790	7	5
+7433	1	0
+6482	12	12
+6798	0	1
+1422	1	0
+3454	1	1
+43	1	1
+3097	0	2
+334	0	18
+1444	1	0
+2400	3	0
+3272	0	1
+9106	1	0
+1573	0	1
+4742	1	0
+3366	1	0
+5484	0	1
+2444	0	5
+5448	8	8
+2539	0	1
+1471	0	1
+238	1	1
+16	1	1
+288	5	5
+2995	0	2
+951	1	1
+35	1	1
+279	16	15
+3534	6	0
+3513	0	1
+163	0	1
+6173	0	1
+1074	1	0
+2818	1	0
+2868	0	1
+3796	1	0
+1118	1	167
+1278267	25	25
+10747172	0	217
+3504877	0	1053
+10844	13	11
+18805	1	0
+1960834	126729	50000
+3065	1	0
+3601036	90008	8833
+34292	1	0
+1834	0	44
+3083	1	1
+43	1	1
+789	1	0
+11432680	153000	50000
+1902015	0	4098
+99	0	21
+3183	6	6
+877	1	1
+49	1	1
+296	0	1
+1375	1	1
+21	1	1
+607	5	5
+98	0	22
+6811	1	1
+17	0	11
+3804	1	0
+1356	1	1
+29	1	1
+297	1	0
+9543	0	2
+3130	0	4
+861	0	1
+27346	1	0
+7547	8	6
+2834	0	2
+394	4	0
+6524	1	0
+405	11	8
+1128	7	0
+271	1	1
+21	0	28
+507	6	0
+1211	44	31
+384	0	3
+521	18	18
+395	11	0
+799	1	1
+25	3	2
+51	1	49
+49	1	1
+558	0	1
+351	1	0
+2779	13	13
+114398	65008	82124
+7795	0	1
+18	1	1
+4140	1	0
+28048	1	1
+32	1	1
+4630	1	0
+4573	3	0
+357	2	0
+4812	1	0
+14372	0	3
+203	0	1
+26257	1	0
+2734	0	2
+19262	5	5
+5022	0	1
+25471	0	1
+1114538	0	53
+82	126	0
+1416	16	16
+629	57	0
+463	1	0
+148	1	1
+24	1	1
+2322	1	1
+23	1	0
+725	0	16
+24	16	0
+95	9	9
+1277	0	1
+2498	0	1
+354	49	0
+41	0	50
+17	0	49
+37	0	49
+65	8	152
+906	0	47
+234
+
+chain	3352932	chr17	78774742	+	33364384	33585329	17	81195210	-	44852585	44945131	363
+36	7017	7017
+2072	1	1
+16	1	1
+2167	2	0
+2513	1	1
+44	1	1
+1296	17	17
+860	5	0
+1482	0	11
+3433	1	1
+18	1	1
+393	0	3
+198	19	18
+1850	4	5
+267	1	0
+1125	6	7
+1255	1	0
+1502	0	1
+37	0	1
+26	0	1
+302	0	1
+1164	4	2
+1145	8	8
+1170	0	1
+298	1	2
+330	1	0
+2433	13	13
+79	0	2
+5343	1	1
+26	1	1
+994	1	3
+943	0	3
+2485	1	1
+22	1	1
+1574	129212	0
+265	54	54
+5225	26	26
+995	36	36
+240	1	0
+5900	61	61
+112	65	65
+53	14	14
+150	95	95
+160	48	48
+108	70	66
+401	0	6
+354	27	27
+56	65	65
+716	5	3
+1097	4	0
+518	27	27
+944	11	11
+579	37	37
+614	1	0
+2967	12	0
+601	1	10
+1307	35	35
+1719	0	889
+1973	0	3
+709	2	0
+496	5	1
+185	11	11
+98	1	0
+724	3	0
+2103	0	5
+1038	0	1
+257	7	0
+231	1	0
+312	0	2
+423	6	6
+520	10	13
+294	1	0
+17	1	1
+413	4	0
+1698	1	1
+46	1	1
+597	1	1
+21	1	1
+1182	0	2
+50	1	1
+44	0	2
+34	66	3
+3318	3	0
+624	7	0
+507	0	1
+60	1	1
+49	1	1
+332	1	1
+38	1	1
+77	1	1
+19	1	1
+65	1	0
+1174	5	0
+76
+
+chain	1309281	chr17	78774742	+	33410392	33424757	17	81195210	+	36336024	36350387	1779
+203	116	116
+6522	2	0
+5195	584	584
+1743
+
+chain	421642	chr17	78774742	+	33424760	33429230	17	81195210	-	44789041	44793512	103557
+258	1	0
+320	0	1
+3477	0	1
+414
+
+chain	288364	chr17	78774742	+	33534894	33553104	17	81195210	+	60335980	60353933	1564
+39	403	82
+124	31	31
+264	17	18
+283	79	89
+146	36	36
+392	27	27
+75	32	32
+295	106	106
+170	1	0
+69	35	35
+148	57	57
+152	23	23
+96	16	16
+594	57	58
+172	87	87
+108	39	39
+156	68	68
+148	63	63
+54	9	9
+39	289	289
+30	13136	13189
+45
+
+chain	141893	chr17	78774742	+	38701721	38703214	17	81195210	+	41346194	41347687	907641
+1493
+
+chain	138910	chr17	78774742	+	59795041	59797994	3	198022430	+	46191235	46194190	927459
+65	140	139
+77	32	32
+50	53	53
+51	108	111
+72	86	86
+65	76	76
+109	74	74
+120	2	0
+121	111	111
+69	23	23
+101	39	39
+56	40	40
+294	20	20
+65	100	100
+105	124	124
+147	116	116
+64	108	110
+70
+
+chain	73899	chr17	78774742	+	33536708	33552896	17	81195210	+	36333128	36349315	1571
+27	75	75
+32	306	306
+95	240	240
+35	148	148
+57	881	881
+57	172	172
+87	108	108
+39	156	156
+68	148	148
+63	6667	6667
+36	6153	6152
+49	112	112
+64	239	239
+74
+
+chain	29385	chr17	78774742	+	33422514	33422962	17	81195210	+	60352539	60352987	2653
+73	72	72
+133	53	53
+117
+
+chain	28843	chr17	78774742	+	33535172	33536316	17	81195210	+	34740000	34741144	3516
+164	124	124
+31	564	564
+79	146	146
+36
+
+chain	23419	chr17	78774742	+	40573363	40573608	17	81195210	-	37977034	37977279	7093437
+245
+
+chain	22267	chr17	78774742	+	59795106	59797450	15	102531392	+	100960318	100962666	927477
+74	509	513
+86	250	250
+74	1061	1061
+100	108	108
+82
+
+chain	19110	chr17	78774742	+	33422430	33422845	17	81195210	+	34807497	34807912	5737
+84	73	73
+72	133	133
+53
+
+chain	15302	chr17	78774742	+	59872221	59872543	X	155270560	+	133327972	133328295	14745200
+91	145	146
+86
+
+chain	15089	chr17	78774742	+	33553212	33554185	17	81195210	+	34758015	34758988	3454
+70	755	755
+27	56	56
+65
+
+chain	12559	chr17	78774742	+	41846587	41875489	17	81195210	+	44708735	44737620	783
+44	4372	4365
+43	24396	24386
+47
+
+chain	12028	chr17	78774742	+	253252	253513	17	81195210	+	253455	253745	1186280
+87	116	116
+26	30	59
+2
+
+chain	9840	chr17	78774742	+	59850421	59850563	12	133851895	-	30785452	30785594	23191844
+56	27	27
+59
+
+chain	8117	chr17	78774742	+	33410595	33410681	17	81195210	+	34744635	34744721	10477
+86
+
+chain	7470	chr17	78774742	+	59872141	59872220	8	146364022	-	25940938	25941017	21166303
+79
+
+chain	6548	chr17	78774742	+	59823421	59823489	9	141213431	+	108396482	108396550	29214974
+68
+
+chain	6212	chr17	78774742	+	33601781	33601849	17	81195210	+	34807429	34807497	5781
+68
+
+chain	6147	chr17	78774742	+	33578902	33578968	17	81195210	+	34784578	34784649	3380
+29	0	5
+37
+
+chain	5883	chr17	78774742	+	33556525	33558123	17	81195210	+	34761324	34762919	3874
+27	1534	1531
+37
+
+chain	5739	chr17	78774742	+	59862459	59862519	13	115169878	+	43436593	43436653	31343618
+60
+
+chain	5729	chr17	78774742	+	59852430	59852489	7	159138663	-	42785228	42785287	31366016
+59
+
+chain	5493	chr17	78774742	+	254397	254454	17	81195210	+	254136	254193	32044913
+57
+
+chain	5493	chr17	78774742	+	254339	254396	17	81195210	+	254136	254193	32044914
+57
+
+chain	4633	chr17	78774742	+	59795405	59797489	7	159138663	+	22571262	22573349	985966
+53	1992	1995
+39
+
+chain	3684	chr17	78774742	+	59871978	59872017	5	180915260	+	67132991	67133030	32368210
+39
+
+chain	3604	chr17	78774742	+	59872312	59872350	6	171115067	+	73766967	73767005	18649321
+38
+
+chain	3578	chr17	78774742	+	59797823	59797921	9	141213431	-	46000791	46000889	1219359
+98
+
+chain	3496	chr17	78774742	+	59872079	59872141	X	155270560	-	52661918	52661980	17303862
+62
+
+chain	3063	chr17	78774742	+	59796390	59796453	18	78077248	+	3738092	3738155	1007405
+63
+
+chain	2832	chr17	78774742	+	78651772	78651801	17	81195210	+	81058451	81058480	35013371
+29
+
+chain	2507	chr17	78774742	+	254312	254338	17	81195210	+	254167	254193	28153285
+26
+
+chain	2327	chr17	78774742	+	253481	253511	17	81195210	+	253858	253888	2965414
+30
+
+chain	2229	chr17	78774742	+	59795509	59795562	9	141213431	+	99971007	99971060	1163412
+53
+
+chain	2158	chr17	78774742	+	59871912	59871978	10	135534747	-	7120285	7120351	17475521
+66
+
+chain	2116	chr17	78774742	+	41755737	41755765	17	81195210	-	18330211	18330239	723
+28
+
+chain	2038	chr17	78774742	+	59872018	59872072	12	133851895	-	60047857	60047911	21673207
+54
+
+chain	1971	chr17	78774742	+	33410681	33410711	17	81195210	+	58084086	58084116	2335
+30
+
+chain	1910	chr17	78774742	+	59797697	59797752	7	159138663	-	95523915	95523970	1276958
+55
+
+chain	1797	chr17	78774742	+	59795569	59795617	8	146364022	-	39560190	39560238	1234503
+48
+
+chain	1764	chr17	78774742	+	59795840	59795881	17	81195210	-	78142303	78142344	1077161
+41
+
+chain	1713	chr17	78774742	+	59797636	59797671	10	135534747	-	112842234	112842269	1000659
+35
+
+chain	1680	chr17	78774742	+	59795180	59795214	3	198022430	+	108471362	108471396	1315432
+34
+
+chain	1591	chr17	78774742	+	59795881	59795916	X	155270560	-	139019545	139019580	1025236
+35
+
+chain	1456	chr17	78774742	+	59796656	59796685	6	171115067	+	121488440	121488469	989186
+29
+
+chain	1332	chr17	78774742	+	33532356	33535172	17	81195210	+	34572150	34574966	5130
+25	2722	2722
+69
+
+chain	1250	chr17	78774742	+	59795215	59795246	11	135006516	-	104930893	104930924	1222490
+31
+
+chain	1089	chr17	78774742	+	59795324	59795355	X	155270560	-	141145732	141145763	1311664
+31
+
+chain	1006	chr17	78774742	+	59797671	59797695	X	155270560	+	72606434	72606458	1154867
+24
+
+chain	622	chr17	78774742	+	33334125	33344374	17	81195210	-	46414201	46424210	397
+69	10130	9890
+50
+
+chain	20335446	chr17_random	2617613	+	224588	1377183	17	81195210	-	41910550	46712950	133
+1433	3	0
+976	0	1
+281	0	1
+1231	0	14
+2584	0	15
+2816	1	0
+3815	1	0
+122	1	1
+25	1	1
+335	0	1
+4687	29	0
+68	0	1
+1769	32	0
+616	3	0
+1017	1	1
+35	1	1
+864	17	17
+321	4	4
+47	1	1
+6467	8	10
+746	1	0
+188	30	0
+179	14	14
+120	1	1
+19	1	1
+477	1	1
+25	1	1
+300	5	5
+33	4	4
+968	6	6
+1546	1	1
+39	1	1
+66	1	1
+92	1	1
+349	12	12
+839	3	3
+36	1	1
+654	1	1
+88	1	1
+647	3	0
+993	10	8
+296	0	12
+183	4	4
+385	1	1
+25	1	1
+405	1	1
+29	1	1
+108	1	1
+36	1	1
+57	1	1
+88	2	1
+78	4	4
+39	1	1
+133	1	1
+133	1	1
+162	1	8
+398	14	14
+52	16	16
+122	1	1
+56	1	1
+98	1	1
+25	1	1
+332	1	1
+48	1	1
+83	0	1
+25	1	1
+71	1	1
+71	1	1
+79	4	0
+87	1	1
+207	1	1
+70	1	1
+263	16	16
+143	1	1
+72	1	1
+198	0	1
+1062	104	0
+6	61	0
+278	8	8
+454	49	49
+297	0	1
+1271	1	1
+48	1	1
+85	1	1
+66	1	1
+89	1	0
+327	1	1
+61	1	1
+51	1	1
+25	2	2
+72	1	1
+80	1	1
+132	1	1
+136	4	4
+63	1	1
+47	1	1
+134	1	1
+28	1	1
+1004	1	1
+45	1	1
+2017	1	1
+22	1	1
+778	8	0
+3805	0	4
+3884	1	0
+1082	1	1
+39	1	1
+926	1	0
+12182	105	0
+19079	4	0
+108	0	6
+81968	13	12
+5894	126	0
+5069	696334	2698100
+65	1	1
+31	0	1
+165	15	0
+2504	0	2
+1155	0	10
+463	1	0
+2422	0	1
+90	10	0
+75	0	1
+397	0	1
+64	31	32
+1531	4	0
+2064	0	1
+1305	1	0
+1045	0	1
+1972	0	1
+3554	0	2
+428	1	0
+1541	10	12
+1808	1	0
+1758	0	1
+500	1	0
+737	1	0
+218	0	1
+2132	0	1
+744	0	1
+7456	2	0
+45	0	2
+2311	23	23
+727	0	2
+916	1	0
+360	5	5
+2956	0	1
+3263	3	0
+1460	1	1
+34	1	1
+117	1	0
+1852	10	0
+50	7	7
+3949	42	42
+528	40	40
+736	100	17954
+680	119199	29667
+516	22	22
+2397	100	1694896
+1291	0	4
+232	1	1
+32	1	1
+1529	0	4
+20	2	0
+42	0	2
+94	0	10
+402	1	1
+16	1	1
+1099	1	1
+49	1	1
+2223	32	32
+1530	36	36
+1563	57608	84063
+160	94	94
+164	108	108
+123	61	61
+136	449	449
+3509	28	28
+1092	1	0
+611	1	1
+28	1	1
+2932	1	1
+52	49	45
+64	1	1
+27	1	1
+1320	1074	0
+6819	0	1
+4716
+
+chain	16836081	chr17_random	2617613	+	2022361	2536424	17	81195210	+	77630507	81150656	169
+143	0	4
+116	4	4
+74	12	10
+298	1	0
+533	1	0
+340	27	27
+130	16	16
+184	15	14
+699	1	0
+68	1	0
+153	1	0
+1835	1	0
+5	2	0
+95	1	0
+105	6	4
+14	1	0
+10	1	0
+88	1	0
+63	1	0
+27	1	0
+37	1	0
+18	1	0
+75	1	0
+49	2	0
+366	1	0
+206	1	0
+114	1	0
+237	1	0
+265	16	12
+223	1	0
+182	1	0
+26	1	0
+34	1	0
+138	1	0
+170	1	0
+26	1	0
+16	1	0
+53	4	2
+85	1	0
+188	1	0
+107	1	0
+31	1	0
+180	1	0
+4	2	1
+4	1	0
+16	1	0
+21	1	0
+324	1	0
+106	2	0
+46	1	0
+74	1	0
+12	1	0
+557	2	0
+194	5	2
+23	1	0
+67	6	3
+7	1	0
+50	1	0
+143	1	0
+190	1	0
+24	1	0
+310	1	0
+204	1	0
+108	1	0
+15	1	0
+212	1	0
+3	1	0
+57	4	2
+44	1	0
+298	1	0
+38	1	0
+54	1	0
+112	1	0
+20	2	0
+79	1	0
+10	6	3
+12	1	0
+59	1	0
+51	1	0
+234	2	0
+43	1	0
+194	1	0
+5	1	0
+96	9	4
+67	2	0
+270	1	0
+13	1	0
+59	1	0
+54	1	0
+57	1	0
+375	1	0
+50	1	0
+87	1	0
+83	4	2
+234	4	2
+44	1	0
+24	7	4
+25	1	0
+44	1	0
+139	1	0
+201	12	9
+215	1	0
+5	1	0
+30	1	0
+43	1	1
+54	16	13
+210	1	0
+109	2	0
+55	1	0
+14	1	0
+126	1	0
+79	1	0
+326	1	0
+18	1	0
+150	1	0
+13	1	0
+85	1	0
+47	1	0
+16	1	0
+41	1	0
+43	5	3
+56	1	0
+62	1	0
+164	1	0
+108	1	0
+20	2	0
+137	1	0
+214	1	0
+14	1	0
+5	2	0
+60	5	3
+24	1	0
+72	2	0
+25	1	0
+23	1	0
+60	1	0
+53	1	0
+15	1	0
+145	1	0
+337	1	0
+112	1	0
+39	1	0
+234	1	0
+7	2	0
+108	1	0
+19	1	0
+150	1	0
+22	5	3
+221	1	0
+30	1	0
+195	1	0
+126	1	0
+116	1	0
+189	1	0
+231	1	0
+87	2	0
+136	2	0
+69	1	0
+350	1	1
+29	1	0
+76	1	0
+42	1	0
+10	3	1
+63	1	0
+168	1	0
+97	1	0
+11	1	0
+291	1	0
+150	1	0
+10	1	0
+141	15	12
+9	1	0
+35	1	1
+57	1	0
+9	2	0
+211	1	0
+193	1	0
+51	1	0
+337	1	0
+94	1	0
+9	1	0
+58	1	0
+152	1	0
+58	1	0
+127	1	0
+6	1	0
+65	1	0
+379	1	0
+93	1	0
+11	1	0
+106	1	0
+545	1	0
+11	1	0
+66	2	0
+28	1	0
+242	4	2
+32	8	5
+373	10	9
+242	1	0
+207	1	0
+51	1	0
+132	1	0
+118	1	0
+19	2	0
+116	1	0
+16	1	0
+23	1	0
+54	1	0
+67	1	0
+62	1	0
+52	10	7
+15	2	0
+33	1	0
+248	1	1
+27	1	0
+122	1	0
+25	1	0
+55	1	0
+141	1	0
+57	1	0
+45	1	0
+21	1	0
+66	4	2
+23	1	1
+234	1	1
+25	2	2
+56	1	0
+34	1	0
+12	1	0
+11	1	0
+5	1	0
+54	1	0
+16	1	0
+64	1	0
+361	1	1
+24	1	0
+111	1	0
+12	1	0
+74	1	0
+56	1	0
+43	1	0
+21	1	0
+8	1	0
+13	2	0
+34	1	0
+59	1	0
+79	1	0
+159	1	0
+69	2	0
+15	2	0
+8	1	0
+142	19	17
+302	1	0
+49	1	0
+114	1	0
+72	1	0
+38	1	0
+16	1	0
+39	1	0
+106	1	0
+16	3	1
+31	1	0
+5	1	0
+43	1	0
+120	1	0
+16	1	0
+82	1	0
+47	4	1
+10	6	3
+59	1	0
+10	1	0
+258	1	0
+97	14	13
+72	1	0
+126	1	0
+14	1	0
+92	1	0
+406	1	0
+194	1	0
+43	1	0
+30	1	0
+50	1	0
+8	1	0
+161	6	4
+39	1	0
+12	1	1
+60	1	0
+61	1	0
+23	1	0
+13	1	0
+41	2	0
+260	1	0
+144	1	0
+38	1	0
+45	1	0
+17	1	0
+73	1	0
+64	20	13
+25	1	0
+84	1	0
+42	11	6
+180	1	0
+32	2	0
+172	0	1
+65	1	0
+53	1	0
+39	3	1
+203	1	0
+16	3	1
+42	3	2
+27	6	4
+13	1	0
+99	1	0
+34	4	2
+511	1	0
+182	1	0
+230	8	3
+42	1	0
+16	1	1
+270	5	4
+13	1	0
+141	1	0
+100	1	0
+144	1	0
+146	1	0
+356	1	0
+99	1	0
+69	2	0
+146	1	0
+55	18	14
+54	7	4
+18	1	0
+170	2	0
+45	1	0
+13	1	0
+628	1	0
+93	1	0
+46	1	0
+131	1	0
+20	1	0
+98	1	0
+20	1	1
+355	0	2
+88	1	0
+121	1	0
+31	1	0
+27	1	0
+132	1	0
+64	1	0
+43	1	0
+30	1	0
+95	1	0
+22	1	0
+44	6	3
+20	1	0
+138	1	0
+198	1	0
+100	1	0
+163	1	0
+6	1	0
+155	1	0
+79	1	0
+34	1	0
+193	1	0
+159	1	0
+50	5	3
+30	1	0
+9	1	0
+115	1	0
+93	1	0
+54	1	0
+91	1	0
+336	1	0
+134	18	13
+126	1	0
+61	1	0
+133	1	0
+613	4	2
+244	1	0
+586	1	0
+5	1	0
+93	19	16
+148	6	3
+12	2	1
+20	1	1
+138	102	11399
+572	8	6
+529	1	0
+659	1	1
+35	1	0
+191	2	0
+56	1	0
+105	1	0
+18	1	0
+226	1	0
+59	15	16
+275	1	0
+87	1	0
+5	1	0
+85	1	0
+21	1	0
+71	1	0
+507	1	0
+21	3	1
+82	1	0
+32	1	0
+39	1	1
+312	1	0
+263	1	0
+196	5	3
+23	5	3
+275	1	0
+46	2	0
+154	0	6
+229	1	0
+27	1	0
+87	1	0
+5	2	0
+502	1	0
+97	105	101
+162	1	0
+114	1	0
+65	1	1
+43	1	0
+217	1	0
+14	1	0
+172	1	0
+326	1	0
+9	1	0
+446	1	0
+73	1	0
+245	2	0
+114	1	0
+237	1	0
+35	22	13
+318	1	0
+320	1	0
+76	1	1
+54	1	0
+44	1	1
+100	1	0
+30	0	1
+462	1	0
+22	1	1
+72	1	1
+121	1	0
+37	1	0
+22	5	0
+23	1	1
+154	1	0
+63	1	1
+87	1	0
+278	1	0
+36	1	1
+230	1	0
+182	3	1
+51	1	0
+7	1	0
+101	1	0
+39	1	0
+17	1	0
+55	1	0
+13	1	0
+114	1	0
+13	1	0
+24	1	1
+69	10	9
+171	1	0
+60	1	1
+77	1	1
+8	2	1
+25	1	0
+51	1	0
+327	1	0
+105	2	0
+133	0	1
+28	1	0
+67	1	0
+119	4	2
+334	1	0
+37	2	1
+47	1	0
+165	1	0
+29	1	0
+35	1	0
+46	1	0
+9	1	0
+657	1	0
+62	1	0
+171	1	0
+17	1	0
+113	1	0
+15	1	1
+123	1	1
+62	1	0
+4	1	1
+288	21	0
+809	0	1
+22	1	0
+61	1	0
+52	1	0
+25	2	0
+263	3	1
+35	1	0
+192	238701	2061422
+87	1	0
+6	1	0
+1080	1	0
+76	1	0
+1007	1	0
+98	1	0
+35	1	0
+134	1	0
+285	1	0
+33	0	1
+225	1	0
+281	1	0
+108	1	0
+55	1	0
+107	1	0
+202	15	12
+111	1	0
+36	2	0
+25	1	0
+202	1	0
+97	1	0
+143	1	1
+21	1	0
+222	1	0
+41	1	0
+492	0	4
+594	1	0
+181	1	0
+410	1	0
+37	1	0
+13	1	0
+34	1	0
+76	38	37
+204	27	27
+204	40	32
+432	1	0
+143	1	0
+271	1	0
+224	96	91
+385	1	0
+337	1	0
+375	1	0
+139	22	17
+297	1	0
+72	1	0
+5	2	0
+193	1	0
+8	1	0
+28	1	0
+17	1	0
+17	1	0
+445	1	0
+169	1	36
+35	3	1
+425	1	0
+41	1	0
+37	1	0
+79	1	0
+100	1	0
+130	1	0
+419	1	0
+17	1	1
+284	3	1
+56	1	0
+9	2	1
+655	1	0
+158	2	0
+8	1	0
+34	1	1
+519	1	0
+39	1	0
+78	1	0
+216	1	0
+3	1	0
+68	1	0
+56	1	0
+70	1	0
+290	0	4
+46	0	2
+108	0	2
+23	0	114
+830	1	0
+136	76	98
+63	65	64
+380	1	0
+106	1	1
+358	1	0
+64	1	1
+17	1	0
+171	5	3
+27	1	1
+130	13	10
+131	1	0
+415	1	0
+5	1	0
+37	1	0
+29	1	0
+27	1	0
+750	1	0
+249	1	0
+221	1	0
+109	1	0
+50	1	0
+323	1	0
+296	1	0
+383	1	0
+67	1	0
+239	2	0
+248	1	0
+9	1	0
+180	1	0
+241	1	0
+40	3	1
+6	1	0
+19	1	0
+27	1	0
+166	1	0
+80	1	0
+163	1	0
+33	1	0
+9	1	0
+172	1	0
+261	1	0
+200	1	0
+14	6	2
+121	1	0
+37	4	2
+74	1	0
+97	5	3
+10	2	1
+51	1	0
+642	1	0
+317	14	11
+163	3	1
+25	2	0
+875	1	0
+128	1	0
+211	8	4
+409	1	0
+233	1	0
+263	1	0
+12	1	0
+73	1	0
+188	1	0
+96	1	0
+183	1	0
+126	1	0
+235	1	1
+68	0	1
+618	1	0
+13	1	0
+73	1	0
+1315	883	57
+78	2	2
+774	1	0
+21	1	0
+13	1	0
+9	2	0
+168	1	0
+214	1	0
+84	3	1
+645	1	0
+150	1	0
+72	1	0
+8	1	0
+108	1	0
+120	1	0
+1469	1	0
+38	1	0
+697	1	0
+44	1	0
+345	1	0
+126	1	0
+46	1	0
+110	1	0
+972	1	0
+104	23	22
+93	2	2
+38	1	0
+34	3	1
+730	1	0
+151	1	0
+124	1	0
+210	1	0
+60	1	0
+227	1	0
+122	1	0
+225	2	0
+26	1	0
+85	1	0
+84	6	3
+408	1	0
+5	3	1
+18	1	0
+69	1	0
+76	1	0
+122	1	0
+288	1	0
+10	1	0
+55	1	0
+22	2	0
+455	1	0
+246	1	0
+37	1	0
+153	1	0
+27	1	0
+101	1	0
+158	1	0
+107	1	0
+437	1	0
+31	1	0
+149	1	0
+121	1	0
+5	1	0
+175	1	0
+76	1	0
+75	1	0
+26	2	0
+98	1	0
+169	1	0
+82	1	0
+20	1	0
+326	1	0
+274	1	0
+78	1	0
+42	1	0
+64	1	0
+11	7	4
+39	1	0
+91	1	0
+140	1	0
+397	14	12
+500	7	4
+879	5	2
+448	1	0
+42	1	0
+522	1	0
+247	1	0
+484	1	0
+689	1	0
+66	1	0
+198	1	0
+441	1	0
+143	1	0
+35	1	0
+84	1	0
+9	1	0
+445	1	0
+110	1	0
+204	1	0
+31	1	0
+77	1	0
+54	1	0
+213	1	0
+601	1	0
+25	1	0
+239	2	2
+42	1	0
+29	2	0
+15	1	0
+175	1	0
+611	1	0
+418	1	0
+191	1	0
+295	1	0
+30	8	5
+609	1	0
+372	1	0
+154	2	0
+117	1	0
+282	1	0
+360	1	0
+750	1	0
+402	1	0
+45	1	0
+678	1	0
+17	1	0
+117	1	0
+148	1	0
+164	3	1
+51	1	0
+65	1	0
+452	1	0
+1443	1	0
+142	1	0
+509	1	0
+92	10	6
+264	1	0
+69	1	0
+78	1	0
+43	1	0
+164	1	0
+349	1	0
+117	1	0
+373	1	0
+235	1	0
+160	1	0
+8	1	0
+263	1	0
+15	1	0
+23	1	0
+151	1	0
+100	1	0
+204	1	0
+250	1	0
+33	3	1
+272	1	0
+262	1	0
+55	1	0
+519	1	0
+251	1	0
+189	1	0
+459	1	0
+183	1	0
+295	1	0
+552	1	0
+94	16	12
+259	1	0
+30	1	0
+396	1	0
+17	1	0
+72	1	0
+56	1	0
+90	1	0
+106	1	0
+19	2	0
+271	1	0
+448	1	0
+628	497	497
+254	26	26
+391	1	0
+32	1	0
+171	1	0
+126	20	17
+94	1	0
+446	1	0
+30	1	0
+96	1	0
+17	1	0
+159	1	0
+390	1	0
+105	1	0
+94	1	0
+5	2	0
+21	1	0
+22	1	0
+380	1	0
+12	1	0
+211	1	0
+377	1	0
+3	1	0
+63	1	0
+37	2	2
+1596	1	0
+638	1	0
+30	1	0
+665	13	10
+32	1	0
+102	1	0
+361	1	0
+609	1	0
+590	1	0
+1189	29	29
+345	1	0
+732	1	0
+544	1	0
+272	1	0
+725	1	0
+198	1	0
+8	1	0
+275	1	0
+95	1	0
+101	1	0
+626	1	0
+154	1	0
+242	1	0
+937	1	0
+142	1	0
+236	1	0
+456	12	9
+77	1	0
+189	1	0
+172	1	0
+201	1	0
+417	1	0
+179	1	0
+141	1	0
+219	1	0
+164	1	0
+138	1	0
+500	2	0
+263	1	0
+48	1	0
+17	1	0
+91	1	0
+169	1	0
+8	1	0
+185	1	0
+48	1	0
+345	1	0
+546	2	2
+229	2	2
+614	1	0
+73	2	2
+129	1	0
+91	1	0
+287	3	1
+504	2	0
+264	22	22
+508	1	0
+1324	1	0
+1313	1	0
+36	1	0
+346	1	0
+285	5	2
+31	1	0
+6	1	0
+133	1	0
+27	1	0
+101	1	0
+249	1	0
+68	5	3
+34	1	0
+31	1	0
+140	1	0
+350	1	0
+312	1	0
+139	1	0
+66	1	0
+24	1	0
+37	1	0
+16	1	0
+32	1	0
+204	1	0
+21	1	0
+11	1	0
+120	2	0
+161	1	0
+13	1	0
+143	1	0
+46	1	0
+136	3	1
+75	1	0
+176	1	0
+23	1	0
+30	1	0
+34	1	0
+307	1	0
+27	1	0
+261	1	0
+39	1	0
+995	1	0
+556	1	0
+211	1	0
+278	1	0
+850	1	0
+285	1	0
+207	1	0
+154	1	0
+51	1	0
+237	1	0
+204	1	0
+11	1	0
+348	2	0
+41	1	0
+75	2	0
+47	1	0
+49	1	0
+253	1	0
+171	10	6
+106	1	0
+83	1	0
+86	1	0
+30	1	0
+166	1	0
+297	1	0
+480	1	0
+285	1	0
+339	1	0
+30	1	0
+74	1	0
+15	1	0
+310	1	0
+88	1	0
+111	1	0
+104	1	0
+644	1	0
+29	1	0
+413	2	0
+33	3	1
+19	1	0
+321	1	0
+318	1	0
+131	1	0
+111	1	0
+89	1	0
+751	120	120
+314	1	0
+613	2	0
+991	3	1
+44	1	0
+42	1	0
+57	1	0
+102	1	0
+318	1	0
+47	2	0
+186	1	0
+550	1	0
+504	1	0
+76	1	0
+336	1	0
+505	1	0
+34	2	0
+61	1	0
+257	1	0
+439	1	0
+94	1	0
+18	1	0
+6	1	0
+86	1	0
+18	1	0
+179	1	0
+52	1	0
+635	1	0
+535	1	0
+90	1	0
+531	2	0
+59	1	0
+132	1	0
+122	1	0
+17	1	0
+96	1	0
+281	1	0
+145	1	0
+342	1	0
+132	1	0
+95	16	12
+417	1	0
+143	1	0
+135	1	0
+11	1	0
+486	1	0
+224	1	0
+277	1	0
+449	1	0
+321	34	30
+96	1	0
+20	1	0
+358	1	0
+146	1	0
+176	1	0
+37	1	0
+92	1	0
+115	1	0
+245	1	0
+72	1	0
+65	1	0
+108	1	0
+41	13	10
+121	65	54
+54	1	0
+359	1	0
+53	1	0
+55	1	0
+10	1	0
+5	1	0
+6	2	1
+43	1	0
+9	1	0
+223	1	0
+90	1	0
+157	1	0
+686	1	0
+250	1	0
+160	1	0
+264	50363	1224780
+4948	0	1
+1850	60	67
+3859	0	1
+456	4	5
+1605	21	21
+1281	7	13
+5090	456	0
+1543	1	1
+37	1	1
+2825	1	1
+64	1	1
+1075	0	1
+721	0	1
+5566	22	5
+1136	1	0
+2390	0	3
+1347	0	2
+4617
+
+chain	16543266	chr17_random	2617613	+	0	174588	GL000205.1	174588	+	0	174588	172
+174588
+
+chain	10747371	chr17_random	2617613	+	1609852	1757206	17	81195210	-	15050606	15196423	297
+3573	1	0
+1031	1	0
+4890	10	7
+318	0	1
+667	1	0
+168	0	2
+974	2	0
+143	2	0
+208	4	0
+2621	10	10
+634	2	0
+1898	0	2
+99	21	21
+6731	1	1
+49	1	1
+345	2	0
+210	1	1
+1621	1	0
+1077	0	2
+371	6	0
+4548	5769	26131
+1148	0	1
+1283	1	1
+24	1	0
+2931	0	6
+38	22	0
+682	0	1
+1267	0	2
+470	9	19
+2335	0	9
+720	8	0
+2859	26315	4346
+4414	0	1
+777	1	4
+894	4	0
+3207	0	3
+3071	0	1
+1338	1	0
+869	1	0
+2072	0	1
+395	1	0
+1060	8	8
+1138	1	1
+6	2	0
+40	1	1
+473	0	1
+748	2	0
+306	8	0
+81	6	0
+748	4	0
+158	0	22
+6454	0	2
+145	1	1
+49	1	1
+619	0	1
+1579	14	14
+455	1	0
+5224	1	1
+31	1	0
+31	0	57
+3855	0	2
+2164	11	21
+1491	0	4
+213	16	4
+4589	6	6
+1564	0	6
+325	0	1
+2241	0	1
+149	0	1
+4150	0	4
+4768	0	12
+411	0	6
+804	2	0
+124	19	19
+937	2	0
+997	27	29
+685	37	37
+5	2	0
+35	37	48
+29	1	1
+237	2	0
+333	0	1
+1296	31	23
+472	4	0
+34	1	1
+683
+
+chain	7797784	chr17_random	2617613	+	2131554	2212864	GL000204.1	81310	+	0	81310	420
+81310
+
+chain	5191141	chr17_random	2617613	+	986480	1282720	17	81195210	+	34482891	34744119	309
+118	29	29
+73	435	3450
+113	9	9
+74	44	43
+109	53	55
+147	361	38
+603	128	128
+69	8	8
+278	22	22
+1262	20	20
+83	37	44
+478	1	1
+32	1	1
+54	1	1
+81	1	1
+57	0	1
+71	4	4
+83	1	1
+103	1	1
+80	1	1
+15	1	1
+312	15	15
+185	1	1
+24	1	1
+720	1	1
+19	1	1
+185	1	1
+35	1	1
+144	7	7
+238	1	1
+62	3	3
+196	10	10
+123	1	1
+99	1	1
+1997	1	1
+27	1	1
+64	49	45
+19	1	1
+547	1	1
+16	1	1
+796	0	2
+213	0	1
+1353	0	5
+59	1	1
+604	1	0
+1099	28	28
+2219	0	1
+1732	6	6
+115	1	1
+80	1	1
+123	1	1
+106	1	1
+164	1	1
+92	1	1
+160	34984	45270
+79	5	5
+348	149	150
+73	23	23
+322	46	46
+284	35	28
+1307	16	16
+515	89	89
+62	9	9
+203	3	0
+65	10	9
+188	33	32
+342	1	0
+100	0	1
+67	48	52
+69	1	0
+2330	39	42
+356	2	0
+767	5	9
+69	4	0
+373	29	30
+138	1	0
+571	0	1
+273	13	13
+140	25	24
+457	39	39
+204	19	19
+137	49	49
+178	59	59
+220	38	38
+66	23	22
+315	1	0
+399	30	30
+345	62	62
+200	36	36
+1097	33	35
+255	5	0
+61	4	0
+371	48	33
+119	30	30
+52	0	2
+236	0	2
+81	13	13
+168	12	12
+174	0	1
+250	81	81
+185	35	35
+343	27	35
+271	232	235
+79	116	119
+288	61	61
+869	9	8
+282	7	0
+6366	1	0
+2033	112	1128
+417	0	1
+64	145492	5631
+587	0	2
+184	392	14227
+792	0	4
+408	2	1
+1608	0	1
+1287	0	2
+676	1	1
+31	1	1
+112	1	1
+91	1	1
+173	1	0
+42	1	14
+784	11	11
+3219	0	13521
+8127	24	23
+7132	0	12
+9450	0	4
+3351	28	28
+5832	3	0
+100	0	1
+67	0	5
+31	6	5
+10	1	1
+69	2	0
+2314	1	0
+11507	0	1
+742	0	63471
+5695	0	1
+731	1	0
+3536
+
+chain	4342758	chr17_random	2617613	+	615163	663282	17	81195210	-	81146986	81195210	699
+117	89	88
+430	1	1
+8	7	3
+19	1	1
+521	14	7
+577	1	0
+4	1	0
+284	1	1
+19	12	6
+55	3	0
+193	1	0
+383	16	13
+508	5	0
+404	6	1
+1326	31	25
+723	84	3
+41	75	0
+21	1	0
+303	27	0
+65	81	27
+94	1	1
+40	1	1
+118	746	87
+30	2	1
+37	1	1
+179	2	0
+43	1	1
+46	27	0
+35	32	0
+278	1	0
+353	8	10
+363	13	1
+106	4	0
+188	34	34
+206	1	0
+3	1	0
+1339	1	0
+632	1	1
+21	0	4
+248	1	0
+655	1	0
+258	1	0
+777	1	0
+1440	16	16
+124	1	1
+36	1	0
+33	1	1
+89	1	0
+165	1	0
+86	1	1
+47	1	1
+319	8	4
+506	4	2
+537	16	12
+2310	1	0
+7	2	0
+922	9	0
+294	1	0
+145	1	0
+1890	2	0
+15	1	0
+38	1	0
+2030	12	6
+1208	2	0
+107	1	0
+438	2	0
+492	2	0
+184	1	0
+42	1	1
+646	1	35
+28	4	4
+62	4	36
+43	0	32
+54	1	1
+8	2	0
+23	1	1
+77	0	32
+34	0	32
+52	1	167
+69	70	6
+61	0	36
+99	0	64
+605	22	22
+133	1	0
+296	1	1
+42	1	0
+361	10	6
+225	14	14
+387	1	97
+405	0	480
+101	1	0
+24	2	2
+339	0	336
+1176	1	0
+192	1	0
+553	1	0
+114	4	1
+544	18	12
+575	3	0
+85	1	0
+934	1	0
+667	13	7
+28	18	12
+770	10	6
+149	1	0
+884	22	20
+214	0	1
+607	1	0
+129	1	0
+14	6	4
+27	6	3
+10	1	0
+4	2	0
+155	39	28
+214	2	0
+43	1	1
+1236	44	27
+1759	2	0
+472	6	2
+342	8	5
+970	6	0
+227	1	0
+691	1	0
+359	2	0
+141	1	0
+5	1	0
+2008	1	0
+302
+
+chain	3923033	chr17_random	2617613	+	864624	922266	17	81195210	+	81075742	81117538	762
+924	1	0
+428	1	0
+763	1	0
+19745	32	32
+637	15873	36
+186	1	0
+2389	1	0
+616	1	0
+1932	12	12
+10081	18	18
+2216	1	0
+92	1	0
+271	4	4
+67	5	5
+698	83	82
+473	27	27
+62
+
+chain	3905383	chr17_random	2617613	+	460666	565054	17	81195210	+	41343520	41406910	763
+9362	3	1
+1313	0	1
+344	1	0
+2289	0	2
+14919	0	1
+1393	6	4
+1047	1	0
+21	0	1
+31	5511	0
+28	783	8
+978	3	4
+213	0	2
+2198	0	702
+75	4479	3549
+723	0	13
+165	1	1
+19	3	3
+113	0	4
+88	1	1
+41	1	0
+38	7	7
+98	17	17
+152	50743	16221
+115	169	185
+169	0	4
+278	1	1
+48	1	1
+6399
+
+chain	3524656	chr17_random	2617613	+	1876393	1913891	GL000203.1	37498	+	0	37498	830
+37498
+
+chain	3296870	chr17_random	2617613	+	1963891	2002673	GL000204.1	81310	+	42877	81310	872
+560	1	0
+101	2	0
+296	42	39
+438	2	0
+256	1	0
+136	1	0
+109	1	0
+101	2	0
+234	64	62
+405	37	35
+61	1	0
+366	5	3
+501	39	37
+142	1	0
+191	27	24
+59	6	4
+53	67	62
+91	1	0
+159	1	0
+74	40	38
+164	1	0
+57	28	26
+75	1	0
+46	1	0
+61	45	43
+117	1	0
+360	45	43
+204	1	0
+180	61	58
+589	1	0
+212	1	0
+88	1	0
+53	1	0
+492	1	0
+75	26	24
+273	1	0
+701	1	0
+444	1	0
+75	1	0
+393	11	9
+105	59	56
+72	42	40
+79	1	0
+79	1	0
+95	153	144
+127	1	0
+85	4	2
+175	3	0
+222	1	0
+121	1	0
+48	1	0
+50	1	0
+61	1	0
+213	1	0
+73	1	0
+180	2	0
+83	1	0
+58	1	0
+192	11	5
+57	140	125
+101	1	0
+91	38	34
+190	1	0
+73	1	0
+116	6	4
+275	16	14
+200	1	0
+201	3	1
+632	1	0
+60	1	0
+198	9	1
+254	2	0
+89	1	0
+60	38	36
+326	32	28
+306	1	0
+55	1	0
+100	18	16
+127	36	32
+67	1	0
+78	1	0
+90	1	0
+63	35	31
+120	150	141
+103	9	7
+406	88	85
+54	15	13
+142	9	7
+112	32	30
+237	1	0
+114	27	18
+157	40	38
+145	1	0
+380	20	18
+73	109	104
+57	1	0
+83	68	65
+567	1	0
+378	0	4
+282	29	27
+725	1	0
+204	1	0
+246	1	0
+295	17	15
+243	1	0
+187	46	44
+56	1	0
+244	1	0
+303	1	0
+121	16	15
+253	1	0
+273	44	44
+427	10	0
+403	2	0
+219	1	0
+151	1	0
+115	14	13
+193	1	0
+63	1	0
+63	38	36
+609	1	0
+81	42	40
+297	1	0
+455	17	14
+278	3	1
+691	1	0
+417	104	101
+57	1	0
+93	5	3
+309	48	47
+303	1	0
+324	1	0
+126	41	37
+138	2	0
+233	1	0
+100	50	47
+86	9	7
+256	1	0
+208	1	0
+486	3	1
+118	1	0
+70	69	64
+455	8	6
+149	1	0
+175	5	2
+115	1	0
+159	1	0
+109	12	9
+135	33	31
+53	1	0
+256	5	3
+82	41	38
+268	70	67
+600	1	0
+128	18	16
+114	1	0
+149	62	58
+99	57	54
+158	42	38
+88	1	0
+75	46	43
+300	50	47
+71	13	11
+118	1	0
+177	1	0
+120	1	0
+275	1	0
+74	13	11
+230	1	0
+117	6	4
+113	39	37
+71	1	0
+597	9	8
+82	10	6
+195	10	8
+361	1	0
+53	1	0
+291	0	1
+149	1	0
+164
+
+chain	2935078	chr17_random	2617613	+	1427191	1457644	17	81195210	+	81045288	81075743	955
+1667	2	0
+1156	0	2
+25	0	2
+27603
+
+chain	2199778	chr17_random	2617613	+	671651	748529	11	135006516	-	134809692	134880676	533
+53	3	0
+176	68	0
+22	38	1
+38	43	16
+122	41	249
+34	4	16
+5	1	0
+6	1	0
+68	0	37
+1042	1	1
+35	1	1
+27	326	0
+359	1	0
+3	2	0
+176	16	5
+44	5	1
+224	1	0
+432	1	1
+35	1	1
+266	21	16
+109	14	10
+806	0	34
+465	56	0
+57	4	0
+787	1	0
+283	1	1
+27	1	1
+1090	1	1
+81	1	0
+1354	1	0
+40	1	1
+305	1	0
+89	1	1
+63	1	1
+48	1	1
+167	11	11
+83	8	4
+45	5	3
+343	1	1
+47	49	0
+56	0	294
+17	49	0
+79	5	103
+162	49	0
+442	10	10
+438	3	0
+50	1	1
+676	1	1
+39	1	1
+66	1	1
+7	1	0
+35	1	1
+547	7	2
+549	2393	0
+3	2913	0
+65	1	0
+60	1	1
+69	1	1
+42	0	1
+175	5	4
+100	1	0
+402	1	0
+39	1	0
+10	1	0
+10	1	0
+14	1	1
+95	4	2
+120	0	5
+126	1	1
+32	2	1
+72	1	1
+335	1	1
+45	1	0
+403	4	1
+54	1	0
+108	1	0
+289	1	1
+40	1	0
+164	12	12
+169	1	1
+76	1	1
+71	3	3
+34	1	1
+65	72	72
+84	64	1
+55	190	1
+52	1	1
+42	5	5
+138	1	1
+39	1	1
+311	6	7
+300	1	0
+597	17	17
+187	1	1
+32	100	2817
+24	203	202
+36	1	1
+115	4	0
+139	25	24
+1050	1	0
+56	1	0
+90	1	0
+33	1	0
+35	3	0
+114	1	1
+19	1	1
+215	1	0
+431	1	1
+23	1	0
+421	14	11
+292	1	1
+22	1	1
+49	2741	2490
+33	4095	4075
+9	0	3
+18	1474	1474
+3	6	1
+11	3	0
+38	14404	14348
+27	15613	15513
+5	5	5
+21	1	2
+13	19	20
+34	104	104
+44	214	216
+8	3	0
+27	2800	929
+60	1	1
+29	4270	3383
+30	49	0
+26	1	1
+40	2712	2960
+33	1	1
+7
+
+chain	2173268	chr17_random	2617613	+	699498	748919	1	249250621	-	248538148	248591008	468
+685	3	3
+36	4	4
+73	9	5
+59	70	63
+42	285	48
+44	1	1
+96	74	80
+321	1	1
+49	1	1
+107	1	1
+47	11	2
+85	3	0
+67	1	0
+179	19	16
+220	9	0
+138	33	33
+136	1	1
+26	1	1
+545	1	0
+8	14	10
+42	1	1
+64	1	1
+28	1	1
+119	1	1
+49	1	1
+54	1	1
+32	1	1
+960	1	1
+41	1	1
+731	16	16
+57	1	1
+19	1	1
+118	1	0
+196	1	1
+50	1	1
+263	1	1
+52	1	1
+171	1	1
+26	1	1
+181	25	16
+51	27	0
+56	1	1
+139	0	4
+33	1	1
+236	1	1
+17	1	1
+192	15	13
+186	1	1
+30	7	7
+280	1	1
+80	1	0
+196	62	54
+290	1	1
+38	1	1
+772	10	10
+123	1	1
+28	1	0
+20	34	22
+81	0	4
+45	1	1
+806	1	1
+31	1	0
+35	1	1
+101	17	15
+89	1	1
+34	1	0
+8	1	1
+290	13	9
+284	1	0
+53	7	0
+26	6	0
+605	4	0
+531	35	35
+704	1	1
+66	1	1
+168	1	1
+34	1	1
+527	1	1
+30	1	1
+249	16	7
+414	1	1
+27	1	1
+344	1	1
+43	1	1
+117	1	1
+30	1	1
+862	0	1
+229	1	1
+48	1	1
+197	14	14
+972	19	31
+924	1	1
+42	1	1
+123	1	1
+56	1	1
+77	1	1
+23	1	1
+119	1	1
+53	18	11
+382	1	1
+17	1	1
+116	5	2
+37	1	1
+38	2	0
+223	1	1
+21	6	1
+583	1	0
+400	0	4
+1574	27	27
+54	4	1
+158	10	7
+336	6	7
+492	1	0
+14	1	1
+843	1	2
+247	1	1
+41	1	1
+50	6	6
+513	17	13
+615	12	12
+585	32	23
+161	6	6
+515	9	5
+43	5	3
+460	5	5
+158	11	11
+252	1	1
+22	3	0
+135	12	12
+556	0	1
+542	3	0
+298	4	1
+24	4	0
+117	9	5
+151	0	1
+291	0	1
+360	15	15
+962	20	17
+231	1	0
+293	1	0
+33	32	0
+40	15	10
+213	23	23
+458	1	1
+51	1	1
+437	1	0
+394	1	1
+25	2	0
+117	10	4
+50	1	1
+40	1	1
+626	8	5
+492	1	0
+383	1	0
+672	1	1
+136	1	1
+203	2	2
+88	1	1
+261	1	1
+45	1	1
+189	15	15
+78	1	1
+49	1	1
+93	1	0
+35	13	10
+21	1	1
+527	99	94
+103	44	44
+79	24	26
+111	39	36
+235	24	27
+117	7	7
+127	222	1777
+58	167	165
+59	75	75
+203	12	12
+55	56	44
+269	34	32
+87	24	24
+250	35	29
+682	91	91
+312	4	3
+583	124	2653
+132	399	398
+134	1	1
+33	1	1
+179	1	1
+27	1	1
+245	4	4
+93	1	1
+940	1	1
+20	1	1
+271	1	1
+16	0	1
+353	24	17
+369	146	0
+83	1	1
+34	1	1
+1103	1	1
+26	1	1
+112	1	0
+3	1	0
+370	32	27
+410	170	174
+51	1	1
+310	42	41
+66	5	2
+319
+
+chain	2047886	chr17_random	2617613	+	532224	554093	17	81195210	-	39794017	39815907	1262
+682	50	50
+270	0	4
+316	0	1
+691	1	0
+678	1	2
+601	1	0
+383	1	0
+20	1	1
+1048	2	0
+1884	0	6
+690	0	5
+1205	1	1
+43	0	2
+891	19	19
+1916	7	6
+2354	0	3
+2253	10	0
+2406	0	13
+1972	6	6
+595	0	4
+148	100	100
+356	20	20
+109	4	4
+73	2	0
+59
+
+chain	1863993	chr17_random	2617613	+	1011919	1106715	17	81195210	+	34578530	36287451	432
+1027	148	148
+295	18	18
+204	37	37
+144	7	7
+238	38	38
+357	101	101
+125	64	64
+712	21	22
+181	126	1729
+702	0	2
+184	29	30
+236	37	37
+1080	60	65
+606	1	0
+328	63	63
+556	20	20
+94	37	37
+172	0	1
+1430	0	1
+151	53	53
+605	36	36
+292	1	0
+84	17921	60667
+87	11034	74480
+38	804	804
+30	345	345
+62	200	200
+36	1097	1097
+33	696	696
+48	119	119
+30	986	986
+81	185	185
+35	641	641
+232	79	79
+116	288	288
+61	11306	1517682
+155	7	0
+427	5	5
+742	2	0
+85	1	1
+401	1	1
+97	1	1
+566	1	0
+607	1	0
+1318	0	24
+1995	71	3
+34	0	2
+44	1	1
+39	0	1
+3518	0	4
+469	1	0
+294	10	13
+520	6	6
+403	0	3
+331	1	0
+231	7	0
+255	0	1
+3122	0	1
+729	0	1
+117	11	11
+186	4	0
+84	1	0
+412	2	0
+19	1	1
+1642	6	0
+628	1	1
+21	1	1
+377	50	50
+151	0	9
+2370	1	1
+35	1	1
+1328	1	10
+586	14	0
+789	12	13
+1397	0	1
+1521	0	2
+382	0	1
+866	1	1
+20	1	1
+710	2	0
+1259	161	161
+387	28	28
+53	24	24
+3626	1	0
+1718
+
+chain	1732426	chr17_random	2617613	+	2586433	2605017	17	81195210	-	39776940	39795500	1439
+1157	1	1
+31	0	5
+2053	8	8
+691	1	1
+30	1	1
+1212	3	0
+3864	1	0
+3	1	0
+56	15	0
+860	1	1
+30	1	1
+6532	4	4
+147	13	13
+1042	17	17
+319	7	0
+181	10	10
+68	42	42
+51	16	14
+115
+
+chain	1719393	chr17_random	2617613	+	1323861	1343929	17	81195210	+	45650033	45670000	1446
+76	1	1
+94	1	1
+84	9	9
+70	1	1
+43	1	0
+40	0	2
+126	1	1
+38	1	1
+391	1	1
+43	1	1
+100	0	1
+66	12	12
+65	1	1
+39	2	0
+9	4	0
+25	1	1
+99	1	1
+27	0	4
+362	22	4
+659	2	0
+433	0	20
+16	1	1
+117	1	1
+248	1	1
+200	1	1
+23	1	1
+248	6	0
+120	1	1
+930	1	1
+14	1	1
+76	1	1
+11	1	0
+23	2	0
+23	1	1
+236	1	1
+48	1	1
+108	1	1
+141	7	5
+50	1	1
+27	1	1
+306	0	3
+290	1	1
+20	0	1
+31	1	1
+618	5	6
+350	14	6
+55	0	2
+112	4	0
+50	1	1
+263	1	0
+51	1	1
+527	1	1
+47	1	1
+247	1	1
+34	3	3
+169	0	2
+33	3	0
+165	12	0
+163	1	1
+77	1	0
+56	26	26
+54	6	6
+338	2	0
+185	73	73
+336	0	3
+89	1	1
+19	1	1
+65	18	18
+89	0	1
+178	1	1
+45	1	1
+67	8	0
+347	0	1
+22	1	1
+192	1	1
+73	1	4
+38	0	1
+61	1	1
+164	1	1
+74	3	3
+260	5	0
+89	9	9
+142	1	1
+49	1	1
+71	0	1
+62	1	1
+391	1	1
+78	1	1
+100	1	1
+32	1	1
+155	11	12
+304	8	0
+79	1	1
+115	1	1
+29	1	1
+97	19	0
+168	1	1
+19	4	4
+359	2	0
+18	1	1
+358	1	1
+38	1	1
+83	1	1
+31	1	1
+389	1	1
+32	1	1
+128	1	1
+39	1	1
+54	1	1
+11	2	0
+165	4	0
+34	1	1
+58	1	1
+68	3	0
+230	1	1
+44	1	1
+276	16	16
+170	6	6
+104	1	1
+61	1	1
+107	6	6
+177	1	1
+66	5	0
+60	1	1
+14	1	1
+50	4	4
+15	1	1
+62	1	1
+194	1	1
+72	22	1
+39	1	1
+70	1	1
+42	1	1
+58	1	1
+36	1	1
+329	1	0
+136	1	1
+192	9	10
+682	24	21
+81	0	1
+367	12	12
+81
+
+chain	1570588	chr17_random	2617613	+	1644335	1687876	17	81195210	+	66068832	66112387	1087
+1168	16352	16361
+2197	2	0
+1554	1	0
+6339	0	4
+1936	0	7
+2357	2	0
+7231	1	0
+4401
+
+chain	1476469	chr17_random	2617613	+	2303443	2319476	17	81195210	+	79885696	79901628	1655
+880	1	0
+298	1	0
+60	43	40
+227	40	38
+326	1	0
+77	1	0
+148	1	0
+199	21	19
+60	1	0
+224	1	0
+173	1	0
+317	88	84
+84	1	0
+96	48	45
+432	1	0
+107	1	0
+505	1	0
+88	1	0
+551	1	0
+107	1	0
+176	1	0
+79	2	0
+127	1	0
+56	1	0
+239	1	0
+218	1	0
+11	1	0
+27	1	0
+256	1	0
+130	1	0
+60	1	0
+586	1	0
+96	1	0
+58	1	0
+80	1	0
+135	1	0
+55	1	0
+219	5	2
+11	4	2
+30	4	1
+368	1	0
+106	1	0
+119	18	13
+146	1	0
+636	1	0
+156	1	0
+541	1	0
+107	1	0
+97	1	0
+61	1	0
+66	1	0
+7	1	0
+238	1	0
+105	1	0
+13	1	0
+667	1	0
+85	1	0
+70	1	0
+642	1	0
+635	1	0
+57	1	0
+249	1	0
+237	1	0
+162	1	0
+166	1	0
+380	1	0
+271	1	0
+215	2	0
+260	1	0
+160	1	0
+62	1	0
+6	1	0
+185	1	0
+48	1	0
+265	5	2
+87	1	0
+186	1	0
+62	1	0
+20	1	0
+135
+
+chain	1260177	chr17_random	2617613	+	853052	928106	17	81195210	-	43628	125104	962
+949	1	0
+3976	1	0
+155	1	0
+1382	1	0
+174	1	0
+249	1	0
+3481	16	14
+138	196	313
+72	88	86
+491	22816	3210
+803	32	32
+116	1	0
+346	10	9
+779	1	0
+620	1	0
+336	1	0
+2035	1	0
+1010	1	0
+1029	22	20
+97	39	114
+77	79	0
+5135	26	26
+535	1	0
+2026	21	19
+206	2	0
+254	19578	45525
+174	1	1
+34	1	1
+97	25	25
+137	6	5
+2443	14	9
+445	1	0
+116	1	0
+2150
+
+chain	1227372	chr17_random	2617613	+	986700	1051441	17	81195210	+	34570816	36317431	617
+294	0	3023
+141	196	196
+44	109	109
+53	147	147
+19	33	32
+101	42	42
+166	603	602
+128	1742	1742
+37	15134	15157
+88	7169	151654
+89	3878	5468
+37	1080	1080
+60	1668	1668
+37	1753	1753
+53	605	605
+36	506	39138
+695	47	47
+375	59	59
+312	20	20
+185	37	37
+144	7	7
+238	38	38
+357	101	101
+125	64	64
+712	185	184
+2677	120	1494235
+1055	15	15
+700	4	4
+1174	24	24
+888	9	3
+1590	0	3
+913	18	20
+1011	1	1
+26	1	1
+2545	1	1
+35	1	1
+1283	87	87
+45	432	432
+149	418	418
+46	284	284
+2	3	3
+30	1838	1839
+89	540	540
+32	511	512
+48	2400	2403
+39	3223	3228
+39	360	360
+49	178	178
+59
+
+chain	1028733	chr17_random	2617613	+	2262901	2274699	17	81195210	-	1281214	1293541	2373
+276	161	161
+1171	1	0
+181	1	0
+943	1	0
+423	1	0
+384	47	47
+111	466	1042
+106	31	31
+75	4	4
+63	20	16
+142	1	0
+59	1	0
+607	1	0
+135	1	0
+31	1	0
+82	1	0
+266	1	0
+76	1	0
+5	4	2
+41	1	0
+52	1	0
+985	1	0
+87	1	0
+4	1	0
+114	1	0
+175	1	0
+30	1	0
+140	2	0
+22	1	0
+130	1	0
+239	1	0
+766	1	0
+203	1	0
+68	2	0
+252	1	0
+300	4	2
+377	1	0
+735	1	0
+279	5	2
+91	1	0
+66	1	0
+159	1	0
+7	1	0
+562
+
+chain	931587	chr17_random	2617613	+	978106	1010959	17	81195210	+	36277154	36406169	991
+1048	10	12
+382	0	1
+199	22	22
+381	8	8
+56	66	66
+80	176	176
+73	27	27
+90	32	32
+166	31	209
+634	0	4
+1199	65	65
+56	27	27
+255	27	27
+50	1	7
+422	5	5
+61	4	0
+80	311	311
+40	144	144
+53	3450	47979
+41	18030	69497
+201	21	0
+219	1	0
+310	0	1
+3136	0	1
+510	50	52
+321	3	0
+279
+
+chain	813092	chr17_random	2617613	+	1807252	1826317	17	81195210	+	22246129	22262163	2589
+338	20	20
+223	15	15
+164	162	162
+54	59	60
+73	230	230
+52	48	48
+50	66	66
+54	49	49
+257	14	14
+103	22	22
+96	5	5
+357	121	121
+100	88	88
+108	94	94
+490	34	34
+81	27	27
+54	82	82
+80	138	138
+128	12	12
+262	24	21
+199	35	35
+263	80	80
+84	52	52
+185	16	16
+75	113	113
+160	99	99
+70	27	27
+84	49	49
+59	25	25
+133	30	30
+64	45	45
+304	25	25
+986	74	74
+160	13	13
+209	22	22
+54	43	43
+61	156	156
+54	6	6
+77	5	5
+86	85	85
+117	48	165
+381	74	74
+262	32	32
+165	71	71
+57	95	95
+89	31	31
+114	140	140
+117	216	216
+77	5	5
+52	442	441
+185	60	60
+363	22	22
+179	11	11
+259	197	197
+118	35	35
+108	60	60
+61	61	61
+137	50	50
+53	56	56
+269	161	161
+106	103	105
+56	8	8
+368	41	41
+47	3145	0
+401	42	42
+90	23	23
+151	73	73
+81	148	146
+351
+
+chain	788653	chr17_random	2617613	+	1298766	1307227	17	81195210	-	44798207	44806654	6145
+463	1	0
+2422	0	1
+90	14	0
+75	0	1
+397	0	1
+64	1	1
+30	0	1
+202	1	0
+1329	2	0
+1396	1	0
+668	0	1
+280	45	45
+980
+
+chain	597412	chr17_random	2617613	+	807879	2303216	17	81195210	-	0	1281216	430
+180	1676	138
+25553	1	0
+149	14	14
+1938	1	0
+350	32	32
+1230	1	0
+3	1	0
+6237	1	0
+45	2	2
+6514	1	0
+228	662945	0
+7897	0	1
+2396	1	0
+1101	17	0
+41	1	1
+355	0	52
+50	18	1
+41	0	68
+84	34	0
+4918	0	1
+717	0	1
+313	1	1
+42	1	1
+73	29	31
+205	58	0
+414	1	1
+64	1	1
+959	1	1
+17	1	1
+2276	1	0
+739	0	1
+418	11	49
+1541	0	1
+3494	7	13
+1281	21	21
+1738	1	191
+26	0	38
+40	0	77
+67	5	5
+11	1	75
+55	2266	0
+112	47	9
+78	38	0
+24	1	1
+80	5	5
+551	0	5
+87	1	1
+35	1	1
+54	119	195
+74	1	1
+957	15	15
+64	1277	306
+91	1	1
+35	1	1
+820	48	67
+330	0	1
+2794	1	0
+1127	1	1
+19	0	5
+1483	715858	1169096
+78	1	0
+529	1	0
+25	1	0
+200	1	0
+643	2	0
+450	2	0
+211	1	0
+380	2	2
+180	2	1
+32	1	0
+246	1	0
+61	1	0
+5	1	0
+351	1	0
+37	1	0
+304	1	0
+18	1	0
+109	1	0
+16	1	0
+200	1	0
+105	1	0
+37	1	0
+376	1	0
+108	1	0
+91	1	0
+394	1	0
+20	1	0
+1014	32	30
+21	2	1
+34	1	0
+230	26	26
+941	1	0
+188	1	0
+610	1	0
+555	1	0
+303	1	0
+509	157	157
+169	22	22
+101	1	0
+501	1	0
+140	1	0
+78	2	1
+22	1	0
+39	6	5
+62	94	94
+593	114	111
+260	120	120
+362	1	0
+697	0	1
+123	28	28
+402	36	36
+904	1	0
+50	1	0
+379	1	0
+256	25	25
+23	17	17
+53	27	27
+556	1	0
+409	1	0
+106	1	0
+276	24	24
+35	2	0
+252	32	32
+213	4	4
+70	2	0
+27	4	2
+82	1	0
+17	1	0
+639	1	0
+172	11	7
+10	1	0
+76	1	0
+1582	1	0
+275	1	0
+21	1	0
+17	4	2
+66	1	0
+1653	1	0
+19	3	3
+139	179	179
+76	2	2
+60	1	0
+226	1	0
+538	1	0
+346	4	4
+42	25	25
+1319	1	0
+261	1	0
+512	1	0
+69	1	0
+480	2	0
+388	8	7
+305	5	5
+64	2	2
+846
+
+chain	590397	chr17_random	2617613	+	1317586	1323861	17	81195210	-	44817018	44823295	6400
+2259	1	0
+955	0	1
+2132	0	1
+744	0	1
+184
+
+chain	365975	chr17_random	2617613	+	1296053	1313819	17	81195210	+	45621804	45639993	6832
+81	12	44
+148	0	6
+401	61	62
+589	32	30
+259	39	57
+53	103	103
+231	127	131
+59	7954	7632
+45	980	978
+16	142	143
+82	46	46
+363	247	934
+159	50	48
+341	33	34
+57	16	16
+304	65	65
+69	9	9
+136	66	66
+138	57	57
+70	10	10
+70	123	120
+143	52	52
+152	15	19
+320	53	52
+121	0	1
+161	98	108
+97	59	59
+205	127	125
+55	11	11
+56	30	30
+88	43	43
+512	45	43
+125	143	136
+165	48	48
+56	24	24
+161	114	115
+364	40	40
+240
+
+chain	323854	chr17_random	2617613	+	753664	757726	11	135006516	+	51394886	51398944	206195
+84	571	570
+807	3	1
+2082	1	0
+514
+
+chain	193433	chr17_random	2617613	+	495545	497612	17	81195210	+	41377728	41379794	617459
+55	1	0
+1306	28	28
+677
+
+chain	170984	chr17_random	2617613	+	1315777	1317585	17	81195210	-	44815210	44817018	741311
+1808
+
+chain	158566	chr17_random	2617613	+	1808012	1818883	17	81195210	+	22251644	22262630	5258
+162	209	210
+87	88	88
+32	270	270
+48	855	855
+36	185	185
+88	888	888
+37	888	888
+35	263	263
+80	85	85
+51	276	276
+47	20	20
+46	329	329
+27	350	350
+4	5	5
+21	413	412
+25	986	986
+74	458	458
+43	137	137
+80	228	228
+85	546	663
+9	10	10
+55	262	262
+32	293	293
+68	116	116
+25	120	120
+109	148	148
+60	1	1
+67	6	4
+74	1	1
+7	134	134
+220	1	1
+65	1	1
+91	1	1
+62	186	186
+60
+
+chain	150869	chr17_random	2617613	+	749022	751008	11	135006516	+	51475668	51477652	852441
+306	379	377
+1301
+
+chain	148651	chr17_random	2617613	+	808184	809735	17	81195210	+	81137722	81139272	865111
+940	1	0
+610
+
+chain	145464	chr17_random	2617613	+	1314230	1315767	17	81195210	-	44813661	44815198	885049
+1537
+
+chain	120518	chr17_random	2617613	+	1343929	1345208	17	81195210	-	44843364	44844643	723183
+1279
+
+chain	116919	chr17_random	2617613	+	1353036	1364922	17	81195210	-	44845210	44857111	1380
+449	299	299
+31	164	164
+55	373	373
+449	9718	9733
+348
+
+chain	115845	chr17_random	2617613	+	508518	509981	17	81195210	-	39794017	39795500	1110103
+682	50	50
+270	0	4
+177	169	185
+115
+
+chain	114042	chr17_random	2617613	+	516500	517961	17	81195210	-	39794017	39795500	1127130
+682	50	50
+210	5	6
+54	0	6
+175	170	185
+115
+
+chain	113591	chr17_random	2617613	+	521388	522849	17	81195210	-	39794017	39795500	1131524
+58	0	1
+623	50	50
+210	5	6
+54	0	6
+175	171	185
+115
+
+chain	112548	chr17_random	2617613	+	503499	505329	17	81195210	-	39794017	39795500	1141710
+27	370	0
+655	50	50
+210	5	6
+54	0	7
+174	170	185
+115
+
+chain	92910	chr17_random	2617613	+	1642194	1643169	17	81195210	-	1314977	1315952	1374174
+975
+
+chain	86438	chr17_random	2617613	+	1345275	1346182	17	81195210	-	44844700	44845607	1472746
+907
+
+chain	80313	chr17_random	2617613	+	2609695	2610598	17	81195210	-	39794017	39794920	1580802
+682	50	50
+171
+
+chain	78741	chr17_random	2617613	+	1643269	1644095	17	81195210	+	79874782	79875608	1611354
+826
+
+chain	75472	chr17_random	2617613	+	1310578	1313579	17	81195210	-	44810007	44813007	188419
+53	282	282
+98	97	97
+59	205	205
+127	122	122
+30	88	88
+43	512	512
+45	125	125
+72	1	0
+70	165	165
+48	241	241
+114	364	364
+40
+
+chain	74354	chr17_random	2617613	+	1547620	1548395	8	146364022	-	2302524	2303299	1703290
+775
+
+chain	61189	chr17_random	2617613	+	1546707	1547351	8	146364022	+	144057273	144057917	2067192
+644
+
+chain	59362	chr17_random	2617613	+	751149	753548	1	249250621	-	248579195	248581575	182656
+35	2	1
+152	1	0
+15	1	0
+107	3	2
+74	1	0
+10	1	0
+19	1	0
+57	1	1
+48	3	1
+6	1	0
+107	12	330
+61	1	1
+51	357	35
+388	110	110
+84	38	38
+62	227	223
+116	106	105
+141
+
+chain	56858	chr17_random	2617613	+	1298104	1298766	17	81195210	-	44797535	44798197	1968612
+85	59	59
+518
+
+chain	56536	chr17_random	2617613	+	501286	502149	17	81195210	-	39794614	39795500	2243684
+85	50	50
+210	5	6
+54	0	7
+174	170	185
+115
+
+chain	55411	chr17_random	2617613	+	688273	689806	7	159138663	-	159114165	159114723	7844
+88	175	0
+148	458	0
+103	231	3
+111	117	3
+102
+
+chain	52941	chr17_random	2617613	+	1822234	1824166	17	81195210	-	58941545	58943477	1155
+887	1	1
+77	1	1
+300	1	1
+20	9	9
+133	1	1
+23	1	1
+59	1	1
+158	1	1
+91	1	1
+54	1	1
+112
+
+chain	52559	chr17_random	2617613	+	983839	1162005	17	81195210	-	44845659	46605886	726
+299	65	65
+117	68	68
+1986	9723	54270
+49	72036	1500609
+1027	6412	6412
+71	13528	13528
+50	11447	11447
+132	60546	169487
+42	528	528
+40
+
+chain	51097	chr17_random	2617613	+	1023443	1026449	17	81195210	+	34744258	34747264	8774
+47	375	375
+59	517	517
+37	389	389
+38	357	357
+101	125	125
+64	712	712
+185
+
+chain	49537	chr17_random	2617613	+	686221	687340	7	159138663	-	159114165	159114714	2581538
+393	570	0
+156
+
+chain	49422	chr17_random	2617613	+	2502237	2515076	GL000206.1	41001	+	6806	19645	760
+60	12323	12323
+456
+
+chain	46461	chr17_random	2617613	+	530697	531391	17	81195210	+	41399710	41400427	2769983
+115	170	185
+151	0	7
+77	5	6
+176
+
+chain	44819	chr17_random	2617613	+	1346282	1352646	17	81195210	+	36399842	36406169	117269
+158	113	113
+546	19	0
+337	0	1
+343	21	0
+219	1	0
+310	0	1
+3136	0	1
+510	1	1
+49	0	2
+321	1	0
+279
+
+chain	42351	chr17_random	2617613	+	1308282	1310091	17	81195210	-	44807710	44809519	659295
+50	341	341
+33	377	377
+65	214	214
+66	138	138
+57	150	150
+123	143	143
+52
+
+chain	41114	chr17_random	2617613	+	1307243	1308123	17	81195210	-	44806671	44807550	1295496
+142	82	82
+46	363	362
+247
+
+chain	38415	chr17_random	2617613	+	980212	983216	17	81195210	-	46382593	46436652	7347
+66	80	80
+176	73	73
+27	90	90
+32	166	166
+31	1833	52888
+65	56	56
+27	255	255
+27
+
+chain	37708	chr17_random	2617613	+	1313819	1314225	17	81195210	-	44813251	44813657	3332998
+406
+
+chain	34385	chr17_random	2617613	+	689365	745709	16	90354753	+	90179685	90235100	655
+111	4456	3661
+64	55	55
+25	28	28
+47	0	945
+90	45591	45393
+56	269	269
+34	5469	4540
+13	2	2
+32	0	48
+2
+
+chain	29758	chr17_random	2617613	+	1820296	1826385	17	81195210	+	22249775	22252718	80336
+37	643	643
+77	136	133
+51	3143	0
+44	74	74
+224	80	80
+64	79	79
+9	741	741
+39	82	82
+59	25	25
+56	358	358
+68
+
+chain	29219	chr17_random	2617613	+	1551349	1551651	17	81195210	+	81144397	81144699	5017519
+302
+
+chain	28762	chr17_random	2617613	+	686677	687796	7	159138663	-	159114165	159114714	2625478
+282	456	0
+111	3	3
+57	114	0
+96
+
+chain	26027	chr17_random	2617613	+	1296695	1298103	17	81195210	-	44796117	44797535	630440
+61	589	589
+32	259	269
+39	53	53
+103	231	231
+41
+
+chain	25589	chr17_random	2617613	+	1810180	1822057	17	81195210	+	22246679	22258671	5893
+31	6949	7063
+28	2666	2666
+60	580	580
+49	73	73
+37	1172	1173
+232
+
+chain	22463	chr17_random	2617613	+	503557	503790	17	81195210	-	39794076	39794309	8690008
+233
+
+chain	21299	chr17_random	2617613	+	1013035	1014722	17	81195210	+	34795732	34797419	1064
+59	517	517
+37	389	389
+38	357	357
+101	125	125
+64
+
+chain	20434	chr17_random	2617613	+	685587	686087	7	159138663	-	159114215	159114487	2822651
+209	248	20
+43
+
+chain	19692	chr17_random	2617613	+	2611651	2612116	17	81195210	-	39813091	39813524	10717347
+67	163	137
+78	68	62
+89
+
+chain	19589	chr17_random	2617613	+	2616810	2617276	17	81195210	+	41381686	41382119	10803726
+89	68	62
+77	165	138
+67
+
+chain	17762	chr17_random	2617613	+	852036	852257	5	180915260	-	51646	51969	938
+13	1	1
+60	1	1
+29	1	1
+13	0	102
+103
+
+chain	17600	chr17_random	2617613	+	1364922	1365125	17	81195210	-	46397651	46397854	1833
+172	1	1
+30
+
+chain	17149	chr17_random	2617613	+	1514626	1514877	1	249250621	+	547399	547650	3354419
+131	1	3
+101	2	0
+16
+
+chain	16567	chr17_random	2617613	+	2610699	2610873	17	81195210	-	39795026	39795200	13468304
+174
+
+chain	16365	chr17_random	2617613	+	1812948	1813633	17	81195210	+	22258959	22259644	44227
+99	181	181
+49	59	59
+25	227	227
+45
+
+chain	16348	chr17_random	2617613	+	525487	525673	11	135006516	+	62609095	62609281	13688187
+75	4	4
+107
+
+chain	14733	chr17_random	2617613	+	2605728	2605963	17	81195210	-	39813295	39813524	15353144
+78	68	62
+89
+
+chain	14711	chr17_random	2617613	+	556093	556262	11	135006516	-	72397235	72397404	15378622
+107	4	4
+58
+
+chain	14711	chr17_random	2617613	+	527846	528015	11	135006516	-	72397235	72397404	15378623
+107	4	4
+58
+
+chain	14711	chr17_random	2617613	+	512402	512571	11	135006516	-	72397235	72397404	15378624
+107	4	4
+58
+
+chain	14711	chr17_random	2617613	+	510910	511079	11	135006516	-	72397235	72397404	15378625
+107	4	4
+58
+
+chain	14711	chr17_random	2617613	+	494247	494416	11	135006516	-	72397235	72397404	15378626
+107	4	4
+58
+
+chain	14711	chr17_random	2617613	+	492878	493047	11	135006516	-	72397235	72397404	15378627
+107	4	4
+58
+
+chain	14711	chr17_random	2617613	+	519356	519525	11	135006516	+	62609112	62609281	15378630
+58	4	4
+107
+
+chain	14711	chr17_random	2617613	+	514467	514636	11	135006516	+	62609112	62609281	15378631
+58	4	4
+107
+
+chain	14711	chr17_random	2617613	+	492408	492577	11	135006516	+	62609112	62609281	15378632
+58	4	4
+107
+
+chain	13395	chr17_random	2617613	+	685879	686024	7	159138663	-	159114165	159114310	16961745
+145
+
+chain	12350	chr17_random	2617613	+	554102	554230	17	81195210	+	41401065	41401193	18472361
+128
+
+chain	11140	chr17_random	2617613	+	2611055	2611170	17	81195210	-	39795385	39795500	20498301
+115
+
+chain	11115	chr17_random	2617613	+	1365516	1365648	17	81195210	-	46613257	46613389	1914
+132
+
+chain	10814	chr17_random	2617613	+	689806	689963	7	159138663	-	159114495	159114652	3160720
+43	20	20
+94
+
+chain	10716	chr17_random	2617613	+	690046	690160	11	135006516	-	134823089	134823203	21297817
+114
+
+chain	10594	chr17_random	2617613	+	686107	686221	11	135006516	-	134823089	134823203	21541329
+114
+
+chain	10432	chr17_random	2617613	+	752965	753084	3	198022430	+	197944313	197944432	1419040
+26	27	27
+66
+
+chain	10233	chr17_random	2617613	+	751962	752152	1	249250621	-	25108929	25109119	2449036
+190
+
+chain	10215	chr17_random	2617613	+	298300	298405	17	81195210	-	41991981	41992086	2272776
+105
+
+chain	10088	chr17_random	2617613	+	2614941	2615048	11	135006516	-	72397235	72397342	22628945
+107
+
+chain	9967	chr17_random	2617613	+	687027	687133	7	159138663	-	159114173	159114279	19905170
+106
+
+chain	9953	chr17_random	2617613	+	1352829	1353036	17	81195210	-	44845003	44845210	3604154
+38	53	53
+37	50	50
+29
+
+chain	9937	chr17_random	2617613	+	2607755	2608553	17	81195210	+	41464708	41466209	22969163
+59	661	1364
+78
+
+chain	9782	chr17_random	2617613	+	685310	686656	7	159138663	-	159114165	159114714	2594423
+225	1079	282
+42
+
+chain	9490	chr17_random	2617613	+	268561	268666	17	81195210	+	39296306	39296411	8067183
+50	6	6
+49
+
+chain	9384	chr17_random	2617613	+	1808529	1810797	17	81195210	+	22256920	22261566	263516
+29	104	104
+28	50	50
+48	1976	4354
+33
+
+chain	9278	chr17_random	2617613	+	1333217	1333901	17	81195210	-	44832655	44833339	2515
+26	585	585
+73
+
+chain	9162	chr17_random	2617613	+	1819790	1824781	17	81195210	+	22261160	22263006	131478
+64	322	322
+59	818	816
+30	3642	499
+56
+
+chain	8930	chr17_random	2617613	+	507298	507390	17	81195210	+	41466131	41466223	25058540
+92
+
+chain	8739	chr17_random	2617613	+	1294354	1363161	17	81195210	-	46388680	46446941	1280
+36	59095	48559
+76	160	160
+63	250	250
+52	124	124
+61	4094	4092
+28	4719	4711
+49
+
+chain	7495	chr17_random	2617613	+	1514877	1514981	17	81195210	-	42613	42717	4053350
+104
+
+chain	7310	chr17_random	2617613	+	1352662	1353007	17	81195210	-	20840434	20840778	292042
+167	38	37
+53	37	37
+50
+
+chain	6706	chr17_random	2617613	+	687825	687939	7	159138663	-	159114173	159114287	10506562
+114
+
+chain	6456	chr17_random	2617613	+	673480	673547	11	135006516	-	134811854	134811921	22781013
+67
+
+chain	5049	chr17_random	2617613	+	752664	753185	1	249250621	-	248584104	248584621	921258
+110	84	84
+38	62	62
+7	119	119
+72	7	3
+22
+
+chain	5012	chr17_random	2617613	+	557502	557555	17	81195210	+	41382227	41382280	33565948
+53
+
+chain	4802	chr17_random	2617613	+	1345218	1345268	17	81195210	-	44844643	44844693	34312672
+50
+
+chain	4547	chr17_random	2617613	+	688053	688156	7	159138663	-	159114401	159114504	10358404
+103
+
+chain	4503	chr17_random	2617613	+	690214	690262	7	159138663	-	159114675	159114723	34814023
+48
+
+chain	4408	chr17_random	2617613	+	1808470	1808528	17	81195210	+	22261618	22261676	11976838
+58
+
+chain	4236	chr17_random	2617613	+	269418	269467	17	81195210	-	41933979	41934028	1349427
+49
+
+chain	3906	chr17_random	2617613	+	1365126	1365187	17	81195210	-	23109543	23109604	10221956
+61
+
+chain	3852	chr17_random	2617613	+	685196	685310	7	159138663	-	159114165	159114279	3139829
+114
+
+chain	3804	chr17_random	2617613	+	676798	676843	11	135006516	-	134814627	134814666	26257176
+33	6	0
+6
+
+chain	3734	chr17_random	2617613	+	1819749	1824493	17	81195210	+	22251604	22253205	550639
+41	1133	1133
+53	3451	308
+4	6	6
+56
+
+chain	3666	chr17_random	2617613	+	689649	689704	3	198022430	+	197891166	197891221	670
+55
+
+chain	3459	chr17_random	2617613	+	687133	687184	7	159138663	-	159114165	159114216	4526522
+51
+
+chain	3336	chr17_random	2617613	+	1365188	1365250	17	81195210	-	20853025	20853087	9938797
+62
+
+chain	3079	chr17_random	2617613	+	681792	681827	11	135006516	-	134820249	134820284	24010224
+35
+
+chain	2916	chr17_random	2617613	+	690160	690191	7	159138663	-	159114621	159114652	25187800
+31
+
+chain	2901	chr17_random	2617613	+	1010962	1011819	17	81195210	-	44844823	44845680	205824
+857
+
+chain	2668	chr17_random	2617613	+	837741	837773	8	146364022	+	31195	31227	1221
+32
+
+chain	2659	chr17_random	2617613	+	747955	747987	5	180915260	+	180755757	180755789	880
+32
+
+chain	2649	chr17_random	2617613	+	622962	622989	17	81195210	-	81153206	81153233	29165068
+27
+
+chain	2631	chr17_random	2617613	+	1252044	1252072	17	81195210	+	34548405	34548433	469
+28
+
+chain	2530	chr17_random	2617613	+	1100849	1100878	17	81195210	-	46384734	46384763	4689
+29
+
+chain	2422	chr17_random	2617613	+	621448	621568	17	81195210	-	81152835	81152952	7235512
+27	65	62
+28
+
+chain	2158	chr17_random	2617613	+	688361	688384	16	90354753	+	90179770	90179793	21906636
+23
+
+chain	2073	chr17_random	2617613	+	690420	690442	7	159138663	-	159114653	159114675	31315602
+22
+
+chain	1877	chr17_random	2617613	+	1533316	1533338	GL000206.1	41001	-	16469	16491	815
+22
+
+chain	1804	chr17_random	2617613	+	687361	687825	7	159138663	-	159114165	159114515	2659234
+54	381	267
+29
+
+chain	1771	chr17_random	2617613	+	742259	742283	1	249250621	-	248585388	248585412	123201
+24
+
+chain	1698	chr17_random	2617613	+	268509	268561	17	81195210	-	41933055	41933107	4387515
+52
+
+chain	1694	chr17_random	2617613	+	747513	747535	1	249250621	-	249115973	249115995	773
+22
+
+chain	1343	chr17_random	2617613	+	555358	555450	17	81195210	-	39728987	39729079	19263806
+92
+
+chain	1343	chr17_random	2617613	+	511667	511759	17	81195210	-	39728987	39729079	19263807
+92
+
+chain	1343	chr17_random	2617613	+	526316	526408	17	81195210	+	41466131	41466223	19263808
+92
+
+chain	1343	chr17_random	2617613	+	520168	520260	17	81195210	+	41466131	41466223	19263809
+92
+
+chain	1129	chr17_random	2617613	+	1019025	1019068	17	81195210	+	60348267	60348310	2834
+43
+
+chain	1082	chr17_random	2617613	+	686959	687027	7	159138663	-	159114561	159114629	2979122
+68
+
+chain	594	chr17_random	2617613	+	1548943	1548990	GL000206.1	41001	-	30268	30353	3713456
+4	9	47
+34
+
+chain	7055976638	chr18	76117153	+	0	76117153	18	78077248	+	10000	78016181	19
+15400898	1363998	3100000
+28218587	15	15
+5329636	47000	150000
+3667309	0	18
+16406890	28008	50000
+3388467	22000	50000
+2103304	3	0
+136125	7	9
+647	0	1
+1543	0	1
+25	0	1
+6	2	7
+19	0	2
+10	4	7
+9	2	4
+656	0	1
+358	0	1
+1625
+
+chain	404699	chr18_random	4262	+	0	4262	GL000207.1	4262	+	0	4262	116011
+4262
+
+chain	5307789368	chr19	63811651	+	11000	63806651	19	59128983	+	60000	59114839	21
+7286004	5000	50000
+1291194	5000	50000
+11767057	0	69160
+4058367	8000000	3100000
+20129228	0	2
+701	3	0
+347	1	1
+31	1	1
+1833	3	0
+1984	1	1
+47	1	1
+190	1	1
+34	1	1
+889	0	2
+1413	0	7
+2680	0	4
+375	0	1
+328	0	4
+15	0	1
+69	1	0
+3881	1	1
+36	0	12
+296	0	14
+1480	0	1
+233	1	1
+45	1	1
+1049	0	1
+1766	44	7
+220	3	0
+536	0	7
+352	8	8
+3603	1	1
+17	3	0
+697	1	0
+269	3	0
+974	6	5
+96	0	10
+1096	10	10
+1177	14	12
+110	3	3
+1028	12	9
+1090	1	0
+173	0	16
+1066	4	0
+4779	1	1
+42	1	1
+722	1	0
+548	2	2
+44	1	1
+424	54	54
+61	1	1
+59	1	1
+2086	0	15
+1500	1	0
+1754	2	0
+11209362
+
+chain	15150451	chr19_random	301858	+	142689	301858	GL000209.1	159169	+	0	159169	196
+159169
+
+chain	8748871	chr19_random	301858	+	0	92689	GL000208.1	92689	+	0	92689	377
+92689
+
+chain	14432273	chr1_random	1663265	+	444114	915337	1	249250621	-	104328377	105379619	206
+1802	63331	510
+7296	6958	14784
+7961	0	2
+631	19782	48350
+2466	1	1
+72	1	1
+281	2	2
+18	1	1
+2234	1	1
+23	2	1
+1869	0	2
+890	0	1
+2816	0	3
+59	12	12
+1298	1	1
+11	1	1
+294	214294	820733
+136815
+
+chain	10693564	chr1_random	1663265	+	965337	1079393	1	249250621	+	199645090	199759149	300
+3537	0	2
+1755	1	1
+38	1	1
+15918	1	0
+2372	0	1
+1251	34	34
+7007	1	6
+3552	1	1
+44	1	1
+799	1	1
+42	1	1
+3907	2	0
+1780	1	1
+49	1	1
+1586	2	0
+197	1	1
+37	1	1
+292	1	1
+47	1	1
+927	0	2
+549	1	1
+27	1	1
+595	1	1
+18	1	1
+291	0	2
+6685	1	0
+2369	1	0
+6503	13	13
+639	1	1
+70	1	1
+477	1	0
+1001	0	2
+1967	2	0
+3454	1	1
+26	1	1
+3144	0	4
+89	1	0
+6546	14	15
+6194	1	0
+5390	13	13
+196	1	0
+7401	1	9
+1242	1	0
+1702	1	0
+477	1	1
+61	0	1
+1487	1	0
+1276	1	0
+1950	9	0
+4681	0	2
+1332	1	0
+956
+
+chain	10110185	chr1_random	1663265	+	1464329	1570762	GL000191.1	106433	+	0	106433	317
+106433
+
+chain	6680210	chr1_random	1663265	+	198768	359123	1	249250621	+	1257620	1436018	467
+467	0	1
+41	0	1
+10	4	4
+930	2	3
+122	3	4
+138	66071	6986
+47	0	1
+945	0	1
+279	1	2
+508	0	1
+482	0	1
+1285	1	1
+40	1	1
+199	0	1
+207	1	1
+29	1	1
+1021	0	1
+1168	0	2
+388	0	1
+69	15	17
+195	4	4
+52	1	1
+9	1	3
+23	0	1
+284	0	1
+1485	15	16
+138	9	9
+27	44	5
+35	46	46
+97	0	1
+5	0	1
+734	0	3
+257	1	1
+18	1	1
+442	0	2
+51	4	0
+424	0	1
+134	1	1
+39	0	1
+22	1	1
+564	15	17
+469	0	3
+39	0	1
+22	2	2
+1076	0	1
+210	14	14
+166	0	1
+3264	1	0
+111	0	1
+309	19898	50666
+91	0	1
+116	0	1
+56	0	1
+152	0	1
+46	0	1
+51	0	1
+63	0	2
+420	4	5
+697	0	1
+2269	7	0
+48	1	1
+4086	0	2
+317	0	1
+49	0	1
+1795	0	1
+1147	1	1
+39	1	1
+1378	0	17
+477	2	0
+4457	1	1
+105	0	1
+1003	0	1
+232	1	2
+147	277	46717
+169	0	1
+37	1	1
+227	0	2
+651	1	0
+1805	1	1
+45	1	1
+498	1	0
+233	1	1
+29	1	1
+231	12	20
+2015	0	1
+20	1	1
+653	0	1
+12	0	1
+17	1	1
+139	0	1
+10	0	1
+22	0	1
+37	16	19
+38	0	5
+54	0	1
+437	0	1
+539	2	0
+1067	0	1
+1042	1	0
+2434	10	0
+256	133	0
+839	0	1
+267	0	1
+640	1	1
+35	1	1
+1351	15	15
+1316	1	1
+31	0	1
+1986	5	5
+1179	0	1
+3153	1	0
+1165	0	1
+22	0	1
+56	1	1
+27	1	1
+77	0	1
+81	15	17
+111	1	1
+44	0	1
+2254	1	0
+320	1	0
+2368	0	1
+26	0	1
+407	5	6
+2982	0	4
+852	0	5
+703	1	0
+191	2	3
+73	5	5
+72
+
+chain	4901563	chr1_random	1663265	+	676697	728522	1	249250621	-	205721991	205773795	637
+1664	1	0
+299	1	0
+1113	4	0
+100	1	0
+1522	1	1
+46	1	1
+83	1	1
+30	1	1
+62	1	1
+46	1	1
+1990	1	1
+41	1	1
+1403	0	4
+1148	0	5
+10134	1	1
+21	1	1
+1479	1	0
+1499	9	9
+3057	0	2
+137	6	0
+1251	2	0
+21	1	1
+897	5	4
+2851	1	0
+399	0	2
+624	6	5
+440	1	0
+5	1	0
+2953	1	0
+480	9	0
+2793	36	35
+6791	1	0
+4870	1	0
+1478
+
+chain	4504833	chr1_random	1663265	+	1205412	1353281	1	249250621	-	133273039	133340206	679
+3980	0	1
+79	1	1
+34	1	1
+916	4	6
+1818	34	28
+51	21	16
+5	1	0
+5	1	0
+4	1	0
+11	1	0
+28	1	0
+8	1	0
+8	1	0
+1366	1	1
+38	0	1
+7507	0	1
+3084	2	0
+2569	1	0
+20	1	0
+8	1	0
+10	21	16
+51	10	10
+3979	6	5
+2086	1	0
+5466	0	1
+27	1	1
+1117	1	0
+66	1	0
+23	1	0
+2070	0	1
+67	1	0
+2611	1	0
+9	1	0
+23	23	18
+577	97925	17254
+5929	0	1
+1948	1	0
+72	0	1
+1365	60	62
+706
+
+chain	3984524	chr1_random	1663265	+	1620762	1663230	X	155270560	-	27920664	27963158	751
+107	0	1
+696	27	12
+658	0	12
+1440	0	2
+671	0	2
+506	0	3
+806	0	1
+4759	0	12
+131	1	0
+848	1	0
+213	0	8
+2046	1	0
+4979	0	1
+2482	1	0
+1502	1	0
+3474	0	4
+782	0	1
+12366	1	0
+3969
+
+chain	2698055	chr1_random	1663265	+	6164	122978	1	249250621	-	139553697	139584554	1020
+486	1	1
+19	9	9
+297	1	1
+73	1	1
+341	1	0
+105	1	0
+286	47997	0
+689	1	1
+48	1	1
+53	0	2
+1870	1	1
+39	1	1
+1682	0	39
+470	8	9
+691	1	0
+370	1	1
+24	1	1
+356	0	1
+1496	9599	84
+28	0	1
+7	4	0
+131	0	1
+66	932	181
+88	9	11
+10	7	0
+10	8	5
+5	0	3
+76	27759	26
+44	3	0
+26	0	2
+6	1	1
+59	3	1
+121	2	4
+4990	1	0
+672	0	1
+1487	1	1
+39	1	1
+1691	0	1
+36	10	10
+3503	1	1
+46	1	1
+4128	0	1
+1818	0	5
+1107	16	16
+841
+
+chain	2474973	chr1_random	1663265	+	1129393	1155387	1	249250621	+	229232478	229258468	1104
+3505	1	1
+44	1	1
+5232	4	0
+17207
+
+chain	2468882	chr1_random	1663265	+	1280682	1387454	1	249250621	-	133163307	133238928	735
+149	0	1
+7073	122	124
+1799	1	1
+43	1	1
+5594	24	23
+60	12182	28596
+3279	1	0
+571	21	21
+1080	1	0
+10	0	2
+1138	1	0
+3484	1	0
+1689	0	8
+810	42350	1
+1088	1	1
+21	1	0
+78	30	29
+746	0	2
+2729	1	0
+2088	0	3
+1949	966	174
+31	9	0
+12	16	16
+29	0	4
+13	100	98
+53	1884	0
+16	1	0
+5	0	1
+18	3916	1388
+1729	0	1
+1373	1	0
+102	1	0
+21	1	0
+4	1	0
+7	1	0
+38	2	0
+48	1	0
+525	5	4
+645	5	5
+1189	1	0
+1911	4	0
+69	8	8
+24	5	4
+284	1	0
+1481
+
+chain	2064841	chr1_random	1663265	+	247141	392880	1	249250621	-	247850669	247948213	608
+351	1	0
+965	0	1
+35	0	1
+248	0	1
+122	0	1
+1194	11	11
+580	3	5
+969	0	1
+425	5	5
+25	1	1
+586	1	1
+77	1	1
+1895	1	1
+37	1	2
+253	0	1
+560	1	1
+62	1	1
+74	1	1
+27	1	1
+90	31631	11346
+887	0	40
+759	32	0
+2596	0	1
+308	1	0
+37	0	1
+40	0	1
+346	17	19
+89	2	2
+34	1	2
+44	0	2
+35	0	1
+20	0	1
+260	0	1
+3009	1	1
+30	0	1
+5	10	12
+104	1	1
+48	0	1
+67	13	15
+1226	0	1
+111	7	7
+31	0	1
+47	1	3
+13	3	5
+38	7	10
+7	0	2
+48	0	1
+110	1	0
+623	0	2
+241	1	1
+47	1	1
+1601	0	1
+582	13	21
+1128	2	0
+348	4	4
+28	22	23
+481	0	2
+30	1	1
+628	0	1
+96	0	1
+30	0	1
+78	17	173
+64	55865	28961
+69	13	14
+498	0	1
+1593	0	4
+183	26	27
+337	1	0
+1433	0	1
+6191	0	2
+2435	0	1
+3451	540	0
+83	695	0
+1318	5	5
+21	1	1
+526	0	1
+833	0	1
+144	0	1
+427	8	8
+235	1	2
+297	1	1
+34	0	1
+250	0	3
+1007	0	1
+1403	1	1
+37	1	1
+355	1	1
+6	0	2
+94	1	1
+278	2	2
+5	0	1
+20	1	1
+667	24	24
+1858	10	12
+146	8	7
+2002	0	1
+284	0	1
+1233	0	1
+840	11	0
+914	2	0
+122	1	1
+26	0	2
+118
+
+chain	1850028	chr1_random	1663265	+	76914	101906	1	249250621	-	139621990	139717568	1363
+3916	0	1
+77	20	20
+26	0	856
+764	17	16
+12	1	0
+295	1	0
+2648	2870	23264
+250	997	50331
+2203	0	5
+797	1	0
+2197	1	1
+117	7	8
+429	1	0
+7345
+
+chain	1707631	chr1_random	1663265	+	501749	626697	1	249250621	+	144188000	145316961	852
+223	42	42
+236	22	22
+242	91	103
+199	8	8
+102	112	112
+50	126	126
+290	32	32
+213	45	45
+125	1	1
+56	1	1
+82	1	1
+27	13	13
+71	5	5
+493	3	3
+15	1	1
+248	1	1
+44	1	1
+65	1	1
+52	1	1
+169	1	1
+82	1	1
+292	1	1
+83	0	1580
+458	1	1
+16	1	1
+478	5	5
+568	23	17
+634	1	1
+46	1	1
+50	14	14
+864	31	61
+55	23320	364967
+85	1	1
+107	1	1
+376	1	1
+20	0	1
+195	10	10
+150	1	1
+35	1	1
+274	5	5
+143	1	0
+862	7	0
+20	1	0
+504	1	1
+25	1	1
+238	1	1
+36	1	1
+139	0	1
+25	1	1
+157	8	8
+60	16	16
+59	17	17
+285	0	1
+120	1	1
+69	1	1
+509	1	1
+59	1	1
+162	0	322
+70	5	5
+2169	1	1
+31	1	1
+224	1	1
+36	1	1
+76	1	0
+5	5	0
+109	6	6
+139	5	3
+65	0	20
+360	47	48
+86	18	17
+149	44	44
+76	54	55
+196	38	38
+139	139	6280
+107	1	1
+95	0	1
+46	1	1
+91	1	1
+18	1	1
+62	11	11
+511	0	1
+106	1	0
+505	0	2
+443	9	9
+519	112	112
+396	1	1
+26	1	1
+225	1	1
+57	1	1
+502	1	0
+485	1	1
+105	0	2
+146	1	1
+41	1	1
+203	1	1
+45	1	1
+62	5	5
+850	1	1
+55	2	2
+215	1	1
+45	1	1
+474	0	3
+19	1	1
+2337	1	1
+34	1	1
+148	1	0
+159	1	1
+32	1	1
+64	0	4
+849	1	1
+34	1	1
+126	38816	272842
+32	0	140
+3176	18	17
+6689	1	0
+274	0	1
+1449	0	1
+1312	1	0
+1861	8888	417910
+92	172	6531
+148	0	2
+213	1	1
+30	1	1
+227	1	1
+62	6	0
+276	1	1
+35	1	1
+94	14	14
+325	5	5
+118	1	1
+81	1	1
+234	4	0
+15	1	1
+243	1	1
+39	1	1
+117	1	1
+35	1	1
+83	1	1
+64	5	5
+55	13	13
+61	11	11
+175	1	1
+27	1	1
+134	1	1
+60	1	1
+64	1	1
+87	1	1
+615	1	1
+22	1	1
+201	5	5
+48	1	1
+117	1	1
+23	3	3
+319	6	6
+156	0	1
+25	1	1
+215	13	13
+97	14	14
+113	0	3
+35	1	1
+65	15	15
+480	0	1
+636	1	1
+107	1	1
+753	1	1
+43	1	1
+861	17	16
+470	1	1
+38	1	1
+579	1	1
+25	1	1
+224	1	1
+71	1	1
+266	36	36
+167	88	88
+400	53	53
+131	6	5
+220	22	19
+317	23	23
+109	95	101
+73	0	4726
+208	28	28
+293
+
+chain	1680348	chr1_random	1663265	+	1245440	1263421	1	249250621	+	116101959	116120000	1475
+441	0	14
+728	0	2
+1146	2	0
+1829	6	6
+93	3	2
+2916	0	6
+2013	0	47
+369	1	1
+27	9	0
+37	1	1
+200	1	0
+2285	0	2
+3527	1	1
+24	0	1
+1001	0	1
+1195	1	1
+39	1	1
+85
+
+chain	1335863	chr1_random	1663265	+	231796	246037	4	191154276	-	30408128	30422371	1784
+3391	6	6
+562	7	7
+5976	2	3
+4144	10	11
+143
+
+chain	1170727	chr1_random	1663265	+	577933	590476	1	249250621	+	144898104	144910646	2036
+1896	48	48
+2779	1	0
+7128	45	45
+646
+
+chain	1143882	chr1_random	1663265	+	1330802	1343100	1	249250621	-	133251270	133263558	2093
+1050	1	1
+51	1	1
+237	1	1
+35	1	1
+514	16	12
+76	9	1
+1642	12	12
+53	0	1
+3766	0	1
+40	1	1
+1513	0	1
+195	11	11
+135	26	26
+2627	1	0
+284
+
+chain	988809	chr1_random	1663265	+	564355	574807	1	249250621	-	104390169	104400621	2516
+59	1	2
+5994	1	1
+45	1	1
+3985	3	3
+42	1	0
+320
+
+chain	957971	chr1_random	1663265	+	256162	266426	1	249250621	+	1291904	1302191	2686
+83	0	1
+585	0	1
+1018	0	1
+18	1	1
+59	16	16
+1569	0	1
+69	1	0
+35	0	1
+36	1	1
+176	0	1
+48	0	1
+56	2	3
+41	0	1
+160	17	1
+461	13	21
+174	0	4
+517	7	7
+141	4	4
+89	0	1
+1155	1	0
+370	7	7
+143	1	0
+1019	22	22
+1177	0	1
+607	0	16
+86	0	3
+279
+
+chain	895962	chr1_random	1663265	+	196343	223209	1	249250621	-	247894293	247990621	2587
+108	25	24
+131	0	1
+299	0	1
+137	44	45
+51	0	1
+572	0	1
+406	36	37
+508	2162	63455
+80	5	8
+86	0	1
+61	0	1
+31	1	0
+165	14	15
+78	75	78
+234	0	1
+152	13	15
+849	0	1
+1798	12505	20653
+3495	0	1
+43	0	1
+1944	1	1
+26	1	1
+169	0	1
+365	0	1
+196
+
+chain	884318	chr1_random	1663265	+	4444	145186	1	249250621	+	109546538	109651856	1047
+123	47	1183
+818	1	1
+75	1	0
+22	1	1
+455	18927	20784
+855	1	0
+74	12001	11300
+2581	2	2
+31	0	1
+81	1	0
+24	1	1
+123	1	0
+147	0	1
+45	0	1
+26	0	1
+9	1	0
+12	2330	786
+22	41	53
+127	1706	714
+3729	74524	39329
+68	5	7
+3088	2	2
+15	5	6
+14	0	2
+657	1	1
+37	1	1
+2140	1	0
+3034	1	0
+42	1	1
+446	0	1
+55	2	2
+30	1	1
+391	1	1
+35	1	1
+982	3	0
+123	1	1
+28	0	4
+1503	1	0
+1159	0	3
+1464	0	1
+838	1	1
+47	1	3
+162	1	0
+139	1	1
+10	0	1
+2424	6	6
+448	1	0
+846	5	0
+1509
+
+chain	739113	chr1_random	1663265	+	68329	76740	1	249250621	+	109654512	109662863	6250
+254	1	0
+27	1	1
+746	1	0
+315	19	19
+163	42	2
+51	3	1
+44	1	1
+592	0	1
+216	1	1
+34	1	1
+2323	10	0
+10	236	236
+125	1	0
+806	213	213
+828	6	0
+82	6	6
+1253
+
+chain	688441	chr1_random	1663265	+	605533	614556	1	249250621	+	144612760	144812114	1498
+76	1	1
+70	1	1
+73	4	2
+40	0	2
+159	1	1
+56	2	0
+911	1	1
+63	1	1
+84	9	1
+149	1	1
+21	1	0
+606	1	1
+21	3	3
+132	12	10
+368	1	1
+26	1	1
+50	1	1
+65	1	1
+57	1	1
+44	1	1
+279	0	1
+34	0	4
+7	1	1
+308	0	32
+331	1	1
+84	1	1
+286	1	1
+35	1	1
+59	8	8
+146	1	1
+237	1	1
+52	1	1
+35	2	0
+40	1	1
+53	3	3
+103	1	1
+397	1	1
+59	1	0
+33	1	1
+587	11	11
+219	10	10
+71	5	5
+62	1	1
+38	1	1
+240	1	1
+70	1	1
+85	12	12
+86	413	190724
+207	1	0
+825	186	186
+172
+
+chain	590572	chr1_random	1663265	+	516651	523401	1	249250621	-	104651805	104658532	8996
+157	1	1
+17	1	1
+395	1	1
+65	1	1
+187	0	9
+21	1	1
+62	16	16
+110	2	0
+205	1	0
+43	1	1
+248	1	1
+59	4	2
+725	1	1
+49	1	1
+455	1	1
+106	1	1
+450	1	1
+133	0	2
+383	1	1
+37	1	1
+178	4	4
+70	1	1
+85	2	2
+43	1	1
+56	1	1
+22	24	0
+30	1	1
+64	1	1
+21	1	1
+198	1	1
+67	1	1
+58	1	0
+79	7	6
+74	1	1
+79	1	0
+26	1	1
+202	15	15
+352	2	2
+16	1	1
+51	22	19
+574	0	1
+87	1	1
+46	1	1
+88	1	1
+27	1	1
+120
+
+chain	526301	chr1_random	1663265	+	1264935	1361969	1	249250621	+	116056429	116101915	1232
+69	0	1
+30	1	1
+2663	2	0
+4185	1	0
+229	1	0
+25	1	1
+1104	1	0
+604	4	0
+1264	1	0
+2613	1	1
+21	1	0
+12	1	13
+2785	72844	21309
+397	19	2
+2203	1	1
+31	1	1
+658	1	1
+27	1	1
+923	9	9
+168	1	1
+46	0	2
+2502	43	43
+879	17	17
+644
+
+chain	506365	chr1_random	1663265	+	1399143	1404500	1	249250621	-	133194419	133199775	28136
+3175	1	0
+1447	0	1
+512	1	0
+221
+
+chain	482769	chr1_random	1663265	+	211415	216543	1	249250621	-	247889067	247894197	45886
+70	2	3
+905	2	3
+1091	1	1
+23	1	1
+302	15	14
+393	1	1
+24	1	1
+1961	0	1
+336
+
+chain	474976	chr1_random	1663265	+	1295676	1399043	1	249250621	+	115999419	116093083	1267
+571	10	10
+627	7	6
+46	1	1
+3095	0	1
+960	0	1
+608	11	10
+426	39	35
+2035	1	1
+23	1	1
+1866	17	18
+79	1	1
+1530	63368	32589
+866	110	110
+100	53	53
+1884	40	40
+3775	15606	36683
+2322	14	14
+145	49	49
+296	96	96
+297	0	2
+465	58	58
+262	22	22
+182	0	1
+638	1	0
+764
+
+chain	456897	chr1_random	1663265	+	1317	37745	1	249250621	+	109592282	109609521	6704
+1178	0	1
+16	1	0
+10	0	1
+4	1	1
+245	7763	188
+27	1	1
+1155	1	1
+91	4156	3450
+1810	51	51
+50	9	10
+567	3839	4491
+37	6346	0
+128	0	2
+29	50	48
+45	1519	155
+6	2	0
+9	10	6
+246	1806	0
+18	1	0
+5	2068	31
+2018	2	2
+20	3	3
+833	1	0
+101	1	0
+149
+
+chain	426748	chr1_random	1663265	+	63710	68210	1	249250621	-	139547929	139552428	99412
+1542	1	0
+2957
+
+chain	353264	chr1_random	1663265	+	462791	467071	1	249250621	+	144608404	144612698	156569
+71	50	50
+33	29	29
+226	10	10
+526	66	67
+55	50	50
+414	5	5
+57	46	58
+57	12	12
+254	1	1
+25	1	1
+52	13	13
+638	16	16
+579	1	1
+60	1	1
+178	1	1
+79	1	0
+35	0	3
+111	1	1
+43	1	1
+264	1	0
+119	1	1
+15	0	1
+76	1	0
+5
+
+chain	327229	chr1_random	1663265	+	1409275	1412904	1	249250621	+	115977641	115981270	200837
+2640	156	155
+473	0	1
+360
+
+chain	312923	chr1_random	1663265	+	1319916	1393318	1	249250621	+	115926067	115986980	1722
+1418	1	0
+1389	1	0
+1620	0	1
+374	1	0
+1361	0	1
+1994	1	0
+827	0	6
+1784	56909	44431
+253	1	0
+12	2	0
+8	24	14
+5344	2	0
+76
+
+chain	244562	chr1_random	1663265	+	478502	503782	1	249250621	-	100680024	100953393	1328
+106	13	13
+478	55	55
+310	1	1
+23	1	1
+376	1	1
+61	1	1
+1100	10	10
+810	5	0
+53	1	1
+119	1	1
+44	1	0
+94	100	32051
+60	5	5
+744	1	1
+87	1	1
+44	2	0
+53	11	5
+584	2	2
+30	0	17
+73	1	1
+49	1	1
+456	8	8
+796	19	19
+166	1	1
+42	1	1
+105	1	1
+38	1	1
+55	1	1
+80	1	1
+293	2	2
+19	1	1
+550	5637	9366
+68	24	22
+103	1	1
+35	0	1
+102	1	1
+39	6	0
+388	9	9
+21	1	1
+338	27	27
+500	4	0
+117	5	5
+271	1	1
+38	1	1
+273	3	3
+16	3	3
+80	1	1
+63	1	1
+130	1	1
+18	1	1
+204	1	1
+45	1	1
+141	1	1
+112	1	1
+75	1	0
+75	4	4
+83	2	0
+854	5	5
+104	0	4
+12	1	1
+351	1	1
+40	1	1
+102	4779	217183
+40	502	502
+31	0	12
+58	311	311
+110	52	52
+78	1	1
+46	535	535
+45
+
+chain	239113	chr1_random	1663265	+	455713	471283	1	249250621	+	144877306	144889304	5703
+73	1	0
+944	0	1
+2741	1	1
+77	1770	1206
+12	1449	338
+10	71	1301
+14	10	145
+26	4281	1018
+2672	0	1
+1418
+
+chain	228041	chr1_random	1663265	+	450807	453388	GL000192.1	547496	+	525635	528523	474030
+521	25	26
+256	4	316
+195	1	0
+183	4	0
+249	48	48
+915	19	18
+161
+
+chain	219405	chr1_random	1663265	+	8071	23476	1	249250621	+	109602419	109665881	23204
+1669	2217	48069
+1950	5	1
+213	6609	8813
+681	1	0
+580	0	1
+296	37	38
+248	0	4
+301	31	31
+143	38	38
+386
+
+chain	219231	chr1_random	1663265	+	32127	34517	1	249250621	-	139682423	139684814	491274
+85	27	27
+14	0	1
+204	5	5
+63	24	24
+1968
+
+chain	210320	chr1_random	1663265	+	459650	474308	GL000192.1	547496	+	522489	531711	22108
+267	0	10
+1175	5	1
+48	0	2
+16	3	3
+119	0	12
+37	12	12
+1340	8711	3256
+34	0	2
+58	1	0
+38	1	0
+351	5	5
+486	17	15
+158	81	81
+76	1	1
+36	1	1
+69	12	13
+1500
+
+chain	207966	chr1_random	1663265	+	29704	55292	1	249250621	+	109529352	109557857	7568
+742	273	273
+560	0	1
+232	17541	20458
+729	2	2
+97	3	3
+89	1	1
+68	0	1
+28	1	1
+2575	2	0
+59	1	1
+2585
+
+chain	202325	chr1_random	1663265	+	27243	45056	1	249250621	-	139669260	139678536	8944
+1432	157	157
+50	45	45
+677	2608	49
+27	8791	867
+266	9	9
+169	1	1
+62	1	1
+67	7	5
+28	1	1
+1619	22	22
+41	127	127
+21	1	1
+40	2	1
+32	1	1
+362	0	1949
+1147
+
+chain	199687	chr1_random	1663265	+	18553	20627	1	249250621	+	109595202	109597276	600797
+2074
+
+chain	171508	chr1_random	1663265	+	447628	491985	1	249250621	+	148535207	148566609	6481
+121	14	14
+517	0	4
+507	1	0
+74	1	1
+41	0	1
+61	4541	11291
+1073	1	0
+718	70	44
+66	31371	11607
+690	1	1
+115	1	1
+61	1	1
+70	1	1
+57	0	4
+54	1	1
+41	2	6
+28	5	77
+73	1	1
+34	5	5
+887	1	0
+427	1	1
+7	0	5
+40	1	1
+59	1	1
+47	1	1
+121	9	9
+57	2	0
+362	1	1
+48	4	4
+429	1	1
+28	1	1
+160	1	1
+92	5	0
+15	0	5
+15	1	1
+139	5	5
+37	1	1
+87	1	1
+40	1	1
+253	1	1
+35	1	1
+197	1	1
+69	1	1
+114	1	1
+79	1	1
+51
+
+chain	170629	chr1_random	1663265	+	474420	479154	1	249250621	-	104365477	104643040	2652
+3982	697	273526
+55
+
+chain	143194	chr1_random	1663265	+	449166	450695	1	249250621	-	104373413	104374943	899312
+167	0	1
+362	11	11
+989
+
+chain	141808	chr1_random	1663265	+	195186	230464	1	249250621	+	1361949	1390000	8100
+66	0	1
+865	27548	20313
+75	1	1
+163	2	2
+2267	0	2
+1549	0	2
+37	1	1
+597	1	1
+28	1	1
+269	14	19
+59	1	1
+20	1	1
+734	2	0
+977
+
+chain	137395	chr1_random	1663265	+	446016	447466	1	249250621	+	144922370	144923820	937713
+1450
+
+chain	120082	chr1_random	1663265	+	1413004	1414278	1	249250621	+	115908963	115910237	1071399
+1274
+
+chain	110577	chr1_random	1663265	+	0	1193	5	180915260	+	33390295	33391489	1161255
+153	0	1
+942	4	4
+94
+
+chain	101176	chr1_random	1663265	+	442945	444014	1	249250621	-	104338746	104339815	1265508
+1069
+
+chain	61431	chr1_random	1663265	+	9891	10535	1	249250621	+	109697165	109697809	2020878
+644
+
+chain	48091	chr1_random	1663265	+	497444	501649	1	249250621	+	144842054	144846259	8551
+4205
+
+chain	31572	chr1_random	1663265	+	576223	577747	4	191154276	+	100714665	100716180	4375428
+114	20	20
+105	460	462
+56	375	378
+65	263	249
+66
+
+chain	28915	chr1_random	1663265	+	230464	231387	1	249250621	+	1420670	1421247	4712368
+191	574	228
+67	38	38
+53
+
+chain	27385	chr1_random	1663265	+	205390	205833	1	249250621	-	247799065	247799507	5896168
+141	86	86
+106	47	46
+63
+
+chain	25670	chr1_random	1663265	+	87811	88395	7	159138663	-	51241913	51242744	3648322
+121	405	652
+58
+
+chain	21035	chr1_random	1663265	+	376636	377171	1	249250621	-	247932544	247932844	3872256
+107	118	0
+61	93	15
+49	39	0
+68
+
+chain	18694	chr1_random	1663265	+	540390	626404	1	249250621	+	148529505	148589817	1111
+44	254	254
+43	76	73
+54	196	196
+37	240	6477
+31	4	4
+4	2528	2531
+8	1	1
+42	1	1
+60	70185	38258
+94	10137	10136
+31	1	1
+3	167	167
+88	400	400
+52	829	828
+33	10	0
+52	281	281
+28
+
+chain	18305	chr1_random	1663265	+	612752	613165	1	249250621	+	146400208	146400621	434456
+18	31	31
+215	97	97
+52
+
+chain	18205	chr1_random	1663265	+	210123	210768	1	249250621	+	1400633	1401273	11939617
+55	410	403
+82	10	12
+88
+
+chain	16211	chr1_random	1663265	+	84691	84862	5	180915260	+	68593902	68594073	10696361
+171
+
+chain	14543	chr1_random	1663265	+	375983	376437	1	249250621	-	247932585	247932921	12601411
+13	231	153
+56	101	61
+53
+
+chain	11766	chr1_random	1663265	+	209234	209374	6	171115067	+	48765751	48765891	19406706
+84	4	4
+52
+
+chain	10899	chr1_random	1663265	+	1264583	1264729	4	191154276	-	96228610	96228756	20935897
+69	19	19
+58
+
+chain	9779	chr1_random	1663265	+	575439	575892	5	180915260	-	127861600	127862049	19918678
+60	389	385
+4
+
+chain	9449	chr1_random	1663265	+	206282	206576	1	249250621	-	247814999	247815293	24134146
+64	179	179
+51
+
+chain	9080	chr1_random	1663265	+	376922	377270	1	249250621	-	247932789	247932982	12922008
+42	39	0
+12	156	79
+8	39	0
+52
+
+chain	7488	chr1_random	1663265	+	375996	376227	1	249250621	-	247932827	247932944	24096271
+39	178	64
+14
+
+chain	7272	chr1_random	1663265	+	492183	493450	GL000192.1	547496	+	517200	518462	5534
+104	1136	1131
+27
+
+chain	7258	chr1_random	1663265	+	576783	577499	14	107349540	-	76512188	76512903	4928952
+56	262	262
+101	216	215
+81
+
+chain	7167	chr1_random	1663265	+	376446	376521	1	249250621	-	247932507	247932582	27908410
+75
+
+chain	6857	chr1_random	1663265	+	87342	87413	4	191154276	-	48731804	48731875	28524152
+71
+
+chain	6426	chr1_random	1663265	+	508964	509092	1	249250621	+	144828390	144828518	146082
+13	51	51
+64
+
+chain	6204	chr1_random	1663265	+	211009	211075	1	249250621	+	1467491	1467557	30075428
+66
+
+chain	6008	chr1_random	1663265	+	376783	376999	1	249250621	-	247932727	247932982	14593768
+49	132	171
+35
+
+chain	5855	chr1_random	1663265	+	576112	576191	20	63025520	+	560198	560277	14627950
+79
+
+chain	5539	chr1_random	1663265	+	247082	247140	16	90354753	-	36623787	36623845	31913042
+58
+
+chain	5517	chr1_random	1663265	+	575499	575571	1	249250621	-	135388947	135389019	22575370
+19	14	14
+39
+
+chain	5153	chr1_random	1663265	+	463736	463802	1	249250621	-	100897669	100897735	496173
+66
+
+chain	4331	chr1_random	1663265	+	576997	577043	4	191154276	+	125192159	125192205	31588172
+46
+
+chain	4269	chr1_random	1663265	+	508977	509028	1	249250621	-	101245694	101245744	11082093
+11	1	0
+24	1	1
+14
+
+chain	3392	chr1_random	1663265	+	1264741	1264777	1	249250621	+	103601716	103601752	22855599
+36
+
+chain	2584	chr1_random	1663265	+	472532	472613	1	249250621	-	104701386	104701467	60543
+81
+
+chain	2530	chr1_random	1663265	+	576576	576677	2	243199373	+	18874674	18874775	4960893
+101
+
+chain	2443	chr1_random	1663265	+	508878	508906	1	249250621	+	145358788	145358816	8460
+28
+
+chain	2298	chr1_random	1663265	+	376035	376059	1	249250621	-	247932520	247932544	25650669
+24
+
+chain	2200	chr1_random	1663265	+	377179	377218	1	249250621	-	247932814	247932853	18046603
+39
+
+chain	2078	chr1_random	1663265	+	576191	576213	2	243199373	-	87184513	87184535	19810119
+22
+
+chain	1902	chr1_random	1663265	+	462945	462974	1	249250621	+	146388727	146388756	1440299
+29
+
+chain	1597	chr1_random	1663265	+	87932	87955	1	249250621	+	203810737	203810760	8954286
+23
+
+chain	1582	chr1_random	1663265	+	576728	576783	12	133851895	+	80469819	80469874	8882774
+55
+
+chain	1575	chr1_random	1663265	+	377270	377295	1	249250621	-	247932789	247932814	25950613
+25
+
+chain	1557	chr1_random	1663265	+	376743	376767	1	249250621	-	247932958	247932982	25686497
+24
+
+chain	1423	chr1_random	1663265	+	577528	577578	3	198022430	+	24122600	24122650	5633229
+50
+
+chain	1401	chr1_random	1663265	+	208964	209027	19	59128983	+	53692979	53693042	24768107
+63
+
+chain	1269	chr1_random	1663265	+	577058	577101	X	155270560	-	54470903	54470946	5438939
+43
+
+chain	1137	chr1_random	1663265	+	88481	88531	X	155270560	-	107394638	107394688	10193603
+50
+
+chain	1096	chr1_random	1663265	+	88429	88481	1	249250621	-	213837318	213837370	14790649
+52
+
+chain	963	chr1_random	1663265	+	575892	575970	1	249250621	-	198864223	198864301	11419759
+78
+
+chain	917	chr1_random	1663265	+	455298	455327	GL000192.1	547496	-	58673	58702	411262
+29
+
+chain	870	chr1_random	1663265	+	577218	577269	6	171115067	-	89553434	89553485	24911812
+51
+
+chain	794	chr1_random	1663265	+	88312	88337	4	191154276	+	171087862	171087887	6635553
+25
+
+chain	649	chr1_random	1663265	+	576545	576576	15	102531392	-	5321440	5321471	7251364
+31
+
+chain	622	chr1_random	1663265	+	576462	576495	11	135006516	+	114505284	114505317	6564387
+33
+
+chain	546	chr1_random	1663265	+	88531	88556	6	171115067	+	144792007	144792032	10415340
+25
+
+chain	398	chr1_random	1663265	+	575763	575814	14	107349540	+	34662629	34662680	24063646
+51
+
+chain	22466167312	chr2	242951149	+	0	242751149	2	243199373	+	10000	243102476	1
+1201236	1	0
+2057	1	1
+26	1	1
+4043	0	22
+82	101	7
+33	0	74
+36	13	1
+67	0	48
+152	0	418
+50	2	0
+6	6	0
+76	74	0
+20	6	0
+22	118	0
+374	0	2446
+836	0	2310
+21	0	2444
+21507	1	1
+50	0	4
+2041	4	0
+9052	0	2
+81	8	0
+10	42	0
+1078	1	0
+4122	0	1
+1608	1	28
+4029	9	0
+967	1000	4547
+414	0	27
+2237132	1	0
+2458	17	17
+3915	47	47
+633	0	4
+3531	14	14
+3954	50000	51129
+1426129	100025	160449
+11087286	3	0
+773	50000	103977
+1576	1	0
+240	1	0
+318	0	2
+258	16	0
+2848	10	10
+1404	1	1
+27	1	1
+703	0	13
+375	1	0
+4783388	25000	35000
+848	2	0
+1225	2	0
+391	0	1
+3445	24	24
+184	1	1
+28	1	1
+49	4	0
+4514	9	0
+9628	9	1
+1483	7	7
+1990	1	0
+1949	0	1
+2716230	0	1
+46732767	9	5
+9477928	3	0
+7520813	0	72396
+1900436	150000	294073
+17672	0	1
+5792	0	1
+9019	266	0
+2942	1	0
+9388	0	2
+37826	0	4
+23440	4	0
+290929	1000000	1273578
+731068	3000000	3000000
+2558421	1	0
+1196	0	10
+686	1	0
+26	3	0
+15	1	1
+2309	1	0
+1332	23	22
+344	1	0
+1645	4	4
+6564	0	1
+6329	0	1
+769	1	0
+873	0	7
+1299	1	0
+8250	15	15
+4291	12548	10626
+1054	0	103
+84	218	0
+5897	1	1
+33	1	1
+9905	37	51
+1645	113	113
+1597	4	4
+61	1	1
+866	0	13
+2830	0	3
+2819	2	0
+156	436	88
+100	54	0
+4753	8	0
+4903	6	6
+3847	2	0
+108126	145	0
+3542	0	1
+10276	1	0
+402	1	1
+47	1	1
+63	0	2
+583	1	1
+34	1	1
+8975	46	0
+378	1	1
+70	1	1
+2476	102	0
+1754	1	0
+8426	1	0
+11986570	142000	151150
+14207	1	1
+49	1	1
+1784	12	0
+406	0	1
+1874	1	1
+33	1	1
+4795	0	2
+3686	1	1
+15	1	1
+164	0	2
+7287	5	5
+702023	150000	72796
+69	0	1
+1598	1	0
+1340	1	0
+1030	4	0
+1166	10	10
+629	27	27
+5750	1	1
+34	1	1
+3283	4	2
+496	21	1
+25	1	9
+41	1	1
+329	4	4
+9955	41	41
+10953	1	2
+1417	44	0
+911	0	17
+18270	0	1
+178429	281526	0
+34455	406	0
+58863	2	1
+1843	2	0
+14994	1	0
+12992	0	2
+2571146	0	1
+35688061	100000	108224
+29671719	0	1
+39665349	0	1
+14876089	20000	64197
+401	3	0
+1831	1	1
+61	1	1
+654	1	11
+138	28	0
+105	1	1
+25	4	0
+73	9	9
+3247	0	2
+1355	0	1
+816	21	25
+526	1	1
+60	1	1
+773	0	1
+1494	0	1
+448	44	44
+1191	0	1
+21	1	1
+596	0	1
+1582	0	1
+425	3	0
+1141	8	0
+136	744	80
+18	1	0
+4	1	0
+8	4	2
+32	1	0
+71	0	1
+385747	1	1
+110	1	1
+51	7	7
+54	15205	15205
+54	7	7
+51	1	1
+110	1	1
+5198249	1	0
+108	0	40
+65	0	80
+100	2	82
+442	1	1
+35	1	1
+119	129	9
+33	40	0
+42	1	1
+86	40	0
+1330	1	0
+1194	2	0
+11	1	1
+1773	5	0
+1623	1	1
+25	1	1
+2422	1	1
+20	1	0
+2315	1	0
+31	1	1
+1508	3	0
+50	4	0
+970	6	6
+7234	0	4
+1228	0	1
+1233	1	8
+744	16	16
+3447	1	1
+41	1	1
+3297	2	0
+1714	0	2
+2299	0	2
+2143	1	1
+18	1	1
+917	0	1
+1082	1	1
+49	1	1
+9098	4	0
+5529	1	0
+3266	8	0
+894	0	6
+3536	0	2
+4179	13	18
+1785	1	0
+1675	6	0
+1216	33000	32348
+287	109	573
+12548	30000	30000
+952154	25000	41011
+1914	0	1
+225	1	1
+57	1	1
+2910	1	0
+471	0	1
+1956	1	1
+43	1	1
+1000	92	0
+2854	0	3
+1837	0	306
+1007	0	30
+206	35	32
+217	17	17
+1525	0	8
+413	1	1
+32	2	2
+1573	12	12
+2258676
+
+chain	1437141	chr2	242951149	+	234136066	234151271	2	243199373	-	8712841	8728046	1459
+15205
+
+chain	1229376	chr2	242951149	+	110524471	111016063	2	243199373	-	132402743	134718956	53
+41	12371	12350
+33	0	23
+11	197610	197512
+5295	5	5
+190	69	19
+2195	1	0
+285	34	34
+1682	1	0
+182	11	6
+291	0	1
+1506	15	16
+146	5	5
+2050	51	51
+186	8	7
+68	7	6
+41	1	0
+306	0	1
+1545	1	0
+1334	25	24
+543	0	2
+224	17	21
+615	1	0
+208	2	0
+158	27	21
+3320	0	1
+576	0	2
+4562	0	6
+1023	0	1
+977	0	1
+3904	1	0
+827	415	28
+1508	14	13
+9571	36	36
+1393	1	1
+42	1	1
+2205	0	2
+5258	36	0
+42	2	0
+4437	2	0
+3357	1	0
+6289	0	9
+1996	1	0
+3228	0	1
+202	0	1
+2743	7	0
+24	0	5
+549	3	1
+942	0	6
+1815	8	0
+874	0	3
+4737	0	2
+852	14	18
+518	14	14
+4377	1	1
+49	1	1
+3270	1	0
+753	0	4
+240	1	0
+2391	0	1
+4745	4	0
+5752	0	2
+880	0	1
+397	1	0
+1407	0	3
+120	1	1
+89	1	1
+7011	3	0
+188	8	8
+834	5	0
+94	18	18
+3711	150112	1975291
+345	52	52
+100	8	8
+52	6	6
+650	6	6
+273	91	95
+88	90	90
+331	116	116
+66	35	35
+145	13	15
+95	6	6
+301	43	47
+444	12	12
+645	116	119
+215	31	31
+748	58	57
+212	71	71
+420	38	38
+190	4	4
+51	32	32
+65	32	32
+182	69	69
+161	17	17
+74	36	36
+170	25	25
+124	19	15
+230
+
+chain	33206	chr2	242951149	+	111008548	111015495	2	243199373	+	113147044	113153995	310
+112	345	345
+52	1095	1095
+15	0	4
+76	88	88
+90	331	331
+116	66	66
+35	560	560
+43	1101	1101
+116	215	215
+31	748	748
+58	212	212
+71	420	420
+38	245	245
+32	65	65
+32	182	182
+69	252	252
+36
+
+chain	15095	chr2	242951149	+	97284299	97473552	2	243199373	-	145080546	145267103	122
+48	13638	11732
+218	15837	15837
+37	1645	1645
+113	8336	8336
+436	100	100
+54	121645	121635
+3	25	0
+101	26915	26159
+9	0	1
+93
+
+chain	10366	chr2	242951149	+	110742577	110753868	2	243199373	+	113162562	113173850	1257
+34	5889	5884
+51	5290	5292
+27
+
+chain	3994	chr2	242951149	+	111050518	111050561	2	243199373	-	132647167	132647210	483
+43
+
+chain	3626	chr2	242951149	+	1208025	1208063	2	243199373	+	1217618	1217656	30090800
+38
+
+chain	3098	chr2	242951149	+	110780566	110780602	2	243199373	+	100698198	100698234	394442
+36
+
+chain	2548	chr2	242951149	+	89594034	89594300	2	243199373	-	153635204	153635700	103
+90	9	107
+22	9	0
+32	3	0
+5	0	125
+21	15	30
+5	1	0
+25	0	5
+29
+
+chain	2507	chr2	242951149	+	1207989	1208025	2	243199373	+	1217656	1217692	7254147
+36
+
+chain	2306	chr2	242951149	+	97446409	97446434	2	243199373	+	98080299	98080324	1844703
+25
+
+chain	5644665978	chr20	62435964	+	8000	62435964	20	63025520	+	60000	62965520	20
+26259569	1765661	3100000
+234339	1000000	150000
+4004088	0	1
+6459	0	244
+37810	0	2
+1044573	20000	50000
+9411883	2	8
+362	0	1
+11607353	0	1
+1301304	1	0
+31033	0	9
+1154	0	2
+1088	1	1
+29	1	1
+2509	0	2
+407	1	0
+40	1	1
+3787164	27050	50000
+71932	110000	50000
+694117	0	1
+1008033
+
+chain	3228730713	chr21	46944323	+	9719767	46944323	21	48129895	+	10697896	48119895	23
+490233	3050000	3150000
+19828060	0	1
+8789369	1199	50000
+243783	1500	1500
+1381822	1359	50000
+3437231
+
+chain	42537850	chr21_random	1679693	+	281005	1255172	21	48129895	+	9411193	10647896	88
+184355	50000	489372
+131056	458754	281918
+150002
+
+chain	21600281	chr21_random	1679693	+	876305	1679693	21	48129895	-	37585054	38304458	99
+178865	280890	346005
+315	2	2
+38	1	1
+261	1	1
+24	1	1
+157	0	325
+16	1	1
+85	1	1
+66	1	1
+330	11	11
+235	1	1
+51	1	1
+405	1	1
+26	1	1
+130	5	5
+80	1	1
+91	1	1
+20	1	1
+244	0	1
+478	1	1
+5	1	0
+13	0	1
+49	1	1
+197	10	10
+158	1	1
+57	0	1
+829	1	1
+60	1	1
+51	0	1
+584	1	0
+21	2	0
+151	20	20
+316	1	1
+16	1	1
+100	7	7
+102	1	1
+49	1	1
+125	1	0
+102	13	13
+153	20	20
+199	1	0
+35	1	1
+367	1	1
+51	1	1
+344	1	1
+101	1	1
+243	1	1
+27	1	1
+338	0	4
+166	15	15
+73	1	1
+44	1	1
+282	4	4
+67	1	1
+54	1	1
+216	1	1
+48	1	1
+76	1	1
+70	1	1
+392	1	1
+44	1	1
+65	8	9
+362	0	4
+34	1	1
+68	1	1
+57	1	0
+120	1	1
+374	1	1
+21	1	1
+121	1	1
+34	1	1
+80	1	0
+64	2	0
+162	8	8
+184	1	1
+34	1	1
+658	2	2
+52	0	4
+297	1	0
+136	1	1
+20	1	1
+905	0	1
+250	7	8
+138	0	3
+104	1	0
+42	1	1
+539	0	1
+43	4	0
+633	0	20
+353	17	17
+969	4	0
+39	3	3
+210	3	1
+188	7	7
+459	2	2
+25	1	1
+207	1	1
+55	1	1
+375	1	1
+66	1	1
+599	0	2
+395	1	1
+33	1	1
+73	1	1
+35	2	0
+275	9999	10000
+353	1	1
+26	1	1
+423	1	1
+32	1	1
+86	7	7
+197	1	1
+44	1	1
+96	1	1
+77	7	0
+247	0	2
+77	1	1
+425	13	1
+32	1	1
+65	1	1
+217	3	2
+115	1	1
+33	1	1
+268	1	0
+959	1	1
+63	1	1
+93	5	5
+185	1	1
+31	1	1
+944	12	12
+413	1	1
+92	1	1
+276	1	1
+35	1	1
+500	1	1
+31	149436	9
+158069
+
+chain	14432948	chr21_random	1679693	+	78709	231005	21	48129895	+	9882623	10034920	205
+77296	0	1
+75000
+
+chain	7807601	chr21_random	1679693	+	1362161	1471624	1	249250621	-	105758025	105867745	293
+77	11427	11419
+174	5	5
+857	64	64
+2170	0	2
+621	1	1
+26	1	1
+4365	0	1
+155	0	1
+452	0	4
+941	0	4
+403	1	1
+45	1	1
+534	86	86
+2198	0	1
+303	2	0
+5470	6	6
+845	1	1
+45	1	1
+221	6	0
+321	1	1
+44	1	1
+354	1	0
+374	131	130
+577	6	5
+263	17	16
+207	0	2
+1746	14	14
+3223	1	1
+46	4	4
+1479	1	1
+46	1	1
+383	0	3
+44	1	1
+2724	67	67
+47	145	145
+350	116	116
+138	0	1
+1	65	65
+796	17	17
+645	1	0
+24	1	1
+1318	1	0
+687	1	1
+41	1	1
+2292	1	1
+37	1	1
+589	1	1
+37	1	0
+670	13	13
+357	4	0
+2667	3	0
+1941	1	1
+31	1	1
+1538	54	54
+64	166	166
+120	226	226
+46	14	0
+14	155	155
+92	54	54
+26	55	55
+98	131	131
+36	1	1
+76	391	391
+44	294	294
+37	813	813
+35	219	219
+898	1	1
+19	1	1
+213	12	12
+1926	1	1
+21	1	1
+4561	1	1
+28	1	1
+8361	1	1
+43	1	1
+429	211	492
+3095	0	1
+3873	1	1
+43	5	5
+3785	171	171
+65	122	122
+70	116	116
+29	459	459
+36	352	352
+39	93	93
+39	190	190
+41	1783	1784
+35	509	509
+27	394	394
+57	834	834
+58	10	10
+17	758	760
+41	0	4
+82	194	194
+60	543	543
+31	58	58
+46	607	607
+34	98	98
+31	1	1
+38	563	562
+135	1980	1976
+48	370	370
+42	515	515
+49	456	456
+3137	0	1
+2483	1	0
+357	1	1
+49	1	1
+1181	1	0
+885	1	0
+86
+
+chain	3630496	chr21_random	1679693	+	696416	1463441	21	48129895	+	9645548	10215976	235
+129889	481231	310631
+225	46	51
+383	6	6
+73	18	18
+200	18	39
+236	63	68
+123	340	365
+57	300	259
+51	138	138
+71	55	55
+60	152	152
+51	100	103
+61	358	357
+85	1906	236
+88	157	153
+56	39	39
+73	20146	20047
+67	1	0
+57	154	154
+59	940	953
+61	205	205
+60	46	46
+122	149	149
+53	64	56
+210	16	16
+209	1	0
+214	29	29
+71	69616	76139
+67	47	47
+145	350	354
+116	139	135
+65	13718	10425
+54	64	64
+166	120	120
+225	75	75
+74	14	13
+67	92	92
+54	26	26
+55	98	98
+127	117	117
+173	16	15
+202	44	44
+198	21	17
+75	37	37
+442	18	18
+353	35	35
+219	27532	0
+105	0	3
+66	65	65
+122	70	70
+116	29	29
+459	36	36
+278	17	17
+57	39	40
+93	39	39
+190	41	41
+285	16	20
+859	22	37
+176	4	4
+183	32	32
+206	35	36
+509	27	27
+394	57	56
+116	5	5
+596	1	0
+116	85	85
+54	0	1
+119	0	2
+585	124	127
+74	10	11
+109	60	60
+82	22	22
+439	31	31
+58	46	46
+106	21	22
+186	15	14
+279	34	34
+98	70	67
+166	1	0
+396	135	135
+1551	12	12
+90	0	3
+69	4	4
+48	3	0
+203	48	48
+370	42	42
+139	14	53
+362	49	49
+456
+
+chain	2630212	chr21_random	1679693	+	936	28709	21	48129895	+	44682664	44710462	1048
+3985	6	7
+8941	0	30
+3327	1	1
+74	1	1
+859	22	22
+89	70	70
+489	14	3
+11	2	1
+10	10	0
+10	0	1
+31	1	27
+556	3	0
+128	0	1
+358	1	1
+45	1	1
+1712	8	0
+6545	32	31
+431
+
+chain	517534	chr21_random	1679693	+	1332563	1373665	GL000194.1	191469	-	21469	62943	261
+130	2	2
+53	1	1
+139	1	1
+60	1	1
+321	125	125
+72	1	1
+81	59	59
+248	22	23
+250	13	13
+407	61	61
+205	60	60
+46	122	122
+149	53	53
+14	0	8
+50	650	650
+29	19697	20073
+100	1	4
+106	2	2
+158	1	1
+89	1	1
+10	1	1
+65	1	1
+48	1	1
+156	1	1
+61	1	1
+156	1	1
+81	1	1
+522	16	16
+377	22	22
+358	1	1
+17	1	1
+141	1	0
+29	0	1
+16	1	1
+105	1	1
+49	2	1
+63	1	1
+32	1	0
+7	1	1
+349	1	2
+102	1	1
+146	1	0
+93	3	0
+149	1	1
+86	1	1
+220	1	1
+111	1	1
+195	19	19
+108	1	1
+79	6	1
+98	0	1
+29	2	2
+98	1	1
+125	1	1
+196	1	1
+52	1	1
+767	1	1
+68	3	3
+70	1	1
+66	1	1
+331	1	1
+22	1	1
+60	77	77
+437	1	1
+61	1	1
+134	1	1
+48	4	2
+26	0	2
+79	1	1
+16	1	1
+77	1	1
+24	1	1
+176	1	1
+33	1	1
+61	0	4
+141	1	1
+17	1	1
+232	1	1
+42	1	1
+439	2	1
+31	1	1
+55	1	0
+181	1	1
+77	4	4
+145	4	5
+22	1	1
+159	1	6
+53	1	1
+63	1	1
+67	6	6
+71	1	1
+25	1	1
+103	6	6
+303	6513	6492
+211	1	1
+87	1	1
+170	2	2
+36	0	6
+361	1	1
+58	1	1
+292	10	10
+201	1	1
+35
+
+chain	353583	chr21_random	1679693	+	1323386	1332563	GL000218.1	161147	-	0	9198	304
+693	1	1
+28	4	0
+425	51	51
+874	2	4
+421	1	1
+23	1	1
+299	2	1
+20	3	3
+88	1	1
+35	1	1
+283	4	4
+42	4	4
+719	14	14
+181	1	1
+41	1	1
+1010	1	1
+59	1	1
+478	1	1
+45	1	0
+78	1	1
+315	1	1
+22	1	1
+342	1	1
+27	1	1
+716	0	25
+83	1	1
+44	1	1
+218	6	6
+142	1	1
+178	1	1
+220	1	1
+35	1	1
+55	1	1
+44	1	1
+143	1	1
+80	1	1
+85	1	1
+46	1	1
+169	1	1
+56	1	1
+94	1	1
+51	1	1
+48
+
+chain	153763	chr21_random	1679693	+	1307498	1317523	1	249250621	+	142541121	142549427	248494
+38	225	225
+46	934	934
+63	240	230
+50	653	627
+57	559	562
+4	186	183
+51	101	101
+16	235	235
+70	1848	174
+58	193	194
+3	255	257
+97	40	40
+164	35	35
+167	27	27
+82	213	218
+106	172	171
+55	274	274
+125	214	209
+158	123	124
+94	169	169
+69	430	425
+66	871	864
+95	213	213
+81
+
+chain	88175	chr21_random	1679693	+	0	28278	GL000210.1	27682	-	0	27251	1050
+107	675	0
+154	27310	26958
+32
+
+chain	46308	chr21_random	1679693	+	1305249	1307368	21	48129895	-	38147885	38150014	728191
+46	171	171
+69	165	166
+32	292	292
+34	184	184
+26	73	73
+23	117	117
+57	54	54
+7	16	25
+68	78	78
+23	242	242
+53	230	230
+59
+
+chain	40072	chr21_random	1679693	+	1311066	1311528	3	198022430	+	38430454	38430916	3283349
+95	1	1
+47	1	1
+177	1	1
+41	1	1
+98
+
+chain	25551	chr21_random	1679693	+	1316263	1317134	21	48129895	+	10022171	10023044	3443865
+97	94	94
+87	148	147
+94	340	343
+11
+
+chain	20886	chr21_random	1679693	+	1305172	1307309	Y	59373566	-	45989384	45991522	2022
+77	46	46
+64	50	50
+57	69	70
+165	32	32
+86	11	11
+195	34	34
+184	122	122
+117	57	57
+54	91	91
+50	51	51
+242	61	61
+68	9	9
+145
+
+chain	10360	chr21_random	1679693	+	1384481	1394861	21	48129895	-	38158677	38169079	831
+56	10224	10246
+100
+
+chain	9106	chr21_random	1679693	+	1316541	1317639	2	243199373	+	56015784	56016880	4408555
+45	37	37
+66	97	95
+66	672	672
+115
+
+chain	7814	chr21_random	1679693	+	1312477	1312593	8	146364022	+	34952530	34952621	21041862
+26	37	12
+53
+
+chain	6987	chr21_random	1679693	+	1305359	1306761	1	249250621	-	105769657	105771059	738748
+38	5	5
+7	1324	1324
+28
+
+chain	3478	chr21_random	1679693	+	1309705	1309742	X	155270560	-	92499801	92499838	30075241
+37
+
+chain	2939	chr21_random	1679693	+	1312274	1312311	1	249250621	-	217601682	217601719	16037052
+37
+
+chain	2906	chr21_random	1679693	+	1394861	1394892	GL000247.1	36422	-	2105	2136	848
+31
+
+chain	2805	chr21_random	1679693	+	1309675	1309705	4	191154276	-	16268024	16268054	28769751
+30
+
+chain	2788	chr21_random	1679693	+	1374701	1374765	GL000194.1	191469	-	63980	64044	1175
+9	36	36
+19
+
+chain	2571	chr21_random	1679693	+	1317411	1317442	20	63025520	-	39738360	39738391	24462467
+31
+
+chain	2324	chr21_random	1679693	+	1311588	1311646	2	243199373	+	3637936	3637994	8156424
+58
+
+chain	1980	chr21_random	1679693	+	1440240	1440313	1	249250621	+	142677559	142677632	922
+73
+
+chain	1679	chr21_random	1679693	+	1316387	1316422	13	115169878	+	41439086	41439121	11997585
+35
+
+chain	1437	chr21_random	1679693	+	1316422	1316454	3	198022430	+	119282439	119282471	8460363
+32
+
+chain	1151	chr21_random	1679693	+	1312216	1312274	13	115169878	+	46060123	46060181	10002138
+58
+
+chain	1007	chr21_random	1679693	+	1312144	1312195	17	81195210	+	33522637	33522688	8813060
+51
+
+chain	810	chr21_random	1679693	+	1306268	1306301	4	191154276	-	63157613	63157646	21715000
+33
+
+chain	762	chr21_random	1679693	+	1312422	1312477	7	159138663	+	153013126	153013181	10840208
+55
+
+chain	732	chr21_random	1679693	+	1312000	1312066	7	159138663	-	102920653	102920719	25474729
+66
+
+chain	561	chr21_random	1679693	+	18264	18311	21	48129895	+	44700101	44700148	25859698
+47
+
+chain	3320960322	chr22	49691432	+	14430000	49591432	22	51304566	+	16050000	51244566	22
+647850	150000	150000
+3661581	50000	100000
+15278435	0	18
+293	0	36
+1410	1	1
+46	1	1
+6626947	2	4
+1759	1	1
+43	1	1
+1367363	12000	10615
+7856	4	0
+809336	0	20
+6307	20	0
+6702	50000	2669
+4247727	10618	0
+1558	0	2719
+35231	0	131
+12647	4	0
+45594	85	9
+19562	0	506
+165501	5	7
+1103946	16700	60575
+644	0	2
+319796	1600	1155
+17927	19763	15469
+464566
+
+chain	6025887	chr22_h2_hap1	63661	+	0	63661	22	51304566	+	42594964	42658568	527
+748	1	0
+260	4	0
+675	1	0
+4844	0	2
+10592	8	0
+3276	29	0
+2384	10	0
+2795	0	2
+464	1	0
+3865	1	0
+1777	1	0
+1286	0	2
+875	1	0
+2336	1	0
+4337	1	0
+2724	0	3
+1087	6	0
+7154	0	1
+1045	2	0
+11070
+
+chain	15737781	chr22_random	257318	+	90752	257318	GL000211.1	166566	+	0	166566	187
+166566
+
+chain	3641362	chr22_random	257318	+	7	38789	11	135006516	-	18284691	18323344	804
+2900	3	1
+66	1	1
+55	1	1
+3449	0	1
+1785	1	1
+37	1	1
+178	1	0
+852	0	1
+2329	2	0
+4939	1	0
+1557	1	1
+30	1	1
+1005	1	0
+622	16	0
+39	0	1
+42	0	22
+755	1	1
+30	1	1
+952	1	1
+26	1	1
+141	18	17
+1110	2	0
+1529	1	1
+22	1	1
+399	1	1
+33	1	1
+1369	20	30
+3959	0	4
+1144	1	0
+1032	27	25
+8	23	0
+56	24	0
+51	0	9
+11	1	57
+34	4	4
+7	134	0
+296	26	0
+25	1	1
+2452	0	5
+19	1	1
+231	1	0
+327	1	0
+962	1	1
+22	1	1
+1571
+
+chain	109494	chr22_random	257318	+	39517	40750	22	51304566	-	30977735	30979001	1172425
+166	5	5
+133	3	3
+48	1	1
+297	0	33
+234	1	1
+58	4	4
+283
+
+chain	19094	chr22_random	257318	+	39007	39213	22	51304566	-	29625864	29626070	11204980
+206
+
+chain	8587	chr22_random	257318	+	39415	39517	22	51304566	-	29782769	29782871	2027258
+50	48	48
+4
+
+chain	3763	chr22_random	257318	+	39465	39513	22	51304566	-	30978529	30978577	2726523
+48
+
+chain	17719073	chr2_random	185571	+	0	185498	2	243199373	+	242522204	242710000	158
+43034	21	22
+16724	1	0
+52199	0	669
+3059	0	4
+14500	1	0
+409	1	1
+22	1	1
+2039	1	0
+809	0	1
+2041	0	4
+2258	6	6
+4179	12	13
+1973	1	1
+21	1	1
+1855	1	1
+37	2	2
+4315	0	1
+1584	14	0
+281	0	2
+78	1	1
+1497	9	0
+237	2	1
+826	4	0
+21273	4	0
+6716	0	1650
+3449
+
+chain	18404389309	chr3	199501827	+	35000	199446827	3	198022430	+	60000	197962430	3
+13552792	1	0
+585083	1	0
+2092	74	72
+31067262	1	0
+90	0	1
+5628461	15	0
+788	0	1
+3676	2	0
+35	1	1
+4682	0	1
+1295	5	0
+437	42	53
+326	2	0
+3309	1	1
+40	1	1
+998	3	0
+3584	0	5
+930	7	5
+845	1	1
+28	1	2
+303	1	0
+509	5	0
+2291	6	6
+2789	0	1
+2541	9692	9690
+949	4	4
+35	1	1
+2874	1	0
+6717	1	0
+2823	0	1
+704	4	0
+5142	0	1
+2490	10	10
+162	7	7
+6308	15	0
+15177535	260003	152352
+2532	0	1
+24209179	4400000	3000000
+60453438	4	0
+40076811	20000	20999
+8195	1	1
+44	1	1
+1408	1	1
+33	1	1
+172	4	3
+25	1	1
+538	13	13
+173	1	1
+27	1	1
+636	1	1
+28	1	1
+470	3	3
+112	1	1
+375	1	1
+26	0	26
+106	0	78
+72	9	6
+12	3	29
+79	5	262
+56	1	1
+20	1	1
+815	43	43
+457	1	1
+49	0	18
+509	3	4
+23	1	1
+391	1	1
+44	1	1
+1270	4	0
+40	1	1
+264	27	31
+2416	2	0
+4377	13	13
+736	1	1
+47	1	1
+1416	1	1
+20	1	1
+1020	1	1
+25	1	1
+482	0	5
+716	0	1
+1697	1	1
+29	1	1
+1270261	27000	23108
+40930	0	1
+17455	1	1
+28	4	4
+45	491	0
+1669	58	0
+18	3	61
+54863	16	53
+7653	6	0
+3	99	0
+170	30	0
+25	0	30
+210	0	45
+359	0	915
+5980	256	640
+1363	1	1
+37	1	1
+7958	1	0
+372	1	0
+2442058
+
+chain	572461	chr3	199501827	+	50900356	50910048	3	198022430	-	147087402	147097092	2111
+52	1	6
+5886	1	0
+2586	6	0
+1160
+
+chain	14997	chr3	199501827	+	196923229	196923617	3	198022430	+	195437554	195437811	3659243
+77	131	0
+180
+
+chain	6146	chr3	199501827	+	196987930	196988205	3	198022430	+	195502296	195502751	2529960
+74	171	141
+23	2	212
+5
+
+chain	4201	chr3	199501827	+	196923126	196923228	3	198022430	+	195438036	195438138	6236935
+102
+
+chain	2082	chr3	199501827	+	196994845	196994975	3	198022430	+	195509346	195509572	2249717
+55	18	114
+57
+
+chain	20970321	chr3_random	749256	+	196010	556188	3	198022430	-	121623404	130096441	129
+131258	0	1
+41217	50000	8162858
+137703
+
+chain	13779918	chr3_random	749256	+	0	146010	3	198022430	-	77602115	77748060	219
+64144	1	0
+1191	0	1
+633	0	1
+4651	29	21
+5147	0	1
+947	14	0
+64	56	0
+55	0	2
+2421	0	15
+741	9	0
+371	6	4
+554	1	0
+5424	0	1
+4074	1	1
+44	1	1
+3065	0	1
+2772	1	1
+36	1	1
+15950	1	0
+2351	0	2
+5999	1	0
+17825	0	13
+74	1	1
+367	1	1
+47	1	1
+2084	2	0
+288	0	3
+744	1	0
+131	0	1
+465	1	1
+29	1	1
+659	10	0
+830	0	3
+262	3	0
+1428
+
+chain	13528802	chr3_random	749256	+	606188	749256	3	198022430	+	46352896	46495976	221
+8517	0	10
+20860	0	6
+16120	0	1
+4148	7	6
+745	7	6
+517	6	0
+907	5	5
+1382	4	0
+2730	0	1
+1143	36	36
+457	13	17
+1748	1	1
+48	1	1
+954	0	2
+767	1	4
+7353	0	8
+4950	0	12
+13338	0	1
+4685	1	1
+21	1	1
+1414	3	0
+4158	23	23
+5081	0	1
+14097	1	1
+49	1	1
+770	16	16
+424	1	1
+17	1	1
+244	1	1
+23	1	1
+1462	12	0
+2048	14	0
+4573	1	0
+3856	2	0
+754	0	8
+7304	1	0
+5243
+
+chain	17653370240	chr4	191273063	+	0	191263063	4	191154276	+	10000	191029082	4
+1413146	51000	71672
+5369	5	6
+65	1	1
+67	1	1
+425	1	1
+32	1	1
+175	1	1
+34	1	1
+5092	1	1
+46	1	1
+1396	15	15
+1446	0	1
+5135	1	0
+586	1	1
+38	1	1
+10	0	21
+1587	0	6
+205	0	3
+97	6	0
+177	0	9
+4059	1	1
+71	1	1
+1413	83	1
+51	7	7
+105	7	7
+67	41	0
+67	42	1
+55	41	0
+25	41	0
+3244	558	0
+64	93	0
+93	558	0
+907	0	2
+1101	55	0
+3473	15	15
+1167	3	0
+25	0	29
+135	29	0
+5074	1	1
+42	1	1
+1825	14	14
+1992	0	3
+23	1	1
+4171	6	6
+796	0	165
+196	0	99
+87	0	33
+190	6	8
+107	2	2
+21	0	2
+62	1	68
+32	14	15
+81	18	18
+55	0	100
+17	1	1
+222	2	169
+51	0	35
+3289	18	18
+298	0	1
+373	0	1
+2965	1	1
+28	0	23
+1704	0	38
+114	0	38
+53	7	44
+119	77	0
+269	1	1
+70	1	1
+2000	23	33
+2400	1	1
+94	1	1
+6002	18	18
+776	1	0
+369	16	16
+418	51	0
+53	1	27
+2181	1	4
+57	1	1
+1973	10	0
+4184	11	11
+1594	0	18
+2038	0	109
+4332	0	7
+49	0	4
+1465	3	1
+4156	2	0
+5455	3	2
+129	4	4
+9082	0	1
+786	20	20
+1506	0	1
+252	8	7
+17512	50	1
+56	1	0
+2474	69	52
+69	0	30
+60	16	0
+19	15	0
+40	1	1
+138	16	0
+74	5	51
+3386	0	1
+968	0	4
+1624	11	11
+1065	0	3
+2935	8	0
+2312	0	181
+2300	1	0
+1641	6	1
+1955	0	1
+68	1	1
+347	1	1
+40	1	1
+1553	6	0
+678	16	16
+92	0	33
+390	4	0
+1147	0	1
+1948	4	4
+4296	18	18
+955	1	1
+47	1	1
+1555	1	0
+2251535	81122	0
+145	1	1
+48	1	1
+718	1	0
+2789	1	1
+27	1	1
+1601	4	0
+1048	39	39
+820	0	2
+20	6	0
+28	2	0
+76	12	18
+28	1	0
+11	9	3
+1772	0	6
+22	1	1
+946	1	1
+24	1	1
+1245	1	0
+3231	1	1
+41	1	1
+1652	20	20
+11270	3	0
+2704	1	1
+41	1	1
+1812	5	6
+1477	0	11
+3790	4	0
+2187	1	1
+48	1	1
+1704	1	1
+73	1	1
+2265	1	1
+10	1	1
+553	1	1
+49	1	1
+67	1	1
+33	1	1
+3932	5	0
+18	1	0
+780	0	1
+1260	0	1
+4203	0	25
+863	14	14
+7114	1	1
+70	1	1
+169	0	1
+43	1	1
+145	1	1
+39	0	3
+8	1	1
+753	0	1
+2255	1	1
+21	1	1
+1605	1	1
+19	2	1
+392	1	1
+29	1	0
+3673	1	0
+145	14	14
+39	0	1
+1246	0	1
+2302	1	0
+1554	9	9
+4537	0	1
+1064	2	0
+2051	1	0
+1130	0	2
+164	1	0
+1972	0	1
+18	3	3
+2597	1	1
+46	3	3
+196	1	1
+17	1	1
+60	4	4
+187	4	4
+46	1	1
+692	1	0
+3920	3	3
+15	1	1
+486	14	14
+1709	8	0
+169	1	0
+597	1	1
+18	0	7
+3423937	0	1
+1295496	1	1
+26	1	1
+760	150000	591802
+22468468	1	1
+27	1	1
+2592	0	2
+33	1	1
+2065	3	0
+1050	11	11
+1046	3	9
+52	11	11
+3200	1	0
+906	1	0
+1644	6	0
+1180	0	1
+475	0	5
+2556	26	22
+351	0	1
+1716	71000	36200
+976586	59000	26528
+7701	0	4
+9296	0	1
+1862	1	0
+3316	7	3
+1131	0	1
+1795	1	0
+569	1	0
+2895	44	44
+458	3	0
+5371	1	0
+6774	0	2
+2504	0	2
+1247	1	1
+45	1	1
+2415	17	17
+8215	1	1
+18	1	1
+272	10	10
+420	1	1
+34	1	1
+7961	4	0
+1973	1	1
+45	1	0
+529	1	0
+603	0	1
+18	1	1
+621	4	12
+67	2	0
+18	34	0
+516	0	1
+1400	38	41
+3786	0	1
+228	3	0
+1026	1	1
+49	1	1
+3336	0	3
+951	1	1
+77	2	1
+441	1	2
+1833	9	9
+301	5	5
+2787	17	17
+1747	1	0
+3040	2	9
+81	10	10
+86	2	0
+7354949	20000	1606
+1681	16	30
+13957	0	8
+1947	0	3
+1255	1	1
+38	0	1
+1788	12	17
+1045	6	0
+1327	0	1
+5775	1	1
+18	1	1
+1933	1	0
+1716	13	13
+255	1	0
+124	0	3
+792	0	5
+1521	1	1
+64	1	1
+9005617	150000	150000
+171176	3000000	3000000
+7074452	53320	65431
+1937	0	1
+2845	2	0
+1387	0	1
+114	1	0
+2382	0	4
+68	6	6
+60	4	0
+20	0	1
+93	0	51
+9781584	351994	0
+1909446	184275	0
+3919546	13	13
+435	23	23
+838	0	1
+807	6	6
+74	1	1
+43	1	1
+652	30000	29839
+13847966	0	1
+14069801	2	0
+8504	0	1
+32266	8	0
+12729	0	2
+35327	12	14
+1503	1	0
+1334	1	0
+759	0	1
+7479	34	34
+2523	7	1
+9912	18	17
+2523	1	0
+1321	0	1
+3684	18	18
+5282	2	0
+5505	20	20
+9694	6	6
+22003	9	0
+578	0	1
+5166	2	0
+92208	2	5
+8	1	0
+5	0	2
+113	4	0
+845	6	7
+2247	3	1
+3770	0	1
+5719	0	2
+2511	0	1
+1557	0	1
+5812	0	1
+3607	0	1
+7405	1	0
+11075	0	1
+2794	1	0
+2340	1	0
+429	0	1
+522	2	0
+2397	5	0
+371	11	0
+1376	1	0
+2416	8	0
+210	1	1
+20	1	1
+5104	1	1
+20	1	1
+525	2	0
+836	0	1
+2094	1	0
+2213	3	0
+327	9	6
+2593	1	1
+57	1	1
+1618	0	1
+1400	4	0
+254	0	2
+93	10	0
+754	0	6
+193	0	1
+2378	0	1
+1753	3	0
+1903	0	4
+29	1	1
+1136	14	14
+2452	4	0
+3622	31	3
+456	14	14
+1076	7	8
+68	1	1
+20	1	1
+145	1	1
+68	1	0
+12	0	1
+10	0	1
+11	1	0
+35	1	0
+5	0	1
+11	1	2
+32	6	7
+35	1	0
+8722	1	0
+888	0	4
+456	3	0
+45	0	1
+151	13	13
+756	0	1
+203	8	7
+140	1	1
+20	1	1
+308	5	0
+1020	0	1
+1258	0	1
+160	0	2
+1411	1	1
+22	1	1
+1180	12	12
+4521	0	2
+1155	27	0
+4954	3	0
+1392	1	1
+47	1	1
+3854	2	1
+130	1	0
+2633	2	0
+3053	12	13
+2308	0	1
+1747	0	45
+732	2	0
+1336	9	11
+3898	0	6
+437	1	0
+981	0	1
+1326	0	1
+382	4	0
+1081	10	0
+81	1	1
+142	0	2
+5452	29	29
+495	1	1
+26	1	1
+485	0	1
+525	0	4
+36	0	6
+3945	347	0
+1034	1	1
+27	1	1
+60	2	0
+2581	3	0
+3880	0	4
+1792	0	1
+20	1	1
+356	1	0
+4244	5	5
+36	1	1
+2232	2	2
+42	1	1
+4462	0	2
+1611	1	0
+1290	0	2
+110	1	0
+1466	0	1
+357	3	0
+850	12	0
+13547766	0	1
+3724943	2	0
+46473408	0	1
+1696	1	1
+28	1	1
+1629	0	4
+666	4	0
+13464	30000	12874
+8520008	2	0
+1107	1	1
+15	1	1
+1892	0	4
+6798	0	2
+1793	1	1
+25	0	3
+422	389	0
+786	2	0
+545	0	2
+54	1	0
+143	1	1
+39	1	1
+89	1	1
+29	1	0
+171	1	1
+46	1	0
+192	1	1
+33	1	1
+2580	0	1
+107	1	1
+29	1	1
+218	1	0
+175	6	5
+1407	1	1
+52	1	1
+8851	1	0
+14427	4	0
+1737	22	0
+5806	1	0
+1115	1	1
+29	0	2
+3395	0	1
+3164	0	2
+522	1	0
+24	1	1
+658	4	0
+5724	9	9
+1209	0	1
+5380	1	0
+97	1	0
+854	4	0
+78	5	11
+2728	6	7
+3754	17	13
+1363	1	0
+1025	1	0
+1811	0	1
+7507	0	4
+1184	3	0
+763	1	0
+797	3	0
+293	2	0
+2488	0	1
+335	0	1
+9959	1	0
+3255	1	0
+1322	0	1
+8118	2	0
+2908	49	49
+369	2	0
+632	1	0
+63	0	5
+3008	0	1
+9582	0	1
+14742673	0	3013
+39686
+
+chain	945825	chr4	191273063	+	69381892	69391896	4	191154276	+	69230000	69240000	2911
+2225	1	0
+4917	1	0
+2807	2	0
+51
+
+chain	941684	chr4	191273063	+	69471941	69481941	4	191154276	+	69320000	69330000	3076
+3521	0	1
+4784	1	0
+1694
+
+chain	941274	chr4	191273063	+	69614595	69624595	4	191154276	+	69580000	69590000	3093
+10000
+
+chain	940419	chr4	191273063	+	69564606	69574607	4	191154276	+	69530000	69540000	3129
+3216	5	5
+134	0	1
+5676	2	0
+968
+
+chain	939146	chr4	191273063	+	69534617	69544617	4	191154276	+	69500000	69510000	3182
+387	6	6
+9607
+
+chain	939091	chr4	191273063	+	69481941	69491934	4	191154276	+	69330000	69340000	3184
+8138	0	4
+1546	0	3
+309
+
+chain	938726	chr4	191273063	+	69461942	69471941	4	191154276	+	69310000	69320000	3193
+130	0	1
+9869
+
+chain	936769	chr4	191273063	+	69604595	69614595	4	191154276	+	69570000	69580000	3285
+2900	25	25
+7075
+
+chain	936653	chr4	191273063	+	69421914	69431904	4	191154276	+	69270000	69280000	3293
+6388	14	14
+338	29	29
+266	0	1
+2309	1	3
+55	1	0
+83	0	8
+506
+
+chain	936357	chr4	191273063	+	69391896	69401898	4	191154276	+	69240000	69250000	3304
+2367	1	0
+2329	0	1
+795	23	23
+2819	2	0
+1666
+
+chain	935200	chr4	191273063	+	69441943	69451948	4	191154276	+	69290000	69300000	3343
+1203	4	0
+488	57	57
+7133	2	1
+310	1	0
+551	0	1
+256
+
+chain	934799	chr4	191273063	+	69544617	69554606	4	191154276	+	69510000	69520000	3366
+1296	39	39
+1112	1	0
+204	1	0
+2340	0	12
+1710	0	1
+3286
+
+chain	933839	chr4	191273063	+	69584607	69594595	4	191154276	+	69550000	69560000	3402
+417	3	0
+966	1	0
+2053	0	1
+1784	5	8
+284	0	12
+4475
+
+chain	932655	chr4	191273063	+	69594595	69604545	4	191154276	+	69560000	69569950	3440
+8695	26	26
+1229
+
+chain	930772	chr4	191273063	+	69451948	69461942	4	191154276	+	69300000	69310000	3507
+1068	0	1
+1437	25	27
+806	0	4
+5337	50	50
+300	1	0
+970
+
+chain	928519	chr4	191273063	+	69411919	69421914	4	191154276	+	69260000	69270000	3571
+62	32	32
+801	11	11
+3595	38	38
+941	54	59
+4461
+
+chain	928371	chr4	191273063	+	69511937	69521941	4	191154276	+	69360000	69370000	3579
+6433	60	60
+335	10	6
+239	10	10
+2917
+
+chain	925594	chr4	191273063	+	69554606	69564602	4	191154276	+	69520000	69529997	3671
+2109	0	1
+4421	81	81
+1599	22	22
+1764
+
+chain	922960	chr4	191273063	+	69501928	69511937	4	191154276	+	69350000	69360000	3756
+714	8	8
+423	18	18
+882	33	33
+952	22	22
+607	1	0
+196	64	64
+495	3	0
+2055	2	0
+548	3	0
+2983
+
+chain	915200	chr4	191273063	+	69491934	69501928	4	191154276	+	69340000	69350000	3933
+1036	10	10
+2821	5	0
+53	40	40
+209	3	0
+3718	11	0
+421	0	23
+332	11	11
+292	0	2
+432	23	23
+159	20	20
+115	20	20
+263
+
+chain	911203	chr4	191273063	+	69431904	69441943	4	191154276	+	69280000	69290000	4026
+364	6	5
+212	4	0
+2445	40	15
+377	30	30
+1126	60	60
+262	8	6
+3222	145	138
+1738
+
+chain	903419	chr4	191273063	+	69401898	69411919	4	191154276	+	69250000	69260000	4208
+1051	52	52
+1007	0	1
+319	27	26
+154	98	97
+145	40	40
+512	23	0
+355	5	5
+126	19	19
+128	49	49
+67	0	1
+3337	0	2
+1729	5	5
+773
+
+chain	895926	chr4	191273063	+	69574644	69584607	4	191154276	+	69540037	69550000	4357
+3368	220	220
+1524	84	84
+1558	19	19
+889	41	41
+1592	43	43
+625
+
+chain	866339	chr4	191273063	+	69524748	69534617	4	191154276	+	69490119	69500000	4930
+190	50	50
+59	111	111
+51	7	7
+78	59	59
+58	121	121
+57	39	39
+70	0	1
+1558	108	108
+737	24	24
+3582	0	1
+84	0	10
+2826
+
+chain	659008	chr4	191273063	+	71711854	71718864	4	191154276	+	71492990	71500000	7936
+7010
+
+chain	608986	chr4	191273063	+	69375441	69381892	4	191154276	+	69223549	69230000	8701
+135	1	0
+2166	0	1
+4149
+
+chain	248590	chr4	191273063	+	69521941	69527313	4	191154276	+	69370000	69375377	111030
+2807	190	190
+50	59	59
+111	136	136
+59	58	58
+121	57	57
+39	1628	1633
+57
+
+chain	214386	chr4	191273063	+	71534589	71536854	4	191154276	+	71500000	71502265	534073
+2265
+
+chain	96900	chr4	191273063	+	3963456	3964475	4	191154276	+	3912520	3913539	1319679
+1019
+
+chain	52181	chr4	191273063	+	69624595	69625143	4	191154276	+	69590000	69590548	2441389
+548
+
+chain	20814	chr4	191273063	+	1495708	1495926	4	191154276	+	1526075	1526293	9826122
+218
+
+chain	8858	chr4	191273063	+	1496845	1496937	4	191154276	+	1526189	1526281	25171661
+92
+
+chain	8858	chr4	191273063	+	1496752	1496844	4	191154276	+	1526189	1526281	25171662
+92
+
+chain	8858	chr4	191273063	+	1496566	1496658	4	191154276	+	1526189	1526281	25171663
+92
+
+chain	7802	chr4	191273063	+	1492030	1492276	4	191154276	+	1522531	1522736	2805154
+25	83	42
+23	15	15
+4	55	55
+41
+
+chain	7606	chr4	191273063	+	69578098	69578232	12	133851895	+	88986938	88987072	9526361
+134
+
+chain	7510	chr4	191273063	+	1496208	1496286	4	191154276	+	1526203	1526281	25171660
+78
+
+chain	7439	chr4	191273063	+	1527942	1528019	4	191154276	+	1557568	1557645	18158883
+77
+
+chain	7376	chr4	191273063	+	1496452	1496529	4	191154276	+	1526075	1526152	27495831
+77
+
+chain	6986	chr4	191273063	+	59479326	59479400	7	159138663	+	119297971	119298045	28268313
+74
+
+chain	6131	chr4	191273063	+	1496080	1496144	4	191154276	+	1526075	1526139	27495827
+64
+
+chain	5599	chr4	191273063	+	1495650	1495708	4	191154276	+	1526203	1526261	27226300
+58
+
+chain	5460	chr4	191273063	+	1496658	1496715	4	191154276	+	1526095	1526152	27495830
+57
+
+chain	4356	chr4	191273063	+	1498960	1499009	4	191154276	+	1528103	1528152	18458745
+49
+
+chain	4121	chr4	191273063	+	69578012	69578069	3	198022430	-	95182224	95182281	17792812
+57
+
+chain	3000	chr4	191273063	+	1495929	1496022	4	191154276	+	1526110	1526203	11256589
+93
+
+chain	2961	chr4	191273063	+	69443663	69443695	4	191154276	-	68628109	68628141	14494983
+32
+
+chain	2485	chr4	191273063	+	1503833	1503862	4	191154276	+	1532970	1532999	23156792
+29
+
+chain	2401	chr4	191273063	+	1492301	1492331	4	191154276	+	1522679	1522709	5335388
+30
+
+chain	2012	chr4	191273063	+	1496731	1496752	4	191154276	+	1526075	1526096	27495829
+21
+
+chain	1744	chr4	191273063	+	1597414	1597448	4	191154276	+	1627062	1627096	3575887
+34
+
+chain	1461	chr4	191273063	+	69579763	69579840	5	180915260	+	121968423	121968500	3935628
+77
+
+chain	1332	chr4	191273063	+	69545913	69545943	11	135006516	-	130984886	130984916	21069914
+30
+
+chain	909	chr4	191273063	+	69582306	69582346	3	198022430	-	10790236	10790276	7796945
+40
+
+chain	18169122	chr4_random	842648	+	440032	631501	GL000194.1	191469	+	0	191469	150
+191469
+
+chain	18001815	chr4_random	842648	+	0	189789	GL000193.1	189789	+	0	189789	151
+189789
+
+chain	15268007	chr4_random	842648	+	681501	842648	GL000218.1	161147	+	0	161147	194
+161147
+
+chain	9245037	chr4_random	842648	+	239789	336038	4	191154276	+	8829368	8925617	353
+96249
+
+chain	137712	chr4_random	842648	+	388580	390032	4	191154276	+	9620000	9621452	935614
+1452
+
+chain	10386	chr4_random	842648	+	388312	388420	11	135006516	-	91778086	91778194	21974850
+108
+
+chain	3377	chr4_random	842648	+	388277	388312	11	135006516	-	84847900	84847935	23649965
+35
+
+chain	2456	chr4_random	842648	+	388184	388235	X	155270560	-	93144339	93144390	24160146
+51
+
+chain	16791974256	chr5	180857866	+	63000	180837866	5	180915260	+	10000	180905260	5
+17520657	24032	50000
+1688	3435	1
+37	1399	0
+27	2	1
+8	1	1
+3983	3434	0
+103	1	1
+32	1	1
+67	1	1
+35	1	1
+752	1669	0
+43	1	1
+1207	0	1
+46	0	1
+5	0	1
+19	1	1
+70	3434	0
+962	16	16
+1905	44	44
+85	41	41
+332	49	49
+1675	23	23
+1185	11	11
+124	35	35
+713	105	105
+408	4	4
+113	16	16
+1835	1	2
+26	7	8
+18	2730	25
+3103	1	0
+7858	718	10488
+307	1	636
+7461	0	1
+23772	51	0
+4031	0	1
+20571	0	1
+9135	0	2
+6885	2	3
+110	3	0
+816	2	3
+2295	0	34
+3936	28	28
+3536	0	2
+2917	0	1
+652	1	1
+37	1	1
+657	1	1
+22	1	1
+419	3	4
+3580	1	1
+29	1	1
+274	11	35
+835	3036	0
+1907	1	0
+10504	30	28
+784	0	6
+127	10	0
+668	1	1
+28	1	1
+2467	4	0
+179	0	2
+1650	1	1
+39	1	1
+2433	1	0
+720	1	1
+40	1	1
+772	1	1
+32	1	1
+353	1	1
+17	1	1
+1776	0	1
+6082	3	0
+2669	12	10
+2857	1	1
+35	1	1
+722	60	60
+200	1	1
+240	1	1
+4048	1	1
+49	1	1
+702	1	1
+33	1	1
+2927	1	2
+1487	17	0
+276	16	16
+1039	1	1
+35	1	1
+2068	1	1
+40	1	1
+828	1	1
+36	2	0
+317	8	0
+893	1	1
+33	1	0
+8143	0	4
+28632199	3000000	3000000
+12470071	0	1
+29760415	40000	50000
+5878002	23000	20845
+4521	1	0
+676	6	6
+5928	0	1
+372	1	1
+47	1	1
+6801	3	2
+639	0	1
+871	3	4
+11530	0	4
+22966	0	1
+15447	0	1
+53856	0	2
+15988	0	2
+906887	10	11
+40152817	5000	52715
+3521239	0	1
+1604	10	0
+12778810	4100	51715
+15152692	27	0
+1852096	1	0
+8710030
+
+chain	924655	chr5	180857866	+	17585088	17611949	5	180915260	-	163333152	163394435	1227
+14	409	52001
+494	3435	1
+24	1	1
+1487	10	10
+682	13	13
+132	3449	15
+306	1	1
+74	1	1
+967	3434	0
+1285	3434	0
+68	4569	1135
+2087	50	50
+435
+
+chain	315813	chr5	180857866	+	17584685	17618655	5	180915260	+	17581691	17599590	1580
+403	14	14
+237	1475	75
+628	25	25
+51	89	89
+304	24	24
+70	33	33
+37	698	698
+667	3506	72
+1354	96	96
+75	4	4
+752	1710	41
+450	382	382
+51	14129	7264
+237	12	12
+614	37	37
+134	16	16
+422	31	31
+796	4345	1642
+62
+
+chain	312488	chr5	180857866	+	17597387	17639380	5	180915260	+	17580657	17599710	1454
+373	70	70
+1245	2263	863
+1184	3434	0
+1733	3775	2106
+50	9111	2246
+1078	993	993
+1363	8015	1147
+44	85	85
+41	332	332
+49	6299	3596
+341	45	44
+70
+
+chain	265075	chr5	180857866	+	17745718	17748537	5	180915260	+	17713035	17715853	333767
+1906	1	0
+912
+
+chain	207388	chr5	180857866	+	17584033	17596937	5	180915260	+	17583073	17597745	2201
+51	557	557
+14	17	17
+13	654	654
+172	494	494
+219	23	23
+567	4975	6743
+176	6	6
+865	14	14
+96	1354	1354
+26	2261	2261
+350
+
+chain	193008	chr5	180857866	+	17583668	17629078	5	180915260	+	17580674	17599710	1465
+356	84	84
+533	3434	0
+698	5562	728
+51	4689	1255
+946	4787	1353
+543	8	8
+167	12743	7643
+324	5466	2032
+306	3553	850
+1045	45	44
+70
+
+chain	130263	chr5	180857866	+	17639380	17641654	5	180915260	+	17592112	17594386	19200
+936	23	23
+116	16	16
+1183
+
+chain	123401	chr5	180857866	+	17602522	17620625	5	180915260	+	17589594	17593961	2306
+159	16	16
+1763	19	19
+54	14448	712
+1644
+
+chain	53192	chr5	180857866	+	17626966	17629142	5	180915260	+	17590000	17592176	2614
+952	1045	1045
+45	70	70
+64
+
+chain	42492	chr5	180857866	+	17625757	17626966	5	180915260	-	163394507	163395716	9006
+1209
+
+chain	23743	chr5	180857866	+	17605548	17605956	5	180915260	+	17596054	17596462	38000
+290	9	9
+109
+
+chain	20601	chr5	180857866	+	17748538	17748754	5	180915260	+	17712817	17713033	9842237
+216
+
+chain	11635	chr5	180857866	+	17618762	17618981	5	180915260	+	17595532	17595751	149283
+219
+
+chain	9108	chr5	180857866	+	17618655	17618762	5	180915260	+	17583355	17583462	1340460
+107
+
+chain	7916	chr5	180857866	+	17587442	17604673	5	180915260	-	163387098	163397461	2244
+25	61	61
+79	398	398
+33	16608	9740
+27
+
+chain	7204	chr5	180857866	+	17604533	17604646	5	180915260	+	17599204	17599317	3499
+113
+
+chain	4292	chr5	180857866	+	17639265	17639310	5	180915260	+	17595431	17595476	67944
+45
+
+chain	2558	chr5	180857866	+	17604673	17604706	5	180915260	+	17591745	17591778	3790746
+33
+
+chain	2511	chr5	180857866	+	170275712	170275739	5	180915260	+	170343161	170343188	11152528
+27
+
+chain	2447	chr5	180857866	+	17635643	17636496	5	180915260	-	163394091	163394944	8841
+35	713	713
+105
+
+chain	2252	chr5	180857866	+	17601306	17601338	5	180915260	+	17595246	17595278	11344
+32
+
+chain	2027	chr5	180857866	+	17785693	17785748	18	78077248	-	45596607	45596662	524022
+55
+
+chain	1518	chr5	180857866	+	17629142	17629191	5	180915260	-	163394458	163394507	205933
+49
+
+chain	1109	chr5	180857866	+	17613421	17613452	5	180915260	-	163395907	163395938	8647
+31
+
+chain	143977943	chr5_h2_hap1	1794870	+	0	1794870	5	180915260	+	68505249	71134051	52
+5440	1	0
+1785	0	1
+12373	0	2
+7216	0	1
+714	2	0
+4360	0	1
+11179	1	0
+2027	1	0
+6969	0	2
+3779	1	0
+634	4	3
+1384	0	9
+378	0	2
+1153	3	0
+1246	0	6
+1427	0	2
+608	1	1
+23	1	1
+1981	44	44
+3998	1	1
+33	5	0
+148	1	1
+18	1	0
+331	2	0
+162	1	0
+333	0	1
+644	1	0
+2053	1	0
+1896	0	1
+2096	1	1
+32	1	1
+265	0	14
+1061	0	1
+7303	6	6
+1313	1	0
+3225	0	2
+65	1	1
+220	1	1
+1422	0	1
+248	1	1
+21	2	0
+641	0	1
+163	3	0
+522	1	0
+1685	0	1
+299	1	1
+16	1	0
+3259	1	0
+6492	9	9
+700	0	2
+379	1	0
+186	0	16
+21	0	27
+242	21	19
+156	0	3
+2040	1	0
+7852	0	2
+1267	0	4
+8016	0	1
+2057	85	0
+449	0	1
+2797	0	1
+3858	0	1
+2129	1	0
+234	1	1
+28	1	1
+2923	0	3
+4346	1	0
+2467	1	0
+11093	1	0
+3932	0	3
+2223	1	1
+22	0	1
+25	0	6
+1909	2	0
+1136	1	0
+658	2	0
+32	8	0
+9	2	0
+14	15	11
+22	14	0
+20	51	1
+34	2	0
+43	0	2
+38	127	19
+15	14	0
+41	0	5
+9200	1	0
+2655	1	0
+38	1	1
+237	1	1
+28	1	1
+1065	1	0
+2979	3	0
+13	1	1
+653	4	0
+1950	1	0
+2320	2	0
+817	3	0
+524	8	0
+417	1	0
+873	1	0
+352	1	0
+152	2	0
+651	1	0
+285	1	0
+1830	0	1
+1271	0	1
+957	0	1
+1506	2	0
+2454	4	0
+6	4	0
+300	1	1
+68	1	1
+1648	0	1
+10725	10	10
+1308	2	1
+48	1	1
+1242	15	0
+1869	1	0
+26	0	452
+1178	0	3
+43	0	4
+3567	0	1
+2289	0	1
+695	0	6
+721	13	14
+192	0	2
+1190	1	1
+36	1	1
+451	0	1
+4137	1	0
+809	23	0
+1624	0	4
+453	4	0
+983	0	1
+188	0	5
+489	0	1
+299	11	11
+1923	1	0
+168	0	1
+891	1	1
+54	0	1
+908	0	28
+1224	2	0
+175	0	1
+459	2	0
+119	133	153
+50	13	13
+4001	0	1
+4764	3	0
+90	1	1
+117	92	0
+325	0	27
+19	1	1
+92	1	67
+21	1	28
+15	1	28
+9013	0	1
+1376	0	1
+674	10	0
+87	0	1
+1317	43	35
+260	1	0
+1518	11	12
+232	0	1
+1093	0	1
+737	0	2
+176	10	10
+664	1	1
+33	1	1
+2816	3	0
+4679	0	2
+3212	0	2
+2383	14	16
+3049	0	1
+146	1	0
+721	1	1
+35	1	1
+2260	2	0
+1228	0	1
+682	1	0
+8927	1	0
+795	2	0
+5278	0	2
+5578	13	0
+3665	20	0
+1852	9	0
+4564	1	1
+20	4	0
+111	1	1
+1065	37	37
+2979	1	0
+820	0	1
+9147	0	1
+411	0	1
+745	2	0
+144	3	3
+27	2	0
+734	1	1
+38	1	1
+105	0	4
+554	1	0
+35	1	1
+226	2	0
+254	1	1
+39	1	1
+3302	0	2
+16	1	1
+1276	1	1
+57	1	1
+122	5	0
+178	0	1
+29	1	1
+89	1	1
+32	1	1
+1743	1	0
+294	1	1
+27	1	1
+1925	1	1
+48	1	1
+116	1	1
+20	1	1
+163	4	4
+821	4	3
+46	1	1
+247	1	1
+27	2	2
+613	1	1
+44	1	1
+181	9	7
+1220	1	1
+53	0	3
+596	1	0
+1052	12	12
+130	1	0
+1524	0	1
+1878	1	4
+76	0	1
+6	0	5
+895	0	1
+290	9	5
+783	1	1
+45	1	1
+1910	1	1
+48	1	1
+409	1	1
+30	1	1
+158	2	0
+69	6	0
+428	1	1
+136	1	1
+418	44	44
+767	35	27
+711	1	1
+28	1	1
+1137	1	0
+585	1	0
+433	13	0
+3034	1	0
+961	0	3
+950	1	1
+15	1	1
+948	0	5
+153	21	20
+181	38	38
+765	8	10
+207	13	15
+3092	4	0
+202	5	5
+1406	0	5
+205	1	1
+44	1	1
+2719	1	1
+36	1	1
+1050	0	9
+108	0	2
+1177	4	0
+115	1	1
+2051	15	0
+520	8	8
+1072	0	1
+595	2	0
+4576	73	73
+6176	1	0
+1299	1	1
+29	1	0
+496	0	4
+379	2024	0
+7	3663	0
+82	4	0
+79	6	1
+556	11	0
+598	9	9
+138	77	73
+1651	3	9
+3302	0	8
+429	1	0
+163	0	3
+60	3	0
+132	1	1
+23	1	0
+1660	1	16
+2124	0	1
+1601	9	0
+35	525	6
+38	1	1
+235	1	30
+497	1	1
+37	1	0
+79	0	1
+1239	1	1
+31	1	1
+135	1	0
+5	2	0
+669	0	1
+1158	1595	0
+21	3	0
+5	126998	500121
+730	31	27
+278	0	2
+352	0	12
+363	13	21
+366	1	0
+378	3	0
+61	1	0
+105	17	68
+1480	32	32
+640	1	1
+52	1	1
+482	1	0
+638	1	1
+20	1	0
+21	1	1
+326	1	1
+37	1	1
+995	0	7
+1685	0	1
+1607	9	8
+633	1	1
+37	1	1
+697	6	6
+1363	8	8
+234	1	1
+44	1	1
+3022	5	6
+96	12	11
+674	4	0
+768	0	1
+169	3	0
+2083	0	1
+1098	20	20
+5586	1	0
+174	28	13
+366	2	0
+202	1	1
+69	1	1
+682	5	5
+3457	1	0
+232	1	0
+305	10	0
+1770	40	40
+349	38	38
+401	0	1
+441	7	3
+547	11	10
+210	4	0
+779	4	0
+193	4	0
+576	0	4
+514	48	48
+789	23	16
+2496	25	25
+874	25	11
+2776	19	19
+2824	4	0
+440	0	2
+876	14	14
+1198	39	39
+521	6	0
+126	40	40
+315	29	29
+616	94	99
+285	35	35
+175	12	12
+320	17	1
+3339	0	1
+260	49	49
+109	11	11
+586	0	1
+133	19	13
+8202	0	1
+307	0	1
+1366	1	0
+1073	9	12
+1385	0	1
+321	106	108
+1101	28	28
+483	42	42
+1752	58	58
+166	37	36
+748	16	16
+52	1	0
+1679	0	2
+455	9	17
+484	1	10
+74	33	33
+155	0	1
+62	0	8
+424	23	23
+491	8	9
+450	0	2
+63	1	0
+410	5	0
+1131	165	170
+254	39	39
+1162	0	272664
+1919	1	1
+82	1	1
+740	4	4
+261	1	1
+83	1	1
+52	1	1
+49	1	1
+231	6	6
+244	1	1
+21	1	1
+52	44	44
+114	20	20
+87	32	32
+149	0	6
+202	50	50
+115	44	44
+114	65	65
+50	111	111
+61	52	52
+101	42	45
+250	15	15
+208	1	0
+2259	3	0
+239	64	66
+168	10	10
+2393	1	1
+38	1	1
+674	1	1
+29	1	1
+469	22	25
+827	1	0
+1679	0	1
+463	9	13
+232	1	0
+248	1	5
+325	0	7
+1389	0	4
+63	1	0
+410	6	0
+685	3	0
+35	1	1
+407	166	168
+253	39	39
+71	0	4
+1288	35	35
+1697	32	32
+243	22	22
+395	51	51
+259	49	49
+108	6	6
+54	168	168
+464	45	45
+81	20	20
+84	21	21
+240	25	25
+584	0	810
+126	4	4
+42	6	6
+101	0	3
+41	1	1
+473	1	0
+373	1	1
+41	1	1
+614	1	1
+41	1	18042
+857	50	50
+279	2	0
+246	67	69
+160	10	10
+199	0	1
+154	1	0
+276	28	28
+124	29	28
+105	7	7
+355	1	1
+45	1	1
+299	1	1
+25	1	1
+283	30	35
+594	2	0
+1401	1	1
+46	1	1
+123	4	0
+830	1	0
+100	1	1
+61	1	1
+737	2	7
+285	1	1
+58	1	1
+143	18	0
+19	1	1
+575	1	1
+91	1	1
+318	2	0
+4090	4	0
+702	0	1
+2007	0	2
+901	0	1
+79	9	9
+31	3	3
+1203	1	0
+16	1	1
+574	1	1
+28	1	1
+346	6	0
+25	1	3
+22	2	0
+34	4	0
+7	1	0
+20	18	22
+511	0	5
+5088	0	1
+1065	0	4
+51	2	0
+2714	25	25
+81	8	8
+56	788	18
+22	1	1
+4702	0	1
+536	6	6
+3900	1	0
+1063	0	8
+4095	1	0
+1841	1	3
+1015	0	1
+2808	1	1
+17	1	1
+340	1	1
+39	1	1
+1548	1	1
+73	1	1
+291	1	0
+236	72	43
+104	0	1
+1843	4	0
+80	15	15
+1140	29	1
+45	1	1
+1245	3	0
+194	1	0
+816	11	1
+25	1	11
+47	1	1
+508	0	1
+255	1	1
+24	1	0
+319	13	13
+1846	397	398
+803	0	37
+509	0	12
+130	0	4
+609	0	3
+6495	1251	1253
+1091	11	11
+384	2	0
+1657	31	30
+109	31	31
+2815	63	63
+85	0	13
+589	48	48
+194	25	25
+1068	16	16
+209	2	0
+215	47	47
+1775	127	77
+533	188	0
+1164	1	0
+1863	1	1
+29	1	1
+1993	1	1
+19	1	1
+782	2	0
+3224	2	0
+22	1	11
+473	332	0
+604	1	1
+28	1	1
+223	1	1
+28	1	1
+2870	0	1
+38	1	1
+313	1	0
+768	0	1
+1039	9	9
+886	0	4
+243	0	1
+172	17	17
+2721	1	1
+71	0	1
+607	105	117
+54	46	44
+2057	1	1
+32	1	1
+452	1	1
+49	1	1
+169	322	6
+26	1	0
+567	3	0
+2324	1	0
+825	4	0
+1251	4	4
+2651	0	4
+703	14	19
+10731	13	0
+741	2	0
+1659	0	12
+7683	0	6
+838	1	0
+2905	12	326
+1714	1	0
+1172	90	100
+619	2	0
+263	0	59
+730	1	0
+56	4	0
+1746	17	17
+377	1	1
+27	4	0
+836	1	1
+67	1	1
+1022	0	1
+1096	1	1
+40	0	1
+8	1	1
+1864	1	0
+56	5	1
+6	0	10
+114	1	1
+34	1	1
+631	19	19
+139	13	13
+1330	1	11
+22	2	0
+2846	1	0
+358	0	2
+798	11	11
+3004	1	1
+30	1	1
+2032	1	16
+752	16	0
+40	0	6
+3211	0	1
+965	0	14
+2978	1	1
+29	1	1
+138	0	2
+1646	2	0
+375	1	1
+31	1	1
+6235	0	2
+2598	0	3
+592	0	4
+135	0	12
+3892	1	0
+840	0	12
+5528	9	5
+5400	0	1
+181	0	1
+836	0	3
+3087	1	1
+46	1	1
+2796	11	9
+6282	1	1
+25	1	1
+2009	1	1
+56	0	2
+209	15	15
+2433	1	1
+50	1	1
+366	1	0
+3233	0	1
+5144	0	2
+811	53	22
+23	1	0
+6	1	3
+43	0	2
+13	2	0
+5	0	14
+634	8	8
+1663	10	12
+433	1	1
+43	1	1
+397	2	0
+638	1	1
+42	1	1
+285	1	1
+28	1	1
+516	1288	2
+424	4	0
+660	1	1
+49	1	1
+816	0	12
+1015	1	1
+47	1	1
+988	0	3
+1000	14	32
+330	1	1
+38	1	1
+124	7	2
+43	1	1
+693	1	1
+61	1	1
+94	0	1
+963	1	1
+46	1	1
+1393	0	2
+139	2	0
+113	1	1
+20	1	1
+323	6	0
+34	0	1
+978	1	1
+38	1	1
+105	1	1
+18	1	2
+43	1	1
+381	0	1
+811	15	8
+2537	0	2436
+2642	1	1
+42	4	0
+92	10	10
+1363	1	1
+37	1	1
+252	5	0
+165	1	1
+329	1	1
+77	1	1
+705	0	6
+258	6	6
+155	0	1
+57	2	0
+1380	5	0
+348	2	0
+489	9	5
+448	1	0
+1681	0	1
+835	29	25
+1359	36	36
+223	0	1
+399	15	15
+466	4	4
+75	10559	200741
+1150	1	0
+682	12	15
+802	53	53
+535	1	0
+65	62	63
+497	30	1
+1458	1	0
+683	0	1
+1449	1	0
+977	15	0
+1636	0	4
+216	3	0
+587	0	10
+4302	1	1
+28	1	1
+733	0	4
+138	9	9
+595	0	11
+249	1	1
+65	1	1
+242	1	6
+74	0	4
+87	6	5694
+363	4	0
+513	0	1
+29	1	1
+1297	0	1
+415	1	3
+1947	0	2
+978	0	1
+3121	1	1
+17	1	1
+872	1	1
+31	1	1
+602	8	8
+238	1	1
+36	1	1
+930	1	1
+36	1	1
+1073	22	0
+494	0	1
+66	1	5
+60	1	1
+15	1	1
+452	1	0
+1587	0	7
+1465	1	1
+27	1	1
+76	1	1
+44	1	1
+143	16	14
+323	23	23
+685	1	1
+15	1	1
+136	6	0
+400	0	2
+109	3	0
+50	1	1
+18	1	1
+985	1	1
+38	1	1
+1034	12	12
+247	1	1
+91	2	1
+1383	1	1
+44	1	1
+164	15	16
+292	1	1
+47	1	1
+73	1	1
+43	1	1
+203	1	0
+420	1	1
+37	1	1
+449	0	2
+25	0	4
+415	4	6
+155	1	1
+26	1	1
+199	1	1
+41	0	32
+20	1	1
+68	1	1
+28	1	1
+2097	13	15
+207	8	10
+984	21	20
+134	5	0
+967	10	10
+956	3	0
+4424	5	6
+595	0	1
+1140	1	1
+28	1	1
+733	7	16
+1218	149	149
+429	0	4
+59	0	2
+2568	1	1
+45	1	1
+784	5	8
+289	1	0
+877	5	0
+34	1	0
+68	4	1
+735	1	1
+35	1	1
+1094	4	4
+1519	5	6
+138	12	12
+1044	0	1
+91	80	80
+369	1	1
+53	2	0
+63	1	1
+1220	7	9
+181	1	1
+44	1	1
+134	0	3
+476	2	2
+27	1	1
+205	1	1
+88	2	2
+822	4	4
+163	22	22
+116	1	1
+48	1	1
+3849	1	1
+21	1	1
+120	1	1
+32	1	1
+89	1	1
+29	1	0
+178	3	6
+1452	19	17
+5455	1	0
+10333	1	0
+784	0	1
+55	8	0
+468	0	1
+539	12	0
+98	1	1
+24	1	1
+77	1	1
+81	1	1
+4604	17	19
+7803	7	7
+807	0	1
+2260	7	5
+980	0	1
+2105	0	1
+4083	0	1
+836	0	2
+5612	1	0
+519	0	1
+1334	0	1
+2401	0	9
+1823	1	0
+159	0	2
+484	2	0
+14815	1	1
+36	1	1
+2512	4	0
+58	3	0
+3277	1	0
+559	0	1
+4024	1	0
+4383	22	13
+4131	1	1
+35	1	1
+290	1	1
+29	3	0
+533	1	0
+305	0	1
+2608	0	1
+443	3	1
+2322	0	20
+514	1	1
+46	1	1
+791	19	30
+3206	3	0
+6272	0	2
+1789	8	0
+291	39	39
+521	6	0
+126	40	40
+315	29	29
+616	94	99
+206	114	109
+506	0	14
+2370	0	2
+4709	1	1
+36	1	1
+5588	0	11
+299	1	0
+1366	1	0
+1644	1	1
+28	1	0
+4859	16	21
+1992	0	10
+505	0	1
+448	8	12
+721	40973	60417
+3484	1	1
+40	1	1
+2152	0	2
+5298	39	40
+141	25	25
+427	0	11
+1543	1	0
+3707	0	1
+1056	292	8656
+1768	2	0
+717	1	0
+14041	0	1
+4167	0	2
+7403	5	0
+7673	0	1
+3630	67	67
+74	129	129
+226	1	0
+1720	138	136
+1185	1	0
+878	46874	0
+862	1	1
+31	1	1
+9409	1	1
+37	1	1
+2231	0	2
+1682	0	1
+13767	0	1
+9473	0	1
+7168	2	0
+12384	1	0
+1188	0	4
+2044	1	0
+3076	1	0
+796	0	1
+5477	0	2
+5780	1	0
+6338	1	0
+2680	0	4
+2033	0	1
+9452	0	12
+402983
+
+chain	13752336	chr5_h2_hap1	1794870	+	324513	1282806	5	180915260	-	110525721	111977366	61
+37	39926	39909
+44	767	767
+34	9178	9179
+38	20004	20004
+27	1	1
+44	8383	8384
+1071	3	3
+511	0	1
+439	7	7
+3663	1483	1482
+77	11199	11214
+525	4132	4132
+704	1	0
+729	3	0
+158	29	29
+653	0	3
+154	0	2
+7041	8	0
+2068	0	7
+166	1	0
+812	6	7
+25	1	1
+1423	0	8
+438	0	1
+4783	0	1
+31	1	1
+1269	1	0
+926	3	0
+2542	2	0
+112	1	1
+2183	1	1
+59	1	1
+1605	2	2
+4515	0	1
+4368	1	0
+382	0	34
+60	1	1
+86	0	1
+552	6	6
+892	1	1
+33	1	1
+6705	0	1
+934	0	2
+8985	2	1
+445	6	0
+6283	0	1
+456	0	1
+1101	0	5
+696	0	1
+2973	6	0
+158	0	3
+449	0	3
+657	12	12
+151	0	1
+406	1	1
+55	1	1
+163	1	1
+72	1	1
+1955	1	0
+713	0	1
+3050	1	1
+35	1	1
+3127	1	0
+233	1	0
+1343	17	7
+1250	3	0
+322	1	0
+2081	0	1
+2413	5	0
+818	0	1
+18	1	1
+268	0	1
+271	1	1
+35	1	0
+586	2	0
+1192	0	1
+494	2	0
+4657	1	1
+30	5	0
+2172	0	334
+1981	5	0
+33	321	0
+2633	2	0
+142	1	0
+1597	7	0
+248	1	0
+317	1	1
+21	1	1
+441	0	1
+600	6	4
+35	1	1
+1593	2	6
+9303	1	0
+2781	0	2
+6052	0	4
+771	1	0
+1500	14	0
+1544	730	730
+31	3419	3419
+30	30394	30395
+40	349	349
+38	3691	3690
+48	3308	3306
+25	874	880
+25	8151	8151
+39	653	653
+40	315	315
+29	616	616
+94	285	285
+35	4123	4120
+49	13570	13573
+58	30899	10440
+165	1652	1655
+35	1697	1697
+32	660	660
+51	259	259
+49	168	168
+168	464	464
+45	446	446
+25	3886	3879
+67	800	800
+28	124	124
+29	1123	1123
+30	24987	23723
+2	1	1
+21	146	146
+2	1	1
+785	22543	22552
+67	3192	3170
+28	5357	5348
+397	8546	8565
+1251	3145	3145
+31	110	110
+29	2816	2816
+63	674	688
+48	195	195
+23	1511	1509
+47	1810	1786
+37	14	0
+41	533	533
+182	1	16
+5	20555	20281
+49	1	21
+55	54	52
+46	2763	2762
+37	5	2
+280	124045	123118
+495	0	1
+703	3	0
+87	27183	48462
+36	1182	1182
+389	16	16
+257	1	0
+118	3	3
+547	1	1
+25	1	1
+126	0	2
+3598	810	0
+148	0	6
+483	1	1
+34	1	1
+266	6	6
+350	2	2
+30	1	1
+297	4	4
+666	1	1
+89	1	1
+52	15	15
+2220	2647	2651
+53	53651	53634
+149	9850	9843
+39	1	1
+39	116984	481498
+39	653	653
+40	315	315
+29	616	616
+94	206	206
+114	65101	68610
+358	27	27
+588	11156	11155
+25	56460	137674
+105	1	0
+2251	13	13
+319	25	26
+826	25	25
+370	7	7
+439	0	1
+192	7	1
+250	0	13
+1302	1	8
+866	91	94
+91	14	14
+501	1	0
+1238	1	0
+113	475	60006
+212	8	10
+907	0	4
+350	1	0
+486	9	17
+448	0	2
+515	0	10
+788	13213	230
+199	16	16
+645	0	2
+112	37	25
+634
+
+chain	283844	chr5_h2_hap1	1794870	+	1261701	1280951	5	180915260	+	69698102	69815360	1487
+91	6326	96869
+318	0	10
+505	0	1
+204	64	64
+440	1	0
+235	0	1
+1269	0	1
+945	1	0
+670	242	551
+75	3	0
+1233	50	50
+199	4900	12045
+409	59	59
+310	37	40
+664
+
+chain	206667	chr5_h2_hap1	1794870	+	1287039	1295912	17	81195210	+	76583705	76597262	568754
+558	4	0
+365	2	2
+40	0	1
+253	1	1
+31	1	1
+522	6316	11003
+780
+
+chain	184822	chr5_h2_hap1	1794870	+	1284679	1286632	17	81195210	-	4506444	4508397	671275
+1953
+
+chain	128717	chr5_h2_hap1	1794870	+	1283006	1284382	5	180915260	+	70517839	70519212	1000883
+791	20	17
+565
+
+chain	128621	chr5_h2_hap1	1794870	+	1291852	1293214	17	81195210	+	76573863	76575225	1001637
+1362
+
+chain	122147	chr5_h2_hap1	1794870	+	627399	939358	5	180915260	-	110828619	111993762	93
+42	1752	1753
+58	6978	6974
+165	255	254
+37	4915	4915
+44	4384	4378
+64	19819	875253
+39	1	1
+9	264030	261784
+58	0	6
+56	6	6
+105	3	3
+98	1	1
+483	7968	7968
+62	497	497
+30
+
+chain	118081	chr5_h2_hap1	1794870	+	1290357	1291631	4	191154276	-	20442500	20443774	1089300
+230	18	18
+1026
+
+chain	112391	chr5_h2_hap1	1794870	+	1288972	1290160	17	81195210	-	4580707	4581894	1143267
+1134	1	0
+53
+
+chain	92982	chr5_h2_hap1	1794870	+	1293593	1294614	4	191154276	+	170627590	170628611	1373141
+72	1	1
+129	1	1
+818
+
+chain	75482	chr5_h2_hap1	1794870	+	1274745	1276419	5	180915260	-	111410923	111412615	820
+271	0	10
+350	0	6
+499	9	9
+444	0	2
+101
+
+chain	68300	chr5_h2_hap1	1794870	+	1276804	1279228	5	180915260	-	110416917	110419341	216
+2424
+
+chain	29652	chr5_h2_hap1	1794870	+	524804	525112	3	198022430	+	8519605	8519913	4781887
+308
+
+chain	29428	chr5_h2_hap1	1794870	+	756919	757240	2	243199373	+	16251117	16251431	4913030
+177	7	0
+137
+
+chain	27649	chr5_h2_hap1	1794870	+	641866	1186473	5	180915260	+	68929706	69564604	89
+32	351	351
+50	115	115
+44	114	114
+65	50	50
+111	61	61
+52	101	101
+42	14056	14883
+33	529303	618767
+27
+
+chain	20581	chr5_h2_hap1	1794870	+	1249367	1254462	5	180915260	-	111122604	111127700	1762
+2153	24	24
+85	8	8
+1086	0	1
+1739
+
+chain	5516	chr5_h2_hap1	1794870	+	253548	253608	5	180915260	+	68759177	68759237	7759123
+60
+
+chain	5218	chr5_h2_hap1	1794870	+	1244675	1244945	5	180915260	-	159621198	159621468	493
+30	1	1
+36	122	122
+81
+
+chain	4702	chr5_h2_hap1	1794870	+	1279881	1280287	5	180915260	+	70518261	70518663	9283
+59	311	307
+36
+
+chain	4436	chr5_h2_hap1	1794870	+	1274323	1274373	5	180915260	+	70526833	70526883	9273
+50
+
+chain	4277	chr5_h2_hap1	1794870	+	625682	625728	5	180915260	-	111701952	111701998	814
+46
+
+chain	3978	chr5_h2_hap1	1794870	+	1276419	1276466	5	180915260	+	70082181	70082228	137301
+47
+
+chain	3805	chr5_h2_hap1	1794870	+	1244816	1244863	5	180915260	+	69926901	69926948	475
+47
+
+chain	2924	chr5_h2_hap1	1794870	+	253608	253640	5	180915260	+	68759034	68759066	4803455
+32
+
+chain	943	chr5_h2_hap1	1794870	+	1282135	1282172	5	180915260	-	111121871	111121900	54522
+21	8	0
+8
+
+chain	692	chr5_h2_hap1	1794870	+	1276691	1276804	5	180915260	+	21496928	21497041	821
+113
+
+chain	13519395	chr5_random	143687	+	0	143687	5	180915260	+	180261930	180405660	222
+5859	0	4
+460	1	1
+23	0	2
+42	1	3
+42	1	1
+1633	55	55
+2271	0	10
+1279	2	0
+761	2	0
+25	1	1
+150	13	13
+4989	0	1
+1174	1	1
+23	1	1
+495	16	16
+2709	1	4
+349	0	4
+466	0	1
+292	2	0
+184	0	5
+621	13	13
+1788	2	0
+21	1	1
+731	12	12
+149	0	3
+5100	1	0
+1059	0	3
+1724	2	0
+4111	1	0
+890	4	4
+47	1	1
+1137	0	1
+147	17	19
+72	1	1
+22	1	1
+365	1	1
+19	2	2
+1360	0	1
+1476	1	1
+43	1	1
+1141	1	0
+2615	18	18
+4308	0	4
+135	0	2
+1484	8	6
+7384	0	11
+284	1	1
+69	1	1
+232	6	0
+1064	0	2
+4530	0	1
+4542	6	6
+10543	1	0
+4051	2	0
+11340	5	6
+4936	1	0
+12029	3	3
+43	1	1
+2955	27	27
+775	0	10
+822	1	0
+2057	1	0
+733	0	1
+4016	0	1
+4514	1	1
+49	1	1
+4484	1	0
+784	1	1
+25	1	1
+5707	2	0
+1274	1	0
+289	1	1
+34	1	0
+80
+
+chain	15799018021	chr6	170899992	+	5000	170896992	6	171115067	+	60000	171055067	6
+1297281	0	1
+7806978	162987	0
+4013144	0	9
+261	15	13
+18786172	17	17
+439	16	16
+59	4	5
+32202	17	17
+439	16	16
+59	5	4
+15403	0	1
+13914166	0	4
+115	1	1
+17	1	1
+415	0	12
+105	3	6
+12160281	50000	50000
+642507	3050000	3100000
+248423	50000	50000
+2918791	0	1238
+9427508	4	4
+162	12	12
+2193	22	22
+293	1	1
+30	1	1
+845	0	1
+45	1	1
+9769	0	2
+6058	1	1
+24	1	1
+2223	1	1
+24	1	1
+182	12	12
+284	1	1
+20	1	1
+970	1	1
+64	36	7
+575	43	43
+389	1	1
+27	1	1
+3279	1	1
+44	1	0
+3012	0	1
+545	17	17
+2562	1	0
+251	1	0
+943	0	8
+29	1	1
+566	0	6
+1483	0	2
+1960	0	1
+4564	1	1
+25	1	1
+832	1	0
+801	8	8
+1131	1	1
+58	1	5
+6177	1	0
+3712	0	1
+2185	1	1
+35	1	1
+710	2	2
+78	1	1
+2201	1	1
+30	1	1
+283	1	1
+30	1	1
+448	0	1
+75012	0	8
+2508457	0	1
+4641788	5	5
+37	1	1
+8503609	2	0
+5363169	200000	150000
+6040303	1	1
+36	0	1
+2020	1	1
+46	1	1
+1559	1	1
+72	1	1
+1098	1	1
+29	1	1
+264	7	7
+580	1	0
+30	1	1
+536	1	1
+41	1	1
+5663	0	1
+423	0	2
+372	1	1
+18	1	1
+9612	0	1
+1414	0	1
+176	2	0
+2742	0	1
+1968	1	0
+754	0	1
+4237	1	0
+2388	1	1
+31	0	1
+3385	1	0
+2004	0	8
+3395	3	0
+32	1	1
+4109	1	0
+1055	0	20
+1611	0	1
+17198424	26	17
+7835	1	0
+11119	1	1
+5197	0	11
+4791	1486	66479
+6787989	1	0
+149	0	4
+947	0	4
+244	1	0
+28418215	1	1
+21	0	1
+3116903	50000	171704
+1939305	1	1
+19	2	0
+8192274	4	4
+122	2	0
+1127	0	1
+1104	1	102
+18	0	29
+40	0	3
+22	1	4
+50	0	26
+56	18125	195105
+950946	1	157
+51	1	1
+104	0	255
+610	0	408
+104	0	105
+1285158	150028	50028
+725067
+
+chain	8374990	chr6	170899992	+	9109557	9199728	6	171115067	+	9164559	9254607	394
+3887	2	0
+1509	45	45
+888	7	8
+372	0	1
+4746	3	0
+1114	31	31
+140	35	35
+2111	13	13
+445	248	137
+1437	38	38
+55	25	25
+739	19	19
+2479	70	58
+1297	0	4
+7065	24	24
+542	31	31
+531	22	22
+824	0	1
+2286	40	39
+1209	48	48
+1435	6	0
+4096	4	0
+495	41	42
+6884	0	1
+3177	0	1
+2843	0	1
+904	5	5
+830	18	18
+1997	0	1
+942	4	0
+122	33	33
+1012	0	10
+3751	0	1
+5959	49	49
+4503	0	20
+7514	8	8
+4012	15	15
+673	16	0
+83	4	0
+424	3	0
+3932
+
+chain	892181	chr6	170899992	+	9258019	9267980	6	171115067	+	9150000	9160000	4430
+970	53	55
+802	16	17
+389	27	27
+73	5	4
+118	9	5
+615	0	2
+69	17	15
+578	0	1
+114	22	22
+888	130	130
+252	3	9
+564	0	1
+211	5	0
+90	4	0
+1846	21	21
+1832	0	42
+238
+
+chain	763150	chr6	170899992	+	9249728	9258019	6	171115067	+	9141295	9150000	6494
+566	0	1
+140	8	0
+205	47	47
+145	18	12
+46	1	0
+3841	0	56
+172	0	372
+444	18	18
+2447	20	20
+173
+
+chain	369937	chr6	170899992	+	9267980	9272102	6	171115067	+	9160000	9164126	144773
+1134	49	45
+1420	38	38
+203	0	4
+144	0	3
+115	54	55
+965
+
+chain	4624	chr6	170899992	+	9129966	9130015	6	171115067	+	165872977	165873026	28640892
+49
+
+chain	1407	chr6	170899992	+	74606704	74606747	X	155270560	+	149588561	149588604	701656
+6	11	11
+26
+
+chain	414456960	chr6_cox_hap1	4731698	+	0	4731698	6	171115067	+	28541283	33351542	27
+3409	1	0
+3526	0	1
+2940	0	4
+981	0	1
+4053	0	2
+1433	0	1
+3153	2	0
+369	0	1
+1090	0	1
+884	1	4
+363	1	0
+1969	0	1
+994	5	0
+58	1	1
+131	1	0
+4080	1	0
+680	0	1
+978	0	1
+1062	1	0
+2669	19	19
+7247	1	2
+1704	0	4
+1513	0	2
+49	2	0
+2160	0	5
+672	1	1
+38	1	1
+1384	1	0
+1685	1	1
+30	1	1
+2421	1	1
+42	1	1
+830	1	1
+41	1	1
+1630	0	1
+7458	1	0
+691	0	1
+525	0	1
+79	1	1
+29	1	1
+2055	1	1
+16	0	24
+1867	5	7
+786	0	2
+280	0	1
+227	2	0
+6678	1	0
+4401	1	0
+210	1	0
+3193	2	0
+3619	0	1
+2414	0	2
+5387	0	3
+2927	0	1
+3304	0	1
+440	0	5
+415	0	9
+3597	1	1
+48	1	1
+3412	1	1
+46	1	1
+3604	4	4
+1063	1	1
+36	1	1
+3511	6	6
+2797	32	41
+393	0	1
+477	1	1
+37	1	1
+2459	2	0
+517	0	12
+318	0	1
+1010	7	6
+2103	0	1
+5171	0	8
+1483	1	0
+3813	888	0
+4675	0	2
+5620	1	0
+2017	1	0
+3363	0	5
+1197	0	3
+3208	1	0
+1928	1	0
+174	6	0
+780	1	3
+443	14	0
+3079	0	5
+1993	0	3
+1089	1	1
+58	1	1
+80	0	8
+256	2	0
+2473	37	43
+752	0	2
+33	0	2
+825	0	1
+787	1	1
+37	1	1
+1168	16	0
+377	5	1
+27	1	1
+2161	2	0
+636	25	25
+1663	1	0
+1757	6	6
+205	4	0
+203	7	7
+107	1	1
+28	1	1
+100	4	4
+258	5	0
+659	1	0
+3805	5	8
+1486	4	4
+213	39	43
+4429	0	2
+1199	13	13
+5803	12	0
+2987	0	1
+813	0	17
+920	2	0
+3820	1	3
+130	21	9
+1913	0	14
+1800	0	1
+1255	2	0
+1466	4	0
+747	0	1
+124	2	0
+2108	1	0
+169	0	26
+593	1	0
+632	5	0
+2711	0	4
+1042	0	1
+34	1	1
+1025	2	0
+27	4	18
+81	1	33
+33	0	1
+6	0	76
+3950	1	0
+86	1	1
+12	1	1
+2947	0	1
+1160	1	0
+2046	3	0
+720	1	0
+1341	1	0
+10205	0	5
+1265	1	0
+10	1	1
+1278	5	6
+399	0	32
+96	16	18
+605	4	0
+1072	12	12
+950	11	7
+5128	9	10
+2711	1	0
+676	0	1
+2904	1	1
+30	1	1
+851	0	1
+1410	0	1
+394	1	1
+57	1	1
+1561	0	2
+11062	1	1
+58	1	1
+3238	1	1
+42	1	1
+269	1	0
+284	3	3
+24	1	0
+2796	0	5
+2451	28	0
+2251	1	1
+32	1	0
+10	0	4
+24	1	1
+694	0	2
+3475	0	1
+2008	1	1
+49	1	1
+475	1	1
+28	1	1
+259	160	0
+1858	1	0
+1621	3	0
+1791	1	0
+316	0	2
+1169	0	1
+2549	1	0
+2941	1	1
+34	1	1
+243	9	0
+5157	0	2
+1748	0	8
+472	4	0
+2470	0	4
+402	1	0
+643	2	0
+748	0	2
+859	1	0
+409	2	0
+267	0	2
+322	0	4
+155	1	0
+9957	0	4
+1440	4	4
+127	1	0
+1085	1	0
+131	1	0
+767	1	0
+1160	21	21
+1294	1	0
+712	1	0
+1819	2	1
+464	1	0
+6944	0	4261
+55	0	7
+1235	0	3
+702	0	24
+2847	0	1
+2428	3	0
+7517	0	1
+3204	1	0
+611	1	0
+7104	1	0
+4959	14	14
+2827	1	0
+9421	82	25
+4428	8	0
+5987	41	41
+2108	0	2
+344	1	0
+4216	1	0
+810	0	5
+4443	1	0
+10291	10	0
+7265	5	0
+7041	1	0
+6007	1	0
+8185	4	0
+4961	0	3
+13564	0	1
+1475	0	2
+105	0	10
+10104	2	0
+3073	1	0
+3715	8	0
+2246	24	24
+11461	0	2
+837	61	1
+7660	39	39
+1705	0	1
+6068	7	0
+916	0	4
+569	1	1
+72	1	1
+2260	0	2
+7036	4	0
+3591	0	3
+713	4	0
+7058	11	11
+3319	0	2
+8475	0	1
+1324	0	2
+5438	5	0
+156	1	1
+44	0	1
+21501	7	7
+3359	16	16
+2138	0	5
+4406	11	11
+1525	1	1
+28	1	1
+2159	16	0
+48	4	0
+3030	0	1
+5717	10	0
+6594	2	0
+648	31	31
+1275	1	0
+4	1	0
+3599	1	0
+7515	4	0
+979	0	2
+1990	0	10
+123	1	1
+27	1	1
+1255	0	2
+2769	5	5
+727	1	1
+26	3	3
+785	0	1
+8871	29	29
+15459	1	0
+5978	5	5
+66	1	1
+46	1	1
+18539	1	0
+7732	2	0
+652	0	1
+861	0	1
+10658	17	17
+1313	0	1
+3515	3	0
+19	18	0
+539	0	1
+655	2	0
+10586	2	0
+2385	0	1
+7589	1	0
+29834	1	1
+27	1	1
+1216	1	0
+1323	1	0
+673	0	3
+20031	0	3
+2841	13	0
+1841	4	0
+6446	1	0
+11727	0	1
+8427	17	17
+2864	0	143
+4107	0	8
+748	0	2
+3417	1	1
+32	1	1
+18799	0	2
+21810	1	1
+34	1	1
+2784	2	0
+7864	2	0
+4498	0	1
+49089	1	1
+32	1	1
+509	1	1
+37	1	1
+5371	22	16
+389	1	1
+21	1	1
+806	1	0
+1638	6	6
+228	1	1
+45	1	1
+2068	6	3
+441	1	0
+2338	1	0
+1948	1	1
+26	1	1
+214	0	1
+6118	1	1
+31	1	1
+2382	5	5
+4335	1	1
+39	1	1
+4561	1	1
+38	1	1
+2199	1	1
+49	1	1
+243	19	6
+2779	1	1
+37	2	0
+24	1	1
+1966	3	0
+233	1	1
+29	1	1
+13756	0	4
+3956	4	1
+33765	46	46
+12758	1	0
+18985	0	8
+1384	3	1
+85	1	0
+3539	1	1
+32	1	1
+145	1	0
+1245	2	0
+1736	80	80
+1607	1	5
+712	10	11
+502	0	1
+3670	1	0
+740	0	1
+1693	0	1
+6497	0	2
+2898	1	3
+141	0	1
+1108	0	2
+1448	1	0
+1340	0	1
+7616	74	66
+2882	1	2
+30	8	0
+896	21	3
+395	1	1
+37	3	0
+23	1	2
+1210	18	0
+65	1	1
+20	1	1
+791	0	4
+389	1	0
+809	1	1
+55	0	7
+428	1	1
+17	1	1
+239	1	1
+20	1	1
+69	1	1
+37	1	1
+955	1	0
+839	0	1
+165	1	0
+3867	0	5
+70	1	1
+27	1	1
+899	1	2
+107	1	0
+1457	1	0
+763	12	5
+35	1	1
+1417	10	10
+121	1	1
+38	0	3
+377	1	0
+325	2	2
+178	1	0
+11	4	0
+297	0	24
+337	11	0
+134	1	1
+694	3	0
+72	1	1
+144	1	1
+96	1	1
+199	2	0
+1011	1	0
+107	1	1
+1280	1	1
+73	1	1
+84	25	25
+287	1	1
+26	1	1
+139	1	1
+41	1	1
+440	4	0
+130	12	12
+435	21	0
+85	1	1
+28	1	1
+73	1	1
+61	1	1
+53	5	1
+70	1	2
+52	2	0
+157	30	30
+554	2	2
+128	1	5
+68	1	1
+44	1	1
+125	0	1
+57	1	1
+308	0	7
+15	1	1
+725	9	0
+60	1	1
+180	1	1
+55	1	1
+61	1	1
+23	1	0
+5	1	2
+88	1	1
+56	1	1
+433	2	0
+84	68	68
+182	12	12
+216	1	1
+94	1	1
+561	1	1
+16	1	1
+113	1	1
+86	1	1
+148	2	0
+75	2	0
+77	1	21
+209	3	8
+374	1	0
+173	4	3
+201	1	1
+42	1	1
+56	1	1
+115	1	0
+327	1	1
+54	5	5
+929	1	1
+21	1	1
+97	1	1
+28	0	3
+830	0	2
+68	1	1
+525	0	1
+2081	1	1
+41	1	1
+165	3	3
+46	1	0
+378	1	1
+49	1	1
+352	0	1
+142	1	1
+30	1	1
+95	1	1
+45	1	1
+227	1	1
+53	1	1
+130	1	1
+18	1	1
+138	1	1
+90	1	1
+129	41	41
+50	1	1
+79	1	1
+117	1	1
+31	1	1
+240	5	5
+57	1	1
+152	1	1
+30	1	1
+177	5	5
+321	1	1
+63	1	1
+504	18	18
+662	1	1
+74	1	1
+248	1	1
+34	1	1
+1507	0	10
+1051	0	2611
+560	3	3
+23	1	1
+1631	0	15
+78	4	0
+160	0	21
+3764	0	4
+1358	0	1
+1773	1	1
+43	1	1
+1263	1	1
+39	1	1
+183	0	16
+4097	10	0
+1261	1	1
+20	1	1
+137	1	0
+2351	1	1
+43	1	1
+1010	0	4
+536	1	1
+38	1	1
+381	0	1
+888	19	19
+1521	1	1
+27	1	1
+161	1	1
+46	1	1
+2659	2	0
+533	10	0
+441	1	12
+1684	1	1
+26	3	4
+879	16	16
+514	0	2
+58	1	1
+117	1	1
+24	1	1
+207	1	0
+38	1	1
+730	1	1
+39	1	1
+429	10	10
+134	0	4
+37	1	1
+144	8	8
+1036	2	0
+262	2	2
+38	0	1
+70	18	18
+84	11	13
+317	0	3
+1256	0	2
+332	1	1
+21	1	1
+193	8	28
+30	1	1
+79	1	1
+29	1	1
+536	1	0
+611	1	1
+25	1	1
+399	4	4
+118	0	32
+23	1	1
+116	1	1
+30	1	1
+503	1	1
+22	0	3
+136	1	1
+48	1	1
+330	9	9
+1108	1	1
+98	1	1
+582	0	4
+711	7	7
+89	1	0
+293	7	6
+159	1	1
+24	1	1
+167	6	6
+171	17	17
+681	1	1
+43	1	1
+538	1	1
+44	1	1
+537	16	16
+180	6	6
+778	2	2
+44	1	1
+168	0	7
+211	1	1
+42	1	1
+1253	1	1
+29	1	1
+320	1	1
+36	2	2
+55	1	2
+460	1	1
+35	1	1
+553	8	8
+386	1	1
+26	1	1
+540	1	1
+31	1	1
+65	0	1
+625	12	12
+313	0	1
+52	1	1
+22	1	1
+583	1	1
+49	1	1
+678	37	37
+784	3	0
+770	1	1
+87	11	0
+1129	1	1
+36	1	1
+553	8	8
+997	16	15
+157	1	1
+31	2	2
+204	18	19
+487	1	1
+29	1	1
+374	1	1
+67	1	1
+720	13	13
+266	10	10
+330	16	14
+413	1	1
+44	1	1
+78	6	6
+181	2	2
+36	1	1
+397	1	1
+20	1	1
+311	1	1
+48	2	2
+1298	11	11
+437	4	4
+35	1	1
+194	10	10
+310	1	1
+51	1	1
+136	1	1
+49	1	1
+521	1	1
+23	1	1
+220	1	1
+71	1	1
+1046	15	15
+216	1	1
+21	1	1
+51	1	1
+49	1	1
+527	17	17
+340	12	11
+1025	1	0
+2572	1	1
+29	1	1
+397	2	5
+668	13	13
+541	1	1
+59	0	2
+6	1	1
+122	14	14
+51	1	1
+46	1	1
+72	5	5
+352	0	21
+136	1	1
+12	1	1
+66	16	16
+456	37	34
+371	7	7
+48	1	1
+194	10	10
+108	1	1
+60	1	1
+122	0	1
+48	1	1
+238	1	1
+32	0	1
+100	1	0
+72	1	0
+390	1	1
+38	1	1
+144	1	1
+27	0	4
+184	21	228
+49	1	1
+608	0	1
+152	1	1
+31	1	1
+281	8	8
+337	1	1
+45	1	1
+222	1	1
+20	1	1
+380	1	0
+44	1	1
+368	1	1
+72	1	1
+502	36	18
+63	1	1
+43	0	4
+136	1	1
+42	1	1
+80	4	4
+35	1	0
+89	1	1
+24	0	5
+829	13	13
+102	14	0
+233	1	1
+42	0	3
+85	0	1
+400	1	1
+40	1	1
+538	25	25
+174	1	1
+20	1	1
+705	1	1
+26	2	2
+614	1	1
+44	1	1
+509	1	1
+32	1	1
+224	1	1
+42	1	1
+747	5	5
+804	1	1
+29	1	1
+166	1	1
+43	1	1
+233	1	1
+44	1	1
+620	8	8
+133	1	1
+31	1	1
+165	1	1
+29	1	1
+1249	1	1
+26	4	0
+56	1	1
+67	1	1
+716	1	1
+46	0	1
+16	1	1
+174	1	1
+96	1	1
+141	1	1
+39	0	4
+263	1	1
+18	1	1
+259	4	4
+38	1	1
+104	1	1
+40	1	0
+248	1	1
+18	1	1
+238	1	1
+32	1	1
+70	0	2
+16	1	1
+818	1	1
+22	4	4
+1641	1	1
+46	1	1
+53	1	0
+38	1	1
+373	1	1
+60	1	1
+1149	0	2
+19	1	1
+1653	4	4
+42	1	1
+218	12	12
+363	1	1
+24	1	1
+457	10	10
+414	13	13
+825	1	1
+41	1	1
+492	0	8
+1370	1	1
+18	1	1
+808	2	2
+335	6	4
+880	1	1
+35	1	1
+236	1	1
+67	1	1
+298	0	1
+147	4	4
+322	11	11
+613	1	1
+62	1	1
+340	1	1
+22	1	1
+1057	1	1
+57	1	1
+358	1	1
+128	1	1
+146	10	10
+490	1	1
+20	1	1
+62	1	1
+88	1	1
+293	1	1
+28	1	0
+20	1	1
+83	0	1
+90	1	1
+312	1	1
+44	1	1
+1213	1	1
+51	1	1
+467	1	1
+39	1	1
+122	14	0
+35	1	1
+485	14	14
+110	13	0
+127	1	1
+7150	9	13
+3278	0	2
+28	1	1
+2211	1	0
+1325	18	18
+1304	3727	0
+299	0	248
+2603	2	0
+160	1	1
+34	1	1
+631	1	1
+40	1	3
+38	1	1
+332	17	17
+231	14	14
+202	1	1
+199	1	1
+71	1	1
+42	1	0
+53	11	10
+82	34	34
+135	1	1
+50	3	0
+32	1	1
+194	1	1
+45	1	1
+143	1	1
+78	1	1
+193	6	0
+40	1	1
+432	1	1
+17	1	1
+429	3	6
+58	1	1
+85	1	1
+62	1	1
+85	1	1
+57	1	1
+51	2	2
+278	1	1
+49	1	1
+77	11	11
+120	0	4
+139	1	1
+30	2	2
+205	4	4
+131	1	1
+22	1	1
+251	1	1
+34	1	1
+175	1	1
+36	1	1
+239	1	1
+32	5	5
+63	1	1
+27	1	1
+78	1	1
+19	1	1
+209	1	1
+143	1	13
+176	0	1
+7	0	8
+375	0	1
+62	1	1
+129	2	2
+135	1	1
+88	8	0
+90	6	8
+796	2	0
+1219	1	1
+34	1	1
+833	1	1
+46	1	1
+74	1	1
+45	1	1
+95	1	1
+29	1	1
+298	0	3
+47	1	1
+311	1	1
+58	1	1
+349	15	15
+208	1	1
+37	3	0
+413	11	11
+54	1	1
+97	1	1
+137	0	2
+95	1	1
+257	3	0
+35	1	1
+66	1	1
+47	1	1
+104	7	7
+220	17	17
+228	4	4
+432	1	1
+34	3	3
+175	4	4
+26	1	2
+116	7	7
+60	13	13
+137	1	1
+44	1	1
+744	1	1
+29	1	1
+148	0	5
+30	1	1
+387	1	1
+22	1	1
+309	1	1
+82	1	1
+52	1	1
+32	1	1
+121	1	1
+37	1	1
+396	3	2
+324	1	1
+92	1	1
+51	9	9
+71	7	7
+24	1	1
+115	1	1
+101	1	1
+799	12	12
+197	1	1
+146	1	1
+103	1	1
+134	1	1
+16	1	1
+378	1	1
+85	1	1
+134	1	1
+25	1	1
+54	3	3
+55	1	1
+67	1	1
+22	1	1
+54	13	13
+55	11	11
+120	1	1
+23	1	1
+51	1	1
+22	1	1
+369	1	1
+273	1	1
+119	6	6
+229	34511	40178
+78	1	1
+22	1	1
+180	1	1
+33	1	2
+26	6	6
+474	1	1
+36	1	1
+151	1	1
+29	1	1
+120	1	1
+23	1	1
+865	1	1
+39	1	1
+330	1	1
+24	1	1
+197	1	1
+69	1	1
+116	3	0
+161	1	1
+38	1	1
+753	1	1
+57	3	3
+145	1	1
+121	1	1
+300	1	1
+147	1	1
+379	1	1
+55	2	2
+65	1	1
+32	1	1
+1008	1	1
+24	1	1
+159	18	18
+659	1	1
+76	0	2
+77	1	3
+65	1	1
+84	1	0
+119	1	1
+15	1	1
+247	4	0
+372	1	0
+1633	1	1
+16	1	1
+221	9772	11561
+315	1	1
+53	1	1
+67	1	1
+91	1	0
+23	1	0
+27	2	2
+66	2	2
+80	0	41
+12	1	1
+158	1	0
+92	2	0
+254	1	1
+43	1	1
+846	6	149
+84	1	1
+29	3	3
+315	17	17
+482	1	1
+29	3	3
+278	1	1
+73	1	1
+2767	1	1
+34	1	1
+192	1	1
+33	1	0
+168	6	0
+276	10	10
+344	1	1
+49	1	1
+109	1	1
+35	3	3
+561	24	27
+923	1	1
+102	1	1
+75	14	14
+266	1	1
+80	2	2
+185	1	0
+1035	1	1
+23	1	1
+417	10	10
+97	1	1
+94	1	1
+492	1	1
+37	5	5
+1429	1	1
+19	1	1
+839	1	1
+96	1	1
+1279	4	0
+683	1	1
+49	1	1
+514	1	1
+28	4	4
+2302	1	1
+42	1	1
+537	2	21
+1555	1	1
+42	0	1
+14	4	4
+86	1	1
+62	1	1
+515	5	1
+330	0	1
+159	0	22
+3841	1	0
+5065	12	12
+97	0	3
+772	1	1
+21	2	1
+1058	0	2
+349	2	0
+1080	6	0
+11	1	3
+53	0	2
+14	1	1
+1035	1	1
+85	1	1
+69	1	1
+27	1	1
+547	7	7
+195	1	1
+41	1	1
+395	1	1
+35	1	1
+73	0	1
+71	1	1
+557	3	3
+30	1	1
+66	49	49
+1310	0	2
+26	2	0
+10	1	15
+36	1	1
+196	1	1
+40	1	1
+141	1	1
+76	1	1
+1480	1	3
+347	1	1
+26	1	1
+231	1	1
+82	3	3
+69	3	0
+441	16	16
+147	1	1
+21	1	1
+3565	0	3
+877	2	0
+1036	1	1
+47	2	1
+3761	12	0
+5345	1	0
+11541	1	0
+1843	0	4
+1157	16	16
+7354	19	0
+736	0	1
+8058	1	0
+4449	21	21
+649	1	0
+2913	0	1
+381	331	0
+6066	0	1
+1968	7	0
+3198	1	0
+667	1	0
+3870	0	1
+36	13	0
+1894	1	1
+40	0	4
+1137	6	0
+211	2	0
+345	1	0
+592	4	4
+1043	4	0
+686	14	0
+1032	0	1
+9035	0	4
+167	0	2
+19472	35	35
+4457	0	3
+1470	0	1
+289	3	0
+3780	41	41
+522	1	0
+2026	8	0
+430	0	1
+631	1	1
+21	1	1
+479	0	1
+697	4	0
+1779	1	1
+27	1	1
+196	4	0
+58	8	0
+2881	1	1
+39	1	1
+120	44	45
+538	1	0
+393	6	6
+3090	1	1
+43	1	1
+1246	1	0
+294	1	1
+27	1	1
+374	3	3
+144	1	1
+190	1	6
+750	1	0
+695	2	0
+1003	11	0
+1185	8	8
+763	0	4
+2737	11	11
+453	1	0
+536	1	1
+43	1	1
+57	1	0
+21	7	0
+3892	0	1
+3177	0	1
+8990	0	2
+2303	1	0
+2850	4	0
+1273	0	2
+5863	1	0
+9593	1	1
+81	1	1
+2777	0	2
+4564	34	34
+674	0	8
+11548	2	0
+6086	0	1
+109	1	1
+2286	0	1
+997	0	18
+3344	1	1
+40	1	1
+842	28	24
+1584	1	0
+1582	0	1
+1670	3	25
+17	0	4
+16	2	0
+6	12	0
+49	1	1
+538	1	1
+26	1	1
+5879	2	4
+2513	0	1
+346	8	8
+222	16	16
+103	1	0
+198	1	3
+539	1	1
+47	1	1
+1154	0	1
+3737	1	2
+370	2	0
+1178	1	1
+78	1	1
+47	0	1
+518	6	0
+646	13	13
+469	1	0
+1072	1	4
+858	1	0
+3674	1	0
+282	1	0
+597	0	6
+505	4	4
+183	1	1
+43	1	1
+1294	1	1
+40	1	1
+572	0	4
+464	0	4
+757	40	40
+1089	2	0
+548	1	0
+1300	0	3
+1839	2	0
+189	1	1
+49	1	1
+1253	1	1
+43	1	0
+498	1	1
+45	4	0
+3538	0	1
+1989	14	14
+1332	2	0
+3586	1	0
+989	1	2
+447	0	4
+40	1	1
+2445	16	17
+291	1	3
+7	1	0
+11	0	1
+41	1	1
+94	1	1
+49	1	1
+1515	6	0
+603	13	13
+163	1	1
+45	1	1
+2050	11	11
+1126	1	1
+16	1	1
+391	1	1
+19	0	1
+932	1	0
+42	1	1
+751	1	0
+287	1	1
+42	1	1
+464	0	4
+4069	5	5
+153	1	0
+514	2	0
+1093	1	1
+41	1	1
+1746	4	4
+1351	1	1
+38	1	1
+682	12	12
+519	0	72
+168	18	18
+146	7	7
+293	1	1
+61	0	1
+43	1	1
+236	1	0
+35	1	1
+152	14	14
+776	0	4
+809	4	0
+155	1	1
+44	1	1
+1068	1	1
+93	1	1
+209	15	15
+1331	0	3
+3912	0	1
+6624	0	4
+375	0	1
+7255	5	0
+419	2	0
+293	1	0
+10397	5	24
+11095	0	1
+1770	4	0
+374	0	4
+7714	1	0
+1229	7	6
+3055	1	0
+5818	1	0
+2415	11	9
+2056	0	1
+955	4	0
+3907	0	2
+16936	0	1
+1044	1	0
+2392	0	1
+158	2	1
+199	0	1
+75	6	6
+2094	8	0
+649	2	0
+373	75	75
+2253	1	0
+15	1	0
+1995	0	2
+818	4	0
+676	0	1
+3171	8	0
+170	0	3
+459	1	1
+37	1	1
+336	1	0
+206	1	1
+26	1	1
+224	15	15
+308	2	1
+82	1	1
+23	1	1
+562	1	1
+80	1	1
+241	0	8
+1530	1	1
+20	1	1
+1372	1	1
+44	1	1
+427	1	1
+20	1	1
+651	105	81
+221	1	1
+45	1	1
+1747	1	1
+27	1	1
+179	1	1
+70	1	1
+173	1	1
+84	0	36
+1864	1	1
+41	1	1
+44	9	0
+1028	1	0
+85	1	1
+21	1	1
+475	0	2
+256	1	1
+31	1	1
+653	1	1
+18	1	1
+62	1	1
+19	1	1
+997	1	1
+22	1	1
+326	1	0
+505	5	4
+386	0	7
+466	13	13
+870	11	12
+134	15	15
+248	0	2
+2281	1	1
+79	1	1
+56	9	6
+498	100	100
+802	1	0
+290	1	1
+38	1	1
+185	1	1
+61	1	1
+944	1	1
+22	1	1
+835	1	1
+66	1	1
+890	0	1
+3503	6	6
+231	0	1
+2136	1	0
+999	1	0
+5220	3	4
+830	1	1
+24	1	1
+1209	1	1
+38	1	1
+7077	1	0
+2939	1	0
+3959	0	2
+3746	0	2
+1011	1	1
+34	1	1
+7443	0	1
+688	2	0
+574	1	1
+29	1	1
+1785	2	0
+16	20	0
+4073	2	0
+136	1	1
+77	1	1
+528	27	0
+253	0	1
+204	1	0
+129	2	0
+811	1	1
+38	1	1
+2347	52	0
+4634	1	0
+856	14	14
+1052	1	1
+28	1	1
+1255	1	1
+36	1	1
+97	0	1
+58	1	1
+1708	1	1
+48	1	1
+958	13	0
+3371	1	1
+37	1	1
+4267	0	15
+1059	0	1
+272	0	20
+168	2	0
+26	4	32
+4090	0	2
+3269	1	1
+17	1	2
+1378	1	0
+1443	0	1
+6206	1	0
+2318	0	1
+7695	2	0
+396	22	12
+918	0	1
+1818	0	1
+28	1	1
+492	1	1
+33	1	1
+326	1	1
+80	1	1
+288	8	17
+2671	0	1
+1099	0	1
+144	1	1
+29	0	1
+2098	0	2
+24	4	0
+1207	4	4
+45	1	1
+757	0	5
+1926	1	1
+40	1	1
+2657	0	1
+414	1	0
+61	0	1
+235	0	2
+2087	0	1
+713	0	4
+58	1	0
+1041	3	0
+36	1	1
+377	1	1
+17	1	1
+948	1	1
+41	1	1
+458	1	1
+21	1	1
+1055	0	1
+8189	4	5
+36	1	1
+102	2	0
+14	1	1
+682	0	6
+147	0	1
+750	0	3
+40	1	1
+2428	0	1
+750	2	0
+473	0	2
+2032	1	0
+3841	1	0
+560	1	0
+1108	1	0
+8087	1	0
+11881	1	1
+30	1	1
+4383	2	0
+6883	49	49
+3146	0	1
+906	2	0
+887	1	1
+80	1	1
+2210	1	0
+905	0	1
+1037	1	0
+5866	0	2
+18	1	1
+582	0	5
+2828	1	0
+847	1	0
+1996	4	0
+3170	1	0
+1751	0	1
+910	2	0
+691	0	1
+32873	0	1
+1722	0	1
+17559	16	24
+1369	29	0
+494	2	0
+4432	0	1
+23680	26	26
+10911	0	1
+920	0	1
+4586	0	2
+2232	1	0
+5718	0	1
+12415	1	1
+51	0	1
+7997	0	2
+1700	1	0
+2697	1	0
+2561	2	0
+1544	0	6
+1613	3	7
+37	9	1
+2113	1	0
+7174	0	34
+7914	1	1
+35	1	1
+5308	1	0
+2303	2	1
+423	7	7
+590	1	0
+24	1	1
+165	6	0
+2848	13	13
+64	0	1
+28	1	1
+723	0	4
+2868	0	1
+731	1	1
+60	1	1
+1012	3	0
+490	29	29
+1225	1	1
+78	1	1
+61	1	0
+2362	11	11
+399	1	0
+1494	16	16
+128	24	24
+530	1	1
+35	1	1
+5276	1	0
+415	0	1
+580	1	2
+1450	22	23
+816	1	0
+1953	1	0
+881	10	1
+885	8	14
+183	14	14
+1139	25	25
+155	1	1
+94	1	1
+419	3	3
+26	1	1
+56	1	0
+69	1	0
+117	1	1
+120	1	1
+42	1	1
+825	0	2
+108	1	1
+24	1	1
+956	3	0
+664	1	1
+41	1	1
+716	4	0
+1731	8	8
+4228	0	1
+5694	3	0
+4493	0	1
+2656	1	0
+3029	4	0
+5688	1	0
+170	2	0
+5972	0	2
+840	0	2
+55	1	1
+28	1	1
+2954	0	1
+4343	6	0
+1663	4	0
+150	1	0
+3128	1	0
+1449	3	0
+1534	1	0
+489	1	0
+431	0	4
+299	2	0
+5082	9	0
+413	0	1
+989	0	2
+4941	0	1
+6655	1	0
+349	8	7
+762	1	1
+29	0	3
+1434	0	1
+1267	0	1
+587	1	1
+22	0	1
+894	28	0
+1343	2	0
+2256	0	1
+4332	0	4
+22	1	1
+12415	12	10
+10485	0	1
+1429	0	12
+625	1	7
+1224	0	10
+1680	4	0
+5169	14	14
+3878	0	8
+2544	0	140
+9238	0	1
+1575	0	3
+1775	1	1
+31	1	1
+1200	1	0
+32	0	3
+797	0	8
+35	0	2
+599	1	1
+22	1	1
+5338	2	0
+1998	0	5
+146	0	4
+12031	0	1
+1993	0	1
+706	2	0
+2735	0	1
+3859	0	4
+4845	0	2
+268	2	0
+827	4	4
+1063	6	6
+7834	2	0
+3195	0	1
+4012	10	0
+6429	0	2
+308	0	1
+808	1	0
+17	8	0
+5472	19	2
+2436	0	14
+820	9	9
+2643	1	1
+32	1	1
+1189	1	0
+5710	0	3
+308	1	0
+4930	0	1
+4308	1	0
+946	82	0
+1790	0	2
+1218	25	0
+52	0	1
+1271	1	1
+33	1	1
+4760	1	0
+4924	0	1
+4817	4	4
+39	1	0
+1116	3715	901
+205	1	0
+1591	5	2
+138	2	2
+16	1	1
+802	0	89
+1600	0	6
+2175	0	5
+606	14	14
+519	1	0
+540	1	1
+40	1	1
+568	2	0
+458	1	1
+41	1	1
+1106	24	62
+818	1	1
+42	1	1
+2266	1	0
+14059	0	4
+5030	1	0
+12630	0	3
+84	9	9
+129	13	18
+564	10	15
+154	1	0
+438	10	10
+38	0	5
+98	11	9
+2034	1	1
+25	1	1
+73	10	10
+70	5	5
+132	1	1
+52	1	1
+599	1	1
+46	1	1
+279	1	1
+18	1	1
+239	3	0
+383	6	0
+224	0	1
+321	15	0
+1783	1	1
+18	3	0
+108	1	1
+60	1	1
+405	16	16
+60	1	1
+16	1	1
+970	1	1
+24	1	1
+424	3	0
+41	1	1
+57	8	8
+285	2	0
+672	1	1
+44	1	4
+103	0	1
+148	1	1
+49	3	0
+146	5	11
+91	1	1
+79	1	1
+94	1	1
+101	1	1
+88	16	16
+117	1	1
+15	1	1
+58	1	1
+93	1	1
+466	1	1
+44	1	1
+160	1	1
+23	1	1
+481	14	14
+181	4	4
+72	1	1
+25	1	1
+82	7	12
+4	0	1
+11	1	4
+20	0	5
+92	1	1
+56	10	0
+80	1	1
+141	2	0
+60	1	1
+372	0	2
+784	1	1
+85	1	1
+109	1	1
+16	1	1
+57	1	1
+92	3	1
+23	1	0
+26	1	1
+74	1	1
+33	1	1
+176	1	1
+25	2	2
+193	1	1
+35	0	1
+383	0	5
+249	1	1
+69	1	1
+98	1	1
+70	1	1
+55	1	1
+143	1	1
+438	1	1
+64	1	1
+53	4	0
+127	3	0
+75	5	5
+45	1	1
+197	1	1
+27	1	1
+116	13	13
+218	15	20
+1107	16	19
+73	1	1
+101	1	1
+123	1	1
+60	1	1
+994	1	1
+43	0	1
+18	1	1
+1215	18	18
+340	1	1
+34	1	1
+1350	16	16
+1417	1	1
+29	1	1
+475	1	1
+48	1	1
+198	10	10
+87	1	1
+18	1	1
+171	7	7
+427	1	1
+21	1	1
+2011	0	3
+17	1	1
+1412	1	1
+24	1	1
+214	8	4
+228	1	1
+34	1	1
+410	16	16
+185	1	1
+24	1	0
+164	0	1
+222	1	1
+25	1	1
+297	10	10
+1171	1	0
+569	19	19
+2755	1	0
+11	1	1
+2502	1	1
+23	1	1
+44	12	0
+2856	0	1
+148	1	1
+36	1	1
+993	2	0
+1251	2	0
+6619	14	14
+1014	4	0
+134	2	9
+818	1	0
+61	1	7
+563	46	0
+78	5	5
+1677	1	1
+49	1	1
+399	1	1
+32	1	1
+790	27	27
+104	1	1
+75	1	1
+1638	1	1
+16	1	1
+92	1	1
+44	1	1
+276	0	13
+1020	1	1
+35	1	1
+389	14	14
+256	1	0
+38	1	3
+631	1	1
+40	1	1
+2356	85	83
+1300	0	5
+511	0	2
+605	1	1
+17	1	1
+880	12	0
+1689	4	0
+2492	1	1
+39	1	1
+641	16	16
+682	0	5
+669	1	1
+25	1	1
+1926	1	1
+39	4	3
+1037	1	1
+40	2	0
+890	6	0
+41	2	0
+498	3	0
+321	0	1
+281	3	0
+450	1	1
+34	1	1
+498	1	1
+28	2	1
+280	0	2
+648	1	1
+47	1	1
+1002	4	0
+120	1	1
+1538	0	1
+75	1	1
+37	1	1
+510	91	91
+60	18	18
+2075	1	1
+19	1	1
+2429	1	1
+21	1	1
+107	1	0
+2786	0	2
+31	5	5
+1973	12	0
+3118	1	0
+246	0	1
+33	1	1
+6752	1	0
+822	2	9
+606	1	1
+18	1	1
+3920	1	1
+37	0	2
+4497	10	13
+301	20	20
+2130	1	1
+16	3	0
+1843	0	4
+3780	3	0
+850	0	1
+2774	0	3
+2065	0	1
+20	1	1
+1400	1	0
+3243	0	15
+1336	5	0
+448	49	49
+121	7	7
+1507	8	7
+422	1	0
+2184	0	1
+304	0	2
+19	0	1
+101	1	1
+417	3	3
+22	1	1
+672	4	4
+31	1	1
+150	1	1
+38	1	1
+161	5	0
+17	1	1
+72	1	0
+106	1	1
+463	1	1
+94	1	1
+138	3	4
+185	1	1
+29	1	1
+220	15	15
+167	1	1
+32	1	1
+93	1	3
+217	1	1
+23	1	1
+137	9	9
+62	0	3
+353	1	1
+27	1	1
+117	9	9
+421	1	1
+47	1	1
+124	0	1
+997	6	0
+54	5	5
+764	1	1
+45	1	1
+1431	7	7
+387	6	6
+1103	0	36
+767	1	1
+31	1	3
+208	5	5
+1610	1	1
+23	1	1
+779	0	8
+324	0	2
+45	1	1
+264	0	3
+45	1	1
+250	1	1
+18	1	1
+517	33	0
+117	1	1
+42	1	1
+550	1	1
+20	1	1
+671	1	1
+68	1	1
+89	1	1
+104	1	1
+172	0	1
+124	0	1
+522	0	1500
+466	5	5
+32	1	0
+171	1	1
+19	1	1
+67	1	1
+22	1	1
+654	1	1
+25	1	1
+68	1	1
+21	4	0
+1588	1	1
+66	1	1
+401	0	1
+186	1	1
+21	1	1
+168	0	1
+686	3	0
+19	1	1
+127	1	1
+29	1	1
+234	1	1
+30	1	1
+141	0	2
+33	1	1
+673	1	1
+89	1	1
+161	16	16
+504	20149	20139
+1269	1	1
+40	1	1
+327	1	1
+24	1	1
+172	2	2
+27	11	15
+381	10	11
+376	1	1
+45	1	1
+121	1	1
+62	1	1
+289	1	1
+26	1	1
+191	1	1
+20	11	11
+425	1	1
+37	1	1
+296	1	1
+149	1	1
+284	1	1
+37	1	1
+705	1	12
+106	12	12
+306	1	1
+24	1	1
+1299	1	1
+47	1	1
+2026	1	1
+20	1	1
+133	1	0
+9803	0	4
+15871	3	0
+2464	1	1
+24	1	1
+879	1	1
+73	1	1
+89	1	1
+42	1	1
+108	1	1
+43	0	1
+26	1	1
+511	5	6
+605	19531	20105
+55	1	1
+37	0	2
+89	1	1
+51	1	1
+85	1	1
+78	1	1
+173	1	1
+51	1	1
+90	3	3
+95	1	1
+32	1	1
+53	1	1
+231	1	0
+82	2	0
+27	0	1
+44	1	0
+96	10	7
+132	1	1
+233	1	1
+257	1	1
+56	5	5
+237	1	1
+141	1	1
+92	1	1
+154	7	7
+3208	1	1
+33	1	1
+671	1	1
+21	1	1
+955	0	3
+130	1	1
+26	1	1
+288	8	8
+218	0	3
+1076	8	0
+609	10041	10021
+240	2	2
+66	1	1
+228	1	1
+23	1	1
+1612	1	1
+21	1	1
+261	1	1
+99	1	1
+128	1	1
+15	1	1
+77	9	9
+618	8	8
+84	4	6
+438	1	1
+140	1	1
+158	4	3
+277	12	12
+165	4	4
+36	1	1
+253	1	1
+59	1	1
+910	0	1
+915	4	5
+276	15	15
+682	1	1
+28	1	1
+1483	13	13
+203	1	0
+52	1	1
+48	1	1
+229	12	12
+68	15	15
+83	1	1
+39	1	1
+194	1	1
+24	1	1
+251	8	8
+619	0	4
+15	1	1
+690	1	1
+28	1	1
+54	0	1
+463	1	1
+30	1	1
+449	1	1
+54	1	1
+58	5	5
+979	1	0
+318	1	1
+28	1	1
+898	10	10
+100	1	1
+22	1	1
+446	1	1
+74	1	1
+273	1	1
+19	1	1
+333	1	1
+44	1	1
+220	1	1
+56	2	0
+209	1	1
+70	1	1
+223	0	20
+220	1	1
+31	1	1
+56	1	1
+111	1	1
+220	1	1
+89	1	1
+119	1	1
+113	2	0
+195	1	1
+46	1	1
+184	1	1
+60	0	4
+76	0	4
+53	3	1
+43	1	1
+153	1	1
+53	1	1
+195	6	0
+60	1	1
+278	1	0
+42	1	1
+124	10014	10005
+302	1	1
+24	1	1
+135	20	19
+55	1	1
+40	1	1
+175	1	1
+46	1	1
+52	1	1
+19	1	1
+277	1	1
+88	1	1
+172	1	1
+26	1	1
+129	1	1
+35	1	1
+55	9	9
+318	3	3
+46	1	1
+101	8	8
+4653	1	1
+38	1	1
+817	2	0
+256	1	1
+27	1	1
+339	1	1
+48	1	1
+54	10	10
+1393	3	0
+1491	2	0
+1983	16	0
+167	0	4
+3886	7	8
+535	1	1
+16	1	1
+1555	3	0
+3131	1	1
+17	1	1
+4196	1	0
+14974	0	1
+3514	0	4
+29	1	1
+123	0	2
+51	33	0
+121	0	133
+80	1	10
+26	60	4
+52	13	0
+20	0	2
+19	2	0
+22	4	156
+57	156	3
+61	0	2
+29	20	0
+42	11	0
+21	2	0
+50	4	6
+31	1	3
+23	1	53
+25	0	32
+66	1	55
+11	0	2
+13	0	41
+68	1	42
+23	1	3
+12	2	0
+17	1	29
+51	17	13
+18	2	0
+28	2	0
+26	2	0
+158	1	25
+102	0	82
+99	280	0
+53	21	0
+5064	0	2
+7569	2	0
+2189	0	1
+85	1	1
+31	0	4
+399	14	14
+408	0	1
+681	0	5
+184	1	1
+20	1	1
+64	1	1
+29	1	0
+9	2	0
+442	4	0
+342	1	1
+24	1	1
+131	1	1
+198	1	1
+370	0	1
+34	1	1
+447	21	20
+259	1	1
+23	0	1
+121	2	0
+2257	1	1
+22	1	1
+811	1	1
+27	1	1
+95	18	18
+631	0	5
+843	0	2889
+55	0	88
+1189	0	2
+2274	1	0
+752	4	0
+164	1	1
+55	1	1
+1033	10	10
+683	1	1
+57	1	1
+3578	1	1
+34	1	1
+1446	1	0
+460	1	1
+31	0	1
+6	1	1
+163	1	1
+22	1	1
+81	1	1
+27	1	1
+548	1	1
+61	1	1
+1169	1	1
+41	1	1
+1568	14	14
+4889	1	1
+62	1	1
+530	17	17
+394	1	1
+40	7	0
+57	12	12
+69	2	2
+39	1	1
+70	1	1
+22	0	3
+2307	1	1
+30	1	1
+411	1	1
+104	1	1
+375	26	27
+1218	1	1
+35	1	1
+85	1	1
+20	6	0
+687	1	1
+34	1	1
+268	13	13
+74	1	1
+47	2	0
+69	1	1
+49	1	1
+73	1	1
+48	1	1
+218	1	1
+42	1	1
+197	1	1
+41	1	1
+313	1	1
+40	1	1
+476	1	1
+29	1	1
+185	1	1
+35	1	1
+594	1	1
+24	1	1
+220	26	0
+245	0	1
+261	13	13
+89	1	1
+90	1	1
+224	1	1
+201	1	1
+306	1	1
+29	5	5
+121	1	1
+31	1	1
+109	1	1
+25	1	1
+168	1	1
+19	1	1
+93	12	11
+132	1	0
+113	1	1
+30	1	1
+56	9	9
+300	1	1
+50	2	2
+96	1	1
+43	1	1
+76	1	1
+44	1	1
+197	1	1
+91	7	1
+119	0	9
+392	5	5
+89	1	1
+428	11	11
+260	1	1
+23	1	0
+10	1	1
+70	1	1
+65	2	0
+16	0	19
+28	1	1
+208	1	1
+70	1	1
+149	0	3
+51	29	29
+163	1	1
+55	1	1
+63	17	17
+1208	1	1
+98	1	1
+162	1	1
+45	1	1
+148	14	14
+51	5	5
+209	4	4
+1242	1	1
+42	5	0
+87	1	1
+522	0	3
+305	0	1
+1379	0	2
+390	0	15
+72	1	1
+16	1	1
+270	1	0
+280	7	7
+2763	20	20
+674	10	10
+1375	14	0
+327	2	0
+107	1	1
+629	16	16
+54	4	4
+680	16	16
+395	1	1
+42	1	1
+1763	1	1
+46	1	1
+282	1	1
+39	1	1
+860	1	1
+26	1	1
+745	0	2
+2081	2	0
+817	4	4
+202	1	1
+48	1	1
+168	1	1
+53	1	1
+379	10	10
+1178	14	14
+132	5	0
+555	1	1
+65	1	1
+550	1	1
+21	1	1
+462	1	1
+43	1	1
+121	1	1
+48	0	3
+15	1	5
+1404	0	1
+450	4	0
+626	1	0
+304	1	1
+39	1	1
+564	1	1
+45	1	1
+303	2	0
+409	1	1
+18	1	0
+858	2	0
+2168	0	1
+54	1	1
+20	1	1
+524	0	1
+410	10	10
+106	1	14
+2419	18	14
+64	1	1
+31	1	1
+185	0	5
+1646	1	1
+20	1	1
+227	1	1
+37	1	1
+500	1	0
+136	3	4
+8239	1	1
+23	1	1
+1114	0	2
+688	0	1
+901	18	18
+4781	0	4
+815	0	1
+5069	0	5
+415	0	2
+352	0	1
+1085	11	11
+1099	0	1
+991	0	1
+845	1	1
+32	0	2
+5751	0	3
+1553	1	1
+60	1	1
+278	0	1
+30	1	1
+1855	0	2
+958	0	1
+66	0	16
+2109	0	2
+1265	0	1
+17312	0	4
+1875	0	1
+2157	1	0
+915	0	6
+4940	1	0
+2649	0	1
+3331	2	0
+2276	14	0
+3128	0	4
+3496	1	0
+966	0	1
+3597	1	0
+1647	0	3
+1182	1	0
+654	0	3
+2049	1	0
+6838	1	1
+39	1	1
+186	1	0
+2718	1	1
+30	1	1
+160	11	11
+4954	0	1
+420	1	1
+123	1	1
+156	0	4
+219	4	0
+195	1	0
+4402	2	0
+4295	1	0
+4207	20	20
+468	0	1
+30	1	1
+6025	1	0
+4179	1	0
+19834	0	1
+11605	0	1
+4121	2	0
+2863	0	2
+4890	1	0
+5576	0	6
+4104	4	0
+19858	4	0
+1616	0	3
+1647	4	1
+36	0	12
+2213	0	14
+414	0	1
+458	20	20
+2860	0	3
+678	3	4
+292	2	0
+1922	0	1
+913	0	1
+2720	1	0
+1111	3	0
+2589	0	8
+9425	1	0
+1403	0	2
+1964	0	12
+4433	0	1
+1569	0	1
+7209	1	1
+41	1	1
+2257	1	0
+3001	0	1
+1845	1	0
+1593	0	1
+497	0	2
+6109	0	1
+2019	2	0
+921	0	1
+241	1	0
+5473	1	0
+2213	2	0
+1974	8	0
+4952	0	1
+6146	2	0
+953	1	0
+4141	0	1
+4244	5	0
+152	0	2
+209	0	1
+2400	0	10
+785	2	0
+1733	0	1
+554	1	0
+128	0	2
+3051	0	1
+8577	0	1
+1503	0	1
+1705	0	3
+2052	17	17
+998	177	0
+2804	1	0
+1925	1	0
+9215	0	1
+971	8	0
+36021	1	0
+8016	29	27
+3890	0	1
+67913	1	1
+18	1	6368
+73	1	32739
+14676	1	1
+19	1	1
+22867	1	1
+20	1	1
+5638	5	0
+47	12	0
+11313	0	1
+1769	0	1
+8355	0	3
+4114	0	2
+1403	1	0
+5140	0	1
+490	0	1
+219	1	0
+3483	1	0
+8939	1	1
+44	1	1
+10813	0	2
+7480	2	0
+617	1	0
+1464	0	1
+500	0	2
+1466	1	0
+527	5	0
+3593	0	1
+374	0	1
+2946	22	22
+698	0	1
+2149	1	0
+311	2	0
+6570	1	0
+962	1	0
+23	1	1
+2647	4	0
+588	1	1
+21	1	1
+3256	28	20
+870	0	1
+644	1	0
+602	2	1
+3730	1	1
+45	1	1
+12848	7	7
+7306	0	3
+6647	45	45
+1365	1	1
+63	1	1
+4166	1	0
+1887	10	0
+2949	1	1
+31	0	1
+669	1	0
+2190	2	0
+2081	0	2
+373	0	6
+421	4	4
+1460	0	1
+1699	0	8
+2882	2	0
+147	0	1
+1656	1	1
+27	1	1
+1828	0	2
+4066	35	38
+361	17	17
+1254	6	0
+1643	0	2
+2542	0	1
+848	2	1
+2117	0	2
+119	1	1
+44	1	1
+1104	0	1
+415	0	12
+634	18	1
+377	6	7
+227	6	0
+449	13	13
+895	0	17
+457	18	18
+663	0	3
+382	1	1
+26	1	1
+135	0	1
+105	1	1
+25	1	1
+620	2	0
+290	5	5
+375	1	1
+30	0	4
+98	1	0
+20	17	4
+3824	28	0
+39	4	0
+28	4	0
+44	4	0
+1898	9	9
+221	0	2
+10522	30	0
+783	1	1
+59	1	1
+94	1	1
+21	1	1
+491	1	1
+49	1	1
+289	2	0
+120	0	1
+37	1	1
+112	1	1
+21	1	1
+183	16	16
+73	2	0
+1007	1	1
+38	0	1
+79	1	1
+48	1	1
+561	1	1
+29	1	1
+145	5	5
+576	12	12
+834	1	0
+846	5	7
+34	1	1
+417	10	11
+55	1	1
+40	1	1
+110	1	1
+47	1	1
+351	1	1
+69	1	1
+53	1	1
+91	1	1
+260	1	1
+36	0	1
+604	1	0
+169	0	1
+2118	1	1
+34	1	1
+147	1	1
+213	1	1
+67	1	1
+31	1	1
+566	1	0
+17	1	1
+763	1	1
+34	1	1
+671	5	0
+41	2	2
+98	0	1
+449	0	2
+61	1	1
+38	1	1
+202	1	1
+44	1	1
+190	1	0
+46	4	4
+51	0	4
+476	1	1
+17	1	1
+212	1	1
+26	1	1
+485	1	1
+25	1	1
+263	1	1
+26	1	1
+1327	4	0
+44	1	0
+2397	1	1
+44	1	1
+4146	14	14
+901	0	1
+1769	14	14
+1721	1	0
+1125	1	0
+254	1	0
+427	0	1
+30	1	1
+111	0	2
+52	0	8
+528	44	0
+969	1	1
+10	1	0
+28	1	1
+140	1	1
+43	1	1
+1989	2	1
+598	1	1
+87	0	4
+124	1	0
+4840	1	1
+28	7	4
+505	0	2
+24	1	1
+5134	4	0
+543	1	0
+18	1	1
+97	1	1
+29	1	3
+101	6	0
+148	13	7
+1346	0	1
+128	7	0
+49	0	1
+876	2	0
+286	5	5
+184	0	1
+84	5	5
+365	9	9
+981	1	1
+11	1	1
+734	4	0
+563	4	0
+244	9	9
+379	1	1
+17	1	1
+49	2	0
+95	1	1
+30	1	1
+147	1	1
+37	0	6
+340	1	2
+58	1	1
+332	0	2
+233	6	9
+156	0	1
+26	1	1
+439	4	0
+34	0	2
+508	5	0
+96	1	1
+34	1	1
+1267	63	63
+590	1	1
+24	4	5
+1055	13	13
+135	0	1
+194	1	1
+61	1	1
+384	6	6
+2756	1	1
+19	1	1
+99	15	15
+1754	2	3
+2238	1	1
+31	1	1
+3002	4	0
+2156	15	15
+855	14	13
+442	5	5
+2022	6	6
+506	0	2
+1110	0	1
+2578	0	2
+4864	1	1
+36	1	0
+3187	1	1
+16	1	1
+184	1	1
+18	1	1
+1636	0	7
+23	1	1
+527	1	1
+39	1	1
+653	3	0
+227	1	1
+18	1	1
+102	7	7
+109	0	323
+91	1	0
+124	0	15
+621	0	4
+553	12	12
+463	1	1
+40	1	1
+372	1	1
+25	1	1
+188	12	12
+357	0	1
+250	0	5
+4193	0	4
+967	1	1
+76	1	1
+3236	4	4
+529	7	7
+246	4	0
+160	1	1
+34	0	3
+1469	0	2
+499	1	0
+937	1	1
+45	1	1
+356	71	65
+2127	0	1
+491	1	0
+80	1	1
+72	2	0
+255	6	6
+728	14	11
+702	3	0
+290	0	2
+210	19	1
+473	1	1
+42	4	0
+219	0	1
+348	1	1
+83	1	1
+851	0	16
+72	13	0
+246	1	1
+47	4	0
+410	1	0
+93	0	12
+225	0	16
+428	1	0
+4	6	0
+324	0	1
+3060	0	16
+1305	1	1
+29	1	1
+3094	0	7
+600	0	2
+5495	1	1
+47	1	1
+1247	49	55
+4351	1	1
+15	1	1
+2011	6	14
+8378	2	0
+295	0	17
+4583	1	0
+4132	0	4
+924	4	3
+1751	0	2
+1060	12	12
+380	0	2
+425	8	0
+84	0	1
+244	1	1
+28	1	1
+221	4	0
+348	1	1
+37	11	11
+50	1	1
+180	1	1
+348	1	1
+20	1	1
+1714	1	1
+79	1	1
+729	1	1
+44	1	0
+78	1	1
+112	1	1
+23	1	1
+55	9	9
+1044	1	1
+27	1	1
+494	1	1
+32	1	1
+237	1	1
+27	1	1
+1422	4	4
+413	7	1
+710	8	0
+185	0	2
+966	1	0
+13	15	1
+251	1	1
+47	1	1
+285	1	1
+103	1	1
+977	1	1
+41	1	0
+97	1	1
+131	1	0
+307	1	1
+47	1	1
+1070	1	1
+69	1	1
+382	0	1
+167	1	1
+35	1	1
+161	1	1
+30	1	1
+1068	18	0
+1173	1	1
+32	1	1
+59	1	1
+12	1	0
+18	1	1
+55	0	22
+72	1	1
+2806	1	1
+15	1	1
+1395	1	0
+157	13	0
+536	8	8
+101	1	1
+21	1	1
+147	8	8
+638	1	1
+18	1	1
+183	15	15
+990	0	12
+21	1	1
+145	0	1
+332	1	1
+31	1	1
+231	22	5
+39	1	1
+414	9	9
+93	1	1
+63	1	1
+739	0	2
+632	1	1
+74	1	1
+138	5	5
+128	0	1
+294	1	1
+45	1	1
+679	6	6
+1756	0	34
+560	27	27
+1608	5	0
+219	1	1
+134	0	3
+81	1	1
+82	0	1
+357	1	1
+28	1	1
+670	7	9
+270	0	1
+891	13	33
+257	4	0
+80	0	4
+130	2	0
+2504	42	42
+1226	1	1
+44	1	1
+2256	0	1
+80	12	0
+5544	1	0
+428	13	13
+77	4	4
+63	1	1
+64	13	19
+178	10023	10000
+157	3	3
+109	1	1
+180	1	1
+56	1	1
+169	1	0
+93	1	1
+33	2	2
+72	1	1
+30	1	1
+267	25	25
+65	1	1
+19	2	0
+108	27	27
+218	1	1
+37	1	1
+477	11	11
+93	1	1
+30	7	5
+242	0	1
+171	1	1
+29	1	1
+218	0	9
+241	1	1
+55	4	4
+88	1	1
+99	1	1
+57	0	1
+523	12	16
+399	1	1
+50	1	1
+389	1	1
+71	4	4
+173	12	12
+92	1	1
+20	1	1
+132	0	5
+15	1	1
+75	1	1
+26	5	5
+119	11	11
+542	1	1
+23	2	2
+254	1	1
+34	1	1
+172	1	1
+45	1	1
+95	11	11
+127	23	23
+64	1	1
+95	1	1
+390	1	1
+52	1	1
+170	1	1
+16	5	0
+30	1	1
+599	1	1
+119	1	1
+85	1	1
+75	1	1
+286	4	4
+61	1	1
+286	9	9
+429	1	1
+21	1	1
+53	1	1
+44	1	1
+77	165084	190027
+5156	0	1
+1680	1	1
+88	1	1
+4502	0	1
+46	1	1
+800	4	4
+23	1	1
+1305	2	0
+136	0	1
+4941	0	1
+547	0	1
+70	8	8
+293	1	1
+35	1	1
+1165	4	0
+6662	1	1
+121	1	1
+92	0	8
+214	1	1
+35	1	1
+108	1	0
+1063	0	1
+1017	1	1
+20	0	6
+1725	0	1
+150	5	5
+33	1	0
+12	1	1
+349	1	1
+24	0	1
+1562	1	1
+31	1	1
+2513	0	1
+73	36	36
+305	1	1
+27	1	1
+543	1	1
+47	4	28
+4874	0	3
+599	10	10
+137	1	0
+7	0	4
+54	1	1
+2497	1	1
+166	1	1
+637	3	3
+46	1	1
+74	4	4
+414	1	1
+48	1	1
+75	4	4
+153	0	26
+93	1	1
+39	1	0
+58	1	1
+51	1	1
+145	9	9
+29	1	1
+55	1	1
+427	1	0
+141	1	1
+87	1	1
+20	1	1
+89	3	3
+141	18	5
+48	1	1
+87	14	14
+173	1	1
+68	1	1
+54	1	1
+51	4	0
+22	1	0
+52	1	1
+171	1	1
+109	3	1
+6	0	2
+205	1	1
+54	10064	10083
+76	3	1
+197	15	15
+77	1	1
+70	1	1
+178	1	1
+60	1	1
+210	1	1
+28	1	1
+62	1	1
+33	1	1
+70	0	1
+202	1	1
+60	1	1
+106	2	0
+176	1	1
+79	0	1
+50	1	1
+50	3	3
+207	1	1
+272	5	5
+243	1	1
+84	1	1
+98	1	1
+50	5	5
+77	1	1
+74	1	1
+20	0	1
+143	1	1
+45	0	1
+4	1	1
+1088	1	1
+35	1	1
+320	1	1
+22	1	1
+275	1	1
+47	1	1
+370	19	19
+119	1	6
+51	1	1
+21	1	1
+244	0	1
+345	1	1
+24	1	1
+181	1	1
+61	3	3
+542	1	1
+16	1	1
+312	1	0
+353	4	3
+279	323	0
+86	1	1
+49	1	1
+342	1	1
+44	0	2
+222	1	1
+37	1	1
+588	8	8
+593	47	47
+359	1	1
+25	1	1
+2054	1	0
+2510	1	0
+5040	11	12
+1489	9	9
+3292	1	0
+1449	1	1
+21	1	1
+6768	1	0
+706	2	0
+7107	1	1
+38	1	1
+1163	1	1
+35	1	1
+435	1	1
+60	1	1
+325	0	1
+254	1	1
+43	1	1
+210	1	1
+7	1	0
+47	1	1
+130	4	4
+34	1	1
+208	1	1
+39	2	2
+526	1	1
+36	1	1
+99	9	7
+20	1	1
+73	1	1
+62	1	1
+425	1	1
+43	1	1
+811	1	1
+38	1	1
+362	1	1
+49	1	1
+109	1	1
+19	1	1
+79	1	1
+29	0	1
+26	1	1
+252	1	1
+75	1	1
+441	1	1
+66	1	1
+389	13	13
+67	7	7
+1185	0	311
+64	6	6
+389	31	31
+247	1	1
+38	1	1
+79	1	0
+553	1	1
+30	1	1
+433	1	1
+16	3	0
+1133	12	12
+262	5	5
+276	1	0
+960	14	14
+272	1	1
+41	1	1
+196	1	0
+1424	18	19
+314	1	1
+22	1	1
+345	1	1
+23	3	0
+245	1	1
+78	1	1
+77	1	1
+779	1	1
+32	1	1
+247	1	1
+48	1	1
+778	2	0
+226	1	1
+61	1	1
+867	0	1
+53	1	1
+397	1	1
+12	4	0
+46	1	1
+602	1	1
+35	1	1
+422	1	1
+49	1	1
+789	1	1
+37	1	1
+268	0	2
+589	8	8
+366	12	20
+1651	2	7
+19	1	1
+417	1	1
+37	1	1
+812	1	1
+33	3	0
+1351	18	18
+2186	1	1
+86	1	1
+1433	1	1
+39	1	1
+83	0	1
+238	0	1
+171	1	1
+7	2	1
+67	1	1
+596	1	1
+29	1	1
+144	4	6
+417	1	0
+88	1	1
+24	1	1
+390	18	18
+496	14	21
+145	1	1
+46	1	1
+310	1	1
+35	1	1
+214	1	1
+38	1	1
+206	1	1
+37	1	0
+240	1	1
+32	1	1
+469	1	1
+32	1	1
+208	1	1
+21	1	1
+343	1	1
+17	1	1
+88	1	1
+58	6	0
+169	1	1
+22	1	1
+162	0	1
+196	0	2
+500	6	5
+108	1	1
+40	2	0
+50	1	1
+111	1	0
+21	0	1066
+175	5	5
+155	1	1
+44	1	1
+11005	0	1
+6280	1	1
+48	1	1
+1173	1	1
+19	1	1
+2664	0	1
+351	1	0
+1059	14	14
+593	0	1
+869	16	16
+23065	2	0
+2197	0	1
+949	0	1
+15048	0	1
+606	1	0
+7820	0	4
+14669	1	0
+14708	0	1
+16326	0	1
+304	18	18
+388	2	0
+194	1	1
+49	1	1
+262	0	1
+92	1	1
+10677	2	0
+4856	3	0
+7447	6	6
+421	1	0
+884	6	0
+17	1	0
+3075	1	0
+1610	12	12
+13049	3	1
+3762	2	0
+601	2	0
+2461	0	2
+5154	1	0
+1604	0	16
+3338	26	26
+225	0	1
+1488	1	0
+1196	0	2
+683	0	1
+1218	1	0
+221	1	1
+22	1	1
+296	4	4
+1456	23	41
+880	1	12
+2490	1	0
+151	1	1
+33	1	1
+2809	4	4
+3645	1	1
+17	1	1
+3496	2	0
+154	1	1
+29	1	1
+158	0	1
+5981	1	1
+32	1	1
+1041	0	2
+174	9	0
+1383	0	1
+389	1	2
+1570	2	0
+3993	4	0
+4576	87	87
+142	8	8
+2203	20	24
+2009	1	1
+39	1	1
+489	1	1
+17	1	1
+628	1	1
+124	1	1
+1607	1	1
+23	1	1
+1021	0	8
+1249	0	20
+46	0	32
+46	6	0
+24	0	10
+7679	1	1
+44	1	1
+580	1	1
+28	1	1
+264	1	1
+65	0	1
+15	1	1
+1513	28	28
+830	19	19
+57	1	1
+21	1	1
+231	1	1
+94	1	1
+105	1	1
+208	5	5
+124	1	1
+112	3	3
+207	1	1
+38	1	1
+244	1	1
+60	1	1
+98	1	1
+50	1	1
+256	29	29
+157	1	1
+33	1	1
+143	1	1
+59	1	1
+51	1	1
+45	1	0
+73	1	1
+81	1	1
+270	1	1
+272	1	1
+232	1	1
+94	1	1
+3189	0	176
+834	0	35
+303	0	51
+321	1	0
+17170	0	1
+321	1	1
+25	1	1
+679	1	1
+33	1	1
+990	11	11
+131	8	8
+79	9	9
+1284	9945	10022
+2039	8	23
+491	1	1
+32	1	1
+85	1	1
+41	1	1
+480	1	1
+74	2	2
+1108	59	0
+70	10	10
+325	11	11
+879	1	1
+34	1	1
+524	1	1
+25	1	1
+202	17	17
+1154	1	1
+26	1	1
+89	17	17
+87	1	1
+39	1	1
+950	1	1
+15	2	2
+51	1	1
+81	1	1
+180	1	0
+187	1	1
+37	1	1
+467	1	1
+19	1	1
+755	0	2
+81	3	1
+16	1	1
+67	6	6
+84	1	1
+37	2	0
+31	0	28
+15	0	37
+266	14	14
+372	1	1
+68	1	1
+462	1	1
+46	1	1
+563	19	0
+217	9	9
+363	1	1
+22	1	1
+884	1	1
+40	1	1
+179	1	1
+42	1	1
+94	6	6
+922	1	1
+30	1	1
+481	0	3
+7925	15	11
+333	5	0
+1235	6	6
+355	1	1
+27	1	1
+515	1	0
+1077	11	0
+1521	1	0
+38	1	1
+119	1	1
+58	1	1
+63	4	3
+385	1	1
+49	1	1
+77	44	46
+87	11	11
+190	2	2
+45	1	1
+373	1	1
+47	1	1
+77	10	10
+186	1	1
+24	1	1
+1140	1	0
+214	1	1
+34	1	1
+89	1	1
+36	1	1
+288	0	1
+544	0	331
+320	1	0
+199	1	1
+16	1	1
+112	1	1
+29	1	1
+783	0	3
+311	1	1
+38	1	1
+59	1	1
+68	1	1
+52	1	1
+98	1	1
+166	7	7
+698	1	1
+68	1	1
+165	0	1
+114	1	1
+92	0	1
+14	1	1
+215	1	1
+81	1	1
+792	1	1
+31	1	1
+54	1	1
+44	1	1
+179	1	1
+26	1	1
+200	1	1
+30	1	1
+639	7	7
+505	40	42
+549	12	0
+19	1	1
+2184	1	0
+840	1	1
+69	1	1
+966	21	21
+33	12	0
+56	1	1
+94	1	1
+237	11	9
+189	1	1
+47	1	1
+318	3	0
+80	1	1
+94	5	1
+32	1	1
+126	16	16
+83	1	1
+47	1	1
+104	6	5
+56	1	1
+68	1	1
+417	12	13
+636	0	2
+30	1	1
+694	0	4
+95	1	1
+28	1	1
+1358	1	1
+19	1	1
+68	1	1
+97	1	1
+155	15	15
+323	1	7
+158	2	0
+42	6	0
+59	1	1
+314	14	14
+94	1	1
+64	1	1
+637	1	1
+21	1	1
+144	2	1
+229	11	5
+410	1	1
+96	1	1
+272	1	1
+22	1	1
+118	1	1
+44	1	1
+96	1	1
+48	1	1
+414	22	22
+373	13	13
+554	1	1
+87	10	0
+313	1	1
+37	1	1
+122	17	18
+179	1	1
+40	1	1
+591	8	8
+129	1	0
+70	1	1
+71	1	0
+73	10	6
+12	1	1
+203	0	6
+24	2	0
+45	4	0
+46	1	1
+186	9	9
+87	1	1
+28	1	1
+3625	0	1
+71	1	1
+126	1	1
+34	1	1
+532	0	2
+696	2	0
+555	1	7
+287	1	1
+30	0	3
+946	0	1
+88	1	1
+60	12	0
+12546	1	1
+37	1	0
+2071	0	1
+1253	9	9
+2003	0	1
+24677	0	2
+6212	1	1
+26	1	1
+816	0	4
+13602	18	15
+2375	2	0
+1957	2	0
+2394	6	0
+1561	0	1
+2805	4	0
+12333	8	0
+835	0	1
+426	0	27
+12156	0	18
+6903	2	0
+21807	3	0
+1588	1	0
+2605	1	1
+23	1	1
+11252	8	0
+298	6	7
+946	2	0
+232	0	1
+501	1	0
+4748	0	4
+770	0	7
+914	0	1
+295	1	0
+214	3	0
+121	0	1
+784	0	1
+2512	0	1
+4476	3	0
+926	0	1
+189	2	0
+3543	2	0
+893	1	1
+46	1	1
+1296	0	1
+153	0	1
+336	5	0
+228	1	1
+45	1	1
+207	3	0
+322	0	1
+658	1	0
+1516	3	0
+1025	0	13
+1518	0	1
+591	10	10
+3384	0	2
+182	12	0
+328	1	0
+301	0	1
+994	1	1
+18	0	6
+1743	0	1
+2350	22	23
+1548	0	7
+1976	1	0
+199	0	1
+5922	12	12
+873	0	3
+3080	12	8
+322	1	0
+490	1	0
+3602	1	0
+482	1	0
+3178	1	0
+5157	0	10
+753	0	1
+885	20	0
+1746	10	0
+4045	6	1
+3520	5	13
+2048	0	1
+3529
+
+chain	323865	chr6_cox_hap1	4731698	+	1267152	1270823	12	133851895	-	763369	785145	206180
+2772	0	815
+201	0	17291
+643	1	0
+54
+
+chain	65284	chr6_cox_hap1	4731698	+	2460102	2460796	6	171115067	-	140105134	140105832	1936071
+178	0	4
+516
+
+chain	59092	chr6_cox_hap1	4731698	+	4004481	4005101	4	191154276	+	48364786	48365406	2142970
+620
+
+chain	52987	chr6_cox_hap1	4731698	+	2674042	2675969	3	198022430	-	151830192	151832103	2402006
+102	557	556
+77	395	393
+169	221	221
+81	15	15
+81	35	35
+55	44	31
+95
+
+chain	40067	chr6_cox_hap1	4731698	+	3843208	3843655	1	249250621	-	189436883	189437330	3283815
+379	3	3
+65
+
+chain	34258	chr6_cox_hap1	4731698	+	2746095	2746514	X	155270560	-	17905933	17906346	3956727
+73	15	15
+155	1	1
+20	6	0
+17	1	1
+131
+
+chain	30865	chr6_cox_hap1	4731698	+	3996373	3996892	6	171115067	+	32713281	32713770	4500603
+73	89	59
+184	77	77
+96
+
+chain	30808	chr6_cox_hap1	4731698	+	1446736	1447059	11	135006516	-	73898390	73898713	4511271
+323
+
+chain	29563	chr6_cox_hap1	4731698	+	4089902	4090211	1	249250621	-	75305559	75305868	4853755
+309
+
+chain	29490	chr6_cox_hap1	4731698	+	3888227	3888535	20	63025520	-	21266962	21267270	4884719
+308
+
+chain	23990	chr6_cox_hap1	4731698	+	1313393	1314169	7	159138663	-	51241795	51242737	7706852
+178	101	101
+72	385	551
+40
+
+chain	19279	chr6_cox_hap1	4731698	+	2759716	2759948	5	180915260	+	25289600	25289832	11061062
+91	17	17
+124
+
+chain	18106	chr6_cox_hap1	4731698	+	3844292	3845362	7	159138663	+	50640514	50641583	3599691
+33	446	444
+74	250	251
+5	55	55
+48	69	69
+90
+
+chain	17763	chr6_cox_hap1	4731698	+	3840247	3840451	6	171115067	-	2083149	2083361	12325354
+52	0	8
+26	2	2
+124
+
+chain	17263	chr6_cox_hap1	4731698	+	3890221	3890428	4	191154276	+	3927369	3927573	12785973
+50	3	0
+26	4	4
+124
+
+chain	16283	chr6_cox_hap1	4731698	+	3267732	3267909	2	243199373	+	128545205	128545381	580296
+28	2	1
+147
+
+chain	16000	chr6_cox_hap1	4731698	+	3842640	3845155	5	180915260	-	144997615	145000132	3598025
+127	1430	1431
+95	205	207
+98	29	29
+57	419	418
+55
+
+chain	15874	chr6_cox_hap1	4731698	+	2744265	2744697	6	171115067	+	31304784	31305225	14156555
+58	158	158
+72	76	85
+68
+
+chain	15671	chr6_cox_hap1	4731698	+	1306242	1307477	6	171115067	-	139875690	139876935	14366990
+56	408	416
+54	620	622
+97
+
+chain	15351	chr6_cox_hap1	4731698	+	2791400	2791601	11	135006516	+	74748600	74748801	14697621
+99	26	26
+76
+
+chain	14920	chr6_cox_hap1	4731698	+	2791114	2791352	12	133851895	+	56894984	56895263	15150280
+65	69	110
+104
+
+chain	14203	chr6_cox_hap1	4731698	+	4000567	4000717	6	171115067	-	148948255	148948405	15963295
+150
+
+chain	14065	chr6_cox_hap1	4731698	+	3901987	3902139	6	171115067	-	138602057	138602209	16122340
+152
+
+chain	13939	chr6_cox_hap1	4731698	+	2790912	2791061	15	102531392	-	60147333	60147482	16276423
+149
+
+chain	13590	chr6_cox_hap1	4731698	+	4000399	4000543	2	243199373	+	178345068	178345212	16711221
+144
+
+chain	13240	chr6_cox_hap1	4731698	+	3909742	3911000	6	171115067	+	32548108	32549235	17164167
+52	422	421
+78	652	522
+54
+
+chain	12556	chr6_cox_hap1	4731698	+	1348680	1348819	2	243199373	-	184149574	184149713	18162971
+139
+
+chain	12225	chr6_cox_hap1	4731698	+	3890501	3890631	13	115169878	-	44980182	44980312	18662730
+130
+
+chain	12178	chr6_cox_hap1	4731698	+	3972449	3972615	14	107349540	-	58393926	58394091	18734378
+55	26	25
+85
+
+chain	12008	chr6_cox_hap1	4731698	+	3896810	3896939	8	146364022	+	49154427	49154556	18990652
+129
+
+chain	11746	chr6_cox_hap1	4731698	+	1299553	1299701	7	159138663	-	7702899	7703047	19437477
+54	14	14
+80
+
+chain	11718	chr6_cox_hap1	4731698	+	299537	299697	13	115169878	+	54026210	54026329	7331663
+62	41	0
+40	13	13
+4
+
+chain	11503	chr6_cox_hap1	4731698	+	3894886	3895312	11	135006516	-	111045874	111046295	19852909
+57	287	282
+82
+
+chain	11377	chr6_cox_hap1	4731698	+	3840583	3840825	11	135006516	+	57049649	57049891	20071170
+62	107	107
+73
+
+chain	10960	chr6_cox_hap1	4731698	+	3841022	3841165	12	133851895	-	49356794	49356937	20822626
+50	15	15
+78
+
+chain	10867	chr6_cox_hap1	4731698	+	2681465	2681622	6	171115067	-	132617434	132617597	20998653
+55	29	35
+73
+
+chain	10738	chr6_cox_hap1	4731698	+	3896518	3896639	10	135534747	+	59600699	59600817	21255898
+61	3	0
+57
+
+chain	10496	chr6_cox_hap1	4731698	+	3892569	3892679	1	249250621	-	174039531	174039641	21744607
+110
+
+chain	10328	chr6_cox_hap1	4731698	+	3840451	3840892	4	191154276	-	114078209	114078650	18698120
+15	372	372
+54
+
+chain	9881	chr6_cox_hap1	4731698	+	2734004	2734554	6	171115067	+	31205448	31206008	23100546
+72	423	433
+55
+
+chain	9755	chr6_cox_hap1	4731698	+	4021493	4021793	6	171115067	+	162490109	162490409	23390927
+65	181	181
+54
+
+chain	9560	chr6_cox_hap1	4731698	+	1301303	1301404	6	171115067	-	141323187	141323288	23857061
+101
+
+chain	9455	chr6_cox_hap1	4731698	+	3891953	3892158	6	171115067	+	32468923	32469135	24116909
+54	91	98
+60
+
+chain	9090	chr6_cox_hap1	4731698	+	2680711	2680821	3	198022430	-	94212956	94213066	24807216
+53	4	4
+53
+
+chain	7297	chr6_cox_hap1	4731698	+	3844000	3844124	8	146364022	+	96809146	96809270	3974525
+124
+
+chain	7162	chr6_cox_hap1	4731698	+	2675969	2676329	17	81195210	-	22005566	22005927	2836104
+7	302	303
+51
+
+chain	7031	chr6_cox_hap1	4731698	+	2673410	2673921	5	180915260	+	106108094	106108601	3265511
+58	376	372
+77
+
+chain	6840	chr6_cox_hap1	4731698	+	3971466	3971538	11	135006516	+	40011829	40011901	28544257
+72
+
+chain	6473	chr6_cox_hap1	4731698	+	3890669	3890742	1	249250621	-	102907635	102907704	21815173
+11	4	0
+58
+
+chain	6422	chr6_cox_hap1	4731698	+	4013834	4013902	6	171115067	+	32728707	32728775	29535230
+68
+
+chain	5921	chr6_cox_hap1	4731698	+	2681183	2681245	4	191154276	-	94306644	94306706	30842389
+62
+
+chain	5676	chr6_cox_hap1	4731698	+	2671999	2672059	3	198022430	+	95260601	95260661	31509897
+60
+
+chain	5595	chr6_cox_hap1	4731698	+	3972615	3972674	14	107349540	-	80191032	80191091	27115653
+59
+
+chain	5576	chr6_cox_hap1	4731698	+	1302171	1302230	18	78077248	-	3698437	3698496	31796878
+59
+
+chain	5517	chr6_cox_hap1	4731698	+	3842389	3842453	20	63025520	-	5368566	5368630	20848663
+64
+
+chain	5458	chr6_cox_hap1	4731698	+	3985007	3985065	2	243199373	+	112827415	112827473	32167738
+58
+
+chain	5421	chr6_cox_hap1	4731698	+	2677334	2677391	19	59128983	-	38462903	38462960	32247802
+57
+
+chain	5403	chr6_cox_hap1	4731698	+	3897499	3897556	12	133851895	+	59864980	59865037	32286341
+57
+
+chain	5339	chr6_cox_hap1	4731698	+	4081817	4081873	17	81195210	+	16805661	16805717	32499905
+56
+
+chain	5266	chr6_cox_hap1	4731698	+	4021149	4021204	3	198022430	+	6923000	6923055	32744278
+55
+
+chain	5103	chr6_cox_hap1	4731698	+	2743431	2743485	3	198022430	+	27241143	27241197	33231446
+54
+
+chain	5094	chr6_cox_hap1	4731698	+	3984745	3984799	6	171115067	+	67966752	67966806	33279729
+54
+
+chain	5089	chr6_cox_hap1	4731698	+	2674314	2675775	1	249250621	+	7474130	7475590	2473669
+98	975	974
+58	295	295
+35
+
+chain	5076	chr6_cox_hap1	4731698	+	1300901	1300955	11	135006516	+	101518151	101518205	33343005
+54
+
+chain	5067	chr6_cox_hap1	4731698	+	2741303	2741357	19	59128983	-	37393851	37393905	33368570
+54
+
+chain	5058	chr6_cox_hap1	4731698	+	3967166	3967220	1	249250621	-	172942963	172943017	33379585
+54
+
+chain	5020	chr6_cox_hap1	4731698	+	1345886	1345938	6	171115067	+	29692684	29692736	33527644
+52
+
+chain	4959	chr6_cox_hap1	4731698	+	3892516	3892569	18	78077248	+	5090594	5090647	22176918
+53
+
+chain	4957	chr6_cox_hap1	4731698	+	2678048	2678100	9	141213431	-	31846047	31846099	33735026
+52
+
+chain	4957	chr6_cox_hap1	4731698	+	3946024	3946076	6	171115067	+	32439356	32439408	33735182
+52
+
+chain	4930	chr6_cox_hap1	4731698	+	3894496	3894548	X	155270560	-	4541772	4541824	33815607
+52
+
+chain	4914	chr6_cox_hap1	4731698	+	2673741	2673793	X	155270560	+	7935883	7935935	17711968
+52
+
+chain	4885	chr6_cox_hap1	4731698	+	2740950	2741002	5	180915260	-	163072859	163072911	33995114
+52
+
+chain	4884	chr6_cox_hap1	4731698	+	2760326	2760379	7	159138663	+	8699184	8699237	23141527
+53
+
+chain	4821	chr6_cox_hap1	4731698	+	3935381	3935432	6	171115067	-	11031703	11031754	34213824
+51
+
+chain	4685	chr6_cox_hap1	4731698	+	3915703	3915753	12	133851895	+	112261417	112261467	34690968
+50
+
+chain	4613	chr6_cox_hap1	4731698	+	2844682	2846505	13	115169878	-	41386504	41386960	3856143
+33	479	279
+7	46	0
+24	11	0
+33	1097	0
+24	13	0
+56
+
+chain	4221	chr6_cox_hap1	4731698	+	2437589	2437671	14	107349540	+	75461679	75461839	4623812
+28	0	78
+54
+
+chain	4202	chr6_cox_hap1	4731698	+	2673968	2674023	3	198022430	+	156309398	156309453	19139889
+55
+
+chain	4186	chr6_cox_hap1	4731698	+	3955813	3955860	5	180915260	-	113986983	113987030	34971958
+47
+
+chain	4136	chr6_cox_hap1	4731698	+	2672610	2672662	13	115169878	+	42049101	42049153	23521137
+52
+
+chain	3978	chr6_cox_hap1	4731698	+	2673481	2673609	X	155270560	-	130914483	130914611	4485241
+128
+
+chain	3891	chr6_cox_hap1	4731698	+	2760039	2760115	16	90354753	-	58442153	58442229	17002345
+76
+
+chain	3877	chr6_cox_hap1	4731698	+	2672485	2672526	15	102531392	+	40275232	40275273	21164310
+41
+
+chain	3776	chr6_cox_hap1	4731698	+	2759549	2759589	1	249250621	-	143888892	143888932	33598889
+40
+
+chain	3639	chr6_cox_hap1	4731698	+	3890631	3890669	3	198022430	+	101411146	101411184	20382394
+38
+
+chain	3574	chr6_cox_hap1	4731698	+	2673146	2673184	3	198022430	-	173409162	173409200	29596627
+38
+
+chain	3573	chr6_cox_hap1	4731698	+	2790788	2791088	16	90354753	+	31183111	31183406	18086604
+58	215	210
+27
+
+chain	3489	chr6_cox_hap1	4731698	+	3842885	3842952	X	155270560	-	48144545	48144612	19043441
+67
+
+chain	3394	chr6_cox_hap1	4731698	+	3896482	3896518	X	155270560	-	4545757	4545793	28280414
+36
+
+chain	3393	chr6_cox_hap1	4731698	+	3840688	3840752	8	146364022	+	7016797	7016861	21522443
+64
+
+chain	3345	chr6_cox_hap1	4731698	+	1313572	1313633	X	155270560	-	101738888	101738949	11083842
+61
+
+chain	3209	chr6_cox_hap1	4731698	+	3842526	3842560	4	191154276	+	80147803	80147837	32673071
+34
+
+chain	3189	chr6_cox_hap1	4731698	+	2790872	2790912	11	135006516	-	131957088	131957128	22905486
+40
+
+chain	3053	chr6_cox_hap1	4731698	+	4021558	4021590	2	243199373	+	38182694	38182726	24706669
+32
+
+chain	3045	chr6_cox_hap1	4731698	+	2677533	2677565	11	135006516	-	20509488	20509520	33762261
+32
+
+chain	3033	chr6_cox_hap1	4731698	+	3842991	3843062	1	249250621	-	90164672	90164743	11203780
+71
+
+chain	2997	chr6_cox_hap1	4731698	+	2759644	2759694	16	90354753	+	47212776	47212826	11278440
+50
+
+chain	2984	chr6_cox_hap1	4731698	+	3842575	3842625	X	155270560	+	76422698	76422748	20248077
+50
+
+chain	2960	chr6_cox_hap1	4731698	+	3896779	3896810	21	48129895	+	18677639	18677670	32477029
+31
+
+chain	2845	chr6_cox_hap1	4731698	+	2673184	2673214	3	198022430	-	156603737	156603767	26791325
+30
+
+chain	2761	chr6_cox_hap1	4731698	+	3844406	3844465	6	171115067	+	18547856	18547915	4276868
+59
+
+chain	2745	chr6_cox_hap1	4731698	+	3842326	3844197	11	135006516	-	48638733	48640605	3968835
+61	675	676
+53	1015	1015
+67
+
+chain	2739	chr6_cox_hap1	4731698	+	2673924	2673968	8	146364022	+	90457478	90457522	20607564
+44
+
+chain	2729	chr6_cox_hap1	4731698	+	1302230	1302259	14	107349540	+	79349511	79349540	33029767
+29
+
+chain	2723	chr6_cox_hap1	4731698	+	2673793	2673825	5	180915260	-	70673106	70673138	18877917
+32
+
+chain	2561	chr6_cox_hap1	4731698	+	299599	299640	6	171115067	+	20244702	20244743	12574490
+41
+
+chain	2518	chr6_cox_hap1	4731698	+	4021649	4021704	16	90354753	-	20685134	20685189	24272036
+55
+
+chain	2470	chr6_cox_hap1	4731698	+	2745980	2746030	1	249250621	+	111776293	111776343	7607561
+50
+
+chain	2373	chr6_cox_hap1	4731698	+	2760156	2760181	17	81195210	-	66761411	66761436	17362234
+25
+
+chain	2319	chr6_cox_hap1	4731698	+	2900811	2900837	6	171115067	+	31357660	31357686	3303778
+26
+
+chain	2312	chr6_cox_hap1	4731698	+	2759490	2759549	4	191154276	+	98204882	98204941	18366184
+59
+
+chain	2209	chr6_cox_hap1	4731698	+	3843799	3843896	12	133851895	+	60159606	60159703	5400255
+97
+
+chain	2146	chr6_cox_hap1	4731698	+	1299766	1299827	12	133851895	+	105697047	105697108	23835468
+61
+
+chain	2140	chr6_cox_hap1	4731698	+	3840491	3840558	6	171115067	-	96829007	96829074	20827044
+67
+
+chain	2000	chr6_cox_hap1	4731698	+	1313744	1313777	4	191154276	+	153686345	153686378	8134925
+33
+
+chain	1995	chr6_cox_hap1	4731698	+	3842817	3842864	4	191154276	-	47817470	47817517	17212566
+47
+
+chain	1991	chr6_cox_hap1	4731698	+	2845315	2845345	4	191154276	-	30046978	30047008	15284842
+30
+
+chain	1990	chr6_cox_hap1	4731698	+	4008195	4011710	6	171115067	+	32722816	32726965	28700009
+61	2506	2690
+85	515	965
+52	103	103
+193
+
+chain	1943	chr6_cox_hap1	4731698	+	3844851	3845272	11	135006516	+	83226111	83226530	3906185
+58	323	321
+40
+
+chain	1927	chr6_cox_hap1	4731698	+	2759609	2759644	7	159138663	-	110094552	110094587	24531071
+35
+
+chain	1727	chr6_cox_hap1	4731698	+	2674522	2674583	20	63025520	-	53185733	53185794	4777998
+61
+
+chain	1671	chr6_cox_hap1	4731698	+	3843897	3843947	9	141213431	+	78317603	78317653	4355881
+50
+
+chain	1637	chr6_cox_hap1	4731698	+	2760272	2760326	2	243199373	+	119859185	119859239	11695157
+54
+
+chain	1632	chr6_cox_hap1	4731698	+	2673214	2673313	4	191154276	-	69486891	69486990	2834158
+99
+
+chain	1628	chr6_cox_hap1	4731698	+	3842952	3842991	2	243199373	-	116273698	116273737	14990340
+39
+
+chain	1584	chr6_cox_hap1	4731698	+	1313851	1313915	1	249250621	-	24961912	24961976	17607390
+64
+
+chain	1548	chr6_cox_hap1	4731698	+	2672923	2673038	2	243199373	-	193655574	193655689	3516324
+115
+
+chain	1509	chr6_cox_hap1	4731698	+	2674838	2674895	5	180915260	+	165569524	165569581	2491813
+57
+
+chain	1508	chr6_cox_hap1	4731698	+	2675985	2676708	6	171115067	-	141365359	141366083	3289535
+50	615	616
+58
+
+chain	1507	chr6_cox_hap1	4731698	+	2673661	2673741	4	191154276	+	138835824	138835904	16168846
+80
+
+chain	1489	chr6_cox_hap1	4731698	+	2845209	2846585	X	155270560	-	102215688	102216455	6549884
+27	1297	452
+2	0	236
+50
+
+chain	1467	chr6_cox_hap1	4731698	+	2760221	2760272	7	159138663	+	122232756	122232807	13147168
+51
+
+chain	1456	chr6_cox_hap1	4731698	+	3844931	3844983	14	107349540	+	48881293	48881345	9320615
+52
+
+chain	1452	chr6_cox_hap1	4731698	+	2673321	2674838	X	155270560	-	1098426	1099942	3000529
+51	1428	1427
+38
+
+chain	1354	chr6_cox_hap1	4731698	+	1313967	1314021	4	191154276	+	544307	544361	14282164
+54
+
+chain	1310	chr6_cox_hap1	4731698	+	3843714	3843782	X	155270560	+	17249549	17249617	3972308
+68
+
+chain	1307	chr6_cox_hap1	4731698	+	1498573	1498607	5	180915260	-	156542608	156542642	2089959
+34
+
+chain	1294	chr6_cox_hap1	4731698	+	2760418	2760473	4	191154276	+	147516497	147516552	12285122
+55
+
+chain	1278	chr6_cox_hap1	4731698	+	3845015	3845082	15	102531392	+	92125438	92125505	4023305
+67
+
+chain	1247	chr6_cox_hap1	4731698	+	3844702	3844748	2	243199373	-	7511493	7511539	13743690
+46
+
+chain	1194	chr6_cox_hap1	4731698	+	2676043	2676103	1	249250621	+	94380187	94380247	20995710
+60
+
+chain	1160	chr6_cox_hap1	4731698	+	2676209	2676237	X	155270560	+	56836392	56836420	21177535
+28
+
+chain	1125	chr6_cox_hap1	4731698	+	3890818	3890886	8	146364022	-	86779351	86779419	20749389
+68
+
+chain	1106	chr6_cox_hap1	4731698	+	2760181	2760221	9	141213431	+	74027839	74027879	13331514
+40
+
+chain	1039	chr6_cox_hap1	4731698	+	2674441	2674507	3	198022430	-	71498815	71498881	4421669
+66
+
+chain	1033	chr6_cox_hap1	4731698	+	2676372	2676431	5	180915260	-	20894072	20894131	3124143
+59
+
+chain	1014	chr6_cox_hap1	4731698	+	2759961	2759990	10	135534747	+	69125589	69125618	23828230
+29
+
+chain	1005	chr6_cox_hap1	4731698	+	2760005	2760039	10	135534747	+	5299750	5299784	23898321
+34
+
+chain	982	chr6_cox_hap1	4731698	+	2759426	2759479	13	115169878	+	111326976	111327029	14386536
+53
+
+chain	977	chr6_cox_hap1	4731698	+	3845410	3845467	X	155270560	-	144584413	144584470	4043690
+57
+
+chain	963	chr6_cox_hap1	4731698	+	2674253	2676589	9	141213431	-	119032541	119034846	4479982
+47	2231	2200
+58
+
+chain	919	chr6_cox_hap1	4731698	+	2677255	2677315	4	191154276	+	45112377	45112437	22402156
+60
+
+chain	883	chr6_cox_hap1	4731698	+	3843656	3843714	18	78077248	+	28929278	28929336	6530663
+58
+
+chain	881	chr6_cox_hap1	4731698	+	2675038	2675098	5	180915260	-	79225133	79225193	14536118
+60
+
+chain	858	chr6_cox_hap1	4731698	+	2676338	2676372	7	159138663	-	148564023	148564057	6699557
+34
+
+chain	857	chr6_cox_hap1	4731698	+	2676103	2677646	4	191154276	+	171430336	171431860	18546235
+50	1412	1393
+81
+
+chain	838	chr6_cox_hap1	4731698	+	3843947	3843980	18	78077248	-	28720814	28720847	7914761
+33
+
+chain	819	chr6_cox_hap1	4731698	+	2673062	2673118	2	243199373	+	149156283	149156339	14209631
+56
+
+chain	796	chr6_cox_hap1	4731698	+	1314021	1314060	X	155270560	-	10752795	10752834	16687246
+39
+
+chain	747	chr6_cox_hap1	4731698	+	1314275	1314339	12	133851895	+	57178267	57178331	20664563
+64
+
+chain	731	chr6_cox_hap1	4731698	+	1638596	1638636	15	102531392	+	55738847	55738887	18753864
+40
+
+chain	704	chr6_cox_hap1	4731698	+	3842767	3842817	9	141213431	+	32212289	32212339	4117535
+50
+
+chain	701	chr6_cox_hap1	4731698	+	2674653	2674701	16	90354753	-	23821388	23821436	3556080
+48
+
+chain	679	chr6_cox_hap1	4731698	+	1313640	1313672	21	48129895	-	2887431	2887463	13569070
+32
+
+chain	672	chr6_cox_hap1	4731698	+	3844325	3844357	10	135534747	-	103351577	103351609	5595826
+32
+
+chain	661	chr6_cox_hap1	4731698	+	2676159	2676209	9	141213431	+	85388422	85388472	5334226
+50
+
+chain	661	chr6_cox_hap1	4731698	+	3844987	3845015	2	243199373	+	98215178	98215206	5611311
+28
+
+chain	650	chr6_cox_hap1	4731698	+	2672375	2672435	7	159138663	-	140047518	140047578	22707410
+60
+
+chain	643	chr6_cox_hap1	4731698	+	2677085	2677144	6	171115067	+	74793831	74793890	5895430
+59
+
+chain	604	chr6_cox_hap1	4731698	+	1314169	1314195	X	155270560	-	101522169	101522195	11588450
+26
+
+chain	595	chr6_cox_hap1	4731698	+	2675343	2675387	12	133851895	-	110550302	110550346	3606052
+44
+
+chain	571	chr6_cox_hap1	4731698	+	2672827	2672901	3	198022430	+	50956018	50956092	15278850
+74
+
+chain	525	chr6_cox_hap1	4731698	+	3902955	3903021	6	171115067	+	32474022	32474088	26162225
+66
+
+chain	485	chr6_cox_hap1	4731698	+	2671938	2671998	1	249250621	-	193322919	193322979	8312425
+60
+
+chain	412	chr6_cox_hap1	4731698	+	2672740	2672827	8	146364022	-	113140827	113140914	13566503
+87
+
+chain	395	chr6_cox_hap1	4731698	+	2846505	2846533	X	155270560	-	102216470	102216498	6380381
+28
+
+chain	395	chr6_cox_hap1	4731698	+	2675098	2675125	12	133851895	+	9999203	9999230	23891782
+27
+
+chain	347	chr6_cox_hap1	4731698	+	2671704	2671754	15	102531392	-	65978487	65978537	12839282
+50
+
+chain	251	chr6_cox_hap1	4731698	+	2671761	2671812	9	141213431	+	17677697	17677748	27279073
+51
+
+chain	184	chr6_cox_hap1	4731698	+	2672526	2672587	X	155270560	-	91681431	91681492	16167874
+61
+
+chain	369716150	chr6_qbl_hap2	4565931	+	0	4565931	6	171115067	+	28742641	33379750	32
+2350	0	1
+1750	0	2
+3815	1	0
+9743	0	2
+3960	0	4
+2109	0	2
+33	2	0
+9000	0	2
+16647	0	2
+38786	1	0
+80529	0	1
+14475	0	1
+6819	1	0
+6845	1	3
+6188	0	1
+6397	0	1
+345	1	0
+68374	2	0
+39133	39	39
+7774	7	0
+1489	1	1
+72	1	1
+2260	0	2
+10629	0	1
+1249	1	1
+195	1	1
+18132	0	1
+1324	0	2
+5438	5	0
+2061	1	0
+3982	6	6
+1725	0	1
+3153	1	0
+18	1	0
+18	1	0
+2026	1	0
+4175	10	10
+4235	18	18
+493	9	9
+4767	7	7
+1225	1	0
+8	1	1
+151	1	2
+5079	1	1
+28	1	1
+281	11	11
+1178	0	4
+685	8	0
+48	4	0
+1701	1	1
+43	5	5
+862	18	18
+58	1	1
+66	1	1
+420	1	1
+44	1	1
+680	4	4
+1675	1	1
+83	1	1
+3082	4	0
+5467	1	1
+27	0	1
+1099	16	0
+627	51	51
+1278	6	1
+129	1	1
+25	1	1
+1397	15	15
+810	1	1
+27	1	1
+1192	2	0
+7515	4	0
+979	0	3
+3406	0	2
+2340	1	1
+20	1	1
+1139	1	1
+26	1	1
+787	0	1
+1416	3	1
+22815	4	4
+126	1	0
+38	1	1
+140	1	0
+999	0	17
+56	0	15
+11759	161391	161513
+11155	0	2
+5376	0	1
+19253	1	0
+4212	1	1
+3671	1	0
+21	0	6
+4451	1	0
+27910	1	0
+9946	0	1
+11233	1	1
+32	1	1
+2238	1	1
+20	1	1
+3659	22	16
+1218	1	0
+1638	6	6
+228	1	1
+45	1	1
+2048	0	3
+461	1	0
+20759	1	0
+3778	2	1
+1268	1	0
+1511	1	1
+42	2	0
+24	1	1
+4119	22	0
+1757	1	0
+1527	1	1
+29	1	1
+1886	1	0
+10628	12	0
+46568	1	0
+18985	0	10
+1825	3	4
+5288	0	9
+1071	50	50
+1607	1	5
+722	0	1
+502	0	1
+1025	0	1
+134	14	0
+4944	0	1
+319	1	0
+6178	0	1
+2898	0	2
+143	0	1
+1775	1	0
+2123	0	1
+2715	1	0
+4901	70	66
+2884	1	0
+1362	1	0
+1233	0	8
+2134	0	1
+1042	0	1
+163	1	1
+45	1	1
+50	2	0
+64	1	1
+48	1	1
+380	0	1
+30	1	0
+30	1	1
+61	1	1
+22	1	1
+368	4	4
+319	5	7
+310	1	1
+37	3	1
+162	1	1
+194	2	0
+36	1	1
+242	9	9
+1932	1	1
+16	1	1
+528	1	1
+20	1	1
+509	0	5
+76	1	1
+21	1	1
+439	15	15
+2779	1	0
+1597	24	28
+59	12	12
+307	1	0
+516	1	0
+286	11	33
+339	5	0
+570	1	1
+37	1	1
+220	1	0
+72	1	1
+144	1	1
+48	1	1
+247	2	0
+174	9	10
+816	1	0
+940	1	1
+45	1	1
+91	3	3
+71	1	1
+291	14	14
+100	1	1
+23	1	1
+452	3	3
+85	1	1
+65	1	1
+77	1	1
+252	0	1
+129	15	15
+432	10	0
+85	1	1
+28	1	1
+189	2	1
+71	1	1
+52	8	0
+810	2	2
+63	1	1
+378	1	1
+26	1	1
+187	31	36
+966	1	1
+25	1	1
+91	12	12
+125	1	1
+38	1	1
+433	2	0
+596	1	1
+48	1	1
+465	4	4
+64	1	1
+20	1	1
+525	5	5
+237	3	8
+183	11	0
+364	4	3
+201	1	1
+42	1	1
+56	1	1
+115	1	0
+67	16	16
+244	1	1
+54	5	5
+929	1	1
+21	1	1
+126	0	3
+830	1	11
+59	1	1
+537	0	2
+24	1	1
+745	15	15
+810	1	0
+425	1	1
+89	1	1
+592	1	1
+49	1	1
+352	0	1
+142	1	1
+30	1	1
+95	1	1
+45	1	1
+227	1	1
+53	1	1
+130	1	1
+18	1	1
+138	1	1
+90	1	1
+129	41	41
+50	1	1
+79	1	1
+117	1	1
+31	1	1
+155	155	0
+34	1	1
+50	5	5
+57	1	1
+152	1	1
+30	1	1
+177	5	5
+345	1	1
+39	1	1
+504	18	18
+596	12	12
+54	1	1
+158	1	1
+164	1	1
+34	1	1
+626	15	15
+866	0	10
+1051	0	2611
+680	0	1
+1537	0	18
+75	1	0
+147	52	1
+119	0	12
+23	1	1
+1927	13	13
+1702	2	0
+3694	1	1
+18	1	1
+958	43	47
+246	2	0
+146	1	1
+49	1	1
+410	1	0
+667	1	1
+38	1	1
+362	7	1
+159	2	0
+515	2	0
+1026	1	1
+29	1	1
+249	0	6
+129	1	1
+33	4	0
+10	1	5
+1236	1	1
+20	1	1
+138	10	9
+448	0	3
+660	1	1
+28	1	1
+83	1	1
+51	1	1
+2659	1	1
+38	1	1
+424	0	1
+70	1	1
+820	1	1
+26	1	1
+1472	1	1
+21	1	1
+491	5	5
+2372	2	0
+533	6	0
+441	1	7
+1689	1	1
+26	3	4
+879	16	16
+514	0	2
+58	1	1
+350	1	0
+769	1	1
+39	1	1
+429	10	10
+134	0	4
+37	1	1
+144	8	8
+668	1	1
+22	1	1
+344	2	0
+262	2	2
+38	0	1
+70	18	18
+84	11	13
+198	0	1
+32	1	1
+74	11	15
+1255	0	2
+332	1	1
+21	1	1
+193	8	24
+34	1	1
+79	1	1
+29	1	1
+536	1	0
+308	0	1
+850	0	32
+23	1	1
+651	1	1
+22	0	3
+136	1	1
+48	1	1
+330	9	9
+1108	1	1
+98	1	1
+582	0	2
+713	7	7
+89	1	0
+293	9	8
+125	1	1
+31	1	1
+192	6	6
+171	17	17
+681	1	1
+43	1	1
+514	1	1
+68	1	1
+537	1	1
+35	1	1
+159	6	6
+778	2	2
+44	1	1
+168	0	7
+211	1	1
+42	1	1
+1253	1	1
+29	1	1
+320	1	1
+36	2	2
+55	1	2
+108	1	1
+33	1	1
+317	1	1
+35	1	1
+553	8	8
+386	1	1
+26	1	1
+540	1	1
+31	1	1
+65	0	1
+625	12	12
+313	0	1
+52	1	1
+22	1	1
+583	1	1
+49	1	1
+678	37	37
+784	3	0
+838	1	1
+19	12	0
+1129	1	1
+36	1	1
+553	8	8
+109	1	1
+45	1	1
+841	16	15
+157	1	1
+31	2	2
+204	18	19
+487	1	1
+29	1	1
+374	1	1
+67	1	1
+720	13	13
+266	10	10
+330	16	14
+413	1	1
+44	1	1
+78	6	6
+181	2	2
+36	1	1
+397	1	1
+20	1	1
+311	1	1
+48	2	2
+1298	11	11
+186	1	1
+33	1	1
+216	4	4
+35	1	1
+194	10	10
+310	1	1
+51	1	1
+136	1	1
+49	1	1
+521	1	1
+23	1	1
+242	1	1
+49	1	1
+600	1	1
+31	1	1
+413	15	15
+290	1	1
+49	1	1
+527	17	17
+340	12	11
+1025	1	0
+2572	1	1
+29	1	1
+397	2	5
+668	13	13
+541	1	1
+59	0	2
+6	1	1
+122	14	14
+51	1	1
+46	1	1
+72	5	5
+110	1	1
+76	1	1
+164	0	21
+136	1	1
+12	1	1
+66	16	16
+456	37	34
+371	7	7
+48	1	1
+194	10	10
+108	1	1
+60	1	1
+122	0	1
+48	1	1
+238	1	1
+32	0	1
+100	1	0
+72	1	0
+390	1	1
+38	1	1
+144	1	1
+27	0	4
+184	21	228
+49	1	1
+608	0	1
+152	1	1
+31	1	1
+281	8	8
+337	1	1
+45	1	1
+222	1	1
+54	1	1
+346	1	0
+44	1	1
+368	1	1
+72	1	1
+502	36	18
+63	1	1
+43	0	4
+136	1	1
+42	1	1
+80	4	4
+35	1	0
+89	1	1
+24	0	5
+829	13	13
+73	1	1
+28	14	0
+233	1	1
+42	0	3
+85	0	1
+400	1	1
+40	1	1
+538	25	25
+174	1	1
+20	1	1
+705	1	1
+26	2	2
+614	1	1
+44	1	1
+793	1	1
+16	1	1
+747	5	5
+804	1	1
+29	1	1
+166	1	1
+43	1	1
+233	1	1
+44	1	1
+507	0	3
+110	8	8
+133	1	1
+31	1	1
+165	1	1
+29	1	1
+1249	1	1
+26	4	0
+56	1	1
+67	1	1
+716	1	1
+46	0	1
+16	1	1
+174	1	1
+96	1	1
+141	1	1
+39	0	4
+263	1	1
+18	1	1
+259	4	4
+38	1	1
+104	1	1
+40	1	0
+248	1	1
+18	1	1
+238	1	1
+32	1	1
+70	0	2
+16	1	1
+818	1	1
+22	4	4
+492	4	4
+1145	1	1
+46	1	1
+53	1	0
+38	1	1
+373	1	1
+60	1	1
+1149	0	1
+20	1	1
+1294	1	1
+41	1	1
+316	4	4
+42	1	1
+218	12	12
+363	1	1
+24	1	1
+457	10	10
+414	13	13
+825	1	1
+41	1	1
+492	0	4
+1374	1	1
+18	1	1
+808	2	2
+335	6	4
+880	1	1
+35	1	1
+236	1	1
+67	1	1
+298	0	1
+147	4	4
+322	11	11
+613	1	1
+62	1	1
+340	1	1
+22	1	1
+1057	1	1
+57	1	1
+358	1	1
+128	1	1
+146	10	10
+490	1	1
+20	1	1
+62	1	1
+88	1	1
+293	1	1
+28	1	0
+20	1	1
+83	0	1
+90	1	1
+312	1	1
+44	1	1
+1213	1	1
+51	1	1
+467	1	1
+39	1	1
+122	14	0
+35	1	1
+485	14	14
+110	12	0
+127	1	1
+5450	0	5
+1699	9	9
+3278	0	2
+28	1	1
+2211	2	0
+521	1	1
+18	1	1
+784	18	18
+1603	0	248
+4769	47	47
+4486	4	4
+103	0	2
+88	1	1
+95	1	1
+2174	1	1
+22	0	1
+1244	7	7
+922	2	0
+1507	1	1
+44	1	1
+208	6	1
+1946	2	2
+85	0	1
+133	1	1
+666	1	0
+52	1	1
+29	1	1
+148	0	5
+30	1	1
+790	14	14
+52	1	1
+32	1	1
+121	1	1
+37	1	1
+396	3	2
+324	1	1
+152	1	1
+71	4	4
+27	1	1
+115	1	1
+101	1	1
+423	10	10
+294	1	1
+101	1	0
+4	0	1
+174	1	1
+146	1	1
+103	1	1
+134	1	1
+16	1	1
+378	1	1
+85	1	1
+134	1	1
+25	1	1
+54	3	3
+55	1	1
+67	1	1
+22	1	1
+54	13	13
+55	11	11
+120	1	1
+23	1	1
+51	1	1
+22	1	1
+364	1	1
+278	1	1
+354	34448	40149
+311	1	1
+33	1	2
+26	6	6
+474	1	1
+36	1	1
+151	1	1
+29	1	1
+120	1	1
+23	1	1
+865	1	1
+39	1	1
+553	1	1
+69	1	1
+116	1	0
+1618	9	9
+820	11	11
+173	0	8
+405	9	9
+196	1	1
+26	1	1
+173	1	1
+27	5	1
+42	1	1
+676	17	19
+77	1	3
+65	16	16
+69	1	0
+277	1	1
+44	1	1
+72	0	3
+70	1	1
+54	1	1
+240	1	0
+31	1	1
+1192	18	19
+454	28	28
+373	1	1
+46	1	1
+1565	1	1
+53	2	2
+543	1	1
+38	1	1
+985	1	1
+27	0	1
+8	1	1
+158	0	38
+656	1	1
+104	1	1
+771	1	1
+21	1	1
+398	1	1
+16	1	2
+163	4	3
+94	1	1
+44	1	1
+172	1	0
+122	5	5
+193	16	16
+535	2	2
+17	1	0
+93	1	1
+580	1	1
+91	1	1
+141	1	1
+79	1	1
+80	13	13
+165	1	1
+129	1	1
+114	1	1
+30	1	1
+83	1	1
+35	1	1
+126	16	16
+270	0	1
+111	9	9
+151	1	1
+118	1	1
+253	1	1
+45	18468	20220
+102	1	1
+20	1	1
+111	1	1
+97	1	0
+86	1	1
+70	0	4
+69	1	1
+52	0	1
+219	3	3
+76	1	5
+209	4	4
+22	1	1
+61	1	1
+91	1	1
+194	0	21
+15	0	1
+229	1	1
+185	0	1
+113	5	5
+45	1	1
+53	1	1
+37	1	1
+157	1	1
+279	1	1
+233	1	1
+19	0	8
+67	2	0
+41	1	1
+102	12	12
+275	14	14
+70	1	1
+82	2	2
+224	5	1
+490	0	22
+3841	1	0
+3216	1	1
+42	1	1
+1914	0	3
+616	11	12
+144	1	1
+21	2	1
+775	1	1
+50	1	1
+50	2	2
+96	2	2
+1522	4	0
+58	0	2
+1099	1	1
+42	1	1
+3502	0	6
+255	1	1
+40	1	1
+150	0	4
+18	1	1
+589	1	1
+37	1	1
+539	5	5
+354	1	3
+128	1	1
+58	1	1
+159	1	1
+5	2	0
+21	1	1
+231	1	1
+82	3	3
+69	3	0
+549	1	1
+69	1	1
+74	9	9
+126	1	1
+47	1	1
+614	9	9
+138	1	1
+29	1	1
+681	1	1
+49	1	1
+67	1	1
+19	4	9
+234	1	1
+93	1	1
+60	4	4
+96	4	4
+76	1	1
+169	1	1
+418	1	1
+130	1	1
+44	1	1
+69	1	1
+80	1	1
+76	1	1
+41	1	1
+129	6	11
+363	1	1
+42	1	1
+295	1	1
+43	1	1
+83	6	0
+52	0	2
+1228	1	1
+34	1	1
+3527	20	0
+1768	2	1
+2467	0	2
+101	10	0
+129	1	1
+37	1	1
+121	1	1
+25	1	1
+161	1	0
+97	1	1
+124	1	0
+178	1	1
+34	1	1
+54	1	1
+38	1	2
+634	83	83
+874	1	1
+40	1	1
+59	0	1
+59	4	4
+316	1	1
+178	1	1
+103	1	1
+61	1	1
+220	1	1
+61	1	1
+296	1	1
+33	1	1
+185	12	12
+269	1	1
+84	1	1
+864	15	15
+241	1	0
+79	3	3
+161	1	1
+48	1	1
+539	1	1
+44	1	1
+357	1	1
+37	1	1
+436	1	1
+59	1	1
+71	1	1
+261	1	1
+289	1	1
+47	1	1
+95	12	12
+97	4	4
+27	1	1
+100	1	1
+16	1	1
+101	1	1
+33	1	2
+481	1	1
+42	1	1
+206	7	7
+56	12	12
+179	10	10
+80	1	1
+41	1	1
+251	1	1
+306	1	1
+80	2	0
+4	94	0
+433	1	1
+23	1	1
+107	1	0
+265	1	1
+49	1	1
+282	72	72
+838	7	7
+60	1	0
+108	1	1
+24	1	1
+134	1	1
+32	1	0
+158	0	2
+1040	1	1
+42	1	1
+737	1	0
+790	1	1
+9	2	1
+11	1	1
+129	1	1
+23	1	1
+894	1	1
+43	3	3
+854	1	1
+23	0	1
+23	2	0
+26	1	1
+395	0	15
+403	5	5
+14	1	1
+2454	1	1
+76	1	1
+170	1	1
+18	1	1
+574	4	0
+291	1	1
+47	1	1
+786	19	0
+88	10	11
+48	1	1
+58	1	1
+28	1	1
+500	0	2
+1280	1	1
+28	1	1
+975	1	0
+3231	1	0
+865	1	1
+39	1	1
+1561	109	100
+1037	0	1
+510	1	1
+49	1	1
+1253	1	1
+19	1	1
+1078	3	0
+221	1	1
+21	1	0
+899	0	4
+466	1	1
+38	1	1
+297	0	3
+730	19	6
+1043	1	1
+49	1	1
+273	0	1
+708	1	0
+364	14	13
+58	1	1
+74	1	1
+614	60	60
+1889	4	0
+531	1	1
+19	1	1
+1944	5	0
+163	6	7
+1206	0	2
+718	1	1
+41	7	0
+1795	13	13
+1390	1	0
+2933	0	16
+540	1	1
+14	1	1
+167	1	0
+897	17	4
+1208	1	0
+1307	1	1
+20	1	1
+540	0	10
+203	2	0
+44	1	1
+298	1	0
+87	11	10
+491	14	8
+991	1	1
+74	6	0
+179	1	1
+34	1	1
+448	10	0
+1688	1	1
+38	21	0
+173	1	1
+49	2	1
+2161	30	30
+203	1	0
+89	1	0
+492	1	1
+30	1	1
+1212	3	0
+990	1	1
+38	1	1
+780	1	0
+191	1	1
+47	6	6
+393	1	1
+41	1	1
+259	1	0
+941	1	1
+20	1	1
+185	0	6
+165	0	16
+420	3	1
+130	1	1
+31	1	1
+253	18	18
+720	16	18
+1257	3	0
+986	0	4
+3311	1	1
+26	1	1
+556	0	4
+120	0	1
+1273	1	1
+20	1	1
+338	8	8
+3965	0	3
+15	1	1
+2531	17	17
+3334	5	5
+121	13	13
+161	1	1
+45	1	1
+94	14	14
+63	9	10
+2108	1	1
+34	1	1
+1436	1	1
+47	1	1
+273	7	0
+153	0	5
+283	12	12
+619	1	1
+36	0	4
+225	1	1
+23	1	1
+553	5	0
+2334	1	1
+49	1	1
+350	1	1
+31	1	1
+1012	2	2
+422	1	1
+46	1	1
+91	4	19
+468	0	1
+46	1	1
+1491	0	4
+426	0	1
+1144	1	2
+1131	1	1
+20	1	1
+1533	16	0
+3103	44	45
+4016	12	12
+346	0	1
+943	1	0
+524	1	1
+20	1	1
+151	3	3
+144	1	1
+189	1	7
+750	1	0
+695	1	0
+1003	0	2
+7819	1	1
+78	1	1
+1811	0	1
+3177	0	1
+8990	0	1
+2268	1	1
+35	0	10
+8205	1	0
+3193	1	1
+76	1	1
+10955	0	1
+22875	0	20
+2417	1	0
+998	0	13
+4236	8	0
+4845	0	2
+64	40	34
+10941	1	1
+40	1	1
+4759	0	6
+12084	0	3
+3052	0	4
+2989	1	0
+13523	1	3
+16170	1	0
+11761	0	3
+3912	3	0
+6620	0	7
+7633	3	0
+419	2	0
+10690	5	24
+10798	0	1
+296	0	1
+1770	4	0
+374	0	4
+230	16	16
+7468	1	0
+1229	1	0
+3061	1	0
+5818	1	0
+2415	12	9
+2056	0	1
+955	4	0
+20022	0	1
+4418	2	1
+2375	0	4
+2086	1	1
+32	1	1
+1225	1	0
+857	2	0
+1154	0	1
+4667	1	0
+170	0	3
+2376	0	1
+2799	10	10
+1512	4	0
+68	9	1
+2170	1	1
+47	1	1
+318	2	0
+19	0	6
+14527	1	1
+33	1	1
+3080	1	1
+23	1	1
+1645	6	6
+231	0	1
+2136	2	0
+6222	0	1
+830	1	1
+24	1	1
+8326	1	0
+2939	1	0
+3959	0	2
+3746	0	2
+1011	1	1
+34	1	1
+7443	0	1
+688	2	0
+574	1	1
+29	1	1
+1799	13	1
+4074	2	0
+136	1	1
+77	1	1
+528	19	0
+253	0	1
+204	1	0
+129	2	0
+811	1	1
+38	1	1
+2347	52	0
+4634	1	0
+856	14	14
+193	0	4
+855	1	1
+28	1	1
+1255	1	1
+36	1	1
+97	0	1
+58	1	1
+1708	1	1
+48	1	1
+958	15	0
+3371	1	1
+37	1	1
+4267	0	13
+1061	0	1
+272	0	26
+8	1	15
+25	0	2
+112	2	0
+26	4	32
+4090	0	1
+3270	1	1
+17	1	1
+2822	0	1
+6206	1	0
+2318	0	2
+1504	0	1
+6189	3	0
+396	22	12
+918	0	1
+2340	1	1
+33	1	1
+326	1	1
+80	1	1
+205	3	2
+81	8	17
+2671	0	1
+1099	0	1
+144	1	1
+29	0	1
+2097	0	3
+24	3	0
+1207	4	4
+45	1	1
+757	0	5
+1926	1	1
+40	1	1
+2657	0	1
+414	1	0
+61	0	1
+235	0	2
+2087	0	1
+713	0	4
+58	3	0
+1027	3	0
+428	1	1
+17	1	1
+948	1	1
+41	1	1
+458	1	1
+21	1	1
+1055	0	1
+6611	0	3
+1575	4	5
+36	1	1
+99	2	0
+700	0	2
+151	0	1
+467	11	11
+272	0	3
+40	1	1
+2428	0	1
+750	2	0
+473	0	2
+421	1	1
+34	1	1
+1575	1	0
+3841	1	0
+560	1	0
+1108	1	0
+8087	1	0
+11881	1	1
+30	1	1
+4383	2	0
+6883	49	49
+3146	0	1
+906	3	0
+887	1	1
+80	1	1
+3115	0	1
+1037	1	0
+5866	0	2
+18	1	1
+582	0	5
+2828	1	0
+847	1	0
+1996	3	0
+3170	1	0
+1751	0	1
+910	3	0
+691	0	1
+5793	0	1
+26407	1	0
+672	0	1
+19269	29	35
+1371	29	0
+494	2	0
+20417	1	0
+18633	0	1
+601	1	0
+319	0	1
+6820	1	0
+5718	0	2
+17894	1	0
+4272	1	0
+4967	3	1
+290	1	0
+2447	1	0
+740	1	9
+9299	0	18
+7427	1	0
+8151	2	1
+673	1	0
+3453	0	1
+149	0	1
+611	0	4
+4662	0	4
+1752	1	1
+78	1	1
+1581	0	1
+1092	2	0
+159	1	0
+4480	0	2
+4019	0	1
+1451	22	23
+816	1	0
+8701	1	1
+23	1	1
+1796	2	0
+5015	6	1
+1383	8	0
+2368	1	1
+31	1	0
+1883	3	0
+335	0	1
+4157	0	1
+561	4	0
+1538	1	1
+61	0	1
+159	0	2
+3362	4	0
+3333	1	1
+46	1	1
+2307	1	0
+170	1	0
+5972	0	2
+840	0	2
+55	1	1
+28	1	1
+1154	0	2
+650	0	4
+30	0	4
+1100	10	11
+4343	6	0
+1663	4	0
+150	1	0
+3128	1	0
+1449	1	0
+2023	0	1
+428	3	6
+299	2	0
+427	7	7
+1914	14	14
+1273	7	7
+1444	72	0
+423	0	4
+954	1	0
+2467	1	0
+190	8	8
+2034	3	1
+6396	1	1
+34	1	1
+485	1	0
+348	7	0
+770	1	1
+29	0	13
+65	1	1
+1358	0	1
+302	0	1
+659	12	12
+293	0	1
+610	0	1
+906	12	0
+1331	0	6
+1786	0	1
+463	0	1
+4305	0	4
+1041	1	0
+11424	3	1
+13797	0	8
+166	0	1
+1510	5	0
+9069	0	8
+25	1	1
+332	5	3
+76	0	1
+1306	1	1
+46	1	1
+134	19	23
+1467	1	1
+32	1	1
+449	17	0
+367	9	9
+3525	12	10
+91	3	0
+1430	1	1
+24	1	1
+1156	9	13
+843	1	1
+28	1	1
+515	0	17
+1559	0	4
+1045	9	9
+1953	1	0
+31	1	1
+843	0	1
+2174	1	0
+3788	1	0
+2001	0	1
+2400	0	1
+1614	1	0
+8167	0	1
+2700	2	0
+2735	0	1
+8508	1	1
+57	1	1
+141	0	3
+448	1	1
+22	1	1
+2215	1	1
+32	1	1
+1714	32	32
+667	14	14
+142	1	0
+789	1	1
+45	1	1
+84	1	1
+95	1	1
+465	1	1
+45	6	4
+541	1	1
+42	1	1
+1339	5	6
+391	1	1
+20	0	1
+251	1	1
+22	1	1
+561	0	2
+78	3	0
+1718	1	1
+12	1	1
+1042	1	1
+38	1	1
+301	14	0
+222	10	10
+436	10	10
+556	55	55
+953	1	1
+17	1	1
+1752	20	0
+1561	135	0
+58	0	45
+245	101	11
+46	90	0
+150	0	270
+54	180	0
+2130	12	12
+1630	1	1
+26	1	1
+189	0	14
+296	2	0
+809	2	0
+17	20	0
+665	0	40
+236	1	1
+44	1	1
+352	1	1
+25	1	1
+554	6	6
+850	1	1
+33	1	1
+809	3	13
+1832	7	9
+468	1	1
+21	1	1
+951	1	1
+22	1	1
+219	17	18
+733	0	14
+215	2	2
+36	1	1
+301	1	1
+22	1	1
+241	1	1
+52	0	1
+47	1	1
+72	1	1
+109	1	1
+129	1	1
+28	1	1
+174	8	8
+683	3	0
+1190	285	0
+48	1	1
+1330	12	0
+557	17	17
+932	3	1
+27	1	1
+166	1	1
+19	1	1
+406	1	1
+48	3	3
+137	1	0
+161	6	6
+884	2	0
+58	1	1
+107	1	1
+150	14	14
+522	1	1
+28	1	1
+945	4	4
+34	1	1
+472	0	2
+203	0	1
+281	1	1
+46	1	1
+1130	1	0
+232	17	17
+510	1	1
+33	1	1
+62	10	10
+1501	1	1
+20	1	1
+573	1	1
+29	1	1
+928	0	3
+304	1	1
+41	1	1
+160	1	1
+58	1	1
+656	1	1
+40	4	0
+108	6	6
+321	1	1
+14	0	16
+91	1	1
+184	1	1
+43	8	3
+180	1	1
+68	1	1
+144	1	1
+27	1	0
+17	1	1
+212	0	1
+212	1	1
+34	1	1
+115	1	1
+41	1	1
+407	10	10
+200	1	1
+44	2	0
+187	2	0
+146	1	1
+17	1	1
+122	4	4
+73	1	0
+56	1	1
+155	1	17
+80	15	15
+458	1	1
+16	3	3
+343	1	1
+111	1	1
+160	55	55
+157	12	12
+346	0	2
+382	4	0
+35	1	1
+937	0	1
+246	25	0
+52	0	1
+419	0	1
+165	1	0
+75	24	3
+297	1	1
+38	1	1
+5066	1	0
+4922	7	9
+2488	14	14
+2241	1	1
+67	4	4
+39	1	0
+547	1	1
+43	1	1
+524	3715	901
+1796	4	2
+138	2	2
+16	1	1
+415	1	1
+18	1	1
+367	0	89
+1600	0	6
+2175	0	5
+606	14	14
+519	1	0
+540	1	1
+40	1	1
+568	2	0
+165	1	2
+31	1	1
+259	1	1
+41	1	1
+452	31	31
+623	40	62
+818	1	1
+42	1	1
+565	1	1
+44	1	1
+571	10	8
+61	1	1
+28	1	1
+233	2	0
+33	28	0
+53	1	1
+37	1	1
+75	0	396
+156	1	0
+473	0	4
+421	1	1
+35	1	1
+2132	1	1
+80	0	2
+544	9	9
+152	2	1
+33	1	1
+2932	1	1
+44	0	1
+164	22	0
+149	1	0
+534	1	1
+36	1	1
+113	1	1
+15	1	1
+661	1	1
+48	1	1
+1987	1	0
+34	1	1
+444	1	1
+45	1	1
+65	1	1
+67	1	1
+210	1	1
+68	1	1
+55	1	1
+47	1	1
+169	1	1
+64	1	1
+109	0	6
+77	2	32
+6	0	5
+67	0	1
+7	16	0
+51	12	0
+36	0	12
+700	1	1
+33	1	0
+49	0	2
+450	0	1
+98	4	0
+489	32	0
+63	5	1
+78	7	7
+538	17	17
+1269	1	0
+841	1	1
+43	1	1
+2004	1	1
+41	1	1
+86	0	4
+5	1	0
+36	1	1
+573	2	1
+297	1	0
+85	1	1
+30	1	1
+1041	1	0
+12	1	1
+392	33	12
+515	5	6
+583	1	1
+33	1	1
+616	16	16
+1052	0	11
+39	1	1
+184	1	1
+67	1	1
+102	7	7
+58	0	1
+307	1	1
+56	0	3
+930	21	19
+1264	0	1
+832	1	1
+28	1	1
+272	1	1
+82	1	1
+56	1	0
+976	6	6
+2015	0	3
+84	9	9
+130	13	17
+564	10	15
+154	1	0
+438	10	10
+38	0	5
+2141	1	1
+25	1	1
+73	10	10
+70	5	5
+132	1	1
+52	1	1
+599	1	1
+46	1	1
+279	1	1
+18	1	1
+239	2	0
+383	6	0
+224	0	1
+321	3	0
+8	16	0
+1775	1	1
+18	2	0
+575	16	16
+60	1	1
+16	1	1
+1247	2	0
+173	3	0
+41	1	1
+57	8	8
+285	2	0
+672	1	1
+44	1	1
+106	0	1
+148	1	1
+49	3	0
+146	5	11
+91	1	1
+79	1	1
+94	1	1
+101	1	1
+88	16	16
+117	1	1
+15	1	1
+58	1	1
+93	1	1
+140	1	0
+326	1	1
+44	1	1
+160	1	1
+23	1	1
+481	14	14
+181	4	4
+72	1	1
+25	1	1
+88	1	3
+36	0	12
+92	1	1
+56	10	0
+13	0	1
+66	1	1
+141	2	0
+65	1	1
+367	0	2
+610	1	1
+22	1	1
+150	1	1
+85	1	1
+109	1	1
+167	3	1
+23	1	0
+26	1	1
+74	1	1
+33	1	1
+176	1	1
+25	2	2
+193	1	1
+35	0	1
+383	0	5
+249	1	1
+69	1	1
+98	1	1
+62	1	1
+62	1	2
+74	0	1
+68	1	1
+438	1	1
+64	1	1
+47	0	8
+125	3	0
+75	5	5
+45	1	1
+197	1	1
+27	1	1
+116	13	13
+218	15	20
+1107	16	19
+73	1	1
+25	1	1
+199	1	1
+60	1	1
+994	1	1
+43	0	1
+18	1	1
+1215	18	18
+340	1	1
+34	1	1
+1350	16	16
+1726	4	4
+193	1	1
+48	1	1
+295	1	1
+18	1	1
+411	19	19
+175	1	1
+49	1	1
+146	1	1
+61	1	1
+116	1	1
+41	1	1
+137	1	1
+30	1	1
+158	9	9
+136	10	13
+349	8	8
+468	1	1
+44	1	1
+862	17	17
+813	1	1
+24	1	1
+214	10	4
+228	1	1
+34	1	1
+101	12	12
+242	1	1
+69	1	1
+185	1	1
+24	1	0
+164	0	1
+222	1	1
+25	1	1
+297	10	10
+1171	1	0
+182	1	1
+35	1	1
+350	19	19
+1966	1	1
+24	1	1
+548	7	7
+208	13	12
+298	1	1
+65	1	1
+193	2	2
+28	1	1
+125	4	4
+95	7	7
+566	1	1
+40	1	1
+118	0	1
+318	1	0
+374	1	1
+58	1	1
+143	1	1
+74	1	1
+53	21	0
+81	1	1
+45	1	1
+138	15	16
+180	1	1
+62	1	1
+661	1	1
+48	1	1
+1463	1	0
+156	0	1
+148	1	1
+19	1	0
+17	1	1
+1927	4	0
+1469	14	14
+466	0	1
+3098	0	1
+1141	2	3
+743	14	14
+79	1	1
+22	1	1
+362	0	1
+682	16	9
+275	0	4
+539	1	0
+61	0	7
+331	0	4
+130	1	1
+31	0	3
+1554	1	1
+43	1	1
+224	1	1
+49	1	1
+159	3	0
+1064	27	27
+104	1	1
+21	1	1
+222	2	2
+49	1	1
+1397	1	1
+37	1	1
+414	0	2
+695	1	1
+31	1	1
+742	1	1
+21	1	1
+230	3	2
+42	1	1
+68	1	1
+37	1	1
+703	0	3
+2216	84	83
+1430	1	1
+23	1	1
+1867	13	0
+35	1	1
+137	16	16
+1500	4	0
+4546	1	1
+25	1	1
+358	19	19
+1549	1	1
+39	4	3
+1037	1	1
+40	2	0
+890	6	0
+41	2	0
+498	3	0
+321	0	1
+281	3	0
+414	1	1
+70	1	1
+284	1	0
+214	1	1
+28	1	1
+280	1	0
+650	1	1
+47	1	1
+1030	1	1
+91	1	1
+6520	5	5
+462	1	0
+2864	0	3
+1930	0	4
+2915	1	1
+20	1	1
+413	1	0
+1844	11	11
+133	0	6
+569	10	10
+110	12	12
+184	0	3
+228	1	1
+43	2	2
+51	14	13
+1499	1	0
+12	1	1
+378	1	1
+49	1	1
+424	1	0
+1069	1	1
+142	0	1
+821	2	9
+311	1	6
+247	1	1
+86	1	1
+1850	1	1
+26	1	1
+498	1	1
+34	1	1
+688	5	9
+44	1	1
+369	1	1
+69	1	1
+156	2	0
+83	1	1
+128	1	1
+50	9	9
+249	1	1
+70	0	1
+624	2	0
+74	2	1
+300	1	1
+26	1	1
+240	4	0
+1705	1	1
+52	1	1
+231	29	24
+378	2	0
+236	1	1
+76	1	1
+116	9	12
+301	20	20
+59	0	6
+43	1	1
+384	15	15
+1414	5	0
+225	0	2
+1234	1	0
+29	1	1
+235	10	10
+227	1	1
+77	4	0
+43	5	9
+485	7	7
+380	10	0
+46	1	0
+90	1	1
+161	1	1
+401	1	1
+58	1	1
+2127	3	0
+186	20	20
+323	5	5
+47	1	1
+236	1	1
+31	0	2
+1568	1	1
+136	0	1
+202	0	3
+77	1	1
+44	1	1
+411	12	11
+317	0	2
+599	1	1
+37	1	1
+391	1	0
+273	1	0
+744	0	4
+703	1	1
+20	1	1
+198	3	0
+158	19	15
+27	12	0
+282	1	1
+32	4	0
+740	1	0
+327	1	1
+105	1	1
+146	16	16
+101	1	0
+21	1	1
+232	1	1
+33	2	0
+12	1	1
+189	1	1
+30	2	2
+544	1	1
+153	1	1
+586	5	0
+1351	21	0
+446	49	49
+121	7	7
+1147	12	12
+777	1	0
+701	1	1
+29	2	2
+154	12	12
+191	1	1
+55	1	1
+113	0	1142
+87	0	2
+15	0	1
+525	1	1
+22	1	1
+355	10	10
+50	0	8
+252	1	1
+31	1	1
+354	6	5
+148	15	15
+407	1	1
+42	1	1
+275	0	1
+737	5	9
+1432	1	1
+39	1	1
+84	0	2
+77	7	7
+514	20	20
+385	7	1
+815	1	1
+45	1	1
+487	1	1
+66	1	1
+2379	0	24
+779	1	1
+18	1	0
+2653	4	0
+34	1	1
+191	1	1
+35	1	1
+1174	12	0
+2497	1	1
+24	0	1500
+447	8	0
+3268	1	0
+946	1	0
+2223	20044	20060
+119	1	1
+71	0	3
+53	0	5
+40	1	1
+309	1	1
+57	1	1
+101	1	1
+47	2	2
+67	1	1
+47	1	1
+74	0	1
+28	1	1
+167	1	1
+33	1	1
+543	1	1
+27	11	34
+33	1	1
+149	7	7
+61	1	1
+120	1	1
+366	1	1
+55	1	1
+121	1	1
+62	1	1
+78	1	1
+48	1	1
+161	1	1
+26	1	1
+191	1	1
+20	11	11
+550	1	1
+76	1	0
+20	1	1
+112	1	1
+149	1	1
+284	1	1
+37	1	1
+705	1	12
+106	12	12
+83	1	1
+46	1	1
+1500	1	1
+81	1	1
+210	1	1
+26	1	1
+713	1	1
+48	1	1
+723	0	3
+196	6	6
+62	2	2
+32	1	1
+606	1	2
+357	1	1
+38	292	0
+589	1	1
+30	1	1
+714	8	8
+639	1	1
+20	1	1
+1068	0	1
+571	1	1
+49	1	1
+436	0	1
+609	0	2
+30	1	1
+66	0	1
+349	11	11
+65	1	1
+40	1	1
+717	0	3
+299	1	1
+29	1	1
+724	1	0
+275	1	1
+33	1	1
+318	0	3
+279	1	1
+28	1	1
+389	1	0
+548	0	8
+330	1	1
+47	1	1
+170	1	1
+47	1	1
+519	14	14
+841	24	24
+732	1	1
+29	3	3
+688	2	2
+23	0	1
+94	14	14
+726	13	13
+508	0	12
+21	6	0
+69	1	1
+37	1	1
+590	1	1
+59	1	1
+89	11	11
+164	1	1
+58	1	1
+1709	18	18
+520	1	1
+27	1	1
+683	10	10
+814	1	1
+26	1	1
+350	1	1
+39	1	1
+132	6	6
+439	10092	10075
+78	15	15
+3352	1	1
+23	1	1
+873	4	4
+887	1	0
+1827	1	0
+216	6	6
+805	2	0
+874	0	8
+2266	1	1
+47	1	1
+761	0	4
+86	1	1
+19	1	1
+1794	9	9
+271	0	1
+2266	1	1
+34	1	1
+916	0	1
+21	1	1
+108	21	21
+141	1	1
+27	1	1
+406	3	0
+3950	1	1
+38	1	1
+128	2	2
+56	1	1
+72	0	1
+96	1	1
+22	1	1
+169	7	7
+511	1	1
+38	1	1
+1070	1	1
+90	1	1
+50	1	1
+41	1	0
+30	1	1
+659	12	12
+701	1	1
+33	1	1
+569	15	15
+70	1	1
+38	1	1
+955	0	3
+130	1	1
+63	1	1
+251	8	8
+191	1	1
+26	0	3
+187	1	0
+916	5	1
+70	13	13
+498	20061	20021
+160	1	1
+76	1	1
+95	1	1
+76	1	1
+275	1	0
+101	1	1
+79	1	1
+100	7	7
+159	1	1
+75	0	8
+87	1	1
+76	1	1
+44	1	1
+71	32	32
+89	11	12
+196	1	1
+55	0	2
+61	1	1
+83	0	1
+944	1	1
+126	1	1
+81	6	6
+41	3	0
+641	1	1
+92	1	0
+113	1	1
+39	1	1
+671	1	1
+28	1	1
+123	1	1
+59	1	1
+210	1	1
+17	1	1
+168	15	14
+494	1	0
+22	1	1
+484	18	18
+376	1	1
+114	2	0
+67	1	1
+10	1	1
+109	1	1
+165	1	1
+149	6	6
+234	1	1
+19	5	5
+64	1	1
+111	1	1
+220	1	1
+89	1	1
+119	1	1
+113	2	0
+168	1	1
+73	1	1
+194	1	1
+50	0	4
+37	1	1
+95	3	1
+43	1	1
+153	1	1
+83	1	1
+55	1	1
+39	1	1
+70	7	0
+59	7	7
+75	1	1
+84	2	2
+110	1	0
+42	1	1
+129	9978	10000
+438	1	1
+43	1	0
+55	1	1
+40	1	1
+175	1	1
+46	1	1
+52	1	1
+19	1	1
+277	1	1
+60	1	1
+98	1	1
+24	1	1
+333	4	4
+1047	2	0
+4080	1	1
+38	1	1
+837	0	64
+172	1	1
+55	1	1
+1818	2	0
+1143	13	13
+335	1	0
+1944	5	0
+39	6	0
+4057	3	8
+9465	5	4
+301	19	1
+191	84	0
+427	1	1
+29	0	4
+157	4	5
+296	21	18
+158	2	2
+36	1	1
+539	13	13
+399	1	1
+46	1	1
+348	1	1
+49	1	1
+268	1	0
+66	0	4
+178	2	2
+107	1	1
+133	5	5
+355	1	1
+30	1	1
+346	1	1
+29	1	1
+161	1	1
+38	1	1
+121	4	4
+55	8	8
+67	7	7
+318	17	17
+259	1	1
+94	1	1
+80	1	1
+35	1	1
+260	1	1
+81	1	1
+106	1	1
+58	1	2
+301	3	0
+2052	1	1
+40	1	1
+174	20	22
+574	0	2
+414	1	0
+234	0	1
+425	51224	51060
+1568	14	14
+11956	0	1
+2667	0	2
+884	1	1
+19	1	1
+676	1	1
+63	1	1
+3138	0	3
+3038	5	2
+132	10	6
+136	18	13
+363	1	1
+89	1	1
+382	1	1
+29	1	1
+58	8	7
+297	4	0
+66	1	1
+93	2	0
+145	1	1
+31	5	5
+576	1	1
+89	1	1
+1256	0	12
+67	1	1
+193	2	2
+23	1	1
+51	1	0
+727	1	0
+1148	12	12
+837	1	1
+77	1	1
+941	10	10
+776	19	19
+300	1	1
+24	1	1
+256	1	7
+93	1	1
+224	2	0
+138	1	1
+563	1	1
+104	4	4
+2898	1	1
+46	1	1
+282	1	1
+39	1	1
+204	2	2
+22	1	1
+469	1	1
+20	1	1
+140	1	1
+26	1	1
+745	0	2
+539	0	6
+1536	1	0
+817	4	4
+202	1	1
+48	1	1
+168	1	1
+53	1	1
+379	10	10
+1178	14	14
+132	5	0
+555	1	1
+42	1	1
+573	1	1
+21	1	1
+462	1	1
+43	1	1
+121	1	1
+48	0	3
+15	1	5
+1404	0	1
+934	1	1
+49	1	1
+1350	1	0
+384	1	1
+24	1	1
+4169	0	15
+244	10	10
+2167	18	14
+64	1	1
+31	1	1
+185	0	4
+1647	1	1
+20	1	1
+227	1	1
+37	1	1
+636	3	4
+5590	1	1
+39	1	1
+461	0	2
+2145	1	1
+23	1	1
+1114	0	2
+688	0	1
+901	18	18
+4781	0	4
+815	0	1
+5027	42	47
+415	0	1
+2743	1	1
+78	1	1
+390	1	0
+328	0	1
+878	0	1
+5752	0	2
+1554	1	1
+60	1	1
+278	0	1
+19	1	1
+1164	11	11
+691	0	2
+960	1	0
+62	0	20
+2108	0	2
+1265	0	1
+1642	2	0
+3584	2	0
+12086	2	0
+3766	0	2
+1209	1	7
+3466	1	0
+1448	1	0
+1943	0	1
+698	0	8
+1166	135	135
+2030	2	0
+540	1	0
+1736	14	0
+3128	0	2
+4464	0	1
+3597	1	0
+378	1	0
+1269	0	3
+1182	1	0
+654	0	3
+2049	1	0
+6838	1	1
+69	0	3
+154	1	0
+2718	1	1
+30	1	1
+160	11	11
+4954	0	1
+420	1	1
+123	1	1
+156	0	4
+219	4	0
+195	1	0
+4402	3	0
+3045	0	1
+1249	1	0
+3522	0	10
+675	20	20
+117	8	0
+346	0	1
+8538	5	0
+455	1	0
+119	0	1
+355	48	48
+724	1	0
+9254	22	22
+1672	1	0
+833	0	1
+4251	1	0
+8	1	1
+2079	0	1
+1735	8	12
+1612	0	1
+1373	5	0
+8585	7	0
+64	1	1
+3799	1	0
+258	2	0
+899	1	0
+1362	8	9
+593	0	2
+3351	2	0
+618	0	4
+905	2	15
+2797	1	0
+2776	2	0
+4110	0	6
+4466	18	18
+1783	9	9
+475	0	4
+134	1	0
+12963	8	0
+1616	0	2
+1685	2	0
+2225	2	0
+428	0	1
+458	20	20
+2860	0	3
+677	4	6
+325	11	1
+1887	0	1
+913	0	1
+997	5	5
+2814	17	15
+1389	1	0
+1200	0	4
+2495	1	0
+3921	26431	26426
+2419	0	1
+6110	0	1
+1370	0	1
+3085	1	0
+3568	1	1
+24	0	9
+597	1	0
+2642	1	0
+1545	10	0
+4952	0	1
+6146	2	0
+1452	1	0
+2967	1	0
+4920	5	0
+147	4	5
+850	1	0
+1875	1	0
+695	3	1
+1719	0	1
+259	0	1
+294	1	0
+128	0	2
+3051	0	1
+908	0	4
+3399	0	1
+4673	1	0
+3179	1	0
+411	1	1
+44	1	1
+174	1	0
+1047	17	17
+998	178	0
+671	0	40
+2093	1	0
+313	0	1
+7581	1	0
+3245	1	0
+972	0	4
+4085	2	0
+346	1	1
+45	1	1
+368	1	0
+26	1	1
+8444	0	1
+17044	1	0
+2795	2	0
+2860	1	0
+622	0	1
+167	0	5
+1968	0	2
+259	2	0
+4992	29	27
+170	1	0
+3528	0	1
+191	1	2
+117	2	0
+2275	1	0
+12676	1	1
+20	1	1
+9972	1	0
+13955	0	5
+19867	1	0
+9612	1	0
+14233	0	32737
+6316	1	1
+19	1	1
+970	8	8
+2685	16	16
+18093	0	1
+6799	0	16
+3350	0	1
+7574	0	12
+2132	0	1
+7228	52793	52800
+1955	22	22
+698	0	1
+2149	1	0
+6880	0	2
+960	0	1
+23	1	1
+2646	2	0
+3867	5	0
+26077	0	3
+3174	1	0
+8183	0	1
+2817	10	0
+5841	1	0
+2081	0	1
+374	0	2
+3589	0	4
+10625	28	28
+3275	3	0
+773	7	7
+175	1	1
+79	1	1
+400	12	12
+1096	0	4
+717	7	7
+52	1	1
+68	5	1
+2117	0	3
+130	14	14
+1124	0	3
+413	0	4
+643	3	0
+58	1	1
+127	1	1
+196	0	2
+226	3	0
+136	3	4
+293	1	1
+25	0	3
+63	1	1
+417	0	2
+412	0	16
+737	4	0
+402	2	0
+654	1	1
+42	1	1
+75	1	1
+64	1	1
+2980	4	0
+576	0	1
+29	2	2
+715	1	1
+36	1	1
+511	38	38
+218	4	40
+44	1	5
+43	49	5
+709	21	21
+1147	9	9
+22	1	1
+195	7	4
+659	3	0
+27	1	1
+637	1	1
+42	1	1
+531	1	1
+67	1	1
+39	1	0
+717	11	11
+53	1	1
+61	1	1
+1535	1	1
+89	0	1
+49	1	0
+102	1	1
+67	1	1
+76	1	1
+129	1	1
+85	1	1
+607	10	0
+12	137	1
+41	1	1
+1043	1	1
+22	1	1
+203	3	0
+480	14	21
+91	23	23
+1345	2	1
+435	15	17
+1188	30	0
+1778	1	0
+120	0	3
+3797	1	0
+3211	0	1
+2456	4	0
+954	0	4
+1847	0	1
+5929	20	20
+984	14	0
+2112	1	0
+2013	1	0
+1770	14	14
+3100	1	0
+1160	16	0
+733	7	7
+238	3	2
+2203	2	1
+5654	1	1
+28	5	10
+482	0	1
+2970	0	4
+2892	0	1
+251	1	7
+1346	1	0
+877	0	4
+3583	0	1
+1178	0	1
+1293	0	2
+491	2	0
+6803	1	1
+22	1	1
+2218	1	1
+44	1	1
+4780	4	0
+3026	14	13
+442	5	5
+2022	6	6
+506	2	0
+8557	1	1
+36	1	0
+1575	1	0
+1329	1	1
+35	1	0
+247	1	1
+16	1	1
+184	1	1
+18	1	1
+1636	0	7
+23	1	1
+527	1	1
+39	1	1
+653	3	0
+227	1	1
+18	1	1
+218	0	323
+91	1	0
+124	0	15
+621	0	2
+555	8	8
+467	1	1
+40	1	1
+372	1	1
+25	1	1
+188	12	12
+357	0	2
+2389	1	1
+22	1	1
+2579	0	5
+461	1	1
+36	1	1
+1584	1	1
+26	1	0
+429	1	0
+33	1	1
+1071	0	4
+1068	9	0
+1472	0	2
+1839	94	92
+337	1	1
+46	1	1
+416	1	1
+42	1	1
+1255	0	2
+628	17	15
+587	15	15
+398	3	0
+623	1	1
+78	0	3
+287	10	0
+191	0	2
+493	1	1
+42	4	0
+219	0	1
+408	1	1
+23	1	1
+283	1	1
+21	1	1
+633	2	0
+241	6	6
+457	1	0
+330	0	16
+428	1	0
+4	6	0
+324	0	1
+3060	0	2
+9953	0	1
+1899	0	6
+6431	0	1
+8674	0	4
+4595	11	0
+5064	2	0
+2813	12	12
+1391	5	0
+3690	1	1
+64	1	1
+2635	1	1
+49	1	1
+69	1	1
+15	1	1
+605	4	4
+400	8	0
+735	0	20
+3074	2	0
+1879	0	1
+572	0	8
+576	1	1
+42	1	1
+265	24	0
+209	11	11
+953	1	1
+42	0	5
+58	1	0
+95	1	0
+1121	1	1
+17	1	1
+751	0	1
+24	1	1
+351	1	1
+43	3	3
+565	1	1
+15	1	1
+271	1	0
+323	1	1
+23	1	1
+221	7	7
+705	9	0
+631	2	0
+64	1	1
+1577	1	1
+21	0	1
+371	7	21
+160	0	1
+283	1	1
+48	1	1
+227	1	1
+40	0	1
+1359	0	2
+836	13	13
+722	7	7
+1153	1	1
+93	1	1
+797	14	14
+433	8	0
+108	11	11
+140	1	1
+40	1	1
+470	1	1
+42	1	1
+1106	0	1
+85	4	4
+129	1	1
+123	1	0
+95	1	1
+104	6	1
+641	1	1
+77	1	1
+57	1	1
+62	1	1
+473	2	0
+262	6	0
+45	1	1
+63	2	0
+39	1	1
+267	0	1
+197	2	104
+189	107	3
+112	0	4
+108	5	0
+563	14	14
+324	1	0
+205	1	1
+17	1	1
+495	0	1
+201	4	0
+14	1	1
+667	42	42
+178	1	1
+58	1	1
+133	1	1
+24	1	1
+91	24	24
+342	1	1
+32	1	1
+121	1	1
+62	1	1
+2371	2	0
+164	8	1
+655	1	1
+30	1	1
+271	1	1
+47	1	1
+609	1	0
+1780	2	0
+742	1	1
+40	1	1
+2014	1	0
+1741	3	0
+3833	0	1
+14622	161198	190000
+5156	0	1
+1680	1	1
+88	1	1
+4502	0	1
+46	1	1
+800	4	4
+23	1	1
+1305	2	0
+136	0	1
+4941	0	1
+547	0	1
+70	8	8
+293	1	1
+35	1	1
+1165	4	0
+6662	1	1
+46	1	1
+167	0	8
+214	1	1
+35	1	1
+108	1	0
+1063	0	1
+1017	1	1
+20	0	6
+1725	0	1
+150	5	5
+33	1	0
+12	1	1
+349	1	1
+24	0	1
+1562	1	1
+31	1	1
+2513	0	1
+73	36	36
+305	1	1
+27	1	1
+543	1	1
+47	4	28
+5476	10	10
+531	1	1
+37	1	1
+776	1	1
+44	2	2
+115	22	20
+181	1	1
+125	3	3
+466	1	1
+76	1	1
+144	5	5
+32	1	1
+225	1	1
+41	1	1
+707	24	24
+66	4	4
+414	1	1
+42	1	1
+81	1	1
+63	1	1
+76	28	46
+187	1	1
+97	1	1
+99	9	9
+85	14	14
+81	6	6
+62	1	1
+109	4	5
+150	1	0
+44	4	4
+93	11	11
+188	3	3
+73	1	1
+52	1	1
+19	13	0
+48	1	1
+62	0	7
+205	1	1
+68	9	9
+99	4	0
+21	1	0
+52	1	1
+171	1	1
+109	3	1
+6	0	2
+190	1	1
+69	10078	10069
+90	3	1
+197	1	1
+157	0	6
+137	1	1
+101	2	2
+233	6	6
+62	1	1
+104	0	1
+143	1	1
+119	1	1
+106	2	0
+176	1	1
+79	0	1
+50	1	1
+50	3	3
+179	1	1
+159	1	1
+36	1	1
+107	1	1
+176	1	1
+154	0	5
+91	1	1
+54	1	1
+77	1	1
+238	2	2
+50	1	1
+1421	1	1
+23	1	1
+216	1	1
+122	1	1
+86	1	1
+41	3	1
+336	7	7
+41	9	0
+107	1	1
+90	1	3
+6	1	0
+84	1	1
+213	1	1
+26	1	1
+138	1	1
+25	1	1
+206	1	1
+36	3	3
+37	7	0
+500	1	1
+52	1	1
+52	1	1
+48	1	1
+395	1	1
+66	6	6
+72	1	0
+69	1	1
+100	10	10
+160	1	0
+64	7	7
+89	1	1
+123	1	1
+128	1	1
+36	1	1
+231	1	1
+61	1	1
+564	8	8
+593	47	47
+163	1	0
+196	8	8
+174	5	5
+37	1	1
+67	0	1
+192	1	1
+60	3	0
+19	1	1
+1149	1	1
+18	1	1
+77	1	1
+32	2	0
+32	1	1
+136	1	1
+78	2	0
+162	4	0
+41	1	1
+351	13	13
+1634	2	0
+229	8	8
+57	13	2
+410	1	1
+76	1	1
+180	1	1
+92	1	1
+270	1	1
+40	1	1
+92	1	1
+53	1	1
+227	1	1
+42	1	1
+357	4	4
+23	1	1
+94	1	0
+200	6	0
+201	7	7
+70	5	13
+57	4	0
+35	1	1
+206	1	1
+76	2	2
+651	1	1
+68	4	0
+73	1	1
+49	4	0
+37	1	1
+145	2	2
+78	2	2
+108	12	12
+52	1	1
+35	1	1
+242	1	3
+76	2	2
+50	12	12
+70	1	1
+33	0	2
+57	1	1
+64	15	15
+168	1	1
+22	1	1
+63	36	37
+73	0	2
+64	1	1
+177	2	0
+19	4	0
+55	1	0
+33	1	1
+51	1	1
+122	1	1
+296	1	1
+85	1	1
+109	1	1
+64	1	1
+155	1	1
+58	0	2
+72	1	1
+25	1	1
+128	1	1
+45	2	0
+444	1	1
+25	1	1
+64	1	1
+21	1	1
+368	15	15
+734	2	0
+701	15	15
+71	1	1
+41	1	1
+77	1	1
+56	1	1
+478	2	0
+714	8	7
+95	2	2
+50	4	3
+1129	1	1
+34	1	1
+1715	1	1
+87	1	1
+692	1	1
+47	0	1
+75	1	1
+541	12	12
+1602	10	10
+1265	1	1
+46	1	1
+298	1	1
+22	1	1
+186	1	1
+34	1	1
+202	1	1
+61	1	0
+185	1	1
+24	1	0
+98	0	2
+258	8	14
+967	1	1
+15	1	1
+625	1	0
+1362	0	4
+23365	4	0
+246	26975	26986
+3307	0	1
+13671	3	3
+52	1	1
+1308	2	0
+942	0	1
+17790	1	0
+4586	0	1
+949	0	2
+15047	0	1
+606	2	0
+7820	0	4
+22313	16	0
+10539	8	0
+4836	0	1
+8320	18	18
+388	2	0
+194	1	1
+49	1	1
+320	1	1
+34	1	1
+6813	0	1
+8719	3	0
+7037	1	0
+721	0	1
+999	6	0
+17	1	0
+3075	5	0
+593	13	11
+1006	12	12
+3487	1	0
+9535	0	4
+23	0	2
+23	2	0
+513	0	3
+377	1	0
+2627	0	2
+16	0	1
+211	18	18
+571	2	0
+7617	0	1
+1607	1	0
+69	1	1
+66	1	1
+275	1	1
+67	7	0
+25	1	1
+1206	1	0
+136	8	7
+612	1	1
+61	1	1
+740	0	2
+78	26	26
+129	15	15
+69	12	16
+1483	13	28
+1062	1	0
+108	4	0
+685	0	2
+1566	1	0
+192	4	4
+1452	9	45
+1514	1	1
+46	1	1
+1969	0	1
+35	1	1
+1094	1	0
+618	1	1
+43	1	1
+6580	1	0
+1636	5	0
+6325	1	1
+32	1	1
+1041	0	2
+174	9	0
+11983	18	18
+142	8	8
+2203	10	8
+2025	1	1
+39	1	1
+907	4	4
+225	1	1
+124	1	1
+3928	0	22
+38	2	0
+44	18	0
+46	0	6
+61	0	1
+3653	6	0
+34	1	1
+4559	1	1
+28	1	1
+283	5	5
+1572	28	28
+351	1	1
+34	1	1
+443	19	19
+57	1	1
+21	1	1
+231	1	1
+94	1	1
+105	1	1
+208	5	5
+124	1	1
+112	3	3
+207	1	1
+38	1	1
+244	1	1
+60	1	1
+98	1	1
+50	1	1
+256	5	5
+23	1	1
+157	1	1
+33	1	1
+143	1	1
+59	1	1
+51	1	1
+45	1	0
+73	1	1
+81	1	1
+339	1	1
+56	0	5
+142	1	1
+232	1	1
+43	1	1
+332	1	1
+47	1	1
+479	1	0
+137	0	3
+1456	10	13
+63	1	1
+37	1	1
+261	0	2
+109	1	1
+50	1	1
+56	129	1
+88	1	0
+44	1	1
+54	1	1
+56	1	50
+58	50	1
+54	277	1
+44	1	1
+297	0	39
+142	1	1
+85	1	1
+124	16	16
+58	3	15
+677	1	0
+1333	2	0
+13591	6	0
+989	1	1
+107	1	1
+678	1	1
+31	1	1
+2571	5	5
+56	2	2
+39	1	1
+3986	0	4
+18351	32	30
+10811	1	1
+25	0	1
+417	1	1
+40	1	1
+159	4	4
+37	4	4
+179	1	1
+51	1	1
+103	2	0
+108	1	1
+79	1	1
+25	1	1
+58	1	1
+12	1	1
+275	14	0
+80	1	1
+83	1	1
+24	1	1
+59	1	0
+91	1	1
+65	1	1
+67	1	1
+136	4	0
+68	8	0
+331	5	0
+40	1	1
+110	10	6
+64	1	1
+368	1	1
+22	1	1
+509	1	1
+89	1	1
+926	1	0
+959	1	1
+44	1	1
+72	11	0
+47	1	1
+361	1	1
+37	1	1
+2204	2	2
+45	1	1
+1117	18	18
+141	1	1
+47	1	1
+148	1	1
+75	1	1
+104	1	0
+205	3	2
+249	1	1
+146	1	1
+94	1	1
+34	1	1
+700	0	331
+21	1	1
+73	1	1
+49	1	1
+356	1	1
+16	1	1
+112	1	1
+36	9	0
+515	1	1
+27	2	2
+192	1	1
+53	0	14
+82	1	1
+302	1	1
+68	1	1
+52	12	12
+52	1	1
+34	1	1
+166	7	7
+384	1	1
+31	1	1
+281	1	1
+57	1	1
+176	0	1
+1625	1	1
+26	1	1
+369	1	1
+21	1	1
+86	1	1
+134	1	1
+215	1	1
+214	15	1
+50	2	2
+26	1	1
+78	0	19
+64	1	1
+118	53	53
+433	1	1
+76	0	1
+6	12	0
+52	1	1
+108	1	1
+87	1	1
+62	1	1
+26	1	1
+291	2	1
+143	1	1
+29	1	1
+56	12	12
+230	1	1
+153	4	4
+87	32	32
+584	12	12
+227	1	0
+1931	4	0
+836	1	1
+68	1	1
+205	24	19
+816	1	2
+1932	0	7
+1732	13	0
+257	4	0
+1423	1	0
+129	6	0
+1505	1	1
+42	0	1
+373	13	13
+565	1	1
+76	1	0
+1881	0	4
+68	4	0
+43	0	4
+2201	8	8
+3726	3	0
+339	15	11
+249	1	1
+35	1	1
+250	1	1
+38	1	1
+359	11	12
+109	1	1
+43	18	0
+822	1	1
+53	1	1
+325	15	15
+123	1	1
+42	6	6
+240	1	1
+44	1	1
+438	7	7
+142	2	0
+1004	0	1
+9275	1	1
+37	1	0
+2071	0	1
+1253	9	9
+9137	0	1
+12513	2	1
+11243	1	1
+26	1	1
+816	4	0
+15996	2	0
+1594	1	0
+363	5	0
+6757	47	41
+2700	1	0
+841	0	1
+1807	0	2
+2565	11	0
+2089	0	2
+477	1	0
+657	0	1
+776	0	20
+365	82	49
+779	0	1
+401	25	63
+441	0	2
+1152	0	2
+1315	1	0
+5352	6	8
+902	0	1
+2154	1	1
+36	1	1
+109	0	1
+668	6	0
+1923	0	1
+91	3	2
+3560	1	0
+1235	1	0
+139	26	0
+7381	1	0
+155	0	14
+2393	1	1
+33	1	1
+507	4	0
+1337	0	1
+9954	3	0
+1588	1	0
+2605	1	1
+23	1	1
+3000	0	3
+8249	8	0
+912	0	1
+338	2	0
+734	1	0
+4332	1	0
+416	0	4
+1691	0	1
+295	1	0
+214	2	0
+121	0	1
+784	0	1
+2512	0	1
+4465	12	11
+926	1	0
+190	1	0
+5780	0	1
+490	5	0
+228	1	1
+45	1	1
+207	3	0
+322	0	1
+633	1	1
+24	1	0
+1516	5	0
+1025	0	13
+1518	0	1
+591	10	10
+1061	1	0
+1371	1	1
+22	1	1
+928	0	2
+182	8	0
+328	1	0
+301	0	1
+994	1	1
+18	0	6
+1743	0	1
+2350	22	23
+1548	0	2
+1498	8	6
+7484	0	3
+2988	7	7
+93	2	0
+322	1	0
+280	1	1
+49	1	1
+2114	16	17
+617	0	1
+1012	0	1
+495	1	0
+29	1	1
+3134	1	0
+1837	0	4
+4079	0	1
+905	8	0
+5764	0	1
+3493	0	20
+1174	0	1
+900	0	1
+1006	1	0
+1699	0	1
+1682	1	0
+688	1	1
+21	1	1
+3349	0	1
+384	3	1
+3616	3	0
+748	0	1
+3001	0	10
+541	1	0
+286	1	1
+22	0	1
+250	1	1
+27	1	1
+898	1	0
+1161	0	2
+2067	0	1
+8000	0	12
+857	29	0
+1399
+
+chain	72788	chr6_qbl_hap2	4565931	+	3808375	3809175	11	135006516	+	118201008	118201901	1739030
+615	13	107
+119	2	1
+51
+
+chain	65509	chr6_qbl_hap2	4565931	+	2258974	2259668	6	171115067	-	140105134	140105832	1929446
+178	0	4
+516
+
+chain	50097	chr6_qbl_hap2	4565931	+	2471491	2473781	6	171115067	+	44553942	44556234	2550079
+125	147	147
+81	297	298
+77	380	378
+160	345	343
+82	181	182
+60	299	303
+56
+
+chain	30865	chr6_qbl_hap2	4565931	+	3800272	3800791	6	171115067	+	32713281	32713770	4500604
+73	89	59
+184	77	77
+96
+
+chain	26769	chr6_qbl_hap2	4565931	+	2218659	2218944	1	249250621	-	83463584	83463869	6084938
+285
+
+chain	25453	chr6_qbl_hap2	4565931	+	1111775	1112573	8	146364022	+	94982474	94983353	6804147
+181	108	108
+72	385	466
+52
+
+chain	18586	chr6_qbl_hap2	4565931	+	2472758	2473366	3	198022430	-	151831455	151832050	2830221
+34	221	221
+81	91	91
+5	35	35
+55	44	31
+42
+
+chain	18520	chr6_qbl_hap2	4565931	+	2558133	2558568	13	115169878	-	5075411	5075846	11677159
+71	220	220
+144
+
+chain	17263	chr6_qbl_hap2	4565931	+	3694162	3694369	4	191154276	+	3927369	3927573	12785974
+50	3	0
+26	4	4
+124
+
+chain	16745	chr6_qbl_hap2	4565931	+	2589692	2589893	11	135006516	+	74748600	74748801	13289219
+113	12	12
+76
+
+chain	15761	chr6_qbl_hap2	4565931	+	3069257	3069435	19	59128983	-	18504215	18504393	607285
+59	1	1
+45	1	1
+72
+
+chain	15688	chr6_qbl_hap2	4565931	+	3804298	3804527	11	135006516	-	109492289	109492518	14350697
+129	50	50
+50
+
+chain	14458	chr6_qbl_hap2	4565931	+	3751685	3752808	6	171115067	+	32441118	32442245	15662572
+59	270	268
+88	656	662
+50
+
+chain	14065	chr6_qbl_hap2	4565931	+	3705931	3706083	6	171115067	-	138602057	138602209	16122341
+152
+
+chain	13955	chr6_qbl_hap2	4565931	+	2589304	2589471	9	141213431	-	10269188	10269355	16251226
+93	11	11
+63
+
+chain	13115	chr6_qbl_hap2	4565931	+	937718	937855	7	159138663	+	102343613	102343750	17340123
+137
+
+chain	12452	chr6_qbl_hap2	4565931	+	4213437	4214179	12	133851895	+	124586233	124586652	1913233
+57	408	105
+14	32	63
+45	0	78
+44	129	0
+13
+
+chain	12361	chr6_qbl_hap2	4565931	+	1150685	1150815	1	249250621	+	48985442	48985572	18455294
+130
+
+chain	12272	chr6_qbl_hap2	4565931	+	2479004	2479160	X	155270560	+	155194421	155194569	18587559
+71	1	1
+25	8	0
+51
+
+chain	12201	chr6_qbl_hap2	4565931	+	1105096	1105867	6	171115067	-	139876162	139876935	18699321
+54	620	622
+97
+
+chain	12178	chr6_qbl_hap2	4565931	+	3776349	3776515	14	107349540	-	58393926	58394091	18734379
+55	26	25
+85
+
+chain	12008	chr6_qbl_hap2	4565931	+	3700751	3700880	8	146364022	+	49154427	49154556	18990653
+129
+
+chain	11752	chr6_qbl_hap2	4565931	+	3745259	3747655	6	171115067	+	32491461	32493852	19428924
+56	676	682
+61	1516	1505
+87
+
+chain	11746	chr6_qbl_hap2	4565931	+	1097944	1098092	7	159138663	-	7702899	7703047	19437479
+54	14	14
+80
+
+chain	11503	chr6_qbl_hap2	4565931	+	3698827	3699253	11	135006516	-	111045874	111046295	19852910
+57	287	282
+82
+
+chain	10738	chr6_qbl_hap2	4565931	+	3700459	3700580	10	135534747	+	59600699	59600817	21255899
+61	3	0
+57
+
+chain	10686	chr6_qbl_hap2	4565931	+	2478152	2478673	18	78077248	+	11342173	11342695	21355061
+80	388	389
+53
+
+chain	10496	chr6_qbl_hap2	4565931	+	3696510	3696620	1	249250621	-	174039531	174039641	21744609
+110
+
+chain	10342	chr6_qbl_hap2	4565931	+	3714159	3714889	6	171115067	+	32548581	32549235	22073729
+78	598	522
+54
+
+chain	9560	chr6_qbl_hap2	4565931	+	1152614	1152715	6	171115067	-	141323187	141323288	23857063
+101
+
+chain	9560	chr6_qbl_hap2	4565931	+	1099695	1099796	6	171115067	-	141323187	141323288	23857064
+101
+
+chain	9385	chr6_qbl_hap2	4565931	+	3825573	3825778	16	90354753	-	20685009	20685189	24272037
+58	92	67
+55
+
+chain	9214	chr6_qbl_hap2	4565931	+	1102327	1102424	6	171115067	+	29758158	29758255	24607529
+97
+
+chain	9048	chr6_qbl_hap2	4565931	+	3694493	3695083	16	90354753	-	14504923	14505798	16016601
+79	460	745
+51
+
+chain	8993	chr6_qbl_hap2	4565931	+	2558568	2558745	2	243199373	+	116390976	116391155	17783325
+1	102	104
+74
+
+chain	8702	chr6_qbl_hap2	4565931	+	3686082	3686238	6	171115067	+	32439449	32439606	25393693
+54	51	52
+51
+
+chain	8427	chr6_qbl_hap2	4565931	+	3804527	3804616	6	171115067	-	148948316	148948405	15963296
+89
+
+chain	7704	chr6_qbl_hap2	4565931	+	3688237	3688318	6	171115067	+	32557831	32557912	26927503
+81
+
+chain	6794	chr6_qbl_hap2	4565931	+	3775350	3775421	3	198022430	-	94748615	94748686	28659148
+71
+
+chain	6473	chr6_qbl_hap2	4565931	+	3694610	3694683	1	249250621	-	102907635	102907704	21815174
+11	4	0
+58
+
+chain	6457	chr6_qbl_hap2	4565931	+	1158502	1158569	6	171115067	+	30228837	30228904	29438118
+67
+
+chain	6422	chr6_qbl_hap2	4565931	+	3817908	3817976	6	171115067	+	32728707	32728775	29535243
+68
+
+chain	6368	chr6_qbl_hap2	4565931	+	2478912	2479004	6	171115067	-	132617434	132617532	20998654
+55	29	35
+8
+
+chain	5830	chr6_qbl_hap2	4565931	+	1098157	1098218	7	159138663	-	104622057	104622118	31091038
+61
+
+chain	5757	chr6_qbl_hap2	4565931	+	3825218	3825278	14	107349540	-	70017731	70017791	31292281
+60
+
+chain	5558	chr6_qbl_hap2	4565931	+	2472407	2472466	15	102531392	+	37673660	37673719	31870719
+59
+
+chain	5479	chr6_qbl_hap2	4565931	+	1111956	1112025	9	141213431	-	103321949	103322018	11235972
+69
+
+chain	5339	chr6_qbl_hap2	4565931	+	3885926	3885982	X	155270560	+	55718242	55718298	32499987
+56
+
+chain	5185	chr6_qbl_hap2	4565931	+	3788909	3788964	14	107349540	+	22827226	22827281	32987373
+55
+
+chain	5179	chr6_qbl_hap2	4565931	+	1150896	1150960	19	59128983	-	37357346	37357410	20742827
+53	10	10
+1
+
+chain	5176	chr6_qbl_hap2	4565931	+	1100596	1100651	14	107349540	+	79349485	79349540	33029769
+55
+
+chain	5058	chr6_qbl_hap2	4565931	+	3771065	3771119	1	249250621	-	172942963	172943017	33379587
+54
+
+chain	5039	chr6_qbl_hap2	4565931	+	2475495	2475548	7	159138663	-	94193358	94193411	33438564
+53
+
+chain	5038	chr6_qbl_hap2	4565931	+	1148806	1148858	6	171115067	+	29856463	29856515	33456716
+52
+
+chain	4959	chr6_qbl_hap2	4565931	+	3696457	3696510	18	78077248	+	5090594	5090647	22176919
+53
+
+chain	4949	chr6_qbl_hap2	4565931	+	3825516	3825569	X	155270560	-	91231208	91231261	33742123
+53
+
+chain	4829	chr6_qbl_hap2	4565931	+	1159026	1159076	6	171115067	+	30459319	30459369	34177698
+50
+
+chain	4685	chr6_qbl_hap2	4565931	+	3719592	3719642	12	133851895	+	112261417	112261467	34690970
+50
+
+chain	4391	chr6_qbl_hap2	4565931	+	4214058	4214103	X	155270560	-	99494613	99494658	30227326
+45
+
+chain	4348	chr6_qbl_hap2	4565931	+	3739277	3739323	7	159138663	-	76863668	76863714	34891433
+46
+
+chain	4338	chr6_qbl_hap2	4565931	+	2201356	2201401	6	171115067	+	30954494	30954539	34909104
+45
+
+chain	4061	chr6_qbl_hap2	4565931	+	2201872	2201914	6	171115067	+	30955145	30955187	31149648
+42
+
+chain	4003	chr6_qbl_hap2	4565931	+	2470663	2474155	12	133851895	+	104783555	104787047	2981748
+99	961	960
+40	481	480
+76	473	472
+44	1256	1259
+62
+
+chain	3775	chr6_qbl_hap2	4565931	+	2471376	2471416	10	135534747	-	90944157	90944197	25967017
+40
+
+chain	3639	chr6_qbl_hap2	4565931	+	3694572	3694610	3	198022430	+	101411146	101411184	20382400
+38
+
+chain	3574	chr6_qbl_hap2	4565931	+	2470595	2470633	3	198022430	-	173409162	173409200	29596632
+38
+
+chain	3494	chr6_qbl_hap2	4565931	+	3700422	3700459	X	155270560	+	104134375	104134412	29536090
+37
+
+chain	3491	chr6_qbl_hap2	4565931	+	2471293	2472133	8	146364022	-	12751685	12752521	3617865
+79	701	697
+60
+
+chain	3436	chr6_qbl_hap2	4565931	+	2471844	2473225	1	249250621	+	7474211	7475590	2872741
+34	959	957
+58	295	295
+35
+
+chain	3220	chr6_qbl_hap2	4565931	+	3776529	3776563	12	133851895	+	85826623	85826657	35349035
+34
+
+chain	3148	chr6_qbl_hap2	4565931	+	3825631	3825664	2	243199373	+	38182693	38182726	24706670
+33
+
+chain	2975	chr6_qbl_hap2	4565931	+	2478232	2478268	3	198022430	-	94213030	94213066	24807218
+36
+
+chain	2972	chr6_qbl_hap2	4565931	+	1105868	1105908	6	171115067	+	30459045	30459085	20759384
+40
+
+chain	2845	chr6_qbl_hap2	4565931	+	2470633	2470663	3	198022430	-	156603737	156603767	26791326
+30
+
+chain	2838	chr6_qbl_hap2	4565931	+	2474990	2475020	4	191154276	+	92075174	92075204	21730347
+30
+
+chain	2761	chr6_qbl_hap2	4565931	+	3804625	3804685	4	191154276	+	37278694	37278754	22658556
+60
+
+chain	2671	chr6_qbl_hap2	4565931	+	2478852	2478911	9	141213431	-	60456470	60456529	21094091
+59
+
+chain	2604	chr6_qbl_hap2	4565931	+	1151032	1151059	17	81195210	+	6784720	6784747	30920849
+27
+
+chain	2579	chr6_qbl_hap2	4565931	+	3700720	3700751	21	48129895	+	18677639	18677670	26190064
+31
+
+chain	2574	chr6_qbl_hap2	4565931	+	1150960	1151032	X	155270560	+	72544773	72544845	18935818
+72
+
+chain	2481	chr6_qbl_hap2	4565931	+	3804442	3804477	3	198022430	-	58737971	58738006	17138123
+35
+
+chain	2394	chr6_qbl_hap2	4565931	+	2478673	2478698	11	135006516	-	67345781	67345806	29321362
+25
+
+chain	2363	chr6_qbl_hap2	4565931	+	2473435	2473485	3	198022430	-	59783725	59783775	3613581
+50
+
+chain	2322	chr6_qbl_hap2	4565931	+	2470859	2470989	15	102531392	-	72822940	72823070	3150079
+130
+
+chain	2266	chr6_qbl_hap2	4565931	+	2470989	2471957	9	141213431	-	114376815	114377769	4168715
+45	845	831
+78
+
+chain	2263	chr6_qbl_hap2	4565931	+	2471123	2471268	12	133851895	+	84401354	84401499	4041581
+145
+
+chain	2209	chr6_qbl_hap2	4565931	+	2470765	2470818	3	198022430	+	182918728	182918781	9563966
+53
+
+chain	2087	chr6_qbl_hap2	4565931	+	2558317	2558369	X	155270560	-	89201309	89201361	22578016
+52
+
+chain	2078	chr6_qbl_hap2	4565931	+	1112026	1112064	3	198022430	+	120909358	120909396	13027265
+38
+
+chain	2035	chr6_qbl_hap2	4565931	+	2557888	2557938	16	90354753	+	47212776	47212826	17692575
+50
+
+chain	1978	chr6_qbl_hap2	4565931	+	4213820	4213948	15	102531392	-	61555806	61555934	2051418
+28	68	68
+32
+
+chain	1899	chr6_qbl_hap2	4565931	+	2558399	2558424	X	155270560	+	94068150	94068175	17734181
+25
+
+chain	1860	chr6_qbl_hap2	4565931	+	1112180	1112230	8	146364022	+	68079613	68079663	13479327
+50
+
+chain	1860	chr6_qbl_hap2	4565931	+	3812269	3815784	6	171115067	+	32722816	32726965	29521084
+61	2506	2690
+85	515	965
+52	103	103
+193
+
+chain	1828	chr6_qbl_hap2	4565931	+	2473656	2473684	14	107349540	-	54723100	54723128	20222699
+28
+
+chain	1658	chr6_qbl_hap2	4565931	+	1112136	1112169	4	191154276	+	153686345	153686378	11053932
+33
+
+chain	1514	chr6_qbl_hap2	4565931	+	1112233	1112291	13	115169878	-	5205835	5205893	10260311
+58
+
+chain	1396	chr6_qbl_hap2	4565931	+	2473606	2473656	1	249250621	+	83820278	83820328	4577579
+50
+
+chain	1388	chr6_qbl_hap2	4565931	+	4214123	4214166	19	59128983	-	43654778	43654821	2801865
+43
+
+chain	1329	chr6_qbl_hap2	4565931	+	2557727	2557778	7	159138663	-	55106997	55107048	20610784
+51
+
+chain	1304	chr6_qbl_hap2	4565931	+	4213365	4213389	1	249250621	+	182710286	182710310	2078906
+24
+
+chain	1296	chr6_qbl_hap2	4565931	+	4213389	4213424	8	146364022	+	99694	99728	9829550
+12	1	0
+22
+
+chain	1233	chr6_qbl_hap2	4565931	+	2558102	2558133	5	180915260	+	67992831	67992862	12309329
+31
+
+chain	1171	chr6_qbl_hap2	4565931	+	2473569	2473606	X	155270560	-	90928252	90928289	23413190
+37
+
+chain	1170	chr6_qbl_hap2	4565931	+	2471983	2472043	9	141213431	+	232427	232487	4190853
+60
+
+chain	1144	chr6_qbl_hap2	4565931	+	2469449	2469508	2	243199373	+	81796678	81796737	21594602
+59
+
+chain	1125	chr6_qbl_hap2	4565931	+	3694759	3694827	8	146364022	-	86779351	86779419	20749390
+68
+
+chain	1106	chr6_qbl_hap2	4565931	+	1112362	1112413	1	249250621	-	17660691	17660742	13643228
+51
+
+chain	1071	chr6_qbl_hap2	4565931	+	2470508	2470575	12	133851895	+	78891507	78891574	9444392
+67
+
+chain	1040	chr6_qbl_hap2	4565931	+	2470400	2470457	5	180915260	-	146134722	146134779	6672758
+57
+
+chain	1023	chr6_qbl_hap2	4565931	+	2471416	2471471	2	243199373	+	162554783	162554838	24613681
+55
+
+chain	935	chr6_qbl_hap2	4565931	+	2558067	2558102	4	191154276	+	31205	31240	16972854
+35
+
+chain	919	chr6_qbl_hap2	4565931	+	2474702	2474762	4	191154276	+	45112377	45112437	22402157
+60
+
+chain	902	chr6_qbl_hap2	4565931	+	2474552	2474612	5	180915260	-	23766246	23766306	4704228
+60
+
+chain	884	chr6_qbl_hap2	4565931	+	2473696	2473725	1	249250621	-	199045131	199045160	12500824
+29
+
+chain	825	chr6_qbl_hap2	4565931	+	1112413	1112452	1	249250621	-	184583816	184583855	16072417
+39
+
+chain	801	chr6_qbl_hap2	4565931	+	2470111	2470156	1	249250621	-	71436588	71436633	19248116
+45
+
+chain	789	chr6_qbl_hap2	4565931	+	3698600	3699777	19	59128983	+	8446620	8447803	26630175
+58	1059	1065
+60
+
+chain	788	chr6_qbl_hap2	4565931	+	2470239	2470322	6	171115067	+	137168270	137168353	4512040
+83
+
+chain	740	chr6_qbl_hap2	4565931	+	1112667	1112731	12	133851895	+	57178267	57178331	20850792
+64
+
+chain	718	chr6_qbl_hap2	4565931	+	2474782	2474837	9	141213431	-	49469911	49469966	23568604
+55
+
+chain	694	chr6_qbl_hap2	4565931	+	2469923	2469992	X	155270560	-	140437581	140437650	5405913
+69
+
+chain	584	chr6_qbl_hap2	4565931	+	2474349	2474405	15	102531392	+	67105223	67105279	15249534
+56
+
+chain	562	chr6_qbl_hap2	4565931	+	2557778	2557819	X	155270560	+	91975692	91975733	21019876
+41
+
+chain	562	chr6_qbl_hap2	4565931	+	2469824	2469884	2	243199373	-	169790362	169790422	25410177
+60
+
+chain	552	chr6_qbl_hap2	4565931	+	2237356	2237383	17	81195210	-	14890828	14890855	11066346
+27
+
+chain	523	chr6_qbl_hap2	4565931	+	2470057	2470111	13	115169878	+	42049099	42049153	16964924
+54
+
+chain	489	chr6_qbl_hap2	4565931	+	2469992	2470048	14	107349540	+	79003493	79003549	5260265
+56
+
+chain	481	chr6_qbl_hap2	4565931	+	2470189	2470239	8	146364022	+	50441810	50441860	5267091
+50
+
+chain	481	chr6_qbl_hap2	4565931	+	2469386	2469447	1	249250621	-	193322918	193322979	8728434
+61
+
+chain	455	chr6_qbl_hap2	4565931	+	2472488	2472547	6	171115067	-	85200236	85200295	17778688
+59
+
+chain	445	chr6_qbl_hap2	4565931	+	2469210	2469265	X	155270560	-	127487766	127487821	16318369
+55
+
+chain	358	chr6_qbl_hap2	4565931	+	2475020	2475084	4	191154276	+	74158363	74158427	16300933
+64
+
+chain	347	chr6_qbl_hap2	4565931	+	2469153	2469203	15	102531392	-	65978487	65978537	12839283
+50
+
+chain	246	chr6_qbl_hap2	4565931	+	3697415	3697467	12	133851895	-	104314075	104314127	28162397
+52
+
+chain	47340388	chr6_random	1875562	+	1357431	1875562	6	171115067	+	157393490	158069469	78
+906	2	2
+193	1	0
+29	1	0
+8	10	8
+11	2	1
+842	41	40
+754	2304	72101
+91082	5628	50000
+31833	338	50000
+42477	272	0
+39	168	66
+53	1	1
+15	1	103
+64	2	172
+23	1	103
+14474	4	0
+30198	0	8
+1391	2	0
+1319	4	0
+142	0	3
+3412	9	7
+372	1	1
+22	1	1
+5871	0	1
+237	26	25
+3020	1	1
+83	1	1
+141	7	7
+201	2	1
+403	1	0
+3638	1	0
+20	1	0
+552	32	32
+1386	0	1
+4174	1	1
+37	1	1
+3912	5	5
+4160	2	0
+6561	0	1
+3879	0	1
+8665	0	1
+2170	0	3
+895	1	0
+1812	0	1
+36	0	4
+133	1	0
+165	0	9
+427	0	1
+917	1	0
+3166	0	1
+16647	1	0
+6161	10	10
+833	4	0
+1934	1	1
+56	1	1
+2622	9	9
+749	1	0
+482	0	2
+344	1	1
+32	1	1
+868	2	0
+444	0	3
+1096	12	0
+709	0	1
+113	1	1
+35	1	1
+2349	20	0
+175	0	1
+1675	0	2
+1206	0	3
+345	0	5
+4695	1	0
+6715	1	1
+35	1	1
+2131	0	1
+4220	8	0
+2065	1	0
+1986	0	1
+484	0	1
+1543	4	4
+52	22	0
+5090	0	1
+2768	9	2
+12577	0	5
+13727	9	9
+51	4	4
+26	2	3
+11	0	1
+735	1	1
+35	0	1
+12	1	1
+2616	1	0
+327	1	1
+35	1	1
+345	0	20
+50	98	187
+975	1	0
+7329	0	1
+3241	0	35
+583	5	5
+278	1	1
+40	1	1
+123	12	12
+1208	17	0
+477	0	1
+163	1	1
+28	1	1
+3307	1	0
+66	1	1
+25	4	0
+2459	0	1
+1326	1	0
+700	1	0
+2316	6067	13
+725	3	0
+42	1	1
+8162	0	2
+2147	0	2
+79	1	1
+25	1	1
+313	1	0
+2194	1	0
+709	1	1
+33	1	1
+934	4	4
+543	1	1
+37	1	1
+2581	1	0
+606	1	0
+666	1	1
+34	2	2
+250	9	8
+652	1	0
+2306	22	0
+38	0	24
+946	1	0
+3766	1	1
+57	1	1
+3591	2	0
+128	1	1
+1414	7	1
+435	1	1
+29	1	0
+529	0	1
+3649	1	1
+32	0	1
+9760	0	18
+6470	1	1
+49	1	1
+488	0	1
+304	2	0
+1780	0	5
+2759	1	0
+48	1	1
+380	1	1
+33	1	1
+5102	1	1
+33	1	1
+192	0	1
+1103	1	1
+29	1	1
+12912	0	1
+9445	2	0
+2949	1	1
+28	1	1
+826	1	1
+19	1	1
+404	1	1
+49	1	1
+1408	8	0
+1625	10	0
+2962	0	1
+1824
+
+chain	37689909	chr6_random	1875562	+	884671	1286589	5	180915260	-	167715260	168127349	92
+6889	0	1
+34829	1	0
+4156	0	2
+4477	0	8
+7827	0	415
+37	9	9
+207	0	1
+272	7	7
+7925	1	0
+75982	0	1
+11336	0	1
+4233	14	14
+362	10	10
+4607	4	0
+1310	0	3
+1741	4	0
+499	1	1
+69	1	1
+509	15	15
+166	12	8
+145	0	2
+66	1	1
+16	1	1
+325	1	1
+31	1	1
+804	1	1
+109	1	1
+1071	0	106
+73	38	121
+1998	1	1
+37	1	1
+500	0	5
+625	3	0
+2354	1	1
+42	1	1
+1652	0	1
+92	1	1
+68	1	1
+1023	1	1
+16	1	1
+849	2	1
+28	1	1
+1793	4	2
+850	26	26
+251	0	2
+794	1	1
+26	1	1
+798	1	1
+80	1	1
+211	20	12
+153	1	3
+373	6	6
+231	0	4
+302	1	1
+26	1	1
+305	0	4
+3735	1	0
+342	0	2
+2211	0	1
+1969	2	0
+2834	0	10
+1054	0	14
+2176	0	2
+10517	0	2
+3071	6	0
+5697	21	21
+2458	0	5
+1335	3	0
+411	1	5
+2718	10	11
+3652	1	0
+785	1	0
+777	1	0
+2088	0	1
+24	1	1
+1005	16	16
+5426	18	0
+378	1	0
+19	1	1
+5303	0	14
+19	18	0
+2125	1	0
+936	0	5
+29	1	1
+893	19	19
+312	0	2
+32151	1	0
+14548	1	0
+109	0	1
+1481	1	0
+6537	0	2
+3390	1	0
+7479	6	0
+29963	4	0
+3972	9	5
+1637	0	9
+7977	1	0
+1973	0	3
+1212	0	5
+372	29	19
+1216	0	50
+628	0	4
+8388	0	1
+1429	1	0
+3029	2	4
+785	1	0
+291	10	9516
+1642	0	1
+5042	1	0
+1117	1	0
+1558	8	7
+1475	4	0
+1859	0	1
+9528	0	1
+877
+
+chain	31999718	chr6_random	1875562	+	165017	507468	6	171115067	-	55532370	55875067	101
+42954	0	1
+24905	1	0
+579	0	6
+612	0	1
+1128	0	2
+5541	1	1
+30	1	1
+2064	1	0
+505	0	1
+1974	0	1
+5299	1	1
+16	1	1
+368	1	1
+28	1	1
+7024	1	0
+19574	8	9
+6646	4	0
+6060	0	1
+2290	0	1
+22638	6	58
+1402	0	1
+502	0	1
+218	0	1
+5768	0	1
+178	0	3
+659	1	1
+33	0	8
+92	4	0
+693	0	2
+1190	0	3
+375	5	0
+422	3	0
+2215	1	0
+7271	1	1
+33	1	1
+817	1	1
+67	1	1
+2442	1	1
+62	16	0
+165	1	0
+1535	1	1
+32	1	1
+596	4	4
+627	1	1
+22	1	2
+201	5	5
+35	1	1
+232	5	0
+651	4	4
+26	1	1
+105	1	1
+45	1	1
+325	1	1
+34	1	1
+265	1	1
+91	2	0
+1383	1	1
+35	1	1
+1469	19	19
+295	0	1
+644	0	1
+3324	1	1
+44	1	1
+1797	1	5
+21	2	0
+10	11	1
+58	2	0
+61	1	9
+715	0	1
+388	1	1
+47	1	1
+774	1	0
+571	0	3
+2308	0	1
+103	15	15
+1339	1	1
+19	1	1
+348	0	1
+372	1	1
+31	0	1
+4	4	0
+14	1	5
+14	1	25
+4634	1	1
+16	2	2
+305	27	24
+2252	10	217
+1695	0	2
+2541	0	7
+741	2	0
+1401	0	2
+202	2	13
+3853	1	0
+3037	36	0
+18	2	0
+25	94	0
+14	0	4
+487	0	1
+5889	0	1
+572	1	1
+17	1	1
+806	1	1
+24	1	1
+723	0	2
+1640	1	0
+2023	1	1
+21	1	1
+192	15	1
+994	0	106
+1362	2	0
+324	1	1
+19	1	1
+683	1	1
+39	1	0
+771	1	0
+1211	13	0
+1728	1	1
+23	1	1
+911	0	2
+1042	6	6
+206	5	0
+17	1	1
+3351	14	19
+783	1	1
+48	1	1
+673	0	4
+137	1	1
+23	1	0
+1357	4	0
+254	0	1
+1408	0	7
+564	1	1
+49	1	1
+319	13	13
+721	12	12
+821	2	0
+912	4	4
+47	1	1
+148	1	1
+61	1	1
+267	1	1
+46	1	1
+421	1	1
+36	1	1
+577	1	1
+35	1	1
+122	1	1
+95	1	1
+241	1	1
+40	1	1
+585	10	1
+1286	0	1
+97	2	0
+22	1	1
+969	0	1
+1448	14	20
+2000	1	0
+1448	0	1
+2390	1	1
+18	5	5
+1421	1	0
+412	0	1
+1867	2	1
+179	3	0
+852	1	0
+1426	20	18
+151	1	1
+26	1	1
+581	1	1
+86	2	1
+2659	1	0
+12163	2	0
+1149	13	13
+818	16	16
+113	1	1
+51	1	1
+343	1	1
+91	0	4
+7	2	0
+8	0	2
+914	1	1
+28	1	1
+670	1	0
+151	7	7
+1887	18	18
+119	0	5
+2395	2	0
+4395	0	6
+380	6	1
+423	17	17
+531	1	0
+23	0	6
+592	1	1
+23	1	0
+844	4	0
+1497	6	0
+407	17	17
+341	19	17
+1020	0	6
+178	1	0
+1233	0	1
+1861	0	1
+2007	2	0
+6480	1	1
+36	1	1
+6817	17	20
+3356	7	5
+1788	1	1
+83	0	1
+7678	18	18
+2095	1	1
+19	1	1
+4934
+
+chain	25195472	chr6_random	1875562	+	615192	884135	6	171115067	+	167833423	168297434	120
+2006	1	0
+2654	1	1
+28	1	1
+3139	1	1
+85	1	1
+690	0	1
+639	0	2
+1589	4	4
+122	2	0
+1127	0	1
+1104	1	102
+18	0	29
+40	0	3
+22	1	4
+50	0	26
+56	124	195105
+10440	18	25
+3042	0	24
+72	0	8
+206	4	0
+146	4	0
+2483	0	4
+702	0	1
+1035	0	8
+85	3	1
+2710	1	1
+84	1	1
+3774	1	1
+58	1	1
+20613	15	53
+14	32	0
+52	0	4
+1883	4	0
+52	3	0
+44036	171	0
+2224	2	2
+57	1	1
+7263	0	64
+5311	0	2
+24677	8	8
+1972	1	0
+3543	2	2
+46	1	0
+11768	1	0
+494	47	19
+36447	1	1
+67	1	1
+11347	8	0
+4230	1	3
+591	5	5
+1020	0	8
+680	1	1
+60	1	1
+4536	0	1
+1417	0	2
+2471	1	1
+22	1	1
+6781	0	5
+4943	5	0
+1067	2	0
+2588	2	0
+523	34	35
+9266	0	2
+3897	0	2
+1404	0	1
+3120	0	1
+2566	1	0
+1825	0	8
+5342
+
+chain	9830417	chr6_random	1875562	+	510011	615192	5	180915260	-	108917398	109022458	335
+331	57	57
+1247	1	0
+4094	15	15
+6775	12	0
+6148	1	0
+30	1	1
+251	0	1
+26	26	1
+238	1	1
+29	1	1
+148	1	1
+41	1	1
+5831	6	7
+2439	1	0
+4247	12	42
+2333	1	9
+3039	5	0
+476	2	2
+4359	0	1
+1237	11	11
+1223	12	0
+2800	2	0
+2660	0	1
+4531	1	1
+24	1	1
+7407	0	1
+395	2	0
+1841	391	0
+410	50	26
+321	1	1
+27	1	1
+226	9	9
+157	6	6
+80	1	1
+70	1	1
+5158	10	10
+1385	4	0
+991	0	2
+48	1	1
+1083	0	2
+751	0	1
+4266	1	1
+48	1	1
+1557	0	304
+1552	1	1
+21	1	1
+2652	1	0
+598	0	8
+115	15	16
+1277	1	1
+38	1	1
+898	1	1
+27	1	1
+699	0	1
+34	1	1
+279	4	0
+12	1	1
+2863	1	1
+25	1	1
+2484	12	15
+1447	1	0
+8689
+
+chain	8736931	chr6_random	1875562	+	25094	155092	6	171115067	-	3172994	3267843	378
+3079	5	5
+1125	2	0
+1270	7	14
+1955	1	1
+47	1	1
+4538	38	38
+1300	25	26
+67	7	8
+176	3	0
+1132	3	0
+906	103	48
+5311	0	16
+133	1	0
+94	153	987
+142	13	13
+2453	2	0
+238	2	0
+960	13	13
+4697	1	1
+26	1	1
+3575	36650	734
+4434	0	1
+5190	138	107
+33	1	1
+5998	4	0
+1660	1	0
+4740	1	1
+29	1	1
+7196	0	12
+17519	30	29
+12768
+
+chain	553807	chr6_random	1875562	+	1768811	1774813	4	191154276	-	111879139	111885141	10762
+1294	2	2
+109	1	1
+242	1	1
+106	1	1
+2122	1	1
+17	1	1
+200	1	1
+40	1	1
+1071	1	1
+24	1	1
+284	1	1
+77	1	1
+403
+
+chain	255982	chr6_random	1875562	+	1456339	1459136	6	171115067	+	157377507	157380303	364419
+1101	4	4
+21	1	0
+70	43	44
+1490	1	0
+66
+
+chain	238316	chr6_random	1875562	+	1453720	1456237	6	171115067	-	13762873	13765390	431401
+2517
+
+chain	190390	chr6_random	1875562	+	1355230	1357270	6	171115067	-	13765611	13767650	644275
+875	0	1
+30	1	0
+7	0	1
+32	2	0
+1093
+
+chain	147846	chr6_random	1875562	+	163259	164828	10	135534747	-	86648034	86649603	870502
+1569
+
+chain	66179	chr6_random	1875562	+	509035	509994	6	171115067	-	55868072	55869030	1909901
+52	241	240
+666
+
+chain	39557	chr6_random	1875562	+	507468	508471	14	107349540	-	76514262	76515265	2447482
+67	13	13
+252	48	48
+70	43	43
+73	340	340
+97
+
+chain	15445	chr6_random	1875562	+	574580	574743	6	171115067	+	168277787	168277950	14597733
+163
+
+chain	11899	chr6_random	1875562	+	508034	508258	7	159138663	-	61729371	61729595	2527246
+50	119	119
+55
+
+chain	6795	chr6_random	1875562	+	508264	508336	5	180915260	+	74550099	74550171	28643390
+72
+
+chain	5830	chr6_random	1875562	+	884328	884389	6	171115067	-	37135398	37135459	31091070
+61
+
+chain	5767	chr6_random	1875562	+	508601	508846	8	146364022	+	54253304	54253548	3655159
+50	103	102
+92
+
+chain	4821	chr6_random	1875562	+	16131	16182	10	135534747	-	59552661	59552712	34213212
+51
+
+chain	3598	chr6_random	1875562	+	720272	720329	6	171115067	+	168133749	168133806	2857460
+57
+
+chain	3185	chr6_random	1875562	+	1768774	1768810	2	243199373	+	130168617	130168653	16948
+36
+
+chain	2982	chr6_random	1875562	+	508896	508970	12	133851895	-	4327021	4327095	12758815
+74
+
+chain	2685	chr6_random	1875562	+	509240	510388	3	198022430	-	97729559	97730704	3388749
+33	1069	1066
+46
+
+chain	2530	chr6_random	1875562	+	720329	720365	6	171115067	+	168133920	168133956	3810246
+36
+
+chain	2208	chr6_random	1875562	+	720386	720422	6	171115067	+	168133692	168133728	3917950
+36
+
+chain	1957	chr6_random	1875562	+	507800	507848	1	249250621	-	36684504	36684552	2679811
+48
+
+chain	1423	chr6_random	1875562	+	508846	508894	2	243199373	-	143356177	143356225	7803118
+48
+
+chain	1172	chr6_random	1875562	+	508537	508601	X	155270560	+	123719418	123719482	4007841
+64
+
+chain	1047	chr6_random	1875562	+	509273	509328	20	63025520	+	3479096	3479151	2808508
+55
+
+chain	560	chr6_random	1875562	+	508669	508719	5	180915260	-	128392227	128392277	20287927
+50
+
+chain	14618906734	chr7	158821424	+	102995	158821424	7	159138663	+	10238	159128663	7
+973	5	0
+3912	0	2
+1234	4	0
+51	0	6
+70	1	1
+24	1	0
+143	8	0
+16	170	1
+47	1	1
+243	0	6
+913	3	0
+2538	980	0
+63	1610	0
+1362	0	1
+2104	0	456
+1158	0	1
+791	1	1
+49	0	1
+4175	8	0
+17	1	1
+4845	12	0
+2509	0	1
+1697	6	6
+192827	150000	278557
+5682472	0	1
+42007910	40000	35970
+4371	7	16
+17699	0	4
+5249	4	0
+2088410	1	1
+47	1	1
+4565	0	1
+7116	0	1
+2706	40000	43050
+6577293	50000	13552
+1052855	3000000	3000000
+256182	50000	416507
+190137	50000	50000
+5722629	24	25
+239	1	1
+59	2	2
+138	1	1
+34	1	1
+206	1	3
+18	1	0
+410	1	1
+72	1	1
+199	1	1
+62	5	5
+120	1	0
+468	1	1
+32	1	1
+264	1	1
+23	1	1
+1459	4	4
+107	1	1
+42	1	0
+14	1	1
+201	1	1
+46	1	1
+268	20	20
+303	2	1
+866	0	4
+76	3	3
+63	1	1
+74	1	0
+25	1	1
+66	1	1
+34	0	2
+180	35	36
+93	1	1
+41	1	1
+70	1	1
+49	1	1
+63	1	1
+57	1	1
+383	1	1
+133	1	1
+87	1	1
+38	4	4
+50	0	1
+46	5	6
+136	11	11
+200	1	1
+63	4	0
+6	9	0
+263	1	1
+32	3	3
+152	16	16
+567	1	0
+322	3	0
+1258	0	1
+505	4	0
+1141	11	10
+537	12	12
+1418	1	1
+47	0	1
+164	7	7
+90	5	0
+156	1	1
+20	1	1
+380	3	3
+41	3	0
+5	2	2
+921	1	1
+34	1	1
+1607	2	2
+73	66	0
+46	14	0
+168	1	1
+53	1	1
+3195	1	1
+23	1	1
+2115	0	14
+9872	1	0
+1204	13	13
+416	1	0
+2311	319	0
+6906	0	10
+184	24	0
+2933	4	0
+1392	0	12
+1856	5	0
+3439	0	1
+469	3	0
+771	15	12
+497	1	1
+65	1	1
+1210	0	2
+4131	10	10
+1198	1	0
+718	1	1
+21	1	1
+3668	1	0
+874	1	1
+25	1	1
+2444	0	1
+1867	1	1
+29	1	1
+1660	0	1
+1232	0	6
+784	1	0
+705	0	3
+3577	1	0
+365	1	0
+3389	8	4
+2652	0	3
+664	0	1
+169	1	0
+8	1	1
+138	0	1
+8037	0	56
+112	196	0
+495	0	35
+3028	1	1
+40	1	1
+1068	4	0
+631	0	33
+29	2	0
+86	9	1
+3081	2	0
+806	0	1
+21	1	1
+3901	26	27
+843	0	1
+6916420	250000	50000
+25789103	0	51216
+1399994	1	0
+3623	0	212
+38	1	1
+210	1	0
+5	1	0
+6	1	0
+18	1	0
+1321	16	0
+2187	1	0
+145	0	1
+1388	7	7
+2240	14	14
+771	1	1
+34	1	1
+92	1	1
+39	1	1
+505	1	0
+66	1	1
+49	1	1
+159	1	0
+78	3	0
+15	2	0
+7	1	0
+28	1	0
+27	468	5
+2022	1	0
+1796	7	7
+61	1	1
+20	1	1
+4560	3	0
+157730	1	0
+194	14	14
+650	0	12
+717	26	26
+819	0	5
+278	60	32
+69	0	5
+1345	8	0
+652	84	0
+118	0	4
+498	0	1
+3187	1	1
+43	1	1
+1476	0	3
+2101	5	0
+788	6	6
+872	0	6
+893	3	0
+155	33	33
+4610	5	7
+521	10	0
+2773	40	40
+627	43	43
+1424	0	1
+2554	8	8
+44	0	7
+615	1	1
+32	3	0
+2693	0	1
+1029	0	2
+151	0	1
+1753	0	21
+370	2	3
+969	0	1
+452	1	0
+3035	1	1
+40	1	1
+704	0	2
+2472	0	6
+238	1	0
+1442	1	1
+37	5	5
+126	0	1
+795	0	1
+1191	1	0
+171	17	16
+724	6	5
+2988	40	42
+359	2	0
+199	19	19
+1969	1	0
+251	0	1
+729	0	1
+992	27	27
+205	4	0
+3209	0	2
+1006	8	10
+1571	10	10
+756	0	1
+36	1	1
+433	0	1
+672	0	3
+4430	157	0
+5606	5	1
+17	1	1
+942	10	9
+3433	2	1
+24	1	1
+4262	13	0
+661	2	0
+167	8	0
+3474	6	11
+217	0	2
+778	34	34
+158	0	1
+1167	0	1
+684	0	1
+878	39	39
+2012	0	1
+345	52	52
+640	0	2
+27874045	0	136705
+2519	0	2
+1000	8	0
+14695	1	0
+4456	1	0
+2977	1	0
+9065130	25000	29055
+2369	1	0
+12174	18	20
+877	0	4
+5247	0	12
+3483	2	0
+6766	0	1
+2469878	0	1
+734	2	2
+99	0	1
+2471	1	1
+11	1	1
+758	8	0
+2234	13	14
+8394	1	0
+47	1	1
+903	0	1
+5537	0	1
+269	1	0
+7114	1	1
+30	1	1
+2412	0	1
+2442	21	21
+91	1	1
+37	1	1
+96	1	1
+22	1	1
+246	1	1
+23	1	1
+254	12	12
+569	1	1
+27	1	1
+1624	1	0
+112	3	3
+45	1	1
+384	13	13
+70	1	0
+658	1	1
+20	1	1
+176	1	0
+307	19	19
+428	1	1
+19	1	1
+87	1	1
+30	1	1
+140	1	0
+292	2	0
+1492	1	0
+302	0	2
+364	1	1
+35	1	1
+1956	0	1
+728	12	12
+6522	2	2
+1531	1	0
+488	1	0
+2056	18	8
+1286	1	1
+27	1	1
+731	1	0
+1423	0	7
+2010	1	1
+19	1	1
+6423	0	4
+57	1	1
+4505	13	0
+933	0	12
+1250	0	1
+1313	1	0
+2610	0	1
+2398	0	1
+453	1	0
+346	1	1
+12	1	1
+83	25	25
+83	12	12
+277	0	1
+45	1	0
+811	2	0
+164	0	1
+104	0	1
+32	1	1
+1386	0	14
+306	1	1
+43	1	1
+2765	0	1
+1819	0	1
+1480	1	1
+24	1	1
+276	0	1
+21	0	1
+119	2	0
+12	26	0
+541	1	1
+63	1	1
+180	0	1
+2456	1	0
+1055	1	0
+1166	2	0
+784	0	4
+170	1	0
+939	6	0
+5597	15	15
+1253	0	1
+3336	0	18
+1851	9	0
+45	1	1
+657	38	38
+4099	0	1
+1387	2	0
+1460	1	0
+204	0	5
+1506	0	1
+2621	1	0
+6620	0	1
+34	1	1
+249	1	0
+1440	0	10
+245	0	1
+368	1	9
+257	4	0
+1589	6	0
+1543	0	1
+4189	120	0
+354	312446	278046
+3734	24	25
+3097	1	0
+8	1	1
+4861	0	4
+5649	1	0
+2011	0	1
+4344	24	24
+10546	42	1467
+20955	0	1
+2075	2	1
+5546	1	0
+2168	4	0
+1266	1	0
+4124	1	1
+46	1	1
+54	1	1
+43	15	0
+780	1	1
+25	1	1
+497	0	1
+46	1	1
+810	0	1
+5701	0	1
+6998	0	1
+2002	0	3
+7160	1	1
+24	1	1
+479	2	0
+1872	0	1
+1192	1	0
+371	2	0
+31	1	1
+572	16	16
+1725	16	16
+588	1	1
+90	1	1
+2483	3	19
+187	0	1
+20	1	1
+3673	1	1
+27	4	0
+3021	1	0
+1323	19	6
+498	13	13
+1618	2	0
+5282	0	1
+719	0	8
+2994	1	0
+2822	0	2
+1396	1	1
+48	1	1
+8723	5	0
+291	1	1
+25	1	1
+116	0	1
+2809	1	1
+27	1	1
+224	1	1
+48	1	1
+292	0	2
+400	0	1
+754	1	1
+19	1	1
+4225	1	1
+28	1	1
+801	1	0
+671	1	1
+17	1	1
+390	1	1
+28	1	1
+84	7	7
+568	1	1
+56	1	1
+499	7	8
+266	1	1
+31	1	1
+518	18	18
+164	1	1
+50	1	1
+162	1	1
+60	1	1
+702	1	1
+28	1	1
+146	18	17
+517	1	1
+24	1	1
+686	12	12
+101	1	1
+22	5	5
+107	5	5
+277	9	9
+272	1	1
+48	1	1
+77	1	1
+67	1	1
+1548	1	1
+40	1	1
+763	1	1
+42	1	1
+541	8	8
+88	1	1
+77	1	1
+233	11	11
+311	1	1
+22	1	1
+147	1	8
+504	1	1
+26	1	1
+987	20433	0
+3090	1	0
+405	5	5
+1811	1	0
+1174	0	1
+70	1	1
+1100	10143	18
+2722	0	1
+2957	1	1
+32	1	1
+9585	0	1
+1350	0	1
+473	0	1
+675	0	1
+1435	0	1
+805423	0	79189
+10872737	100000	100000
+721570	1	1
+19	1	1
+816	1	1
+44	1	1
+572	8	6
+2021	0	4
+1001	2	0
+3757	1	0
+5942	2	2
+70	1	1
+100	7	7
+395	80000	17188
+1010	1	1
+45	1	1
+1486	18	18
+173	1	17
+15	1	17
+158	0	192
+33	0	368
+50	50	2
+40	1	1
+95	4	52
+60	39	8
+15	16	0
+92	16	0
+1589	0	1
+897	13	13
+28	3	3
+2454	1	1
+44	1	1
+301	0	468
+2030	1	1
+45	1	1
+1277	8	0
+1716	1	0
+1579	11	15
+2439	36	0
+39	37	1
+349	21	92
+2096	13	11
+192	1	1
+48	1	1
+130	1	1
+22	1	1
+970	1	1
+23	4	0
+64	0	14
+129	17	11
+154	13	14
+53	15	5
+48	1	1
+47	0	2
+114	18	16
+363	1	1
+43	1	1
+559	1	1
+32	1	1
+3980007
+
+chain	16701236	chr7	158821424	+	141723881	141902219	7	159138663	-	16862466	17040468	171
+1662	1	1
+69	1	1
+887	1	1
+16	1	1
+115	339	1
+1512	0	1
+3597	0	1
+309	2	0
+34	1	1
+623	0	2
+1746	2	0
+816	4	0
+7868	1	0
+22	0	4
+593	0	1
+2757	0	1
+1147	7	7
+134	1	1
+42	1	1
+669	1	1
+25	1	1
+539	1	1
+49	1	1
+1387	1	1
+53	0	1
+19	1	1
+878	1	1
+27	1	1
+9739	1	1
+15	1	1
+2064	0	1
+1069	1	1
+31	1	1
+612	0	1
+21	1	1
+821	2	0
+1002	2	0
+3478	4	0
+1394	1	1
+25	1	0
+60	1	0
+4	1	0
+10	1	0
+23	0	1
+12	0	1
+2396	1	1
+25	1	1
+401	0	2
+1918	0	2
+43	1	1
+806	1	1
+36	1	1
+126	1	1
+53	1	1
+411	5	5
+524	13	13
+2896	1	1
+62	1	1
+4194	2	0
+8269	2	0
+368	11	10
+546	1	0
+1040	2	0
+45	1	1
+234	1	1
+29	1	1
+1218	16	16
+206	11	11
+584	13	13
+334	4	4
+167	3	3
+31	1	1
+973	9	9
+142	81	81
+58	1	0
+74	1	0
+1707	19	19
+2413	1	1
+57	1	1
+160	1	1
+23	1	1
+2380	0	1
+5561	0	4
+2790	14	14
+76	3	0
+1823	1	1
+11	0	9
+6	2	0
+5	3	0
+9	5	0
+28	1	1
+727	1	1
+37	1	1
+2678	0	3
+1497	1	0
+3414	1	0
+1171	6	6
+4018	7	7
+269	1	1
+36	1	1
+366	1	1
+22	1	1
+916	0	9
+2431	1	1
+68	1	1
+855	4	4
+1052	2	2
+81	0	2
+45	7	7
+648	1	1
+27	1	1
+402	1	0
+791	1	1
+41	1	1
+1041	20	20
+1094	1	1
+29	4	0
+364	1	1
+40	0	1
+22	0	1
+124	0	1
+205	0	1
+720	0	1
+59	1	1
+1063	2	0
+112	2	0
+3106	15	15
+2542	1	1
+64	1	1
+3052	1	1
+73	1	1
+3722	1	1
+31	1	1
+3476	1	0
+229	1	1
+40	1	1
+1321	0	5
+1845	1	0
+558	5	5
+3811	19	19
+125	1	1
+25	1	1
+3387	1	0
+1781	4	4
+2191	0	1
+1201	0	1
+260	1	1
+17	7	7
+137	0	1
+38	1	1
+732	0	1
+1626	1	0
+1987	2	0
+45	1	1
+763	0	1
+1978	0	1
+135	1	0
+6209	1	0
+24	1	1
+4867	0	1
+171	0	1
+6299
+
+chain	6490016	chr7	158821424	+	34000	116005	16	90354753	-	90001	171511	354
+591	11	11
+383	0	4
+1364	1	0
+430	12	13
+1431	1	1
+21	1	1
+490	12	12
+509	1	1
+97	1	1
+604	2	0
+1188	1	3
+665	1	1
+22	6	0
+499	1	1
+19	1	1
+402	1	1
+51	1	1
+1193	0	4
+245	1	0
+688	0	1
+975	2	0
+463	0	23
+73	24	0
+32	7	0
+165	1	0
+1593	1	1
+20	1	1
+1203	1	1
+31	1	1
+740	2	0
+47	1	1
+485	1	1
+63	1	1
+381	5	0
+28	1	1
+254	1	1
+22	1	1
+306	0	1
+34	1	1
+283	0	2
+627	10	10
+74	1	1
+50	1	1
+1053	0	1
+54	1	1
+77	1	1
+210	1	1
+70	0	3
+1957	0	4
+2154	1	1
+69	1	1
+147	67	67
+69	1	1
+74	1	1
+242	1	1
+41	1	1
+63	5	5
+155	3	1
+101	1	1
+53	1	1
+877	1	1
+21	1	1
+60	1	1
+49	1	1
+167	1	1
+21	1	1
+623	15	15
+202	0	97
+86	0	49
+9	2	2
+84	5	248
+56	1	98
+40	0	1
+48	1	0
+87	1	1
+55	99	1
+50	50	0
+23	1	1
+81	0	194
+78	1	1
+55	3	3
+53	6	344
+15	1	1
+262	1	1
+80	1	1
+455	1	1
+108	3	3
+431	1	1
+101	1	1
+158	1	0
+9	1	1
+323	3	0
+85	1	1
+19	1	1
+345	32	0
+24	1	1
+342	1	1
+65	1	1
+90	8	8
+545	1	1
+130	2	2
+87	4	3
+62	3	3
+34	2	2
+77	1	1
+47	1	1
+61	1	1
+27	1	1
+224	7	7
+117	2	0
+17	1	1
+242	1	1
+34	1	1
+107	1	1
+36	1	1
+100	15	15
+154	0	8
+13	1	0
+34	5	5
+100	27	27
+263	11	11
+116	1	1
+41	1	1
+117	1	1
+49	1	1
+116	2	0
+70	1	1
+174	1	1
+125	1	1
+70	1	1
+30	1	1
+74	1	1
+32	1	1
+337	1	1
+49	1	1
+2127	1	1
+35	1	1
+538	1	1
+32	1	1
+744	10	10
+471	53	17
+2001	7	7
+453	1	0
+2656	0	1
+1785	1	0
+1454	1	1
+33	1	1
+419	1	1
+49	1	1
+4610	1	1
+36	1	1
+905	1	1
+13	0	2
+5128	17	17
+519	0	3
+613	7	0
+660	0	4
+2632	1	2
+278	21	21
+969	1	0
+2852	14	14
+149	1	1
+21	1	1
+198	1	1
+29	1	1
+801	6442	6416
+125	6	0
+39	3745	3755
+814	162	1
+4	63	63
+74	63	0
+47	1056	13
+370
+
+chain	227647	chr7	158821424	+	141707499	141716076	7	159138663	+	142043811	142047809	475649
+53	484	465
+55	51	51
+78	242	220
+60	274	271
+51	13	13
+51	37	37
+229	4	4
+228	16	16
+108	47	47
+50	4583	49
+498	131	130
+945	36	36
+253
+
+chain	87685	chr7	158821424	+	58756	115635	3	198022430	-	71488	126874	406
+67	3328	3375
+28	1	1
+29	2	2
+39	50	50
+7	2	2
+41	2708	1663
+32	2831	2828
+27	46647	46820
+96	378	0
+152	47	12
+72	252	0
+43
+
+chain	48969	chr7	158821424	+	142175391	142175904	7	159138663	+	142475439	142475952	2613549
+513
+
+chain	47803	chr7	158821424	+	141911444	141913842	7	159138663	-	17029555	17031946	2683091
+78	139	139
+57	226	225
+124	92	92
+56	135	135
+72	193	193
+53	23	23
+133	958	952
+59
+
+chain	43189	chr7	158821424	+	142199519	142199970	7	159138663	+	142498738	142499189	3009311
+451
+
+chain	30396	chr7	158821424	+	67364377	67364696	15	102531392	-	56463077	56463396	4465114
+319
+
+chain	30094	chr7	158821424	+	141700053	141707301	7	159138663	+	142042846	142043613	4669748
+89	15	15
+68	6585	104
+66	129	129
+62	35	35
+199
+
+chain	30060	chr7	158821424	+	141963578	141964737	11	135006516	+	33264685	33266127	4680203
+91	398	397
+87	228	512
+77	163	163
+115
+
+chain	28591	chr7	158821424	+	141910578	141910878	7	159138663	-	17028690	17028990	5361712
+300
+
+chain	21822	chr7	158821424	+	141716123	141716468	7	159138663	+	142047850	142048195	9124304
+170	99	99
+76
+
+chain	20144	chr7	158821424	+	142166403	142167075	9	141213431	+	33792981	33793662	10344618
+82	380	389
+66	18	18
+51	19	19
+56
+
+chain	16654	chr7	158821424	+	101805867	101806156	7	159138663	-	92369277	92369565	11127744
+33	12	11
+63	91	91
+90
+
+chain	14923	chr7	158821424	+	102039289	102039446	7	159138663	+	102153090	102153247	2823
+157
+
+chain	10542	chr7	158821424	+	115456	115592	16	90354753	-	170836	170972	2672410
+136
+
+chain	10012	chr7	158821424	+	114469	115025	9	141213431	-	90660	90901	550
+63	395	80
+98
+
+chain	9195	chr7	158821424	+	141943788	141943884	7	159138663	-	16914722	16914818	24637833
+96
+
+chain	8667	chr7	158821424	+	142177809	142178136	7	159138663	+	142477851	142478180	25450135
+54	219	221
+54
+
+chain	7349	chr7	158821424	+	142180607	142180684	7	159138663	+	142480664	142480741	27551182
+77
+
+chain	7340	chr7	158821424	+	142180197	142180274	7	159138663	+	142480253	142480330	27565643
+77
+
+chain	6886	chr7	158821424	+	141960844	141960917	8	146364022	-	77913390	77913463	28463282
+73
+
+chain	6730	chr7	158821424	+	102059075	102062034	7	159138663	+	102172727	102175692	3338
+34	2887	2893
+38
+
+chain	6431	chr7	158821424	+	142166514	142166582	7	159138663	+	142454997	142455065	29498865
+68
+
+chain	6414	chr7	158821424	+	114166	115456	9	141213431	-	90644	91234	1816570
+68	791	378
+44	328	41
+59
+
+chain	6276	chr7	158821424	+	142176939	142177005	7	159138663	+	142476982	142477048	29891950
+66
+
+chain	6166	chr7	158821424	+	142179945	142180009	7	159138663	+	142480002	142480066	30171758
+64
+
+chain	5761	chr7	158821424	+	141963726	141963989	14	107349540	-	25420241	25420503	6848073
+68	130	129
+65
+
+chain	5666	chr7	158821424	+	142179798	142179857	7	159138663	+	142479855	142479914	31548103
+59
+
+chain	5608	chr7	158821424	+	101977370	101977454	7	159138663	+	44036096	44036185	7960
+10	0	5
+74
+
+chain	5430	chr7	158821424	+	142178562	142178619	7	159138663	+	142478613	142478670	32231795
+57
+
+chain	5139	chr7	158821424	+	142176520	142176574	7	159138663	+	142476565	142476619	33117712
+54
+
+chain	5020	chr7	158821424	+	141966623	141966675	12	133851895	+	53762512	53762564	33527602
+52
+
+chain	4939	chr7	158821424	+	142176195	142176247	7	159138663	+	142476241	142476293	33775264
+52
+
+chain	4778	chr7	158821424	+	73598	73651	5	180915260	-	172444	172497	587
+53
+
+chain	4039	chr7	158821424	+	101996220	101996263	7	159138663	+	102308194	102308237	1871
+43
+
+chain	3908	chr7	158821424	+	142167123	142167183	7	159138663	+	142455620	142455680	17639294
+60
+
+chain	3217	chr7	158821424	+	141963833	141963883	6	171115067	-	41704900	41704950	22743877
+50
+
+chain	2759	chr7	158821424	+	67423135	67423165	7	159138663	+	67785172	67785202	11329361
+30
+
+chain	2575	chr7	158821424	+	67423107	67423135	7	159138663	+	67785172	67785200	11329362
+28
+
+chain	2575	chr7	158821424	+	67423079	67423107	7	159138663	+	67785172	67785200	11329363
+28
+
+chain	2575	chr7	158821424	+	67423051	67423079	7	159138663	+	67785172	67785200	11329364
+28
+
+chain	2575	chr7	158821424	+	67423023	67423051	7	159138663	+	67785172	67785200	11329365
+28
+
+chain	2575	chr7	158821424	+	67422995	67423023	7	159138663	+	67785172	67785200	11329366
+28
+
+chain	2457	chr7	158821424	+	114257	114311	16	90354753	-	170806	170860	17475755
+54
+
+chain	2391	chr7	158821424	+	67422969	67422995	7	159138663	+	67785202	67785228	13667102
+26
+
+chain	2359	chr7	158821424	+	101974113	101974139	7	159138663	+	102286210	102286236	158723
+26
+
+chain	1502	chr7	158821424	+	141709533	141709580	7	159138663	+	142013474	142013521	12917072
+47
+
+chain	721	chr7	158821424	+	141963699	141963726	17	81195210	+	19853796	19853823	7983736
+27
+
+chain	615	chr7	158821424	+	141964154	141964190	19	59128983	-	28688778	28688814	21921932
+36
+
+chain	362	chr7	158821424	+	101987601	101987634	7	159138663	-	57149003	57149036	1101
+33
+
+chain	17312866	chr7_random	549659	+	162804	345700	GL000195.1	182896	+	0	182896	164
+182896
+
+chain	10142542	chr7_random	549659	+	0	112804	7	159138663	+	158928464	159038297	315
+4073	0	1
+5056	1	0
+1766	1	1
+63	5	5
+2422	1	0
+1297	1	0
+1967	196	0
+230	28	0
+2331	5	0
+47	1	1
+345	1	0
+41	1	1
+807	1	1
+31	1	1
+238	3	0
+100	1	0
+281	1	1
+43	1	1
+359	27	26
+59	1	1
+43	1	1
+1385	1	0
+161	1	0
+45	1	1
+1693	1	0
+93	1	0
+5	1	0
+805	0	3
+649	0	49
+1400	1	1
+4	1	0
+28	0	1
+7	0	1
+157	1	1
+117	0	31
+166	13	12
+138	1	0
+556	1	1
+46	1	1
+204	1	1
+21	1	1
+511	2	0
+390	1	1
+29	1	1
+60	1	1
+68	0	3
+27	1	1
+71	0	1
+37	5	0
+18	0	6
+56	3	3
+89	2	0
+103	6	15
+43	5	0
+7	0	11
+55	0	4
+456	46	45
+1286	1	1
+46	1	0
+36	2	0
+57	1	0
+396	1	1
+38	1	1
+298	1	1
+16	1	1
+602	224	0
+82	1	56
+1115	1	74
+17	3	3
+88	1	74
+98	158	12
+90	3	3
+70	3	3
+117	1	1
+43	1	1
+53	1	1
+21	1	1
+53	229	10
+120	81	8
+59	8	10
+411	1	0
+47	1	1
+723	0	9
+8142	6	6
+1297	1	1
+22	0	1
+7799	12	11
+1878	1	0
+70	5	5
+592	1	1
+28	1	1
+2251	1	0
+1474	1	0
+1975	0	1
+2577	0	1
+612	15	15
+93	1	0
+3	1	0
+149	1	0
+61	3	3
+34	1	0
+11	2101	0
+63	73	3
+67	106	1
+57	83	13
+60	70	0
+79	561	1
+321	70	0
+262	0	35
+83	183	8
+2406	0	549
+85	32	0
+27	0	26
+72	0	35
+22	3	0
+24	0	93
+74	2	0
+17	28	0
+63	1	0
+6	1	0
+1451	44	4
+23	1	1
+38	0	40
+80	1	121
+34	1	1
+58	0	82
+839	1	0
+31	1	1
+2861	0	4
+1376	1	1
+20	0	1
+78	2	0
+24	2	2
+2760	3	1
+585	8	0
+761	1	0
+6449	4	1
+259	1	1
+22	1	1
+717	0	1
+887	7	8
+2174	3	0
+970	1	0
+1768	12	0
+4378	0	1
+5	0	1
+13	1	0
+1637	5	10
+312	0	1
+2167	11	0
+164	10	10
+1517	1	1
+42	0	3
+698	0	4
+90	1	1
+20	1	1
+167	1	1
+16	1	1
+860	0	1
+1719
+
+chain	9633059	chr7_random	549659	+	402818	549659	7	159138663	+	514489	666751	345
+3766	22099	5004
+26	4	4
+11014	7	5
+17	1	0
+8	21	0
+3389	1	1
+54	1	1
+55	1	1
+66	1	1
+165	1	1
+38	1	1
+52	22350	21842
+816	4	4
+10432	15	15
+20532	1	1
+29	9	9
+13871	157	23205
+37837
+
+chain	2073422	chr7_random	549659	+	444161	465736	7	159138663	-	158510053	158531628	1246
+21575
+
+chain	1225579	chr7_random	549659	+	415456	428202	7	159138663	+	537499	550245	1943
+12746
+
+chain	745495	chr7_random	549659	+	406711	414469	7	159138663	-	158580384	158588142	6708
+215	11	11
+2423	4	4
+5105
+
+chain	224185	chr7_random	549659	+	399770	402202	7	159138663	+	518876	521308	490490
+367	50	50
+1609	1	1
+53	3	3
+304	1	1
+44
+
+chain	25943	chr7_random	549659	+	67571	70764	7	159138663	+	158995434	158996421	1881723
+67	73	3
+55	13	153
+17	71	0
+159	183	8
+119	21	21
+154	1960	0
+64	35	0
+105	35	0
+62
+
+chain	21070	chr7_random	549659	+	68795	70055	7	159138663	+	158995572	158996097	2684005
+86	98	63
+43	35	0
+76	455	0
+18	248	38
+61	57	57
+83
+
+chain	19298	chr7_random	549659	+	67796	68209	7	159138663	+	158995799	158996246	2040899
+35	195	229
+183
+
+chain	8295	chr7_random	549659	+	70341	70449	7	159138663	+	158996348	158996421	13908836
+11	35	0
+62
+
+chain	8007	chr7_random	549659	+	70264	70825	7	159138663	+	158995746	158996237	2373081
+77	186	46
+35	218	288
+45
+
+chain	7010	chr7_random	549659	+	69669	69742	7	159138663	+	158996026	158996099	13809421
+73
+
+chain	6757	chr7_random	549659	+	71674	71744	7	159138663	+	158996246	158996316	26425870
+70
+
+chain	6582	chr7_random	549659	+	16740	16849	7	159138663	+	158945342	158945395	9902405
+48	56	0
+5
+
+chain	5793	chr7_random	549659	+	36845	36905	7	159138663	+	158964922	158964982	31172491
+60
+
+chain	5504	chr7_random	549659	+	68645	69446	7	159138663	+	158995947	158996153	2767372
+68	176	1
+63	420	0
+74
+
+chain	5075	chr7_random	549659	+	34499	34552	7	159138663	+	158962931	158962984	33354772
+53
+
+chain	4386	chr7_random	549659	+	36139	36193	7	159138663	+	158964435	158964489	9901820
+54
+
+chain	4359	chr7_random	549659	+	69809	69854	7	159138663	+	158996061	158996106	24027999
+45
+
+chain	3345	chr7_random	549659	+	71561	71653	7	159138663	+	158995923	158996015	5823696
+92
+
+chain	3242	chr7_random	549659	+	36212	36249	7	159138663	+	158964435	158964472	7647561
+37
+
+chain	3169	chr7_random	549659	+	68713	69336	7	159138663	+	158995385	158995658	13517397
+46	500	150
+77
+
+chain	2856	chr7_random	549659	+	36091	36138	7	159138663	+	158964168	158964215	3415068
+47
+
+chain	2508	chr7_random	549659	+	74235	74267	7	159138663	+	158999705	158999737	11181217
+32
+
+chain	2422	chr7_random	549659	+	16701	16740	7	159138663	+	158944995	158945034	20425801
+39
+
+chain	2296	chr7_random	549659	+	76078	76102	7	159138663	+	159001472	159001496	26237556
+24
+
+chain	1888	chr7_random	549659	+	68772	68795	7	159138663	+	158995829	158995852	23967691
+23
+
+chain	1646	chr7_random	549659	+	16653	16684	7	159138663	+	158945171	158945202	6593972
+31
+
+chain	1510	chr7_random	549659	+	34573	34664	7	159138663	+	158962893	158962984	9181320
+91
+
+chain	1319	chr7_random	549659	+	70142	70185	7	159138663	+	158996289	158996332	23051286
+43
+
+chain	1065	chr7_random	549659	+	69520	69582	7	159138663	+	158996297	158996359	18766264
+62
+
+chain	13483752813	chr8	146274826	+	0	146274826	8	146364022	+	10000	146304022	9
+930417	1	1243
+52	10	10
+44	0	972
+100	0	54
+162	0	324
+409	0	1
+2323216	1	0
+3352649	2	0
+854996	100000	50000
+3399023	1	1
+46	1	1
+13965	1	1
+30	1	1
+121189	1	1
+35	1	1
+283700	0	1
+719291	100016	93054
+1155	0	2
+755	26	26
+980	21	21
+1479	54	54
+3597	1	0
+1937	19	19
+322	1	0
+1758	2	0
+1141	0	1
+956	48	48
+739	21	21
+1005	0	1
+543	1734	1734
+5338	15	15
+1029	1	1
+28	1	1
+305	57	57
+164	27	27
+5130707	0	1
+1288	0	1
+446	1	1
+80	1	1
+2123	4	4
+2514	3	0
+545	9	0
+527	1	1
+18	1	1
+256	9	9
+79	1	1
+40	1	1
+148	0	2
+2231	0	27
+958	1	1
+20	1	1
+2487	1	1
+113	1	1
+73	13	13
+365	10	10
+151	1	1
+32	3	0
+26	1	1
+1480	1	1
+29	1	1
+621	1	1
+28	1	1
+701	9	9
+362	1	1
+19	1	1
+691	1	1
+44	6	0
+47	1	1
+513	12	11
+382	1	1
+22	1	1
+111	1	1
+36	1	1
+337	1	1
+42	1	1
+602	2	0
+36	1	1
+475	1	1
+23	0	1
+32	4	3
+65	1	1
+59	1	1
+688	1	1
+22	1	1
+1473	1	1
+36	1	1
+372	1	1
+16	6	6
+1605	1	1
+38	1	1
+816	1	1
+17	1	0
+374	1	1
+17	1	1
+48	1	0
+82	1	1
+45	1	1
+263	1	1
+23	1	1
+204	1	1
+39	1	1
+2341	0	1
+2989	9	11
+811	8	8
+741	0	2
+337	1	1
+25	4	4
+763	1	1
+19	1	1
+343	1	1
+31	1	1
+1953	1	1
+74	1	1
+67	1	1
+18	4	4
+73	1	1
+31	1	1
+114	11	1
+87	1	1
+65	1	1
+125	9	9
+378	49	48
+90	1	1
+99	1	0
+173	13	7
+696	0	1
+6184	13	13
+830	13	13
+128	1	1
+37	1	1
+136	1	0
+66	5	6
+870	1	0
+4877	0	1
+585	3	7
+1728	1	0
+33	1	1
+465	1	1
+68	1	1
+581	6	0
+2088	1	0
+304	0	1
+2674	1	1
+28	1	0
+54	8	8
+846	0	1
+1409	16	16
+559	0	1
+407	0	5
+11	5	1
+29	1	1
+4051	1	1
+10	0	1
+43	1	1
+385	1	1
+35	1	1
+101	11	11
+602	1	0
+491	14	16
+1366	19	19
+321	1	1
+49	1	1
+546	1	1
+25	1	1
+2568	1	1
+51	4	0
+119	1	1
+39	0	1
+1040	0	1
+1682	0	4
+39	8	0
+862	1	1
+17	1	1
+587	1	1
+21	1	1
+904	0	1
+261	0	1
+1151	0	2
+2325	5	5
+5415	0	3
+1545	1	0
+428	4	4
+1950	2	0
+1073	0	1
+3653	0	86
+1283	1	1
+79	1	1
+6656	12	12
+1550	0	18
+5832	1	0
+4835	10	10
+1719	1	1
+84	1	1
+848	0	2
+236	1	1
+42	1	1
+1272	12	0
+49	1	1
+820	1	1
+22	1	0
+58	0	22
+510	8	8
+983	6	0
+539	14	14
+863	0	2
+27	1	1
+204	14	14
+163	4	4
+290	1	1
+59	1	1
+842	0	2
+2044	1	1
+90	0	1
+3434	0	3
+356	0	1
+873	0	1
+864	25	1
+630	12	7
+62	10	10
+156	11	11
+1364	19	19
+156	4	4
+244	4	18
+505	1	0
+109	1	1
+230	1	1
+107	4	3
+150	1	1
+83	5	5
+70	1	1
+33	1	0
+142	1	1
+626	5	6
+274	10	10
+128	1	1
+35	1	1
+216	1	1
+44	1	1
+312	1	1
+16	1	1
+1496	8	7
+451	0	1
+855	1	1
+20	1	1
+350	1	1
+62	1	1
+617	10	10
+845	1	1
+58	1	1
+2189	1	1
+147	1	1
+475	1	1
+27	1	1
+278	1	1
+17	1	1
+994	1	1
+40	1	1
+219	5	5
+26	1	1
+900	1	1
+29	1	0
+26	1	1
+484	15	16
+61	9	9
+114	21	26
+801	1	1
+33	1	1
+560	1	1
+37	1	1
+80	14	14
+211	1	1
+43	1	1
+156	1	1
+20	1	1
+685	1	1
+18	1	1
+48	4	0
+711	1	1
+38	1	1
+402	7	7
+1045	1	1
+37	1	1
+4035	9	9
+247	4	0
+4146274	17400	5734
+330366	0	1
+2346742	0	55
+413177	3	0
+450	1	0
+9436	3	1
+7044	4	0
+2886	1	0
+635	1	0
+16567	1	0
+6926	29	28
+9249	1	0
+14916	8	0
+12872	2	0
+3330	2	0
+2673376	2	0
+2603	1	1
+78	1	1
+2170491	7	7
+29817	66108	2485
+6473782	5	5
+39	1	1
+9574	0	2
+5879	1	1
+29	1	1
+6139	1	0
+2354	1	1
+28	1	1
+91	88	87
+142	16	15
+54	1	1
+22	3	3
+1479	4	4
+221	4	4
+132	1	0
+574	11	11
+23	1	0
+604	1	1
+44	1	1
+899	1	0
+70	1	0
+10	1	0
+13561	1	1
+44	1	1
+4476	4	4
+799	26	25
+1466	18	18
+17897	4	0
+1667	1	0
+4250	1	1
+44	1	3
+14	1	1
+4956	1	1
+18	1	0
+39	3	2
+4990	1	1
+47	13	13
+69	4	0
+9729	1	0
+355	0	1
+2186	1	1
+37	1	1
+6111	3	3
+100	4	4
+68	1	1
+43	1	1
+1126	5	7
+5520	8	8
+2316	1	1
+181	6	6
+50	1	1
+29	1	0
+83	1	1
+1073	245	639
+150	1	1
+25272	0	1
+2132	0	4
+2522	1	1
+48	1	1
+1498528	0	1
+6044582	3000008	3000000
+1291113	60074	16691
+3837	3	0
+811	1	0
+2567	1	0
+7375465	11	11
+42062	1	0
+19604621	1	0
+10692667	1	0
+110	0	1
+3577	0	3
+907	1	1
+18	1	1
+897	1	1
+64	535	251
+21	0	1
+140	0	1
+70	1	0
+77	9	10
+149	4	0
+5	1	5
+68	1	0
+142	5	5
+57	14	14
+43	1	1
+31034	124100	99683
+2301	0	2
+44	2	0
+568015	87325	183549
+330	5	5
+114	0	3088
+1776	0	3085
+949	0	4
+514	37	37
+963	15	14
+1351	71	71
+56	15	15
+405	713	713
+651	1	1
+41	1	1
+837	1	0
+658	0	1
+794	0	1
+73	1	1
+30	1	1
+817	51	51
+566	72	72
+195	0	12193
+1599	0	3085
+217	43	43
+247	29	29
+4148	1	0
+158	266	266
+696	20	20
+58	69	69
+100	13	13
+326	137	137
+151	35	35
+1804	151	151
+1341	289	289
+154	23	23
+1932	17	17
+111	47	47
+128	16	16
+78	30	30
+1022	6	10
+78	1	0
+342	31	31
+86	23	23
+1601	41	41
+144	49	49
+170	10	10
+398	23	23
+419	20	20
+955	55	55
+1139	11	11
+1925	0	276
+223	58	58
+702	25	25
+1030	23	23
+363	164	164
+653	16	16
+78	13	13
+1035	0	4
+514	37	37
+1069	10	10
+321	15	15
+603	68	68
+789	20	20
+56	25	25
+1007	5	5
+1198	24	24
+689	3	0
+743	32	32
+817	43	43
+574	11	11
+123	19	19
+618	28	28
+1270	15	15
+289	29	29
+106	11	11
+1395	46	46
+850	4	4
+777	62	62
+86	36	36
+374	97	97
+2072	31	31
+195	56	56
+379	80	80
+64	11	11
+191	18	18
+1051	13	13
+52	163	169
+1297	1	1
+25	1	1
+3451	0	188
+3097	0	9
+2715	1	0
+11829	0	3
+6001	28	0
+10728	0	1
+3770769	1	0
+62	1	0
+22	1	0
+827	1	0
+1485	1	0
+242	0	1
+7142	1	0
+4029	3	3
+69	1	1
+15865	1	0
+83463	4	0
+5976	9	0
+2661	1	0
+1483	1	0
+15868	4	0
+17798	1	0
+2649	1	0
+3627	1	0
+4789	1	0
+9541	1	0
+6844	1	0
+3187	2	0
+411	14	0
+3056	4	0
+19776	3	0
+29085	0	1
+745	2	0
+11453	2	0
+16739	1	0
+14697	1	0
+8539	1	0
+25514443	1	0
+17680	0	1
+55359	0	1
+58	57	59
+1515	1	0
+1111	1	0
+5736	6	6
+66213	1	0
+68	1	1
+24	6	7
+43	1	1
+33414	7	7
+22	1	1
+19312	0	1
+8588	1	1
+31	1	1
+15969	1	1
+32	1	1
+27034	1	1
+42	1	1
+3352	0	1
+15009	1	0
+20433	18	18
+32141	9	8
+116	41	41
+4920	1	0
+33364	1	0
+11160	15	17
+28423	1	0
+43835	1	1
+24	4	2
+269244	4	4
+37	1	1
+17193	4	3
+53	12	11
+23	2	1
+7	1	1
+37978	9	9
+37743	1	1
+35	3	3
+26636	1	1
+17	1	1
+8728292	1	0
+16734742	0	71275
+27	1	1
+657033	0	2
+2911	0	2
+1941	1	1
+35	1	1
+835	1	1
+116	1	1
+399	1	1
+101	1	0
+194	1	2
+450	1	0
+825	1	1
+73	1	1
+156	1	1
+58	1	1
+50	5	5
+153	11	11
+189	5	5
+233	1	1
+83	1	1
+642	0	1
+1380	1	1
+17	1	1
+315	1	1
+26	1	1
+786	0	901
+76	1	1
+45	1	1
+535	1	1
+34	1	1
+2007	7	7
+159	1	1
+26	1	1
+6362	13	13
+504325	100008	25635
+420771	0	232
+287680	0	104
+73	0	364
+181	0	55
+95	1	1
+46	1	1
+4002	1	1
+24	1	1
+183	49	0
+72	1	2
+8	1	0
+39	688	1
+306	0	50
+1939	0	1
+615	684	0
+254	0	1
+572035	7362	108542
+480202	1	0
+11866	6	6
+26917	0	1
+6097	15	15
+3074	0	1
+12292	0	1
+2209	0	1
+7358	0	1
+321393
+
+chain	161719	chr8	146274826	+	12213564	12217654	8	146364022	+	11922619	11926713	3890
+48	2333	2337
+1544	26	26
+139
+
+chain	94297	chr8	146274826	+	86864948	86909782	8	146364022	+	86767902	86816113	712
+43	4583	4586
+51	23	23
+69	22	22
+81	3466	3466
+114	1460	1461
+170	2237	2237
+47	3442	3445
+24	161	161
+49	1995	1995
+32	5554	5830
+116	4	4
+12	2309	5394
+37	2018	2018
+68	865	865
+25	3669	3669
+32	817	817
+42	1346	1346
+28	1574	1574
+29	1512	1515
+46	1652	1652
+41	2665	2665
+30	2224	2230
+50
+
+chain	49697	chr8	146274826	+	86036864	86037399	8	146364022	+	85964814	85965349	932809
+535
+
+chain	26725	chr8	146274826	+	86857851	86907733	8	146364022	+	86754632	86786590	1026
+491	49362	31438
+29
+
+chain	24621	chr8	146274826	+	145396034	145396288	8	146364022	+	145493131	145493385	2960834
+254
+
+chain	18039	chr8	146274826	+	144819613	144819801	8	146364022	+	144748845	144749033	12082915
+188
+
+chain	14890	chr8	146274826	+	86857082	86862299	8	146364022	-	59611598	59616815	1124
+71	476	476
+222	4397	4397
+51
+
+chain	13243	chr8	146274826	+	144819801	144819938	8	146364022	+	144748593	144748730	12136518
+137
+
+chain	9530	chr8	146274826	+	144823061	144823289	8	146364022	+	144751680	144751756	18947814
+3	152	0
+73
+
+chain	9463	chr8	146274826	+	144819938	144820036	8	146364022	+	144748632	144748730	13619337
+98
+
+chain	8087	chr8	146274826	+	86874741	86874834	8	146364022	+	86817360	86817453	1088
+93
+
+chain	7965	chr8	146274826	+	86865238	86879045	8	146364022	+	86780387	86797281	766
+29	7982	7984
+37	5729	8814
+30
+
+chain	7439	chr8	146274826	+	12201270	12203830	8	146364022	+	11910337	11912897	3584
+26	2480	2480
+54
+
+chain	6315	chr8	146274826	+	86909619	86909690	8	146364022	+	86556151	86556222	765064
+71
+
+chain	6303	chr8	146274826	+	144823559	144823625	8	146364022	+	144751722	144751788	29838951
+66
+
+chain	5756	chr8	146274826	+	86854716	86862896	8	146364022	+	86782059	86817706	1940
+37	8112	35579
+31
+
+chain	5521	chr8	146274826	+	144823643	144823701	8	146364022	+	144751730	144751788	31959915
+58
+
+chain	5339	chr8	146274826	+	144823077	144823133	8	146364022	+	144751620	144751676	32492605
+56
+
+chain	4702	chr8	146274826	+	144819343	144819392	8	146364022	+	144748967	144749016	12082914
+49
+
+chain	4684	chr8	146274826	+	144823154	144823323	8	146364022	+	144751621	144751752	19314390
+33	102	64
+34
+
+chain	4385	chr8	146274826	+	144820066	144820134	8	146364022	+	144748613	144748681	20813384
+68
+
+chain	3959	chr8	146274826	+	144820160	144820201	8	146364022	+	144748560	144748601	13619336
+41
+
+chain	3959	chr8	146274826	+	144819572	144819613	8	146364022	+	144748560	144748601	13619338
+41
+
+chain	3270	chr8	146274826	+	86905368	86905406	8	146364022	-	59611399	59611437	120315
+38
+
+chain	3190	chr8	146274826	+	144819513	144819546	8	146364022	+	144748697	144748730	12136519
+33
+
+chain	2525	chr8	146274826	+	144823339	144823377	8	146364022	+	144751692	144751730	23202086
+38
+
+chain	2511	chr8	146274826	+	144819546	144819572	8	146364022	+	144748632	144748658	13619339
+26
+
+chain	2509	chr8	146274826	+	144820134	144820160	8	146364022	+	144748632	144748658	22535050
+26
+
+chain	2395	chr8	146274826	+	144820036	144820061	8	146364022	+	144748974	144748999	15328526
+25
+
+chain	2146	chr8	146274826	+	86862896	86862937	8	146364022	-	59626667	59626708	2042
+38	1	1
+2
+
+chain	2013	chr8	146274826	+	12224371	12224395	8	146364022	+	11933433	11933457	5802
+24
+
+chain	928	chr8	146274826	+	86871422	86871445	8	146364022	+	86566156	86566179	4371
+23
+
+chain	19961283	chr8_random	943810	+	732172	943810	5	180915260	+	69954173	70165811	138
+211638
+
+chain	4772201	chr8_random	943810	+	62854	113804	8	146364022	+	16274686	16325603	650
+4146	9	9
+1642	5	9
+541	4	0
+1197	1	1
+27	1	1
+2498	0	1
+20171	4	0
+2761	3	0
+1978	0	1
+628	10	0
+5533	3	0
+2428	24	0
+47	5	9
+197	11	11
+687	0	2
+642	1	1
+17	1	1
+2228	0	4
+1978	1	0
+1521
+
+chain	4401722	chr8_random	943810	+	396973	443039	8	146364022	-	801667	847519	685
+2079	1	0
+22818	62	9
+50	57	0
+25	0	8
+40	91	0
+5953	32	0
+1937	0	2
+803	13	14
+786	0	5
+3908	2	0
+783	0	1
+854	1	0
+142	1	0
+1521	1	0
+114	0	1
+498	4	4
+591	2	0
+2750	0	9
+147
+
+chain	3680035	chr8_random	943810	+	643258	682172	GL000196.1	38914	+	0	38914	797
+38914
+
+chain	3554032	chr8_random	943810	+	493047	530222	GL000197.1	37175	+	0	37175	825
+37175
+
+chain	1222443	chr8_random	943810	+	0	12854	8	146364022	-	108556772	108569616	1946
+5765	0	1
+2843	2	0
+279	0	1
+299	1	0
+1113	9	0
+2543
+
+chain	995258	chr8_random	943810	+	250482	297042	8	146364022	+	46838897	46856230	2491
+52	5	5
+72	1882	0
+246	1888	0
+158	79	78
+59	82	81
+53	46	46
+76	18	18
+100	1942	59
+231	1	0
+84	1	0
+49	23	22
+65	25	25
+312	49	47
+118	1	0
+169	645	640
+71	18	18
+202	15	15
+74	114	112
+65	1444	30
+86	2249	34
+216	9	8
+173	33	30
+63	81	79
+265	87	84
+103	11	10
+122	1	1
+47	1	1
+165	858	0
+14	1027	0
+88	1879	0
+148	7	6
+166	1	0
+288	1888	1
+62	1	1
+90	1	0
+35	1890	1
+280	3	3
+23	1	0
+109	1	1
+283	4	4
+88	1	1
+67	1	1
+23	1	1
+109	680	0
+89	1876	0
+41	1	0
+45	1898	0
+107	18	18
+18	1	0
+28	1	1
+50	1	0
+35	1	1
+50	7	4
+54	1	0
+37	1	1
+298	11	10
+94	1	0
+17	1	0
+36	1	0
+55	1	0
+12	1	1
+148	1	1
+79	11	9
+78	1	1
+140	5	4
+54	3	0
+97	1	0
+138	6	4
+73	1	0
+59	19	19
+207	1	1
+45	1	1
+76	1	0
+8	3	1
+60	2	2
+56	1	1
+70	1	0
+45	1	1
+136	131	128
+86	17	16
+75	7	7
+53	483	144
+75	26	26
+230	135	132
+110	15	15
+61	25	23
+76	43	42
+120	1	0
+78	1735	1728
+192	42	41
+61	82	82
+190	37	37
+90	1911	30
+168	56	56
+56	10	10
+83	26	26
+230	1927	49
+224	1937	52
+244	41	41
+125	36	36
+96	26	26
+83	81	78
+272	2019	139
+59	236	231
+103	71	70
+183	31	31
+58	119	117
+131	1	0
+167	25	25
+72	97	96
+91	6	6
+75	10	9
+219
+
+chain	895028	chr8_random	943810	+	298039	346176	8	146364022	-	99507152	99525054	4376
+63	126	463
+229	1883	1
+104	25	25
+58	6	6
+155	36	35
+84	10	10
+88	23	23
+53	1	0
+164	5	5
+68	56	55
+231	24	24
+149	409	408
+53	1	0
+69	1	0
+134	6	6
+201	318	315
+27	1885	0
+105	1	0
+82	82	82
+144	27	27
+56	238	235
+130	24	23
+109	1	0
+77	2	1
+100	31	30
+102	14	14
+63	11	10
+108	91	91
+72	94	93
+169	149	148
+198	238	234
+86	2	0
+169	3	1
+72	11	11
+66	1	0
+247	18	17
+392	540	533
+186	7	7
+121	1	0
+254	1977	89
+53	7	7
+193	483	475
+93	50	47
+198	28	28
+76	1883	8
+61	130	129
+123	29	29
+112	201	199
+138	12	11
+21	1873	0
+107	33	33
+53	1880	1
+118	40	38
+141	1943	53
+168	137	134
+81	16	16
+115	2216	0
+103	32	29
+71	128	127
+104	54	53
+121	128	127
+66	99	96
+80	75	74
+128	1924	40
+53	2	1
+288	1910	24
+53	1907	23
+56	40	40
+72	111	111
+62	127	127
+122	65	65
+80	210	206
+115	0	1
+146	5663	0
+183	40	40
+53	34	33
+229	28	28
+92	83	83
+234	1983	101
+57	1885	0
+44	11	11
+62	1	0
+69	28	28
+126	1	0
+148	147	144
+58	14	12
+53	1	0
+66	1	0
+105	34	33
+71	39	38
+69	17	17
+56	6	5
+79	48	46
+53	6	6
+57	38	35
+77	78	75
+111	649	644
+110	45	43
+235
+
+chain	604051	chr8_random	943810	+	178170	281976	8	146364022	+	46838954	46856867	5476
+212	1875	0
+272	566	562
+114	1	0
+143	1	0
+55	74	74
+65	25	25
+63	62	62
+61	31	31
+102	23	23
+215	1	0
+63	67	68
+68	373	34
+158	64	63
+53	46	46
+105	67	67
+55	2294	38
+202	15	15
+63	51	51
+246	23	23
+71	1	0
+271	103	102
+427	6	5
+51	25	22
+54	1878	0
+36	10	10
+122	26	26
+134	1886	0
+121	93	92
+51	1	2
+246	54742	0
+134	1884	0
+129	33	31
+147	39	38
+116	65	61
+66	43	41
+62	1982	95
+213	196	193
+339	260	254
+187	89	88
+10	2292	403
+57	5123	1343
+293	24	22
+61	1	0
+73	7	7
+53	1877	144
+91	4270	499
+59	2463	581
+37	339	671
+59	342	0
+110	266	261
+150	6	6
+92	244	241
+51	62	62
+51	3119	1229
+91	761	80
+60	48	47
+137	1876	0
+136	12	10
+131	12	11
+290	1	0
+45	4005	2083
+59	88	424
+59
+
+chain	496223	chr8_random	943810	+	580222	593236	8	146364022	-	59615387	59795086	34662
+2144	4634	17818
+237	1	1
+31	1	1
+194	35	40
+1575	162	153603
+534	0	55
+995	64	64
+1343	58	58
+112	1	1
+38	1	1
+70	1	1
+41	1	1
+81	1	1
+34	1	1
+624
+
+chain	279595	chr8_random	943810	+	199376	329223	8	146364022	-	99506514	99525054	6095
+67	50	47
+55	631	967
+63	1082	0
+177	61	58
+147	6	6
+143	1	0
+42	1882	0
+74	31	30
+83	23	23
+13	1879	0
+204	5	5
+58	69	69
+227	1933	51
+152	123	122
+83	1	0
+118	72	72
+159	17	17
+119	34	34
+230	36	36
+134	1929	32
+189	3017	0
+24	83	83
+121	1	0
+49	5680	1
+325	136	129
+277	30	30
+335	1436	53
+51	63	62
+99	867	859
+154	860	855
+269	32	31
+112	1	0
+50	1877	0
+99	58	58
+108	1	0
+96	2221	0
+37	1546	0
+136	2648	89
+52	7	8
+278	1	0
+202	139	136
+145	65	63
+51	44	42
+62	143	139
+61	156	155
+243	214	215
+20	1872	0
+194	74	75
+337	25	25
+145	15	15
+71	65	65
+84	1878	0
+60	1	0
+244	227	225
+226	53	53
+62	42	41
+66	63	61
+120	35	34
+64	56110	1
+98	41	40
+53	2795	914
+65	10	10
+57	8290	755
+67	63	61
+66	17	16
+53	1	0
+58	36	36
+92	3924	162
+40	61	61
+58	4119	368
+133	2082	185
+58	42	42
+167	2235	21
+50	4401	627
+71	40	39
+147	360	353
+60	174	173
+446
+
+chain	208078	chr8_random	943810	+	170910	242131	8	146364022	-	99506628	99524507	6380
+55	632	967
+69	73	73
+115	28	28
+146	4836	20
+75	1	0
+54	58	58
+87	10	10
+294	22105	209
+184	59	59
+53	209	208
+64	1388	305
+56	340	338
+60	50	50
+134	32	32
+108	2	0
+106	83	82
+108	1884	0
+62	68	68
+216	1	0
+55	20	20
+107	3862	104
+61	311	311
+29	2182	2154
+53	1	0
+93	1388	251
+108	3	2
+129	159	158
+109	1	0
+31	114	113
+51	60	60
+78	14	14
+99	14	13
+152	64	62
+60	13	12
+120	98	98
+138	115	114
+56	6	4
+26	438	436
+213	183	182
+53	1	0
+81	2318	428
+71	25	25
+145	15	15
+71	65	65
+109	1956	43
+69	112	108
+33	397	392
+58	1466	80
+62	46	46
+401	64	64
+45	51	51
+56	1	0
+6	99	99
+54	146	144
+187	67	67
+166	52	49
+51	9	8
+63	11	10
+61	186	186
+68	38	38
+168	105	102
+125	3	2
+113	17	17
+186	2	0
+3	6394	747
+113	762	83
+102	4015	254
+238	102	101
+91	6	6
+85	1999	129
+12	9	9
+44	2322	442
+90	319	318
+42
+
+chain	110041	chr8_random	943810	+	584910	586860	8	146364022	-	59525621	59532924	58275
+151	1	1
+64	1	1
+158	1	1
+137	0	5353
+14	3	3
+73	8	8
+52	11	11
+57	9	9
+54	15	15
+289	15	15
+837
+
+chain	81230	chr8_random	943810	+	228410	243660	8	146364022	-	99515272	99524158	121868
+53	818	813
+113	55	55
+76	1036	1025
+78	1	0
+115	1280	591
+98	36	34
+79	25	25
+73	189	188
+120	2622	738
+79	145	145
+8	21	19
+36	157	155
+27	18	14
+98	82	81
+130	280	280
+78	83	83
+21	20	20
+27	51	51
+134	238	238
+10	39	39
+53	216	215
+252	5175	1418
+73	6	6
+146	231	228
+111	1	0
+201	35	35
+101
+
+chain	78595	chr8_random	943810	+	271315	287023	8	146364022	+	46844767	46855610	13381
+177	7	6
+61	49	46
+54	86	84
+62	24	23
+151	92	91
+73	109	107
+108	1	0
+51	8	6
+97	2409	1723
+29	1995	118
+92	64	63
+24	701	695
+42	7	7
+53	90	89
+54	403	392
+25	6360	4099
+70	192	192
+26	77	76
+63	336	336
+129	125	126
+143	878	869
+27	23	23
+61
+
+chain	70241	chr8_random	943810	+	583972	584708	8	146364022	-	2327498	2328234	1800744
+736
+
+chain	67060	chr8_random	943810	+	583131	583834	8	146364022	+	144032710	144033413	1885205
+703
+
+chain	60161	chr8_random	943810	+	163863	193392	8	146364022	+	46840361	46854926	51951
+69	30	30
+79	155	153
+22	224	224
+36	635	633
+54	78	77
+53	1660	61
+55	408	405
+36	32	32
+40	163	161
+29	96	89
+5	85	85
+4	108	106
+193	10362	0
+211	23	23
+164	214	212
+108	41	40
+217	35	35
+85	25	25
+266	2366	490
+48	600	260
+32	3507	4987
+74	590	587
+105	2319	2307
+66	2880	990
+102	1	0
+89	507	168
+143
+
+chain	59106	chr8_random	943810	+	169718	174718	8	146364022	-	99507650	99524666	884317
+69	73	73
+53	107	105
+145	323	5927
+57	45	43
+58	51	49
+65	130	129
+16	74	74
+175	49	49
+53	423	422
+53	2360	8782
+34	55	55
+95	1	0
+28	1	0
+2	113	113
+292
+
+chain	53138	chr8_random	943810	+	171392	346403	8	146364022	-	102525263	102570806	8603
+57	57	57
+79	626	627
+64	1139	91
+72	32	32
+61	1	0
+192	55	53
+253	233	231
+113	1894	10
+151	18218	118
+161	39	39
+89	168	167
+68	174	168
+68	7236	473
+76	2229	347
+40	124	120
+50	21	21
+55	1906	29
+98	2	0
+51	3928	158
+113	3230	214
+58	5760	82
+62	113	112
+39	7442	4152
+122	13	12
+149	90	90
+56	48	47
+71	400	397
+133	1910	21
+97	23	23
+92	2561	0
+54	15	13
+67	70	69
+90	95	94
+59	72	72
+139	45	45
+101	71659	2394
+62	72	72
+84	1	0
+9	2000	117
+95	39	39
+65	70	68
+87	2031	150
+103	1949	61
+106	17	17
+136	75	74
+53	5662	38
+58	1936	41
+42	168	168
+108	95	95
+66	243	241
+50	5018	908
+53	4282	513
+74	1906	30
+83	2078	26035
+107	1947	59
+57	500	483
+160	1936	53
+185	1897	12
+119	3972	202
+29	14	14
+79	61	61
+44
+
+chain	52733	chr8_random	943810	+	164218	295513	8	146364022	+	43821028	43838759	7574
+63	20	20
+141	36	36
+153	32	31
+103	40	40
+53	86	85
+99	1658	59
+83	265	263
+110	21	21
+51	29	27
+160	108	108
+51	1	0
+49	1	0
+61	130	123
+85	12281	44
+69	272	272
+118	62	62
+75	7995	1645
+102	45	45
+59	32	32
+14	328	328
+126	2372	483
+86	58668	153
+40	4323	551
+31	1938	56
+58	2392	511
+58	234	222
+51	1403	0
+51	91	91
+50	218	218
+83	67	66
+75	77	77
+110	391	53
+2	2678	792
+147	104	101
+59	1917	33
+92	1958	75
+54	5899	1442
+11	105	104
+132	1	0
+50	2212	332
+66	5506	1369
+60	189	189
+173	223	221
+222	1874	0
+87	23	23
+54	108	108
+109	29	28
+94	64	63
+70	91	86
+97	164	161
+112	123	123
+78	1942	66
+145	118	118
+69	1917	31
+51	10	10
+113	235	231
+193	327	327
+41	392	391
+51	363	361
+123	1977	94
+57
+
+chain	48120	chr8_random	943810	+	172087	205615	8	146364022	-	99508140	99525054	275640
+50	1136	89
+81	56	55
+4	1876	5603
+199	577	570
+71	144	141
+39	17920	1690
+56	276	276
+117	289	289
+64	172	170
+10	18	18
+76	284	279
+308	237	229
+64	1904	0
+33	2094	204
+40	43	43
+63	3	2
+59	12	12
+306	15	15
+33	1146	61
+49	757	4487
+37	62	62
+83	46	46
+112	178	174
+95	1	0
+29	1956	73
+248
+
+chain	37837	chr8_random	943810	+	253130	272078	8	146364022	+	46839659	46847391	87472
+42	44	44
+61	2771	880
+109	37	36
+171	1	0
+120	209	204
+98	56	55
+61	10	9
+23	187	186
+75	18	18
+17	5316	1682
+9	145	143
+53	1	0
+29	137	137
+73	132	128
+65	14	14
+79	6214	2430
+95	70	70
+83	2232	342
+91
+
+chain	33662	chr8_random	943810	+	209837	215530	8	146364022	-	99514311	99520696	710844
+71	67	65
+87	1	0
+118	10	8
+19	543	533
+53	11	11
+89	4	2
+68	143	138
+148	1307	167
+110	627	624
+30	2103	3960
+84
+
+chain	32940	chr8_random	943810	+	226035	229035	8	146364022	-	102534454	102537445	203694
+68	23	23
+49	847	842
+50	91	91
+134	57	57
+61	1290	1287
+37	113	113
+86	41	40
+53
+
+chain	31024	chr8_random	943810	+	206449	211988	8	146364022	-	99514678	99520173	701886
+8	43	43
+64	6	5
+58	14	12
+82	340	0
+49	416	749
+81	59	59
+117	75	75
+207	1422	3285
+36	2428	531
+34
+
+chain	29825	chr8_random	943810	+	245532	246838	8	146364022	+	46839602	46840894	3893579
+57	560	553
+119	226	222
+5	184	184
+21	75	72
+59
+
+chain	28513	chr8_random	943810	+	169082	170209	8	146364022	-	99514495	99515614	2995290
+72	337	330
+70	17	17
+84	143	144
+53	81	80
+64	162	161
+44
+
+chain	28403	chr8_random	943810	+	244271	247583	8	146364022	+	46840215	46841632	1514192
+150	21	21
+65	247	246
+61	60	60
+144	37	36
+68	1	0
+56	146	144
+158	1945	55
+153
+
+chain	27366	chr8_random	943810	+	305024	329400	8	146364022	-	99508828	99514021	185326
+30	144	144
+27	1950	69
+57	1	0
+69	4733	954
+80	7	7
+60	2015	139
+144	51	51
+17	50	48
+20	2199	324
+179	83	83
+149	1	0
+45	50	50
+29	198	197
+38	56	56
+36	163	162
+27	2035	153
+71	157	157
+56	6099	109
+62	47	47
+93	104	100
+75	1	0
+39	342	0
+49	1641	94
+81	539	539
+177
+
+chain	25161	chr8_random	943810	+	165410	166073	8	146364022	+	46840031	46840686	5084847
+51	107	104
+69	107	106
+77	51	48
+53	79	78
+69
+
+chain	23498	chr8_random	943810	+	275598	276538	8	146364022	+	46848347	46849285	1106774
+150	39	39
+58	1	0
+156	159	160
+43	237	235
+97
+
+chain	22556	chr8_random	943810	+	221873	233787	8	146364022	-	102535430	102541485	264178
+56	92	91
+134	1524	140
+26	9348	4879
+77	298	294
+159	126	126
+55	8	7
+11
+
+chain	21554	chr8_random	943810	+	211856	229563	8	146364022	-	102534119	102541711	230838
+98	1283	144
+76	1760	1749
+25	1	0
+80	1889	12
+87	80	79
+50	14	14
+51	55	50
+59	207	201
+52	31	30
+212	2303	390
+120	3503	2102
+43	5590	1830
+38
+
+chain	21378	chr8_random	943810	+	315539	346866	8	146364022	-	99515536	99522005	182294
+65	7	7
+59	1872	0
+52	1	0
+110	59	59
+145	1929	47
+157	4107	0
+50	19	19
+76	11	11
+9	218	215
+20	69	68
+27	104	104
+38	3941	169
+93	9868	446
+40	53	53
+33	350	349
+83	1915	34
+228	2	1
+71	4993	3080
+80	103	101
+58	162	162
+50
+
+chain	20133	chr8_random	943810	+	187153	190961	8	146364022	+	46839718	46841635	711123
+27	2490	610
+70	193	186
+75	6	6
+22	81	81
+48	1	0
+41	200	200
+10	13	12
+78	103	101
+193	10	10
+147
+
+chain	19851	chr8_random	943810	+	184692	274845	8	146364022	+	46839508	46849467	34309
+59	20	20
+103	2903	645
+204	29	27
+122	5	4
+251	1	1
+19	1	1
+370	102	102
+45	59	59
+32	2407	520
+35	53082	226
+207	6009	346
+163	6	4
+101	79	79
+50	419	416
+33	1900	15
+227	6	6
+48	1	0
+53	22	21
+65	58	57
+59	43	42
+133	81	80
+20	44	42
+50	14	12
+53	37	36
+104	2375	490
+62	1340	1334
+14	1	0
+183	3854	228
+49	6055	405
+35	6036	1578
+80	25	25
+89	8	7
+13
+
+chain	19146	chr8_random	943810	+	175023	175290	8	146364022	-	99508150	99508416	4025470
+88	58	57
+65	25	25
+31
+
+chain	17870	chr8_random	943810	+	167013	193249	8	146364022	+	46840039	46851047	112211
+37	407	404
+31	233	231
+41	10382	13
+26	802	800
+40	282	279
+41	6132	1660
+77	3954	2070
+28	510	4239
+81	90	89
+50	30	30
+120	2083	201
+60	192	191
+51	338	0
+118
+
+chain	17758	chr8_random	943810	+	265412	266607	8	146364022	+	43830436	43831619	676151
+58	100	98
+16	14	14
+59	946	936
+2
+
+chain	17102	chr8_random	943810	+	196211	212812	8	146364022	-	102534634	102539542	315778
+4	176	169
+110	677	661
+101	229	222
+63	12	11
+71	2311	416
+66	5	5
+3	2545	1456
+25	7	5
+52	21	20
+3	9994	1320
+61	8	7
+57
+
+chain	16958	chr8_random	943810	+	303736	319647	8	146364022	-	99509421	99514022	288375
+62	1	0
+115	55	55
+12	6716	1059
+173	60	58
+5	238	238
+27	142	138
+80	1	0
+32	1181	1170
+56	95	93
+15	6818	1186
+27
+
+chain	16519	chr8_random	943810	+	191041	191237	8	146364022	+	46841712	46841907	5194781
+138	7	6
+51
+
+chain	16395	chr8_random	943810	+	250196	250458	8	146364022	+	46842349	46842610	5706058
+109	63	63
+38	1	0
+51
+
+chain	16284	chr8_random	943810	+	248826	295566	8	146364022	+	43821313	43835075	8983
+38	3114	1217
+58	3878	108
+134	2320	436
+35	2074	180
+90	6230	729
+53	51	51
+165	2138	257
+18	1	0
+14	9087	4604
+68	26	23
+70	26	25
+165	4726	2469
+31	113	113
+45	6358	726
+53	323	321
+29	3160	1272
+53	1943	60
+1	1	0
+51
+
+chain	16072	chr8_random	943810	+	313809	340982	8	146364022	-	102527896	102533983	267291
+28	5309	1547
+73	15383	1858
+110	23	22
+51	120	119
+75	171	167
+144	2405	509
+56	2087	199
+104	240	238
+93	367	364
+59	113	109
+162
+
+chain	15849	chr8_random	943810	+	261982	295288	8	146364022	+	43821759	43829198	76114
+110	412	75
+52	237	234
+137	1904	21
+61	17	17
+88	8048	505
+97	1212	533
+118	1	0
+62	80	80
+12	643	644
+105	9123	1231
+153	113	112
+50	1019	1018
+55	3899	142
+89	478	475
+43	4836	1068
+52
+
+chain	15670	chr8_random	943810	+	194296	345941	8	146364022	-	102525263	102540770	8834
+113	3789	1
+79	5134	279
+81	25039	3655
+36	72	71
+66	2073	189
+82	66	62
+87	280	277
+20	23	23
+59	87	84
+72	49	48
+51	7	7
+82	1014	334
+62	79983	3178
+76	18	17
+68	2382	504
+43	42	41
+108	10477	733
+134	2033	147
+59	5650	11
+88	3846	65
+64	297	293
+50	3779	12
+69	123	122
+120	121	120
+68	15	15
+57	136	135
+139	239	237
+72	1	0
+63	4	3
+53	59	59
+8	490	488
+28	84	81
+35	298	293
+34	805	799
+67	1	0
+53	69	67
+100	14	14
+81	134	132
+53	38	38
+39	110	109
+45
+
+chain	14986	chr8_random	943810	+	225882	226349	8	146364022	-	99518359	99518822	2174986
+18	53	51
+56	166	164
+73	33	33
+68
+
+chain	14834	chr8_random	943810	+	243014	243551	8	146364022	-	99519780	99520313	2299338
+16	162	159
+19	313	312
+27
+
+chain	14491	chr8_random	943810	+	298927	299279	8	146364022	-	102541139	102541484	3650546
+95	253	246
+4
+
+chain	13927	chr8_random	943810	+	330425	330634	8	146364022	-	99513165	99513373	16289681
+108	47	46
+54
+
+chain	13708	chr8_random	943810	+	204114	204446	8	146364022	-	99514221	99514551	7956244
+38	2	1
+51	137	136
+104
+
+chain	13201	chr8_random	943810	+	267894	296641	8	146364022	+	46841376	46846486	149880
+47	8325	118
+153	12619	975
+124	10	10
+59	1933	45
+415	178	178
+62	103	99
+67	193	193
+45	34	34
+4	542	542
+26	2853	963
+60	194	194
+31	632	628
+38
+
+chain	12234	chr8_random	943810	+	261803	269960	8	146364022	+	46841266	46843423	172872
+35	2890	667
+1	24	24
+60	15	15
+6	166	166
+32	2034	149
+193	134	132
+81	69	68
+116	2096	211
+21	87	83
+97
+
+chain	10617	chr8_random	943810	+	337138	337293	8	146364022	-	99523571	99523724	21494273
+69	29	27
+57
+
+chain	10554	chr8_random	943810	+	261774	276161	8	146364022	+	46850579	46856384	287750
+26	3379	1156
+30	20	20
+51	4844	1067
+12	16	15
+65	51	50
+53	361	357
+85	102	101
+13	51	51
+26	87	87
+46	4988	2413
+81
+
+chain	10039	chr8_random	943810	+	325665	325968	8	146364022	-	99512180	99512483	3203386
+32	146	146
+51	12	12
+62
+
+chain	9889	chr8_random	943810	+	299929	343052	8	146364022	-	99507161	99512618	194143
+54	125	463
+172	6011	368
+29	4240	471
+68	8003	490
+69	47	47
+10	133	133
+55	45	44
+46	4488	379
+66	1908	22
+82	7833	307
+63	2043	161
+90	115	115
+101	1	0
+97	2144	241
+32	4543	773
+83	294	293
+33
+
+chain	9887	chr8_random	943810	+	315022	315154	8	146364022	-	99513153	99513284	7544872
+79	1	0
+52
+
+chain	9860	chr8_random	943810	+	311200	311307	8	146364022	-	99513093	99513199	8991129
+52	1	0
+54
+
+chain	9817	chr8_random	943810	+	331048	331155	8	146364022	-	99513786	99513892	13428201
+64	1	0
+42
+
+chain	9446	chr8_random	943810	+	266857	296082	8	146364022	+	43794817	43828117	103381
+44	9743	27369
+146	121	120
+47	983	976
+79	10221	2331
+165	112	112
+51	81	80
+39	1877	0
+66	2043	157
+36	3318	1429
+53
+
+chain	9082	chr8_random	943810	+	283227	283503	8	146364022	+	46855567	46855841	3572014
+72	39	38
+7	101	100
+57
+
+chain	9078	chr8_random	943810	+	266179	266275	8	146364022	+	46841541	46841637	24832874
+96
+
+chain	9056	chr8_random	943810	+	234327	343102	8	146364022	-	102532678	102541696	177988
+49	2060	180
+83	4311	566
+60	72559	3258
+278	110	111
+124	380	378
+51	246	244
+21	14	13
+37	2147	273
+83	195	193
+50	29	28
+5	2000	121
+73	4435	328
+132	3864	97
+47	5706	63
+45	54	54
+151	1883	5
+99	3796	15
+99	63	61
+64	1	0
+58	1881	0
+137	76	74
+53	53	48
+27	312	310
+85	17	16
+19	140	140
+52	244	244
+62	105	104
+50
+
+chain	8907	chr8_random	943810	+	174718	174972	8	146364022	-	99514987	99515577	3222521
+12	195	531
+47
+
+chain	8843	chr8_random	943810	+	329461	329557	8	146364022	-	99512211	99512306	12312646
+78	1	0
+17
+
+chain	8728	chr8_random	943810	+	244822	248433	8	146364022	+	46838897	46840609	1548241
+52	2949	1051
+100	1	0
+231	55	55
+65	34	34
+124
+
+chain	8619	chr8_random	943810	+	294534	295111	8	146364022	+	46855606	46856180	1696895
+31	25	25
+71	52	51
+46	97	97
+58	132	130
+65
+
+chain	8428	chr8_random	943810	+	281982	282213	8	146364022	+	46854328	46854560	448042
+60	97	98
+56	17	17
+1
+
+chain	8419	chr8_random	943810	+	261190	261281	8	146364022	+	43820969	43821060	10860311
+91
+
+chain	8395	chr8_random	943810	+	294914	295046	8	146364022	+	46848509	46848640	12873675
+58	69	68
+5
+
+chain	8358	chr8_random	943810	+	183391	183662	8	146364022	+	46851295	46851565	1204104
+177	39	38
+55
+
+chain	8235	chr8_random	943810	+	303417	303563	8	146364022	-	99516580	99516725	5721277
+92	1	0
+53
+
+chain	8187	chr8_random	943810	+	330253	330340	8	146364022	-	99512994	99513081	26147162
+87
+
+chain	7754	chr8_random	943810	+	175981	176066	8	146364022	-	99524049	99524133	15930227
+61	1	0
+23
+
+chain	7677	chr8_random	943810	+	237294	312035	8	146364022	-	99517817	99525125	210590
+33	254	254
+156	1	0
+142	25	25
+70	127	127
+226	1925	53
+62	55	55
+112	29	28
+91	36	36
+139	46	43
+7	796	791
+54	65384	1748
+45	3060	1165
+46	839	833
+119	535	529
+77	214	206
+36
+
+chain	7632	chr8_random	943810	+	192816	192897	8	146364022	+	46850614	46850695	27043702
+81
+
+chain	7605	chr8_random	943810	+	285785	290878	8	146364022	+	46850643	46851974	486318
+50	2571	689
+13	4	4
+73	73	73
+25	2038	160
+132	56	54
+58
+
+chain	7406	chr8_random	943810	+	221929	222203	8	146364022	-	99519540	99519813	598559
+62	1	0
+29	134	134
+48
+
+chain	7383	chr8_random	943810	+	294257	294361	8	146364022	+	43837510	43837614	4128881
+70	9	9
+25
+
+chain	7298	chr8_random	943810	+	168270	168367	8	146364022	+	46839414	46839508	6543284
+4	56	53
+37
+
+chain	7295	chr8_random	943810	+	336620	336697	8	146364022	-	99513722	99513799	27625946
+77
+
+chain	7211	chr8_random	943810	+	261472	261549	8	146364022	+	46839068	46839145	24666501
+77
+
+chain	7186	chr8_random	943810	+	330047	330123	8	146364022	-	99512791	99512867	27853996
+76
+
+chain	7178	chr8_random	943810	+	316571	316677	8	146364022	-	102541857	102541963	5712191
+106
+
+chain	7102	chr8_random	943810	+	318170	320971	8	146364022	-	99520028	99520932	765669
+72	19	19
+135	121	121
+72	13	12
+29	2280	384
+60
+
+chain	7077	chr8_random	943810	+	192950	193025	8	146364022	+	46850748	46850823	28082919
+75
+
+chain	7057	chr8_random	943810	+	203108	206189	8	146364022	-	99515093	99516287	1156085
+30	91	89
+53	2333	448
+35	503	503
+36
+
+chain	6980	chr8_random	943810	+	332337	335152	8	146364022	-	99522544	99523471	1124480
+50	412	409
+6	79	79
+50	126	126
+65	1978	93
+49
+
+chain	6922	chr8_random	943810	+	183305	183378	8	146364022	+	46840000	46840073	28376594
+73
+
+chain	6904	chr8_random	943810	+	266355	266429	8	146364022	+	46841714	46841788	28413782
+74
+
+chain	6731	chr8_random	943810	+	303313	303384	8	146364022	-	99509001	99509072	28774708
+71
+
+chain	6664	chr8_random	943810	+	303981	314057	8	146364022	-	99517140	99519668	641395
+51	3	2
+55	1	0
+72	170	168
+30	7422	1761
+7	12	11
+54	1882	0
+68	153	153
+96
+
+chain	6603	chr8_random	943810	+	322619	327380	8	146364022	-	99513231	99513884	1344743
+127	337	0
+120	9	8
+78	1963	78
+31	1885	0
+211
+
+chain	6584	chr8_random	943810	+	197737	202982	8	146364022	-	102536127	102540259	775939
+91	1155	1137
+22	12	11
+57	3876	2782
+32
+
+chain	6449	chr8_random	943810	+	218412	233428	8	146364022	-	99516080	99519573	697985
+27	8506	1438
+73	54	54
+91	295	295
+235	28	28
+6	100	100
+56	5516	1061
+29
+
+chain	6331	chr8_random	943810	+	327023	327090	8	146364022	-	99511661	99511728	29751334
+67
+
+chain	6250	chr8_random	943810	+	208146	208242	8	146364022	-	99508890	99508983	12204367
+15	70	67
+11
+
+chain	6212	chr8_random	943810	+	207786	207861	8	146364022	-	99514136	99514211	3829743
+75
+
+chain	6150	chr8_random	943810	+	203513	205795	8	146364022	-	102537045	102537445	1909663
+16	3	2
+125	118	117
+8	1955	75
+57
+
+chain	6094	chr8_random	943810	+	299279	299402	8	146364022	-	99508718	99508841	2977078
+68	21	21
+34
+
+chain	6085	chr8_random	943810	+	250101	250166	8	146364022	+	46842254	46842319	30387783
+65
+
+chain	6067	chr8_random	943810	+	293889	294038	8	146364022	+	46845620	46845767	4301892
+66	21	19
+62
+
+chain	6049	chr8_random	943810	+	230044	230135	8	146364022	-	102569888	102569979	10345810
+91
+
+chain	5962	chr8_random	943810	+	207380	207446	8	146364022	-	99509995	99510061	8394857
+66
+
+chain	5949	chr8_random	943810	+	272784	272847	8	146364022	+	46853694	46853757	30762472
+63
+
+chain	5823	chr8_random	943810	+	299452	300023	8	146364022	-	99514497	99515068	1422380
+470	61	61
+40
+
+chain	5814	chr8_random	943810	+	289476	289952	8	146364022	+	46839369	46839842	2257769
+77	110	110
+124	92	90
+42	1	0
+30
+
+chain	5753	chr8_random	943810	+	192024	192086	8	146364022	+	46838954	46839016	21955899
+62
+
+chain	5749	chr8_random	943810	+	233271	233333	8	146364022	-	102570546	102570608	31315232
+62
+
+chain	5681	chr8_random	943810	+	341821	341883	8	146364022	-	99511396	99511458	7040566
+62
+
+chain	5649	chr8_random	943810	+	174777	174837	8	146364022	-	99507908	99507968	31588023
+60
+
+chain	5623	chr8_random	943810	+	175706	175950	8	146364022	-	102534119	102534360	3287579
+59	23	22
+63	22	20
+77
+
+chain	5394	chr8_random	943810	+	322313	322370	8	146364022	-	99511057	99511114	32316179
+57
+
+chain	5303	chr8_random	943810	+	187437	187493	8	146364022	+	46840000	46840056	32583273
+56
+
+chain	5285	chr8_random	943810	+	290446	290502	8	146364022	+	43794807	43794863	32673339
+56
+
+chain	5276	chr8_random	943810	+	336755	336811	8	146364022	-	99513853	99513909	32693850
+56
+
+chain	5265	chr8_random	943810	+	208344	208568	8	146364022	-	99514691	99514915	3842595
+38	152	152
+34
+
+chain	5263	chr8_random	943810	+	587464	592229	8	146364022	+	86573610	86746488	37343
+35	3283	168311
+47	1343	1343
+20	1	3086
+36
+
+chain	5194	chr8_random	943810	+	184072	184128	8	146364022	+	46838897	46838953	32965865
+56
+
+chain	5184	chr8_random	943810	+	329855	329911	8	146364022	-	99512600	99512656	19420929
+56
+
+chain	5176	chr8_random	943810	+	177599	177656	8	146364022	-	99506628	99506685	33029925
+57
+
+chain	5155	chr8_random	943810	+	281730	289038	8	146364022	+	46843205	46844537	960143
+32	6927	953
+200	103	101
+46
+
+chain	5093	chr8_random	943810	+	184617	184671	8	146364022	+	43793908	43793962	23494272
+54
+
+chain	5050	chr8_random	943810	+	326962	327016	8	146364022	-	102542496	102542550	23236949
+54
+
+chain	5030	chr8_random	943810	+	212164	212217	8	146364022	-	99524079	99524132	33461083
+53
+
+chain	5021	chr8_random	943810	+	265903	265956	8	146364022	+	46841267	46841320	33516233
+53
+
+chain	5010	chr8_random	943810	+	325697	333370	8	146364022	-	99519686	99521704	323579
+146	5416	1638
+176	1905	28
+30
+
+chain	4963	chr8_random	943810	+	195042	195095	8	146364022	-	99525006	99525059	2910708
+53
+
+chain	4923	chr8_random	943810	+	294759	294811	8	146364022	+	46846486	46846538	24481170
+52
+
+chain	4775	chr8_random	943810	+	300049	300108	8	146364022	-	99511357	99511416	2287019
+59
+
+chain	4729	chr8_random	943810	+	323590	341586	8	146364022	-	99508256	99511164	508733
+81	188	186
+45	5653	0
+76	6291	651
+50	2125	222
+31	36	36
+21	50	50
+1	57	52
+62	3121	1237
+18	5	4
+85
+
+chain	4516	chr8_random	943810	+	291820	291870	8	146364022	+	46839826	46839876	19135311
+50
+
+chain	4460	chr8_random	943810	+	340307	340812	8	146364022	-	99522970	99523472	2799007
+59	396	393
+50
+
+chain	4363	chr8_random	943810	+	169662	169718	8	146364022	-	99524410	99524466	15024078
+25	20	20
+11
+
+chain	4245	chr8_random	943810	+	323934	340633	8	146364022	-	102539490	102542980	824111
+57	5415	1637
+55	4265	507
+46	6509	840
+13	129	125
+132	10	10
+68
+
+chain	4191	chr8_random	943810	+	346770	346816	8	146364022	-	99523777	99523823	32415009
+46
+
+chain	4157	chr8_random	943810	+	182640	182685	8	146364022	+	46841541	46841586	34989719
+45
+
+chain	4075	chr8_random	943810	+	287206	294116	8	146364022	+	46853923	46857394	507901
+58	44	43
+3	6754	3316
+51
+
+chain	4035	chr8_random	943810	+	210210	231774	8	146364022	-	99509073	99511132	504053
+68	1	0
+87	1	0
+47	151	148
+33	3084	58
+60	3981	215
+31	2075	179
+62	11852	1040
+31
+
+chain	3902	chr8_random	943810	+	322746	322788	8	146364022	-	99511490	99511532	25070576
+42
+
+chain	3842	chr8_random	943810	+	326212	339029	8	146364022	-	99518333	99519833	259270
+47	312	308
+17	60	57
+117	12236	926
+28
+
+chain	3793	chr8_random	943810	+	191943	191984	8	146364022	+	43793349	43793390	19585042
+41
+
+chain	3728	chr8_random	943810	+	267941	270995	8	146364022	+	46845159	46846318	991534
+57	2323	433
+41	406	402
+51	140	139
+36
+
+chain	3715	chr8_random	943810	+	252408	255104	8	146364022	+	46840810	46841615	879027
+44	1	0
+30	2575	685
+46
+
+chain	3689	chr8_random	943810	+	281829	281916	8	146364022	+	46850779	46850864	2001274
+26	3	1
+58
+
+chain	3667	chr8_random	943810	+	254324	254368	8	146364022	+	46840842	46840884	6647423
+30	11	9
+3
+
+chain	3646	chr8_random	943810	+	267998	268037	8	146364022	+	46850823	46850862	21797624
+39
+
+chain	3562	chr8_random	943810	+	168212	168270	8	146364022	+	43793831	43793889	3070871
+58
+
+chain	3504	chr8_random	943810	+	293480	293517	8	146364022	+	46839611	46839648	25642059
+37
+
+chain	3471	chr8_random	943810	+	337522	337596	8	146364022	-	99523948	99524022	18137430
+74
+
+chain	3448	chr8_random	943810	+	276204	276644	8	146364022	+	46854559	46854996	1897606
+49	365	362
+26
+
+chain	3411	chr8_random	943810	+	253189	255402	8	146364022	+	46850929	46853124	621337
+27	1269	1253
+37	776	774
+2	49	49
+53
+
+chain	3373	chr8_random	943810	+	338130	338166	8	146364022	-	99513335	99513371	20995505
+36
+
+chain	3359	chr8_random	943810	+	165298	184945	8	146364022	+	43823972	43836890	282023
+56	2595	8459
+64	12771	2404
+3	8	8
+69	4024	1798
+57
+
+chain	3297	chr8_random	943810	+	194502	225687	8	146364022	-	102525468	102530377	366001
+70	4347	545
+64	92	91
+87	8182	1452
+36	9798	1128
+56	8421	1348
+32
+
+chain	3286	chr8_random	943810	+	278118	290566	8	146364022	+	43833036	43837583	504233
+53	11	9
+65	12260	4361
+59
+
+chain	3257	chr8_random	943810	+	218922	219219	8	146364022	-	99516581	99516875	4722847
+56	32	30
+58	32	31
+119
+
+chain	3241	chr8_random	943810	+	233589	233706	8	146364022	-	102539417	102539534	832166
+52	16	16
+49
+
+chain	3212	chr8_random	943810	+	266430	268559	8	146364022	+	46841788	46842035	1348744
+53	1890	10
+128	11	9
+47
+
+chain	3157	chr8_random	943810	+	327996	328036	8	146364022	-	99512626	99512665	16621225
+16	15	14
+9
+
+chain	3082	chr8_random	943810	+	310645	310683	8	146364022	-	99512541	99512579	16551162
+38
+
+chain	3062	chr8_random	943810	+	163933	165245	8	146364022	+	46851641	46852949	942341
+29	1223	1219
+60
+
+chain	3030	chr8_random	943810	+	262108	262298	8	146364022	+	43831228	43834818	1405601
+67	13	3413
+110
+
+chain	2982	chr8_random	943810	+	183568	183600	8	146364022	+	46840262	46840294	9991965
+32
+
+chain	2745	chr8_random	943810	+	335974	336003	8	146364022	-	99513082	99513111	33185960
+29
+
+chain	2672	chr8_random	943810	+	298503	298547	8	146364022	-	99522900	99522944	24221385
+44
+
+chain	2671	chr8_random	943810	+	332183	346560	8	146364022	-	102528996	102533910	187401
+51	6123	457
+105	6796	3008
+38	249	246
+57	891	885
+67
+
+chain	2639	chr8_random	943810	+	219413	219441	8	146364022	-	99507721	99507749	35294427
+28
+
+chain	2612	chr8_random	943810	+	200816	200846	8	146364022	-	99525102	99525132	4075609
+30
+
+chain	2604	chr8_random	943810	+	240329	240369	8	146364022	-	99522715	99522755	8959532
+40
+
+chain	2556	chr8_random	943810	+	216929	216957	8	146364022	-	99514612	99514640	10325210
+28
+
+chain	2552	chr8_random	943810	+	191384	191411	8	146364022	+	46840185	46840212	15340406
+27
+
+chain	2552	chr8_random	943810	+	304972	304999	8	146364022	-	99516251	99516278	22571486
+27
+
+chain	2523	chr8_random	943810	+	327142	327169	8	146364022	-	99524856	99524883	11689776
+27
+
+chain	2451	chr8_random	943810	+	317909	318170	8	146364022	-	99521638	99521896	1452880
+31	226	223
+4
+
+chain	2447	chr8_random	943810	+	313295	313321	8	146364022	-	99513300	99513326	34910154
+26
+
+chain	2433	chr8_random	943810	+	230135	233158	8	146364022	-	99507638	99508095	1270471
+81	73	73
+21	37	37
+40	18	18
+82	2643	77
+28
+
+chain	2394	chr8_random	943810	+	309803	310102	8	146364022	-	102570308	102570605	11245020
+97	185	183
+17
+
+chain	2370	chr8_random	943810	+	237880	237905	8	146364022	-	99520270	99520295	11943708
+25
+
+chain	2370	chr8_random	943810	+	302899	302924	8	146364022	-	99512327	99512352	35222469
+25
+
+chain	2330	chr8_random	943810	+	274710	274735	8	146364022	+	46843727	46843752	26272760
+25
+
+chain	2188	chr8_random	943810	+	303139	303300	8	146364022	-	99512566	99512727	1325340
+161
+
+chain	2164	chr8_random	943810	+	254246	254269	8	146364022	+	46840765	46840788	24904248
+23
+
+chain	2146	chr8_random	943810	+	166073	166100	8	146364022	+	43793293	43793320	16498497
+27
+
+chain	2129	chr8_random	943810	+	171463	171506	8	146364022	-	99524332	99524375	3948851
+43
+
+chain	2094	chr8_random	943810	+	256486	256530	8	146364022	+	46856070	46856114	4878843
+44
+
+chain	2067	chr8_random	943810	+	182380	182437	8	146364022	+	46850625	46850682	3805032
+57
+
+chain	2054	chr8_random	943810	+	318711	318733	8	146364022	-	99511225	99511247	10715405
+22
+
+chain	1964	chr8_random	943810	+	202805	202867	8	146364022	-	99509184	99509246	3143072
+62
+
+chain	1962	chr8_random	943810	+	187357	187601	8	146364022	+	46841788	46842031	9057308
+62	87	86
+95
+
+chain	1941	chr8_random	943810	+	278085	278118	8	146364022	+	46854559	46854592	1239137
+33
+
+chain	1922	chr8_random	943810	+	294361	294534	8	146364022	+	46849827	46850000	1057760
+173
+
+chain	1907	chr8_random	943810	+	166115	166177	8	146364022	+	46850070	46850132	2756260
+62
+
+chain	1904	chr8_random	943810	+	294565	294590	8	146364022	+	46846293	46846318	7797359
+25
+
+chain	1899	chr8_random	943810	+	239038	239062	8	146364022	-	99519559	99519583	3632092
+24
+
+chain	1874	chr8_random	943810	+	311858	316542	8	146364022	-	99523087	99524010	1127459
+40	4555	794
+89
+
+chain	1842	chr8_random	943810	+	208242	208344	8	146364022	-	99510852	99510954	1122309
+102
+
+chain	1826	chr8_random	943810	+	333370	333404	8	146364022	-	102528310	102528344	12860155
+34
+
+chain	1699	chr8_random	943810	+	189740	189801	8	146364022	+	43830083	43830143	11700756
+13	1	0
+47
+
+chain	1671	chr8_random	943810	+	586860	586891	8	146364022	-	59596972	59597003	79385
+31
+
+chain	1671	chr8_random	943810	+	582366	582405	8	146364022	+	86778164	86778203	135745
+39
+
+chain	1614	chr8_random	943810	+	174855	174917	8	146364022	-	102535142	102535204	7562660
+62
+
+chain	1604	chr8_random	943810	+	210485	210541	8	146364022	-	99516819	99516875	24689779
+56
+
+chain	1577	chr8_random	943810	+	165529	165568	8	146364022	+	43833540	43833579	5487018
+39
+
+chain	1529	chr8_random	943810	+	199844	199893	8	146364022	-	99524132	99524181	16599934
+49
+
+chain	1430	chr8_random	943810	+	204007	204051	8	146364022	-	102535667	102535711	2444362
+44
+
+chain	1384	chr8_random	943810	+	331973	334317	8	146364022	-	99510969	99511436	2459541
+88	2124	247
+132
+
+chain	1361	chr8_random	943810	+	178432	178456	8	146364022	+	43821398	43821422	13532386
+24
+
+chain	1349	chr8_random	943810	+	282101	282136	8	146364022	+	43834762	43834797	3301014
+35
+
+chain	1325	chr8_random	943810	+	330748	334904	8	146364022	-	99513486	99513886	3761248
+39	3999	243
+118
+
+chain	1299	chr8_random	943810	+	216700	216875	8	146364022	-	99512515	99512690	2121346
+175
+
+chain	1278	chr8_random	943810	+	275077	288204	8	146364022	+	46842223	46845574	199410
+48	13052	3276
+27
+
+chain	1258	chr8_random	943810	+	272883	272996	8	146364022	+	43835974	43836087	2232086
+113
+
+chain	1256	chr8_random	943810	+	324880	325008	8	146364022	-	99513272	99513400	5381670
+128
+
+chain	1237	chr8_random	943810	+	196535	196612	8	146364022	-	99507792	99507869	15310375
+77
+
+chain	1235	chr8_random	943810	+	284286	284429	8	146364022	+	46839806	46839949	2930992
+143
+
+chain	1191	chr8_random	943810	+	293574	293786	8	146364022	+	46839704	46839915	1788603
+62	1	0
+149
+
+chain	1161	chr8_random	943810	+	294116	294212	8	146364022	+	43829899	43829995	1318655
+4	39	39
+53
+
+chain	1160	chr8_random	943810	+	183897	184027	8	146364022	+	43793197	43793327	2884372
+130
+
+chain	1130	chr8_random	943810	+	241032	308421	8	146364022	-	102539359	102541234	585349
+125	60736	871
+57	75	74
+53	2150	266
+105	4036	272
+52
+
+chain	1119	chr8_random	943810	+	229190	229281	8	146364022	-	99508572	99508663	1537143
+73	17	17
+1
+
+chain	1018	chr8_random	943810	+	315759	315867	8	146364022	-	102570622	102570730	1907772
+108
+
+chain	1013	chr8_random	943810	+	274298	274330	8	146364022	+	46839580	46839612	3252033
+32
+
+chain	968	chr8_random	943810	+	209695	209807	8	146364022	-	102537590	102537702	976902
+112
+
+chain	955	chr8_random	943810	+	319692	319755	8	146364022	-	102541225	102541288	3356813
+63
+
+chain	920	chr8_random	943810	+	258623	258775	8	146364022	+	46839508	46839659	980562
+59	25	24
+68
+
+chain	912	chr8_random	943810	+	192332	192490	8	146364022	+	46839260	46839417	3759652
+73	1	0
+84
+
+chain	891	chr8_random	943810	+	282553	282623	8	146364022	+	46843688	46843758	5243973
+70
+
+chain	873	chr8_random	943810	+	329911	329999	8	146364022	-	99523866	99523954	8492095
+88
+
+chain	847	chr8_random	943810	+	202393	202429	8	146364022	-	99516251	99516287	1768031
+36
+
+chain	808	chr8_random	943810	+	208103	208146	8	146364022	-	99506642	99506685	12166401
+43
+
+chain	772	chr8_random	943810	+	215530	215581	8	146364022	-	102536642	102536693	4621463
+51
+
+chain	770	chr8_random	943810	+	298794	298927	8	146364022	-	102529795	102529928	1833110
+38	53	53
+42
+
+chain	762	chr8_random	943810	+	250305	250368	8	146364022	+	43793197	43793260	2202736
+63
+
+chain	756	chr8_random	943810	+	175550	175595	8	146364022	-	102569149	102569194	15473865
+45
+
+chain	725	chr8_random	943810	+	227416	227458	8	146364022	-	102569147	102569189	2128584
+42
+
+chain	715	chr8_random	943810	+	237975	238010	8	146364022	-	99524101	99524136	9984625
+35
+
+chain	713	chr8_random	943810	+	336818	336983	8	146364022	-	102542943	102543107	12287033
+51	32	31
+82
+
+chain	659	chr8_random	943810	+	178382	178432	8	146364022	+	43825088	43825138	1126561
+50
+
+chain	630	chr8_random	943810	+	343296	343350	8	146364022	-	102532544	102532598	1087222
+54
+
+chain	622	chr8_random	943810	+	284683	284767	8	146364022	+	46845804	46845888	4299331
+84
+
+chain	618	chr8_random	943810	+	240201	240253	8	146364022	-	99520719	99520771	5790991
+52
+
+chain	609	chr8_random	943810	+	323290	333340	8	146364022	-	99511696	99512332	2037608
+32	1962	77
+33	7985	456
+38
+
+chain	511	chr8_random	943810	+	216312	216456	8	146364022	-	99508390	99508534	2116227
+83	23	23
+38
+
+chain	484	chr8_random	943810	+	208068	208103	8	146364022	-	102535970	102536005	2214348
+35
+
+chain	473	chr8_random	943810	+	323389	323449	8	146364022	-	102540821	102540881	1734527
+60
+
+chain	468	chr8_random	943810	+	200282	202177	8	146364022	-	99515228	99517906	493558
+37	1827	2610
+31
+
+chain	468	chr8_random	943810	+	309496	309560	8	146364022	-	99509535	99509598	902510
+13	1	0
+50
+
+chain	464	chr8_random	943810	+	238361	238411	8	146364022	-	102570011	102570061	2549299
+50
+
+chain	406	chr8_random	943810	+	336390	336452	8	146364022	-	99513496	99513558	3227798
+62
+
+chain	400	chr8_random	943810	+	198171	198198	8	146364022	-	99524348	99524375	19170252
+27
+
+chain	389	chr8_random	943810	+	239467	298039	8	146364022	-	99516251	99516834	914933
+36	19	19
+76	58363	374
+78
+
+chain	383	chr8_random	943810	+	268230	268298	8	146364022	+	43829500	43829568	7647204
+68
+
+chain	371	chr8_random	943810	+	289553	289594	8	146364022	+	43829105	43829146	1419836
+41
+
+chain	325	chr8_random	943810	+	171359	194889	8	146364022	-	102534570	102537063	1177879
+33	23458	2421
+39
+
+chain	321	chr8_random	943810	+	245198	245253	8	146364022	+	46850481	46850536	16403329
+55
+
+chain	316	chr8_random	943810	+	336558	336619	8	146364022	-	99513661	99513722	9588463
+61
+
+chain	316	chr8_random	943810	+	215939	215982	8	146364022	-	102570362	102570405	11794790
+43
+
+chain	307	chr8_random	943810	+	268331	268373	8	146364022	+	46843677	46843719	14936951
+42
+
+chain	302	chr8_random	943810	+	246654	246683	8	146364022	+	46846317	46846346	2597963
+29
+
+chain	277	chr8_random	943810	+	330681	336249	8	146364022	-	99513081	99513355	13257215
+37	5476	182
+55
+
+chain	224	chr8_random	943810	+	233016	233053	8	146364022	-	102535110	102535147	5909193
+37
+
+chain	219	chr8_random	943810	+	216875	216929	8	146364022	-	99508952	99509006	1250703
+54
+
+chain	217	chr8_random	943810	+	192086	192136	8	146364022	+	43793491	43793541	12267504
+50
+
+chain	176	chr8_random	943810	+	230251	230289	8	146364022	-	99522702	99522740	26486914
+38
+
+chain	171	chr8_random	943810	+	301863	301893	8	146364022	-	99524375	99524405	2607431
+30
+
+chain	128	chr8_random	943810	+	303580	303689	8	146364022	-	102542031	102542140	1606173
+109
+
+chain	117	chr8_random	943810	+	213542	213590	8	146364022	-	102569848	102569896	24793283
+48
+
+chain	107	chr8_random	943810	+	265719	265758	8	146364022	+	43793691	43793730	32387625
+39
+
+chain	103	chr8_random	943810	+	302985	303114	8	146364022	-	99516149	99516278	2070053
+129
+
+chain	102	chr8_random	943810	+	266041	266087	8	146364022	+	43794012	43794058	15664471
+46
+
+chain	87	chr8_random	943810	+	266314	266347	8	146364022	+	46839806	46839839	33038660
+33
+
+chain	11336435868	chr9	140273252	+	0	140273252	9	141213431	+	10000	141153431	13
+189075	1	1
+14	2	2
+39464594	50000	50000
+261110	50000	50000
+208233	50000	50000
+142805	50000	50000
+464507	50000	50000
+152873	50000	50000
+172579	50000	50000
+799200	0	4
+398958	50000	50000
+549743	50000	100000
+632871	50000	50000
+680077	50000	50000
+181647	50000	50000
+291910	50000	100000
+465318	50000	50000
+350909	50000	50000
+194609	50000	100000
+370335	0	176
+128583	50000	100000
+157546	18100000	18150000
+450681	50000	50000
+223855	50000	50000
+162441	50000	50000
+159539	50000	50000
+199148	50000	50000
+194491	50000	100000
+158462	50000	150000
+471702	50000	150000
+376183	50000	150000
+174765	50000	150000
+289439	50000	50000
+682157	50000	50000
+158187	50000	100000
+187806	50000	50000
+178933	50000	100000
+21507948	50000	100000
+85380	50000	150000
+834971	1	0
+39559293	100000	150000
+3818133	200000	50000
+2075804	30000	50000
+1936434
+
+chain	19053295	chr9_random	1146434	+	140076	853151	9	141213431	+	43822338	44639038	145
+1110	1	1
+47	1	0
+215	1	0
+468	9	9
+1934	0	1
+953	14319	26012
+970	11	11
+117	1	1
+57	1	1
+127	0	1
+1035	1	1
+123	1	1
+1418	29455	36221
+965	1	1
+33	5	5
+816	1	1
+38	1	1
+87	8	8
+588	6	6
+286	13	13
+967	6	6
+911	125	14857
+67	1	1
+18	1	1
+472	11	11
+269	7	0
+869	1	1
+23	1	1
+240	1	0
+456	1	1
+96	1	1
+247	22	22
+225	1	1
+13	0	4
+40	1	1
+211	13	29
+582	1	1
+22	4	0
+453	1	1
+37	1	1
+251	11	11
+87	1	1
+49	1	1
+95	11	11
+149	1	1
+31	1	1
+205	5	0
+1090	5	5
+89	1	1
+74	14	14
+83	1	1
+51	1	1
+594	1	3
+462	85	85
+635	50621	3293
+88	0	1
+148	18	18
+428	2	0
+5	2	0
+19	0	1
+43	1	1
+529	1	6
+77	1	1
+31	1	1
+39	0	5
+124	15	15
+51	1	1
+80	1	1
+103	1	1
+77	1	1
+147	1	1
+72	1	1
+95	10	10
+657	1	1
+57	1	1
+69	1	1
+32	1	1
+587	4	4
+298	14	14
+1505	10	8
+560	0	4
+171	1	1
+44	1	1
+211	1	1
+22	1	1
+649	1	1
+42	0	2
+96	8	8
+45	1	0
+195	402195	519766
+38949	0	176
+45847	1	0
+46124	1	0
+3889	0	1
+52224
+
+chain	10363290	chr9_random	1146434	+	903151	1075657	GL000199.1	169874	+	0	130000	308
+35955	882	0
+20	1020	0
+32	3062	0
+106	14	15
+100	9	7
+334	16	18
+121	1	0
+84	3469	73
+179	1193	0
+255	3064	0
+235	844	167
+325	2720	0
+211	25	25
+216	3639	67
+100	681	1
+58	5271	0
+71	36	36
+155	11817	855
+1017	1	0
+10599	1	1
+42	0	1
+8519	112	112
+9882	0	680
+263	8	8
+56	30	30
+206	865	183
+1131	1	0
+12309	16295	0
+37	2637	0
+463	15	15
+739	1	1
+64	1	1
+2323	1	0
+743	202	202
+245	2	0
+10307	33	32
+8496	15	15
+1065	3	3
+49	1	1
+67	1	1
+24	1	1
+150	15	15
+81	1112	7412
+104	5	5
+160	48	48
+156	31	31
+109	29	29
+32	0	337
+118	36	36
+108	21	21
+69	163	165
+105	29	29
+255	32	32
+176	46	46
+97	54	54
+158	110	5213
+54	5	5
+61	1	0
+12	66	578
+49	0	1
+256	0	1
+5	1	0
+110	0	507
+39	59	227
+44	1	0
+5	1	2
+13	268	611
+32	340	0
+2169	5	5
+109
+
+chain	8496666	chr9_random	1146434	+	526031	616031	GL000198.1	90085	+	0	90000	391
+90000
+
+chain	3482851	chr9_random	1146434	+	0	36148	GL000201.1	36148	+	0	36148	837
+36148
+
+chain	3114479	chr9_random	1146434	+	350153	383343	7	159138663	+	58020084	58054331	923
+5741	0	1
+5176	1	1
+36	1	1
+8401	0	3
+180	1	0
+1283	1	371
+2015	11	695
+10343
+
+chain	2652717	chr9_random	1146434	+	939453	971857	GL000199.1	169874	+	50544	169869	966
+78	104	103
+57	43	43
+41	0	1193
+212	20	20
+112	51	51
+93	1	0
+763	32	32
+929	0	85729
+2133	785	785
+1551	1	1
+38	0	1
+29	1	1
+1849	179	179
+1081	14	14
+98	255	255
+3064	235	235
+844	325	325
+2000	1	1
+55	1	1
+663	211	211
+25	216	216
+3639	100	100
+681	58	58
+5271	71	71
+36	155	155
+4203
+
+chain	864673	chr9_random	1146434	+	1126594	1146123	9	141213431	-	1097613	1113419	4959
+1953	6	5
+978	2409	6373
+1991	1	1
+30	1	1
+1102	7741	55
+57	1	1
+3259
+
+chain	850211	chr9_random	1146434	+	1025598	1042157	GL000199.1	169874	+	85137	125159	1202
+223	15	15
+69	106	782
+56	4	4
+103	0	1190
+57	51	51
+154	11	11
+103	0	1190
+303	94	5704
+122	20	700
+283	11	11
+564	0	6798
+68	31	31
+85	0	1
+80	48	48
+422	49	50
+604	27	3091
+147	0	4594
+563	468	470
+104	1	1
+65	1	1
+786	1	1
+26	4	4
+3436	346	0
+2356	158	158
+2985	37	37
+170	167	170
+910	11	11
+54
+
+chain	769263	chr9_random	1146434	+	86461	232520	9	141213431	+	40031497	40507253	306
+1287	1	1
+39	9090	8469
+1482	3	0
+72	22972	39210
+845	1	5
+1628	100	33581
+19	1	1
+708	1	1
+40	1	1
+1672	2596	163229
+3012	1	1
+27	1	0
+759	0	1
+98	72164	49914
+85	17764	159979
+3474	1	1
+50	1	1
+6064
+
+chain	759449	chr9_random	1146434	+	205961	214049	9	141213431	+	40301888	40309971	6546
+2149	0	1
+2715	38	32
+3186
+
+chain	584316	chr9_random	1146434	+	1135427	1141773	9	141213431	+	140095418	140108346	9081
+578	0	1
+958	0	1
+3002	120	6700
+1688
+
+chain	406492	chr9_random	1146434	+	174973	187473	9	141213431	-	97329171	97382324	1352
+1045	1	0
+610	3	3
+25	1	1
+707	0	1
+949	1	0
+476	1	1
+37	0	2
+115	22	0
+99	2	0
+19	0	1
+85	84	84
+391	0	2
+2020	102	40820
+178	0	5
+70	1	1
+108	1	0
+1683	56	22
+203	4	0
+53	0	3
+1920	1	0
+25	15	0
+171	0	4
+991	1	0
+102	1	1
+39	1	0
+81
+
+chain	392431	chr9_random	1146434	+	102229	150933	9	141213431	-	100800050	101111299	1649
+1200	31	31
+61	100	87
+1550	13066	115954
+174	1	7
+2845	28138	189099
+40	1462	165
+36
+
+chain	384690	chr9_random	1146434	+	98535	256322	9	141213431	-	100787713	101169878	613
+1160	1	0
+743	100	2055
+1590	33793	2374
+3943	1	0
+110	10986	2654
+28	3892	11
+65	38	37
+101	8010	603
+1627	0	1
+4154	127	18597
+1903	17	17
+1098	1	0
+907	16	6
+635	1	0
+110	11	10
+1170	39276	55950
+254	1	1
+16	1	1
+222	1	1
+23	0	3
+11	1	1
+963	0	1
+1311	1	1
+22	1	1
+1083	0	2
+4770	9790	219711
+142	1	1
+35	1	1
+191	1	1
+48	1	1
+4295	1	0
+1323	1	1
+26	1	0
+2991	1	0
+1653	100	28511
+184	1	1
+25	1	1
+2332	2	0
+2424	1	1
+18	1	1
+1612	0	2
+1973	2	0
+4314
+
+chain	222862	chr9_random	1146434	+	974475	976909	GL000199.1	169874	-	29206	35723	496317
+103	0	512
+103	0	2379
+1951	0	1192
+277
+
+chain	216950	chr9_random	1146434	+	179171	191499	9	141213431	-	75591738	75613431	4354
+84	8327	17685
+315	1	1
+43	1	1
+565	1	1
+45	1	1
+144	1	1
+47	3	3
+216	4	8
+856	15	15
+173	1	1
+23	0	1
+306	1	1
+34	1	2
+855	1	1
+41	1	1
+59	0	1
+60	1	1
+46	1	1
+55
+
+chain	213582	chr9_random	1146434	+	1129631	1131840	9	141213431	-	1091833	1094042	537694
+2209
+
+chain	165378	chr9_random	1146434	+	971957	973731	X	155270560	+	21244335	21246110	770883
+1088	0	1
+111	1	1
+46	3	3
+525
+
+chain	132596	chr9_random	1146434	+	92033	271291	9	141213431	-	75460140	75627580	890
+687	15	5
+714	42447	12782
+26	11947	6649
+27	11	12
+38	1490	2
+104	2	0
+98	117515	142147
+548	14	14
+760	1	1
+15	5	5
+244	0	8
+225	1	1
+25	1	1
+184	1	1
+24	1	1
+112	1	1
+49	1	1
+657	0	4
+26	1	1
+142	1	1
+117	1	1
+521	1	1
+30	1	1
+427
+
+chain	126182	chr9_random	1146434	+	264182	265594	9	141213431	+	41417376	41418784	8289
+408	11	11
+453	3	0
+470	1	0
+66
+
+chain	121265	chr9_random	1146434	+	153981	183865	9	141213431	+	40369543	40485128	5651
+820	1	0
+80	65	65
+38	101	101
+1814	1	1
+19	1	1
+2113	24775	110477
+56
+
+chain	112452	chr9_random	1146434	+	977951	979143	9	141213431	+	41554070	41555262	1142654
+1192
+
+chain	111666	chr9_random	1146434	+	115028	116206	9	141213431	+	38976673	38977851	1144814
+1178
+
+chain	91839	chr9_random	1146434	+	95026	96000	9	141213431	-	97340505	97341479	1389514
+974
+
+chain	86695	chr9_random	1146434	+	89274	94894	9	141213431	+	40421854	40482922	755289
+656	0	1
+294	1	0
+357	1	1
+58	1	1
+181	2726	58174
+1345
+
+chain	85848	chr9_random	1146434	+	116324	118085	9	141213431	+	40126032	40127795	187229
+1300	0	2
+247	1	1
+31	1	1
+181
+
+chain	83527	chr9_random	1146434	+	105271	111078	9	141213431	+	43838264	43842306	8535
+1025	1	1
+44	1	1
+374	2077	318
+609	3	0
+643	18	19
+121	15	16
+135	5	0
+736
+
+chain	82351	chr9_random	1146434	+	265594	267154	9	141213431	-	97363431	97364991	1727
+341	2	2
+20	1	1
+738	1	1
+34	1	1
+206	1	1
+40	1	1
+174
+
+chain	74906	chr9_random	1146434	+	107880	108681	9	141213431	+	40288016	40288817	1344818
+46	1	0
+553	0	1
+201
+
+chain	73427	chr9_random	1146434	+	106816	115028	9	141213431	-	93902441	93905998	1707
+229	0	1
+500	19	19
+145	5760	1098
+49	0	1
+9	0	1
+188	1	1
+43	1	1
+243	1	1
+41	1	1
+206	1	1
+25	1	1
+443	0	1
+171	0	3
+135
+
+chain	72594	chr9_random	1146434	+	977068	977842	9	141213431	-	99740263	99741035	1743552
+651	1	0
+45	1	0
+76
+
+chain	68316	chr9_random	1146434	+	87923	91873	9	141213431	-	101134923	101183249	1049825
+372	0	1
+115	1	1
+37	1	1
+725	1749	46124
+950
+
+chain	61838	chr9_random	1146434	+	1042331	1042988	GL000199.1	169874	-	40496	41153	2045151
+657
+
+chain	55013	chr9_random	1146434	+	1075993	1076574	2	243199373	-	242829160	242829741	2308873
+581
+
+chain	54512	chr9_random	1146434	+	144930	149178	9	141213431	-	75605255	75609502	8620
+250	1	1
+26	1	1
+262	14	19
+1397	10	9
+876	1	0
+98	79	75
+65	1	1
+772	1	1
+31	1	1
+235	1	1
+74	1	1
+51
+
+chain	52053	chr9_random	1146434	+	149316	153855	9	141213431	+	40375457	40380000	99648
+79	244	244
+76	2437	2440
+75	10	10
+247	0	1
+19	1304	1304
+48
+
+chain	51431	chr9_random	1146434	+	126523	128919	9	141213431	-	101152632	101155028	6098
+2396
+
+chain	48062	chr9_random	1146434	+	390785	391322	5	180915260	-	163073999	163074536	2667488
+241	1	1
+201	3	3
+91
+
+chain	43629	chr9_random	1146434	+	1073062	1075987	GL000199.1	169874	+	35053	37976	298767
+312	2456	2456
+1	2	0
+78	21	21
+55
+
+chain	37453	chr9_random	1146434	+	1024767	1030521	GL000199.1	169874	+	88172	123905	8301
+52	0	3738
+40	1994	12406
+94	1068	11110
+31	165	2038
+48	1933	5847
+329
+
+chain	33524	chr9_random	1146434	+	133017	135796	9	141213431	+	39163384	39166153	115831
+53	1	1
+307	5	4
+44	1	1
+406	1	1
+21	5	0
+43	1	1
+177	1	1
+25	1	0
+31	1	1
+137	5	5
+20	1	1
+52	1	1
+27	1	1
+233	1	1
+20	1	1
+394	3	0
+363	1	1
+24	1	1
+370
+
+chain	29196	chr9_random	1146434	+	343146	344485	3	198022430	+	156000638	156001989	5034584
+50	1	0
+56	1	1
+104	128	140
+64	838	839
+97
+
+chain	28265	chr9_random	1146434	+	96095	96747	9	141213431	-	93903474	93904131	1828707
+74	0	10
+511	4	0
+47	1	0
+15
+
+chain	26156	chr9_random	1146434	+	111189	113362	9	141213431	-	102220148	102222323	47568
+1400	0	1
+94	5	6
+674
+
+chain	25868	chr9_random	1146434	+	149715	153807	9	141213431	-	93950637	93954729	91748
+181	1	1
+57	1	1
+353	15	15
+330	1	0
+22	1	1
+220	93	93
+114	0	17
+104	9	9
+290	2	0
+293	1	1
+20	1	1
+328	351	343
+127	1	1
+76	1	1
+331	4	0
+52	1	1
+17	1	1
+106	5	0
+146	1	1
+38	0	3
+7	1	0
+116	3	3
+16	1	1
+168	0	1
+85
+
+chain	25003	chr9_random	1146434	+	1069304	1075830	GL000199.1	169874	+	56286	59580	21268
+305	7	7
+77	487	487
+25	288	288
+36	198	198
+163	105	105
+29	463	463
+46	1256	67
+82	36	36
+95	32	32
+28	2595	552
+103	9	9
+61
+
+chain	23281	chr9_random	1146434	+	1028681	1035309	GL000199.1	169874	+	97567	114227	7110
+30	1360	6799
+121	342	0
+5	4424	9363
+103	237	233
+6
+
+chain	21805	chr9_random	1146434	+	1135081	1135321	9	141213431	+	140101239	140101479	9135145
+197	1	1
+42
+
+chain	21533	chr9_random	1146434	+	1010735	1043373	GL000199.1	169874	+	61213	69988	6310
+337	14018	4703
+439	42	42
+27	307	307
+106	220	220
+51	16938	2390
+153
+
+chain	19014	chr9_random	1146434	+	335566	335883	16	90354753	-	56512811	56513131	11268597
+170	97	100
+50
+
+chain	18803	chr9_random	1146434	+	86148	86348	9	141213431	-	100705477	100705677	11441237
+200
+
+chain	13349	chr9_random	1146434	+	1068589	1070018	GL000199.1	169874	+	79052	79803	7749
+23	14	14
+253	37	37
+60	717	39
+8	269	269
+48
+
+chain	13149	chr9_random	1146434	+	410938	411078	8	146364022	+	38639711	38639851	17290853
+140
+
+chain	12972	chr9_random	1146434	+	332343	332481	7	159138663	+	61759398	61759536	17535033
+138
+
+chain	12821	chr9_random	1146434	+	388858	389014	15	102531392	+	80798356	80798512	17757829
+81	12	12
+63
+
+chain	11442	chr9_random	1146434	+	388166	388417	12	133851895	+	34836761	34837526	19956621
+81	109	623
+61
+
+chain	11149	chr9_random	1146434	+	343358	343713	3	198022430	-	62479553	62479920	5356830
+1	103	115
+24	134	134
+93
+
+chain	11085	chr9_random	1146434	+	468603	468722	9	141213431	+	42720405	42720524	20596057
+119
+
+chain	9550	chr9_random	1146434	+	389696	390760	X	155270560	+	61752907	61753125	23891795
+65	939	93
+60
+
+chain	9178	chr9_random	1146434	+	345818	345932	16	90354753	+	32819577	32819691	24666411
+52	7	7
+55
+
+chain	9128	chr9_random	1146434	+	321692	322933	7	159138663	+	61799163	61799701	24755828
+61	1115	412
+65
+
+chain	9086	chr9_random	1146434	+	338884	339289	16	90354753	+	32789437	32789842	24819157
+53	289	289
+63
+
+chain	9023	chr9_random	1146434	+	387021	388166	7	159138663	+	61404533	61405164	23790101
+52	1085	571
+8
+
+chain	7872	chr9_random	1146434	+	1069035	1072121	GL000199.1	169874	+	119465	157584	536281
+72	46	46
+97	2835	37868
+36
+
+chain	7579	chr9_random	1146434	+	402601	403961	3	198022430	-	107545066	107546932	27123369
+31	1026	0
+52	201	1733
+50
+
+chain	7458	chr9_random	1146434	+	343360	343449	6	171115067	+	69499143	69499232	6836024
+89
+
+chain	6713	chr9_random	1146434	+	425056	425127	16	90354753	+	46455806	46455877	28826250
+71
+
+chain	6541	chr9_random	1146434	+	468921	468991	7	159138663	+	61361207	61361277	29216706
+70
+
+chain	6486	chr9_random	1146434	+	330636	330705	10	135534747	+	42383267	42383336	29375264
+69
+
+chain	6456	chr9_random	1146434	+	411427	412083	11	135006516	+	48877623	48879132	29439180
+48	554	1407
+54
+
+chain	6295	chr9_random	1146434	+	404771	404838	8	146364022	+	43770407	43770474	29850106
+67
+
+chain	6049	chr9_random	1146434	+	414120	414184	7	159138663	-	101095351	101095415	30492982
+64
+
+chain	6040	chr9_random	1146434	+	465963	466027	6	171115067	+	83274875	83274939	30512451
+64
+
+chain	5969	chr9_random	1146434	+	389015	389089	Y	59373566	-	43064540	43064609	20514560
+61	5	0
+8
+
+chain	5636	chr9_random	1146434	+	406636	407740	8	146364022	+	43770397	43770476	31630565
+28	1025	0
+51
+
+chain	5631	chr9_random	1146434	+	426803	426863	10	135534747	+	42387748	42387808	31636152
+60
+
+chain	5540	chr9_random	1146434	+	419067	419126	7	159138663	+	61079182	61079241	31906304
+59
+
+chain	5476	chr9_random	1146434	+	398987	399045	12	133851895	+	34839855	34839913	32105830
+58
+
+chain	5376	chr9_random	1146434	+	415322	415379	11	135006516	-	86268315	86268372	32415872
+57
+
+chain	5358	chr9_random	1146434	+	413960	414017	Y	59373566	-	49305277	49305334	32458256
+57
+
+chain	5349	chr9_random	1146434	+	411179	411236	7	159138663	+	91218545	91218602	32466470
+57
+
+chain	5349	chr9_random	1146434	+	417041	417098	11	135006516	-	84295010	84295067	32466776
+57
+
+chain	5305	chr9_random	1146434	+	979284	979471	GL000199.1	169874	+	100510	100697	1541
+187
+
+chain	5294	chr9_random	1146434	+	393589	393645	GL000208.1	92689	-	78786	78842	32648958
+56
+
+chain	5285	chr9_random	1146434	+	407829	407885	16	90354753	+	34022252	34022308	32672407
+56
+
+chain	5248	chr9_random	1146434	+	345095	345150	3	198022430	+	72765342	72765397	32777800
+55
+
+chain	5194	chr9_random	1146434	+	325928	325983	16	90354753	+	46454212	46454267	32965981
+55
+
+chain	5076	chr9_random	1146434	+	385523	385577	9	141213431	-	74211269	74211323	33342253
+54
+
+chain	5012	chr9_random	1146434	+	398477	398530	3	198022430	-	107545544	107545597	33565319
+53
+
+chain	4985	chr9_random	1146434	+	417987	418040	8	146364022	+	43776134	43776187	33649135
+53
+
+chain	4821	chr9_random	1146434	+	397137	397188	X	155270560	+	61817502	61817553	34214385
+51
+
+chain	4794	chr9_random	1146434	+	414576	414627	11	135006516	+	50778923	50778974	34325073
+51
+
+chain	4794	chr9_random	1146434	+	397714	397765	GL000208.1	92689	-	71810	71861	34325191
+51
+
+chain	4730	chr9_random	1146434	+	411917	411967	21	48129895	-	33764186	33764236	34527656
+50
+
+chain	4709	chr9_random	1146434	+	107713	107880	9	141213431	+	40326898	40327067	460940
+64	0	2
+103
+
+chain	4703	chr9_random	1146434	+	396620	396670	11	135006516	+	50701175	50701225	34648839
+50
+
+chain	4594	chr9_random	1146434	+	460317	460366	1	249250621	+	72586197	72586246	34758860
+49
+
+chain	4154	chr9_random	1146434	+	389765	389825	X	155270560	+	61859291	61859351	24051909
+60
+
+chain	4125	chr9_random	1146434	+	1047887	1048034	GL000199.1	169874	+	145761	145908	266403
+21	18	18
+108
+
+chain	4032	chr9_random	1146434	+	1010207	1010501	GL000199.1	169874	+	46738	47032	105345
+133	51	51
+110
+
+chain	3744	chr9_random	1146434	+	974418	974475	GL000199.1	169874	-	111819	111876	792102
+57
+
+chain	3426	chr9_random	1146434	+	939387	939437	GL000199.1	169874	+	161370	161420	23133078
+50
+
+chain	3397	chr9_random	1146434	+	1069115	1069304	GL000199.1	169874	+	57287	57476	721888
+38	97	97
+54
+
+chain	3297	chr9_random	1146434	+	1037665	1037723	GL000199.1	169874	+	108413	108471	1099981
+5	32	32
+21
+
+chain	2900	chr9_random	1146434	+	210827	210859	9	141213431	+	43889710	43889742	6957
+32
+
+chain	2688	chr9_random	1146434	+	1042157	1042279	GL000199.1	169874	+	112227	112349	8300
+65	9	9
+48
+
+chain	2652	chr9_random	1146434	+	999650	1043482	GL000199.1	169874	+	41812	46278	8409
+112	43376	4009
+54	0	1
+28	153	153
+109
+
+chain	2438	chr9_random	1146434	+	1025529	1025571	GL000199.1	169874	+	134052	134094	269933
+42
+
+chain	2404	chr9_random	1146434	+	153855	153881	9	141213431	+	40071265	40071291	103174
+26
+
+chain	2298	chr9_random	1146434	+	1010672	1010735	GL000199.1	169874	+	66766	66829	8935
+63
+
+chain	2164	chr9_random	1146434	+	1010368	1010391	9	141213431	-	71502272	71502295	32168220
+23
+
+chain	2160	chr9_random	1146434	+	388789	388840	7	159138663	-	101569537	101569588	23945255
+51
+
+chain	2026	chr9_random	1146434	+	343746	343819	10	135534747	+	18324071	18324144	14357746
+73
+
+chain	1834	chr9_random	1146434	+	1010501	1010672	GL000199.1	169874	+	60299	60470	7461
+171
+
+chain	1808	chr9_random	1146434	+	391322	391360	7	159138663	-	47529927	47529965	6263864
+38
+
+chain	1777	chr9_random	1146434	+	343550	344817	22	51304566	+	35077657	35078810	5733588
+48	1167	1053
+52
+
+chain	1529	chr9_random	1146434	+	263922	264091	9	141213431	+	65673675	65673833	515
+62	10	0
+17	1	0
+14	2	2
+63
+
+chain	1325	chr9_random	1146434	+	1037723	1037780	GL000199.1	169874	+	96057	96114	245438
+57
+
+chain	1237	chr9_random	1146434	+	1024624	1024767	GL000199.1	169874	+	49580	49723	8604
+143
+
+chain	1217	chr9_random	1146434	+	1071842	1072151	GL000199.1	169874	+	48108	48417	165690
+30	6	6
+74	169	169
+30
+
+chain	897	chr9_random	1146434	+	1035274	1035303	GL000199.1	169874	+	108574	108603	711169
+29
+
+chain	881	chr9_random	1146434	+	345308	345393	X	155270560	-	77826120	77826205	8910963
+85
+
+chain	812	chr9_random	1146434	+	344331	344387	9	141213431	+	18649465	18649521	20542621
+56
+
+chain	538	chr9_random	1146434	+	1029334	1029359	GL000199.1	169874	+	75943	75968	9317
+25
+
+chain	480	chr9_random	1146434	+	344828	344880	4	191154276	-	62643619	62643671	15050009
+52
+
+chain	461	chr9_random	1146434	+	96747	96777	9	141213431	+	38980922	38980952	1279
+30
+
+chain	364	chr9_random	1146434	+	1025018	1025062	GL000199.1	169874	+	64308	64352	115390
+44
+
+chain	296	chr9_random	1146434	+	1009971	1010001	GL000199.1	169874	+	44634	44664	18919
+30
+
+chain	288	chr9_random	1146434	+	974120	974172	GL000199.1	169874	+	44920	44972	1936043
+52
+
+chain	260	chr9_random	1146434	+	394227	394279	11	135006516	+	50701175	50701227	28339537
+52
+
+chain	210	chr9_random	1146434	+	1025062	1025090	GL000199.1	169874	+	71670	71699	216729
+6	0	1
+22
+
+chain	209	chr9_random	1146434	+	388033	388083	11	135006516	-	84294197	84294247	27927923
+50
+
+chain	152	chr9_random	1146434	+	393023	393074	20	63025520	+	26259164	26259215	28112557
+51
+
+chain	86	chr9_random	1146434	+	405210	405252	3	198022430	-	107550280	107550322	32195393
+42
+
+chain	79	chr9_random	1146434	+	392892	392941	11	135006516	+	50661000	50661049	27948217
+49
+
+chain	1574309	chrM	16571	+	0	16571	MT	16569	+	0	16569	1567
+302	1	0
+8	1	0
+2796	0	1
+13086	1	0
+376
+
+chain	14267288654	chrX	154913754	+	0	154913754	X	155270560	+	60000	155260560	8
+34821	50000	50000
+86563	30000	50000
+766173	50000	50000
+36556	50000	50000
+80121	90000	50000
+754004	100000	50000
+5505644	0	50000
+3064785	0	50079
+26309510	25000	50000
+201175	0	8
+7417	2	0
+53136	0	8
+3076	12	0
+21092	2	0
+60831	0	2
+57728	20	0
+54336	1	0
+31676	4	0
+9986	0	4
+12109	4	0
+11227342	2000	0
+354815	50000	50000
+77401	1	1
+17	1	1
+94	3	0
+266	10	10
+113	1	1
+21	1	1
+5401	5	0
+4970	2	0
+33	6	0
+3221	1	5
+6456	0	1
+1476	5	5
+2100	1	1
+40	1	1
+1316	1	0
+2446	0	1
+1589	17	15
+11171	0	1
+2639	0	1
+5190	4	0
+78	0	8
+5087	1	0
+2663	0	1
+9149	8	7
+1851	1	0
+9081	1	0
+7249	0	25
+199	2	0
+12	2	0
+16	0	209
+37	0	20
+2536	1	0
+1394	6	0
+12550	42	0
+821	0	4
+30579	0	1
+3710	0	4
+3638	0	1
+11945	1	0
+20204	1	0
+4171	0	8
+5680	0	1
+23827	2	0
+54817	1	0
+657	1	0
+342931	180000	50000
+2052068	1	27
+5375	0	2
+46	2	0
+6489	1	0
+7175	0	2
+1239	0	2
+4302	4	0
+27253	1	0
+4244	2	0
+717	2	0
+261	6	0
+26074	0	1
+236464	50000	50000
+6136098	3000000	3100000
+13518993	0	1
+449	0	1
+4533	0	4
+757	0	1
+1102	25	26
+107	0	2
+3470	1	0
+1108	0	1
+4775	0	1
+8628	1	1
+46	1	1
+1072	1	1
+44	1	1
+292	5	4
+9091	4	4
+2218	4	4
+705	1	5
+452	1	0
+88	32	32
+212	1	0
+1801	1	7
+3960	0	1
+2007	0	1
+1979	38	38
+1320	0	1
+2093	0	1
+403	0	310
+6134	1	1
+36	1	1
+1697	0	1
+97	0	13
+7624	1	1
+19	1	1
+6933	0	1
+779	7	7
+721	1	1
+43	1	1
+1626	1	0
+6146	2	0
+150	1	1
+47	1	1
+2172	2	0
+398	1	1
+31	1	1
+1149	2	2
+183	16	16
+1663	1	1
+18	1	1
+2105	10	11
+1409	1	1
+33	1	1
+1753	0	1
+408	1	0
+1916	0	1
+477	37	37
+1415	12	0
+3799	17	17
+2921	1	0
+1811	33	33
+2753	2	0
+486	0	6
+1388	1	1
+44	1	1
+186	1	1
+46	1	1
+3037	1	0
+2301	3	0
+3876	1	1
+22	1	1
+1724	0	1
+3733	0	1
+627	0	1
+250	1	0
+194	1	1
+26	1	1
+20797	10	10
+2445	1	0
+1733	0	2
+1001	12	0
+4394	9	9
+4052	10	9
+670	1	1
+97	6	0
+25	1486	1188
+10	3	2
+28	41	41
+28	2	3
+10	126	1058
+11	1051	417
+25	0	6
+18	1	1
+62	17	17
+77	0	1
+1009	41	41
+3899	10	10
+4690	0	1
+7343	1	0
+1248	1	0
+1259	1	0
+1345	0	4
+1534	1	0
+3797	16	16
+807	1	0
+2427	1	0
+48	0	1
+287	1	0
+611353	0	1
+1041	6	0
+371	0	1
+227	0	1
+2806	1	0
+36	1	1
+234	1	1
+23	1	1
+584	1	0
+22241	1	1
+65	1	1
+4605	0	1
+2326	0	20
+2130	0	1
+6170	9	13
+10665	0	1
+14631	1	0
+5359	4	0
+4004	1	0
+3182	11	0
+3897	14	16
+2551	1	0
+1824	1	0
+5274	1	1
+41	1	1
+4309	0	1
+3827	0	1
+4594	0	1
+65	1	1
+1170	1	1
+42	4	4
+214	0	1
+5228	0	1
+553	1	0
+5528	7	7
+735	14	14
+2861	1	0
+156	0	2
+6183	42	42
+2595	1	1
+41	1	1
+472	1	1
+65	0	1
+8	1	1
+1162	1	0
+565	1	1
+48	1	1
+536	2	1
+766	0	2
+4520	0	1
+1574	1	0
+503	0	1
+2558	0	1
+250061	7	7
+9650	18	18
+3208	1	1
+25	0	1
+744	2	0
+2994	1	1
+33	1	1
+1331	1	0
+2042	6	17
+1292	1	1
+35	1	1
+2485	1	1
+35	1	1
+17284	1	0
+7	7	1
+670	0	4
+429	0	1
+4736	1	0
+3849	0	1
+6745	16	16
+2344	1	1
+41	1	1
+4459	9	9
+3449	0	1
+3876	1	1
+75	1	1
+1429	7	7
+11126	26	26
+781	1	1
+28	1	1
+409	12	13
+1223	12	12
+5354	0	1
+1255	0	6
+851	65	65
+126	1	1
+47	5	5
+5931	4	0
+420	0	1
+2949	0	6
+193	324	324
+6740	1	3
+1074	1	0
+2465	1	1
+40	1	1
+640	2	0
+550	1	1
+32	1	1
+4096	1	1
+29	1	1
+949	6	6
+6258	1	0
+3957	1	0
+19608	1	1
+48	1	1
+234	0	1
+13246	13	13
+4651	321	0
+2617	1	0
+4553	0	3
+491	0	6
+7496	1	1
+9	0	10
+77	0	4
+3314	1	1
+32	1	1
+5217	1	0
+1500	17	17
+2023	1	0
+2425	0	18
+3110	8	8
+3248	1	0
+1946	1	1
+48	1	1
+9620	0	2
+31242	20000	50000
+36075685	3	0
+36004	1	1
+27	1	1
+5196	0	1
+293	0	2
+13307	0	3
+2420	6	0
+1863	0	2
+2911	0	1
+3233	2	0
+66	1	0
+2376	10	0
+4893	1	0
+745	1	0
+3897	0	13
+3835	1	1
+55	1	1
+538	1	1
+48	4	1
+20	0	2
+279	0	2
+33	1	1
+48	1	0
+387	8	8
+692	0	1
+375	3	0
+383	1	1
+18	1	1
+1289	1	1
+29	1	1
+12332	0	331
+856	4	0
+48	0	4
+8716	0	5
+130	2	0
+3001	0	1
+1332	8	5
+23273	0	1
+30174	27	39
+337	0	3
+2838	1	0
+1614	0	9
+313	0	1
+83	4	0
+172	1	1
+25	1	1
+4912	0	39
+1863	0	1
+2931	1	0
+3134	0	3
+390880	0	1
+7199	1	0
+305	2	0
+1811	2	0
+5449	0	3
+7443	0	2
+2171	1	1
+27	1	1
+2668	0	2
+2180	0	1
+1170	0	9
+1450	16	16
+3080	1	0
+920	18	18
+10219	1	0
+678	1	1
+28	1	1
+698	1	0
+112	1	0
+1831	3	0
+14327	2	0
+2087	10	10
+150	0	3
+380	1	1
+28	1	1
+1265	19	21
+7184	3	2
+4225	9	14
+1002	0	1
+3855	4	0
+2534	1	1
+30	1	1
+794	1	0
+25	1	1
+76140	70000	50000
+1432750	4799	0
+8	2973	0
+681864	20000	50000
+4278742	0	56347
+12021233	9	9
+1775	1	0
+1468	1	1
+51	16	14
+6	0	1
+6	0	1
+11	4	5
+7	0	1
+4	0	1
+75	1	2
+26	1	0
+16	0	1
+9	0	1
+19	0	2
+22	1	0
+9	0	1
+5	1	3
+14	6	7
+38	1	0
+26	1	1
+62	0	1
+38	1	1
+1687	0	1
+54	0	1
+8528	0	1
+2722	0	1
+6240	0	1
+33	0	1
+121285	1	0
+6	0	1
+35	1	0
+1381	0	1
+5368	1	0
+3079	0	1
+10863441	0	4
+1799	1	1
+24	1	1
+334	1	0
+4960	17	0
+1160	1	1
+34	1	1
+6153	3	0
+1346	4	0
+103	4	0
+2835	12	12
+304	0	16
+719	0	1
+3286	1	0
+10182	0	9
+804	1	1
+28	1	1
+749	0	1
+3387	1	1
+47	1	1
+482	0	1
+455	15	15
+719	1	1
+18	1	1
+2074	0	1
+1348	0	4
+3928	1	1
+18	1	1
+907	0	1
+2972	2	0
+115	1	1
+37	1	1
+4428	1	0
+1120	1	0
+4055	5	0
+2753	18	18
+158	3	0
+3590	1	1
+47	1	1
+62	1	0
+947	1	1
+45	1	1
+1639	1	1
+32	1	1
+1076	0	1
+3996	4	0
+7965	1	0
+1733	1	0
+1451	0	2
+617	1	0
+4375	0	1
+2194	64	63
+301	1	1
+27	1	1
+6661	1	1
+79	1	1
+1495	1	0
+499	1	1
+37	2	2
+968	1	0
+34	1	1
+6337	1	1
+18	1	1
+8162	1	1
+22	5	0
+9274	1	0
+6017	5	5
+3872	8	0
+5421	1	0
+532	6	7
+5673	0	4
+1542	4	0
+890	3	1
+2561	1	0
+1692	1	0
+1142	1	1
+32	1	1
+503	2	1
+123	1	1
+75	1	1
+2322	1	0
+201	1	0
+40	3	3
+149	3	0
+1441	1	1
+40	1	1
+159	2	0
+1278	1	1
+33	1	1
+221	0	1
+31	1	1
+161	9	10
+1890	0	1
+132	1	1
+37	1	1
+514	17	23
+1373	4	0
+907	1	1
+15	1	1
+714	1	1
+18	0	1
+10	1	1
+55	1	1
+24	1	1
+1038	2	0
+95	1	5
+1094	1	1
+170	1	1
+844	0	3
+369	1	1
+39	1	1
+650	1	1
+41	1	1
+176	12	12
+688	1	0
+7640	4	0
+2650	1	1
+28	0	4
+44	1	1
+728	8	0
+2196	0	1
+13466	0	1
+3510	0	2
+2147	1	1
+44	0	3
+1320	11	11
+210	0	4
+105	1	0
+3239	0	1
+1496	142	153
+2391	1	1
+39	0	2
+438	4	0
+2272	8	0
+6865	0	3
+7183	0	1
+5104	0	3
+182	1	0
+3131	1	1
+31	1	0
+14	1	1
+59	1	0
+373	1	1
+42	1	1
+235	13	13
+1608	0	5
+152	1	1
+106	1	1
+783	34	34
+1633	1	1
+29	3	0
+821	1	1
+24	1	1
+1178	1	1
+33	1	1
+328	1	1
+27	1	1
+5682	16	13
+146398	30000	50000
+59809	0	2
+3389	1	1
+37	1	1
+11606	0	1
+1597	0	1
+618	1	1
+47	1	1
+2698	0	1
+826	5	5
+33	0	2
+2560	0	14
+98	0	3
+1287	0	1
+7600	0	1
+9894	0	8
+7160	0	1
+32	1	1
+1698	0	1
+754	2	0
+6787	0	1
+584	0	2
+1107	1	1
+40	1	1
+365	1	1
+35	1	1
+399	0	8
+11444	0	1
+1973	0	1
+1200	0	1
+716	1	1
+25	1	1
+1570	0	2
+433	2	0
+905	0	2
+94	1	1
+28	1	1
+2490	18	18
+5054	9	1
+2184	0	2
+2955	23	21
+431	49	49
+314	1	0
+1563	1	1
+20	1	1
+1632	11	0
+1671	2	0
+1527	0	1
+676	1	1
+29	1	1
+1245	1	1
+34	0	1
+1203	22	30
+1934	1	0
+3421	0	2
+17	1	1
+774	0	30
+97	6	6
+59	12	26
+840	1	1
+19	1	1
+2036	27	53
+683	30	30
+401	0	1
+25	1	1
+381	16	0
+159	1	1
+17	1	1
+1150	0	4
+700	1	0
+29	0	2
+409	1	1
+49	1	1
+1240	1	1
+37	3	3
+2248	0	1
+1828	0	1
+1997	1	5
+4640	4	4
+4555	2	0
+150	52	0
+618	2	2
+16	1	1
+83	0	22
+56	1	57
+2531	8	0
+4250	17	17
+2203	4	0
+1665	10	0
+415	0	2
+393	0	1
+15728	1	0
+158	0	4
+82	0	14
+543	1	1
+42	1	1
+3261	18	18
+139	1	1
+37	1	1
+410	1	1
+18	1	1
+5405	0	1
+1104	1	1
+53	1	1
+392	1	1
+55	3	3
+3352	0	9
+692	106	52
+27	4	0
+13	1	3
+14	88	0
+61	2	0
+8931	0	1
+6692	2	1
+253	19	19
+869	2	0
+196	0	2
+389	1	1
+30	1	1
+949	1	0
+6057	3	0
+4741	0	1
+7689	0	2
+2046	18	18
+215	1	0
+46885	0	2
+24138	0	2
+4037	0	1
+4047693	0	1
+9545	2	0
+11590	0	4
+1698	3	1
+18923	0	4
+1806	1	1
+44	1	1
+2581	2	0
+10620	1	0
+3804	1	0
+339	2	0
+476	1	0
+5861	5	8
+109	14	0
+901	1	1
+19	1	1
+45	0	2
+1736	0	1
+6625	0	2
+7812	0	4
+7678	0	2
+5086	3	8
+4170	1	0
+1671	0	6
+6333	16	0
+902	1	1
+44	1	1
+384	6	0
+23181	4	4
+214	0	2
+8958	4	0
+220	1	1
+49	1	1
+2783	1	0
+2641	1	0
+136	20	20
+1279	1	0
+3924	6	6
+13054	0	6
+8954	13	0
+4128	0	2
+2269	0	1
+16258	2	0
+30076	1	1
+49	1	1
+102	0	1
+8824	27	27
+1730	1	1
+47	1	1
+3339	1	0
+132	16	0
+81	0	16
+89	0	6
+6369	0	1
+541	0	1
+6288	4	0
+3814	0	2
+7260	1	0
+802	0	68
+1166	1	0
+2230	0	1
+1109	1	0
+1106	0	2
+12396	1	0
+26207	1	1
+21	1	1
+4087	16	0
+1323	7	7
+525	1	0
+4198	1	0
+4682	13	13
+890	2	0
+816	2	0
+1961	4	0
+24586	1	1
+19	1	1
+4403	0	1
+1342	0	1
+57	11	12
+2229	30	31
+1979	35	0
+10541	1	0
+9725	6	0
+2536	1	2
+20	1	1
+1541	12	0
+1130	1	1
+34	1	1
+927	1	0
+4003	1	0
+966	0	1
+149	1	0
+842	0	8
+4326	1	1
+25	1	1
+569	6	7
+664	2	2
+5695	0	1
+3074	1	0
+1539	9	3
+634	1	1
+39	1	1
+8610	1	1
+11	0	1
+345	43	43
+372	0	2
+4311	6	0
+3122	2	0
+369	0	1
+9963	10	10
+2191	1	1
+23	1	1
+1060	1	1
+19	1	1
+240	12	12
+1748	1	1
+45	1	1
+1040	1	1
+31	1	1
+7446	1	1
+25	1	1
+8379	7	7
+7325	0	3
+357	1	0
+1313	1	0
+11624	0	4
+5865	0	1
+9750	0	1
+3540	16	0
+5671	13	13
+2885	4	0
+8179	0	1
+753	1	0
+2289	49	49
+1979	2	0
+1318	0	1
+957	1	0
+825	12	12
+1110	16	0
+3735	17	17
+9997	223	53
+149	22	24
+636	1	1
+22	0	1
+42	1	1
+1634	4	4
+3380	3	0
+979	0	2
+3429	1	0
+7138	14	0
+1727	1	1
+38	1	0
+88	0	1
+630	20	20
+476	0	5
+21	0	1
+94	0	1
+42	1	0
+17	0	1
+27	0	1
+172	1	1
+37	1	1
+191	1	1
+66	1	1
+630	0	1
+261	1	1
+28	1	1
+1282	17	18
+429	0	1
+1588	1	1
+20	1	1
+1416	1	1
+33	1	1
+529	0	1
+25	0	1
+1863	0	4
+1651	1	1
+28	1	1
+11815	0	1
+26	0	1
+19	1	1
+3105	0	1
+700	0	1
+150	0	1
+68	0	1
+1420	0	6
+568	14	16
+2415	0	1
+41	1	1
+415	1	1
+33	1	1
+4521	1	1
+33	1	1
+307	1	0
+176	1	0
+3790	1	1
+86	1	1
+67	1	1
+65	0	1
+7439	1	1
+18	1	1
+16805	0	1
+1764	1	0
+3104	35	35
+3845	0	1
+3384	0	2
+17	0	18
+156	1	1
+30	1	1
+165	0	2
+1087	1	0
+953	1	0
+483	0	1
+632	1	0
+652	1	0
+8563	9	7
+1860	1	0
+398	1	0
+2219	1	1
+53	1	1
+756	1	1
+66	1	1
+69	1	1
+48	1	1
+63	1	1
+28	3	0
+1057	3	0
+63	0	3
+55	1	1
+74	3	2
+159	0	3
+92	1	1
+29	1	1
+58	3	0
+1210	9	9
+54	1	1
+27	1	1
+1374	0	2
+1775	17	2
+764	14	14
+331	16	16
+2291	3	4
+1687	1	1
+26	1	1
+2469	1	0
+3243	0	1
+3636	1	1
+24	1	1
+615	1	0
+2566	0	1
+275	5	0
+695	7	0
+9686	32	32
+3416	0	1
+1452	4	0
+214	13	13
+49	0	124
+1393	9	9
+5812	1	1
+24	1	1
+5703	0	1
+4006	1	0
+1462	3	0
+5199	2	0
+1554	0	2
+715	10	12
+1966	0	2
+2801	0	16
+618	0	1
+413	18	0
+730	1	1
+31	1	1
+4372	5	0
+10789	1	0
+2399	1	0
+6750	0	2
+1363	6	0
+6736	2	0
+4457	0	4
+7867	1	0
+3495	2	1
+7584	0	1
+2652	1	0
+1771	0	1
+14808	41015	41008
+19235	0	1
+9638	0	1
+2994	0	1
+469	3	1
+499	0	1
+12074	13	13
+2807	10	11
+715	0	2
+1627	6	6
+5099	1	0
+488	1	5
+975	0	2
+1761	0	1
+1794	5	0
+8254	3	3
+18	1	1
+3737	9	9
+1442	13	13
+212	0	10
+7712	1	1
+44	1	1
+4480	40	40
+1751	1	0
+1316	1	1
+49	1	1
+9050	4	0
+143	0	2
+2813	13	13
+1286	2857	49999
+75638	40000	50000
+1583473	0	2
+1564099	1	97463
+2933461
+
+chain	1621142	chrX	154913754	+	148570601	148611616	X	155270560	-	6466757	6507765	175
+13140	0	1
+20345	6	0
+3704	1	0
+1517	1	0
+2301
+
+chain	259772	chrX	154913754	+	75282398	75286444	X	155270560	-	79901776	79905823	6183
+1486	41	41
+41	40	40
+126	11	11
+1051	1209	1210
+41
+
+chain	192506	chrX	154913754	+	114908114	114911060	X	155270560	+	114997023	115000000	3054
+63	528	528
+60	0	16
+630	28	44
+689	16	16
+436	1	0
+495
+
+chain	188216	chrX	154913754	+	114908656	114914454	X	155270560	+	115000574	115005488	36116
+49	2721	1850
+47	8	8
+197	704	696
+2	16	0
+1155	42	43
+455	2	12
+400
+
+chain	119665	chrX	154913754	+	114906873	114908114	X	155270560	+	115003848	115005094	1024208
+1216	0	5
+25
+
+chain	29390	chrX	154913754	+	76491035	76491342	1	249250621	-	136684922	136685229	4932608
+307
+
+chain	25643	chrX	154913754	+	114911150	114911426	X	155270560	+	115005157	115005433	246321
+276
+
+chain	19821	chrX	154913754	+	114908177	114911739	X	155270560	+	114982173	114982762	1997
+479	3022	49
+61
+
+chain	15998	chrX	154913754	+	114911743	114912382	X	155270560	+	114967843	114968482	6239
+639
+
+chain	9708	chrX	154913754	+	148714470	148714905	5	180915260	-	8837105	8837560	23506322
+56	313	333
+66
+
+chain	9294	chrX	154913754	+	114906712	114906808	X	155270560	+	115005518	115005614	24447825
+96
+
+chain	6266	chrX	154913754	+	114906808	114906873	X	155270560	+	114962882	114962947	1027613
+65
+
+chain	6215	chrX	154913754	+	76426104	76426191	X	155270560	+	29934095	29934182	9535161
+87
+
+chain	5894	chrX	154913754	+	143027611	143027675	2	243199373	-	154977524	154977591	249
+15	0	3
+49
+
+chain	3277	chrX	154913754	+	76426069	76426104	1	249250621	-	60612464	60612499	19993171
+35
+
+chain	2407	chrX	154913754	+	148714814	148714839	2	243199373	+	100113459	100113484	27784968
+25
+
+chain	1984	chrX	154913754	+	76426191	76426234	8	146364022	-	27059036	27059079	21505033
+43
+
+chain	1549	chrX	154913754	+	114911087	114911150	X	155270560	+	114976136	114976199	336010
+63
+
+chain	1443	chrX	154913754	+	114913555	114913597	X	155270560	+	114984570	114984612	98822
+42
+
+chain	1245	chrX	154913754	+	148714288	148714366	4	191154276	-	133575330	133575408	22672116
+78
+
+chain	1030	chrX	154913754	+	114911060	114911082	X	155270560	+	114988042	114988064	7002
+22
+
+chain	733	chrX	154913754	+	148715982	148716070	X	155270560	-	110405878	110405966	21525610
+88
+
+chain	469	chrX	154913754	+	76426248	76426375	8	146364022	-	18567958	18568085	6841016
+127
+
+chain	293	chrX	154913754	+	148716634	148716684	2	243199373	-	107635751	107635801	26436223
+50
+
+chain	50554324	chrX_random	1719168	+	610279	1452044	X	155270560	+	76412035	77367385	75
+7124	5	6
+4742	1	1
+31	1	1
+1606	21	28
+3800	1	1
+23	1	1
+6209	1	1
+4	1	0
+22	1	0
+13	1	0
+1193	1	1
+32	1	1
+2218	0	1
+7608	6	1
+670	0	2
+1396	0	2
+1207	20	20
+5098	1	0
+1294	1	0
+119	0	1
+6626	16	16
+8221	1	0
+3722	4	0
+169	0	4
+1754	11	13
+58	0	1
+239	1	1
+75	1	1
+910	0	1
+518	7	7
+6771	0	1
+4354	26	26
+781	1	1
+28	1	1
+406	16	16
+4353	1	0
+22	100	24
+930	1	0
+33	1	1
+1226	0	1
+1278	660	1078
+3884	2	2
+22	1	1
+2022	4	0
+2593	1	0
+777	0	3
+4596	153	64
+2593	1	10
+1074	1	0
+3147	1	0
+2227	1	0
+9697	1	0
+3957	1	0
+3098	0	186786
+22519	1	0
+204	1	0
+22	1	0
+63	17	18
+9565	0	6
+6660	129	0
+58	1	0
+17671	100	83
+39	1	1
+9798	2	1
+5	0	1
+19	100	237
+1127	0	1
+4928	133	164
+8370	115	394
+3028	259	91
+9555	100	1670
+18018	6	0
+3818	1	0
+72	1	0
+15	1	0
+11	1	0
+4	1	0
+10	100	30
+18171	0	1
+18316	0	28
+22590	0	1
+2592	2	0
+8265	0	2
+4335	4	3
+14218	100	218
+8896	0	2
+5422	18	17
+1347	4	4
+83	166	0
+5120	101	153
+3114	126	148
+4567	1	0
+2511	0	1
+1289	2	0
+3129	124	175
+5332	1	0
+20	1	0
+15993	0	4
+9940	115	1562
+10856	1	1
+18	0	1
+2379	1	1
+32	74	72
+41	1	1
+3148	155	3622
+2876	621	0
+31	1	1
+2212	81729	108028
+557	0	1
+4283	1	0
+148	0	457
+722	1	1
+49	113	176
+33	2	2
+2654	1	0
+25	188	415
+1394	12	0
+5398	0	1
+28	100	19
+5509	151745	28754
+87	102	102
+66	5	5
+53	70	72
+56	201	601
+7819	256	150
+16	0	1
+6	0	1
+8001	4	0
+8135	0	1
+528	12	0
+797	100	193
+2857	496	0
+5822	153	0
+8578	1	0
+10594	1	0
+6352	3	3
+35	6	7
+50	55655	72028
+890	0	1
+72	0	1
+2125	1	1
+64	1	0
+15	1	0
+5	22	19
+12	129	67
+11	1	0
+8	0	1
+4	1	0
+16	2	2
+3637	1	1
+36	1	0
+28	1	0
+942	0	1
+231	1	1
+109	101	336
+18	11	294
+14959	0	2
+22656	3	1
+1280
+
+chain	6857177	chrX_random	1719168	+	1212241	1285856	X	155270560	+	76337041	76411192	460
+53	4	4
+3247	0	6
+51	2	0
+2014	2	0
+45	4	0
+20	4	0
+48	1	0
+5158	1	1
+29	1	1
+394	16	13
+1410	1	0
+12	1	0
+14	1	0
+7	1	0
+5	1	0
+13	1	0
+36	106	188
+1195	0	31
+133	0	4
+28	1	1
+1388	1	1
+18	1	1
+2790	0	1
+767	4	4
+49	0	1
+10	110	385
+52	0	1
+56	0	1
+4004	182	11
+23	1	1
+767	1	1
+66	1	1
+3217	2	0
+25	1	1
+4309	1	0
+26	0	1
+820	2	2
+4450	0	1
+1391	1	1
+33	0	1
+31	0	8
+3634	1	0
+1669	111	432
+10524	1	2
+8620	1	0
+2158	1	0
+1513	7	7
+4600	4	4
+2111
+
+chain	5479158	chrX_random	1719168	+	19684	169644	X	155270560	+	3753512	3953553	578
+1162	21228	9243
+742	1	0
+2200	7659	14347
+948	1	0
+4152	211	33421
+819	48	49
+92	22	22
+544	44	42
+175	0	1
+63	102	104
+246	37	37
+203	6	5
+279	27	27
+206	54	54
+394	39	40
+260	2	0
+311	16	16
+208	57	57
+349	6	6
+262	134	134
+481	0	6
+56	1	1
+868	0	5
+1387	18095	3193
+790	8	6
+1718	0	2
+3436	13	13
+241	40033	77157
+63	10	10
+425	63	0
+38963
+
+chain	5155611	chrX_random	1719168	+	1349115	1404263	X	155270560	-	77841540	77897663	609
+4514	1	1
+4	1	0
+15	0	1
+1714	142	0
+26953	1	1
+31	100	192
+4795	129	41
+2612	4	0
+3389	4	0
+5037	1	1
+22	101	1223
+13	9	8
+34	2	2
+5520
+
+chain	4548442	chrX_random	1719168	+	595876	1601165	X	155270560	-	77827311	79038577	141
+3039	114	45
+9150	2	0
+1995	422998	109473
+19795	1	0
+23	1	0
+12	111	343
+20	5	4
+13	1	1
+2240	1980	60
+2381	1	3
+44	1	0
+37	0	1
+24	100	79
+2445	100	136
+5050	0	1
+8804	4	0
+4444	704	262
+34	2	2
+12610	100	395
+4803	1	1
+22	1	1
+4171	128	46
+569	0	1
+2902	29308	112180
+236	1	0
+659	1	0
+711	1	0
+104	0	6764
+3212	4	2485
+1198	1	0
+8224	110	1
+4	0	1
+8	0	1
+21	0	1
+23	4	4
+5939	0	1
+182	101	1162
+2127	1	0
+28	100	77
+5048	2	0
+2345	1	0
+3616	100	211
+11	10	11
+1378	0	44
+1405	0	1
+1238	0	1
+575	0	20
+9423	100	122
+20	1	1
+7723	0	1
+431	0	1
+181	2	0
+5386	16	0
+866	105	61
+1365	0	1
+11613	318206	1966
+13	1	2
+40	1	1
+781	0	2
+5976	121	213
+3371	0	1
+693	1	0
+169	2337	746790
+586	1	0
+2072	1	1
+34	1	1
+58	13	13
+211	1	1
+28	1	1
+332	1	1
+31	1	1
+179	11	0
+2785	0	5
+1418	1	0
+12774	0	1
+3561	1	0
+4305	1	1
+120	1	1
+377	1	1
+68	1	1
+208	9	9
+998	15	15
+2146	0	1
+693	101	90
+36	1	1
+1743	1	1
+18	1	1
+2412	15	15
+1943	29	30
+3136	0	3
+12327	3	4
+2517
+
+chain	4126434	chrX_random	1719168	+	1485975	1530227	X	155270560	+	76291305	76335950	725
+1188	0	2
+717	1	1
+34	1	1
+1032	1	1
+42	1	1
+974	1	0
+5479	16	16
+2476	1	1
+35	1	1
+1212	3	0
+152	1	1
+46	1	1
+77	7	6
+912	1	1
+38	1	1
+4230	17	17
+617	146	545
+27	3	3
+374	1	1
+18	1	1
+3639	1	1
+122	1	1
+435	4	4
+1916	16	16
+2739	1	0
+622	16	16
+6383	2	0
+2520	35	35
+5915
+
+chain	3853214	chrX_random	1719168	+	170863	1715347	X	155270560	-	151357158	154150181	220
+101	0	61
+11	0	2
+38	0	155
+54	0	1
+34100	0	1
+12001	158233	27287
+105	0	1
+847	4191	3311
+101	25049	633
+4294	18781	8391
+120	26	27
+1173	0	1
+2374	87	87
+206	41	40
+40	7493	0
+1552	0	1
+194	0	1
+6613	4	3
+492	13807	11516
+2651	0	2
+1724	0	2
+2453	0	1
+3866	165	10497
+2912	8	0
+2305	93	94
+6287	1	0
+3225	7	7
+393	1	1
+18	1	1
+298	495	25877
+271	0	138
+31886	6	0
+14613	3	0
+9199	1105799	2318225
+448	0	73
+215	36	2
+248	14	15
+1012	1	0
+110	1	1
+211	15	16
+87	3	0
+268	10	6
+108	12	12
+74	1	1
+27	1	1
+178	1	1
+18	1	1
+1429	0	10
+168	1	1
+36	1	1
+64	1	1
+62	0	1
+129	2	0
+80	13	10
+11	3	0
+19	823	1702
+36	1	0
+605	17	17
+193	1	0
+215	12	13
+271	1	1
+18	1	1
+91	1	0
+178	4	4
+39	1	1
+233	1	1
+31	1	1
+500	1	1
+68	1	1
+325	9	9
+244	0	1
+843	1	1
+46	1	1
+202	0	1
+957	0	1
+150	1	1
+81	1	0
+6	1	1
+303	8540	16182
+59	4	0
+415	4	7
+127	38	38
+333	0	44
+16	0	252
+226	27	26
+64	4	0
+91	0	4
+56	32	32
+977	0	16
+701	1	1
+29	1	1
+1743	1	0
+676	0	2
+2780	0	16
+85	0	11
+22	1	1
+952	3	0
+470	1	0
+840	4	0
+146	0	4
+131	0	34
+39	4	0
+99	1	1
+26	0	4
+80	1	1
+1476	0	13
+977	0	2
+480	0	800
+1133	4	5
+532	1	1
+37	1	1
+207	0	117633
+2070	1	1
+30	2	0
+524	2	0
+484	0	1
+446	1	0
+1642	2	0
+63	1	1
+43	1	1
+148	12	12
+2115	0	1
+116	1	1
+182	10	10
+88	1	1
+65	0	320
+107	0	2
+2083	295	0
+1170	10932	59997
+1792	0	1
+292	6	7
+677	8	11
+1932
+
+chain	2670012	chrX_random	1719168	+	22277	129533	X	155270560	-	151420019	151525192	697
+318	0	8
+1212	7792	0
+1334	4590	634
+3132	4549	4298
+403	12	12
+889	7	7
+393	20	20
+2070	17932	14002
+179	0	1
+1042	0	1
+4330	476	475
+66	0	1
+1653	797	0
+2278	8	0
+5943	18846	26826
+69	77	81
+86	822	824
+287	1	0
+7796	1771	9789
+1118	1349	0
+2572	2	0
+4177	1	0
+2904	5	0
+881	1	1
+56	6	0
+590	1	1
+23	1	1
+262	6	6
+349	1	1
+55	1	1
+208	16	16
+311	0	2
+260	1	0
+34	5	5
+394	54	54
+206	27	27
+199
+
+chain	2529127	chrX_random	1719168	+	1458959	1485875	X	155270560	+	77160344	77187173	1079
+634	0	1
+9184	1	0
+59	1	0
+14	100	16
+21	1	0
+53	2	2
+11087	2	0
+2487	0	2
+2602	1	0
+667
+
+chain	902700	chrX_random	1719168	+	269161	291745	Y	59373566	-	58967799	59197152	4215
+4053	3	0
+293	1	1
+26	0	1
+791	0	165863
+51	243	5
+66	134	1
+42	388	5
+141	0	15
+35	2	2
+42	361	0
+256	1	0
+341	3	36
+453	301	1
+147	0	1
+278	4	4
+15	0	3
+29	1	1
+122	2	0
+148	430	0
+222	151	0
+55	0	2
+149	1	0
+687	6309	50121
+61	1	1
+43	1	1
+408	80	0
+147	11	11
+228	1	1
+48	2	2
+1372	1	1
+31	1	1
+75	1	1
+28	97	0
+263	0	1
+495	98	1
+51	1	33
+52	1	1
+51	33	1
+226	1	1
+20	4	0
+211	340	0
+179	1	0
+10	1	1
+236	341	1
+555
+
+chain	569801	chrX_random	1719168	+	1106858	1112877	X	155270560	-	78234537	78240560	9279
+4787	0	4
+1232
+
+chain	569444	chrX_random	1719168	+	1452563	1458801	X	155270560	-	78136578	78142679	9342
+609	3	13
+1692	0	8
+1539	155	0
+30	3	3
+254	9	9
+1944
+
+chain	534458	chrX_random	1719168	+	90245	170863	X	155270560	-	151402385	151465977	943
+12303	69	69
+77	86	86
+822	66146	49119
+57	3	4
+1055
+
+chain	494413	chrX_random	1719168	+	391508	439759	X	155270560	-	151446976	151536655	1213
+50	57	60
+3938	36909	78166
+87	206	206
+41	40	40
+6143	240	408
+340	6	6
+194
+
+chain	379298	chrX_random	1719168	+	415243	419212	X	155270560	-	151507548	151511517	135808
+663	12	12
+3294
+
+chain	372919	chrX_random	1719168	+	1663885	1667930	X	155270560	-	153907181	153911269	141765
+802	0	3
+83	1	1
+47	1	1
+767	17	17
+1585	0	73
+215	36	2
+248	14	15
+229
+
+chain	274258	chrX_random	1719168	+	1667930	1671196	X	155270560	-	154066175	154070218	305212
+2034	1	281
+24	1	1
+190	0	200
+632	326	623
+58
+
+chain	267510	chrX_random	1719168	+	422339	428025	X	155270560	-	151460048	151465730	1055
+1034	4	3
+2317	3	0
+2328
+
+chain	266050	chrX_random	1719168	+	27992	75212	X	155270560	-	151430977	151495459	1091
+2648	315	25719
+644	9056	5097
+1296	30530	26348
+164	1	0
+310	1720	1720
+536
+
+chain	247472	chrX_random	1719168	+	49544	52383	X	155270560	+	3800594	3803433	7089
+2766	6	6
+67
+
+chain	247318	chrX_random	1719168	+	58807	462399	X	155270560	+	3743706	3828677	987
+48	658	658
+44	238	238
+102	246	246
+37	488	488
+27	206	206
+54	394	394
+39	797	797
+57	617	617
+134	287931	26427
+60	1338	0
+1419	8746	13247
+2214	50	50
+51	31242	578
+263	4	4
+5180	1349	0
+1121	24105	7962
+467	20820	8687
+32	2	2
+3992	2	0
+898	48	49
+92	22	22
+544	44	42
+175	0	1
+63	102	104
+246	37	37
+203	6	5
+279	27	27
+206	54	54
+394	39	40
+260	2	0
+311	16	16
+208	57	57
+349	6	6
+262	25	25
+590	57	63
+881	1017	1022
+1498
+
+chain	203629	chrX_random	1719168	+	419791	421950	X	155270560	-	151464996	151467156	582605
+2107	0	1
+52
+
+chain	199106	chrX_random	1719168	+	1699808	1701947	X	155270560	-	153935858	153937997	603481
+61	1	1
+57	1	1
+1588	4	4
+59	7	7
+361
+
+chain	199089	chrX_random	1719168	+	378452	380544	X	155270560	+	3796616	3798707	602253
+1586	1	0
+505
+
+chain	187776	chrX_random	1719168	+	376353	378301	X	155270560	+	3798256	3800203	654951
+729	1	0
+1218
+
+chain	174234	chrX_random	1719168	+	1285969	1288372	X	155270560	+	77019422	77021825	343560
+1763	87	87
+102	124	124
+70	56	56
+201
+
+chain	157788	chrX_random	1719168	+	111815	113457	X	155270560	+	3753462	3755104	810742
+1642
+
+chain	154415	chrX_random	1719168	+	1055747	1057376	X	155270560	+	77369279	77370908	822932
+1629
+
+chain	134293	chrX_random	1719168	+	1708912	1710376	X	155270560	+	1185231	1187137	959481
+129	1	1
+82	1	1
+350	2	297
+68	0	147
+831
+
+chain	132265	chrX_random	1719168	+	403961	405553	X	155270560	-	151477034	151478628	31377
+436	0	2
+1156
+
+chain	90853	chrX_random	1719168	+	1707707	1708693	X	155270560	+	1353464	1354449	1404000
+164	1	0
+46	1	1
+620	1	1
+37	1	1
+115
+
+chain	74037	chrX_random	1719168	+	267762	268693	Y	59373566	-	59139189	59140054	1710353
+79	97	0
+220	1	0
+317	27	60
+128	1	0
+61
+
+chain	63811	chrX_random	1719168	+	410390	415127	X	155270560	+	3822705	3827447	11885
+2487	0	6
+1981	48	47
+221
+
+chain	61116	chrX_random	1719168	+	346359	347004	X	155270560	+	3777922	3778567	2069731
+645
+
+chain	55813	chrX_random	1719168	+	2787	3496	X	155270560	-	151499719	151505905	2274078
+50	6	6
+412	0	5477
+241
+
+chain	38577	chrX_random	1719168	+	1651263	1651671	X	155270560	-	153943757	153944164	3434500
+271	1	0
+136
+
+chain	34659	chrX_random	1719168	+	1707297	1707664	X	155270560	+	1118849	1119216	3901406
+367
+
+chain	33830	chrX_random	1719168	+	267400	267758	X	155270560	-	154819600	154819959	4017435
+54	0	1
+304
+
+chain	33594	chrX_random	1719168	+	347004	347356	X	155270560	-	151523309	151523661	4010211
+352
+
+chain	33500	chrX_random	1719168	+	290273	291150	X	155270560	-	155043354	155044230	1935940
+149	427	427
+91	1	0
+137	17	17
+55
+
+chain	33229	chrX_random	1719168	+	1452213	1452563	X	155270560	-	78136229	78136579	3954656
+350
+
+chain	31748	chrX_random	1719168	+	1656832	1657169	X	155270560	-	154080972	154081310	4345014
+118	0	1
+219
+
+chain	31047	chrX_random	1719168	+	364702	460901	X	155270560	+	3752840	3788747	1318
+48	54	53
+80	31133	470
+26	58237	28604
+46	660	660
+40	242	241
+78	0	2
+22	248	248
+33	492	491
+25	208	208
+52	400	400
+34	798	798
+56	1232	1232
+21	1	1
+34	882	887
+1017
+
+chain	26366	chrX_random	1719168	+	1717468	1717765	X	155270560	-	154599490	154599787	6355797
+65	8	8
+224
+
+chain	20775	chrX_random	1719168	+	1657225	1657446	Y	59373566	+	1138227	1138450	9855403
+101	0	2
+120
+
+chain	20767	chrX_random	1719168	+	4453	4700	X	155270560	-	151332163	151332410	9860775
+174	10	10
+63
+
+chain	20271	chrX_random	1719168	+	1698243	1698467	X	155270560	-	154161726	154161950	2868
+224
+
+chain	20189	chrX_random	1719168	+	22064	22277	X	155270560	+	3752676	3752889	10232162
+213
+
+chain	20092	chrX_random	1719168	+	410218	414905	X	155270560	+	3784106	3788794	77876
+172	4468	4469
+47
+
+chain	19894	chrX_random	1719168	+	365127	367414	X	155270560	+	3744796	3747084	92469
+246	37	37
+203	5	6
+279	27	27
+206	54	54
+394	41	39
+260	0	2
+535
+
+chain	19881	chrX_random	1719168	+	217168	217385	X	155270560	+	3913712	3913929	10410664
+217
+
+chain	19372	chrX_random	1719168	+	1704190	1704597	2	243199373	+	106598364	106598785	10983407
+91	100	114
+81	74	74
+61
+
+chain	17351	chrX_random	1719168	+	365104	366619	X	155270560	+	3783188	3784703	560009
+23	246	246
+37	487	487
+27	206	206
+54	394	394
+41
+
+chain	16176	chrX_random	1719168	+	3557	21469	X	155270560	+	3768043	3793719	20345
+896	16406	24170
+326	33	33
+130	29	29
+92
+
+chain	15865	chrX_random	1719168	+	276938	277188	Y	59373566	-	59140528	59140772	2014767
+82	6	0
+162
+
+chain	15331	chrX_random	1719168	+	367414	367617	X	155270560	+	3823924	3824127	647220
+203
+
+chain	13713	chrX_random	1719168	+	489399	489544	X	155270560	+	3712149	3712294	16431967
+145
+
+chain	12918	chrX_random	1719168	+	274951	275159	Y	59373566	-	59139058	59139278	8720139
+52	0	12
+156
+
+chain	12632	chrX_random	1719168	+	1705530	1705970	X	155270560	+	145057484	145057926	18056495
+78	288	290
+74
+
+chain	12447	chrX_random	1719168	+	1030429	1030575	5	180915260	-	168461964	168462110	18325086
+146
+
+chain	12016	chrX_random	1719168	+	1317064	1317191	X	155270560	+	77214259	77214386	18979178
+127
+
+chain	11687	chrX_random	1719168	+	278072	278210	X	155270560	-	154988343	154988492	4329206
+112	25	36
+1
+
+chain	11514	chrX_random	1719168	+	278210	278346	Y	59373566	-	59141204	59141340	4138572
+136
+
+chain	10224	chrX_random	1719168	+	1704620	1704728	19	59128983	-	37939031	37939139	22329028
+108
+
+chain	10213	chrX_random	1719168	+	277934	278654	Y	59373566	-	59141065	59141499	2702219
+138	514	228
+68
+
+chain	9983	chrX_random	1719168	+	290082	290229	X	155270560	-	155043503	155043650	2501552
+48	40	40
+59
+
+chain	9686	chrX_random	1719168	+	1671544	1671645	X	155270560	+	1359785	1359886	23561825
+101
+
+chain	8627	chrX_random	1719168	+	274506	274913	X	155270560	-	154985996	154986278	9490470
+54	20	20
+32	0	8
+10	242	109
+49
+
+chain	7400	chrX_random	1719168	+	1030281	1030397	9	141213431	+	129760930	129761046	27439238
+59	26	26
+31
+
+chain	7194	chrX_random	1719168	+	274704	274779	Y	59373566	-	59139208	59139283	27842833
+75
+
+chain	7041	chrX_random	1719168	+	129047	129334	X	155270560	-	151486292	151486579	1717
+54	206	206
+27
+
+chain	6777	chrX_random	1719168	+	275159	275252	X	155270560	-	154986140	154986238	15049098
+1	37	42
+55
+
+chain	6125	chrX_random	1719168	+	479075	479168	X	155270560	-	151461082	151461175	898
+93
+
+chain	5720	chrX_random	1719168	+	1705205	1705283	3	198022430	-	36255828	36255906	21764861
+52	21	21
+5
+
+chain	5699	chrX_random	1719168	+	57777	57859	X	155270560	+	3747892	3747974	156364
+82
+
+chain	5684	chrX_random	1719168	+	275730	275789	X	155270560	-	154985991	154986050	31480070
+59
+
+chain	5671	chrX_random	1719168	+	278678	278737	X	155270560	-	154987944	154988003	7684992
+59
+
+chain	5648	chrX_random	1719168	+	288487	288546	Y	59373566	-	59194675	59194734	31602153
+59
+
+chain	5292	chrX_random	1719168	+	1698467	1698538	X	155270560	-	154160180	154160251	1242775
+71
+
+chain	4986	chrX_random	1719168	+	1705613	1705672	7	159138663	+	43857891	43857950	19004666
+59
+
+chain	4456	chrX_random	1719168	+	1030620	1030666	X	155270560	+	76367481	76367527	34837220
+46
+
+chain	4200	chrX_random	1719168	+	65786	66804	X	155270560	+	3789104	3790122	1705
+1018
+
+chain	4147	chrX_random	1719168	+	1704281	1704341	4	191154276	-	52750556	52750615	11058024
+1	2	1
+57
+
+chain	4142	chrX_random	1719168	+	276887	276938	Y	59373566	-	59140619	59140670	3855343
+51
+
+chain	3859	chrX_random	1719168	+	291150	291190	Y	59373566	-	59196218	59196258	16097861
+40
+
+chain	3722	chrX_random	1719168	+	1703633	1706063	17	81195210	-	47362086	47364493	15646977
+109	441	439
+7	1805	1784
+68
+
+chain	3009	chrX_random	1719168	+	1705804	1705856	X	155270560	+	62632912	62632964	24180689
+52
+
+chain	2509	chrX_random	1719168	+	1708877	1708912	X	155270560	+	1109247	1109282	2078841
+35
+
+chain	2078	chrX_random	1719168	+	1706063	1706085	1	249250621	+	114909259	114909281	21967653
+22
+
+chain	1700	chrX_random	1719168	+	274379	274412	Y	59373566	-	59139235	59139268	19436247
+33
+
+chain	990	chrX_random	1719168	+	1705283	1705342	X	155270560	+	119232530	119232589	19658805
+59
+
+chain	463	chrX_random	1719168	+	1703519	1703583	X	155270560	+	65440530	65440594	26501250
+64
+
+chain	2373402471	chrY	57772954	+	0	27228749	Y	59373566	+	10000	28819361	24
+34821	50000	50000
+86563	30000	50000
+766173	50000	50000
+36556	50000	50000
+80121	90000	50000
+754004	100000	50000
+6846717	50000	50000
+276367	600000	50000
+813231	500000	3000000
+39401	400000	50000
+554624	100000	50000
+535761	1	0
+32919	1	0
+10	1	1
+12811	5	0
+18899	1	1
+121	5	4
+230478	1	0
+750	24	24
+14340	1	1
+43	1	1
+2095	1	0
+14635	9	0
+2781	1	0
+45022	6	5
+7151	1	0
+9343	0	628
+5417477	0	50006
+2175794	0	50000
+1481749	50000	50000
+4867933
+
+chain	46617811	chrY	57772954	+	57228749	57772954	Y	59373566	+	58819361	59363566	80
+98295	50000	50000
+395910
+
diff --git a/public/chainFiles/hg19toHg18.chain b/public/chainFiles/hg19toHg18.chain
new file mode 100644
index 0000000..b00e42c
--- /dev/null
+++ b/public/chainFiles/hg19toHg18.chain
@@ -0,0 +1,49040 @@
+chain 21270171362 chr1 249250621 + 10000 249233096 chr1 247249719 + 0 247199719 2
+619	137	0
+166661	50000	50000
+40302	50000	50000
+153649	50000	50000
+1098479	1	1
+47	1	1
+73	117	114
+773	1	1
+43	1	1
+864369	2	2
+51	3	0
+104	13694	13694
+104	0	3
+51	2	2
+134936	50000	50000
+1161048	150000	60000
+1440092	27273	50000
+7590365	50000	50000
+116914	100000	50000
+237250	50000	50000
+3518496	50000	50000
+12702424	150000	50000
+16145012	0	1
+7772	1	0
+4705841	0	1
+52977198	50000	50000
+157344	21065	50000
+16604841	50000	50000
+189539	150000	50000
+398739	21050000	20290000
+195588	50000	50000
+186739	150000	50000
+175055	50000	50000
+201709	100000	50000
+126477	130183	50000
+381	0	3
+315	0	2
+62	1	1
+45	1	0
+19	0	1
+8	1	1
+1158	1	0
+314	12	13
+2849	3	0
+5615	1	1
+37	1	1
+3172	6	4
+190	1	1
+34	1	1
+380	0	1
+2099	3	0
+765	2	2
+366	0	4
+1186	1	0
+460	0	1
+1242	28	28
+574	1	1
+21	1	1
+1460	1	1
+105	1	1
+701	3	0
+239	0	1
+970	11	11
+2365	1	1
+21	1	1
+384	8	8
+996	2	0
+10383	2	0
+713	0	1
+5188	1	1
+30	1	1
+1233	1	0
+132	1	1
+44	1	1
+1123	22	22
+1810	1	0
+512	1	1
+39	1	1
+1096	0	16
+743	1	0
+9028	0	1
+2506	0	6
+8446	2	0
+5505	0	3
+7541	1	0
+109864	50000	50000
+78698	50000	50000
+127263	50000	50000
+170669	50000	50000
+38311	100000	100000
+1022394	50000	50000
+281532	289973	50000
+1648	1539	0
+76	3225	3
+1018	34	34
+1716	2	0
+159	4	0
+1600	0	6
+1385	1	0
+2066	1	1
+32	1	3
+1556908	150000	50000
+185320	150000	50000
+172789	50000	50000
+220313	50000	50000
+455185	50000	50000
+22047237	1	0
+34365824	150000	50000
+259514	150000	50000
+17265625	50000	50000
+11394365	50000	50000
+13665999	150000	50000
+174886
+
+chain 3264727 chr1 249250621 + 146303299 146341166 chr16 88827254 - 19388358 19424466 890
+577	1	1
+25	1	1
+63	19	19
+840	1	1
+60	1	1
+146	8	8
+874	1	1
+17	1	1
+386	1	1
+27	1	1
+931	1	1
+19	1	1
+200	1	1
+26	1	1
+72	1	0
+39	1	1
+107	2	1
+26	1	0
+25	1	1
+146	1	1
+45	1	1
+49	0	1
+434	0	4
+21	1	1
+572	0	2
+464	1	1
+50	1	1
+628	1	1
+48	1	1
+184	1	1
+25	1	1
+330	0	3
+308	14	14
+289	1	1
+57	1	1
+709	107	107
+247	1	1
+72	1	1
+470	1	1
+36	1	1
+353	1	0
+27	1	1
+92	12	12
+1001	1	1
+39	1	1
+650	1	1
+22	1	1
+171	1	1
+21	1	1
+88	0	9
+107	36	11
+23	0	1
+29	0	26
+20	3	79
+161	11	11
+134	1	1
+89	1	1
+547	1	1
+15	1	1
+409	1	1
+36	1	1
+376	11	10
+1545	1	0
+4	0	1
+36	1	1
+373	0	1
+326	1	1
+42	17	0
+97	1	0
+187	2	0
+503	1	1
+57	1	1
+443	1	1
+35	1	1
+633	1	0
+2044	3	13
+299	1	1
+37	1	1
+1159	1	1
+39	1	1
+124	1	1
+74	1	1
+103	1	1
+55	1	1
+280	10	9
+474	0	1
+382	1	1
+31	1	1
+1812	1	1
+76	1681	0
+25	1	1
+145	1	1
+18	1	1
+1228	1	1
+31	1	1
+126	9	9
+186	2	0
+142	1	1
+25	1	0
+442	10	0
+339	0	1
+89	1	1
+21	2	0
+21	151	4
+15	1	1
+489	9	9
+311	1	1
+75	1	1
+75	1	0
+124	1	1
+114	1	1
+23	1	1
+1489	0	3
+391	1	0
+2141	10	10
+460	11	11
+422	1	1
+30	1	1
+296	8	8
+638	1	1
+38	1	1
+341
+
+chain 2374970 chr1 249250621 + 146214652 146460889 chr1 247249719 - 102316553 102503720 74
+488	1	1
+24	1	1
+971	6293	0
+994	2	0
+183	2	0
+1408	1	0
+1360	1541	0
+211	0	12
+1506	111528	93105
+421	5	6
+2973	8	8
+118	12	12
+157	10	10
+706	0	18
+26	2884	0
+127	4	1
+1518	1	1
+33	1	1
+934	9	9
+908	0	1
+126	1	0
+695	20	20
+2250	5	5
+1662	179	172
+975	1	1
+53	1	1
+62	2	2
+40	1	1
+1561	1	1
+34	1	1
+668	1	0
+1671	2	0
+480	1	1
+17	4	4
+103	0	1
+50	6	6
+230	1	1
+71	1	1
+139	1	0
+975	5	0
+180	1	1
+37	1	1
+1888	3	2
+1101	1	0
+354	64	9327
+654	1	1
+36	1	1
+888	0	2
+18	1	1
+74	1	1
+25	1	1
+81	2	0
+779	1	1
+41	0	12
+22	1	1
+436	1	6
+293	1	1
+31	1	1
+83	4	0
+694	1	1
+42	1	1
+913	0	9
+472	0	1
+253	12	12
+148	89	1
+41	89	1
+342	1	1
+72	1	1
+97	1	1
+41	1	1
+108	13	16
+280	12	12
+61	1	1
+30	0	1
+71	1	1
+42	2	2
+139	0	3
+85	5	5
+90	1	1
+39	0	1
+366	13	14
+332	0	3744
+123	1	1
+19	1	1
+264	2	0
+47	1	1
+381	3	5
+109	0	1
+521	0	1
+503	1	1
+42	0	1
+739	1	1
+77	1	1
+883	0	2
+220	0	3
+93	4	0
+12	4	0
+39	5	0
+91	1	1
+34	1	1
+562	1	1
+30	1	1
+660	13	0
+1172	16	16
+69	1	1
+32	1	1
+310	1	1
+33	1	1
+97	0	1
+38	1	1
+295	0	2
+499	1	1
+57	31	14
+607	10	10
+145	1	1
+101	1	1
+346	1	1
+30	1	1
+74	1	1
+16	1	1
+203	1	1
+36	12	0
+483	16	0
+977	1	1
+86	1	1
+66	1	1
+35	1	1
+692	16	13
+402	34	34
+287	0	5
+523	0	18
+350	4	0
+32	0	2
+108	39	45
+66	30	0
+969	0	5
+1749	5	5
+95	2	0
+5	1	0
+4	0	1
+79	0	2
+65	8	11
+63	1	1
+49	1	1
+1381	0	1
+870	17	0
+139	1	1
+89	1	1
+270	3	3
+97	1	1
+66	1	1
+50	1	1
+126	1	0
+182	1	1
+83	0	4
+125	1	1
+35	1	1
+263	1	1
+32	4	4
+202	1	0
+94	1	1
+46	1	1
+206	1	1
+56	1	1
+50	1	1
+49	1	1
+188	16	16
+589	1	1
+38	1	1
+178	0	4
+67	1	1
+421	51	0
+117	1	1
+36	1	1
+71	1	1
+74	1	1
+68	10	10
+131	3	3
+56	1	0
+52	1	1
+207	4	4
+30	1	1
+283	14	14
+93	0	4
+66	1	1
+89	7	5
+36	1	1
+79	1	1
+46	21	0
+99	1	1
+229	10	10
+100	5	0
+19	8	8
+78	1	1
+87	1	1
+125	5	5
+65	1	1
+74	3	3
+344	1	1
+24	1	1
+683	1	1
+43	6287	0
+250	15	15
+798	13	12
+267	2	1
+881	1	0
+374	10	10
+1237	1	1
+40	1	1
+620	1	1
+43	1	1
+1491	1	1
+28	1	1
+68	5	5
+413	1	2
+183	5	5
+42	1	1
+363	1	1
+26	23	0
+53	1	0
+1011	15	15
+173	4	4
+15	1	1
+801	4	4
+1197	0	10
+432	22154	19
+283	4702	22
+850	9524	0
+78	76	76
+568	10	10
+775	40	32
+274	4	0
+1120	17	17
+195
+
+chain 990444 chr1 249250621 + 2485433 2499127 chr1 247249719 - 244760735 244774429 1366
+13694
+
+chain 614409 chr1 249250621 + 249233096 249240448 chr21 46944323 + 46937133 46944296 2013
+2867	16	16
+420	9	9
+176	0	1
+1252	6	0
+1275	1	1
+25	0	344
+76	0	58
+545	484	7
+40	109	0
+51
+
+chain 498595 chr1 249250621 + 146216137 146242853 chr1 247249719 - 104315183 104389677 383
+30	657	657
+196	19	18
+134	27	27
+445	20	20
+101	9	9
+169	62	62
+116	10	10
+70	62	62
+54	26	26
+70	0	22267
+240	1539	0
+91	20	24
+246	22	22
+270	112	112
+118	143	143
+86	24	24
+184	81	81
+67	47	46
+110	83	95
+335	59	59
+139	4179	2633
+241	27	27
+273	109	109
+185	76	76
+86	24	24
+184	81	81
+26	1717	1732
+80	85	53
+151	37	37
+99	37	37
+113	20	20
+101	9	9
+169	62	62
+89	37	37
+70	62	62
+54	33	33
+382	279	5055
+291	112	112
+125	147	147
+256	382	24225
+58	106	106
+51	29	29
+422	19	19
+221	84	84
+156	29	29
+162	33	33
+80	4	4
+79	11	11
+209	29	29
+183	34	34
+116	44	44
+122	5	5
+554	41	41
+140	8	8
+161	0	1
+67	58	51
+138	10	10
+246	60	60
+124	59	60
+101	138	138
+109	161	161
+56	31	28
+163	74	74
+136	7	7
+303	34	34
+119	10	10
+339	30	30
+141	91	91
+222	107	93
+237	205	205
+134	49	49
+87	22	22
+128	87	87
+105	33	33
+52	58	58
+52	87	87
+198	158	162
+125	44	44
+82	42	42
+54	10	9
+72	27	27
+154	18	18
+186	39	39
+61	87	86
+71	38	38
+116	43	43
+268	50	50
+58	120	120
+152
+
+chain 376931 chr1 249250621 + 143880003 143901185 chr1 247249719 - 126576077 126597249 122
+127	70	71
+181	31	31
+3325	1	1
+49	1	1
+820	1	1
+75	1	1
+393	1	1
+21	1	1
+2956	3	0
+232	0	5
+77	4	4
+531	1	1
+42	5	3
+183	1	1
+19	1	1
+644	1	1
+25	1	1
+701	1	1
+21	1	1
+954	1	1
+31	1	1
+129	24	14
+650	1	1
+25	1	1
+560	0	2
+1372	1	1
+46	1	1
+1547	3	1
+883	1	0
+22	1	1
+818	1	1
+30	1	1
+1231	1	1
+34	1	1
+1758	1	1
+35	1	1
+468
+
+chain 360128 chr1 249250621 + 146427813 146438983 chr1 247249719 + 144926007 144932406 9045
+138	252	252
+1258	1540	0
+76	3256	30
+81	283	283
+87	185	185
+109	273	273
+7	19	19
+155	43	43
+91	1	0
+1185	11	11
+212	2	0
+158	2	0
+1336	64	64
+346
+
+chain 260187 chr1 249250621 + 146226436 146443808 chr1 247249719 - 100391956 100589719 716
+173	5526	775
+60	400	391
+120	18	17
+164	81	83
+26	45	45
+35	1589	1589
+29	2518	2516
+7	17	17
+56	30	30
+51	56	53
+31	163	163
+74	446	446
+34	468	468
+30	141	141
+33	624	609
+8	133	133
+64	134	134
+49	237	237
+71	316	316
+58	1199	1203
+39	219	219
+38	6697	424
+97	18	18
+77	219	219
+114	64	64
+138	183	187
+118	99	99
+89	25	31
+69	24	24
+100	30	30
+69	49	49
+54	125	125
+182	197	197
+107	156930	137139
+140	175	171
+75	164	162
+157	49	49
+69	45	45
+61	48	48
+51	61	60
+71	70	70
+108	10955	10956
+84	24	24
+75	87	87
+185	109	109
+273	22	22
+246	20	24
+49	494	19550
+70	10	10
+116	62	9592
+169	9	9
+324	83	83
+151	87	77
+90	22	22
+196	68	68
+95	5	5
+57	71	71
+196	17	17
+75	73	73
+563	83	87
+110	1555	14
+45	7990	0
+54	81	81
+184	24	24
+75	87	87
+185	109	109
+273	3222	27
+64	1605	35
+142	1567	44
+37	1539	0
+281
+
+chain 257136 chr1 249250621 + 146423276 146434218 chr1 247249719 + 144926235 144932406 9046
+68	157	157
+71	288	288
+73	563	563
+83	4962	196
+1052	19	19
+155	43	43
+91	1	0
+99	76	76
+1010	11	11
+212	2	0
+158	2	0
+1746
+
+chain 252664 chr1 249250621 + 146424776 146427813 chr1 247249719 + 144927734 144930766 96654
+1055	16	16
+124	74	74
+74	224	223
+979	11	11
+212	2	0
+158	2	0
+106
+
+chain 244411 chr1 249250621 + 146449863 146457732 chr1 247249719 + 144926007 144929115 8960
+1648	1539	0
+76	3225	3
+265	45	45
+708	34	34
+329
+
+chain 149837 chr1 249250621 + 146221841 146454623 chr1 247249719 + 146043049 146859300 923
+56	335	335
+59	4859	3299
+109	185	185
+76	5018	258
+57	409	426
+45	777	777
+84	1850	1850
+41	841	820
+47	125	126
+58	101	101
+138	2026	2026
+51	4	2
+52	297	297
+81	786	786
+33	347	347
+90	23	23
+35	125	125
+44	82	81
+42	634	634
+74	225	224
+43	268	267
+50	58	58
+120	152	152
+515	62	62
+68	41	41
+432	0	18
+180	46	46
+67	26	28
+192	26	26
+231	107	107
+67	72	67
+53	67	67
+151	171	168
+59	46	47
+86	57	54
+51	138	138
+397	18	18
+114	3	2
+182	20	20
+86	167	167
+51	48	48
+233	42	42
+89	55	55
+163	43	44
+112	70	70
+355	154	154
+174	157	641342
+145	228	228
+152	366	366
+64	1134	1135
+35	269	265
+46	15	14
+137	8	8
+70	11	11
+73	29	29
+55	63	63
+62	262	247
+77	100	100
+155	39	39
+215	72	72
+178	20	20
+64	13	13
+123	12	12
+124	127	127
+100	135495	128258
+34	14433	8189
+138	64	64
+114	219	219
+77	19	19
+96	17464	11155
+185	22232	98
+69	26	26
+54	62	62
+70	10	10
+116	62	62
+169	32	32
+211	37	37
+99	9482	37
+161	23	13
+130
+
+chain 124274 chr1 249250621 + 143871002 143921945 chr1_random 1663265 - 747928 798871 209
+9001	127	127
+70	181	181
+31	41505	41505
+28
+
+chain 121346 chr1 249250621 + 146403114 146428203 chr1 247249719 - 230466401 230485108 1747
+70	156	156
+17	25	25
+22	146	146
+152	249	249
+94	2285	2290
+63	34	34
+79	80	80
+89	48	42
+85	127	127
+68	502	495
+87	61	61
+136	127	126
+4	272	272
+43	396	396
+49	175	175
+48	183	187
+40	11298	11284
+59	5488	723
+50	98	104
+107	63	63
+54	1608	4
+83	9	9
+160
+
+chain 97594 chr1 249250621 + 146218654 146221704 chr1 247249719 - 102320562 102322071 123803
+154	24	24
+174	6	6
+1045	1614	73
+33
+
+chain 76810 chr1 249250621 + 146441138 146441951 chr1 247249719 - 102499725 102500538 1571454
+813
+
+chain 54094 chr1 249250621 + 146439071 146449863 chr1 247249719 + 144927734 144930766 9063
+156	32	32
+864	3151	76
+253	432	432
+62	196	196
+62	169	169
+32	211	211
+37	99	99
+87	4753	70
+88	2	0
+106
+
+chain 51170 chr1 249250621 + 146420674 146422968 chr1 247249719 + 144928397 144930686 91522
+82	822	821
+37	60	60
+212	196	196
+62	502	502
+83	151	149
+59	2	0
+26
+
+chain 47243 chr1 249250621 + 146249630 146253102 chr1 247249719 + 146058248 146061700 347899
+23	176	176
+41	89	89
+25	420	420
+79	245	245
+20	78	78
+29	495	490
+29	72	72
+46	158	145
+143	628	627
+53	534	533
+17	5	5
+67
+
+chain 34253 chr1 249250621 + 146404045 146461111 chr1 247249719 - 100757623 100773572 2307
+96	91	95
+87	237	237
+54	39	39
+166	170	170
+93	270	264
+54	177	172
+56	15121	8830
+27	23096	966
+26	9686	241
+71	62	62
+168	10	10
+112	7057	3813
+40
+
+chain 33489 chr1 249250621 + 146442066 146462163 chr1 247249719 + 144023055 144028915 8758
+86	162	162
+20	322	322
+153	82	82
+116	7	7
+260	4934	262
+352	142	142
+79	60	60
+57	99	99
+135	6	6
+234	31	31
+264	6949	535
+45	4229	1077
+134	1105	1106
+34
+
+chain 33218 chr1 249250621 + 146446746 146453724 chr1 247249719 + 144927655 144929867 162700
+76	4	3
+532	5285	520
+407	76	76
+465	71	71
+62
+
+chain 32794 chr1 249250621 + 146404432 146406255 chr1 247249719 - 230461418 230463242 176920
+104	280	280
+90	172	172
+62	25	26
+120	135	135
+128	18	18
+13	515	515
+161
+
+chain 26745 chr1 249250621 + 146451818 146452101 chr1 247249719 - 102499420 102499703 6165314
+283
+
+chain 24305 chr1 249250621 + 146405140 146406723 chr1_random 1663265 + 611385 612968 836039
+25	120	120
+23	14	14
+26	287	287
+50	8	8
+128	685	685
+19	35	35
+26	105	105
+32
+
+chain 22423 chr1 249250621 + 146216204 146248536 chr1 247249719 + 146043705 146710884 2213
+65	5	5
+58	95	95
+44	58	58
+67	1348	1339
+20	10	10
+32	196	196
+62	2594	1055
+96	153	153
+108	10232	605314
+55	16610	57923
+59	315	315
+50
+
+chain 21816 chr1 249250621 + 146442152 146442891 chr1 247249719 + 144927740 144928479 1347746
+148	509	509
+82
+
+chain 20351 chr1 249250621 + 146356780 146459279 chr1 247249719 - 101132456 101205064 466
+178	42398	55179
+51	39820	14441
+32	3075	0
+39	16869	2651
+37
+
+chain 17175 chr1 249250621 + 249240118 249240599 chr1 247249719 - 247249264 247249719 6645750
+53	7	10
+47	109	0
+21	6	0
+36	51	102
+5	22	73
+56	16	0
+52
+
+chain 16391 chr1 249250621 + 146446357 146448997 chr1 247249719 + 144928805 144929904 1203759
+155	2048	507
+109	112	112
+60	57	57
+99
+
+chain 14917 chr1 249250621 + 146407068 146408474 chr1 247249719 + 144010187 144011603 12383
+76	149	159
+73	240	240
+47	136	136
+39	587	587
+59
+
+chain 14732 chr1 249250621 + 104074421 104074580 chr20 62435964 - 41767962 41768121 15357748
+159
+
+chain 13179 chr1 249250621 + 146404319 146408384 chr1 247249719 + 146846894 147006750 8455
+113	104	104
+20	54	54
+39	1744	1736
+34	1903	157702
+54
+
+chain 12360 chr1 249250621 + 146216167 146250305 chr1 247249719 - 103194351 103244298 1211
+37	128	128
+95	44	44
+58	67	67
+60	5	5
+51	3345	6525
+128	0	9435
+8	6200	4617
+43	3518	3485
+37	13507	18215
+40	613	636
+46	716	718
+72	53	53
+30	240	240
+72	1522	1531
+48	233	233
+42	89	89
+36	14	14
+5	804	801
+66	696	696
+34	1307	1378
+29
+
+chain 11952 chr1 249250621 + 146445104 146445575 chr1 247249719 - 100776503 100776974 637661
+94	18	18
+359
+
+chain 11854 chr1 249250621 + 146229744 146232010 chr1 247249719 + 144747607 144749863 153009
+21	19	9
+19	736	736
+20	10	10
+32	196	196
+62	54	54
+33	556	556
+43	383	383
+82
+
+chain 10753 chr1 249250621 + 146408065 146408192 chr1 247249719 - 101190210 101190337 3832842
+127
+
+chain 10394 chr1 249250621 + 104091245 104091359 chr5 180857866 + 153305659 153305773 21933263
+114
+
+chain 10333 chr1 249250621 + 104091131 104091240 chrX 154913754 + 74963065 74963174 22062861
+109
+
+chain 9815 chr1 249250621 + 146403058 146404974 chr1 247249719 - 101191494 101193412 750328
+43	256	256
+25	136	136
+32	152	152
+35	1179	1181
+58
+
+chain 9804 chr1 249250621 + 146245618 146249581 chr1 247249719 + 16785678 16789645 248382
+32	19	19
+6	51	51
+11	80	80
+47	3688	3692
+29
+
+chain 8504 chr1 249250621 + 146408954 146409155 chr1 247249719 - 101191099 101191300 2114480
+61	111	111
+29
+
+chain 8318 chr1 249250621 + 146407418 146407505 chr1 247249719 - 102486621 102486708 14753827
+87
+
+chain 7171 chr1 249250621 + 1619987 1620086 chr1 247249719 + 1662789 1662888 1670813
+99
+
+chain 7168 chr1 249250621 + 146247532 146247756 chr1 247249719 + 144759088 144759312 2272140
+43	123	123
+58
+
+chain 6908 chr1 249250621 + 146440123 146445030 chr1 247249719 - 101203201 101205034 129817
+119	142	142
+69	4461	1387
+116
+
+chain 6650 chr1 249250621 + 146406255 146406330 chr1 247249719 - 101188413 101188487 10133477
+21	3	2
+51
+
+chain 6566 chr1 249250621 + 146445881 146445977 chr1 247249719 + 144059904 144060000 2107997
+23	21	21
+52
+
+chain 6380 chr1 249250621 + 10629 10716 chrY 57772954 - 1612 1699 6955
+87
+
+chain 5940 chr1 249250621 + 146231384 146231447 chr1 247249719 - 102320696 102320759 393064
+63
+
+chain 5684 chr1 249250621 + 146407187 146407246 chr1 247249719 - 101189341 101189400 31412390
+59
+
+chain 5452 chr1 249250621 + 146243368 146248596 chr1_random 1663265 - 1047698 1052949 2624
+34	4838	4857
+26	270	274
+60
+
+chain 5266 chr1 249250621 + 249240022 249240077 chr1 247249719 - 247249582 247249637 32667083
+55
+
+chain 5203 chr1 249250621 + 146446237 146446668 chr1 247249719 - 102500144 102500575 1674615
+120	155	155
+156
+
+chain 4958 chr1 249250621 + 146451766 146451818 chr1 247249719 + 142879884 142879936 20619966
+52
+
+chain 4944 chr1 249250621 + 104074593 104074659 chr8 146274826 - 121738108 121738174 21132898
+66
+
+chain 4456 chr1 249250621 + 146406808 146406855 chr1 247249719 - 101188965 101189012 6127414
+47
+
+chain 4404 chr1 249250621 + 146406008 146406074 chr1 247249719 - 100540708 100540774 1844606
+66
+
+chain 4255 chr1 249250621 + 146230090 146231384 chr1 247249719 - 103181490 103211127 6721
+37	1201	29544
+56
+
+chain 4244 chr1 249250621 + 146216712 146216757 chr1 247249719 - 102323372 102323417 831523
+45
+
+chain 4123 chr1 249250621 + 146421615 146421675 chr1 247249719 + 143536766 143536826 34723
+60
+
+chain 3877 chr1 249250621 + 146435532 146435575 chr1 247249719 - 101203375 101203418 141544
+43
+
+chain 3825 chr1 249250621 + 146430767 146430810 chr1 247249719 - 101203375 101203418 118474
+43
+
+chain 3528 chr1 249250621 + 146454014 146454173 chr1 247249719 - 100628659 100628818 205230
+159
+
+chain 3185 chr1 249250621 + 146406525 146406559 chr1 247249719 - 101188682 101188716 16359386
+34
+
+chain 3178 chr1 249250621 + 104074770 104074842 chr7 158821424 + 21042162 21042234 21615733
+72
+
+chain 3121 chr1 249250621 + 146445079 146445768 chr1 247249719 + 144930661 144931350 792159
+25	471	471
+193
+
+chain 3050 chr1 249250621 + 146407036 146407068 chr1 247249719 - 101189190 101189222 23011976
+32
+
+chain 2960 chr1 249250621 + 146249122 146249154 chr1 247249719 + 144760680 144760712 1406096
+32
+
+chain 2741 chr1 249250621 + 146231545 146231601 chr1 247249719 - 104345036 104345092 8679
+56
+
+chain 2464 chr1 249250621 + 146424736 146424776 chr1 247249719 + 144037261 144037301 21508852
+40
+
+chain 2405 chr1 249250621 + 249239910 249239972 chr1 247249719 - 247249327 247249389 7681464
+62
+
+chain 2390 chr1 249250621 + 249240288 249240334 chr1 247249719 - 247249596 247249642 26481552
+46
+
+chain 2344 chr1 249250621 + 146216757 146250883 chr1 247249719 - 103711249 103726499 1396
+67	32948	14063
+57	892	901
+7	127	127
+28
+
+chain 2164 chr1 249250621 + 146237300 146252192 chr1 247249719 + 16771061 16779662 20592
+30	14825	8534
+37
+
+chain 1926 chr1 249250621 + 10623 10756 chr15 100338915 - 932 978 361
+6	87	0
+40
+
+chain 1909 chr1 249250621 + 146251590 146251644 chr1 247249719 - 103917507 103917561 1304306
+54
+
+chain 1317 chr1 249250621 + 146445768 146445881 chr1 247249719 + 142919887 142920000 1148922
+113
+
+chain 1215 chr1 249250621 + 146245082 146245105 chr1 247249719 + 144762924 144762947 79987
+23
+
+chain 1154 chr1 249250621 + 146232196 146232260 chr1 247249719 + 16765963 16766027 137025
+64
+
+chain 1035 chr1 249250621 + 146367698 146367747 chr1 247249719 - 99837677 99837726 4094688
+49
+
+chain 827 chr1 249250621 + 146445037 146445075 chr1 247249719 - 102502075 102502113 153232
+38
+
+chain 691 chr1 249250621 + 146454173 146454226 chr1 247249719 - 100557283 100557336 435331
+53
+
+chain 604 chr1 249250621 + 146429501 146429541 chr1 247249719 + 147018285 147018325 1335641
+40
+
+chain 424 chr1 249250621 + 146449372 146449403 chr1 247249719 - 100776122 100776153 793932
+31
+
+chain 395 chr1 249250621 + 146448669 146448702 chr1 247249719 + 144078479 144078512 164120
+33
+
+chain 88 chr1 249250621 + 146452351 146452395 chr1 247249719 - 99890656 99890700 12702616
+44
+
+chain 71 chr1 249250621 + 146451564 146451618 chr1 247249719 - 102499166 102499220 29039078
+54
+
+chain 12431961244 chr10 135534747 + 60000 135524747 chr10 135374737 + 50000 135374737 10
+5577104	0	50006
+12337571	50000	50000
+20794160	50000	50000
+286100	3200000	2480000
+191752	50000	50000
+3830277	50000	150000
+952205	100000	150000
+263307	100000	150000
+163231	50000	150000
+989829	100000	150000
+1941874	50000	50000
+211435	50000	50000
+30112515	0	319974
+13249156	0	10
+31058956	50000	50000
+2696597	150000	50000
+4615335	50000	10000
+246123	50000	50000
+1327328	1	1
+47	1	1
+1312	0	1
+56	1	1
+190	1	1
+31	1	1
+20182	1	0
+448068
+
+chain 12415603391 chr11 135006516 + 60000 134946516 chr11 134452384 + 50000 134451988 11
+1102759	50000	16576
+49571094	307000	207000
+503352	3100000	3000000
+14395596	47395	0
+491076	304	60
+30213	182	114
+26	142	1
+27914	0	1
+20009	0	1
+19	0	1
+39	0	1
+17	1	3
+10	0	1
+1008	0	1
+95	0	1
+5126	0	15
+303	0	1
+975	4	0
+1548	1	0
+191	0	20
+40	0	1
+74	1	0
+101	0	1
+25	1	0
+6178	1	0
+1875	52561	21437
+468	1	1
+81	1	1
+2620	0	1
+1640	0	4
+3305	1	0
+3342	0	1
+17899663	50000	12000
+8549206	150000	15562
+38507167	37	39
+1282	0	174
+387	0	86
+59
+
+chain 112280 chr11 135006516 + 69774695 69777256 chr11_random 215294 - 174770 177331 705
+2561
+
+chain 3731264 chr11_gl000202_random 40103 + 0 40103 chr11_random 215294 - 0 39615 791
+14658	1036	100
+6712	6	6
+32	35	523
+27	51	11
+17546
+
+chain 12330185447 chr12 133851895 + 145739 133779461 chr12 132349534 + 16000 132289534 12
+7035084	4	0
+543	1	0
+3777	1	0
+3889	52114	73000
+6014	0	1
+6524	5	126
+29	0	13
+20974	2	0
+3965	0	3
+444	11	0
+464	0	1
+27577110	3000000	1395000
+38631945	1	0
+14544	4	0
+1700	0	1
+789	12128	250000
+1783	0	1
+1075	2	0
+1042	0	1
+1526	1	1
+27	1	1
+2320	1	0
+166	0	1
+564	1	0
+2856	2	0
+900	1	0
+1387	1	1
+33	1	1
+2139	1	1
+48	1	1
+1305	2	0
+1533	2	1
+879	1	0
+744	26	26
+858	4	0
+1089	0	6
+1113	0	12
+818	1	1
+18	0	1
+217	1	1
+36	1	1
+2002	0	1
+1025	1	0
+450	48	48
+916	0	1
+18	1	1
+4694	8	0
+142	0	4
+3656	0	2
+3403	1	1
+47	1	1
+1524	1	1
+28	1	1
+5560	48	45
+676	8	8
+810	16	16
+536	0	2
+236	0	4
+167	4	0
+1419	53	49
+4688	1	1
+38	1	1
+18576	0	5
+5285	2	0
+6486	1	1
+25	1	1
+4341	14	0
+2662	0	5
+1170	0	1
+4268	4	0
+1036	1	0
+2117	8	0
+5917	0	1
+3239	4	0
+2619	1	1
+21	1	1
+937	1	1
+38	1	1
+2412	124	139
+2648	2	0
+9314	0	2
+1986	2	2
+16	1	1
+229	1	1
+93	1	1
+895	0	12
+415	5	1
+119	1	1
+185	9	8
+458	2	0
+89	1	1
+42	1	1
+2034	1	0
+1545	2	0
+280	4	0
+97	14	14
+231	2	0
+2814	0	5
+1679	1	1
+27	1	1
+25758689	1	0
+6536665	1	0
+377270	96749	57000
+668	1	1
+20	0	1
+3348	1	1
+33	1	1
+648	1	1
+29	1	1
+3731	0	4
+1834	9	14
+1688	10	0
+3103	5	5
+1140	0	1
+1167	0	1
+985	9	9
+2897	0	1
+1625	0	9
+1101	1	0
+1358	8	0
+13065721	68352	150000
+810	0	2
+343	1	0
+1771	1	0
+2702	6	7
+1900	0	1
+705	0	6
+303	0	1
+727	1	1
+43	3	6
+490	1	1
+59	1	1
+226	1	1
+52	0	3
+465	8	0
+194	1	1
+25	0	1
+139	17	17
+1833	0	1
+81	1	1
+39	1	1
+453	0	1
+719	1	1
+47	1	1
+558	0	1
+838	1	8
+288	9	10
+741	2	5
+465	1	1
+48	1	1
+268	1	1
+26	0	1
+1337	17	0
+12	2	1
+16	1	1
+84	85	2
+917	0	1
+110	1	1
+29	1	1
+1580	1	1
+40	1	1
+683	1	1
+24	1	1
+247	1	1
+36	1	1
+1411	14	14
+149	1	0
+10091386	3	0
+296	5	0
+220	100872	45000
+972469
+
+chain 2067120 chr12 133851895 + 60245 88108 chr2 242951149 + 114046160 114069967 1234
+334	1	1
+47	1	1
+111	1	1
+20	0	13
+84	1	1
+84	7	15
+55	1	1
+28	1	1
+77	1	1
+49	1	1
+99	10	10
+345	1	1
+48	0	4
+16	2	2
+168	1	1
+160	1	1
+68	1	0
+62	1	1
+23	1	1
+144	7	7
+94	2128	0
+762	12	12
+305	1	1
+40	1	1
+385	196	196
+207	0	1
+267	1	1
+53	1	1
+58	0	12
+43	1	1
+55	4	4
+38	1	0
+361	1	0
+53	1	1
+27	1	1
+448	1	1
+18	1	1
+309	4	0
+104	1	1
+35	1	1
+394	1	1
+16	1	1
+159	1	1
+38	1	1
+413	14	14
+82	5	7
+699	0	1
+52	23	24
+1077	9	9
+492	1	0
+144	18	19
+69	1	1
+26	1	1
+689	2	0
+34	5	6
+34	1	1
+187	1	1
+65	1	1
+181	9	9
+82	1	1
+55	0	2
+310	1	1
+25	1	1
+71	1	1
+74	3	3
+64	6	6
+216	5	5
+62	1	1
+35	8	3
+803	1	0
+23	1	1
+124	1	1
+90	1	1
+300	4	0
+48	0	4
+28	1	0
+85	7	4
+63	2	0
+7	3	0
+49	1	1
+255	31	31
+462	1	1
+38	1	1
+414	1	1
+37	1	1
+304	1	1
+36	1	1
+119	16	19
+62	1	1
+26	1	1
+306	1	1
+93	1	1
+114	1	1
+141	1	1
+464	1	1
+25	1	1
+145	1	1
+21	1	1
+196	1	1
+46	1	1
+295	11	11
+255	1	1
+21	1	1
+280	1	1
+90	1	1
+413	8	8
+1039	24	24
+761	1	0
+53	1	1
+94	1	0
+25	1	1
+63	1	1
+71	2070	1
+21	2	47
+228	3	0
+17	1	1
+133	11	0
+137	1	1
+43	1	1
+90	3	3
+23	2	0
+144	1	1
+99	1	1
+349	3	3
+29	5	5
+60	0	70
+93	1	1
+21	1	1
+138	0	2
+83	1	1
+68	1	1
+166	1	1
+49	1	1
+461	1	1
+18	0	17
+26	1	1
+50	1	1
+14	0	1
+34	1	1
+370	1	1
+32	1	1
+68	14	14
+98
+
+chain 484774 chr12 133851895 + 88108 95739 chrX 154913754 + 154905409 154913416 8417
+2	1	1
+34	1	1
+80	1	1
+32	1	1
+415	1	1
+48	1	1
+73	1	1
+44	1	1
+149	13	13
+211	1	1
+26	1	1
+271	0	3
+528	1	1
+96	1	1
+507	1	1
+100	1	1
+121	37	37
+520	1	1
+34	1	1
+166	1	1
+45	1	1
+96	1	1
+87	1	1
+82	4	4
+71	1	1
+34	1	1
+132	1	1
+23	1	1
+97	1	1
+30	2	2
+109	3	3
+36	1	1
+134	2135	2017
+245	454	1029
+82	84	0
+113
+
+chain 233388 chr12 133851895 + 133837240 133840071 chr7 158821424 + 158817351 158819960 454901
+564	1	1
+52	1	0
+36	1	1
+470	1	1
+28	1	1
+359	1	1
+38	1	1
+130	5	0
+3	216	0
+97	3	2
+46	1	1
+559	1	1
+43	0	1
+78	1	1
+94
+
+chain 194103 chr12 133851895 + 62428 64518 chr14 106368585 + 64430621 64433205 634790
+748	40	40
+140	0	1
+167	0	373
+27	0	120
+968
+
+chain 49263 chr12 133851895 + 133825767 133827148 chr11 134452384 + 74280352 74281733 2582033
+188	22	24
+55	110	110
+117	297	297
+62	252	253
+116	101	98
+61
+
+chain 35717 chr12 133851895 + 133841521 133841895 chr5 180857866 - 180793287 180793661 3746803
+374
+
+chain 32957 chr12 133851895 + 133823831 133824928 chrX 154913754 - 110744397 110745491 4131553
+102	47	47
+104	308	309
+61	155	155
+59	173	169
+88
+
+chain 18331 chr12 133851895 + 133822513 133823307 chr7 158821424 + 35158939 35159735 11829157
+110	151	152
+60	413	414
+60
+
+chain 16856 chr12 133851895 + 66036 76221 chr19 63811651 - 63781390 63791585 1292
+70	1	1
+57	16	16
+51	9959	9969
+31
+
+chain 16157 chr12 133851895 + 109428208 109428485 chr2 242951149 - 225002676 225002954 13880737
+71	91	92
+115
+
+chain 11750 chr12 133851895 + 60000 60122 chr12 132349534 - 132324140 132324262 19413804
+122
+
+chain 9037 chr12 133851895 + 133826997 133827421 chr2 242951149 + 160701141 160701565 3717783
+90	61	61
+34	175	175
+64
+
+chain 8057 chr12 133851895 + 133826086 133826759 chr3 199501827 - 98694913 98695583 3241421
+56	127	126
+50	305	303
+135
+
+chain 4873 chr12 133851895 + 133822983 133823177 chr6 170899992 + 146924403 146924597 15743780
+57	73	73
+64
+
+chain 4427 chr12 133851895 + 133827536 133827658 chr3 199501827 - 37386916 37387038 7696734
+122
+
+chain 4266 chr12 133851895 + 109428325 109428370 chr8 146274826 + 102422247 102422292 23131068
+45
+
+chain 4036 chr12 133851895 + 133826320 133826456 chrX 154913754 + 144352164 144352300 4124454
+136
+
+chain 3880 chr12 133851895 + 95312 95362 chr1 247249719 - 247249339 247249389 25961870
+50
+
+chain 3693 chr12 133851895 + 63176 63216 chr6 170899992 - 141104715 141104755 640206
+40
+
+chain 3673 chr12 133851895 + 133827423 133827506 chr2 242951149 - 104106513 104106596 10382380
+83
+
+chain 3091 chr12 133851895 + 133826496 133826821 chr11 134452384 - 91473718 91474043 4183905
+58	205	205
+62
+
+chain 3057 chr12 133851895 + 133822699 133822767 chr2 242951149 + 211079534 211079602 19980130
+68
+
+chain 2758 chr12 133851895 + 133827507 133827536 chr3 199501827 - 112531647 112531676 15775673
+29
+
+chain 2377 chr12 133851895 + 133825725 133826065 chr1 247249719 + 157351310 157351652 3309912
+42	265	267
+33
+
+chain 2375 chr12 133851895 + 95368 95419 chr1 247249719 - 247249256 247249307 12772530
+51
+
+chain 2223 chr12 133851895 + 133827262 133827357 chr6 170899992 + 81976496 81976591 4176034
+95
+
+chain 2091 chr12 133851895 + 109428279 109428301 chr20 62435964 + 39979396 39979418 21613404
+22
+
+chain 1955 chr12 133851895 + 133822880 133822953 chr4 191273063 - 60412182 60412255 19166211
+73
+
+chain 1569 chr12 133851895 + 133823330 133823447 chr5 180857866 + 90128366 90128483 9408356
+117
+
+chain 1532 chr12 133851895 + 133822199 133822253 chr12 132349534 + 77527067 77527121 12101346
+54
+
+chain 1265 chr12 133851895 + 133825609 133825680 chr2 242951149 + 183532658 183532729 7750866
+71
+
+chain 1251 chr12 133851895 + 95185 95235 chr18 76117153 - 76117025 76117075 24929113
+50
+
+chain 1165 chr12 133851895 + 133826456 133826496 chrX 154913754 - 53085075 53085115 5993397
+40
+
+chain 1153 chr12 133851895 + 133824667 133824711 chr10 135374737 - 97414674 97414718 8388000
+44
+
+chain 852 chr12 133851895 + 133822443 133822508 chr5 180857866 + 49699275 49699340 23831787
+65
+
+chain 636 chr12 133851895 + 133823040 133823067 chr6 170899992 + 127619395 127619422 20859432
+27
+
+chain 615 chr12 133851895 + 133823498 133823556 chr14 106368585 - 76653675 76653733 3589163
+58
+
+chain 440 chr12 133851895 + 133827198 133827224 chr1 247249719 - 50786620 50786646 7302157
+26
+
+chain 9007882413 chr13 115169878 + 19020000 115109878 chr13 114142980 + 17918000 114127980 14
+26987167	0	1
+40753157	150000	50000
+25443670	150000	400000
+1821999	413955	384056
+369930
+
+chain 17589438 chr13 115169878 + 114456082 114639948 chr13 114142980 - 484930 668986 160
+430	0	2
+2905	4	8
+143	0	30
+612	0	4
+18	0	2
+175	1	1
+49	0	2
+2159	1	1
+27	1	1
+979	0	144
+1492	0	2
+174870
+
+chain 8359015315 chr14 107349540 + 19000000 107289540 chr14 106368585 + 18070000 106360585 15
+1081285	1	1
+43	1	1
+76	0	2
+437	1	1
+19	1	1
+440	1	0
+11	1	1
+59	15	15
+63	12	12
+70	1	0
+734	1	1
+165	4	1
+96	1	1
+46	0	1
+83	1	1
+149	4	4
+164	20	20
+63	16	15
+359	1	1
+39	1	1
+103	1	1
+76	1	1
+139	1	1
+38	1	1
+344	1	1
+65	1	0
+166	5	5
+88	1	1
+57	287	0
+59	1	1
+317	1	0
+52	1	1
+92	0	4
+651	4	4
+82	1	1
+93	1	1
+64	1	1
+24	1	1
+856	1	1
+35	1	1
+258	1	1
+17	1	1
+478	0	1
+1335	33	33
+1029	1	1
+37	1	1
+1115	4	3
+72	1	1
+643	10	10
+132	6	6
+89	2	0
+209	4	15
+77	5	5
+427	1	1
+41	1	1
+949	1	1
+16	1	1
+732	1	1
+44	0	2
+128	1	0
+91	1	1
+180	6	6
+388	6	6
+50	12	13
+275	1	1
+33	1	1
+142	1	1
+61	1	1
+560	1	1
+20	1	1
+1327	13	6
+1013	83	83
+202	4	0
+43	1	1
+352	10	10
+261	1	1
+39	1	1
+939	0	12
+1678	0	36
+159	1	1
+32	1	8
+818	6	0
+580	0	1
+931	0	1
+276	0	2
+3513	46	60
+882	0	2
+94	1	1
+49	1	1
+864	0	4
+40	1	1
+807	15	16
+416	3	0
+3345	15	15
+92	29	30
+80	1	1
+48	1	1
+2459	1	0
+646	66	66
+359	1	1
+29	0	54
+1875	0	3
+141696	1	1
+32	1	1
+8201115	0	1
+107	0	1
+2137	1	1
+39	1	1
+8848	1	0
+4806	0	1
+2075	0	1
+16612	0	1
+2385	0	3
+11506	0	8
+1353	1	0
+4596	1	0
+2073	1	2
+28	1	1
+2311	1	1
+44	1	1
+10440	4	0
+894	1	0
+1638	96	0
+41	0	9
+20	1	1
+2705	0	6
+352	1	1
+25	1	1
+742	1	0
+1048	18	2
+12085977	1	0
+14871228	0	3
+29067652	1	1
+47	1	1
+20173856	0	1292
+2548494
+
+chain 25802 chr14 107349540 + 20085579 20085848 chr8 146274826 + 118781991 118782260 6606813
+269
+
+chain 9908 chr14 107349540 + 20110215 20120217 chr22 49691432 + 14757849 14767860 97
+45	9891	9900
+66
+
+chain 8901 chr14 107349540 + 20090287 20100367 chr14 106368585 - 87815145 87825210 65
+33	9964	9949
+83
+
+chain 7700563179 chr15 102531392 + 20000000 102521392 chr15 100338915 + 18260008 100338915 16
+8448	2	6
+4086	0	1
+9569	1	1
+40	5	0
+56	1	7
+872354	40513	40506
+553	4	4
+876	40	39
+139	25	25
+1881	18	19
+499	8	8
+310	79	85
+78	26	23
+181	6	5
+569	11	11
+539	28	24
+261	22	20
+776	15	13
+62	13	13
+860	0	1
+716	0	26
+1349	167	166
+1070	23	23
+398	1	0
+177	21	5
+534	0	4
+770	24	18
+606	33	33
+1861	55	55
+2169	0	3
+558	19	20
+227	14	16
+329	5	5
+430	18	20
+620	1	0
+1112	0	2
+641	4	0
+476	47	47
+1285	1	0
+1139	49	49
+183	0	4
+1425	0	20
+186	1	0
+219	1	0
+607	44	44
+371	8	2
+507	0	2
+66	42	43
+999	4	4
+318	15	15
+1092	74	74
+808	61	61
+52	42	42
+109	51	51
+1535	0	14
+14011	0	4
+7955	1	4
+1350	0	1
+318	27	27
+600	4	0
+442	1	0
+1396	38	38
+1107	3	0
+1441	5	0
+360	49	49
+256	10	20
+497	39	39
+2129	0	4
+1242	0	2
+478	0	4
+708	92	92
+154	10	10
+1583	33	33
+1303	37	0
+100	14	14
+1138	92	109
+114	31	31
+2917	34	34
+1762	48	48
+449	0	1
+2458	1	9
+869	0	1
+534	49	49
+309	0	1
+2627	1	1
+3729	0	22
+565	1	0
+1845	0	1
+660	27	27
+68	0	1
+217	46	22
+1519	34	34
+559	32	32
+3851	0	1
+265	7	8
+224	0	4474
+444	0	1
+1651	10	11
+297	0	1
+665	0	21
+48	1	1
+1763	0	2
+245	1	1
+39	1	1
+519	1	1
+31	1	1
+2398	6	0
+749	1	49
+2072	0	4
+703	5	5
+337	0	1
+470	45	45
+1163	0	3
+1342	45	45
+140	1	0
+83	65	64
+723	38	38
+99	28	31
+92	0	1
+1218	13	0
+384	2	0
+292	41	41
+101	12	12
+576	2	0
+1907	21	21
+318	0	1
+1973	34	34
+689	51	51
+357	8	8
+2354	15	15
+2295	26	26
+2558	28	28
+571	2	0
+16	5	0
+323	1	0
+36	1	0
+5342	0	111
+1722	70	38
+272	13	13
+1284	1	0
+1128	4	4
+2189	0	1
+474	0	2
+1284	27	27
+36	6	0
+641	39	39
+381	2	0
+56	0	1
+2591	57	57
+160	121	121
+89	0	2
+316	1	0
+782	0	20
+155	1	1
+21	1	1
+601	6	0
+567	0	1
+278	1	1
+29	1	1
+89	4	0
+1737	1	1
+58	1	1
+368	24	24
+2113	24	20
+218	2	0
+18	1	1
+684	4	4
+3200	33	33
+58	18	18
+164	39	39
+296	6	6
+431	37	37
+431	47	47
+93	26	26
+216	48	48
+2779	17	0
+745	1	2
+104	61	61
+445	28	28
+356	0	1
+1484	2	1
+436	25	25
+306	57	57
+230	4	4
+843	49	50
+364	7	7
+796	28	28
+663	2	0
+93	15	0
+4378	0	1
+133	30	26
+41	2	0
+80	150	150
+925	0	3
+1882	13	13
+4513	0	1
+111	78	78
+200	0	6
+682	1	0
+200	0	3
+429	2	0
+736	20	20
+1573	121	120
+245	21	12
+1656	22	54
+616	1	2
+158	1	0
+587	41	44
+1053	6	6
+1116	36	36
+152	7	10
+448	1	0
+269024	863295	100000
+334079	50000	100000
+180557	74	0
+62	0	107
+7	2	1
+26	3	4
+4	0	1
+19	3	4
+10	42	87
+27	1	1
+202	1	1
+17	1	0
+156	1	1
+55	1	1
+111	1	0
+144	1	1
+57	1	0
+687074	50000	50000
+120648	348	0
+45585	1	0
+6994	0	1
+3398063	12354	44008
+7672	2	0
+1809	0	1
+428524	10165	101014
+43170	4	4
+1064959	5086	128966
+1021	1	0
+1710	0	1
+931	2	0
+4505	1	0
+686	2	525
+360	0	33
+130	1	1
+18	1	1
+12369	0	1014
+6233	1	0
+359485	111749	100000
+33855822	239	0
+2852112	0	1
+7040367	1	0
+2815738	1	3
+7055922	50000	60000
+363827	32	32
+104991	1	0
+203136	6050	0
+1426791	50000	60000
+13510190	5553	22012
+9194	3	0
+108	4	0
+41	1	0
+45	7	0
+2350	13	0
+5027	2	0
+534	0	1
+794	2	0
+4227	8	6
+5769	0	1
+381	0	1
+2524	2	0
+547	5	0
+1967	1	0
+1192	0	105
+1042	6	0
+3935380
+
+chain 22529558 chr15 102531392 + 21901199 22210800 chr15 100338915 + 19154576 19464222 111
+143347	1	1
+30	1	1
+2265	10	11
+297	0	1
+665	49	70
+240	39	39
+1731	41	41
+519	33	33
+339	22	22
+2037	4	0
+749	1	49
+910	38	38
+1831	3	9
+333	0	1
+470	1	1
+43	1	1
+1518	1	1
+51	1	1
+1122	1	0
+2351	19	6
+376	2	0
+1022	2	0
+1907	1	1
+19	1	1
+318	0	1
+3104	8	8
+179	1	1
+29	1	1
+3162	2	0
+2854	1	1
+26	1	1
+482	1	0
+512	1	1
+26	1	1
+571	27	16
+323	37	36
+5342	0	111
+542	40	39
+1141	64	35
+275	13	13
+503	26	26
+130	44	44
+581	4	0
+1128	4	4
+749	0	1
+1439	0	1
+474	0	16
+1270	1	1
+25	1	1
+54	11	0
+623	1	1
+37	1	1
+381	20	0
+56	0	1
+2591	1	1
+55	1	1
+160	4	4
+75	14	14
+1217	0	15
+742	59	53
+955	3	0
+1737	60	60
+391	43	43
+2071	24	20
+218	21	19
+684	4	4
+1195	4	4
+2001	1	1
+31	1	1
+58	18	18
+499	6	6
+431	1	1
+35	1	1
+431	1	1
+45	1	1
+3158	17	0
+983	0	1
+773	16	16
+1457	4	1
+767	1	1
+55	1	1
+338	10	10
+650	0	2
+123	3	4
+261	1	1
+48	1	1
+53	7	7
+776	1	1
+46	1	1
+663	2	0
+377	13	13
+4081	0	1
+159	5	0
+41	1	0
+164	1	1
+61	4	4
+925	0	3
+934	18	18
+1971	0	5
+3592	1	1
+76	1	1
+200	0	6
+682	1	0
+632	2	0
+2338	1	0
+110	1	1
+231	10	0
+1682	42	54
+616	1	2
+171	2	1
+543	1	1
+45	0	12
+2837	1	0
+441	2	0
+4958	5	5
+455	37	37
+330	22	22
+711	46	46
+184	49	49
+153	61	62
+392	11	11
+1266	8	7
+241	42	41
+198	31	31
+1064	78	78
+528	0	4
+431	1	0
+108	64	53
+358	5	5
+566	35	33
+168	1	0
+251	41	41
+880	33	33
+248	7	9
+583	3	4
+217	41	41
+117	13	14
+203	78	78
+133	44	45
+59	43	43
+129	19	19
+887	1	0
+264	30	30
+352	16	16
+719	36	35
+196	49	49
+425	4	0
+358	15	15
+151	22	22
+714	0	3
+165	41	0
+199	134	134
+504	47	47
+526	12	16
+206	39	39
+372	6	6
+224	25	25
+304	7	7
+186	90	90
+1872	0	3
+1066	7	7
+180	85	75
+63	37	37
+157	65	65
+331	3	0
+302	3	6
+213	42	45
+350	45	49
+580	42	45
+252	43	43
+337	4	0
+667	10	7
+94	9	9
+441	18	18
+124	0	1
+277	42	42
+1729	37	37
+1562	3	1
+546	15	13
+409	22	22
+312	45	45
+46	0	2
+268	14	14
+1166	35	38
+460	0	2
+74	0	1
+323	27	26
+2747	24	28
+322	10	0
+592	23	21
+161	45	45
+207	50	50
+409	22	23
+188	50	49
+396	152	151
+343	26	28
+3430	49	49
+2161	72	72
+1696	5	0
+389	50	50
+340	23	23
+169	0	3
+70	0	4
+392	0	1
+106	32	32
+2476	23	23
+1397	53	54
+2187	18	18
+489	9	9
+2018	4	0
+108	17	14
+836	5	5
+417	48	48
+358	34	34
+481	55	56
+277	48	48
+180	25	21
+356	3	0
+66	66	66
+407	28	27
+603	36	36
+1239	0	3
+194	8	8
+444	0	1
+204	35	35
+162	15	15
+418	6	5
+236	9	9
+55	52	52
+105	145	146
+57	143	143
+52
+
+chain 868538 chr15 102531392 + 21886534 21896633 chr15 100338915 + 19140000 19150000 4870
+1208	1	0
+245	165	68
+494	89	89
+824	15	15
+196	0	1
+197	50	50
+274	0	1
+1127	15	15
+230	4	0
+76	48	49
+671	0	1
+352	24	19
+117	11	11
+288	5	4
+122	0	3
+135	37	37
+265	0	2
+62	2	0
+656	0	2
+792	69	69
+142	73	73
+307	2	0
+331	0	2
+378
+
+chain 566185 chr15 102531392 + 83551634 83557670 chr8 146274826 + 129534406 129540446 9431
+549	1	1
+105	1	1
+1154	0	4
+273	6	6
+3947
+
+chain 334937 chr15 102531392 + 21896662 21900709 chr15 100338915 + 19150028 19154088 190582
+86	46	44
+567	11	9
+733	23	25
+212	2	0
+100	40	40
+155	1	0
+189	34	34
+165	42	42
+219	56	68
+259	61	62
+380	3	8
+242	13	13
+408
+
+chain 246244 chr15 102531392 + 22183221 22212114 chr15 100338915 + 19767012 19795905 936
+45	207	207
+50	619	619
+50	396	396
+152	343	343
+26	3430	3430
+49	2161	2161
+72	2090	2090
+50	1100	1100
+32	3896	3896
+53	6108	6108
+48	358	358
+34	481	481
+55	277	277
+48	180	180
+25	425	425
+66	407	407
+28	603	603
+36	2089	2089
+35	901	901
+52	105	105
+145	57	57
+143	52	52
+1314
+
+chain 136774 chr15 102531392 + 21885000 21886534 chr15 100338915 + 19138465 19140000 942717
+402	49	49
+445	0	1
+638
+
+chain 38827 chr15 102531392 + 28705151 28710237 chr15 100338915 - 73838719 73843805 82
+5086
+
+chain 19525 chr15 102531392 + 27138463 27148846 chr15_random 784346 + 739466 749849 392
+10383
+
+chain 9597 chr15 102531392 + 29116154 29116267 chr19 63811651 - 22308947 22309060 23761910
+59	4	4
+50
+
+chain 6273 chr15 102531392 + 23685556 23685849 chr15 100338915 + 21236652 21236834 12713809
+67	205	94
+21
+
+chain 4893 chr15 102531392 + 29111049 29111100 chr21 46944323 + 41885809 41885860 33898070
+51
+
+chain 3039 chr15 102531392 + 22178426 22178458 chr8 146274826 + 6100529 6100561 34349851
+32
+
+chain 2975 chr15 102531392 + 22826750 22826789 chr15 100338915 + 20381852 20381891 2718765
+39
+
+chain 2542 chr15 102531392 + 21049663 21065195 chr18 76117153 + 14510749 14526638 994
+38	2128	2130
+28	13310	13665
+28
+
+chain 1826 chr15 102531392 + 20950735 20950759 chr19 63811651 - 51273213 51273237 15159639
+24
+
+chain 1062 chr15 102531392 + 21028626 21028659 chr21 46944323 - 32992576 32992609 1118
+33
+
+chain 912 chr15 102531392 + 22826789 22826824 chr15 100338915 + 20377303 20377338 985154
+35
+
+chain 7474990131 chr16 90354753 + 60000 90294753 chr16 88827254 + 0 88822254 17
+172343	1	0
+111	0	1
+5627	1	2
+8398838	50000	17500
+25336229	150000	100000
+1112651	11100000	9800000
+42003582	50000	20000
+1855370
+
+chain 7369719958 chr17 81195210 + 0 81060651 chr17 78774742 + 0 78654742 18
+252627	1	1
+24	1	1
+41	29	0
+295	0	29
+261	0	58
+116	0	58
+94	0	29
+79	37	8
+485	59	1
+28	1	1
+76	1	233
+26	0	29
+2765	1	0
+17	2	0
+2220	18	18
+343	37	37
+457	1	1
+39	1	1
+564	16	16
+2523	9	39
+1878	56	0
+22	0	29
+1681	1	0
+414	3	0
+282	68	0
+93	10	10
+293	4	0
+3190	0	1
+2562	4	0
+1809	0	3
+84	1	1
+62	1	1
+3775	27	0
+1968	0	16
+912	2	0
+696	4	4
+1428	15	15
+290	0	1
+1779	1	0
+60	1	1
+216	1	0
+375	1	1
+41	1	0
+9221	100000	46522
+3080543	1	0
+1208216	2	0
+1370	0	2
+1279	4	0
+322	5	0
+5660	0	210
+308	22	21
+973	0	8
+2901	0	1
+8479	1	0
+4122	0	7
+3187	0	4
+571	1	0
+167	1	0
+10174	7	7
+856	1	2
+1630	0	1
+4258	1	3
+1688	0	1
+388	304	0
+672	0	1
+8495	10	0
+2272	0	1
+8297	0	1
+1500	4	1
+733	2	37
+57	17	0
+51	532	42
+2085	0	2
+52	1	1
+2913	13	14
+1309	1	0
+3991	0	3
+1939	3	0
+887	2	0
+463	0	18
+64	3	0
+2104	20	0
+557	4	0
+120	1	0
+3670	0	2
+4347	5394	0
+5332	1	0
+2505	10	4
+6776	11	14
+9573	1	0
+1136	2	0
+3754	0	1
+4588	0	1
+637	17	17
+1283	0	8
+371	1	0
+2084	0	1
+492	0	2
+519	4	0
+952	2	0
+1517	0	1
+987	0	9
+1152	10	0
+3608	2	0
+3199	39	0
+734	0	1
+646	0	2
+2211	0	1
+14829	0	1
+3473	34	1
+22	0	11
+2194	1	0
+6443	4	5
+2627353	0	1
+11581974	43	0
+31	89	0
+238782	1	0
+1830653	0	1
+419873	116477	100008
+5586	0	6
+11057	2	0
+3240	0	1
+1237	2	0
+373	1	1
+43	1	1
+558379	3000000	100000
+1823446	1	0
+2728383	1	0
+29	1	0
+138	0	1
+144	8	6
+38	2	0
+7	1	0
+18	1	1
+70935	1	0
+10	2	0
+52	31	28
+189	1	0
+41	2	2
+750363	44	44
+4038953	50039	100039
+1523967	1	1
+47	1	1
+231	0	2
+1175	0	1
+555	1	1
+49	1	1
+566	0	7
+607	0	2
+4954	1	1
+18	7	6
+567	1	0
+421	0	2
+1010	0	8
+777	3	0
+925	5	12
+318	0	1
+230	13	20
+244	1	1
+13	1	0
+42	1	1
+220	1	1
+56	1	1
+101	0	225
+1113	0	1
+17	1	1
+2614	0	4
+7108	2	0
+617	0	14
+5674	2	0
+1852	1	1
+63	1	1
+56	1	1
+25	1	1
+332	6	0
+423	5	5
+61	0	4
+108	1	1
+46	1	1
+160	2	2
+72	1	1
+162	1	1
+20	1	1
+53	1	1
+63	1	1
+112	1	1
+59	1	1
+5885	0	2
+5871	30040	159230
+925	0	5
+214	7	7
+641	17	17
+1296	46	46
+2513	69	71
+76	2	1
+57	0	50226
+1963	18	18
+2694	55	55
+6616	0	1
+5106	18	0
+2521	7	7
+49	0	10
+3440	4	0
+4179	4	0
+2749	1	0
+1125	0	8
+55	1	1
+1840	14	14
+624	0	8
+1742	0	4
+3690	4	0
+2051	1	0
+751	1	0
+2111	11	10
+3110	0	1
+682	0	1
+2795	2	5
+241	1	0
+165	3	1
+1258	1	0
+1601	0	5
+3716	1	0
+1308	1	0
+2058	0	1
+1624	1	0
+478	0	4
+9	0	6
+35	1	3
+47	1	0
+2425	0	1
+1178	4	0
+33	1	1
+415	5	5
+887	3	1
+1605	0	15
+259	0	2
+78	1	0
+4570	1	0
+322	0	1
+1801	0	2
+836	0	3
+1509	1	0
+1732	1	0
+936	6	0
+1371	0	1
+625	12	2
+5009	1	1
+75	1	0
+20	0	1
+139	1	0
+523	3	0
+11	319	0
+1368	0	1
+774	1	1
+16	1	1
+3523	119	124
+497	0	4
+174	0	9
+1317	3	0
+508	1	0
+1126	0	1
+1952	2	0
+565	0	2
+871	1	0
+1460	0	6
+55	1	0
+420	0	6
+57	1	1
+119	1	1
+427	0	1
+459	11	14
+448	1	0
+1275	7	7
+360	0	1
+73	1	1
+48	1	1
+4920	0	3
+713	1	1
+21	0	3
+6	0	3
+6	0	1
+691	1	1
+44	1	1
+1158	38	38
+446	10	9
+566	1	0
+175	4	0
+796	10	0
+810	0	1
+78	17	18
+1531	2	0
+1274	1	1
+39	1	1
+53	1	3
+202	1	0
+707	17	17
+1733	1	0
+1540	42	42
+12471	0	3
+286	1	3
+5600	0	4
+6458	1	0
+4866328	0	102000
+1870126	0	257
+590080	18	6
+26953	0	1
+6737	4	0
+5946	0	1
+2319	4	0
+1641	1	1
+27	1	1
+1237	0	1
+2698	1	1
+140	1	1
+1689	2	0
+836	30	29
+5333	0	1
+509	0	1
+224	9	9
+4983	0	6
+4981	30	30
+6913	3	13
+1039	1	0
+11605	0	1
+22064	1	0
+16612	0	8
+902	0	1
+757	0	1
+84	46	46
+489	1	0
+10979	1	1
+18	1	1
+1517	0	1
+4576	0	1
+12558	0	4
+2726	1	0
+5291	0	2
+8706	1	0
+83	0	1
+406	7	0
+87	0	38
+5531	0	1
+23971	0	1
+7855	22	54
+4095	1	0
+803	5	5
+6382	0	6
+3546	28	0
+4264	2	0
+13194	6	6
+6463	0	1
+26075	1	1
+59	1	1
+10791	7	17
+707	1	0
+210	0	1
+1655	2	0
+5301	0	1
+1930	0	1
+14632	0	2
+1043	0	1
+3607	0	3
+312	1	0
+5953	0	2
+170	17	0
+489	1	0
+5260	28	0
+888	0	10
+2461	10	10
+237	0	2
+1716	1	3
+10694	4	0
+3754	0	1
+6173	1	0
+8017	2	1
+3594	4	0
+5439	1	0
+4137	14	0
+29	15	0
+6418	1	0
+1267	0	1
+723	6	0
+1080	0	2
+3878	1	0
+7682	1	1
+44	1	1
+3135	1	0
+174853	2	1
+2008	7	7
+5657	1	0
+6496	3	0
+89	5	0
+665	1	0
+954	1	1
+44	1	1
+375	8	7
+3317	2	0
+2753	0	1
+1863	3	0
+3228	0	1
+3571	49	45
+6488	2	0
+8451	172	172
+3797	16	0
+2103	1	0
+268	23	26
+7888	0	4
+701	0	4
+2402	6	0
+37	1	1
+2943	3	2
+8420	0	1
+932	324	0
+6726	0	1
+543	3	4
+4028	0	18
+88	4	0
+2999	0	1
+530	0	1
+1153	11	11
+919	2	0
+1174	17	0
+118	16	16
+2727	0	1
+543	1	0
+783	0	1
+1374	4	0
+8619	0	20
+281	44	44
+4364	50	51
+2856	1	0
+5399	1	0
+1506	0	1
+919	6	0
+7228	0	10
+3226	0	1
+435	0	1
+4463	132	0
+9760	1	0
+2034	0	6
+7656	0	1
+198212	132	0
+11700	5	0
+7647	0	1
+9062	0	4
+8778	2	0
+7014	0	1
+1613	2	0
+790	5	7
+7433	0	1
+6482	12	12
+6798	1	0
+1422	0	1
+3454	1	1
+43	1	1
+3097	2	0
+334	18	0
+1444	0	1
+2400	0	3
+3272	1	0
+9106	0	1
+1573	1	0
+4742	0	1
+3366	0	1
+5484	1	0
+2445	5	0
+5447	8	8
+2539	1	0
+1471	1	0
+238	1	1
+16	1	1
+288	5	5
+2995	2	0
+951	1	1
+35	1	1
+279	15	16
+3534	0	6
+3513	1	0
+163	1	0
+6173	1	0
+1074	0	1
+2818	0	1
+2868	1	0
+3796	0	1
+1118	167	1
+1278267	25	25
+10747175	217	0
+3504874	1053	0
+10844	11	13
+18805	0	1
+1960834	50000	126729
+3065	0	1
+3601036	8833	90008
+34292	0	1
+376	14	14
+1447	44	0
+3080	1	1
+43	1	1
+789	0	1
+11432680	50000	153000
+1902016	4098	0
+102	21	0
+3179	6	6
+877	1	1
+49	1	1
+296	1	0
+1375	1	1
+21	1	1
+607	5	5
+98	22	0
+6811	1	1
+17	11	0
+3804	0	1
+1356	1	1
+29	1	1
+297	0	1
+9543	2	0
+3131	4	0
+860	1	0
+27346	0	1
+7553	0	2
+2834	2	0
+394	0	4
+6322	44	44
+158	0	1
+405	8	11
+1128	0	7
+271	1	1
+21	28	0
+504	0	6
+1214	31	44
+384	3	0
+521	18	18
+392	0	11
+802	1	1
+25	2	3
+51	49	1
+49	1	1
+558	1	0
+351	0	1
+2779	13	13
+114398	82124	65008
+7795	1	0
+18	1	1
+4140	0	1
+28048	1	1
+32	1	1
+4630	0	1
+4573	0	3
+357	0	2
+4812	0	1
+14372	3	0
+203	1	0
+26257	0	1
+2734	2	0
+19262	5	5
+5022	1	0
+25471	1	0
+1114538	53	0
+82	0	126
+1416	16	16
+610	0	57
+482	0	1
+148	1	1
+24	1	1
+2322	1	1
+23	0	1
+719	16	0
+20	0	16
+105	9	9
+1277	1	0
+2498	1	0
+352	0	49
+50	50	0
+21	49	0
+28	49	0
+60	47	0
+17	97	0
+901	47	0
+272	14	1104
+279	1	0
+37	12	11
+65	32	0
+18	94	0
+60
+
+chain 3227650 chr17 81195210 + 81075742 81110122 chr17_random 2617613 + 864624 914847 755
+922	0	1
+430	0	1
+763	0	1
+19745	32	32
+637	36	15873
+186	0	1
+2389	0	1
+616	0	1
+1932	12	12
+6680
+
+chain 2732964 chr17 81195210 + 36295616 36336227 chr17 78774742 - 45363365 45403960 362
+666	1	1
+114	1	1
+1777	1	1
+22	1	1
+2481	3	0
+947	3	1
+994	1	1
+26	1	1
+5327	2	0
+95	13	13
+2424	0	1
+339	2	1
+288	1	0
+1180	8	8
+1145	2	4
+1144	1	0
+322	1	0
+28	1	0
+35	1	0
+1499	0	1
+1258	7	6
+1123	0	1
+269	5	4
+1850	18	19
+188	3	0
+403	1	1
+18	1	1
+3148	1	1
+160	1	1
+105	11	0
+573	10538	10545
+33
+
+chain 1501094 chr17 81195210 + 81048174 81075742 chr17_random 2617613 + 1430075 1457643 965
+53	10174	10174
+50	21	21
+49	28	28
+49	60	60
+47	17	17
+97	901	901
+47	680	680
+32	18	18
+94	60	60
+15091
+
+chain 1197294 chr17 81195210 + 21670280 21683085 chr17_random 2617613 - 711226 724030 995
+6335	1	0
+1486	0	2
+2024	2	0
+2957
+
+chain 653269 chr17 81195210 + 66064861 66073694 chr17_random 2617613 - 926391 957193 299
+3246	4346	26315
+1241
+
+chain 307142 chr17 81195210 + 79761820 81150656 chr17_random 2617613 + 2320255 2536424 170
+87	6	8
+1077	0	1
+77	0	1
+1009	0	1
+98	0	1
+35	0	1
+131	0	1
+288	0	1
+33	1	0
+225	0	1
+279	0	1
+110	0	1
+55	0	1
+107	0	1
+202	12	15
+111	0	1
+36	0	2
+25	0	1
+202	0	1
+95	0	1
+145	1	1
+21	0	1
+222	0	1
+41	0	1
+492	4	0
+594	0	1
+179	0	1
+412	0	1
+37	0	1
+13	0	1
+34	0	1
+76	37	38
+204	27	27
+204	1	3
+8	0	5
+23	0	1
+430	0	1
+145	0	1
+271	0	1
+222	0	1
+51	0	1
+17	0	1
+23	2	4
+385	0	1
+337	0	1
+374	0	1
+140	17	22
+297	0	1
+72	5	8
+193	0	1
+8	0	1
+28	0	1
+17	0	1
+17	0	1
+445	0	1
+169	0	1
+35	37	3
+425	0	1
+41	0	1
+37	0	1
+79	0	1
+100	0	1
+127	0	1
+422	0	1
+17	1	1
+284	1	3
+56	10	12
+650	0	1
+163	0	2
+6	0	1
+36	1	1
+519	0	1
+39	0	1
+78	0	1
+216	3	5
+66	0	1
+58	0	1
+68	0	1
+292	4	0
+46	2	0
+108	2	0
+23	114	0
+830	0	1
+136	43	43
+23	32	10
+63	64	65
+380	0	1
+22	1	1
+440	0	1
+66	1	1
+17	0	1
+171	3	5
+27	1	1
+130	10	13
+128	0	1
+418	0	1
+4	1	2
+37	0	1
+29	0	1
+27	0	1
+748	0	1
+251	0	1
+219	0	1
+111	0	1
+48	0	1
+325	0	1
+296	0	1
+383	0	1
+62	0	1
+244	0	2
+248	9	11
+180	0	1
+241	0	1
+40	1	3
+6	0	1
+19	0	1
+27	0	1
+166	0	1
+78	0	1
+165	0	1
+33	0	1
+9	0	1
+172	0	1
+261	0	1
+200	16	21
+121	0	1
+37	2	4
+74	0	1
+97	3	5
+11	0	1
+51	0	1
+642	0	1
+317	11	14
+138	1324229	151143
+4948	1	0
+1850	67	60
+3859	1	0
+456	5	4
+1605	21	21
+1281	13	7
+5085	0	456
+1548	1	1
+37	1	1
+2825	1	1
+64	1	1
+1075	1	0
+721	1	0
+5566	5	22
+1136	0	1
+2390	3	0
+1347	2	0
+4617
+
+chain 266741 chr17 81195210 + 81150656 81195210 chr17_random 2617613 - 1100691 1809734 427
+1871	0	662945
+298	0	1
+6514	2	2
+45	0	1
+6237	3	5
+1230	32	32
+347	0	1
+1941	14	14
+149	0	1
+25553	59	1621
+16	63	39
+180
+
+chain 215840 chr17 81195210 + 66068832 66109867 chr17_random 2617613 + 1644335 1685356 1023
+3394	37597	37583
+44
+
+chain 30167 chr17 81195210 + 44458173 44458487 chr2 242951149 - 34181426 34181740 4632506
+314
+
+chain 29586 chr17 81195210 + 36420504 36420817 chr7 158821424 - 10371995 10372309 4828537
+136	0	1
+177
+
+chain 20882 chr17 81195210 + 56914122 56914339 chrX 154913754 + 31643322 31643539 5151267
+217
+
+chain 16484 chr17 81195210 + 44491151 44521781 chr17 78774742 + 42064051 42094670 662
+44	30454	30443
+132
+
+chain 14999 chr17 81195210 + 44428451 44428612 chr17 78774742 + 42001706 42001867 887
+161
+
+chain 12695 chr17 81195210 + 44739444 44739576 chr17 78774742 + 41877181 41877313 13974721
+132
+
+chain 12494 chr17 81195210 + 19077136 19077299 chr17 78774742 - 59726399 59726562 431
+43	31	31
+89
+
+chain 7858 chr17 81195210 + 253568 254148 chr17 78774742 + 253365 253974 1160836
+37	486	515
+57
+
+chain 5202 chr17 81195210 + 79704633 79704687 chrY 57772954 - 54321400 54321454 32857515
+54
+
+chain 5149 chr17 81195210 + 36426505 36456524 chr17 78774742 - 35824084 35853324 896
+73	1	1
+45	29858	29079
+42
+
+chain 3754 chr17 81195210 + 60419213 60419252 chr8 146274826 - 11845696 11845735 33181261
+39
+
+chain 3753 chr17 81195210 + 44413461 44413510 chr17 78774742 - 18492830 18492879 715
+49
+
+chain 3637 chr17 81195210 + 79776689 79776727 chr17_random 2617613 + 2335092 2335130 5614693
+38
+
+chain 3637 chr17 81195210 + 79776651 79776689 chr17_random 2617613 + 2335092 2335130 5614694
+38
+
+chain 3636 chr17 81195210 + 79776613 79776651 chr17_random 2617613 + 2335130 2335168 7454076
+38
+
+chain 2637 chr17 81195210 + 252694 252723 chr17 78774742 + 252810 252839 1426666
+29
+
+chain 2581 chr17 81195210 + 81166856 81166888 chr1 247249719 + 441705 441737 997
+32
+
+chain 2427 chr17 81195210 + 79772596 79772621 chr17_random 2617613 + 2331168 2331193 24392944
+25
+
+chain 1872 chr17 81195210 + 79585571 79585619 chr11 134452384 + 72960908 72960956 2849402
+48
+
+chain 790 chr17 81195210 + 36328756 36331384 chr17_random 2617613 - 1242589 1245215 133
+46	2513	2511
+69
+
+chain 170 chr17 81195210 + 34725848 34725887 chr17_random 2617613 + 1051433 1051472 428
+39
+
+chain 94559897 chr17_ctg5_hap1 1680828 + 188271 1499222 chr17 78774742 - 36776984 37845687 55
+188	30	30
+348	14	15
+235	24	24
+194	3	0
+334	40	40
+270	54	54
+61	87	84
+948	4	3
+1658	2	0
+1730	0	2
+285	0	1
+2885	1	1
+38	1	1
+2933	0	1
+1942	10	0
+375	0	1
+5094	0	1
+814	1	1
+18	1	1
+4676	8	0
+578	10	7
+467	0	1
+892	1	0
+479	48	48
+132	0	6
+61	13	15
+66	38	38
+1901	35	35
+862	7	0
+3895	1	0
+740	44	44
+313	7	6
+4916	4	4
+507	0	1
+2214	1	1
+25	0	3
+106	2	0
+40	1	1
+146	1	1
+30	1	1
+63	0	1
+192	5	5
+3242	0	2
+385	33	33
+972	12	0
+93	1	1
+3332	2	2
+71	1	1
+57	1	1
+149	0	2
+91	1	1
+219	14	14
+606	1	1
+53	1	1
+1068	0	12
+3191	29	29
+7028	1	0
+478	1	0
+2064	0	1
+408	17	21
+675	1	1
+17	1	0
+4	1	1
+3445	0	1
+158	0	2
+312	0	14
+1801	0	1
+1424	4	0
+1894	2	0
+364	6	6
+54	2	0
+47	1	1
+1105	10	1
+3088	0	1
+1176	6	0
+4141	1	1
+24	0	1
+169	71	71
+1596	1	1
+37	1	1
+2758	5	0
+2986	1	1
+20	1	1
+206	4	0
+11154	0	17
+583	0	8
+1703	0	10
+1675	1	0
+392	1	0
+6851	37	37
+2872	132	0
+446	9	0
+3437	5	5
+995	0	2
+898	1	1
+18	1	1
+128	0	1
+2151	2	0
+6413	1	1
+48	1	1
+786	0	1
+939	0	1
+258	0	4
+1247	2	0
+4742	0	1
+3520	54	51
+1220	1	1
+30	1	1
+638	1	0
+2474	1	1
+42	1	1
+266	0	16
+106	1	1
+19	1	1
+3806	328	0
+1161	1	0
+4896	0	1
+779	0	2
+543	1	0
+4979	11	11
+1670	1	0
+889	3	0
+2126	2	0
+87	0	18
+193	1	0
+3840	12	0
+3234	4	0
+2802	0	1
+873	1	0
+1288	1	5
+2202	1	1
+21	1	0
+1366	0	1
+4830	4	0
+48	1	1
+2894	1	1
+7	14	0
+43	0	4
+1003	1	1
+28	1	1
+102	3	0
+370	50	50
+830	1	3
+674	3	7
+2759	2	0
+4559	14	12
+862	1	0
+245	49	49
+1367	0	3
+428	13	41
+77	0	9
+701	1	0
+528	1	1
+31	1	1
+1397	0	2
+832	1	1
+34	2	0
+404	1	0
+142	1	1
+30	1	1
+272	2	0
+783	0	2
+4039	1	0
+449	8	0
+2647	1	0
+1730	7	1
+38	80	0
+160	5	0
+492	0	12
+1920	1	1
+117	1	1
+350	1	1
+38	1	1
+279	1	1
+40	1	1
+1367	4	0
+427	35	35
+141	46	46
+399	1	0
+1786	35	35
+697	0	1
+1104	20	20
+290	28	28
+1774	0	5
+1339	5	0
+527	1	0
+312	62	62
+199	1	1
+239	42	42
+629	1	1
+41	1	1
+298	3	3
+26	1	1
+642	1	1
+52	1	1
+206	8	0
+1930	0	1
+806	19	12
+578	10	7
+375	1	1
+44	1	1
+939	2	0
+679	10	0
+56	0	2
+73	13	13
+556	1	1
+18	1	1
+1386	1	1
+35	281	0
+106	1	1
+435	13	0
+686	2	0
+1401	0	8
+1799	1	0
+1566	0	3
+692	21	21
+1368	5	5
+150	28	28
+53	6	11
+54	50	50
+129	4	4
+550	15	0
+160	13	13
+1640	1	0
+170	31	31
+1087	124	123
+249	12	12
+407	1	1
+18	1	1
+637	13	13
+450	1	1
+30	1	1
+100	1	1
+37	1	1
+407	0	2
+2327	8	1
+107	1	1
+37	1	1
+885	1	1
+20	1	1
+134	18	18
+168	1	0
+161	6	6
+497	1	1
+16	1	1
+2755	29	29
+102	242	244
+58	8	8
+153	14	14
+711	41	41
+76	35	35
+287	93	93
+472	14	21
+608	7	8
+171	34873	0
+117	7	7
+68	10	0
+31	1	1
+95	11	11
+267	1	1
+19	1	1
+494	1	1
+26	1	1
+135	1	0
+302	1	1
+26	1	1
+349	0	1
+37	1	1
+254	1	1
+24	1	1
+550	1	0
+170	1	1
+38	1	1
+100	1	1
+31	0	1
+305	6	8
+370	0	3
+162	7	0
+39	4	4
+112	6	6
+318	1	1
+49	1	1
+135	1	1
+34	1	1
+129	1	1
+49	1	1
+620	0	1
+98	1	1
+43	1	1
+252	1	1
+37	1	1
+824	5	5
+131	9	10
+247	1	1
+20	1	1
+303	1	0
+668	1	1
+45	1	1
+316	14	14
+657	1	1
+93	1	1
+290	0	3
+148	1	1
+29	5	5
+74	1	1
+40	1	1
+1516	1	1
+57	1	1
+132	3	0
+178	1	1
+131	1	1
+127	1	1
+103	0	1
+61	1	1
+460	5	7
+90	1	1
+22	1	1
+87	1	1
+44	1	1
+85	1	3
+767	0	7
+60	1	1
+79	1	1
+31	1	1
+258	1	1
+26	0	1
+11	2	2
+140	1	1
+31	1	1
+110	1	0
+12	9	0
+776	8	8
+50	1	0
+445	1	1
+34	1	1
+278	15	15
+125	1	0
+635	18	19
+183	0	1
+75	10	10
+200	19	21
+832	14	14
+2247	6	0
+318	0	2
+180	10	0
+167	1	1
+43	1	1
+60	1	1
+43	1	1
+268	0	11
+1220	1	1
+46	5	5
+1001	16	16
+218	7	7
+142	17	0
+74	1	1
+130	1	1
+30	2	0
+588	1	1
+83	2	2
+58	25	25
+65	50	50
+873	23	23
+277	21	20
+237	3	0
+66	0	51
+145	0	1
+133	1	1
+23	1	1
+1087	3	2
+295	4	5
+57	10	8
+347	1	1
+18	1	1
+350	3	5
+259	0	1
+771	3	4
+85	1	1
+62	8	8
+224	1	1
+40	1	1
+50	0	3
+137	1	1
+199	3	3
+21	1	1
+272	0	10
+66	12	0
+27	1	1
+138	6	5
+762	1	1
+20	1	1
+324	9	9
+71	0	4
+174	5	12
+237	6	6
+57	1	6
+21	1	1
+156	0	2
+89	1	1
+140	1	1
+69	11	0
+407	0	2
+20	1	1
+131	0	2
+162	1	1
+29	1	1
+65	7	7
+1199	1	1
+68	1	1
+75	12	12
+78	3	3
+37	1	1
+499	1	1
+44	1	0
+397	1	1
+116	1	1
+147	1	0
+286	4	0
+122	31	0
+436	1	1
+27	1	1
+137	11	0
+448	40	0
+174	5	5
+148	1	0
+42	40	0
+506	850	23
+509	1	1
+61	1	1
+113	1	1
+83	1	0
+90	1	1
+229	0	1
+366	0	6
+625	0	1
+160	1	1
+43	1	1
+174	1	1
+53	1	1
+129	10	10
+205	1	1
+18	1	1
+386	1	1
+36	1	1
+775	1	1
+49	0	2
+118	10	10
+238	4	0
+801	0	5
+164	73	73
+1003	22	15
+181	1	1
+62	1	1
+1006	1	1
+25	1	1
+361	1	1
+76	21	0
+386	9	0
+224	25	34
+1276	0	4
+157	4	4
+450	1	1
+15	1	0
+36	1	1
+402	15	0
+1572	8	9
+272	3	0
+319	9	9
+673	0	724
+177	23	26
+230	2	0
+107	1	1
+80	99	99
+319	1	0
+711	0	1
+18	1	1
+674	3	0
+826	0	2
+503	1	1
+25	32	0
+42	1	1
+67	1	0
+395	19	14
+328	1	1
+69	1	1
+520	1	1
+31	1	1
+1063	1	1
+67	2	2
+55	4	0
+477	4	0
+69	0	1
+807	4	3
+26	1	1
+400	2	0
+707	5	0
+41	1	1
+200	1	1
+33	1	1
+744	1	1
+25	1	1
+224	2	0
+121	9	4
+44	1	1
+266	78	94
+522	0	1
+81	1	1
+3286	0	1
+341	1	1
+17	2	1
+445	1	1
+23	1	1
+1029	2	0
+169	1	1
+30	1	1
+577	1	0
+754	2	2
+43	1	1
+170	20	14
+365	1	1
+88	0	1
+1312	0	1
+354	1	4
+526	4	2
+1931	3	0
+650	17	17
+454	1	1
+59	2	3
+167	3	0
+1448	13	13
+69	1	1
+48	1	1
+398	1	1
+89	5	0
+33	1	1
+422	1	1
+39	0	1
+250	86	15
+1631	0	1
+20	1	1
+69	1	1
+38	1	1
+104	0	2
+30	1	1
+420	1	1
+70	1	0
+497	1	0
+68	0	14
+1402	1	1
+28	1	1
+385	4	0
+42	1	1
+245	1	1
+31	2	1
+1110	1	1
+44	1	1
+1784	1	1
+42	1	1
+194	0	1
+181	0	4
+278	14	13
+800	1	0
+160	0	2
+259	1	1
+48	1	1
+336	5	0
+49	12	0
+814	1	1
+39	1	1
+144	4	0
+618	0	4
+159	0	3
+30	1	1
+443	2	0
+140	1	1
+49	1	1
+510	1	1
+22	1	1
+1186	1	1
+45	1	1
+2488	9	0
+226	12	8
+769	1	1
+36	3	0
+1785	1	1
+40	1	1
+570	5	0
+122	7	7
+181	11	11
+539	0	8
+1090	7	7
+128	0	1
+918	0	1
+314	43	43
+173	26	25
+374	0	1
+267	43	49
+69	16	15
+531	16	16
+179	0	6
+604	2	0
+646	28	35
+276	0	1
+1116	21	21
+257	1	0
+165	56	57
+85	41	41
+939	52	52
+134	6	6
+966	5	0
+1657	1	0
+142	22	23
+301	14	0
+280	35	35
+304	3	0
+1345	4	0
+219	1	1
+93	1	1
+646	1	1
+70	1	1
+115	1	1
+25	0	2
+6	1	1
+876	0	1
+750	1	0
+1106	1	1
+44	1	1
+1136	0	1
+2705	1	1
+29	1	1
+474	1	0
+24	1	1
+517	18	17
+283	45	35
+190	6	3
+714	102	102
+1046	0	2
+2521	29	29
+123	1	0
+171	0	8
+504	5	6
+2380	0	1
+1479	53	42
+159	5	5
+248	1	1
+34	1	1
+643	2	0
+586	0	4
+1216	1	1
+30	1	1
+1308	1	1
+25	1	1
+244	0	4
+1092	11	11
+297	0	4
+776	22	22
+62	1	0
+222	0	1
+38	1	1
+808	0	7
+45	1	1
+42	2	0
+313	5	0
+1028	2	3
+366	0	2
+298	41	355
+1457	37	37
+356	49	49
+849	140	128
+155	0	4
+92	6	6
+2333	1	0
+546	1	0
+612	68	68
+259	1	0
+304	3	0
+1246	1	0
+351	22	21
+1110	14	14
+364	0	3
+349	1	1
+39	1	1
+76	0	8
+152	9	0
+283	1	0
+117	1	2
+304	1	0
+1958	19	0
+278	1	1
+109	1	1
+1942	1	1
+31	2	0
+13	1	1
+312	18	0
+151	7	0
+62	1	1
+694	1	1
+18	1	1
+163	1	1
+17	1	0
+1103	2	0
+218	1	0
+21	1	1
+372	11	11
+434	3	4
+440	4	0
+45	1	0
+402	1	1
+46	1	1
+757	1	1
+43	1	1
+96	27	81
+499	1	1
+21	1	1
+184	14	14
+307	15	16
+1265	1	1
+62	1	1
+1051	1	0
+1157	1	1
+28	2	0
+349	3	0
+606	1	1
+22	1	1
+107	0	1
+36	1	1
+499	1	1
+27	1	1
+505	0	1
+1698	6	0
+38	1	1
+924	1	1
+33	1	1
+108	0	2
+196	1	1
+25	1	0
+24	1	1
+824	6	0
+725	0	1
+917	17	0
+185	1	1
+51	4	4
+93	0	1
+351	1	1
+34	1	1
+608	10	10
+82	2	0
+27	1	1
+2343	1	1
+48	1	1
+188	9	9
+623	4	3
+603	0	6
+11	1	1
+379	1	1
+52	1	1
+157	37	20
+879	51	58
+229	14	2
+83	1	1
+70	1	0
+1849	1	1
+42	1	1
+961	1	1
+22	1	1
+219	1	1
+25	1	1
+551	0	3
+26	1	7
+250	1	1
+44	1	1
+1028	9	2
+471	1	1
+31	0	1
+574	0	323
+192	1	1
+44	1	1
+1934	168	168
+186	1	0
+197	25	0
+161	1	0
+15	6	0
+806	1	1
+18	1	1
+184	1	0
+86	1	1
+16	1	1
+183	0	1
+641	12	12
+687	0	2
+735	2	0
+45	0	6
+308	11	11
+153	1	1
+23	1	1
+143	1	1
+59	1	1
+178	28	0
+899	0	3
+1351	2	0
+168	3	0
+407	1	0
+290	2	1
+227	1	1
+48	1	1
+704	1	1
+48	1	1
+866	93	93
+536	1	5
+1481	8	11
+180	16	16
+88	6	0
+249	0	44
+37	1	1
+294	1	1
+32	0	20
+1368	1	1
+93	1	1
+1638	11	11
+303	0	1
+55	1	1
+24	1	1
+1188	1	0
+227	2	2
+45	3	0
+205	0	4
+34	0	1
+159	1	1
+24	1	1
+398	0	1
+1259	16	16
+64	2336	0
+59	1	1
+44	0	3
+25	1	1
+209	1	1
+18	1	1
+348	1	1
+30	1	1
+413	27	0
+53	1	1
+23	2	0
+25	0	4
+532	0	12
+184	1	0
+278	1	1
+29	1	1
+1186	1	1
+15	1	1
+300	12	12
+570	1	1
+43	1	1
+183	5	6
+134	1	0
+508	1	1
+30	1	1
+1074	1	1
+24	1	1
+162	8	8
+1046	1	1
+20	1	1
+817	0	3
+1128	1	1
+41	1	1
+166	27	27
+667	15	15
+967	2	0
+10	2	0
+261	1	0
+792	1	8
+153	0	3
+1788	13	22
+1089	1	0
+994	2	0
+368	0	18
+207	1	1
+39	1	1
+332	0	3
+298	5	3
+68	1	1
+44	1	1
+958	1	1
+41	1	1
+1009	0	24
+12	1	0
+118	0	1
+171	16	16
+229	8	8
+233	21	21
+71	1	1
+38	1	1
+185	1	0
+544	1	1
+64	2	0
+614	1	1
+62	1	1
+536	1	1
+143	1	1
+679	0	5
+169	0	3
+597	1	0
+654	1	0
+1270	0	11
+174	0	2
+606	1	1
+59	2	0
+153	3	4
+1186	10	11
+92	1	4
+956	4	0
+302	0	9
+199	1	1
+31	1	1
+878	31	0
+452	10	10
+988	20	15
+1054	0	1
+131	0	4
+652	2	0
+37	1	1
+142	1	1
+36	0	5
+29	0	8
+4136	1	1
+32	1	1
+701	11	11
+258	0	1
+133	7	7
+170	1	0
+372	0	1
+26	4	3
+31	1	1
+131	1	0
+29	1	0
+2657	10	10
+2046	7	0
+870	1	0
+101	16	18
+163	0	1
+526	4	3
+281	0	3
+1907	0	1
+30	0	3
+164	0	3
+132	0	1
+352	1	0
+455	1	0
+726	0	2
+107	1	1
+33	1	1
+156	2	0
+576	1	1
+16	1	0
+76	1	0
+862	11	11
+1049	1	0
+47	1	1
+69	0	3
+607	1	1
+46	1	1
+1700	0	1
+825	13	13
+813	0	1
+213	1	0
+46	1	1
+630	1	0
+683	51	52
+118	1	1
+28	1	1
+1162	1	1
+66	0	3
+472	14	0
+16	1	1
+134	1	1
+119	1	1
+1129	5	5
+149	1	1
+57	1	1
+918	1	1
+36	1	1
+752	12	12
+1962	0	238
+2372	0	15
+175	7	7
+833	1	1
+25	1	1
+315	1	1
+16	1	0
+436	15	15
+67	15	15
+1207	6	5
+732	6	0
+79	1	1
+53	1	1
+1521	5	6
+140	1	0
+3576	12	12
+479	1	1
+37	1	1
+1518	1	1
+77	1	1
+102	1	1
+26	1	1
+812	1	1
+23	1	1
+1740	0	1
+1077	1	1
+17	1	1
+885	6	6
+441	17	17
+284	1	1
+37	1	1
+107	1	1
+17	1	1
+335	1	1
+50	1	1
+120	8	7
+588	0	8
+1512	38	1
+550	45	45
+376	1	1
+63	1	1
+2111	0	1
+574	14	14
+1622	3	1
+683	23	26
+673	1	1
+45	12	0
+98	3	4
+93	20	0
+2130	10	10
+941	1	1
+24	1	1
+1362	2	0
+1696	1	1
+22	2	2
+737	1	1
+26	1	1
+922	1	1
+32	1	1
+923	7	8
+432	0	1
+152	1	1
+26	1	1
+841	0	4
+441	0	103
+1348	10	11
+589	1	1
+44	1	1
+775	8	8
+1051	0	2
+152	13	13
+572	6	6
+543	1	1
+45	1	1
+663	7	7
+802	1	0
+888	1	1
+44	1	1
+210	1	0
+111	1	1
+34	1	1
+459	0	1
+323	1	0
+1116	1	0
+27	1	1
+142	1	1
+21	1	1
+784	1	1
+37	0	4
+40	1	1
+813	1	3
+371	1	1
+25	1	1
+257	1	1
+88	1	1
+276	47	47
+192	5	9
+445	1	1
+19	1	1
+66	8	8
+205	1	1
+79	11	0
+106	1	1
+122	1	1
+2478	0	6
+89	1	1
+47	1	0
+68	1	1
+680	0	4
+1040	0	1
+424	1	1
+33	1	1
+170	0	1
+456	1	1
+66	1	1
+820	18	18
+146	11	11
+642	2	0
+28	1	1
+242	1	0
+50	0	3
+7	1	1
+301	13	13
+126	1	1
+40	1	1
+98	0	2
+202	11	11
+564	23	0
+145	10	7
+1202	1	1
+103	1	1
+459	1	1
+24	1	1
+298	1	1
+44	1	1
+1384	1	1
+31	1	1
+569	1	1
+68	1	1
+535	5	45
+575	1	1
+30	1	1
+1885	1	0
+426	3	0
+19	1	1
+136	1	0
+556	1	1
+17	1	1
+463	6	8
+803	35	35
+170	1	0
+28	1	1
+454	9	9
+450	1	1
+34	1	1
+728	12	13
+1023	0	3
+204	1	1
+33	1	1
+322	1	1
+35	5	0
+147	1	1
+6	1	0
+107	1	1
+442	1	1
+44	1	1
+407	1	0
+1683	1	5
+53	1	1
+1265	1	0
+209	1	1
+28	1	1
+92	1	1
+44	1	1
+671	1	1
+42	0	2
+39	1	1
+74	1	1
+67	1	1
+854	0	30
+676	2	0
+33	0	1
+145	1	1
+48	1	1
+261	3	0
+166	1	1
+24	0	1
+311	1	1
+76	1	1
+893	1	1
+39	1	1
+65	1	0
+1321	1	1
+31	1	1
+316	0	14
+78	9	9
+2264	1	1
+20	1	1
+777	1	2
+274	0	1
+1285	0	11
+500	1	1
+24	1	1
+107	0	3
+77	1	1
+76	1	1
+1414	5	5
+54	37	0
+421	8	8
+150	1	1
+71	1	1
+128	0	1
+514	75	0
+116	1	0
+201	1	1
+17	0	1
+1181	1	1
+30	1	1
+131	12	12
+386	0	1
+351	3	3
+6	4	0
+14	0	1
+48	1	1
+1034	0	4
+789	2	0
+76	1	1
+29	1	1
+691	1	1
+65	1	1
+1723	4	4
+22	1	1
+2576	1	3
+235	1	1
+35	1	1
+52	70	144
+15	1	3
+5	1	0
+51	1	3
+6	3	0
+6	1	0
+4	1	0
+8	0	2
+15	1	0
+8	2	1
+20	1	0
+7	130	13
+22	2	0
+22	2	0
+17	43	281
+23	6	0
+1593	1	1
+35	1	1
+171	0	1
+670	1	1
+20	1	1
+283	1	1
+24	1	1
+448	1	1
+18	1	1
+78	11	0
+46	1	1
+652	1	1
+30	1	1
+333	1	1
+56	1	1
+1209	22	44
+88	1	1
+21	1	1
+908	7	10
+114	26	26
+791	6	6
+286	1	1
+40	1	1
+623	4	0
+430	0	1
+423	8	8
+115	1	1
+23	1	1
+215	11	0
+27	0	5
+797	4	0
+95	15	15
+148	1	1
+141	2	0
+60	1	1
+692	1	0
+91	1	1
+31	1	1
+116	1	1
+24	1	1
+56	1	1
+99	3	0
+101	8	0
+273	1	1
+47	1	1
+1276	14	13
+169	1	1
+40	3	0
+119	1	1
+45	1	1
+466	1	1
+21	1	1
+572	8	8
+247	0	1
+290	0	1
+573	1	1
+27	1	1
+333	47	47
+2439	23	25
+654	1	1
+46	1	1
+78	8	8
+569	1	1
+57	1	1
+666	0	1
+502	1	1
+20	1	1
+347	9	9
+358	0	2
+13	1	1
+148	2	0
+134	1	1
+809	1	1
+47	1	1
+442	1	1
+43	1	1
+308	1	1
+54	1	1
+48	0	2
+152	5	0
+1137	1	1
+27	0	11
+575	1	0
+189	18	18
+490	25	25
+165	1	1
+26	1	1
+241	0	6
+75	1	1
+162	1	1
+1156	0	7
+248	0	4
+972	8	7
+177	0	1
+50	1	1
+1385	1	1
+30	1	1
+1048	1	1
+44	1	17
+690	6	7
+295	1	1
+36	1	1
+519	1	1
+26	1	1
+352	8	8
+204	1	1
+38	1	1
+580	7	7
+888	54	54
+183	18	18
+2465	16	16
+1454	10	10
+352	1	1
+49	1	1
+176	1	1
+32	11	11
+1717	1	1
+37	1	1
+127	1	1
+44	1	1
+275	1	1
+21	1	1
+349	9	9
+1977	1	1
+78	0	1
+8	0	1
+144	0	1
+335	46	46
+79	0	6
+10	1	1
+137	12	0
+99	1	1
+44	5	13
+31	1	1
+416	0	1
+177	0	6
+19	1	1
+372	2	2
+55	1	1
+256	0	6
+313	1	1
+43	1	1
+79	1	1
+20	1	1
+120	1	1
+38	0	8
+880	1	1
+24	1	1
+921	1	1
+40	1	1
+1358	0	4
+56	1	1
+1282	1	1
+34	1	1
+262	1	1
+43	1	1
+158	1	1
+33	1	1
+637	0	4
+1310	1	1
+26	1	1
+544	32	32
+496	1	1
+48	1	1
+3097	2	0
+145	1	1
+32	1	1
+152	0	3
+1117	1	1
+31	6	6
+416	1	1
+37	1	1
+293	0	14
+66	1	1
+48	1	1
+371	1	1
+41	1	1
+639	1	1
+49	1	1
+2092	10	13
+381	1	1
+39	5	5
+995	15	15
+165	0	12
+536	1	1
+43	1	1
+295	1	1
+35	1	1
+171	9	8
+831	20	20
+1980	12	0
+31	1	1
+389	1	1
+32	1	1
+414	20	0
+97	0	1
+835	6	0
+4305	1	1
+37	1	1
+191	1	1
+16	1	1
+227	1	1
+61	1	1
+257	1	1
+35	1	1
+946	1	1
+29	1	1
+710	1	1
+56	1	1
+534	2	0
+439	1	1
+58	1	1
+69	3	3
+43	1	1
+193	1	1
+15	1	1
+1032	1	4
+884	1	1
+30	1	1
+202	1	1
+43	1	1
+171	0	4
+163	0	1
+128	1	1
+43	1	1
+52	1	1
+20	1	1
+818	1	1
+45	1	1
+54	1	1
+42	1	1
+122	1	1
+28	1	1
+329	1	0
+163	1	1
+17	1	1
+442	1	1
+61	1	0
+695	0	1
+13	1	7
+54	1	1
+553	0	14
+360	5	5
+11641	3	7
+7822	1	0
+4105	0	8
+5193	0	1
+516	1	0
+3576	3	0
+825	1	1
+40	1	1
+738	1	1
+18	1	1
+989	0	5
+579	1	1
+19	1	1
+337	1	1
+42	55	0
+726	1	1
+99	1	2
+32	1	1
+932	1	1
+33	1	1
+234	33	33
+1101	1	1
+23	1	1
+345	0	1
+30	1	1
+111	17	17
+1395	1	0
+243	1	1
+29	4	5
+881	2	0
+465	0	1
+165	1	1
+87	1	1
+565	1	1
+10	1	1
+102	9	10
+176	1	1
+48	1	1
+499	1	1
+43	1	1
+263	0	8
+427	2	0
+75	1	1
+2053	1	1
+63	1	1
+744	32	32
+1706	1	1
+31	1	1
+829	12	0
+258	0	2
+433	1	1
+70	1	1
+137	2	0
+45	1	1
+664	11	11
+844	0	1
+440	1	1
+41	1	1
+760	1	6
+39	15	0
+757	1	1
+23	1	1
+137	1	1
+32	1	1
+246	9	9
+549	3	0
+1242	6	1
+200	1	0
+2306	1	1
+29	1	1
+197	2	0
+24	1	1
+1224	0	124
+61	1	1
+64	1	1
+3131	1	1
+116	1	1
+146	1	1
+34	1	1
+51	0	1
+805	1	1
+45	1	1
+579	15	15
+134	9	9
+1033	1	5
+147	1	1
+33	1	1
+118	29	29
+311	10	10
+1107	4	4
+3165	0	1
+122	1	1
+64	0	2
+29	1	1
+437	1	1
+39	1	1
+215	1	1
+78	1	1
+1953	3	3
+49	1	1
+745	1	1
+38	1	1
+881	0	4
+562	0	1
+956	1	1
+44	1	1
+685	1	1
+84	1	1
+380	1	1
+40	1	1
+182	0	4
+40	1	1
+877	13	13
+157	1	1
+50	1	1
+1282	0	1
+1612	17	37
+772	1	1
+70	1	1
+1866	0	2
+1406	16	15
+1398	1	0
+1112	1	1
+77	1	1
+1374	7	7
+751	5	5
+14	1	1
+239	6	6
+12	1	1
+189	0	1
+38	1	1
+144	1	1
+40	1	1
+1200	0	1
+758	0	1
+338	18	0
+15	10	0
+187	1	1
+90	1	1
+76	0	6
+611	6	131
+44	1	1
+221	5	0
+460	64	64
+488	15	15
+262	1	1
+45	1	1
+848	4	0
+75	8	8
+52	1	1
+31	1	1
+226	10	10
+437	1	1
+67	1	1
+115	1	1
+62	1	1
+60	13	13
+721	2	0
+164	1	1
+44	1	1
+395	1	1
+33	1	1
+260	13	13
+283	10	18
+600	1	1
+28	1	1
+100	18	18
+229	1	1
+47	1	1
+1672	1	1
+21	1	1
+1571	12	9
+101	1	1
+58	1	1
+706	11	11
+627	1	1
+16	1	1
+864	16	16
+200	1	1
+36	1	1
+676	1	1
+51	5	0
+2069	1	1
+32	1	1
+584	7	0
+271	1	1
+15	1	1
+435	0	1
+312	1	1
+38	0	3
+80	1	1
+32	0	12
+91	1	1
+34	1	1
+131	1	1
+35	1	1
+754	1	1
+44	2	2
+132	2	9
+174	3	1
+53	1	1
+213	2	0
+937	0	3
+720	1	1
+48	0	2
+32	12	0
+155	38	42
+692	9	2
+399	1	1
+54	0	1
+2625	1	1
+26	1	1
+584	0	5
+505	1	1
+43	1	1
+549	1	1
+23	1	1
+69	8	9
+123	1	1
+33	1	1
+651	1	1
+41	1	1
+141	4	4
+408	1	1
+30	1	1
+690	2	1
+78	4	4
+2106	8	4
+245	0	16
+802	1	1
+38	1	1
+607	1	1
+56	1	1
+358	0	1
+192	1	1
+45	1	1
+373	1	1
+82	1	1
+720	0	1
+161	1	1
+21	1	1
+187	7	6
+184	8	8
+760	6	6
+527	14	14
+94	4	4
+44	1	1
+455	7	0
+48	1	1
+89	1	1
+27	0	4
+38	1	1
+1571	1	1
+47	1	1
+81	1	1
+35	1	1
+161	4	0
+1244	0	2
+82	1	1
+67	0	4
+202	8	8
+351	9	9
+2130	1	0
+82	11	0
+397	0	1
+37	1	0
+315	1	1
+22	1	1
+1212	1	1
+60	1	1
+1847	1	1
+54	1	1
+362	7	7
+1065	3	0
+422	0	1
+3143	1	1
+33	1	1
+552	0	1
+822	1	0
+493	0	4
+26	1	1
+2435	1	1
+48	1	1
+3350	1	1
+17	1	1
+953	86	87
+509	0	1
+1811	1	1
+58	1	1
+1200	1	1
+55	4	0
+863	0	1
+284	1	1
+47	1	1
+2795	15	15
+2326	31	30
+2510	0	8
+1829	1	1
+40	1	1
+3584	58	90
+1937	29	28
+3805	14	14
+477	1	1
+25	1	1
+529	0	1
+918	1	2
+461	5	5
+102	9	10
+3603	18	18
+790	1	0
+797	881	2
+226	10	10
+52	4	4
+40	1	1
+128	5	5
+28	1	1
+50	14	11
+53	2	1
+1451	2	1
+119	1	1
+68	1	1
+164	0	2
+1257	1	1
+12	1	0
+42	1	1
+882	1	1
+47	1	1
+274	16	16
+82	1	1
+63	1	1
+100	11	11
+581	0	1
+60	1	1
+464	1	1
+29	1	0
+5	13	0
+23	1	1
+286	1	1
+38	0	2
+17	0	5
+108	6	0
+73	7	6
+105	1	1
+72	1	1
+115	1	1
+37	1	1
+86	1	1
+34	1	1
+143	28	25
+572	4	1
+114	3	0
+134	57	56
+836	0	1
+39	1	1
+1284	0	3
+858	2	1
+42	1	1
+795	1	0
+105	1	0
+343	3	0
+1040	0	3
+548	1	1
+67	1	1
+206	6	14
+830	0	1
+1490	10	10
+139	1	1
+29	0	1
+236	6	4
+217	1	1
+48	1	1
+578	0	1
+165	1	0
+59	9	9
+113	1	2
+294	0	3
+41	0	2
+126	1	1
+29	1	1
+393	7	7
+791	1	1
+51	1	0
+30	1	1
+110	21	11
+57	1	1
+64	1	1
+68	3	3
+58	1	1
+52	9	9
+63	1	1
+85	1	1
+72	1	1
+32	1	1
+315	13	13
+138	1	0
+1106	8	4
+923	12	12
+1310	1	0
+20	1	1
+307	18	15
+995	9	9
+71	1	1
+71	1	1
+85	6	1
+202	1	1
+57	1	1
+483	1	1
+57	1	2
+185	1	1
+17	1	1
+129	1	1
+34	0	2
+179	8	10
+175	1	1
+102	1	1
+154	220	220
+71	1	1
+62	1	1
+60	1	1
+164	7	7
+126	1	1
+19	1	1
+118	13	13
+126	1	1
+53	1	1
+67	4	4
+42	7	7
+54	1	1
+51	1	1
+139	13	14
+96	1	1
+19	1	1
+163	1	1
+33	1	1
+309	0	18
+38	1	1
+318	3	0
+70	4	0
+203	3	3
+30	1	1
+606	1	1
+22	1	0
+209	0	1
+520	1	0
+415	1	1
+51	1	1
+367	5	1
+16	0	8
+137	6	3
+290	0	4
+157	1	1
+79	1	1
+275	1	1
+14	4	0
+69	1	1
+215	1	1
+7	1	0
+7	1	4
+33	1	1
+169	1	1
+101	1	1
+78	1	1
+41	3	3
+364	0	2
+577	34	29
+268	60	60
+60	47	47
+133	8	8
+68	2	0
+172	2	3
+162	30	30
+186	3	8
+235	58	58
+64	16	12
+138	24	17
+112	246	235
+51	56	56
+146	18	18
+206	49	49
+267	18	18
+152	1	1
+18	1	1
+63	13	1
+235	6	5
+209	1	1
+24	4	0
+53	1	1
+73	29409	0
+126	1	1
+85	1	1
+76	3	3
+159	1	0
+29	11	11
+72	8	8
+496	9	9
+202	1	1
+90	1	1
+692	1	1
+27	1	1
+111	0	10
+89	1	1
+33	1	1
+153	3268	0
+205	0	3
+50	3	0
+605	6	6
+59	16	16
+136	1	1
+28	1	1
+417	1	1
+17	1	1
+70	10	10
+259	1	1
+37	0	1
+352	1	1
+40	1	1
+814	1	1
+80	1	1
+125	11	11
+137	1	1
+82	1	1
+408	1	1
+56	1	1
+367	1	0
+26	1	1
+390	185277	11600
+75	2	0
+81	1	1
+175	1	1
+23	1	1
+56	1	1
+37	3	0
+55	1	1
+248	3	0
+74	2	0
+139	1	1
+26	1	1
+131	1	1
+32	5	9
+246	3	5
+53	0	4
+22	5	0
+71	0	1
+255	1	1
+189	1	1
+121	1	1
+149	1	1
+65	1	1
+322	1	1
+36	17	5
+27	4	0
+39	1	1
+346	15	1
+48	0	1
+148	1	1
+57	1	1
+38	1	1
+653	1	0
+213	1	1
+35	1	1
+60	1	1
+72	1	1
+71	6	6
+76	1	1
+73	5	5
+114	1	1
+92	1	1
+145	1	1
+108	1	1
+54	0	2
+82	11	11
+303	0	4
+149	23	23
+57	1	1
+57	1	1
+485	1	1
+64	1	1
+112	1	1
+19	1	1
+226	1	1
+70	0	1
+83	1	1
+60	1	0
+28	1	1
+1629	34	1
+5621	0	12
+37	1	1
+1691	14	14
+151	10	10
+58	1	1
+91	0	2
+149	1	1
+57	1	1
+72	1	1
+932	1	1
+21	1	1
+732	1	1
+24	1	1
+438	1	1
+17	1	1
+1100	146	145
+189	18	18
+1079	1	1
+37	1	1
+69	10	1
+241	1	1
+23	1	1
+247	1	1
+48	1	1
+3441	1	1
+18	1	1
+491	0	1
+250	12	8
+108	1	1
+37	1	2
+339	1	1
+36	1	1
+1289	4	4
+406	9	9
+579	1	1
+37	1	1
+282	2	0
+6	12	0
+42	1	1
+55	1	1
+36	1	1
+396	54	54
+1355	2	0
+101	0	1
+149	1	1
+25	1	1
+611	1	1
+60	1	1
+224	20	0
+60	1	1
+398	0	2
+819	1	1
+48	1	1
+233	1	0
+459	6	6
+1131	10	10
+129	791	450
+41	119	117
+102	14	24
+16	1	1
+379	11	10
+240	1	1
+49	1	1
+203	1	1
+96	1	1
+50	896	15
+110	1	1
+59	1	1
+387	10	10
+157	1	1
+126	1	1
+60	1	1
+86	1	1
+124	1	1
+118	1	1
+160	3	1
+82	1	1
+64	0	1
+59	1	1
+235	1	1
+43	1	1
+126	45	34
+50	0	27
+37	0	2
+74	1	1
+69	13484	10061
+60	44	44
+112	244	248
+256	4076	10878
+54	1	1
+18	0	1
+10	1	1
+76	1	1
+36	1	1
+130	1	1
+25	1	1
+85	2	2
+21	1	0
+67	1	1
+32	1	1
+162	1	1
+23	1	1
+453	10	10
+396	5	0
+82	1	1
+397	0	1
+89	3	0
+40	1	1
+157	1	1
+43	0	8
+146	1	1
+38	1	1
+101	1	1
+33	7	1
+53	1	1
+41	1	1
+60	25	18
+60	1	1
+25	1	1
+80	1	1
+31	1	1
+88	8	7
+24	1	1
+417	0	1
+42	1	1
+122	1	1
+72	5	5
+88	1	1
+36	1	1
+495	14	14
+278	3	3
+48	1	1
+50	11	0
+147	1	1
+87	1	1
+67	1	1
+788	8	0
+51	1	1
+37	1	1
+107	1	1
+22	1	1
+290	1	0
+58	3	3
+804	12	12
+133	5	0
+34	0	8
+116	1	1
+592	112	115
+93	0	1
+84	1	1
+22	1	1
+188	1	1
+46	1	0
+10	1	0
+375	6	6
+117
+
+chain 13264711 chr17_ctg5_hap1 1680828 + 0 1680828 chr17 78774742 + 40740646 42268630 76
+1491	0	1
+105829	1	0
+7	1	0
+38	1	0
+39	0	3
+1127	2	0
+399	1	1
+36	1	1
+1284	2	0
+96	1	1
+18	1	1
+402	0	1
+1243	1	17
+1187	1	1
+93	2	2
+135	1	0
+1300	1	0
+970	1	1
+33	1	1
+1390	1	1
+32	0	1
+1238	11	11
+1231	1	0
+4784	7	7
+1610	0	43
+312	0	20
+4544	1	1
+80	1	1
+5233	1	1
+31	1	1
+1582	0	4
+606	1	0
+1781	1	0
+183	14	16
+1226	6	0
+3095	1	1
+81	1	1
+4769	1	0
+4452	3	3
+41	1	1
+1401	1	1
+34	1	1
+1154	1	1
+28	1	1
+2549	12	12
+2173	2	0
+2280	1	1
+38	1	3
+2217	0	1
+498	0	1
+93	1	1
+22	1	1
+1950	0	2
+66	0	2
+1228	8	5
+1593	0	1
+468	1	1
+21	0	1
+170	10	0
+794	0	8
+1870	8	2
+3575	2	2
+43	1	1
+244	13	13
+611	5	5
+4057	4	1
+721	0	1
+1373	0	3
+28	1	1
+1422	1	0
+788	2	0
+584	188	188
+30	1152	1152
+40	270	270
+53	62	62
+87	227791	12647
+23	8319	12304
+52	449	449
+41	17972	13320
+26	114	119
+50	2682	2667
+31	1087	1088
+42	10911	10903
+41	76	76
+35	287	287
+93	1272	1285
+4834	34	1
+1629	1	1
+28	0	1
+59	1	1
+83	0	1
+25	1	1
+271	1	1
+19	1	1
+112	1	1
+64	1	1
+485	1	1
+57	1	1
+57	23	23
+144	0	4
+308	11	11
+82	0	2
+54	1	1
+70	1	1
+37	1	1
+145	1	1
+92	1	1
+114	5	5
+73	1	1
+76	6	6
+71	1	1
+72	1	1
+60	1	1
+35	1	1
+208	1	0
+658	1	1
+38	1	1
+57	1	1
+148	0	1
+48	14	1
+238	1	1
+34	1	1
+72	1	1
+39	4	0
+27	17	5
+36	1	1
+322	1	1
+65	1	1
+149	1	1
+121	1	1
+189	14	14
+54	1	1
+187	0	1
+71	5	0
+22	0	4
+53	3	5
+246	5	9
+32	1	1
+131	1	1
+26	1	1
+139	2	0
+74	3	0
+248	1	1
+70	3	0
+22	1	1
+56	1	1
+23	1	1
+175	1	1
+81	2	0
+75	32	32
+220	14	13
+196	178	178
+126	28	22
+332	8	8
+98	35	35
+82	0	1
+246	10	10
+80	24	21
+105	4	4
+104	18	20
+52	22	22
+224	6	6
+62	174	173
+149	6	9
+188	4	0
+164	0	1
+157	1	1
+264	8	0
+51	0	1
+5	0	1
+5	1	0
+32	1	1
+262	1	1
+42	1	1
+59	1	1
+68	1	1
+277	1	1
+48	1	1
+52	1	1
+30	4	4
+92	1	1
+40	1	1
+164	1	1
+34	1	1
+249	5	5
+70	5	5
+145	1	1
+55	1	1
+56	0	1
+38	1	1
+96	0	3
+143	1	1
+146	1	1
+158	15	15
+775	8	0
+80	1	1
+38	1	1
+556	1	1
+44	1	1
+79	1	0
+44	1	1
+86	4	4
+121	1	1
+13	0	1
+13	1	1
+203	1	1
+44	1	1
+567	1	0
+384	1	1
+43	1	1
+576	0	2
+167	1	1
+698	1	1
+41	1	1
+207	2	0
+342	0	1
+113	1	1
+595	13	13
+666	1	1
+19	1	1
+471	1	1
+25	1	1
+327	1	1
+36	1	1
+549	0	16
+83	17	17
+149	1	1
+40	1	1
+206	1	1
+48	1	1
+96	0	1
+87	1	1
+83	1	1
+130	1	1
+350	1	1
+17	1	1
+141	1	1
+45	1	0
+210	0	4
+428	13	13
+135	1	0
+555	8	0
+29	1	1
+108	1	1
+67	1	1
+481	2	0
+575	4	4
+10	0	3
+28	1	1
+55	4	4
+125	0	9
+59	3	3
+73	8	8
+146	1	1
+203	1	1
+132	1	1
+71	48592	13305
+71	3382	3374
+25	5834	5854
+89	1	1
+9	10000	10418
+20	1	1
+40	0	4
+13	1	1
+3	602540	600615
+450	1	1
+71	1	1
+126	4	0
+131	2	2
+95	7526	7516
+28	827	819
+39	10	10
+8	19785	19984
+220	7353	7908
+33	269	269
+60	61	61
+46	547	550
+30	424	423
+57	355	353
+45	1	1
+108	46	38
+46	51	51
+56	371	371
+48	1139	1133
+154	7	7
+118	1	1
+28	1	1
+69	1	1
+80	2	1
+56	0	3
+50	1	1
+40	1	1
+47	0	1
+176	8	8
+35	1	1
+86	1	1
+19	0	7
+57	1	1
+179	1	1
+53	1	1
+64	1	1
+39	1	1
+93	2	2
+138	0	2
+402	3	5
+350	1	1
+18	1	1
+413	8	4
+297	7	0
+273	5	0
+96	1	1
+17	1	1
+241	0	1
+593	4	0
+50	1	1
+179	30	0
+8	0	2
+6	0	1
+27	6	0
+7	1	15
+77	51	25
+119	16	15
+89	1	1
+36	5	5
+156	23	23
+66	1	1
+20	1	1
+785	62	62
+118	1	1
+97	1	1
+84	1	1
+53	2	2
+141	0	12
+60	1	1
+47	1	1
+67	1	1
+61	1	1
+61	2	0
+64	1	1
+160	1	12
+1118	3	3
+54	9	31
+96	1	1
+20	1	1
+55	1	1
+23	1	1
+260	12	12
+134	13	13
+447	5	5
+659	1	1
+76	1	1
+57	1	1
+30	1	1
+150	11	0
+11	3	0
+85	1	1
+82	0	3
+128	1	1
+83	1	1
+35	0	2
+17	1	1
+157	0	1
+5	0	2
+14	3	3
+177	1	1
+32	1	1
+355	1	1
+25	1	0
+26	0	2
+77	1	1
+31	1	1
+190	1	1
+34	1	1
+77	15	15
+79	12	14
+200	17	17
+721	1	1
+35	1	1
+247	1	1
+44	1	1
+107	1	1
+52	1	1
+391	19	23
+467	18	19
+535	1	1
+30	1	1
+54	1	2
+55	3	3
+22	2	2
+348	1	1
+34	1	1
+429	4	0
+66	8	8
+298	1	1
+56	1	1
+316	5	5
+71	1	1
+11	10	0
+31	12	0
+90	1	1
+16	1	4457
+76	1	1
+48	1	1
+66	4	5
+164	1	0
+354	1	1
+46	1	1
+779	19	19
+189	1	1
+45	1	1
+477	9	9
+180	1	0
+305	1	1
+20	1	1
+247	9	10
+131	5	5
+1115	1	1
+43	1	1
+98	0	1
+27	1	1
+152	15	15
+295	1	1
+18	1	1
+110	1	1
+49	1	1
+129	1	1
+34	1	1
+93	1	1
+91	1	1
+318	6	6
+112	4	4
+31	7	0
+150	0	2
+130	1	1
+19	1	1
+747	8	8
+708	9	9
+295	0	1
+25	1	1
+320	1	1
+26	1	1
+302	1	0
+45	15	0
+14	1	1
+75	1	1
+26	1	1
+494	1	1
+19	1	1
+267	11	11
+95	1	1
+15	4	0
+84	7	7
+87	206984	212276
+34	11226	11239
+62	1	1
+82	9866	9856
+54	5848	5823
+791	41	41
+31	1	1
+47	1	1
+39	1165	1166
+864	1	1
+31	2021	2021
+8	0	8
+37	259	273
+434	1	0
+1376	9	7
+578	14	5
+814	6	5
+638	0	1
+416	1	1
+49	1	1
+5436	0	6
+3224	0	1
+352	1	1
+31	10	0
+65	60	60
+44	112	112
+244	256	256
+1152	1	0
+773	0	5
+2150	2914	2914
+7	0	1
+18	5377	5375
+112	946	946
+2705	0	2
+1072	1	1
+30	1	1
+126	0	1
+1278	0	2
+1963	1	0
+706	0	9
+89	1	29
+428	0	3
+306	0	14
+149	1	1
+22	1	1
+1153	1	0
+877	14	12
+1014	1	1
+49	1	1
+3485	1	0
+2740	1	1
+27	4	0
+238	1	1
+48	1	1
+385	6	0
+1355	1	1
+27	2	2
+1020	10	0
+2311	0	2
+646	0	2
+8446	1	0
+1582	3	4
+2031	1	0
+1347	0	4
+939	1	1
+82	1	1
+2216	0	12
+806	0	4
+3009	7	0
+73	1	1
+37	1	1
+88	79	85
+2100	2	0
+804	1	1
+31	1	1
+56	1	0
+531	0	1
+3255	0	17
+119	16	16
+2727	0	5
+1516	1	0
+88	1	1
+31	1	1
+2085	0	1
+2381	3	0
+988	0	1
+1138	2	2
+37	1	1
+3015	12	0
+3465	1	1
+30	1	1
+1220	54	43
+3519	0	1
+4735	1	0
+1246	0	4
+257	1	0
+919	0	5
+811	53	53
+5990	0	1
+369	0	4
+1080	50000	139273
+41860
+
+chain 2227376 chr17_ctg5_hap1 1680828 + 1397503 1425444 chr17 78774742 + 41665512 41694673 1168
+810	6	0
+20	1	0
+396	1	0
+77	1	1
+160	1	1
+198	18	18
+170	1	0
+835	7	0
+178	0	1
+512	1	1
+18	0	1
+91	1	1
+41	5	4
+205	1	1
+46	1	1
+313	1	0
+195	1	1
+34	1	1
+81	114	114
+158	1	1
+29	5	0
+216	7	0
+202	0	724
+357	0	2
+36	1	1
+281	25	26
+94	1	1
+45	1	0
+56	1	1
+102	5	0
+286	8	9
+1295	1	1
+110	1	1
+117	0	5
+157	16	16
+272	1	1
+26	2	0
+277	6	6
+193	4	4
+153	1	9
+20	1	1
+1068	8	4
+216	2	0
+224	9	0
+383	21	0
+79	1	1
+361	1	1
+25	1	1
+1006	1	1
+62	1	1
+60	15	15
+107	12	14
+73	0	3
+33	0	4
+890	73	73
+139	0	5
+826	5	0
+366	0	2
+187	0	2
+175	146	146
+739	20	20
+205	13	13
+355	45	45
+160	0	1
+617	0	15
+366	28	27
+202	111	110
+154	52	52
+368	997	1615
+183	2	2
+449	4	0
+108	17	0
+162	0	2
+93	1	1
+31	0	1
+149	9	9
+69	11	11
+275	1	1
+14	0	4
+120	1	1
+115	1	1
+76	2	1
+121	1	1
+72	1	1
+88	3	3
+68	1	1
+96	57	1
+229	1	1
+21	0	1
+25	2	0
+112	2	2
+84	5	0
+75	3	3
+171	66	65
+113	18	18
+348	81	73
+67	44	44
+67	16	19
+149	0	3
+72	36	36
+123	92	91
+67	297	297
+178	433	428
+365	20	20
+130	51	51
+302	17	17
+62	20	20
+316	1	0
+138	37	25
+75	5	9
+267	7	7
+118	30	30
+69	92	92
+99	42	42
+47	0	1
+113
+
+chain 1902497 chr17_ctg5_hap1 1680828 + 1349157 1369929 chr17 78774742 - 37173234 37193985 1316
+1852	2	0
+9	8	8
+283	11	0
+34	0	1
+190	1	0
+3	2	0
+457	2	0
+106	1	1
+28	1	1
+144	4	0
+2112	6	6
+1530	1	1
+27	1	1
+123	1	0
+171	0	8
+504	5	6
+2360	1	1
+19	1	0
+1463	10	0
+471	36	36
+785	32	32
+412	0	3
+1217	32	32
+1308	28	26
+1339	13	13
+311	29	33
+733	22	22
+62	2	0
+251	11	11
+799	0	7
+97	3	0
+324	4	0
+473	46	46
+459
+
+chain 1776951 chr17_ctg5_hap1 1680828 + 1329556 1349123 chr17 78774742 - 37153638 37173199 1401
+128	0	1
+918	0	1
+530	2	0
+20	1	1
+129	1	0
+249	0	1
+279	4	0
+12	4	0
+26	4	0
+614	16	16
+179	4	0
+610	2	0
+646	28	35
+276	0	1
+1341	1	0
+360	1	1
+39	1	1
+467	1	1
+23	1	1
+633	6	6
+309	1	1
+27	0	2
+627	5	0
+1032	8	8
+226	1	1
+17	1	1
+385	5	4
+125	22	23
+301	14	0
+199	1	1
+26	1	1
+53	1	1
+33	1	1
+304	3	0
+1345	0	16
+944	72	72
+115	82	91
+248	14	14
+558	0	1
+750	1	0
+1083	69	69
+1136	0	2
+82	22	16
+836	0	4
+926
+
+chain 893264 chr17_ctg5_hap1 1680828 + 1372124 1381789 chr17 78774742 - 37196506 37206183 4351
+35	1	1
+343	27	25
+861	0	10
+298	0	4
+92	6	6
+784	0	5
+2089	1	0
+940	1	0
+304	2	0
+1246	1	0
+168	2	0
+171	1	0
+32	1	1
+1110	14	14
+833	0	4
+155	1	0
+146
+
+chain 666279 chr17_ctg5_hap1 1680828 + 1381822 1393172 chr17 78774742 + 60348942 60360296 7820
+119	36	36
+84	52	49
+205	29	29
+190	52	58
+180	57	57
+51	14	14
+312	54	54
+55	16	16
+52	88	88
+203	0	5
+250	22	25
+110	147	149
+328	217	214
+84	88	88
+79	39	39
+231	67	53
+89	16	17
+62	15	15
+187	47	51
+315	45	45
+78	214	214
+360	182	184
+116	67	67
+75	70	75
+106	18	20
+98	95	95
+54	19	19
+292	76	76
+171	87	87
+338	28	28
+98	78	75
+53	77	77
+51	62	62
+118	32	32
+192	39	39
+52	62	62
+175	44	44
+195	97	97
+75	173	173
+154	50	50
+125	17	17
+71	57	59
+92	12	12
+303	164	166
+258	424	419
+69	123	123
+345	40	39
+240	14	14
+128	87	86
+73
+
+chain 416007 chr17_ctg5_hap1 1680828 + 1245181 1252036 chr17 78774742 + 60351908 60358760 108741
+51	63	63
+229	10	10
+151	43	37
+58	47	48
+62	20	20
+152	91	97
+163	9	9
+305	11	11
+75	57	57
+75	6	6
+295	59	59
+64	15	17
+160	30	30
+112	70	75
+96	28	30
+98	95	95
+54	63	63
+249	75	75
+324	49	49
+113	42	41
+69	28	28
+98	78	75
+53	77	77
+51	62	62
+342	39	39
+52	62	62
+173	28	28
+82	49	49
+82	94	94
+78	209	203
+52	122	122
+206	100	102
+341	71	71
+53	44	44
+82	29	24
+180
+
+chain 246453 chr17_ctg5_hap1 1680828 + 1237068 1240267 chr9 140273252 + 109577466 109580401 401240
+805	41	1
+100	1	1
+90	49	0
+45	176	0
+349	1	1
+67	1	50
+65	127	0
+114	1	1
+48	1	1
+139	98	1
+58	1	0
+53	1	1
+94	1	178
+186	1	1
+21	2	2
+463
+
+chain 239377 chr17_ctg5_hap1 1680828 + 1312949 1315506 chr17 78774742 - 37137002 37139560 429566
+798	1	0
+565	0	1
+1034	0	1
+159
+
+chain 228096 chr17_ctg5_hap1 1680828 + 1321688 1324178 chr17 78774742 - 37145748 37148235 477585
+1787	39	36
+563	23	23
+78
+
+chain 196783 chr17_ctg5_hap1 1680828 + 1369959 1372123 chr17 78774742 - 37194027 37196505 622087
+666	41	355
+857	1	1
+25	1	1
+573
+
+chain 176658 chr17_ctg5_hap1 1680828 + 1325052 1326989 chr17 78774742 - 37149126 37151061 719570
+150	2	0
+143	37	37
+1605
+
+chain 168141 chr17_ctg5_hap1 1680828 + 711752 714062 chr16 88827254 + 28616023 28618285 762738
+361	1	1
+33	1	1
+130	127	0
+96	1	0
+50	19	19
+119	49	0
+110	1	2
+9	48	0
+90	98	0
+72	11	325
+56	14	14
+246	40	0
+212	17	17
+299
+
+chain 154508 chr17_ctg5_hap1 1680828 + 1307063 1308700 chr17 78774742 - 37131110 37132746 835029
+145	1	0
+1491
+
+chain 148102 chr17_ctg5_hap1 1680828 + 1232106 1430374 chr17 78774742 - 18425735 18434371 621
+4	1	1
+60	1	1
+112	0	1
+97	1	1
+125	2	0
+21	2	2
+61	1	1
+74	1	1
+73	1	1
+34	1	1
+300	1	1
+38	1	1
+80	12	12
+97	8	0
+29	2	2
+185	4	0
+515	2	0
+42	4	4
+430	190939	1320
+75	1	1
+18	1	1
+338	6	6
+61	1	0
+467	12	12
+451	1	0
+100	1	1
+50	1	1
+27	1	1
+132	0	2
+233	1	1
+37	1	1
+50	0	3
+469	1	1
+37	1	1
+94	1	1
+36	1	1
+125	4	4
+132	0	2
+39	1	1
+213	12	12
+184	3	0
+52	1	1
+16	1	1
+159	1	1
+19	2	2
+686	10	10
+230	15	15
+296
+
+chain 145367 chr17_ctg5_hap1 1680828 + 1327932 1329549 chr17 78774742 - 37151994 37153631 887940
+554	56	76
+1007
+
+chain 137569 chr17_ctg5_hap1 1680828 + 1309956 1311426 chr17 78774742 - 37134002 37135486 937317
+68	0	14
+1402
+
+chain 110156 chr17_ctg5_hap1 1680828 + 1320345 1321641 chr17 78774742 - 37144406 37145701 1161060
+640	31	31
+224	12	12
+204	52	51
+133
+
+chain 108079 chr17_ctg5_hap1 1680828 + 1315884 1317028 chr17 78774742 - 37139952 37141098 1182036
+885	0	2
+259
+
+chain 107213 chr17_ctg5_hap1 1680828 + 216004 477608 chr17 78774742 - 36300720 36848371 128
+48	7751	7515
+31	3	3
+10	52129	338773
+71	29976	29992
+37	2872	2872
+132	77377	77001
+50	9950	9939
+49	15970	16004
+80	5205	5206
+35	2373	2374
+35	2111	2102
+28	13945	13928
+281	29828	29826
+34	8713	8715
+32	430	430
+178	126	126
+28	438	438
+35	1039	1039
+174
+
+chain 88256 chr17_ctg5_hap1 1680828 + 1254762 1255800 chr17 78774742 - 37066345 37067387 1434130
+467	19	23
+391	54	54
+107
+
+chain 84535 chr17_ctg5_hap1 1680828 + 1416653 1417623 chr17 78774742 - 37747883 37748853 1275488
+209	0	1
+520	1	0
+240
+
+chain 83787 chr17_ctg5_hap1 1680828 + 1255846 1256794 chr17 78774742 - 37067433 37068381 1508032
+247	37	37
+664
+
+chain 81881 chr17_ctg5_hap1 1680828 + 1394662 1395623 chr17 78774742 - 37062220 37063176 1542051
+178	0	4
+127	43	43
+207	27	18
+379
+
+chain 78522 chr17_ctg5_hap1 1680828 + 1324178 1325052 chr17 78774742 - 37148244 37149121 1606324
+554	0	3
+200	43	43
+77
+
+chain 75262 chr17_ctg5_hap1 1680828 + 1317476 1318285 chr17 78774742 - 37141533 37142347 1673849
+255	0	5
+554
+
+chain 72597 chr17_ctg5_hap1 1680828 + 1318474 1319252 chr17 78774742 - 37142532 37143313 1734349
+618	0	3
+160
+
+chain 68786 chr17_ctg5_hap1 1680828 + 1312168 1312905 chr17 78774742 - 37136222 37136958 1829107
+216	1	0
+520
+
+chain 66138 chr17_ctg5_hap1 1680828 + 458426 496420 chr17 78774742 + 60323662 60348977 381
+29	102	102
+150	0	2
+92	35229	22555
+47	1	1
+72	0	3
+361	0	1
+361	1	1
+59	1	1
+79	1	1
+12	4	0
+22	8	0
+164	1	1
+29	8	0
+22	1	1
+166	1	1
+38	1	1
+167	0	3
+68	1	1
+61	1	1
+34	0	19
+130	1	1
+61	2	2
+22	7	0
+118	7	0
+90	0	1
+162
+
+chain 63091 chr17_ctg5_hap1 1680828 + 1252401 1253149 chr17 78774742 - 37063986 37064734 1993873
+71	5	5
+316	58	58
+298
+
+chain 58162 chr17_ctg5_hap1 1680828 + 1254067 1254744 chr17 78774742 - 37065648 37066326 2166241
+55	1	2
+54	32	32
+535
+
+chain 54716 chr17_ctg5_hap1 1680828 + 1319283 1319868 chr17 78774742 - 37143347 37143930 2309300
+443	2	0
+140
+
+chain 54428 chr17_ctg5_hap1 1680828 + 1396409 1397035 chr17 78774742 - 37063962 37064589 2322100
+416	38	39
+172
+
+chain 53306 chr17_ctg5_hap1 1680828 + 1327031 1327602 chr17 78774742 - 37151103 37151673 2373745
+61	1	0
+509
+
+chain 45719 chr17_ctg5_hap1 1680828 + 1253157 1253656 chr17 78774742 - 37064742 37065237 2803981
+63	4	0
+432
+
+chain 44822 chr17_ctg5_hap1 1680828 + 1308965 1309441 chr17 78774742 - 37133014 37133490 2867866
+476
+
+chain 44716 chr17_ctg5_hap1 1680828 + 1309483 1309955 chr17 78774742 - 37133530 37134002 2875759
+472
+
+chain 42970 chr17_ctg5_hap1 1680828 + 1249019 1250432 chr17 78774742 - 37056169 37057582 957875
+28	98	98
+37	9	10
+32	53	53
+77	51	51
+55	349	348
+39	52	52
+47	9	9
+6	173	173
+28	82	82
+49	82	82
+57
+
+chain 39900 chr17_ctg5_hap1 1680828 + 1311434 1311858 chr17 78774742 - 37135495 37135919 3282293
+424
+
+chain 36548 chr17_ctg5_hap1 1680828 + 1397076 1397503 chr17 78774742 - 37727818 37728245 1867431
+351	31	31
+45
+
+chain 35186 chr17_ctg5_hap1 1680828 + 1319971 1320341 chr17 78774742 - 37144033 37144403 3815477
+370
+
+chain 32846 chr17_ctg5_hap1 1680828 + 1253692 1254040 chr17 78774742 - 37065273 37065621 4148877
+348
+
+chain 32058 chr17_ctg5_hap1 1680828 + 1394126 1394519 chr17 78774742 - 37061682 37062075 4275850
+85	42	42
+266
+
+chain 30381 chr17_ctg5_hap1 1680828 + 343779 344098 chr13 114142980 + 60207729 60208048 4580555
+319
+
+chain 29004 chr17_ctg5_hap1 1680828 + 1317078 1317414 chr17 78774742 - 37141148 37141484 5128137
+110	17	17
+209
+
+chain 28739 chr17_ctg5_hap1 1680828 + 1393298 1393613 chr17 78774742 - 37060859 37061169 5278988
+151	5	0
+159
+
+chain 28608 chr17_ctg5_hap1 1680828 + 1381941 1384110 chr17 78774742 - 37049506 37051670 737272
+33	87	87
+3	16	17
+33	205	205
+29	190	190
+52	180	180
+57	377	361
+54	123	123
+34	639	649
+57
+
+chain 27290 chr17_ctg5_hap1 1680828 + 1250687 1251236 chr17 78774742 - 37057837 37058386 1723424
+69	52	52
+122	206	206
+100
+
+chain 23334 chr17_ctg5_hap1 1680828 + 1315561 1315806 chr17 78774742 - 37139619 37139864 8092879
+245
+
+chain 22172 chr17_ctg5_hap1 1680828 + 1247931 1248795 chr17 78774742 - 37055081 37055945 1359053
+50	54	54
+63	249	249
+75	324	324
+49
+
+chain 21861 chr17_ctg5_hap1 1680828 + 1311933 1312163 chr17 78774742 - 37135987 37136217 9092092
+230
+
+chain 20267 chr17_ctg5_hap1 1680828 + 1388625 1389065 chr17 78774742 - 37056169 37056610 1819714
+28	98	98
+37	9	10
+32	53	53
+77	51	51
+55
+
+chain 19257 chr17_ctg5_hap1 1680828 + 1251577 1252102 chr17 78774742 - 37058727 37059253 2345365
+71	53	53
+44	82	82
+24	1	0
+4	180	182
+66
+
+chain 18858 chr17_ctg5_hap1 1680828 + 1395798 1396023 chr17 78774742 - 37063364 37063589 11391766
+69	17	17
+139
+
+chain 17539 chr17_ctg5_hap1 1680828 + 1306794 1306981 chr17 78774742 - 37130913 37131100 12530835
+187
+
+chain 17362 chr17_ctg5_hap1 1680828 + 1327740 1327921 chr17 78774742 - 37151802 37151983 12688794
+181
+
+chain 16114 chr17_ctg5_hap1 1680828 + 1386775 1387126 chr17 78774742 - 37054317 37054668 3847861
+129	155	155
+67
+
+chain 14712 chr17_ctg5_hap1 1680828 + 1471572 1581528 chr17 78774742 + 41752645 41862594 227
+27	72594	72528
+20	0	36
+59	37204	37227
+3	1	1
+48
+
+chain 14021 chr17_ctg5_hap1 1680828 + 1391766 1393099 chr17 78774742 - 37059329 37060660 1551546
+50	88	88
+58	1094	1092
+43
+
+chain 13718 chr17_ctg5_hap1 1680828 + 1245232 1246117 chr17 78774742 - 37052388 37053271 1534336
+63	390	390
+37	2	0
+4	339	339
+50
+
+chain 13678 chr17_ctg5_hap1 1680828 + 1387543 1388241 chr17 78774742 - 37055086 37055784 1538578
+45	365	365
+76	171	171
+41
+
+chain 13678 chr17_ctg5_hap1 1680828 + 1386064 1386301 chr17 78774742 - 37053606 37053843 4358174
+45	78	78
+49	4	4
+61
+
+chain 12960 chr17_ctg5_hap1 1680828 + 1390153 1390290 chr17 78774742 - 37057697 37057834 10954124
+137
+
+chain 12859 chr17_ctg5_hap1 1680828 + 712690 713529 chr13 114142980 - 94890835 94891950 786174
+26	1	277
+22	258	82
+37	49	0
+12	399	624
+35
+
+chain 11529 chr17_ctg5_hap1 1680828 + 1327611 1327733 chr17 78774742 - 37151673 37151795 19785711
+122
+
+chain 11334 chr17_ctg5_hap1 1680828 + 1238199 1238375 chr13 114142980 + 19251561 19251738 585429
+101	4	5
+56	1	1
+14
+
+chain 11041 chr17_ctg5_hap1 1680828 + 1384528 1384669 chr17 78774742 - 37052089 37052230 4204331
+1	58	58
+82
+
+chain 10878 chr17_ctg5_hap1 1680828 + 1393633 1393747 chr17 78774742 - 37061189 37061303 20959654
+114
+
+chain 10460 chr17_ctg5_hap1 1680828 + 1396115 1396225 chr17 78774742 - 37063682 37063792 21801362
+110
+
+chain 10352 chr17_ctg5_hap1 1680828 + 1391207 1391342 chr17 78774742 - 37058757 37058894 7784932
+37	10	12
+88
+
+chain 9842 chr17_ctg5_hap1 1680828 + 1308830 1308934 chr17 78774742 - 37132877 37132981 23170572
+104
+
+chain 9287 chr17_ctg5_hap1 1680828 + 1318326 1318424 chr17 78774742 - 37142388 37142486 24449821
+98
+
+chain 8968 chr17_ctg5_hap1 1680828 + 1389414 1389567 chr17 78774742 - 37056958 37057111 4148137
+39	52	52
+47	9	9
+6
+
+chain 8877 chr17_ctg5_hap1 1680828 + 1252246 1252339 chr17 78774742 - 37063853 37063946 25134532
+93
+
+chain 8768 chr17_ctg5_hap1 1680828 + 1393172 1393264 chr17 78774742 - 37060733 37060825 25011976
+92
+
+chain 8158 chr17_ctg5_hap1 1680828 + 1393848 1393933 chr17 78774742 - 37061404 37061489 26172124
+85
+
+chain 7594 chr17_ctg5_hap1 1680828 + 1416023 1416258 chr17 78774742 - 37747254 37747489 2219812
+29	154	154
+52
+
+chain 7515 chr17_ctg5_hap1 1680828 + 1389981 1390060 chr17 78774742 - 37057525 37057604 6485868
+79
+
+chain 7285 chr17_ctg5_hap1 1680828 + 1252152 1252228 chr17 78774742 - 37059303 37059379 27632598
+76
+
+chain 6684 chr17_ctg5_hap1 1680828 + 1308721 1308790 chr17 78774742 - 37132768 37132837 28870693
+69
+
+chain 6515 chr17_ctg5_hap1 1680828 + 1247168 1247482 chr17 78774742 - 37054317 37054631 3599890
+45	239	239
+30
+
+chain 6497 chr17_ctg5_hap1 1680828 + 1387201 1387271 chr17 78774742 - 37054743 37054813 5969263
+70
+
+chain 6494 chr17_ctg5_hap1 1680828 + 1396307 1396375 chr17 78774742 - 37063872 37063940 29322189
+68
+
+chain 6058 chr17_ctg5_hap1 1680828 + 1315820 1315884 chr17 78774742 - 37139877 37139941 30402031
+64
+
+chain 5566 chr17_ctg5_hap1 1680828 + 218263 246046 chr17 78774742 + 60300789 60329221 713
+35	27719	28368
+29
+
+chain 5502 chr17_ctg5_hap1 1680828 + 1238858 1238932 chr5 180857866 - 146515862 146515936 441292
+74
+
+chain 5265 chr17_ctg5_hap1 1680828 + 1247608 1247664 chr17 78774742 - 37054757 37054813 15861596
+56
+
+chain 5130 chr17_ctg5_hap1 1680828 + 1393995 1394049 chr17 78774742 - 37061551 37061605 33050310
+54
+
+chain 4602 chr17_ctg5_hap1 1680828 + 1415941 1415989 chr17 78774742 - 37747172 37747220 10895303
+48
+
+chain 4584 chr17_ctg5_hap1 1680828 + 1237882 1239358 chr3 199501827 + 130155920 130156866 476764
+32	1412	882
+32
+
+chain 4558 chr17_ctg5_hap1 1680828 + 1317419 1317468 chr17 78774742 - 37141484 37141533 34680290
+49
+
+chain 4268 chr17_ctg5_hap1 1680828 + 1385266 1385319 chr17 78774742 - 37052825 37052878 8381466
+53
+
+chain 4260 chr17_ctg5_hap1 1680828 + 1246721 1246766 chr17 78774742 - 37053870 37053915 4651304
+45
+
+chain 4113 chr17_ctg5_hap1 1680828 + 1390480 1390530 chr17 78774742 - 37058030 37058080 2324449
+50
+
+chain 4082 chr17_ctg5_hap1 1680828 + 1239288 1239381 chr3 199501827 + 42815100 42815194 539611
+38	32	33
+23
+
+chain 4047 chr17_ctg5_hap1 1680828 + 833483 833530 chr2 242951149 + 222576128 222576175 5745276
+47
+
+chain 4004 chr17_ctg5_hap1 1680828 + 1413149 1413191 chr17 78774742 - 37744368 37744410 15417978
+42
+
+chain 3932 chr17_ctg5_hap1 1680828 + 1246117 1246158 chr17 78774742 - 37053273 37053314 13638111
+41
+
+chain 3773 chr17_ctg5_hap1 1680828 + 1250577 1250669 chr2 242951149 + 55360621 55360713 11417907
+92
+
+chain 3751 chr17_ctg5_hap1 1680828 + 1385702 1385742 chr17 78774742 - 37053251 37053291 3400438
+40
+
+chain 3702 chr17_ctg5_hap1 1680828 + 712859 712906 chr3 199501827 - 151273341 151273388 853543
+47
+
+chain 3381 chr17_ctg5_hap1 1680828 + 713034 713083 chr1 247249719 - 160795106 160795155 805231
+49
+
+chain 3244 chr17_ctg5_hap1 1680828 + 1389742 1389776 chrX 154913754 - 110129876 110129910 25281679
+34
+
+chain 2964 chr17_ctg5_hap1 1680828 + 236048 236081 chr17 78774742 - 37041849 37041882 635
+33
+
+chain 2912 chr17_ctg5_hap1 1680828 + 448843 448913 chr17 78774742 - 36315447 36315517 1328
+70
+
+chain 2802 chr17_ctg5_hap1 1680828 + 1237022 1237068 chr18 76117153 + 50122791 50122837 616904
+46
+
+chain 2574 chr17_ctg5_hap1 1680828 + 1384829 1384856 chr17 78774742 - 37052388 37052415 20977188
+27
+
+chain 2078 chr17_ctg5_hap1 1680828 + 1250433 1250469 chr3 199501827 - 96596057 96596093 10950065
+36
+
+chain 1744 chr17_ctg5_hap1 1680828 + 1238128 1238154 chr10 135374737 + 101842906 101842932 538799
+26
+
+chain 1504 chr17_ctg5_hap1 1680828 + 1238956 1238985 chr16 88827254 + 28335851 28335880 780320
+29
+
+chain 1483 chr17_ctg5_hap1 1680828 + 1250547 1250577 chr19 63811651 + 22556112 22556142 10358829
+30
+
+chain 1204 chr17_ctg5_hap1 1680828 + 1386904 1386940 chr7 158821424 - 133749629 133749665 22723933
+36
+
+chain 996 chr17_ctg5_hap1 1680828 + 535350 535379 chr20 62435964 + 35074223 35074252 2591094
+29
+
+chain 372 chr17_ctg5_hap1 1680828 + 1421954 1423021 chr17 78774742 - 37753177 37754232 1257025
+92	67	67
+4	0	5
+235	1	1
+56	179	175
+23	17	0
+223	1	1
+102	1	5
+66
+
+chain 3524656 chr17_gl000203_random 37498 + 0 37498 chr17_random 2617613 + 1876393 1913891 829
+37498
+
+chain 7797784 chr17_gl000204_random 81310 + 0 81310 chr17_random 2617613 + 2131554 2212864 420
+81310
+
+chain 16543266 chr17_gl000205_random 174588 + 0 174588 chr17_random 2617613 + 0 174588 173
+174588
+
+chain 3927003 chr17_gl000206_random 41001 + 0 41001 chr17_random 2617613 + 2495431 2536432 754
+41001
+
+chain 7055977505 chr18 78077248 + 10000 78016181 chr18 76117153 + 0 76117153 19
+15400898	3100000	1363998
+28218587	15	15
+5329636	150000	47000
+3667310	18	0
+16406889	50000	28008
+3388467	50000	22000
+2103304	0	3
+136125	1	0
+7	1	0
+647	1	0
+1543	1	0
+25	14	8
+19	2	0
+10	7	4
+9	4	2
+663	1	0
+359	1	0
+1617
+
+chain 404699 chr18_gl000207_random 4262 + 0 4262 chr18_random 4262 + 0 4262 116705
+4262
+
+chain 5307806876 chr19 59128983 + 60000 59114839 chr19 63811651 + 11000 63806651 21
+7286004	50000	5000
+1291194	45000	0
+11772188	69160	0
+4058236	3100000	8000000
+20129228	2	0
+701	0	3
+347	1	1
+31	1	1
+1833	0	3
+1984	1	1
+47	1	1
+190	1	1
+34	1	1
+889	2	0
+1413	7	0
+2680	4	0
+375	1	0
+314	4	0
+29	1	0
+69	0	1
+3881	1	1
+40	12	0
+293	14	0
+1479	1	0
+233	1	1
+45	1	1
+1049	1	0
+1766	7	44
+220	0	3
+537	7	0
+351	8	8
+3603	1	1
+17	0	3
+697	0	1
+269	0	3
+974	5	6
+96	10	0
+1096	10	10
+1177	12	14
+1141	9	12
+1090	0	1
+175	16	0
+1063	0	4
+4780	44	44
+722	0	1
+548	2	2
+44	1	1
+424	2	2
+26	1	0
+4	0	1
+82	1	1
+59	1	1
+2087	15	0
+1499	0	1
+1754	0	2
+11209362
+
+chain 1655749 chr19 59128983 + 20505321 20523415 chr19 63811651 + 20366320 20387252 1476
+2041	4	4
+5604	0	2
+363	0	1
+2655	5	2857
+153	46	46
+705	79	83
+370	6	1
+1668	27	26
+347	21	0
+191	6	6
+369	0	2
+393	68	67
+328	0	6
+2049	1	0
+464	35	35
+96
+
+chain 207934 chr19 59128983 + 59114839 59117224 chr22 49691432 + 49588728 49591432 1471
+992	1	1
+63	1	1
+125	152	154
+174	1	1
+47	3	0
+214	5	5
+254	1	1
+67	1	1
+55	1	321
+72	14	14
+142
+
+chain 126422 chr19 59128983 + 59117224 59118680 chr10 135374737 + 135372723 135373917 1944
+177	13	13
+165	1	1
+156	1	1
+205	4	4
+93	1	1
+14	5	0
+88	1	1
+110	1	1
+52	2	1
+28	2	1
+14	255	0
+68
+
+chain 13558 chr19 59128983 + 59116021 59116173 chr2 242951149 - 128870722 128870873 1493
+33	1	0
+24	1	1
+57	1	1
+35
+
+chain 7358 chr19 59128983 + 59118906 59118983 chr21 46944323 + 46944213 46944290 27502546
+77
+
+chain 3811 chr19 59128983 + 20573506 20573546 chr19 63811651 - 43994109 43994149 26416662
+40
+
+chain 174 chr19 59128983 + 47898161 47898204 chr18 76117153 + 27836426 27836469 20429401
+43
+
+chain 8748871 chr19_gl000208_random 92689 + 0 92689 chr19_random 301858 + 0 92689 377
+92689
+
+chain 15150451 chr19_gl000209_random 159169 + 0 159169 chr19_random 301858 + 142689 301858 196
+159169
+
+chain 10110185 chr1_gl000191_random 106433 + 0 106433 chr1_random 1663265 + 1464329 1570762 316
+106433
+
+chain 32373596 chr1_gl000192_random 547496 + 48723 413485 chr16 88827254 + 69402787 69760000 100
+342	1	1
+38	1	1
+638	8	8
+750	11	11
+240	11	11
+1444	1	1
+23	1	1
+1265	0	3
+1506	1	1
+23	1	1
+114	1	1
+80	1	1
+118	1	1
+75	1	1
+311	9	9
+489	1	1
+27	168	14
+109	0	1
+340	5	0
+442	1	0
+25	1	1
+336	0	2
+672	1	1
+21	1	1
+691	1	1
+18	1	1
+144	2	2
+22	1681	0
+79	1	1
+1812	1	1
+31	1	1
+382	0	1
+474	10	9
+280	1	1
+39	0	2
+14	1	1
+103	1	1
+74	1	1
+124	1	1
+39	1	1
+471	1	1
+33	1	1
+653	1	1
+37	1	1
+94	9	10
+195	1	13
+2039	1	0
+1635	1	1
+27	1	0
+301	17	0
+42	1	1
+315	0	1
+384	1	1
+36	0	1
+8	2	0
+1541	11	10
+376	1	1
+36	1	1
+409	1	1
+15	1	1
+547	1	1
+89	1	1
+134	11	11
+161	3	79
+23	0	26
+39	0	1
+6	25	0
+14	1	1
+101	0	9
+94	1	1
+21	1	1
+171	1	1
+81	1	1
+1737	1	1
+27	1	0
+353	1	1
+36	1	1
+470	1	1
+72	1	1
+247	107	107
+709	1	1
+57	1	1
+289	14	14
+296	0	3
+342	1	1
+25	1	1
+184	1	1
+48	1	1
+628	1	1
+50	1	1
+457	0	2
+579	1	1
+21	0	4
+431	0	1
+52	1	1
+45	1	1
+146	1	1
+25	1	0
+26	2	1
+107	1	1
+39	1	0
+72	1	1
+26	1	1
+200	1	1
+19	1	1
+931	1	1
+27	1	1
+386	1	1
+17	1	1
+874	8	8
+146	1	1
+60	1	1
+840	19	19
+63	1	1
+25	1	1
+704	0	1
+721	1	1
+23	1	1
+673	29	14
+370	2	0
+25	1	1
+53	10	10
+591	1	1
+17	1	1
+124	0	1
+373	11	11
+234	12	12
+230	1	1
+31	1	1
+63	0	3
+903	27	28
+874	1	0
+290	11	12
+275	15	15
+290	3	0
+140	1	1
+36	1	1
+99	1	1
+38	1	1
+291	7	7
+1388	8	8
+1013	0	1
+2046	1	2
+423	1	1
+51	1	1
+1534	1	1
+78	1	1
+345	1	1
+37	1	1
+673	16	17
+742	1	1
+41	1	1
+545	1	1
+21	4	4
+387	5	0
+36	1	1
+420	0	28
+640	1	1
+23	1	1
+109	10	10
+1286	1	1
+37	2	2
+294	0	1
+24	1	1
+235	5	8
+223	1	1
+17	1	1
+673	1	1
+22	1	1
+685	10	10
+1762	1	0
+560	1	1
+37	1	1
+279	1	1
+73	1	3
+124	7	8
+495	0	1
+361	0	12
+63	4	0
+127	0	3
+129	0	8
+96	1	1
+34	4	0
+2212	3	0
+954	8	9
+1081	1	1
+45	1	1
+1449	62	57
+910	1	1
+33	1	1
+627	4	0
+933	1	1
+65	0	4
+196	1	1
+198	5	1
+268	1	1
+27	1	1
+994	1	1
+93	1	1
+839	1	1
+31	1	1
+798	0	25
+1007	1	1
+27	0	1
+1076	1	0
+216	0	8
+865	1	1
+61	1	1
+627	9	9
+98	1	1
+25	1	1
+1211	1	1
+61	1	1
+1142	1	1
+37	1	2
+25	1	1
+1594	1	1
+57	1	1
+310	1	1
+21	1	1
+324	3	0
+648	1	1
+44	1	1
+128	1	1
+65	1	1
+1411	1	1
+49	2	2
+563	1	1
+109	1	1
+95	1	1
+16	4	0
+869	1	1
+68	1	1
+178	1	1
+16	1	1
+952	3	0
+206	14	6
+916	10	10
+591	0	1
+240	0	8
+189	0	14
+383	10	10
+242	27	22
+393	310	0
+472	0	1
+364	0	18
+58	1	1
+27	1	1
+40	0	1
+1533	1	24
+460	1	1
+31	1	1
+637	0	5
+63	1	1
+440	8	9
+997	1	1
+25	1	1
+1009	12	12
+317	68	68
+1117	12	8
+97	1	1
+24	1	1
+413	0	1
+1417	1	1
+28	1	1
+165	1	1
+40	1	1
+1132	1	1
+22	1	1
+193	1	1
+124	1	1
+812	1	0
+3002	1	1
+48	1	1
+1345	48	48
+673	4	0
+1213	1	1
+17	1	1
+118	2	2
+33	1	1
+84	13	28
+55	1	1
+34	1	1
+105	1	1
+29	1	1
+348	0	6
+39	0	8
+826	1	1
+26	1	1
+489	25	28
+655	0	1
+179	7	13
+51	1	1
+81	1	1
+24	0	1
+1169	0	1
+178	14	15
+410	1	1
+98	1	1
+90	0	1
+81	1	1
+120	1	1
+57	1	1
+101	11	11
+98	1	1
+16	1	1
+1379	1	1
+106	1	1
+82	1	1
+30	1	1
+85	3	20
+1047	17	17
+780	1	1
+33	1	1
+431	1	1
+62	1	1
+272	1	1
+45	1	1
+363	1	1
+50	1	1
+121	8	1
+188	1	1
+56	1	1
+358	1	1
+36	1	0
+158	0	3
+44	1	0
+253	16	16
+829	1	1
+17	1	1
+78	6	6
+473	1	1
+39	1	1
+92	1	0
+87	1	1
+2589	1	0
+85	13	13
+499	16	20
+512	7	0
+47	1	1
+257	1	1
+32	1	1
+272	14	15
+559	1	1
+25	1	1
+3126	7	4
+461	1	1
+26	1	1
+323	1	1
+30	1	1
+695	0	1
+61	1	1
+178	1	1
+100	0	2095
+496	1	1
+23	1	1
+907	1	1
+35	1	1
+300	1	1
+30	1	1
+215	1	1
+43	1	1
+542	58	58
+88	1	1
+19	1	1
+327	1	1
+61	418	1
+335	0	1
+318	1	1
+45	0	3
+922	15	15
+370	1	1
+20	1	1
+69	0	20
+25	0	4
+32	1	1
+77	7	0
+45	1	1
+3019	34	0
+111	13	13
+514	11	11
+278	1	1
+35	1	1
+462	10	10
+354	0	3
+82	5	1
+366	1	1
+43	1	1
+728	1	1
+51	1	1
+609	1	1
+21	1	1
+428	28	28
+1350	5	5
+737	1	1
+23	1	1
+499	1	1
+21	1	1
+957	3	7
+324	1	2
+466	14	14
+90	8	8
+2017	1	1
+41	1	1
+58	0	2
+498	5	5
+899	1	1
+40	1	1
+62	16	16
+422	0	1
+38	1	1
+264	2	0
+67	1	1
+988	41	41
+267	1	1
+19	1	1
+1598	61	0
+309	1	1
+35	1	1
+469	0	2
+751	0	3
+2839	1	1
+42	1	1
+1760	0	2
+330	1	1
+34	1	1
+561	1	1
+30	1	1
+664	1	1
+79	1	1
+194	67	67
+518	1	1
+29	1	1
+68	1	1
+29	1	1
+615	22	21
+389	0	1
+197	30	0
+271	1	0
+448	1	1
+33	1	1
+839	14	13
+78	1	1
+20	1	1
+331	4	0
+1237	1	1
+40	1	1
+489	1	1
+44	1	0
+303	1	1
+40	1	1
+196	0	1
+129	9	8
+424	1	1
+35	1	1
+852	5	0
+105	1	1
+2114	30	30
+513	1	1
+22	1	1
+56	2	0
+704	1	1
+35	1	1
+427	1	1
+34	0	10
+42	1	0
+294	1	0
+153	9	8
+84	1	1
+45	4	4
+1521	1	1
+29	1	1
+530	1	1
+43	1	1
+894	6127	21
+161	0	4
+175	17	17
+636	12	12
+79	11	11
+69	0	1
+76	1	1
+359	1	1
+31	0	4
+67	1	1
+439	14	14
+343	0	3
+254	0	1
+189	0	1
+35	1	1
+1458	48	48
+1591	14	14
+708	8	8
+976	6	17
+637	1	1
+33	0	1
+956	1	1
+54	1	1
+135	1	1
+23	1	1
+467	1	1
+22	1	1
+87	1	0
+11	1	1
+94	4	0
+684	17	17
+344	1	1
+23	1	1
+1534	1	1
+32	4	0
+245	1	1
+44	1	1
+880	0	5
+105	1	1
+48	1	1
+2535	9	9
+129	0	12
+287	1	1
+46	1	1
+121	1	5
+158	13	14
+80	6	6
+698	5	6
+75	1	1
+43	1	1
+123	1	1
+24	2	7
+58	7	0
+2751	8	8
+528	1	1
+39	1	1
+223	1	0
+912	1	1
+39	0	1
+1215	30	30
+874	1	1
+31	1	1
+113	0	1
+511	1	1
+28	1	1
+291	1	3
+81	1	1
+109	1	1
+152	1	1
+39	10	5
+361	1	1
+31	2	0
+20	1	1
+180	1	1
+109	1	1
+324	1	1
+25	1	1
+539	1	1
+5	2	0
+61	1	1
+395	1	0
+1146	1	1
+45	1	1
+804	1	1
+95	1	1
+856	15	15
+541	322	0
+256	1	1
+23	1	1
+347	1	1
+21	1	1
+332	1	1
+71	1	1
+531	1	0
+488	1	1
+21	0	1
+74	20	19
+517	1	1
+35	1	1
+738	1	1
+41	1	1
+91	3	3
+117	1	1
+85	9	10
+200	6	0
+489	1	1
+271	10	0
+208	1	1
+46	2	2
+708	11	11
+70	1	1
+61	1	0
+88	1	1
+45	1	1
+1206	3	0
+19	1	1
+521	1	1
+25	1	1
+1518	1	1
+42	6	6
+1124	7	8
+53	1	1
+42	1	1
+825	17	17
+825	0	3
+568	1	1
+66	1	1
+394	17	17
+126	1	1
+41	1	1
+577	26	28
+367	12	11
+489	1	1
+65	1	1
+457	1	1
+16	1	1
+350	8	8
+18	4	4
+402	1	0
+103	1	0
+648	1	1
+36	1	1
+446	0	3
+61	16	16
+823	1	1
+32	1	1
+516	1	1
+111	1	1
+1091	1	1
+38	1	1
+49	1	0
+635	0	3
+14	1	1
+153	1	1
+40	1	1
+359	1	1
+35	4	4
+283	2	0
+557	1	1
+19	1	1
+293	3	4
+454	1	1
+70	1	1
+405	0	4
+1613	1	1
+26	13	15
+44	1	1
+458	13	13
+253	0	1
+1200	0	2
+244	1	4
+247	1	1
+38	1	1
+102	0	14
+710	1	1
+20	1	1
+1098	0	4
+200	2	0
+386	0	3
+683	1	1
+26	1	1
+327	4	0
+172	1	1
+311	1	1
+18	1	1
+338	28	28
+420	1	1
+29	1	1
+352	12	12
+301	1	1
+75	1	1
+205	1	0
+250	1	1
+20	1	1
+990	1	1
+20	1	1
+233	0	6
+342	5	9
+156	1	1
+30	1	1
+321	16	16
+420	11	11
+968	3	3
+15	1	1
+162	1	1
+68	1	1
+825	18	18
+153	1	1
+42	1	1
+711	1	1
+20	1	1
+269	1	0
+1414	4	3
+641	9	9
+1000	1	1
+29	1	1
+437	0	6
+45	1	1
+261	1	1
+31	0	2
+168	1	1
+26	1	1
+73	15	7
+29	4	0
+56	1	1
+126	1	1
+32	1	1
+463	6	6
+388	14	14
+1024	1	1
+54	1	1
+1019	1	1
+27	1	1
+428	3	3
+40	1	1
+86	1	1
+29	1	0
+610	6	10
+492	1	1
+28	3	3
+1202	11	11
+981	1	1
+28	1	1
+306	1	1
+39	1	1
+696	1	0
+157	1	1
+38	1	1
+170	1	1
+44	1	1
+2005	1	1
+26	1	1
+473	4	4
+491	0	1
+331	12	12
+1430	3	3
+11	0	5
+662	2	1
+494	12	13
+673	1	1
+76	1	1
+584	1	1
+36	1	1
+872	12	12
+123	1	1
+24	1	1
+540	15	15
+1309	1	1
+22	1	1
+71	15	15
+289	1	1
+38	1	1
+145	0	4
+731	3	0
+44	1	1
+2057	6	0
+446	4	0
+156	9	9
+55	0	1
+503	0	5
+38	1	1
+341	15	15
+493	1	1
+29	5	5
+1796	2	0
+1039	7	7
+444	8	8
+37	1	1
+205	0	1
+106	1	1
+386	1	1
+20	0	6
+2818	12	12
+498	15	15
+593	1	0
+203	1	1
+49	1	1
+313	1	2
+666	1	1
+46	0	2
+1360	1	0
+954	1	1
+65	1	1
+67	1	1
+33	1	1
+1062	1	1
+48	4	4
+600	16	16
+139	1	1
+29	1	1
+150	103	103
+813	1	1
+23	1	1
+775	1	1
+28	2	0
+55	13	0
+39	2	0
+17	0	1
+23	0	1
+7	11	1
+94	74	0
+163	1	1
+27	1	1
+2843	7	7
+73	4	0
+151	1	1
+22	0	1
+90	1	1
+316	15	15
+787	0	1
+405	1	1
+36	1	1
+833	2	0
+18	1	1
+1716	12	12
+78	0	1
+1860	0	1
+696	0	4
+16	1	1
+2116	3	4
+1554	1	1
+53	1	1
+1460	1	1
+25	1	1
+427	1	1
+37	1	1
+554	1	1
+36	1	1
+1626	40	40
+1079	1	1
+26	1	1
+427	2	0
+344	6	333
+1112	1	1
+19	1	1
+796	6	0
+373	1	1
+22	1	1
+787	1	0
+34	1	1
+1007	1	1
+36	2	0
+52	1	1
+945	1	0
+11	1	1
+743	1	1
+28	2	0
+1105	5	0
+45	2	0
+17	0	2
+49	1	1
+832	1	1
+33	1	1
+176	1	1
+48	0	4
+83	1	1
+91	1	1
+47	1	1
+256	1	1
+32	1	1
+1635	3	0
+175	5	1
+30	1	1
+1026	1	0
+13	1	1
+2090	20	20
+655	0	3
+628	1	1
+63	1	1
+380	1	1
+47	1	1
+2190	24	24
+149	0	2
+747	1	1
+17	0	7
+238	1048	0
+904	1	1
+78	1	1
+433	14	14
+153	1	1
+19	1	1
+561	1	1
+35	1	1
+271	2	0
+699	1	1
+53	1	1
+1273	0	1
+3111	11	11
+235	16	16
+490	3	0
+190	32	0
+83	18	19
+182	4	5
+78	0	4
+1098	1	1
+43	2	1
+1431	1	1
+35	4	4
+1822	0	6
+198	1	1
+41	1	1
+683	15	15
+1327	0	2
+18	1	1
+324	4	7
+1392	14	14
+1447
+
+chain 5080406 chr1_gl000192_random 547496 + 490457 547496 chr1 247249719 - 103949739 104006714 618
+285	2	1
+83	1	1
+1165	5	5
+59	1	1
+331	3	3
+32	1	1
+159	9	8
+140	1	1
+34	1	1
+111	1	1
+56	1	1
+419	1	1
+30	0	1
+231	16	16
+720	1	1
+47	1	1
+992	14	14
+147	1	1
+35	1	1
+270	2	2
+55	1	1
+204	1	1
+35	1	1
+189	12	12
+393	2	0
+504	2	0
+443	0	1
+181	0	6
+45	1	1
+719	1	1
+26	1	1
+723	9	9
+295	1	1
+56	1	1
+384	0	1
+516	1	0
+24	1	1
+81	0	1
+748	1	1
+47	1	1
+110	1	1
+38	82	0
+28	1	1
+526	1	1
+27	5	5
+166	8	7
+1312	0	4
+31	1	1
+230	1	1
+87	1	1
+309	13	0
+405	1	1
+33	1	0
+100	1	1
+59	1	1
+39	1	9
+184	0	4
+50	1	1
+211	4	4
+435	1	1
+55	1	1
+160	1	1
+39	1	1
+1986	1	1
+16	1	1
+117	0	1
+55	1	1
+357	0	1
+50	1	0
+368	0	20
+62	2	0
+4	2	0
+97	1	1
+121	0	1
+29	3	0
+857	36	36
+1724	0	322
+1221	1	1
+15	1	1
+135	8	8
+157	1	1
+25	0	1
+139	1	1
+36	1	1
+722	1	1
+46	1	0
+20	7	0
+862	1	0
+143	5	5
+274	1	1
+35	1	1
+355	0	1
+20	1	1
+376	1	1
+63	1	1
+199	1	1
+31	1	1
+261	0	1
+155	20	21
+52	0	1
+56	3	0
+151	23	23
+214	16	16
+105	1	1
+9	0	4
+41	1	1
+155	1	1
+77	1	1
+487	4	0
+82	1	1
+34	1	1
+275	1	1
+38	1	1
+334	1	1
+45	1	0
+4	0	4
+455	1	1
+47	1	1
+282	3	0
+74	14	14
+82	7	0
+717	1	1
+39	1	1
+197	0	4
+12	1	1
+50	17	17
+76	1	1
+38	1	1
+148	1	1
+60	1	1
+245	1	1
+18	1	1
+380	10	0
+348	1	1
+17	1	1
+515	1	1
+24	1	1
+267	5	7
+44	2	0
+25	1	1
+111	18	0
+162	1	1
+66	0	4
+109	1	1
+39	1	1
+676	16	16
+256	1	1
+48	1	1
+791	2	1
+61	1	1
+55	312	0
+281	7	7
+98	0	4
+66	1	1
+115	9	9
+678	1	1
+37	1	1
+304	1	1
+23	1	1
+283	1	1
+19	1	1
+164	10	10
+252	0	2
+131	4	4
+36	5	5
+83	1	1
+40	1	1
+361	27	20
+303	1	1
+69	1	1
+324	40	40
+72	12	0
+397	1	1
+23	1	1
+467	0	1
+418	6	6
+77	0	1
+21	1	1
+98	0	1
+21	1	1
+282	1	2
+107	22	22
+74	3	3
+47	1	1
+193	1	1
+46	1	1
+334	0	1
+78	0	1
+355	11	12
+823	1	1
+20	1	1
+173	1	1
+65	1	1
+335	0	4
+599	12	12
+143	1	1
+25	1	1
+1136	1	1
+38	1	1
+247	0	4
+30	1	1
+86	1	1
+19	1	1
+735	8	8
+679	15	15
+456	1	1
+43	1	1
+312	1	1
+94	1	1
+1047	1	1
+40	1	1
+1645	1	1
+37	1	1
+267	1	1
+55	1	1
+187	8	18
+480	1	1
+85	1	1
+537	1	1
+80	1	0
+80	0	11
+249	1	1
+24	1	1
+134	1	1
+36	1	1
+62	1	1
+81	0	2
+93	5	5
+46	1	1
+158	1	1
+36	1	1
+148	1	1
+67	1	1
+595	1	1
+30	1	1
+946	14	14
+58	1	1
+15	1	1
+321
+
+chain 2388490 chr1_gl000192_random 547496 + 0 480547 chr1 247249719 + 146071331 146197786 328
+299	0	14
+547	0	5
+291	3	3
+30	1	1
+1107	1	1
+35	1	1
+66	1	1
+86	1	1
+975	16	0
+485	12	0
+240	1	1
+16	1	1
+452	1	1
+26	2	2
+219	10	10
+607	31	14
+57	1	1
+397	1	1
+27	1	1
+69	0	2
+299	1	1
+38	0	1
+97	1	1
+33	1	1
+310	1	1
+63	1	1
+1214	11	0
+672	1	1
+30	1	1
+562	1	1
+34	1	1
+86	5	0
+36	52	0
+40	36	0
+73	0	3
+218	0	2
+885	1	1
+77	1	1
+153	1	1
+46	1	1
+538	0	1
+42	1	1
+495	0	1
+618	0	1
+406	1	1
+47	2	0
+264	1	1
+19	1	1
+112	0	3744
+343	13	14
+366	0	1
+39	1	1
+90	5	5
+72	0	3
+152	2	2
+42	1	1
+71	0	1
+30	1	1
+61	12	12
+280	0	3
+12	1	1
+101	1	1
+48	1	1
+97	1	1
+115	1	1
+299	1	1
+41	89	1
+148	7	7
+250	0	1
+1402	1	1
+69	1	0
+239	1	1
+38	1	1
+376	2	0
+96	1	1
+31	1	1
+273	0	4
+458	1	1
+22	0	12
+149	1	1
+38	0	2
+18	1	1
+443	1	0
+252	1	1
+25	1	1
+74	1	1
+18	0	1
+1535	108	9368
+354	1	0
+37	1	1
+1063	3	2
+3079	1	0
+142	1	1
+71	1	1
+230	6	6
+41	0	1
+112	4	4
+17	1	1
+478	2	0
+242	1	1
+21	1	1
+1407	1	0
+669	1	1
+34	1	1
+1561	1	1
+40	2	2
+62	1	1
+53	1	1
+975	1	1
+119	1	1
+1713	5	5
+132	0	3
+2570	1	0
+1294	9	9
+934	1	1
+33	1	1
+1518	4	1
+125	2889	0
+28	0	18
+706	10	10
+156	13	13
+1659	13	14
+1183	1	1
+49	1	1
+173	23	25
+420	364833	841
+3162	1	1
+44	1	1
+3579	1	1
+17	2	1
+30	3	0
+56	13	14
+298	1	1
+45	1	1
+388	1	1
+85	1	3
+162	2	0
+3397	3	5
+143	1	1
+19	1	1
+1299	1	1
+27	1	1
+10915	0	1
+4994	8	0
+1610	0	1
+3783	7	7
+606	4	0
+304	0	15
+143	12	14
+390	1	1
+43	0	2
+16	1	1
+231	5	0
+127	0	2
+222	2	0
+218	1	1
+45	1	1
+331	1	1
+23	1	1
+216	1	1
+21	1	1
+999	5	0
+563	1	1
+23	1	1
+305	1	1
+44	1	1
+466	2	0
+20	0	4
+234	16	21
+104	1	1
+28	1	1
+465	0	6
+137	1	3
+115	1	1
+23	1	1
+409	1	2
+762	1	1
+34	1	1
+133	1	1
+67	1	1
+1539	1	1
+24	1	1
+1362	9	2
+1632	1	1
+28	1	1
+1531	2	0
+26	1	1
+1909	10	2
+1605	1	1
+26	0	1
+834	0	1
+393	1	0
+40	1	1
+1724	1	1
+46	1	1
+588	8	8
+61	16	16
+669	1	1
+39	1	0
+1028	1	0
+21	1	1
+320	8	4
+1618	13	13
+569	18	15
+151	76	46
+2055	1	1
+35	1	1
+232	2	2
+26	1	1
+244	23	21
+54	16	16
+162	9	9
+61	1	1
+45	1	1
+72	1	1
+81	1	1
+197	1	1
+39	1	1
+300	1	1
+19	1	1
+370	9	9
+1433	1	0
+76	1	1
+21	1	1
+415	1	1
+26	1	1
+175	1	1
+9	2	0
+25	1	1
+413	1	1
+32	1	1
+299
+
+chain 551976 chr1_gl000192_random 547496 + 231797 237825 chr6 170899992 - 168530959 168536987 11545
+330	1	1
+17	2	2
+622	1	1
+19	1	1
+487	6	6
+662	1	1
+28	1	1
+1141	1	1
+84	1	1
+122	1	1
+29	1	1
+938	1	1
+49	1	1
+234	1	1
+107	1	1
+1138
+
+chain 488033 chr1_gl000192_random 547496 + 485075 510500 chr1 247249719 - 100429719 100455173 784
+56	1	1
+59	1	1
+88	1	0
+166	1	1
+42	1	1
+157	3	0
+1500	0	4
+24	1	1
+173	13	13
+537	1	1
+71	1	1
+274	1	1
+48	2	0
+29	1	1
+419	1	1
+75	1	1
+714	1	0
+919	11263	11275
+82	8662	8682
+36
+
+chain 29331 chr1_gl000192_random 547496 + 141011 141318 chr6 170899992 + 18853789 18854096 4814875
+307
+
+chain 25541 chr1_gl000192_random 547496 + 270161 270431 chr1 247249719 - 64213918 64214188 6752530
+270
+
+chain 18946 chr1_gl000192_random 547496 + 186298 186626 chr3 199501827 + 41796165 41796493 1046918
+124	44	44
+160
+
+chain 12970 chr1_gl000192_random 547496 + 526591 526726 chr14 106368585 + 78475097 78475232 7622843
+135
+
+chain 5617 chr1_gl000192_random 547496 + 185742 186466 chr4 191273063 - 143160847 143161571 1095905
+58	622	622
+44
+
+chain 2480 chr1_gl000192_random 547496 + 270431 270457 chr18 76117153 + 32169444 32169470 11367132
+26
+
+chain 2357 chr1_gl000192_random 547496 + 186676 186702 chr16 88827254 + 78288031 78288057 25120671
+26
+
+chain 2224 chr1_gl000192_random 547496 + 530486 530526 chr1_random 1663265 + 473083 473123 25958
+40
+
+chain 22466185064 chr2 243199373 + 10000 243102476 chr2 242951149 + 0 242751149 1
+1201236	0	1
+2057	1	1
+26	1	1
+4043	22	0
+82	7	101
+33	84	0
+26	1	23
+67	48	0
+176	318	0
+40	92	0
+33	0	74
+62	0	6
+22	0	118
+387	2446	0
+843	2450	0
+167	2304	0
+21342	1	1
+50	4	0
+2040	0	4
+9053	2	0
+88	3	53
+1078	0	1
+4122	1	0
+1608	28	1
+4029	0	9
+967	4547	1000
+420	27	0
+2237126	0	1
+2458	17	17
+4595	4	0
+3531	14	14
+3954	51129	50000
+1426129	160449	100025
+11087286	0	3
+773	103977	50000
+1576	0	1
+240	0	1
+318	2	0
+255	0	16
+2851	10	10
+1404	1	1
+27	1	1
+703	13	0
+375	0	1
+4783388	35000	25000
+848	0	2
+1225	0	2
+391	1	0
+3653	1	1
+28	1	1
+49	0	4
+4514	0	9
+9628	1	9
+1483	7	7
+1990	0	1
+1949	1	0
+2716230	1	0
+7799848	851	851
+38932068	5	9
+9477928	0	3
+7529698	72396	0
+1891551	294073	150000
+17672	1	0
+5792	1	0
+9017	0	266
+2944	0	1
+9388	2	0
+37828	4	0
+23436	0	4
+290931	1273578	1000000
+731068	3000000	3000000
+2558421	0	1
+1197	10	0
+685	42	46
+2309	0	1
+1332	22	23
+344	0	1
+1645	4	4
+4093	25	25
+2446	1	0
+6329	1	0
+769	0	1
+873	7	0
+1299	0	1
+8250	15	15
+4291	10626	12548
+1063	103	0
+75	0	218
+5897	1	1
+33	1	1
+9905	51	37
+1711	1	1
+45	1	1
+1597	4	4
+61	1	1
+869	13	0
+1633	15	15
+1179	3	0
+2819	0	2
+156	88	465
+100	0	25
+4753	0	8
+4903	6	6
+3847	0	2
+108126	0	145
+3542	1	0
+10276	0	1
+402	1	1
+47	1	1
+63	2	0
+583	1	1
+34	1	1
+8974	0	46
+379	1	1
+70	1	1
+2474	0	102
+1756	0	1
+8426	0	1
+11986570	151150	142000
+14207	1	1
+49	1	1
+1781	0	12
+409	1	0
+1874	1	1
+33	1	1
+4795	2	0
+3686	1	1
+15	1	1
+164	2	0
+7287	5	5
+702023	72796	150000
+69	1	0
+1598	0	1
+1340	0	1
+1030	0	4
+1166	10	10
+6406	1	1
+34	1	1
+3283	2	4
+496	1	23
+25	10	0
+40	1	1
+21282	2	1
+1406	0	44
+937	17	0
+18255	1	0
+172366	0	281526
+40517	0	406
+58864	1	2
+1843	0	2
+14994	0	1
+12992	2	0
+2571146	1	0
+35688061	108224	100000
+29671719	1	0
+39665349	1	0
+14876089	64197	20000
+401	0	3
+1831	1	1
+61	1	1
+654	11	1
+127	0	28
+116	25	29
+74	9	9
+3247	2	0
+1355	1	0
+816	1	0
+21	3	0
+526	1	1
+60	1	1
+773	1	0
+1494	1	0
+1683	1	0
+21	1	1
+596	1	0
+1582	1	0
+425	0	3
+1139	0	8
+138	144	813
+71	1	0
+385638	1	1
+219	1	1
+51	7	7
+54	15205	15205
+54	7	7
+51	1	1
+110	1	1
+5198249	0	1
+115	80	0
+60	40	0
+80	100	20
+442	1	1
+35	1	1
+119	9	129
+14	0	40
+61	1	1
+85	0	40
+1331	0	1
+1194	12	14
+1773	0	5
+1623	1	1
+25	1	1
+2422	21	22
+2315	0	1
+31	1	1
+1508	0	3
+50	0	4
+970	6	6
+7234	4	0
+1228	1	0
+1233	8	1
+4207	1	1
+41	1	1
+1715	50	50
+1532	0	2
+1714	2	0
+2299	2	0
+2143	1	1
+18	1	1
+917	1	0
+1082	1	1
+49	1	1
+9098	0	4
+5529	0	1
+3266	0	8
+894	6	0
+1440	1	1
+2095	2	0
+4179	18	13
+1785	0	1
+1674	0	6
+1217	32348	33000
+287	17	23
+40	173	0
+20	161	0
+13	66	0
+12	71	1
+12548	30000	30000
+952154	41011	25000
+1914	1	0
+225	1	1
+57	1	1
+2910	0	1
+471	1	0
+1956	1	1
+43	1	1
+991	0	92
+2863	3	0
+1838	306	0
+1006	30	0
+206	1	1
+27	0	3
+221	17	17
+1525	8	0
+413	1	1
+32	2	2
+1573	12	12
+2258676
+
+chain 8298836 chr2 243199373 + 90373613 90527957 chr2 242951149 + 90958828 91114560 236
+29837	32	32
+212	25	25
+508	90	90
+1291	33	33
+2574	1	0
+833	28	28
+2712	0	1
+805	10	5
+565	68	68
+75	69	57
+176	58	513
+63	105	105
+336	33	33
+69	1	0
+280	4	4
+111	12	12
+523	1	0
+136	55	56
+198	0	1
+630	0	1
+362	42	42
+405	30	30
+78	5	0
+125	5	0
+75	140	0
+166	49	49
+1653	30	30
+3790	5	5
+500	21	21
+577	23	23
+180	0	1
+1105	1	0
+231	4	4
+333	33	33
+852	2	0
+2709	16	16
+476	28	28
+53	33	57
+256	0	3
+900	0	1
+227	0	2
+718	0	2
+244	42	42
+302	30	30
+211	21	21
+1809	16	17
+204	33	32
+341	9	9
+176	0	5
+180	67	67
+73	39	39
+369	49	49
+52	9	15
+699	9	13
+142	0	4
+184	0	4
+248	27	26
+306	10	10
+63	20	20
+533	22	22
+432	86	85
+97	19	19
+383	19	23
+642	10	9
+156	88	88
+217	0	6
+1798	9	7
+425	0	4
+1191	0	4
+465	40	37
+671	7	7
+450	0	1
+714	31	32
+682	38	15
+230	28	1076
+95	220	261
+80	1967	0
+118	383	158
+81	28	2
+247	0	1
+181	0	1
+702	47	47
+361	39	39
+300	50	50
+195	9	9
+179	35	35
+228	0	10
+321	65	65
+233	20	20
+368	35	35
+1436	37	37
+985	5	5
+140	73	73
+1031	25	25
+957	51	51
+690	23	48
+1047	49	49
+186	1	0
+244	4	4
+166	16	16
+173	1	0
+387	51	51
+122	59	58
+141	1	0
+72	102	84
+75	203	201
+276	30	30
+367	20	20
+105	67	68
+82	0	1
+386	7	7
+68	61	61
+514	56	56
+92	91	91
+268	89	89
+200	4	4
+526	33	36
+370	10	10
+366	20	26
+1107	0	2
+130	74	74
+101	0	1
+542	32	34
+179	43	43
+151	84	84
+421	25	25
+332	1	0
+561	64	65
+1406	10	10
+161	97	88
+564	27	30
+123	29	33
+170	0	1
+183	94	94
+52	4	0
+379	83	83
+237	32	31
+187	46	46
+236	728	703
+50	1494	1865
+72	67	32
+25	1732	6535
+52	52	52
+104	647	648
+27	494	471
+23	0	137
+1	1884	302
+115	8	8
+76	3078	388
+26	200	44
+59	2295	2292
+40	1854	1861
+54	2541	2546
+27	28	27
+57	56	56
+26	2212	2216
+181	494	652
+42	2237	2213
+40	2572	2562
+36	1791	1791
+34	2776	2807
+23	7115	7113
+44	509	509
+36	664	665
+43	1891	2219
+36	256	256
+31	276	289
+42	881	1734
+67	149	144
+49	190	190
+73	357	345
+30	1074	1075
+42	1850	1850
+47	469	481
+24	2460	2482
+41	3325	3319
+32	306	296
+26
+
+chain 2305993 chr2 243199373 + 243162866 243189340 chr16 88827254 - 5000 31222 1142
+136	9	9
+870	16	16
+229	1	1
+44	1	1
+330	10	14
+243	1	1
+93	1	1
+58	1	1
+144	1	1
+62	95	95
+333	1	1
+77	1	1
+494	9	11
+230	8	8
+61	12	13
+128	14	14
+123	1	1
+68	1	1
+4208	5	1
+1989	71	0
+121	1	1
+35	1	1
+1498	59	0
+443	69	69
+237	1	1
+45	1	1
+75	1	1
+32	2	1
+20	1	1
+152	1	1
+129	0	1
+1040	1	1
+70	2	0
+128	1	1
+50	1	1
+605	9	8
+62	1	1
+155	1	1
+50	11	6
+94	1	1
+409	1	1
+34	1	1
+217	1	1
+39	1	1
+287	0	9
+102	1	1
+56	30	26
+64	108	0
+127	1	0
+373	1	1
+18	1	1
+194	1	1
+10	1	1
+98	1	1
+67	1	1
+184	1	1
+21	1	1
+86	0	1
+44	1	1
+50	15	15
+177	1	1
+72	1	1
+222	1	1
+44	1	1
+50	1	1
+46	1	1
+449	1	1
+118	1	1
+127	0	1
+242	1	1
+36	1	1
+710	4	4
+69	1	1
+87	1	1
+115	1	1
+68	17	0
+12	2	1
+14	0	12
+36	4	0
+102	1	1
+105	24	24
+131	18	18
+64	19	19
+293	1	1
+43	1	1
+134	25	25
+77	14	14
+225	1	0
+93	1	1
+363	11	11
+271	25	25
+136	1	1
+36	1	1
+102	4	4
+29	1	1
+51	2	0
+162	0	4
+61	1	0
+65	1	1
+26	4	4
+140	17	17
+336	1	1
+25	1	1
+408	16	16
+311	27	27
+90	7	7
+449	1	1
+47	1	1
+133	1	1
+62	7	7
+194	1	1
+13	3	0
+54	2	0
+28	1	1
+72	1	1
+45	1	1
+65	1	1
+23	1	1
+279	1	1
+61	1	1
+55
+
+chain 1358560 chr2 243199373 + 89890737 90543561 chr2 242951149 - 153539598 155537136 99
+8973	0	1
+939	0	1
+4351	0	2
+2413	1	1
+37	1	1
+515	1	0
+224	1	1
+22	1	1
+203	1	1
+18	1	1
+249	8	7
+830	4	0
+177	1	0
+30	1	1
+224	1	1
+75	1	1
+243	1	1
+20	0	5
+2724	0	137
+439	1	1
+35	1	1
+444	0	2
+1484	1	1
+41	1	1
+395	1	1
+40	1	1
+417	1	1
+44	1	1
+909	1	1
+32	24	14
+1057	2	2
+46	1	1
+306	1	1
+32	3	0
+269	10	10
+535	10	10
+615	1	1
+42	1	1
+1295	1	1
+21	1	1
+84	1	1
+30	0	1
+19	1	1
+434	57	57
+283	15	15
+304	12	12
+149	17	17
+1413	1	1
+32	1	1
+66	550910	1890523
+54	205	14
+64	147	86
+119	57	8
+71	27	96
+100	1265	73
+307	7	9
+182	31	30
+128	15	15
+95	61	59
+92	20	296
+50	77	75
+255	261	3338
+95	264	262
+204	53	55
+136	81	81
+173	62	57
+130	77	76
+241	35	35
+424	0	154
+42	3	3
+109	0	434
+68	0	59
+215	1	1
+47	1	1
+109	0	180
+10	4	0
+21	7	104
+33	31	37
+62	17	17
+114	1	1
+50	0	9
+117	9	0
+63	1	1
+92	1	1
+37	146	0
+49	956	0
+32	163	4
+37	619	0
+42	1	1
+108	973	20
+91	1	18
+215	19	19
+20	26	0
+124	56	0
+14	65	0
+65	1	1
+465	1	1
+45	1	0
+126	1	1
+46	1	1
+1501	1	1
+41	40	0
+58	2	5
+574	8	0
+830	0	5
+121	0	3
+26	0	2
+52	0	2
+183	54	0
+1069	1	1
+62	4	0
+23	1	1
+62	0	3
+233	0	2
+32	3	0
+1051	112	112
+56	26	26
+59	7	7
+588	17	18
+401	18	18
+472	1	0
+398	2	3
+249	181	22
+397	0	158
+97	42	42
+1302	24	2
+162	9	9
+740	40	40
+554	0	1
+1362	23	19
+249	12	12
+372	36	36
+987	1	0
+221	10	8
+394	9	9
+169	34	36
+170	1	1
+27	1	1
+61	1	0
+396	0	120
+152	1	13
+60	0	5
+12	1	1
+145	1	1
+51	1	1
+847	6	6
+420	1	1
+46	1	0
+43	1	1
+145	1	1
+41	1	1
+142	25	24
+332	14	14
+310	1	1
+91	1	1
+605	1	1
+47	1	1
+361	10	10
+183	0	5
+672	8	8
+76	17	20
+227	1	1
+86	1	1
+60	1	0
+30	5	5
+2399	1	1
+29	1	1
+547	10	17
+195	3	0
+609	3	0
+175	44	44
+292	8	8
+209	36	37
+543	39	39
+82	43	43
+235	38	38
+760	20	20
+502	8	0
+108	7	18
+66	2	0
+57	0	3
+88	36	36
+77	0	15
+94	24	24
+61	31	1532
+146	38	41
+92	82	77
+151	0	2606
+94	93	1000
+189	50	50
+234	100	94
+146	49	49
+189	74	74
+62	37	17
+258	30	30
+114	47	47
+494	96	98
+323	42	43
+106	20	20
+142	250	250
+161	7	7
+651	21	21
+492	237	249
+144	23	23
+88	48	48
+52	15	15
+201	6	0
+105	29	29
+68	18	18
+87	50	50
+227	147	147
+176	17	17
+404	9	9
+457	0	23
+392	41	41
+196	18	18
+99	77	80
+219	52	53
+156	0	7
+323	28	28
+99	43	42
+229	27	27
+156	107	103
+95	1	0
+1118	0	1
+282	41	41
+172	21	3
+104	26	0
+21	1	71
+54	6	76
+63	1	1
+58	1	1
+84	1	1
+285	1	1
+46	1	1
+320	15	15
+326	7	7
+170	1	1
+73	1	1
+214	1	1
+40	1	1
+613	1	0
+772	0	2
+424	1	1
+34	1	1
+423	1	1
+33	1	1
+1157	1	1
+43	2	2
+82	1	1
+21	1	1
+65	1	1
+62	1	1
+250	1	1
+79	1	1
+88	2	2
+79	1	1
+68	11	11
+115	1	1
+38	1	1
+63	9	0
+39	1	1
+73	1	1
+77	3	3
+55	1	1
+46	1	1
+157	1	1
+58	0	2
+92	1	1
+67	1	1
+48	1	1
+289	1	1
+40	1	0
+398	1	1
+31	1	1
+729	1	1
+72	1	1
+575	1	1
+86	1	1
+495	3	0
+472	1	1
+34	1	1
+87	1	0
+28	1	1
+441	20	0
+31	1	1
+61	1	1
+152	5	5
+774	0	1
+114	2	0
+355	0	3
+415	5	0
+76	1	1
+18	1	1
+308	1	1
+18	1	1
+226	4	4
+490	0	3
+104	1	1
+47	1	1
+542	6	6
+131	8	0
+152	49	1
+68	9	9
+198	1	1
+40	0	10
+78	1	1
+108	1	1
+73	1	1
+50
+
+chain 1317324 chr2 243199373 + 234472598 234486532 chr2 242951149 - 8801149 8815083 1658
+13934
+
+chain 1182591 chr2 243199373 + 111018489 111031067 chr2 242951149 - 132350497 132363075 1985
+750	1	0
+155	1	0
+2029	0	1
+2687	0	1
+2417	3	0
+3105	1	3
+965	35	36
+238	6	6
+185
+
+chain 907761 chr2 243199373 + 111000659 111010676 chr2 242951149 + 110060000 110070000 4064
+3405	66	54
+839	0	1
+854	33	33
+1502	180	174
+250	88	88
+1904	40	40
+856
+
+chain 864618 chr2 243199373 + 110991361 111000659 chr2 242951149 + 110050705 110060000 3488
+3987	37	37
+135	34	34
+2446	4	0
+1497	0	1
+1158
+
+chain 730598 chr2 243199373 + 111010676 111018489 chr2 242951149 + 110070000 110077815 3339
+976	16	15
+4855	0	3
+320	26	26
+1620
+
+chain 247895 chr2 243199373 + 111031067 111033745 chr2 242951149 - 131778891 131781575 150672
+814	1	1
+73	1	1
+148	0	6
+1211	4	4
+426
+
+chain 233678 chr2 243199373 + 87718206 87726480 chr2 242951149 - 151887377 151890935 691
+139	0	3
+233	4	2
+36	0	1
+291	21	13
+104	28	28
+303	26	26
+314	134	82
+86	0	1
+53	4314	721
+22	22	0
+50	389	652
+54	1133	0
+17	214	6
+79	34	60
+62	59	67
+53
+
+chain 228678 chr2 243199373 + 243159401 243162866 chr1 247249719 + 217390 220668 1312
+57	88	88
+22	186	0
+101	49	49
+417	53	54
+61	3	0
+141	0	1
+198	8	8
+852	39	39
+405	56	56
+61	27	27
+589	1	1
+51
+
+chain 207578 chr2 243199373 + 243152688 243155284 chr10 135374737 - 346 2792 2690
+533	150	0
+105	1	1
+49	1	1
+260	1	1
+69	1	1
+262	1	1
+29	1	1
+1133
+
+chain 148868 chr2 243199373 + 243155284 243160374 chr5 180857866 - 20000 25834 2103
+547	1	1
+38	1	1
+431	1	1
+24	1	1
+1389	1	1
+36	1	1
+1646	57	57
+82	0	744
+6	22	22
+186	101	101
+49	417	417
+53
+
+chain 147892 chr2 243199373 + 97920581 97932373 chr2 242951149 - 145465890 145477699 123
+1513	0	1
+2596	1	1
+36	1	1
+1383	5	1
+46	4	0
+550	1	4
+1798	7	8
+158	1	29
+18	1	1
+110	1	1
+48	1	1
+1617	7	0
+723	1063	1063
+93	1	0
+9
+
+chain 133880 chr2 243199373 + 87666489 111064157 chr2 242951149 - 130965951 132771520 53
+624	23366717	1774574
+2397	0	12
+14288	0	1
+1427	1	1
+24	1	1
+1756	10	10
+83	69	69
+698	0	21
+1910	1	1
+61	1	1
+3754	0	8
+243	1	1
+33	1	1
+320	0	1
+163	1	1
+36	1	1
+809	0	1
+1762	1	1
+49	1	1
+425
+
+chain 127176 chr2 243199373 + 5140970 5146585 chr2 242951149 - 235014747 235020583 1011815
+158	1545	1830
+107	308	308
+50	129	129
+85	163	165
+62	65	65
+282	81	63
+147	650	624
+67	138	138
+59	285	285
+76	61	62
+92	72	72
+76	266	249
+70	129	128
+83	107	102
+202
+
+chain 104115 chr2 243199373 + 87667113 87668206 chr2 242951149 + 87520624 87521717 786265
+1093
+
+chain 95484 chr2 243199373 + 87729232 87738885 chr2 242951149 + 87510347 87520000 5761
+9653
+
+chain 84057 chr2 243199373 + 90492917 90545103 chr2 242951149 - 152993866 153046874 435
+28	21223	21222
+38	2087	2087
+38	134	134
+40	246	246
+45	0	255
+13	0	572
+34	189	189
+50	234	234
+30	1029	1029
+47	494	494
+96	633	633
+250	1379	1379
+190	682	682
+29	173	173
+50	227	227
+147	1809	1804
+77	219	219
+52	479	479
+28	99	99
+43	229	229
+27	156	156
+107	16787	16788
+49	628	628
+1542
+
+chain 73315 chr2 243199373 + 87720014 87720774 chr2 242951149 - 155450797 155451557 1717423
+760
+
+chain 66981 chr2 243199373 + 1219529 1222202 chr2 242951149 + 1208584 1209647 1299817
+61	279	0
+275	1051	0
+115	843	563
+49
+
+chain 64603 chr2 243199373 + 90371566 90373613 chr2 242951149 + 90963202 90965490 370989
+76	46	46
+165	47	47
+460	75	75
+51	403	393
+63	64	364
+66	168	168
+56	68	19
+69	135	135
+35
+
+chain 46427 chr2 243199373 + 1223650 1226709 chr2 242951149 + 1208645 1209604 1438302
+140	630	0
+183	167	167
+210	1050	0
+171	420	0
+88
+
+chain 36623 chr2 243199373 + 89847430 89848295 chr5 180857866 + 153976522 153977390 3635252
+54	96	96
+262	346	349
+107
+
+chain 34396 chr2 243199373 + 87721616 87729232 chr2 242951149 + 87502993 87507825 13964
+67	36	543
+1013	77	25
+569	4	4
+189	715	6
+6	94	94
+389	54	54
+542	2531	33
+70	11	11
+68	21	21
+129	10	10
+126	0	22
+162	9	0
+89	28	26
+108	298	307
+116	64	12
+21
+
+chain 31906 chr2 243199373 + 90476997 90485104 chr2 242951149 - 155439923 155448722 818134
+65	4692	1587
+31	1167	442
+62	157	183
+65	24	24
+92	31	191
+67	10	184
+32	72	0
+76	105	36
+60	4	0
+97	52	697
+66	9	0
+169	1	23
+85	272	2102
+131	95	43
+149	89	1960
+80
+
+chain 31233 chr2 243199373 + 239788914 239789423 chr2 242951149 + 239454423 239454932 2214253
+173	20	20
+161	13	13
+66	12	12
+64
+
+chain 27639 chr2 243199373 + 243165116 243187640 chr8 146274826 + 470 67316 1215
+95	9992	9923
+69	4222	48594
+49	1	1
+58	4967	4926
+25	3019	3079
+27
+
+chain 25982 chr2 243199373 + 16340754 16341023 chr3 199501827 - 118072788 118073057 6523537
+269
+
+chain 25898 chr2 243199373 + 1220683 1220990 chr2 242951149 + 1208828 1209135 2249524
+307
+
+chain 25826 chr2 243199373 + 87728597 87729031 chr2 242951149 + 87491002 87491436 712257
+28	108	108
+298
+
+chain 25128 chr2 243199373 + 5141270 5144398 chr1 247249719 + 207689145 207692170 1456022
+66	87	87
+79	23	23
+95	979	893
+74	119	119
+116	487	487
+54	893	876
+56
+
+chain 24661 chr2 243199373 + 16273805 16274100 chr4 191273063 - 182882474 182882769 7289877
+128	26	26
+141
+
+chain 19295 chr2 243199373 + 90372486 90373577 chr2 242951149 + 90976555 90977646 1336226
+61	57	57
+56	292	292
+41	202	202
+55	193	193
+134
+
+chain 19158 chr2 243199373 + 1225400 1225680 chr2 242951149 + 1208855 1209065 11144872
+180	70	0
+30
+
+chain 18303 chr2 243199373 + 1219198 1219473 chr2 242951149 + 1208603 1208808 11853376
+134	73	3
+68
+
+chain 13465 chr2 243199373 + 16354747 16354888 chr5 180857866 + 167726962 167727103 16868271
+141
+
+chain 13298 chr2 243199373 + 89875086 89876327 chr20 62435964 + 29293186 29293377 17078580
+57	350	0
+39	320	0
+36	155	0
+6	225	0
+53
+
+chain 13261 chr2 243199373 + 1224140 1224280 chr2 242951149 + 1208645 1208785 17127371
+140
+
+chain 12749 chr2 243199373 + 5141660 5146147 chr5 180857866 - 44949635 44952639 1949230
+55	641	482
+80	490	492
+69	238	238
+34	2813	1487
+67
+
+chain 11727 chr2 243199373 + 240838559 240838726 chr2 242951149 + 240487433 240487623 18443158
+86	35	58
+46
+
+chain 11295 chr2 243199373 + 1226909 1227026 chr2 242951149 + 1209530 1209647 20202652
+117
+
+chain 11288 chr2 243199373 + 1223295 1223413 chr2 242951149 + 1208990 1209108 3139804
+118
+
+chain 10759 chr2 243199373 + 90430195 90457119 chr2 242951149 - 151338126 151363320 2584
+28	2775	2822
+30	11958	12016
+40	1843	1850
+30	5080	3227
+47	361	361
+39	312	312
+38	383	383
+35	2707	2718
+36	1130	1130
+52
+
+chain 9553 chr2 243199373 + 89869741 89871237 chrY 57772954 + 11913136 11913399 23867669
+64	1367	134
+65
+
+chain 9489 chr2 243199373 + 110253717 110253937 chr2 242951149 + 106303434 106303606 24025084
+58	106	58
+56
+
+chain 9445 chr2 243199373 + 1223971 1224070 chr2 242951149 + 1208756 1208855 24130758
+99
+
+chain 8720 chr2 243199373 + 1222223 1225291 chr2 242951149 + 1208828 1209516 2041184
+278	99	99
+79	2535	155
+77
+
+chain 8428 chr2 243199373 + 90482794 90485288 chr2 242951149 - 155439240 155441007 1572933
+56	44	44
+58	400	417
+31	1832	1088
+73
+
+chain 8213 chr2 243199373 + 87720809 87720895 chr2 242951149 + 87507349 87507434 5227216
+41	1	0
+44
+
+chain 8069 chr2 243199373 + 90483014 90484786 chr2 242951149 - 155448229 155461339 1164914
+45	110	127
+2	735	1564
+52	750	11246
+68	4	0
+6
+
+chain 7776 chr2 243199373 + 1217508 1217592 chr2 242951149 + 1207753 1207837 7243988
+84
+
+chain 7421 chr2 243199373 + 1226334 1226411 chr2 242951149 + 1209439 1209516 27381596
+77
+
+chain 7358 chr2 243199373 + 89880461 89880538 chr22 49691432 - 33895115 33895192 27502443
+77
+
+chain 7257 chr2 243199373 + 1219025 1219100 chr2 242951149 + 1208570 1208645 27695248
+75
+
+chain 7028 chr2 243199373 + 1220317 1225128 chr2 242951149 + 1208603 1209423 1749868
+42	70	0
+111	1961	0
+99	2380	420
+148
+
+chain 6973 chr2 243199373 + 1223223 1223295 chr2 242951149 + 1208568 1208640 27324023
+72
+
+chain 6924 chr2 243199373 + 1220268 1221195 chr2 242951149 + 1208974 1209200 2111755
+49	743	42
+135
+
+chain 6823 chr2 243199373 + 243161637 243162225 chr6 170899992 - 4262 4850 1512
+39	405	405
+56	61	61
+27
+
+chain 6757 chr2 243199373 + 1224280 1224350 chr2 242951149 + 1209065 1209135 28694341
+70
+
+chain 6747 chr2 243199373 + 1219799 1219869 chr2 242951149 + 1208645 1208715 25148698
+70
+
+chain 6633 chr2 243199373 + 89847849 89847926 chr14 106368585 - 28607150 28607227 5517613
+77
+
+chain 6601 chr2 243199373 + 239685120 239685200 chr2 242951149 + 239350340 239350540 24829287
+66	1	121
+13
+
+chain 6531 chr2 243199373 + 89865276 89865345 chr16 88827254 - 55053025 55053094 29215386
+69
+
+chain 6312 chr2 243199373 + 111004064 111004130 chr2 242951149 - 132336069 132336135 211650
+66
+
+chain 6255 chr2 243199373 + 1226201 1226267 chr2 242951149 + 1209586 1209652 12280449
+66
+
+chain 6049 chr2 243199373 + 89847131 89847195 chr1 247249719 + 184405152 184405216 30439720
+64
+
+chain 6014 chr2 243199373 + 89850535 89853562 chr10 135374737 - 96209116 96209251 30527518
+57	2911	19
+59
+
+chain 5970 chr2 243199373 + 87721480 87727902 chr2 242951149 + 87501266 87503920 375724
+136	1955	628
+417	2657	546
+67	36	27
+57	474	105
+64	294	290
+36	0	52
+229
+
+chain 5911 chr2 243199373 + 87725643 87726005 chr2 242951149 + 87495962 87496324 1452475
+79	29	29
+211	17	17
+26
+
+chain 5902 chr2 243199373 + 90476920 90476981 chr2 242951149 - 155440689 155440750 30819911
+61
+
+chain 5764 chr2 243199373 + 1219128 1219198 chr2 242951149 + 1208603 1208673 13156733
+70
+
+chain 5625 chr2 243199373 + 87727023 87727089 chr2 242951149 + 87494216 87494282 1840679
+66
+
+chain 5449 chr2 243199373 + 1221033 1223650 chr2 242951149 + 1208828 1209415 2333010
+27	2353	323
+237
+
+chain 5435 chr2 243199373 + 87725371 87725531 chr2 242951149 + 87487864 87488024 3394118
+65	44	44
+51
+
+chain 5351 chr2 243199373 + 243152496 243152579 chr21 46944323 - 27 110 6622
+83
+
+chain 5348 chr2 243199373 + 5153354 5153410 chr2 242951149 + 239297362 239297418 32407088
+56
+
+chain 5167 chr2 243199373 + 89830753 89830808 chr16 88827254 - 55048203 55048258 32968623
+55
+
+chain 5034 chr2 243199373 + 90484935 90484987 chr2 242951149 - 155462101 155462153 29809699
+52
+
+chain 5012 chr2 243199373 + 89872838 89872891 chr4 191273063 + 48825877 48825930 33453820
+53
+
+chain 4920 chr2 243199373 + 89890558 89890609 chr2 242951149 + 89623647 89623698 33788797
+51
+
+chain 4886 chr2 243199373 + 90477063 90477242 chr2 242951149 - 155440771 155441314 25803008
+53	75	439
+51
+
+chain 4812 chr2 243199373 + 89870406 89870457 chr4 191273063 + 48802771 48802822 34140093
+51
+
+chain 4757 chr2 243199373 + 234058786 234058836 chr13 114142980 + 90951015 90951065 34330265
+50
+
+chain 4737 chr2 243199373 + 5145834 5145884 chr3 199501827 - 155139362 155139412 33407240
+50
+
+chain 4647 chr2 243199373 + 1226779 1226827 chr2 242951149 + 1209604 1209652 34630462
+48
+
+chain 4644 chr2 243199373 + 111007822 111007876 chr2 242951149 - 132339823 132339877 533729
+54
+
+chain 4607 chr2 243199373 + 5145066 5145350 chr3 199501827 + 191348934 191349218 1967131
+93	45	45
+57	39	39
+50
+
+chain 4552 chr2 243199373 + 1219473 1219520 chr2 242951149 + 1208598 1208645 27324024
+47
+
+chain 4467 chr2 243199373 + 5146638 5146689 chr8 146274826 + 70047993 70048044 10546953
+51
+
+chain 4382 chr2 243199373 + 239685380 239685447 chr2 242951149 + 239350400 239350507 10821439
+47	0	40
+20
+
+chain 4286 chr2 243199373 + 89847926 89848007 chr18 76117153 + 56250573 56250654 7293717
+81
+
+chain 4166 chr2 243199373 + 90482850 90482893 chr2 242951149 - 155471295 155471338 33373631
+43
+
+chain 4069 chr2 243199373 + 90483640 90483682 chr2 242951149 - 155471279 155471321 32448532
+42
+
+chain 4027 chr2 243199373 + 89848079 89848577 chr11 134452384 - 130303828 130304326 4308822
+70	372	372
+56
+
+chain 3915 chr2 243199373 + 89847485 89847537 chr4 191273063 - 120181520 120181572 9841777
+52
+
+chain 3887 chr2 243199373 + 1222921 1225400 chr2 242951149 + 1208756 1209205 3355598
+176	2233	203
+70
+
+chain 3870 chr2 243199373 + 5146741 5146807 chr4 191273063 - 106282745 106282811 8233254
+2	4	4
+60
+
+chain 3851 chr2 243199373 + 243174715 243174760 chr1 247249719 + 80163 80208 1584
+45
+
+chain 3776 chr2 243199373 + 1223932 1223971 chr2 242951149 + 1208577 1208616 29100476
+39
+
+chain 3766 chr2 243199373 + 1225991 1226030 chr2 242951149 + 1209516 1209555 18014514
+39
+
+chain 3567 chr2 243199373 + 89848026 89848188 chr6 170899992 - 102513053 102513215 4544108
+53	70	70
+39
+
+chain 3456 chr2 243199373 + 87720895 87724286 chr2 242951149 + 87506634 87508855 332559
+59	4	143
+126	0	22
+162	9	0
+89	28	26
+108	1252	650
+77	1179	461
+298
+
+chain 3166 chr2 243199373 + 90482349 90482483 chr2 242951149 - 155440886 155440924 3921176
+20	96	0
+18
+
+chain 3114 chr2 243199373 + 1223097 1223130 chr2 242951149 + 1209002 1209035 21012522
+33
+
+chain 3110 chr2 243199373 + 1225750 1225960 chr2 242951149 + 1209065 1209275 3693305
+210
+
+chain 2962 chr2 243199373 + 16340723 16340754 chr16 88827254 + 56242121 56242152 7757072
+31
+
+chain 2946 chr2 243199373 + 1225580 1225611 chr2 242951149 + 1209315 1209346 16952082
+31
+
+chain 2859 chr2 243199373 + 243189340 243189373 chr2 242951149 - 213544 213577 2192
+33
+
+chain 2638 chr2 243199373 + 5146355 5146383 chr9 140273252 + 31324189 31324217 27516381
+28
+
+chain 2632 chr2 243199373 + 87721683 87721719 chr2 242951149 + 87489021 87489057 886310
+36
+
+chain 2630 chr2 243199373 + 5144933 5144985 chr19 63811651 + 23161927 23161979 24515130
+52
+
+chain 2538 chr2 243199373 + 16338477 16338504 chr3 199501827 - 154040818 154040845 35425972
+27
+
+chain 2527 chr2 243199373 + 111053817 111053884 chr2 242951149 + 110544305 110544372 1691975
+67
+
+chain 2476 chr2 243199373 + 5146689 5146741 chr2 242951149 - 88851718 88851770 6471285
+52
+
+chain 2465 chr2 243199373 + 16260450 16260476 chr14 106368585 - 56125663 56125689 35442474
+26
+
+chain 2448 chr2 243199373 + 90475509 90477186 chr2 242951149 - 155452726 155455668 5069202
+50	704	1477
+39	832	1324
+52
+
+chain 2256 chr2 243199373 + 89865421 89865445 chr4 191273063 + 48820096 48820120 35487368
+24
+
+chain 2132 chr2 243199373 + 90371525 90371566 chr2 242951149 + 90975643 90975684 3405316
+41
+
+chain 2046 chr2 243199373 + 87729180 87729211 chr2 242951149 + 87489147 87489178 2812396
+31
+
+chain 2012 chr2 243199373 + 16273933 16273955 chr11 134452384 + 22938127 22938149 7662326
+22
+
+chain 1994 chr2 243199373 + 5144152 5145822 chr11 134452384 + 133004933 133006812 2924035
+46	1530	1739
+23	20	20
+51
+
+chain 1907 chr2 243199373 + 5146585 5146633 chr1 247249719 - 174030724 174030772 3467396
+48
+
+chain 1894 chr2 243199373 + 1220990 1221013 chr2 242951149 + 1208785 1208808 13156732
+23
+
+chain 1847 chr2 243199373 + 87729147 87729180 chr2 242951149 + 87508312 87508345 2784752
+33
+
+chain 1616 chr2 243199373 + 5141194 5141259 chr4 191273063 + 140068684 140068749 14298254
+65
+
+chain 1606 chr2 243199373 + 89847307 89847375 chr6 170899992 + 54305106 54305174 19190580
+68
+
+chain 1373 chr2 243199373 + 243172974 243173045 chr8 146274826 + 8401 8472 3798112
+71
+
+chain 1350 chr2 243199373 + 87719705 87727637 chr2 242951149 + 87486442 87489057 666335
+5	4	8
+60	6231	0
+175	909	1819
+190	64	64
+294
+
+chain 1237 chr2 243199373 + 5143151 5144336 chr3 199501827 - 33955506 33956705 3724972
+50	1070	1084
+65
+
+chain 1182 chr2 243199373 + 1222834 1225214 chr2 242951149 + 1208599 1208809 9180420
+46	2248	78
+86
+
+chain 1157 chr2 243199373 + 87726368 87726988 chr2 242951149 + 87492753 87493373 434529
+59	53	53
+165	67	67
+36	57	57
+183
+
+chain 1107 chr2 243199373 + 5141765 5144570 chr1 247249719 + 5005582 5008225 2100127
+50	2701	2539
+54
+
+chain 1007 chr2 243199373 + 5142524 5142584 chr7 158821424 - 115940368 115940428 3379044
+60
+
+chain 998 chr2 243199373 + 234471343 234471369 chr18 76117153 + 53315026 53315052 2684166
+26
+
+chain 997 chr2 243199373 + 1223799 1223839 chr2 242951149 + 1209424 1209464 2284434
+40
+
+chain 932 chr2 243199373 + 87725722 87725751 chr2 242951149 + 87499077 87499106 1733344
+29
+
+chain 867 chr2 243199373 + 1226560 1226598 chr2 242951149 + 1209385 1209423 17548334
+38
+
+chain 822 chr2 243199373 + 5144726 5144801 chr2 242951149 - 76674151 76674226 3649555
+75
+
+chain 767 chr2 243199373 + 5141372 5141411 chr7 158821424 + 51905543 51905582 3310848
+39
+
+chain 651 chr2 243199373 + 5141336 5141372 chr5 180857866 - 59015526 59015562 2717102
+36
+
+chain 561 chr2 243199373 + 5140901 5140953 chr6 170899992 + 131686128 131686180 4225085
+52
+
+chain 545 chr2 243199373 + 90414124 90414152 chr7 158821424 - 94210194 94210222 18407154
+28
+
+chain 270 chr2 243199373 + 89868258 89868320 chrY 57772954 + 11916008 11916070 28746465
+62
+
+chain 5644665978 chr20 63025520 + 60000 62965520 chr20 62435964 + 8000 62435964 20
+26259569	3100000	1765661
+234339	150000	1000000
+4004088	1	0
+6459	244	0
+37810	2	0
+1044573	50000	20000
+9411883	8	2
+362	1	0
+11607353	1	0
+1301304	0	1
+31036	9	0
+1151	2	0
+1088	1	1
+29	1	1
+2509	2	0
+407	0	1
+40	1	1
+3787164	50000	27050
+71932	50000	110000
+694117	1	0
+1008033
+
+chain 3228736998 chr21 48129895 + 10697896 48119895 chr21 46944323 + 9719767 46944323 23
+490233	3150000	3050000
+19828060	1	0
+8789369	48801	0
+222468	500	500
+22014	1500	1500
+1381822	48641	0
+3438590
+
+chain 42537850 chr21 48129895 + 9411193 10647896 chr21_random 1679693 + 281005 1255172 87
+184355	489372	50000
+131056	281918	458754
+150002
+
+chain 16006699 chr21 48129895 + 9825437 10497894 chr21_random 1679693 - 0 756441 94
+158053	0	149427
+56	1	1
+500	1	1
+35	1	1
+276	1	1
+92	1	1
+413	12	12
+944	1	1
+31	1	1
+185	5	5
+93	1	1
+63	1	1
+959	0	1
+268	1	1
+33	1	1
+115	1	0
+12	0	2
+56	1	1
+99	1	1
+49	1	1
+65	1	1
+32	1	13
+425	1	1
+77	2	0
+252	0	7
+72	1	1
+96	1	1
+44	1	1
+197	7	7
+86	1	1
+32	1	1
+423	1	1
+26	1	1
+758	1	1
+77	1	1
+217	3	0
+50	1	1
+290	1	1
+112	1	1
+66	14	14
+116	18	22
+727	19	19
+140	4	0
+393	1	1
+28	1	1
+50	2	0
+38	6	1
+21	1	1
+80	1	1
+71	1	1
+179	1	1
+35	1	1
+69	1	1
+20	1	1
+216	1	1
+31	1	1
+182	1	1
+43	1	1
+97	1	1
+22	1	1
+87	1	1
+66	1	1
+72	1	1
+68	1	1
+312	1	1
+28	1	1
+478	1	1
+111	1	1
+191	1	1
+18	1	1
+98	1	2
+29	2	1
+57	1	1
+44	1	6
+74	1	1
+79	77	78
+186	1	1
+107	1	1
+202	2	2
+135	1	1
+95	0	3
+93	1	0
+48	5	0
+170	1	1
+43	1	0
+260	1	1
+23	1	1
+312	1	0
+26	1	0
+28	0	1
+87	0	10
+157	8	8
+900	1	1
+56	1	1
+235	1	1
+81	1	1
+156	1	1
+61	1	1
+156	1	1
+48	1	1
+65	12	12
+89	1	1
+158	2	2
+106	3	1
+375	0	2
+35	1	1
+73	1	1
+33	1	1
+392	2	0
+602	1	1
+66	1	1
+375	1	1
+55	1	1
+207	1	1
+25	2	2
+459	7	7
+188	1	3
+210	3	3
+28	0	4
+980	1	1
+15	1	1
+350	20	0
+636	0	4
+43	1	0
+539	63	64
+80	3	0
+142	8	7
+247	1	0
+908	1	1
+20	1	1
+128	0	1
+301	4	0
+56	2	2
+658	1	1
+34	1	1
+184	8	8
+162	0	2
+64	0	1
+80	1	1
+34	1	1
+121	1	1
+21	1	1
+374	1	1
+130	0	1
+47	1	1
+68	1	1
+35	4	0
+361	1	0
+73	1	1
+44	1	1
+392	1	1
+70	1	1
+76	1	1
+48	1	1
+216	1	1
+54	1	1
+67	4	4
+282	1	1
+44	1	1
+73	15	15
+166	4	0
+338	1	1
+27	1	1
+243	1	1
+101	1	1
+344	1	1
+51	1	1
+367	1	1
+35	0	1
+199	1	1
+18	1	1
+153	13	13
+102	0	1
+125	1	1
+49	1	1
+102	7	7
+100	18	18
+316	20	20
+151	0	2
+21	0	1
+575	1	0
+60	1	1
+60	1	1
+441	24	24
+364	1	0
+57	1	1
+158	10	10
+197	1	1
+49	1	0
+13	0	1
+5	1	1
+478	1	0
+244	22	22
+91	1	1
+80	5	5
+130	1	1
+26	1	1
+405	1	1
+51	1	1
+235	11	11
+330	1	1
+66	1	1
+85	342	17
+157	26	26
+261	1	1
+38	2	2
+824	20	20
+252	12	0
+119	1	1
+42	1	1
+1237	23	22
+103	1	1
+70	1	1
+155	1	1
+26	0	1
+80	1	1
+468	1	1
+60	1	1
+139	1	1
+53	2	2
+194	1	1
+35	1	1
+94	1	1
+56	1	1
+128	1	1
+40	1	1
+124	0	1
+54	1	1
+75	1	1
+79	1	1
+66	1	1
+82	0	1
+88	1	1
+146	0	3
+60	1	1
+67	2	2
+36	5	5
+147	1	1
+32	1	1
+185	1	1
+44	1	1
+68	40	15
+201	1	1
+37	1	1
+387	1	1
+18	1	1
+103	339913	274830
+131918
+
+chain 2365142 chr21 48129895 + 9686364 9760752 chr1 247249719 - 105115380 105189719 169
+453	1	1
+62	1	1
+312	9	9
+152	1	1
+34	1	1
+205	1	1
+109	44	0
+14	7	65
+203	5	5
+26	1	1
+70	1	1
+17	1	1
+847	1	1
+49	1	1
+99	1	1
+87	1	1
+51	1	1
+26	1	1
+374	1	1
+43	0	6
+139	1	1
+128	1	1
+54	1	1
+45	2	0
+17	1	1
+75	1	1
+59	1	1
+210	1	1
+70	1	1
+158	43	43
+56	12	12
+109	1	1
+48	5	5
+116	1	1
+49	1	1
+307	1	1
+45	1	1
+440	5	5
+106	9	9
+784	1	1
+42	1	1
+228	0	1
+114	17	17
+88	11	11
+161	1	1
+38	1	1
+825	2	2
+38	1	1
+105	22	22
+81	1	1
+29	1	1
+300	23	23
+147	1	1
+26	1	1
+164	1	1
+35	1	1
+227	6	6
+56	2	2
+109	1	1
+25	4	0
+116	15	23
+172	1	1
+40	1	1
+68	15	15
+158	7	7
+349	14	14
+133	1	1
+39	1	1
+145	12	12
+60	1	1
+43	1	1
+101	21	21
+307	1	1
+42	1	1
+93	1	1
+162	1	1
+143	1	1
+40	1	1
+54	1	1
+107	9	10
+319	1	1
+43	4	4
+200	1	1
+18	1	1
+127	1	1
+90	1	1
+250	3	3
+93	148	1
+443	0	1
+77	9	9
+295	1	1
+59	1	1
+438	31	31
+127	3	0
+88	1	1
+109	7	8
+79	14	14
+112	10	8
+114	1	1
+94	1	1
+150	10	7
+69	1	1
+110	1	1
+17	1	0
+222	0	1
+195	1	1
+16	1	0
+89	1	1
+123	38	0
+43	1	1
+83	1	1
+47	3	4
+64	0	3
+38	1	1
+268	1	1
+27	1	1
+230	17	17
+252	1	1
+24	0	3
+168	1	1
+41	5	0
+50	1	1
+212	9	9
+40	29	0
+271	1	1
+48	1	1
+124	1	1
+57	1	1
+125	16	16
+136	29	29
+157	1	1
+27	7	0
+482	10	4
+158	1	1
+62	1	1
+371	1	1
+83	1	1
+120	1	1
+45	1	1
+189	0	1
+84	1	1
+103	18	18
+494	1	1
+55	3	0
+139	1	1
+264	18	18
+75	2	3
+130	1	1
+97	1	1
+193	1	1
+25	1	1
+167	1	1
+49	1	1
+62	16	16
+65	13	13
+62	1	1
+101	1	1
+60	1	1
+50	1	1
+307	9	9
+131	13	13
+94	1	1
+78	1	1
+132	1	1
+27	1	1
+358	1	1
+21	1	1
+466	14	14
+590	1	1
+34	1	1
+242	1	1
+29	1	1
+116	1	1
+44	1	1
+117	1	1
+67	2	1
+71	1	1
+32	1	1
+506	18	18
+88	1	1
+27	1	1
+78	0	11
+215	1	1
+77	1	1
+291	1	1
+56	3	3
+126	1	1
+42	1	1
+332	9	9
+280	6	9
+641	15	15
+59	6	10
+31	1	1
+62	1	1
+40	1	1
+298	1	1
+40	1	1
+146	1	1
+66	1	0
+757	2	0
+169	1	1
+65	1	0
+285	1	1
+20	1	1
+109	1	1
+67	1	1
+68	1	1
+32	1	1
+93	4	4
+147	0	14
+646	0	1
+544	8	8
+47	1	0
+141	14	14
+678	1	0
+154	0	1
+346	1	1
+73	1	1
+232	5	5
+113	1	1
+32	2	0
+23	1	1
+92	10	10
+1121	1	1
+143	1	1
+300	1	1
+49	1	1
+392	5	5
+242	1	1
+21	1	1
+369	1	1
+67	1	1
+47	0	1
+618	23	23
+565	1	1
+140	1	1
+247	1	1
+41	1	1
+50	1	1
+18	1	1
+65	1	1
+66	1	1
+108	0	4
+158	1	1
+105	1	1
+70	1	1
+25	6	8
+77	1	1
+323	1	1
+28	1	1
+258	1	1
+47	1	1
+393	1	1
+72	1	1
+149	13	13
+142	1	0
+60	0	1
+78	4	4
+100	1	1
+51	1	1
+156	1	1
+20	1	1
+510	1	1
+22	1	0
+67	1	1
+54	1	1
+45	1	1
+133	1	1
+23	1	1
+63	1	1
+32	1	1
+349	1	1
+15	1	1
+103	1	1
+36	1	1
+119	1	1
+47	1	1
+312	4	4
+66	13	13
+357	0	76
+20	1	1
+177	1	1
+91	1	1
+52	1	1
+36	1	1
+141	10060	10099
+90	1	1
+49	1	1
+212	1	1
+20	1	1
+286	1	1
+48	2	1
+50	1	1
+67	8	8
+63	1	1
+30	1	1
+93	1	1
+48	1	1
+129	1	1
+46	1	1
+455	1	1
+46	3	0
+84	1	1
+39	0	1
+229	2	11
+79	4	4
+731	17	16
+725	8	8
+249	1	1
+78	1	1
+1065	3	0
+735	0	1
+124	10	10
+51	1	1
+35	1	1
+315	25	25
+749	6	6
+343	1	1
+29	1	1
+386	1	1
+24	1	1
+407	1	0
+73	1	1
+708	1	1
+71	0	1
+16	1	1
+92	1	1
+25	1	1
+447	14	14
+190	85	85
+60	1	1
+66	1	1
+238	1	1
+87	5	5
+118	7	7
+696	0	12
+49	1	1
+823	1	1
+77	1	1
+154	0	3
+102	12	12
+698	1	1
+21	1	1
+591	1	1
+16	1	1
+59	1	1
+27	1	1
+114	1	0
+593	1	1
+30	1	1
+1351	1	1
+17	1	1
+77	6	0
+647	1	1
+23	1	1
+235	1	1
+39	1	1
+141	1	1
+80	5	5
+181	10	11
+1091	1	1
+58	0	1
+19	1	1
+305	0	1
+429	17	17
+107	1	1
+25	1	1
+156	5	5
+22	1	1
+188
+
+chain 1441791 chr21 48129895 + 9645548 9775437 chr21_random 1679693 + 696416 826305 252
+40816	1341	1341
+44	2893	2893
+43	8663	8663
+148	1323	1323
+31	1767	1767
+38	1629	1629
+29	781	781
+29	25619	25619
+10060	6346	6346
+25	3590	3590
+85	9904	9904
+14685
+
+chain 891297 chr21 48129895 + 9995689 10034920 chr21_random 1679693 + 191774 231005 206
+77	9866	9866
+63	13134	13134
+342	157	157
+26	5919	5919
+40	750	750
+8857
+
+chain 2615495 chr21_gl000210_random 27682 + 0 27682 chr21_random 1679693 - 1650984 1679693 1058
+9933	367	719
+17272	0	675
+110
+
+chain 25569 chr21_gl000210_random 27682 + 10033 10300 chr21_random 1679693 - 1660317 1660584 5767478
+267
+
+chain 3320966530 chr22 51304566 + 16050000 51244566 chr22 49691432 + 14430000 49591432 22
+647850	150000	150000
+3661581	100000	50000
+15278437	18	0
+294	36	0
+1407	1	1
+46	1	1
+6626947	4	2
+1759	1	1
+43	1	1
+1367363	10613	11998
+7858	0	4
+809337	20	0
+6305	0	20
+6703	2669	50000
+4247674	0	10618
+1611	2719	0
+35235	131	0
+12642	0	4
+45595	9	85
+19564	506	0
+165499	7	5
+1103946	60575	16700
+644	2	0
+319796	1155	1600
+17927	15406	19700
+464629
+
+chain 11044 chr22 51304566 + 50772606 50772840 chr1 247249719 + 28744016 28744317 20648865
+55	103	170
+76
+
+chain 18404394637 chr3 198022430 + 60000 197962430 chr3 199501827 + 35000 199446827 3
+13552792	0	1
+585083	0	1
+2092	1	2
+71	0	1
+31067262	0	1
+90	1	0
+5628461	0	15
+788	1	0
+3676	0	2
+35	1	1
+4682	1	0
+1295	0	5
+437	53	42
+326	0	2
+3309	1	1
+40	1	1
+998	0	3
+3584	5	0
+930	5	7
+845	1	1
+28	2	1
+303	0	1
+507	0	5
+5088	1	0
+2185	10046	10048
+949	4	4
+35	1	1
+2874	0	1
+6717	0	1
+2823	1	0
+703	0	4
+5143	1	0
+2490	10	10
+162	7	7
+6308	0	15
+15177535	152352	260003
+2532	1	0
+1633	2	2
+24207544	3000000	4400000
+60453436	0	4
+40076813	20999	20000
+8195	1	1
+44	1	1
+1408	1	1
+33	1	1
+172	3	4
+25	1	1
+538	13	13
+173	1	1
+27	1	1
+636	1	1
+28	1	1
+470	3	3
+112	1	1
+375	1	1
+26	26	0
+115	78	0
+52	23	0
+104	26	0
+15	231	0
+56	1	1
+20	1	1
+815	16	16
+484	1	1
+49	18	0
+509	4	3
+23	1	1
+391	1	1
+44	1	1
+1278	0	4
+32	1	1
+263	4	0
+27	1	1
+2416	0	2
+3184	43	43
+1150	13	13
+736	1	1
+47	1	1
+1416	1	1
+20	1	1
+1020	1	1
+25	1	1
+482	5	0
+716	1	0
+1697	1	1
+29	1	1
+1270261	23108	27000
+40930	1	0
+17455	1	1
+28	4	4
+43	0	491
+1679	1	1
+33	7	5
+29	1	3
+54863	53	16
+7653	2	2
+29	2	2
+15	0	30
+180	0	75
+215	45	0
+360	915	0
+6188	96	0
+17	288	0
+1388	1	1
+37	1	1
+7956	0	1
+374	0	1
+2442058
+
+chain 905554 chr3 198022430 + 50925386 50935027 chr3 199501827 - 148591827 148601470 3167
+1111	0	6
+2584	0	1
+5889	6	1
+51
+
+chain 274603 chr3 198022430 + 195356374 195379482 chr3 199501827 - 629997 657219 690
+621	1	1
+42	1	1
+893	1	121
+66	1	1
+693	1	1
+27	1	1
+761	1	1
+79	2	2
+297	1	1
+40	1	1
+643	1	1
+22	1	1
+410	8	9
+110	1	1
+16	0	5
+314	3	0
+1846	4	7
+39	1	1
+420	10	9
+335	6	0
+238	0	1
+76	1	0
+310	1	2
+175	1	1
+17	1	1
+268	1	1
+46	1	1
+114	1	1
+19	1	1
+127	8	8
+30	1	1
+207	6	6
+62	9	9
+505	22	22
+160	1	1
+34	1	1
+187	1	1
+138	0	1
+844	1	1
+103	0	1
+65	3459	3402
+90	4	4
+90	42	794
+52	478	4
+78	154	154
+28	235	0
+59	1501	5454
+143	19	19
+425	7	54
+39	46	0
+75	8	8
+73	1	95
+58	1	1
+51	16	63
+140	1	1
+33	1	1
+682	1	1
+68	1	1
+147	1	1
+82	1	1
+119	33	0
+262	0	1
+54	1	0
+13	56	0
+111	5	5
+722	1	1
+19	1	1
+60	1	1
+33	1	0
+7	1	1
+108	0	2
+302	1	1
+68	1	0
+42	1	1
+50	1	1
+80	1	0
+95	1	1
+19	1	1
+119	0	1
+493	16	16
+316
+
+chain 30227 chr3 198022430 + 66156466 66156782 chr5 180857866 - 15729243 15729559 4617547
+316
+
+chain 25764 chr3 198022430 + 195503126 195503723 chr3 199501827 + 196988790 196989012 1952307
+75	360	0
+127	20	5
+15
+
+chain 19039 chr3 198022430 + 195503723 195504023 chr3 199501827 + 196988637 196988937 1894839
+300
+
+chain 11786 chr3 198022430 + 195373997 195374119 chr3 199501827 - 651916 652038 19355983
+122
+
+chain 9624 chr3 198022430 + 195503246 195503561 chr3 199501827 + 196988205 196988400 2003832
+53	137	2
+73	4	19
+48
+
+chain 7908 chr3 198022430 + 195510214 195510615 chr3 199501827 + 196993313 196993714 919394
+96	17	17
+288
+
+chain 6921 chr3 198022430 + 66275488 66275560 chr6 170899992 + 144236219 144236291 28346484
+72
+
+chain 6012 chr3 198022430 + 66274973 66275036 chr15 100338915 - 38411650 38411713 30540003
+63
+
+chain 5039 chr3 198022430 + 66276813 66276866 chr9 140273252 + 71084115 71084168 33364454
+53
+
+chain 4902 chr3 198022430 + 66152713 66152764 chr11 134452384 + 5803379 5803430 33869306
+51
+
+chain 3381 chr3 198022430 + 195371524 195371562 chr3 199501827 - 645118 645156 13662757
+38
+
+chain 3356 chr3 198022430 + 50925108 50925187 chr3 199501827 - 92152745 92152824 20266108
+79
+
+chain 2109 chr3 198022430 + 195371614 195371638 chr3 199501827 - 645161 645185 16027164
+24
+
+chain 1800 chr3 198022430 + 195503201 195503246 chr3 199501827 + 196989165 196989195 4219824
+23	17	2
+5
+
+chain 1295 chr3 198022430 + 195372257 195372308 chr3 199501827 - 2286585 2286636 21843906
+51
+
+chain 17653654354 chr4 191154276 + 10000 191029082 chr4 191273063 + 0 191263063 4
+1413146	71672	51000
+5369	6	5
+65	1	1
+67	1	1
+425	1	1
+32	1	1
+175	1	1
+34	1	1
+5092	1	1
+46	1	1
+1396	15	15
+1446	1	0
+1679	13	13
+3443	0	1
+586	1	1
+38	1	1
+18	21	0
+1582	6	0
+202	3	0
+92	0	6
+187	9	0
+4054	1	1
+71	1	1
+1413	1	83
+51	7	7
+105	7	7
+53	0	41
+81	1	42
+41	0	41
+37	0	41
+3274	1	94
+114	0	1116
+921	2	0
+935	0	55
+3639	15	15
+1167	0	3
+44	29	0
+44	0	29
+5146	1	1
+42	1	1
+3831	3	0
+23	1	1
+4171	6	6
+796	165	0
+196	99	0
+94	33	0
+183	8	6
+107	2	2
+21	2	0
+62	68	1
+32	15	14
+81	18	18
+55	1	0
+17	67	1
+188	133	0
+44	67	0
+43	35	0
+3289	18	18
+298	1	0
+373	1	0
+2965	1	1
+30	23	0
+1718	38	0
+98	38	0
+53	44	7
+116	0	77
+272	1	1
+70	1	1
+1591	49	49
+360	33	23
+2400	1	1
+94	1	1
+6002	1	1
+16	1	1
+776	0	1
+324	46	46
+433	0	51
+53	27	1
+2181	4	1
+57	1	1
+1969	0	10
+4188	11	11
+1595	18	0
+2050	109	0
+4319	7	0
+50	4	0
+1464	1	3
+4156	0	2
+5455	2	3
+129	4	4
+9082	1	0
+786	20	20
+1506	1	0
+252	7	8
+17512	1	50
+56	0	1
+2474	52	69
+75	30	0
+61	0	16
+11	0	15
+41	1	1
+133	0	16
+79	17	0
+16	29	0
+3375	1	0
+969	4	0
+1623	11	11
+1065	3	0
+2934	0	8
+2323	181	0
+2290	0	1
+1641	1	6
+1955	1	0
+68	1	1
+347	1	1
+40	1	1
+1553	0	6
+678	16	16
+92	33	0
+390	0	4
+1147	1	0
+1948	4	4
+4296	1	1
+16	1	1
+955	1	1
+47	1	1
+1555	0	1
+2251509	0	81122
+171	1	1
+48	1	1
+718	0	1
+2789	1	1
+27	1	1
+1601	0	4
+1907	2	0
+31	1	5
+16	0	4
+76	2	0
+13	4	0
+27	1	0
+12	1	9
+1772	6	0
+22	1	1
+946	1	1
+24	1	1
+1245	0	1
+3231	1	1
+41	1	1
+736	4	4
+912	1	1
+18	1	1
+11270	0	3
+2704	1	1
+41	1	1
+1812	6	5
+1477	11	0
+1744	6	6
+2039	0	4
+2188	1	1
+48	1	1
+1704	1	1
+73	1	1
+2265	12	12
+553	1	1
+49	1	1
+67	1	1
+33	1	1
+3935	0	5
+15	0	1
+780	1	0
+1260	1	0
+4204	25	0
+862	14	14
+7114	1	1
+70	1	1
+169	1	0
+43	1	1
+145	1	1
+39	3	0
+8	1	1
+753	1	0
+1535	41	41
+679	1	1
+21	1	1
+1605	1	1
+19	1	2
+392	1	1
+29	0	1
+3673	0	1
+145	14	14
+39	1	0
+1246	1	0
+2302	0	1
+1554	9	9
+4537	1	0
+1064	0	2
+2051	0	1
+1130	2	0
+164	0	1
+1972	1	0
+18	3	3
+2597	1	1
+46	3	3
+196	1	1
+17	1	1
+60	4	4
+187	4	4
+46	1	1
+692	0	1
+3382	41	41
+497	3	3
+15	1	1
+486	14	14
+1709	0	8
+169	0	1
+597	1	1
+18	7	0
+3423937	1	0
+1295496	1	1
+26	1	1
+760	591802	150000
+22468468	1	1
+27	1	1
+2592	2	0
+33	1	1
+2065	0	3
+1050	11	11
+1046	9	3
+3263	0	1
+906	0	1
+1643	0	6
+1181	1	0
+475	5	0
+2522	0	4
+407	1	0
+517	77	77
+1122	36199	70999
+976587	26528	59000
+7703	4	0
+4545	9	9
+4740	1	0
+1862	0	1
+3316	3	7
+51	14	14
+1066	1	0
+1795	0	1
+569	0	1
+2895	1	1
+39	1	1
+461	0	3
+3168	6	6
+2197	0	1
+6774	2	0
+2504	2	0
+1247	1	1
+45	1	1
+2415	17	17
+4792	36	36
+3387	20	20
+272	10	10
+420	1	1
+34	1	1
+7961	0	4
+1973	1	1
+45	0	1
+529	0	1
+603	1	0
+18	1	1
+606	4	0
+65	1	25
+41	0	8
+517	1	0
+1400	41	38
+3786	1	0
+228	0	3
+1026	1	1
+49	1	1
+3336	3	0
+951	1	1
+77	1	2
+441	2	1
+1833	9	9
+301	5	5
+2787	17	17
+1747	0	1
+3040	9	2
+81	10	10
+86	0	2
+2113	45	45
+7352791	1606	20000
+1651	0	2
+45	16	0
+13956	8	0
+1947	3	0
+1255	1	1
+38	1	0
+1778	4	0
+22	1	0
+1045	0	6
+1327	1	0
+5775	1	1
+18	1	1
+1933	0	1
+1716	13	13
+255	0	1
+124	3	0
+792	5	0
+1521	1	1
+64	1	1
+9005617	150000	150000
+171176	3000000	3000000
+7074452	62111	50000
+5257	1	0
+2845	0	2
+1387	1	0
+114	0	1
+2385	4	0
+65	6	6
+62	0	4
+18	1	0
+100	51	0
+9781577	0	351994
+1903288	0	184275
+3925704	13	13
+435	1	1
+21	1	1
+838	1	0
+281	35	35
+491	6	6
+74	1	1
+43	1	1
+652	29839	30000
+13847966	1	0
+14069801	0	2
+8504	1	0
+32265	0	8
+12730	2	0
+35327	14	12
+1503	0	1
+1334	0	1
+759	1	0
+10036	1	7
+9912	17	18
+2523	0	1
+1321	1	0
+8984	0	2
+5505	20	20
+9694	6	6
+22003	0	9
+578	1	0
+5166	0	2
+92208	5	2
+8	0	1
+5	2	0
+110	0	4
+848	7	6
+2247	1	3
+3770	1	0
+5719	2	0
+2511	1	0
+1557	1	0
+5812	1	0
+3607	1	0
+7405	0	1
+11075	1	0
+2794	0	1
+2340	0	1
+429	1	0
+233	27	27
+262	0	2
+2397	0	5
+371	0	11
+1376	0	1
+2416	0	8
+210	1	1
+20	1	1
+5104	1	1
+20	1	1
+525	0	2
+836	1	0
+2094	0	1
+2213	0	3
+327	6	9
+1711	45	45
+837	1	1
+57	1	1
+1618	1	0
+1400	0	4
+254	2	0
+93	0	10
+755	6	0
+192	1	0
+2378	1	0
+1753	0	3
+644	14	14
+1244	4	0
+30	1	1
+1136	14	14
+2450	0	4
+3624	3	31
+456	14	14
+1076	8	7
+68	1	1
+20	1	1
+145	1	1
+68	0	1
+12	1	0
+10	1	0
+11	0	1
+35	0	1
+5	1	0
+11	2	1
+32	7	6
+35	0	1
+8722	0	1
+888	4	0
+456	0	3
+45	1	0
+151	13	13
+756	1	0
+203	7	8
+140	1	1
+20	1	1
+308	0	5
+1020	1	0
+1258	1	0
+160	2	0
+1411	1	1
+22	1	1
+1180	12	12
+4521	2	0
+1153	0	27
+4956	0	3
+1392	1	1
+47	1	1
+3854	1	2
+130	0	1
+2633	0	2
+3030	1	0
+2343	1	0
+1748	45	0
+731	0	2
+1336	11	9
+3899	6	0
+436	0	1
+981	1	0
+1326	1	0
+382	0	4
+1081	0	10
+81	1	1
+142	2	0
+5976	1	1
+26	1	1
+377	22	22
+86	1	0
+55	1	1
+93	1	1
+374	4	0
+38	6	0
+3944	0	347
+1034	1	1
+27	1	1
+60	0	2
+2581	0	3
+3882	4	0
+1790	1	0
+20	1	1
+356	0	1
+4244	5	5
+36	1	1
+2232	2	2
+42	1	1
+4462	2	0
+1611	0	1
+1290	2	0
+110	0	1
+1466	1	0
+357	0	3
+850	0	12
+13547766	1	0
+3724943	0	2
+46473408	1	0
+1696	1	1
+28	1	1
+1629	4	0
+666	0	4
+13464	12874	30000
+8520008	0	2
+1107	1	1
+15	1	1
+1892	4	0
+6798	2	0
+1793	1	1
+25	3	0
+421	0	389
+787	0	2
+545	2	0
+54	0	1
+143	1	1
+39	1	1
+89	1	1
+29	0	1
+171	1	1
+46	0	1
+192	1	1
+33	1	1
+336	18	18
+2226	1	0
+107	1	1
+29	1	1
+218	0	1
+175	5	6
+1407	1	1
+52	1	1
+8851	0	1
+14427	0	4
+1737	0	22
+5806	0	1
+1115	1	1
+29	2	0
+3395	1	0
+386	38	38
+2740	2	0
+522	0	1
+24	1	1
+658	0	4
+5724	9	9
+1209	1	0
+5380	0	1
+97	0	1
+853	0	4
+79	11	5
+2728	7	6
+3754	13	17
+1363	0	1
+1025	0	1
+1811	1	0
+7507	4	0
+1184	0	3
+763	0	1
+797	0	3
+293	0	2
+2488	1	0
+335	1	0
+9959	0	1
+3255	0	1
+1322	1	0
+8118	0	2
+3326	0	2
+632	0	1
+63	5	0
+1886	12	12
+1110	1	0
+9582	1	0
+14742673	3013	0
+39686
+
+chain 9245037 chr4 191154276 + 8829368 8925617 chr4_random 842648 + 239789 336038 353
+96249
+
+chain 1255876 chr4 191154276 + 9214880 9257600 chr4 191273063 + 8933741 8943231 721
+156	22	22
+1030	14	14
+303	27	27
+166	4935	184
+220	23	24
+72	54	54
+771	13	13
+270	4744	0
+2627	17	17
+289	4743	0
+890	4745	0
+772	9500	0
+268	4749	1
+266	11	11
+1023
+
+chain 912330 chr4 191154276 + 9211690 9265763 chr4 191273063 + 8940042 8979863 947
+75	220	220
+51	122	122
+54	54	54
+51	167	167
+180	47	47
+70	24	24
+94	37	37
+257	59	59
+316	11	11
+163	60	60
+53	61	61
+95	21	21
+109	24	24
+217	32	32
+186	47	47
+233	1926	1924
+88	13	13
+123	125	126
+1453	4747	0
+2227	0	1
+278	535	535
+213	87	87
+92	7	7
+755	18715	9222
+268	6439	6434
+1089	14	14
+243	9	9
+78	4	4
+157	214	209
+200	23	24
+72	5972	5972
+655	413	413
+1441	14	14
+243	9	9
+78	4	4
+157	213	209
+200	23	24
+72	54	54
+771	13	13
+119	17	17
+221
+
+chain 676976 chr4 191154276 + 191033807 191044200 chr4 191273063 - 191263147 191273063 1558
+68	4	0
+34	1	1
+323	3	3
+31	1	1
+807	1	1
+26	1	1
+526	2	3
+34	1	0
+704	1	0
+6	1	0
+240	1	0
+237	2	0
+8	1	1
+371	10	0
+264	1	0
+205	1	1
+57	1	0
+601	1	1
+15	1	1
+1214	4	8
+1661	3	0
+94	1	1
+50	1	1
+355	15	15
+638	1	1
+54	1	1
+54	8	9
+323	67	9
+85	0	1
+96	1	1
+58	1	1
+35	1	0
+31	1	1
+86	1	1
+30	1	1
+76	1	1
+40	1	1
+121	282	27
+49	53	0
+63	92	0
+52
+
+chain 512088 chr4 191154276 + 8956990 9037962 chr4 191273063 + 9100119 9179836 26299
+71	118	113
+60	152	152
+88	33	33
+136	71	71
+85	43	43
+87	66	66
+92	87	87
+88	187	185
+156	1	81
+67	128	129
+76	143	143
+50	44	44
+212	52	52
+64	13	16
+267	79	79
+284	58	58
+51	76	76
+51	94	91
+55	77	77
+95	15	15
+74	251	251
+116	107	28
+64	188	188
+77	4	4
+113	11	11
+62	44	44
+102	237	237
+154	79	79
+58	86	86
+53	39	39
+50	36	35
+412	36	36
+75	225	225
+313	30	30
+54	84	83
+69	156	147
+104	89	77
+54	162	162
+226	16	16
+95	26	26
+60	14	14
+59	8	8
+120	7	7
+162	67	67
+65	210	210
+112	204	203
+63	53	53
+50	140	139
+127	143	143
+149	97	97
+88	61282	60044
+56	370	381
+50	56	56
+84	370	368
+52	288	288
+54	25	25
+72	923	933
+55	768	765
+68	70	70
+52	196	196
+62	305	305
+50	43	43
+129	114	114
+53	66	65
+116	411	423
+58	314	324
+68	0	1
+123	0	1
+53	58	59
+116	401	399
+539	6	0
+397	18	18
+60	211	211
+55	175	175
+63	553	556
+55	10	10
+53	1024	1003
+58	34	34
+81	43	43
+75	9	9
+51	1	0
+69
+
+chain 476298 chr4 191154276 + 9230645 9271936 chr4 191273063 + 8940012 8967053 893
+192	87	88
+429	187	187
+754	4750	6
+744	23	25
+2003	14	14
+246	42	42
+74	48	48
+71	104	104
+291	226	226
+81	4533	4529
+47	562	562
+111	285	285
+89	35	35
+2637	17	17
+240	9	9
+78	4	4
+157	215	209
+179	17	17
+100	4802	54
+343	13	13
+785	10920	6171
+1114	17	17
+243	6	6
+58	2	1
+272	1	0
+404	10	10
+1194	31	31
+266	11	11
+770	21	21
+327
+
+chain 377656 chr4 191154276 + 9257600 9267189 chr4 191273063 + 8933740 8938580 708
+1209	17	17
+571	1	0
+1617	4779	31
+1395
+
+chain 310844 chr4 191154276 + 9241835 9252105 chr4 191273063 + 8941714 8947231 850
+2726	14	14
+243	9	9
+78	4	4
+157	213	211
+265	85	85
+524	4751	0
+379	283	283
+539
+
+chain 275688 chr4 191154276 + 190986479 190989396 chr4 191273063 + 191223755 191226674 1129
+58	2	0
+265	1	0
+205	0	1
+208	4	5
+205	1	0
+122	55	53
+54	0	1
+411	25	25
+282	1	0
+419	14	20
+585
+
+chain 164691 chr4 191154276 + 9225860 9240813 chr4 191273063 + 8954210 8973910 1376
+232	87	87
+216	5946	5946
+93	12	12
+116	46	46
+231	32	32
+884	2511	7257
+718	3769	3770
+60
+
+chain 136190 chr4 191154276 + 9219745 9221340 chr4 191273063 + 8971822 8973417 7780
+1090	14	14
+243	9	9
+78	80	80
+81
+
+chain 127110 chr4 191154276 + 9223074 9241806 chr4 191273063 + 8960913 8979648 1585
+266	11	11
+4	10400	10401
+206	20	21
+668	26	27
+395	17	17
+14	6682	6682
+23
+
+chain 113888 chr4 191154276 + 59794841 59796661 chr7 158821424 + 43068053 43069865 1124766
+203	13	13
+161	140	141
+116	42	42
+240	178	178
+142	63	63
+254	11	11
+90	67	58
+100
+
+chain 91306 chr4 191154276 + 9218608 9227700 chr4 191273063 + 8961194 8975031 2525
+1019	3329	8072
+118	4492	4494
+89	35	35
+10
+
+chain 70288 chr4 191154276 + 9018276 9021043 chr11 134452384 - 130908986 130911761 1790585
+117	359	362
+150	330	330
+55	237	237
+99	73	73
+100	253	253
+70	73	78
+137	311	312
+72	249	248
+82
+
+chain 69967 chr4 191154276 + 8969559 8971297 chr11 134452384 - 66940622 66942298 1798470
+59	244	176
+78	49	49
+76	0	4
+72	217	218
+85	102	102
+264	12	12
+52	246	247
+66	24	24
+92
+
+chain 66013 chr4 191154276 + 9271936 9272654 chr4 191273063 + 8948073 8948792 572417
+692	0	1
+26
+
+chain 45624 chr4 191154276 + 9079872 9084019 chr4 191273063 - 187198263 187202501 2810559
+137	1640	1673
+114	79	83
+52	281	281
+64	700	698
+99	226	253
+83	576	605
+96
+
+chain 42774 chr4 191154276 + 9272654 9274373 chr4 191273063 + 8958282 8960000 1428
+395	17	17
+243	6	6
+329	3	2
+726
+
+chain 41852 chr4 191154276 + 9086638 9087081 chr1 247249719 - 105679719 105680162 3102182
+443
+
+chain 32596 chr4 191154276 + 9003477 9005348 chr8 146274826 + 6937943 6939835 4188535
+92	357	358
+96	443	443
+52	521	541
+122	129	129
+59
+
+chain 27953 chr4 191154276 + 9001038 9001387 chr11 134452384 - 130891915 130892264 5650797
+153	24	24
+85	11	11
+76
+
+chain 25460 chr4 191154276 + 1547039 1548332 chr4 191273063 + 1517808 1518962 1406869
+132	196	194
+8	33	0
+58	94	94
+33	400	430
+53	219	85
+67
+
+chain 23919 chr4 191154276 + 9060276 9060815 chrX 154913754 - 61464264 61464816 7738233
+150	249	262
+51	8	8
+81
+
+chain 23663 chr4 191154276 + 9250380 9252971 chr4 191273063 + 8954996 8957588 1596
+343	1382	1382
+494	21	21
+330	20	21
+1
+
+chain 23348 chr4 191154276 + 8954155 8955149 chr13 114142980 + 67377165 67378170 8084807
+108	119	119
+58	448	459
+78	128	128
+55
+
+chain 23051 chr4 191154276 + 9178657 9179321 chr8 146274826 - 138181840 138182484 8260527
+67	301	281
+58	86	86
+152
+
+chain 21854 chr4 191154276 + 9064978 9065877 chr1 247249719 + 159299736 159300622 9096955
+140	389	376
+61	239	239
+70
+
+chain 20302 chr4 191154276 + 59794670 59795934 chr19 63811651 - 51831683 51832948 1313667
+101	447	447
+6	69	70
+65	116	116
+17	4	4
+21	351	351
+67
+
+chain 19591 chr4 191154276 + 9123525 9124535 chr8 146274826 - 133912952 133913964 10789494
+68	696	699
+88	66	65
+92
+
+chain 17609 chr4 191154276 + 9152849 9153208 chr8 146274826 - 133934464 133934826 12466518
+149	157	160
+53
+
+chain 17420 chr4 191154276 + 9097653 9099623 chr11 134452384 - 51628045 51630034 12637575
+61	831	818
+58	894	926
+126
+
+chain 17154 chr4 191154276 + 8944061 8944687 chr3 199501827 - 68270290 68270918 12891537
+94	361	363
+56	52	52
+63
+
+chain 16449 chr4 191154276 + 9179756 9180625 chr8 146274826 + 7630543 7631403 13585678
+50	232	222
+54	427	428
+106
+
+chain 16159 chr4 191154276 + 9066614 9068459 chr16 88827254 - 83675354 83677175 13878826
+62	1020	1018
+99	597	575
+67
+
+chain 16115 chr4 191154276 + 9109381 9109952 chr21 46944323 + 28460282 28460853 13923553
+84	119	119
+62	249	249
+57
+
+chain 15306 chr4 191154276 + 8980490 8981996 chr4 191273063 - 187061282 187061823 14745791
+66	1267	302
+72	36	36
+65
+
+chain 15299 chr4 191154276 + 9056645 9056806 chr7 158821424 - 61471183 61471344 14752363
+161
+
+chain 14776 chr4 191154276 + 8950227 8950452 chr10 135374737 - 120304145 120304370 15312555
+84	55	55
+86
+
+chain 14403 chr4 191154276 + 9126194 9127408 chr5 180857866 - 26856190 26857401 15732261
+94	264	256
+54	752	757
+50
+
+chain 14224 chr4 191154276 + 8969618 8970298 chr11 134452384 - 67220551 67221216 1931088
+4	94	93
+78	397	383
+107
+
+chain 14155 chr4 191154276 + 9145781 9146043 chrX 154913754 - 45908091 45908403 16013758
+81	98	148
+83
+
+chain 14099 chr4 191154276 + 9060197 9060675 chr3 199501827 + 53477967 53478452 7798477
+58	172	171
+90	137	145
+21
+
+chain 13997 chr4 191154276 + 9005833 9006439 chr8 146274826 - 139204211 139204817 16201090
+60	438	438
+108
+
+chain 13823 chr4 191154276 + 8945988 8946280 chr4 191273063 + 9373057 9373350 16411372
+60	133	134
+99
+
+chain 13439 chr4 191154276 + 8975637 8975779 chr3 199501827 + 126919507 126919649 16900342
+142
+
+chain 12765 chr4 191154276 + 9077064 9077200 chr1 247249719 - 177698311 177698447 17836871
+136
+
+chain 12497 chr4 191154276 + 8950452 8951505 chr4 191273063 - 187091946 187092996 17010995
+3	953	950
+97
+
+chain 12348 chr4 191154276 + 8983189 8983604 chr8 146274826 - 138673776 138674197 18460871
+61	268	274
+86
+
+chain 11880 chr4 191154276 + 8972496 8973020 chr14 106368585 - 55089898 55090495 19186930
+61	378	451
+85
+
+chain 11818 chr4 191154276 + 9096126 9096305 chr11 134452384 - 67086036 67086266 19295429
+55	42	93
+82
+
+chain 11496 chr4 191154276 + 8948423 8949198 chr12 132349534 + 50778185 50778960 19846856
+94	629	629
+52
+
+chain 11391 chr4 191154276 + 8947143 8947401 chr8 146274826 - 134472454 134472711 20027902
+53	123	122
+82
+
+chain 11111 chr4 191154276 + 9107828 9107946 chr16 88827254 + 2897686 2897804 20531108
+118
+
+chain 10916 chr4 191154276 + 9261701 9262066 chr4 191273063 + 8952078 8952443 1072
+365
+
+chain 10832 chr4 191154276 + 8994164 8994326 chr6 170899992 - 100664994 100665156 21051510
+55	36	36
+71
+
+chain 10756 chr4 191154276 + 8943247 8943361 chr4 191273063 + 9116977 9117091 21193988
+114
+
+chain 10679 chr4 191154276 + 191030273 191030443 chr3 199501827 + 127002379 127002551 21342971
+68	44	46
+58
+
+chain 10668 chr4 191154276 + 1582572 1582681 chr4 191273063 + 1552756 1552865 12282737
+109
+
+chain 10529 chr4 191154276 + 191032229 191032410 chr11 134452384 + 3430296 3430477 21654608
+64	55	55
+62
+
+chain 10273 chr4 191154276 + 9096703 9097008 chr3 199501827 + 187858881 187859186 22199926
+64	181	181
+60
+
+chain 10137 chr4 191154276 + 9099965 9100095 chr6 170899992 - 166526436 166526567 22497437
+61	12	13
+57
+
+chain 10052 chr4 191154276 + 9066676 9066805 chr10 135374737 - 108696851 108696974 16846521
+41	9	9
+20	6	0
+53
+
+chain 9949 chr4 191154276 + 8999157 8999260 chr6 170899992 + 1823421 1823524 22925909
+103
+
+chain 9823 chr4 191154276 + 9071238 9072065 chr19 63811651 - 22299002 22299820 23218142
+65	697	688
+65
+
+chain 9746 chr4 191154276 + 8950613 8951219 chr7 158821424 - 151976579 151977185 23399634
+66	481	481
+59
+
+chain 9713 chr4 191154276 + 9012936 9013126 chrX 154913754 + 119487462 119487653 23485630
+58	74	75
+58
+
+chain 9679 chr4 191154276 + 9083038 9083589 chr12 132349534 + 77527128 77527707 10056562
+24	185	212
+17	262	263
+63
+
+chain 9579 chr4 191154276 + 9105290 9105637 chr8 146274826 - 6609 6954 23801877
+63	229	227
+55
+
+chain 9552 chr4 191154276 + 8956536 8957179 chr8 146274826 - 139187457 139188099 13944787
+92	234	234
+51	240	239
+26
+
+chain 9532 chr4 191154276 + 8978497 8978597 chr21 46944323 - 3695413 3695513 23932747
+100
+
+chain 9412 chr4 191154276 + 9108273 9108605 chr2 242951149 + 34780701 34781033 24211634
+61	216	216
+55
+
+chain 9361 chr4 191154276 + 9207159 9207725 chr7 158821424 + 92958588 92959148 24306771
+65	445	439
+56
+
+chain 9304 chr4 191154276 + 8946418 8946780 chr13 114142980 + 45938942 45939304 24422281
+63	247	247
+52
+
+chain 9136 chr4 191154276 + 9129485 9129655 chr1 247249719 - 82404984 82405154 24736407
+59	59	59
+52
+
+chain 9105 chr4 191154276 + 8982741 8983189 chr10 135374737 - 120304868 120305301 22041837
+59	380	365
+9
+
+chain 8777 chr4 191154276 + 9118310 9118402 chr11 134452384 - 67092191 67092283 25280535
+92
+
+chain 8617 chr4 191154276 + 59794359 59794524 chrX 154913754 + 69736929 69737094 2995761
+75	86	86
+4
+
+chain 8389 chr4 191154276 + 9219628 9219725 chr4 191273063 + 8933741 8933838 871949
+97
+
+chain 8260 chr4 191154276 + 8989895 8989983 chr4 191273063 + 9362532 9362620 26013719
+88
+
+chain 8131 chr4 191154276 + 9102626 9102711 chr4 191273063 - 187087880 187087965 26219988
+85
+
+chain 7754 chr4 191154276 + 190986383 190986479 chr10 135374737 + 135327923 135328019 562
+96
+
+chain 7688 chr4 191154276 + 8999849 9001530 chr8 146274826 + 7459813 7461495 7287525
+76	15	15
+50	236	236
+59	1157	1158
+88
+
+chain 7445 chr4 191154276 + 1642823 1642928 chr4 191273063 + 1612696 1612801 10569689
+105
+
+chain 7390 chr4 191154276 + 9235101 9235376 chr4 191273063 + 8934980 8935255 884
+275
+
+chain 6985 chr4 191154276 + 9132536 9132609 chr10 135374737 + 82556085 82556158 28236044
+73
+
+chain 6957 chr4 191154276 + 9079830 9084724 chr8 146274826 - 133860764 133864463 3584848
+42	1125	1126
+68	534	536
+50	1109	1111
+56	1741	541
+169
+
+chain 6924 chr4 191154276 + 9086283 9086357 chr3 199501827 + 28200221 28200295 17749225
+74
+
+chain 6522 chr4 191154276 + 59794524 59794670 chr4 191273063 + 131104023 131104168 2551460
+51	42	41
+53
+
+chain 6459 chr4 191154276 + 191029213 191029282 chr11 134452384 - 63299390 63299459 29377341
+69
+
+chain 6349 chr4 191154276 + 8971797 8971864 chr9 140273252 + 68477506 68477573 29649127
+67
+
+chain 6310 chr4 191154276 + 1548554 1548645 chr4 191273063 + 1518821 1518912 10939184
+91
+
+chain 6297 chr4 191154276 + 59793454 59794143 chr3 199501827 - 40571037 40571724 2330420
+79	562	560
+48
+
+chain 6221 chr4 191154276 + 9064020 9064085 chr16 88827254 - 83673859 83673924 29990023
+65
+
+chain 6094 chr4 191154276 + 9110081 9110145 chr1 247249719 + 181849295 181849359 30306899
+64
+
+chain 6086 chr4 191154276 + 191030472 191030537 chr11 134452384 - 75925756 75925821 30317869
+65
+
+chain 5966 chr4 191154276 + 9104473 9104535 chr11 134452384 + 71003965 71004027 30644952
+62
+
+chain 5912 chr4 191154276 + 8947661 8947723 chr9 140273252 - 2802727 2802789 30796182
+62
+
+chain 5903 chr4 191154276 + 9101296 9101358 chr4 191273063 + 9087606 9087668 30814689
+62
+
+chain 5842 chr4 191154276 + 9036574 9036668 chr4 191273063 - 85960898 85960992 17872768
+94
+
+chain 5712 chr4 191154276 + 9132160 9132220 chr12 132349534 + 8264132 8264192 31330015
+60
+
+chain 5710 chr4 191154276 + 191042876 191042934 chr4 191273063 - 191272139 191272197 15878613
+58
+
+chain 5622 chr4 191154276 + 9070424 9070484 chr3 199501827 - 68123367 68123427 31584493
+60
+
+chain 5594 chr4 191154276 + 1547006 1547408 chr4 191273063 + 1517841 1518435 2949224
+33	336	530
+7	8	6
+18
+
+chain 5494 chr4 191154276 + 8989383 8989441 chr10 135374737 + 82555871 82555929 31956576
+58
+
+chain 5493 chr4 191154276 + 9123841 9123899 chr3 199501827 - 55547554 55547612 22296298
+58
+
+chain 5485 chr4 191154276 + 9108193 9108251 chr17 78774742 + 49845783 49845841 31992260
+58
+
+chain 5354 chr4 191154276 + 9123785 9123841 chr19 63811651 + 46743056 46743112 26997396
+56
+
+chain 5287 chr4 191154276 + 191044097 191044231 chr11 134452384 + 134452193 134452328 8509115
+51	52	53
+31
+
+chain 5247 chr4 191154276 + 1642928 1642982 chr4 191273063 + 1612682 1612736 32710536
+54
+
+chain 5146 chr4 191154276 + 9109529 9109584 chr3 199501827 + 191350023 191350078 20827932
+55
+
+chain 5102 chr4 191154276 + 9012475 9012528 chr7 158821424 - 61434988 61435041 33179954
+53
+
+chain 4979 chr4 191154276 + 59793133 59793454 chr14 106368585 + 47992116 47992437 1636209
+52	1	1
+72	116	116
+45	1	1
+34
+
+chain 4919 chr4 191154276 + 59793533 59793585 chr1 247249719 + 177132715 177132767 25644257
+52
+
+chain 4894 chr4 191154276 + 8980336 8980388 chr8 146274826 - 134343460 134343512 33871905
+52
+
+chain 4776 chr4 191154276 + 59793593 59793649 chr8 146274826 + 78720544 78720600 25267381
+56
+
+chain 4646 chr4 191154276 + 9032086 9032149 chr11 134452384 - 67001981 67002044 11075042
+63
+
+chain 4523 chr4 191154276 + 9083642 9083690 chr4 191273063 + 9229696 9229744 33561479
+48
+
+chain 4481 chr4 191154276 + 9110034 9110081 chr1 247249719 + 117212387 117212434 31311635
+47
+
+chain 4466 chr4 191154276 + 8975249 8975296 chr4 191273063 + 9087559 9087606 34734206
+47
+
+chain 4380 chr4 191154276 + 9065601 9065685 chr14 106368585 - 65288844 65288928 12690014
+84
+
+chain 4316 chr4 191154276 + 8994219 8994386 chr9 140273252 - 20618312 20618467 21123765
+25	83	71
+59
+
+chain 4224 chr4 191154276 + 1548697 1548764 chr4 191273063 + 1518798 1518831 14337246
+14	34	0
+19
+
+chain 4196 chr4 191154276 + 59793649 59793759 chr3 199501827 - 110817223 110817333 10064550
+110
+
+chain 4174 chr4 191154276 + 9006462 9006529 chr3 199501827 - 68301162 68301229 17546615
+67
+
+chain 4160 chr4 191154276 + 9087190 9087234 chr3 199501827 + 69469088 69469132 19451262
+44
+
+chain 4035 chr4 191154276 + 59793991 59794095 chr4 191273063 - 43511377 43511481 1601554
+104
+
+chain 3949 chr4 191154276 + 59793891 59793960 chr7 158821424 - 5091499 5091568 15707336
+69
+
+chain 3917 chr4 191154276 + 59794575 59794617 chr19 63811651 + 46686810 46686852 11955254
+42
+
+chain 3916 chr4 191154276 + 9180332 9180405 chr8 146274826 + 7130141 7130214 14314247
+73
+
+chain 3790 chr4 191154276 + 9231440 9231540 chr4 191273063 + 8950300 8950400 218917
+92	7	7
+1
+
+chain 3686 chr4 191154276 + 59793772 59793811 chr15 100338915 + 77825223 77825262 17426618
+39
+
+chain 3659 chr4 191154276 + 9096554 9096861 chr3 199501827 - 6400721 6401028 23757316
+67	190	190
+50
+
+chain 3657 chr4 191154276 + 59794470 59794516 chr6 170899992 - 3232006 3232052 26376367
+46
+
+chain 3647 chr4 191154276 + 1557695 1557733 chr4 191273063 + 1527878 1527916 12331685
+38
+
+chain 3642 chr4 191154276 + 9109808 9109863 chr6 170899992 - 83529676 83529731 23755843
+55
+
+chain 3437 chr4 191154276 + 9178724 9179540 chr12 132349534 + 34224690 34225504 10931865
+32	667	665
+117
+
+chain 3342 chr4 191154276 + 9274373 9274605 chr4 191273063 + 8969490 8969722 4902
+232
+
+chain 3310 chr4 191154276 + 8971045 8971455 chr9 140273252 - 10330739 10331149 20511421
+70	288	288
+52
+
+chain 3302 chr4 191154276 + 1548711 1548745 chr4 191273063 + 1518614 1518648 32145222
+34
+
+chain 3283 chr4 191154276 + 9102560 9102594 chr10 135374737 - 120311822 120311856 35225233
+34
+
+chain 3261 chr4 191154276 + 8994091 8994458 chr8 146274826 + 9742146 9742512 23065618
+62	246	245
+59
+
+chain 3172 chr4 191154276 + 59794789 59794841 chr3 199501827 - 24852035 24852087 14612523
+52
+
+chain 3108 chr4 191154276 + 9060565 9060615 chr13 114142980 - 41995201 41995251 9632166
+50
+
+chain 3078 chr4 191154276 + 1548520 1548554 chr4 191273063 + 1518360 1518394 5794973
+34
+
+chain 3017 chr4 191154276 + 9065206 9065807 chr10 135374737 + 117208692 117209275 9578047
+65	480	462
+56
+
+chain 2924 chr4 191154276 + 59795756 59795800 chr5 180857866 + 175080369 175080413 1478283
+44
+
+chain 2887 chr4 191154276 + 59793960 59793991 chr2 242951149 - 7484272 7484303 15380677
+31
+
+chain 2846 chr4 191154276 + 9001603 9001654 chr8 146274826 - 133764474 133764525 19750221
+51
+
+chain 2767 chr4 191154276 + 8957324 8957381 chr4 191273063 + 9129618 9129675 15542671
+57
+
+chain 2754 chr4 191154276 + 9087109 9087190 chr6 170899992 + 92706078 92706159 16313416
+81
+
+chain 2673 chr4 191154276 + 9065350 9065411 chr1 247249719 - 53009045 53009106 13821618
+61
+
+chain 2622 chr4 191154276 + 59793258 59793374 chr14 106368585 + 42536813 42536929 1616879
+116
+
+chain 2598 chr4 191154276 + 59795229 59795281 chr6 170899992 + 57310821 57310873 1524793
+52
+
+chain 2565 chr4 191154276 + 190987578 190987605 chr4 191273063 + 191231440 191231467 2372
+27
+
+chain 2557 chr4 191154276 + 9066521 9067027 chr12 132349534 + 72855206 72855711 22561893
+55	378	377
+73
+
+chain 2500 chr4 191154276 + 9083457 9083524 chr8 146274826 + 32149594 32149661 28386486
+67
+
+chain 2474 chr4 191154276 + 1651689 1651722 chr4 191273063 + 1621541 1621574 19254204
+33
+
+chain 2389 chr4 191154276 + 9036810 9036873 chr2 242951149 - 1691358 1691421 23135357
+63
+
+chain 2338 chr4 191154276 + 59796505 59796540 chr17 78774742 + 47057876 47057911 2877115
+35
+
+chain 2291 chr4 191154276 + 9216761 9217155 chr8 146274826 - 133997030 133997425 4114277
+45	320	321
+29
+
+chain 2265 chr4 191154276 + 9065418 9065482 chr9 140273252 + 44106224 44106288 9767431
+64
+
+chain 2116 chr4 191154276 + 8944155 8944177 chr3 199501827 + 126918676 126918698 25172225
+22
+
+chain 2099 chr4 191154276 + 9099268 9099290 chr2 242951149 + 169698626 169698648 26708137
+22
+
+chain 2025 chr4 191154276 + 9097343 9097409 chr3 199501827 + 179409375 179409441 24047564
+66
+
+chain 2003 chr4 191154276 + 9108252 9108273 chr2 242951149 - 190846639 190846660 24998179
+21
+
+chain 1997 chr4 191154276 + 9146164 9146218 chr15 100338915 - 2487154 2487208 24249848
+54
+
+chain 1870 chr4 191154276 + 190988070 190988095 chr10 135374737 + 135329605 135329630 1377
+25
+
+chain 1826 chr4 191154276 + 8957935 8957992 chr4 191273063 + 9362404 9362461 11066413
+57
+
+chain 1826 chr4 191154276 + 9097476 9098043 chr12 132349534 - 122338357 122338925 15828070
+57	424	425
+86
+
+chain 1767 chr4 191154276 + 8990059 8990106 chr1 247249719 + 148949220 148949267 26452494
+47
+
+chain 1744 chr4 191154276 + 59793037 59793133 chr3 199501827 + 30427927 30428023 1883621
+96
+
+chain 1736 chr4 191154276 + 9086392 9087109 chr4 191273063 - 127153063 127153784 14070511
+50	639	643
+28
+
+chain 1668 chr4 191154276 + 9124660 9124729 chr4 191273063 + 9269820 9269889 23245150
+69
+
+chain 1556 chr4 191154276 + 9060815 9060839 chr10 135374737 - 108080722 108080746 12503169
+24
+
+chain 1546 chr4 191154276 + 9180153 9180207 chr8 146274826 - 138844855 138844909 16808195
+54
+
+chain 1517 chr4 191154276 + 59794322 59794359 chr11 134452384 - 119842384 119842421 16271509
+37
+
+chain 1488 chr4 191154276 + 59796097 59796124 chr9 140273252 + 9925299 9925326 2265670
+27
+
+chain 1436 chr4 191154276 + 191043722 191043759 chr1 247249719 - 247249574 247249611 18645625
+37
+
+chain 1374 chr4 191154276 + 9065276 9065337 chr1 247249719 - 201083821 201083882 10540800
+61
+
+chain 1348 chr4 191154276 + 9109064 9109144 chr2 242951149 - 126292213 126292293 15140626
+80
+
+chain 1343 chr4 191154276 + 9146043 9146068 chr18 76117153 + 30068723 30068748 16305066
+25
+
+chain 1292 chr4 191154276 + 9123899 9123951 chr4 191273063 - 148574019 148574071 20863102
+52
+
+chain 1290 chr4 191154276 + 9179321 9179368 chr11 134452384 + 3426025 3426072 10983647
+47
+
+chain 1231 chr4 191154276 + 59794434 59794461 chr5 180857866 + 147382264 147382291 9387523
+27
+
+chain 1177 chr4 191154276 + 9065884 9065939 chr9 140273252 - 70318092 70318147 10006368
+55
+
+chain 1097 chr4 191154276 + 9086357 9086392 chr1 247249719 - 129588705 129588740 16923174
+35
+
+chain 1085 chr4 191154276 + 9066380 9066450 chr13 114142980 + 68490318 68490388 22728993
+70
+
+chain 1083 chr4 191154276 + 9032737 9032804 chr13 114142980 + 26049760 26049827 24893033
+67
+
+chain 1011 chr4 191154276 + 9067073 9067124 chr10 135374737 - 108679092 108679143 23379890
+51
+
+chain 996 chr4 191154276 + 8971509 8971561 chr12 132349534 + 31168410 31168462 23661941
+52
+
+chain 963 chr4 191154276 + 9066836 9066890 chr1 247249719 - 151454542 151454596 25048936
+54
+
+chain 958 chr4 191154276 + 9145173 9145232 chr1 247249719 - 217919030 217919089 20381976
+59
+
+chain 937 chr4 191154276 + 8958092 8958125 chr11 134452384 + 67446107 67446140 12651114
+33
+
+chain 917 chr4 191154276 + 9146455 9146505 chr8 146274826 + 19957787 19957837 24577235
+50
+
+chain 910 chr4 191154276 + 9097602 9098317 chr2 242951149 - 190844271 190844995 14887788
+50	595	604
+70
+
+chain 894 chr4 191154276 + 9109146 9109219 chrX 154913754 - 13573867 13573940 23078019
+73
+
+chain 878 chr4 191154276 + 9178986 9179012 chr2 242951149 - 137542666 137542692 11507142
+26
+
+chain 871 chr4 191154276 + 9082368 9082425 chr3 199501827 - 78731030 78731087 22332859
+57
+
+chain 858 chr4 191154276 + 9098043 9099355 chr5 180857866 - 58871729 58873086 24126323
+56	1191	1236
+65
+
+chain 777 chr4 191154276 + 8955354 8955423 chr3 199501827 - 68281758 68281827 15856837
+69
+
+chain 715 chr4 191154276 + 191033511 191033568 chr7 158821424 + 30724536 30724593 23744345
+57
+
+chain 650 chr4 191154276 + 9126884 9126934 chr3 199501827 + 102896742 102896792 23688110
+50
+
+chain 507 chr4 191154276 + 59793857 59793890 chr8 146274826 + 107120151 107120184 20878932
+33
+
+chain 468 chr4 191154276 + 40297344 40297404 chr4 191273063 + 39972706 39972766 25333266
+60
+
+chain 438 chr4 191154276 + 9098988 9099041 chr4 191273063 - 56600577 56600630 25949595
+53
+
+chain 368 chr4 191154276 + 191031439 191031496 chr19 63811651 - 43557899 43557956 26568315
+57
+
+chain 315 chr4 191154276 + 8972631 8972682 chr12 132349534 - 123858147 123858198 26303923
+51
+
+chain 268 chr4 191154276 + 59793813 59793857 chr13 114142980 - 20847506 20847550 12435901
+44
+
+chain 209 chr4 191154276 + 9096427 9096486 chr3 199501827 - 25140168 25140227 30710814
+59
+
+chain 54948874 chr4_ctg9_hap1 590426 + 0 590426 chr4 191273063 + 68852671 69912764 73
+1837	0	2
+151607	0	469345
+122242	3	1
+4137	1	1
+70	1	1
+5254	0	2
+2782	48	48
+1074	0	2
+2825	0	5
+2047	2	0
+6949	1	1
+41	1	1
+232	0	1
+1965	12	0
+694	1	1
+22	1	0
+945	14	14
+416	1	1
+36	2	0
+75	1	1
+21	1	0
+52	1	1
+41	1	1
+144	1	1
+87	1	1
+71	1	1
+35	1	1
+145	0	1
+503	1	1
+88	1	1
+99	1	1
+30	1	1
+293	0	5
+360	19	19
+380	1	1
+23	1	1
+209	36	36
+557	10	10
+820	1	1
+38	1	1
+868	0	2
+227	0	353
+5432	0	1
+1459	1	0
+210	20	20
+125	8	0
+5	32	0
+65	0	2
+10	23	5
+240	0	1
+233	14	14
+1076	14	14
+100	1	1
+28	1	1
+199	0	1
+287	1	1
+36	1	0
+17	1	1
+132	1	1
+25	1	1
+193	1	0
+305	0	28
+50	0	1
+544	1	1
+40	4	0
+794	15	15
+179	1	1
+72	1	1
+142	1	1
+65	1	1
+364	0	1
+335	0	1
+52	4	4
+48	1	1
+934	1	1
+50	0	1
+44	1	1
+1074	1	1
+22	1	1
+286	4	0
+33	1	1
+303	1	1
+5	0	1
+63	1	1
+972	1	1
+69	1	1
+602	1	1
+25	1	1
+2469	5	5
+1033	1	1
+63	1	1
+233	0	3
+311	1	1
+29	1	1
+881	6	6
+123	15	16
+283	1	1
+39	1	1
+57	5	0
+613	1	1
+42	1	1
+1598	0	2
+730	1	1
+47	1	1
+459	1	1
+25	1	1
+775	7	7
+534	0	1
+1090	5	5
+375	1	1
+62	1	1
+133	15	15
+700	1	1
+36	4	0
+365	9	9
+468	1	1
+45	1	1
+1356	16	16
+422	1	0
+55	0	2
+7890	1	1
+30	1	1
+1445	1	1
+27	1	1
+96	4	0
+2114	10	11
+1940	2	0
+1687	1	1
+40	1	1
+1679	1	0
+734	0	1
+480	1	0
+7344	1	0
+3930	17	17
+1001	0	8
+216373
+
+chain 4430 chr4_ctg9_hap1 590426 + 287934 287982 chr4 191273063 + 69257952 69258000 221
+48
+
+chain 18001815 chr4_gl000193_random 189789 + 0 189789 chr4_random 842648 + 0 189789 149
+189789
+
+chain 18169122 chr4_gl000194_random 191469 + 0 191469 chr4_random 842648 + 440032 631501 148
+191469
+
+chain 16792065298 chr5 180915260 + 10000 180905260 chr5 180857866 + 63000 180837866 5
+17520657	50017	11
+356	84	84
+496	0	3434
+735	75	1475
+628	25	3459
+51	50	3484
+3427	1	1
+39	3	3437
+577	8	8
+167	44	1713
+23	0	3434
+1184	1	0
+46	1	0
+5	1	0
+266	1	1
+21	1	1
+763	16	16
+422	1	1
+29	1	1
+5243	1	1
+37	1	1
+978	1	1
+21	1	1
+116	16	3450
+1792	146	16585
+3079	0	1
+7857	9770	0
+1026	636	1
+7461	1	0
+23769	0	51
+4034	1	0
+20571	1	0
+9135	2	0
+6885	3	2
+110	0	3
+816	3	2
+2296	34	0
+7499	2	0
+2917	1	0
+652	1	1
+37	1	1
+657	1	1
+22	1	1
+419	4	3
+3580	1	1
+29	1	1
+274	35	11
+833	1	0
+1908	0	3038
+10504	1	1
+27	0	2
+784	6	0
+127	0	10
+668	1	1
+28	1	1
+2464	0	4
+182	2	0
+1650	1	1
+39	1	1
+2433	0	1
+720	1	1
+40	1	1
+772	1	1
+32	1	1
+353	1	1
+17	1	1
+1776	1	0
+6082	0	3
+2669	10	12
+2857	1	1
+35	1	1
+982	1	1
+173	1	1
+4115	1	1
+49	1	1
+702	1	1
+33	1	1
+2927	2	1
+1472	0	17
+1346	1	1
+35	1	1
+2068	1	1
+40	1	1
+828	1	1
+36	0	2
+317	0	8
+893	1	1
+33	0	1
+8145	4	0
+28632197	3000000	3000000
+12470071	1	0
+29760415	50000	40000
+5878002	20845	23000
+4521	0	1
+676	6	6
+5928	1	0
+372	1	1
+47	1	1
+6801	2	3
+639	1	0
+871	4	3
+11530	4	0
+22966	1	0
+15447	1	0
+53856	2	0
+15988	2	0
+906887	1	0
+8	2	2
+40152828	47715	0
+3526228	1	0
+1604	0	10
+12778810	51715	4100
+15152690	0	27
+1852098	0	1
+8710030
+
+chain 78758 chr5 180915260 + 17610410 17613099 chr5 180857866 + 17647305 17649997 1601642
+85	49	49
+57	201	201
+189	17	17
+78	77	77
+75	178	181
+116	179	179
+91	8	8
+51	298	300
+51	664	662
+64	26	26
+135
+
+chain 31383 chr5 180915260 + 97574240 97575427 chr4 191273063 - 170991967 170993160 4391624
+188	108	110
+89	705	709
+97
+
+chain 22831 chr5 180915260 + 97580590 97581374 chr2 242951149 - 86243998 86244777 8407693
+68	180	179
+95	326	322
+115
+
+chain 16108 chr5 180915260 + 97571166 97571372 chr3 199501827 + 12403992 12404198 13932022
+51	22	22
+133
+
+chain 10260 chr5 180915260 + 97573380 97573866 chrX 154913754 + 72466087 72466572 22227065
+67	357	356
+62
+
+chain 9281 chr5 180915260 + 97573916 97574127 chr3 199501827 - 17931346 17931561 24462523
+61	98	102
+52
+
+chain 8534 chr5 180915260 + 17581030 17583073 chr5 180857866 + 17608062 17614939 1974
+70	1948	6782
+25
+
+chain 7377 chr5 180915260 + 17614165 17614243 chr8 146274826 + 118652818 118652896 27454171
+78
+
+chain 7140 chr5 180915260 + 97574682 97574775 chr9 140273252 + 18188007 18188100 13076039
+11	6	6
+76
+
+chain 6854 chr5 180915260 + 97574980 97575063 chr2 242951149 + 163688921 163689004 19449593
+83
+
+chain 6104 chr5 180915260 + 97573580 97573645 chrX 154913754 + 86697567 86697632 30283885
+65
+
+chain 5931 chr5 180915260 + 97571838 97571901 chr11 134452384 + 21528921 21528984 30747470
+63
+
+chain 5358 chr5 180915260 + 97565266 97565323 chr3 199501827 + 123413571 123413628 32371600
+57
+
+chain 5211 chr5 180915260 + 97574626 97575600 chr2 242951149 - 205065194 205066172 4657168
+56	746	750
+172
+
+chain 4836 chr5 180915260 + 97570927 97570987 chr12 132349534 + 79028695 79028755 21429371
+60
+
+chain 3976 chr5 180915260 + 97580463 97580554 chrX 154913754 + 120621333 120621424 19038460
+91
+
+chain 3896 chr5 180915260 + 17583124 17583167 chr5 180857866 + 17601254 17601297 1526
+43
+
+chain 3528 chr5 180915260 + 97573879 97573916 chr4 191273063 - 42047288 42047325 31874217
+37
+
+chain 3107 chr5 180915260 + 97574479 97575651 chr2 242951149 + 88874356 88875531 4418505
+53	767	770
+31	271	271
+50
+
+chain 3026 chr5 180915260 + 97580178 97580228 chr15 100338915 - 8217824 8217874 19735797
+50
+
+chain 2922 chr5 180915260 + 97575231 97575262 chr5 180857866 - 151978291 151978322 11789776
+31
+
+chain 2640 chr5 180915260 + 97575132 97575230 chr6 170899992 - 85176442 85176540 6161475
+98
+
+chain 2605 chr5 180915260 + 97580235 97580338 chr6 170899992 - 161277959 161278062 12089137
+103
+
+chain 2572 chr5 180915260 + 97580955 97581020 chr4 191273063 + 75087136 75087201 9159879
+65
+
+chain 2511 chr5 180915260 + 97573039 97573123 chr5 180857866 + 96582581 96582665 20564544
+84
+
+chain 2425 chr5 180915260 + 97580778 97580807 chr7 158821424 + 56235832 56235861 15947917
+29
+
+chain 2390 chr5 180915260 + 97580658 97580706 chr6 170899992 + 77924350 77924398 14557662
+48
+
+chain 2360 chr5 180915260 + 97575070 97575127 chr15 100338915 - 65496060 65496117 11267266
+57
+
+chain 2316 chr5 180915260 + 97574862 97574967 chr5 180857866 + 122822031 122822136 6403532
+105
+
+chain 2262 chr5 180915260 + 97575262 97575299 chr5 180857866 + 117084659 117084696 9926189
+37
+
+chain 2258 chr5 180915260 + 97570996 97571059 chr6 170899992 + 98788934 98788997 20073703
+63
+
+chain 2234 chr5 180915260 + 97575771 97575825 chr15 100338915 + 19192799 19192853 13777203
+54
+
+chain 2112 chr5 180915260 + 17598551 17598575 chr5 180857866 + 17621050 17621074 2441
+24
+
+chain 2082 chr5 180915260 + 97581410 97581440 chr5 180857866 - 81177483 81177513 18145628
+30
+
+chain 2013 chr5 180915260 + 97574428 97574456 chr6 170899992 + 12662047 12662075 5707452
+28
+
+chain 1804 chr5 180915260 + 97574815 97574862 chr7 158821424 + 102470537 102470584 21213680
+47
+
+chain 1676 chr5 180915260 + 97571668 97571723 chr9 140273252 - 49451145 49451200 15925569
+55
+
+chain 1630 chr5 180915260 + 97575847 97575921 chr14 106368585 + 65599248 65599322 16554081
+74
+
+chain 1394 chr5 180915260 + 17611593 17611672 chr5 180857866 - 163271537 163271616 20711197
+79
+
+chain 1250 chr5 180915260 + 97570872 97570926 chrX 154913754 + 128632888 128632942 22138126
+54
+
+chain 1212 chr5 180915260 + 17598429 17598472 chr5 180857866 - 163276581 163276624 866388
+43
+
+chain 683 chr5 180915260 + 97570493 97570549 chr4 191273063 + 125149085 125149141 22694892
+56
+
+chain 625 chr5 180915260 + 97572119 97572183 chr5 180857866 - 153619225 153619289 25061319
+64
+
+chain 466 chr5 180915260 + 97569261 97569351 chr7 158821424 - 120247996 120248086 22482305
+90
+
+chain 395 chr5 180915260 + 97572751 97572804 chr2 242951149 - 47300723 47300776 19687839
+53
+
+chain 15799169383 chr6 171115067 + 60000 171055067 chr6 170899992 + 5000 170896992 6
+1297281	1	0
+7806968	0	162987
+4013154	9	0
+261	13	15
+18786172	17	17
+439	16	16
+59	5	4
+32202	17	17
+439	16	16
+59	4	5
+15403	1	0
+13914169	4	0
+112	1	1
+17	1	1
+415	12	0
+105	6	3
+12160281	50000	50000
+642507	3100000	3050000
+248423	50000	50000
+2918791	1238	0
+9427508	4	4
+162	12	12
+2193	22	22
+293	1	1
+30	1	1
+845	1	0
+45	1	1
+9769	2	0
+6058	1	1
+24	1	1
+2223	1	1
+24	1	1
+182	12	12
+284	1	1
+20	1	1
+1035	7	36
+1007	1	1
+27	1	1
+3279	1	1
+44	0	1
+3012	1	0
+545	17	17
+2562	0	1
+251	0	1
+935	8	0
+37	1	1
+566	6	0
+1483	2	0
+1960	1	0
+4564	1	1
+25	1	1
+832	0	1
+801	8	8
+1131	1	1
+58	5	1
+6177	0	1
+3712	1	0
+2185	1	1
+35	1	1
+710	2	2
+78	1	1
+2201	1	1
+30	1	1
+283	1	1
+30	1	1
+448	1	0
+74814	2	2
+197	8	0
+2508456	1	0
+4641788	5	5
+37	1	1
+8503609	0	2
+5363169	150000	200000
+6040303	1	1
+36	1	0
+2020	1	1
+46	1	1
+1559	1	1
+72	1	1
+1098	1	1
+29	1	1
+264	7	7
+580	0	1
+30	1	1
+536	1	1
+41	1	1
+5663	1	0
+438	5	3
+354	1	1
+18	1	1
+9613	14	13
+1400	1	0
+176	0	2
+2742	1	0
+1968	0	1
+754	1	0
+4237	0	1
+2388	1	1
+31	1	0
+3385	0	1
+2004	8	0
+3395	0	3
+32	1	1
+4109	0	1
+1058	20	0
+1608	1	0
+17198424	17	26
+7835	0	1
+16317	11	0
+6277	64993	0
+6787989	0	1
+149	4	0
+949	4	0
+242	0	1
+28418215	1	1
+21	1	0
+3116903	171704	50000
+1939305	1	1
+19	0	2
+8192274	4	4
+122	0	2
+1127	1	0
+1102	75	0
+21	8	5
+30	29	0
+27	6	3
+62	52	0
+42	195105	18125
+950946	1	1
+51	157	1
+107	255	0
+714	513	0
+1285155	50000	150000
+725095
+
+chain 12021668 chr6 171115067 + 157540957 157712661 chr6_random 1875562 + 1435107 1512777 78
+18510	50000	5628
+31833	50000	338
+21361
+
+chain 8743144 chr6 171115067 + 167847224 167942073 chr6_random 1875562 - 1720470 1850468 378
+12768	1	1
+28	0	1
+17496	12	0
+7219	1	1
+29	1	1
+4716	0	1
+1645	0	4
+6037	1	1
+33	94	125
+10	3	3
+5171	1	0
+4453	734	36650
+3575	1	1
+26	1	1
+4697	13	13
+958	0	2
+228	0	2
+2465	13	13
+142	1	1
+15	1	0
+33	937	104
+94	0	1
+125	16	0
+5319	48	103
+897	0	3
+1130	0	3
+187	8	7
+67	26	25
+5876	1	1
+47	1	1
+1955	14	7
+575	36	36
+641	0	2
+1143	5	5
+3079
+
+chain 27931 chr6 171115067 + 168993335 168994451 chr6 170899992 + 168736232 168737615 1527785
+96	36	36
+16	0	51
+107	739	901
+51	0	54
+71
+
+chain 17101 chr6 171115067 + 119158013 119159004 chr8 146274826 + 76280127 76281098 12940826
+78	146	105
+78	622	643
+67
+
+chain 14766 chr6 171115067 + 119189669 119190286 chr7 158821424 - 68703788 68704409 15321990
+54	439	443
+124
+
+chain 13062 chr6 171115067 + 168994482 168994817 chr6 170899992 + 168736716 168737003 1274096
+205	50	2
+80
+
+chain 12205 chr6 171115067 + 119155128 119155329 chr8 146274826 - 70047959 70048173 18676577
+72	59	72
+70
+
+chain 11124 chr6 171115067 + 168993071 168993228 chr6 170899992 + 168736229 168736638 2160304
+29	1	52
+50	25	226
+52
+
+chain 10673 chr6 171115067 + 119159180 119160231 chr10 135374737 - 59595554 59596042 21356650
+62	913	350
+76
+
+chain 10669 chr6 171115067 + 119157022 119157134 chr14 106368585 + 59942933 59943045 21369163
+112
+
+chain 9554 chr6 171115067 + 119189632 119189818 chrX 154913754 + 133155010 133155200 16872824
+37	54	54
+12	31	35
+52
+
+chain 7928 chr6 171115067 + 167846995 167847141 chr6_random 1875562 + 628575 628698 120
+41	26	0
+57	0	3
+22
+
+chain 7384 chr6 171115067 + 167920474 167920550 chr6_random 1875562 - 1829156 1829232 27447594
+76
+
+chain 7241 chr6 171115067 + 119190390 119190581 chr13 114142980 + 101174758 101174949 23777400
+2	136	136
+53
+
+chain 6904 chr6 171115067 + 119156272 119156345 chr11 134452384 - 108078565 108078638 28375374
+73
+
+chain 6531 chr6 171115067 + 119159999 119160068 chr4 191273063 - 87162214 87162283 29199925
+69
+
+chain 5948 chr6 171115067 + 119160915 119160977 chrX 154913754 - 59556739 59556801 30709264
+62
+
+chain 5818 chr6 171115067 + 119158407 119158509 chr18 76117153 + 30261305 30261403 24322730
+1	51	47
+50
+
+chain 5749 chr6 171115067 + 119155939 119156000 chr6 170899992 + 92063509 92063570 31228902
+61
+
+chain 5103 chr6 171115067 + 119189831 119189885 chrX 154913754 - 76833525 76833579 33162260
+54
+
+chain 5032 chr6 171115067 + 119156645 119156719 chrX 154913754 + 87420725 87420799 20704812
+74
+
+chain 5002 chr6 171115067 + 119160862 119160914 chrX 154913754 + 56955255 56955307 33524497
+52
+
+chain 4995 chr6 171115067 + 168994451 168994737 chr6 170899992 + 168737201 168737385 2349016
+31	205	103
+50
+
+chain 4921 chr6 171115067 + 119156041 119156093 chr9 140273252 + 81227536 81227588 33775667
+52
+
+chain 4912 chr6 171115067 + 119160087 119160139 chr5 180857866 + 63815067 63815119 33803556
+52
+
+chain 3597 chr6 171115067 + 119157136 119157361 chr2 242951149 + 31758724 31758949 14786968
+84	78	78
+63
+
+chain 3223 chr6 171115067 + 119156854 119156913 chr15 100338915 - 54365651 54365710 24573102
+59
+
+chain 3204 chr6 171115067 + 119155364 119155420 chr6 170899992 - 73613724 73613780 24603360
+56
+
+chain 2966 chr6 171115067 + 119156499 119156577 chrX 154913754 - 137505405 137505483 21485501
+78
+
+chain 2728 chr6 171115067 + 119159004 119159033 chr3 199501827 - 198198433 198198462 28454448
+29
+
+chain 2528 chr6 171115067 + 119156618 119156645 chr11 134452384 + 82352593 82352620 34284540
+27
+
+chain 2454 chr6 171115067 + 119155233 119155259 chr9 140273252 + 122001720 122001746 35057240
+26
+
+chain 2315 chr6 171115067 + 119156723 119156806 chr4 191273063 + 116661391 116661474 16361102
+83
+
+chain 2146 chr6 171115067 + 119158341 119158407 chr6 170899992 + 115819766 115819832 17078055
+66
+
+chain 1866 chr6 171115067 + 119190053 119190120 chr5 180857866 + 56063062 56063129 22879278
+67
+
+chain 1656 chr6 171115067 + 119158523 119158602 chr11 134452384 + 2473635 2473714 18654554
+79
+
+chain 1624 chr6 171115067 + 119189898 119189948 chr4 191273063 - 66123378 66123428 24040914
+50
+
+chain 1451 chr6 171115067 + 119158163 119158229 chr15 100338915 - 64161282 64161348 22109122
+66
+
+chain 1209 chr6 171115067 + 168994304 168994329 chr6 170899992 + 168736283 168736308 2117199
+25
+
+chain 1198 chr6 171115067 + 119156176 119156250 chr5 180857866 + 3717928 3718002 22194292
+74
+
+chain 980 chr6 171115067 + 119158602 119158634 chr8 146274826 + 104450758 104450790 18747323
+32
+
+chain 943 chr6 171115067 + 119157563 119157614 chr2 242951149 + 163020248 163020299 23359839
+51
+
+chain 785 chr6 171115067 + 119156425 119156485 chr17 78774742 - 29484860 29484920 22136428
+60
+
+chain 779 chr6 171115067 + 119190333 119190390 chr3 199501827 - 104453282 104453339 22453017
+57
+
+chain 696 chr6 171115067 + 119158674 119158726 chr6 170899992 - 83894386 83894438 23403881
+52
+
+chain 689 chr6 171115067 + 119157650 119157707 chrX 154913754 + 101935638 101935695 24716105
+57
+
+chain 360 chr6 171115067 + 119160319 119160372 chr3 199501827 - 158113258 158113311 26359861
+53
+
+chain 282 chr6 171115067 + 119159242 119159272 chr19 63811651 + 46835118 46835148 25343818
+30
+
+chain 202629822 chr6_apd_hap1 4622290 + 0 4622290 chr6 170899992 + 28804582 33443471 49
+932	3	0
+804	0	1
+2406	2	0
+178370	1	0
+25289	44253	44253
+3450	0	1
+345	1	0
+3096	39	0
+16669	1	0
+48609	0	2
+2804	29384	29384
+14756	7	0
+1489	1	1
+72	1	1
+2260	0	2
+7033	0	8
+3588	0	1
+9760	32	32
+9786	0	1
+1324	0	2
+5438	5	0
+2061	2	0
+3982	6	6
+1725	0	1
+3153	1	0
+18	1	0
+18	1	0
+2026	1	0
+4175	10	10
+4746	9	9
+4767	7	7
+1225	1	0
+8	1	1
+151	1	2
+5079	1	1
+28	1	1
+249	43	43
+1178	0	4
+685	8	0
+48	4	0
+1144	87598	87598
+5106	2	0
+1514	0	1
+3116	0	1
+3278	1	1
+21	1	1
+1738	0	1
+8576	19	0
+8020	1	0
+2049	1	0
+518	13	11
+1704	1	1
+117	1	1
+1448	10	0
+4403	9	9
+2265	1	0
+8656	104192	104192
+1686	0	2
+5376	0	1
+19253	1	0
+7884	1	0
+21	0	6
+4451	1	0
+27910	1	0
+9946	0	1
+11233	1	1
+32	1	1
+2238	1	1
+20	1	1
+3659	22	16
+1218	1	0
+1638	6	6
+228	1	1
+45	1	1
+2048	0	2
+462	1	0
+20759	1	0
+3778	2	1
+1268	1	0
+1511	1	1
+42	2	0
+24	1	1
+4119	22	0
+1757	1	0
+1527	1	1
+29	1	1
+1886	1	0
+6666	0	4
+1349	0	4
+1102	10	8
+1463	34	31
+168	1	1
+21	1	1
+304	1	1
+31	1	1
+549	1	0
+5745	1	0
+5097	0	1
+534	1	1
+17	1	1
+2233	1	1
+37	1	1
+3328	0	1
+4783	6	0
+3323	0	3
+965	1	0
+1234	28	0
+1194	1	0
+1855	18	18
+1024	0	1
+5932	1	0
+5395	9	9
+2759	0	10
+618	5	0
+667	0	8
+580	0	1
+109	1	1
+326	1	0
+9436	5	0
+6164	0	1
+1064	0	6
+1374	2	0
+3637	1	1
+32	1	1
+145	1	0
+1245	2	0
+1736	1	1
+29	1	1
+1656	1	5
+712	10	11
+502	0	1
+3670	1	0
+740	0	1
+1693	0	1
+6497	0	2
+2700	1	0
+198	1	3
+141	0	1
+1108	0	2
+1448	1	0
+947	31	31
+8047	4	0
+842	19167	19167
+101	1	0
+11	4	0
+297	0	24
+337	11	0
+134	1	1
+694	3	0
+72	1	1
+144	128	128
+169	2	0
+1011	1	0
+107	1	1
+1280	1	1
+73	1	1
+84	25	25
+287	1	1
+26	1	1
+139	1	1
+41	1	1
+440	4	0
+130	12	12
+435	18	0
+85	1	1
+28	1	1
+73	59397	59260
+107	0	32
+23	1	1
+116	1	1
+30	1	1
+503	1	1
+22	0	3
+136	1	1
+48	1	1
+330	9	9
+1108	1	1
+98	1	1
+582	0	4
+711	7	7
+89	1	0
+291	1	0
+167	1	1
+24	1	1
+167	6	6
+171	17	17
+681	1	1
+43	1	1
+538	1	1
+44	1	1
+537	16	16
+180	6	6
+778	2	2
+44	1	1
+168	0	7
+211	1	1
+42	1	1
+1253	1	1
+29	1	1
+320	1	1
+36	2	2
+55	1	2
+228	1	1
+17	1	1
+213	1	1
+35	1	1
+553	8	8
+386	1	1
+26	1	1
+540	1	1
+31	1	1
+65	0	1
+625	12	12
+313	0	1
+52	1	1
+22	1	1
+583	1	1
+49	1	1
+1499	3	0
+729	1	1
+40	1	1
+67	1	1
+19	11	0
+323	19	19
+787	1	1
+36	1	1
+553	8	8
+997	16	15
+157	1	1
+31	2	2
+204	18	19
+487	1	1
+29	1	1
+374	1	1
+67	1	1
+720	13	13
+266	10	10
+330	16	14
+413	1	1
+44	1	1
+78	6	6
+181	2	2
+36	1	1
+397	1	1
+20	1	1
+311	1	1
+48	2	2
+1746	4	4
+35	1	1
+194	10	10
+310	1	1
+51	1	1
+84	1	1
+101	1	1
+521	1	1
+23	1	1
+220	73	73
+1046	15	15
+216	1	1
+21	1	1
+51	1	1
+49	1	1
+527	17	17
+340	12	11
+1025	1	0
+2572	1	1
+29	1	1
+397	2	5
+668	13	13
+541	1	1
+59	0	2
+6	1	1
+122	14	14
+51	1	1
+46	1	1
+429	0	21
+136	1	1
+12	1	1
+66	16	16
+456	37	34
+371	7	7
+48	1	1
+194	10	10
+108	1	1
+60	1	1
+122	49	50
+238	1	1
+32	0	1
+100	1	0
+72	1	0
+390	1	1
+38	1	1
+144	1	1
+27	0	4
+184	21	228
+49	1	1
+608	0	1
+152	1	1
+31	1	1
+281	8	8
+337	1	1
+45	1	1
+222	1	1
+20	1	1
+380	1	0
+44	1	1
+368	1	1
+72	1	1
+502	36	18
+63	1	1
+43	0	4
+136	1	1
+42	1	1
+80	4	4
+35	1	0
+89	1	1
+24	0	5
+829	13	13
+102	14	0
+233	1	1
+42	0	3
+85	0	1
+400	1	1
+40	1	1
+538	25	25
+174	1	1
+20	1	1
+705	1	1
+26	2	2
+614	1	1
+44	1	1
+509	1	1
+32	1	1
+224	1	1
+42	1	1
+99	38	38
+610	5	5
+804	1	1
+29	1	1
+166	1	1
+43	1	1
+233	1	1
+44	1	1
+620	8	8
+133	1	1
+31	1	1
+165	1	1
+29	1	1
+1249	1	1
+26	4	0
+56	1	1
+67	1	1
+716	1	1
+46	0	1
+16	1	1
+174	1	1
+96	1	1
+141	1	1
+39	0	4
+263	1	1
+18	1	1
+259	4	4
+38	1	1
+104	1	1
+40	1	0
+248	1	1
+18	1	1
+238	1	1
+32	1	1
+70	0	2
+16	1	1
+818	1	1
+22	4	4
+1641	1	1
+46	1	1
+53	1	0
+38	1	1
+373	38443	100035
+112	1	1
+39	1	1
+330	1	1
+24	1	1
+197	1	1
+69	1	1
+116	3	0
+161	1	1
+38	1	1
+753	1	1
+57	3	3
+145	1	1
+121	1	1
+300	1	1
+147	1	1
+379	1	1
+55	2	2
+65	1	1
+32	1	1
+1008	1	1
+24	1	1
+159	18	18
+659	1	1
+76	0	2
+77	1	3
+65	1	1
+84	1	0
+119	1	1
+15	1	1
+247	4	0
+372	1	0
+1633	1	1
+16	1	1
+456	7	7
+114	1	1
+102	1	1
+109	4	0
+61	2	2
+80	1	1
+47	1	1
+168	1	1
+31	1	1
+269	2	2
+42	1	1
+626	2	2
+14	1	1
+76	8356	10147
+66	2	2
+80	0	41
+12	1	1
+158	1	0
+92	1	0
+254	1	1
+43	1	1
+846	6	149
+84	1	1
+29	3	3
+315	17	17
+482	1	1
+29	3	3
+278	1	1
+73	1	1
+2767	1	1
+34	1	1
+192	1	1
+33	1	0
+168	6	0
+276	10	10
+344	1	1
+49	1	1
+109	1	1
+35	3	3
+561	24	27
+923	1	1
+102	1	1
+75	14	14
+266	1	1
+80	2	2
+185	1	0
+1035	1	1
+23	1	1
+417	10	10
+97	1	1
+94	1	1
+492	1	1
+37	5	5
+1429	1	1
+19	1	1
+839	1	1
+96	1	1
+1279	4	0
+683	1	1
+49	1	1
+514	1	1
+28	4	4
+2302	1	1
+42	1	1
+537	2	21
+1555	1	1
+42	0	1
+14	4	4
+86	1	1
+62	1	1
+515	5	1
+330	0	1
+159	0	22
+3841	1	0
+3862	16	16
+1187	12	12
+97	0	3
+748	24594	24594
+686	1	0
+11541	1	0
+1843	0	4
+1157	16	16
+7354	19	0
+741	0	1
+8053	1	0
+4449	21	21
+649	1	0
+2913	0	1
+381	332	0
+3533	31	31
+2502	0	1
+1968	7	0
+3198	1	0
+667	1	0
+3870	0	1
+36	13	0
+1894	1	1
+40	0	4
+1137	2	0
+211	2	0
+345	1	0
+592	4	4
+1043	4	0
+686	14	0
+1032	0	1
+9035	0	4
+167	0	2
+23964	0	3
+1760	3	0
+3371	1	1
+23	1	1
+321	5	0
+644	8	0
+47	1	1
+322	1	1
+145	1	1
+1551	11	15
+355	0	1
+1831	4	0
+1779	1	1
+27	1	1
+199	43	55
+767	9786	9786
+338	0	1
+1002	0	1
+7912	4	0
+4977	0	1
+9275	2953	2950
+21511	0	1
+4385	0	7
+881	0	8
+17594	0	20
+2417	1	0
+998	0	10
+4239	7	0
+4845	0	2
+95	28	23
+10921	1	1
+40	1	1
+4759	0	6
+12084	0	3
+3052	0	4
+2989	1	0
+13523	1	3
+3050	104591	33135
+2281	0	7
+377	3	0
+7256	3	0
+419	2	0
+10674	0	17
+5362	16440	16440
+408	1	0
+3061	2	0
+5818	1	0
+2415	11	9
+2056	0	1
+955	4	0
+17260	1	0
+9557	0	2
+5358	0	1
+11548	13	13
+2604	2	0
+57496	1	1
+29	1	1
+6617	19	0
+12369	49753	49753
+608	0	5
+1926	1	1
+40	1	1
+330	3	0
+2327	0	1
+414	1	0
+61	0	1
+235	0	2
+2087	0	1
+713	0	8
+54	3	0
+1027	3	0
+428	1	1
+17	1	1
+948	1	1
+41	1	1
+458	1	1
+21	1	1
+1055	0	1
+8189	4	5
+36	1	1
+99	2	0
+700	0	3
+150	0	1
+750	0	3
+40	1	1
+3179	2	0
+473	0	2
+2032	1	0
+3841	1	0
+560	1	0
+1108	1	0
+8087	1	0
+5394	103872	103871
+16267	1	0
+18633	0	1
+920	0	1
+6820	1	0
+1376	1	2
+1931	33	33
+2376	0	1
+12415	1	1
+51	0	1
+9375	0	1
+323	1	0
+1715	154558	154558
+4522	85167	85167
+6234	0	3
+4009	0	5
+6425	2	0
+1119	2	0
+17	8	0
+2256	0	1
+3209	15	8
+2436	0	14
+1040	1	1
+52	1	1
+6972	1	0
+2357	0	1
+29	1	1
+262	1	0
+72	1	1
+45	1	1
+57	17	17
+1390	0	16
+328	312	0
+65	1	1
+217	10	10
+925	0	33
+1490	1	0
+35	1	1
+226	0	3
+805	1	1
+46	1	1
+192	1	1
+56	1	1
+245	1	1
+61	1	1
+198	4	0
+82	2	2
+29	1	1
+57	0	2
+320	1	1
+22	1	1
+267	5	0
+427	1	0
+17	1	1
+425	1	1
+34	1	1
+565	10	10
+432	9	0
+55	1	1
+90	1	1
+140	1	1
+83	1	1
+1035	1	1
+33	1	1
+144	4	4
+38	1	1
+171	1	1
+35	3	3
+161	6	6
+731	7	3
+1216	25	0
+52	0	1
+419	2	0
+87	1	1
+54	1	1
+4713	30	0
+791	3	0
+2849	1	1
+33	1	1
+6790	1	1
+67	4	4
+39	2	0
+251	1	1
+37	1	1
+826	3715	901
+205	2	0
+946	1	1
+30	1	1
+613	5	2
+128	29	29
+802	0	89
+1600	0	6
+2155	1	0
+1164	1	0
+1310	1	0
+2327	1	1
+42	1	1
+2266	1	0
+21451	401282	401282
+2475	1	1
+58	1	1
+375	25	27
+9941	0	1
+6798	0	19
+5779	11	10
+21042	0	1
+13887	36782	36752
+28930	1	1
+19	1	1
+1494	7	0
+148	15	0
+2797	0	2
+329	10	0
+2475	142825	142825
+382	4	0
+707	0	1
+12092	0	1
+2431	1	0
+158	0	1
+281	1	0
+1573	0	1
+11079	1	0
+6938	0	1
+14766	1	0
+4187	10	0
+11099	3	0
+9487	0	6
+467	1	0
+2143	1	0
+697	1	1
+25	0	6
+58	8	8
+1733	0	1
+259	2	0
+295	1	0
+128	0	1
+3052	0	1
+1419	13507	13507
+201	13	12
+15310	1	1
+26	1	1
+461	1	1
+33	0	2
+16	1	1
+649	1	1
+48	1	1
+818	1	1
+21	1	1
+424	1	1
+25	1	1
+632	1	1
+39	1	1
+310	1	1
+27	1	1
+616	1	0
+17240	4	0
+3936	3	0
+2976	174972	174972
+5315	0	20
+2124	0	1
+7445	45267	45267
+361	0	2
+1466	1	0
+6628	1	1
+110	0	1
+1422	0	1
+324	1	0
+1825	1	0
+311	0	1
+6568	1	0
+5228	1	0
+2273	2	1
+6123	1	0
+18640	29	29
+1283	0	3
+11560	6	6
+708	15	14
+1887	10	0
+509	1	0
+1581	1	1
+46	1	1
+811	1	1
+31	0	1
+1557	43	43
+1172	1	1
+18	1	1
+67	1	0
+2081	0	2
+373	0	4
+538	103035	103035
+2665	46	46
+554	0	21
+4473	2	3
+921	1	1
+47	1	1
+2605	9	3
+50	1	1
+178	1	1
+26	1	1
+316	0	2
+1120	4	0
+177	1	2
+960	1	1
+65	1	1
+964	4	4
+783	8	8
+61	34	13
+121	1	1
+22	1	0
+118	1	1
+49	4	4
+281	1	1
+27	1	1
+958	0	1
+107	1	1
+31	1	1
+171	14	14
+302	0	13
+33	1	1
+108	0	4
+98	1	1
+53	1	1
+986	1	1
+37	2	0
+1829	1	1
+38	1	1
+440	1	1
+82	3	4
+647	45	45
+660	1	1
+28	1	1
+1993	0	1
+373	19	19
+835	1	1
+42	1	1
+635	0	5
+307	1	1
+36	1	0
+1055	1	1
+43	1	1
+475	1	0
+60	1	1
+127	1	1
+509	1	1
+71	1	1
+485	1	0
+26	1	1
+531	1	1
+18	1	1
+551	1	1
+18	1	1
+884	5	5
+147	53	60
+527	1	1
+26	2	2
+322	0	17
+32	2	2
+85	1	1
+45	1	1
+625	0	323
+540	0	1
+43	1	1
+266	0	2
+228	1	1
+42	1	1
+283	1	1
+92	1	1
+381	1	1
+40	1	1
+1906	0	4
+3495	0	4
+561	36	36
+370	1	1
+76	1	1
+1824	3653	3651
+214	0	2
+499	1	0
+937	1	1
+45	1	1
+421	6	0
+87	22	22
+1254	1	1
+36	0	1
+357	18	18
+391	0	1
+451	1	0
+105	1	1
+47	1	0
+255	6	6
+739	3	0
+386	1	1
+33	1	1
+281	4	0
+481	2	0
+495	1	1
+42	4	0
+219	0	1
+408	1	1
+23	1	1
+283	1	1
+25	0	1
+541	1	0
+88	2	0
+216	1	1
+29	1	1
+457	1	0
+331	7	19
+181	15	15
+228	1	0
+4	2	0
+324	0	1
+3063	0	2
+11850	0	12
+839	0	1
+14260	0	2
+9658	4	3
+2813	12	12
+782	39571	39571
+1619	2	0
+164	8	1
+655	1	1
+30	1	1
+271	1	1
+47	1	1
+609	1	0
+516	1	1
+19	1	1
+1243	2	0
+742	1	1
+40	1	1
+3755	3	0
+13	1	1
+3819	0	1
+10010	1	0
+3051	1	1
+46	3322	3320
+1751	1	1
+103	1	2
+74	1	1
+93	1	0
+22	1	1
+149	4	0
+94	1	1
+31	7	0
+74	1	1
+275	1	0
+99	221094	247530
+272	5	5
+243	1	1
+84	1	1
+98	1	1
+50	5	5
+77	1	1
+74	1	1
+20	0	1
+143	1	1
+45	0	1
+4	1	1
+1088	1	1
+35	1	1
+320	1	1
+22	1	1
+275	1	1
+47	1	1
+370	19	19
+119	1	6
+51	1	1
+21	1	1
+244	0	1
+345	1	1
+24	1	1
+181	1	1
+61	3	3
+542	1	1
+16	1	1
+312	1	0
+353	4	3
+279	323	0
+86	1	1
+49	1	1
+342	1	1
+44	0	2
+222	1	1
+37	1	1
+588	8	8
+593	2	2
+44	1	1
+359	1	1
+25	1	1
+1612	14	14
+428	1	0
+2510	1	0
+5051	0	1
+1489	9	9
+3292	1	0
+1449	1	1
+21	1	1
+6768	1	0
+706	2	0
+6662	1	1
+30	1	1
+228	1	1
+28	0	2
+300	5	5
+887	1	1
+23	1	1
+104	9625	10000
+107	1	1
+47	0	1
+63	1	1
+114	1	1
+219	1	1
+63	9	9
+35	1	1
+290	0	4
+45	0	1
+54	0	1
+40	1	3
+21	6	6
+54	1	1
+41	1	1
+155	1	1
+29	1	1
+220	1	1
+27	1	1
+611	1	1
+163	1	1
+134	1	1
+16	1	0
+5	1	1
+151	15	15
+138	2	2
+27	1	1
+73	2	2
+97	1	1
+204	1	1
+47	1	1
+84	1	1
+74	2	2
+381	20	20
+425	1	1
+21	1	1
+71	1	1
+28	1	1
+245	25	22
+71	1	1
+93	1	0
+82	1	1
+129	1	1
+26	1	1
+294	16	16
+1139	0	1
+1588	0	1
+51	9	9
+60	26	25
+312	15	11
+1008	17	17
+85	1	1
+49	1	1
+702	1	0
+87	1	1
+37	1	1
+859	8	8
+296	4	4
+105	0	4
+43	1	1
+67	10	7
+2839	3	0
+1283	1	1
+67	0	1
+32	2	0
+61	1	1
+140	15	15
+1047	1	1
+38	1	1
+87	1	1
+24	5	4
+1291	1	1
+49	1	1
+421	0	1
+75	1	1
+78	1	1
+243	1	0
+33	1	1
+116	19	19
+65	0	1
+238	0	1
+179	2	1
+67	1	1
+60	1	1
+32	1	1
+677	4	6
+83	314	0
+334	1	0
+1018	5	5
+127	1	1
+83	1	1
+347	0	2
+111	1	1
+30	1	1
+66	1	1
+38	1	1
+218	8	8
+754	1	1
+65	1	1
+182	1	1
+21	1	1
+285	1	1
+75	1	1
+147	6	0
+65	1	1
+42	1	1
+380	1	1
+84	2	0
+88	1	1
+25	1	1
+210	1	1
+17	1	1
+136	6	5
+108	1	1
+40	1	0
+50	1	1
+111	1	0
+21	0	1066
+119	0	1
+2641	1	1
+22	1	1
+689	1	1
+41	1	1
+1415	1	1
+29	1	1
+2252	1	1
+19	1	1
+1524	0	10
+2104	0	1
+511	2	0
+1696	26	8
+2593	0	177
+338	1	1
+37	2	2
+395	10	0
+67	1	1
+131	1	1
+31	1	1
+386	1	1
+42	1	1
+372	1	1
+48	1	1
+8705	0	3
+330	9	9
+600	2	0
+261	8	8
+9909	0	2
+2337	2	0
+2567	1	1
+26	1	1
+561	1	1
+48	1	1
+2440	1	1
+30	1	1
+1289	0	1
+162	1	0
+730	0	3
+658	1	0
+25	1	1
+1027	1	1
+43	1	1
+472	0	1
+219	1	1
+20	1	1
+495	1	0
+6	2	0
+1007	0	1
+169	0	10
+33	1	1
+266	11	11
+752	1	1
+30	1	1
+438	1	1
+39	1	1
+511	0	1
+1247	1	0
+1055	1	0
+491	1	0
+108	1	1
+48	1	1
+1324	0	1
+143	1	1
+40	1	1
+679	1	1
+45	1	1
+1036	0	2
+58	1	1
+46	1	1
+229	16	16
+149	10	10
+94	1	1
+63	1	1
+222	1	0
+55	1	1
+115	5	1
+219	15	15
+692	28	28
+159	1	1
+41	1	1
+211	1	0
+20	1	1
+1099	0	4
+155	6	0
+178	13	15
+32	1	1
+953	1	1
+47	1	1
+174	1	1
+22	1	1
+401	0	13
+588	5	21
+130	1	1
+157	4	4
+86	1	1
+29	0	2
+67	3	0
+641	0	1
+571	0	1
+250	1	1
+34	1	1
+255	0	2
+572	12	12
+275	6	1
+974	0	1
+578	12	12
+612	1	1
+43	1	1
+56	0	7
+1170	0	1
+1236	0	4
+2118	5	0
+1090	0	2
+4424	1	1
+34	1	1
+4897	8	0
+2112	0	1
+2874	1	1
+21	1	1
+442	22	22
+805	0	1
+3476	16	0
+7063	0	1
+65	3	0
+4293	0	1
+3181	0	4
+9515	5	1
+172	1	1
+49	1	1
+320	1	1
+34	1	1
+10677	2	0
+4856	3	0
+6082	1	0
+955	0	1
+1720	6	0
+17	1	0
+8156	53709	53709
+819	9	0
+1244	1	1
+32	5	5
+2063	14	0
+357	3	0
+321	46	46
+873	1	1
+47	1	1
+1156	10	9
+1180	29	25
+247	9	9
+1870	0	1
+17	1	0
+366	7	7
+101	0	1
+134	8	8
+1654	0	4
+8741	1	1
+24	1	1
+991	0	210
+20	2	0
+906	13	13
+478	1	1
+21	1	1
+812	88	88
+2215	16	16
+1485	1	1
+18	1	1
+883	1	1
+20	1	1
+1354	1	1
+28	1	1
+283	5	5
+640	1	1
+40	1	1
+560	1	1
+42	1	1
+1144	19	19
+57	1	1
+21	1	1
+216	1	1
+109	1	1
+105	1	1
+208	5	5
+124	1	1
+112	3	3
+207	40	40
+244	1	1
+60	1	1
+98	1	1
+50	1	1
+256	5	5
+23	1	1
+157	1	1
+33	1	1
+143	1	1
+59	1	1
+51	1	1
+45	1	0
+73	1	1
+81	1	1
+427	1	1
+115	1	1
+232	1	1
+94	1	1
+809	1	0
+2261	16	15
+1824	1	0
+1990	1	0
+9965	0	18
+2951	6	0
+798	1	1
+30	1	1
+159	1	1
+124	1	1
+661	1	1
+31	1	1
+2632	4	4
+4024	0	16
+9373	7	7
+8626	0	1
+316	0	26
+10715	6	6
+110	1	1
+25	0	1
+7753	1	1
+30	0	1
+4078	0	2
+5144	1	1
+36	1	1
+69	1	1
+21	1	1
+135	1	1
+85	1	1
+125	3	4
+128	5	5
+24	1	1
+91	1	1
+61	15	0
+69	1	1
+78	0	19
+64	1	1
+138	1	1
+31	1	1
+510	18	7
+161	1	1
+30	1	1
+119	1	1
+26	1	1
+291	2	1
+143	1	1
+29	1	1
+293	1	1
+158	4	4
+87	32	32
+778	1	1
+58	0	1
+127	1	1
+75	28	0
+26	0	2
+204	207869	207869
+1739	1	0
+702	0	1
+5133	0	2
+3096	1	0
+315	1	0
+490	0	1
+2588	3	0
+1013	0	1
+3659	1	0
+2412	1	2
+2723	4	0
+523
+
+chain 80965 chr6_apd_hap1 4622290 + 2323391 2324248 chr6 170899992 - 139781917 139782778 1559018
+341	0	4
+516
+
+chain 30899 chr6_apd_hap1 4622290 + 1238363 1238687 chr13 114142980 + 81787211 81787535 4477038
+324
+
+chain 29563 chr6_apd_hap1 4622290 + 3995951 3996260 chr1 247249719 - 75038034 75038343 4838475
+309
+
+chain 28633 chr6_apd_hap1 4622290 + 2292529 2292831 chr7 158821424 - 147037095 147037398 5180885
+171	0	1
+131
+
+chain 28481 chr6_apd_hap1 4622290 + 4061349 4061647 chr17 78774742 + 29063769 29064067 5407270
+298
+
+chain 23990 chr6_apd_hap1 4622290 + 1105022 1105798 chr7 158821424 - 51137320 51138262 7695539
+178	101	101
+72	385	551
+40
+
+chain 15671 chr6_apd_hap1 4622290 + 1097871 1099106 chr6 170899992 - 139552636 139553881 14365447
+56	408	416
+54	620	622
+97
+
+chain 15338 chr6_apd_hap1 4622290 + 4034892 4035065 chr1 247249719 - 181871461 181871634 14713407
+25	1	0
+58	0	1
+89
+
+chain 13894 chr6_apd_hap1 4622290 + 1139363 1141753 chr6 170899992 + 30021566 30022999 16323533
+75	1920	964
+70	255	254
+70
+
+chain 11891 chr6_apd_hap1 4622290 + 3988844 3989392 chrX 154913754 + 64750681 64751228 19168306
+89	401	400
+58
+
+chain 11819 chr6_apd_hap1 4622290 + 1140317 1140448 chr19 63811651 + 15986621 15986752 19293908
+131
+
+chain 11746 chr6_apd_hap1 4622290 + 1091182 1091330 chr7 158821424 - 7754727 7754875 19419742
+54	14	14
+80
+
+chain 9888 chr6_apd_hap1 4622290 + 4031953 4032128 chr8 146274826 + 50466266 50466441 23070160
+60	56	56
+59
+
+chain 9560 chr6_apd_hap1 4622290 + 1092932 1093033 chr6 170899992 - 141000133 141000234 23851264
+101
+
+chain 7776 chr6_apd_hap1 4622290 + 4298814 4298901 chr8 146274826 + 14484871 14484958 2851549
+87
+
+chain 6175 chr6_apd_hap1 4622290 + 1094444 1094508 chr6 170899992 + 30079296 30079360 30094026
+64
+
+chain 6113 chr6_apd_hap1 4622290 + 3989871 3989936 chrX 154913754 - 39339630 39339695 30268027
+65
+
+chain 5831 chr6_apd_hap1 4622290 + 3989150 3989212 chr2 242951149 + 73586935 73586997 31012834
+62
+
+chain 5731 chr6_apd_hap1 4622290 + 1104489 1104550 chr6 170899992 + 29872087 29872148 31286972
+61
+
+chain 5730 chr6_apd_hap1 4622290 + 1107647 1107707 chr6 170899992 + 29878483 29878543 31293431
+60
+
+chain 5676 chr6_apd_hap1 4622290 + 1093802 1093862 chr8 146274826 - 42258664 42258724 31433499
+60
+
+chain 5492 chr6_apd_hap1 4622290 + 4034227 4034285 chr22 49691432 - 27111287 27111345 17799541
+58
+
+chain 5339 chr6_apd_hap1 4622290 + 3987866 3987922 chr2 242951149 + 186720203 186720259 32420506
+56
+
+chain 5203 chr6_apd_hap1 4622290 + 3989590 3989645 chr5 180857866 + 19136434 19136489 32834289
+55
+
+chain 4712 chr6_apd_hap1 4622290 + 4038649 4038699 chr4 191273063 + 53804403 53804453 34512110
+50
+
+chain 4392 chr6_apd_hap1 4622290 + 1105241 1105300 chr7 158821424 - 126060926 126060985 9905437
+59
+
+chain 2852 chr6_apd_hap1 4622290 + 4034783 4034846 chr15 100338915 + 44177073 44177136 17837211
+63
+
+chain 2740 chr6_apd_hap1 4622290 + 3988933 3988962 chr7 158821424 + 83092272 83092301 22772951
+29
+
+chain 2440 chr6_apd_hap1 4622290 + 3988349 3988416 chr3 199501827 + 102678562 102678629 22367094
+67
+
+chain 2360 chr6_apd_hap1 4622290 + 4034867 4034892 chr4 191273063 - 72949130 72949155 34483441
+25
+
+chain 2247 chr6_apd_hap1 4622290 + 4033024 4033048 chr20 62435964 - 19518135 19518159 35490184
+24
+
+chain 2194 chr6_apd_hap1 4622290 + 1105201 1105241 chrX 154913754 - 101365357 101365397 11073770
+40
+
+chain 2146 chr6_apd_hap1 4622290 + 1091395 1091456 chr12 132349534 + 104221177 104221238 23825288
+61
+
+chain 2000 chr6_apd_hap1 4622290 + 1105373 1105406 chr4 191273063 + 153905795 153905828 8127683
+33
+
+chain 1977 chr6_apd_hap1 4622290 + 3989088 3989138 chr18 76117153 - 10057795 10057845 19617710
+50
+
+chain 1946 chr6_apd_hap1 4622290 + 1105615 1105690 chr1 247249719 - 137852311 137852386 12720712
+75
+
+chain 1584 chr6_apd_hap1 4622290 + 1105480 1105544 chr1 247249719 - 24894387 24894451 17598706
+64
+
+chain 1098 chr6_apd_hap1 4622290 + 4034150 4034227 chr3 199501827 + 101474041 101474118 17425868
+77
+
+chain 917 chr6_apd_hap1 4622290 + 4034367 4034423 chr8 146274826 + 48207051 48207107 19960483
+56
+
+chain 847 chr6_apd_hap1 4622290 + 3988270 3988330 chr20 62435964 - 51574691 51574751 25106564
+60
+
+chain 754 chr6_apd_hap1 4622290 + 3988131 3988185 chr6 170899992 + 30241568 30241622 20370721
+54
+
+chain 747 chr6_apd_hap1 4622290 + 1105904 1105968 chr12 132349534 + 55464534 55464598 20643869
+64
+
+chain 716 chr6_apd_hap1 4622290 + 3989517 3989569 chr16 88827254 - 38714794 38714846 22851158
+52
+
+chain 604 chr6_apd_hap1 4622290 + 1105798 1105824 chrX 154913754 - 101148638 101148664 11583040
+26
+
+chain 420574415 chr6_cox_hap2 4795371 + 0 4795371 chr6 170899992 + 28585775 33459520 26
+95659	1	0
+2669	19	19
+7247	1	2
+1704	0	4
+1513	0	2
+49	2	0
+2160	0	5
+672	1	1
+38	1	1
+1384	1	0
+1685	1	1
+30	1	1
+2421	1	1
+42	1	1
+830	1	1
+41	1	1
+1630	0	1
+7458	1	0
+691	0	1
+525	0	1
+79	1	1
+29	1	1
+2055	1	1
+16	0	24
+1867	5	7
+786	0	2
+280	0	1
+227	2	0
+6678	1	0
+4401	1	0
+210	1	0
+3193	2	0
+3619	0	1
+2414	0	2
+5387	0	3
+2927	0	1
+3304	0	1
+440	0	5
+415	0	9
+3597	1	1
+48	1	1
+3412	1	1
+46	1	1
+3604	4	4
+1063	1	1
+36	1	1
+6311	0	1
+35	0	8
+393	0	1
+477	1	1
+37	1	1
+2459	2	0
+517	0	12
+318	0	1
+1010	7	6
+2103	0	1
+5171	0	8
+1483	1	0
+3813	888	0
+4675	0	2
+5620	1	0
+2017	1	0
+3363	0	5
+1197	0	3
+3208	1	0
+1928	1	0
+174	6	0
+780	1	3
+443	14	0
+3079	0	5
+1993	0	3
+1089	1	1
+58	1	1
+80	0	8
+256	2	0
+2473	37	43
+752	0	2
+33	0	2
+825	0	1
+787	1	1
+37	1	1
+1168	16	0
+377	5	1
+27	1	1
+2161	2	0
+2324	1	0
+1757	6	6
+205	4	0
+203	7	7
+107	1	1
+28	1	1
+100	4	4
+258	5	0
+659	1	0
+3805	5	8
+1486	4	4
+213	39	43
+4429	0	2
+1199	13	13
+5814	18	6
+2970	0	1
+813	0	17
+920	2	0
+3820	1	3
+130	21	9
+1913	0	14
+1800	0	1
+1255	2	0
+1466	4	0
+747	0	1
+124	2	0
+2108	1	0
+169	0	26
+593	1	0
+632	5	0
+2711	0	4
+1042	0	1
+34	1	1
+1025	2	0
+27	4	18
+81	1	33
+33	0	1
+6	0	76
+3950	1	0
+86	1	1
+12	1	1
+2947	0	1
+1160	1	0
+2046	3	0
+720	1	0
+1341	1	0
+10205	0	5
+1265	1	0
+10	1	1
+1278	5	6
+340	9	9
+50	0	32
+96	16	18
+605	4	0
+1072	12	12
+950	11	7
+5137	0	1
+2711	1	0
+676	0	1
+2904	1	1
+30	1	1
+851	0	1
+1410	0	1
+394	1	1
+57	1	1
+1561	0	2
+14360	1	1
+42	1	1
+269	1	0
+284	3	3
+24	1	0
+2796	0	5
+2451	28	0
+2251	1	1
+32	1	0
+10	0	4
+24	1	1
+694	0	2
+3475	0	1
+2008	1	1
+49	1	1
+475	1	1
+28	1	1
+259	160	0
+1854	5	4
+1621	3	0
+1791	1	0
+316	0	2
+1169	0	1
+2549	1	0
+2941	1	1
+34	1	1
+243	9	0
+5157	0	2
+1748	0	8
+472	4	0
+2470	0	4
+402	1	0
+643	2	0
+748	0	2
+859	1	0
+409	2	0
+267	0	2
+322	0	4
+155	1	0
+9957	0	4
+1440	4	4
+127	1	0
+1085	1	0
+131	1	0
+767	1	0
+1160	21	21
+1294	1	0
+712	1	0
+1819	2	1
+464	1	0
+6944	0	4261
+55	0	7
+1235	0	3
+702	0	24
+2847	0	1
+2428	3	0
+7517	0	1
+3204	1	0
+611	1	0
+7104	1	0
+4959	14	14
+2827	1	0
+9421	82	25
+2434	43	43
+1951	8	0
+8136	0	2
+344	1	0
+4216	1	0
+810	0	5
+4443	1	0
+10291	10	0
+7265	5	0
+7041	1	0
+6007	1	0
+8185	4	0
+4961	0	3
+13564	0	1
+1475	0	2
+105	0	10
+10104	2	0
+3073	1	0
+3715	8	0
+13731	0	2
+837	61	1
+9404	0	1
+6068	7	0
+916	0	4
+569	1	1
+72	1	1
+2260	0	2
+7036	4	0
+3591	0	3
+713	4	0
+10388	0	2
+8475	0	1
+1324	0	2
+5438	5	0
+156	1	1
+44	0	1
+21501	7	7
+3359	16	16
+2138	0	5
+4406	11	11
+1525	1	1
+28	1	1
+2159	16	0
+48	4	0
+3030	0	1
+5717	10	0
+6594	2	0
+1954	1	0
+4	1	0
+3599	1	0
+7515	4	0
+979	0	2
+1990	0	10
+123	1	1
+27	1	1
+1255	0	2
+2769	5	5
+727	1	1
+26	3	3
+785	0	1
+24359	1	0
+5978	5	5
+66	1	1
+46	1	1
+18539	1	0
+7732	2	0
+652	0	1
+861	0	1
+11988	0	1
+3515	3	0
+19	18	0
+539	0	1
+655	2	0
+10586	2	0
+2385	0	1
+2979	10	10
+4600	1	0
+29834	1	1
+27	1	1
+1216	1	0
+1323	1	0
+673	0	3
+20031	0	3
+2841	13	0
+1841	4	0
+6446	1	0
+11727	0	1
+8427	17	17
+2864	0	143
+4107	0	8
+748	0	2
+3417	1	1
+32	1	1
+18799	0	2
+21810	1	1
+34	1	1
+2784	2	0
+7864	2	0
+4498	0	1
+49089	1	1
+32	1	1
+509	1	1
+37	1	1
+5371	22	16
+389	1	1
+21	1	1
+806	1	0
+1638	6	6
+228	1	1
+45	1	1
+2068	6	3
+441	1	0
+2338	1	0
+1948	1	1
+26	1	1
+214	0	1
+6118	1	1
+31	1	1
+2382	5	5
+4335	1	1
+39	1	1
+4561	1	1
+38	1	1
+2199	1	1
+49	1	1
+243	19	6
+2779	1	1
+37	2	0
+24	1	1
+1966	3	0
+233	1	1
+29	1	1
+13756	0	4
+3956	4	1
+46569	1	0
+18985	0	8
+1384	3	1
+85	1	0
+3539	1	1
+32	1	1
+145	1	0
+1245	2	0
+1736	1	1
+29	1	1
+1656	1	5
+712	10	11
+502	0	1
+3670	1	0
+740	0	1
+1693	0	1
+6497	0	2
+2898	1	3
+141	0	1
+1108	0	2
+1448	1	0
+947	31	31
+362	0	1
+7684	8	0
+2880	1	2
+30	8	0
+896	21	3
+395	1	1
+37	3	0
+23	1	2
+1210	18	0
+65	1	1
+20	1	1
+791	0	4
+389	1	0
+809	1	1
+55	0	7
+428	1	1
+17	1	1
+239	1	1
+20	1	1
+69	1	1
+37	1	1
+955	1	0
+839	0	1
+165	1	0
+3867	0	5
+70	1	1
+27	1	1
+899	1	2
+107	1	0
+1457	1	0
+763	12	5
+35	1	1
+1417	10	10
+121	1	1
+38	0	3
+377	1	0
+505	1	0
+11	4	0
+297	0	24
+337	11	0
+134	1	1
+694	3	0
+72	1	1
+144	128	128
+169	2	0
+1011	1	0
+107	1	1
+1280	1	1
+73	1	1
+84	25	25
+287	1	1
+26	1	1
+139	1	1
+41	1	1
+440	4	0
+130	12	12
+435	21	0
+85	1	1
+28	1	1
+73	1	1
+115	5	1
+70	1	2
+52	2	0
+157	30	30
+554	2	2
+128	1	5
+68	1	1
+44	1	1
+125	0	1
+57	1	1
+308	0	7
+15	1	1
+725	9	0
+60	1	1
+180	1	1
+55	1	1
+61	1	1
+23	1	0
+5	1	2
+88	1	1
+56	1	1
+433	2	0
+84	1	1
+66	1	1
+182	12	12
+216	1	1
+94	1	1
+561	1	1
+16	1	1
+113	1	1
+86	1	1
+148	2	0
+75	2	0
+77	1	21
+209	3	8
+99	31	31
+244	1	0
+173	4	3
+201	1	1
+42	1	1
+56	1	1
+115	1	0
+327	1	1
+54	5	5
+929	1	1
+21	1	1
+97	1	1
+28	0	3
+830	0	2
+68	1	1
+525	0	1
+2081	1	1
+41	1	1
+165	3	3
+46	1	0
+378	1	1
+49	1	1
+352	0	1
+142	1	1
+30	1	1
+95	1	1
+45	1	1
+227	1	1
+53	1	1
+130	1	1
+18	1	1
+138	1	1
+90	1	1
+129	1	1
+39	1	1
+50	1	1
+79	1	1
+117	1	1
+31	1	1
+240	5	5
+57	1	1
+152	1	1
+30	1	1
+177	5	5
+321	1	1
+63	1	1
+504	18	18
+662	1	1
+74	1	1
+248	1	1
+34	1	1
+1507	0	10
+1051	0	2611
+560	3	3
+23	1	1
+1631	0	15
+78	4	0
+160	0	21
+3764	0	4
+1358	0	1
+1773	1	1
+43	1	1
+1263	1	1
+39	1	1
+183	0	16
+3001	40	40
+1056	10	0
+1261	1	1
+20	1	1
+137	1	0
+2351	1	1
+43	1	1
+1010	0	4
+536	1	1
+38	1	1
+381	0	1
+888	19	19
+1521	1	1
+27	1	1
+161	1	1
+46	1	1
+2659	2	0
+533	10	0
+441	1	12
+1684	1	1
+26	3	4
+879	16	16
+514	0	2
+58	1	1
+117	1	1
+24	1	1
+207	1	0
+38	1	1
+730	1	1
+39	1	1
+573	0	4
+37	1	1
+144	8	8
+1036	2	0
+262	2	2
+38	0	1
+70	18	18
+84	11	13
+317	0	3
+1256	0	2
+332	1	1
+21	1	1
+193	8	28
+30	1	1
+79	1	1
+29	1	1
+536	1	0
+611	1	1
+25	1	1
+399	4	4
+118	0	32
+23	1	1
+116	1	1
+30	1	1
+503	1	1
+22	0	3
+136	1	1
+48	1	1
+330	9	9
+1108	1	1
+98	1	1
+582	0	4
+711	7	7
+89	1	0
+291	1	0
+167	1	1
+24	1	1
+167	6	6
+171	17	17
+681	1	1
+43	1	1
+538	1	1
+44	1	1
+537	16	16
+180	6	6
+778	2	2
+44	1	1
+168	0	7
+211	1	1
+42	1	1
+1253	1	1
+29	1	1
+320	1	1
+36	2	2
+55	1	2
+460	1	1
+35	1	1
+553	8	8
+386	1	1
+26	1	1
+540	1	1
+31	1	1
+65	0	1
+625	12	12
+313	0	1
+52	1	1
+22	1	1
+583	1	1
+49	1	1
+1499	3	0
+770	1	1
+87	11	0
+323	19	19
+787	1	1
+36	1	1
+553	8	8
+997	16	15
+157	1	1
+31	2	2
+204	18	19
+487	1	1
+29	1	1
+374	1	1
+67	1	1
+720	13	13
+266	10	10
+330	16	14
+413	1	1
+44	1	1
+78	6	6
+181	2	2
+36	1	1
+397	1	1
+20	1	1
+311	1	1
+48	2	2
+1746	4	4
+35	1	1
+194	10	10
+310	1	1
+51	1	1
+136	1	1
+49	1	1
+521	1	1
+23	1	1
+220	73	73
+735	3	3
+123	1	1
+184	15	15
+216	1	1
+21	1	1
+51	1	1
+49	1	1
+527	17	17
+340	12	11
+1025	1	0
+2572	1	1
+29	1	1
+397	2	5
+668	13	13
+541	1	1
+59	0	2
+6	1	1
+122	14	14
+51	1	1
+46	1	1
+429	0	21
+136	1	1
+12	1	1
+66	16	16
+456	37	34
+371	7	7
+48	1	1
+194	10	10
+108	1	1
+60	1	1
+122	49	50
+238	1	1
+32	0	1
+100	1	0
+72	1	0
+390	1	1
+38	1	1
+144	1	1
+27	0	4
+184	21	228
+49	1	1
+608	0	1
+152	1	1
+31	1	1
+281	8	8
+337	1	1
+45	1	1
+222	1	1
+20	1	1
+380	1	0
+44	1	1
+368	1	1
+72	1	1
+502	36	18
+63	1	1
+43	0	4
+136	1	1
+42	1	1
+80	4	4
+35	1	0
+89	1	1
+24	0	5
+829	13	13
+102	14	0
+233	1	1
+42	0	3
+85	0	1
+400	1	1
+40	1	1
+538	25	25
+174	1	1
+20	1	1
+705	1	1
+26	2	2
+614	1	1
+44	1	1
+509	1	1
+32	1	1
+224	1	1
+42	1	1
+99	38	38
+610	5	5
+804	1	1
+29	1	1
+166	1	1
+43	1	1
+233	1	1
+44	1	1
+620	8	8
+133	1	1
+31	1	1
+165	1	1
+29	1	1
+1249	1	1
+26	4	0
+56	1	1
+67	1	1
+716	1	1
+46	0	1
+16	1	1
+174	1	1
+96	1	1
+141	1	1
+39	0	4
+263	1	1
+18	1	1
+259	4	4
+38	1	1
+104	1	1
+40	1	0
+248	1	1
+18	1	1
+238	1	1
+32	1	1
+70	0	2
+16	1	1
+818	1	1
+22	4	4
+1641	1	1
+46	1	1
+53	1	0
+38	1	1
+373	62	62
+1149	0	2
+19	1	1
+1653	4	4
+42	1	1
+218	12	12
+363	1	1
+24	1	1
+457	10	10
+414	13	13
+825	1	1
+41	1	1
+492	0	8
+1370	1	1
+18	1	1
+1145	6	4
+880	1	1
+35	1	1
+236	1	1
+67	1	1
+298	0	1
+147	14	14
+312	11	11
+613	1	1
+62	1	1
+340	1	1
+22	1	1
+1057	1	1
+57	1	1
+358	1	1
+128	1	1
+146	10	10
+490	1	1
+20	1	1
+62	1	1
+88	1	1
+293	1	1
+28	1	0
+20	1	1
+83	0	1
+90	1	1
+312	1	1
+44	1	1
+1213	1	1
+51	1	1
+467	1	1
+39	1	1
+122	14	0
+35	1	1
+485	14	14
+110	13	0
+127	1	1
+7112	0	8
+45	4	0
+3276	0	2
+28	1	1
+2195	17	16
+1325	18	18
+1304	3727	0
+299	0	248
+2603	2	0
+160	1	1
+34	1	1
+631	1	1
+40	1	3
+38	1	1
+332	17	17
+231	14	14
+202	1	1
+199	1	1
+71	1	1
+42	1	0
+53	11	10
+83	1	1
+31	1	1
+135	1	1
+50	3	0
+32	1	1
+194	1	1
+45	1	1
+143	1	1
+78	1	1
+193	6	0
+40	1	1
+432	1	1
+17	1	1
+429	3	6
+58	236	236
+57	1	1
+51	2	2
+278	1	1
+49	1	1
+77	11	11
+120	0	4
+139	1	1
+30	2	2
+205	4	4
+131	1	1
+22	1	1
+251	1	1
+34	1	1
+175	1	1
+36	1	1
+239	1	1
+32	5	5
+63	1	1
+27	1	1
+78	1	1
+19	1	1
+209	1	1
+143	1	13
+176	0	1
+7	0	8
+375	0	1
+62	1	1
+129	2	2
+135	1	1
+88	8	0
+90	6	8
+796	2	0
+1219	1	1
+34	1	1
+833	1	1
+46	1	1
+74	1	1
+45	1	1
+95	1	1
+29	1	1
+298	0	3
+47	1	1
+311	1	1
+58	1	1
+349	9	9
+214	1	1
+37	3	0
+413	11	11
+54	1	1
+97	1	1
+137	0	2
+95	1	1
+257	3	0
+35	1	1
+66	1	1
+47	1	1
+104	7	7
+220	17	17
+207	44327	50000
+112	1	1
+39	1	1
+330	1	1
+24	1	1
+197	1	1
+69	1	1
+116	3	0
+161	1	1
+38	1	1
+753	1	1
+57	3	3
+145	1	1
+121	1	1
+300	1	1
+147	1	1
+379	1	1
+55	2	2
+65	1	1
+32	1	1
+1008	1	1
+24	1	1
+159	18	18
+659	1	1
+76	0	2
+77	1	3
+65	1	1
+84	1	0
+119	1	1
+15	1	1
+247	4	0
+372	1	0
+1633	1	1
+16	1	1
+456	7	7
+114	1	1
+102	1	1
+109	4	0
+61	2	2
+80	1	1
+47	1	1
+168	1	1
+31	1	1
+269	2	2
+42	1	1
+626	2	2
+14	1	1
+76	8356	10147
+66	2	2
+80	0	41
+12	1	1
+158	1	0
+92	2	0
+254	1	1
+43	1	1
+846	6	149
+84	1	1
+29	3	3
+315	17	17
+482	1	1
+29	3	3
+278	1	1
+73	1	1
+2767	1	1
+34	1	1
+192	1	1
+33	1	0
+168	6	0
+276	10	10
+344	1	1
+49	1	1
+109	1	1
+35	3	3
+561	24	27
+923	1	1
+102	1	1
+75	14	14
+266	1	1
+80	2	2
+185	1	0
+1035	1	1
+23	1	1
+417	10	10
+97	1	1
+94	1	1
+492	1	1
+37	5	5
+1429	1	1
+19	1	1
+839	1	1
+96	1	1
+1279	4	0
+683	1	1
+49	1	1
+514	1	1
+28	4	4
+2302	1	1
+42	1	1
+537	2	21
+1555	1	1
+42	0	1
+14	4	4
+86	1	1
+62	1	1
+515	5	1
+330	0	1
+159	0	22
+3841	1	0
+3862	16	16
+1187	12	12
+97	0	3
+772	1	1
+21	2	1
+1058	0	2
+349	2	0
+1080	6	0
+11	1	3
+53	0	2
+14	1	1
+1035	1	1
+85	1	1
+69	1	1
+27	1	1
+547	7	7
+195	1	1
+41	1	1
+395	1	1
+35	1	1
+73	0	1
+71	1	1
+557	3	3
+30	1	1
+66	1	1
+25	1	1
+1332	0	2
+26	2	0
+10	1	15
+36	1	1
+196	1	1
+40	1	1
+141	1	1
+76	1	1
+1480	1	3
+347	1	1
+26	1	1
+231	1	1
+82	3	3
+69	3	0
+441	16	16
+147	1	1
+21	1	1
+3565	0	3
+877	2	0
+1036	1	1
+47	2	1
+3761	12	0
+5345	1	0
+11541	1	0
+1843	0	4
+1157	16	16
+7354	19	0
+741	0	1
+8053	1	0
+4449	21	21
+649	1	0
+2913	0	1
+381	331	0
+3533	31	31
+2502	0	1
+1968	7	0
+3198	1	0
+667	1	0
+3870	0	1
+36	13	0
+1894	1	1
+40	0	4
+1137	6	0
+211	2	0
+345	1	0
+592	4	4
+1043	4	0
+686	14	0
+1032	0	1
+9035	0	4
+167	0	2
+23964	0	3
+1470	0	1
+289	3	0
+4343	1	0
+2026	8	0
+430	0	1
+631	1	1
+21	1	1
+479	0	1
+697	4	0
+1779	1	1
+27	1	1
+196	4	0
+58	8	0
+2881	1	1
+39	1	1
+120	1	2
+24	1	1
+556	1	0
+393	6	6
+3090	1	1
+43	1	1
+1246	1	0
+294	1	1
+27	1	1
+374	3	3
+144	1	1
+190	1	6
+750	1	0
+695	2	0
+1003	11	0
+1956	0	4
+1235	19	19
+1483	11	11
+453	1	0
+536	1	1
+43	1	1
+57	1	0
+21	7	0
+3892	0	1
+3177	0	1
+8990	0	2
+2267	1	1
+35	1	0
+2850	4	0
+1273	0	2
+5863	1	0
+9593	1	1
+81	1	1
+2777	0	2
+5272	0	8
+11548	2	0
+6086	0	1
+109	1	1
+2286	0	1
+997	0	18
+3344	1	1
+40	1	1
+842	28	24
+1584	1	0
+1582	0	1
+1670	3	25
+17	0	4
+16	2	0
+6	12	0
+49	1	1
+538	1	1
+26	1	1
+5879	2	4
+2513	0	1
+346	8	8
+222	16	16
+103	1	0
+198	1	3
+539	1	1
+47	1	1
+1154	0	1
+3737	1	2
+370	2	0
+1178	1	1
+78	1	1
+47	0	1
+518	6	0
+646	13	13
+469	1	0
+1072	1	4
+858	1	0
+3674	1	0
+282	1	0
+597	0	6
+505	4	4
+183	1	1
+43	1	1
+1294	1	1
+40	1	1
+572	0	4
+464	0	4
+1886	2	0
+548	1	0
+1300	0	3
+1839	2	0
+189	1	1
+49	1	1
+1253	1	1
+43	1	0
+498	1	1
+45	4	0
+3538	0	1
+1582	31	31
+376	14	14
+1332	2	0
+3586	1	0
+989	1	2
+447	0	4
+40	1	1
+2445	16	17
+291	1	3
+7	1	0
+11	0	1
+41	1	1
+94	1	1
+49	1	1
+1515	6	0
+603	13	13
+163	1	1
+45	1	1
+2050	11	11
+1126	1	1
+16	1	1
+391	1	1
+19	0	1
+932	1	0
+42	1	1
+751	1	0
+287	1	1
+42	1	1
+464	0	4
+4069	5	5
+153	1	0
+514	2	0
+1093	1	1
+41	1	1
+1746	4	4
+1351	1	1
+38	1	1
+1213	0	72
+168	18	18
+146	7	7
+293	1	1
+61	0	1
+43	1	1
+236	1	0
+35	1	1
+152	14	14
+240	13	13
+523	0	4
+809	4	0
+155	1	1
+44	1	1
+1068	1	1
+93	1	1
+209	15	15
+1331	0	3
+3912	0	1
+6624	0	4
+375	0	1
+7255	5	0
+419	2	0
+293	1	0
+10397	5	24
+11095	0	1
+1770	4	0
+374	0	4
+7714	1	0
+1229	7	6
+3055	1	0
+5818	1	0
+2415	11	9
+2056	0	1
+955	4	0
+3907	0	2
+16936	0	1
+1044	1	0
+2392	0	1
+158	2	1
+199	0	1
+75	6	6
+2094	8	0
+649	2	0
+373	1	1
+39	1	1
+2287	1	0
+15	1	0
+1995	0	2
+818	4	0
+676	0	1
+3171	8	0
+170	0	3
+459	1	1
+37	1	1
+336	1	0
+206	1	1
+26	1	1
+224	15	15
+308	2	1
+82	1	1
+23	1	1
+562	1	1
+80	1	1
+241	0	8
+1530	1	1
+20	1	1
+1372	1	1
+44	1	1
+427	1	1
+20	1	1
+651	105	81
+221	1	1
+45	1	1
+1747	1	1
+27	1	1
+179	1	1
+70	1	1
+173	1	1
+84	0	36
+1864	1	1
+41	1	1
+44	9	0
+1028	1	0
+85	1	1
+21	1	1
+474	1	3
+256	1	1
+31	1	1
+653	1	1
+18	1	1
+62	1	1
+19	1	1
+997	1	1
+22	1	1
+326	1	0
+505	5	4
+386	0	7
+466	13	13
+870	11	12
+134	15	15
+248	0	2
+2281	1	1
+79	1	1
+56	9	6
+528	1	1
+68	1	1
+802	1	0
+290	1	1
+38	1	1
+185	1	1
+61	1	1
+944	1	1
+22	1	1
+835	1	1
+66	1	1
+890	0	1
+3503	6	6
+231	0	1
+2136	1	0
+999	1	0
+5220	3	4
+830	1	1
+24	1	1
+1209	1	1
+38	1	1
+7077	1	0
+2939	1	0
+3511	47	47
+401	0	2
+3746	0	2
+1011	1	1
+34	1	1
+7443	0	1
+688	2	0
+574	1	1
+29	1	1
+1785	2	0
+16	20	0
+4073	2	0
+136	79	79
+528	27	0
+253	0	1
+204	1	0
+129	2	0
+811	1	1
+38	1	1
+2347	52	0
+4634	1	0
+856	14	14
+1052	1	1
+28	1	1
+1255	1	1
+36	1	1
+97	0	1
+58	1	1
+1708	1	1
+48	1	1
+958	13	0
+3371	1	1
+37	1	1
+4267	0	15
+1059	0	1
+272	0	20
+168	2	0
+26	4	32
+4090	0	2
+3269	1	1
+17	1	2
+1378	1	0
+1443	0	1
+6206	1	0
+2318	0	1
+7695	2	0
+396	22	12
+918	0	1
+1818	0	1
+28	1	1
+492	1	1
+33	1	1
+326	1	1
+80	1	1
+288	8	17
+2671	0	1
+1099	0	1
+144	1	1
+29	0	1
+2098	0	2
+24	4	0
+1207	4	4
+45	1	1
+757	0	5
+1926	1	1
+40	1	1
+2657	0	1
+414	1	0
+61	0	1
+235	0	2
+2087	0	1
+713	0	4
+58	1	0
+1027	3	0
+428	1	1
+17	1	1
+948	1	1
+41	1	1
+458	1	1
+21	1	1
+1055	0	1
+8189	4	5
+36	1	1
+102	2	0
+14	1	1
+682	0	6
+147	0	1
+750	0	3
+40	1	1
+2428	0	1
+750	2	0
+473	0	2
+2032	1	0
+3841	1	0
+560	1	0
+1108	1	0
+8087	1	0
+11881	1	1
+30	1	1
+4383	2	0
+10078	0	1
+906	2	0
+887	1	1
+80	1	1
+2210	1	0
+905	0	1
+1037	1	0
+5866	0	2
+18	1	1
+582	0	5
+2828	1	0
+847	1	0
+1996	4	0
+700	1	1
+2469	1	0
+1751	0	1
+910	2	0
+691	0	1
+32873	0	1
+1722	0	1
+17575	0	8
+1369	29	0
+494	2	0
+4432	0	1
+34617	0	1
+920	0	1
+4586	0	2
+2232	1	0
+5718	0	1
+12415	1	1
+51	0	1
+7997	0	2
+1700	1	0
+2697	1	0
+2561	2	0
+1544	0	6
+1613	3	7
+37	9	1
+2113	1	0
+7174	0	34
+7914	1	1
+35	1	1
+5308	1	0
+2303	2	1
+423	7	7
+590	1	0
+24	1	1
+165	6	0
+896	33	33
+1919	13	13
+64	0	1
+28	1	1
+723	0	4
+2868	0	1
+731	1	1
+60	1	1
+1012	3	0
+1744	1	1
+78	1	1
+61	1	0
+2362	11	11
+399	1	0
+1494	16	16
+128	24	24
+530	1	1
+35	1	1
+5276	1	0
+415	0	1
+580	1	2
+1450	22	23
+816	1	0
+1953	1	0
+881	10	1
+885	8	14
+183	14	14
+1319	1	1
+94	1	1
+419	3	3
+26	1	1
+56	1	0
+69	1	0
+117	1	1
+120	1	1
+42	1	1
+834	125	127
+956	3	0
+664	1	1
+41	1	1
+716	4	0
+1731	8	8
+4228	0	1
+5694	3	0
+4493	0	1
+1373	20	20
+1263	1	0
+3029	4	0
+5702	7	6
+150	2	0
+5972	0	2
+840	0	2
+55	1	1
+28	1	1
+2949	5	6
+4343	6	0
+1663	4	0
+150	1	0
+3128	1	0
+1449	3	0
+1534	1	0
+489	1	0
+431	0	4
+299	2	0
+5082	9	0
+156	1	1
+256	0	1
+992	14	16
+4924	0	1
+6655	1	0
+349	8	7
+762	1	1
+29	0	3
+1434	0	1
+1267	0	1
+587	1	1
+22	0	1
+894	28	0
+1343	2	0
+2256	0	1
+4332	0	4
+22	1	1
+5069	33	33
+7313	12	10
+10485	0	1
+1429	0	12
+625	1	7
+1224	0	10
+1680	4	0
+9061	0	8
+2544	0	140
+5451	33	33
+3754	0	1
+1575	0	3
+1775	1	1
+31	1	1
+1200	1	0
+32	0	3
+790	0	8
+42	0	2
+599	1	1
+22	1	1
+5338	2	0
+1998	0	5
+146	0	4
+12031	0	1
+1993	0	1
+706	2	0
+2735	0	1
+3859	0	4
+1304	47	47
+3494	0	2
+268	2	0
+827	4	4
+1063	6	6
+7834	2	0
+3195	0	1
+4012	10	0
+6429	0	2
+308	0	1
+808	1	0
+17	8	0
+5472	19	2
+2436	0	14
+820	9	9
+2643	1	1
+32	1	1
+1189	1	0
+5710	0	3
+308	1	0
+3028	14	14
+1888	0	1
+4308	1	0
+946	82	0
+1790	0	2
+1218	25	0
+52	0	1
+1271	1	1
+33	1	1
+4760	1	0
+4924	0	1
+4817	4	4
+39	1	0
+1116	3715	901
+205	1	0
+1591	5	2
+128	29	29
+802	0	89
+1600	0	6
+2175	0	5
+606	14	14
+519	1	0
+540	1	1
+40	1	1
+568	2	0
+458	1	1
+41	1	1
+1106	24	62
+818	1	1
+42	1	1
+2266	1	0
+14059	0	4
+5030	1	0
+12630	0	3
+84	9	9
+129	13	18
+564	10	15
+154	1	0
+438	10	10
+38	0	5
+98	11	9
+2034	1	1
+25	1	1
+73	10	10
+70	5	5
+132	1	1
+52	1	1
+599	1	1
+46	1	1
+279	1	1
+18	1	1
+239	3	0
+383	6	0
+224	0	1
+321	15	0
+1783	1	1
+18	3	0
+575	16	16
+60	1	1
+16	1	1
+970	1	1
+24	1	1
+424	3	0
+41	1	1
+57	8	8
+285	2	0
+672	1	1
+44	1	4
+103	0	1
+148	1	1
+49	3	0
+146	5	11
+91	1	1
+79	1	1
+94	1	1
+101	1	1
+88	16	16
+117	1	1
+15	1	1
+58	1	1
+93	1	1
+466	1	1
+44	1	1
+160	1	1
+23	1	1
+481	14	14
+181	4	4
+72	1	1
+25	1	1
+82	7	12
+4	0	1
+11	1	4
+20	0	5
+92	1	1
+56	10	0
+80	1	1
+141	2	0
+60	1	1
+372	0	2
+784	1	1
+85	1	1
+109	1	1
+16	1	1
+57	1	1
+92	3	1
+23	1	0
+26	1	1
+74	1	1
+33	1	1
+176	1	1
+25	2	2
+193	42	43
+377	0	5
+249	1	1
+69	1	1
+98	1	1
+70	1	1
+55	1	1
+143	1	1
+438	1	1
+64	1	1
+53	4	0
+127	3	0
+75	5	5
+45	1	1
+197	1	1
+27	1	1
+116	13	13
+218	15	20
+1107	16	19
+73	1	1
+25	1	1
+199	1	1
+60	1	1
+994	1	1
+43	0	1
+18	1	1
+1215	18	18
+340	1	1
+34	1	1
+2783	1	1
+29	1	1
+475	82	82
+166	10	10
+87	1	1
+18	1	1
+171	7	7
+427	1	1
+21	1	1
+2011	0	3
+17	1	1
+1412	1	1
+24	1	1
+214	8	4
+228	1	1
+34	1	1
+410	16	16
+185	1	1
+24	1	0
+164	0	1
+222	1	1
+25	1	1
+297	10	10
+1171	1	0
+3343	1	0
+11	1	1
+2502	1	1
+23	1	1
+44	12	0
+2856	0	1
+148	1	1
+36	1	1
+993	2	0
+1251	2	0
+6619	14	14
+1014	4	0
+134	2	9
+818	1	0
+61	1	7
+563	46	0
+78	5	5
+1677	1	1
+49	1	1
+399	1	1
+32	1	1
+790	27	27
+104	1	1
+75	1	1
+1638	1	1
+16	1	1
+92	1	1
+44	1	1
+276	0	13
+1020	1	1
+35	1	1
+389	14	14
+256	1	0
+38	1	3
+631	1	1
+40	1	1
+2356	1	1
+82	2	0
+1300	0	5
+511	0	2
+605	1	1
+17	1	1
+880	12	0
+1689	4	0
+2492	1	1
+39	1	1
+641	16	16
+682	0	5
+669	1	1
+25	1	1
+1926	1	1
+39	4	3
+1037	1	1
+40	2	0
+890	6	0
+41	2	0
+498	3	0
+321	0	1
+281	3	0
+450	1	1
+34	1	1
+498	1	1
+28	2	1
+280	0	2
+648	1	1
+47	1	1
+1002	4	0
+120	1	1
+1538	0	1
+75	1	1
+37	1	1
+517	1	1
+79	4	4
+60	18	18
+2075	1	1
+19	1	1
+2429	1	1
+21	1	1
+107	1	0
+2786	0	2
+31	5	5
+1973	12	0
+3118	1	0
+246	0	1
+33	1	1
+6752	1	0
+822	2	9
+606	1	1
+18	1	1
+3920	1	1
+37	0	2
+4497	10	13
+2451	1	1
+16	3	0
+1843	0	4
+3780	3	0
+850	0	1
+2774	0	3
+2065	0	1
+20	1	1
+1400	1	0
+3243	0	15
+1336	5	0
+618	7	7
+1507	8	7
+379	44	43
+2184	0	1
+304	0	2
+19	0	1
+101	1	1
+417	3	3
+22	1	1
+672	4	4
+221	1	1
+161	5	0
+17	1	1
+72	1	0
+106	1	1
+463	1	1
+94	1	1
+138	3	4
+185	1	1
+29	1	1
+220	15	15
+167	1	1
+32	1	1
+93	1	3
+217	1	1
+23	1	1
+137	9	9
+62	0	3
+353	1	1
+27	1	1
+117	9	9
+421	1	1
+47	1	1
+124	0	1
+997	6	0
+54	5	5
+764	1	1
+45	1	1
+1431	7	7
+387	6	6
+1103	0	36
+767	1	1
+31	1	3
+208	5	5
+1610	1	1
+23	1	1
+779	0	8
+324	0	2
+45	1	1
+264	0	3
+45	1	1
+250	1	1
+18	1	1
+517	33	0
+117	1	1
+42	1	1
+550	1	1
+20	1	1
+671	1	1
+68	1	1
+89	1	1
+104	1	1
+172	0	1
+124	0	1
+524	0	1500
+464	5	5
+32	1	0
+171	1	1
+19	1	1
+67	1	1
+22	1	1
+654	1	1
+25	1	1
+68	1	1
+21	4	0
+1588	1	1
+66	1	1
+401	0	1
+186	1	1
+21	1	1
+168	0	1
+686	3	0
+19	1	1
+127	1	1
+29	1	1
+234	1	1
+30	1	1
+141	0	2
+33	1	1
+673	1	1
+89	1	1
+161	16	16
+504	1	1
+192	0	3
+105	1	1
+286	1	1
+101	15	16
+158	8	0
+57	1	1
+332	2	2
+35	1	1
+371	1	1
+55	1	1
+86	1	1
+29	1	1
+196	1	1
+44	1	0
+52	10019	10030
+89	1	1
+35	1	1
+153	1	0
+37	35	6
+68	1	1
+69	3	3
+78	28	28
+85	1	1
+148	1	1
+248	1	1
+77	1	1
+61	1	1
+55	1	1
+82	1	1
+41	2	2
+113	1	1
+59	1	1
+417	5	5
+65	1	1
+55	1	1
+212	0	14
+40	1	1
+112	1	1
+22	0	2
+47	1	1
+75	1	1
+208	5	5
+55	1	1
+78	1	1
+136	13	13
+93	3	0
+140	1	2
+46	1	1
+78	6	6
+52	1	1
+51	1	1
+97	1	1
+107	1	1
+5453	1	1
+40	1	1
+327	1	1
+24	1	1
+172	2	2
+27	11	15
+381	10	11
+376	1	1
+45	1	1
+121	1	1
+62	1	1
+289	1	1
+26	1	1
+191	1	1
+20	11	11
+425	1	1
+37	1	1
+296	1	1
+149	1	1
+284	1	1
+37	1	1
+705	1	12
+106	12	12
+306	1	1
+24	1	1
+1299	1	1
+47	1	1
+2026	1	1
+20	1	1
+133	1	0
+9803	0	4
+15871	3	0
+2464	1	1
+24	1	1
+879	1	1
+73	1	1
+89	1	1
+42	1	1
+108	1	1
+43	0	1
+26	1	1
+511	5	6
+605	1	1
+47	1	1
+73	1	1
+62	1	1
+1928	19438	20008
+56	5	5
+237	1	1
+141	1	1
+92	1	1
+154	7	7
+3208	1	1
+33	1	1
+671	1	1
+21	1	1
+955	0	3
+130	1	1
+26	1	1
+288	8	8
+218	0	3
+1076	8	0
+609	1	0
+55	2	1
+242	1	1
+23	1	1
+834	1	1
+112	1	1
+67	1	1
+43	1	1
+86	1	1
+30	1	1
+73	13	13
+88	11	11
+145	13	13
+63	1	1
+62	1	1
+59	51	50
+432	1	1
+45	1	1
+68	1	1
+48	1	1
+64	9	9
+299	14	14
+169	10	10
+69	2	2
+85	1	1
+207	6	6
+85	1	1
+44	3	3
+181	11	11
+55	13	13
+258	1	1
+103	1	1
+298	7	7
+268	1	1
+16	1	1
+66	1	1
+97	16	0
+322	1	1
+58	1	1
+55	1	1
+77	1	1
+186	1	1
+55	1	1
+218	1	1
+153	1	1
+53	1	1
+98	1	1
+371	1	1
+303	3	3
+63	1	1
+303	1	1
+121	0	2
+55	8	8
+208	1	1
+26	1	1
+447	6	6
+76	1	1
+46	1	1
+782	12	12
+230	1	1
+67	1	1
+60	1	1
+80	1	1
+170	3	0
+53	1	1
+31	1	1
+317	2	2
+66	1	1
+228	1	1
+23	1	1
+1612	1	1
+21	1	1
+261	1	1
+99	1	1
+128	1	1
+15	1	1
+77	9	9
+618	8	8
+84	4	6
+438	1	1
+140	1	1
+158	4	3
+277	12	12
+165	4	4
+36	1	1
+253	1	1
+59	1	1
+910	0	1
+915	4	5
+276	15	15
+682	1	1
+28	1	1
+1483	13	13
+203	1	0
+52	1	1
+48	1	1
+229	12	12
+166	1	1
+39	1	1
+194	1	1
+24	1	1
+251	8	8
+619	0	4
+15	1	1
+690	84	85
+463	1	1
+30	1	1
+449	1	1
+54	1	1
+58	5	5
+979	1	0
+318	1	1
+28	1	1
+898	10	10
+100	1	1
+22	1	1
+446	1	1
+74	1	1
+273	1	1
+19	1	1
+333	1	1
+44	1	1
+220	1	1
+56	2	0
+209	1	1
+70	1	1
+223	0	20
+220	1	1
+31	1	1
+56	1	1
+111	1	1
+220	1	1
+89	1	1
+119	1	1
+113	2	0
+195	1	1
+46	1	1
+184	1	1
+60	0	4
+76	0	4
+53	3	1
+43	1	1
+153	1	1
+53	1	1
+195	6	0
+60	1	1
+278	1	0
+42	1	1
+341	13	13
+262	4	4
+67	1	1
+32	1	0
+28	1	1
+287	7	7
+318	1	1
+78	1	1
+157	1	1
+19	1	1
+64	1	2
+31	1	1
+52	1	1
+51	1	1
+77	10280	10270
+101	8	8
+4653	1	1
+38	1	1
+817	2	0
+256	1	1
+27	1	1
+339	1	1
+48	1	1
+54	10	10
+1393	3	0
+1491	2	0
+1983	16	0
+167	0	4
+3886	7	8
+535	1	1
+16	1	1
+1555	3	0
+3131	1	1
+17	1	1
+4196	1	0
+14974	0	1
+3514	0	4
+29	1	1
+123	0	2
+27	11	0
+35	0	50
+43	2	0
+55	6	100
+96	11	0
+22	67	0
+49	13	0
+20	0	2
+19	2	0
+22	4	156
+57	156	3
+61	0	2
+29	20	0
+42	11	0
+21	2	0
+50	4	6
+31	1	3
+23	1	53
+25	0	32
+66	1	55
+11	0	2
+13	0	41
+68	1	42
+23	1	3
+12	2	0
+17	1	29
+51	17	13
+18	2	0
+28	2	0
+26	2	0
+158	1	25
+96	0	28
+51	1	29
+79	254	0
+53	21	0
+5064	0	2
+7569	2	0
+2189	0	1
+85	1	1
+31	0	4
+399	14	14
+408	0	1
+681	0	5
+184	1	1
+20	1	1
+64	1	1
+29	1	0
+9	2	0
+442	4	0
+342	1	1
+24	1	1
+131	1	1
+198	1	1
+370	0	1
+34	1	1
+447	21	20
+259	1	1
+23	0	1
+121	2	0
+2257	1	1
+22	1	1
+811	1	1
+27	1	1
+744	0	5
+843	0	2889
+55	0	88
+1189	0	2
+2274	1	0
+752	4	0
+164	1	1
+55	1	1
+1726	1	1
+57	1	1
+3578	1	1
+34	1	1
+1446	1	0
+460	1	1
+31	0	1
+6	1	1
+163	1	1
+22	1	1
+81	1	1
+27	1	1
+548	1	1
+61	1	1
+1169	1	1
+41	1	1
+6471	1	1
+62	1	1
+530	17	17
+394	1	1
+40	7	0
+57	12	12
+69	2	2
+39	1	1
+70	1	1
+22	0	3
+2307	1	1
+30	1	1
+411	1	1
+104	1	1
+375	26	27
+1218	1	1
+35	1	1
+85	1	1
+20	6	0
+687	1	1
+34	1	1
+268	13	13
+74	1	1
+47	2	0
+51	69	69
+73	1	1
+48	1	1
+218	1	1
+42	1	1
+197	1	1
+41	1	1
+313	1	1
+40	1	1
+476	1	1
+29	1	1
+185	1	1
+35	1	1
+594	1	1
+24	1	1
+220	26	0
+245	0	1
+261	13	13
+89	1	1
+90	1	1
+224	1	1
+201	1	1
+306	1	1
+29	5	5
+121	1	1
+31	1	1
+109	1	1
+25	1	1
+168	1	1
+19	1	1
+93	12	11
+132	1	0
+113	1	1
+30	1	1
+56	9	9
+300	1	1
+50	2	2
+96	1	1
+43	1	1
+76	1	1
+44	1	1
+197	1	1
+91	7	1
+119	0	9
+392	5	5
+89	1	1
+428	11	11
+260	1	1
+23	1	0
+10	1	1
+70	1	1
+65	2	0
+16	0	19
+28	1	1
+208	1	1
+70	1	1
+149	0	3
+243	1	1
+55	1	1
+63	17	17
+1208	1	1
+98	1	1
+162	1	1
+45	1	1
+148	70	70
+209	4	4
+1242	1	1
+42	5	0
+87	1	1
+522	0	3
+305	0	1
+1379	0	2
+390	0	15
+72	1	1
+16	1	1
+270	1	0
+280	7	7
+2763	20	20
+674	10	10
+1375	14	0
+294	143	141
+629	16	16
+54	4	4
+680	16	16
+395	1	1
+42	1	1
+1763	1	1
+46	1	1
+282	1	1
+39	1	1
+860	1	1
+26	1	1
+745	0	2
+2081	2	0
+817	4	4
+202	1	1
+48	1	1
+168	1	1
+53	1	1
+379	10	10
+1178	14	14
+132	5	0
+555	1	1
+65	1	1
+550	1	1
+21	1	1
+462	1	1
+43	1	1
+121	1	1
+48	0	3
+15	1	5
+1404	0	1
+450	4	0
+626	1	0
+304	1	1
+39	1	1
+564	1	1
+45	1	1
+303	2	0
+409	1	1
+18	1	0
+858	2	0
+2168	0	1
+54	22	22
+524	0	1
+410	10	10
+106	1	14
+2419	18	14
+64	1	1
+31	1	1
+185	0	5
+1646	1	1
+20	1	1
+227	1	1
+37	1	1
+500	1	0
+136	3	4
+8239	1	1
+23	1	1
+1114	0	2
+688	0	1
+901	18	18
+4781	0	4
+815	0	1
+5069	0	5
+415	0	2
+352	0	1
+1085	11	11
+1099	0	1
+991	0	1
+845	1	1
+32	0	2
+5751	0	3
+1553	1	1
+60	1	1
+278	0	1
+30	1	1
+1855	0	2
+958	0	1
+66	0	16
+2109	0	2
+1265	0	1
+17312	0	4
+1875	0	1
+2157	1	0
+915	0	6
+4940	1	0
+2649	0	1
+3322	11	9
+2276	14	0
+3128	0	4
+3496	1	0
+966	0	1
+120	4	4
+3473	1	0
+1647	0	3
+1182	1	0
+654	0	3
+2049	1	0
+6838	1	1
+39	1	1
+186	1	0
+2718	1	1
+30	1	1
+160	11	11
+4954	0	1
+420	1	1
+123	1	1
+156	0	4
+219	4	0
+195	1	0
+4402	2	0
+4295	1	0
+4695	0	1
+30	1	1
+6025	1	0
+4179	1	0
+19834	0	1
+11605	0	1
+4121	2	0
+2863	0	2
+4890	1	0
+5576	0	6
+4104	4	0
+19858	4	0
+1616	0	3
+1647	4	1
+36	0	12
+2213	0	14
+414	0	1
+3338	0	3
+678	3	4
+292	2	0
+1922	0	1
+913	0	1
+2720	1	0
+1111	3	0
+2589	0	8
+9425	1	0
+1403	0	2
+1964	0	12
+4433	0	1
+1569	0	1
+89	46	46
+7074	1	1
+41	1	1
+2257	1	0
+3001	0	1
+1845	1	0
+1593	0	1
+497	0	2
+6109	0	1
+2019	2	0
+921	0	1
+241	1	0
+4348	72	72
+1053	1	0
+2213	2	0
+1974	8	0
+4952	0	1
+6146	2	0
+953	1	0
+4141	0	1
+4244	5	0
+152	0	2
+209	0	1
+2400	0	10
+785	2	0
+1733	0	1
+554	1	0
+128	0	2
+3051	0	1
+5221	17	17
+3339	0	1
+1503	0	1
+1705	0	3
+2052	17	17
+998	177	0
+2804	1	0
+1925	1	0
+5635	17	17
+3563	0	1
+971	8	0
+36021	1	0
+8016	29	27
+3890	0	1
+67913	1	1
+18	1	6368
+73	1	1
+3119	23	23
+7239	0	32738
+4295	1	1
+19	1	1
+6198	1	0
+16668	1	1
+20	1	1
+5638	5	0
+47	12	0
+11313	0	1
+1769	0	1
+8355	0	3
+4114	0	2
+1403	1	0
+5140	0	1
+490	0	1
+219	1	0
+3483	1	0
+8939	1	1
+44	1	1
+10813	0	2
+7480	2	0
+617	1	0
+1464	0	1
+500	0	2
+1466	1	0
+527	5	0
+3593	0	1
+374	0	1
+3666	0	1
+2149	1	0
+311	2	0
+6570	1	0
+962	1	0
+23	1	1
+2647	4	0
+588	1	1
+21	1	1
+3256	28	20
+870	0	1
+644	1	0
+602	2	1
+3730	1	1
+45	1	1
+12848	7	7
+5994	29	29
+1283	0	3
+8057	1	1
+63	1	1
+4166	1	0
+1887	10	0
+2949	1	1
+31	0	1
+669	1	0
+888	43	43
+1259	2	0
+2081	0	2
+373	0	6
+421	4	4
+1460	0	1
+1699	0	8
+2882	2	0
+147	0	1
+1656	1	1
+27	1	1
+1828	0	2
+4066	0	3
+34	1	1
+361	17	17
+1254	6	0
+1643	0	2
+2542	0	1
+848	2	1
+2117	0	2
+119	1	1
+44	1	1
+1104	0	1
+415	0	12
+634	18	1
+377	6	7
+227	6	0
+449	13	13
+895	0	17
+457	18	18
+663	0	3
+382	1	1
+26	1	1
+135	0	1
+105	1	1
+25	1	1
+620	2	0
+290	5	5
+375	1	1
+30	0	4
+98	1	0
+20	17	4
+3824	28	0
+39	4	0
+28	4	0
+44	4	0
+1898	9	9
+221	0	2
+10522	30	0
+783	1	1
+59	1	1
+94	1	1
+21	1	1
+491	1	1
+49	1	1
+289	2	0
+120	0	1
+37	1	1
+112	1	1
+21	1	1
+183	16	16
+73	2	0
+1007	1	1
+38	0	1
+79	1	1
+48	1	1
+561	1	1
+29	1	1
+145	5	5
+576	12	12
+834	1	0
+846	5	7
+34	1	1
+417	0	1
+65	1	1
+40	1	1
+110	1	1
+47	1	1
+351	1	1
+69	1	1
+53	1	1
+91	1	1
+260	1	1
+36	0	1
+604	1	0
+169	0	1
+2118	1	1
+34	1	1
+147	1	1
+213	1	1
+67	1	1
+31	1	1
+566	1	0
+17	1	1
+763	1	1
+34	1	1
+671	5	0
+41	2	2
+98	0	1
+449	0	2
+61	1	1
+38	1	1
+202	1	1
+44	1	1
+190	1	0
+46	4	4
+51	0	4
+476	1	1
+17	1	1
+212	1	1
+26	1	1
+485	1	1
+25	1	1
+263	1	1
+26	1	1
+1327	4	0
+44	1	0
+2397	1	1
+44	1	1
+4146	14	14
+901	0	1
+3504	1	0
+1125	1	0
+254	1	0
+427	0	1
+30	1	1
+111	0	2
+52	0	8
+528	44	0
+969	1	1
+10	1	0
+28	1	1
+140	1	1
+43	1	1
+1989	2	1
+598	1	1
+87	0	4
+124	1	0
+4840	1	1
+28	7	4
+505	0	2
+24	1	1
+5134	4	0
+543	1	0
+18	1	1
+97	1	1
+29	1	3
+101	6	0
+148	13	7
+1346	0	1
+128	7	0
+49	0	1
+876	2	0
+286	5	5
+184	0	1
+84	5	5
+365	9	9
+981	1	1
+11	1	1
+734	4	0
+563	4	0
+244	9	9
+379	1	1
+17	1	1
+49	2	0
+95	1	1
+30	1	1
+147	1	1
+37	0	6
+340	1	2
+58	1	1
+332	0	2
+233	6	9
+156	0	1
+26	1	1
+439	4	0
+34	0	2
+508	5	0
+96	1	1
+34	1	1
+1267	15	15
+638	1	1
+24	4	5
+1055	13	13
+135	0	1
+194	63	63
+384	6	6
+2756	1	1
+19	1	1
+99	15	15
+1754	2	3
+2238	1	1
+31	1	1
+3002	4	0
+2156	15	15
+855	14	13
+442	5	5
+2022	6	6
+506	0	2
+1110	0	1
+2578	0	2
+4864	1	1
+36	1	0
+3187	1	1
+16	1	1
+184	1	1
+18	1	1
+1607	53	60
+527	1	1
+39	1	1
+653	3	0
+227	1	1
+18	1	1
+102	7	7
+109	0	323
+91	1	0
+124	0	15
+621	0	4
+553	12	12
+463	1	1
+40	1	1
+372	1	1
+25	1	1
+188	12	12
+357	0	1
+250	0	5
+4193	0	4
+967	1	1
+76	1	1
+3236	4	4
+529	7	7
+246	4	0
+160	1	1
+34	0	3
+1469	0	2
+499	1	0
+937	1	1
+45	1	1
+421	6	0
+2127	0	1
+491	1	0
+80	1	1
+72	2	0
+255	6	6
+728	14	11
+702	3	0
+290	0	2
+210	19	1
+473	1	1
+42	4	0
+219	0	1
+348	1	1
+83	1	1
+851	0	16
+72	13	0
+246	1	1
+47	4	0
+410	1	0
+93	0	12
+225	0	16
+428	1	0
+4	6	0
+324	0	1
+3060	0	16
+1305	1	1
+29	1	1
+3094	0	7
+600	0	2
+5495	1	1
+47	1	1
+1247	9	21
+35	6	0
+4350	1	1
+15	1	1
+2011	6	14
+8378	2	0
+295	0	17
+4583	1	0
+4132	0	4
+924	4	3
+1751	0	2
+1060	12	12
+380	0	2
+425	8	0
+84	0	1
+244	1	1
+28	1	1
+221	4	0
+348	1	1
+37	11	11
+50	1	1
+180	1	1
+348	1	1
+20	1	1
+1714	1	1
+79	1	1
+729	1	1
+44	1	0
+78	1	1
+112	1	1
+23	1	1
+55	9	9
+1044	1	1
+27	1	1
+494	1	1
+32	1	1
+237	1	1
+27	1	1
+1839	7	1
+710	8	0
+185	0	2
+966	1	0
+13	15	1
+251	1	1
+47	1	1
+285	1	1
+103	1	1
+977	1	1
+41	1	0
+97	1	1
+131	1	0
+307	1	1
+47	1	1
+1070	1	1
+69	1	1
+382	0	1
+167	1	1
+35	1	1
+161	1	1
+30	1	1
+1068	18	0
+1173	1	1
+32	1	1
+59	1	1
+12	1	0
+18	1	1
+55	0	22
+72	1	1
+2806	1	1
+15	1	1
+1395	1	0
+157	13	0
+536	8	8
+101	1	1
+21	1	1
+147	8	8
+638	1	1
+18	1	1
+183	15	15
+990	0	12
+21	1	1
+145	0	1
+332	1	1
+31	1	1
+231	22	5
+39	1	1
+414	9	9
+93	1	1
+63	1	1
+739	0	2
+632	1	1
+74	1	1
+138	5	5
+128	0	1
+294	1	1
+45	1	1
+679	6	6
+1773	0	34
+543	27	27
+1608	5	0
+219	1	1
+134	0	3
+164	0	1
+357	1	1
+28	1	1
+670	7	9
+270	0	1
+891	13	33
+257	4	0
+80	0	4
+130	2	0
+3772	1	1
+44	1	1
+2256	0	1
+80	12	0
+5544	1	0
+428	13	13
+77	4	4
+63	1	1
+64	13	19
+906	1	1
+84	1	1
+290	1	1
+41	1	1
+144	15	15
+238	3	0
+61	1	1
+31	1	1
+189	10245	10222
+107	11	11
+93	1	1
+30	7	5
+242	0	1
+171	1	1
+29	1	1
+218	0	9
+241	1	1
+55	4	4
+88	1	1
+99	1	1
+57	0	1
+523	12	16
+399	1	1
+50	1	1
+389	1	1
+71	4	4
+173	12	12
+92	1	1
+20	1	1
+132	0	5
+15	1	1
+75	1	1
+26	5	5
+119	11	11
+542	1	1
+23	2	2
+254	1	1
+34	1	1
+172	1	1
+45	1	1
+95	11	11
+127	23	23
+64	1	1
+95	1	1
+390	1	1
+52	1	1
+170	1	1
+16	5	0
+30	1	1
+599	1	1
+119	1	1
+85	1	1
+75	1	1
+286	4	4
+61	1	1
+286	9	9
+429	1	1
+21	1	1
+53	1	1
+44	1	1
+130	1	1
+30	1	1
+190	2	2
+127	1	1
+96	4	4
+112	1	1
+105	5	5
+19	3659	4
+244	10	11
+69	1	1
+29	1	1
+281	1	1
+38	1	1
+212	1	1
+36	1	1
+79	1	1
+29	3	3
+125	161746	190163
+3115	0	1
+152	1	1
+1518	1	1
+88	1	1
+4502	0	1
+46	1	1
+800	4	4
+23	1	1
+1305	2	0
+136	0	1
+4941	0	1
+547	0	1
+70	8	8
+293	1	1
+35	1	1
+1165	4	0
+6662	1	1
+121	1	1
+92	0	8
+214	1	1
+35	1	1
+108	1	0
+1063	0	1
+1017	1	1
+20	0	6
+1725	0	1
+134	68	67
+349	1	1
+24	0	1
+1562	1	1
+31	1	1
+2513	0	1
+73	36	36
+305	1	1
+27	1	1
+543	1	1
+47	4	28
+4387	20057	20086
+272	5	5
+243	1	1
+84	1	1
+98	1	1
+50	5	5
+77	1	1
+74	1	1
+20	0	1
+143	1	1
+45	0	1
+4	1	1
+1088	1	1
+35	1	1
+320	1	1
+22	1	1
+275	1	1
+47	1	1
+370	19	19
+119	1	6
+51	1	1
+21	1	1
+244	0	1
+345	1	1
+24	1	1
+181	1	1
+61	3	3
+542	1	1
+16	1	1
+312	1	0
+353	4	3
+279	323	0
+86	1	1
+49	1	1
+342	1	1
+44	0	2
+222	1	1
+37	1	1
+588	8	8
+593	2	2
+44	1	1
+359	1	1
+25	1	1
+2054	1	0
+2510	1	0
+5051	0	1
+1489	9	9
+3292	1	0
+1449	1	1
+21	1	1
+6768	1	0
+706	2	0
+7107	1	1
+38	1	1
+1127	73	73
+435	1	1
+60	1	1
+325	0	1
+254	1	1
+43	1	1
+210	1	1
+7	1	0
+47	1	1
+130	4	4
+34	1	1
+208	1	1
+39	2	2
+526	1	1
+36	1	1
+99	9	7
+20	1	1
+73	1	1
+62	1	1
+425	1	1
+43	1	1
+811	1	1
+38	1	1
+362	1	1
+49	1	1
+109	1	1
+19	1	1
+79	1	1
+29	0	1
+26	1	1
+252	1	1
+75	1	1
+441	1	1
+66	1	1
+389	13	13
+67	7	7
+1185	0	311
+64	6	6
+667	1	1
+38	1	1
+79	1	0
+553	1	1
+30	1	1
+433	1	1
+16	3	0
+1133	12	12
+262	5	5
+276	1	0
+960	14	14
+272	1	1
+41	1	1
+196	1	0
+1424	18	19
+314	1	1
+22	1	1
+345	1	1
+23	3	0
+245	1	1
+78	1	1
+77	1	1
+779	1	1
+32	1	1
+247	1	1
+48	1	1
+778	2	0
+226	1	1
+61	1	1
+861	0	1
+51	9	9
+397	1	1
+12	4	0
+46	1	1
+602	1	1
+35	1	1
+422	1	1
+49	1	1
+789	1	1
+37	1	1
+268	0	2
+589	8	8
+366	1	1
+6	0	7
+5	0	1
+66	1	1
+1584	2	7
+19	1	1
+417	1	1
+37	1	1
+812	1	1
+33	3	0
+1351	18	18
+2186	1	1
+86	1	1
+1433	59	59
+65	0	1
+238	0	1
+171	1	1
+7	2	1
+67	1	1
+596	1	1
+29	1	1
+144	4	6
+417	1	0
+88	1	1
+24	1	1
+390	18	18
+496	14	21
+145	1	1
+46	1	1
+310	1	1
+35	1	1
+214	1	1
+38	1	1
+206	1	1
+37	1	0
+240	1	1
+32	1	1
+469	1	1
+32	1	1
+208	1	1
+21	1	1
+343	1	1
+17	1	1
+88	1	1
+58	6	0
+169	1	1
+22	1	1
+162	0	1
+196	0	2
+500	6	5
+108	1	1
+40	2	0
+50	1	1
+111	1	0
+21	0	1066
+335	1	1
+44	1	1
+11005	0	1
+6280	1	1
+48	1	1
+1173	1	1
+19	1	1
+2664	0	1
+351	1	0
+1059	14	14
+593	0	1
+869	16	16
+23065	2	0
+2197	0	1
+949	0	1
+15048	0	1
+606	1	0
+7820	0	4
+14669	1	0
+14708	0	1
+16326	0	1
+710	2	0
+194	1	1
+49	1	1
+262	0	1
+92	1	1
+10677	2	0
+4856	3	0
+7447	6	6
+421	1	0
+884	6	0
+17	1	0
+3075	1	0
+14671	3	1
+3762	2	0
+601	2	0
+2461	0	2
+5154	1	0
+1604	0	16
+3589	0	1
+1488	1	0
+1196	0	2
+683	0	1
+1218	1	0
+221	1	1
+22	1	1
+296	4	4
+1456	23	41
+880	1	12
+2490	1	0
+151	1	1
+33	1	1
+2809	4	4
+3645	1	1
+17	1	1
+3496	2	0
+154	1	1
+29	1	1
+158	0	1
+5981	1	1
+32	1	1
+1041	0	2
+174	9	0
+1383	0	1
+389	1	2
+1570	2	0
+3993	4	0
+4576	1	1
+45	1	1
+182	8	8
+2203	20	24
+2009	1	1
+39	1	1
+489	1	1
+17	1	1
+628	1	1
+124	1	1
+1607	1	1
+23	1	1
+1021	0	8
+1249	0	20
+46	0	32
+46	6	0
+24	0	10
+7679	1	1
+44	1	1
+580	1	1
+28	1	1
+264	1	1
+65	0	1
+15	1	1
+2371	19	19
+57	1	1
+21	1	1
+231	1	1
+94	1	1
+105	1	1
+208	5	5
+124	1	1
+112	3	3
+207	40	40
+244	1	1
+60	1	1
+98	1	1
+50	1	1
+256	29	29
+157	1	1
+33	1	1
+143	1	1
+59	1	1
+51	1	1
+45	1	0
+73	1	1
+81	1	1
+270	1	1
+272	1	1
+232	1	1
+94	1	1
+3189	0	176
+834	0	35
+303	0	51
+321	1	0
+17170	0	1
+321	1	1
+25	1	1
+679	1	1
+33	1	1
+990	11	11
+131	8	8
+79	9	9
+1284	5	5
+537	6	6
+127	1	1
+28	1	1
+145	1	1
+47	1	1
+399	4	4
+35	1	1
+143	1	1
+39	1	1
+53	9	9
+61	1	1
+95	12	22
+86	1	0
+71	5	0
+11	1	1
+58	8490	8674
+113	1403	1307
+491	1	1
+32	1	1
+85	1	1
+41	1	1
+480	1	1
+74	2	2
+1108	59	0
+70	10	10
+325	11	11
+879	1	1
+34	1	1
+524	1	1
+25	1	1
+202	17	17
+1154	1	1
+26	1	1
+89	17	17
+87	1	1
+39	1	1
+950	1	1
+15	2	2
+51	1	1
+81	1	1
+180	1	0
+187	1	1
+37	1	1
+467	1	1
+19	1	1
+755	0	2
+81	3	1
+16	1	1
+67	6	6
+84	1	1
+37	2	0
+31	0	28
+15	0	37
+266	14	14
+372	1	1
+68	1	1
+205	40	40
+217	1	1
+46	1	1
+563	19	0
+217	9	9
+363	1	1
+22	1	1
+884	1	1
+40	1	1
+179	1	1
+42	1	1
+94	6	6
+922	1	1
+30	1	1
+481	0	3
+7925	15	11
+333	5	0
+1235	6	6
+355	1	1
+27	1	1
+515	1	0
+1077	11	0
+1521	1	0
+38	1	1
+119	1	1
+58	1	1
+63	4	3
+385	1	1
+49	1	1
+77	20	22
+111	11	11
+190	2	2
+45	1	1
+373	1	1
+47	1	1
+77	10	10
+186	1	1
+24	1	1
+965	27	27
+148	1	0
+214	1	1
+34	1	1
+89	1	1
+36	1	1
+288	0	1
+544	0	331
+320	1	0
+199	1	1
+16	1	1
+112	1	1
+29	1	1
+808	0	3
+45	1	1
+240	1	1
+38	1	1
+59	1	1
+68	1	1
+52	1	1
+98	1	1
+166	7	7
+698	1	1
+68	1	1
+165	0	1
+114	1	1
+92	0	1
+14	1	1
+215	1	1
+81	1	1
+792	1	1
+31	1	1
+54	1	1
+44	1	1
+179	1	1
+26	1	1
+200	1	1
+30	1	1
+639	7	7
+505	0	1
+18	0	1
+21	1	1
+549	12	0
+19	1	1
+1413	19	19
+752	1	0
+840	1	1
+69	1	1
+966	21	21
+33	12	0
+56	1	1
+94	1	1
+237	11	9
+189	1	1
+47	1	1
+318	3	0
+80	16	16
+67	1	2
+11	5	0
+32	1	1
+126	1	1
+146	1	1
+104	6	5
+56	1	1
+68	1	1
+417	12	13
+636	0	2
+30	1	1
+694	0	4
+95	1	1
+28	1	1
+1358	1	1
+19	1	1
+68	1	1
+97	1	1
+493	1	7
+158	2	0
+42	6	0
+59	1	1
+314	14	14
+94	1	1
+64	1	1
+637	1	1
+21	1	1
+144	2	1
+229	11	5
+410	1	1
+96	1	1
+272	1	1
+22	1	1
+118	1	1
+44	1	1
+96	1	1
+48	1	1
+414	22	22
+373	13	13
+554	1	1
+87	10	0
+313	1	1
+37	1	1
+122	17	18
+179	1	1
+40	1	1
+591	8	8
+129	1	0
+70	1	1
+71	1	0
+73	10	6
+12	1	1
+203	0	6
+24	2	0
+45	4	0
+46	1	1
+186	9	9
+87	1	1
+28	1	1
+3625	0	1
+233	1	1
+532	0	2
+696	2	0
+555	1	7
+287	1	1
+30	0	3
+946	0	1
+88	1	1
+60	12	0
+12546	1	1
+37	1	0
+2071	0	1
+3270	4	5
+24668	0	2
+6212	1	1
+26	1	1
+816	0	4
+8244	26	26
+5332	18	15
+2375	2	0
+1957	2	0
+2394	6	0
+1561	0	1
+2805	4	0
+12333	8	0
+835	0	1
+391	35	62
+12156	0	18
+6903	2	0
+21807	3	0
+1588	1	0
+2605	1	1
+23	1	1
+11252	8	0
+298	6	7
+946	2	0
+232	0	1
+501	1	0
+4748	0	4
+770	0	7
+914	0	1
+295	1	0
+214	3	0
+121	0	1
+784	0	1
+2512	0	1
+1205	21	21
+3250	3	0
+926	0	1
+189	2	0
+3543	2	0
+893	1	1
+46	1	1
+1296	0	1
+153	0	1
+336	5	0
+228	1	1
+45	1	1
+207	3	0
+322	0	1
+658	1	0
+1516	3	0
+1025	0	13
+1518	0	1
+591	10	10
+3384	0	2
+182	12	0
+328	1	0
+301	0	1
+994	1	1
+18	0	6
+1743	0	1
+2350	22	23
+1548	0	7
+1976	1	0
+199	0	1
+5922	12	12
+873	0	3
+3080	12	8
+322	1	0
+490	1	0
+3602	1	0
+482	1	0
+3178	1	0
+5157	0	10
+753	0	1
+885	20	0
+1746	10	0
+4045	6	1
+3520	5	13
+2048	0	1
+3529
+
+chain 323865 chr6_cox_hap2 4795371 + 1330645 1334316 chr12 132349534 - 750935 772711 208090
+2772	0	815
+201	0	17291
+643	1	0
+54
+
+chain 80740 chr6_cox_hap2 4795371 + 2523432 2524289 chr6 170899992 - 139781917 139782778 1563239
+341	0	4
+516
+
+chain 70254 chr6_cox_hap2 4795371 + 4067974 4068737 chr9 140273252 + 98508948 98509710 1791394
+611	16	15
+136
+
+chain 49863 chr6_cox_hap2 4795371 + 2736707 2740201 chr12 132349534 + 103307685 103311177 2548369
+99	961	960
+121	35	35
+77	287	287
+76	473	472
+80	230	229
+64	37	37
+96	796	797
+62
+
+chain 42593 chr6_cox_hap2 4795371 + 3906996 3908960 chrX 154913754 - 144265701 144267664 3039954
+86	125	125
+67	358	358
+186	154	154
+98	734	733
+51	48	48
+57
+
+chain 34258 chr6_cox_hap2 4795371 + 2809588 2810007 chrX 154913754 - 17721461 17721874 3940368
+73	15	15
+155	1	1
+20	6	0
+17	1	1
+131
+
+chain 30865 chr6_cox_hap2 4795371 + 4059866 4060385 chr6 170899992 + 32821259 32821748 4483190
+73	89	59
+184	77	77
+96
+
+chain 30808 chr6_cox_hap2 4795371 + 1510229 1510552 chr13 114142980 + 81787211 81787534 4493802
+323
+
+chain 29563 chr6_cox_hap2 4795371 + 4153575 4153884 chr1 247249719 - 75038034 75038343 4838476
+309
+
+chain 29490 chr6_cox_hap2 4795371 + 3951720 3952028 chr20 62435964 - 21243992 21244300 4870682
+308
+
+chain 27083 chr6_cox_hap2 4795371 + 3906819 3907206 chr15 100338915 - 11358130 11358517 3142845
+177	86	86
+124
+
+chain 23990 chr6_cox_hap2 4795371 + 1376886 1377662 chr7 158821424 - 51137320 51138262 7695540
+178	101	101
+72	385	551
+40
+
+chain 17935 chr6_cox_hap2 4795371 + 3928197 3929285 chr6 170899992 + 32648139 32649803 12171469
+63	855	1431
+170
+
+chain 17763 chr6_cox_hap2 4795371 + 3903740 3903944 chr6 170899992 - 2126149 2126361 12324873
+52	0	8
+26	2	2
+124
+
+chain 17461 chr6_cox_hap2 4795371 + 3908117 3908804 chr7 158821424 + 50608340 50609026 3099178
+57	90	88
+74	250	251
+108	69	69
+39
+
+chain 17263 chr6_cox_hap2 4795371 + 3953714 3953921 chr4 191273063 + 3978296 3978500 12788147
+50	3	0
+26	4	4
+124
+
+chain 16515 chr6_cox_hap2 4795371 + 3904181 3904724 chr8 146274826 - 138245724 138246268 13519146
+75	324	325
+78	15	15
+51
+
+chain 16283 chr6_cox_hap2 4795371 + 3331225 3331402 chr2 242951149 + 128261675 128261851 587006
+28	2	1
+147
+
+chain 15874 chr6_cox_hap2 4795371 + 2807758 2808190 chr6 170899992 + 31412763 31413204 14155918
+58	158	158
+72	76	85
+68
+
+chain 15671 chr6_cox_hap2 4795371 + 1369735 1370970 chr6 170899992 - 139552636 139553881 14365445
+56	408	416
+54	620	622
+97
+
+chain 15351 chr6_cox_hap2 4795371 + 2854893 2855094 chr11 134452384 + 74426248 74426449 14701290
+99	26	26
+76
+
+chain 15299 chr6_cox_hap2 4795371 + 2737173 2739469 chr4 191273063 + 161293453 161295747 2664175
+134	30	30
+77	352	352
+1	899	896
+68	663	664
+72
+
+chain 15059 chr6_cox_hap2 4795371 + 3958379 3959329 chr11 134452384 - 110535166 110536123 15004208
+57	287	282
+82	464	476
+60
+
+chain 14920 chr6_cox_hap2 4795371 + 2854607 2854845 chr12 132349534 + 55181251 55181530 15152322
+65	69	110
+104
+
+chain 14553 chr6_cox_hap2 4795371 + 4145755 4147026 chr20 62435964 - 45982841 45983887 15553025
+59	654	439
+82	417	407
+59
+
+chain 14203 chr6_cox_hap2 4795371 + 4064060 4064210 chr6 170899992 - 148625201 148625351 15961753
+150
+
+chain 14065 chr6_cox_hap2 4795371 + 3965480 3965632 chr6 170899992 - 138279004 138279156 16120854
+152
+
+chain 13894 chr6_cox_hap2 4795371 + 1411227 1413617 chr6 170899992 + 30021566 30022999 16323534
+75	1920	964
+70	255	254
+70
+
+chain 13590 chr6_cox_hap2 4795371 + 4063892 4064036 chr2 242951149 + 178053314 178053458 16703151
+144
+
+chain 13480 chr6_cox_hap2 4795371 + 1351610 1352327 chr6 170899992 + 29984509 29985227 16847522
+104	551	552
+62
+
+chain 13240 chr6_cox_hap2 4795371 + 3973235 3974493 chr6 170899992 + 32656086 32657213 17156367
+52	422	421
+78	652	522
+54
+
+chain 12556 chr6_cox_hap2 4795371 + 1412173 1412312 chr2 242951149 - 184047846 184047985 18149165
+139
+
+chain 12225 chr6_cox_hap2 4795371 + 3953994 3954124 chr13 114142980 - 45055283 45055413 18644548
+130
+
+chain 12178 chr6_cox_hap2 4795371 + 4035942 4036108 chr14 106368585 - 58343221 58343386 18718227
+55	26	25
+85
+
+chain 11746 chr6_cox_hap2 4795371 + 1363046 1363194 chr7 158821424 - 7754727 7754875 19419744
+54	14	14
+80
+
+chain 11718 chr6_cox_hap2 4795371 + 363030 363190 chr13 114142980 + 52924211 52924330 7321463
+62	41	0
+40	13	13
+4
+
+chain 11256 chr6_cox_hap2 4795371 + 4009517 4011696 chr6 170899992 + 32547334 32549511 20265569
+52	1710	1710
+59	270	268
+88
+
+chain 11034 chr6_cox_hap2 4795371 + 3906701 3906819 chr11 134452384 - 106076910 106077028 5031217
+118
+
+chain 10867 chr6_cox_hap2 4795371 + 2744958 2745115 chr6 170899992 - 132294381 132294544 20980270
+55	29	35
+73
+
+chain 10852 chr6_cox_hap2 4795371 + 2854438 2854554 chr15 100338915 - 60167597 60167713 16273329
+116
+
+chain 10738 chr6_cox_hap2 4795371 + 3960011 3960132 chr10 135374737 + 59270705 59270823 21232182
+61	3	0
+57
+
+chain 10631 chr6_cox_hap2 4795371 + 4504746 4504857 chr6 170899992 + 33168511 33168622 21069572
+111
+
+chain 10496 chr6_cox_hap2 4795371 + 3956062 3956172 chr1 247249719 - 172266041 172266151 21720779
+110
+
+chain 10389 chr6_cox_hap2 4795371 + 2738194 2739397 chr3 199501827 - 153335243 153336431 2813504
+77	463	461
+101	221	221
+81	230	217
+30
+
+chain 9881 chr6_cox_hap2 4795371 + 2797497 2798047 chr6 170899992 + 31313427 31313987 23083507
+72	423	433
+55
+
+chain 9755 chr6_cox_hap2 4795371 + 4085166 4085466 chr6 170899992 + 162410099 162410399 23379361
+65	181	181
+54
+
+chain 9455 chr6_cox_hap2 4795371 + 3955446 3955651 chr6 170899992 + 32576901 32577113 24108453
+54	91	98
+60
+
+chain 9090 chr6_cox_hap2 4795371 + 2744204 2744314 chr3 199501827 - 94209663 94209773 24799752
+53	4	4
+53
+
+chain 9032 chr6_cox_hap2 4795371 + 4005585 4007249 chr6 170899992 + 32600177 32601830 24897713
+61	1516	1505
+87
+
+chain 8805 chr6_cox_hap2 4795371 + 4070123 4070583 chr6 170899992 + 32730844 32731277 25222810
+56	347	320
+57
+
+chain 8241 chr6_cox_hap2 4795371 + 4030549 4030636 chr6 170899992 + 65319659 65319746 26041488
+87
+
+chain 7395 chr6_cox_hap2 4795371 + 3960355 3960433 chr12 132349534 + 58155129 58155207 27414638
+78
+
+chain 7276 chr6_cox_hap2 4795371 + 4034939 4035015 chr6 170899992 - 67344251 67344327 27653179
+76
+
+chain 7068 chr6_cox_hap2 4795371 + 3976155 3976230 chr3 199501827 - 153055114 153055189 28061906
+75
+
+chain 6977 chr6_cox_hap2 4795371 + 3979195 3979269 chr3 199501827 - 153056804 153056878 28244736
+74
+
+chain 6795 chr6_cox_hap2 4795371 + 2799999 2800071 chr6 170899992 + 31318116 31318188 28604513
+72
+
+chain 6742 chr6_cox_hap2 4795371 + 3906310 3906388 chr13 114142980 - 44754607 44754685 6636725
+47	2	2
+29
+
+chain 6584 chr6_cox_hap2 4795371 + 3989668 3989736 chr6 170899992 + 32559900 32559968 29100412
+68
+
+chain 6522 chr6_cox_hap2 4795371 + 4087338 4087407 chr15 100338915 + 41279078 41279147 29241043
+69
+
+chain 6495 chr6_cox_hap2 4795371 + 4147491 4147560 chr3 199501827 + 170919021 170919090 29304086
+69
+
+chain 6422 chr6_cox_hap2 4795371 + 4077507 4077575 chr6 170899992 + 32836685 32836753 29490822
+68
+
+chain 6368 chr6_cox_hap2 4795371 + 4147386 4147454 chr14 106368585 + 45132269 45132337 29601986
+68
+
+chain 6249 chr6_cox_hap2 4795371 + 2736394 2736460 chr4 191273063 - 25496702 25496768 29900240
+66
+
+chain 5885 chr6_cox_hap2 4795371 + 4087248 4087310 chr1 247249719 - 180983801 180983863 30853903
+62
+
+chain 5792 chr6_cox_hap2 4795371 + 4036108 4036169 chr10 135374737 - 103149812 103149873 26755013
+61
+
+chain 5767 chr6_cox_hap2 4795371 + 4085838 4085899 chr6 170899992 + 75566512 75566573 31174158
+61
+
+chain 5767 chr6_cox_hap2 4795371 + 4147632 4147693 chr2 242951149 - 84322530 84322591 31176268
+61
+
+chain 5731 chr6_cox_hap2 4795371 + 1376353 1376414 chr6 170899992 + 29872087 29872148 31286976
+61
+
+chain 5730 chr6_cox_hap2 4795371 + 1379511 1379571 chr6 170899992 + 29878483 29878543 31293433
+60
+
+chain 5576 chr6_cox_hap2 4795371 + 1365664 1365723 chr18 76117153 - 3609354 3609413 31727123
+59
+
+chain 5458 chr6_cox_hap2 4795371 + 4048500 4048558 chr16 88827254 + 47978524 47978582 32101537
+58
+
+chain 5403 chr6_cox_hap2 4795371 + 3960992 3961049 chr8 146274826 - 83195522 83195579 32234296
+57
+
+chain 5339 chr6_cox_hap2 4795371 + 4145490 4145546 chr3 199501827 + 495644 495700 32419958
+56
+
+chain 5275 chr6_cox_hap2 4795371 + 4086549 4086604 chr8 146274826 - 2308124 2308179 32643336
+55
+
+chain 5206 chr6_cox_hap2 4795371 + 3904515 3904580 chr1 247249719 - 87949826 87949891 19914856
+50	10	10
+5
+
+chain 5193 chr6_cox_hap2 4795371 + 4086093 4086147 chr5 180857866 + 130110350 130110404 32896485
+54
+
+chain 5184 chr6_cox_hap2 4795371 + 4084818 4084872 chrX 154913754 + 10188597 10188651 32929250
+54
+
+chain 5094 chr6_cox_hap2 4795371 + 4048238 4048292 chr6 170899992 + 68023473 68023527 33192695
+54
+
+chain 5067 chr6_cox_hap2 4795371 + 2804796 2804850 chr19 63811651 - 42284679 42284733 33279532
+54
+
+chain 5066 chr6_cox_hap2 4795371 + 1412096 1412149 chr21 46944323 - 1867343 1867396 33290791
+53
+
+chain 5020 chr6_cox_hap2 4795371 + 1409379 1409431 chr6 170899992 + 29800663 29800715 33444450
+52
+
+chain 4959 chr6_cox_hap2 4795371 + 3956009 3956062 chr18 76117153 + 5080594 5080647 22154822
+53
+
+chain 4930 chr6_cox_hap2 4795371 + 3957989 3958041 chrX 154913754 - 4434310 4434362 33717677
+52
+
+chain 4885 chr6_cox_hap2 4795371 + 2804443 2804495 chr5 180857866 - 162979708 162979760 33920646
+52
+
+chain 4847 chr6_cox_hap2 4795371 + 4047956 4048006 chr8 146274826 + 123332061 123332111 34011268
+50
+
+chain 4821 chr6_cox_hap2 4795371 + 3998874 3998925 chr6 170899992 - 10896638 10896689 34121637
+51
+
+chain 4712 chr6_cox_hap2 4795371 + 1364779 1364829 chr8 146274826 + 57925971 57926021 34511278
+50
+
+chain 4712 chr6_cox_hap2 4795371 + 4048918 4048968 chrX 154913754 + 54878538 54878588 34513604
+50
+
+chain 4392 chr6_cox_hap2 4795371 + 1377105 1377164 chr7 158821424 - 126060926 126060985 9905438
+59
+
+chain 4221 chr6_cox_hap2 4795371 + 2501082 2501164 chr14 106368585 + 74531432 74531592 4607333
+28	0	78
+54
+
+chain 4156 chr6_cox_hap2 4795371 + 3908195 3908241 chr2 242951149 - 7598530 7598576 17599965
+46
+
+chain 3903 chr6_cox_hap2 4795371 + 2908687 2909998 chr13 114142980 - 41461917 41462061 3840414
+7	46	0
+24	11	0
+33	1102	5
+19	13	0
+56
+
+chain 3865 chr6_cox_hap2 4795371 + 3903984 3904315 chr6 170899992 - 96557211 96557546 20806006
+67	210	214
+54
+
+chain 3734 chr6_cox_hap2 4795371 + 4145889 4145954 chr6 170899992 + 80018577 80018642 19955866
+65
+
+chain 3639 chr6_cox_hap2 4795371 + 3954124 3954162 chr3 199501827 + 102893836 102893874 20360982
+38
+
+chain 3394 chr6_cox_hap2 4795371 + 3959975 3960011 chrX 154913754 - 4438295 4438331 28244218
+36
+
+chain 3053 chr6_cox_hap2 4795371 + 4085231 4085263 chr2 242951149 + 38036198 38036230 24698963
+32
+
+chain 2845 chr6_cox_hap2 4795371 + 2736677 2736707 chr3 199501827 - 158108130 158108160 26771662
+30
+
+chain 2771 chr6_cox_hap2 4795371 + 2403948 2403980 chr16 88827254 + 61371572 61371604 11881973
+32
+
+chain 2645 chr6_cox_hap2 4795371 + 3954296 3954371 chr19 63811651 - 40112981 40113056 21687958
+75
+
+chain 2587 chr6_cox_hap2 4795371 + 2737535 2737662 chr15 100338915 + 91973389 91973516 3332233
+127
+
+chain 2561 chr6_cox_hap2 4795371 + 363092 363133 chr6 170899992 + 20352681 20352722 12577879
+41
+
+chain 2518 chr6_cox_hap2 4795371 + 4085322 4085377 chr16 88827254 - 20600134 20600189 24262923
+55
+
+chain 2470 chr6_cox_hap2 4795371 + 2809473 2809523 chr1 247249719 + 111577816 111577866 7596664
+50
+
+chain 2411 chr6_cox_hap2 4795371 + 3932607 3932633 chr1 247249719 - 51484714 51484740 35456234
+26
+
+chain 2403 chr6_cox_hap2 4795371 + 3907493 3907603 chr2 242951149 + 38214752 38214862 4277847
+110
+
+chain 2400 chr6_cox_hap2 4795371 + 2741593 2741618 chr4 191273063 + 159509242 159509267 32929303
+25
+
+chain 2393 chr6_cox_hap2 4795371 + 4068737 4068764 chrX 154913754 - 92588093 92588120 1797125
+27
+
+chain 2375 chr6_cox_hap2 4795371 + 3904076 3904137 chr11 134452384 - 60265228 60265289 23423532
+61
+
+chain 2319 chr6_cox_hap2 4795371 + 2964304 2964330 chr6 170899992 + 31465639 31465665 3286069
+26
+
+chain 2194 chr6_cox_hap2 4795371 + 1377065 1377105 chrX 154913754 - 101365357 101365397 11073776
+40
+
+chain 2146 chr6_cox_hap2 4795371 + 1363259 1363320 chr12 132349534 + 104221177 104221238 23825280
+61
+
+chain 2104 chr6_cox_hap2 4795371 + 4036001 4036023 chr6 170899992 - 77175689 77175711 26219289
+22
+
+chain 2011 chr6_cox_hap2 4795371 + 4029977 4029999 chrX 154913754 + 85587943 85587965 35529089
+22
+
+chain 2000 chr6_cox_hap2 4795371 + 1377237 1377270 chr4 191273063 + 153905795 153905828 8127681
+33
+
+chain 1991 chr6_cox_hap2 4795371 + 2908808 2908838 chr4 191273063 - 29946315 29946345 15287751
+30
+
+chain 1988 chr6_cox_hap2 4795371 + 3958152 3958211 chr1 247249719 + 152912877 152912936 23823437
+59
+
+chain 1918 chr6_cox_hap2 4795371 + 2736976 2737099 chr5 180857866 + 51070203 51070326 3385212
+123
+
+chain 1873 chr6_cox_hap2 4795371 + 3906133 3906260 chr5 180857866 - 144904464 144904591 3580450
+127
+
+chain 1857 chr6_cox_hap2 4795371 + 4071868 4075383 chr6 170899992 + 32830794 32834943 29519981
+61	2506	2690
+85	515	965
+52	103	103
+193
+
+chain 1825 chr6_cox_hap2 4795371 + 3906512 3906555 chr4 191273063 - 47717007 47717050 17204973
+43
+
+chain 1793 chr6_cox_hap2 4795371 + 3907342 3908508 chr2 242951149 + 97580469 97581638 5600825
+48	1090	1093
+28
+
+chain 1708 chr6_cox_hap2 4795371 + 3906388 3906482 chr7 158821424 + 109077307 109077401 4717797
+94
+
+chain 1690 chr6_cox_hap2 4795371 + 4147205 4147262 chr11 134452384 - 120264308 120264365 24918209
+57
+
+chain 1584 chr6_cox_hap2 4795371 + 1377344 1377408 chr1 247249719 - 24894387 24894451 17598707
+64
+
+chain 1503 chr6_cox_hap2 4795371 + 2736094 2736140 chr13 114142980 - 72925076 72925122 23344710
+46
+
+chain 1489 chr6_cox_hap2 4795371 + 2908702 2910078 chrX 154913754 - 101842157 101842924 6540871
+27	1297	452
+2	0	236
+50
+
+chain 1456 chr6_cox_hap2 4795371 + 3908424 3908476 chr14 106368585 + 47951043 47951095 9313420
+52
+
+chain 1455 chr6_cox_hap2 4795371 + 2738121 2739528 chr6 170899992 - 65542196 65543586 3697883
+64	1285	1268
+58
+
+chain 1368 chr6_cox_hap2 4795371 + 1377482 1377548 chr11 134452384 + 118435255 118435321 13435147
+66
+
+chain 1368 chr6_cox_hap2 4795371 + 4145973 4146044 chr5 180857866 - 127160909 127160980 20267229
+71
+
+chain 1324 chr6_cox_hap2 4795371 + 3907899 3907958 chr1 247249719 + 29601245 29601304 5732716
+59
+
+chain 1278 chr6_cox_hap2 4795371 + 3908508 3908575 chr15 100338915 + 89926442 89926509 4006770
+67
+
+chain 1265 chr6_cox_hap2 4795371 + 3904331 3904385 chr4 191273063 - 113978359 113978413 18680359
+54
+
+chain 1224 chr6_cox_hap2 4795371 + 2740399 2740456 chr4 191273063 - 135903806 135903863 24465805
+57
+
+chain 1167 chr6_cox_hap2 4795371 + 3908344 3908402 chr4 191273063 + 111464967 111465025 3502724
+58
+
+chain 1054 chr6_cox_hap2 4795371 + 3907390 3907440 chr10 135374737 + 6453196 6453246 3643427
+50
+
+chain 1002 chr6_cox_hap2 4795371 + 2736140 2736200 chr1 247249719 - 71169048 71169108 10800621
+60
+
+chain 988 chr6_cox_hap2 4795371 + 2739771 2739829 chr15 100338915 - 47558730 47558788 2837698
+58
+
+chain 983 chr6_cox_hap2 4795371 + 2737443 2737516 chr11 134452384 - 130067201 130067274 24083146
+73
+
+chain 952 chr6_cox_hap2 4795371 + 2735975 2736093 chr12 132349534 - 67686596 67686714 8250173
+118
+
+chain 919 chr6_cox_hap2 4795371 + 2740748 2740808 chr4 191273063 + 44807134 44807194 22381054
+60
+
+chain 915 chr6_cox_hap2 4795371 + 2736903 2736961 chr18 76117153 + 57868323 57868381 3224910
+58
+
+chain 912 chr6_cox_hap2 4795371 + 2740082 2740112 chr7 158821424 + 107644178 107644208 21981894
+30
+
+chain 876 chr6_cox_hap2 4795371 + 2739742 2739771 chr1 247249719 - 197271642 197271671 12596898
+29
+
+chain 869 chr6_cox_hap2 4795371 + 3907293 3907342 chr10 135374737 + 5116762 5116811 5781535
+49
+
+chain 859 chr6_cox_hap2 4795371 + 2736813 2741147 chr15 100338915 + 18498519 18502823 4451069
+52	4214	4184
+68
+
+chain 858 chr6_cox_hap2 4795371 + 2739831 2739865 chr7 158821424 - 148280259 148280293 6691657
+34
+
+chain 832 chr6_cox_hap2 4795371 + 3906555 3906608 chr11 134452384 - 48407690 48407743 4638931
+53
+
+chain 819 chr6_cox_hap2 4795371 + 3906260 3906310 chr9 140273252 + 32202289 32202339 4057214
+50
+
+chain 781 chr6_cox_hap2 4795371 + 2736320 2736393 chr5 180857866 - 50968960 50969033 9780107
+73
+
+chain 771 chr6_cox_hap2 4795371 + 3907818 3907850 chr10 135374737 - 103151561 103151593 7179825
+32
+
+chain 761 chr6_cox_hap2 4795371 + 2736552 2736619 chr2 242951149 - 140069145 140069212 14744509
+67
+
+chain 747 chr6_cox_hap2 4795371 + 1377768 1377832 chr12 132349534 + 55464534 55464598 20643860
+64
+
+chain 734 chr6_cox_hap2 4795371 + 2739880 2739936 chr3 199501827 - 145206053 145206109 3741906
+56
+
+chain 734 chr6_cox_hap2 4795371 + 2735396 2736320 chr8 146274826 - 112931559 112932176 13565225
+68	769	462
+87
+
+chain 718 chr6_cox_hap2 4795371 + 2740828 2740883 chr9 140273252 - 49339912 49339967 23555332
+55
+
+chain 716 chr6_cox_hap2 4795371 + 4147141 4147193 chr16 88827254 - 38714794 38714846 22851159
+52
+
+chain 709 chr6_cox_hap2 4795371 + 2739652 2739702 chr11 134452384 - 107252690 107252740 6149448
+50
+
+chain 685 chr6_cox_hap2 4795371 + 2738531 2738584 chrX 154913754 - 2978832 2978885 8357317
+53
+
+chain 604 chr6_cox_hap2 4795371 + 1377662 1377688 chrX 154913754 - 101148638 101148664 11583046
+26
+
+chain 566 chr6_cox_hap2 4795371 + 2740606 2740665 chr2 242951149 + 168011719 168011778 5902375
+59
+
+chain 547 chr6_cox_hap2 4795371 + 2740492 2740542 chr11 134452384 - 79794459 79794509 15991276
+50
+
+chain 544 chr6_cox_hap2 4795371 + 2738003 2738054 chr13 114142980 + 104410064 104410115 4879951
+51
+
+chain 541 chr6_cox_hap2 4795371 + 2738408 2738434 chr2 242951149 - 229173591 229173617 17449766
+26
+
+chain 532 chr6_cox_hap2 4795371 + 2740024 2740082 chr9 140273252 - 118104609 118104667 4462652
+58
+
+chain 525 chr6_cox_hap2 4795371 + 3966448 3966514 chr6 170899992 + 32582000 32582066 26144539
+66
+
+chain 497 chr6_cox_hap2 4795371 + 2738584 2738618 chr12 132349534 + 9890463 9890497 23880878
+34
+
+chain 493 chr6_cox_hap2 4795371 + 2739023 2739056 chr22 49691432 + 27063354 27063387 3888752
+33
+
+chain 395 chr6_cox_hap2 4795371 + 2909998 2910026 chrX 154913754 - 101842939 101842967 6370567
+28
+
+chain 367 chr6_cox_hap2 4795371 + 2735248 2735298 chrX 154913754 + 118995097 118995147 25845816
+50
+
+chain 290 chr6_cox_hap2 4795371 + 2741541 2741593 chr1 247249719 - 204952078 204952130 18508596
+52
+
+chain 288 chr6_cox_hap2 4795371 + 3906008 3906069 chr4 191273063 - 55159498 55159559 26293742
+61
+
+chain 182 chr6_cox_hap2 4795371 + 3905895 3905941 chr9 140273252 + 29711555 29711601 32244349
+46
+
+chain 172 chr6_cox_hap2 4795371 + 4087589 4087640 chr1 247249719 - 204983626 204983677 25877235
+51
+
+chain 361837920 chr6_dbb_hap3 4610396 + 0 4610396 chr6 170899992 + 28804582 33437054 36
+932	3	0
+804	0	1
+2406	2	0
+9637	0	1
+2736	6	0
+4013	2	0
+6498	4	0
+6886	0	4
+15284	1	0
+937	0	8
+13552	0	2
+3960	0	2
+2111	0	2
+41	19	0
+8992	0	4
+59229	107905	107904
+87624	0	1
+5902	0	1
+31697	7	0
+1489	1	1
+72	1	1
+2260	0	2
+7033	0	4
+3592	0	1
+19578	0	1
+1324	0	2
+5438	5	0
+2061	1	0
+3982	6	6
+1725	0	1
+3153	1	0
+18	1	0
+18	1	0
+2026	1	0
+4175	10	10
+4746	9	9
+4767	7	7
+1225	1	0
+8	1	1
+151	1	2
+5079	1	1
+28	1	1
+249	43	43
+1178	0	4
+685	8	0
+48	4	0
+1701	1	1
+43	5	5
+862	18	18
+58	1	1
+66	1	1
+420	1	1
+44	1	1
+680	4	4
+1675	1	1
+83	1	1
+3082	4	0
+5467	1	1
+27	0	1
+1099	12	0
+627	12	12
+1317	6	1
+129	1	1
+25	1	1
+1397	15	15
+810	1	1
+27	1	1
+1192	3	0
+7515	4	0
+979	0	3
+3406	0	2
+3501	1	1
+26	1	1
+787	0	1
+1416	3	1
+22815	4	4
+126	1	0
+38	1	1
+140	1	0
+999	0	17
+56	0	15
+15438	4	0
+6165	0	1
+1768	1	0
+7727	1	0
+1514	0	1
+3116	0	1
+3278	1	1
+21	1	1
+1738	0	1
+8576	19	0
+8020	1	0
+2049	1	0
+518	13	11
+1704	1	1
+117	1	1
+1448	10	0
+4403	9	9
+2265	1	0
+25400	9	9
+4420	1	1
+32	1	1
+2539	1	0
+9981	17923	17922
+148	1	1
+25	1	1
+1461	4	1
+1402	0	1
+3961	0	3
+58	1	1
+112	1	1
+1419	1	1
+34	0	1
+2697	0	2
+40	1	1
+2168	0	1
+1019	0	2
+1099	0	4
+40	1	1
+1374	11	0
+31	1	1
+189	1	1
+26	1	1
+327	1	1
+38	1	1
+177	11	11
+303	1	1
+34	1	1
+1438	1	1
+46	1	1
+727	1	1
+26	1	1
+2373	5	0
+321	1	0
+933	17	17
+82	9	9
+2773	0	143
+80	1	1
+25	1	1
+467	1	1
+27	1	1
+143	1	1
+47	4	4
+1194	10	10
+1455	1	1
+33	1	1
+601	1	1
+46	0	4
+694	1	3
+91	1	1
+59	1	1
+167	6	6
+113	1	1
+31	1	1
+1181	0	1
+422	15	0
+36	1	1
+2219	1	1
+35	1	1
+2116	0	1
+8249	0	3
+1120	1	0
+870	16	0
+5547	0	2
+5376	0	6
+2275	1	1
+43	1	1
+78	4	4
+24710	1	0
+64762	6	3
+441	1	0
+2338	1	0
+1948	1	1
+26	1	1
+214	0	1
+6118	1	1
+31	1	1
+2382	5	5
+4335	1	1
+39	1	1
+4561	1	1
+38	1	1
+2199	1	1
+49	1	1
+243	17	6
+2779	1	1
+37	2	0
+24	1	1
+1966	3	0
+233	1	1
+29	1	1
+17718	6	0
+46568	1	0
+18985	0	2
+1833	3	4
+5288	0	9
+2728	1	5
+722	0	1
+502	0	1
+1025	0	1
+134	14	0
+4944	0	1
+319	1	0
+6178	0	1
+2880	1	1
+17	0	2
+143	0	1
+1775	1	0
+2123	0	1
+2715	1	0
+4921	1	1
+47	4	0
+2882	1	0
+1362	1	0
+1233	0	8
+2134	0	1
+1042	0	1
+163	1	1
+45	1	1
+50	2	0
+64	1	1
+48	1	1
+380	0	1
+30	1	0
+30	1	1
+61	1	1
+22	1	1
+691	0	2
+84	1	1
+230	1	1
+37	3	1
+162	1	1
+194	2	0
+36	1	1
+242	9	9
+697	33	33
+1202	1	1
+16	1	1
+528	1	1
+20	1	1
+131	9	9
+369	0	5
+76	1	1
+21	1	1
+439	15	15
+2779	1	0
+1597	24	28
+59	12	12
+307	1	0
+516	1	0
+286	11	33
+339	5	0
+570	1	1
+37	1	1
+220	1	0
+72	1	1
+144	1	1
+48	1	1
+247	2	0
+174	9	10
+816	1	0
+940	1	1
+45	1	1
+91	3	3
+71	1	1
+291	14	14
+100	1	1
+23	1	1
+452	3	3
+229	1	1
+252	0	1
+129	15	15
+432	10	0
+85	1	1
+28	1	1
+189	2	1
+71	1	1
+52	8	0
+810	2	2
+63	1	1
+378	1	1
+26	1	1
+187	31	36
+966	1	1
+25	1	1
+91	12	12
+125	1	1
+38	1	1
+433	2	0
+596	1	1
+48	1	1
+465	4	4
+64	1	1
+20	1	1
+525	5	5
+237	3	8
+99	31	31
+53	11	0
+364	4	3
+201	1	1
+42	1	1
+56	1	1
+115	1	0
+67	16	16
+244	1	1
+54	5	5
+929	1	1
+21	1	1
+126	0	3
+830	1	11
+59	1	1
+537	0	2
+24	1	1
+745	15	15
+810	1	0
+425	1	1
+89	1	1
+592	1	1
+49	1	1
+352	0	1
+142	1	1
+30	1	1
+95	1	1
+45	1	1
+227	1	1
+53	1	1
+130	1	1
+18	1	1
+138	1	1
+90	1	1
+129	1	1
+39	1	1
+50	1	1
+79	1	1
+117	1	1
+31	1	1
+155	156	0
+34	1	1
+50	5	5
+57	1	1
+152	1	1
+30	1	1
+177	5	5
+345	1	1
+39	1	1
+504	18	18
+596	12	12
+54	1	1
+158	1	1
+164	1	1
+34	1	1
+626	15	15
+866	0	10
+1051	0	2611
+680	0	1
+1537	0	18
+75	1	0
+145	6	0
+9	39	0
+107	0	18
+23	1	1
+1927	13	13
+1702	2	0
+3694	1	1
+18	1	1
+958	39	47
+246	2	0
+146	1	1
+49	1	1
+410	1	0
+667	1	1
+38	1	1
+362	7	1
+159	2	0
+515	2	0
+1026	1	1
+29	1	1
+249	0	6
+129	1	1
+33	4	0
+10	1	5
+1236	1	1
+20	1	1
+138	10	9
+448	0	3
+660	1	1
+28	1	1
+83	1	1
+51	1	1
+2659	1	1
+38	1	1
+424	0	1
+70	1	1
+694	1	1
+19	1	1
+105	1	1
+26	1	1
+1472	1	1
+21	1	1
+491	5	5
+163	15	15
+2194	2	0
+533	2	0
+441	1	7
+1689	1	1
+26	3	4
+879	16	16
+514	0	2
+58	1	1
+350	1	0
+769	1	1
+39	1	1
+573	0	4
+37	1	1
+144	8	8
+1036	2	0
+262	2	2
+38	0	1
+70	18	18
+84	11	13
+169	62	63
+74	11	15
+1255	0	2
+332	1	1
+21	1	1
+193	8	24
+34	1	1
+79	1	1
+29	1	1
+536	1	0
+308	0	1
+850	0	32
+23	1	1
+651	1	1
+22	0	3
+136	1	1
+48	1	1
+330	9	9
+1108	1	1
+98	1	1
+582	0	2
+713	7	7
+89	1	0
+293	9	8
+125	1	1
+31	1	1
+192	6	6
+171	17	17
+681	1	1
+43	1	1
+514	1	1
+68	1	1
+537	1	1
+35	1	1
+159	6	6
+778	17	17
+198	0	7
+105	1	1
+40	1	1
+95	13	13
+247	1	1
+19	1	1
+2044	7	8
+2512	0	15
+2982	4	0
+3135	1	2
+1698	13	13
+15862	0	1
+925	0	183
+36	16	1
+18	0	1
+25	1	1
+7717	1	1
+40	1	1
+758	1	1
+46	1	1
+5530	11	9
+3326	1	1
+37	1	1
+6743	0	4
+7923	1	1
+26	5	5
+3475	26	0
+8	1	1
+566	4	0
+141	0	1
+2078	24	24
+2759	0	4
+1659	4	0
+52	4	0
+3265	0	2
+2235	17	16
+2946	0	372
+2644	31	31
+92	1	1
+35	1	1
+705	323	0
+3157	40	40
+718	0	4
+787	1	1
+34	1	1
+927	4	4
+72	1	1
+2414	0	1
+993	1	1
+31	1	1
+1514	1	1
+29	1	1
+1109	1	1
+44	1	1
+208	4	1
+1022	11767	11699
+85	98	98
+60	2515	8169
+103	11	11
+41	1	1
+72	4	4
+76	1	1
+70	5	5
+83	1	1
+117	1	1
+130	1	1
+44	1	1
+414	1	1
+152	1	0
+218	1	1
+161	1	0
+120	14	14
+145	1	1
+49	4	4
+72	1	1
+53	19	19
+111	2	2
+32	3	3
+553	0	2
+336	12	12
+54	24	24
+171	0	6
+90	1	1
+28	1	1
+142	16	16
+36	1	1
+428	1	1
+16	1	1
+338	1	1
+31	1	1
+294	1	1
+92	0	1
+129	13	14
+602	1	1
+112	1	1
+247	1	1
+80	1	1
+173	1	1
+44	1	5
+497	1	1
+38	1	1
+98	1	1
+130	1	1
+319	1	1
+16	1	1
+59	1	1
+82	1	1
+141	1	1
+23	1	1
+241	1	1
+26	1	1
+184	0	3
+19	1	1
+510	1	1
+36	1	1
+162	2	2
+15	1	1
+145	1	1
+28	1	1
+120	0	3
+93	1	2
+24	0	9
+169	12	0
+292	9911	10000
+401	1	1
+27	1	1
+296	1	1
+120	1	1
+357	1	1
+107	2	0
+31	1	1
+83	89	0
+194	1	1
+33	1	1
+230	1	1
+142	5	5
+108	1	1
+36	1	1
+287	1	1
+19	1	1
+104	1	1
+31	1	1
+144	1	1
+212	1	1
+452	5	6
+148	1	1
+70	1	1
+137	3	3
+67	1	1
+73	22	22
+115	12	12
+142	5	5
+269	15	15
+102	6	6
+93	1	1
+82	1	1
+170	1	1
+22	1	1
+504	2	2
+60	1	1
+150	1	1
+31	1	1
+90	1	1
+15	1	0
+258	6	7
+85	1	1
+77	1	1
+123	2	2
+67	0	1
+56	2	2
+25	1	1
+71	1	1
+28	2	2
+50	1	1
+85	2	2
+66	6	6
+186	1	1
+20	1	1
+67	1	1
+25	1	1
+227	2	2
+155	1	1
+777	1	1
+33	1	2
+26	6	6
+474	1	1
+36	1	1
+151	1	1
+29	1	1
+120	1	1
+23	1	1
+736	17	17
+112	1	1
+39	1	1
+553	1	1
+69	1	1
+116	2	0
+161	1	1
+86	1	1
+705	1	1
+57	3	3
+145	1	1
+204	1	1
+88	1	1
+35	1	1
+92	1	1
+147	1	1
+149	20	20
+210	1	1
+55	2	2
+65	1	1
+32	1	1
+1008	1	1
+24	1	1
+159	18	18
+391	0	1
+327	17	19
+77	1	3
+65	1	1
+84	1	0
+392	2	0
+363	1	0
+1024	0	1
+480	9	9
+119	1	1
+72	1	1
+400	1	1
+46	1	1
+288	11	7
+53	1	1
+80	1	1
+37	1	1
+129	1	1
+80	1	1
+252	4	4
+86	0	1
+129	3	3
+67	1	1
+123	9	9
+199	2	2
+80	1	1
+114	28369	30000
+51	5	5
+45	1	1
+53	1	1
+37	1	1
+81	1	1
+369	1	1
+72	15	15
+98	1	1
+53	0	8
+67	2	0
+41	1	1
+92	1	1
+20	1	1
+283	6	6
+70	7	7
+50	1	1
+25	1	1
+225	5	1
+31	1	1
+449	2	1
+10	1	23
+64	4	4
+3770	1	0
+3862	16	16
+1187	12	12
+97	0	3
+772	1	1
+21	2	1
+1058	0	2
+349	2	0
+1080	18	14
+53	15	17
+1035	1	1
+85	1	1
+69	1	1
+27	1	1
+547	7	7
+195	1	1
+41	1	1
+395	1	1
+35	1	1
+73	0	1
+71	1	1
+557	3	3
+30	1	1
+66	1	1
+25	1	1
+1332	0	2
+26	2	0
+10	1	15
+36	1	1
+196	1	1
+40	1	1
+141	1	1
+76	1	1
+1480	1	3
+347	1	1
+26	1	1
+231	1	1
+82	3	3
+69	3	0
+441	16	16
+147	1	1
+21	1	1
+3565	0	6
+874	2	0
+1036	1	1
+47	3	1
+3761	12	0
+5345	1	0
+11541	1	0
+1843	0	4
+1157	16	16
+7354	19	0
+741	0	1
+8053	1	0
+4449	21	21
+649	1	0
+2913	0	1
+381	332	0
+3533	31	31
+2502	0	1
+1968	7	0
+3198	1	0
+667	1	0
+3870	0	1
+36	13	0
+1894	1	1
+40	0	4
+1348	2	0
+345	1	0
+592	4	4
+1043	4	0
+686	14	0
+1032	0	1
+9035	0	4
+167	0	2
+13644	6258	6257
+4063	0	3
+1760	3	0
+3371	1	1
+23	1	1
+321	5	0
+644	8	0
+47	1	1
+322	1	1
+145	1	1
+1551	11	15
+355	0	1
+1831	4	0
+1779	1	1
+27	1	1
+199	43	55
+2881	1	1
+39	1	1
+120	1	2
+24	1	1
+556	1	0
+393	6	6
+4381	1	0
+524	1	1
+20	1	1
+151	3	3
+144	1	1
+189	1	7
+1445	0	1
+1002	0	1
+7912	4	0
+4977	0	1
+10485	1	1
+48	1	1
+724	1	1
+51	5	0
+39	1	1
+6830	0	1
+15554	0	1
+4385	0	7
+881	0	8
+17594	0	20
+2417	1	0
+998	0	10
+4239	7	0
+4845	0	2
+95	28	23
+10921	1	1
+40	1	1
+4759	0	6
+12084	0	3
+3052	0	4
+2989	1	0
+13523	1	3
+16170	1	0
+11761	0	6
+1158	3	0
+2751	0	6
+1294	1	1
+43	1	1
+5275	0	7
+377	3	0
+7256	3	0
+419	2	0
+10674	0	17
+10821	0	1
+296	0	1
+1770	2	0
+374	0	3
+7469	0	4
+1471	1	0
+3061	2	0
+5818	1	0
+2415	11	9
+2056	0	1
+955	4	0
+17260	1	0
+9557	0	2
+5358	0	1
+11538	4	0
+2627	2	0
+57496	1	1
+29	1	1
+6617	19	0
+254	0	1
+14267	2	0
+9045	3	1
+174	2	0
+4155	1	0
+1153	1	0
+1289	0	40
+12155	0	4
+7692	2	0
+396	22	12
+918	0	1
+1818	0	1
+28	1	1
+492	1	1
+33	1	1
+326	1	1
+80	1	1
+288	8	17
+2671	0	1
+1099	0	1
+144	1	1
+29	0	1
+2098	0	2
+24	3	0
+1207	4	4
+45	1	1
+757	0	5
+1926	1	1
+40	1	1
+330	3	0
+340	1	1
+43	1	1
+1942	0	1
+414	1	0
+61	0	1
+235	0	2
+2087	0	1
+754	0	4
+17	3	0
+1027	3	0
+428	1	1
+17	1	1
+948	1	1
+41	1	1
+458	1	1
+21	1	1
+1055	0	1
+8189	4	5
+36	1	1
+99	2	0
+700	0	4
+149	0	1
+750	0	3
+40	1	1
+3179	2	0
+473	0	2
+2032	1	0
+3841	1	0
+560	1	0
+1108	1	0
+8087	1	0
+11881	1	1
+30	1	1
+4383	3	0
+9930	1	1
+56	510	509
+518	8	5
+853	1	1
+80	1	1
+2210	1	0
+905	0	1
+1037	2	0
+5866	0	2
+18	1	1
+582	0	5
+2828	1	0
+847	1	0
+1996	2	0
+700	1	1
+1970	0	1
+498	1	0
+1751	0	1
+910	2	0
+691	0	1
+32873	0	1
+19298	0	6
+1371	29	0
+494	2	0
+39050	0	1
+920	0	1
+6820	1	0
+1376	1	2
+1931	33	33
+2376	0	1
+12415	1	1
+51	0	1
+9375	0	1
+323	1	0
+2697	1	0
+15090	120	0
+7116	1	0
+2469	1	0
+5977	2	1
+4888	0	4
+4674	1	0
+2044	1	0
+2153	0	1
+1964	5	5
+2153	1	1
+41	1	1
+774	0	2
+2623	1	1
+81	1	1
+335	2	2
+59	1	1
+335	0	3
+533	2	0
+45	4	0
+986	2	0
+13	1	1
+450	28	27
+295	1	0
+202	1	1
+27	1	1
+70	312	0
+218	1	0
+51	1	1
+31	1	1
+428	0	1
+28	1	1
+118	1	1
+24	1	18
+34	1	1
+75	1	1
+43	2	2
+73	1	1
+29	1	1
+246	1	1
+42	1	1
+409	4	4
+1168	10	1
+310	1	1
+49	1	1
+3002	1	1
+38	1	1
+789	0	1
+63	9	9
+2434	0	8
+980	0	2
+749	8	8
+528	1	1
+24	1	1
+1646	15	15
+528	1	1
+16	1	1
+1402	1	1
+23	1	1
+67	7	0
+35	2	0
+7	0	2
+221	1	1
+45	1	1
+259	1	1
+47	1	1
+384	1	1
+47	1	1
+330	0	4
+490	1	1
+33	1	1
+1841	1	1
+52	0	2
+6	11	0
+193	1	1
+47	1	1
+164	3	7
+31	0	1
+291	1	1
+15	1	1
+877	4	0
+30	1	1
+194	6	0
+93	4	4
+1004	1	1
+20	1	1
+345	1	1
+43	1	1
+365	0	1
+388	1	1
+27	1	1
+253	9	9
+390	1	0
+118	0	1
+170	4	0
+915	1	0
+352	0	4
+520	1	1
+29	20	0
+1167	1	1
+45	1	1
+213	8	0
+51	1	1
+107	10	11
+134	2	0
+228	103	1
+51	2	1
+68	1	1
+59	1	1
+195	1	161
+13	1	1
+553	2	2
+36	1	1
+143	1	0
+1874	4	0
+519	0	1
+476	1	0
+1530	0	1
+1126	2	0
+831	1	1
+40	1	1
+1131	88	87
+2063	0	2
+1950	1	1
+32	1	1
+2217	2	1
+661	0	2
+1239	0	1
+64	1	1
+33	1	1
+13968	0	1
+1222	2	0
+5082	10	0
+413	0	1
+986	23	22
+1194	2527	2526
+12324	0	2
+893	8	0
+1343	2	0
+5784	9	9
+770	12	0
+1044	2	0
+2231	1	1
+48	1	1
+557	0	1
+7497	8	8
+1051	16	0
+49	1	1
+10474	0	3
+1427	1	0
+670	1	3
+766	1	1
+32	1	1
+395	0	9
+170	1	0
+792	2	0
+286	1	0
+117	11	12
+283	26	21
+277	0	2
+48	1	1
+124	1	1
+34	2	1
+316	1	1
+41	1	1
+8214	0	8
+368	2	0
+4	4	0
+3535	17	0
+4228	33	33
+945	0	1
+562	0	1
+1440	0	1
+804	0	11
+1565	0	3
+3008	1	0
+31	1	1
+800	21	17
+650	1	1
+30	1	1
+82	13	13
+5212	1	0
+2003	1	2
+12179	0	1
+2700	2	0
+2735	0	1
+4202	0	3
+4503	1	0
+270	1	0
+12929	0	3
+4009	0	5
+6425	2	0
+310	1	0
+809	2	0
+17	8	0
+2256	0	1
+3207	17	10
+2436	0	14
+1040	1	1
+52	1	1
+6972	1	0
+2357	0	1
+29	1	1
+262	1	0
+72	1	1
+45	1	1
+57	17	17
+1390	0	16
+328	312	0
+65	1	1
+217	10	10
+925	0	33
+1490	1	0
+35	1	1
+226	0	3
+805	1	1
+46	1	1
+192	1	1
+56	1	1
+245	1	1
+61	1	1
+198	4	0
+82	2	2
+29	1	1
+57	0	2
+320	1	1
+22	1	1
+267	5	0
+427	1	0
+17	1	1
+425	1	1
+34	1	1
+565	10	10
+432	10	0
+55	1	1
+90	1	1
+140	1	1
+83	1	1
+1035	1	1
+33	1	1
+144	4	4
+38	1	1
+171	1	1
+35	3	3
+161	6	6
+731	7	3
+1216	25	0
+52	0	1
+419	2	0
+87	8	8
+757	1	1
+67	1	1
+3935	30	0
+791	3	0
+2849	1	1
+33	1	1
+6790	1	1
+67	4	4
+39	2	0
+251	1	1
+37	1	1
+826	3715	901
+205	2	0
+946	1	1
+30	1	1
+613	5	2
+128	29	29
+802	0	89
+1600	0	6
+2112	1	1
+42	1	0
+1164	1	0
+1310	1	0
+1501	0	4
+822	1	1
+42	1	1
+2266	1	0
+25235	0	1
+6697	1	0
+766	1	0
+4188	0	2
+2710	1	1
+17	1	1
+1924	0	7
+5868	1	1
+22	1	1
+2394	0	4
+125	3	0
+718	1	0
+8414	1	1
+49	1	1
+146	1	1
+61	1	1
+116	1	1
+41	1	1
+137	1	1
+30	1	1
+158	9	9
+136	10	13
+1733	17	17
+1053	4	4
+228	1	1
+34	1	1
+355	1	1
+113	1	1
+330	0	1
+222	1	1
+25	1	1
+267	1	1
+38	1	1
+709	2	0
+1448	0	1
+152	1	1
+46	1	1
+237	1	1
+20	1	1
+195	21	21
+88	1	1
+33	1	1
+211	1	1
+65	1	1
+516	58	58
+491	7	7
+208	13	12
+558	2	2
+28	1	1
+125	4	4
+634	1	1
+33	1	1
+159	0	1
+318	1	0
+370	5	5
+80	1	1
+250	0	3
+78	1	1
+45	1	1
+130	3	1
+22	0	1
+180	1	1
+90	1	1
+633	1	1
+36	0	1
+388	0	1
+861	1	1
+103	1	1
+274	16	18
+170	30	30
+796	0	1
+167	0	1
+871	1	1
+27	1	1
+32	0	8
+831	0	13
+90	1	1
+527	1	1
+125	1	1
+1050	10	10
+624	16	16
+1093	5	5
+48	1	0
+168	30	34
+1315	1	1
+33	1	1
+303	1	1
+36	1	1
+601	14	14
+1014	4	0
+134	2	9
+818	1	0
+61	1	7
+641	5	5
+1677	1	1
+49	1	1
+346	87	87
+790	27	27
+104	1	1
+75	1	1
+1638	1	1
+16	1	1
+92	1	1
+44	1	1
+276	0	13
+1020	1	1
+35	1	1
+389	14	14
+256	1	0
+38	1	3
+106	1	1
+21	1	1
+502	1	1
+40	1	1
+2356	1	1
+82	2	0
+1300	0	5
+511	0	2
+605	1	1
+17	1	1
+880	13	0
+1689	4	0
+2492	1	1
+39	1	1
+641	16	16
+682	0	5
+669	1	1
+25	1	1
+1926	1	1
+39	4	3
+1037	1	1
+40	2	0
+890	6	0
+41	2	0
+501	4	1
+317	0	1
+281	3	0
+450	1	1
+34	1	1
+498	1	1
+28	2	1
+280	0	2
+648	1	1
+47	1	1
+1002	4	0
+120	1	1
+1538	0	1
+75	1	1
+37	1	1
+517	1	1
+79	4	4
+60	18	18
+2075	1	1
+19	1	1
+2429	1	1
+21	1	1
+107	1	0
+2786	0	2
+33	3	3
+1973	8	0
+3118	1	0
+246	0	1
+33	1	1
+1333	9	9
+5410	1	0
+822	2	9
+606	1	1
+18	1	1
+3920	1	1
+37	0	2
+4497	10	13
+2468	2	0
+1510	1	1
+23	1	1
+308	0	4
+3780	3	0
+850	0	1
+2774	0	3
+3487	1	0
+3243	0	15
+1336	5	0
+618	7	7
+1507	8	7
+379	44	43
+2184	0	1
+304	0	2
+19	0	1
+101	1	1
+417	3	3
+22	1	1
+672	4	4
+31	1	1
+150	1	1
+38	1	1
+161	5	0
+17	1	1
+72	1	0
+106	1	1
+463	1	1
+236	0	2
+184	1	1
+29	1	1
+220	15	15
+167	1	1
+32	1	1
+93	1	3
+217	1	1
+23	1	1
+137	9	9
+62	0	3
+353	1	1
+27	1	1
+117	9	9
+421	1	1
+47	1	1
+124	0	1
+997	6	0
+54	5	5
+764	1	1
+45	1	1
+1431	7	7
+387	6	6
+1103	0	44
+759	1	1
+31	1	3
+208	5	5
+1610	1	1
+23	1	1
+779	0	8
+311	0	3
+322	0	3
+45	1	1
+250	1	1
+18	1	1
+517	29	0
+117	1	1
+42	1	1
+550	1	1
+20	1	1
+671	1	1
+68	1	1
+89	1	1
+104	1	1
+172	0	1
+124	0	1
+522	0	1500
+466	5	5
+32	1	0
+171	1	1
+19	1	1
+67	1	1
+22	1	1
+654	1	1
+25	1	1
+68	1	1
+21	4	0
+1588	1	1
+66	1	1
+401	0	1
+186	1	1
+21	1	1
+168	0	1
+686	3	0
+19	1	1
+127	1	1
+29	1	1
+234	1	1
+30	1	1
+141	0	2
+33	1	1
+673	1	1
+89	1	1
+161	16	16
+504	1	1
+192	0	3
+105	1	1
+286	1	1
+101	15	16
+158	8	0
+57	1	1
+332	2	2
+35	1	1
+371	1	1
+55	1	1
+86	1	1
+29	1	1
+196	1	1
+44	1	0
+52	19995	20030
+60	8	8
+50	0	3
+129	1	1
+281	1	1
+30	1	1
+109	1	1
+35	1	1
+113	1	1
+34	1	1
+734	1	1
+44	1	1
+106	1	1
+62	1	1
+140	1	1
+76	1	0
+34	1	1
+98	1	1
+149	1	1
+284	1	1
+37	1	1
+705	1	12
+106	1	1
+55	1	1
+1470	0	7
+258	1	1
+48	1	1
+1807	6	6
+63	1	1
+32	1	1
+346	18	18
+9596	12	0
+3853	9	9
+317	4	4
+30	1	1
+71	1	1
+60	1	1
+103	10	10
+71	2	0
+30	1	1
+312	5	0
+170	13	13
+55	2	2
+58	1	0
+30	1	1
+189	37	38
+827	0	17
+26	1	1
+1461	1	1
+24	1	1
+2968	22	22
+137	12	14
+889	11	11
+4010	0	6
+1377	1	1
+34	1	1
+312	1	1
+16	1	1
+715	1	1
+24	1	1
+930	1	1
+22	1	1
+89	1	1
+42	1	1
+108	44	45
+228	149088	159295
+108	1	1
+41	1	1
+11025	4	4
+1194	1	1
+59	1	1
+128	1	0
+1177	82	82
+60	1	1
+48	1	1
+501	19	19
+336	1	1
+42	1	1
+176	4	4
+469	1	1
+35	1	1
+270	1	1
+33	1	1
+289	1	1
+24	1	1
+226	64	0
+42	1	1
+651	1	1
+39	1	1
+123	1	1
+35	1	0
+294	1	1
+32	18	4
+351	1	1
+39	1	1
+135	1	1
+46	1	1
+121	1	1
+19	1	1
+755	4	4
+70	1	1
+456	39	36
+82	1	1
+48	1	1
+441	1	1
+70	1	1
+381	1	1
+46	1	1
+239	1	1
+30	1	1
+87	1	1
+102	3	4
+34	1	1
+488	12	12
+1059	1	1
+45	1	1
+705	1	1
+21	1	1
+107	111	111
+432	3	0
+460	4	4
+1212	0	2
+306	0	1
+1446	19	19
+299	7	33
+78	195	6
+66	1	1
+135	12	12
+778	1	0
+773	1	1
+45	1	1
+253	6	6
+823	1	1
+22	1	1
+2476	10	0
+294	28	10
+307	3	11
+65	0	4
+40	1	1
+4535	1	1
+26	1	1
+371	0	2
+3510	1	1
+16	1	1
+189	1	1
+19	1	1
+814	0	1
+2785	6	1
+1424	0	1
+934	1	1
+49	1	1
+1350	1	0
+384	1	1
+24	1	1
+3117	10	10
+518	0	1
+523	0	16
+243	10	10
+2167	18	14
+64	1	1
+31	1	1
+185	0	4
+1647	1	1
+20	1	1
+227	1	1
+37	1	1
+636	3	4
+8239	1	1
+23	1	1
+1114	0	2
+1590	18	18
+4781	0	4
+815	0	1
+5069	0	5
+415	0	1
+3541	0	1
+878	0	1
+5752	0	2
+1502	0	1
+51	1	1
+60	1	1
+278	0	1
+19	1	1
+1164	11	11
+691	0	2
+960	1	0
+63	0	18
+2109	0	2
+1265	0	1
+1642	2	0
+10831	4	2
+188	0	1
+1650	1	0
+40	1	1
+2962	2	0
+48	1	1
+4899	6	0
+4945	1	0
+60	4	0
+964	0	1
+918	1	0
+706	0	3
+349	1	0
+1673	0	1
+1909	11	11
+1662	15	0
+720	0	1
+2076	0	2
+329	14	0
+3605	0	3
+853	5	6
+3597	1	0
+378	0	1
+969	2	0
+299	0	1
+874	0	4
+663	6	0
+297	0	3
+2049	0	3
+878	11	11
+93	43	43
+13912	0	1
+398	1	1
+145	1	1
+512	16	16
+3139	0	4
+1305	7	0
+3045	1	0
+4179	1	1
+37	1	1
+1336	4	0
+13736	1	0
+11145	1	0
+3867	1	0
+1713	0	1
+2721	0	9
+8875	0	2
+4120	2	0
+13331	0	2
+15149	0	1
+8815	2	0
+1617	0	1
+1686	4	0
+2225	4	0
+7008	1	0
+4374	0	1
+2620	4	0
+43394	1	0
+10823	4	0
+25730	0	1
+554	1	0
+128	0	1
+8274	17	17
+22100	0	4
+40775	1	0
+5693	29	27
+170	1	0
+3528	0	1
+191	1	2
+117	2	0
+2275	1	0
+12676	1	1
+20	1	1
+5364	1	0
+1275	0	2
+3331	1	0
+310	1	0
+13645	0	5
+14860	1	1
+38	1	1
+3605	0	1
+2898	0	1
+10662	1	0
+8241	17	17
+439	16	16
+59	5	4
+7707	1	0
+3007	1	1
+40	1	1
+1569	1	1
+30	1	1
+163	11	11
+8253	35	6402
+5016	17	17
+439	16	16
+59	4	5
+9184	1	1
+19	1	1
+2941	1	1
+105	1	1
+803	5	4
+1011	1	1
+43	1	1
+705	8	8
+574	1	0
+7691	1	0
+5183	0	2
+9452	5	0
+45	0	8
+4438	1	0
+6869	1	0
+1770	0	1
+4094	0	12
+4249	0	3
+4114	0	1
+1404	0	1
+1229	0	2
+3129	0	10
+769	0	2
+709	1	0
+161	0	1
+969	0	1
+1492	0	7
+655	8	8
+251	0	2
+234	1	0
+19500	0	2
+8097	1	0
+1243	0	4
+718	0	2
+1466	1	0
+527	1	0
+3294	1	0
+299	0	1
+374	1	0
+107	1	1
+21	1	1
+2114	0	1
+1422	0	1
+2149	1	0
+311	2	0
+2025	1	1
+36	1	1
+4504	2	0
+3636	10	0
+588	1	1
+21	1	1
+3237	15	0
+39	6	0
+547	74304	74303
+1020	0	3
+747	0	1
+1011	1	1
+43	1	1
+3164	1	0
+1681	0	2
+473	1	5
+107	4	0
+719	0	1
+1154	9	9
+221	0	2
+9332	1	0
+1190	30	0
+783	1	1
+59	1	1
+94	1	1
+21	1	1
+430	11	11
+50	1	1
+49	1	1
+289	3	0
+120	0	1
+37	1	1
+112	1	1
+21	1	1
+183	16	16
+73	2	0
+1007	1	1
+38	0	1
+79	1	1
+48	1	1
+561	1	1
+29	1	1
+145	5	5
+576	12	12
+834	1	0
+846	5	7
+34	1	1
+483	1	1
+40	1	1
+110	7	7
+393	1	1
+215	1	1
+260	1	1
+36	0	1
+604	1	0
+169	0	1
+2118	1	1
+34	1	1
+147	1	1
+213	1	1
+67	1	1
+31	1	1
+566	1	0
+17	1	1
+210	0	2
+551	1	1
+34	1	1
+685	0	3
+24	2	2
+98	0	1
+449	0	2
+61	1	1
+38	1	1
+202	1	1
+44	1	1
+190	1	0
+46	4	4
+51	0	4
+476	1	1
+17	1	1
+82	1	1
+46	1	1
+82	1	1
+26	1	1
+485	1	1
+25	1	1
+263	1	1
+26	1	1
+1327	4	0
+44	1	0
+2397	1	1
+44	1	1
+928	4	0
+3218	14	14
+4406	1	0
+1125	1	0
+254	1	0
+427	0	1
+30	1	1
+111	0	2
+586	17	1
+970	1	1
+10	1	0
+28	1	1
+140	1	1
+43	1	1
+1327	1	1
+24	1	1
+636	2	1
+598	1	1
+44	1	1
+170	1	0
+4840	1	1
+28	11	7
+485	0	1
+263	0	2
+4912	4	0
+543	1	0
+18	1	1
+127	1	2
+102	6	0
+148	16	7
+1346	0	1
+128	7	0
+49	0	1
+876	1	0
+286	5	5
+184	0	1
+84	5	5
+365	9	9
+981	1	1
+11	1	1
+734	4	0
+563	4	0
+632	1	1
+17	1	1
+49	1	0
+95	1	1
+30	1	1
+147	1	1
+37	0	6
+340	1	2
+58	1	1
+112	0	1
+219	0	2
+231	0	3
+164	0	1
+26	1	1
+439	4	0
+34	0	2
+508	3	0
+96	1	1
+34	1	1
+829	1	1
+31	1	1
+405	15	15
+663	4	5
+1055	13	13
+135	0	1
+194	63	63
+384	6	6
+2756	1	1
+19	1	1
+1868	2	3
+2238	1	1
+31	1	1
+3002	4	0
+1116	1	1
+22	1	1
+1016	15	15
+855	15	13
+442	5	5
+2022	6	6
+506	0	2
+1110	0	1
+7396	1	1
+84	1	0
+3187	1	1
+16	1	1
+184	1	1
+18	1	1
+1607	53	60
+527	1	1
+39	1	1
+288	0	1
+364	3	0
+227	1	1
+18	1	1
+218	0	323
+91	1	0
+124	0	15
+621	0	4
+553	8	8
+467	1	1
+40	1	1
+372	1	1
+25	1	1
+188	12	12
+357	0	1
+250	0	5
+4193	0	4
+597	49	49
+321	1	1
+76	1	1
+2040	11	10
+1137	1	1
+48	4	4
+529	7	7
+246	4	0
+160	1	1
+34	0	3
+1469	0	2
+241	1	1
+17	1	1
+239	1	0
+937	1	1
+45	1	1
+421	6	0
+2127	0	1
+491	1	0
+80	1	1
+72	2	0
+255	6	6
+739	3	0
+702	5	0
+290	0	2
+210	5	1
+473	1	1
+42	4	0
+219	0	1
+348	1	1
+83	1	1
+851	0	16
+72	14	0
+246	1	1
+47	4	0
+410	1	0
+93	0	12
+225	0	14
+430	1	0
+4	6	0
+324	0	1
+939	1	1
+27	1	1
+142	1	1
+37	1	1
+1246	1	1
+44	1	1
+445	0	4
+173	0	2
+10545	1	1
+47	1	1
+1247	37	55
+805	1	0
+3789	1	1
+35	1	1
+1731	30	30
+2105	1	1
+30	1	1
+6075	1	0
+462	0	15
+4585	1	0
+3297	1	1
+49	1	1
+606	1	1
+48	1	1
+123	5	9
+109	1	31
+44	10	781
+77	2	0
+114	1	1
+62	1	1
+106	1	1
+268	18	4
+1079	0	2
+381	4	4
+106	1	1
+376	1	0
+1011	8	0
+584	5	0
+7537	7	0
+736	13	3
+2095	1	1
+45	1	1
+12786	0	11
+43	1	1
+720	5	7
+1358	0	2
+3813	19986	20000
+486	1	1
+46	1	1
+412	1	1
+23	1	0
+174	1	1
+24	1	1
+83	15	15
+363	1	1
+91	1	1
+51	17	17
+315	20	20
+199	13	13
+976	1	1
+39	0	3
+161	14	15
+127	16	16
+517	1	1
+81	1	1
+218	28	28
+124	1	1
+68	0	22
+252	1	1
+36	1	1
+784	0	1
+175	1	0
+148	1	1
+83	1	1
+469	1	1
+69	1	1
+245	1	1
+90	4	4
+1034	15	15
+69	1	1
+33	1	1
+174	1	1
+56	1	1
+169	1	0
+201	1	1
+30	1	1
+58	1	1
+38	1	1
+91	1	1
+98	4	4
+65	1	1
+19	2	0
+104	6	5
+25	1	1
+218	1	1
+37	1	1
+343	153809	150023
+66	8	8
+36	0	11
+62	1	1
+107	1	1
+68	3	130
+66	4	4
+50	21	21
+98	1	1
+127	1	0
+192	1	1
+71	1	1
+52	1	1
+200	1	1
+97	4	4
+85	5	5
+448	1	1
+97	11	11
+171	1	1
+61	1	1
+37	1	1
+156	3	0
+63	0	3
+155	3	0
+32	2	0
+232	1	1
+33	1	1
+175	2	0
+131	6	6
+1409	0	3
+222	1	1
+23	0	1
+1470	1	1
+21	1	1
+460	1	1
+71	1	1
+394	2	8
+37	1	1
+90	1	1
+43	1	1
+650	1	1
+34	1	1
+839	0	1
+431	1	1
+36	1	1
+284	60066	60160
+93	1	1
+75	808	0
+46	1	1
+221	1	1
+213	8	0
+63	1	1
+60	17	17
+53	1	1
+29	1	1
+68	8	8
+62	9	9
+51	1	1
+85	1	1
+101	1	1
+54	2	2
+116	1	1
+66	1	1
+182	1	0
+37	1	1
+134	14	14
+117	1	1
+45	1	1
+120	1	1
+47	1	1
+342	1	1
+46	1	1
+237	12	12
+107	8	8
+754	1	0
+880	1	1
+16	1	1
+741	1	1
+47	0	1
+19	2	2
+165	0	21
+26	1	1
+183	13	13
+72	1	1
+23	1	0
+268	14	14
+320	1	1
+55	1	1
+414	5	5
+172	0	1
+620	1	1
+18	1	1
+190	1	1
+20	0	8
+849	1	1
+29	1	1
+978	30213	30058
+159	1	1
+36	1	1
+107	1	1
+176	1	1
+154	0	5
+91	1	1
+54	1	1
+77	1	1
+239	1	1
+50	1	1
+128	1	1
+40	1	1
+62	1	0
+111	11	11
+734	1	1
+31	1	1
+215	1	1
+108	1	1
+259	1	1
+79	1	1
+80	1	1
+47	3	1
+40	1	1
+54	1	1
+46	1	1
+118	9	9
+98	1	0
+5	11	4
+23	0	7
+84	1	1
+84	2	2
+6	0	1
+6	1	0
+110	0	7
+537	1	1
+96	1	1
+441	1	1
+101	1	1
+242	14	14
+255	16	16
+142	1	0
+345	10	10
+54	1	1
+26	1	1
+108	1	1
+83	1	1
+128	1	1
+36	1	1
+231	1	1
+37	1	1
+534	1	1
+60	1	1
+804	0	3
+43	1	1
+148	1	1
+25	1	1
+69	10	10
+76	5	5
+37	1	1
+66	0	2
+192	1	1
+60	3	0
+19	1	1
+1149	1	1
+18	1	1
+77	1	1
+22	3	0
+42	1	1
+136	1	1
+78	2	0
+1712	8	9
+548	1	1
+50	1	1
+177	1	0
+410	1	1
+42	1	1
+422	10	10
+963	4	4
+329	1	9
+648	5	1
+117	1	1
+27	1	1
+574	1	0
+507	1	1
+39	1	1
+294	3	2
+549	1	1
+22	1	1
+74	0	1
+98	1	1
+65	3	3
+230	1	1
+18	1	0
+33	1	1
+51	1	1
+24	1	1
+811	1	1
+59	0	2
+8	1	1
+80	9	9
+437	14	14
+57	4	4
+588	15	15
+305	1	1
+17	1	1
+135	1	1
+50	1	1
+59	16	16
+129	1	1
+25	2	0
+12	1	1
+106	1	1
+31	1	1
+350	1	1
+47	1	1
+340	1	1
+65	1	1
+478	2	0
+714	8	7
+95	2	2
+52	2	1
+1129	1	1
+34	1	1
+1715	1	1
+87	1	1
+692	1	1
+47	0	1
+75	1	1
+2155	10	10
+1407	0	2
+202	1	1
+22	1	1
+186	1	1
+34	1	1
+264	1	0
+185	1	1
+24	1	0
+98	0	2
+258	8	14
+967	1	1
+37	3	3
+502	1	1
+22	1	1
+75	0	3
+163	1	1
+40	1	1
+638	0	3
+150	1	1
+11	0	1
+29	1	1
+125	1	1
+78	1	1
+115	8	0
+195	14	14
+1413	18	19
+1471	1	1
+30	1	1
+228	1	1
+28	0	2
+1142	1	1
+73	1	1
+104	73	73
+435	1	1
+37	1	3
+601	1	1
+43	1	1
+181	14	0
+37	1	0
+52	1	1
+125	4	4
+34	1	1
+208	1	1
+39	2	2
+418	1	1
+25	1	1
+81	1	1
+36	1	1
+99	6	7
+20	1	1
+73	1	1
+62	1	1
+103	1	1
+34	1	1
+772	0	1
+369	1	1
+29	0	2
+220	1	1
+89	1	1
+58	2	2
+103	1	1
+55	1	1
+19	1	1
+79	1	1
+29	0	1
+26	1	1
+252	1	1
+75	1	1
+467	1	1
+40	1	1
+389	13	13
+67	7	7
+1185	0	311
+64	6	6
+667	1	1
+38	1	1
+79	1	0
+517	1	1
+66	1	1
+450	3	0
+1133	12	12
+543	2	0
+960	14	14
+272	1	1
+41	1	1
+196	1	0
+1424	18	19
+271	1	1
+65	1	1
+345	1	1
+23	3	0
+116	3	3
+86	1	1
+39	1	1
+129	1	1
+26	1	1
+779	1	1
+32	1	1
+247	1	1
+48	1	1
+379	1	1
+18	1	1
+379	1	0
+226	1	1
+61	1	1
+861	0	1
+51	9	9
+397	1	1
+12	4	0
+46	1	1
+602	1	1
+35	1	1
+422	1	1
+49	1	1
+789	1	1
+37	1	1
+859	8	8
+378	0	4
+703	0	4
+2277	3	0
+1334	1	1
+10	0	1
+38	2	0
+61	1	1
+140	15	15
+1047	1	1
+38	1	1
+87	1	1
+24	5	4
+1291	1	1
+49	1	1
+307	14	14
+100	0	1
+75	1	1
+78	1	1
+243	1	0
+33	1	1
+116	19	19
+65	0	1
+238	0	1
+179	2	1
+67	1	1
+60	1	1
+32	1	1
+677	4	6
+83	318	0
+334	1	0
+1018	5	5
+559	0	2
+111	1	1
+30	1	1
+66	1	1
+38	1	1
+218	8	8
+754	1	1
+65	1	1
+182	1	1
+21	1	1
+285	1	1
+75	1	1
+147	6	0
+65	1	1
+42	1	1
+380	1	1
+84	6	0
+88	1	1
+25	1	1
+365	6	5
+108	1	1
+40	1	0
+50	1	1
+111	1	0
+21	0	1066
+119	0	1
+2641	1	1
+22	1	1
+2147	1	1
+29	1	1
+2252	1	1
+19	1	1
+1650	6	6
+1982	0	2
+2213	23	1
+2593	0	177
+338	1	1
+37	2	2
+395	10	0
+67	1	1
+131	1	1
+31	1	1
+386	1	1
+42	1	1
+372	1	1
+48	1	1
+3858	0	1
+351	1	0
+2536	16	16
+253	1	1
+16	1	1
+308	3	3
+52	1	1
+1308	0	3
+330	9	9
+600	2	0
+261	8	8
+9909	0	2
+2337	2	0
+3769	1	0
+1505	0	1
+4327	1	1
+15	1	1
+241	0	1
+230	1	0
+5263	1	0
+1386	0	41
+119	1	0
+4323	0	1
+54	1	1
+116	0	4
+1354	1	0
+1161	20	21
+1946	0	1
+584	0	2
+3100	1	0
+3491	1	0
+461	1	0
+762	0	8
+14669	1	0
+7644	6	0
+10539	4	0
+24841	1	0
+4856	3	0
+6082	2	0
+955	0	2
+1622	20422	20421
+76	0	3
+1724	2	0
+1173	1	0
+1783	1	1
+41	1	1
+4618	1	0
+232	0	2
+4975	2	0
+1487	15	14
+1184	2	0
+342	16	15
+328	0	3
+570	1	0
+995	1	0
+192	4	4
+1434	4	0
+62	1	1
+3531	2	3
+2846	1	1
+17	1	1
+704	0	1
+4801	1	0
+1417	0	4
+50	3	0
+165	0	1
+7575	9	0
+7359	11	0
+14219	0	2
+50	24	10
+38	2	0
+42	0	24
+24	0	18
+8297	1	1
+28	1	1
+264	1	1
+65	0	1
+15	1	1
+2371	19	19
+57	1	1
+21	1	1
+231	1	1
+94	1	1
+105	1	1
+208	5	5
+124	1	1
+112	3	3
+207	40	40
+244	1	1
+60	1	1
+98	1	1
+50	1	1
+256	5	5
+23	1	1
+157	1	1
+33	1	1
+143	1	1
+59	1	1
+51	1	1
+45	1	0
+73	1	1
+81	1	1
+427	1	1
+115	1	1
+28630	0	8
+18331	0	26
+1830	22668	22667
+16645	4	0
+4458	0	2
+2318	1	1
+24	1	1
+2089	0	1
+68717	1	0
+8718	4	0
+12333	12	0
+835	0	1
+391	58	61
+12157	1	0
+5577	1	0
+23151	3	0
+1588	1	0
+2605	1	1
+23	1	1
+11252	8	0
+298	6	7
+946	2	0
+232	0	1
+501	1	0
+4748	0	4
+770	0	7
+914	0	1
+295	1	0
+214	2	0
+121	0	1
+784	0	1
+2512	0	1
+1205	21	21
+3250	1	0
+926	0	1
+189	2	0
+3543	2	0
+893	1	1
+46	1	1
+1296	0	1
+153	0	2
+335	5	0
+187	1	1
+86	1	1
+207	3	0
+322	0	1
+658	1	0
+1516	3	0
+1025	0	13
+1518	0	1
+591	10	10
+3384	0	2
+182	12	0
+328	1	0
+301	0	1
+994	1	1
+18	0	6
+1743	0	1
+2350	22	23
+1548	0	7
+1976	1	0
+199	0	1
+3290	1	1
+28	1	1
+2602	12	12
+873	0	3
+3080	12	8
+322	1	0
+490	1	0
+4084	1	0
+2421
+
+chain 584308 chr6_dbb_hap3 4610396 + 3832023 3871403 chr5 180857866 - 25428915 25436336 9077
+107	1	1
+69	1	1
+306	1	1
+71	1	1
+121	1	1
+88	1	1
+96	12	1
+257	1	1
+92	32139	188
+68	1	0
+39	1	1
+136	4	4
+14	1	1
+82	1	1
+80	1	1
+217	1	1
+28	0	4
+34	1	1
+114	1	1
+29	2	2
+1703	4	4
+315	13	13
+184	1	1
+31	1	1
+789	1	1
+47	5	5
+415	8	8
+85	13	13
+985	1	1
+142	1	1
+205	1	1
+35	1	1
+174
+
+chain 148040 chr6_dbb_hap3 4610396 + 3896754 3898327 chr9 140273252 + 114315581 114318014 872071
+803	1	1
+32	0	453
+67	2	409
+668
+
+chain 80965 chr6_dbb_hap3 4610396 + 2305865 2306722 chr6 170899992 - 139781917 139782778 1559016
+341	0	4
+516
+
+chain 59035 chr6_dbb_hap3 4610396 + 3814253 3815703 chr1 247249719 + 235898881 235900160 2133080
+173	33	33
+70	99	102
+68	14	14
+66	427	253
+104	96	96
+78	80	80
+142
+
+chain 56303 chr6_dbb_hap3 4610396 + 3895098 3898571 chr8 146274826 - 53671532 53672205 16841
+99	13	14
+38	12	0
+6	3	15
+341	2802	1
+101	1	1
+57
+
+chain 51533 chr6_dbb_hap3 4610396 + 2519888 2521822 chr1 247249719 + 7396445 7398379 2460894
+102	170	170
+98	761	760
+135	79	79
+58	214	214
+173	73	74
+71
+
+chain 35778 chr6_dbb_hap3 4610396 + 1195644 1199573 chr6 170899992 + 29950082 29959351 3739128
+53	1042	1027
+90	511	191
+90	460	6138
+153	336	337
+77	683	679
+78	267	267
+89
+
+chain 29930 chr6_dbb_hap3 4610396 + 1291857 1292168 chr10 135374737 + 129836562 129836873 4701711
+311
+
+chain 29904 chr6_dbb_hap3 4610396 + 1119153 1119465 chr7 158821424 + 38479558 38479870 4710596
+312
+
+chain 29422 chr6_dbb_hap3 4610396 + 2048496 2048802 chr6 170899992 + 69396184 69396490 4710630
+306
+
+chain 29265 chr6_dbb_hap3 4610396 + 2582091 2582592 chr2 242951149 + 112146990 112147493 4980566
+65	94	96
+54	27	27
+152	33	33
+76
+
+chain 28976 chr6_dbb_hap3 4610396 + 4055704 4056006 chr2 242951149 - 177193633 177193935 5141771
+302
+
+chain 28679 chr6_dbb_hap3 4610396 + 2275002 2275314 chr3 199501827 - 86469460 86469765 4692119
+171	7	0
+134
+
+chain 26875 chr6_dbb_hap3 4610396 + 2605062 2605840 chr6 170899992 + 31342625 31343398 6110200
+75	247	243
+74	12	16
+72	194	189
+104
+
+chain 23264 chr6_dbb_hap3 4610396 + 3891437 3892382 chr6 170899992 + 32821586 32822354 8135396
+218	677	500
+50
+
+chain 23054 chr6_dbb_hap3 4610396 + 3970815 3971054 chr3 199501827 - 39984613 39984852 8258949
+239
+
+chain 22312 chr6_dbb_hap3 4610396 + 1158170 1158946 chr7 158821424 - 51137320 51138262 8787332
+90	9	9
+79	101	101
+72	385	551
+40
+
+chain 21919 chr6_dbb_hap3 4610396 + 3896060 3896302 chrX 154913754 - 82335943 82336185 9052373
+242
+
+chain 19800 chr6_dbb_hap3 4610396 + 3895610 3895845 chr7 158821424 - 34919795 34920030 7485763
+5	1	1
+87	3	3
+71	1	1
+67
+
+chain 19015 chr6_dbb_hap3 4610396 + 3943955 3944187 chr11 134452384 + 111558067 111558299 11259777
+149	20	20
+63
+
+chain 18237 chr6_dbb_hap3 4610396 + 2595793 2596391 chr13 114142980 + 51183720 51184326 11909510
+52	119	119
+108	253	261
+66
+
+chain 17641 chr6_dbb_hap3 4610396 + 3836782 3837025 chrX 154913754 + 35042287 35042530 12436913
+99	43	43
+101
+
+chain 17270 chr6_dbb_hap3 4610396 + 3918499 3918707 chr10 135374737 - 70196080 70196288 12781659
+86	2	2
+48	5	5
+67
+
+chain 16865 chr6_dbb_hap3 4610396 + 3983463 3983966 chrX 154913754 + 8861421 8861925 13172813
+68	216	217
+63	77	77
+79
+
+chain 16634 chr6_dbb_hap3 4610396 + 3895901 3896503 chr2 242951149 + 35312811 35313413 7601022
+134	363	363
+105
+
+chain 13803 chr6_dbb_hap3 4610396 + 3796429 3796972 chr2 242951149 - 211383777 211384322 16433564
+114	376	378
+53
+
+chain 13479 chr6_dbb_hap3 4610396 + 1132829 1133547 chr6 170899992 + 29984509 29985227 16848878
+104	552	552
+62
+
+chain 13400 chr6_dbb_hap3 4610396 + 3837061 3837652 chr1 247249719 + 76199329 76199914 13528533
+72	466	460
+53
+
+chain 13024 chr6_dbb_hap3 4610396 + 983805 983941 chr11 134452384 - 45905925 45906061 17454496
+136
+
+chain 12671 chr6_dbb_hap3 4610396 + 3940526 3940660 chrX 154913754 - 65797896 65798030 17982412
+134
+
+chain 12198 chr6_dbb_hap3 4610396 + 3795847 3796096 chr7 158821424 + 40936078 40936329 18688113
+94	105	107
+50
+
+chain 11398 chr6_dbb_hap3 4610396 + 2592168 2592321 chr6 170899992 - 161606914 161607067 20013435
+64	22	22
+67
+
+chain 11324 chr6_dbb_hap3 4610396 + 3938144 3938291 chr6 170899992 - 138135992 138136139 20148164
+68	15	15
+64
+
+chain 10873 chr6_dbb_hap3 4610396 + 1193470 1193591 chr19 63811651 + 15986631 15986752 20965589
+121
+
+chain 10867 chr6_dbb_hap3 4610396 + 2527311 2527468 chr6 170899992 - 132294381 132294544 20980273
+55	29	35
+73
+
+chain 10755 chr6_dbb_hap3 4610396 + 2751799 2751912 chrX 154913754 - 134479310 134479423 11323978
+113
+
+chain 10634 chr6_dbb_hap3 4610396 + 3919991 3920105 chr5 180857866 + 34801263 34801377 21438493
+114
+
+chain 10332 chr6_dbb_hap3 4610396 + 3984189 3984438 chr18 76117153 - 27021129 27021380 22068171
+57	124	126
+68
+
+chain 10015 chr6_dbb_hap3 4610396 + 3921148 3921283 chr14 106368585 + 84133812 84133947 22772205
+59	19	19
+57
+
+chain 9987 chr6_dbb_hap3 4610396 + 3796659 3796919 chr12 132349534 + 56701652 56701911 19406222
+70	165	164
+25
+
+chain 9750 chr6_dbb_hap3 4610396 + 2598300 2598402 chr6 170899992 + 31328563 31328665 23393690
+102
+
+chain 9528 chr6_dbb_hap3 4610396 + 1160418 1160855 chr6 170899992 + 29878108 29878543 23937745
+59	318	316
+60
+
+chain 9496 chr6_dbb_hap3 4610396 + 3698327 3698427 chr11 134452384 - 102104468 102104568 24009659
+100
+
+chain 9090 chr6_dbb_hap3 4610396 + 2526557 2526667 chr3 199501827 - 94209663 94209773 24799755
+53	4	4
+53
+
+chain 9042 chr6_dbb_hap3 4610396 + 3982887 3983463 chrX 154913754 - 39105241 39105605 22912000
+59	507	295
+10
+
+chain 8509 chr6_dbb_hap3 4610396 + 3919900 3919991 chr9 140273252 - 54900636 54900727 21580039
+91
+
+chain 7414 chr6_dbb_hap3 4610396 + 3922665 3922744 chr6 170899992 - 151548315 151548394 27385131
+79
+
+chain 7276 chr6_dbb_hap3 4610396 + 3860392 3860468 chr6 170899992 - 67344251 67344327 27653182
+76
+
+chain 7202 chr6_dbb_hap3 4610396 + 3830969 3832020 chr3 199501827 + 106790123 106791174 346924
+69	5	5
+109	2	2
+142	1	1
+77	1	1
+51	1	0
+194	0	1
+399
+
+chain 6804 chr6_dbb_hap3 4610396 + 3735469 3735541 chr6 170899992 + 32582474 32582546 28581342
+72
+
+chain 6776 chr6_dbb_hap3 4610396 + 3900841 3908708 chr6 170899992 + 32827127 32834907 28655646
+50	4318	3617
+61	2532	2695
+93	658	1109
+155
+
+chain 6739 chr6_dbb_hap3 4610396 + 3920547 3920617 chr6 170899992 + 53525586 53525656 28727012
+70
+
+chain 6718 chr6_dbb_hap3 4610396 + 3983858 3984010 chr15 100338915 - 66378648 66378800 16209113
+29	79	79
+44
+
+chain 6712 chr6_dbb_hap3 4610396 + 2536742 2536812 chr6 170899992 - 140565854 140565924 28801697
+70
+
+chain 6657 chr6_dbb_hap3 4610396 + 3814584 3815561 chr4 191273063 - 103136563 103137365 2286737
+44	251	76
+51	551	551
+20	37	37
+23
+
+chain 6566 chr6_dbb_hap3 4610396 + 1190938 1191006 chr6 170899992 + 30567038 30567106 29137401
+68
+
+chain 6566 chr6_dbb_hap3 4610396 + 3835601 3835669 chr6 170899992 + 32665461 32665529 29137402
+68
+
+chain 6459 chr6_dbb_hap3 4610396 + 3795625 3795694 chr11 134452384 + 89638894 89638963 29378141
+69
+
+chain 6457 chr6_dbb_hap3 4610396 + 1205138 1205205 chr6 170899992 + 30336816 30336883 29393793
+67
+
+chain 6404 chr6_dbb_hap3 4610396 + 3984475 3984543 chr7 158821424 + 141217888 141217956 29535627
+68
+
+chain 6112 chr6_dbb_hap3 4610396 + 3700406 3700470 chr18 76117153 - 19156586 19156650 30278938
+64
+
+chain 6077 chr6_dbb_hap3 4610396 + 3828852 3828917 chr6 170899992 + 32661358 32661423 30333820
+65
+
+chain 6003 chr6_dbb_hap3 4610396 + 2599299 2599362 chr6 170899992 + 31329552 31329615 30561641
+63
+
+chain 5676 chr6_dbb_hap3 4610396 + 2522554 2523018 chr1 247249719 + 71360098 71360557 7933597
+8	394	389
+62
+
+chain 5420 chr6_dbb_hap3 4610396 + 1191387 1191443 chr6 170899992 + 29965652 29965708 32189291
+56
+
+chain 5384 chr6_dbb_hap3 4610396 + 3920366 3920422 chr5 180857866 + 130110350 130110406 32314816
+56
+
+chain 5365 chr6_dbb_hap3 4610396 + 1189212 1189267 chr6 170899992 + 30335396 30335451 32370613
+55
+
+chain 5349 chr6_dbb_hap3 4610396 + 1146055 1146112 chr1 247249719 + 172045890 172045947 32394662
+57
+
+chain 5348 chr6_dbb_hap3 4610396 + 3704305 3704361 chr13 114142980 - 61076835 61076891 32406029
+56
+
+chain 5312 chr6_dbb_hap3 4610396 + 3955463 3955519 chr2 242951149 - 134958526 134958582 32494768
+56
+
+chain 5202 chr6_dbb_hap3 4610396 + 3920808 3920862 chr12 132349534 + 102926992 102927046 32856661
+54
+
+chain 5194 chr6_dbb_hap3 4610396 + 2522678 2522733 chr2 242951149 + 136412357 136412412 32870828
+55
+
+chain 5157 chr6_dbb_hap3 4610396 + 3919474 3919528 chr18 76117153 - 75578306 75578360 33003263
+54
+
+chain 5129 chr6_dbb_hap3 4610396 + 3699000 3699053 chr5 180857866 + 132341386 132341439 33069683
+53
+
+chain 5112 chr6_dbb_hap3 4610396 + 3702291 3702345 chr21 46944323 - 8455162 8455216 33113520
+54
+
+chain 5085 chr6_dbb_hap3 4610396 + 3943091 3943145 chrX 154913754 - 38541067 38541121 33235366
+54
+
+chain 5066 chr6_dbb_hap3 4610396 + 1193375 1193428 chr21 46944323 - 1867343 1867396 33290795
+53
+
+chain 5058 chr6_dbb_hap3 4610396 + 3934514 3934568 chr11 134452384 + 35678810 35678864 33301897
+54
+
+chain 4994 chr6_dbb_hap3 4610396 + 3795260 3795313 chr12 132349534 + 29061661 29061714 33541955
+53
+
+chain 4994 chr6_dbb_hap3 4610396 + 3796133 3796186 chr4 191273063 + 58121526 58121579 33542099
+53
+
+chain 4976 chr6_dbb_hap3 4610396 + 3794848 3794901 chrX 154913754 - 55960756 55960809 33594824
+53
+
+chain 4966 chr6_dbb_hap3 4610396 + 3797697 3797749 chr2 242951149 - 82237285 82237337 33630342
+52
+
+chain 4930 chr6_dbb_hap3 4610396 + 3702504 3702556 chr9 140273252 + 93086155 93086207 33718599
+52
+
+chain 4923 chr6_dbb_hap3 4610396 + 1158348 1158410 chr9 140273252 - 102391777 102391839 11227004
+62
+
+chain 4922 chr6_dbb_hap3 4610396 + 3834682 3834735 chr6 170899992 + 32548301 32548354 33750858
+53
+
+chain 4921 chr6_dbb_hap3 4610396 + 3919158 3919210 chrX 154913754 - 85139489 85139541 33755277
+52
+
+chain 4914 chr6_dbb_hap3 4610396 + 2519587 2519639 chrX 154913754 + 7895883 7895935 17698100
+52
+
+chain 4895 chr6_dbb_hap3 4610396 + 3971054 3971105 chr9 140273252 + 7362065 7362116 8474619
+51
+
+chain 4839 chr6_dbb_hap3 4610396 + 2523181 2523232 chr1 247249719 - 83322643 83322694 34042185
+51
+
+chain 4829 chr6_dbb_hap3 4610396 + 1205662 1205712 chr6 170899992 + 30567298 30567348 34088050
+50
+
+chain 4821 chr6_dbb_hap3 4610396 + 3921606 3921657 chr19 63811651 + 44797095 44797146 34119671
+51
+
+chain 4821 chr6_dbb_hap3 4610396 + 3795725 3795776 chr6 170899992 - 89445109 89445160 34121660
+51
+
+chain 4812 chr6_dbb_hap3 4610396 + 3797020 3797071 chr9 140273252 - 60383600 60383651 34150921
+51
+
+chain 4802 chr6_dbb_hap3 4610396 + 3704401 3704451 chr4 191273063 - 155219143 155219193 34221295
+50
+
+chain 4766 chr6_dbb_hap3 4610396 + 3700117 3700167 chr9 140273252 + 86874856 86874906 34319112
+50
+
+chain 4694 chr6_dbb_hap3 4610396 + 3910535 3910585 chr6 170899992 + 32836714 32836764 34581613
+50
+
+chain 4630 chr6_dbb_hap3 4610396 + 2519306 2519455 chrX 154913754 - 130647735 130647884 4467919
+8	13	13
+128
+
+chain 4435 chr6_dbb_hap3 4610396 + 2521889 2521945 chr1 247249719 + 68329905 68329961 24341076
+56
+
+chain 4406 chr6_dbb_hap3 4610396 + 3836685 3836748 chr12 132349534 + 83019068 83019131 17889506
+63
+
+chain 4295 chr6_dbb_hap3 4610396 + 2518454 2518508 chr13 114142980 + 40947099 40947153 23509760
+54
+
+chain 4259 chr6_dbb_hap3 4610396 + 2520658 2522182 chr1 247249719 + 175639486 175641011 2690506
+58	695	694
+59	250	251
+31	373	374
+58
+
+chain 4202 chr6_dbb_hap3 4610396 + 2519814 2519869 chr3 199501827 + 157792092 157792147 19123443
+55
+
+chain 4148 chr6_dbb_hap3 4610396 + 2596230 2596277 chr7 158821424 - 75232531 75232578 15855534
+47
+
+chain 3884 chr6_dbb_hap3 4610396 + 2596391 2596432 chr8 146274826 + 74136425 74136466 15736555
+41
+
+chain 3783 chr6_dbb_hap3 4610396 + 2595924 2595964 chr2 242951149 - 166645324 166645364 18114608
+40
+
+chain 3633 chr6_dbb_hap3 4610396 + 2595546 2596150 chr14 106368585 - 51104394 51104979 12640292
+71	478	459
+55
+
+chain 3600 chr6_dbb_hap3 4610396 + 3984599 3984637 chr2 242951149 + 129304609 129304647 25766382
+38
+
+chain 3466 chr6_dbb_hap3 4610396 + 3944209 3944269 chr5 180857866 - 165236686 165236746 13055377
+60
+
+chain 3427 chr6_dbb_hap3 4610396 + 2595867 2595923 chrX 154913754 - 74451128 74451184 24425971
+56
+
+chain 3366 chr6_dbb_hap3 4610396 + 3697430 3697469 chr7 158821424 - 31427441 31427480 35195573
+39
+
+chain 3356 chr6_dbb_hap3 4610396 + 2596277 2596325 chr6 170899992 + 67193869 67193917 14667051
+48
+
+chain 3333 chr6_dbb_hap3 4610396 + 3796616 3796658 chr6 170899992 + 112361298 112361340 25801948
+42
+
+chain 3275 chr6_dbb_hap3 4610396 + 1138782 1138817 chr6 170899992 + 29990315 29990350 35226052
+35
+
+chain 3219 chr6_dbb_hap3 4610396 + 2595512 2595546 chr15 100338915 + 54012038 54012072 22943633
+34
+
+chain 3113 chr6_dbb_hap3 4610396 + 2519060 2522554 chr12 132349534 + 103307685 103311177 2899166
+99	961	960
+40	1029	1028
+44	1259	1259
+62
+
+chain 2845 chr6_dbb_hap3 4610396 + 2519030 2519060 chr3 199501827 - 158108130 158108160 26771667
+30
+
+chain 2771 chr6_dbb_hap3 4610396 + 2186148 2186180 chr16 88827254 + 61371572 61371604 11881974
+32
+
+chain 2656 chr6_dbb_hap3 4610396 + 3920105 3920152 chr1 247249719 + 97086811 97086858 21929674
+47
+
+chain 2634 chr6_dbb_hap3 4610396 + 3702345 3702373 chr4 191273063 - 9754971 9754999 34558482
+28
+
+chain 2599 chr6_dbb_hap3 4610396 + 1158410 1158448 chr7 158821424 - 126060947 126060985 11258553
+38
+
+chain 2560 chr6_dbb_hap3 4610396 + 3796543 3796570 chr9 140273252 + 82550760 82550787 23127746
+27
+
+chain 2433 chr6_dbb_hap3 4610396 + 3814163 3814213 chr5 180857866 - 58683848 58683898 14264874
+50
+
+chain 2422 chr6_dbb_hap3 4610396 + 3815331 3815377 chr6 170899992 + 32052376 32052422 9201222
+46
+
+chain 2386 chr6_dbb_hap3 4610396 + 3944336 3944393 chr4 191273063 + 105171966 105172023 11828581
+57
+
+chain 2350 chr6_dbb_hap3 4610396 + 1144323 1144351 chr9 140273252 + 98495373 98495401 22648902
+28
+
+chain 2334 chr6_dbb_hap3 4610396 + 1197501 1197553 chr1 247249719 + 48751712 48751764 24363112
+52
+
+chain 2326 chr6_dbb_hap3 4610396 + 3944285 3944315 chr5 180857866 - 104226614 104226644 17910212
+30
+
+chain 2262 chr6_dbb_hap3 4610396 + 1158146 1158170 chr19 63811651 - 5696072 5696096 21221760
+24
+
+chain 2258 chr6_dbb_hap3 4610396 + 2582592 2582621 chr10 135374737 - 49445077 49445106 7325456
+29
+
+chain 2252 chr6_dbb_hap3 4610396 + 3944437 3944463 chr1 247249719 - 9396437 9396463 17746619
+26
+
+chain 2238 chr6_dbb_hap3 4610396 + 3984543 3984572 chr8 146274826 + 40415013 40415042 30916283
+1	3	0
+5	0	3
+20
+
+chain 2198 chr6_dbb_hap3 4610396 + 3591295 3591318 chrX 154913754 - 138619630 138619653 32682302
+23
+
+chain 2171 chr6_dbb_hap3 4610396 + 3944636 3944659 chr5 180857866 - 116975655 116975678 23231315
+23
+
+chain 2164 chr6_dbb_hap3 4610396 + 2581904 2581960 chr15 100338915 + 41094361 41094417 6236685
+56
+
+chain 2136 chr6_dbb_hap3 4610396 + 2582305 2582331 chrX 154913754 + 74544454 74544480 5553867
+24	1	1
+1
+
+chain 2131 chr6_dbb_hap3 4610396 + 3895846 3896559 chr7 158821424 + 107074762 107075475 8294701
+30	628	628
+55
+
+chain 2073 chr6_dbb_hap3 4610396 + 1158564 1158618 chr1 247249719 + 222604152 222604206 12884992
+54
+
+chain 2063 chr6_dbb_hap3 4610396 + 2527468 2527490 chr10 135374737 + 5170837 5170859 26024714
+22
+
+chain 2035 chr6_dbb_hap3 4610396 + 3944660 3944732 chr8 146274826 + 40414891 40414930 35524999
+20	2	0
+3	8	0
+5	23	0
+11
+
+chain 1939 chr6_dbb_hap3 4610396 + 1197585 1197647 chr4_random 842648 + 579429 579491 24056746
+62
+
+chain 1911 chr6_dbb_hap3 4610396 + 3796202 3796275 chr20 62435964 - 40308436 40308509 20356789
+73
+
+chain 1856 chr6_dbb_hap3 4610396 + 1158521 1158554 chr4 191273063 + 153905795 153905828 9266240
+33
+
+chain 1843 chr6_dbb_hap3 4610396 + 2520547 2520624 chr3 199501827 - 153335243 153335320 2775919
+77
+
+chain 1791 chr6_dbb_hap3 4610396 + 3814944 3814997 chr2 242951149 + 15669060 15669113 2773805
+53
+
+chain 1791 chr6_dbb_hap3 4610396 + 3896327 3896371 chr3 199501827 - 21590873 21590917 16297046
+44
+
+chain 1748 chr6_dbb_hap3 4610396 + 3896647 3898412 chr12 132349534 + 37486950 37487098 8651766
+20	2	0
+53	1616	1
+74
+
+chain 1729 chr6_dbb_hap3 4610396 + 2592021 2592074 chr14 106368585 - 49465840 49465893 23309002
+53
+
+chain 1667 chr6_dbb_hap3 4610396 + 2519690 2519769 chr4 191273063 + 150810923 150811002 4477040
+79
+
+chain 1644 chr6_dbb_hap3 4610396 + 3795469 3795533 chr5 180857866 - 17624826 17624890 19426880
+64
+
+chain 1588 chr6_dbb_hap3 4610396 + 2519256 2520761 chr7 158821424 + 116147190 116148689 3019444
+50	1410	1404
+45
+
+chain 1514 chr6_dbb_hap3 4610396 + 1158618 1158676 chr13 114142980 - 5380936 5380994 10250152
+58
+
+chain 1507 chr6_dbb_hap3 4610396 + 2519507 2519587 chr4 191273063 + 139055274 139055354 16166689
+80
+
+chain 1497 chr6_dbb_hap3 4610396 + 2596436 2596504 chr13 114142980 - 63160902 63160970 14379683
+68
+
+chain 1378 chr6_dbb_hap3 4610396 + 2518320 2518446 chr9 140273252 + 106017756 106017882 9913209
+126
+
+chain 1359 chr6_dbb_hap3 4610396 + 1158766 1158832 chr11 134452384 + 118435255 118435321 13536573
+66
+
+chain 1326 chr6_dbb_hap3 4610396 + 2518769 2518884 chr2 242951149 - 193553846 193553961 4392729
+115
+
+chain 1279 chr6_dbb_hap3 4610396 + 3895876 3895901 chr5 180857866 - 141473608 141473633 7934834
+25
+
+chain 1261 chr6_dbb_hap3 4610396 + 2595748 2595793 chr7 158821424 - 113148258 113148303 12073479
+45
+
+chain 1252 chr6_dbb_hap3 4610396 + 3944555 3944605 chr10 135374737 + 81711914 81711964 14060366
+50
+
+chain 1247 chr6_dbb_hap3 4610396 + 3837297 3837358 chrY 57772954 + 10103368 10103429 19375318
+61
+
+chain 1238 chr6_dbb_hap3 4610396 + 1193115 1193174 chr8 146274826 - 84904941 84905000 22834115
+59
+
+chain 1229 chr6_dbb_hap3 4610396 + 3797090 3797164 chr7 158821424 - 63976160 63976234 19674520
+74
+
+chain 1211 chr6_dbb_hap3 4610396 + 2596569 2596648 chr11 134452384 + 125240934 125241013 21730841
+79
+
+chain 1198 chr6_dbb_hap3 4610396 + 3983120 3983171 chrX 154913754 - 112657474 112657525 22999394
+51
+
+chain 1198 chr6_dbb_hap3 4610396 + 2520259 2520315 chr1 247249719 - 41799264 41799320 23684518
+56
+
+chain 1160 chr6_dbb_hap3 4610396 + 2522055 2522083 chrX 154913754 + 56853117 56853145 21155197
+28
+
+chain 1156 chr6_dbb_hap3 4610396 + 3814529 3814567 chr1 247249719 - 95427068 95427106 3236426
+38
+
+chain 1115 chr6_dbb_hap3 4610396 + 2519770 2519814 chr17 78774742 - 18978582 18978626 19145840
+44
+
+chain 1092 chr6_dbb_hap3 4610396 + 3815720 3815773 chr6 170899992 + 33136473 33136526 4404150
+53
+
+chain 1080 chr6_dbb_hap3 4610396 + 3982965 3983026 chr4 191273063 + 91007246 91007307 23248893
+61
+
+chain 1070 chr6_dbb_hap3 4610396 + 3983531 3983571 chr13 114142980 + 78421238 78421278 18216872
+40
+
+chain 1033 chr6_dbb_hap3 4610396 + 3797495 3797589 chr2 242951149 - 222175668 222175762 18472154
+94
+
+chain 1021 chr6_dbb_hap3 4610396 + 3944605 3944636 chr3 199501827 + 41781985 41782016 21488147
+31
+
+chain 961 chr6_dbb_hap3 4610396 + 2591988 2592021 chr6 170899992 + 31311499 31311532 23940424
+33
+
+chain 912 chr6_dbb_hap3 4610396 + 2522218 2522277 chr5 180857866 - 20904100 20904159 3597825
+59
+
+chain 912 chr6_dbb_hap3 4610396 + 2522435 2522465 chr7 158821424 + 107644178 107644208 21981895
+30
+
+chain 892 chr6_dbb_hap3 4610396 + 3815177 3815203 chr1 247249719 - 223546777 223546803 2552155
+26
+
+chain 886 chr6_dbb_hap3 4610396 + 2518921 2518972 chrX 154913754 - 65002049 65002100 8335918
+51
+
+chain 881 chr6_dbb_hap3 4610396 + 2521831 2521881 chr4 191273063 + 5547185 5547235 3823174
+50
+
+chain 876 chr6_dbb_hap3 4610396 + 2522095 2522124 chr1 247249719 - 197271642 197271671 12596899
+29
+
+chain 858 chr6_dbb_hap3 4610396 + 2522184 2522218 chr7 158821424 - 148280259 148280293 6691658
+34
+
+chain 850 chr6_dbb_hap3 4610396 + 3815307 3815331 chr11 134452384 + 75267105 75267129 2466745
+24
+
+chain 846 chr6_dbb_hap3 4610396 + 3896560 3896615 chr1 247249719 - 102242947 102243002 13724822
+55
+
+chain 818 chr6_dbb_hap3 4610396 + 3815047 3815103 chr9 140273252 - 13362556 13362612 11609524
+56
+
+chain 787 chr6_dbb_hap3 4610396 + 2522005 2522055 chr2 242951149 + 76860552 76860602 3963281
+50
+
+chain 742 chr6_dbb_hap3 4610396 + 2520888 2520940 chr10 135374737 + 51611354 51611406 20534291
+52
+
+chain 740 chr6_dbb_hap3 4610396 + 1159052 1159116 chr12 132349534 + 55464534 55464598 20832677
+64
+
+chain 734 chr6_dbb_hap3 4610396 + 2517749 2518673 chr8 146274826 - 112931559 112932176 13565224
+68	769	462
+87
+
+chain 717 chr6_dbb_hap3 4610396 + 3984125 3984177 chr16 88827254 - 38714794 38714846 22849175
+52
+
+chain 688 chr6_dbb_hap3 4610396 + 2519167 2519218 chr12 132349534 - 101137563 101137614 3748471
+51
+
+chain 684 chr6_dbb_hap3 4610396 + 2522743 2522826 chr1 247249719 + 68246247 68246330 16550290
+83
+
+chain 681 chr6_dbb_hap3 4610396 + 3982752 3982809 chr8 146274826 - 64029404 64029461 24731945
+57
+
+chain 668 chr6_dbb_hap3 4610396 + 3714611 3714639 chr13 114142980 + 25366313 25366341 2606938
+28
+
+chain 661 chr6_dbb_hap3 4610396 + 2523098 2523163 chr5 180857866 + 99923773 99923838 9614006
+65
+
+chain 654 chr6_dbb_hap3 4610396 + 1158946 1158972 chr4 191273063 - 137719796 137719822 10317120
+26
+
+chain 638 chr6_dbb_hap3 4610396 + 3795059 3795115 chr1 247249719 - 190736869 190736925 22996754
+56
+
+chain 603 chr6_dbb_hap3 4610396 + 3896371 3896398 chr6 170899992 + 38375889 38375916 7901672
+27
+
+chain 602 chr6_dbb_hap3 4610396 + 2519990 2520031 chr6 170899992 - 100068900 100068941 3263990
+41
+
+chain 571 chr6_dbb_hap3 4610396 + 2518673 2518747 chr3 199501827 + 50931043 50931117 15282719
+74
+
+chain 547 chr6_dbb_hap3 4610396 + 2522845 2522895 chr11 134452384 - 79794459 79794509 15991277
+50
+
+chain 544 chr6_dbb_hap3 4610396 + 2520356 2520407 chr13 114142980 + 104410064 104410115 4879952
+51
+
+chain 461 chr6_dbb_hap3 4610396 + 2522377 2522435 chr9 140273252 - 118104609 118104667 6129577
+58
+
+chain 447 chr6_dbb_hap3 4610396 + 2517845 2517905 chr8 146274826 - 66271750 66271810 23464585
+60
+
+chain 423 chr6_dbb_hap3 4610396 + 2520499 2520535 chr16 88827254 - 23736388 23736424 4641188
+36
+
+chain 407 chr6_dbb_hap3 4610396 + 3833249 3833277 chr11 134452384 + 92791982 92792010 9335
+28
+
+chain 395 chr6_dbb_hap3 4610396 + 3896615 3896647 chr10 135374737 - 43610926 43610958 15449290
+32
+
+chain 363 chr6_dbb_hap3 4610396 + 2522305 2522360 chr2 242951149 + 137419466 137419521 26505689
+55
+
+chain 350 chr6_dbb_hap3 4610396 + 2523417 2523489 chr15 100338915 + 97778900 97778972 9309023
+72
+
+chain 312 chr6_dbb_hap3 4610396 + 2520407 2520446 chr10 135374737 - 80033072 80033111 12533916
+39
+
+chain 290 chr6_dbb_hap3 4610396 + 2523894 2523946 chr1 247249719 - 204952078 204952130 18508597
+52
+
+chain 258 chr6_dbb_hap3 4610396 + 2518973 2519027 chr2 242951149 + 129418481 129418535 12872927
+54
+
+chain 235 chr6_dbb_hap3 4610396 + 3982484 3982540 chr21 46944323 + 15992125 15992181 26051708
+56
+
+chain 337820870 chr6_mann_hap4 4683263 + 0 4683263 chr6 170899992 + 28804582 33333955 39
+932	3	0
+804	0	1
+2406	2	0
+141275	1	0
+429	38391	38391
+17722	4	0
+12815	0	1
+28140	1	3
+12586	0	1
+9819	0	1
+69013	0	1
+22684	1	0
+14147	7	0
+1489	1	1
+72	1	1
+2260	0	2
+7033	0	4
+13929	13	14
+9228	0	1
+1324	0	3
+5437	5	0
+2061	1	0
+3982	6	6
+1725	0	1
+3153	1	0
+18	1	0
+18	1	0
+2026	1	0
+4175	10	10
+4746	9	9
+4767	7	7
+1169	1	1
+55	1	0
+8	1	1
+151	1	2
+5079	1	1
+28	1	1
+249	43	43
+1178	0	4
+685	8	0
+48	8	0
+1701	1	1
+43	5	5
+862	18	18
+58	1	1
+66	1	1
+420	1	1
+44	1	1
+680	4	4
+1675	1	1
+83	1	1
+3082	4	0
+5467	1	1
+27	0	1
+1099	16	0
+627	12	12
+1317	6	1
+129	1	1
+25	1	1
+1397	15	15
+810	1	1
+27	1	1
+1192	2	0
+7515	4	0
+979	0	4
+3405	0	2
+3501	1	1
+26	1	1
+787	0	1
+1416	3	1
+22815	4	4
+126	1	0
+38	1	1
+140	1	0
+999	0	17
+56	0	15
+15438	4	0
+6165	0	1
+1768	1	0
+7727	2	0
+1514	0	1
+3116	0	1
+3278	1	1
+21	1	1
+1738	0	1
+8576	19	0
+1877	15	15
+6128	1	0
+2049	1	0
+518	13	11
+1704	1	1
+117	1	1
+1448	10	0
+1521	0	4
+2878	9	9
+2265	1	0
+25400	9	9
+4420	1	1
+32	1	1
+2539	1	0
+18012	1	1
+42	1	1
+2651	0	3
+2544	0	318
+1507	1	0
+313	4	0
+2659	1	1
+25	1	1
+1461	4	1
+1402	0	1
+3961	0	3
+58	1	1
+112	1	1
+1419	1	1
+34	0	1
+2697	0	2
+40	1	1
+2168	0	1
+1019	0	2
+1099	0	4
+40	1	1
+1374	11	0
+31	1	1
+189	1	1
+26	1	1
+327	1	1
+38	1	1
+177	11	11
+303	1	1
+34	1	1
+5868	17	17
+2864	0	143
+4107	0	4
+752	0	2
+10360	0	1
+37	1	1
+11851	0	2
+5376	0	1
+19253	0	6
+7878	1	0
+21	0	6
+4451	1	0
+27910	1	0
+9946	0	1
+11233	1	1
+32	1	1
+366	1	1
+38	1	1
+1832	1	1
+20	1	1
+3659	22	16
+1218	1	0
+1638	6	6
+228	1	1
+45	1	1
+2048	0	2
+462	1	0
+20759	1	0
+3778	2	1
+1268	1	0
+1511	1	1
+42	2	0
+24	1	1
+4119	22	0
+1757	1	0
+1527	1	1
+29	1	1
+1886	1	0
+6666	0	4
+2358	1	1
+23	1	1
+1549	12	0
+36	12	0
+484	1	1
+31	1	1
+549	3	0
+5745	1	0
+19358	0	3
+12224	1	0
+34	1	1
+3228	11	16
+250	1	1
+17	1	1
+1482	0	1
+1280	1	0
+103	1	1
+29	1	1
+68	4	4
+1493	1	1
+49	1	1
+102	4	0
+287	1	1
+21	3	0
+273	1	1
+43	9	1
+667	0	8
+138	1	1
+20	1	1
+255	0	2
+67	1	1
+33	1	1
+62	1	0
+118	0	5
+313	0	3
+2354	0	28
+1203	0	3
+3975	1	1
+44	1	1
+4899	3	0
+2101	2	0
+363	1	1
+49	1	1
+1639	0	30
+248	46	46
+1068	4	1
+85	1	0
+357	3	4
+5288	0	9
+2728	1	5
+722	0	1
+502	0	1
+1025	0	1
+134	12	0
+4944	0	1
+319	1	0
+1314	5	6
+4858	0	1
+2923	1	3
+117	0	1
+1775	1	0
+2123	0	1
+2715	1	0
+4921	1	1
+17	1	1
+4273	1	0
+1233	0	8
+2134	0	1
+1042	0	1
+163	1	1
+45	1	1
+50	2	0
+64	1	1
+48	1	1
+379	0	3
+29	1	0
+30	1	1
+61	1	1
+22	1	1
+691	5	7
+310	1	1
+37	3	1
+225	1	1
+131	2	0
+36	1	1
+242	9	9
+697	33	33
+1202	1	1
+16	1	1
+528	1	1
+20	1	1
+509	0	5
+76	1	1
+21	1	1
+439	15	15
+2778	2	1
+1597	24	28
+59	12	12
+307	1	0
+516	1	0
+286	11	33
+339	5	0
+570	1	1
+37	1	1
+220	1	0
+72	1	1
+144	1	1
+48	1	1
+247	2	0
+174	9	10
+816	1	0
+940	1	1
+45	1	1
+91	3	3
+71	1	1
+291	14	14
+100	1	1
+23	1	1
+452	3	3
+85	1	1
+65	1	1
+77	1	1
+252	0	1
+129	15	15
+432	14	0
+85	1	1
+28	1	1
+189	2	1
+71	1	1
+52	8	0
+810	2	2
+63	1	1
+378	1	1
+26	1	1
+187	31	36
+966	1	1
+25	1	1
+72	1	1
+29	1	1
+125	1	1
+38	1	1
+433	2	0
+596	1	1
+48	1	1
+465	4	4
+64	1	1
+20	1	1
+525	5	5
+237	3	8
+99	31	31
+53	11	0
+364	4	3
+201	1	1
+42	1	1
+56	1	1
+115	1	0
+67	16	16
+244	1	1
+54	5	5
+929	1	1
+21	1	1
+126	0	3
+830	1	11
+59	1	1
+537	0	2
+24	1	1
+745	15	15
+810	1	0
+425	1	1
+89	1	1
+592	1	1
+49	1	1
+352	0	1
+142	1	1
+30	1	1
+95	1	1
+45	1	1
+227	1	1
+53	1	1
+130	1	1
+18	1	1
+138	1	1
+90	1	1
+129	1	1
+39	1	1
+50	1	1
+79	1	1
+117	1	1
+31	1	1
+155	154	0
+34	1	1
+50	5	5
+57	1	1
+152	1	1
+30	1	1
+177	5	5
+345	1	1
+39	1	1
+504	18	18
+596	12	12
+54	1	1
+158	1	1
+164	1	1
+34	1	1
+626	15	15
+866	0	10
+1051	0	2611
+680	0	1
+1537	0	18
+75	1	0
+145	60	0
+122	0	12
+23	1	1
+1927	13	13
+1702	2	0
+3694	1	1
+18	1	1
+958	43	47
+246	2	0
+146	1	1
+49	1	1
+410	1	0
+667	1	1
+38	1	1
+362	7	1
+159	3	0
+515	2	0
+1026	1	1
+29	1	1
+249	0	6
+129	1	1
+33	4	0
+9	0	6
+1236	1	1
+20	1	1
+138	10	9
+448	0	3
+660	1	1
+28	1	1
+83	1	1
+51	1	1
+2659	1	1
+38	1	1
+424	0	1
+70	1	1
+820	1	1
+26	1	1
+1472	1	1
+21	1	1
+491	5	5
+163	15	15
+2194	2	0
+533	6	0
+441	1	7
+1689	1	1
+26	3	4
+879	16	16
+75	10	10
+429	0	2
+58	1	1
+350	1	0
+769	1	1
+39	1	1
+573	0	4
+37	1	1
+144	8	8
+1036	2	0
+262	2	2
+38	0	1
+70	18	18
+84	11	13
+169	147	153
+1254	0	2
+332	1	1
+21	1	1
+193	8	24
+34	1	1
+79	1	1
+29	1	1
+536	1	0
+308	0	1
+850	0	32
+23	1	1
+651	1	1
+22	0	3
+136	1	1
+48	1	1
+330	9	9
+1108	1	1
+98	1	1
+582	0	1
+714	7	7
+89	1	0
+293	9	8
+125	1	1
+31	1	1
+192	6	6
+171	17	17
+681	1	1
+43	1	1
+514	1	1
+68	1	1
+537	1	1
+35	1	1
+159	6	6
+179	1	1
+37	1	1
+560	17	17
+198	0	7
+105	1	1
+40	1	1
+95	13	13
+247	1	1
+19	1	1
+2044	7	8
+2512	0	15
+2982	4	0
+342	41	41
+2752	1	2
+1698	13	13
+4264	0	4
+12512	105	53
+7	0	5
+29	5	129
+49	1	1
+7717	1	1
+40	1	1
+4564	1	1
+45	1	1
+2289	1	1
+41	1	1
+1994	0	1
+733	1	1
+37	1	1
+5170	1	1
+22	1	1
+718	0	3
+828	0	8
+2128	11	11
+5142	0	1
+4144	18	0
+8	1	1
+4824	12	12
+727	6	16
+1705	4	0
+3265	0	2
+2235	18	16
+2946	0	372
+2644	31	31
+3991	40	40
+559	1	1
+28	1	1
+129	0	4
+787	1	1
+34	1	1
+927	4	4
+123	0	4
+6	1	1
+2353	0	1
+331	1	1
+27	1	1
+633	1	1
+31	1	1
+1147	1	0
+1507	1	1
+44	1	1
+166	1	1
+41	3	1
+1022	34253	40039
+275	1	1
+38	1	1
+1307	1	1
+26	1	1
+1467	1	1
+27	1	1
+568	11	11
+693	1	1
+26	1	1
+297	11	11
+183	1	1
+40	1	1
+589	1	1
+26	1	1
+838	1	1
+44	0	1
+877	1	1
+39	1	1
+347	1	1
+36	1	1
+1288	10	10
+731	2	1
+75	3	3
+91	171	171
+553	1	1
+61	1	1
+70	1	1
+53	0	2
+315	1	1
+29	1	1
+581	1	1
+82	1	1
+605	9	9
+691	2	2
+72	1	1
+55	1	1
+45	1	1
+196	4	4
+123	0	1
+40	1	1
+183	23	23
+183	1	1
+67	1	1
+304	1	1
+108	1	1
+165	1	1
+72	1	1
+167	1	1
+59	0	1
+10	3	1
+21	82	2
+58	0	2
+69	1	1
+25	1	1
+57	2	1
+107	2	2
+93	1	1
+194	0	3
+120	7	4
+431	1	1
+78	1	1
+84	0	1
+74	1	1
+52	13	13
+158	5	7
+434	0	1
+295	16	16
+290	1	1
+26	1	1
+373	1	1
+46	1	1
+94	1	1
+81	1	1
+109	4	0
+61	2	2
+80	1	1
+47	1	1
+168	1	1
+31	1	1
+269	2	2
+42	1	1
+322	2	2
+36	1	1
+265	2	2
+14	1	1
+76	7762	9566
+315	55	55
+67	36167	30035
+308	1	1
+49	1	1
+219	0	1
+87	7	5
+223	10	8
+235	11	11
+772	0	2
+187	2	1
+1058	0	2
+349	0	1
+264	1	1
+43	1	1
+781	3	1
+55	0	2
+13	0	4
+1077	1	1
+48	1	1
+62	1	1
+27	1	1
+1270	1	1
+44	1	1
+2070	3	1
+27	1	7
+251	1	1
+40	1	1
+130	1	1
+41	4	4
+478	1	1
+30	1	1
+162	11	11
+209	10	0
+150	1	1
+36	0	2
+31	1	1
+55	1	1
+51	1	1
+221	8	13
+418	1	1
+26	1	1
+386	3	0
+549	1	1
+76	1	1
+67	1	1
+25	3	3
+777	1	1
+17	1	1
+970	3	8
+714	1	1
+25	1	1
+192	1	1
+236	1	1
+524	0	12
+51	10	9
+664	1	1
+29	1	1
+62	1	1
+50	2	0
+119	1	1
+10	0	2
+19	4	6
+117	1	1
+69	1	1
+731	1	0
+3768	9	1
+1328	0	1
+6188	1	1
+43	1	1
+7157	4	0
+2168	1	0
+10374	19	0
+742	2	3
+4846	0	1
+3203	1	0
+2662	1	1
+27	1	1
+3920	1	1
+47	1	1
+2081	1	0
+377	1	0
+172	0	1
+5189	0	1
+1968	7	0
+3198	1	0
+667	1	0
+3902	17	4
+310	0	5
+2762	0	10
+201	2	0
+345	1	0
+594	0	2
+1043	10	0
+1426	0	9
+17	1	1
+265	0	1
+6069	0	3
+2963	0	3
+168	0	3
+194	2	1
+4260	1	0
+19508	0	1
+1762	0	3
+4356	0	4
+401	1	0
+1148	1	1
+28	0	11
+847	0	1
+1133	0	1
+1143	1	1
+20	1	1
+1533	0	8
+128	0	4
+2963	0	1
+25	1	1
+5336	1	0
+322	6	6
+196	1	1
+20	1	1
+151	3	3
+87	1	1
+246	1	7
+368	1	1
+26	1	1
+1049	0	1
+1002	0	1
+7912	4	0
+3532	50004	0
+1445	0	1
+10485	1	1
+48	1	1
+724	1	1
+51	5	0
+39	1	1
+22385	0	1
+4385	0	7
+881	0	12
+11532	13	12
+409	0	1
+3492	0	2
+2158	0	25
+109	1	1
+3284	0	19
+2586	2	0
+757	1	1
+22	1	1
+860	29	24
+1584	1	0
+1598	1	2
+1653	3	25
+17	0	4
+16	2	0
+6	10	0
+40	1	0
+10	6	0
+6448	0	1
+2513	0	1
+576	16	16
+103	1	0
+198	1	3
+539	1	1
+47	1	1
+158	2	0
+996	0	1
+3736	1	3
+371	1	3
+1174	1	1
+56	1	1
+69	0	1
+518	6	0
+646	13	13
+469	1	0
+1072	1	4
+911	1	1
+16	1	1
+3603	1	0
+282	1	0
+597	0	6
+496	13	13
+183	1	1
+43	1	1
+1294	1	1
+40	1	1
+572	0	5
+463	0	4
+1886	1	0
+548	1	0
+1300	0	3
+1839	2	0
+189	1	1
+49	1	1
+1253	1	1
+43	1	0
+498	1	1
+45	4	0
+3538	0	1
+1582	31	31
+376	14	14
+867	3	4
+253	1	1
+34	1	1
+172	2	0
+1094	0	1
+281	1	1
+49	1	1
+397	1	1
+43	1	1
+1082	1	1
+26	1	1
+1030	1	1
+24	0	419
+125	2	0
+709	1	1
+36	1	1
+393	1	1
+21	1	1
+1773	16	17
+181	12	12
+98	1	4
+6	1	0
+53	1	1
+94	1	1
+49	1	1
+1495	10	0
+623	13	13
+163	1	1
+45	1	1
+2050	11	11
+2452	1	1
+42	1	0
+35	1	1
+751	1	0
+287	1	1
+60	1	1
+446	0	4
+2620	8	7
+1442	5	5
+153	1	0
+514	2	0
+3349	1	1
+23	0	1
+12	1	1
+296	8	9
+291	1	1
+21	1	0
+245	2	2
+24	1	1
+150	1	1
+46	1	1
+325	1	1
+38	1	1
+52	6	9
+154	1	1
+42	1	1
+942	1	1
+36	1	1
+5168	0	3
+2172	1	0
+1740	0	8
+4919	1	0
+1388	4	0
+310	0	9
+370	22	0
+503	0	3
+6750	8	0
+419	2	0
+945	0	4
+3485	5	1
+789	0	1
+1882	45	44
+1047	1	1
+60	1	1
+2432	0	15
+16	1	1
+5898	0	1
+2260	1	0
+2629	0	5
+55	1	1
+28	1	1
+1978	1	0
+374	0	5
+7713	1	0
+1229	1	0
+708	2	0
+84	5	0
+2071	1	1
+23	1	0
+174	5	0
+1776	0	9
+15	6	11
+4007	1	0
+2414	12	10
+2056	0	1
+955	4	0
+9566	1	0
+1267	2	0
+1646	2	2
+30	1	1
+4770	7	6
+150	14	14
+9365	0	2
+5358	0	1
+4837	1	0
+6701	4	0
+66771	0	2
+54634	0	2
+8292	0	4
+7941	0	8
+7495	1	0
+5591	4	0
+4127	1	0
+473	1	0
+6435	1	0
+53744	1	0
+6522	0	1
+48591	18	23
+4935	29	0
+40465	0	1
+12538	0	1
+24928	8701	8701
+6291	0	10
+15586	2	1
+56398	4	0
+5858	1	0
+5972	0	2
+2081	0	1
+12533	1	0
+25305	0	1
+2237	0	2
+18999	0	4
+13824	0	2
+11096	2	0
+10773	0	1
+804	1	0
+5431	31	34
+598	1	1
+22	1	1
+2240	24813	24813
+1765	0	4
+4845	0	3
+448	1	1
+22	1	1
+2215	1	1
+32	1	1
+2413	14	14
+142	1	0
+789	1	1
+45	1	1
+154	1	1
+25	1	1
+465	1	1
+45	6	4
+541	1	1
+42	1	1
+1339	5	6
+391	1	1
+20	0	1
+251	1	1
+22	1	1
+561	0	2
+78	3	0
+1718	1	1
+12	1	1
+1042	1	1
+38	0	1
+301	14	0
+222	10	10
+436	10	10
+1564	1	1
+17	1	1
+1752	5	0
+1561	135	0
+58	0	45
+212	90	0
+42	2	2
+43	1	1
+152	0	270
+54	180	0
+2130	12	12
+1630	1	1
+26	1	1
+189	0	14
+296	2	0
+809	2	0
+17	16	0
+665	0	40
+236	1	1
+44	1	1
+352	1	1
+25	1	1
+316	14442	14257
+51	2	0
+58	1	1
+107	1	1
+150	14	14
+522	1	1
+28	1	1
+945	4	4
+34	1	1
+472	0	2
+203	0	1
+281	1	1
+46	1	1
+1130	1	0
+232	17	17
+510	1	1
+33	1	1
+62	10	10
+1501	1	1
+20	1	1
+573	1	1
+29	1	1
+928	0	3
+304	1	1
+41	1	1
+160	1	1
+58	1	1
+656	1	1
+40	4	0
+108	6	6
+321	1	1
+14	0	16
+91	1	1
+184	1	1
+43	8	3
+180	1	1
+68	1	1
+144	1	1
+27	1	0
+17	1	1
+212	0	1
+212	1	1
+34	1	1
+115	1	1
+41	1	1
+407	10	10
+200	1	1
+44	2	0
+187	3	0
+146	1	1
+17	1	1
+122	4	4
+73	1	0
+56	1	1
+155	1	17
+80	15	15
+458	1	1
+16	3	3
+343	1	1
+111	1	1
+201	14	14
+157	12	12
+346	0	2
+382	4	0
+35	1	1
+937	0	1
+246	25	0
+52	0	1
+419	0	1
+165	1	0
+75	24	3
+297	1	1
+38	1	1
+271	1	1
+33	1	1
+4777	4	2
+43	3	0
+1254	0	1
+16	1	1
+1411	0	4
+424	1	1
+51	1	1
+113	1	1
+34	1	1
+344	9	9
+15845	1	0
+2814	1	5
+2389	0	4
+3883	0	1
+10926	0	4
+17866	4	10
+744	1	0
+564	2	0
+16701	3	0
+7721	11	0
+1411	1	1
+49	1	1
+146	1	1
+61	1	1
+116	1	1
+41	1	1
+137	1	1
+30	1	1
+158	9	9
+136	10	13
+973	6	6
+547	1	1
+41	1	1
+164	17	17
+137	1	1
+68	1	1
+846	4	4
+228	1	1
+34	1	1
+355	1	1
+113	1	1
+330	0	1
+222	1	1
+25	1	1
+267	1	1
+38	1	1
+716	2	0
+23	1	1
+1417	0	1
+152	1	1
+46	1	1
+237	1	1
+20	1	1
+211	5	5
+88	1	1
+33	1	1
+211	1	1
+65	1	1
+516	58	58
+491	7	7
+208	13	12
+558	2	2
+28	1	1
+125	4	4
+1853	12	0
+845	6	6
+2005	0	1
+148	1	1
+36	1	1
+993	1	0
+3580	10	10
+1203	1	0
+530	5	5
+216	1	1
+32	1	1
+312	1	1
+44	1	1
+1934	14	14
+1149	0	8
+835	1	1
+29	0	2
+2323	1	1
+18	1	1
+1273	27	27
+104	1	1
+21	1	1
+1520	1	1
+23	1	1
+147	1	1
+16	1	1
+429	8	16
+1419	23	23
+256	1	0
+39	1	2
+106	1	1
+21	1	1
+501	2	2
+40	1	1
+2249	1	1
+19	1	1
+86	1	1
+82	0	1
+180	14	1
+1272	17	17
+345	0	2
+1504	14	0
+1689	4	0
+3174	16	16
+607	4	34
+41	0	5
+669	1	1
+25	1	1
+1926	1	1
+39	4	3
+1037	1	1
+40	2	0
+890	6	0
+41	2	0
+466	1	1
+31	3	0
+321	0	1
+281	3	0
+450	1	1
+34	1	1
+498	1	1
+28	2	1
+280	0	1
+649	1	1
+47	1	1
+1002	4	0
+120	1	1
+533	7	7
+998	0	1
+75	1	1
+37	1	1
+473	1	0
+44	1	1
+64	19	19
+60	18	18
+2075	1	1
+51	1	1
+779	0	1
+1286	0	2
+271	1	1
+57	1	1
+129	4	0
+87	1	1
+160	1	1
+49	1	1
+147	18	14
+128	4	4
+34	1	1
+865	4	0
+160	1	1
+35	1	1
+1119	1	1
+13	0	3
+242	1	1
+23	1	1
+1705	0	4
+103	0	1
+1117	2	0
+67	1	1
+1825	0	1
+855	8	0
+1368	3	0
+320	1	1
+19	1	1
+100	1	1
+28	1	1
+97	1	1
+15	1	1
+442	1	1
+189	0	2
+5	1	1
+1520	1	1
+28	1	1
+367	4	0
+267	13	13
+175	1	0
+225	1	1
+45	1	1
+859	1	1
+80	2	0
+38	0	2
+318	8	7
+50	1	1
+29	1	1
+376	4	9
+548	1	1
+57	1	1
+665	4	0
+146	30562	30549
+225	2	2
+49	1	1
+129	1	1
+20	1	1
+757	9	9
+151	1	1
+49	1	1
+282	0	2
+128	0	1
+174	15	18
+175	1	1
+16	1	1
+332	1	1
+22	1	1
+554	0	1
+120	1	1
+31	1	1
+351	5	0
+80	1	0
+76	1	1
+39	1	1
+1447	1	0
+1072	1	1
+43	0	4
+43	1	1
+393	0	1
+1820	6	6
+457	1	1
+18	1	1
+87	1	1
+30	1	1
+861	1	1
+20	1	1
+1057	23	23
+416	0	16
+787	1	1
+17	1	2
+37	1	1
+1675	1	1
+27	1	1
+901	0	8
+47	1	1
+274	0	3
+75	0	1
+234	0	3
+45	1	1
+250	1	1
+18	1	1
+517	33	0
+117	1	1
+55	1	1
+537	1	1
+20	1	1
+671	1	1
+68	1	1
+89	1	1
+104	1	1
+172	0	1
+124	0	1
+522	0	1500
+466	5	5
+32	1	0
+171	1	1
+19	1	1
+67	1	1
+22	1	1
+654	1	1
+25	1	1
+68	1	1
+21	4	0
+1588	1	1
+66	1	1
+401	0	1
+186	1	1
+21	1	1
+168	0	1
+601	1	1
+29	1	1
+36	4	0
+37	1	1
+127	1	1
+29	1	1
+404	0	2
+710	1	1
+89	1	1
+161	16	16
+405	1	1
+39	3	3
+56	1	1
+192	0	4
+104	1	1
+89	1	1
+64	1	1
+102	1	1
+130	15	16
+158	8	0
+57	1	1
+731	1	1
+57	1	1
+321	1	1
+44	3	0
+52	19987	20030
+60	8	8
+133	1	1
+48	1	1
+287	1	1
+24	1	1
+1273	1	1
+24	1	1
+86	1	1
+76	1	0
+20	1	1
+112	1	1
+149	1	1
+284	1	1
+37	1	1
+559	10	10
+136	1	12
+106	12	12
+3153	1	1
+34	1	1
+453	1	1
+63	1	1
+645	0	2
+50	1	0
+712	1	1
+35	1	1
+158	1	1
+52	1	1
+123	1	1
+45	0	1
+32	1	1
+253	1	1
+48	1	1
+101	16	16
+64	1	1
+124	1	1
+1429	13	13
+196	0	1
+1629	1	1
+39	0	1
+30	1	1
+514	1	1
+32	0	3
+3600	1	13
+1047	1	1
+43	1	1
+55	14	14
+853	12	12
+2313	13	13
+537	6	0
+1430	1	1
+48	1	1
+400	1	1
+100	1	1
+148	19	19
+152	1	1
+25	1	1
+70	1	1
+102	1	1
+158	1	1
+56	2	2
+57	1	1
+10	5	10
+24	2	0
+71	1	1
+54	1	1
+73	1	1
+85	1	1
+105	1	1
+117	2	2
+29	1	1
+92	2	2
+42	0	1
+154	1	1
+10	1	0
+47	4	5
+35	1	1
+56	1	1
+64	3	3
+67	5	5
+72	1	1
+60	1	1
+45	1	1
+82	1	1
+95	2	2
+161	1	1
+301	1	1
+67	1	0
+430	1	1
+105	10	10
+38	0	4
+386	11	11
+101	3	2
+117	0	2
+77	1	1
+481	0	1
+68	1	1
+81	1	1
+467	1	1
+34	1	1
+359	1	1
+35	1	1
+2283	1	1
+26	1	1
+506	19	0
+51	0	1
+166	1	1
+65	1	0
+211	0	17
+410	3	0
+622	0	1
+143	1	1
+22	1	1
+150	2	2
+49	1	1
+312	1	1
+16	1	1
+715	1	1
+24	1	1
+896	1	1
+33	1	1
+308	22	28
+78	1	1
+144	1	1
+733	0	1
+212	1	1
+40	1	1
+1233	1	1
+48	1	1
+741	49699	50070
+885	1	1
+113	1	1
+141	2	0
+842	1	0
+1507	1	1
+40	1	1
+279	0	1
+724	1	1
+15	1	1
+252	1	1
+29	2	0
+229	1	1
+50	3	3
+221	7	7
+216	1	1
+36	5	5
+64	1	1
+111	1	1
+220	1	1
+89	1	1
+119	1	1
+113	2	0
+195	1	1
+46	1	1
+245	0	4
+70	1	1
+62	4	1
+43	1	1
+153	1	1
+93	1	1
+85	1	1
+68	5	0
+47	2	2
+291	1	0
+42	1	1
+341	13	13
+262	4	4
+67	1	1
+32	1	0
+28	1	1
+612	1	1
+123	1	1
+112	1	1
+19	1	4
+61	1	2
+136	1	1
+83	1	1
+78	1	1
+61	288	288
+119	1	1
+158	1	1
+146	1	1
+28	1	1
+372	1	1
+18	0	4
+44	1	1
+120	7	7
+73	1	4
+42	1	1
+52	1	1
+24	1	1
+143	1	1
+34	1	1
+376	1	1
+26	1	1
+243	1	1
+41	1	1
+53	1	1
+35	5	5
+101	1	1
+20	1	1
+114	1	1
+43	1	1
+184	4	8
+650	23	23
+192	1	1
+44	1	0
+103	1	1
+202	2	2
+33	1	1
+51	1	1
+26	1	1
+277	3	0
+19	1	1
+263	2	2
+49	1	1
+63	1	1
+200	1	1
+320	4	12
+10	2	0
+11	8	1
+26	1	1
+86	13	13
+15	1	1
+3255	1	1
+52	1	1
+159	1	1
+88	1	0
+118	1	1
+172	1	1
+26	1	1
+69	1	1
+95	1	1
+124	1	1
+30	1	1
+216	41	41
+51	5	5
+123	1	1
+53	1	1
+110	1	1
+307	1	1
+101	1	1
+53	15	15
+127	2	2
+65	1	1
+553	1	1
+45	1	1
+52	0	1
+99	4	4
+1538	1	1
+31	1	1
+930	7	3
+472	13	13
+606	1	1
+38	1	1
+230	10	0
+30	6	0
+35	0	22
+168	1	1
+55	1	1
+309	2	3
+58	1	1
+44	1	1
+333	1	1
+81	3	3
+77	1	1
+140	1	1
+136	1	1
+40	5	5
+160	1	1
+21	5	5
+253	1	1
+37	1	1
+104	3	0
+867	14	15
+178	1	1
+94	1	1
+254	0	1
+101	0	5
+17	1	1
+528	1	1
+42	1	1
+261	1	1
+19	3	3
+83	10	10
+114	1	1
+194	1	1
+19	1	1
+286	1	1
+38	1	1
+295	0	4
+35	10	0
+205	0	2
+29	1	1
+178	1	1
+31	1	1
+57	1	1
+76	1	1
+228	1	1
+28	1	1
+101	1	1
+109	0	1
+93	0	2
+46	1	1
+109	1	1
+33	1	1
+932	12	12
+1047	1	1
+26	1	1
+699	0	8
+35	1	1
+472	1	1
+43	1	1
+242	1	1
+28	1	1
+385	1	1
+91	1	1
+805	0	2
+4744	3	2
+1144	0	1
+1453	0	1
+934	1	1
+28	3	7
+155	0	1
+840	18	18
+346	1	1
+25	1	1
+1020	2	0
+260	1	1
+26	1	1
+357	1	1
+44	1	1
+639	1	1
+26	1	1
+3965	1	1
+40	1	1
+194	1	0
+279	1	1
+18	1	1
+277	0	2
+1883	0	1
+31	1	1
+1925	1	0
+2650	16	16
+2463	117	0
+67	8	17
+77	0	2
+55	17	17
+60	24	0
+126	0	64
+26	0	7
+19	0	7
+38	18	0
+40	40	0
+49	0	124
+32	15	8
+22	43	4
+36	1	614
+68	1	1
+7	0	2
+17	2	0
+7	0	2
+17	2	0
+20	0	2
+76	41	13
+71	60	21
+122	0	73
+72	28	0
+117	11	35
+24	13	0
+56	19	0
+3413	6	0
+9102	0	1
+87	0	2
+2219	0	1
+85	1	1
+31	0	4
+399	14	14
+408	0	1
+148	0	1
+807	1	1
+28	1	0
+452	4	0
+499	1	1
+25	1	1
+1037	1	0
+1066	1	1
+102	1	1
+1111	1	1
+47	1	1
+291	1	1
+49	1	1
+1195	1	1
+46	1	1
+370	1	1
+56	1	1
+142	1	1
+54	1	1
+538	0	1
+46	1	2890
+74	9	97
+1161	0	1
+1161	1	1
+23	1	1
+189	1	1
+43	1	1
+855	1	0
+353	8	0
+751	42950	42933
+383	0	4
+40	1	1
+3304	1	1
+46	1	1
+282	1	1
+39	1	1
+698	1	1
+20	1	1
+140	1	1
+26	1	1
+745	0	2
+2081	1	0
+817	4	4
+206	1	1
+44	1	1
+168	1	1
+20	1	1
+164	1	0
+21	1	1
+648	1	0
+912	6	0
+55	0	1
+1116	1	1
+21	1	1
+462	1	1
+43	1	1
+121	1	1
+48	0	3
+16	1	4
+1404	0	1
+450	4	0
+612	15	14
+304	1	1
+39	1	1
+564	1	1
+45	1	1
+303	2	0
+409	1	1
+18	1	0
+858	2	0
+2168	0	1
+54	22	22
+524	0	1
+523	0	12
+2424	18	14
+64	1	1
+31	1	1
+185	0	4
+657	10	10
+980	1	1
+20	1	1
+227	1	1
+37	1	1
+636	3	4
+3780	0	1
+4458	1	1
+23	1	1
+1114	1	3
+696	16	32
+861	18	18
+4781	0	4
+815	0	1
+9910	0	1
+10538	0	6
+25675	0	6
+10912	9	10
+824	0	1
+1450	11	0
+403	0	1
+154	1	1
+34	1	1
+146	1	0
+26	1	1
+2361	0	2
+775	8460	8460
+474	0	1
+1838	0	3
+2049	3	0
+14940	0	1
+398	17	17
+3797	0	4
+1305	10	0
+15047	1	0
+20201	1	0
+3812	0	1
+11605	0	1
+4121	2	0
+7755	1	0
+2661	3	1
+138	1	0
+2776	0	2
+4108	0	4
+8944	1	0
+10910	4	0
+1616	0	1
+1645	4	5
+36	0	2
+2223	0	16
+4729	10	0
+1921	0	1
+913	0	1
+2531	89346	89346
+3450	17	17
+3339	0	1
+3130	0	1
+2106	1	1
+42	1	1
+382	1	0
+616	178	0
+9555	52932	52932
+383	0	1
+2529	19	19
+10441	0	1
+24	1	1
+246	0	4
+1724	1	1
+37	1	1
+141	11	11
+103	1	128
+292	1	1
+20	1	1
+67	0	117
+30	1	1
+2771	0	3
+1487	0	3
+251	1	0
+1263	18	12
+888	1	1
+20	1	1
+2423	10	0
+1337	10	10
+6619	2	0
+982	113131	113131
+3241	16	0
+10939	12	0
+2143	0	1
+8355	0	3
+4114	0	1
+1404	0	1
+5850	1	0
+1691	38609	38609
+338	6	6
+2331	0	1
+2149	1	0
+10496	17	35
+3831	1	0
+8737	0	3
+16043	29	29
+1283	0	3
+8057	1	1
+63	1	1
+6053	5	0
+4539	43	43
+1259	2	0
+1628	5	5
+448	0	1
+374	0	1
+3431	1	0
+3049	32	0
+147	0	1
+1181	10	15
+206	3	4
+613	0	1
+1815	1	1
+18	1	1
+3726	0	3
+34	1	1
+361	17	17
+1252	0	3
+1642	1	0
+374	1	1
+19	1	1
+316	1	0
+13	2	0
+712	12	12
+204	1	1
+60	1	1
+843	1	3
+705	7	7
+72	1	1
+29	0	2
+332	0	1
+136	1	1
+1071	3	0
+548	1	1
+45	3	0
+121	1	1
+24	1	1
+262	16	16
+846	0	4
+412	0	2
+644	0	1
+26	1	1
+75	1	1
+32	1	1
+247	0	1
+174	1	2
+77	3	0
+113	0	1
+79	44	44
+186	0	14
+80	1	1
+813	0	9
+465	1	1
+60	1	1
+217	0	2
+400	0	3
+367	1	1
+37	1	1
+245	1	1
+25	1	1
+469	0	8
+857	17	18
+278	0	1
+1507	3	0
+1681	0	2
+429	4	0
+148	17	5
+278	4362	4362
+3670	16	16
+108	1	2
+197	1	1
+20	1	1
+367	20	19
+488	0	4
+1457	2	1
+205	5	5
+11	1	1
+213	20	15
+1190	30	0
+35	1	1
+1742	1	0
+123	1	0
+4678	0	2
+5739	0	1
+1167	0	1
+1767	1	0
+253	15	15
+5582	1	21
+8987	1	0
+2138	3	2
+2203	2	1
+5654	1	1
+24	3	3
+3229	0	1
+3385	4	4
+6989	1	0
+1294	4	0
+9088	2	3
+2270	1	1
+32	1	1
+6293	1	1
+26	1	1
+2668	4	0
+7792	1	0
+7099	2	0
+1639	1	0
+13217	0	2
+6668	0	2
+2319	1	0
+1034	0	6
+430	1	0
+1276	1	1
+27	1	1
+142	3	3
+35	1	1
+1211	1	1
+34	1	1
+664	0	10
+59	1	1
+78	1	1
+1519	1	1
+27	1	1
+154	14	14
+2525	0	4
+79	1	1
+145	1	1
+63	1	1
+70	1	1
+21	1	1
+695	1	1
+41	2	2
+564	1	1
+46	1	1
+279	4	0
+38	5	5
+201	22	22
+1020	1	1
+25	1	1
+2253	32	32
+545	1	1
+27	1	0
+54	15	16
+363	0	1
+845	0	2
+60	7	0
+787	2	0
+3691	1	0
+1843	1	1
+45	1	0
+11	1	2
+3499	1	1
+27	1	1
+970	0	1
+76	0	2
+1804	2	0
+1079	1	1
+17	1	1
+639	3	5
+73	1	1
+13	13	0
+66	1	1
+96	0	1
+294	14	0
+4554	0	1
+53	9	6
+691	0	1
+989	1	1
+143	1	1
+223	0	2
+95	1	1
+1136	1	1
+49	1	1
+606	1	1
+48	1	1
+128	0	4
+109	1	31
+44	10	781
+62	4	0
+129	1	1
+62	1	1
+106	1	1
+268	18	4
+125	1	1
+43	1	1
+909	0	2
+381	4	4
+74	1	1
+408	1	0
+1011	8	0
+8833	1	1
+23	6	19
+6628	1	1
+28	1	1
+4872	20	20
+692	1	0
+2650	0	4
+194	0	1
+596	5	6
+1359	0	1
+1572	7	7
+299	1	1
+49	1	1
+803	1	1
+93	1	1
+797	14	14
+433	8	0
+108	11	11
+140	1	1
+40	1	1
+470	1	1
+42	1	1
+1192	4	4
+129	1	1
+123	2	0
+95	1	1
+82	3	0
+664	1	1
+77	1	1
+57	1	1
+62	1	1
+473	2	0
+262	6	0
+45	1	1
+63	2	0
+39	1	1
+267	0	1
+197	2	104
+87	111	0
+122	0	7
+88	0	4
+86	1	1
+21	6	0
+563	14	14
+324	1	0
+205	1	1
+17	1	1
+426	17	17
+52	0	1
+201	4	0
+14	1	1
+1080	1	1
+24	1	1
+91	24	24
+279	9	8
+55	1	1
+32	1	1
+121	1	1
+62	1	1
+80	1	1
+72	1	1
+2217	2	0
+820	1	1
+30	1	1
+271	1	1
+47	1	1
+609	1	0
+1780	2	0
+742	1	1
+40	1	1
+272	1	1
+52	1	1
+1187	1	1
+23	1	1
+254	1	1
+60	1	1
+176	3	6
+463	1	1
+36	1	1
+797	1	1
+22	1	1
+395	5	2
+61	1	1
+31	3	3
+226	1	1
+59	1	1
+581	1	1
+46	1	1
+412	1	1
+23	1	0
+174	1	1
+24	1	1
+83	15	15
+363	1	1
+91	1	1
+383	20	20
+90	1	1
+44	1	1
+63	13	13
+976	1	1
+29	1	0
+10	0	3
+161	14	15
+127	16	16
+517	1	1
+81	1	1
+218	28	28
+124	1	1
+68	0	22
+399	7	7
+668	0	1
+175	1	0
+1018	1	1
+90	4	4
+1034	15	15
+69	1	1
+33	1	1
+174	1	1
+56	1	1
+169	1	0
+201	1	1
+30	1	1
+58	1	1
+38	1	1
+91	1	1
+98	4	4
+65	1	1
+19	2	0
+104	6	5
+25	1	1
+218	1	1
+37	1	1
+343	264243	150023
+66	8	8
+36	0	11
+62	1	1
+107	1	1
+68	3	130
+66	4	4
+50	21	21
+98	1	1
+127	1	0
+192	1	1
+71	1	1
+52	1	1
+200	1	1
+97	4	4
+85	5	5
+448	1	1
+97	11	11
+171	1	1
+61	1	1
+37	1	1
+156	3	0
+63	0	3
+155	3	0
+32	2	0
+232	1	1
+33	1	1
+175	2	0
+131	6	6
+1409	0	3
+222	1	1
+23	0	1
+1470	1	1
+21	1	1
+460	1	1
+71	1	1
+394	2	8
+37	1	1
+90	1	1
+43	1	1
+650	1	1
+34	1	1
+839	0	1
+431	1	1
+36	1	1
+284	51277	50054
+255	1	1
+80	5	5
+71	1	1
+48	3	3
+65	1	1
+83	1	1
+292	1	1
+33	1	1
+421	1	1
+74	1	0
+151	8	0
+65	1	1
+70	0	2
+58	0	8
+157	1	1
+64	1	1
+66	2	1
+97	1	1
+54	1	1
+46	0	1
+20	1	1
+210	16	16
+270	1	1
+46	1	1
+202	1	1
+22	1	1
+309	1	1
+25	0	1
+174	10	10
+305	1	1
+40	1	1
+75	32	30
+150	1	0
+17	1	1
+69	2	2
+27	1	1
+38	6	0
+49	5	3
+255	1	1
+43	1	1
+90	1	1
+74	1	1
+364	1	1
+23	3	3
+69	1	1
+22	2	0
+78	1	1
+29	1	0
+96	1	1
+56	8	0
+87	5	10
+85	2	2
+39	1	1
+87	314	0
+364	1	1
+64	1	1
+201	0	4
+42	0	1
+56	5	9
+62	0	5
+45	1	1
+109	25	25
+314	1	2
+16	0	2
+45	1	1
+103	17	17
+84	8	8
+294	17	17
+527	10	10
+435	4	0
+91	0	4
+387	10	10
+312	1	1
+43	1	1
+181	1	0
+1737	2	3
+50	1	1
+140	1	1
+33	1	0
+113	7	7
+353	6	6
+794	8	8
+510	1	1
+18	1	1
+124	1	1
+19	8	4
+76	1	0
+880	1	1
+16	1	1
+491	1	1
+49	1	1
+239	1	1
+7	0	1
+67	1	1
+114	0	25
+26	1	1
+183	13	13
+72	1	1
+26	1	0
+42	1	1
+222	14	14
+320	1	1
+55	1	1
+414	6	5
+1003	1	1
+20	0	8
+849	1	1
+29	1	1
+978	29539	30058
+159	1	1
+36	1	1
+107	1	1
+176	1	1
+154	0	5
+91	1	1
+54	1	1
+77	1	1
+238	2	2
+50	1	1
+1421	1	1
+23	1	1
+216	1	1
+122	1	1
+86	1	1
+41	3	1
+336	7	7
+41	9	0
+107	1	1
+90	1	3
+6	1	0
+84	1	1
+213	1	1
+26	1	1
+138	1	1
+25	1	1
+206	1	1
+36	3	3
+37	7	0
+500	1	1
+52	1	1
+52	1	1
+48	1	1
+186	1	1
+66	1	1
+141	1	1
+66	6	6
+72	1	0
+69	1	1
+100	10	10
+160	1	0
+64	7	7
+89	1	1
+123	1	1
+128	1	1
+36	1	1
+231	1	1
+61	1	1
+564	8	8
+593	1	1
+45	1	1
+163	1	0
+196	8	8
+97	1	1
+118	1	1
+67	0	1
+192	1	1
+60	3	0
+19	1	1
+1149	1	1
+18	1	1
+77	1	1
+32	2	0
+32	1	1
+136	1	1
+78	2	0
+162	4	0
+41	1	1
+351	13	13
+1634	2	0
+229	8	8
+59	11	0
+410	1	1
+76	1	1
+180	1	1
+92	1	1
+270	1	1
+40	1	1
+92	1	1
+53	1	1
+227	1	1
+42	1	1
+357	4	4
+23	1	1
+94	1	0
+200	6	0
+201	7	7
+70	5	13
+57	4	0
+35	1	1
+206	1	1
+76	2	2
+651	1	1
+68	4	0
+73	1	1
+49	4	0
+37	1	1
+145	2	2
+78	2	2
+108	12	12
+52	1	1
+35	1	1
+242	1	3
+76	2	2
+50	12	12
+70	1	1
+33	0	2
+57	1	1
+64	15	15
+168	1	1
+22	1	1
+66	2	2
+6	0	1
+24	1	1
+73	0	2
+64	1	1
+177	2	0
+19	4	0
+55	1	0
+33	1	1
+51	1	1
+122	1	1
+296	1	1
+85	1	1
+109	1	1
+64	1	1
+155	1	1
+58	0	2
+72	1	1
+25	1	1
+128	1	1
+45	2	0
+334	4	4
+106	1	1
+25	1	1
+64	1	1
+21	1	1
+368	15	15
+734	2	0
+701	15	15
+71	1	1
+41	1	1
+77	1	1
+56	1	1
+478	2	0
+714	8	7
+95	2	2
+52	2	1
+1129	1	1
+34	1	1
+1715	1	1
+87	1	1
+692	1	1
+47	0	1
+75	1	1
+2155	10	10
+1265	1	1
+46	1	1
+298	1	1
+22	1	1
+186	1	1
+34	1	1
+202	1	1
+61	1	0
+185	1	1
+24	1	0
+98	0	2
+258	8	14
+967	1	1
+15	1	1
+625	1	0
+1362	0	4
+23365	4	0
+6220	3	0
+1351	18	18
+11498	8145	8145
+3307	0	1
+13671	3	3
+52	1	1
+1308	2	0
+942	0	1
+17790	1	0
+4586	0	1
+949	0	2
+15047	0	1
+606	3	0
+7820	0	4
+22313	6	0
+10539	12	0
+4836	0	1
+8726	2	0
+194	1	1
+49	1	1
+15889	3	0
+2693	0	2
+2787	56	56
+544	0	1
+2673	26	19
+3075	2	0
+4230	8	0
+879	0	1
+9534	0	4
+23	1	1
+599	0	1
+317	1	0
+2844	27	31
+571	2	0
+3158	0	4
+4455	2	0
+1609	0	7
+61	1	1
+66	1	1
+343	7	0
+25	1	1
+246	0	1
+15	1	1
+943	2	0
+136	8	7
+589	1	1
+84	1	1
+280	17	15
+680	15	15
+81	0	3
+1484	12	28
+1016	1	1
+45	1	0
+108	0	10
+675	4	0
+1568	0	1
+191	4	4
+1484	9	13
+3530	2	4
+2846	1	1
+17	1	1
+704	0	1
+4801	1	0
+1417	0	4
+50	3	0
+165	0	1
+4044	39283	39283
+854	1	1
+47	1	1
+479	1	0
+137	0	3
+1456	10	13
+63	1	1
+37	1	1
+261	0	2
+109	1	1
+50	1	1
+56	129	1
+88	1	0
+44	1	1
+54	1	1
+56	1	50
+58	50	1
+54	277	1
+44	1	1
+297	0	39
+142	1	1
+85	1	1
+124	16	16
+58	3	15
+677	1	0
+1333	2	0
+13591	6	0
+1050	1	1
+46	1	1
+678	1	1
+31	1	1
+2632	4	4
+37	1	1
+22341	32	30
+10811	1	1
+25	0	1
+129	62	62
+226	1	1
+40	1	1
+159	4	4
+37	4	4
+179	1	1
+51	1	1
+103	2	0
+108	1	1
+79	1	1
+25	1	1
+58	1	1
+12	1	1
+275	14	0
+80	1	1
+83	1	1
+24	1	1
+59	1	0
+91	1	1
+65	1	1
+67	1	1
+136	4	0
+68	8	0
+331	5	0
+40	1	1
+110	10	6
+64	1	1
+368	1	1
+22	1	1
+509	1	1
+89	1	1
+926	1	0
+959	1	1
+44	1	1
+72	11	0
+47	1	1
+361	1	1
+37	1	1
+2204	2	2
+45	1	1
+1117	18	18
+141	1	1
+47	1	1
+148	1	1
+75	1	1
+107	57	56
+146	3	2
+249	1	1
+146	1	1
+94	1	1
+34	1	1
+700	0	331
+21	1	1
+73	1	1
+49	1	1
+356	1	1
+16	1	1
+112	1	1
+36	9	0
+515	1	1
+27	2	2
+192	1	1
+53	0	14
+82	1	1
+302	1	1
+68	1	1
+52	12	12
+52	1	1
+34	1	1
+166	7	7
+384	1	1
+31	1	1
+281	1	1
+57	1	1
+176	0	1
+1625	1	1
+26	1	1
+369	1	1
+21	1	1
+86	1	1
+134	1	1
+215	1	1
+214	15	1
+50	2	2
+26	1	1
+78	0	19
+64	1	1
+126	1	1
+43	1	1
+433	1	1
+76	0	1
+6	12	0
+52	1	1
+108	1	1
+87	1	1
+62	1	1
+26	1	1
+291	2	1
+143	1	1
+29	1	1
+56	12	12
+230	1	1
+153	4	4
+87	32	32
+584	12	12
+227	1	0
+1931	4	0
+836	1	1
+68	1	1
+205	24	19
+816	1	2
+1932	0	7
+1732	13	0
+257	4	0
+1441	1	0
+111	6	0
+1505	1	1
+42	0	1
+373	13	13
+565	1	1
+76	1	0
+1881	0	4
+68	4	0
+43	0	4
+2201	8	8
+3726	3	0
+339	15	11
+249	1	1
+35	1	1
+250	1	1
+38	1	1
+359	11	12
+109	1	1
+43	18	0
+822	1	1
+53	1	1
+325	15	15
+123	1	1
+42	6	6
+240	1	1
+44	1	1
+438	7	7
+142	2	0
+1004	0	1
+9275	1	1
+37	1	0
+2071	0	1
+10399	0	1
+12513	2	1
+11243	1	1
+26	1	1
+816	4	0
+8248	26	26
+7722	2	0
+1594	1	0
+363	5	0
+2394	0	2
+4361	43	41
+12296	4	0
+835	0	1
+391	34	61
+12157	0	18
+1719
+
+chain 576814 chr6_mann_hap4 4683263 + 1212600 1230600 chr10 135374737 - 28241612 28250801 9180
+481	1	1
+46	1	1
+3015	1	1
+93	1	1
+2394	11402	2623
+68	26	25
+5	0	2
+124	0	1
+62	39	3
+39	3	5
+199
+
+chain 536760 chr6_mann_hap4 4683263 + 4039899 4045825 chr5 180857866 + 39823592 39829519 16844
+294	1	1
+54	1	1
+302	0	1
+93	1	1
+29	2	2
+134	1	1
+55	1	1
+603	13	13
+1215	13	13
+1780	1	1
+42	1	1
+233	1	1
+94	1	1
+485	1	1
+173	1	1
+76	1	1
+24	1	1
+71	1	1
+44	1	1
+82
+
+chain 146874 chr6_mann_hap4 4683263 + 4071169 4072762 chr6 170899992 + 134026872 134029045 878977
+503	1	1
+42	1	1
+274	1	1
+24	0	1
+48	1	0
+10	0	1
+42	0	579
+646
+
+chain 102870 chr6_mann_hap4 4683263 + 3889360 3891944 chr7 158821424 + 116952571 116956379 1238703
+117	2	2
+40	1	1
+56	1	1
+110	1	1
+92	1	1
+113	2	2
+63	1	1
+85	102	1326
+64	26	26
+95	124	124
+108	355	355
+211	690	690
+124
+
+chain 88220 chr6_mann_hap4 4683263 + 4099145 4105339 chr12 132349534 - 75332582 75341961 1434691
+65	33	33
+177	10	15
+106	4900	8080
+86	4	4
+267	1	1
+40	1	1
+504
+
+chain 82095 chr6_mann_hap4 4683263 + 3946479 3947465 chr2 242951149 - 63941857 63946734 1538129
+173	0	3890
+317	1	1
+39	1	1
+234	0	4
+116	1	1
+18	3	0
+83
+
+chain 77658 chr6_mann_hap4 4683263 + 3855504 3856400 chrX 154913754 + 120225651 120226547 1623639
+896
+
+chain 47748 chr6_mann_hap4 4683263 + 3888321 3890147 chrX 154913754 + 47530376 47536125 1299062
+73	10	10
+52	18	17
+100	64	64
+53	6	6
+131	99	99
+213	51	51
+144	732	4656
+80
+
+chain 47213 chr6_mann_hap4 4683263 + 3989872 3990794 chr5 180857866 + 134244858 134245983 2704506
+144	28	28
+67	90	94
+193	60	61
+52	141	339
+53	41	41
+53
+
+chain 46978 chr6_mann_hap4 4683263 + 2571063 2572874 chr3 199501827 - 190558999 190560805 2719824
+64	48	48
+112	161	161
+89	220	218
+60	475	474
+84	303	301
+99	9	9
+87
+
+chain 44341 chr6_mann_hap4 4683263 + 3927110 3927612 chrX 154913754 - 52960373 52960875 2903522
+147	1	1
+78	1	1
+160	1	1
+114
+
+chain 44107 chr6_mann_hap4 4683263 + 3835941 3836978 chr5 180857866 + 173373371 173375321 2921175
+63	100	100
+147	427	1340
+300
+
+chain 39461 chr6_mann_hap4 4683263 + 4070547 4070992 chr9 140273252 + 112733643 112734088 3326103
+238	2	2
+149	1	1
+55
+
+chain 35818 chr6_mann_hap4 4683263 + 3871024 3871462 chr17 78774742 - 29841443 29841854 3734139
+50	1	1
+51	12	0
+240	15	0
+69
+
+chain 30934 chr6_mann_hap4 4683263 + 2643294 2643706 chr7 158821424 + 2168309 2168721 4470814
+207	3	3
+37	1	1
+54	50	50
+60
+
+chain 26090 chr6_mann_hap4 4683263 + 1150980 1153720 chr6 170899992 + 30003398 30007118 6475487
+62	70	70
+76	766	798
+93	658	655
+52	786	1737
+53	61	61
+63
+
+chain 23990 chr6_mann_hap4 4683263 + 1157427 1158203 chr7 158821424 - 51137320 51138262 7695541
+178	101	101
+72	385	551
+40
+
+chain 23264 chr6_mann_hap4 4683263 + 4065870 4066815 chr6 170899992 + 32821586 32822354 8135397
+218	677	500
+50
+
+chain 21807 chr6_mann_hap4 4683263 + 2512201 2512573 chrX 154913754 - 34520894 34521266 9125800
+131	125	125
+116
+
+chain 20350 chr6_mann_hap4 4683263 + 2657077 2657501 chr7 158821424 - 21000102 21000525 10170609
+90	41	41
+55	140	139
+98
+
+chain 20145 chr6_mann_hap4 4683263 + 4080253 4081781 chr7 158821424 + 28844408 28845333 2477233
+50	75	74
+83	106	109
+74	174	246
+103	816	139
+47
+
+chain 19089 chr6_mann_hap4 4683263 + 3856636 3856946 chr6 170899992 - 57258123 57258433 11200200
+55	51	51
+66	32	32
+106
+
+chain 17641 chr6_mann_hap4 4683263 + 4011215 4011458 chrX 154913754 + 35042287 35042530 12436915
+99	43	43
+101
+
+chain 16962 chr6_mann_hap4 4683263 + 2570543 2573577 chr6 170899992 - 142198254 142201285 2740643
+52	14	14
+92	178	178
+78	1931	1927
+60	60	61
+102	387	387
+80
+
+chain 16215 chr6_mann_hap4 4683263 + 3951844 3952907 chr6 170899992 + 32656500 32657559 13820716
+58	826	822
+72	27	27
+80
+
+chain 16190 chr6_mann_hap4 4683263 + 3164538 3164716 chr2 242951149 + 128261675 128261851 597537
+28	10	8
+140
+
+chain 16086 chr6_mann_hap4 4683263 + 4006818 4007634 chr1 247249719 - 180906629 180907434 2580692
+2	123	123
+47	104	104
+70	400	389
+70
+
+chain 15557 chr6_mann_hap4 4683263 + 4157319 4158144 chr7 158821424 + 130132312 130132930 14485178
+71	636	429
+118
+
+chain 15452 chr6_mann_hap4 4683263 + 3929430 3929596 chrX 154913754 + 67920599 67920765 14594392
+166
+
+chain 14605 chr6_mann_hap4 4683263 + 4069695 4069910 chr5 180857866 + 98319067 98319283 15498993
+64	48	49
+103
+
+chain 14320 chr6_mann_hap4 4683263 + 3970754 3970920 chr5 180857866 + 46013667 46013833 15829593
+166
+
+chain 13359 chr6_mann_hap4 4683263 + 4006581 4006818 chr5 180857866 - 39455571 39455808 2075146
+237
+
+chain 13048 chr6_mann_hap4 4683263 + 3971467 3971895 chr2 242951149 + 206984071 206984490 17422560
+94	272	263
+62
+
+chain 13024 chr6_mann_hap4 4683263 + 983409 983545 chr11 134452384 - 45905925 45906061 17454497
+136
+
+chain 12983 chr6_mann_hap4 4683263 + 3892428 3892585 chr15 100338915 + 59852230 59852387 17511267
+67	7	7
+83
+
+chain 12686 chr6_mann_hap4 4683263 + 3839048 3839184 chr6 170899992 - 138278996 138279132 17957207
+136
+
+chain 12556 chr6_mann_hap4 4683263 + 1192697 1192836 chr2 242951149 - 184047846 184047985 18149168
+139
+
+chain 12476 chr6_mann_hap4 4683263 + 3826791 3826924 chr6 170899992 + 32549390 32549523 18269668
+133
+
+chain 12434 chr6_mann_hap4 4683263 + 3808825 3809130 chr7 158821424 - 76714202 76714512 18331176
+70	158	163
+77
+
+chain 12179 chr6_mann_hap4 4683263 + 3831748 3831876 chr6 170899992 + 32566069 32566197 18716372
+128
+
+chain 12137 chr6_mann_hap4 4683263 + 3872720 3873131 chr7 158821424 + 90920405 90920810 18779045
+54	266	260
+91
+
+chain 12051 chr6_mann_hap4 4683263 + 1151414 1151573 chr6 170899992 + 30566919 30567079 18913589
+81	23	24
+55
+
+chain 11900 chr6_mann_hap4 4683263 + 3926391 3926689 chr5 180857866 - 150002482 150002780 2916742
+72	52	52
+94	24	24
+56
+
+chain 11872 chr6_mann_hap4 4683263 + 1146859 1148064 chr6 170899992 + 29900614 29901492 19205041
+65	1050	723
+90
+
+chain 11746 chr6_mann_hap4 4683263 + 1143598 1143746 chr7 158821424 - 7754727 7754875 19419747
+54	14	14
+80
+
+chain 11745 chr6_mann_hap4 4683263 + 1218680 1218806 chr10 135374737 - 135314271 135314397 19420295
+126
+
+chain 11699 chr6_mann_hap4 4683263 + 1229899 1230035 chr10 135374737 + 90412720 90412856 14918390
+117	3	3
+16
+
+chain 11593 chr6_mann_hap4 4683263 + 3807962 3808085 chr1 247249719 - 238369051 238369174 19677684
+123
+
+chain 11428 chr6_mann_hap4 4683263 + 3972086 3972349 chr9 140273252 + 73803510 73803773 19960546
+86	127	127
+50
+
+chain 11397 chr6_mann_hap4 4683263 + 3965743 3966049 chr6 170899992 + 32661358 32661660 20018576
+64	168	164
+74
+
+chain 11122 chr6_mann_hap4 4683263 + 1203623 1204440 chr6 170899992 - 139553083 139553887 20511870
+77	676	663
+64
+
+chain 11075 chr6_mann_hap4 4683263 + 3824678 3824943 chrX 154913754 - 91757488 91757751 20592182
+66	132	130
+67
+
+chain 11034 chr6_mann_hap4 4683263 + 2653282 2653431 chr6 170899992 - 161606914 161607063 20670487
+64	22	22
+63
+
+chain 10867 chr6_mann_hap4 4683263 + 2578599 2578756 chr6 170899992 - 132294381 132294544 20980274
+55	29	35
+73
+
+chain 10661 chr6_mann_hap4 4683263 + 4070344 4070547 chr9 140273252 + 21133799 21134002 3998059
+43	83	83
+77
+
+chain 10522 chr6_mann_hap4 4683263 + 3881310 3881592 chr6 170899992 + 32650612 32650898 21668160
+51	155	159
+76
+
+chain 10446 chr6_mann_hap4 4683263 + 3833364 3833476 chr10 135374737 + 116791472 116791584 21828222
+112
+
+chain 10440 chr6_mann_hap4 4683263 + 3811691 3811821 chr3 199501827 - 53390365 53390495 21843018
+67	9	9
+54
+
+chain 10424 chr6_mann_hap4 4683263 + 1196400 1196662 chr1 247249719 - 93388912 93389184 21873906
+71	137	147
+54
+
+chain 10120 chr6_mann_hap4 4683263 + 4070282 4070470 chr7 158821424 - 148539669 148539857 3454343
+62	43	43
+83
+
+chain 10097 chr6_mann_hap4 4683263 + 3811321 3811557 chr6 170899992 - 10896454 10896689 22596969
+52	115	114
+69
+
+chain 10000 chr6_mann_hap4 4683263 + 4096293 4096805 chr2 242951149 - 75663422 75663931 22813441
+66	387	384
+59
+
+chain 9988 chr6_mann_hap4 4683263 + 3809787 3810216 chr10 135374737 - 44216709 44217139 22840112
+60	305	306
+64
+
+chain 9977 chr6_mann_hap4 4683263 + 4081621 4081734 chr6 170899992 - 39392888 39393001 3205407
+113
+
+chain 9923 chr6_mann_hap4 4683263 + 1132190 1132294 chr6 170899992 + 29984509 29984613 22990369
+104
+
+chain 9759 chr6_mann_hap4 4683263 + 3834344 3834498 chr10 135374737 + 105999092 105999246 23372649
+62	39	39
+53
+
+chain 9755 chr6_mann_hap4 4683263 + 3833117 3833361 chrX 154913754 - 4438295 4438540 23379344
+56	126	127
+62
+
+chain 9686 chr6_mann_hap4 4683263 + 3810435 3810616 chr18 76117153 - 71040520 71040702 23549061
+65	65	66
+51
+
+chain 9627 chr6_mann_hap4 4683263 + 3972992 3973194 chr2 242951149 + 230690248 230690450 23687186
+65	86	86
+51
+
+chain 9614 chr6_mann_hap4 4683263 + 2669709 2670446 chr6 170899992 - 140934793 140935541 23727233
+66	613	624
+58
+
+chain 9599 chr6_mann_hap4 4683263 + 4070139 4070248 chr11 134452384 + 56073710 56073819 11992436
+109
+
+chain 9564 chr6_mann_hap4 4683263 + 3827056 3827221 chr6 170899992 + 32549657 32549823 23841399
+59	50	51
+56
+
+chain 9528 chr6_mann_hap4 4683263 + 1159675 1160112 chr6 170899992 + 29878108 29878543 23937749
+59	318	316
+60
+
+chain 9459 chr6_mann_hap4 4683263 + 4095177 4095476 chr6 170899992 + 162410099 162410399 24103461
+60	183	184
+56
+
+chain 9368 chr6_mann_hap4 4683263 + 3972521 3972756 chr12 132349534 - 95011118 95011354 24299159
+63	120	121
+52
+
+chain 9354 chr6_mann_hap4 4683263 + 3870808 3870942 chr6 170899992 + 119226702 119226836 9825430
+89	20	20
+25
+
+chain 9352 chr6_mann_hap4 4683263 + 3873416 3873994 chr1 247249719 - 127730766 127731350 24325058
+63	457	463
+58
+
+chain 9220 chr6_mann_hap4 4683263 + 3811888 3812097 chr14 106368585 - 26360313 26360419 24589598
+77	103	0
+29
+
+chain 9090 chr6_mann_hap4 4683263 + 2577845 2577955 chr3 199501827 - 94209663 94209773 24799757
+53	4	4
+53
+
+chain 8867 chr6_mann_hap4 4683263 + 2303270 2303362 chr6 170899992 + 31062348 31062440 25148412
+92
+
+chain 8658 chr6_mann_hap4 4683263 + 3940022 3940112 chr6 170899992 + 32624355 32624445 25451087
+90
+
+chain 8423 chr6_mann_hap4 4683263 + 4072785 4072907 chr8 146274826 - 73050790 73050912 14363914
+122
+
+chain 8057 chr6_mann_hap4 4683263 + 3926870 3927000 chr16 88827254 + 18531944 18532074 3198196
+130
+
+chain 7759 chr6_mann_hap4 4683263 + 2673921 2674003 chr6 170899992 + 31350450 31350532 26801069
+82
+
+chain 7673 chr6_mann_hap4 4683263 + 2657501 2657610 chr6 170899992 + 83069844 83069953 14556403
+4	44	44
+61
+
+chain 7642 chr6_mann_hap4 4683263 + 3888828 3890773 chr8 146274826 - 66025745 66026665 1359052
+97	215	215
+31	1	1
+19	1532	507
+50
+
+chain 7574 chr6_mann_hap4 4683263 + 4484512 4485183 chr20 62435964 + 45587686 45587880 2535008
+51	481	51
+16	61	14
+62
+
+chain 7541 chr6_mann_hap4 4683263 + 2688373 2688460 chr9 140273252 - 10289268 10289355 15645101
+13	6	6
+68
+
+chain 7487 chr6_mann_hap4 4683263 + 2574042 2574244 chr12 132349534 - 40641236 40641438 23940543
+56	141	141
+5
+
+chain 7440 chr6_mann_hap4 4683263 + 3850580 3850658 chrX 154913754 - 39741290 39741368 27355538
+78
+
+chain 7404 chr6_mann_hap4 4683263 + 3850662 3850740 chr11 134452384 + 35675434 35675512 27404541
+78
+
+chain 7364 chr6_mann_hap4 4683263 + 4081165 4082062 chr1 247249719 + 33290703 33291601 1419850
+50	1	0
+53	86	88
+56	370	370
+160	42	42
+79
+
+chain 7276 chr6_mann_hap4 4683263 + 4034825 4034901 chr6 170899992 - 67344251 67344327 27653184
+76
+
+chain 7232 chr6_mann_hap4 4683263 + 3936821 3936898 chr6 170899992 + 32620027 32620104 27728489
+77
+
+chain 7204 chr6_mann_hap4 4683263 + 3963650 3963727 chr13 114142980 + 48271341 48271418 27789281
+77
+
+chain 7199 chr6_mann_hap4 4683263 + 4005404 4006455 chr3 199501827 + 106790123 106791174 347314
+69	5	5
+109	2	2
+142	1	1
+77	1	1
+51	1	0
+194	0	1
+399
+
+chain 7168 chr6_mann_hap4 4683263 + 4101507 4101583 chr12 132349534 + 30936505 30936581 27864404
+76
+
+chain 7077 chr6_mann_hap4 4683263 + 3870942 3871024 chr3 199501827 - 45186978 45187059 5450943
+68	1	0
+13
+
+chain 7012 chr6_mann_hap4 4683263 + 4115371 4115645 chr5 180857866 - 50439772 50440046 4370271
+130	8	8
+64	1	1
+71
+
+chain 6949 chr6_mann_hap4 4683263 + 3795791 3795864 chr6 170899992 + 32549387 32549460 28300222
+73
+
+chain 6804 chr6_mann_hap4 4683263 + 3799462 3799534 chr6 170899992 + 32582474 32582546 28581367
+72
+
+chain 6732 chr6_mann_hap4 4683263 + 2675578 2675667 chr18 76117153 - 11487790 11487879 28728624
+29	7	7
+53
+
+chain 6712 chr6_mann_hap4 4683263 + 2588030 2588100 chr6 170899992 - 140565854 140565924 28801698
+70
+
+chain 6680 chr6_mann_hap4 4683263 + 4075286 4087765 chr6 170899992 + 32827127 32836923 21175981
+50	4327	3617
+61	4734	2690
+85	515	965
+52	119	119
+177	2121	1742
+68	118	118
+52
+
+chain 6622 chr6_mann_hap4 4683263 + 3824747 3824817 chr11 134452384 + 57802002 57802072 28988414
+70
+
+chain 6586 chr6_mann_hap4 4683263 + 2674213 2674283 chr6 170899992 - 140567268 140567338 29088341
+70
+
+chain 6584 chr6_mann_hap4 4683263 + 3990111 3990185 chr18 76117153 - 4274607 4274681 4481991
+74
+
+chain 6566 chr6_mann_hap4 4683263 + 4010034 4010102 chr6 170899992 + 32665461 32665529 29137405
+68
+
+chain 6513 chr6_mann_hap4 4683263 + 4099018 4099087 chr12 132349534 + 47073126 47073195 29262419
+69
+
+chain 6495 chr6_mann_hap4 4683263 + 4159049 4159118 chr5 180857866 + 76445848 76445917 29303918
+69
+
+chain 6436 chr6_mann_hap4 4683263 + 3871527 3871805 chr7 158821424 + 110932926 110933204 10468972
+57	171	171
+50
+
+chain 6411 chr6_mann_hap4 4683263 + 4039821 4039893 chr7 158821424 + 30445389 30445461 17285
+72
+
+chain 6359 chr6_mann_hap4 4683263 + 3869372 3869440 chr6 170899992 + 32566306 32566374 29618338
+68
+
+chain 6271 chr6_mann_hap4 4683263 + 3932457 3932523 chr18 76117153 + 11207587 11207653 29843873
+66
+
+chain 6221 chr6_mann_hap4 4683263 + 4094828 4094893 chr13 114142980 + 50378597 50378662 29991830
+65
+
+chain 6213 chr6_mann_hap4 4683263 + 1229662 1229728 chrX 154913754 + 137911239 137911305 30001477
+66
+
+chain 6203 chr6_mann_hap4 4683263 + 3873624 3873689 chr10 135374737 + 5090148 5090213 30033078
+65
+
+chain 6176 chr6_mann_hap4 4683263 + 4099536 4099611 chr11 134452384 - 71399807 71399882 3438338
+75
+
+chain 6158 chr6_mann_hap4 4683263 + 3877219 3877284 chr8 146274826 + 95080661 95080726 30127968
+65
+
+chain 6140 chr6_mann_hap4 4683263 + 4095848 4095913 chr6 170899992 - 34774251 34774316 30199403
+65
+
+chain 6109 chr6_mann_hap4 4683263 + 3890332 3891494 chr3 199501827 - 173189040 173190202 2018297
+14	5	5
+73	23	23
+9	985	985
+53
+
+chain 6085 chr6_mann_hap4 4683263 + 3815553 3815617 chr6 170899992 - 55240220 55240284 30326057
+64
+
+chain 6021 chr6_mann_hap4 4683263 + 4094914 4094977 chr10 135374737 - 117721859 117721922 30522771
+63
+
+chain 5976 chr6_mann_hap4 4683263 + 2676901 2676964 chr6 170899992 + 31358648 31358711 30614230
+63
+
+chain 5949 chr6_mann_hap4 4683263 + 3824409 3824472 chr7 158821424 + 26639264 26639327 30690415
+63
+
+chain 5940 chr6_mann_hap4 4683263 + 3886792 3886855 chr2 242951149 - 15301589 15301652 30719367
+63
+
+chain 5911 chr6_mann_hap4 4683263 + 3951381 3951442 chrX 154913754 - 11371530 11371591 30799839
+61
+
+chain 5847 chr6_mann_hap4 4683263 + 4105339 4105404 chr17 78774742 - 73855979 73856044 1451430
+65
+
+chain 5813 chr6_mann_hap4 4683263 + 3850423 3850485 chr1 247249719 + 47323960 47324022 31053357
+62
+
+chain 5712 chr6_mann_hap4 4683263 + 3809370 3809430 chr12 132349534 - 114271713 114271773 31330278
+60
+
+chain 5702 chr6_mann_hap4 4683263 + 3970106 3970165 chr6 170899992 + 32605878 32605937 31357679
+59
+
+chain 5680 chr6_mann_hap4 4683263 + 2302831 2302921 chr6 170899992 + 31062944 31063124 23617653
+33	39	129
+18
+
+chain 5655 chr6_mann_hap4 4683263 + 3855204 3855371 chrX 154913754 + 81246238 81246422 14247867
+57	109	126
+1
+
+chain 5594 chr6_mann_hap4 4683263 + 3796059 3796118 chr6 170899992 + 32549657 32549716 31663072
+59
+
+chain 5594 chr6_mann_hap4 4683263 + 3893458 3893517 chr1 247249719 - 146336256 146336315 31665010
+59
+
+chain 5512 chr6_mann_hap4 4683263 + 3824164 3824222 chr7 158821424 + 45670922 45670980 31905208
+58
+
+chain 5502 chr6_mann_hap4 4683263 + 3808491 3808548 chr1 247249719 - 79348621 79348678 31943034
+57
+
+chain 5494 chr6_mann_hap4 4683263 + 4130703 4130761 chr5 180857866 - 119300515 119300573 31945207
+58
+
+chain 5494 chr6_mann_hap4 4683263 + 3808247 3808305 chr4 191273063 - 5377020 5377078 31946828
+58
+
+chain 5476 chr6_mann_hap4 4683263 + 2311526 2311584 chrX 154913754 + 154691014 154691072 32018635
+58
+
+chain 5448 chr6_mann_hap4 4683263 + 1152324 1152381 chr6 170899992 + 29906136 29906193 32122349
+57
+
+chain 5435 chr6_mann_hap4 4683263 + 4007164 4007322 chr6 170899992 - 63943483 63943641 1906371
+158
+
+chain 5402 chr6_mann_hap4 4683263 + 1156066 1156122 chr10 135374737 + 63402064 63402120 32243879
+56
+
+chain 5394 chr6_mann_hap4 4683263 + 3972634 3972691 chr9 140273252 - 60383594 60383651 32250416
+57
+
+chain 5385 chr6_mann_hap4 4683263 + 4130844 4130901 chr6 170899992 - 83909587 83909644 32298057
+57
+
+chain 5367 chr6_mann_hap4 4683263 + 2578199 2578256 chr18 76117153 + 1134159 1134216 32358571
+57
+
+chain 5330 chr6_mann_hap4 4683263 + 3931278 3931334 chr6 170899992 + 32568311 32568367 32437916
+56
+
+chain 5276 chr6_mann_hap4 4683263 + 4098513 4098569 chr12 132349534 + 40414598 40414654 32640380
+56
+
+chain 5229 chr6_mann_hap4 4683263 + 2586412 2586466 chr6 170899992 - 140897459 140897513 32754405
+54
+
+chain 5211 chr6_mann_hap4 4683263 + 3836033 3836093 chr18 76117153 - 36956615 36956675 5572697
+38	15	15
+7
+
+chain 5158 chr6_mann_hap4 4683263 + 3970466 3970521 chr10 135374737 - 40576729 40576784 32990090
+55
+
+chain 5146 chr6_mann_hap4 4683263 + 3856405 3856719 chr8 146274826 + 48564292 48564606 15853984
+85	201	201
+28
+
+chain 5121 chr6_mann_hap4 4683263 + 3811628 3811682 chr10 135374737 - 125001214 125001268 33093899
+54
+
+chain 5103 chr6_mann_hap4 4683263 + 1145020 1145074 chr6 170899992 + 76955761 76955815 33170027
+54
+
+chain 5103 chr6_mann_hap4 4683263 + 2640619 2640673 chr4 191273063 + 102542252 102542306 33171908
+54
+
+chain 5085 chr6_mann_hap4 4683263 + 4098430 4098484 chrX 154913754 - 140611616 140611670 33235342
+54
+
+chain 5066 chr6_mann_hap4 4683263 + 1192620 1192673 chr21 46944323 - 1867343 1867396 33290792
+53
+
+chain 5062 chr6_mann_hap4 4683263 + 2570759 2570813 chr8 146274826 - 12544502 12544556 11634211
+54
+
+chain 5031 chr6_mann_hap4 4683263 + 3825550 3825604 chr11 134452384 + 134387408 134387462 33376435
+54
+
+chain 5030 chr6_mann_hap4 4683263 + 4130785 4130838 chr15 100338915 + 69519076 69519129 33389328
+53
+
+chain 5021 chr6_mann_hap4 4683263 + 2574130 2574183 chrX 154913754 + 36345885 36345938 33439867
+53
+
+chain 5020 chr6_mann_hap4 4683263 + 4060907 4060959 chr3 199501827 + 48220698 48220750 33444406
+52
+
+chain 5012 chr6_mann_hap4 4683263 + 3951677 3951730 chr6 170899992 + 32629462 32629515 33454256
+53
+
+chain 5003 chr6_mann_hap4 4683263 + 4102005 4102058 chr5 180857866 + 152654188 152654241 33499797
+53
+
+chain 5003 chr6_mann_hap4 4683263 + 1229462 1229515 chr19 63811651 - 15372469 15372522 33501003
+53
+
+chain 4985 chr6_mann_hap4 4683263 + 2640409 2640462 chr16 88827254 - 40848691 40848744 33578669
+53
+
+chain 4971 chr6_mann_hap4 4683263 + 2512062 2512133 chr4 191273063 - 56892114 56892185 10839773
+71
+
+chain 4967 chr6_mann_hap4 4683263 + 3825268 3825321 chr3 199501827 + 186460138 186460191 33617850
+53
+
+chain 4957 chr6_mann_hap4 4683263 + 3885923 3885975 chrX 154913754 + 147065533 147065585 33651269
+52
+
+chain 4957 chr6_mann_hap4 4683263 + 2575182 2575234 chr9 140273252 - 31866047 31866099 33651494
+52
+
+chain 4948 chr6_mann_hap4 4683263 + 4100717 4100769 chr1 247249719 - 35792193 35792245 33679191
+52
+
+chain 4948 chr6_mann_hap4 4683263 + 2574667 2574719 chr8 146274826 - 9857366 9857418 33680602
+52
+
+chain 4922 chr6_mann_hap4 4683263 + 4009115 4009168 chr6 170899992 + 32548301 32548354 33750859
+53
+
+chain 4903 chr6_mann_hap4 4683263 + 3850504 3850556 chr10 135374737 - 57466002 57466054 33851105
+52
+
+chain 4903 chr6_mann_hap4 4683263 + 4012033 4012085 chr10 135374737 + 117209347 117209399 33851122
+52
+
+chain 4863 chr6_mann_hap4 4683263 + 4069590 4069643 chr17 78774742 + 14392768 14392821 28434808
+53
+
+chain 4829 chr6_mann_hap4 4683263 + 1204441 1204491 chr6 170899992 + 29800923 29800973 34088054
+50
+
+chain 4821 chr6_mann_hap4 4683263 + 4157686 4157737 chrX 154913754 - 88293005 88293056 34119905
+51
+
+chain 4821 chr6_mann_hap4 4683263 + 3816946 3816997 chrX 154913754 + 135859174 135859225 34119936
+51
+
+chain 4812 chr6_mann_hap4 4683263 + 1190701 1190752 chr6 170899992 + 30567861 30567912 34152526
+51
+
+chain 4784 chr6_mann_hap4 4683263 + 3932557 3932607 chr3 199501827 + 84648995 84649045 34278095
+50
+
+chain 4758 chr6_mann_hap4 4683263 + 4095126 4095177 chr11 134452384 + 59226474 59226525 34323839
+51
+
+chain 4757 chr6_mann_hap4 4683263 + 2310474 2310524 chr11 134452384 + 7692440 7692490 34342561
+50
+
+chain 4739 chr6_mann_hap4 4683263 + 2310303 2310353 chr18 76117153 + 71840104 71840154 34400727
+50
+
+chain 4730 chr6_mann_hap4 4683263 + 3787434 3787484 chr4 191273063 - 37377714 37377764 34442427
+50
+
+chain 4712 chr6_mann_hap4 4683263 + 1146218 1146268 chr14 106368585 - 81295539 81295589 34510763
+50
+
+chain 4703 chr6_mann_hap4 4683263 + 2675065 2675115 chr8 146274826 + 89610032 89610082 34558303
+50
+
+chain 4685 chr6_mann_hap4 4683263 + 1229409 1229459 chrX 154913754 - 17497814 17497864 34590611
+50
+
+chain 4676 chr6_mann_hap4 4683263 + 3971574 3971624 chr8 146274826 + 69479304 69479354 34603338
+50
+
+chain 4606 chr6_mann_hap4 4683263 + 4016520 4016570 chr5 180857866 - 14463729 14463779 34659648
+50
+
+chain 4600 chr6_mann_hap4 4683263 + 2569984 2570033 chr12 132349534 - 4862576 4862625 22913313
+49
+
+chain 4530 chr6_mann_hap4 4683263 + 3886656 3886704 chr13 114142980 - 22170853 22170901 34701009
+48
+
+chain 4406 chr6_mann_hap4 4683263 + 4011118 4011181 chr12 132349534 + 83019068 83019131 17889504
+63
+
+chain 4392 chr6_mann_hap4 4683263 + 1157646 1157705 chr7 158821424 - 126060926 126060985 9905440
+59
+
+chain 4358 chr6_mann_hap4 4683263 + 3963545 3963592 chr4 191273063 + 98116240 98116287 34788627
+47
+
+chain 4338 chr6_mann_hap4 4683263 + 2302495 2302540 chr6 170899992 + 31062473 31062518 34812241
+45
+
+chain 4205 chr6_mann_hap4 4683263 + 2570813 2571448 chr4 191273063 + 161293453 161294088 2765734
+66	98	98
+77	6	6
+3	343	343
+42
+
+chain 4169 chr6_mann_hap4 4683263 + 4069643 4069694 chrX 154913754 + 84821116 84821167 24393818
+51
+
+chain 4167 chr6_mann_hap4 4683263 + 3838733 3838778 chr16 88827254 - 62536028 62536073 34880256
+45
+
+chain 4152 chr6_mann_hap4 4683263 + 3836004 3836104 chr19 63811651 + 19808105 19808205 3095372
+29	60	60
+11
+
+chain 4047 chr6_mann_hap4 4683263 + 3972236 3972287 chr6 170899992 + 112361298 112361349 25801950
+42	5	5
+4
+
+chain 3949 chr6_mann_hap4 4683263 + 2688555 2688633 chr19 63811651 + 60123016 60123094 19419643
+78
+
+chain 3938 chr6_mann_hap4 4683263 + 3812129 3812170 chr12 132349534 + 106783136 106783177 34996469
+41
+
+chain 3933 chr6_mann_hap4 4683263 + 2511488 2511645 chr1 247249719 - 10334654 10334811 9926759
+99	7	7
+51
+
+chain 3926 chr6_mann_hap4 4683263 + 4006888 4006943 chr9 140273252 - 21404336 21404391 4875740
+55
+
+chain 3812 chr6_mann_hap4 4683263 + 4007464 4007564 chr3 199501827 + 15208966 15209066 3047556
+56	42	42
+2
+
+chain 3783 chr6_mann_hap4 4683263 + 2657037 2657077 chr2 242951149 - 166645324 166645364 18114610
+40
+
+chain 3746 chr6_mann_hap4 4683263 + 3833193 3833245 chr3 199501827 + 114553026 114553078 23981702
+52
+
+chain 3734 chr6_mann_hap4 4683263 + 4157453 4157518 chr6 170899992 + 80018577 80018642 19955867
+65
+
+chain 3720 chr6_mann_hap4 4683263 + 4102548 4102587 chr5 180857866 - 28755460 28755499 35075682
+39
+
+chain 3600 chr6_mann_hap4 4683263 + 4159173 4159211 chr2 242951149 + 129304609 129304647 25766361
+38
+
+chain 3592 chr6_mann_hap4 4683263 + 3870724 3870762 chr3 199501827 - 38712743 38712781 26080747
+38
+
+chain 3526 chr6_mann_hap4 4683263 + 1196363 1196400 chr3 199501827 + 179624737 179624774 21949405
+37
+
+chain 3503 chr6_mann_hap4 4683263 + 3972049 3972086 chrX 154913754 + 6516305 6516342 20940830
+37
+
+chain 3405 chr6_mann_hap4 4683263 + 3888574 3888637 chr12 132349534 - 63727404 63727467 1360984
+63
+
+chain 3368 chr6_mann_hap4 4683263 + 3807881 3807940 chr10 135374737 - 122033518 122033577 24304357
+59
+
+chain 3334 chr6_mann_hap4 4683263 + 3942243 3942283 chr16 88827254 - 56809950 56809989 35201127
+19	1	0
+20
+
+chain 3303 chr6_mann_hap4 4683263 + 3972756 3972791 chr1 247249719 + 73729369 73729404 27153556
+35
+
+chain 3293 chr6_mann_hap4 4683263 + 4158373 4158408 chr7 158821424 - 26273345 26273380 30505739
+35
+
+chain 3293 chr6_mann_hap4 4683263 + 3825694 3825729 chr16 88827254 - 56536304 56536339 35220873
+35
+
+chain 3290 chr6_mann_hap4 4683263 + 2574386 2574448 chr8 146274826 + 34715687 34715749 20565863
+62
+
+chain 3284 chr6_mann_hap4 4683263 + 3962434 3962469 chr7 158821424 - 75715212 75715247 35222192
+35
+
+chain 3275 chr6_mann_hap4 4683263 + 1138144 1138179 chr6 170899992 + 29990315 29990350 35226053
+35
+
+chain 3266 chr6_mann_hap4 4683263 + 3971216 3971273 chr3 199501827 - 22333077 22333134 22107564
+57
+
+chain 3253 chr6_mann_hap4 4683263 + 4099622 4099676 chr19 63811651 + 42514641 42514695 4288250
+54
+
+chain 3205 chr6_mann_hap4 4683263 + 4070992 4071055 chr1 247249719 + 196464086 196464149 10251011
+63
+
+chain 3203 chr6_mann_hap4 4683263 + 3824817 3824851 chr3 199501827 - 28583100 28583134 30999626
+34
+
+chain 3180 chr6_mann_hap4 4683263 + 3893634 3893669 chr18 76117153 - 75290002 75290037 35254886
+35
+
+chain 3155 chr6_mann_hap4 4683263 + 4006480 4006566 chr8 146274826 - 94420792 94420878 3680803
+86
+
+chain 3107 chr6_mann_hap4 4683263 + 3887907 3887940 chr2 242951149 + 18209140 18209173 23522185
+33
+
+chain 3079 chr6_mann_hap4 4683263 + 2571537 2573841 chr6 170899992 + 126959071 126961365 3502977
+2	117	114
+67	2060	2053
+58
+
+chain 3064 chr6_mann_hap4 4683263 + 2303363 2303395 chr6 170899992 + 31062756 31062788 33922186
+32
+
+chain 3031 chr6_mann_hap4 4683263 + 3886413 3886445 chr2 242951149 + 186256011 186256043 29433855
+32
+
+chain 3016 chr6_mann_hap4 4683263 + 2311494 2311526 chrX 154913754 + 79124038 79124070 32077336
+32
+
+chain 2979 chr6_mann_hap4 4683263 + 3855470 3855504 chr3 199501827 + 4042271 4042305 1799588
+34
+
+chain 2964 chr6_mann_hap4 4683263 + 1196678 1196709 chrX 154913754 + 72461549 72461580 26677785
+31
+
+chain 2956 chr6_mann_hap4 4683263 + 3866093 3866129 chr1 247249719 - 141171387 141171423 35318155
+36
+
+chain 2906 chr6_mann_hap4 4683263 + 3932526 3932557 chr9 140273252 + 22587602 22587633 35284164
+31
+
+chain 2906 chr6_mann_hap4 4683263 + 3886745 3886778 chr8 146274826 - 118435747 118435780 35339754
+33
+
+chain 2872 chr6_mann_hap4 4683263 + 3971341 3971392 chr12 132349534 + 117591668 117591719 18400010
+51
+
+chain 2863 chr6_mann_hap4 4683263 + 2569913 2569984 chrX 154913754 + 15788619 15788690 15376547
+71
+
+chain 2850 chr6_mann_hap4 4683263 + 3872455 3872908 chr4 191273063 + 173531459 173531912 22440020
+66	326	326
+61
+
+chain 2847 chr6_mann_hap4 4683263 + 3886091 3886121 chr14 106368585 + 78698582 78698612 35350318
+30
+
+chain 2843 chr6_mann_hap4 4683263 + 4080743 4081595 chr9 140273252 + 76002383 76002587 2839818
+50	737	89
+65
+
+chain 2810 chr6_mann_hap4 4683263 + 3944503 3944532 chr1 247249719 - 39748406 39748435 35362931
+29
+
+chain 2797 chr6_mann_hap4 4683263 + 4484961 4485121 chr19 63811651 - 12967948 12968184 2658963
+29	70	70
+17	13	89
+31
+
+chain 2786 chr6_mann_hap4 4683263 + 3891682 3891777 chrX 154913754 - 85953788 85953883 2307593
+61	1	1
+33
+
+chain 2782 chr6_mann_hap4 4683263 + 2656861 2656923 chr8 146274826 - 144762871 144762933 15570304
+62
+
+chain 2778 chr6_mann_hap4 4683263 + 4115342 4115371 chr5 180857866 - 91122400 91122429 5117904
+29
+
+chain 2753 chr6_mann_hap4 4683263 + 1196549 1196608 chr12 132349534 + 50414483 50414542 22637630
+59
+
+chain 2740 chr6_mann_hap4 4683263 + 3887725 3887787 chr5 180857866 + 121612373 121612435 20400020
+62
+
+chain 2671 chr6_mann_hap4 4683263 + 2578539 2578598 chr9 140273252 - 60326471 60326530 21074054
+59
+
+chain 2624 chr6_mann_hap4 4683263 + 2643215 2643265 chr12 132349534 - 76880491 76880541 6796930
+50
+
+chain 2617 chr6_mann_hap4 4683263 + 4484579 4484636 chr11 134452384 - 70226060 70226117 2741353
+57
+
+chain 2617 chr6_mann_hap4 4683263 + 3951354 3951381 chrX 154913754 + 30529839 30529866 35092612
+27
+
+chain 2616 chr6_mann_hap4 4683263 + 3927817 3927913 chr6 170899992 - 159168046 159168142 3467812
+96
+
+chain 2596 chr6_mann_hap4 4683263 + 3973087 3973114 chr3 199501827 + 56590732 56590759 32896512
+27
+
+chain 2531 chr6_mann_hap4 4683263 + 3971895 3971925 chr3 199501827 + 180701028 180701058 25637788
+30
+
+chain 2466 chr6_mann_hap4 4683263 + 3824382 3824409 chr3 199501827 - 192093673 192093700 31748081
+27
+
+chain 2451 chr6_mann_hap4 4683263 + 3971666 3971716 chr2 242951149 + 181100921 181100971 18669842
+50
+
+chain 2440 chr6_mann_hap4 4683263 + 2572049 2572075 chr12 132349534 - 35755450 35755476 32394235
+26
+
+chain 2374 chr6_mann_hap4 4683263 + 3950266 3950291 chr1 247249719 - 157289487 157289512 35464629
+25
+
+chain 2364 chr6_mann_hap4 4683263 + 3819663 3819687 chr11 134452384 - 104747367 104747391 35468112
+24
+
+chain 2345 chr6_mann_hap4 4683263 + 2657279 2657339 chr9 140273252 + 101754649 101754709 22265309
+60
+
+chain 2313 chr6_mann_hap4 4683263 + 3890591 3890665 chr6 170899992 + 55285173 55285247 1894941
+74
+
+chain 2296 chr6_mann_hap4 4683263 + 2570274 2570347 chr10 135374737 + 81973802 81973875 17155090
+73
+
+chain 2290 chr6_mann_hap4 4683263 + 1157821 1157878 chr1 247249719 + 222604152 222604209 12152480
+57
+
+chain 2274 chr6_mann_hap4 4683263 + 3934768 3934792 chr3 199501827 + 107081622 107081646 35482673
+24
+
+chain 2265 chr6_mann_hap4 4683263 + 3887959 3887983 chrX 154913754 - 124439583 124439607 35484926
+24
+
+chain 2258 chr6_mann_hap4 4683263 + 3824852 3824876 chrX 154913754 - 132191215 132191239 25992080
+24
+
+chain 2257 chr6_mann_hap4 4683263 + 4006990 4007066 chr6 170899992 - 104582331 104582407 2576654
+76
+
+chain 2255 chr6_mann_hap4 4683263 + 4159118 4159146 chr8 146274826 + 40415014 40415042 30252789
+28
+
+chain 2253 chr6_mann_hap4 4683263 + 2653160 2653184 chr2 242951149 + 186158239 186158263 32681827
+24
+
+chain 2249 chr6_mann_hap4 4683263 + 4006455 4006480 chr5 180857866 - 144759522 144759547 4178637
+25
+
+chain 2214 chr6_mann_hap4 4683263 + 3971284 3971340 chr11 134452384 + 87181255 87181311 21919084
+56
+
+chain 2211 chr6_mann_hap4 4683263 + 3809943 3809993 chr20 62435964 - 30230318 30230368 23880964
+50
+
+chain 2210 chr6_mann_hap4 4683263 + 3835038 3835061 chr1 247249719 + 53077746 53077769 35492698
+23
+
+chain 2194 chr6_mann_hap4 4683263 + 1157606 1157646 chrX 154913754 - 101365357 101365397 11073773
+40
+
+chain 2181 chr6_mann_hap4 4683263 + 4081491 4081530 chrX 154913754 - 85175003 85175042 4116465
+39
+
+chain 2160 chr6_mann_hap4 4683263 + 3942219 3942243 chr1 247249719 - 214605983 214606007 35201144
+24
+
+chain 2156 chr6_mann_hap4 4683263 + 1145077 1145100 chr1 247249719 + 41331153 41331176 35506781
+23
+
+chain 2149 chr6_mann_hap4 4683263 + 4099822 4099870 chr9 140273252 + 102195866 102195914 4118428
+48
+
+chain 2146 chr6_mann_hap4 4683263 + 1143811 1143872 chr12 132349534 + 104221177 104221238 23825289
+61
+
+chain 2141 chr6_mann_hap4 4683263 + 4081286 4081346 chr20 62435964 - 10135341 10135401 5446947
+60
+
+chain 2127 chr6_mann_hap4 4683263 + 4045825 4045849 chr6 170899992 + 156402969 156402993 17746
+24
+
+chain 2123 chr6_mann_hap4 4683263 + 4007634 4007684 chr1 247249719 - 1324986 1325036 2693877
+50
+
+chain 2120 chr6_mann_hap4 4683263 + 3892019 3892104 chr14 106368585 + 35729289 35729374 2483709
+85
+
+chain 2099 chr6_mann_hap4 4683263 + 1196341 1196363 chr8 146274826 + 94956096 94956118 22553599
+22
+
+chain 2075 chr6_mann_hap4 4683263 + 4011497 4011566 chr6 170899992 - 138358121 138358190 21792053
+69
+
+chain 2039 chr6_mann_hap4 4683263 + 2571934 2572049 chr7 158821424 + 116148574 116148689 3252915
+115
+
+chain 2027 chr6_mann_hap4 4683263 + 3809848 3810361 chr5 180857866 - 108598115 108598712 24999557
+55	397	481
+61
+
+chain 2014 chr6_mann_hap4 4683263 + 4099976 4100031 chr3 199501827 + 188094551 188094606 22317615
+55
+
+chain 2010 chr6_mann_hap4 4683263 + 3935813 3935834 chrX 154913754 + 30529615 30529636 35529704
+21
+
+chain 2000 chr6_mann_hap4 4683263 + 1157778 1157811 chr4 191273063 + 153905795 153905828 8127682
+33
+
+chain 2000 chr6_mann_hap4 4683263 + 4158272 4158321 chr6 170899992 - 39092714 39092763 20395916
+49
+
+chain 1976 chr6_mann_hap4 4683263 + 1229873 1229899 chr9 140273252 + 92917708 92917734 26443005
+26
+
+chain 1931 chr6_mann_hap4 4683263 + 3926709 3926764 chr3 199501827 + 181243093 181243148 3766615
+55
+
+chain 1921 chr6_mann_hap4 4683263 + 4158321 4158373 chr11 134452384 + 132133410 132133462 17748702
+52
+
+chain 1919 chr6_mann_hap4 4683263 + 2511945 2511997 chr4 191273063 + 131153712 131153764 15450947
+52
+
+chain 1907 chr6_mann_hap4 4683263 + 2572521 2573169 chr12 132349534 - 49839290 49839926 3124499
+58	540	528
+50
+
+chain 1805 chr6_mann_hap4 4683263 + 3891144 3891220 chrX 154913754 + 107411806 107411882 2933427
+76
+
+chain 1798 chr6_mann_hap4 4683263 + 3870776 3870808 chr5 180857866 + 161128758 161128790 11651368
+32
+
+chain 1772 chr6_mann_hap4 4683263 + 4007367 4007430 chr16 88827254 - 2018363 2018426 2212652
+63
+
+chain 1763 chr6_mann_hap4 4683263 + 4080494 4080567 chr14 106368585 - 71004341 71004414 2917022
+73
+
+chain 1747 chr6_mann_hap4 4683263 + 2573669 2574306 chr1 247249719 + 71359925 71360557 7388765
+54	521	516
+62
+
+chain 1746 chr6_mann_hap4 4683263 + 3990700 3990741 chr6 170899992 + 88517978 88518019 3345644
+17	14	14
+10
+
+chain 1730 chr6_mann_hap4 4683263 + 2653102 2653160 chr15 100338915 + 50804927 50804985 23248991
+58
+
+chain 1696 chr6_mann_hap4 4683263 + 4006820 4006866 chrX 154913754 - 37494215 37494261 4107897
+46
+
+chain 1694 chr6_mann_hap4 4683263 + 4099748 4099799 chr1 247249719 + 46568424 46568475 18602659
+51
+
+chain 1690 chr6_mann_hap4 4683263 + 4158763 4158820 chr11 134452384 - 120264308 120264365 24918211
+57
+
+chain 1684 chr6_mann_hap4 4683263 + 3891607 3891668 chr9 140273252 - 45892574 45892635 2466690
+61
+
+chain 1664 chr6_mann_hap4 4683263 + 2656660 2656721 chr14 106368585 - 51104394 51104455 13584343
+61
+
+chain 1636 chr6_mann_hap4 4683263 + 3926463 3926504 chr15 100338915 - 30465019 30465060 3027934
+41
+
+chain 1600 chr6_mann_hap4 4683263 + 3973114 3973143 chr13 114142980 - 18785120 18785149 24380543
+29
+
+chain 1599 chr6_mann_hap4 4683263 + 3971096 3971159 chr8 146274826 + 126278291 126278354 19925893
+63
+
+chain 1591 chr6_mann_hap4 4683263 + 2511679 2511736 chr12 132349534 + 73083054 73083111 11729778
+57
+
+chain 1570 chr6_mann_hap4 4683263 + 4158461 4158521 chr12 132349534 + 40906087 40906147 15863002
+60
+
+chain 1569 chr6_mann_hap4 4683263 + 2569611 2569737 chr1 247249719 + 93626635 93626761 9616359
+126
+
+chain 1566 chr6_mann_hap4 4683263 + 3927068 3927110 chr4 191273063 - 20598961 20599003 3502725
+42
+
+chain 1557 chr6_mann_hap4 4683263 + 3927759 3927810 chrX 154913754 + 117055564 117055615 4598072
+51
+
+chain 1477 chr6_mann_hap4 4683263 + 3891945 3892006 chr10 135374737 + 87524787 87524848 2722375
+61
+
+chain 1473 chr6_mann_hap4 4683263 + 4080991 4081045 chr17 78774742 + 33000128 33000182 3754636
+54
+
+chain 1460 chr6_mann_hap4 4683263 + 3890832 3890888 chr8 146274826 + 57494812 57494868 2709746
+56
+
+chain 1455 chr6_mann_hap4 4683263 + 4007066 4007094 chr6 170899992 - 11011124 11011152 3343257
+28
+
+chain 1453 chr6_mann_hap4 4683263 + 3891391 3891437 chr8 146274826 + 51746327 51746373 3488858
+46
+
+chain 1424 chr6_mann_hap4 4683263 + 2571563 2571641 chr9 140273252 - 113447512 113447590 4199477
+78
+
+chain 1424 chr6_mann_hap4 4683263 + 3871462 3871507 chr1 247249719 - 200018115 200018160 11574863
+45
+
+chain 1406 chr6_mann_hap4 4683263 + 3890773 3890831 chr4 191273063 + 55621101 55621159 1970745
+58
+
+chain 1406 chr6_mann_hap4 4683263 + 4158521 4158575 chr1 247249719 + 49943386 49943440 15855508
+54
+
+chain 1397 chr6_mann_hap4 4683263 + 3890211 3890236 chr10 135374737 - 71340044 71340069 2299991
+25
+
+chain 1392 chr6_mann_hap4 4683263 + 3971636 3971666 chr3 199501827 - 51819316 51819346 23522768
+30
+
+chain 1373 chr6_mann_hap4 4683263 + 2511768 2511834 chr5 180857866 + 26360477 26360543 20230569
+66
+
+chain 1361 chr6_mann_hap4 4683263 + 4070248 4070282 chr4 191273063 + 53456808 53456842 4749510
+34
+
+chain 1354 chr6_mann_hap4 4683263 + 1158001 1158055 chr4 191273063 + 534307 534361 14280054
+54
+
+chain 1345 chr6_mann_hap4 4683263 + 3855264 3855317 chrX 154913754 + 62583130 62583183 22642552
+53
+
+chain 1311 chr6_mann_hap4 4683263 + 3990016 3990044 chr12 132349534 - 10940806 10940834 3119062
+28
+
+chain 1285 chr6_mann_hap4 4683263 + 2741741 2741814 chrX 154913754 - 101841552 101841726 4764485
+55	2	103
+16
+
+chain 1271 chr6_mann_hap4 4683263 + 4485264 4485308 chr2 242951149 + 42686810 42686854 6287037
+44
+
+chain 1232 chr6_mann_hap4 4683263 + 3891286 3891326 chr4 191273063 + 121886954 121886994 3320472
+40
+
+chain 1228 chr6_mann_hap4 4683263 + 4081088 4081138 chr7 158821424 + 22807318 22807368 2860523
+50
+
+chain 1216 chr6_mann_hap4 4683263 + 3886222 3886374 chr6 170899992 + 81566192 81566344 3344709
+59	17	17
+76
+
+chain 1200 chr6_mann_hap4 4683263 + 4080922 4080972 chrX 154913754 - 78005269 78005319 2937486
+50
+
+chain 1196 chr6_mann_hap4 4683263 + 2642964 2643022 chr13 114142980 - 87864434 87864492 20517842
+58
+
+chain 1192 chr6_mann_hap4 4683263 + 3871650 3871705 chr15 100338915 - 25838674 25838729 13558940
+55
+
+chain 1173 chr6_mann_hap4 4683263 + 3856498 3856532 chr11 134452384 - 32778066 32778100 22709110
+34
+
+chain 1168 chr6_mann_hap4 4683263 + 3891494 3891535 chr15 100338915 + 80079703 80079744 3327446
+41
+
+chain 1163 chr6_mann_hap4 4683263 + 3926838 3926870 chr6 170899992 + 66742660 66742692 3612231
+32
+
+chain 1163 chr6_mann_hap4 4683263 + 3887419 3887473 chrX 154913754 + 89074833 89074887 25104537
+54
+
+chain 1160 chr6_mann_hap4 4683263 + 2573343 2573371 chrX 154913754 + 56853117 56853145 21155199
+28
+
+chain 1149 chr6_mann_hap4 4683263 + 3856532 3856615 chr10 135374737 + 110407978 110408061 14842132
+83
+
+chain 1128 chr6_mann_hap4 4683263 + 2742956 2742992 chr13 114142980 - 41462025 41462061 4150569
+36
+
+chain 1122 chr6_mann_hap4 4683263 + 4080072 4080135 chr19 63811651 + 62685625 62685688 7787530
+63
+
+chain 1120 chr6_mann_hap4 4683263 + 3927728 3927759 chr20 62435964 + 16923180 16923211 7977510
+31
+
+chain 1120 chr6_mann_hap4 4683263 + 3887060 3887131 chr11 134452384 - 72766723 72766794 12188515
+71
+
+chain 1113 chr6_mann_hap4 4683263 + 2570192 2570259 chr2 242951149 - 140069145 140069212 8748780
+67
+
+chain 1096 chr6_mann_hap4 4683263 + 2643706 2643734 chr15 100338915 + 86869156 86869184 12823891
+28
+
+chain 1076 chr6_mann_hap4 4683263 + 3892300 3892346 chr11 134452384 + 14828539 14828585 2361427
+46
+
+chain 1041 chr6_mann_hap4 4683263 + 4080135 4080193 chr6 170899992 - 117620920 117620978 4257272
+58
+
+chain 1023 chr6_mann_hap4 4683263 + 4007334 4007366 chr9 140273252 + 86970417 86970449 7865338
+32
+
+chain 1010 chr6_mann_hap4 4683263 + 4082082 4082129 chr3 199501827 + 184810220 184810267 11973355
+47
+
+chain 998 chr6_mann_hap4 4683263 + 3886377 3886573 chrX 154913754 - 91757557 91757751 5295832
+36	35	33
+55	3	3
+67
+
+chain 990 chr6_mann_hap4 4683263 + 4007430 4007464 chr4 191273063 + 5326352 5326386 2516557
+34
+
+chain 984 chr6_mann_hap4 4683263 + 4072955 4073012 chr5 180857866 - 58582170 58582227 6154457
+57
+
+chain 967 chr6_mann_hap4 4683263 + 2573177 2573236 chr6 170899992 + 103362020 103362079 14394857
+59
+
+chain 965 chr6_mann_hap4 4683263 + 3891326 3891365 chr9 140273252 + 71286813 71286852 2824412
+39
+
+chain 945 chr6_mann_hap4 4683263 + 3694820 3694851 chr14 106368585 - 6650576 6650607 2401116
+31
+
+chain 927 chr6_mann_hap4 4683263 + 2572422 2572476 chr15 100338915 - 47557741 47557795 3382810
+54
+
+chain 920 chr6_mann_hap4 4683263 + 1157878 1157917 chr16 88827254 - 23604715 23604754 19693069
+39
+
+chain 898 chr6_mann_hap4 4683263 + 4081045 4081072 chr22 49691432 - 26647849 26647876 3840718
+27
+
+chain 895 chr6_mann_hap4 4683263 + 3891777 3891813 chr14 106368585 - 61283307 61283343 2761593
+36
+
+chain 893 chr6_mann_hap4 4683263 + 2570451 2570505 chr3 199501827 + 23577885 23577939 11107673
+54
+
+chain 890 chr6_mann_hap4 4683263 + 3892242 3892300 chr1 247249719 - 65356530 65356588 2061731
+58
+
+chain 880 chr6_mann_hap4 4683263 + 2570034 2570140 chr20 62435964 - 37396821 37396927 8091728
+106
+
+chain 869 chr6_mann_hap4 4683263 + 3887839 3887907 chr6 170899992 + 169492007 169492075 20963963
+68
+
+chain 868 chr6_mann_hap4 4683263 + 3891249 3891286 chrX 154913754 - 77282087 77282124 4725533
+37
+
+chain 836 chr6_mann_hap4 4683263 + 3890695 3890723 chrX 154913754 + 120843366 120843394 2304611
+28
+
+chain 836 chr6_mann_hap4 4683263 + 2570399 2570451 chr6 170899992 - 98122344 98122396 3449700
+52
+
+chain 827 chr6_mann_hap4 4683263 + 3855371 3855442 chr15 100338915 - 22701000 22701071 11814601
+71
+
+chain 815 chr6_mann_hap4 4683263 + 2572376 2572422 chr8 146274826 - 36260073 36260119 3779418
+46
+
+chain 812 chr6_mann_hap4 4683263 + 2571127 2571156 chr4 191273063 + 177039024 177039053 12879824
+29
+
+chain 785 chr6_mann_hap4 4683263 + 2569744 2569799 chr10 135374737 - 48892377 48892432 10678423
+55
+
+chain 771 chr6_mann_hap4 4683263 + 2573374 2573466 chr4 191273063 - 179199127 179199219 9189435
+92
+
+chain 767 chr6_mann_hap4 4683263 + 2511738 2511768 chr12 132349534 + 6687829 6687859 23736981
+30
+
+chain 753 chr6_mann_hap4 4683263 + 3873530 3873605 chr13 114142980 + 107345301 107345376 25181199
+75
+
+chain 746 chr6_mann_hap4 4683263 + 2572477 2572521 chrX 154913754 + 101830803 101830847 3498092
+44
+
+chain 715 chr6_mann_hap4 4683263 + 3891220 3891248 chr1 247249719 - 137161636 137161664 4268110
+28
+
+chain 711 chr6_mann_hap4 4683263 + 3892346 3892371 chr5 180857866 - 112926636 112926661 14369717
+25
+
+chain 705 chr6_mann_hap4 4683263 + 3891557 3891590 chr20 62435964 + 38686583 38686616 3341082
+33
+
+chain 701 chr6_mann_hap4 4683263 + 4158699 4158752 chr6 170899992 + 104136271 104136324 24904048
+53
+
+chain 698 chr6_mann_hap4 4683263 + 3885778 3885835 chrX 154913754 - 89052462 89052519 24703469
+57
+
+chain 694 chr6_mann_hap4 4683263 + 3890564 3890590 chr20 62435964 + 53857851 53857877 2569420
+26
+
+chain 686 chr6_mann_hap4 4683263 + 4080461 4080493 chr9 140273252 + 6612523 6612555 3647698
+32
+
+chain 684 chr6_mann_hap4 4683263 + 2569065 2569115 chr10 135374737 + 37248665 37248715 24627179
+50
+
+chain 630 chr6_mann_hap4 4683263 + 3887534 3887605 chr7 158821424 + 132658309 132658380 10507147
+71
+
+chain 626 chr6_mann_hap4 4683263 + 2571287 2571318 chr20 62435964 - 10143997 10144028 3304786
+31
+
+chain 604 chr6_mann_hap4 4683263 + 1158203 1158229 chrX 154913754 - 101148638 101148664 11583043
+26
+
+chain 598 chr6_mann_hap4 4683263 + 2573593 2573648 chr4 191273063 - 105845249 105845304 24500343
+55
+
+chain 587 chr6_mann_hap4 4683263 + 4081958 4081983 chr17 78774742 + 38379379 38379404 3048972
+25
+
+chain 582 chr6_mann_hap4 4683263 + 1229585 1229648 chrX 154913754 - 143767987 143768050 25106055
+63
+
+chain 511 chr6_mann_hap4 4683263 + 1158055 1158090 chr3 199501827 + 56593596 56593631 24560538
+35
+
+chain 500 chr6_mann_hap4 4683263 + 3810617 3810668 chr2 242951149 - 179547194 179547245 25332432
+51
+
+chain 484 chr6_mann_hap4 4683263 + 3874010 3874062 chr2 242951149 - 202196458 202196510 23986516
+52
+
+chain 477 chr6_mann_hap4 4683263 + 4080303 4080328 chr1 247249719 + 23702472 23702497 3860771
+25
+
+chain 433 chr6_mann_hap4 4683263 + 3970685 3970735 chr12 132349534 + 80047789 80047839 27634717
+50
+
+chain 409 chr6_mann_hap4 4683263 + 2572208 2572259 chr12 132349534 + 9890446 9890497 14217469
+51
+
+chain 405 chr6_mann_hap4 4683263 + 3838348 3838386 chr6 170899992 + 85325597 85325635 11867781
+38
+
+chain 400 chr6_mann_hap4 4683263 + 2570347 2570381 chr20 62435964 + 18791073 18791107 4207227
+34
+
+chain 399 chr6_mann_hap4 4683263 + 3891365 3891391 chr14 106368585 - 67199393 67199419 2293377
+26
+
+chain 392 chr6_mann_hap4 4683263 + 2573293 2573343 chr7 158821424 + 83182800 83182850 10714169
+50
+
+chain 389 chr6_mann_hap4 4683263 + 2574727 2574788 chr5 180857866 + 78276420 78276481 6835510
+61
+
+chain 320 chr6_mann_hap4 4683263 + 2572172 2572208 chrX 154913754 - 2978832 2978868 15103888
+36
+
+chain 315 chr6_mann_hap4 4683263 + 2572091 2572150 chr12 132349534 + 56700130 56700189 16626895
+59
+
+chain 314 chr6_mann_hap4 4683263 + 3838291 3838335 chr7 158821424 + 152689672 152689716 19362320
+44
+
+chain 313 chr6_mann_hap4 4683263 + 3838601 3838636 chr8 146274826 + 137657008 137657043 12505292
+35
+
+chain 281 chr6_mann_hap4 4683263 + 2568901 2568956 chr11 134452384 - 27880406 27880461 26521414
+55
+
+chain 157 chr6_mann_hap4 4683263 + 4157054 4157110 chr2 242951149 - 84321569 84321625 30149802
+56
+
+chain 327477534 chr6_mcf_hap5 4833398 + 0 4833398 chr6 170899992 + 28804582 33467620 43
+932	3	0
+804	0	1
+2406	2	0
+88370	0	6
+2011	17	17
+871	93	85
+100	12	14
+2623	33	29
+3737	1	1
+39	1	1
+3903	2	0
+844	0	1
+5198	0	1
+2452	0	1
+14547	0	1
+603	2	0
+4648	0	3
+887	2902	2902
+668	1	0
+3862	0	6
+1025	160	0
+3444	3	0
+1791	1	0
+2207	0	3
+1827	1	0
+3220	9	0
+5157	0	4
+1394	1	0
+279	0	2
+71	0	4
+163	1	1
+31	1	1
+280	8	0
+1059	0	2
+1373	40	40
+402	1	0
+642	1	3
+746	0	2
+1268	2	0
+267	0	1
+1868	1	1
+44	1	1
+8066	7328	7328
+1695	2	1
+4264	0	1
+3195	0	2
+2504	39	38
+70	1	1
+1649	1	0
+953	0	1
+295	1	1
+32	0	6
+661	4	0
+5298	1	0
+1243	1	0
+122	0	1
+6151	2	0
+1123	0	9
+2073	1	0
+611	1	0
+1053	5	5
+71	0	3
+562	11	11
+8681	53599	53599
+1476	0	3
+3442	1	1
+61	1	1
+472	1	0
+1606	1	0
+2825	1	1
+15	1	1
+2498	1	0
+1445	2	0
+3490	0	1
+31	1	1
+4168	1	0
+4249	0	3
+27	0	1
+660	1	3
+1336	2	1
+3805	1	1
+20	1	1
+2330	0	4
+782	0	3
+3397	0	3
+46	1	2
+2599	7	0
+167	0	1
+670	8	0
+686	13	15
+1313	1	1
+41	1	1
+5555	1	1
+31	1	1
+5562	0	11
+82	1	1
+1227	0	1
+1556	1	0
+817	2	0
+22	8	0
+11441	0	4
+2264	0	2
+2164	0	6
+5363	1	1
+20	1	1
+45	1	0
+1351	1	0
+1292	0	2
+6063	8	1
+3826	10	0
+7034	0	8
+1703	6	6
+72	20447	20447
+2264	0	3
+5437	5	0
+3414	35	35
+12896	0	4
+3018	1	1
+24	1	1
+2310	7	7
+11460	1	1
+28	1	1
+2157	0	4
+46	8	0
+8748	6	0
+8539	1	0
+753	1	2
+651	8	8
+7720	1	0
+2972	1	0
+6912	1	1
+26	1	1
+7721	68853	68853
+7209	1	0
+313	21	0
+2014	2	0
+631	1	1
+120	1	1
+1202	1	1
+84	0	1
+1481	10	0
+785	34	0
+493	0	2
+283	11	1
+513	67	67
+212	16	16
+1192	0	1
+3112	1	0
+25400	9	9
+6993	1	0
+675	1	0
+20032	0	3
+2544	0	318
+1507	2	0
+313	4	0
+2659	1	1
+25	1	1
+1461	4	1
+364	1	1
+33	1	1
+1003	0	1
+1656	1	1
+42	1	1
+3874	2	0
+149	0	1
+6897	0	3
+40	1	1
+1374	1	0
+5757	5	0
+1254	17	17
+2864	0	143
+4107	0	6
+5270	8989	8989
+14121	1	0
+19254	2	0
+7864	2	0
+635	1	0
+39010	1	0
+13943	1	1
+32	1	1
+509	1	1
+73	1	1
+5335	22	16
+1218	1	0
+1638	6	6
+228	1	1
+45	1	1
+2048	0	1
+463	1	0
+24243	1	1
+19	1	1
+7240	22	0
+3284	1	1
+29	1	1
+8552	0	4
+3962	7	16
+474	1	1
+31	1	1
+549	2	0
+5745	1	0
+5097	1	0
+34650	0	1
+16931	0	1
+2053	1	7
+1384	3	1
+442	3	4
+1804	1	1
+101	1	1
+1465	2	0
+1230	2	0
+3399	0	8
+743	0	1
+502	0	1
+732	0	1
+5371	0	1
+1633	6	5
+4859	0	1
+3043	0	1
+1108	0	2
+1448	1	0
+2959	10	10
+6054	0	4
+1927	18	24
+890	1	1
+16	1	0
+2617	2	0
+4921	1	0
+570	2	0
+8231	1	1
+25	1	0
+1193	0	11
+350	0	1
+4470	1	1
+41	1	1
+942	4	5
+1892	0	5
+15	1	1
+2144	1	1
+194	1	1
+938	0	1
+141	5	5
+237	3	8
+99	31	31
+53	11	0
+364	4	3
+201	1	1
+42	1	1
+56	1	1
+115	1	0
+67	16	16
+244	1	1
+54	5	5
+929	1	1
+21	1	1
+126	0	3
+830	0	14
+56	1	1
+525	0	2
+782	15	15
+810	1	0
+272	8	8
+145	1	1
+89	1	1
+592	1	1
+49	1	1
+352	0	1
+142	1	1
+30	1	1
+95	1	1
+45	1	1
+227	1	1
+53	1	1
+130	1	1
+18	1	1
+138	1	1
+90	1	1
+129	1	1
+39	1	1
+50	1	1
+79	1	1
+117	1	1
+31	1	1
+240	5	5
+57	1	1
+152	1	1
+30	1	1
+177	5	5
+345	1	1
+39	1	1
+504	18	18
+662	1	1
+74	1	1
+248	1	1
+34	1	1
+1507	0	10
+1051	0	2611
+680	0	1
+1537	0	19
+74	1	0
+137	50	11
+112	0	18
+24	1	1
+1927	13	13
+1082	15046	15046
+185	0	1
+70	1	1
+2835	4	4
+163	15	15
+685	0	1
+1508	1	0
+533	14	0
+441	0	13
+2121	1	1
+40	1	1
+2754	0	4
+37	1	1
+144	8	8
+1040	2	0
+28	1	1
+229	12	12
+201	13	13
+169	19	20
+118	10	12
+1257	0	2
+243	16	16
+73	1	1
+21	1	1
+201	0	14
+116	1	1
+29	1	1
+536	1	0
+1159	0	32
+23	1	1
+674	0	3
+136	1	1
+48	1	1
+330	9	9
+1108	1	1
+98	1	1
+582	0	2
+713	7	7
+89	1	0
+293	9	8
+350	6	6
+145	1	1
+41	1	1
+681	1	1
+43	1	1
+1121	16	16
+964	17	17
+198	0	7
+105	1	1
+40	1	1
+95	13	13
+247	1	1
+19	1	1
+2044	7	8
+2512	0	15
+2982	4	0
+3135	1	2
+1698	13	13
+15862	0	1
+925	0	191
+23	15	1
+23	0	1
+25	1	1
+7717	1	1
+40	1	1
+758	1	1
+46	1	1
+5530	11	9
+3326	1	1
+37	1	1
+2148	2	1
+4594	0	4
+7923	1	1
+26	5	5
+3475	24	0
+8	1	1
+566	4	0
+141	0	1
+2078	24	24
+171	18	18
+2570	0	6
+1709	4	0
+3265	0	2
+2235	17	16
+2946	0	372
+2644	31	31
+92	1	1
+35	1	1
+705	321	0
+3157	40	40
+718	0	4
+787	1	1
+34	1	1
+927	4	4
+103	0	8
+2376	0	1
+993	1	1
+31	1	1
+2654	1	1
+44	1	1
+208	4	1
+1022	11763	11699
+85	98	98
+60	2515	8169
+103	11	11
+41	1	1
+72	4	4
+76	1	1
+70	5	5
+83	1	1
+117	1	1
+130	1	1
+44	1	1
+414	1	1
+152	1	0
+218	1	1
+161	1	0
+120	14	14
+145	1	1
+49	4	4
+72	1	1
+53	19	19
+111	2	2
+32	3	3
+554	0	1
+336	12	12
+54	24	24
+171	0	6
+90	1	1
+28	1	1
+142	16	16
+36	1	1
+428	1	1
+16	1	1
+338	1	1
+31	1	1
+294	1	1
+92	0	1
+129	13	14
+602	1	1
+112	1	1
+247	1	1
+80	1	1
+173	1	1
+44	1	5
+497	1	1
+38	1	1
+98	1	1
+130	1	1
+319	1	1
+16	1	1
+59	1	1
+82	1	1
+141	1	1
+23	1	1
+241	1	1
+26	1	1
+109	3	3
+72	0	3
+19	1	1
+510	1	1
+36	1	1
+162	2	2
+15	1	1
+145	1	1
+28	1	1
+120	0	3
+93	1	2
+24	0	9
+169	12	0
+292	9911	10000
+401	1	1
+27	1	1
+296	1	1
+120	1	1
+357	1	1
+107	2	0
+31	1	1
+83	89	0
+194	1	1
+33	1	1
+230	1	1
+142	5	5
+108	1	1
+36	1	1
+287	1	1
+19	1	1
+104	1	1
+31	1	1
+144	1	1
+212	1	1
+452	5	6
+148	1	1
+70	1	1
+137	3	3
+67	1	1
+73	22	22
+115	12	12
+142	5	5
+269	15	15
+102	6	6
+93	1	1
+82	1	1
+170	1	1
+22	1	1
+504	2	2
+60	1	1
+150	1	1
+31	1	1
+90	1	1
+15	1	0
+258	6	7
+85	1	1
+77	1	1
+123	2	2
+67	0	1
+56	2	2
+25	1	1
+71	1	1
+28	2	2
+50	1	1
+85	2	2
+66	6	6
+186	1	1
+20	1	1
+67	1	1
+25	1	1
+227	2	2
+155	1	1
+777	1	1
+33	1	2
+26	6	6
+474	1	1
+36	1	1
+151	1	1
+29	1	1
+120	1	1
+23	1	1
+736	127279	40017
+51	5	5
+45	1	1
+53	1	1
+37	1	1
+81	1	1
+369	1	1
+72	15	15
+98	1	1
+53	0	8
+67	2	0
+41	1	1
+92	1	1
+20	1	1
+283	6	6
+70	7	7
+50	1	1
+25	1	1
+225	5	1
+31	1	1
+449	2	1
+10	1	23
+64	4	4
+832	1	0
+492	1	0
+587	0	15
+1821	1	1
+22	1	0
+36	1	1
+73	1	1
+38	1	1
+318	1	1
+20	1	1
+176	13	13
+216	1	1
+17	1	1
+515	0	1
+704	0	4
+153	1	1
+44	1	1
+538	1	1
+30	1	1
+411	0	8
+419	1	1
+34	1	1
+66	15	15
+308	1	1
+49	1	1
+484	1	1
+50	10	8
+1019	17	5
+132	1	1
+50	2	1
+38	1	1
+736	0	1
+50	1	1
+50	1	1
+23	2	1
+156	0	1
+385	15	15
+207	1	1
+92	1	1
+415	1	1
+43	1	1
+52	5	5
+223	2	0
+31	4	0
+17	3	27
+88	13	1
+308	1	1
+43	2	2
+186	0	4
+153	1	1
+69	0	3
+14	1	1
+159	1	1
+92	1	1
+62	1	1
+27	1	1
+443	10	10
+77	1	1
+51	1	1
+604	1	1
+35	1	1
+703	1	1
+32	1	1
+1452	4	0
+259	1	1
+40	1	1
+130	1	1
+87	1	1
+164	105	105
+64	14	15
+87	1	1
+30	1	1
+123	2	2
+91	0	3
+95	1	1
+67	10	0
+631	1	3
+315	1	1
+31	1	1
+315	1	1
+25	3	3
+80	3	0
+45	1	1
+511	1	1
+57	1	1
+3565	0	12
+39	0	1
+5674	16	0
+1327	0	1
+7941	1	1
+26	1	1
+13472	1	1
+48	1	1
+4441	19	0
+741	0	1
+8053	0	1
+3976	1	0
+10503	0	1
+5525	0	2
+306	1	0
+3902	17	4
+3077	0	4
+207	2	0
+1984	8	0
+686	2	0
+10068	0	3
+32266	0	2
+428	0	1
+3832	0	12
+8454	1	0
+524	1	1
+59	1	1
+112	3	3
+50	1	1
+267	0	4
+1464	2	0
+1003	0	1
+4062	1	0
+3850	4	0
+4977	0	1
+2718	1	0
+1588	1	1
+30	4	0
+879	0	1
+1332	18	12
+1688	4	4
+88	1	1
+439	2	0
+209	1	0
+1322	54	54
+893	1	1
+49	1	2
+1773	1	1
+24	1	1
+540	1	1
+41	1	1
+460	1	7
+165	1	1
+45	1	1
+903	1	2
+140	0	1
+36	1	1
+2019	0	1
+657	1	1
+48	1	0
+1329	0	1
+268	1	1
+47	1	1
+336	1	1
+25	2	0
+43	1	1
+1484	1	1
+53	1	1
+1151	1	1
+42	1	1
+1870	1	1
+24	5	5
+853	0	3
+23	0	1
+326	9	9
+131	9	9
+623	0	3
+34	1	1
+809	1	1
+36	1	1
+690	2	0
+44	1	1
+285	8	7
+455	1	1
+32	1	1
+102	1	1
+47	1	1
+4338	0	1
+5273	0	4
+11552	1	0
+409	16	17
+3476	0	1
+2160	0	24
+109	1	1
+3284	0	19
+2586	2	0
+757	1	1
+22	1	1
+860	17	24
+1584	1	0
+1582	0	2
+117	1	0
+1552	3	25
+17	0	4
+16	2	0
+6	10	0
+40	9	0
+10	8	0
+10605	1	0
+4733	1	3
+370	2	0
+1305	0	1
+518	6	0
+646	13	13
+469	1	0
+1072	1	4
+404	163747	163747
+942	4	0
+68	13	1
+2539	25	19
+1982	6	0
+5362	0	9
+10293	1	1
+98	1	1
+1006	1	1
+44	1	1
+518	1	1
+26	0	4
+185	0	1
+30	1	0
+19	1	1
+599	1	1
+22	1	1
+218	1	1
+49	1	1
+362	0	1
+852	0	2
+1066	0	2
+811	21	21
+1434	1	1
+27	1	1
+2116	1	1
+25	1	1
+82	7	7
+625	0	1
+1756	4	4
+93	1	1
+26	1	1
+320	0	3
+2150	1	1
+41	1	1
+1091	2	1
+8378	0	1
+2212	0	2
+671	1	0
+4088	1	1
+34	1	1
+2520	0	1
+1933	4	3
+2567	0	5
+1677	1	1
+29	1	1
+1829	12	0
+4788	13	0
+253	2	1
+204	0	1
+128	1	0
+4271	0	1
+6896	0	1
+2766	1	0
+2234	1	1
+52	1	1
+1098	1	1
+37	1	1
+3385	22337	22337
+10967	0	4
+6064	0	1
+10170	0	8
+17213	1	0
+6908	1	0
+328	1	0
+53416	3	2
+4463	1	0
+2057	0	1
+15162	1	0
+25886	3	1
+12500	29	0
+4926	0	1
+9038	0	1
+26499	0	1
+12538	0	1
+34918	97959	97959
+758	4	0
+150	1	0
+3128	1	0
+1300	0	1
+148	1	0
+1534	0	1
+488	0	1
+429	3	5
+299	2	0
+427	7	7
+1914	14	14
+1556	1	1
+28	1	1
+1138	78	0
+409	0	1
+985	22	23
+2430	1	0
+190	8	8
+2034	3	1
+5337	42	42
+1017	1	1
+34	1	1
+485	1	0
+348	7	0
+770	1	1
+8	1	0
+22	0	13
+64	1	1
+1358	0	1
+302	0	1
+964	0	1
+610	0	1
+906	12	0
+1331	0	8
+1784	0	1
+463	0	1
+4305	0	4
+1041	1	0
+11424	3	1
+530	10174	10174
+1857	0	1
+1230	0	8
+1682	5	0
+9069	0	8
+25	1	1
+330	5	5
+76	0	1
+1306	1	1
+46	1	1
+134	19	23
+1467	1	1
+32	1	1
+449	17	0
+367	9	9
+3525	12	10
+105	7	4
+208	33	33
+1171	1	1
+24	1	1
+1156	9	13
+841	3	3
+28	1	1
+515	0	17
+1559	0	4
+1045	9	9
+1953	1	0
+31	1	1
+843	0	1
+2174	1	0
+3788	1	0
+6017	1	0
+5658	4797	4797
+413	2	0
+2735	0	1
+941	4	0
+7767	0	1
+17211	5	0
+7531	0	1
+5505	1	2
+3443	0	2
+24240	1	1
+33	1	1
+4777	4	2
+43	3	0
+1254	0	1
+16	1	1
+1411	0	4
+424	1	1
+51	1	1
+113	1	1
+34	1	1
+344	9	9
+15845	1	0
+1155	1	0
+1648	0	16
+2071	0	9
+25450	1	0
+7543	4	10
+744	1	0
+564	2	0
+16701	3	0
+9132	1	1
+49	1	1
+146	1	1
+61	1	1
+116	1	1
+41	1	1
+137	1	1
+30	1	1
+158	9	9
+136	10	13
+973	6	6
+547	1	1
+41	1	1
+164	17	17
+1053	4	4
+228	1	1
+34	1	1
+355	1	1
+113	1	1
+330	0	1
+222	1	1
+25	1	1
+267	1	1
+38	1	1
+709	2	0
+1448	0	1
+152	1	1
+46	1	1
+237	1	1
+20	1	1
+211	5	5
+88	1	1
+33	1	1
+211	1	1
+65	1	1
+516	58	58
+491	7	7
+208	13	12
+558	2	2
+28	1	1
+125	4	4
+1853	21	0
+845	6	6
+2005	0	1
+148	1	1
+36	1	1
+993	1	0
+3580	10	10
+1203	1	0
+530	5	5
+216	1	1
+32	1	1
+312	1	1
+44	1	1
+1934	14	14
+1149	0	8
+835	1	1
+29	0	1
+2324	1	1
+18	1	1
+1273	27	27
+104	1	1
+21	1	1
+53	8	8
+1631	1	1
+16	1	1
+429	8	16
+1419	23	23
+256	1	0
+40	1	1
+106	1	1
+21	1	1
+501	2	2
+40	1	1
+2249	1	1
+189	0	1
+180	14	1
+1272	17	17
+345	0	2
+1504	14	0
+1689	4	0
+3174	16	16
+607	4	34
+41	0	5
+669	1	1
+25	1	1
+1926	1	1
+39	4	3
+1037	1	1
+40	2	0
+890	6	0
+41	2	0
+466	1	1
+31	3	0
+321	0	1
+281	3	0
+450	1	1
+34	1	1
+498	1	1
+28	2	1
+280	0	1
+649	1	1
+47	1	1
+1002	4	0
+120	1	1
+533	7	7
+998	0	1
+75	1	1
+37	1	1
+582	19	19
+60	18	18
+4194	0	2
+216	1	1
+112	1	1
+129	4	0
+87	1	1
+160	1	1
+49	1	1
+147	18	14
+128	1	1
+37	1	1
+865	4	0
+160	1	1
+35	1	1
+1119	1	1
+13	0	3
+242	1	1
+23	1	1
+1705	0	4
+103	0	1
+1117	2	0
+67	1	1
+1825	0	1
+855	8	0
+1368	3	0
+320	1	1
+149	1	1
+97	1	1
+15	1	1
+371	1	1
+165	1	1
+61	1	1
+32	0	2
+5	1	1
+1520	1	1
+28	1	1
+367	4	0
+267	13	13
+175	1	0
+225	1	1
+45	1	1
+797	1	1
+142	1	0
+38	0	2
+318	8	7
+50	1	1
+29	1	1
+376	4	9
+548	1	1
+57	1	1
+665	4	0
+1690	17	17
+208	6	6
+398	13	13
+63	1	1
+80	1	1
+57	1	1
+61	1	1
+170	1	1
+56	1	1
+93	1	1
+106	1	1
+41	1	1
+68	12	7
+13	4	0
+68	1	1
+76	1	1
+658	11	11
+447	4	4
+385	1	1
+35	1	1
+108	1	1
+37	4	0
+304	1	1
+70	1	0
+1242	12	12
+371	50	8
+386	2	0
+29	1	1
+204	1	1
+80	1	1
+112	12	11
+315	7	7
+97	0	2
+1756	1	1
+38	1	1
+106	23	23
+125	20	0
+1226	1	0
+16	5	0
+21	1	1
+235	10	10
+181	1	1
+72	1	1
+51	5	1
+43	5	7
+485	7	7
+127	1	1
+140	1	1
+105	5	6
+18	1	1
+88	1	1
+190	1	1
+68	10	10
+323	1	1
+59	4	0
+1507	3	0
+123	1	1
+73	1	1
+137	16	16
+132	1	1
+131	2	0
+5	0	3
+76	1	1
+40	1	1
+273	9	10
+172	1	1
+76	1	1
+98	1	1
+57	1	1
+54	1	0
+16	1	1
+66	1	1
+36	1	1
+120	1	1
+77	0	1
+34	1	1
+102	1	1
+41	1	1
+126	6	7
+1059	0	1
+1067	0	12
+1292	1	0
+744	0	4
+990	2	2
+58	1	1
+45	0	1
+308	1	1
+49	0	1
+21	1	1
+700	1	0
+973	2	0
+548	0	2
+982	10	0
+242	1	1
+38	1	1
+1067	3	0
+618	7	7
+1893	44	43
+731	2	2
+49	1	1
+908	9	9
+484	0	2
+128	0	1
+174	15	18
+175	1	1
+16	1	1
+332	1	1
+22	1	1
+554	0	1
+120	1	1
+31	1	1
+351	5	0
+80	1	0
+76	1	1
+39	1	1
+1447	1	0
+1072	1	1
+43	0	4
+43	1	1
+393	0	1
+1820	6	6
+457	1	1
+18	1	1
+87	1	1
+30	1	1
+861	1	1
+20	1	1
+1057	23	23
+416	0	24
+779	1	1
+17	1	2
+37	1	1
+1675	1	1
+27	1	1
+901	0	8
+47	1	1
+262	0	3
+57	1	1
+29	0	1
+234	0	3
+45	1	1
+250	1	1
+18	1	1
+517	33	0
+117	1	1
+55	1	1
+537	1	1
+20	1	1
+671	1	1
+68	1	1
+89	1	1
+104	1	1
+172	0	1
+124	0	1
+522	0	1500
+466	5	5
+32	1	0
+171	1	1
+19	1	1
+67	1	1
+22	1	1
+654	1	1
+25	1	1
+68	1	1
+21	4	0
+1588	1	1
+66	1	1
+401	0	1
+186	1	1
+21	1	1
+168	0	1
+601	1	1
+29	1	1
+36	4	0
+37	1	1
+127	1	1
+29	1	1
+404	0	2
+710	1	1
+89	1	1
+161	16	16
+405	1	1
+39	3	3
+56	1	1
+82	1	1
+71	1	1
+37	0	4
+104	1	1
+89	1	1
+64	1	1
+102	1	1
+130	15	16
+158	8	0
+57	1	1
+731	1	1
+65	1	1
+313	1	1
+44	1	0
+52	20006	20030
+60	8	8
+61	1	1
+120	1	1
+366	1	1
+55	1	1
+121	1	1
+62	1	1
+127	1	1
+18	1	1
+142	1	1
+26	1	1
+149	1	1
+62	11	11
+550	1	1
+76	1	0
+20	1	1
+112	1	1
+149	1	1
+284	1	1
+37	1	1
+705	1	12
+106	12	12
+1631	1	1
+47	1	1
+244	3	3
+22	3	3
+1486	0	3
+196	6	6
+63	1	1
+70	1	1
+325	14	19
+220	0	1
+773	1	1
+35	1	1
+153	1	1
+57	1	1
+123	1	1
+45	0	1
+15	1	1
+270	1	1
+48	1	1
+101	16	16
+64	1	1
+124	1	1
+1429	25	25
+184	0	1
+4315	4	4
+1530	4	0
+1062	1	1
+43	1	1
+55	14	14
+853	12	12
+2313	13	13
+537	9	0
+1430	1	1
+48	1	1
+400	1	1
+100	1	1
+148	19	19
+152	1	1
+25	1	1
+70	1	1
+102	1	1
+158	1	1
+56	2	2
+57	1	1
+10	5	10
+24	2	0
+71	1	1
+54	1	1
+73	1	1
+85	1	1
+105	1	1
+117	2	2
+29	1	1
+92	2	2
+42	0	1
+154	1	1
+10	1	0
+47	4	5
+35	1	1
+56	1	1
+64	3	3
+67	5	5
+72	1	1
+60	1	1
+45	1	1
+82	1	1
+95	2	2
+161	1	1
+301	1	1
+67	1	0
+430	1	1
+105	10	10
+38	0	4
+386	11	11
+101	3	2
+117	0	2
+77	1	1
+481	0	2
+67	1	1
+45	1	1
+503	1	1
+34	1	1
+359	1	1
+35	1	1
+534	11	11
+1738	1	1
+26	1	1
+506	19	0
+356	1	1
+138	0	3
+1403	13	13
+1045	1	1
+24	1	1
+879	1	1
+73	1	1
+89	1	1
+42	1	1
+108	1	1
+19	1	5
+41	0	1
+4	1	1
+511	5	6
+605	1	1
+47	1	1
+73	1	1
+62	1	1
+1912	49303	50027
+638	99452	99452
+4150	1	1
+31	0	1
+6	1	1
+163	1	1
+22	1	1
+81	1	1
+27	1	1
+548	1	1
+61	1	1
+1169	1	1
+41	1	1
+6471	1	1
+62	1	1
+530	17	17
+394	1	1
+40	7	0
+57	12	12
+69	2	2
+39	1	1
+70	1	1
+22	0	3
+2796	1	1
+58	1	1
+375	25	27
+1218	1	1
+35	1	1
+85	1	1
+20	6	0
+687	1	1
+34	1	1
+355	1	1
+47	1	0
+51	69	69
+73	1	1
+48	1	1
+218	1	1
+42	1	1
+197	1	1
+41	1	1
+313	1	1
+40	1	1
+476	1	1
+29	1	1
+185	1	1
+35	1	1
+594	1	1
+24	1	1
+219	2	0
+246	0	1
+261	4	4
+43	1	1
+54	1	1
+130	1	1
+184	1	1
+201	1	1
+306	1	1
+29	5	5
+121	1	1
+31	1	1
+109	1	1
+25	1	1
+168	1	1
+19	1	1
+104	1	0
+132	1	0
+113	1	1
+30	1	1
+56	9	9
+300	1	1
+50	2	2
+96	1	1
+43	1	1
+76	1	1
+44	1	1
+197	1	1
+38	2	1
+52	0	2
+18	1	1
+99	0	9
+392	5	5
+89	1	1
+399	1	1
+35	3	4
+260	1	1
+23	1	0
+10	1	1
+70	1	1
+65	2	0
+17	0	18
+28	1	1
+208	1	1
+70	1	1
+149	0	3
+243	1	1
+55	1	1
+63	17	17
+1208	1	1
+98	1	1
+58	1	1
+43	1	1
+59	1	1
+45	1	1
+148	70	70
+209	4	4
+1242	1	1
+42	5	0
+87	1	1
+522	0	3
+305	0	1
+1379	0	2
+390	0	15
+72	1	1
+16	1	1
+270	1	0
+280	7	7
+2763	20	20
+674	10	10
+1375	8	0
+294	142	141
+145	1	1
+35	1	1
+447	16	16
+54	4	4
+680	16	16
+1123	4	4
+1075	1	1
+46	1	1
+282	1	1
+39	1	1
+860	1	1
+26	1	1
+745	0	2
+2081	2	0
+817	4	4
+202	1	1
+48	1	1
+168	1	1
+53	1	1
+379	10	10
+1178	14	14
+135	5	0
+1169	1	1
+21	1	1
+462	1	1
+43	1	1
+121	1	1
+48	0	3
+16	1	4
+1404	0	1
+450	4	0
+626	1	0
+304	1	1
+39	1	1
+564	1	1
+45	1	1
+303	2	0
+409	1	1
+18	1	0
+858	3	0
+2168	0	1
+54	22	22
+220	1	1
+48	1	1
+254	0	1
+523	0	13
+2423	18	14
+64	1	1
+30	2	2
+185	0	4
+966	16	16
+123	11	11
+531	1	1
+20	1	1
+227	1	1
+37	1	1
+636	3	4
+8239	1	1
+23	1	1
+1114	0	2
+688	0	1
+901	18	18
+4781	0	4
+815	0	1
+5069	0	5
+415	0	1
+353	0	1
+1087	9	9
+108	30	30
+144	1	0
+817	1	0
+194	10	10
+460	0	1
+327	0	1
+878	0	1
+854	0	1
+4897	0	2
+1554	1	1
+60	1	1
+278	0	1
+19	1	1
+1866	0	1
+961	0	3
+60	0	18
+2122	0	2
+19	1	1
+1232	0	2
+1641	2	0
+10831	3	2
+188	0	1
+1650	3	6
+2842	0	4
+146	2	0
+4952	0	2
+4944	1	0
+1024	0	1
+803	11423	11423
+1739	0	4
+852	5	6
+1925	15	15
+1657	1	0
+378	0	2
+968	1	0
+1174	0	4
+663	6	0
+297	0	3
+2049	0	5
+876	11	11
+12081	1	1
+33	1	1
+1932	0	1
+398	1	1
+145	1	1
+3667	0	4
+1305	0	10
+3035	1	0
+5554	6	0
+42067	0	1
+4121	2	0
+13331	4	0
+2404	8	8
+1698	0	2
+19856	4	0
+1616	0	1
+1686	0	2
+2223	0	4
+4741	12	0
+1921	0	1
+913	0	1
+3801	0	1
+2620	8	0
+12800	0	1
+2431	1	0
+158	0	1
+281	1	0
+12653	1	0
+6938	0	1
+14766	1	0
+1654	34221	34221
+3000	17	17
+689	0	3
+62	1	0
+5716	1	0
+456	1	0
+2077	2	0
+616	178	0
+14916	0	4
+672	1	1
+26	1	1
+461	1	1
+33	0	2
+16	1	1
+649	1	1
+48	1	1
+818	1	1
+21	1	1
+424	1	1
+25	1	1
+632	1	1
+39	1	1
+310	1	1
+27	1	1
+616	1	0
+17240	4	0
+3936	3	0
+3834	2	0
+426	1	0
+5704	1	1
+43	1	0
+622	0	1
+167	0	5
+1968	0	3
+258	2	0
+4089	1	0
+903	29	27
+1088	7	6
+290	3	3
+117	13	0
+2194	0	1
+191	0	1
+118	1	0
+2013	1	0
+7453	1	0
+3382	0	1
+1544	0	1
+634	0	49
+5260	0	1
+4607	1	0
+32465	1	0
+1323	1	0
+39	0	1
+5117	27143	27143
+480	9	9
+746	11	11
+29289	0	3
+99	1	1
+19	1	1
+259	1	1
+57	1	1
+105	0	1
+2134	9	9
+2299	1	1
+43	1	1
+1287	1	0
+22328	5	0
+47	8	0
+4444	2	0
+6495	0	16
+2128	0	1
+8355	0	3
+4114	0	1
+1404	0	1
+5139	0	2
+1840	2	0
+1214	6	6
+273	0	7
+653	10	10
+189	1	0
+27280	0	2
+615	1	0
+1600	0	1
+364	0	2
+1466	1	0
+6628	1	1
+110	0	1
+1422	0	1
+324	1	0
+173	0	1
+1651	1	0
+311	0	1
+10202	4	0
+3867	9	7
+19808	0	2
+4947	29	29
+1283	0	3
+14175	10	0
+29	1	1
+4509	43	43
+1259	1	0
+2089	1	2
+365	0	2
+3430	1	0
+159	0	4
+2886	28	0
+147	0	1
+1181	10	15
+206	3	4
+208	1	1
+25	1	1
+2194	1	1
+18	1	1
+3726	0	3
+34	1	1
+361	17	17
+6271	1	0
+4854	0	1
+1587	0	1
+9534	1	1
+50	1	0
+1082	1	1
+42	1	1
+639	1	0
+145	13	15
+557	11	11
+53	1	1
+61	1	1
+454	1	1
+26	1	1
+1053	1	1
+60	1	1
+51	1	1
+26	1	0
+102	1	1
+67	1	1
+71	1	1
+134	1	1
+85	1	1
+607	36	0
+58	1	1
+1266	2	0
+480	14	21
+1459	2	1
+435	15	17
+224	57380	57335
+2665	46	46
+554	0	21
+4473	2	3
+921	1	1
+47	1	1
+2605	9	3
+50	1	1
+178	1	1
+26	1	1
+316	0	2
+1120	4	0
+177	1	2
+1991	4	4
+783	8	8
+61	34	13
+121	1	1
+22	1	0
+118	1	1
+49	4	4
+217	1	1
+91	1	1
+958	0	1
+107	1	1
+31	1	1
+171	14	14
+302	0	13
+33	1	1
+108	0	4
+98	1	1
+53	1	1
+457	2	0
+529	1	1
+37	2	0
+1829	1	1
+38	1	1
+440	1	1
+82	3	4
+647	45	45
+660	1	1
+28	1	1
+1993	0	1
+373	19	19
+835	1	1
+42	1	1
+947	1	1
+36	1	0
+1055	1	1
+43	1	1
+475	1	0
+60	1	1
+127	1	1
+509	1	1
+71	1	1
+485	1	0
+26	1	1
+531	1	1
+18	1	1
+551	1	1
+18	1	1
+884	5	5
+147	53	60
+527	1	1
+26	2	2
+322	0	17
+32	2	2
+85	1	1
+45	1	1
+625	0	323
+540	0	1
+43	1	1
+266	0	2
+228	1	1
+42	1	1
+283	1	1
+92	1	1
+381	1	1
+40	1	1
+1906	0	4
+3495	0	4
+967	1	1
+76	1	1
+3236	4	4
+529	7	7
+246	4	0
+38	1	1
+156	0	6
+1466	0	2
+499	1	0
+937	1	1
+45	1	1
+421	6	0
+87	22	22
+1254	1	1
+36	0	1
+357	18	18
+391	0	1
+451	1	0
+105	1	1
+47	1	0
+255	6	6
+739	3	0
+386	1	1
+33	1	1
+281	5	0
+481	2	0
+495	1	1
+42	4	0
+219	0	1
+408	1	1
+23	1	1
+283	1	1
+25	0	1
+541	1	0
+88	2	0
+216	1	1
+29	1	1
+457	1	0
+331	9	3
+197	15	15
+228	1	0
+4	2	0
+333	0	1
+19	1	1
+1081	3	3
+35	1	1
+1211	1	1
+34	1	1
+667	0	2
+64	1	1
+78	1	1
+1519	1	1
+27	1	1
+154	14	14
+1090	1	1
+40	0	3
+35	1	1
+1355	0	4
+79	1	1
+145	1	1
+63	1	1
+70	1	1
+21	1	1
+695	1	1
+41	2	2
+564	1	1
+46	1	1
+279	4	0
+38	5	5
+3523	32	32
+545	1	1
+27	1	0
+54	15	16
+1212	0	14
+34	0	11
+787	2	0
+3691	1	0
+1843	1	1
+45	1	0
+11	1	2
+3499	1	1
+27	1	1
+1047	0	2
+1804	2	0
+1079	1	1
+17	1	1
+639	3	5
+73	1	1
+13	13	0
+66	1	1
+391	0	7
+4547	0	1
+53	9	6
+691	0	1
+989	1	1
+143	1	1
+223	0	2
+95	1	1
+1000	1	1
+41	1	1
+93	1	1
+49	1	1
+606	1	1
+48	1	1
+128	0	4
+109	1	31
+44	10	781
+62	4	0
+129	1	1
+62	1	1
+106	1	1
+247	1	1
+20	18	4
+125	1	1
+43	1	1
+909	0	2
+381	4	4
+74	1	1
+408	1	0
+1595	5	0
+3690	1	1
+64	1	1
+754	0	4
+1877	1	1
+49	1	1
+1095	11	0
+732	0	27
+3070	2	0
+1879	0	1
+572	0	8
+215	1	1
+58	1	1
+301	1	1
+42	1	1
+265	24	0
+209	11	11
+953	1	1
+42	0	5
+58	1	0
+95	1	0
+210	1	1
+27	1	1
+882	1	1
+17	1	1
+751	0	1
+24	1	1
+351	1	1
+43	3	3
+565	1	1
+15	1	1
+150	27	27
+94	1	0
+323	1	1
+23	1	1
+221	7	7
+705	15	0
+631	2	0
+64	1	1
+1577	1	1
+21	0	1
+354	0	10
+188	0	1
+283	1	1
+48	1	1
+227	1	1
+40	0	3
+1357	0	2
+1571	7	7
+1153	1	1
+93	1	1
+797	14	14
+433	8	0
+108	11	11
+140	1	1
+40	1	1
+470	1	1
+42	1	1
+1106	0	2
+84	4	4
+129	1	1
+123	1	0
+95	1	1
+82	0	3
+661	1	1
+77	1	1
+57	1	1
+62	1	1
+473	2	0
+262	6	0
+45	1	1
+49	3	0
+321	0	1
+197	2	104
+202	0	10
+92	0	4
+108	6	0
+563	14	14
+324	1	0
+205	1	1
+17	1	1
+495	0	1
+201	4	0
+14	1	1
+1080	1	1
+24	1	1
+91	24	24
+279	1	1
+95	1	1
+121	1	1
+62	1	1
+2371	1	0
+164	9	1
+655	1	1
+30	1	1
+271	1	1
+47	1	1
+609	1	0
+1780	2	0
+742	1	1
+40	1	1
+272	1	1
+52	1	1
+1187	1	1
+23	1	1
+254	1	1
+60	1	1
+176	3	6
+463	1	1
+36	1	1
+797	1	1
+22	1	1
+395	5	2
+61	1	1
+31	3	3
+226	1	1
+59	1	1
+581	1	1
+46	1	1
+412	1	1
+23	1	0
+74	1	1
+17	1	1
+81	1	1
+24	1	1
+83	15	15
+363	1	1
+91	1	1
+383	20	20
+199	13	13
+976	1	1
+39	0	3
+161	14	15
+127	16	16
+517	1	1
+132	1	1
+167	28	28
+124	1	1
+68	0	22
+1074	0	1
+175	1	0
+1018	1	1
+90	4	4
+1034	15	15
+69	1	1
+33	1	1
+174	1	1
+56	1	1
+169	1	0
+201	1	1
+30	1	1
+58	1	1
+38	1	1
+91	1	1
+98	4	4
+65	1	1
+19	2	0
+104	6	5
+25	1	1
+218	1	1
+37	1	1
+343	110361	150022
+67	8	8
+36	0	11
+62	1	1
+107	1	1
+68	3	130
+66	4	4
+50	22	21
+98	1	1
+127	1	0
+192	1	1
+71	1	1
+52	1	1
+200	1	1
+307	0	1
+331	1	1
+97	11	11
+171	1	1
+61	1	1
+37	1	1
+156	3	0
+63	0	3
+155	4	1
+31	2	0
+232	1	1
+33	1	1
+175	2	0
+131	6	6
+1409	0	3
+180	1	1
+65	0	1
+703	1	1
+19	1	1
+254	1	1
+22	1	1
+424	1	1
+65	1	1
+532	1	1
+48	1	1
+347	0	12
+578	16	17
+965	1	1
+45	1	1
+893	57505	60106
+93	1	1
+75	808	0
+46	1	1
+221	1	1
+213	8	0
+63	1	1
+60	17	17
+53	1	1
+29	1	1
+68	8	8
+62	9	9
+51	1	1
+85	1	1
+101	1	1
+54	2	2
+116	1	1
+66	1	1
+182	1	0
+37	1	1
+134	14	14
+117	1	1
+45	1	1
+120	1	1
+47	1	1
+342	1	1
+46	1	1
+237	12	12
+107	8	8
+754	1	0
+880	1	1
+16	1	1
+491	1	1
+49	1	1
+192	1	1
+54	0	1
+19	2	2
+165	0	21
+26	1	1
+183	13	13
+72	1	1
+23	1	0
+268	14	14
+320	1	1
+55	1	1
+414	5	5
+172	0	1
+620	1	1
+18	1	1
+190	1	1
+20	0	8
+849	1	1
+29	1	1
+978	30198	30058
+159	1	1
+36	1	1
+107	1	1
+176	1	1
+154	0	5
+91	1	1
+54	1	1
+77	1	1
+239	1	1
+50	1	1
+128	1	1
+40	1	1
+173	11	11
+734	1	1
+31	1	1
+215	1	1
+108	1	1
+259	1	1
+79	1	1
+80	1	1
+47	3	1
+40	1	1
+54	1	1
+46	1	1
+118	9	9
+98	1	0
+5	11	4
+23	0	7
+84	1	1
+84	2	2
+6	0	1
+6	1	0
+110	0	7
+537	1	1
+96	1	1
+441	1	1
+101	1	1
+242	14	14
+255	16	16
+142	1	0
+345	10	10
+54	1	1
+26	1	1
+108	1	1
+83	1	1
+128	1	1
+36	1	1
+231	1	1
+37	1	1
+534	1	1
+60	1	1
+804	0	3
+43	1	1
+148	1	1
+25	1	1
+69	10	10
+76	5	5
+37	1	1
+66	0	2
+192	1	1
+60	3	0
+19	1	1
+1149	1	1
+18	1	1
+77	1	1
+32	2	0
+32	1	1
+136	1	1
+78	2	0
+1680	1	1
+39	0	1
+548	1	1
+50	1	1
+177	2	0
+340	1	1
+112	1	1
+422	10	10
+963	4	4
+329	1	9
+648	5	1
+117	1	1
+27	1	1
+574	1	0
+507	1	1
+39	1	1
+294	3	2
+549	1	1
+22	1	1
+74	0	1
+98	1	1
+65	3	3
+230	1	1
+18	1	0
+33	1	1
+51	1	1
+24	1	1
+811	1	1
+59	0	2
+8	1	1
+80	9	9
+437	14	14
+57	4	4
+588	15	15
+305	1	1
+17	1	1
+135	1	1
+50	1	1
+59	16	16
+129	1	1
+25	2	0
+12	1	1
+106	1	1
+31	1	1
+350	1	1
+47	1	1
+340	1	1
+65	1	1
+478	2	0
+714	8	7
+95	2	2
+52	2	1
+1129	1	1
+34	1	1
+1715	1	1
+87	1	1
+692	1	1
+47	0	1
+75	1	1
+2155	10	10
+1611	1	1
+22	1	1
+186	1	1
+34	1	1
+98	1	1
+47	1	1
+117	1	0
+185	1	1
+24	1	0
+98	0	2
+258	8	14
+967	1	1
+37	3	3
+502	1	1
+22	1	1
+75	0	3
+163	1	1
+40	1	1
+638	0	3
+150	1	1
+11	0	1
+29	1	1
+125	1	1
+78	1	1
+115	8	0
+1622	18	19
+1471	1	1
+30	1	1
+1580	73	73
+435	1	1
+60	1	1
+325	0	1
+254	1	1
+43	1	1
+181	14	0
+37	1	0
+47	1	1
+130	4	4
+34	1	1
+208	1	1
+39	2	2
+526	1	1
+36	1	1
+99	9	7
+20	1	1
+73	1	1
+62	1	1
+425	1	1
+43	1	1
+811	1	1
+38	1	1
+362	1	1
+49	1	1
+109	1	1
+19	1	1
+79	1	1
+29	0	1
+26	1	1
+252	1	1
+75	1	1
+467	1	1
+40	1	1
+389	13	13
+57	17	17
+544	1	1
+42	1	1
+597	0	311
+64	6	6
+568	1	1
+35	1	1
+62	1	1
+38	1	1
+79	1	0
+553	1	1
+30	1	1
+433	1	1
+16	3	0
+1133	12	12
+1503	14	14
+272	1	1
+41	1	1
+196	1	0
+571	1	1
+38	1	1
+813	18	19
+314	1	1
+22	1	1
+345	1	1
+23	3	0
+245	1	1
+129	1	1
+26	1	1
+435	1	1
+16	0	4
+323	1	1
+32	1	1
+247	1	1
+48	1	1
+778	2	0
+226	1	1
+61	1	1
+861	3	0
+471	4	0
+6220	3	0
+1351	18	18
+1560	1	0
+8099	1	0
+7388	0	5
+5386	0	1
+511	0	1
+599	0	6
+10541	11	21
+1909	16	16
+253	1	1
+16	1	1
+308	3	3
+27	1	1
+1333	0	3
+330	9	9
+600	2	0
+261	8	8
+5249	47	47
+4613	0	2
+2337	2	0
+2567	1	1
+26	1	1
+561	1	1
+48	1	1
+2440	1	1
+30	1	1
+1289	0	1
+162	1	0
+730	0	3
+663	1	0
+20	1	1
+1027	1	1
+43	1	1
+472	0	1
+219	1	1
+20	1	1
+495	1	0
+6	2	0
+1007	0	1
+169	0	10
+33	1	1
+1029	1	1
+30	1	1
+438	1	1
+39	1	1
+511	0	1
+1247	1	0
+1055	1	0
+491	1	0
+108	1	1
+48	1	1
+1324	0	1
+143	1	1
+40	1	1
+679	1	1
+45	1	1
+1036	0	1
+59	1	1
+46	1	1
+229	16	16
+149	10	10
+94	1	1
+63	1	1
+222	2	0
+55	1	1
+115	1	1
+219	15	15
+692	28	28
+159	1	1
+41	1	1
+211	1	0
+20	1	1
+1099	0	4
+28	13	12
+32	1	1
+60	1	1
+21	6	0
+178	13	15
+32	1	1
+953	1	1
+47	1	1
+174	1	1
+22	1	1
+401	0	13
+588	5	21
+288	4	4
+86	1	1
+29	0	2
+67	3	0
+641	0	1
+571	0	1
+250	1	1
+34	1	1
+255	0	2
+572	12	12
+275	6	1
+974	0	1
+578	12	12
+612	1	1
+43	1	1
+56	0	7
+1170	0	1
+477	4	3
+282	8	8
+466	0	4
+2118	5	0
+1090	0	2
+4424	1	1
+34	1	1
+4897	8	0
+2112	0	1
+2874	1	1
+21	1	1
+442	22	22
+805	0	1
+3476	10	0
+7129	3	0
+7475	0	4
+9494	2	0
+194	1	1
+49	1	1
+1349	22	22
+9662	2	0
+4856	3	0
+7447	6	6
+421	1	0
+884	6	0
+17	1	0
+3075	1	0
+14671	3	1
+3762	2	0
+601	2	0
+57	17921	17921
+1415	0	8
+42791	2	0
+100	2	0
+50	2	0
+13955	1	1
+272	1	1
+1137	1	0
+2261	16	15
+1824	1	0
+1990	1	0
+9965	0	18
+2951	6	0
+798	1	1
+30	1	1
+159	1	1
+124	1	1
+661	1	1
+31	1	1
+2632	4	4
+4024	0	16
+9373	7	7
+8626	0	1
+316	0	26
+10715	6	6
+110	1	1
+25	0	1
+3506	172081	34208
+1156	1	1
+161	1	1
+532	1	0
+698	2	0
+549	1	13
+287	1	1
+32	1	1
+1073	1	1
+22	6	0
+1829	3	923
+21	1	1
+721	1	1
+16	1	1
+1033	0	1
+10108	0	1
+10399	0	1
+14490	0	2
+3051	0	1
+6213	1	1
+26	1	1
+9064	26	26
+7722	3	0
+1957	2	0
+2288	1	0
+4470	0	4
+2115	1	0
+621	1	0
+563	0	2
+68	13	30
+160	18	19
+1807	0	2
+291	0	1
+2273	7	0
+2089	2	0
+479	1	0
+657	0	1
+772	4	0
+384	98	54
+779	0	2
+390	62	73
+1595	2	0
+1317	2	0
+5358	0	3
+2273	0	1
+597	0	8
+993	0	26
+1897	1	0
+76	0	1
+966	1	0
+2611	2	0
+1374	20	0
+831	33	33
+1574	0	2
+5096	0	3
+2404	1	1
+33	1	1
+507	4	0
+6366	0	25
+1550	0	5
+25133	1	0
+2111	0	1
+630	0	1
+784	0	1
+6989	1	0
+1116	0	1
+6270	0	1
+9520	1	0
+184	2	0
+328	1	0
+1089	1	0
+6600	0	1
+2450	1	0
+702	0	1
+5133	0	2
+3096	1	0
+315	1	0
+490	0	1
+684	9	9
+1895	3	0
+1013	0	1
+3659	1	0
+2412	1	2
+2723	4	0
+761	1	0
+22	0	1
+885	20	0
+5236	1	0
+2186	0	4
+1852	0	12
+991	0	1
+1091	0	1
+1006	1	0
+1699	0	1
+1682	1	0
+3693	1	0
+752	3	1
+497	5	6
+2292
+
+chain 61057 chr6_mcf_hap5 4833398 + 3953063 3953737 chr5 180857866 - 98127116 98127790 2061247
+526	1	1
+147
+
+chain 45613 chr6_mcf_hap5 4833398 + 2604717 2606756 chrX 154913754 + 17160000 17162038 2811400
+57	320	319
+92	373	373
+91	278	277
+94	320	320
+74	118	118
+78	42	43
+102
+
+chain 37022 chr6_mcf_hap5 4833398 + 2676816 2677228 chr7 158821424 + 107683864 107684276 3588094
+68	1	1
+54	1	1
+288
+
+chain 29722 chr6_mcf_hap5 4833398 + 1118803 1119113 chr7 158821424 + 38479558 38479868 4774007
+310
+
+chain 28137 chr6_mcf_hap5 4833398 + 3872548 3872872 chr18 76117153 - 36956533 36956857 5572699
+120	15	15
+189
+
+chain 28017 chr6_mcf_hap5 4833398 + 4025444 4025737 chr3 199501827 - 39984613 39984906 5625287
+293
+
+chain 26200 chr6_mcf_hap5 4833398 + 3998590 3999326 chr11 134452384 + 59999264 60000000 6424852
+154	126	126
+50	51	51
+57	235	235
+63
+
+chain 24804 chr6_mcf_hap5 4833398 + 1157807 1158609 chr7 158821424 - 51137320 51138288 7188387
+90	9	9
+79	101	101
+72	385	551
+66
+
+chain 21727 chr6_mcf_hap5 4833398 + 2690400 2690887 chr7 158821424 + 97232934 97233614 9179962
+159	171	400
+51	53	17
+53
+
+chain 21165 chr6_mcf_hap5 4833398 + 3891845 3892417 chr2 242951149 + 148617877 148618443 9563049
+63	162	156
+73	154	154
+120
+
+chain 20574 chr6_mcf_hap5 4833398 + 3328381 3329672 chr6 170899992 + 32089252 32090543 23930
+1291
+
+chain 19063 chr6_mcf_hap5 4833398 + 3948619 3949559 chr6 170899992 + 32821586 32822354 11222040
+175	715	543
+50
+
+chain 17270 chr6_mcf_hap5 4833398 + 3973147 3973355 chr10 135374737 - 70196080 70196288 12781660
+86	2	2
+48	5	5
+67
+
+chain 16223 chr6_mcf_hap5 4833398 + 3893015 3893224 chrX 154913754 - 4338266 4338475 13813426
+77	26	26
+106
+
+chain 15776 chr6_mcf_hap5 4833398 + 3956381 3966455 chr6 170899992 + 32827127 32836991 14253206
+50	4318	3617
+61	2558	2719
+69	660	1109
+229	767	762
+55	1248	1134
+59
+
+chain 15767 chr6_mcf_hap5 4833398 + 3201357 3201535 chr19 63811651 - 18495043 18495221 597719
+59	1	1
+45	1	1
+72
+
+chain 15397 chr6_mcf_hap5 4833398 + 4023860 4024020 chr7 158821424 + 63574132 63574292 14648759
+160
+
+chain 14519 chr6_mcf_hap5 4833398 + 3953825 3954073 chr3 199501827 + 161525390 161525638 4654449
+168	65	65
+15
+
+chain 14389 chr6_mcf_hap5 4833398 + 3863245 3863650 chr6 170899992 + 32665471 32665876 15746939
+57	86	85
+55	139	140
+68
+
+chain 13989 chr6_mcf_hap5 4833398 + 4038478 4038630 chr15 100338915 - 66378648 66378800 16209114
+152
+
+chain 13654 chr6_mcf_hap5 4833398 + 143599 143759 chr18 76117153 - 3498140 3498418 7857182
+83	1	1
+24	4	122
+48
+
+chain 12613 chr6_mcf_hap5 4833398 + 3848362 3848586 chr7 158821424 + 82112728 82112976 18070517
+51	77	101
+96
+
+chain 12612 chr6_mcf_hap5 4833398 + 3974617 3974791 chr6 170899992 - 53320727 53320901 18071926
+52	29	29
+93
+
+chain 12358 chr6_mcf_hap5 4833398 + 3995163 3995295 chr3 199501827 - 96522027 96522159 18443506
+132
+
+chain 12272 chr6_mcf_hap5 4833398 + 2612337 2612493 chrX 154913754 + 154847615 154847763 18572107
+71	1	1
+25	8	0
+51
+
+chain 12186 chr6_mcf_hap5 4833398 + 4038990 4039164 chr8 146274826 + 100984503 100984677 18706381
+68	32	32
+74
+
+chain 11876 chr6_mcf_hap5 4833398 + 2675238 2675454 chr6 170899992 + 31412979 31413204 19200916
+72	76	85
+68
+
+chain 11593 chr6_mcf_hap5 4833398 + 3844564 3844687 chr1 247249719 - 238369051 238369174 19677685
+123
+
+chain 11398 chr6_mcf_hap5 4833398 + 2686795 2686948 chr6 170899992 - 161606914 161607067 20013430
+64	22	22
+67
+
+chain 11324 chr6_mcf_hap5 4833398 + 3992779 3992926 chr6 170899992 - 138135992 138136139 20148163
+68	15	15
+64
+
+chain 10446 chr6_mcf_hap5 4833398 + 3869965 3870077 chr10 135374737 + 116791472 116791584 21828223
+112
+
+chain 9923 chr6_mcf_hap5 4833398 + 1132469 1132573 chr6 170899992 + 29984509 29984613 22990373
+104
+
+chain 9881 chr6_mcf_hap5 4833398 + 2664761 2665311 chr6 170899992 + 31313427 31313987 23083508
+72	423	433
+55
+
+chain 9817 chr6_mcf_hap5 4833398 + 3847924 3848156 chr8 146274826 + 42542364 42542493 23227154
+51	115	12
+66
+
+chain 9806 chr6_mcf_hap5 4833398 + 3846392 3846808 chr9 140273252 + 87960114 87960526 23254845
+57	294	290
+65
+
+chain 9661 chr6_mcf_hap5 4833398 + 3952556 3954131 chr6 170899992 + 104209491 104209913 3704454
+364	1153	0
+58
+
+chain 9564 chr6_mcf_hap5 4833398 + 3863653 3863818 chr6 170899992 + 32549657 32549823 23841400
+59	50	51
+56
+
+chain 9560 chr6_mcf_hap5 4833398 + 1145708 1145809 chr6 170899992 - 141000133 141000234 23851242
+101
+
+chain 9528 chr6_mcf_hap5 4833398 + 1160055 1160492 chr6 170899992 + 29878108 29878543 23937752
+59	318	316
+60
+
+chain 9472 chr6_mcf_hap5 4833398 + 3845655 3846032 chr1 247249719 - 150861000 150861377 24067468
+58	259	259
+60
+
+chain 9229 chr6_mcf_hap5 4833398 + 1293933 1294239 chr6 170899992 + 30567017 30567348 24575632
+62	194	219
+50
+
+chain 9124 chr6_mcf_hap5 4833398 + 3952955 3953063 chr3 199501827 + 1828344 1828452 9077956
+37	5	5
+66
+
+chain 9090 chr6_mcf_hap5 4833398 + 2611491 2611601 chr3 199501827 - 94209663 94209773 24799758
+53	4	4
+53
+
+chain 8464 chr6_mcf_hap5 4833398 + 2604519 2607426 chr2 242951149 + 56633977 56636883 3022124
+85	222	222
+134	2098	2097
+59	305	305
+4
+
+chain 8278 chr6_mcf_hap5 4833398 + 3861449 3861537 chr6 170899992 + 109538171 109538259 25991766
+88
+
+chain 8104 chr6_mcf_hap5 4833398 + 2618687 2620101 chr6 170899992 - 140880008 140881409 26266194
+74	1287	1274
+53
+
+chain 7774 chr6_mcf_hap5 4833398 + 2606022 2606534 chr1 247249719 + 7397644 7398156 2978583
+66	79	79
+58	214	214
+95
+
+chain 7592 chr6_mcf_hap5 4833398 + 3998745 3998829 chr8 146274826 + 68214220 68214304 9264343
+84
+
+chain 7141 chr6_mcf_hap5 4833398 + 3891766 3891845 chr12 132349534 + 113006300 113006379 12958594
+79
+
+chain 7041 chr6_mcf_hap5 4833398 + 3977312 3977387 chr4 191273063 + 139492368 139492443 28109801
+75
+
+chain 6949 chr6_mcf_hap5 4833398 + 3832393 3832466 chr6 170899992 + 32549387 32549460 28300224
+73
+
+chain 6795 chr6_mcf_hap5 4833398 + 2667263 2667335 chr6 170899992 + 31318116 31318188 28604524
+72
+
+chain 6658 chr6_mcf_hap5 4833398 + 3886931 3887001 chr5 180857866 - 20421148 20421218 28921167
+70
+
+chain 6650 chr6_mcf_hap5 4833398 + 3892813 3892896 chr11 134452384 - 10112929 10113012 19771549
+83
+
+chain 6648 chr6_mcf_hap5 4833398 + 3975186 3975255 chr12 132349534 - 72343253 72343322 28941661
+69
+
+chain 6613 chr6_mcf_hap5 4833398 + 3860999 3861069 chr1 247249719 + 37577726 37577796 29019074
+70
+
+chain 6545 chr6_mcf_hap5 4833398 + 3974547 3974617 chr9 140273252 - 54900636 54900706 21580040
+70
+
+chain 6522 chr6_mcf_hap5 4833398 + 3976253 3976322 chr15 100338915 + 41279078 41279147 29241047
+69
+
+chain 6504 chr6_mcf_hap5 4833398 + 3997726 3997795 chrX 154913754 - 101090292 101090361 29284261
+69
+
+chain 6494 chr6_mcf_hap5 4833398 + 2693655 2693723 chr6 170899992 + 30480336 30480404 29322144
+68
+
+chain 6459 chr6_mcf_hap5 4833398 + 2707667 2707736 chr6 170899992 + 31350859 31350928 29378028
+69
+
+chain 6376 chr6_mcf_hap5 4833398 + 3878588 3878655 chr1 247249719 - 291603 291670 29590708
+67
+
+chain 6368 chr6_mcf_hap5 4833398 + 2612245 2612337 chr6 170899992 - 132294381 132294479 20980271
+55	29	35
+8
+
+chain 6240 chr6_mcf_hap5 4833398 + 3861275 3861341 chr7 158821424 + 89136765 89136831 29917654
+66
+
+chain 6086 chr6_mcf_hap5 4833398 + 3886692 3886757 chr11 134452384 + 38517427 38517492 30319385
+65
+
+chain 5976 chr6_mcf_hap5 4833398 + 2710238 2710301 chr6 170899992 + 31358648 31358711 30614233
+63
+
+chain 5852 chr6_mcf_hap5 4833398 + 3892417 3892480 chr15 100338915 - 42450883 42450946 16059711
+63
+
+chain 5666 chr6_mcf_hap5 4833398 + 2692721 2692780 chr6 170899992 + 31328563 31328622 31482266
+59
+
+chain 5512 chr6_mcf_hap5 4833398 + 3860761 3860819 chr7 158821424 + 45670922 45670980 31905209
+58
+
+chain 5511 chr6_mcf_hap5 4833398 + 3953994 3954057 chr10 135374737 + 9454041 9454104 5673198
+63
+
+chain 5494 chr6_mcf_hap5 4833398 + 4010098 4010156 chr12 132349534 + 106784665 106784723 31946442
+58
+
+chain 5381 chr6_mcf_hap5 4833398 + 3848293 3848360 chr3 199501827 - 53390365 53390432 21843019
+67
+
+chain 5267 chr6_mcf_hap5 4833398 + 3861386 3861442 chr11 134452384 - 52779924 52779980 32661477
+56
+
+chain 5202 chr6_mcf_hap5 4833398 + 3975455 3975509 chr5 180857866 - 172710630 172710684 32856943
+54
+
+chain 5103 chr6_mcf_hap5 4833398 + 1145380 1145434 chr6 170899992 + 76955761 76955815 33170037
+54
+
+chain 5030 chr6_mcf_hap5 4833398 + 4010180 4010233 chr15 100338915 + 69519076 69519129 33389330
+53
+
+chain 5012 chr6_mcf_hap5 4833398 + 2695933 2695986 chr6 170899992 + 30481807 30481860 33454260
+53
+
+chain 4957 chr6_mcf_hap5 4833398 + 2608828 2608880 chr7 158821424 + 132662537 132662589 33651030
+52
+
+chain 4923 chr6_mcf_hap5 4833398 + 1157985 1158047 chr9 140273252 - 102391777 102391839 11227007
+62
+
+chain 4903 chr6_mcf_hap5 4833398 + 3886776 3886828 chrX 154913754 + 93227263 93227315 33852040
+52
+
+chain 4884 chr6_mcf_hap5 4833398 + 2690887 2690940 chr7 158821424 + 8665709 8665762 23124552
+53
+
+chain 4830 chr6_mcf_hap5 4833398 + 3870967 3871018 chr7 158821424 + 82104686 82104737 34087624
+51
+
+chain 4730 chr6_mcf_hap5 4833398 + 4037119 4037169 chr10 135374737 + 93200055 93200105 34443435
+50
+
+chain 4636 chr6_mcf_hap5 4833398 + 3953764 3953825 chr15 100338915 + 36217680 36217741 14854688
+61
+
+chain 4082 chr6_mcf_hap5 4833398 + 3861341 3861384 chr2 242951149 - 201903615 201903658 30854026
+43
+
+chain 3962 chr6_mcf_hap5 4833398 + 2605054 2607488 chr12 132349534 + 103308744 103311177 2987803
+40	116	116
+77	836	835
+44	1259	1259
+62
+
+chain 3938 chr6_mcf_hap5 4833398 + 3848731 3848772 chr12 132349534 + 106783136 106783177 34996470
+41
+
+chain 3860 chr6_mcf_hap5 4833398 + 3952301 3952346 chr3 199501827 + 112943878 112943923 15335435
+45
+
+chain 3596 chr6_mcf_hap5 4833398 + 3844515 3844564 chr19 63811651 + 37876836 37876885 21722630
+49
+
+chain 3519 chr6_mcf_hap5 4833398 + 3892776 3892813 chr10 135374737 + 82581588 82581625 28921113
+37
+
+chain 3457 chr6_mcf_hap5 4833398 + 3892907 3892997 chr5 180857866 + 79763558 79763648 18723404
+90
+
+chain 3302 chr6_mcf_hap5 4833398 + 2677228 2677268 chrX 154913754 - 17721831 17721871 3601717
+40
+
+chain 3266 chr6_mcf_hap5 4833398 + 3862147 3862182 chr9 140273252 + 83968215 83968250 35227644
+35
+
+chain 3215 chr6_mcf_hap5 4833398 + 2690311 2690345 chr13 114142980 - 34852829 34852863 33454154
+34
+
+chain 3191 chr6_mcf_hap5 4833398 + 2608477 2608530 chr16 88827254 + 57584329 57584382 22020535
+53
+
+chain 2914 chr6_mcf_hap5 4833398 + 3891647 3891703 chrX 154913754 + 119403135 119403191 11929641
+56
+
+chain 2795 chr6_mcf_hap5 4833398 + 3892480 3892522 chr15 100338915 + 56426321 56426363 16223719
+42
+
+chain 2771 chr6_mcf_hap5 4833398 + 2273985 2274017 chr16 88827254 + 61371572 61371604 11881975
+32
+
+chain 2705 chr6_mcf_hap5 4833398 + 3974669 3974698 chr5 180857866 + 34801294 34801323 21438495
+29
+
+chain 2671 chr6_mcf_hap5 4833398 + 2612185 2612244 chr9 140273252 - 60326471 60326530 21074056
+59
+
+chain 2599 chr6_mcf_hap5 4833398 + 1158047 1158085 chr7 158821424 - 126060947 126060985 11258554
+38
+
+chain 2590 chr6_mcf_hap5 4833398 + 3892269 3892297 chr5 180857866 - 137356848 137356876 18664742
+28
+
+chain 2589 chr6_mcf_hap5 4833398 + 3891454 3891482 chr11 134452384 - 49993356 49993384 29810036
+28
+
+chain 2555 chr6_mcf_hap5 4833398 + 2690245 2690311 chr18 76117153 + 25734423 25734489 18753960
+66
+
+chain 2509 chr6_mcf_hap5 4833398 + 2605481 2605558 chr3 199501827 - 153335243 153335320 3148850
+77
+
+chain 2466 chr6_mcf_hap5 4833398 + 2605403 2605466 chr2 242951149 + 186971340 186971403 6103613
+63
+
+chain 2459 chr6_mcf_hap5 4833398 + 3974791 3974822 chr14 106368585 + 48563076 48563107 22466897
+31
+
+chain 2459 chr6_mcf_hap5 4833398 + 3780767 3780793 chr17 78774742 - 42818294 42818320 32009757
+26
+
+chain 2427 chr6_mcf_hap5 4833398 + 2690989 2691048 chr3 199501827 - 193383909 193383968 24279045
+59
+
+chain 2365 chr6_mcf_hap5 4833398 + 4038809 4038866 chrX 154913754 + 103588329 103588386 22063660
+57
+
+chain 2350 chr6_mcf_hap5 4833398 + 1143959 1143987 chr9 140273252 + 98495373 98495401 22648903
+28
+
+chain 2348 chr6_mcf_hap5 4833398 + 2602541 2602596 chr7 158821424 + 35337254 35337309 23750584
+55
+
+chain 2343 chr6_mcf_hap5 4833398 + 3952502 3952527 chr11 134452384 - 60697549 60697574 22749508
+25
+
+chain 2320 chr6_mcf_hap5 4833398 + 4019609 4019634 chr19 63811651 - 56872967 56872992 35475512
+25
+
+chain 2317 chr6_mcf_hap5 4833398 + 2604190 2604320 chr15 100338915 - 72843171 72843301 3140919
+130
+
+chain 2262 chr6_mcf_hap5 4833398 + 1157783 1157807 chr19 63811651 - 5696072 5696096 21221761
+24
+
+chain 2188 chr6_mcf_hap5 4833398 + 1158201 1158258 chr1 247249719 + 222604152 222604209 12884993
+57
+
+chain 2183 chr6_mcf_hap5 4833398 + 3892590 3892636 chr7 158821424 + 113918927 113918973 16141801
+46
+
+chain 2172 chr6_mcf_hap5 4833398 + 3845632 3845655 chr3 199501827 + 38460301 38460324 24137330
+23
+
+chain 2171 chr6_mcf_hap5 4833398 + 3892683 3892706 chr13 114142980 - 13381431 13381454 25956368
+23
+
+chain 2132 chr6_mcf_hap5 4833398 + 2603254 2603380 chr1 247249719 + 93626635 93626761 5313263
+126
+
+chain 1996 chr6_mcf_hap5 4833398 + 2607152 2607223 chr3 199501827 + 178864208 178864279 4788720
+71
+
+chain 1952 chr6_mcf_hap5 4833398 + 3999028 3999070 chr2 242951149 - 218681061 218681103 8791220
+42
+
+chain 1946 chr6_mcf_hap5 4833398 + 1158400 1158475 chr1_random 1663265 - 1644029 1644104 12720667
+75
+
+chain 1930 chr6_mcf_hap5 4833398 + 3891482 3891539 chrX 154913754 + 81246238 81246295 14247869
+57
+
+chain 1927 chr6_mcf_hap5 4833398 + 2690365 2690400 chr7 158821424 - 109806767 109806802 24526345
+35
+
+chain 1921 chr6_mcf_hap5 4833398 + 4038367 4038423 chr11 134452384 - 48517870 48517926 18924823
+56
+
+chain 1856 chr6_mcf_hap5 4833398 + 1158158 1158191 chr4 191273063 + 153905795 153905828 9266241
+33
+
+chain 1833 chr6_mcf_hap5 4833398 + 2606939 2606989 chr9 140273252 + 84578242 84578292 7882125
+50
+
+chain 1827 chr6_mcf_hap5 4833398 + 3844483 3844515 chr10 135374737 - 122033518 122033550 24304365
+32
+
+chain 1796 chr6_mcf_hap5 4833398 + 2603994 2604348 chrX 154913754 + 100577502 100577856 3969599
+99	227	227
+28
+
+chain 1766 chr6_mcf_hap5 4833398 + 2690182 2690238 chr4 191273063 - 32209724 32209780 19175813
+56
+
+chain 1695 chr6_mcf_hap5 4833398 + 2604644 2604717 chr5 180857866 + 63682850 63682923 4402620
+59	4	4
+10
+
+chain 1651 chr6_mcf_hap5 4833398 + 3892522 3892590 chr11 134452384 + 18101372 18101440 12538366
+68
+
+chain 1629 chr6_mcf_hap5 4833398 + 4038630 4038657 chr2 242951149 - 84022333 84022360 21351212
+27
+
+chain 1606 chr6_mcf_hap5 4833398 + 3869684 3869743 chr4 191273063 - 166421863 166421922 24717461
+59
+
+chain 1597 chr6_mcf_hap5 4833398 + 3845427 3846126 chrX 154913754 - 128485360 128486059 24583609
+70	578	578
+51
+
+chain 1587 chr6_mcf_hap5 4833398 + 4039212 4039257 chr14 106368585 + 80426596 80426641 23776282
+45
+
+chain 1583 chr6_mcf_hap5 4833398 + 2676737 2676787 chr8 146274826 - 103361273 103361323 22022004
+50
+
+chain 1578 chr6_mcf_hap5 4833398 + 2686639 2686691 chr2 242951149 + 183623425 183623477 24278977
+52
+
+chain 1568 chr6_mcf_hap5 4833398 + 3998920 3998948 chr16 88827254 - 17543433 17543461 11021050
+28
+
+chain 1537 chr6_mcf_hap5 4833398 + 3999190 3999240 chr5 180857866 + 49878691 49878741 10672840
+50
+
+chain 1433 chr6_mcf_hap5 4833398 + 3999082 3999106 chr2 242951149 - 185977428 185977452 16089470
+24
+
+chain 1432 chr6_mcf_hap5 4833398 + 2607885 2607952 chr4 191273063 - 25455517 25455584 19723766
+67
+
+chain 1386 chr6_mcf_hap5 4833398 + 4037584 4037655 chr5 180857866 - 127160909 127160980 20252959
+71
+
+chain 1383 chr6_mcf_hap5 4833398 + 3892706 3892771 chr14 106368585 - 49729815 49729880 20850419
+65
+
+chain 1324 chr6_mcf_hap5 4833398 + 4038089 4038139 chr11 134452384 - 110737438 110737488 16281354
+50
+
+chain 1320 chr6_mcf_hap5 4833398 + 2607682 2607744 chr3 199501827 - 89080446 89080508 24774355
+62
+
+chain 1310 chr6_mcf_hap5 4833398 + 3891543 3891595 chrX 154913754 + 62583131 62583183 22867198
+52
+
+chain 1254 chr6_mcf_hap5 4833398 + 2605313 2605381 chr9 140273252 + 222427 222495 3502715
+68
+
+chain 1253 chr6_mcf_hap5 4833398 + 4038318 4038354 chr6 170899992 - 39092714 39092750 23906153
+36
+
+chain 1143 chr6_mcf_hap5 4833398 + 3998844 3998870 chr1 247249719 + 180123990 180124016 10456151
+26
+
+chain 1071 chr6_mcf_hap5 4833398 + 2603839 2603906 chr12 132349534 + 77415638 77415705 9437719
+67
+
+chain 1059 chr6_mcf_hap5 4833398 + 3952346 3952428 chr17 78774742 - 53522383 53522465 12152498
+82
+
+chain 1040 chr6_mcf_hap5 4833398 + 2603731 2603788 chr5 180857866 - 146041571 146041628 6664547
+57
+
+chain 1025 chr6_mcf_hap5 4833398 + 3892143 3892170 chr2 242951149 - 81435622 81435649 19840221
+27
+
+chain 1003 chr6_mcf_hap5 4833398 + 3731571 3731602 chr2 242951149 - 44758448 44758479 2126761
+31
+
+chain 978 chr6_mcf_hap5 4833398 + 1158258 1158286 chr6 170899992 - 112879191 112879219 17119903
+28
+
+chain 958 chr6_mcf_hap5 4833398 + 2606823 2606882 chr18 76117153 + 12161176 12161235 15243828
+59
+
+chain 919 chr6_mcf_hap5 4833398 + 2608035 2608095 chr4 191273063 + 44807134 44807194 22381057
+60
+
+chain 910 chr6_mcf_hap5 4833398 + 2604348 2604389 chrX 154913754 - 130647843 130647884 6306827
+41
+
+chain 899 chr6_mcf_hap5 4833398 + 3952444 3952502 chr9 140273252 + 66213924 66213982 10448615
+58
+
+chain 889 chr6_mcf_hap5 4833398 + 1158286 1158322 chr1 247249719 - 24894408 24894444 17913365
+36
+
+chain 857 chr6_mcf_hap5 4833398 + 4037505 4037565 chr20 62435964 - 51574691 51574751 25098794
+60
+
+chain 841 chr6_mcf_hap5 4833398 + 2603443 2603495 chr20 62435964 - 59823019 59823071 21526397
+52
+
+chain 825 chr6_mcf_hap5 4833398 + 2604460 2604519 chr7 158821424 + 140056560 140056619 5253720
+59
+
+chain 798 chr6_mcf_hap5 4833398 + 3846536 3846592 chr1 247249719 - 94337351 94337407 25194613
+56
+
+chain 791 chr6_mcf_hap5 4833398 + 2606765 2606815 chr2 242951149 + 171191285 171191335 4492406
+50
+
+chain 774 chr6_mcf_hap5 4833398 + 4038161 4038190 chr13 114142980 + 78421249 78421278 18219143
+29
+
+chain 760 chr6_mcf_hap5 4833398 + 2605737 2605796 chr12 132349534 + 56700130 56700189 25330835
+59
+
+chain 740 chr6_mcf_hap5 4833398 + 1158689 1158753 chr12 132349534 + 55464534 55464598 20832675
+64
+
+chain 725 chr6_mcf_hap5 4833398 + 2603907 2603961 chr2 242951149 + 129418481 129418535 15959343
+54
+
+chain 718 chr6_mcf_hap5 4833398 + 2608115 2608170 chr9 140273252 - 49339912 49339967 23555333
+55
+
+chain 716 chr6_mcf_hap5 4833398 + 4038745 4038797 chr16 88827254 - 38714794 38714846 22851160
+52
+
+chain 700 chr6_mcf_hap5 4833398 + 2604093 2604149 chr1 247249719 + 47033162 47033218 11748494
+56
+
+chain 697 chr6_mcf_hap5 4833398 + 2606088 2606122 chr18 76117153 + 57870219 57870253 3091588
+34
+
+chain 684 chr6_mcf_hap5 4833398 + 2603585 2603653 chrX 154913754 - 140171184 140171252 5395481
+68
+
+chain 681 chr6_mcf_hap5 4833398 + 4037371 4037428 chr8 146274826 - 64029404 64029461 24731946
+57
+
+chain 668 chr6_mcf_hap5 4833398 + 3815206 3815234 chr13 114142980 + 25366313 25366341 2606939
+28
+
+chain 607 chr6_mcf_hap5 4833398 + 2608345 2608426 chr12 132349534 + 61847837 61847918 15157322
+81
+
+chain 554 chr6_mcf_hap5 4833398 + 2607118 2607152 chr6 170899992 + 75108555 75108589 7134095
+34
+
+chain 547 chr6_mcf_hap5 4833398 + 2607779 2607829 chr11 134452384 - 79794459 79794509 15991278
+50
+
+chain 541 chr6_mcf_hap5 4833398 + 2605695 2605721 chr2 242951149 - 229173591 229173617 17449769
+26
+
+chain 537 chr6_mcf_hap5 4833398 + 2602778 2602824 chr20 62435964 + 38578434 38578480 23803873
+46
+
+chain 487 chr6_mcf_hap5 4833398 + 2603535 2603585 chr18 76117153 - 44468395 44468445 11618572
+50
+
+chain 479 chr6_mcf_hap5 4833398 + 3847219 3847270 chr8 146274826 - 91739126 91739177 25862760
+51
+
+chain 461 chr6_mcf_hap5 4833398 + 2607311 2607369 chr9 140273252 - 118104609 118104667 6129578
+58
+
+chain 456 chr6_mcf_hap5 4833398 + 2605822 2605854 chr10 135374737 + 51611354 51611386 20534292
+32
+
+chain 442 chr6_mcf_hap5 4833398 + 2602717 2602778 chr4 191273063 - 135500139 135500200 15116367
+61
+
+chain 412 chr6_mcf_hap5 4833398 + 2605854 2605905 chr12 132349534 + 9890446 9890497 14104676
+51
+
+chain 263 chr6_mcf_hap5 4833398 + 2604406 2604441 chr6 170899992 + 111492261 111492296 25439357
+35
+
+chain 227 chr6_mcf_hap5 4833398 + 2621672 2621728 chr6 170899992 - 140565854 140565910 28646895
+56
+
+chain 373682699 chr6_qbl_hap6 4611984 + 0 4611984 chr6 170899992 + 28804582 33487728 31
+932	3	0
+804	0	1
+2406	2	0
+210632	0	1
+14475	0	1
+6819	1	0
+6845	1	3
+6188	0	1
+6397	0	1
+345	1	0
+68374	2	0
+46946	7	0
+1489	1	1
+72	1	1
+2260	0	2
+10629	0	1
+19578	0	1
+1324	0	2
+5438	5	0
+2061	1	0
+3982	6	6
+1725	0	1
+3153	1	0
+18	1	0
+18	1	0
+2026	1	0
+4175	10	10
+4746	9	9
+4767	7	7
+1169	1	1
+55	1	0
+8	1	1
+151	1	2
+5079	1	1
+28	1	1
+249	43	43
+1178	0	4
+685	8	0
+48	4	0
+1701	1	1
+43	5	5
+862	18	18
+58	1	1
+66	1	1
+420	1	1
+44	1	1
+680	4	4
+1675	1	1
+83	1	1
+3082	4	0
+5467	1	1
+27	0	1
+1099	16	0
+627	12	12
+1317	6	1
+129	1	1
+25	1	1
+1397	15	15
+810	1	1
+27	1	1
+1192	2	0
+7515	4	0
+979	0	3
+3406	0	2
+2340	1	1
+20	1	1
+1139	1	1
+26	1	1
+787	0	1
+1416	3	1
+22815	4	4
+126	1	0
+38	1	1
+140	1	0
+999	0	17
+56	0	15
+11759	163412	163534
+9134	0	2
+5376	0	1
+19253	1	0
+7884	1	0
+21	0	6
+4451	1	0
+27910	1	0
+9946	0	1
+11233	1	1
+32	1	1
+2238	1	1
+20	1	1
+3659	22	16
+1218	1	0
+1638	6	6
+228	1	1
+45	1	1
+2048	0	3
+461	1	0
+20759	1	0
+3778	2	1
+1268	1	0
+1511	1	1
+42	2	0
+24	1	1
+4119	22	0
+1757	1	0
+1527	1	1
+29	1	1
+1886	1	0
+10628	12	0
+46568	1	0
+18985	0	10
+1825	3	4
+5288	0	9
+2728	1	5
+722	0	1
+502	0	1
+1025	0	1
+134	14	0
+4944	0	1
+319	1	0
+6178	0	1
+2898	0	2
+143	0	1
+1775	1	0
+2123	0	1
+2715	1	0
+4921	1	1
+47	4	0
+2882	1	0
+1362	1	0
+1233	0	8
+2134	0	1
+1042	0	1
+163	1	1
+45	1	1
+50	2	0
+64	1	1
+48	1	1
+380	0	1
+30	1	0
+30	1	1
+61	1	1
+22	1	1
+691	5	7
+310	1	1
+37	3	1
+162	1	1
+194	2	0
+36	1	1
+242	9	9
+697	33	33
+1202	1	1
+16	1	1
+528	1	1
+20	1	1
+509	0	5
+76	1	1
+21	1	1
+439	15	15
+2779	1	0
+1597	24	28
+59	12	12
+307	1	0
+516	1	0
+286	11	33
+339	5	0
+570	1	1
+37	1	1
+220	1	0
+72	1	1
+144	1	1
+48	1	1
+247	2	0
+174	9	10
+816	1	0
+940	1	1
+45	1	1
+91	3	3
+71	1	1
+291	14	14
+100	1	1
+23	1	1
+452	3	3
+229	1	1
+252	0	1
+129	15	15
+432	10	0
+85	1	1
+28	1	1
+189	2	1
+71	1	1
+52	8	0
+810	2	2
+63	1	1
+378	1	1
+26	1	1
+187	31	36
+966	1	1
+25	1	1
+91	12	12
+125	1	1
+38	1	1
+433	2	0
+596	1	1
+48	1	1
+465	4	4
+64	1	1
+20	1	1
+525	5	5
+237	3	8
+99	31	31
+53	11	0
+364	4	3
+201	1	1
+42	1	1
+56	1	1
+115	1	0
+67	16	16
+244	1	1
+54	5	5
+929	1	1
+21	1	1
+126	0	3
+830	1	11
+59	1	1
+537	0	2
+24	1	1
+745	15	15
+810	1	0
+425	1	1
+89	1	1
+592	1	1
+49	1	1
+352	0	1
+142	1	1
+30	1	1
+95	1	1
+45	1	1
+227	1	1
+53	1	1
+130	1	1
+18	1	1
+138	1	1
+90	1	1
+129	1	1
+39	1	1
+50	1	1
+79	1	1
+117	1	1
+31	1	1
+155	155	0
+34	1	1
+50	5	5
+57	1	1
+152	1	1
+30	1	1
+177	5	5
+345	1	1
+39	1	1
+504	18	18
+596	12	12
+54	1	1
+158	1	1
+164	1	1
+34	1	1
+626	15	15
+866	0	10
+1051	0	2611
+680	0	1
+1537	0	18
+75	1	0
+147	52	1
+119	0	12
+23	1	1
+1927	13	13
+1702	2	0
+3694	1	1
+18	1	1
+958	43	47
+246	2	0
+146	1	1
+49	1	1
+410	1	0
+667	1	1
+38	1	1
+362	7	1
+159	2	0
+515	2	0
+1026	1	1
+29	1	1
+249	0	6
+129	1	1
+33	4	0
+10	1	5
+1236	1	1
+20	1	1
+138	10	9
+448	0	3
+660	1	1
+28	1	1
+83	1	1
+51	1	1
+2659	1	1
+38	1	1
+424	0	1
+70	1	1
+820	1	1
+26	1	1
+1472	1	1
+21	1	1
+491	5	5
+163	15	15
+2194	2	0
+533	6	0
+441	1	7
+1689	1	1
+26	3	4
+879	16	16
+514	0	2
+58	1	1
+350	1	0
+769	1	1
+39	1	1
+573	0	4
+37	1	1
+144	8	8
+668	1	1
+22	1	1
+344	2	0
+262	2	2
+38	0	1
+70	18	18
+84	11	13
+169	62	63
+74	11	15
+1255	0	2
+332	1	1
+21	1	1
+193	8	24
+34	1	1
+79	1	1
+29	1	1
+536	1	0
+308	0	1
+850	0	32
+23	1	1
+651	1	1
+22	0	3
+136	1	1
+48	1	1
+330	9	9
+1108	1	1
+98	1	1
+582	0	2
+713	7	7
+89	1	0
+293	9	8
+125	1	1
+31	1	1
+192	6	6
+171	17	17
+681	1	1
+43	1	1
+514	1	1
+68	1	1
+537	1	1
+35	1	1
+159	6	6
+778	2	2
+44	1	1
+168	0	7
+211	1	1
+42	1	1
+1253	1	1
+29	1	1
+320	1	1
+36	2	2
+55	1	2
+108	1	1
+33	1	1
+317	1	1
+35	1	1
+553	8	8
+386	1	1
+26	1	1
+540	1	1
+31	1	1
+65	0	1
+625	12	12
+313	0	1
+52	1	1
+22	1	1
+583	1	1
+49	1	1
+1499	3	0
+838	1	1
+19	12	0
+1129	1	1
+36	1	1
+553	8	8
+109	1	1
+45	1	1
+841	16	15
+157	1	1
+31	2	2
+204	18	19
+487	1	1
+29	1	1
+374	1	1
+67	1	1
+720	13	13
+266	10	10
+330	16	14
+413	1	1
+44	1	1
+78	6	6
+181	2	2
+36	1	1
+397	1	1
+20	1	1
+311	1	1
+48	2	2
+1495	1	1
+33	1	1
+216	4	4
+35	1	1
+194	10	10
+310	1	1
+51	1	1
+84	1	1
+101	1	1
+521	1	1
+23	1	1
+242	51	51
+600	1	1
+31	1	1
+413	15	15
+290	1	1
+49	1	1
+527	17	17
+340	12	11
+1025	1	0
+2572	1	1
+29	1	1
+397	2	5
+668	13	13
+541	1	1
+59	0	2
+6	1	1
+122	14	14
+51	1	1
+46	1	1
+187	1	1
+76	1	1
+164	0	21
+136	1	1
+12	1	1
+66	16	16
+456	37	34
+371	7	7
+48	1	1
+194	10	10
+108	1	1
+60	1	1
+122	49	50
+238	1	1
+32	0	1
+100	1	0
+72	1	0
+390	1	1
+38	1	1
+144	1	1
+27	0	4
+184	21	228
+49	1	1
+608	0	1
+152	1	1
+31	1	1
+281	8	8
+337	1	1
+45	1	1
+222	1	1
+54	1	1
+346	1	0
+44	1	1
+368	1	1
+72	1	1
+502	36	18
+63	1	1
+43	0	4
+136	1	1
+42	1	1
+80	4	4
+35	1	0
+89	1	1
+24	0	5
+829	13	13
+73	1	1
+28	14	0
+233	1	1
+42	0	3
+85	0	1
+400	1	1
+40	1	1
+538	25	25
+174	1	1
+20	1	1
+705	1	1
+26	2	2
+614	1	1
+44	1	1
+793	1	1
+16	1	1
+99	38	38
+610	5	5
+804	1	1
+29	1	1
+166	1	1
+43	1	1
+233	1	1
+44	1	1
+507	0	3
+110	8	8
+133	1	1
+31	1	1
+165	1	1
+29	1	1
+1249	1	1
+26	4	0
+56	1	1
+67	1	1
+716	1	1
+46	0	1
+16	1	1
+174	1	1
+96	1	1
+141	1	1
+39	0	4
+263	1	1
+18	1	1
+259	4	4
+38	1	1
+104	1	1
+40	1	0
+248	1	1
+18	1	1
+238	1	1
+32	1	1
+70	0	2
+16	1	1
+818	1	1
+22	4	4
+492	4	4
+1145	1	1
+46	1	1
+53	1	0
+38	1	1
+373	62	62
+1149	0	1
+20	1	1
+1294	1	1
+41	1	1
+316	4	4
+42	1	1
+218	12	12
+363	1	1
+24	1	1
+457	10	10
+414	13	13
+825	1	1
+41	1	1
+492	0	4
+1374	1	1
+18	1	1
+1145	6	4
+880	1	1
+35	1	1
+236	1	1
+67	1	1
+298	0	1
+147	14	14
+312	11	11
+613	1	1
+62	1	1
+340	1	1
+22	1	1
+1057	1	1
+57	1	1
+358	1	1
+128	1	1
+146	10	10
+490	1	1
+20	1	1
+62	1	1
+88	1	1
+293	1	1
+28	1	0
+20	1	1
+83	0	1
+90	1	1
+312	1	1
+44	1	1
+1213	1	1
+51	1	1
+467	1	1
+39	1	1
+122	14	0
+35	1	1
+485	14	14
+110	12	0
+127	1	1
+5450	0	5
+1699	9	9
+3278	0	2
+28	1	1
+2195	18	16
+521	1	1
+18	1	1
+784	18	18
+1603	0	248
+9302	4	4
+72	1	1
+30	0	2
+2359	1	1
+22	0	1
+1244	7	7
+922	2	0
+1507	1	1
+44	1	1
+208	6	1
+1022	34244	40039
+401	1	1
+27	1	1
+369	1	1
+47	1	1
+256	1	1
+27	1	1
+72	1	1
+107	2	0
+21	1	1
+93	89	0
+194	1	1
+33	1	1
+230	1	1
+142	5	5
+108	1	1
+99	1	1
+349	1	1
+31	1	1
+144	1	1
+155	1	1
+56	1	1
+46	1	1
+405	5	6
+148	1	1
+70	1	1
+137	3	3
+67	1	1
+73	22	22
+115	12	12
+142	5	5
+269	15	15
+102	6	6
+93	30	30
+224	1	1
+22	1	1
+459	1	1
+106	1	1
+150	1	1
+50	1	1
+71	1	1
+15	1	0
+258	6	7
+117	1	1
+45	1	1
+123	2	2
+49	1	1
+173	1	1
+28	2	2
+50	1	1
+158	1	1
+186	1	1
+20	1	1
+67	1	1
+25	1	1
+227	2	2
+155	1	1
+777	1	1
+33	1	2
+26	6	6
+474	1	1
+36	1	1
+151	1	1
+29	1	1
+120	1	1
+23	1	1
+736	17	17
+112	1	1
+39	1	1
+553	1	1
+69	1	1
+116	1	0
+1618	9	9
+820	11	11
+173	0	8
+405	9	9
+196	1	1
+26	1	1
+173	1	1
+27	5	1
+42	1	1
+676	17	19
+77	1	3
+65	16	16
+69	1	0
+277	1	1
+44	1	1
+72	0	3
+70	1	1
+54	1	1
+240	1	0
+31	1	1
+1192	18	19
+454	28	28
+373	1	1
+46	1	1
+1565	1	1
+53	2	2
+543	1	1
+38	1	1
+985	1	1
+27	0	1
+8	1	1
+158	0	38
+656	1	1
+104	1	1
+771	1	1
+21	1	1
+398	1	1
+16	1	2
+163	4	3
+94	1	1
+44	1	1
+172	1	0
+122	5	5
+193	16	16
+535	2	2
+17	1	0
+93	1	1
+580	1	1
+91	1	1
+141	1	1
+79	1	1
+80	13	13
+165	1	1
+129	1	1
+114	1	1
+30	1	1
+83	1	1
+35	1	1
+126	16	16
+270	0	1
+111	9	9
+151	1	1
+118	1	1
+253	1	1
+45	20456	22239
+51	5	5
+45	1	1
+53	1	1
+37	1	1
+157	1	1
+279	1	1
+233	1	1
+19	0	8
+67	2	0
+41	1	1
+102	12	12
+275	14	14
+70	1	1
+82	2	2
+224	5	1
+490	0	22
+3841	1	0
+3216	1	1
+42	1	1
+1914	0	3
+616	11	12
+144	1	1
+21	2	1
+775	1	1
+50	1	1
+50	2	2
+96	2	2
+1522	4	0
+58	0	2
+1099	1	1
+42	1	1
+3502	0	6
+255	1	1
+40	1	1
+150	0	4
+18	1	1
+589	1	1
+37	1	1
+539	5	5
+354	1	3
+128	1	1
+58	1	1
+159	1	1
+5	2	0
+21	1	1
+231	1	1
+82	3	3
+69	3	0
+549	1	1
+69	1	1
+74	9	9
+126	1	1
+47	1	1
+614	9	9
+138	1	1
+29	1	1
+681	1	1
+49	1	1
+67	1	1
+19	4	9
+234	1	1
+93	1	1
+60	4	4
+96	4	4
+76	1	1
+169	1	1
+50	1	1
+54	1	1
+312	1	1
+130	1	1
+44	1	1
+69	1	1
+80	1	1
+76	1	1
+41	1	1
+89	0	6
+45	1	0
+363	1	1
+42	1	1
+295	1	1
+43	1	1
+83	6	0
+52	0	2
+1228	1	1
+34	1	1
+3527	20	0
+1768	2	1
+2467	0	2
+101	10	0
+129	1	1
+37	1	1
+121	1	1
+25	1	1
+161	1	0
+97	1	1
+124	1	0
+178	1	1
+34	1	1
+54	1	1
+38	1	2
+670	1	1
+45	1	1
+874	1	1
+40	1	1
+59	0	1
+59	4	4
+316	1	1
+178	1	1
+103	1	1
+61	1	1
+220	63	63
+296	1	1
+33	1	1
+185	12	12
+269	1	1
+84	1	1
+864	15	15
+241	1	0
+79	3	3
+161	1	1
+48	1	1
+539	1	1
+44	1	1
+357	1	1
+37	1	1
+436	1	1
+59	1	1
+71	1	1
+261	1	1
+289	1	1
+47	1	1
+95	12	12
+97	4	4
+27	1	1
+100	1	1
+16	1	1
+101	1	1
+33	1	2
+481	1	1
+42	1	1
+206	7	7
+56	12	12
+179	10	10
+80	1	1
+41	1	1
+251	1	1
+306	1	1
+80	2	0
+4	94	0
+433	1	1
+23	1	1
+107	1	0
+265	1	1
+49	1	1
+282	1	1
+43	1	1
+865	7	7
+60	1	0
+108	1	1
+24	1	1
+134	1	1
+32	1	0
+158	0	2
+1040	1	1
+42	1	1
+737	1	0
+790	1	1
+9	2	1
+11	1	1
+129	1	1
+23	1	1
+894	1	1
+43	3	3
+854	1	1
+23	0	1
+23	2	0
+26	1	1
+395	0	15
+403	5	5
+14	1	1
+2454	1	1
+76	1	1
+170	1	1
+18	1	1
+574	4	0
+291	1	1
+47	1	1
+786	19	0
+88	10	11
+48	1	1
+58	1	1
+28	1	1
+504	0	2
+1276	1	1
+28	1	1
+975	1	0
+3231	1	0
+865	1	1
+39	1	1
+1604	1	1
+56	9	0
+1037	0	1
+510	1	1
+49	1	1
+1253	1	1
+19	1	1
+1078	3	0
+221	1	1
+21	1	0
+899	0	4
+466	1	1
+38	1	1
+297	0	3
+730	19	6
+1043	1	1
+49	1	1
+273	0	1
+708	1	0
+364	14	13
+58	1	1
+74	1	1
+2563	4	0
+531	1	1
+19	1	1
+1944	5	0
+163	6	7
+1206	0	2
+718	1	1
+41	7	0
+1795	13	13
+1390	1	0
+2933	0	16
+540	1	1
+14	1	1
+167	1	0
+897	17	4
+1208	1	0
+1307	1	1
+20	1	1
+540	0	10
+203	2	0
+44	1	1
+298	1	0
+87	11	10
+491	14	8
+991	1	1
+74	6	0
+179	1	1
+34	1	1
+448	10	0
+1688	102	81
+131	1	1
+49	2	1
+2161	30	30
+203	1	0
+89	1	0
+492	1	1
+30	1	1
+1212	3	0
+990	1	1
+38	1	1
+780	1	0
+191	1	1
+47	6	6
+393	1	1
+41	1	1
+259	1	0
+941	1	1
+20	1	1
+185	0	6
+165	0	16
+420	3	1
+130	1	1
+31	1	1
+253	18	18
+720	16	18
+1257	3	0
+986	0	4
+3311	1	1
+26	1	1
+556	0	4
+120	0	1
+1273	1	1
+20	1	1
+4311	0	3
+15	1	1
+2531	17	17
+3334	5	5
+295	1	1
+45	1	1
+94	1	1
+85	0	1
+1603	16	16
+489	1	1
+34	1	1
+1436	1	1
+47	1	1
+273	7	0
+153	0	5
+283	12	12
+619	1	1
+36	0	4
+225	1	1
+23	1	1
+553	5	0
+2334	1	1
+49	1	1
+350	1	1
+31	1	1
+1436	1	1
+46	1	1
+91	4	19
+468	0	1
+46	1	1
+923	37	37
+531	0	4
+426	0	1
+1144	1	2
+1131	1	1
+20	1	1
+1533	16	0
+3103	0	1
+25	1	1
+4034	12	12
+346	0	1
+943	1	0
+524	1	1
+20	1	1
+151	3	3
+144	1	1
+189	1	7
+750	1	0
+695	1	0
+1003	0	2
+9710	0	1
+3177	0	1
+8990	0	1
+2268	1	1
+35	0	10
+8205	1	0
+3193	1	1
+76	1	1
+10955	0	1
+22875	0	20
+2417	1	0
+998	0	13
+4236	8	0
+4845	0	2
+64	40	34
+10941	1	1
+40	1	1
+4759	0	6
+12084	0	3
+3052	0	4
+2989	1	0
+13523	1	3
+16170	1	0
+11761	0	3
+3912	3	0
+6620	0	7
+7633	3	0
+419	2	0
+10690	5	24
+10798	0	1
+296	0	1
+1770	4	0
+374	0	4
+230	16	16
+7468	1	0
+1229	1	0
+3061	1	0
+5818	1	0
+2415	12	9
+2056	0	1
+955	4	0
+20022	0	1
+4418	2	1
+2375	0	4
+2086	1	1
+32	1	1
+1225	1	0
+857	2	0
+1154	0	1
+4667	1	0
+170	0	3
+2376	0	1
+503	37	37
+2259	10	10
+1512	4	0
+68	9	1
+2170	1	1
+47	1	1
+318	2	0
+19	0	6
+14527	1	1
+33	1	1
+3080	1	1
+23	1	1
+1645	6	6
+231	0	1
+2136	2	0
+6222	0	1
+830	1	1
+24	1	1
+8326	1	0
+2939	1	0
+3959	0	2
+3746	0	2
+1011	1	1
+34	1	1
+7443	0	1
+688	2	0
+574	1	1
+29	1	1
+1799	13	1
+4074	2	0
+136	79	79
+528	19	0
+253	0	1
+204	1	0
+129	2	0
+811	1	1
+38	1	1
+2347	52	0
+4634	1	0
+856	14	14
+159	34	38
+855	1	1
+28	1	1
+1255	1	1
+36	1	1
+97	0	1
+58	1	1
+1708	1	1
+48	1	1
+958	15	0
+3371	1	1
+37	1	1
+4267	0	13
+1061	0	1
+272	0	26
+8	1	15
+25	0	2
+112	2	0
+26	4	32
+4090	0	1
+3270	1	1
+17	1	1
+2822	0	1
+6206	1	0
+2318	0	2
+1504	0	1
+6189	3	0
+396	22	12
+918	0	1
+2340	1	1
+33	1	1
+326	1	1
+80	1	1
+205	3	2
+81	8	17
+2671	0	1
+1099	0	1
+144	1	1
+29	0	1
+2097	0	3
+24	3	0
+1207	4	4
+45	1	1
+757	0	5
+1926	1	1
+40	1	1
+2657	0	1
+414	1	0
+61	0	1
+235	0	2
+2087	0	1
+754	0	4
+17	3	0
+1027	3	0
+428	1	1
+17	1	1
+948	1	1
+41	1	1
+458	1	1
+21	1	1
+1055	0	1
+6611	0	3
+1575	4	5
+36	1	1
+99	2	0
+700	0	2
+151	0	1
+467	11	11
+272	0	3
+40	1	1
+2428	0	1
+750	2	0
+473	0	2
+421	1	1
+34	1	1
+1575	1	0
+3841	1	0
+560	1	0
+1108	1	0
+8087	1	0
+11881	1	1
+30	1	1
+4406	2	0
+183	1	1
+9871	0	1
+906	3	0
+887	1	1
+80	1	1
+3115	0	1
+1037	1	0
+5866	0	2
+18	1	1
+582	0	5
+2828	1	0
+847	1	0
+1996	3	0
+700	1	1
+2469	1	0
+1751	0	1
+910	3	0
+691	0	1
+5793	0	1
+26407	1	0
+672	0	1
+19269	1	1
+28	0	6
+1371	29	0
+494	2	0
+20417	1	0
+18633	0	1
+601	1	0
+319	0	1
+6820	1	0
+5718	0	2
+17894	1	0
+4272	1	0
+4967	3	1
+290	1	0
+2447	1	0
+740	1	9
+9299	0	18
+7427	1	0
+8151	2	1
+673	1	0
+3453	0	1
+149	0	1
+611	0	4
+4669	0	4
+176	1	1
+3229	0	1
+1092	2	0
+159	1	0
+4480	0	2
+4019	0	1
+1451	22	23
+816	1	0
+8701	1	1
+23	1	1
+1796	2	0
+5015	6	1
+1383	8	0
+2368	1	1
+31	1	0
+1883	3	0
+335	0	1
+4157	0	1
+561	4	0
+1538	1	1
+61	0	1
+159	0	2
+3362	4	0
+3333	1	1
+46	1	1
+2321	7	6
+150	1	0
+5972	0	2
+840	0	2
+55	1	1
+28	1	1
+1154	0	2
+650	0	4
+30	0	4
+1100	10	11
+4343	6	0
+1663	4	0
+150	1	0
+3128	1	0
+1449	1	0
+2023	0	1
+428	3	6
+299	2	0
+427	7	7
+1914	14	14
+1273	7	7
+1444	72	0
+423	0	4
+969	23	22
+2430	1	0
+190	8	8
+2034	3	1
+5337	42	42
+1017	1	1
+34	1	1
+485	1	0
+348	7	0
+770	1	1
+28	0	13
+1425	0	1
+302	0	1
+659	12	12
+293	0	1
+610	0	1
+906	12	0
+1331	0	6
+1686	26	26
+74	0	1
+463	0	1
+4305	0	4
+1041	1	0
+11424	3	1
+13797	0	8
+166	0	1
+1510	5	0
+9069	0	8
+25	1	1
+332	5	3
+76	0	1
+1306	1	1
+46	1	1
+134	19	23
+1467	1	1
+32	1	1
+449	17	0
+367	9	9
+3525	12	10
+91	3	0
+226	33	33
+1171	1	1
+24	1	1
+1156	9	13
+843	1	1
+28	1	1
+515	0	17
+1559	0	4
+1045	9	9
+1953	1	0
+31	1	1
+843	0	1
+2174	1	0
+3788	1	0
+2001	0	1
+2400	0	1
+1614	1	0
+8167	0	1
+2700	2	0
+2735	0	1
+8708	0	3
+448	1	1
+22	1	1
+2215	1	1
+32	1	1
+2413	14	14
+142	1	0
+789	1	1
+45	1	1
+154	1	1
+25	1	1
+465	1	1
+45	6	4
+541	1	1
+42	1	1
+1339	5	6
+391	1	1
+20	0	1
+251	1	1
+22	1	1
+561	0	2
+78	3	0
+1718	1	1
+12	1	1
+1042	1	1
+38	1	1
+301	14	0
+222	10	10
+436	10	10
+1564	1	1
+17	1	1
+1752	20	0
+1561	135	0
+58	0	45
+245	101	11
+46	90	0
+150	0	270
+54	180	0
+2130	12	12
+1630	1	1
+26	1	1
+189	0	14
+296	2	0
+809	2	0
+17	20	0
+665	0	40
+236	1	1
+44	1	1
+352	1	1
+25	1	1
+554	6	6
+850	1	1
+33	1	1
+809	3	13
+1832	7	9
+468	1	1
+21	1	1
+951	1	1
+22	1	1
+219	17	18
+733	0	14
+215	2	2
+36	1	1
+301	1	1
+22	1	1
+241	1	1
+52	0	1
+47	1	1
+72	1	1
+109	1	1
+129	1	1
+28	1	1
+174	8	8
+683	3	0
+1190	285	0
+439	13	13
+927	12	0
+557	17	17
+932	3	1
+27	1	1
+166	1	1
+19	1	1
+406	1	1
+48	3	3
+137	1	0
+161	6	6
+884	2	0
+58	1	1
+107	1	1
+150	14	14
+522	1	1
+28	1	1
+945	4	4
+34	1	1
+472	0	2
+203	0	1
+281	1	1
+46	1	1
+1130	1	0
+232	17	17
+510	1	1
+33	1	1
+62	10	10
+1501	1	1
+20	1	1
+573	1	1
+29	1	1
+928	0	3
+304	1	1
+41	1	1
+160	1	1
+58	1	1
+656	1	1
+40	4	0
+108	6	6
+321	1	1
+14	0	16
+91	1	1
+184	1	1
+43	8	3
+180	1	1
+68	1	1
+144	1	1
+27	1	0
+17	1	1
+212	0	1
+212	1	1
+34	1	1
+115	1	1
+41	1	1
+407	10	10
+200	1	1
+44	2	0
+187	2	0
+146	1	1
+17	1	1
+122	4	4
+73	1	0
+56	1	1
+155	1	17
+80	15	15
+458	1	1
+16	3	3
+343	1	1
+111	1	1
+201	14	14
+157	12	12
+346	0	2
+382	4	0
+35	1	1
+937	0	1
+246	25	0
+52	0	1
+419	0	1
+165	1	0
+75	24	3
+297	1	1
+38	1	1
+5066	1	0
+4922	7	9
+2488	14	14
+2241	1	1
+67	4	4
+39	1	0
+547	1	1
+43	1	1
+524	3715	901
+1796	4	2
+128	29	29
+415	1	1
+18	1	1
+367	0	89
+1600	0	6
+2175	0	5
+606	14	14
+519	1	0
+540	1	1
+40	1	1
+568	2	0
+165	1	2
+31	1	1
+259	1	1
+41	1	1
+1106	40	62
+818	1	1
+42	1	1
+565	1	1
+44	1	1
+571	10	8
+61	1	1
+28	1	1
+233	2	0
+33	28	0
+53	1	1
+37	1	1
+75	0	396
+156	1	0
+473	0	4
+421	1	1
+35	1	1
+2132	1	1
+80	0	2
+544	9	9
+152	2	1
+33	1	1
+2977	0	1
+164	22	0
+149	1	0
+534	1	1
+36	1	1
+113	1	1
+15	1	1
+661	1	1
+48	1	1
+1987	1	0
+34	1	1
+444	1	1
+45	1	1
+65	1	1
+67	1	1
+210	1	1
+68	1	1
+55	1	1
+47	1	1
+169	1	1
+64	1	1
+109	0	6
+77	2	32
+6	0	5
+67	0	1
+7	16	0
+51	12	0
+36	0	12
+700	1	1
+33	1	0
+49	0	2
+450	0	1
+98	4	0
+489	32	0
+63	5	1
+78	7	7
+538	17	17
+1269	1	0
+841	1	1
+43	1	1
+1257	49	49
+698	1	1
+41	1	1
+86	0	4
+5	1	0
+36	1	1
+573	2	1
+297	1	0
+85	1	1
+30	1	1
+1041	1	0
+12	1	1
+392	33	12
+515	5	6
+583	1	1
+33	1	1
+616	16	16
+1052	0	11
+39	1	1
+184	1	1
+67	1	1
+102	7	7
+58	0	1
+307	1	1
+56	0	3
+918	2	0
+1295	0	1
+832	1	1
+28	1	1
+272	1	1
+82	1	1
+56	1	0
+976	6	6
+2015	0	3
+84	9	9
+130	13	17
+564	10	15
+154	1	0
+438	10	10
+38	0	5
+2141	1	1
+25	1	1
+73	10	10
+70	5	5
+132	1	1
+52	1	1
+599	1	1
+46	1	1
+279	1	1
+18	1	1
+239	2	0
+383	6	0
+224	0	1
+321	3	0
+8	16	0
+1775	1	1
+18	2	0
+575	16	16
+60	1	1
+16	1	1
+1247	2	0
+173	3	0
+41	1	1
+57	8	8
+285	2	0
+672	1	1
+44	1	1
+106	0	1
+148	1	1
+49	3	0
+146	5	11
+91	1	1
+79	1	1
+94	1	1
+101	1	1
+88	16	16
+117	1	1
+15	1	1
+58	1	1
+93	1	1
+140	1	0
+326	1	1
+44	1	1
+160	1	1
+23	1	1
+481	14	14
+181	4	4
+72	1	1
+25	1	1
+88	1	3
+36	0	12
+92	1	1
+56	10	0
+13	0	1
+66	1	1
+141	2	0
+65	1	1
+367	0	2
+610	1	1
+22	1	1
+150	1	1
+85	1	1
+109	1	1
+167	3	1
+23	1	0
+26	1	1
+74	1	1
+33	1	1
+176	1	1
+25	2	2
+193	42	43
+377	0	5
+249	1	1
+69	1	1
+98	1	1
+62	1	1
+62	1	2
+74	0	1
+68	1	1
+438	1	1
+64	1	1
+47	0	8
+125	3	0
+75	5	5
+45	1	1
+197	1	1
+27	1	1
+116	13	13
+218	15	20
+1107	16	19
+73	1	1
+25	1	1
+199	1	1
+60	1	1
+994	1	1
+43	0	1
+18	1	1
+1215	18	18
+340	1	1
+34	1	1
+1358	8	8
+1726	4	4
+193	82	82
+263	1	1
+18	1	1
+411	19	19
+175	1	1
+49	1	1
+146	1	1
+61	1	1
+116	1	1
+41	1	1
+137	1	1
+30	1	1
+158	9	9
+136	10	13
+349	8	8
+468	1	1
+44	1	1
+862	17	17
+813	1	1
+24	1	1
+214	10	4
+228	1	1
+34	1	1
+101	12	12
+242	1	1
+69	1	1
+185	1	1
+24	1	0
+164	0	1
+222	1	1
+25	1	1
+297	10	10
+1171	1	0
+182	1	1
+35	1	1
+2335	83	83
+491	7	7
+208	13	12
+298	1	1
+65	1	1
+193	2	2
+28	1	1
+125	4	4
+95	7	7
+566	1	1
+40	1	1
+118	0	1
+318	1	0
+374	1	1
+58	1	1
+143	1	1
+74	1	1
+53	21	0
+81	1	1
+45	1	1
+138	15	16
+180	1	1
+62	1	1
+661	1	1
+48	1	1
+1463	1	0
+156	0	1
+148	1	1
+19	1	0
+17	1	1
+1927	4	0
+1469	14	14
+466	0	1
+3098	0	1
+1141	2	3
+743	14	14
+79	1	1
+22	1	1
+362	0	1
+682	16	9
+275	0	4
+462	1	1
+76	1	0
+47	1	0
+13	0	8
+331	0	4
+130	1	1
+31	0	3
+1554	1	1
+43	1	1
+224	1	1
+49	1	1
+159	3	0
+1064	27	27
+104	1	1
+21	1	1
+222	2	2
+49	1	1
+1397	1	1
+37	1	1
+414	0	2
+695	1	1
+31	1	1
+742	1	1
+21	1	1
+230	3	2
+42	1	1
+68	1	1
+37	1	1
+703	0	3
+2216	1	1
+82	1	0
+1430	1	1
+23	1	1
+1867	13	0
+35	1	1
+137	16	16
+1500	4	0
+4546	1	1
+25	1	1
+1926	1	1
+39	4	3
+1037	1	1
+40	2	0
+890	6	0
+41	2	0
+498	3	0
+321	0	1
+281	3	0
+414	1	1
+70	1	1
+284	1	0
+214	1	1
+28	1	1
+280	1	0
+650	1	1
+47	1	1
+1030	1	1
+91	1	1
+6520	5	5
+478	1	0
+76	1	1
+2771	0	3
+1930	0	4
+2915	1	1
+20	1	1
+413	1	0
+1844	11	11
+133	0	6
+569	10	10
+110	12	12
+184	0	3
+228	1	1
+43	2	2
+51	14	13
+1499	1	0
+12	1	1
+378	1	1
+49	1	1
+424	1	0
+1131	1	1
+80	0	1
+821	2	9
+311	1	6
+247	1	1
+86	1	1
+1850	1	1
+26	1	1
+498	1	1
+34	1	1
+688	5	9
+44	1	1
+369	1	1
+69	1	1
+156	2	0
+83	1	1
+128	1	1
+50	9	9
+249	1	1
+70	0	1
+624	2	0
+74	2	1
+300	1	1
+26	1	1
+240	4	0
+1705	1	1
+52	1	1
+231	29	24
+378	2	0
+236	1	1
+76	1	1
+116	9	12
+380	0	6
+43	1	1
+384	15	15
+1414	5	0
+225	0	2
+1234	1	0
+29	1	1
+235	10	10
+227	1	1
+77	4	0
+43	5	9
+485	7	7
+380	10	0
+46	1	0
+90	1	1
+161	1	1
+401	1	1
+58	1	1
+2127	3	0
+186	20	20
+323	5	5
+47	1	1
+236	1	1
+31	0	2
+1692	13	14
+202	0	3
+77	1	1
+44	1	1
+411	12	11
+317	0	2
+599	39	39
+391	1	0
+273	1	0
+744	0	4
+703	1	1
+20	1	1
+198	3	0
+158	1	1
+14	4	0
+27	12	0
+282	1	1
+32	4	0
+740	1	0
+327	1	1
+105	1	1
+146	16	16
+101	1	0
+21	1	1
+232	1	1
+33	2	0
+12	1	1
+189	1	1
+30	2	2
+544	1	1
+153	1	1
+586	5	0
+1351	21	0
+446	1	1
+32	1	1
+136	7	7
+1147	12	12
+734	44	43
+701	1	1
+29	2	2
+154	12	12
+191	1	1
+55	1	1
+28	0	1142
+172	15	18
+525	1	1
+22	1	1
+355	10	10
+50	0	8
+252	1	1
+31	1	1
+354	6	5
+148	15	15
+407	1	1
+42	1	1
+275	0	1
+737	5	9
+1432	1	1
+39	1	1
+84	0	2
+77	7	7
+919	7	1
+815	1	1
+45	1	1
+487	1	1
+66	1	1
+2379	0	24
+779	1	1
+18	1	0
+2653	4	0
+34	1	1
+191	1	1
+35	1	1
+1174	12	0
+2497	25	1525
+447	8	0
+3268	1	0
+946	1	0
+2277	0	2
+1446	1	1
+77	1	1
+313	1	1
+44	1	0
+52	19983	20030
+61	7	7
+61	1	1
+120	1	1
+366	1	1
+55	1	1
+121	1	1
+62	1	1
+78	1	1
+48	1	1
+161	1	1
+26	1	1
+191	1	1
+20	11	11
+550	1	1
+76	1	0
+20	1	1
+112	1	1
+149	1	1
+284	1	1
+37	1	1
+705	1	12
+106	12	12
+83	1	1
+46	1	1
+1500	1	1
+81	1	1
+210	1	1
+26	1	1
+713	1	1
+48	1	1
+723	0	3
+196	6	6
+62	2	2
+32	1	1
+606	1	2
+357	1	1
+38	292	0
+589	1	1
+30	1	1
+714	8	8
+639	1	1
+20	1	1
+1068	0	1
+571	1	1
+49	1	1
+436	0	1
+609	0	2
+30	1	1
+66	0	1
+349	11	11
+65	1	1
+40	1	1
+717	0	3
+299	1	1
+29	1	1
+724	1	0
+275	1	1
+33	1	1
+318	0	3
+279	1	1
+28	1	1
+389	1	0
+548	0	8
+330	1	1
+47	1	1
+170	1	1
+47	1	1
+519	14	14
+841	24	24
+732	1	1
+29	3	3
+688	2	2
+23	0	1
+94	14	14
+726	13	13
+508	0	12
+21	6	0
+69	1	1
+37	1	1
+590	1	1
+59	1	1
+89	11	11
+164	1	1
+58	1	1
+1709	18	18
+520	1	1
+27	1	1
+683	10	10
+814	1	1
+26	1	1
+350	1	1
+39	1	1
+132	6	6
+439	1	1
+38	41	6
+15	0	1
+5	4	11
+81	1	1
+19	0	2
+167	1	1
+90	0	2
+85	1	1
+78	1	1
+87	19	2
+53	23	0
+255	0	1
+211	1	1
+54	1	1
+206	0	1
+60	35	33
+279	1	1
+76	179	180
+90	1	1
+119	3	0
+19	1	1
+60	1	1
+347	0	4
+30	2	2
+68	1	1
+78	1	1
+298	5	5
+67	1	1
+99	1	1
+97	1	1
+74	1	1
+52	1	1
+44	1	1
+65	1	4
+349	14	14
+109	1	1
+159	2	2
+214	9	9
+97	1	1
+73	1	1
+58	1	1
+42	1	1
+133	1	1
+99	0	10
+124	12	12
+281	3	0
+940	2	2
+49	1	1
+303	1	1
+25	1	1
+309	15	22
+384	1	1
+24	1	1
+896	1	1
+56	1	1
+168	0	19
+54	0	6
+60	0	1
+13	1	1
+502	1	1
+4	0	1
+23	1	1
+581	1	1
+47	1	1
+122	15	15
+3352	1	1
+23	1	1
+873	4	4
+887	1	0
+1827	1	0
+216	6	6
+805	2	0
+874	0	8
+2266	1	1
+47	1	1
+736	25	29
+86	1	1
+19	1	1
+1794	9	9
+271	0	1
+2266	1	1
+34	1	1
+916	0	1
+21	1	1
+108	21	21
+141	1	1
+27	1	1
+406	3	0
+3830	59	59
+61	1	1
+38	1	1
+128	2	2
+56	1	1
+72	0	1
+96	1	1
+22	1	1
+169	7	7
+511	1	1
+38	1	1
+1070	1	1
+90	1	1
+50	1	1
+41	1	0
+30	1	1
+659	12	12
+701	1	1
+33	1	1
+569	15	15
+70	1	1
+38	1	1
+955	0	3
+130	1	1
+63	1	1
+251	8	8
+191	1	1
+26	0	3
+187	1	0
+916	5	1
+70	13	13
+498	1	0
+55	0	1
+242	25	25
+237	1	1
+20	0	1
+61	1	1
+203	6	6
+262	1	1
+154	1	1
+104	1	1
+20	1	1
+156	1	1
+32	1	1
+88	17	17
+139	13	13
+148	20091	20061
+944	1	1
+126	1	1
+81	6	6
+41	3	0
+641	1	1
+92	1	0
+113	1	1
+39	1	1
+671	1	1
+28	1	1
+123	1	1
+59	1	1
+210	1	1
+17	1	1
+168	15	14
+494	1	0
+22	1	1
+484	18	18
+376	1	1
+114	2	0
+67	1	1
+10	1	1
+109	1	1
+165	1	1
+149	6	6
+234	1	1
+19	5	5
+64	1	1
+111	1	1
+220	1	1
+89	1	1
+119	1	1
+113	2	0
+168	1	1
+73	1	1
+194	1	1
+50	0	4
+37	1	1
+95	3	1
+43	1	1
+153	1	1
+83	1	1
+55	1	1
+39	1	1
+70	7	0
+59	7	7
+75	1	1
+84	2	2
+110	1	0
+42	1	1
+341	13	13
+262	4	4
+67	1	1
+32	1	0
+38	1	1
+277	7	7
+318	1	1
+145	1	1
+90	1	1
+19	4	4
+61	1	2
+31	1	1
+52	1	1
+214	1	1
+61	10083	10104
+701	2	0
+4080	1	1
+38	1	1
+837	0	64
+172	1	1
+55	1	1
+1818	2	0
+1143	13	13
+335	1	0
+1944	5	0
+39	6	0
+4057	3	8
+9465	5	4
+301	19	1
+191	84	0
+427	1	1
+29	0	4
+157	4	5
+296	21	18
+158	2	2
+36	1	1
+539	13	13
+399	1	1
+46	1	1
+348	1	1
+49	1	1
+268	1	0
+66	0	4
+178	2	2
+107	1	1
+133	5	5
+355	1	1
+30	1	1
+346	1	1
+29	1	1
+161	1	1
+38	1	1
+121	4	4
+55	8	8
+67	7	7
+318	17	17
+259	1	1
+94	1	1
+80	1	1
+35	1	1
+260	1	1
+81	1	1
+106	1	1
+58	1	2
+55	1	1
+245	3	0
+2052	1	1
+40	1	1
+174	20	22
+574	0	2
+414	1	0
+234	0	1
+425	51224	51060
+13549	39	40
+2617	0	2
+884	1	1
+19	1	1
+676	1	1
+63	1	1
+3138	0	3
+3038	5	2
+132	10	6
+136	18	13
+363	1	1
+89	1	1
+382	1	1
+29	1	1
+58	8	7
+297	4	0
+66	1	1
+93	2	0
+145	1	1
+31	5	5
+576	1	1
+89	1	1
+1256	0	12
+67	1	1
+193	2	2
+23	1	1
+51	1	0
+727	1	0
+1148	12	12
+837	1	1
+77	1	1
+941	10	10
+776	19	19
+300	1	1
+24	1	1
+256	1	7
+93	1	1
+191	174	172
+563	1	1
+104	4	4
+2898	1	1
+46	1	1
+282	1	1
+39	1	1
+204	2	2
+22	1	1
+469	1	1
+20	1	1
+140	1	1
+26	1	1
+745	0	2
+539	0	6
+1536	1	0
+817	4	4
+202	1	1
+48	1	1
+168	1	1
+53	1	1
+379	10	10
+1178	14	14
+132	5	0
+555	1	1
+42	1	1
+573	1	1
+21	1	1
+462	1	1
+43	1	1
+121	1	1
+48	0	3
+15	1	5
+1404	0	1
+934	1	1
+49	1	1
+1350	1	0
+384	1	1
+24	1	1
+3117	10	10
+1042	0	15
+244	10	10
+2167	18	14
+64	1	1
+31	1	1
+185	0	4
+1647	1	1
+20	1	1
+227	1	1
+37	1	1
+636	3	4
+5590	1	1
+39	1	1
+461	0	2
+2145	1	1
+23	1	1
+1114	0	2
+688	0	1
+901	18	18
+4781	0	4
+815	0	1
+5069	0	5
+415	0	1
+2743	1	1
+78	1	1
+390	1	0
+328	0	1
+878	0	1
+5752	0	2
+1554	1	1
+60	1	1
+278	0	1
+19	1	1
+1164	11	11
+691	0	2
+960	1	0
+62	0	20
+2108	0	2
+1265	0	1
+1642	2	0
+3584	2	0
+12086	2	0
+3766	0	2
+1209	1	7
+3466	1	0
+1448	1	0
+1943	0	1
+698	0	8
+1166	1	1
+34	1	1
+2120	11	9
+540	1	0
+1736	14	0
+3128	0	2
+4464	0	1
+120	4	4
+3473	1	0
+378	1	0
+1269	0	3
+1182	1	0
+654	0	3
+2049	1	0
+6838	1	1
+69	0	3
+154	1	0
+2718	1	1
+30	1	1
+160	11	11
+4954	0	1
+420	1	1
+123	1	1
+156	0	4
+219	4	0
+195	1	0
+4402	3	0
+3045	0	1
+1249	1	0
+3522	0	10
+812	8	0
+346	0	1
+8538	5	0
+455	1	0
+119	0	1
+1127	1	0
+10948	1	0
+833	0	1
+4251	1	0
+8	1	1
+2079	0	1
+1735	8	12
+1612	0	1
+1373	5	0
+8585	7	0
+64	1	1
+3799	1	0
+258	2	0
+899	1	0
+1362	8	9
+593	0	2
+3351	2	0
+618	0	4
+905	2	15
+2797	1	0
+2776	2	0
+4110	0	6
+4466	18	18
+2267	0	4
+134	1	0
+12963	8	0
+1616	0	2
+1685	2	0
+2225	2	0
+428	0	1
+3338	0	3
+677	4	6
+325	11	1
+1887	0	1
+913	0	1
+997	5	5
+2814	17	15
+1389	1	0
+1200	0	4
+2495	1	0
+3921	26431	26426
+2419	0	1
+6110	0	1
+1370	0	1
+3085	1	0
+3568	1	1
+24	0	9
+597	1	0
+2642	1	0
+1545	10	0
+4952	0	1
+6146	2	0
+1452	1	0
+2967	1	0
+4920	5	0
+147	4	5
+850	1	0
+1875	1	0
+695	3	1
+1719	0	1
+259	0	1
+294	1	0
+128	0	2
+3051	0	1
+908	0	4
+3399	0	1
+909	17	17
+3747	1	0
+3179	1	0
+411	1	1
+44	1	1
+174	1	0
+1047	17	17
+998	178	0
+671	0	40
+2093	1	0
+313	0	1
+7168	78	78
+335	1	0
+3245	1	0
+972	0	4
+4085	2	0
+346	1	1
+45	1	1
+368	1	0
+26	1	1
+8444	0	1
+17044	1	0
+2795	2	0
+2860	1	0
+622	0	1
+167	0	5
+1968	0	2
+259	2	0
+4992	29	27
+170	1	0
+3528	0	1
+191	1	2
+117	2	0
+2275	1	0
+12676	1	1
+20	1	1
+9972	1	0
+13955	0	5
+19867	1	0
+5866	0	32737
+3746	1	0
+20549	1	1
+19	1	1
+970	8	8
+5220	1	0
+15573	0	1
+6799	0	16
+3350	0	1
+7574	0	12
+2132	0	1
+7228	52793	52800
+2675	0	1
+2149	1	0
+6880	0	2
+960	0	1
+23	1	1
+2646	2	0
+3867	5	0
+24765	29	29
+1283	0	3
+3174	1	0
+8183	0	1
+2817	10	0
+4539	43	43
+1259	1	0
+2081	0	1
+374	0	2
+3589	0	4
+13928	3	0
+773	7	7
+175	1	1
+79	1	1
+400	12	12
+1096	0	4
+717	7	7
+52	1	1
+68	5	1
+2117	0	3
+130	14	14
+1124	0	3
+413	0	4
+643	3	0
+58	1	1
+127	1	1
+208	0	2
+45	1	1
+168	3	0
+136	3	4
+79	44	44
+170	1	1
+25	0	3
+63	1	1
+417	0	2
+412	0	16
+737	4	0
+402	2	0
+654	1	1
+42	1	1
+75	1	1
+64	1	1
+938	1	1
+53	1	1
+1987	4	0
+576	0	1
+29	2	2
+715	1	1
+36	1	1
+767	4	40
+44	1	5
+43	49	5
+709	21	21
+1147	9	9
+22	1	1
+195	7	4
+659	3	0
+27	1	1
+637	1	1
+42	1	1
+531	1	1
+67	1	1
+39	1	0
+717	11	11
+53	1	1
+61	1	1
+1535	1	1
+89	0	1
+49	1	0
+102	1	1
+67	1	1
+76	1	1
+129	1	1
+85	1	1
+607	10	0
+12	137	1
+41	1	1
+1043	1	1
+22	1	1
+203	3	0
+480	14	21
+1459	2	1
+435	15	17
+1188	30	0
+1778	1	0
+120	0	3
+3797	1	0
+887	1	1
+58	1	1
+2264	0	1
+2456	4	0
+954	0	4
+1847	0	1
+5929	20	20
+984	14	0
+2112	1	0
+2013	1	0
+4884	1	0
+1160	16	0
+733	7	7
+238	3	2
+2203	2	1
+5654	1	1
+28	5	10
+482	0	1
+2970	0	4
+2892	0	1
+251	1	7
+1346	1	0
+877	0	4
+3583	0	1
+1178	0	1
+1293	0	2
+491	2	0
+3501	46	46
+3256	1	1
+22	1	1
+2218	1	1
+44	1	1
+4780	4	0
+3026	14	13
+442	5	5
+2022	6	6
+546	2	0
+31	1	1
+8485	1	1
+36	1	0
+1575	1	0
+1329	1	1
+35	1	0
+247	1	1
+16	1	1
+184	1	1
+18	1	1
+1607	53	60
+527	1	1
+39	1	1
+653	3	0
+227	1	1
+18	1	1
+218	0	323
+91	1	0
+124	0	15
+621	0	2
+555	8	8
+467	1	1
+40	1	1
+372	1	1
+25	1	1
+188	12	12
+357	0	2
+2389	1	1
+22	1	1
+2579	0	5
+461	1	1
+36	1	1
+1584	1	1
+26	1	0
+429	1	0
+33	1	1
+1071	0	4
+1068	9	0
+1472	0	2
+1859	1	1
+61	2	0
+9	1	1
+337	1	1
+46	1	1
+416	1	1
+42	1	1
+1060	25	25
+170	0	2
+628	17	15
+587	15	15
+398	3	0
+696	6	9
+287	10	0
+191	0	2
+493	1	1
+42	4	0
+219	0	1
+408	1	1
+23	1	1
+283	1	1
+21	1	1
+633	2	0
+241	6	6
+457	1	0
+330	0	16
+428	1	0
+4	6	0
+324	0	1
+3063	0	2
+9960	39	40
+1850	0	6
+6431	0	1
+8674	0	4
+4595	11	0
+5064	2	0
+2813	12	12
+1391	5	0
+3690	1	1
+64	1	1
+2635	1	1
+49	1	1
+69	1	1
+15	1	1
+1009	8	0
+735	0	20
+3074	2	0
+1879	0	1
+572	0	8
+576	1	1
+42	1	1
+265	24	0
+209	11	11
+953	1	1
+42	0	5
+58	1	0
+95	1	0
+1121	1	1
+17	1	1
+751	0	1
+24	1	1
+351	1	1
+43	3	3
+565	1	1
+15	1	1
+150	27	27
+94	1	0
+323	1	1
+23	1	1
+221	7	7
+705	9	0
+631	2	0
+64	1	1
+1577	1	1
+21	0	1
+371	7	21
+160	0	1
+283	1	1
+48	1	1
+227	1	1
+40	0	1
+1359	0	2
+836	13	13
+722	7	7
+1153	1	1
+93	1	1
+797	14	14
+433	8	0
+108	11	11
+140	1	1
+40	1	1
+470	1	1
+42	1	1
+1106	0	1
+85	4	4
+129	1	1
+123	1	0
+95	1	1
+104	6	1
+641	1	1
+77	1	1
+57	1	1
+62	1	1
+473	2	0
+262	6	0
+45	1	1
+63	2	0
+39	1	1
+267	0	1
+197	2	104
+87	111	0
+122	0	7
+88	0	4
+108	5	0
+563	14	14
+324	1	0
+205	1	1
+17	1	1
+495	0	1
+201	4	0
+14	1	1
+887	1	1
+58	1	1
+133	1	1
+24	1	1
+91	24	24
+342	1	1
+32	1	1
+121	1	1
+62	1	1
+2371	2	0
+164	8	1
+655	1	1
+30	1	1
+271	1	1
+47	1	1
+609	1	0
+1780	2	0
+742	1	1
+40	1	1
+2014	1	0
+1741	3	0
+3833	0	1
+16381	3	3
+25	1	1
+234	161226	190028
+3106	0	1
+1680	1	1
+88	1	1
+4502	0	1
+46	1	1
+800	4	4
+23	1	1
+1305	2	0
+136	0	1
+4941	0	1
+547	0	1
+70	8	8
+293	1	1
+35	1	1
+1165	4	0
+6662	1	1
+46	1	1
+167	0	8
+214	1	1
+35	1	1
+108	1	0
+1063	0	1
+1017	1	1
+20	0	6
+1725	0	1
+134	68	67
+349	1	1
+24	0	1
+1562	1	1
+31	1	1
+2513	0	1
+73	36	36
+305	1	1
+27	1	1
+543	1	1
+47	4	28
+4387	20058	20058
+159	1	1
+36	1	1
+107	1	1
+176	1	1
+154	0	5
+91	1	1
+54	1	1
+77	1	1
+238	2	2
+50	1	1
+1421	1	1
+23	1	1
+216	1	1
+122	1	1
+86	1	1
+41	3	1
+336	7	7
+41	9	0
+107	1	1
+90	8	9
+53	1	1
+30	1	1
+213	1	1
+26	1	1
+138	1	1
+25	1	1
+206	1	1
+36	3	3
+37	7	0
+500	1	1
+52	1	1
+52	1	1
+48	1	1
+395	1	1
+66	6	6
+72	1	0
+69	1	1
+100	10	10
+160	1	0
+64	7	7
+89	1	1
+123	1	1
+128	1	1
+36	1	1
+231	1	1
+61	1	1
+564	8	8
+593	1	1
+45	1	1
+163	1	0
+196	8	8
+174	5	5
+37	1	1
+67	0	1
+192	1	1
+60	3	0
+19	1	1
+1149	1	1
+18	1	1
+77	1	1
+32	2	0
+32	1	1
+136	1	1
+78	2	0
+162	4	0
+41	1	1
+351	13	13
+1634	2	0
+229	8	8
+57	13	2
+410	1	1
+76	1	1
+180	1	1
+92	1	1
+270	1	1
+40	1	1
+92	1	1
+53	1	1
+227	1	1
+42	1	1
+357	4	4
+23	1	1
+94	1	0
+200	6	0
+201	7	7
+70	5	13
+57	4	0
+35	1	1
+206	1	1
+76	2	2
+651	1	1
+68	4	0
+73	1	1
+49	4	0
+37	1	1
+145	2	2
+78	2	2
+108	12	12
+52	1	1
+35	1	1
+242	1	3
+76	2	2
+50	12	12
+70	1	1
+33	0	2
+57	1	1
+64	15	15
+168	1	1
+22	1	1
+66	2	2
+6	0	1
+24	1	1
+73	0	2
+64	1	1
+177	2	0
+19	4	0
+55	1	0
+33	1	1
+51	1	1
+122	1	1
+296	1	1
+85	1	1
+109	1	1
+64	1	1
+155	1	1
+58	0	2
+72	1	1
+25	1	1
+128	1	1
+45	2	0
+334	4	4
+106	1	1
+25	1	1
+64	1	1
+21	1	1
+368	15	15
+734	2	0
+701	15	15
+71	1	1
+41	1	1
+77	1	1
+56	1	1
+478	2	0
+714	8	7
+95	2	2
+50	4	3
+1129	1	1
+34	1	1
+1715	1	1
+87	1	1
+692	1	1
+47	0	1
+75	1	1
+2155	10	10
+1265	1	1
+46	1	1
+298	1	1
+22	1	1
+186	1	1
+34	1	1
+202	1	1
+61	1	0
+185	1	1
+24	1	0
+98	0	2
+258	8	14
+967	1	1
+15	1	1
+625	1	0
+1362	0	4
+23365	4	0
+246	26975	26986
+3307	0	1
+13671	3	3
+52	1	1
+1308	2	0
+942	0	1
+17790	1	0
+4586	0	1
+949	0	2
+15047	0	1
+606	2	0
+7820	0	4
+22313	16	0
+10539	8	0
+4836	0	1
+8726	2	0
+194	1	1
+49	1	1
+320	1	1
+34	1	1
+6813	0	1
+8719	3	0
+5482	46	46
+1509	1	0
+721	0	1
+999	6	0
+17	1	0
+3075	5	0
+593	13	11
+4505	1	0
+9535	0	4
+23	0	2
+23	2	0
+513	0	3
+377	1	0
+2627	0	2
+16	0	1
+211	18	18
+571	2	0
+7617	0	1
+1607	1	0
+69	1	1
+66	1	1
+275	1	1
+67	7	0
+25	1	1
+1206	1	0
+136	8	7
+612	1	1
+61	1	1
+740	0	2
+233	1	1
+95	0	4
+1483	13	28
+1062	1	0
+108	4	0
+685	0	2
+1566	1	0
+192	4	4
+1452	9	45
+1514	1	1
+46	1	1
+1969	0	1
+35	1	1
+1094	1	0
+618	1	1
+43	1	1
+6580	1	0
+1636	5	0
+6325	1	1
+32	1	1
+1041	0	2
+174	9	0
+4023	14	14
+8106	8	8
+2203	10	8
+2025	1	1
+39	1	1
+907	4	4
+225	1	1
+124	1	1
+3928	0	22
+38	2	0
+44	18	0
+46	0	6
+61	0	1
+3653	6	0
+34	1	1
+4559	1	1
+28	1	1
+283	5	5
+1951	1	1
+34	1	1
+443	19	19
+57	1	1
+21	1	1
+231	1	1
+94	1	1
+105	1	1
+208	5	5
+124	1	1
+112	3	3
+207	40	40
+244	1	1
+60	1	1
+98	1	1
+50	1	1
+256	5	5
+23	1	1
+157	1	1
+33	1	1
+143	1	1
+59	1	1
+51	1	1
+45	1	0
+73	1	1
+81	1	1
+339	1	1
+56	0	5
+142	1	1
+232	1	1
+43	1	1
+332	1	1
+47	1	1
+479	1	0
+137	0	3
+1456	10	13
+63	1	1
+37	1	1
+261	0	2
+109	1	1
+50	1	1
+56	129	1
+88	1	0
+44	1	1
+54	1	1
+56	1	50
+58	50	1
+54	277	1
+44	1	1
+297	0	39
+142	1	1
+85	1	1
+124	16	16
+58	3	15
+677	1	0
+1333	2	0
+13591	6	0
+989	1	1
+107	1	1
+678	1	1
+31	1	1
+2571	5	5
+56	2	2
+39	1	1
+3986	0	4
+18351	32	30
+10811	1	1
+25	0	1
+129	62	62
+226	1	1
+40	1	1
+159	4	4
+37	4	4
+179	1	1
+51	1	1
+103	2	0
+108	1	1
+79	1	1
+25	1	1
+58	1	1
+12	1	1
+275	14	0
+80	1	1
+83	1	1
+24	1	1
+59	1	0
+91	1	1
+65	1	1
+67	1	1
+136	4	0
+68	8	0
+331	5	0
+40	1	1
+110	10	6
+64	1	1
+368	1	1
+22	1	1
+509	1	1
+89	1	1
+926	1	0
+959	1	1
+44	1	1
+72	11	0
+47	1	1
+361	1	1
+37	1	1
+2204	2	2
+45	1	1
+1117	18	18
+141	1	1
+47	1	1
+148	1	1
+75	1	1
+107	57	56
+146	3	2
+249	1	1
+146	1	1
+94	1	1
+34	1	1
+700	0	331
+21	1	1
+73	1	1
+49	1	1
+356	1	1
+16	1	1
+112	1	1
+36	9	0
+515	1	1
+27	2	2
+192	1	1
+53	0	14
+82	1	1
+302	1	1
+68	1	1
+52	12	12
+52	1	1
+34	1	1
+166	7	7
+384	1	1
+31	1	1
+281	1	1
+57	1	1
+176	0	1
+1625	1	1
+26	1	1
+369	1	1
+21	1	1
+86	1	1
+134	1	1
+215	1	1
+214	15	1
+50	2	2
+26	1	1
+78	0	19
+64	1	1
+126	1	1
+43	1	1
+433	1	1
+76	0	1
+6	12	0
+52	1	1
+108	1	1
+87	1	1
+62	1	1
+26	1	1
+291	2	1
+143	1	1
+29	1	1
+56	12	12
+230	1	1
+153	4	4
+87	32	32
+584	12	12
+227	1	0
+1931	4	0
+836	1	1
+68	1	1
+205	24	19
+816	1	2
+1932	0	7
+1732	13	0
+257	4	0
+1441	1	0
+111	6	0
+1505	1	1
+42	0	1
+373	13	13
+565	1	1
+76	1	0
+1881	0	4
+68	4	0
+43	0	4
+2201	8	8
+3726	3	0
+339	15	11
+249	1	1
+35	1	1
+250	1	1
+38	1	1
+359	11	12
+109	1	1
+43	18	0
+822	1	1
+53	1	1
+325	15	15
+123	1	1
+42	6	6
+240	1	1
+44	1	1
+438	7	7
+142	2	0
+1004	0	1
+9275	1	1
+37	1	0
+2071	0	1
+10399	0	1
+12513	2	1
+11243	1	1
+26	1	1
+816	4	0
+8248	26	26
+7722	2	0
+1594	1	0
+363	5	0
+6757	47	41
+2700	1	0
+823	18	19
+1807	0	2
+2565	11	0
+2089	0	2
+477	1	0
+657	0	1
+776	0	20
+365	82	49
+779	0	1
+391	35	73
+441	0	2
+1152	0	2
+1315	1	0
+5352	6	8
+902	0	1
+2154	1	1
+36	1	1
+109	0	1
+668	6	0
+1923	0	1
+91	3	2
+3560	1	0
+1235	1	0
+139	26	0
+831	3	3
+6547	1	0
+155	0	14
+2393	1	1
+33	1	1
+507	4	0
+1337	0	1
+9954	3	0
+1588	1	0
+2605	1	1
+23	1	1
+3000	0	3
+8249	8	0
+912	0	1
+338	2	0
+734	1	0
+4332	1	0
+416	0	4
+1691	0	1
+295	1	0
+214	2	0
+121	0	1
+784	0	1
+2512	0	1
+1205	21	21
+3239	12	11
+926	1	0
+190	1	0
+5780	0	1
+490	5	0
+228	1	1
+45	1	1
+207	3	0
+322	0	1
+633	1	1
+24	1	0
+1516	5	0
+1025	0	13
+1518	0	1
+591	10	10
+1061	1	0
+1371	1	1
+22	1	1
+928	0	2
+182	8	0
+328	1	0
+301	0	1
+994	1	1
+18	0	6
+1743	0	1
+2350	22	23
+1548	0	2
+1498	8	6
+7484	0	3
+2988	7	7
+93	2	0
+322	1	0
+280	1	1
+49	1	1
+2114	16	17
+617	0	1
+1012	0	1
+495	1	0
+29	1	1
+3134	1	0
+1837	0	4
+4079	0	1
+905	8	0
+5764	0	1
+3493	0	20
+1174	0	1
+900	0	1
+1006	1	0
+1699	0	1
+1682	1	0
+688	1	1
+21	1	1
+3349	0	1
+384	3	1
+3616	3	0
+748	0	1
+3001	0	10
+541	1	0
+286	1	1
+22	0	1
+250	1	1
+27	1	1
+898	1	0
+1161	0	2
+2067	0	1
+8000	0	12
+857	29	0
+1399
+
+chain 80965 chr6_qbl_hap6 4611984 + 2304864 2305721 chr6 170899992 - 139781917 139782778 1559017
+341	0	4
+516
+
+chain 72788 chr6_qbl_hap6 4611984 + 3854428 3855228 chr11 134452384 + 117706218 117707111 1729754
+615	13	107
+119	2	1
+51
+
+chain 45972 chr6_qbl_hap6 4611984 + 2517561 2519479 chr10 135374737 + 90380381 90382315 2786707
+110	146	146
+63	324	322
+53	379	396
+81	331	331
+99	110	110
+78	40	41
+104
+
+chain 30865 chr6_qbl_hap6 4611984 + 3846325 3846844 chr6 170899992 + 32821259 32821748 4483191
+73	89	59
+184	77	77
+96
+
+chain 26769 chr6_qbl_hap6 4611984 + 2264712 2264997 chr1 247249719 - 83196058 83196343 6075821
+285
+
+chain 22241 chr6_qbl_hap6 4611984 + 1157838 1158189 chr4 191273063 + 37186911 37187262 8835264
+178	101	101
+72
+
+chain 17263 chr6_qbl_hap6 4611984 + 3740215 3740422 chr4 191273063 + 3978296 3978500 12788148
+50	3	0
+26	4	4
+124
+
+chain 16745 chr6_qbl_hap6 4611984 + 2635745 2635946 chr11 134452384 + 74426248 74426449 13289834
+113	12	12
+76
+
+chain 16124 chr6_qbl_hap6 4611984 + 3115310 3115488 chr2 242951149 + 128261675 128261851 618783
+28	10	8
+140
+
+chain 15557 chr6_qbl_hap6 4611984 + 3932244 3933069 chr7 158821424 + 130132312 130132930 14485186
+71	636	429
+118
+
+chain 14855 chr6_qbl_hap6 4611984 + 3933226 3933509 chr9 140273252 - 14741363 14741645 15225313
+54	109	108
+120
+
+chain 14065 chr6_qbl_hap6 4611984 + 3751984 3752136 chr6 170899992 - 138279004 138279156 16120856
+152
+
+chain 13590 chr6_qbl_hap6 4611984 + 3850351 3850495 chr2 242951149 + 178053314 178053458 16703161
+144
+
+chain 13364 chr6_qbl_hap6 4611984 + 3822393 3822546 chr3 199501827 + 102278307 102278460 16996123
+67	1	1
+85
+
+chain 13024 chr6_qbl_hap6 4611984 + 983771 983907 chr11 134452384 - 45905925 45906061 17454498
+136
+
+chain 12452 chr6_qbl_hap6 4611984 + 4259490 4260232 chr12 132349534 + 123152186 123152605 1903988
+57	408	105
+14	32	63
+45	0	78
+44	129	0
+13
+
+chain 12361 chr6_qbl_hap6 4611984 + 1196738 1196868 chr1 247249719 + 48758029 48758159 18440544
+130
+
+chain 12272 chr6_qbl_hap6 4611984 + 2525057 2525213 chrX 154913754 + 154847615 154847763 18572106
+71	1	1
+25	8	0
+51
+
+chain 12201 chr6_qbl_hap6 4611984 + 1151149 1151920 chr6 170899992 - 139553108 139553881 18681505
+54	620	622
+97
+
+chain 11746 chr6_qbl_hap6 4611984 + 1143997 1144145 chr7 158821424 - 7754727 7754875 19419749
+54	14	14
+80
+
+chain 11418 chr6_qbl_hap6 4611984 + 3733988 3734369 chr6 170899992 + 32605989 32606372 19978843
+55	244	246
+82
+
+chain 11340 chr6_qbl_hap6 4611984 + 3744880 3745292 chr11 134452384 + 42855603 42856006 20116653
+57	275	266
+80
+
+chain 11205 chr6_qbl_hap6 4611984 + 3740546 3740663 chr3 199501827 + 102893757 102893874 20360983
+117
+
+chain 10738 chr6_qbl_hap6 4611984 + 3746512 3746633 chr10 135374737 + 59270705 59270823 21232184
+61	3	0
+57
+
+chain 10686 chr6_qbl_hap6 4611984 + 2524205 2524726 chr18 76117153 + 11332173 11332695 21332094
+80	388	389
+53
+
+chain 10567 chr6_qbl_hap6 4611984 + 3783253 3785836 chr6 170899992 + 32627140 32629242 21577879
+86	1741	1742
+57	646	164
+53
+
+chain 10496 chr6_qbl_hap6 4611984 + 3742563 3742673 chr1 247249719 - 172266041 172266151 21720781
+110
+
+chain 10342 chr6_qbl_hap6 4611984 + 3760212 3760942 chr6 170899992 + 32656559 32657213 22046794
+78	598	522
+54
+
+chain 10139 chr6_qbl_hap6 4611984 + 1198462 1198648 chr16 88827254 + 79406655 79406844 22494560
+65	65	68
+56
+
+chain 9962 chr6_qbl_hap6 4611984 + 3745365 3745830 chr4 191273063 - 17741127 17741604 22894345
+65	340	352
+60
+
+chain 9923 chr6_qbl_hap6 4611984 + 1132589 1132693 chr6 170899992 + 29984509 29984613 22990380
+104
+
+chain 9560 chr6_qbl_hap6 4611984 + 1145748 1145849 chr6 170899992 - 141000133 141000234 23851260
+101
+
+chain 9413 chr6_qbl_hap6 4611984 + 2517880 2518811 chr3 199501827 - 190559447 190560375 2816976
+26	220	218
+60	531	530
+94
+
+chain 9385 chr6_qbl_hap6 4611984 + 3871626 3871831 chr16 88827254 - 20600009 20600189 24262926
+58	92	67
+55
+
+chain 9214 chr6_qbl_hap6 4611984 + 1148380 1148477 chr6 170899992 + 29866137 29866234 24599827
+97
+
+chain 9032 chr6_qbl_hap6 4611984 + 3792044 3793708 chr6 170899992 + 32600177 32601830 24897719
+61	1516	1505
+87
+
+chain 8560 chr6_qbl_hap6 4611984 + 1158286 1158614 chr13 114142980 - 5380936 5381417 10250153
+58	237	390
+33
+
+chain 8241 chr6_qbl_hap6 4611984 + 3817008 3817095 chr6 170899992 + 65319659 65319746 26041518
+87
+
+chain 7487 chr6_qbl_hap6 4611984 + 3850495 3850589 chr16 88827254 + 12353631 12353725 21356530
+23	11	11
+60
+
+chain 7405 chr6_qbl_hap6 4611984 + 3933869 3933948 chr6 170899992 + 125781203 125781282 27398065
+79
+
+chain 7276 chr6_qbl_hap6 4611984 + 3821398 3821474 chr6 170899992 - 67344251 67344327 27653186
+76
+
+chain 7270 chr6_qbl_hap6 4611984 + 2635437 2635524 chr9 140273252 - 10289268 10289355 16248608
+13	11	11
+63
+
+chain 7204 chr6_qbl_hap6 4611984 + 3822572 3822648 chr7 158821424 - 147092048 147092124 27788942
+76
+
+chain 6530 chr6_qbl_hap6 4611984 + 3872997 3873065 chr8 146274826 + 43408268 43408336 29217082
+68
+
+chain 6522 chr6_qbl_hap6 4611984 + 3873792 3873861 chr15 100338915 + 41279078 41279147 29241048
+69
+
+chain 6486 chr6_qbl_hap6 4611984 + 3835377 3835446 chr4 191273063 - 136771275 136771344 29334522
+69
+
+chain 6459 chr6_qbl_hap6 4611984 + 2621390 2621459 chr6 170899992 + 31350859 31350928 29378034
+69
+
+chain 6457 chr6_qbl_hap6 4611984 + 1204555 1204622 chr6 170899992 + 30336816 30336883 29393800
+67
+
+chain 6422 chr6_qbl_hap6 4611984 + 3863961 3864029 chr6 170899992 + 32836685 32836753 29490928
+68
+
+chain 6404 chr6_qbl_hap6 4611984 + 3933974 3934042 chr7 158821424 + 141217888 141217956 29535655
+68
+
+chain 6368 chr6_qbl_hap6 4611984 + 2524965 2525057 chr6 170899992 - 132294381 132294479 20980275
+55	29	35
+8
+
+chain 6276 chr6_qbl_hap6 4611984 + 3873712 3873778 chrX 154913754 + 50967168 50967234 29833134
+66
+
+chain 5979 chr6_qbl_hap6 4611984 + 3850589 3850678 chr7 158821424 + 47749290 47749379 21749072
+4	34	34
+51
+
+chain 5976 chr6_qbl_hap6 4611984 + 2623961 2624024 chr6 170899992 + 31358648 31358711 30614264
+63
+
+chain 5908 chr6_qbl_hap6 4611984 + 1197012 1197085 chr19 63811651 - 42248237 42248310 20723418
+73
+
+chain 5877 chr6_qbl_hap6 4611984 + 3715034 3715097 chr6 170899992 + 32648139 32648202 30861180
+63
+
+chain 5767 chr6_qbl_hap6 4611984 + 3872292 3872353 chr6 170899992 + 75566512 75566573 31174250
+61
+
+chain 5730 chr6_qbl_hap6 4611984 + 1160462 1160522 chr6 170899992 + 29878483 29878543 31293472
+60
+
+chain 5694 chr6_qbl_hap6 4611984 + 3933682 3933742 chr5 180857866 - 92908144 92908204 31375044
+60
+
+chain 5621 chr6_qbl_hap6 4611984 + 1160085 1160144 chr6 170899992 + 29878108 29878167 31597733
+59
+
+chain 5594 chr6_qbl_hap6 4611984 + 2515502 2515561 chrX 154913754 - 63050736 63050795 31662666
+59
+
+chain 5458 chr6_qbl_hap6 4611984 + 3834959 3835017 chr16 88827254 + 47978524 47978582 32101539
+58
+
+chain 5276 chr6_qbl_hap6 4611984 + 3754169 3754225 chr6 170899992 + 32648605 32648661 32642677
+56
+
+chain 5193 chr6_qbl_hap6 4611984 + 3872547 3872601 chr5 180857866 + 130110350 130110404 32896488
+54
+
+chain 5176 chr6_qbl_hap6 4611984 + 1146649 1146704 chr14 106368585 + 78419238 78419293 32952450
+55
+
+chain 5094 chr6_qbl_hap6 4611984 + 3834697 3834751 chr6 170899992 + 68023473 68023527 33192803
+54
+
+chain 4984 chr6_qbl_hap6 4611984 + 3871272 3871324 chr1 247249719 - 76982562 76982614 33591211
+52
+
+chain 4959 chr6_qbl_hap6 4611984 + 3742510 3742563 chr18 76117153 + 5080594 5080647 22154819
+53
+
+chain 4930 chr6_qbl_hap6 4611984 + 3744490 3744542 chrX 154913754 - 4434310 4434362 33717622
+52
+
+chain 4923 chr6_qbl_hap6 4611984 + 1158016 1158078 chr9 140273252 - 102391777 102391839 11227006
+62
+
+chain 4829 chr6_qbl_hap6 4611984 + 1205079 1205129 chr6 170899992 + 30567298 30567348 34088060
+50
+
+chain 4815 chr6_qbl_hap6 4611984 + 2517906 2519257 chr1 247249719 + 7396807 7398156 2855562
+25	959	957
+58	214	214
+95
+
+chain 4391 chr6_qbl_hap6 4611984 + 4260111 4260156 chrX 154913754 - 99121082 99121127 30173418
+45
+
+chain 4349 chr6_qbl_hap6 4611984 + 2517042 2517321 chr5 180857866 + 51070260 51070539 3385343
+66	110	110
+103
+
+chain 4295 chr6_qbl_hap6 4611984 + 2516110 2516164 chr13 114142980 + 40947099 40947153 23509762
+54
+
+chain 3734 chr6_qbl_hap6 4611984 + 3932378 3932443 chr6 170899992 + 80018577 80018642 19955879
+65
+
+chain 3600 chr6_qbl_hap6 4611984 + 3934098 3934136 chr2 242951149 + 129304609 129304647 25766390
+38
+
+chain 3399 chr6_qbl_hap6 4611984 + 1196935 1197002 chr12 132349534 + 50414483 50414550 19205048
+67
+
+chain 3394 chr6_qbl_hap6 4611984 + 3746476 3746512 chrX 154913754 - 4438295 4438331 28244178
+36
+
+chain 3148 chr6_qbl_hap6 4611984 + 3871684 3871717 chr2 242951149 + 38036197 38036230 24698966
+33
+
+chain 2975 chr6_qbl_hap6 4611984 + 2524285 2524321 chr3 199501827 - 94209737 94209773 24799760
+36
+
+chain 2972 chr6_qbl_hap6 4611984 + 1151921 1151961 chr6 170899992 + 30567024 30567064 20739259
+40
+
+chain 2845 chr6_qbl_hap6 4611984 + 2516686 2516716 chr3 199501827 - 158108130 158108160 26771673
+30
+
+chain 2771 chr6_qbl_hap6 4611984 + 2185017 2185049 chr16 88827254 + 61371572 61371604 11881976
+32
+
+chain 2691 chr6_qbl_hap6 4611984 + 3933197 3933226 chr3 199501827 - 121608742 121608771 23862843
+29
+
+chain 2671 chr6_qbl_hap6 4611984 + 2524905 2524964 chr9 140273252 - 60326471 60326530 21074055
+59
+
+chain 2645 chr6_qbl_hap6 4611984 + 3740797 3740872 chr19 63811651 - 40112981 40113056 21687959
+75
+
+chain 2599 chr6_qbl_hap6 4611984 + 1158078 1158116 chr7 158821424 - 126060947 126060985 11258555
+38
+
+chain 2365 chr6_qbl_hap6 4611984 + 3662868 3662893 chr9 140273252 - 56082033 56082058 25372966
+25
+
+chain 2302 chr6_qbl_hap6 4611984 + 2518282 2518373 chrX 154913754 + 17160841 17160932 3083108
+91
+
+chain 2226 chr6_qbl_hap6 4611984 + 2516716 2520208 chr12 132349534 + 103307685 103311177 3426888
+99	961	960
+41	2329	2330
+62
+
+chain 2196 chr6_qbl_hap6 4611984 + 3573229 3573252 chr8 146274826 - 36256974 36256997 29790670
+23
+
+chain 2146 chr6_qbl_hap6 4611984 + 1144210 1144271 chr12 132349534 + 104221177 104221238 23825291
+61
+
+chain 2027 chr6_qbl_hap6 4611984 + 2518845 2519837 chr4 191273063 + 75333400 75334396 3306565
+44	889	893
+59
+
+chain 2011 chr6_qbl_hap6 4611984 + 3750379 3750401 chr12 132349534 - 27555073 27555095 35529087
+22
+
+chain 2003 chr6_qbl_hap6 4611984 + 1715012 1715046 chr6 170899992 + 30558380 30558414 2034666
+34
+
+chain 1988 chr6_qbl_hap6 4611984 + 3744653 3744712 chr1 247249719 + 152912877 152912936 23823439
+59
+
+chain 1906 chr6_qbl_hap6 4611984 + 2517426 2517496 chr17 78774742 - 18978582 18978652 12332136
+70
+
+chain 1860 chr6_qbl_hap6 4611984 + 1158233 1158283 chr8 146274826 + 68242167 68242217 13480681
+50
+
+chain 1860 chr6_qbl_hap6 4611984 + 3858322 3861837 chr6 170899992 + 32830794 32834943 29475612
+61	2506	2690
+85	515	965
+52	103	103
+193
+
+chain 1658 chr6_qbl_hap6 4611984 + 1158189 1158222 chr4 191273063 + 153905795 153905828 11042895
+33
+
+chain 1451 chr6_qbl_hap6 4611984 + 2516912 2518845 chr18 76117153 + 57868323 57870253 3225031
+58	1841	1838
+34
+
+chain 1444 chr6_qbl_hap6 4611984 + 2517346 2518418 chr3 199501827 + 26257399 26258470 3460386
+77	968	967
+27
+
+chain 1437 chr6_qbl_hap6 4611984 + 2517932 2518010 chr9 140273252 - 113447512 113447590 4152331
+78
+
+chain 1395 chr6_qbl_hap6 4611984 + 2517496 2517525 chr4 191273063 + 177039024 177039053 17309502
+29
+
+chain 1388 chr6_qbl_hap6 4611984 + 4260176 4260219 chr19 63811651 - 48476446 48476489 2785288
+43
+
+chain 1332 chr6_qbl_hap6 4611984 + 3612848 3612887 chr2 242951149 - 44758440 44758479 1994605
+39
+
+chain 1326 chr6_qbl_hap6 4611984 + 2516425 2516540 chr2 242951149 - 193553846 193553961 4393012
+115
+
+chain 1313 chr6_qbl_hap6 4611984 + 4259851 4259901 chr1 247249719 - 36229834 36229933 2748513
+7	14	63
+29
+
+chain 1148 chr6_qbl_hap6 4611984 + 4259442 4259473 chr8 146274826 + 89694 89724 9819782
+12	1	0
+18
+
+chain 1111 chr6_qbl_hap6 4611984 + 1158412 1158466 chr19 63811651 - 5696793 5696847 17027637
+54
+
+chain 1071 chr6_qbl_hap6 4611984 + 2516561 2516628 chr12 132349534 + 77415638 77415705 9437720
+67
+
+chain 1001 chr6_qbl_hap6 4611984 + 4259418 4259442 chr1 247249719 + 40151331 40151355 3139135
+24
+
+chain 975 chr6_qbl_hap6 4611984 + 2516971 2517042 chr1 247249719 + 183489007 183489078 3337949
+71
+
+chain 917 chr6_qbl_hap6 4611984 + 2518025 2518086 chr8 146274826 - 9314035 9314096 4594958
+61
+
+chain 884 chr6_qbl_hap6 4611984 + 2519749 2519778 chr1 247249719 - 197271642 197271671 12501548
+29
+
+chain 844 chr6_qbl_hap6 4611984 + 2520091 2520119 chr7 158821424 + 107644180 107644208 22181631
+28
+
+chain 841 chr6_qbl_hap6 4611984 + 2516165 2516217 chr20 62435964 - 59823019 59823071 21526398
+52
+
+chain 836 chr6_qbl_hap6 4611984 + 4259969 4260001 chr3 199501827 + 123981761 123981793 2757122
+32
+
+chain 835 chr6_qbl_hap6 4611984 + 2519837 2519906 chr4 191273063 + 99162526 99162595 6917305
+69
+
+chain 764 chr6_qbl_hap6 4611984 + 1158466 1158505 chr14 106368585 - 57011112 57011151 17388689
+39
+
+chain 760 chr6_qbl_hap6 4611984 + 2520610 2520672 chr1 247249719 + 71360495 71360557 7931067
+62
+
+chain 760 chr6_qbl_hap6 4611984 + 2518460 2518519 chr12 132349534 + 56700130 56700189 25330836
+59
+
+chain 746 chr6_qbl_hap6 4611984 + 2519488 2519538 chr22 49691432 + 27063810 27063860 3889151
+50
+
+chain 745 chr6_qbl_hap6 4611984 + 2516014 2516077 chr6 170899992 + 44660392 44660455 3181879
+63
+
+chain 740 chr6_qbl_hap6 4611984 + 1158720 1158784 chr12 132349534 + 55464534 55464598 20832676
+64
+
+chain 718 chr6_qbl_hap6 4611984 + 2520835 2520890 chr9 140273252 - 49339912 49339967 23555331
+55
+
+chain 716 chr6_qbl_hap6 4611984 + 3933624 3933676 chr16 88827254 - 38714794 38714846 22851161
+52
+
+chain 710 chr6_qbl_hap6 4611984 + 2519659 2519709 chr11 134452384 - 107252690 107252740 6149242
+50
+
+chain 706 chr6_qbl_hap6 4611984 + 2516328 2516399 chr18 76117153 + 57376973 57377044 7676567
+71
+
+chain 700 chr6_qbl_hap6 4611984 + 2516815 2516871 chr1 247249719 + 47033162 47033218 11749470
+56
+
+chain 685 chr6_qbl_hap6 4611984 + 2520397 2520480 chr1 247249719 + 68246247 68246330 16545799
+83
+
+chain 662 chr6_qbl_hap6 4611984 + 2520752 2520817 chr5 180857866 + 99923773 99923838 9608666
+65
+
+chain 654 chr6_qbl_hap6 4611984 + 1158614 1158640 chr4 191273063 - 137719796 137719822 10317123
+26
+
+chain 604 chr6_qbl_hap6 4611984 + 2520031 2520091 chr8 146274826 - 111755913 111755973 4980877
+60
+
+chain 569 chr6_qbl_hap6 4611984 + 2515445 2515500 chr12 132349534 - 4861980 4862035 16127490
+55
+
+chain 521 chr6_qbl_hap6 4611984 + 2517182 2517218 chr15 100338915 - 47556137 47556173 3431041
+36
+
+chain 465 chr6_qbl_hap6 4611984 + 2518541 2518594 chrX 154913754 - 2978832 2978885 15318329
+53
+
+chain 465 chr6_qbl_hap6 4611984 + 2515257 2515307 chr13 114142980 + 94087883 94087933 15752176
+50
+
+chain 431 chr6_qbl_hap6 4611984 + 2516292 2516328 chrX 154913754 + 109116067 109116103 11044816
+36
+
+chain 377 chr6_qbl_hap6 4611984 + 2521082 2521150 chrX 154913754 - 100727898 100727966 10456810
+68
+
+chain 364 chr6_qbl_hap6 4611984 + 2519959 2520014 chr2 242951149 + 137419466 137419521 26497561
+55
+
+chain 357 chr6_qbl_hap6 4611984 + 2516242 2516292 chr3 199501827 + 59182343 59182393 15538406
+50
+
+chain 252 chr6_qbl_hap6 4611984 + 2519906 2519943 chr10 135374737 + 69013226 69013263 15789370
+37
+
+chain 172 chr6_qbl_hap6 4611984 + 3874043 3874094 chr1 247249719 - 204983626 204983677 25877237
+51
+
+chain 126 chr6_qbl_hap6 4611984 + 2521548 2521600 chr16 88827254 - 42325840 42325892 26081164
+52
+
+chain 345833726 chr6_ssto_hap7 4928567 + 0 4928567 chr6 170899992 + 28767121 33556332 37
+43705	3	0
+396	1	1
+36	1	1
+327	0	2
+458	8	0
+6175	1	1
+58	1	1
+80	0	7
+257	2	0
+2504	0	12
+1614	0	1
+1985	6	0
+370	1	0
+2206	2	0
+4292	4	0
+5173	33	8
+1486	4	4
+213	2	2
+71	0	1
+437	0	1
+897	1	1
+34	1	1
+10055	18	6
+2970	0	1
+813	0	15
+922	0	20
+1095	1	1
+43	1	1
+1829	0	1
+2885	0	10
+5273	0	1
+108	2	0
+571	0	3
+2338	1	0
+934	1	0
+2409	0	8
+2132	54	16
+77	1	52
+38	0	59
+40	0	2
+3908	1	0
+3045	2	4
+758	0	1
+174	15	15
+211	1	0
+608	0	4
+1434	2	0
+2061	2	0
+10205	0	6
+2011	17	17
+871	89	85
+91	0	2
+2644	33	29
+3737	1	1
+39	1	1
+1512	1	0
+2391	2	0
+844	0	1
+5198	0	1
+17000	0	1
+603	2	0
+4648	0	3
+2281	1	0
+38	1	1
+334	1	1
+41	1	1
+1760	1	0
+3862	0	6
+1025	160	0
+3444	3	0
+282	0	1
+1508	1	0
+2207	0	3
+1827	1	0
+3220	9	0
+5157	0	4
+1394	1	0
+279	0	2
+71	0	4
+163	1	1
+31	1	1
+280	8	0
+1059	0	2
+1409	0	4
+402	1	0
+643	0	2
+746	0	2
+1268	2	0
+267	0	1
+1868	1	1
+44	1	1
+8525	0	4
+1440	4	4
+127	0	6
+204	1	2
+873	1	0
+131	2	0
+3954	0	1
+1818	2	1
+4264	0	1
+3195	0	2
+2446	1	1
+70	26	25
+70	1	1
+1649	1	0
+953	0	1
+295	1	1
+32	0	6
+661	8	0
+5298	1	0
+1365	0	1
+6151	2	0
+1123	0	9
+2073	1	0
+611	1	0
+1129	0	3
+562	11	11
+9680	4	4
+316	19	19
+831	2	0
+3215	1	0
+1710	0	1
+2693	0	3
+4148	82	25
+807	0	1
+85	1	1
+114	1	1
+489	10	0
+936	43	43
+6001	0	1
+3807	5	0
+191	14	14
+73	0	1
+345	2	0
+3436	3	0
+780	1	0
+6	1	0
+2268	0	1
+569	5	5
+1359	2	1
+1049	3	0
+371	1	0
+5832	1	1
+13	1	1
+4064	0	105
+776	3	2
+1696	1	1
+34	1	1
+5830	0	3
+3442	1	1
+61	1	1
+472	1	0
+22361	20	19
+3288	0	3
+10522	4	0
+16901	2	0
+30045	7	0
+1489	1	1
+72	1	1
+2260	0	2
+7033	0	4
+3592	0	1
+11101	0	1
+8476	0	1
+1324	0	2
+5438	5	0
+2061	1	0
+3982	6	6
+1725	0	1
+3153	1	0
+18	1	0
+18	1	0
+2026	1	0
+4175	10	10
+4746	9	9
+4767	7	7
+1225	1	0
+8	1	1
+151	1	2
+5079	1	1
+28	1	1
+249	43	43
+1178	0	4
+685	12	0
+48	8	0
+1701	1	1
+43	5	5
+862	18	18
+58	1	1
+66	1	1
+420	1	1
+44	1	1
+680	4	4
+1675	1	1
+83	1	1
+3082	4	0
+5467	1	1
+27	0	1
+1099	16	0
+627	12	12
+1317	6	1
+129	1	1
+25	1	1
+1397	15	15
+810	1	1
+27	1	1
+1192	2	0
+7515	4	0
+979	0	3
+3406	0	2
+1730	11	11
+1760	1	1
+26	1	1
+787	0	1
+1416	3	1
+22815	4	4
+126	1	0
+38	1	1
+140	1	0
+1072	0	15
+15438	4	0
+6165	0	1
+1768	1	0
+7727	2	0
+1514	0	1
+3116	0	1
+3278	1	1
+21	1	1
+1738	0	1
+8576	19	0
+8020	1	0
+2049	1	0
+528	3	1
+1704	1	1
+117	1	1
+1448	10	0
+4403	9	9
+1142	9	9
+1114	1	0
+1382	1	1
+32	1	1
+1519	11	11
+2877	0	2
+1221	0	1
+1974	4	0
+71	32	24
+565	1	0
+1447	1	0
+1362	0	4
+4579	0	1
+3278	0	1
+2020	1	1
+31	1	1
+673	1	0
+2321	9	9
+155	1	1
+18	1	1
+1427	1	0
+4008	1	1
+59	2	0
+1998	11	0
+942	1	1
+39	1	1
+2252	1	0
+6944	0	4
+342	1	1
+16	1	1
+4918	1	1
+30	1	1
+1530	0	1
+313	1	1
+59	1	1
+1737	1	1
+34	1	1
+852	9	12
+1814	0	5
+742	0	318
+10	1	1
+484	0	2
+993	0	1
+312	4	0
+23	1	1
+476	0	1
+195	2	0
+1963	1	1
+25	1	1
+1942	1	1
+26	0	1
+13516	0	3
+40	1	1
+1374	20	0
+31	1	1
+189	1	1
+26	1	1
+327	1	1
+38	1	1
+177	11	11
+709	1	1
+38	1	1
+1803	1	1
+26	1	1
+2373	5	0
+321	1	0
+933	17	17
+82	9	9
+2773	0	143
+80	1	1
+25	1	1
+467	1	1
+27	1	1
+143	1	1
+47	1	1
+1197	10	10
+1455	1	1
+33	1	1
+601	1	1
+48	0	2
+694	1	4
+132	1	1
+17	1	1
+167	6	6
+113	1	1
+31	1	1
+1181	0	1
+422	15	0
+36	1	1
+2219	1	1
+35	1	1
+2116	0	1
+15789	0	2
+24630	1	0
+7864	1	0
+13424	0	2
+12333	1	1
+41	1	1
+33759	6	0
+3090	1	1
+41	1	1
+2048	0	2
+462	1	0
+31504	22	0
+880	79442	79440
+1063	1	7
+1384	4	1
+85	1	0
+357	3	4
+9255	0	1
+6104	0	1
+6497	0	1
+713	0	4
+2181	2	0
+145	0	1
+1108	0	2
+1448	1	0
+1835	1	0
+4207	1	0
+5843	0	1
+1398	0	1
+5972	1	0
+7345	4	0
+2841	1	0
+361	1	0
+5438	0	1
+1889	0	3
+1737	2	0
+5252	2	0
+9241	0	10
+575	1	1
+30	2	2
+78	1	1
+49	1	1
+294	1	1
+37	1	2612
+385	17	17
+259	0	1
+107	32	32
+72	1	1
+29	1	1
+123	1	1
+121	1	1
+435	1	0
+32	1	1
+255	1	1
+52	1	1
+201	1	1
+59	0	2
+9	0	21
+72	0	2
+141	5	137
+425	1	1
+42	1	1
+572	1	1
+30	1	1
+560	1	1
+28	1	1
+98	0	12
+18	0	15
+144	13	13
+1410	1	0
+291	0	4
+1637	0	1
+231	1	1
+35	1	1
+2158	1	1
+21	1	1
+581	59	48
+181	4	0
+65	0	4
+603	3	0
+591	1	1
+23	1	1
+51	1	1
+38	1	1
+362	1	1
+44	1	1
+1935	0	2
+165	13	19
+1394	8	7
+450	7	0
+483	1	1
+27	1	1
+264	1	1
+51	1	1
+355	1	1
+45	1	1
+1717	0	4
+80	1	1
+18	1	0
+437	1	1
+38	1	1
+454	1	1
+40	1	1
+2320	1	1
+21	1	1
+161	1	1
+37	1	1
+1424	1	1
+48	1	1
+392	1	1
+35	1	1
+147	4	4
+436	1	1
+28	4	5
+144	3	0
+533	0	4
+437	1	9
+1714	0	1
+31	0	1
+850	16	16
+515	0	1
+58	1	1
+142	1	1
+33	1	1
+173	1	0
+753	1	1
+55	1	1
+573	0	4
+37	1	1
+144	8	8
+1004	0	4
+28	2	0
+153	15	15
+94	12	12
+201	12	13
+169	19	20
+118	10	15
+1254	0	2
+243	16	16
+73	1	1
+21	1	1
+196	0	28
+36	2	0
+18	1	1
+52	1	1
+29	1	1
+162	2	1
+373	1	0
+1159	0	32
+23	1	1
+674	0	3
+136	1	1
+48	1	1
+330	9	9
+1108	1	1
+98	1	1
+582	1	0
+715	7	7
+89	1	0
+115	1	1
+31	1	1
+145	9	8
+350	6	6
+145	1	1
+41	1	1
+681	1	1
+43	1	1
+518	1	1
+19	1	1
+582	16	16
+180	6	6
+993	0	7
+9811	1	1
+27	1	1
+1374	1	0
+1705	13	13
+4591	1	1
+9	1	1
+5418	1	0
+5474	33	33
+1261	74	190
+19692	5	1
+1674	4	4
+42	1	1
+593	1	1
+24	1	1
+457	10	10
+414	13	13
+825	1	1
+41	1	1
+492	0	8
+1196	1	1
+23	1	1
+149	1	1
+18	1	1
+1145	6	4
+880	1	1
+35	1	1
+236	1	1
+67	1	1
+298	0	1
+147	14	14
+312	11	11
+99	1	1
+43	1	1
+469	1	1
+62	1	1
+288	0	1
+51	1	1
+22	1	1
+204	1	1
+39	1	1
+812	1	1
+57	1	1
+358	1	1
+128	1	1
+146	10	10
+490	1	1
+20	1	1
+62	1	1
+88	1	1
+135	1	1
+47	1	1
+109	1	1
+28	1	0
+20	1	1
+83	0	1
+90	1	1
+312	1	1
+44	1	1
+1213	1	1
+51	1	1
+473	1	1
+33	1	1
+122	14	0
+35	1	1
+485	14	14
+110	9	0
+127	1	1
+746	1	1
+40	1	1
+50	1	0
+1765	5	5
+773	1	2
+48	1	0
+1699	1	0
+293	1	1
+33	13	0
+7	7	27
+303	1	1
+16	1	1
+289	1	1
+23	1	1
+217	1	1
+42	1	1
+320	1	1
+44	1	1
+298	1	1
+7	4	0
+32	0	7
+14	1	0
+6	5	37
+272	6	0
+1071	8	8
+143	10	10
+522	8	13
+85	1	1
+49	0	1
+90	1	1
+85	1	1
+89	1	1
+568	1	0
+265	0	2
+501	1	1
+36	1	1
+330	0	1
+1365	23	16
+81	1	1
+36	1	1
+184	0	1
+465	1	1
+26	1	1
+139	1	1
+87	0	3
+298	1	1
+45	1	1
+118	1	1
+44	1	1
+1277	6	4
+129	0	496
+233	1	1
+73	1	1
+1947	0	4
+265	1	1
+25	1	1
+200	6	6
+93	1	1
+34	2	2
+98	3	0
+1010	15	15
+366	1	0
+610	1	1
+21	1	1
+422	6	0
+358	1	1
+51	1	1
+700	40	40
+127	1	1
+51	2	2
+395	13	13
+148	0	5
+119	1	1
+103	1	1
+268	1	1
+22	1	1
+251	1	1
+34	1	1
+175	1	1
+36	1	1
+239	1	1
+32	5	5
+63	1	1
+126	1	1
+209	1	1
+143	1	13
+175	7	17
+393	1	1
+44	1	1
+129	1	1
+84	1	1
+140	8	0
+90	6	8
+450	1	1
+25	1	1
+265	1	1
+35	0	1
+17	2	0
+428	1	1
+92	1	1
+697	1	1
+34	1	1
+955	1	1
+45	1	1
+95	1	1
+29	1	1
+660	1	1
+18	1	1
+389	9	9
+252	3	0
+284	1	1
+38	1	1
+81	9	9
+90	1	1
+71	1	1
+132	0	6
+96	1	1
+257	3	0
+56	1	1
+159	1	1
+44	1	1
+409	34254	40035
+275	1	1
+38	1	1
+1307	1	1
+26	1	1
+1467	1	1
+27	1	1
+568	11	11
+693	1	1
+47	1	1
+276	11	11
+183	1	1
+40	1	1
+589	1	1
+26	1	1
+4216	2	1
+170	17	17
+893	2	0
+24	1	1
+2666	4	4
+545	1	1
+76	1	1
+163	4	0
+141	1	1
+108	1	1
+165	1	1
+72	1	1
+167	1	1
+33	0	1
+42	0	2
+83	0	2
+60	1	1
+84	1	0
+383	2	0
+736	15	15
+770	13	13
+76	14	14
+410	1	1
+43	1	1
+542	1	1
+81	1	1
+111	8	4
+137	1	1
+37	1	1
+127	1	1
+34	0	3
+45	1	1
+269	2	2
+126	1	1
+259	26	26
+257	2	2
+14	1	1
+114	5483	21566
+75	1919	964
+70	30518	17325
+308	1	1
+49	1	1
+285	29	27
+223	10	8
+230	1	2
+69	12	12
+705	0	2
+187	2	1
+402	1	0
+656	0	2
+614	1	1
+43	1	1
+781	3	1
+55	13	19
+1083	5	5
+38	1	1
+62	1	1
+80	1	1
+1217	1	1
+44	1	1
+2070	27	27
+259	1	1
+40	1	1
+115	1	1
+56	4	4
+478	1	1
+30	1	1
+162	11	11
+209	10	0
+150	1	1
+36	0	2
+31	1	1
+55	1	1
+51	1	1
+221	8	13
+386	1	1
+58	1	1
+397	3	0
+45	1	1
+547	1	1
+21	1	1
+4446	4	0
+1282	1	1
+44	1	1
+8862	1	0
+4998	10	10
+6533	1	0
+1116	28	28
+9230	19	0
+741	0	1
+2695	0	1
+5382	1	0
+4424	21	21
+3562	0	1
+381	1072	0
+6066	0	1
+1968	7	0
+3198	1	0
+667	1	0
+3902	17	4
+1895	1	1
+40	0	4
+1137	0	6
+205	2	0
+345	1	0
+1639	8	0
+686	5	0
+1032	0	1
+9206	0	4
+1574	1	0
+22388	1	0
+1656	2	0
+118	1	5
+4748	1	0
+2035	0	1
+1151	5	6
+1120	1	1
+20	1	1
+1533	16	0
+3103	0	1
+25	1	1
+2642	1	1
+43	0	3
+1703	0	1
+409	7	7
+527	1	0
+524	1	1
+59	1	1
+112	3	3
+50	1	1
+267	0	7
+286	14	14
+1161	2	0
+1003	0	1
+4062	1	0
+3850	4	0
+4977	0	1
+2718	1	0
+1588	1	1
+30	4	0
+879	0	1
+1332	18	12
+1688	4	4
+88	1	1
+439	2	0
+209	1	0
+1322	54	54
+893	1	1
+49	1	2
+1773	1	1
+24	1	1
+540	1	1
+41	1	1
+460	1	7
+165	1	1
+45	1	1
+903	1	2
+140	0	1
+36	1	1
+2019	0	1
+657	1	1
+48	1	0
+1329	0	1
+268	1	1
+47	1	1
+336	1	1
+25	2	0
+43	1	1
+1484	1	1
+53	1	1
+1151	1	1
+42	1	1
+1870	1	1
+24	5	5
+853	0	3
+23	0	1
+326	9	9
+131	9	9
+623	0	3
+34	1	1
+809	1	1
+36	1	1
+690	2	0
+44	1	1
+285	8	7
+455	1	1
+32	1	1
+102	1	1
+47	1	1
+4338	0	1
+5275	4	0
+11554	1	0
+409	16	17
+3476	0	1
+2160	0	24
+109	1	1
+3284	0	19
+2586	2	0
+757	1	1
+22	1	1
+860	17	24
+1584	1	0
+1582	0	2
+117	1	0
+1552	3	25
+17	0	4
+20	14	0
+42	9	0
+10	6	0
+10605	1	0
+4733	1	3
+371	4	0
+1177	1	1
+85	1	1
+40	0	1
+518	6	0
+646	13	13
+469	1	0
+1072	1	4
+565	1	1
+44	1	1
+3082	1	0
+839	1	0
+282	1	0
+597	0	6
+505	4	4
+45	1	1
+137	1	1
+43	1	1
+1294	1	1
+40	1	1
+572	0	5
+463	0	4
+1886	1	0
+548	1	0
+1300	0	3
+1839	2	0
+189	1	1
+49	1	1
+1253	1	1
+43	1	0
+498	1	1
+45	4	0
+3538	0	1
+1582	31	31
+376	14	14
+867	3	4
+253	1	1
+34	1	1
+172	2	0
+1094	0	1
+2856	1	1
+82	0	419
+125	3	0
+709	1	1
+36	1	1
+2189	16	17
+181	1	1
+109	0	1
+8	0	1
+53	1	1
+94	1	1
+49	1	1
+1495	15	0
+623	13	13
+163	1	1
+45	1	1
+2050	11	11
+474	1	1
+29	1	1
+1947	1	1
+42	1	0
+35	1	1
+751	1	0
+287	1	1
+60	1	1
+446	0	4
+2620	8	7
+1600	1	0
+11761	0	12
+3903	0	5
+4922	0	1
+1697	9	0
+379	0	1
+16104	1	0
+2244	0	14
+1780	1	1
+32	1	1
+9010	0	1
+296	0	1
+9862	0	1
+10107	1	0
+2415	11	9
+29829	0	12
+5348	0	1
+4837	0	1
+461	1	1
+37	1	1
+6200	4	0
+68	13	1
+2539	25	19
+1982	3	0
+5200	1	0
+162	0	9
+11963	1	1
+26	0	4
+206	1	0
+652	1	1
+27	1	1
+150	1	0
+1774	1	1
+18	1	1
+1410	4	4
+323	1	1
+64	5	5
+126	1	1
+28	1	1
+318	16	16
+579	1	1
+35	1	1
+206	1	1
+32	1	1
+50	1	1
+16	1	1
+279	1	1
+52	1	1
+167	16	16
+135	8	8
+802	1	1
+21	1	1
+278	1	1
+35	1	1
+663	1	1
+57	0	3
+29	1	0
+792	7	7
+111	1	1
+25	1	1
+387	1	1
+37	1	1
+55	1	1
+23	1	1
+623	1	1
+46	1	1
+494	1	1
+84	1	1
+276	0	2
+83	7	8
+114	1	1
+52	1	1
+48	0	1
+440	0	5
+101	1	1
+73	1	1
+329	0	2
+84	1	1
+41	1	1
+162	1	1
+29	1	1
+658	1	1
+28	1	1
+246	1	0
+155	28	28
+263	16	16
+1316	1	1
+29	1	1
+92	1	1
+30	1	1
+517	1	1
+23	1	1
+161	7	7
+668	1	1
+56	1	1
+761	1	1
+29	1	1
+276	16	16
+305	1	0
+546	3	5
+77	2	2
+45	0	2
+76	0	7
+18	1	1
+969	7	7
+84	0	3
+208	1	1
+25	1	1
+670	1	0
+179	0	1
+294	6	6
+578	1	1
+176	1	1
+216	1	1
+19	1	1
+142	4	4
+201	1	1
+34	1	1
+63	1	1
+49	1	1
+136	1	1
+112	0	1
+58	1	1
+46	1	0
+26	1	1
+80	0	3
+142	22576	22570
+400	1	1
+29	1	1
+982	0	2
+559	1	1
+59	1	1
+367	6	6
+288	1	1
+49	1	1
+193	1	1
+45	1	1
+183	16	16
+651	0	1
+136	1	1
+89	1	1
+341	14	14
+90	1	1
+151	1	1
+196	1	1
+66	1	1
+118	1	1
+55	1	1
+305	1	1
+81	1	1
+178	1	1
+18	1	1
+138	1	1
+103	1	1
+161	1	1
+27	1	1
+477	21	21
+417	2	2
+60	1	1
+51	1	1
+25	2	2
+231	1	1
+9	0	1
+24	1	1
+759	14	14
+107	1	1
+99	7	7
+236	1	1
+35	1	1
+121	1	1
+24	1	1
+92	0	2
+43	1	1
+68	1	1
+110	2	2
+52	1	1
+30	1	1
+201	1	1
+70	2	0
+99	1	1
+54	10	10
+125	0	1
+7	1	1
+132	18	25
+235	1	2
+189	1	1
+21	1	1
+278	1	1
+22	1	3
+22	1	1
+801	1	1
+51	1	1
+265	1	1
+84	1	1
+350	15	15
+259	1	0
+5	18	0
+368	1	1
+30	1	1
+840	1	1
+33	1	1
+490	1	1
+64	1	1
+1540	1	1
+37	1	1
+3927	1	1
+22	1	1
+316	0	5
+1069	0	2
+277	0	2
+69	14	0
+19	0	2
+31	2	0
+17	4	92
+2837	1	1
+197	2419	0
+840	1	1
+45	1	1
+176	1	0
+277	1	0
+1541	1	1
+17	1	1
+1434	18	22
+322	1	0
+193	0	1
+366	0	1
+493	1	0
+378	1	0
+1065	0	1
+4782	1	0
+656	13	13
+705	1	1
+49	0	3
+2315	0	3
+7693	2	0
+396	22	12
+918	0	1
+1126	0	4
+1210	1	1
+33	1	1
+326	1	1
+80	1	1
+288	8	17
+2671	0	1
+1244	1	1
+29	0	1
+2098	0	2
+24	4	0
+1207	4	4
+45	1	1
+175	34	34
+548	0	5
+1926	1	1
+40	1	1
+2657	0	1
+414	1	0
+61	0	1
+235	0	2
+2087	0	1
+713	0	4
+58	3	0
+1041	3	0
+36	1	1
+377	1	1
+17	1	1
+948	1	1
+41	1	1
+458	1	1
+21	1	1
+1055	0	1
+8168	1	1
+5	0	2
+18	1	0
+36	1	1
+99	2	0
+700	0	5
+148	0	1
+750	0	3
+40	1	1
+2428	0	1
+750	2	0
+473	0	2
+2032	1	0
+1184	2260	2258
+399	1	0
+560	1	0
+1108	1	0
+8087	1	0
+4298	0	2
+7581	1	1
+30	1	1
+4383	2	0
+10078	0	1
+906	4	0
+887	1	1
+80	1	1
+2210	1	0
+905	0	1
+1037	1	0
+5867	0	1
+18	1	1
+582	0	5
+2828	1	0
+847	1	0
+1996	1	0
+700	1	1
+4220	0	1
+910	2	0
+687	0	1
+32877	1	0
+19299	0	8
+1369	29	0
+494	2	0
+6182	1	0
+12	1	1
+23175	14263	14261
+152	1	0
+8727	0	1
+9606	1	0
+15258	1	0
+5758	8	0
+3591	1	0
+5707	0	28
+6100	34700	34698
+298	0	1
+28	1	1
+118	1	1
+24	1	18
+34	1	1
+75	1	1
+43	2	2
+73	1	1
+29	1	1
+246	1	1
+42	1	1
+409	4	4
+1168	10	1
+310	1	1
+49	1	1
+3002	1	1
+38	1	1
+789	0	1
+63	9	9
+2434	0	8
+980	0	2
+749	8	8
+528	1	1
+24	1	1
+1646	15	15
+528	1	1
+16	1	1
+165	12467	12465
+758	1	1
+45	1	1
+213	8	0
+51	1	1
+107	10	11
+134	2	0
+228	103	1
+51	2	1
+68	1	1
+59	1	1
+195	1	161
+13	1	1
+553	2	2
+36	1	1
+143	1	0
+1874	4	0
+519	0	1
+476	1	0
+1530	0	1
+1126	2	0
+831	1	1
+40	1	1
+1131	88	87
+598	1	1
+41	1	1
+1422	0	2
+1950	1	1
+32	1	1
+2037	0	2
+178	2	1
+7938	164527	164525
+7881	0	3
+162	1	1
+39	0	1
+281	1	1
+46	1	1
+1703	1	0
+1253	1	1
+48	1	1
+538	0	2
+576	1	1
+21	1	1
+561	1	0
+3867	10	10
+200	1	1
+29	1	1
+201	2	0
+508	11	11
+1281	1	1
+35	1	1
+299	0	1
+588	1	0
+1231	25	0
+52	0	1
+419	1	0
+1601	6	6
+4040	2	0
+4924	0	1
+4749	1	1
+67	4	4
+39	1	0
+1116	3715	901
+205	2	0
+1591	5	2
+128	29	29
+802	0	89
+1600	0	6
+2177	0	3
+606	14	14
+519	1	0
+540	1	1
+40	1	1
+568	2	0
+458	1	1
+41	1	1
+1105	5	0
+58	1	5
+30	1	1
+558	1	0
+229	1	1
+42	1	1
+610	1	1
+115	1	1
+214	12	12
+237	9	7
+279	1	1
+49	0	2
+13	5	11
+86	1	1
+627	1	0
+473	0	4
+974	7	7
+717	1	1
+19	1	1
+531	1	1
+47	1	1
+372	0	2
+703	0	1
+35	1	1
+53	1	1
+46	1	1
+1322	0	1
+45	1	1
+148	1	1
+19	1	1
+1293	1	1
+44	0	1
+158	0	2
+153	1	0
+1027	21	21
+315	1	1
+48	1	1
+647	0	1
+104	1	1
+31	1	1
+1332	1	1
+63	5	5
+392	5	5
+127	5	5
+68	8	8
+66	1	1
+172	1	1
+156	1	1
+77	1	1
+192	1	1
+25	0	23
+57	0	24
+39	6	0
+34	1	1
+713	1	1
+33	1	0
+507	2	3
+90	4	0
+489	40	0
+63	5	1
+623	17	17
+353	14	14
+1743	1	1
+43	1	1
+1257	49	49
+698	1	1
+41	1	1
+109	1	0
+22	1	1
+288	1	1
+16	1	1
+267	2	1
+175	0	1
+121	1	0
+1158	2	0
+12	1	1
+392	29	12
+515	5	6
+583	1	1
+33	1	1
+616	16	16
+1050	0	10
+42	1	1
+184	1	1
+67	1	1
+102	7	7
+58	0	1
+307	1	1
+36	4	0
+20	24	0
+921	1	0
+913	1	0
+304	0	1
+77	0	1
+756	106	106
+272	1	1
+82	1	1
+56	2	0
+367	4	7
+602	6	6
+2102	9	9
+96	1	1
+45	0	5
+564	10	15
+154	1	0
+438	10	10
+38	0	5
+94	9	13
+2034	1	1
+25	1	1
+73	10	10
+70	5	5
+132	1	1
+52	1	1
+599	1	1
+46	1	1
+279	1	1
+18	1	1
+622	6	0
+224	0	1
+321	16	0
+1783	1	1
+18	2	0
+575	16	16
+60	1	1
+16	1	1
+609	1	1
+28	1	1
+781	3	0
+41	1	1
+57	8	8
+285	2	0
+717	1	1
+85	1	1
+402	0	4
+23	1	1
+64	1	1
+56	1	1
+1387	0	1
+972	4	1
+2390	1	2
+120	0	4
+11	1	1
+652	2	86
+42	0	1
+85	0	1
+22	1	1
+323	1	1
+39	1	1
+185	1	1
+53	4	0
+127	3	0
+703	2	0
+15	1	0
+619	1	1
+45	1	1
+442	16	19
+73	1	1
+25	1	1
+194	1	1
+65	1	1
+129	1	0
+201	49946	49944
+3358	1	1
+25	1	1
+1926	1	1
+39	4	3
+1037	1	1
+40	2	0
+890	6	0
+41	2	0
+498	3	0
+321	0	1
+281	3	0
+414	1	1
+70	1	1
+284	1	0
+214	1	1
+28	1	1
+930	1	1
+47	1	1
+1030	1	1
+91	1	1
+1538	0	1
+3268	1	0
+2180	1	0
+2256	14	14
+594	0	3
+1930	0	4
+3114	1	0
+3833	1	1
+32	1	1
+1073	0	1
+2092	1	0
+38	1	0
+327	2	0
+460	0	6
+8619	0	1
+463	10	12
+315	7	7
+1903	1	1
+18	5	0
+227	5	0
+162	1	1
+28	1	0
+1043	1	0
+29	1	1
+334	1	1
+37	1	1
+177	4	0
+46	0	1
+4	2	2
+484	7	7
+230	1	1
+37	1	1
+81	0	6
+160	1	1
+206	1	1
+356	6	6
+54	1	0
+1704	1	1
+85	1	1
+51	13	13
+207	1	1
+57	2	0
+20	4	7
+59	1	1
+40	1	1
+80	5	5
+16	1	1
+169	12	12
+125	5	5
+119	1	1
+98	1	1
+458	1	1
+26	1	1
+1064	1	1
+30	1	1
+227	0	14
+264	1	1
+44	1	1
+422	1	0
+317	0	6
+282	9	9
+762	8	8
+237	1	0
+199	0	1
+47	1	1
+496	0	3
+1097	4	0
+188	11	11
+143	5	0
+740	1	0
+558	1	1
+36	1	1
+98	1	1
+23	1	1
+232	1	1
+21	0	1
+244	1	1
+35	1	1
+620	1	1
+56	1	1
+470	1	1
+16	1	1
+540	1	1
+42	1	1
+90	1	1
+32	1	1
+110	2	0
+609	12	6
+17	5	1
+21	1	1
+352	2	0
+56	1	1
+175	1	1
+769	1	1
+78	1	1
+87	6	6
+586	0	1
+51	1	1
+92	1	1
+23	1	1
+195	73	72
+619	1	0
+53	1	1
+29	2	2
+357	1	1
+84	1	0
+516	1	1
+41	1	1
+107	11	11
+323	22	25
+114	1	0
+1881	2	0
+1560	2	0
+5260	6	0
+1103	0	4
+832	2	1
+2627	3	11
+34	1	1
+599	0	3
+65	1	1
+230	1	1
+18	1	1
+484	24	0
+150	1	1
+42	1	1
+184	1	1
+8	0	1
+27	1	1
+320	9	9
+376	1	1
+48	1	1
+266	1	1
+44	1	1
+113	1	1
+104	1	1
+297	0	1
+522	0	1500
+471	4	0
+32	1	0
+124	1	1
+46	1	1
+784	8	8
+68	1	1
+21	4	0
+193	7	7
+457	1	1
+23	1	1
+906	1	1
+78	1	1
+385	4	5
+344	1	1
+32	1	0
+669	6	0
+37	1	1
+127	1	1
+29	1	1
+60	5	5
+48	1	1
+290	0	2
+1482	1	1
+39	1	1
+114	1	1
+37	0	4
+104	1	1
+257	1	1
+130	15	16
+158	8	0
+57	1	1
+332	2	2
+35	1	1
+197	1	1
+44	1	1
+106	1	1
+77	1	1
+313	1	1
+44	1	0
+52	19983	20030
+61	7	7
+61	1	1
+120	1	1
+366	1	1
+55	1	1
+121	1	1
+62	1	1
+78	1	1
+48	1	1
+161	1	1
+26	1	1
+191	1	1
+20	11	11
+550	1	1
+76	1	0
+20	1	1
+112	1	1
+149	1	1
+284	1	1
+37	1	1
+705	1	12
+106	12	12
+83	1	1
+46	1	1
+1500	1	1
+81	1	1
+210	1	1
+26	1	1
+713	1	1
+48	1	1
+723	0	3
+196	6	6
+62	2	2
+32	1	1
+606	1	2
+357	1	1
+38	292	0
+589	1	1
+30	1	1
+714	8	8
+639	1	1
+20	1	1
+1068	0	1
+571	1	1
+49	1	1
+436	0	1
+609	0	2
+30	1	1
+66	0	1
+349	11	11
+65	1	1
+40	1	1
+717	0	3
+299	1	1
+29	1	1
+724	1	0
+275	1	1
+33	1	1
+318	0	3
+279	1	1
+28	1	1
+389	1	0
+548	0	8
+330	1	1
+47	1	1
+170	1	1
+47	1	1
+519	14	14
+841	24	24
+732	1	1
+29	3	3
+688	2	2
+23	0	1
+94	14	14
+726	13	13
+508	0	12
+21	6	0
+69	1	1
+37	1	1
+590	1	1
+59	1	1
+89	11	11
+164	1	1
+58	1	1
+1709	18	18
+520	1	1
+27	1	1
+683	10	10
+814	1	1
+26	1	1
+350	1	1
+39	1	1
+132	6	6
+439	1	1
+38	41	6
+15	0	1
+5	4	11
+81	1	1
+19	0	2
+167	1	1
+90	0	2
+85	1	1
+78	1	1
+87	19	2
+53	23	0
+255	0	1
+211	1	1
+54	1	1
+206	0	1
+60	35	33
+279	1	1
+76	179	180
+90	1	1
+119	3	0
+19	1	1
+60	1	1
+347	0	4
+30	2	2
+68	1	1
+78	1	1
+298	5	5
+67	1	1
+99	1	1
+97	1	1
+74	1	1
+52	1	1
+44	1	1
+65	1	4
+349	14	14
+109	1	1
+159	2	2
+214	9	9
+97	1	1
+73	1	1
+58	1	1
+42	1	1
+133	1	1
+99	0	10
+124	12	12
+281	3	0
+940	2	2
+49	1	1
+303	1	1
+25	1	1
+309	15	22
+384	1	1
+24	1	1
+896	1	1
+56	1	1
+168	0	19
+54	6	14
+66	1	1
+502	1	1
+4	0	1
+23	1	1
+581	1	1
+47	1	1
+122	15	15
+3352	1	1
+23	1	1
+873	4	4
+887	1	0
+1827	1	0
+216	6	6
+805	2	0
+874	8	0
+2274	1	1
+47	1	1
+736	25	29
+86	1	1
+19	1	1
+1794	9	9
+271	0	1
+2266	1	1
+34	1	1
+916	0	1
+21	1	1
+108	21	21
+141	1	1
+27	1	1
+406	3	0
+3830	59	59
+61	1	1
+38	1	1
+128	2	2
+56	1	1
+72	0	1
+96	1	1
+22	1	1
+169	7	7
+511	1	1
+38	1	1
+1070	1	1
+90	1	1
+50	1	1
+41	1	0
+30	1	1
+659	12	12
+701	1	1
+33	1	1
+569	15	15
+70	1	1
+38	1	1
+955	0	3
+130	1	1
+63	1	1
+251	8	8
+191	1	1
+26	0	3
+187	1	0
+916	5	1
+70	13	13
+498	1	0
+55	0	1
+242	25	25
+237	1	1
+20	0	1
+61	1	1
+203	6	6
+262	1	1
+154	1	1
+104	1	1
+20	1	1
+156	1	1
+32	1	1
+88	17	17
+139	13	13
+148	20156	20120
+885	1	1
+113	1	1
+141	2	0
+842	1	0
+1246	1	1
+29	1	1
+898	1	1
+19	1	1
+333	1	1
+44	1	1
+220	1	1
+56	2	0
+209	1	1
+70	1	1
+223	0	20
+182	1	1
+69	1	1
+56	1	1
+111	1	1
+220	1	1
+89	1	1
+119	1	1
+113	2	0
+195	1	1
+46	1	1
+101	8	8
+85	1	1
+50	0	4
+76	0	4
+53	3	1
+43	1	1
+153	1	1
+53	1	1
+195	6	0
+60	1	1
+278	1	0
+42	1	1
+298	1	1
+54	1	1
+262	4	4
+67	1	1
+32	1	0
+28	1	1
+612	1	1
+78	1	1
+157	1	1
+19	1	1
+64	1	2
+31	1	1
+52	1	1
+51	1	1
+77	10295	10251
+91	1	1
+35	1	1
+5232	1	1
+47	1	1
+295	2	0
+2065	2	0
+1143	13	13
+335	2	0
+1944	4	0
+39	6	0
+4057	5	8
+535	1	1
+16	1	1
+1555	0	1
+3130	1	1
+17	1	1
+4196	1	0
+14974	0	1
+3667	2	6
+42	22	0
+63	2	0
+15	2	0
+61	0	160
+66	1	14
+70	2	0
+25	44	4
+49	6	77
+18	0	6
+24	0	2
+57	143	3
+61	0	2
+29	20	0
+37	0	2
+29	0	74
+58	1	29
+34	1	5
+21	31	0
+12	0	65
+62	11	0
+5	0	41
+68	1	42
+23	1	3
+12	2	0
+17	1	29
+51	29	1
+6	2	0
+25	53	1
+52	2	0
+125	19	58
+124	41	0
+51	49	29
+79	89	0
+53	21	0
+5064	0	2
+6897	1	1
+38	1	1
+2821	0	1
+85	1	1
+31	0	4
+399	14	14
+408	0	1
+956	1	1
+29	1	0
+9	2	0
+442	4	0
+342	1	1
+24	1	1
+131	1	1
+198	1	1
+370	0	1
+34	1	1
+447	21	20
+259	1	1
+23	0	1
+121	2	0
+2257	1	1
+22	1	1
+811	1	1
+27	1	1
+484	0	1
+259	0	5
+843	0	2889
+55	0	88
+1189	2	0
+2276	1	0
+353	8	0
+7126	0	1
+798	1	1
+31	0	1
+6	1	1
+268	1	1
+27	1	1
+131	0	2
+47	1	1
+367	1	1
+61	1	1
+84	14	14
+173	15	15
+883	1	1
+41	1	1
+1356	1	1
+134	1	1
+62	1	1
+18	1	1
+644	1	1
+17	1	1
+297	15	14
+1015	26	26
+1532	4	0
+16	1	1
+183	1	0
+2792	12	12
+2660	0	2
+254	1	2
+1369	1	0
+342	0	1
+49	1	1
+733	0	1
+50	82	82
+60	1	1
+48	1	1
+1488	1	0
+97	1	1
+84	6	6
+214	1	1
+37	1	1
+222	1	1
+53	1	1
+220	58	0
+238	0	3
+459	1	1
+39	1	1
+222	1	1
+67	1	1
+280	1	1
+45	0	16
+208	1	1
+39	1	1
+135	1	1
+46	1	1
+121	1	1
+19	1	1
+349	1	1
+30	1	1
+56	1	1
+23	1	1
+283	1	1
+51	2	2
+217	1	1
+44	1	1
+92	1	1
+36	1	1
+67	1	1
+38	3	1
+23	4	0
+598	1	1
+45	1	1
+663	1	1
+59	1	0
+10	1	1
+70	1	1
+65	2	0
+11	0	16
+36	1	1
+342	17	17
+70	0	3
+243	1	1
+55	1	1
+63	17	17
+2165	5	2
+132	10	6
+136	18	13
+363	1	1
+89	1	1
+382	1	1
+29	1	1
+58	8	7
+297	4	0
+66	1	1
+93	1	0
+145	1	1
+31	5	5
+576	1	1
+89	1	1
+811	16	16
+428	0	13
+67	1	1
+193	2	2
+23	1	1
+51	1	0
+727	1	0
+1148	12	12
+837	1	1
+77	1	1
+941	10	10
+776	19	19
+300	1	1
+24	1	1
+256	1	7
+93	1	1
+188	17	13
+117	1	1
+43	1	1
+563	1	1
+104	4	4
+2898	1	1
+46	1	1
+282	1	1
+39	1	1
+698	1	1
+20	1	1
+140	1	1
+26	1	1
+745	0	2
+541	6	0
+1540	1	0
+781	1	1
+35	4	4
+202	1	1
+48	1	1
+168	1	1
+53	1	1
+379	10	10
+1178	14	14
+132	5	0
+555	1	1
+42	1	1
+573	1	1
+21	1	1
+462	1	1
+43	1	1
+121	1	1
+48	0	3
+13	1	7
+8319	1	0
+21899	0	1
+8703	0	1
+1206	0	1
+13954	0	1
+12475	1	0
+6716	0	1
+3072	0	4
+7591	0	1
+3322	9	10
+539	1	0
+1736	14	0
+3128	0	2
+4464	0	1
+120	4	4
+3473	1	0
+378	1	0
+576	5	9
+684	0	3
+1182	1	0
+654	0	3
+2049	1	0
+6838	1	1
+39	1	1
+186	1	0
+2718	1	1
+30	1	1
+160	11	11
+4954	0	1
+420	1	1
+123	1	1
+156	0	4
+219	4	0
+195	1	0
+4402	3	0
+3045	0	1
+1249	1	0
+3522	0	10
+808	5	1
+349	0	1
+8538	5	0
+455	1	0
+119	0	1
+1127	1	0
+276	1	0
+10672	1	0
+833	0	1
+4251	1	0
+8	1	1
+2079	0	1
+1736	8	11
+1612	0	1
+1373	5	0
+2438	4	0
+6147	7	0
+64	1	1
+3799	1	0
+258	2	0
+899	1	0
+1362	8	9
+593	0	2
+3351	2	0
+618	0	4
+917	0	3
+2797	2	0
+2776	2	0
+23968	6	0
+1616	0	1
+1686	0	4
+2221	0	8
+252	14783	14780
+11763	0	1
+2431	1	0
+158	0	1
+281	1	0
+1573	0	1
+11079	1	0
+6938	0	1
+4376	61201	59265
+14552	0	4
+672	1	1
+26	1	1
+461	1	1
+33	0	2
+16	1	1
+649	1	1
+48	1	1
+818	1	1
+21	1	1
+424	1	1
+25	1	1
+632	1	1
+39	1	1
+310	1	1
+27	1	1
+616	1	0
+17043	23170	23168
+104	7	6
+290	3	3
+117	13	0
+2194	0	1
+191	0	1
+118	1	0
+1283	7	7
+723	1	0
+7453	1	0
+3382	0	1
+2179	0	49
+5260	0	1
+4607	1	0
+32465	1	0
+1362	0	1
+20971	5	4
+11765	9	9
+746	11	11
+19671	17	17
+439	16	16
+9146	0	3
+99	1	1
+19	1	1
+259	1	1
+57	1	1
+202	1	1
+27	1	1
+2009	9	9
+2299	1	1
+43	1	1
+1287	1	0
+22328	5	0
+47	12	0
+1295	77056	62052
+228	0	2
+615	1	0
+1965	0	2
+1466	1	0
+3821	0	1
+2806	1	1
+110	0	1
+1422	0	1
+324	1	0
+1825	1	0
+311	0	1
+11796	1	0
+2273	2	1
+6123	1	0
+18640	29	29
+1283	0	3
+167	1	0
+11393	6	6
+708	15	14
+1887	10	0
+509	1	0
+1581	1	1
+46	1	1
+811	1	1
+31	0	1
+1557	43	43
+1172	1	1
+18	1	1
+67	1	0
+2081	0	2
+373	0	4
+1829	1	1
+56	0	1
+1700	0	4
+2886	2	0
+14416	1	0
+2137	1	0
+2717	0	1
+1587	0	1
+7106	8	0
+2428	1	1
+50	1	0
+1082	1	1
+42	1	1
+639	1	0
+717	11	11
+53	1	1
+61	1	1
+454	1	1
+26	1	1
+1053	1	1
+60	1	1
+51	1	1
+26	1	0
+102	1	1
+67	1	1
+71	1	1
+134	1	1
+85	1	1
+607	36	0
+58	1	1
+1266	2	0
+480	14	21
+1459	2	1
+435	15	17
+1204	30	0
+1762	2	0
+123	1	0
+3025	0	1
+771	1	0
+3211	0	1
+3410	13	0
+1260	1	0
+591	0	1
+1107	15	15
+5811	0	22
+4103	0	2
+4882	1	0
+2138	3	2
+2203	2	1
+2338	1	0
+3316	1	1
+27	2	0
+6360	0	1
+251	19	7
+6605	1	1
+23	2	0
+360	0	2
+1292	0	2
+3992	46	46
+554	0	21
+4473	2	3
+921	1	1
+47	1	1
+2605	9	3
+50	1	1
+178	1	1
+26	1	1
+316	0	2
+1120	4	0
+177	1	2
+960	1	1
+65	1	1
+964	4	4
+783	8	8
+61	34	13
+121	1	1
+22	1	0
+118	1	1
+49	4	4
+281	1	1
+27	1	1
+958	0	1
+107	1	1
+31	1	1
+171	14	14
+302	0	13
+33	1	1
+108	0	4
+98	1	1
+53	1	1
+457	2	0
+529	1	1
+37	2	0
+1829	1	1
+38	1	1
+440	1	1
+82	3	4
+647	45	45
+660	1	1
+28	1	1
+1993	0	1
+373	19	19
+835	1	1
+42	1	1
+947	1	1
+36	1	0
+1055	1	1
+43	1	1
+475	1	0
+60	1	1
+127	1	1
+509	1	1
+71	1	1
+485	1	0
+26	1	1
+531	1	1
+18	1	1
+551	1	1
+18	1	1
+884	5	5
+147	53	60
+527	1	1
+26	2	2
+322	0	17
+32	2	2
+85	1	1
+45	1	1
+625	0	323
+540	0	1
+43	1	1
+266	0	2
+228	1	1
+42	1	1
+283	1	1
+92	1	1
+381	1	1
+40	1	1
+1906	0	4
+3495	0	4
+967	1	1
+76	1	1
+3236	4	4
+529	7	7
+246	4	0
+38	1	1
+156	0	6
+1466	0	2
+499	1	0
+937	1	1
+45	1	1
+421	6	0
+87	22	22
+1254	1	1
+36	0	1
+357	18	18
+391	0	1
+451	1	0
+105	1	1
+47	1	0
+255	6	6
+739	3	0
+386	1	1
+33	1	1
+281	4	0
+481	2	0
+495	1	1
+42	4	0
+219	0	1
+408	1	1
+23	1	1
+283	1	1
+25	0	1
+541	1	0
+88	2	0
+216	1	1
+29	1	1
+457	1	0
+331	9	1
+199	15	15
+228	1	0
+4	2	0
+333	0	1
+19	1	1
+910	1	1
+27	1	1
+142	3	3
+35	1	1
+1211	1	1
+34	1	1
+667	0	2
+64	1	1
+78	1	1
+1519	1	1
+27	1	1
+154	14	14
+1090	1	1
+40	0	3
+35	1	1
+1355	0	4
+79	1	1
+145	1	1
+63	1	1
+70	1	1
+21	1	1
+695	1	1
+41	2	2
+564	1	1
+46	1	1
+279	4	0
+38	5	5
+3523	32	32
+545	1	1
+27	1	0
+54	15	16
+1212	0	14
+34	0	11
+787	2	0
+3691	1	0
+1843	1	1
+45	1	0
+11	1	2
+3499	1	1
+27	1	1
+1047	0	2
+1804	2	0
+1079	1	1
+17	1	1
+639	3	5
+73	1	1
+13	13	0
+66	1	1
+391	0	7
+4547	0	1
+53	9	6
+691	0	1
+989	1	1
+143	1	1
+223	0	2
+95	1	1
+1000	1	1
+41	1	1
+93	1	1
+49	1	1
+606	1	1
+48	1	1
+128	0	4
+109	1	31
+44	10	781
+62	4	0
+129	1	1
+62	1	1
+106	1	1
+247	1	1
+20	18	4
+125	1	1
+43	1	1
+909	0	2
+381	4	4
+74	1	1
+408	1	0
+1595	5	0
+3690	1	1
+64	1	1
+754	0	4
+1877	1	1
+49	1	1
+1095	11	0
+734	0	23
+3072	2	0
+1879	0	1
+572	0	8
+215	1	1
+58	1	1
+301	1	1
+42	1	1
+265	24	0
+209	11	11
+953	1	1
+42	0	5
+58	1	0
+95	1	0
+210	1	1
+27	1	1
+882	1	1
+17	1	1
+751	0	1
+24	1	1
+351	1	1
+43	3	3
+565	1	1
+15	1	1
+150	27	27
+94	1	0
+323	1	1
+23	1	1
+221	7	7
+705	15	0
+631	2	0
+64	1	1
+1577	1	1
+21	0	1
+354	0	9
+189	0	1
+283	1	1
+48	1	1
+227	1	1
+40	0	3
+1357	0	2
+1571	7	7
+1153	1	1
+93	1	1
+797	14	14
+433	8	0
+108	11	11
+140	1	1
+40	1	1
+470	1	1
+42	1	1
+1106	0	2
+84	4	4
+129	1	1
+123	1	0
+95	1	1
+82	0	3
+661	1	1
+77	1	1
+57	1	1
+62	1	1
+473	2	0
+262	6	0
+45	1	1
+49	3	0
+321	0	1
+197	2	104
+87	222	0
+115	0	10
+92	0	4
+108	6	0
+563	14	14
+324	1	0
+205	1	1
+17	1	1
+495	0	1
+201	4	0
+14	1	1
+1080	1	1
+24	1	1
+91	24	24
+279	1	1
+95	1	1
+121	1	1
+62	1	1
+2371	1	0
+164	9	1
+655	1	1
+30	1	1
+271	1	1
+47	1	1
+609	1	0
+1780	2	0
+742	1	1
+40	1	1
+272	1	1
+52	1	1
+1187	1	1
+23	1	1
+254	1	1
+60	1	1
+176	3	6
+463	1	1
+36	1	1
+797	1	1
+22	1	1
+395	5	2
+61	1	1
+31	3	3
+226	1	1
+59	1	1
+581	1	1
+46	1	1
+412	1	1
+23	1	0
+74	1	1
+17	1	1
+81	1	1
+24	1	1
+83	15	15
+363	1	1
+91	1	1
+383	20	20
+199	13	13
+976	1	1
+39	0	3
+161	14	15
+127	16	16
+517	1	1
+132	1	1
+167	28	28
+124	1	1
+68	0	22
+1074	0	1
+175	1	0
+1018	1	1
+90	4	4
+1034	15	15
+69	1	1
+33	1	1
+174	1	1
+56	1	1
+169	1	0
+201	1	1
+30	1	1
+58	1	1
+38	1	1
+91	1	1
+98	4	4
+65	1	1
+19	2	0
+104	6	5
+25	1	1
+218	1	1
+37	1	1
+343	236832	150022
+67	8	8
+36	0	11
+62	1	1
+107	1	1
+68	3	130
+66	4	4
+50	21	21
+98	1	1
+127	1	0
+192	1	1
+71	1	1
+52	1	1
+200	1	1
+307	0	1
+331	1	1
+97	11	11
+171	1	1
+61	1	1
+37	1	1
+156	3	0
+63	0	3
+155	4	1
+31	2	0
+232	1	1
+33	1	1
+175	2	0
+131	6	6
+1409	0	3
+180	1	1
+65	0	1
+703	1	1
+19	1	1
+702	1	1
+65	1	1
+532	1	1
+48	1	1
+347	0	12
+578	16	17
+965	1	1
+45	1	1
+893	78201	80000
+406	1	1
+22	1	1
+462	1	1
+139	1	1
+154	1	0
+37	1	9
+11	2	0
+22	2	0
+14	46	22
+320	1	1
+117	1	1
+493	1	1
+129	1	1
+243	27	30
+170	1	1
+125	3	3
+2476	4	0
+27525	1	0
+2162	0	2
+2887	0	1
+17286	4	0
+22898	0	1
+51	9	9
+60	26	25
+312	15	11
+1008	17	17
+85	1	1
+49	1	1
+702	1	0
+87	1	1
+37	1	1
+859	8	8
+296	4	4
+105	0	4
+43	1	1
+67	10	7
+2839	3	0
+1283	1	1
+67	0	1
+32	2	0
+61	1	1
+140	15	15
+1047	1	1
+38	1	1
+87	1	1
+24	5	4
+1291	1	1
+49	1	1
+421	0	1
+75	1	1
+78	1	1
+243	1	0
+33	1	1
+116	19	19
+65	0	1
+238	0	1
+179	2	1
+67	1	1
+60	1	1
+32	1	1
+677	4	6
+83	314	0
+334	1	0
+1018	5	5
+127	1	1
+83	1	1
+347	0	2
+111	1	1
+30	1	1
+66	1	1
+38	1	1
+218	8	8
+754	1	1
+65	1	1
+182	1	1
+21	1	1
+285	1	1
+75	1	1
+147	6	0
+65	1	1
+42	1	1
+380	1	1
+84	2	0
+88	1	1
+25	1	1
+210	1	1
+17	1	1
+136	6	5
+108	1	1
+40	1	0
+50	1	1
+111	1	0
+21	0	1066
+119	0	1
+2641	1	1
+22	1	1
+689	1	1
+41	1	1
+1415	1	1
+29	1	1
+2252	1	1
+19	1	1
+1524	0	10
+2104	0	1
+511	2	0
+1696	26	8
+2593	0	177
+338	1	1
+37	2	2
+395	10	0
+67	1	1
+131	1	1
+31	1	1
+386	1	1
+42	1	1
+372	1	1
+48	1	1
+8705	0	4
+329	9	9
+600	2	0
+261	8	8
+9909	0	2
+2337	2	0
+2567	1	1
+26	1	1
+561	1	1
+48	1	1
+2440	1	1
+30	1	1
+1289	0	1
+162	1	0
+730	0	3
+658	1	0
+25	1	1
+1027	1	1
+43	1	1
+472	0	1
+219	1	1
+20	1	1
+495	1	0
+6	2	0
+1007	0	1
+169	0	10
+33	1	1
+266	11	11
+752	1	1
+30	1	1
+438	1	1
+39	1	1
+511	0	1
+1247	1	0
+1055	1	0
+491	1	0
+108	1	1
+48	1	1
+1324	0	1
+143	1	1
+40	1	1
+679	1	1
+45	1	1
+1036	0	2
+58	1	1
+46	1	1
+229	16	16
+149	10	10
+94	1	1
+63	1	1
+222	2	0
+55	1	1
+115	5	1
+219	15	15
+692	28	28
+159	1	1
+41	1	1
+211	1	0
+20	1	1
+1099	0	4
+155	6	0
+178	13	15
+32	1	1
+953	1	1
+47	1	1
+174	1	1
+22	1	1
+402	0	12
+588	5	21
+288	4	4
+86	1	1
+29	0	2
+67	3	0
+641	0	1
+571	0	1
+250	1	1
+34	1	1
+255	0	2
+572	12	12
+275	6	1
+974	0	1
+578	12	12
+612	1	1
+43	1	1
+56	0	7
+1170	0	1
+1242	0	8
+2108	5	0
+1090	0	2
+4424	1	1
+34	1	1
+4897	8	0
+1998	2	0
+114	0	1
+2874	1	1
+21	1	1
+442	22	22
+805	0	1
+3476	16	0
+7063	0	1
+65	3	0
+7475	0	4
+9515	5	1
+172	1	1
+49	1	1
+1349	22	22
+9662	2	0
+4856	3	0
+7447	6	6
+421	1	0
+884	6	0
+17	1	0
+3075	1	0
+11403	50004	0
+1397	12	12
+1859	3	1
+3762	2	0
+601	2	0
+7617	1	0
+1604	0	16
+3589	0	1
+1487	2	1
+1196	0	20
+2233	1	0
+192	4	4
+1470	9	27
+880	1	12
+2490	1	0
+151	1	1
+33	1	1
+2191	1	1
+47	1	1
+572	1	1
+17	1	1
+512	1	1
+83	1	1
+107	0	1
+4191	1	1
+36	1	1
+1530	1	1
+23	1	1
+311	0	4
+47	1	1
+141	2	0
+73	1	1
+330	1	1
+54	0	1
+32	0	1
+210	4	0
+219	1	0
+24	1	1
+425	1	1
+34	2	2
+1227	11	11
+2454	1	1
+36	1	1
+1368	1	1
+39	1	1
+134	1	1
+28	1	1
+123	1	1
+46	4	4
+839	9	0
+1244	1	1
+32	5	5
+2063	12	0
+357	3	0
+321	46	46
+873	1	1
+47	1	1
+1156	10	9
+1180	9	1
+271	9	9
+1870	0	1
+17	1	0
+366	7	7
+101	0	1
+134	8	8
+1654	0	4
+8741	1	1
+24	1	1
+1003	0	186
+12	0	20
+906	13	13
+1313	241	241
+2062	16	16
+1485	1	1
+18	1	1
+883	1	1
+20	1	1
+1354	1	1
+28	1	1
+283	5	5
+640	1	1
+40	1	1
+560	1	1
+42	1	1
+1144	19	19
+57	1	1
+21	1	1
+216	1	1
+109	1	1
+105	1	1
+208	5	5
+124	1	1
+112	3	3
+207	40	40
+244	1	1
+60	1	1
+98	1	1
+50	1	1
+256	5	5
+23	1	1
+157	1	1
+33	1	1
+143	1	1
+59	1	1
+51	1	1
+45	1	0
+73	1	1
+81	1	1
+5071	0	35
+42407	0	26
+13084	15	11
+333	5	0
+1235	6	6
+899	1	0
+1077	11	0
+1521	1	0
+38	1	1
+135	1	1
+42	1	1
+63	4	3
+385	1	1
+49	1	1
+77	20	22
+111	11	11
+190	2	2
+45	1	1
+373	1	1
+47	1	1
+77	10	10
+186	1	1
+24	1	1
+855	1	0
+23	1	1
+86	27	27
+148	1	0
+249	1	1
+22	1	1
+88	1	1
+31	1	1
+816	0	331
+433	1	1
+31	1	1
+53	1	1
+27	1	1
+101	1	1
+29	1	1
+406	1	1
+43	1	1
+306	1	1
+25	0	5
+68	1	1
+727	7	7
+237	1	1
+65	1	1
+178	1	1
+52	1	1
+667	1	1
+17	1	1
+359	1	1
+22	1	1
+1244	1	1
+36	1	1
+1349	29808	29806
+7637	1	1
+37	1	1
+1019	0	1
+10399	0	1
+10494	21750	21748
+607	26	26
+5347	2	0
+2375	3	0
+1594	1	0
+363	4	0
+2394	2	0
+3590	0	2
+2891	1	0
+621	1	0
+563	0	2
+85	0	13
+160	18	19
+1807	0	2
+291	0	1
+2273	8	0
+2568	1	0
+657	0	1
+772	4	0
+377	8	0
+62	52	0
+778	0	1
+391	62	72
+1596	2	0
+1317	2	0
+5358	0	3
+2273	0	1
+597	0	8
+993	0	26
+1897	1	0
+76	0	1
+966	1	0
+2611	2	0
+1374	18	0
+831	33	33
+1574	0	2
+306	0	1
+4789	0	3
+2404	1	1
+33	1	1
+507	4	0
+1627	50858	50856
+7863	53819	53813
+259	1	0
+752	3	1
+497	5	6
+3113	3	0
+748	1	0
+3002	0	1
+836	1	1
+22	1	0
+251	1	1
+27	1	1
+4128	0	1
+8869	29	0
+4065	0	2
+19869	0	1
+564	1	0
+4734	1	1
+36	1	1
+5630	1	0
+339	0	3
+1029	12	12
+15996	0	3
+1380	6	6
+57	0	1
+6265	14	14
+127	1	1
+21	1	1
+1709	1	1
+131	1	1
+64	9	9
+67	0	2
+290	23	22
+456	1	0
+587	0	1
+1610	0	2
+1243	1	0
+26	1	1
+2049	0	1
+1091	0	21
+357	11	14
+90
+
+chain 125812 chr6_ssto_hap7 4928567 + 3907506 3911494 chr4 191273063 + 128070000 128074446 1022492
+87	39	39
+217	93	93
+54	128	128
+101	185	185
+82	24	24
+306	274	274
+86	19	19
+109	42	42
+79	311	313
+96	87	87
+72	74	530
+57	170	170
+64	268	268
+56	709	709
+99
+
+chain 123442 chr6_ssto_hap7 4928567 + 3929629 3931354 chr2 242951149 - 63927014 63946734 1041108
+108	1	1
+44	0	2
+39	0	554
+170	0	2655
+81	3	3007
+63	15	1052
+119	0	1562
+96	0	5290
+67	9	9
+97	0	3890
+317	1	1
+39	1	1
+234	0	4
+116	1	1
+18	3	0
+83
+
+chain 92865 chr6_ssto_hap7 4928567 + 3892702 3894943 chr5 180857866 - 117045391 117059708 1366079
+75	6	6
+69	60	59
+68	1	0
+272	118	118
+148	29	29
+50	4	4
+75	91	91
+79	11	11
+52	94	94
+155	362	12440
+253	93	93
+76
+
+chain 86945 chr6_ssto_hap7 4928567 + 4078541 4079510 chr17 78774742 - 73855076 73856044 1454888
+79	12	12
+357	1	1
+20	1	1
+121	1	0
+377
+
+chain 80740 chr6_ssto_hap7 4928567 + 2343665 2344522 chr6 170899992 - 139781917 139782778 1563240
+341	0	4
+516
+
+chain 52870 chr6_ssto_hap7 4928567 + 2557772 2559707 chr1 247249719 + 7396445 7398379 2394598
+102	170	170
+115	745	743
+132	82	82
+58	214	214
+173	73	74
+71
+
+chain 47213 chr6_ssto_hap7 4928567 + 3973739 3974661 chr5 180857866 + 134244858 134245983 2704507
+144	28	28
+67	90	94
+193	60	61
+52	141	339
+53	41	41
+53
+
+chain 45302 chr6_ssto_hap7 4928567 + 4047815 4048319 chr5 180857866 - 98127286 98127790 2833261
+202	1	1
+153	1	1
+147
+
+chain 41978 chr6_ssto_hap7 4928567 + 1328154 1328662 chr6 170899992 + 30106460 30106967 3091365
+343	49	48
+116
+
+chain 40676 chr6_ssto_hap7 4928567 + 3875056 3875551 chr11 134452384 - 84966990 84967480 3207740
+246	1	1
+93	33	28
+122
+
+chain 35112 chr6_ssto_hap7 4928567 + 3906419 3911395 chr6 170899992 - 169520190 169525607 1043651
+51	464	464
+53	202	202
+87	154	151
+74	492	483
+28	798	798
+12	65	65
+50	80	80
+67	619	621
+27	1627	2078
+26
+
+chain 32670 chr6_ssto_hap7 4928567 + 3859757 3860527 chrX 154913754 + 119403135 119403904 4176412
+56	142	141
+152	178	178
+66	56	56
+120
+
+chain 29091 chr6_ssto_hap7 4928567 + 3895286 3896158 chr11 134452384 + 7157531 7158401 1526824
+161	614	612
+97
+
+chain 28481 chr6_ssto_hap7 4928567 + 4205119 4205417 chr17 78774742 + 29063769 29064067 5407271
+298
+
+chain 27018 chr6_ssto_hap7 4928567 + 3840659 3840971 chr18 76117153 - 36956533 36956845 6049052
+120	15	15
+177
+
+chain 25604 chr6_ssto_hap7 4928567 + 3994310 3994584 chr15 100338915 - 55375038 55375312 6715162
+274
+
+chain 23990 chr6_ssto_hap7 4928567 + 1194494 1195270 chr7 158821424 - 51137320 51138262 7695545
+178	101	101
+72	385	551
+40
+
+chain 23269 chr6_ssto_hap7 4928567 + 4043201 4044141 chr6 170899992 + 32821586 32822354 8132442
+218	672	500
+50
+
+chain 22259 chr6_ssto_hap7 4928567 + 1328662 1328894 chr10 135374737 + 129836641 129836873 8045146
+232
+
+chain 21089 chr6_ssto_hap7 4928567 + 3982819 3983044 chr14 106368585 + 105956394 105956619 9616367
+225
+
+chain 21066 chr6_ssto_hap7 4928567 + 4492538 4492777 chr8 146274826 + 14484871 14485110 2051461
+239
+
+chain 19470 chr6_ssto_hap7 4928567 + 3875397 3875736 chrX 154913754 - 111580561 111580900 4149836
+32	122	122
+185
+
+chain 19015 chr6_ssto_hap7 4928567 + 4093694 4093926 chr11 134452384 + 111558067 111558299 11259779
+149	20	20
+63
+
+chain 18910 chr6_ssto_hap7 4928567 + 3979875 3980839 chr6 170899992 + 32656485 32657452 11346766
+153	738	741
+73
+
+chain 18705 chr6_ssto_hap7 4928567 + 4047429 4047645 chr3 199501827 + 1828236 1828452 4490189
+145	5	5
+66
+
+chain 15452 chr6_ssto_hap7 4928567 + 3913430 3913596 chrX 154913754 + 67920599 67920765 14594390
+166
+
+chain 15351 chr6_ssto_hap7 4928567 + 2675966 2676167 chr11 134452384 + 74426248 74426449 14701293
+99	26	26
+76
+
+chain 15233 chr6_ssto_hap7 4928567 + 4047645 4047815 chr9 140273252 + 78741245 78741415 2998928
+170
+
+chain 15018 chr6_ssto_hap7 4928567 + 1260636 1260812 chr10 135374737 + 90412720 90412896 15044285
+117	3	3
+56
+
+chain 13654 chr6_ssto_hap7 4928567 + 180964 181124 chr18 76117153 - 3498140 3498418 7857183
+83	1	1
+24	4	122
+48
+
+chain 13627 chr6_ssto_hap7 4928567 + 3831356 3831761 chr6 170899992 + 32665471 32665876 16657612
+57	86	85
+47	147	148
+68
+
+chain 13048 chr6_ssto_hap7 4928567 + 3955374 3955802 chr2 242951149 + 206984071 206984490 17422582
+94	272	263
+62
+
+chain 12923 chr6_ssto_hap7 4928567 + 3954673 3954823 chr18 76117153 - 36956845 36956995 17596042
+150
+
+chain 12671 chr6_ssto_hap7 4928567 + 4090259 4090393 chrX 154913754 - 65797896 65798030 17982401
+134
+
+chain 12395 chr6_ssto_hap7 4928567 + 3983294 3983607 chrX 154913754 - 110185784 110186095 13720297
+4	222	220
+87
+
+chain 12272 chr6_ssto_hap7 4928567 + 2565285 2565441 chrX 154913754 + 154847615 154847763 18572104
+71	1	1
+25	8	0
+51
+
+chain 12207 chr6_ssto_hap7 4928567 + 3955802 3957116 chr4 191273063 - 84720316 84722799 17649000
+5	186	1341
+68	1003	1017
+52
+
+chain 12179 chr6_ssto_hap7 4928567 + 3836462 3836590 chr6 170899992 + 32566069 32566197 18716373
+128
+
+chain 12178 chr6_ssto_hap7 4928567 + 4018814 4018980 chr14 106368585 - 58343221 58343386 18718222
+55	26	25
+85
+
+chain 12137 chr6_ssto_hap7 4928567 + 3877094 3877505 chr7 158821424 + 90920405 90920810 18779047
+54	266	260
+91
+
+chain 11985 chr6_ssto_hap7 4928567 + 3892853 3894867 chr3 199501827 - 92708356 92711059 1441087
+59	394	394
+65	307	307
+90	391	391
+54	622	1311
+32
+
+chain 11952 chr6_ssto_hap7 4928567 + 4105293 4105419 chr4 191273063 - 72853862 72853988 19072608
+126
+
+chain 11593 chr6_ssto_hap7 4928567 + 3812675 3812798 chr1 247249719 - 238369051 238369174 19677686
+123
+
+chain 11535 chr6_ssto_hap7 4928567 + 1260812 1261322 chr1 247249719 - 129350638 129351114 18024798
+7	405	371
+98
+
+chain 11457 chr6_ssto_hap7 4928567 + 3994790 3994923 chr3 199501827 - 53316844 53316977 14718915
+32	6	6
+95
+
+chain 11393 chr6_ssto_hap7 4928567 + 4065042 4065262 chr10 135374737 - 122210308 122210526 20025571
+60	86	84
+74
+
+chain 11122 chr6_ssto_hap7 4928567 + 1240573 1241390 chr6 170899992 - 139553083 139553887 20511868
+77	676	663
+64
+
+chain 10873 chr6_ssto_hap7 4928567 + 1229721 1229842 chr19 63811651 + 15986631 15986752 20965590
+121
+
+chain 10852 chr6_ssto_hap7 4928567 + 2675511 2675627 chr15 100338915 - 60167597 60167713 16273330
+116
+
+chain 10686 chr6_ssto_hap7 4928567 + 2564433 2564954 chr18 76117153 + 11332173 11332695 21332096
+80	388	389
+53
+
+chain 10631 chr6_ssto_hap7 4928567 + 3935233 3935343 chr12 132349534 - 69483966 69484076 21446055
+110
+
+chain 10605 chr6_ssto_hap7 4928567 + 1188476 1188620 chr6 170899992 + 30566919 30567064 21497459
+81	23	24
+40
+
+chain 10522 chr6_ssto_hap7 4928567 + 3885687 3885969 chr6 170899992 + 32650612 32650898 21668161
+51	155	159
+76
+
+chain 10487 chr6_ssto_hap7 4928567 + 3763802 3763912 chr6 170899992 + 32525095 32525205 21738406
+110
+
+chain 10446 chr6_ssto_hap7 4928567 + 3838076 3838188 chr10 135374737 + 116791472 116791584 21828224
+112
+
+chain 10440 chr6_ssto_hap7 4928567 + 3816404 3816534 chr3 199501827 - 53390365 53390495 21843020
+67	9	9
+54
+
+chain 10424 chr6_ssto_hap7 4928567 + 1233358 1233620 chr1 247249719 - 93388912 93389184 21873908
+71	137	147
+54
+
+chain 10414 chr6_ssto_hap7 4928567 + 3814490 3814706 chr20 62435964 - 30230151 30230368 21892854
+65	92	93
+59
+
+chain 10301 chr6_ssto_hap7 4928567 + 3898517 3899557 chr6 170899992 + 32656523 32657565 22135092
+82	902	904
+56
+
+chain 10251 chr6_ssto_hap7 4928567 + 3994584 3994790 chr1 247249719 - 4492483 4492689 9976242
+1	153	153
+52
+
+chain 10098 chr6_ssto_hap7 4928567 + 3860255 3860748 chr12 132349534 - 132021867 132022360 5505364
+30	66	66
+56	251	251
+90
+
+chain 10097 chr6_ssto_hap7 4928567 + 3816034 3816270 chr6 170899992 - 10896454 10896689 22596963
+52	115	114
+69
+
+chain 10009 chr6_ssto_hap7 4928567 + 1180658 1180788 chr7 158821424 - 7754727 7754857 22790797
+54	14	14
+62
+
+chain 9863 chr6_ssto_hap7 4928567 + 4074075 4074200 chr1 247249719 + 10410145 10410270 23122655
+62	11	11
+52
+
+chain 9833 chr6_ssto_hap7 4928567 + 1235234 1235338 chr6 170899992 - 141000130 141000234 23192992
+104
+
+chain 9829 chr6_ssto_hap7 4928567 + 3815276 3815381 chr2 242951149 - 95164602 95164707 23200543
+105
+
+chain 9703 chr6_ssto_hap7 4928567 + 4070399 4070911 chr2 242951149 - 75663422 75663931 23509887
+63	390	387
+59
+
+chain 9614 chr6_ssto_hap7 4928567 + 2657013 2657750 chr6 170899992 - 140934793 140935541 23727231
+66	613	624
+58
+
+chain 9528 chr6_ssto_hap7 4928567 + 1196742 1197179 chr6 170899992 + 29878108 29878543 23937753
+59	318	316
+60
+
+chain 9448 chr6_ssto_hap7 4928567 + 4048489 4048611 chr8 146274826 - 73050790 73050912 12492975
+122
+
+chain 9438 chr6_ssto_hap7 4928567 + 3910395 3911369 chr15 100338915 - 30464954 30465929 1082363
+106	42	42
+63	674	675
+89
+
+chain 9407 chr6_ssto_hap7 4928567 + 3856752 3857141 chr6 170899992 + 32635022 32635416 24217249
+67	271	276
+51
+
+chain 9325 chr6_ssto_hap7 4928567 + 3877913 3878051 chr5 180857866 - 41992384 41992522 24382359
+55	28	28
+55
+
+chain 9223 chr6_ssto_hap7 4928567 + 4072536 4072675 chr3 199501827 + 115197797 115197935 24583947
+54	29	28
+56
+
+chain 8918 chr6_ssto_hap7 4928567 + 3893253 3894424 chr9 140273252 - 41262761 41263931 1574906
+43	979	978
+149
+
+chain 8559 chr6_ssto_hap7 4928567 + 1185037 1185127 chr6 170899992 + 29901402 29901492 25589405
+90
+
+chain 8551 chr6_ssto_hap7 4928567 + 3829560 3829651 chrX 154913754 + 101188135 101188226 25594732
+91
+
+chain 8473 chr6_ssto_hap7 4928567 + 3956061 3956256 chr9 140273252 + 73803578 73803773 19960547
+18	127	127
+50
+
+chain 8431 chr6_ssto_hap7 4928567 + 4017811 4017899 chr6 170899992 - 67344251 67344339 25766641
+88
+
+chain 8320 chr6_ssto_hap7 4928567 + 4046958 4047055 chr3 199501827 + 112943953 112944050 15335436
+35	7	7
+55
+
+chain 8195 chr6_ssto_hap7 4928567 + 1189357 1189443 chr6 170899992 + 29906107 29906193 26123218
+86
+
+chain 7977 chr6_ssto_hap7 4928567 + 3854972 3855056 chr3 199501827 - 65120650 65120734 26447349
+84
+
+chain 7864 chr6_ssto_hap7 4928567 + 3956899 3957064 chr2 242951149 + 230690248 230690413 23687196
+65	86	86
+14
+
+chain 7746 chr6_ssto_hap7 4928567 + 4069960 4070399 chr1 247249719 + 17543299 17543737 25591741
+58	375	374
+6
+
+chain 7672 chr6_ssto_hap7 4928567 + 3894447 3895071 chr11 134452384 + 90348791 90349415 1473761
+74	253	253
+37	159	159
+101
+
+chain 7498 chr6_ssto_hap7 4928567 + 3878051 3879311 chr1 247249719 + 173341048 173342322 26722357
+5	1190	1204
+65
+
+chain 7331 chr6_ssto_hap7 4928567 + 4098258 4098335 chr16 88827254 - 31115279 31115356 27543534
+77
+
+chain 7232 chr6_ssto_hap7 4928567 + 3920814 3920891 chr6 170899992 + 32620027 32620104 27728494
+77
+
+chain 7168 chr6_ssto_hap7 4928567 + 4075613 4075689 chr1 247249719 - 67121697 67121773 27863207
+76
+
+chain 7154 chr6_ssto_hap7 4928567 + 3982483 3982643 chrX 154913754 + 57427313 57427473 11452806
+160
+
+chain 6975 chr6_ssto_hap7 4928567 + 1189014 1189086 chr6 170899992 + 29905761 29905833 28257011
+72
+
+chain 6949 chr6_ssto_hap7 4928567 + 3816604 3816677 chr8 146274826 - 83195506 83195579 28299872
+73
+
+chain 6859 chr6_ssto_hap7 4928567 + 3943496 3943569 chr6 170899992 + 32632193 32632266 28469740
+73
+
+chain 6788 chr6_ssto_hap7 4928567 + 4050963 4058824 chr6 170899992 + 32827127 32834907 28622110
+50	4319	3617
+61	2525	2695
+93	658	1109
+155
+
+chain 6731 chr6_ssto_hap7 4928567 + 1724741 1724812 chrX 154913754 + 77548522 77548593 28736593
+71
+
+chain 6723 chr6_ssto_hap7 4928567 + 3873757 3873829 chr6 170899992 + 32566306 32566378 28747170
+72
+
+chain 6686 chr6_ssto_hap7 4928567 + 1260394 1260465 chr10 135374737 - 59340781 59340852 28859379
+71
+
+chain 6665 chr6_ssto_hap7 4928567 + 3154699 3154769 chr19 63811651 - 18495515 18495585 1124045
+70
+
+chain 6650 chr6_ssto_hap7 4928567 + 3860923 3861067 chr11 134452384 - 10112929 10113073 19771550
+33	61	61
+50
+
+chain 6622 chr6_ssto_hap7 4928567 + 3829455 3829525 chr2 242951149 - 225543946 225544016 28987379
+70
+
+chain 6618 chr6_ssto_hap7 4928567 + 3895820 3896010 chr13 114142980 + 101977588 101977777 1936459
+53	63	62
+74
+
+chain 6613 chr6_ssto_hap7 4928567 + 3829110 3829180 chrX 154913754 + 79202976 79203046 29019460
+70
+
+chain 6584 chr6_ssto_hap7 4928567 + 3973978 3974052 chr18 76117153 - 4274607 4274681 4481992
+74
+
+chain 6521 chr6_ssto_hap7 4928567 + 3924035 3924103 chr6 170899992 + 32624377 32624445 29251175
+68
+
+chain 6513 chr6_ssto_hap7 4928567 + 4073124 4073193 chr12 132349534 + 47073126 47073195 29262428
+69
+
+chain 6459 chr6_ssto_hap7 4928567 + 2661634 2661703 chr6 170899992 + 31350859 31350928 29378029
+69
+
+chain 6412 chr6_ssto_hap7 4928567 + 3941116 3941183 chr5 180857866 - 156512753 156512820 29524988
+67
+
+chain 6368 chr6_ssto_hap7 4928567 + 2565193 2565285 chr6 170899992 - 132294381 132294479 20980272
+55	29	35
+8
+
+chain 6368 chr6_ssto_hap7 4928567 + 4074498 4074566 chr21 46944323 + 22987814 22987882 29601883
+68
+
+chain 6359 chr6_ssto_hap7 4928567 + 3988556 3988624 chr6 170899992 + 32661355 32661423 29618339
+68
+
+chain 6278 chr6_ssto_hap7 4928567 + 3866522 3866590 chr6 170899992 + 32559120 32559188 29828351
+68
+
+chain 6275 chr6_ssto_hap7 4928567 + 1183919 1183984 chr6 170899992 + 29900614 29900679 29842805
+65
+
+chain 6265 chr6_ssto_hap7 4928567 + 3855056 3855122 chr11 134452384 + 35675446 35675512 27404543
+66
+
+chain 6240 chr6_ssto_hap7 4928567 + 3829386 3829452 chr7 158821424 + 89136765 89136831 29917662
+66
+
+chain 6231 chr6_ssto_hap7 4928567 + 4071456 4071522 chr15 100338915 + 41279078 41279144 29959209
+66
+
+chain 6221 chr6_ssto_hap7 4928567 + 4068934 4068999 chr5 180857866 + 81769172 81769237 29991772
+65
+
+chain 6158 chr6_ssto_hap7 4928567 + 3881593 3881658 chr8 146274826 + 95080661 95080726 30127973
+65
+
+chain 6116 chr6_ssto_hap7 4928567 + 3859885 3859954 chr6 170899992 - 133628666 133628735 10717008
+69
+
+chain 6039 chr6_ssto_hap7 4928567 + 3985075 3985138 chr6 170899992 + 32660531 32660594 30469869
+63
+
+chain 5986 chr6_ssto_hap7 4928567 + 4018730 4018794 chr1 247249719 - 129681820 129681884 30582101
+64
+
+chain 5986 chr6_ssto_hap7 4928567 + 3949638 3949702 chr6 170899992 + 32601206 32601270 30582240
+64
+
+chain 5977 chr6_ssto_hap7 4928567 + 3861125 3861202 chrX 154913754 - 4338266 4338343 13813425
+77
+
+chain 5976 chr6_ssto_hap7 4928567 + 2664206 2664269 chr6 170899992 + 31358648 31358711 30614237
+63
+
+chain 5958 chr6_ssto_hap7 4928567 + 3891447 3891510 chr2 242951149 + 38038620 38038683 30678163
+63
+
+chain 5912 chr6_ssto_hap7 4928567 + 3875752 3875836 chr7 158821424 - 35299548 35299632 7605861
+84
+
+chain 5886 chr6_ssto_hap7 4928567 + 1725643 1725706 chr4 191273063 - 86591247 86591310 30840494
+63
+
+chain 5792 chr6_ssto_hap7 4928567 + 4018980 4019041 chr10 135374737 - 103149812 103149873 26755020
+61
+
+chain 5742 chr6_ssto_hap7 4928567 + 3983333 3983412 chr5 180857866 + 128901198 128901277 14868038
+79
+
+chain 5702 chr6_ssto_hap7 4928567 + 3954013 3954072 chr6 170899992 + 32605878 32605937 31357680
+59
+
+chain 5594 chr6_ssto_hap7 4928567 + 4069284 4069343 chr3 199501827 - 15131518 15131577 31663339
+59
+
+chain 5502 chr6_ssto_hap7 4928567 + 3813204 3813261 chr1 247249719 - 79348621 79348678 31943035
+57
+
+chain 5348 chr6_ssto_hap7 4928567 + 4071259 4071315 chr3 199501827 + 160253017 160253073 32406182
+56
+
+chain 5330 chr6_ssto_hap7 4928567 + 3915278 3915334 chr6 170899992 + 32568311 32568367 32437918
+56
+
+chain 5330 chr6_ssto_hap7 4928567 + 2561771 2561827 chr9 140273252 - 28635638 28635694 32438181
+56
+
+chain 5304 chr6_ssto_hap7 4928567 + 4073642 4073717 chr11 134452384 - 71399807 71399882 4131480
+75
+
+chain 5230 chr6_ssto_hap7 4928567 + 3820271 3820326 chrX 154913754 - 97033891 97033946 32742019
+55
+
+chain 5203 chr6_ssto_hap7 4928567 + 4076111 4076166 chr5 180857866 + 152654188 152654243 32834294
+55
+
+chain 5185 chr6_ssto_hap7 4928567 + 4075517 4075572 chr1 247249719 + 155449681 155449736 32900354
+55
+
+chain 5152 chr6_ssto_hap7 4928567 + 3860576 3860657 chr6 170899992 + 32435407 32435488 15981349
+81
+
+chain 5151 chr6_ssto_hap7 4928567 + 3860169 3860251 chr10 135374737 - 104426563 104426645 8666574
+82
+
+chain 5139 chr6_ssto_hap7 4928567 + 4018355 4018409 chr4 191273063 + 178947604 178947658 33042950
+54
+
+chain 5132 chr6_ssto_hap7 4928567 + 3876113 3876181 chr3 199501827 + 30016279 30016347 19245837
+68
+
+chain 5130 chr6_ssto_hap7 4928567 + 3954272 3954326 chr6 170899992 + 32549431 32549485 33050033
+54
+
+chain 5103 chr6_ssto_hap7 4928567 + 1182080 1182134 chr6 170899992 + 76955761 76955815 33170047
+54
+
+chain 5094 chr6_ssto_hap7 4928567 + 1724204 1724258 chr7 158821424 + 103641158 103641212 33192903
+54
+
+chain 5085 chr6_ssto_hap7 4928567 + 1328098 1328151 chr10 135374737 + 129836820 129836873 10408987
+53
+
+chain 5085 chr6_ssto_hap7 4928567 + 4092830 4092884 chrX 154913754 - 38541067 38541121 33235347
+54
+
+chain 5066 chr6_ssto_hap7 4928567 + 1229626 1229679 chr21 46944323 - 1867343 1867396 33290794
+53
+
+chain 5031 chr6_ssto_hap7 4928567 + 3830258 3830312 chr11 134452384 + 134387408 134387462 33376437
+54
+
+chain 5021 chr6_ssto_hap7 4928567 + 3819996 3820049 chr12 132349534 - 47076480 47076533 33436792
+53
+
+chain 5018 chr6_ssto_hap7 4928567 + 4073251 4073642 chr3 199501827 - 85266868 85267256 1587398
+65	97	89
+113	2	7
+114
+
+chain 5003 chr6_ssto_hap7 4928567 + 3830053 3830106 chr1 247249719 - 154726869 154726922 33499615
+53
+
+chain 5003 chr6_ssto_hap7 4928567 + 4072679 4072732 chr16 88827254 + 14169487 14169540 33499780
+53
+
+chain 4994 chr6_ssto_hap7 4928567 + 3891033 3891086 chr21 46944323 - 10747178 10747231 33543756
+53
+
+chain 4967 chr6_ssto_hap7 4928567 + 3832675 3832728 chr6 170899992 + 32558903 32558956 33617414
+53
+
+chain 4965 chr6_ssto_hap7 4928567 + 2731195 2731249 chr6 170899992 + 31505531 31505585 32711054
+54
+
+chain 4948 chr6_ssto_hap7 4928567 + 4074823 4074875 chr4 191273063 - 118568999 118569051 33679640
+52
+
+chain 4921 chr6_ssto_hap7 4928567 + 3956534 3956586 chr1 247249719 + 94607233 94607285 33754873
+52
+
+chain 4903 chr6_ssto_hap7 4928567 + 3854886 3854938 chr7 158821424 + 104157517 104157569 33851522
+52
+
+chain 4893 chr6_ssto_hap7 4928567 + 3982754 3982817 chr22 49691432 + 37111300 37111363 16902914
+63
+
+chain 4873 chr6_ssto_hap7 4928567 + 3911814 3911922 chr18 76117153 - 50730715 50730823 6267534
+108
+
+chain 4830 chr6_ssto_hap7 4928567 + 3900138 3900189 chr6 170899992 + 32631274 32631325 34086153
+51
+
+chain 4830 chr6_ssto_hap7 4928567 + 3839078 3839129 chr7 158821424 + 82104686 82104737 34087626
+51
+
+chain 4829 chr6_ssto_hap7 4928567 + 1241391 1241441 chr6 170899992 + 29800923 29800973 34088055
+50
+
+chain 4821 chr6_ssto_hap7 4928567 + 2662906 2662957 chr3 199501827 - 33183122 33183173 34119642
+51
+
+chain 4775 chr6_ssto_hap7 4928567 + 2648374 2648424 chr6 170899992 + 31537299 31537349 34295026
+50
+
+chain 4758 chr6_ssto_hap7 4928567 + 4069230 4069281 chr12 132349534 + 47071874 47071925 34323771
+51
+
+chain 4757 chr6_ssto_hap7 4928567 + 3952724 3952774 chr6 170899992 + 32548169 32548219 34341756
+50
+
+chain 4730 chr6_ssto_hap7 4928567 + 3994932 3994982 chrX 154913754 + 47978704 47978754 34444069
+50
+
+chain 4716 chr6_ssto_hap7 4928567 + 4048342 4048408 chr3 199501827 - 34165769 34165835 12625077
+66
+
+chain 4703 chr6_ssto_hap7 4928567 + 2662371 2662421 chr19 63811651 + 65370 65420 34557514
+50
+
+chain 4694 chr6_ssto_hap7 4928567 + 4060651 4060701 chr6 170899992 + 32836714 32836764 34581664
+50
+
+chain 4679 chr6_ssto_hap7 4928567 + 3906823 3908410 chr10 135374737 + 93253585 93255039 1065758
+52	974	846
+68	463	458
+30
+
+chain 4568 chr6_ssto_hap7 4928567 + 1261137 1261199 chrX 154913754 - 132036612 132036674 19096001
+62
+
+chain 4552 chr6_ssto_hap7 4928567 + 3860527 3860576 chr15 100338915 - 42450883 42450932 16059710
+49
+
+chain 4547 chr6_ssto_hap7 4928567 + 2556944 2560436 chr12 132349534 + 103307685 103311177 2570686
+99	961	960
+40	481	480
+76	473	472
+44	1256	1259
+62
+
+chain 4462 chr6_ssto_hap7 4928567 + 2729793 2731102 chr13 114142980 - 41461751 41462033 3580573
+3	13	0
+61	0	13
+33	683	3
+44	2	0
+7	414	58
+20	0	11
+29
+
+chain 4428 chr6_ssto_hap7 4928567 + 4094024 4094075 chr14 106368585 + 31457415 31457466 15616811
+28	1	1
+22
+
+chain 4397 chr6_ssto_hap7 4928567 + 4073349 4073413 chr11 134452384 - 124082096 124082160 4425866
+64
+
+chain 4392 chr6_ssto_hap7 4928567 + 1194713 1194772 chr7 158821424 - 126060926 126060985 9905441
+59
+
+chain 4342 chr6_ssto_hap7 4928567 + 4094294 4094398 chr5 180857866 - 116975574 116975678 23231318
+23	58	58
+23
+
+chain 4295 chr6_ssto_hap7 4928567 + 2556338 2556392 chr13 114142980 + 40947099 40947153 23509763
+54
+
+chain 4294 chr6_ssto_hap7 4928567 + 1260590 1260636 chr12 132349534 - 115571292 115571338 21618938
+46
+
+chain 4197 chr6_ssto_hap7 4928567 + 4047303 4047429 chr5 180857866 + 138042715 138042841 4048116
+126
+
+chain 4074 chr6_ssto_hap7 4928567 + 3895452 3896721 chr2 242951149 - 163460907 163462170 1597366
+57	1112	1106
+100
+
+chain 4047 chr6_ssto_hap7 4928567 + 1227212 1227254 chr6 170899992 + 30567064 30567106 34943638
+42
+
+chain 4028 chr6_ssto_hap7 4928567 + 2557654 2557724 chr8 146274826 - 45767632 45767702 6509640
+70
+
+chain 3802 chr6_ssto_hap7 4928567 + 3983413 3983485 chr9 140273252 - 109331781 109331853 15187387
+72
+
+chain 3788 chr6_ssto_hap7 4928567 + 3983607 3983647 chr5 180857866 + 163886600 163886640 18371448
+40
+
+chain 3783 chr6_ssto_hap7 4928567 + 3861067 3861107 chr8 146274826 + 47663219 47663259 26644949
+40
+
+chain 3780 chr6_ssto_hap7 4928567 + 1260148 1260195 chr3 199501827 + 129107515 129107562 25050682
+47
+
+chain 3771 chr6_ssto_hap7 4928567 + 3910850 3910969 chr11 134452384 + 91939775 91939894 1347783
+119
+
+chain 3720 chr6_ssto_hap7 4928567 + 4076654 4076693 chr5 180857866 - 28755460 28755499 35075689
+39
+
+chain 3674 chr6_ssto_hap7 4928567 + 1327942 1328098 chr13 114142980 - 16623521 16623677 9556113
+156
+
+chain 3526 chr6_ssto_hap7 4928567 + 1233321 1233358 chr3 199501827 + 179624737 179624774 21949411
+37
+
+chain 3523 chr6_ssto_hap7 4928567 + 3861357 3861409 chrX 154913754 - 71079157 71079209 23377911
+52
+
+chain 3519 chr6_ssto_hap7 4928567 + 3860886 3860923 chr10 135374737 + 82581588 82581625 28921115
+37
+
+chain 3516 chr6_ssto_hap7 4928567 + 3983122 3983159 chr14 106368585 + 44215304 44215341 21050502
+37
+
+chain 3503 chr6_ssto_hap7 4928567 + 3955956 3955993 chrX 154913754 + 6516305 6516342 20940822
+37
+
+chain 3500 chr6_ssto_hap7 4928567 + 3911536 3911575 chr13 114142980 + 94757263 94757302 7214953
+39
+
+chain 3483 chr6_ssto_hap7 4928567 + 4093962 4094024 chr18 76117153 - 13046880 13046942 11655771
+62
+
+chain 3478 chr6_ssto_hap7 4928567 + 3815148 3815213 chr18 76117153 - 71040520 71040585 23549077
+65
+
+chain 3458 chr6_ssto_hap7 4928567 + 3983209 3983294 chr8 146274826 - 67597789 67597874 12879815
+85
+
+chain 3397 chr6_ssto_hap7 4928567 + 4048453 4048489 chr17 78774742 - 56852494 56852530 15165556
+36
+
+chain 3368 chr6_ssto_hap7 4928567 + 3812594 3812653 chr10 135374737 - 122033518 122033577 24304367
+59
+
+chain 3327 chr6_ssto_hap7 4928567 + 1327907 1327942 chr2 242951149 - 102468165 102468200 11981936
+35
+
+chain 3310 chr6_ssto_hap7 4928567 + 3973883 3974608 chr4 191273063 + 16003477 16004520 2930244
+28	656	974
+41
+
+chain 3301 chr6_ssto_hap7 4928567 + 2558188 2558238 chr3 199501827 + 116399611 116399661 15972636
+50
+
+chain 3279 chr6_ssto_hap7 4928567 + 2675861 2675917 chrX 154913754 + 134744376 134744432 23888160
+56
+
+chain 3275 chr6_ssto_hap7 4928567 + 1175210 1175245 chr6 170899992 + 29990315 29990350 35226054
+35
+
+chain 3266 chr6_ssto_hap7 4928567 + 3955123 3955180 chr3 199501827 - 22333077 22333134 22107567
+57
+
+chain 3198 chr6_ssto_hap7 4928567 + 3983298 3983333 chr9 140273252 - 16426927 16426962 15083539
+35
+
+chain 3194 chr6_ssto_hap7 4928567 + 3955248 3955303 chr12 132349534 + 117591668 117591723 17819023
+55
+
+chain 3180 chr6_ssto_hap7 4928567 + 3983045 3983105 chr5 180857866 - 166783333 166783393 16589034
+60
+
+chain 3166 chr6_ssto_hap7 4928567 + 3843125 3843159 chr4 191273063 + 105842978 105843012 35258022
+34
+
+chain 3121 chr6_ssto_hap7 4928567 + 3896015 3896048 chr12 132349534 + 40503685 40503718 34691345
+33
+
+chain 3047 chr6_ssto_hap7 4928567 + 3816677 3816709 chr10 135374737 - 66254665 66254697 30311304
+32
+
+chain 3032 chr6_ssto_hap7 4928567 + 4105261 4105293 chr8 146274826 - 64365138 64365170 21873611
+32
+
+chain 3023 chr6_ssto_hap7 4928567 + 4076166 4076198 chr7 158821424 - 25244743 25244775 33809340
+32
+
+chain 3020 chr6_ssto_hap7 4928567 + 3860793 3860825 chr14 106368585 - 87125958 87125990 25956389
+32
+
+chain 3015 chr6_ssto_hap7 4928567 + 3983163 3983195 chr3 199501827 + 120260171 120260203 17223389
+32
+
+chain 2990 chr6_ssto_hap7 4928567 + 3896241 3896359 chr13 114142980 + 83437980 83438098 1629523
+118
+
+chain 2988 chr6_ssto_hap7 4928567 + 3982643 3982709 chr1 247249719 + 240403964 240404030 13152492
+66
+
+chain 2975 chr6_ssto_hap7 4928567 + 2564513 2564549 chr3 199501827 - 94209737 94209773 24799761
+36
+
+chain 2970 chr6_ssto_hap7 4928567 + 4070462 4070493 chr3 199501827 - 179622086 179622117 31254285
+31
+
+chain 2964 chr6_ssto_hap7 4928567 + 3891798 3891851 chr5 180857866 + 101832950 101833003 21914612
+53
+
+chain 2888 chr6_ssto_hap7 4928567 + 4065158 4065188 chr19 63811651 - 5427097 5427127 31160360
+30
+
+chain 2845 chr6_ssto_hap7 4928567 + 2556914 2556944 chr3 199501827 - 158108130 158108160 26771676
+30
+
+chain 2753 chr6_ssto_hap7 4928567 + 1233507 1233566 chr12 132349534 + 50414483 50414542 22637631
+59
+
+chain 2740 chr6_ssto_hap7 4928567 + 3892104 3892166 chr5 180857866 + 121612373 121612435 20400021
+62
+
+chain 2698 chr6_ssto_hap7 4928567 + 3907323 3908062 chr7 158821424 + 92810174 92810913 1211789
+52	649	649
+38
+
+chain 2671 chr6_ssto_hap7 4928567 + 2565133 2565192 chr9 140273252 - 60326471 60326530 21074057
+59
+
+chain 2634 chr6_ssto_hap7 4928567 + 3829525 3829553 chr11 134452384 - 52779952 52779980 32661482
+28
+
+chain 2606 chr6_ssto_hap7 4928567 + 4048612 4048640 chr10 135374737 - 125708744 125708772 21482387
+28
+
+chain 2596 chr6_ssto_hap7 4928567 + 3956994 3957021 chr3 199501827 + 56590732 56590759 32896514
+27
+
+chain 2579 chr6_ssto_hap7 4928567 + 2557143 2557298 chr6 170899992 - 49784063 49784218 3056426
+155
+
+chain 2576 chr6_ssto_hap7 4928567 + 3895108 3895185 chr6 170899992 + 169119449 169119526 1708984
+77
+
+chain 2565 chr6_ssto_hap7 4928567 + 3829029 3829056 chr12 132349534 - 5427347 5427374 35416045
+27
+
+chain 2538 chr6_ssto_hap7 4928567 + 4095308 4095335 chrX 154913754 - 17724530 17724557 35428225
+27
+
+chain 2483 chr6_ssto_hap7 4928567 + 2785408 2785434 chr6 170899992 + 31465639 31465665 7427670
+26
+
+chain 2481 chr6_ssto_hap7 4928567 + 2556543 2556631 chr3 199501827 + 50931029 50931117 15954243
+88
+
+chain 2458 chr6_ssto_hap7 4928567 + 3955303 3955329 chr2 242951149 + 162131406 162131432 29918335
+26
+
+chain 2454 chr6_ssto_hap7 4928567 + 4073316 4073349 chr4 191273063 + 122379593 122379626 9286528
+33
+
+chain 2452 chr6_ssto_hap7 4928567 + 3955573 3955623 chr15 100338915 - 6219909 6219959 18667645
+50
+
+chain 2424 chr6_ssto_hap7 4928567 + 235781 235807 chr6 170899992 - 141897118 141897144 13814892
+26
+
+chain 2387 chr6_ssto_hap7 4928567 + 3979548 3981344 chr6 170899992 + 32629287 32631086 11569193
+64	1054	1061
+59	8	8
+33	512	508
+66
+
+chain 2367 chr6_ssto_hap7 4928567 + 3861203 3861228 chr5 180857866 - 25449026 25449051 27433905
+25
+
+chain 2364 chr6_ssto_hap7 4928567 + 3896486 3896567 chr12 132349534 - 118913454 118913535 1891796
+81
+
+chain 2348 chr6_ssto_hap7 4928567 + 2555491 2555546 chr7 158821424 + 35337254 35337309 23750585
+55
+
+chain 2343 chr6_ssto_hap7 4928567 + 3895509 3895593 chr5 180857866 + 145974017 145974101 2481028
+84
+
+chain 2329 chr6_ssto_hap7 4928567 + 3908230 3908283 chr14 106368585 - 66110025 66110078 1963434
+53
+
+chain 2303 chr6_ssto_hap7 4928567 + 3910235 3910298 chr9 140273252 + 106520457 106520520 13548409
+63
+
+chain 2290 chr6_ssto_hap7 4928567 + 1194888 1194945 chr1 247249719 + 222604152 222604209 12152481
+57
+
+chain 2264 chr6_ssto_hap7 4928567 + 4094107 4094165 chr6 170899992 - 103114933 103114991 11782722
+58
+
+chain 2239 chr6_ssto_hap7 4928567 + 3859859 3859885 chr10 135374737 - 31460228 31460254 11102876
+26
+
+chain 2227 chr6_ssto_hap7 4928567 + 3896386 3896483 chr3 199501827 + 28081389 28081486 2734455
+97
+
+chain 2194 chr6_ssto_hap7 4928567 + 1194673 1194713 chrX 154913754 - 101365357 101365397 11073774
+40
+
+chain 2194 chr6_ssto_hap7 4928567 + 3911725 3911783 chr20 62435964 + 16923180 16923238 16666656
+58
+
+chain 2183 chr6_ssto_hap7 4928567 + 3982709 3982750 chrX 154913754 + 100681659 100681700 16994110
+41
+
+chain 2146 chr6_ssto_hap7 4928567 + 1180871 1180932 chr12 132349534 + 104221177 104221238 23825292
+61
+
+chain 2099 chr6_ssto_hap7 4928567 + 1233299 1233321 chr8 146274826 + 94956096 94956118 22553602
+22
+
+chain 2073 chr6_ssto_hap7 4928567 + 3956611 3956663 chr12 132349534 - 95011302 95011354 24299162
+52
+
+chain 2037 chr6_ssto_hap7 4928567 + 3907120 3907174 chr16 88827254 + 61739431 61739485 9206264
+54
+
+chain 1971 chr6_ssto_hap7 4928567 + 1260864 1260916 chr6 170899992 - 43699516 43699568 21479541
+52
+
+chain 1962 chr6_ssto_hap7 4928567 + 3860956 3861008 chr2 242951149 - 71012239 71012291 15891024
+52
+
+chain 1959 chr6_ssto_hap7 4928567 + 4047151 4047237 chr9 140273252 + 88182498 88182584 7672012
+86
+
+chain 1911 chr6_ssto_hap7 4928567 + 4094317 4094375 chr3 199501827 + 41781958 41782016 21488153
+58
+
+chain 1911 chr6_ssto_hap7 4928567 + 1260320 1260381 chr10 135374737 - 106297874 106297935 24479059
+61
+
+chain 1874 chr6_ssto_hap7 4928567 + 2557724 2557753 chr7 158821424 + 91452357 91452386 16326510
+29
+
+chain 1780 chr6_ssto_hap7 4928567 + 3910029 3910068 chr14 106368585 - 82341010 82341049 3087250
+39
+
+chain 1777 chr6_ssto_hap7 4928567 + 2675677 2675732 chr16 88827254 + 88260921 88260976 23365193
+55
+
+chain 1697 chr6_ssto_hap7 4928567 + 2559283 2559636 chr4 191273063 - 69388564 69388918 2817550
+72	250	251
+31
+
+chain 1664 chr6_ssto_hap7 4928567 + 3911192 3911255 chr5 180857866 - 81785123 81785186 3114861
+63
+
+chain 1653 chr6_ssto_hap7 4928567 + 2560066 2560131 chr7 158821424 - 148280259 148280324 6636035
+65
+
+chain 1644 chr6_ssto_hap7 4928567 + 3910172 3910234 chrX 154913754 - 124216188 124216250 1928091
+62
+
+chain 1640 chr6_ssto_hap7 4928567 + 3906670 3906720 chr3 199501827 - 110018776 110018826 1171918
+50
+
+chain 1620 chr6_ssto_hap7 4928567 + 4048655 4048716 chr11 134452384 - 43500788 43500849 9791170
+61
+
+chain 1606 chr6_ssto_hap7 4928567 + 3837795 3837854 chr4 191273063 - 166421863 166421922 24717464
+59
+
+chain 1605 chr6_ssto_hap7 4928567 + 3875836 3875881 chr1 247249719 - 200018115 200018160 9990642
+45
+
+chain 1600 chr6_ssto_hap7 4928567 + 3957021 3957050 chr13 114142980 - 18785120 18785149 24380544
+29
+
+chain 1599 chr6_ssto_hap7 4928567 + 3955003 3955066 chr8 146274826 + 126278291 126278354 19925896
+63
+
+chain 1576 chr6_ssto_hap7 4928567 + 3910706 3910761 chr3 199501827 + 169002538 169002593 7318777
+55
+
+chain 1576 chr6_ssto_hap7 4928567 + 3876008 3876074 chr21 46944323 + 28977016 28977082 11761970
+66
+
+chain 1567 chr6_ssto_hap7 4928567 + 3909838 3909895 chr12 132349534 + 31210742 31210799 2955344
+57
+
+chain 1566 chr6_ssto_hap7 4928567 + 3893961 3894004 chr5 180857866 - 2394787 2394830 2003043
+43
+
+chain 1548 chr6_ssto_hap7 4928567 + 2556653 2556768 chr2 242951149 - 193553846 193553961 3498208
+115
+
+chain 1539 chr6_ssto_hap7 4928567 + 3891177 3891234 chr1 247249719 - 78251618 78251675 24446661
+57
+
+chain 1535 chr6_ssto_hap7 4928567 + 3911107 3911157 chr1 247249719 - 72372939 72372989 9173856
+50
+
+chain 1534 chr6_ssto_hap7 4928567 + 4094211 4094262 chrX 154913754 - 868272 868323 12957412
+51
+
+chain 1513 chr6_ssto_hap7 4928567 + 3906987 3907031 chr5 180857866 - 10434692 10434736 1299581
+44
+
+chain 1493 chr6_ssto_hap7 4928567 + 2556789 2556856 chr13 114142980 + 99769649 99769716 4762882
+67
+
+chain 1490 chr6_ssto_hap7 4928567 + 3814865 3814929 chr10 135374737 - 44217075 44217139 22840138
+64
+
+chain 1482 chr6_ssto_hap7 4928567 + 3909632 3909684 chr11 134452384 + 100031701 100031753 1214591
+52
+
+chain 1453 chr6_ssto_hap7 4928567 + 1327842 1327906 chr7 158821424 + 38479547 38479611 8534629
+64
+
+chain 1406 chr6_ssto_hap7 4928567 + 3909452 3909505 chr2 242951149 - 92980714 92980767 1301647
+53
+
+chain 1403 chr6_ssto_hap7 4928567 + 3860825 3860881 chr2 242951149 + 213976883 213976939 18753925
+56
+
+chain 1392 chr6_ssto_hap7 4928567 + 3955543 3955573 chr3 199501827 - 51819316 51819346 23522770
+30
+
+chain 1378 chr6_ssto_hap7 4928567 + 2556204 2556330 chr9 140273252 + 106017756 106017882 9913210
+126
+
+chain 1352 chr6_ssto_hap7 4928567 + 4047237 4047285 chr4 191273063 - 68812874 68812922 21085894
+48
+
+chain 1344 chr6_ssto_hap7 4928567 + 3893519 3893548 chr4 191273063 + 75333241 75333270 1578953
+29
+
+chain 1342 chr6_ssto_hap7 4928567 + 2557427 2557573 chr1 247249719 + 169787922 169788068 14592994
+146
+
+chain 1328 chr6_ssto_hap7 4928567 + 3895210 3895266 chr1 247249719 - 722390 722446 2029679
+56
+
+chain 1323 chr6_ssto_hap7 4928567 + 3815012 3815074 chrY 57772954 + 15217299 15217361 24773594
+62
+
+chain 1317 chr6_ssto_hap7 4928567 + 2559037 2559074 chr2 242951149 - 160628689 160628726 4907065
+37
+
+chain 1310 chr6_ssto_hap7 4928567 + 3859653 3859705 chrX 154913754 + 62583131 62583183 22867194
+52
+
+chain 1305 chr6_ssto_hap7 4928567 + 1233633 1233684 chr10 135374737 - 7751536 7751587 24635136
+51
+
+chain 1291 chr6_ssto_hap7 4928567 + 3908834 3908875 chr4 191273063 - 115939442 115939483 1333239
+41
+
+chain 1287 chr6_ssto_hap7 4928567 + 3909608 3909632 chr5 180857866 + 103723323 103723347 7290377
+24
+
+chain 1280 chr6_ssto_hap7 4928567 + 3895766 3895816 chr8 146274826 + 51746323 51746373 2903032
+50
+
+chain 1274 chr6_ssto_hap7 4928567 + 2557298 2557339 chrX 154913754 - 130647843 130647884 4467918
+41
+
+chain 1257 chr6_ssto_hap7 4928567 + 2558435 2558509 chr10 135374737 + 60854508 60854582 4145356
+74
+
+chain 1250 chr6_ssto_hap7 4928567 + 4094075 4094107 chr12 132349534 + 74093056 74093088 12787103
+32
+
+chain 1238 chr6_ssto_hap7 4928567 + 1229366 1229425 chr8 146274826 - 84904941 84905000 22834116
+59
+
+chain 1235 chr6_ssto_hap7 4928567 + 3861228 3861334 chr15 100338915 - 22701786 22701892 11814602
+106
+
+chain 1193 chr6_ssto_hap7 4928567 + 3906339 3906392 chr6 170899992 + 117066655 117066708 1525034
+53
+
+chain 1176 chr6_ssto_hap7 4928567 + 3909895 3909925 chr8 146274826 - 24546743 24546773 1399929
+30
+
+chain 1144 chr6_ssto_hap7 4928567 + 3892335 3892388 chrX 154913754 - 80891112 80891165 18462511
+53
+
+chain 1143 chr6_ssto_hap7 4928567 + 3876074 3876097 chr4 191273063 - 150305688 150305711 12943108
+23
+
+chain 1107 chr6_ssto_hap7 4928567 + 3890850 3890949 chr11 134452384 - 72766127 72766226 17974034
+99
+
+chain 1099 chr6_ssto_hap7 4928567 + 2557592 2557651 chr14 106368585 + 52836717 52836776 3332437
+59
+
+chain 1093 chr6_ssto_hap7 4928567 + 2560006 2560065 chr11 134452384 + 32923634 32923693 3048042
+59
+
+chain 1080 chr6_ssto_hap7 4928567 + 4073853 4073903 chr19 63811651 - 3657843 3657893 23666214
+50
+
+chain 1031 chr6_ssto_hap7 4928567 + 3910512 3910543 chr8 146274826 + 76357761 76357792 1122615
+31
+
+chain 1019 chr6_ssto_hap7 4928567 + 3956446 3956499 chr2 242951149 - 47303049 47303102 21955737
+53
+
+chain 1013 chr6_ssto_hap7 4928567 + 3876829 3876895 chr5 180857866 - 104615327 104615393 22955784
+66
+
+chain 1003 chr6_ssto_hap7 4928567 + 3699456 3699487 chr2 242951149 - 44758448 44758479 2126762
+31
+
+chain 980 chr6_ssto_hap7 4928567 + 1260084 1260145 chrX 154913754 - 382349 382410 22927465
+61
+
+chain 926 chr6_ssto_hap7 4928567 + 3896721 3896750 chr5 180857866 - 112926632 112926661 13782082
+29
+
+chain 919 chr6_ssto_hap7 4928567 + 2560983 2561043 chr4 191273063 + 44807134 44807194 22381059
+60
+
+chain 917 chr6_ssto_hap7 4928567 + 3906720 3906770 chr1 247249719 - 157593440 157593490 1436049
+50
+
+chain 909 chr6_ssto_hap7 4928567 + 3909310 3909343 chr3 199501827 + 106500697 106500730 2326646
+33
+
+chain 904 chr6_ssto_hap7 4928567 + 2560317 2560347 chr7 158821424 + 107644178 107644208 22181612
+30
+
+chain 884 chr6_ssto_hap7 4928567 + 2559977 2560006 chr1 247249719 - 197271642 197271671 12501549
+29
+
+chain 879 chr6_ssto_hap7 4928567 + 3814083 3814143 chr2 242951149 + 8957980 8958040 24745704
+60
+
+chain 871 chr6_ssto_hap7 4928567 + 3908354 3908380 chr5 180857866 - 86285693 86285719 1813846
+26
+
+chain 854 chr6_ssto_hap7 4928567 + 2559716 2559766 chr4 191273063 + 5547185 5547235 3968222
+50
+
+chain 842 chr6_ssto_hap7 4928567 + 3909997 3910029 chr12 132349534 + 65262069 65262101 1358106
+32
+
+chain 834 chr6_ssto_hap7 4928567 + 2558357 2558414 chr5 180857866 - 149870489 149870546 4554917
+57
+
+chain 818 chr6_ssto_hap7 4928567 + 3895593 3895627 chr1 247249719 - 137161630 137161664 3053056
+34
+
+chain 805 chr6_ssto_hap7 4928567 + 4046900 4046958 chr3 199501827 - 135889823 135889881 13048217
+58
+
+chain 792 chr6_ssto_hap7 4928567 + 2556476 2556543 chrX 154913754 - 448312 448379 10955677
+67
+
+chain 788 chr6_ssto_hap7 4928567 + 2557050 2557102 chr9 140273252 - 129331917 129331969 3471854
+52
+
+chain 766 chr6_ssto_hap7 4928567 + 3895074 3895108 chrX 154913754 - 143143280 143143314 1988289
+34
+
+chain 764 chr6_ssto_hap7 4928567 + 3911494 3911520 chr5 180857866 - 28611213 28611239 1520834
+26
+
+chain 760 chr6_ssto_hap7 4928567 + 3891913 3891984 chr7 158821424 + 132658309 132658380 7665022
+71
+
+chain 760 chr6_ssto_hap7 4928567 + 2558688 2558747 chr12 132349534 + 56700130 56700189 25330837
+59
+
+chain 751 chr6_ssto_hap7 4928567 + 3908062 3908116 chrX 154913754 - 27278752 27278806 23595528
+54
+
+chain 750 chr6_ssto_hap7 4928567 + 2558241 2558292 chr3 199501827 - 21470788 21470839 4018903
+51
+
+chain 747 chr6_ssto_hap7 4928567 + 1195376 1195440 chr12 132349534 + 55464534 55464598 20643872
+64
+
+chain 741 chr6_ssto_hap7 4928567 + 2558773 2558825 chr10 135374737 + 51611354 51611406 20535555
+52
+
+chain 725 chr6_ssto_hap7 4928567 + 2556857 2556911 chr2 242951149 + 129418481 129418535 15959344
+54
+
+chain 718 chr6_ssto_hap7 4928567 + 3906470 3906504 chr13 114142980 + 74008819 74008853 1439498
+34
+
+chain 683 chr6_ssto_hap7 4928567 + 4094187 4094211 chr12 132349534 - 78902290 78902314 13929920
+24
+
+chain 678 chr6_ssto_hap7 4928567 + 2557391 2557427 chr4 191273063 + 139055274 139055310 16166693
+36
+
+chain 667 chr6_ssto_hap7 4928567 + 2560843 2560917 chr5 180857866 - 57070089 57070163 4646233
+74
+
+chain 646 chr6_ssto_hap7 4928567 + 2558159 2558188 chr1 247249719 - 41799280 41799309 22422429
+29
+
+chain 632 chr6_ssto_hap7 4928567 + 3892229 3892286 chr5 180857866 + 40599364 40599421 14690520
+57
+
+chain 624 chr6_ssto_hap7 4928567 + 2558292 2558324 chr9 140273252 + 222455 222487 4174075
+32
+
+chain 617 chr6_ssto_hap7 4928567 + 3894943 3894969 chr9 140273252 - 67269827 67269853 2340131
+26
+
+chain 612 chr6_ssto_hap7 4928567 + 1195270 1195296 chr2 242951149 + 158875930 158875956 11360379
+26
+
+chain 602 chr6_ssto_hap7 4928567 + 3896359 3896385 chr2 242951149 + 96414192 96414218 2435436
+26
+
+chain 600 chr6_ssto_hap7 4928567 + 2560187 2560242 chr4 191273063 - 105845249 105845304 24497060
+55
+
+chain 588 chr6_ssto_hap7 4928567 + 3911575 3911637 chr9 140273252 + 26038500 26038562 6400007
+62
+
+chain 588 chr6_ssto_hap7 4928567 + 3911157 3911192 chr2 242951149 - 186209425 186209460 7977621
+35
+
+chain 537 chr6_ssto_hap7 4928567 + 3890472 3890554 chr20 62435964 + 39823688 39823770 23049583
+82
+
+chain 533 chr6_ssto_hap7 4928567 + 2560261 2560317 chr7 158821424 + 35749861 35749917 7559420
+56
+
+chain 506 chr6_ssto_hap7 4928567 + 1194845 1194871 chr17 78774742 + 16156064 16156090 14435127
+26
+
+chain 492 chr6_ssto_hap7 4928567 + 2561299 2561367 chr13 114142980 - 65973713 65973781 6503172
+68
+
+chain 482 chr6_ssto_hap7 4928567 + 3909557 3909588 chr4 191273063 + 109100594 109100625 25171244
+31
+
+chain 475 chr6_ssto_hap7 4928567 + 3910969 3910996 chr2 242951149 + 170022712 170022739 3066592
+27
+
+chain 474 chr6_ssto_hap7 4928567 + 2555667 2555728 chr3 199501827 + 34096453 34096514 5935624
+61
+
+chain 454 chr6_ssto_hap7 4928567 + 3783318 3783345 chr7 158821424 + 43780404 43780431 3672784
+27
+
+chain 453 chr6_ssto_hap7 4928567 + 2558825 2558856 chr12 132349534 + 9890466 9890497 23880886
+31
+
+chain 435 chr6_ssto_hap7 4928567 + 3813557 3813608 chrX 154913754 + 70635923 70635974 25591729
+51
+
+chain 433 chr6_ssto_hap7 4928567 + 3954592 3954642 chr12 132349534 + 80047789 80047839 27634718
+50
+
+chain 421 chr6_ssto_hap7 4928567 + 3906299 3906339 chr6 170899992 - 100687874 100687914 2311527
+40
+
+chain 415 chr6_ssto_hap7 4928567 + 4047055 4047086 chr2 242951149 - 64586829 64586860 16220906
+31
+
+chain 395 chr6_ssto_hap7 4928567 + 3877505 3877535 chr2 242951149 - 195767137 195767167 24444969
+30
+
+chain 389 chr6_ssto_hap7 4928567 + 2560634 2560691 chr4 191273063 - 135903806 135903863 10538130
+57
+
+chain 364 chr6_ssto_hap7 4928567 + 3892286 3892319 chr2 242951149 + 18209140 18209173 14942259
+33
+
+chain 312 chr6_ssto_hap7 4928567 + 2559887 2559937 chr6 170899992 + 118230705 118230755 8173852
+50
+
+chain 289 chr6_ssto_hap7 4928567 + 2561063 2561118 chr9 140273252 - 49339912 49339967 9048484
+55
+
+chain 276 chr6_ssto_hap7 4928567 + 3878310 3878371 chr4 191273063 - 5378508 5378569 28215176
+61
+
+chain 273 chr6_ssto_hap7 4928567 + 2560131 2560171 chr10 135374737 + 69013223 69013263 15789387
+40
+
+chain 167 chr6_ssto_hap7 4928567 + 3908301 3908353 chr3 199501827 + 163583012 163583064 2366456
+52
+
+chain 14618488008 chr7 159138663 + 10238 159128663 chr7 158821424 + 102995 158821424 7
+973	0	5
+3912	2	0
+1234	0	4
+51	6	0
+70	1	1
+24	0	1
+147	0	8
+12	1	170
+47	1	1
+246	6	0
+99	4	4
+807	0	3
+2546	0	63
+44	0	2527
+1373	1	0
+2109	456	0
+1153	1	0
+791	1	1
+49	1	0
+4175	18	26
+4318	11	11
+514	0	12
+2511	1	0
+1697	6	6
+192827	278557	150000
+5682433	40	39
+42007910	35970	40000
+2048	3	3
+2320	16	7
+17699	4	0
+5248	0	4
+2088411	1	1
+47	1	1
+4565	1	0
+7116	1	0
+2706	43050	40000
+6577293	13552	50000
+1052855	3000000	3000000
+256182	416507	50000
+190137	50000	50000
+5722629	1	0
+23	1	1
+239	1	1
+59	2	2
+138	1	1
+34	1	1
+206	3	1
+18	0	1
+410	1	1
+72	1	1
+199	1	1
+62	5	5
+120	0	1
+468	1	1
+32	1	1
+264	1	1
+23	1	1
+1459	4	4
+107	1	1
+42	0	1
+14	1	1
+201	1	1
+46	1	1
+268	20	20
+303	1	2
+866	4	0
+76	3	3
+63	1	1
+74	0	1
+25	1	1
+66	1	1
+34	2	0
+180	36	35
+93	1	1
+41	1	1
+70	1	1
+49	1	1
+63	1	1
+57	1	1
+383	1	1
+133	1	1
+87	1	1
+38	4	4
+50	1	0
+46	6	5
+136	11	11
+200	1	1
+64	5	18
+263	1	1
+32	3	3
+152	16	16
+567	0	1
+322	0	3
+1258	1	0
+504	0	4
+1142	10	11
+537	12	12
+1418	1	1
+47	1	0
+164	7	7
+113	0	5
+59	2	2
+72	1	1
+20	1	1
+380	3	3
+41	0	3
+5	2	2
+921	1	1
+34	1	1
+1607	2	2
+73	0	66
+45	0	14
+169	1	1
+53	1	1
+3195	1	1
+23	1	1
+2115	14	0
+9872	0	1
+1204	13	13
+416	0	1
+2298	0	319
+6918	10	0
+184	0	24
+2932	0	4
+1394	12	0
+1853	0	5
+3442	1	0
+469	0	3
+771	12	15
+497	1	1
+65	1	1
+1210	2	0
+4131	10	10
+1198	0	1
+718	1	1
+21	1	1
+3668	0	1
+874	1	1
+25	1	1
+2444	1	0
+1867	1	1
+29	1	1
+1660	1	0
+1233	6	0
+783	0	1
+705	3	0
+3577	0	1
+365	0	1
+3389	4	8
+2652	3	0
+664	1	0
+169	9	10
+138	1	0
+8038	56	0
+109	0	196
+522	35	0
+3003	1	1
+40	1	1
+1065	0	4
+634	1	0
+51	30	0
+66	1	9
+3081	0	2
+806	1	0
+21	1	1
+3901	27	26
+843	1	0
+6916420	50000	250000
+25789109	51216	0
+1399988	0	1
+3623	212	0
+38	1	1
+210	29	33
+1318	0	16
+2190	0	1
+145	1	0
+1388	7	7
+2240	14	14
+771	1	1
+34	1	1
+92	1	1
+39	1	1
+505	0	1
+66	1	1
+49	1	1
+159	0	1
+78	0	2
+2	0	1
+13	0	2
+7	0	1
+28	0	1
+27	5	468
+2022	0	1
+1796	7	7
+61	1	1
+20	1	1
+4560	0	3
+157730	0	1
+194	14	14
+650	12	0
+669	74	74
+820	5	0
+277	32	60
+69	5	0
+1345	0	8
+652	0	84
+118	4	0
+498	1	0
+3187	1	1
+43	1	1
+1476	3	0
+2101	0	5
+788	6	6
+872	6	0
+691	202	205
+155	33	33
+4610	7	5
+521	0	10
+2773	1	1
+38	1	1
+627	1	1
+41	1	1
+1424	1	0
+2554	8	8
+45	7	0
+614	1	1
+32	0	3
+2693	1	0
+1029	2	0
+151	1	0
+1753	21	0
+370	3	2
+969	1	0
+452	0	1
+3035	42	42
+704	2	0
+2472	6	0
+238	0	1
+1442	43	43
+126	1	0
+795	1	0
+1191	0	1
+171	16	17
+724	27	28
+2966	1	1
+38	3	1
+359	0	2
+199	1	1
+17	1	1
+1969	0	1
+251	1	0
+729	1	0
+992	1	1
+25	1	1
+203	0	4
+3211	2	0
+1006	10	8
+1571	10	10
+756	38	37
+433	1	0
+672	3	0
+4460	25	182
+5551	19	23
+942	9	10
+3433	1	2
+24	1	1
+4262	0	13
+661	0	2
+167	0	8
+3474	66	61
+162	2	0
+778	34	34
+158	1	0
+1167	1	0
+684	1	0
+878	39	39
+2012	1	0
+345	1	1
+50	1	1
+626	2	0
+27874083	136705	0
+2495	2	0
+1000	0	8
+14695	0	1
+4456	0	1
+2977	0	1
+9065130	29055	25000
+2369	0	1
+12174	20	18
+878	4	0
+5247	12	0
+3482	0	2
+6766	1	0
+2469878	1	0
+835	1	0
+2471	13	13
+751	0	8
+2241	1	0
+12	1	1
+8394	0	1
+47	1	1
+903	1	0
+5537	1	0
+269	0	1
+7114	1	1
+30	1	1
+2412	1	0
+2442	21	21
+91	1	1
+37	1	1
+96	1	1
+22	1	1
+246	1	1
+23	1	1
+241	25	25
+569	1	1
+27	1	1
+1624	0	1
+112	3	3
+45	1	1
+384	13	13
+70	0	1
+658	1	1
+20	1	1
+176	0	1
+307	19	19
+428	1	1
+19	1	1
+87	1	1
+30	1	1
+140	0	1
+292	0	2
+1492	0	1
+302	2	0
+364	1	1
+35	1	1
+1956	1	0
+728	57	57
+8010	0	1
+488	0	1
+2056	8	18
+1286	1	1
+27	1	1
+731	0	1
+1423	7	0
+2010	1	1
+19	1	1
+3925	37	37
+2438	4	0
+80	1	1
+4505	0	13
+933	12	0
+1250	1	0
+1313	0	1
+2610	1	0
+2398	1	0
+453	0	1
+346	14	14
+83	0	1
+24	1	0
+83	12	12
+277	1	0
+45	0	1
+811	0	2
+164	1	0
+104	1	0
+32	1	1
+1386	14	0
+306	1	1
+43	1	1
+2765	1	0
+1819	1	0
+1480	1	1
+24	1	1
+276	1	0
+21	1	0
+119	11	39
+542	1	1
+63	1	1
+180	1	0
+2456	0	1
+392	62	62
+601	0	1
+1166	0	2
+784	4	0
+170	0	1
+939	0	6
+5597	15	15
+1253	1	0
+3336	18	0
+1851	0	9
+45	1	1
+4794	1	0
+1387	0	2
+1460	0	1
+204	5	0
+1506	1	0
+2621	0	1
+6620	1	0
+34	1	1
+249	0	1
+1443	10	0
+242	1	0
+368	9	1
+257	0	4
+1588	0	6
+1544	1	0
+4189	0	120
+354	278046	312446
+3728	1	0
+3127	9	10
+4861	4	0
+5649	0	1
+2011	1	0
+14914	1467	42
+20955	1	0
+2075	1	2
+5546	0	1
+2168	0	4
+1266	0	1
+4124	1	1
+46	1	1
+54	1	1
+43	0	15
+780	1	1
+25	1	1
+497	1	0
+46	1	1
+770	41	40
+5701	1	0
+4251	8	8
+2739	1	0
+2002	3	0
+7160	1	1
+24	1	1
+479	0	2
+1872	1	0
+1192	0	1
+371	0	2
+31	1	1
+572	16	16
+1725	16	16
+588	1	1
+90	1	1
+2483	19	3
+187	1	0
+20	1	1
+3673	1	1
+27	0	4
+3021	0	1
+1323	6	19
+498	13	13
+1618	0	2
+5282	1	0
+720	8	0
+2993	0	1
+2822	2	0
+1396	1	1
+48	1	1
+8723	0	5
+291	1	1
+25	1	1
+116	1	0
+2809	1	1
+27	1	1
+224	1	1
+48	1	1
+292	2	0
+400	1	0
+754	1	1
+19	1	1
+4225	1	1
+28	1	1
+801	0	1
+671	1	1
+17	1	1
+390	1	1
+28	1	1
+84	7	7
+568	1	1
+56	1	1
+499	8	7
+266	1	1
+31	1	1
+518	18	18
+164	1	1
+50	1	1
+162	1	1
+60	1	1
+702	1	1
+28	1	1
+146	17	18
+517	1	1
+24	1	1
+799	1	1
+22	5	5
+107	5	5
+277	9	9
+272	1	1
+48	1	1
+77	1	1
+67	1	1
+1548	1	1
+40	1	1
+763	1	1
+42	1	1
+541	8	8
+88	1	1
+77	1	1
+233	11	11
+311	1	1
+22	1	1
+147	8	1
+504	1	1
+26	1	1
+996	3615	24049
+1687	0	1
+1174	1	0
+70	1	1
+1100	18	10143
+2722	1	0
+2957	1	1
+32	1	1
+9585	1	0
+1350	1	0
+473	1	0
+675	1	0
+1435	1	0
+805463	79189	0
+10872697	100000	100000
+721570	1	1
+19	1	1
+816	1	1
+44	1	1
+572	6	8
+2021	4	0
+1001	0	2
+3757	0	1
+5942	2	2
+70	1	1
+100	7	7
+395	17188	80000
+1010	1	1
+45	1	1
+1486	18	18
+173	145	1
+139	65	1
+41	16	0
+32	368	0
+44	2	50
+40	1	1
+95	52	4
+60	8	39
+12	0	16
+93	0	16
+1591	1	0
+897	13	13
+28	3	3
+2454	1	1
+44	1	1
+305	468	0
+2026	1	1
+45	1	1
+1273	3	11
+1717	0	1
+1575	4	0
+14	1	1
+2428	0	36
+50	10	154
+247	185	6
+2096	11	13
+192	1	1
+48	1	1
+130	1	1
+22	1	1
+970	1	1
+22	0	4
+76	14	0
+118	58	64
+107	1	0
+12	1	1
+53	5	15
+48	1	1
+47	2	0
+114	16	18
+363	1	1
+43	1	1
+559	1	1
+32	1	1
+3980007
+
+chain 16700437 chr7 159138663 + 142098195 142276197 chr7 158821424 - 16919205 17097543 171
+6297	1	0
+171	1	0
+4869	1	1
+24	0	1
+6208	0	1
+135	1	0
+1978	1	0
+764	1	1
+45	0	2
+1984	0	1
+1628	1	0
+733	1	1
+38	1	0
+137	7	7
+17	1	1
+259	1	0
+1200	1	0
+2193	4	4
+1781	0	1
+3387	1	1
+25	1	1
+125	1	1
+17	1	1
+3811	5	5
+556	0	1
+1846	5	0
+1322	1	1
+40	1	1
+228	0	1
+3477	1	1
+31	1	1
+3722	1	1
+73	1	1
+3052	66	66
+2542	15	15
+3103	0	2
+112	0	2
+1066	1	1
+59	1	0
+719	1	0
+203	1	0
+127	1	0
+30	1	0
+32	1	1
+366	0	4
+27	1	1
+2155	1	1
+41	1	1
+790	0	1
+403	1	1
+27	1	1
+648	7	7
+48	2	0
+78	2	2
+1052	4	4
+855	1	1
+68	1	1
+2428	9	0
+919	1	1
+22	1	1
+366	1	1
+36	1	1
+269	7	7
+4018	6	6
+1168	0	1
+3409	0	1
+1503	3	0
+2680	1	1
+37	1	1
+727	1	1
+28	0	5
+9	0	3
+5	0	2
+4	9	0
+13	1	1
+1801	0	3
+98	14	14
+2789	4	0
+5562	1	0
+2380	1	1
+23	1	1
+160	1	1
+57	1	1
+2413	19	19
+1704	0	1
+67	0	1
+68	1	1
+45	1	1
+176	9	9
+973	1	1
+31	3	3
+167	4	4
+334	13	13
+584	11	11
+206	16	16
+1218	1	1
+29	1	1
+234	1	1
+45	0	2
+1027	0	1
+559	10	11
+367	0	2
+8269	0	2
+4195	1	1
+62	1	1
+2896	13	13
+524	5	5
+411	1	1
+53	1	1
+126	1	1
+36	1	1
+806	1	1
+43	2	0
+1905	2	0
+414	1	1
+25	1	1
+2396	1	0
+12	1	0
+23	0	1
+10	0	1
+4	0	1
+60	0	1
+25	1	1
+1387	0	4
+3461	0	2
+1026	0	2
+821	1	1
+21	1	0
+612	1	1
+31	1	1
+1053	1	0
+2080	17	17
+9739	5	12
+17	7	0
+878	1	1
+19	1	0
+53	1	1
+839	26	26
+522	1	1
+49	1	1
+539	1	1
+25	1	1
+669	1	1
+42	1	1
+134	7	7
+1145	1	0
+2731	1	0
+590	4	0
+41	0	1
+7853	0	4
+830	0	2
+1742	2	0
+640	1	1
+34	0	2
+298	1	0
+3598	1	0
+1522	1	339
+115	18	18
+887	1	1
+69	1	1
+1662
+
+chain 1755125 chr7 159138663 + 143318748 143347897 chr7 158821424 - 15657394 15686558 532
+923	0	15
+1431	698	698
+3421	10	12
+405	1	1
+16	1	1
+5116	1	1
+27	1	1
+334	1	1
+15	1	0
+724	13	13
+109	0	2
+1784	1	0
+1588	1	1
+43	1	1
+908	9684	9682
+464	445	445
+982
+
+chain 939937 chr7 159138663 + 61402791 61412791 chr7 158821424 + 61280000 61290000 3137
+10000
+
+chain 921443 chr7 159138663 + 61382791 61392786 chr7 158821424 + 61260000 61269994 3741
+1722	1	0
+433	30	30
+1603	4	4
+4846	27	27
+478	19	19
+584	36	36
+212
+
+chain 898631 chr7 159138663 + 61392792 61402791 chr7 158821424 + 61270000 61280000 4251
+316	76	76
+3924	49	49
+2708	28	28
+1134	174	174
+156	40	41
+1394
+
+chain 896117 chr7 159138663 + 61422788 61432614 chr7 158821424 + 61300000 61310000 4294
+1207	50	50
+1637	22	22
+347	30	30
+983	48	48
+2562	0	172
+1941	14	14
+487	39	41
+459
+
+chain 881174 chr7 159138663 + 61412791 61422788 chr7 158821424 + 61290000 61300000 4600
+2588	34	34
+299	23	23
+1680	4	6
+286	395	396
+256	39	39
+220	18	18
+675	16	16
+3464
+
+chain 807485 chr7 159138663 + 61372814 61382791 chr7 158821424 + 61250000 61260000 5800
+91	75	75
+308	91	91
+99	88	88
+175	43	43
+577	65	65
+289	17	17
+186	21	21
+119	72	72
+80	98	98
+114	2	1
+115	51	51
+319	90	97
+54	49	50
+590	135	136
+749	1	0
+467	41	41
+153	21	21
+97	102	118
+935	19	19
+3186	43	43
+150
+
+chain 475263 chr7 159138663 + 143336322 143346915 chr7 158821424 - 15765291 15775883 242
+2017	14	14
+1214	1	1
+32	1	1
+3171	0	8
+760	1	1
+49	1	1
+68	10	10
+1210	1	1
+39	1	1
+60	18	9
+568	4	4
+357	12	12
+75	512	512
+397
+
+chain 413572 chr7 159138663 + 61432614 61437066 chr7 158821424 + 61310000 61314455 110492
+105	12	12
+1311	18	21
+3006
+
+chain 327362 chr7 159138663 + 130261501 130267755 chr7 158821424 - 80118425 80124354 202501
+81	547	220
+108	98	98
+188	35	35
+305	168	168
+59	47	46
+67	25	25
+301	6	6
+107	44	44
+133	23	23
+174	0	4
+110	27	27
+188	31	31
+86	62	62
+284	66	66
+205	34	34
+171	16	16
+85	35	35
+152	206	205
+64	33	33
+71	76	76
+129	26	26
+52	79	80
+203	92	92
+193	64	64
+113	490	490
+131	98	97
+66
+
+chain 116757 chr7 159138663 + 56987924 57001476 chr7 158821424 - 96066875 96080423 71
+182	4	0
+366	2	0
+47	6	0
+1290	7	1
+317	25	25
+90	14	15
+195	1	6
+96	1	1
+280	1	1
+59	1	1
+435	1	1
+51	1	1
+1067	22	22
+3594	0	1
+645	0	1
+507	7	7
+1383	0	6
+531	0	1
+1396	1	0
+927
+
+chain 94083 chr7 159138663 + 61667110 61669673 chr9 140273252 - 71180528 71183093 1349166
+123	22	22
+57	154	154
+93	530	532
+407	16	16
+95	28	28
+72	290	290
+83	43	43
+61	266	266
+77	77	77
+69
+
+chain 75094 chr7 159138663 + 433321 434167 chr14 106368585 - 82907729 82908574 1677524
+115	1	1
+30	1	0
+335	22	22
+342
+
+chain 74694 chr7 159138663 + 61674373 61676412 chr2 242951149 + 91627954 91629996 1686429
+59	154	155
+210	438	438
+221	259	259
+81	77	77
+52	201	203
+222	15	15
+50
+
+chain 54428 chr7 159138663 + 61360568 61361523 chr9 140273252 + 69464390 69465353 2322078
+76	100	105
+56	176	179
+432	51	51
+64
+
+chain 45723 chr7 159138663 + 100554977 100556023 chr7 158821424 + 100392913 100393963 2803709
+153	225	232
+246	8	8
+74	288	285
+52
+
+chain 42415 chr7 159138663 + 130262863 130266857 chr20 62435964 + 18530662 18534660 203154
+65	162	162
+47	67	67
+25	425	425
+33	1127	1130
+57	206	206
+33	274	274
+33	152	152
+121	149	149
+33	83	83
+64	129	129
+26	335	336
+91	194	194
+63
+
+chain 34286 chr7 159138663 + 61670163 61670988 chr1 247249719 - 187008143 187008914 3936433
+177	89	89
+59	338	284
+162
+
+chain 30309 chr7 159138663 + 61417768 61418394 chr15 100338915 + 53005912 53006538 319980
+332	256	256
+38
+
+chain 29619 chr7 159138663 + 130261638 130262129 chr18 76117153 - 20889181 20889344 211760
+82	389	61
+20
+
+chain 28749 chr7 159138663 + 102187071 102200348 chr7 158821424 + 102073398 102086671 912
+74	1102	1102
+32	11867	11863
+202
+
+chain 27540 chr7 159138663 + 61526936 61527567 chr17 78774742 - 13987513 13988140 5824140
+131	255	251
+90	52	52
+103
+
+chain 25455 chr7 159138663 + 61658206 61658677 chr21 46944323 + 31224827 31225297 6797318
+187	186	185
+98
+
+chain 25398 chr7 159138663 + 130275431 130276578 chrX 154913754 + 99697151 99697788 219009
+66	77	207
+69	353	1
+53	369	81
+54	49	49
+57
+
+chain 24368 chr7 159138663 + 61663982 61664383 chr7 158821424 - 97410910 97411311 7475570
+54	99	99
+67	16	16
+165
+
+chain 23018 chr7 159138663 + 61372081 61372809 chr7 158821424 + 61249436 61249995 8282044
+79	92	92
+52	313	144
+58	34	34
+100
+
+chain 22330 chr7 159138663 + 61674796 61675234 chr16 88827254 - 56087354 56087792 5126597
+69	100	100
+51	129	129
+89
+
+chain 22048 chr7 159138663 + 61583753 61648197 chr7 158821424 - 97506969 97571424 1587
+3024	0	1
+5860	1	1
+34	1	1
+1210	1	1
+46	1	1
+1360	1	1
+20	1	1
+6247	7	7
+2011	22	23
+15979	1	1
+20	0	1
+39	1	1
+156	1	1
+79	1	1
+1227	1	1
+26	1	1
+201	17	17
+6321	11	11
+106	2	2
+66	33	33
+316	6	6
+832	1	1
+17	1	1
+478	1	1
+25	1	1
+4306	14	0
+14	1	1
+525	4	4
+1603	1	1
+28	1	1
+433	1	0
+1365	1	1
+35	1	1
+3699	1	1
+17	1	1
+962	0	16
+124	1	1
+221	1	1
+50	1	1
+446	1	0
+788	0	1
+38	1	1
+470	14	14
+173	1	1
+48	0	1
+54	1	1
+71	0	7
+17	1	1
+319	1	1
+49	1	1
+115	2	1
+167	1	1
+41	3	3
+80	1	1
+70	1	1
+119	1	1
+19	1	1
+186	17	17
+347	7	7
+549	1	1
+69	1	1
+175	1	1
+55	1	1
+101	1	1
+118	2	2
+307	1	1
+73	1	1
+91
+
+chain 20717 chr7 159138663 + 61531674 61531894 chrY 57772954 + 23149505 23149725 9889131
+220
+
+chain 20603 chr7 159138663 + 61525953 61526232 chr8 146274826 + 92437703 92437982 9974457
+114	48	48
+117
+
+chain 20209 chr7 159138663 + 61534129 61534693 chr5 180857866 - 39454690 39455254 10284708
+41	129	129
+72	189	189
+133
+
+chain 19256 chr7 159138663 + 10000 10238 chr11 134452384 - 108 510 10867298
+115	1	145
+57	3	0
+12	3	26
+47
+
+chain 17549 chr7 159138663 + 23954 24387 chr3 199501827 - 125819 126212 1017
+61	27	17
+87	27	17
+87	27	17
+87	27	17
+3
+
+chain 17511 chr7 159138663 + 61459516 61459775 chr3 199501827 + 156410667 156410926 12559831
+104	60	60
+95
+
+chain 17423 chr7 159138663 + 130286013 130286315 chr3 199501827 + 134941335 134941641 12635149
+64	74	78
+72	18	18
+74
+
+chain 17216 chr7 159138663 + 61561042 61561226 chr18 76117153 + 1344411 1344595 12834816
+184
+
+chain 15818 chr7 159138663 + 130258842 130259235 chr20 62435964 - 56174662 56175052 14212289
+60	144	139
+68	52	54
+69
+
+chain 15803 chr7 159138663 + 434188 434399 chr9 140273252 - 53303336 53303547 1693631
+211
+
+chain 15460 chr7 159138663 + 61363520 61363685 chr14 106368585 + 46013452 46013617 14586403
+165
+
+chain 15455 chr7 159138663 + 61533249 61533413 chr10 135374737 - 122138066 122138230 14591550
+164
+
+chain 14801 chr7 159138663 + 61526597 61527118 chr11 134452384 + 128715236 128715756 6490404
+89	98	98
+58	225	224
+51
+
+chain 14577 chr7 159138663 + 61459836 61459991 chr2 242951149 - 172428837 172428992 15528208
+155
+
+chain 14381 chr7 159138663 + 61532809 61533249 chr5 180857866 - 128913075 128913510 15277847
+110	278	273
+52
+
+chain 14182 chr7 159138663 + 61362349 61362804 chr1 247249719 - 101935287 101935742 15983329
+55	287	287
+113
+
+chain 13384 chr7 159138663 + 130261760 130262050 chr18 76117153 - 65538588 65538878 302793
+128	17	17
+145
+
+chain 12863 chr7 159138663 + 61659684 61659821 chr18 76117153 + 15161457 15161594 17682773
+137
+
+chain 12713 chr7 159138663 + 130268588 130270221 chr7 158821424 - 62883278 62884905 17912238
+74	1316	1311
+67	121	120
+55
+
+chain 12498 chr7 159138663 + 61527567 61527825 chr2 242951149 - 136022598 136022856 13034573
+7	155	155
+96
+
+chain 12424 chr7 159138663 + 61560835 61560980 chr21 46944323 - 5411573 5411718 18347201
+82	1	1
+62
+
+chain 11917 chr7 159138663 + 130274671 130277102 chr2 242951149 + 85567844 85569506 1111973
+198	73	73
+65	403	530
+21	111	209
+32	1149	157
+77	81	81
+50	6	4
+165
+
+chain 11414 chr7 159138663 + 61446485 61446604 chr8 146274826 - 97728756 97728875 19987436
+119
+
+chain 11204 chr7 159138663 + 323186 323319 chr13 114142980 - 47557127 47557260 20361650
+67	7	7
+59
+
+chain 11191 chr7 159138663 + 61533547 61533688 chr10 135374737 + 121736617 121736758 14568606
+63	20	20
+58
+
+chain 11162 chr7 159138663 + 143321102 143321761 chr7 158821424 + 143031254 143031913 1465
+659
+
+chain 11033 chr7 159138663 + 155133717 155133867 chr7 158821424 + 154826660 154826810 3228542
+150
+
+chain 10743 chr7 159138663 + 130272956 130273070 chr20 62435964 - 54784771 54784885 21217928
+114
+
+chain 10697 chr7 159138663 + 61363082 61363210 chr8 146274826 + 114533399 114533527 21308454
+63	1	1
+64
+
+chain 10686 chr7 159138663 + 130276049 130276418 chr5 180857866 - 110000669 110000947 1711166
+8	218	161
+54	34	0
+55
+
+chain 10550 chr7 159138663 + 61534371 61534497 chr2 242951149 - 102597516 102597642 13706867
+22	1	1
+103
+
+chain 10502 chr7 159138663 + 61658058 61658206 chr3 199501827 - 100394760 100394909 7999945
+74	51	52
+23
+
+chain 9908 chr7 159138663 + 155127373 155127651 chr7 158821424 + 154820991 154821604 23020589
+62	155	490
+61
+
+chain 9705 chr7 159138663 + 130254993 130255333 chr5 180857866 - 86134908 86135248 23505792
+58	220	220
+62
+
+chain 9691 chr7 159138663 + 61363878 61364175 chr6 170899992 - 83481581 83481894 23533804
+52	178	194
+67
+
+chain 9557 chr7 159138663 + 130275060 130277190 chr4 191273063 + 57733996 57734920 1639272
+2	161	201
+75	1804	558
+40	10	10
+38
+
+chain 9406 chr7 159138663 + 61531909 61532009 chr3 199501827 - 114948547 114948647 24221847
+100
+
+chain 9378 chr7 159138663 + 61670488 61670618 chr1 247249719 + 166585217 166585347 4198164
+130
+
+chain 9215 chr7 159138663 + 61369893 61370445 chr20 62435964 + 26207014 26207215 24594255
+60	436	85
+56
+
+chain 8793 chr7 159138663 + 61533688 61534015 chr8 146274826 + 132629025 132629349 11801047
+54	54	51
+58	97	97
+64
+
+chain 8578 chr7 159138663 + 61650566 61651111 chr20 62435964 - 36228749 36228943 25570183
+56	436	85
+53
+
+chain 8304 chr7 159138663 + 61532721 61532809 chr5 180857866 - 33354116 33354204 19653256
+88
+
+chain 8273 chr7 159138663 + 61375213 61375308 chr10 135374737 - 99567310 99567405 2885342
+95
+
+chain 7707 chr7 159138663 + 61670340 61670429 chr11 134452384 + 5653851 5653940 4693035
+89
+
+chain 7687 chr7 159138663 + 61362996 61363078 chr1 247249719 - 62796192 62796274 26921084
+82
+
+chain 7328 chr7 159138663 + 130260449 130260631 chr6 170899992 + 18975635 18975819 23797357
+8	121	123
+53
+
+chain 7084 chr7 159138663 + 155107000 155107125 chr8 146274826 + 127792382 127792507 21399384
+5	63	63
+57
+
+chain 6750 chr7 159138663 + 130268276 130268348 chr9 140273252 + 6309168 6309240 28699203
+72
+
+chain 6727 chr7 159138663 + 61364306 61364811 chr19 63811651 + 24391898 24393602 28746452
+47	400	1599
+58
+
+chain 6689 chr7 159138663 + 130262523 130267689 chr14 106368585 - 15396362 15401535 205901
+35	1928	1932
+35	3110	3113
+58
+
+chain 6657 chr7 159138663 + 130262248 130266269 chr20 62435964 - 53906684 53910704 204336
+68	3910	3909
+43
+
+chain 6632 chr7 159138663 + 61362621 61362691 chr14 106368585 - 25756639 25756709 18227251
+70
+
+chain 6604 chr7 159138663 + 61516196 61516266 chr14 106368585 + 18700177 18700247 29040667
+70
+
+chain 6561 chr7 159138663 + 61362487 61362621 chr5 180857866 - 77495083 77495217 25581093
+60	70	70
+4
+
+chain 6504 chr7 159138663 + 61563734 61563803 chr14 106368585 + 18700333 18700402 29292943
+69
+
+chain 6504 chr7 159138663 + 61457014 61457083 chr14 106368585 + 19014991 19015060 29292944
+69
+
+chain 6486 chr7 159138663 + 61439583 61439652 chr7 158821424 + 61677724 61677793 29330266
+69
+
+chain 6486 chr7 159138663 + 61453269 61453338 chr11 134452384 + 54672038 54672107 29330599
+69
+
+chain 6415 chr7 159138663 + 130266970 130267081 chr2 242951149 - 44689835 44689946 206027
+111
+
+chain 6395 chr7 159138663 + 61581171 61581239 chr12 132349534 + 36481345 36481413 29552558
+68
+
+chain 6295 chr7 159138663 + 130268491 130268558 chr12 132349534 - 16670768 16670835 29797454
+67
+
+chain 6222 chr7 159138663 + 61516757 61516823 chr7 158821424 - 100865546 100865612 29971261
+66
+
+chain 6149 chr7 159138663 + 61518444 61518509 chr9 140273252 - 73547747 73547812 30146556
+65
+
+chain 6147 chr7 159138663 + 61360661 61361459 chr1 247249719 - 99965931 99966729 2490905
+65	694	694
+39
+
+chain 6131 chr7 159138663 + 61545392 61545457 chr9 140273252 - 71283139 71283204 30224431
+65
+
+chain 6031 chr7 159138663 + 61649702 61649766 chr8 146274826 - 102385209 102385273 30479392
+64
+
+chain 5940 chr7 159138663 + 61567501 61567564 chr11 134452384 - 79723078 79723141 30715303
+63
+
+chain 5895 chr7 159138663 + 130261352 130261415 chr12 132349534 - 16670326 16670389 30822868
+63
+
+chain 5890 chr7 159138663 + 130272150 130272376 chr5 180857866 - 150003108 150003332 287879
+73	71	69
+82
+
+chain 5831 chr7 159138663 + 61540614 61540676 chr20 62435964 + 26207004 26207066 31016062
+62
+
+chain 5822 chr7 159138663 + 61534741 61534803 chr2 242951149 + 182601389 182601451 31037299
+62
+
+chain 5767 chr7 159138663 + 61657263 61657324 chrX 154913754 + 145511099 145511160 31173265
+61
+
+chain 5740 chr7 159138663 + 61561871 61561932 chrX 154913754 + 61825831 61825892 31255925
+61
+
+chain 5707 chr7 159138663 + 155133639 155133717 chr7 158821424 + 154826660 154826738 3248987
+78
+
+chain 5671 chr7 159138663 + 130267178 130267274 chr3 199501827 + 136865539 136865635 212140
+96
+
+chain 5649 chr7 159138663 + 61510793 61510853 chr14 106368585 + 18700200 18700260 31523979
+60
+
+chain 5614 chr7 159138663 + 61459620 61459680 chr8 146274826 + 85828676 85828736 12834914
+60
+
+chain 5505 chr7 159138663 + 130286091 130286151 chr11 134452384 + 126327988 126328048 18815467
+60
+
+chain 5376 chr7 159138663 + 61368713 61368770 chr5 180857866 - 134492854 134492911 32331066
+57
+
+chain 5358 chr7 159138663 + 130272706 130272763 chr4 191273063 - 62601703 62601760 32378845
+57
+
+chain 5239 chr7 159138663 + 61375927 61375982 chr3 199501827 + 176568366 176568421 32719676
+55
+
+chain 5238 chr7 159138663 + 155133561 155133639 chr7 158821424 + 154826660 154826738 3316763
+78
+
+chain 5212 chr7 159138663 + 48202742 48202797 chrY 57772954 + 8140437 8140492 32786933
+55
+
+chain 5203 chr7 159138663 + 61362897 61362952 chr2 242951149 - 204521553 204521608 32840726
+55
+
+chain 5203 chr7 159138663 + 61514738 61514793 chr3 199501827 - 109094736 109094791 32841435
+55
+
+chain 5196 chr7 159138663 + 102270836 102270891 chr7 158821424 + 101958735 101958790 2864
+55
+
+chain 5085 chr7 159138663 + 61522548 61522602 chr11 134452384 - 85760698 85760752 33224588
+54
+
+chain 5081 chr7 159138663 + 61542952 61543361 chrX 154913754 - 96402533 96402599 33252017
+22	343	0
+44
+
+chain 5076 chr7 159138663 + 61566776 61566830 chrX 154913754 + 58536057 58536111 33266851
+54
+
+chain 5003 chr7 159138663 + 321166 321219 chr9 140273252 + 26769862 26769915 33490833
+53
+
+chain 4985 chr7 159138663 + 61511756 61511809 chrX 154913754 + 58510881 58510934 33583214
+53
+
+chain 4976 chr7 159138663 + 61453966 61454019 chr11 134452384 + 48695047 48695100 33600288
+53
+
+chain 4976 chr7 159138663 + 61579973 61580026 chr12 132349534 + 36420396 36420449 33600992
+53
+
+chain 4967 chr7 159138663 + 61528283 61528336 chr2 242951149 - 102597577 102597630 33622422
+53
+
+chain 4930 chr7 159138663 + 61528065 61528117 chr11 134452384 - 85701922 85701974 33735561
+52
+
+chain 4921 chr7 159138663 + 61566142 61566194 chr3 199501827 - 104503080 104503132 33762259
+52
+
+chain 4903 chr7 159138663 + 61364673 61364725 chr9 140273252 + 69253479 69253531 33844300
+52
+
+chain 4894 chr7 159138663 + 61535225 61535277 chrX 154913754 + 61822223 61822275 33894839
+52
+
+chain 4894 chr7 159138663 + 61555289 61555341 chrX 154913754 - 93093366 93093418 33894887
+52
+
+chain 4894 chr7 159138663 + 61367691 61367743 chr11 134452384 + 48824621 48824673 33895037
+52
+
+chain 4876 chr7 159138663 + 61446263 61446315 chr11 134452384 + 54670005 54670057 33929755
+52
+
+chain 4860 chr7 159138663 + 61671055 61671121 chr6 170899992 - 77150208 77150274 16663217
+66
+
+chain 4803 chr7 159138663 + 61582505 61582556 chr5 180857866 + 46128392 46128443 34201035
+51
+
+chain 4803 chr7 159138663 + 61548133 61548184 chr5 180857866 - 134730739 134730790 34201101
+51
+
+chain 4803 chr7 159138663 + 61656299 61656350 chr8 146274826 - 102385679 102385730 34201707
+51
+
+chain 4803 chr7 159138663 + 61371246 61371297 chr20 62435964 + 26207164 26207215 34201851
+51
+
+chain 4803 chr7 159138663 + 61538491 61538542 chrX 154913754 + 61822744 61822795 34202106
+51
+
+chain 4803 chr7 159138663 + 61550591 61550642 chrX 154913754 - 96402828 96402879 34202170
+51
+
+chain 4794 chr7 159138663 + 61568385 61568436 chr12 132349534 - 30627763 30627814 34229426
+51
+
+chain 4794 chr7 159138663 + 61560404 61560455 chrX 154913754 + 58511165 58511216 34229878
+51
+
+chain 4785 chr7 159138663 + 61555628 61555679 chr5 180857866 + 49580248 49580299 34261015
+51
+
+chain 4757 chr7 159138663 + 155127495 155127545 chr7 158821424 + 154820841 154820891 34330191
+50
+
+chain 4745 chr7 159138663 + 61527127 61527200 chr1 247249719 - 196249350 196249423 12580328
+73
+
+chain 4730 chr7 159138663 + 61454627 61454677 chrX 154913754 - 93091546 93091596 34451023
+50
+
+chain 4721 chr7 159138663 + 61547785 61547835 chr14 106368585 + 19015139 19015189 34474345
+50
+
+chain 4712 chr7 159138663 + 61542078 61542128 chr7 158821424 - 97143221 97143271 34536293
+50
+
+chain 4712 chr7 159138663 + 61650232 61650282 chr7 158821424 + 61292872 61292922 34536325
+50
+
+chain 4712 chr7 159138663 + 61447406 61447456 chr12 132349534 - 95867613 95867663 34536696
+50
+
+chain 4712 chr7 159138663 + 61573362 61573412 chr11 134452384 - 79778078 79778128 34537090
+50
+
+chain 4694 chr7 159138663 + 61361784 61361834 chr20 62435964 + 26208957 26209007 34582417
+50
+
+chain 4533 chr7 159138663 + 61657325 61657373 chr14 106368585 - 60354968 60355016 14458107
+48
+
+chain 4330 chr7 159138663 + 61571756 61571802 chrX 154913754 + 58511174 58511220 34815702
+46
+
+chain 4322 chr7 159138663 + 61527200 61527268 chr1 247249719 + 66112503 66112571 10645536
+68
+
+chain 4309 chr7 159138663 + 130262963 130263031 chr20 62435964 + 59813 59881 233275
+68
+
+chain 4243 chr7 159138663 + 130267293 130267390 chr15 100338915 - 46124324 46124421 430805
+97
+
+chain 4225 chr7 159138663 + 130272413 130272571 chr3 199501827 - 60665919 60666077 310359
+158
+
+chain 4225 chr7 159138663 + 130275130 130275387 chr10 135374737 + 61126513 61126771 1703431
+71	112	113
+74
+
+chain 4135 chr7 159138663 + 61657814 61657864 chr4 191273063 - 103880681 103880731 24177091
+50
+
+chain 4106 chr7 159138663 + 130265690 130265763 chr2 242951149 + 45160326 45160399 259070
+73
+
+chain 4049 chr7 159138663 + 61417706 61417751 chr19 63811651 + 35324192 35324237 995629
+45
+
+chain 4036 chr7 159138663 + 102224324 102224366 chr7 158821424 + 102110621 102110663 1050243
+42
+
+chain 3993 chr7 159138663 + 130270112 130270163 chr3 199501827 - 142320121 142320172 24066397
+51
+
+chain 3975 chr7 159138663 + 130269077 130269119 chr8 146274826 + 76339197 76339239 33761016
+42
+
+chain 3893 chr7 159138663 + 61535529 61535570 chr9_random 1146434 - 229264 229305 35008771
+41
+
+chain 3839 chr7 159138663 + 61659187 61659228 chr7 158821424 - 97183039 97183080 35036445
+41
+
+chain 3820 chr7 159138663 + 143397897 143397937 chr7 158821424 - 15657354 15657394 1380183
+40
+
+chain 3770 chr7 159138663 + 130272223 130272265 chr7 158821424 - 144399150 144399192 18136384
+42
+
+chain 3724 chr7 159138663 + 61669828 61671669 chr18 76117153 - 60916397 60916965 5934170
+170	1399	126
+50	156	156
+66
+
+chain 3694 chr7 159138663 + 130276177 130276253 chrX 154913754 + 40955942 40956018 2422661
+76
+
+chain 3685 chr7 159138663 + 102274757 102274796 chr7 158821424 + 101962659 101962698 2923
+39
+
+chain 3592 chr7 159138663 + 102246649 102246687 chr7 158821424 + 101934491 101934529 2920
+38
+
+chain 3540 chr7 159138663 + 61670988 61671026 chr1 247249719 - 1293349 1293387 6950988
+38
+
+chain 3536 chr7 159138663 + 155127890 155127927 chr7 158821424 + 154820516 154820553 31559480
+37
+
+chain 3498 chr7 159138663 + 61668816 61668875 chr21_random 1679693 + 339817 339876 2744470
+59
+
+chain 3321 chr7 159138663 + 130259738 130259803 chr5 180857866 + 117134963 117135028 22545496
+65
+
+chain 3254 chr7 159138663 + 155127171 155127205 chr7 158821424 + 154821284 154821318 30495954
+34
+
+chain 3179 chr7 159138663 + 61671122 61671197 chr3 199501827 + 3741295 3741370 21259213
+75
+
+chain 3139 chr7 159138663 + 61669998 61670032 chr7 158821424 - 73313700 73313734 35261607
+34
+
+chain 3136 chr7 159138663 + 155133873 155133906 chr7 158821424 + 154826660 154826693 3164897
+33
+
+chain 3128 chr7 159138663 + 61657490 61657523 chr14 106368585 + 19500965 19500998 15505654
+33
+
+chain 3124 chr7 159138663 + 61362864 61362897 chr13 114142980 - 56785908 56785941 33122705
+33
+
+chain 3114 chr7 159138663 + 61363362 61363395 chr11 134452384 + 38920746 38920779 30450202
+33
+
+chain 3035 chr7 159138663 + 130267390 130267459 chr5 180857866 + 148307658 148307727 349562
+69
+
+chain 3005 chr7 159138663 + 130258675 130258738 chr3 199501827 - 66319298 66319361 23438786
+63
+
+chain 2998 chr7 159138663 + 61670741 61670826 chr2 242951149 - 144372974 144373059 5019535
+68	11	11
+6
+
+chain 2929 chr7 159138663 + 61366904 61366935 chr9 140273252 + 69000834 69000865 35330365
+31
+
+chain 2883 chr7 159138663 + 130274908 130276723 chr12 132349534 - 84232022 84233270 1810563
+34	1716	687
+63	1	463
+1
+
+chain 2844 chr7 159138663 + 61525923 61525953 chr11 134452384 + 42874872 42874902 16620335
+30
+
+chain 2837 chr7 159138663 + 155133483 155133522 chr7 158821424 + 154826738 154826777 5314872
+39
+
+chain 2752 chr7 159138663 + 130270309 130270363 chr15 100338915 - 53351487 53351541 22720352
+54
+
+chain 2749 chr7 159138663 + 61657932 61657999 chr9 140273252 + 120725102 120725169 13790105
+67
+
+chain 2677 chr7 159138663 + 61657615 61657668 chr2 242951149 - 80490248 80490301 14907722
+53
+
+chain 2675 chr7 159138663 + 61657868 61657928 chr14 106368585 - 67199431 67199491 8049700
+60
+
+chain 2656 chr7 159138663 + 61658132 61658174 chr14 106368585 - 39618235 39618277 11504442
+42
+
+chain 2625 chr7 159138663 + 61376053 61376101 chr2 242951149 - 165273826 165273874 3000213
+48
+
+chain 2574 chr7 159138663 + 130285941 130286005 chr3 199501827 + 177805790 177805854 20115306
+64
+
+chain 2555 chr7 159138663 + 61657373 61657490 chr10 135374737 + 110991454 110991571 9489838
+117
+
+chain 2533 chr7 159138663 + 130255333 130255360 chr5 180857866 + 110504974 110505001 34260994
+27
+
+chain 2525 chr7 159138663 + 155133522 155133561 chr7 158821424 + 154826699 154826738 3760022
+39
+
+chain 2511 chr7 159138663 + 130261431 130261481 chr6 170899992 - 80902268 80902318 240832
+50
+
+chain 2491 chr7 159138663 + 130275062 130277276 chr7 158821424 + 139777825 139778654 1647744
+34	1723	339
+29	404	403
+24
+
+chain 2465 chr7 159138663 + 102229230 102229256 chr7 158821424 + 101917063 101917089 2852
+26
+
+chain 2367 chr7 159138663 + 61656836 61656861 chr8 146274826 - 114798799 114798824 27799318
+25
+
+chain 2262 chr7 159138663 + 61363303 61363362 chr15 100338915 - 25052381 25052440 19971588
+59
+
+chain 2184 chr7 159138663 + 61360913 61360944 chr16 88827254 + 45047397 45047428 3009512
+31
+
+chain 2183 chr7 159138663 + 61655805 61655828 chr8 146274826 - 102376418 102376441 35497387
+23
+
+chain 2181 chr7 159138663 + 61362804 61362827 chr8 146274826 - 64142945 64142968 28339747
+23
+
+chain 2177 chr7 159138663 + 61363497 61363520 chr15 100338915 - 57516283 57516306 24810342
+23
+
+chain 2111 chr7 159138663 + 102252256 102252279 chr7 158821424 + 101940282 101940305 3979
+23
+
+chain 2085 chr7 159138663 + 61668033 61668084 chr9 140273252 + 42719058 42719109 1926685
+51
+
+chain 2073 chr7 159138663 + 130274605 130277252 chr2 242951149 - 168073547 168075372 1534321
+53	350	351
+52	688	693
+76	1025	208
+32	309	298
+62
+
+chain 2067 chr7 159138663 + 155127207 155127236 chr7 158821424 + 154821033 154821062 24052540
+29
+
+chain 2049 chr7 159138663 + 130259609 130260449 chr2 242951149 + 217320568 217321411 19749334
+52	691	694
+97
+
+chain 1867 chr7 159138663 + 61360944 61360976 chr1 247249719 + 146935382 146935414 2538402
+32
+
+chain 1866 chr7 159138663 + 130286570 130286642 chr8 146274826 + 120193638 120193710 13784733
+72
+
+chain 1860 chr7 159138663 + 130271889 130271917 chr3 199501827 + 158050218 158050246 8145167
+28
+
+chain 1834 chr7 159138663 + 130267107 130267162 chr2 242951149 - 74722759 74722814 2183237
+55
+
+chain 1810 chr7 159138663 + 434399 434426 chr8 146274826 + 50019771 50019798 1840028
+27
+
+chain 1807 chr7 159138663 + 61459483 61459516 chr20 62435964 - 10907955 10907988 13772492
+33
+
+chain 1749 chr7 159138663 + 61534521 61534560 chr8 146274826 - 57707270 57707309 18613209
+39
+
+chain 1741 chr7 159138663 + 130275927 130275994 chr3 199501827 - 85253648 85253715 1907688
+67
+
+chain 1725 chr7 159138663 + 130286346 130286404 chr5 180857866 - 156929708 156929766 24410167
+58
+
+chain 1675 chr7 159138663 + 61360800 61360833 chr2 242951149 - 151940057 151940090 10244640
+33
+
+chain 1649 chr7 159138663 + 61527639 61527689 chr10 135374737 - 21832678 21832728 15020107
+50
+
+chain 1626 chr7 159138663 + 61525699 61525759 chr5 180857866 + 119849560 119849620 22270263
+60
+
+chain 1538 chr7 159138663 + 130271917 130271979 chrX 154913754 + 106499092 106499154 335529
+62
+
+chain 1512 chr7 159138663 + 130270436 130270487 chr7 158821424 + 123638895 123638946 23964536
+51
+
+chain 1449 chr7 159138663 + 61671198 61671257 chr11 134452384 + 48551200 48551259 6005368
+59
+
+chain 1444 chr7 159138663 + 130272046 130272150 chr5 180857866 - 107650838 107650942 1109190
+41	46	46
+17
+
+chain 1406 chr7 159138663 + 130268385 130269191 chr13 114142980 + 104373808 104374629 24734362
+65	682	697
+59
+
+chain 1391 chr7 159138663 + 130271979 130272046 chr12 132349534 + 128856107 128856174 572332
+67
+
+chain 1342 chr7 159138663 + 130255652 130255716 chr6 170899992 - 118498216 118498280 24733557
+64
+
+chain 1277 chr7 159138663 + 61525407 61525458 chr14 106368585 - 54569941 54569992 25208354
+51
+
+chain 1239 chr7 159138663 + 61657050 61657132 chr1 247249719 + 60704689 60704771 10216239
+82
+
+chain 1222 chr7 159138663 + 24387 24410 chr9 140273252 - 34976 34999 792
+23
+
+chain 1201 chr7 159138663 + 130267591 130267617 chr3 199501827 - 22519451 22519477 371093
+26
+
+chain 1176 chr7 159138663 + 61533413 61533439 chr9 140273252 + 78066621 78066647 21815254
+26
+
+chain 1159 chr7 159138663 + 130255953 130256003 chr18 76117153 + 30232927 30232977 26680295
+50
+
+chain 1143 chr7 159138663 + 130272637 130272705 chr4 191273063 - 164951872 164951940 23193314
+68
+
+chain 1120 chr7 159138663 + 130267081 130267107 chr4 191273063 + 53894987 53895013 453066
+26
+
+chain 1090 chr7 159138663 + 61375539 61375583 chr16 88827254 - 2017000 2017044 2867569
+44
+
+chain 967 chr7 159138663 + 61363930 61363960 chr5 180857866 - 77417997 77418027 26429199
+30
+
+chain 922 chr7 159138663 + 130269744 130269794 chr6 170899992 - 168370205 168370255 24919326
+50
+
+chain 916 chr7 159138663 + 130272376 130272413 chr7 158821424 - 119807072 119807109 361270
+37
+
+chain 903 chr7 159138663 + 130274518 130274571 chr18 76117153 + 7087852 7087905 2747041
+53
+
+chain 875 chr7 159138663 + 61656861 61656912 chr1 247249719 - 3737712 3737763 19994037
+51
+
+chain 825 chr7 159138663 + 130276127 130276177 chr9 140273252 + 78760365 78760415 3856900
+50
+
+chain 821 chr7 159138663 + 61657151 61657205 chr18 76117153 - 50729761 50729815 10763263
+54
+
+chain 764 chr7 159138663 + 155106965 155107000 chr2 242951149 - 97843675 97843710 19287766
+35
+
+chain 760 chr7 159138663 + 130260179 130260244 chr15 100338915 - 29035916 29035981 5017751
+65
+
+chain 738 chr7 159138663 + 61528144 61528186 chr5 180857866 + 37689556 37689598 26578239
+42
+
+chain 665 chr7 159138663 + 61657587 61657615 chr4 191273063 - 56344538 56344566 26451583
+28
+
+chain 506 chr7 159138663 + 130259438 130259491 chr7 158821424 - 81365049 81365102 23441660
+53
+
+chain 492 chr7 159138663 + 130276335 130276363 chr8 146274826 - 17074751 17074779 8865204
+28
+
+chain 466 chr7 159138663 + 130268939 130269012 chr2 242951149 - 225017173 225017246 26097376
+73
+
+chain 388 chr7 159138663 + 130271813 130271889 chr3 199501827 + 120370918 120370994 4694596
+76
+
+chain 379 chr7 159138663 + 130275097 130275130 chr3 199501827 + 9586745 9586778 4580558
+33
+
+chain 379 chr7 159138663 + 61363702 61363740 chr5 180857866 - 91082220 91082258 29303651
+38
+
+chain 348 chr7 159138663 + 102200504 102200535 chr7 158821424 - 57045045 57045076 1079
+31
+
+chain 17312866 chr7_gl000195_random 182896 + 0 182896 chr7_random 549659 + 162804 345700 162
+182896
+
+chain 13484003737 chr8 146364022 + 10000 146304022 chr8 146274826 + 0 146274826 9
+930417	1243	1
+52	10	10
+91	972	0
+54	54	0
+281	324	0
+289	1	0
+2323216	0	1
+3352649	0	2
+854996	50000	100000
+3399023	1	1
+46	1	1
+13965	1	1
+30	1	1
+121189	1	1
+35	1	1
+283700	1	0
+719291	93054	100016
+1155	2	0
+755	26	26
+980	21	21
+1479	422	422
+3229	0	1
+1937	1	1
+17	1	1
+322	0	1
+1758	0	2
+1141	1	0
+956	48	48
+1765	1	0
+543	25	25
+7047	15	15
+1029	1	1
+28	1	1
+314	1	1
+46	1	1
+164	1	1
+25	1	1
+5130707	1	0
+1288	1	0
+446	1	1
+80	1	1
+2123	4	4
+2514	0	3
+545	0	9
+527	1	1
+18	1	1
+256	9	9
+79	1	1
+40	1	1
+148	2	0
+2236	27	0
+953	1	1
+20	1	1
+2487	1	1
+113	1	1
+73	13	13
+365	10	10
+151	1	1
+32	0	3
+26	1	1
+1480	1	1
+29	1	1
+621	1	1
+28	1	1
+701	9	9
+362	1	1
+19	1	1
+691	1	1
+45	0	6
+46	1	1
+513	11	12
+382	1	1
+22	1	1
+111	1	1
+36	1	1
+337	1	1
+42	1	1
+602	0	2
+36	1	1
+475	1	1
+23	1	0
+32	3	4
+65	1	1
+59	1	1
+688	1	1
+22	1	1
+1473	1	1
+36	1	1
+372	1	1
+16	6	6
+640	25	25
+940	1	1
+38	1	1
+816	1	1
+17	0	1
+374	1	1
+17	1	1
+48	0	1
+82	1	1
+45	1	1
+263	1	1
+23	1	1
+204	1	1
+39	1	1
+2341	1	0
+2989	1	0
+9	1	0
+811	8	8
+741	2	0
+337	1	1
+25	4	4
+763	1	1
+19	1	1
+343	1	1
+31	1	1
+1953	1	1
+74	1	1
+67	1	1
+18	4	4
+73	1	1
+31	1	1
+114	1	11
+87	1	1
+65	1	1
+125	9	9
+378	0	1
+47	1	1
+90	1	1
+96	0	1
+176	7	13
+696	1	0
+6184	13	13
+830	13	13
+128	1	1
+37	1	1
+136	0	1
+66	6	5
+870	0	1
+4877	1	0
+585	7	3
+1728	0	1
+33	1	1
+465	1	1
+68	1	1
+581	0	6
+2088	0	1
+304	1	0
+2674	1	1
+28	0	1
+54	8	8
+846	1	0
+1409	16	16
+559	1	0
+401	5	0
+17	1	5
+29	1	1
+4051	1	1
+10	1	0
+43	1	1
+385	1	1
+35	1	1
+101	11	11
+602	0	1
+491	16	14
+1366	19	19
+321	1	1
+49	1	1
+546	1	1
+25	1	1
+1333	28	28
+1207	1	1
+51	0	4
+159	1	0
+1040	1	0
+1682	4	0
+34	0	8
+867	1	1
+17	1	1
+587	1	1
+21	1	1
+904	1	0
+261	1	0
+1151	2	0
+2325	5	5
+5415	3	0
+1545	0	1
+428	4	4
+1950	0	2
+1073	1	0
+3658	86	0
+1278	1	1
+79	1	1
+6656	12	12
+1550	18	0
+5832	0	1
+4835	10	10
+1719	1	1
+84	1	1
+848	2	0
+236	1	1
+42	1	1
+1286	0	12
+35	1	1
+820	1	1
+22	0	1
+63	22	0
+167	23	23
+315	8	8
+983	0	6
+539	14	14
+863	2	0
+27	1	1
+204	14	14
+163	4	4
+290	1	1
+59	1	1
+842	2	0
+2044	1	1
+90	1	0
+3434	3	0
+356	1	0
+873	1	0
+864	1	25
+630	7	12
+62	1	1
+88	1	1
+76	11	11
+1366	17	17
+156	4	4
+244	18	4
+505	0	1
+109	1	1
+230	1	1
+107	3	4
+150	1	1
+83	5	5
+70	1	1
+33	0	1
+142	1	1
+626	6	5
+274	10	10
+128	1	1
+35	1	1
+216	1	1
+44	1	1
+312	18	18
+1496	7	8
+451	1	0
+212	14	14
+629	1	1
+20	1	1
+350	1	1
+62	1	1
+617	10	10
+845	1	1
+58	1	1
+2189	1	1
+147	1	1
+475	1	1
+27	1	1
+278	1	1
+17	1	1
+994	1	1
+40	1	1
+219	5	5
+26	1	1
+900	1	1
+29	0	1
+26	1	1
+484	16	15
+61	9	9
+114	26	21
+801	1	1
+33	1	1
+465	32	32
+63	1	1
+37	1	1
+80	14	14
+211	1	1
+43	1	1
+156	1	1
+20	1	1
+685	1	1
+67	0	4
+711	1	1
+38	1	1
+402	7	7
+1045	1	1
+37	1	1
+4035	9	9
+247	0	4
+4146274	5734	17400
+330366	1	0
+2346742	55	0
+413177	0	3
+450	0	1
+9436	1	3
+7044	0	4
+2886	0	1
+635	0	1
+16567	0	1
+6918	0	1
+9285	0	1
+14909	0	8
+12879	0	2
+3330	0	2
+2673376	0	2
+2173174	7	7
+29817	2485	66108
+6473782	5	5
+39	1	1
+9574	2	0
+5879	1	1
+29	1	1
+6139	0	1
+2354	1	1
+28	1	1
+91	1	1
+23	0	1
+62	1	1
+142	15	16
+54	1	1
+22	3	3
+1479	4	4
+221	4	4
+132	0	1
+574	11	11
+23	0	1
+604	1	1
+44	1	1
+899	0	1
+70	10	12
+13561	1	1
+44	1	1
+4476	4	4
+799	25	26
+1466	18	18
+17896	0	4
+1668	0	1
+4250	1	1
+44	1	0
+4	1	0
+11	1	1
+4956	1	1
+18	0	1
+39	2	3
+4990	1	1
+47	13	13
+68	0	4
+9730	0	1
+355	1	0
+2186	1	1
+37	1	1
+6111	3	3
+100	4	4
+68	1	1
+43	1	1
+1126	7	5
+5520	8	8
+2316	1	1
+181	6	6
+50	1	1
+29	0	1
+83	1	1
+1073	150	154
+100	398	0
+141	1	1
+25272	1	0
+2132	4	0
+2522	1	1
+48	1	1
+1498528	1	0
+6044582	3000000	3000008
+1291149	16655	60038
+3837	0	3
+811	0	1
+2567	0	1
+7375465	1	0
+10	0	1
+42062	0	1
+19604621	0	1
+10692667	0	1
+110	1	0
+3577	3	0
+907	1	1
+18	1	1
+528	1	1
+50	1	1
+317	1	1
+64	251	535
+21	1	0
+140	1	0
+70	0	1
+77	10	9
+227	0	1
+142	5	5
+57	14	14
+43	1	1
+31034	99683	124100
+2301	2	0
+44	0	2
+568015	186612	87300
+355	5	5
+1916	3085	0
+924	4	0
+339	211	211
+963	14	15
+1157	12194	0
+242	23	23
+56	15	15
+405	20	20
+955	49	49
+1347	1	1
+2289	51	51
+555	253	253
+1723	77	77
+396	13	13
+112	3085	0
+3945	0	1
+209	23	23
+69	22	22
+81	20	20
+696	20	20
+58	69	69
+100	13	13
+326	137	137
+151	35	35
+1804	37	37
+1548	26	26
+324	23	23
+1932	17	17
+111	47	47
+128	16	16
+78	30	30
+1022	10	6
+78	0	1
+342	31	31
+86	23	23
+1580	255	255
+170	10	10
+398	23	23
+419	20	20
+955	55	55
+1139	11	11
+1925	276	0
+223	1	1
+56	1	1
+702	5	5
+17	3	3
+1030	1	1
+21	1	1
+363	1	1
+30	1	1
+785	16	16
+78	13	13
+1036	4	0
+482	68	68
+1069	10	10
+321	200	200
+434	43	43
+798	20	20
+56	25	25
+1007	5	5
+1198	24	24
+689	0	3
+743	32	32
+817	43	43
+574	11	11
+760	69	69
+1229	32	32
+272	29	29
+106	97	97
+1309	46	46
+850	4	4
+777	62	62
+86	36	36
+374	93	93
+2076	31	31
+195	56	56
+379	80	80
+64	11	11
+191	18	18
+1051	13	13
+52	119	113
+1347	1	1
+25	1	1
+3451	188	0
+3097	9	0
+2715	0	1
+11829	3	0
+6000	0	28
+10729	1	0
+3770769	0	1
+62	0	1
+22	0	1
+827	0	1
+1485	0	1
+242	1	0
+7142	0	1
+4029	3	3
+69	1	1
+15865	0	1
+83461	0	4
+5978	0	9
+2661	0	1
+1483	0	1
+15868	0	4
+17798	0	1
+2649	0	1
+3627	0	1
+4789	0	1
+9541	0	1
+6844	0	1
+3187	0	2
+411	0	14
+3056	0	4
+19776	0	3
+29085	1	0
+745	0	2
+11453	0	2
+16739	0	1
+14697	0	1
+8539	0	1
+25514443	0	1
+17680	1	0
+55359	1	0
+58	13	11
+5	1	0
+6	1	0
+5	1	0
+22	0	1
+4	1	3
+1515	0	1
+1111	0	1
+5736	6	6
+66213	0	1
+68	1	1
+24	7	6
+43	1	1
+33414	7	7
+22	1	1
+12288	22	22
+7002	1	0
+8588	1	1
+31	1	1
+15969	1	1
+32	1	1
+27034	1	1
+42	1	1
+3352	1	0
+15009	0	1
+20433	18	18
+32141	8	9
+116	41	41
+4920	0	1
+33364	0	1
+11160	1	0
+15	1	0
+28423	0	1
+43835	1	1
+24	2	4
+269244	4	4
+37	1	1
+17193	3	4
+53	11	12
+23	1	2
+7	1	1
+37978	9	9
+37743	1	1
+35	3	3
+26636	1	1
+17	1	1
+8728292	0	1
+16734777	71275	0
+657026	2	0
+2911	2	0
+1941	1	1
+35	1	1
+835	1	1
+116	1	1
+399	1	1
+101	0	1
+194	2	1
+450	0	1
+825	1	1
+73	1	1
+156	1	1
+58	1	1
+50	5	5
+153	11	11
+189	5	5
+233	1	1
+83	1	1
+642	1	0
+1380	1	1
+17	1	1
+315	1	1
+26	1	1
+789	901	0
+73	1	1
+45	1	1
+535	1	1
+34	1	1
+2007	7	7
+159	1	1
+26	1	1
+6362	13	13
+504325	25635	100008
+420771	232	0
+287688	104	0
+65	364	0
+183	55	0
+93	1	1
+46	1	1
+4002	1	1
+24	1	1
+190	0	147
+65	2	1
+8	0	1
+39	2	591
+306	50	0
+1938	1	0
+578	0	684
+291	1	0
+572289	108288	7108
+480202	0	1
+11866	6	6
+26917	1	0
+6097	15	15
+3074	1	0
+12292	1	0
+2209	1	0
+7358	1	0
+321393
+
+chain 2607822 chr8 146364022 + 12061935 12091854 chr8 146274826 + 12348580 12378713 990
+895	20	0
+1391	22	21
+53	88	0
+99	36	0
+9	0	346
+255	0	44
+496	1	0
+1013	0	4
+1698	1	0
+1054	37	37
+915	52	54
+2295	9	9
+123	1	0
+1295	162	162
+2903	50	50
+913	24	24
+2382	1	0
+299	85	85
+61	27	16
+1351	37	37
+974	4	4
+571	1	0
+530	11	0
+572	18	18
+76	4	4
+398	0	2
+54	31	31
+115	37	37
+125	364	364
+70	47	47
+56	8	8
+979	57	57
+248	50	50
+65	100	100
+82	1	0
+428	34	34
+51	6	0
+156	66	66
+257	132	132
+56	49	49
+91	19	19
+67	38	37
+142	6	6
+249	17	17
+123	104	104
+190	36	37
+355	5	1
+161	1	0
+89	48	48
+62	38	38
+136	67	67
+839
+
+chain 2498503 chr8 146364022 + 86726531 86754632 chr8 146274826 - 59364826 59419953 1092
+268	2	2
+114	6	0
+49	13	13
+1051	18	18
+117	8	3
+81	1	1
+64	4	4
+73	3	3
+379	1	1
+54	1	1
+183	13	13
+374	1	1
+43	1	1
+874	2	2
+22	1	1
+56	20	20
+712	1	1
+91	1	1
+374	1	1
+73	1	1
+88	21	21
+83	1	1
+27	1	1
+302	29	29
+1591	1	1
+27	4	0
+1250	1	1
+20	1	1
+2246	10	9115
+1002	49	49
+314	4	4
+116	32	32
+363	23	23
+1050	13	13
+119	0	8829
+1050	16	16
+1869	31	31
+119	0	9106
+593	13	13
+396	77	77
+1017	32	32
+888	39	39
+2895	1	1
+964	43	43
+1769	15	15
+292	35	35
+97	5	5
+313	13	13
+248	40	40
+435	10	11
+129	6	6
+712
+
+chain 1152177 chr8 146364022 + 142754466 142766515 chr8 146274826 + 142956164 142968213 2035
+12049
+
+chain 1081960 chr8 146364022 + 86772301 86823828 chr8 146274826 + 86857153 86905309 683
+56	15	15
+405	21	21
+1003	383	383
+837	0	1
+126	1	1
+531	1	0
+794	1	0
+73	32	32
+817	43	43
+214	432	432
+212	114	114
+373	28	28
+159	32	32
+832	44	44
+217	192	192
+330	927	923
+88	39	40
+1839	279	279
+283	13	13
+143	1716	1717
+49	3637	3637
+51	555	555
+97	1	1
+21	1	1
+133	1723	1723
+13	16	16
+48	8749	5664
+69	439	439
+62	43	43
+32	151	151
+35	1804	1804
+37	1548	1272
+26	2407	2407
+32	1719	1716
+31	1784	1784
+160	1995	1995
+55	3075	3075
+276	4870	4866
+68	1429	1429
+83	21	21
+67	434	434
+36
+
+chain 801068 chr8 146364022 + 145324300 145332588 chr8 146274826 + 145464193 145472508 5275
+3979	8	0
+2057	0	35
+2244
+
+chain 744541 chr8 146364022 + 86754632 86807992 chr8 146274826 + 86857851 86901670 688
+637	20	20
+440	88	88
+964	1	1
+2289	52	52
+554	1	1
+37	1	1
+1606	46	43
+288	6565	395
+203	3612	3608
+265	1500	1501
+278	1	1
+104	3213	3212
+43	214	214
+138	26	26
+268	212	212
+80	594	594
+32	832	832
+34	227	227
+16	27	27
+149	330	330
+33	21	21
+873	88	85
+39	1839	1839
+229	17	17
+33	9021	8745
+425	14725	11640
+30
+
+chain 657279 chr8 146364022 + 12141854 12149156 chr8 146274826 + 11932698 11940000 7963
+232	8	8
+466	34	34
+801	48	48
+815	68	68
+1203	29	29
+407	31	31
+467	26	26
+1146	18	18
+1503
+
+chain 521724 chr8 146364022 + 12149156 12156927 chr8 146274826 + 11940000 11947772 4417
+2168	0	1
+503	25	25
+153	202	202
+106	107	107
+851	39	39
+1679	1912	1912
+26
+
+chain 511532 chr8 146364022 + 142816515 142822092 chr8 146274826 + 142814667 142820000 26584
+2797	244	0
+2536
+
+chain 345755 chr8 146364022 + 142822092 142825705 chr8 146274826 + 142820000 142823612 174979
+3531	1	0
+81
+
+chain 305790 chr8 146364022 + 86765339 86795897 chr8 146274826 + 86865470 86901765 930
+477	0	9106
+123	31	31
+1705	14	14
+503	14	14
+15	1470	1466
+91	31	31
+52	35	35
+2	7890	7613
+26	560	560
+34	16750	13662
+405	127	127
+203
+
+chain 137107 chr8 146364022 + 85964683 85966170 chr8 146274826 + 86036733 86038220 940425
+1283	19	19
+185
+
+chain 118247 chr8 146364022 + 86759071 86769900 chr8 146274826 + 86874481 86903237 1649
+52	2533	2530
+13	16	16
+1046	0	8829
+123	13	13
+196	2878	11983
+29	3812	3808
+31	52	52
+35
+
+chain 109647 chr8 146364022 + 21624541 21625686 chr8_random 943810 + 516200 517342 1758
+687	1	0
+241	2	0
+214
+
+chain 97713 chr8 146364022 + 86793362 86840444 chr8 146274826 + 86862935 86885634 1255
+1752	44	44
+4	38618	14235
+46	1631	1631
+62	86	86
+36	374	374
+93	2302	2302
+56	379	379
+80	1400	1400
+119
+
+chain 85095 chr8 146364022 + 85924850 85927320 chr2 242951149 - 28701067 28703532 1485529
+52	143	142
+173	208	208
+107	181	181
+68	70	66
+129	101	101
+183	373	373
+87	163	163
+164	198	198
+70
+
+chain 67060 chr8 146364022 + 144032710 144033413 chr8_random 943810 + 583131 583834 1875893
+703
+
+chain 47407 chr8 146364022 + 85907218 85908847 chr10 135374737 - 19950497 19952126 2691979
+115	531	531
+182	240	240
+64	202	202
+122	22	22
+52	45	45
+54
+
+chain 45318 chr8 146364022 + 85909407 85911400 chr3 199501827 - 58732681 58734687 2832173
+138	151	157
+53	129	125
+171	674	685
+80	116	116
+82	347	347
+52
+
+chain 43260 chr8 146364022 + 12069066 12090712 chr8 146274826 - 138168279 138189929 1162
+37	915	915
+52	6789	6802
+48	3620	3620
+85	61	59
+27	1351	1348
+5	1	1
+30	3223	3218
+22	115	115
+37	465	465
+24	3764	3760
+90	837	842
+48
+
+chain 38958 chr8 146364022 + 12159413 12159829 chr8 146274826 + 11950258 11950674 3228
+416
+
+chain 38127 chr8 146364022 + 86726451 86753339 chr8 146274826 - 59376930 59524482 1121
+80	11856	20676
+48	435	435
+32	4503	13609
+31	1121	10227
+77	1017	94649
+32	888	888
+39	3860	3860
+15	1	1
+26	2078	2078
+33	678	678
+38
+
+chain 31437 chr8 146364022 + 85955665 85955994 chr3 199501827 - 6162711 6163040 4382021
+329
+
+chain 30755 chr8 146364022 + 85915208 85915710 chr8 146274826 - 4216734 4217241 4503764
+255	160	165
+87
+
+chain 27896 chr8 146364022 + 940417 941596 chr8 146274826 + 930633 930948 5586021
+100	54	0
+108	810	0
+107
+
+chain 26413 chr8 146364022 + 85978864 85981144 chr9 140273252 - 40203469 40205589 6324943
+79	1134	635
+70	83	416
+56	207	205
+56	22	22
+63	455	463
+55
+
+chain 25390 chr8 146364022 + 85975200 85975766 chr6 170899992 - 89617888 89618457 6830715
+67	141	143
+50	38	39
+54	78	78
+138
+
+chain 20285 chr8 146364022 + 85975766 85977415 chr3 199501827 - 82189783 82191451 9116338
+8	700	763
+50	465	465
+54	309	265
+63
+
+chain 20226 chr8 146364022 + 85979170 85979799 chr3 199501827 - 161413320 161413963 10270718
+61	394	408
+174
+
+chain 20141 chr8 146364022 + 12151827 12152420 chr8 146274826 + 11902715 11903309 638255
+25	153	154
+202	106	106
+107
+
+chain 19400 chr8 146364022 + 85925267 85925628 chr10 135374737 + 135080720 135081080 3597149
+102	2	1
+54	131	131
+72
+
+chain 18915 chr8 146364022 + 942460 942893 chr8 146274826 + 930516 930733 3835109
+63	162	0
+46	108	54
+54
+
+chain 18062 chr8 146364022 + 942088 942460 chr8 146274826 + 930684 930948 5250846
+157	108	0
+107
+
+chain 17886 chr8 146364022 + 943174 943431 chr8 146274826 + 930690 930893 4105167
+149	55	1
+53
+
+chain 15443 chr8 146364022 + 941596 942029 chr8 146274826 + 930516 930841 4827909
+64	207	153
+65	54	0
+43
+
+chain 14855 chr8 146364022 + 85924497 85927134 chrX 154913754 + 50874366 50877002 1910511
+90	57	57
+50	108	108
+48	52	52
+79	801	801
+50	953	952
+50	236	236
+63
+
+chain 12854 chr8 146364022 + 144743895 144744094 chr8 146274826 + 144814885 144815084 3961669
+199
+
+chain 12042 chr8 146364022 + 85907589 85907864 chr4 191273063 + 22500316 22500591 2841396
+81	177	177
+17
+
+chain 11713 chr8 146364022 + 36265496 36265620 chr7 158821424 - 150143040 150143164 19315609
+124
+
+chain 10744 chr8 146364022 + 85909592 85910073 chr4 191273063 - 317022 317498 3271263
+71	86	86
+68	232	227
+24
+
+chain 10295 chr8 146364022 + 85917935 85918395 chr16 88827254 - 19324120 19324578 22152835
+60	331	329
+69
+
+chain 9964 chr8 146364022 + 85927135 85927250 chr3 199501827 - 159900532 159900647 3087651
+115
+
+chain 9833 chr8 146364022 + 85908046 85908504 chr8 146274826 - 114124165 114124623 2795681
+56	59	59
+58	162	162
+123
+
+chain 9709 chr8 146364022 + 943330 943485 chr8 146274826 + 930684 930839 15332741
+48	53	53
+54
+
+chain 9657 chr8 146364022 + 86004292 86004501 chrX 154913754 + 27575363 27575573 23616431
+52	93	94
+64
+
+chain 9406 chr8 146364022 + 85945093 85945452 chr12 132349534 + 8944725 8945099 24220725
+61	243	258
+55
+
+chain 9151 chr8 146364022 + 85910121 85910218 chr10 135374737 - 38564811 38564908 24713323
+97
+
+chain 8406 chr8 146364022 + 85924386 85924476 chr5 180857866 + 127114677 127114767 25803856
+90
+
+chain 7367 chr8 146364022 + 85911400 85911623 chrX 154913754 - 44623158 44623382 4824008
+72	91	92
+60
+
+chain 7214 chr8 146364022 + 85983029 85983106 chr3 199501827 + 182981094 182981171 27755476
+77
+
+chain 7178 chr8 146364022 + 85926461 85926638 chr7 158821424 + 131250991 131251168 8959140
+97	79	79
+1
+
+chain 6913 chr8 146364022 + 85946010 85946083 chr5 180857866 - 76444763 76444836 28360557
+73
+
+chain 6866 chr8 146364022 + 85981016 85981089 chr3 199501827 - 137848275 137848348 18929141
+73
+
+chain 6722 chr8 146364022 + 85915749 85915820 chr6 170899992 - 41858720 41858791 28750065
+71
+
+chain 6523 chr8 146364022 + 85874468 85874538 chr6 170899992 + 80165568 80165638 29222062
+70
+
+chain 6284 chr8 146364022 + 48138290 48138355 chr12 132349534 - 99530740 99530805 29826800
+65
+
+chain 6255 chr8 146364022 + 86830665 86832268 chr8 146274826 + 86851473 86853076 5870
+41	1533	1533
+29
+
+chain 6230 chr8 146364022 + 143494784 143494849 chr8 146274826 + 143492621 143492686 29969115
+65
+
+chain 5949 chr8 146364022 + 85946624 85946687 chr7 158821424 - 150469376 150469439 30705065
+63
+
+chain 5930 chr8 146364022 + 86000088 86000150 chr4 191273063 - 114595117 114595179 30759641
+62
+
+chain 5722 chr8 146364022 + 85909210 85909271 chr4 191273063 - 32715229 32715290 31306692
+61
+
+chain 5681 chr8 146364022 + 85907187 85907519 chr7 158821424 - 141596962 141597294 3108677
+31	137	137
+3	85	85
+76
+
+chain 5594 chr8 146364022 + 85966181 85966240 chr2 242951149 + 129692100 129692159 31643052
+59
+
+chain 5348 chr8 146364022 + 85946168 85946224 chrX 154913754 + 22697258 22697314 32405249
+56
+
+chain 5330 chr8 146364022 + 85945000 85945056 chrX 154913754 - 56717679 56717735 32442268
+56
+
+chain 5292 chr8 146364022 + 85926370 85926785 chr12 132349534 + 42776733 42777148 2271290
+75	280	280
+14	27	27
+19
+
+chain 5194 chr8 146364022 + 85992019 85992074 chr17_random 2617613 - 1345968 1346023 32873362
+55
+
+chain 5161 chr8 146364022 + 941932 941986 chr8 146274826 + 930312 930366 21107216
+54
+
+chain 5012 chr8 146364022 + 85946286 85946339 chr1 247249719 - 150482359 150482412 33477745
+53
+
+chain 4929 chr8 146364022 + 941384 941435 chr8 146274826 + 930304 930355 33748771
+51
+
+chain 4927 chr8 146364022 + 85874401 85874458 chr12 132349534 + 21319375 21319432 33750711
+57
+
+chain 4920 chr8 146364022 + 85945525 85945576 chr10 135374737 + 87468307 87468358 33788347
+51
+
+chain 4810 chr8 146364022 + 942523 942621 chr8 146274826 + 930741 930839 7547023
+98
+
+chain 4803 chr8 146364022 + 85970009 85970060 chr11 134452384 + 10157776 10157827 34198727
+51
+
+chain 4793 chr8 146364022 + 85975065 85975115 chr21 46944323 - 30257577 30257627 34245350
+50
+
+chain 4738 chr8 146364022 + 942303 942352 chr8 146274826 + 930521 930570 34412340
+49
+
+chain 4461 chr8 146364022 + 85910862 85910919 chrX 154913754 + 151305652 151305709 4935543
+57
+
+chain 4271 chr8 146364022 + 86793237 86793293 chr8 146274826 + 86902190 86902246 1452514
+56
+
+chain 4178 chr8 146364022 + 85915489 85915539 chr3 199501827 + 132299011 132299061 5319224
+50
+
+chain 4079 chr8 146364022 + 85926268 85926343 chr2 242951149 - 211437807 211437882 2547607
+75
+
+chain 3965 chr8 146364022 + 85910617 85910659 chr5 180857866 + 105218926 105218968 18292131
+42
+
+chain 3826 chr8 146364022 + 85911256 85911310 chr7 158821424 + 49570162 49570216 23840400
+54
+
+chain 3809 chr8 146364022 + 86829249 86829292 chr8 146274826 + 86874439 86874482 7328
+43
+
+chain 3796 chr8 146364022 + 85928889 85929141 chrX 154913754 + 121492736 121492988 2565989
+99	40	40
+113
+
+chain 3755 chr8 146364022 + 85925629 85925714 chr5 180857866 + 141403818 141403903 2005326
+54	23	23
+8
+
+chain 3680 chr8 146364022 + 36265255 36265294 chr21 46944323 - 8931342 8931381 34138292
+39
+
+chain 3466 chr8 146364022 + 85917822 85917882 chr11 134452384 - 107659023 107659083 22827264
+60
+
+chain 3460 chr8 146364022 + 85925991 85926082 chr19 63811651 + 46688677 46688768 2544872
+91
+
+chain 3412 chr8 146364022 + 85981195 85981250 chr12 132349534 - 23016451 23016506 20760996
+55
+
+chain 3378 chr8 146364022 + 144744318 144744353 chr8 146274826 + 144814727 144814762 26884487
+35
+
+chain 3372 chr8 146364022 + 12064503 12064539 chr8 146274826 + 12351001 12351037 28926895
+36
+
+chain 3336 chr8 146364022 + 85910527 85910617 chr6 170899992 + 121091189 121091279 5885029
+90
+
+chain 3306 chr8 146364022 + 85975140 85975200 chr5 180857866 - 14200316 14200376 14215921
+60
+
+chain 3123 chr8 146364022 + 144455804 144455869 chr8 146274826 + 144526757 144526822 16634618
+65
+
+chain 3122 chr8 146364022 + 85910073 85910106 chr10 135374737 + 91515201 91515234 27999029
+33
+
+chain 2973 chr8 146364022 + 85975297 85975339 chr11 134452384 + 70894433 70894475 12515399
+42
+
+chain 2846 chr8 146364022 + 85980398 85980477 chr6 170899992 + 12780268 12780347 14041671
+79
+
+chain 2664 chr8 146364022 + 85980653 85980843 chr13 114142980 + 79661332 79661527 13462115
+54	70	75
+66
+
+chain 2542 chr8 146364022 + 86811232 86811259 chr8 146274826 + 86750599 86750626 581042
+27
+
+chain 2408 chr8 146364022 + 86780113 86780140 chr8 146274826 + 86901259 86901286 3284
+27
+
+chain 2361 chr8 146364022 + 86795114 86795665 chr8_random 943810 - 353250 353801 88303
+34	419	419
+98
+
+chain 2314 chr8 146364022 + 85909329 85909403 chr5 180857866 - 126448590 126448664 8133335
+74
+
+chain 2312 chr8 146364022 + 85964546 85964619 chr5 180857866 - 22206487 22206560 13216855
+73
+
+chain 2306 chr8 146364022 + 85909062 85909878 chr5 180857866 - 76491094 76491924 7171448
+57	726	740
+33
+
+chain 2277 chr8 146364022 + 85945069 85945093 chr2 242951149 - 76417863 76417887 30610067
+24
+
+chain 2276 chr8 146364022 + 85915156 85915196 chr9 140273252 + 96271703 96271743 9134049
+40
+
+chain 2255 chr8 146364022 + 12171549 12171574 chr8 146274826 + 11962388 11962413 4339
+25
+
+chain 2213 chr8 146364022 + 85976678 85976734 chr10 135374737 + 107478570 107478626 23840391
+56
+
+chain 2193 chr8 146364022 + 85909817 85909844 chr1 247249719 - 204777828 204777855 6141044
+27
+
+chain 2188 chr8 146364022 + 85915463 85915489 chr4 191273063 + 117566433 117566459 5547542
+26
+
+chain 2086 chr8 146364022 + 85907670 85907692 chr9 140273252 + 84577624 84577646 25068333
+22
+
+chain 2042 chr8 146364022 + 85906786 85906876 chr1 247249719 - 187757137 187757227 3120497
+90
+
+chain 2008 chr8 146364022 + 85975339 85978010 chr12 132349534 - 60955403 60957663 7657094
+69	2448	2037
+58	20	20
+76
+
+chain 1976 chr8 146364022 + 85910386 85910476 chr11 134452384 + 108691426 108691516 10944711
+90
+
+chain 1915 chr8 146364022 + 85915895 85915946 chr2 242951149 - 57258601 57258652 18793758
+51
+
+chain 1706 chr8 146364022 + 85926558 85926608 chr20 62435964 + 52983902 52983952 9284939
+50
+
+chain 1666 chr8 146364022 + 85915539 85915568 chr3 199501827 - 58686941 58686970 11643280
+29
+
+chain 1625 chr8 146364022 + 85977632 85977856 chr3 199501827 - 45071352 45071581 10048168
+62	161	166
+1
+
+chain 1603 chr8 146364022 + 36265620 36265653 chr4 191273063 + 189716401 189716434 1596951
+33
+
+chain 1586 chr8 146364022 + 86793293 86793362 chr8_random 943810 + 582217 582286 150907
+69
+
+chain 1585 chr8 146364022 + 85907040 85907092 chr7 158821424 + 38674874 38674926 25744726
+52
+
+chain 1584 chr8 146364022 + 85964393 85964443 chr1 247249719 - 57954630 57954680 20174423
+50
+
+chain 1470 chr8 146364022 + 85911121 85911160 chr15 100338915 + 92120615 92120654 21684489
+39
+
+chain 1463 chr8 146364022 + 942731 942785 chr8 146274826 + 930679 930733 5019737
+54
+
+chain 1440 chr8 146364022 + 85911043 85911098 chr1 247249719 - 141715465 141715520 4313974
+55
+
+chain 1426 chr8 146364022 + 85978253 85978320 chr2 242951149 - 208172805 208172872 22624190
+67
+
+chain 1403 chr8 146364022 + 85928837 85929028 chr18 76117153 + 39707440 39707631 2816562
+52	99	99
+40
+
+chain 1344 chr8 146364022 + 85907124 85907170 chr12 132349534 + 45103963 45104009 16171151
+46
+
+chain 1332 chr8 146364022 + 85927450 85927503 chr1 247249719 - 29234742 29234795 3133635
+53
+
+chain 1287 chr8 146364022 + 85907361 85907411 chr1 247249719 - 78547145 78547195 4245040
+50
+
+chain 1276 chr8 146364022 + 85927323 85927376 chr4 191273063 - 93337200 93337253 2720957
+53
+
+chain 1269 chr8 146364022 + 85908257 85908286 chr9 140273252 - 124490379 124490408 3695355
+29
+
+chain 1238 chr8 146364022 + 85978601 85978678 chr9 140273252 - 23294193 23294270 19053025
+77
+
+chain 1193 chr8 146364022 + 144455743 144455792 chr8 146274826 + 144526504 144526553 26679478
+49
+
+chain 1175 chr8 146364022 + 12087452 12087488 chr11 134452384 - 63301652 63301688 1994288
+36
+
+chain 1137 chr8 146364022 + 85909119 85909164 chr2 242951149 + 35848313 35848358 13461114
+45
+
+chain 1067 chr8 146364022 + 86832385 86832437 chr8_random 943810 - 358237 358289 86749
+52
+
+chain 1048 chr8 146364022 + 86824709 86824734 chr8 146274826 + 86857705 86857730 2636
+25
+
+chain 1045 chr8 146364022 + 85911001 85911043 chr15 100338915 - 40210675 40210717 4055996
+42
+
+chain 1028 chr8 146364022 + 85910323 85910373 chr4 191273063 + 26203887 26203937 5050480
+50
+
+chain 1020 chr8 146364022 + 85924694 85924736 chr3 199501827 + 1701599 1701641 4262142
+42
+
+chain 1005 chr8 146364022 + 85977261 85977320 chr10 135374737 + 45388722 45388781 14596230
+59
+
+chain 998 chr8 146364022 + 85908847 85908872 chr4 191273063 + 183519567 183519592 8543079
+25
+
+chain 985 chr8 146364022 + 85918576 85918627 chr3 199501827 - 21820872 21820923 24828426
+51
+
+chain 981 chr8 146364022 + 144744094 144744133 chr8 146274826 + 144814821 144814860 14840226
+39
+
+chain 922 chr8 146364022 + 85918981 85919046 chrX 154913754 - 100261670 100261735 22334691
+65
+
+chain 912 chr8 146364022 + 85964449 85964513 chr6 170899992 + 131272389 131272453 24950513
+64
+
+chain 888 chr8 146364022 + 85915710 85915739 chr9 140273252 + 12069456 12069485 13568361
+29
+
+chain 867 chr8 146364022 + 85976220 85976271 chrX 154913754 - 36573362 36573413 23586363
+51
+
+chain 857 chr8 146364022 + 86832445 86832471 chr8 146274826 + 86747431 86747457 7742
+26
+
+chain 802 chr8 146364022 + 85978516 85978572 chr3 199501827 + 80520031 80520087 22639668
+56
+
+chain 801 chr8 146364022 + 85911160 85911249 chr16 88827254 + 31611661 31611750 16482423
+89
+
+chain 785 chr8 146364022 + 85917259 85917324 chr5 180857866 - 163179499 163179564 25049793
+65
+
+chain 721 chr8 146364022 + 85926739 85926765 chr18 76117153 + 15364211 15364237 2792298
+26
+
+chain 647 chr8 146364022 + 85918645 85918703 chr11 134452384 - 90657004 90657062 25582649
+58
+
+chain 612 chr8 146364022 + 941818 941867 chr8 146274826 + 930360 930409 12502809
+49
+
+chain 596 chr8 146364022 + 85976593 85979111 chrX 154913754 - 42670843 42673368 13030869
+53	2388	2395
+77
+
+chain 568 chr8 146364022 + 85966335 85966385 chrX 154913754 + 36275879 36275929 27751459
+50
+
+chain 474 chr8 146364022 + 85917714 85917772 chr1 247249719 + 62707004 62707062 26279221
+58
+
+chain 396 chr8 146364022 + 85977502 85977572 chrX 154913754 - 138803117 138803187 17501406
+70
+
+chain 369 chr8 146364022 + 85976646 85976678 chr7 158821424 + 51906674 51906706 15299893
+32
+
+chain 360 chr8 146364022 + 85980297 85980349 chr12 132349534 - 124024481 124024533 24774043
+52
+
+chain 337 chr8 146364022 + 85981293 85981372 chr1 247249719 - 152445011 152445090 12777550
+79
+
+chain 328 chr8 146364022 + 85976447 85976474 chr2 242951149 - 99982783 99982810 22051776
+27
+
+chain 310 chr8 146364022 + 85976849 85976905 chr3 199501827 - 69459686 69459742 25770085
+56
+
+chain 286 chr8 146364022 + 85979114 85979170 chr7 158821424 - 11181572 11181628 19756881
+56
+
+chain 232 chr8 146364022 + 85978010 85978057 chr1 247249719 + 108819891 108819938 19586297
+47
+
+chain 3680035 chr8_gl000196_random 38914 + 0 38914 chr8_random 943810 + 643258 682172 798
+38914
+
+chain 3554032 chr8_gl000197_random 37175 + 0 37175 chr8_random 943810 + 493047 530222 826
+37175
+
+chain 11336430536 chr9 141213431 + 10000 141153431 chr9 140273252 + 0 140273252 13
+189075	17	17
+39464594	50000	50000
+261110	50000	50000
+208233	50000	50000
+142805	50000	50000
+464507	50000	50000
+152873	50000	50000
+172579	50000	50000
+799200	4	0
+398958	50000	50000
+549743	100000	50000
+632871	50000	50000
+680077	50000	50000
+181647	50000	50000
+291910	100000	50000
+465318	50000	50000
+350909	50000	50000
+194609	100000	50000
+370337	176	0
+128581	100047	50047
+157499	18150000	18100000
+450681	50000	50000
+223855	50000	50000
+162441	50000	50000
+159539	50000	50000
+199148	50000	50000
+194491	100000	50000
+158462	150000	50000
+471702	150000	50000
+376183	150000	50000
+174765	150000	50000
+289439	50000	50000
+682157	50000	50000
+158187	100000	50000
+187806	50000	50000
+178933	100000	50000
+21507948	100000	50000
+85380	150000	50000
+834971	0	1
+39559293	150000	100000
+3818133	50000	200000
+2075804	50000	30000
+1936434
+
+chain 1179 chr9 141213431 + 46931376 46931552 chr9 140273252 - 98415895 98416071 50
+176
+
+chain 443 chr9 141213431 + 47160133 47160180 chr9 140273252 - 72994158 72994205 112
+47
+
+chain 8504653 chr9_gl000198_random 90085 + 0 90085 chr9_random 1146434 + 526031 616116 387
+90085
+
+chain 10524551 chr9_gl000199_random 169874 + 0 146316 chr9_random 1146434 + 903151 1075994 305
+35956	981	11726
+149	118	118
+212	21	21
+101	50	50
+98	0	8841
+196	126	126
+211	19	19
+115	44	44
+76	72	72
+100	9	9
+92	107	107
+86	1193	169
+50	168	18105
+488	0	1
+10599	1	1
+42	1	0
+8869	101	101
+10239	51	51
+179	500	502
+1131	0	1
+12346	0	18932
+463	15	15
+739	1	1
+64	1	1
+2323	0	1
+755	1	1
+188	1	1
+245	0	2
+10316	4	5
+18	1	1
+8496	15	15
+1065	3	3
+49	1	1
+67	1	1
+24	1	1
+150	15	15
+2700	5110	0
+46	11735	0
+376	5	5
+2019	342	0
+1220	1192	0
+221	37	37
+60	21	21
+334	6678	50
+235	1381	27
+52	2571	21
+62
+
+chain 3014585 chr9_gl000199_random 169874 + 136786 169869 chr9_random 1146434 + 939452 971857 944
+79	683	6
+4467	235	235
+1381	52	52
+786	1	1
+38	1	0
+29	1	1
+1715	62	62
+1332	14	14
+6821	1	1
+55	1	1
+15329
+
+chain 306268 chr9_gl000199_random 169874 + 114056 136743 chr9_random 1146434 + 1030711 1052467 1210
+785	60	60
+2828	46	46
+527	6	352
+63	378	378
+514	181	181
+824	72	72
+329	1	1
+35	1	1
+68	1	1
+37	1	1
+3228	135	132
+81	325	325
+52	391	391
+60	10252	2341
+243	179	691
+73	42	42
+155	0	1190
+24	0	1871
+442	0	3064
+2	95	95
+151
+
+chain 178734 chr9_gl000199_random 169874 + 38939 136592 chr9_random 1146434 + 940083 990000 1006
+27	31954	13752
+34	77	77
+166	43	43
+110	68	68
+2	41253	31459
+196	349	7
+48	5105	0
+83	14	14
+62	11	11
+208	514	2
+181	824	144
+72	3917	172
+325	52	52
+391	9096	1608
+467	1909	41
+95
+
+chain 108146 chr9_gl000199_random 169874 + 35956 37588 chr9_random 1146434 + 1073965 1075597 311529
+981	149	149
+118	334	334
+50
+
+chain 94079 chr9_gl000199_random 169874 + 125187 127738 chr9_random 1146434 + 934627 937178 173754
+2551
+
+chain 56396 chr9_gl000199_random 169874 + 38488 39821 chr9_random 1146434 + 1072584 1073917 324037
+57	225	225
+83	113	113
+855
+
+chain 37331 chr9_gl000199_random 169874 + 127738 129141 chr9_random 1146434 + 1073395 1074798 197032
+1403
+
+chain 15154 chr9_gl000199_random 169874 + 133472 133633 chr9_random 1146434 - 103942 104103 2035052
+161
+
+chain 14222 chr9_gl000199_random 169874 + 39821 40265 chr9_random 1146434 + 982531 990446 140426
+290	71	7542
+83
+
+chain 13688 chr9_gl000199_random 169874 + 112619 134922 chr9_random 1146434 + 997840 1005340 1760
+54	480	138
+65	48	48
+86	0	1
+62	27	27
+193	20460	5998
+27	467	467
+2	15	15
+59	221	221
+37
+
+chain 12407 chr9_gl000199_random 169874 + 60350 137506 chr9_random 1146434 + 944493 957004 1913
+35	10569	695
+47	196	196
+40	113	113
+68	62256	9695
+367	1799	779
+34	1232	42
+400
+
+chain 5910 chr9_gl000199_random 169874 + 112953 113153 chr9_random 1146434 + 1036251 1036451 100700
+200
+
+chain 4997 chr9_gl000199_random 169874 + 124080 124135 chr9_random 1146434 + 959057 959112 19926960
+55
+
+chain 4162 chr9_gl000199_random 169874 + 113634 113846 chr9_random 1146434 + 995454 995665 201802
+27	40	39
+145
+
+chain 3441 chr9_gl000199_random 169874 + 37915 38008 chr9_random 1146434 + 950621 950714 48386
+93
+
+chain 3360 chr9_gl000199_random 169874 + 129226 129424 chr9_random 1146434 + 996412 996610 9342
+198
+
+chain 3255 chr9_gl000199_random 169874 + 70690 70741 chr9_random 1146434 + 1012726 1012777 23586
+51
+
+chain 3031 chr9_gl000199_random 169874 + 112869 137060 chr9_random 1146434 + 964682 969139 3960
+84	23929	4195
+178
+
+chain 2784 chr9_gl000199_random 169874 + 60406 60450 chr9_random 1146434 + 1000736 1000780 8481
+44
+
+chain 2406 chr9_gl000199_random 169874 + 38361 40328 chr9_random 1146434 + 940183 941126 6867
+36	1868	844
+63
+
+chain 2091 chr9_gl000199_random 169874 + 135580 135759 chr9_random 1146434 + 1043989 1044168 130849
+179
+
+chain 1790 chr9_gl000199_random 169874 + 113899 113969 chr9 140273252 - 71272426 71272496 22178754
+70
+
+chain 1047 chr9_gl000199_random 169874 + 114872 114901 chr9_random 1146434 + 1035274 1035303 118930
+29
+
+chain 1014 chr9_gl000199_random 169874 + 129141 129510 chr9_random 1146434 + 949663 949862 115384
+82	201	31
+86
+
+chain 827 chr9_gl000199_random 169874 + 125159 125187 chr9 140273252 - 71272290 71272318 10194134
+28
+
+chain 754 chr9_gl000199_random 169874 + 136743 136786 chr9_random 1146434 - 170925 170968 528799
+43
+
+chain 683 chr9_gl000199_random 169874 + 134041 134094 chr9_random 1146434 + 1025518 1025571 412663
+53
+
+chain 494 chr9_gl000199_random 169874 + 71001 71031 chr9_random 1146434 + 983095 983125 1059560
+30
+
+chain 444 chr9_gl000199_random 169874 + 133651 133674 chr9_random 1146434 + 1066888 1066911 84972
+23
+
+chain 309 chr9_gl000199_random 169874 + 137506 137547 chr9_random 1146434 + 967717 967758 659942
+41
+
+chain 254 chr9_gl000199_random 169874 + 125119 125159 chr9_random 1146434 + 1071966 1072006 1499804
+40
+
+chain 241 chr9_gl000199_random 169874 + 137060 137086 chr9_random 1146434 + 965055 965081 39489
+26
+
+chain 190 chr9_gl000199_random 169874 + 124136 124176 chr9_random 1146434 + 947206 947246 772655
+40
+
+chain 17692629 chr9_gl000200_random 187035 + 0 187035 chr9_random 1146434 + 666116 853151 157
+187035
+
+chain 3482851 chr9_gl000201_random 36148 + 0 36148 chr9_random 1146434 + 0 36148 835
+36148
+
+chain 1574309 chrM 16571 + 0 16571 chrM 16571 + 0 16571 1542
+16571
+
+chain 15737781 chrUn_gl000211 166566 + 0 166566 chr22_random 257318 + 90752 257318 187
+166566
+
+chain 17750502 chrUn_gl000212 186858 + 0 186858 chr13_random 186858 + 0 186858 154
+186858
+
+chain 15269201 chrUn_gl000213 164239 + 0 164239 chr21 46944323 - 32900547 33064909 192
+4659	1	0
+8525	1	0
+592	12	11
+2258	2	0
+942	18	18
+7633	0	33
+6726	1	1
+49	4	4
+119	1	1
+127	6	0
+114	1	1
+1963	1	1
+856	0	1
+2836	1	0
+20	0	1
+262	6	6
+128	1	1
+22	1	1
+8105	14	0
+16	4	0
+1875	0	1
+8447	4	0
+157	10	10
+2207	0	1
+2729	0	2
+9463	1	0
+239	1	0
+17	2	0
+1990	3	0
+7559	3	2
+1342	1	1
+73	1	1
+1095	9	9
+57	1	1
+80	1	1
+290	16	16
+79	9	9
+151	4	4
+728	4	0
+580	4	0
+160	8	8
+184	1	1
+21	1	1
+3074	12	10
+471	6	6
+698	11	11
+338	0	3
+205	0	28
+1909	0	10
+508	1	1
+31	1	1
+847	1	2
+271	0	4
+337	1	1
+31	3	0
+355	1	1
+61	1	1
+237	1	1
+60	24	0
+307	0	4
+941	1	1
+37	5	0
+338	31	24
+563	0	644
+637	12	12
+369	1	1
+26	1	1
+136	630	0
+374	1	1
+31	1	1
+375	1	1
+48	1	1
+2210	1	1
+35	0	1
+1039	19	1
+53	1	1
+270	8	6
+337	1	1
+40	1	1
+2174	6	6
+841	1	1
+29	1	1
+1975	0	10
+37	1	1
+703	0	60
+223	15	15
+1844	0	4
+394	3	0
+63	1	1
+34	1	1
+121	1	1
+25	4	10
+12	12	0
+2694	8	8
+100	2	0
+2952	1	1
+27	1	1
+1508	0	4
+2169	16	16
+48	1	0
+894	9	9
+310	0	1
+2288	0	2
+4522	0	4
+32	1	1
+3231	0	6
+2045	1	1
+44	1	1
+955	9	9
+345	6	6
+129	1	1
+19	1	1
+167	1	0
+333	2	0
+716	22	22
+1384	1	0
+189	1	1
+23	0	28
+1452	1	1
+28	1	1
+1661	1	4
+496	18	17
+141	1	1
+44	1	1
+1971	1	6
+103	1	1
+47	1	1
+662	6	0
+318	0	5
+935	1	1
+47	1	1
+220	1	1
+36	1	1
+815	1	0
+49	1	0
+224	3	4
+86	1	1
+47	1	1
+683	2	2
+42	1	1
+1493	0	1
+373	0	1
+454	0	2
+179	0	12
+639	0	5
+616	66	81
+613	0	1
+198	8	11
+1412	4	0
+604	4	0
+1065	5	0
+3599	1	1
+44	1	1
+311	4	0
+302	1	0
+1762	31	31
+555
+
+chain 19447 chrUn_gl000213 164239 + 98731 98946 chr21 46944323 - 32999281 32999496 6410578
+102	6	6
+107
+
+chain 5115 chrUn_gl000213 164239 + 98535 98731 chr15 100338915 + 19297082 19297917 3190124
+68	49	688
+79
+
+chain 918427 chrUn_gl000214 137718 + 80069 90748 chr1 247249719 - 105489797 105500468 3815
+119	1	1
+25	1	1
+201	5	5
+65	5	5
+139	1	1
+69	1	1
+150	1	1
+67	4	4
+380	6	0
+73	10	10
+167	10	10
+63	1	1
+23	1	1
+369	4	4
+43	1	1
+235	1	1
+83	6	6
+99	1	1
+91	1	1
+116	14	14
+488	3	3
+47	1	0
+11	1	1
+216	1	1
+23	1	1
+84	1	1
+71	1	1
+549	1	1
+22	1	1
+146	1	1
+102	1	1
+104	1	1
+80	1	1
+59	1	1
+19	1	1
+402	1	1
+39	1	1
+284	1	1
+33	1	1
+161	4	4
+34	1	1
+125	1	1
+20	1	1
+472	1	1
+19	1	1
+228	23	23
+425	1	1
+99	1	1
+266	1	1
+42	1	1
+54	1	1
+62	1	1
+228	4	2
+85	6	6
+68	1	1
+242	1	1
+167	1	1
+33	1	1
+133	24	24
+773	7	7
+379	0	1
+218	62	62
+81	1	1
+37	1	1
+364	1	1
+29	1	1
+234
+
+chain 143213 chrUn_gl000214 137718 + 129234 137707 chr4 191273063 - 142244722 142253930 901087
+227	142	142
+52	32	32
+60	159	159
+56	5	5
+135	69	69
+183	83	83
+78	152	152
+70	161	161
+102	13	13
+186	9	9
+127	123	123
+78	241	241
+116	4845	5724
+91	242	98
+110	65	65
+64	13	13
+72	181	181
+131
+
+chain 112581 chrUn_gl000214 137718 + 116800 119267 chr4 191273063 + 48987510 48989977 1137439
+144	225	225
+135	141	141
+87	10	10
+130	173	173
+90	147	147
+57	103	103
+70	22	22
+84	50	50
+113	26	26
+103	37	37
+69	102	102
+127	4	4
+58	73	73
+87
+
+chain 35731 chrUn_gl000214 137718 + 49713 50123 chr21_random 1679693 + 637667 638077 3744988
+55	5	5
+34	1	1
+315
+
+chain 33173 chrUn_gl000214 137718 + 125487 134177 chr1 247249719 - 105123947 105126634 1162767
+65	110	110
+58	32	32
+395	7	7
+90	6069	74
+68	8	0
+64	36	36
+114	56	56
+54	63	63
+58	137	137
+182	277	277
+54	21	21
+122	248	248
+52	190	190
+60
+
+chain 26395 chrUn_gl000214 137718 + 40302 40606 chr1 247249719 - 18749005 18749307 6333362
+57	1	0
+75	1	0
+112	1	1
+57
+
+chain 25884 chrUn_gl000214 137718 + 126321 126850 chr21_random 1679693 + 746615 747120 6569895
+87	97	73
+114	5	5
+50	118	118
+58
+
+chain 25524 chrUn_gl000214 137718 + 41463 41766 chr9 140273252 - 40046622 40046925 6760130
+54	7	7
+122	4	4
+116
+
+chain 25177 chrUn_gl000214 137718 + 122978 125190 chr21_random 1679693 - 928041 930254 1258444
+118	228	229
+72	288	288
+139	44	44
+185	600	600
+136	37	37
+126	58	58
+181
+
+chain 23478 chrUn_gl000214 137718 + 136191 136535 chr4 191273063 + 48976406 48976750 8004925
+183	83	83
+78
+
+chain 20443 chrUn_gl000214 137718 + 41766 42878 chr3 199501827 + 629423 630533 8757399
+9	908	906
+118	25	25
+52
+
+chain 20379 chrUn_gl000214 137718 + 135162 135774 chr21_random 1679693 - 927923 928535 1491304
+50	44	44
+225	152	152
+141
+
+chain 18931 chrUn_gl000214 137718 + 44528 44730 chr10 135374737 - 38544783 38544985 11331455
+202
+
+chain 18826 chrUn_gl000214 137718 + 43343 43562 chr2 242951149 - 53551644 53551863 11416331
+110	1	1
+31	1	1
+76
+
+chain 18670 chrUn_gl000214 137718 + 90865 91063 chr1 247249719 - 105065042 105065240 11545618
+198
+
+chain 17773 chrUn_gl000214 137718 + 131919 132224 chr1 247249719 - 105124387 105124692 2973977
+225	10	10
+70
+
+chain 16259 chrUn_gl000214 137718 + 112825 112997 chr2 242951149 + 132826168 132826340 13778307
+172
+
+chain 16179 chrUn_gl000214 137718 + 117367 119564 chr1 247249719 + 142120582 142122781 1230197
+57	994	995
+43	121	121
+25	103	103
+37	69	69
+76	567	568
+105
+
+chain 14745 chrUn_gl000214 137718 + 40137 40293 chr18 76117153 + 36159000 36159156 15342897
+156
+
+chain 14511 chrUn_gl000214 137718 + 35480 35726 chr21_random 1679693 + 599809 599984 15605110
+107	80	9
+59
+
+chain 13694 chrUn_gl000214 137718 + 21320 21487 chrX 154913754 - 125740203 125740370 16565517
+81	11	11
+75
+
+chain 13486 chrUn_gl000214 137718 + 6106 6250 chr5 180857866 + 84443323 84443467 16839883
+144
+
+chain 13485 chrUn_gl000214 137718 + 18381 18548 chrX 154913754 + 88818181 88818344 16841154
+59	4	0
+49	4	4
+51
+
+chain 12687 chrUn_gl000214 137718 + 41058 41208 chr4 191273063 - 138230980 138231130 9286530
+62	5	5
+83
+
+chain 12516 chrUn_gl000214 137718 + 121124 121344 chr4 191273063 + 48979662 48979882 18214722
+66	74	74
+80
+
+chain 12053 chrUn_gl000214 137718 + 40633 40761 chrX 154913754 + 112045399 112045527 18908316
+128
+
+chain 11633 chrUn_gl000214 137718 + 43977 44114 chr4 191273063 - 11125034 11125171 12115615
+68	9	9
+60
+
+chain 11343 chrUn_gl000214 137718 + 39886 40006 chr13 114142980 + 66998338 66998458 20107936
+120
+
+chain 10884 chrUn_gl000214 137718 + 18108 18254 chr7 158821424 - 131367688 131367833 20945231
+55	19	18
+72
+
+chain 10521 chrUn_gl000214 137718 + 42241 42602 chr8 146274826 - 25959812 25960177 13454333
+84	222	226
+55
+
+chain 10411 chrUn_gl000214 137718 + 45055 45186 chr20 62435964 + 7050253 7050384 21896014
+54	12	12
+65
+
+chain 10343 chrUn_gl000214 137718 + 8804 8914 chrY 57772954 + 22287260 22287370 22043563
+110
+
+chain 9757 chrUn_gl000214 137718 + 19458 19875 chr3 199501827 - 187590477 187590901 23376485
+52	295	302
+70
+
+chain 9700 chrUn_gl000214 137718 + 39692 39809 chrX 154913754 - 41279737 41279854 23514677
+52	4	4
+61
+
+chain 9578 chrUn_gl000214 137718 + 45502 45617 chrX 154913754 + 43420636 43420751 23808291
+55	5	5
+55
+
+chain 7894 chrUn_gl000214 137718 + 124390 125487 chr4 191273063 - 142252912 142254012 6167993
+130	754	757
+69	123	123
+21
+
+chain 7612 chrUn_gl000214 137718 + 129655 137576 chr1 247249719 + 142120436 142122192 1126110
+32	89	89
+59	44	44
+27	862	716
+54	6116	97
+123	138	138
+47	149	149
+97	35	35
+49
+
+chain 7146 chrUn_gl000214 137718 + 43209 43286 chr18 76117153 - 9582204 9582281 16185526
+77
+
+chain 6775 chrUn_gl000214 137718 + 131335 131918 chr4 191273063 - 142062211 142062794 1233528
+62	218	218
+89	189	189
+25
+
+chain 6321 chrUn_gl000214 137718 + 44440 44513 chr1 247249719 + 157810312 157810385 13757396
+56	5	5
+12
+
+chain 5727 chrUn_gl000214 137718 + 119564 119897 chr4 191273063 - 142062730 142063063 7342832
+77	196	196
+60
+
+chain 5584 chrUn_gl000214 137718 + 136603 136661 chr4 191273063 + 48976819 48976877 31707162
+58
+
+chain 5192 chrUn_gl000214 137718 + 41407 41463 chr4 191273063 + 95935104 95935160 21196855
+56
+
+chain 4895 chrUn_gl000214 137718 + 6041 6105 chr11 134452384 + 65843917 65843981 20155275
+64
+
+chain 4869 chrUn_gl000214 137718 + 43083 43135 chr9 140273252 - 106613347 106613399 21934699
+52
+
+chain 4480 chrUn_gl000214 137718 + 42602 42659 chr7 158821424 - 39929511 39929568 12681275
+57
+
+chain 4078 chrUn_gl000214 137718 + 41235 41291 chrX 154913754 - 134405062 134405118 18412789
+56
+
+chain 4015 chrUn_gl000214 137718 + 42902 42960 chr10 135374737 + 54220968 54221026 24474909
+58
+
+chain 3895 chrUn_gl000214 137718 + 40957 41057 chr14 106368585 + 31140172 31140272 6582169
+100
+
+chain 3738 chrUn_gl000214 137718 + 42125 42173 chrX 154913754 + 103679820 103679868 22522957
+48
+
+chain 3537 chrUn_gl000214 137718 + 136028 136122 chr4 191273063 + 48976243 48976337 4189785
+94
+
+chain 3097 chrUn_gl000214 137718 + 17979 18039 chrX 154913754 - 102020287 102020347 24003938
+60
+
+chain 2977 chrUn_gl000214 137718 + 126408 126469 chr1 247249719 - 105124849 105124910 6601664
+61
+
+chain 2968 chrUn_gl000214 137718 + 41775 41809 chr8 146274826 + 100416036 100416070 11606659
+34
+
+chain 2831 chrUn_gl000214 137718 + 137492 137527 chr4 191273063 + 48977417 48977452 2940885
+17	9	9
+9
+
+chain 2572 chrUn_gl000214 137718 + 44291 44369 chr11 134452384 - 117952414 117952492 17845944
+78
+
+chain 2345 chrUn_gl000214 137718 + 42033 42103 chr4 191273063 - 122527078 122527148 13059103
+70
+
+chain 2276 chrUn_gl000214 137718 + 43135 43209 chr1 247249719 + 86869873 86869947 13860931
+74
+
+chain 1770 chrUn_gl000214 137718 + 44144 44227 chr3 199501827 + 24100092 24100175 18271654
+83
+
+chain 1506 chrUn_gl000214 137718 + 36174 36256 chr1 247249719 - 105422371 105422453 16376759
+82
+
+chain 1502 chrUn_gl000214 137718 + 43875 43977 chr9 140273252 + 102510935 102511037 11228177
+102
+
+chain 1456 chrUn_gl000214 137718 + 130737 130768 chr21_random 1679693 - 929809 929840 22601085
+31
+
+chain 1365 chrUn_gl000214 137718 + 125246 125274 chr21_random 1679693 - 930310 930338 15151243
+28
+
+chain 1098 chrUn_gl000214 137718 + 42962 43013 chr6 170899992 - 83239423 83239474 24355258
+51
+
+chain 931 chrUn_gl000214 137718 + 41878 41928 chr11 134452384 - 41659375 41659425 15038916
+50
+
+chain 888 chrUn_gl000214 137718 + 45207 45259 chr11 134452384 + 93610909 93610961 21407350
+52
+
+chain 856 chrUn_gl000214 137718 + 119897 119930 chr19 63811651 - 14205840 14205873 23032647
+33
+
+chain 766 chrUn_gl000214 137718 + 127016 127090 chr19 63811651 - 14200495 14200569 19831992
+74
+
+chain 676 chrUn_gl000214 137718 + 18987 19049 chr11 134452384 + 106173710 106173772 23556763
+62
+
+chain 650 chrUn_gl000214 137718 + 132603 132659 chr21_random 1679693 + 746889 746945 1349757
+56
+
+chain 423 chrUn_gl000214 137718 + 20746 20796 chr2 242951149 - 226029097 226029147 25845790
+50
+
+chain 16237347 chrUn_gl000215 172545 + 28 172526 chr21 46944323 + 13950000 14122426 177
+3255	0	4
+29034	1	0
+5104	4	0
+10299	0	8
+14263	11	11
+94	6	0
+113	107	1
+75	1	1
+91	1	1
+24	1	1
+6681	0	33
+907	41	41
+7674	2	0
+2274	12	11
+563	0	1
+8540	1	0
+12525	1	1
+36	1	1
+25408	0	12
+3782	0	2
+694	85	67
+996	1	3
+1425	12	12
+1827	1	1
+21	1	1
+941	13	13
+2073	0	8
+28	1	1
+506	0	2
+1227	1	0
+1108	2	2
+28	1	1
+396	1	0
+253	14	14
+184	1	1
+49	1	1
+2962	1	1
+45	4	0
+1510	19	19
+2709	25	25
+1068	0	4
+836	1	0
+1871	0	1
+579	4	0
+60	14	14
+2466	27	27
+1450	1	0
+19	1	1
+618	6	6
+2880	1	0
+450	0	2
+27	0	4
+4576	1	1
+20	1	1
+789	0	1
+721	14	14
+1438	35	31
+1381	1	1
+18	1	1
+73	12	12
+195	1	1
+35	1	1
+708
+
+chain 40526 chrUn_gl000216 172294 + 149263 155793 chr18 76117153 - 76016375 76018189 3221814
+113	325	326
+78	431	292
+71	14	14
+107	786	375
+37	69	0
+81	2953	216
+58	1361	0
+46
+
+chain 27660 chrUn_gl000216 172294 + 75671 76099 chr20 62435964 - 33142597 33142960 5774439
+63	0	10
+32	5	0
+14	10	0
+50	35	0
+20	10	0
+56	5	0
+53	21	11
+54
+
+chain 27279 chrUn_gl000216 172294 + 130292 130617 chrX 154913754 + 63390360 63390685 5931924
+69	12	12
+78	1	1
+165
+
+chain 17860 chrUn_gl000216 172294 + 130000 130214 chr4 191273063 + 73778471 73778685 12240737
+58	12	12
+144
+
+chain 16947 chrUn_gl000216 172294 + 147288 147775 chr18 76117153 - 76016450 76016937 13094679
+76	288	288
+123
+
+chain 13816 chrUn_gl000216 172294 + 129031 129176 chr8 146274826 - 38602125 38602270 16419487
+145
+
+chain 12180 chrUn_gl000216 172294 + 145189 145506 chrY 57772954 + 11928279 11928596 18712695
+46	95	95
+51	66	66
+59
+
+chain 11701 chrUn_gl000216 172294 + 158739 158864 chr18 76117153 + 99277 99402 19495084
+125
+
+chain 11637 chrUn_gl000216 172294 + 171754 172194 chrY 57772954 + 11932706 11933147 19600583
+53	299	300
+88
+
+chain 11521 chrUn_gl000216 172294 + 129787 129947 chr6 170899992 + 5983639 5983799 19799726
+64	26	26
+70
+
+chain 10625 chrUn_gl000216 172294 + 164963 165111 chr18 76117153 + 100265 100413 21456050
+73	25	25
+50
+
+chain 10470 chrUn_gl000216 172294 + 131591 131702 chrX 154913754 + 36583233 36583344 21778508
+111
+
+chain 10288 chrUn_gl000216 172294 + 131963 132072 chr3 199501827 - 99262429 99262538 22162166
+109
+
+chain 9778 chrUn_gl000216 172294 + 141853 142019 chr18 76117153 - 76016600 76016834 23327029
+64	49	117
+53
+
+chain 9609 chrUn_gl000216 172294 + 135933 137341 chrY 57772954 + 11926871 11928279 23735609
+56	647	1260
+56	613	0
+36
+
+chain 9489 chrUn_gl000216 172294 + 169302 169609 chrY 57772954 + 11921023 11921330 24024953
+52	191	191
+64
+
+chain 9460 chrUn_gl000216 172294 + 132170 132290 chrY 57772954 + 11935643 11935763 24098583
+50	10	10
+60
+
+chain 9059 chrUn_gl000216 172294 + 169179 169274 chrY 57772954 - 366511 366606 24861253
+95
+
+chain 8863 chrUn_gl000216 172294 + 133271 135681 chrY 57772954 - 372628 372853 25150456
+61	2277	92
+72
+
+chain 8329 chrUn_gl000216 172294 + 1479 1877 chr4 191273063 - 141929935 141931620 25915977
+67	278	1565
+53
+
+chain 8155 chrUn_gl000216 172294 + 150573 151188 chrY 57772954 - 377413 378366 22301630
+51	559	897
+5
+
+chain 8086 chrUn_gl000216 172294 + 168370 168455 chr18 76117153 - 76017788 76017873 26288571
+85
+
+chain 7777 chrUn_gl000216 172294 + 34186 34268 chr1 247249719 - 24981278 24981360 26771397
+82
+
+chain 6822 chrUn_gl000216 172294 + 132393 132465 chrY 57772954 - 376390 376462 28544596
+72
+
+chain 6622 chrUn_gl000216 172294 + 9240 9310 chr10 135374737 + 41683434 41683504 28988878
+70
+
+chain 6573 chrUn_gl000216 172294 + 130631 130733 chr5 180857866 - 72032622 72032724 12023329
+102
+
+chain 6476 chrUn_gl000216 172294 + 146529 146597 chr18 76117153 - 76017808 76017876 29355811
+68
+
+chain 6422 chrUn_gl000216 172294 + 8523 8591 chr4 191273063 + 48829234 48829302 29489285
+68
+
+chain 6384 chrUn_gl000216 172294 + 148442 148586 chrY 57772954 - 378355 378430 29582296
+29	69	0
+46
+
+chain 6003 chrUn_gl000216 172294 + 133483 133546 chrY 57772954 - 370776 370839 30561430
+63
+
+chain 5985 chrUn_gl000216 172294 + 11844 11907 chr4 191273063 + 48811176 48811239 30589131
+63
+
+chain 5885 chrUn_gl000216 172294 + 151788 151850 chrY 57772954 - 366263 366325 30854068
+62
+
+chain 5721 chrUn_gl000216 172294 + 136853 136913 chrY 57772954 - 372235 372295 31317120
+60
+
+chain 5667 chrUn_gl000216 172294 + 19071 19131 chr4 191273063 + 48811263 48811323 31460984
+60
+
+chain 5339 chrUn_gl000216 172294 + 145664 145720 chrY 57772954 + 11941006 11941062 32420221
+56
+
+chain 5322 chrUn_gl000216 172294 + 130963 131035 chr5 180857866 - 36043748 36043820 20305124
+72
+
+chain 5257 chrUn_gl000216 172294 + 158216 158271 chr18 76117153 + 96100 96155 32682417
+55
+
+chain 5221 chrUn_gl000216 172294 + 7155 7210 chr4 191273063 + 48836505 48836560 32772522
+55
+
+chain 5121 chrUn_gl000216 172294 + 15141 15195 chr4 191273063 + 48847759 48847813 33093239
+54
+
+chain 5012 chrUn_gl000216 172294 + 26593 26646 chr21 46944323 - 37095349 37095402 33456608
+53
+
+chain 4930 chrUn_gl000216 172294 + 37276 37328 chr1 247249719 - 24981705 24981757 33717061
+52
+
+chain 4884 chrUn_gl000216 172294 + 137193 137244 chrY 57772954 - 377416 377467 33922210
+51
+
+chain 4821 chrUn_gl000216 172294 + 20849 20900 chr20 62435964 - 33142732 33142783 34122269
+51
+
+chain 4766 chrUn_gl000216 172294 + 152958 153008 chr18 76117153 - 76017195 76017245 34319410
+50
+
+chain 4757 chrUn_gl000216 172294 + 155624 155674 chr18 76117153 - 76018020 76018070 34342345
+50
+
+chain 2863 chrUn_gl000216 172294 + 172194 172224 chrY 57772954 + 11925069 11925099 19922357
+30
+
+chain 2829 chrUn_gl000216 172294 + 131145 131290 chr12 132349534 + 50244945 50245090 12112131
+51	88	88
+6
+
+chain 2529 chrUn_gl000216 172294 + 129176 129203 chr9 140273252 - 119219512 119219539 22134781
+27
+
+chain 2341 chrUn_gl000216 172294 + 131196 131233 chr3 199501827 - 98572452 98572489 18288091
+37
+
+chain 2151 chrUn_gl000216 172294 + 131290 131397 chr7 158821424 - 127191925 127192032 12067691
+107
+
+chain 2108 chrUn_gl000216 172294 + 149377 153105 chrY 57772954 + 11933439 11934497 20496839
+67	3022	286
+50	506	572
+83
+
+chain 1614 chrUn_gl000216 172294 + 130868 130925 chr3 199501827 - 79251115 79251172 16953843
+57
+
+chain 1538 chrUn_gl000216 172294 + 76099 76129 chr21 46944323 - 37102976 37103006 11762953
+30
+
+chain 694 chrUn_gl000216 172294 + 135555 135593 chrY 57772954 - 377637 377675 25976788
+38
+
+chain 532 chrUn_gl000216 172294 + 153980 155370 chrY 57772954 - 378352 378449 22847936
+39	1293	0
+58
+
+chain 454 chrUn_gl000216 172294 + 863 915 chr4 191273063 + 48799453 48799505 31198348
+52
+
+chain 383 chrUn_gl000216 172294 + 153157 153210 chr18 76117153 - 76017394 76017447 29745290
+53
+
+chain 174 chrUn_gl000216 172294 + 138050 138103 chrY 57772954 + 11945950 11946003 28091780
+53
+
+chain 99 chrUn_gl000216 172294 + 11396 11447 chr20 62435964 - 33142766 33142817 31359773
+51
+
+chain 13777792 chrUn_gl000217 172149 + 23665 172149 chr21_random 1679693 - 1239693 1388121 218
+366	17	17
+766	1	0
+21	0	8
+60	2	0
+3460	4	0
+2511	2	0
+113	1	0
+1145	0	1
+931	1	1
+37	1	1
+107	13	13
+4657	1	1
+48	1	1
+2113	0	1
+574	10	0
+111	1	0
+49	1	1
+1025	3	0
+497	0	11
+154	5	0
+640	0	6
+1684	0	16
+300	1	0
+1527	0	6
+147	1	0
+718	18	0
+30	1	1
+1243	1	1
+16	1	1
+162	28	0
+401	0	11
+281	1	1
+27	1	1
+892	1	0
+45	1	1
+2501	0	26
+74	115	11
+2278	8	8
+1028	0	1
+756	7	7
+1386	1	0
+3286	40	0
+504	1	0
+989	1	1
+24	1	1
+123	36	37
+2057	0	26
+72	2	0
+945	1	1
+22	1	1
+1558	1	1
+43	2	0
+2083	22	0
+462	0	1
+86	1	1
+37	1	1
+1415	0	1
+22	0	1
+1139	24	25
+1775	11	11
+2714	1	1
+41	1	1
+4780	0	1
+352	1	1
+25	1	1
+171	1	0
+514	1	0
+2199	1	1
+48	1	1
+262	3	1
+2426	0	1
+502	0	2
+1043	1	1
+49	1	0
+3147	0	3
+4432	1	1
+17	1	1
+2420	1	0
+43	1	1
+1809	1	0
+15	1	1
+1710	0	34
+61	36	0
+119	0	2
+4683	1	1
+44	1	1
+58	23	0
+44	0	104
+50	98	0
+43	1	1
+214	1	41
+29	0	1
+4	6	13
+39	0	105
+122	1	1
+31	17	1
+69	234	6
+48	1	17
+40	1	1
+1306	2	0
+3089	0	1
+2059	1	1
+32	1	1
+137	1	4
+584	1	0
+2518	1	0
+480	0	4
+6	2	0
+22	8	0
+177	1	1
+29	1	1
+6728	0	1
+1945	0	2
+8972	11	11
+806	1	3
+3054	0	3
+649	0	4
+1956	1	3
+795	1	0
+16	1	1
+1498	1	1
+28	1	1
+3012	5	0
+238	0	5
+220	0	5
+441	0	31
+141	10	0
+57	5	0
+1652	1	0
+233	1	0
+855	1	0
+845	38	0
+395	0	38
+182	22	0
+494	0	139
+1699	1	1
+42	0	1
+2261	1	1
+33	1	1
+3400	1	1
+41	1	1
+2247	0	2
+46	4	0
+34	0	14
+1049	1	13
+223	1	1
+49	1	1
+746	1	1
+36	1	1
+3491	0	1
+528
+
+chain 29979 chrUn_gl000217 172149 + 0 388 chr9 140273252 - 70842853 70843241 4686196
+80	39	39
+172	1	1
+24	1	1
+71
+
+chain 18989 chrUn_gl000217 172149 + 8221 8418 chr12 132349534 - 39661230 39661427 11281819
+197
+
+chain 10175 chrUn_gl000217 172149 + 14880 15009 chr19 63811651 + 45504623 45504752 22420709
+57	12	12
+60
+
+chain 3003 chrUn_gl000217 172149 + 63765 63801 chr6 170899992 + 56559189 56559225 3519131
+36
+
+chain 15268007 chrUn_gl000218 161147 + 0 161147 chr4_random 842648 + 681501 842648 193
+161147
+
+chain 274326 chrUn_gl000219 179198 + 111203 114251 chr8 146274826 - 136639851 136643413 309026
+102	1	1
+45	1	1
+484	9	9
+416	19	537
+171	4	0
+45	1	1
+189	7	7
+1328	1	1
+25	1	1
+199
+
+chain 235925 chrUn_gl000219 179198 + 35758 40113 chr15 100338915 - 47328984 47333335 444051
+127	1	1
+284	1	1
+140	1	1
+133	1	1
+73	1	1
+89	1	1
+75	13	8
+90	1	1
+92	1	1
+53	1	1
+73	1	1
+71	137	137
+163	8	8
+63	55	55
+141	31	31
+188	97	97
+60	103	103
+177	192	193
+314	188	188
+58	236	236
+75	260	260
+62	155	155
+105	29	29
+135
+
+chain 46161 chrUn_gl000219 179198 + 66272 68851 chrX 154913754 - 104037210 104039793 2773810
+120	238	238
+52	281	281
+59	653	657
+101	247	247
+106	343	343
+50	27	27
+62	173	173
+67
+
+chain 39536 chrUn_gl000219 179198 + 161917 162706 chr3 199501827 + 46165513 46166302 3318717
+67	218	218
+170	33	33
+104	60	60
+51	4	4
+82
+
+chain 37284 chrUn_gl000219 179198 + 19843 20929 chr8 146274826 + 98123209 98124295 3557690
+51	99	100
+128	134	134
+52	226	225
+160	168	168
+68
+
+chain 28967 chrUn_gl000219 179198 + 161273 161605 chr11 134452384 - 120964606 120964939 5150829
+171	2	3
+60	3	3
+96
+
+chain 28762 chrUn_gl000219 179198 + 6734 7878 chr3 199501827 - 92709198 92710343 5264432
+50	316	316
+83	67	67
+64	228	228
+51	85	86
+50	65	65
+85
+
+chain 21234 chrUn_gl000219 179198 + 175633 175875 chr1 247249719 - 2003467 2003709 9514914
+86	1	1
+40	1	1
+114
+
+chain 19234 chrUn_gl000219 179198 + 161066 161917 chr3 199501827 - 120235323 120237534 3582834
+110	737	2097
+4
+
+chain 14579 chrUn_gl000219 179198 + 21180 21751 chr1 247249719 - 137161846 137162418 6911796
+101	255	256
+2	163	163
+50
+
+chain 14519 chrUn_gl000219 179198 + 21064 21625 chr8 146274826 - 24167411 24167976 5552170
+59	415	419
+87
+
+chain 12254 chrUn_gl000219 179198 + 20707 20861 chr10 135374737 - 130087649 130087801 7386312
+11	3	1
+47	1	0
+4	0	1
+88
+
+chain 9835 chrUn_gl000219 179198 + 175209 175553 chr1 247249719 + 75620763 75621106 11122143
+78	179	178
+87
+
+chain 9013 chrUn_gl000219 179198 + 69512 69754 chr7 158821424 - 49488455 49488697 24923378
+57	133	133
+52
+
+chain 8698 chrUn_gl000219 179198 + 38816 38977 chr2 242951149 + 197483269 197483430 445169
+50	27	27
+84
+
+chain 7558 chrUn_gl000219 179198 + 37648 39844 chr4 191273063 - 67477312 67479509 573905
+31	2054	2055
+111
+
+chain 7043 chrUn_gl000219 179198 + 7883 7996 chrX 154913754 + 69120337 69120450 10599908
+113
+
+chain 6948 chrUn_gl000219 179198 + 21437 21525 chr10 135374737 - 55879531 55879619 9852807
+88
+
+chain 6886 chrUn_gl000219 179198 + 69191 69264 chrX 154913754 - 102980817 102980890 28429791
+73
+
+chain 6839 chrUn_gl000219 179198 + 21356 21436 chr11 134452384 + 41149119 41149199 10517795
+80
+
+chain 6788 chrUn_gl000219 179198 + 67776 67858 chr1 247249719 - 168765537 168765619 14909693
+1	2	2
+79
+
+chain 6785 chrUn_gl000219 179198 + 65376 65449 chr6 170899992 - 64502886 64502959 18163056
+73
+
+chain 6479 chrUn_gl000219 179198 + 35525 35758 chr13 114142980 - 61572553 61572786 1009673
+94	1	1
+129	2	2
+7
+
+chain 6180 chrUn_gl000219 179198 + 161178 161256 chr16 88827254 + 48470284 48470362 9569492
+78
+
+chain 5767 chrUn_gl000219 179198 + 65835 65896 chr1 247249719 + 223356684 223356745 31174397
+61
+
+chain 5622 chrUn_gl000219 179198 + 64700 64760 chr20 62435964 - 34176164 34176224 31585501
+60
+
+chain 4453 chrUn_gl000219 179198 + 175305 175363 chr7 158821424 - 154223466 154223524 19289607
+58
+
+chain 4398 chrUn_gl000219 179198 + 39190 39280 chr3 199501827 - 39205036 39205126 641764
+90
+
+chain 4168 chrUn_gl000219 179198 + 39128 39178 chrX 154913754 + 101254041 101254091 4762602
+50
+
+chain 4142 chrUn_gl000219 179198 + 160731 161020 chr7 158821424 + 108154685 108154975 5568871
+69	147	148
+73
+
+chain 4059 chrUn_gl000219 179198 + 39531 39627 chrY 57772954 + 3377002 3377098 1049766
+96
+
+chain 3905 chrUn_gl000219 179198 + 39425 39515 chr4 191273063 - 20599126 20599216 1025664
+90
+
+chain 3833 chrUn_gl000219 179198 + 19916 19966 chr11 134452384 - 24481539 24481589 14324455
+50
+
+chain 3723 chrUn_gl000219 179198 + 21281 21353 chr8 146274826 + 142341809 142341882 8036105
+11	0	1
+61
+
+chain 3631 chrUn_gl000219 179198 + 7185 7231 chr4 191273063 - 60113302 60113348 10096087
+46
+
+chain 3560 chrUn_gl000219 179198 + 35297 35440 chrX 154913754 + 31459857 31460000 1356163
+59	9	9
+75
+
+chain 3418 chrUn_gl000219 179198 + 74680 74734 chr2 242951149 + 159856161 159856226 35171835
+17	0	12
+9	2	1
+26
+
+chain 3363 chrUn_gl000219 179198 + 65597 65637 chr10 135374737 + 67903510 67903550 17680942
+40
+
+chain 3281 chrUn_gl000219 179198 + 38411 38486 chr18 76117153 + 65271563 65271638 907991
+75
+
+chain 3262 chrUn_gl000219 179198 + 162509 162544 chrX 154913754 - 14195886 14195921 20233062
+35
+
+chain 3092 chrUn_gl000219 179198 + 161605 161689 chr2 242951149 - 35465049 35465133 8792079
+19	6	6
+59
+
+chain 3074 chrUn_gl000219 179198 + 8990 9025 chr5 180857866 - 164468813 164468848 19527162
+35
+
+chain 3012 chrUn_gl000219 179198 + 38101 39406 chr14 106368585 - 62185839 62187145 783679
+26	1240	1241
+39
+
+chain 2934 chrUn_gl000219 179198 + 161840 161913 chr5 180857866 + 13471789 13471862 3866284
+73
+
+chain 2839 chrUn_gl000219 179198 + 34989 35118 chr8 146274826 + 40409778 40409907 1133484
+56	12	12
+61
+
+chain 2727 chrUn_gl000219 179198 + 21634 21700 chr14 106368585 - 78516623 78516689 9118599
+66
+
+chain 2697 chrUn_gl000219 179198 + 68852 68888 chr5 180857866 + 9312654 9312690 14610628
+36
+
+chain 2584 chrUn_gl000219 179198 + 35177 35274 chr3 199501827 + 147129328 147129425 4467916
+97
+
+chain 2547 chrUn_gl000219 179198 + 161690 161789 chr5 180857866 + 112830789 112830888 9276265
+99
+
+chain 2541 chrUn_gl000219 179198 + 162131 162175 chr12 132349534 + 54242993 54243037 9307702
+44
+
+chain 2485 chrUn_gl000219 179198 + 66217 68255 chr3 199501827 - 72358479 72360521 2866668
+55	1368	1372
+35	524	524
+56
+
+chain 2353 chrUn_gl000219 179198 + 38305 38360 chr8 146274826 - 49639359 49639414 1034303
+55
+
+chain 2230 chrUn_gl000219 179198 + 19408 19487 chr7 158821424 - 133365577 133365656 10769161
+79
+
+chain 2205 chrUn_gl000219 179198 + 37167 37218 chr2 242951149 - 113063084 113063135 1010147
+51
+
+chain 2136 chrUn_gl000219 179198 + 65993 67374 chr8 146274826 - 58386388 58387767 6969587
+99	1231	1229
+51
+
+chain 2065 chrUn_gl000219 179198 + 7314 7369 chr14 106368585 + 55554421 55554476 5303485
+55
+
+chain 1985 chrUn_gl000219 179198 + 5703 5757 chr4 191273063 - 94652192 94652246 23958560
+54
+
+chain 1979 chrUn_gl000219 179198 + 66506 66565 chr7 158821424 + 94546370 94546429 13229356
+59
+
+chain 1960 chrUn_gl000219 179198 + 8700 8761 chrY 57772954 + 20614456 20614517 21829859
+61
+
+chain 1888 chrUn_gl000219 179198 + 38366 38411 chr2 242951149 - 129971519 129971564 1057646
+45
+
+chain 1811 chrUn_gl000219 179198 + 160836 160864 chr22 49691432 - 22795768 22795796 23819908
+28
+
+chain 1737 chrUn_gl000219 179198 + 20319 20358 chrX 154913754 + 73928334 73928373 13243726
+39
+
+chain 1736 chrUn_gl000219 179198 + 19558 19630 chr12 132349534 - 63652443 63652515 6467659
+72
+
+chain 1682 chrUn_gl000219 179198 + 39076 39116 chr3 199501827 + 15208154 15208194 1287150
+40
+
+chain 1666 chrUn_gl000219 179198 + 38024 38063 chr1 247249719 - 83040882 83040921 867179
+39
+
+chain 1646 chrUn_gl000219 179198 + 37115 37153 chr15 100338915 - 50839190 50839228 850747
+38
+
+chain 1585 chrUn_gl000219 179198 + 67541 68190 chr8 146274826 - 129698985 129699635 3519578
+54	538	539
+57
+
+chain 1568 chrUn_gl000219 179198 + 21824 21882 chr4 191273063 + 144137347 144137405 18944021
+58
+
+chain 1525 chrUn_gl000219 179198 + 6513 6565 chr8 146274826 - 33560291 33560343 10738256
+52
+
+chain 1509 chrUn_gl000219 179198 + 162035 162086 chr3 199501827 + 35122783 35122834 10573790
+51
+
+chain 1485 chrUn_gl000219 179198 + 160887 160939 chr4 191273063 + 75861307 75861359 9708390
+52
+
+chain 1479 chrUn_gl000219 179198 + 65726 65767 chrX 154913754 - 87810259 87810300 15949912
+41
+
+chain 1467 chrUn_gl000219 179198 + 39689 39722 chrX 154913754 + 69240387 69240420 781473
+33
+
+chain 1461 chrUn_gl000219 179198 + 67280 67323 chr10 135374737 - 66201225 66201268 13894764
+43
+
+chain 1450 chrUn_gl000219 179198 + 67375 67437 chr5 180857866 + 57384861 57384923 6350454
+62
+
+chain 1396 chrUn_gl000219 179198 + 67210 67264 chr9 140273252 - 22551031 22551085 6094817
+54
+
+chain 1389 chrUn_gl000219 179198 + 66392 68784 chr1 247249719 + 65797848 65800245 3034140
+29	2307	2312
+56
+
+chain 1366 chrUn_gl000219 179198 + 20143 20198 chr4 191273063 - 69480908 69480963 5880463
+55
+
+chain 1339 chrUn_gl000219 179198 + 162175 162202 chr1 247249719 - 74777177 74777204 3339890
+27
+
+chain 1337 chrUn_gl000219 179198 + 68329 68386 chr10 135374737 - 97276986 97277043 13905473
+57
+
+chain 1334 chrUn_gl000219 179198 + 39950 39978 chr8 146274826 - 60735711 60735739 964260
+28
+
+chain 1215 chrUn_gl000219 179198 + 19784 19836 chr1 247249719 - 212757024 212757076 9451024
+52
+
+chain 1204 chrUn_gl000219 179198 + 9400 9453 chr2 242951149 - 221538709 221538762 17248558
+53
+
+chain 1196 chrUn_gl000219 179198 + 65543 65596 chrX 154913754 - 74732188 74732241 11122165
+53
+
+chain 1136 chrUn_gl000219 179198 + 160693 160717 chr2 242951149 + 96004141 96004165 19597584
+24
+
+chain 1088 chrUn_gl000219 179198 + 19507 19558 chr9 140273252 + 124212712 124212763 4480835
+51
+
+chain 1079 chrUn_gl000219 179198 + 37482 37507 chr4 191273063 - 92702671 92702696 10491706
+25
+
+chain 1063 chrUn_gl000219 179198 + 6670 6734 chr3 199501827 + 6965033 6965097 10403549
+64
+
+chain 1052 chrUn_gl000219 179198 + 19721 19774 chr1 247249719 + 112545490 112545543 7413376
+53
+
+chain 1038 chrUn_gl000219 179198 + 160800 160824 chrX 154913754 + 84200659 84200683 17773754
+24
+
+chain 979 chrUn_gl000219 179198 + 67437 67498 chr12 132349534 + 127544420 127544481 8975114
+61
+
+chain 882 chrUn_gl000219 179198 + 68888 68940 chr2 242951149 + 41597257 41597309 8629613
+52
+
+chain 862 chrUn_gl000219 179198 + 34692 34749 chr7 158821424 + 91057493 91057550 3914497
+57
+
+chain 862 chrUn_gl000219 179198 + 19258 19321 chr17 78774742 + 11706793 11706856 10608405
+63
+
+chain 836 chrUn_gl000219 179198 + 6404 6488 chrX_random 1719168 - 557556 557640 15714908
+84
+
+chain 826 chrUn_gl000219 179198 + 6064 6121 chr4 191273063 + 114632432 114632489 6389008
+57
+
+chain 786 chrUn_gl000219 179198 + 19327 19383 chr4 191273063 + 95451114 95451170 8391346
+56
+
+chain 781 chrUn_gl000219 179198 + 66882 66938 chr15 100338915 + 35480475 35480531 9740616
+56
+
+chain 780 chrUn_gl000219 179198 + 5491 5548 chr19 63811651 + 45237769 45237826 8205599
+57
+
+chain 773 chrUn_gl000219 179198 + 18906 18956 chr5 180857866 - 161656026 161656076 5757214
+50
+
+chain 756 chrUn_gl000219 179198 + 5561 5620 chr8 146274826 - 76452822 76452881 8679584
+59
+
+chain 744 chrUn_gl000219 179198 + 8892 8945 chr18 76117153 + 27187323 27187376 6534410
+53
+
+chain 702 chrUn_gl000219 179198 + 67866 67921 chr11 134452384 - 45331858 45331913 4032419
+55
+
+chain 658 chrUn_gl000219 179198 + 65665 65726 chr11 134452384 - 71401302 71401363 8693276
+61
+
+chain 610 chrUn_gl000219 179198 + 68611 68641 chr6 170899992 - 104159480 104159510 6224934
+30
+
+chain 600 chrUn_gl000219 179198 + 34306 34379 chr9 140273252 + 67999140 67999213 8057147
+73
+
+chain 566 chrUn_gl000219 179198 + 68393 68455 chr13 114142980 + 104410587 104410649 8663433
+62
+
+chain 556 chrUn_gl000219 179198 + 66682 66718 chr4 191273063 - 23557773 23557809 3204114
+36
+
+chain 543 chrUn_gl000219 179198 + 66718 66743 chr4 191273063 + 67612053 67612078 7944900
+25
+
+chain 543 chrUn_gl000219 179198 + 8373 8450 chr1 247249719 - 76782344 76782421 23880934
+77
+
+chain 532 chrUn_gl000219 179198 + 6121 6161 chr13 114142980 - 84408205 84408245 7620044
+40
+
+chain 531 chrUn_gl000219 179198 + 66743 66797 chr3 199501827 - 142542844 142542898 11924432
+54
+
+chain 522 chrUn_gl000219 179198 + 7996 8024 chr12 132349534 + 73188186 73188214 12754595
+28
+
+chain 500 chrUn_gl000219 179198 + 67110 67168 chr5 180857866 + 134363242 134363300 15867098
+58
+
+chain 485 chrUn_gl000219 179198 + 69293 69355 chr1 247249719 + 99641891 99641953 7463394
+62
+
+chain 483 chrUn_gl000219 179198 + 66186 66217 chrX 154913754 - 138658729 138658760 7191935
+31
+
+chain 477 chrUn_gl000219 179198 + 19687 19721 chr7 158821424 + 45385787 45385821 16982489
+34
+
+chain 474 chrUn_gl000219 179198 + 8598 8650 chrX 154913754 - 113360025 113360077 16003052
+52
+
+chain 421 chrUn_gl000219 179198 + 65449 65511 chr1 247249719 + 187704570 187704632 12170451
+62
+
+chain 402 chrUn_gl000219 179198 + 8487 8537 chr8 146274826 - 79772642 79772692 15615542
+50
+
+chain 400 chrUn_gl000219 179198 + 67611 67640 chr1 247249719 - 149721975 149722004 3673241
+29
+
+chain 357 chrUn_gl000219 179198 + 8945 8990 chr3 199501827 - 164258935 164258980 15296887
+45
+
+chain 325 chrUn_gl000219 179198 + 66571 66608 chr6 170899992 - 28562683 28562720 10433787
+37
+
+chain 267 chrUn_gl000219 179198 + 66437 66493 chr8 146274826 + 91475861 91475917 20384527
+56
+
+chain 259 chrUn_gl000219 179198 + 68682 68710 chr11 134452384 - 28278838 28278866 23153636
+28
+
+chain 207038 chrUn_gl000220 161802 + 151486 153627 chr21_random 1679693 - 0 2145 573346
+1058	0	1
+394	0	4
+106	1	0
+582
+
+chain 207038 chrUn_gl000220 161802 + 107514 109655 chr21_random 1679693 - 0 2145 573347
+1058	0	1
+394	0	4
+106	1	0
+582
+
+chain 69503 chrUn_gl000220 161802 + 67389 69230 chr2 242951149 + 25799043 25800417 1810371
+218	1	1
+72	2	2
+113	1024	551
+85	19	19
+226	0	6
+81
+
+chain 31351 chrUn_gl000220 161802 + 117547 117875 chr1 247249719 - 155624021 155624349 4397311
+328
+
+chain 29427 chrUn_gl000220 161802 + 67361 68249 chr1 247249719 - 87588997 87589612 2331939
+28	406	406
+54	1	1
+64	273	0
+62
+
+chain 27049 chrUn_gl000220 161802 + 161519 161802 chr1 247249719 - 155624021 155624304 6035035
+283
+
+chain 25088 chrUn_gl000220 161802 + 36919 37185 chr1 247249719 - 45093231 45093497 6989949
+266
+
+chain 24729 chrUn_gl000220 161802 + 117030 117449 chrX 154913754 + 108184031 108184449 7237839
+197	142	141
+80
+
+chain 20499 chrUn_gl000220 161802 + 65633 66956 chr8 146274826 - 2314439 2315749 10054888
+157	1045	1032
+53	13	13
+55
+
+chain 20386 chrUn_gl000220 161802 + 75253 75471 chr11 134452384 + 26865999 26866217 10139728
+218
+
+chain 17914 chrUn_gl000220 161802 + 106337 107514 chr20 62435964 - 36297925 36299106 11745937
+55	875	884
+91	103	98
+53
+
+chain 17680 chrUn_gl000220 161802 + 84353 85836 chr15 100338915 + 87980076 87981560 12400789
+131	384	386
+57	861	860
+50
+
+chain 16118 chrUn_gl000220 161802 + 159904 160089 chr5 180857866 + 71182513 71182698 13920446
+124	8	8
+53
+
+chain 16118 chrUn_gl000220 161802 + 115932 116117 chr5 180857866 + 71182513 71182698 13920447
+124	8	8
+53
+
+chain 15578 chrUn_gl000220 161802 + 85289 85786 chr10 135374737 - 97997712 97998207 12517238
+97	354	352
+46
+
+chain 14161 chrUn_gl000220 161802 + 154326 154474 chr12 132349534 + 20595624 20595772 16008128
+148
+
+chain 14161 chrUn_gl000220 161802 + 110354 110502 chr12 132349534 + 20595624 20595772 16008129
+148
+
+chain 13476 chrUn_gl000220 161802 + 149534 149686 chr1 247249719 + 154452993 154453145 16852628
+91	5	5
+56
+
+chain 13476 chrUn_gl000220 161802 + 105562 105714 chr1 247249719 + 154452993 154453145 16852629
+91	5	5
+56
+
+chain 13074 chrUn_gl000220 161802 + 75664 75872 chr5 180857866 + 148307676 148307883 12475568
+65	80	79
+63
+
+chain 12291 chrUn_gl000220 161802 + 109957 110143 chr2 242951149 - 110221779 110221963 18542579
+61	44	42
+81
+
+chain 11141 chrUn_gl000220 161802 + 65790 65916 chr6 170899992 - 125538722 125538849 11778575
+19	0	1
+11	1	1
+95
+
+chain 11117 chrUn_gl000220 161802 + 113673 113902 chr11 134452384 + 84872723 84872926 20519201
+78	99	73
+52
+
+chain 10468 chrUn_gl000220 161802 + 30468 30675 chr1 247249719 + 43344900 43345108 21782937
+53	83	84
+71
+
+chain 10467 chrUn_gl000220 161802 + 122720 122828 chr16 88827254 - 74338770 74338878 21787089
+108
+
+chain 10454 chrUn_gl000220 161802 + 159242 159370 chr19 63811651 + 40758345 40758473 21809803
+64	8	8
+56
+
+chain 10022 chrUn_gl000220 161802 + 109687 109957 chr16 88827254 + 33870609 33870877 21321955
+66	160	158
+44
+
+chain 9617 chrUn_gl000220 161802 + 65083 65225 chr6 170899992 - 64517981 64518123 23713679
+59	28	28
+55
+
+chain 9067 chrUn_gl000220 161802 + 65995 66091 chr5 180857866 - 61890711 61890807 15044279
+96
+
+chain 8090 chrUn_gl000220 161802 + 66643 66751 chrX 154913754 + 93027353 93027460 18331310
+57	8	8
+30	1	0
+12
+
+chain 7895 chrUn_gl000220 161802 + 83808 83891 chr8 146274826 - 74499810 74499893 26574027
+83
+
+chain 7508 chrUn_gl000220 161802 + 130266 131540 chr16 88827254 + 33860661 33862774 27224265
+76	1140	1979
+58
+
+chain 6793 chrUn_gl000220 161802 + 85386 85459 chr4 191273063 - 132701421 132701494 16466620
+73
+
+chain 6622 chrUn_gl000220 161802 + 69230 69303 chr7 158821424 + 72850229 72850302 6119994
+73
+
+chain 6240 chrUn_gl000220 161802 + 117008 117283 chr8 146274826 - 75509656 75509931 8997966
+22	197	197
+56
+
+chain 6018 chrUn_gl000220 161802 + 66770 66835 chr7 158821424 + 124008505 124008570 12829512
+65
+
+chain 5720 chrUn_gl000220 161802 + 75185 75250 chr19 63811651 + 15679634 15679699 12473683
+65
+
+chain 4703 chrUn_gl000220 161802 + 23204 23254 chr5 180857866 + 95719433 95719483 34557350
+50
+
+chain 4701 chrUn_gl000220 161802 + 84689 84759 chr7 158821424 - 101943693 101943763 18053161
+10	42	42
+18
+
+chain 4653 chrUn_gl000220 161802 + 75476 75531 chr2 242951149 + 164831342 164831397 18833276
+55
+
+chain 4071 chrUn_gl000220 161802 + 75577 75664 chr7 158821424 + 127724988 127725075 11086017
+87
+
+chain 3907 chrUn_gl000220 161802 + 84699 84740 chr8 146274826 - 59752347 59752388 23243247
+41
+
+chain 3445 chrUn_gl000220 161802 + 84526 84576 chr7 158821424 - 54802302 54802352 16133139
+50
+
+chain 3298 chrUn_gl000220 161802 + 84484 84519 chr4 191273063 + 150269733 150269768 14985224
+35
+
+chain 3145 chrUn_gl000220 161802 + 68319 68372 chr3 199501827 - 131923719 131923772 22478960
+53
+
+chain 2432 chrUn_gl000220 161802 + 68042 68092 chrX 154913754 - 83094892 83094942 21808406
+50
+
+chain 2258 chrUn_gl000220 161802 + 85510 85565 chr1 247249719 - 82513050 82513105 16301029
+55
+
+chain 1955 chrUn_gl000220 161802 + 67950 68004 chr10 135374737 - 36348792 36348846 20124747
+54
+
+chain 1529 chrUn_gl000220 161802 + 84950 85016 chr15 100338915 + 47627030 47627096 15111622
+66
+
+chain 994 chrUn_gl000220 161802 + 68645 68697 chr6 170899992 - 81185693 81185745 23384366
+52
+
+chain 895 chrUn_gl000220 161802 + 75776 75809 chrX 154913754 - 34420755 34420788 14557377
+33
+
+chain 866 chrUn_gl000220 161802 + 65932 65995 chr12 132349534 - 68316854 68316917 13749883
+63
+
+chain 724 chrUn_gl000220 161802 + 83556 83614 chrX 154913754 - 81676829 81676887 19557019
+58
+
+chain 624 chrUn_gl000220 161802 + 83438 83493 chr11 134452384 + 91542956 91543011 19738951
+55
+
+chain 591 chrUn_gl000220 161802 + 84637 84689 chr12 132349534 - 49421504 49421556 13261533
+52
+
+chain 561 chrUn_gl000220 161802 + 84759 84817 chr6_random 1875562 - 1459651 1459709 15884202
+58
+
+chain 14216718 chrUn_gl000221 155397 + 0 155355 chr1 247249719 + 141752984 141907993 211
+623	1	1
+49	1	1
+619	1	1
+34	1	1
+307	1	1
+31	1	1
+1912	1	1
+41	1	1
+994	1	1
+23	1	1
+1203	0	1
+1157	57	60
+181	1	1
+26	1	1
+643	1	2
+61	1	1
+43	1	1
+300	6	6
+241	11	11
+1194	8	8
+173	1	1
+31	1	1
+1099	13	13
+321	0	3
+456	23	24
+402	1	1
+28	1	1
+533	0	3
+476	2	0
+870	1	1
+47	1	1
+1339	4	4
+25	1	1
+474	0	1
+869	34	34
+615	1	1
+18	1	1
+1449	1	1
+47	1	1
+60	11	11
+465	8	8
+54	6	0
+164	11	11
+546	15	15
+172	1	0
+1686	0	1
+987	1	1
+38	1	1
+2146	1	1
+29	1	1
+645	1	1
+19	1	1
+804	10	10
+2676	0	1
+430	1	1
+48	1	1
+1099	1	1
+39	1	1
+127	0	1
+450	0	1
+22	1	1
+1754	1	1
+38	1	1
+152	3	0
+1066	1	1
+41	1	1
+3598	1	1
+17	1	1
+363	4	4
+63	504	9
+154	1	1
+15	1	1
+574	1	1
+43	1	1
+515	1	1
+31	1	1
+99	0	8
+378	1	1
+25	1	1
+477	1	1
+19	1	1
+466	1	1
+70	5	5
+79	1	1
+108	1	1
+210	1	1
+156	1	1
+265	7	7
+64	1	1
+98	1	1
+114	1	1
+39	1	1
+363	5	5
+28	1	1
+2637	1	1
+35	1	1
+702	1	1
+15	1	1
+122	30	30
+60	20	19
+194	1	1
+44	1	1
+1196	4	3
+141	1	1
+49	1	1
+274	2	0
+235	3	0
+152	9	9
+258	1	1
+34	1	0
+45	1	1
+370	1	1
+27	1	1
+235	10	0
+378	1	1
+17	1	0
+4	7	4
+437	15	16
+291	12	12
+101	1	1
+29	0	1
+219	0	1
+90	0	1
+164	1	1
+35	1	0
+916	1	1
+44	1	1
+54	29	25
+111	1	1
+31	1	1
+199	2	0
+360	2	0
+533	7	7
+281	14	14
+1751	1	1
+16	1	1
+136	1	0
+513	1	0
+216	2	0
+694	1	1
+30	1	1
+136	1	1
+34	1	1
+640	1	0
+17	1	0
+910	5	5
+36	4	4
+1047	1	1
+91	1	1
+1268	1	1
+49	4	4
+2141	1	1
+78	1	1
+309	1	1
+19	1	1
+116	1	1
+51	1	1
+282	4	4
+626	14	14
+2635	2	2
+37	1	1
+1324	1	1
+111	1	1
+332	1	1
+40	1	1
+1585	0	1
+1044	0	1
+456	1	1
+56	1	1
+733	0	37
+398	1	1
+24	1	1
+941	0	1
+533	1	1
+46	1	1
+425	1	1
+29	1	1
+209	1	1
+656	14	14
+2193	0	1
+340	0	1
+1318	1	1
+29	1	1
+734	13	0
+736	2	0
+395	0	1
+543	1	0
+449	2	0
+2005	1	1
+29	1	1
+748	0	1
+1298	1	1
+18	1	1
+1823	1	1
+26	1	1
+735	16	16
+1067	1	1
+20	1	1
+205	1	1
+36	1	1
+1358	0	1
+938	1	1
+87	1	1
+1100	1	1
+30	1	0
+2470	0	16
+317	10	0
+1289	5	5
+78	1	1
+1424	0	2
+656	2	2
+32	2	1
+223	0	1
+71	1	1
+289	1	0
+15	1	1
+104	1	1
+147	0	2
+15	1	1
+187	1	1
+50	1	1
+56	1	1
+31	3	3
+103	1	1
+130	1	1
+58	10	76
+99	3	3
+352	1	1
+72	1	1
+49	1	1
+105	1	1
+71	2	2
+120	1	1
+152	1	1
+87	15	84
+27	1	0
+5	1	1
+779	1	1
+42	1	1
+351	1	1
+45	1	1
+74	1	1
+46	1	1
+583	9	9
+3745	27	27
+500	0	2
+56	8	0
+105	4	4
+54	3	3
+39	1	1
+111	5	5
+2408	0	3
+1986	0	1
+4003	1	1
+38	1	1
+2084	1	1
+88	1	1
+1007	10	0
+1048	0	1
+180	6	6
+1628	0	1
+1953	1	0
+1428	1	1
+44	1	1
+475	11	11
+551	0	3
+702	2	1
+137	0	6
+829	6	6
+1463	1	1
+30	1	1
+155	1	1
+23	1	1
+1026	7	7
+987	1	1
+48	1	1
+94	1	1
+45	1	1
+706	1	1
+28	1	1
+1055	1	1
+26	1	1
+71	1	1
+53	1	1
+2245	1	1
+22	1	1
+328	1	1
+16	1	1
+1264	1	1
+33	1	1
+247	0	1
+2369	11	11
+105	11	11
+665	0	1
+27	1	1
+379	4	0
+1936	4	3
+441	1	1
+28	1	1
+736	0	5
+248	1	1
+55	1	1
+853	1	0
+415	1	1
+63	2	0
+7	1	2
+49	1	1
+324	1	1
+25	1	1
+2107	0	4
+431	9	9
+204	1	1
+25	1	1
+93	1	1
+46	1	1
+425	1	0
+321	12	12
+266
+
+chain 55879 chrUn_gl000221 155397 + 39022 155397 chr21_random 1679693 - 1044434 1160777 269
+504	7942	7889
+30	63609	63627
+27	44221	44224
+42
+
+chain 7421 chrUn_gl000221 155397 + 7003 17005 chr1 247249719 + 142211716 142221729 942
+52	9916	9927
+34
+
+chain 17470138 chrUn_gl000222 186861 + 0 186861 chr3 199501827 - 123616420 123803195 161
+1250	0	4
+3271	1	1
+48	1	1
+748	1	1
+29	1	1
+336	0	1
+397	14	15
+315	1	1
+47	1	1
+76	1	1
+49	1	1
+1417	5	0
+399	2	1
+112	1	1
+20	1	1
+667	0	3
+1357	1	1
+24	1	1
+409	1	0
+9	1	1
+173	0	1
+36	1	1
+1372	1	0
+369	9	10
+484	0	4
+411	21	25
+242	1	0
+833	14	14
+895	0	9
+1067	0	3
+87	1	1
+33	1	1
+52	1	1
+35	1	1
+564	3	2
+80	9	9
+77	3	0
+126	120	0
+626	1	1
+84	0	5
+30	1	1
+337	0	8
+384	1	1
+30	0	1
+153	0	1
+16	1	1
+52	6	0
+185	1	2
+111	4	4
+54	1	1
+29	1	1
+479	1	0
+23	1	1
+1089	1	1
+21	1	1
+194	1	1
+20	1	0
+1217	0	1
+728	1	0
+497	120	0
+130	1	1
+45	1	1
+364	0	3
+2459	4	4
+883	5	4
+785	14	14
+1180	5	0
+420	1	1
+39	0	4
+13	1	1
+60	16	16
+592	11	14
+246	0	1
+520	1	1
+19	1	1
+843	1	1
+33	1	1
+462	0	9
+24	1	1
+661	3	0
+22	1	1
+1102	6	6
+2016	1	0
+106	1	1
+40	0	1
+2177	1	1
+39	1	1
+806	0	4
+412	1	0
+317	0	2
+775	0	4
+289	1	1
+22	1	1
+920	1	1
+72	0	5
+58	1	1
+345	1	1
+22	1	1
+302	2	2
+84	1	1
+210	8	8
+98	3	1
+673	1	1
+33	1	1
+299	4	0
+1477	4	4
+475	1	1
+46	1	1
+369	13	13
+60	1	1
+37	1	1
+260	1	0
+274	6	0
+1598	1	1
+28	1	1
+2138	16	16
+793	1	0
+142	1	1
+18	1	0
+1920	0	1
+164	6	0
+859	1	1
+49	1	0
+333	2	0
+1437	1	1
+32	1	1
+243	4	5
+719	0	1
+39	1	1
+861	1	1
+41	1	1
+812	1	1
+46	9	8
+145	1	1
+50	1	1
+552	2	2
+27	0	3
+477	1	1
+41	1	1
+307	1	1
+67	1	1
+283	1	1
+27	1	1
+151	0	1
+21	1	1
+128	1	0
+42	1	1
+415	0	110
+781	2	2
+44	1	1
+176	2	2
+21	1	1
+181	4	0
+440	47	47
+326	1	1
+27	1	1
+228	1	1
+36	1	1
+138	12	12
+3038	11	11
+3781	0	1
+1856	0	58
+1813	1	0
+3776	21	0
+1096	8	0
+9578	0	4
+924	0	1
+662	1	0
+942	1	0
+1709	8	8
+167	1	0
+6850	0	6
+58	1	1
+5315	1	1
+22	1	1
+2377	1	0
+3702	1	1
+17	1	1
+1405	1	0
+38	3	0
+10654	0	1
+35	1	1
+3464	0	1
+424	12	12
+6848	13	13
+444	0	5
+1121	0	10
+3015	11	10
+5936	1	1
+45	1	1
+134	1	1
+33	1	1
+913	1	1
+33	1	1
+7377	1	1
+26	1	1
+2213	3	0
+1310	19	16
+1028	1	1
+30	1	1
+1346	0	1
+3453	23	23
+2511	0	2
+2170	1	0
+5294	16	17
+1031	0	1
+5779	30	0
+4540
+
+chain 4695 chrUn_gl000222 186861 + 24563 24635 chr3 199501827 - 123640889 123640961 14387967
+72
+
+chain 1361 chrUn_gl000222 186861 + 182291 182321 chr3 199501827 - 123798570 123798600 19416990
+30
+
+chain 17090000 chrUn_gl000223 180455 + 8 180455 chr12 132349534 - 156807 337156 167
+1699	1	0
+921	0	1
+476	0	3
+2781	5	0
+2337	0	4
+2044	1	1
+52	1	1
+99	4	0
+3342	10	10
+76207	0	1
+61652	112	0
+5333	2	15
+2060	0	1
+6964	2	2
+29	1	1
+4046	1	1
+74	0	2
+1140	1	1
+45	1	0
+610	2	0
+5062	1	0
+917	0	3
+2412
+
+chain 149624 chrUn_gl000224 179693 + 16452 19204 chr21_random 1679693 - 927993 930745 862809
+59	44	44
+122	26	26
+66	78	78
+132	53	53
+52	89	89
+402	80	80
+70	427	427
+293	109	109
+159	56	56
+159	73	73
+203
+
+chain 136876 chrUn_gl000224 179693 + 10143 12844 chr21_random 1679693 - 927993 930694 942020
+59	44	44
+122	243	243
+59	53	53
+52	89	89
+402	291	291
+56	138	138
+69	23	23
+293	109	109
+159	56	56
+159	73	73
+152
+
+chain 125386 chrUn_gl000224 179693 + 4608 7033 chr4 191273063 - 142060444 142063015 1025800
+181	62	62
+67	290	436
+77	128	128
+226	170	170
+58	50	50
+165	20	20
+83	29	29
+137	31	31
+189	59	59
+173	72	72
+64	43	43
+51
+
+chain 115319 chrUn_gl000224 179693 + 12844 15391 chr1 247249719 - 105124090 105126655 1054758
+4	101	101
+115	120	120
+83	6	6
+88	7	7
+90	138	143
+213	56	56
+54	27	27
+110	76	76
+135	22	22
+85	408	408
+51	98	112
+51	71	70
+151	97	97
+90
+
+chain 114018 chrUn_gl000224 179693 + 0 2892 chr4 191273063 - 142260101 142263001 1123540
+55	9	9
+211	93	93
+53	8	8
+62	480	490
+69	30	30
+169	1	0
+59	374	374
+170	104	104
+66	127	127
+67	134	134
+53	28	28
+127	117	117
+109	4	4
+55	1	0
+57
+
+chain 36836 chrUn_gl000224 179693 + 6824 7667 chr1 247249719 - 105124398 105125248 1790194
+51	165	165
+90	136	143
+213	56	56
+54	27	27
+51
+
+chain 33992 chrUn_gl000224 179693 + 112940 113352 chrX 154913754 - 88823320 88823732 3977820
+120	1	1
+31	1	1
+187	19	19
+53
+
+chain 18992 chrUn_gl000224 179693 + 17725 19327 chr4 191273063 - 142245973 142247284 981259
+45	153	153
+54	736	445
+17	9	9
+9	181	181
+60	269	269
+69
+
+chain 18703 chrUn_gl000224 179693 + 36684 37079 chr4 191273063 - 141982606 141983001 11515138
+60	182	182
+153
+
+chain 18089 chrUn_gl000224 179693 + 111527 111723 chr9 140273252 - 128738409 128738605 12039465
+196
+
+chain 15842 chrUn_gl000224 179693 + 43681 43852 chr5 180857866 + 121997129 121997300 14188216
+171
+
+chain 14214 chrUn_gl000224 179693 + 491 737 chr4 191273063 - 142062769 142063015 3040816
+16	72	72
+64	43	43
+51
+
+chain 12738 chrUn_gl000224 179693 + 10425 11345 chr1 247249719 + 142120275 142121196 1008989
+81	89	89
+16	667	668
+67
+
+chain 12408 chrUn_gl000224 179693 + 111770 111902 chr13 114142980 + 92814175 92814307 18368674
+132
+
+chain 11212 chrUn_gl000224 179693 + 19478 19617 chr21_random 1679693 + 1399634 1399773 20347362
+79	8	8
+52
+
+chain 11202 chrUn_gl000224 179693 + 112010 112131 chr2 242951149 - 63390730 63390851 20364580
+121
+
+chain 10961 chrUn_gl000224 179693 + 113403 113519 chr15 100338915 + 33416357 33416473 20796127
+116
+
+chain 10599 chrUn_gl000224 179693 + 45499 45614 chr4 191273063 - 16476018 16476133 21505928
+115
+
+chain 10461 chrUn_gl000224 179693 + 5286 5406 chr4 191273063 - 142252631 142253042 21797237
+48	0	291
+72
+
+chain 9625 chrUn_gl000224 179693 + 45086 45377 chr7 158821424 + 147179139 147179431 23689916
+56	173	174
+62
+
+chain 8966 chrUn_gl000224 179693 + 43852 44339 chr6 170899992 - 123605243 123606037 22200679
+5	424	731
+58
+
+chain 8686 chrUn_gl000224 179693 + 150637 150728 chr17_random 2617613 - 2481086 2481177 25413154
+91
+
+chain 8418 chrUn_gl000224 179693 + 113901 114092 chr1 247249719 + 51102379 51102577 12937085
+62	97	104
+32
+
+chain 7836 chrUn_gl000224 179693 + 113729 114060 chr15 100338915 + 29700006 29700343 12648008
+52	182	188
+97
+
+chain 7180 chrUn_gl000224 179693 + 111450 111527 chr20 62435964 + 7228195 7228272 16795381
+77
+
+chain 6302 chrUn_gl000224 179693 + 16769 18129 chr1 247249719 + 142120310 142121524 963429
+46	1235	1089
+79
+
+chain 6103 chrUn_gl000224 179693 + 42952 43016 chr3 199501827 - 123620077 123620141 30294157
+64
+
+chain 5895 chrUn_gl000224 179693 + 2013 2591 chr1 247249719 - 105125890 105126468 2699632
+97	439	439
+42
+
+chain 5875 chrUn_gl000224 179693 + 112823 112897 chr5 180857866 + 101476275 101476349 19139195
+74
+
+chain 5761 chrUn_gl000224 179693 + 112501 112575 chr5 180857866 - 18785409 18785483 18767594
+74
+
+chain 5594 chrUn_gl000224 179693 + 14410 14469 chr2 242951149 + 132757818 132757877 31664825
+59
+
+chain 5426 chrUn_gl000224 179693 + 112319 112377 chrX 154913754 + 51601613 51601671 20663092
+58
+
+chain 5157 chrUn_gl000224 179693 + 36781 36835 chr3 199501827 - 123619604 123619658 33003364
+54
+
+chain 4848 chrUn_gl000224 179693 + 38244 38295 chr17_random 2617613 - 2478551 2478602 33999646
+51
+
+chain 4029 chrUn_gl000224 179693 + 112591 112679 chr5 180857866 + 175637665 175637753 5293308
+88
+
+chain 3738 chrUn_gl000224 179693 + 13809 15505 chr21_random 1679693 + 746889 748597 1305848
+56	1588	1600
+52
+
+chain 3444 chrUn_gl000224 179693 + 17845 17922 chr4 191273063 - 142061190 142061267 1001031
+77
+
+chain 2897 chrUn_gl000224 179693 + 17977 18049 chr4 191273063 - 142253123 142253195 6314050
+72
+
+chain 2788 chrUn_gl000224 179693 + 7479 7535 chr21_random 1679693 + 746889 746945 1938894
+56
+
+chain 2567 chrUn_gl000224 179693 + 112204 112294 chr11 134452384 - 41661604 41661694 17596092
+90
+
+chain 2514 chrUn_gl000224 179693 + 112910 112940 chr7 158821424 - 149074801 149074831 4457011
+30
+
+chain 2362 chrUn_gl000224 179693 + 112294 112319 chr6 170899992 + 161846864 161846889 20635445
+25
+
+chain 2067 chrUn_gl000224 179693 + 113791 113854 chr10 135374737 - 12705669 12705732 4536722
+63
+
+chain 2066 chrUn_gl000224 179693 + 12137 18504 chr4 191273063 + 48989335 49001828 975845
+58	6251	12377
+58
+
+chain 1330 chrUn_gl000224 179693 + 113854 113878 chr5 180857866 - 104048317 104048341 15104584
+24
+
+chain 1281 chrUn_gl000224 179693 + 13065 13119 chr2 242951149 + 132762412 132762466 24130660
+54
+
+chain 1137 chrUn_gl000224 179693 + 4993 5088 chr21_random 1679693 - 929171 929266 9927235
+95
+
+chain 848 chrUn_gl000224 179693 + 1580 1641 chr19 63811651 - 14200495 14200556 15170632
+61
+
+chain 531 chrUn_gl000224 179693 + 111324 111398 chrX 154913754 + 45796753 45796827 23841494
+74
+
+chain 30238 chrUn_gl000225 211173 + 3384 6975 chr18 76117153 - 76016439 76019286 4615508
+88	182	182
+34	2463	1785
+83	385	319
+50	111	111
+195
+
+chain 23455 chrUn_gl000225 211173 + 60973 61217 chr12 132349534 - 101518303 101518547 8018503
+244
+
+chain 20111 chrUn_gl000225 211173 + 166962 167202 chrY 57772954 - 350039 350279 10363809
+137	15	15
+88
+
+chain 18512 chrUn_gl000225 211173 + 25429 25744 chrY 57772954 - 45830615 45830930 11677619
+72	105	105
+138
+
+chain 17348 chrUn_gl000225 211173 + 69995 70696 chr18 76117153 + 100273 101110 12705104
+54	377	445
+95	106	174
+69
+
+chain 16827 chrUn_gl000225 211173 + 145466 146389 chr12 132349534 - 82104353 82105276 13209656
+90	95	95
+78	609	609
+51
+
+chain 16532 chrUn_gl000225 211173 + 6975 7480 chrY 57772954 + 11929182 11929688 9693145
+6	195	195
+56	193	194
+55
+
+chain 14751 chrUn_gl000225 211173 + 146689 146847 chr12 132349534 + 39722955 39723113 15337789
+158
+
+chain 14284 chrUn_gl000225 211173 + 109330 111760 chrY 57772954 + 11933408 11933865 15870073
+76	260	260
+66	1973	0
+55
+
+chain 14255 chrUn_gl000225 211173 + 98785 99342 chr18 76117153 + 100216 100772 15900410
+38	387	386
+132
+
+chain 13725 chrUn_gl000225 211173 + 126918 127062 chr18 76117153 + 100627 100771 16530918
+144
+
+chain 13602 chrUn_gl000225 211173 + 147672 147817 chr8 146274826 + 107672556 107672701 16687743
+145
+
+chain 12515 chrUn_gl000225 211173 + 44909 48118 chrY 57772954 + 11932705 11933485 18215669
+61	2725	295
+67	280	281
+76
+
+chain 11840 chrUn_gl000225 211173 + 21194 21753 chrY 57772954 - 366515 367006 19262147
+78	414	346
+67
+
+chain 11658 chrUn_gl000225 211173 + 205576 205759 chr2 242951149 - 95682635 95682818 19568742
+65	47	47
+71
+
+chain 11142 chrUn_gl000225 211173 + 75498 75615 chrY 57772954 - 45851825 45851942 20475254
+117
+
+chain 10869 chrUn_gl000225 211173 + 51801 51915 chr18 76117153 - 76020289 76020403 20977270
+114
+
+chain 10758 chrUn_gl000225 211173 + 209713 209913 chr4 191273063 + 39081959 39082160 21190890
+74	74	75
+52
+
+chain 10616 chrUn_gl000225 211173 + 146389 146556 chr5 180857866 - 159454687 159454854 16369709
+43	58	58
+66
+
+chain 10035 chrUn_gl000225 211173 + 171673 171813 chr8 146274826 - 67038436 67038576 22726539
+51	22	22
+67
+
+chain 9917 chrUn_gl000225 211173 + 144822 145109 chr5 180857866 + 8336803 8337089 22999312
+67	165	164
+55
+
+chain 9896 chrUn_gl000225 211173 + 62060 62164 chr18 76117153 + 100627 100731 23055661
+104
+
+chain 9807 chrUn_gl000225 211173 + 137863 140640 chrY 57772954 - 45826954 45827260 23254439
+47	2048	0
+54	576	153
+52
+
+chain 8932 chrUn_gl000225 211173 + 69636 69730 chrY 57772954 - 45829605 45829699 25046033
+94
+
+chain 8413 chrUn_gl000225 211173 + 85100 85188 chrY 57772954 - 45832076 45832164 25801593
+88
+
+chain 8359 chrUn_gl000225 211173 + 142638 142726 chrY 57772954 + 57394412 57394500 25874101
+88
+
+chain 8122 chrUn_gl000225 211173 + 119411 119496 chr18 76117153 + 100254 100339 26237196
+85
+
+chain 8086 chrUn_gl000225 211173 + 55593 55678 chr18 76117153 - 76016415 76016500 26288572
+85
+
+chain 7431 chrUn_gl000225 211173 + 23911 23989 chrY 57772954 - 45832097 45832175 27364689
+78
+
+chain 7085 chrUn_gl000225 211173 + 97023 98440 chrY 57772954 - 45830811 45832294 28041027
+71	1296	1362
+50
+
+chain 7083 chrUn_gl000225 211173 + 18039 19438 chrY 57772954 - 366566 367008 28041757
+40	1295	338
+64
+
+chain 6978 chrUn_gl000225 211173 + 146217 146291 chr8 146274826 - 115673008 115673082 20162064
+74
+
+chain 6840 chrUn_gl000225 211173 + 144371 144443 chr18 76117153 + 100407 100479 28513456
+72
+
+chain 6667 chrUn_gl000225 211173 + 66486 66556 chrY 57772954 - 45828773 45828843 28907810
+70
+
+chain 6303 chrUn_gl000225 211173 + 137 203 chrY 57772954 - 45847922 45847988 29790939
+66
+
+chain 6276 chrUn_gl000225 211173 + 106597 106663 chr18 76117153 - 76016724 76016790 29833436
+66
+
+chain 6212 chrUn_gl000225 211173 + 69391 69456 chrY 57772954 - 45832092 45832157 30018585
+65
+
+chain 6148 chrUn_gl000225 211173 + 11132 11196 chrY 57772954 + 11939704 11939768 30172463
+64
+
+chain 6094 chrUn_gl000225 211173 + 68190 68254 chrY 57772954 + 57406356 57406420 30311205
+64
+
+chain 6058 chrUn_gl000225 211173 + 127450 127514 chrY 57772954 - 45844945 45845009 30402909
+64
+
+chain 6003 chrUn_gl000225 211173 + 143303 143366 chrY 57772954 + 57402115 57402178 30561429
+63
+
+chain 5903 chrUn_gl000225 211173 + 139264 139326 chrY 57772954 - 45844705 45844767 30818028
+62
+
+chain 5884 chrUn_gl000225 211173 + 104096 104157 chr18 76117153 + 102216 102277 30859822
+61
+
+chain 5803 chrUn_gl000225 211173 + 103301 103362 chr18 76117153 + 99316 99377 31083648
+61
+
+chain 5794 chrUn_gl000225 211173 + 26451 26512 chrY 57772954 - 45851626 45851687 31099284
+61
+
+chain 5721 chrUn_gl000225 211173 + 139049 139109 chrY 57772954 + 57400659 57400719 31317119
+60
+
+chain 5684 chrUn_gl000225 211173 + 146628 146689 chr1 247249719 - 54812307 54812368 16334743
+61
+
+chain 5630 chrUn_gl000225 211173 + 92437 92496 chr18 76117153 + 98445 98504 31574579
+59
+
+chain 5539 chrUn_gl000225 211173 + 140791 140849 chrY 57772954 + 57392905 57392963 31849395
+58
+
+chain 5539 chrUn_gl000225 211173 + 4266 4324 chrY 57772954 + 11928245 11928303 31849396
+58
+
+chain 5521 chrUn_gl000225 211173 + 40432 40490 chrY 57772954 - 370968 371026 31891738
+58
+
+chain 5438 chrUn_gl000225 211173 + 36214 36270 chrY 57772954 + 11930450 11930506 32145366
+56
+
+chain 5339 chrUn_gl000225 211173 + 74478 74534 chrY 57772954 - 45832726 45832782 32420219
+56
+
+chain 5339 chrUn_gl000225 211173 + 28866 28922 chrY 57772954 - 45832726 45832782 32420220
+56
+
+chain 5321 chrUn_gl000225 211173 + 77215 77271 chrY 57772954 - 45830350 45830406 32462996
+56
+
+chain 5248 chrUn_gl000225 211173 + 101556 101611 chrY 57772954 - 45844698 45844753 32703748
+55
+
+chain 5182 chrUn_gl000225 211173 + 145986 146041 chr9 140273252 + 120936021 120936076 15500236
+55
+
+chain 5139 chrUn_gl000225 211173 + 133143 133197 chrY 57772954 - 45844651 45844705 33042666
+54
+
+chain 5074 chrUn_gl000225 211173 + 44289 44341 chr18 76117153 - 76014945 76014997 33275500
+52
+
+chain 5048 chrUn_gl000225 211173 + 121427 121480 chrY 57772954 - 45831892 45831945 33345462
+53
+
+chain 5048 chrUn_gl000225 211173 + 133955 134008 chr18 76117153 + 100319 100372 33345768
+53
+
+chain 4966 chrUn_gl000225 211173 + 41802 41854 chr18 76117153 - 76019839 76019891 33630431
+52
+
+chain 4957 chrUn_gl000225 211173 + 75225 75277 chrY 57772954 + 57406623 57406675 33650989
+52
+
+chain 4953 chrUn_gl000225 211173 + 145598 145651 chr12 132349534 + 53460575 53460628 18762227
+53
+
+chain 4857 chrUn_gl000225 211173 + 102498 102549 chrY 57772954 - 45844483 45844534 33969906
+51
+
+chain 4802 chrUn_gl000225 211173 + 22297 22347 chr18 76117153 - 76019708 76019758 34221217
+50
+
+chain 4766 chrUn_gl000225 211173 + 81781 81831 chrY 57772954 - 45844484 45844534 34318861
+50
+
+chain 4730 chrUn_gl000225 211173 + 116183 116233 chrY 57772954 - 45830882 45830932 34441464
+50
+
+chain 4684 chrUn_gl000225 211173 + 16126 16175 chr18 76117153 - 76016743 76016792 34599346
+49
+
+chain 4593 chrUn_gl000225 211173 + 106022 106070 chrY 57772954 + 11933099 11933147 34665488
+48
+
+chain 4475 chrUn_gl000225 211173 + 6365 6412 chrY 57772954 - 366519 366566 34731069
+47
+
+chain 4436 chrUn_gl000225 211173 + 146291 146338 chr11 134452384 + 56488704 56488751 17449786
+47
+
+chain 3836 chrUn_gl000225 211173 + 145834 145884 chr5 180857866 + 144814068 144814118 22871561
+50
+
+chain 3811 chrUn_gl000225 211173 + 55287 55327 chrY 57772954 + 11933059 11933099 35041388
+40
+
+chain 3584 chrUn_gl000225 211173 + 145220 145258 chrX 154913754 - 118330483 118330521 21778509
+38
+
+chain 3107 chrUn_gl000225 211173 + 145429 145466 chr16 88827254 + 32289765 32289802 21377803
+37
+
+chain 3086 chrUn_gl000225 211173 + 145167 145986 chr10 135374737 + 122669077 122669897 13514114
+53	666	667
+100
+
+chain 2556 chrUn_gl000225 211173 + 117483 117510 chrY 57772954 - 45844918 45844945 35420092
+27
+
+chain 2529 chrUn_gl000225 211173 + 147645 147672 chr9 140273252 + 21053713 21053740 22333825
+27
+
+chain 2173 chrUn_gl000225 211173 + 146432 146455 chrX 154913754 - 151862289 151862312 20635516
+23
+
+chain 1176 chrUn_gl000225 211173 + 24983 25041 chrY 57772954 + 57406385 57406443 21696161
+58
+
+chain 970 chrUn_gl000225 211173 + 65774 66239 chr10 135374737 - 23380 24256 23288653
+57	372	783
+36
+
+chain 296 chrUn_gl000225 211173 + 124568 124644 chr18 76117153 + 100627 100703 23494333
+76
+
+chain 11961323 chrUn_gl000227 128374 + 0 128374 chr6 170899992 + 19668 147274 264
+1643	0	1
+255	1	1
+40	1	0
+61	4	4
+343	1	1
+168	1	1
+211	1	1
+18	1	1
+525	0	4
+549	1	1
+22	1	1
+440	16	16
+122	14	17
+167	4	4
+205	4	0
+98	1	1
+164	8	9
+585	0	1
+1278	1	1
+26	1	1
+2038	1	1
+17	1	1
+1741	15	15
+917	1	1
+26	1	1
+1021	0	1
+1314	77	0
+306	0	1
+109	0	153
+152	79	2
+199	153	0
+146	1	1
+49	1	1
+144	385	0
+4558	1	0
+5544	4	3
+2373	1	1
+40	1	0
+14638	6	0
+5386	0	1
+1491	2	0
+1835	20	20
+1481	0	4
+5348	0	1
+135	0	2
+2128	35	35
+4707	0	1
+1696	0	1
+893	1	1
+47	1	1
+766	1	1
+49	1	1
+542	1	1
+28	2	0
+334	1	1
+31	1	1
+1092	0	1
+803	1	0
+1815	6	0
+25	134	0
+37	79	0
+7668	1	0
+603	1	1
+28	1	1
+1020	0	1
+3033	0	2
+619	7	7
+1434	1	0
+1954	1	0
+9909	1	0
+1155	1	1
+36	1	1
+327	7	7
+133	4	0
+1499	0	2
+96	1	0
+3257	11	0
+46	1	1
+207	1	1
+20	1	1
+2919	18	18
+765	4	4
+1829	0	1
+1864	5	5
+123	15	15
+13751
+
+chain 49410 chrUn_gl000227 128374 + 14106 15875 chr8 146274826 + 86449 88144 529
+45	569	417
+43	288	289
+64	1	1
+12	362	363
+150	18	18
+153	1	77
+63
+
+chain 13413 chrUn_gl000227 128374 + 14996 15149 chr19 63811651 + 91181 91257 491
+55	77	0
+21
+
+chain 5337 chrUn_gl000227 128374 + 73853 73996 chr1 247249719 + 231 416 19004415
+27	66	108
+50
+
+chain 5015 chrUn_gl000227 128374 + 14074 14797 chr1 247249719 - 246873620 246874345 559
+32	658	660
+33
+
+chain 2271 chrUn_gl000227 128374 + 73917 73946 chr15 100338915 - 29 58 23118832
+29
+
+chain 8904085 chrUn_gl000228 129120 + 0 98333 chr4 191273063 + 191152836 191248399 371
+1288	1	1
+65	1	1
+695	1	1
+24	1	0
+6	1	1
+50	0	312
+260	1	1
+46	1	1
+993	1	0
+2168	1	1
+31	1	1
+3958	0	4
+257	0	18
+9	1	1
+267	3	3
+16	1	1
+1441	0	4
+68	0	1
+1387	0	2
+3469	11	11
+3245	1	0
+777	1	1
+25	1	1
+597	2	0
+30	1	1
+1792	1	1
+34	1	1
+543	0	1
+98	1	1
+25	1	1
+1024	8	0
+2103	1	1
+1898	0	12
+71	10	11
+1335	0	2
+7908	172	0
+4213	0	1
+4548	43	43
+334	0	1
+381	3	3
+46	1	1
+1201	1	1
+25	0	2
+1296	0	1
+526	4	0
+459	1	1
+56	1	1
+2023	2	2
+35	1	1
+1479	0	142
+2019	0	1
+370	8	8
+1586	1	0
+337	0	1
+921	2	0
+84	1	1
+22	1	0
+8	1	2
+206	0	4
+799	1	1
+18	0	1
+223	0	1
+295	1	70
+43	0	1
+72	68	0
+41	1	1
+90	4	4
+1051	1	1
+32	1	1
+182	7	7
+225	3	3
+22	1	1
+1660	0	1
+357	8	8
+101	13	13
+198	7	7
+412	1	0
+4	0	1
+19	1	0
+137	6	7
+361	0	2
+1716	1	0
+511	0	1
+91	0	1
+954	3024	0
+365	13	13
+1256	1	1
+74	1	1
+256	1	1
+68	1	1
+671	5	0
+144	4	0
+2140	1	1
+44	4	0
+223	1	1
+23	1	1
+716	5	0
+144	4	0
+2080	109	105
+223	70	70
+671	5	0
+144	4	0
+2140	16	16
+982	16	14
+148	4	0
+1095	66	60
+945	50	50
+996	2	0
+148	4	0
+2080	109	105
+964	5	0
+144	4	0
+2106	50	50
+996	2	0
+148	4	0
+2106	50	50
+242
+
+chain 2215952 chrUn_gl000228 129120 + 46991 129120 chr10 135374737 + 135304834 135360693 463
+43	23181	23046
+6	90	90
+334	6	0
+395	27	27
+494	145	149
+426	19	19
+480	1	11
+131	1	1
+19	4	0
+120	1	1
+35	1	1
+289	8247	8248
+26	0	8
+78	17650	1111
+121	3307	1
+35	1	1
+1001	6	0
+395	1	1
+25	1	1
+494	1	1
+26	0	8
+78	4	0
+35	1	1
+426	1	1
+17	1	1
+480	1	11
+131	1	1
+19	4	0
+120	1	1
+35	1	1
+1001	6	0
+395	1	1
+25	1	1
+494	1	1
+26	0	8
+78	4	0
+35	1	1
+426	1	1
+17	1	1
+474	10	9
+128	1	1
+19	4	0
+120	1	1
+35	1	1
+1001	6	0
+395	1	1
+25	1	1
+376	3306	0
+74	1	1
+83	1	1
+60	1	1
+52	1	1
+55	1	1
+32	1	1
+360	1	1
+88	1	1
+180	27	27
+1282	2251	0
+30	545	0
+105	1	1
+46	136	0
+1176	1	1
+47	18	0
+18	18	0
+55	18	0
+793	1	1
+28	1	1
+581	1	0
+4074	2	1
+2446
+
+chain 254528 chrUn_gl000228 129120 + 88123 111265 chr4 191273063 + 191234920 191248107 1604
+34	10176	3552
+754	2	0
+148	124	120
+1960	109	105
+964	5	0
+144	4	0
+121	8453	5141
+144
+
+chain 164891 chrUn_gl000228 129120 + 101397 114404 chr4 191273063 + 191238264 191247940 1939
+33	9885	6560
+996	2	0
+148	4	0
+1939
+
+chain 40159 chrUn_gl000228 129120 + 70221 91512 chr4 191273063 + 191223665 191244890 1141
+90	735	735
+27	570	570
+69	10105	10070
+70	5225	5207
+66	4225	4212
+26	50	50
+33
+
+chain 6229 chrUn_gl000228 129120 + 38164 38230 chr4 191273063 + 191191215 191191281 15369017
+66
+
+chain 5671 chrUn_gl000228 129120 + 71567 71627 chr4 191273063 + 191228308 191228368 1250
+60
+
+chain 3930 chrUn_gl000228 129120 + 118712 119504 chr18 76117153 - 76020078 76020393 13741639
+85	601	124
+106
+
+chain 1375 chrUn_gl000228 129120 + 91429 91463 chr4 191273063 + 191234920 191234954 1972
+34
+
+chain 1278 chrUn_gl000228 129120 + 101321 101347 chr4 191273063 + 191244781 191244807 2333
+26
+
+chain 1170 chrUn_gl000228 129120 + 94735 94769 chr4 191273063 + 191234920 191234954 2163
+34
+
+chain 1124 chrUn_gl000228 129120 + 98041 98075 chr4 191273063 + 191234920 191234954 26578
+34
+
+chain 919 chrUn_gl000228 129120 + 101347 101381 chr4 191273063 + 191234920 191234954 6339
+34
+
+chain 827 chrUn_gl000228 129120 + 111265 111299 chr4 191273063 + 191234920 191234954 87434
+34
+
+chain 12702 chrUn_gl000229 19913 + 412 548 chrX 154913754 - 39233529 39233665 17935142
+136
+
+chain 5098 chrUn_gl000229 19913 + 301 375 chr7 158821424 - 9920014 9920088 18279747
+74
+
+chain 15401 chrUn_gl000230 43691 + 29842 30067 chr20 62435964 - 41024366 41024591 14643913
+125	46	46
+54
+
+chain 12153 chrUn_gl000230 43691 + 28959 29088 chr10 135374737 - 34208037 34208166 18757529
+129
+
+chain 12020 chrUn_gl000230 43691 + 8092 8221 chrX 154913754 - 124835983 124836112 18957002
+129
+
+chain 10060 chrUn_gl000230 43691 + 30261 30455 chr3 199501827 - 88301345 88301539 22679433
+66	74	74
+54
+
+chain 7157 chrUn_gl000230 43691 + 30067 30154 chr2 242951149 + 86047836 86047923 19665405
+3	7	7
+77
+
+chain 24015 chrUn_gl000231 27386 + 4654 6337 chr5 180857866 + 70288528 70290201 7680780
+118	1377	1367
+188
+
+chain 18946 chrUn_gl000231 27386 + 6337 7360 chr5 180857866 - 104048753 104049775 8708063
+12	704	704
+72	144	143
+91
+
+chain 16625 chrUn_gl000231 27386 + 2163 2336 chr10 135374737 - 36902825 36902998 13411217
+173
+
+chain 16014 chrUn_gl000231 27386 + 5036 5206 chrX 154913754 + 20633055 20633225 14022851
+170
+
+chain 12702 chrUn_gl000231 27386 + 25798 25934 chrX 154913754 - 39233529 39233665 17935131
+136
+
+chain 12391 chrUn_gl000231 27386 + 23126 23294 chr11 134452384 + 50262817 50262985 18392381
+50	25	25
+93
+
+chain 12273 chrUn_gl000231 27386 + 3627 3759 chr1 247249719 - 155709229 155709361 18571004
+132
+
+chain 11334 chrUn_gl000231 27386 + 4172 4292 chr9 140273252 + 21364524 21364644 20124920
+120
+
+chain 10621 chrUn_gl000231 27386 + 8382 8524 chr4 191273063 + 136252211 136252355 21465956
+54	20	22
+68
+
+chain 10028 chrUn_gl000231 27386 + 22560 22688 chr10 135374737 + 99449647 99449775 22748041
+55	11	11
+62
+
+chain 9550 chrUn_gl000231 27386 + 3054 3241 chr11 134452384 + 46467217 46467406 23880867
+57	73	75
+57
+
+chain 9277 chrUn_gl000231 27386 + 7360 7468 chr2 242951149 - 156204992 156205100 12158462
+56	1	1
+51
+
+chain 8841 chrUn_gl000231 27386 + 25683 25776 chr5 180857866 - 144622856 144622949 25181714
+93
+
+chain 6713 chrUn_gl000231 27386 + 4772 4844 chr5 180857866 + 161861178 161861250 12370362
+72
+
+chain 5312 chrUn_gl000231 27386 + 6933 6989 chr2 242951149 + 51579869 51579925 20211932
+56
+
+chain 5053 chrUn_gl000231 27386 + 6349 6408 chr3 199501827 + 110713055 110713114 8874439
+59
+
+chain 3623 chrUn_gl000231 27386 + 5878 5917 chr8 146274826 - 130943147 130943186 24063221
+39
+
+chain 3087 chrUn_gl000231 27386 + 4499 4564 chr5 180857866 - 151976801 151976866 22766591
+65
+
+chain 2462 chrUn_gl000231 27386 + 23294 23322 chr5 180857866 - 140993746 140993774 21430514
+28
+
+chain 2380 chrUn_gl000231 27386 + 6863 7736 chrX 154913754 + 74323412 74324284 13413701
+70	748	747
+55
+
+chain 1938 chrUn_gl000231 27386 + 6415 7249 chr11 134452384 - 85742217 85743051 12694925
+59	715	715
+60
+
+chain 1209 chrUn_gl000231 27386 + 5917 6017 chr14 106368585 - 47277371 47277471 12257740
+100
+
+chain 575 chrUn_gl000231 27386 + 5818 5878 chr10 135374737 + 22451146 22451206 15305599
+60
+
+chain 354 chrUn_gl000231 27386 + 8607 8658 chr12 132349534 + 50248139 50248190 23666106
+51
+
+chain 55981 chrUn_gl000232 40652 + 2672 3286 chr1 247249719 + 29558771 29559386 2254424
+370	0	4
+68	3	0
+173
+
+chain 30625 chrUn_gl000232 40652 + 2331 2672 chrY 57772954 - 44046862 44047204 2487561
+217	1	1
+106	0	1
+17
+
+chain 14972 chrUn_gl000232 40652 + 34329 34487 chrX 154913754 + 113699598 113699756 15100139
+158
+
+chain 13390 chrUn_gl000232 40652 + 34068 34210 chr20 62435964 + 22916565 22916707 16960157
+142
+
+chain 12645 chrUn_gl000232 40652 + 33771 33906 chr14 106368585 - 63812125 63812260 18020773
+135
+
+chain 10324 chrUn_gl000232 40652 + 33919 34028 chr6 170899992 - 74634926 74635035 22085896
+109
+
+chain 3584 chrUn_gl000232 40652 + 34210 34248 chrX 154913754 - 70416101 70416139 23473516
+38
+
+chain 52638 chrUn_gl000233 45941 + 802 3019 chr12 132349534 + 50244492 50249723 2405861
+98	46	46
+53	1005	4019
+127	111	110
+54	26	26
+50	78	79
+98	98	98
+201	114	114
+58
+
+chain 27263 chrUn_gl000233 45941 + 999 1823 chr10 135374737 - 12704868 12705692 5123253
+41	437	437
+167	94	94
+85
+
+chain 26029 chrUn_gl000233 45941 + 396 699 chr5 180857866 - 24413022 24413325 6500883
+125	1	1
+95	4	4
+78
+
+chain 17811 chrUn_gl000233 45941 + 38826 39439 chr5 180857866 + 131253656 131254277 12283916
+54	333	341
+69	57	57
+100
+
+chain 13316 chrUn_gl000233 45941 + 3397 4215 chr1 247249719 + 164486340 164487158 3912391
+74	253	253
+51	378	378
+62
+
+chain 12153 chrUn_gl000233 45941 + 40193 40322 chr10 135374737 + 101166571 101166700 18757528
+129
+
+chain 10603 chrUn_gl000233 45941 + 723 943 chrX 154913754 - 28357792 28358012 5819450
+79	98	98
+4	1	1
+38
+
+chain 10115 chrUn_gl000233 45941 + 229 336 chr16 88827254 - 77406522 77406629 22552939
+107
+
+chain 10011 chrUn_gl000233 45941 + 39757 39898 chr3 199501827 - 59132119 59132260 22787689
+54	23	23
+64
+
+chain 9607 chrUn_gl000233 45941 + 40007 40142 chr6 170899992 + 77925734 77925869 23736932
+53	22	22
+60
+
+chain 8580 chrUn_gl000233 45941 + 2847 2960 chr3 199501827 + 21585914 21586027 3712717
+12	37	37
+64
+
+chain 8195 chrUn_gl000233 45941 + 1041 1127 chr2 242951149 - 119093538 119093624 26123131
+86
+
+chain 7332 chrUn_gl000233 45941 + 23927 24005 chr21_random 1679693 + 1414162 1414240 27537185
+78
+
+chain 7075 chrUn_gl000233 45941 + 39127 39213 chr2 242951149 - 156903226 156903312 19665406
+77	7	7
+2
+
+chain 6404 chrUn_gl000233 45941 + 24027 24095 chrY 57772954 - 45969314 45969382 29536962
+68
+
+chain 5994 chrUn_gl000233 45941 + 27720 27783 chr21_random 1679693 + 736671 736734 30572390
+63
+
+chain 5521 chrUn_gl000233 45941 + 35462 35520 chr1 247249719 + 141994539 141994597 31891728
+58
+
+chain 5421 chrUn_gl000233 45941 + 28860 28917 chrY 57772954 - 45972382 45972439 32185620
+57
+
+chain 5057 chrUn_gl000233 45941 + 42227 42280 chr21_random 1679693 + 1416441 1416494 33306944
+53
+
+chain 4977 chrUn_gl000233 45941 + 1660 1713 chr4 191273063 + 44000159 44000212 13885847
+53
+
+chain 4794 chrUn_gl000233 45941 + 1831 1882 chr3 199501827 + 28976359 28976410 34225448
+51
+
+chain 4402 chrUn_gl000233 45941 + 1908 1964 chr13 114142980 + 80218714 80218770 15308796
+56
+
+chain 2915 chrUn_gl000233 45941 + 2179 2231 chrX 154913754 - 85677566 85677618 5760053
+52
+
+chain 2427 chrUn_gl000233 45941 + 2296 2322 chr19 63811651 + 22356620 22356646 20880110
+26
+
+chain 2315 chrUn_gl000233 45941 + 3684 3890 chr3 199501827 - 103452931 103453137 5210342
+40	106	106
+60
+
+chain 2208 chrUn_gl000233 45941 + 2131 2646 chr1 247249719 - 90778455 90778971 3568552
+48	399	400
+51	14	14
+3
+
+chain 1953 chrUn_gl000233 45941 + 38960 39031 chr5 180857866 - 170798397 170798468 22477108
+71
+
+chain 1946 chrUn_gl000233 45941 + 39721 39757 chr4 191273063 + 150118550 150118586 24103400
+36
+
+chain 1711 chrUn_gl000233 45941 + 39314 39339 chr20 62435964 + 21411473 21411498 14643912
+25
+
+chain 1675 chrUn_gl000233 45941 + 40142 40172 chr2 242951149 + 189896983 189897013 24596006
+30
+
+chain 1565 chrUn_gl000233 45941 + 363 396 chr12 132349534 + 84953855 84953888 22905876
+33
+
+chain 1086 chrUn_gl000233 45941 + 38662 38716 chr5 180857866 - 112830741 112830795 14413069
+54
+
+chain 921 chrUn_gl000233 45941 + 38880 38926 chr2 242951149 - 186445721 186445767 19984811
+46
+
+chain 665 chrUn_gl000233 45941 + 38435 38508 chr7 158821424 - 45635266 45635339 24997339
+73
+
+chain 567 chrUn_gl000233 45941 + 4533 4589 chr4 191273063 - 120708136 120708192 24665208
+56
+
+chain 30885 chrUn_gl000234 40531 + 20770 21098 chrX 154913754 - 26469860 26470188 4479555
+328
+
+chain 18772 chrUn_gl000234 40531 + 29542 30847 chr2 242951149 + 66700377 66701693 11461281
+64	220	219
+130	836	848
+55
+
+chain 13381 chrUn_gl000234 40531 + 28891 29033 chr18 76117153 - 28506207 28506349 16971585
+142
+
+chain 13011 chrUn_gl000234 40531 + 32848 33004 chr21 46944323 - 3527568 3527724 17471551
+76	8	8
+72
+
+chain 12758 chrUn_gl000234 40531 + 27971 28107 chr9 140273252 + 40275857 40275993 17847477
+136
+
+chain 12298 chrUn_gl000234 40531 + 28202 28332 chr17 78774742 - 28650231 28650361 18533743
+130
+
+chain 9791 chrUn_gl000234 40531 + 31998 32458 chr4 191273063 + 52500251 52500712 23294807
+66	336	337
+58
+
+chain 9445 chrUn_gl000234 40531 + 21230 21331 chr5 180857866 + 160948764 160948865 16866863
+101
+
+chain 9406 chrUn_gl000234 40531 + 8297 8397 chr11 134452384 + 7899462 7899562 24219742
+100
+
+chain 6549 chrUn_gl000234 40531 + 28360 28429 chr3 199501827 - 77716231 77716300 29160148
+69
+
+chain 6432 chrUn_gl000234 40531 + 29956 30025 chr9 140273252 - 130605711 130605780 11645810
+69
+
+chain 5827 chrUn_gl000234 40531 + 29314 29391 chr4 191273063 + 65542826 65542903 22318479
+51	16	16
+10
+
+chain 5276 chrUn_gl000234 40531 + 28653 28709 chr11 134452384 + 42875218 42875274 32641801
+56
+
+chain 4982 chrUn_gl000234 40531 + 30259 30327 chr14 106368585 + 25312855 25312923 19084936
+68
+
+chain 4894 chrUn_gl000234 40531 + 31773 31825 chr12 132349534 + 50249715 50249767 33891551
+52
+
+chain 4820 chrUn_gl000234 40531 + 29245 29296 chr14 106368585 - 60597784 60597835 15880947
+51
+
+chain 4045 chrUn_gl000234 40531 + 29485 29542 chr4 191273063 + 52727852 52727909 20475295
+29	27	27
+1
+
+chain 4004 chrUn_gl000234 40531 + 32772 32822 chr11 134452384 + 25701880 25701930 20350535
+50
+
+chain 3827 chrUn_gl000234 40531 + 28796 28856 chr4 191273063 - 132749043 132749103 24150596
+60
+
+chain 3767 chrUn_gl000234 40531 + 29621 29672 chr4 191273063 + 109408128 109408179 23756830
+51
+
+chain 3326 chrUn_gl000234 40531 + 28132 28194 chr11 134452384 - 79489503 79489565 19687374
+62
+
+chain 3219 chrUn_gl000234 40531 + 21331 21396 chr1 247249719 + 86010808 86010873 5256643
+65
+
+chain 3215 chrUn_gl000234 40531 + 29391 30409 chr8 146274826 + 121721424 121722437 11517523
+94	843	838
+81
+
+chain 2086 chrUn_gl000234 40531 + 20746 20770 chr3 199501827 + 2077213 2077237 10890452
+24
+
+chain 1294 chrUn_gl000234 40531 + 30170 30235 chr5 180857866 + 175635483 175635548 13040504
+65
+
+chain 1179 chrUn_gl000234 40531 + 29160 29245 chr12 132349534 - 94862097 94862182 15299249
+85
+
+chain 30892 chrUn_gl000235 34474 + 10284 10636 chrX 154913754 - 137753964 137754316 4478171
+63	1	1
+187	1	1
+100
+
+chain 28245 chrUn_gl000235 34474 + 6990 7286 chr1 247249719 - 201110718 201111014 5523327
+296
+
+chain 15633 chrUn_gl000235 34474 + 10772 10939 chrX 154913754 + 111228690 111228857 14403755
+167
+
+chain 15123 chrUn_gl000235 34474 + 11327 11488 chr2 242951149 - 221981770 221981931 14935235
+161
+
+chain 15020 chrUn_gl000235 34474 + 8981 9146 chrX 154913754 + 150122103 150122269 15041806
+50	0	1
+115
+
+chain 14740 chrUn_gl000235 34474 + 10108 10284 chr1 247249719 - 105280685 105280865 6177884
+93	11	15
+68	3	3
+1
+
+chain 14088 chrUn_gl000235 34474 + 24168 24356 chrX 154913754 + 151092975 151093164 16094556
+70	28	29
+90
+
+chain 13398 chrUn_gl000235 34474 + 8127 8288 chr19 63811651 + 57248305 57248465 16951668
+53	1	0
+22	4	4
+81
+
+chain 11780 chrUn_gl000235 34474 + 9511 9636 chr4 191273063 - 168773683 168773808 19365753
+125
+
+chain 11069 chrUn_gl000235 34474 + 356 472 chrY 57772954 - 45847823 45847939 20603157
+116
+
+chain 10033 chrUn_gl000235 34474 + 11631 11737 chr1 247249719 + 193278857 193278963 22733668
+106
+
+chain 9778 chrUn_gl000235 34474 + 9888 9991 chr12 132349534 - 43209673 43209776 23326812
+103
+
+chain 8409 chrUn_gl000235 34474 + 11238 11327 chr2 242951149 - 175961361 175961450 14938980
+89
+
+chain 7852 chrUn_gl000235 34474 + 10013 10108 chr6 170899992 - 132065708 132065803 19855689
+76	7	7
+12
+
+chain 6783 chrUn_gl000235 34474 + 11488 11562 chr6 170899992 - 86591617 86591691 15132212
+74
+
+chain 5385 chrUn_gl000235 34474 + 11562 11620 chr5 180857866 + 115696160 115696218 18047359
+58
+
+chain 2922 chrUn_gl000235 34474 + 11207 11238 chrX 154913754 - 92875478 92875509 23049192
+31
+
+chain 2825 chrUn_gl000235 34474 + 10636 10670 chr12 132349534 - 101871456 101871490 12092770
+34
+
+chain 2162 chrUn_gl000235 34474 + 6967 6990 chr2 242951149 - 129587776 129587799 9249038
+23
+
+chain 1547 chrUn_gl000235 34474 + 7820 7881 chr12 132349534 + 82509454 82509515 19217212
+61
+
+chain 923 chrUn_gl000235 34474 + 7388 7458 chr11 134452384 + 54653442 54653512 19210883
+70
+
+chain 719 chrUn_gl000235 34474 + 8037 8087 chr5 180857866 - 7479901 7479951 22691815
+50
+
+chain 508 chrUn_gl000235 34474 + 9360 9418 chr10 135374737 + 96904139 96904197 25463139
+58
+
+chain 3900762 chrUn_gl000236 41934 + 0 41934 chr22 49691432 + 15341912 15383621 761
+910	1	1
+44	1	1
+601	16	16
+51	24	24
+382	118	108
+316	0	158
+302	1	1
+33	1	1
+1588	1	1
+18	1	1
+15101	0	1
+1338	0	39
+4044	417	7
+5600	2	0
+8329	1	0
+2693
+
+chain 39503 chrUn_gl000236 41934 + 24892 25309 chr22 49691432 + 15365763 15366180 3274701
+417
+
+chain 2040494 chrUn_gl000237 45867 + 12002 45867 chr21 46944323 + 10130092 10164119 1248
+88	1	1
+65	1	1
+74	5	15
+34	1	1
+139	1	1
+26	0	1
+241	1	1
+50	0	1
+91	1	1
+194	1	1
+29	1	1
+59	13	13
+54	1	1
+75	1	1
+89	1	1
+230	1	1
+59	3	3
+74	1	1
+199	1	1
+54	1	1
+488	1	16
+78	1	1
+75	1	1
+151	1	1
+93	1	1
+323	18	18
+327	1	1
+52	1	1
+853	1	1
+54	1	1
+409	1	1
+16	1	1
+42	0	1
+336	1	1
+61	1	1
+326	12	12
+295	1	0
+10	1	1
+201	3	1
+316	1	1
+15	1	1
+121	11	11
+574	1	1
+36	0	1
+40	1	1
+80	9	6
+383	4	0
+81	17	17
+172	0	4
+104	2	0
+542	1	0
+249	1	1
+48	1	1
+357	0	20
+81	0	4
+218	0	4
+46	4	0
+31	7	7
+58	4	0
+53	21	21
+2520	14	16
+343	0	1
+641	1	1
+40	0	1
+106	1	1
+353	0	49
+582	1	1
+108	0	3
+12	15	0
+14	3	18
+64	1	1
+37	1	1
+64	1	1
+27	1	1
+239	6	7
+69	2	4
+61	2	2
+29	3	3
+125	1	1
+20	1	1
+164	1	1
+98	1	1
+76	1	1
+33	1	1
+94	84	66
+45	3	0
+14	0	12
+28	3	0
+7	66	0
+56	12	0
+121	1	1
+139	1	1
+253	5	5
+79	3	0
+227	1	1
+115	1	1
+101	0	1
+116	3	3
+33	5	14
+140	1	1
+61	0	3
+70	0	1
+97	0	13
+150	1	1
+50	1	1
+52	3	3
+116	5	5
+114	1	1
+20	1	1
+94	8	8
+82	3	3
+70	1	1
+62	0	1
+20	1	1
+181	1	1
+122	0	130
+79	1	1
+27	103	0
+63	0	104
+146	52	0
+58	1	1
+74	1	1
+54	0	26
+66	3036	1025
+74	6289	8520
+54	654	456
+65	1	1
+25	1	1
+394	10	10
+48	0	1
+244	1	1
+44	1	1
+103	0	1
+74	1	1
+56	4	4
+94	1	1
+452	1	1
+33	1	1
+158	1	1
+63	1	1
+64	7	12
+33	11	11
+295	2	0
+560	1	1
+45	1	1
+1120	4	0
+97
+
+chain 3720276 chrUn_gl000238 39939 + 0 39939 chr22 49691432 - 34115067 34154863 793
+2039	8	12
+1016	5	5
+4821	1	0
+921	2	1
+890	0	1
+423	0	2
+3925	1	1
+72	1	1
+67	1	1
+148	1	1
+74	167	5
+60	1	1
+50	13	13
+3576	1	1
+54	1	1
+575	1	1
+26	1	1
+165	1	1
+46	1	1
+1550	1	1
+35	1	1
+3673	0	14
+2364	11	11
+568	0	3
+2927	4	0
+4923	1	0
+11	1	1
+988	0	1
+81	4	0
+545	1	1
+20	0	1
+1072	0	2
+750	7	7
+640	0	2
+606
+
+chain 2054582 chrUn_gl000239 33824 + 0 33798 chr21 46944323 + 10136554 10170496 1239
+77	1	1
+15	1	1
+121	11	11
+574	1	1
+36	0	1
+40	1	1
+80	9	6
+383	4	0
+81	17	17
+172	0	4
+104	2	0
+542	1	0
+249	1	1
+48	1	1
+357	0	20
+81	0	4
+218	0	4
+46	4	0
+31	7	7
+58	4	0
+53	21	21
+2520	14	16
+343	0	1
+641	1	1
+40	0	1
+106	1	1
+353	0	49
+582	1	1
+108	0	3
+12	15	0
+14	3	18
+64	1	1
+37	1	1
+64	1	1
+27	1	1
+239	6	7
+69	2	4
+61	2	2
+29	3	3
+125	1	1
+20	1	1
+164	1	1
+98	1	1
+76	1	1
+33	1	1
+94	84	66
+45	3	0
+14	0	12
+28	3	0
+7	66	0
+56	18	0
+121	1	1
+139	1	1
+253	5	5
+79	3	0
+227	1	1
+115	1	1
+101	0	1
+116	3	3
+33	5	14
+140	1	1
+61	0	3
+70	0	1
+97	0	13
+150	1	1
+50	1	1
+52	3	3
+116	5	5
+114	1	1
+20	1	1
+94	8	8
+82	3	3
+70	1	1
+62	0	1
+20	1	1
+181	1	1
+122	0	130
+79	1	1
+27	103	0
+63	0	104
+146	52	0
+58	1	1
+74	1	1
+54	0	26
+66	10199	10221
+394	10	10
+48	0	1
+244	1	1
+44	1	1
+103	0	1
+131	4	4
+94	1	1
+452	1	1
+33	1	1
+158	1	1
+63	1	1
+64	7	12
+33	11	11
+295	2	0
+560	1	1
+45	1	1
+1120	4	0
+137	4	0
+672	0	4
+1808	0	14
+3268	1	0
+571
+
+chain 3684438 chrUn_gl000240 41933 + 27 41933 chr4 191273063 - 142375113 142417352 796
+132	1	1
+44	1	1
+295	1	1
+24	1	1
+488	1	1
+52	1	1
+33	0	48
+279	7	7
+772	1	1
+16	1	1
+244	4	4
+486	0	4
+29	1	1
+375	0	48
+45	1	1
+61	0	48
+516	55	7
+557	1	1
+48	1	1
+61	1	1
+33	1	1
+195	1	1
+32	1	1
+304	1	1
+58	1	1
+428	3	0
+350	1	0
+477	15	12
+413	1	1
+46	1	1
+66	19	19
+257	1	1
+80	1	1
+180	1	1
+18	1	1
+92	1	1
+61	1	1
+80	25	25
+574	1	1
+33	1	1
+124	10	10
+1336	7	7
+113	1	1
+170	1	1
+22	0	4
+173	1	1
+21	1	1
+198	1	0
+62	1	1
+269	10	10
+109	1	3
+136	1	1
+38	1	0
+26	1	1
+514	1	1
+68	0	1
+76	0	1
+712	1	0
+9	0	1
+38	1	1
+53	1	1
+21	1	1
+369	1	0
+243	1	1
+28	1	1
+111	0	5
+186	1	1
+117	1	1
+29	0	5
+343	1	0
+77	1	1
+23	1	1
+69	1	1
+41	1	1
+237	11	11
+518	1	1
+79	1	1
+332	1	1
+70	1	1
+610	1	1
+27	1	1
+86	22	24
+793	1	1
+48	1	1
+80	1	1
+85	1	1
+366	38	38
+1127	1	1
+42	1	1
+607	9	9
+69	0	3
+45	0	1
+77	1	1
+30	5	5
+797	1	1
+49	1	1
+152	14	14
+65	13	13
+79	1	1
+37	1	1
+129	4	4
+192	1	1
+28	1	1
+124	17	17
+518	1	1
+99	1	1
+308	16	16
+70	1	1
+134	1	1
+69	1	1
+34	1	1
+162	1	1
+61	1	1
+405	1	1
+45	2	2
+183	1	1
+60	1	1
+227	4	4
+72	1	1
+190	1	1
+30	1	1
+387	1	1
+37	1	1
+553	1	1
+20	0	1
+58	1	1
+23	1	1
+72	5	4
+27	1	1
+322	0	7
+46	1	1
+83	1	1
+16	1	1
+60	1	1
+204	1	1
+895	8	8
+191	1	1
+44	1	1
+378	86	86
+148	9	9
+123	1	1
+48	1	1
+292	7	7
+106	1	1
+16	1	1
+350	15	15
+66	1	1
+43	1	0
+684	1	1
+74	1	1
+97	1	1
+66	1	1
+144	1	1
+45	1	1
+64	1	1
+24	1	1
+131	0	1
+30	1	1
+104	14	14
+228	1	1
+69	1	1
+247	1	0
+50	1	1
+54	1	1
+26	3	0
+73	2	0
+181	1	1
+18	1	1
+185	6	6
+280	1	0
+435	1	1
+40	0	10
+14	1	1
+52	1	1
+85	2	1
+27	1	1
+625	1	1
+15	1	1
+237	1	1
+26	1	1
+349	0	1
+51	1	1
+488	0	175
+143	36	0
+83	0	74
+38	1	1
+58	1	1
+51	2	2
+57	1	1
+144	1	1
+131	17	17
+487	1	1
+83	1	1
+137	12	12
+419	1	1
+24	1	1
+97	12	12
+64	18	18
+310	1	1
+31	1	1
+186	1	1
+36	1	1
+316	10	11
+301	1	1
+176	1	1
+599	4	0
+63	1	1
+511	11	11
+79	1	1
+44	3	3
+51	1	1
+116	1	1
+146	1	1
+135	2	2
+216	1	0
+21	1	1
+227	1	1
+58	1	1
+883	1	1
+62	1	1
+375	0	1
+366
+
+chain 6945 chrUn_gl000240 41933 + 0 3993 chr4 191273063 + 49288042 49296423 8111
+27	3912	8300
+54
+
+chain 3230 chrUn_gl000240 41933 + 27771 27827 chr3_random 749256 - 628862 628918 7525302
+56
+
+chain 28578 chrUn_gl000241 42152 + 7510 7836 chr10 135374737 - 24528620 24528946 5359884
+111	1	1
+117	1	1
+96
+
+chain 20691 chrUn_gl000241 42152 + 6884 7123 chr10 135374737 + 90379126 90379365 9909152
+113	1	1
+27	1	1
+97
+
+chain 19954 chrUn_gl000241 42152 + 8113 8344 chr11 134452384 + 17008798 17009029 10487677
+119	1	1
+24	1	1
+86
+
+chain 18714 chrUn_gl000241 42152 + 6396 7510 chr11 134452384 - 41660838 41661948 7928017
+55	850	846
+81	125	125
+3
+
+chain 18427 chrUn_gl000241 42152 + 6233 6498 chrX 154913754 + 121132265 121132530 8141535
+145	8	8
+10	55	55
+47
+
+chain 15897 chrUn_gl000241 42152 + 8957 9127 chr13 114142980 - 60623878 60624048 14134116
+170
+
+chain 13800 chrUn_gl000241 42152 + 6632 6782 chr2 242951149 + 123256405 123256555 16436015
+150
+
+chain 7239 chrUn_gl000241 42152 + 7836 7932 chr5 180857866 + 56109789 56109885 15641960
+1	26	26
+69
+
+chain 6771 chrUn_gl000241 42152 + 7140 7224 chr3 199501827 - 172585013 172585097 14071569
+84
+
+chain 4980 chrUn_gl000241 42152 + 6505 6564 chr9 140273252 - 115026189 115026248 16703028
+59
+
+chain 4801 chrUn_gl000241 42152 + 8656 8714 chr6 170899992 + 62873357 62873415 24154704
+58
+
+chain 4757 chrUn_gl000241 42152 + 6569 6626 chr3 199501827 - 23594171 23594228 19385889
+57
+
+chain 3592 chrUn_gl000241 42152 + 6075 6113 chr5 180857866 + 41171487 41171525 22768222
+38
+
+chain 2241 chrUn_gl000241 42152 + 6207 6233 chr5 180857866 - 32390164 32390190 11097341
+26
+
+chain 1486 chrUn_gl000241 42152 + 6113 6164 chr12 132349534 - 4193660 4193711 21729418
+51
+
+chain 1297 chrUn_gl000241 42152 + 6024 6075 chr6 170899992 + 73104104 73104155 18904124
+51
+
+chain 1062 chrUn_gl000241 42152 + 8600 8652 chr11 134452384 - 41655227 41655279 14169249
+52
+
+chain 4122233 chrUn_gl000242 43523 + 0 43523 chr22 49691432 + 23741157 23784637 726
+37	0	1
+501	0	1
+108	3	0
+187	0	1
+1121	1	1
+20	1	1
+1027	1	1
+34	1	1
+52	0	1
+765	0	4
+610	1	1
+19	0	1
+4259	1	0
+1146	31	0
+6060	1	1
+22	1	1
+2400	5	0
+8889	3	0
+179	0	1
+1992	0	1
+1767	16	0
+568	0	2
+178	0	2
+2610	4	0
+1173	1	0
+3097	0	2
+1764	0	6
+1838	2	0
+1027
+
+chain 4053524 chrUn_gl000243 43341 + 0 43341 chr21_random 1679693 + 729451 772721 736
+1181	1	1
+44	1	1
+164	1	1
+68	1	1
+111	1	1
+38	0	1
+6062	1	1
+22	3	3
+1372	1	1
+42	14	0
+910	1	1
+31	1	1
+463	28	28
+3921	1	0
+409	1	0
+1228	13	13
+561	1	1
+22	1	1
+527	4	0
+1153	1	1
+35	1	1
+2127	15	15
+1821	1	0
+407	0	1
+391	0	6
+613	1	1
+28	1	1
+191	36	0
+25	0	2
+13	0	2
+41	9	15
+922	16	16
+114	1	0
+479	29	0
+1850	1	0
+1511	0	3
+355	1	1
+48	1	1
+3880	1	1
+29	1	1
+1605	1	1
+47	1	1
+1485	1	1
+34	1	1
+907	8	8
+532	0	1
+1067	1	0
+1245	1	0
+2731	4	4
+31	3	0
+236
+
+chain 2844 chrUn_gl000243 43341 + 25693 25722 chr22_random 257318 + 139119 139148 22581207
+29
+
+chain 3756669 chrUn_gl000244 39929 + 8 39929 chr22 49691432 - 35197541 35237456 785
+890	0	2
+6963	1	0
+6036	101	101
+1666	0	1
+212	0	5
+237	1	0
+873	1	0
+227	3	0
+42	1	1
+4812	1	1
+36	1	1
+6217	2	0
+192	4	0
+249	1	0
+4665	0	5
+662	30	34
+257	12	12
+841	10	0
+4675
+
+chain 11637 chrUn_gl000244 39929 + 13898 34133 chr14 106368585 + 18813314 18833199 821
+26	1	1
+73	20106	19756
+29
+
+chain 3438216 chrUn_gl000245 36651 + 0 36651 chr1 247249719 - 105352682 105389363 845
+12574	2	0
+842	0	2
+6285	0	1
+6019	0	21
+4218	0	3
+2704	0	4
+81	0	1
+1294	1	1
+47	1	1
+1004	1	1
+21	1	1
+73	16	16
+108	1	1
+32	1	1
+1325
+
+chain 3563345 chrUn_gl000246 38154 + 0 38154 chr22 49691432 - 34033100 34071273 824
+1862	1	1
+45	1	1
+3608	0	3
+107	1	15
+848	1	1
+43	1	0
+337	1	1
+35	1	1
+176	0	2
+91	3	4
+2683	0	1
+1321	18	2
+519	1	1
+27	1	1
+472	1	1
+44	1	1
+2452	0	8
+253	1	1
+21	1	1
+48	8	0
+6372	1	1
+38	1	0
+33	1	1
+777	0	1
+139	0	3
+2402	0	2
+3053	1	1
+46	1	1
+198	4	4
+27	1	1
+1883	0	9
+1592	0	4
+320	0	1
+1542	11	11
+412	12	12
+1421	4	0
+2828
+
+chain 3430032 chrUn_gl000247 36422 + 0 36422 chr1 247249719 + 142267104 142303524 847
+151	8	8
+412	1	0
+642	0	1
+3260	12	12
+7577	0	1
+311	3	0
+2665	4	0
+3223	0	1
+437	0	1
+726	0	2
+340	1	0
+1345	1	0
+1511	0	2
+890	1	1
+29	1	1
+2699	1	1
+41	0	2
+1893	1	1
+49	1	1
+5180	1	0
+296	0	4
+573	1	0
+35	1	1
+1170	4	0
+925
+
+chain 3751823 chrUn_gl000248 39786 + 0 39786 chr22 49691432 + 31380700 31420473 786
+9870	4	0
+430	0	3
+13	1	1
+275	3	3
+48	0	1
+149	0	4
+854	1	0
+15	1	0
+1499	1	0
+3772	2	0
+2363	16	16
+1406	10	10
+813	1	0
+269	0	1
+2137	0	3
+379	0	1
+286	1	0
+504	7	0
+2925	1	0
+41	1	1
+1183	25	25
+1285	0	1
+1290	0	1
+93	5	4
+521	1	0
+239	1	0
+304	1	0
+202	1	0
+774	1	0
+3448	1	1
+29	1	1
+565	1	0
+303	2	0
+1412
+
+chain 3662710 chrUn_gl000249 38502 + 0 38502 chr22 49691432 + 26547108 26585613 801
+1207	1	0
+15053	0	12
+44	8	0
+22189
+
+chain 14267284136 chrX 155270560 + 60000 155260560 chrX 154913754 + 0 154913754 8
+34821	50000	50000
+86563	50000	30000
+766173	50000	50000
+36556	50000	50000
+80121	50000	90000
+754004	50000	100000
+5505644	50000	0
+3064790	50079	0
+26309505	50000	25000
+201176	8	0
+7416	0	2
+53134	8	0
+3073	0	12
+21097	0	2
+60831	2	0
+57728	0	20
+54336	0	1
+31675	0	4
+9987	4	0
+12108	0	4
+11225906	0	2000
+356252	50059	50059
+77342	1	1
+17	1	1
+94	0	3
+266	10	10
+113	1	1
+21	1	1
+5400	0	5
+4996	7	15
+3222	5	1
+6456	1	0
+1476	5	5
+2100	1	1
+40	1	1
+1316	0	1
+2446	1	0
+1555	0	2
+11220	1	0
+2639	1	0
+5190	0	4
+79	8	0
+5086	0	1
+2663	1	0
+9149	7	8
+1851	0	1
+9081	0	1
+7248	25	0
+208	28	0
+25	2	0
+15	83	0
+17	116	4
+2536	0	1
+1394	0	6
+12550	0	42
+822	4	0
+30578	1	0
+3711	4	0
+3637	1	0
+11945	0	1
+20204	0	1
+4172	8	0
+5679	1	0
+23827	0	2
+54817	0	1
+657	0	1
+342931	50000	180000
+2052068	27	1
+5375	2	0
+46	0	2
+6489	0	1
+7175	2	0
+1239	2	0
+4301	0	4
+27254	0	1
+4244	0	2
+717	0	2
+260	0	6
+26075	1	0
+236464	50000	50000
+6136098	3100000	3000000
+13518993	1	0
+449	1	0
+4535	4	0
+755	1	0
+1102	1	0
+24	1	1
+107	2	0
+3470	0	1
+1108	1	0
+4775	1	0
+8628	1	1
+46	1	1
+1072	1	1
+44	1	1
+292	4	5
+9091	4	4
+2218	4	4
+705	5	1
+452	0	1
+332	0	1
+1801	7	1
+3960	1	0
+2007	1	0
+3337	1	0
+2093	1	0
+407	310	0
+6130	1	1
+36	1	1
+1697	1	0
+97	13	0
+7624	1	1
+19	1	1
+3806	24	24
+3103	1	0
+779	7	7
+721	1	1
+43	1	1
+1626	0	1
+6146	0	2
+150	1	1
+47	1	1
+2172	0	2
+398	1	1
+31	1	1
+1334	16	16
+1663	1	1
+18	1	1
+2105	1	0
+9	1	1
+1409	1	1
+33	1	1
+1753	1	0
+408	0	1
+1916	1	0
+1928	0	12
+3800	1	1
+15	1	1
+2921	0	1
+4597	0	2
+486	6	0
+308	24	24
+1056	1	1
+44	1	1
+186	1	1
+46	1	1
+3037	0	1
+2301	0	3
+3876	1	1
+22	1	1
+1724	1	0
+3733	1	0
+627	1	0
+250	0	1
+194	1	1
+26	1	1
+20797	10	10
+2445	0	1
+1733	2	0
+1001	0	12
+4394	9	9
+4052	9	10
+670	1	1
+96	0	6
+26	1269	1568
+28	3	2
+10	1486	1188
+25	6	0
+18	1	1
+62	17	17
+77	1	0
+4949	10	10
+4690	1	0
+7343	0	1
+1248	0	1
+1259	0	1
+1347	4	0
+1532	0	1
+3797	16	16
+807	0	1
+2427	0	1
+48	1	0
+287	0	1
+611353	1	0
+1041	0	6
+371	1	0
+227	1	0
+2806	0	1
+36	1	1
+234	1	1
+23	1	1
+584	0	1
+22241	1	1
+65	1	1
+4605	1	0
+2337	20	0
+2119	1	0
+6170	13	9
+10665	1	0
+14631	0	1
+5359	0	4
+4004	0	1
+3182	0	11
+3897	16	14
+2551	0	1
+1824	0	1
+5274	1	1
+41	1	1
+4309	1	0
+3827	1	0
+4594	1	0
+65	1	1
+1170	1	1
+42	4	4
+214	1	0
+5228	1	0
+553	0	1
+6270	1	1
+12	1	1
+2849	12	13
+156	2	0
+8820	1	1
+41	1	1
+472	1	1
+65	1	0
+8	1	1
+1162	0	1
+565	1	1
+48	1	1
+536	1	2
+766	2	0
+4520	1	0
+1574	0	1
+503	1	0
+2558	1	0
+250061	7	7
+9650	18	18
+3208	1	1
+25	1	0
+744	0	2
+2994	1	1
+33	1	1
+1331	0	1
+87	19	19
+1935	5	0
+7	6	0
+1292	1	1
+35	1	1
+2485	1	1
+35	1	1
+4184	23	23
+13077	8	15
+671	4	0
+428	1	0
+4736	0	1
+3849	1	0
+6745	16	16
+2344	1	1
+41	1	1
+7917	1	0
+3876	1	1
+75	1	1
+1429	7	7
+11933	1	1
+28	1	1
+409	1	0
+11	1	1
+1223	12	12
+5354	1	0
+1255	6	0
+851	1	1
+45	1	1
+144	1	1
+47	5	5
+5929	0	4
+422	1	0
+2949	6	0
+193	1	1
+319	4	4
+3592	33	33
+3115	3	1
+1074	0	1
+2465	1	1
+40	1	1
+640	0	2
+550	1	1
+32	1	1
+4096	1	1
+29	1	1
+949	6	6
+6258	0	1
+3957	0	1
+19608	1	1
+48	1	1
+234	1	0
+16874	11	11
+1018	0	321
+2624	0	1
+4553	3	0
+491	6	0
+7496	1	1
+10	10	0
+76	4	0
+3314	1	1
+32	1	1
+5217	0	1
+3540	0	1
+1254	48	48
+1124	18	0
+3109	8	8
+3248	0	1
+1946	1	1
+48	1	1
+9620	2	0
+31242	50000	20000
+36075685	0	3
+36004	1	1
+27	1	1
+5196	1	0
+293	2	0
+13307	3	0
+2420	0	6
+1863	2	0
+2911	1	0
+3233	0	2
+66	0	1
+2375	0	10
+4894	0	1
+745	0	1
+3897	13	0
+4430	1	1
+48	1	4
+20	2	0
+279	2	0
+33	1	1
+48	0	1
+387	8	8
+692	1	0
+375	0	3
+380	23	23
+1289	1	1
+29	1	1
+12336	331	0
+852	0	4
+48	4	0
+4350	1	1
+59	1	1
+4306	5	0
+129	0	2
+3001	1	0
+1332	5	8
+23273	1	0
+30174	39	27
+337	3	0
+2838	0	1
+1614	9	0
+313	1	0
+82	0	4
+173	1	1
+25	1	1
+4912	39	0
+1863	1	0
+2931	0	1
+3134	3	0
+390880	1	0
+7199	0	1
+305	0	2
+1811	0	2
+5449	3	0
+7443	2	0
+2171	1	1
+27	1	1
+2668	2	0
+2180	1	0
+1170	9	0
+1450	16	16
+3080	0	1
+11157	0	1
+678	1	1
+28	1	1
+698	0	1
+112	0	1
+1831	0	3
+14327	0	2
+2247	3	0
+380	1	1
+28	1	1
+1265	21	19
+7184	2	3
+4225	14	9
+1002	1	0
+3854	0	4
+2535	1	1
+30	1	1
+794	0	1
+25	1	1
+76140	50000	70000
+1432750	0	7772
+681872	50000	20000
+4278742	56347	0
+12021233	1	0
+8	0	1
+1775	0	1
+1468	1	1
+51	14	16
+6	1	0
+6	1	0
+11	5	4
+7	1	0
+4	1	0
+75	2	1
+26	0	1
+16	1	0
+9	1	0
+19	2	0
+22	0	1
+9	1	0
+5	3	1
+14	7	6
+38	0	1
+26	1	1
+62	40	39
+1687	1	0
+54	1	0
+8528	1	0
+2722	1	0
+6240	1	0
+33	1	0
+121285	0	1
+6	1	0
+35	0	1
+1381	1	0
+5368	0	1
+3079	1	0
+10863441	4	0
+1799	1	1
+24	1	1
+334	0	1
+4960	0	17
+1160	1	1
+34	1	1
+6153	0	3
+1346	0	4
+103	0	4
+168	27	27
+2640	12	12
+304	16	0
+719	1	0
+3286	0	1
+10182	9	0
+804	1	1
+28	1	1
+749	1	0
+3387	1	1
+47	1	1
+482	1	0
+455	15	15
+719	1	1
+18	1	1
+2074	1	0
+1349	4	0
+3927	1	1
+18	1	1
+907	1	0
+2972	0	2
+115	1	1
+37	1	1
+4428	0	1
+1120	0	1
+4055	0	5
+2929	0	3
+3590	1	1
+47	1	1
+62	0	1
+947	1	1
+45	1	1
+1639	1	1
+32	1	1
+1076	1	0
+3996	0	4
+686	41	41
+7238	0	1
+1733	0	1
+1451	2	0
+617	0	1
+4375	1	0
+2194	15	16
+349	1	1
+27	1	1
+8237	0	1
+499	1	1
+37	2	2
+968	0	1
+34	1	1
+6337	1	1
+18	1	1
+8162	1	1
+21	0	5
+7668	45	45
+1562	0	1
+6017	5	5
+3872	0	8
+5421	0	1
+532	7	6
+5673	4	0
+1542	0	4
+890	1	3
+2561	0	1
+1692	0	1
+1142	1	1
+32	1	1
+503	1	2
+123	1	1
+75	1	1
+2322	0	1
+201	0	1
+40	3	3
+149	0	3
+1441	1	1
+40	1	1
+159	0	2
+1278	1	1
+33	1	1
+221	1	0
+31	1	1
+161	10	9
+1890	1	0
+132	1	1
+37	1	1
+514	23	17
+1373	0	4
+907	17	17
+714	31	30
+55	1	1
+24	1	1
+1038	0	2
+95	5	1
+1094	1	1
+170	1	1
+844	3	0
+369	1	1
+39	1	1
+650	1	1
+41	1	1
+176	1	1
+10	1	1
+688	0	1
+7637	0	4
+2653	1	1
+26	4	0
+46	1	1
+727	0	8
+2197	1	0
+13466	1	0
+3510	2	0
+2147	1	1
+44	3	0
+1320	11	11
+213	4	0
+102	0	1
+3239	1	0
+1492	0	3
+107	1	1
+35	14	0
+2391	1	1
+39	2	0
+436	0	4
+2271	0	8
+6868	3	0
+7183	1	0
+5104	3	0
+182	0	1
+3131	1	1
+31	0	1
+14	1	1
+59	0	1
+373	1	1
+42	1	1
+235	13	13
+1608	5	0
+152	1	1
+106	1	1
+783	34	34
+1633	1	1
+29	0	3
+821	1	1
+24	1	1
+1178	1	1
+33	1	1
+328	1	1
+27	1	1
+5682	1	0
+11	1	5
+146398	50000	30000
+59809	2	0
+3389	1	1
+37	1	1
+11606	1	0
+1597	1	0
+618	1	1
+47	1	1
+2698	1	0
+826	5	5
+33	2	0
+2560	14	0
+98	3	0
+1287	1	0
+7600	1	0
+9897	8	0
+7157	1	0
+32	1	1
+1698	1	0
+754	0	2
+6787	1	0
+584	2	0
+1107	1	1
+40	1	1
+365	1	1
+35	1	1
+400	8	0
+11443	1	0
+1973	1	0
+497	46	46
+657	1	0
+716	1	1
+25	1	1
+1570	2	0
+433	0	2
+905	2	0
+94	1	1
+28	1	1
+2490	1	1
+16	1	1
+5054	1	9
+2184	2	0
+2955	21	23
+794	0	1
+1563	1	1
+20	1	1
+1627	0	11
+1676	0	2
+1527	1	0
+676	1	1
+29	1	1
+1245	1	1
+34	1	0
+1192	7	0
+27	1	0
+1940	0	1
+3421	2	0
+17	1	1
+774	30	0
+97	6	6
+59	26	12
+840	1	1
+19	1	1
+2036	13	1
+26	14	0
+1114	1	0
+25	1	1
+380	0	16
+160	1	1
+17	1	1
+1151	4	0
+699	0	1
+29	2	0
+409	1	1
+49	1	1
+1240	1	1
+37	3	3
+2248	1	0
+1828	1	0
+1997	5	1
+4640	4	4
+4555	0	2
+149	0	52
+619	2	2
+16	1	1
+83	22	0
+56	57	1
+2531	0	8
+4250	1	1
+15	1	1
+2203	0	4
+1665	0	10
+415	2	0
+395	19	18
+15708	0	1
+161	4	0
+79	14	0
+543	1	1
+42	1	1
+3261	18	18
+139	46	46
+403	1	1
+18	1	1
+5405	1	0
+1104	1	1
+53	1	1
+392	1	1
+55	3	3
+3352	9	0
+692	1	9
+8	4	0
+27	3	97
+39	3	1
+21	3	51
+61	0	2
+8931	1	0
+6692	1	2
+1141	0	2
+196	2	0
+389	1	1
+30	1	1
+949	0	1
+6057	0	3
+4741	1	0
+7689	2	0
+2046	18	18
+215	0	1
+46885	2	0
+24138	2	0
+4037	1	0
+4047693	1	0
+9545	0	2
+11590	4	0
+1698	1	3
+13506	37	37
+5380	4	0
+1806	1	1
+44	1	1
+2581	0	2
+10620	0	1
+3804	0	1
+339	0	2
+476	0	1
+5861	8	5
+109	0	14
+901	1	1
+19	1	1
+45	2	0
+1736	1	0
+6625	2	0
+7812	4	0
+7678	2	0
+5068	4	0
+21	1	0
+4170	0	1
+1671	6	0
+6333	0	16
+902	1	1
+44	1	1
+384	0	6
+23418	2	0
+36	1	1
+8900	0	4
+222	1	1
+49	1	1
+2783	0	1
+2641	0	1
+136	20	20
+1279	0	1
+3924	6	6
+13054	6	0
+8965	23	36
+4094	2	0
+2269	1	0
+13621	16	16
+2621	0	2
+30076	1	1
+49	1	1
+102	1	0
+8824	1	1
+25	1	1
+1730	1	1
+47	1	1
+3339	0	1
+131	0	16
+83	16	0
+89	6	0
+2826	33	33
+3509	1	0
+541	1	0
+6288	0	4
+3814	2	0
+7260	0	1
+806	68	0
+1162	0	1
+2230	1	0
+1109	0	1
+1106	2	0
+12396	0	1
+26207	1	1
+21	1	1
+3541	18	18
+525	0	16
+1326	7	7
+525	0	1
+4198	0	1
+4682	13	13
+890	0	2
+816	0	2
+1961	0	4
+24586	1	1
+19	1	1
+4403	1	0
+1342	1	0
+57	12	11
+2225	1	0
+2011	0	35
+10543	0	1
+9766	6	12
+2489	2	1
+20	1	1
+1541	0	12
+1130	1	1
+34	1	1
+927	0	1
+4003	0	1
+966	1	0
+149	0	1
+844	8	0
+4324	1	1
+25	1	1
+569	7	6
+6361	1	0
+3074	0	1
+1539	3	9
+634	1	1
+39	1	1
+8610	13	12
+760	2	0
+4311	0	6
+3122	0	2
+369	1	0
+9963	10	10
+2191	1	1
+23	1	1
+1060	1	1
+19	1	1
+240	12	12
+1748	1	1
+45	1	1
+1040	1	1
+31	1	1
+7446	1	1
+25	1	1
+8379	7	7
+7325	3	0
+357	0	1
+1313	0	1
+11627	4	0
+5862	1	0
+9750	1	0
+3539	0	16
+5672	13	13
+2885	0	4
+8179	1	0
+753	0	1
+4317	0	2
+1318	1	0
+957	0	1
+825	12	12
+1109	0	16
+3736	17	17
+2236	8	8
+7791	15	185
+149	1	1
+21	2	0
+636	1	1
+22	1	0
+42	1	1
+1634	4	4
+3380	0	3
+979	2	0
+3429	0	1
+7132	0	14
+1733	1	1
+38	0	1
+88	1	0
+630	6	6
+489	5	0
+22	1	0
+94	1	0
+42	0	1
+17	1	0
+27	1	0
+172	1	1
+37	1	1
+191	1	1
+66	1	1
+630	1	0
+261	30	30
+1282	1	0
+16	1	1
+429	1	0
+1588	1	1
+20	1	1
+1416	1	1
+33	1	1
+529	1	0
+25	1	0
+1863	4	0
+1651	1	1
+28	1	1
+11815	1	0
+26	1	0
+19	1	1
+3105	1	0
+700	1	0
+150	1	0
+68	1	0
+1421	6	0
+567	1	0
+14	1	0
+2415	1	0
+41	1	1
+415	1	1
+33	1	1
+4521	1	1
+33	1	1
+307	0	1
+176	0	1
+3790	1	1
+86	1	1
+67	1	1
+65	1	0
+7439	1	1
+18	1	1
+16805	1	0
+1764	0	1
+6984	1	0
+3401	20	0
+156	1	1
+30	1	1
+165	2	0
+1087	0	1
+953	0	1
+483	1	0
+632	0	1
+652	0	1
+8559	0	2
+1871	0	1
+398	0	1
+2219	1	1
+53	1	1
+756	1	1
+66	1	1
+69	1	1
+48	1	1
+63	1	1
+28	0	3
+1057	0	3
+63	3	0
+55	1	1
+74	2	3
+159	3	0
+92	1	1
+29	1	1
+58	0	3
+1210	9	9
+54	1	1
+27	1	1
+1374	2	0
+1775	2	17
+764	14	14
+331	16	16
+2291	4	3
+1687	1	1
+26	1	1
+2469	0	1
+3243	1	0
+3636	1	1
+24	1	1
+615	0	1
+2566	1	0
+275	0	5
+690	0	7
+13139	1	0
+1452	0	4
+214	13	13
+61	124	0
+1381	9	9
+5812	1	1
+24	1	1
+5703	1	0
+3992	14	15
+1462	0	3
+5199	0	2
+1554	2	0
+715	12	10
+1966	2	0
+2808	16	0
+611	1	0
+406	0	18
+737	1	1
+31	1	1
+4372	0	5
+10789	0	1
+2399	0	1
+6750	2	0
+96	48	48
+1219	0	6
+6736	0	2
+4457	4	0
+7867	0	1
+3495	1	2
+6215	12	12
+1357	1	0
+2652	0	1
+1771	1	0
+14207	41609	41616
+18338	46	46
+851	1	0
+9638	1	0
+2994	1	0
+469	1	3
+499	1	0
+12074	13	13
+2807	11	10
+715	2	0
+1627	6	6
+5099	0	1
+488	5	1
+975	2	0
+1730	32	31
+1791	0	5
+8135	38	38
+84	3	3
+18	1	1
+3737	9	9
+1442	13	13
+212	10	0
+7712	1	1
+44	1	1
+6271	0	1
+1316	1	1
+49	1	1
+9052	28	32
+113	2	0
+2813	13	13
+1285	50000	2858
+75638	50000	40000
+1583473	2	0
+1564100	97462	0
+2933461
+
+chain 4369679 chrX 155270560 + 152229637 152277099 chrX 154913754 + 151980294 152116665 696
+7131	26	26
+1319	1	0
+10288	0	88910
+2852	19	19
+3721	0	1
+13270	1	0
+8834
+
+chain 2629454 chrX 155270560 + 120011032 120067379 chrX 154913754 + 119895063 119899921 647
+714	51489	0
+4144
+
+chain 1494650 chrX 155270560 + 148762194 148872193 chrX 154913754 - 6301537 6445444 168
+2899	0	1
+1499	0	1
+3725	0	6
+20333	1	0
+13152	18338	18338
+46	40010	73911
+32	9926	9926
+38
+
+chain 260907 chrX 155270560 + 75365988 75368784 chrX 154913754 - 79628560 79631356 2215
+1269	41	41
+1486
+
+chain 138004 chrX 155270560 + 120011746 120013199 chrX 154913754 + 119920102 119921555 138939
+1453
+
+chain 29712 chrX 155270560 + 112877029 112877338 chr12 132349534 + 121720730 121721039 4776951
+309
+
+chain 29117 chrX 155270560 + 75253866 75254170 chr12 132349534 - 49782819 49783123 5064709
+304
+
+chain 10575 chrX 155270560 + 143182285 143275757 chr2 242951149 - 154930543 155024664 254
+41	49992	50582
+45	43365	43424
+29
+
+chain 3572 chrX 155270560 + 148224541 148224579 chrX 154913754 + 148032219 148032257 5503764
+38
+
+chain 3404 chrX 155270560 + 120013199 120013235 chrX 154913754 + 119931276 119931312 297576
+36
+
+chain 3363 chrX 155270560 + 49293018 49293056 chrX 154913754 + 49218184 49218222 1450
+38
+
+chain 2275 chrX 155270560 + 152236768 152236794 chrX 154913754 - 2913071 2913097 1916
+26
+
+chain 2111 chrX 155270560 + 143122309 143122332 chr17 78774742 - 16413594 16413617 6765736
+23
+
+chain 2063 chrX 155270560 + 148224511 148224541 chrX 154913754 + 148032257 148032287 9904071
+30
+
+chain 1738 chrX 155270560 + 76513595 76513628 chrX_random 1719168 + 711492 711525 75
+33
+
+chain 1275 chrX 155270560 + 148522048 148522077 chr11 134452384 + 59964168 59964197 432609
+29
+
+chain 391 chrX 155270560 + 112955240 112955279 chr3 199501827 - 80088461 80088500 4668596
+20	4	4
+15
+
+chain 2373403023 chrY 59373566 + 10000 28819361 chrY 57772954 + 0 27228749 24
+34821	50000	50000
+86563	50000	30000
+766173	50000	50000
+36556	50000	50000
+80121	50000	90000
+754004	50000	100000
+6846717	50000	50000
+276367	50000	600000
+813231	3000000	500000
+39401	50000	400000
+554624	50000	100000
+535761	0	1
+32919	11	12
+12810	0	5
+18900	1	1
+121	4	5
+230478	0	1
+750	1	1
+22	1	1
+14340	1	1
+43	1	1
+2095	0	1
+14635	0	9
+2781	0	1
+45022	5	6
+7151	0	1
+9344	628	0
+5417479	50006	0
+2175791	50000	0
+1481749	50000	50000
+4867933
+
+chain 46617811 chrY 59373566 + 58819361 59363566 chrY 57772954 + 57228749 57772954 80
+98295	50000	50000
+395910
+
+chain 9624 chrY 59373566 + 14725909 14726162 chrX 154913754 + 99410441 99410697 23695076
+50	136	139
+67
+
diff --git a/public/chainFiles/makeChains.py b/public/chainFiles/makeChains.py
new file mode 100644
index 0000000..114b9a2
--- /dev/null
+++ b/public/chainFiles/makeChains.py
@@ -0,0 +1,50 @@
+#!/bin/tcsh
+import os.path
+import sys
+from optparse import OptionParser
+from itertools import *
+
+def main():
+    global OPTIONS
+    usage = "usage: %prog [options] mode hg19Tohg18.chain"
+    parser = OptionParser(usage=usage)
+    
+#     parser.add_option("-D", "--delete_while_archiving", dest="reallyDeleteInArchiveMode",
+#                         action='store_true', default=False,
+#                         help="if provided, we'll actually delete records when running in archive mode")
+         
+    (OPTIONS, args) = parser.parse_args()
+    if len(args) != 1:
+        parser.error("Requires exact 1 chain to analyze")
+
+    hg192hg18 = args[0]
+    
+    writeChain(hg192hg18, "b37tohg18.chain", lambda x: hg2b(x, 2))
+    writeChain(hg192hg18, "b37tob36.chain", lambda x: hg2b(hg2b(x, 2), 7))
+    
+HG2BCONTIG = dict()
+for c in range(1, 23) + ["X", "Y"]:
+    HG2BCONTIG["chr" + str(c)] = str(c)
+HG2BCONTIG["chrM"] = "MT"
+    
+def hg2b(line, pos):
+    parts = line.split()
+    if len(parts) > pos and "chr" in parts[pos]:
+        if parts[pos] in HG2BCONTIG:
+            parts[pos] = HG2BCONTIG[parts[pos]]
+        else:
+            print 'Skipping ', parts[pos]
+    return "\t".join(parts)
+    
+def writeChain(inFile, outFile, transform):
+    out = open(outFile, "w")
+    for line in open(inFile):
+        newLine = transform(line)
+        #print 'newline', newLine
+        if newLine != None:
+            out.write(newLine)
+            out.write("\n")
+    out.close()
+
+if __name__ == "__main__":
+    main()
diff --git a/public/doc/Ant_Help.tex b/public/doc/Ant_Help.tex
new file mode 100644
index 0000000..e119843
--- /dev/null
+++ b/public/doc/Ant_Help.tex
@@ -0,0 +1,9 @@
+\begin{description}
+  \item[compile] Compiles all java code in the source tree.  Places generated classes in the build directory.
+  \item[dist] Generates jar files, suitable for running via java -jar {YOUR\_JAR}.  Places resulting jars in the dist subdirectory.
+  \item[resolve] Resolves third-party dependencies.  Downloads all third-party dependencies to the lib directory.
+  \item[javadoc] Generates javadoc for the source tree.  Places javadoc in the javadoc directory.
+  \item[clean] Removes artifacts from old compilations / distributions.
+\end{description}
+View all available ant targets by running 'ant -projecthelp' in the directory containing build.xml.
+
diff --git a/public/doc/GATK_Coding_Standards.pdf b/public/doc/GATK_Coding_Standards.pdf
new file mode 100644
index 0000000..81148bd
Binary files /dev/null and b/public/doc/GATK_Coding_Standards.pdf differ
diff --git a/public/doc/GATK_Coding_Standards.tex b/public/doc/GATK_Coding_Standards.tex
new file mode 100644
index 0000000..42b6830
--- /dev/null
+++ b/public/doc/GATK_Coding_Standards.tex
@@ -0,0 +1,288 @@
+\documentclass[9pt]{report}
+\usepackage{fullpage}
+\usepackage{listings}
+\begin{document}
+
+\title{Genome Analysis Toolkit Coding Standards for Java}
+\author{Genome Analysis Software Engineering}
+\date{\today}
+\maketitle
+\tableofcontents
+
+\chapter{Overview}
+
+\section{Credit}
+The majority of text in this document is verbatim from the production informatics coding standard document, produced by Ted Sharpe and the production
+informatics team here at the Broad Institute.  They deserve all the credit for the insights in this document, and if you feel so inclined please share statements
+of gratitude with them.
+
+\section{Summary}
+This document is an attempt to describe a brief and minimal set of standards for Java code for use by production informatics projects at the Broad.  The goal of the standards is to allow programmers to be innovative and expressive, while allowing their peers a vague hope of maintaining and extending their output.  This document describes a set of arbitrary standards for naming and documentation based on industry-standard practices, and a set of �good practices� guidelines intended to imp [...]
+\pagebreak
+\section{Cheat Sheet}
+\begin{table}[htdp]
+\caption{default}
+\begin{center}
+\begin{tabular}{l p{4.5cm} r}
+Type & Style & Example \\ \hline
+Function names & uppercase words, with the first word lowercase & \texttt{convertToParser} \\
+Package names & lowercase, with specific functional encapsulation for each class  & \texttt{org.broadinstitute.sting.gatk}\\
+Variable names & uppercase words, with the first word lowercase & \texttt{resetCounter} \\
+Class names & uppercase words representing a noun & \texttt{TraversalEngine} \\
+Interface names & the same as class names, no 'i' before the name  & \texttt{GenomeEngine} \\
+Tab length & 4 spaces &  \\
+
+\end{tabular}
+\end{center}
+\label{default}
+\end{table}%
+
+
+
+\chapter{Naming}
+Choosing names is among the more arduous tasks in programming.  There is constant contention between creativity�finding the mot juste�and following fashion so as to more easily allow names to be guessed; and a tug between being concise�if only to save typing�and being verbose so as to provide greater explicitness.  Expending the time necessary to create a really good name conflicts with the programmer�s appropriate desire to get on with the job and get something done.
+Unfortunately, naming has a great impact on the maintainability of the code, and despite its being a somewhat fussy and fusty topic, a few guidelines are appropriate.  If the standards document is well crafted it will free the programmer from some of the arbitrary decision-making that, when inconsistent, detracts from the intelligibility of the code, while allowing the programmer to focus on the semantics of the name.
+
+\section{Package Naming}
+Package names should be all lower case, and should begin with: \\ \\ 
+\texttt{org.broadinstitute.sting}\\ \\
+To this add the product name (e.g., basecaller), and subdivide packages according to functionality below that.  Put all classes in a package (to allow for more easily understood dependency trees, and to allow reuse via a CLASSPATH of reasonable length).\\
+
+\lstset{language=Java, caption=Good Package Names, frame=leftline, label=PackageNames,basicstyle=\small}
+\lstset{tabsize=4}
+\begin{lstlisting}
+
+package org.broadinstitute.gatk.tools.walkers.basecalller.basecallerEngine; // Good
+package org.broadinstitute.gatk.tools.walkers.baseCallingStuff;			  // Bad
+package myBaseCaller;								  		// Unacceptable
+
+\end{lstlisting}
+
+
+\subsection{Good practices}  Try to organize packages so that the dependency tree isn�t total spaghetti.  Ideally, there should be a hierarchy among the packages so that, for example, the web support classes are in one package, and don�t know anything about database access, and the database access classes are in another package, and don�t know anything about web support.  Something that knows about both (a package that supports servlet development, for example) should be in a separate pa [...]
+
+\section{Interface Naming}
+Interfaces require no special naming convention to distinguish them from classes.  (See the Class naming conventions below.)  The presumption is that most of the types that you are passing around are, in fact, abstract types that don�t lock you into a particular implementation:  elaborate decoration of interface names is therefore unnecessary and undesirable.  Distinguish the implementation class names instead (since they should be repeated far less often throughout the code than the nam [...]
+\lstset{language=Java, caption=Good Interface Names, frame=leftline, label=InterfaceNames,basicstyle=\small}
+\lstset{tabsize=4}
+\begin{lstlisting}
+
+interface DatabaseBinder		// OK
+interface ITagFactory		// not as good
+
+\end{lstlisting}
+
+
+Some people like to reserve �able or �ible names for interfaces (e.g., Cloneable, Comparable, or Runnable).  This is especially useful for mix-in interfaces, where the interface describes a capability that can be shared among otherwise disparate types of objects.  Not all interfaces fall into this pattern, however, and you needn�t be concerned if your interface seems to want to have a noun as its name, rather than forcing it into the verb-able mold.
+\subsection{Good practices}
+ Expending the time necessary to abstract common behavior from a set of related classes is probably the single most important thing you can do to improve the extensibility and adaptability of your code.  Use interfaces to describe the common behavior so that you don�t force your clients to use particular implementations.
+In all cases, the methods of the interface describe the complete repertoire of behaviors necessary to be an object of the type named by the interface.  So check your name to see if it describes something possessing the interface�s set of behaviors, and check your methods to see if that�s what something by that name should be able to do.  Ruthlessly eliminate any inconsistencies.
+
+\section{Class Naming} 
+Naming:  Use mixed-case names, capitalizing the first character of each word.  Avoid overly short, and overly common names, and overly long, verbose names.  If there is doubt about whether the components of a name are separate words, use less capitalization rather than more.  (E.g, Timezone, not TimeZone.  Barcode, not BarCode.)  You are aiming to capitalize each concept, not each morpheme.  A primary interface name is a good prefix for a class name.  A package name is not a good prefix. [...]
+Don�t abbreviate any of the words in a class name.  It�s just too hard to remember, and too likely to introduce inconsistency.  You may, however, use very common acronyms as if they were a word.  For example, StructuredQueryLanguageHelper would be quite ridiculous�SQL is a common acronym, and the class should be called SqlHelper (note the lower case ql).
+Class names must be nouns.
+\lstset{language=Java, caption=Good Class Names, frame=leftline, label=ClassNames,basicstyle=\small}
+\lstset{tabsize=4}
+\begin{lstlisting}
+
+class FormModule		// OK
+class SOExecutor		// not very good � obscure abbreviations
+class State				// not good � too vague, ambiguous, and common
+
+\end{lstlisting}
+
+\subsection{Good practices}
+A class should model a clear concept.  If you can�t explain the concept behind a class in a sentence or two, there is probably something wrong.  (And if your sentence or two seems to require extensive use of the word �or� you can be certain that you have a problem.)
+
+\section{Field and Variable Naming}
+Use mixed case names, capitalizing the first character of each word except the first.  Constants may be all upper case, using underscores to separate words.
+Idiosyncratic abbreviations are acceptable for variable and field names, because their scope is very limited.  (This is because you won�t be using any public fields:  see below.)
+Public constants should follow the semantic rules already specified for classes:  not too short, not too long, no cryptic abbreviations.  Remember that your clients will qualify the name of the constant with the class name, so overly common words are not so much of a problem as for class names.  
+
+\subsection{Good practices}
+ No non-final public fields.  Ever.  Period.  You know why.  (But just to be tediously explicit, we�ll go on a bit about it.)  Just when you think you�ve got a totally passive data-bearing object that might just as well be a C-language struct as a Java class, and you reckon you�ll just make its fields public, you�ll figure out that it needs behavior.  It needs to be persistent, and has to keep track of whether it�s been dirtied or not.  Or it needs a new field that is dependent in some w [...]
+Sacks of data are so boring�objects long to have behavior.
+Note that public members of private, nested classes aren�t really public at all, and so they�re perfectly fine.  (This allows you to create struct-like objects for internal use within a class.)
+Be careful about static objects (whether public or private, final or not):  they get created when the class is loaded and there is no easy way to handle complex dependencies among them that might require some particular loading order.  It�s best to keep them very simple�for example, creating tiny immutable static objects to simulate C++-style enumerations is completely appropriate.
+Experience has shown that distinguishing the names of instance fields, class (i.e., static) fields, and constants from each other and from temporaries (i.e., stack frame variables, whether declared in a local block or passed as arguments) is enormously helpful in quickly comprehending a method:  It�s good to know at a glance how the code is affecting the state of the object (instance fields) or of all the objects in the class (class fields) without having to study the entire class to lea [...]
+Overly short variable names, especially one-character names, and names that are common words, or parts of common words, are a problem for programmers who use editors with a limited understanding of Java�s syntax.  Using iii as a for-loop index instead of i doesn�t really take much extra time, and it makes it a great deal easier to find all the places where the variable is used.
+\lstset{language=Java, caption=Good Variable Names, frame=leftline, label=VarNames,basicstyle=\small}
+\lstset{tabsize=4}
+\begin{lstlisting}
+
+private static Section gHeader;	// class member
+private URL mMyURL;				// instance member
+String wfQName;					// local � ugly, but who cares?
+for ( int i = 0; i < k; ++i )	// Please, don�t.
+int iii;						// Thank you.
+\end{lstlisting}
+
+
+\section{Method Naming}  
+Use mixed case names, capitalizing the first character of each word except for the first.  The first, uncapitalized word should be a verb.  Uncomplicated, local fetchers and modifiers of independent state ought to use get and set as their first word.  Getters for boolean values can use is, has, or can instead of get.  (Conversely, a method that causes the lights to dim over a several square block area should not be called getFoo.  Merely to name it fetchFoo instead appropriately hints th [...]
+It�s especially important that you don�t use obscure abbreviations or leave the vowels out of words in method names:  they�re too hard to remember.  Common acronyms, treated as if they were words, are fine.  It�s quite helpful if the name of the method is pronounceable, and spelled as it�s pronounced.
+\subsection{Good practices}
+Methods that have more lines than can fit on the screen all at once are much harder to understand than those that don�t.  Ditto for methods that have numerous lines that must be wrapped due to their length.  Some suggest that each method can have at most one looping control structure.  That doesn�t always work in practice, but you get the gist.
+Following strict structured programming rules is usually an aid to comprehension.  (This might not be true if doing so requires you to use a complicated set of flags to control the flow.)  If you feel that a continue, labelled break, or early return is less confusing than the structured alternatives, provide a comment to call attention to the easily overlooked, one- or two-token statement that breaks the rules of structured programming.
+
+\lstset{language=Java, caption=Good Method Names, frame=leftline, label=MethodNames,basicstyle=\small}
+\lstset{tabsize=4}
+\begin{lstlisting}
+
+while ( itr.hasNext() )
+{
+	if ( "foo".equals((String)itr.next()) )
+	{
+		return;	// HEY!  There�s an early return, here.
+	}
+}
+
+\end{lstlisting}
+
+A method should do one job.  And, as stated earlier for classes, you ought to be able to describe that job in a crisp sentence or two.  After you�ve done so, type it in as javadoc.
+Take switches and long series of if / else if blocks as a warning sign that polymorphism might have served you better.
+Methods with more than a very few parameters are difficult to use.  If you have a method with more than three or four parameters you might consider passing an object instead.  If you have more than seven, you definitely need to do something else.
+There is a delicate balance to strike between sanity-checking every argument passed to every method and never testing your inputs at all.  Too much checking chews into performance, too little means the code will not be robust.  Here are two criteria for achieving a happy medium:
+Arguments that are not used directly by the method, but simply passed through to lower layers need not be checked.  Arguments that are used directly by the method ought to be checked, especially if the consequence of not checking them will be something completely uninformative like a NullPointerException.  You cannot assume that it will be easy to produce a stack trace to home in on what code is producing the exception, and so the exception�s message must serve that purpose.
+The second criterion is to ask whether the consequences of passing bad arguments will be felt immediately or whether doing so will deploy a delayed-action time bomb.  For example, passing a null object that gets saved as a part of the object�s state (even if it�s not used directly within the method that received it) may put a na�ve object into an unstable state that may not reveal itself until much later in the program�s execution.  This can be the very devil to debug.  Your goal is to m [...]
+
+
+
+\chapter{Layout}
+\section{File Template}
+Begin each file with the following bit of rote material.  Just cut and paste it into your IDE so that it becomes the first few lines of every source file:
+\lstset{language=Java, caption=A Good Code Header, frame=leftline, label=Header,basicstyle=\small}
+\lstset{tabsize=4}
+\begin{lstlisting}
+/*
+ * $Id$
+ * BROAD INSTITUTE SOFTWARE COPYRIGHT NOTICE AND AGREEMENT
+ * Software and documentation are copyright 2005 by the Broad Institute.
+ * All rights are reserved.
+ *
+ * Users acknowledge that this software is supplied without any warranty or support.
+ * The Broad Institute is not responsible for its use, misuse, or
+ * functionality.
+ */
+\end{lstlisting}
+
+\section{Documentation}
+
+All classes must have the following, minimum level of javadoc:
+\lstset{language=Java, caption=Javadoc Class Style, frame=leftline, label=GoodJavadoc,basicstyle=\small}
+\lstset{tabsize=4}
+\begin{lstlisting}
+/**
+ * One crisp, informative sentence or noun phrase that explains
+ * the concept modeled by the class.
+ *
+ * This class is [<em>not</em>] thread safe [because it is immutable].
+ *
+ * @author	I. M. Coder
+ * @version	$Revision$
+ */
+class CrispConcept
+{
+    public static final String ID = "$Id$";
+\end{lstlisting}
+
+
+You are encouraged to provide as much explanatory material as you feel is helpful following that first, summary sentence.  Information on algorithms and other information that will help a client make appropriate use of the class is particularly welcome.  (But see Stateful Interfaces, and Rules for Use, below.)
+Tell us whether your class is thread-safe or not.  Thread safety due to immutability is particularly well worth mentioning.  (It may warn a maintenance programmer off adding the set methods that you apparently forgot to provide.)
+All methods must have the following, minimum level of javadoc:
+\lstset{language=Java, caption=Good Method Javadoc, frame=leftline, label=MethodJavadoc,basicstyle=\small}
+\lstset{tabsize=4}
+\begin{lstlisting}
+/**
+ * One crisp, informative sentence or noun phrase that explains
+ * what the method does.
+ *
+ * @param	parm1	Parm1 selects the widget to be frobnicated.  Cannot be null.
+ * @param	parm2	Parm2 specifies the type of frobnication to apply.
+ * @return	The frobnicated widget.
+ * @throws	FrobnicationException Thrown if widget isn�t frobnicable.
+ */
+\end{lstlisting}
+For each parameter of reference type, tell us whether the reference may be null.
+\section{Imports}
+There is a balance between trying to maintain lengthy lists of classes imported one-by-one on the one hand, and importing many packages wholesale using an asterisk on the other.  It shouldn�t often be a big problem:  there are exceptions, but a class that makes use of dozens of other classes may be trying to tell you that it needs some redesign.  The suggestion is to import classes explicitly from packages we have written�especially those under active development.  Also import explicitly [...]
+\section{Order of Class Members}
+Classes should be laid out consistently.  You may put the member fields at either the bottom or the top, but you must not sprinkle them throughout.
+There is an argument that a class ought to be ordered with its public constants and constructors at the very top, its public methods next, and its internal stuff last, since that concentrates at the very top what a programmer needs to know to make use of the class.  This isn�t obligatory, but you may wish to give it some consideration.
+Nested classes go at the very bottom, after everything else.
+\section{Make �em Pretty}
+Use four space tabs.  Don�t omit braces around single statements.  Line things up so that it�s clear what things are on the same level.  Give us enough white space to make it pretty.
+
+
+\chapter{Design Considerations}
+If you�re doing things right (and the DoD doesn�t) design isn�t a distinct phase that ends when coding begins.  Ideally, you�ll develop a comprehensive, top-down design before you begin coding.  This may take more than one napkin.  Even so, you�ll face many decisions about implementation details that are not completely specified by the overall design.  In other words, it�s inevitable that you�ll be doing design while you code.  What follows are some coding standards for you to consider w [...]
+\section{Encapsulation}
+With very rare exception, all fields�both instance members and static members�should be private.  Protected and default (i.e., package-scoped) access is like public access, only less so.  (Making a change in such a field still requires you to locate and analyze use of the field in indefinitely many files:  for public fields you need to look everywhere, for protected fields you need only scan everything that extends you, and for default-access fields, you need only scan everything in the  [...]
+Always use the most restrictive permission consistent with the design of your class.  Don�t make all of your internal methods protected in the vain hope that someday, some extending class might need to tweak your internal state, and you�ll make it easy.
+Similarly, don�t provide a getter and setter for every piece of your internal state:  the goal is to meet the contract of the interfaces you implement, and to hide the details of how you do it.  Even the most legitimately passive of objects�the model objects you�ve just hauled out of the relational database�will likely have private, internal state that should not be exposed directly to clients.  (Check out all the hidden state in EJB entity beans, for example.)
+\section{Is-A versus Has-A}
+A subclass and its superclass have an Is-A (or specialization-generalization) relationship.  A class and a component of that class have a Has-A (or containment) relationship.  If you have a crisp, clear idea of what kind of things two classes represent, then simply saying to yourself �Thing A is a (special kind of a) Thing B�, and �Thing A has a Thing B (as one of its parts)�, will often make it clear what the relationship should be:  one of the two sentences may sound very odd.  �A Dog  [...]
+\section{Redundant data}
+If you have only one copy of a given datum, it will be either right or wrong, but it won�t be inconsistent with other data.  Guaranteeing consistency is a great deal more complex than guaranteeing accuracy.  Checking for and maintaining consistency among multiple copies of a datum often robs you of the efficiency you hoped to gain by the denormalization; not checking for and not maintaining consistency is a very frequent source of hard-to-fix bugs, and weird, unreliable program behavior.
+\section{Exceptions}
+Exceptions handle, well, exceptional conditions.  Properly used, they provide a last-gasp attempt to allow a robust program to clean-up and recover from catastrophic situations.  Exceptions should not be thrown frequently, certainly not as a part of the normal, expected flow of a program.  Do not use them as a nifty hack for implementing non-local transfer of control.  (Exceptions are far more expensive than normal returns, so the performance wizards won�t be tempted to do this, anyway.  [...]
+RuntimeExceptions are for even more rare, more catastrophic situations from which recovery is unlikely, at best.
+In code which will be called by general clients outside your package, catch and re-throw exceptions from the lower layers of code on which you depend to give a more package-oriented explanation of the bad thing that happened.  However, preserve information when you do this:  Wrap the original exception in a new exception that supplements rather than replaces the original message.  And respond to all flavors of printStackTrace with the nested exception�s stack trace (i.e., delegate these  [...]
+Never create exceptions with null messages.
+\section{Recovering External Resources}
+Java frees you from having to worry about memory as a resource.  (Well, it reduces the worry, anyway.)  Therefore you should have oodles of time left over to make certain that you free other resources when you�re done with them.  Two key external resources that you must make certain to release are open streams (which chew up a precious operating system file handle), and database connections (which chew up precious DBMS memory).  The only really reliable way to make certain that these res [...]
+Try to avoid designs that require a class to maintain an open stream.  One technique is to use an event-driven model to turn the file processing upside down:  you can still have a nicely modular and reusable class while processing the file within the scope of a single block by using Listeners.
+\section{Stateful Interfaces and Rules for Use}
+Good interfaces are concise, comprehensive, and orthogonal.  Concise means that there are no superfluous operations that don�t seem to fit the underlying abstraction, and that there is one good way of accomplishing a given end, not a variety of ways from which you must choose.  Comprehensive means that everything you might need to do in manipulating the object has been provided for.  And orthogonal means that each method does something independent, and that any method can be called at an [...]
+Poor interfaces are cluttered with Rules for Use.  If you are lucky, these rules are made explicit in documentation:  Be sure to call this method before calling that one, but never call this method if you�ve ever called that one, and do, please, remember to call this one when you�re all done.  Needless to say, these interfaces are very difficult for clients to use correctly.
+One particularly common form of this blight is the Stateful Interface:  the object has a lifecycle, and certain methods are appropriate only when the object is in some particular phase of the lifecycle.  For a simple example, read the javadoc for the java.sql.CallableStatement class.  It describes how you must call registerOutputParameter before calling execute, how, for maximum portability, you should not call getMoreResults if you have called any of the getOutputParameter methods, and  [...]
+If you can�t seem to work out how to avoid Rules for Use on your interfaces, you must at the very least make sure that each method call detects misuse, and throws an appropriate exception or does something other than trash your internal state.  Every public method, if it affects object state at all, must transform the object from one valid, consistent state to another valid, consistent state.
+If you need some ego-incentive to motivate you, consider this:  Hard-to-use, hard-to-understand, hard-to-maintain code is quickly replaced after you cease to maintain it.  What kind of legacy is that?
+Sometimes you can see several distinct patterns of use among the clients of an interface:  they might be telling you that you need to re-factor the interface into two separate interfaces.
+\section{Multithreading}
+Making your implementations thread-safe is a enormously complex issue.  Unfortunately, almost all of us are doing some work in multi-threaded environments (writing servlets, for example), and it's an issue that we are forced to confront.
+If you haven�t examined the issue for one of the classes you�ve implemented (either because you don�t anticipate its being used in a multi-threaded environment, or because the whole thing makes your brain ache), please provide a javadoc comment for the class indicating that it is not thread-safe.  If you�re not sure, it�s not safe!
+Don�t just synchronize every method.  Synchronization is far too expensive to use carelessly.  (Less so than it used to be, but still expensive.  And it doesn�t resolve all multi-threading issues, anyway.)
+One way of beginning to address the issue of thread-safety is to understand what doesn�t need any special thread-safety code, and try to produce as much of that as you can.  Here are a couple of quick tips.
+Objects that can be seen only by a single thread are immune from the issue:  If the only references to an object are from local variables�that is, if a reference to the object is never stored in an instance or static field�it will be visible only from the thread that creates it.
+Immutable objects are automatically thread-safe.  If you can�t change it, you can�t see it in an inconsistent, intermediate state.
+\section{Canonical methods}
+Most simple classes either do or are.  In the EJB environment session beans are the do classes, and entity beans are the are classes.  In the model-view-controller paradigm, model objects are the are objects, controllers are the do objects, and views are mostly are, but typically also have a little bit of do flavor.  So, you see, it does depend on what your definition of is is.
+The point of the distinction is that most of the are classes, those often immutable little bags of independent state, usually need to override equals and hashCode to behave properly.  You must implement these basic object operations in each of your passive, data-bearing classes; you may wish (or need) to implement them in the others.
+The ares are typically more useful when Comparable�implementing that interface allows you to put them into sorted Collections�so you ought to consider that next.
+Being Cloneable and Serializable usually come for free (no code to write), so throw those into the mix, too, unless there�s a compelling reason not to.  An example of a reason not to might be that you need to maintain uniqueness at a level of abstraction higher than object identity�you don�t want to allow clients to make copies.
+\section{Performance}
+Your overall design�your selection of algorithms and data structures, for example�has a far greater impact on performance than any little hacks you can apply while implementing the code.  So design for performance, and implement for clarity.
+Nonetheless, the java compiler that most of us use can use a little help in doing optimization.  Don�t expect order-of-magnitude performance gains�you�ll get those by designing away I/O, replacing searches with hashes, etc.�these are percentage point tweaks.
+Move invariant code out of loops.  For example, many for loops can calculate their terminating condition once, before the loop starts, rather than at each iteration through the loop.
+\lstset{language=Java, caption=Improvements to loops, frame=leftline, label=loopInprovements,basicstyle=\small}
+\lstset{tabsize=4}
+\begin{lstlisting}
+for ( int iii = 0; iii < str.length(); ++iii )	// bad
+
+int nnn = str.length();
+for ( int iii = 0; iii < nnn; ++iii )		// good
+\end{lstlisting}
+Strength reduction:  do a simple calculation to update the value of some variable using the value it has from a previous trip through a loop, rather than from scratch each time.
+\lstset{language=Java, caption=Good looping practices, frame=leftline, label=loopPractices,basicstyle=\small}
+\lstset{tabsize=4}
+\begin{lstlisting}
+for ( int iii = 0; iii < nnn; ++iii )		// bad
+{
+	double val = pow( 2., iii );
+	. . .
+}
+
+double val = 1.;
+for ( int iii = 0; iii < nnn; ++iii )		// good
+{
+	. . .
+	val *= 2.;
+}
+\end{lstlisting}
+Avoid some performance dogs in the SDK:  Use the underlying Stream classes rather than Readers when appropriate.  Use the newer, non-synchronized collection classes rather than Vector and Hashtable.
+Penalties
+Code that fails to follow these guidelines will be posted around the MIT campus, along with the author�s email address and an urgent request for comments.
+
+\end{document}
\ No newline at end of file
diff --git a/public/doc/README b/public/doc/README
new file mode 100644
index 0000000..e70ced0
--- /dev/null
+++ b/public/doc/README
@@ -0,0 +1,86 @@
+The Genome Analysis Toolkit (GATK) 
+Copyright (c) 2009 The Broad Institute 
+
+Overview 
+-------- 
+The Genome Analysis Toolkit (GATK) is a structured programming
+framework designed to enable rapid development of efficient and robust
+analysis tools for next-generation DNA sequencers.  The GATK solves
+the data management challenge by separating data access patterns from
+analysis algorithms, using the functional programming philosophy of
+Map/Reduce.  Consequently, the GATK is structured into data traversals
+and data walkers that interact through a programming contract in which
+the traversal provides a series of units of data to the walker, and
+the walker consumes each datum to generate an output for each datum.
+Because many tools to analyze next-generation sequencing data access
+the data in a very similar way, the GATK can provide a small but
+nearly comprehensive set of traversal types that satisfying the data
+access needs of the majority of analysis tools.  For example,
+traversals "by each sequencer read" and "by every read covering
+each locus in a genome" are common throughout many tools such as
+counting reads, building base quality histograms, reporting average
+coverage of the genome, and calling SNPs.  The small number of these
+traversals, shared among many tools enables the core GATK development
+team to optimize such traversals for correctness, stability, CPU
+performance, memory footprint, and in many cases to even automatically
+parallelize calculations.  Moreover, since the traversal engine
+encapsulates the complexity of efficiently accessing the
+next-generation sequencing data, researchers and developers are free
+to focus on their specific analysis algorithms.  This not only vastly
+improves productivity of the developers, who can quickly write new
+analyses, but also results in tools that are efficient and robust and
+can benefit from improvement to a common data management engine.
+
+Capabilities 
+------------ 
+The GenomeAnalysisTK development environment is currently provided as
+a platform-independent Java programming language library.  The core
+system works with the nascent standard Sequence Alignment/Map (SAM)
+format to represent reads using a production-quality SAM library
+developed at the Broad.  The system can access a variety of metadata
+files such as dbSNP, Hapmap, RefSeq as well as work with genotype and
+SNP files in GLF, Geli, and other common formats.  The core system
+handles read data from Illumina/Solexa, SOLiD, and Roche/454.  The
+current GATK engine can process all of the 1000 genomes data
+representing ~5Tb of data from these three technologies produced from
+multiple sequencing centers and aligned to the human reference genome
+with multiple aligners.  The GATK currently provides traversals by
+each read (ByRead traversal), by all reads covering each locus in the
+genome (ByLoci traversal), and by all reads within pre-specified
+intervals on the genome (ByWindow traversal).
+
+Dependencies
+------------
+The GATK relies on a Java 6-compatible JRE.  At the time of this writing,
+the GATK team tests with Sun JRE version 1.6.0_12-b04.  Additionally, the
+GATK requires as inputs a sorted, indexed BAM file containing aligned reads 
+and a fasta-format reference with associated dictionary file (.dict)and 
+index (.fasta.fai).  
+
+Instructions for preparing input files are available here:
+
+http://www.broadinstitute.org/gatk/guide/article?id=1204
+
+The bundled 'resources' directory  contains an example BAM and fasta.
+
+Getting Started
+---------------
+The GATK is distributed with a few standard analyses, including PrintReads,
+Pileup, and DepthOfCoverage.  More information on the included walkers is
+available here:
+
+http://www.broadinstitute.org/gatk/gatkdocs
+
+To print the reads of the included sample data, untar the package into
+the GenomeAnalysisTK directory and run the following command:
+
+java -jar GenomeAnalysisTK/GenomeAnalysisTK.jar \
+     -T PrintReads \
+     -R GenomeAnalysisTK/resources/exampleFASTA.fasta \
+     -I GenomeAnalysisTK/resources/exampleBAM.bam
+
+Support
+-------
+Documentation for the GATK is available at http://www.broadinstitute.org/gatk/guide.
+For help using the GATK, developing analyses with the GATK, bug reports, 
+or feature requests, please visit our support forum at http://gatkforums.broadinstitute.org/
diff --git a/public/external-example/pom.xml b/public/external-example/pom.xml
new file mode 100644
index 0000000..5065805
--- /dev/null
+++ b/public/external-example/pom.xml
@@ -0,0 +1,272 @@
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+    <modelVersion>4.0.0</modelVersion>
+
+    <!-- Properties for your assembly -->
+    <groupId>org.mycompany.app</groupId>
+    <artifactId>external-example</artifactId>
+    <packaging>jar</packaging>
+    <version>1.0-SNAPSHOT</version>
+    <name>External Example</name>
+
+    <properties>
+        <gatk.version>3.3</gatk.version>
+        <!--
+        gatk.basedir property must point to your checkout of GATK/GATK until we can get all the
+        dependencies out of the committed gatk repo and into central.
+        The installed pom for gatk-root looks for this property.
+        Alternatively, one can install all the gatk files into their local ~/.m2/repository repo.
+        http://maven.apache.org/plugins/maven-install-plugin/examples/custom-pom-installation.html
+        -->
+        <gatk.basedir>../..</gatk.basedir>
+        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
+        <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
+        <maven.build.timestamp.format>yyyy/MM/dd HH:mm:ss</maven.build.timestamp.format>
+
+        <!-- NOTE: Currently the testing infrastructure for walkers does not support running outside the Broad. -->
+        <gatk.committests.skipped>true</gatk.committests.skipped>
+        <gatk.unittests.skipped>${gatk.committests.skipped}</gatk.unittests.skipped>
+        <gatk.integrationtests.skipped>${gatk.committests.skipped}</gatk.integrationtests.skipped>
+
+        <!-- This flag is used by the package tests to disable re-shading -->
+        <gatk.unpack.phase>process-resources</gatk.unpack.phase>
+        <gatk.shade.phase>package</gatk.shade.phase>
+    </properties>
+
+    <repositories>
+        <repository>
+            <id>gatk.public.repo.local</id>
+            <name>GATK Public Local Repository</name>
+            <url>file:${gatk.basedir}/public/repo</url>
+        </repository>
+    </repositories>
+
+    <dependencies>
+        <dependency>
+            <groupId>org.broadinstitute.gatk</groupId>
+            <artifactId>gatk-tools-public</artifactId>
+            <version>${gatk.version}</version>
+        </dependency>
+
+        <dependency>
+            <groupId>org.broadinstitute.gatk</groupId>
+            <artifactId>gatk-tools-public</artifactId>
+            <version>${gatk.version}</version>
+            <type>test-jar</type>
+            <scope>test</scope>
+        </dependency>
+
+        <dependency>
+            <groupId>org.testng</groupId>
+            <artifactId>testng</artifactId>
+            <version>6.8</version>
+            <scope>test</scope>
+        </dependency>
+    </dependencies>
+
+    <build>
+        <plugins>
+
+            <!-- Copy test resources to your classes directory -->
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-dependency-plugin</artifactId>
+                <version>2.8</version>
+                <executions>
+                    <execution>
+                        <id>unpack</id>
+                        <phase>${gatk.unpack.phase}</phase>
+                        <goals>
+                            <goal>unpack</goal>
+                        </goals>
+                        <configuration>
+                            <artifactItems>
+                                <artifactItem>
+                                    <groupId>org.broadinstitute.gatk</groupId>
+                                    <artifactId>gatk-engine</artifactId>
+                                    <version>${gatk.version}</version>
+                                    <classifier>example-resources</classifier>
+                                    <type>tar.bz2</type>
+                                    <outputDirectory>${project.build.outputDirectory}</outputDirectory>
+                                </artifactItem>
+                            </artifactItems>
+                        </configuration>
+                    </execution>
+                </executions>
+            </plugin>
+
+            <!-- Generate help text -->
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-javadoc-plugin</artifactId>
+                <version>2.9.1</version>
+                <executions>
+                    <execution>
+                        <id>extract-resource-bundle</id>
+                        <goals>
+                            <goal>javadoc</goal>
+                        </goals>
+                        <phase>prepare-package</phase>
+                        <configuration>
+                            <doclet>org.broadinstitute.gatk.utils.help.ResourceBundleExtractorDoclet</doclet>
+                            <!-- Required as doclet uses reflection to access classes for documentation, instead of source java-->
+                            <docletPath>${project.build.outputDirectory}</docletPath>
+                            <docletArtifact>
+                                <groupId>org.broadinstitute.gatk</groupId>
+                                <!-- TODO: THIS IS SUPPOSED TO BE GATK-UTILS! -->
+                                <artifactId>gatk-tools-public</artifactId>
+                                <version>${gatk.version}</version>
+                            </docletArtifact>
+                            <maxmemory>2g</maxmemory>
+                            <useStandardDocletOptions>false</useStandardDocletOptions>
+                            <quiet>true</quiet>
+                            <additionalparam>-build-timestamp "${maven.build.timestamp}" -absolute-version "${project.version}" -out ${project.build.outputDirectory}/GATKText.properties</additionalparam>
+                        </configuration>
+                    </execution>
+                </executions>
+            </plugin>
+
+            <!-- Create packaged jar, containing only your walker and required classes -->
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-shade-plugin</artifactId>
+                <version>2.1</version>
+                <executions>
+                    <execution>
+                        <phase>${gatk.shade.phase}</phase>
+                        <goals>
+                            <goal>shade</goal>
+                        </goals>
+                        <configuration>
+                            <minimizeJar>true</minimizeJar>
+                            <!-- Explicitly include classes loaded via reflection from artifacts below -->
+                            <filters>
+                                <filter>
+                                    <artifact>commons-logging:commons-logging</artifact>
+                                    <includes>
+                                        <include>**</include>
+                                    </includes>
+                                </filter>
+                                <filter>
+                                    <artifact>samtools:htsjdk</artifact>
+                                    <includes>
+                                        <include>**</include>
+                                    </includes>
+                                </filter>
+                            </filters>
+                            <!-- Stop shade from trying to unzip these indirect dependencies -->
+                            <artifactSet>
+                                <excludes>
+                                    <exclude>org.broadinstitute.gatk:gsalib:tar.gz:*</exclude>
+                                    <exclude>org.broadinstitute.gatk:*:tar.bz2:example-resources</exclude>
+                                </excludes>
+                            </artifactSet>
+                            <transformers>
+                                <!-- Set the main class to the GATK -->
+                                <transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
+                                    <mainClass>org.broadinstitute.gatk.engine.CommandLineGATK</mainClass>
+                                </transformer>
+                                <!-- Include and append to the existing gatk help text in GATKText.properties -->
+                                <transformer implementation="org.apache.maven.plugins.shade.resource.AppendingTransformer">
+                                    <resource>GATKText.properties</resource>
+                                </transformer>
+                            </transformers>
+                        </configuration>
+                    </execution>
+                </executions>
+            </plugin>
+
+            <!-- surefire runs fast, small (aka unit) tests -->
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-surefire-plugin</artifactId>
+                <version>2.16</version>
+                <configuration>
+                    <!-- See explicit executions below -->
+                    <skip>true</skip>
+                    <failIfNoTests>false</failIfNoTests>
+                    <!-- Pass various system properties -->
+                    <systemPropertyVariables>
+                        <gatkdir>${gatk.basedir}</gatkdir>
+                        <java.io.tmpdir>${java.io.tmpdir}</java.io.tmpdir>
+                    </systemPropertyVariables>
+                </configuration>
+                <executions>
+                    <!-- Disable maven default execution -->
+                    <execution>
+                        <id>default-test</id>
+                        <phase>none</phase>
+                    </execution>
+                    <execution>
+                        <id>unit-tests</id>
+                        <goals>
+                            <goal>test</goal>
+                        </goals>
+                        <configuration>
+                            <skip>${gatk.unittests.skipped}</skip>
+                            <includes>
+                                <include>**/*UnitTest.class</include>
+                            </includes>
+                            <systemPropertyVariables>
+                                <testType>unit</testType>
+                            </systemPropertyVariables>
+                        </configuration>
+                    </execution>
+                </executions>
+            </plugin>
+
+            <!-- failsafe runs all other tests that may take longer, and may require pre/post test setup and teardown -->
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-failsafe-plugin</artifactId>
+                <version>2.16</version>
+                <configuration>
+                    <!-- See explicit executions below -->
+                    <skip>true</skip>
+                    <failIfNoTests>false</failIfNoTests>
+                    <!-- Pass various system properties -->
+                    <systemPropertyVariables>
+                        <gatkdir>${gatk.basedir}</gatkdir>
+                        <java.io.tmpdir>${java.io.tmpdir}</java.io.tmpdir>
+                    </systemPropertyVariables>
+                </configuration>
+                <executions>
+                    <execution>
+                        <id>integration-tests</id>
+                        <goals>
+                            <goal>integration-test</goal>
+                            <goal>verify</goal>
+                        </goals>
+                        <!-- run integration tests -->
+                        <configuration>
+                            <skip>${gatk.integrationtests.skipped}</skip>
+                            <includes>
+                                <include>**/*IntegrationTest.class</include>
+                            </includes>
+                            <systemPropertyVariables>
+                                <testType>integrationtest</testType>
+                            </systemPropertyVariables>
+                        </configuration>
+                    </execution>
+                </executions>
+            </plugin>
+        </plugins>
+    </build>
+
+    <profiles>
+        <profile>
+            <id>packagetests-enabled</id>
+            <activation>
+                <property>
+                    <name>gatk.packagetests.enabled</name>
+                    <value>true</value>
+                </property>
+            </activation>
+            <properties>
+                <gatk.jar.phase>none</gatk.jar.phase>
+                <gatk.unpack.phase>none</gatk.unpack.phase>
+                <gatk.shade.phase>none</gatk.shade.phase>
+            </properties>
+        </profile>
+    </profiles>
+
+</project>
diff --git a/public/external-example/src/main/java/org/mycompany/app/MyExampleWalker.java b/public/external-example/src/main/java/org/mycompany/app/MyExampleWalker.java
new file mode 100644
index 0000000..1834c4a
--- /dev/null
+++ b/public/external-example/src/main/java/org/mycompany/app/MyExampleWalker.java
@@ -0,0 +1,56 @@
+/*
+* Copyright (c) 2012 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 org.mycompany.app;
+
+import org.broadinstitute.gatk.utils.commandline.Output;
+import org.broadinstitute.gatk.engine.contexts.AlignmentContext;
+import org.broadinstitute.gatk.engine.contexts.ReferenceContext;
+import org.broadinstitute.gatk.engine.refdata.RefMetaDataTracker;
+import org.broadinstitute.gatk.engine.walkers.LocusWalker;
+
+import java.io.PrintStream;
+
+/**
+ * An example walker that looks surprisingly like CountLoci.
+ */
+public class MyExampleWalker extends LocusWalker<Integer, Long> {
+    @Output
+    PrintStream out;
+
+    public Integer map(RefMetaDataTracker tracker, ReferenceContext ref, AlignmentContext context) {
+        return 1;
+    }
+
+    public Long reduceInit() { return 0l; }
+
+    public Long reduce(Integer value, Long sum) {
+        return value + sum;
+    }
+
+    public void onTraversalDone( Long c ) {
+        out.println(c);
+    }
+}
diff --git a/public/external-example/src/test/java/org/mycompany/app/MyExampleWalkerIntegrationTest.java b/public/external-example/src/test/java/org/mycompany/app/MyExampleWalkerIntegrationTest.java
new file mode 100644
index 0000000..ee625a4
--- /dev/null
+++ b/public/external-example/src/test/java/org/mycompany/app/MyExampleWalkerIntegrationTest.java
@@ -0,0 +1,54 @@
+/*
+* Copyright (c) 2012 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 org.mycompany.app;
+
+import org.broadinstitute.gatk.engine.walkers.WalkerTest;
+import org.testng.annotations.Test;
+
+import java.io.File;
+import java.net.URISyntaxException;
+import java.net.URL;
+import java.util.Collections;
+import java.util.MissingResourceException;
+
+/**
+ * NOTE: Currently the testing infrastructure for walkers does not support running outside the Broad.
+ */
+public class MyExampleWalkerIntegrationTest extends WalkerTest {
+    @Test
+    public void testMyExampleWalker() throws URISyntaxException {
+        String gatk_args = String.format("-T MyExampleWalker -I %s -R %s", getResource("/exampleBAM.bam"), getResource("/exampleFASTA.fasta"));
+        WalkerTestSpec spec = new WalkerTestSpec(gatk_args, Collections.<String>emptyList());
+        executeTest("Testing count on the example bam", spec);
+    }
+
+    private File getResource(String path) throws URISyntaxException {
+        URL resourceUrl = getClass().getResource(path);
+        if (resourceUrl == null)
+            throw new MissingResourceException("Resource not found: " + path, getClass().getSimpleName(), path);
+        return new File(resourceUrl.toURI());
+    }
+}
diff --git a/public/external-example/src/test/java/org/mycompany/app/MyExampleWalkerUnitTest.java b/public/external-example/src/test/java/org/mycompany/app/MyExampleWalkerUnitTest.java
new file mode 100644
index 0000000..56335f1
--- /dev/null
+++ b/public/external-example/src/test/java/org/mycompany/app/MyExampleWalkerUnitTest.java
@@ -0,0 +1,41 @@
+/*
+* Copyright (c) 2012 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 org.mycompany.app;
+
+import org.broadinstitute.gatk.utils.BaseTest;
+import org.testng.Assert;
+import org.testng.annotations.Test;
+
+/**
+ * NOTE: Currently the testing infrastructure for walkers does not support running outside the Broad.
+ */
+public class MyExampleWalkerUnitTest extends BaseTest {
+    @Test
+    public void testMyExampleWalker() {
+        MyExampleWalker walker = new MyExampleWalker();
+        Assert.assertEquals((long)walker.reduce(1, 1L), 2L);
+    }
+}
diff --git a/public/gatk-engine/pom.xml b/public/gatk-engine/pom.xml
new file mode 100644
index 0000000..15ba06e
--- /dev/null
+++ b/public/gatk-engine/pom.xml
@@ -0,0 +1,94 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+    <modelVersion>4.0.0</modelVersion>
+
+    <parent>
+        <groupId>org.broadinstitute.gatk</groupId>
+        <artifactId>gatk-aggregator</artifactId>
+        <version>3.3</version>
+        <relativePath>../..</relativePath>
+    </parent>
+
+    <artifactId>gatk-engine</artifactId>
+    <packaging>jar</packaging>
+    <name>GATK Engine</name>
+
+    <properties>
+        <gatk.basedir>${project.basedir}/../..</gatk.basedir>
+        <gatk.packagetests.artifactId>gatk-package-distribution</gatk.packagetests.artifactId>
+    </properties>
+
+    <dependencies>
+        <dependency>
+            <groupId>${project.groupId}</groupId>
+            <artifactId>gatk-utils</artifactId>
+            <version>${project.version}</version>
+        </dependency>
+
+        <dependency>
+            <groupId>com.google.caliper</groupId>
+            <artifactId>caliper</artifactId>
+            <scope>test</scope>
+        </dependency>
+    </dependencies>
+
+    <build>
+        <plugins>
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-assembly-plugin</artifactId>
+                <executions>
+                    <execution>
+                        <id>example-resources</id>
+                        <phase>${gatk.generate-resources.phase}</phase>
+                    </execution>
+                </executions>
+            </plugin>
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-resources-plugin</artifactId>
+                <executions>
+                    <execution>
+                        <id>copy-resource-bundle-log4j</id>
+                        <phase>prepare-package</phase>
+                    </execution>
+                </executions>
+            </plugin>
+            <!--
+            TODO: Refactor ResourceBundleExtractorDoclet.isWalker() and move the RBED to utils.
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-javadoc-plugin</artifactId>
+                <executions>
+                    <execution>
+                        <id>extract-resource-bundle</id>
+                        <phase>prepare-package</phase>
+                    </execution>
+                </executions>
+            </plugin>
+            -->
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-invoker-plugin</artifactId>
+                <executions>
+                    <execution>
+                        <id>package-unittests</id>
+                    </execution>
+                    <execution>
+                        <id>package-integrationtests</id>
+                    </execution>
+                    <execution>
+                        <id>package-largescaletests</id>
+                    </execution>
+                    <execution>
+                        <id>package-knowledgebasetests</id>
+                    </execution>
+                    <execution>
+                        <id>package-queuetests</id>
+                    </execution>
+                </executions>
+            </plugin>
+        </plugins>
+    </build>
+
+</project>
diff --git a/public/gatk-engine/src/main/assembly/example-resources.xml b/public/gatk-engine/src/main/assembly/example-resources.xml
new file mode 100644
index 0000000..5a5fc66
--- /dev/null
+++ b/public/gatk-engine/src/main/assembly/example-resources.xml
@@ -0,0 +1,37 @@
+<assembly xmlns="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.2" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.2 http://maven.apache.org/xsd/assembly-1.1.2.xsd">
+    <id>example-resources</id>
+    <formats>
+        <format>tar.bz2</format>
+    </formats>
+    <includeBaseDirectory>false</includeBaseDirectory>
+    <fileSets>
+        <fileSet>
+            <directory>${project.build.sourceDirectory}/org/broadinstitute/gatk/gatk/walkers/qc</directory>
+            <outputDirectory>.</outputDirectory>
+            <includes>
+                <include>Pileup.java</include>
+                <include>CountLoci.java</include>
+                <include>CountReads.java</include>
+                <include>CheckPileup.java</include>
+            </includes>
+        </fileSet>
+        <fileSet>
+            <directory>${project.build.sourceDirectory}/org/broadinstitute/gatk/gatk/walkers/readutils</directory>
+            <outputDirectory>.</outputDirectory>
+            <includes>
+                <include>PrintReads.java</include>
+            </includes>
+        </fileSet>
+        <fileSet>
+            <directory>src/test/resources</directory>
+            <outputDirectory>.</outputDirectory>
+            <includes>
+                <include>exampleBAM.bam</include>
+                <include>exampleBAM.bam.bai</include>
+                <include>exampleFASTA.fasta</include>
+                <include>exampleFASTA.fasta.fai</include>
+                <include>exampleFASTA.dict</include>
+            </includes>
+        </fileSet>
+    </fileSets>
+</assembly>
diff --git a/public/gatk-engine/src/main/java/org/broadinstitute/gatk/engine/ReadMetrics.java b/public/gatk-engine/src/main/java/org/broadinstitute/gatk/engine/ReadMetrics.java
new file mode 100644
index 0000000..0f00bd6
--- /dev/null
+++ b/public/gatk-engine/src/main/java/org/broadinstitute/gatk/engine/ReadMetrics.java
@@ -0,0 +1,121 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.engine;
+
+import htsjdk.samtools.filter.SamRecordFilter;
+import org.broadinstitute.gatk.utils.exceptions.ReviewedGATKException;
+
+import java.util.HashMap;
+import java.util.Map;
+import java.util.TreeMap;
+
+/**
+ * Holds a bunch of basic information about the traversal.
+ */
+public class ReadMetrics implements Cloneable {
+    // Number of records (loci, reads) we've processed
+    private long nRecords;
+    // How many reads have we processed, along with those skipped for various reasons
+    private long nReads;
+
+    // keep track of filtered records by filter type (class)
+    private Map<String, Long> filterCounter = new HashMap<>();
+
+    /**
+     * Combines these metrics with a set of other metrics, storing the results in this class.
+     * @param metrics The metrics to fold into this class.
+     */
+    public synchronized void incrementMetrics(ReadMetrics metrics) {
+        nRecords += metrics.nRecords;
+        nReads += metrics.nReads;
+        for(Map.Entry<String, Long> counterEntry: metrics.filterCounter.entrySet()) {
+            final String counterType = counterEntry.getKey();
+            final long newValue = (filterCounter.containsKey(counterType) ? filterCounter.get(counterType) : 0) + counterEntry.getValue();
+            filterCounter.put(counterType, newValue);
+        }
+    }
+
+    /**
+     * Create a copy of the given read metrics.
+     * @return a non-null clone
+     */
+    public ReadMetrics clone() {
+        ReadMetrics newMetrics;
+        try {
+            newMetrics = (ReadMetrics)super.clone();
+        }
+        catch(CloneNotSupportedException ex) {
+            throw new ReviewedGATKException("Unable to clone runtime metrics",ex);
+        }
+        newMetrics.nRecords = nRecords;
+        newMetrics.nReads = nReads;
+        newMetrics.filterCounter = new HashMap<>(filterCounter);
+
+        return newMetrics;
+    }
+
+
+    public void setFilterCount(final String filter, final long count) {
+        filterCounter.put(filter, count);
+    }
+
+    public Map<String,Long> getCountsByFilter() {
+        return new TreeMap<>(filterCounter);
+    }
+
+    /**
+     * Gets the number of 'iterations' (one call of filter/map/reduce sequence) performed.
+     * @return The number of iterations completed.
+     */
+    public long getNumIterations() {
+        return nRecords;
+    }
+
+    /**
+     * Increments the number of 'iterations' (one call of filter/map/reduce sequence) completed.
+     */
+    public void incrementNumIterations(final long by) {
+        nRecords += by;
+    }
+
+    /**
+     * Increments the number of 'iterations' (one call of filter/map/reduce sequence) completed.
+     */
+    public void incrementNumIterations() {
+        incrementNumIterations(1);
+    }
+
+    public long getNumReadsSeen() {
+        return nReads;
+    }
+
+    /**
+     * Increments the number of reads seen in the course of this run.
+     */
+    public void incrementNumReadsSeen() {
+        nReads++;
+    }
+}
diff --git a/public/gatk-engine/src/main/java/org/broadinstitute/gatk/engine/package-info.java b/public/gatk-engine/src/main/java/org/broadinstitute/gatk/engine/package-info.java
new file mode 100644
index 0000000..bd34a17
--- /dev/null
+++ b/public/gatk-engine/src/main/java/org/broadinstitute/gatk/engine/package-info.java
@@ -0,0 +1,26 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.engine;
\ No newline at end of file
diff --git a/public/gatk-engine/src/test/resources/exampleBAM.bam b/public/gatk-engine/src/test/resources/exampleBAM.bam
new file mode 100644
index 0000000..319dd1a
Binary files /dev/null and b/public/gatk-engine/src/test/resources/exampleBAM.bam differ
diff --git a/public/gatk-engine/src/test/resources/exampleBAM.bam.bai b/public/gatk-engine/src/test/resources/exampleBAM.bam.bai
new file mode 100644
index 0000000..052ac61
Binary files /dev/null and b/public/gatk-engine/src/test/resources/exampleBAM.bam.bai differ
diff --git a/public/gatk-engine/src/test/resources/exampleBAM.simple.bai b/public/gatk-engine/src/test/resources/exampleBAM.simple.bai
new file mode 100644
index 0000000..2d8268b
Binary files /dev/null and b/public/gatk-engine/src/test/resources/exampleBAM.simple.bai differ
diff --git a/public/gatk-engine/src/test/resources/exampleBAM.simple.bam b/public/gatk-engine/src/test/resources/exampleBAM.simple.bam
new file mode 100644
index 0000000..c3eb7ae
Binary files /dev/null and b/public/gatk-engine/src/test/resources/exampleBAM.simple.bam differ
diff --git a/public/gatk-engine/src/test/resources/exampleDBSNP.vcf b/public/gatk-engine/src/test/resources/exampleDBSNP.vcf
new file mode 100644
index 0000000..9e7e96f
--- /dev/null
+++ b/public/gatk-engine/src/test/resources/exampleDBSNP.vcf
@@ -0,0 +1,282 @@
+##fileformat=VCFv4.1
+##FILTER=<ID=NC,Description="Inconsistent Genotype Submission For At Least One Sample">
+##INFO=<ID=AF,Number=.,Type=Float,Description="Allele Frequency, for each ALT allele, in the same order as listed">
+##INFO=<ID=ASP,Number=0,Type=Flag,Description="Is Assembly specific. This is set if the variant only maps to one assembly">
+##INFO=<ID=ASS,Number=0,Type=Flag,Description="In acceptor splice site FxnCode = 73">
+##INFO=<ID=CDA,Number=0,Type=Flag,Description="Variation is interrogated in a clinical diagnostic assay">
+##INFO=<ID=CFL,Number=0,Type=Flag,Description="Has Assembly conflict. This is for weight 1 and 2 variant that maps to different chromosomes on different assemblies.">
+##INFO=<ID=CLN,Number=0,Type=Flag,Description="Variant is Clinical(LSDB,OMIM,TPA,Diagnostic)">
+##INFO=<ID=DSS,Number=0,Type=Flag,Description="In donor splice-site FxnCode = 75">
+##INFO=<ID=G5,Number=0,Type=Flag,Description=">5% minor allele frequency in 1+ populations">
+##INFO=<ID=G5A,Number=0,Type=Flag,Description=">5% minor allele frequency in each and all populations">
+##INFO=<ID=GCF,Number=0,Type=Flag,Description="Has Genotype Conflict Same (rs, ind), different genotype.  N/N is not included.">
+##INFO=<ID=GENEINFO,Number=1,Type=String,Description="Pairs each of gene symbol:gene id.  The gene symbol and id are delimited by a colon (:) and each pair is delimited by a vertical bar (|)">
+##INFO=<ID=GMAF,Number=1,Type=Float,Description="Global Minor Allele Frequency [0, 0.5]; global population is 1000GenomesProject phase 1 genotype data from 629 individuals, released in the 08-04-2010 dataset">
+##INFO=<ID=GNO,Number=0,Type=Flag,Description="Genotypes available. The variant has individual genotype (in SubInd table).">
+##INFO=<ID=HD,Number=0,Type=Flag,Description="Marker is on high density genotyping kit (50K density or greater).  The variant may have phenotype associations present in dbGaP.">
+##INFO=<ID=INT,Number=0,Type=Flag,Description="In Intron FxnCode = 6">
+##INFO=<ID=KGPROD,Number=0,Type=Flag,Description="1000 Genome production phase">
+##INFO=<ID=KGPilot1,Number=0,Type=Flag,Description="1000 Genome discovery(pilot1) 2009">
+##INFO=<ID=KGPilot123,Number=0,Type=Flag,Description="1000 Genome discovery all pilots 2010(1,2,3)">
+##INFO=<ID=KGVAL,Number=0,Type=Flag,Description="1000 Genome validated by second method">
+##INFO=<ID=LSD,Number=0,Type=Flag,Description="Submitted from a locus-specific database">
+##INFO=<ID=MTP,Number=0,Type=Flag,Description="Microattribution/third-party annotation(TPA:GWAS,PAGE)">
+##INFO=<ID=MUT,Number=0,Type=Flag,Description="Is mutation (journal citation, explicit fact): a low frequency variation that is cited in journal and other reputable sources">
+##INFO=<ID=NOC,Number=0,Type=Flag,Description="Contig allele not present in variant allele list. The reference sequence allele at the mapped position is not present in the variant allele list, adjusted for orientation.">
+##INFO=<ID=NOV,Number=0,Type=Flag,Description="Rs cluster has non-overlapping allele sets. True when rs set has more than 2 alleles from different submissions and these sets share no alleles in common.">
+##INFO=<ID=NS,Number=1,Type=Integer,Description="Number of Samples With Data">
+##INFO=<ID=NSF,Number=0,Type=Flag,Description="Has non-synonymous frameshift A coding region variation where one allele in the set changes all downstream amino acids. FxnClass = 44">
+##INFO=<ID=NSM,Number=0,Type=Flag,Description="Has non-synonymous missense A coding region variation where one allele in the set changes protein peptide. FxnClass = 42">
+##INFO=<ID=NSN,Number=0,Type=Flag,Description="Has non-synonymous nonsense A coding region variation where one allele in the set changes to STOP codon (TER). FxnClass = 41">
+##INFO=<ID=OM,Number=0,Type=Flag,Description="Has OMIM/OMIA">
+##INFO=<ID=OTH,Number=0,Type=Flag,Description="Has other variant with exactly the same set of mapped positions on NCBI refernce assembly.">
+##INFO=<ID=PH1,Number=0,Type=Flag,Description="Phase 1 genotyped: filtered, non-redundant">
+##INFO=<ID=PH2,Number=0,Type=Flag,Description="Phase 2 genotyped: filtered, non-redundant">
+##INFO=<ID=PH3,Number=0,Type=Flag,Description="Phase 3 genotyped: filtered, non-redundant">
+##INFO=<ID=PM,Number=0,Type=Flag,Description="Variant is Precious(Clinical,Pubmed Cited)">
+##INFO=<ID=PMC,Number=0,Type=Flag,Description="Links exist to PubMed Central article">
+##INFO=<ID=R3,Number=0,Type=Flag,Description="In 3' gene region FxnCode = 13">
+##INFO=<ID=R5,Number=0,Type=Flag,Description="In 5' gene region FxnCode = 15">
+##INFO=<ID=REF,Number=0,Type=Flag,Description="Has reference A coding region variation where one allele in the set is identical to the reference sequence. FxnCode = 8">
+##INFO=<ID=RSPOS,Number=1,Type=Integer,Description="Chr position reported in dbSNP">
+##INFO=<ID=RV,Number=0,Type=Flag,Description="RS orientation is reversed">
+##INFO=<ID=S3D,Number=0,Type=Flag,Description="Has 3D structure - SNP3D table">
+##INFO=<ID=SAO,Number=1,Type=Integer,Description="Variant Allele Origin: 0 - unspecified, 1 - Germline, 2 - Somatic, 3 - Both">
+##INFO=<ID=SCS,Number=1,Type=Integer,Description="Variant Clinical Significance, 0 - unknown, 1 - untested, 2 - non-pathogenic, 3 - probable-non-pathogenic, 4 - probable-pathogenic, 5 - pathogenic, 6 - drug-response, 7 - histocompatibility, 255 - other">
+##INFO=<ID=SLO,Number=0,Type=Flag,Description="Has SubmitterLinkOut - From SNP->SubSNP->Batch.link_out">
+##INFO=<ID=SSR,Number=1,Type=Integer,Description="Variant Suspect Reason Code, 0 - unspecified, 1 - Paralog, 2 - byEST, 3 - Para_EST, 4 - oldAlign, 5 - other">
+##INFO=<ID=SYN,Number=0,Type=Flag,Description="Has synonymous A coding region variation where one allele in the set does not change the encoded amino acid. FxnCode = 3">
+##INFO=<ID=TPA,Number=0,Type=Flag,Description="Provisional Third Party Annotation(TPA) (currently rs from PHARMGKB who will give phenotype data)">
+##INFO=<ID=U3,Number=0,Type=Flag,Description="In 3' UTR Location is in an untranslated region (UTR). FxnCode = 53">
+##INFO=<ID=U5,Number=0,Type=Flag,Description="In 5' UTR Location is in an untranslated region (UTR). FxnCode = 55">
+##INFO=<ID=VC,Number=1,Type=String,Description="Variation Class">
+##INFO=<ID=VLD,Number=0,Type=Flag,Description="Is Validated.  This bit is set if the variant has 2+ minor allele count based on frequency or genotype data.">
+##INFO=<ID=VP,Number=1,Type=String,Description="Variation Property">
+##INFO=<ID=WGT,Number=1,Type=Integer,Description="Weight, 00 - unmapped, 1 - weight 1, 2 - weight 2, 3 - weight 3 or more">
+##INFO=<ID=WTD,Number=0,Type=Flag,Description="Is Withdrawn by submitter If one member ss is withdrawn by submitter, then this bit is set.  If all member ss' are withdrawn, then the rs is deleted to SNPHistory">
+##INFO=<ID=dbSNPBuildID,Number=1,Type=Integer,Description="First dbSNP Build for RS">
+##LeftAlignVariants="analysis_type=LeftAlignVariants input_file=[] read_buffer_size=null phone_home=STANDARD read_filter=[] intervals=null excludeIntervals=null interval_set_rule=UNION interval_merging=ALL reference_sequence=/humgen/gsa-hpprojects/GATK/bundle/current/b37/human_g1k_v37.fasta rodBind=[] nonDeterministicRandomSeed=false downsampling_type=BY_SAMPLE downsample_to_fraction=null downsample_to_coverage=1000 baq=OFF baqGapOpenPenalty=40.0 performanceLog=null useOriginalQualities= [...]
+##contig=<ID=chr1,length=249250621,assembly=b37>
+##phasing=partial
+##reference=GRCh37.3
+##reference=file:///humgen/gsa-hpprojects/GATK/bundle/current/b37/human_g1k_v37.fasta
+##source=dbSNP
+##variationPropertyDocumentationUrl=ftp://ftp.ncbi.nlm.nih.gov/snp/specs/dbSNP_BitField_latest.pdf	
+#CHROM	POS	ID	REF	ALT	QUAL	FILTER	INFO	
+chr1	10144	rs144773400	TA	T	.	PASS	ASP;RSPOS=10145;SAO=0;SSR=0;VC=DIV;VP=050000000004000000000200;WGT=0;dbSNPBuildID=134
+chr1	10228	rs143255646	TA	T	.	PASS	ASP;RSPOS=10229;SAO=0;SSR=0;VC=DIV;VP=050000000004000000000200;WGT=0;dbSNPBuildID=134
+chr1	10234	rs145599635	C	T	.	PASS	ASP;RSPOS=10234;SAO=0;SSR=0;VC=SNV;VP=050000000004000000000100;WGT=0;dbSNPBuildID=134
+chr1	10248	rs148908337	A	T	.	PASS	ASP;RSPOS=10248;SAO=0;SSR=0;VC=SNV;VP=050000000004000000000100;WGT=0;dbSNPBuildID=134
+chr1	10254	rs140194106	TA	T	.	PASS	ASP;RSPOS=10255;SAO=0;SSR=0;VC=DIV;VP=050000000004000000000200;WGT=0;dbSNPBuildID=134
+chr1	10291	rs145427775	C	T	.	PASS	ASP;RSPOS=10291;SAO=0;SSR=0;VC=SNV;VP=050000000004000000000100;WGT=0;dbSNPBuildID=134
+chr1	10327	rs112750067	T	C	.	PASS	ASP;GENEINFO=LOC100652771:100652771;RSPOS=10327;SAO=0;SSR=0;VC=SNV;VP=050000000004000000000100;WGT=0;dbSNPBuildID=132
+chr1	10329	rs150969722	AC	A	.	PASS	ASP;RSPOS=10330;SAO=0;SSR=0;VC=DIV;VP=050000000004000000000200;WGT=0;dbSNPBuildID=134
+chr1	10351	rs145072688	CTA	C,CA	.	PASS	ASP;RSPOS=10352;SAO=0;SSR=0;VC=DIV;VP=050000000004000000000200;WGT=0;dbSNPBuildID=134
+chr1	10382	rs147093981	AAC	A,AC	.	PASS	ASP;RSPOS=10383;SAO=0;SSR=0;VC=DIV;VP=050000000004000000000200;WGT=0;dbSNPBuildID=134
+chr1	10433	rs56289060	A	AC	.	PASS	ASP;GENEINFO=LOC100652771:100652771;RSPOS=10433;SAO=0;SSR=0;VC=DIV;VP=050000000004000000000200;WGT=0;dbSNPBuildID=129
+chr1	10439	rs112766696	AC	A	.	PASS	ASP;GENEINFO=LOC100652771:100652771;GNO;RSPOS=10440;SAO=0;SLO;SSR=0;VC=DIV;VP=050100000004000100000200;WGT=0;dbSNPBuildID=132
+chr1	10439	rs138941843	AC	A	.	PASS	ASP;RSPOS=10440;SAO=0;SSR=0;VC=DIV;VP=050000000004000000000200;WGT=0;dbSNPBuildID=134
+chr1	10440	rs112155239	C	A	.	PASS	ASP;GENEINFO=LOC100652771:100652771;RSPOS=10440;SAO=0;SSR=0;VC=SNV;VP=050000000004000000000100;WGT=0;dbSNPBuildID=132
+chr1	10492	rs55998931	C	T	.	PASS	ASP;GENEINFO=LOC100652771:100652771;GMAF=0.0617001828153565;RSPOS=10492;SAO=0;SSR=0;VC=SNV;VLD;VP=050000000004040000000100;WGT=0;dbSNPBuildID=129
+chr1	10519	rs62636508	G	C	.	PASS	ASP;GENEINFO=LOC100652771:100652771;RSPOS=10519;SAO=0;SSR=0;VC=SNV;VP=050000000004000000000100;WGT=0;dbSNPBuildID=129
+chr1	10583	rs58108140	G	A	.	PASS	ASP;GENEINFO=LOC100652771:100652771;GMAF=0.270566727605119;KGPilot123;RSPOS=10583;SAO=0;SSR=0;VC=SNV;VLD;VP=050000000004040010000100;WGT=0;dbSNPBuildID=129
+chr1	10611	rs189107123	C	G	.	PASS	KGPilot123;RSPOS=10611;SAO=0;SSR=0;VC=SNV;VP=050000000000000010000100;WGT=0;dbSNPBuildID=135
+chr1	10828	rs10218492	G	A	.	PASS	ASP;GENEINFO=LOC100652771:100652771;RSPOS=10828;SAO=0;SSR=0;VC=SNV;VP=050000000004000000000100;WGT=0;dbSNPBuildID=119
+chr1	10904	rs10218493	G	A	.	PASS	ASP;GENEINFO=LOC100652771:100652771;GNO;RSPOS=10904;SAO=0;SSR=0;VC=SNV;VP=050000000004000100000100;WGT=0;dbSNPBuildID=119
+chr1	10927	rs10218527	A	G	.	PASS	ASP;GENEINFO=LOC100652771:100652771;RSPOS=10927;SAO=0;SSR=0;VC=SNV;VP=050000000004000000000100;WGT=0;dbSNPBuildID=119
+chr1	10938	rs28853987	G	A	.	PASS	ASP;GENEINFO=LOC100652771:100652771;RSPOS=10938;SAO=0;SSR=0;VC=SNV;VP=050000000004000000000100;WGT=0;dbSNPBuildID=125
+chr1	11014	rs28484712	G	A	.	PASS	ASP;GENEINFO=LOC100652771:100652771;RSPOS=11014;SAO=0;SSR=0;VC=SNV;VP=050000000004000000000100;WGT=0;dbSNPBuildID=125
+chr1	11022	rs28775022	G	A	.	PASS	ASP;GENEINFO=LOC100652771:100652771;RSPOS=11022;SAO=0;SSR=0;VC=SNV;VP=050000000004000000000100;WGT=0;dbSNPBuildID=125
+chr1	11081	rs10218495	G	T	.	PASS	CFL;GENEINFO=LOC100652771:100652771;GNO;RSPOS=11081;SAO=0;SSR=0;VC=SNV;VP=050000000008000100000100;WGT=0;dbSNPBuildID=119
+chr1	11863	rs187669455	C	A	.	PASS	RSPOS=11863;SAO=0;SSR=0;VC=SNV;VP=050000000000000000000100;WGT=0;dbSNPBuildID=135
+chr1	13302	rs180734498	C	T	.	PASS	KGPilot123;RSPOS=13302;SAO=0;SSR=0;VC=SNV;VP=050000000000000010000100;WGT=0;dbSNPBuildID=135
+chr1	13327	rs144762171	G	C	.	PASS	ASP;KGPilot123;RSPOS=13327;SAO=0;SSR=0;VC=SNV;VP=050000000004000010000100;WGT=0;dbSNPBuildID=134
+chr1	13684	rs71260404	C	T	.	PASS	GENEINFO=LOC100652771:100652771;GNO;RSPOS=13684;RV;SAO=0;SLO;SSR=0;VC=SNV;VP=050100000000000100000100;WGT=0;dbSNPBuildID=130
+chr1	13980	rs151276478	T	C	.	PASS	ASP;KGPilot123;RSPOS=13980;SAO=0;SSR=0;VC=SNV;VP=050000000004000010000100;WGT=0;dbSNPBuildID=134
+chr1	14889	rs142444908	G	A	.	PASS	ASP;RSPOS=14889;SAO=0;SSR=0;VC=SNV;VP=050000000004000000000100;WGT=0;dbSNPBuildID=134
+chr1	14907	rs79585140	A	G	.	PASS	GNO;RSPOS=14907;SAO=0;SSR=0;VC=SNV;VLD;VP=050000000000040100000100;WGT=0;dbSNPBuildID=131
+chr1	14930	rs75454623	A	G	.	PASS	GNO;RSPOS=14930;SAO=0;SSR=0;VC=SNV;VLD;VP=050000000000040100000100;WGT=0;dbSNPBuildID=131
+chr1	14976	rs71252251	G	A	.	PASS	ASP;GNO;RSPOS=14976;RV;SAO=0;SLO;SSR=0;VC=SNV;VP=050100000004000100000100;WGT=0;dbSNPBuildID=130
+chr1	15061	rs71268703	T	TG	.	PASS	ASP;GNO;RSPOS=15061;RV;SAO=0;SLO;SSR=0;VC=DIV;VP=050100000004000100000200;WGT=0;dbSNPBuildID=130
+chr1	15118	rs71252250	A	G	.	PASS	ASP;GNO;RSPOS=15118;RV;SAO=0;SLO;SSR=0;VC=SNV;VP=050100000004000100000100;WGT=0;dbSNPBuildID=130
+chr1	15211	rs144718396	T	G	.	PASS	ASP;RSPOS=15211;SAO=0;SSR=0;VC=SNV;VP=050000000004000000000100;WGT=0;dbSNPBuildID=134
+chr1	15211	rs78601809	T	G	.	PASS	ASP;GNO;RSPOS=15211;SAO=0;SSR=0;VC=SNV;VLD;VP=050000000004040100000100;WGT=0;dbSNPBuildID=131
+chr1	16257	rs78588380	G	C	.	PASS	ASP;GNO;RSPOS=16257;SAO=0;SSR=0;VC=SNV;VP=050000000004000100000100;WGT=0;dbSNPBuildID=131
+chr1	16378	rs148220436	T	C	.	PASS	ASP;RSPOS=16378;SAO=0;SSR=0;VC=SNV;VP=050000000004000000000100;WGT=0;dbSNPBuildID=134
+chr1	16495	rs141130360	G	C	.	PASS	ASP;RSPOS=16495;SAO=0;SSR=0;VC=SNV;VP=050000000004000000000100;WGT=0;dbSNPBuildID=134
+chr1	16497	rs150723783	A	G	.	PASS	ASP;RSPOS=16497;SAO=0;SSR=0;VC=SNV;VP=050000000004000000000100;WGT=0;dbSNPBuildID=134
+chr1	17519	rs192890528	G	T	.	PASS	RSPOS=17519;SAO=0;SSR=0;VC=SNV;VP=050000000000000000000100;WGT=0;dbSNPBuildID=135
+chr1	19226	rs138930629	T	A	.	PASS	ASP;RSPOS=19226;SAO=0;SSR=0;VC=SNV;VP=050000000004000000000100;WGT=0;dbSNPBuildID=134
+chr1	20141	rs56336884	G	A	.	PASS	HD;RSPOS=20141;SAO=0;SLO;SSR=0;VC=SNV;VP=050100000000000400000100;WGT=0;dbSNPBuildID=129
+chr1	20144	rs143346096	G	A	.	PASS	ASP;RSPOS=20144;SAO=0;SSR=0;VC=SNV;VP=050000000004000000000100;WGT=0;dbSNPBuildID=134
+chr1	20206	rs71262675	C	T	.	PASS	GNO;RSPOS=20206;RV;SAO=0;SLO;SSR=0;VC=SNV;VP=050100000000000100000100;WGT=0;dbSNPBuildID=130
+chr1	20245	rs71262674	G	A	.	PASS	GMAF=0.256398537477148;GNO;RSPOS=20245;RV;SAO=0;SLO;SSR=0;VC=SNV;VP=050100000000000100000100;WGT=0;dbSNPBuildID=130
+chr1	20304	rs71262673	G	C	.	PASS	GMAF=0.338208409506399;GNO;RSPOS=20304;RV;SAO=0;SLO;SSR=0;VC=SNV;VP=050100000000000100000100;WGT=0;dbSNPBuildID=130
+chr1	26999	rs147506580	A	G	.	PASS	ASP;RSPOS=26999;SAO=0;SSR=0;VC=SNV;VP=050000000004000000000100;WGT=0;dbSNPBuildID=134
+chr1	29436	rs2462493	G	A	.	PASS	GNO;RSPOS=29436;SAO=0;SSR=0;VC=SNV;VP=050000000000000100000100;WGT=0;dbSNPBuildID=100
+chr1	30923	rs140337953	G	T	.	PASS	ASP;KGPilot123;RSPOS=30923;SAO=0;SSR=0;VC=SNV;VP=050000000004000010000100;WGT=0;dbSNPBuildID=134
+chr1	33487	rs77459554	C	T	.	PASS	ASP;GNO;RSPOS=33487;SAO=0;SSR=0;VC=SNV;VP=050000000004000100000100;WGT=0;dbSNPBuildID=131
+chr1	33495	rs75468675	C	T	.	PASS	ASP;GNO;RSPOS=33495;SAO=0;SSR=0;VC=SNV;VLD;VP=050000000004040100000100;WGT=0;dbSNPBuildID=131
+chr1	33505	rs75627161	T	C	.	PASS	ASP;GNO;RSPOS=33505;SAO=0;SSR=0;VC=SNV;VLD;VP=050000000004040100000100;WGT=0;dbSNPBuildID=131
+chr1	33508	rs75609629	A	T	.	PASS	ASP;GNO;RSPOS=33508;SAO=0;SSR=0;VC=SNV;VLD;VP=050000000004040100000100;WGT=0;dbSNPBuildID=131
+chr1	33521	rs76098219	T	A	.	PASS	GNO;RSPOS=33521;SAO=0;SSR=0;VC=SNV;VLD;VP=050000000000040100000100;WGT=0;dbSNPBuildID=131
+chr1	33593	rs557585	G	A	.	PASS	RSPOS=33593;SAO=0;SSR=0;VC=SNV;VP=050000000000000000000100;WGT=0;dbSNPBuildID=83
+chr1	33648	rs62028204	G	T	.	PASS	RSPOS=33648;RV;SAO=0;SSR=0;VC=SNV;VP=050000000000000000000100;WGT=0;dbSNPBuildID=129
+chr1	33656	rs113821789	T	C	.	PASS	RSPOS=33656;RV;SAO=0;SSR=0;VC=SNV;VP=050000000000000000000100;WGT=0;dbSNPBuildID=132
+chr1	51476	rs187298206	T	C	.	PASS	KGPilot123;RSPOS=51476;SAO=0;SSR=0;VC=SNV;VP=050000000000000010000100;WGT=0;dbSNPBuildID=135
+chr1	51479	rs116400033	T	A	.	PASS	ASP;G5;G5A;GMAF=0.113802559414991;KGPilot123;RSPOS=51479;SAO=0;SSR=0;VC=SNV;VLD;VP=050000000004070010000100;WGT=0;dbSNPBuildID=132
+chr1	51803	rs62637812	T	C	.	PASS	GMAF=0.468921389396709;RSPOS=51803;SAO=0;SSR=0;VC=SNV;VLD;VP=050000000000040000000100;WGT=0;dbSNPBuildID=129
+chr1	51898	rs76402894	C	A	.	PASS	GMAF=0.0731261425959781;GNO;RSPOS=51898;SAO=0;SSR=0;VC=SNV;VP=050000000000000100000100;WGT=0;dbSNPBuildID=131
+chr1	51914	rs190452223	T	G	.	PASS	KGPilot123;RSPOS=51914;SAO=0;SSR=0;VC=SNV;VP=050000000000000010000100;WGT=0;dbSNPBuildID=135
+chr1	51928	rs78732933	G	A	.	PASS	GNO;RSPOS=51928;SAO=0;SSR=0;VC=SNV;VP=050000000000000100000100;WGT=0;dbSNPBuildID=131
+chr1	51935	rs181754315	C	T	.	PASS	KGPilot123;RSPOS=51935;SAO=0;SSR=0;VC=SNV;VP=050000000000000010000100;WGT=0;dbSNPBuildID=135
+chr1	51954	rs185832753	G	C	.	PASS	KGPilot123;RSPOS=51954;SAO=0;SSR=0;VC=SNV;VP=050000000000000010000100;WGT=0;dbSNPBuildID=135
+chr1	52058	rs62637813	G	C	.	PASS	GMAF=0.0342778793418647;KGPilot123;RSPOS=52058;SAO=0;SSR=1;VC=SNV;VLD;VP=050000000000040010000140;WGT=0;dbSNPBuildID=129
+chr1	52144	rs190291950	T	A	.	PASS	KGPilot123;RSPOS=52144;SAO=0;SSR=0;VC=SNV;VP=050000000000000010000100;WGT=0;dbSNPBuildID=135
+chr1	52238	rs150021059	T	G	.	PASS	ASP;KGPilot123;RSPOS=52238;SAO=0;SSR=0;VC=SNV;VP=050000000004000010000100;WGT=0;dbSNPBuildID=134
+chr1	54353	rs140052487	C	A	.	PASS	ASP;KGPilot123;RSPOS=54353;SAO=0;SSR=0;VC=SNV;VP=050000000004000010000100;WGT=0;dbSNPBuildID=134
+chr1	54421	rs146477069	A	G	.	PASS	ASP;KGPilot123;RSPOS=54421;SAO=0;SSR=0;VC=SNV;VP=050000000004000010000100;WGT=0;dbSNPBuildID=134
+chr1	54490	rs141149254	G	A	.	PASS	ASP;KGPilot123;RSPOS=54490;SAO=0;SSR=0;VC=SNV;VP=050000000004000010000100;WGT=0;dbSNPBuildID=134
+chr1	54676	rs2462492	C	T	.	PASS	ASP;GMAF=0.191956124314442;GNO;HD;KGPilot123;RSPOS=54676;SAO=0;SSR=0;VC=SNV;VLD;VP=050000000004040510000100;WGT=0;dbSNPBuildID=100
+chr1	54753	rs143174675	T	G	.	PASS	ASP;KGPilot123;RSPOS=54753;SAO=0;SSR=0;VC=SNV;VP=050000000004000010000100;WGT=0;dbSNPBuildID=134
+chr1	54788	rs59861892	CC	C,CCT	.	PASS	ASP;RSPOS=54789;SAO=0;SSR=0;VC=DIV;VP=050000000004000000000200;WGT=0;dbSNPBuildID=129
+chr1	54795	rs58014817	T	A	.	PASS	ASP;RSPOS=54795;SAO=0;SSR=0;VC=SNV;VP=050000000004000000000100;WGT=0;dbSNPBuildID=129
+chr1	55164	rs3091274	C	A	.	PASS	G5;G5A;GMAF=0.145338208409506;GNO;KGPilot123;RSPOS=55164;SAO=0;SLO;SSR=0;VC=SNV;VP=050100000000030110000100;WGT=0;dbSNPBuildID=103
+chr1	55299	rs10399749	C	T	.	PASS	G5;G5A;GMAF=0.278793418647166;GNO;KGPilot123;PH2;RSPOS=55299;SAO=0;SLO;SSR=0;VC=SNV;VP=050100000000030112000100;WGT=0;dbSNPBuildID=119
+chr1	55302	rs3091273	C	T	.	PASS	RSPOS=55302;SAO=0;SSR=0;VC=SNV;VP=050000000000000000000100;WGT=0;dbSNPBuildID=103
+chr1	55313	rs182462964	A	T	.	PASS	KGPilot123;RSPOS=55313;SAO=0;SSR=0;VC=SNV;VP=050000000000000010000100;WGT=0;dbSNPBuildID=135
+chr1	55322	rs3107974	C	T	.	PASS	RSPOS=55322;SAO=0;SSR=0;VC=SNV;VP=050000000000000000000100;WGT=0;dbSNPBuildID=103
+chr1	55326	rs3107975	T	C	.	PASS	GNO;HD;KGPilot123;RSPOS=55326;SAO=0;SSR=0;VC=SNV;VP=050000000000000510000100;WGT=0;dbSNPBuildID=103
+chr1	55330	rs185215913	G	A	.	PASS	KGPilot123;RSPOS=55330;SAO=0;SSR=0;VC=SNV;VP=050000000000000010000100;WGT=0;dbSNPBuildID=135
+chr1	55367	rs190850374	G	A	.	PASS	KGPilot123;RSPOS=55367;SAO=0;SSR=0;VC=SNV;VP=050000000000000010000100;WGT=0;dbSNPBuildID=135
+chr1	55388	rs182711216	C	T	.	PASS	KGPilot123;RSPOS=55388;SAO=0;SSR=0;VC=SNV;VP=050000000000000010000100;WGT=0;dbSNPBuildID=135
+chr1	55394	rs2949420	T	A	.	PASS	GNO;KGPilot123;PH2;RSPOS=55394;SAO=0;SSR=0;VC=SNV;VP=050000000000000112000100;WGT=0;dbSNPBuildID=101
+chr1	55416	rs193242050	G	A	.	PASS	KGPilot123;RSPOS=55416;SAO=0;SSR=0;VC=SNV;VP=050000000000000010000100;WGT=0;dbSNPBuildID=135
+chr1	55427	rs183189405	T	C	.	PASS	KGPilot123;RSPOS=55427;SAO=0;SSR=0;VC=SNV;VP=050000000000000010000100;WGT=0;dbSNPBuildID=135
+chr1	55545	rs28396308	C	T	.	PASS	GNO;RSPOS=55545;SAO=0;SSR=0;VC=SNV;VP=050000000000000100000100;WGT=0;dbSNPBuildID=125
+chr1	55816	rs187434873	G	A	.	PASS	KGPilot123;RSPOS=55816;SAO=0;SSR=0;VC=SNV;VP=050000000000000010000100;WGT=0;dbSNPBuildID=135
+chr1	55850	rs191890754	C	G	.	PASS	KGPilot123;RSPOS=55850;SAO=0;SSR=0;VC=SNV;VP=050000000000000010000100;WGT=0;dbSNPBuildID=135
+chr1	55852	rs184233019	G	C	.	PASS	KGPilot123;RSPOS=55852;SAO=0;SSR=0;VC=SNV;VP=050000000000000010000100;WGT=0;dbSNPBuildID=135
+chr1	56644	rs143342222	A	C	.	PASS	ASP;KGPilot123;RSPOS=56644;SAO=0;SSR=0;VC=SNV;VP=050000000004000010000100;WGT=0;dbSNPBuildID=134
+chr1	57952	rs189727433	A	C	.	PASS	KGPilot123;RSPOS=57952;SAO=0;SSR=0;VC=SNV;VP=050000000000000010000100;WGT=0;dbSNPBuildID=135
+chr1	58771	rs140128481	T	C	.	PASS	ASP;RSPOS=58771;SAO=0;SSR=0;VC=SNV;VP=050000000004000000000100;WGT=0;dbSNPBuildID=134
+chr1	58814	rs114420996	G	A	.	PASS	ASP;G5;GMAF=0.0982632541133455;KGPilot123;RSPOS=58814;SAO=0;SSR=0;VC=SNV;VLD;VP=050000000004050010000100;WGT=0;dbSNPBuildID=132
+chr1	59040	rs149755937	T	C	.	PASS	ASP;KGPilot123;RSPOS=59040;SAO=0;SSR=0;VC=SNV;VP=050000000004000010000100;WGT=0;dbSNPBuildID=134
+chr1	60718	rs78395614	G	A	.	PASS	CFL;GNO;RSPOS=60718;SAO=0;SSR=0;VC=SNV;VP=050000000008000100000100;WGT=0;dbSNPBuildID=131
+chr1	60726	rs192328835	C	A	.	PASS	KGPilot123;RSPOS=60726;SAO=0;SSR=0;VC=SNV;VP=050000000000000010000100;WGT=0;dbSNPBuildID=135
+chr1	60791	rs76199781	A	G	.	PASS	CFL;GNO;RSPOS=60791;SAO=0;SSR=0;VC=SNV;VP=050000000008000100000100;WGT=0;dbSNPBuildID=131
+chr1	61442	rs74970982	A	G	.	PASS	CFL;GMAF=0.076782449725777;GNO;KGPilot123;RSPOS=61442;SAO=0;SSR=0;VC=SNV;VP=050000000008000110000100;WGT=0;dbSNPBuildID=131
+chr1	61462	rs56992750	T	A	.	PASS	CFL;G5;G5A;GMAF=0.0383912248628885;GNO;KGPilot123;RSPOS=61462;SAO=0;SLO;SSR=0;VC=SNV;VP=050100000008030110000100;WGT=0;dbSNPBuildID=129
+chr1	61480	rs75526266	G	C	.	PASS	CFL;GNO;RSPOS=61480;SAO=0;SSR=0;VC=SNV;VP=050000000008000100000100;WGT=0;dbSNPBuildID=131
+chr1	61499	rs75719746	G	A	.	PASS	CFL;GNO;RSPOS=61499;SAO=0;SSR=0;VC=SNV;VP=050000000008000100000100;WGT=0;dbSNPBuildID=131
+chr1	61743	rs184286948	G	C	.	PASS	KGPilot123;RSPOS=61743;SAO=0;SSR=0;VC=SNV;VP=050000000000000010000100;WGT=0;dbSNPBuildID=135
+chr1	61920	rs62637820	G	A	.	PASS	CFL;GMAF=0.0255941499085923;RSPOS=61920;SAO=0;SSR=0;VC=SNV;VLD;VP=050000000008040000000100;WGT=0;dbSNPBuildID=129
+chr1	61987	rs76735897	A	G	.	PASS	CFL;GMAF=0.292961608775137;GNO;KGPilot123;RSPOS=61987;SAO=0;SSR=0;VC=SNV;VP=050000000008000110000100;WGT=0;dbSNPBuildID=131
+chr1	61989	rs77573425	G	C	.	PASS	CFL;GMAF=0.309414990859232;GNO;KGPilot123;RSPOS=61989;SAO=0;SSR=0;VC=SNV;VP=050000000008000110000100;WGT=0;dbSNPBuildID=131
+chr1	61993	rs190553843	C	T	.	PASS	KGPilot123;RSPOS=61993;SAO=0;SSR=0;VC=SNV;VP=050000000000000010000100;WGT=0;dbSNPBuildID=135
+chr1	62156	rs181864839	C	T	.	PASS	KGPilot123;RSPOS=62156;SAO=0;SSR=0;VC=SNV;VP=050000000000000010000100;WGT=0;dbSNPBuildID=135
+chr1	62157	rs10399597	G	A	.	PASS	CFL;GMAF=0.00228519195612431;KGPilot123;RSPOS=62157;SAO=0;SSR=0;VC=SNV;VLD;VP=050000000008040010000100;WGT=0;dbSNPBuildID=119
+chr1	62162	rs140556834	G	A	.	PASS	ASP;KGPilot123;RSPOS=62162;SAO=0;SSR=0;VC=SNV;VP=050000000004000010000100;WGT=0;dbSNPBuildID=134
+chr1	62203	rs28402963	T	C	.	PASS	CFL;KGPilot123;RSPOS=62203;SAO=0;SSR=0;VC=SNV;VP=050000000008000010000100;WGT=0;dbSNPBuildID=125
+chr1	62271	rs28599927	A	G	.	PASS	CFL;GMAF=0.138482632541133;RSPOS=62271;SAO=0;SSR=0;VC=SNV;VLD;VP=050000000008040000000100;WGT=0;dbSNPBuildID=125
+chr1	63268	rs75478250	T	C	.	PASS	CFL;GNO;RSPOS=63268;SAO=0;SSR=0;VC=SNV;VP=050000000008000100000100;WGT=0;dbSNPBuildID=131
+chr1	63276	rs185977555	G	A	.	PASS	KGPilot123;RSPOS=63276;SAO=0;SSR=0;VC=SNV;VP=050000000000000010000100;WGT=0;dbSNPBuildID=135
+chr1	63297	rs188886746	G	A	.	PASS	KGPilot123;RSPOS=63297;SAO=0;SSR=0;VC=SNV;VP=050000000000000010000100;WGT=0;dbSNPBuildID=135
+chr1	63671	rs116440577	G	A	.	PASS	ASP;G5;GMAF=0.170018281535649;KGPilot123;RSPOS=63671;SAO=0;SSR=0;VC=SNV;VLD;VP=050000000004050010000100;WGT=0;dbSNPBuildID=132
+chr1	63737	rs77426996	TACT	T,TCTA	.	PASS	CFL;RSPOS=63738;SAO=0;SSR=0;VC=DIV;VP=050000000008000000000200;WGT=0;dbSNPBuildID=131
+chr1	64649	rs181431124	A	C	.	PASS	KGPilot123;RSPOS=64649;SAO=0;SSR=0;VC=SNV;VP=050000000000000010000100;WGT=0;dbSNPBuildID=135
+chr1	66008	rs2691286	C	G	.	PASS	CFL;GNO;RSPOS=66008;SAO=0;SLO;SSR=0;VC=SNV;VP=050100000008000100000100;WGT=0;dbSNPBuildID=100
+chr1	66162	rs62639105	A	T	.	PASS	CFL;GMAF=0.320383912248629;GNO;KGPilot123;RSPOS=66162;SAO=0;SLO;SSR=0;VC=SNV;VP=050100000008000110000100;WGT=0;dbSNPBuildID=129
+chr1	66176	rs28552463	T	A	.	PASS	CFL;GMAF=0.0484460694698355;KGPilot123;RSPOS=66176;SAO=0;SSR=0;VC=SNV;VLD;VP=050000000008040010000100;WGT=0;dbSNPBuildID=125
+chr1	66219	rs181028663	A	T	.	PASS	KGPilot123;RSPOS=66219;SAO=0;SSR=0;VC=SNV;VP=050000000000000010000100;WGT=0;dbSNPBuildID=135
+chr1	66238	rs113961546	T	A	.	PASS	CFL;GNO;RSPOS=66238;SAO=0;SLO;SSR=0;VC=SNV;VP=050100000008000100000100;WGT=0;dbSNPBuildID=132
+chr1	66314	rs28534012	T	A	.	PASS	CFL;RSPOS=66314;SAO=0;SSR=0;VC=SNV;VP=050000000008000000000100;WGT=0;dbSNPBuildID=125
+chr1	66331	rs186063952	A	C	.	PASS	KGPilot123;RSPOS=66331;SAO=0;SSR=0;VC=SNV;VP=050000000000000010000100;WGT=0;dbSNPBuildID=135
+chr1	66334	rs28464214	T	A	.	PASS	CFL;RSPOS=66334;SAO=0;SSR=0;VC=SNV;VP=050000000008000000000100;WGT=0;dbSNPBuildID=125
+chr1	66442	rs192044252	T	A	.	PASS	KGPilot123;RSPOS=66442;SAO=0;SSR=0;VC=SNV;VP=050000000000000010000100;WGT=0;dbSNPBuildID=135
+chr1	66457	rs13328655	T	A	.	PASS	CFL;GMAF=0.0795246800731261;KGPilot123;RSPOS=66457;SAO=0;SSR=0;VC=SNV;VLD;VP=050000000008040010000100;WGT=0;dbSNPBuildID=121
+chr1	66503	rs112350669	T	A	.	PASS	CFL;RSPOS=66503;SAO=0;SSR=0;VC=SNV;VP=050000000008000000000100;WGT=0;dbSNPBuildID=132
+chr1	66507	rs12401368	T	A	.	PASS	CFL;GMAF=0.479890310786106;KGPilot123;RSPOS=66507;SAO=0;SSR=0;VC=SNV;VLD;VP=050000000008040010000100;WGT=0;dbSNPBuildID=120
+chr1	66651	rs2257270	A	T	.	PASS	CFL;GNO;RSPOS=66651;SAO=0;SSR=0;VC=SNV;VP=050000000008000100000100;WGT=0;dbSNPBuildID=100
+chr1	67179	rs149952626	C	G	.	PASS	ASP;KGPilot123;RSPOS=67179;SAO=0;SSR=0;VC=SNV;VP=050000000004000010000100;WGT=0;dbSNPBuildID=134
+chr1	67181	rs77662731	A	G	.	PASS	ASP;G5;G5A;GENEINFO=OR4F5:79501;GMAF=0.0470749542961609;GNO;KGPilot123;RSPOS=67181;SAO=0;SSR=0;VC=SNV;VLD;VP=050000000004070110000100;WGT=0;dbSNPBuildID=131
+chr1	67223	rs78676975	C	A	.	PASS	ASP;GENEINFO=OR4F5:79501;GNO;RSPOS=67223;SAO=0;SSR=0;VC=SNV;VP=050000000004000100000100;WGT=0;dbSNPBuildID=131
+chr1	69428	rs140739101	T	G	.	PASS	ASP;RSPOS=69428;S3D;SAO=0;SSR=0;VC=SNV;VLD;VP=050200000004040000000100;WGT=0;dbSNPBuildID=134
+chr1	69453	rs142004627	G	A	.	PASS	ASP;RSPOS=69453;S3D;SAO=0;SSR=0;VC=SNV;VP=050200000004000000000100;WGT=0;dbSNPBuildID=134
+chr1	69476	rs148502021	T	C	.	PASS	ASP;RSPOS=69476;S3D;SAO=0;SSR=0;VC=SNV;VLD;VP=050200000004040000000100;WGT=0;dbSNPBuildID=134
+chr1	69496	rs150690004	G	A	.	PASS	ASP;RSPOS=69496;S3D;SAO=0;SSR=0;VC=SNV;VLD;VP=050200000004040000000100;WGT=0;dbSNPBuildID=134
+chr1	69511	rs75062661	A	G	.	PASS	GENEINFO=OR4F5:79501;GMAF=0.193784277879342;GNO;KGPilot123;RSPOS=69511;S3D;SAO=0;SSR=0;VC=SNV;VP=050200000000000110000100;WGT=0;dbSNPBuildID=131
+chr1	69534	rs190717287	T	C	.	PASS	KGPilot123;RSPOS=69534;S3D;SAO=0;SSR=0;VC=SNV;VP=050200000000000010000100;WGT=0;dbSNPBuildID=135
+chr1	69552	rs55874132	G	C	.	PASS	GENEINFO=OR4F5:79501;HD;RSPOS=69552;S3D;SAO=0;SLO;SSR=0;VC=SNV;VLD;VP=050300000000040400000100;WGT=0;dbSNPBuildID=129
+chr1	69590	rs141776804	T	A	.	PASS	ASP;RSPOS=69590;S3D;SAO=0;SSR=0;VC=SNV;VP=050200000004000000000100;WGT=0;dbSNPBuildID=134
+chr1	69594	rs144967600	T	C	.	PASS	ASP;RSPOS=69594;S3D;SAO=0;SSR=0;VC=SNV;VP=050200000004000000000100;WGT=0;dbSNPBuildID=134
+chr1	72148	rs182862337	C	T	.	PASS	KGPilot123;RSPOS=72148;SAO=0;SSR=0;VC=SNV;VP=050000000000000010000100;WGT=0;dbSNPBuildID=135
+chr1	73841	rs143773730	C	T	.	PASS	ASP;KGPilot123;RSPOS=73841;SAO=0;SSR=0;VC=SNV;VP=050000000004000010000100;WGT=0;dbSNPBuildID=134
+chr1	74651	rs62641291	G	A	.	PASS	RSPOS=74651;SAO=0;SSR=0;VC=SNV;VP=050000000000000000000100;WGT=0;dbSNPBuildID=129
+chr1	74681	rs13328683	G	T	.	PASS	CFL;GMAF=0.286106032906764;RSPOS=74681;SAO=0;SSR=0;VC=SNV;VLD;VP=050000000008040000000100;WGT=0;dbSNPBuildID=121
+chr1	74709	rs62641292	T	A	.	PASS	CFL;RSPOS=74709;SAO=0;SSR=0;VC=SNV;VP=050000000008000000000100;WGT=0;dbSNPBuildID=129
+chr1	74771	rs13328675	A	G	.	PASS	CFL;RSPOS=74771;SAO=0;SSR=0;VC=SNV;VP=050000000008000000000100;WGT=0;dbSNPBuildID=121
+chr1	74790	rs13328700	C	G	.	PASS	CFL;RSPOS=74790;SAO=0;SSR=0;VC=SNV;VP=050000000008000000000100;WGT=0;dbSNPBuildID=121
+chr1	74792	rs13328684	G	A	.	PASS	CFL;RSPOS=74792;SAO=0;SSR=0;VC=SNV;VP=050000000008000000000100;WGT=0;dbSNPBuildID=121
+chr1	77462	rs188023513	G	A	.	PASS	KGPilot123;RSPOS=77462;SAO=0;SSR=0;VC=SNV;VP=050000000000000010000100;WGT=0;dbSNPBuildID=135
+chr1	77470	rs192898053	T	C	.	PASS	KGPilot123;RSPOS=77470;SAO=0;SSR=0;VC=SNV;VP=050000000000000010000100;WGT=0;dbSNPBuildID=135
+chr1	77874	rs184538873	G	A	.	PASS	KGPilot123;RSPOS=77874;SAO=0;SSR=0;VC=SNV;VP=050000000000000010000100;WGT=0;dbSNPBuildID=135
+chr1	77961	rs78385339	G	A	.	PASS	GMAF=0.125685557586837;KGPilot123;RSPOS=77961;SAO=0;SSR=0;VC=SNV;VLD;VP=050000000000040010000100;WGT=0;dbSNPBuildID=131
+chr1	79033	rs62641298	A	G	.	PASS	GMAF=0.438299817184644;GNO;HD;KGPilot123;RSPOS=79033;SAO=0;SSR=0;VC=SNV;VP=050000000000000510000100;WGT=0;dbSNPBuildID=129
+chr1	79050	rs62641299	G	T	.	PASS	GMAF=0.224405850091408;GNO;KGPilot123;RSPOS=79050;SAO=0;SSR=0;VC=SNV;VP=050000000000000110000100;WGT=0;dbSNPBuildID=129
+chr1	79137	rs143777184	A	T	.	PASS	ASP;KGPilot123;RSPOS=79137;SAO=0;SSR=0;VC=SNV;VP=050000000004000010000100;WGT=0;dbSNPBuildID=134
+chr1	79417	rs184768190	C	T	.	PASS	KGPilot123;RSPOS=79417;SAO=0;SSR=0;VC=SNV;VP=050000000000000010000100;WGT=0;dbSNPBuildID=135
+chr1	79418	rs2691296	G	C	.	PASS	GMAF=0.0178244972577697;RSPOS=79418;RV;SAO=0;SLO;SSR=0;VC=SNV;VLD;VP=050100000000040000000100;WGT=0;dbSNPBuildID=100
+chr1	79538	rs2691295	C	T	.	PASS	RSPOS=79538;RV;SAO=0;SSR=0;VC=SNV;VP=050000000000000000000100;WGT=0;dbSNPBuildID=100
+chr1	79772	rs147215883	C	G	.	PASS	ASP;KGPilot123;RSPOS=79772;SAO=0;SSR=0;VC=SNV;VP=050000000004000010000100;WGT=0;dbSNPBuildID=134
+chr1	79872	rs189224661	T	G	.	PASS	KGPilot123;RSPOS=79872;SAO=0;SSR=0;VC=SNV;VP=050000000000000010000100;WGT=0;dbSNPBuildID=135
+chr1	80323	rs3942603	G	C	.	PASS	CFL;GNO;RSPOS=80323;RV;SAO=0;SLO;SSR=0;VC=SNV;VP=050100000008000100000100;WGT=0;dbSNPBuildID=108
+chr1	80386	rs3878915	C	A	.	PASS	GMAF=0.0118829981718464;RSPOS=80386;RV;SAO=0;SLO;SSR=0;VC=SNV;VLD;VP=050100000000040000000100;WGT=0;dbSNPBuildID=108
+chr1	80454	rs144226842	G	C	.	PASS	ASP;KGPilot123;RSPOS=80454;SAO=0;SSR=0;VC=SNV;VP=050000000004000010000100;WGT=0;dbSNPBuildID=134
+chr1	81836	rs2259560	A	T	.	PASS	ASP;GNO;RSPOS=81836;RV;SAO=0;SLO;SSR=0;VC=SNV;VP=050100000004000100000100;WGT=0;dbSNPBuildID=100
+chr1	81949	rs181567186	T	C	.	PASS	KGPilot123;RSPOS=81949;SAO=0;SSR=0;VC=SNV;VP=050000000000000010000100;WGT=0;dbSNPBuildID=135
+chr1	81962	rs4030308	T	TAA	.	PASS	ASP;RSPOS=81962;RV;SAO=0;SLO;SSR=0;VC=DIV;VP=050100000004000000000200;WGT=0;dbSNPBuildID=108
+chr1	82102	rs4030307	C	T	.	PASS	ASP;RSPOS=82102;RV;SAO=0;SLO;SSR=0;VC=SNV;VP=050100000004000000000100;WGT=0;dbSNPBuildID=108
+chr1	82103	rs2020400	T	C	.	PASS	ASP;RSPOS=82103;RV;SAO=0;SLO;SSR=0;VC=SNV;VP=050100000004000000000100;WGT=0;dbSNPBuildID=92
+chr1	82126	rs1815133	C	T	.	PASS	ASP;RSPOS=82126;RV;SAO=0;SLO;SSR=0;VC=SNV;VP=050100000004000000000100;WGT=0;dbSNPBuildID=92
+chr1	82133	rs4030306	CA	C,CAAAAAAAAAAAAAAA	.	PASS	ASP;RSPOS=82136;RV;SAO=0;SLO;SSR=0;VC=DIV;VP=050100000004000000000200;WGT=0;dbSNPBuildID=108
+chr1	82154	rs4477212	A	G	.	PASS	ASP;HD;RSPOS=82154;SAO=0;SSR=0;VC=SNV;VP=050000000004000400000100;WGT=0;dbSNPBuildID=111
+chr1	82162	rs1815132	C	A	.	PASS	ASP;GMAF=0.0351919561243144;GNO;RSPOS=82162;RV;SAO=0;SLO;SSR=0;VC=SNV;VP=050100000004000100000100;WGT=0;dbSNPBuildID=92
+chr1	82163	rs139113303	G	A	.	PASS	ASP;KGPilot123;RSPOS=82163;SAO=0;SSR=0;VC=SNV;VP=050000000004000010000100;WGT=0;dbSNPBuildID=134
+chr1	82196	rs112844054	A	T	.	PASS	ASP;RSPOS=82196;SAO=0;SSR=0;VC=SNV;VP=050000000004000000000100;WGT=0;dbSNPBuildID=132
+chr1	82249	rs1851945	A	G	.	PASS	ASP;GMAF=0.0452468007312614;KGPilot123;RSPOS=82249;RV;SAO=0;SLO;SSR=0;VC=SNV;VLD;VP=050100000004040010000100;WGT=0;dbSNPBuildID=92
+chr1	82282	rs3871775	G	A	.	PASS	ASP;RSPOS=82282;RV;SAO=0;SLO;SSR=0;VC=SNV;VP=050100000004000000000100;WGT=0;dbSNPBuildID=108
+chr1	82303	rs3871776	T	C	.	PASS	ASP;RSPOS=82303;RV;SAO=0;SLO;SSR=0;VC=SNV;VP=050100000004000000000100;WGT=0;dbSNPBuildID=108
+chr1	82316	rs4030305	A	C	.	PASS	ASP;GNO;RSPOS=82316;RV;SAO=0;SLO;SSR=0;VC=SNV;VP=050100000004000100000100;WGT=0;dbSNPBuildID=108
+chr1	82609	rs149189449	C	G	.	PASS	ASP;KGPilot123;RSPOS=82609;SAO=0;SSR=0;VC=SNV;VP=050000000004000010000100;WGT=0;dbSNPBuildID=134
+chr1	82676	rs185237834	T	G	.	PASS	KGPilot123;RSPOS=82676;SAO=0;SSR=0;VC=SNV;VP=050000000000000010000100;WGT=0;dbSNPBuildID=135
+chr1	82734	rs4030331	T	C	.	PASS	ASP;GMAF=0.261882998171846;KGPilot123;RSPOS=82734;RV;SAO=0;SLO;SSR=0;VC=SNV;VLD;VP=050100000004040010000100;WGT=0;dbSNPBuildID=108
+chr1	82957	rs189774606	C	T	.	PASS	KGPilot123;RSPOS=82957;SAO=0;SSR=0;VC=SNV;VP=050000000000000010000100;WGT=0;dbSNPBuildID=135
+chr1	83084	rs181193408	T	A	.	PASS	KGPilot123;RSPOS=83084;SAO=0;SSR=0;VC=SNV;VP=050000000000000010000100;WGT=0;dbSNPBuildID=135
+chr1	83088	rs186081601	G	C	.	PASS	KGPilot123;RSPOS=83088;SAO=0;SSR=0;VC=SNV;VP=050000000000000010000100;WGT=0;dbSNPBuildID=135
+chr1	83107	rs4405097	G	C	.	PASS	ASP;RSPOS=83107;SAO=0;SSR=0;VC=SNV;VP=050000000004000000000100;WGT=0;dbSNPBuildID=111
+chr1	83119	rs4030324	AA	A,ATAAC	.	PASS	ASP;RSPOS=83120;RV;SAO=0;SLO;SSR=0;VC=DIV;VP=050100000004000000000200;WGT=0;dbSNPBuildID=108
+chr1	83771	rs189906733	T	G	.	PASS	KGPilot123;RSPOS=83771;SAO=0;SSR=0;VC=SNV;VP=050000000000000010000100;WGT=0;dbSNPBuildID=135
+chr1	83786	rs58520670	T	TA	.	PASS	ASP;RSPOS=83794;SAO=0;SSR=0;VC=DIV;VP=050000000004000000000200;WGT=0;dbSNPBuildID=129
+chr1	83815	rs58857344	GAGAA	G	.	PASS	ASP;RSPOS=83827;SAO=0;SSR=0;VC=DIV;VP=050000000004000000000200;WGT=0;dbSNPBuildID=129
+chr1	83826	rs71281475	AAAGA	A,AAA	.	PASS	ASP;GNO;RSPOS=83827;RV;SAO=0;SLO;SSR=0;VC=DIV;VP=050100000004000100000200;WGT=0;dbSNPBuildID=130
+chr1	83855	rs59596480	GAA	G	.	PASS	ASP;RSPOS=83857;SAO=0;SSR=0;VC=DIV;VP=050000000004000000000200;WGT=0;dbSNPBuildID=129
+chr1	83872	rs59556914	AA	A,AAGA	.	PASS	ASP;RSPOS=83873;SAO=0;SSR=0;VC=DIV;VP=050000000004000000000200;WGT=0;dbSNPBuildID=129
+chr1	83884	rs59586754	GAAA	G	.	PASS	ASP;RSPOS=83885;SAO=0;SSR=0;VC=DIV;VP=050000000004000000000200;WGT=0;dbSNPBuildID=129
+chr1	83897	rs61330047	GAA	G	.	PASS	ASP;RSPOS=83899;SAO=0;SSR=0;VC=DIV;VP=050000000004000000000200;WGT=0;dbSNPBuildID=129
+chr1	83901	rs58254183	GAAAGAA	G	.	PASS	ASP;RSPOS=83903;SAO=0;SSR=0;VC=DIV;VP=050000000004000000000200;WGT=0;dbSNPBuildID=129
+chr1	83921	rs61338823	GAA	G	.	PASS	ASP;RSPOS=83923;SAO=0;SSR=0;VC=DIV;VP=050000000004000000000200;WGT=0;dbSNPBuildID=129
+chr1	83930	rs71281474	AG	A,AGA	.	PASS	ASP;GNO;RSPOS=83931;RV;SAO=0;SLO;SSR=0;VC=DIV;VP=050100000004000100000200;WGT=0;dbSNPBuildID=130
+chr1	83934	rs59235392	AG	A,AGAAA	.	PASS	ASP;RSPOS=83935;SAO=0;SSR=0;VC=DIV;VP=050000000004000000000200;WGT=0;dbSNPBuildID=129
+chr1	83977	rs180759811	A	G	.	PASS	KGPilot123;RSPOS=83977;SAO=0;SSR=0;VC=SNV;VP=050000000000000010000100;WGT=0;dbSNPBuildID=135
+chr1	84002	rs28850140	G	A	.	PASS	ASP;GMAF=0.138939670932358;KGPilot123;RSPOS=84002;SAO=0;SSR=0;VC=SNV;VLD;VP=050000000004040010000100;WGT=0;dbSNPBuildID=125
+chr1	84010	rs186443818	G	A	.	PASS	KGPilot123;RSPOS=84010;SAO=0;SSR=0;VC=SNV;VP=050000000000000010000100;WGT=0;dbSNPBuildID=135
+chr1	84018	rs61352176	GAA	G	.	PASS	ASP;RSPOS=84020;SAO=0;SSR=0;VC=DIV;VP=050000000004000000000200;WGT=0;dbSNPBuildID=129
+chr1	84079	rs190867312	T	C	.	PASS	KGPilot123;RSPOS=84079;SAO=0;SSR=0;VC=SNV;VP=050000000000000010000100;WGT=0;dbSNPBuildID=135
+chr1	84139	rs183605470	A	T	.	PASS	KGPilot123;RSPOS=84139;SAO=0;SSR=0;VC=SNV;VP=050000000000000010000100;WGT=0;dbSNPBuildID=135
+chr1	84156	rs188652299	A	C	.	PASS	KGPilot123;RSPOS=84156;SAO=0;SSR=0;VC=SNV;VP=050000000000000010000100;WGT=0;dbSNPBuildID=135
+chr1	84244	rs191297051	A	C	.	PASS	KGPilot123;RSPOS=84244;SAO=0;SSR=0;VC=SNV;VP=050000000000000010000100;WGT=0;dbSNPBuildID=135
+chr1	84295	rs183209871	G	A	.	PASS	KGPilot123;RSPOS=84295;SAO=0;SSR=0;VC=SNV;VP=050000000000000010000100;WGT=0;dbSNPBuildID=135
+chr1	84346	rs187855973	T	C	.	PASS	KGPilot123;RSPOS=84346;SAO=0;SSR=0;VC=SNV;VP=050000000000000010000100;WGT=0;dbSNPBuildID=135
+chr1	84453	rs191379015	C	G	.	PASS	KGPilot123;RSPOS=84453;SAO=0;SSR=0;VC=SNV;VP=050000000000000010000100;WGT=0;dbSNPBuildID=135
+chr1	84705	rs183470350	T	G	.	PASS	KGPilot123;RSPOS=84705;SAO=0;SSR=0;VC=SNV;VP=050000000000000010000100;WGT=0;dbSNPBuildID=135
diff --git a/public/gatk-engine/src/test/resources/exampleDBSNP.vcf.idx b/public/gatk-engine/src/test/resources/exampleDBSNP.vcf.idx
new file mode 100644
index 0000000..7239e36
Binary files /dev/null and b/public/gatk-engine/src/test/resources/exampleDBSNP.vcf.idx differ
diff --git a/public/gatk-engine/src/test/resources/exampleFASTA-3contigs.fasta b/public/gatk-engine/src/test/resources/exampleFASTA-3contigs.fasta
new file mode 100644
index 0000000..cc31f38
--- /dev/null
+++ b/public/gatk-engine/src/test/resources/exampleFASTA-3contigs.fasta
@@ -0,0 +1,24 @@
+>chr1
+AAAAA
+AAAAA
+AAAAA
+AA
+
+
+>chr2
+BBBBBBB
+BBBBBBB
+BBBBBBB
+
+>chr3
+CCCCCCCCCC
+CCCCCCCCCC
+CCCCCCCCCC
+CCCCCCCCCC
+CCCCCCCCCC
+CCCCCCCCCC
+CCCCCCCCCC
+CCCCCCCCCC
+CCCCCCCCCC
+CCCCCCCCCC
+
diff --git a/public/gatk-engine/src/test/resources/exampleFASTA-combined.fasta b/public/gatk-engine/src/test/resources/exampleFASTA-combined.fasta
new file mode 100644
index 0000000..4bfa409
--- /dev/null
+++ b/public/gatk-engine/src/test/resources/exampleFASTA-combined.fasta
@@ -0,0 +1,1675 @@
+>chr1
+taaccctaaccctaaccctaaccctaaccctaaccctaaccctaaccctaaccctaaccc
+taaccctaaccctaaccctaaccctaaccctaaccctaaccctaacccaaccctaaccct
+aaccctaaccctaaccctaaccctaacccctaaccctaaccctaaccctaaccctaacct
+aaccctaaccctaaccctaaccctaaccctaaccctaaccctaaccctaacccctaaccc
+taaccctaaaccctaaaccctaaccctaaccctaaccctaaccctaaccccaaccccaac
+cccaaccccaaccccaaccccaaccctaacccctaaccctaaccctaaccctaccctaac
+cctaaccctaaccctaaccctaaccctaacccctaacccctaaccctaaccctaacccta
+accctaaccctaaccctaacccctaaccctaaccctaaccctaaccctcgcggtaccctc
+agccggcccgcccgcccgggtctgacctgaggagaactgtgctccgccttcagagtacca
+ccgaaatctgtgcagaggacaacgcagctccgccctcgcggtgctctccgggtctgtgct
+gaggagaacgcaactccgccggcgcaggcgcagagaggcgcgccgcgccggcgcaggcgc
+agacacatgctagcgcgtcggggtggaggcgtggcgcaggcgcagagaggcgcgccgcgc
+cggcgcaggcgcagagacacatgctaccgcgtccaggggtggaggcgtggcgcaggcgca
+gagaggcgcaccgcgccggcgcaggcgcagagacacatgctagcgcgtccaggggtggag
+gcgtggcgcaggcgcagagacgcaagcctacgggcgggggttgggggggcgtgtgttgca
+ggagcaaagtcgcacggcgccgggctggggcggggggagggtggcgccgtgcacgcgcag
+aaactcacgtcacggtggcgcggcgcagagacgggtagaacctcagtaatccgaaaagcc
+gggatcgaccgccccttgcttgcagccgggcactacaggacccgcttgctcacggtgctg
+tgccagggcgccccctgctggcgactagggcaactgcagggctctcttgcttagagtggt
+ggccagcgccccctgctggcgccggggcactgcagggccctcttgcttactgtatagtgg
+tggcacgccgcctgctggcagctagggacattgcagggtcctcttgctcaaggtgtagtg
+gcagcacgcccacctgctggcagctggggacactgccgggccctcttgctCCAACAGTAC
+TGGCGGATTATAGGGAAACACCCGGAGcatatgctgtttggtctcagtagactcctaaat
+atgggattcctgggtttaaaagtaaaaaataaatatgtttaatttgtgaactgattacca
+tcagaattgtactgttctgtatcccaccagcaatgtctaggaatgcctgtttctccacaa
+agtgtttacttttggatttttgccagtctaacaggtgaAGccctggagattcttattagt
+gatttgggctggggcctggccatgtgtatttttttaaatttccactgatgattttgctgc
+atggccggtgttgagaatgactgCGCAAATTTGCCGGATTTCCTTTGCTGTTCCTGCATG
+TAGTTTAAACGAGATTGCCAGCACCGGGTATCATTCACCATTTTTCTTTTCGTTAACTTG
+CCGTCAGCCTTTTCTTTGACCTCTTCTTTCTGTTCATGTGTATTTGCTGTCTCTTAGCCC
+AGACTTCCCGTGTCCTTTCCACCGGGCCTTTGAGAGGTCACAGGGTCTTGATGCTGTGGT
+CTTCATCTGCAGGTGTCTGACTTCCAGCAACTGCTGGCCTGTGCCAGGGTGCAAGCTGAG
+CACTGGAGTGGAGTTTTCCTGTGGAGAGGAGCCATGCCTAGAGTGGGATGGGCCATTGTT
+CATCTTCTGGCCCCTGTTGTCTGCATGTAACTTAATACCACAACCAGGCATAGGGGAAAG
+ATTGGAGGAAAGATGAGTGAGAGCATCAACTTCTCTCACAACCTAGGCCAGTAAGTAGTG
+CTTGTGCTCATCTCCTTGGCTGTGATACGTGGCCGGCCCTCGCTCCAGCAGCTGGACCCC
+TACCTGCCGTCTGCTGCCATCGGAGCCCAAAGCCGGGCTGTGACTGCTCAGACCAGCCGG
+CTGGAGGGAGGGGCTCAGCAGGTCTGGCTTTGGCCCTGGGAGAGCAGGTGGAAGATCAGG
+CAGGCCATCGCTGCCACAGAACCCAGTGGATTGGCCTAGGTGGGATCTCTGAGCTCAACA
+AGCCCTCTCTGGGTGGTAGGTGCAGAGACGGGAGGGGCAGAGCCGCAGGCACAGCCAAGA
+GGGCTGAAGAAATGGTAGAACGGAGCAGCTGGTGATGTGTGGGCCCACCGGCCCCAGGCT
+CCTGTCTCCCCCCAGGTGTGTGGTGATGCCAGGCATGCCCTTCCCCAGCATCAGGTCTCC
+AGAGCTGCAGAAGACGACGGCCGACTTGGATCACACTCTTGTGAGTGTCCCCAGTGTTGC
+AGAGGTGAGAGGAGAGTAGACAGTGAGTGGGAGTGGCGTCGCCCCTAGGGCTCTACGGGG
+CCGGCGTCTCCTGTCTCCTGGAGAGGCTTCGATGCCCCTCCACACCCTCTTGATCTTCCC
+TGTGATGTCATCTGGAGCCCTGCTGCTTGCGGTGGCCTATAAAGCCTCCTAGTCTGGCTC
+CAAGGCCTGGCAGAGTCTTTCCCAGGGAAAGCTACAAGCAGCAAACAGTCTGCATGGGTC
+ATCCCCTTCACTCCCAGCTCAGAGCCCAGGCCAGGGGCCCCCAAGAAAGGCTCTGGTGGA
+GAACCTGTGCATGAAGGCTGTCAACCAGTCCATAGGCAAGCCTGGCTGCCTCCAGCTGGG
+TCGACAGACAGGGGCTGGAGAAGGGGAGAAGAGGAAAGTGAGGTTGCCTGCCCTGTCTCC
+TACCTGAGGCTGAGGAAGGAGAAGGGGATGCACTGTTGGGGAGGCAGCTGTAACTCAAAG
+CCTTAGCCTCTGTTCCCACGAAGGCAGGGCCATCAGGCACCAAAGGGATTCTGCCAGCAT
+AGTGCTCCTGGACCAGTGATACACCCGGCACCCTGTCCTGGACACGCTGTTGGCCTGGAT
+CTGAGCCCTGGTGGAGGTCAAAGCCACCTTTGGTTCTGCCATTGCTGCTGTGTGGAAGTT
+CACTCCTGCCTTTTCCTTTCCCTAGAGCCTCCACCACCCCGAGATCACATTTCTCACTGC
+CTTTTGTCTGCCCAGTTTCACCAGAAGTAGGCCTCTTCCTGACAGGCAGCTGCACCACTG
+CCTGGCGCTGTGCCCTTCCTTTGCTCTGCCCGCTGGAGACGGTGTTTGTCATGGGCCTGG
+TCTGCAGGGATCCTGCTACAAAGGTGAAACCCAGGAGAGTGTGGAGTCCAGAGTGTTGCC
+AGGACCCAGGCACAGGCATTAGTGCCCGTTGGAGAAAACAGGGGAATCCCGAAGAAATGG
+TGGGTCCTGGCCATCCGTGAGATCTTCCCAGGGCAGCTCCCCTCTGTGGAATCCAATCTG
+TCTTCCATCCTGCGTGGCCGAGGGCCAGGCTTCTCACTGGGCCTCTGCAGGAGGCTGCCA
+TTTGTCCTGCCCACCTTCTTAGAAGCGAGACGGAGCAGACCCATCTGCTACTGCCCTTTC
+TATAATAACTAAAGTTAGCTGCCCTGGACTATTCACCCCCTAGTCTCAATTTAAGAAGAT
+CCCCATGGCCACAGGGCCCCTGCCTGGGGGCTTGTCACCTCCCCCACCTTCTTCCTGAGT
+CATTCCTGCAGCCTTGCTCCCTAACCTGCCCCACAGCCTTGCCTGGATTTCTATCTCCCT
+GGCTTGGTGCCAGTTCCTCCAAGTCGATGGCACCTCCCTCCCTCTCAACCACTTGAGCAA
+ACTCCAAGACATCTTCTACCCCAACACCAGCAATTGTGCCAAGGGCCATTAGGCTCTCAG
+CATGACTATTTTTAGAGACCCCGTGTCTGTCACTGAAACCTTTTTTGTGGGAGACTATTC
+CTCCCATCTGCAACAGCTGCCCCTGCTGACTGCCCTTCTCTCCTCCCTCTCATCCCAGAG
+AAACAGGTCAGCTGGGAGCTTCTGCCCCCACTGCCTAGGGACCAACAGGGGCAGGAGGCA
+GTCACTGACCCCGAGACGTTTGCATCCTGCACAGCTAGAGATCCTTTATTAAAAGCACAC
+TGTTGGTTTCTGCTCAGTTCTTTATTGATTGGTGTGCCGTTTTCTCTGGAAGCCTCTTAA
+GAACACAGTGGCGCAGGCTGGGTGGAGCCGTCCCCCCATGGAGCACAGGCAGACAGAAGT
+CCCCGCCCCAGCTGTGTGGCCTCAAGCCAGCCTTCCGCTCCTTGAAGCTGGTCTCCACAC
+AGTGCTGGTTCCGTCACCCCCTCCCAAGGAAGTAGGTCTGAGCAGCTTGTCCTGGCTGTG
+TCCATGTCAGAGCAACGGCCCAAGTCTGGGTCTGGGGGGGAAGGTGTCATGGAGCCCCCT
+ACGATTCCCAGTCGTCCTCGTCCTCCTCTGCCTGTGGCTGCTGCGGTGGCGGCAGAGGAG
+GGATGGAGTCTGACACGCGGGCAAAGGCTCCTCCGGGCCCCTCACCAGCCCCAGGTCCTT
+TCCCAGAGATGCCTGGAGGGAAAAGGCTGAGTGAGGGTGGTTGGTGGGAAACCCTGGTTC
+CCCCAGCCCCCGGAGACTTAAATACAGGAAGAAAAAGGCAGGACAGAATTACAAGGTGCT
+GGCCCAGGGCGGGCAGCGGCCCTGCCTCCTACCCTTGCGCCTCATGACCAGCTTGTTGAA
+GAGATCCGACATCAAGTGCCCACCTTGGCTCGTGGCTCTCACTGCAACGGGAAAGCCACA
+GACTGGGGTGAAGAGTTCAGTCACATGCGACCGGTGACTCCCTGTCCCCACCCCCATGAC
+ACTCCCCAGCCCTCCAAGGCCACTGTGTTTCCCAGTTAGCTCAGAGCCTCAGTCGATCCC
+TGACCCAGCACCGGGCACTGATGAGACAGCGGCTGTTTGAGGAGCCACCTCCCAGCCACC
+TCGGGGCCAGGGCCAGGGTGTGCAGCAccactgtacaatggggaaactggcccagagagg
+tgaggcagcttgcctggggtcacagagcaaggcaaaagcagcgctgggtacaagctcaAA
+ACCATAGTGCCCAGGGCACTGCCGCTGCAGGCGCAGGCATCGCATCACACCAGTGTCTGC
+GTTCACAGCAGGCATCATCAGTAGCCTCCAGAGGCCTCAGGTCCAGTCTCTAAAAATATC
+TCAGGAGGCTGCAGTGGCTGACCATTGCCTTGGACCGCTCTTGGCAGTCGAAGAAGATTC
+TCCTGTCAGTTTGAGCTGGGTGAGCTTAGAGAGGAAAGCTCCACTATGGCTCCCAAACCA
+GGAAGGAGCCATAGCCCAGGCAGGAGGGCTGAGGACCTCTGGTGGCGGCCCAGGGCTTCC
+AGCATGTGCCCTAGGGGAAGCAGGGGCCAGCTGGCAAGAGCAGGGGGTGGGCAGAAAGCA
+CCCGGTGGACTCAGGGCTGGAGGGGAGGAGGCGATCTTGCCCAAGGCCCTCCGACTGCAA
+GCTCCAGGGCCCGCTCACCTTGCTCCTGCTCCTTCTGCTGCTGCTTCTCCAGCTTTCGCT
+CCTTCATGCTGCGCAGCTTGGCCTTGCCGATGCCCCCAGCTTGGCGGATGGACTCTAGCA
+GAGTGGCCAGCCACCGGAGGGGTCAACCACTTCCCTGGGAGCTCCCTGGACTGGAGCCGG
+GAGGTGGGGAACAGGGCAAGGAGGAAAGGCTGCTCAGGCAGGGCTGGGGAAGCTTACTGT
+GTCCAAGAGCCTGCTGGGAGGGAAGTCACCTCCCCTCAAACGAGGAGCCCTGCGCTGGGG
+AGGCCGGACCTTTGGAGACTGTGTGTGGGGGCCTGGGCACTGACTTCTGCAACCACCTGA
+GCGCGGGCATCCTGTGTGCAGATACTCCCTGCTTCCTCTCTAGCCCCCACCCTGCAGAGC
+TGGACCCCTGAGCTAGCCATGCTCTGACAGTCTCAGTTGCACACACGAGCCAGCAGAGGG
+GTTTTGTGCCACTTCTGGATGCTAGGGTTACACTGGGAGACACAGCAGTGAAGCTGAAAT
+GAAAAATGTGTTGCTGTAGTTTGTTATTAGACCCCTTCTTTCCATTGGTTTAATTAGGAA
+TGGGGAACCCAGAGCCTCACTTGTTCAGGCTCCCTCTGCCCTAGAAGTGAGAAGTCCAGA
+GCTCTACAGTTTGAAAACCACTATTTTATGAACCAAGTAGAACAAGATATTTGAAATGGA
+AACTATTCAAAAAATTGAGAATTTCTGACCACTTAACAAACCCACAGAAAATCCACCCGA
+GTGCACTGAGCACGCCAGAAATCAGGTGGCCTCAAAGAGCTGCTCCCACCTGAAGGAGAC
+GCGCTGCTGCTGCTGTCGTCCTGCCTGGCGCCTTGGCCTACAGGGGCCGCGGTTGAGGGT
+GGGAGTGGGGGTGCACTGGCCAGCACCTCAGGAGCtgggggtggtggtgggggcggtggg
+ggtggtgttagtACCCCATCTTGTAGGTCTGAAACACAAAGTGTGGGGTGTCTAGGGAAG
+AAGGTGTGTGACCAGGGAGGTCCCCGGCCCAGCTCCCATCCCAGAACCCAGCTCACCTAC
+CTTGAGAGGCTCGGCTACCTCAGTGTGGAAGGTGGGCAGTTCTGGAATGGTGCCAGGGGC
+AGAGGGGGCAATGCCGGGGCCCAGGTCGGCAATGTACATGAGGTCGTTGGCAATGCCGGG
+CAGGTCAGGCAGGTAGGATGGAACATCAATCTCAGGCACCTGGCCCAGGTCTGGCACATA
+GAAGTAGTTCTCTGGGACCTGCAAGATTAGGCAGGGACATGTGAGAGGTGACAGGGACCT
+GCAGGGGCAGCCAACAAGACCTTGTGTGCACCTCCCATGGGTGGAATAAGGGGCCCAACA
+GCCTTGACTGGAGAGGAGCTCTGGCAAGGCCCTGGGCCACTGCACCTGTCTCCACCTCTG
+TCCCACCCCTCCCACCTGCTGTTCCAGCTGCTCTCTCTTGCTGATGGACAAGGGGGCATC
+AAACAGCTTCTCCTCTGTCTCTGCCCCCAGCATCACATGGGTCTTTGTTACAGCACCAGC
+CAGGGGGTCCAGGAAGACATACTTCTTCTACCTACAGAGGCGACATGGGGGTCAGGCAAG
+CTGACACCCGCTGTCCTGAGCCCATGTTCCTCTCCCACATCATCAGGGGCACAGCGTGCA
+CTGTGGGGTCCCAGGCCTCCCGAGCCGAGCCACCCGTCACCCCCTGGCTCCTGGCCTATG
+TGCTGTACCTGTGTCTGATGCCCTGGGTCCCCACTAAGCCAGGCCGGGCCTCCCGCCCAC
+ACCCCTCGGCCCTGCCCTCTGGCCATACAGGTTCTCGGTGGTGTTGAAGAGCAGCAAGGA
+GCTGACAGAGCTGATGTTGCTGGGAAGACCCCCAAGTCCCTCTTCTGCATCGTCCTCGGG
+CTCCGGCTTGGTGCTCACGCACACAGGAAAGTCCTTCAGCTTCTCCTGAGAGGGCCAGGA
+TGGCCAAGGGATGGTGAATATTTGGTGCTGGGCCTAATCAGCTGCCATCCCATCCCAGTC
+AGCCTCCTCTGGGGGACAGAACCCTATGGTGGCCCCGGCTCCTCCCCAGTATCCAGTCCT
+CCTGGTGTGTGACAGGCTATATGCGCGGCCAGCAGACCTGCAGGGCCCGCTCGTCCAGGG
+GGCGGTGCTTGCTCTGGATCCTGTGGCGGGGGCGTCTCTGCAGGCCAGGGTCCTGGGCGC
+CCGTGAAGATGGAGCCATATTCCTGCAGGCGCCCTGGAGCAGGGTACTTGGCACTGGAGA
+ACACCTGTGGACACAGGGACAAGTCTGAGGGGGCCCCAAGAGGCTCAGAGGGCTAGGATT
+GCTTGGCAGGAGAGGGTGGAGTTGGAAGCCTGGGCGAGAAGAAAGCTCAAGGTACAGGTG
+GGCAGCAGGGCAGAGACTGGGCAGCCTCAGAGGCACGGGGAAATGGAGGGACTGCCCAGT
+AGCCTCAGGACACAGGGGTATGGGGACTACCTTGATGGCCTTCTTGCTGCCCTTGATCTT
+CTCAATCTTGGCCTGGGCCAAGGAGACCTTCTCTCCAATGGCCTGCACCTGGCTCCGGCT
+CTGCTCTACCTGCTGGGAGATCCTGCCATGGAGAAGATCACAGAGGCTGGGCTGCTCCCC
+ACCCTCTGCACACCTCCTGCTTCTAACAGCAGAGCTGCCAGGCCAGGCCCTCAGGCAAGG
+GCTCTGAAGTCAGGGTCACCTACTTGCCAGGGCCGATCTTGGTGCCATCCAGGGGGCCTC
+TACAAGGATAATCTGACCTGCAGGGTCGAGGAGTTGACGGTGCTGAGTTCCCTGCACTCT
+CAGTAGGGACAGGCCCTATGCTGCCACCTGTACATGCTATCTGAAGGACAGCCTCCAGGG
+CACACAGAGGATGGTATTTACACATGCACACATGGCTACTGATGGGGCAAGCACTTCACA
+ACCCCTCATGATCACGTGCAGCAGACAATGTGGCCTCTGCAGAGGGGGAACGGAGACCGG
+AGGCTGAGACTGGCAAGGCTGGACCTGAGTGTCGTCACCTAAATTCAGACGGGGAACTGC
+CCCTGCACATACTGAACGGCTCACTGAGCAAACCCCGAGTCCCGACCACCGCCTCAGTGT
+GGTCTAGCTcctcacctgcttccatcctccctggtgcggggtgggcccagtgatatcagc
+tgcctgctgttccccagatgtgccaagtgcattcttgtgtgcttgcatctcatggaacgc
+catttccccagacatccctgtggctggctcctGATGCCCGAGGCCCAAGTGTCTGATGCT
+TTAAGGCACATCACCCCACTCATGCTTTTCCATGTTCTTTGGCCGCAGCAAGGCCGCTCT
+CACTGCAAAGTTAACTCTGATGCGTGTGTAACACAACATCCTCCTCCCAGTCGCCCCTGT
+AGCTCCCCTACCTCCAAGAGCCCAGCCCTTGCCCACAGGGCCACACTCCACGTGCAGAGC
+AGCCTCAGCACTCACCGGGCACGAGCGAGCCTGTGTGGTGCGCAGGGATGAGAAGGCAGA
+GGCGCGACTGGGGTTCATGAGGAAGGGCAGGAGGAGGGTGTGGGATGGTGGAGGGGTTTG
+AGAAGGCAGAGGCGCGACTGGGGTTCATGAGGAAAGGGAGGGGGAGGATGTGGGATGGTG
+GAGGGGCTGCAGACTCTGGGCTAGGGAAAGCTGGGATGTCTCTAAAGGTTGGAATGAATG
+GCCTAGAATCCGACCCAATAAGCCAAAGCCACTTCCACCAACGTTAGAAGGCCTTGGCCC
+CCAGAGAGCCAATTTCACAATCCAGAAGTCCCCGTGCCCTAAAGGGTCTGCCCTGATTAC
+TCCTGGCTCCTTGTGTGCAGGGGGCTCAGGCATGGCAGGGCTGGGAGTACCAGCAGGCAC
+TCAAGCGGCTTAAGTGTTCCATGACAGACTGGTATGAAGGTGGCCACAATTCAGAAAGAA
+AAAAGAAGAGCACCATCTCCTTCCAGTGAGGAAGCGGGACCACCACCCAGCGTGTGCTCC
+ATCTTTTCTGGCTGGGGAGAGGCCTTCATCTGCTGTAAAGGGTCCTCCAGCACAAGCTGT
+CTTAATTGACCCTAGTTCCCAGGGCAGCCTCGTTCTGCCTTGGGTGCTGACACGACCTTC
+GGTAGGTGCATAAGCTCTGCATTCGAGGTCcacaggggcagtgggagggaactgagactg
+gggagggacaaaggctgctctgtcctggtgctcccacaaaggagaagggctgatcactca
+aagttgcgaacaccaagctcaacaatgagccctggaaaatttctggaatggattattaaa
+cagagagtctgtaagcacttagaaaaggccgcggtgagtcccaggggccagcactgctcg
+aaatgtacagcatttctctttgtaacaggattattagcctgctgtgcccggggaaaacat
+gcagcacagtgcatctcgagtcagcaggattttgacggcttctaacaaaatcttgtagac
+aagatggagctatgggggttggaggagagaacatataggaaaaatcagagccaaatgaac
+cacagccccaaagggcacagttgaacaatggactgattccagccttgcacggagggatct
+ggcagagtccatccagttcattcaacacctggttagaaaactggggccagcacacagggg
+aagggtaagctggtttcatgatcgaatcaaggctcagacaatttttaaaggccagagggt
+agactgcaatcaccaagatgaaatttacaaggaacaaatgtgaagcccaacatttaggtt
+ttaaaaatcaagcgtataaatacagaaggtggagggaacttgctttagacacagttcagg
+tgaagaaagacctggaaacttctgttaactataagctcagtaggggctaaaagcatgtta
+atcggcataaaaaggcaatgagatcttaggGCACACAGCTCCCCGCCCCTCTTCTGCCCT
+TCATCCTTCTTTCAATCAGCAGGGACCGTGCACTCTCTTGGAGCCACCACAGAAAACAGA
+GGTGCATCCAGCACCACAGAAAACAGAGCCACCACAGAAAACAGAGGGTGACTGTCATCC
+CCTCCAGTCTCTGCACACTCCCAGCTGCAGCAGAGCAGGAGGAGAGAGCACAGCCTGCAA
+TGCTAATTTGCCAGGAGCTCACCTGCCTGCGTCACTGGGCACAGACGCCAGTGAGGCCAG
+AGGCCGGGCTGTGCTGGGGCCTGAGCCGGGTGGTGGGGAGAGAGTCTCTCCCCTGCCCCT
+GTCTCTTCCGTGCAGGAGGAGCATGTTTAAGGGGACGGGTTCAAAGCTGGTCACATCCCC
+ACCGAAAAAGCCCATGGACAACGAAAAGCCCACTAGCTTGTCCAGTGCCACAGGAGGGGC
+AAGTGGAGGAGGAGAGGTGGCGGTGCTCCCCACTCCACTGCCAGTCGTCACTGGCTCTCC
+CTTCCCTTCATCCTCGTTCCCTATCTGTCACCATTTCCTGTCGTCGTTTCCTCTGAATGT
+CTCACCCTGCCCTCCCTGCTTGCAAGTCCCCTGTCTGTAGCCTCACCCCTGTCGTATCCT
+GACTACAATAACAGCTTCTGGGTGTCCCTGGCATCCACTCTCTCTCCCTTCTTGTCCCTT
+CCGTGACGGATGCCTGAGGAACCTTCCCCAAACTCTTCTGTCCCATCCCTGCCCTGCTCA
+AAATCCAATCACAGCTCCCTAACACGCCTGAATCAACTTGAAGTCCTGTCTTGAGTAATC
+CGTGGGCCCTAACTCACTCATCCCAACTCTTCACTCACTGCCCTGCCCCACACCCTGCCA
+GGGAGCCTCCCGTGGCACCGTGGGGACACAAAGGAACCAGGGCAAAGCTCCCTCAGCCCC
+ATTCAAAGAGGCCTGGCCCACAGGCTCACGGAAAGTCAGCCTCTCATGCCCCGAGAGCTG
+AGTGCAAGGGAGAGGCAGCGCTGTCTGTGCTTCCCATGCAGAAGCACCCCCCTCCCACCC
+CTGTGCAGGCCGGCCTTCGCGGCAGACCACCATACACCACGTTCCAAGCCACACTGAGGC
+CTCCCTCCAAGCCTGCAGCCCCCATTTCCAGACCCTGCCAGGGCAACCTGCATATCCACC
+TCCCTACCCTGCCCCCCTCTTCCAGGAGTCTGCCCTATGTGGAGTAAGCACgtggttttc
+ctcttcagcaactatttcctttttactcaagcaatggccccatttcccttggggaatcca
+tctctctcgcaggcttagtcccagagcttcaggtggggctgcccacagagctcctcagtc
+taagccaagtggtgtgtcatagtcccctggccccattaatggattctgggatagacatga
+ggaccaagccaggTGGGATGAGTGAGTGTGGCTTCTGGAGGAAGTGGGGACACAGGACAG
+CATTCTTTCCTGCTGGACCTGACCCTGTGTCATGTCACCTTGCTACCACGAGAGCATGGC
+CTGTCTGGGAATGCAGCCAGACCCAAAGAAGCAAACTGACATGGAAGGAAAGCAAAACCA
+GGCCCTGAGGACATCATTTTAGCCCTTACTCCGAAGGCTGCTCTACTGATTGGTTAATTT
+TTGCTTAGCTTGGTCTGGGGAGTTCTGACAGGCGTGCCACCAATTCTTACCGATTTCTCT
+CCACTCTAGACCCTGAGAAGCCCACGCGGTTCATGCTAGCAATTAACAATCAATCTCGCC
+CTATGTGTTCCCATTCCAGCCTCTAGGACACAGTGGCAGCCACATAATTGGTATCTCTTA
+AGGTCCAGCACGAGGTGGAGCACATGGTGGAGAGACAGATGCAGTGACCTGGAACCCAGG
+AGTGAGGGAGCCAGGACTCAGGCCCAAGGCTCCTGAGAGGCATCTGGCCCTCCCTGCGCT
+GTGCCAGCAGCTTGGAGAACCCACACTCAATGAACGCAGCACTCCACTACCCAGGAAATG
+CCTTCCTGCCCTCTCCTCATCCCATCCCTGGGCAGGGGACATGCAACTGTCTACAAGGTG
+CCAAGTACCAGGACAGGAAAGGAAAGACGCCAAAAATCCAGCGCTGCCCTCAGAGAAGGG
+CAACCACGCAGTCCCCATCTTGGCAAGGAAACACAATTTCCGAGGGAATGGTTTTGGCCT
+CCATTCTAAGTGCTGGACATGGGGTGGCCATAATCTGGAGCTGATGGCTCTTAAAGACCT
+GCATCCTCTTCCCTAGGTGTCCCTCGGGCACATTTAGCACAAAGATAAGCACAAAAGGTG
+CATCCAGCACTTTGTTACTATTGGTGGCAGGTTTATGAATGGCAACCAAAGGCAGTGTAC
+GGGTCAAGATTATCAACAGGGAAGAGATagcatttcctgaaggcttcctaggtgccaggc
+actgttccattcctttgcatgttttgattaatttaatatttaaaataattctaccaggaa
+gctaccattattaccacaacttcacaaatgagaacaccgaggcttagaggggttgggttg
+cccaaggttacagaggaagaaaacaggggagctggatctgagccaaggcatcaactccaa
+ggtAACCCCTCAGTCACTTCACTGTGTGTCCCCTGGTTACTGGGACATTCTTGACAAACT
+CGGGGCAAGCCGGTGAGTCAGTGGGGGAGGACTTTCAGGAAGAGGTGGGTTCCCAGTTGG
+TGACAGAAGAGGAGGCTGCAAAGTGAAGGAGCAGGGGCTCCAGGTCTGGCGACAACCAGG
+GAAGGGACAGGGCAGGGATGGCTTGGACCACGAGAGGCACCTGAGTCAGGCAGTCACATA
+CTTCCCACTGGGGTCTACCATGTGAGGCATGGTGTGGGATCCTGGGAAGGAGACCAAGCC
+TCATTTCAGTTTGCTTATGGCCAAAGACAGGACCTGTGTACCCGACAACCCCTGGGACCT
+TTACCAAAAAAAGAGCAAACACCATTCACTCACTCATGTTAGATAAACACTGAGTGAAGT
+CACTGGAGCCCAAGGACTGTGCGAGGTCAGCACTGCCAATACAAGAAGCTGCAGCCCTCC
+AGCTCGCctccctcaatggccactccgtgctccagccatgctggcttccttttaggtcct
+ccacctccaggctgtagttcatgtgcttctttctggaatgttcttcccaacctacccact
+caaccctcagactttaccataaatgtcatttcctcacgtctgccttccctgacctgagac
+caagccaggCTTCCCATGACGAGCCTCACAGTACCCCATCTCCCCTGAACAGATGCAGTA
+ATAACCTACATAACccggggccatgatctatggctttgaatcctggctctgtcactaggc
+caggtctctcagcccttctgtgcctcagtttcctcatctataaaatgagatgacggcagt
+gcctgctcatgaagtgtgagttaatgcactcaaatcaatggttgtgcacggtttatatga
+atattagtgattaCAAAATATTATCAatagaccttgtcacaactgttattgaagaactaa
+tcatctattgcttatttaggtctttctctcctgccagaatgtgcgctccaggtggagagg
+tatgttgccttatccgtggctggatatatagagattcccacactgccttgcacacgagca
+ctgctgggtaaatatttgttggctgcaggaaAACGTGAAGGAATAGGCCCTCCAATGGGA
+GGAAAAGCATGAGTTGTGAGAGCAGAGCCACCACAGGAAACCAGGAGGCTAAGTGGGGTG
+GAAGGGAGTGAGCTCTCGGACTCCCAGGAGTAAAAGCTTCCAAGTTGGGCTCTCACTTCA
+GCCCCTCCCACACAGGGAAGCCAGATGGGTTCCCCAGGACCGGGATTCCCCAAGGGGGCT
+GCTCCCAGAGGGTGTGTTGCTGGGATTGCCCAGGACAGGGATGGCCCTCTCATCAGGTGG
+GGGTGAGTGGCAGCACCCACCTGCTGAAGATGTCTCCAGAGACCTTCTGCAGGTACTGCA
+GGGCATCCGCCATCTGCTGGACGGCCTCCTCTCGCCGCAGGTCTGGCTGGATGAAGGGCA
+CGGCATAGGTCTGACCTGCCAGGGAGTGCTGCATCCTCACAGGAGTCATGGTGCCTGTGG
+GTCGGAGCCGGAGCGTCAGAGCCACCCACGACCACCGGCACGCCCCCACCACAGGGCAGC
+GTGGTGTTGAGACAACACAGCCCTCATCCCAACTATGCACATAGCTTCAGCCTGCACAGA
+TAGGGGAGTAGGGGACAGAGCATTTGCTGAGAGGCCAGGAGCGCATAGATGGGACTCTGC
+TGATGCCTGCTGAGTGAATGAGGGAAAGGGCAGGGCCCGGGACTGGGGAATCTGTAGGGT
+CAATGGAGGAGTTCAGAGAAGGTGCAACATTTCTGACCCCCTACAAGGTGCTTGCTACCT
+GCCAGGCACCCTTTCCATACCTTGTCTCAGTTCAGCTCCCCACCTTGGATAAACAAGAAA
+CCTTGGTTGCAGAGGAAAAAAGAGGCTGGAAACAAAGGGGTAGAAATGGGGTAGCAGGGG
+AGATTGCCTGATCAACTGCCAAATGGTACACAGTTCTGGAAAAGCACAAAAAATGTGCAC
+ACACGGGTTCTTCCCACTTTAACCCCTGAGGAATCTGAGGCCTGCTCCTGAAACAGACTG
+GGCAGTGGCTAGTGACTCTAGGTATAGGAGTATCCAGCCCTGCTCACCCAGGCTAGAGCT
+TAGGGGGACAAGAGGAAAGAGGTGCCTGTGGGGGTGGAGGACAGGAAGGAAAAACACTCC
+TGGAATTGCAAAGTGAGGGCAGAGTCTATTTATATTGGGTTTAATTAACTCCTCTCCCTG
+GTGCCACTAAAGCAGCAATCACACTGCAGACAGCACTGATTTGATTGGCAAGAGATGCAC
+CAGGCAGAATATTAAGGGACCAGGCCCCTATAAATAGGCCTAATCACAGCCCCTCACTGG
+AAAATGGTAAGGAAGACATTAATCAGGCCTGGCACTGTGCCCTAGACCTGCTCCCCTAGG
+CACTACAGTGGGGCCCTTGGTTGCAACACAAGTAGGTAGGGATGGATGAGTGTGGCATGA
+AGGGCCTAGGAGATTTCACTTGGGTTTAAAATGCTGTGACCTTGAGTAAGTTGCCGTCTC
+TGAATCTGATCCTTTCGATTTCCCATTCTCCAAACTGAGAACTAGCACTGCTGAGACGTG
+GTTATTTCCAATAATAATTTGTATATTTTACATAACGCACCACACCAACATCTTCACCCA
+GTTGGAGCCTACTCCTTTGCTCCCGCTGCTGGCTTCCCCAGCCCTCCCTTCTGCCCTCCT
+CAGGCCAGCACTTTTCAGTGAGTTCCTCCTTTGCATACAGGCTTTCCAGATCTGTACTTG
+CCTTGAATACTCATCAGAGCCCAGGAGTTACTCCTCACCTCCCACTTATTTTTCCTCCCA
+TCAAATAACTAAAGCATGGCCAGCTGATGCCCAGCCAACTGAGAAACCCAACCCTCTGAG
+ACCAGCACACCCCTTTCAAGCATGTTCCTCCCTCCCCTTCTTTGTATTTATACTGATGCA
+AGTTTGCTGGCTGTcctaacttatttctgtgcctcagttctcccatatgtaagatcacaa
+agggggtaaagaTGCAAGATATTTCCTGTGCACATCTTCAGATGAATTTCTTGTTAGTGT
+GTGTGTGTTTGCTCACACATATGCGTGAAAGAAGAGTACATACACAGATCTCCTCAAAAA
+GGAGGCAGCAAGCCCGTTCAAGAATGGGACTGAATACACCTGATGAGTGGTTTACTTTCT
+GTCTGCAAACATCTACTGATCATCTGTTAGGTGCAGGCCATGATCACAACAAAGACGAAT
+AAGACACTACACTAGCCAGGGAGAGTCTCAAAAACAACTAAACTCAAATTAAATTCATTC
+TACTCCAGTCATGGGTACAAAGCTAAGGAGTGACAAATCCCTCTTGGAGTTAGGGGAGTC
+AGGAAAAAGCTCTTAGCAGAATGTGTGCCTCTCggccgggcgcagcggctcacgcctgta
+atcccagcactttgggaggcgaaggcaggcagatcacctgaggtcgggagttcgagacca
+gtctgaccaacatggtgaaactccatctctactaaaaatacaaaattagccaggcgtggt
+ggtgcatgcctgtaatccccgctactcgggaggctgaggaaggagaatcacttgaaccag
+gaaggtggaggttgcagtgtgccaagatcgcgccatggcactccagcctaggcaacgagg
+gtgaaCCAGGTCCAGGAAGAAGGTGCAAAGACAGCATTCCAGGTAAAAGAAACAGCTTGA
+ACAAAAAGTGTGTAGGGGAACCGCAAGCGGTCTTGAGTGCTGAGGGTACAATCATCCTTG
+GGGAAGTACTAGAAGAAAGAATGATAAACAGAGGCCAGTTTGTTAAAAACACTCAAAATT
+AAAGCTAGGAGTTTGGACTTGTGGCAGGAATgaaatccttagacctgtgctgtccaatat
+ggtagccaccaggcacatgcagccactgagcacttgaaatgtggatagtctgaattgaga
+tgtgccataagtgtaaaatatgcaccaaatttcaaaggctagaaaaaaagaatgtaaaat
+atcttattattttatattgattacgtgctaaaataaccatatttgggatatactggattt
+taaaaatatatcactaatttcatctgtttctttttacttttAGAAATCACATATGTGACT
+TAAATATTTCTTTTCTTTTTCTTTCCTCTCACTCAGCGTCCTGTGATTCCAAAGAAATGA
+GTCTCTGCTGTTTTTGGGCAGCAGATATCCTAGAATGGACTCTGACCTAAGCATCAAAAT
+TAATCATCATAACGTTATCATTTTATGGCCCCTTCTTCCTATATCTGGTAGCTTTTAAAT
+GATGACCATGTAGATAATCTTTATTGTCCCTCTTTCAGCAGACGGTATTTTCTTATGCTA
+CAGTATGACTGCTAATAATACCTACACATGTTAGAACCATTCTGACTCCTCAAGAatctc
+atttaactcttattatcagtgaatttatcatcatcccctattttacataaggaaatgggg
+ttagaaagaccaaataacattttttcaacatcaaaacactagcttgagatcaagcccaga
+cttggatctgtcgtctgaattccaagctttttgttatttattgatatgttttgttgtTTT
+CATGCAATAATGCAAATCTTAGCCCAAACATTTTGTTAGTAGTACCAACTGTAAGTCACC
+TTATCTTCATACTTTGTCTTTATGTAAACCTAAATTAGATCTGTTTTTGATACTGAGGGA
+AAAACAAGGGAATctaacactaaccagcccgtagtgtgtggtcaacactttcgttacttt
+agtatacatcaccccaattgtttgtcttcaccacacactttggagttaggtagtagtatc
+tatttttacaaataagaaaacccaggcacaaaggggttgattagcAATTATCTTTTGAAA
+AGCCTGTAGTTGCTCATCTGAAGAAGTGACGGACCACCTCTTATTTAGTGGACAGACAGT
+AACTAGTTGAGAAGACAGGGGATTTTGTTGGCGGAAAAAAAAATTTATCAAAAGTCGTCT
+TCTATCAGGGAGTTTTATGAGAAACCCTAGCTCCTCAGTTCCACAGTGGGTAACTGTAAT
+TCATTCTAGGTCTGCGATATTTCCTGCCTATCCATTTTGTTAACTCTTCAATGCATTCCA
+CAAATACCTAAGTATTCTTTAATAATGGTGGTTTTTTTTTTTTTTTGCATCTATGAAGTT
+TTTTCAAATTCTTTTTAAGTGACAAAACTTGTACATGTGTATCGCTCAATATTTCTAGTC
+GACAGCACTGCTTTCGAGAATGTAAACCGTGCACTCCCAGGAAAATGCAGACACAGCACG
+CCTCTTTGGGACCGCGGTTTATACTTTCGAAGTGCTCGGAGCCCTTCCTCCAGACCGTTC
+TCCCACACCCCGCTCCAGGGTCTCTCCCGGAGTTACAAGCCTCGCTGTAGGCCCCGGGAA
+CCCAACGCGGTGTCAGAGAAGTGGGGTCCCCTACGAGGGACCAGGAGCTCCGGGCGGGCA
+GCAGCTGCGGAAGAGCCGCGCGAGGCTTCCCAGAACCCGGCAGGGGCGGGAAGACGCAGG
+AGTGGGGAGGCGGAACCGGGACCCCGCAGAGCCCGGGTCCCTGCGCCCCACAAGCCTTGG
+CTTCCCTGCTAGGGCCGGGCAAGGCCGGGTGCAGGGCGCGGCTCCAGGGAGGAAGCTCCG
+GGGCGAGCCCAAGACGCCTCCCGGGCGGTCGGGGCCCAGCGGCGGCGTTCGCAGTGGAGC
+CGGGCACCGGGCAGCGGCCGCGGAACACCAGCTTGGCGCAGGCTTCTCGGTCAGGAACGG
+TCCCGGGCCTCCCGCCCGCCTCCCTCCAGCCCCTCCGGGTCCCCTACTTCGCCCCGCCAG
+GCCCCCACGACCCTACTTCCCGCGGCCCCGGACGCCTCCTCACCTGCGAGCCGCCCTCCC
+GGAAGCTCCCGCCGCCGCTTCCGCTCTGCCGGAGCCGCTGGGTCCTAGCCCCGCCGCCCC
+CAGTCCGCCCGCGCCTCCGGGTCCTAACGCCGCCGCTCGCCCTCCACTGCGCCCTCCCCG
+AGCGCGGCTCCAGGACCCCGTCGACCCGGAGCGCTGTCCTGTCGGGCCGAGTCGCGGGCC
+TGGGCACGGAACTCACGCTCACTCCGAGCTCCCGACGTGCACACGGCTCCCATGCGTTGT
+CTTCCGAGCGTCAGGCCGCCCCTACCCGTGCTTTCTGCTCTGCAGACCCTCTTCCTAGAC
+CTCCGTCCTTTGTCCCATCGCTGCCTTCCCCTCAAGCTCAGGGCCAAGCTGTCCGCCAAC
+CTCGGCTCCTCCGGGCAGCCCTCGCCCGGGGTGCGCCCCGGGGCAGGACCCCCAGCCCAC
+GCCCAGGGCCCGCCCCTGCCCTCCAGCCCTACGCCTTGACCCGCTTTCCTGCGTCTCTCA
+GCCTACCTGACCTTGTCTTTACCTCTGTGGGCAGCTCCCTTGTGATCTGCTTAGTTCCCA
+CCCCCCTTTAAGAATTCAATAGAGaagccagacgcaaaactacagatatcgtatgagtcc
+agttttgtgaagtgcctagaatagtcaaaattcacagagacagaagcagtggtcgccagg
+aatggggaagcaaggcggagttgggcagctcgtgttcaatgggtagagtttcaggctggg
+gtgatggaagggtgctggaaatgagtggtagtgatggcggcacaacagtgtgaatctact
+taatcccactgaactgtatgctgaaaaatggtttagacggtgaattttaggttatgtatg
+ttttaccacaatttttaaaaaGCTAGTGAAAAGCTGGTAAAAAGAAAGAAAAGAGGCTTT
+TTTAAAAAGTTAAATATATAAAAAGAGCATCATCAGTCCAAAGTCCAGCAGTTGTCCCTC
+CTGGAATCCGTTGGCTTGCCTCCGGCATTTTTGGCCCTTGCCTTTtagggttgccagatt
+aaaagacaggatgcccagctagtttgaattttagataaacaacgaataatttcgtagcat
+aaatatgtcccaagcttagtttgggacatacttatgctaaaaaacattattggttgttta
+tctgagattcagaattaagcattttatattttatttgctgcctctggccaccctaCTCTC
+TTCCTAACACTCTCTCCCTCTCCCAGTTTTGTCCGCCTTCCCTGCCTCCTCTTCTGGGGG
+AGTTAGATCGAGTTGTAACAAGAACATGCCACTGTCTCGCTGGCTGCAGCGTGTGGTCCC
+CTTACCAGAGGTAAAGAAGAGATGGATCTCCACTCAtgttgtagacagaatgtttatgtc
+ctctccaaatgcttatgttgaaaccctaacccctaatgtgatggtatgtggagatgggcc
+tttggtaggtaattacggttagatgaggtcatggggtggggccctcattatagatctggt
+aagaaaagagaGCATTGtctctgtgtctccctctctctctctctctctctctctcatttc
+tctctatctcatttctctctctctcgctatctcatttttctctctctctctttctctcct
+ctgtcttttcccaccaagtgaggatgcgaagagaaggtggctgtctgcaaaccaggaaga
+gagccctcaccgggaacccgtccagctgccaccttgaacttggacttccaagcctccaga
+actgtgagggataaatgtatgattttaaagtcgcccagtgtgtggtattttgttttgact
+aatacaaCCTGAAAACATTTTCCCCTCACTCCACCTGAGCAATATCTGAGTGGCTTAAGG
+TACTCAGGACACAACAAAGGAGAAATGTCCCATGCACAAGGTGCACCCATGCCTGGGTAA
+AGCAGCCTGGCACAGAGGGAAGCACACAGGCTCAGggatctgctattcattctttgtgtg
+accctgggcaagccatgaatggagcttcagtcaccccatttgtaatgggatttaattgtg
+cttgccctgcctccttttgagggctgtagagaaaagatgtcaaagtattttgtaATCTgg
+ctgggcgtggtggctcatgcctgtaatcctagcactttggtaggctgacgcgagaggact
+gcttgagcccaagagtttgagatcagcctgggcaatattgtgagattccatctctacaaa
+aataaaataaaatagccagtcatggtgtcacacacctgtagtcccagctacatgggaggc
+tgaggcgggaggatcacttgagcttgggagatcgaggctgcagtgagctatgattgtacc
+actgcactccaggctgggcgacagagagagaccctgtctcagaaaaaaaaaaaaaaGTAC
+TTTGTAATCTGTAAGGTTTATTTCAACACACACAAAAAAAGTGTATATGCTCCACGATGC
+CTGTGAATATACACACACACCACATCATATACCAAGCCTGGCTGTGTCTTCTCACAAATG
+CACTGCTAGGCACCACCCCCAGTTCTAGAATCACACCAGCCAGTTCACCCTCCAGATGGT
+TCACCCTCAACTTCATAAAAGTTCCCTACCTAATCTACTGACAGGCTCATCCCCGACCTA
+ATTTTAAAGATTTCCTAGGAGCTGCAGTGGGAATCCTGGACCTCAGCCTGGACAAAGAAC
+AGCTGCAGGTCATTCTCATGTGTGGACACAGAAGCTCTGCCTGCCTTTGCTGGCCAGCTG
+GGCTGAGCGGGCCTGGGAATTAAGGCTGCAGGGTTGGTCCCAGGCAGTCTTGCTGAAGCT
+TGCCACATCCCCCAGCCTCCTGGATTTGCCAGGATCCAAGAGCATGGACTTTAGGAATTC
+CTGGTGGAGGAGTGAAGAAAATGTGACAGGGTGTCCTAAGCCCCGATCTACAGGAAGAAA
+ACTGGAAATAAGACTGAGGACTTAGTTTAAGATGTTCCTACTCAGCCTCTAGCTTTTGTG
+CTACAGTTCTGGGAACAGACTCCTCTCTCCTGAAAACCACTTCCCTCCGCAGCATTAGAT
+TTCACCAAGATGTCTTGCTTGTGGGAAAGACTTCCAAGGATGCCTGGAGAGAGGAGGATG
+GAAATGTCCTGCTCTCTAAACAGATAGACAGATGCAGCCAGACAGAAAATAGTTTATCTT
+GCTGAGGTTTCTAATGTATTTGAAAGAGGCCTGGGTCTAGAAGTCTACCCAGAGGGCTCT
+GTGTTGTGCACGCAAAGATAAGAACCTTCCCTGTGGGAGTTCCAGAGCCAGTTTTCATAA
+ACACCCATCGGTGACTGTGTTCAGAGTGAGTTCACACCATCCTGACCTGCCCTGAGTTAG
+ACCTTACATGGTCTTCCTCCTCTAGGAAGCCTCTGCAGCCCAGGAACCTCCCCTTATCGG
+AAATGAACAGCATTTGAAGCTTCACCAGACAGACCAGACAGCTTAGCCCTCGTGTTGTGC
+CATGTGGGTTGTTCTCTGAGAGGcaggagagcatagtggttactaggaagggaaggactt
+tgggactagactgcctcggctggagtcctctttctgcttcatagccacgtgatcctaggc
+atgttacctgtgcctcagttttcactctgtcaatatgtaataactgaatctgtctttgtg
+gtgaggattcagtgagttaacatatttgaagtgcttaaaaATGAGGCTTGtgtccataga
+ttaatgagtgaatacacaaatggtgatatggacatacagtggagtattagtcataaaaag
+gaaggcagagctgatccatggcaccatgtgacagaacctcaaaagcattaggttaagtgg
+aagaagccagacacaggtcacctattgtgtaattccatttataggaaatatacagaatat
+gtaaatccgtggagaaagaaagccgatttccaggggctaaggggaggggagaatgggaag
+tggctgcttcatgggtacaaggtttcattttgagctgatgaaaatgttttggaactacat
+agagatagtgttggcacaacatggtgaatgtactgaatgccactgattgttcaatttaaa
+atggtcaaacttatatgaatttcacctccattaaaaaaaAAAAAAAAGgaccagatgtgg
+ttgctcacacccataatcccaacactttggaaAAAGGTGAAAGTTTTTTTTtcttttttt
+ttttatatacttaagttctagggtacatgtgcataatgtgcaggttggatacatagatat
+gcgtgtgccatgttggtttgctgcacccatcaacttgtcatttacattaggtatttcttc
+taatgctatccctcccccagccccccacccactgacaggccccagtgtatgatgttctct
+gccccatgtccaagcgttctcattgttcaattcccacctgtgagtgagaacatgcagtgt
+ttggttttctgtctttgtgatagtttgctcagaatgatggtttccagcttcatccatgtc
+cctgcaaaggacatgaactcatcctttttaatggctgcatagtatcccatggtatatatg
+tgccacattctcttaatccagtctgtcattgatggacatttgggttggttcaaagtcttt
+gctattgtgaatactgccacaataaacatacatgtgcatgtgtctttatagtagcacgat
+ttataatcctttgggtatatacccTAAGACctgggacgcatttaaagcagtgtgtaaaga
+gacatttatagcactaaatgcccacaagagaCCTCTGCCTGAGAACGTGGGTTTCAGCCT
+AAGAGTTGTAATATGTGTGCCCATTCACAGGTGCTGCATCAGAGTCCCAGGTGGGAAGAA
+GGCAAGCATACACAAAAATGGTAAaaggcagaaaggagcccagtctcgttctttttaaga
+agttttcctaagaatctccacccagcgacttgctctcacatcttcttggccagcactgga
+ccacacaactccttctagatacagaggagTCCTAGGATTCTATGAGAAAGAAGGGGAGGG
+TGGGCAAAGGGCAGCCAGCTGTGCAGCATCTGCTGGAGACACCTAACCCTTGGTGGAGGG
+GTTGTGGTGCTGGgagaaggctttctggacggtgtgacagcagagataaacttaaaggcc
+aagtaggagttaccctggtgaagcagggcagggttacaagcattccagcaacatgaagca
+gcaGGAGtgttttaattaaaagaaggcagttgctgtaaccaactataaacaaataaaggc
+ttaaacacaatggaagtttatttctcactaagggaacatccaaatccatgatactttaag
+tcagggacccaggttcctcccatctatggttctgccatcactaatctgggtcttccacaa
+ttgccgtgctccttggaggtgggaagagcaggcggaggacacgtgggaggttttagggac
+aagcctggaggcagcatgcgtcactcccatgcagagtccattggccaatgctggctccga
+tggccacatctcactgcaggggcagctgggaaatacagtctggctgtctacccaggagga
+agagcagccagtttctgctgCTGATGATCAGGAGGTGGAGAAAATGTTCAGTCAGGCAGG
+GAGTGGGAATAGACAAGACCACAAGCAGCTTGGTGCCTCTGAAAGGGAGAGGGGTGGAGG
+GGAGACTAGAGAGGTGGGTAGGAATACTGGATTCCACTGACCACGTGCTGGATGTCACGC
+TTAGCCCTCCTGCTCTGTGCCGGGTTAGGCACCTGGTGTTTTACGTACATAATCTCAATT
+CTGTGAGGGCATCCGACCTGTGGGAAAAGAGCTGTTTGTTTCAAATGCCAGTCCTGCTTC
+CTAACAAGTGTTTAGAGCTTAATCGTGTTCAAAAtacatatacaatgtttaatacttaca
+agaatttggtggggaaaatattaccatctttcccttttgtgattggagaaaaatgaggct
+ttgaagggtttaagaacttgcccaaggtcggccaggtgcagtggctcatgtctataatcc
+caacactttgggaggctgaggtgggaggatcgcttgaggccaggagttcaagaccagcct
+gagcaacatagtgagactttgtctctataaaaaataaataaataaataaaaaCAACTTGT
+CCAAGGTCAGACAGGCAGCCTCTTAGTAAGCACACATATCCTCTATATTATACTACCTCT
+CATGGAGGATCTCCTGTGTTCTACAAATAGTCTGGACTTGAGCCAGAATGTGTTATAATC
+CTGGGATCACGGCCAGTGGGCTTAGAAGAAGCCATCTCTTTCTCATGCCAAGATGAGGCT
+CCCCCAGATTTGCTCAGACTTACCTATAGTCAGCAGCATCGGGGGTCAGGAAAGACTTCA
+CGAAGCCATAAATGCATCCTTCTCGGGGCAGCACCTGGCTCTCCCAGGTGAGAGAGGACT
+CCATTTTCACAGGCAGGCGTGGGAGCTTCAGCACCCATCTCTGGGCCCAGAATGACCCAC
+TGGAGACCTTACAGCTCTCCTGTCACCCCCAATTCCTGCCCCCTCTGCAGCCTTGGAGGA
+GAATGGAGCTGAAGGGCCTGCCCTCTGTAGGGTGAGAAAGGGAGGCTAAAGCCTGGTGCC
+CACTGCCCTGGCTGCTCCGCATTGCAGGAGCTGCGCCCTTCCTTTCCTGGCACAGGGTCC
+ACAGCCCCGAAACCCCGTTGTGTGGGAGCTGGGCACAGGGCAGCAGGACTAATCCTTGGA
+ACAGCTCAGGGAGGATTATCCCAGCCACTGTCAGCAGCGGTGCAGCTGGCTCATTCCCAT
+ATAGGGGGAGGCCAGAGCCAGGGGCCTGCCACAAGTTGGAAGGCTGGGGAAGGGGAGGCC
+AGCAGAGGTGTCCTGGCTGTGGGTGGCTCTGAGGGGGCTCTCAGGGGTGGGGCTAAATCT
+CAGGGGCAGGATTATGTAAATCAAACCAATTCTAGCCACAGATTTAAAGTTTGGAAAAAA
+AAAAAAACCCAGCCTGGCGGAAAGAATTTAAATTATAAAAACTTAGAAGTATGGAATGTG
+AAATCATCCTGTAGGTGCTTATTTAACAACGAAATCATCCCGACACAATGAGCCATATGT
+GAAAAGTCATCCTTCCCCAACACATCCCCCAACAGGCACTCCTCAAGCCTCTCCCACCCA
+AGTGCTGGCATCCTCCCTGTCCTGCTTCACCTGAGACACCCCTTGTCTCATTAGACATGC
+AACTACGGGAGGGGTGACAGGAAGACAAGACACTATTTCCTCAGGCCCAGTTTGGTGTGG
+GGAGAAAGCCTCCTGATCCTGAAAGCAAGAATTTGACCAGAGCAGAAGTAATCAGTATGC
+AGATTGATTCTGTGGTATGTTAATGTTTATGCATAGATTATGAGGACCAGGTGAAAAGTG
+GGCCAGGGGAGCCAGATGTGTGTGTGAGTCATGGGTGGCTGAGATGAGGACAGGAGGGAA
+ACTGGTTTGGAGGGTGCTGGCGATGGGGTGGGGGTGCCAGGAGGAAGGGAGGCTAGTTGT
+TTGAATGTCTGCATGAAAAAGCGGACGACAGCGGGGTCTGGGTGAATTCGGGCAACCATT
+TGGACCGTGGAGAAAACTGCCTGCGTGCGGCTGAGGACCTGCACTATTAATTTGTTTTTT
+AGCTAAGGCAAAGATAAATATAAAAACtgatactccacccagttaccagaaaacatttag
+gtatgtgtgagacaacttgggtatgtgaacctaccttttcaatgtaaattcagtgaaatc
+taagtgcagatcccatatttccaataaaaaggtaacatccaaactcagatgtcctatgag
+tataaaatacacaaagatcttctggacttagtatgaaaagggattttttttttgtcaggt
+acctcactagttatttttaaaataggattgcatgttgaaatgataatcttttggatatat
+tgggttaaataaatttattattaaagttaatttcacttaaaaatgtttaatgtagctact
+agaaattttaaaattaagcatgttgctcaccttatgtttctattggacggctctCTCTAG
+ATACAAAGGCTGCCAAGAGGGACCTCACTCTAGCTTCAGGGAGAAGAGAGGAATTAGCAA
+GGCCAAGCAGAGGCTCCTGAGGGCAGGGCCAAGGGCGGCTTGGTGGGGTGGGGATGGGAT
+GCACAGAGATAACTCCAACCCTTAAGAAGGTGTTTCCTAGAGCAGGCTGTGACCTGTCAG
+TTTATATACTGAGGCTTAGGAGCCTCTTGGATGCCCCCAGATCTGCACCCCTGAATTGCC
+CTGTGCCCCTGCCGTCTTTGTTCCTGTGCTGGCATAGTGGTCTCACCTCCGGCAGtatca
+ccaccactgggcacaagcttctccagcacagcaactgtgtcttatttctccttgtactcc
+cagtgttcacaccatgctgcactcacagaagactcttcgttgatattttgtggacagaga
+gaatGCCTGTGAGAGTGGGCTGAAGTGTGCGTTGGGCTCCAGAGACCTTAAGGAGGGGAG
+ACCAGGTCCTGAGTAAAGTTGAAGGGGAGGGGCTGAGTCCTGCTAGCCAGGAGTCTCATC
+CCCTGGGGAAGTTCCAGGGACCCCTCAGAAGTGCAAGGGGACGGTGTTAGTGTTAGTCCA
+GTAACACAGCCCAGAGCCTGCcttccacgtgggtttgacaggagcctcctaactgctctt
+ctgcttccatttttgccccttcagtctattctcaacagggaagccagaggcatccttaac
+catgtcagatcatgtggctcctcagctcaaagccTCATCTCAGAGGAAAGCTCTGGTCCC
+TTAGAAATGGCCCAAGTGGTGACAGACAGACTCTAAGGtgagcagactgttgctagatat
+ctgggctcggaggactcgccactgctcaaaggcagtgaggattttcgcactagaagctgg
+aggacagggatccttgttaggtaggagcagaaagcttagaaaagtggtctcctgcagtta
+cgtggcaaacacatcatgtaagtgataaattgggtatgcagttgaggagatttccaagta
+aaatgttgaggatgctgcctggtttcttcttactgcttataatatagtgtgagagaagag
+agataaattgagaaagagactggtttttaaactgttaaaattgaatcaggacttgatgat
+tttgaaaattgtcagtctccccacatggaaaaagatgctgaaattaacaaatggcttctg
+agcatgtggcatagggtgtaactgtacagtcttttgtgattatgcataaagatcaaagga
+tgggagtagcaatgagtcacacagaggtctgttgcaagagattacaagggtgtaccatgc
+agaacctctccaccaaaccttagggcccttgggaagcttcagtgagttaccctgggggcc
+atcttggcaggagctgaaggtagaaaggtagagtttatctctaaaagattcatgggtatg
+gctcttgacaaatcgactatgagccccaccgaaacccacagaggacaggcaaagggtttg
+ggaaagctgtttcacccacagtgctggcagattggtctgtaggggacagagtgcaaaatg
+aaagaagactgtcagagaccccaaactctgctgtcaagaagaaggctgataaaactactt
+ggctgcaaacacgtggatctttcgtgagaaaagaaggatgacccagaggcagaagcccag
+aaggcagagccaagagacatggaatcttcccacatcttaaaacctgtttagggaacacca
+gcatctgtccagctggatttcagaaccaccattccttcatccttcccctgctgcctcttt
+ctgaacagcaatgtctcaagctttacccaccattgtgtgttgcatatgtagggggcagat
+agcttgtatctttagttttccagatcagaggaacatccaaagaaatctgttctacaccta
+aacccgatttagatgagattcgggactgtgagcatgaagggatctcaagaggggtgaatg
+tgttttgcatgcacaagggacaggagtcttggggacagaggacaggctgtggtggcagat
+actaaggtgacccccacaacccccacctctgccattcacacccttgaataatccccttct
+ctggttgtaagcagaacctgtggcttgcttatgaaggaggcggtatatatgtgattcatg
+tactgatcatattgtataagatcactggctggatgcagtggctcgtgcctgtaatcccaa
+cactttgggaggctgaggcgggtggatcacctgaggtcaggagttcgagaccaggctggc
+caacatggcaaaaccccgcctctactaaaaatacaaaaattagccaggcatagtggtgca
+cgcctgtaatcacagctactcaagaggctgaagcaggagaattgcttgaactcaggaggt
+ggaggtggcagtgagccaagatcgtgccactgcactccagcctcagtgacagagcgagac
+tctgtctcaaaaaataaataaataaaatgttaagatcataacctgtctttctggggactc
+tctcttgacgcctttgaagaagcaggctgccatgttgcaagctgcctcatggaggggatc
+agctgcgaggagctaagagccccctccagtcgatgctcaccaggaagctgaggtcttgtg
+tccagcaccctgcatagaactgaatgctgccatgtgagcttggaagcagagccatccaca
+cagctgagccctagatgagaacccagtgctggctgacaccctgatggcaccttacagagg
+accagttaggctgtgccaactcctgacctgcagaagctggggaacactgggtcgtatttg
+cagctgctggatttgtgggaatttgtcacacagcaatTGGGAGTCACACAGCCTGTGACG
+CCCCAACAATCCACAcctcctgcatctccctgccttcacttcctagcacactgccctgac
+tccctctgccgcagccacgctggccctctgctgttcttcgaagccaccagggctgcattg
+gctcccagcctttgctctcactgctttctcctcctagagagcccttcctgcatgtatatg
+tttgactcactcccttgcctccttcagacttgtacttaaaaatctcagtaagcatttccc
+tggctacccttttaaaaattgcaacccacttccatccccatccccaacatgccatatttc
+ctttcttcttcttccttcttcctttttttttttttttttttgacacaggttctctgtcac
+ccagcctggagtgcagtgacatgatctcggctcactgcaacctctgcctcccCAGGCAag
+aaaaggggaggatgccaataaaggatgcattgatttgtatttactacagtggacatcaag
+ggcacattcttgctgtggccatcaagagactgtataaattctatgacttgtagttgtccc
+acttaagaaacaaagaagctgtgcatttctttactggtctagagctgctctagggcattt
+tctctacagcaattctaggtttccccaccttgtgagtttagctttttctatattcaaaga
+aaagtcctcagccagagattctcaggagcttatagaacaatccaaactcttgggaatatt
+aagtggagaggggtacgtgcaagacaccaacagcACTAGAAACAGTCCACATCTTTCCAT
+GCGTGGAGGAGTTTATGCTCTATGTGAGTTCACTCCATCATTAATTCTTCAAACACAAGA
+GTGTTAAAGGAACAAGAGTTAATGGGTCCTGTCATTACACTTGTTCCCAGGATGACATTC
+TTCATCTTCCTCTTCTACAACCTGTTCTATATTCCCCTCATGTTTATCCAGTGCTTCTGC
+TAGTCTAGTTCACTTCCAAAGACCCATGATTACCATGGCCCTGTCAGGCTGTAATTGCTG
+CAATTTCCAATTTACAATTGTCATCATCTATGGTTGATAAAGgtatagcaatatttctat
+ttcctcatgataatgaaggtcaattacaactgccagtataataacttatttctttgtctg
+ccaacctacatacacaaggaagccaaaatgacagggagctactaaaactttattcttatt
+ggaatgcttactatgtacccagaagaagcattctccctactccagcagagcttaatgctg
+taggtccaggaagctcaaattctccaagggagttttagtgagaggagccactctcaccct
+ctgcccttggtttacaaacctgtatattctaggacccaatatcttacaatgtccattggt
+tcaaagtataacatgttaaagcacagagccccaactctgaaaagtaccatccctaaattg
+gcatttagttgcacctttatatccacctttaaaagaaatatcttttaatgttctatcaga
+ctgatagattctgtttaatatagtatattatagcaccagtggatcatttggttgtatgca
+tattattgtaccttctctgctacaaaatatattcctttgtcctaaggtgtgttacaaaga
+acattaggcattctatgcatctttggatagtttaatggccaagacattgatggcaggaga
+gtcaaagccacaggtggaaaacacatttatcccagtaagaacaaattgctattcttccac
+tgtagagagggtaaacaatgtgccattacgttgccaattgaatgcctcaatcatgtcaag
+ggctgaacatctatgactgtttctgaaaggtcaaacattcaacagaggctgtagctagaa
+ctgccttaatgataagagatcatgctgaattacccatgcaaaaccttaatacttgacact
+tatcactactttattcaagagcctattgtgcaagcataagtggctgagTCAGGTTCTCAA
+CTCTGCTCATTAATACTATGCTTGGAGTATACAGTAAGATAAGAAACATAAATAAGAAGT
+GTACATTTGTTTCTTCCTGTTTTCTTCTGGCTATTGGATCAATTACATCCCATCTTAAGC
+TGACCCCTGTGTAATTAATCAATATCCGTTTTAAGCAGCAATCCATAGTTGTGCAGAAAT
+TAGAAAACTGACCCACACAGAAAAACTAATTGTGAGAACCAATATTATACTAAATTCATT
+TGACAATTCTCAGCAAAGTGCTGGGTTGATCTCTATTTACGCTTTTCTTAAACACACAAA
+ATACAAAAGTTAACCCATATGGAATGCAATGGAGGAAATCAATGACATATCAGATCTAGA
+AACTAATCAATTAGCAATCAGGAAGGAGTTGTGGTAGGAAGTCTGTGCTGTTGAATGTAC
+ACTAATCAATGATTCCTTAAATTATTCACAATAAAAAAAAAGATTAGAATAGTTTTTTTA
+AAAAAAAAGCCCAGAAACTAATCTAAGTTTTGTCTGGTAATAAAGGTATATTTTCAAAAG
+AGAGGTAAATAGATCCACATACTGTGGAGGGAATAAAATACTTTTTGAAAAACAAACAAC
+AAGTTGGATTTTTAGACACATAGAAATTGAATATGTACATTTATAAATATTTTTGGATTG
+AACTATTTCAAAATTATACCATAAAATAACTTGTAAAAATGTAGGCAAAATGTATATAAT
+TATGGCATGAGGTATGCAACTTTAGGCAAGGAAGCAAAAGCAGAAACCATGAAAAAAGTC
+TAAATTTTACCATATTGAATTTAAATTTTCAAAAACAAAAATAAAGACAAAGTGGGAAAA
+ATATGTATGCTTCATGTGTGACAAGCCACTGATACCTATTAAATATGAAGAATATTATAA
+ATCATATCAATAACCACAACATTCAAGCTGTCAGTTTGAATAGACaatgtaaatgacaaa
+actacatactcaacaagataacagcaaaccagcttcgacagcacgttaaaggggtcatac
+aacataatcgagtagaatttatctctgagatgcaagaatggttcaaaatatggaaaccaa
+taaatgtgatatgccacactaacagaataaaaaataaaaatcatattatcatctcaatag
+atgcagaaaaagcattaacaaaagtaaacattctttcataataagacatcagataaaaca
+aattaggaatagaaggaatgtaccgcaacacaataaaggccatatataacaagcccacag
+ctaacatcataatagtaaaatcatcacactggtaaaaaaaatgaaagcttttcctctaag
+gtcagaaataatataaaggttcccactcttgctatttctattccatatcgtactaaaagt
+cctagccaggacaattagacaaaataaaaataaaaacacccaaattggaaagatagaagc
+aaacttttctgtttacagataacataatcttatatgtagaaaccccttaaaacttcagca
+aaaaaaaaaaaaaaactacagagctagtaaattcagtgaagttgcagaatacaaaatcaa
+catacaaaaatcagtagtgtctctatacactaataaggacttaacagagaaagaagttaa
+gaaaacaataccactaacaatagaatccaaaaaataaaatacttaggaataaattttacc
+aaacatctgtacactaaaaactataaaacattgaaaaaagaagttgaataagacacatat
+aaatagaaagctatctcatgttaatagattagaaaaagtaatattgttaagatgtcctca
+ctacttaaagcaatttatagatctaatgcatttattgcaatctcttcaaaatcccaaagg
+tatttttgacagaaataaaaaaaaaattctaaaatatgcatgaaaccacaaaagactgtg
+aatagctaaagcaatcttgagcaagatgaacaacactggaagcatcacactaccttattt
+caaaatctactacaaagctatagtgatcaaagcaacatgatactgtcataaaaacacaca
+gataaacctatggaatggaataaagagcacagaaataagtccacacatttacattcaatt
+gattttcaacaacaatgtcaagaagacaatggggaaaagacaatctcttcaataaatgat
+gctggaaaaactatatatccacatgcagaagaatgcagttgaatcctgatttcataccat
+atgcaaaattcaactggaaatggattaaatacaaatttaaaacatgaaatggtataacta
+ttagaacaaaacatagaaaatattcttcctgacattggtttgggccatcatttttctgat
+atgactctaaaagcacaggcaaaaaaagaaaaaatagacaaatgagactatgccaaatta
+aaaaatttctaacaacaaaagaaacgatcaatagagtgaaaaagataacctcttgaatgg
+gagaaatatttgcaaactactcatccaaccggggattgatatccagaatatacaagtaac
+acaaatatgtcaaaagtaaaataaataaataaataaataaataaataaattaaataaatt
+atttaaaaatcggcagaggacaggaatagacatttctcaggagacaacatacaaagggcc
+acagatacatcaaaaaatgctcaacatcactatttgtcagggaagtactaattaaaacca
+aaatgagatgtcccctcaaacctgttagaatggctattatcaaaaagatgaaagatagca
+actatcagagaggatgatagaaaagggaacccttgcatcatgtacaaattaaaaatagaa
+ctatcacatgatccaagaatcctacttctgggtatatagccaaaggaattgaaatcaata
+tgtcaaagggatatctgcactcctatgttattgcagcatgttcacaatggccaagatata
+gaatcaacctaactgttcatagacagatgaatggataaatgaaatgtgatatggaaaatt
+attcagccttaaaaacagtaggaaattctgtcatttgagacaacgtggatgaacctagag
+gacattaagctaagtgaaataagctagacacagaaagacaaatattgcatgatctcactt
+agaatctaaaaaatctgaactcatagaagcagagaatagtatgatggttactagggttat
+ctggcagggagaggatgaggaaatgggacattgttaataaaaggaaaaaaattcaattag
+taggattacattcaggggacccaatatacgacatgttgactgtaattaataatgtattgt
+atgcttgaaaattgctaatacagtatattgtaaatgttaatatgaggtaatatatgtgtt
+aattaacttgatttattcattcaacaacatacacatatattaaaacatcacactgtattc
+cacaaatatatataatttttgtcaattaaaaaaTAATTTTTAAAAATGAGAAACAAAAAA
+GCTGACATTTTCAGATTAAAAAAATTATACAGAAGAATTAATTCATTAAAGTAAAAACAA
+ATGTGGGAAAATGGTTTTTAAATATAATTTAAACCAAATTTAAAATAAGCATATaaagac
+tatggacaaaacaagaaatccaaataaaaaataaacatatgaagaatattcaaactcact
+ttttatcaaagaaatgtaaattTTAAAATATAGCATTGCTATTGTGTTTTCATAAATAAT
+AATATATCATGGATGAGCCTGTGAGGAAACAGACACTCATACTCTGCAAAGCAATGACTA
+Agataattatgtcagatcatgaattacgttaattagcttgatggtggtcactgtttcacg
+ataaatatacatatgtatcaaaacatcacattacacaccataaagatatataacttgtta
+tCAAAAAGAAATATAGCAGttaaaatttaaaatttttaaaaaaCGTCTTTTTGAGGTTCG
+TACCTCACTTAAGTCACACTGTTCAAAATATTCATGCACTCATTTCTCTCATTCATGTGT
+TAATGTACAGGGTACGGGCCACTATAAATTCCTTCAGCAACTGGAAAGGAAACTTTATGT
+ACTGAGTGCTCAGAGTTGTATTAACTTTTTTTTTTTTTtgagcagcagcaagatttattg
+tgaagagtgaaagaacaaagcttccacagtgtggaaggggacccgagcggtttgccCAGT
+TGTATTAACTTCTAATTCAACACTTTAAGATTCTTAGCATTATTGCAGACAACATcagct
+tcacaagtgtgtgtcctgtgcagttgaacaagatcccacacttaaaaggatcctacactt
+tttttaatgctctgctgtttctgccttgaaattcttaacaatttttttaaccaaagtcct
+cacaaattcagtttacattagccctgcaatcatgtagacatcctgATTCCAGACAATGTG
+TCTGGAGGCAGGGTTTACAGGACTTCAAGAACCTTACCTTCTCAACTTTCATCTGCATCT
+TTACTCCCAACTATATATGAAGATGATGAAGATAGATATGGATGGTGCTTCTACCATACC
+CTCTTCCTCTGCCAAACTTCCTTGATCTAGGATAAggtcagtaaacttcttccgtaaaag
+gccaaaagtaaatattataggctctacaggccctagagtgtctgtcataactactcaact
+cttattgtagcataaaaactgtcaacagacaatacagaaacaaatgagtgtgactgggtt
+ccagtgaaactttatttacaaaagatttgtcccatgagtcaaatttaccacctccAGATC
+TAGAGAAACAGTTTTGAGCCCTTTTATTTTGCTCAACAGTTAAGCATGGCTCCATGTCCC
+TTATATTTAGTCAGAACTCGGTATGTTTTAAGGAAAGAATGGTTACACGAAGACATACAT
+TCATTCATTTATACAACACATTTTCAGTGTTGAATGATAAATTTTGGAATAGTTAACAGA
+TGATAAAAGTGTTGTTTTCAGTCATCCCTATCCAATGAAGTAAAAAAAAAAGTGTTGAAT
+GGGAAGAAATCAAGAATAGTTATACGAATATCACCATTGCATTAAAGCTCTCTTCCTTGT
+TTCTAAAAGAATATCTTGACACACATTAAGCTCACTGACCCCCACACCATGAATGAGGGC
+ATCTTCAACAATGGTGGATGACGTCTTAGTTTCCCTCAACTCAGTTAATCTAAGTAAGCT
+CATGGTATCACTTTCCTGTCCTAGAGGGAACATATTTCCTGCATTTTTCTTTTTTTCCTT
+ACTTTCCATCACCAAGTAACTCTTCTGATATTTTTTCTCTTGAGAAAATTAATATGACTC
+ATAGATCTGGTTCCCAAGAGAAATCAATGGAGGCCTGGTTACAAGGATCTAAGAAGCATC
+AATGGGTCACTAACATCTAGTGGTACTAATTAACTCTGTTAATCATTGGGAAGAAAATGT
+ATATATACTTTTGTCTTGGAGCTGATTCTACTAGAAAGCAGAAATCAAAATGATCAGTTT
+CCCAGTGTCACTACTGCACACCCTGGAACAGAACAGGTAGGTCAGAAAAACGCTCCCAAA
+GTTTAGCAATGTCAAGGCAATCTCTCTCTTCTTACATTTCCCTTCAACCTTCTATCTCCT
+CCACTTTTCTGTTTTCCTCCTATCTCCAATTATTTCAATCCTCAGAGCATTATTCTTACA
+ATCTTAATCACTAAATTATATTACACCCGTTAAAGGAGAGATTTCTAAATGCATTGACAT
+TTGTACTGTCTCTCTTTGGAGAATTAGTATTATAAGGATCTGTTATCTCTTGTCACCTTC
+CTTATGTCATATGATATGTCACATTTCCCACTGCGGAGACCAAACATGTTCACATCGTGT
+GCGTTCCATTTTCCTAATGGAAAGTGGGGGGAAGTGATTTTCTGTCCTCATATAGAGAAT
+GCTGGGGCCATTCCCTCTGTATGCCATATTTGATAAAGCATTTGATAATCTTAGTCAATG
+CCTGGGCCAAGAATTAAAGGGGTAATTATCAGAATGAAAATGGTTTAATGAAACTGTGTC
+TATCAGTTCTGAAAAGGGCCTCTATCACAATGAACTAAGGTAGTTATGAATAGAGCTAAa
+acttaggcaacaccatcctggacataggaacgggcaaagatttcatgacaaagacacgga
+aaccaatcacaacaaaagcaaaaattgagaagtggaatctaataaaacaatagcttctgc
+acagcaaaagaagctaccaacaaagtaaacagacaacctacagaatgggagaaaatattt
+gccaactgtaagtctgacaaaaatctaatatctggcagctataaggaacttaaatttaca
+agacaaaaacaaccccattaaaaagtgggcaaagaacatgaatagacactctcaaaagaa
+gatatacatatggttaacaagcatatgaaaaaaaagctcaatatactgagcattagagaa
+atgcaaatcaaaaccatattgagatatcatctcataccaggcagaatggctattattaaa
+aagtcaaaaataacagatatcggtgaggttacagagaaaagggaacacttatacactgtt
+ggtgggactgtaaattatttcaaccattgtggaaagcagtatgggatggcgattcctcaa
+aaagccaaaaacagaactatcattcaacccagcaattccattactgggtatatacccaga
+agaatataaatcgttctaccataaagacgcatgcatgagaatgttcattgcagcactact
+cacaatagcagagacatggaatcaacttaaatgcccatcagtaacagactggataaagaa
+agtgtggtacagatacaccgtggattactatgcagccataaaaaagaacaagatcatgtc
+tttgacaggaacatggatggagctggaggctactatccttagcaagctaaggcaggaaca
+gaaatccaaataccgcatgttctcacttatgagcgtgagataaatgatgagaacttgtaa
+acacaaagaaggaaacaacaggcagtggggtctacttgaggacgacgggaagagggagag
+gagcagaaaagataactactgactaccgggcgctacctgggggatgaaacaatctgtaca
+acgaacccccaggacatgagtttacctatgtaacaaaccttcacgtgtacccccgaacct
+aaaataaaagtcaaaaagaaaAAGAAAAAAAGAAAAATCCATGCATATGATACATCAGTT
+AACAAGGCACTGGTGAAATTAATTTTAAGTATTATTGTCTCTTTGTGTTTTTGGTCTCAG
+AAAAGTTACGATTTCCCTTAGTTCCTTAGGGCAGAGAGAATCTTCAATCACTGAAGTCAG
+GAGACACACATTCTATCTGATTTTCTACATTATCTGTTTGAAAAGGTTACCCACTTATTA
+GTGTTAAAGCCAAGATATCCAGCAAGGATAGCAACCAACTCTTAAGGTACTCTCCCTTAG
+GAGGATTCCTGATTCTTTAATGTTTTCTAAAAAAGCAAAACAAACAAACAAACAAAACAA
+AACACTAAATGTTTTCTCTTTCAACTTATTTGAATACACTCTTTTCTCACTGCTCTGAGC
+ATGAATTCAATATTTCAGGGCAAACTAACTGAATGTTAGAACCAACTCCTGATAAGTCTT
+GAACAAAAGATAGGATCCTCTATAAACAGGTTAATCGCCACGACATAGTAGTATTTAGAG
+TTACTAGTAAGCCTGATGCCACTACACAATTCTAGCTTTTCTCTTTAGGATGATTGTTTC
+ATTCAGTCTTATCTCTTTTAGAAAACATAGGaaaaaattatttaataataaaatttaatt
+GGCAAAATGAAGGTATGGCTTATAAGAGTGTTTTCCTATTGTTTTCAGTGTAGGACTCAC
+TGTTCTAAATAACTGGGACACCCAAGGATTCTGTAAAATGCCATCCAGTTATCATTTATA
+TTCCCTAACTCAAAATTCATTCACATGTATTCATTTTTTTCTAAACAAATTAGCATGTAG
+AATTCTGGTTAAAATTTGGCATAGAACACCCGGGTATTTTTTCATAATGCACCCAATAAC
+TGTCATTCACTAATTGAGAATGGTGATTTAACAAAGGATAATAAAGTTATGAAACCAATG
+CCACAAAACATCTGTCTCTAACTGgtgtgtgtgtgtgtgtgtgtgtgtgtgtgtgtAAGA
+GGGAGAGAGAGAAAATTTCACTCCCTCCATAAATCTCACAGTATTCTTTTCTTtttcctt
+tcctttccttgctcttctttctctcctattgctttcctttcatttccttCTCATAAAAGA
+AAAATAACAATATAGAAAATAACAAAATATAGATGGTCAACCTTTTTAATATTAAGGTTA
+CCTAAAATGCCATTATCCAAAGTGGTTCTCTAGAGATGCTGATGTATATACTTACATATT
+TTACAGTGTATTCAAATAAAGAGTATATTACATAAGACATATCCTTTTGTAACCAACTTT
+TGTCATTAACAATTTACTGGACTTGTCAACAAACCTAAATCTGTATCGTCTATAATGGCT
+ACGTTCATTTTGGTATGAATCTTAATTACCCCTTTCTGCATTATTTAATGATTTTCTCAT
+ATGTCACTCTTAAATGTACTTCTAATTTTTCACTTTACATCACATAATGAATGGATCCAA
+ATATGTTATGGATAGATATCTTCAAACTTTCTACTTACAAGTAGTGATAATAACAGATGT
+TCTCTCTAAAGTGTAGTTGGTATCAATTTTACTGACCTTTAAAAATATCTTAATGGGACA
+AAGTTCAAATATTTGATGACCAGCTATCGTGACCTTTATCTCTGTGGCTCTGTGGGCCTG
+TAGTTTTTACGTGCTTTTAGTGTATCATGATTAAATATTTTGTTTTAGTAAAGACACCAT
+TATTTCCCAACTTCATATTCAAATTGTCAAAGGTATTAATCCTAGAGCAGAACTCTCAAA
+AGCACCAACTCTGATTCCTAACAAAGCATGGAAAAGCCCTCTCTCTGAGTTTCAGATACT
+CTTTTTTGTGGGGGTTGAGTTTCACTTTATTTAAAGTGAGTCTTAATCCTCCAACAAGTC
+AACAAGTGATTGGCTGGAATCACACGTATTGGAAAACCAGCGGAAGAGTAAGTCTTTGTA
+TTTTATGCTACTGTACCTCTGGGATTAATTGCTCTTTCCCTCATTGGCCAGTCACTCTTA
+GTGTGTGATTAATGCCTGAGACTGTGTGAAGTAAGAGATGGATCAGAggccgggcgcggg
+ggctcgcgcctgtcatcccagcactttgggaggccgaggcgggcggatcacgaggtcagg
+agatcgagaccatcctggctaacacggggaaaccccgtctccactaaaaatacaaaaagt
+tagccgggcgcggtggcgggcgcctgcggtcccagctgctggggaggccgaggcgggagc
+atggcgggaaccgggaggcggagcctgcagtgagccgagatggcgccaccgcactccagc
+ctgggcgacccagcgagactccgcctcaaaaaaaaaaaaagaaGATTGATCAGAGAGTAC
+CTCCCCTAAGGGTACATGCAGATAAATACAGTTAAGGCGATTAACATTTCAAATACGGTG
+ACTGTTTCTTACGTGGACGACGTTGTGTTGAACATGGGTGAGTAAGACTGAAGCAGCCGT
+AATTACTGCACGATGCGCATGGTAAAGAAGCACTCCGTTAGGGAAATTATATTCTTTGCC
+CCTCTAATCCTTCACTCCACCTGCCATATTCCCACATGATTTTTTTCTTTGCTGTTCTTG
+TCTAATTGttattaataattaataaataaCTTATGATCTAATTGTTATTAATAATAACTT
+ATCATCACATGatttattaataaattaataaataacttattatCACCGCATTTCCCCAAT
+TCATTTATCTTTCTTTCATTTTCTCTCTTTGTGTGTTTTCTGTCTTCATATTTCAGCACT
+TGCCACATATTTCCCACAAAATCATTTATGGTCAAACAACACTTCAACGTGTAGCATTTG
+TATTTCTCAATTCTTCCTCACTTTCTTCCTTCAGAATACTAAAGCTTCTTCTCTACTGAC
+TGAGTCAATGGCCAATGGATAGAGTAAATAATTCTGCGGTATCTAAATTTGTATTGATTG
+GACTTTCAAGCTCTTGGGAGATGCATCTTTTTCTTTTTTGGTTCTTCTCTGTGTTCTACA
+TGGGAATTATCCTGGAAAATCTCTTCATTGTGTTCACAGTAATTATTGACTCTCATTTAA
+ATTCCCCAGGTACTGCCTACTGGCCAACATTTATCTTCTTGATCTGGGTCTTCTCCTACA
+GTTCTGACTTTTTCACTAACTGCAGCATCATTTCTTTTCCAAGATGCATCATACAGATAT
+TTTTCATTTGTGTCATGCGTAAAAATTGAGATGGTGCTGCTCATAACCATGGCATAGAGC
+AGGTACACTGCCAATCTGTAAGCCTCCCCATTACCTGACCACAATGAACCCCAAAATGTG
+TGTTTCCTTTGTTGGAGGCATCCTGGATAGTCAGGATAATCCATGCTGTATCTCAGTTTG
+TTTTTGCCATAAACTTGCCTTTTTGTGGCCCTAATAGAGTAGGTAGTTTTCACTGTGATT
+TTCCTTATGTCATGAAACTTGCTTGTGTAGACACTTACAAACTAGAGGTTGTAGTCACTG
+CTAACAGTGGGCTTATATCCATAGCTACCTGTTTCTTATTAATAATATCCTATATTTTCA
+TTTCGGTAACCGTCTAGAATCCTTCTTCAGGAGACTTATCTAAAGCATTTGTGTCATGTT
+AGATCACATCACAGTAGGGATTTTGTTTTTTATGCCATGTATATTTCTGTATGTGTAGCC
+TTTGCCTAAAACAACACATGATTAATATTTGTTCATTGTTCCTTTTGCTATCACCCCTGT
+CTAGGATCTACACATTAAGAAACAAAGACATGAACGTCTCCATGGAAAGACTGGGAAAAT
+GGATTGCAGGTTCTAGCAGGATGTCATAATAAATGGTGCATATCCAGAGTGCAAGATGAT
+TCAGTCTCACCAAGAACACTGAAAGTCACATGGCTACCAGCATTATTGTGATAAGAACTA
+CTATTTTGGGAGATAGTTTAGCAAAGGTGCCATGTAGAAATTGATTAAGTCAGAGGTATC
+TTTAACTTGCCACCACAGAGAAGAGATTAATTTCATATACTTCCATTGAGAAGAGAGATA
+AGAATACAAAACCAAGCTGATTTGCAGGAGTAAACTTGATATTCAAATACTATTTCCTGA
+ATGACATTTTCTGAGACATGCTAATTGTAATTACTTTCAGCTTCAAAACATAATAAATTT
+ATCTCATAGTAAGCATATAGATGGAATAAATAAAATGTGAACTTAGGtaaattataaatt
+aataaagtatatttttaaaatttCCATTTTAATTTCTGTTTAAATTAGAATAAGAAACAA
+AAACAACTATGTAATACGTGTGCAAAGCCCTGAACTGAGATTTGACTTTACCTTGAGCTT
+TGTCAGTTTACGATGCTATTTCAGTTTTGTGCTCAGATTTGAGTGATTGCAGGAAGAGAA
+TAAATTTCTTTAATGCTGTCAAGACTTTAAATAGATACAGACAGAGCATTTTCACTTTTT
+CCTACATCTCTATTATTCTAAAAATGAGAACATTCCAAAAGTCAACCATCCAAGTTTATT
+CTAAATAGATGTGTAGAAATAACAGTTGTTTCACAGGAGACTAATCGCCCAAGGATATGT
+GTTTAGAGGTACTGGTTTCTTAAATAAGGTTTTCTAGTCAGGCAAAAGATTCCCTGGAGC
+TTATGCATCTGTGGTTGATATTTTGGGATAAGAATAAAGCTAGAAATGGTGAGGCATATT
+CAATTTCATTGAAGATTTCTGCATTCAAAATAAAAACTCTATTGAAGTTACACATACTTT
+TTTCATGTATTTGTTTCTACTGCTTTGTAAATTATAACAGCTCAATTAAGAGAAACCGTA
+CCTATGCTATTTTGTCCTGTGATTCTCCAAGAACCTTCCTAAGTTATTCTACTTAATTGC
+TTTATCACTCATATGAATGGGAATTTCTTCTCTTAATTGCTGCTAATctcccccatcttc
+aaatactctaccgggcttctggaacaccacagcttcctggctttttctcctacctcctgg
+gcaagtccttccctgtgtcttttgttgagtgttcctcatctgcttaactaccaatcaacc
+tattgcccctaatttgatctttggcctgttttcacttagattctatccctacgtatcacc
+cattcccacagctttaatcaccatctaaacactaggggctctcaaaccttgtatttttct
+ttctttctttctttctttctttctttctttctttctttctttctttctttctttcttcct
+ccttttctttccttttctttctttcattctttctttcttttttaaggggcagggtctcac
+tatgttgctgaggctggtctcaaactcctgacctcaagcaatctgtctgcttcagcctcc
+caagtagctgagaatacagggacaagccattgcacctgaccctggtactatttcttgagt
+tcctgatccacagatctaacctcctactttcctggatgccacacaagatcttccactcaa
+caagtctgcaactaaactagccttcctcttttcaaacctactcttctttcagtgttctca
+gtcacaataatttgtaccaactagttacctagttgcacaacccaaaatctgggaaaaata
+atagatttctttctccatagtacccccaaatcaataaatcatcaagtcttattctacctt
+ccaaagagccttacatatgttcctttattttcatctgtaacaccactattcctgtctaag
+cctacctatgtcatttttggaagagaatatagtcacctatgcgaccttcccacttaaaat
+cctactatttacgcttcagtaaaagaaaaaaaatttttaatctaagtatgtaattctttt
+gctgaagacacttcacttgcttctgtgcccttaaactggtatgttatcatggtatagtag
+gccatccaagacctggcttccttcctttttttcagtctcagagaataacatactctttcc
+ctgcaactccagatccaatttggttttcttttacttgcctggaaactccaaaatctatca
+actctggggctttccactagctaatcattttgtatacaatatttgtccttcATGTTTTGC
+CTCTTAACATCTCAGCTTTCAGTTTCATCATTTTACCAGGGAGGCCTCCCAGAACCTGAG
+TCCAGAAGAGTTCCTTCCATTGTATATTCCTCTAGCACTACCTATTACCTCTTTTGTAAG
+ACTAACAGCCCTCAAAATTTTTCATTCAGTGATGTCTTCCTCATTGCATTTTAAGTTCAA
+CATGAGCAGGACTTTGTCGTGTTCACCTCTATCACATCATAAATATAGCAAACAGTAAAA
+CTATTGCAACATGACTAATGTATTGAACGATGCTTCAGCTTTCTTCTTACGTTCAATCAC
+AGGTCATATGACTAAAGAACTTCCTTTTTAATCTCCTTTTCTATTCTCAATTAATTTCTT
+CTGCCTGCATCACCTCAAGTCTCTGGGGTGAAATCCACTAATGAATTCCTTTTGCAGCTT
+AAGCCAATTCCAATCTTGAGCCAATCTCAGGTGAAGAAGCCTGTAAATTATCACTCTCAG
+TCCTCTCTTGTACTACTAGGTCTCATGAACTCTTCATTAACAACTCCAGCTTCTCTGTTA
+GCCCAAAAGCCTTTTGCTGCCTAGAAAACCCATGATTCATGCCTCAGGAAACAGCCTTCA
+AATCACAACATGTTCTGTATCTGGCTGGCCAACTCCCTGCAACTTATTTCTGCCTAGATT
+CTCCCTCATTCATTTCAATACGCTGTTCGGCCTGCTACCCCAGTTTCCCACTTAGAACAA
+TGGCACACAGGACAGGAGCACATTGGCACATCAGAATGACTTATGTACTGCTCATTGTGT
+TGCAGAAGAGACCTCTGTGGGGGCAATAGAACAGATTTTCCTCTCACGTCACTGTAGTTG
+TGGTTTCCCTAAGCACCTACACTGTTTCACCTCATCTTAGGTAGACAATAATCCATGTAA
+CTGACTGTGTATCCTAATTTTAAAAAATATTTCTGCCCACATTATTCTGCAGTTTTTATC
+TTGCTTACGTATTTTTGGAATGTTACTATTTTTCAAAAATTAATTTGGGATCAACCAACA
+CTTCTTATTCTGCTGCTGTTCTAGAGAAAATCATTTTCCTCATTTCTGAACAAGAGAAAA
+TGAAATACAGCTCTAAACAAATGCCACTGTAAACCAAGGTGGAGCCTTTGCACTTTCAGG
+CCACCATGATAACCTGGAGATTAGATTTTTCTGTGTCTTTATATCAATAATAAAGCCAAG
+CTTCTCCAGGGGTATCCACTAGGCTTGTCTCAATGGCTCAATACAGGTCCTTTTGTGAAT
+GATTACCTCACCCTCATGGAAACACACTCTTGTTACAGAAACTCAGAATGATTCTATTTT
+TTCTTTTATATTTGTATATGTTTTTCCAATACCTCTGAAAAAACTGATCCAAAAAAAATA
+CAAATTTTAATTGTAGCCAGTCAATTCAGGAAGGATAAAGGTCAAAAACTTTCAAAGAAA
+CCTTCAGCCCCAACACACTAAACTTTGGGAGCACAGGTTGGCATCCAGAGGTAAACATTT
+GCTATAACTGATAACAGGAGAAGGATCCATTTATTCACCTGTTATCAATTACAGGCATTG
+TATTTAAAGATCAGATGTTTTATATTTATTTCTTCAAATTTCATTCATGGTGCCATAAGT
+GAAGGTATCTCTGTCCACCCTGAATATATTTTCACTCCCTCATCTCAGTCATTCCGAACA
+ATTCACACACTAAGATTACCCATGCTAAATGGGGATTCTTTTTTACTAGCCAATGTAGTA
+CCTCAAATCCTTCCTTCCCTCCCCCTATTTCATCAGCAGGCAATTCTTTTGATACTTTTG
+TCAAGGGGAAATTGTGTGACTCAGAGATCTAGTCCCCAAGAGAAACTAATAATGGGCTGG
+GTATTGTCTGTCTCAGCAGCATCAGTGGGTCCCTCTCCTGTGCAGCTAATTAGCTTCCTT
+TCCAATATGAAGAATCTTATATATAGCTTTGTCTTTGGGGTATTACATAAATGAAGATTA
+AGCTATCTGAATTTCTCCTTCTCCTAAAAATGCACATCCTATGACTGAAAAGACAGGTAA
+AAGAGATGCTTTTAATTACAAAACTTTCCCTGTCGTGGTTGCTTCTCTCTATCCTTCTAA
+ACTCCCTTTCAATTTCTTCTCTTCTGTAACATATTTGTGCCCAAAATCTTCTGCTTTCTG
+AAATATTTTATCTTTTTCTTCCACACTATCTCTTATTTTCCAATTTTAATCATTAAATTA
+TATTATGTCTTATAAAACTAATCCCACATATAAACCCCTATGATAATTTCAGTTTGTCCC
+TAGTATGAAGTTCTTTAAAGATGTGTAGTTTTCTAACTTTCATGCTCTCCAATTAATTAT
+AAACTTCATTTTCCACTCTGAAAAGGAGATGTCTGATCTCAGCTATTTCCATCCTATTTG
+AAAACCAGATTTAGTTTTAAACCAGAGGAAGGGAATCTCAAGTCTTTACCTCCCACAGTC
+TGGTGTGATTCTCTCTCTTTTGGTATTACCTTCCTCCACATTGGAACACTCCAGCCAATG
+CATAGGCTGAGAGGCTATCTCAGATTCAGAAAGATTTGGCCTCATCCCAGGGGAGGGTAC
+AGAGGAGCTGATGACTATGAATTCTGAAATGGAACTGTTCCAGGTTGAAGAAATAAGAAA
+GGGAATTGGGAAGAGCAATGCCCAGTGAAAAAGAAGAAATAATATTTTAGGAAGTGAATG
+CTAATTTTATTTTAAACAAAATAAGAACTCAAGGAATAAGAGGGTTCTTCCAATAGGTTA
+GAGTGATCCTGTCAAACATATATGCTTCTAGATTTTTTTAAAGACTGTTTCTACTAAGAA
+AGCATAGACCGCTATTGAGAAAGATCATTAAACTGGAATTTAGGAGGTCTGCCTTCTGAT
+TCTGACTTCTTGAATGTATTGTTAGCCATTTAACCACACTGTGTTGTTTCTCATTCTACC
+TGTAGAATCTCAAAGTTCTTTCCCACTTCTATACAAAACTATAATTCTGAACATCCTTTT
+TGTTTAATATAAGTCTGCATTTCCTGTTTGAAGATATGTGTCCCAGACCCTAAATGACTG
+ACAAATTTTAAATCTCCAATAGGAAAGATGACAAACTCTATGGAAACTTGGCTTCTGAAG
+AACTCCTAGAAGCTTTCCAAAGTCATCAGTGTTTCCTAAGAAGGCAGAGAAATCAAACAC
+ATGGTCTTTTCCTCCAGACAAGCTCCTTTGGGTCATCAGGATTTCTTCAACAATAAAATG
+TAATAATTCCAAATGTTTGTAACAGAATGGGTAGGACTTTCTTCACTTATTTAAATACTC
+CCTTTTTTATGCAACTGAGTTTTCATCAACAAGTACAAGCTTGTGAAGGAGTACTTTAAA
+ATGCAATTTCTCTCTATTTTTGTGGGGGCTAATATTTTATTTCTCATATTGACAATTTAT
+TATGCTGTTTTTAAAAAGttcattcatcaagtatttcttgagctttttctatgagacagg
+cactgttttaggcaagtaattatgcactgaacaatgcaaaaagtttccctgcactcatgg
+actttaattttaCATTTATGAAAAGCTACAAATATTAGAATAAGTAAAATACTGCCTGGA
+GGCTAAAGCATATTTTGATCACTTATTCCCTAATTCTTTTAGAAGAGAACTCACCTGTCG
+GTTAGCTGAACCACTGCCAGTGATATCCAACTATACATTCAATCCCACCATACCTCATTA
+TCACACCTATTCACTCACAAGCTTAAACTCTTAACTTTTCTCCACATATCAGTGACTATT
+TCCTACAGCTTTTCTTTTACTTTCCATGTTTGCAGTGACAATATACATAAACAGTGTATG
+AAAACTCAAGTAAAATCTACTCTCTCAGGTGTTCATAATGTATCAATGTATATTGCTTTA
+AGCCTGAAGGTAACCTAAGTAAAGATGTACCATGTTCCACCAATGCTTCTTTTGATCATC
+ATTTTATCCTGTTTTTTCTTTAGGATTCTTTCTTATTCCTTCCCCTGACCCTTCTTTTAT
+TCTCCAAATTTCTTTCCAATTCATCTTTGTTCTTCCCTTTCCTTTTTACTCTCTTTAAAC
+ATTCTATGGACTCTGCCTCCTTCACACTGATATTGAACGCCCATAGTTTCATATTTTGGA
+TTGCGATTGTTTTATTTTAAAATGGCAAATGTTCATGTTATAAAGAGAATTTTTCAGTCT
+TTAGACTAATAGGTTCATGTAGTTTGGGATTTTCCTCTTTAAGAAAATTAATTATCACTC
+ACACTCCAAGACAAACACCATTTCAGTAGCAATATGAATTTCAGTAGTAATAGGAATCTC
+CAAATATGACAAAGTAATTCAGACATTAATTGCTTTTGTTTTGGAATTGCTCTTATAAGA
+TGAAATATCACTTTCATGATGAGAGTCCTAGAGTGCTTGGTTTATATATTGTATCTTAGT
+TTTAACAGGATAAAACACTTGATCCTAAGCAGTAAACATGATTCTTCAGCTTCAACTTCA
+TTTCTTTATAAATAACTATTTATGAATTGGTGTTGAGCTTAGTAAGTCACCAAACACCTT
+CTGCTCAGCAGCATAAAGGACATTTCCATGAAACCTCCCAGGGATAATCTTATTTACTCT
+ATAATGTTTCCCGGGTTCAATTCCTCTCCCAAAATTCTTTGTTCTTAAGCCCCTATGATC
+TGGGTGATCTAAATATGGGTAAGAAGTCCAGGGATAGCACTATGAATGAAGTGAAAATAG
+TAAAACATAGTTAAAAATGTAcagatgctctctgacttataatagggttacgtcctgata
+aatccatcataagtcaaaaatgcatttaatattcctaatgtacctcacatcatagtttgg
+cctagcctaccttaaatgtgctcagaacactttcattagcttatataagatcacctaata
+caaagcctattttataataaaatattgaatagctcacgtaatatactgactactatactc
+aagtacagtttcttctgaatgcatgtcactttctcaccattgtaaagtcaaacaattata
+agtcaaactatcacaagccagggaccatcCATATGTATTTCATTCAGAAAATGCTGGAAA
+GAGCATTTCGGAGAATATCTAGATGAGAGAAGGTAGAAAGCCATGCACAAATTCACTGAG
+AGTTTAAAAAAATACATGCATATTGTGGAGATAGAAATCAAATCTATTTGTCTCCATCTG
+CTGTATTCTTCCCAAAATATTATCTCTTCTTATCCCATTGTACTATATTGCATTTCTTTG
+ACCATTTATTGTGTATCTCTTAATATTTCCCACTTCATCATTACTAACCTCACTCACTCT
+GAACTTGATGAGAGCACCTGAGCATTAATTTTTCTTATAATTATTTAATGATTACCAGAA
+TTCGTTCAGTATGGCCAGCTCTGGTCAAAGTGAGGCAGGCAAGATGCTTTGTCAACTGCC
+TGGATGGAATGTCTCAAAAGGTTTCCATTTCATGGTAGCATTATGCAAAGTTCAAGACGT
+TTAATCAAGACCCTTCACTTACTTAACTATACCTCCTTGAGAATCCCATCTATGAAAAAA
+TTCTAGTCATTATAAAAATGATTGATTAAATGAGGGAAGTAGTAGAGTTCTTCATTTCTT
+TAGTTGGTTTAGTCTCCTATGAGTCAATCCTATTTTCAAAATTCTTAATAAACCATTTAT
+TCCTTCAACTTTCTATGCCATTTGATGTTTTGTAAAAAAAAAAATATAATATGTATACAA
+AAAGATATTTCAAAATCTAGAAAGAGAGCTTTAGAGCTTTGTAAAGCTCTTTTAAAAATC
+AAAAACAACTACTGTTAATTAACATGTTGTACTATGCAATTTGTTTACCATTATTACTCT
+TGGTATTTTTAAGAAAAGTCTTTCCATTGTTATTATAAATGCTTCTATTGATATTTATTT
+TAATAACTGTTATTACAGTCCGTCATGTACATACACTATACTTAAACCTAATGTTTGGTA
+TTTAAATCGTTTCAAGATTTTATCACTGTCAACAAAGTATGATGAATATTTTTATGCTGA
+AAACTTCTGTAAAAatagaattccaagagtattattgcaccaaaaggcatggacttaaaa
+ttcttgatacatgatttcaaaatattttctttaaggtttgaatcagtctatattccctcc
+agcagcgtataaaagtgccaatttctctgatccttaGCCAGTTTGGGTAATAATAATTGT
+AAAACttttttttctttttttttgagacagagtctccctctgtcgccaggctgaagtgca
+gtggcgcaatctcggctcactgcaacctccgcctcccggggtcaagctattctcctgcct
+cagcctcccaagtagctgggactacaggcatgcaccaccatgcccagctaatttttgtta
+tttttagtagagatggagtttccccatgttggacaggatggtctcgatctcttgacctcg
+tgatccaccctcctcggcctcccaaagtgctgggataacaggcgtgaacaaccatgcccg
+gccTGTAAAACTTTTTCCTAATTTAACAGAAAAATAATAGTATTATATTTTATCATATTT
+CTTTGATTTCTAAGacacacatacacacacacacacacaTATCTGTATATACAAATACAC
+GTATAGCTTACATTTTAATTCTTCATTTCATTTGTTCATTTATTAGGTCTTGGAGATTTT
+GTGAAACTGTTTAAATTCTTTTTTATACTATGAAGATATCAACCTTTTGTCTCTACAGCA
+TTTCAAATTCAAGTATGATTCACGTGTTGGTTTGGGGTAGATCATTATAGGCACATGTAG
+GAAACAGCTTTCAGAGATGCCTTAACCGTAATTATGCATTTGTATTCTAATTTTTATTTA
+ATGTTATTATTGATTGCATTTTTAAAGATTCTGTATTTTTTAAACCATTTATTTGTATAT
+GTTGGTATACAATCTTGCCATTTTCTGGGATTTCATATTTCCTTATTTTTGTTTTTTACC
+TTTTTTGGCTTGAATTTTTTGAGTTTTTATGCATTCTTTTCCAGTTTCTTAAGATGCTAA
+TAAGTTCATGTATTTGAGCAATTGAGAACATTTAAAGCAATAGACTGCCTCTGAGCACAG
+CTTTGTCCATATTACATTAACCTTTTATACCCTGGGTTCCCACTAGTTTTTAAATAATCT
+ACTATCAAATAAAAGATTTGTTAATAATAAATTTTAAATCATTAACACTTAACGCATTAT
+TTTCAGTCACACTAAGTTGATTCCTTCGTTTCTTTCAGGTTGCTTCAGAGTCTTCCCTTC
+TATCTGATTCAGTGGACCAAGTAAATGACTCTCTGGTAACAGAATTTGTATTACTTGGAC
+TTGCACAATCCTTGGAAATGCAGTTTTTCCTTTTTCTCTTCTTCTCTTTATTCTATGTGG
+GAATTATCCTGGGAAAACTCTTCATTGTGTTCACAGTGATCTTTGATCCTCACTTACACT
+CCCCCATGTATATTCTGCTGGCCAACCTATCGCTCATTGACTTGAGCCTTTCATCTACCA
+CAGTTCCTAGGTTGATCTACGATCTTTTTACTGATTGTAAAGTTATTTCCTTCCATAATT
+GCATGATACAAAAGTTCTTTATCCATGTTATGGGAGGAGTTGAAATGGTGCTGCTGATAG
+TCATGGCATATGATAGGTACACTGCGATCTGCAAGCCTCTCCACTATCCAACTATTATGA
+ATCCCAAAATGTGCATGTTTTTGGTAGCAGCAGCTTGGGTCATTGGGGTGATTCATGCTA
+TGTCTCAGTTTGTTTTTGTCATAAATTTACCCTTCTGTGGCCCTAATAATGTGGGGAGCT
+TTTATTGTGATTTTCCTCGGGTTATTAAACTTGCATGCATGGACACTTATGGGCTAGAAT
+TTGTGGTCACTGCCAACAGTGGATTCATATCGATGGGCACCTTCTTTTTCTTAATTGTAT
+CATACATTTTTATTCTGGTCACTGTCCAACGACATTCCTCAAATGATTTATCCAAAGCAT
+TCTTCACTTCGTCGGCTCACATCACCGTAGTGGTTTTGTTTTTTGCTCCATGCATGTTTC
+TCTACGTGTGGCCTTTCCCTACTAAGTCATTGGATAAATTTTTTGCCATCATGAACTTTG
+TTGTCACCCCTGTCGTAAATCCTGCCATCTATACTTTAAGGAACAAAGATATGAAGTTTG
+CAATGAGAAGGCTGAATCAACATATTTTAAATTCTATGGAGACGACATAACACATTTGGT
+TGATGAGAGCACAGGATAAATGCCATGGACCATCAAGACTCCTGTGATCACCATGATCAC
+TATGGAACGCGCACATTTTTAGTATTGCCTGAAAAAACTGAAAAATCTGCAAAAAGGATG
+CATTAAATCTAAGAATTGTATTTCAGATAAAGTTGCAACATTTTTTGTTAATCATAAAAA
+GTATATATTTCTATCTAATGTGTGTATCTAATTAACAGCAATGACTACCTTTAATTTTGA
+TGTAGTTATTTTATATCTGTATATAAGCACATACACATATATATGACCTAGGTTTATTTA
+TCAGTATTTTTATGCTGATAATAAGCATCACTGGAAATTAATTTTCTTATGGAAATTATG
+TGGATCCAATGGATAAAATATGAGTTTATATAAATTAGTAAATGCCAAAATCAAGGAAGA
+AACAATTTTTATTTTAATTGTACTTTAAGTTAGATAAATGGTAAGGTCAACAGCTTGTTA
+CAACCCTTAAGTATTATTTTCAGGCTGATTGTCAATATGTTTTGTACAatgttctcactt
+ataggtgggaattgaacaatgagaacacatggacacaggaaggggaacatcacacaccgg
+ggcctgttgtggggtggggggaagggggagggatagcattaggagatataactagtgtta
+aatgacgagttaatgggtgcagcacacccacatggcacatgtatacatatgtaactaacc
+tgcacattgtgcacatgtaccctagaacttaaagtataataaaaaaaaaTAGACTCTAGT
+ACTCTGTATTATGCAAAATTTGTCTATGTTACACTTTTTTAACAACACAATCCTATTGCC
+CTTGAAATCTTCTTCAAAGCATTTCTCGAGTCACTCTTAAAAAGCATCTACAACCTAAAA
+GTATAGGAAGAGATTTATTTCCTGGAGAAGAGACCCCATTGAGATCTTAAAAGCACATTT
+AATGTGCCTGTGCTTAACTTAAGGTGCTTAGGACAAAGAAGGCGATTGACATCTTTCAGG
+TAAAACCTGGTAAGTTTGGTGGTCAAGGAACACAACTGAGACATCACTTGGATGTATTCC
+TATGACTATTTTAAGAAACATAAATTGTGGTGACTCACTCAGCTCACTTTTAACTACTGC
+ATGGTAATTAAAGATGCAAAATAAAATAAGTTACAAGAAGTGAGGTTTTTTATTGGTTAA
+AGCAATTTTTCTATATTTTCTCCGCAAGTTGGTCATAAAAGTTCTAAGCATTCCTCTTTT
+TATAAAATCGAAGCATTATTACTTACTCTCTTGTTAACCTATCTGGATTTTAATTTTGTA
+ACTTTATTATATTTGTTTTGCTGTGATTCTTTAAAAAGCACCTTTAGACTCAGTGAGATA
+GCAAAAATATCCAAATAGGCCAAAAAATTGTGGCAATGTCCTCTCACTCAGGAAAATTCT
+GTGTGTTTTCTCTAATGGCCAAGGGAAAACTTGTGAGACTATAAAAGTTAGTCTCAGTAC
+ACAAAGCTCAGACTGGCTATTCCCAGATCTCTTCAGGTACATCTAGTCCATTCATAAAGG
+GCTTTTAATTAACCAAGTGGTTTACTAAAAAGGACAATTCACTACATATTATTCTCTTAC
+AGTTTTTATGCCTCATTCTGTGAAAATTGCTGTAGTCTCTTCCAGTTATGAAGAAGGTAG
+GTGGAAACAAAGACAAAACACATATATTAGAAGAATGAATGAAATTGTAGCATTTTATTG
+ACAATGAGATGGTTCTATTAGTAGGAATCTATTCTGCATAATTCCATTTTGTGTTTACCT
+TCTGGAAAAATGAAAGGATTCTGTATGGTTAACTTAAATACTTAGAGAAATTAATATGAA
+TAATGTTAGCAAGAATAACCCTTGTTATAAGTATTATGCTGGCAACAATTGTCGAGTCCT
+CCTCCTCACTCTTCTGGGCTAATTTGTTCTTTTCTCCCCATTTAATAGTCCTTTTCCCCA
+TCTTTCCCCAGGTCCGGTGTTTTCTTACCCACCTCCTTCCCTCCTTTTTATAATACCAGT
+GAAACTTGGTTTGGAGCATTTCTTTCACATAAAGGTACAaatcatactgctagagttgtg
+aggatttttacagcttttgaaagaataaactcattttaaaaacaggaaagctaaggccca
+gagatttttaaatgatattcccatgatcacactgtgaatttgtgccagaacccaaatgcc
+tactcccatctcactgaGACTTACTATAAGGACATAAGGCatttatatatatatatatta
+tatatactatatatttatatatattacatattatatatataatatatattatataatata
+tattatattatataatatataatataaatataatataaattatattatataatatataat
+ataaatataatataaattatataaatataatatatattttattatataatataatatata
+ttatataaatataatatataaattatataatataatatatattatataatataatatatt
+ttattatataaatatatattatattatataatatatattttattatataatatatattat
+atatttatagaatataatatatattttattatataatatatattatataatatatattat
+atttatatataacatatattattatataaaatatgtataatatatattatataaatatat
+ttatatattatataaatatatatattatatataatTCTAATGGTTGAATTCCAAGAATAA
+TCTATGGCATGAAAGATTTTACCTGTCAACAGTGGCTGGCTCTTCATGGTTGCTACAATG
+AGTGTGTAAGATTCTGAAGGACTCCTTTAATAAGCCTAAACTTAATGTTCAACTTAGAAT
+AAATACAATTCTTCTAATTTTTTTTGAATAATTTTTAAAAAGTCAGAAATGAGCTTTGAA
+AGAATTATGGTGGTGAAGGATCCCCTCAGCAGCACAAATTCAGGAGAGAGATGTCTTAAC
+TACGTTAGCAAGAAATTCCTTTTGCTAAAGAATAGCATTCCTGAATTCTTACTAACAGCC
+ATGATAGAAAGTCTTTTGCTACAGATGAGAACCCTCGGGTCAACCTCATCCTTGGCATAT
+TTCATGTGAAGATATAACTTCAAGATTGTCCTTGCCTATCAATGAAATGAATTAATTTTA
+TGTCAATGCATATTTAAGGTCTATTCTAAATTGCACACTTTGATTCAAAAGAAACAGTCC
+AACCAACCAGTCAGGACAGAAATTATCTCACAATAAAAATCCTATCGTTTGTACTGTCAA
+TGATTAGTATGATTATATTTATTACCGTGCTAAGCAGAAGAGAAATGAAGTGAATGTTCA
+TGATTTATTCCACTATTAGACTTCTCTTTATTCTTAAAAATATTTAAGATCACTAAATTT
+TTATAGGACTTTAAAAACAGTAATGTGCTGCTTTGAGTGTGTAGGACTAAGAAATGGGAT
+TCAGAGTAGTAAAGAGAAAAGTGGAATTTCCAAGCACTATGAATTACTGTTCTTTAAAAA
+ACAGCAAAAATCAAATAACAGTATTCCTCCAAAAAAGATGGCAAGTGTAAACTCTATACC
+TTCATGTCTCCCGTGGAATGTTAGTGATCAATTTCCACTTCTCTCTTTTACATCTTACTT
+GCCCATTAACTCTTATACCTAATCCAAAGATTGTTAATATGGCTATGTCTCACTTTCAGG
+ACACCTTTTATTTGTTACTTCTCTTCACTGCAAAACTTCTTGAAACAGTACTTATTTTCT
+CTCCTCCATACACAATTGAAATGGCTCTCAACTCATGCCCAGAAGTCAGTGTTCAGTCTC
+TCACCTGGCAGATAGCAACTTACAAAGATGCCCCAACAATACCTCCTTGTGTCTAGACAG
+TCATCATTATCCTTTACCTTTTTCTGTATTTATTTCTGCTCCTAAAAGGGATCTCTATGT
+AAAGTATTGTTATACTAGTGCTTGTTATAATTATTATCAGAGTTAAAGCCATCACAATGT
+TCCCAATTACTTAAAGACATTGGAATAACATTTTTTTTATTTTCCACATCTTGCCAAAAA
+ATATTTTGTTATCAGTACCTTaataatggctattatatattgaccattactatttgctag
+aaaatttatatacctggtcgtatccaatcctcacagaacttctataaagttgtgctatta
+tcacctatattttccagatgtggccgtaagactgaaatcacttaggtgacttgtctaagg
+tcattcagatacatagtagataacccaggatttgaacacaggcctcctagcacacaagct
+catatcttaactactttaatacgttgctcGATGGGATCTTACAGGTCTTCATTCACCCCT
+TTCCTGCTCACACAACCACAACCTGCAGCTATTACCTATTGTTAGGCTTAAAATAATTAC
+TTGGCTTCATTTCCAAGCTCCCTCCCTTCCAATTCACATTGAGTCCAGAGCTAAATTAAA
+CAATCATTCAAAATTTTTCAGTAGTTCTTGTCTCTATAATAAAACAGAAATGCTTTAGAA
+AGCATTCCAAAATCTCTTACCAGTTTTATCTCCTATGAAAGTCCTTCACactttctctca
+tttaaactttattgcattttcctcactttttctcacttcacttttgaattccctattctt
+ttatcctctgttaatttttaagtattatatttgtgatattattttttctttttttctatt
+ttttatctttcatttcattttggcctatttttttctcttAAGAACTTTAATATCACCAAA
+TAACATGTGTGCTACAAACTGTTTTGTAGTTCAAAGAAAAAGGAGATAAACATAGAGTTA
+TGGCATAGACTTAATCTGGCAGAGAGACAAGCATAAATAATGGTATTTTATATTAGGAAT
+AAACCTAACATTAATGGAGACACTGAGAAGCCGAGATAACTGAATTATAAGGCATAGCCA
+GGGAAGTAGTGCGAGATAGAATTATGATCTTGTTGAATTCTGAATGTCTTTAAGTAATAG
+ATTATAGAAAGTCACTGTAAGAGTGAGCAGAATGATATAAAATGAGGCTTTGAATTTGAA
+TATAATAATTCTGACTTCCTTCTCCTTCTCTTCTTCAAGGTAACTGCAGAGGCTATTTCC
+TGGAATGAATCAACGAGTGAAACGAATAACTCTATGGTGACTGAATTCATTTTTCTGGGT
+CTCTCTGATTCTCAGGAACTCCAGACCTTCCTATTTATGTTGTTTTTTGTATTCTATGGA
+GGAATCGTGTTTGGAAACCTTCTTATTGTCATAACAGTGGTATCTGACTCCCACCTTCAC
+TCTCCCATGTACTTCCTGCTAGCCAACCTCTCACTCATTGATCTGTCTCTGTCTTCAGTC
+ACAGCCCCCAAGATGATTACTGACTTTTTCAGCCAGCGCAAAGTCATCTCTTTCAAGGGC
+TGCCTTGTTCAGATATTTCTCCTTCACTTCTTTGGTGGGAGTGAGATGGTGATCCTCATA
+GCCATGGGCTTTGACAGATATATAGCAATATGCAAGCCCCTACACTACACTACAATTATG
+TGTGGCAACGCATGTGTCGGCATTATGGCTGTCACATGGGGAATTGGCTTTCTCCATTCG
+GTGAGCCAGTTGGCGTTTGCCGTGCACTTACTCTTCTGTGGTCCCAATGAGGTCGATAGT
+TTTTATTGTGACCTTCCTAGGGTAATCAAACTTGCCTGTACAGATACCTACAGGCTAGAT
+ATTATGGTCATTGCTAACAGTGGTGTGCTCACTGTGTGTTCTTTTGTTCTTCTAATCATC
+TCATACACTATCATCCTAATGACCATCCAGCATCGCCCTTTAGATAAGTCGTCCAAAGCT
+CTGTCCACTTTGACTGCTCACATTACAGTAGTTCTTTTGTTCTTTGGACCATGTGTCTTT
+ATTTATGCCTGGCCATTCCCCATCAAGTCATTAGATAAATTCCTTGCTGTATTTTATTCT
+GTGATCACCCCTCTCTTGAACCCAATTATATACACACTGAGGAACAAAGACATGAAGACG
+GCAATAAGACAGCTGAGAAAATGGGATGCACATTCTAGTGTAAAGTTTTAGATCTTATAT
+AACTGTGAGATTAATCTCAGATAATGACACAAAATATAGTGAAGTTGGTAAGTTATTTAG
+TAAAGCTCATGAAAATTGTGCCCTCCATTCCCATATAATTTAGTAATTGTCTAGGAACTT
+CCACATACATTGCCTCAATTTATCTTTCAACAACTTGTGTGTTATATTTTGGAATACAGA
+TACAAAGTTATTATGCTTTCAAAATATTCTTTTGCTAATTCTTAGAACAAAGAAAGGCAT
+AAATATATTAGTATTTGTGTACACCTGTTCCTTCCTGTGTGACCCTAAGTTTAGTAGAAG
+AAAGGAGAGAAAATATAGCCTAGCttataaatttaaaaaaaaatttatttGGTCCATTTT
+GTGAAAAACATAAAAAAAGAACTGTCACATCTTAATTTAAAAAATATATGCTTAGTGGTA
+AGGAGATATATGTCAACTTTTAAGAGGTTGAAAAACAAACGCCTCCCATTATAAGTTTAT
+ACTTCACCTCCCACCACTATAACAACCCAGAATCCATGAGGGCATTATCAGGAGTGAGTG
+GAAGAGTAAGTTTGCCAATGTGAAATGTGCCTTCTAGGTCCTAGACGTCTGTGGTATAAC
+TGCTCATAAGCAGTAGAAAGAATTTAGAGGGATCCAGGCTCTCATCACGTTGGCACAAAG
+TATATTACTTGGATCCATCTATGTCATTTTCCATGGTTAATGTTTaaaagcacaggcttt
+aaagtaaaaaacaaagagctggattcaactctactgactcttattaatcatgattttggg
+cacattacgtagctttcatgagctttagtttctacatttataaacaggagattataccta
+ttatgcatggttattatgaaggaaaatgacaaaatagatataaatcaaatagcccacttc
+gagacatattaagcatgaataaacattagatactattaAAATCCTATATATTAACAAAGC
+CAAAAGTTTCAAACTTTACTTTTTCCCAACATTCTTGTGAAATATGACACATCCCAATCT
+TAACAGATGCTCATTTGGGATACTGTACTTGTGAGTGGAAGTGTGTATATTTGTGTGCAA
+GTGTGTACTCATATACTTCCACCTTACCACCCTAGAAAGGCATGATGAAAATTTAAGATA
+GAAGGAAAATATAAATTGAAAAAAAAAAACCTTAACAAATGATTCTGACAAATATCTTCT
+CTTTCCAGGGAGAATCACTGAGCCAGAATAAAATTGAACACTAAATATTCTAAGAAAAAA
+GGAATCTAGTTTGTCAAAATGTGACTTGAATTAATAGATAAGGAGAGTCAGATGATAAGA
+GGGTCAAAATTATGTTTATCTTAGGAAAAGTAGAATAGAAAATTTATAAGCAGATTAAAA
+ACACATAATAAAAGTAGTAAATAATAATGACAGTATCTCAAATcagtgcaggggggaaag
+gcctactaatgtgatggtgggataattggatagcaatatgggaaaagatatatttaattt
+atttgctacaccaaatgccaggacaatctctaagtgaattcaagacataactcttttttc
+aaaaaaactatgcaaatattaaaagaaaacaagttaatgtttttataatctatgaatatg
+gtaaagatGGATAACATTGACTATCAAATTAATTTTTAATGCGTAATAAAACTATGAGAA
+AATTTAAAAGTGAGAAGAAACTACTTGTAACTCACATAATAGActagtacttctaacaca
+tagggaacttctaaaacaaaacccaaaatattaataggaaaatgggcaaaacagttaaac
+ttacagttcataCATAAGGAGAATCAGTCTTTTTTTTTTTTTTTACAGTTGTAGGCAGAA
+AACTTTTATTTTTCATTTATTTGTAAAATTTACCCCTAATTTATTCATAATTCATTTAAC
+TGCTAAGGGCATTAATGTGTACAACGCCATGGGAGAAACCAGTATATTCAGAATTTCTCC
+TGAAATTTGACCAGAAGTTATGGGCATCCCTCCCCTGGGAAGGAGGCAGGCAGAAAAGTT
+TGGAATCTATGTAGTAAAATATGTTACTCTTTtatatatatacatatatgtgtgtatatg
+tgtatatatatatacacacatatatacatacatacatacatacatatTATCTGAATTAGG
+CCTGGTCttttttaatactttaagttctgggatacatgtgcagaatgtacaggtttgtta
+cacaggtatacacctgccatggttgtttgctgcacccatcaactcaccatctacattagg
+tatttctcctaacgttatccctctccttgcctcccacctcccgacaggccctggtgtgtg
+atattcccttccctgtgcccatatgttctcattggtcaactcccatttatgagtgagaac
+atgcggtgtttggttttctgttcttgtgttagtttgcggagaatgatggtttccagcttc
+atccatgtccctgcaaaggacatgaactcattcttttttatggctgcaagaaatgcaaat
+caaaaccacaatgagatgccatctcacaccagttagaatggcaatcattaaaaagtcagg
+aaacaatagatgctggagaggatgtggagaaataggaatgcttttacactgttggtggga
+gcgtacattagttcaaccattgtggaagacagtgtggtgtttcctcaaggatctaaaact
+agaaataccatttgacccagcaatcccattactgggtatatacccaaacgattgtaagtc
+attctactacaaagacacatgcacaggtatgtttattgcagcactattcacaatagggaa
+gacttggaaccaacccaaatgcccgtcaatgttagactagataaaatgtggcacatagac
+CTGGTCTTAAAATCAAGAACAGAGATTGTTACTTTTACATCCATTCCTAATTGATAAACC
+ATTCAGTTATACCACATCTTAGCTTCTGGACTACAATGACCATATTTGGGGttttctttc
+taatttcattataggttcagagggtacatgtgcaggtttgagacaaaggtatattgcatg
+atactaaggtttggagtacaaatgattccacctcccaggtagcaagaataatacccaata
+tgtagtttttcaactctttcccctcttcctccatcctccctctgctactctgtggtgtct
+gtttttctcatctttatgtccatgtgtactcgatgtttagctcccccttgttaggtgaga
+acatgtggtatttggttttctgtttcagtgttaattcacttaggataatggcctccaact
+gcattcatgctgctgcaaaggatgtgactttcttcttattagctgcatatattttgtggt
+ggatttgtaccacatttactttatctagtccaaagttgttgggcacccaggtggattcca
+tgtctttgctattgtgaatagcactgggacaacccatacaagttcatgtgtctttttggt
+aaaacaatgtattttcctttgggcatatatgcggtgatggaattgctggatcgagtggta
+gtttaactcttagttctttgagaaatccccagactgttctccacagtggctggactaagt
+tgcattcccaccagcagtgtagaagtgttccccattctctgtagcctcaccagcacatgt
+tAAACTATCTttaaatatatgaaaaaaatgttcaagtctctcagattaagatgcatgcaa
+agtaaaatgatacttaaatatcagttctaacctataaaatatcaaatatctgacctcaat
+atttgataatccaacctgttgatgaagctgtagagagaggcaccctTtttttttttttta
+attatactttaagttttagggtacatgtgcaccttgtgcaggttagttacatatgtatac
+atgtgccatgctggtgcgctgaacccactaactcgtcatctagcattaggtatatctccc
+aatgctatccctcccccctccccccaccccacaacagtccccagagtgtgatattcccct
+tcctgtgtccatgtgatctcattgttcacttcccacctatgagtgagaatatgcggtgtt
+tggttttttgttcttgcgatagtttactgagaatgatgatttccagtttcatccatgtcc
+ctacaaaggacatgaactcatcattttttatggctgcatagtattccatggtgtatatgt
+gccacattttcttaatccagtctatcattgttggacatttgggttggttccaagtctttg
+ctattgtgaataatgccgcaataaacatacgtgtgcatgtgtctttatagcagcatgatt
+tatagtcctttgggtatatacccagtaatgggatggctgggtcaaatggtatttccagtt
+cgagatccctgaggaatcgccacactgacttccacaatggttgaactagtttacagtccc
+accaacagtgtaaaagtgttcctatttctccacatcctctccagcacctgttgtttcctg
+actttttaatgattgccattctaactggtgtgagatgatatctcattgtggttttgattt
+gcatttctctgatggccagtgatgatgagcattttttcatgtgttttttggctgcataga
+tgtcttcttttgagaagtgtctgttcatgtccttcgcccacttgttgatggggttgtttg
+tttttttcttgtaaatttgtttgagttcattgtagattctggatattagccctttgtcag
+atgagtaggttgcaaaaattttctcccattttctgggttgcctgttcactctgatggtag
+tttcttttgctgtgcagaagctctttagtttaattagatcccatttgtcaattttgtctt
+ttgttgccattgcttttgTCccaccgatcccacagaaatacaaactaccatcagagaata
+ctacaaacacctctacgcaaataaactagaaaatctagaagaaatggataaattcctgga
+cacatacactctcccaagcctaaaccaggaagaagttgaatctctgaatagaccaataac
+agaagctgaaattgtggcaataatcaatagcttaccaaccaaaaagagtccaggaccaga
+tggattcacagccgaattctaccagaggtacaaggaggaactggtaccattccttctgaa
+actattccaatcaatagaaaaagagggagtcctccctaactcattttatgaggccagcat
+cattctgataccaaagccaggcagagacacaacaaaaaaagagaattttagaccaatatc
+cttgatgaacattgatgcaaaaatcctcaataaaatactggcaaaacgaatccagcagca
+catcaaaaagcttatccaccaagatcaagtgggcttcatccctgggatgcaaggctggtt
+caatatacgcaaatcaataaatgtaatccagcatataaacagagccaaagacaaaaacca
+catgattatctcaatagatgcagaaaaggcctttgacaaaattcaacaacccttcatgct
+aaaaactctcaataaattaggtattgatgggacgtatttcaaaataataagagctatcta
+tgacaaacccacagccaatatcatactgaatgggcaaaaactggaagcattccctttgaa
+aactggcacaagacagggatgccctctctcaccactcctattcaacatagtgttggaagt
+tctggccagggcaattaggcaggagaaggaaataaagggtattcagttaggaaaagagga
+agtcaaattgtccctgtttgcagacgacatgattgtatatctagaaaaccccattgtctc
+agcccaaaatcttcctaagctgataagcaacttcagcaaagtctcaggatacaaaatcaa
+tgtacaaaaatcacaagcattcttatacaccaacaacagacaaacagagagccaaaccat
+gagtgaactcccattcacaattgtttcaaagagaataaaatacctaggaatccaacttac
+aagggacgtgaaggacctcttcaaggagaactacaaatcactgctcaaggaaataaaaga
+ggatacaaagaaatggaagaacattccatgctcatgggtaggaagaatcaatatcgtgaa
+aatggccatactgcccaaggtaatttacagattcaatgccatccccatcaagctaccaat
+gactttcttcacagaattggaaaaaactactttaaagttcatatggaaccaaaaaagagc
+ctgcattgccaagtcaatcctaagccaaaagaacaaagctggaggcatcacgctacctga
+cttcaaactatacgacaaggctacagtaaccaaaacagcatggtactggtaccaaaacag
+agatatagatcaatggaacagaacagagccctcagaaataatgccgcatatctacaacta
+tctgatctttgacaaacctgagaaaaacaagcaatggggaaaggattccctatttaataa
+atggtgctgggaaaactggctagccatatgtagaaagctgaaactggatcccttccttac
+accttatacaaaaatcaattcaagatggattaaagacttaaacgttagacctcaaaccat
+aaaaaccctagaagaaaacctaggctttaccattcaggacataggcatgggcaaggactt
+catgtctaaaacaccgagagaggcactcttatgcattgttggtgagaatacaaaatggta
+caactcttggcaatatcttaaaaaatttacatggtactgacttttggtctagcaatccta
+cttctatcctaaagatatattggcaaaaatacaaaataattgatgcactcaagtctattc
+attgaagcattgtttttcatagtaaacggaaagtaggccgggcgtggtggctcatgcctg
+tgatcccagcattttgggaggctgaggcgggcagatcacttgaggccaggaattcaagac
+cagcgtggctaacatggcgaaaccccatctctaccaaaaatacaaaaattagctgggcgt
+ggtggtgcacacttgtaattccagctacttgagaggctgaggtgggaggatcgcttgaac
+ctgggaggcagaagtttcagtgagcccagaacgtgcctctgcactccagccaggatgaca
+gagcaagactccatctcaaaaaaaaaaaaaaaaaaaaaggaaaataaccaaatgacaatt
+agtgagtactacttgcaaaacttgtacgcaatagagtatgaagcaactataaaatgagag
+agaaatatctccaaatactactctaaagtaatctacaaggtataccttaactgaaaagaa
+acaaaaaagtgacaccagaatgctatttttatgttaaaacagggataaataCATTGGATT
+TACATGCatatataagtatatattttataaatgtttaaataaGCATACTTAAAATGGCAA
+AAACGTAATACATATATAATTTTCTTATGGCAGGAGGAGGAAACAGGGCAAGGCACAGGG
+ATAAAAGTTATTCTGAATACATCTTATTTTATATTTTTGACTTTGAAATCCTGTAGCTGT
+TTTATGTAATATAAAAATGTAATTAAATTAACAGAAAAAAATTACAACTGCTAAAAATCA
+AGATCTGGCATTTTAATTAAGTTATAAAACATCGGAGAAAAGAATTGTTTCATGGGACAC
+TAACATACAGACAAATTCATTTGGAACCCAATGAATTAATGGGCCTAAGATAACAACCAA
+TAGAAGCTAAAATGACGAATAACTGTTTCAGAAGAAAACATATATGGAATGAATCAGCTG
+AAAATACCTGAACCTACTGATCAATTTTTATATCACATGAAGTGAATACACATAAAGTAT
+AATATGGAGCACATAGAACCAACTAGAAATGAGCCTAATTGTTAAATATTCTCTATTTTA
+TGAcaatatacaggaaatatgtcgaagagagaaacatgcaagaacaccgtagggtttaat
+aagataatcacaaggtatggaatattcaacaggatgagtatcctggattattcagcaaat
+acacagagctaaaaagcaggagaaaggaattcatatatatttttaaaaactaaaaagata
+tattagctgatgcaactttgaaacttctttagatcctgattcaaatagagcaaatttaac
+aaatatatttgaaactattaaaataatttaaaaatgaccaagtatttgattatatcaaat
+atagacaataataaccttgaatgtacatggattaaatgtccacttaGGggctgggtgtgg
+tggctcatgactataattccagcactttgggaggccaaggcagaaggattgcttgaggtc
+agaggttcaagtgcagcctggtcaacacagtgaaaccctatctctacaaaaaacaaacaa
+aaataaaaaaTTAACtaattttaaaaaatatatatttCTTCtaaattctccacctgaaag
+atatagactgactgaatgaattttaactatgatctgactatgtgcttccctgaacaaatg
+cactttacctgtaaaacacatattaactaaaagaaaagagatggaaaaaggtattccatg
+aacagaaaccaaaatgagtaggagtagctatacttctgtcagacaaaacagactttaagt
+caaaactagctttagaaaaaagacaaaaatgcttattatacaacgataaaggaatcaatc
+cagaaagaggatataacaattttaaatatatatgcagccaacactggagcagccagattc
+ataaagcaaatactactagatcaaaacagagaggtagactcaaatataataatagtgaag
+gacttcaacaccccactttcagcattaaacagatcatctaataagaaaaccaatctcgca
+gccctcaccctggagagtccacaggtaccaggggttggtctgaacccccagcacagagca
+cctgcctcacagaagagtggctgcatttttcttcctgcagttttcagtcctcacttctcc
+ttaccaagcagggccacctggcctgggactccggtacaactaccctgccccccacctgac
+gacttcaataagaagtagcccagcatttctccaaggaggaaataccagagtcaattcaca
+accactgcaattgcagtggtaccaccataacagcccttgggctgcagaaggaactaagag
+tctagtcactacagtggcaccttcagcacaccacagccaccatacagagaggaatccagc
+cccctcccctgggaacccccaccacccactccaccaggcacagcacccagctcataactg
+cagatcagttgccccacccacagctgagcttacctactggcagtggcccagactttccct
+agggagaggctcccagaggcaaacggcagcctctctgcccgtgtcacagcagcagttcta
+tccatgctgtcctcaggcttggaaagaaacaaagcgcctgaaggctgcacctgaacttac
+agcatgccacagttcccatatggagaggagaccagtctctcctcccagtgagccctaaac
+cccctgatccccaacaagcagagccctaacctcacaccagcagtacagctgccccatccc
+ccaggctgaacattcccagtaatagcagctccacctggagatggaacccccagggtcaac
+taaaagcccctctgccactgcctctacagtggtactacccctgctacccttgaactaaca
+aaggagcaaagaccccagtgctttatccacacctccaacaagctgcagtcgaccacaaag
+aagaaacacgtctgtctcccatgggtcctacccacaccccctgctgttcaccatggatga
+tagagtcaacagtgtgaaaacgaccatactgccaaaagcaacctacaaattcaatgcaat
+tcccatcaaaataccaccatcattcttcacagaactagaaaaaacaaggctaaaattcac
+atggaaccaaaaaagagcccacatagccaaagcaagactaagcaaaaagaataaatctag
+aggcatcacattactcgacttcaaactatactataaggccatagtcaccaaaacagcatg
+gtactggtataaaaataggcatatagaccaatggaatagaataaagaacccagaaataaa
+gccaaatactttcagccaactgatctttgacaaagcaagcaaaaacataaagtggggaaa
+ggacaccctattcaacaaatggtgctggtataattggcaagccacatgtagaagaatgca
+actggatcctcatctctcaccttataaacaaatcaactcaagatggttcacagacttaaa
+tctaagacctgaaaccataaaaattctagaagataagattggaaaaacccttctagacat
+tggcttaggcaaagacttcacaatcaagaacccaaaagcaaacacaacaaaacaaagata
+aatagatgggacttaattaaactgaaagccttctgcacatcaaaataaataatcagcaga
+gtaaacagacaacccacagagtgggagaaaatcttcacaaactatgcatccaacagagga
+ctaatatccagaatctacaaagaattggaacaaatcagcaagaaaaaaaaccaaacaCAA
+GGATGACAGTGGAAATACAAAAACAAGACATAAATATTCTGAATAGTGATAATAAAACAG
+TGCATACCAGAATAcaaactgtttccaagttacaatggttcaaccatttttcagctttat
+ggtggtgtgaaagtgatatccattcattagaaaccatgctccaggatgggcgcagtgggt
+cacgcctgtaatcctagcactttgggaggccgaggagggcggatcacaaggtcaagagat
+caagaccatcctggccaacatggtgaaaccccgtctctcctaaaaatacaaaaattagct
+gggcattgtggtgcgtgcctgtaatcccagctattcgggaggctgaggcaggagaatcac
+ttgaaccagggagtcggaggtgttgcagtgagccgagatcgtgccactgcctccagcctg
+gcaacagagtgagactccatctcaaaaaaaagaaagaaaccctactccgaattttgaatt
+ttgatattttcctggactaccaatatgtggcacaatgctctctcacaatgttgtgcaaca
+gcggtgagctgcagcttccagtcagctaaatgataataaaggtagataatccatcttgat
+atcttcctgaagaacataatgcctgcctaccatcaacaggcatcaatactttctaccagc
+tattctcaaccctcatgatcggaagagacagagactgactgtgtcaaagtattagtccca
+tcattcagcaattaactttagctcaatgcttcaaaaattcttcaggccctgtgtaatttc
+agctacgtacattaatgatgagtacccatacaaccattctgtttcttattttcagtacca
+tatttaataaatatcagttattcaatactttatttagacattttgttagattattttgac
+caactgaagtctaatctaaatgttctgagcatgttcaaagtaagctaggccaacctataa
+ttttcggtgtgctaaatgcatttttaacttatgatattttcagtttacgggggtttgttg
+agacataacttcatcatacatcaaggagcatctgTAtatgggatatagttaaagcagtga
+tcagaggaaaatctatagccttaacacatttattaataaaagtgtaggaattaaattatc
+agctgaaaaatgtaaaaagtatctaaaagagtaagcagaaagtacaagaaagaacccaaa
+gtagaaaaaagtgaaaattaataaaataagaagccaaaaaacagatcaaatcagtaaacc
+aaaaatcttgttctttaaacaaatcaacaaagttgacaaaaaaattagatcttttaatca
+tgaataaaaaaaagagaaagcacaaaaatgaataaggaatggtgagagaaataactattg
+ataatcagcaaataaaaaatcattaaaaacaatgttgttcacatctatgaaaaacattga
+aagctagagggaatgggtaattttctagaaaaatacaattcaccacaactgacttcaaaa
+aaaaaaaaaaaaAAAAAGAAGTACCGCACTTATGTGAGCAATTTCCATAGAGAAATACAG
+TTGTCATGGAATTATAACACACACACAAACACTAGGTTTAGATGTTTTCACAGAGAATTC
+CACCAAACCTTTAGAAATCAGATCGTCCAaaggcaaattaacaactctcagccatttgag
+gcaaaatattacaattgaggcaagatatactgtactgaaaacttgaggaaaaagcaggag
+agaaagttcctttgggaaattcgaatactcaaaagtgcttacatacaatgaaaaatttgg
+aaatccataagcatggccaaggtgggacacatgctcagaaaaggcctgagaagacactaa
+taactcacctttagtaattcctaggctcacagcaagaaaaaatgaaggctaaggcagaat
+tatatatggctccgctaagtgttgagggagccccaatacagagtcagtaagcaaagtctg
+ggagaagtttttcatatttttttctttcttggctccttgcagtcaaggaaatcattttta
+aatcactaaatgctaaatgaacacaagctaaaggaaccgagccttcaaacatcaaatata
+aaaaagaatgcagatattacaaaaccagtttacaaaagttactaaacaaataaaaactac
+atcccacagtgggtaacaaaaataaccttgaagaagggaaaaatttggtttccagaataa
+acacattataatatccaaaatgtccagttttcaacaaaaattaagaagcatgcaaataaa
+cacaaaactatggcccatttacagaagaaataaatgagactctccctgagtaagcagata
+ttgaaaatattagacaaaaactttatataactgtcttaaataaacttaaagagctaaaga
+aacccaagagaatgacatataaataaataagaaatatgaatttttttaaaggtacaaaaa
+aattctgaggctgaaaagtacaataagtaaaaagttactttttacttagggttccaatag
+aagatttgagcagctggaaaaaagaatcagtgaacttgatagatcaaatgaaatgattca
+gtctgaagagcaggaaaatgaaagaatgacaacaaaaaagaatagagcctaaagacctgt
+gtaacaacatcaagaatgcctacatacagaatcctggtggggagtgaggggcaggaagac
+tatttgaagaaatgtgtttgaaagcttcccaaatttcactaaaaacaaatatatacattc
+aaaaagctcagtgaacttcatcaaggaaatatacaaagatattcacaccaagacacacta
+tgtttcaaattgtcaaaaggcaaagcgaatgtttgaaagcagcaagagaaaggcaacgcg
+tcatttacaaaggatcctcaataagtttgacagcagatagtgcattataagccatggatg
+ccagaagagcttaggaaaaaggcaacgcgtcatttacaaaggatcctcagtaagtttgac
+agcagagagctcattataaaccatgggtgccagaagagcttaggatgacattttaaagtt
+ctgaaagaaaaaaacactgtcaaccaaaaattctataacttggaagatgccccttcaagt
+attaaggataaattacacattcccagattaaaaaaaagaaagagagagagagagaaagag
+aaagaaagaaagagaaagaaagaaagaaagaaagaaagaaagaaagaaagaaagaagaga
+aagaaagaaagaagaaagagaaagaaagaaagaaagagagagagaaagagagagaaagaa
+aaagaaggaaagaaagaaagaaagaaaaaagaaagaaaaagaaagaaagaaagaaagaaa
+gaaagaaagaaagaaagaaagaaagaaagaaagaaagaaagaaaagcaagcaagctttaa
+aagttcatgtttggtaggctgtacttcaagatacacttttaaaaaaaagactccttcaga
+tacaaactaaaaaacactagaaagtaactcaaaaccacataaagaaataactccagtaaa
+gataactacataggtaaatataaaagcaattatcacattttttgtaagtcttttttaata
+ttctatatgttttaaaacaaatgtgtaaaataatgactataaatctatgttaatgaagca
+tgatgtatacagatgtggtttgtgaaattaccaacataaagaaattcataggaaactaaa
+taataatagagattttgtatactattgaagttgtttcaatttactctaaattgttccaaa
+ttaagaatgttaattgtaaatccccatggtaaccactaagttaatatcttttgaaaatac
+agaaaaggaaagcacagggtaaacacagtgatatgctacaaaatagcaactaaacacaaa
+agaaggcgataattgaggaaattaggaacaaaggaggtataagacatacagaaaacaaaa
+gcaaaatggtaggagtaagcccctctttatcagtaattacattaaatacaaatgaattaa
+actctccaatccaaagaaagagattaacagaatggattttttaaaaatgatccaactata
+ttgtccacaagatactcactttagatcaaaatacacaatgagttgaaatgaaaggatggg
+agaaaatattccatgtaagtaataaccaaaggagatctgaggcaaatatacttatatcag
+acaaaatagactttaagtcaaaaactgttacaaaatacaaagaacagtatatattgattt
+caaaattaattaagaagatataacaattataaatatatgtacaccaactaacagggctcc
+aaaatatataatgtaaccattgagagaattaaagggagagacagacaattccacgaaaat
+tgttgggcatttgaaaacccaactttaaataaaagataaaacatctagagcaaatatcaa
+gggaggaattagaggatttgaataaaactataagcaataactatagataacacttctctc
+aaaaactgcagagtacacattcttctcaagtgaacatggaacattctccagcacagatga
+tatgttaggccataagataagctcaataaacttaaaaagattgaaatcatgcaaagtatc
+ttcactggccacaatggaatgaaataagatatcaataacaaaagaaaaactagaaaattt
+acaaatatttggaaattaaacaacacagtatttaccaaccaatgaatcaaagaacaaatc
+atgagggaaattagaaaatgtttagagacgattgaaaacaaatatataacaagatgggtg
+tgatatatcaaaagcagtgctcagagttgtaacacctacattttaaaaaagaaacatgtc
+aaatcaataaccaaactttactcaataaaccgtaaaaggaagagcaaacaaaatccagag
+ctagcagaaggaaggaaatgaagattagagcagagataaatgaaattgagaattaaaaaa
+ttatacagagatcaacaaaattaaaagttggttcttttaaaatatcaataaaattaatat
+acttttacatagactaagcaaaacatctctattcagctgactttttttacaagggagcca
+acattattcagtggggaataatagctttttcaacaaaaagtgctgggaatactgaatatt
+catatgcaaaaaaaatgaagctggacccctacctcacattatatacaaaatctagattgg
+atcaataatgtaaatataagagtgaaaaccatacatgcttagaagaaaacatggaaataa
+aacattgctgtggattggcaatgcgttcttagataatacaccaaaaatacaagcatgaaa
+caaacaaatGCAGCCAAAATGTACCAGAATCTGAAAACATCTATTATCTATGAAGAATTA
+GAGGGGAATTTGGTGAAAGAAATatgggagaatgggacattgctctgtgaatgcttttgt
+gcataattgtacatttttaattaagttaatcttttacactctcaaagtgtgatattaagc
+aagcaaagataagttattacaagactctaaaaccgaatgcaatgagaaacaagtgaatcc
+aaatatatttcaaatgaatgaatgacataatcaaacttaaggggaaaataataattaatc
+tgattaatttttgactgttcttttagttcaaattgacttttgaacatacttggactacat
+accattgcttgaaaaaataaaatatctgcaaaaaattattaaatcttcatgataggcttt
+tttctttttatattagtataaatataacaattctgaaacaaatgtatgtgcattgtaaga
+ttaagccaatgagtaaatattaatatatttgtattgctagaaccccagattctcactgtg
+aaaggacagagatacagatatggaataagacaaggaaagaagcagcccactgagttacat
+tagaatcagtattatcaacataaaTATGCAATGTGCTCTCTCACATGCTCTTTCCTTCTC
+TTAAAAAAATATAATATGGACATATTATATATTATATGCATAGACACACGTGTGTCTATA
+CATATCCTATCTATACATATTGAGGATTAACAGGTGCTAGTAGAAAATATTAACTTTCTT
+TGTATTAACAGGTGTTAGTAGAAAGTAGTAGTAGGTGCTAAGATAAAAGCCATAATTAAA
+cctcctggtgaatgaacacaccatcacctacaatcttaccaaaaatagaatcaagcacgt
+gtcctagtcaaacctctggattcaactgtcatttggataaaacgcaaaggatagtgaaaa
+tgtcgatcttcactgagagtctaaccagcaaatttcacagtgtggacatcaagtgacaaa
+aatcccaaatttttcaacaaatatattgtatgggaaagaaaactttgaaaagaaacctgt
+atgttagaagagattttaaaaacatgacaaATGAAAAAAAATGGGCAAGACTAAAACTTT
+TAAAAAAGtttgagacagggtctcactctgtcacccaggctggagtgcagtggtgtgacc
+atggctcactgtggcctcaacctcctggctcaagtgatcctaccacctcagtcttccatg
+tagctgggactacagctgcgtgccaccacatctggctcatttttttttcttttttaagta
+gagacggggacttgctatgttgcccaggctagtctcaaactcctaagcacaagcgatcct
+cccgcctcggcccctgaaagtgctgggattgcaggcatgagccaccacacccggccAAAA
+GTTGCTTTTGAGGAGTTATTGCTGTGTGGATGTGATATAACCCTTTCTGTCATCTCTTCA
+CAAAACTTTCTGTAAAACATAAAAATCACCTGGACCTTCAGAGATGAGTTTGtttatttt
+tttattttttaaaaaattGCTAATTTACAGAACATGGAGATGAGTATGTTTTGAAGGCTT
+GGAAGCATGCAAGTGGGAGAAGAAAGGAGTCAGCTACATTCTGGCTGTGTGCAGAGGCAG
+GTCACTGTGGTGGGAGTGTTCCTGTTTCATGGACTCTGCAAATCGCAATGCTTGGCATGG
+CCTCCCGACCCTGATGGCAGAGAAGCAAACACCAGTCGGAGAGCTGGGGTCCTCCCAGCC
+CTCTTGGCCCTGTGGCCAATTTTTTCTTCAATAGCCTCATAAAATCACATTATTTGAGTG
+CCCATGGCTCCAAAACAAGCAGGGATGCCCATGGACCCTGATTATCCATTGTCACCCTTC
+CCTCCAAACAGCCACCTCTCCCCTGGAGACAGCCCCATACTCCACTCAGACCTGTGCACT
+TTCTGGTATCCTTGTCACCTGCTTTTTATGTCTCATTTTACAAACACCAAATTGGAAGAC
+AGCAGGAGCTGCCCCATAATACCAGTAAAGTGAGAAGCAGAGATAAACTAGTCCTAGACA
+GCCGACTCATGTTGGGGGCAGCCCACTCACAGTGGCCCTGACCCAACTCTGACTAGAGGC
+CACTTGctctcaacaccagggtgctcaatggcccgtcctggtactctgctcttctctctc
+caccttcgctttcctgcaatctatgcagcctgtgactccatccatgggctagtgaccccc
+agaccttctcctgggaccacaggcctgtgtctctatctgctgctcaatacctcccctcga
+acatccatggctaaaactgagctcctgatactctctccctacccgcttctctgtggattc
+cccacctccgcgaaggacagcttcatcctttcagctactcaggccagaagattgaagtca
+tctccttctccaggaaatcgtattgagggagctacaaatatccaaaatccgatcgcttct
+cctccactacacccgaggcccgccacccatttttgcctgaattgctgcagcagcctccta
+accgatctctgctttcacgtgggcacctcagttttttccagaacaacaaccagagagatc
+tgctcacacccaagtcagaccaggttactcctctgctctcatagcatttggaggaaaacc
+cagagtgctcgtgttggccggcagagccggcccccatctcctctgacctcctccccacct
+cttgccctcagcacccagagtgctcgtgacggccagcagagccagcctccatctcctctg
+acctcccacctctcgccctcagcaccCAGAGTGCTCGTGTTGGCCAGCAAAGCCGGCCCC
+CATCTCCTCTGACCTCCCACCTCTCGCCCTCTGCACCCAGAGTGCTCGTGACGGCCAGCA
+GAGCCGGcccccatctcctctgacctcccacctctctccctcagctagtcctcgaacatg
+tctgatgtggtcccaccttgggacccacattgctactcctctgcctgtaggggtacccac
+agttatccacacagttcactcctgtctttcaggtctttgtgcaaatatcaccttctcagt
+ggagacTACaccttcaggacttaggctgtgcctggcacatagtaggtgctcagtagacac
+tggttgtaggaaggaatCTACAGGTTGAAATAAGGAGATCATTTCCCTGAGGTTCCGAAG
+CTCATATTTACTCACCATTTGTTGTTTACTGCTAATATTGAGCACTATCAGTAAAATACA
+TAAAACCCtttgccaatccaggaagtgaaaatgacactttactgttttagtttgcatttc
+tctgcttacaaatggattacacgcattttcatgtgctgttggctacttATTCATTCAGAA
+AACATACTAAGTGCTGGCTCTTTTTCATGTCCTTTATCAAGTTTGGATCATGTCATTTGC
+TGTTTTCTTTCTGATGTAAACTCTCAAAGTTTGAAGGGTATTGTCTTTTCCTGACACATA
+CGTTGTAAATAATTTTCTGGCTTACATTTTGACTTTTAATTTCATTCACGATGTTTTTAA
+TGAATAATTTTAATTTTTATGAATGCAAGTTAAAATAATTCTTTCATTGTGGTTTCTGAC
+ATGTCATGCCAATAAGGGTCTTCTCCTCCAAGAGCACAGAAATATTTGCCAATACTGTCC
+TTAAAATCGGTCACAGTTTCATTTTTTATATATGCATTTTACTTCAATTGGGGCTTCATT
+TTACTGGCCCTATTTGAAGCAAGTTTCTCAGTTAATTCTTTTCTCAAAGTGCTAAGTATG
+GTAGATTGCAAACATAAGTGGCCACATAATACTCCCACCTCctttgcctcctctcccagg
+aggagatagcctccatctttccactccttaatctgggcttggccaagtgacttacactgg
+ccaatgggatattaacaagtctgatgtgcacagaggctgtagaatgtgcactggggcttg
+gtctctcttgctgccctggagaccagctgccCCACGAAGGAAACAGAGCCAACCTGCTGC
+TTCCTGGGGGGAGACAGTCCCTCAGTCCCTCTGTCTCTGCCAATCAGTTAACCTGCTGCT
+TCCTGGAGGAAGACAGTCCCTCAGTCCCTCTGTCTCTGCCAACCAGTTAACCTGCTGCTT
+CCTGGAGGAAGACAGTCCCTCAGTCCCTCTGTCTCTGCCAACCAGTTAACCTGCTGCTTC
+ATGGAGGAAGACAGTCCCTCAGTCCCTCTGTCTCTGCCAACCAGTTAACCTGCTGCTTCC
+TGGAGGAAGACAGTCCCTCTGTCCCTCTGTCTCTGCCAACCAGTTAACCTGCTGCTTCCT
+GGAGGAAGACAGTCCCTCTGTCCCTCTGTCTCTGCCAACCAGTTAACCTGCTGCTTCCTG
+GAGGAAGACAGTCACTCTGTCTCTGCcaacccagttgaccgcagacatgcaggtctgctc
+aggtaagaccagcacagtccctgccctgtgagccaaaccaaatggtccagccacagaatc
+gtgagcaaataagtgatgcttaagtcactaagatttgggCAAAAGCTGAGCATTTATCCC
+AATCCCAATACTGTTTGTCCTTCTGTTTATCTGTCTGTCCTTCTCTGCTCATTTAAAATG
+CCCCCACTGCATCTAGTACATTTTTATAGGATCAGGGATCTGCTCTTGGATTTATGTCAT
+GTTCCCACCTCGAGGCAGCTTTGTAAGCTTCTGAGCACTTCCCAATTCCGGGTGACTTCA
+GGCGCTGGGAGGCCTGTGCATCAGCTGCTGCTGTCTGTAGCTGAGTTCCTTCACCCCTCT
+GCTGTCCTCAGCTCCTTCGCCCCTGGGCCTCAGGAAATCAATGTCATGCTGACATCACTC
+TAGATCTAAAACTTGGGTTCTTGgaccaggtgcggtggctcacatctgtaatcccagcaa
+tttgggaggccgaggcgggtggatcacaaggtcaggagatcaagacgatcctggctaaca
+cggtgaaaccccgtctctactaaaaatacaaaaaaattagccgggtttggtggcaggtgc
+ctgtagccccagctacttgggaggctgaagcaggagaatggcgtgaacctgggaggtgga
+gctggcagtgagccaagatcacgccactgcactccagactgggagagagagcgagacttt
+ctcaaaaaaaaaaaaaTCTTAGGTTCTTGGATGTTCGGGAAAGGGGGTTATTATCTAGAA
+TCCTTGAAGCGCCCCCAAGGGCATCTTCTCAAAGTTGGATGTGTGCATTTTCCTGAGAGG
+AAAGCTTTCCCACATTATACAGCTTCTGAAAGGGTTGCTTGACCCACAGATGTGAAGCTG
+AGGCTGAAGGAGACTGATGTGGTTTCTCCTCAGTTTCTCTGTGTGGCACCAGGTGGCAGC
+AGAGGTCAGCAAGGCAAACCCGAGCCCAGGGATGCGGGGTGGGGGCAGGTACATCCTCTC
+TTGAGCTACAGCAGATTAACTCTGTTCTGTTTCATTGTGGTTGTTTAGTTTGCGTTTTTT
+TTTCTCCAACTTTGTGCTTCATCGGGAAAAGCTTTGGATCACAATTCCCAGtgctgaaga
+aaaggccaaactctggaaaaaatttgaatattttgagccaaatgtgaggaccacaacctg
+tgagaacggaaaataaatcctgggaccccagactcactaagccaaagggaaaagccaagc
+tgggaactggcttatgcaaacctgcttcccatctggttcctaaataagatagctattaca
+caaagacaaaaaagctacatccctgcctctacctccatcgcatgcaaaatgtgtattcag
+tgaacgctgaccaaagacagaagaatgcaaccatttgcctctgatttacccacacccatt
+ttttccacttcttcccctttccccaatacccgcacttttcccctttacttactgaggtcc
+ccagacaacctttgggaaaagcacggaccacagtttttcctgtggttctctgttcttttc
+tcaggtgtgtccttaaccttgcaaatagatttcttgaaatgattgagactcaccttggtt
+gtgttctttgattAGTgcctgtgacgcagcttcaggaggtcctgagaacgtgtgcacagt
+ttagtcggcagaaacttagggaaatgtaagaccaccatcagcacataggagttctgcatt
+ggtttggtctgcattggtttggtctggaaggaggaaaattcaaagtaatggggcttacag
+gtcatagatagattcaaagattttctgattgtcaattggttgaaagaattattatctaca
+gacctgctatcaatagaaaggagagtctgggttaagataagagactgtggagaccGTGCA
+TAGTTGCTTCCTGATCAGCTCTTTATTTGATTGAGAGTGAGGCAGGGAAGATTAGAGGGA
+AGCTTACAGTGGAATTCAGGGCTGAGGCTGCTATTCTTTTGCTCCTTGTAACTTCCTACA
+GTGTTGTCAGCATCCACATACTTCTCTGTGGGGTTggtctcagagccaggttaccttgtc
+ttaggtccagtggcaccctgactggcttggtgtccttgaacaagttacctaacctctcca
+aacctcagtccctcagttgtaaaattaaaaaaaaaaaaaagaagaagaagagtacctact
+gtatagcattgatttgaagattgaatgagctggtattatacaacgtttagaagcagtgcc
+tgacacgcaaaaggctctcaacaaatACTATCCTTTACTAATATCCTGTGTGTCTGTATC
+AGAGCTGGTGGGGTGGAGGGACAGAAACAAGTGGGAGAAGGTaaagagatggacaaatga
+tctctaaagtctctctggcactaacaCAATTCTTTATTATGTGTTTTGTCTGGCTCTTTA
+TATTGATAGCTGTTCCAGAGGCAATCAATAGCTATTAGTCGGTTTTATTCTTATTTTTCT
+GTCTGATCTTACAGGGGAGCAAACTGTGGCAAAGTATGAACTTACTTCTCAGGAAATTAA
+CCATTATATTGGCAATCACTGTGATTATTTGAACTTCAGCGTCTGGACAAATTTAGTCAC
+ATGAAATACAGAAGAGAGATTTCTCATGGTTAAAACGAAGCTCTCTTTATTTGCTTCTGC
+TAATTAAAAAATCAGAGCTAAAGATACTTAAACACTACAGTTAAAATGCCATGGTTGTCT
+ATTGGCTTAACGAATTCTCTTATGAAATCAACTCTAAAATGCTATCCATCATAAATCATG
+AAACGCAATTTTTCTTATTCTCTTTAGAGCTTTACAATTCATCTTAAAGACCAGTGTTTA
+CACTCTCTTCTGTAGGTTGTACAATAACTTTTGGCGAGAAAAAATAAAAGTCTGGCTTTC
+TGACTCATAGGTGTGTTCCCTTTAACAGAAAAAGAAAATATGTCCTCTTTAAAACTGATG
+ATCATTGGTCACCTCAATTTTATTGAAGTTCACTTCTGACCTCTTTAGATGTAGTTCTCT
+ACATAAAACTGCCCAACAGAATTCTCTGTCTGAATGTCTCCTCCACAAACAAAATTTTAA
+GAACTAAAATTATCATCTTTCCTTCCAAATATGCTCTCCCTATGTCCCCAGGGCTCTCCA
+TGTGTAGAGCTGAGACCATTTGCCACTCAGTTTCCTCACCCAATTAATTACAAGTCCCAA
+CAATTTTCCGGtttttttgtttttgtttttgtttttagacggagtcttgctctgtcacca
+ggctggtgtgcggtggtgcaatctcagctcactgcaacctccgctgcctgtgttcaagcg
+attctcctgcctcagcttcccaagtagctgggattataggtgtgtgccactacatccaga
+taatttttgtatttttagtagagaggggatttcaccatattggcccagatgatctcaatc
+tcttgacctcatgatctgcccaccttggcctcccaaagtgctgggattacaggtgtgagc
+cgccatccctggccCAGTTTTGCCTTTTTAACATCCCTCAGCTCTTCAAATCCATTTTCT
+cttctctaacacctccccattccccagctcgtaatgaactcgtaagtagattactacaat
+cacctcccaaatggtcttcctggctccatcagccttgtgaccttcaagttcattttccac
+atggatgtcagagtaactttctaaaatgaaaatctgaccacgttactctcttgcctaaat
+ccgcctatggccgctgttaggatcaagtctaaactcccgaccctggaacatcaggtcttc
+gtgctctgttcactgcttctctacctcacctgcaaccaACACCACTCCCACATCCATATG
+CTGCTCACCGTGTATCAACATGAACAGGAGGTGGGTGTTTCAGTCCCCAGGAAGACACTG
+GGCCTTTTCAATCATCTACTGCTGTGTAATAACCACCCCGCAAACTGACCACATGATTTC
+ATTTTGCAAGGGTTCCTTCCTTgggctgtgttcagcaaaagggtttactgagctggcagg
+tccaagatggcctcactcacaggactggctgttgatgggagccttgatgctcttgggctc
+accccttatcctccagtaggttagagcttcttacagtggtttcaggcagcatctgaagac
+agtaaaagcagaagctccaaggcttcttacattctagcctggaaaatcacatcacattgc
+ttccttcatatttttttggcaaatcaggttgcaaggcttgcccagattagggtaaagagg
+caaagaggctccttttcttTTCttttctttttttttttttttttttttttgagtcagaat
+ctcgctctgttgcccaggctggagtgcagtggtgcaatctaggctcactgcaagctctgc
+ctcctgggttcacgtcattctcctgcctcaggctcccaagtagctgagactacaggcacc
+taccaccacgcctggctaatttttttttattttttattttttagtagagactgtgtttca
+ctgtgttagccaggatggtctccatctcctgacctcgtgatccTTGCAAAGGGACATGCA
+GACCACATTAGTGAGAATATGTGCCTGTATTTTGCAATCTGTAACATGGGCATAAACTAA
+ATGTTTTCCAAAGGGAATAGGGCAAAACAAAAAGGACCTTGACCACTCCTTGGCCCTGAA
+TAAATCCAGGAAGCCTAAGAGTATGACTATCCTGAGGTAGAAAGAGGGTCACATGCTGGA
+TAAGAGGTACCTGGGCTCTCCACTTACAAGAAGAGAGCATGGTTACATTTATAATCACCA
+TTCCCAACATGCTGTGAGTGCAGGCAGCTACCAGGAGGAGAACAAAGGAAATAACCAGGA
+CACTCATCTCTAAACCTGTTAATTTAATCACACGGAACACTTCTATTTAAAATTCCCGAG
+AGTTAAGATGTAAGAATGCTTATCAAGGTAAATGCTGTTCACACTGCTTGGAGTGTCAGG
+CCTAGATCTCTATCCATCAGAaacaacaatatcaataacaacaacagcaacaTGATGATG
+GGGCAATTTCTTAAAAGCACCATGTATTTTATCGATACATGTCCGTTGCAGAAAATCCAG
+GTGAATCCAAAGAAGAAATAAATGTCTTCCACAATCCCATAGCCCAGAGCTAACTAACCA
+CTATAAAGAACCCAGCGTGGTTTTAACTAATGGATCAAAAGATGCTCATCAAAGGCTCTG
+AGCTTTCCTGAGTGCTAACAGGAAACATCCAGCATCACTGGTCTCTCCAAGGCTGCAGGT
+GTCTTTGCCCATAGTGCCTGTTTTGTGTCAGGGAAAGAATCAACCTGGGAGCCAAGCCCA
+GGAATCAGGATGACCAAGACATACTGCACAAGGAGGGAACAAACCCATCCAAGGACACTC
+AAGGACAAATCAAGCAAATGAATTTAAGGGAGACGTGCTCATGGTCTGCTTTGCTGCTCA
+GCATGGCTGGGAGGCACAGTGGAAGATCATGCATCCTGCCCCTGGGACTCCTCTGCCAGA
+GCCTGAGAGCTTTCTCCTGCCCACAGGCTAGGGGTAGGGCAGTTGGAATTGATCCATGCC
+TTCTAGCTAGACTGTGGGTCCCCTCAGTCTTGGGCATGGTGACAGCCCAGCATCAGACAG
+AGGTCAGTATCAAACTAGAAAATTTAATAAATACTGTCAGATTTGTAGACCCAAGAAAAT
+ATAAACTGCCAATCACGGAGGAAAAAAATCTCTCAATGATCTTATCTTTATATGATTCCC
+TTGCTGCCTGGAGATTGACATTTCCTTGGGGATAATCTGGTCATAGGATTGGTGAAGGTG
+GAAGGGAGGCAACCTCCAAAGGTGGGGCCCTCTGCTCACCTGGGACAGGGAGGGCCTGAG
+GTAGGTGTCTGTGTGGGCTGGGGAGGAGGATGGGAGCAGTGCTTCTAGATGTTTCCACTT
+TCTCCTCATTAGATAATAACGAATGGGTGATTTCCCTAGTCACTGCAGTGTGAGGAAATC
+TACAAAATTAATTTCACAATACGCTTTACAGGATAGGTGGAGAAACACATGAAGTACAAC
+TGCAGTGGGTTATAAAAAACGGCCTTTCGAGTTGAGCAATAAATTCGTTCAAGCAGCCAT
+TCTGAAGGACAAACTGGCTCTGTATTTAAGAGGGGCATTCCAGCACTTCTCTAGCCACTG
+GGTTGACAATGACTCACCAAAGCCTCTGGTAGCCACCACAGGACACCCAGAGCATATGTT
+TTAAAGCTGAACACCAAACTGCGGACTTCGGGAGTAAGTGAACTGACTGGTTTTTATTTT
+GTTTTACTGCTTTTAACATTACAGTAACTGTTACAGGTTCCAGCAGGCTAACTGGGTGGA
+AATGAGTTTGGTTTCACTTAGTCTCTCTAAAGAGAAAGCAAGTCGGTAGACTAATACCTA
+ATAAAAGCAAAGCTGCCAACAATTGAAATTGCCTAGGCTGCTCTGTGTGTCCCACAtgca
+tgggtgtgggtgccagtgtgtgtgcgtgtgtgcatgcatgtgcatgtgtgtTGGGATAGA
+GTGGTAAGAAAATGGGAAATAATAAGAATGTTCAGTCCATAGCCCTTCATTATAAAAAGG
+TGAGCTGTAATAAATACTAGTGCCACATTTAGCCAAAACTTTACTCCAGCCAAAGGTGAT
+ATTTTCATGATAACATCCTGTGATTGCTTTGTTCTTCGTCTTTTATGTTCTTCCTAGATG
+GGCTCAGAACATACAAGAATTAAGTACACATCTTATTTTCCAGTGATAATGCTACCGGCA
+AATTCTGTTGTTTGTATAAACATCAGCCATGTTTATATAACTAAACTAGTGTTTTGTTTT
+GTCAATTCAGCAAGAAATTAGACCAAATGGTGGCTTAATGCTGCATTGATTTGGCTATCA
+ATTTGTTTTCACTTTTCTGCAAAATAATTAATACATTATTAAATTGAATTGTGCTGATGC
+CACAGTTGTTCTTATCTCAAGTGTCTTAAAATTCATTTAATTTGTTTTTCCTTTGGTTTC
+ATTATTCAAATTTTAACTTCAGTTCTCAAGATTTTATCTGATGGAAGAGATGGAGTCCAT
+TACTAAGGACTCCATTGTGCTCCATCATGCCAGAGTTGTAAAATAGATCTTTTAAAGGAA
+ATTTACTGTGATTTTTTTTCTATTTAAGAGCTTCCTCTCCAGTTGAGCATGTAAGAAAAT
+TATACCAGGAGAATACAGTAAACTCTATGAGGCAAGCTATAAACATGTAGCATTGTGATT
+AGGGctggttctccttctagagacatggtaggattgcaatttcataccatccttgaagtt
+agagagagccacgtgactcatttagccaatgaactgtgagcagaatgacatgtcacttcc
+agctgaagctttaaCAATCTGAGAGACATTCATACATTTTCCATGTGCTGTAGCCTTATA
+CCCAAAGCCTGGGTCCCAAGTGACCATGACAGGCAGAGCTCCCTGttgagccacagagat
+ttagagaatggctgttaacacagcataatccagcccatcctgactaatCTGATATTAACA
+TGTATAATAAAGAATTCTATCAATGCTGAGGGAAGATGACTAGTTAAGGTCCTAGGTTGC
+AAGTCTCAAAACCTCTTCTAAGGATTGTAGACAGGAAATTAAATGACTTCTAGTCCCTAG
+AGTTCCCAATCTCCTACCATCCCATCCTAATATGACAGAAGTAATTCCTGAGTTGCTTCT
+GAAACCAGAGCTTCCCTCAGAACCCTTAGCCTGCCAGATGGCTTCTTGGAGAGCCCTCAC
+TCACTTTTCTCCTTCTGCTATTGCTGCTCATTCATTCCAGTTTTTAAAAATTCATCTTTA
+TCCAGGAACCTCGCTTCTAGAAAAGTCATACAGGTGCTTCCAGGAGGCTACATGGGCACC
+CATATTTTTCTAGCCACTTTCATTAGACCAATGCAGCAGAGAAGAAAAGCCTCAATAATT
+ATTATGACATGGCATGTTAGGATACCAAGTAAATTGCATTTGTAAAATGTGATTTTCTGT
+TGGTGTTCACTTCAGCTCTACTGACATTTGGTAAGTATTATTGACTGACTGACTAACTAA
+TGTGGTCATTAGTCTTCATAAAGAAAGGCTCTCTACAAAAACGGAGGGATGCCCTTTTTC
+TGGCATTTAATACGTAAGAAATTGCCTCCAATAGAAACCAGAGTTGCCTGATTACTATCA
+GCACAGGAGAAATGTATTAATGTGCCTTTCTAGTAACAGGTTTTTAGAAAGTCAAATATA
+AACAAATCTGTCTATTTGTGTGTGTGCATGTGGTAGTGGGGAGGGAAGAAAAAAGGAGGG
+GGAGAGAAAGAGAAATAAGAACCAAGTTTATTATACTGTATTCAGGGGGAAAAAATTTTC
+CCAAGGTCCTAACAGAAGAGCAAAGTGCCACTGTCAATAGCCTCAGTAGTGTTAGGGTTG
+CTtttatttatttatttatttatttatttatttatttatttatttttccttttttttctt
+tctctttttttcttcttttttttttcttttctttcttttttttttttttttttttttttg
+gacagagtctcacactgtcacctgggctggagtgcattggtgcaatctcgactcactgca
+acttctgcctcccaggttcaagtgattctcctgcctcagccgcccaagtagctgggatta
+caggtgtctgccaccgtgcctagctaatttttttgtatttttagtagagatgaggtttca
+ctatgttggccaggctggtctcaaactcctgacctcatgatccacccacgttggcctccc
+aaagtgctgggattacaggcgtgagccaccgcccctggccAGGATTGCTTTTACAGCCAG
+TCTTCAGGTGCCCACTGTAGGAACAATGTCATTTAACCCTCGGGATTATTCTGTGCCAAA
+TATGGATAATGACTAATATCCAACACAGATATTCTCAGCTCAGAAGAGCAATTAGCAAAT
+TCATAAATTAAGTGCTTGCTTCCTCTTTAGTCAAATACAAACGTTTGTTAAAAGATATTA
+TTTTGCTTTACACTTTTTCTCTCAGAAATAAGCAGATGCTTGAATTCCCACAGTGCTGCT
+TGAGCCTCACACCATGTCATCCTGCCAGGCACCCAGATCCAGTTCTAGAGTTTCACATGA
+TCGTGAgtgttggttaataagtcaatgtgaactgggaggggagatttttcaggagtgcca
+cagggctctccctttaatcACATACACTCCCTGCTTTCATTGGAAAGTGTATAATGATGT
+CAGAGTGCCCCAGAATGGAGCTAGTTGGAAGACTGCCGTCATAGGGATGCCTTAGTGAAT
+TAATAAGGTTTTAATTTCTGGCTCTCAACTTTGTAGATGTAAAAGTTGATTTATCAATAT
+GTGAGAAAGGATGAATCTTTCTGAAGGTTATGTCATCACACTCACTAAGCACACAGAGAA
+TAATGTCTAGAATCTGAGTGCCATGTTATCAAATTGTACTGAGACTCTTGCAGTCACACA
+GGCTGACATGTAAGCATCGCCATGCCTAGTACAGACTCTCCCTGCAGATGAAATTATATG
+GGATGCTAAATTATAATGAGAACAATGTTTGGTGAGCCAAAACTACAACAAGGGAAGCTA
+ATTGGATGAATTTATAAAAATATGCCTCAGCCAAAATAGCTTAATTCACTCTCCCTTATC
+ATAAGGATAATCTTGCCTAAAGGGACAGTAATATTAAAGACACTAGGAATAACCTCTGTA
+CTTTGGACAGTAGACCTGCATAGCCCATTAGGCCTCAATGAAGTCTTATGCAAGACCAGA
+AGCCAATTTGCCATTTAAGGTGATTCTCCATGTTTCTGCTCTAACTGTGCTTCACAATAC
+TCAAAACACTAAATCAGGATGTTTCCTGGAGTTCAGGGAGCTGTCCGTGTTACTGAGCAG
+TTCTCAGCAACACAAAGATCCTACTGACTCCTCATCAGACTTCTTTCTCACTGGAATTTT
+ACACCTGGGCTGTTAACACCAGGCCAGGTCAAATTCAAAGGAGAGAAAAAAGCTCATTAT
+GAAGGGTAAAATCCAAAACACTGTGCATAAAGATATGGCACAATTTTTATACATAAAGAT
+TTCATAAAACCAAAGCATCAGGAAATGAAAAGAGATACAGAAAGAAAAATGATGGTAAAT
+GAGACATTAATTTACCCTTCTAATCTCTATCACAGCAAAAAGATAATTAAAAAATCTATA
+TGAGGACCACAAAATACACAAAAATTATGTAGCAAAGCCTATAGCCTGAAAAAGTAAACA
+TTGAAATTTGTATGTCCATAAAATGTTTACAAAATTCAGTACATATTACACACCCCACCC
+TAAAAACATCTAAGCAAAGTAGAGAATGTAGAAATGCTACAGATTATATTCTCTGATTAT
+GACACAACAAAACTAGAAATTACAGCATGGAAATTTAAAAGCTTTCTCTTAAATAATTCT
+ATGTCAAAAAGAAATCCAggccgggtacagtggctcatgcctgtaattccagtactttgg
+gaggccaaggtgggcaggtcacttgaggtcagcagttcaagaccagcctcgtcaacatgg
+taacaccctgtctctactaaaaatacaaaaattagctgggcctggtggctcatgcctgta
+atcccagctacttaggaggctgaggcaggagaattccttgaacccagaaggtggaggttg
+cagtgagctgagattgcaccactgcactccagcctaggtgacacagcaagactctgtcaa
+aaaaaaaaaaagaaaTCCAAATAAAATTTCCAGAATATGTGGAAAATAGTGACAATAAAA
+ATATTAcacatgtgtaatcccagcattttgagatgccaaggtggcaggatcacttgagac
+caggagttcgcaaccagcctggacaacatagggagactccatctccacacacgccaaaaa
+aaattttaaatagccaggtatagtggtacttcctgtaatcccatctacttgggaggctaa
+ggtgggagaatcacccaacctcaggagttcagggcttcagcaagccatgatcatatcact
+gcactccagcctcagcaacagagcaagatcctatctcaaaaaaaaaaaaaaaaTCACATG
+TGGGAAATAGCTATAGCACAAtaaaaataaatgtattaagtatgaacaacaaaaaagcta
+gtaaaggttgaacaacaactatccttaggaaagtggaaataatgtattaataaatatgaa
+agcaggctagccacggtgactcacatctgtaatcccagcactttgggaggctgaggcagg
+cagatcacctgaggtcaggagttccagaccagcctggccaacatggtgaaatcttgtctc
+tcctacaaatacaaaaactagccaggcttggttgtgcactcctgtaattcgagctacttg
+ggaggctgaggcaggagaatctcttgaacctgagaggcagaggttgcagtgagccaagat
+catgccactgcactccagctggggcaacagagtgacactccatctcaaaataaataaata
+agaaagcagaaactaataaactagaaaacagaaacatagaactaatttataaatcaaagc
+actatgccttgaaaagaGGGAGAAAAATTGTGAATTAAGGAAGGGAAGAGATGGTTGGAG
+AGGAGGTGGGAGAAGGCAGAGATAATTGAAGGAGCAAAAGCATCTGGAGAAGCAAAGCCA
+CTGAAAGATGAACAGGGCTCTGAAAGAGATGCTTGACTGCTATCTTTTCAAATGACTGCA
+GTTCCCAGTGACATCATTTTTCTCCTCCCTGGAAGTCTGAGGGGCAGTTCACTTATCTCC
+TCCCCTCCCCTACTCCTCACCCCACACTCAAAACCTGTCTATGCTCCTTTCATTCTCATA
+TGACAGATTTCAGATGGCATTCTTATTTCCCTGATTTCTTTTTGAGATAGCTTGCATTTC
+CCTCCTCTATataaagccaccgtttatcaaatgcctacatggaccaagcagtccacaagg
+gcttcacagacagttttactaaactcatgccaaaactttcaggttttatacctaccttat
+agataaagaaattgaagcttatagagtttaagtaatgttcccaaagcctcgtggctagta
+attcaaacctaatttctgcctactccaaagtctatttttccttatgatactctactgcct
+ctcCAtggataaagacagagatcacatattaataaaatttgcacaaagtcggcaaattgt
+tgaaagggaaggctaagatgattaataaaatcaagagccagatgatctcaacaacctgaa
+ataactggctgacaaccaatttgaataactccctgcgggtgaagttcaaagtactatttg
+ggtttttttttaaagtttggctgggtgcagcggctcacgcctgtaatccaagcacttagg
+gaagccaaggtgggcagatcatgaagtcaggagttgaagaccagcccggtcaacatggtg
+aaaccccatctctactaaaaataaaaaattagccgggcctgctggtggatgcctgtagtc
+ccagctactcgggaggctaaggcaggagaatcgcttgaacccaggaggtggaggttgcag
+ggagccgagatcgcaccactgcactccagcctgggcgacagagcgagattccgtctcaaa
+aagtaaaataaaataaaataaaaAATAAAAgtttgatatattcagaatcagggaggtctg
+ttgggtgcagttcatttgaaaaattcctcagcattttagtGATCTGTATGGTCCCTCtat
+ctgtcagggtcctagcaggaaattgttgcactctcaaaggattaagcagaaagagtttaa
+tgaagggtctctttccagggttaagggaactgctagggtttggatatttgaccactccaa
+actcatgttgaaatgtgatccccattgttggaggtggggcctaatgggaggtgttttggt
+cctgagtgtggacctctcacgaatgtcttggtgccatccaagtgagttcttgctcgctct
+tttttttctttttgagatgtagtttcactcttgctgcccaggttggaatgtagtggtgcg
+atcttggctcactgcaacatccacctcacgggttcaacccattctcctgtgtcagcctcc
+agagtagctaggattacaggtgcccaccactatgcccagctaatttttggtatttttagt
+agagacggggtttcaccatgttggccaggctggtctcaaactcctgacctcaggtgatac
+acctgcctcggcctcccaaagtgctgggattacaggtgtgagccaccatgcctacctagt
+tctagctctcttaattcccacaagagctggttgttaacaagagcctggcacaaacccctc
+tctctcgccacgtgatctctgcacatgccagcttcccttccccttctgccatgagtggaa
+acagcctaacgccctcaccagaagcaaatggtggcaccatgcttcttgcacaccttcaga
+actgtgagccaaataaacctctcttctttaaaattattcagcctctggtattcctttata
+acaacacacacacacacacacacacacatacacacacacgcaaaagcagactaaaacagg
+aactaattagaaatggtgatgcaccgagggattggcaCCGAGGCTCCCCAACAGGAACTG
+AGGTCATGGATAGAAGGACACATTCATGTTATTTTTTTCTAATGGTTAAGTAATTATTTG
+ctcttactctcaaaatttctgccaaggcctcccatggaccaaactcaactagaatctagg
+aagcagagaacctgagtgttgcattcagcagaagtcagcttcctagggaatcttgcagga
+agggtgaaggtagagaatctggtggggaagcaagcaaatgcccatcacaTGCACTTTCCT
+ccaacagagcgactcagatgctataaaacttgctaacacagtctcagggtctgatcacag
+taacatacaatccaggttttaatcatcagaaatcacagtcctattgtcttctgcacagac
+ccaaacacacttggaggtcatgttcaatatgaatacctcacagagaaggaaatttacacg
+cgagaagtacatctgcagaaagccagctggcatgtcaaccattcaaaaactcagggtgtt
+ctggataaagaagactcaggaagacaagtatgaagcataatctgtgacattccatgcggc
+agacattagacacatacaagagagttgttggaaagcggaatttatcttcatataaacaac
+actgagctaaatctcaatatttcagatctctagaactatccatcagtgaaatggattgca
+aatacaaagagtaataccatgtcacttaagaatagaatcatggacgaggctgccacctgc
+tgttgggggccactgcagaagaaattccagaacactggactggagagcacctcactttcc
+ttacagctctaagtttctgACTCAGTGACCTGATTCACTACCATATACACAAAGACCCAC
+TTACACAAATGACTGTTCTTCACACTAGGCCCATGGAGACAGGGATAAAATTCTGAATTT
+GCTCAGATACCTTCTCCGCTACTGACATCTAGGCATTACACAATTCATCTCTTCATATTT
+AACCTTTGAAGTTTGCTACTTCTCAGAGAGACTAATGAGTAGTGAGCAAATATCCTGAAG
+CTGAGAATGCTTCTACCTCCTCTCAAAACAACGGAATATTCATCAAAACACAGCAGTTCT
+GCACTTAACTTTAGGCCTTTTCTAACACCTTGTTTCTTGGCAGTAACTGTGGCCAGAATA
+GCTCTTTCCACAGATAAAGGACCTTTTGAAAGGATAGGGTCTCTAGATAGAAAAGCAAAT
+GCCTCATTCCAGAAGGTCTTCAAGAAGAAAATGTTGTGGTGATAACAAACATAACTGATT
+ATAATCTATTCTGTGAAAAAAGCTTATGAAACAGTAGATGTGTGTATCTAGTACATAAGA
+GCTGAATGTCAATATATATATAGATATATACacacactcaaataaataatagttatctct
+aactagagaaattctagttgccttatattttcttctttttccttactatattttctacaa
+taaacatgtgtttttaacaagaaaaGTCTTTTCTGGTGTGCTTTTTAATTTTCTTTGTTT
+AAGTGAGAGTGAGGCTACATAACTACATGGCTAGGTAGACTTTTAGAAAACTTGGCTGCT
+CTAGAAAATTGACATATCCTGATTTCTTCCATAGCTTGGATCTTGACCTAGAGGGAAATA
+TAAAAGTGTTGACTTGAACCTGAGGGGTGCCATTTTCACTGCTGAAGTAGTTTCATGGAT
+CATGAATTGGAGAAATGACTTCAGCAACATGGGTGTTAAAATCAGAAAGCACAAGTGACC
+CACAACAGATGATGGAGAACAAAGAGCAAGCTGGGAAAGCAGTGGCCTTTAATACAGAAA
+AGAAGAAGTATAGCCACAATAAATATTAGGCAGACAGCAGTTCAGCAGTTTATACTATTA
+AGCTGTTGTTTAGGGGAATAGTAAACTGACATGACCCTTGAGGTAGGTATATATAGGTAA
+ATTCTATGTGTCCCTTGAAATAGGTGTATGACACAACTTCTGGCATCTACATGGATTTGG
+TCACTCTAAAGTAGCCATGAGGCTTAAGATAGTTCAGCTGTTTGGGGATAAGTTAAATCA
+TTTGCCATTGTCTTTCTGCAATTTGCATATCCTACAGTTATCATTGCCATTACTGAATGG
+CACAGAGAAAAATTCTGGTCTAAAGTGGTTCTCAAACCTGGTtgctggagggccaccctc
+agtgatgatgatttaatctgtagaagaatagaacattgatagtttttatatatctccagg
+taattttaatatataactggggtgagaatcattgACATAATTGTAACAGGATAATATTCA
+GGAAATATGGAGATAAATAATTTTCTTCTCGACATTAAAAAAATCTAATAAAAAGTTTTA
+TGTTTTCCCCTAACTCAGGGTCATCAGCCTTCAAGCTTCAGTCTCTGTGTGTTCACAGGT
+GCTGTAAACACACGCATCACTACTAATATCCCACTTCAGTGCTATTGCTGCTCCCAAAAC
+TCCAGGTATTTTTAACCTTATAAACCTCCAGAATAATGAGACCACTGGGTTCAGTAAATT
+GCTTTGTTTTGAAGCACTATTAGACAAAGTGGGAGACTAGAAGATAAATCTGTCAATGAC
+ATGTCCTTTAAGACTACTTAGATTTTGTTGAATTTGTGGATCATTCCTTACTTGAGCAAA
+TGGTAAATTAACTCTCTCTTTTCTCTCTCTCTCTAGCTGGCACACTTTTTCCAGTAGCCA
+TTCTACTTGGTATGCTTACTTATCAGCTGTCCTCCAGGGGCCTCACATTAGATGTTTCTC
+TGACTAACCAAACATGACACACAGCTGAAGTCAGAAAAACCAGATTGATAATTTCACTCA
+AACTATTTTCCTTCATTCTAACAATTTACTGGAGTACACAATTGTGACTATTTTTAGCCA
+TAGGAACTCATAGAAAGACCAACTTCATTAGACCTACAAAATCGAATTGTGTAACAGTAT
+ATGCAGTATGTGTAGGAATAAAAAGCATTTCTCAAATATGCAGTACTGGATTTTGCAAAA
+GCACCTTACACTTAGCTATAAAGGAGTGGAAAACACAAAGATGAGTAACTGCACTTTTCA
+AAAGACTAGAGCTATACCAATAATACAAAGGTGTAAACAAATAATGATGAGATGACAAAG
+GCTGAGTGTTTTCTATTTGGAAGCTATGTTGTTGAGTTATTTATGTATATAATTTCATGC
+AATCTTCATGTTATGGGGATGTTctaatccactgtgactctgtccttaaataaaagggag
+atttggacatagagagaggcacacggggaggatgccatatgagaattgacactgtgctgt
+cacaagccaaggaactactggaaggagagaaagaggactggaacagttccttccttagca
+ccttttcaggcagcctagccctgccagcttcttgatctggacttctcacctctagaattg
+tgaggcaataaatctctgttgcttaagttacccagtttgtggtaccttattacaggagcc
+ctaggaaaataattcaTTATataatctgctaaggtagatatgatcattgtctccaatttc
+catatgaagaaactatgcctcaggcattgtgtcagttgtccaaaatcatacattcctgac
+tcacttcaatgaattcttcattcagcaaaatttttaaggtaccttaaaaaaattatgtta
+actcttagggccttgctttaaagcttcaatgggcttttcctttgcaaagaataaaatcct
+aatacttaagcatagctctctttcctggctatgtttctgacatcctcttgtaccatgctc
+ctccttaatcattctgaggttacatcttaagtcctttccccttgccattcccacttcttg
+gaatactttcccatcaactcttcaaagaactgccttctttaagtatttggtctcagttcc
+aatgtcacttccctgtaaaagcttcctggccatcaagccttctttacacactctatttta
+ttttttcatggttcctataacaacctaatatattctcaattgattaactgttttgctgaa
+tactgccttccataagaatggaaagaaaacatggccaggtgcagtggctcacacctgtaa
+tcccaccacttcaggaggctgaggcaacatggcaaaaccttctcttcaaaaaatttttta
+aaagttagctggatgttgtggaggcaagaggatcacttgaggatcacttgagtccatgag
+gtcaaggctgcagtgagtcatgtttgcaccactgcactctagcctaggtgacagagctag
+tcactatcaaaaaaaaaaaaaaaagaatggagagaatgctacatgagagaaaggatctta
+tctatcatgttcacctcccaagaggtgaacatatcccccaaagcctgatagagagaagat
+gctcattaatatttaatgcatgaCCATGTGCAGACTTGGGAGGAAAAATATGCCTCAGCC
+TATCAATATTGGATCCTTAATAAACAAGGATGTTTCTGCATCATTTCCCCACAACACCGA
+ACAAGTGTGGCTCACTGTGGATGTTTAAGCAAATGCATTGTTTTTCCAGTTATATATCTG
+GTAGAGATGAGGCCATTGATAGGAATGGGAAGACGATCTCCTTTTATTTTGATGACCCAG
+CATGGCTGAACACTCAGTGACTACCACTGCACTTTGTTGTACTTTCAGCATTAGAGATGC
+CAGCCCTGTAGGATATAAAACAGGAACATCTAGTCCTCAATTATATTCAGAATTACTCAA
+GTCTTAGAAGCACCACTTGTCTTTTTTCAAGGGAGAGAAATGCTCAAGTGATGGGCTGAA
+GTGAAGGGAGGGAGTCACTCACTTGAACGGTTCCCTTAGGCTGTGTGGATGCAAACAGCA
+TTAGACAATGACACTGACAGTGGGAAATGCACTGGAGACGATGACTGGCAAAGCCCTCCT
+TTTCTCCCCATCCACTATAGATACTGACAGCAAAGGGTTTGTCACAATGACAACTATACA
+CTCCCAATATCACAGAAGAAGGAGGAATAAAAGGGTATATTATGAGTGACTGAAGTTTAG
+AATAAATTAATAAATATTATGTCCCTCATCCATAGAAACCACAAAGGTCTAGTAAGGCTA
+AGGATATAACAAGAAAATAATATGAATATTTGCTTCCCCTTCCTAGTGTAATAGAGTAAG
+TTACAAATGGCTTCAGGAAGGGGAGAGAGGAAGAAGAGTGGATGAGATACGTAAGAGTGC
+TTGAGGGCTAATTTTATGAAAGCTTTGGGAAGTTTTAAGAAAAAGAAAAGCTATTTTTCA
+AGGTACAtgtgtgtatgcgtgtgtgtgtgtgtgtgtgtgtgtgtgtgtgtgtgtgtgAAA
+GACAGAAGAAAGAGGGAGACCTTAGAAGACTATGAGACACTAAGAGAAAAATTAAGGTAA
+AAAAGACACACACTTAGAAAAACACACATAGGGAGGAGGGAGGAGGTTAAGACATTTTAC
+TATGTGCTGTGAATGGAAACTACAAACCATTTTTGATatatgcaatatatatacatatat
+acacacatatacatatGTATTTAAATATTTAAATTACAttttctctttttttagagatat
+ggtttcactatgtcactctgcccaggctgcagtacagtggttgttcacagtcatgatcat
+agcacattatagccttgaactcctgggctcaagcaaccctcctgtattagtctccccagt
+agttgggattactagcatatgccaccatgtccACCTTTATGCTTTTTAAAGTGAAAAACC
+ATACTAAGAATGAGGCAGCTCAACTTAATAATAAAAACATTTCAAATGtaaagaaattta
+caaaagaaaaacaatcaaccccattaaaattgggcaaagg
+>chr2
+AAAAAAA
+AAAAAAA
+DDDDDDD
+CCCCCCC
+D
+
diff --git a/public/gatk-engine/src/test/resources/exampleFASTA-windows.fasta b/public/gatk-engine/src/test/resources/exampleFASTA-windows.fasta
new file mode 100644
index 0000000..92e642f
--- /dev/null
+++ b/public/gatk-engine/src/test/resources/exampleFASTA-windows.fasta
@@ -0,0 +1,7 @@
+>chr2
+AAAAAAA
+AAAAAAA
+DDDDDDD
+CCCCCCC
+D
+
diff --git a/public/gatk-engine/src/test/resources/exampleFASTA.dict b/public/gatk-engine/src/test/resources/exampleFASTA.dict
new file mode 100644
index 0000000..3887c5e
--- /dev/null
+++ b/public/gatk-engine/src/test/resources/exampleFASTA.dict
@@ -0,0 +1,2 @@
+ at HD	VN:1.0	SO:unsorted
+ at SQ	SN:chr1	LN:100000	UR:file:/humgen/gsa-scr1/hanna/src/StingWorking/exampleFASTA.fasta	M5:b52f0a0422e9544b50ac1f9d2775dc23
diff --git a/public/gatk-engine/src/test/resources/exampleFASTA.fasta b/public/gatk-engine/src/test/resources/exampleFASTA.fasta
new file mode 100644
index 0000000..2f5d1dc
--- /dev/null
+++ b/public/gatk-engine/src/test/resources/exampleFASTA.fasta
@@ -0,0 +1,1668 @@
+>chr1
+taaccctaaccctaaccctaaccctaaccctaaccctaaccctaaccctaaccctaaccc
+taaccctaaccctaaccctaaccctaaccctaaccctaaccctaacccaaccctaaccct
+aaccctaaccctaaccctaaccctaacccctaaccctaaccctaaccctaaccctaacct
+aaccctaaccctaaccctaaccctaaccctaaccctaaccctaaccctaacccctaaccc
+taaccctaaaccctaaaccctaaccctaaccctaaccctaaccctaaccccaaccccaac
+cccaaccccaaccccaaccccaaccctaacccctaaccctaaccctaaccctaccctaac
+cctaaccctaaccctaaccctaaccctaacccctaacccctaaccctaaccctaacccta
+accctaaccctaaccctaacccctaaccctaaccctaaccctaaccctcgcggtaccctc
+agccggcccgcccgcccgggtctgacctgaggagaactgtgctccgccttcagagtacca
+ccgaaatctgtgcagaggacaacgcagctccgccctcgcggtgctctccgggtctgtgct
+gaggagaacgcaactccgccggcgcaggcgcagagaggcgcgccgcgccggcgcaggcgc
+agacacatgctagcgcgtcggggtggaggcgtggcgcaggcgcagagaggcgcgccgcgc
+cggcgcaggcgcagagacacatgctaccgcgtccaggggtggaggcgtggcgcaggcgca
+gagaggcgcaccgcgccggcgcaggcgcagagacacatgctagcgcgtccaggggtggag
+gcgtggcgcaggcgcagagacgcaagcctacgggcgggggttgggggggcgtgtgttgca
+ggagcaaagtcgcacggcgccgggctggggcggggggagggtggcgccgtgcacgcgcag
+aaactcacgtcacggtggcgcggcgcagagacgggtagaacctcagtaatccgaaaagcc
+gggatcgaccgccccttgcttgcagccgggcactacaggacccgcttgctcacggtgctg
+tgccagggcgccccctgctggcgactagggcaactgcagggctctcttgcttagagtggt
+ggccagcgccccctgctggcgccggggcactgcagggccctcttgcttactgtatagtgg
+tggcacgccgcctgctggcagctagggacattgcagggtcctcttgctcaaggtgtagtg
+gcagcacgcccacctgctggcagctggggacactgccgggccctcttgctCCAACAGTAC
+TGGCGGATTATAGGGAAACACCCGGAGcatatgctgtttggtctcagtagactcctaaat
+atgggattcctgggtttaaaagtaaaaaataaatatgtttaatttgtgaactgattacca
+tcagaattgtactgttctgtatcccaccagcaatgtctaggaatgcctgtttctccacaa
+agtgtttacttttggatttttgccagtctaacaggtgaAGccctggagattcttattagt
+gatttgggctggggcctggccatgtgtatttttttaaatttccactgatgattttgctgc
+atggccggtgttgagaatgactgCGCAAATTTGCCGGATTTCCTTTGCTGTTCCTGCATG
+TAGTTTAAACGAGATTGCCAGCACCGGGTATCATTCACCATTTTTCTTTTCGTTAACTTG
+CCGTCAGCCTTTTCTTTGACCTCTTCTTTCTGTTCATGTGTATTTGCTGTCTCTTAGCCC
+AGACTTCCCGTGTCCTTTCCACCGGGCCTTTGAGAGGTCACAGGGTCTTGATGCTGTGGT
+CTTCATCTGCAGGTGTCTGACTTCCAGCAACTGCTGGCCTGTGCCAGGGTGCAAGCTGAG
+CACTGGAGTGGAGTTTTCCTGTGGAGAGGAGCCATGCCTAGAGTGGGATGGGCCATTGTT
+CATCTTCTGGCCCCTGTTGTCTGCATGTAACTTAATACCACAACCAGGCATAGGGGAAAG
+ATTGGAGGAAAGATGAGTGAGAGCATCAACTTCTCTCACAACCTAGGCCAGTAAGTAGTG
+CTTGTGCTCATCTCCTTGGCTGTGATACGTGGCCGGCCCTCGCTCCAGCAGCTGGACCCC
+TACCTGCCGTCTGCTGCCATCGGAGCCCAAAGCCGGGCTGTGACTGCTCAGACCAGCCGG
+CTGGAGGGAGGGGCTCAGCAGGTCTGGCTTTGGCCCTGGGAGAGCAGGTGGAAGATCAGG
+CAGGCCATCGCTGCCACAGAACCCAGTGGATTGGCCTAGGTGGGATCTCTGAGCTCAACA
+AGCCCTCTCTGGGTGGTAGGTGCAGAGACGGGAGGGGCAGAGCCGCAGGCACAGCCAAGA
+GGGCTGAAGAAATGGTAGAACGGAGCAGCTGGTGATGTGTGGGCCCACCGGCCCCAGGCT
+CCTGTCTCCCCCCAGGTGTGTGGTGATGCCAGGCATGCCCTTCCCCAGCATCAGGTCTCC
+AGAGCTGCAGAAGACGACGGCCGACTTGGATCACACTCTTGTGAGTGTCCCCAGTGTTGC
+AGAGGTGAGAGGAGAGTAGACAGTGAGTGGGAGTGGCGTCGCCCCTAGGGCTCTACGGGG
+CCGGCGTCTCCTGTCTCCTGGAGAGGCTTCGATGCCCCTCCACACCCTCTTGATCTTCCC
+TGTGATGTCATCTGGAGCCCTGCTGCTTGCGGTGGCCTATAAAGCCTCCTAGTCTGGCTC
+CAAGGCCTGGCAGAGTCTTTCCCAGGGAAAGCTACAAGCAGCAAACAGTCTGCATGGGTC
+ATCCCCTTCACTCCCAGCTCAGAGCCCAGGCCAGGGGCCCCCAAGAAAGGCTCTGGTGGA
+GAACCTGTGCATGAAGGCTGTCAACCAGTCCATAGGCAAGCCTGGCTGCCTCCAGCTGGG
+TCGACAGACAGGGGCTGGAGAAGGGGAGAAGAGGAAAGTGAGGTTGCCTGCCCTGTCTCC
+TACCTGAGGCTGAGGAAGGAGAAGGGGATGCACTGTTGGGGAGGCAGCTGTAACTCAAAG
+CCTTAGCCTCTGTTCCCACGAAGGCAGGGCCATCAGGCACCAAAGGGATTCTGCCAGCAT
+AGTGCTCCTGGACCAGTGATACACCCGGCACCCTGTCCTGGACACGCTGTTGGCCTGGAT
+CTGAGCCCTGGTGGAGGTCAAAGCCACCTTTGGTTCTGCCATTGCTGCTGTGTGGAAGTT
+CACTCCTGCCTTTTCCTTTCCCTAGAGCCTCCACCACCCCGAGATCACATTTCTCACTGC
+CTTTTGTCTGCCCAGTTTCACCAGAAGTAGGCCTCTTCCTGACAGGCAGCTGCACCACTG
+CCTGGCGCTGTGCCCTTCCTTTGCTCTGCCCGCTGGAGACGGTGTTTGTCATGGGCCTGG
+TCTGCAGGGATCCTGCTACAAAGGTGAAACCCAGGAGAGTGTGGAGTCCAGAGTGTTGCC
+AGGACCCAGGCACAGGCATTAGTGCCCGTTGGAGAAAACAGGGGAATCCCGAAGAAATGG
+TGGGTCCTGGCCATCCGTGAGATCTTCCCAGGGCAGCTCCCCTCTGTGGAATCCAATCTG
+TCTTCCATCCTGCGTGGCCGAGGGCCAGGCTTCTCACTGGGCCTCTGCAGGAGGCTGCCA
+TTTGTCCTGCCCACCTTCTTAGAAGCGAGACGGAGCAGACCCATCTGCTACTGCCCTTTC
+TATAATAACTAAAGTTAGCTGCCCTGGACTATTCACCCCCTAGTCTCAATTTAAGAAGAT
+CCCCATGGCCACAGGGCCCCTGCCTGGGGGCTTGTCACCTCCCCCACCTTCTTCCTGAGT
+CATTCCTGCAGCCTTGCTCCCTAACCTGCCCCACAGCCTTGCCTGGATTTCTATCTCCCT
+GGCTTGGTGCCAGTTCCTCCAAGTCGATGGCACCTCCCTCCCTCTCAACCACTTGAGCAA
+ACTCCAAGACATCTTCTACCCCAACACCAGCAATTGTGCCAAGGGCCATTAGGCTCTCAG
+CATGACTATTTTTAGAGACCCCGTGTCTGTCACTGAAACCTTTTTTGTGGGAGACTATTC
+CTCCCATCTGCAACAGCTGCCCCTGCTGACTGCCCTTCTCTCCTCCCTCTCATCCCAGAG
+AAACAGGTCAGCTGGGAGCTTCTGCCCCCACTGCCTAGGGACCAACAGGGGCAGGAGGCA
+GTCACTGACCCCGAGACGTTTGCATCCTGCACAGCTAGAGATCCTTTATTAAAAGCACAC
+TGTTGGTTTCTGCTCAGTTCTTTATTGATTGGTGTGCCGTTTTCTCTGGAAGCCTCTTAA
+GAACACAGTGGCGCAGGCTGGGTGGAGCCGTCCCCCCATGGAGCACAGGCAGACAGAAGT
+CCCCGCCCCAGCTGTGTGGCCTCAAGCCAGCCTTCCGCTCCTTGAAGCTGGTCTCCACAC
+AGTGCTGGTTCCGTCACCCCCTCCCAAGGAAGTAGGTCTGAGCAGCTTGTCCTGGCTGTG
+TCCATGTCAGAGCAACGGCCCAAGTCTGGGTCTGGGGGGGAAGGTGTCATGGAGCCCCCT
+ACGATTCCCAGTCGTCCTCGTCCTCCTCTGCCTGTGGCTGCTGCGGTGGCGGCAGAGGAG
+GGATGGAGTCTGACACGCGGGCAAAGGCTCCTCCGGGCCCCTCACCAGCCCCAGGTCCTT
+TCCCAGAGATGCCTGGAGGGAAAAGGCTGAGTGAGGGTGGTTGGTGGGAAACCCTGGTTC
+CCCCAGCCCCCGGAGACTTAAATACAGGAAGAAAAAGGCAGGACAGAATTACAAGGTGCT
+GGCCCAGGGCGGGCAGCGGCCCTGCCTCCTACCCTTGCGCCTCATGACCAGCTTGTTGAA
+GAGATCCGACATCAAGTGCCCACCTTGGCTCGTGGCTCTCACTGCAACGGGAAAGCCACA
+GACTGGGGTGAAGAGTTCAGTCACATGCGACCGGTGACTCCCTGTCCCCACCCCCATGAC
+ACTCCCCAGCCCTCCAAGGCCACTGTGTTTCCCAGTTAGCTCAGAGCCTCAGTCGATCCC
+TGACCCAGCACCGGGCACTGATGAGACAGCGGCTGTTTGAGGAGCCACCTCCCAGCCACC
+TCGGGGCCAGGGCCAGGGTGTGCAGCAccactgtacaatggggaaactggcccagagagg
+tgaggcagcttgcctggggtcacagagcaaggcaaaagcagcgctgggtacaagctcaAA
+ACCATAGTGCCCAGGGCACTGCCGCTGCAGGCGCAGGCATCGCATCACACCAGTGTCTGC
+GTTCACAGCAGGCATCATCAGTAGCCTCCAGAGGCCTCAGGTCCAGTCTCTAAAAATATC
+TCAGGAGGCTGCAGTGGCTGACCATTGCCTTGGACCGCTCTTGGCAGTCGAAGAAGATTC
+TCCTGTCAGTTTGAGCTGGGTGAGCTTAGAGAGGAAAGCTCCACTATGGCTCCCAAACCA
+GGAAGGAGCCATAGCCCAGGCAGGAGGGCTGAGGACCTCTGGTGGCGGCCCAGGGCTTCC
+AGCATGTGCCCTAGGGGAAGCAGGGGCCAGCTGGCAAGAGCAGGGGGTGGGCAGAAAGCA
+CCCGGTGGACTCAGGGCTGGAGGGGAGGAGGCGATCTTGCCCAAGGCCCTCCGACTGCAA
+GCTCCAGGGCCCGCTCACCTTGCTCCTGCTCCTTCTGCTGCTGCTTCTCCAGCTTTCGCT
+CCTTCATGCTGCGCAGCTTGGCCTTGCCGATGCCCCCAGCTTGGCGGATGGACTCTAGCA
+GAGTGGCCAGCCACCGGAGGGGTCAACCACTTCCCTGGGAGCTCCCTGGACTGGAGCCGG
+GAGGTGGGGAACAGGGCAAGGAGGAAAGGCTGCTCAGGCAGGGCTGGGGAAGCTTACTGT
+GTCCAAGAGCCTGCTGGGAGGGAAGTCACCTCCCCTCAAACGAGGAGCCCTGCGCTGGGG
+AGGCCGGACCTTTGGAGACTGTGTGTGGGGGCCTGGGCACTGACTTCTGCAACCACCTGA
+GCGCGGGCATCCTGTGTGCAGATACTCCCTGCTTCCTCTCTAGCCCCCACCCTGCAGAGC
+TGGACCCCTGAGCTAGCCATGCTCTGACAGTCTCAGTTGCACACACGAGCCAGCAGAGGG
+GTTTTGTGCCACTTCTGGATGCTAGGGTTACACTGGGAGACACAGCAGTGAAGCTGAAAT
+GAAAAATGTGTTGCTGTAGTTTGTTATTAGACCCCTTCTTTCCATTGGTTTAATTAGGAA
+TGGGGAACCCAGAGCCTCACTTGTTCAGGCTCCCTCTGCCCTAGAAGTGAGAAGTCCAGA
+GCTCTACAGTTTGAAAACCACTATTTTATGAACCAAGTAGAACAAGATATTTGAAATGGA
+AACTATTCAAAAAATTGAGAATTTCTGACCACTTAACAAACCCACAGAAAATCCACCCGA
+GTGCACTGAGCACGCCAGAAATCAGGTGGCCTCAAAGAGCTGCTCCCACCTGAAGGAGAC
+GCGCTGCTGCTGCTGTCGTCCTGCCTGGCGCCTTGGCCTACAGGGGCCGCGGTTGAGGGT
+GGGAGTGGGGGTGCACTGGCCAGCACCTCAGGAGCtgggggtggtggtgggggcggtggg
+ggtggtgttagtACCCCATCTTGTAGGTCTGAAACACAAAGTGTGGGGTGTCTAGGGAAG
+AAGGTGTGTGACCAGGGAGGTCCCCGGCCCAGCTCCCATCCCAGAACCCAGCTCACCTAC
+CTTGAGAGGCTCGGCTACCTCAGTGTGGAAGGTGGGCAGTTCTGGAATGGTGCCAGGGGC
+AGAGGGGGCAATGCCGGGGCCCAGGTCGGCAATGTACATGAGGTCGTTGGCAATGCCGGG
+CAGGTCAGGCAGGTAGGATGGAACATCAATCTCAGGCACCTGGCCCAGGTCTGGCACATA
+GAAGTAGTTCTCTGGGACCTGCAAGATTAGGCAGGGACATGTGAGAGGTGACAGGGACCT
+GCAGGGGCAGCCAACAAGACCTTGTGTGCACCTCCCATGGGTGGAATAAGGGGCCCAACA
+GCCTTGACTGGAGAGGAGCTCTGGCAAGGCCCTGGGCCACTGCACCTGTCTCCACCTCTG
+TCCCACCCCTCCCACCTGCTGTTCCAGCTGCTCTCTCTTGCTGATGGACAAGGGGGCATC
+AAACAGCTTCTCCTCTGTCTCTGCCCCCAGCATCACATGGGTCTTTGTTACAGCACCAGC
+CAGGGGGTCCAGGAAGACATACTTCTTCTACCTACAGAGGCGACATGGGGGTCAGGCAAG
+CTGACACCCGCTGTCCTGAGCCCATGTTCCTCTCCCACATCATCAGGGGCACAGCGTGCA
+CTGTGGGGTCCCAGGCCTCCCGAGCCGAGCCACCCGTCACCCCCTGGCTCCTGGCCTATG
+TGCTGTACCTGTGTCTGATGCCCTGGGTCCCCACTAAGCCAGGCCGGGCCTCCCGCCCAC
+ACCCCTCGGCCCTGCCCTCTGGCCATACAGGTTCTCGGTGGTGTTGAAGAGCAGCAAGGA
+GCTGACAGAGCTGATGTTGCTGGGAAGACCCCCAAGTCCCTCTTCTGCATCGTCCTCGGG
+CTCCGGCTTGGTGCTCACGCACACAGGAAAGTCCTTCAGCTTCTCCTGAGAGGGCCAGGA
+TGGCCAAGGGATGGTGAATATTTGGTGCTGGGCCTAATCAGCTGCCATCCCATCCCAGTC
+AGCCTCCTCTGGGGGACAGAACCCTATGGTGGCCCCGGCTCCTCCCCAGTATCCAGTCCT
+CCTGGTGTGTGACAGGCTATATGCGCGGCCAGCAGACCTGCAGGGCCCGCTCGTCCAGGG
+GGCGGTGCTTGCTCTGGATCCTGTGGCGGGGGCGTCTCTGCAGGCCAGGGTCCTGGGCGC
+CCGTGAAGATGGAGCCATATTCCTGCAGGCGCCCTGGAGCAGGGTACTTGGCACTGGAGA
+ACACCTGTGGACACAGGGACAAGTCTGAGGGGGCCCCAAGAGGCTCAGAGGGCTAGGATT
+GCTTGGCAGGAGAGGGTGGAGTTGGAAGCCTGGGCGAGAAGAAAGCTCAAGGTACAGGTG
+GGCAGCAGGGCAGAGACTGGGCAGCCTCAGAGGCACGGGGAAATGGAGGGACTGCCCAGT
+AGCCTCAGGACACAGGGGTATGGGGACTACCTTGATGGCCTTCTTGCTGCCCTTGATCTT
+CTCAATCTTGGCCTGGGCCAAGGAGACCTTCTCTCCAATGGCCTGCACCTGGCTCCGGCT
+CTGCTCTACCTGCTGGGAGATCCTGCCATGGAGAAGATCACAGAGGCTGGGCTGCTCCCC
+ACCCTCTGCACACCTCCTGCTTCTAACAGCAGAGCTGCCAGGCCAGGCCCTCAGGCAAGG
+GCTCTGAAGTCAGGGTCACCTACTTGCCAGGGCCGATCTTGGTGCCATCCAGGGGGCCTC
+TACAAGGATAATCTGACCTGCAGGGTCGAGGAGTTGACGGTGCTGAGTTCCCTGCACTCT
+CAGTAGGGACAGGCCCTATGCTGCCACCTGTACATGCTATCTGAAGGACAGCCTCCAGGG
+CACACAGAGGATGGTATTTACACATGCACACATGGCTACTGATGGGGCAAGCACTTCACA
+ACCCCTCATGATCACGTGCAGCAGACAATGTGGCCTCTGCAGAGGGGGAACGGAGACCGG
+AGGCTGAGACTGGCAAGGCTGGACCTGAGTGTCGTCACCTAAATTCAGACGGGGAACTGC
+CCCTGCACATACTGAACGGCTCACTGAGCAAACCCCGAGTCCCGACCACCGCCTCAGTGT
+GGTCTAGCTcctcacctgcttccatcctccctggtgcggggtgggcccagtgatatcagc
+tgcctgctgttccccagatgtgccaagtgcattcttgtgtgcttgcatctcatggaacgc
+catttccccagacatccctgtggctggctcctGATGCCCGAGGCCCAAGTGTCTGATGCT
+TTAAGGCACATCACCCCACTCATGCTTTTCCATGTTCTTTGGCCGCAGCAAGGCCGCTCT
+CACTGCAAAGTTAACTCTGATGCGTGTGTAACACAACATCCTCCTCCCAGTCGCCCCTGT
+AGCTCCCCTACCTCCAAGAGCCCAGCCCTTGCCCACAGGGCCACACTCCACGTGCAGAGC
+AGCCTCAGCACTCACCGGGCACGAGCGAGCCTGTGTGGTGCGCAGGGATGAGAAGGCAGA
+GGCGCGACTGGGGTTCATGAGGAAGGGCAGGAGGAGGGTGTGGGATGGTGGAGGGGTTTG
+AGAAGGCAGAGGCGCGACTGGGGTTCATGAGGAAAGGGAGGGGGAGGATGTGGGATGGTG
+GAGGGGCTGCAGACTCTGGGCTAGGGAAAGCTGGGATGTCTCTAAAGGTTGGAATGAATG
+GCCTAGAATCCGACCCAATAAGCCAAAGCCACTTCCACCAACGTTAGAAGGCCTTGGCCC
+CCAGAGAGCCAATTTCACAATCCAGAAGTCCCCGTGCCCTAAAGGGTCTGCCCTGATTAC
+TCCTGGCTCCTTGTGTGCAGGGGGCTCAGGCATGGCAGGGCTGGGAGTACCAGCAGGCAC
+TCAAGCGGCTTAAGTGTTCCATGACAGACTGGTATGAAGGTGGCCACAATTCAGAAAGAA
+AAAAGAAGAGCACCATCTCCTTCCAGTGAGGAAGCGGGACCACCACCCAGCGTGTGCTCC
+ATCTTTTCTGGCTGGGGAGAGGCCTTCATCTGCTGTAAAGGGTCCTCCAGCACAAGCTGT
+CTTAATTGACCCTAGTTCCCAGGGCAGCCTCGTTCTGCCTTGGGTGCTGACACGACCTTC
+GGTAGGTGCATAAGCTCTGCATTCGAGGTCcacaggggcagtgggagggaactgagactg
+gggagggacaaaggctgctctgtcctggtgctcccacaaaggagaagggctgatcactca
+aagttgcgaacaccaagctcaacaatgagccctggaaaatttctggaatggattattaaa
+cagagagtctgtaagcacttagaaaaggccgcggtgagtcccaggggccagcactgctcg
+aaatgtacagcatttctctttgtaacaggattattagcctgctgtgcccggggaaaacat
+gcagcacagtgcatctcgagtcagcaggattttgacggcttctaacaaaatcttgtagac
+aagatggagctatgggggttggaggagagaacatataggaaaaatcagagccaaatgaac
+cacagccccaaagggcacagttgaacaatggactgattccagccttgcacggagggatct
+ggcagagtccatccagttcattcaacacctggttagaaaactggggccagcacacagggg
+aagggtaagctggtttcatgatcgaatcaaggctcagacaatttttaaaggccagagggt
+agactgcaatcaccaagatgaaatttacaaggaacaaatgtgaagcccaacatttaggtt
+ttaaaaatcaagcgtataaatacagaaggtggagggaacttgctttagacacagttcagg
+tgaagaaagacctggaaacttctgttaactataagctcagtaggggctaaaagcatgtta
+atcggcataaaaaggcaatgagatcttaggGCACACAGCTCCCCGCCCCTCTTCTGCCCT
+TCATCCTTCTTTCAATCAGCAGGGACCGTGCACTCTCTTGGAGCCACCACAGAAAACAGA
+GGTGCATCCAGCACCACAGAAAACAGAGCCACCACAGAAAACAGAGGGTGACTGTCATCC
+CCTCCAGTCTCTGCACACTCCCAGCTGCAGCAGAGCAGGAGGAGAGAGCACAGCCTGCAA
+TGCTAATTTGCCAGGAGCTCACCTGCCTGCGTCACTGGGCACAGACGCCAGTGAGGCCAG
+AGGCCGGGCTGTGCTGGGGCCTGAGCCGGGTGGTGGGGAGAGAGTCTCTCCCCTGCCCCT
+GTCTCTTCCGTGCAGGAGGAGCATGTTTAAGGGGACGGGTTCAAAGCTGGTCACATCCCC
+ACCGAAAAAGCCCATGGACAACGAAAAGCCCACTAGCTTGTCCAGTGCCACAGGAGGGGC
+AAGTGGAGGAGGAGAGGTGGCGGTGCTCCCCACTCCACTGCCAGTCGTCACTGGCTCTCC
+CTTCCCTTCATCCTCGTTCCCTATCTGTCACCATTTCCTGTCGTCGTTTCCTCTGAATGT
+CTCACCCTGCCCTCCCTGCTTGCAAGTCCCCTGTCTGTAGCCTCACCCCTGTCGTATCCT
+GACTACAATAACAGCTTCTGGGTGTCCCTGGCATCCACTCTCTCTCCCTTCTTGTCCCTT
+CCGTGACGGATGCCTGAGGAACCTTCCCCAAACTCTTCTGTCCCATCCCTGCCCTGCTCA
+AAATCCAATCACAGCTCCCTAACACGCCTGAATCAACTTGAAGTCCTGTCTTGAGTAATC
+CGTGGGCCCTAACTCACTCATCCCAACTCTTCACTCACTGCCCTGCCCCACACCCTGCCA
+GGGAGCCTCCCGTGGCACCGTGGGGACACAAAGGAACCAGGGCAAAGCTCCCTCAGCCCC
+ATTCAAAGAGGCCTGGCCCACAGGCTCACGGAAAGTCAGCCTCTCATGCCCCGAGAGCTG
+AGTGCAAGGGAGAGGCAGCGCTGTCTGTGCTTCCCATGCAGAAGCACCCCCCTCCCACCC
+CTGTGCAGGCCGGCCTTCGCGGCAGACCACCATACACCACGTTCCAAGCCACACTGAGGC
+CTCCCTCCAAGCCTGCAGCCCCCATTTCCAGACCCTGCCAGGGCAACCTGCATATCCACC
+TCCCTACCCTGCCCCCCTCTTCCAGGAGTCTGCCCTATGTGGAGTAAGCACgtggttttc
+ctcttcagcaactatttcctttttactcaagcaatggccccatttcccttggggaatcca
+tctctctcgcaggcttagtcccagagcttcaggtggggctgcccacagagctcctcagtc
+taagccaagtggtgtgtcatagtcccctggccccattaatggattctgggatagacatga
+ggaccaagccaggTGGGATGAGTGAGTGTGGCTTCTGGAGGAAGTGGGGACACAGGACAG
+CATTCTTTCCTGCTGGACCTGACCCTGTGTCATGTCACCTTGCTACCACGAGAGCATGGC
+CTGTCTGGGAATGCAGCCAGACCCAAAGAAGCAAACTGACATGGAAGGAAAGCAAAACCA
+GGCCCTGAGGACATCATTTTAGCCCTTACTCCGAAGGCTGCTCTACTGATTGGTTAATTT
+TTGCTTAGCTTGGTCTGGGGAGTTCTGACAGGCGTGCCACCAATTCTTACCGATTTCTCT
+CCACTCTAGACCCTGAGAAGCCCACGCGGTTCATGCTAGCAATTAACAATCAATCTCGCC
+CTATGTGTTCCCATTCCAGCCTCTAGGACACAGTGGCAGCCACATAATTGGTATCTCTTA
+AGGTCCAGCACGAGGTGGAGCACATGGTGGAGAGACAGATGCAGTGACCTGGAACCCAGG
+AGTGAGGGAGCCAGGACTCAGGCCCAAGGCTCCTGAGAGGCATCTGGCCCTCCCTGCGCT
+GTGCCAGCAGCTTGGAGAACCCACACTCAATGAACGCAGCACTCCACTACCCAGGAAATG
+CCTTCCTGCCCTCTCCTCATCCCATCCCTGGGCAGGGGACATGCAACTGTCTACAAGGTG
+CCAAGTACCAGGACAGGAAAGGAAAGACGCCAAAAATCCAGCGCTGCCCTCAGAGAAGGG
+CAACCACGCAGTCCCCATCTTGGCAAGGAAACACAATTTCCGAGGGAATGGTTTTGGCCT
+CCATTCTAAGTGCTGGACATGGGGTGGCCATAATCTGGAGCTGATGGCTCTTAAAGACCT
+GCATCCTCTTCCCTAGGTGTCCCTCGGGCACATTTAGCACAAAGATAAGCACAAAAGGTG
+CATCCAGCACTTTGTTACTATTGGTGGCAGGTTTATGAATGGCAACCAAAGGCAGTGTAC
+GGGTCAAGATTATCAACAGGGAAGAGATagcatttcctgaaggcttcctaggtgccaggc
+actgttccattcctttgcatgttttgattaatttaatatttaaaataattctaccaggaa
+gctaccattattaccacaacttcacaaatgagaacaccgaggcttagaggggttgggttg
+cccaaggttacagaggaagaaaacaggggagctggatctgagccaaggcatcaactccaa
+ggtAACCCCTCAGTCACTTCACTGTGTGTCCCCTGGTTACTGGGACATTCTTGACAAACT
+CGGGGCAAGCCGGTGAGTCAGTGGGGGAGGACTTTCAGGAAGAGGTGGGTTCCCAGTTGG
+TGACAGAAGAGGAGGCTGCAAAGTGAAGGAGCAGGGGCTCCAGGTCTGGCGACAACCAGG
+GAAGGGACAGGGCAGGGATGGCTTGGACCACGAGAGGCACCTGAGTCAGGCAGTCACATA
+CTTCCCACTGGGGTCTACCATGTGAGGCATGGTGTGGGATCCTGGGAAGGAGACCAAGCC
+TCATTTCAGTTTGCTTATGGCCAAAGACAGGACCTGTGTACCCGACAACCCCTGGGACCT
+TTACCAAAAAAAGAGCAAACACCATTCACTCACTCATGTTAGATAAACACTGAGTGAAGT
+CACTGGAGCCCAAGGACTGTGCGAGGTCAGCACTGCCAATACAAGAAGCTGCAGCCCTCC
+AGCTCGCctccctcaatggccactccgtgctccagccatgctggcttccttttaggtcct
+ccacctccaggctgtagttcatgtgcttctttctggaatgttcttcccaacctacccact
+caaccctcagactttaccataaatgtcatttcctcacgtctgccttccctgacctgagac
+caagccaggCTTCCCATGACGAGCCTCACAGTACCCCATCTCCCCTGAACAGATGCAGTA
+ATAACCTACATAACccggggccatgatctatggctttgaatcctggctctgtcactaggc
+caggtctctcagcccttctgtgcctcagtttcctcatctataaaatgagatgacggcagt
+gcctgctcatgaagtgtgagttaatgcactcaaatcaatggttgtgcacggtttatatga
+atattagtgattaCAAAATATTATCAatagaccttgtcacaactgttattgaagaactaa
+tcatctattgcttatttaggtctttctctcctgccagaatgtgcgctccaggtggagagg
+tatgttgccttatccgtggctggatatatagagattcccacactgccttgcacacgagca
+ctgctgggtaaatatttgttggctgcaggaaAACGTGAAGGAATAGGCCCTCCAATGGGA
+GGAAAAGCATGAGTTGTGAGAGCAGAGCCACCACAGGAAACCAGGAGGCTAAGTGGGGTG
+GAAGGGAGTGAGCTCTCGGACTCCCAGGAGTAAAAGCTTCCAAGTTGGGCTCTCACTTCA
+GCCCCTCCCACACAGGGAAGCCAGATGGGTTCCCCAGGACCGGGATTCCCCAAGGGGGCT
+GCTCCCAGAGGGTGTGTTGCTGGGATTGCCCAGGACAGGGATGGCCCTCTCATCAGGTGG
+GGGTGAGTGGCAGCACCCACCTGCTGAAGATGTCTCCAGAGACCTTCTGCAGGTACTGCA
+GGGCATCCGCCATCTGCTGGACGGCCTCCTCTCGCCGCAGGTCTGGCTGGATGAAGGGCA
+CGGCATAGGTCTGACCTGCCAGGGAGTGCTGCATCCTCACAGGAGTCATGGTGCCTGTGG
+GTCGGAGCCGGAGCGTCAGAGCCACCCACGACCACCGGCACGCCCCCACCACAGGGCAGC
+GTGGTGTTGAGACAACACAGCCCTCATCCCAACTATGCACATAGCTTCAGCCTGCACAGA
+TAGGGGAGTAGGGGACAGAGCATTTGCTGAGAGGCCAGGAGCGCATAGATGGGACTCTGC
+TGATGCCTGCTGAGTGAATGAGGGAAAGGGCAGGGCCCGGGACTGGGGAATCTGTAGGGT
+CAATGGAGGAGTTCAGAGAAGGTGCAACATTTCTGACCCCCTACAAGGTGCTTGCTACCT
+GCCAGGCACCCTTTCCATACCTTGTCTCAGTTCAGCTCCCCACCTTGGATAAACAAGAAA
+CCTTGGTTGCAGAGGAAAAAAGAGGCTGGAAACAAAGGGGTAGAAATGGGGTAGCAGGGG
+AGATTGCCTGATCAACTGCCAAATGGTACACAGTTCTGGAAAAGCACAAAAAATGTGCAC
+ACACGGGTTCTTCCCACTTTAACCCCTGAGGAATCTGAGGCCTGCTCCTGAAACAGACTG
+GGCAGTGGCTAGTGACTCTAGGTATAGGAGTATCCAGCCCTGCTCACCCAGGCTAGAGCT
+TAGGGGGACAAGAGGAAAGAGGTGCCTGTGGGGGTGGAGGACAGGAAGGAAAAACACTCC
+TGGAATTGCAAAGTGAGGGCAGAGTCTATTTATATTGGGTTTAATTAACTCCTCTCCCTG
+GTGCCACTAAAGCAGCAATCACACTGCAGACAGCACTGATTTGATTGGCAAGAGATGCAC
+CAGGCAGAATATTAAGGGACCAGGCCCCTATAAATAGGCCTAATCACAGCCCCTCACTGG
+AAAATGGTAAGGAAGACATTAATCAGGCCTGGCACTGTGCCCTAGACCTGCTCCCCTAGG
+CACTACAGTGGGGCCCTTGGTTGCAACACAAGTAGGTAGGGATGGATGAGTGTGGCATGA
+AGGGCCTAGGAGATTTCACTTGGGTTTAAAATGCTGTGACCTTGAGTAAGTTGCCGTCTC
+TGAATCTGATCCTTTCGATTTCCCATTCTCCAAACTGAGAACTAGCACTGCTGAGACGTG
+GTTATTTCCAATAATAATTTGTATATTTTACATAACGCACCACACCAACATCTTCACCCA
+GTTGGAGCCTACTCCTTTGCTCCCGCTGCTGGCTTCCCCAGCCCTCCCTTCTGCCCTCCT
+CAGGCCAGCACTTTTCAGTGAGTTCCTCCTTTGCATACAGGCTTTCCAGATCTGTACTTG
+CCTTGAATACTCATCAGAGCCCAGGAGTTACTCCTCACCTCCCACTTATTTTTCCTCCCA
+TCAAATAACTAAAGCATGGCCAGCTGATGCCCAGCCAACTGAGAAACCCAACCCTCTGAG
+ACCAGCACACCCCTTTCAAGCATGTTCCTCCCTCCCCTTCTTTGTATTTATACTGATGCA
+AGTTTGCTGGCTGTcctaacttatttctgtgcctcagttctcccatatgtaagatcacaa
+agggggtaaagaTGCAAGATATTTCCTGTGCACATCTTCAGATGAATTTCTTGTTAGTGT
+GTGTGTGTTTGCTCACACATATGCGTGAAAGAAGAGTACATACACAGATCTCCTCAAAAA
+GGAGGCAGCAAGCCCGTTCAAGAATGGGACTGAATACACCTGATGAGTGGTTTACTTTCT
+GTCTGCAAACATCTACTGATCATCTGTTAGGTGCAGGCCATGATCACAACAAAGACGAAT
+AAGACACTACACTAGCCAGGGAGAGTCTCAAAAACAACTAAACTCAAATTAAATTCATTC
+TACTCCAGTCATGGGTACAAAGCTAAGGAGTGACAAATCCCTCTTGGAGTTAGGGGAGTC
+AGGAAAAAGCTCTTAGCAGAATGTGTGCCTCTCggccgggcgcagcggctcacgcctgta
+atcccagcactttgggaggcgaaggcaggcagatcacctgaggtcgggagttcgagacca
+gtctgaccaacatggtgaaactccatctctactaaaaatacaaaattagccaggcgtggt
+ggtgcatgcctgtaatccccgctactcgggaggctgaggaaggagaatcacttgaaccag
+gaaggtggaggttgcagtgtgccaagatcgcgccatggcactccagcctaggcaacgagg
+gtgaaCCAGGTCCAGGAAGAAGGTGCAAAGACAGCATTCCAGGTAAAAGAAACAGCTTGA
+ACAAAAAGTGTGTAGGGGAACCGCAAGCGGTCTTGAGTGCTGAGGGTACAATCATCCTTG
+GGGAAGTACTAGAAGAAAGAATGATAAACAGAGGCCAGTTTGTTAAAAACACTCAAAATT
+AAAGCTAGGAGTTTGGACTTGTGGCAGGAATgaaatccttagacctgtgctgtccaatat
+ggtagccaccaggcacatgcagccactgagcacttgaaatgtggatagtctgaattgaga
+tgtgccataagtgtaaaatatgcaccaaatttcaaaggctagaaaaaaagaatgtaaaat
+atcttattattttatattgattacgtgctaaaataaccatatttgggatatactggattt
+taaaaatatatcactaatttcatctgtttctttttacttttAGAAATCACATATGTGACT
+TAAATATTTCTTTTCTTTTTCTTTCCTCTCACTCAGCGTCCTGTGATTCCAAAGAAATGA
+GTCTCTGCTGTTTTTGGGCAGCAGATATCCTAGAATGGACTCTGACCTAAGCATCAAAAT
+TAATCATCATAACGTTATCATTTTATGGCCCCTTCTTCCTATATCTGGTAGCTTTTAAAT
+GATGACCATGTAGATAATCTTTATTGTCCCTCTTTCAGCAGACGGTATTTTCTTATGCTA
+CAGTATGACTGCTAATAATACCTACACATGTTAGAACCATTCTGACTCCTCAAGAatctc
+atttaactcttattatcagtgaatttatcatcatcccctattttacataaggaaatgggg
+ttagaaagaccaaataacattttttcaacatcaaaacactagcttgagatcaagcccaga
+cttggatctgtcgtctgaattccaagctttttgttatttattgatatgttttgttgtTTT
+CATGCAATAATGCAAATCTTAGCCCAAACATTTTGTTAGTAGTACCAACTGTAAGTCACC
+TTATCTTCATACTTTGTCTTTATGTAAACCTAAATTAGATCTGTTTTTGATACTGAGGGA
+AAAACAAGGGAATctaacactaaccagcccgtagtgtgtggtcaacactttcgttacttt
+agtatacatcaccccaattgtttgtcttcaccacacactttggagttaggtagtagtatc
+tatttttacaaataagaaaacccaggcacaaaggggttgattagcAATTATCTTTTGAAA
+AGCCTGTAGTTGCTCATCTGAAGAAGTGACGGACCACCTCTTATTTAGTGGACAGACAGT
+AACTAGTTGAGAAGACAGGGGATTTTGTTGGCGGAAAAAAAAATTTATCAAAAGTCGTCT
+TCTATCAGGGAGTTTTATGAGAAACCCTAGCTCCTCAGTTCCACAGTGGGTAACTGTAAT
+TCATTCTAGGTCTGCGATATTTCCTGCCTATCCATTTTGTTAACTCTTCAATGCATTCCA
+CAAATACCTAAGTATTCTTTAATAATGGTGGTTTTTTTTTTTTTTTGCATCTATGAAGTT
+TTTTCAAATTCTTTTTAAGTGACAAAACTTGTACATGTGTATCGCTCAATATTTCTAGTC
+GACAGCACTGCTTTCGAGAATGTAAACCGTGCACTCCCAGGAAAATGCAGACACAGCACG
+CCTCTTTGGGACCGCGGTTTATACTTTCGAAGTGCTCGGAGCCCTTCCTCCAGACCGTTC
+TCCCACACCCCGCTCCAGGGTCTCTCCCGGAGTTACAAGCCTCGCTGTAGGCCCCGGGAA
+CCCAACGCGGTGTCAGAGAAGTGGGGTCCCCTACGAGGGACCAGGAGCTCCGGGCGGGCA
+GCAGCTGCGGAAGAGCCGCGCGAGGCTTCCCAGAACCCGGCAGGGGCGGGAAGACGCAGG
+AGTGGGGAGGCGGAACCGGGACCCCGCAGAGCCCGGGTCCCTGCGCCCCACAAGCCTTGG
+CTTCCCTGCTAGGGCCGGGCAAGGCCGGGTGCAGGGCGCGGCTCCAGGGAGGAAGCTCCG
+GGGCGAGCCCAAGACGCCTCCCGGGCGGTCGGGGCCCAGCGGCGGCGTTCGCAGTGGAGC
+CGGGCACCGGGCAGCGGCCGCGGAACACCAGCTTGGCGCAGGCTTCTCGGTCAGGAACGG
+TCCCGGGCCTCCCGCCCGCCTCCCTCCAGCCCCTCCGGGTCCCCTACTTCGCCCCGCCAG
+GCCCCCACGACCCTACTTCCCGCGGCCCCGGACGCCTCCTCACCTGCGAGCCGCCCTCCC
+GGAAGCTCCCGCCGCCGCTTCCGCTCTGCCGGAGCCGCTGGGTCCTAGCCCCGCCGCCCC
+CAGTCCGCCCGCGCCTCCGGGTCCTAACGCCGCCGCTCGCCCTCCACTGCGCCCTCCCCG
+AGCGCGGCTCCAGGACCCCGTCGACCCGGAGCGCTGTCCTGTCGGGCCGAGTCGCGGGCC
+TGGGCACGGAACTCACGCTCACTCCGAGCTCCCGACGTGCACACGGCTCCCATGCGTTGT
+CTTCCGAGCGTCAGGCCGCCCCTACCCGTGCTTTCTGCTCTGCAGACCCTCTTCCTAGAC
+CTCCGTCCTTTGTCCCATCGCTGCCTTCCCCTCAAGCTCAGGGCCAAGCTGTCCGCCAAC
+CTCGGCTCCTCCGGGCAGCCCTCGCCCGGGGTGCGCCCCGGGGCAGGACCCCCAGCCCAC
+GCCCAGGGCCCGCCCCTGCCCTCCAGCCCTACGCCTTGACCCGCTTTCCTGCGTCTCTCA
+GCCTACCTGACCTTGTCTTTACCTCTGTGGGCAGCTCCCTTGTGATCTGCTTAGTTCCCA
+CCCCCCTTTAAGAATTCAATAGAGaagccagacgcaaaactacagatatcgtatgagtcc
+agttttgtgaagtgcctagaatagtcaaaattcacagagacagaagcagtggtcgccagg
+aatggggaagcaaggcggagttgggcagctcgtgttcaatgggtagagtttcaggctggg
+gtgatggaagggtgctggaaatgagtggtagtgatggcggcacaacagtgtgaatctact
+taatcccactgaactgtatgctgaaaaatggtttagacggtgaattttaggttatgtatg
+ttttaccacaatttttaaaaaGCTAGTGAAAAGCTGGTAAAAAGAAAGAAAAGAGGCTTT
+TTTAAAAAGTTAAATATATAAAAAGAGCATCATCAGTCCAAAGTCCAGCAGTTGTCCCTC
+CTGGAATCCGTTGGCTTGCCTCCGGCATTTTTGGCCCTTGCCTTTtagggttgccagatt
+aaaagacaggatgcccagctagtttgaattttagataaacaacgaataatttcgtagcat
+aaatatgtcccaagcttagtttgggacatacttatgctaaaaaacattattggttgttta
+tctgagattcagaattaagcattttatattttatttgctgcctctggccaccctaCTCTC
+TTCCTAACACTCTCTCCCTCTCCCAGTTTTGTCCGCCTTCCCTGCCTCCTCTTCTGGGGG
+AGTTAGATCGAGTTGTAACAAGAACATGCCACTGTCTCGCTGGCTGCAGCGTGTGGTCCC
+CTTACCAGAGGTAAAGAAGAGATGGATCTCCACTCAtgttgtagacagaatgtttatgtc
+ctctccaaatgcttatgttgaaaccctaacccctaatgtgatggtatgtggagatgggcc
+tttggtaggtaattacggttagatgaggtcatggggtggggccctcattatagatctggt
+aagaaaagagaGCATTGtctctgtgtctccctctctctctctctctctctctctcatttc
+tctctatctcatttctctctctctcgctatctcatttttctctctctctctttctctcct
+ctgtcttttcccaccaagtgaggatgcgaagagaaggtggctgtctgcaaaccaggaaga
+gagccctcaccgggaacccgtccagctgccaccttgaacttggacttccaagcctccaga
+actgtgagggataaatgtatgattttaaagtcgcccagtgtgtggtattttgttttgact
+aatacaaCCTGAAAACATTTTCCCCTCACTCCACCTGAGCAATATCTGAGTGGCTTAAGG
+TACTCAGGACACAACAAAGGAGAAATGTCCCATGCACAAGGTGCACCCATGCCTGGGTAA
+AGCAGCCTGGCACAGAGGGAAGCACACAGGCTCAGggatctgctattcattctttgtgtg
+accctgggcaagccatgaatggagcttcagtcaccccatttgtaatgggatttaattgtg
+cttgccctgcctccttttgagggctgtagagaaaagatgtcaaagtattttgtaATCTgg
+ctgggcgtggtggctcatgcctgtaatcctagcactttggtaggctgacgcgagaggact
+gcttgagcccaagagtttgagatcagcctgggcaatattgtgagattccatctctacaaa
+aataaaataaaatagccagtcatggtgtcacacacctgtagtcccagctacatgggaggc
+tgaggcgggaggatcacttgagcttgggagatcgaggctgcagtgagctatgattgtacc
+actgcactccaggctgggcgacagagagagaccctgtctcagaaaaaaaaaaaaaaGTAC
+TTTGTAATCTGTAAGGTTTATTTCAACACACACAAAAAAAGTGTATATGCTCCACGATGC
+CTGTGAATATACACACACACCACATCATATACCAAGCCTGGCTGTGTCTTCTCACAAATG
+CACTGCTAGGCACCACCCCCAGTTCTAGAATCACACCAGCCAGTTCACCCTCCAGATGGT
+TCACCCTCAACTTCATAAAAGTTCCCTACCTAATCTACTGACAGGCTCATCCCCGACCTA
+ATTTTAAAGATTTCCTAGGAGCTGCAGTGGGAATCCTGGACCTCAGCCTGGACAAAGAAC
+AGCTGCAGGTCATTCTCATGTGTGGACACAGAAGCTCTGCCTGCCTTTGCTGGCCAGCTG
+GGCTGAGCGGGCCTGGGAATTAAGGCTGCAGGGTTGGTCCCAGGCAGTCTTGCTGAAGCT
+TGCCACATCCCCCAGCCTCCTGGATTTGCCAGGATCCAAGAGCATGGACTTTAGGAATTC
+CTGGTGGAGGAGTGAAGAAAATGTGACAGGGTGTCCTAAGCCCCGATCTACAGGAAGAAA
+ACTGGAAATAAGACTGAGGACTTAGTTTAAGATGTTCCTACTCAGCCTCTAGCTTTTGTG
+CTACAGTTCTGGGAACAGACTCCTCTCTCCTGAAAACCACTTCCCTCCGCAGCATTAGAT
+TTCACCAAGATGTCTTGCTTGTGGGAAAGACTTCCAAGGATGCCTGGAGAGAGGAGGATG
+GAAATGTCCTGCTCTCTAAACAGATAGACAGATGCAGCCAGACAGAAAATAGTTTATCTT
+GCTGAGGTTTCTAATGTATTTGAAAGAGGCCTGGGTCTAGAAGTCTACCCAGAGGGCTCT
+GTGTTGTGCACGCAAAGATAAGAACCTTCCCTGTGGGAGTTCCAGAGCCAGTTTTCATAA
+ACACCCATCGGTGACTGTGTTCAGAGTGAGTTCACACCATCCTGACCTGCCCTGAGTTAG
+ACCTTACATGGTCTTCCTCCTCTAGGAAGCCTCTGCAGCCCAGGAACCTCCCCTTATCGG
+AAATGAACAGCATTTGAAGCTTCACCAGACAGACCAGACAGCTTAGCCCTCGTGTTGTGC
+CATGTGGGTTGTTCTCTGAGAGGcaggagagcatagtggttactaggaagggaaggactt
+tgggactagactgcctcggctggagtcctctttctgcttcatagccacgtgatcctaggc
+atgttacctgtgcctcagttttcactctgtcaatatgtaataactgaatctgtctttgtg
+gtgaggattcagtgagttaacatatttgaagtgcttaaaaATGAGGCTTGtgtccataga
+ttaatgagtgaatacacaaatggtgatatggacatacagtggagtattagtcataaaaag
+gaaggcagagctgatccatggcaccatgtgacagaacctcaaaagcattaggttaagtgg
+aagaagccagacacaggtcacctattgtgtaattccatttataggaaatatacagaatat
+gtaaatccgtggagaaagaaagccgatttccaggggctaaggggaggggagaatgggaag
+tggctgcttcatgggtacaaggtttcattttgagctgatgaaaatgttttggaactacat
+agagatagtgttggcacaacatggtgaatgtactgaatgccactgattgttcaatttaaa
+atggtcaaacttatatgaatttcacctccattaaaaaaaAAAAAAAAGgaccagatgtgg
+ttgctcacacccataatcccaacactttggaaAAAGGTGAAAGTTTTTTTTtcttttttt
+ttttatatacttaagttctagggtacatgtgcataatgtgcaggttggatacatagatat
+gcgtgtgccatgttggtttgctgcacccatcaacttgtcatttacattaggtatttcttc
+taatgctatccctcccccagccccccacccactgacaggccccagtgtatgatgttctct
+gccccatgtccaagcgttctcattgttcaattcccacctgtgagtgagaacatgcagtgt
+ttggttttctgtctttgtgatagtttgctcagaatgatggtttccagcttcatccatgtc
+cctgcaaaggacatgaactcatcctttttaatggctgcatagtatcccatggtatatatg
+tgccacattctcttaatccagtctgtcattgatggacatttgggttggttcaaagtcttt
+gctattgtgaatactgccacaataaacatacatgtgcatgtgtctttatagtagcacgat
+ttataatcctttgggtatatacccTAAGACctgggacgcatttaaagcagtgtgtaaaga
+gacatttatagcactaaatgcccacaagagaCCTCTGCCTGAGAACGTGGGTTTCAGCCT
+AAGAGTTGTAATATGTGTGCCCATTCACAGGTGCTGCATCAGAGTCCCAGGTGGGAAGAA
+GGCAAGCATACACAAAAATGGTAAaaggcagaaaggagcccagtctcgttctttttaaga
+agttttcctaagaatctccacccagcgacttgctctcacatcttcttggccagcactgga
+ccacacaactccttctagatacagaggagTCCTAGGATTCTATGAGAAAGAAGGGGAGGG
+TGGGCAAAGGGCAGCCAGCTGTGCAGCATCTGCTGGAGACACCTAACCCTTGGTGGAGGG
+GTTGTGGTGCTGGgagaaggctttctggacggtgtgacagcagagataaacttaaaggcc
+aagtaggagttaccctggtgaagcagggcagggttacaagcattccagcaacatgaagca
+gcaGGAGtgttttaattaaaagaaggcagttgctgtaaccaactataaacaaataaaggc
+ttaaacacaatggaagtttatttctcactaagggaacatccaaatccatgatactttaag
+tcagggacccaggttcctcccatctatggttctgccatcactaatctgggtcttccacaa
+ttgccgtgctccttggaggtgggaagagcaggcggaggacacgtgggaggttttagggac
+aagcctggaggcagcatgcgtcactcccatgcagagtccattggccaatgctggctccga
+tggccacatctcactgcaggggcagctgggaaatacagtctggctgtctacccaggagga
+agagcagccagtttctgctgCTGATGATCAGGAGGTGGAGAAAATGTTCAGTCAGGCAGG
+GAGTGGGAATAGACAAGACCACAAGCAGCTTGGTGCCTCTGAAAGGGAGAGGGGTGGAGG
+GGAGACTAGAGAGGTGGGTAGGAATACTGGATTCCACTGACCACGTGCTGGATGTCACGC
+TTAGCCCTCCTGCTCTGTGCCGGGTTAGGCACCTGGTGTTTTACGTACATAATCTCAATT
+CTGTGAGGGCATCCGACCTGTGGGAAAAGAGCTGTTTGTTTCAAATGCCAGTCCTGCTTC
+CTAACAAGTGTTTAGAGCTTAATCGTGTTCAAAAtacatatacaatgtttaatacttaca
+agaatttggtggggaaaatattaccatctttcccttttgtgattggagaaaaatgaggct
+ttgaagggtttaagaacttgcccaaggtcggccaggtgcagtggctcatgtctataatcc
+caacactttgggaggctgaggtgggaggatcgcttgaggccaggagttcaagaccagcct
+gagcaacatagtgagactttgtctctataaaaaataaataaataaataaaaaCAACTTGT
+CCAAGGTCAGACAGGCAGCCTCTTAGTAAGCACACATATCCTCTATATTATACTACCTCT
+CATGGAGGATCTCCTGTGTTCTACAAATAGTCTGGACTTGAGCCAGAATGTGTTATAATC
+CTGGGATCACGGCCAGTGGGCTTAGAAGAAGCCATCTCTTTCTCATGCCAAGATGAGGCT
+CCCCCAGATTTGCTCAGACTTACCTATAGTCAGCAGCATCGGGGGTCAGGAAAGACTTCA
+CGAAGCCATAAATGCATCCTTCTCGGGGCAGCACCTGGCTCTCCCAGGTGAGAGAGGACT
+CCATTTTCACAGGCAGGCGTGGGAGCTTCAGCACCCATCTCTGGGCCCAGAATGACCCAC
+TGGAGACCTTACAGCTCTCCTGTCACCCCCAATTCCTGCCCCCTCTGCAGCCTTGGAGGA
+GAATGGAGCTGAAGGGCCTGCCCTCTGTAGGGTGAGAAAGGGAGGCTAAAGCCTGGTGCC
+CACTGCCCTGGCTGCTCCGCATTGCAGGAGCTGCGCCCTTCCTTTCCTGGCACAGGGTCC
+ACAGCCCCGAAACCCCGTTGTGTGGGAGCTGGGCACAGGGCAGCAGGACTAATCCTTGGA
+ACAGCTCAGGGAGGATTATCCCAGCCACTGTCAGCAGCGGTGCAGCTGGCTCATTCCCAT
+ATAGGGGGAGGCCAGAGCCAGGGGCCTGCCACAAGTTGGAAGGCTGGGGAAGGGGAGGCC
+AGCAGAGGTGTCCTGGCTGTGGGTGGCTCTGAGGGGGCTCTCAGGGGTGGGGCTAAATCT
+CAGGGGCAGGATTATGTAAATCAAACCAATTCTAGCCACAGATTTAAAGTTTGGAAAAAA
+AAAAAAACCCAGCCTGGCGGAAAGAATTTAAATTATAAAAACTTAGAAGTATGGAATGTG
+AAATCATCCTGTAGGTGCTTATTTAACAACGAAATCATCCCGACACAATGAGCCATATGT
+GAAAAGTCATCCTTCCCCAACACATCCCCCAACAGGCACTCCTCAAGCCTCTCCCACCCA
+AGTGCTGGCATCCTCCCTGTCCTGCTTCACCTGAGACACCCCTTGTCTCATTAGACATGC
+AACTACGGGAGGGGTGACAGGAAGACAAGACACTATTTCCTCAGGCCCAGTTTGGTGTGG
+GGAGAAAGCCTCCTGATCCTGAAAGCAAGAATTTGACCAGAGCAGAAGTAATCAGTATGC
+AGATTGATTCTGTGGTATGTTAATGTTTATGCATAGATTATGAGGACCAGGTGAAAAGTG
+GGCCAGGGGAGCCAGATGTGTGTGTGAGTCATGGGTGGCTGAGATGAGGACAGGAGGGAA
+ACTGGTTTGGAGGGTGCTGGCGATGGGGTGGGGGTGCCAGGAGGAAGGGAGGCTAGTTGT
+TTGAATGTCTGCATGAAAAAGCGGACGACAGCGGGGTCTGGGTGAATTCGGGCAACCATT
+TGGACCGTGGAGAAAACTGCCTGCGTGCGGCTGAGGACCTGCACTATTAATTTGTTTTTT
+AGCTAAGGCAAAGATAAATATAAAAACtgatactccacccagttaccagaaaacatttag
+gtatgtgtgagacaacttgggtatgtgaacctaccttttcaatgtaaattcagtgaaatc
+taagtgcagatcccatatttccaataaaaaggtaacatccaaactcagatgtcctatgag
+tataaaatacacaaagatcttctggacttagtatgaaaagggattttttttttgtcaggt
+acctcactagttatttttaaaataggattgcatgttgaaatgataatcttttggatatat
+tgggttaaataaatttattattaaagttaatttcacttaaaaatgtttaatgtagctact
+agaaattttaaaattaagcatgttgctcaccttatgtttctattggacggctctCTCTAG
+ATACAAAGGCTGCCAAGAGGGACCTCACTCTAGCTTCAGGGAGAAGAGAGGAATTAGCAA
+GGCCAAGCAGAGGCTCCTGAGGGCAGGGCCAAGGGCGGCTTGGTGGGGTGGGGATGGGAT
+GCACAGAGATAACTCCAACCCTTAAGAAGGTGTTTCCTAGAGCAGGCTGTGACCTGTCAG
+TTTATATACTGAGGCTTAGGAGCCTCTTGGATGCCCCCAGATCTGCACCCCTGAATTGCC
+CTGTGCCCCTGCCGTCTTTGTTCCTGTGCTGGCATAGTGGTCTCACCTCCGGCAGtatca
+ccaccactgggcacaagcttctccagcacagcaactgtgtcttatttctccttgtactcc
+cagtgttcacaccatgctgcactcacagaagactcttcgttgatattttgtggacagaga
+gaatGCCTGTGAGAGTGGGCTGAAGTGTGCGTTGGGCTCCAGAGACCTTAAGGAGGGGAG
+ACCAGGTCCTGAGTAAAGTTGAAGGGGAGGGGCTGAGTCCTGCTAGCCAGGAGTCTCATC
+CCCTGGGGAAGTTCCAGGGACCCCTCAGAAGTGCAAGGGGACGGTGTTAGTGTTAGTCCA
+GTAACACAGCCCAGAGCCTGCcttccacgtgggtttgacaggagcctcctaactgctctt
+ctgcttccatttttgccccttcagtctattctcaacagggaagccagaggcatccttaac
+catgtcagatcatgtggctcctcagctcaaagccTCATCTCAGAGGAAAGCTCTGGTCCC
+TTAGAAATGGCCCAAGTGGTGACAGACAGACTCTAAGGtgagcagactgttgctagatat
+ctgggctcggaggactcgccactgctcaaaggcagtgaggattttcgcactagaagctgg
+aggacagggatccttgttaggtaggagcagaaagcttagaaaagtggtctcctgcagtta
+cgtggcaaacacatcatgtaagtgataaattgggtatgcagttgaggagatttccaagta
+aaatgttgaggatgctgcctggtttcttcttactgcttataatatagtgtgagagaagag
+agataaattgagaaagagactggtttttaaactgttaaaattgaatcaggacttgatgat
+tttgaaaattgtcagtctccccacatggaaaaagatgctgaaattaacaaatggcttctg
+agcatgtggcatagggtgtaactgtacagtcttttgtgattatgcataaagatcaaagga
+tgggagtagcaatgagtcacacagaggtctgttgcaagagattacaagggtgtaccatgc
+agaacctctccaccaaaccttagggcccttgggaagcttcagtgagttaccctgggggcc
+atcttggcaggagctgaaggtagaaaggtagagtttatctctaaaagattcatgggtatg
+gctcttgacaaatcgactatgagccccaccgaaacccacagaggacaggcaaagggtttg
+ggaaagctgtttcacccacagtgctggcagattggtctgtaggggacagagtgcaaaatg
+aaagaagactgtcagagaccccaaactctgctgtcaagaagaaggctgataaaactactt
+ggctgcaaacacgtggatctttcgtgagaaaagaaggatgacccagaggcagaagcccag
+aaggcagagccaagagacatggaatcttcccacatcttaaaacctgtttagggaacacca
+gcatctgtccagctggatttcagaaccaccattccttcatccttcccctgctgcctcttt
+ctgaacagcaatgtctcaagctttacccaccattgtgtgttgcatatgtagggggcagat
+agcttgtatctttagttttccagatcagaggaacatccaaagaaatctgttctacaccta
+aacccgatttagatgagattcgggactgtgagcatgaagggatctcaagaggggtgaatg
+tgttttgcatgcacaagggacaggagtcttggggacagaggacaggctgtggtggcagat
+actaaggtgacccccacaacccccacctctgccattcacacccttgaataatccccttct
+ctggttgtaagcagaacctgtggcttgcttatgaaggaggcggtatatatgtgattcatg
+tactgatcatattgtataagatcactggctggatgcagtggctcgtgcctgtaatcccaa
+cactttgggaggctgaggcgggtggatcacctgaggtcaggagttcgagaccaggctggc
+caacatggcaaaaccccgcctctactaaaaatacaaaaattagccaggcatagtggtgca
+cgcctgtaatcacagctactcaagaggctgaagcaggagaattgcttgaactcaggaggt
+ggaggtggcagtgagccaagatcgtgccactgcactccagcctcagtgacagagcgagac
+tctgtctcaaaaaataaataaataaaatgttaagatcataacctgtctttctggggactc
+tctcttgacgcctttgaagaagcaggctgccatgttgcaagctgcctcatggaggggatc
+agctgcgaggagctaagagccccctccagtcgatgctcaccaggaagctgaggtcttgtg
+tccagcaccctgcatagaactgaatgctgccatgtgagcttggaagcagagccatccaca
+cagctgagccctagatgagaacccagtgctggctgacaccctgatggcaccttacagagg
+accagttaggctgtgccaactcctgacctgcagaagctggggaacactgggtcgtatttg
+cagctgctggatttgtgggaatttgtcacacagcaatTGGGAGTCACACAGCCTGTGACG
+CCCCAACAATCCACAcctcctgcatctccctgccttcacttcctagcacactgccctgac
+tccctctgccgcagccacgctggccctctgctgttcttcgaagccaccagggctgcattg
+gctcccagcctttgctctcactgctttctcctcctagagagcccttcctgcatgtatatg
+tttgactcactcccttgcctccttcagacttgtacttaaaaatctcagtaagcatttccc
+tggctacccttttaaaaattgcaacccacttccatccccatccccaacatgccatatttc
+ctttcttcttcttccttcttcctttttttttttttttttttgacacaggttctctgtcac
+ccagcctggagtgcagtgacatgatctcggctcactgcaacctctgcctcccCAGGCAag
+aaaaggggaggatgccaataaaggatgcattgatttgtatttactacagtggacatcaag
+ggcacattcttgctgtggccatcaagagactgtataaattctatgacttgtagttgtccc
+acttaagaaacaaagaagctgtgcatttctttactggtctagagctgctctagggcattt
+tctctacagcaattctaggtttccccaccttgtgagtttagctttttctatattcaaaga
+aaagtcctcagccagagattctcaggagcttatagaacaatccaaactcttgggaatatt
+aagtggagaggggtacgtgcaagacaccaacagcACTAGAAACAGTCCACATCTTTCCAT
+GCGTGGAGGAGTTTATGCTCTATGTGAGTTCACTCCATCATTAATTCTTCAAACACAAGA
+GTGTTAAAGGAACAAGAGTTAATGGGTCCTGTCATTACACTTGTTCCCAGGATGACATTC
+TTCATCTTCCTCTTCTACAACCTGTTCTATATTCCCCTCATGTTTATCCAGTGCTTCTGC
+TAGTCTAGTTCACTTCCAAAGACCCATGATTACCATGGCCCTGTCAGGCTGTAATTGCTG
+CAATTTCCAATTTACAATTGTCATCATCTATGGTTGATAAAGgtatagcaatatttctat
+ttcctcatgataatgaaggtcaattacaactgccagtataataacttatttctttgtctg
+ccaacctacatacacaaggaagccaaaatgacagggagctactaaaactttattcttatt
+ggaatgcttactatgtacccagaagaagcattctccctactccagcagagcttaatgctg
+taggtccaggaagctcaaattctccaagggagttttagtgagaggagccactctcaccct
+ctgcccttggtttacaaacctgtatattctaggacccaatatcttacaatgtccattggt
+tcaaagtataacatgttaaagcacagagccccaactctgaaaagtaccatccctaaattg
+gcatttagttgcacctttatatccacctttaaaagaaatatcttttaatgttctatcaga
+ctgatagattctgtttaatatagtatattatagcaccagtggatcatttggttgtatgca
+tattattgtaccttctctgctacaaaatatattcctttgtcctaaggtgtgttacaaaga
+acattaggcattctatgcatctttggatagtttaatggccaagacattgatggcaggaga
+gtcaaagccacaggtggaaaacacatttatcccagtaagaacaaattgctattcttccac
+tgtagagagggtaaacaatgtgccattacgttgccaattgaatgcctcaatcatgtcaag
+ggctgaacatctatgactgtttctgaaaggtcaaacattcaacagaggctgtagctagaa
+ctgccttaatgataagagatcatgctgaattacccatgcaaaaccttaatacttgacact
+tatcactactttattcaagagcctattgtgcaagcataagtggctgagTCAGGTTCTCAA
+CTCTGCTCATTAATACTATGCTTGGAGTATACAGTAAGATAAGAAACATAAATAAGAAGT
+GTACATTTGTTTCTTCCTGTTTTCTTCTGGCTATTGGATCAATTACATCCCATCTTAAGC
+TGACCCCTGTGTAATTAATCAATATCCGTTTTAAGCAGCAATCCATAGTTGTGCAGAAAT
+TAGAAAACTGACCCACACAGAAAAACTAATTGTGAGAACCAATATTATACTAAATTCATT
+TGACAATTCTCAGCAAAGTGCTGGGTTGATCTCTATTTACGCTTTTCTTAAACACACAAA
+ATACAAAAGTTAACCCATATGGAATGCAATGGAGGAAATCAATGACATATCAGATCTAGA
+AACTAATCAATTAGCAATCAGGAAGGAGTTGTGGTAGGAAGTCTGTGCTGTTGAATGTAC
+ACTAATCAATGATTCCTTAAATTATTCACAATAAAAAAAAAGATTAGAATAGTTTTTTTA
+AAAAAAAAGCCCAGAAACTAATCTAAGTTTTGTCTGGTAATAAAGGTATATTTTCAAAAG
+AGAGGTAAATAGATCCACATACTGTGGAGGGAATAAAATACTTTTTGAAAAACAAACAAC
+AAGTTGGATTTTTAGACACATAGAAATTGAATATGTACATTTATAAATATTTTTGGATTG
+AACTATTTCAAAATTATACCATAAAATAACTTGTAAAAATGTAGGCAAAATGTATATAAT
+TATGGCATGAGGTATGCAACTTTAGGCAAGGAAGCAAAAGCAGAAACCATGAAAAAAGTC
+TAAATTTTACCATATTGAATTTAAATTTTCAAAAACAAAAATAAAGACAAAGTGGGAAAA
+ATATGTATGCTTCATGTGTGACAAGCCACTGATACCTATTAAATATGAAGAATATTATAA
+ATCATATCAATAACCACAACATTCAAGCTGTCAGTTTGAATAGACaatgtaaatgacaaa
+actacatactcaacaagataacagcaaaccagcttcgacagcacgttaaaggggtcatac
+aacataatcgagtagaatttatctctgagatgcaagaatggttcaaaatatggaaaccaa
+taaatgtgatatgccacactaacagaataaaaaataaaaatcatattatcatctcaatag
+atgcagaaaaagcattaacaaaagtaaacattctttcataataagacatcagataaaaca
+aattaggaatagaaggaatgtaccgcaacacaataaaggccatatataacaagcccacag
+ctaacatcataatagtaaaatcatcacactggtaaaaaaaatgaaagcttttcctctaag
+gtcagaaataatataaaggttcccactcttgctatttctattccatatcgtactaaaagt
+cctagccaggacaattagacaaaataaaaataaaaacacccaaattggaaagatagaagc
+aaacttttctgtttacagataacataatcttatatgtagaaaccccttaaaacttcagca
+aaaaaaaaaaaaaaactacagagctagtaaattcagtgaagttgcagaatacaaaatcaa
+catacaaaaatcagtagtgtctctatacactaataaggacttaacagagaaagaagttaa
+gaaaacaataccactaacaatagaatccaaaaaataaaatacttaggaataaattttacc
+aaacatctgtacactaaaaactataaaacattgaaaaaagaagttgaataagacacatat
+aaatagaaagctatctcatgttaatagattagaaaaagtaatattgttaagatgtcctca
+ctacttaaagcaatttatagatctaatgcatttattgcaatctcttcaaaatcccaaagg
+tatttttgacagaaataaaaaaaaaattctaaaatatgcatgaaaccacaaaagactgtg
+aatagctaaagcaatcttgagcaagatgaacaacactggaagcatcacactaccttattt
+caaaatctactacaaagctatagtgatcaaagcaacatgatactgtcataaaaacacaca
+gataaacctatggaatggaataaagagcacagaaataagtccacacatttacattcaatt
+gattttcaacaacaatgtcaagaagacaatggggaaaagacaatctcttcaataaatgat
+gctggaaaaactatatatccacatgcagaagaatgcagttgaatcctgatttcataccat
+atgcaaaattcaactggaaatggattaaatacaaatttaaaacatgaaatggtataacta
+ttagaacaaaacatagaaaatattcttcctgacattggtttgggccatcatttttctgat
+atgactctaaaagcacaggcaaaaaaagaaaaaatagacaaatgagactatgccaaatta
+aaaaatttctaacaacaaaagaaacgatcaatagagtgaaaaagataacctcttgaatgg
+gagaaatatttgcaaactactcatccaaccggggattgatatccagaatatacaagtaac
+acaaatatgtcaaaagtaaaataaataaataaataaataaataaataaattaaataaatt
+atttaaaaatcggcagaggacaggaatagacatttctcaggagacaacatacaaagggcc
+acagatacatcaaaaaatgctcaacatcactatttgtcagggaagtactaattaaaacca
+aaatgagatgtcccctcaaacctgttagaatggctattatcaaaaagatgaaagatagca
+actatcagagaggatgatagaaaagggaacccttgcatcatgtacaaattaaaaatagaa
+ctatcacatgatccaagaatcctacttctgggtatatagccaaaggaattgaaatcaata
+tgtcaaagggatatctgcactcctatgttattgcagcatgttcacaatggccaagatata
+gaatcaacctaactgttcatagacagatgaatggataaatgaaatgtgatatggaaaatt
+attcagccttaaaaacagtaggaaattctgtcatttgagacaacgtggatgaacctagag
+gacattaagctaagtgaaataagctagacacagaaagacaaatattgcatgatctcactt
+agaatctaaaaaatctgaactcatagaagcagagaatagtatgatggttactagggttat
+ctggcagggagaggatgaggaaatgggacattgttaataaaaggaaaaaaattcaattag
+taggattacattcaggggacccaatatacgacatgttgactgtaattaataatgtattgt
+atgcttgaaaattgctaatacagtatattgtaaatgttaatatgaggtaatatatgtgtt
+aattaacttgatttattcattcaacaacatacacatatattaaaacatcacactgtattc
+cacaaatatatataatttttgtcaattaaaaaaTAATTTTTAAAAATGAGAAACAAAAAA
+GCTGACATTTTCAGATTAAAAAAATTATACAGAAGAATTAATTCATTAAAGTAAAAACAA
+ATGTGGGAAAATGGTTTTTAAATATAATTTAAACCAAATTTAAAATAAGCATATaaagac
+tatggacaaaacaagaaatccaaataaaaaataaacatatgaagaatattcaaactcact
+ttttatcaaagaaatgtaaattTTAAAATATAGCATTGCTATTGTGTTTTCATAAATAAT
+AATATATCATGGATGAGCCTGTGAGGAAACAGACACTCATACTCTGCAAAGCAATGACTA
+Agataattatgtcagatcatgaattacgttaattagcttgatggtggtcactgtttcacg
+ataaatatacatatgtatcaaaacatcacattacacaccataaagatatataacttgtta
+tCAAAAAGAAATATAGCAGttaaaatttaaaatttttaaaaaaCGTCTTTTTGAGGTTCG
+TACCTCACTTAAGTCACACTGTTCAAAATATTCATGCACTCATTTCTCTCATTCATGTGT
+TAATGTACAGGGTACGGGCCACTATAAATTCCTTCAGCAACTGGAAAGGAAACTTTATGT
+ACTGAGTGCTCAGAGTTGTATTAACTTTTTTTTTTTTTtgagcagcagcaagatttattg
+tgaagagtgaaagaacaaagcttccacagtgtggaaggggacccgagcggtttgccCAGT
+TGTATTAACTTCTAATTCAACACTTTAAGATTCTTAGCATTATTGCAGACAACATcagct
+tcacaagtgtgtgtcctgtgcagttgaacaagatcccacacttaaaaggatcctacactt
+tttttaatgctctgctgtttctgccttgaaattcttaacaatttttttaaccaaagtcct
+cacaaattcagtttacattagccctgcaatcatgtagacatcctgATTCCAGACAATGTG
+TCTGGAGGCAGGGTTTACAGGACTTCAAGAACCTTACCTTCTCAACTTTCATCTGCATCT
+TTACTCCCAACTATATATGAAGATGATGAAGATAGATATGGATGGTGCTTCTACCATACC
+CTCTTCCTCTGCCAAACTTCCTTGATCTAGGATAAggtcagtaaacttcttccgtaaaag
+gccaaaagtaaatattataggctctacaggccctagagtgtctgtcataactactcaact
+cttattgtagcataaaaactgtcaacagacaatacagaaacaaatgagtgtgactgggtt
+ccagtgaaactttatttacaaaagatttgtcccatgagtcaaatttaccacctccAGATC
+TAGAGAAACAGTTTTGAGCCCTTTTATTTTGCTCAACAGTTAAGCATGGCTCCATGTCCC
+TTATATTTAGTCAGAACTCGGTATGTTTTAAGGAAAGAATGGTTACACGAAGACATACAT
+TCATTCATTTATACAACACATTTTCAGTGTTGAATGATAAATTTTGGAATAGTTAACAGA
+TGATAAAAGTGTTGTTTTCAGTCATCCCTATCCAATGAAGTAAAAAAAAAAGTGTTGAAT
+GGGAAGAAATCAAGAATAGTTATACGAATATCACCATTGCATTAAAGCTCTCTTCCTTGT
+TTCTAAAAGAATATCTTGACACACATTAAGCTCACTGACCCCCACACCATGAATGAGGGC
+ATCTTCAACAATGGTGGATGACGTCTTAGTTTCCCTCAACTCAGTTAATCTAAGTAAGCT
+CATGGTATCACTTTCCTGTCCTAGAGGGAACATATTTCCTGCATTTTTCTTTTTTTCCTT
+ACTTTCCATCACCAAGTAACTCTTCTGATATTTTTTCTCTTGAGAAAATTAATATGACTC
+ATAGATCTGGTTCCCAAGAGAAATCAATGGAGGCCTGGTTACAAGGATCTAAGAAGCATC
+AATGGGTCACTAACATCTAGTGGTACTAATTAACTCTGTTAATCATTGGGAAGAAAATGT
+ATATATACTTTTGTCTTGGAGCTGATTCTACTAGAAAGCAGAAATCAAAATGATCAGTTT
+CCCAGTGTCACTACTGCACACCCTGGAACAGAACAGGTAGGTCAGAAAAACGCTCCCAAA
+GTTTAGCAATGTCAAGGCAATCTCTCTCTTCTTACATTTCCCTTCAACCTTCTATCTCCT
+CCACTTTTCTGTTTTCCTCCTATCTCCAATTATTTCAATCCTCAGAGCATTATTCTTACA
+ATCTTAATCACTAAATTATATTACACCCGTTAAAGGAGAGATTTCTAAATGCATTGACAT
+TTGTACTGTCTCTCTTTGGAGAATTAGTATTATAAGGATCTGTTATCTCTTGTCACCTTC
+CTTATGTCATATGATATGTCACATTTCCCACTGCGGAGACCAAACATGTTCACATCGTGT
+GCGTTCCATTTTCCTAATGGAAAGTGGGGGGAAGTGATTTTCTGTCCTCATATAGAGAAT
+GCTGGGGCCATTCCCTCTGTATGCCATATTTGATAAAGCATTTGATAATCTTAGTCAATG
+CCTGGGCCAAGAATTAAAGGGGTAATTATCAGAATGAAAATGGTTTAATGAAACTGTGTC
+TATCAGTTCTGAAAAGGGCCTCTATCACAATGAACTAAGGTAGTTATGAATAGAGCTAAa
+acttaggcaacaccatcctggacataggaacgggcaaagatttcatgacaaagacacgga
+aaccaatcacaacaaaagcaaaaattgagaagtggaatctaataaaacaatagcttctgc
+acagcaaaagaagctaccaacaaagtaaacagacaacctacagaatgggagaaaatattt
+gccaactgtaagtctgacaaaaatctaatatctggcagctataaggaacttaaatttaca
+agacaaaaacaaccccattaaaaagtgggcaaagaacatgaatagacactctcaaaagaa
+gatatacatatggttaacaagcatatgaaaaaaaagctcaatatactgagcattagagaa
+atgcaaatcaaaaccatattgagatatcatctcataccaggcagaatggctattattaaa
+aagtcaaaaataacagatatcggtgaggttacagagaaaagggaacacttatacactgtt
+ggtgggactgtaaattatttcaaccattgtggaaagcagtatgggatggcgattcctcaa
+aaagccaaaaacagaactatcattcaacccagcaattccattactgggtatatacccaga
+agaatataaatcgttctaccataaagacgcatgcatgagaatgttcattgcagcactact
+cacaatagcagagacatggaatcaacttaaatgcccatcagtaacagactggataaagaa
+agtgtggtacagatacaccgtggattactatgcagccataaaaaagaacaagatcatgtc
+tttgacaggaacatggatggagctggaggctactatccttagcaagctaaggcaggaaca
+gaaatccaaataccgcatgttctcacttatgagcgtgagataaatgatgagaacttgtaa
+acacaaagaaggaaacaacaggcagtggggtctacttgaggacgacgggaagagggagag
+gagcagaaaagataactactgactaccgggcgctacctgggggatgaaacaatctgtaca
+acgaacccccaggacatgagtttacctatgtaacaaaccttcacgtgtacccccgaacct
+aaaataaaagtcaaaaagaaaAAGAAAAAAAGAAAAATCCATGCATATGATACATCAGTT
+AACAAGGCACTGGTGAAATTAATTTTAAGTATTATTGTCTCTTTGTGTTTTTGGTCTCAG
+AAAAGTTACGATTTCCCTTAGTTCCTTAGGGCAGAGAGAATCTTCAATCACTGAAGTCAG
+GAGACACACATTCTATCTGATTTTCTACATTATCTGTTTGAAAAGGTTACCCACTTATTA
+GTGTTAAAGCCAAGATATCCAGCAAGGATAGCAACCAACTCTTAAGGTACTCTCCCTTAG
+GAGGATTCCTGATTCTTTAATGTTTTCTAAAAAAGCAAAACAAACAAACAAACAAAACAA
+AACACTAAATGTTTTCTCTTTCAACTTATTTGAATACACTCTTTTCTCACTGCTCTGAGC
+ATGAATTCAATATTTCAGGGCAAACTAACTGAATGTTAGAACCAACTCCTGATAAGTCTT
+GAACAAAAGATAGGATCCTCTATAAACAGGTTAATCGCCACGACATAGTAGTATTTAGAG
+TTACTAGTAAGCCTGATGCCACTACACAATTCTAGCTTTTCTCTTTAGGATGATTGTTTC
+ATTCAGTCTTATCTCTTTTAGAAAACATAGGaaaaaattatttaataataaaatttaatt
+GGCAAAATGAAGGTATGGCTTATAAGAGTGTTTTCCTATTGTTTTCAGTGTAGGACTCAC
+TGTTCTAAATAACTGGGACACCCAAGGATTCTGTAAAATGCCATCCAGTTATCATTTATA
+TTCCCTAACTCAAAATTCATTCACATGTATTCATTTTTTTCTAAACAAATTAGCATGTAG
+AATTCTGGTTAAAATTTGGCATAGAACACCCGGGTATTTTTTCATAATGCACCCAATAAC
+TGTCATTCACTAATTGAGAATGGTGATTTAACAAAGGATAATAAAGTTATGAAACCAATG
+CCACAAAACATCTGTCTCTAACTGgtgtgtgtgtgtgtgtgtgtgtgtgtgtgtgtAAGA
+GGGAGAGAGAGAAAATTTCACTCCCTCCATAAATCTCACAGTATTCTTTTCTTtttcctt
+tcctttccttgctcttctttctctcctattgctttcctttcatttccttCTCATAAAAGA
+AAAATAACAATATAGAAAATAACAAAATATAGATGGTCAACCTTTTTAATATTAAGGTTA
+CCTAAAATGCCATTATCCAAAGTGGTTCTCTAGAGATGCTGATGTATATACTTACATATT
+TTACAGTGTATTCAAATAAAGAGTATATTACATAAGACATATCCTTTTGTAACCAACTTT
+TGTCATTAACAATTTACTGGACTTGTCAACAAACCTAAATCTGTATCGTCTATAATGGCT
+ACGTTCATTTTGGTATGAATCTTAATTACCCCTTTCTGCATTATTTAATGATTTTCTCAT
+ATGTCACTCTTAAATGTACTTCTAATTTTTCACTTTACATCACATAATGAATGGATCCAA
+ATATGTTATGGATAGATATCTTCAAACTTTCTACTTACAAGTAGTGATAATAACAGATGT
+TCTCTCTAAAGTGTAGTTGGTATCAATTTTACTGACCTTTAAAAATATCTTAATGGGACA
+AAGTTCAAATATTTGATGACCAGCTATCGTGACCTTTATCTCTGTGGCTCTGTGGGCCTG
+TAGTTTTTACGTGCTTTTAGTGTATCATGATTAAATATTTTGTTTTAGTAAAGACACCAT
+TATTTCCCAACTTCATATTCAAATTGTCAAAGGTATTAATCCTAGAGCAGAACTCTCAAA
+AGCACCAACTCTGATTCCTAACAAAGCATGGAAAAGCCCTCTCTCTGAGTTTCAGATACT
+CTTTTTTGTGGGGGTTGAGTTTCACTTTATTTAAAGTGAGTCTTAATCCTCCAACAAGTC
+AACAAGTGATTGGCTGGAATCACACGTATTGGAAAACCAGCGGAAGAGTAAGTCTTTGTA
+TTTTATGCTACTGTACCTCTGGGATTAATTGCTCTTTCCCTCATTGGCCAGTCACTCTTA
+GTGTGTGATTAATGCCTGAGACTGTGTGAAGTAAGAGATGGATCAGAggccgggcgcggg
+ggctcgcgcctgtcatcccagcactttgggaggccgaggcgggcggatcacgaggtcagg
+agatcgagaccatcctggctaacacggggaaaccccgtctccactaaaaatacaaaaagt
+tagccgggcgcggtggcgggcgcctgcggtcccagctgctggggaggccgaggcgggagc
+atggcgggaaccgggaggcggagcctgcagtgagccgagatggcgccaccgcactccagc
+ctgggcgacccagcgagactccgcctcaaaaaaaaaaaaagaaGATTGATCAGAGAGTAC
+CTCCCCTAAGGGTACATGCAGATAAATACAGTTAAGGCGATTAACATTTCAAATACGGTG
+ACTGTTTCTTACGTGGACGACGTTGTGTTGAACATGGGTGAGTAAGACTGAAGCAGCCGT
+AATTACTGCACGATGCGCATGGTAAAGAAGCACTCCGTTAGGGAAATTATATTCTTTGCC
+CCTCTAATCCTTCACTCCACCTGCCATATTCCCACATGATTTTTTTCTTTGCTGTTCTTG
+TCTAATTGttattaataattaataaataaCTTATGATCTAATTGTTATTAATAATAACTT
+ATCATCACATGatttattaataaattaataaataacttattatCACCGCATTTCCCCAAT
+TCATTTATCTTTCTTTCATTTTCTCTCTTTGTGTGTTTTCTGTCTTCATATTTCAGCACT
+TGCCACATATTTCCCACAAAATCATTTATGGTCAAACAACACTTCAACGTGTAGCATTTG
+TATTTCTCAATTCTTCCTCACTTTCTTCCTTCAGAATACTAAAGCTTCTTCTCTACTGAC
+TGAGTCAATGGCCAATGGATAGAGTAAATAATTCTGCGGTATCTAAATTTGTATTGATTG
+GACTTTCAAGCTCTTGGGAGATGCATCTTTTTCTTTTTTGGTTCTTCTCTGTGTTCTACA
+TGGGAATTATCCTGGAAAATCTCTTCATTGTGTTCACAGTAATTATTGACTCTCATTTAA
+ATTCCCCAGGTACTGCCTACTGGCCAACATTTATCTTCTTGATCTGGGTCTTCTCCTACA
+GTTCTGACTTTTTCACTAACTGCAGCATCATTTCTTTTCCAAGATGCATCATACAGATAT
+TTTTCATTTGTGTCATGCGTAAAAATTGAGATGGTGCTGCTCATAACCATGGCATAGAGC
+AGGTACACTGCCAATCTGTAAGCCTCCCCATTACCTGACCACAATGAACCCCAAAATGTG
+TGTTTCCTTTGTTGGAGGCATCCTGGATAGTCAGGATAATCCATGCTGTATCTCAGTTTG
+TTTTTGCCATAAACTTGCCTTTTTGTGGCCCTAATAGAGTAGGTAGTTTTCACTGTGATT
+TTCCTTATGTCATGAAACTTGCTTGTGTAGACACTTACAAACTAGAGGTTGTAGTCACTG
+CTAACAGTGGGCTTATATCCATAGCTACCTGTTTCTTATTAATAATATCCTATATTTTCA
+TTTCGGTAACCGTCTAGAATCCTTCTTCAGGAGACTTATCTAAAGCATTTGTGTCATGTT
+AGATCACATCACAGTAGGGATTTTGTTTTTTATGCCATGTATATTTCTGTATGTGTAGCC
+TTTGCCTAAAACAACACATGATTAATATTTGTTCATTGTTCCTTTTGCTATCACCCCTGT
+CTAGGATCTACACATTAAGAAACAAAGACATGAACGTCTCCATGGAAAGACTGGGAAAAT
+GGATTGCAGGTTCTAGCAGGATGTCATAATAAATGGTGCATATCCAGAGTGCAAGATGAT
+TCAGTCTCACCAAGAACACTGAAAGTCACATGGCTACCAGCATTATTGTGATAAGAACTA
+CTATTTTGGGAGATAGTTTAGCAAAGGTGCCATGTAGAAATTGATTAAGTCAGAGGTATC
+TTTAACTTGCCACCACAGAGAAGAGATTAATTTCATATACTTCCATTGAGAAGAGAGATA
+AGAATACAAAACCAAGCTGATTTGCAGGAGTAAACTTGATATTCAAATACTATTTCCTGA
+ATGACATTTTCTGAGACATGCTAATTGTAATTACTTTCAGCTTCAAAACATAATAAATTT
+ATCTCATAGTAAGCATATAGATGGAATAAATAAAATGTGAACTTAGGtaaattataaatt
+aataaagtatatttttaaaatttCCATTTTAATTTCTGTTTAAATTAGAATAAGAAACAA
+AAACAACTATGTAATACGTGTGCAAAGCCCTGAACTGAGATTTGACTTTACCTTGAGCTT
+TGTCAGTTTACGATGCTATTTCAGTTTTGTGCTCAGATTTGAGTGATTGCAGGAAGAGAA
+TAAATTTCTTTAATGCTGTCAAGACTTTAAATAGATACAGACAGAGCATTTTCACTTTTT
+CCTACATCTCTATTATTCTAAAAATGAGAACATTCCAAAAGTCAACCATCCAAGTTTATT
+CTAAATAGATGTGTAGAAATAACAGTTGTTTCACAGGAGACTAATCGCCCAAGGATATGT
+GTTTAGAGGTACTGGTTTCTTAAATAAGGTTTTCTAGTCAGGCAAAAGATTCCCTGGAGC
+TTATGCATCTGTGGTTGATATTTTGGGATAAGAATAAAGCTAGAAATGGTGAGGCATATT
+CAATTTCATTGAAGATTTCTGCATTCAAAATAAAAACTCTATTGAAGTTACACATACTTT
+TTTCATGTATTTGTTTCTACTGCTTTGTAAATTATAACAGCTCAATTAAGAGAAACCGTA
+CCTATGCTATTTTGTCCTGTGATTCTCCAAGAACCTTCCTAAGTTATTCTACTTAATTGC
+TTTATCACTCATATGAATGGGAATTTCTTCTCTTAATTGCTGCTAATctcccccatcttc
+aaatactctaccgggcttctggaacaccacagcttcctggctttttctcctacctcctgg
+gcaagtccttccctgtgtcttttgttgagtgttcctcatctgcttaactaccaatcaacc
+tattgcccctaatttgatctttggcctgttttcacttagattctatccctacgtatcacc
+cattcccacagctttaatcaccatctaaacactaggggctctcaaaccttgtatttttct
+ttctttctttctttctttctttctttctttctttctttctttctttctttctttcttcct
+ccttttctttccttttctttctttcattctttctttcttttttaaggggcagggtctcac
+tatgttgctgaggctggtctcaaactcctgacctcaagcaatctgtctgcttcagcctcc
+caagtagctgagaatacagggacaagccattgcacctgaccctggtactatttcttgagt
+tcctgatccacagatctaacctcctactttcctggatgccacacaagatcttccactcaa
+caagtctgcaactaaactagccttcctcttttcaaacctactcttctttcagtgttctca
+gtcacaataatttgtaccaactagttacctagttgcacaacccaaaatctgggaaaaata
+atagatttctttctccatagtacccccaaatcaataaatcatcaagtcttattctacctt
+ccaaagagccttacatatgttcctttattttcatctgtaacaccactattcctgtctaag
+cctacctatgtcatttttggaagagaatatagtcacctatgcgaccttcccacttaaaat
+cctactatttacgcttcagtaaaagaaaaaaaatttttaatctaagtatgtaattctttt
+gctgaagacacttcacttgcttctgtgcccttaaactggtatgttatcatggtatagtag
+gccatccaagacctggcttccttcctttttttcagtctcagagaataacatactctttcc
+ctgcaactccagatccaatttggttttcttttacttgcctggaaactccaaaatctatca
+actctggggctttccactagctaatcattttgtatacaatatttgtccttcATGTTTTGC
+CTCTTAACATCTCAGCTTTCAGTTTCATCATTTTACCAGGGAGGCCTCCCAGAACCTGAG
+TCCAGAAGAGTTCCTTCCATTGTATATTCCTCTAGCACTACCTATTACCTCTTTTGTAAG
+ACTAACAGCCCTCAAAATTTTTCATTCAGTGATGTCTTCCTCATTGCATTTTAAGTTCAA
+CATGAGCAGGACTTTGTCGTGTTCACCTCTATCACATCATAAATATAGCAAACAGTAAAA
+CTATTGCAACATGACTAATGTATTGAACGATGCTTCAGCTTTCTTCTTACGTTCAATCAC
+AGGTCATATGACTAAAGAACTTCCTTTTTAATCTCCTTTTCTATTCTCAATTAATTTCTT
+CTGCCTGCATCACCTCAAGTCTCTGGGGTGAAATCCACTAATGAATTCCTTTTGCAGCTT
+AAGCCAATTCCAATCTTGAGCCAATCTCAGGTGAAGAAGCCTGTAAATTATCACTCTCAG
+TCCTCTCTTGTACTACTAGGTCTCATGAACTCTTCATTAACAACTCCAGCTTCTCTGTTA
+GCCCAAAAGCCTTTTGCTGCCTAGAAAACCCATGATTCATGCCTCAGGAAACAGCCTTCA
+AATCACAACATGTTCTGTATCTGGCTGGCCAACTCCCTGCAACTTATTTCTGCCTAGATT
+CTCCCTCATTCATTTCAATACGCTGTTCGGCCTGCTACCCCAGTTTCCCACTTAGAACAA
+TGGCACACAGGACAGGAGCACATTGGCACATCAGAATGACTTATGTACTGCTCATTGTGT
+TGCAGAAGAGACCTCTGTGGGGGCAATAGAACAGATTTTCCTCTCACGTCACTGTAGTTG
+TGGTTTCCCTAAGCACCTACACTGTTTCACCTCATCTTAGGTAGACAATAATCCATGTAA
+CTGACTGTGTATCCTAATTTTAAAAAATATTTCTGCCCACATTATTCTGCAGTTTTTATC
+TTGCTTACGTATTTTTGGAATGTTACTATTTTTCAAAAATTAATTTGGGATCAACCAACA
+CTTCTTATTCTGCTGCTGTTCTAGAGAAAATCATTTTCCTCATTTCTGAACAAGAGAAAA
+TGAAATACAGCTCTAAACAAATGCCACTGTAAACCAAGGTGGAGCCTTTGCACTTTCAGG
+CCACCATGATAACCTGGAGATTAGATTTTTCTGTGTCTTTATATCAATAATAAAGCCAAG
+CTTCTCCAGGGGTATCCACTAGGCTTGTCTCAATGGCTCAATACAGGTCCTTTTGTGAAT
+GATTACCTCACCCTCATGGAAACACACTCTTGTTACAGAAACTCAGAATGATTCTATTTT
+TTCTTTTATATTTGTATATGTTTTTCCAATACCTCTGAAAAAACTGATCCAAAAAAAATA
+CAAATTTTAATTGTAGCCAGTCAATTCAGGAAGGATAAAGGTCAAAAACTTTCAAAGAAA
+CCTTCAGCCCCAACACACTAAACTTTGGGAGCACAGGTTGGCATCCAGAGGTAAACATTT
+GCTATAACTGATAACAGGAGAAGGATCCATTTATTCACCTGTTATCAATTACAGGCATTG
+TATTTAAAGATCAGATGTTTTATATTTATTTCTTCAAATTTCATTCATGGTGCCATAAGT
+GAAGGTATCTCTGTCCACCCTGAATATATTTTCACTCCCTCATCTCAGTCATTCCGAACA
+ATTCACACACTAAGATTACCCATGCTAAATGGGGATTCTTTTTTACTAGCCAATGTAGTA
+CCTCAAATCCTTCCTTCCCTCCCCCTATTTCATCAGCAGGCAATTCTTTTGATACTTTTG
+TCAAGGGGAAATTGTGTGACTCAGAGATCTAGTCCCCAAGAGAAACTAATAATGGGCTGG
+GTATTGTCTGTCTCAGCAGCATCAGTGGGTCCCTCTCCTGTGCAGCTAATTAGCTTCCTT
+TCCAATATGAAGAATCTTATATATAGCTTTGTCTTTGGGGTATTACATAAATGAAGATTA
+AGCTATCTGAATTTCTCCTTCTCCTAAAAATGCACATCCTATGACTGAAAAGACAGGTAA
+AAGAGATGCTTTTAATTACAAAACTTTCCCTGTCGTGGTTGCTTCTCTCTATCCTTCTAA
+ACTCCCTTTCAATTTCTTCTCTTCTGTAACATATTTGTGCCCAAAATCTTCTGCTTTCTG
+AAATATTTTATCTTTTTCTTCCACACTATCTCTTATTTTCCAATTTTAATCATTAAATTA
+TATTATGTCTTATAAAACTAATCCCACATATAAACCCCTATGATAATTTCAGTTTGTCCC
+TAGTATGAAGTTCTTTAAAGATGTGTAGTTTTCTAACTTTCATGCTCTCCAATTAATTAT
+AAACTTCATTTTCCACTCTGAAAAGGAGATGTCTGATCTCAGCTATTTCCATCCTATTTG
+AAAACCAGATTTAGTTTTAAACCAGAGGAAGGGAATCTCAAGTCTTTACCTCCCACAGTC
+TGGTGTGATTCTCTCTCTTTTGGTATTACCTTCCTCCACATTGGAACACTCCAGCCAATG
+CATAGGCTGAGAGGCTATCTCAGATTCAGAAAGATTTGGCCTCATCCCAGGGGAGGGTAC
+AGAGGAGCTGATGACTATGAATTCTGAAATGGAACTGTTCCAGGTTGAAGAAATAAGAAA
+GGGAATTGGGAAGAGCAATGCCCAGTGAAAAAGAAGAAATAATATTTTAGGAAGTGAATG
+CTAATTTTATTTTAAACAAAATAAGAACTCAAGGAATAAGAGGGTTCTTCCAATAGGTTA
+GAGTGATCCTGTCAAACATATATGCTTCTAGATTTTTTTAAAGACTGTTTCTACTAAGAA
+AGCATAGACCGCTATTGAGAAAGATCATTAAACTGGAATTTAGGAGGTCTGCCTTCTGAT
+TCTGACTTCTTGAATGTATTGTTAGCCATTTAACCACACTGTGTTGTTTCTCATTCTACC
+TGTAGAATCTCAAAGTTCTTTCCCACTTCTATACAAAACTATAATTCTGAACATCCTTTT
+TGTTTAATATAAGTCTGCATTTCCTGTTTGAAGATATGTGTCCCAGACCCTAAATGACTG
+ACAAATTTTAAATCTCCAATAGGAAAGATGACAAACTCTATGGAAACTTGGCTTCTGAAG
+AACTCCTAGAAGCTTTCCAAAGTCATCAGTGTTTCCTAAGAAGGCAGAGAAATCAAACAC
+ATGGTCTTTTCCTCCAGACAAGCTCCTTTGGGTCATCAGGATTTCTTCAACAATAAAATG
+TAATAATTCCAAATGTTTGTAACAGAATGGGTAGGACTTTCTTCACTTATTTAAATACTC
+CCTTTTTTATGCAACTGAGTTTTCATCAACAAGTACAAGCTTGTGAAGGAGTACTTTAAA
+ATGCAATTTCTCTCTATTTTTGTGGGGGCTAATATTTTATTTCTCATATTGACAATTTAT
+TATGCTGTTTTTAAAAAGttcattcatcaagtatttcttgagctttttctatgagacagg
+cactgttttaggcaagtaattatgcactgaacaatgcaaaaagtttccctgcactcatgg
+actttaattttaCATTTATGAAAAGCTACAAATATTAGAATAAGTAAAATACTGCCTGGA
+GGCTAAAGCATATTTTGATCACTTATTCCCTAATTCTTTTAGAAGAGAACTCACCTGTCG
+GTTAGCTGAACCACTGCCAGTGATATCCAACTATACATTCAATCCCACCATACCTCATTA
+TCACACCTATTCACTCACAAGCTTAAACTCTTAACTTTTCTCCACATATCAGTGACTATT
+TCCTACAGCTTTTCTTTTACTTTCCATGTTTGCAGTGACAATATACATAAACAGTGTATG
+AAAACTCAAGTAAAATCTACTCTCTCAGGTGTTCATAATGTATCAATGTATATTGCTTTA
+AGCCTGAAGGTAACCTAAGTAAAGATGTACCATGTTCCACCAATGCTTCTTTTGATCATC
+ATTTTATCCTGTTTTTTCTTTAGGATTCTTTCTTATTCCTTCCCCTGACCCTTCTTTTAT
+TCTCCAAATTTCTTTCCAATTCATCTTTGTTCTTCCCTTTCCTTTTTACTCTCTTTAAAC
+ATTCTATGGACTCTGCCTCCTTCACACTGATATTGAACGCCCATAGTTTCATATTTTGGA
+TTGCGATTGTTTTATTTTAAAATGGCAAATGTTCATGTTATAAAGAGAATTTTTCAGTCT
+TTAGACTAATAGGTTCATGTAGTTTGGGATTTTCCTCTTTAAGAAAATTAATTATCACTC
+ACACTCCAAGACAAACACCATTTCAGTAGCAATATGAATTTCAGTAGTAATAGGAATCTC
+CAAATATGACAAAGTAATTCAGACATTAATTGCTTTTGTTTTGGAATTGCTCTTATAAGA
+TGAAATATCACTTTCATGATGAGAGTCCTAGAGTGCTTGGTTTATATATTGTATCTTAGT
+TTTAACAGGATAAAACACTTGATCCTAAGCAGTAAACATGATTCTTCAGCTTCAACTTCA
+TTTCTTTATAAATAACTATTTATGAATTGGTGTTGAGCTTAGTAAGTCACCAAACACCTT
+CTGCTCAGCAGCATAAAGGACATTTCCATGAAACCTCCCAGGGATAATCTTATTTACTCT
+ATAATGTTTCCCGGGTTCAATTCCTCTCCCAAAATTCTTTGTTCTTAAGCCCCTATGATC
+TGGGTGATCTAAATATGGGTAAGAAGTCCAGGGATAGCACTATGAATGAAGTGAAAATAG
+TAAAACATAGTTAAAAATGTAcagatgctctctgacttataatagggttacgtcctgata
+aatccatcataagtcaaaaatgcatttaatattcctaatgtacctcacatcatagtttgg
+cctagcctaccttaaatgtgctcagaacactttcattagcttatataagatcacctaata
+caaagcctattttataataaaatattgaatagctcacgtaatatactgactactatactc
+aagtacagtttcttctgaatgcatgtcactttctcaccattgtaaagtcaaacaattata
+agtcaaactatcacaagccagggaccatcCATATGTATTTCATTCAGAAAATGCTGGAAA
+GAGCATTTCGGAGAATATCTAGATGAGAGAAGGTAGAAAGCCATGCACAAATTCACTGAG
+AGTTTAAAAAAATACATGCATATTGTGGAGATAGAAATCAAATCTATTTGTCTCCATCTG
+CTGTATTCTTCCCAAAATATTATCTCTTCTTATCCCATTGTACTATATTGCATTTCTTTG
+ACCATTTATTGTGTATCTCTTAATATTTCCCACTTCATCATTACTAACCTCACTCACTCT
+GAACTTGATGAGAGCACCTGAGCATTAATTTTTCTTATAATTATTTAATGATTACCAGAA
+TTCGTTCAGTATGGCCAGCTCTGGTCAAAGTGAGGCAGGCAAGATGCTTTGTCAACTGCC
+TGGATGGAATGTCTCAAAAGGTTTCCATTTCATGGTAGCATTATGCAAAGTTCAAGACGT
+TTAATCAAGACCCTTCACTTACTTAACTATACCTCCTTGAGAATCCCATCTATGAAAAAA
+TTCTAGTCATTATAAAAATGATTGATTAAATGAGGGAAGTAGTAGAGTTCTTCATTTCTT
+TAGTTGGTTTAGTCTCCTATGAGTCAATCCTATTTTCAAAATTCTTAATAAACCATTTAT
+TCCTTCAACTTTCTATGCCATTTGATGTTTTGTAAAAAAAAAAATATAATATGTATACAA
+AAAGATATTTCAAAATCTAGAAAGAGAGCTTTAGAGCTTTGTAAAGCTCTTTTAAAAATC
+AAAAACAACTACTGTTAATTAACATGTTGTACTATGCAATTTGTTTACCATTATTACTCT
+TGGTATTTTTAAGAAAAGTCTTTCCATTGTTATTATAAATGCTTCTATTGATATTTATTT
+TAATAACTGTTATTACAGTCCGTCATGTACATACACTATACTTAAACCTAATGTTTGGTA
+TTTAAATCGTTTCAAGATTTTATCACTGTCAACAAAGTATGATGAATATTTTTATGCTGA
+AAACTTCTGTAAAAatagaattccaagagtattattgcaccaaaaggcatggacttaaaa
+ttcttgatacatgatttcaaaatattttctttaaggtttgaatcagtctatattccctcc
+agcagcgtataaaagtgccaatttctctgatccttaGCCAGTTTGGGTAATAATAATTGT
+AAAACttttttttctttttttttgagacagagtctccctctgtcgccaggctgaagtgca
+gtggcgcaatctcggctcactgcaacctccgcctcccggggtcaagctattctcctgcct
+cagcctcccaagtagctgggactacaggcatgcaccaccatgcccagctaatttttgtta
+tttttagtagagatggagtttccccatgttggacaggatggtctcgatctcttgacctcg
+tgatccaccctcctcggcctcccaaagtgctgggataacaggcgtgaacaaccatgcccg
+gccTGTAAAACTTTTTCCTAATTTAACAGAAAAATAATAGTATTATATTTTATCATATTT
+CTTTGATTTCTAAGacacacatacacacacacacacacaTATCTGTATATACAAATACAC
+GTATAGCTTACATTTTAATTCTTCATTTCATTTGTTCATTTATTAGGTCTTGGAGATTTT
+GTGAAACTGTTTAAATTCTTTTTTATACTATGAAGATATCAACCTTTTGTCTCTACAGCA
+TTTCAAATTCAAGTATGATTCACGTGTTGGTTTGGGGTAGATCATTATAGGCACATGTAG
+GAAACAGCTTTCAGAGATGCCTTAACCGTAATTATGCATTTGTATTCTAATTTTTATTTA
+ATGTTATTATTGATTGCATTTTTAAAGATTCTGTATTTTTTAAACCATTTATTTGTATAT
+GTTGGTATACAATCTTGCCATTTTCTGGGATTTCATATTTCCTTATTTTTGTTTTTTACC
+TTTTTTGGCTTGAATTTTTTGAGTTTTTATGCATTCTTTTCCAGTTTCTTAAGATGCTAA
+TAAGTTCATGTATTTGAGCAATTGAGAACATTTAAAGCAATAGACTGCCTCTGAGCACAG
+CTTTGTCCATATTACATTAACCTTTTATACCCTGGGTTCCCACTAGTTTTTAAATAATCT
+ACTATCAAATAAAAGATTTGTTAATAATAAATTTTAAATCATTAACACTTAACGCATTAT
+TTTCAGTCACACTAAGTTGATTCCTTCGTTTCTTTCAGGTTGCTTCAGAGTCTTCCCTTC
+TATCTGATTCAGTGGACCAAGTAAATGACTCTCTGGTAACAGAATTTGTATTACTTGGAC
+TTGCACAATCCTTGGAAATGCAGTTTTTCCTTTTTCTCTTCTTCTCTTTATTCTATGTGG
+GAATTATCCTGGGAAAACTCTTCATTGTGTTCACAGTGATCTTTGATCCTCACTTACACT
+CCCCCATGTATATTCTGCTGGCCAACCTATCGCTCATTGACTTGAGCCTTTCATCTACCA
+CAGTTCCTAGGTTGATCTACGATCTTTTTACTGATTGTAAAGTTATTTCCTTCCATAATT
+GCATGATACAAAAGTTCTTTATCCATGTTATGGGAGGAGTTGAAATGGTGCTGCTGATAG
+TCATGGCATATGATAGGTACACTGCGATCTGCAAGCCTCTCCACTATCCAACTATTATGA
+ATCCCAAAATGTGCATGTTTTTGGTAGCAGCAGCTTGGGTCATTGGGGTGATTCATGCTA
+TGTCTCAGTTTGTTTTTGTCATAAATTTACCCTTCTGTGGCCCTAATAATGTGGGGAGCT
+TTTATTGTGATTTTCCTCGGGTTATTAAACTTGCATGCATGGACACTTATGGGCTAGAAT
+TTGTGGTCACTGCCAACAGTGGATTCATATCGATGGGCACCTTCTTTTTCTTAATTGTAT
+CATACATTTTTATTCTGGTCACTGTCCAACGACATTCCTCAAATGATTTATCCAAAGCAT
+TCTTCACTTCGTCGGCTCACATCACCGTAGTGGTTTTGTTTTTTGCTCCATGCATGTTTC
+TCTACGTGTGGCCTTTCCCTACTAAGTCATTGGATAAATTTTTTGCCATCATGAACTTTG
+TTGTCACCCCTGTCGTAAATCCTGCCATCTATACTTTAAGGAACAAAGATATGAAGTTTG
+CAATGAGAAGGCTGAATCAACATATTTTAAATTCTATGGAGACGACATAACACATTTGGT
+TGATGAGAGCACAGGATAAATGCCATGGACCATCAAGACTCCTGTGATCACCATGATCAC
+TATGGAACGCGCACATTTTTAGTATTGCCTGAAAAAACTGAAAAATCTGCAAAAAGGATG
+CATTAAATCTAAGAATTGTATTTCAGATAAAGTTGCAACATTTTTTGTTAATCATAAAAA
+GTATATATTTCTATCTAATGTGTGTATCTAATTAACAGCAATGACTACCTTTAATTTTGA
+TGTAGTTATTTTATATCTGTATATAAGCACATACACATATATATGACCTAGGTTTATTTA
+TCAGTATTTTTATGCTGATAATAAGCATCACTGGAAATTAATTTTCTTATGGAAATTATG
+TGGATCCAATGGATAAAATATGAGTTTATATAAATTAGTAAATGCCAAAATCAAGGAAGA
+AACAATTTTTATTTTAATTGTACTTTAAGTTAGATAAATGGTAAGGTCAACAGCTTGTTA
+CAACCCTTAAGTATTATTTTCAGGCTGATTGTCAATATGTTTTGTACAatgttctcactt
+ataggtgggaattgaacaatgagaacacatggacacaggaaggggaacatcacacaccgg
+ggcctgttgtggggtggggggaagggggagggatagcattaggagatataactagtgtta
+aatgacgagttaatgggtgcagcacacccacatggcacatgtatacatatgtaactaacc
+tgcacattgtgcacatgtaccctagaacttaaagtataataaaaaaaaaTAGACTCTAGT
+ACTCTGTATTATGCAAAATTTGTCTATGTTACACTTTTTTAACAACACAATCCTATTGCC
+CTTGAAATCTTCTTCAAAGCATTTCTCGAGTCACTCTTAAAAAGCATCTACAACCTAAAA
+GTATAGGAAGAGATTTATTTCCTGGAGAAGAGACCCCATTGAGATCTTAAAAGCACATTT
+AATGTGCCTGTGCTTAACTTAAGGTGCTTAGGACAAAGAAGGCGATTGACATCTTTCAGG
+TAAAACCTGGTAAGTTTGGTGGTCAAGGAACACAACTGAGACATCACTTGGATGTATTCC
+TATGACTATTTTAAGAAACATAAATTGTGGTGACTCACTCAGCTCACTTTTAACTACTGC
+ATGGTAATTAAAGATGCAAAATAAAATAAGTTACAAGAAGTGAGGTTTTTTATTGGTTAA
+AGCAATTTTTCTATATTTTCTCCGCAAGTTGGTCATAAAAGTTCTAAGCATTCCTCTTTT
+TATAAAATCGAAGCATTATTACTTACTCTCTTGTTAACCTATCTGGATTTTAATTTTGTA
+ACTTTATTATATTTGTTTTGCTGTGATTCTTTAAAAAGCACCTTTAGACTCAGTGAGATA
+GCAAAAATATCCAAATAGGCCAAAAAATTGTGGCAATGTCCTCTCACTCAGGAAAATTCT
+GTGTGTTTTCTCTAATGGCCAAGGGAAAACTTGTGAGACTATAAAAGTTAGTCTCAGTAC
+ACAAAGCTCAGACTGGCTATTCCCAGATCTCTTCAGGTACATCTAGTCCATTCATAAAGG
+GCTTTTAATTAACCAAGTGGTTTACTAAAAAGGACAATTCACTACATATTATTCTCTTAC
+AGTTTTTATGCCTCATTCTGTGAAAATTGCTGTAGTCTCTTCCAGTTATGAAGAAGGTAG
+GTGGAAACAAAGACAAAACACATATATTAGAAGAATGAATGAAATTGTAGCATTTTATTG
+ACAATGAGATGGTTCTATTAGTAGGAATCTATTCTGCATAATTCCATTTTGTGTTTACCT
+TCTGGAAAAATGAAAGGATTCTGTATGGTTAACTTAAATACTTAGAGAAATTAATATGAA
+TAATGTTAGCAAGAATAACCCTTGTTATAAGTATTATGCTGGCAACAATTGTCGAGTCCT
+CCTCCTCACTCTTCTGGGCTAATTTGTTCTTTTCTCCCCATTTAATAGTCCTTTTCCCCA
+TCTTTCCCCAGGTCCGGTGTTTTCTTACCCACCTCCTTCCCTCCTTTTTATAATACCAGT
+GAAACTTGGTTTGGAGCATTTCTTTCACATAAAGGTACAaatcatactgctagagttgtg
+aggatttttacagcttttgaaagaataaactcattttaaaaacaggaaagctaaggccca
+gagatttttaaatgatattcccatgatcacactgtgaatttgtgccagaacccaaatgcc
+tactcccatctcactgaGACTTACTATAAGGACATAAGGCatttatatatatatatatta
+tatatactatatatttatatatattacatattatatatataatatatattatataatata
+tattatattatataatatataatataaatataatataaattatattatataatatataat
+ataaatataatataaattatataaatataatatatattttattatataatataatatata
+ttatataaatataatatataaattatataatataatatatattatataatataatatatt
+ttattatataaatatatattatattatataatatatattttattatataatatatattat
+atatttatagaatataatatatattttattatataatatatattatataatatatattat
+atttatatataacatatattattatataaaatatgtataatatatattatataaatatat
+ttatatattatataaatatatatattatatataatTCTAATGGTTGAATTCCAAGAATAA
+TCTATGGCATGAAAGATTTTACCTGTCAACAGTGGCTGGCTCTTCATGGTTGCTACAATG
+AGTGTGTAAGATTCTGAAGGACTCCTTTAATAAGCCTAAACTTAATGTTCAACTTAGAAT
+AAATACAATTCTTCTAATTTTTTTTGAATAATTTTTAAAAAGTCAGAAATGAGCTTTGAA
+AGAATTATGGTGGTGAAGGATCCCCTCAGCAGCACAAATTCAGGAGAGAGATGTCTTAAC
+TACGTTAGCAAGAAATTCCTTTTGCTAAAGAATAGCATTCCTGAATTCTTACTAACAGCC
+ATGATAGAAAGTCTTTTGCTACAGATGAGAACCCTCGGGTCAACCTCATCCTTGGCATAT
+TTCATGTGAAGATATAACTTCAAGATTGTCCTTGCCTATCAATGAAATGAATTAATTTTA
+TGTCAATGCATATTTAAGGTCTATTCTAAATTGCACACTTTGATTCAAAAGAAACAGTCC
+AACCAACCAGTCAGGACAGAAATTATCTCACAATAAAAATCCTATCGTTTGTACTGTCAA
+TGATTAGTATGATTATATTTATTACCGTGCTAAGCAGAAGAGAAATGAAGTGAATGTTCA
+TGATTTATTCCACTATTAGACTTCTCTTTATTCTTAAAAATATTTAAGATCACTAAATTT
+TTATAGGACTTTAAAAACAGTAATGTGCTGCTTTGAGTGTGTAGGACTAAGAAATGGGAT
+TCAGAGTAGTAAAGAGAAAAGTGGAATTTCCAAGCACTATGAATTACTGTTCTTTAAAAA
+ACAGCAAAAATCAAATAACAGTATTCCTCCAAAAAAGATGGCAAGTGTAAACTCTATACC
+TTCATGTCTCCCGTGGAATGTTAGTGATCAATTTCCACTTCTCTCTTTTACATCTTACTT
+GCCCATTAACTCTTATACCTAATCCAAAGATTGTTAATATGGCTATGTCTCACTTTCAGG
+ACACCTTTTATTTGTTACTTCTCTTCACTGCAAAACTTCTTGAAACAGTACTTATTTTCT
+CTCCTCCATACACAATTGAAATGGCTCTCAACTCATGCCCAGAAGTCAGTGTTCAGTCTC
+TCACCTGGCAGATAGCAACTTACAAAGATGCCCCAACAATACCTCCTTGTGTCTAGACAG
+TCATCATTATCCTTTACCTTTTTCTGTATTTATTTCTGCTCCTAAAAGGGATCTCTATGT
+AAAGTATTGTTATACTAGTGCTTGTTATAATTATTATCAGAGTTAAAGCCATCACAATGT
+TCCCAATTACTTAAAGACATTGGAATAACATTTTTTTTATTTTCCACATCTTGCCAAAAA
+ATATTTTGTTATCAGTACCTTaataatggctattatatattgaccattactatttgctag
+aaaatttatatacctggtcgtatccaatcctcacagaacttctataaagttgtgctatta
+tcacctatattttccagatgtggccgtaagactgaaatcacttaggtgacttgtctaagg
+tcattcagatacatagtagataacccaggatttgaacacaggcctcctagcacacaagct
+catatcttaactactttaatacgttgctcGATGGGATCTTACAGGTCTTCATTCACCCCT
+TTCCTGCTCACACAACCACAACCTGCAGCTATTACCTATTGTTAGGCTTAAAATAATTAC
+TTGGCTTCATTTCCAAGCTCCCTCCCTTCCAATTCACATTGAGTCCAGAGCTAAATTAAA
+CAATCATTCAAAATTTTTCAGTAGTTCTTGTCTCTATAATAAAACAGAAATGCTTTAGAA
+AGCATTCCAAAATCTCTTACCAGTTTTATCTCCTATGAAAGTCCTTCACactttctctca
+tttaaactttattgcattttcctcactttttctcacttcacttttgaattccctattctt
+ttatcctctgttaatttttaagtattatatttgtgatattattttttctttttttctatt
+ttttatctttcatttcattttggcctatttttttctcttAAGAACTTTAATATCACCAAA
+TAACATGTGTGCTACAAACTGTTTTGTAGTTCAAAGAAAAAGGAGATAAACATAGAGTTA
+TGGCATAGACTTAATCTGGCAGAGAGACAAGCATAAATAATGGTATTTTATATTAGGAAT
+AAACCTAACATTAATGGAGACACTGAGAAGCCGAGATAACTGAATTATAAGGCATAGCCA
+GGGAAGTAGTGCGAGATAGAATTATGATCTTGTTGAATTCTGAATGTCTTTAAGTAATAG
+ATTATAGAAAGTCACTGTAAGAGTGAGCAGAATGATATAAAATGAGGCTTTGAATTTGAA
+TATAATAATTCTGACTTCCTTCTCCTTCTCTTCTTCAAGGTAACTGCAGAGGCTATTTCC
+TGGAATGAATCAACGAGTGAAACGAATAACTCTATGGTGACTGAATTCATTTTTCTGGGT
+CTCTCTGATTCTCAGGAACTCCAGACCTTCCTATTTATGTTGTTTTTTGTATTCTATGGA
+GGAATCGTGTTTGGAAACCTTCTTATTGTCATAACAGTGGTATCTGACTCCCACCTTCAC
+TCTCCCATGTACTTCCTGCTAGCCAACCTCTCACTCATTGATCTGTCTCTGTCTTCAGTC
+ACAGCCCCCAAGATGATTACTGACTTTTTCAGCCAGCGCAAAGTCATCTCTTTCAAGGGC
+TGCCTTGTTCAGATATTTCTCCTTCACTTCTTTGGTGGGAGTGAGATGGTGATCCTCATA
+GCCATGGGCTTTGACAGATATATAGCAATATGCAAGCCCCTACACTACACTACAATTATG
+TGTGGCAACGCATGTGTCGGCATTATGGCTGTCACATGGGGAATTGGCTTTCTCCATTCG
+GTGAGCCAGTTGGCGTTTGCCGTGCACTTACTCTTCTGTGGTCCCAATGAGGTCGATAGT
+TTTTATTGTGACCTTCCTAGGGTAATCAAACTTGCCTGTACAGATACCTACAGGCTAGAT
+ATTATGGTCATTGCTAACAGTGGTGTGCTCACTGTGTGTTCTTTTGTTCTTCTAATCATC
+TCATACACTATCATCCTAATGACCATCCAGCATCGCCCTTTAGATAAGTCGTCCAAAGCT
+CTGTCCACTTTGACTGCTCACATTACAGTAGTTCTTTTGTTCTTTGGACCATGTGTCTTT
+ATTTATGCCTGGCCATTCCCCATCAAGTCATTAGATAAATTCCTTGCTGTATTTTATTCT
+GTGATCACCCCTCTCTTGAACCCAATTATATACACACTGAGGAACAAAGACATGAAGACG
+GCAATAAGACAGCTGAGAAAATGGGATGCACATTCTAGTGTAAAGTTTTAGATCTTATAT
+AACTGTGAGATTAATCTCAGATAATGACACAAAATATAGTGAAGTTGGTAAGTTATTTAG
+TAAAGCTCATGAAAATTGTGCCCTCCATTCCCATATAATTTAGTAATTGTCTAGGAACTT
+CCACATACATTGCCTCAATTTATCTTTCAACAACTTGTGTGTTATATTTTGGAATACAGA
+TACAAAGTTATTATGCTTTCAAAATATTCTTTTGCTAATTCTTAGAACAAAGAAAGGCAT
+AAATATATTAGTATTTGTGTACACCTGTTCCTTCCTGTGTGACCCTAAGTTTAGTAGAAG
+AAAGGAGAGAAAATATAGCCTAGCttataaatttaaaaaaaaatttatttGGTCCATTTT
+GTGAAAAACATAAAAAAAGAACTGTCACATCTTAATTTAAAAAATATATGCTTAGTGGTA
+AGGAGATATATGTCAACTTTTAAGAGGTTGAAAAACAAACGCCTCCCATTATAAGTTTAT
+ACTTCACCTCCCACCACTATAACAACCCAGAATCCATGAGGGCATTATCAGGAGTGAGTG
+GAAGAGTAAGTTTGCCAATGTGAAATGTGCCTTCTAGGTCCTAGACGTCTGTGGTATAAC
+TGCTCATAAGCAGTAGAAAGAATTTAGAGGGATCCAGGCTCTCATCACGTTGGCACAAAG
+TATATTACTTGGATCCATCTATGTCATTTTCCATGGTTAATGTTTaaaagcacaggcttt
+aaagtaaaaaacaaagagctggattcaactctactgactcttattaatcatgattttggg
+cacattacgtagctttcatgagctttagtttctacatttataaacaggagattataccta
+ttatgcatggttattatgaaggaaaatgacaaaatagatataaatcaaatagcccacttc
+gagacatattaagcatgaataaacattagatactattaAAATCCTATATATTAACAAAGC
+CAAAAGTTTCAAACTTTACTTTTTCCCAACATTCTTGTGAAATATGACACATCCCAATCT
+TAACAGATGCTCATTTGGGATACTGTACTTGTGAGTGGAAGTGTGTATATTTGTGTGCAA
+GTGTGTACTCATATACTTCCACCTTACCACCCTAGAAAGGCATGATGAAAATTTAAGATA
+GAAGGAAAATATAAATTGAAAAAAAAAAACCTTAACAAATGATTCTGACAAATATCTTCT
+CTTTCCAGGGAGAATCACTGAGCCAGAATAAAATTGAACACTAAATATTCTAAGAAAAAA
+GGAATCTAGTTTGTCAAAATGTGACTTGAATTAATAGATAAGGAGAGTCAGATGATAAGA
+GGGTCAAAATTATGTTTATCTTAGGAAAAGTAGAATAGAAAATTTATAAGCAGATTAAAA
+ACACATAATAAAAGTAGTAAATAATAATGACAGTATCTCAAATcagtgcaggggggaaag
+gcctactaatgtgatggtgggataattggatagcaatatgggaaaagatatatttaattt
+atttgctacaccaaatgccaggacaatctctaagtgaattcaagacataactcttttttc
+aaaaaaactatgcaaatattaaaagaaaacaagttaatgtttttataatctatgaatatg
+gtaaagatGGATAACATTGACTATCAAATTAATTTTTAATGCGTAATAAAACTATGAGAA
+AATTTAAAAGTGAGAAGAAACTACTTGTAACTCACATAATAGActagtacttctaacaca
+tagggaacttctaaaacaaaacccaaaatattaataggaaaatgggcaaaacagttaaac
+ttacagttcataCATAAGGAGAATCAGTCTTTTTTTTTTTTTTTACAGTTGTAGGCAGAA
+AACTTTTATTTTTCATTTATTTGTAAAATTTACCCCTAATTTATTCATAATTCATTTAAC
+TGCTAAGGGCATTAATGTGTACAACGCCATGGGAGAAACCAGTATATTCAGAATTTCTCC
+TGAAATTTGACCAGAAGTTATGGGCATCCCTCCCCTGGGAAGGAGGCAGGCAGAAAAGTT
+TGGAATCTATGTAGTAAAATATGTTACTCTTTtatatatatacatatatgtgtgtatatg
+tgtatatatatatacacacatatatacatacatacatacatacatatTATCTGAATTAGG
+CCTGGTCttttttaatactttaagttctgggatacatgtgcagaatgtacaggtttgtta
+cacaggtatacacctgccatggttgtttgctgcacccatcaactcaccatctacattagg
+tatttctcctaacgttatccctctccttgcctcccacctcccgacaggccctggtgtgtg
+atattcccttccctgtgcccatatgttctcattggtcaactcccatttatgagtgagaac
+atgcggtgtttggttttctgttcttgtgttagtttgcggagaatgatggtttccagcttc
+atccatgtccctgcaaaggacatgaactcattcttttttatggctgcaagaaatgcaaat
+caaaaccacaatgagatgccatctcacaccagttagaatggcaatcattaaaaagtcagg
+aaacaatagatgctggagaggatgtggagaaataggaatgcttttacactgttggtggga
+gcgtacattagttcaaccattgtggaagacagtgtggtgtttcctcaaggatctaaaact
+agaaataccatttgacccagcaatcccattactgggtatatacccaaacgattgtaagtc
+attctactacaaagacacatgcacaggtatgtttattgcagcactattcacaatagggaa
+gacttggaaccaacccaaatgcccgtcaatgttagactagataaaatgtggcacatagac
+CTGGTCTTAAAATCAAGAACAGAGATTGTTACTTTTACATCCATTCCTAATTGATAAACC
+ATTCAGTTATACCACATCTTAGCTTCTGGACTACAATGACCATATTTGGGGttttctttc
+taatttcattataggttcagagggtacatgtgcaggtttgagacaaaggtatattgcatg
+atactaaggtttggagtacaaatgattccacctcccaggtagcaagaataatacccaata
+tgtagtttttcaactctttcccctcttcctccatcctccctctgctactctgtggtgtct
+gtttttctcatctttatgtccatgtgtactcgatgtttagctcccccttgttaggtgaga
+acatgtggtatttggttttctgtttcagtgttaattcacttaggataatggcctccaact
+gcattcatgctgctgcaaaggatgtgactttcttcttattagctgcatatattttgtggt
+ggatttgtaccacatttactttatctagtccaaagttgttgggcacccaggtggattcca
+tgtctttgctattgtgaatagcactgggacaacccatacaagttcatgtgtctttttggt
+aaaacaatgtattttcctttgggcatatatgcggtgatggaattgctggatcgagtggta
+gtttaactcttagttctttgagaaatccccagactgttctccacagtggctggactaagt
+tgcattcccaccagcagtgtagaagtgttccccattctctgtagcctcaccagcacatgt
+tAAACTATCTttaaatatatgaaaaaaatgttcaagtctctcagattaagatgcatgcaa
+agtaaaatgatacttaaatatcagttctaacctataaaatatcaaatatctgacctcaat
+atttgataatccaacctgttgatgaagctgtagagagaggcaccctTtttttttttttta
+attatactttaagttttagggtacatgtgcaccttgtgcaggttagttacatatgtatac
+atgtgccatgctggtgcgctgaacccactaactcgtcatctagcattaggtatatctccc
+aatgctatccctcccccctccccccaccccacaacagtccccagagtgtgatattcccct
+tcctgtgtccatgtgatctcattgttcacttcccacctatgagtgagaatatgcggtgtt
+tggttttttgttcttgcgatagtttactgagaatgatgatttccagtttcatccatgtcc
+ctacaaaggacatgaactcatcattttttatggctgcatagtattccatggtgtatatgt
+gccacattttcttaatccagtctatcattgttggacatttgggttggttccaagtctttg
+ctattgtgaataatgccgcaataaacatacgtgtgcatgtgtctttatagcagcatgatt
+tatagtcctttgggtatatacccagtaatgggatggctgggtcaaatggtatttccagtt
+cgagatccctgaggaatcgccacactgacttccacaatggttgaactagtttacagtccc
+accaacagtgtaaaagtgttcctatttctccacatcctctccagcacctgttgtttcctg
+actttttaatgattgccattctaactggtgtgagatgatatctcattgtggttttgattt
+gcatttctctgatggccagtgatgatgagcattttttcatgtgttttttggctgcataga
+tgtcttcttttgagaagtgtctgttcatgtccttcgcccacttgttgatggggttgtttg
+tttttttcttgtaaatttgtttgagttcattgtagattctggatattagccctttgtcag
+atgagtaggttgcaaaaattttctcccattttctgggttgcctgttcactctgatggtag
+tttcttttgctgtgcagaagctctttagtttaattagatcccatttgtcaattttgtctt
+ttgttgccattgcttttgTCccaccgatcccacagaaatacaaactaccatcagagaata
+ctacaaacacctctacgcaaataaactagaaaatctagaagaaatggataaattcctgga
+cacatacactctcccaagcctaaaccaggaagaagttgaatctctgaatagaccaataac
+agaagctgaaattgtggcaataatcaatagcttaccaaccaaaaagagtccaggaccaga
+tggattcacagccgaattctaccagaggtacaaggaggaactggtaccattccttctgaa
+actattccaatcaatagaaaaagagggagtcctccctaactcattttatgaggccagcat
+cattctgataccaaagccaggcagagacacaacaaaaaaagagaattttagaccaatatc
+cttgatgaacattgatgcaaaaatcctcaataaaatactggcaaaacgaatccagcagca
+catcaaaaagcttatccaccaagatcaagtgggcttcatccctgggatgcaaggctggtt
+caatatacgcaaatcaataaatgtaatccagcatataaacagagccaaagacaaaaacca
+catgattatctcaatagatgcagaaaaggcctttgacaaaattcaacaacccttcatgct
+aaaaactctcaataaattaggtattgatgggacgtatttcaaaataataagagctatcta
+tgacaaacccacagccaatatcatactgaatgggcaaaaactggaagcattccctttgaa
+aactggcacaagacagggatgccctctctcaccactcctattcaacatagtgttggaagt
+tctggccagggcaattaggcaggagaaggaaataaagggtattcagttaggaaaagagga
+agtcaaattgtccctgtttgcagacgacatgattgtatatctagaaaaccccattgtctc
+agcccaaaatcttcctaagctgataagcaacttcagcaaagtctcaggatacaaaatcaa
+tgtacaaaaatcacaagcattcttatacaccaacaacagacaaacagagagccaaaccat
+gagtgaactcccattcacaattgtttcaaagagaataaaatacctaggaatccaacttac
+aagggacgtgaaggacctcttcaaggagaactacaaatcactgctcaaggaaataaaaga
+ggatacaaagaaatggaagaacattccatgctcatgggtaggaagaatcaatatcgtgaa
+aatggccatactgcccaaggtaatttacagattcaatgccatccccatcaagctaccaat
+gactttcttcacagaattggaaaaaactactttaaagttcatatggaaccaaaaaagagc
+ctgcattgccaagtcaatcctaagccaaaagaacaaagctggaggcatcacgctacctga
+cttcaaactatacgacaaggctacagtaaccaaaacagcatggtactggtaccaaaacag
+agatatagatcaatggaacagaacagagccctcagaaataatgccgcatatctacaacta
+tctgatctttgacaaacctgagaaaaacaagcaatggggaaaggattccctatttaataa
+atggtgctgggaaaactggctagccatatgtagaaagctgaaactggatcccttccttac
+accttatacaaaaatcaattcaagatggattaaagacttaaacgttagacctcaaaccat
+aaaaaccctagaagaaaacctaggctttaccattcaggacataggcatgggcaaggactt
+catgtctaaaacaccgagagaggcactcttatgcattgttggtgagaatacaaaatggta
+caactcttggcaatatcttaaaaaatttacatggtactgacttttggtctagcaatccta
+cttctatcctaaagatatattggcaaaaatacaaaataattgatgcactcaagtctattc
+attgaagcattgtttttcatagtaaacggaaagtaggccgggcgtggtggctcatgcctg
+tgatcccagcattttgggaggctgaggcgggcagatcacttgaggccaggaattcaagac
+cagcgtggctaacatggcgaaaccccatctctaccaaaaatacaaaaattagctgggcgt
+ggtggtgcacacttgtaattccagctacttgagaggctgaggtgggaggatcgcttgaac
+ctgggaggcagaagtttcagtgagcccagaacgtgcctctgcactccagccaggatgaca
+gagcaagactccatctcaaaaaaaaaaaaaaaaaaaaaggaaaataaccaaatgacaatt
+agtgagtactacttgcaaaacttgtacgcaatagagtatgaagcaactataaaatgagag
+agaaatatctccaaatactactctaaagtaatctacaaggtataccttaactgaaaagaa
+acaaaaaagtgacaccagaatgctatttttatgttaaaacagggataaataCATTGGATT
+TACATGCatatataagtatatattttataaatgtttaaataaGCATACTTAAAATGGCAA
+AAACGTAATACATATATAATTTTCTTATGGCAGGAGGAGGAAACAGGGCAAGGCACAGGG
+ATAAAAGTTATTCTGAATACATCTTATTTTATATTTTTGACTTTGAAATCCTGTAGCTGT
+TTTATGTAATATAAAAATGTAATTAAATTAACAGAAAAAAATTACAACTGCTAAAAATCA
+AGATCTGGCATTTTAATTAAGTTATAAAACATCGGAGAAAAGAATTGTTTCATGGGACAC
+TAACATACAGACAAATTCATTTGGAACCCAATGAATTAATGGGCCTAAGATAACAACCAA
+TAGAAGCTAAAATGACGAATAACTGTTTCAGAAGAAAACATATATGGAATGAATCAGCTG
+AAAATACCTGAACCTACTGATCAATTTTTATATCACATGAAGTGAATACACATAAAGTAT
+AATATGGAGCACATAGAACCAACTAGAAATGAGCCTAATTGTTAAATATTCTCTATTTTA
+TGAcaatatacaggaaatatgtcgaagagagaaacatgcaagaacaccgtagggtttaat
+aagataatcacaaggtatggaatattcaacaggatgagtatcctggattattcagcaaat
+acacagagctaaaaagcaggagaaaggaattcatatatatttttaaaaactaaaaagata
+tattagctgatgcaactttgaaacttctttagatcctgattcaaatagagcaaatttaac
+aaatatatttgaaactattaaaataatttaaaaatgaccaagtatttgattatatcaaat
+atagacaataataaccttgaatgtacatggattaaatgtccacttaGGggctgggtgtgg
+tggctcatgactataattccagcactttgggaggccaaggcagaaggattgcttgaggtc
+agaggttcaagtgcagcctggtcaacacagtgaaaccctatctctacaaaaaacaaacaa
+aaataaaaaaTTAACtaattttaaaaaatatatatttCTTCtaaattctccacctgaaag
+atatagactgactgaatgaattttaactatgatctgactatgtgcttccctgaacaaatg
+cactttacctgtaaaacacatattaactaaaagaaaagagatggaaaaaggtattccatg
+aacagaaaccaaaatgagtaggagtagctatacttctgtcagacaaaacagactttaagt
+caaaactagctttagaaaaaagacaaaaatgcttattatacaacgataaaggaatcaatc
+cagaaagaggatataacaattttaaatatatatgcagccaacactggagcagccagattc
+ataaagcaaatactactagatcaaaacagagaggtagactcaaatataataatagtgaag
+gacttcaacaccccactttcagcattaaacagatcatctaataagaaaaccaatctcgca
+gccctcaccctggagagtccacaggtaccaggggttggtctgaacccccagcacagagca
+cctgcctcacagaagagtggctgcatttttcttcctgcagttttcagtcctcacttctcc
+ttaccaagcagggccacctggcctgggactccggtacaactaccctgccccccacctgac
+gacttcaataagaagtagcccagcatttctccaaggaggaaataccagagtcaattcaca
+accactgcaattgcagtggtaccaccataacagcccttgggctgcagaaggaactaagag
+tctagtcactacagtggcaccttcagcacaccacagccaccatacagagaggaatccagc
+cccctcccctgggaacccccaccacccactccaccaggcacagcacccagctcataactg
+cagatcagttgccccacccacagctgagcttacctactggcagtggcccagactttccct
+agggagaggctcccagaggcaaacggcagcctctctgcccgtgtcacagcagcagttcta
+tccatgctgtcctcaggcttggaaagaaacaaagcgcctgaaggctgcacctgaacttac
+agcatgccacagttcccatatggagaggagaccagtctctcctcccagtgagccctaaac
+cccctgatccccaacaagcagagccctaacctcacaccagcagtacagctgccccatccc
+ccaggctgaacattcccagtaatagcagctccacctggagatggaacccccagggtcaac
+taaaagcccctctgccactgcctctacagtggtactacccctgctacccttgaactaaca
+aaggagcaaagaccccagtgctttatccacacctccaacaagctgcagtcgaccacaaag
+aagaaacacgtctgtctcccatgggtcctacccacaccccctgctgttcaccatggatga
+tagagtcaacagtgtgaaaacgaccatactgccaaaagcaacctacaaattcaatgcaat
+tcccatcaaaataccaccatcattcttcacagaactagaaaaaacaaggctaaaattcac
+atggaaccaaaaaagagcccacatagccaaagcaagactaagcaaaaagaataaatctag
+aggcatcacattactcgacttcaaactatactataaggccatagtcaccaaaacagcatg
+gtactggtataaaaataggcatatagaccaatggaatagaataaagaacccagaaataaa
+gccaaatactttcagccaactgatctttgacaaagcaagcaaaaacataaagtggggaaa
+ggacaccctattcaacaaatggtgctggtataattggcaagccacatgtagaagaatgca
+actggatcctcatctctcaccttataaacaaatcaactcaagatggttcacagacttaaa
+tctaagacctgaaaccataaaaattctagaagataagattggaaaaacccttctagacat
+tggcttaggcaaagacttcacaatcaagaacccaaaagcaaacacaacaaaacaaagata
+aatagatgggacttaattaaactgaaagccttctgcacatcaaaataaataatcagcaga
+gtaaacagacaacccacagagtgggagaaaatcttcacaaactatgcatccaacagagga
+ctaatatccagaatctacaaagaattggaacaaatcagcaagaaaaaaaaccaaacaCAA
+GGATGACAGTGGAAATACAAAAACAAGACATAAATATTCTGAATAGTGATAATAAAACAG
+TGCATACCAGAATAcaaactgtttccaagttacaatggttcaaccatttttcagctttat
+ggtggtgtgaaagtgatatccattcattagaaaccatgctccaggatgggcgcagtgggt
+cacgcctgtaatcctagcactttgggaggccgaggagggcggatcacaaggtcaagagat
+caagaccatcctggccaacatggtgaaaccccgtctctcctaaaaatacaaaaattagct
+gggcattgtggtgcgtgcctgtaatcccagctattcgggaggctgaggcaggagaatcac
+ttgaaccagggagtcggaggtgttgcagtgagccgagatcgtgccactgcctccagcctg
+gcaacagagtgagactccatctcaaaaaaaagaaagaaaccctactccgaattttgaatt
+ttgatattttcctggactaccaatatgtggcacaatgctctctcacaatgttgtgcaaca
+gcggtgagctgcagcttccagtcagctaaatgataataaaggtagataatccatcttgat
+atcttcctgaagaacataatgcctgcctaccatcaacaggcatcaatactttctaccagc
+tattctcaaccctcatgatcggaagagacagagactgactgtgtcaaagtattagtccca
+tcattcagcaattaactttagctcaatgcttcaaaaattcttcaggccctgtgtaatttc
+agctacgtacattaatgatgagtacccatacaaccattctgtttcttattttcagtacca
+tatttaataaatatcagttattcaatactttatttagacattttgttagattattttgac
+caactgaagtctaatctaaatgttctgagcatgttcaaagtaagctaggccaacctataa
+ttttcggtgtgctaaatgcatttttaacttatgatattttcagtttacgggggtttgttg
+agacataacttcatcatacatcaaggagcatctgTAtatgggatatagttaaagcagtga
+tcagaggaaaatctatagccttaacacatttattaataaaagtgtaggaattaaattatc
+agctgaaaaatgtaaaaagtatctaaaagagtaagcagaaagtacaagaaagaacccaaa
+gtagaaaaaagtgaaaattaataaaataagaagccaaaaaacagatcaaatcagtaaacc
+aaaaatcttgttctttaaacaaatcaacaaagttgacaaaaaaattagatcttttaatca
+tgaataaaaaaaagagaaagcacaaaaatgaataaggaatggtgagagaaataactattg
+ataatcagcaaataaaaaatcattaaaaacaatgttgttcacatctatgaaaaacattga
+aagctagagggaatgggtaattttctagaaaaatacaattcaccacaactgacttcaaaa
+aaaaaaaaaaaaAAAAAGAAGTACCGCACTTATGTGAGCAATTTCCATAGAGAAATACAG
+TTGTCATGGAATTATAACACACACACAAACACTAGGTTTAGATGTTTTCACAGAGAATTC
+CACCAAACCTTTAGAAATCAGATCGTCCAaaggcaaattaacaactctcagccatttgag
+gcaaaatattacaattgaggcaagatatactgtactgaaaacttgaggaaaaagcaggag
+agaaagttcctttgggaaattcgaatactcaaaagtgcttacatacaatgaaaaatttgg
+aaatccataagcatggccaaggtgggacacatgctcagaaaaggcctgagaagacactaa
+taactcacctttagtaattcctaggctcacagcaagaaaaaatgaaggctaaggcagaat
+tatatatggctccgctaagtgttgagggagccccaatacagagtcagtaagcaaagtctg
+ggagaagtttttcatatttttttctttcttggctccttgcagtcaaggaaatcattttta
+aatcactaaatgctaaatgaacacaagctaaaggaaccgagccttcaaacatcaaatata
+aaaaagaatgcagatattacaaaaccagtttacaaaagttactaaacaaataaaaactac
+atcccacagtgggtaacaaaaataaccttgaagaagggaaaaatttggtttccagaataa
+acacattataatatccaaaatgtccagttttcaacaaaaattaagaagcatgcaaataaa
+cacaaaactatggcccatttacagaagaaataaatgagactctccctgagtaagcagata
+ttgaaaatattagacaaaaactttatataactgtcttaaataaacttaaagagctaaaga
+aacccaagagaatgacatataaataaataagaaatatgaatttttttaaaggtacaaaaa
+aattctgaggctgaaaagtacaataagtaaaaagttactttttacttagggttccaatag
+aagatttgagcagctggaaaaaagaatcagtgaacttgatagatcaaatgaaatgattca
+gtctgaagagcaggaaaatgaaagaatgacaacaaaaaagaatagagcctaaagacctgt
+gtaacaacatcaagaatgcctacatacagaatcctggtggggagtgaggggcaggaagac
+tatttgaagaaatgtgtttgaaagcttcccaaatttcactaaaaacaaatatatacattc
+aaaaagctcagtgaacttcatcaaggaaatatacaaagatattcacaccaagacacacta
+tgtttcaaattgtcaaaaggcaaagcgaatgtttgaaagcagcaagagaaaggcaacgcg
+tcatttacaaaggatcctcaataagtttgacagcagatagtgcattataagccatggatg
+ccagaagagcttaggaaaaaggcaacgcgtcatttacaaaggatcctcagtaagtttgac
+agcagagagctcattataaaccatgggtgccagaagagcttaggatgacattttaaagtt
+ctgaaagaaaaaaacactgtcaaccaaaaattctataacttggaagatgccccttcaagt
+attaaggataaattacacattcccagattaaaaaaaagaaagagagagagagagaaagag
+aaagaaagaaagagaaagaaagaaagaaagaaagaaagaaagaaagaaagaaagaagaga
+aagaaagaaagaagaaagagaaagaaagaaagaaagagagagagaaagagagagaaagaa
+aaagaaggaaagaaagaaagaaagaaaaaagaaagaaaaagaaagaaagaaagaaagaaa
+gaaagaaagaaagaaagaaagaaagaaagaaagaaagaaagaaaagcaagcaagctttaa
+aagttcatgtttggtaggctgtacttcaagatacacttttaaaaaaaagactccttcaga
+tacaaactaaaaaacactagaaagtaactcaaaaccacataaagaaataactccagtaaa
+gataactacataggtaaatataaaagcaattatcacattttttgtaagtcttttttaata
+ttctatatgttttaaaacaaatgtgtaaaataatgactataaatctatgttaatgaagca
+tgatgtatacagatgtggtttgtgaaattaccaacataaagaaattcataggaaactaaa
+taataatagagattttgtatactattgaagttgtttcaatttactctaaattgttccaaa
+ttaagaatgttaattgtaaatccccatggtaaccactaagttaatatcttttgaaaatac
+agaaaaggaaagcacagggtaaacacagtgatatgctacaaaatagcaactaaacacaaa
+agaaggcgataattgaggaaattaggaacaaaggaggtataagacatacagaaaacaaaa
+gcaaaatggtaggagtaagcccctctttatcagtaattacattaaatacaaatgaattaa
+actctccaatccaaagaaagagattaacagaatggattttttaaaaatgatccaactata
+ttgtccacaagatactcactttagatcaaaatacacaatgagttgaaatgaaaggatggg
+agaaaatattccatgtaagtaataaccaaaggagatctgaggcaaatatacttatatcag
+acaaaatagactttaagtcaaaaactgttacaaaatacaaagaacagtatatattgattt
+caaaattaattaagaagatataacaattataaatatatgtacaccaactaacagggctcc
+aaaatatataatgtaaccattgagagaattaaagggagagacagacaattccacgaaaat
+tgttgggcatttgaaaacccaactttaaataaaagataaaacatctagagcaaatatcaa
+gggaggaattagaggatttgaataaaactataagcaataactatagataacacttctctc
+aaaaactgcagagtacacattcttctcaagtgaacatggaacattctccagcacagatga
+tatgttaggccataagataagctcaataaacttaaaaagattgaaatcatgcaaagtatc
+ttcactggccacaatggaatgaaataagatatcaataacaaaagaaaaactagaaaattt
+acaaatatttggaaattaaacaacacagtatttaccaaccaatgaatcaaagaacaaatc
+atgagggaaattagaaaatgtttagagacgattgaaaacaaatatataacaagatgggtg
+tgatatatcaaaagcagtgctcagagttgtaacacctacattttaaaaaagaaacatgtc
+aaatcaataaccaaactttactcaataaaccgtaaaaggaagagcaaacaaaatccagag
+ctagcagaaggaaggaaatgaagattagagcagagataaatgaaattgagaattaaaaaa
+ttatacagagatcaacaaaattaaaagttggttcttttaaaatatcaataaaattaatat
+acttttacatagactaagcaaaacatctctattcagctgactttttttacaagggagcca
+acattattcagtggggaataatagctttttcaacaaaaagtgctgggaatactgaatatt
+catatgcaaaaaaaatgaagctggacccctacctcacattatatacaaaatctagattgg
+atcaataatgtaaatataagagtgaaaaccatacatgcttagaagaaaacatggaaataa
+aacattgctgtggattggcaatgcgttcttagataatacaccaaaaatacaagcatgaaa
+caaacaaatGCAGCCAAAATGTACCAGAATCTGAAAACATCTATTATCTATGAAGAATTA
+GAGGGGAATTTGGTGAAAGAAATatgggagaatgggacattgctctgtgaatgcttttgt
+gcataattgtacatttttaattaagttaatcttttacactctcaaagtgtgatattaagc
+aagcaaagataagttattacaagactctaaaaccgaatgcaatgagaaacaagtgaatcc
+aaatatatttcaaatgaatgaatgacataatcaaacttaaggggaaaataataattaatc
+tgattaatttttgactgttcttttagttcaaattgacttttgaacatacttggactacat
+accattgcttgaaaaaataaaatatctgcaaaaaattattaaatcttcatgataggcttt
+tttctttttatattagtataaatataacaattctgaaacaaatgtatgtgcattgtaaga
+ttaagccaatgagtaaatattaatatatttgtattgctagaaccccagattctcactgtg
+aaaggacagagatacagatatggaataagacaaggaaagaagcagcccactgagttacat
+tagaatcagtattatcaacataaaTATGCAATGTGCTCTCTCACATGCTCTTTCCTTCTC
+TTAAAAAAATATAATATGGACATATTATATATTATATGCATAGACACACGTGTGTCTATA
+CATATCCTATCTATACATATTGAGGATTAACAGGTGCTAGTAGAAAATATTAACTTTCTT
+TGTATTAACAGGTGTTAGTAGAAAGTAGTAGTAGGTGCTAAGATAAAAGCCATAATTAAA
+cctcctggtgaatgaacacaccatcacctacaatcttaccaaaaatagaatcaagcacgt
+gtcctagtcaaacctctggattcaactgtcatttggataaaacgcaaaggatagtgaaaa
+tgtcgatcttcactgagagtctaaccagcaaatttcacagtgtggacatcaagtgacaaa
+aatcccaaatttttcaacaaatatattgtatgggaaagaaaactttgaaaagaaacctgt
+atgttagaagagattttaaaaacatgacaaATGAAAAAAAATGGGCAAGACTAAAACTTT
+TAAAAAAGtttgagacagggtctcactctgtcacccaggctggagtgcagtggtgtgacc
+atggctcactgtggcctcaacctcctggctcaagtgatcctaccacctcagtcttccatg
+tagctgggactacagctgcgtgccaccacatctggctcatttttttttcttttttaagta
+gagacggggacttgctatgttgcccaggctagtctcaaactcctaagcacaagcgatcct
+cccgcctcggcccctgaaagtgctgggattgcaggcatgagccaccacacccggccAAAA
+GTTGCTTTTGAGGAGTTATTGCTGTGTGGATGTGATATAACCCTTTCTGTCATCTCTTCA
+CAAAACTTTCTGTAAAACATAAAAATCACCTGGACCTTCAGAGATGAGTTTGtttatttt
+tttattttttaaaaaattGCTAATTTACAGAACATGGAGATGAGTATGTTTTGAAGGCTT
+GGAAGCATGCAAGTGGGAGAAGAAAGGAGTCAGCTACATTCTGGCTGTGTGCAGAGGCAG
+GTCACTGTGGTGGGAGTGTTCCTGTTTCATGGACTCTGCAAATCGCAATGCTTGGCATGG
+CCTCCCGACCCTGATGGCAGAGAAGCAAACACCAGTCGGAGAGCTGGGGTCCTCCCAGCC
+CTCTTGGCCCTGTGGCCAATTTTTTCTTCAATAGCCTCATAAAATCACATTATTTGAGTG
+CCCATGGCTCCAAAACAAGCAGGGATGCCCATGGACCCTGATTATCCATTGTCACCCTTC
+CCTCCAAACAGCCACCTCTCCCCTGGAGACAGCCCCATACTCCACTCAGACCTGTGCACT
+TTCTGGTATCCTTGTCACCTGCTTTTTATGTCTCATTTTACAAACACCAAATTGGAAGAC
+AGCAGGAGCTGCCCCATAATACCAGTAAAGTGAGAAGCAGAGATAAACTAGTCCTAGACA
+GCCGACTCATGTTGGGGGCAGCCCACTCACAGTGGCCCTGACCCAACTCTGACTAGAGGC
+CACTTGctctcaacaccagggtgctcaatggcccgtcctggtactctgctcttctctctc
+caccttcgctttcctgcaatctatgcagcctgtgactccatccatgggctagtgaccccc
+agaccttctcctgggaccacaggcctgtgtctctatctgctgctcaatacctcccctcga
+acatccatggctaaaactgagctcctgatactctctccctacccgcttctctgtggattc
+cccacctccgcgaaggacagcttcatcctttcagctactcaggccagaagattgaagtca
+tctccttctccaggaaatcgtattgagggagctacaaatatccaaaatccgatcgcttct
+cctccactacacccgaggcccgccacccatttttgcctgaattgctgcagcagcctccta
+accgatctctgctttcacgtgggcacctcagttttttccagaacaacaaccagagagatc
+tgctcacacccaagtcagaccaggttactcctctgctctcatagcatttggaggaaaacc
+cagagtgctcgtgttggccggcagagccggcccccatctcctctgacctcctccccacct
+cttgccctcagcacccagagtgctcgtgacggccagcagagccagcctccatctcctctg
+acctcccacctctcgccctcagcaccCAGAGTGCTCGTGTTGGCCAGCAAAGCCGGCCCC
+CATCTCCTCTGACCTCCCACCTCTCGCCCTCTGCACCCAGAGTGCTCGTGACGGCCAGCA
+GAGCCGGcccccatctcctctgacctcccacctctctccctcagctagtcctcgaacatg
+tctgatgtggtcccaccttgggacccacattgctactcctctgcctgtaggggtacccac
+agttatccacacagttcactcctgtctttcaggtctttgtgcaaatatcaccttctcagt
+ggagacTACaccttcaggacttaggctgtgcctggcacatagtaggtgctcagtagacac
+tggttgtaggaaggaatCTACAGGTTGAAATAAGGAGATCATTTCCCTGAGGTTCCGAAG
+CTCATATTTACTCACCATTTGTTGTTTACTGCTAATATTGAGCACTATCAGTAAAATACA
+TAAAACCCtttgccaatccaggaagtgaaaatgacactttactgttttagtttgcatttc
+tctgcttacaaatggattacacgcattttcatgtgctgttggctacttATTCATTCAGAA
+AACATACTAAGTGCTGGCTCTTTTTCATGTCCTTTATCAAGTTTGGATCATGTCATTTGC
+TGTTTTCTTTCTGATGTAAACTCTCAAAGTTTGAAGGGTATTGTCTTTTCCTGACACATA
+CGTTGTAAATAATTTTCTGGCTTACATTTTGACTTTTAATTTCATTCACGATGTTTTTAA
+TGAATAATTTTAATTTTTATGAATGCAAGTTAAAATAATTCTTTCATTGTGGTTTCTGAC
+ATGTCATGCCAATAAGGGTCTTCTCCTCCAAGAGCACAGAAATATTTGCCAATACTGTCC
+TTAAAATCGGTCACAGTTTCATTTTTTATATATGCATTTTACTTCAATTGGGGCTTCATT
+TTACTGGCCCTATTTGAAGCAAGTTTCTCAGTTAATTCTTTTCTCAAAGTGCTAAGTATG
+GTAGATTGCAAACATAAGTGGCCACATAATACTCCCACCTCctttgcctcctctcccagg
+aggagatagcctccatctttccactccttaatctgggcttggccaagtgacttacactgg
+ccaatgggatattaacaagtctgatgtgcacagaggctgtagaatgtgcactggggcttg
+gtctctcttgctgccctggagaccagctgccCCACGAAGGAAACAGAGCCAACCTGCTGC
+TTCCTGGGGGGAGACAGTCCCTCAGTCCCTCTGTCTCTGCCAATCAGTTAACCTGCTGCT
+TCCTGGAGGAAGACAGTCCCTCAGTCCCTCTGTCTCTGCCAACCAGTTAACCTGCTGCTT
+CCTGGAGGAAGACAGTCCCTCAGTCCCTCTGTCTCTGCCAACCAGTTAACCTGCTGCTTC
+ATGGAGGAAGACAGTCCCTCAGTCCCTCTGTCTCTGCCAACCAGTTAACCTGCTGCTTCC
+TGGAGGAAGACAGTCCCTCTGTCCCTCTGTCTCTGCCAACCAGTTAACCTGCTGCTTCCT
+GGAGGAAGACAGTCCCTCTGTCCCTCTGTCTCTGCCAACCAGTTAACCTGCTGCTTCCTG
+GAGGAAGACAGTCACTCTGTCTCTGCcaacccagttgaccgcagacatgcaggtctgctc
+aggtaagaccagcacagtccctgccctgtgagccaaaccaaatggtccagccacagaatc
+gtgagcaaataagtgatgcttaagtcactaagatttgggCAAAAGCTGAGCATTTATCCC
+AATCCCAATACTGTTTGTCCTTCTGTTTATCTGTCTGTCCTTCTCTGCTCATTTAAAATG
+CCCCCACTGCATCTAGTACATTTTTATAGGATCAGGGATCTGCTCTTGGATTTATGTCAT
+GTTCCCACCTCGAGGCAGCTTTGTAAGCTTCTGAGCACTTCCCAATTCCGGGTGACTTCA
+GGCGCTGGGAGGCCTGTGCATCAGCTGCTGCTGTCTGTAGCTGAGTTCCTTCACCCCTCT
+GCTGTCCTCAGCTCCTTCGCCCCTGGGCCTCAGGAAATCAATGTCATGCTGACATCACTC
+TAGATCTAAAACTTGGGTTCTTGgaccaggtgcggtggctcacatctgtaatcccagcaa
+tttgggaggccgaggcgggtggatcacaaggtcaggagatcaagacgatcctggctaaca
+cggtgaaaccccgtctctactaaaaatacaaaaaaattagccgggtttggtggcaggtgc
+ctgtagccccagctacttgggaggctgaagcaggagaatggcgtgaacctgggaggtgga
+gctggcagtgagccaagatcacgccactgcactccagactgggagagagagcgagacttt
+ctcaaaaaaaaaaaaaTCTTAGGTTCTTGGATGTTCGGGAAAGGGGGTTATTATCTAGAA
+TCCTTGAAGCGCCCCCAAGGGCATCTTCTCAAAGTTGGATGTGTGCATTTTCCTGAGAGG
+AAAGCTTTCCCACATTATACAGCTTCTGAAAGGGTTGCTTGACCCACAGATGTGAAGCTG
+AGGCTGAAGGAGACTGATGTGGTTTCTCCTCAGTTTCTCTGTGTGGCACCAGGTGGCAGC
+AGAGGTCAGCAAGGCAAACCCGAGCCCAGGGATGCGGGGTGGGGGCAGGTACATCCTCTC
+TTGAGCTACAGCAGATTAACTCTGTTCTGTTTCATTGTGGTTGTTTAGTTTGCGTTTTTT
+TTTCTCCAACTTTGTGCTTCATCGGGAAAAGCTTTGGATCACAATTCCCAGtgctgaaga
+aaaggccaaactctggaaaaaatttgaatattttgagccaaatgtgaggaccacaacctg
+tgagaacggaaaataaatcctgggaccccagactcactaagccaaagggaaaagccaagc
+tgggaactggcttatgcaaacctgcttcccatctggttcctaaataagatagctattaca
+caaagacaaaaaagctacatccctgcctctacctccatcgcatgcaaaatgtgtattcag
+tgaacgctgaccaaagacagaagaatgcaaccatttgcctctgatttacccacacccatt
+ttttccacttcttcccctttccccaatacccgcacttttcccctttacttactgaggtcc
+ccagacaacctttgggaaaagcacggaccacagtttttcctgtggttctctgttcttttc
+tcaggtgtgtccttaaccttgcaaatagatttcttgaaatgattgagactcaccttggtt
+gtgttctttgattAGTgcctgtgacgcagcttcaggaggtcctgagaacgtgtgcacagt
+ttagtcggcagaaacttagggaaatgtaagaccaccatcagcacataggagttctgcatt
+ggtttggtctgcattggtttggtctggaaggaggaaaattcaaagtaatggggcttacag
+gtcatagatagattcaaagattttctgattgtcaattggttgaaagaattattatctaca
+gacctgctatcaatagaaaggagagtctgggttaagataagagactgtggagaccGTGCA
+TAGTTGCTTCCTGATCAGCTCTTTATTTGATTGAGAGTGAGGCAGGGAAGATTAGAGGGA
+AGCTTACAGTGGAATTCAGGGCTGAGGCTGCTATTCTTTTGCTCCTTGTAACTTCCTACA
+GTGTTGTCAGCATCCACATACTTCTCTGTGGGGTTggtctcagagccaggttaccttgtc
+ttaggtccagtggcaccctgactggcttggtgtccttgaacaagttacctaacctctcca
+aacctcagtccctcagttgtaaaattaaaaaaaaaaaaaagaagaagaagagtacctact
+gtatagcattgatttgaagattgaatgagctggtattatacaacgtttagaagcagtgcc
+tgacacgcaaaaggctctcaacaaatACTATCCTTTACTAATATCCTGTGTGTCTGTATC
+AGAGCTGGTGGGGTGGAGGGACAGAAACAAGTGGGAGAAGGTaaagagatggacaaatga
+tctctaaagtctctctggcactaacaCAATTCTTTATTATGTGTTTTGTCTGGCTCTTTA
+TATTGATAGCTGTTCCAGAGGCAATCAATAGCTATTAGTCGGTTTTATTCTTATTTTTCT
+GTCTGATCTTACAGGGGAGCAAACTGTGGCAAAGTATGAACTTACTTCTCAGGAAATTAA
+CCATTATATTGGCAATCACTGTGATTATTTGAACTTCAGCGTCTGGACAAATTTAGTCAC
+ATGAAATACAGAAGAGAGATTTCTCATGGTTAAAACGAAGCTCTCTTTATTTGCTTCTGC
+TAATTAAAAAATCAGAGCTAAAGATACTTAAACACTACAGTTAAAATGCCATGGTTGTCT
+ATTGGCTTAACGAATTCTCTTATGAAATCAACTCTAAAATGCTATCCATCATAAATCATG
+AAACGCAATTTTTCTTATTCTCTTTAGAGCTTTACAATTCATCTTAAAGACCAGTGTTTA
+CACTCTCTTCTGTAGGTTGTACAATAACTTTTGGCGAGAAAAAATAAAAGTCTGGCTTTC
+TGACTCATAGGTGTGTTCCCTTTAACAGAAAAAGAAAATATGTCCTCTTTAAAACTGATG
+ATCATTGGTCACCTCAATTTTATTGAAGTTCACTTCTGACCTCTTTAGATGTAGTTCTCT
+ACATAAAACTGCCCAACAGAATTCTCTGTCTGAATGTCTCCTCCACAAACAAAATTTTAA
+GAACTAAAATTATCATCTTTCCTTCCAAATATGCTCTCCCTATGTCCCCAGGGCTCTCCA
+TGTGTAGAGCTGAGACCATTTGCCACTCAGTTTCCTCACCCAATTAATTACAAGTCCCAA
+CAATTTTCCGGtttttttgtttttgtttttgtttttagacggagtcttgctctgtcacca
+ggctggtgtgcggtggtgcaatctcagctcactgcaacctccgctgcctgtgttcaagcg
+attctcctgcctcagcttcccaagtagctgggattataggtgtgtgccactacatccaga
+taatttttgtatttttagtagagaggggatttcaccatattggcccagatgatctcaatc
+tcttgacctcatgatctgcccaccttggcctcccaaagtgctgggattacaggtgtgagc
+cgccatccctggccCAGTTTTGCCTTTTTAACATCCCTCAGCTCTTCAAATCCATTTTCT
+cttctctaacacctccccattccccagctcgtaatgaactcgtaagtagattactacaat
+cacctcccaaatggtcttcctggctccatcagccttgtgaccttcaagttcattttccac
+atggatgtcagagtaactttctaaaatgaaaatctgaccacgttactctcttgcctaaat
+ccgcctatggccgctgttaggatcaagtctaaactcccgaccctggaacatcaggtcttc
+gtgctctgttcactgcttctctacctcacctgcaaccaACACCACTCCCACATCCATATG
+CTGCTCACCGTGTATCAACATGAACAGGAGGTGGGTGTTTCAGTCCCCAGGAAGACACTG
+GGCCTTTTCAATCATCTACTGCTGTGTAATAACCACCCCGCAAACTGACCACATGATTTC
+ATTTTGCAAGGGTTCCTTCCTTgggctgtgttcagcaaaagggtttactgagctggcagg
+tccaagatggcctcactcacaggactggctgttgatgggagccttgatgctcttgggctc
+accccttatcctccagtaggttagagcttcttacagtggtttcaggcagcatctgaagac
+agtaaaagcagaagctccaaggcttcttacattctagcctggaaaatcacatcacattgc
+ttccttcatatttttttggcaaatcaggttgcaaggcttgcccagattagggtaaagagg
+caaagaggctccttttcttTTCttttctttttttttttttttttttttttgagtcagaat
+ctcgctctgttgcccaggctggagtgcagtggtgcaatctaggctcactgcaagctctgc
+ctcctgggttcacgtcattctcctgcctcaggctcccaagtagctgagactacaggcacc
+taccaccacgcctggctaatttttttttattttttattttttagtagagactgtgtttca
+ctgtgttagccaggatggtctccatctcctgacctcgtgatccTTGCAAAGGGACATGCA
+GACCACATTAGTGAGAATATGTGCCTGTATTTTGCAATCTGTAACATGGGCATAAACTAA
+ATGTTTTCCAAAGGGAATAGGGCAAAACAAAAAGGACCTTGACCACTCCTTGGCCCTGAA
+TAAATCCAGGAAGCCTAAGAGTATGACTATCCTGAGGTAGAAAGAGGGTCACATGCTGGA
+TAAGAGGTACCTGGGCTCTCCACTTACAAGAAGAGAGCATGGTTACATTTATAATCACCA
+TTCCCAACATGCTGTGAGTGCAGGCAGCTACCAGGAGGAGAACAAAGGAAATAACCAGGA
+CACTCATCTCTAAACCTGTTAATTTAATCACACGGAACACTTCTATTTAAAATTCCCGAG
+AGTTAAGATGTAAGAATGCTTATCAAGGTAAATGCTGTTCACACTGCTTGGAGTGTCAGG
+CCTAGATCTCTATCCATCAGAaacaacaatatcaataacaacaacagcaacaTGATGATG
+GGGCAATTTCTTAAAAGCACCATGTATTTTATCGATACATGTCCGTTGCAGAAAATCCAG
+GTGAATCCAAAGAAGAAATAAATGTCTTCCACAATCCCATAGCCCAGAGCTAACTAACCA
+CTATAAAGAACCCAGCGTGGTTTTAACTAATGGATCAAAAGATGCTCATCAAAGGCTCTG
+AGCTTTCCTGAGTGCTAACAGGAAACATCCAGCATCACTGGTCTCTCCAAGGCTGCAGGT
+GTCTTTGCCCATAGTGCCTGTTTTGTGTCAGGGAAAGAATCAACCTGGGAGCCAAGCCCA
+GGAATCAGGATGACCAAGACATACTGCACAAGGAGGGAACAAACCCATCCAAGGACACTC
+AAGGACAAATCAAGCAAATGAATTTAAGGGAGACGTGCTCATGGTCTGCTTTGCTGCTCA
+GCATGGCTGGGAGGCACAGTGGAAGATCATGCATCCTGCCCCTGGGACTCCTCTGCCAGA
+GCCTGAGAGCTTTCTCCTGCCCACAGGCTAGGGGTAGGGCAGTTGGAATTGATCCATGCC
+TTCTAGCTAGACTGTGGGTCCCCTCAGTCTTGGGCATGGTGACAGCCCAGCATCAGACAG
+AGGTCAGTATCAAACTAGAAAATTTAATAAATACTGTCAGATTTGTAGACCCAAGAAAAT
+ATAAACTGCCAATCACGGAGGAAAAAAATCTCTCAATGATCTTATCTTTATATGATTCCC
+TTGCTGCCTGGAGATTGACATTTCCTTGGGGATAATCTGGTCATAGGATTGGTGAAGGTG
+GAAGGGAGGCAACCTCCAAAGGTGGGGCCCTCTGCTCACCTGGGACAGGGAGGGCCTGAG
+GTAGGTGTCTGTGTGGGCTGGGGAGGAGGATGGGAGCAGTGCTTCTAGATGTTTCCACTT
+TCTCCTCATTAGATAATAACGAATGGGTGATTTCCCTAGTCACTGCAGTGTGAGGAAATC
+TACAAAATTAATTTCACAATACGCTTTACAGGATAGGTGGAGAAACACATGAAGTACAAC
+TGCAGTGGGTTATAAAAAACGGCCTTTCGAGTTGAGCAATAAATTCGTTCAAGCAGCCAT
+TCTGAAGGACAAACTGGCTCTGTATTTAAGAGGGGCATTCCAGCACTTCTCTAGCCACTG
+GGTTGACAATGACTCACCAAAGCCTCTGGTAGCCACCACAGGACACCCAGAGCATATGTT
+TTAAAGCTGAACACCAAACTGCGGACTTCGGGAGTAAGTGAACTGACTGGTTTTTATTTT
+GTTTTACTGCTTTTAACATTACAGTAACTGTTACAGGTTCCAGCAGGCTAACTGGGTGGA
+AATGAGTTTGGTTTCACTTAGTCTCTCTAAAGAGAAAGCAAGTCGGTAGACTAATACCTA
+ATAAAAGCAAAGCTGCCAACAATTGAAATTGCCTAGGCTGCTCTGTGTGTCCCACAtgca
+tgggtgtgggtgccagtgtgtgtgcgtgtgtgcatgcatgtgcatgtgtgtTGGGATAGA
+GTGGTAAGAAAATGGGAAATAATAAGAATGTTCAGTCCATAGCCCTTCATTATAAAAAGG
+TGAGCTGTAATAAATACTAGTGCCACATTTAGCCAAAACTTTACTCCAGCCAAAGGTGAT
+ATTTTCATGATAACATCCTGTGATTGCTTTGTTCTTCGTCTTTTATGTTCTTCCTAGATG
+GGCTCAGAACATACAAGAATTAAGTACACATCTTATTTTCCAGTGATAATGCTACCGGCA
+AATTCTGTTGTTTGTATAAACATCAGCCATGTTTATATAACTAAACTAGTGTTTTGTTTT
+GTCAATTCAGCAAGAAATTAGACCAAATGGTGGCTTAATGCTGCATTGATTTGGCTATCA
+ATTTGTTTTCACTTTTCTGCAAAATAATTAATACATTATTAAATTGAATTGTGCTGATGC
+CACAGTTGTTCTTATCTCAAGTGTCTTAAAATTCATTTAATTTGTTTTTCCTTTGGTTTC
+ATTATTCAAATTTTAACTTCAGTTCTCAAGATTTTATCTGATGGAAGAGATGGAGTCCAT
+TACTAAGGACTCCATTGTGCTCCATCATGCCAGAGTTGTAAAATAGATCTTTTAAAGGAA
+ATTTACTGTGATTTTTTTTCTATTTAAGAGCTTCCTCTCCAGTTGAGCATGTAAGAAAAT
+TATACCAGGAGAATACAGTAAACTCTATGAGGCAAGCTATAAACATGTAGCATTGTGATT
+AGGGctggttctccttctagagacatggtaggattgcaatttcataccatccttgaagtt
+agagagagccacgtgactcatttagccaatgaactgtgagcagaatgacatgtcacttcc
+agctgaagctttaaCAATCTGAGAGACATTCATACATTTTCCATGTGCTGTAGCCTTATA
+CCCAAAGCCTGGGTCCCAAGTGACCATGACAGGCAGAGCTCCCTGttgagccacagagat
+ttagagaatggctgttaacacagcataatccagcccatcctgactaatCTGATATTAACA
+TGTATAATAAAGAATTCTATCAATGCTGAGGGAAGATGACTAGTTAAGGTCCTAGGTTGC
+AAGTCTCAAAACCTCTTCTAAGGATTGTAGACAGGAAATTAAATGACTTCTAGTCCCTAG
+AGTTCCCAATCTCCTACCATCCCATCCTAATATGACAGAAGTAATTCCTGAGTTGCTTCT
+GAAACCAGAGCTTCCCTCAGAACCCTTAGCCTGCCAGATGGCTTCTTGGAGAGCCCTCAC
+TCACTTTTCTCCTTCTGCTATTGCTGCTCATTCATTCCAGTTTTTAAAAATTCATCTTTA
+TCCAGGAACCTCGCTTCTAGAAAAGTCATACAGGTGCTTCCAGGAGGCTACATGGGCACC
+CATATTTTTCTAGCCACTTTCATTAGACCAATGCAGCAGAGAAGAAAAGCCTCAATAATT
+ATTATGACATGGCATGTTAGGATACCAAGTAAATTGCATTTGTAAAATGTGATTTTCTGT
+TGGTGTTCACTTCAGCTCTACTGACATTTGGTAAGTATTATTGACTGACTGACTAACTAA
+TGTGGTCATTAGTCTTCATAAAGAAAGGCTCTCTACAAAAACGGAGGGATGCCCTTTTTC
+TGGCATTTAATACGTAAGAAATTGCCTCCAATAGAAACCAGAGTTGCCTGATTACTATCA
+GCACAGGAGAAATGTATTAATGTGCCTTTCTAGTAACAGGTTTTTAGAAAGTCAAATATA
+AACAAATCTGTCTATTTGTGTGTGTGCATGTGGTAGTGGGGAGGGAAGAAAAAAGGAGGG
+GGAGAGAAAGAGAAATAAGAACCAAGTTTATTATACTGTATTCAGGGGGAAAAAATTTTC
+CCAAGGTCCTAACAGAAGAGCAAAGTGCCACTGTCAATAGCCTCAGTAGTGTTAGGGTTG
+CTtttatttatttatttatttatttatttatttatttatttatttttccttttttttctt
+tctctttttttcttcttttttttttcttttctttcttttttttttttttttttttttttg
+gacagagtctcacactgtcacctgggctggagtgcattggtgcaatctcgactcactgca
+acttctgcctcccaggttcaagtgattctcctgcctcagccgcccaagtagctgggatta
+caggtgtctgccaccgtgcctagctaatttttttgtatttttagtagagatgaggtttca
+ctatgttggccaggctggtctcaaactcctgacctcatgatccacccacgttggcctccc
+aaagtgctgggattacaggcgtgagccaccgcccctggccAGGATTGCTTTTACAGCCAG
+TCTTCAGGTGCCCACTGTAGGAACAATGTCATTTAACCCTCGGGATTATTCTGTGCCAAA
+TATGGATAATGACTAATATCCAACACAGATATTCTCAGCTCAGAAGAGCAATTAGCAAAT
+TCATAAATTAAGTGCTTGCTTCCTCTTTAGTCAAATACAAACGTTTGTTAAAAGATATTA
+TTTTGCTTTACACTTTTTCTCTCAGAAATAAGCAGATGCTTGAATTCCCACAGTGCTGCT
+TGAGCCTCACACCATGTCATCCTGCCAGGCACCCAGATCCAGTTCTAGAGTTTCACATGA
+TCGTGAgtgttggttaataagtcaatgtgaactgggaggggagatttttcaggagtgcca
+cagggctctccctttaatcACATACACTCCCTGCTTTCATTGGAAAGTGTATAATGATGT
+CAGAGTGCCCCAGAATGGAGCTAGTTGGAAGACTGCCGTCATAGGGATGCCTTAGTGAAT
+TAATAAGGTTTTAATTTCTGGCTCTCAACTTTGTAGATGTAAAAGTTGATTTATCAATAT
+GTGAGAAAGGATGAATCTTTCTGAAGGTTATGTCATCACACTCACTAAGCACACAGAGAA
+TAATGTCTAGAATCTGAGTGCCATGTTATCAAATTGTACTGAGACTCTTGCAGTCACACA
+GGCTGACATGTAAGCATCGCCATGCCTAGTACAGACTCTCCCTGCAGATGAAATTATATG
+GGATGCTAAATTATAATGAGAACAATGTTTGGTGAGCCAAAACTACAACAAGGGAAGCTA
+ATTGGATGAATTTATAAAAATATGCCTCAGCCAAAATAGCTTAATTCACTCTCCCTTATC
+ATAAGGATAATCTTGCCTAAAGGGACAGTAATATTAAAGACACTAGGAATAACCTCTGTA
+CTTTGGACAGTAGACCTGCATAGCCCATTAGGCCTCAATGAAGTCTTATGCAAGACCAGA
+AGCCAATTTGCCATTTAAGGTGATTCTCCATGTTTCTGCTCTAACTGTGCTTCACAATAC
+TCAAAACACTAAATCAGGATGTTTCCTGGAGTTCAGGGAGCTGTCCGTGTTACTGAGCAG
+TTCTCAGCAACACAAAGATCCTACTGACTCCTCATCAGACTTCTTTCTCACTGGAATTTT
+ACACCTGGGCTGTTAACACCAGGCCAGGTCAAATTCAAAGGAGAGAAAAAAGCTCATTAT
+GAAGGGTAAAATCCAAAACACTGTGCATAAAGATATGGCACAATTTTTATACATAAAGAT
+TTCATAAAACCAAAGCATCAGGAAATGAAAAGAGATACAGAAAGAAAAATGATGGTAAAT
+GAGACATTAATTTACCCTTCTAATCTCTATCACAGCAAAAAGATAATTAAAAAATCTATA
+TGAGGACCACAAAATACACAAAAATTATGTAGCAAAGCCTATAGCCTGAAAAAGTAAACA
+TTGAAATTTGTATGTCCATAAAATGTTTACAAAATTCAGTACATATTACACACCCCACCC
+TAAAAACATCTAAGCAAAGTAGAGAATGTAGAAATGCTACAGATTATATTCTCTGATTAT
+GACACAACAAAACTAGAAATTACAGCATGGAAATTTAAAAGCTTTCTCTTAAATAATTCT
+ATGTCAAAAAGAAATCCAggccgggtacagtggctcatgcctgtaattccagtactttgg
+gaggccaaggtgggcaggtcacttgaggtcagcagttcaagaccagcctcgtcaacatgg
+taacaccctgtctctactaaaaatacaaaaattagctgggcctggtggctcatgcctgta
+atcccagctacttaggaggctgaggcaggagaattccttgaacccagaaggtggaggttg
+cagtgagctgagattgcaccactgcactccagcctaggtgacacagcaagactctgtcaa
+aaaaaaaaaaagaaaTCCAAATAAAATTTCCAGAATATGTGGAAAATAGTGACAATAAAA
+ATATTAcacatgtgtaatcccagcattttgagatgccaaggtggcaggatcacttgagac
+caggagttcgcaaccagcctggacaacatagggagactccatctccacacacgccaaaaa
+aaattttaaatagccaggtatagtggtacttcctgtaatcccatctacttgggaggctaa
+ggtgggagaatcacccaacctcaggagttcagggcttcagcaagccatgatcatatcact
+gcactccagcctcagcaacagagcaagatcctatctcaaaaaaaaaaaaaaaaTCACATG
+TGGGAAATAGCTATAGCACAAtaaaaataaatgtattaagtatgaacaacaaaaaagcta
+gtaaaggttgaacaacaactatccttaggaaagtggaaataatgtattaataaatatgaa
+agcaggctagccacggtgactcacatctgtaatcccagcactttgggaggctgaggcagg
+cagatcacctgaggtcaggagttccagaccagcctggccaacatggtgaaatcttgtctc
+tcctacaaatacaaaaactagccaggcttggttgtgcactcctgtaattcgagctacttg
+ggaggctgaggcaggagaatctcttgaacctgagaggcagaggttgcagtgagccaagat
+catgccactgcactccagctggggcaacagagtgacactccatctcaaaataaataaata
+agaaagcagaaactaataaactagaaaacagaaacatagaactaatttataaatcaaagc
+actatgccttgaaaagaGGGAGAAAAATTGTGAATTAAGGAAGGGAAGAGATGGTTGGAG
+AGGAGGTGGGAGAAGGCAGAGATAATTGAAGGAGCAAAAGCATCTGGAGAAGCAAAGCCA
+CTGAAAGATGAACAGGGCTCTGAAAGAGATGCTTGACTGCTATCTTTTCAAATGACTGCA
+GTTCCCAGTGACATCATTTTTCTCCTCCCTGGAAGTCTGAGGGGCAGTTCACTTATCTCC
+TCCCCTCCCCTACTCCTCACCCCACACTCAAAACCTGTCTATGCTCCTTTCATTCTCATA
+TGACAGATTTCAGATGGCATTCTTATTTCCCTGATTTCTTTTTGAGATAGCTTGCATTTC
+CCTCCTCTATataaagccaccgtttatcaaatgcctacatggaccaagcagtccacaagg
+gcttcacagacagttttactaaactcatgccaaaactttcaggttttatacctaccttat
+agataaagaaattgaagcttatagagtttaagtaatgttcccaaagcctcgtggctagta
+attcaaacctaatttctgcctactccaaagtctatttttccttatgatactctactgcct
+ctcCAtggataaagacagagatcacatattaataaaatttgcacaaagtcggcaaattgt
+tgaaagggaaggctaagatgattaataaaatcaagagccagatgatctcaacaacctgaa
+ataactggctgacaaccaatttgaataactccctgcgggtgaagttcaaagtactatttg
+ggtttttttttaaagtttggctgggtgcagcggctcacgcctgtaatccaagcacttagg
+gaagccaaggtgggcagatcatgaagtcaggagttgaagaccagcccggtcaacatggtg
+aaaccccatctctactaaaaataaaaaattagccgggcctgctggtggatgcctgtagtc
+ccagctactcgggaggctaaggcaggagaatcgcttgaacccaggaggtggaggttgcag
+ggagccgagatcgcaccactgcactccagcctgggcgacagagcgagattccgtctcaaa
+aagtaaaataaaataaaataaaaAATAAAAgtttgatatattcagaatcagggaggtctg
+ttgggtgcagttcatttgaaaaattcctcagcattttagtGATCTGTATGGTCCCTCtat
+ctgtcagggtcctagcaggaaattgttgcactctcaaaggattaagcagaaagagtttaa
+tgaagggtctctttccagggttaagggaactgctagggtttggatatttgaccactccaa
+actcatgttgaaatgtgatccccattgttggaggtggggcctaatgggaggtgttttggt
+cctgagtgtggacctctcacgaatgtcttggtgccatccaagtgagttcttgctcgctct
+tttttttctttttgagatgtagtttcactcttgctgcccaggttggaatgtagtggtgcg
+atcttggctcactgcaacatccacctcacgggttcaacccattctcctgtgtcagcctcc
+agagtagctaggattacaggtgcccaccactatgcccagctaatttttggtatttttagt
+agagacggggtttcaccatgttggccaggctggtctcaaactcctgacctcaggtgatac
+acctgcctcggcctcccaaagtgctgggattacaggtgtgagccaccatgcctacctagt
+tctagctctcttaattcccacaagagctggttgttaacaagagcctggcacaaacccctc
+tctctcgccacgtgatctctgcacatgccagcttcccttccccttctgccatgagtggaa
+acagcctaacgccctcaccagaagcaaatggtggcaccatgcttcttgcacaccttcaga
+actgtgagccaaataaacctctcttctttaaaattattcagcctctggtattcctttata
+acaacacacacacacacacacacacacatacacacacacgcaaaagcagactaaaacagg
+aactaattagaaatggtgatgcaccgagggattggcaCCGAGGCTCCCCAACAGGAACTG
+AGGTCATGGATAGAAGGACACATTCATGTTATTTTTTTCTAATGGTTAAGTAATTATTTG
+ctcttactctcaaaatttctgccaaggcctcccatggaccaaactcaactagaatctagg
+aagcagagaacctgagtgttgcattcagcagaagtcagcttcctagggaatcttgcagga
+agggtgaaggtagagaatctggtggggaagcaagcaaatgcccatcacaTGCACTTTCCT
+ccaacagagcgactcagatgctataaaacttgctaacacagtctcagggtctgatcacag
+taacatacaatccaggttttaatcatcagaaatcacagtcctattgtcttctgcacagac
+ccaaacacacttggaggtcatgttcaatatgaatacctcacagagaaggaaatttacacg
+cgagaagtacatctgcagaaagccagctggcatgtcaaccattcaaaaactcagggtgtt
+ctggataaagaagactcaggaagacaagtatgaagcataatctgtgacattccatgcggc
+agacattagacacatacaagagagttgttggaaagcggaatttatcttcatataaacaac
+actgagctaaatctcaatatttcagatctctagaactatccatcagtgaaatggattgca
+aatacaaagagtaataccatgtcacttaagaatagaatcatggacgaggctgccacctgc
+tgttgggggccactgcagaagaaattccagaacactggactggagagcacctcactttcc
+ttacagctctaagtttctgACTCAGTGACCTGATTCACTACCATATACACAAAGACCCAC
+TTACACAAATGACTGTTCTTCACACTAGGCCCATGGAGACAGGGATAAAATTCTGAATTT
+GCTCAGATACCTTCTCCGCTACTGACATCTAGGCATTACACAATTCATCTCTTCATATTT
+AACCTTTGAAGTTTGCTACTTCTCAGAGAGACTAATGAGTAGTGAGCAAATATCCTGAAG
+CTGAGAATGCTTCTACCTCCTCTCAAAACAACGGAATATTCATCAAAACACAGCAGTTCT
+GCACTTAACTTTAGGCCTTTTCTAACACCTTGTTTCTTGGCAGTAACTGTGGCCAGAATA
+GCTCTTTCCACAGATAAAGGACCTTTTGAAAGGATAGGGTCTCTAGATAGAAAAGCAAAT
+GCCTCATTCCAGAAGGTCTTCAAGAAGAAAATGTTGTGGTGATAACAAACATAACTGATT
+ATAATCTATTCTGTGAAAAAAGCTTATGAAACAGTAGATGTGTGTATCTAGTACATAAGA
+GCTGAATGTCAATATATATATAGATATATACacacactcaaataaataatagttatctct
+aactagagaaattctagttgccttatattttcttctttttccttactatattttctacaa
+taaacatgtgtttttaacaagaaaaGTCTTTTCTGGTGTGCTTTTTAATTTTCTTTGTTT
+AAGTGAGAGTGAGGCTACATAACTACATGGCTAGGTAGACTTTTAGAAAACTTGGCTGCT
+CTAGAAAATTGACATATCCTGATTTCTTCCATAGCTTGGATCTTGACCTAGAGGGAAATA
+TAAAAGTGTTGACTTGAACCTGAGGGGTGCCATTTTCACTGCTGAAGTAGTTTCATGGAT
+CATGAATTGGAGAAATGACTTCAGCAACATGGGTGTTAAAATCAGAAAGCACAAGTGACC
+CACAACAGATGATGGAGAACAAAGAGCAAGCTGGGAAAGCAGTGGCCTTTAATACAGAAA
+AGAAGAAGTATAGCCACAATAAATATTAGGCAGACAGCAGTTCAGCAGTTTATACTATTA
+AGCTGTTGTTTAGGGGAATAGTAAACTGACATGACCCTTGAGGTAGGTATATATAGGTAA
+ATTCTATGTGTCCCTTGAAATAGGTGTATGACACAACTTCTGGCATCTACATGGATTTGG
+TCACTCTAAAGTAGCCATGAGGCTTAAGATAGTTCAGCTGTTTGGGGATAAGTTAAATCA
+TTTGCCATTGTCTTTCTGCAATTTGCATATCCTACAGTTATCATTGCCATTACTGAATGG
+CACAGAGAAAAATTCTGGTCTAAAGTGGTTCTCAAACCTGGTtgctggagggccaccctc
+agtgatgatgatttaatctgtagaagaatagaacattgatagtttttatatatctccagg
+taattttaatatataactggggtgagaatcattgACATAATTGTAACAGGATAATATTCA
+GGAAATATGGAGATAAATAATTTTCTTCTCGACATTAAAAAAATCTAATAAAAAGTTTTA
+TGTTTTCCCCTAACTCAGGGTCATCAGCCTTCAAGCTTCAGTCTCTGTGTGTTCACAGGT
+GCTGTAAACACACGCATCACTACTAATATCCCACTTCAGTGCTATTGCTGCTCCCAAAAC
+TCCAGGTATTTTTAACCTTATAAACCTCCAGAATAATGAGACCACTGGGTTCAGTAAATT
+GCTTTGTTTTGAAGCACTATTAGACAAAGTGGGAGACTAGAAGATAAATCTGTCAATGAC
+ATGTCCTTTAAGACTACTTAGATTTTGTTGAATTTGTGGATCATTCCTTACTTGAGCAAA
+TGGTAAATTAACTCTCTCTTTTCTCTCTCTCTCTAGCTGGCACACTTTTTCCAGTAGCCA
+TTCTACTTGGTATGCTTACTTATCAGCTGTCCTCCAGGGGCCTCACATTAGATGTTTCTC
+TGACTAACCAAACATGACACACAGCTGAAGTCAGAAAAACCAGATTGATAATTTCACTCA
+AACTATTTTCCTTCATTCTAACAATTTACTGGAGTACACAATTGTGACTATTTTTAGCCA
+TAGGAACTCATAGAAAGACCAACTTCATTAGACCTACAAAATCGAATTGTGTAACAGTAT
+ATGCAGTATGTGTAGGAATAAAAAGCATTTCTCAAATATGCAGTACTGGATTTTGCAAAA
+GCACCTTACACTTAGCTATAAAGGAGTGGAAAACACAAAGATGAGTAACTGCACTTTTCA
+AAAGACTAGAGCTATACCAATAATACAAAGGTGTAAACAAATAATGATGAGATGACAAAG
+GCTGAGTGTTTTCTATTTGGAAGCTATGTTGTTGAGTTATTTATGTATATAATTTCATGC
+AATCTTCATGTTATGGGGATGTTctaatccactgtgactctgtccttaaataaaagggag
+atttggacatagagagaggcacacggggaggatgccatatgagaattgacactgtgctgt
+cacaagccaaggaactactggaaggagagaaagaggactggaacagttccttccttagca
+ccttttcaggcagcctagccctgccagcttcttgatctggacttctcacctctagaattg
+tgaggcaataaatctctgttgcttaagttacccagtttgtggtaccttattacaggagcc
+ctaggaaaataattcaTTATataatctgctaaggtagatatgatcattgtctccaatttc
+catatgaagaaactatgcctcaggcattgtgtcagttgtccaaaatcatacattcctgac
+tcacttcaatgaattcttcattcagcaaaatttttaaggtaccttaaaaaaattatgtta
+actcttagggccttgctttaaagcttcaatgggcttttcctttgcaaagaataaaatcct
+aatacttaagcatagctctctttcctggctatgtttctgacatcctcttgtaccatgctc
+ctccttaatcattctgaggttacatcttaagtcctttccccttgccattcccacttcttg
+gaatactttcccatcaactcttcaaagaactgccttctttaagtatttggtctcagttcc
+aatgtcacttccctgtaaaagcttcctggccatcaagccttctttacacactctatttta
+ttttttcatggttcctataacaacctaatatattctcaattgattaactgttttgctgaa
+tactgccttccataagaatggaaagaaaacatggccaggtgcagtggctcacacctgtaa
+tcccaccacttcaggaggctgaggcaacatggcaaaaccttctcttcaaaaaatttttta
+aaagttagctggatgttgtggaggcaagaggatcacttgaggatcacttgagtccatgag
+gtcaaggctgcagtgagtcatgtttgcaccactgcactctagcctaggtgacagagctag
+tcactatcaaaaaaaaaaaaaaaagaatggagagaatgctacatgagagaaaggatctta
+tctatcatgttcacctcccaagaggtgaacatatcccccaaagcctgatagagagaagat
+gctcattaatatttaatgcatgaCCATGTGCAGACTTGGGAGGAAAAATATGCCTCAGCC
+TATCAATATTGGATCCTTAATAAACAAGGATGTTTCTGCATCATTTCCCCACAACACCGA
+ACAAGTGTGGCTCACTGTGGATGTTTAAGCAAATGCATTGTTTTTCCAGTTATATATCTG
+GTAGAGATGAGGCCATTGATAGGAATGGGAAGACGATCTCCTTTTATTTTGATGACCCAG
+CATGGCTGAACACTCAGTGACTACCACTGCACTTTGTTGTACTTTCAGCATTAGAGATGC
+CAGCCCTGTAGGATATAAAACAGGAACATCTAGTCCTCAATTATATTCAGAATTACTCAA
+GTCTTAGAAGCACCACTTGTCTTTTTTCAAGGGAGAGAAATGCTCAAGTGATGGGCTGAA
+GTGAAGGGAGGGAGTCACTCACTTGAACGGTTCCCTTAGGCTGTGTGGATGCAAACAGCA
+TTAGACAATGACACTGACAGTGGGAAATGCACTGGAGACGATGACTGGCAAAGCCCTCCT
+TTTCTCCCCATCCACTATAGATACTGACAGCAAAGGGTTTGTCACAATGACAACTATACA
+CTCCCAATATCACAGAAGAAGGAGGAATAAAAGGGTATATTATGAGTGACTGAAGTTTAG
+AATAAATTAATAAATATTATGTCCCTCATCCATAGAAACCACAAAGGTCTAGTAAGGCTA
+AGGATATAACAAGAAAATAATATGAATATTTGCTTCCCCTTCCTAGTGTAATAGAGTAAG
+TTACAAATGGCTTCAGGAAGGGGAGAGAGGAAGAAGAGTGGATGAGATACGTAAGAGTGC
+TTGAGGGCTAATTTTATGAAAGCTTTGGGAAGTTTTAAGAAAAAGAAAAGCTATTTTTCA
+AGGTACAtgtgtgtatgcgtgtgtgtgtgtgtgtgtgtgtgtgtgtgtgtgtgtgtgAAA
+GACAGAAGAAAGAGGGAGACCTTAGAAGACTATGAGACACTAAGAGAAAAATTAAGGTAA
+AAAAGACACACACTTAGAAAAACACACATAGGGAGGAGGGAGGAGGTTAAGACATTTTAC
+TATGTGCTGTGAATGGAAACTACAAACCATTTTTGATatatgcaatatatatacatatat
+acacacatatacatatGTATTTAAATATTTAAATTACAttttctctttttttagagatat
+ggtttcactatgtcactctgcccaggctgcagtacagtggttgttcacagtcatgatcat
+agcacattatagccttgaactcctgggctcaagcaaccctcctgtattagtctccccagt
+agttgggattactagcatatgccaccatgtccACCTTTATGCTTTTTAAAGTGAAAAACC
+ATACTAAGAATGAGGCAGCTCAACTTAATAATAAAAACATTTCAAATGtaaagaaattta
+caaaagaaaaacaatcaaccccattaaaattgggcaaagg
diff --git a/public/gatk-engine/src/test/resources/exampleFASTA.fasta.amb b/public/gatk-engine/src/test/resources/exampleFASTA.fasta.amb
new file mode 100644
index 0000000..986e6d6
--- /dev/null
+++ b/public/gatk-engine/src/test/resources/exampleFASTA.fasta.amb
@@ -0,0 +1 @@
+100000 1 0
diff --git a/public/gatk-engine/src/test/resources/exampleFASTA.fasta.ann b/public/gatk-engine/src/test/resources/exampleFASTA.fasta.ann
new file mode 100644
index 0000000..642ddb6
--- /dev/null
+++ b/public/gatk-engine/src/test/resources/exampleFASTA.fasta.ann
@@ -0,0 +1,3 @@
+100000 1 11
+0 chr1 (null)
+0 100000 0
diff --git a/public/gatk-engine/src/test/resources/exampleFASTA.fasta.bwt b/public/gatk-engine/src/test/resources/exampleFASTA.fasta.bwt
new file mode 100644
index 0000000..fe74222
Binary files /dev/null and b/public/gatk-engine/src/test/resources/exampleFASTA.fasta.bwt differ
diff --git a/public/gatk-engine/src/test/resources/exampleFASTA.fasta.fai b/public/gatk-engine/src/test/resources/exampleFASTA.fasta.fai
new file mode 100644
index 0000000..1cc63a5
--- /dev/null
+++ b/public/gatk-engine/src/test/resources/exampleFASTA.fasta.fai
@@ -0,0 +1 @@
+chr1	100000	6	60	61
diff --git a/public/gatk-engine/src/test/resources/exampleFASTA.fasta.pac b/public/gatk-engine/src/test/resources/exampleFASTA.fasta.pac
new file mode 100644
index 0000000..b0f55c0
Binary files /dev/null and b/public/gatk-engine/src/test/resources/exampleFASTA.fasta.pac differ
diff --git a/public/gatk-engine/src/test/resources/exampleFASTA.fasta.rbwt b/public/gatk-engine/src/test/resources/exampleFASTA.fasta.rbwt
new file mode 100644
index 0000000..f623b8c
Binary files /dev/null and b/public/gatk-engine/src/test/resources/exampleFASTA.fasta.rbwt differ
diff --git a/public/gatk-engine/src/test/resources/exampleFASTA.fasta.rpac b/public/gatk-engine/src/test/resources/exampleFASTA.fasta.rpac
new file mode 100644
index 0000000..b88ff49
Binary files /dev/null and b/public/gatk-engine/src/test/resources/exampleFASTA.fasta.rpac differ
diff --git a/public/gatk-engine/src/test/resources/exampleFASTA.fasta.rsa b/public/gatk-engine/src/test/resources/exampleFASTA.fasta.rsa
new file mode 100644
index 0000000..6e7e213
Binary files /dev/null and b/public/gatk-engine/src/test/resources/exampleFASTA.fasta.rsa differ
diff --git a/public/gatk-engine/src/test/resources/exampleFASTA.fasta.sa b/public/gatk-engine/src/test/resources/exampleFASTA.fasta.sa
new file mode 100644
index 0000000..d6db971
Binary files /dev/null and b/public/gatk-engine/src/test/resources/exampleFASTA.fasta.sa differ
diff --git a/public/gatk-engine/src/test/resources/exampleGATKReport.eval b/public/gatk-engine/src/test/resources/exampleGATKReport.eval
new file mode 100644
index 0000000..3d43c81
--- /dev/null
+++ b/public/gatk-engine/src/test/resources/exampleGATKReport.eval
@@ -0,0 +1,36 @@
+##:GATKReport.v0.1 CompOverlap : The overlap between eval and comp sites
+CompOverlap  CompRod  EvalRod  JexlExpression  Novelty  nEvalVariants  nCompVariants  novelSites  nVariantsAtComp  compRate  nConcordant  concordantRate
+CompOverlap  none     eval     none            all      0              0              0           0                0.00000000  0            0.00000000    
+CompOverlap  none     eval     none            known    0              0              0           0                0.00000000  0            0.00000000    
+CompOverlap  none     eval     none            novel    0              0              0           0                0.00000000  0            0.00000000    
+
+##:GATKReport.v0.1 CountVariants : Counts different classes of variants in the sample
+CountVariants  CompRod  EvalRod  JexlExpression  Novelty  nProcessedLoci  nCalledLoci  nRefLoci  nVariantLoci  variantRate  variantRatePerBp  nSNPs  nMNPs  nInsertions  nDeletions  nComplex  nNoCalls  nHets  nHomRef  nHomVar  nSingletons  heterozygosity  heterozygosityPerBp  hetHomRatio  indelRate  indelRatePerBp  deletionInsertionRatio
+CountVariants  none     eval     none            all      100000          100000       100000    0             0.00000000   0.00000000        0      0      0            0           0         99872     0      128      0        0            0.00000000      0.00000000           0.00000000   0.00000000  0.00000000      0.00000000            
+CountVariants  none     eval     none            known    100000          0            0         0             0.00000000   0.00000000        0      0      0            0           0         0         0      0        0        0            0.00000000      0.00000000           0.00000000   0.00000000  0.00000000      0.00000000            
+CountVariants  none     eval     none            novel    100000          100000       100000    0             0.00000000   0.00000000        0      0      0            0           0         99872     0      128      0        0            0.00000000      0.00000000           0.00000000   0.00000000  0.00000000      0.00000000            
+
+##:GATKReport.v0.1 SimpleMetricsByAC.metrics : TiTv by allele count
+SimpleMetricsByAC.metrics  CompRod  EvalRod  JexlExpression  Novelty  row  AC  nTi  nTv  n  TiTv
+SimpleMetricsByAC.metrics  none     eval     none            all      ac0  0   0    0    0  0.0 
+SimpleMetricsByAC.metrics  none     eval     none            all      ac1  1   0    0    0  0.0 
+SimpleMetricsByAC.metrics  none     eval     none            all      ac2  2   0    0    0  0.0 
+SimpleMetricsByAC.metrics  none     eval     none            known    ac0  0   0    0    0  0.0 
+SimpleMetricsByAC.metrics  none     eval     none            known    ac1  1   0    0    0  0.0 
+SimpleMetricsByAC.metrics  none     eval     none            known    ac2  2   0    0    0  0.0 
+SimpleMetricsByAC.metrics  none     eval     none            novel    ac0  0   0    0    0  0.0 
+SimpleMetricsByAC.metrics  none     eval     none            novel    ac1  1   0    0    0  0.0 
+SimpleMetricsByAC.metrics  none     eval     none            novel    ac2  2   0    0    0  0.0 
+
+##:GATKReport.v0.1 TiTvVariantEvaluator : Ti/Tv Variant Evaluator
+TiTvVariantEvaluator  CompRod  EvalRod  JexlExpression  Novelty  nTi  nTv  tiTvRatio  nTiInComp  nTvInComp  TiTvRatioStandard
+TiTvVariantEvaluator  none     eval     none            all      0    0    0.00000000  0          0          0.00000000       
+TiTvVariantEvaluator  none     eval     none            known    0    0    0.00000000  0          0          0.00000000       
+TiTvVariantEvaluator  none     eval     none            novel    0    0    0.00000000  0          0          0.00000000       
+
+##:GATKReport.v0.1 ValidationReport : Assess site accuracy and sensitivity of callset against follow-up validation assay
+ValidationReport  CompRod  EvalRod  JexlExpression  Novelty  nComp  TP  FP  FN  TN  sensitivity  PPV  FDR  CompMonoEvalNoCall  CompMonoEvalFiltered  CompMonoEvalMono  CompMonoEvalPoly  CompPolyEvalNoCall  CompPolyEvalFiltered  CompPolyEvalMono  CompPolyEvalPoly  CompFiltered  nDifferentAlleleSites
+ValidationReport  none     eval     none            all      0      0   0   0   0   NaN          NaN  NaN  0                   0                     0                 0                 0                   0                     0                 0                 0             0                    
+ValidationReport  none     eval     none            known    0      0   0   0   0   NaN          NaN  NaN  0                   0                     0                 0                 0                   0                     0                 0                 0             0                    
+ValidationReport  none     eval     none            novel    0      0   0   0   0   NaN          NaN  NaN  0                   0                     0                 0                 0                   0                     0                 0                 0             0                    
+
diff --git a/public/gatk-engine/src/test/resources/exampleGATKReportv1.tbl b/public/gatk-engine/src/test/resources/exampleGATKReportv1.tbl
new file mode 100644
index 0000000..1002274
--- /dev/null
+++ b/public/gatk-engine/src/test/resources/exampleGATKReportv1.tbl
@@ -0,0 +1,36 @@
+#:GATKReport.v1.0:5
+#:GATKTable:false:11:3:%s:%s:%s:%s:%s:%s:%s:%s:%.2f:%s:%.2f
+#:GATKTable:CompOverlap:The overlap between eval and comp sites
+CompOverlap  CompRod  EvalRod  JexlExpression  Novelty  nEvalVariants  novelSites  nVariantsAtComp  compRate  nConcordant  concordantRate
+CompOverlap  dbsnp    eval     none            all                481          12              469     97.51          468           99.79
+CompOverlap  dbsnp    eval     none            known              469           0              469    100.00          468           99.79
+CompOverlap  dbsnp    eval     none            novel               12          12                0      0.00            0            0.00
+
+#:GATKTable:false:30:3:%s:%s:%s:%s:%s:%s:%s:%s:%s:%s:%s:%s:%s:%s:%s:%s:%s:%s:%s:%s:%s:%s:%s:%s:%.2e:%.2f:%.2f:%.2e:%.2f:%.2f
+#:GATKTable:CountVariants:Counts different classes of variants in the sample
+CountVariants  CompRod  EvalRod  JexlExpression  Novelty  nProcessedLoci  nCalledLoci  nRefLoci  nVariantLoci  variantRate            variantRatePerBp  nSNPs  nMNPs  nInsertions  nDeletions  nComplex  nSymbolic  nMixed  nNoCalls  nHets  nHomRef  nHomVar  nSingletons  nHomDerived  heterozygosity  heterozygosityPerBp  hetHomRatio  indelRate  indelRatePerBp  deletionInsertionRatio
+CountVariants  dbsnp    eval     none            all            63025520          481         0           481    7.63182913841885E-6          131030.0    481      0            0           0         0          0       0         0    298        0      183          298            0        4.73e-06            211495.00         1.63   0.00e+00            0.00                    0.00
+CountVariants  dbsnp    eval     none            known          63025520          469         0           469   7.441430074674513E-6          134382.0    469      0            0           0         0          0       0         0    288        0      181          288            0        4.57e-06            218838.00         1.59   0.00e+00            0.00                    0.00
+CountVariants  dbsnp    eval     none            novel          63025520           12         0            12  1.9039906374433722E-7         5252126.0     12      0            0           0         0          0       0         0     10        0        2           10            0        1.59e-07           6302552.00         5.00   0.00e+00            0.00                    0.00
+
+#:GATKTable:false:14:3:%s:%s:%s:%s:%s:%s:%s:%.2f:%s:%s:%.2f:%s:%s:%.2f
+#:GATKTable:TiTvVariantEvaluator:Ti/Tv Variant Evaluator
+TiTvVariantEvaluator  CompRod  EvalRod  JexlExpression  Novelty  nTi  nTv  tiTvRatio  nTiInComp  nTvInComp  TiTvRatioStandard  nTiDerived  nTvDerived  tiTvDerivedRatio
+TiTvVariantEvaluator  dbsnp    eval     none            all      382   99       3.86     203506      85497               2.38           0           0              0.00
+TiTvVariantEvaluator  dbsnp    eval     none            known    374   95       3.94        360         91               3.96           0           0              0.00
+TiTvVariantEvaluator  dbsnp    eval     none            novel      8    4       2.00     203146      85406               2.38           0           0              0.00
+
+#:GATKTable:false:24:3:%s:%s:%s:%s:%s:%s:%s:%s:%s:%s:%.2f:%.2f:%.2f:%.2f:%s:%s:%s:%s:%s:%s:%s:%s:%s:%s
+#:GATKTable:ValidationReport:Assess site accuracy and sensitivity of callset against follow-up validation assay
+ValidationReport  CompRod  EvalRod  JexlExpression  Novelty  nComp   TP   FP  FN      TN  sensitivity  specificity  PPV     FDR   CompMonoEvalNoCall  CompMonoEvalFiltered  CompMonoEvalMono  CompMonoEvalPoly  CompPolyEvalNoCall  CompPolyEvalFiltered  CompPolyEvalMono  CompPolyEvalPoly  CompFiltered  nDifferentAlleleSites
+ValidationReport  dbsnp    eval     none            all      369102  469   0  368633   0         0.13       100.00  100.00  0.00                   0                     0                 0                 0              368633                     0                 0               469             0                      0
+ValidationReport  dbsnp    eval     none            known       469  469   0       0   0       100.00       100.00  100.00  0.00                   0                     0                 0                 0                   0                     0                 0               469             0                      0
+ValidationReport  dbsnp    eval     none            novel    368633    0   0  368633   0         0.00       100.00     NaN   NaN                   0                     0                 0                 0              368633                     0                 0                 0             0                      0
+
+#:GATKTable:false:20:3:%s:%s:%s:%s:%s:%s:%s:%s:%.2f:%s:%s:%.2f:%.1f:%s:%s:%s:%.1f:%s:%s:%s
+#:GATKTable:VariantSummary:1000 Genomes Phase I summary of variants table
+VariantSummary  CompRod  EvalRod  JexlExpression  Novelty  nSamples  nProcessedLoci  nSNPs  TiTvRatio  SNPNoveltyRate  nSNPsPerSample  TiTvRatioPerSample  SNPDPPerSample  nIndels  IndelNoveltyRate  nIndelsPerSample  IndelDPPerSample  nSVs  SVNoveltyRate  nSVsPerSample
+VariantSummary  dbsnp    eval     none            all             1        63025520    481       3.86            0.02             481                3.86           481.0        0                NA                 0               0.0     0             NA              0
+VariantSummary  dbsnp    eval     none            known           1        63025520    469       3.94            0.00             469                3.94           469.0        0                NA                 0               0.0     0             NA              0
+VariantSummary  dbsnp    eval     none            novel           1        63025520     12       2.00            1.00              12                2.00            12.0        0                NA                 0               0.0     0             NA              0
+
diff --git a/public/gatk-engine/src/test/resources/exampleGATKReportv2.tbl b/public/gatk-engine/src/test/resources/exampleGATKReportv2.tbl
new file mode 100644
index 0000000..8b300a1
--- /dev/null
+++ b/public/gatk-engine/src/test/resources/exampleGATKReportv2.tbl
@@ -0,0 +1,36 @@
+#:GATKReport.v1.1:5
+#:GATKTable:11:3:%s:%s:%s:%s:%s:%s:%s:%s:%.2f:%s:%.2f
+#:GATKTable:CompOverlap:The overlap between eval and comp sites
+CompOverlap  CompRod  EvalRod  JexlExpression  Novelty  nEvalVariants  novelSites  nVariantsAtComp  compRate  nConcordant  concordantRate
+CompOverlap  dbsnp    eval     none            all                481          12              469     97.51          468           99.79
+CompOverlap  dbsnp    eval     none            known              469           0              469    100.00          468           99.79
+CompOverlap  dbsnp    eval     none            novel               12          12                0      0.00            0            0.00
+
+#:GATKTable:30:3:%s:%s:%s:%s:%s:%s:%s:%s:%s:%s:%s:%s:%s:%s:%s:%s:%s:%s:%s:%s:%s:%s:%s:%s:%.2e:%.2f:%.2f:%.2e:%.2f:%.2f
+#:GATKTable:CountVariants:Counts different classes of variants in the sample
+CountVariants  CompRod  EvalRod  JexlExpression  Novelty  nProcessedLoci  nCalledLoci  nRefLoci  nVariantLoci  variantRate            variantRatePerBp  nSNPs  nMNPs  nInsertions  nDeletions  nComplex  nSymbolic  nMixed  nNoCalls  nHets  nHomRef  nHomVar  nSingletons  nHomDerived  heterozygosity  heterozygosityPerBp  hetHomRatio  indelRate  indelRatePerBp  deletionInsertionRatio
+CountVariants  dbsnp    eval     none            all            63025520          481         0           481    7.63182913841885E-6          131030.0    481      0            0           0         0          0       0         0    298        0      183          298            0        4.73e-06            211495.00         1.63   0.00e+00            0.00                    0.00
+CountVariants  dbsnp    eval     none            known          63025520          469         0           469   7.441430074674513E-6          134382.0    469      0            0           0         0          0       0         0    288        0      181          288            0        4.57e-06            218838.00         1.59   0.00e+00            0.00                    0.00
+CountVariants  dbsnp    eval     none            novel          63025520           12         0            12  1.9039906374433722E-7         5252126.0     12      0            0           0         0          0       0         0     10        0        2           10            0        1.59e-07           6302552.00         5.00   0.00e+00            0.00                    0.00
+
+#:GATKTable:14:3:%s:%s:%s:%s:%s:%s:%s:%.2f:%s:%s:%.2f:%s:%s:%.2f
+#:GATKTable:TiTvVariantEvaluator:Ti/Tv Variant Evaluator
+TiTvVariantEvaluator  CompRod  EvalRod  JexlExpression  Novelty  nTi  nTv  tiTvRatio  nTiInComp  nTvInComp  TiTvRatioStandard  nTiDerived  nTvDerived  tiTvDerivedRatio
+TiTvVariantEvaluator  dbsnp    eval     none            all      382   99       3.86     203506      85497               2.38           0           0              0.00
+TiTvVariantEvaluator  dbsnp    eval     none            known    374   95       3.94        360         91               3.96           0           0              0.00
+TiTvVariantEvaluator  dbsnp    eval     none            novel      8    4       2.00     203146      85406               2.38           0           0              0.00
+
+#:GATKTable:24:3:%s:%s:%s:%s:%s:%s:%s:%s:%s:%s:%.2f:%.2f:%.2f:%.2f:%s:%s:%s:%s:%s:%s:%s:%s:%s:%s
+#:GATKTable:ValidationReport:Assess site accuracy and sensitivity of callset against follow-up validation assay
+ValidationReport  CompRod  EvalRod  JexlExpression  Novelty  nComp   TP   FP  FN      TN  sensitivity  specificity  PPV     FDR   CompMonoEvalNoCall  CompMonoEvalFiltered  CompMonoEvalMono  CompMonoEvalPoly  CompPolyEvalNoCall  CompPolyEvalFiltered  CompPolyEvalMono  CompPolyEvalPoly  CompFiltered  nDifferentAlleleSites
+ValidationReport  dbsnp    eval     none            all      369102  469   0  368633   0         0.13       100.00  100.00  0.00                   0                     0                 0                 0              368633                     0                 0               469             0                      0
+ValidationReport  dbsnp    eval     none            known       469  469   0       0   0       100.00       100.00  100.00  0.00                   0                     0                 0                 0                   0                     0                 0               469             0                      0
+ValidationReport  dbsnp    eval     none            novel    368633    0   0  368633   0         0.00       100.00     NaN   NaN                   0                     0                 0                 0              368633                     0                 0                 0             0                      0
+
+#:GATKTable:20:3:%s:%s:%s:%s:%s:%s:%s:%s:%.2f:%s:%s:%.2f:%.1f:%s:%s:%s:%.1f:%s:%s:%s
+#:GATKTable:VariantSummary:1000 Genomes Phase I summary of variants table
+VariantSummary  CompRod  EvalRod  JexlExpression  Novelty  nSamples  nProcessedLoci  nSNPs  TiTvRatio  SNPNoveltyRate  nSNPsPerSample  TiTvRatioPerSample  SNPDPPerSample  nIndels  IndelNoveltyRate  nIndelsPerSample  IndelDPPerSample  nSVs  SVNoveltyRate  nSVsPerSample
+VariantSummary  dbsnp    eval     none            all             1        63025520    481       3.86            0.02             481                3.86           481.0        0                NA                 0               0.0     0             NA              0
+VariantSummary  dbsnp    eval     none            known           1        63025520    469       3.94            0.00             469                3.94           469.0        0                NA                 0               0.0     0             NA              0
+VariantSummary  dbsnp    eval     none            novel           1        63025520     12       2.00            1.00              12                2.00            12.0        0                NA                 0               0.0     0             NA              0
+
diff --git a/public/gatk-engine/src/test/resources/exampleGRP.grp b/public/gatk-engine/src/test/resources/exampleGRP.grp
new file mode 100644
index 0000000..61a10ac
--- /dev/null
+++ b/public/gatk-engine/src/test/resources/exampleGRP.grp
@@ -0,0 +1,1118 @@
+#:GATKReport.v1.1:5
+#:GATKTable:2:18:%s:%s:;
+#:GATKTable:Arguments:Recalibration argument collection values used in this run
+Argument                    Value                                                                   
+binary_tag_name             null                                                                    
+covariate                   ReadGroupCovariate,QualityScoreCovariate,ContextCovariate,CycleCovariate
+default_platform            null                                                                    
+deletions_default_quality   45                                                                      
+force_platform              null                                                                    
+indels_context_size         3                                                                       
+insertions_default_quality  45                                                                      
+low_quality_tail            2                                                                       
+maximum_cycle_value         500                                                                     
+mismatches_context_size     2                                                                       
+mismatches_default_quality  -1                                                                      
+no_standard_covs            false                                                                   
+plot_pdf_file               null                                                                    
+quantizing_levels           16                                                                      
+recalibration_report        null                                                                    
+run_without_dbsnp           false                                                                   
+solid_nocall_strategy       THROW_EXCEPTION                                                         
+solid_recal_mode            SET_Q_ZERO                                                              
+
+#:GATKTable:3:94:%s:%s:%s:;
+#:GATKTable:Quantized:Quality quantization map
+QualityScore  Count  QuantizedScore
+           0      0               8
+           1      0               8
+           2      0               8
+           3      0               8
+           4      0               8
+           5      0               8
+           6     11               8
+           7      0               8
+           8      7               8
+           9      4               8
+          10      1               8
+          11      2               8
+          12      4              19
+          13      3              19
+          14      1              19
+          15      5              19
+          16     10              19
+          17      6              19
+          18      7              19
+          19     15              19
+          20      5              19
+          21     17              19
+          22      9              19
+          23     15              23
+          24     20              24
+          25     15              13
+          26      6              13
+          27     22              27
+          28     15              28
+          29     20              29
+          30     20              30
+          31     25              31
+          32     32              32
+          33     35              33
+          34     36              34
+          35      0              93
+          36      0              93
+          37      0              93
+          38      0              93
+          39      0              93
+          40      0              93
+          41      0              93
+          42      0              93
+          43      0              93
+          44      0              93
+          45    736              45
+          46      0              93
+          47      0              93
+          48      0              93
+          49      0              93
+          50      0              93
+          51      0              93
+          52      0              93
+          53      0              93
+          54      0              93
+          55      0              93
+          56      0              93
+          57      0              93
+          58      0              93
+          59      0              93
+          60      0              93
+          61      0              93
+          62      0              93
+          63      0              93
+          64      0              93
+          65      0              93
+          66      0              93
+          67      0              93
+          68      0              93
+          69      0              93
+          70      0              93
+          71      0              93
+          72      0              93
+          73      0              93
+          74      0              93
+          75      0              93
+          76      0              93
+          77      0              93
+          78      0              93
+          79      0              93
+          80      0              93
+          81      0              93
+          82      0              93
+          83      0              93
+          84      0              93
+          85      0              93
+          86      0              93
+          87      0              93
+          88      0              93
+          89      0              93
+          90      0              93
+          91      0              93
+          92      0              93
+          93      0              93
+
+#:GATKTable:6:3:%s:%s:%.4f:%.4f:%d:%.2f:;
+#:GATKTable:RecalTable0:
+ReadGroup       EventType  EmpiricalQuality  EstimatedQReported  Observations  Errors
+exampleBAM.bam  M                   17.0000             17.4959           368   11.00
+exampleBAM.bam  I                   45.0000             45.0000           368    0.00
+exampleBAM.bam  D                   45.0000             45.0000           368    0.00
+
+#:GATKTable:6:30:%s:%s:%s:%.4f:%d:%.2f:;
+#:GATKTable:RecalTable1:
+ReadGroup       QualityScore  EventType  EmpiricalQuality  Observations  Errors
+exampleBAM.bam             6  M                    6.0000            11    3.00
+exampleBAM.bam             8  M                    8.0000             7    1.00
+exampleBAM.bam             9  M                    9.0000             4    0.00
+exampleBAM.bam            10  M                   10.0000             1    0.00
+exampleBAM.bam            11  M                   11.0000             2    1.00
+exampleBAM.bam            12  M                   12.0000             4    0.00
+exampleBAM.bam            13  M                   13.0000             3    0.00
+exampleBAM.bam            14  M                   14.0000             1    0.00
+exampleBAM.bam            15  M                   15.0000             5    0.00
+exampleBAM.bam            16  M                   16.0000            10    1.00
+exampleBAM.bam            17  M                   17.0000             6    1.00
+exampleBAM.bam            18  M                   18.0000             7    1.00
+exampleBAM.bam            19  M                   19.0000            15    1.00
+exampleBAM.bam            20  M                   20.0000             5    1.00
+exampleBAM.bam            21  M                   21.0000            17    0.00
+exampleBAM.bam            22  M                   22.0000             9    0.00
+exampleBAM.bam            23  M                   23.0000            15    0.00
+exampleBAM.bam            24  M                   24.0000            20    1.00
+exampleBAM.bam            25  M                   25.0000            15    0.00
+exampleBAM.bam            26  M                   26.0000             6    0.00
+exampleBAM.bam            27  M                   27.0000            22    0.00
+exampleBAM.bam            28  M                   28.0000            15    0.00
+exampleBAM.bam            29  M                   29.0000            20    0.00
+exampleBAM.bam            30  M                   30.0000            20    0.00
+exampleBAM.bam            31  M                   31.0000            25    0.00
+exampleBAM.bam            32  M                   32.0000            32    0.00
+exampleBAM.bam            33  M                   33.0000            35    0.00
+exampleBAM.bam            34  M                   34.0000            36    0.00
+exampleBAM.bam            45  I                   45.0000           368    0.00
+exampleBAM.bam            45  D                   45.0000           368    0.00
+
+#:GATKTable:8:952:%s:%s:%s:%s:%s:%.4f:%d:%.2f:;
+#:GATKTable:RecalTable2:
+ReadGroup       QualityScore  CovariateValue  CovariateName  EventType  EmpiricalQuality  Observations  Errors
+exampleBAM.bam             6  AA              Context        M                    6.0000             1    0.00
+exampleBAM.bam             6  GA              Context        M                    6.0000             1    0.00
+exampleBAM.bam             6  GC              Context        M                    6.0000             2    2.00
+exampleBAM.bam             6  TG              Context        M                    6.0000             1    0.00
+exampleBAM.bam             6  AT              Context        M                    6.0000             1    0.00
+exampleBAM.bam             6  CT              Context        M                    6.0000             1    0.00
+exampleBAM.bam             6  GT              Context        M                    6.0000             2    0.00
+exampleBAM.bam             6  TT              Context        M                    6.0000             2    1.00
+exampleBAM.bam             8  AA              Context        M                    8.0000             1    0.00
+exampleBAM.bam             8  GA              Context        M                    8.0000             2    0.00
+exampleBAM.bam             8  GC              Context        M                    8.0000             1    0.00
+exampleBAM.bam             8  TG              Context        M                    8.0000             1    1.00
+exampleBAM.bam             8  GT              Context        M                    8.0000             2    0.00
+exampleBAM.bam             9  TG              Context        M                    9.0000             1    0.00
+exampleBAM.bam             9  AT              Context        M                    9.0000             1    0.00
+exampleBAM.bam             9  CT              Context        M                    9.0000             1    0.00
+exampleBAM.bam             9  GT              Context        M                    9.0000             1    0.00
+exampleBAM.bam            10  TT              Context        M                   10.0000             1    0.00
+exampleBAM.bam            11  TC              Context        M                   11.0000             1    1.00
+exampleBAM.bam            11  GT              Context        M                   11.0000             1    0.00
+exampleBAM.bam            12  GA              Context        M                   12.0000             1    0.00
+exampleBAM.bam            12  CC              Context        M                   12.0000             1    0.00
+exampleBAM.bam            12  TC              Context        M                   12.0000             1    0.00
+exampleBAM.bam            12  AG              Context        M                   12.0000             1    0.00
+exampleBAM.bam            13  AA              Context        M                   13.0000             1    0.00
+exampleBAM.bam            13  AG              Context        M                   13.0000             1    0.00
+exampleBAM.bam            13  AT              Context        M                   13.0000             1    0.00
+exampleBAM.bam            14  GA              Context        M                   14.0000             1    0.00
+exampleBAM.bam            15  AA              Context        M                   15.0000             2    0.00
+exampleBAM.bam            15  GA              Context        M                   15.0000             1    0.00
+exampleBAM.bam            15  GT              Context        M                   15.0000             2    0.00
+exampleBAM.bam            16  AA              Context        M                   16.0000             1    0.00
+exampleBAM.bam            16  TA              Context        M                   16.0000             4    1.00
+exampleBAM.bam            16  TC              Context        M                   16.0000             1    0.00
+exampleBAM.bam            16  GG              Context        M                   16.0000             1    0.00
+exampleBAM.bam            16  TG              Context        M                   16.0000             1    0.00
+exampleBAM.bam            16  CT              Context        M                   16.0000             1    0.00
+exampleBAM.bam            16  GT              Context        M                   16.0000             1    0.00
+exampleBAM.bam            17  CA              Context        M                   17.0000             1    0.00
+exampleBAM.bam            17  TA              Context        M                   17.0000             1    0.00
+exampleBAM.bam            17  TG              Context        M                   17.0000             1    1.00
+exampleBAM.bam            17  GT              Context        M                   17.0000             1    0.00
+exampleBAM.bam            17  TT              Context        M                   17.0000             2    0.00
+exampleBAM.bam            18  AC              Context        M                   18.0000             1    0.00
+exampleBAM.bam            18  TC              Context        M                   18.0000             1    1.00
+exampleBAM.bam            18  AT              Context        M                   18.0000             1    0.00
+exampleBAM.bam            18  GT              Context        M                   18.0000             1    0.00
+exampleBAM.bam            18  TT              Context        M                   18.0000             2    0.00
+exampleBAM.bam            19  AA              Context        M                   19.0000             2    0.00
+exampleBAM.bam            19  CA              Context        M                   19.0000             2    0.00
+exampleBAM.bam            19  GA              Context        M                   19.0000             2    0.00
+exampleBAM.bam            19  TA              Context        M                   19.0000             3    0.00
+exampleBAM.bam            19  GC              Context        M                   19.0000             1    0.00
+exampleBAM.bam            19  GG              Context        M                   19.0000             1    0.00
+exampleBAM.bam            19  TG              Context        M                   19.0000             2    1.00
+exampleBAM.bam            19  GT              Context        M                   19.0000             1    0.00
+exampleBAM.bam            19  TT              Context        M                   19.0000             1    0.00
+exampleBAM.bam            20  AA              Context        M                   20.0000             1    0.00
+exampleBAM.bam            20  CA              Context        M                   20.0000             1    0.00
+exampleBAM.bam            20  CC              Context        M                   20.0000             1    0.00
+exampleBAM.bam            20  TG              Context        M                   20.0000             1    0.00
+exampleBAM.bam            20  TT              Context        M                   20.0000             1    1.00
+exampleBAM.bam            21  CA              Context        M                   21.0000             1    0.00
+exampleBAM.bam            21  GA              Context        M                   21.0000             1    0.00
+exampleBAM.bam            21  TA              Context        M                   21.0000             1    0.00
+exampleBAM.bam            21  CC              Context        M                   21.0000             1    0.00
+exampleBAM.bam            21  TC              Context        M                   21.0000             2    0.00
+exampleBAM.bam            21  AG              Context        M                   21.0000             1    0.00
+exampleBAM.bam            21  GG              Context        M                   21.0000             4    0.00
+exampleBAM.bam            21  TG              Context        M                   21.0000             1    0.00
+exampleBAM.bam            21  AT              Context        M                   21.0000             2    0.00
+exampleBAM.bam            21  CT              Context        M                   21.0000             1    0.00
+exampleBAM.bam            21  GT              Context        M                   21.0000             2    0.00
+exampleBAM.bam            22  CA              Context        M                   22.0000             1    0.00
+exampleBAM.bam            22  GA              Context        M                   22.0000             3    0.00
+exampleBAM.bam            22  TA              Context        M                   22.0000             1    0.00
+exampleBAM.bam            22  GC              Context        M                   22.0000             1    0.00
+exampleBAM.bam            22  GG              Context        M                   22.0000             1    0.00
+exampleBAM.bam            22  TG              Context        M                   22.0000             1    0.00
+exampleBAM.bam            22  TT              Context        M                   22.0000             1    0.00
+exampleBAM.bam            23  AA              Context        M                   23.0000             1    0.00
+exampleBAM.bam            23  CA              Context        M                   23.0000             1    0.00
+exampleBAM.bam            23  TA              Context        M                   23.0000             1    0.00
+exampleBAM.bam            23  CC              Context        M                   23.0000             2    0.00
+exampleBAM.bam            23  GC              Context        M                   23.0000             1    0.00
+exampleBAM.bam            23  TC              Context        M                   23.0000             2    0.00
+exampleBAM.bam            23  GG              Context        M                   23.0000             1    0.00
+exampleBAM.bam            23  TG              Context        M                   23.0000             3    0.00
+exampleBAM.bam            23  AT              Context        M                   23.0000             1    0.00
+exampleBAM.bam            23  TT              Context        M                   23.0000             2    0.00
+exampleBAM.bam            24  CA              Context        M                   24.0000             3    0.00
+exampleBAM.bam            24  GA              Context        M                   24.0000             2    0.00
+exampleBAM.bam            24  TA              Context        M                   24.0000             2    1.00
+exampleBAM.bam            24  GC              Context        M                   24.0000             1    0.00
+exampleBAM.bam            24  AG              Context        M                   24.0000             2    0.00
+exampleBAM.bam            24  CG              Context        M                   24.0000             1    0.00
+exampleBAM.bam            24  GG              Context        M                   24.0000             3    0.00
+exampleBAM.bam            24  AT              Context        M                   24.0000             1    0.00
+exampleBAM.bam            24  CT              Context        M                   24.0000             1    0.00
+exampleBAM.bam            24  GT              Context        M                   24.0000             1    0.00
+exampleBAM.bam            24  TT              Context        M                   24.0000             3    0.00
+exampleBAM.bam            25  AA              Context        M                   25.0000             2    0.00
+exampleBAM.bam            25  CA              Context        M                   25.0000             1    0.00
+exampleBAM.bam            25  GG              Context        M                   25.0000             2    0.00
+exampleBAM.bam            25  TG              Context        M                   25.0000             2    0.00
+exampleBAM.bam            25  AT              Context        M                   25.0000             2    0.00
+exampleBAM.bam            25  GT              Context        M                   25.0000             1    0.00
+exampleBAM.bam            25  TT              Context        M                   25.0000             5    0.00
+exampleBAM.bam            26  TA              Context        M                   26.0000             1    0.00
+exampleBAM.bam            26  GG              Context        M                   26.0000             1    0.00
+exampleBAM.bam            26  TG              Context        M                   26.0000             1    0.00
+exampleBAM.bam            26  AT              Context        M                   26.0000             1    0.00
+exampleBAM.bam            26  GT              Context        M                   26.0000             1    0.00
+exampleBAM.bam            26  TT              Context        M                   26.0000             1    0.00
+exampleBAM.bam            27  AA              Context        M                   27.0000             2    0.00
+exampleBAM.bam            27  CA              Context        M                   27.0000             1    0.00
+exampleBAM.bam            27  TA              Context        M                   27.0000             1    0.00
+exampleBAM.bam            27  TC              Context        M                   27.0000             2    0.00
+exampleBAM.bam            27  AG              Context        M                   27.0000             3    0.00
+exampleBAM.bam            27  GG              Context        M                   27.0000             3    0.00
+exampleBAM.bam            27  TG              Context        M                   27.0000             2    0.00
+exampleBAM.bam            27  AT              Context        M                   27.0000             4    0.00
+exampleBAM.bam            27  CT              Context        M                   27.0000             2    0.00
+exampleBAM.bam            27  TT              Context        M                   27.0000             2    0.00
+exampleBAM.bam            28  AA              Context        M                   28.0000             1    0.00
+exampleBAM.bam            28  CA              Context        M                   28.0000             1    0.00
+exampleBAM.bam            28  TA              Context        M                   28.0000             2    0.00
+exampleBAM.bam            28  AG              Context        M                   28.0000             3    0.00
+exampleBAM.bam            28  GG              Context        M                   28.0000             3    0.00
+exampleBAM.bam            28  TG              Context        M                   28.0000             1    0.00
+exampleBAM.bam            28  GT              Context        M                   28.0000             4    0.00
+exampleBAM.bam            29  CA              Context        M                   29.0000             1    0.00
+exampleBAM.bam            29  TA              Context        M                   29.0000             1    0.00
+exampleBAM.bam            29  AC              Context        M                   29.0000             1    0.00
+exampleBAM.bam            29  CC              Context        M                   29.0000             1    0.00
+exampleBAM.bam            29  GC              Context        M                   29.0000             1    0.00
+exampleBAM.bam            29  AG              Context        M                   29.0000             3    0.00
+exampleBAM.bam            29  CG              Context        M                   29.0000             1    0.00
+exampleBAM.bam            29  GG              Context        M                   29.0000             4    0.00
+exampleBAM.bam            29  TG              Context        M                   29.0000             1    0.00
+exampleBAM.bam            29  AT              Context        M                   29.0000             1    0.00
+exampleBAM.bam            29  GT              Context        M                   29.0000             1    0.00
+exampleBAM.bam            29  TT              Context        M                   29.0000             4    0.00
+exampleBAM.bam            30  AA              Context        M                   30.0000             2    0.00
+exampleBAM.bam            30  CA              Context        M                   30.0000             1    0.00
+exampleBAM.bam            30  AC              Context        M                   30.0000             4    0.00
+exampleBAM.bam            30  CC              Context        M                   30.0000             1    0.00
+exampleBAM.bam            30  TC              Context        M                   30.0000             2    0.00
+exampleBAM.bam            30  AG              Context        M                   30.0000             3    0.00
+exampleBAM.bam            30  GG              Context        M                   30.0000             1    0.00
+exampleBAM.bam            30  TG              Context        M                   30.0000             1    0.00
+exampleBAM.bam            30  AT              Context        M                   30.0000             2    0.00
+exampleBAM.bam            30  CT              Context        M                   30.0000             2    0.00
+exampleBAM.bam            30  GT              Context        M                   30.0000             1    0.00
+exampleBAM.bam            31  CA              Context        M                   31.0000             1    0.00
+exampleBAM.bam            31  GA              Context        M                   31.0000             1    0.00
+exampleBAM.bam            31  CC              Context        M                   31.0000             2    0.00
+exampleBAM.bam            31  GC              Context        M                   31.0000             2    0.00
+exampleBAM.bam            31  AG              Context        M                   31.0000             2    0.00
+exampleBAM.bam            31  GG              Context        M                   31.0000             6    0.00
+exampleBAM.bam            31  TG              Context        M                   31.0000             2    0.00
+exampleBAM.bam            31  AT              Context        M                   31.0000             2    0.00
+exampleBAM.bam            31  CT              Context        M                   31.0000             2    0.00
+exampleBAM.bam            31  GT              Context        M                   31.0000             1    0.00
+exampleBAM.bam            31  TT              Context        M                   31.0000             3    0.00
+exampleBAM.bam            32  CA              Context        M                   32.0000             2    0.00
+exampleBAM.bam            32  TA              Context        M                   32.0000             1    0.00
+exampleBAM.bam            32  AC              Context        M                   32.0000             1    0.00
+exampleBAM.bam            32  CC              Context        M                   32.0000             1    0.00
+exampleBAM.bam            32  TC              Context        M                   32.0000             1    0.00
+exampleBAM.bam            32  AG              Context        M                   32.0000             1    0.00
+exampleBAM.bam            32  CG              Context        M                   32.0000             1    0.00
+exampleBAM.bam            32  GG              Context        M                   32.0000             8    0.00
+exampleBAM.bam            32  TG              Context        M                   32.0000             3    0.00
+exampleBAM.bam            32  AT              Context        M                   32.0000             4    0.00
+exampleBAM.bam            32  CT              Context        M                   32.0000             2    0.00
+exampleBAM.bam            32  TT              Context        M                   32.0000             6    0.00
+exampleBAM.bam            33  CA              Context        M                   33.0000             2    0.00
+exampleBAM.bam            33  GA              Context        M                   33.0000             2    0.00
+exampleBAM.bam            33  TA              Context        M                   33.0000             1    0.00
+exampleBAM.bam            33  AC              Context        M                   33.0000             1    0.00
+exampleBAM.bam            33  CC              Context        M                   33.0000             2    0.00
+exampleBAM.bam            33  GC              Context        M                   33.0000             1    0.00
+exampleBAM.bam            33  TC              Context        M                   33.0000             3    0.00
+exampleBAM.bam            33  AG              Context        M                   33.0000             2    0.00
+exampleBAM.bam            33  CG              Context        M                   33.0000             1    0.00
+exampleBAM.bam            33  GG              Context        M                   33.0000             2    0.00
+exampleBAM.bam            33  TG              Context        M                   33.0000             5    0.00
+exampleBAM.bam            33  AT              Context        M                   33.0000             2    0.00
+exampleBAM.bam            33  CT              Context        M                   33.0000             4    0.00
+exampleBAM.bam            33  GT              Context        M                   33.0000             1    0.00
+exampleBAM.bam            33  TT              Context        M                   33.0000             4    0.00
+exampleBAM.bam            34  AA              Context        M                   34.0000             1    0.00
+exampleBAM.bam            34  CA              Context        M                   34.0000             3    0.00
+exampleBAM.bam            34  GA              Context        M                   34.0000             1    0.00
+exampleBAM.bam            34  TA              Context        M                   34.0000             2    0.00
+exampleBAM.bam            34  AC              Context        M                   34.0000             1    0.00
+exampleBAM.bam            34  CC              Context        M                   34.0000             1    0.00
+exampleBAM.bam            34  GC              Context        M                   34.0000             2    0.00
+exampleBAM.bam            34  TC              Context        M                   34.0000             6    0.00
+exampleBAM.bam            34  AG              Context        M                   34.0000             1    0.00
+exampleBAM.bam            34  CG              Context        M                   34.0000             1    0.00
+exampleBAM.bam            34  GG              Context        M                   34.0000             1    0.00
+exampleBAM.bam            34  TG              Context        M                   34.0000             4    0.00
+exampleBAM.bam            34  AT              Context        M                   34.0000             4    0.00
+exampleBAM.bam            34  CT              Context        M                   34.0000             2    0.00
+exampleBAM.bam            34  GT              Context        M                   34.0000             1    0.00
+exampleBAM.bam            34  TT              Context        M                   34.0000             5    0.00
+exampleBAM.bam            45  AAA             Context        I                   45.0000             5    0.00
+exampleBAM.bam            45  AAA             Context        D                   45.0000             5    0.00
+exampleBAM.bam            45  CAA             Context        I                   45.0000             5    0.00
+exampleBAM.bam            45  CAA             Context        D                   45.0000             5    0.00
+exampleBAM.bam            45  GAA             Context        I                   45.0000             2    0.00
+exampleBAM.bam            45  GAA             Context        D                   45.0000             2    0.00
+exampleBAM.bam            45  TAA             Context        I                   45.0000             6    0.00
+exampleBAM.bam            45  TAA             Context        D                   45.0000             6    0.00
+exampleBAM.bam            45  ACA             Context        I                   45.0000             4    0.00
+exampleBAM.bam            45  ACA             Context        D                   45.0000             4    0.00
+exampleBAM.bam            45  CCA             Context        I                   45.0000             8    0.00
+exampleBAM.bam            45  CCA             Context        D                   45.0000             8    0.00
+exampleBAM.bam            45  GCA             Context        I                   45.0000             5    0.00
+exampleBAM.bam            45  GCA             Context        D                   45.0000             5    0.00
+exampleBAM.bam            45  TCA             Context        I                   45.0000             6    0.00
+exampleBAM.bam            45  TCA             Context        D                   45.0000             6    0.00
+exampleBAM.bam            45  AGA             Context        I                   45.0000             5    0.00
+exampleBAM.bam            45  AGA             Context        D                   45.0000             5    0.00
+exampleBAM.bam            45  GGA             Context        I                   45.0000             3    0.00
+exampleBAM.bam            45  GGA             Context        D                   45.0000             3    0.00
+exampleBAM.bam            45  TGA             Context        I                   45.0000            10    0.00
+exampleBAM.bam            45  TGA             Context        D                   45.0000            10    0.00
+exampleBAM.bam            45  ATA             Context        I                   45.0000             6    0.00
+exampleBAM.bam            45  ATA             Context        D                   45.0000             6    0.00
+exampleBAM.bam            45  CTA             Context        I                   45.0000             3    0.00
+exampleBAM.bam            45  CTA             Context        D                   45.0000             3    0.00
+exampleBAM.bam            45  GTA             Context        I                   45.0000             2    0.00
+exampleBAM.bam            45  GTA             Context        D                   45.0000             2    0.00
+exampleBAM.bam            45  TTA             Context        I                   45.0000            11    0.00
+exampleBAM.bam            45  TTA             Context        D                   45.0000            11    0.00
+exampleBAM.bam            45  CAC             Context        I                   45.0000             6    0.00
+exampleBAM.bam            45  CAC             Context        D                   45.0000             6    0.00
+exampleBAM.bam            45  GAC             Context        I                   45.0000             2    0.00
+exampleBAM.bam            45  GAC             Context        D                   45.0000             2    0.00
+exampleBAM.bam            45  TAC             Context        I                   45.0000             1    0.00
+exampleBAM.bam            45  TAC             Context        D                   45.0000             1    0.00
+exampleBAM.bam            45  ACC             Context        I                   45.0000             3    0.00
+exampleBAM.bam            45  ACC             Context        D                   45.0000             3    0.00
+exampleBAM.bam            45  CCC             Context        I                   45.0000             1    0.00
+exampleBAM.bam            45  CCC             Context        D                   45.0000             1    0.00
+exampleBAM.bam            45  GCC             Context        I                   45.0000             5    0.00
+exampleBAM.bam            45  GCC             Context        D                   45.0000             5    0.00
+exampleBAM.bam            45  TCC             Context        I                   45.0000             4    0.00
+exampleBAM.bam            45  TCC             Context        D                   45.0000             4    0.00
+exampleBAM.bam            45  AGC             Context        I                   45.0000             3    0.00
+exampleBAM.bam            45  AGC             Context        D                   45.0000             3    0.00
+exampleBAM.bam            45  GGC             Context        I                   45.0000             6    0.00
+exampleBAM.bam            45  GGC             Context        D                   45.0000             6    0.00
+exampleBAM.bam            45  TGC             Context        I                   45.0000             4    0.00
+exampleBAM.bam            45  TGC             Context        D                   45.0000             4    0.00
+exampleBAM.bam            45  ATC             Context        I                   45.0000             7    0.00
+exampleBAM.bam            45  ATC             Context        D                   45.0000             7    0.00
+exampleBAM.bam            45  CTC             Context        I                   45.0000             3    0.00
+exampleBAM.bam            45  CTC             Context        D                   45.0000             3    0.00
+exampleBAM.bam            45  GTC             Context        I                   45.0000             3    0.00
+exampleBAM.bam            45  GTC             Context        D                   45.0000             3    0.00
+exampleBAM.bam            45  TTC             Context        I                   45.0000             9    0.00
+exampleBAM.bam            45  TTC             Context        D                   45.0000             9    0.00
+exampleBAM.bam            45  AAG             Context        I                   45.0000             4    0.00
+exampleBAM.bam            45  AAG             Context        D                   45.0000             4    0.00
+exampleBAM.bam            45  CAG             Context        I                   45.0000             7    0.00
+exampleBAM.bam            45  CAG             Context        D                   45.0000             7    0.00
+exampleBAM.bam            45  GAG             Context        I                   45.0000             6    0.00
+exampleBAM.bam            45  GAG             Context        D                   45.0000             6    0.00
+exampleBAM.bam            45  TAG             Context        I                   45.0000             5    0.00
+exampleBAM.bam            45  TAG             Context        D                   45.0000             5    0.00
+exampleBAM.bam            45  TCG             Context        I                   45.0000             5    0.00
+exampleBAM.bam            45  TCG             Context        D                   45.0000             5    0.00
+exampleBAM.bam            45  AGG             Context        I                   45.0000             7    0.00
+exampleBAM.bam            45  AGG             Context        D                   45.0000             7    0.00
+exampleBAM.bam            45  CGG             Context        I                   45.0000             3    0.00
+exampleBAM.bam            45  CGG             Context        D                   45.0000             3    0.00
+exampleBAM.bam            45  GGG             Context        I                   45.0000            16    0.00
+exampleBAM.bam            45  GGG             Context        D                   45.0000            16    0.00
+exampleBAM.bam            45  TGG             Context        I                   45.0000            16    0.00
+exampleBAM.bam            45  TGG             Context        D                   45.0000            16    0.00
+exampleBAM.bam            45  ATG             Context        I                   45.0000             8    0.00
+exampleBAM.bam            45  ATG             Context        D                   45.0000             8    0.00
+exampleBAM.bam            45  CTG             Context        I                   45.0000             6    0.00
+exampleBAM.bam            45  CTG             Context        D                   45.0000             6    0.00
+exampleBAM.bam            45  GTG             Context        I                   45.0000             8    0.00
+exampleBAM.bam            45  GTG             Context        D                   45.0000             8    0.00
+exampleBAM.bam            45  TTG             Context        I                   45.0000            11    0.00
+exampleBAM.bam            45  TTG             Context        D                   45.0000            11    0.00
+exampleBAM.bam            45  AAT             Context        I                   45.0000             7    0.00
+exampleBAM.bam            45  AAT             Context        D                   45.0000             7    0.00
+exampleBAM.bam            45  CAT             Context        I                   45.0000             6    0.00
+exampleBAM.bam            45  CAT             Context        D                   45.0000             6    0.00
+exampleBAM.bam            45  GAT             Context        I                   45.0000             8    0.00
+exampleBAM.bam            45  GAT             Context        D                   45.0000             8    0.00
+exampleBAM.bam            45  TAT             Context        I                   45.0000             9    0.00
+exampleBAM.bam            45  TAT             Context        D                   45.0000             9    0.00
+exampleBAM.bam            45  ACT             Context        I                   45.0000             4    0.00
+exampleBAM.bam            45  ACT             Context        D                   45.0000             4    0.00
+exampleBAM.bam            45  CCT             Context        I                   45.0000             4    0.00
+exampleBAM.bam            45  CCT             Context        D                   45.0000             4    0.00
+exampleBAM.bam            45  GCT             Context        I                   45.0000             2    0.00
+exampleBAM.bam            45  GCT             Context        D                   45.0000             2    0.00
+exampleBAM.bam            45  TCT             Context        I                   45.0000             8    0.00
+exampleBAM.bam            45  TCT             Context        D                   45.0000             8    0.00
+exampleBAM.bam            45  AGT             Context        I                   45.0000             5    0.00
+exampleBAM.bam            45  AGT             Context        D                   45.0000             5    0.00
+exampleBAM.bam            45  CGT             Context        I                   45.0000             2    0.00
+exampleBAM.bam            45  CGT             Context        D                   45.0000             2    0.00
+exampleBAM.bam            45  GGT             Context        I                   45.0000            13    0.00
+exampleBAM.bam            45  GGT             Context        D                   45.0000            13    0.00
+exampleBAM.bam            45  TGT             Context        I                   45.0000             5    0.00
+exampleBAM.bam            45  TGT             Context        D                   45.0000             5    0.00
+exampleBAM.bam            45  ATT             Context        I                   45.0000             9    0.00
+exampleBAM.bam            45  ATT             Context        D                   45.0000             9    0.00
+exampleBAM.bam            45  CTT             Context        I                   45.0000             7    0.00
+exampleBAM.bam            45  CTT             Context        D                   45.0000             7    0.00
+exampleBAM.bam            45  GTT             Context        I                   45.0000            17    0.00
+exampleBAM.bam            45  GTT             Context        D                   45.0000            17    0.00
+exampleBAM.bam            45  TTT             Context        I                   45.0000            12    0.00
+exampleBAM.bam            45  TTT             Context        D                   45.0000            12    0.00
+exampleBAM.bam             6  -4              Cycle          M                    6.0000             1    0.00
+exampleBAM.bam             6  31              Cycle          M                    6.0000             1    1.00
+exampleBAM.bam             6  36              Cycle          M                    6.0000             1    0.00
+exampleBAM.bam             6  -52             Cycle          M                    6.0000             1    1.00
+exampleBAM.bam             6  -62             Cycle          M                    6.0000             1    0.00
+exampleBAM.bam             6  63              Cycle          M                    6.0000             1    0.00
+exampleBAM.bam             6  -63             Cycle          M                    6.0000             1    0.00
+exampleBAM.bam             6  -65             Cycle          M                    6.0000             1    0.00
+exampleBAM.bam             6  67              Cycle          M                    6.0000             1    0.00
+exampleBAM.bam             6  -68             Cycle          M                    6.0000             1    1.00
+exampleBAM.bam             6  75              Cycle          M                    6.0000             1    0.00
+exampleBAM.bam             8  17              Cycle          M                    8.0000             1    0.00
+exampleBAM.bam             8  46              Cycle          M                    8.0000             1    0.00
+exampleBAM.bam             8  57              Cycle          M                    8.0000             1    1.00
+exampleBAM.bam             8  58              Cycle          M                    8.0000             1    0.00
+exampleBAM.bam             8  60              Cycle          M                    8.0000             1    0.00
+exampleBAM.bam             8  63              Cycle          M                    8.0000             1    0.00
+exampleBAM.bam             8  71              Cycle          M                    8.0000             1    0.00
+exampleBAM.bam             9  -16             Cycle          M                    9.0000             1    0.00
+exampleBAM.bam             9  38              Cycle          M                    9.0000             1    0.00
+exampleBAM.bam             9  52              Cycle          M                    9.0000             1    0.00
+exampleBAM.bam             9  69              Cycle          M                    9.0000             1    0.00
+exampleBAM.bam            10  -75             Cycle          M                   10.0000             1    0.00
+exampleBAM.bam            11  -20             Cycle          M                   11.0000             1    0.00
+exampleBAM.bam            11  -40             Cycle          M                   11.0000             1    1.00
+exampleBAM.bam            12  25              Cycle          M                   12.0000             1    0.00
+exampleBAM.bam            12  40              Cycle          M                   12.0000             1    0.00
+exampleBAM.bam            12  62              Cycle          M                   12.0000             1    0.00
+exampleBAM.bam            12  68              Cycle          M                   12.0000             1    0.00
+exampleBAM.bam            13  39              Cycle          M                   13.0000             1    0.00
+exampleBAM.bam            13  55              Cycle          M                   13.0000             1    0.00
+exampleBAM.bam            13  75              Cycle          M                   13.0000             1    0.00
+exampleBAM.bam            14  -33             Cycle          M                   14.0000             1    0.00
+exampleBAM.bam            15  -8              Cycle          M                   15.0000             1    0.00
+exampleBAM.bam            15  -14             Cycle          M                   15.0000             1    0.00
+exampleBAM.bam            15  35              Cycle          M                   15.0000             1    0.00
+exampleBAM.bam            15  68              Cycle          M                   15.0000             1    0.00
+exampleBAM.bam            15  74              Cycle          M                   15.0000             1    0.00
+exampleBAM.bam            16  7               Cycle          M                   16.0000             1    0.00
+exampleBAM.bam            16  19              Cycle          M                   16.0000             1    0.00
+exampleBAM.bam            16  -34             Cycle          M                   16.0000             1    1.00
+exampleBAM.bam            16  -47             Cycle          M                   16.0000             1    0.00
+exampleBAM.bam            16  51              Cycle          M                   16.0000             1    0.00
+exampleBAM.bam            16  -55             Cycle          M                   16.0000             1    0.00
+exampleBAM.bam            16  -58             Cycle          M                   16.0000             1    0.00
+exampleBAM.bam            16  -65             Cycle          M                   16.0000             1    0.00
+exampleBAM.bam            16  70              Cycle          M                   16.0000             1    0.00
+exampleBAM.bam            16  73              Cycle          M                   16.0000             1    0.00
+exampleBAM.bam            17  -4              Cycle          M                   17.0000             1    0.00
+exampleBAM.bam            17  -20             Cycle          M                   17.0000             1    0.00
+exampleBAM.bam            17  58              Cycle          M                   17.0000             1    0.00
+exampleBAM.bam            17  62              Cycle          M                   17.0000             1    0.00
+exampleBAM.bam            17  -63             Cycle          M                   17.0000             1    0.00
+exampleBAM.bam            17  -76             Cycle          M                   17.0000             1    1.00
+exampleBAM.bam            18  -1              Cycle          M                   18.0000             1    0.00
+exampleBAM.bam            18  10              Cycle          M                   18.0000             1    0.00
+exampleBAM.bam            18  -19             Cycle          M                   18.0000             1    0.00
+exampleBAM.bam            18  22              Cycle          M                   18.0000             1    0.00
+exampleBAM.bam            18  36              Cycle          M                   18.0000             1    0.00
+exampleBAM.bam            18  -56             Cycle          M                   18.0000             1    0.00
+exampleBAM.bam            18  -58             Cycle          M                   18.0000             1    1.00
+exampleBAM.bam            19  5               Cycle          M                   19.0000             1    0.00
+exampleBAM.bam            19  -7              Cycle          M                   19.0000             1    0.00
+exampleBAM.bam            19  10              Cycle          M                   19.0000             1    0.00
+exampleBAM.bam            19  21              Cycle          M                   19.0000             2    0.00
+exampleBAM.bam            19  -30             Cycle          M                   19.0000             1    0.00
+exampleBAM.bam            19  32              Cycle          M                   19.0000             1    0.00
+exampleBAM.bam            19  33              Cycle          M                   19.0000             1    0.00
+exampleBAM.bam            19  49              Cycle          M                   19.0000             1    0.00
+exampleBAM.bam            19  54              Cycle          M                   19.0000             1    0.00
+exampleBAM.bam            19  61              Cycle          M                   19.0000             1    0.00
+exampleBAM.bam            19  65              Cycle          M                   19.0000             1    0.00
+exampleBAM.bam            19  -70             Cycle          M                   19.0000             1    1.00
+exampleBAM.bam            19  -71             Cycle          M                   19.0000             1    0.00
+exampleBAM.bam            19  72              Cycle          M                   19.0000             1    0.00
+exampleBAM.bam            20  9               Cycle          M                   20.0000             1    0.00
+exampleBAM.bam            20  -28             Cycle          M                   20.0000             1    1.00
+exampleBAM.bam            20  -29             Cycle          M                   20.0000             1    0.00
+exampleBAM.bam            20  -57             Cycle          M                   20.0000             1    0.00
+exampleBAM.bam            20  69              Cycle          M                   20.0000             1    0.00
+exampleBAM.bam            21  -3              Cycle          M                   21.0000             1    0.00
+exampleBAM.bam            21  11              Cycle          M                   21.0000             1    0.00
+exampleBAM.bam            21  17              Cycle          M                   21.0000             1    0.00
+exampleBAM.bam            21  29              Cycle          M                   21.0000             1    0.00
+exampleBAM.bam            21  -42             Cycle          M                   21.0000             1    0.00
+exampleBAM.bam            21  -44             Cycle          M                   21.0000             1    0.00
+exampleBAM.bam            21  48              Cycle          M                   21.0000             1    0.00
+exampleBAM.bam            21  -50             Cycle          M                   21.0000             1    0.00
+exampleBAM.bam            21  59              Cycle          M                   21.0000             1    0.00
+exampleBAM.bam            21  -60             Cycle          M                   21.0000             1    0.00
+exampleBAM.bam            21  -61             Cycle          M                   21.0000             1    0.00
+exampleBAM.bam            21  64              Cycle          M                   21.0000             1    0.00
+exampleBAM.bam            21  66              Cycle          M                   21.0000             1    0.00
+exampleBAM.bam            21  67              Cycle          M                   21.0000             1    0.00
+exampleBAM.bam            21  71              Cycle          M                   21.0000             1    0.00
+exampleBAM.bam            21  73              Cycle          M                   21.0000             1    0.00
+exampleBAM.bam            21  74              Cycle          M                   21.0000             1    0.00
+exampleBAM.bam            22  -9              Cycle          M                   22.0000             1    0.00
+exampleBAM.bam            22  -15             Cycle          M                   22.0000             1    0.00
+exampleBAM.bam            22  -23             Cycle          M                   22.0000             1    0.00
+exampleBAM.bam            22  38              Cycle          M                   22.0000             1    0.00
+exampleBAM.bam            22  44              Cycle          M                   22.0000             1    0.00
+exampleBAM.bam            22  -44             Cycle          M                   22.0000             1    0.00
+exampleBAM.bam            22  51              Cycle          M                   22.0000             1    0.00
+exampleBAM.bam            22  -59             Cycle          M                   22.0000             1    0.00
+exampleBAM.bam            22  -70             Cycle          M                   22.0000             1    0.00
+exampleBAM.bam            23  -12             Cycle          M                   23.0000             1    0.00
+exampleBAM.bam            23  -15             Cycle          M                   23.0000             1    0.00
+exampleBAM.bam            23  18              Cycle          M                   23.0000             1    0.00
+exampleBAM.bam            23  19              Cycle          M                   23.0000             1    0.00
+exampleBAM.bam            23  -35             Cycle          M                   23.0000             1    0.00
+exampleBAM.bam            23  37              Cycle          M                   23.0000             1    0.00
+exampleBAM.bam            23  -38             Cycle          M                   23.0000             1    0.00
+exampleBAM.bam            23  56              Cycle          M                   23.0000             1    0.00
+exampleBAM.bam            23  59              Cycle          M                   23.0000             1    0.00
+exampleBAM.bam            23  61              Cycle          M                   23.0000             1    0.00
+exampleBAM.bam            23  64              Cycle          M                   23.0000             1    0.00
+exampleBAM.bam            23  -64             Cycle          M                   23.0000             1    0.00
+exampleBAM.bam            23  66              Cycle          M                   23.0000             1    0.00
+exampleBAM.bam            23  -67             Cycle          M                   23.0000             1    0.00
+exampleBAM.bam            23  -75             Cycle          M                   23.0000             1    0.00
+exampleBAM.bam            24  3               Cycle          M                   24.0000             1    0.00
+exampleBAM.bam            24  5               Cycle          M                   24.0000             1    0.00
+exampleBAM.bam            24  6               Cycle          M                   24.0000             1    0.00
+exampleBAM.bam            24  -6              Cycle          M                   24.0000             1    0.00
+exampleBAM.bam            24  -10             Cycle          M                   24.0000             1    1.00
+exampleBAM.bam            24  13              Cycle          M                   24.0000             2    0.00
+exampleBAM.bam            24  -13             Cycle          M                   24.0000             1    0.00
+exampleBAM.bam            24  -25             Cycle          M                   24.0000             1    0.00
+exampleBAM.bam            24  27              Cycle          M                   24.0000             1    0.00
+exampleBAM.bam            24  33              Cycle          M                   24.0000             1    0.00
+exampleBAM.bam            24  41              Cycle          M                   24.0000             1    0.00
+exampleBAM.bam            24  45              Cycle          M                   24.0000             1    0.00
+exampleBAM.bam            24  -48             Cycle          M                   24.0000             1    0.00
+exampleBAM.bam            24  -49             Cycle          M                   24.0000             1    0.00
+exampleBAM.bam            24  50              Cycle          M                   24.0000             1    0.00
+exampleBAM.bam            24  52              Cycle          M                   24.0000             1    0.00
+exampleBAM.bam            24  53              Cycle          M                   24.0000             1    0.00
+exampleBAM.bam            24  56              Cycle          M                   24.0000             1    0.00
+exampleBAM.bam            24  -62             Cycle          M                   24.0000             1    0.00
+exampleBAM.bam            25  -9              Cycle          M                   25.0000             1    0.00
+exampleBAM.bam            25  14              Cycle          M                   25.0000             1    0.00
+exampleBAM.bam            25  -21             Cycle          M                   25.0000             1    0.00
+exampleBAM.bam            25  -24             Cycle          M                   25.0000             1    0.00
+exampleBAM.bam            25  31              Cycle          M                   25.0000             1    0.00
+exampleBAM.bam            25  -32             Cycle          M                   25.0000             1    0.00
+exampleBAM.bam            25  -36             Cycle          M                   25.0000             1    0.00
+exampleBAM.bam            25  37              Cycle          M                   25.0000             1    0.00
+exampleBAM.bam            25  46              Cycle          M                   25.0000             1    0.00
+exampleBAM.bam            25  47              Cycle          M                   25.0000             1    0.00
+exampleBAM.bam            25  -51             Cycle          M                   25.0000             1    0.00
+exampleBAM.bam            25  -52             Cycle          M                   25.0000             1    0.00
+exampleBAM.bam            25  55              Cycle          M                   25.0000             1    0.00
+exampleBAM.bam            25  -73             Cycle          M                   25.0000             1    0.00
+exampleBAM.bam            25  -74             Cycle          M                   25.0000             1    0.00
+exampleBAM.bam            26  -3              Cycle          M                   26.0000             1    0.00
+exampleBAM.bam            26  7               Cycle          M                   26.0000             1    0.00
+exampleBAM.bam            26  20              Cycle          M                   26.0000             1    0.00
+exampleBAM.bam            26  -44             Cycle          M                   26.0000             1    0.00
+exampleBAM.bam            26  50              Cycle          M                   26.0000             1    0.00
+exampleBAM.bam            26  -67             Cycle          M                   26.0000             1    0.00
+exampleBAM.bam            27  11              Cycle          M                   27.0000             1    0.00
+exampleBAM.bam            27  14              Cycle          M                   27.0000             1    0.00
+exampleBAM.bam            27  16              Cycle          M                   27.0000             1    0.00
+exampleBAM.bam            27  -17             Cycle          M                   27.0000             1    0.00
+exampleBAM.bam            27  -18             Cycle          M                   27.0000             1    0.00
+exampleBAM.bam            27  22              Cycle          M                   27.0000             1    0.00
+exampleBAM.bam            27  -27             Cycle          M                   27.0000             1    0.00
+exampleBAM.bam            27  28              Cycle          M                   27.0000             1    0.00
+exampleBAM.bam            27  30              Cycle          M                   27.0000             1    0.00
+exampleBAM.bam            27  -31             Cycle          M                   27.0000             1    0.00
+exampleBAM.bam            27  40              Cycle          M                   27.0000             1    0.00
+exampleBAM.bam            27  53              Cycle          M                   27.0000             1    0.00
+exampleBAM.bam            27  -53             Cycle          M                   27.0000             1    0.00
+exampleBAM.bam            27  -55             Cycle          M                   27.0000             1    0.00
+exampleBAM.bam            27  -56             Cycle          M                   27.0000             1    0.00
+exampleBAM.bam            27  57              Cycle          M                   27.0000             1    0.00
+exampleBAM.bam            27  65              Cycle          M                   27.0000             1    0.00
+exampleBAM.bam            27  -66             Cycle          M                   27.0000             1    0.00
+exampleBAM.bam            27  -69             Cycle          M                   27.0000             1    0.00
+exampleBAM.bam            27  -72             Cycle          M                   27.0000             1    0.00
+exampleBAM.bam            27  -73             Cycle          M                   27.0000             1    0.00
+exampleBAM.bam            27  76              Cycle          M                   27.0000             1    0.00
+exampleBAM.bam            28  -2              Cycle          M                   28.0000             1    0.00
+exampleBAM.bam            28  -11             Cycle          M                   28.0000             1    0.00
+exampleBAM.bam            28  25              Cycle          M                   28.0000             1    0.00
+exampleBAM.bam            28  -27             Cycle          M                   28.0000             1    0.00
+exampleBAM.bam            28  30              Cycle          M                   28.0000             1    0.00
+exampleBAM.bam            28  34              Cycle          M                   28.0000             1    0.00
+exampleBAM.bam            28  39              Cycle          M                   28.0000             1    0.00
+exampleBAM.bam            28  -41             Cycle          M                   28.0000             1    0.00
+exampleBAM.bam            28  47              Cycle          M                   28.0000             1    0.00
+exampleBAM.bam            28  48              Cycle          M                   28.0000             1    0.00
+exampleBAM.bam            28  -50             Cycle          M                   28.0000             1    0.00
+exampleBAM.bam            28  -53             Cycle          M                   28.0000             1    0.00
+exampleBAM.bam            28  54              Cycle          M                   28.0000             1    0.00
+exampleBAM.bam            28  -61             Cycle          M                   28.0000             1    0.00
+exampleBAM.bam            28  -71             Cycle          M                   28.0000             1    0.00
+exampleBAM.bam            29  4               Cycle          M                   29.0000             1    0.00
+exampleBAM.bam            29  -5              Cycle          M                   29.0000             1    0.00
+exampleBAM.bam            29  6               Cycle          M                   29.0000             1    0.00
+exampleBAM.bam            29  -7              Cycle          M                   29.0000             1    0.00
+exampleBAM.bam            29  -8              Cycle          M                   29.0000             1    0.00
+exampleBAM.bam            29  9               Cycle          M                   29.0000             1    0.00
+exampleBAM.bam            29  12              Cycle          M                   29.0000             1    0.00
+exampleBAM.bam            29  -24             Cycle          M                   29.0000             1    0.00
+exampleBAM.bam            29  27              Cycle          M                   29.0000             1    0.00
+exampleBAM.bam            29  -28             Cycle          M                   29.0000             1    0.00
+exampleBAM.bam            29  -37             Cycle          M                   29.0000             1    0.00
+exampleBAM.bam            29  42              Cycle          M                   29.0000             1    0.00
+exampleBAM.bam            29  -43             Cycle          M                   29.0000             1    0.00
+exampleBAM.bam            29  -45             Cycle          M                   29.0000             1    0.00
+exampleBAM.bam            29  -47             Cycle          M                   29.0000             1    0.00
+exampleBAM.bam            29  -48             Cycle          M                   29.0000             1    0.00
+exampleBAM.bam            29  -54             Cycle          M                   29.0000             1    0.00
+exampleBAM.bam            29  -60             Cycle          M                   29.0000             1    0.00
+exampleBAM.bam            29  -68             Cycle          M                   29.0000             1    0.00
+exampleBAM.bam            29  -76             Cycle          M                   29.0000             1    0.00
+exampleBAM.bam            30  -9              Cycle          M                   30.0000             1    0.00
+exampleBAM.bam            30  12              Cycle          M                   30.0000             1    0.00
+exampleBAM.bam            30  -17             Cycle          M                   30.0000             2    0.00
+exampleBAM.bam            30  18              Cycle          M                   30.0000             1    0.00
+exampleBAM.bam            30  20              Cycle          M                   30.0000             1    0.00
+exampleBAM.bam            30  -21             Cycle          M                   30.0000             1    0.00
+exampleBAM.bam            30  23              Cycle          M                   30.0000             1    0.00
+exampleBAM.bam            30  24              Cycle          M                   30.0000             1    0.00
+exampleBAM.bam            30  26              Cycle          M                   30.0000             1    0.00
+exampleBAM.bam            30  -30             Cycle          M                   30.0000             1    0.00
+exampleBAM.bam            30  32              Cycle          M                   30.0000             1    0.00
+exampleBAM.bam            30  34              Cycle          M                   30.0000             1    0.00
+exampleBAM.bam            30  35              Cycle          M                   30.0000             1    0.00
+exampleBAM.bam            30  -35             Cycle          M                   30.0000             1    0.00
+exampleBAM.bam            30  -42             Cycle          M                   30.0000             1    0.00
+exampleBAM.bam            30  -45             Cycle          M                   30.0000             1    0.00
+exampleBAM.bam            30  -52             Cycle          M                   30.0000             1    0.00
+exampleBAM.bam            30  -54             Cycle          M                   30.0000             1    0.00
+exampleBAM.bam            30  -69             Cycle          M                   30.0000             1    0.00
+exampleBAM.bam            31  -1              Cycle          M                   31.0000             1    0.00
+exampleBAM.bam            31  4               Cycle          M                   31.0000             1    0.00
+exampleBAM.bam            31  -5              Cycle          M                   31.0000             1    0.00
+exampleBAM.bam            31  -6              Cycle          M                   31.0000             1    0.00
+exampleBAM.bam            31  8               Cycle          M                   31.0000             2    0.00
+exampleBAM.bam            31  -10             Cycle          M                   31.0000             1    0.00
+exampleBAM.bam            31  -11             Cycle          M                   31.0000             1    0.00
+exampleBAM.bam            31  -12             Cycle          M                   31.0000             1    0.00
+exampleBAM.bam            31  -13             Cycle          M                   31.0000             1    0.00
+exampleBAM.bam            31  15              Cycle          M                   31.0000             2    0.00
+exampleBAM.bam            31  -16             Cycle          M                   31.0000             1    0.00
+exampleBAM.bam            31  -19             Cycle          M                   31.0000             1    0.00
+exampleBAM.bam            31  -25             Cycle          M                   31.0000             1    0.00
+exampleBAM.bam            31  26              Cycle          M                   31.0000             1    0.00
+exampleBAM.bam            31  -26             Cycle          M                   31.0000             1    0.00
+exampleBAM.bam            31  -32             Cycle          M                   31.0000             1    0.00
+exampleBAM.bam            31  -34             Cycle          M                   31.0000             1    0.00
+exampleBAM.bam            31  -39             Cycle          M                   31.0000             2    0.00
+exampleBAM.bam            31  43              Cycle          M                   31.0000             1    0.00
+exampleBAM.bam            31  -45             Cycle          M                   31.0000             1    0.00
+exampleBAM.bam            31  60              Cycle          M                   31.0000             1    0.00
+exampleBAM.bam            31  -66             Cycle          M                   31.0000             1    0.00
+exampleBAM.bam            32  1               Cycle          M                   32.0000             1    0.00
+exampleBAM.bam            32  2               Cycle          M                   32.0000             1    0.00
+exampleBAM.bam            32  -2              Cycle          M                   32.0000             1    0.00
+exampleBAM.bam            32  -14             Cycle          M                   32.0000             2    0.00
+exampleBAM.bam            32  -15             Cycle          M                   32.0000             1    0.00
+exampleBAM.bam            32  16              Cycle          M                   32.0000             1    0.00
+exampleBAM.bam            32  -16             Cycle          M                   32.0000             1    0.00
+exampleBAM.bam            32  -18             Cycle          M                   32.0000             1    0.00
+exampleBAM.bam            32  -19             Cycle          M                   32.0000             1    0.00
+exampleBAM.bam            32  23              Cycle          M                   32.0000             1    0.00
+exampleBAM.bam            32  24              Cycle          M                   32.0000             1    0.00
+exampleBAM.bam            32  28              Cycle          M                   32.0000             1    0.00
+exampleBAM.bam            32  -28             Cycle          M                   32.0000             1    0.00
+exampleBAM.bam            32  -30             Cycle          M                   32.0000             1    0.00
+exampleBAM.bam            32  -31             Cycle          M                   32.0000             1    0.00
+exampleBAM.bam            32  -33             Cycle          M                   32.0000             2    0.00
+exampleBAM.bam            32  -36             Cycle          M                   32.0000             2    0.00
+exampleBAM.bam            32  41              Cycle          M                   32.0000             1    0.00
+exampleBAM.bam            32  -41             Cycle          M                   32.0000             1    0.00
+exampleBAM.bam            32  43              Cycle          M                   32.0000             1    0.00
+exampleBAM.bam            32  -43             Cycle          M                   32.0000             2    0.00
+exampleBAM.bam            32  -46             Cycle          M                   32.0000             1    0.00
+exampleBAM.bam            32  -49             Cycle          M                   32.0000             1    0.00
+exampleBAM.bam            32  -51             Cycle          M                   32.0000             1    0.00
+exampleBAM.bam            32  -53             Cycle          M                   32.0000             1    0.00
+exampleBAM.bam            32  -54             Cycle          M                   32.0000             1    0.00
+exampleBAM.bam            32  -57             Cycle          M                   32.0000             1    0.00
+exampleBAM.bam            32  -72             Cycle          M                   32.0000             1    0.00
+exampleBAM.bam            33  1               Cycle          M                   33.0000             1    0.00
+exampleBAM.bam            33  -1              Cycle          M                   33.0000             1    0.00
+exampleBAM.bam            33  2               Cycle          M                   33.0000             1    0.00
+exampleBAM.bam            33  3               Cycle          M                   33.0000             1    0.00
+exampleBAM.bam            33  -7              Cycle          M                   33.0000             1    0.00
+exampleBAM.bam            33  -8              Cycle          M                   33.0000             1    0.00
+exampleBAM.bam            33  -10             Cycle          M                   33.0000             1    0.00
+exampleBAM.bam            33  -12             Cycle          M                   33.0000             1    0.00
+exampleBAM.bam            33  -18             Cycle          M                   33.0000             1    0.00
+exampleBAM.bam            33  -22             Cycle          M                   33.0000             2    0.00
+exampleBAM.bam            33  -23             Cycle          M                   33.0000             1    0.00
+exampleBAM.bam            33  -24             Cycle          M                   33.0000             1    0.00
+exampleBAM.bam            33  -29             Cycle          M                   33.0000             2    0.00
+exampleBAM.bam            33  -31             Cycle          M                   33.0000             1    0.00
+exampleBAM.bam            33  -32             Cycle          M                   33.0000             1    0.00
+exampleBAM.bam            33  -35             Cycle          M                   33.0000             1    0.00
+exampleBAM.bam            33  -37             Cycle          M                   33.0000             1    0.00
+exampleBAM.bam            33  -39             Cycle          M                   33.0000             1    0.00
+exampleBAM.bam            33  -40             Cycle          M                   33.0000             1    0.00
+exampleBAM.bam            33  42              Cycle          M                   33.0000             1    0.00
+exampleBAM.bam            33  44              Cycle          M                   33.0000             1    0.00
+exampleBAM.bam            33  45              Cycle          M                   33.0000             1    0.00
+exampleBAM.bam            33  -46             Cycle          M                   33.0000             1    0.00
+exampleBAM.bam            33  -48             Cycle          M                   33.0000             1    0.00
+exampleBAM.bam            33  -49             Cycle          M                   33.0000             1    0.00
+exampleBAM.bam            33  -57             Cycle          M                   33.0000             1    0.00
+exampleBAM.bam            33  -59             Cycle          M                   33.0000             1    0.00
+exampleBAM.bam            33  -66             Cycle          M                   33.0000             1    0.00
+exampleBAM.bam            33  -67             Cycle          M                   33.0000             1    0.00
+exampleBAM.bam            33  -69             Cycle          M                   33.0000             1    0.00
+exampleBAM.bam            33  -72             Cycle          M                   33.0000             1    0.00
+exampleBAM.bam            33  -73             Cycle          M                   33.0000             1    0.00
+exampleBAM.bam            33  -76             Cycle          M                   33.0000             1    0.00
+exampleBAM.bam            34  -2              Cycle          M                   34.0000             1    0.00
+exampleBAM.bam            34  -3              Cycle          M                   34.0000             1    0.00
+exampleBAM.bam            34  -4              Cycle          M                   34.0000             1    0.00
+exampleBAM.bam            34  -5              Cycle          M                   34.0000             1    0.00
+exampleBAM.bam            34  -6              Cycle          M                   34.0000             1    0.00
+exampleBAM.bam            34  -11             Cycle          M                   34.0000             1    0.00
+exampleBAM.bam            34  -13             Cycle          M                   34.0000             1    0.00
+exampleBAM.bam            34  -20             Cycle          M                   34.0000             1    0.00
+exampleBAM.bam            34  -21             Cycle          M                   34.0000             1    0.00
+exampleBAM.bam            34  -23             Cycle          M                   34.0000             1    0.00
+exampleBAM.bam            34  -25             Cycle          M                   34.0000             1    0.00
+exampleBAM.bam            34  -26             Cycle          M                   34.0000             1    0.00
+exampleBAM.bam            34  -27             Cycle          M                   34.0000             1    0.00
+exampleBAM.bam            34  -34             Cycle          M                   34.0000             1    0.00
+exampleBAM.bam            34  -38             Cycle          M                   34.0000             1    0.00
+exampleBAM.bam            34  -40             Cycle          M                   34.0000             1    0.00
+exampleBAM.bam            34  -41             Cycle          M                   34.0000             1    0.00
+exampleBAM.bam            34  -42             Cycle          M                   34.0000             1    0.00
+exampleBAM.bam            34  -47             Cycle          M                   34.0000             1    0.00
+exampleBAM.bam            34  -50             Cycle          M                   34.0000             1    0.00
+exampleBAM.bam            34  -51             Cycle          M                   34.0000             1    0.00
+exampleBAM.bam            34  -55             Cycle          M                   34.0000             1    0.00
+exampleBAM.bam            34  -56             Cycle          M                   34.0000             1    0.00
+exampleBAM.bam            34  -58             Cycle          M                   34.0000             1    0.00
+exampleBAM.bam            34  -59             Cycle          M                   34.0000             1    0.00
+exampleBAM.bam            34  -60             Cycle          M                   34.0000             1    0.00
+exampleBAM.bam            34  -61             Cycle          M                   34.0000             1    0.00
+exampleBAM.bam            34  -62             Cycle          M                   34.0000             1    0.00
+exampleBAM.bam            34  -63             Cycle          M                   34.0000             1    0.00
+exampleBAM.bam            34  -64             Cycle          M                   34.0000             1    0.00
+exampleBAM.bam            34  -65             Cycle          M                   34.0000             1    0.00
+exampleBAM.bam            34  -68             Cycle          M                   34.0000             1    0.00
+exampleBAM.bam            34  -70             Cycle          M                   34.0000             1    0.00
+exampleBAM.bam            34  -71             Cycle          M                   34.0000             1    0.00
+exampleBAM.bam            34  -74             Cycle          M                   34.0000             1    0.00
+exampleBAM.bam            34  -75             Cycle          M                   34.0000             1    0.00
+exampleBAM.bam            45  5               Cycle          I                   45.0000             2    0.00
+exampleBAM.bam            45  5               Cycle          D                   45.0000             2    0.00
+exampleBAM.bam            45  -5              Cycle          I                   45.0000             3    0.00
+exampleBAM.bam            45  -5              Cycle          D                   45.0000             3    0.00
+exampleBAM.bam            45  6               Cycle          I                   45.0000             2    0.00
+exampleBAM.bam            45  6               Cycle          D                   45.0000             2    0.00
+exampleBAM.bam            45  -6              Cycle          I                   45.0000             3    0.00
+exampleBAM.bam            45  -6              Cycle          D                   45.0000             3    0.00
+exampleBAM.bam            45  7               Cycle          I                   45.0000             2    0.00
+exampleBAM.bam            45  7               Cycle          D                   45.0000             2    0.00
+exampleBAM.bam            45  -7              Cycle          I                   45.0000             3    0.00
+exampleBAM.bam            45  -7              Cycle          D                   45.0000             3    0.00
+exampleBAM.bam            45  8               Cycle          I                   45.0000             2    0.00
+exampleBAM.bam            45  8               Cycle          D                   45.0000             2    0.00
+exampleBAM.bam            45  -8              Cycle          I                   45.0000             3    0.00
+exampleBAM.bam            45  -8              Cycle          D                   45.0000             3    0.00
+exampleBAM.bam            45  9               Cycle          I                   45.0000             2    0.00
+exampleBAM.bam            45  9               Cycle          D                   45.0000             2    0.00
+exampleBAM.bam            45  -9              Cycle          I                   45.0000             3    0.00
+exampleBAM.bam            45  -9              Cycle          D                   45.0000             3    0.00
+exampleBAM.bam            45  10              Cycle          I                   45.0000             2    0.00
+exampleBAM.bam            45  10              Cycle          D                   45.0000             2    0.00
+exampleBAM.bam            45  -10             Cycle          I                   45.0000             3    0.00
+exampleBAM.bam            45  -10             Cycle          D                   45.0000             3    0.00
+exampleBAM.bam            45  11              Cycle          I                   45.0000             2    0.00
+exampleBAM.bam            45  11              Cycle          D                   45.0000             2    0.00
+exampleBAM.bam            45  -11             Cycle          I                   45.0000             3    0.00
+exampleBAM.bam            45  -11             Cycle          D                   45.0000             3    0.00
+exampleBAM.bam            45  12              Cycle          I                   45.0000             2    0.00
+exampleBAM.bam            45  12              Cycle          D                   45.0000             2    0.00
+exampleBAM.bam            45  -12             Cycle          I                   45.0000             3    0.00
+exampleBAM.bam            45  -12             Cycle          D                   45.0000             3    0.00
+exampleBAM.bam            45  13              Cycle          I                   45.0000             2    0.00
+exampleBAM.bam            45  13              Cycle          D                   45.0000             2    0.00
+exampleBAM.bam            45  -13             Cycle          I                   45.0000             3    0.00
+exampleBAM.bam            45  -13             Cycle          D                   45.0000             3    0.00
+exampleBAM.bam            45  14              Cycle          I                   45.0000             2    0.00
+exampleBAM.bam            45  14              Cycle          D                   45.0000             2    0.00
+exampleBAM.bam            45  -14             Cycle          I                   45.0000             3    0.00
+exampleBAM.bam            45  -14             Cycle          D                   45.0000             3    0.00
+exampleBAM.bam            45  15              Cycle          I                   45.0000             2    0.00
+exampleBAM.bam            45  15              Cycle          D                   45.0000             2    0.00
+exampleBAM.bam            45  -15             Cycle          I                   45.0000             3    0.00
+exampleBAM.bam            45  -15             Cycle          D                   45.0000             3    0.00
+exampleBAM.bam            45  16              Cycle          I                   45.0000             2    0.00
+exampleBAM.bam            45  16              Cycle          D                   45.0000             2    0.00
+exampleBAM.bam            45  -16             Cycle          I                   45.0000             3    0.00
+exampleBAM.bam            45  -16             Cycle          D                   45.0000             3    0.00
+exampleBAM.bam            45  17              Cycle          I                   45.0000             2    0.00
+exampleBAM.bam            45  17              Cycle          D                   45.0000             2    0.00
+exampleBAM.bam            45  -17             Cycle          I                   45.0000             3    0.00
+exampleBAM.bam            45  -17             Cycle          D                   45.0000             3    0.00
+exampleBAM.bam            45  18              Cycle          I                   45.0000             2    0.00
+exampleBAM.bam            45  18              Cycle          D                   45.0000             2    0.00
+exampleBAM.bam            45  -18             Cycle          I                   45.0000             3    0.00
+exampleBAM.bam            45  -18             Cycle          D                   45.0000             3    0.00
+exampleBAM.bam            45  19              Cycle          I                   45.0000             2    0.00
+exampleBAM.bam            45  19              Cycle          D                   45.0000             2    0.00
+exampleBAM.bam            45  -19             Cycle          I                   45.0000             3    0.00
+exampleBAM.bam            45  -19             Cycle          D                   45.0000             3    0.00
+exampleBAM.bam            45  20              Cycle          I                   45.0000             2    0.00
+exampleBAM.bam            45  20              Cycle          D                   45.0000             2    0.00
+exampleBAM.bam            45  -20             Cycle          I                   45.0000             3    0.00
+exampleBAM.bam            45  -20             Cycle          D                   45.0000             3    0.00
+exampleBAM.bam            45  21              Cycle          I                   45.0000             2    0.00
+exampleBAM.bam            45  21              Cycle          D                   45.0000             2    0.00
+exampleBAM.bam            45  -21             Cycle          I                   45.0000             3    0.00
+exampleBAM.bam            45  -21             Cycle          D                   45.0000             3    0.00
+exampleBAM.bam            45  22              Cycle          I                   45.0000             2    0.00
+exampleBAM.bam            45  22              Cycle          D                   45.0000             2    0.00
+exampleBAM.bam            45  -22             Cycle          I                   45.0000             2    0.00
+exampleBAM.bam            45  -22             Cycle          D                   45.0000             2    0.00
+exampleBAM.bam            45  23              Cycle          I                   45.0000             2    0.00
+exampleBAM.bam            45  23              Cycle          D                   45.0000             2    0.00
+exampleBAM.bam            45  -23             Cycle          I                   45.0000             3    0.00
+exampleBAM.bam            45  -23             Cycle          D                   45.0000             3    0.00
+exampleBAM.bam            45  24              Cycle          I                   45.0000             2    0.00
+exampleBAM.bam            45  24              Cycle          D                   45.0000             2    0.00
+exampleBAM.bam            45  -24             Cycle          I                   45.0000             3    0.00
+exampleBAM.bam            45  -24             Cycle          D                   45.0000             3    0.00
+exampleBAM.bam            45  25              Cycle          I                   45.0000             2    0.00
+exampleBAM.bam            45  25              Cycle          D                   45.0000             2    0.00
+exampleBAM.bam            45  -25             Cycle          I                   45.0000             3    0.00
+exampleBAM.bam            45  -25             Cycle          D                   45.0000             3    0.00
+exampleBAM.bam            45  26              Cycle          I                   45.0000             2    0.00
+exampleBAM.bam            45  26              Cycle          D                   45.0000             2    0.00
+exampleBAM.bam            45  -26             Cycle          I                   45.0000             2    0.00
+exampleBAM.bam            45  -26             Cycle          D                   45.0000             2    0.00
+exampleBAM.bam            45  27              Cycle          I                   45.0000             2    0.00
+exampleBAM.bam            45  27              Cycle          D                   45.0000             2    0.00
+exampleBAM.bam            45  -27             Cycle          I                   45.0000             3    0.00
+exampleBAM.bam            45  -27             Cycle          D                   45.0000             3    0.00
+exampleBAM.bam            45  28              Cycle          I                   45.0000             2    0.00
+exampleBAM.bam            45  28              Cycle          D                   45.0000             2    0.00
+exampleBAM.bam            45  -28             Cycle          I                   45.0000             3    0.00
+exampleBAM.bam            45  -28             Cycle          D                   45.0000             3    0.00
+exampleBAM.bam            45  29              Cycle          I                   45.0000             1    0.00
+exampleBAM.bam            45  29              Cycle          D                   45.0000             1    0.00
+exampleBAM.bam            45  -29             Cycle          I                   45.0000             3    0.00
+exampleBAM.bam            45  -29             Cycle          D                   45.0000             3    0.00
+exampleBAM.bam            45  30              Cycle          I                   45.0000             2    0.00
+exampleBAM.bam            45  30              Cycle          D                   45.0000             2    0.00
+exampleBAM.bam            45  -30             Cycle          I                   45.0000             3    0.00
+exampleBAM.bam            45  -30             Cycle          D                   45.0000             3    0.00
+exampleBAM.bam            45  31              Cycle          I                   45.0000             2    0.00
+exampleBAM.bam            45  31              Cycle          D                   45.0000             2    0.00
+exampleBAM.bam            45  -31             Cycle          I                   45.0000             3    0.00
+exampleBAM.bam            45  -31             Cycle          D                   45.0000             3    0.00
+exampleBAM.bam            45  32              Cycle          I                   45.0000             2    0.00
+exampleBAM.bam            45  32              Cycle          D                   45.0000             2    0.00
+exampleBAM.bam            45  -32             Cycle          I                   45.0000             3    0.00
+exampleBAM.bam            45  -32             Cycle          D                   45.0000             3    0.00
+exampleBAM.bam            45  33              Cycle          I                   45.0000             2    0.00
+exampleBAM.bam            45  33              Cycle          D                   45.0000             2    0.00
+exampleBAM.bam            45  -33             Cycle          I                   45.0000             3    0.00
+exampleBAM.bam            45  -33             Cycle          D                   45.0000             3    0.00
+exampleBAM.bam            45  34              Cycle          I                   45.0000             2    0.00
+exampleBAM.bam            45  34              Cycle          D                   45.0000             2    0.00
+exampleBAM.bam            45  -34             Cycle          I                   45.0000             3    0.00
+exampleBAM.bam            45  -34             Cycle          D                   45.0000             3    0.00
+exampleBAM.bam            45  35              Cycle          I                   45.0000             2    0.00
+exampleBAM.bam            45  35              Cycle          D                   45.0000             2    0.00
+exampleBAM.bam            45  -35             Cycle          I                   45.0000             3    0.00
+exampleBAM.bam            45  -35             Cycle          D                   45.0000             3    0.00
+exampleBAM.bam            45  36              Cycle          I                   45.0000             2    0.00
+exampleBAM.bam            45  36              Cycle          D                   45.0000             2    0.00
+exampleBAM.bam            45  -36             Cycle          I                   45.0000             3    0.00
+exampleBAM.bam            45  -36             Cycle          D                   45.0000             3    0.00
+exampleBAM.bam            45  37              Cycle          I                   45.0000             2    0.00
+exampleBAM.bam            45  37              Cycle          D                   45.0000             2    0.00
+exampleBAM.bam            45  -37             Cycle          I                   45.0000             2    0.00
+exampleBAM.bam            45  -37             Cycle          D                   45.0000             2    0.00
+exampleBAM.bam            45  38              Cycle          I                   45.0000             2    0.00
+exampleBAM.bam            45  38              Cycle          D                   45.0000             2    0.00
+exampleBAM.bam            45  -38             Cycle          I                   45.0000             2    0.00
+exampleBAM.bam            45  -38             Cycle          D                   45.0000             2    0.00
+exampleBAM.bam            45  39              Cycle          I                   45.0000             2    0.00
+exampleBAM.bam            45  39              Cycle          D                   45.0000             2    0.00
+exampleBAM.bam            45  -39             Cycle          I                   45.0000             3    0.00
+exampleBAM.bam            45  -39             Cycle          D                   45.0000             3    0.00
+exampleBAM.bam            45  40              Cycle          I                   45.0000             2    0.00
+exampleBAM.bam            45  40              Cycle          D                   45.0000             2    0.00
+exampleBAM.bam            45  -40             Cycle          I                   45.0000             3    0.00
+exampleBAM.bam            45  -40             Cycle          D                   45.0000             3    0.00
+exampleBAM.bam            45  41              Cycle          I                   45.0000             2    0.00
+exampleBAM.bam            45  41              Cycle          D                   45.0000             2    0.00
+exampleBAM.bam            45  -41             Cycle          I                   45.0000             3    0.00
+exampleBAM.bam            45  -41             Cycle          D                   45.0000             3    0.00
+exampleBAM.bam            45  42              Cycle          I                   45.0000             2    0.00
+exampleBAM.bam            45  42              Cycle          D                   45.0000             2    0.00
+exampleBAM.bam            45  -42             Cycle          I                   45.0000             3    0.00
+exampleBAM.bam            45  -42             Cycle          D                   45.0000             3    0.00
+exampleBAM.bam            45  43              Cycle          I                   45.0000             2    0.00
+exampleBAM.bam            45  43              Cycle          D                   45.0000             2    0.00
+exampleBAM.bam            45  -43             Cycle          I                   45.0000             3    0.00
+exampleBAM.bam            45  -43             Cycle          D                   45.0000             3    0.00
+exampleBAM.bam            45  44              Cycle          I                   45.0000             2    0.00
+exampleBAM.bam            45  44              Cycle          D                   45.0000             2    0.00
+exampleBAM.bam            45  -44             Cycle          I                   45.0000             3    0.00
+exampleBAM.bam            45  -44             Cycle          D                   45.0000             3    0.00
+exampleBAM.bam            45  45              Cycle          I                   45.0000             2    0.00
+exampleBAM.bam            45  45              Cycle          D                   45.0000             2    0.00
+exampleBAM.bam            45  -45             Cycle          I                   45.0000             3    0.00
+exampleBAM.bam            45  -45             Cycle          D                   45.0000             3    0.00
+exampleBAM.bam            45  46              Cycle          I                   45.0000             2    0.00
+exampleBAM.bam            45  46              Cycle          D                   45.0000             2    0.00
+exampleBAM.bam            45  -46             Cycle          I                   45.0000             2    0.00
+exampleBAM.bam            45  -46             Cycle          D                   45.0000             2    0.00
+exampleBAM.bam            45  47              Cycle          I                   45.0000             2    0.00
+exampleBAM.bam            45  47              Cycle          D                   45.0000             2    0.00
+exampleBAM.bam            45  -47             Cycle          I                   45.0000             3    0.00
+exampleBAM.bam            45  -47             Cycle          D                   45.0000             3    0.00
+exampleBAM.bam            45  48              Cycle          I                   45.0000             2    0.00
+exampleBAM.bam            45  48              Cycle          D                   45.0000             2    0.00
+exampleBAM.bam            45  -48             Cycle          I                   45.0000             3    0.00
+exampleBAM.bam            45  -48             Cycle          D                   45.0000             3    0.00
+exampleBAM.bam            45  49              Cycle          I                   45.0000             1    0.00
+exampleBAM.bam            45  49              Cycle          D                   45.0000             1    0.00
+exampleBAM.bam            45  -49             Cycle          I                   45.0000             3    0.00
+exampleBAM.bam            45  -49             Cycle          D                   45.0000             3    0.00
+exampleBAM.bam            45  50              Cycle          I                   45.0000             2    0.00
+exampleBAM.bam            45  50              Cycle          D                   45.0000             2    0.00
+exampleBAM.bam            45  -50             Cycle          I                   45.0000             3    0.00
+exampleBAM.bam            45  -50             Cycle          D                   45.0000             3    0.00
+exampleBAM.bam            45  51              Cycle          I                   45.0000             2    0.00
+exampleBAM.bam            45  51              Cycle          D                   45.0000             2    0.00
+exampleBAM.bam            45  -51             Cycle          I                   45.0000             3    0.00
+exampleBAM.bam            45  -51             Cycle          D                   45.0000             3    0.00
+exampleBAM.bam            45  52              Cycle          I                   45.0000             2    0.00
+exampleBAM.bam            45  52              Cycle          D                   45.0000             2    0.00
+exampleBAM.bam            45  -52             Cycle          I                   45.0000             3    0.00
+exampleBAM.bam            45  -52             Cycle          D                   45.0000             3    0.00
+exampleBAM.bam            45  53              Cycle          I                   45.0000             2    0.00
+exampleBAM.bam            45  53              Cycle          D                   45.0000             2    0.00
+exampleBAM.bam            45  -53             Cycle          I                   45.0000             3    0.00
+exampleBAM.bam            45  -53             Cycle          D                   45.0000             3    0.00
+exampleBAM.bam            45  54              Cycle          I                   45.0000             2    0.00
+exampleBAM.bam            45  54              Cycle          D                   45.0000             2    0.00
+exampleBAM.bam            45  -54             Cycle          I                   45.0000             3    0.00
+exampleBAM.bam            45  -54             Cycle          D                   45.0000             3    0.00
+exampleBAM.bam            45  55              Cycle          I                   45.0000             2    0.00
+exampleBAM.bam            45  55              Cycle          D                   45.0000             2    0.00
+exampleBAM.bam            45  -55             Cycle          I                   45.0000             3    0.00
+exampleBAM.bam            45  -55             Cycle          D                   45.0000             3    0.00
+exampleBAM.bam            45  56              Cycle          I                   45.0000             2    0.00
+exampleBAM.bam            45  56              Cycle          D                   45.0000             2    0.00
+exampleBAM.bam            45  -56             Cycle          I                   45.0000             3    0.00
+exampleBAM.bam            45  -56             Cycle          D                   45.0000             3    0.00
+exampleBAM.bam            45  57              Cycle          I                   45.0000             2    0.00
+exampleBAM.bam            45  57              Cycle          D                   45.0000             2    0.00
+exampleBAM.bam            45  -57             Cycle          I                   45.0000             3    0.00
+exampleBAM.bam            45  -57             Cycle          D                   45.0000             3    0.00
+exampleBAM.bam            45  58              Cycle          I                   45.0000             2    0.00
+exampleBAM.bam            45  58              Cycle          D                   45.0000             2    0.00
+exampleBAM.bam            45  -58             Cycle          I                   45.0000             3    0.00
+exampleBAM.bam            45  -58             Cycle          D                   45.0000             3    0.00
+exampleBAM.bam            45  59              Cycle          I                   45.0000             2    0.00
+exampleBAM.bam            45  59              Cycle          D                   45.0000             2    0.00
+exampleBAM.bam            45  -59             Cycle          I                   45.0000             3    0.00
+exampleBAM.bam            45  -59             Cycle          D                   45.0000             3    0.00
+exampleBAM.bam            45  60              Cycle          I                   45.0000             2    0.00
+exampleBAM.bam            45  60              Cycle          D                   45.0000             2    0.00
+exampleBAM.bam            45  -60             Cycle          I                   45.0000             3    0.00
+exampleBAM.bam            45  -60             Cycle          D                   45.0000             3    0.00
+exampleBAM.bam            45  61              Cycle          I                   45.0000             2    0.00
+exampleBAM.bam            45  61              Cycle          D                   45.0000             2    0.00
+exampleBAM.bam            45  -61             Cycle          I                   45.0000             3    0.00
+exampleBAM.bam            45  -61             Cycle          D                   45.0000             3    0.00
+exampleBAM.bam            45  62              Cycle          I                   45.0000             2    0.00
+exampleBAM.bam            45  62              Cycle          D                   45.0000             2    0.00
+exampleBAM.bam            45  -62             Cycle          I                   45.0000             3    0.00
+exampleBAM.bam            45  -62             Cycle          D                   45.0000             3    0.00
+exampleBAM.bam            45  63              Cycle          I                   45.0000             2    0.00
+exampleBAM.bam            45  63              Cycle          D                   45.0000             2    0.00
+exampleBAM.bam            45  -63             Cycle          I                   45.0000             3    0.00
+exampleBAM.bam            45  -63             Cycle          D                   45.0000             3    0.00
+exampleBAM.bam            45  64              Cycle          I                   45.0000             2    0.00
+exampleBAM.bam            45  64              Cycle          D                   45.0000             2    0.00
+exampleBAM.bam            45  -64             Cycle          I                   45.0000             2    0.00
+exampleBAM.bam            45  -64             Cycle          D                   45.0000             2    0.00
+exampleBAM.bam            45  65              Cycle          I                   45.0000             2    0.00
+exampleBAM.bam            45  65              Cycle          D                   45.0000             2    0.00
+exampleBAM.bam            45  -65             Cycle          I                   45.0000             3    0.00
+exampleBAM.bam            45  -65             Cycle          D                   45.0000             3    0.00
+exampleBAM.bam            45  66              Cycle          I                   45.0000             2    0.00
+exampleBAM.bam            45  66              Cycle          D                   45.0000             2    0.00
+exampleBAM.bam            45  -66             Cycle          I                   45.0000             3    0.00
+exampleBAM.bam            45  -66             Cycle          D                   45.0000             3    0.00
+exampleBAM.bam            45  67              Cycle          I                   45.0000             2    0.00
+exampleBAM.bam            45  67              Cycle          D                   45.0000             2    0.00
+exampleBAM.bam            45  -67             Cycle          I                   45.0000             3    0.00
+exampleBAM.bam            45  -67             Cycle          D                   45.0000             3    0.00
+exampleBAM.bam            45  68              Cycle          I                   45.0000             2    0.00
+exampleBAM.bam            45  68              Cycle          D                   45.0000             2    0.00
+exampleBAM.bam            45  -68             Cycle          I                   45.0000             3    0.00
+exampleBAM.bam            45  -68             Cycle          D                   45.0000             3    0.00
+exampleBAM.bam            45  69              Cycle          I                   45.0000             2    0.00
+exampleBAM.bam            45  69              Cycle          D                   45.0000             2    0.00
+exampleBAM.bam            45  -69             Cycle          I                   45.0000             3    0.00
+exampleBAM.bam            45  -69             Cycle          D                   45.0000             3    0.00
+exampleBAM.bam            45  70              Cycle          I                   45.0000             1    0.00
+exampleBAM.bam            45  70              Cycle          D                   45.0000             1    0.00
+exampleBAM.bam            45  -70             Cycle          I                   45.0000             3    0.00
+exampleBAM.bam            45  -70             Cycle          D                   45.0000             3    0.00
+exampleBAM.bam            45  71              Cycle          I                   45.0000             2    0.00
+exampleBAM.bam            45  71              Cycle          D                   45.0000             2    0.00
+exampleBAM.bam            45  -71             Cycle          I                   45.0000             3    0.00
+exampleBAM.bam            45  -71             Cycle          D                   45.0000             3    0.00
+exampleBAM.bam            45  72              Cycle          I                   45.0000             1    0.00
+exampleBAM.bam            45  72              Cycle          D                   45.0000             1    0.00
+exampleBAM.bam            45  -72             Cycle          I                   45.0000             3    0.00
+exampleBAM.bam            45  -72             Cycle          D                   45.0000             3    0.00
+
diff --git a/public/gatk-engine/src/test/resources/exampleINTERVAL.intervals b/public/gatk-engine/src/test/resources/exampleINTERVAL.intervals
new file mode 100644
index 0000000..f224381
--- /dev/null
+++ b/public/gatk-engine/src/test/resources/exampleINTERVAL.intervals
@@ -0,0 +1,3 @@
+chr1:1-100
+chr1:200-400
+chr1:450-459
diff --git a/public/gatk-engine/src/test/resources/exampleNORG.bam b/public/gatk-engine/src/test/resources/exampleNORG.bam
new file mode 100644
index 0000000..f59219f
Binary files /dev/null and b/public/gatk-engine/src/test/resources/exampleNORG.bam differ
diff --git a/public/gatk-engine/src/test/resources/exampleNORG.bam.bai b/public/gatk-engine/src/test/resources/exampleNORG.bam.bai
new file mode 100644
index 0000000..26cfe74
Binary files /dev/null and b/public/gatk-engine/src/test/resources/exampleNORG.bam.bai differ
diff --git a/public/gatk-engine/src/test/resources/forAlleleFractionSimulation.vcf b/public/gatk-engine/src/test/resources/forAlleleFractionSimulation.vcf
new file mode 100644
index 0000000..e29e49d
--- /dev/null
+++ b/public/gatk-engine/src/test/resources/forAlleleFractionSimulation.vcf
@@ -0,0 +1,29 @@
+##fileformat=VCFv4.1
+##phasing=none
+##INDIVIDUAL=TRUTH
+##SAMPLE=<ID=TRUTH,Individual="TRUTH",Description="bamsurgeon spike-in">
+##INFO=<ID=SOMATIC,Number=0,Type=Flag,Description="Somatic mutation in primary">
+##INFO=<ID=AF,Number=1,Type=Float,Description="Variant Allele Frequency">
+##FORMAT=<ID=GT,Number=1,Type=String,Description="Genotype">
+#CHROM	POS	ID	REF	ALT	QUAL	FILTER	INFO	FORMAT	TUMOR
+20	100000	.	A	T	100	PASS	SOMATIC;AF=0.500	GT	0/1
+20	101000	.	T	C	100	PASS	SOMATIC;AF=0.400	GT	0/1
+20	102000	.	A	C	100	PASS	SOMATIC;AF=0.300	GT	0/1
+20	103000	.	C	T	100	PASS	SOMATIC;AF=0.200	GT	0/1
+20	104000	.	A	C	100	PASS	SOMATIC;AF=0.100	GT	0/1
+20	105000	.	A	C	100	PASS	SOMATIC;AF=0.050	GT	0/1
+20	105500	.	A	G	100	PASS	SOMATIC;AF=0.020	GT	0/1
+20	106000	.	CAT	C	100	PASS	SOMATIC;AF=0.500	GT	0/1
+20	107000	.	ACT	A	100	PASS	SOMATIC;AF=0.400	GT	0/1
+20	107994	.	AAG	A	100	PASS	SOMATIC;AF=0.300	GT	0/1
+20	108999	.	GCA	G	100	PASS	SOMATIC;AF=0.200	GT	0/1
+20	110009	.	CAT	C	100	PASS	SOMATIC;AF=0.100	GT	0/1
+20	112000	.	ACC	A	100	PASS	SOMATIC;AF=0.050	GT	0/1
+20	112500	.	AGC	A	100	PASS	SOMATIC;AF=0.020	GT	0/1
+20	113000	.	G	GAAT	100	PASS	SOMATIC;AF=0.500	GT	0/1
+20	113999	.	G	GTGA	100	PASS	SOMATIC;AF=0.400	GT	0/1
+20	115000	.	T	TCCA	100	PASS	SOMATIC;AF=0.300	GT	0/1
+20	116000	.	G	GTTT	100	PASS	SOMATIC;AF=0.200	GT	0/1
+20	117000	.	T	TCCA	100	PASS	SOMATIC;AF=0.100	GT	0/1
+20	118000	.	C	CTGT	100	PASS	SOMATIC;AF=0.050	GT	0/1
+20	119000	.	C	CTGT	100	PASS	SOMATIC;AF=0.020	GT	0/1
\ No newline at end of file
diff --git a/public/gatk-engine/src/test/resources/forAlleleFractionSimulation.vcf.idx b/public/gatk-engine/src/test/resources/forAlleleFractionSimulation.vcf.idx
new file mode 100644
index 0000000..8b82f26
Binary files /dev/null and b/public/gatk-engine/src/test/resources/forAlleleFractionSimulation.vcf.idx differ
diff --git a/public/gatk-engine/src/test/resources/forLongInsert.vcf b/public/gatk-engine/src/test/resources/forLongInsert.vcf
new file mode 100644
index 0000000..3566b88
--- /dev/null
+++ b/public/gatk-engine/src/test/resources/forLongInsert.vcf
@@ -0,0 +1,16 @@
+##fileformat=VCFv4.1
+##fileDate=20140820
+##source=mutatrix population genome simulator
+##seed=100
+##reference=ref.fasta
+##phasing=true
+##commandline=mutatrix ref.fasta --file-prefix mutations/ --sample-prefix 0 -n 1 --ploidy 2 --random-seed 100 --snp-rate 0.001
+##INFO=<ID=AC,Number=A,Type=Integer,Description="Alternate allele count">
+##INFO=<ID=TYPE,Number=A,Type=String,Description="Type of each allele (snp, ins, del, mnp, complex)">
+##INFO=<ID=NS,Number=1,Type=Integer,Description="Number of samples at the site">
+##INFO=<ID=NA,Number=1,Type=Integer,Description="Number of alternate alleles">
+##INFO=<ID=LEN,Number=A,Type=Integer,Description="Length of each alternate allele">
+##INFO=<ID=MICROSAT,Number=0,Type=Flag,Description="Generated at a sequence repeat loci">
+##FORMAT=<ID=GT,Number=1,Type=String,Description="Genotype">
+#CHROM	POS	ID	REF	ALT	QUAL	FILTER	INFO	FORMAT	01
+20	10000000	.	T	TGTCTTAGTGTCGTATGGGCTTCCATATTCAACTTTCTTCTATAAGTAGAATATCTACACGTGATGCTCTGGTCTTTCTACTACACGTCTATTGTAGCTTAATCTTTTCCTCGGGGGGGAAGAGGCTGTTTAGAATCATACCTCCAACCGACATTAACCCTGTTGGATTATAACTAGGGGCAAATCCGGATATTGGTATACGGCCCTATTATTCTATGGGTCTACGCACCTAGTAGGCACCCACGCAGTCTCTGGCCCGACCCCA	99	.	AC=2;LEN=264;NA=1;NS=1;TYPE=ins	GT	1|1
diff --git a/public/gatk-engine/src/test/resources/forLongInsert.vcf.idx b/public/gatk-engine/src/test/resources/forLongInsert.vcf.idx
new file mode 100644
index 0000000..a22e932
Binary files /dev/null and b/public/gatk-engine/src/test/resources/forLongInsert.vcf.idx differ
diff --git a/public/gatk-engine/src/test/resources/forSimulation.vcf b/public/gatk-engine/src/test/resources/forSimulation.vcf
new file mode 100644
index 0000000..a0c57c2
--- /dev/null
+++ b/public/gatk-engine/src/test/resources/forSimulation.vcf
@@ -0,0 +1,8 @@
+##fileformat=VCFv4.1
+##FORMAT=<ID=GT,Number=1,Type=String,Description="Genotype">
+#CHROM	POS	ID	REF	ALT	QUAL	FILTER	INFO	FORMAT	NA12878	NA12891	NA12892
+20	10000000	.	T	C	.	.	.	GT	0/1	0/0	1/1
+20	10001000	.	GG	AA	.	.	.	GT	0/1	0/0	1/1
+20	10002000	.	TAGTA	T	.	.	.	GT	0/1	0/0	1/1
+20	10003000	.	A	AGCT	.	.	.	GT	0/1	0/0	1/1
+20	10004000	.	GAT	G,GATAT	.	.	.	GT	0/1	0/0	1/1
diff --git a/public/gatk-engine/src/test/resources/forSimulation.vcf.idx b/public/gatk-engine/src/test/resources/forSimulation.vcf.idx
new file mode 100644
index 0000000..4f734b7
Binary files /dev/null and b/public/gatk-engine/src/test/resources/forSimulation.vcf.idx differ
diff --git a/public/gatk-engine/src/test/resources/testfile.sam b/public/gatk-engine/src/test/resources/testfile.sam
new file mode 100644
index 0000000..7345c03
--- /dev/null
+++ b/public/gatk-engine/src/test/resources/testfile.sam
@@ -0,0 +1,450 @@
+ at HD	VN:1.0	GO:none	SO:coordinate
+ at SQ	SN:chrM	LN:16571	AS:HG18	UR:/seq/references/Homo_sapiens_assembly18/v0/Homo_sapiens_assembly18.fasta	M5:d2ed829b8a1628d16cbeee88e88e39eb	SP:Homo sapiens
+ at SQ	SN:chr1	LN:247249719	AS:HG18	UR:/seq/references/Homo_sapiens_assembly18/v0/Homo_sapiens_assembly18.fasta	M5:9ebc6df9496613f373e73396d5b3b6b6	SP:Homo sapiens
+ at SQ	SN:chr2	LN:242951149	AS:HG18	UR:/seq/references/Homo_sapiens_assembly18/v0/Homo_sapiens_assembly18.fasta	M5:b12c7373e3882120332983be99aeb18d	SP:Homo sapiens
+ at SQ	SN:chr3	LN:199501827	AS:HG18	UR:/seq/references/Homo_sapiens_assembly18/v0/Homo_sapiens_assembly18.fasta	M5:0e48ed7f305877f66e6fd4addbae2b9a	SP:Homo sapiens
+ at SQ	SN:chr4	LN:191273063	AS:HG18	UR:/seq/references/Homo_sapiens_assembly18/v0/Homo_sapiens_assembly18.fasta	M5:cf37020337904229dca8401907b626c2	SP:Homo sapiens
+ at SQ	SN:chr5	LN:180857866	AS:HG18	UR:/seq/references/Homo_sapiens_assembly18/v0/Homo_sapiens_assembly18.fasta	M5:031c851664e31b2c17337fd6f9004858	SP:Homo sapiens
+ at SQ	SN:chr6	LN:170899992	AS:HG18	UR:/seq/references/Homo_sapiens_assembly18/v0/Homo_sapiens_assembly18.fasta	M5:bfe8005c536131276d448ead33f1b583	SP:Homo sapiens
+ at SQ	SN:chr7	LN:158821424	AS:HG18	UR:/seq/references/Homo_sapiens_assembly18/v0/Homo_sapiens_assembly18.fasta	M5:74239c5ceee3b28f0038123d958114cb	SP:Homo sapiens
+ at SQ	SN:chr8	LN:146274826	AS:HG18	UR:/seq/references/Homo_sapiens_assembly18/v0/Homo_sapiens_assembly18.fasta	M5:1eb00fe1ce26ce6701d2cd75c35b5ccb	SP:Homo sapiens
+ at SQ	SN:chr9	LN:140273252	AS:HG18	UR:/seq/references/Homo_sapiens_assembly18/v0/Homo_sapiens_assembly18.fasta	M5:ea244473e525dde0393d353ef94f974b	SP:Homo sapiens
+ at SQ	SN:chr10	LN:135374737	AS:HG18	UR:/seq/references/Homo_sapiens_assembly18/v0/Homo_sapiens_assembly18.fasta	M5:4ca41bf2d7d33578d2cd7ee9411e1533	SP:Homo sapiens
+ at SQ	SN:chr11	LN:134452384	AS:HG18	UR:/seq/references/Homo_sapiens_assembly18/v0/Homo_sapiens_assembly18.fasta	M5:425ba5eb6c95b60bafbf2874493a56c3	SP:Homo sapiens
+ at SQ	SN:chr12	LN:132349534	AS:HG18	UR:/seq/references/Homo_sapiens_assembly18/v0/Homo_sapiens_assembly18.fasta	M5:d17d70060c56b4578fa570117bf19716	SP:Homo sapiens
+ at SQ	SN:chr13	LN:114142980	AS:HG18	UR:/seq/references/Homo_sapiens_assembly18/v0/Homo_sapiens_assembly18.fasta	M5:c4f3084a20380a373bbbdb9ae30da587	SP:Homo sapiens
+ at SQ	SN:chr14	LN:106368585	AS:HG18	UR:/seq/references/Homo_sapiens_assembly18/v0/Homo_sapiens_assembly18.fasta	M5:c1ff5d44683831e9c7c1db23f93fbb45	SP:Homo sapiens
+ at SQ	SN:chr15	LN:100338915	AS:HG18	UR:/seq/references/Homo_sapiens_assembly18/v0/Homo_sapiens_assembly18.fasta	M5:5cd9622c459fe0a276b27f6ac06116d8	SP:Homo sapiens
+ at SQ	SN:chr16	LN:88827254	AS:HG18	UR:/seq/references/Homo_sapiens_assembly18/v0/Homo_sapiens_assembly18.fasta	M5:3e81884229e8dc6b7f258169ec8da246	SP:Homo sapiens
+ at SQ	SN:chr17	LN:78774742	AS:HG18	UR:/seq/references/Homo_sapiens_assembly18/v0/Homo_sapiens_assembly18.fasta	M5:2a5c95ed99c5298bb107f313c7044588	SP:Homo sapiens
+ at SQ	SN:chr18	LN:76117153	AS:HG18	UR:/seq/references/Homo_sapiens_assembly18/v0/Homo_sapiens_assembly18.fasta	M5:3d11df432bcdc1407835d5ef2ce62634	SP:Homo sapiens
+ at SQ	SN:chr19	LN:63811651	AS:HG18	UR:/seq/references/Homo_sapiens_assembly18/v0/Homo_sapiens_assembly18.fasta	M5:2f1a59077cfad51df907ac25723bff28	SP:Homo sapiens
+ at SQ	SN:chr20	LN:62435964	AS:HG18	UR:/seq/references/Homo_sapiens_assembly18/v0/Homo_sapiens_assembly18.fasta	M5:f126cdf8a6e0c7f379d618ff66beb2da	SP:Homo sapiens
+ at SQ	SN:chr21	LN:46944323	AS:HG18	UR:/seq/references/Homo_sapiens_assembly18/v0/Homo_sapiens_assembly18.fasta	M5:f1b74b7f9f4cdbaeb6832ee86cb426c6	SP:Homo sapiens
+ at SQ	SN:chr22	LN:49691432	AS:HG18	UR:/seq/references/Homo_sapiens_assembly18/v0/Homo_sapiens_assembly18.fasta	M5:2041e6a0c914b48dd537922cca63acb8	SP:Homo sapiens
+ at SQ	SN:chrX	LN:154913754	AS:HG18	UR:/seq/references/Homo_sapiens_assembly18/v0/Homo_sapiens_assembly18.fasta	M5:d7e626c80ad172a4d7c95aadb94d9040	SP:Homo sapiens
+ at SQ	SN:chrY	LN:57772954	AS:HG18	UR:/seq/references/Homo_sapiens_assembly18/v0/Homo_sapiens_assembly18.fasta	M5:62f69d0e82a12af74bad85e2e4a8bd91	SP:Homo sapiens
+ at SQ	SN:chr1_random	LN:1663265	AS:HG18	UR:/seq/references/Homo_sapiens_assembly18/v0/Homo_sapiens_assembly18.fasta	M5:cc05cb1554258add2eb62e88c0746394	SP:Homo sapiens
+ at SQ	SN:chr2_random	LN:185571	AS:HG18	UR:/seq/references/Homo_sapiens_assembly18/v0/Homo_sapiens_assembly18.fasta	M5:18ceab9e4667a25c8a1f67869a4356ea	SP:Homo sapiens
+ at SQ	SN:chr3_random	LN:749256	AS:HG18	UR:/seq/references/Homo_sapiens_assembly18/v0/Homo_sapiens_assembly18.fasta	M5:9cc571e918ac18afa0b2053262cadab6	SP:Homo sapiens
+ at SQ	SN:chr4_random	LN:842648	AS:HG18	UR:/seq/references/Homo_sapiens_assembly18/v0/Homo_sapiens_assembly18.fasta	M5:9cab2949ccf26ee0f69a875412c93740	SP:Homo sapiens
+ at SQ	SN:chr5_random	LN:143687	AS:HG18	UR:/seq/references/Homo_sapiens_assembly18/v0/Homo_sapiens_assembly18.fasta	M5:05926bdbff978d4a0906862eb3f773d0	SP:Homo sapiens
+ at SQ	SN:chr6_random	LN:1875562	AS:HG18	UR:/seq/references/Homo_sapiens_assembly18/v0/Homo_sapiens_assembly18.fasta	M5:d62eb2919ba7b9c1d382c011c5218094	SP:Homo sapiens
+ at SQ	SN:chr7_random	LN:549659	AS:HG18	UR:/seq/references/Homo_sapiens_assembly18/v0/Homo_sapiens_assembly18.fasta	M5:28ebfb89c858edbc4d71ff3f83d52231	SP:Homo sapiens
+ at SQ	SN:chr8_random	LN:943810	AS:HG18	UR:/seq/references/Homo_sapiens_assembly18/v0/Homo_sapiens_assembly18.fasta	M5:0ed5b088d843d6f6e6b181465b9e82ed	SP:Homo sapiens
+ at SQ	SN:chr9_random	LN:1146434	AS:HG18	UR:/seq/references/Homo_sapiens_assembly18/v0/Homo_sapiens_assembly18.fasta	M5:1e3d2d2f141f0550fa28a8d0ed3fd1cf	SP:Homo sapiens
+ at SQ	SN:chr10_random	LN:113275	AS:HG18	UR:/seq/references/Homo_sapiens_assembly18/v0/Homo_sapiens_assembly18.fasta	M5:50be2d2c6720dabeff497ffb53189daa	SP:Homo sapiens
+ at SQ	SN:chr11_random	LN:215294	AS:HG18	UR:/seq/references/Homo_sapiens_assembly18/v0/Homo_sapiens_assembly18.fasta	M5:bfc93adc30c621d5c83eee3f0d841624	SP:Homo sapiens
+ at SQ	SN:chr13_random	LN:186858	AS:HG18	UR:/seq/references/Homo_sapiens_assembly18/v0/Homo_sapiens_assembly18.fasta	M5:563531689f3dbd691331fd6c5730a88b	SP:Homo sapiens
+ at SQ	SN:chr15_random	LN:784346	AS:HG18	UR:/seq/references/Homo_sapiens_assembly18/v0/Homo_sapiens_assembly18.fasta	M5:bf885e99940d2d439d83eba791804a48	SP:Homo sapiens
+ at SQ	SN:chr16_random	LN:105485	AS:HG18	UR:/seq/references/Homo_sapiens_assembly18/v0/Homo_sapiens_assembly18.fasta	M5:dd06ea813a80b59d9c626b31faf6ae7f	SP:Homo sapiens
+ at SQ	SN:chr17_random	LN:2617613	AS:HG18	UR:/seq/references/Homo_sapiens_assembly18/v0/Homo_sapiens_assembly18.fasta	M5:34d5e2005dffdfaaced1d34f60ed8fc2	SP:Homo sapiens
+ at SQ	SN:chr18_random	LN:4262	AS:HG18	UR:/seq/references/Homo_sapiens_assembly18/v0/Homo_sapiens_assembly18.fasta	M5:f3814841f1939d3ca19072d9e89f3fd7	SP:Homo sapiens
+ at SQ	SN:chr19_random	LN:301858	AS:HG18	UR:/seq/references/Homo_sapiens_assembly18/v0/Homo_sapiens_assembly18.fasta	M5:420ce95da035386cc8c63094288c49e2	SP:Homo sapiens
+ at SQ	SN:chr21_random	LN:1679693	AS:HG18	UR:/seq/references/Homo_sapiens_assembly18/v0/Homo_sapiens_assembly18.fasta	M5:a7252115bfe5bb5525f34d039eecd096	SP:Homo sapiens
+ at SQ	SN:chr22_random	LN:257318	AS:HG18	UR:/seq/references/Homo_sapiens_assembly18/v0/Homo_sapiens_assembly18.fasta	M5:4f2d259b82f7647d3b668063cf18378b	SP:Homo sapiens
+ at SQ	SN:chrX_random	LN:1719168	AS:HG18	UR:/seq/references/Homo_sapiens_assembly18/v0/Homo_sapiens_assembly18.fasta	M5:f4d71e0758986c15e5455bf3e14e5d6f	SP:Homo sapiens
+ at RG	ID:20FUK.1	PL:illumina	PU:20FUKAAXX100202.1	LB:Solexa-18483	DT:2010-02-02T00:00:00-0500	SM:NA12878	CN:BI
+ at RG	ID:20FUK.2	PL:illumina	PU:20FUKAAXX100202.2	LB:Solexa-18484	DT:2010-02-02T00:00:00-0500	SM:NA12878	CN:BI
+ at RG	ID:20FUK.3	PL:illumina	PU:20FUKAAXX100202.3	LB:Solexa-18483	DT:2010-02-02T00:00:00-0500	SM:NA12878	CN:BI
+ at RG	ID:20FUK.4	PL:illumina	PU:20FUKAAXX100202.4	LB:Solexa-18484	DT:2010-02-02T00:00:00-0500	SM:NA12878	CN:BI
+ at RG	ID:20FUK.5	PL:illumina	PU:20FUKAAXX100202.5	LB:Solexa-18483	DT:2010-02-02T00:00:00-0500	SM:NA12878	CN:BI
+ at RG	ID:20FUK.6	PL:illumina	PU:20FUKAAXX100202.6	LB:Solexa-18484	DT:2010-02-02T00:00:00-0500	SM:NA12878	CN:BI
+ at RG	ID:20FUK.7	PL:illumina	PU:20FUKAAXX100202.7	LB:Solexa-18483	DT:2010-02-02T00:00:00-0500	SM:NA12878	CN:BI
+ at RG	ID:20FUK.8	PL:illumina	PU:20FUKAAXX100202.8	LB:Solexa-18484	DT:2010-02-02T00:00:00-0500	SM:NA12878	CN:BI
+ at RG	ID:20GAV.1	PL:illumina	PU:20GAVAAXX100126.1	LB:Solexa-18483	DT:2010-01-26T00:00:00-0500	SM:NA12878	CN:BI
+ at RG	ID:20GAV.2	PL:illumina	PU:20GAVAAXX100126.2	LB:Solexa-18484	DT:2010-01-26T00:00:00-0500	SM:NA12878	CN:BI
+ at RG	ID:20GAV.3	PL:illumina	PU:20GAVAAXX100126.3	LB:Solexa-18483	DT:2010-01-26T00:00:00-0500	SM:NA12878	CN:BI
+ at RG	ID:20GAV.4	PL:illumina	PU:20GAVAAXX100126.4	LB:Solexa-18484	DT:2010-01-26T00:00:00-0500	SM:NA12878	CN:BI
+ at RG	ID:20GAV.5	PL:illumina	PU:20GAVAAXX100126.5	LB:Solexa-18483	DT:2010-01-26T00:00:00-0500	SM:NA12878	CN:BI
+ at RG	ID:20GAV.6	PL:illumina	PU:20GAVAAXX100126.6	LB:Solexa-18484	DT:2010-01-26T00:00:00-0500	SM:NA12878	CN:BI
+ at RG	ID:20GAV.7	PL:illumina	PU:20GAVAAXX100126.7	LB:Solexa-18483	DT:2010-01-26T00:00:00-0500	SM:NA12878	CN:BI
+ at RG	ID:20GAV.8	PL:illumina	PU:20GAVAAXX100126.8	LB:Solexa-18484	DT:2010-01-26T00:00:00-0500	SM:NA12878	CN:BI
+ at PG	ID:BWA	VN:0.5.7	CL:tk
+20GAVAAXX100126:8:21:18798:198557	83	chr1	9999918	60	101M	=	9999594	-424	CAAGCTCCGCCTCCCAGGTTCACGCCATTCTCCTGCCTCAGCCTCCCGAGTAGCTGGGACTACAGGCACCCACCACCACGCCTGGCCAATTTTTTTGTATT	7<CAB>A9AAA79;;.@=BAA;60@<CDACBCC at A@CDBDBCCBCC;BDACCBCCBBBBCCBBCBBBACCBBCBBCBB;BCCCBBCBDBAAADDDCAABDC	MD:Z:15G85	PG:Z:BWA	RG:Z:20GAV.8	AM:i:23	NM:i:1	SM:i:23	MQ:i:60	OQ:Z:5BFFF?GGFFG:=@@/FDFDF=D7FBHHDHFHHDGFHHHHHHHFHHHHHHHHHHHHHHHHHHHHHHHGHHHHHHHHHHHHHHHHHHHHGGGGHHHHHHHHH	UQ:i:13
+20GAVAAXX100126:8:22:9500:19764	147	chr1	9999949	60	6S95M	=	9999628	-415	CATTCTCCTGCCTCAGCCTCCCGAGTAGCTGGGACTACAGGCACCCACCACCACGCCTGGCCAATTTTTTTGTATTTTTAGTAGAGATAGGGTTTCACCAT	#######A:A@?3=<AA:.,A:B:??:?BB at BA79BBAAA>C=BCBBAC<ACA;CBACAACABBBCCDDDCBCCDDDDCEACDCDCCADCCACC at AAABC@	MD:Z:95	PG:Z:BWA	RG:Z:20GAV.8	AM:i:37	NM:i:0	SM:i:37	MQ:i:60	OQ:Z:#######@4?@:1;4=?7+0 at AA8A?6?@>@@@5;A>A??@B6?BA;BB9BB at BBABBAABBBBBBBBBBBCBBBBBBBCBBBCBCBBBCCBBCCB@CCBB	UQ:i:0
+20GAVAAXX100126:8:26:17788:24663	99	chr1	9999965	60	101M	=	10000321	441	GAGTAGCTGGGACTACAGGCACCCACCACCACGCCTGGCCAATTTTTTTGTATTTTTAGTAGAGATAGGGTTTCACCATATTAGCCAGGATGGTCTTGATC	CDBACCCDBCCDADCACCCACABBBABC;BCA;BBCBCBBCDCDDDDDA at BBCDDDABCACCDCDCCCCCAD@BCABCCCCDCCBCCCCDCCCCCDDCDDD	MD:Z:101	PG:Z:BWA	RG:Z:20GAV.8	AM:i:37	NM:i:0	SM:i:37	MQ:i:60	OQ:Z:HHHHHHHHHHHHHHHHHHHGHHHHIHHHDHHHHHHHHHHHHHHHHHHHGGGGHHHHGGHGHHHHHHHHHHFHGHHHHHHHHHHHHHHHHHHHHHHHHHHHH	UQ:i:0
+20GAVAAXX100126:8:47:10796:84088	99	chr1	9999998	60	101M	=	10000328	430	CCTGGCCAATTTTTTTGTATTTTTAGTAGAGATAGGGTTTCACCATATTAGCCAGGATGGTCTTGATCTGCTGACCTCATGACCCACCCGCCTCGGCCTTC	CBC at CCCCDCDDDDDAA@BCDDDAACBCCDCDCC at CCBBDBBABCCCCDCCBBCCCCC>C;BDDBDCBDBBDBDABDBCCBDACCC at AA9CCDC;DCCDED	MD:Z:101	PG:Z:BWA	RG:Z:20GAV.8	AM:i:37	NM:i:0	SM:i:37	MQ:i:60	OQ:Z:HHHHHHHHHHHHHHHGGEGHHHHGGHHHHHHHHHGHHHIHHIHHHHHHHHHHHHHHGHDHCHHHHHHHHHHHHHHHHHHHHHHHHHIGGGHHHHHHHHHHH	UQ:i:0
+20GAVAAXX100126:8:62:7317:185100	675	chr1	10000001	60	78M23S	=	10000382	415	GGCCAATTTTTTTGTATTTTTAGTAGAGATAGAGTTTCACCATATTAGCCAGGATGGCCTTAATCTGCTGACCTCATAATCACACAGCCTCGTCCTTCAAA	>?78+*?88CBC24B.BBCA>6=846;8C-2@(?@10AB++7C>A/C9<>A,@?.B,()C6*B3:D8 at C*+92A:BA########################	MD:Z:32G24T3G15G0	PG:Z:BWA	RG:Z:20GAV.8	AM:i:25	NM:i:4	SM:i:25	MQ:i:60	OQ:Z:==76**=76BCA44A.ACC?;4:43273B,1=*=A34BB--8B<B/B4=9B+=@+@/))@7+ at 26ACC@)+5/@9AA########################	UQ:i:25
+20GAVAAXX100126:8:5:4250:100581	99	chr1	10000006	60	101M	=	10000330	415	ATTTTTTTGTATTTTTAGTAGAGATAGGGTTTCACCATATTAGCCAGGATGGTCTTGATCTGCTGACCTCATGACCCACCCGCCTCGGCCTTCCAAAGTGC	CCCBDDDA at BBCDDDABCBCCDCDBCCCCBDDBCABCCCCDCCBBCCCCCBCBBDDBDCBDBBDBDABDBCCADABBCAC>7BCDB;CCCDDCCBE>D at DD	MD:Z:101	PG:Z:BWA	RG:Z:20GAV.8	AM:i:37	NM:i:0	SM:i:37	MQ:i:60	OQ:Z:HHHHHHHGGGGHHHHGGHHHHHHHGHHHHHHHHHHHHHHHHHHHHHHHGHHHHHHHHHHHHHHHHHHHHHHHFHHHHHHHEEHHHHHHHHHHHHGHBHGHH	UQ:i:0
+20GAVAAXX100126:8:64:9003:28381	83	chr1	10000026	60	101M	=	9999704	-422	GAGATAGGGTTTCACCATATTAGCCAGGATGGTCTTGATCTGCTGACCTCATGACCCACCCGCCTCGGCCTTCCAAAGTGCTGGGATTACAGGTGTGAGCC	DCCBDD?A2ABB at BCBCCCDC@BC at CA@AB at ABCDCBCCCCBACAACCDBCCB@BCB at CC;BCCD;BBCCDDCBDDDACBCCBBBCDCCBDBACACBBBCC	MD:Z:101	PG:Z:BWA	RG:Z:20GAV.8	AM:i:37	NM:i:0	SM:i:37	MQ:i:60	OQ:Z:HFHFHHDG9GGGGGHHHHHHHDHHGIGGFFFHGHHHHHGHHHGHGFHHHHHHHEGHHFHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHH	UQ:i:0
+20GAVAAXX100126:8:66:8049:3241	83	chr1	10000031	60	101M	=	9999623	-508	AGGGTTTCACCATATTAGCCAGGATGGTCTTGATCTGCTGACCTCATGACCCACCCGCCTCGGCCTTCCAAAGTGCTGGGATTACAGGTGTGAGCCACCGC	?DCBEEDCCCCCCCD=DBCBDCBCCBADCDCBCCCCBCCBBCCDB at CB9BCBBCC;BCCD;BBCCDDCBDDDACBCCBBBCDCBBDBACACBDCCCCA:BC	MD:Z:101	PG:Z:BWA	RG:Z:20GAV.8	AM:i:37	NM:i:0	SM:i:37	MQ:i:60	OQ:Z:BHHHHHHHIHHHHHHBHHHHHHHHHHHHHHHHHGHHHHHHGHHHHFHHBGHHGHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHH	UQ:i:0
+20GAVAAXX100126:8:65:18189:17218	163	chr1	10000038	60	101M	=	10000302	364	CACCATATTAGCCAGGATGGTCTTGATCTGCTGACCTCATGACCCACCCGCCTCGGCCTTCCAAAGTGCTGGGATTACAGGTGTGAGCCACCGCGACCGGC	@CABAAABCCBBCBCCCCCCBBDCBCCBDCBDBA at BB?B at B@AC?CACC;@CD@:BBCBB>CB>=A;ACC@:CA@@@>A<@<B7ABBA7C>B9@;B?C4BB	MD:Z:101	PG:Z:BWA	RG:Z:20GAV.8	AM:i:37	NM:i:0	SM:i:37	MQ:i:60	OQ:Z:BCCCBCCCBCCCCBCCBBCB at BBBBBBBBBBBB>BBBABAB at BBABBBBABBAB@?AB@@@B@>9?=@BAA8A@?>@@=;?6?4?=?@6@??<@?@==8=A	UQ:i:0
+20GAVAAXX100126:8:27:11272:197846	611	chr1	10000110	60	79M22S	=	10000329	297	GATTACAGGTGTGAGCCACCGCGACCGGCCTGCTCAAGATAATTTTTAGGGCTAACTATGACATGAACCCCAAAATTCCTGTCCTCTAGATGGCAGAAACC	1;>5;;5?9>>;:;02<=<<5>5@;<4 at 9<<=:><<>=A6;*<;<???:=(:?=;/=5::?3>:=B8?)78:9::;9;#######################	MD:Z:79	PG:Z:BWA	RG:Z:20GAV.8	AM:i:25	NM:i:0	SM:i:37	MQ:i:60	OQ:Z:5555551455<==@014544EEEEA>>F@>>E>AE>AAF:4+454AAF=A/=AA50=9==A7A=AF;F-;44544=5?#######################	UQ:i:0
+20GAVAAXX100126:8:7:13574:93999	163	chr1	10000133	60	101M	=	10000392	359	ACCGGCCTGCTCAAGATAATTTTTAGGGCTAACTATGACATGAACCCCAAAATTCCTGTCCTCTAGATGGCAGAAACCAAGATAAAGTATCCCCACATGGC	@AB:AABCBBDBCBCCCCDCCCCCCCCCCDCDADB=>A at BAACD=BCCCDBBC at CCCCABBCB@CC@@AA at CBBAB?BC=ABC at CDB??A?B>AC?CC<CC	MD:Z:101	PG:Z:BWA	RG:Z:20GAV.8	AM:i:37	NM:i:0	SM:i:37	MQ:i:60	OQ:Z:BBBBBBBBABBBBBBBBBBBCBBABBBBBBBBBBB at AABBAABBAABBBBBAAABAAA>ABAB?BAA?@?AA at A?@AA@<@@@@A@?;@=?A9AA@??:>B	UQ:i:0
+20GAVAAXX100126:8:65:18208:188053	163	chr1	10000137	60	101M	=	10000358	321	GCCTGCTCAAGATAATTTTTAGGGCTAACTATGACATGAACCCCAAAATTCCTGTCCTCTAGATGGCAGAAACCAAGATAAAGTATCCCCACATGGCCACA	@CCC?@BBBDBBCAEDBBCCCCDDCDDEBECCBC?@AAB@?CCDADDDCC at AD@BCADADBCCBCC8CCCBDBABCABABBBDABDCB at C@?C at CACD?BC	MD:Z:101	PG:Z:BWA	RG:Z:20GAV.8	AM:i:37	NM:i:0	SM:i:37	MQ:i:60	OQ:Z:BCCCCCCCCCCCCCCCCCCCBCCCCBCCCCCBBCCCBBBCCBBCBBBBBBBCBBBCCBCBBBBBBACBBBABBBBBBB?BB at B>BBBBABBBBBA at ABBBB	UQ:i:0
+20GAVAAXX100126:8:65:17424:133143	163	chr1	10000184	60	101M	=	10000444	360	ATTCCTGTCCTCTAGATGGCAGAAACCAAGATAAAGTATCCCCACATGGCCACAAGGTTAAGCTCTTATGGACACAAAACAAGGCAGAGAAATGTCATTTG	@CBA at BAABCDBDACCBBCBC=CDDACCDCCCCDCB;BBABCCC?CCBCC at BAADCBBCBBBBBBD@CBB at DBA?BBBB?@BBABCCC=BAAA at A@CBAAB	MD:Z:101	PG:Z:BWA	RG:Z:20GAV.8	AM:i:37	NM:i:0	SM:i:37	MQ:i:60	OQ:Z:BBBBCBBABBBBBBBB at BBBB9BBBBBBBBBBBBBB?BBBBBBBBBAABBAABBAAA:AAAABABAAB at A@ABA at A@A>@?A?@A@@@>>A>>@9@@=?;A	UQ:i:0
+20GAVAAXX100126:8:24:16681:115751	83	chr1	10000185	60	101M	=	9999853	-432	TTCCTGTCCTCTAGATGGCAGAAACCAAGATAAAGTATCCCCACATGGCCACAAGGTTAAGCTCTTATGGACACAAAACAAGGCAGAGAAATGTCATTTGG	6EA6DADD?DCCD at CCCB?DBDDCCBDDBCCDDDACCDCCCBBBCCBB at BBBDDBADCDCBCDCDCCCBBBBC=>DDBBDDBBBDBDBDD at CADCCDBCBC	MD:Z:101	PG:Z:BWA	RG:Z:20GAV.8	AM:i:23	NM:i:0	SM:i:37	MQ:i:60	OQ:Z:5HG;HHHHEHHHHGHHHHDHHHHHHHHHHHHHHHHHHHHHHHGHHHHHFHHHHHHHHHHHHHHHHHHHHHHHHEEHHHHHHHHHHHHHHHFHHHHHHHHHH	UQ:i:0
+20GAVAAXX100126:8:65:2449:158320	147	chr1	10000187	60	24S77M	=	9999832	-431	AACTATGACATGACCCCCAAAATTCCTGTCCTCTAGATGGCAGAAACCAAGATAAAGTATCCCCACATGGCCACAAGGTTAAGCTCTTATGGACACAAAAC	#########################@<=?>?A at 67C@?A@>?4BACB=D?<B:CCB:A>>A==@;?BBCBACBCCDCADCCDBCACDACCCBBBBAA at BA@	MD:Z:77	PG:Z:BWA	RG:Z:20GAV.8	AM:i:37	NM:i:0	SM:i:37	MQ:i:60	OQ:Z:#########################?:?::?><68B>?@??;1??@@@A>@@;@@@@@?>A@@A?AB at AA@BABBBBBBBBBBB?BBBBBBBABABBCBBB	UQ:i:0
+20GAVAAXX100126:8:66:6889:6402	163	chr1	10000196	60	74M27S	=	10000514	418	TAGATGGCAGAAACCAAGATAAAGTATCCCCACATGGCCACAAGGTTAAGCTCTTATGGACACAAAACAAGGCAGAGAAATGTCATTTGGCATTGGTTTCA	@C<<B9?=>B>?A at BDD?<=?DD>-A=<C>C?=?;97A7B<=7>532;C><9B7D=8<<C<277?=@4D>2:B############################	MD:Z:74	PG:Z:BWA	RG:Z:20GAV.8	AM:i:37	NM:i:0	SM:i:37	MQ:i:60	OQ:Z:BC;9B:=>:B><ACACB;7;?BB:*@::B<B<>=>;=B;B@>7;;-08B9 at 7A6B:56<B?/85<9B5B:08?############################	UQ:i:0
+20GAVAAXX100126:8:68:13621:42696	675	chr1	10000250	37	35M66S	=	10000556	340	TATGGACACAAAAAAAGGCAGAGAAATGTCATTTGGCATTGGTTTCAGGGACCCATAGCAACATTTGTAAATGACCAGCCTGTTGGGCTGGCTTTTTACAT	=C7A at B=8-B5>2)8B#####################################################################################	MD:Z:13C21	PG:Z:BWA	RG:Z:20GAV.8	AM:i:0	NM:i:1	SM:i:37	MQ:i:29	OQ:Z::B5BCB=6,A4:1)4@#####################################################################################	UQ:i:8
+20GAVAAXX100126:8:65:18189:17218	83	chr1	10000302	60	101M	=	10000038	-364	CCATAGCAACATTTGTAAATGACCAGCCTGATGGGCTGGCTTGAAAACTTGGCTTATAGGCATCCTAAACCCACGTTCTATCCCCTGATACTCCCCTCTTC	DDCDDCCDCCCDDCACDDCBBCCBDBCCCBCCBBBCCCBBDCBDDDBCDCBBCDCCCCBBBCDCCCDD at CCBA;ADDCCCDCCCCCBCCBCDCCCCDADDC	MD:Z:101	PG:Z:BWA	RG:Z:20GAV.8	AM:i:37	NM:i:0	SM:i:37	MQ:i:60	OQ:Z:HHHHHHHHHHHIHHHHHHHFHHHHHHHHHHHHHHHHHHHIHHHHHHGHHHHHHHHHHHHHHHHHHHHHFHHHGHHHHHHHHHHHHHHHHHHHHHHHHHHHH	UQ:i:0
+20GAVAAXX100126:8:4:6560:50417	163	chr1	10000312	60	76M25S	=	10000637	425	ATTTGTAAATGACCAGCCTGATGGGCTGGCTTGAAAACTTGGCTTATAGGCATCCTAAACCCACCTTCTATCCCCTGATACTCCGCTTTTCATTACAGCAC	?>9?=7;BA;:B;<C<B?907>/5BCD?CCC>)A8=:$;30B474@>8<8?*B)BE7?@+?<.-/+39978BCAA##########################	MD:Z:64G11	PG:Z:BWA	RG:Z:20GAV.8	AM:i:37	NM:i:1	SM:i:37	MQ:i:60	OQ:Z:?;9=:18A?7:???B:B<4-4;,6ACB<BBA;)>8?>'=60A627@:6<8A*@*>B58>+?;+-,)69259 at CB@##########################	UQ:i:14
+20GAVAAXX100126:8:26:17788:24663	147	chr1	10000321	60	15S86M	=	9999965	-441	AGCAACATTTGTAAATGACCAGCCTGATGGGCTGGCTTGAAAACTTGGCTTATAGGCATCCTAATCCCACGTTCTATCCCCTGATACTCCCCTCTTCATTA	################B=?@@@B@>>4:CB5;C??BDB@@<BBCCCC<CB9@=DCB9>3>BBB8&4BCB;?DCCCB at CCDCBACA<ABCCCBCBCBABCC@	MD:Z:49A36	PG:Z:BWA	RG:Z:20GAV.8	AM:i:37	NM:i:1	SM:i:37	MQ:i:60	OQ:Z:################B7<@>@?@=>2:?>77@>B at BB??=@?BA at B?AA>>>AAB=;2?BBB<(9BBAB at BBBBA=BBCCAABA7 at BBBBBBBBBBCBCB	UQ:i:5
+20GAVAAXX100126:8:3:21049:178760	163	chr1	10000325	60	95M6S	=	10000650	425	CAGCCTGATGGGCTGGCTTGAAAACTTGGCTTATAGGCATCCTAAACCCACGTTCTATCCCCTGATACTCCCCTCTTCATTACAGAACAACAAAGAAAGAC	@CBAABACCBCCBCBCBDC?CDDEADCCCBDCAAB=?==@@CBCBD8CCC?;CAAD=C at BBC?>BA=?C>?=CA at CB?B<B<?<?AC?<D<8BA#######	MD:Z:95	PG:Z:BWA	RG:Z:20GAV.8	AM:i:37	NM:i:0	SM:i:37	MQ:i:60	OQ:Z:BBBBBBBBBBBBBBBBBBB=BBBCBBBBCABB@@B at A@@AABABBB5ABABB?B at A<A??BA<???@@?<?8A@@AB??<B=<:=;??<A>4>?#######	UQ:i:0
+20GAVAAXX100126:8:47:10796:84088	147	chr1	10000328	60	101M	=	9999998	-430	CCTGATGGGCTGGCTTGAAAACTTGGCTTATAGGCATCCTAAACCCACGTTCTATCCCCTGATACTCCCCTCTTCATTACAGAACAACAAAGAAAGACAAA	;?@B::A5;?8B:9@?=@DB at B@97@>4':8>B>?>?@>:BC>CCAC6AC>C at CCCABBCBB?>A3>CCCBCBCBD at B?BEBCACCAACCDBCBCA at ABC@	MD:Z:101	PG:Z:BWA	RG:Z:20GAV.8	AM:i:37	NM:i:0	SM:i:37	MQ:i:60	OQ:Z::7>@55<37=6=;6:9<?A@>A;78?>3'4::>>A;;@<;AA8AB>>?AB at A@AABB at BBBBA@B3 at BBB@B?ABC=A:ACBCBCBBBBBBBBBBBBBBBB	UQ:i:0
+20GAVAAXX100126:8:27:11272:197846	659	chr1	10000329	60	22S79M	=	10000110	-297	GCAACCTTTGTAACAGACCTGTCTGATGGGCTGGCTTGAAAACTTGGCTTATAGGAATCCGAAACCTACGTACTATCCCCTGATACTCCCCTCTTCATTAC	#######################@1>:@C3<B;377:2BB(@BC4)A2+>ACBB1*?CA7(-)87)'>%.(-65;B&@<765@=B3 at 2C5;C7,*?76 at A;	MD:Z:33C4T5C4T29	PG:Z:BWA	RG:Z:20GAV.8	AM:i:25	NM:i:4	SM:i:25	MQ:i:60	OQ:Z:#######################?0=8??0>?839350@@);A?0)@1*?BBC at -,ACA@)/,6=)):*-)(128@)>;333?;@1=7B6;B3+*@33AB7	UQ:i:34
+20GAVAAXX100126:8:5:4250:100581	147	chr1	10000330	60	9S92M	=	10000006	-415	TGACCAGCCTGATGGGCTGGCTTGAAAACTTGGCTTATAGGCATCCTAAACCCACGTTCTATCCCCTGATACTCCCCTCTTCATTACAGAACAACAAAGAA	##########?A>@==??B79=@819@;>8 at BBA=@;5?A>@=::BA;B?<C@>:>>B?A;5@>?@=BBBBCCCCCCBCDCBCDCBBCBCABCAAAACBC@	MD:Z:92	PG:Z:BWA	RG:Z:20GAV.8	AM:i:37	NM:i:0	SM:i:37	MQ:i:60	OQ:Z:##########?>>>7:>==77<<817?9:1@?A@??86<@@><4:??=?>?A at 7@@@?@A>6A at AA?AAA at B@BBBB at BBABBBB@BBBBBBBBBBBBBBB	UQ:i:0
+20GAVAAXX100126:8:65:18208:188053	83	chr1	10000358	60	101M	=	10000137	-321	TAGGCATCCTAAACCCACGTTCTATCCCCTGATACTCCCCTCTTCATTACAGAACAACAAAGAAAGACAAATTCTTAGCATAAAGTACACCAGATTTGCTA	DECCCCDDCCA@>BBAC9ADDCCCDCCCCCBCCCCDCCCCDCDDBCDCBBCBDBBDB@@DDBDDCBBBDDCDDCDCDBBCCDDDACBBCCBDBCDDC at BCC	MD:Z:101	PG:Z:BWA	RG:Z:20GAV.8	AM:i:37	NM:i:0	SM:i:37	MQ:i:60	OQ:Z:HHHHHHHHHHGGAGGFHIHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHGGHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHH	UQ:i:0
+20GAVAAXX100126:8:62:7317:185100	595	chr1	10000382	60	66S35M	=	10000001	-415	TTAAATGTCCAGCATGATGGGCTGGCTTGAAAACTTGGCTTATAGGCATCCTAAACCCACGTTCTATCCCCTGATACTCCCCTCTTCATTCCAGAACAACA	#####################################################################################################	MD:Z:24A10	PG:Z:BWA	RG:Z:20GAV.8	AM:i:25	NM:i:1	SM:i:37	MQ:i:60	OQ:Z:#####################################################################################################	UQ:i:2
+20GAVAAXX100126:8:7:13574:93999	83	chr1	10000392	60	101M	=	10000133	-359	CTCCCCTCTTCATTACAGAACAACAAAGAAAGACAAATTCTTAGCATAAAGTACACCAGATTTGCTACAGCCTAAGACTGGTCTGACAAATCCTTTTTTTC	DEDDDCDCDDCCDCCBDBDCBDC at ADDBDDDBCBDDCDCCDCDBBCCDDDACBBBCBCBCDDCBCCBBCBCCCDDBBCCBADCCBBBDDCDCAADDDBDDC	MD:Z:101	PG:Z:BWA	RG:Z:20GAV.8	AM:i:37	NM:i:0	SM:i:37	MQ:i:60	OQ:Z:HHHHHHHHHHHHHHHHHHHHHHHGGHHHHHHHHHHHHHGHHHHHHHHHHHHHIHIHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHGGHHHHHHH	UQ:i:0
+20GAVAAXX100126:8:25:6601:158705	99	chr1	10000400	37	101M	=	10000802	436	TTCATTACAGAACAACAAAGAAAGACAAATTCTTAGCATAAAGTACACCAGATTTGCTACAGCCTAAGACTGGTCTGACAAATCCTTTTTTTCTACTAATC	8;>7=;A?@5>>=>>;3>6=5=4328<::9;;=;:<6198=*7;9>A>??;<:>>?<A><A?@@@81;:9;,:89;:97,99999@>>B6==:41>A:4;,	MD:Z:101	PG:Z:BWA	RG:Z:20GAV.8	AM:i:0	NM:i:0	SM:i:37	MQ:i:29	OQ:Z:@CCEE at CCC;44444A7A;<7<863@<===55444=:1===,:@@FFFFD@==CAE<EEEFEFFD515444.@:=4455.44455ACCF;=@>88CE>9 at 0	UQ:i:0
+20GAVAAXX100126:8:4:15177:54134	99	chr1	10000435	60	101M	=	10000750	415	GCATAAAGTACACCAGATTTGCTACAGCCTAAGACTGGTCTGACAAATCCTTTTTTTCTACTAATCAGACCCTCGCAGAGAAGACAAATAGTGGCATTTAC	CBCACDDC at CACAB-CDCDDBBCCACCBBDCDCDACBCABDBDACDDCBBCDDDDDA>CAADBDCBBCDABBDB;BCCDCDDCDACDDCCCBCDCDCDBDB	MD:Z:101	PG:Z:BWA	RG:Z:20GAV.8	AM:i:37	NM:i:0	SM:i:37	MQ:i:60	OQ:Z:HHHHHHHHIHHHHH-HHHHHHHHHHHHHHHHHHHHHHHIHHHHHHHHHHHHHHHHHGEGGHHIHHHFHHHHHHHHHHHHHHHHHHHHHHHHGHHHHHIFHH	UQ:i:0
+20GAVAAXX100126:8:65:17424:133143	83	chr1	10000444	60	101M	=	10000184	-360	ACACCAGATTTGCTACAGCCTAAGACTGGTCTGACAAATCCTTTTTTTCTACTAATCAGACCCTCGCAGAGAAGACAAATAGTGGCATTTACCGTTTACAC	DDCDCDCCDDCBCCCBDBCCCDDBBCCBADCCBCBDDCDCBAAADDDDCCBCCDCDBCBBCCCD;BBCBCBDDBBBDDCCDACBBBCDDCCC;ADDCABCC	MD:Z:101	PG:Z:BWA	RG:Z:20GAV.8	AM:i:37	NM:i:0	SM:i:37	MQ:i:60	OQ:Z:HHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHGGGGHHHHHHHHHHHHHHHIHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHH	UQ:i:0
+20GAVAAXX100126:8:61:14621:35929	163	chr1	10000470	60	101M	=	10000818	448	TGGTCTGACAAATCCTTTTTTTCTACTAATCAGACCCTCGCAGAGAAGACAAATAGTGGCATTTACCGTTTACACAACATATACAGAGAGAGAGAGACCAG	=BC at ABAAAC=DCADDBBCCCCBDCBDCEDCC at C?B>C<:@CAC?BDB@@@BDACCACCCAC6?AA>8BCACA?>AB?CBA9C?BDDB>C@>C at DACB>@7	MD:Z:101	PG:Z:BWA	RG:Z:20GAV.8	AM:i:37	NM:i:0	SM:i:37	MQ:i:60	OQ:Z:<BB?BACCCB=BCCCBCCCCCABBBCBCCCCB?CCBCB at BCBAAACB@?@ACBBBB?BBBAB4?CC at CBBBCA???BBCBBCBBABBBBBB;?B at A?A<82	UQ:i:0
+20GAVAAXX100126:8:66:6889:6402	83	chr1	10000514	60	101M	=	10000196	-418	GAAGACAAATAGTGGCATTTACCGTTTACACAACATATACAGAGAGAGAGAGACCAGAAACTTGGCTGGTAAGAATTTCTTCCTCTGGCCAGGAGCGGTGG	;ED>CCBBB=A?ACCB?DDBC>5<?@CBBBB@@>@@?>:?BBC at DBC@C@?;;7=>9>=>;@?AACCBACDDBDCDAD@?D:=?=><===?<?<=9?09:;	MD:Z:101	PG:Z:BWA	RG:Z:20GAV.8	AM:i:37	NM:i:0	SM:i:37	MQ:i:60	OQ:Z:<HHEHHFFFBDGEHHHDHHGHEEEEEHHHHHDDEEFDECDFHGGHHGGGGD55544 at A??@GEGGHHHHHHHHHHHFHFDH at ADAADDDDDDCBDC?@@>?	UQ:i:0
+20GAVAAXX100126:8:21:13663:85034	163	chr1	10000518	60	86M15S	=	10000794	376	ACAAATAGTGGCATTTACCGTTTACACAACATATACAGAGAGAGAGAGACCAGAAACTTGGCTGGTAAGAATTTCTTCCTCTGGCCAGGAGCGGTGGCTCA	@ABCBABBBBCBCABCCAC;ACCCACBCDACCCCB>ABBBAABC at CCCBA@CC at DDADCA?BB?CB=CABACCA at CB<?B@@B at A################	MD:Z:86	PG:Z:BWA	RG:Z:20GAV.8	AM:i:37	NM:i:0	SM:i:37	MQ:i:60	OQ:Z:BBBBBCBBABCBBCCBCBBBBBBBBBCBBBBBBBBABBBBAAABABABAAABBAABBAA@@A@@A>@A=@@A@@@A@=;@@>???################	UQ:i:0
+20GAVAAXX100126:8:68:13621:42696	595	chr1	10000556	29	66S35M	=	10000250	-340	TTCTACAAATCAGACCCTCGCAGAGAAGACAAATAGTGGCATTTACCGTTTACCCAACATATACAGAGAGAGAGAGACCAGAAACTTGGCTGGTAAGCATT	#####################################################################################################	MD:Z:31A3	PG:Z:BWA	RG:Z:20GAV.8	AM:i:0	NM:i:1	SM:i:0	MQ:i:37	OQ:Z:#####################################################################################################	UQ:i:2
+20GAVAAXX100126:8:4:6560:50417	83	chr1	10000637	60	101M	=	10000312	-425	TTGGGGAGGTTGAGGCGTGTGGATCAGAAGGTCAAGAGATCCAGACCATCCTGGCCAACATGGTGAAACCCCGTCTCTACTAAAAATACAAAAATTAGCTG	A37:<;++7+::2%848-8:909::>9;;;:9<:<;6,:A>;<<==;6>=<@BB:B@@=>;=AC=D;;7778A@=D>CBA@>DD>C39@>=@>;;=:8:6:	MD:Z:2T6C7G83	PG:Z:BWA	RG:Z:20GAV.8	AM:i:37	NM:i:3	SM:i:37	MQ:i:60	OQ:Z:E84<@<-05-443(444/4553<<=<@@=@>544446-=DA?@?A?=:A?=EHH=HFFDDBEHHEH55445FHDDHCHHGCCHHEH11444FDBBDBFEBE	UQ:i:44
+20GAVAAXX100126:8:3:21049:178760	83	chr1	10000650	60	101M	=	10000325	-425	GGCGGGTGGATCAGAAGGTCAAGAGATCCAGACCATCCTGGCCAACATGGTGAAACCCCGTCTCTACTAAAAATACAAAAATTAGCTGGACATGGTGGTGG	DD;CCADCCCDCDBDDCADBDDBDBCDCBDBBCBCDCCCBBCBDCBCCBACBDDBCCC;ADCDCCBCA at DDDCAABDDDDCDCDBCCBBBBCCCACC?CBC	MD:Z:101	PG:Z:BWA	RG:Z:20GAV.8	AM:i:37	NM:i:0	SM:i:37	MQ:i:60	OQ:Z:HHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHIHHHHHHHHHHHHHHHHHHHHHHGHHHHHHHHHHHHGGHHHHGGHHHHHHHHHHHHHHHHHHHHHHHHHH	UQ:i:0
+20GAVAAXX100126:8:4:15177:54134	147	chr1	10000750	60	101M	=	10000435	-415	GGCGCCTGTAGTCCCAGCTACTCAGGAGGCTGAGGCAGGAGAATTGCTTGAACCCAGGAGGTGGAGGTTGCAGTGAGCCTAGATCACGCCACTGCACTCCA	CA8 at 1@B?BC>D?BCDBBCAB>CBBACABDABEC?CDBBDACCCCCCAC@@ACDCDACDC at BAABB@DCBCDACBDBCCCDBCCBA;ACA,ACBA at ABCB@	MD:Z:101	PG:Z:BWA	RG:Z:20GAV.8	AM:i:37	NM:i:0	SM:i:37	MQ:i:60	OQ:Z:A<>;2>=?A@?@@AAAAAA?B=BABBABABABBBBBBBBBBBB at BBBBBCA;BBBBBBBBBBBBBBBBBBBBBBBBBABBBBBBBBBBB@)@BBB at BBBBB	UQ:i:0
+20GAVAAXX100126:8:21:13663:85034	83	chr1	10000794	60	101M	=	10000518	-376	TGCTTGAACCCAGGAGGTGGAGGTTGCAGTGAGCCTAGATCACGCCACTGCACTCCAGCCTGGCGACACAGCGAGACTCCGTCTCAAAAAAAAAAATAATA	=0;BC at D<A?CDCBDCACCBCCADCBBDAABDBBCC at BCCB@;BCBBCB;B at CACBCB?CCBB8BBBBBCB;B?BBC at C;@DCD>>>>>>>>=DDCCBBCC	MD:Z:101	PG:Z:BWA	RG:Z:20GAV.8	AM:i:37	NM:i:0	SM:i:37	MQ:i:60	OQ:Z:@8 at FFFH@FDHHHHHHHHHHIHHHHHHHHDHHHIHHEHHGHEHHHHGHGBHFHFHHHHFHHHHFHHHHHHHHHEHHHEHHGHHHEEEEEEEEEHHHHHHHH	UQ:i:0
+20GAVAAXX100126:8:25:6601:158705	147	chr1	10000802	29	66S35M	=	10000400	-436	TGTACATGGTGGTGGGAGCATGGAGTCCCACCTACTCAGGAGGCTGAGGCAGGAGAATTGCTTTAACCCAGGAGGTGGAGCTTGCAGTGAGCCTAGATCAC	##########################################################################??=9;5*BBA6:?9'@5;096;>8?B?	MD:Z:14G20	PG:Z:BWA	RG:Z:20GAV.8	AM:i:0	NM:i:1	SM:i:0	MQ:i:37	OQ:Z:##########################################################################@;9654)@@@35@<'<5;-:/<<5@??	UQ:i:9
+20GAVAAXX100126:8:61:14621:35929	83	chr1	10000818	60	101M	=	10000470	-448	TGCAGTGAGCCTAGATCACGCCACTGCACTCCAGCCTGGCGACACAGCGAGACTCCGTCTCAAAAAAAAAAATAATAAATAAGAAAAGGAAAAAAAAGAAT	7D2DAD at AAA?@DBC??@9;=>AAC?BBCDCADABCCCB;BCB at BDB;BDB?CDC;ADADA@@@@A@@>@DCCDCCDDCBADBDDDDB at AAAAADDD@CCC	MD:Z:101	PG:Z:BWA	RG:Z:20GAV.8	AM:i:37	NM:i:0	SM:i:37	MQ:i:60	OQ:Z:5H8HHHGDFFEFHHHCDDFBBDFFHEHHHHHFHFGHHHHHHHIDHHHHHHHDHHHHHHGHGGGGGGGGEGHHHHHHHHHGGHHHHHHHGGGGGGHHHHHHH	UQ:i:0
+20GAVAAXX100126:8:22:20335:91038	163	chr1	10000847	29	68M33S	=	10001097	350	TCCAGCCTGGCGACACAGCGAGACTCCGTCTCAAAAAAAAAAAAAATAAAAAAAAAAAGAAAAAAAAAAAAAAAAATAAAGGAAAAGCCAAATGCAGAGAA	@BBBAABCBCA;A at B@CBA:CBB?CBC;BBDB9ACC?<@A??2)<4';C72<8)AC;%7(=CCBCD=##################################	MD:Z:43T6T2G5G8	PG:Z:BWA	RG:Z:20GAV.8	AM:i:0	NM:i:4	SM:i:0	MQ:i:37	OQ:Z:BBBBBBBBABABABAABAAAAA??ABBB?ABA7?BBA>AA@?2(?4'8A22;3'<A7%3'>AAAAA?##################################	UQ:i:40
+20GAVAAXX100126:8:65:4263:123939	99	chr1	10000877	60	101M	=	10001182	403	CAAAAAAAAAAAATAATAAATAAGAAAAGGAAAAAAAAGAATACAACTCAGGAACAGCCAAATGGAGGAGATGCATGGGACAAGGTTTAGTGGGGGGCTGC	CCDBDDD>>>??>A>?A?DDCCDCDDD?=CDDDDDD??>@A at C>CDADBCCCBDACCBACDDCBCDCCDCA:;9:B@@ABACBACAB@>;::555@?>DD5	MD:Z:0T0C99	PG:Z:BWA	RG:Z:20GAV.8	AM:i:37	NM:i:2	SM:i:37	MQ:i:60	OQ:Z:HHHHHHHEEEEEECEECFHHHHHHHHHEEHHHHHHHEECECCHFHHHHHHHHFHHHHHGHHHHHHHHHHHE at B@=GGFFGHHFGHDFDD?54444CCCHH5	UQ:i:68
+20GAVAAXX100126:8:48:15961:32254	675	chr1	10000919	29	27M74S	=	10001301	416	ACAACTCAGGAACAGCCAAATGGAGGATTTGCGCGGGCCTTGGTTTAGTGGGCGGCGGCGGAGCTTTCTCGCCCTCCGCAAGTGAATCACCCTTCCAGTGC	8=1==>?4A############################################################################################	MD:Z:27	PG:Z:BWA	RG:Z:20GAV.8	AM:i:29	NM:i:0	SM:i:29	MQ:i:29	OQ:Z:3</<===0@############################################################################################	UQ:i:0
+20GAVAAXX100126:8:25:1952:6902	99	chr1	10000924	60	101M	=	10001276	438	TCAGGAACAGCCAAATGGAGGAGATGCATGGGACAAGGTTTAGTGGGGGGCTGCGGAGCTTCCTTGCCCTCTGCAGGTGCACCACCCTTGCAGTGCGTGGA	CBCACDDACCBBCDDCBCDCCDCDCBBCCBCCDACDCCADDCCABCCCBBBDBB;CCCBDDBBDDBBBBDBDBBCCC:BBCACC?CCDDCCCCC at C;CCE=	MD:Z:101	PG:Z:BWA	RG:Z:20GAV.8	AM:i:37	NM:i:0	SM:i:37	MQ:i:60	OQ:Z:HHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHIHHHHIHHHHGGGHHHHHGHHHHHHHHHIHHHHHHHHHHCHHHHHHGHHHHHHHHHGHHHHH?	UQ:i:0
+20GAVAAXX100126:8:22:20896:187194	163	chr1	10000959	60	55M46S	=	10001303	444	AGGTTTAGTGGGGGGCTGCGGAGCTTCCTTGCCCTCTGCAGGTGCACCACCCTTGCAGTGCGTGGATATGTTTGAGGCAGGGGGGCAGGGTGTGGGGGTTG	@C<9BAA@@>=BCBBAC;@::3<AA99B at 5@;(;?63=947;94%>;>78;5A@###############################################	MD:Z:55	PG:Z:BWA	RG:Z:20GAV.8	AM:i:37	NM:i:0	SM:i:37	MQ:i:60	OQ:Z:BB=5 at BA@<;>ABBAA at 7@A:/9@=55@<4 at 9)9 at 84@>69=70(=9:56>5;A###############################################	UQ:i:0
+20GAVAAXX100126:8:22:20335:91038	83	chr1	10001097	37	101M	=	10000847	-350	AAATTGAAAAGAAAATCCTAACTTTCCAAGCCTAAGTAACAAAAGGACCAGAGGCTACCCCTTTGCAAACCCCTACCTTTTCTGTGGCAGATGGGAAATTG	EECED?@?ADCDDB at CCCCD;CDDDCBDDBCCCDDABAABDDDDBBBCBDBCBBCC at CCCCDDCBBDD:CCCCCACCDDDDCCACBBBDBCCBCBDDADCC	MD:Z:101	PG:Z:BWA	RG:Z:20GAV.8	AM:i:0	NM:i:0	SM:i:37	MQ:i:29	OQ:Z:HHHHHEGEGHHHHFEFHHHHBHHHHHHHHHHHHHHHGGFHHHHHHHGHHHHHHHHHFHHHHHHHHHHHCHHHHHIHHHHHHHHHHHHHHHHHHHHHHHHHH	UQ:i:0
+20GAVAAXX100126:8:48:6949:111164	99	chr1	10001106	60	101M	=	10001431	425	AGAAAATCCTAACTTTCCAAGCCTAAGTAACAAAAGGACCAGAGGCTACCCCTTTGCAAACCCCTACCTTTTCTGTGGCAGATGGGAAATTGTAAGTACCT	CCCBDDCBBDCDADDDBBCDCBBDCDCBCDACDD at ACDABCCDCCBCCABBBDDDBBCDDABBCDCABDDDDBDBCBCBBC<CCCC=AA at BABABA>A?A@	MD:Z:101	PG:Z:BWA	RG:Z:20GAV.8	AM:i:37	NM:i:0	SM:i:37	MQ:i:60	OQ:Z:HHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHGGHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHGH at HHHHBGGEFFFFFGAFFFA	UQ:i:0
+20GAVAAXX100126:8:21:7038:31450	99	chr1	10001134	60	101M	=	10001404	359	AACAAAAGGACCAGAGGCTACCCCTTTGCAAACCCCTACCTTTTCTGTGGCAGATGGGAAATTGTAAGTACCTCTAATTAATTAATTAATTGCCTTTTTTT	CD at ADDAACDABCCDCCBDCABBBDDDBBCDDABBBCCABDDDDBCBBBCBCCDCBCC;DDCDBBCDC=CABDBDCDCDCDCDCDCDCDCDCCADDDDDE@	MD:Z:101	PG:Z:BWA	RG:Z:20GAV.8	AM:i:37	NM:i:0	SM:i:37	MQ:i:60	OQ:Z:HHHHHHGGHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHBHHHHHGHHHAHHHHHHHHHHHHHHHHHHHIHHHHGHHHHHHE	UQ:i:0
+20GAVAAXX100126:8:65:4263:123939	147	chr1	10001182	60	2S99M	=	10000877	-403	GTTGCAGATGGGAAATTGTAAGTACCTCTAATTAATTAATTAATTGCCTTTTTTTTTTTTTGAGACAGAGTCTCTCTCTGTTGCCCAGGCTGGAGTGCAGT	###B;?C2%<?@>CCD@=1?C<B=2<??<?<C;-?BC7<B/?;??@?@DBBECDCB:?BBA>C??ACCDACCCCABCB?ACBBCCBCA?CABBC at AAAB@?	MD:Z:0G98	PG:Z:BWA	RG:Z:20GAV.8	AM:i:37	NM:i:1	SM:i:37	MQ:i:60	OQ:Z:###@5;B/%9><BAAA=>.>A>@:6:>?99>A8-A?B7;@0<98=><ABCBCBBA@=;AACCBCBBBCBBBBAB?AAA<BAABBBBABABAABBBAABAA?	UQ:i:2
+20GAVAAXX100126:8:4:13777:19279	633	chr1	10001217	0	66S35M	=	10001217	0	AAGAGAAAATCTTGCATTTTTAAAACTCAAATGTGGATTTCACGGAAACATCAAGGTGATTTGTGTAATTAACTCCCTTTTTTTTTTTTTGAGACAGAGTC	#####################################################################################################	MD:Z:6T1G26	PG:Z:BWA	RG:Z:20GAV.8	AM:i:0	NM:i:2	SM:i:0	OQ:Z:#####################################################################################################	UQ:i:4
+20GAVAAXX100126:8:4:13777:19279	693	chr1	10001217	0	*	=	10001217	0	AAGAAAACCCACTCAAGACTGACTTCCCAGAGAGGTGATGGATGAAGCATTTCCCTTTTACTATTATCTTTCCATATTGTTTAATAGCCTTCAATAAGAAG	########################################>;@=B4B at D=<>9>,1)@7A;:*3;3;,A2=-:+:A4A=AD=-=AB8:2C?<ABB=9-AC2	PG:Z:BWA	RG:Z:20GAV.8	OQ:Z:########################################@9>8 at .ABC=>8;<*/)=:A=>+5 at 4=+>.:14*9 at 1>>>B=,:A at 6>1A?8?CB=3+@@-
+20GAVAAXX100126:8:25:1952:6902	147	chr1	10001276	60	14S87M	=	10000924	-438	GCCCAGGCTGGAGTGCAGTGGCACCATCTCAGCTTGCTGCAACCTCCACCTCCTGCGTTCAGGTGATTCCCCCACACTTACTGGGCTGCATTCCCAGAAGG	###############BB:;?9ABA?>A=C=<BC@@CBBAB3>4?CBC4DC at DCC@;=DCACB at B@BCC=CBCCBBBCDCACDDCBCCABCCBBBAA?@CD@	MD:Z:16G70	PG:Z:BWA	RG:Z:20GAV.8	AM:i:37	NM:i:1	SM:i:37	MQ:i:60	OQ:Z:###############??:4>:B=@?=?>?6;BA>ABABAB4859A at B4BBABBA>BABBABBBBBBBA=BABCBB at CBBBBCCBBCBCBCBCCCCCCCCCB	UQ:i:27
+20GAVAAXX100126:8:48:15961:32254	595	chr1	10001301	29	66S35M	=	10000919	-416	TTTTATGAGACAGAGTCTCTCTCTGTTTCCCAGGCTGTAGTGCAGCGCCACCATCTAAGCTTGCTGCAACCTACACCTCCTGCGTTCAGGTGATTCCCCCA	#####################################################################################################	MD:Z:6C28	PG:Z:BWA	RG:Z:20GAV.8	AM:i:29	NM:i:1	SM:i:29	MQ:i:29	OQ:Z:#####################################################################################################	UQ:i:2
+20GAVAAXX100126:8:22:20896:187194	83	chr1	10001303	60	101M	=	10000959	-444	ACCTCCACCTCCTGCGTTCAGGTGATTCCCCCACACTTACTGGGCTGCATTCCCAGAAGGTTAAGGCATTCTTAGTCACAGGATGAGATAGGAGGACAGCA	7ADDAC8A;.?C>B;ADDCDBABB at D=:BB at AAAAAABBCCB=ACAABCAA:CBCBDCB<DCDCB?@CDCCDCDADBBBDBBC?BD?CCDBBDCBCCBBBC	MD:Z:101	PG:Z:BWA	RG:Z:20GAV.8	AM:i:37	NM:i:0	SM:i:37	MQ:i:60	OQ:Z:6FHHFH;F?0DHAHHHHHHHHHFHEH>@GGFFFFFFGGGHGHEGHEGHHGF at HHHHHHHAHHHHHEFHHGHHHHHHHHHHHHHDHHFHHHHHHHHHHHHHH	UQ:i:0
+20GAVAAXX100126:8:63:14360:55959	163	chr1	10001309	60	101M	=	10001646	437	ACCTCCTGCGTTCAGGTGATTCCCCCACACTTACTGGGCTGCATTCCCAGAAGGTTAAGGCATTCTTAGTCACAGGATGAGATAGGAGGACAGCACAAGAC	@ABCAACBB;ACBBCC at BCDCBCCCCCACADCCBCAA@ACBBCCABCCCCABCACDCDBCACCBBD at CCB@DBAAB?ACBBBCABDBB at C>BBAC?C=@EA	MD:Z:101	PG:Z:BWA	RG:Z:20GAV.8	AM:i:37	NM:i:0	SM:i:37	MQ:i:60	OQ:Z:BBBBBBBBBBBBBBBB=BBCBBBBBBBBBBBBBCBBBABBBBBBBBBBBBBABB?BBBABBBBBBBBBBABBBB at B>AB at B@AABA>BA?@ABAAAA5>@B	UQ:i:0
+20GAVAAXX100126:8:23:14390:98082	99	chr1	10001338	60	101M	=	10001748	510	CTTACTGGGCTGCATTCCCAGAAGGTTAAGGCATTCTTAGTCACAGGATGAGATAGGAGGACAGCACAAGACACAGGTCACAAAGACCTTGCTAATAAAAC	CDCAADCCCBDBBCCDBBBCCDDCCBDCDCCBCCDBCDCCBBCACCCDCBDCDCCCCDCCDACCBCACDCDACACCCCBCACADCDAADDCCDCACDE@@>	MD:Z:101	PG:Z:BWA	RG:Z:20GAV.8	AM:i:37	NM:i:0	SM:i:37	MQ:i:60	OQ:Z:HHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHIHHHHGHHHHGHHHHHHGHHHGGE	UQ:i:0
+20GAVAAXX100126:8:42:20734:56938	633	chr1	10001343	23	66S35M	=	10001343	0	ACAGACATCTGAACCAGAGAAACCAAAGGTTGTATAGAATCTGTGTAAAATGAAGTTGATGCCGAATGGGGTGCATTCCCAGAAGGTTAAGGCATTCTTAG	################################################################################################948>8	MD:Z:4C30	PG:Z:BWA	RG:Z:20GAV.8	AM:i:0	NM:i:1	SM:i:23	OQ:Z:################################################################################################@@@G@	UQ:i:2
+20GAVAAXX100126:8:42:20734:56938	693	chr1	10001343	0	*	=	10001343	0	CGTTTCATGGAGCTGGAAAGCTAGAGCTTTCCTCTAAAAGGCAGGAAGATGGGTGCTAGTCACAGCTCTAATCCTAAATTGTGAAACCTTAAGCAATTCAT	##########################################################################################AB%6/>:)*?>	PG:Z:BWA	RG:Z:20GAV.8	OQ:Z:##########################################################################################@?'3-?6))>=
+20GAVAAXX100126:8:63:8225:63647	163	chr1	10001369	60	69M32S	=	10001736	467	CATTCTTAGTCACAGGATGAGATAGGAGGACAGCACAAGACACAGGTCACAAAGACCTTGCTAATAAAACAGGTTGCGGTAAAGAAGCCAGGAAAAACCAC	@AAA>?>BB=<B9BA at CA?>@ACCC@@52B,B47>48A?>?B:A76:<<>5@>.C/?B8C;1?<)?0B#################################	MD:Z:69	PG:Z:BWA	RG:Z:20GAV.8	AM:i:37	NM:i:0	SM:i:37	MQ:i:60	OQ:Z:@=A@>?;BC6=A>B??B@=:>>BBB?=13@, at 27@8=AA at AA>>9959;=6?8- at -==6B>.?;)>0@#################################	UQ:i:0
+20GAVAAXX100126:8:21:7038:31450	147	chr1	10001404	60	11S90M	=	10001134	-359	GGAGGACAGCACAAGACACAGGTCACAAAGACCTTGCTAATAAAACAGGTTGTGGTAAAGAAGCCAGGAAAACCCACCAAAACCAAGATGGTGATGAGAGT	############ACACB>ABA?@@;=BBDB>CB?7>C?CA=CCDBCCAAA at ABC@BACBABCABACBBCCCBCCCADBCCCBDCCDCBCCACBCA at BACA@	MD:Z:90	PG:Z:BWA	RG:Z:20GAV.8	AM:i:37	NM:i:0	SM:i:37	MQ:i:60	OQ:Z:############A@>>A:>A?@;@9<@AA?>B@=9<B at B@?BBA at B@BA at AAAA@ABBAABBBBBBBBBBB at BBC?CBCCCACCBBCBBCCBBBCCBCCBB	UQ:i:0
+20GAVAAXX100126:8:48:6949:111164	147	chr1	10001431	60	101M	=	10001106	-425	AATAAAACAGGTTGTGGTAAAGAAGCCAGGAAAACCCACCAAAACCAAGATGGTGATGAGAGTGGCCTCTGGTCTTCCTCACTGCTCATCATACACTAATT	C@/CD=9=:B4A7?>B78D?*7DB?B at ABBBCC;@CB>CBBCCCCBDACC at CACBCACDBC@BB>B at CCCCACCECCCCBBCCBCCBBCBCCBAB@A at BD@	MD:Z:101	PG:Z:BWA	RG:Z:20GAV.8	AM:i:37	NM:i:0	SM:i:37	MQ:i:60	OQ:Z:A:->@:/;3?5;6?8=77B>)7A@?A@@@@AA at 6BAA>BABBA?BABABBAABBABBBBBBBBBABABBBBBBBCBBBBB at CBBBBBBBCBCACACBCCBB	UQ:i:0
+20GAVAAXX100126:8:41:12744:193967	163	chr1	10001443	60	101M	=	10001607	264	TGTGGTAAAGAAGCCAGGAAAACCCACCAAAACCAAGATGGTGATGAGAGTGGCCTCTGGTCTTCCTCACTGCTCATCATACACTAATTATAATGCATTAG	@CAA?<ABC at CD;>B=ABCDDDADCCACCDDD at CBAAA8?>9<7:>BB)@8=A9CBBC@>6:@=<B?9>?<BAA=;?@CB?<@<?5B@<8@;=;A8?C9=7	MD:Z:101	PG:Z:BWA	RG:Z:20GAV.8	AM:i:37	NM:i:0	SM:i:37	MQ:i:60	OQ:Z:BCBB>9AAB=BB>AA;@AABBBBCBBBBBBBBABBABA<A at 6>3>>>?*<6>>=?=A??=2:>=:@@99@;@@@=9?@@A?=:=<1=?<4@:7:<6:?672	UQ:i:0
+20GAVAAXX100126:8:67:20277:111625	163	chr1	10001509	37	90M11S	=	10001528	88	TCACTGCTCATCATACACTAATTATAATGCATTAGCATTAGCACCCACCACACCCAGCTAATTTTTGTATTTTTAGTAGAGACGGGGGTAGATCGGAAGAG	@CB>B>AB>B;A<BCAD@@;?>:C at ADDC@DBC<=A7=<=@>@AA at B@>D60 at ACD?AC?>CCBCA7>B?=7CA<B>:A>BAB::@D,;C4 at 6;;@9C;C=	MD:Z:51G35T1T0	PG:Z:BWA	RG:Z:20GAV.8	AM:i:37	NM:i:3	SM:i:37	MQ:i:37	OQ:Z:BCC at B?BA<A<?>BBBCA<:<<7B?ABCC?CAA<@B<@?@C?@BB??@>C;- at BBB>>A>?BBBBC::A=>1@@=A=C==BBBA:=B06B1=1:BB4>7<:	UQ:i:60	XT:i:90
+20GAVAAXX100126:8:2:15613:129653	99	chr1	10001516	29	101M	=	10001879	396	TCATCATACACTAATTATAATGCATTAGCATTAGCACCCACCACGCCCAGCTAATTTTTGTATTTTTAGTAGAGACGGGGTTTTACCATGTTGGCCAGGAT	CBCABCCCACADBDCDCCCDCBBCCDCCBCCDCCBCABBCABCA;BBBCCBDCDCDDDDBBBCDDDAACCCCBCDA;CCC;DDDCACCCCCDCC>CDDDE=	MD:Z:101	PG:Z:BWA	RG:Z:20GAV.8	AM:i:29	NM:i:0	SM:i:29	MQ:i:29	OQ:Z:HHHHHHHHHHHHGHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHGGHHHHGGHHHHGHHHHHHHCHHHHHHHHHIHHICHHHHH@	UQ:i:0
+20GAVAAXX100126:8:6:3004:12551	675	chr1	10001521	29	74M27S	=	10001879	391	ATACACTAATTATAATGCATTAGCATTAGCACCCACCACGCCCAGCTAATTTTTGTATTTTTAGTAGAGACGGGGTTTTACCATGTTGTCCAGGATGGTCT	@B6<A?BBCCA?::C:=A>ACD@@CC?;A:9><AB at 6=:.72?::@@'5B1=C;@B6B>C9=/;>9=@.7?9C############################	MD:Z:74	PG:Z:BWA	RG:Z:20GAV.8	AM:i:29	NM:i:0	SM:i:29	MQ:i:29	OQ:Z:B at 7=ABCBBB@>=?@8:@:@AC>?BB=:@:6=:@BB;??8;3 at 5=@;(3 at 3=B=;;4@<B:<.;67@>+4B;A############################	UQ:i:0
+20GAVAAXX100126:8:67:20277:111625	83	chr1	10001528	37	31S70M	=	10001509	-88	CTCTTCCGATCTTCACTGCTCATCATCCACTAATTATAATGCATTAGCATTAGCACCCACCACACCCAGCTAATTTTTGTATTTTTAGTAGAGACGGGGTT	################################=?:69;;3:-;;9>-2;<:=/=.78=48>195?@9?==B<-48>==02=?>?AB?:>A>?<<8=?7<=<	MD:Z:32G37	PG:Z:BWA	RG:Z:20GAV.8	AM:i:37	NM:i:1	SM:i:37	MQ:i:37	OQ:Z:################################AA>655515/555502555514'4442440 at 3CC@DADG?08:A44114DADGG55444DD:FDFFGGG	UQ:i:20	XT:i:90
+20GAVAAXX100126:8:21:3663:199637	99	chr1	10001543	60	101M	=	10001860	376	GCATTAGCACCCACCACGCCCAGCTAATTTTTGTATTTTTAGTAGAGACGGGGTTTTACCATGTTGGCCAGGATGGTCTCCATCTCTTGACCTCATCATCC	CBCADCCCCABBCABCA;BBBCCBDCDCDDDDB at ACDDD@BCBCCDCDA;CCCBDDDCABCCBCDBCBBCCCDCBCBBDBBCCBDBDDCDACDCDCCDCDD	MD:Z:101	PG:Z:BWA	RG:Z:20GAV.8	AM:i:37	NM:i:0	SM:i:37	MQ:i:60	OQ:Z:HHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHEGHHHHGGHHHHHHHHHHHHGHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHH	UQ:i:0
+20GAVAAXX100126:8:63:4634:186518	99	chr1	10001553	23	71M30S	=	10001924	425	CCACCACGCCCAGCTAATTTTTGTATTTTTAGTAGAGACGGGGTTTTACCATGTTGGCCAGGATGGTCTCCATCTCTTGACCTCATCATCCGCCCACCTCA	:<>6=@>8@??;=:<?;=>?>>5;;@AA@;3::83;=;:4B>=@@<<;9;9:;;;=7:;;=7;;<@;>?=###############################	MD:Z:71	PG:Z:BWA	RG:Z:20GAV.8	AM:i:0	NM:i:0	SM:i:23	MQ:i:29	OQ:Z:EFCFDFFFFFFBABBF at AAAEC;@>FFFF at 6=@=844445GEEEF44455:>=@=4555555555CCCCA###############################	UQ:i:0
+20GAVAAXX100126:8:26:17894:31587	163	chr1	10001582	60	97M4S	=	10001891	407	TAGTAGAGACGGGGTTTTACCATGTTGGCCAGGATGGTCTCCATCTCTTGACCTCATCATCCGCCCACCTCTGCTTTCCGCAACCAATCGGACTGATTACA	@CBAAABBCA:CCBBCCCCACCCBACBCCCC@@BBA?>?C8C at C@BCDCA@>CACCAB at A@C9>CA9 at BC@B?@=<@<C7=A?>BCC>;48?@BBB#####	MD:Z:97	PG:Z:BWA	RG:Z:20GAV.8	AM:i:37	NM:i:0	SM:i:37	MQ:i:60	OQ:Z:BBBAABABBBABBBABBBBBBBBBBBBABBB>?@BBA at AB;B at BB@BAA at A@AABA@?>?AA@?B><A?AA<;B:;?=A>=?9????<=5:;??=?#####	UQ:i:0
+20GAVAAXX100126:8:41:12744:193967	83	chr1	10001607	60	101M	=	10001443	-264	TGGCCAGGATGGTCTCCATCTCTTGACCTCATCATCCGCCCACCTCTGCTTTCCGCAACCAATCGGACTGATTACAGGCCACTACTTCACCTCATTTACAT	A>CACBC>CC at AC?CCBCAAD at ABBCA>B at CDB@D>;?CCBACCCCCBC?D:C;BB at BCBDCD;BBBCCBCDCBBDBBCBCCCBCDDB at CC<BCDDCABCC	MD:Z:101	PG:Z:BWA	RG:Z:20GAV.8	AM:i:37	NM:i:0	SM:i:37	MQ:i:60	OQ:Z:GAHFHDHEHGFHGEFGHHEGHGGFHHGDGGHHHEHDHDHHHGHHGHHHHDHBHHHHGHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHEHHBHHHHHHHHH	UQ:i:0
+20GAVAAXX100126:8:63:14360:55959	83	chr1	10001646	60	101M	=	10001309	-437	CCACCTCTGCTTTCCGCAACCAATCGGACTGATTACAGGCCACTACTTCACCTCATTTACATGGGTGAACACCCAGTGGCCAATGGGAAACCTCTAGTGGG	BDCDCDCDCCDDDC;BBDCCBDCD;B at BBCBCDCBBDCBCBACCBCDDB@CCDBCDDCBBCCBBACBDBB at CCBDACBBCBDCCBBBDDBCCDCCDAABBC	MD:Z:101	PG:Z:BWA	RG:Z:20GAV.8	AM:i:37	NM:i:0	SM:i:37	MQ:i:60	OQ:Z:FHHHHHHHHHHHHHHHHHHHHHHHHHGHIHHHHHHHHHHHHGHHGHHHHEHHHHHHHHHHHHHHHHHHHHEHHHHHHHHHHHHHHHHHHHHHHHHHHHHHH	UQ:i:0
+20GAVAAXX100126:8:65:13649:138985	99	chr1	10001701	60	93M8S	=	10002037	410	TTTACATGGGTGAACACCCAGTGGCCAATGGGAAACCTCTAGTGGGTATTTGGACTGGAGAAAATTCTGTATCCAGGGCCCTTGAGTGGCTGGCGGGGGCC	CDCAACCCCCBBDDACABBCCBBCBBCDCBCCDDDABCBCCCBBCC at CCDDBCDADBCDCDDDDCD@DBCCCBBCCC at BCBDDCDCCCCBBA#########	MD:Z:92C0	PG:Z:BWA	RG:Z:20GAV.8	AM:i:37	NM:i:1	SM:i:37	MQ:i:60	OQ:Z:HHHHHHHHHHGHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHIHHHEHHHHHHHHHHHHHHHHHHHGHHHHHHHHHHFHHHHHHHHHHHHFF#########	UQ:i:2
+20GAVAAXX100126:8:63:8225:63647	83	chr1	10001736	60	101M	=	10001369	-467	CCTCTAGTGGGTATTTGGACTGGAGAAAATTCTGTATCCAGGGCCCTTGAGTGGCTGCTGGGGCCCGCTCCCACCTGGTGAAATGTACTTTCATTTTCAAT	&<C=?A?A<=>CCBBC;=:?<:;===DAADD?B9:?8C>AB::+09 at A=A>=:9:<B:C=BB=CC;BCDCC=====BACBDDCCACB at DDDBCDDDD@CCC	MD:Z:101	PG:Z:BWA	RG:Z:20GAV.8	AM:i:37	NM:i:0	SM:i:37	MQ:i:60	OQ:Z:2BFBDCFEBBEHHFFH at DCD@@>>A>HFFHHDFB at D:HEEH==26:CFDFFA@@@=H at HEHHAHHHHHHHHA4DDAHHHHHHHHHHGCHHHHHHHHHHHHH	UQ:i:0
+20GAVAAXX100126:8:23:14390:98082	147	chr1	10001748	60	101M	=	10001338	-510	ATTTGGACTGGAGAAAATTCTGTATCCAGGGCCCTTGAGTGGCTGCTGGGGCCCGCTCCCACCTGGTGAAATGTACTTTCATTTTCAATAACTCTCTGCTT	BE at DC@CAC?@D??DA>BCAB at CABB@ACB@;BA at CBAACBBCDBCDACC?DB9CB at CAB>=AB7 at BBCCDCACBCDECBCDEECCBABBABCBB@AABD@	MD:Z:101	PG:Z:BWA	RG:Z:20GAV.8	AM:i:37	NM:i:0	SM:i:37	MQ:i:60	OQ:Z:@@BBA???@=A@@=@<<A?ABBBA at A@@B>A:?@B at A@BBBABBBBBBBBABA at BAABAB?@BB<BBBABCBBB at BBCBBBBCCBCCCBCACACBCBCCBB	UQ:i:0
+20GAVAAXX100126:8:66:19565:6891	99	chr1	10001761	60	35M66S	=	10002052	375	AAAATTCTGTATCCAGGGCCCTTGAGTGGCTGGCGGGGGCCGCCCCCACCCTGTGAAATTTACTTTTACTTTCTATAACTCTCTGCTTTTTTTGTTTCATT	>>=7>@?A?@<B<B?<@=9><?<<;A@@B@#######################################################################	MD:Z:32C0T1	PG:Z:BWA	RG:Z:20GAV.8	AM:i:25	NM:i:2	SM:i:25	MQ:i:60	OQ:Z:DFADAFFFFFDGDGD>C?@A44555GEFGF#######################################################################	UQ:i:4
+20GAVAAXX100126:8:28:18116:51320	99	chr1	10001794	60	101M	=	10002126	432	TGGGGCCCGCTCCCACCTGGTGAAATGTACTTTCATTTTCAATAACTCTCTGCTTTTGTTGTTTCATTTTTTTCTTGGTTGTGTGTTTTCTTAAACTCTTT	CBCACCCC;BDBBBBABDBCCBDDDCBBCADDDBCCDDDBCDCCDACBCBCBBDDDDBC at ACADBCCDDDDD@@BA>CBDBCCCBCDDDBDA<<AAD at BEE	MD:Z:101	PG:Z:BWA	RG:Z:20GAV.8	AM:i:37	NM:i:0	SM:i:37	MQ:i:60	OQ:Z:HHHHHHHHHHHHHHIHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHGGHGHHHHHHHHHGGGGEHIHHHHHHHHHHHHGB at GHHGGHH	UQ:i:0
+20GAVAAXX100126:8:25:15872:153534	163	chr1	10001807	60	101M	=	10002149	442	CACCTGGTGAAATGTACTTTCATTTTCAATAACTCTCTGCTTTTGTTGTTTCATTTTTTTCTTGGTTGTGTGTTTTCTTAAACTCTTTTTTTTTTTTTTTT	@CABAABABCCDCABCADCCBCDCCCBCDCCDADAC at AAACCCC@ACCACAACADDCDCC at DCACC@BCB at CCACC@BD???@BADDC at BBCBBBBDCBEC	MD:Z:101	PG:Z:BWA	RG:Z:20GAV.8	AM:i:37	NM:i:0	SM:i:37	MQ:i:60	OQ:Z:BBCCCBB at BBBBBB@BBBCBBBCBBBBBBBBBBBBBBABBBBBBB at BB@BBAABBBABBBABBBA at AB>A?B@@AA at BA?>>@@?@@A@?AA?@?@@?AAB	UQ:i:0
+20GAVAAXX100126:8:25:15890:153544	1187	chr1	10001807	60	101M	=	10002149	442	CACCTGGTGAAATGTACTTTCATTTTCAATAACTCTCTGCTTTTGTTGTTTCATTTTTTTCTTGGTTGTGTGTTTTCTGATACTCTTTTTTTTTTTTTTTT	@@ABB at A6BCBC;>@?ADCCABCCCC=CDCACAD at C@C<?>5CC at BCCACABCACDCDCCADCACC@BC>7AAAB(A?(5(5ABB at DC>B>5A at CACAACA	MD:Z:78T1A20	PG:Z:BWA	RG:Z:20GAV.8	AM:i:37	NM:i:2	SM:i:37	MQ:i:60	OQ:Z:B>CABA?4BAAA>A8?BBBAAABBCC;ABBAABBCBBB at A?5BBBABCBBBBBBCBBBBABBABBABB?;3><BB(A>'5)5ABB:@AB>=3=>>??;?<>	UQ:i:14
+20GAVAAXX100126:8:24:3855:143240	163	chr1	10001827	60	85M16S	=	10002054	327	CATTTTCAATAACTCTCTGCTTTTGTTGTTTCATTTTTTTCTTGGTTGTGTGTTTTCTTAAACTCTTTTTTTTTTTTTTTTTTTTTTCTTTGATTTTTCCT	@CB at A<ABC>AD>BBE at CCBECCCCACCBCBBBA@><BBBBBBCA>BC at C=BBADDABCCBDACB/5;D>:BD3=BBA??@AD@#################	MD:Z:85	PG:Z:BWA	RG:Z:20GAV.8	AM:i:37	NM:i:0	SM:i:37	MQ:i:60	OQ:Z:BCCCB<AAA<ABACBC?ACBCCBCCBCB?BCA@@CC at BBBBAABB=>B?B?BABABC=BBBBBBB+7:B;;?A3<@BB;>?BB?#################	UQ:i:0
+20GAVAAXX100126:8:21:3663:199637	147	chr1	10001860	60	41S60M	=	10001543	-376	TGTGCTTTCATTTTTAATAACTCTCTGCTTTTGTTGTTTTTTTTTTTTCTTGGTTTTGTGTTTTTTTAAACTCTTTTTTTTTTTTTTTTTTTTTGATGGAG	##########################################BCDCD8(;8/;>>)0.2-9A>?(>:3=89+)CDDDDDDDDDDDDDBCDCCCBABABBD@	MD:Z:14G8C36	PG:Z:BWA	RG:Z:20GAV.8	AM:i:37	NM:i:2	SM:i:37	MQ:i:60	OQ:Z:##########################################@@B at B8'::->:9(/-1/;A@@*@>3<16+(ABBBBBBBBBBBBBBBBBBBBCBBBBBB	UQ:i:15
+20GAVAAXX100126:8:2:15613:129653	147	chr1	10001879	29	64S34M3S	=	10001516	-396	GGAATGTCGTTTCATTTTCAATAACTCTCTTCTTTTTTTTTTTCATTTTTTTCTTGGTTTTGTTTTTTCTTAAACTCTTTTTTTTTTTTTTTTTTTTTTGA	#################################################################>C;'79AA94)*ADEEEEEEDEBCDDCCCBABCBC@	MD:Z:34	PG:Z:BWA	RG:Z:20GAV.8	AM:i:29	NM:i:0	SM:i:29	MQ:i:29	OQ:Z:#################################################################@B8&39>>40*)?BCCCCCCBCCBCCBBBCCBBCCB	UQ:i:0
+20GAVAAXX100126:8:6:3004:12551	595	chr1	10001879	29	68S10M1D23M	=	10001521	-391	TATGAGATTGTTTCTTTTTTTTTTCATTCCGCGAGTTTTTTTTTTTTTCTTTTTTTTCTTTGTTGGTTTTTTTTTATATATTTTTTTTTTTTTTTTTTTTT	##################################################################################;;;<;;;;=;;;;=?428?	MD:Z:4C3A1^C1C21	PG:Z:BWA	RG:Z:20GAV.8	AM:i:29	NM:i:4	SM:i:29	MQ:i:29	OQ:Z:##################################################################################@@@@@@@@>@@@@EA at 2@A	UQ:i:6
+20GAVAAXX100126:8:26:17894:31587	83	chr1	10001891	60	2S99M	=	10001582	-407	CTCTTTTTTTTTTTTTTTTTTTTTGATGGAGTCTTGCTCTGTCACCCAGGCTGGAGTACAGTGGCGTGATCTCGGCTCACTGCAACCTCTGCCTCCCAGGT	###@>BA;A at AAA@AB=ADDDDDCBCCBBDADCDCBCDCCADBBCCBDBBCCBBCACBBCACBB;ACBCCCD;BBCDBBCCBBDBCCDCCBCCDCCCBBAC	MD:Z:99	PG:Z:BWA	RG:Z:20GAV.8	AM:i:37	NM:i:0	SM:i:37	MQ:i:60	OQ:Z:###GBGG?GEEGGEGG>GHHHHHHHHHHHHHHHHHHHHHHHHHGHHHHHHHHHHHHHHHHHHHHHHHHHGHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHH	UQ:i:0
+20GAVAAXX100126:8:63:4634:186518	147	chr1	10001924	29	46S55M	=	10001553	-425	TGTTTTTTACATTTTTTTTTTTTTTTTTTTTTTTTGATGGAGTCTTGCTCTGTCACCCAGGCTGGAGTACAGTGGCGTGATCTCGGCTCACTGCAACCTCT	###############################################@C:5==8->548?7027 at 84B,-B2**(%6A;>))B4B:A4-B9<==A at 7>A@?	MD:Z:55	PG:Z:BWA	RG:Z:20GAV.8	AM:i:0	NM:i:0	SM:i:0	MQ:i:23	OQ:Z:###############################################A?95;<3'>:08?;029B88A)+ at 2(**)6?8<))@7 at 9@5- at 88;=?A7>@<>	UQ:i:0
+20GAVAAXX100126:8:65:13649:138985	147	chr1	10002037	60	26S75M	=	10001701	-410	GCCCGCCGAAGAGCTGGGACCACAGGCACCCGCCACCACGCCCGGCTAATTTTTTGTATTTTTAGTAGAGACAGTGTTTCACTATGTTAGCCAGGATGGTC	###########################ADB3?8>9DC@;=BC;B>CC9DBBDCDBAACCB879C4BCBDAACC?B>DCCB?AADDBEADBCBCBAA at BAC@	MD:Z:75	PG:Z:BWA	RG:Z:20GAV.8	AM:i:37	NM:i:0	SM:i:37	MQ:i:60	OQ:Z:###########################@B>;>8>9BBBB=BAB>>CBCCABBBB?BBBCA:9>B<BBBC@?CA@@?BAAA8?ACCCCCCCCCCCCCCBCBB	UQ:i:0
+20GAVAAXX100126:8:66:19565:6891	147	chr1	10002052	60	16S85M	=	10001761	-375	GCTCCCGCCGCCACGCCCGGCTAATTTTTTGTATTTTTAGTAGAGACAGTGTTTCCCTATGTTAGCCAGGATGGTCTCACTCTCCTGACCTCGTGATCTGC	#################95>>784B6A14:35D4:*C4A:6:B@<;79AC667=<$87B:3>3C896+8A9<@9)6)A7*,+).>B*/5>9:A>777:??>	MD:Z:39A23A21	PG:Z:BWA	RG:Z:20GAV.8	AM:i:25	NM:i:2	SM:i:37	MQ:i:60	OQ:Z:#################@1>>942A4?//353B2=*@5?;95B9;519BB;168:(;5C;7 at 8B>=5*8 at 79=7)2*@0)+*)0;A*+9;7AC=2527?==	UQ:i:12
+20GAVAAXX100126:8:24:3855:143240	83	chr1	10002054	60	101M	=	10001827	-327	GGCTAATTTTTTGTATTTTTAGTAGAGACAGTGTTTCACTATGTTAGCCAGGATGGTCTCAATCTCCTGACCTCGTGATCTGCCCGCCTCGGCCTCCCAAA	AD<DDA?@@DDC=?@DDDDCDAAD at DBABDACAADB:9>@=CA@;DBCBDBBCC=A>9:??>6=;==?B at CCD;?CBC=CCABB5>=CD;BBC=D=<4:<<	MD:Z:101	PG:Z:BWA	RG:Z:20GAV.8	AM:i:37	NM:i:0	SM:i:37	MQ:i:60	OQ:Z:FHBHHEEEEHHHEEDHHHHHHHGHGHHGHHHHHGHF at BCCBHHCBHHHHHHHHHEHCBBCDD;A at DEEHFHHHHGHHH>HHGGGEEEHHHHHHEHDEEEGG	UQ:i:0
+20GAVAAXX100126:8:48:18256:122283	163	chr1	10002059	60	101M	=	10002396	437	ATTTTTTGTATTTTTAGTAGAGACAGTGTTTCACTATGTTAGCCAGGATGGTCTCAATCTCCTGACCTCGTGATCTGCCCGCCTCGGCCTCCCAAAGTGCT	@CA@??@ABBCBB at BCCBCCCCCACCBCBCCBCACBAA?BBCBCACDCCCA at CBCDDDBDACC?CA at DC;@CA<@BAAB?8ACBB:DA at D>ABAC@@<<DA	MD:Z:101	PG:Z:BWA	RG:Z:20GAV.8	AM:i:37	NM:i:0	SM:i:37	MQ:i:60	OQ:Z:BCCCCCCCABCCCCCBBABCBBBBBCACBBBBBBBBBBABBBBBBBBABBB?BBBBBBABBBA@@BABBB?B=>@@AA@>@A@@B at A?A@>BB??=;1:B>	UQ:i:0
+20GAVAAXX100126:8:61:16672:156327	163	chr1	10002072	60	101M	=	10002410	438	TTAGTAGAGACAGTGTTTCACTATGTTAGCCAGGATGGTCTCAATCTCCTGACCTCGTGATCTGCCCGCCTCGGCCTCCCAAAGTGCTGGGATTACAGGCG	@CBBA at BCBCACB>BACCBCBDCCBACCCCCBCCABAB>ACBCCABDBCD?BA at DC;CCB?BC?AB49ACAB:AAAB?CB>9BA=CC>?C1BBA@<=C>C:	MD:Z:101	PG:Z:BWA	RG:Z:20GAV.8	AM:i:37	NM:i:0	SM:i:37	MQ:i:60	OQ:Z:BBBB at CBBBBBBBABABBBBCBBBBBBBBBBABBABBB@BBBBABBBABBAABAABB at B@@AA@@@8@@B at A@AA at A?AB=7=@6AA;@A4@@?<;7@=?@	UQ:i:0
+20GAVAAXX100126:8:28:18116:51320	147	chr1	10002126	60	101M	=	10001794	-432	TCGTGATCTGCCCGCCTCGGCCTCCCAAAGTGCTGGGATTACAGGCGTGAGCCACCGCACCTGGCCCTTGTTAAATTCTTTGTTCAAAATGCCAAAAACCT	85=C@;CA75=9/=A<?9C==9@;<>BADA at ABB@B?@CA>A at C@:A at BC@CABC;;C at CABAA?=BCCADCCCCDCCEECADCCCB at CCBCBBBAAACC@	MD:Z:101	PG:Z:BWA	RG:Z:20GAV.8	AM:i:37	NM:i:0	SM:i:37	MQ:i:60	OQ:Z:45==<8??14=84<>6<??==8;<==@@@A@@?AA@>@B@>@=B@@AAAABAA>ABCB at BABBBA@BABBBBBBBBBBCCBBBBCBCCCBBBBBBBBABCB	UQ:i:0
+20GAVAAXX100126:8:65:9835:166164	163	chr1	10002137	60	101M	=	10002441	404	CCGCCTCGGCCTCCCAAAGTGCTGGGATTACAGGCGTGAGCCACCGCACCTGGCCCTTGTTAAATTCTTTGTTCAAAATGCCAAAAACCTGGACACCCTCC	@C:AABA:CBCDBACCDDB?BBDBCCCBCCABBC?8>A=B;CAA=7 at C=C;?A?CCBB@@BBAABA?BDA>CB at B?=?CAAACACDB@@C at 4(9C?7D>@B	MD:Z:101	PG:Z:BWA	RG:Z:20GAV.8	AM:i:37	NM:i:0	SM:i:37	MQ:i:60	OQ:Z:BBBBBBBBBBBBBBBBBBA<BBBBBBAABBBAABAAAB?B>BAA?>>A?B=?>AAB???;AA?@A?A at A????A@=<>AAB?@?@@=B@?A5'9?A3?::?	UQ:i:0
+20GAVAAXX100126:8:26:12389:180500	99	chr1	10002138	60	101M	=	10002456	418	CGCCTCGGCCTCCCAAAGTGCTGGGATTACAGGCGTGAGCCACCGCACCTGGCCCTTGTTAAATTCTTTGTTCAAAATGCCAAAAACCTGGACACCCTCCA	C;B at DB;CBBDBBBCDDCB at BDBCCDCDCACCCA;B at DCBBCAB;BCABCBCBBBDDBC at CDDCDBDD@BCDBCDDDCBBBBDDDBA+ACCDADABABCDE	MD:Z:101	PG:Z:BWA	RG:Z:20GAV.8	AM:i:37	NM:i:0	SM:i:37	MQ:i:60	OQ:Z:HHHHHHHHHHHHHHHHHHHIHHHHHHHHHHHHHIHHGHHHHHHHHHHHHHHHHHHHHHHGHHHHHHHHGHHHHHHHHHHHHGHHHFH0DHHHHHHGGDHHH	UQ:i:0
+20GAVAAXX100126:8:23:10396:142336	163	chr1	10002141	60	101M	=	10002456	415	CTCGGCCTCCCAAAGTGCTGGGATTACAGGCGTGAGCCACCGCACCTGGCCCTTGTTAAATTCTTTGTTCAAAATGCCAAACACCTGGACGCCATCCACTG	@DB:BA at CBCCCCBA<AACBCBCCCCACCCB;BA?;@7<;-7 at B=CD at 898BD;CBAADC<<;<CC??DA=CB3>;'7<49/A;.A5;<)#8?):>=C?E9	MD:Z:81A8A2C7	PG:Z:BWA	RG:Z:20GAV.8	AM:i:37	NM:i:3	SM:i:37	MQ:i:60	OQ:Z:BBBAAB=BABBBBB at 7@AAABABBBBBBBABBA@@>B9?@. at A@ABA=:6;AA=BA??BA>;:;ABB=B@=??1>:*6737/<;-;0;<*&6;'4=8??@4	UQ:i:24
+20GAVAAXX100126:8:25:15872:153534	83	chr1	10002149	60	101M	=	10001807	-442	CCCAAAGTGCTGGGATTACAGGCGTGAGCCACCGCACCTGGCCCTTGTTAAATTCTTTGTTCAAAATGCCAAAAACCTGGACACCCTCCACTGGTACTGAA	DE?DDDADCCCCCBCDCACDB>;ACBBBCBBC;BBBCCCBBCCCDCADCDDCDDCDDCADDBDDDCCBCBDDDDBCCCBBCBBCCCDCBBCCBACCCABDC	MD:Z:101	PG:Z:BWA	RG:Z:20GAV.8	AM:i:37	NM:i:0	SM:i:37	MQ:i:60	OQ:Z:HHGHHHHHHHHHHHHHHEHHHCHHHHGHHHIHHHHIHHHHIHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHGHHHHHHHHHHHHHHHHHH	UQ:i:0
+20GAVAAXX100126:8:25:15890:153544	1107	chr1	10002149	60	101M	=	10001807	-442	CCCAAAGTGCTGGGATTACAGGCGTGAGCCACCGCCCCTGGCCCTTGTTAAATTCTTTGTTCAAAATGCCAAAAACCTGGACACCCTCCACTGGTACTGAA	?<ABAB-?A=B8(99:4AAB at A97B;;85;2)526%==<>7=BADCADCAD at AA@ADCADD=DDD?CBC=D at DDACAAA@A=7CCCBCBBCCBACCCABDC	MD:Z:35A65	PG:Z:BWA	RG:Z:20GAV.8	AM:i:37	NM:i:1	SM:i:37	MQ:i:60	OQ:Z:BBFFDF2CFBF4,555;FFFFFF5F at 5444/0464'AA at A9DGGHHHHHGHFFFFFHHHHHEHHHEHHHEHGHHGHGFGGFD8HHHFHHHHHHHHHHHHHH	UQ:i:4
+20GAVAAXX100126:8:47:1669:10922	99	chr1	10002166	60	101M	=	10002512	444	ACAGGCGTGAGCCACCGCACCTGGCCCTTGTTAAATTCTTTGTTCAAAATGCCAAAAACCTGGACACCCTCCACTGGTACTGAAGCTCACTGAACCTCCTT	CACACC;C:DCBBCAB5BCABDBCBBBD at BBD=DD;@=??DB:D?CD?D?@BBCDDDD9BA?CA<B<>@@B at C<BBC at CABABBA@B>B=>7=<9CDCCAE	MD:Z:101	PG:Z:BWA	RG:Z:20GAV.8	AM:i:37	NM:i:0	SM:i:37	MQ:i:60	OQ:Z:HHHHHHHHBHHHHHHHEHHHHHHHHHHHGHGHEHHBFEDDHHCHFHHEHEFHHHHHHHBHEEHEEFAAFDHFHDFHHEHHFFFFFCFCFD?;@@@HHHHDH	UQ:i:0
+20GAVAAXX100126:8:21:8551:122892	163	chr1	10002192	60	101M	=	10002500	408	CTTGTTAAATTCTTTGTTCAAAATGCCAAAAACCTGGCCACCCTCCACTGGTACTGAAGCTCACTGAACCTCCTTGTTCAGGAGTTTTCATAGAGCTCCAT	@DAA;?ABCC=AD at BB?BCDEEEDBCDCDDCC>CCA4)7B at CCD@DCBDCAAC?B<BDCBCBC at D@?9?=>CCB?ABACBA8D=8)@@=B=?<7>?DC at DC	MD:Z:37A63	PG:Z:BWA	RG:Z:20GAV.8	AM:i:37	NM:i:1	SM:i:37	MQ:i:60	OQ:Z:BCCCCCAAAC=ACCCBCCCCCCCCBCCBBBAA?BBB;,;BBBBBBCBCBCB at BB<7 at BBCBBBBB>@7>:>BAA>A at BBA@9@;2);>B>=>748B?A>BA	UQ:i:8
+20GAVAAXX100126:8:25:5802:132383	99	chr1	10002223	60	101M	=	10002536	413	ACCTGGACACCCTCCACTGGTACTGAAGCTCACTGAACCTCCTTGTTCAGGAGTTTTCATAGAGCTCCATCTCCAGCCCCCTTCCCTCCCAGGAGGTTGGG	CABBCCDACABBDBBCADBCCCADBDDABDBCACBDDABCBBCDBBDBCCCDABDDDBCCCCDCBDBBCCBDBBCCBCBCBDDB=CDBCABCCBC=6??>A	MD:Z:101	PG:Z:BWA	RG:Z:20GAV.8	AM:i:37	NM:i:0	SM:i:37	MQ:i:60	OQ:Z:HHHHHHHHHHHHHHHHHHHHHHHHHHHGHHHHHHHHHHHHHHHHHHHHHHHHGGHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHEHHHHGEHHEH?7ADEG	UQ:i:0
+20GAVAAXX100126:8:21:10727:109276	99	chr1	10002227	60	101M	=	10002534	407	GGACACCCTCCACTGGTACTGAAGCTCACTGAACCTCCTTGTTCAGGAGTTTTCATAGAGCTCCATCTCCAGCCCCCTTCCCTCCCAGGAGGTTGGGGTGG	CCC?CACCDBBCADBCBCADBDDCBDBCADBDDABCBBDDBBDBCACDCADDDBCCCCCCBDBCCCBDBBCCBBBBBDDBBCDBCBBACDCCCDCDDD at DA	MD:Z:101	PG:Z:BWA	RG:Z:20GAV.8	AM:i:37	NM:i:0	SM:i:37	MQ:i:60	OQ:Z:HHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHGHHHGHHHHHHHHGHHHHHHHHHHHHHHHHHHHHHHHHHHGGGHHHHHHHHHHGHG	UQ:i:0
+20GAVAAXX100126:8:28:14388:67948	163	chr1	10002344	60	101M	=	10002661	417	TAATCAAAGTCCTCTAATTTGGTCTTTCTGGTGAGCAGCCCCAACCCTGAGTCACATCATTAGCATAGACTCTGGTGTGTTCTAAAGGGGCTCCTTATGAA	@CCBABCCBBBCDADCDCCCBCBADCCBDCCBAC=AAB<BBCCD?CCCBCAAB at BDCBCCBCCACC@CC at BBEAA@=8=B;@B?CC?23B?CAAD?BC at C@	MD:Z:101	PG:Z:BWA	RG:Z:20GAV.8	AM:i:37	NM:i:0	SM:i:37	MQ:i:60	OQ:Z:BCBBBBBBBABBBBBBBBBBBBA at BBBBBBB@@B at BBB@BBBBBBBB at B@B at AABBBAABABBABABBAAAABA@>>39@:B<?@>:46?@@@@A<@@A;<	UQ:i:0
+20GAVAAXX100126:8:48:18256:122283	83	chr1	10002396	60	101M	=	10002059	-437	CACATCATTAGCATAGACTCTGGTGTGTTCTAAAGGGGCTCCTTATGAATAGCAAAAGACAATCCTATCACTCAGGAAATTCCAAGGAATTTAGGAGCCCT	DDCCDCCDCDCCCCDBCCDCCCACACADDCCDDDBBCBCDCCDCCCBDCCCBBDDDCBBBDCDCCCCDBBCDBDBBDDCDDCBDDBBDCDDCDCBDCACCC	MD:Z:101	PG:Z:BWA	RG:Z:20GAV.8	AM:i:37	NM:i:0	SM:i:37	MQ:i:60	OQ:Z:HHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHH	UQ:i:0
+20GAVAAXX100126:8:61:16672:156327	83	chr1	10002410	60	101M	=	10002072	-438	AGACTCTGGTGTGTTCTAAAGGGGCTCCTTATGAATAGCAAAAGACAATCCTATCACTCAGGAAATTCCAAGGAATTTAGGAGCCCTGTGCCAGAACCAGG	EDCDDCDCACACADDCCDDDBCABCDCCDCCCBDCCDBBDDDDBCBDCDCBCCDBACDBCBBDDCDDCBDDBBDCDDCCBBDBCCCCACBCBDBDCC at CBC	MD:Z:101	PG:Z:BWA	RG:Z:20GAV.8	AM:i:37	NM:i:0	SM:i:37	MQ:i:60	OQ:Z:HHHHHHIHHHHHHHIHHHHHHHIHHHHHHHHHHHHHHHHHHHHHHHHHHHGHHHHIHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHH	UQ:i:0
+20GAVAAXX100126:8:65:9835:166164	83	chr1	10002441	60	101M	=	10002137	-404	TGAATAGCAAAAGACAATCCTATCACTCAGGAAATTCCAAGGAATTTAGGAGCCCTGTGCCAGAACCAGGGAAAAAGACCAAATATATATTTCATTAAACT	EDDCBDCCDDDDBCCD?DCCCCDBBCDBDBBDDCDDCBDDBBDCDDCDBBCBCCCCACBCBCBDBCBCBB@@DDDDBBCBDDCCCCCCCDDDBCDCDBBCC	MD:Z:101	PG:Z:BWA	RG:Z:20GAV.8	AM:i:37	NM:i:0	SM:i:37	MQ:i:60	OQ:Z:HHHHGHHHHHHHHHHHEHHHHHHHHHIHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHGGHHHHHHHHHHHHHHHHHHHHHHHHHHHHH	UQ:i:0
+20GAVAAXX100126:8:23:10396:142336	83	chr1	10002456	60	101M	=	10002141	-415	AATCCTATCACTCAGGAAATTCCAAGGAATTTAGGAGCCCTGTGCCAGAACCAGGGAAAAAGACCAAATATATATTTCATTAAACTTTACTACATGATACA	EDDA?DC>CCCBCDCADDCBAABDDBBDBADCDB>D?>CC at ACBCBDB>BCBCBBA at DDDD?BC at DDCACCCCCDDDBADCDDBCDDCCCCCBCCBC:<BC	MD:Z:101	PG:Z:BWA	RG:Z:20GAV.8	AM:i:37	NM:i:0	SM:i:37	MQ:i:60	OQ:Z:HHHFEHHAHHHFHHHGHHHFDGHHHHHHGGHHHHEHEEHHDHHHHHHHEHGHHHHGGHHHHGHHGHHHGHHHHHHHHHIHHHHHHHHHHHHHHHHHHGEHH	UQ:i:0
+20GAVAAXX100126:8:26:12389:180500	147	chr1	10002456	60	101M	=	10002138	-418	AATCCTATCACTCAGGAAATTCCAAGGAATTTAGGAGCCCTGTGCCAGAACCAGGGAAAAAGACCAAATATATATTTCATTAAACTTTACTACATGATACA	CC=@C at C@BB at A5ADBB>@BB6C@<<>?A?BCC49C?BC?B?CCC6D at D>7BC>C<AC at 6;(8@;A?DCDCDBBEECCBEDACACED>@BBABBBAAA<B@	MD:Z:101	PG:Z:BWA	RG:Z:20GAV.8	AM:i:37	NM:i:0	SM:i:37	MQ:i:60	OQ:Z:A?9<@B at BB@@;3>B at B=<@A9B?:C>??8BB at 4=@>BB>B at BBB1ABA=<AA:A=BB at 8<)9A at A@CCCBCAACCCCACC?ABBCBAAAB=BCABAA9A@	UQ:i:0
+20GAVAAXX100126:8:21:8551:122892	83	chr1	10002500	60	101M	=	10002192	-408	CCAGAACCAGGGAAAAAGACCAAATATATATTTCATTAAACTTTACTACATGATACAAACTACAGTTTGGAAAGACATTTAGGAATGGTAGAACAAAACAA	&?DCDBDCDCC1:?@A at BBCBDDCCCCCACDDDBCDCDDCCDDCCCCBBCCBCCBBDDBBCBBCADDCBBDDDBBBCDDCDBBDCCBACD@AC at ADD9BDC	MD:Z:101	PG:Z:BWA	RG:Z:20GAV.8	AM:i:37	NM:i:0	SM:i:37	MQ:i:60	OQ:Z:2GHHHFHHHHH7<ADDDHIHHHHHHHHHGHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHIHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHGGHGGHHFHHH	UQ:i:0
+20GAVAAXX100126:8:47:1669:10922	147	chr1	10002512	60	2S99M	=	10002166	-444	GCAAAAAGAACAAATATATATTTCATTAAACTTTACTACATGATACAAACTACAGTTTGGAAAGACATTTAGGAATGGTAGAACAAAACAAGTGAGAAAAT	###DD?C8;->D>>@?;=773/65608?DC?9:78CBAB>6=C=ACDAB at 3BBC@B7)/3B>CA?AAA)?DA at CA<A?=DAC?CBBB<BBDABAB@?@AC@	MD:Z:7C91	PG:Z:BWA	RG:Z:20GAV.8	AM:i:37	NM:i:1	SM:i:37	MQ:i:60	OQ:Z:###@@=>56'>A>=>;;<251-236.9?B@@5576BA at B>6;B:>BBBA at 5?B@?@9'/4BCBBBBC>(>B?>B at 9>?<BACCCCCCCCCCBAACCCCCC@	UQ:i:12
+20GAVAAXX100126:8:21:10727:109276	147	chr1	10002534	60	101M	=	10002227	-407	ATTAAACTTTACTACATGATACAAACTACAGTTTGGAAAGACATTTAGGAATGGTAGAACAAAACAAGTGAGAAAATATAATATGTAAAAGGTCTTTTTGT	CD7DCBCBCA@@>5BCB9DAAACBB<B at CE?CD at 9<CBDA at CBC@CE;DC;DCBDD?B=A?B>@=BBBCCECBCCDCDDCDCDDBCBBBDCACBBABCBB@	MD:Z:101	PG:Z:BWA	RG:Z:20GAV.8	AM:i:37	NM:i:0	SM:i:37	MQ:i:60	OQ:Z:C>CBB at BABBACB-CC@CBBABBA at CBBBBBAACC9BBBCBBC@>BCCCBCCBCCBA at CCCBCBCBCCCCCCCBCCBCCCCBCCCCCBCCCCBBCCBBBCB	UQ:i:0
+20GAVAAXX100126:8:25:5802:132383	147	chr1	10002536	60	101M	=	10002223	-413	TAAACTTTACTACATGATACAAACTACAGTTTGGAAAGACATTTAGGAATGGTAGAACAAAACAAGTGAGAAAATATAATATGTAAAAGGTCTTTTTGTCA	BDBD@@D at AA<B>>DB>AB8BBB:ABB;ADBCCB at CC<AA=DDDBDC9DA;BADCB?C at CB@?B?>ACDCBBBDDDDCDDDDBDBBBBCAABDCBA@@AC@	MD:Z:101	PG:Z:BWA	RG:Z:20GAV.8	AM:i:37	NM:i:0	SM:i:37	MQ:i:60	OQ:Z:CB@@CBBBBB=BBCBCCBBCBBBCBABCCBBBBBBBACBCCBBCCCBCCCCCCBCCBCCBBBABCCCCCCCCCCCCCCCCCCCCCCCCCB at BCCCCCCCCB	UQ:i:0
+20GAVAAXX100126:8:46:6526:26315	99	chr1	10002542	60	101M	=	10002857	415	TTACTACATGATACAAACTACAGTTTGGAAAGACATTTAGGAATGGTAGAACAAAACAAGTGAGAAAATATAATATGTAAAAGGTCTTTTTGTCATTTCAA	CDC?DCACCBDCCACDDADCACCBDDBCDDDCDACCDDCCCDDCBCBCCDDACDDB at CAABBDCDDDDCCCCDCCCBCCDDDCCABDDDDAAA@DCDDCEE	MD:Z:101	PG:Z:BWA	RG:Z:20GAV.8	AM:i:37	NM:i:0	SM:i:37	MQ:i:60	OQ:Z:HHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHIHHHHHHHHGGHGGIHHHHHHHHHHHHHHHHHHHHHHHGHHHHHGGEGHHHHHHH	UQ:i:0
+20GAVAAXX100126:8:61:8680:44720	163	chr1	10002550	60	101M	=	10002899	449	TGATACAAACTACAGTTTGGAAAGACATTTAGGAATGGTAGAACAAAACAAGTGAGAAAATATAATATGTAAAAGGTCTTTTTGTCATTTCAAAATACAAG	@AA at 7;B?D@=@;9A at BAACCEECB:CCBCCCC9=B7/8?A09?ADDAAA=B:<BB=AB?ACBB at B@ABB?DDAB<45B?6?3=BCCB;D@<?<?ABB>C=	MD:Z:101	PG:Z:BWA	RG:Z:20GAV.8	AM:i:37	NM:i:0	SM:i:37	MQ:i:60	OQ:Z:@?@@4=A?CA<?@;@>@?@BBCCB at 9BBCBBBA7?B=59CA/:@BBB=B=?A4?>?9;@<ABAB=@B at A@@AA at A<03>>5>/;?B at B;AA9:98@@A<<:	UQ:i:0
+20GAVAAXX100126:8:28:14388:67948	83	chr1	10002661	60	101M	=	10002344	-417	GCATGGTGGCTCACACCTGTAATCCTAGCATTTTGGGAGGCTGAGGCAGGAGGATCCCTTGAGCCCAGGAGTTGGAGACCAGCCTGAACAACATACTGAGA	DDCDCADCCCDCCCBCCCACDCDCCCDABCDDDCBBBDBBCCBCBBBDBBCBBCDCCCDCBCBCCBCBBCADCBBDBACBDBCCCBDBBDCBCCCCC at CBC	MD:Z:101	PG:Z:BWA	RG:Z:20GAV.8	AM:i:37	NM:i:0	SM:i:37	MQ:i:60	OQ:Z:HHHHHHHHHHHHHHFHHHHHHHHHHHHGHHHHHHHHHHHHHHHGHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHFHHHHHHHHHHHHHHHHHHHHHHH	UQ:i:0
+20GAVAAXX100126:8:5:7404:40226	163	chr1	10002668	37	91M10S	=	52476437	42473869	GGCTCACACCTGTAATCCTAGCATTTTGGGAGGCTGAGGCAGGAGGATCCCTTGAGCCCAGGAGTTGGAGACCAGCCTGAACAACATACTGAGACCCCGTC	@CBB?A?BACAA@<>ACDED@>@CCCCCBAC@?BB;6<8?AC=B76A38AAD=6A8/A:@7CC=:D7 at BA7'B38ABBCB>7B@:BC72D###########	MD:Z:91	PG:Z:BWA	RG:Z:20GAV.8	AM:i:37	NM:i:0	SM:i:37	MQ:i:37	OQ:Z:BCBACA at ACC@@A@:@CCCC?=>BBCCB@@B>>BC>:?=ACB>?99=08=BB97;2.=7=8AA=2A9?=?6(>16BBAAA=8=>:>@73@###########	UQ:i:0
+20GAVAAXX100126:8:43:16629:51559	163	chr1	10002681	60	100M1S	=	10002869	288	AATCCTAGCATTTTGGGAGGCTGAGGCAGGAGGATCCCTTGAGCCCAGGAGTTGGAGACCAGCCTGAACAACATACTGAGACCCCGTCTCTACAAAAAATA	@DCA at BBBBCCBBBCCCCCCBDBCCCBCCCBBA=:7;B at B;?;>=C;ACB::@8B?==?C>==@AA8A<=?>@;<?831:>>BA?;@9:B<8>5:9AAA##	MD:Z:100	PG:Z:BWA	RG:Z:20GAV.8	AM:i:37	NM:i:0	SM:i:37	MQ:i:60	OQ:Z:BBBBCBBBBBCCCBCBBBBBBBBABBBBBB at A@:=:@BAB>?<<?B6>B?>6<:?::6 at B?<<?>?:?:9?:;<<@61-9=?=?=?669?:7=145;8?##	UQ:i:0
+20GAVAAXX100126:8:45:10866:114173	99	chr1	10002696	60	101M	=	10003041	434	GGAGGCTGAGGCAGGAGGATCCCTTGAGCCCAGGAGTTGGAGACCAGCCTGAACAACATACTGAGACCCCGTCTCTACAAAAAATAGAAAATTAGTTGGGG	CCCACCDCDCCBCCCDCCDCBBBDDBDCBBBCCCDCADBCDCDABCCBBCBDDACDACCCADBDCDABBB;BBDBDCACDDDAABBADDDDCDCCBDC>E#	MD:Z:100T0	PG:Z:BWA	RG:Z:20GAV.8	AM:i:37	NM:i:1	SM:i:37	MQ:i:60	OQ:Z:HHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHIHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHGGGGGHHHHHHHHGHHCH#	UQ:i:2
+20GAVAAXX100126:8:65:6494:152486	99	chr1	10002718	60	101M	=	10003049	431	CTTGAGCCCAGGAGTTGGAGACCAGCCTGAACAACATACTGAGACCCCGTCTCTACAAAAAATAGAAAATTAGTTGGGTGTGGTGGTCCATGCCTGTAGTC	CDC at DCCCBCCCDCBDBCDCDABCCBBDBDDACDACCCACBDCDABBB;BBDBDCACDDD@@BBADDD at CDCCBDBCCABCBCCBCCBCCCCCCDCCADDD	MD:Z:101	PG:Z:BWA	RG:Z:20GAV.8	AM:i:37	NM:i:0	SM:i:37	MQ:i:60	OQ:Z:HHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHEEGGGHHHDHHHHHHHHHFHHHHHHHHHHHHHHHHHHGHHH	UQ:i:0
+20GAVAAXX100126:8:65:4031:65332	163	chr1	10002722	60	101M	=	10003065	443	AGCCCAGGAGTTGGAGACCAGCCTGAACAACATACTGAGACCCCGTCTCTACAAAAAATAGAAAATTAGTTGGGTGTGGTGGTCCATGCCTGTAGTCCCAG	@C at BABBCCB@CBBCC<AB?CBCDACDACD at CDC9;;BAB?CCC3ACDADA?C:BDDDCC<CC>D at 8CC>BCBA5A?@D>AACABC at B=BAAB at CBCC=?B	MD:Z:101	PG:Z:BWA	RG:Z:20GAV.8	AM:i:37	NM:i:0	SM:i:37	MQ:i:60	OQ:Z:BBAABBABAB?BBBAB8BA<BBBB at BBBBBACCB>=@BBBABBBCBCBCBBCB<?BBBBBCBB>B>;BB7AB at B0B>@B;B@@ABA<BB=?A;B@@B=:7@	UQ:i:0
+20GAVAAXX100126:8:63:2945:69121	163	chr1	10002736	60	95M6S	=	10003053	412	AGACCAGCCTGAACAACATACTGAGACCCCGTCTCTACAAAAAATAGAAAATTAGTTGGGTGTGGTGGTCCATGCCTGTAGTCCCAGCTACTCCAGAGGCT	@CC at ABBBBDBCC@CDACCCACBCCCACCC;BBDACA>BBCCBDACCCCC at CC@CCCCAC>AAAA??A?8AC@?@?98C;@<A:BA?A<A><AA#######	MD:Z:95	PG:Z:BWA	RG:Z:20GAV.8	AM:i:37	NM:i:0	SM:i:37	MQ:i:60	OQ:Z:BBBBBBBBBBBBBBBBBBBBBABBBBBBBBBABBBBBCBBBBABBBB at BAAB@BB at AB@B>@?A?8B at 64AA=@@>76><?6>7?<:@;?@8?@#######	UQ:i:0
+20GAVAAXX100126:8:27:6582:134282	163	chr1	10002742	60	94M7S	=	10003068	426	GCCTGAACAACATACTGAGACCCCGTCTCTACAAAAAATAGAAAATTAGTTGGGTGTGGTGGTCCATGCCTGTAGTCCCAGCTACTCCAGAGGCTGAGGGG	@BCCABB at CCACCAADBCCCBCCC;ABDCECACDCCBBBB@@CCB?CCCCABD at CCBCCBA;8>B=<B at C@BB?A>AAC@=A???>=B?A64B########	MD:Z:94	PG:Z:BWA	RG:Z:20GAV.8	AM:i:37	NM:i:0	SM:i:37	MQ:i:60	OQ:Z:BBCCBBCBBBBBCBBBBBBACBBBCBBBCCBBBBBBBBBBC at BAB?BBB>BBBA?B at AA?B</?@9?A>A??=@@8A at A?<A8??67B?<41@########	UQ:i:0
+20GAVAAXX100126:8:25:10200:154913	99	chr1	10002841	60	101M	=	10003177	436	TGAGGGGATAGCTTAAGCCAGGAAGTTGAGGCTGCAGTGAGCCAAGATTGTGCCAGTGCACTCCAGACTGGACAACAGAGCAAGACCCTGTCTCAGGGGGC	CBCACCCDCCCBDDCDCBBCCCDDCBD at DCCBCB@CCBBDCBBCDADCDBBBBBCCCBBCADBCCCDADB at CACDA@CDCBCDBDACCBCCCDCDCCACE@	MD:Z:101	PG:Z:BWA	RG:Z:20GAV.8	AM:i:37	NM:i:0	SM:i:37	MQ:i:60	OQ:Z:HHHHHHHHHHHHHHHHHHHHHHHHHHHFHHHHHHGHHHHHHHHHHGHHHHGHHHHHHHHHHHHHHHHHHHFGHHHHDHHHHHHIHHHHFHIHHHHHIGIHD	UQ:i:0
+20GAVAAXX100126:8:46:6526:26315	147	chr1	10002857	60	101M	=	10002542	-415	GCCAGGAAGTTGAGGCTGCAGTGAGCCAAGATTGTGCCAGTGCACTCCAGACTGGACAACAGAGCAAGACCCTGTCTCAAGGGGCTGGCCACGCATGGTGA	?D<:B>B;>6>A=@AB=@B>>>AA<==:<A>BB@=BC>@>>BB:<B??CA;C at C@>@C at BBA@AAAC??CBCC at CBCBC@CCCACCCA at BA;BBBBA at BB@	MD:Z:79G21	PG:Z:BWA	RG:Z:20GAV.8	AM:i:37	NM:i:1	SM:i:37	MQ:i:60	OQ:Z:>?:1=<=7<3=><>==:?@<?=??==<:6=??=A?AA?=??AA49=<A?A=B?B==BA at BABABBAB>;BABBABAABA=BBBABBBBABABBBABBBBBB	UQ:i:31
+20GAVAAXX100126:8:43:16629:51559	83	chr1	10002869	60	101M	=	10002681	-288	AGGCTGCAGTGAGCCAAGATTGTGCCAGTGCACTCCAGACTGGACAACAGAGCAAGACCCTGTCTCAGGGGGCTGGCCACGCATGGTGACACATCCCTGTA	:DCDDCCDACCDCCCDDBCDCACBCBDACBB at CDCBDBCCCBBCBDBBDBCBBDCBBCCCCADCDBCBBBBBCCBBCBB;BBCCBACBCBCBCDCCCA at CC	MD:Z:101	PG:Z:BWA	RG:Z:20GAV.8	AM:i:37	NM:i:0	SM:i:37	MQ:i:60	OQ:Z:;HHHHHHHHHHHHHHHHHHHGHHHHHHHHHHEHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHH	UQ:i:0
+20GAVAAXX100126:8:63:6936:45669	611	chr1	10002875	29	35M66S	=	10003208	424	CAGTGAGCCAAGATTGTGCCAGTGCACTCCAGACTGGACAACAGAGCAAGACCCTGTCTCAGGGGGCTGGCCAAGCATGGTCACACATCCCTGTAGTCTGT	#####################################################################################################	MD:Z:35	PG:Z:BWA	RG:Z:20GAV.8	AM:i:0	NM:i:0	SM:i:0	MQ:i:37	OQ:Z:#####################################################################################################	UQ:i:0
+20GAVAAXX100126:8:61:8680:44720	83	chr1	10002899	60	101M	=	10002550	-449	CACTCCAGACTGGACAACAGAGCAAGACCCTGTCTCAGGGGGCTGGCCACGCATGGTGACACATGCCTGTAGTCTGAGGAGCTCAAGGTTGCAACAGTGAG	646:<?<:<?=>>:CD9A=>@B=DDBA=CCC<ACDB<@;8>A?C>B<:98;B:CBABBBBBB?CBCCC?ACADACBDBBDBACBADBADCBBDCCDAABDC	MD:Z:64C36	PG:Z:BWA	RG:Z:20GAV.8	AM:i:37	NM:i:1	SM:i:37	MQ:i:60	OQ:Z:47;<@A?@@A>EECHHCF?DDHAHHHGEHHHEEHHHBFB9DGCGEG?BBFBHBHHHGHHHHHCHHHHHGGGHHGHHHHHHHGGHGHHHHHHHHHHHHHHHH	UQ:i:33
+20GAVAAXX100126:8:28:18332:173597	163	chr1	10002902	60	97M4S	=	10003158	356	TCCAGACTGGACAACAGAGCAAGACCCTGTCTCAGGGGGCTGGCCACGCATGGTGACACATGCCTGTAGTCTGAGGAGCTCAAGGTTGCAACAGTGAGCCA	@BCBAB at CBCCACBACCCCBCDBBACDDCBBDBC@B?@BABA?B=C>:AC:?B6BC=B:A?@=@BA;=?><D@:8=29<797B>A at BA875:BACA#####	MD:Z:61C35	PG:Z:BWA	RG:Z:20GAV.8	AM:i:37	NM:i:1	SM:i:37	MQ:i:60	OQ:Z:BBCBBBBBBBBBBBBBBBBBBBA at BBCBBBBBBAABAABBAA@A?B=?AA>??3??=>:?@?=@??;=:7>?=:5=17:494>=?6>?:13:?@=?#####	UQ:i:31
+20GAVAAXX100126:8:62:6496:91010	99	chr1	10002902	60	101M	=	10003193	391	TCCAGACTGGACAACAGAGCAAGACCCTGTCTCAGGGGGCTGGCCACGCATGGTGACACATCCCTGTAGTCTGAGGAGCTCAAGGTTGCAACAGTGAGCCA	CBBACDADBCDACDACCDCBCDCDABBDBBBCBCCCCCC at DBCBBCA;BCCBCBBDACACCBBCDBBCCCBCBDCCDCBDBCDCC>DCCCB at BABCDD@D>	MD:Z:101	PG:Z:BWA	RG:Z:20GAV.8	AM:i:37	NM:i:0	SM:i:37	MQ:i:60	OQ:Z:HHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHFHHHHHHHHHHHHHGHHHHHHHHHHHHHHHHHGHHHHHHHHHHHHHAHHHHFGGFFHHHDHB	UQ:i:0
+20GAVAAXX100126:8:45:20504:142467	163	chr1	10003007	60	90M11S	=	10003337	430	CGCACCATTCCACTTCATCCTGGGCAACAGAGCAAAACCCTATCTCTATGAAAAAAAAAAAAAAGCAAGAGGCTATCTTCTCTGAGGTTTACTATAGTTAA	@;BB>AACABCCACCBDCCDDBDCCCDBCCCCBCCCB at A?C?CCBCDCACACD at DDDDDDBDCB=A at B;/<6688.5B?4:<?60B?=@############	MD:Z:90	PG:Z:BWA	RG:Z:20GAV.8	AM:i:37	NM:i:0	SM:i:37	MQ:i:60	OQ:Z:BCCCCCCBCCCCCBBBCBCCBBCBCBBCBBBBBBBBBBBCB at BBBCBBCCBBBAABBBBBBBAB:@B at 5,=4459,4@;37<82.=<9@############	UQ:i:0
+20GAVAAXX100126:8:48:5253:110179	675	chr1	10003025	60	38M63S	=	10003197	242	CCTGGGCAACAGAGCAAAACCCTATCTCTATGAAAAAAAAAAAAAAGAAATTGGCTATCTTCTCTAAGGTTTACTTTGGTTAACTTTTACAAGAATTTAAT	><AABBAA??<A36CC??:@>>8:?@B>C5BA1>A<;################################################################	MD:Z:38	PG:Z:BWA	RG:Z:20GAV.8	AM:i:37	NM:i:0	SM:i:37	MQ:i:60	OQ:Z:=7 at BABA@;@;@28CB;:6A;:39>@@<@5A@/;A>?################################################################	UQ:i:0
+20GAVAAXX100126:8:45:10866:114173	147	chr1	10003041	60	11S90M	=	10002696	-434	GCAACAGAGCAAAACCCTATCTCTATGAAAAAAAAAAAAAAGCAAGAGGCTATCTTCTCTGAGGTTTACTATAGTTAACTTTTACAAGTATTTAATCATAA	############?8.D=4.,9388?<3<CBBBDB>CCACCB at BCCBC@BB=B at BCBACBBBAA@BCB<BCBADADACBCDDEA?ACD at BCCCBBBAABBC@	MD:Z:90	PG:Z:BWA	RG:Z:20GAV.8	AM:i:37	NM:i:0	SM:i:37	MQ:i:60	OQ:Z:############?1/A;2++7139?:1<@?A at A@@@A at AAA@A at AA@A?A@@?@@@BABABABBBBB6ABA at BBBABABBBCA9ABBBBBBBBBBABBBBB	UQ:i:0
+20GAVAAXX100126:8:65:6494:152486	147	chr1	10003049	60	101M	=	10002718	-431	TCTCTATGAAAAAAAAAAAAAAGCAAGAGGCTATCTTCTCTGAGGTTTACTATAGTTAACTTTTACAAGTATTTAATCATAATTGCTTAGATTGAATTCGG	6B=74698BC?DACDDCBDBBCC at BCABCBABBC@ACBCCABDCADB at CCADCDACAC@CCBBB>ABDACCDDCCCCCDCCDDCBCDADCCCCBBBBB:C@	MD:Z:101	PG:Z:BWA	RG:Z:20GAV.8	AM:i:37	NM:i:0	SM:i:37	MQ:i:60	OQ:Z:2;901225?A>@AAAAA at A@@AB at AABBBABA@BB>ABABABBABB?B at BBBBBAABB@BBBBBABBBBBBBBBBBBCCBCCBBBBBBBCBBBBBBBBBBB	UQ:i:0
+20GAVAAXX100126:8:45:5977:75469	163	chr1	10003052	60	71M30S	=	10003336	384	CTATGAAAAAAAAAAAAAAGCAAGAGGCTATCTTCTCTGAGGTTTACTATAGTTAACTTTTACAAGTATTTAATCATAATTGCTTAGATTGAATTCGGTTC	@DBBABCCCCCDCBDDDA=.7@@4)@@397:6?:241'-%366C6/0?-:37A6>=3 at BC303<=45';B###############################	MD:Z:71	PG:Z:BWA	RG:Z:20GAV.8	AM:i:37	NM:i:0	SM:i:37	MQ:i:60	OQ:Z:BBBBBBBBBBBBBBBBB?9,6==1*?>13683=9224'-%4:5A90.:-55688;729 at A402;902'7@###############################	UQ:i:0
+20GAVAAXX100126:8:63:2945:69121	83	chr1	10003053	60	5S96M	=	10002736	-412	TTCTCTATGAAAAAAAAAAAAAAGCAAGAGGCTATCTTCTCTGAGGTTTACTATAGTTAACTTTTACAAGTATTTAATCATAATTGCTTAGATTGAATTCG	######@A;AA at A?AA at DDDDDDBBDDBDBBCCCDCDDCDCCBDBADDCBCCCCCADCDBCDDDCBBDCACCDDCDCDBCCDCDCBCDCDBCDCBDCBC;C	MD:Z:96	PG:Z:BWA	RG:Z:20GAV.8	AM:i:37	NM:i:0	SM:i:37	MQ:i:60	OQ:Z:######DD at GGGGEGGGHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHH	UQ:i:0
+20GAVAAXX100126:8:65:4031:65332	83	chr1	10003065	60	101M	=	10002722	-443	AAAAAAGCAAGAGGCTATCTTCTCTGAGGTTTACTATAGTTAACTTTTACAAGTATTTAATCATAATTGCTTAGATTGAATTCGGTTCAGTATATATTCCT	EEDDAD=?=A>DCBCCCDCDDCDCCAD at A?DCCCCCC6ADCACADDDCBB?CACCDDCDCDBCCDCDCBCDADBCDCBDCDD;BADDBBACCCCCCDBCCC	MD:Z:101	PG:Z:BWA	RG:Z:20GAV.8	AM:i:37	NM:i:0	SM:i:37	MQ:i:60	OQ:Z:HHHHGHAD at DAHHHHHHHHHHHHHHGHFHEHHHHHHH7HHHFHGHHHHHHEHHHHHHHHHHHHHHHHHHHHGHHHHHHHHHHHHHHHHIHHHHHHHHHHHH	UQ:i:0
+20GAVAAXX100126:8:27:6582:134282	83	chr1	10003068	60	101M	=	10002742	-426	AAAGCAAGAGGCTATCTTCTCTGAGGTTTACTATAGTTAACTTTTACAAGTATTTAATCATAATTGCTTAGATTGAATTCGGTTCAGTATATATTCCTGGA	EDDCCDDCACCCCCDCDCCDCCBDBAD at CBCCCCDADCDCCDDDCBBDDACCDDCDCDBCCDCDCBCDCCBCDCBDCDD;BADDBDACCCCCCDDCCABBC	MD:Z:101	PG:Z:BWA	RG:Z:20GAV.8	AM:i:37	NM:i:0	SM:i:37	MQ:i:60	OQ:Z:HIHHHHHHEHHHHHHHHIHHHHHHHHHDHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHH	UQ:i:0
+20GAVAAXX100126:8:26:6455:142223	163	chr1	10003070	60	101M	=	10003403	433	AGCAAGAGGCTATCTTCTCTGAGGTTTACTATAGTTAACTTTTACAAGTATTTAATCATAATTGCTTAGATTGAATTCGGTTCAGTATATATTCCTGGAAG	@CBBBABBCBDCCADCCDCDBBCCBCCCADCCBC>BAB;CBBBC?CDC at B?CC at DCBDBABCCABD@CCB at CCABBB@;B at BCBBAB>>C;BC?CBBCBDB	MD:Z:101	PG:Z:BWA	RG:Z:20GAV.8	AM:i:37	NM:i:0	SM:i:37	MQ:i:60	OQ:Z:BCBBBBBBBBBBBBBBCBCBA at BB@BCBBBBBAC at BBB@BBAABBBBB?AABBBAABBA at ABBAABABB@@@A@@B@@BA>@BAA9@<?@<A@>A?@@@>@	UQ:i:0
+20GAVAAXX100126:8:68:8704:167789	99	chr1	10003123	60	101M	=	10003414	361	AATCATAATTGCTTAGATTGAATTCGGTTCAGTATATATTCCTGGAAGTTCACTATTATTATTATTACTAGGTCCTGAGAATATGAAACAACCATAAAAAT	CDB at CCCDCABBDDCCDCDBDDCDB;CBDBCCAC>CC>CDBBC9CDDC at DBCADCCDCCDCCDCCDCADCACCBBDBBCDDCCCBDADACDACDCDE=E@;	MD:Z:101	PG:Z:BWA	RG:Z:20GAV.8	AM:i:37	NM:i:0	SM:i:37	MQ:i:60	OQ:Z:HHHHHHHHHGHHHHHHHHHHHHHHHHHHHHHHGHEHHEHHHHH at HHHHEHHHHHHHHHHHHHHHHHHHHHGHHHHHHGHHHHHHHHGHHHHHHHHHHBHG>	UQ:i:0
+20GAVAAXX100126:8:28:18332:173597	83	chr1	10003158	60	101M	=	10002902	-356	ATATTCCTGGAAGTTCACTATTATTATTATTACTAGGTCCTGAGAATATGAAACAACCATAAAAATGAGTGATGAATTCAATATATATTATTCTGACACTG	BDCEBDCBCCDD?DDBCACCDCCDCCDCCDCCCCDBADCCCBDBDCCCCBDDBBDBC at BCDDDDCCBCACBCCBDCDDBDCCCCCCCDCCDDCCBCC:BCC	MD:Z:101	PG:Z:BWA	RG:Z:20GAV.8	AM:i:37	NM:i:0	SM:i:37	MQ:i:60	OQ:Z:FHHHEHHGHHHHGHHHHGHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHGGHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHGHHH	UQ:i:0
+20GAVAAXX100126:8:25:10200:154913	147	chr1	10003177	60	101M	=	10002841	-436	ATTATTATTATTACTAGGTCCTGAGAATATGAAACAACCATAAAAATGAGTGATGAATTCAATATATATTATTCTGACACTGAGAAGTATTGTAACAAAAA	<C<=C at BAAB?B<>=>455>8=@B at B@5>=8AD>?DBABB at CCDCCC?D@>BBCBCAC>AABAB>BBCDCCCCCCBBBBCCBDBCDAACDCABBBAABAC@	MD:Z:101	PG:Z:BWA	RG:Z:20GAV.8	AM:i:37	NM:i:0	SM:i:37	MQ:i:60	OQ:Z:9<<6>????A>@:<97340>6<=@@@?6:69?A<BA at AAAABBBBAAABA@AAAABBA>AABBBABBBBBBABBBB at B@CBBBBBBBBBBBBBBABBBCBB	UQ:i:0
+20GAVAAXX100126:8:62:6496:91010	147	chr1	10003193	60	101M	=	10002902	-391	GGTCCTGAGAATATGAAACAACCATAAAAATGAGTGATGAATTCAATATATATTATTCTGACACTGAGAAGTATTGTAACAAAAAACAAGTTTCTAGGTCA	CA=2CAAB at B>>;;>AA5BB>BBAACBACDABEA at BCBBCBCCCCDCACCADCCDDACCB@A?BAACBCDACCDBBCCABCCCBBACBDACCCBBB@@CB@	MD:Z:101	PG:Z:BWA	RG:Z:20GAV.8	AM:i:37	NM:i:0	SM:i:37	MQ:i:60	OQ:Z:B=81??>?>@>;<9:<?,?@<A at ABA@B at BABBBBABBBBBABBBBBBBBBBBBBBBBBBABABBBBBBBBBBBACBBBBBBCCCACBCCBBBBBBCCBBB	UQ:i:0
+20GAVAAXX100126:8:48:5253:110179	595	chr1	10003197	60	30S71M	=	10003025	-242	GAAGTTCACTATTATTATTATTACTAGGTCCTGAGAATATGAAACAACCATAAAAATGAGTGAGGAATTCAATATATATTATTCTGACCCTGAGAAGTATT	###############################B at B=?<2,-+2;=;@<72+1+<.2;0589557&99;;;=<-(=;<-<2)=>884:>9'>>351>;77?9<	MD:Z:33T24A12	PG:Z:BWA	RG:Z:20GAV.8	AM:i:37	NM:i:2	SM:i:37	MQ:i:60	OQ:Z:###############################FFFAA43.-,64<>D551-1.421=09:>7::)@:55444/+444/43+4>::3B>=+<?8804@:FC?F	UQ:i:11
+20GAVAAXX100126:8:26:15631:70339	163	chr1	10003203	60	101M	=	10003538	435	ATATGAAACAACCATAAAAATGAGTGATGAATTCAATATATATTATTCTGACACTGAGAAGTATTGTAACAAAAAACAAGTTTCTAGGTCATACCAAAAGC	@CBBA?CC@?CABBCCDDDDCBBABBCACCBCCBBCABBBCACCAACCACAAC?EBCCCCB>@ACA>=A=ACB?AC at BBB>BB at CCCA<CAAB?CAA>=CB	MD:Z:101	PG:Z:BWA	RG:Z:20GAV.8	AM:i:37	NM:i:0	SM:i:37	MQ:i:60	OQ:Z:BBBBBCBBA;BBBBBBBBBBBB@@ABA?BB at BBBBBBBBBBABBB@BB at BBBABBABAAAB<@AA@@><>A????ABA?B;@?@@A@?<BA at A?>?;6:=A	UQ:i:0
+20GAVAAXX100126:8:63:6936:45669	659	chr1	10003208	37	9S92M	=	10002875	-424	GAGAATATGAAACAACCATAAAAATGAGTGATGAATTCAATATATCTTATTCTGACACTGAGAAGTATTGTAACAAAAAACAAGTTTCTAGGTCATACCAA	##########B at 19<?:=>:97;=>;C?@43?;B at 9(0<>5>BD8(28C=3B97C>?C,5B?>?08;3@*>A@;?CBCA@?-C'9<CA5;,'AA?5A49<@	MD:Z:36A55	PG:Z:BWA	RG:Z:20GAV.8	AM:i:0	NM:i:1	SM:i:37	MQ:i:29	OQ:Z:##########A9073<8<:9977=>:BA;.3<7 at B5'.:>7<AB5'-<A=2 at 83@>AA+6AA@@6<>1>+>?85=C at B>:=-@)6:AC86-)=A>5 at 589@	UQ:i:7
+20GAVAAXX100126:8:68:17460:23672	99	chr1	10003272	60	101M	=	10003550	378	CAAAAAACAAGTTTCTAGGTCATACCAAAAGCCGGGCAAAGTGGCAGATTCCTGTAATCCCAGCTACTCAGGAGGCTGAGGGGGGAGGATTGCTTGAACCC	CCD:@DDA at A@BD>BDCCCCBCCC?BCDDDAB=;C@?B@@=;===?A;BABB at ABC?:=BBCCADCAD@>C>DCC=@?@ACCC>>???>?DACAD<=:>?=	MD:Z:101	PG:Z:BWA	RG:Z:20GAV.8	AM:i:37	NM:i:0	SM:i:37	MQ:i:60	OQ:Z:HHHGGHHHCCCGHDHHHHHHHHHHGHHHHHGHDHHCCGCGD at DDDDG=GGHHEGHHE=EHHHHGHHHHGCHDHHH?DDDFHHHCCCCCCCHGHDH<?<DD=	UQ:i:0
+20GAVAAXX100126:8:68:4068:49998	585	chr1	10003316	0	35M66S	=	10003316	0	CAGATTCCTGTAATCCCAGCTACTCAGGAGGCTGAGGCAGGAGAATCGCTTGAACCCAGGAGGCAGAGGGTGCAGTGAGCCTAGATTGCGCCATTGCACTC	#####################################################################################################	MD:Z:35	PG:Z:BWA	RG:Z:20GAV.8	AM:i:0	NM:i:0	SM:i:0	OQ:Z:#####################################################################################################	UQ:i:0
+20GAVAAXX100126:8:68:4068:49998	645	chr1	10003316	0	*	=	10003316	0	TGCAAAAGCGCAAACTCGGCTCTTTGCAACCTACGCTTGCTGGGTTCAGGGAATTATTCGGCTTAAGCCCTCTGAGTAGTTGAGGCTACAGGCACCTTACA	;7(A#################################################################################################	PG:Z:BWA	RG:Z:20GAV.8	OQ:Z:70*@#################################################################################################
+20GAVAAXX100126:8:45:5977:75469	83	chr1	10003336	60	101M	=	10003052	-384	TACTCAGGAGGCTGAGGGGGGAGGATTGCTTGAACCCGGGAGGCAGAGGTTGCAGTGAGCAGAGATAGCGCCATGCCATTGCACTCCAGCCTGGGCAACAA	>ADDCDCCDCCCB at CBAACCBD@BCDCBCDCBDACC;CBBDBBBDBDBADCBBDACBCBBDBDBCCCB;>CBCCBCBCDCBBBCDCBDBCCCBCCCDABDC	MD:Z:101	PG:Z:BWA	RG:Z:20GAV.8	AM:i:37	NM:i:0	SM:i:37	MQ:i:60	OQ:Z:BGHHHHHHHHHHGGGGGGHHHHFHHHHHHHHHHGHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHEHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHH	UQ:i:0
+20GAVAAXX100126:8:45:20504:142467	83	chr1	10003337	60	101M	=	10003007	-430	ACTCAGGAGGCTGAGGGGGGAGGATTGCTTGAACCCGGGAGGCAGAGGTTGCAGTGAGCAGAGATAGCGCCATGCCATTGCACTCCAGCCTGGGCAACAAG	DDD at DCCDCCCB@CABACC at DCBCDCBCDCBD@CC;CCBDBBBDBDBADCBBCACBCBBCBCBCCCB;BCBCCBCBCDCBB at CDCBDBCCCBBCCDC@CDC	MD:Z:101	PG:Z:BWA	RG:Z:20GAV.8	AM:i:37	NM:i:0	SM:i:37	MQ:i:60	OQ:Z:HHHDHHHHHHHGGGGGGHHGHHHHHHHHHHHHEHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHFHHHHHHHHHHHHHHHHHHH	UQ:i:0
+20GAVAAXX100126:8:26:6455:142223	83	chr1	10003403	60	101M	=	10003070	-433	GCGCCATGCCATTGCACTCCAGCCTGGGCAACAAGAGTGAAACTCCATCTCAAAAAAAAAAAAATCCTTTCATGAAATTACTACCAGATGTTGGCCCTTCA	>6=@>=<??<@9:8::?<A;BBCCCB@>;A@>AB at BACBDDC>BCBCDC@?AAAAA at ADDDDDCDCCDDDACCBDDCDCBCCBCBDBCCADCBCCCCBCBC	MD:Z:101	PG:Z:BWA	RG:Z:20GAV.8	AM:i:37	NM:i:0	SM:i:37	MQ:i:60	OQ:Z:BAADA?BDDBD55444DBFBFHHIHHFDBFDEFFFFHHHHHHEFHHHHHDCGGGGGGGHHHHHHHHHHHHIHHHHHHHHHHHHHHHHHHHHHHHHHHHHHH	UQ:i:0
+20GAVAAXX100126:8:68:8704:167789	147	chr1	10003414	60	30S71M	=	10003123	-361	GTTGCAGTGAGCAGAGATAGCGCCATGCCATTGCACTCCAGCCTGGGCAACAAGAGTGAAACTCCATCTCAAAAAAAAAAAAATCCTTTCATGAAATTACT	###############################B@<347:@::>>A at CC=B>7A@@C>9A;<:;7>;28>>>CCCCCCCCCCCCBCCCDBCBCCBBBBBBAC@	MD:Z:71	PG:Z:BWA	RG:Z:20GAV.8	AM:i:37	NM:i:0	SM:i:37	MQ:i:60	OQ:Z:###############################?=;002<?7<=<;>AB@?=:=?>?@<@<=<>:@@39<<<ABBBCBBBBBBBABBBBBBCCBCBBBABACB	UQ:i:0
+20GAVAAXX100126:8:2:19645:190338	163	chr1	10003434	60	82M19S	=	10003700	366	CAAGAGTGAAACTCCATCTCAAAAAAAAAAAAATCCTTTCATGAAATTACTACCAGATGTTGGCCCTTCAGCACAACCAGCTTGGGAGCTTCATCCTTAGC	?A?A??@BADDADADDBCCCCAEEEED at CEEDB59=0145<6:DBCCA1:>5?;:B71?A8>:07B49;9-6.5?A9B@;A####################	MD:Z:82	PG:Z:BWA	RG:Z:20GAV.8	AM:i:37	NM:i:0	SM:i:37	MQ:i:60	OQ:Z:???AC@:BCCCBCCCC at CACB?CCCCB=ACCC at 4<?0478>8<BBAA>08 at 7>=4 at 4-==9=;14 at 3875,2+7>?;A<:A####################	UQ:i:0
+20GAVAAXX100126:8:45:3960:5771	163	chr1	10003525	60	101M	=	10003872	447	CATCCTTAGCAAAGAAAGATCTTCAAAGCAGGCACTTCCATGATCCACATACTTTGGATGCCCTTAAAGGGGGGGAAAAAGGGAGAGGAAGGGAGGAGAGG	@CBA at BBBBBCDCABEECCCBECBDEECBACCCD@CAAA?CBCC?CCACDAADADCCDCBACCCCB?DCCADDAB>@BB=BBCBB0CB at DABC@AACC?DB	MD:Z:101	PG:Z:BWA	RG:Z:20GAV.8	AM:i:37	NM:i:0	SM:i:37	MQ:i:60	OQ:Z:BCCBCBBBBCBCBBCCCBBBBCCBCCCBA?BBCCBBBBBCBBBBABBBBBBBBBBBBABCBBBBBA at BBBABBBB;?A?<BA@@A,A@?@AAA><@?@;@@	UQ:i:0
+20GAVAAXX100126:8:26:5030:62604	99	chr1	10003529	60	101M	=	10003851	422	CTTAGCAAAGAAAGATCTTCAAAGCAGGCACTTCCATGATCCACATACTTTGGATGCCCTTAAAGGGGGGGAAAAAGGGAGAGGAAGGGAGGAGAGGAAGA	CDCACCCDDCDDAADCBDDBCDDCBCCCBCACDBBCCBDCBBCACCCACDDBCDCBBBBDDBDDCCCCC>B>DDDDCCCDCBCCDDCCCDCCCCCCDDED5	MD:Z:101	PG:Z:BWA	RG:Z:20GAV.8	AM:i:37	NM:i:0	SM:i:37	MQ:i:60	OQ:Z:HHHHHHHHHHHHGGHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHGHHHHHHHEGCHHHHHHHHHEHHHHHHHIHHGHFHHIHH4	UQ:i:0
+20GAVAAXX100126:8:26:15631:70339	83	chr1	10003538	60	101M	=	10003203	-435	GAAAGATCTTCAAAGCAGGCACTTCCATGATCCACATACTTTGGATGCCCTTAAAGGGGGGAAAAAAGGGAGAGGAAGGGAGGAGAGGAAGAGGAGGAGAA	DEDDCCDCD?CDDDABDCBBCCDDCBCCBCDCACBCCBCADCBBCCBCC at DCDDCBBBBBBDDDDDCBBBDBDBBDDBBBDBBDBDBBDDBDBBDCBBBDC	MD:Z:61G39	PG:Z:BWA	RG:Z:20GAV.8	AM:i:37	NM:i:1	SM:i:37	MQ:i:60	OQ:Z:HHHHHHHHHCHHIHGHHHHHHHHHHHHHHHHHIHHHHGHFHHHHHHHHHFHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHH	UQ:i:35
+20GAVAAXX100126:8:68:17460:23672	147	chr1	10003550	60	101M	=	10003272	-378	AAGCAGGCACTTCCATGATCCACATACTTTGGATGCCCTTAAAGGGGGGGAAAAAGGGAGAGGAAGGGAGGAGAGGAAGAGGAGGAGAAATAGCATTTCAA	CE at CBA?1B>)8.>1%94=096A;>->88CAA=:4=.?7A0CAC<>B78=A=CCDC8C7?==?:?@9<DC@;BDC at BB?AABDBB>@BCC<ABAB:BB?@@	MD:Z:101	PG:Z:BWA	RG:Z:20GAV.8	AM:i:37	NM:i:0	SM:i:37	MQ:i:60	OQ:Z:@@@B<>;.=<'23<-%616384?;?'=74?B?997<0?3 at 2A>B99>94>B9BBBB;B6@>@A=AA;;BB at 8ABB?@?>>?BB at B;?BBB>>ACB:BA?<B	UQ:i:0
+20GAVAAXX100126:8:47:13004:90024	99	chr1	10003567	60	101M	=	10003910	383	ATCCACATACTTTGGATGCCCTTAAAGGGGGGGAAAAAGGGAGAGGAAGGGAGGAGAGGAAGAGGAGGAGAAATAGCATTTCAATTCTGCTTTAATATATA	>982;8A>=?DDD==?CBBBADDCDA>=>A@=;;@?A@=;8<13=,<;<78)=7<=2=72A>B@>B;>*</:9:8:(:9:7@<@???,;=699&:7B?@?4	MD:Z:101	PG:Z:BWA	RG:Z:20GAV.8	AM:i:37	NM:i:0	SM:i:37	MQ:i:60	OQ:Z:><@==@CDACHHHDDDHHHHGHHHHCADAGCD>4CEFCE?44234245554+44441443FAFFCF=C,?254444-5559F?DDCC.?A654'5:GCGE4	UQ:i:0
+20GAVAAXX100126:8:25:18450:91287	163	chr1	10003652	60	101M	=	10003979	427	TCTGCTTTAATATATATATATTTTTTGAGACAGAGTCTCACTCTGTCATCCAGGCTGGAGTGCAGTGGTGCAATCTCCGCTCACTGCAACCTCCACCTCCC	@CCA?A at ABCCCCACCCCCCDCCCCCBCCC@CACB>@C?B at DBD@BCCCAACB=BDBCBA<B@<AB=A at B?CB@>@=A9AA<=>ABBB>=@BAAB>BA?AB	MD:Z:101	PG:Z:BWA	RG:Z:20GAV.8	AM:i:37	NM:i:0	SM:i:37	MQ:i:60	OQ:Z:BCBBCCCCBBBBBBBBBBBBCCCBBBAABBAB at BB?BBABBBBBBABBB at BB??AAAA?@;A?<@>@@9A@?>@>>>@>B?<6?>@@@>:???@>>>9>:@	UQ:i:0
+20GAVAAXX100126:8:44:17629:79062	1187	chr1	10003678	60	99M2S	=	10004001	423	GAGACAGAGTCTCACTCTGTCATCCAGGCTGGAGTGCAGTGGTGCAATCTCCGCTCACTGCAACCTCCACCTCCCGGGTTTAAGCGATTCTCCTGCCTCAG	=B:6:=::9ABD61?D<D??@BA>DDCCCD97@@>374=48?AA@<;@BD8B46CB5>C<<C<8BD98;1::A7(#2&9?8'@8%2B@:=@ABB59CD###	MD:Z:84T14	PG:Z:BWA	RG:Z:20GAV.8	AM:i:37	NM:i:1	SM:i:37	MQ:i:60	OQ:Z:<?949=474BCB80 at B:B=C@@@=CCBBBB68>?@2=6 at 5;@B at B;6=BA;A4:@A1;A:CA9;@B>85/:2?7*'5)4>8':4&3=?:8BABA07B@###	UQ:i:4
+20GAVAAXX100126:8:2:19645:190338	83	chr1	10003700	60	101M	=	10003434	-366	TCCAGGCTGGAGTGCAGTGGTGCAATCTCCGCTCACTGCAACCTCCACCTCCCGGGTTTAAGTGATTCTCCTGCCTCAGCCTCCCTAGTAGCTGGGATTAC	5ECACCC?;CD?BBCD=A><A495:=;9547;:<;;3:<;+7=<83=CCACC;BBADDCD@;@<=?<<>=:?9==<BDACCD at CCCDACDBCCCCBCBC;C	MD:Z:101	PG:Z:BWA	RG:Z:20GAV.8	AM:i:37	NM:i:0	SM:i:37	MQ:i:60	OQ:Z:5HHEHHHC=HHGGHHHDDDAD;<;<=44444444551555)44442<HHEHHHHHHHHHHEDDDAA>?AA at D=DDBHHGHHHFHHHHHHHHHHHHHHHHEH	UQ:i:0
+20GAVAAXX100126:8:25:1734:195910	99	chr1	10003819	60	101M	=	10004149	430	TGGCCAGCTAATTTTTGTATTTTTAGTATTTTTGTATTTTTGTTTCGCCATGTTGGTTGGGCTGGTCTCCAACTCCTGGCCTCAAGTGATCCACCCACCTC	CBC at CCCCDCDCDDDDBBBCDDDAACBCCDDD@@ABCDDDA at AA@=;BBCCBBDBCCDBCCBDBCCBDBBCDADBBDBCBBDBCDCCCDC at CC:CCDBAED	MD:Z:101	PG:Z:BWA	RG:Z:20GAV.8	AM:i:37	NM:i:0	SM:i:37	MQ:i:60	OQ:Z:HHHHHHHHHHHHHHHHHGGHHHHGGHHHHHHHGGGGHHHHGGGGGEHHHHHHHHHHHHHHHHHHHHHHHHGHHHHHHHHHHHHHHHIHHHFHHBHHHHFHH	UQ:i:0
+20GAVAAXX100126:8:26:5030:62604	147	chr1	10003851	60	101M	=	10003529	-422	TGTATTTTTGTTTCGCCATGTTGGTTGGGCTGGTCTCCAACTCCTGGCCTCAAGTGATCCACCCACCTCAGCCTACCAAAATGCTCGGATTACAAGTGTGG	C@<CDBC6B?AD at 9CD<8:>B;)?9)8=@BAC at C?CB?=7ABCCBCC at C@@CDA>?=DCB3BBA6BBCBDBCCCBDBCCCCCBCC;DACDCABAB?@@BD@	MD:Z:101	PG:Z:BWA	RG:Z:20GAV.8	AM:i:37	NM:i:0	SM:i:37	MQ:i:60	OQ:Z:@<<?@@?3?B@@@@AA:53@@:)A8'8=>=AA?AA@@@;2A?ABAABAB?BBBB9?@BBB4BBB6BBABBBBCB at CBBCCBBBCBCCCBCCBCCCCCCCCB	UQ:i:0
+20GAVAAXX100126:8:45:3960:5771	83	chr1	10003872	60	101M	=	10003525	-447	TGGTTGGGCTGGTCTCCAACTCCTGGCCTCAAGTGATCCACCCACCTCAGCCTACCAAAATGCTCGGATTACAAGTGTGGCCCCTTGTAATAAAAATTTAA	EA?A, at CCCCCADCDCBDCCDCCCBBCADBDDACBCDCBACCBBCCDBDBCCCBCBDDDCCBCD;BBCDCBBDDACACBBCCCCDCABABCDDDDCDBCDC	MD:Z:101	PG:Z:BWA	RG:Z:20GAV.8	AM:i:37	NM:i:0	SM:i:37	MQ:i:60	OQ:Z:HFFD.CHHHHHHHHHHHHHHHHHHHHHFHHHHHHHHHHHFHHHIHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHGGGHHHHHHHHHHH	UQ:i:0
+20GAVAAXX100126:8:4:16802:116090	611	chr1	10003895	60	101M	=	10004234	439	TGGCCTCAAGTGATCCACCCACCTCAGCCTACCAAAATGCTCGGATTACAAGTGTGGCCCCTTGTAATAAAAATTTAATTTTTTGGAATATGACTCTTGGA	1.)4=???3/>@,=<<30+->;>6<<<:;>:+:6;;;<<:9*31=;;99=97=:<@>:==AA7=<9::9:>765198:9+=;:5:A/<>:::86<9@=:.B	MD:Z:101	PG:Z:BWA	RG:Z:20GAV.8	AM:i:37	NM:i:0	SM:i:37	MQ:i:60	OQ:Z:5..54544/.44+55473+0<AA9E45554=/=:=444549+=8<55554:8A==FA at EECC:A at 45544?:::744550===:<F2 at A@445555AB=8E	UQ:i:0
+20GAVAAXX100126:8:63:8454:180865	1187	chr1	10003896	60	101M	=	10004216	420	GGCCTCAAGTGATCCACCCACCTCAGCCTACCAAAATGCTCGGATTACAAGTGTGGCCCCTTGTAATAAAAATTTAATTTTTTGGAATATGACTCTTGGAG	@CBBB at ACBBBCCADDACBBACDBCCBBDCACCAAAAAACB;CDACC at CCAAC;ADBCBCCBB=CC at AC?ACDABA@=CCBADA8=AB9C>B at BBBCB;8@	MD:Z:101	PG:Z:BWA	RG:Z:20GAV.8	AM:i:37	NM:i:0	SM:i:37	MQ:i:60	OQ:Z:BBBCBCCBB at BBBBCCBBAABBBBBBB@BBBBB>AABBBBBBBBBBB at BAB@B=@BAAABB at A<B at B@@<@@B@@A?=BA at B@B96;A;@>@@@@??<;1=	UQ:i:0
+20GAVAAXX100126:8:47:13004:90024	147	chr1	10003910	60	60S41M	=	10003567	-383	TTGTATTTTTGTTTCGCCATGTTGGTTGGGCTGGCATCCAACTCCTGGCCTCAAGTAATCCACCCACCTCAGCCTACCAAAATGCTCGGATTACAAGTGTG	#############################################################>:;6=5 at 6BB7;;A8(@CCC>;AAC;>?A<B>=AB>A at B@	MD:Z:41	PG:Z:BWA	RG:Z:20GAV.8	AM:i:37	NM:i:0	SM:i:37	MQ:i:60	OQ:Z:#############################################################@>><>9>5A at 6:6A1,>BBB=7A?BBAA?;B7=?B@@BAB	UQ:i:0
+20GAVAAXX100126:8:2:13260:81311	163	chr1	10003923	60	90M11S	=	10004222	399	CTACCAAAATGCTCGGATTACAAGTGTGGCCCCTTGTAATAAAAATTTAATTTTTTGGAATATGACTCTTGGAGTTTTTCTTTTTCTTTTTTTACTTTTGG	@C4:97@:CB>??>9=;<@:??2?-4?BACACC:<=6:<:16>@9BAD9 at 889:?BBB3?96>;?=;BDB:?4877?(?;C?D>78D6@############	MD:Z:90	PG:Z:BWA	RG:Z:20GAV.8	AM:i:37	NM:i:0	SM:i:37	MQ:i:60	OQ:Z:B at 4;66=7 at A?=@A@=79=9@<.;'1:A?B at BA7>@6>?>47><<A=A:<;84<;>B?0<;7><<<=BA@;<0755>);;B>B<53 at 4@############	UQ:i:0
+20GAVAAXX100126:8:1:17413:63912	1187	chr1	10003958	60	101M	=	10004229	371	GTAATAAAAATTTAATTTTTTGGAATATGACTCTTGGAGATTTTCTTTTTATTCTTTTACTTTTGGACTCTGTTGGACTTCAGTTGTTTTTCTTTAATGGC	@BBCBACCCCCCCADCCCCCCBCCDCCCCCADBDB?*34->CCC6DDCCB&:C/CDCD4;8C6BB at 0@EB*CC2>$8<D;(3D9=CC9,=7;C8B@>?5>4	MD:Z:39T10C2T26G20	PG:Z:BWA	RG:Z:20GAV.8	AM:i:37	NM:i:4	SM:i:37	MQ:i:60	OQ:Z:BABBBBBBBABBBBBBBBBBBBBBBBBBBABBBBBA355- at BBA:BABB?';@.>BBB3;7A4BA>/ABA)BA1=(6>B:(0B1;B?7-869?6??991:2	UQ:i:38
+20GAVAAXX100126:8:7:11540:56171	163	chr1	10003958	60	101M	=	10004229	371	GTAATAAAAATTTAATTTTTTGGAATATGACTCTTGGAGTTTTTCTTTTTCTTTTTTTACTTTTGGACTCTGTTGGACTTGAGTTGTTTTTCTTTAATGGC	@ABCBACCCCCCCAACCCCCCBCBCCACCBADBDBAA<A=BCCC?CDDCC<DDADDCCB at BCB?BC=@EB at CC?@@=?CB at AB?@CB@>D=ABBA?CA at C?	MD:Z:101	PG:Z:BWA	RG:Z:20GAV.8	AM:i:37	NM:i:0	SM:i:37	MQ:i:60	OQ:Z:ABBBBBBBBBBBBB?BBBBBCBB?ABABB at BBBBBBB>B?BBBBAAAAAA at BABBAA@AAAA@?AA?ABA?A>?@?<A?@??@=>B8>>@<?>@<>><?><	UQ:i:0
+20GAVAAXX100126:8:7:11542:56193	1187	chr1	10003958	60	101M	=	10004229	371	GTAATAAAAATTTAATTTTTTGGAATATGACTCTTGGAGTTTTTCTTTTTCTTTTTTTACTTTTGGACTCTGTTGGACTTGAGTTGTTTTTCTTTAATGGC	@ABBBACCCCCCCACCCCCCCBCBBCACCBADBDBAA7A<BBCC?DCDCC<CCADDCDB?CB at AAB;>EABCCAAA=9DBA>C?ACB@>B@=ABB?CA?D#	MD:Z:101	PG:Z:BWA	RG:Z:20GAV.8	AM:i:37	NM:i:0	SM:i:37	MQ:i:60	OQ:Z:BBBABBBBAABBBBABBBBBCBB?@BABB at BBABBBB9B>BABBABBAA@?A at BBAAAA?B@?@@@>?B?AA>@A@<;A at A<A<?B<>>=?<<@?>><>?#	UQ:i:0
+20GAVAAXX100126:8:25:18450:91287	83	chr1	10003979	60	101M	=	10003652	-427	GGAATATGACTCTTGGAGTTTTTCTTTTTCTTTTTTTACTTTTGGACTCTGTTGGACTTGAGTTGTTTTTCTTTAATGGCTTTATTGAGGTATATTTTATG	>D<CBCDCCCDCDCCBD?AABABAAA at ABAADDDDDCBCDDDCBBBC@CCADCBBBCDCBD?@B?A@@DDCDDCDCCBBCDDCCDCBDBACCCCDDDABCC	MD:Z:101	PG:Z:BWA	RG:Z:20GAV.8	AM:i:37	NM:i:0	SM:i:37	MQ:i:60	OQ:Z:BHBHGHHHHHHHHHHHHGGGGGGGGGGGGGGHHHHHHGHHHHHHHGHDHHHHHHHHHHHHHGGGGGGGHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHH	UQ:i:0
+20GAVAAXX100126:8:25:13133:61877	99	chr1	10003984	60	101M	=	10004291	407	ATGACTCTTGGAGTTTTTCTTTTTCTTTTTTTACTTTTGGACTCTGTTGGACTTGAGTTGTTTTTCTTTAATGGCTTTATTGAGGTATATTTTATGTACCA	CCBBADBDDBCDCBDDDDBCAAAA at CAA@@A at AACDDDBCDACBCBBDBCDADDBDCCDBCDDAAAC@@ADCACBDDDCCDBDCCBCCCADDBCCCCDBDE	MD:Z:101	PG:Z:BWA	RG:Z:20GAV.8	AM:i:37	NM:i:0	SM:i:37	MQ:i:60	OQ:Z:HHHHHHHHHHHHHHHHHHHGGGGGGGGGGGGGGHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHGGGGGGGHHFHHHHHHHHHHHHIHHHGHHFHHHHHHHH	UQ:i:0
+20GAVAAXX100126:8:8:8310:17522	99	chr1	10003989	60	101M	=	10004327	421	TCTTGGAGTTTTTCTTTTTCTTTTTTTACTTTTGGACTCTGTTGGACTTGAGTTGTTTTTCTTTAATGGCTTTATTGAGGTATATTTTATGTACCATAAAA	CBCBCCDCCDDDDBCAAAA at CAAA@AAAADDDDBCDACBCBBDBCDADDBDCBDBBDDA at ACAABDCBCBDDDCCDBDCCCCCCCDDDCCCBCACDBDEE@	MD:Z:101	PG:Z:BWA	RG:Z:20GAV.8	AM:i:37	NM:i:0	SM:i:37	MQ:i:60	OQ:Z:HHHHHHHHHHHHHHGGGGGGGGGGGGGGHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHGGGGGGGHHHHHHHHHHHHHHHHHHHHHHHHHHFHHHHGHHIG	UQ:i:0
+20GAVAAXX100126:8:45:4754:168834	1187	chr1	10003992	60	86M15S	=	10004321	413	TGGAGTTTTTCTTTTTCTTTTTTTACTTTTGGACTCTGTTGGACTTGAGTTGTTTTTCTTTAATGGCTTTATTGAGGTATATTTTATGTACCATAAAATGC	@A2?A@=AAC;C?=8B=CCCBCCCC:DC4C at 7A@>ABA><0*(?BC:BCA;B9(BDCBCCBC at 6;96ADC?DD7+>65=8'=D at C################	MD:Z:86	PG:Z:BWA	RG:Z:20GAV.8	AM:i:37	NM:i:0	SM:i:37	MQ:i:60	OQ:Z:B at 6=AA:@CB<A@@4@;@CB at BCAB9BB2A@7?A?BBB@>00)?BA6>B<>B/)=BBAABBB>679:?BB at BB6+=9-;8(=B?A################	UQ:i:0
+20GAVAAXX100126:8:44:17629:79062	1107	chr1	10004001	60	101M	=	10003678	-423	TCTTTTTCTTTTTTTACTTTTGGACTCTGTTGGACTTGAGTTGTTTTTCTTTAATGGCTTTATTGAGGTATATTTTATGTACCATAAAATGCACCTAAGTG	=::6<=<<=BBB@<=>A@@<C==;>B;@?ABA@:ABA at B:=:9<<=AC>ABAABABAAAABAA@@C@??@B>???=<??B99?>====<><=;?AA@<<><	MD:Z:101	PG:Z:BWA	RG:Z:20GAV.8	AM:i:37	NM:i:0	SM:i:37	MQ:i:60	OQ:Z:?><:><BBBFGFD at AAGDD@GDD at DF?EGGFGGCGGFGFBBBBBBBGGEGGGGGFGGGGGGGFDGGGGFFGDDDDD>DGGB5444445554DCFGGGGFGF	UQ:i:0
+20GAVAAXX100126:8:25:9891:26690	99	chr1	10004020	60	101M	=	10004321	387	TTGGACTCTGTTGGACTTGAGTTGTTTTTCTTTAATGGCTTTATTGAGGTATATTTTATGTACCATAAAATGCACCTAAGTGTACAATTTGATAATTTCTA	CDBADADBDBCDBCDADDBDCBDBBDDA@@C@@ADCBCBCDDCCDBCCCBCCCCDDDCCBCCACCCCDDDCBBCABDCDCABCCACDCDDCDCCDCDDCED	MD:Z:101	PG:Z:BWA	RG:Z:20GAV.8	AM:i:37	NM:i:0	SM:i:37	MQ:i:60	OQ:Z:HHHHHHHHHHHHHHHHHHHHHHHHHHHGGGGGGGHHHHHHHHHHHHGHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHFHHHHHHHHHHHHHHHHHHHH	UQ:i:0
+20GAVAAXX100126:8:21:17746:177127	163	chr1	10004141	60	101M	=	10004479	438	AACCATTCCTACAATCCAGTTTCAGAACAAGTCAATCACTCCAAAAAGTTCCCTAGAGACCATGTGCTGACAACTATTATTTTATAGGCTTTTCTTTTTCT	@DAB at A@BCDCACBDCDDCACCCDCCEACCCBBDC@=B@@@CBDBD?CAC?CDBD:CCCABCBABC8DCC?BB>CBBBB>BAD at BBDB=CAAC>D at CCBCD	MD:Z:101	PG:Z:BWA	RG:Z:20GAV.8	AM:i:37	NM:i:0	SM:i:37	MQ:i:60	OQ:Z:BCCCCCCCCCCCCCCCCCBBCCCCCCCBBACBBCBCCBBCCBCBBC:BABABCBC4BCBBBBABBBCBBBB>>@BBBA@>BB@@A at BBB=@BB=ABB?A at A	UQ:i:0
+20GAVAAXX100126:8:21:17763:177132	1187	chr1	10004141	60	101M	=	10004479	438	AACCATTCCTACAATCCAGTTTCAGAACAAGTCAATCACTCCAAAAAGTTCCCTAGAGACCATGTGCTGACAACTATTATTTTATAGGATTTTTTTTTTCT	>C>A at AB?@D9:@<DB>BA?CC?*;CBBCAC8 at B)=6B4 at BC;=:<@=7C<AD>C at CCC?BB@<B at 8CB??D?>AB=>;71<B??BB<'C8CD)DBDD>BD	MD:Z:88C4C7	PG:Z:BWA	RG:Z:20GAV.8	AM:i:37	NM:i:2	SM:i:37	MQ:i:60	OQ:Z:=A@@?CB?=C;9A?CB<A?:CA>)7A at CB?B4@@)@<B:CBB;9=;<91@?CC?B;ACA at BC?>@>CAACBB:@?BC=872;=?>C?<(A7AA)BA at B<<C	UQ:i:14
+20GAVAAXX100126:8:25:1734:195910	147	chr1	10004149	60	101M	=	10003819	-430	CTACAATCCAGTTTCAGAACAAGTCAATCACTCCAAAAAGTTCCCTAGAGACCATGTGCTGACAACTATTATTTTATAGGCTTTTCTTTTTCTTTTTCTTT	CCBCBACAAA6A:>CEABCABCAA at BAACCACCA@CCBDABBCDCBE at D@?DBDCAACBCB at A>??ADDCDDDDDDDEDBCDEECCDBDDCBCCBABACD@	MD:Z:101	PG:Z:BWA	RG:Z:20GAV.8	AM:i:37	NM:i:0	SM:i:37	MQ:i:60	OQ:Z:B??A>A?@>>6<:;AB@@AA at BA?@@@@B?BBA at BBABBBB@BBBABBBCABBCBBBBBBBBBCBCCCBCCBBBCCCCCBCBCCCCBCCCBCBCCCBCBBB	UQ:i:0
+20GAVAAXX100126:8:42:7969:44162	1187	chr1	10004170	60	101M	=	10004491	421	AGTCAATCACTCCAAAAAGTTCCCTAGAGACCATGTGCTGACAACTATTATTTTATAGGCTTTTCTTTTTCTTTTTCTTTTTTTTCTATTTCTGTTTGAGA	@CAA at ABBCADCCAEEEECBBCDDDCDCCCBBC?@>AACAA at CD:DCDCC;CCACDCCCCCC?BBD at CCC@DDABCABCBBBBABCDB>CAADABBDCBB>	MD:Z:101	PG:Z:BWA	RG:Z:20GAV.8	AM:i:37	NM:i:0	SM:i:37	MQ:i:60	OQ:Z:@CBCCCCBBCCCCCCCCCC@@CCCBBCBCBCAA>A at BBBBACBBCBBBBBCBBBBBBBBBBB=BBAAB at BA?BBBABB at BAA=BBB at ABB@BBA:@@A@<:	UQ:i:0
+20GAVAAXX100126:8:42:7986:44148	163	chr1	10004170	60	101M	=	10004491	421	AGTCAATCACTCCAAAAAGTTCCCTAGAGACCATGTGCTGACAACTATTATTTTATAGGCTTTTCTTTTTCTTTTTCTTTTTTTTCTATTTCTGTTTGAGA	@CAA at ABBCADCCBEEEDCBCCDDECCCCCBCCCB>=AC>AACD?DCDCBACCACDBCCCCCCBBD at CDC@EDABB?BCBBADABCE=>CBAD at CBCC5B;	MD:Z:101	PG:Z:BWA	RG:Z:20GAV.8	AM:i:37	NM:i:0	SM:i:37	MQ:i:60	OQ:Z:BCBCCCCCBCCCCBCCCBCACCCCCBBBBBCBBBB at CBBCABBBBBBCBABBBBBBABBBBBBBABBBBBBBBBBB?BB at BBBBBBB=BBA at A??AB?1<6	UQ:i:0
+20GAVAAXX100126:8:28:13507:25203	99	chr1	10004176	60	101M	=	10004453	376	TCACTCCAAAAAGTTCCCTAGAGACCATGTGCTGACAACTATTATTTTATAGGCTTTTCTTTTTCTTTTTCTTTTTTTTCTATTTCTGTTTGAGACAGAGT	CBC?DBCCDDDDCBDBBBDCCDCDABCCBBBBCBDACDACCCDCCDDABCCCCBDDDDBDAAAA at CA@@@@C@@@AA@@@C<CDDBDCCDDCDCDADDDDD	MD:Z:101	PG:Z:BWA	RG:Z:20GAV.8	AM:i:37	NM:i:0	SM:i:37	MQ:i:60	OQ:Z:HHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHGGHHHHHHHHHHHGGGGGGGGGGGGGGGGGGGGGBHHHHHHHHHHHHHHHHHHI	UQ:i:0
+20GAVAAXX100126:8:63:8454:180865	1107	chr1	10004216	60	101M	=	10003896	-420	ATTATTTTATAGGCTTTTCTTTTTCTTTTTCTTTTTTTTCTATTTCTGTTTGAGACAGAGTCTCTTTCTGTCACCCAGGGTGGAGTGGAGTGGCATAATCT	A at DCEEDCCCDCCAABABAABAABAA@AACAA?A at DDDDCCCDDDCCADDCBCBBBCBCADCDCDDDCCADBACCBDBBACBBDACBBDACBBCCCDACCC	MD:Z:95C5	PG:Z:BWA	RG:Z:20GAV.8	AM:i:37	NM:i:1	SM:i:37	MQ:i:60	OQ:Z:GGHHHHHHHHHHHGGGGGGGGGGGGGGGGGGGEGEHHHHHHHHHHHHHHHHHHHGHHHHHHHHHHHHHHHHHGHHHHHHHHHHHHHHHHHHHHHHHHHHHH	UQ:i:34
+20GAVAAXX100126:8:2:15114:83430	99	chr1	10004220	60	101M	=	10004542	422	TTTTATAGGCTTTTCTTTTTCTTTTTCTTTTTTTTCTATTTCTGTTTGAGACAGAGTCTCTTTCTGTCACCCAGGGTGGAGTGGAGTGGCACAATCTCAGC	CDCBCCCCCBDDDDBDAAAA at CAA@A at C@@A@@@@@CACDDBCBBDDBDCDACCDCCBDBDDDBDBBBCABBBCCCBBCDCCCCDCCCCBCACDCCDCDD>	MD:Z:101	PG:Z:BWA	RG:Z:20GAV.8	AM:i:37	NM:i:0	SM:i:37	MQ:i:60	OQ:Z:HHHHHHHHHHHHHHHHGGGGGGGGGGGGGGGGGGGGGGHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHGHHHGHHHHHHHHHHHHHHHHHHHHHHHA	UQ:i:0
+20GAVAAXX100126:8:2:13260:81311	83	chr1	10004222	60	101M	=	10003923	-399	TTATAGGCTTTTCTTTTTCTTTTTCTTTTTTTTCTATTTCTGTTTGAGACAGAGTCTCTTTCTGTCACCCAGGGTGGAGTGGAGTGGCACAATCTCAGCTC	?<@AC>C>@AA>>@@A;<;?=?@>>A??9DDADCBC?AAACADDCB=;>==B?A-CD=DADC??DBB=C>DBBAC=BDA at BBDACBBBCB@CDCD at D@>DC	MD:Z:101	PG:Z:BWA	RG:Z:20GAV.8	AM:i:37	NM:i:0	SM:i:37	MQ:i:60	OQ:Z:BBEGFBHCCCCCCCCC@@@A at CCCCCCC5HHGHHGHEGEGHHHHHH????@HDH.HHEHGHHEGHHHEHCHHHHHDHHHEHHHHHHHHHHFHHHHGHHFHH	UQ:i:0
+20GAVAAXX100126:8:45:4354:79437	99	chr1	10004223	60	101M	=	10004540	414	TATAGGCTTTTCTTTTTCTTTTTCTTTTTTTTCTATTTCTGTTTGAGACAGAGTCTCTTTCTGTCACCCAGGGTGGAGTGGAGTGGCACAATCTCAGCTCA	CCBACCCDDDDBDAAAAACAAAA<BAAA@@A@@BACDDBCBBDDBDCDACCDCBBDBDDDBDBCBCABBCCCCABCDCCBCDC at BCCBACDCCDCDC@DDA	MD:Z:101	PG:Z:BWA	RG:Z:20GAV.8	AM:i:37	NM:i:0	SM:i:37	MQ:i:60	OQ:Z:HHHHHHHHHHHHHGGGGGGGGGGEGGGGGGGGGGGHHHHHHHHHHHHHHHHHHGHHHHHHHHHHHHHHHHHHHGHHHHHHHHHDHHHGHHHHHHHHHDHHG	UQ:i:0
+20GAVAAXX100126:8:4:5529:91628	163	chr1	10004227	60	101M	=	10004550	423	GGCTTTTCTTTTTCTTTTTCTTTTTTTTCTATTTCTGTTTGAGACAGAGTCTCTTTCTGTCACCCAGGGTGGAGTGGAGTGGCACAATCTCAGCTCACTGC	@B?C?ABBCBCBBADBBBCADCCCCCCCBDCCCCAC6 at BA@;AC?CCC at C@DBBDDBDCB>B=ACC?9C??C?=>@ABC6>>BB at C?:<C06>@C6A@?C?	MD:Z:101	PG:Z:BWA	RG:Z:20GAV.8	AM:i:37	NM:i:0	SM:i:37	MQ:i:60	OQ:Z:B@@BCBBCCCBCCBCCCCCABCCCCCCBBBBBBBBB<ABAA<AABBB@@@BBABBABAB@@@>AA at A:A:@@:>;@@@A5>>@@A?89>=-29?>2<=;><	UQ:i:0
+20GAVAAXX100126:8:44:5789:104432	163	chr1	10004228	60	101M	=	10004558	430	GCTTTTCTTTTTCTTTTTCTTTTTTTTCTATTTCTGTTTGAGACAGAGTCTCTTTCTGTCACCCAGGGTGGAGTGGAGTGGCACAATCTCAGCTCACTGCA	@BCB??ACCBBBBBBBBBBECCCCCCCCECDBBCBA?B>ACCCA<BBCAC<BDADCDCBBBACBC>@CCB at DC@@B?ABAA at D@CDCAACA>=BB at AD@?C	MD:Z:101	PG:Z:BWA	RG:Z:20GAV.8	AM:i:37	NM:i:0	SM:i:37	MQ:i:60	OQ:Z:BBCBCCBCBCCCCCCCCCBCCCCCCCCCCCCCCCCBBBCBBBBBCA>AABCBBBBBBBBBBBBBA:BA>B at AB?@B>A=A at BBAB@@AABA<:@@BA@?:A	UQ:i:0
+20GAVAAXX100126:8:1:17413:63912	1107	chr1	10004229	60	101M	=	10003958	-371	CTTTTCTTTTTCTTTTTCTTTTTTTTCTATTTCTGTTTGAGACAGAGTCTCTTTCTGTCACCCAGGGTGGAGTGGAGTGGCACAATCTCAGCTCACTGCAA	@@@@CAAAAACAAAABBAAABADDDDCCCDDDCCADDCBDBCBDBDADCDCDDDCCADBBCCBCBBACBBDACBBDACBBBCBDCDCDBDBCDCCCC at BDC	MD:Z:101	PG:Z:BWA	RG:Z:20GAV.8	AM:i:37	NM:i:0	SM:i:37	MQ:i:60	OQ:Z:GGGGGGGGGGGGGGGGGGGGGGHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHGHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHH	UQ:i:0
+20GAVAAXX100126:8:7:11540:56171	83	chr1	10004229	60	101M	=	10003958	-371	CTTTTCTTTTTCTTTTTCTTTTTTTTCTATTTCTGTTTGAGACAGAGTCTCTTTCTGTCACCCAGGGTGGAGTGGAGTGGCACAATCTCAGCTCACTGCAA	@@@@CAAAAACAAAABBAAABADDDDCCCDDDCCADDCBDBCBDBDADCDCDDDCCADBBCCBCBBACBBDACBBDACBBBCBDCDCDBDBCDCCCC at BDC	MD:Z:101	PG:Z:BWA	RG:Z:20GAV.8	AM:i:37	NM:i:0	SM:i:37	MQ:i:60	OQ:Z:GGGGGGGGGGGGGGGGGGGGGGHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHH	UQ:i:0
+20GAVAAXX100126:8:7:11542:56193	1107	chr1	10004229	60	101M	=	10003958	-371	CTTTTCTTTTTCTTTTTCTTTTTTTTCTATTTCTGTTTGAGACAGAGTCTCTTTCTGTCACCCAGGGTGGAGTGGAGTGGCACAATCTCAGCTCACTGCAA	@@@@CAAAAACAAAABBAAABADDADCCCDDDCCADDCBDBCBDBDADCDCDDDCCADBBCCBCBBACBBDACBBDACBBBCBDCDCDBDBCDCCCC at BDC	MD:Z:101	PG:Z:BWA	RG:Z:20GAV.8	AM:i:37	NM:i:0	SM:i:37	MQ:i:60	OQ:Z:GGGGGGGGGGGGGGGGGGGGGGHHGHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHH	UQ:i:0
+20GAVAAXX100126:8:4:16802:116090	659	chr1	10004234	60	101M	=	10003895	-439	CTTTTTCTTTATCTTTTTTTTCTATTACTGTTTGAGACAGAGTCTCTTTCTGTCACCCAGGGTGGAGTGGAGTGGCTCAATCTCAGCTCACTGCAACCTCT	CEAB?%B*A<&A>)D?;@9<9<@;43, at B(=9C>8AA<D,B87C at CD;/B922<BC at CDB>3<85?;*A47?CC>3)@*6,44BA:@?71B@@;>4B=A9;	MD:Z:10T15T49A24	PG:Z:BWA	RG:Z:20GAV.8	AM:i:37	NM:i:3	SM:i:37	MQ:i:60	OQ:Z:BB>;8%=)<;'<B*B98>3:7C>;42)@?)=5A>9?==B+A84ACCA=,A<008ABABBC?8?;;@@*?13 at AB</)>*3+01A>9=A8+C>?9;-A;@37	UQ:i:24
+20GAVAAXX100126:8:25:13133:61877	147	chr1	10004291	60	101M	=	10003984	-407	CAGGGTGGAGTGGAGTGGCACAATCTCAGCTCACTGCACCCTCTGTCTCCTGGGTTCAAGGGATTCTCCTGCCTCAGCTTCCCAAGTAGCTGGGATTACAG	BBA>AAC9A:2>?@@=>=A7<><9>9@;?B7=@>=?B>,=ABAC=4@>B?;CB at C=8A?AB<;?0:ACBCBCCCBDBCDCCCCCEACCBCCCBBBBA at BD@	MD:Z:38A62	PG:Z:BWA	RG:Z:20GAV.8	AM:i:37	NM:i:1	SM:i:37	MQ:i:60	OQ:Z:A:?8A??6<:/9@=?7<<<5<=96>6?:<>6:8=?>A>/=A?@@=/<?@?=BA@@<<??AB??@3=ABABBABBBBBBBBBBCBCBBBBBBBBBBBBBCBB	UQ:i:11
+20GAVAAXX100126:8:66:6823:31942	163	chr1	10004294	29	35M66S	=	10004641	427	GGTGGAGTGGAGTGGCACAATCCCAGCTCACTGAAACCTCTGTCTCCGGGGTTCAAGGGATTCTCCTGCCTCAGCTCCCCAAGAAGCTGGGATTCCAGGCC	@B0 at A:A6AC5C<<#######################################################################################	MD:Z:22T10C1	PG:Z:BWA	RG:Z:20GAV.8	AM:i:0	NM:i:2	SM:i:0	MQ:i:37	OQ:Z:@@+ at B9@4 at B3B=@#######################################################################################	UQ:i:4
+20GAVAAXX100126:8:25:9891:26690	147	chr1	10004321	60	14S87M	=	10004020	-387	GGCACAATCTCAGCTCACTGCAACCTCTGTCTCCTGGGTTCAAGGGATTCTCCTGCCTCAGCTTCCCAAGTAGCTGGGATTACAGGCACTTGCCACCACGC	###############B=:A7<9>>:<@?@B?BBB=BB?B@>CCC>BC=A@@DCCBC?CBD at BBB5BBCDACDCCCCCBCEDABCCAB;BDCACBBBA@:B@	MD:Z:87	PG:Z:BWA	RG:Z:20GAV.8	AM:i:37	NM:i:0	SM:i:37	MQ:i:60	OQ:Z:###############?67<7<97>::???<??@A???A@>?AAB<AA?<@ABBAABAABBABBB<BBBBBBBBBBBBBBCCBAABAA=BBBABBABABBBB	UQ:i:0
+20GAVAAXX100126:8:45:4754:168834	1107	chr1	10004321	60	16S85M	=	10003992	-413	GTGGCACAATCTCAGCTCACTGCAACCTCTGTCTCCTGGGTTCAAGGGATTCTCCTGCCTCAGCTTCCCAAGTAGCTGGGATTACAGGCACTTGCCACCAC	#################=<<<8:,:55<56<3<:6;<:;0<<6<==;;<<1=:7<<;8=;==9<;;:995=;:@>@35??@==>>>>B=B@>A==9?5<=>	MD:Z:85	PG:Z:BWA	RG:Z:20GAV.8	AM:i:37	NM:i:0	SM:i:37	MQ:i:60	OQ:Z:#################A??>552449>;9A3455544515<8<><55440455554445555554<=@9=A>CCC89CCC54455AGDGFAFAD at DDDDD	UQ:i:0
+20GAVAAXX100126:8:8:8310:17522	147	chr1	10004327	60	17S84M	=	10003989	-421	ACAATCTCAGCTCACTGCAACCTCTGTCTCCTGGGTTCAAGGGATTCTCCTGCCTCAGCTTCCCAAGTAGCTGGGATTACAGGCACTTGCCACCACGCGCA	##################B<@AA@>147?874 at C8BB>CAAB?@CCA9ABACBCCB=CB?C@@A?C at CDBBCCCB?DBBBCCBBBCDBBCBBCB at 9A:BB@	MD:Z:84	PG:Z:BWA	RG:Z:20GAV.8	AM:i:37	NM:i:0	SM:i:37	MQ:i:60	OQ:Z:##################?6?@<?=115:670<B=???A?A?>=A@>:>ABBABAB?BB?BAABABBBBAABBBB>BAAAABBBABBBBBBABBBBBBBBB	UQ:i:0
+20GAVAAXX100126:8:21:4413:182078	99	chr1	10004409	60	101M	=	10004700	382	CAGCTAATTTTTGCATTTTGAGTAGACAGGGGGTTTCACCATGTTGGCAAGGCTGGTCTCGAACTCCTGACCTCAGGTGATCTGCCCACCTTGGCCTGCTG	CCB at DCDCDDDDBBCCDDDBDCBCCDACCCCCCADDBCABCCBBDBCBCDCCBDBCBBDB;DD at DBBDBCABDBCCCA@DCBDCBCCCACDDCD?CDCCED	MD:Z:101	PG:Z:BWA	RG:Z:20GAV.8	AM:i:23	NM:i:0	SM:i:37	MQ:i:60	OQ:Z:HHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHIHHHHHHHHHHHHHHHHHHHHHHIHHHHHHIHHHHHIHHHHHHHGGHHHHHHHHHHHHHHHEHHHHHH	UQ:i:0
+20GAVAAXX100126:8:1:11745:83846	163	chr1	10004442	37	101M	=	10004719	377	TTTCACCATGTTGGCAAGGCTGGTCTCGAACTCCTGACCTCAGGTGATCTGCCCACCTTGGCCTGCTGGAGGTATGTGACAAACTGATGGCAAATGGATTA	@BAA@?BBCBACBBCCDCCCDBC at BBB;CDADBCC;7 at ACBCBC;BD?BD=BC@?BBCCAABBCAC at B8A?C?;:>A;C>BAC?@BA;?C=;C>=A;?AA;	MD:Z:101	PG:Z:BWA	RG:Z:20GAV.8	AM:i:0	NM:i:0	SM:i:37	MQ:i:29	OQ:Z:BCCCCCCCBCBBBBCBBCBCBBB:B at BBABBBABB><BBBBBBB=AB<BA at BBA9BA@A?ABAB?BAB7>@A6=9=?:??B??B=?;:?@=CB;7?97@:8	UQ:i:0
+20GAVAAXX100126:8:45:9158:12274	633	chr1	10004442	0	62S39M	=	10004442	0	CTGGGATTACAGGTGCCCACCACCACACTTGGCTAAGTTTTGTATTTTTAGTAGAGTCGGGGTTTCACCATGTTGGCAAGGCTGGTCTCGAACTCCTGACC	###############################################################>>=;+<<=9;<:9=;?;;?=<<=?<6==?@>9@>5>*1	MD:Z:39	PG:Z:BWA	RG:Z:20GAV.8	AM:i:0	NM:i:0	SM:i:0	OQ:Z:###############################################################AA?51544555455545545544455544445455515	UQ:i:0
+20GAVAAXX100126:8:45:9158:12274	693	chr1	10004442	0	*	=	10004442	0	CAAGAATTTCAGTTGCAGTCAGTACTCGGTTCAGGAACACTCCACCCAGGTTTGTAGCTTAGGAGCAATAGACTTTTTCCTATGCAATGTAGGTGTGTGGT	##################################################################?1AC5516*B*C'BA*A&@-<-0;4;6B.@)41@<	PG:Z:BWA	RG:Z:20GAV.8	OQ:Z:##################################################################@/@A30-2)@*A*A@*?'?-8,29074A,@*02A8
+20GAVAAXX100126:8:28:13507:25203	147	chr1	10004453	60	1S100M	=	10004176	-376	TTGGCAAGGCTGGTCTCGAACTCCTGACCTCAGGTGATCTGCCCACCTTGGCCTGCTGGAGGTATGTGACAAACTGATGGCAAATGGATTATGCCCCCAAT	##A:AAC?:?@C:CBB1 at B>A>@A at A=ABC at CC@@BBBBB at AAC>BC at CC?CBCCC=CBA5>ABA at BBBCCCBCCBCBCBBCCCCCCBCCCCBCBBAABC@	MD:Z:100	PG:Z:BWA	RG:Z:20GAV.8	AM:i:37	NM:i:0	SM:i:37	MQ:i:60	OQ:Z:##@4=?<=6=?A=@==4B=;@==A?B8A@?AABAAA at AA@A@@A8 at AA@BAAAABB at AB@7ABBBBBBABBBABBBB at BBBBCBBBCBBBBBBBBBBBBCB	UQ:i:0
+20GAVAAXX100126:8:21:17746:177127	83	chr1	10004479	60	101M	=	10004141	-438	CCTCAGGTGATCTGCCCACCTTGGCCTGCTGGAGGTATGTGACAAACTGATGGCAAATGGATTATGCCCCCAATGGACAGTGTTCTCAAACCGTGATCTGA	DDDCAC?DCCDCCBCCBCCAD;BBCCCBCCABDBACCCACBCBDDBCCBCCBBBDDCCBBCDCCCBCCCABDCCBBBBCACADDCDBDDBC;ACBCDACBC	MD:Z:101	PG:Z:BWA	RG:Z:20GAV.8	AM:i:37	NM:i:0	SM:i:37	MQ:i:60	OQ:Z:HHHHDHGHHHHIHHHHHHHGHBHHHHHHHHGHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHIHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHH	UQ:i:0
+20GAVAAXX100126:8:21:17763:177132	1107	chr1	10004479	60	101M	=	10004141	-438	CCTCAGGTGATCTGCCCACCTTGGCCTGCTGGAGGTATGTGACAAACTGATGGCAAATGGATTATGCCCCCAATGGACAGTGTTCTCAAACCGTGATCTGA	BACCDC=D at CD??>?@;45::@A>B?B>><A at BB??@<9<<C>DDA=A:@@B at BADCCBBCDCCC@CCCCBDCCBB at BC<C<ADCD=;;A;;ACB=B:?8<	MD:Z:101	PG:Z:BWA	RG:Z:20GAV.8	AM:i:37	NM:i:0	SM:i:37	MQ:i:60	OQ:Z:FFFHHHEHGHHDCCCC43555EGEGCGDCBGGFHGEF@@@BHEHHEEFBEDHFHGHHHHHHHHHHFHHHHHHHHHHFHHEHEGHHHDB at FBHHHHEGGGEG	UQ:i:0
+20GAVAAXX100126:8:45:18787:46333	163	chr1	10004482	60	100M1S	=	10004790	408	CAGGTGATCTGCCCACCTTGGCCTGCTGGAGGTATGTGACAAACTGATGGCAAATGGATTATGCCCCCAATGGACAGTGTTCTCAAACCGTGATCTGAGGA	@CBB?ABABDBBBACACDCBBACCBBBBCCCC?BBA:AB at ACBABBCABC@CD?DCBCBB at ABA?C>CCB>BB=?AA<BA@@C@@4@<7;;AA;BBACA##	MD:Z:100	PG:Z:BWA	RG:Z:20GAV.8	AM:i:37	NM:i:0	SM:i:37	MQ:i:60	OQ:Z:BBBB<BBABBBBBBBBBBBAAABABB at AAABB=ABB>BBBABABBA@?BABBB at BBA@A at A@AA<A at BA??@@=@?A9@????@=/:<6?7?=:??==?##	UQ:i:0
+20GAVAAXX100126:8:42:7969:44162	1107	chr1	10004491	60	101M	=	10004170	-421	TGCCCACCTTGGCCTGCTGGAGGTATGTGACAAACTGATGGCAAATGGATTATGCCCCCAATGGACAGTGTTCTCAAACCGTGATCTGAGGACCCGGGGAT	7 at A@@<A>@CBA>ABBABA at CA?ABC<>>8@@@AAC at BBBB@AABCA@@?BB@>BBBB=AB>A@:AB?B?AB at C@A at AB9@BABCAC at CA@?BB:@@:==<	MD:Z:101	PG:Z:BWA	RG:Z:20GAV.8	AM:i:37	NM:i:0	SM:i:37	MQ:i:60	OQ:Z:5GGDG;GCEGGGEGGGGGGGGGGGGGCAC9CGGEGGGGGGGGGGGGGGCDGGECGGGGEGGAGGCGGGGGGGGGGGGGGGGGGGGGGGGGGEGGGGGGGGG	UQ:i:0
+20GAVAAXX100126:8:42:7986:44148	83	chr1	10004491	60	101M	=	10004170	-421	TGCCCACCTTGGCCTGCTGGAGGTATGTGACAAACTGATGGCAAATGGATTATGCCCCCAATGGACAGTGTTCTCAAACCGTGATCTGAGGACCCGGGGAT	<DDACBDCDCCBCCCBCCC at D=ACCCABBBBDDCCCBCBBBBDDCCBBCDCCCBCCCCBDCCBBBBCACADDCDBDDAC;ACBCDCCBCBB at CC;CC at BCC	MD:Z:101	PG:Z:BWA	RG:Z:20GAV.8	AM:i:37	NM:i:0	SM:i:37	MQ:i:60	OQ:Z:<HHFHGHHHHHHHHHHHHHGHEHHHHHGHHHHHHHHHHFHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHGHHHHHHHHHHGHHFHHHHHHHHH	UQ:i:0
+20GAVAAXX100126:8:45:4354:79437	147	chr1	10004540	60	3S98M	=	10004223	-414	GGATTATGCCCCCAATGGACAGTGTTCTCAAACCGTGATCTGAGGACCCGGGGATCCCGAGACCTTTTAAGGGTATCTGTGAGATCAAAGCTATTTTCATA	####A?>89A4 at 9@BCB at C@@>B>BBAABB=?B7>CBABB at BCBBCD>:C=CBDCB@;BDB>=BBCCCCDCCACCCCCACBDBCCBCBDBCBCCCBBABC@	MD:Z:98	PG:Z:BWA	RG:Z:20GAV.8	AM:i:37	NM:i:0	SM:i:37	MQ:i:60	OQ:Z:####?>778?6=9>??A???>??@@@@@@=>:@>BAAA at A@BA at B?B@@B at ABBAAAABBB@@BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBCBB	UQ:i:0
+20GAVAAXX100126:8:2:15114:83430	147	chr1	10004542	60	101M	=	10004220	-422	ATGCCCCCAATGGACAGTGTTCTCAAACCGTGATCTGAGGACCCGGGGATCCCGAGACCTTTTAAGGGTATCTGTGAGATCAAAGCTATTTTCATAATAAT	>D=@B<=ACAAC?BCD at BABBBDAB@=A;BABDC?CBCC>;CC;CCC?DC at C;CDB>BBCCBABBBBACCCCCACBDCCCCCCDBCCBCDDCBBB?@ABC@	MD:Z:101	PG:Z:BWA	RG:Z:20GAV.8	AM:i:37	NM:i:0	SM:i:37	MQ:i:60	OQ:Z:;?;<?;:A@@@A@@B at A@ABAAAB@>8AABABBBABBBB>:BABBBAABBAABBBB@@BBBBBBBBBBBBBBBBBBBCBBCBBBBBBBBBCBBCBCCCBCB	UQ:i:0
+20GAVAAXX100126:8:4:5529:91628	83	chr1	10004550	60	101M	=	10004227	-423	AATGGACAGTGTTCTCAAACCGTGATCTGAGGACCCGGGGATCCCGAGACCTTTTAAGGGTATCTGTGAGATCAAAGCTATTTTCATAATAATCCTGAGAT	EDDCCCCDAC at DDCDBDDBC;ACBCDCCBDBBBCC;CCBBCDC>;BDBBCCDDDCDCBBACCDCCACBCBCDBDDDBACCDDDDBCCDCCDCDCCCBBBCC	MD:Z:101	PG:Z:BWA	RG:Z:20GAV.8	AM:i:37	NM:i:0	SM:i:37	MQ:i:60	OQ:Z:HHHHHHHHHHIHHHHHHHGHHHHHHHHHHHHHIHHHHHHHHHHEHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHGHHHHHHHHHHHHHHHHHHHHHHH	UQ:i:0
+20GAVAAXX100126:8:44:5789:104432	83	chr1	10004558	60	101M	=	10004228	-430	GTGTTCTCAAACCGTGATCTGAGGACCCGGGGATCCCGAGACCTTTTAAGGGTATCTGTGAGATCAAAGCTATTTTCATAATAATCCTGAGATGATATTTG	?EBEDCCCDDCC;ACBCDCCBBBB at CC;BBBBCDCC8BDBBCCDDDCDDBBACCDCCACBDB at DBDDCBCCCDDDDBCCDCCDCDCCCBDBCCBCCCBDCC	MD:Z:101	PG:Z:BWA	RG:Z:20GAV.8	AM:i:37	NM:i:0	SM:i:37	MQ:i:60	OQ:Z:GHHHHHFHHHHHHHHHHHHHHGHHEHHHHHHHHHHHFHHHIHHHHHHHHHHHHHHHHHHHHHFHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHH	UQ:i:0
+20GAVAAXX100126:8:25:3804:30880	163	chr1	10004579	60	101M	=	10004891	412	AGGACCCGGGGATCCCGAGACCTTTTAAGGGTATCTGTGAGATCAAAGCTATTTTCATAATAATCCTGAGATGATATTTGCTCTTCATTCTCTCTCTCTCA	@CCB?AB:CCCCCACC;CCCACDCCCCDCCCACCACA>AB at CCCADDCBDACCADCCDBDBCCBACABDCADBABAB@?AABCCCCDB>:AAD?D?DBBD@	MD:Z:101	PG:Z:BWA	RG:Z:20GAV.8	AM:i:37	NM:i:0	SM:i:37	MQ:i:60	OQ:Z:ABBBBBBBBBBBBBBBBBBBBBBBBBBBBBB;BBBBB at BBCBBBBBBBBBBBBBBCBBCBBBABCABBBB@BCBBAB?;AB at BA@BBB>4??BB?B@@@A<	UQ:i:0
+20GAVAAXX100126:8:42:4321:53069	99	chr1	10004580	60	101M	=	10004795	315	GGACCCGGGGATCCCGAGACCTTTTAAGGGTATCTGTGAGATCAAAGCTATTTTCATAATAATCCTGAGATGATATTTGCTCTTCATTCTCTCTCTCTCAT	CCC?CC;ACCDCBBB;DCDABDDDDCDCCCBCCBCBB at DCDCBCDDCBCCCDDDBCCCDCCDCBCDBACDCBDC=CDDBBDBDDBCCD at DADCDCDCDCED	MD:Z:101	PG:Z:BWA	RG:Z:20GAV.8	AM:i:37	NM:i:0	SM:i:37	MQ:i:60	OQ:Z:HHHHHHHIHHHHHHHHHHHHHHHHHHHHHHHHHHHHHGHHHHHHHHHHHHHHHHHHHHHHHHHHHHHDHHHHHHDHHHHHHHHHHHHHGHGHHHHHHHHHH	UQ:i:0
+20GAVAAXX100126:8:41:10214:75276	163	chr1	10004590	60	101M	=	10004899	409	ATCCCGAGACCTTTTAAGGGTATCTGTGAGATCAAAGCTATTTTCATAATAATCCTGAGATGATATTTGCTCTTCATTCTCTCTCTCTCATGAGCATATGG	@CBBA8BBCACDB at CCDCDCBCCCDBBCCCCCBCCCAACBCCCC@CDCCDABD at CEBDCCBBCBCD@CCBBCEAABAAAC at BBBADCC?C at AC@BAC at ACD	MD:Z:101	PG:Z:BWA	RG:Z:20GAV.8	AM:i:37	NM:i:0	SM:i:37	MQ:i:60	OQ:Z:BBCCBCBBBBBCCCBBBCCB at BBCBBABABBBBBBBBBBBBBBBBBBBBBBABBBBBABBBBBBBBAABAABBBBBAB@B at B@B at ABB@@BA at B@?@<@@B	UQ:i:0
+20GAVAAXX100126:8:5:7628:108971	99	chr1	10004623	60	101M	=	10004891	362	AAAGCTATTTTCATAATAATCCTGAGATGATATTTGCTCTTCATTCTCTCTCTCTCATGAGCATATGGGAGTTTTCCAGAGACTTCCTGCCAGGCCACATC	CDDACDCCDDDBCCCDCCDCBBCBDCDCBDCCCDDBBCBCDBCCDBCBCBCBDBDBCCBDCBCCCCBCCACBDDDBBCCDCDADDBCDCACCCDCCDBDDD	MD:Z:101	PG:Z:BWA	RG:Z:20GAV.8	AM:i:37	NM:i:0	SM:i:37	MQ:i:60	OQ:Z:HHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHEHHHHHHHHHHHHHHHHHHHGHHHHHHHHHHH	UQ:i:0
+20GAVAAXX100126:8:5:7649:108990	1123	chr1	10004623	60	101M	=	10004910	362	GAAGCTATTTTCATAATAATCCTGAGATGATATTTGCTCTTCATTCTCTCTCTCTCATGAGCATATGGGAGTTTTCCAGAGACTTCCTGCCAGGCCACATC	*DDACBCADBD?ACBCC?ACBABBDCDCBDCCADBBBCBCDBCCDBCBC?CBDBDBCCBDCBCC>CBCBACBDDDABC at DCDADDBCDCA@CADCCD?DDD	MD:Z:0A100	PG:Z:BWA	RG:Z:20GAV.8	AM:i:37	NM:i:1	SM:i:37	MQ:i:60	OQ:Z:8HHHHGHIHIHIIHGIHFGHHGIHHHHHHHHHIHIHHHHHHHHHHHHHHFHHHHHHHHHHHHHHCHHHGDHHHHHGHHGHHHHHHHHHHGFHFHHHHGHHH	UQ:i:9
+20GAVAAXX100126:8:42:11066:118124	163	chr1	10004633	60	101M	=	10004938	405	TCATAATAATCCTGAGATGATATTTGCTCTTCATTCTCTCTCTCTCATGAGCATATGGGAGTTTTCCAGAGACTTCCTGCCAGGCCACATCACAACTGACC	@CBB at ABBDCBCDACCCCCCCCDCCBBDBDCBCCBABACACBDCBBCDBDABCABDBDCCBACACB@CCCACABC at BBB@ABBB?CC@@C?B?>D?DCBBA	MD:Z:101	PG:Z:BWA	RG:Z:20GAV.8	AM:i:37	NM:i:0	SM:i:37	MQ:i:60	OQ:Z:BCCCCCCCCBCCCCBCBBCBBBCCCBBBBBBBBBBBBBBBBBBBBBBBBBBBBBABBBAAB?A at BAABBAB@AAA at BA@?@A?A>A at A@@@@><@??@@@>	UQ:i:0
+20GAVAAXX100126:8:66:6823:31942	83	chr1	10004641	37	20S81M	=	10004294	-427	TCAAAGCTATTTTTATAATAATCCTGAGATGATATTTGCTCTTCATTCTCTCTCTCTCATGAGCATATGGGAGTTTTCCAGAGACTTCCTGCCAGGCCACA	#####################<>6=><99:26:>@=<:=<=;,<<<+5<;9=<=<===BB?B<BCBC?BBBBAADD at CB?=CBBCDDCCCBC=DCC=4:<<	MD:Z:81	PG:Z:BWA	RG:Z:20GAV.8	AM:i:0	NM:i:0	SM:i:37	MQ:i:29	OQ:Z:#####################?A;?A45553:?AD?544455-544-8<@;44444<EGGCG?HHGHDHHHGHGHHEHHDEGHHHHHHHHHHDHHHDECGG	UQ:i:0
+20GAVAAXX100126:8:25:19700:154119	99	chr1	10004642	60	101M	=	10004969	427	TCCTGAGATGATATTTGCTCTTCATTCTCTCTCTCTCATGAGCATATGGGAGTTTTCCAGAGACTTCCTGCCAGGCCACATCACAACTGACCTGACCCAGA	CBBBCDCDCBDCCCDDBBDBDDBCCDBDBDBCBCBCBCCBDCBCCCCBCCDCBDDDBBCBDCDADDBBDBBBCCCBBCACCBCACDADCDACDCDACCDDE	MD:Z:101	PG:Z:BWA	RG:Z:20GAV.8	AM:i:37	NM:i:0	SM:i:37	MQ:i:60	OQ:Z:HHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHIHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHH	UQ:i:0
+20GAVAAXX100126:8:21:4413:182078	147	chr1	10004700	60	9S92M	=	10004409	-382	GAGTTTTCCAGAGACTTCCTGCCAGGCCACATCACAACTGACCTGACCCAGAAGTACATCTGAGAATTCAGCTGTCTTCTATTAAGCCAGACATTAAAGAG	##########?:77BC<A?1<>??AAB8AA>@A@=CBAAB9CACBAB at AC@CDABA?C at CB?@AA at CCBCBBCACADC=CADDCDBCADBABCCBA?CBD@	MD:Z:92	PG:Z:BWA	RG:Z:20GAV.8	AM:i:23	NM:i:0	SM:i:23	MQ:i:60	OQ:Z:##########?364??8 at 9-<>;>@AA8;;?=@>@B>A?A6A@?A:@A at ABBBAABAA@BBAABBABBB at BABBB@BB:B at BCBBBBCBBBCCBBBCCBBB	UQ:i:0
+20GAVAAXX100126:8:1:11745:83846	83	chr1	10004719	29	101M	=	10004442	-377	ACATCACAACTGACCTGACCCAGAAGTACATCTGAGAATTCAGCTGTCTTCTATTAAGCCAGACATTAAAGAGATTTGCAAAAATGTCAAACAAGGCCACT	DDCBCCCDCCCBCCCCBCCCBDBDDACBBCDCCBDBDCDDBDBCCADCDDCCCDCDCBCBDBBBCDCDDCBDBCDDCBBDDDDCCADBDDCBDDCCC at BCC	MD:Z:101	PG:Z:BWA	RG:Z:20GAV.8	AM:i:0	NM:i:0	SM:i:0	MQ:i:37	OQ:Z:HHHGHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHH	UQ:i:0
+20GAVAAXX100126:8:26:5797:83894	99	chr1	10004750	60	101M	=	10005102	425	CTGAGAATTCAGCTGTCTTCTATTAAGCCAGACATTAAAGAGATTTGCAAAAATGTCAAACAAGGCCACTCTGCATGTAATAGGCTTATCTTAAAAATGAA	CDBBCDDCDBCCBDBBBDDBDCCDCDCBBCCCABCDCDDCDCDCDDBBCADDDCBBBCDDACDCCBBCADBDBBCCBCCBCC>CBADC at BDDCDB?>BAC6	MD:Z:101	PG:Z:BWA	RG:Z:20GAV.8	AM:i:37	NM:i:0	SM:i:37	MQ:i:60	OQ:Z:HHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHGHIHHHHHHHHHHHHHHHGHHHHHHHHHHHHHHHHHHHHHHHHHHHHHFHHEHHEHHEHHHHHFBBFFF5	UQ:i:0
+20GAVAAXX100126:8:43:4132:159191	675	chr1	10004784	29	95M6S	=	10005128	377	TTAAATAGATTTGCAAAAATGTCAAACAAGGCCACTCTGCATGTAATAGGCTTATCTTAAAAATGAATTAATATGTCTCTTGGTTGCCGTTTCTAATCAAA	<*89B,A<C<BC6;<@C at D@6==BDC8C?,B?@<@A=?44;;8=A9>A=@4@)(@@CCB=6/C>CB5>B6)7C<>7A;@?.7DA>CCB8BBABA#######	MD:Z:5G89	PG:Z:BWA	RG:Z:20GAV.8	AM:i:29	NM:i:1	SM:i:29	MQ:i:29	OQ:Z:8):5@,@;B:AA7 at 7>A=B?27;ABA7A<+A=>:BAC at 78==:7B9:@==8?))<>ACC:6-A?B?6=>4(1B==/A9==.4B?<AABABABAB#######	UQ:i:11
+20GAVAAXX100126:8:45:18787:46333	83	chr1	10004790	60	101M	=	10004482	-408	AGATTTGCAAAAATGTCAAACAAGGCCACTCTGCATGTAATAGGCTTATCTTAAAAATGAATTAATATGTCTCTTGGTTGCCGTTTCTAATACAATCCATC	EDCEECCCDDDDCCADBDDCBDDCBCBBCDCCBBCCACDCCDBBCDCCDCDCDDDDCCBDCDCDCCCCABCDCDCBADCBC;ADDDCCDCCCBDCDC at BDC	MD:Z:101	PG:Z:BWA	RG:Z:20GAV.8	AM:i:37	NM:i:0	SM:i:37	MQ:i:60	OQ:Z:HHHHHGHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHIHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHH	UQ:i:0
+20GAVAAXX100126:8:68:18251:192056	99	chr1	10004792	60	101M	=	10005081	362	ATTTGCAAAAATGTCAAACAAGGCCACTCTGCATGTAATAGGCTTATCTTAAAAATGAATTAATATGTCTCTTGGTTGCCGTTTCTAATACAATCCATCTG	CCCBCCCDDDDCBBBCDDACDCCBBCADBDBBCCBBCDCCCCBCDCCBCDCDDDDCBDDCDBDCCCBCBDBDDBCCD at BC;CDDBDCDCCACDCCCDCCED	MD:Z:101	PG:Z:BWA	RG:Z:20GAV.8	AM:i:37	NM:i:0	SM:i:37	MQ:i:60	OQ:Z:HHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHGHHHHHHHHHHHHHHHGHHHHHHHHHHHHHHHHHHHHHHH	UQ:i:0
+20GAVAAXX100126:8:42:4321:53069	147	chr1	10004795	60	101M	=	10004580	-315	TGCAAAAATGTCAAACAAGGCCACTCTGCATGTAATAGGCTTATCTTAAAAATGAATTAATATGTCTCTTGGTTGCCGTTTCTAATACAATCCATCTGCCT	@C at EDBDAC?AC<BDBBBD at 7ACA=BB at CDAAAC@CDBBCBCCDCDCAC?:DCBCD at C@A@?@><?BCDCC at DC?D;ADECCDBDCAABCCCBBB at AABC@	MD:Z:101	PG:Z:BWA	RG:Z:20GAV.8	AM:i:37	NM:i:0	SM:i:37	MQ:i:60	OQ:Z:<@AAA at B@@@@B<@@@BBBB9B at A<B at BABAB@BBBBBBBBBBBBBBBCCCCBACCABCCACAC at CBBBBBABB>CCBBCCBCCCCBCCCBCCCBCBCCCB	UQ:i:0
+20GAVAAXX100126:8:27:3628:73265	611	chr1	10004826	60	35M66S	=	10005114	346	GTAATAGGCTTATCTTAAAAATGAATTAATATGTCTCTTGGTTGCCGTTTCTAATACAATCCATCTGCCTCAGACTCCCAAAGTCCTAAGATTATAGGTAT	1405==>9;?<+?>@==<<>>=<=#############################################################################	MD:Z:35	PG:Z:BWA	RG:Z:20GAV.8	AM:i:37	NM:i:0	SM:i:37	MQ:i:60	OQ:Z:51155455555,44444554??>?#############################################################################	UQ:i:0
+20GAVAAXX100126:8:21:16295:166486	163	chr1	10004833	60	101M	=	10005120	387	GCTTATCTTAAAAATGAATTAATATGTCTCTTGGTTGCCGTTTCTAATACAATCCATCTGCCTCGGCCTCCCAAAGTCCTGAGATTATAGGTATGAGCCGC	@BCBAAACACDDDBCCCDDCCDDCCBBBDBDCBC at BA?A:@BCCBCDDCAACD at CDBBCB@AC@:C=ACA at DCABA?@BA@;B at ACAB<B@@AAABBCA;A	MD:Z:101	PG:Z:BWA	RG:Z:20GAV.8	AM:i:37	NM:i:0	SM:i:37	MQ:i:60	OQ:Z:BBBBBCBCCCCCCCBCBBCBBBCBBBABBBBBBBABBABBAABBBBBBBABBBBBBAAAAA?AA?A@?@@@B@@@@>@@?@8@>?@?@>@?;?@>?>??>?	UQ:i:0
+20GAVAAXX100126:8:63:6148:94882	675	chr1	10004865	37	73M28S	=	10005252	421	GGTTGCCGTTTCTAATACAATCCATCTGCCTCGGCCTCCCAAAGTCCTGAGATTATAGGTATGAGCCGCTGCACCCGACCTAGCCTTTTCATATGGAGTCT	@?5??AB6>A;A71DC;@CABB9?C;CA60790,%=7/=?>BC=?8;;=665D=77:;483A:24A.0;73B#############################	MD:Z:73	PG:Z:BWA	RG:Z:20GAV.8	AM:i:0	NM:i:0	SM:i:37	MQ:i:29	OQ:Z:B=4=?BB>7?;@62BB:AB?AB5;B9A at 3.2650(?;0 at C?AB9A975>175B?32945/5 at 80/?/5811@#############################	UQ:i:0
+20GAVAAXX100126:8:42:16609:191180	163	chr1	10004875	60	101M	=	10005207	432	TCTAATACAATCCATCTGCCTCGGCCTCCCAAAGTCCTGAGATTATAGGTATGAGCCGCTGCACCCGGCCTAGCCTTTTCATATGGAGTCTCAGACAGTGA	@CCAAAA at BDCCCACCDCCDDC;CCDEBCDDDDC at A>CABBBCCACCCCBACCACBC;BCABB?CB5CBCBBC at ACBBCAAABBACAB:BBA:AD?BD at DD	MD:Z:101	PG:Z:BWA	RG:Z:20GAV.8	AM:i:37	NM:i:0	SM:i:37	MQ:i:60	OQ:Z:BCBCCCCCCCCCCCBCBCCCBCBBCCCBBCCBBBABCBBBBABBBBBBB?BBBBBABBBABAAAB@@BABAAAB at AAA@B at B@A@@<A7@@A4?@A=A=BB	UQ:i:0
+20GAVAAXX100126:8:8:2524:114198	675	chr1	10004891	29	35M66S	=	10005259	428	TGCCTCGGCCTCCCCACGTCCTGCGATTATAGGTATGAGCCGCTGCACCCGGCCAAACCATTTCGTATGGAGTCAAAATCCATGAAGTTCATGCAATCTAT	@:0?B::=4(6AB:)A#####################################################################################	MD:Z:14A1A6A11	PG:Z:BWA	RG:Z:20GAV.8	AM:i:29	NM:i:3	SM:i:29	MQ:i:29	OQ:Z:A60=B;B=2)2 at B=*@#####################################################################################	UQ:i:12
+20GAVAAXX100126:8:25:3804:30880	83	chr1	10004891	60	101M	=	10004579	-412	TGCCTCGGCCTCCCAAAGTCCTGAGATTATAGGTATGAGCCGCTGCACCCGGCCTAGCCTTTTCATATGGAGTCTCAGACAGTGAAATTCAGTCAATATAT	#DDDD;CCCC at BCCDDDABCCCBDBBDCCCDBA>CCBDBC;BCCBB at CC;BBCCCCBCCDDDDBCCCCBBDADCDBDBBBDACBDDCDDBDADCDCCACCC	MD:Z:101	PG:Z:BWA	RG:Z:20GAV.8	AM:i:37	NM:i:0	SM:i:37	MQ:i:60	OQ:Z:#HHHHHHHHHAGHHHHHHFHHHHHHIHHHHHHHDHHHHHHHHHHHHEHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHH	UQ:i:0
+20GAVAAXX100126:8:5:7628:108971	147	chr1	10004891	60	6S95M	=	10004623	-362	TCCATCTGCCTCGGCCTCCCAAAGTCCTGAGATTATAGGTATGAGCCGCTGCACCCGGCCTAGCCTTTTCATATGGAGTCTCAGACAGTGAAATTCAGTCA	#######@B>25;8 at 8/:A;>B<><B887B;;B=9=@@>9;;>C at B;<B?<A=DD:ABC?BAABACCDCCCCCCCCDACCCBDCACD at CBCBCCB@A at CC@	MD:Z:95	PG:Z:BWA	RG:Z:20GAV.8	AM:i:37	NM:i:0	SM:i:37	MQ:i:60	OQ:Z:#######??;/6;7=2-:=:=@6?;A673:=9?==<<@?:=7=>?@?????@;BBABAB at BABBBBBBBBBBBBBCBBBBBBBCBCBBBBBCBBBCCCBCB	UQ:i:0
+20GAVAAXX100126:8:41:10214:75276	83	chr1	10004899	60	101M	=	10004590	-409	CCTCCCAAAGTCCTGAGATTATAGGTATGAGCCGCTGCACCCGGCCTAGCCTTTTCATATGGAGTCTCAGACAGTGAAATTCAGTCAATATATTTATAATG	DDCDDCDDDADCCCBDBADCCCDCACCCBDBC;BCCBBBCC;BBCCCDBCCDDDDBCCCCBBDADCDBCBBBDACBDDCDDBDADBDCCCCCDDCCCBBCC	MD:Z:101	PG:Z:BWA	RG:Z:20GAV.8	AM:i:37	NM:i:0	SM:i:37	MQ:i:60	OQ:Z:HHFHHHHHHHHHHHHHHFHHHHHHHHHHHHHHHHHHHHGHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHH	UQ:i:0
+20GAVAAXX100126:8:5:7649:108990	1171	chr1	10004910	60	25S76M	=	10004623	-362	TCCATCTGCCTCGGCCTCCCAAAGTCCTGAGATTATAGGTATGAGCCGCTGCACCCGGCCTAGCCTTTTCATATGGAGTCTCAGACAGTGAAATTCAGTCA	##########################B7:B8;C<88 at A740B@C=D:?C?<C;DD8<A??BCA;>ACDCCCCDCDCDACCCBDCBBD at CCCBCCBAB@CB@	MD:Z:76	PG:Z:BWA	RG:Z:20GAV.8	AM:i:37	NM:i:0	SM:i:37	MQ:i:60	OQ:Z:##########################A56<99@<<6<A740@@@<B at AA??B7BB at C@@@BBB>ACBBBBBBCBCCBBBCBBBCABBBBCBCBCBBBCBBB	UQ:i:0
+20GAVAAXX100126:8:42:11066:118124	83	chr1	10004938	60	101M	=	10004633	-405	CCCGGCCTAGCCTTTTCATATGGAGTCTCAGACAGTGAAATTCAGTCAATATATTTATAATGAATACTTTTTTTTTTGAGATGGAGTCTTGCTCTTGTCAC	DE;AADCCDCCCDDDCBCCCCCBDADCDADBCBDAC>ADBBCBCACADCBCACCC?CADBC?D at C;=>AAADDDDDCBCBCCBBDADCDCBCDCDCABBCC	MD:Z:70A30	PG:Z:BWA	RG:Z:20GAV.8	AM:i:37	NM:i:1	SM:i:37	MQ:i:60	OQ:Z:IHHGGHHHHHHHHHHGHHHHHHHHHHHHIHHHHHHHCGHIGGHGHGGHHIGIHIIFHGHGHGHFHCEEGGGHHHHHHHHHHHHHHHHHHHHHHHHHHHHHH	UQ:i:32
+20GAVAAXX100126:8:25:19700:154119	147	chr1	10004969	60	101M	=	10004642	-427	ACAGTGAAATTCAGTCAATATATTTATAATGAATACTTTTTTTTTTGAGATGGAGTCTTGCTCTTGTCACCCAGGCTGGAGTGCAATGGCGTGATCTTGGC	BD?@C at D@CCAC??DCCAC@<@DBABAADD at CDC<CD=CDBDCDDDCBDCACBEAC;ECA@>>AA>BCACCCEDBCCDCDBDCCBDCBB;ACBC@@ABCC@	MD:Z:39A61	PG:Z:BWA	RG:Z:20GAV.8	AM:i:37	NM:i:1	SM:i:37	MQ:i:60	OQ:Z:?B;<B@@BBAABB at AB@BB?=?ABBAABBBBBBB>BBCBBBBCBBCCBCBBBBCBBCCBCCCCABCBC>BBBCCBCBCCBCCCCCCCCCCCCCBCCCCCCB	UQ:i:35
+20GAVAAXX100126:8:48:10519:110723	99	chr1	10004994	60	101M	=	10005311	417	ATAATGAATACTTTTTTTTTTGAGATGGAGTCTTGCTCTTGTCACCCAGGCTGGAGTGCAATGGCGTGATCTTGGCTCACTGCAACCTCCGCCTCCCAGGC	CCCBCCCDCCADDDDDD;>:?>:C@<<7:==;=;=???A@>BBBABBCCCB at BC8CCB?@BC>B:5<:7;9<9;5B<BCAA?B at DACDBC;CCD>CCDDE@	MD:Z:14A86	PG:Z:BWA	RG:Z:20GAV.8	AM:i:37	NM:i:1	SM:i:37	MQ:i:60	OQ:Z:HHHHHHGHHHHHHHHHHBCBCC=HD4555445444EDFFFEHHGHGHHHHHEHH:HHHCDGHCGB=<@;>54445H=HHHEEHEHHHHHHHHHHDHHHHHE	UQ:i:35
+20GAVAAXX100126:8:68:18251:192056	147	chr1	10005081	60	27S74M	=	10004792	-362	ATGTCGTGATCTTGGCTCACTGCAACCTCCGCCTCCCAGGCTCAAGCGATTCTCCTGTCTCAGCCTCCTGAGTAGCTGGAATTACAGGCATGGGCCACCAC	############################B99A at 9<AA;A@>?9BBA;<?B=C at AC@?C?@@9<@>=@@<BB?>BB@@CACBDCBACC>@AABBABA at BBC@	MD:Z:74	PG:Z:BWA	RG:Z:20GAV.8	AM:i:37	NM:i:0	SM:i:37	MQ:i:60	OQ:Z:############################?;;?<6???:@??<6?????;A?A?>A?B@@@A;@AA?A?:A@@=?B>>BABABB@@ABAA?AABABB>AB at B	UQ:i:0
+20GAVAAXX100126:8:1:6636:49601	99	chr1	10005102	29	101M	=	10005477	440	ATTCTCCTGTCTCAGCCTCCTGAGTAGCTGGAATTACAGGCATGGGCCACCACGCCCGGCTAATTTTTGTGTATTTAGTAGAGATGGGGGTTTCACTATGT	CCC at DBCDBCBDBCCBBDBBDBDCBCCBDBCDDCDCACCCBCCBCCBBCABCA;BBB;CBDCDCDDDDB at ABCCDDCCCCCDCDCBCCCC?DDCDADD at DD	MD:Z:101	PG:Z:BWA	RG:Z:20GAV.8	AM:i:29	NM:i:0	SM:i:29	MQ:i:29	OQ:Z:HHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHEGHHHHHHHHHHHHHHHHHHHAHHHHHHHDHH	UQ:i:0
+20GAVAAXX100126:8:26:5797:83894	147	chr1	10005102	60	27S74M	=	10004750	-425	GCAACATCCGCCTCCCAGGCTCAAGCCATTCTCCTGTCTCAGCCTCCTGAGTAGCTGGAATTACAGGCATGGGCCACCACGCCCGGCTAATTTTTGTGTAT	############################B865235A?;>>C;9A:>@)?C7<=@>C899CC28)5B??:CB at CA<8/B>8B;@8@>B:CC?CCCB?@@BC@	MD:Z:74	PG:Z:BWA	RG:Z:20GAV.8	AM:i:37	NM:i:0	SM:i:37	MQ:i:60	OQ:Z:############################?161316B;;<=B99=6<;*;A<9<>:B;6:BB58)8BA>9BA>B at 942B9>B;><>>A?BB?BBCBB?BBBB	UQ:i:0
+20GAVAAXX100126:8:27:3628:73265	659	chr1	10005114	60	42S59M	=	10004826	-346	CATCCAAGCACCCACTCCAAGGCTCAAGCAATTCTCCTGTCTCAGGCTCCTGAGTAGCTGCAATTACAGGCATGGGCCACCACGCCCGGCTAATTTTTGTG	###########################################C at 3=3<=>C<&><@C@*'8B9;:'>@8?:BCBBC<,0CA;C9&0/1>9C.CB?@?9A?	MD:Z:3C14G40	PG:Z:BWA	RG:Z:20GAV.8	AM:i:37	NM:i:2	SM:i:37	MQ:i:60	OQ:Z:###########################################?>172:>@B:(;;BA@,';B;@9';>6>9?BABB9)3CBCC9)204;;B,BC??><=>	UQ:i:24
+20GAVAAXX100126:8:21:16295:166486	83	chr1	10005120	60	101M	=	10004833	-387	CCTGAGTAGCTGGAATTACAGGCATGGGCCACCACGCCCGGCTAATTTTTGTGTATTTAGTAGAGATGGGGGTTTCACTATGTTGGCCAGGCTGGTCTCGA	DDDCDACDCCCCBDCDCCCDBBBCCBBBCBCCBC;BCC;BBCCDBBDDDCACACCDDCCACCBCBCCBBBBADDDBBCCCCADCBBCBDBBCCCADCB:BC	MD:Z:101	PG:Z:BWA	RG:Z:20GAV.8	AM:i:37	NM:i:0	SM:i:37	MQ:i:60	OQ:Z:HHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHGGHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHH	UQ:i:0
+20GAVAAXX100126:8:43:4132:159191	595	chr1	10005128	29	66S34M1S	=	10004784	-377	GTCTGGGCTCACTGCAACCTCCGCCTCCCAGGATCAAGCGATTCTCCTGTCTCAGCCTCCTGAGTAGCGGGAATTAAAGGCATGGGCCCCCACGCCCGGCG	###################################################################################################4.	MD:Z:2T7C11A11	PG:Z:BWA	RG:Z:20GAV.8	AM:i:29	NM:i:3	SM:i:29	MQ:i:29	OQ:Z:###################################################################################################A7	UQ:i:6
+20GAVAAXX100126:8:48:2299:12648	99	chr1	10005135	60	101M	=	10005519	438	TTACAGGCATGGGCCACCACGCCCGGCTAATTTTTGTGTATTTAGTAGAGATGGGGGTTTCACTATGTTGGCCAGGCTGGTCTCGAACTCCTGACCTCATG	9DC?CCCCCCBCABBCABCA;BBB;CBDCDCDDDDBA@?CCD at CCBCC@:DC at CCCC9@DBCADCCBC@:==;;=BABA;:>?:69A9A=?=AC:A=?BAD	MD:Z:101	PG:Z:BWA	RG:Z:20GAV.8	AM:i:37	NM:i:0	SM:i:37	MQ:i:60	OQ:Z:IHHHHHHHHHHHIHHGHHHHHHHHHHHHHHHHHHHHGGEHHHFHHHHHDBHHFHHHHBFHHHHHHHHHD at BABBAGGFFB;DA at D:D at DAA?GGBF>DDGH	UQ:i:0
+20GAVAAXX100126:8:42:16609:191180	83	chr1	10005207	60	101M	=	10004875	-432	CAGGCTGGTCTCGAACTCCTGACCTCATGATCCACCTGCCTCAGCCTCCCAAAGTGCTGGAATTACAGGCGTGAGCCACTGTGCCTGGCCTATAATGAATA	DBC?CDCADCD;BDBCACCB at 9CCDB?B=<ACB3CCCB at CDBDBCCCCCBDDCABBCCB@DCDCABCBB;ACBDBCBACCACBCCCBBCCCCCDCCBBBCC	MD:Z:101	PG:Z:BWA	RG:Z:20GAV.8	AM:i:37	NM:i:0	SM:i:37	MQ:i:60	OQ:Z:HGHEHHHHHHHHHHGHDHHFFBHHHHDFDBDHH/HHGHFHHHHHHHIHHHHHHHGHHHHIHHHHGHHHHHHHHHHHHFHHHHHHHHHHHHHHHHHHHHHHH	UQ:i:0
+20GAVAAXX100126:8:63:6148:94882	595	chr1	10005252	29	66S35M	=	10004865	-421	TGGCAGTTTCATTATGTTGGCCAGCCTGGTCTCAAACTCCTGACCTCATGATCCACCTCCCTCAGCCTCCCAAAGTGCTGGATTTCCAGGCGTGAGCCACT	#####################################################################################################	MD:Z:16A2A15	PG:Z:BWA	RG:Z:20GAV.8	AM:i:0	NM:i:2	SM:i:0	MQ:i:37	OQ:Z:#####################################################################################################	UQ:i:4
+20GAVAAXX100126:8:8:2524:114198	595	chr1	10005259	29	40S61M	=	10004891	-428	GAACTCTTGCCCTCATGATCCACCTGCCTCAGCCTCCCAAAGTGCTGGAATTACAGGCGTGAGCCACTGTGCCTGGCCTATAATGAATACTTTTTAATATT	#########################################;<=7>7=>-A9;:<<;7:===:7=<<<:<:7<<,99=</:=978<@@=>>>?>=>?5>;1	MD:Z:61	PG:Z:BWA	RG:Z:20GAV.8	AM:i:29	NM:i:0	SM:i:29	MQ:i:29	OQ:Z:#########################################A=A9A:AA/F=@===444444444544454555/5444/55=9:=CF5AA4454444555	UQ:i:0
+20GAVAAXX100126:8:48:10519:110723	147	chr1	10005311	60	101M	=	10004994	-417	TTTAATATTCTCTTTGTTTCTGTCCACAGCAAGAATCTTTATTTCCTGAGACCTTTTGTAGCAGATTATTTTCCCTCAGTTTCTTGCCCTTAAGAGTCTTC	DE?BC at ABCA?A=CDAC?A at B@CB:9BACC at CCB>BABCCBDDDCBD:CB:DBDBDABBABACA>A?CDDDCCCDCBDAAECCCDCC8BDCBCBC??BCB@	MD:Z:101	PG:Z:BWA	RG:Z:20GAV.8	AM:i:37	NM:i:0	SM:i:37	MQ:i:60	OQ:Z:BAB<@B=AA@>==@BA@=;?BA at A:3B at BA@AB@@?@BBBBBBBB at CC@B<BAB?CBCB at BBBBCCABBBBBABCBBBB?CBBACCB=BCCCCCBBCBCCB	UQ:i:0
+20GAVAAXX100126:8:22:15343:70426	675	chr1	10005335	37	77M24S	=	10005751	450	CACAGCAAGAATCTTTTTTTCCTGAGACCTTTTGTAGCAGATGATTTTCCCTCAGTTTCTTGCCCGTAAGAGTCTTCGATTCTCCTCTGAGCAGAGGTTTG	-,&@>-A2A(;A3;9B*ACB8A8;B+A&;>B>81:=/852?97481CB=2=4+*)A)CBC/++@)%>.?''8C3C@#########################	MD:Z:16A25T22T11	PG:Z:BWA	RG:Z:20GAV.8	AM:i:0	NM:i:3	SM:i:37	MQ:i:29	OQ:Z:*((?<-?/?(:@4=6@*>C at 4@37@*>(8;@;7/9 at 1<72@;81<1@?>/?1*)(<)@B@/*+@))@.:'(1 at 2A?#########################	UQ:i:35
+20GAVAAXX100126:8:43:10736:78356	611	chr1	10005394	60	35M66S	=	10005705	411	TTGCCCTTAAGAGTCTTCGGTTCTCCACAGATAAGAGATTTGCTTTTGATATTTCCTCGACCTGCTCATAAGGATTTCATTATAACTTCTGGGTGCAATCT	?</3>################################################################################################	MD:Z:35	PG:Z:BWA	RG:Z:20GAV.8	AM:i:37	NM:i:0	SM:i:37	MQ:i:60	OQ:Z:AA7>A################################################################################################	UQ:i:0
+20GAVAAXX100126:8:61:2951:38254	163	chr1	10005434	60	96M5S	=	10005758	424	TGCTTTTGATATTTCCTCGACCTGCTCATAAGGATTTCATTATAACTTCTGGGTGCAATCTTTAGGAGAGTTTGCAAAACAGTCTTTTTTTTTTTTGTAAT	@BBC??@ACCBCB at CDEC;CBDDCCDCCDCDCCCBBAABBBACCBBDCBD at CD>CCCDCB=CC;CD at ACC@DD?ABBBC@@ACACCDCADBCD at D######	MD:Z:96	PG:Z:BWA	RG:Z:20GAV.8	AM:i:37	NM:i:0	SM:i:37	MQ:i:60	OQ:Z:BBCCCCCCBBBCCCCCCCCBCCBCCBCBCBBCBBBBBBBBBCBBBCBBBBBBB?BBBBBBCBB=BBB at AB@BB at BBA@@B?B?AB at AAAAAAABA######	UQ:i:0
+20GAVAAXX100126:8:21:9990:22806	163	chr1	10005457	60	72M29S	=	10005782	425	GCTCATAAGGATTTCATTATAACTTCTGGGTGCAATCTTTAGGAGAGTTTGCAAAACAGTCTTTTTTTTTTTGTAATGGAGTTTCGCTCCGTCACCCAGGC	@CCAABBCBCCCB at CCDBCCCDADCBECCCBCBCAB@C>BBCCDACCBCC at BC@CC?DCBADCBCC at CDCA##############################	MD:Z:72	PG:Z:BWA	RG:Z:20GAV.8	AM:i:37	NM:i:0	SM:i:37	MQ:i:60	OQ:Z:BCBCBBBBBCBBCCCBCCBBBBBBCBCBBBABBBABBBCBBBBBBBB?BABBBA at ACBBBBBBBBBBBBBB##############################	UQ:i:0
+20GAVAAXX100126:8:6:21370:119926	99	chr1	10005465	60	97M4S	=	10005757	389	GGATTTCATTATAACTTCTGGGTGCAATCTTTAGGAGAGTTTGCAAAACAGTCTTTTTTTTTTTTGTAATGGAGTTTCGCTCAGTCACCCAGGCTGAAGTT	>743?<?A>@CCBDADD?DBC=?BBCDC?DDDCCCCA>=?DDB<?DDDACC=BDDDD>>>????>;;2>:=4A>@?D56>B2:>98</58A;?;A=#####	MD:Z:82C14	PG:Z:BWA	RG:Z:20GAV.8	AM:i:37	NM:i:1	SM:i:37	MQ:i:60	OQ:Z:>@/<CEFFEFHHGHHHHFHHHEEHHHHHFHHHHHHGGAEDHHH?EHHHHHHAHHHHHCCCEEEEE448A@?:DCECH;CCF64CC;@6;4D>DBD?#####	UQ:i:25
+20GAVAAXX100126:8:1:6636:49601	147	chr1	10005477	29	35S66M	=	10005102	-440	ATGATTCCTCGGGCTGCGCATAAGGATCTCCTTTGAACTTCTGGGTGGAATCTTTAAGAGAGTCCTCAAAACAGTCTTTTTTTTTTTTGTAATGGAGTTTC	###############################BC*89BA>=(29CACC?:+8'%BC54 at 21,-6%5'85=CB?<7%0>EEEEEEEEEEAACBCCBAA?CCB@	MD:Z:12C8G6T0T0G35	PG:Z:BWA	RG:Z:20GAV.8	AM:i:29	NM:i:5	SM:i:29	MQ:i:29	OQ:Z:###############################?@);6 at A<;(.8BB at AA5+:'%?B54>/1+08,:(:4<BA=55%-:CCCCCCCCCCCCCCCBCCCBBBCB	UQ:i:79
+20GAVAAXX100126:8:67:2948:89942	99	chr1	10005484	60	101M	=	10005805	401	GGGTGCAATCTTTAGGAGAGTTTGCAAAACAGTCTTTTTTTTTTTTGTAATGGAGTTTCGCTCCGTCACCCAGGCTGAAGTGCAGTGGTGCAATCTTGGCT	CCC:CCCDCBDDDCCCDCDC at DDBBCDDDACCBBCDDD@@AA at A@A>=BDCBCCCBDDA;BABC6BBCABBCACB=@BBA;A?;?CCCCBCCDCCDD at D@.	MD:Z:101	PG:Z:BWA	RG:Z:20GAV.8	AM:i:37	NM:i:0	SM:i:37	MQ:i:60	OQ:Z:HHHGHHHHHHHHHHHHHHHHIHHHHHHHHHHHHHHHHHGGGGGGGGEAGHGHHGHGHHIHHEHHEGHHHHHHGHH=GFFFCFDBDHHHHIHHHHHHHGHG2	UQ:i:0
+20GAVAAXX100126:8:48:2299:12648	147	chr1	10005519	60	46S55M	=	10005135	-438	TTTAAACTTTGGGGTTAAACTTTTAGGAGAGTTTGCAAAAAATTCTTTTTTTTTTTTGTAATGGAGTTTCGCTCCGTCACCCAGGCTGAAGTGCAGTGGTG	###############################################ACCBDCDDDA=3>C9A?<@CDC;ABCC;=BBBBC?EDAABABD=CB?B?A@=C?	MD:Z:55	PG:Z:BWA	RG:Z:20GAV.8	AM:i:37	NM:i:0	SM:i:37	MQ:i:60	OQ:Z:###############################################B at BBBBBBBB<5?B;BA at BBBBBAAABB=@A at AB=CCA at ACCC?CC at CAB??B?	UQ:i:0
+20GAVAAXX100126:8:48:13575:23805	163	chr1	10005529	60	83M18S	=	10005856	427	TGTAATGGAGTTTCGCTCCGTCACCCAGGCTGAAGTGCAGTGGTGCAATCTTGGCTCACTGCAACCTCCGCCTCCAGGGTTCAAGGGATTCTTGTGCCCCA	@BABBBACCBACC>;BDBC;BABACABACBDCCDB;A<<B>ACA at BCBBA>?B at BC@C?BA at A=?B>@B9>CC?>A@<B46A###################	MD:Z:83	PG:Z:BWA	RG:Z:20GAV.8	AM:i:37	NM:i:0	SM:i:37	MQ:i:60	OQ:Z:BBBBBBBBAAABBABBBBBC at AABB@A?AABBABB=B??B?AB=BB@?A@@??AA?????B@?=@??@?@???@=??=?.5A###################	UQ:i:0
+20GAVAAXX100126:8:3:12608:19745	585	chr1	10005617	23	35M66S	=	10005617	0	TTCTTGTGCCCCAGCCTCCCAAGTAGTTGGGATTACAGGCGCGTGCCACCATGCCCGGCTAATTGTTGTATTTTTAGTAGAGGTGGGGTTTCACCATGTTG	#####################################################################################################	MD:Z:35	PG:Z:BWA	RG:Z:20GAV.8	AM:i:0	NM:i:0	SM:i:23	OQ:Z:#####################################################################################################	UQ:i:0
+20GAVAAXX100126:8:3:12608:19745	645	chr1	10005617	0	*	=	10005617	0	AAAAAAAAGAGTCAAGGTAATTCTGAGGACTTAGCCTGCATAAATGACGTACGGATTTGCCTTCAAATTACAAGAAAAAGACTCTAAGATATTACATTGAA	-C,BBACBB at 6>9<#######################################################################################	PG:Z:BWA	RG:Z:20GAV.8	OQ:Z:*@+ABCBAA=47;?#######################################################################################
+20GAVAAXX100126:8:46:11003:55063	99	chr1	10005652	60	101M	=	10005971	396	CAGGCGCCCGCCACCACACCTGGCTAATTGTTGTATTTTTAGTAGAGATGGGGTTTTACCATGTTGCCCAGGCTGATCTCAACTCCTTTTTTTTTGAGACA	CCBAC;CCB;BBCABCACABDBCBDCDCDBB@@@ACDDD at BCBCADCCCBCBC@ADDCABCCBCDBBBBCCBADBBCBCBCDAD at CDDDDDD?@@?D at DBE	MD:Z:101	PG:Z:BWA	RG:Z:20GAV.8	AM:i:37	NM:i:0	SM:i:37	MQ:i:60	OQ:Z:HHHHHHHHHHHHHHHHHHHHHHHHHHHHHHGGGFGHHHHGGHHHGHHGHHHGHFGHHHHHHHHHHHHHHHHGGHHFHHIHHHHHFHHHHHHHEGGCHDHHH	UQ:i:0
+20GAVAAXX100126:8:43:10736:78356	659	chr1	10005705	60	101M	=	10005394	-411	GTTTACCATGTTGCCCAGGGTGATCTCAACTCCTGTTTTTTTGAGACAGAGTCTCGCTCTGTTGCCCAGGCTGGAGTATAGTGGCATGATCTCGGCTCACT	=@BA::A=C648=BD96>C'@4:(1?5:CD at CCA'3;*@?=C@=>C2<=>8BCD5>?B8@/9@/2@<+@?>CBAB=ACA79B@?@B=69A899BA?@4,?<	MD:Z:0T18C14T66	PG:Z:BWA	RG:Z:20GAV.8	AM:i:37	NM:i:3	SM:i:37	MQ:i:60	OQ:Z:=9@>2:>;B512BAB32<A)?36(0=2:?B?BB?*07)>=>C at 5=?-=9=>>BB8>A>9 at 2<A39A?*>=<A?@?=@B at 28@==?A8:;>75 at BA@>1';9	UQ:i:40
+20GAVAAXX100126:8:43:10431:27195	99	chr1	10005733	60	101M	=	10006098	428	ACTCCTTTTTTTTTGAGACAGAGTCTCGCTCTGTTGCCCAGGCTGGAGTATAGTGGCATGATCTCGGCTCACTGCAACCTCTGCCTCCCGGGTTCAAGCGA	CAC at CDDDDDDAAAADCCACCDCBBDB;AABCB at DBBBBACCBCBCAC@CCCCBBCBCCBC@@DB9CBBBB:@@@ADA at DBCCBCDBCC9??;?=>?<;6B	MD:Z:101	PG:Z:BWA	RG:Z:20GAV.8	AM:i:37	NM:i:0	SM:i:37	MQ:i:60	OQ:Z:HHHHHHHHHHHGGGGHHGHHHHHHHHHHGFHHHFHHHHHFHHHHHHFHFHHHHGHHHHHHGEFHHIHHGHFBDGFFHHFHHIHHHHHHHGDD<AA at A@@AD	UQ:i:0
+20GAVAAXX100126:8:22:15343:70426	595	chr1	10005751	29	66S35M	=	10005335	-450	GATTTTTAGAAACAATGGGGTTATAACCTGTTTCCCATGATAAACTAAACTCCTTTTTTTTTGAGACAGAGTCTCGCTCTGTTGCCCAGGCTGGAGTATAG	#####################################################################################################	MD:Z:35	PG:Z:BWA	RG:Z:20GAV.8	AM:i:0	NM:i:0	SM:i:0	MQ:i:37	OQ:Z:#####################################################################################################	UQ:i:0
+20GAVAAXX100126:8:6:21370:119926	147	chr1	10005757	60	3S98M	=	10005465	-389	AGTCTCGCTCTGTTGCCCAGGCTGGAGTATAGTGGCATGATCTCGGCTCACTACAACCTCTGCCTCCCGGGTTCAAGCGATTCTCTTGCCTTGGCCTCCTG	####D:C>A;6A8BAACAEA7BBA9<>9>8:@@A6@@=8;1BB;CCA at CA:;->C4 at A7<BA at B3BB;A=<EACCD at 9@CEBCCCECA@@3BB1??*AAB=	MD:Z:49G48	PG:Z:BWA	RG:Z:20GAV.8	AM:i:37	NM:i:1	SM:i:37	MQ:i:60	OQ:Z:####AAB<<83B7B>>ABBB7A?@:9?;:39A<?:>>>6:0A??BB>ACA>8(:@0A at 7=BBAB6BBC@:=C>BCB?@@BC at CACCBCA>1@@1>@*@AA<	UQ:i:12
+20GAVAAXX100126:8:61:2951:38254	83	chr1	10005758	60	101M	=	10005434	-424	TCGCTCTGTTGCCCAGGCTGGAGTATAGTGGCATGATCTCGGCTCACTGCAACCTCTGCCTCCCGGGTTCAAGCGATTCTCTTGCCTTGGCCTCCTGAGTA	B<CDDCDADCCCBCDCBCCCBDACCCDACBBBCCBCBCD;BBCDBBCCBBDBCCDCCBCCDCC;BBADDBDDB;BCDDCDCDCBCCDCBBCCDCCCBB at CC	MD:Z:101	PG:Z:BWA	RG:Z:20GAV.8	AM:i:37	NM:i:0	SM:i:37	MQ:i:60	OQ:Z:GHHHHHHHHHHHGHHHHHHHHHHHHHHHHHHHHHHHFHHHGHHHHGHHHHHIHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHH	UQ:i:0
+20GAVAAXX100126:8:21:9990:22806	83	chr1	10005782	60	101M	=	10005457	-425	ATAGTGGCATGATCTCGGCTCACTGCAACCTCTGCCTCCCGGGTTCAAGCGATTCTCTTGCCTTGGCCTCCTGAGTAGCTGGGACTACGGGCACATGCCAT	ADBBDCCCCCA9DCD;CBCDBCCCBBDBCCDCCB>C>CC;BBA at DBDDB;>CDDCDCDCBBCDCBBCCDCCCBDACDBCCBBBBCCB;BBBBCCCCCABCC	MD:Z:101	PG:Z:BWA	RG:Z:20GAV.8	AM:i:37	NM:i:0	SM:i:37	MQ:i:60	OQ:Z:GHGHHHHHHHG=HHHHHHHHHHHHHHIHHHHHHHDHCHHHHHHEHHHHHHEHHHHHHHHHGHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHH	UQ:i:0
+20GAVAAXX100126:8:67:2948:89942	147	chr1	10005805	60	20S81M	=	10005484	-401	GTGGCATGATCTCGGCTCCCTGCAACCTCTGCCTCCCGGGTTCAAGCGATTCTCTTGCCTTGGCCTCCTGAGTAGCTGGGACTACGGGCACATGCCATCAT	#####################@A=;@>=BB at AA5<@:@CA>=@ABC:<BC>CBCBC<CABBB<@>@@B?BDACBBB at CCB@>CB;CCABBBCCBBABBBC@	MD:Z:81	PG:Z:BWA	RG:Z:20GAV.8	AM:i:37	NM:i:0	SM:i:37	MQ:i:60	OQ:Z:#####################?=<6?==@>A?=4?>?@BB?:?=?B=??B at BAB?B?AAABB?AAAAA=BBBB?BA=BBB<<BABBBBBABBBBBBBBBBB	UQ:i:0
+20GAVAAXX100126:8:45:17313:6715	163	chr1	10005854	60	92M9S	=	10006154	400	GAGTAGCTGGGACTACGGGCACATGCCATCATGCCCGGCTAATTTTTGCATTTTTAGTAGGGACGGGGTTTCACCATGTCGGCCAGGATGGTCTTGATCTC	@BB@@AACBCCCACCA;CBBCACCBACCCBCCBBBB9BAABCCCACCCAC?CCADBBCBBACB at 9C>C at CBCD?BBAACA8=BBA<B:6<@##########	MD:Z:92	PG:Z:BWA	RG:Z:20GAV.8	AM:i:37	NM:i:0	SM:i:37	MQ:i:60	OQ:Z:BCCBCBCCCCCBCBBBBBABBBBBAABBBBBBBBBBBBBABBBBBBBBAAABBBAAA?AAAB at B@A at B8AABBABB@A?A@=@A?6?766?##########	UQ:i:0
+20GAVAAXX100126:8:48:13575:23805	83	chr1	10005856	60	101M	=	10005529	-427	GTAGCTGGGACTACGGGCACATGCCATCATGCCCGGCTAATTTTTGCATTTTTAGTAGGGACGGGGTTTCACCATGTCGGCCAGGATGGTCTTGATCTCCT	BDDCCDCCCBCCC;CCBCCBCCBCBCDBCCBCC;BBCCDCDDDDCBBCDDDDCDACCBBBB;BBBADDDBBCBCCAD;BBCBDBBCCBADCDCBCDCBCCC	MD:Z:101	PG:Z:BWA	RG:Z:20GAV.8	AM:i:37	NM:i:0	SM:i:37	MQ:i:60	OQ:Z:HHHHHHHHHGHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHH	UQ:i:0
+20GAVAAXX100126:8:43:16553:40365	99	chr1	10005967	37	101M	=	10006358	425	TCTGTCTGCCTCAGCCTCCCAAAGTGCTGGGATTACAGGCGTGAGCCACCTCACCCAGCCAAGTTAGTATGTGTTTAAAGATCACACTTGTAATCCTAGCA	CBC at CBDCBBDBCCBBDBBBCDDC@BBDBCCDCDCACCCB;BBDCBBCABCBCABBCCBBCDCBDCCBCCBBBADDCADCDCBCACADDCCCDCCCDD>DE	MD:Z:101	PG:Z:BWA	RG:Z:20GAV.8	AM:i:0	NM:i:0	SM:i:37	MQ:i:29	OQ:Z:HHHHHHHHHHHHHHHHHHHHHHHHFHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHIHHHIHHHHHFHHHGHHHHHHHHHHHHHHHHHHHHEHH	UQ:i:0
+20GAVAAXX100126:8:46:11003:55063	147	chr1	10005971	60	23S78M	=	10005652	-396	TGATCTCCTGACCTCGTGATCTGTCTGCCTCAGCCTCCCAAAGTGCTGGGATTACAGGCGTGAGCCACCTCACCCAGCCAAGTTAGTATGTGTTTAAAGAT	########################@=@=8><>?C96A88@=?<*;;BAB67C;>;4?:2;B<7=A95C;B@,BCBCCCACDBDCEBCBCACADCA??CBC@	MD:Z:78	PG:Z:BWA	RG:Z:20GAV.8	AM:i:37	NM:i:0	SM:i:37	MQ:i:60	OQ:Z:########################?;@>36>9<A;2?:4>>;<(:6>B at 6:A=672A89>B at 9@B<1B9?@)@BBACB at BBCBBCCBBBCCCCCCCCCBCB	UQ:i:0
+20GAVAAXX100126:8:26:2983:65747	99	chr1	10005981	29	79M22S	=	10006359	410	CCTCCCAAAGGGCTGGGATTACAGGCGTGAGCCACCTCACCCAGCCAAGTTAGTATGTGTTAAAAGATCACACTTGTAATCCTAGAACTTTGGGAGGCTGA	64911=?>?@*:=?>?@A@@:9==8'6==<=::<:@9>>=>>63;;<;<;<:<29@?6?:A;<A>;:;:;??=3>>=;#######################	MD:Z:10T50T17	PG:Z:BWA	RG:Z:20GAV.8	AM:i:29	NM:i:2	SM:i:29	MQ:i:29	OQ:Z:=9==84454404455FFFFF55445+444444554C:CAC??;7?55555555.5CC3CCG4 at GA44455CCC8AA??#######################	UQ:i:35
+20GAVAAXX100126:8:61:18274:143796	163	chr1	10006062	60	92M9S	=	10006396	429	CTAGCACTTTGGGAGGCTGATGTAGGAGGATCACTTGAAGCCAGGGGTTTGAGCCCAGCCTGGGCAACATAAAGATTACAGGCGTTAGCCACTAAGCCTGG	>A:@?@?A?C?/>9A:AB;??:-7@@A<;B9<C69>1'<B8>8C.>>B;C7=A%?>@@B9(8C<;:?@@A/A8::57::=0,C1%%?>:C@##########	MD:Z:53A31G6	PG:Z:BWA	RG:Z:20GAV.8	AM:i:37	NM:i:2	SM:i:37	MQ:i:60	OQ:Z:;>;@CC@@<A at 1@;@;A>7;>7'5>??8:@79B79 at 2)?B<>8A4><>;@9==(99>;A8'5B=96 at A;@0:4:737;9<.0A5%%<<<AB##########	UQ:i:8
+20GAVAAXX100126:8:62:16536:90438	99	chr1	10006082	60	101M	=	10006385	337	TGTAGGAGGATCACTTGAAGCCAGGGGTTTGAGACCAGCCTGGGCAACATAAAGATTACAGGCGTGAGCCACTGAGCCTGGACCCTTCCCTCTCTTAATCT	<<>5 at A>@>=<==<@<>7?=>=>=977=;<=:<;:;<<9:=;:::@A=??;<<=<<;99<=7:6<?74;?=8>5>A5:@:617/8>?;><=3?9<>?5>8B	MD:Z:101	PG:Z:BWA	RG:Z:20GAV.8	AM:i:23	NM:i:0	SM:i:37	MQ:i:60	OQ:Z:FFDDFCACA>55544=<9<<DDAD=444544544455555>><<=CCCCC444444555445544C98>C><A9AG;=D<53534 at A?A>>7A<4 at C9A<D	UQ:i:0
+20GAVAAXX100126:8:43:10431:27195	147	chr1	10006098	60	37S64M	=	10005733	-428	CCTAGCACTTTGGGAGGCTGATGTAGGAGGATCACTTGAAGCCAGGGGTTTGAGACCAGCCTGGGCAACATAAAGATTACAGGCGTGAGCCACTGAGCCTG	######################################B:2A5>ACC;CA8>>@9A8C<B8>@@34BBBB at CCC?CD?7A:CA:@;B?BCBBBBABABBB@	MD:Z:64	PG:Z:BWA	RG:Z:20GAV.8	AM:i:37	NM:i:0	SM:i:37	MQ:i:60	OQ:Z:######################################@74 at 16@AA at A@:;=>4@<@>A:@AA94B at AA@BBA>BB>0 at 6BA?A9BABBB?BBBBBBBAB	UQ:i:0
+20GAVAAXX100126:8:3:10732:109401	163	chr1	10006103	60	101M	=	10006447	444	CAGGGGTTTGAGACCAGCCTGGGCAACATAAAGATTACAGGCGTGAGCCACTGAGCCTGGACCCTTCCCTCTCTTAATCTGTTCAGGCTGCTATAACATAA	@BBBABBAABCBA at CCCBCABBCACDADCCDDCCBAA;;BCB9 at 7>CCCC?AC at CCADCAB>BBB@?CBD:E@@@BBAAC<AB at BCCA?A=;A9==>D;D=	MD:Z:101	PG:Z:BWA	RG:Z:20GAV.8	AM:i:37	NM:i:0	SM:i:37	MQ:i:60	OQ:Z:BABBBBACCBBAABBBBBB>BAB at BBBCBBBBBBBAB@>BBBA;9=ABBBB at BAABCBB@A?AB?=BB?BCB>??BB@@A<??B at A@BB==6?68:<@9A9	UQ:i:0
+20GAVAAXX100126:8:48:11905:175240	163	chr1	10006103	60	81M20S	=	10006478	475	CAGGGGTTTGAGACCAGCCTGGGCAACATAAAGATTACAGGCGTGAGCCACTGAGCCTGGACCCTTCCCTCTCTTAATCTGTTCAGGCTGCTATAACATAA	=7 at AA>BBC<B>58CAABAD at C51BCACBBEDA906>;8=AB9@<CCCCA8>B:CCB@<C61 at 88<98CA at EC><;@9BC#####################	MD:Z:81	PG:Z:BWA	RG:Z:20GAV.8	AM:i:37	NM:i:0	SM:i:37	MQ:i:60	OQ:Z:<0@@@??AA9A;5>B@?B?B?B60 at ABBAACB@608C@;@ABA;?BABB>>=A<ABA99B62>729=8A>ABB>;;?9AA#####################	UQ:i:0
+20GAVAAXX100126:8:46:19844:141004	99	chr1	10006137	60	95M6S	=	10006468	401	TTACAGGCGTGAGCCACTGAGCCTGGACCCTTCCCTCTCTTAATCTGTTCAGGCTGCTATAACATAATACTGTAGGCTGGCTACAGAGGTTTTAAAATTTG	CDC?CCCA;CBDCBBCADBDCBBD@=><=<@;<A@@=@BCDC;CBA:9 at 9<=79=BBDBC?AA@::<:99<;:8:)8<:6-+77:??;$A@@?:#######	MD:Z:88T6	PG:Z:BWA	RG:Z:20GAV.8	AM:i:37	NM:i:1	SM:i:37	MQ:i:60	OQ:Z:HHHHHHHGHHHHHHHHHHHHHHHHGAAADDEBEGGEEEHHHHBHHFBBFB55555HHHGHEFHE==<=<<55445255552-554DA at .DAAA?#######	UQ:i:3
+20GAVAAXX100126:8:67:19765:57485	163	chr1	10006149	11	101M	=	10006437	382	GCCACTGAGCCTGGACCCTTCCCTCTCTTAATCTGTTCAGGCTGCTATAACATAATACTGTAGGCTGGCTACAGAGTTTTTAAAATTAGTATTTTTTTTTT	@BBB?BACBBCD at BCACCDCBCCCBDBDCCDCBDB@A?BBCBDC?DCDCD?CD at DCBACB?BAACC=CA;:=93.:,3 at BB2B@A>B34;82ABB>DCBEC	MD:Z:101	PG:Z:BWA	RG:Z:20GAV.8	AM:i:11	NM:i:0	SM:i:11	MQ:i:11	OQ:Z:BBBBBBBBBBBBABABBBBBBBBABBBBBBBBBBBABCBBBBBBABBBBBBBBBBAABAA?A at AB?@A?5<941,8'3<@@1=>>:>32280=@?;@>A at B	UQ:i:0
+20GAVAAXX100126:8:45:17313:6715	83	chr1	10006154	60	101M	=	10005854	-400	TGAGCCTGGACCCTTCCCTCTCTTAATCTGTTCAGGCTGCTATAACATAATACTGTAGGCTGGCTACAGAGTTTTTAAAATTAGTATTTTTTTTTTTTTTG	<>A@??BA at B?CCD>CCCACDCDCDCDCCADA at DBB;CBAB at CDCAC?DCC at CCAC?B at C@@A@?=@;??>DDDDCDDDCDBA<:;?>>??>>>DDDBDCC	MD:Z:101	PG:Z:BWA	RG:Z:20GAV.8	AM:i:37	NM:i:0	SM:i:37	MQ:i:60	OQ:Z:<DDDDAFFGFEHHHCHHHEHHHHHHHHHHHHEFHHHBHIGIFHHHGHFHHHEHHHHEHFHEGGFFAG=FDFHHHHHHHHHHGFA@=EEEEEEEEHHHHHHH	UQ:i:0
+20GAVAAXX100126:8:22:5067:77679	1187	chr1	10006173	60	82M19S	=	10006497	424	CTCTTAATCTGTTCAGGCTGCTATAACATAATACTGTAGGCTGGCTACAGAGTTTTTAAAATTAGTATTTTTTTTTTTTTTGAGACTGAGTCTTTCTCTGT	@DBCAACCBDBACABCCBCB>BACBDACCABAB><;;7?@@A?C<=;;8>+665DC:0<?==B8@:2<CBA?CAC@=BD;@####################	MD:Z:82	PG:Z:BWA	RG:Z:20GAV.8	AM:i:37	NM:i:0	SM:i:37	MQ:i:60	OQ:Z:BBBBBBBBBBBBBBABBBAB<?ABABBAB@@@A?=>?<AAA@@A?<8:7:+4,5A at 8-9<><@:>35;@@B9@@A?=@A;?####################	UQ:i:0
+20GAVAAXX100126:8:22:5084:77687	163	chr1	10006173	60	81M20S	=	10006497	424	CTCTTAATCTGTTCAGGCTGCTATAACATAATACTGTAGGCTGGCTACAGAGTTTTTAAAATTAGTATTTTTTTTTTTTTTGAGACGGAGGCTTGCTCTGT	@DBC?ACCBDBBCACCCBDB?BCAACACCCDBCA??>=?<@=;C5;@@983<::DDC;AA>A>3813ADBACC<@BBABC#####################	MD:Z:81	PG:Z:BWA	RG:Z:20GAV.8	AM:i:37	NM:i:0	SM:i:37	MQ:i:60	OQ:Z:BBCCCBBBBBBABBBBBBBB>?B@@ABBBBBABB at AA@A?A==B::>@832<4<BBB7???@<33+7 at A@B@@<?@@B?A#####################	UQ:i:0
+20GAVAAXX100126:8:21:11247:101401	99	chr1	10006257	60	101M	=	10006514	345	ACGGAGTCTTGCTCTGTTGCCCAGGCTGGAGTGCAGTGGTGTGATCTCGGCTCACTGCAAGCTCCACCTCCCAGGTTCACACCATTCTCCTGCCTCAGCCT	CA:ADCCBDDBBDBDBBDBBBBCCCBDBCDCABBCCBBCBBBBDCBCB;CBDBCADBBC??BDBCCABDBBBCCCCDBCACACCCDBDBCDCCCDCDDCB8	MD:Z:39C61	PG:Z:BWA	RG:Z:20GAV.8	AM:i:23	NM:i:1	SM:i:23	MQ:i:60	OQ:Z:HHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHGHHHHHHHHHHHHHHHHHHHHHHHHHHHEEHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHI5	UQ:i:33
+20GAVAAXX100126:8:46:8850:165700	163	chr1	10006281	29	101M	=	10006624	443	GCTGGAGTGCAGTGGTGTGATCTCGGCTCACTGCAAGCTCCACCTCCCAGGTTCACACCATTCTCCTGCCTCAGCCTCCCGAGTAGCTGGGACTACAGGCG	@BBAABB at BBCC?ACACACCDBDB;CADBCADBB at AAA@ABB?BBBCCBCA?D?CAC?BC<CABBC?B>CBCD?AB?;BB6?C:9ACB?@7@=AA?B<>73	MD:Z:15C85	PG:Z:BWA	RG:Z:20GAV.8	AM:i:0	NM:i:1	SM:i:0	MQ:i:37	OQ:Z:BBABBBB>BBBB at CC?C=CBCBBBBBABBABBABAABBABBAA?BBBBAAB>AAAAB>AA>BAAAB at A;BBBB?AB=;@B==A39>A??=9=;>>@>4=26	UQ:i:32
+20GAVAAXX100126:8:43:16553:40365	147	chr1	10006358	29	66S35M	=	10005967	-425	GTGGTGTGAGCGCGGTTCACTGCAAGCCCCACCCCCCAGGTTCCCACCATCCCCCTGCCTCAGCCTCCCGAGTAGCTGGGACTACAGGCGCCTGCCACCAC	#############################################################################BA:8:8::2B420 at B@ABA at BBC@	MD:Z:35	PG:Z:BWA	RG:Z:20GAV.8	AM:i:0	NM:i:0	SM:i:0	MQ:i:37	OQ:Z:#############################################################################@@727537. at 8<. at A>ABB>BB at B	UQ:i:0
+20GAVAAXX100126:8:26:2983:65747	147	chr1	10006359	29	68S33M	=	10005981	-410	AGGTGCTTGAGCCCGCCCACATGCACGCTCCACATCCCGGTTGCACACCGTACCCCTCCCTCAGCATTCCGAGTAGCTGGGACTACAGGCGCCTGCCACCA	############################################################################################BB@?;7=@?	MD:Z:33	PG:Z:BWA	RG:Z:20GAV.8	AM:i:29	NM:i:0	SM:i:29	MQ:i:29	OQ:Z:############################################################################################BB@@70>=>	UQ:i:0
+20GAVAAXX100126:8:62:16536:90438	147	chr1	10006385	60	66S35M	=	10006082	-337	CCCTCCTCCCAGCTTCACTCCTTTCTCCTCCCTCAGCCTCCCGAGTAGATGGGACTACAGGCGCCTGCCACCACGCCGGGCTAATTTTTTTATTTTAGTAG	#####################################################################B4,B3?$6;63ACC at 9@DBDA;9?8C5?1:D@	MD:Z:35	PG:Z:BWA	RG:Z:20GAV.8	AM:i:23	NM:i:0	SM:i:23	MQ:i:60	OQ:Z:#####################################################################?5+ at 5>(:742 at BB>6>BBC?=6<5B6;1;CB	UQ:i:0
+20GAVAAXX100126:8:61:18274:143796	83	chr1	10006396	60	5S96M	=	10006062	-429	ACGCCGGGCTAATTTTTTTATTTTAGTAGAGACGGGGTTTCACCATGTTAGCCAGGATGGTCTCGATCTCCTGACCTCGTGATCTGCCGGCCTCGGCCTCC	######?9AB><<<=@<<A at B;>>@==B at B4;59*:@AB?A8;;;=>?@A>7.=,;2;=88<:4;<6<<=:;95:=:8>A?>>==;/7=/:@<7</:7=71	MD:Z:96	PG:Z:BWA	RG:Z:20GAV.8	AM:i:37	NM:i:0	SM:i:37	MQ:i:60	OQ:Z:######D=FGBB>>BAB>GDG<ADDDDFGF7544,5GGFAG:>@=@FDFFD5/5.57 at A@845554;?<?@@@3<<BFFFF445558<>2=4555044555	UQ:i:0
+20GAVAAXX100126:8:23:12774:197414	99	chr1	10006420	60	101M	=	10006790	437	AGACGGGGTTTCACCATGTTAGCCAGGATGGTCTCGATCTCCTGACCTCGTGATCTGCCGGCCTCGGCCTCCCAAAGTGCTGGGATTACAGGCGTGAGCCA	CCC?;CCCCDDBCABCCBBDCCBBCCCDCBCBBCB;CCBCBBCBDABDB;BBDCBDBBB;CBBDB;CBBDBBBCDDCABBDB>CDCDCACCCC;CCDDCDA	MD:Z:101	PG:Z:BWA	RG:Z:20GAV.8	AM:i:23	NM:i:0	SM:i:23	MQ:i:60	OQ:Z:HHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHGHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHGHHHHEHHHHHHHHHHHHHHHHHG	UQ:i:0
+20GAVAAXX100126:8:67:19765:57485	83	chr1	10006437	11	1S18M3I77M2S	=	10006149	-382	CGTTGGCCAGGATGCTCTCGTGGATCTCTTGACCTCGTAATCCGCCCACCTCCGCCTCCCAAAATGCTGGGGTTACAGGCATGAGCCACTGTGCCCGGCTT	<BEDCCD at DCC@CBCD;B9 at BCBCDCDCDCB=CCB6ACDCCC;BCCBBCCDC;BCCDCCBDDDCCBCCBBBADCBBDBBBCCBDBCBBCCACBCC;C at BDC	MD:Z:3A9G10C9G3T3G0G4G10G7A8G8C0A0C7	PG:Z:BWA	RG:Z:20GAV.8	AM:i:11	NM:i:17	SM:i:11	MQ:i:11	OQ:Z:HHHHHHHGHHHDHHHHBFGGFHHHHHHHHHH>HHFEHHHHGHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHH	UQ:i:456
+20GAVAAXX100126:8:3:10732:109401	83	chr1	10006447	60	101M	=	10006103	-444	ATGGTCTCGATCTCCTGACCTCGTGATCTGCCGGCCTCGGCCTCCCAAAGTGCTGGGATTACAGGCGTGAGCCACCACGCCCGGCCTAAAATTAGTATGTT	=ECBDC=4@=B;5>>=B at CCB9AC@BDCCBC;BBCCD;BBCCACBBDDDACBCBBBBCACBBDBB;?CBCBCBBCBB;BCC;BBCCCDDDCDCDACCA at DC	MD:Z:101	PG:Z:BWA	RG:Z:20GAV.8	AM:i:37	NM:i:0	SM:i:37	MQ:i:60	OQ:Z:@HHHHHCBFBD?9AA?HDHHEGHHGGHHHHHHHHHHHHHHHHEHGHHHHHHHHGHHHHGHHHHHHHGHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHH	UQ:i:0
+20GAVAAXX100126:8:46:19844:141004	147	chr1	10006468	60	30S71M	=	10006137	-401	TGAGCCAGGTTGGTCTCGATCTCATGACTGCGTGATCTGCCGGCCTCGGCCTCCCAAAGTGCTGGGATTACAGGCGTGAGCCACCACGCCCGGCCTAAAAT	###############################?9<'@A<:=9>8@:>;7C632<83.1;A=;000-8*?<B at 4@<-8B>;&9A>>BA9>>86>?CA;B at A>@	MD:Z:71	PG:Z:BWA	RG:Z:20GAV.8	AM:i:37	NM:i:0	SM:i:37	MQ:i:60	OQ:Z:###############################@4<&<?<9=A<7=78A9B92.=7.036B>>0032;+==?@0=907A;6(9 at 6=BB at A@8=;=B@=@?@;@	UQ:i:0
+20GAVAAXX100126:8:48:11905:175240	83	chr1	10006478	60	101M	=	10006103	-475	CGGCCTCGGCCTCCCAAAGTGCTGGGATTACAGGCGTGAGCCACCACGCCCGGCCTAAAATTAGTATGTTTTTTGTTGTACTTGTTTTTGTTTTTGTTTTT	/8,)09:AABA<>B>ADDACBACCB>AD>BBBBB9ACBDB>B at CBA;B at C;BB at BCD@DCDCDAC??<>??DDBADCACB>?@<???>?<?AAAAADBDDC	MD:Z:101	PG:Z:BWA	RG:Z:20GAV.8	AM:i:37	NM:i:0	SM:i:37	MQ:i:60	OQ:Z:551215FGGGGBEGAGHHHHHFHHHDGHEHHGHHGHHHHHDHDHHEHHFHHHHFIHHFHHHHHHHEEEEEEHHGHHHHHGEEEEEEEEEEECCCCHHHHHH	UQ:i:0
+20GAVAAXX100126:8:22:5067:77679	1107	chr1	10006497	60	101M	=	10006173	-424	TGCTGGGATTACAGGCGTGAGCCACCACGCCCGGCCTAAAATTAGTATGTTTTTTGTTGTACTTGTTTTTGTTTTTGTTTTTTTTTTGAGGCGGAGTTTCA	7D>DCCCBDCC at D>C;ABBCBCBCCBB9BCC;BBCCCDDDCDCDACBB?ABADDCADCAC9@@B?A@@AB at AAAAB?AAAADDDDDCBDBB;BBDADBCBC	MD:Z:101	PG:Z:BWA	RG:Z:20GAV.8	AM:i:37	NM:i:0	SM:i:37	MQ:i:60	OQ:Z:5HEHHHHGHHHGHEHHHGHGHHHHHHHGHHHHHHHHHHHHHHHHHHGGGGGGHHHHHHHHBGGGGGGGGGGGGGGGGGGGGHHHHHHHHHHHHHHHHHHHH	UQ:i:0
+20GAVAAXX100126:8:22:5084:77687	83	chr1	10006497	60	101M	=	10006173	-424	GGCTGGGATTACAGGCGTGAGCCACCACGCCCGGCCTAAAATTAGTATGTTTTTTGTTGTACTTGTTTTTGTTTTTGTTTTTTTTTTGAGGCGGAGTTTCA	*@DBCCCCDCCCDCC;ACBDBCBC at BB;A@@:BACCC?DDCDCDACBB?ABADDCADCACB@@B?A@@AB at AAAAB?AAAADDDDDCBDBB;BBDADBCBC	MD:Z:0T100	PG:Z:BWA	RG:Z:20GAV.8	AM:i:37	NM:i:1	SM:i:37	MQ:i:60	OQ:Z:2GHGHHHHHHHHHHHHHHHHHHHHFHHHFFFIHGHHHEHHHHHHHHGGGGGGHHHHHHHHHGGGGGGGGGGGGGGGGGGGGHHHHHHHHHHHHHHHHHHHH	UQ:i:9
+20GAVAAXX100126:8:21:11247:101401	147	chr1	10006514	60	12S89M	=	10006257	-345	GGATTACAGGCGTGAGCCACCACGCCCGGCCTAAAATTAGTATGTTTTTTGTTGTACTTGTTTTTGTTTTTGTTTTTTTTTTGAGGCGGAGTTTCACTCTT	#############@@A6 at A@>@;@@A:A at C<BBC at CDBC??BC at CDD;CC?CCAB6?CCAC=BBA;CDDDCADDEDDEEEEDCDDC;ABDACDAA@?BBD@	MD:Z:89	PG:Z:BWA	RG:Z:20GAV.8	AM:i:23	NM:i:0	SM:i:37	MQ:i:60	OQ:Z:#############?:=7 at 9?>>B@?@AB=@>A>BAABBA@@AB at ABA=ABBABBA1AABBB?BBB at BBBCBBBBCBBCCCCCCBCCBBCBCBCCB@CBBCB	UQ:i:0
+20GAVAAXX100126:8:46:8850:165700	83	chr1	10006624	37	101M	=	10006281	-443	TGGCGTGATCTTGGTTCACCACGACCTCTGCCTCCCGGGTTCAAGCGATTCTCCTGCCTCAGCCTCCTGAGTAGCTGGGACTACAAGCATGCACCACCATG	EDC;ADCCDADBA at ACB@CBC;BACCDCCBCCDCC;CCADDBDDB;?CDDCDCCCBCCDBDBCCDCCCBCACDBCCBBBBCCBBDDBBCCBBCCCCC at BCC	MD:Z:101	PG:Z:BWA	RG:Z:20GAV.8	AM:i:0	NM:i:0	SM:i:37	MQ:i:29	OQ:Z:HHHHHHHHHGHGGGGFHDHHHHHFHHHHHHHHHHHHHHHHHHHHHHFHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHH	UQ:i:0
+20GAVAAXX100126:8:22:6227:26566	163	chr1	10006730	60	83M18S	=	10006988	358	CTAATTTTGTATTTTTAGTAGAGACAGAGTTTCTCCATATTGGTCAGGCTGGTCTCGAACTCCCGACATCACGTGATCCACCTGCCTCAACGTCCATAAGG	@DBC@?BBBBCCBBCCCCADCCCCBCBCCBCCBDABAB9BBA?@?@@?A??=;7=?39@?81AA886:?>:>3687':A@?A###################	MD:Z:83	PG:Z:BWA	RG:Z:20GAV.8	AM:i:37	NM:i:0	SM:i:37	MQ:i:60	OQ:Z:BCCBCCBBCACBCBBBBB;CBBBACBABB?BBBBBBBB>BBA@;A?<=A:A>2:6;83>?7/?A=5<9<<:;5/55(:=?@?###################	UQ:i:0
+20GAVAAXX100126:8:2:2951:16973	99	chr1	10006763	60	101M	=	10007005	342	TCCATATTGGTCAGGCTGGTCTCGAACTCCCGACATCACGTGATCCACCTGCCTCAACCTCCAAAAGGGCTGGGATTACAGGTGCGAGCCACCTCGCCTGA	<<>7A<BA at BB@B;=;?=8==?<5 at A?C at AA9B?:=9@<49;6:<<786;??=@=CA at ACABBAA:;'69<;55:BAA?B@?<;95<:91178;::?A@:B	MD:Z:67T33	PG:Z:BWA	RG:Z:20GAV.8	AM:i:37	NM:i:1	SM:i:37	MQ:i:60	OQ:Z:GGGCGEGGGGGGGBE55555EDEEEGGGGGGGGGB?@DD?;=;@<=;=;@CEEEEGGGGGGGGGG44/4455544GGGGGCC??@<===824444GCGE=G	UQ:i:6
+20GAVAAXX100126:8:1:16535:116063	99	chr1	10006767	60	101M	=	10007127	436	TATTGGTCAGGCTGGTCTCGAACTCCCGACATCACGTGATCCACCTGCCTCAACCTCCAAAAGTGCTGGGATTACAGGTGCGAGCCACCTCGCCTGACCAA	CCBBCCCBCCCBAB@@BDB;DDA?BBB;DACCBCA5 at BACBBCABC>BBCBCDABDBBADDD>:BBDB at CCCD@AACCC=B4BCBCCACDC;CCDCDBC<6	MD:Z:101	PG:Z:BWA	RG:Z:20GAV.8	AM:i:37	NM:i:0	SM:i:37	MQ:i:60	OQ:Z:HHHHHHHHHHHHCHFEHHHHHHHEHHHHHHHHHHHDFHFHHHHHHHEHHHHHHHHHHHFHHHECHHHHFHGHHFHEHHHEHBFHHHHHHHHHHHHHHHH at 5	UQ:i:0
+20GAVAAXX100126:8:23:12774:197414	147	chr1	10006790	60	33S68M	=	10006420	-437	AGTTTCTCCATATGGGTCAGGCTGGTCTCGAACTCCCGACATCACGTGATCCACCTGCCTCAACCTCCAAAAGTGCTGGGATTACAGGTGCGAGCCACCTC	##################################<?7:=@1/:;59/1>'@@3DB:?CA@@A9BA=BBCCCDACABACCABDABACC<<A:BDABA at BBC@	MD:Z:68	PG:Z:BWA	RG:Z:20GAV.8	AM:i:23	NM:i:0	SM:i:37	MQ:i:60	OQ:Z:##################################?=<;6?1,7596+1:(A=,B?:AAA at AA:BB?BABBBBBAAA?BBAABAAAABA=AABBABB>BBAB	UQ:i:0
+20GAVAAXX100126:8:21:7822:20748	163	chr1	10006812	60	83M18S	=	10007120	408	TGCCTCAACCTCCAAAAGTGCTGGGATTACAGGTGCGAGCCACCTCGCCTGACCAAGTTAGTATGTGTTTAAAGATCACACTTGTAATCCCAGCACTTTGG	@=5AA>>A:AA>=7:C?4 at A@A>CC?;A:;A@;=7<+77:>C?C at 5.A:B(4 at .+**@@><;BA<61ADC8:@;A7;AA<@A###################	MD:Z:83	PG:Z:BWA	RG:Z:20GAV.8	AM:i:37	NM:i:0	SM:i:37	MQ:i:60	OQ:Z:@86@??:@9?@<?:5A;08@@>;BB;8?7;?><88 at 59;>?BAAA50 at 9>(3@/)()6>=>7AA9-0BBA:3<;?5<BB;B?###################	UQ:i:0
+20GAVAAXX100126:8:68:20656:34221	163	chr1	10006818	60	101M	=	10007102	384	AACCTCCAAAAGTGCTGGGATTACAGGTGCGAGCCACCTCGCCTGACCAAGTTAGTATGTGTTTAAAGATCACACTTGTAATCCCAGCACTTTGGGAGGCT	@D at BBAB>CCCC?ABDBCCCCCCACCB at BC;CCB at B=BCA9ACD at CACACA@C at CCCDBAAACBBD@ACA4CA?@@B at BA@AB@@CCA?@AAA at C*ACA:A	MD:Z:101	PG:Z:BWA	RG:Z:20GAV.8	AM:i:37	NM:i:0	SM:i:37	MQ:i:60	OQ:Z:BBBBBBB>ABBB at BBBBBBABBBBBBA<ABBABAABABBBAABABABB at AB?BBB at BBA=B?AAAAA at A@3?A?B>B@=A?A@>>@@@?@??=?@-<=A4<	UQ:i:0
+20GAVAAXX100126:8:1:4286:192808	99	chr1	10006849	60	101M	=	10007174	425	AGCCACCTCGCCTGACCAAGTTAGTATGTGTTTAAAGATCACACTTGTAATCCCAGCACTTTGGGAGGCTGATGTAGGAGGATCGCTTGAGGCCAGGTGTT	<<;:A:<DB5BBDBD<B at A=BA?A?CCBCBBDDAD<@5@?=>??BDBBCDC=BAC?BCA?DDB>>?ABABBACBB>><:=CDCB;@ADCDC?@CDA=;?A5	MD:Z:101	PG:Z:BWA	RG:Z:20GAV.8	AM:i:37	NM:i:0	SM:i:37	MQ:i:60	OQ:Z:GGEGGEDHHEHHHHHEGCGDGGCGEHHHHHHHHGHBF9FF=CDGGHHGHHHEHGHEHHHDHHHEECGGGGHEHHHAA?=AHHHHHEEHHHHDEHHGBBGG4	UQ:i:0
+20GAVAAXX100126:8:63:5666:148033	163	chr1	10006932	60	101M	=	10007256	424	CGCTTGAGGCCAGGTGTTTGAGACCAGCCTGGGCAACATAGGGAGACCCTGTCTCTACAAAAAATACAAAAATTAGTTGGGTGTGATGGTTCATGCCTGTA	@;BCAABBCBCCBBABABCBCCABCCBCCCBCCBBC?BBBBBCCA?ACCC@>BACD>ACBBBCBBA>BDCACBB at B:BBB;9A>ADCA at C?AC?B?CD at B@	MD:Z:101	PG:Z:BWA	RG:Z:20GAV.8	AM:i:37	NM:i:0	SM:i:37	MQ:i:60	OQ:Z:BBBBBBBBBBBBBB;BBCBABB>CBBABBAAAABBBBBBBBABAB>AAB?B=?ABA>BA at A@AAA at B@A@@@@A at A7A@A<3>9 at AA@A>>?A>@B@>@9?	UQ:i:0
+20GAVAAXX100126:8:62:2555:107007	99	chr1	10006969	60	101M	=	10007301	421	ATAGGGAGACCCTGTCTCTACAAAAAATACAAAAATTAGTTGGGTGTGATGGTTCATGCCTGTAGTCTCAGCTACTCAGGAAGCTGAGGTGGGAGGATTAC	CCCACCDCDABBDBBBDBDCACDDDAABA?CDDD at BDCCBDBCC@B at BDCBCBDBC@BBBDBCCCCBDBCCBDCADBCCCCDCBDBDAC=CC?DCD?B<DB	MD:Z:101	PG:Z:BWA	RG:Z:20GAV.8	AM:i:37	NM:i:0	SM:i:37	MQ:i:60	OQ:Z:HHHHHHHHHHHHHHHHHHHHHHHHHGGGGGHHHHGGHHHHHHHHFHEHHHHHGHHHFHHHHHHHHHHHHHHHHHHHHHHHGHHHHHHGHAHHEHHHAFBHH	UQ:i:0
+20GAVAAXX100126:8:22:6227:26566	83	chr1	10006988	60	101M	=	10006730	-358	ACAAAAAATACAAAAATTAGTTGGGTGTGATGGTTCATGCCTGTAGTCTCAGCTACTCAGGAAGCTGAGGTGGGAGGATTACTTGGGCCCAGGAGGTCGGG	=?@?DDDCBBCDDDDCDCBADCBCACACBCCBADDBCCBCCCACDADCDBCBCCBCDBCBBDDBCCBCBACBBBDBBCDCCCDCBBBCCBDBBDCAD9BBC	MD:Z:101	PG:Z:BWA	RG:Z:20GAV.8	AM:i:37	NM:i:0	SM:i:37	MQ:i:60	OQ:Z:BGGEHHHHGEHHHHHHHHFHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHH	UQ:i:0
+20GAVAAXX100126:8:2:2951:16973	147	chr1	10007005	60	101M	=	10006763	-342	GAGTTGGGTGTGATGGTTCATGCATGTAGTCTCAGCTACTCAGGAAGCTGAGGTGGGAGGATTCCTTGGGCCCAGGAGGTCGGGGCTGCAGTGAGCCAGTG	#E38>AC1 at 9?A8 at C1CB@4?<@%1:<9@@7?>C<CB@>CACCC*BB9C?;;0BC@@A?799>#7)6ACBBA66CBDC<(-A?B=AB96<;BBAAAA@@C@	MD:Z:0T22C39A37	PG:Z:BWA	RG:Z:20GAV.8	AM:i:37	NM:i:3	SM:i:37	MQ:i:60	OQ:Z:#?219@>1;9>>8>A. at A;2><<%/;=7 at 97;9A?BAB=BAABB*=?<B?=70 at A?B<?9<;@(<'5 at ABA@10BBBB;'1><?;@A=75>AB at CAA=BBA	UQ:i:8
+20GAVAAXX100126:8:46:18774:97831	163	chr1	10007015	60	79M22S	=	10007344	429	TGATGGTTCATGCCTGTAGTCTCAGCTACTCAGGAAGCTGAGGTGGGAGGATTACTTGGGCCCAGGAGGTCGGGGCTGCAGTGAGCCAGTGACCATGCCAG	@CCB?B at BBCCBBBDBBCCBBDBCCBCCADBBBC?AAA at A?AC=?CCACC=?C==CB@;A>AB=AA6 at B8>;?<>@??#######################	MD:Z:79	PG:Z:BWA	RG:Z:20GAV.8	AM:i:37	NM:i:0	SM:i:37	MQ:i:60	OQ:Z:BCBBCBBBBBBBBCBBABBABBBBBBABBBBAAB at ABBAB@AB6ABA=BA??@@;?@<;@?@A=@?7?@4??==>?=?#######################	UQ:i:0
+20GAVAAXX100126:8:24:7834:75053	163	chr1	10007028	60	64M37S	=	10007352	424	CTGTAGTCTCAGCTACTCAGGAAGCTGAGGTGGGAGGATTACTTGGGCCCAGGAGGTCGGGGCTGCCGTGAGCCAGTGACCATGCCAGTATACTCCAGCCC	@DB at AA@ADACCBCC>CAABCBCBADBBCC<ACC?BA9?>@?BB7<DA at C>BB:CB9<80:C@######################################	MD:Z:64	PG:Z:BWA	RG:Z:20GAV.8	AM:i:37	NM:i:0	SM:i:37	MQ:i:60	OQ:Z:BBBBBBBABABBBBB at AA?AB at AAABB@BB6 at BB@BB;A at AAA@:=B??A at A?<A at 57>3=B?######################################	UQ:i:0
+20GAVAAXX100126:8:68:8790:55871	163	chr1	10007049	60	96M5S	=	10007343	394	AAGCTGAGGCGGGAGGATTACTTGGGCCCAGGAGGTCGGGGCTGCAGTGAGCCAGTGACCATGCCAGTATACTCCAGTCCTGATTACAGAACAAACCCCTA	>=<1?;B>:&0B1'253=B8>=3:5A<3=*?.>=15255%><;=78;CB<6&?@@B<59B<855(C<?<A9:<2'*44A==6B(-D?>;D?@<AD######	MD:Z:9T67C18	PG:Z:BWA	RG:Z:20GAV.8	AM:i:37	NM:i:2	SM:i:37	MQ:i:60	OQ:Z:;9;1;;@=9(5 at 5(.80:@7?8255@:09*>1;;5/5@;+@>;9;77 at B75(;A<B909?=716(@?=9@;651()2,@<;3>(-B>C;A>A6BA######	UQ:i:24
+20GAVAAXX100126:8:68:20656:34221	83	chr1	10007102	60	101M	=	10006818	-384	AGTGACCATGCCAGTATACTCCAGCCCTGATTACAGAACAAACCCCTATCTCAAACAAACAAACAAGTACATAAATGAAAGAAAGTTTGTGTTCCTACCAC	=BDCCDCCCCCAB?@>@ACDCBDBCCCCBCDCC at D@DCBDDACCCCCCDCD at ADBA@DBBDDBBDCACBBCCDDCC at ADD@DDDADDCACAADCCCCABCC	MD:Z:101	PG:Z:BWA	RG:Z:20GAV.8	AM:i:37	NM:i:0	SM:i:37	MQ:i:60	OQ:Z:>HHHHHHHHHHFFFFBFFHHHHHHHHHHHHHHHGHFHHHHHFHHHHHHHHHGGHHGGHHHHHHHHHHHHHHHHHHHGGHHGHHHHHHHHHHGHHHHHHHHH	UQ:i:0
+20GAVAAXX100126:8:21:7822:20748	83	chr1	10007120	60	101M	=	10006812	-408	CTCCAGCCCTGATTACAGAACAAACCCCTATCTCAAACAAACAAACAAGTACATAAATGAAAGAAAGTTTGTGTTCCTACCACAGGTGTGTCCAGTGAGAA	>)49;7%9;<;0:?9 at B9>A?990555;8:945;8?@:;AA><<:=;7;?9=<;<;;49;>;1@>A><AA>?:<>;=>:??5<<=<A<@>A?=A>9;7==<	MD:Z:101	PG:Z:BWA	RG:Z:20GAV.8	AM:i:37	NM:i:0	SM:i:37	MQ:i:60	OQ:Z:C+5554.=>=>3<C;CF=CFC4504454444885:CEBBFFC<<;A=:?C744445>6@@EB6FDFF?FFFC?<C at ACCCC7?=A?F?FFFFEFFBEEFFF	UQ:i:0
+20GAVAAXX100126:8:3:4038:181802	1187	chr1	10007126	60	99M2S	=	10007427	401	CCCTGATTACAGAACAAACCCCTATCTCAAACAAACAAACAAGTACATAAATGAAAGAAAGTTTGTGTTCCTACCACAGGTGTGTCCAGTGAGAAGAGTGT	@DCC??BABACCCBBDEEBDDDDDDCECDDEBCAB@>B@=ACAB;ADDADBACADDADDB<AC;CB?BDAADC;AB at BB=@8C8ACCB5C?@BB?@8C###	MD:Z:99	PG:Z:BWA	RG:Z:20GAV.8	AM:i:37	NM:i:0	SM:i:37	MQ:i:60	OQ:Z:BCCCCCCCBCBBBCCCCCCCCCBCCCCCCBCCC?CBCBCCCBCACBCBABBCCBBBCAB at CBBCBBB@B?A?B>@BBACCBC at CBACBC@B=?@9>3?###	UQ:i:0
+20GAVAAXX100126:8:3:4050:181815	163	chr1	10007126	60	101M	=	10007427	401	CCCTGATTACAGAACAAACCCCTATCTCAAACAAACAAACAAGTACATAAATGAAAGAAAGTTTGTGTTCCTACCACAGGTGTGTCCAGTGAGAAGAGTGT	@CCCABBABACCCBADDDBDCCDCDCDCDDEACDC at ABB@BCBBAACDCD>CCADDCCDBBBCBCC?BDBAEC?BB@@BBB at CABCDB>C77B at A>1C?D?	MD:Z:101	PG:Z:BWA	RG:Z:20GAV.8	AM:i:37	NM:i:0	SM:i:37	MQ:i:60	OQ:Z:BBCCBBBCBBBBBCBCBBCCBBBBCCBCCBCBBBBBBBBBBBB at BBBBBB@BBBBBB at B@B at BBBAB@BBBBBBBAB?CB@@AB at BBAB@C4@>;;-?<B9	UQ:i:0
+20GAVAAXX100126:8:1:16535:116063	147	chr1	10007127	60	24S77M	=	10006767	-436	GTGACCATGCCAGTATACTCCAGCCCTGATTACAGAACAAACCCCTATCTCAAACAAACAAACAAGTACATAAATGAAAGAAAGTTTGTGTTCCTACCACA	#########################@=<6?;A?A8A9':>9>5BA<@:@;=CC at 61<B?@;57A<79<?B?BC>>>CC=9BCCADC?<:4<?BBA<@A<B@	MD:Z:77	PG:Z:BWA	RG:Z:20GAV.8	AM:i:37	NM:i:0	SM:i:37	MQ:i:60	OQ:Z:#########################?;>28>=;?;?4'8=7=6?@9<<<:@BB<11?>@@=3;A@<=6>A?@B<:<AB95 at BABBA;A<2;;@BA:?A9BB	UQ:i:0
+20GAVAAXX100126:8:48:10097:181097	1699	chr1	10007155	29	92M9S	=	10007512	383	AACAAACAAACAAGTACATATATGAAAGAAAGTTTGTGTTCCTACCACAGGTGTGTCCAGTGAGAAGAGTGTGATGTTGCAGTTGAGAGGGGGTAAATGCT	18246))A339B36AC?C>3*?>;=?3BAEEAA=<<26:35//C029A0A&4::A9</+*@@<:(*<5BA:CB(:@7AB'*@-CA at BB;3@##########	MD:Z:20A61A9	PG:Z:BWA	RG:Z:20GAV.8	AM:i:29	NM:i:2	SM:i:29	MQ:i:29	OQ:Z:,3202(*@//;A47;B?B<2*?;89<0A>CC at B;>?59=672-B444A-=+-49=/:,))@?9:'(?3?BC@?)9?CBC**?)A@:CB<3@##########	UQ:i:21
+20GAVAAXX100126:8:48:10108:181079	163	chr1	10007155	60	101M	=	10007444	389	AACAAACAAACAAGTACATAAATGAAAGAAAGTTTGTGTTCCTACCACAGGTGTGTCCAGTGAGAAGAGTGTGATGTTGCAGATGAGAGGGGATAAATGCT	@D at BBA@BCDACCAACACDCDDCCCDDCCDDCBC at A>A at BBCDC?CCACC at AB>CBBCCC at BBBCD?AC?@CC at BA?BBA at ABABCBB?C at AB?BBCB at DA	MD:Z:101	PG:Z:BWA	RG:Z:20GAV.8	AM:i:37	NM:i:0	SM:i:37	MQ:i:60	OQ:Z:BCBBBCBCBCBCBCBBBBCBBBBCBBBBABBB at BCBABBBBBBBBBBBBBA@A?BABBBB at B@B at AA?B8B>A?AA>@@B?B>@A???@@?@>>@@?>@A>	UQ:i:0
+20GAVAAXX100126:8:48:10118:181094	1187	chr1	10007155	60	101M	=	10007444	389	AACAAACAAACAAGTACATAAATGAAAGAAAGTTTGTGTTCCTACCACAGGTGTGTCCAGTGAGAAGAGTGTGATGTTGCAGATGAGAGGGGATAAATGCT	@D at BBB@BCCACCABCACCCDDCBCDDCCCDCACBA>A at BBCDC=BCABC@<C>CBBCCC?BABB?@@C@@CCABABBCA at ABABBA<@B at A>A@<=C at CB	MD:Z:101	PG:Z:BWA	RG:Z:20GAV.8	AM:i:37	NM:i:0	SM:i:37	MQ:i:60	OQ:Z:BCBBBBBBBBBBBB?BBBBBBBBBBBBBAABBBBBBABBBBBBBAABBABA8B at BABBAB?B?B?;B>A;B>B at BB@@BA?A>@A>>8A?@?9@=87??@?	UQ:i:0
+20GAVAAXX100126:8:1:4286:192808	147	chr1	10007174	60	101M	=	10006849	-425	AAATGAAAGAAAGTTTGTGTTCCTACAACAGGTGTGTCCAGTGAGAAGAGTGTGATGTTGCAGATGAGAGGGGATAAATGCTGGACCAAAGTCCTTGAGAA	=DADBADAB+ at D8CDC:.;>6A?3:>'?@DA@;;@ACBBD9BBE at DE?A at AAACDC:DCBB at A@>?BCDB5=ADCBCBB@@CCC?CC?BDACA?CBACB<@	MD:Z:26C74	PG:Z:BWA	RG:Z:20GAV.8	AM:i:37	NM:i:1	SM:i:37	MQ:i:60	OQ:Z::?AAA?BBB+?@;BB?:+8=5@;37>(><@AA6<BBBBBB=@AC at ACA<ABBCBCBCBBBBCBCCCCCCA4;?CB at AA@??BBCCCCACCCB??BBABB5A	UQ:i:6
+20GAVAAXX100126:8:3:11681:100672	163	chr1	10007181	60	101M	=	10007491	410	AGAAAGTTTGTGTTCCTACCACAGGTGTGTCCAGTGAGAAGAGTGTGATGTTGCAGATGAGAGGGGATAAATGCTGGACCAAAGTCCTTGAGAAGGTGAGA	@CCCBABBCBABABCDDDBDCACCCBBBCBBCCC>A?B>ABBBB at ACDCC?CC at CCADCBB@CBBC=ABCBCC?@ABBA;ABCB?8CCACAAA>BB at CAD@	MD:Z:101	PG:Z:BWA	RG:Z:20GAV.8	AM:i:37	NM:i:0	SM:i:37	MQ:i:60	OQ:Z:BBBBBBABBBBBBBCCBCCCBBBCB at B?BABBBB at BAB@ABAB>B at BBBBBBBB@B?BB at B>BB at A?@A at AAB@>BABA;@B?A;3?BAA?@;<>A6@>@=	UQ:i:0
+20GAVAAXX100126:8:7:7502:151389	1187	chr1	10007181	60	101M	=	10007491	410	AGAAAGTTTGTGTTCCTACCACAGGTGTGTCCAGTGAGAAGAGTGTGATGTTGCAGATGAGAGGGGATAAATGCTGGACCAAAGTCCTTGAGAAGGTGAGA	@CACB?8AABABA at CDECBDCACCC@B?CBCCCC;A7=:+;;9??;C at CC?CB=DCCDCC?5ABCA6>BC?@B;8=<9 at BBBDB?C@;@B9B>1ABCC?>@	MD:Z:101	PG:Z:BWA	RG:Z:20GAV.8	AM:i:37	NM:i:0	SM:i:37	MQ:i:60	OQ:Z:BCCCB at .@CCAABCCCCBCCBBBCB<B9CACBBB<B;@=+=<:8A9B<BBAA?@BBABBB at 4@BB?7>A@?:@<4<=C at BAB@A:A;6@?7A9.<A>@;6<	UQ:i:0
+20GAVAAXX100126:8:24:17458:9144	163	chr1	10007190	60	101M	=	10007539	449	GTGTTCCTACCACAGGTGTGTCCAGTGAGAAGAGTGTGATGTTGCAGATGAGAGGGGATAAATGCTGGACCAAAGTCCTTGAGAAGGTGAGAGAGAAAGGA	@AB at A@BCBACCABCCBBBBBCDBCABCCCDCB?9A;@@@B@@A at ACC@A>BCACBBCACBBA?AC=@DA;CCBB>A at D92=BA at BA8?C>@A?CBCD at CA	MD:Z:101	PG:Z:BWA	RG:Z:20GAV.8	AM:i:37	NM:i:0	SM:i:37	MQ:i:60	OQ:Z:BBBBBCBBBBBCBBBB at B@BACCAB?BABBBB@=7B?AAAB@@@B at BA@@@A at BA@A@@BB@@@?@@?BB<@@AA:A?@9/;@?=@>5@?====@?>@>>>	UQ:i:0
+20GAVAAXX100126:8:45:16821:90529	1187	chr1	10007194	60	101M	=	10007535	436	TCCTACCACAGGTGTGTCCAGTGAGAAGAGTGTGATGTTGCAGATGAGAGGGGATAAATGCTGGACCAAAGTCCTTGAGAAGGTGAGAGAGAAAGGAGAGA	@BCCA?BBACCC?ABC?BDCCBBCCCDC>C9CBC?B>=7ABBB=ABACBC9=A@@CD??>AC at 8CA;CBD?C@&=B at BA<BAA89?9@?@@?*>BBA>;:D	MD:Z:101	PG:Z:BWA	RG:Z:20GAV.8	AM:i:37	NM:i:0	SM:i:37	MQ:i:60	OQ:Z:BBCBBCBCCBBC at C?CCBCBBABBBBBC9C5B at B@BA>;BBAB9BB=BAB=>>A<BB9><BA@:BB>B>B?>=':B at A=:@@=/683=?:@<(<=A<663B	UQ:i:0
+20GAVAAXX100126:8:45:16833:90513	163	chr1	10007194	60	101M	=	10007530	436	TCCTACCACAGGTGTGTCCAGTGAGAAGAGTGTGATGTTGCAGATGAGAGGGGATAAATGCTGGACCAAAGTCCTTGAGAAGGTGAGAGAGAAAGGAGAGA	@CCC@?BBACCC=AABABDCC at BCCCDCCCBCACBBA@@?BBB@?BCC at BABB@?<BB?>@=B?AA>CDDAC at +>BABC?>AC8=>@2<C?BABAACC;DD	MD:Z:101	PG:Z:BWA	RG:Z:20GAV.8	AM:i:37	NM:i:0	SM:i:37	MQ:i:60	OQ:Z:BCCBCCCCCBBB>BBBBBCBB<BABBBB at B@B?BBBBAAABAB<AB at B??BA at A:9@=><A;B?CB at BABB@>+;BAAB>=A at 5;7;/=?B@<A;@?@7 at B	UQ:i:0
+20GAVAAXX100126:8:43:20013:129172	163	chr1	10007196	60	97M4S	=	10007463	367	CTACCACAGGTGTGTCCAGTGAGAAGAGTGTGATGTTGCAGATGAGAGGGGATAAATGCTGGACCAAAGTCCTTGAGAAGGTGAGAGAGAAAGGAGAGAAA	@DB at AB@BBC at BAABBB?BBBCCCDCCC at CACCCB@?AA at B@AC=BCCCC@@B?DCAC at B?AC=BC=?B?@BD<<>AAC>A=C>ABC<?B>=CABA#####	MD:Z:97	PG:Z:BWA	RG:Z:20GAV.8	AM:i:37	NM:i:0	SM:i:37	MQ:i:60	OQ:Z:BBCBBBCBBB at BBB>BA;AABBBBBBAB8B?BABBAABBAB at AB?A?BBAA?@AA@@A@?@@B?@B?=?9B=A<;<A?@>@9A<?>@8@>=:A?=@#####	UQ:i:0
+20GAVAAXX100126:8:27:21458:11536	629	chr1	10007225	0	*	=	10007225	0	NNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNTNAAANTGTTAANNNNNNNNNNNNNNNNNNNNNAGTN	#####################################################################################################	PG:Z:BWA	RG:Z:20GAV.8	OQ:Z:#####################################################################################################
+20GAVAAXX100126:8:27:21458:11536	697	chr1	10007225	37	16S85M	=	10007225	0	GTCCAGTGAGAAGAGTGTGATGTTGCAGATGAGAGGGGATAAATGCTGGACCAAAGTCCTTGAGAAGGTGAGAGAGAAAGGAGAGAAAGGAATCCAGAGTC	#################BAA=@D at 2@;974/A at B:3'2>7 at CBC=>D>::73?BB87=28?A=AAC>7:8 at BC@D=CCCCCD?BACBBB>CCCBAAACAC@	MD:Z:85	PG:Z:BWA	RG:Z:20GAV.8	AM:i:0	NM:i:0	SM:i:37	OQ:Z:#################A=@<AA?3?8:3-->>@=1'0=8 at AA@<9B at 56<.??=;8<19 at B?BBB at 884>BA>B;BCABCB>?AACCB<BBBCCCBCCBB	UQ:i:0
+20GAVAAXX100126:8:27:21479:11534	629	chr1	10007241	0	*	=	10007241	0	NNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNN	#####################################################################################################	PG:Z:BWA	RG:Z:20GAV.8	XN:i:1	OQ:Z:#####################################################################################################
+20GAVAAXX100126:8:27:21479:11534	1721	chr1	10007241	37	32S69M	=	10007241	0	GTCCAGTGAGAAGAGTGTGATGTTGCAGATGAGAGGGGATAAATGCTGGACCAAAGTCCTTGAGAAGGTGAGAGAGAAAGGAGAGAAAGGAATCCAGAGTC	#################################B5224>?;=@C>;B4=>2 at A?C=9C>:>?>=?A8-8ACBDAD at CCCA?D at E=BBCBBCCBCABAC at C@	MD:Z:69	PG:Z:BWA	RG:Z:20GAV.8	AM:i:0	NM:i:0	SM:i:37	OQ:Z:#################################@7/03=?<;?@=6>59=7=@;??;B?;?A@@AA:-6?AAB at B@BB@?=B at C<CCBBBBB at BBBABBAB	UQ:i:0
+20GAVAAXX100126:8:63:5666:148033	83	chr1	10007256	60	101M	=	10006932	-424	GGACCAAAGTCCTTGAGAAGGTGAGAGAGAAAGGAGAGAAAGGAATCCAGAGTCCAGATGAAGGAGTTGATCTCTGATGGCAGCCGAGATAACAGCACATC	DDCD=DDDADCCDCBDBDDCACBDBDBDBDDDBBDBDBDDDBBDCBCBDBCADCBCBCCBDCBBCADCBCDCDCCBCCBBBDBC;BDBCCDCBDCCC at BDC	MD:Z:101	PG:Z:BWA	RG:Z:20GAV.8	AM:i:37	NM:i:0	SM:i:37	MQ:i:60	OQ:Z:HHHHBHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHEHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHH	UQ:i:0
+20GAVAAXX100126:8:67:10895:75253	99	chr1	10007283	60	101M	=	10007475	292	AGAAAGGAGAGAAAGGAATCCAGAGTCCAGATGAAGGAGTTGATCTCTGATGGCAGCCGAGATAACAGCACATCCTTACGGTTGTAGGTGGCTTTGTAGAT	CCCBDCCDCDCDDDCCDDCBBCCDCBBBCCDCBDDCCDCBDBDCBCBDBDCBCBCCBB;DCDCCDACCBCACCBBDDCA;CCDCCCCCBCCCCDDCCDDBB	MD:Z:101	PG:Z:BWA	RG:Z:20GAV.8	AM:i:37	NM:i:0	SM:i:37	MQ:i:60	OQ:Z:HHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHGHHHFHHHHHHGF	UQ:i:0
+20GAVAAXX100126:8:62:2555:107007	147	chr1	10007301	60	11S90M	=	10006969	-421	AGAGAAATGAATCCAGAGTCCAGATGAAGGATTTGATCTCTGATGGCAGCCGAGATAACAGCACATCCTTACGGTTGTAGGTGGCTTTGTAGATCTAAGAA	############?AC;;8=>@CA?==?@C?83A<5@?7669-<B>@BBCC5AABDBABBBBA?AABBCCCB;CADCABDD at C?ACEEAACDBCCA@?CBB@	MD:Z:20G69	PG:Z:BWA	RG:Z:20GAV.8	AM:i:37	NM:i:1	SM:i:37	MQ:i:60	OQ:Z:############??=5686>@A@?<<>??:9/=:8>;524:+:=<=ABBB@@@ABAB at BABBABBBBBABABBBBBBABCAB<ABCCCBCCBBBCCCCBCB	UQ:i:18
+20GAVAAXX100126:8:68:8790:55871	83	chr1	10007343	60	101M	=	10007049	-394	GATAACAGCACATCCTTACGGTTGTAGGTGGCTTTGTAGATCTAAGAAGATCAGGAAGATTGCTGGCTCTAGTTTTGTAGATTATCAGGAAGATTATCAGA	>9789;<8::;985;:8:298648:==<@>;:;;;:6C@@C<:;>=<=:6=?A??@?>5<<9<;;:>?=???>AAB<=?<@<<==<>:@?=<@?=>B5?:<	MD:Z:101	PG:Z:BWA	RG:Z:20GAV.8	AM:i:37	NM:i:0	SM:i:37	MQ:i:60	OQ:Z:A44445544455555555554:9<>=DDDD>@==@<;GFFG54444?<>8<FFFFFCC8>>55554ADDFAGAGFGDDADF??A>>>@C?>DFAADGAGDG	UQ:i:0
+20GAVAAXX100126:8:46:18774:97831	83	chr1	10007344	60	101M	=	10007015	-429	ATAACAGCACATCCTTACGGTTGTAGGTGGCTTTGTAGATCTAAGAAGATCAGGAAGATTGCTGGCTCTAGTTTTGTAGATTATCAGGAAGATTATCAGAA	?DDCCBCCCCCDCCDCC;CADCACDBACBBCDDCACDBCDCCDDBDDBCDBCBBDCBCDCBCCBBCDCCCADDDCACDBCDCCDBDBBDDBCDCCDCBBDC	MD:Z:101	PG:Z:BWA	RG:Z:20GAV.8	AM:i:37	NM:i:0	SM:i:37	MQ:i:60	OQ:Z:BHHHHEHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHH	UQ:i:0
+20GAVAAXX100126:8:24:7834:75053	83	chr1	10007352	60	101M	=	10007028	-424	ACATCCTTACGGTTGTAGGTGGCTTTGTAGATCTAAGAAGATCAGGAAGATTGCTGGCTCTAGTTTTGTAGATTATCAGGAAGATTATCAGAAAAACATAT	C?CDDCDCC;CADCACDCACBBCDDCACDBCDCCDDBDDBCDBDBBDDBCDCBCCBBCDCCCADDDCACCBCDCCDBDBBDDBCDCCDAC at ADDDCCACCC	MD:Z:101	PG:Z:BWA	RG:Z:20GAV.8	AM:i:37	NM:i:0	SM:i:37	MQ:i:60	OQ:Z:FGHHHHHHHHHHIHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHGGGGHHHHHHHHH	UQ:i:0
+20GAVAAXX100126:8:3:4038:181802	1107	chr1	10007427	60	101M	=	10007126	-401	TCAGGAAGATTATCAGAAAAACATATCTTAACCTGGTGAGCTCTCTATGCTCTGGCACTTGAATAAAAGCTATCCTAAAATATTACAAATTCTAGAATTTA	EDDCCDDCCDC at DACA@DDDCBCCCDCDCDCCCCBACBDBBDCDCCCCBCDCCBBBBCDC@@CCDDDCBCCCDCCCDDDCCCDCBBDDCDDCCDBDCBDCC	MD:Z:101	PG:Z:BWA	RG:Z:20GAV.8	AM:i:37	NM:i:0	SM:i:37	MQ:i:60	OQ:Z:HHHHHHHHHHHEHGGGGHHHHHHHHHHHHHHHHHHHHHHHGHHHHHHHHHHHHHHHHHHHGGHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHH	UQ:i:0
+20GAVAAXX100126:8:3:4050:181815	83	chr1	10007427	60	101M	=	10007126	-401	TCAGGAAGATTATCAGAAAAACATATCTTAACCTGGTGAGCTCTCTATGCTCTGGCACTTGAATAAAAGCTATCCTAAAATATTACAAATTCTAGAATTTA	BDDCCDDCCDBCDACA at DDDCBCCCDCDCDCCCCBACBDBCDCDCCCCBCDCCBBBBCDC@@CCDDDCBCCCDCCCDDDCCCDCBBDDCDDCCDBDCBDCC	MD:Z:101	PG:Z:BWA	RG:Z:20GAV.8	AM:i:37	NM:i:0	SM:i:37	MQ:i:60	OQ:Z:GHHHHHHHIHIHHGGGGHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHGGHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHH	UQ:i:0
+20GAVAAXX100126:8:48:10108:181079	83	chr1	10007444	60	101M	=	10007155	-389	AAAACATATCTTAACCTGGTGAGCTCTCTATGCTCTGGCACTTGAATAAAAGCTATCCTAAAATATTACAAATTCTAGAATTTACCTTCACAAAAACTTTT	EEDCCCCCDCDCDCCCCCACBDBCDCBCCCCBCDCCCBBCCDC at ACCDDDCBCCCDCCCDDDCCCDCBBDDCDDCCDBDCDDCBCCDDABBDDDDCCBDDC	MD:Z:101	PG:Z:BWA	RG:Z:20GAV.8	AM:i:37	NM:i:0	SM:i:37	MQ:i:60	OQ:Z:HHHHHHHHHHIHHHHHIHHHHHHHHHGHHHIHHHHHHHHHHHHGGHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHGGHHHHHHHHHHH	UQ:i:0
+20GAVAAXX100126:8:48:10118:181094	1107	chr1	10007444	60	101M	=	10007155	-389	AAAACATATCTTAACCTGGTGAGCTCTCTATGCTCTGGCACTTGAATAAAAGCTATCCTAAAATATTACAAATTCTAGAATTTACCTTCACAAAAACTTTT	EEDC at CCCDCBCABCCBCABBDBCDCDCCCCBC<CCCBBBCAC>?CCDDDC at CCCDCCCDDDCACDABBDDCDDCCDBDCDDCBCCDD@;BAAAA@@7>=<	MD:Z:101	PG:Z:BWA	RG:Z:20GAV.8	AM:i:37	NM:i:0	SM:i:37	MQ:i:60	OQ:Z:HHHHGHHHHHFHGGHHGHHGHHHHHHHHHHHHHBHHHHHGHGHEEHHHHHHFHHHHHHHHHHHGHHGHHHHHHHHHHHHHHHHHHHHHCCHGGGGFGDGGG	UQ:i:0
+20GAVAAXX100126:8:43:20013:129172	83	chr1	10007463	60	101M	=	10007196	-367	TGAGCTCTCTATGCTCTGGCACTTGAATAAAAGCTATCCTAAAATATTACAAATTCTAGAATTTACCTTCACAAAAACTTTTTCATTAACTAGGAGGCTTT	DDDCCCCDCCCCCCDCCCBBCBDC at ACCDDDDA>CCDCCCDDDBCCD>BBDDCDDCCCBDCDDCBCCDD@@BDDDDACDDDDDBCDCDCCCDBBDC at A>DC	MD:Z:101	PG:Z:BWA	RG:Z:20GAV.8	AM:i:37	NM:i:0	SM:i:37	MQ:i:60	OQ:Z:IHHHHGIHHHHHHHHHHHHHHIHHGGHHHHHHFEHHHHHHHHHGHHHEHHHHHHHHHHHHHHHHHHHHHGEHHHHHIHHHHHHHHHHHHHHHHHHHGHGHH	UQ:i:0
+20GAVAAXX100126:8:42:6558:108923	163	chr1	10007468	60	101M	=	10007800	432	TCTCTATGCTCTGGCACTTGAATAAAAGCTATCCTAAAATATTACAAATTCTAGAATTTACCTTCACAAAAACTTTTTCATTAACTAGGAGGCTTTTTTTT	@BCABABBBDBDBBBCBDCBCDDCEDDCCDCCBCCBBBBBBCCC:CDCCC at DDADCCDCC@CDBBC>BDCBD at BBCBBCBBBCB@ECB=D at ABBDBCDAAC	MD:Z:101	PG:Z:BWA	RG:Z:20GAV.8	AM:i:37	NM:i:0	SM:i:37	MQ:i:60	OQ:Z:BBCCBBBBBBBBBBBBCBCBCBCBCBBBBBCBBBBBBBBBBBBB at BBABBBBCBBABBBBBBBBABBAAABA@B at A@ABABAB at BBAB>A@@A?@@?@?;B	UQ:i:0
+20GAVAAXX100126:8:45:3840:54807	163	chr1	10007468	60	101M	=	10007795	427	TCTCTATGCTCTGGCACTTGAATAAAAGCTATCCTAAAATATTACAAATTCTAGAATTTACCTTCACAAAAACTTTTTCATTAACTAGGAGGCTTTTTTTT	@CCAA at BABDBBB<?BADCCCDDCDEECA?CCBCC:?B at B6C@C:CE@<C;AD;CECD at C@CD;BC>?DABDBB7B?9A=BAC:@D??@??AB=;ADCBDC	MD:Z:101	PG:Z:BWA	RG:Z:20GAV.8	AM:i:37	NM:i:0	SM:i:37	MQ:i:60	OQ:Z:BCCBCCBCBBC?B@>ABBBCCBCBBCCB?<BBBBB>ABCB:B at BCBC<=BCCC>@CBB>BBBBCBBB=BCBBBA6B>C at CBBBCBA<>ACBBA95>A?@BB	UQ:i:0
+20GAVAAXX100126:8:61:17876:93642	99	chr1	10007468	29	101M	=	10007872	438	TCTCTATGCTCTGGCACTTGAATAAAAGCTATCCTAAAATATTACAAATTCTAGAATTTACCTTCACAAAAACTTTTTCATTAACTAGGAGGCTTTTTTTT	CBC at DCCCBDBDBCBCADDBDDCCDDAABDCCBBCCDDDCCCDCACDDCDBDCCDDCDDCABDDBCACDDDA?DDDDDBCCDCDADCCCDCCCDDADDD@@	MD:Z:101	PG:Z:BWA	RG:Z:20GAV.8	AM:i:29	NM:i:0	SM:i:29	MQ:i:29	OQ:Z:HHHHHHHHHHHHHHHHHHHHHHHHHHGGHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHGGHHHHHHHHHHHHHHHHHHHHHHGHHHGG	UQ:i:0
+20GAVAAXX100126:8:67:10895:75253	147	chr1	10007475	60	101M	=	10007283	-292	GCTCTGGCACTTGAATAAAAGCTATCCTAAAATATTACAAATTCTAGAATTTACCTTCACAAAAACTTTTTCATTAACTAGGAGGCTTTTTTTTTTGGATA	;DBCCAB at CAAC?BCBCCDB=ABA>BB?DDACAC at BBACCBCCCCECADBBCADCC@C at BBBBB:BACDCCCCDCCACCDDBDCBBDBCDCDDCB@@ACC@	MD:Z:101	PG:Z:BWA	RG:Z:20GAV.8	AM:i:37	NM:i:0	SM:i:37	MQ:i:60	OQ:Z:9@?@@>@@?@@@A at A@@A@@>@A@=AB at BBBB@BAA?ABBBAABBBBBBABB at BBAAB@BBBBB>BAABAABBBBBBBBBCBBBBABBBBBCCBCCCBBCB	UQ:i:0
+20GAVAAXX100126:8:68:20495:7123	99	chr1	10007491	60	101M	=	10007858	412	AAAAGCTATCCTAAAATATTACAAATTCTAGAATTTACCTTCACAAAAACTTTTTCATTAACTAGGAGGCTTTTTTTTTTGGATACGGAGTCTTGCTCTGT	CDDBCCDCCBBDCDDDCCCDCACDDCDBDACDDCDDCABCDBCACDDDA?CDDDDBCCDCDADCCCDCCBDDDDDDA@@@ACDCCA;CDCCCDDCCDCDDD	MD:Z:101	PG:Z:BWA	RG:Z:20GAV.8	AM:i:25	NM:i:0	SM:i:37	MQ:i:60	OQ:Z:HHHHHHHHHHHHHHHHHHHHHHHHHHHHHGHHHHHHHHHHHHHHHHHHGGHHHHHHHHHHHHHHHHHHHHHHHHHHGGGGGHHHHHHHHHIHHHHHHHHHH	UQ:i:0
+20GAVAAXX100126:8:3:11681:100672	83	chr1	10007491	60	101M	=	10007181	-410	AAAAGCTATCCTAAAATATTACAAATTCTAGAATTTACCTTCACAAAAACTTTTTCATTAACTAGGAGGCTTTTTTTTTTGGATACGGAGTCTTGCTCTGT	<E at DCCCACCCCDDDCCCDCBBDDCDDCCCB@ADDCACCAB:9>DDDDBADDDDDB>DCD@==6@<=BB6AAAADDDDDCBBCCB;BBDADCDCCCDACAC	MD:Z:101	PG:Z:BWA	RG:Z:20GAV.8	AM:i:37	NM:i:0	SM:i:37	MQ:i:60	OQ:Z:<HGHHHHFFHHHHHHHHHHHGHHHHHHHHGHGFHHHFHHFFB9EHHHHGGHHHHHHEHHHFAA9CD?HH9GGGGHHHHHHHHHHHHHHHHHHHHHHHHHHH	UQ:i:0
+20GAVAAXX100126:8:7:7502:151389	1107	chr1	10007491	60	101M	=	10007181	-410	AAAAGCTATCCTAAAATATTACAAATTCTAGAATTTACCTTCACAAAAACTTTTTCATTAACTAGGAGGCTTTTTTTTTTGGATACGGAGTCTTGCTCTGT	@EDDCCC at BCCCDDDC;?=>@@DDCDDC>@BDCDDC=BAAB@:BDDDDBC?DDDDBC>ADBCCCBBBBBAAAAADDDDDCBBC at B;BBDADCDCCCDACAC	MD:Z:101	PG:Z:BWA	RG:Z:20GAV.8	AM:i:37	NM:i:0	SM:i:37	MQ:i:60	OQ:Z:AHHHHHHEEHHHHHHHBCBDDGHHHHHHEEHHHHHH?GGFFGBHHHHHHHDHHHHHHEGHHHHHHHIHHGGGGGHHHHHHHHHIHHHHHHHHHHHHHHHHH	UQ:i:0
+20GAVAAXX100126:8:3:9830:12196	163	chr1	10007492	60	83M18S	=	10007808	416	AAAGCTATCCTAAAATATTACAAATTCTAGAATTTACCTTCACAAAAACTTTTTCATTAACTAGGAGGCTTTTTTTTTTGGATACGGAGTCTTGCTCTGTC	@DCBAAABBCDCCBDDCDCCACDDCCBDCCCDDCBB?BCB at CACBBDDADACCACDCDBD;D at BCC=CCCBDCABC at 8.67A###################	MD:Z:83	PG:Z:BWA	RG:Z:20GAV.8	AM:i:37	NM:i:0	SM:i:37	MQ:i:60	OQ:Z:BBBBBCCCBCCBBBBCBCCBBBBBBCBBCBBBCBBBBBBBABBBB at BBBBBBBBBBBBABCB@BA@@AB at AB@@@A?8-49?###################	UQ:i:0
+20GAVAAXX100126:8:4:4481:73051	163	chr1	10007500	60	101M	=	10007790	390	CCTAAAATATTACAAATTCTAGAATTTACCTTCACAAAAACTTTTTCATTAACTAGGAGGCTTTTTTTTTTGGATACGGAGTCTTGCTCTGTCCTCCAGGC	@DCAAABBBCBCA>DDCBCEDCCEDCCCBDEBBD?@?B at B@B at CACCCAC;BB;DC at DCCADCB@C>?DCABDAB>;6>98-CC@>@C=D at BB@D@?D=B<	MD:Z:101	PG:Z:BWA	RG:Z:20GAV.8	AM:i:37	NM:i:0	SM:i:37	MQ:i:60	OQ:Z:BCCCCCCCBCCCCABBBCCCCCCCCCCCCCCCBCCCCBCBBCCCBBCBCCCCCCCC?BBABBBBCB at CBBB=B at B>=><76(AA>9<AB@@@ABA@:@:=:	UQ:i:0
+20GAVAAXX100126:8:48:10097:181097	1619	chr1	10007512	29	68S27M6S	=	10007155	-383	AGAACGTATCTTCACCTGGTGAGCTCTCTATGCTCTGGCACTTGAATAAAAGCTACCCTAAAATATAGCAAATTCAAGGACTTACCTTCACAAAAGCGCTG	#####################################################################################################	MD:Z:7T2A1T14	PG:Z:BWA	RG:Z:20GAV.8	AM:i:29	NM:i:3	SM:i:29	MQ:i:29	OQ:Z:#####################################################################################################	UQ:i:6
+20GAVAAXX100126:8:3:12227:40820	611	chr1	10007513	60	35M66S	=	10007841	377	AAATTCTAGAATTTACCTTCACAAAAACTTTTTCAATAACTAGGAGGCTTTATTATTTCGAAAAGGATTACAACTCTGACCTCAAGGCTCGAGTCCAGAGG	1;?6=2;89############################################################################################	MD:Z:35	PG:Z:BWA	RG:Z:20GAV.8	AM:i:37	NM:i:0	SM:i:37	MQ:i:60	OQ:Z:554452@=@############################################################################################	UQ:i:0
+20GAVAAXX100126:8:63:18841:113901	675	chr1	10007517	60	54M47S	=	10007842	359	TCTAGAATTTACCTTCACAAAAACTTTTTCATCAACTAGGAGGCTTTTTTTTTTTGACACGGTATCTTGCTCCGTCCTACCGGAGAGATGGCGGTGGCCCG	@<75;)A(((?(*9C?4'A1 at B2?311(A6BA(AA'.+:5CA3A>0))?(*CD################################################	MD:Z:32T21	PG:Z:BWA	RG:Z:20GAV.8	AM:i:37	NM:i:1	SM:i:37	MQ:i:60	OQ:Z:A7445*?)))@*+<B?1)?.=@.?.0/(>4@?)?A*.->:BA8?@2))?(+BA################################################	UQ:i:7
+20GAVAAXX100126:8:45:16833:90513	83	chr1	10007530	60	101M	=	10007194	-436	TTCACAAAAACTTTTTCATTAACTAGGAGGCTTTTTTTTTTGGATACGGAGTCTTGCTCTGTCCTCCAGGCTGGAGTGCAGTGGCACCATCTAGGCTAACT	AE>;CDDDDBC?DADB at CDCDCC>DB@@=B><??@DDDDDCBBCCB;BBDADCDCBCDCCA at CCDCBCBBCCBBDABBBDABBB>?CBCDCCDCCCCBBCC	MD:Z:101	PG:Z:BWA	RG:Z:20GAV.8	AM:i:37	NM:i:0	SM:i:37	MQ:i:60	OQ:Z:EHCBHHHHHGHEHGHEGHHHHHHDHHGEEHEBEEEHHHHHHHHHHHHHHHHHHHHHHHHHHEHHHHHHHHHHHHHHGHHHHGGGEDHHHHHHHHHHHHHHH	UQ:i:0
+20GAVAAXX100126:8:45:16821:90529	1107	chr1	10007535	60	5S96M	=	10007194	-436	TTCACAAAAACTTTTTCATTAACTAGGAGGCTTTTTTTTTTGGATACGGAGTCTTGCTCTGTCCTCCAGGCTGGAGTGCAGTGGCACCATCTAGGCTAACT	######<<=965DDDDBADCDC>=?BBB=B4=A?ADAADDCBBCCB;BBDADCDCBCDCCADCCDCBCBBCCBBDACBBDACBBB at CBCDCCDCCCCBBCC	MD:Z:96	PG:Z:BWA	RG:Z:20GAV.8	AM:i:37	NM:i:0	SM:i:37	MQ:i:60	OQ:Z:######@@@:89HHHHHFHHHHDAAHHFEH6>GEGHGFHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHEHHHHHHHHHHHHHHH	UQ:i:0
+20GAVAAXX100126:8:24:17458:9144	83	chr1	10007539	60	101M	=	10007190	-449	ACTTTTTCATTAACTAGGAGGCTTTTTTTTTTGGATACGGAGTCTTGCTCTGTCCTCCAGGCTGGAGTGCAGTGGCACCATCTAGGCTAACTGCAACCTCT	D at E@EEDCCDCDBCCDCBDCB=A?AADDAADCBBCCC;ABDADADCBCDBCADCCDCBCBBCABBCACBBDACBBB at CBCDCCDBBCCDBCCBCDCCACCC	MD:Z:101	PG:Z:BWA	RG:Z:20GAV.8	AM:i:37	NM:i:0	SM:i:37	MQ:i:60	OQ:Z:HGHEHHHHHHHHGHHHHHHHHEGEGGHHGGHHHHHHHHIHHHHGHHHHHIHHHHHHHHHHHHFHHHHHHHHHHHHHFHHHHHHHHHHHHHHHHHHHHHHHH	UQ:i:0
+20GAVAAXX100126:8:63:6242:80411	163	chr1	10007707	60	101M	=	10007988	381	CCACACCCAGCTAATTTTTGTATTTTTAGTGGAGACGGGGTTTCACCATACTGGCCAGGCTGGTCTGGAACTCCTGACCTCAGGTGATCTGCCCGGTGAGG	@CB at A?BBCBBDBBCCCBCCBCDCCCCCCBCCCCA at 9@<B>BCB at ACCBC>CC at BCBBC<4<B7??<A=?9>A at 9;-2B<@7@<-<::7-88AA7<9=75A	MD:Z:101	PG:Z:BWA	RG:Z:20GAV.8	AM:i:37	NM:i:0	SM:i:37	MQ:i:60	OQ:Z:BBBBBBCBBBBBBBBBBCBC at BCCCCBBB@BBBBABBA?B?ABAABBAABAABA?AA at A;1;A1=;?@7;<6?@59,3@:?4;<(5586*67=@8;/44/?	UQ:i:0
+20GAVAAXX100126:8:7:17495:193398	99	chr1	10007724	60	101M	=	10007961	337	TTGTATTTTTAGTGGAGACGGGGTTTCACCATACTGGCCAGGCTGGTCTGGAACTCCTGACCTCAGGTGATCTGCCCGGTGAGGCATAACTTTTATTTCAG	<<=:AAAAA;;A=AB?@C@:=?=9 at A@B?AB?A?A at BAABA?A@;73;718;;9=8><<>?@@>?AB:@AA>=5A<=7;:<A;>?CB at A?@A?@A>==:>@	MD:Z:101	PG:Z:BWA	RG:Z:20GAV.8	AM:i:37	NM:i:0	SM:i:37	MQ:i:60	OQ:Z:GGGGGGGGGBBGAGGDFGGGDCDCGGGGGGGCGGFFGGGGGCGC=5/582555559D=?CCCCCCGGCGEFC?;G@?D?4BD at DDGGFGGAGEGGBBB>CG	UQ:i:0
+20GAVAAXX100126:8:68:12222:58992	99	chr1	10007740	60	101M	=	10008056	416	GACGGGGTTTCACCATACTGGCCAGGCTGGTCTGGAACTCCTGACCTCAGGTGATCTGCCCGGTGAGGCATAACTTTTATTTCAGTCTCACATTTCAGTTT	CD at 9CCCCDDBCABCCCADBCBBCCCADBC;BCBCDD?DBBCBAABCBCC?BBACBDBBBB;BCBDCCBCCCDADDDD>C?A at CCCBDBCACCDDCADBEE	MD:Z:101	PG:Z:BWA	RG:Z:20GAV.8	AM:i:37	NM:i:0	SM:i:37	MQ:i:60	OQ:Z:HHHHHHHHHHHHHHHHHHHHHHHHHHIHHHCHHHHHHGHHHHHFHHHHHHFGHFHHHHHHHHGHHHHHHHHHHHHHHHDHEGGHHHHHHHHIHHHHEHFHH	UQ:i:0
+20GAVAAXX100126:8:44:5440:118213	163	chr1	10007743	60	101M	=	10008043	400	GGGGTTTCACCATACTGGCCAGGCTGGTCTGGAACTCCTGACCTCAGGTGATCTGCCCGGTGAGGCATAACTTTTATTTCAGTCTCACATTTCAGTTTGTT	@CCBA?BBCACCCABDCCCDCBCCA at A9B;?C;C7;>@3:;8CA@=@B5A:9@;A at CC:@6=:<C=783?:BCAB9:BC1-3 at 6@@C?8>?A=:@:AD at AA	MD:Z:101	PG:Z:BWA	RG:Z:20GAV.8	AM:i:37	NM:i:0	SM:i:37	MQ:i:60	OQ:Z:BBBBACBBBCCBBBCBCBCCBABC>?@4B8>B8A<<AA3>=<B=B<<@0><:=<>=BB?>3<7<A;970<=:@B at 9:@@/+063=<?@7:>?96:3<@@7>	UQ:i:0
+20GAVAAXX100126:8:4:4481:73051	83	chr1	10007790	60	101M	=	10007500	-390	GTGATCTGCCCGGTGAGGCATAACTTTTATTTCAGTCTCACATTTCAGTTTGTTCTGTGGTCTCCTCCTTTATTTGTTGCTAGGTAAAAAACATTTTTTTT	BECCDCDCCC;CACBDCBCCCDCAAADACDDDBDADCDBCBCDDDBDADACADDCCACBADCDCCDC at ADCCDDCADCBCCDBABAADDDCBBAADDBDDC	MD:Z:101	PG:Z:BWA	RG:Z:20GAV.8	AM:i:37	NM:i:0	SM:i:37	MQ:i:60	OQ:Z:HHHHHHHHHHHHHHHHHHHHHHHGGGHGHHHHHHHHHHHHHHHHHHHHHGHHHHHHHHHHHHHHHHHGGHHHHHHHHHHHHHHHGGGHHHHHGGGHHHHHH	UQ:i:0
+20GAVAAXX100126:8:45:3840:54807	83	chr1	10007795	60	101M	=	10007468	-427	CTGCCCGGTGAGGCATAACTTTTATTTCAGTCTCACATTTCAGTTTGTTCTGTGGTCTCCTCCTTTATTTGTTGCTAGGTAAAAAACATTTTTTTTTTTTT	@A@??:A?BACAA>BB at A<=>AABAAB at B?CAB>A?BAACAC at AAC?@C>C<@A<A46&<;::;AB=?AA<A?A?===;<;:AAABA><<<<;<;@@:>=<	MD:Z:101	PG:Z:BWA	RG:Z:20GAV.8	AM:i:37	NM:i:0	SM:i:37	MQ:i:60	OQ:Z:GGGECGGGGGGGGCGGGGBBBGGGGGGGGGGFFEFEGGGGGGGGGGGCGEGEEGEE69*<5<@@GGADGFEGEGCD?EE4 at BGGGGG?BBBBBBBGGGGGG	UQ:i:0
+20GAVAAXX100126:8:42:6558:108923	83	chr1	10007800	60	101M	=	10007468	-432	CGGTGAGGCATAACTTTTATTTCAGTCTCACATTTCAGTTTGTTCTGTGGTCTCCTCCTTTATTTGTTGCTAGGTAAAAAACATTTTTTTTTTTTTTTTTT	8D>DCD?A?=?;C>@=D>9DD9:<896::67?DADB=28<>/>@7<37@;701+.4=3<@=+;;<1>=;7:@?>1<;AAAA=:????>>??>>>>DDBDDC	MD:Z:101	PG:Z:BWA	RG:Z:20GAV.8	AM:i:37	NM:i:0	SM:i:37	MQ:i:60	OQ:Z:GHGHHHDFDBDBHCC at HE=HH55544;=<6;EHGHH?6;@A3AD9>8:C?6022/3A7<CD.4443AA<:@CFF6@@GGGFDBEEEEEEEEEEEEHHHHHH	UQ:i:0
+20GAVAAXX100126:8:3:9830:12196	83	chr1	10007808	60	101M	=	10007492	-416	GATAACTTTTATTTCAGTCTCACATTTCAGTTTGTTCTGTGGTCTCCTCCTTTATTTGTTGCTAGGTAAAAAACATTTTTTTTTTTTTTTTTTTGCTGGTT	#><BB>;:??=BBBAB89:1:::,9:D>D=DBB?@B==:8=:<=88CAC>>AB3AAC8?CB:C?BA:=@DD>@=1>AAAAAAAAAAAADDDDDCCCC@@DC	MD:Z:0C100	PG:Z:BWA	RG:Z:20GAV.8	AM:i:37	NM:i:1	SM:i:37	MQ:i:60	OQ:Z:#CBFFB<<AD at FFFFF4443445/45HCHCHFGFDF4<<:=?=?94HFHD?GG6GGH at DHHBHDHH<CGHHDF?7<GGGGGGGGGGGGHHHHHHHHHHHHH	UQ:i:2
+20GAVAAXX100126:8:3:8864:24332	1187	chr1	10007819	60	83M18S	=	10008145	426	TTTCAGTCTCACATTTCAGTTTGTTCTGTGGTCTCCTCCTTTATTTGTTGCTAGGTAAAAAACATTTTTTTTTTTTTTTTTTTTGTTGGTTTCAGGGGAAT	@BAAAA at BDBCACABCBCCACCBACBDCBCCBBDABBAACBBBCACCBCC@DBADC at CBCBB>@CD at BDCBDCABCBACBBA###################	MD:Z:83	PG:Z:BWA	RG:Z:20GAV.8	AM:i:37	NM:i:0	SM:i:37	MQ:i:60	OQ:Z:BCCBBBBCBBBBBCCBBBCBCBBBBBBBABB at BBBBBBBBBABBBBBAABBBABB@@@@AA@?@BAB at AAAB@B at A@B at BAB###################	UQ:i:0
+20GAVAAXX100126:8:3:8873:24347	163	chr1	10007819	60	83M18S	=	10008145	426	TTTCAGTCTCACATTTCAGTTTGTTCTGTGGTCTCCTCCTTTATTTGTTGCTAGGTAAAAAACATTTTTTTTTTTTTTTTTTTTTTGGTTTCCAGGGAATT	@BAAAA at BDBCACABBBCCACCBACBDCBCCBBDABBAACBCBCACCBCC@DAADC at DBCBB??BD at CDCACDBBBBBC?BA###################	MD:Z:83	PG:Z:BWA	RG:Z:20GAV.8	AM:i:37	NM:i:0	SM:i:37	MQ:i:60	OQ:Z:BCCBBBBCBBBBBCCCBBCBCCBBBBBBABBABBBBBBBBBBBBBABABBBB at BB?@A at AA@@?AAAABAB at AA@BAAB>AB###################	UQ:i:0
+20GAVAAXX100126:8:3:12227:40820	659	chr1	10007841	60	51S50M	=	10007513	-377	GTGAGCTGCGACGTGAGGCATAACTTTTATTTCAGTCTCTCATTTCAGTTTGTTCTGTGGTCTCCTCATTTATTTGTTGCTAGGTAAAAAACCTTTTTTTT	####################################################@9B at -3A='&77,''&9=@6%343A>4A.43<2B456B;A'4C76:>D@	MD:Z:16C24A8	PG:Z:BWA	RG:Z:20GAV.8	AM:i:37	NM:i:2	SM:i:37	MQ:i:60	OQ:Z:####################################################?5@?//A@''9<-'''78 at 4%.12?:3 at -02;1 at 277@7@'1B627=BB	UQ:i:11
+20GAVAAXX100126:8:63:18841:113901	595	chr1	10007842	60	66S35M	=	10007517	-359	ACTCCTGACCTCAGGTGATCTGCCCGCTGAGGCATAACTTTTATTTCAGTATCACATTTCAGTTTGTTCTGTGGTCTGCTCCTTTATTTGTTGCTAGGTAA	#####################################################################################################	MD:Z:11C23	PG:Z:BWA	RG:Z:20GAV.8	AM:i:37	NM:i:1	SM:i:37	MQ:i:60	OQ:Z:#####################################################################################################	UQ:i:2
+20GAVAAXX100126:8:68:20495:7123	147	chr1	10007858	60	55S46M	=	10007491	-412	TGAGGCATAACTTTTATTTCAGTCTCACATTTCAGTTTGTTCTGTGGTCTCCTCCTTTTTTTGTTGCTAGGTAAAAAACATTTTTTTTTTTTTTTTTTTTG	########################################################@B);C9,?33277?85ACCCC92(ADDDDDDBCDCCCCCBBCCC@	MD:Z:3A40G0C0	PG:Z:BWA	RG:Z:20GAV.8	AM:i:25	NM:i:3	SM:i:25	MQ:i:60	OQ:Z:########################################################A?)<B</@65074<85>BCCB5.(>BBBBBBBBBBBBBBBBBBBB	UQ:i:73
+20GAVAAXX100126:8:64:7784:120262	163	chr1	10007860	60	42M59S	=	10008147	387	TATTTGTTGCTAGGTAAAAAACATTTTTTTTTTTTTTTTTTTTCTGGTTTCCGGGAATTTTAAAAAATAACTAAAGGCCCGTTTCTTTGGAGTTTCTCAGG	@CBB?A at BBBDCBABCDDDDD@BCCCCCCCCCCCBBABBB?############################################################	MD:Z:42	PG:Z:BWA	RG:Z:20GAV.8	AM:i:37	NM:i:0	SM:i:37	MQ:i:60	OQ:Z:BBCBCBBBBCBBCC at BBBBBBAABCCBBBBBBBBBBBBBB@############################################################	UQ:i:0
+20GAVAAXX100126:8:61:17876:93642	147	chr1	10007872	29	66S35M	=	10007468	-438	GGATTAACTTTTTTTTCATCTTCACTTTCAGGTTTGTCTTGTGGTCCCCCCTTTTTTTTTTTCCAGGGAAAAAAAATTTTTTTTTTTTTTTTTTTTGCTGG	#####################################################################ACCCA-')CEEEEEDEDDBCDCCCCCBABBC@	MD:Z:2T6C0A24	PG:Z:BWA	RG:Z:20GAV.8	AM:i:29	NM:i:3	SM:i:29	MQ:i:29	OQ:Z:#####################################################################?BBB?-''ACCCCCBCBBBBCBBBBBBBBBBB	UQ:i:16
+20GAVAAXX100126:8:62:20479:199378	99	chr1	10007875	60	8M1D78M15S	=	10008195	420	AAAAAACATTTTTTTTTTTTTTTTTTGCTGGTTTCCAGGTAATTCTAAGAACTAACTAAGGTCCTGTTGCTTGGTGGTTACTAAGGGGGGCAGACAGAGTA	CDDBDDABBDDDDDAAAAAAAAAA at 3+36;;@@@?A?@@;:=:<.6;;0<A<?BA3>9;<C:B?A;;:<9<::541$:,8?=><A################	MD:Z:8^T67A10	PG:Z:BWA	RG:Z:20GAV.8	AM:i:37	NM:i:2	SM:i:37	MQ:i:60	OQ:Z:HHHHHHHGGHHHHHGGGGGGGGGGG6-;;>BFFFFGCGF=><=?/34504FDDGF34555HBHCF54445555531-425FBDBF################	UQ:i:16
+20GAVAAXX100126:8:7:17495:193398	147	chr1	10007961	60	101M	=	10007724	-337	GGAGGCAGACAGAGTATTTTGCACCATCCAAAGGAGGTAATGTAATGCTTAAATGGAAGAAACTGAACCAAACAACGAAAATATGGGCTATGTATTACAAA	CD<4A<8)A9:C9%5?-ADA6 at AA=@48<?@AC at 9CA>=<B?BB?C?9CBACCCC>4A<>A<:;4<AC:@@BACA:BCCCDD at DBDCACCCABCBA@ABC@	MD:Z:101	PG:Z:BWA	RG:Z:20GAV.8	AM:i:37	NM:i:0	SM:i:37	MQ:i:60	OQ:Z:BA70=91)<66B8%1;,?B?6@;@>?1;89@>AC:AA?;;B?C>>@<;@BBBBBB>5<>>A>>=:>BB8=>A?A?ABBCCCC?CACCCCBCCBB at B;ABBB	UQ:i:0
+20GAVAAXX100126:8:63:6242:80411	83	chr1	10007988	60	101M	=	10007707	-381	CCAAAGGAGGTAATGTAATGCTTAAATGGAAGAAACTGAACCAAACAACGAAAATATGGGCTATGTATTACAAACAACTCTGACACACTGTTATTTATGAT	DDDDDCCDCACDCCACDCCBCDCDDCCBBDDBDDBCCBDCCBDDCBDB;BDDDCCCCBBBCCCCACCDCBBDDBBDBCDCCBBBBBBCCADCCDDCCABCC	MD:Z:101	PG:Z:BWA	RG:Z:20GAV.8	AM:i:37	NM:i:0	SM:i:37	MQ:i:60	OQ:Z:HHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHH	UQ:i:0
+20GAVAAXX100126:8:44:5440:118213	83	chr1	10008043	60	101M	=	10007743	-400	ATGGGCTATGTATTACAAACAACTCTGACACACTGTTATTTATGATATTATAGGAAAGCTTCTCCCAAGGAAAGTGGTGGAAACTCCATCACTTAGACAAG	DECCCCCCCACCDCCBDDCBDCCDCCBBBBBCCCADCCDDCCCBCCCDCCCCBBDDCBCDDCDCCBDCBBDDDACBACBBDDBCDCBCDBCCDCDBC at CDC	MD:Z:101	PG:Z:BWA	RG:Z:20GAV.8	AM:i:37	NM:i:0	SM:i:37	MQ:i:60	OQ:Z:HHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHH	UQ:i:0
+20GAVAAXX100126:8:4:14239:56438	611	chr1	10008048	60	35M66S	=	10008306	358	CTATGTATTACAAACAACTCTGACACACTGTTATTTATGATATTATAGGAAAGCTTCTCCCAAGGAAAGTGGTGGAAGATCCATCACTTAGACAAGTTAGA	#####################################################################################################	MD:Z:35	PG:Z:BWA	RG:Z:20GAV.8	AM:i:37	NM:i:0	SM:i:37	MQ:i:60	OQ:Z:#####################################################################################################	UQ:i:0
+20GAVAAXX100126:8:68:12222:58992	147	chr1	10008056	60	101M	=	10007740	-416	TACAAACAACTCTGACACACTGTTATTTATGATATTATAGGAAAGCTTCTCCCAAGGAAAGTGGTGGAAACTCCATCACTTAGACAAGTTAGAACACAACT	BA:CD at CBCAAC@ACCBACAB at DAACCADD:CCC?CCBDC at CAD@CD at CCADBCDD@CCD at BA>>@@CCBCCCCCCCACEDECACBD at DCDBCAA@?@AC@	MD:Z:101	PG:Z:BWA	RG:Z:20GAV.8	AM:i:37	NM:i:0	SM:i:37	MQ:i:60	OQ:Z:A77=A<A@?B?A at BABAAABBBBBABABBBCBBB@BBBBBAB?BCBBABBBCBBBCBCBBBBBCCCCBBBCBBCBBCBCCCCCBCCCCCCCCBBCBCCBCB	UQ:i:0
+20GAVAAXX100126:8:63:20674:138624	163	chr1	10008082	60	101M	=	10008392	410	TTATGATATTATAGGAAAGCTTCTCCCAAGGAAAGTGGTGGAAACTCCATCACTTAGACAAGTTAGAACACAACTGTAAAGGTACTAAAAAGTGTATTAGA	@CBB?BBBCCBCBACCDDCBDCBDBDCCDCCCDDB>AB>AABCC?DCCCD at CABDCCDACBCBBCC?D at B?CD?CAA?BBBA@@@ECC?D at BAACACC@DC	MD:Z:101	PG:Z:BWA	RG:Z:20GAV.8	AM:i:37	NM:i:0	SM:i:37	MQ:i:60	OQ:Z:BBBBCBBBCBBBBBBBBBBBBBBBBCBBBBBBBBB at BB@BAABABBBBBBBBABBBBBBAAB at ABB@B@@AAABAB???@A at 7@ABAA?A?A<A>@A?@@@	UQ:i:0
+20GAVAAXX100126:8:45:11956:153764	1699	chr1	10008108	29	56M1D3M1I41M	=	10008497	423	CAAGGAAAGTGGTGGACACTCCATCACTTAGACAAGTTAGCACACCCGTGTAAAGGACTCATTTAGTGTCTCAGTGACATTTCTACTGTAATAGCCACTGG	>:5=A7=C?A?8+5<:-+76;A86)B12C9>C45);641+&B2/?+4%,<?/*?7C6;();&''3@?B-)B9+8,AB,DBB8)2(B9+-B=(15(6CBBBB	MD:Z:16A23A4A0A0C8^T4A0A0A5A1T2A2G3C0A1C6A2A1C4	PG:Z:BWA	RG:Z:20GAV.8	AM:i:29	NM:i:20	SM:i:29	MQ:i:29	OQ:Z:;64<B68B;B at 7)7;7-*528 at 43)@0-A9<B52)>775+)A4,B+1))8A/)@1A28')<''(0>AA))A2)7*BB,BBB7(-)B2*(@<(.1)4@ [...]
+20GAVAAXX100126:8:45:11971:153753	163	chr1	10008108	60	101M	=	10008431	423	CAAGGAAAGTGGTGGAAACTCCATCACTTAGACAAGTTAGAACACAACTGTAAAGGTACTAAAAAGTGTATTAGAGAGATTCATCCTGTAAAAGACCCTGG	@CCBAACCBBBC>ACCDD at DBCCCACACCBCCAC?B;AA@?BAC=BCACB=BC at CB?AACB at C?CC:AABACBABAB at DA@@DAACDA<BA>BAC>4CBCC	MD:Z:101	PG:Z:BWA	RG:Z:20GAV.8	AM:i:37	NM:i:0	SM:i:37	MQ:i:60	OQ:Z:BBBBBABBB at BB?BBBBBABBBBBABBABABABA at B?ABA at ABBAAABAA?BAAA@;@BAB>A?@A<@:AA@@A@@@?A@?@A@@@??<@@;>??>2@@>A	UQ:i:0
+20GAVAAXX100126:8:3:8864:24332	1107	chr1	10008145	60	101M	=	10007819	-426	TAGAACACAACTGTAAAGGTACTAAAAAGTGTATTAGAGAGATTCATCCTGTAAAAGACCCTGGGGGCTGAGTGTGGTGGCTCATGCCTGTAACCCTAACA	DECDBCCCDCCCACDDDCACCCCDDDDDACACCDCDBDBDBCDDBCDCCCACDDDCBBCCCCBBBBBCCBDACACBACBBCDBCCBCCCACDCCCCCBBBC	MD:Z:101	PG:Z:BWA	RG:Z:20GAV.8	AM:i:37	NM:i:0	SM:i:37	MQ:i:60	OQ:Z:HHHHFHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHH	UQ:i:0
+20GAVAAXX100126:8:3:8873:24347	83	chr1	10008145	60	101M	=	10007819	-426	TAGAACACAACTGTAAAGGTACTAAAAAGTGTATTAGAGAGATTCATCCTGTAAAAGACCCTGGGGGCTGAGTGTGGTGGCTCATGCCTGTAACCCTAACA	DECDCCCCDCCCACDDDCACCCCDDDDDACACCDCDBDBDBCDDBCDCCCACDDDCBACCCCBBBBBCCBDACACBACBBCDBCCBCCCACDCCCCCBBBC	MD:Z:101	PG:Z:BWA	RG:Z:20GAV.8	AM:i:37	NM:i:0	SM:i:37	MQ:i:60	OQ:Z:HHHHHHHHHHHHHHIHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHIHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHH	UQ:i:0
+20GAVAAXX100126:8:64:7784:120262	83	chr1	10008147	60	101M	=	10007860	-387	GAACACAACTGTAAAGGTACTAAAAAGTGTATTAGAGAGATTCATCCTGTAAAAGACCCTGGGGGCTGAGTGTGGTGGCTCATGCCTGTAACCCTAACACT	DECCCCDCCCACDDDCACCCCDDDDDACACCDCDBDBDBCDDBCDCCCACDDDDBACCCCBBBBBCCBCACACBACBBCDBCCBCCCACDCCCCCDC at BCC	MD:Z:101	PG:Z:BWA	RG:Z:20GAV.8	AM:i:37	NM:i:0	SM:i:37	MQ:i:60	OQ:Z:HHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHIHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHH	UQ:i:0
+20GAVAAXX100126:8:4:10255:86573	99	chr1	10008172	60	101M	=	10008499	427	AGTGTATTAGAGAGATTCATCCTGTAAAAGACCCTGGGGGCTGAGTGTGGTGGCTCATGCCTGTAACCCTAACACTTTGGGAGGGTGAAGCAGAAGGATCA	CCB at CCCDCCDCDCDCDBCCBBCBBCDDDCDABBCBCCCCBCBDCBBBBCBBCBDBCCBBBDBCCD=BBDCDACADDDBCCDCCB<CDDCCCCDDCDDCD=	MD:Z:101	PG:Z:BWA	RG:Z:20GAV.8	AM:i:37	NM:i:0	SM:i:37	MQ:i:60	OQ:Z:HHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHGHHHHHHHHHHHHHHHEHHHHHHHHHHHHHHHHHGCHHHHHHHHHHHHHH?	UQ:i:0
+20GAVAAXX100126:8:1:9991:44859	163	chr1	10008183	60	101M	=	10008551	429	GAGATTCATCCTGTAAAAGACCCTGGGGGCTGAGTGTGGTGGCTCATGCCTGTAACCCTAACACTTTGGGAGGGTGAAGCAGAAGGATCACTTGAGTCCAG	@CB at B?ABCBADB<CEEECCBDDECDDCCCECCC;A??@;BCAD at CC@ABBBB at DBCCDCBAC@DC7B<BABD.6A80<-5;@%?9::=B4>7)(=DB@@B	MD:Z:101	PG:Z:BWA	RG:Z:20GAV.8	AM:i:37	NM:i:0	SM:i:37	MQ:i:60	OQ:Z:@AB?BCCBCBABCCCCCCCCCCCCCCCBBCCCBC<BBCA=BBCBBBA>A?BBABBCBBBBBBBBBBCA:@B>B34B7.8.3::%=859B=5:3(':@>>8C	UQ:i:0
+20GAVAAXX100126:8:5:20728:120252	163	chr1	10008188	60	93M8S	=	10008458	370	TCATCCTGTAAAAGACCCTGGGGGCTGAGTGTGGTGGCTCATGCCTGTAACCCTAACACTTTGGGAGGGTGAAGCAGAAGGATCACTTGAGTCCAGGAGTT	@BBBAABBABCDCABACCDBCCCCABBBC at CBBC::7<=<>>;?==B?>?7 at C9AC???CBC@?A5?@B=<>B<:A==27=6;=@@>B77:B#########	MD:Z:93	PG:Z:BWA	RG:Z:20GAV.8	AM:i:37	NM:i:0	SM:i:37	MQ:i:60	OQ:Z:BBBBBBCBBBBBBB?BBBBBBBBBA at B?B=B?BA9==?????==@<A9?:<@?:?A?9?AAA???1A??6>6?<:?=<.6=45==@6 at 519?#########	UQ:i:0
+20GAVAAXX100126:8:62:20479:199378	147	chr1	10008195	60	101M	=	10007875	-420	GTAAAAGACCCTGGGGGCTGAGTGTGGTGGCTCATGCCTGTAACCCTAACACTTTGGGAGGGTGAAGCAGAAGGATCACTTGAGTCCAGGAGTTTGAGACC	ADB;@BB?C:AC at BDC7AD@C at D?BA at ABBACBB@?CBC at BC@D9CCAB?>CCDCCACCBB@?AAC at CDCBECBCCCBCEDCEBCCCBCCDADCA@AAAC@	MD:Z:101	PG:Z:BWA	RG:Z:20GAV.8	AM:i:37	NM:i:0	SM:i:37	MQ:i:60	OQ:Z:BA at 4;??<A:A at AAB?6BA at BBBAA?BB at ABAAAA=BBBCBB=B9ABB=@@BBBBBBCCCBBCBBBCBCCCCBBBCCACCCCCCBCCCCCCCCCCCCCBBB	UQ:i:0
+20GAVAAXX100126:8:43:9142:90413	99	chr1	10008198	60	101M	=	10008465	366	AAAGACCCTGGGGGCTGAGTGTGGTGGCTCATGCCTGTAACCCTAACACTTTGGGAGGGTGAAGCAGAAGGATCACTTGAGTCCAGGAGTTTGAGACCAGC	CDDADACCDBCCCCBDBDCCBBBCABCBDBCCBBBCBBCDABBCCDACACDDBCCDCCB:BDDCBCCDDCCDC at CAD@ADCCBABCBBACDACDCDACADB	MD:Z:101	PG:Z:BWA	RG:Z:20GAV.8	AM:i:37	NM:i:0	SM:i:37	MQ:i:60	OQ:Z:HHHHHHHHHHHHHHHHHHHHHHHHGHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHGCHHHHHHHHHHHHHGIHHGIHHHHIGHGFGHHGHIHHHHGHF	UQ:i:0
diff --git a/public/gatk-queue-extensions-generator/pom.xml b/public/gatk-queue-extensions-generator/pom.xml
new file mode 100644
index 0000000..296ca52
--- /dev/null
+++ b/public/gatk-queue-extensions-generator/pom.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+    <modelVersion>4.0.0</modelVersion>
+
+    <parent>
+        <groupId>org.broadinstitute.gatk</groupId>
+        <artifactId>gatk-aggregator</artifactId>
+        <version>3.3</version>
+        <relativePath>../..</relativePath>
+    </parent>
+
+    <artifactId>gatk-queue-extensions-generator</artifactId>
+    <packaging>jar</packaging>
+    <name>GATK Queue Extensions Generator</name>
+    <description>GATK Queue Extensions Generator</description>
+
+    <properties>
+        <gatk.basedir>${project.basedir}/../..</gatk.basedir>
+    </properties>
+
+    <dependencies>
+        <dependency>
+            <groupId>${project.groupId}</groupId>
+            <artifactId>gatk-tools-public</artifactId>
+            <version>${project.version}</version>
+        </dependency>
+    </dependencies>
+
+</project>
diff --git a/public/gatk-queue-extensions-generator/src/main/java/org/broadinstitute/gatk/queue/extensions/gatk/ArgumentDefinitionField.java b/public/gatk-queue-extensions-generator/src/main/java/org/broadinstitute/gatk/queue/extensions/gatk/ArgumentDefinitionField.java
new file mode 100644
index 0000000..1e9e5cc
--- /dev/null
+++ b/public/gatk-queue-extensions-generator/src/main/java/org/broadinstitute/gatk/queue/extensions/gatk/ArgumentDefinitionField.java
@@ -0,0 +1,558 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.queue.extensions.gatk;
+import htsjdk.samtools.BAMIndex;
+import htsjdk.samtools.SAMFileWriter;
+import htsjdk.tribble.Tribble;
+import org.broadinstitute.gatk.engine.arguments.GATKArgumentCollection;
+import org.broadinstitute.gatk.utils.commandline.*;
+import htsjdk.variant.variantcontext.writer.VariantContextWriter;
+
+import java.io.File;
+import java.lang.annotation.Annotation;
+import java.lang.reflect.Field;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+
+public abstract class ArgumentDefinitionField extends ArgumentField {
+
+    protected final ArgumentDefinition argumentDefinition;
+    protected ArgumentDefinitionField(ArgumentDefinition argumentDefinition) {
+        this.argumentDefinition = argumentDefinition;
+    }
+
+    @Override protected String getRawFieldName() { return argumentDefinition.fullName; }
+    @Override protected Class<? extends Annotation> getAnnotationIOClass() { return argumentDefinition.ioType.annotationClass; }
+    @Override protected String getDoc() { return escape(argumentDefinition.doc); }
+    @Override protected String getFullName() { return escape(argumentDefinition.fullName); }
+    @Override protected String getShortName() { return escape(argumentDefinition.shortName); }
+    @Override protected boolean isRequired() { return argumentDefinition.required; }
+    @Override protected String getExclusiveOf() { return escape(argumentDefinition.exclusiveOf); }
+    @Override protected String getValidation() { return escape(argumentDefinition.validation); }
+    protected boolean isFlag() { return argumentDefinition.isFlag; }
+    protected boolean isMultiValued() { return argumentDefinition.isMultiValued; }
+
+    protected final String getShortFieldGetter() { return getFieldName(getRawShortFieldName()); }
+    protected final String getShortFieldSetter() { return getFieldName(getRawShortFieldName() + "_="); }
+    protected String getRawShortFieldName() { return argumentDefinition.shortName; }
+    @Override protected String getDefineAddition() {
+        if (argumentDefinition.shortName == null)
+            return "";
+        else if(getShortFieldGetter().equals(getFieldName()))
+            return "";
+        else
+            return String.format("%n" +
+                    "/**%n" +
+                    " * Short name of %1$s%n" +
+                    " * @return Short name of %1$s%n" +
+                    " */%n" +
+                    "%5$sdef %3$s = this.%1$s%n" +
+                    "%n" +
+                    "/**%n" +
+                    " * Short name of %1$s%n" +
+                    " * @param value Short name of %1$s%n" +
+                    " */%n" +
+                    "%5$sdef %4$s(value: %2$s) { this.%1$s = value }%n",
+                    getFieldName(),
+                    getFieldType(),
+                    getShortFieldGetter(),
+                    getShortFieldSetter(),
+                    getPrivacy());
+    }
+
+    protected static final String REQUIRED_TEMPLATE = " + required(\"%1$s\", %3$s, spaceSeparated=true, escape=true, format=%2$s)";
+    protected static final String REPEAT_TEMPLATE = " + repeat(\"%1$s\", %3$s, spaceSeparated=true, escape=true, format=%2$s)";
+    protected static final String OPTIONAL_TEMPLATE = " + optional(\"%1$s\", %3$s, spaceSeparated=true, escape=true, format=%2$s)";
+    protected static final String FLAG_TEMPLATE = " + conditional(%3$s, \"%1$s\", escape=true, format=%2$s)";
+
+    public final String getCommandLineAddition() {
+        return String.format(getCommandLineTemplate(), getCommandLineParam(), getCommandLineFormat(), getFieldName());
+    }
+
+    protected String getCommandLineParam() {
+        return (argumentDefinition.shortName != null)
+                ? "-" + argumentDefinition.shortName
+                : "--" + argumentDefinition.fullName;
+    }
+
+    protected String getCommandLineFormat() {
+        return "\"%s\"";
+    }
+
+    @Override
+    protected String getGatherAnnotation() {
+        return "";
+    }
+
+    protected String getCommandLineTemplate() {
+        if (isFlag()) return FLAG_TEMPLATE;
+        if (isMultiValued()) return REPEAT_TEMPLATE;
+        if (isRequired()) return REQUIRED_TEMPLATE;
+        return OPTIONAL_TEMPLATE;
+    }
+
+    public static List<? extends ArgumentField> getArgumentFields(ParsingEngine parsingEngine,Class<?> classType) {
+        List<ArgumentField> argumentFields = new ArrayList<>();
+        for (ArgumentSource argumentSource: parsingEngine.extractArgumentSources(classType))
+            if (!argumentSource.isDeprecated()) {
+                String gatherer = null;
+                if (argumentSource.field.isAnnotationPresent(Gather.class)) {
+                    Gather gather = argumentSource.field.getAnnotation(Gather.class);
+                    if(! "".equals(gather.className()))
+                        gatherer = gather.className();
+                    else
+                        gatherer = gather.value().getName();
+                }
+                for (ArgumentDefinition argumentDefinition: argumentSource.createArgumentDefinitions())
+                    argumentFields.addAll(getArgumentFields(argumentDefinition, gatherer));
+            }
+        return argumentFields;
+    }
+
+    public static String getArgumentFullName(final Class<?> collection, final String fieldName) {
+        try {
+            final Field field = collection.getField(fieldName);
+            final Argument arg = field.getAnnotation(Argument.class);
+            if (arg != null)
+                return arg.fullName();
+            final Input inputAnnotation = field.getAnnotation(Input.class);
+            if (inputAnnotation != null)
+                return inputAnnotation.fullName();
+            final Output outputAnnotation = field.getAnnotation(Output.class);
+            if (outputAnnotation != null)
+                return outputAnnotation.fullName();
+        } catch (NoSuchFieldException e) {
+            throw new IllegalStateException(String.format("Can't find field %s in ArgumentCollection %s", fieldName, collection.getSimpleName()), e);
+        }
+        throw new IllegalStateException(String.format("Field %s in class %s is not annotated as an argument", fieldName, collection.getName()));
+    }
+
+    private static final List<String> intervalFields = new ArrayList<>();
+    private static final String inputFileArgument = getArgumentFullName(GATKArgumentCollection.class, "samFiles");
+
+    static {
+        intervalFields.add(getArgumentFullName(IntervalArgumentCollection.class, "intervals"));
+        intervalFields.add(getArgumentFullName(IntervalArgumentCollection.class, "excludeIntervals"));
+    }
+
+    private static List<? extends ArgumentField> getArgumentFields(ArgumentDefinition argumentDefinition, String gatherer) {
+        if (intervalFields.contains(argumentDefinition.fullName) && argumentDefinition.ioType == ArgumentIOType.INPUT) {
+            return Arrays.asList(
+                    new IntervalFileArgumentField(argumentDefinition),
+                    new IntervalStringArgumentField(argumentDefinition));
+
+        } else if (NumThreadsArgumentField.NUM_THREADS_FIELD.equals(argumentDefinition.fullName)) {
+            return Arrays.asList(new NumThreadsArgumentField(argumentDefinition));
+
+        } else if (inputFileArgument.equals(argumentDefinition.fullName) && argumentDefinition.ioType == ArgumentIOType.INPUT) {
+            return Arrays.asList(new InputTaggedFileDefinitionField(argumentDefinition), new InputIndexesArgumentField(argumentDefinition, BAMIndex.BAMIndexSuffix, ".bam"));
+
+        } else if ((RodBinding.class.equals(argumentDefinition.argumentType) || RodBinding.class.equals(argumentDefinition.componentType) || RodBindingCollection.class.equals(argumentDefinition.componentType)) && argumentDefinition.ioType == ArgumentIOType.INPUT) {
+            return Arrays.asList(new InputTaggedFileDefinitionField(argumentDefinition), new InputIndexesArgumentField(argumentDefinition, Tribble.STANDARD_INDEX_EXTENSION));
+
+        } else if (argumentDefinition.ioType == ArgumentIOType.INPUT) {
+            return Collections.singletonList(new InputArgumentField(argumentDefinition));
+
+        } else if (argumentDefinition.ioType == ArgumentIOType.OUTPUT) {
+
+            List<ArgumentField> fields = new ArrayList<>();
+
+            String gatherClass;
+
+            // one can set the specific gatherer to use by adding @Gather before any output argument.
+            // For example (used to be part of UG):
+            //      @Gather(className = "org.broadinstitute.gatk.queue.extensions.gatk.CatVariantsGatherer")
+            //      @Output(doc="File to which variants should be written",required=true)
+            //      protected VariantContextWriter writer = null;
+            if (gatherer != null)
+                gatherClass = gatherer;
+            else if (SAMFileWriter.class.isAssignableFrom(argumentDefinition.argumentType))
+                gatherClass = "BamGatherFunction";
+            else if (VariantContextWriter.class.isAssignableFrom(argumentDefinition.argumentType))
+                gatherClass = "CatVariantsGatherer"; // used to be "VcfGatherFunction";
+            else
+                gatherClass = "org.broadinstitute.gatk.queue.function.scattergather.SimpleTextGatherFunction";
+
+            fields.add(new OutputArgumentField(argumentDefinition, gatherClass));
+
+            if (SAMFileWriter.class.isAssignableFrom(argumentDefinition.argumentType)) {
+                fields.add(new SAMFileWriterIndexArgumentField(argumentDefinition));
+                fields.add(new SAMFileWriterMD5ArgumentField(argumentDefinition));
+            }
+            else if (VariantContextWriter.class.isAssignableFrom(argumentDefinition.argumentType)) {
+                fields.add(new VCFWriterIndexArgumentField(argumentDefinition));
+            }
+
+            return fields;
+
+        } else if (argumentDefinition.isFlag) {
+            return Collections.singletonList(new FlagArgumentField(argumentDefinition));
+
+        } else if (argumentDefinition.isMultiValued) {
+            return Collections.singletonList(new MultiValuedArgumentField(argumentDefinition));
+
+        } else if (!argumentDefinition.required && useOption(argumentDefinition.argumentType)) {
+            boolean useFormat = useFormatter(argumentDefinition.argumentType);
+            List<ArgumentField> fields = new ArrayList<>();
+            ArgumentField field = new OptionedArgumentField(argumentDefinition, useFormat);
+            fields.add(field);
+            if (useFormat) fields.add(new FormatterArgumentField(field));
+            return fields;
+
+        } else {
+            boolean useFormat = useFormatter(argumentDefinition.argumentType);
+            List<ArgumentField> fields = new ArrayList<>();
+            ArgumentField field = new DefaultArgumentField(argumentDefinition, useFormat);
+            fields.add(field);
+            if (useFormat) fields.add(new FormatterArgumentField(field));
+            return fields;
+
+        }
+    }
+
+    // if (intervalFields.contains(argumentDefinition.fullName) && argumentDefinition.ioType == ArgumentIOType.INPUT)
+    // Change intervals exclusive of intervalsString.
+    private static class IntervalFileArgumentField extends InputArgumentField {
+        public IntervalFileArgumentField(ArgumentDefinition argumentDefinition) {
+            super(argumentDefinition);
+        }
+
+        @Override
+        protected String getExclusiveOf() {
+            StringBuilder exclusiveOf = new StringBuilder(super.getExclusiveOf());
+            if (exclusiveOf.length() > 0)
+                exclusiveOf.append(",");
+            exclusiveOf.append(escape(argumentDefinition.fullName)).append("String");
+            return exclusiveOf.toString();
+        }
+    }
+
+    // if (intervalFields.contains(argumentDefinition.fullName) && argumentDefinition.ioType == ArgumentIOType.INPUT)
+    // Change intervals to a string but as an argument.
+    private static class IntervalStringArgumentField extends ArgumentDefinitionField {
+        public IntervalStringArgumentField(ArgumentDefinition argumentDefinition) {
+            super(argumentDefinition);
+        }
+
+        @SuppressWarnings("unchecked")
+        @Override protected Class<? extends Annotation> getAnnotationIOClass() { return Argument.class; }
+        @Override protected Class<?> getInnerType() { return String.class; }
+        @Override protected String getRawFieldName() { return super.getRawFieldName() + "String"; }
+        @Override protected String getFullName() { return super.getFullName() + "String"; }
+        @Override protected String getRawShortFieldName() { return super.getRawShortFieldName() + "String"; }
+        @Override protected String getFieldType() { return "Seq[String]"; }
+        @Override protected String getDefaultValue() { return "Nil"; }
+        @Override public String getCommandLineTemplate() { return REPEAT_TEMPLATE; }
+
+        @Override
+        protected String getExclusiveOf() {
+            StringBuilder exclusiveOf = new StringBuilder(super.getExclusiveOf());
+            if (exclusiveOf.length() > 0)
+                exclusiveOf.append(",");
+            exclusiveOf.append(escape(argumentDefinition.fullName));
+            return exclusiveOf.toString();
+        }
+    }
+
+    // if (argumentDefinition.ioType == ArgumentIOType.INPUT)
+    // Map all inputs to files.  Handles multi valued files.
+    private static class InputArgumentField extends ArgumentDefinitionField {
+        public InputArgumentField(ArgumentDefinition argumentDefinition) {
+            super(argumentDefinition);
+        }
+
+        @Override protected Class<?> getInnerType() { return File.class; }
+        @Override protected String getFieldType() { return isMultiValued() ? "Seq[File]" : "File"; }
+        @Override protected String getDefaultValue() { return isMultiValued() ? "Nil" : "_"; }
+    }
+
+    // if (argumentDefinition.ioType == ArgumentIOType.OUTPUT)
+    // Map all outputs to files.
+    private static class OutputArgumentField extends ArgumentDefinitionField {
+        private final String gatherClass;
+        public OutputArgumentField(ArgumentDefinition argumentDefinition, String gatherClass) {
+            super(argumentDefinition);
+            this.gatherClass = gatherClass;
+        }
+
+        @Override protected Class<?> getInnerType() { return File.class; }
+        @Override protected String getFieldType() { return "File"; }
+        @Override protected String getDefaultValue() { return "_"; }
+
+        @Override public boolean isGather() { return true; }
+        @Override protected String getGatherAnnotation() {
+            return String.format("@Gather(classOf[%s])%n", gatherClass);
+        }
+    }
+
+    // if (argumentDefinition.isFlag)
+    // Booleans should be set on the commandline only if they are true.
+    private static class FlagArgumentField extends ArgumentDefinitionField {
+        public FlagArgumentField(ArgumentDefinition argumentDefinition) {
+            super(argumentDefinition);
+        }
+
+        @Override protected Class<?> getInnerType() { return boolean.class; }
+        @Override protected String getFieldType() { return "Boolean"; }
+        @Override protected String getDefaultValue() { return "_"; }
+        @Override protected String getCommandLineTemplate() { return FLAG_TEMPLATE; }
+    }
+
+    // if (argumentDefinition.isMultiValued)
+    // Multi value arguments are mapped to List[] and use repeat.
+    private static class MultiValuedArgumentField extends ArgumentDefinitionField {
+        public MultiValuedArgumentField(ArgumentDefinition argumentDefinition) {
+            super(argumentDefinition);
+        }
+
+        @Override protected Class<?> getInnerType() { return mapType(argumentDefinition.componentType); }
+        @Override protected String getFieldType() { return String.format("Seq[%s]", getType(getInnerType())); }
+        @Override protected String getDefaultValue() { return "Nil"; }
+        @Override protected String getCommandLineTemplate() { return REPEAT_TEMPLATE; }
+    }
+
+    // if (!argumentDefinition.required && useOption(argumentDefinition.argumentType))
+    // Any optional arguments that are primitives are wrapped in options.
+    private static class OptionedArgumentField extends ArgumentDefinitionField {
+        private final boolean useFormatter;
+
+        public OptionedArgumentField(ArgumentDefinition argumentDefinition, boolean useFormatter) {
+            super(argumentDefinition);
+            this.useFormatter = useFormatter;
+        }
+
+        @Override protected Class<?> getInnerType() { return mapType(argumentDefinition.argumentType); }
+        @Override protected String getFieldType() { return String.format("Option[%s]", getType(getInnerType())); }
+        @Override protected String getDefaultValue() { return "None"; }
+        @Override protected String getCommandLineTemplate() { return OPTIONAL_TEMPLATE; }
+        @Override protected String getCommandLineFormat() {
+            return this.useFormatter ? getFieldName(this.getRawFieldName() + "Format") : super.getCommandLineFormat();
+        }
+    }
+
+    // Any other @Arguments
+    private static class DefaultArgumentField extends ArgumentDefinitionField {
+        private final boolean useFormatter;
+
+        public DefaultArgumentField(ArgumentDefinition argumentDefinition, boolean useFormatter) {
+            super(argumentDefinition);
+            this.useFormatter = useFormatter;
+        }
+
+        @Override protected Class<?> getInnerType() { return mapType(argumentDefinition.argumentType); }
+        @Override protected String getFieldType() { return getType(getInnerType()); }
+        @Override protected String getDefaultValue() { return "_"; }
+        @Override protected String getCommandLineFormat() {
+            return this.useFormatter ? getFieldName(this.getRawFieldName() + "Format") : super.getCommandLineFormat();
+        }
+    }
+
+    // Allows the user to specify the track name, track type, and the file.
+    public static class NumThreadsArgumentField extends OptionedArgumentField {
+        public static final String NUM_THREADS_FIELD = getArgumentFullName(GATKArgumentCollection.class, "numberOfDataThreads");
+        public static final String NCT_FIELD = getArgumentFullName(GATKArgumentCollection.class, "numberOfCPUThreadsPerDataThread");
+
+        public NumThreadsArgumentField(ArgumentDefinition argumentDefinition) {
+            super(argumentDefinition, false);
+        }
+
+        @Override
+        protected String getFreezeFields() {
+            return String.format("if (%1$s.isDefined) nCoresRequest = %1$s%nif (%2$s.isDefined) nCoresRequest = Some(nCoresRequest.getOrElse(1) * %2$s.getOrElse(1))%n",
+                    NUM_THREADS_FIELD, NCT_FIELD);
+        }
+    }
+
+    // Tagged input_files or other rods.
+    public static class InputTaggedFileDefinitionField extends ArgumentDefinitionField {
+        public InputTaggedFileDefinitionField(ArgumentDefinition argumentDefinition) {
+            super(argumentDefinition);
+        }
+        @Override protected Class<?> getInnerType() { return null; } // TaggedFile does not need to be imported.
+        @Override protected String getFieldType() { return argumentDefinition.isMultiValued ? "Seq[File]" :  "File"; }
+        @Override protected String getDefaultValue() { return argumentDefinition.isMultiValued ? "Nil" : "_"; }
+        @Override protected String getCommandLineTemplate() {
+            if (argumentDefinition.isMultiValued) {
+                return " + repeat(\"%1$s\", %3$s, formatPrefix=TaggedFile.formatCommandLineParameter, spaceSeparated=true, escape=true, format=%2$s)";
+            } else if (!argumentDefinition.required) {
+                return " + optional(TaggedFile.formatCommandLineParameter(\"%1$s\", %3$s), %3$s, spaceSeparated=true, escape=true, format=%2$s)";
+            } else {
+                return " + required(TaggedFile.formatCommandLineParameter(\"%1$s\", %3$s), %3$s, spaceSeparated=true, escape=true, format=%2$s)";
+            }
+        }
+    }
+
+    // Adds optional inputs for the indexes of any rods added to this function.
+    private static class InputIndexesArgumentField extends ArgumentField {
+        private final boolean originalIsMultiValued;
+        private final String indexFieldName;
+        private final String originalFieldName;
+        private final String indexSuffix;
+        private final String originalSuffix;
+        public InputIndexesArgumentField(ArgumentDefinition originalArgumentDefinition, String indexSuffix) {
+            this(originalArgumentDefinition, indexSuffix, null);
+        }
+        public InputIndexesArgumentField(ArgumentDefinition originalArgumentDefinition, String indexSuffix, String originalSuffix) {
+            this.originalIsMultiValued = originalArgumentDefinition.isMultiValued;
+            this.indexFieldName = originalArgumentDefinition.fullName + "Index" + (originalIsMultiValued ? "es" : "");
+            this.originalFieldName = originalArgumentDefinition.fullName;
+            this.indexSuffix = indexSuffix;
+            this.originalSuffix = originalSuffix;
+        }
+        @Override protected Class<? extends Annotation> getAnnotationIOClass() { return Input.class; }
+        @Override public String getCommandLineAddition() { return ""; }
+        @Override protected String getDoc() {
+            return originalIsMultiValued
+                    ? "Dependencies on any indexes of " + this.originalFieldName
+                    : "Dependencies on the index of " + this.originalFieldName;
+        }
+        @Override protected String getFullName() { return this.indexFieldName; }
+        @Override protected boolean isRequired() { return false; }
+        @Override protected String getFieldType() { return "Seq[File]"; }
+        @Override protected String getDefaultValue() { return "Nil"; }
+        @Override protected Class<?> getInnerType() { return File.class; }
+        @Override protected String getRawFieldName() { return this.indexFieldName; }
+        @Override protected String getPrivacy() { return "private "; }
+        @Override protected String getFreezeFields() {
+            if (originalIsMultiValued) {
+                if (originalSuffix == null) {
+                    return String.format(
+                            ("%1$s ++= %2$s" +
+                                    ".filter(orig => orig != null && (!orig.getName.endsWith(\".list\")))" +
+                                    ".map(orig => new File(orig.getPath + \"%3$s\"))%n"),
+                            indexFieldName, originalFieldName, indexSuffix);
+                } else {
+                    return String.format(
+                            ("%1$s ++= %2$s" +
+                                    ".filter(orig => orig != null && orig.getName.endsWith(\"%4$s\"))" +
+                                    ".flatMap(orig => Array(" +
+                                    " new File(orig.getPath + \"%3$s\")," +
+                                    " new File(orig.getPath.stripSuffix(\"%4$s\") + \"%3$s\") ))%n"),
+                            indexFieldName, originalFieldName, indexSuffix, originalSuffix);
+                }
+            } else {
+                if (originalSuffix == null) {
+                    return String.format(
+                            ("if (%2$s != null)%n  " +
+                                    "%1$s :+= new File(%2$s.getPath + \"%3$s\")%n"),
+                            indexFieldName, originalFieldName, indexSuffix);
+                } else {
+                    return String.format(
+                            ("if (%2$s != null && %2$s.getName.endsWith(\"%4$s\"))%n  " +
+                                    "%1$s ++= Array(" +
+                                    " new File(%2$s.getPath + \"%3$s\")," +
+                                    " new File(%2$s.getPath.stripSuffix(\"%4$s\") + \"%3$s\") )%n"),
+                            indexFieldName, originalFieldName, indexSuffix, originalSuffix);
+                }
+            }
+        }
+    }
+
+    // Tracks an automatically generated index, md5, etc.
+    private static abstract class AuxilliaryOutputArgumentField extends ArgumentField {
+        protected final String originalFieldName;
+        protected final String auxFieldName;
+        protected final String auxFieldLabel;
+        public AuxilliaryOutputArgumentField(ArgumentDefinition originalArgumentDefinition, String auxFieldLabel) {
+            this.originalFieldName = originalArgumentDefinition.fullName;
+            this.auxFieldName = originalArgumentDefinition.fullName + auxFieldLabel;
+            this.auxFieldLabel = auxFieldLabel;
+        }
+        @Override protected Class<? extends Annotation> getAnnotationIOClass() { return Output.class; }
+        @Override public String getCommandLineAddition() { return ""; }
+        @Override protected String getDoc() { return String.format("Automatically generated %s for %s", auxFieldLabel.toLowerCase(), this.originalFieldName); }
+        @Override protected String getFullName() { return this.auxFieldName; }
+        @Override protected boolean isRequired() { return false; }
+        @Override protected String getFieldType() { return "File"; }
+        @Override protected String getDefaultValue() { return "_"; }
+        @Override protected Class<?> getInnerType() { return File.class; }
+        @Override protected String getRawFieldName() { return this.auxFieldName; }
+        @Override protected String getPrivacy() { return "private "; }
+
+        @Override public boolean isGather() { return true; }
+        @Override protected String getGatherAnnotation() {
+            return String.format("@Gather(enabled=false)%n");
+        }
+    }
+
+    private static class VCFWriterIndexArgumentField extends AuxilliaryOutputArgumentField {
+        public VCFWriterIndexArgumentField(ArgumentDefinition originalArgumentDefinition) {
+            super(originalArgumentDefinition, "Index");
+        }
+        @Override protected String getFreezeFields() {
+            return String.format(
+                    ("if (%2$s != null && !org.broadinstitute.gatk.utils.io.IOUtils.isSpecialFile(%2$s))%n" +
+                            "  if (!org.broadinstitute.gatk.engine.io.stubs.VCFWriterArgumentTypeDescriptor.isCompressed(%2$s.getPath))%n" +
+                            "    %1$s = new File(%2$s.getPath + \"%3$s\")%n"),
+                    auxFieldName, originalFieldName, Tribble.STANDARD_INDEX_EXTENSION);
+        }
+    }
+
+    private static class SAMFileWriterIndexArgumentField extends AuxilliaryOutputArgumentField {
+        public SAMFileWriterIndexArgumentField(ArgumentDefinition originalArgumentDefinition) {
+            super(originalArgumentDefinition, "Index");
+        }
+        @Override protected String getFreezeFields() {
+            return String.format(
+                    ("if (%2$s != null && !org.broadinstitute.gatk.utils.io.IOUtils.isSpecialFile(%2$s))%n" +
+                            "  if (!%3$s)%n" +
+                            "    %1$s = new File(%2$s.getPath.stripSuffix(\".bam\") + \"%4$s\")%n"),
+                    auxFieldName, originalFieldName, getArgumentFullName(GATKArgumentCollection.class, "disableBAMIndexing"), BAMIndex.BAMIndexSuffix);
+        }
+    }
+
+    private static class SAMFileWriterMD5ArgumentField extends AuxilliaryOutputArgumentField {
+        public SAMFileWriterMD5ArgumentField(ArgumentDefinition originalArgumentDefinition) {
+            super(originalArgumentDefinition, "MD5");
+        }
+        @Override protected String getFreezeFields() {
+            return String.format(
+                    ("if (%2$s != null && !org.broadinstitute.gatk.utils.io.IOUtils.isSpecialFile(%2$s))%n" +
+                            "  if (%3$s)%n" +
+                            "    %1$s = new File(%2$s.getPath + \"%4$s\")%n"),
+                    auxFieldName, originalFieldName, getArgumentFullName(GATKArgumentCollection.class, "enableBAMmd5"), ".md5");
+        }
+    }
+
+    // Allows setting the format for floats and doubles
+    private static class FormatterArgumentField extends ArgumentField {
+        private final ArgumentField argumentField;
+        public FormatterArgumentField(ArgumentField argumentField) {
+            this.argumentField = argumentField;
+        }
+        @Override protected Class<? extends Annotation> getAnnotationIOClass() { return Argument.class; }
+        @Override public String getCommandLineAddition() { return ""; }
+        @Override protected String getDoc() { return "Format string for " + this.argumentField.getFullName(); }
+        @Override protected String getFullName() { return this.argumentField.getFullName() + "Format"; }
+        @Override protected boolean isRequired() { return false; }
+        @Override protected String getFieldType() { return "String"; }
+        @Override protected String getDefaultValue() { return "\"%s\""; }
+        @Override protected Class<?> getInnerType() { return String.class; }
+        @Override protected String getRawFieldName() { return this.argumentField.getRawFieldName() + "Format"; }
+    }
+}
diff --git a/public/gatk-queue-extensions-generator/src/main/java/org/broadinstitute/gatk/queue/extensions/gatk/ArgumentField.java b/public/gatk-queue-extensions-generator/src/main/java/org/broadinstitute/gatk/queue/extensions/gatk/ArgumentField.java
new file mode 100644
index 0000000..9c93efd
--- /dev/null
+++ b/public/gatk-queue-extensions-generator/src/main/java/org/broadinstitute/gatk/queue/extensions/gatk/ArgumentField.java
@@ -0,0 +1,250 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.queue.extensions.gatk;
+
+import htsjdk.samtools.SAMFileReader;
+import htsjdk.samtools.SAMFileWriter;
+import org.apache.commons.lang.StringEscapeUtils;
+import org.apache.commons.lang.StringUtils;
+import org.broadinstitute.gatk.engine.filters.PlatformUnitFilterHelper;
+import htsjdk.variant.variantcontext.writer.VariantContextWriter;
+
+import java.io.File;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.lang.annotation.Annotation;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.List;
+
+public abstract class ArgumentField {
+
+    public Collection<String> getImportStatements() {
+        List<String> imports = new ArrayList<String>();
+        for (Class<?> importClass: getImportClasses()) {
+            if (!isBuiltIn(importClass))
+                imports.add("import " + importClass.getName().replace("$", "."));
+        }
+        return imports;
+    }
+
+    /** @return Scala code defining the argument and it's annotation. */
+    public final String getArgumentAddition() {
+        return String.format("%n" +
+                "/** %s */%n" +
+                "@%s(fullName=\"%s\", shortName=\"%s\", doc=\"%s\", required=%s, exclusiveOf=\"%s\", validation=\"%s\")%n" +
+                "%s%svar %s: %s = %s%n" +
+                "%s",
+                getDoc(),
+                getAnnotationIOClass().getSimpleName(),
+                getFullName(),
+                getShortName(),
+                getDoc(),
+                isRequired(),
+                getExclusiveOf(),
+                getValidation(),
+                getGatherAnnotation(), getPrivacy(), getFieldName(), getFieldType(), getDefaultValue(),
+                getDefineAddition());
+    }
+
+    /** @return Scala code with defines to append to the argument definition. */
+    protected String getDefineAddition() { return ""; }
+
+    /** @return Scala code to append to the command line. */
+    public abstract String getCommandLineAddition();
+
+    // Argument Annotation
+
+    /** @return Documentation for the annotation. */
+    protected abstract String getDoc();
+
+    /** @return Annotation class of the annotation. */
+    protected abstract Class<? extends Annotation> getAnnotationIOClass();
+
+    /** @return Full name for the annotation. */
+    protected abstract String getFullName();
+
+    /** @return Short name for the annotation or "". */
+    protected String getShortName() { return ""; }
+
+    /** @return true if the argument is required. */
+    protected abstract boolean isRequired();
+
+    /** @return A comma separated list of arguments that may be substituted for this field. */
+    protected String getExclusiveOf() { return ""; }
+
+    /** @return A validation string for the argument. */
+    protected String getValidation() { return ""; }
+
+    /** @return A gather annotation with a line feed, or "". */
+    protected String getGatherAnnotation() { return ""; }
+
+    // Scala
+
+    /** @return The scala field type. */
+    protected abstract String getFieldType();
+
+    /** @return The scala default value. */
+    protected abstract String getDefaultValue();
+
+    /** @return The class of the field, or the component type if the scala
+     * field is a collection, or null if no type needs to be imported.
+     * NOTE: Used in some cases by getFieldType so the two function should be overriden together.
+     */
+    protected abstract Class<?> getInnerType();
+
+    /** @return A custom command for overriding freeze. */
+    protected String getFreezeFields() { return ""; }
+
+    /** @return Classes that should be imported. */
+    protected Collection<Class<?>> getImportClasses() {
+        ArrayList<Class<?>> importClasses = new ArrayList<Class<?>>();
+        importClasses.add(this.getAnnotationIOClass());
+        Class<?> innerType = this.getInnerType();
+        if (innerType != null)
+            if (!innerType.isEnum()) // see getType()
+                importClasses.add(innerType);
+        return importClasses;
+    }
+
+    /** @return Classes that should be imported by BCEL during packaging. */
+    protected Collection<Class<?>> getDependentClasses() {
+        ArrayList<Class<?>> dependentClasses = new ArrayList<Class<?>>();
+        Class<?> innerType = this.getInnerType();
+        if (innerType != null)
+            if (innerType.isEnum()) // Enums are not being implicitly picked up...
+                dependentClasses.add(innerType);
+        return dependentClasses;
+    }
+
+    /** @return True if this field uses @Gather. */
+    public boolean isGather() { return false; }
+
+    /** @return Privacy for the field. */
+    protected String getPrivacy() { return ""; }
+
+    /** @return The raw field name, which will be checked against scala build in types. */
+    protected abstract String getRawFieldName();
+    /** @return The field name checked against reserved words. */
+    protected final String getFieldName() {
+        return getFieldName(this.getRawFieldName());
+    }
+
+    /**
+     * Returns true if a class is built in and doesn't need to be imported.
+     * @param argType The class to check.
+     * @return true if the class is built in and doesn't need to be imported
+     */
+    public static boolean isBuiltIn(Class<?> argType) {
+        return argType.isPrimitive() || argType == String.class || Number.class.isAssignableFrom(argType);
+    }
+
+    /**
+     * @param rawFieldName The raw field name
+     * @return The field name checked against reserved words.
+     */
+    protected static String getFieldName(String rawFieldName) {
+        String fieldName = rawFieldName;
+        if (StringUtils.isNumeric(fieldName.substring(0,1)))
+            fieldName = "_" + fieldName;
+        if (isReserved(fieldName) || fieldName.contains("-"))
+            fieldName = "`" + fieldName + "`";
+        return fieldName;
+    }
+
+    /** via http://www.scala-lang.org/sites/default/files/linuxsoft_archives/docu/files/ScalaReference.pdf */
+    private static final List<String> reservedWords = Arrays.asList(
+            "abstract", "case", "catch", "class", "def",
+            "do", "else", "extends", "false", "final",
+            "finally", "for", "forSome", "if", "implicit",
+            "import", "lazy", "match", "new", "null",
+            "object", "override", "package", "private", "protected",
+            "return", "sealed", "super", "this", "throw",
+            "trait", "try", "true", "type", "val",
+            "var", "while", "with", "yield");
+
+    protected static boolean isReserved(String word) {
+        return reservedWords.contains(word);
+    }
+
+    /**
+     * On primitive types returns the capitalized scala type.
+     * @param argType The class to check for options.
+     * @return the simple name of the class.
+     */
+    protected static String getType(Class<?> argType) {
+        // Special case for enums.
+        // Return the full path as sometimes two enums
+        // used in the same class have the same name
+        // ex: Model and Model
+        if (argType.isEnum())
+          return argType.getName().replace("$", ".");
+                
+        String type = argType.getSimpleName();
+
+        if (argType.isPrimitive())
+            type = StringUtils.capitalize(type);
+
+        if ("Integer".equals(type))
+            type = "Int";
+
+        return type;
+    }
+
+    protected static String escape(String string) {
+        return (string == null) ? "" : StringEscapeUtils.escapeJava(string);
+    }
+
+    /**
+     * @param argType The class to check for options.
+     * @return true if option should be used.
+     */
+    protected static boolean useOption(Class<?> argType) {
+        return (argType.isPrimitive()) || (Number.class.isAssignableFrom(argType));
+    }
+
+    /**
+     * @param argType The class to check for options.
+     * @return true if option should be used.
+     */
+    protected static boolean useFormatter(Class<?> argType) {
+        return (argType.equals(Double.class) || argType.equals(Double.TYPE) ||
+                argType.equals(Float.class) || argType.equals(Float.TYPE));
+    }
+
+    // TODO: Use an annotation, type descriptor, anything but hardcoding these lists!
+
+    protected static Class<?> mapType(Class<?> clazz) {
+        if (InputStream.class.isAssignableFrom(clazz)) return File.class;
+        if (SAMFileReader.class.isAssignableFrom(clazz)) return File.class;
+        if (OutputStream.class.isAssignableFrom(clazz)) return File.class;
+        if (VariantContextWriter.class.isAssignableFrom(clazz)) return File.class;
+        if (SAMFileWriter.class.isAssignableFrom(clazz)) return File.class;
+        if (PlatformUnitFilterHelper.class.isAssignableFrom(clazz)) return String.class;
+        return clazz;
+    }
+}
diff --git a/public/gatk-queue-extensions-generator/src/main/java/org/broadinstitute/gatk/queue/extensions/gatk/GATKExtensionsGenerator.java b/public/gatk-queue-extensions-generator/src/main/java/org/broadinstitute/gatk/queue/extensions/gatk/GATKExtensionsGenerator.java
new file mode 100644
index 0000000..d125e3d
--- /dev/null
+++ b/public/gatk-queue-extensions-generator/src/main/java/org/broadinstitute/gatk/queue/extensions/gatk/GATKExtensionsGenerator.java
@@ -0,0 +1,399 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.queue.extensions.gatk;
+
+import org.apache.commons.io.FileUtils;
+import org.apache.commons.lang.StringUtils;
+import org.apache.log4j.Logger;
+import org.broadinstitute.gatk.utils.commandline.ArgumentTypeDescriptor;
+import org.broadinstitute.gatk.utils.commandline.CommandLineProgram;
+import org.broadinstitute.gatk.utils.commandline.Output;
+import org.broadinstitute.gatk.utils.commandline.ParsingEngine;
+import org.broadinstitute.gatk.engine.CommandLineGATK;
+import org.broadinstitute.gatk.engine.GenomeAnalysisEngine;
+import org.broadinstitute.gatk.engine.WalkerManager;
+import org.broadinstitute.gatk.engine.filters.FilterManager;
+import org.broadinstitute.gatk.engine.filters.ReadFilter;
+import org.broadinstitute.gatk.engine.io.stubs.OutputStreamArgumentTypeDescriptor;
+import org.broadinstitute.gatk.engine.io.stubs.SAMFileWriterArgumentTypeDescriptor;
+import org.broadinstitute.gatk.engine.io.stubs.VCFWriterArgumentTypeDescriptor;
+import org.broadinstitute.gatk.engine.walkers.PartitionBy;
+import org.broadinstitute.gatk.engine.walkers.PartitionType;
+import org.broadinstitute.gatk.engine.walkers.Walker;
+import org.broadinstitute.gatk.utils.classloader.JVMUtils;
+import org.broadinstitute.gatk.utils.classloader.PluginManager;
+import org.broadinstitute.gatk.utils.exceptions.ReviewedGATKException;
+
+import java.io.File;
+import java.io.IOException;
+import java.lang.reflect.Method;
+import java.lang.reflect.Modifier;
+import java.lang.reflect.Type;
+import java.lang.reflect.TypeVariable;
+import java.util.*;
+import java.util.Map.Entry;
+
+/**
+ * Generates Queue modules that can be used to run GATK walkers.
+ *
+ * ArgumentCollections are flattened into a single module.
+ */
+public class GATKExtensionsGenerator extends CommandLineProgram {
+    private static final Logger logger = Logger.getLogger(GATKExtensionsGenerator.class);
+    public static final String GATK_EXTENSIONS_PACKAGE_NAME = GATKExtensionsGenerator.class.getPackage().getName();
+    private static final String NEWLINE = String.format("%n");
+
+    private static final String CLASS_TEMPLATE = "package %s%n"+
+            "%s%n" +
+            "class %s extends %s {%n" +
+            "%s%s%n" +
+            "%soverride def commandLine = super.commandLine%s%n" +
+            "}%n";
+
+    private static final String TRAIT_TEMPLATE = "package %s%n"+
+            "%s%n" +
+            "trait %s extends %s {%n" +
+            "%s%s%n" +
+            "%sabstract override def commandLine = super.commandLine%s%n" +
+            "}%n";
+
+    private static final String GATK_DEPENDENCIES_TEMPLATE = "package %s%n" +
+            "%n" +
+            "/** A dynamicly generated list of classes that the GATK Extensions depend on, but are not be detected by default by BCEL. */%n" +
+            "class %s {%n" +
+            "val types = Seq(%n%s)%n" +
+            "}%n";
+
+    @Output(fullName="output_directory", shortName="outDir", doc="Directory to output the generated scala", required=true)
+    public File outputDirectory;
+
+    PluginManager<CommandLineProgram> clpManager = new PluginManager<CommandLineProgram>(CommandLineProgram.class, "CommandLineProgram", "CLP");
+    GenomeAnalysisEngine GATKEngine = new GenomeAnalysisEngine();
+    WalkerManager walkerManager = new WalkerManager();
+    FilterManager filterManager = new FilterManager();
+
+    /**
+     * Required main method implementation.
+     * @param argv Command-line arguments.
+     */
+    public static void main(String[] argv) {
+        try {
+            start(new GATKExtensionsGenerator(), argv);
+            System.exit(CommandLineProgram.result);
+        } catch (Exception e) {
+            exitSystemWithError(e);
+        }
+    }
+
+    @Override
+    protected Collection<ArgumentTypeDescriptor> getArgumentTypeDescriptors() {
+        List<ArgumentTypeDescriptor> typeDescriptors = new ArrayList<ArgumentTypeDescriptor>();
+        typeDescriptors.add(new VCFWriterArgumentTypeDescriptor(GATKEngine,System.out,Collections.<Object>emptyList()));
+        typeDescriptors.add(new SAMFileWriterArgumentTypeDescriptor(GATKEngine,System.out));
+        typeDescriptors.add(new OutputStreamArgumentTypeDescriptor(GATKEngine,System.out));
+        return typeDescriptors;
+    }
+
+    /**
+     * Loops over all the walkers and filters and generates a scala class for each.
+     * @return zero if the run was successful, non-zero if there was an error.
+     */
+    @Override
+    protected int execute() {
+        try {
+            if (!outputDirectory.isDirectory() && !outputDirectory.mkdirs())
+                throw new ReviewedGATKException("Unable to create output directory: " + outputDirectory);
+
+            SortedSet<Class<?>> dependents = new TreeSet<Class<?>>(classComparator);
+
+            for (Class<? extends CommandLineProgram> clp: clpManager.getPlugins()) {
+
+                try {
+                    if (!isGatkProgram(clp)) {
+                        logger.debug("Skipping: " + clp);
+                        continue;
+                    }
+
+                    logger.debug("Generating: " + clp);
+                    String clpClassName = clpManager.getName(clp);
+                    String clpConstructor = String.format("analysisName = \"%s\"%njavaMainClass = \"%s\"%n", clpClassName, clp.getName());
+
+                    writeClass("org.broadinstitute.gatk.queue.function.JavaCommandLineFunction", clpClassName,
+                            false, clpConstructor, ArgumentDefinitionField.getArgumentFields(parser,clp), dependents);
+
+                    if (clp == CommandLineGATK.class) {
+                        for (Entry<String, Collection<Class<? extends Walker>>> walkersByPackage: walkerManager.getWalkerNamesByPackage(false).entrySet()) {
+                            for(Class<? extends Walker> walkerType: walkersByPackage.getValue()) {
+                                try {
+                                    String walkerName = walkerManager.getName(walkerType);
+                                    List<ArgumentField> argumentFields = new ArrayList<ArgumentField>();
+
+                                    argumentFields.addAll(ArgumentDefinitionField.getArgumentFields(parser,walkerType));
+                                    //argumentFields.addAll(RodBindField.getRodArguments(walkerType, trackBuilder));
+                                    argumentFields.addAll(ReadFilterField.getFilterArguments(parser,walkerType));
+
+                                    String constructor = String.format("analysisName = \"%1$s\"%nanalysis_type = \"%1$s\"%n", walkerName);
+                                    String scatterClass = getScatterClass(walkerType);
+                                    boolean isScatter = false;
+                                    if (scatterClass != null) {
+                                        isScatter = true;
+                                        constructor += String.format("scatterClass = classOf[%s]%n", scatterClass);
+                                    }
+
+                                    writeClass(GATK_EXTENSIONS_PACKAGE_NAME + "." + clpClassName, walkerName,
+                                            isScatter, constructor, argumentFields, dependents);
+                                } catch (Exception e) {
+                                    throw new ReviewedGATKException("Error generating wrappers for walker " + walkerType, e);
+                                }
+                            }
+                        }
+                    }
+                } catch (Exception e) {
+                    throw new ReviewedGATKException("Error generating wrappers for " + clp, e);
+                }
+            }
+
+            for (Class<? extends ReadFilter> filter: filterManager.getValues()) {
+                String filterName = filterManager.getName(filter);
+                writeFilter(filterName, ArgumentDefinitionField.getArgumentFields(new ParsingEngine(null),filter), dependents);
+            }
+
+            writeDependencies(dependents);
+            
+            return 0;
+        } catch (IOException exception) {
+            logger.error("Error generating queue output.", exception);
+            return 1;
+        }
+    }
+
+    /**
+     * The list of packages to search through.
+     */
+    private static final List<String> gatkPackages = Arrays.asList(
+            "org.broadinstitute.gatk.engine",
+            "org.broadinstitute.gatk.utils.pipeline",
+            "org.broadinstitute.gatk.tools",
+            "org.broadinstitute.gatk.engine.datasources.reads.utilities");
+
+    /**
+     * Returns true if the class is part of the GATK.
+     * @param clazz Class to check.
+     * @return True if the class is part of the GATK.
+     */
+    private boolean isGatkProgram(Class<?> clazz) {
+        if (clazz.getPackage() == null)
+            return false;
+        String classPackage = clazz.getPackage().getName();
+        for (String gatkPackage : gatkPackages)
+            if (classPackage.startsWith(gatkPackage))
+                return true;
+        return false;
+    }
+
+    /**
+     * Returns the scatter type for a walker.
+     * @param walkerType The walker to check.
+     * @return The scatter type for the walker.
+     */
+    private String getScatterClass(Class<? extends Walker> walkerType) {
+        PartitionType partitionType = walkerType.getAnnotation(PartitionBy.class).value();
+        if (partitionType == PartitionType.NONE)
+            return null;
+        return StringUtils.capitalize(partitionType.name().toLowerCase()) + "ScatterFunction";
+    }
+
+    /**
+     * Writes a dynamically generated scala wrapper for a class.
+     * @param baseClass The class to extend from.
+     * @param className The class name to generate.
+     * @param isScatter True if the class is scatter/gatherable.
+     * @param constructor Additional logic for the constructor, or an empty string.
+     * @param argumentFields The list of argument fields for the generated class.
+     * @param dependents A set that should be updated with explicit dependencies that need to be packaged.
+     * @throws IOException If the file cannot be written.
+     */
+    private void writeClass(String baseClass, String className, boolean isScatter,
+                            String constructor, List<? extends ArgumentField> argumentFields,
+                            Set<Class<?>> dependents) throws IOException {
+        String content = getContent(CLASS_TEMPLATE, baseClass, className, constructor, isScatter, "", argumentFields, dependents);
+        writeFile(GATK_EXTENSIONS_PACKAGE_NAME + "." + className, content);
+    }
+
+    /**
+     * Writes a dynamically generated scala wrapper for a GATK filter.
+     * The filter is defined as a trait in scala, and can be mixed into a GATK command via "val myMixin = new PrintReads with FilterName"
+     * @param className The class name to generate.
+     * @param argumentFields The list of argument fields for the generated class.
+     * @param dependents A set that should be updated with explicit dependencies that need to be packaged.
+     * @throws IOException If the file cannot be written.
+     */
+    private void writeFilter(String className, List<? extends ArgumentField> argumentFields, Set<Class<?>> dependents) throws IOException {
+        String content = getContent(TRAIT_TEMPLATE, "org.broadinstitute.gatk.queue.function.CommandLineFunction",
+                className, "", false, String.format(" + required(\"--read_filter\", \"%s\")", className), argumentFields, dependents);
+        writeFile(GATK_EXTENSIONS_PACKAGE_NAME + "." + className, content);
+    }
+
+    /**
+     * Writes the dependents to a scala wrapper that will compile and get picked up by BCEL.
+     * BCEL was missing some classes, such as Enums, when they were defined in the other generated classes.
+     * This generated wrapper makes sure they are explicitly seen by BCEL.
+     * @param dependents Explicit dependencies that need to be packaged.
+     * @throws IOException If the file cannot be written.
+     */
+    private void writeDependencies(SortedSet<Class<?>> dependents) throws IOException {
+        // Include the enclosing classes too.  Scala will be looking for them.
+        SortedSet<Class<?>> enclosings = new TreeSet<Class<?>>(classComparator);
+        for (Class<?> dependent: dependents)
+            for (Class<?> enclosing = dependent; enclosing != null; enclosing = enclosing.getEnclosingClass())
+                enclosings.add(enclosing);
+        dependents = enclosings;
+
+        // Oh, and include the classes defined on methods too!
+        enclosings = new TreeSet<Class<?>>(classComparator);
+        for (Class<?> dependent: dependents) {
+            for (Method method: dependent.getDeclaredMethods()) {
+                JVMUtils.addGenericTypes(enclosings, method.getGenericReturnType());
+                for (Type parameterType: method.getGenericParameterTypes())
+                    JVMUtils.addGenericTypes(enclosings, parameterType);
+                for (Type exceptionType: method.getGenericExceptionTypes())
+                    JVMUtils.addGenericTypes(enclosings, exceptionType);
+            }
+        }
+        dependents = enclosings;
+
+        // Generate the dependents.
+        String className = "GATKClassDependencies";
+        StringBuilder classes = new StringBuilder();
+        
+        for (Class<?> dependent: dependents) {
+            if (dependent.isArray())
+                continue;
+            if (ArgumentField.isBuiltIn(dependent))
+                continue;
+            if (!Modifier.isPublic(dependent.getModifiers()))
+                continue;
+            if (classes.length() > 0)
+                classes.append(",").append(NEWLINE);
+            String typeParams = getScalaTypeParams(dependent);
+            classes.append("classOf[").append(dependent.getName().replace("$", ".")).append(typeParams).append("]");
+        }
+        String content = String.format(GATK_DEPENDENCIES_TEMPLATE, GATK_EXTENSIONS_PACKAGE_NAME, className, classes);
+        writeFile(GATK_EXTENSIONS_PACKAGE_NAME + "." + className, content);
+    }
+
+    /**
+     * Returns a string representing the type parameters for a class, or an empty string if there are no type parameters.
+     * @param clazz The class to look for type parameters.
+     * @return The type parameters or an empty string.
+     */
+    private String getScalaTypeParams(Class<?> clazz) {
+        TypeVariable[] typeParams = clazz.getTypeParameters();
+        if (typeParams.length == 0)
+            return "";
+        return "[" + StringUtils.repeat("_", ",", typeParams.length) + "]";
+    }
+
+    /**
+     * Writes the generated scala file with this content.
+     * @param fullClassName Generated class name.
+     * @param content scala content.
+     * @throws IOException If the file cannot be written.
+     */
+    private void writeFile(String fullClassName, String content) throws IOException {
+        File outputFile = new File(outputDirectory, fullClassName.replace(".", "/") + ".scala");
+        if (outputFile.exists()) {
+            String existingContent = FileUtils.readFileToString(outputFile);
+            if (StringUtils.equals(content, existingContent))
+                return;
+        }
+        FileUtils.writeStringToFile(outputFile, content);
+    }
+
+    /**
+     * Generates scala content using CLASS_TEMPLATE or TRAIT_TEMPLATE.
+     * @param scalaTemplate CLASS_TEMPLATE or TRAIT_TEMPLATE
+     * @param baseClass The class to extend from.
+     * @param className The class name to generate.
+     * @param constructor Additional logic for the constructor, or an empty string.
+     * @param isScatter True if the class is scatter/gatherable.
+     * @param commandLinePrefix Additional logic to prefix to the QCommandLine.commandLine, or an empty string.
+     * @param argumentFields The list of argument fields for the generated class.
+     * @param dependents A set that should be updated with explicit dependencies that need to be packaged.
+     * @return The populated template.
+     */
+    private static String getContent(String scalaTemplate, String baseClass, String className,
+                                     String constructor, boolean isScatter, String commandLinePrefix,
+                                     List<? extends ArgumentField> argumentFields, Set<Class<?>> dependents) {
+        StringBuilder arguments = new StringBuilder();
+        StringBuilder commandLine = new StringBuilder(commandLinePrefix);
+
+        Set<String> importSet = new HashSet<String>();
+        boolean isGather = false;
+        List<String> freezeFields = new ArrayList<String>();
+        for(ArgumentField argumentField: argumentFields) {
+            arguments.append(argumentField.getArgumentAddition());
+            commandLine.append(argumentField.getCommandLineAddition());
+            importSet.addAll(argumentField.getImportStatements());
+            freezeFields.add(argumentField.getFreezeFields());
+            dependents.addAll(argumentField.getDependentClasses());
+
+            isGather |= argumentField.isGather();
+        }
+
+        if (isScatter) {
+            importSet.add("import org.broadinstitute.gatk.queue.function.scattergather.ScatterGatherableFunction");
+            baseClass += " with ScatterGatherableFunction";
+        }
+        if (isGather)
+            importSet.add("import org.broadinstitute.gatk.utils.commandline.Gather");
+
+        // Sort the imports so that the are always in the same order.
+        List<String> sortedImports = new ArrayList<String>(importSet);
+        Collections.sort(sortedImports);
+
+        StringBuffer freezeFieldOverride = new StringBuffer();
+        for (String freezeField: freezeFields)
+            freezeFieldOverride.append(freezeField);
+        if (freezeFieldOverride.length() > 0) {
+            freezeFieldOverride.insert(0, String.format("override def freezeFieldValues() {%nsuper.freezeFieldValues()%n"));
+            freezeFieldOverride.append(String.format("}%n%n"));
+        }
+
+        String importText = sortedImports.size() == 0 ? "" : NEWLINE + StringUtils.join(sortedImports, NEWLINE) + NEWLINE;
+
+        // see CLASS_TEMPLATE and TRAIT_TEMPLATE below
+        return String.format(scalaTemplate, GATK_EXTENSIONS_PACKAGE_NAME, importText,
+                className, baseClass, constructor, arguments, freezeFieldOverride, commandLine);
+    }
+
+    private static final Comparator<Class<?>> classComparator = new Comparator<Class<?>>() {
+        @Override
+        public int compare(Class<?> a, Class<?> b) {
+            return (a == null ? "" : a.getName()).compareTo(b == null ? "" : b.getName());
+        }
+    };
+}
diff --git a/public/gatk-queue-extensions-generator/src/main/java/org/broadinstitute/gatk/queue/extensions/gatk/ReadFilterField.java b/public/gatk-queue-extensions-generator/src/main/java/org/broadinstitute/gatk/queue/extensions/gatk/ReadFilterField.java
new file mode 100644
index 0000000..b23f1aa
--- /dev/null
+++ b/public/gatk-queue-extensions-generator/src/main/java/org/broadinstitute/gatk/queue/extensions/gatk/ReadFilterField.java
@@ -0,0 +1,48 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.queue.extensions.gatk;
+
+import htsjdk.samtools.filter.SamRecordFilter;
+import org.broadinstitute.gatk.utils.commandline.ParsingEngine;
+import org.broadinstitute.gatk.engine.WalkerManager;
+import org.broadinstitute.gatk.engine.walkers.Walker;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public class ReadFilterField {
+    /**
+     * Adds an argument for each read filters listed on the walker.
+     * @param walkerClass the class of the walker
+     * @return the list of argument fields
+     */
+    public static List<ArgumentField> getFilterArguments(ParsingEngine parser, Class<? extends Walker> walkerClass) {
+        List<ArgumentField> argumentFields = new ArrayList<ArgumentField>();
+        for(Class<? extends SamRecordFilter> filter: WalkerManager.getReadFilterTypes(walkerClass))
+            argumentFields.addAll(ArgumentDefinitionField.getArgumentFields(parser,filter));
+        return argumentFields;
+    }
+}
diff --git a/public/gatk-queue-extensions-public/pom.xml b/public/gatk-queue-extensions-public/pom.xml
new file mode 100644
index 0000000..4d46ce1
--- /dev/null
+++ b/public/gatk-queue-extensions-public/pom.xml
@@ -0,0 +1,168 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+    <modelVersion>4.0.0</modelVersion>
+
+    <parent>
+        <groupId>org.broadinstitute.gatk</groupId>
+        <artifactId>gatk-aggregator</artifactId>
+        <version>3.3</version>
+        <relativePath>../..</relativePath>
+    </parent>
+
+    <artifactId>gatk-queue-extensions-public</artifactId>
+    <packaging>jar</packaging>
+    <name>GATK Queue Extensions Public</name>
+
+    <properties>
+        <gatk.basedir>${project.basedir}/../..</gatk.basedir>
+        <gatk.extensions.sources>${project.build.directory}/generated-sources/gatk-extensions</gatk.extensions.sources>
+        <gatk.generate-gatk-extensions.skipped>false</gatk.generate-gatk-extensions.skipped>
+        <gatk.packagetests.artifactId>gatk-queue-package-distribution</gatk.packagetests.artifactId>
+    </properties>
+
+    <dependencies>
+        <dependency>
+            <groupId>${project.groupId}</groupId>
+            <artifactId>gatk-tools-public</artifactId>
+            <version>${project.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>${project.groupId}</groupId>
+            <artifactId>gatk-queue</artifactId>
+            <version>${project.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>org.scala-lang</groupId>
+            <artifactId>scala-compiler</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>log4j</groupId>
+            <artifactId>log4j</artifactId>
+        </dependency>
+        <!--
+        Extensions generator dependency only applies to the exec:exec,
+        not the artifact, but don't know another way to include
+        the artifact *only* in the <classpath/> of exec.
+        See https://jira.codehaus.org/browse/MEXEC-111
+
+        Perhaps extensions-generator should be wrapped in a maven plugin?
+        -->
+        <dependency>
+            <groupId>${project.groupId}</groupId>
+            <artifactId>gatk-queue-extensions-generator</artifactId>
+            <version>${project.version}</version>
+            <scope>runtime</scope>
+        </dependency>
+
+        <!--
+        NOTE: Because exec-maven-plugin is used, this aggregator dependency
+        will cause mvn compile to not work. Use mvn test-compile for now.
+
+        See:
+          http://stackoverflow.com/questions/4786881/why-is-test-jar-dependency-required-for-mvn-compile
+          http://jira.codehaus.org/browse/MEXEC-91
+        -->
+        <dependency>
+            <groupId>${project.groupId}</groupId>
+            <artifactId>gatk-tools-public</artifactId>
+            <version>${project.version}</version>
+            <type>test-jar</type>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>${project.groupId}</groupId>
+            <artifactId>gatk-queue</artifactId>
+            <version>${project.version}</version>
+            <type>test-jar</type>
+            <scope>test</scope>
+        </dependency>
+    </dependencies>
+
+    <build>
+        <plugins>
+            <!--
+            See note above about exec plugin breaking mvn compile
+            -->
+            <plugin>
+                <groupId>org.codehaus.mojo</groupId>
+                <artifactId>exec-maven-plugin</artifactId>
+                <executions>
+                    <execution>
+                        <id>generate-gatk-extensions</id>
+                        <goals>
+                            <goal>exec</goal>
+                        </goals>
+                        <phase>generate-sources</phase>
+                        <configuration>
+                            <skip>${gatk.generate-gatk-extensions.skipped}</skip>
+                            <executable>java</executable>
+                            <arguments>
+                                <argument>-classpath</argument>
+                                <classpath />
+                                <argument>org.broadinstitute.gatk.queue.extensions.gatk.GATKExtensionsGenerator</argument>
+                                <argument>-l</argument>
+                                <argument>WARN</argument>
+                                <argument>-outDir</argument>
+                                <argument>${gatk.extensions.sources}</argument>
+                            </arguments>
+                        </configuration>
+                    </execution>
+                </executions>
+            </plugin>
+            <plugin>
+                <groupId>org.codehaus.mojo</groupId>
+                <artifactId>build-helper-maven-plugin</artifactId>
+                <executions>
+                    <execution>
+                        <id>add-gatk-extensions</id>
+                        <goals>
+                            <goal>add-source</goal>
+                        </goals>
+                        <phase>generate-sources</phase>
+                        <configuration>
+                            <sources>
+                                <source>${gatk.extensions.sources}</source>
+                            </sources>
+                        </configuration>
+                    </execution>
+                </executions>
+            </plugin>
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-assembly-plugin</artifactId>
+                <executions>
+                    <execution>
+                        <id>example-resources</id>
+                        <phase>${gatk.generate-resources.phase}</phase>
+                    </execution>
+                </executions>
+            </plugin>
+            <plugin>
+                <groupId>org.scala-tools</groupId>
+                <artifactId>maven-scala-plugin</artifactId>
+            </plugin>
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-invoker-plugin</artifactId>
+                <executions>
+                    <execution>
+                        <id>package-unittests</id>
+                    </execution>
+                    <execution>
+                        <id>package-integrationtests</id>
+                    </execution>
+                    <execution>
+                        <id>package-largescaletests</id>
+                    </execution>
+                    <execution>
+                        <id>package-knowledgebasetests</id>
+                    </execution>
+                    <execution>
+                        <id>package-queuetests</id>
+                    </execution>
+                </executions>
+            </plugin>
+        </plugins>
+    </build>
+
+</project>
diff --git a/public/gatk-queue-extensions-public/src/main/assembly/example-resources.xml b/public/gatk-queue-extensions-public/src/main/assembly/example-resources.xml
new file mode 100644
index 0000000..f3cd6f9
--- /dev/null
+++ b/public/gatk-queue-extensions-public/src/main/assembly/example-resources.xml
@@ -0,0 +1,20 @@
+<assembly xmlns="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.2" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.2 http://maven.apache.org/xsd/assembly-1.1.2.xsd">
+    <id>example-resources</id>
+    <formats>
+        <format>tar.bz2</format>
+    </formats>
+    <includeBaseDirectory>false</includeBaseDirectory>
+    <fileSets>
+        <fileSet>
+            <directory>src/main/qscripts/org/broadinstitute/gatk/queue/qscripts/examples</directory>
+            <outputDirectory>.</outputDirectory>
+            <includes>
+                <include>ExampleCountReads.scala</include>
+                <include>ExampleCountLoci.scala</include>
+                <include>ExampleUnifiedGenotyper.scala</include>
+                <include>ExampleReadFilter.scala</include>
+                <include>ExampleCustomWalker.scala</include>
+            </includes>
+        </fileSet>
+    </fileSets>
+</assembly>
diff --git a/public/gatk-queue-extensions-public/src/main/qscripts/org/broadinstitute/gatk/queue/qscripts/CNV/xhmmCNVpipeline.scala b/public/gatk-queue-extensions-public/src/main/qscripts/org/broadinstitute/gatk/queue/qscripts/CNV/xhmmCNVpipeline.scala
new file mode 100644
index 0000000..7d25668
--- /dev/null
+++ b/public/gatk-queue-extensions-public/src/main/qscripts/org/broadinstitute/gatk/queue/qscripts/CNV/xhmmCNVpipeline.scala
@@ -0,0 +1,615 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.queue.qscripts.CNV
+
+import org.broadinstitute.gatk.queue.extensions.gatk._
+import org.broadinstitute.gatk.queue.QScript
+import org.broadinstitute.gatk.queue.util.VCF_BAM_utilities
+import org.broadinstitute.gatk.queue.extensions.gatk.DoC._
+import org.broadinstitute.gatk.utils.commandline._
+import java.io.{File, PrintStream, PrintWriter}
+import org.broadinstitute.gatk.utils.text.XReadLines
+import collection.JavaConversions._
+import org.broadinstitute.gatk.tools.walkers.coverage.CoverageUtils
+import org.broadinstitute.gatk.queue.function.scattergather.{CloneFunction, ScatterFunction, GatherFunction, ScatterGatherableFunction}
+import org.broadinstitute.gatk.queue.function.{CommandLineFunction, InProcessFunction}
+import org.broadinstitute.gatk.utils.io.IOUtils
+
+class xhmmCNVpipeline extends QScript {
+  qscript =>
+
+  @Input(doc = "bam input, as as a list of .bam files, or a list of bam files with sample IDs to be used ( as specified at https://www.broadinstitute.org/gatk/gatkdocs/org_broadinstitute_sting_gatk_CommandLineGATK.html#--sample_rename_mapping_file )", shortName = "I", required = true)
+  var bams: File = _
+
+  @Input(doc = "gatk jar file", shortName = "J", required = true)
+  var gatkJarFile: File = _
+
+  @Input(doc = "xhmm executable file", shortName = "xhmmExec", required = true)
+  var xhmmExec: File = _
+
+  @Input(doc = "Plink/Seq executable file", shortName = "pseqExec", required = true)
+  var pseqExec: File = _
+
+  @Argument(doc = "Plink/Seq SEQDB file (Reference genome sequence)", shortName = "SEQDB", required = true)
+  var pseqSeqDB: String = _
+
+  @Input(shortName = "R", doc = "ref", required = true)
+  var referenceFile: File = _
+
+  @Input(shortName = "L", doc = "Intervals", required = false)
+  var intervals: File = _
+
+  @Argument(doc = "level of parallelism for BAM DoC.   By default is set to 0 [no scattering].", shortName = "scatter", required = false)
+  var scatterCountInput = 0
+
+  @Argument(doc = "Samples to run together for DoC, CNV discovery, and CNV genotyping.  By default is set to 1 [one job per sample].", shortName = "samplesPerJob", required = false)
+  var samplesPerJob = 1
+
+  @Output(doc = "Base name for files to output", shortName = "o", required = true)
+  var outputBase: File = _
+
+  @Hidden
+  @Argument(doc = "How should overlapping reads from the same fragment be handled?", shortName = "countType", required = false)
+  var countType = CoverageUtils.CountPileupType.COUNT_FRAGMENTS
+
+  @Argument(doc = "Maximum depth (before GATK down-sampling kicks in...)", shortName = "MAX_DEPTH", required = false)
+  var MAX_DEPTH = 20000
+
+  @Hidden
+  @Argument(doc = "Number of read-depth bins", shortName = "NUM_BINS", required = false)
+  var NUM_BINS = 200
+
+  @Hidden
+  @Argument(doc = "Starting value of read-depth bins", shortName = "START_BIN", required = false)
+  var START_BIN = 1
+
+  @Argument(doc = "Minimum read mapping quality", shortName = "MMQ", required = false)
+  var minMappingQuality = 0
+
+  @Argument(doc = "Minimum base quality to be counted in depth", shortName = "MBQ", required = false)
+  var minBaseQuality = 0
+
+  @Argument(doc = "Memory (in GB) required for storing the whole matrix in memory", shortName = "wholeMatrixMemory", required = false)
+  var wholeMatrixMemory = -1
+
+  @Argument(shortName = "minTargGC", doc = "Exclude all targets with GC content less than this value", required = false)
+  var minTargGC : Double = 0.1
+
+  @Argument(shortName = "maxTargGC", doc = "Exclude all targets with GC content greater than this value", required = false)
+  var maxTargGC : Double = 0.9
+
+  @Argument(shortName = "minTargRepeats", doc = "Exclude all targets with % of repeat-masked bases less than this value", required = false)
+  var minTargRepeats : Double = 0.0
+
+  @Argument(shortName = "maxTargRepeats", doc = "Exclude all targets with % of repeat-masked bases greater than this value", required = false)
+  var maxTargRepeats : Double = 0.1
+
+  @Argument(shortName = "rawFilters", doc = "xhmm command-line parameters to filter targets and samples from raw data", required = false)
+  var targetSampleFiltersString: String = ""
+
+  @Argument(shortName = "PCAnormalize", doc = "xhmm command-line parameters to Normalize data using PCA information", required = false)
+  var PCAnormalizeMethodString: String = ""
+
+  @Argument(shortName = "normalizedFilters", doc = "xhmm command-line parameters to filter targets and samples from PCA-normalized data", required = false)
+  var targetSampleNormalizedFiltersString: String = ""
+
+  @Argument(shortName = "xhmmParams", doc = "xhmm model parameters file", required = true)
+  var xhmmParamsArg: File = _
+
+  @Argument(shortName = "discoverParams", doc = "xhmm command-line parameters for discovery step", required = false)
+  var discoverCommandLineParams: String = ""
+
+  @Argument(shortName = "genotypeParams", doc = "xhmm command-line parameters for genotyping step", required = false)
+  var genotypeCommandLineParams: String = ""
+
+  @Argument(shortName = "genotypeSubsegments", doc = "Should we also genotype all subsegments of the discovered CNV?", required = false)
+  var genotypeSubsegments: Boolean = false
+
+  @Argument(shortName = "maxTargetsInSubsegment", doc = "If genotypeSubsegments, then only consider sub-segments consisting of this number of targets or fewer", required = false)
+  var maxTargetsInSubsegment = 30
+
+  @Argument(shortName = "subsegmentGenotypeThreshold", doc = "If genotypeSubsegments, this is the default genotype quality threshold for the sub-segments", required = false)
+  var subsegmentGenotypeThreshold = 20.0
+
+  @Argument(shortName = "longJobQueue", doc = "Job queue to run the 'long-running' commands", required = false)
+  var longJobQueue: String = ""
+
+
+  val PREPARED_TARGS_SUFFIX: String = ".merged.interval_list"
+
+  val RD_OUTPUT_SUFFIX: String = ".RD.txt"
+
+  val TARGS_GC_SUFFIX = ".locus_GC.txt"
+  val EXTREME_GC_TARGS_SUFFIX = ".extreme_gc_targets.txt"
+
+  val TARGS_REPEAT_COMPLEXITY_SUFFIX = ".locus_complexity.txt"
+  val EXTREME_REPEAT_COMPLEXITY_SUFFIX = ".extreme_complexity_targets.txt"
+
+  val FILTERED_TARGS_SUFFIX: String = ".filtered_targets.txt"
+  val FILTERED_SAMPS_SUFFIX: String =  ".filtered_samples.txt"
+
+
+  trait WholeMatrixMemoryLimit extends CommandLineFunction {
+    // Since loading ALL of the data can take significant memory:
+    if (wholeMatrixMemory < 0) {
+      this.memoryLimit = 24
+    }
+    else {
+      this.memoryLimit = wholeMatrixMemory
+    }
+  }
+
+  trait LongRunTime extends CommandLineFunction {
+    if (longJobQueue != "")
+      this.jobQueue = longJobQueue
+  }
+
+  def script = {
+    val prepTargets = new PrepareTargets(List(qscript.intervals), outputBase.getPath + PREPARED_TARGS_SUFFIX, xhmmExec, referenceFile)
+    add(prepTargets)
+
+    trait CommandLineGATKArgs extends CommandLineGATK {
+      this.intervals :+= prepTargets.out
+      this.jarFile = qscript.gatkJarFile
+      this.reference_sequence = qscript.referenceFile
+      this.logging_level = "INFO"
+    }
+
+    val parseMixedInputBamList = parseBamListWithOptionalSampleMappings(bams)
+
+    val processMixedInputBamList = new ProcessBamListWithOptionalSampleMappings(parseMixedInputBamList, outputBase.getPath)
+    add(processMixedInputBamList)
+
+    val samples: List[String] = parseMixedInputBamList.sampleToBams.keys.toList
+    Console.out.printf("Samples are %s%n", samples)
+
+    val groups: List[Group] = buildDoCgroups(samples, parseMixedInputBamList.sampleToBams, samplesPerJob, outputBase)
+    var docs: List[DoC] = List[DoC]()
+    for (group <- groups) {
+      Console.out.printf("Group is %s%n", group)
+      docs ::= new DoC(group.bams, group.DoC_output, countType, MAX_DEPTH, minMappingQuality, minBaseQuality, scatterCountInput, START_BIN, NUM_BINS, Nil, Some(processMixedInputBamList.bamSampleMap)) with CommandLineGATKArgs
+    }
+    addAll(docs)
+
+    val mergeDepths = new MergeGATKdepths(docs.map(u => u.intervalSampleOut), outputBase.getPath + RD_OUTPUT_SUFFIX, "_mean_cvg", xhmmExec, None, false) with WholeMatrixMemoryLimit with LongRunTime
+    add(mergeDepths)
+
+    var excludeTargets : List[File] = List[File]()
+    if (minTargGC > 0 || maxTargGC < 1) {
+      val calcGCcontents = new GCContentByInterval with CommandLineGATKArgs
+      calcGCcontents.out = outputBase.getPath + TARGS_GC_SUFFIX
+      add(calcGCcontents)
+
+      val excludeTargetsBasedOnGC = new ExcludeTargetsBasedOnValue(calcGCcontents.out, EXTREME_GC_TARGS_SUFFIX, minTargGC, maxTargGC)
+      add(excludeTargetsBasedOnGC)
+      excludeTargets ::= excludeTargetsBasedOnGC.out
+    }
+
+
+    class CalculateRepeatComplexity(outFile : String) extends CommandLineFunction {
+      @Input(doc="")
+      var intervals: File = prepTargets.out
+
+      @Output(doc="")
+      var out : File = new File(outFile)
+
+      val regFile : String = outputBase.getPath + ".targets.reg"
+      val locDB : String = outputBase.getPath + ".targets.LOCDB"
+
+      val removeFiles = "rm -f " + regFile + " " + locDB
+      val createRegFile = "cat " + intervals + " | awk 'BEGIN{OFS=\"\\t\"; print \"#CHR\\tBP1\\tBP2\\tID\"} {split($1,a,\":\"); chr=a[1]; if (match(chr,\"chr\")==0) {chr=\"chr\"chr} split(a[2],b,\"-\"); bp1=b[1]; bp2=bp1; if (length(b) > 1) {bp2=b[2]} print chr,bp1,bp2,NR}' > " + regFile
+      val createLOCDB = pseqExec + " . loc-load --locdb " + locDB + " --file " + regFile + " --group targets --out " + locDB + ".loc-load"
+      val calcRepeatMaskedPercent = pseqExec + " . loc-stats --locdb " + locDB + " --group targets --seqdb " + pseqSeqDB + " --out " + locDB + ".loc-stats"
+      val extractRepeatMaskedPercent = "cat " + locDB + ".loc-stats.locstats | awk '{if (NR > 1) print $_}' | sort -k1 -g | awk '{print $10}' | paste " + intervals + " - | awk '{print $1\"\\t\"$2}' > " + out
+
+      var command: String =
+        removeFiles +
+          " && " + createRegFile +
+          " && " + createLOCDB +
+          " && " + calcRepeatMaskedPercent +
+          " && " + extractRepeatMaskedPercent
+
+      override def commandLine = command
+
+      override def description = "Calculate the percentage of each target that is repeat-masked in the reference sequence: " + command
+    }
+
+    if (minTargRepeats > 0 || maxTargRepeats < 1) {
+      val calcRepeatComplexity = new CalculateRepeatComplexity(outputBase.getPath + TARGS_REPEAT_COMPLEXITY_SUFFIX)
+      add(calcRepeatComplexity)
+
+      val excludeTargetsBasedOnRepeats = new ExcludeTargetsBasedOnValue(calcRepeatComplexity.out, EXTREME_REPEAT_COMPLEXITY_SUFFIX, minTargRepeats, maxTargRepeats)
+      add(excludeTargetsBasedOnRepeats)
+      excludeTargets ::= excludeTargetsBasedOnRepeats.out
+    }
+
+    val filterCenterDepths = new FilterCenterRawMatrix(mergeDepths.mergedDoC, excludeTargets)
+    add(filterCenterDepths)
+
+    val pca = new PCA(filterCenterDepths.filteredCentered)
+    add(pca)
+
+    val normalize = new Normalize(pca)
+    add(normalize)
+
+    val filterZscore = new FilterAndZscoreNormalized(normalize.normalized)
+    add(filterZscore)
+
+    val filterOriginal = new FilterOriginalData(mergeDepths.mergedDoC, filterCenterDepths, filterZscore)
+    add(filterOriginal)
+
+
+    class DiscoverCNVs(inputParam: File, origRDParam: File) extends SamplesScatterable(xhmmExec, groups) with LongRunTime {
+      @Input(doc = "")
+      val input = inputParam
+
+      @Input(doc = "")
+      val xhmmParams = xhmmParamsArg
+
+      @Input(doc = "")
+      val origRD = origRDParam
+
+      @Output
+      @Gather(classOf[org.broadinstitute.gatk.queue.function.scattergather.SimpleTextGatherFunction])
+      val xcnv: File = new File(outputBase.getPath + ".xcnv")
+
+      @Output
+      @Gather(classOf[org.broadinstitute.gatk.queue.function.scattergather.SimpleTextGatherFunction])
+      val aux_xcnv: File = new File(outputBase.getPath + ".aux_xcnv")
+
+      // Set as an @Output, so that its value is updated in the cloned jobs being scattered:
+      @Output
+      @Gather(classOf[DummyGatherFunction])
+      val posteriorsBase = outputBase
+
+      @Output
+      @Gather(classOf[org.broadinstitute.gatk.queue.function.scattergather.SimpleTextGatherFunction])
+      val dipPosteriors: File = new File(posteriorsBase.getPath + ".posteriors.DIP.txt")
+
+      @Output
+      @Gather(classOf[org.broadinstitute.gatk.queue.function.scattergather.SimpleTextGatherFunction])
+      val delPosteriors: File = new File(posteriorsBase.getPath + ".posteriors.DEL.txt")
+
+      @Output
+      @Gather(classOf[org.broadinstitute.gatk.queue.function.scattergather.SimpleTextGatherFunction])
+      val dupPosteriors: File = new File(posteriorsBase.getPath + ".posteriors.DUP.txt")
+
+      override def commandLine =
+        xhmmExec + " --discover" +
+        " -p " + xhmmParams +
+        " -r " + input +
+        " -R " + origRD +
+        " -c " + xcnv +
+        " -a " + aux_xcnv +
+        " -s " + posteriorsBase +
+        " " + discoverCommandLineParams +
+        " " + addCommand
+
+      override def description = "Discovers CNVs in normalized data: " + commandLine
+    }
+
+    val discover = new DiscoverCNVs(filterZscore.filteredZscored, filterOriginal.sameFiltered)
+    add(discover)
+
+
+    abstract class BaseGenotypeCNVs(inputParam: File, xcnv: File, origRDParam: File, outName: String) extends SamplesScatterable(xhmmExec, groups) with LongRunTime {
+      @Input(doc = "")
+      val input = inputParam
+
+      @Input(doc = "")
+      val xhmmParams = xhmmParamsArg
+
+      @Input(doc = "")
+      val origRD = origRDParam
+
+      @Input(doc = "")
+      val inXcnv = xcnv
+
+      @Output
+      @Gather(classOf[MergeVCFsGatherFunction])
+      val vcf: File = new File(outName)
+
+      override def commandLine =
+        xhmmExec + " --genotype" +
+          " -p " + xhmmParams +
+          " -r " + input +
+          " -g " + inXcnv +
+          " -F " + referenceFile +
+          " -R " + origRD +
+          " -v " +  vcf +
+          " " + genotypeCommandLineParams +
+          " " + addCommand
+    }
+
+    class GenotypeCNVs(inputParam: File, xcnv: File, origRDParam: File) extends BaseGenotypeCNVs(inputParam, xcnv, origRDParam, outputBase.getPath + ".vcf") {
+      override def description = "Genotypes discovered CNVs in all samples: " + commandLine
+    }
+
+    class GenotypeCNVandSubsegments(inputParam: File, xcnv: File, origRDParam: File) extends BaseGenotypeCNVs(inputParam, xcnv, origRDParam, outputBase.getPath + ".subsegments.vcf") {
+      override def commandLine =
+        super.commandLine +
+        " --subsegments" +
+          " --maxTargetsInSubsegment " + maxTargetsInSubsegment +
+          " --genotypeQualThresholdWhenNoExact " + subsegmentGenotypeThreshold
+
+      override def description = "Genotypes discovered CNVs (and their sub-segments, of up to " + maxTargetsInSubsegment + " targets) in all samples: " + commandLine
+    }
+
+    val genotype = new GenotypeCNVs(filterZscore.filteredZscored, discover.xcnv, filterOriginal.sameFiltered)
+    add(genotype)
+
+    if (genotypeSubsegments) {
+      val genotypeSegs = new GenotypeCNVandSubsegments(filterZscore.filteredZscored, discover.xcnv, filterOriginal.sameFiltered)
+      add(genotypeSegs)
+    }
+  }
+
+  class ExcludeTargetsBasedOnValue(locus_valueIn : File, outSuffix : String, minVal : Double, maxVal : Double) extends InProcessFunction {
+    @Input(doc="")
+    var locus_value : File = locus_valueIn
+
+    @Output(doc="")
+    var out : File = new File(outputBase.getPath + outSuffix)
+
+    def run = {
+      var outWriter = new PrintWriter(new PrintStream(out))
+      var elems = asScalaIterator(new XReadLines(locus_value))
+
+      while (elems.hasNext) {
+        val line = elems.next
+        val splitLine = line.split("\\s+")
+        val locus = splitLine(0)
+        val locValStr = splitLine(1)
+        try {
+          val locVal = locValStr.toDouble
+          if (locVal < minVal || locVal > maxVal)
+            outWriter.printf("%s%n", locus)
+        }
+        catch {
+          case nfe: NumberFormatException => println("Ignoring non-numeric value " + locValStr + " for locus " + locus)
+          case e: Exception => throw e
+        }
+      }
+
+      outWriter.close
+    }
+  }
+
+  class FilterCenterRawMatrix(inputParam: File, excludeTargetsIn : List[File]) extends CommandLineFunction with WholeMatrixMemoryLimit with LongRunTime {
+    @Input(doc = "")
+    val input = inputParam
+
+    @Input(doc = "")
+    val excludeTargets = excludeTargetsIn
+
+    @Output
+    val filteredCentered: File = new File(outputBase.getPath + ".filtered_centered" + RD_OUTPUT_SUFFIX)
+    @Output
+    val filteredTargets: File = new File(filteredCentered.getPath + FILTERED_TARGS_SUFFIX)
+    @Output
+    val filteredSamples: File = new File(filteredCentered.getPath + FILTERED_SAMPS_SUFFIX)
+
+    var command: String =
+      xhmmExec + " --matrix" +
+      " -r " + input +
+      " --centerData --centerType target" +
+      " -o " + filteredCentered +
+      " --outputExcludedTargets " + filteredTargets +
+      " --outputExcludedSamples " + filteredSamples
+    command += excludeTargets.map(u => " --excludeTargets " + u).reduceLeft(_ + "" + _)
+    if (targetSampleFiltersString != "")
+      command += " " + targetSampleFiltersString
+
+    override def commandLine = command
+
+    override def description = "Filters samples and targets and then mean-centers the targets: " + command
+  }
+
+  class PCA(inputParam: File) extends CommandLineFunction with WholeMatrixMemoryLimit with LongRunTime {
+    @Input(doc = "")
+    val input = inputParam
+
+    val PCAbase: String = outputBase.getPath + ".RD_PCA"
+
+    @Output
+    val outPC: File = new File(PCAbase + ".PC.txt")
+    @Output
+    val outPC_SD: File = new File(PCAbase + ".PC_SD.txt")
+    @Output
+    val outPC_LOADINGS: File = new File(PCAbase + ".PC_LOADINGS.txt")
+
+    var command: String =
+      xhmmExec + " --PCA" +
+      " -r " + input +
+      " --PCAfiles " + PCAbase
+
+    override def commandLine = command
+
+    override def description = "Runs PCA on mean-centered data: " + command
+  }
+
+  class Normalize(pca: PCA) extends CommandLineFunction with LongRunTime {
+    @Input(doc = "")
+    val input = pca.input
+
+    @Input(doc = "")
+    val inPC = pca.outPC
+
+    @Input(doc = "")
+    val inPC_SD = pca.outPC_SD
+
+    @Input(doc = "")
+    val inPC_LOADINGS = pca.outPC_LOADINGS
+
+    @Output
+    val normalized: File = new File(outputBase.getPath + ".PCA_normalized.txt")
+
+    var command: String =
+      xhmmExec + " --normalize" +
+      " -r " + input +
+      " --PCAfiles " + pca.PCAbase +
+      " --normalizeOutput " + normalized
+    if (PCAnormalizeMethodString != "")
+      command += " " + PCAnormalizeMethodString
+
+    override def commandLine = command
+
+    override def description = "Normalizes mean-centered data using PCA information: " + command
+  }
+
+  class FilterAndZscoreNormalized(inputParam: File) extends CommandLineFunction with WholeMatrixMemoryLimit with LongRunTime {
+    @Input(doc = "")
+    val input = inputParam
+
+    @Output
+    val filteredZscored: File = new File(outputBase.getPath + ".PCA_normalized.filtered.sample_zscores" + RD_OUTPUT_SUFFIX)
+    @Output
+    val filteredTargets: File = new File(filteredZscored.getPath + FILTERED_TARGS_SUFFIX)
+    @Output
+    val filteredSamples: File = new File(filteredZscored.getPath + FILTERED_SAMPS_SUFFIX)
+
+    var command: String =
+      xhmmExec + " --matrix" +
+      " -r " + input +
+      " --centerData --centerType sample --zScoreData" +
+      " -o " + filteredZscored +
+      " --outputExcludedTargets " + filteredTargets +
+      " --outputExcludedSamples " + filteredSamples
+    if (targetSampleNormalizedFiltersString != "")
+      command += " " + targetSampleNormalizedFiltersString
+
+    override def commandLine = command
+
+    override def description = "Filters and z-score centers (by sample) the PCA-normalized data: " + command
+  }
+
+  class FilterOriginalData(inputParam: File, filt1: FilterCenterRawMatrix, filt2: FilterAndZscoreNormalized) extends CommandLineFunction with WholeMatrixMemoryLimit with LongRunTime {
+    @Input(doc = "")
+    val input = inputParam
+
+    @Input(doc = "")
+    val targFilters: List[File] = List(filt1.filteredTargets, filt2.filteredTargets).map(u => new File(u))
+
+    @Input(doc = "")
+    val sampFilters: List[File] = List(filt1.filteredSamples, filt2.filteredSamples).map(u => new File(u))
+
+    @Output
+    val sameFiltered: File = new File(outputBase.getPath + ".same_filtered" + RD_OUTPUT_SUFFIX)
+
+    var command: String =
+      xhmmExec + " --matrix" +
+      " -r " + input +
+      targFilters.map(u => " --excludeTargets " + u).reduceLeft(_ + "" + _) +
+      sampFilters.map(u => " --excludeSamples " + u).reduceLeft(_ + "" + _) +
+      " -o " + sameFiltered
+
+    override def commandLine = command
+
+    override def description = "Filters original read-depth data to be the same as filtered, normalized data: " + command
+  }
+}
+
+
+abstract class SamplesScatterable(val xhmmExec: File, val groups: List[Group]) extends ScatterGatherableFunction with CommandLineFunction {
+  this.scatterCount = groups.size
+  this.scatterClass = classOf[SamplesScatterFunction]
+
+  @Input(doc = "", required=false)
+  var keepSampleIDs: Option[String] = None
+
+  def addCommand = if (keepSampleIDs.isDefined) ("--keepSampleIDs " + keepSampleIDs.get) else ""
+}
+
+class SamplesScatterFunction extends ScatterFunction with InProcessFunction {
+  protected var groups: List[Group] = _
+  override def scatterCount = groups.size
+
+  @Output(doc="Scatter function outputs")
+  var scatterSamples: Seq[File] = Nil
+
+  override def init() {
+    this.groups = this.originalFunction.asInstanceOf[SamplesScatterable].groups
+  }
+
+  override def bindCloneInputs(cloneFunction: CloneFunction, index: Int) {
+    val scatterPart = IOUtils.absolute(cloneFunction.commandDirectory, "keepSampleIDs.txt")
+    cloneFunction.setFieldValue("keepSampleIDs", Some(scatterPart))
+    this.scatterSamples :+= scatterPart
+  }
+
+  override def run() {
+    if (groups.size != this.scatterSamples.size)
+      throw new Exception("Internal inconsistency error in scattering jobs")
+
+    (groups, this.scatterSamples).zipped foreach {
+      (group, sampsFile) => {
+        val sampsWriter = new PrintWriter(new PrintStream(sampsFile))
+
+        for (samp <- group.samples) {
+          try {
+            sampsWriter.printf("%s%n", samp)
+          }
+          catch {
+            case e: Exception => throw e
+          }
+        }
+        sampsWriter.close
+      }
+    }
+  }
+}
+
+trait MergeVCFs extends CommandLineFunction {
+  var xhmmExec: File = _
+
+  @Input(doc = "")
+  var inputVCFs: List[File] = Nil
+
+  @Output
+  var mergedVCF: File = null
+
+  override def commandLine =
+    xhmmExec + " --mergeVCFs" +
+      inputVCFs.map(input => " --mergeVCF " + input).reduceLeft(_ + "" + _) +
+      " -v " + mergedVCF
+
+  override def description = "Combines VCF outputs for multiple samples (at same loci): " + commandLine
+}
+
+class MergeVCFsGatherFunction extends MergeVCFs with GatherFunction {
+  override def freezeFieldValues() {
+    super.freezeFieldValues()
+
+    this.xhmmExec = originalFunction.asInstanceOf[SamplesScatterable].xhmmExec
+
+    this.inputVCFs = this.gatherParts.toList
+    this.mergedVCF = this.originalOutput
+  }
+}
+
+class DummyGatherFunction extends InProcessFunction with GatherFunction {
+  override def run() {}
+}
diff --git a/public/gatk-queue-extensions-public/src/main/qscripts/org/broadinstitute/gatk/queue/qscripts/GATKResourcesBundle.scala b/public/gatk-queue-extensions-public/src/main/qscripts/org/broadinstitute/gatk/queue/qscripts/GATKResourcesBundle.scala
new file mode 100644
index 0000000..d89e605
--- /dev/null
+++ b/public/gatk-queue-extensions-public/src/main/qscripts/org/broadinstitute/gatk/queue/qscripts/GATKResourcesBundle.scala
@@ -0,0 +1,426 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.queue.qscripts
+
+import org.broadinstitute.gatk.queue.QScript
+import org.broadinstitute.gatk.queue.extensions.gatk._
+import org.broadinstitute.gatk.queue.extensions.samtools.SamtoolsIndexFunction
+import org.broadinstitute.gatk.utils.exceptions.ReviewedGATKException
+import org.broadinstitute.gatk.queue.extensions.picard.PicardBamFunction
+import org.broadinstitute.gatk.queue.function.JavaCommandLineFunction
+
+class GATKResourcesBundle extends QScript {
+  // todo -- update to released version when things stabilize
+  @Argument(doc="gatkJarFile", required=false)
+  var gatkJarFile: File = new File("dist/GenomeAnalysisTK.jar")
+
+  @Argument(doc="liftOverPerl", required=false)
+  var liftOverPerl: File = new File("./public/perl/liftOverVCF.pl")
+
+  @Argument(shortName = "ver", doc="The GIT version of this release", required=true)
+  var BUNDLE_VERSION: String = _
+
+  @Argument(shortName = "bundleDir", doc="Path to root where resource files will be placed", required=false)
+  val BUNDLE_ROOT = new File("/humgen/gsa-hpprojects/GATK/bundle")
+
+  @Argument(shortName = "downloadDir", doc="Path to root where resource files will be placed for users to download", required=false)
+  val DOWNLOAD_ROOT = new File("/humgen/gsa-scr1/pub/bundle")
+
+  @Argument(shortName = "test", doc="", required=false)
+  val TEST = false
+
+  @Argument(shortName = "phase2", doc="", required=false)
+  val DO_DOWNLOAD = false
+
+  val SITES_EXT: String = "sites"
+
+  def BUNDLE_DIR: File = BUNDLE_ROOT + "/" + BUNDLE_VERSION
+  def DOWNLOAD_DIR: File = DOWNLOAD_ROOT + "/" + BUNDLE_VERSION
+
+  // REFERENCES
+  class Reference( val name: String, val file: File ) { }
+  var hg19: Reference = _
+  var b37: Reference = _
+  var hg18: Reference = _
+  var b36: Reference = _
+  var exampleFASTA: Reference = _
+  var refs: List[Reference] = _
+
+  class Resource(val file: File, val name: String, val ref: Reference, val useName: Boolean = true, val makeSites: Boolean = true, val makeCallsIfBam: Boolean = true ) {
+    def destname(target: Reference): String = {
+      if ( useName )
+        return name + "." + target.name + "." + getExtension(file)
+      else
+        return file.getName
+    }
+  }
+
+  def liftover(in: File, inRef: Reference, out: File, outRef: Reference): CommandLineFunction = {
+    //Console.printf("liftover(%s => %s)%n", inRef.name, outRef.name)
+    (inRef.name, outRef.name) match {
+      case ("b37", "hg19") =>
+        return new LiftOverPerl(in, out, new File("public/chainFiles/b37tohg19.chain"), inRef, outRef)
+      case ("b37", "hg18") =>
+        return new LiftOverPerl(in, out, new File("public/chainFiles/b37tohg18.chain"), inRef, outRef)
+      case ("b37", "b36") =>
+        return new LiftOverPerl(in, out, new File("public/chainFiles/b37tob36.chain"), inRef, outRef)
+      case _ => return null
+    }
+  }
+
+  def isVCF(file: File) = file.getName.endsWith(".vcf")
+  def isBAM(file: File) = file.getName.endsWith(".bam")
+  def isOUT(file: File) = file.getName.endsWith(".out")
+  def isFASTA(file: File) = file.getName.endsWith(".fasta")
+  def isIntervalList(file: File) = file.getName.endsWith(".interval_list")
+
+  var RESOURCES: List[Resource] = Nil
+  def addResource(comp: Resource) { RESOURCES = comp :: RESOURCES }
+
+  trait UNIVERSAL_GATK_ARGS extends CommandLineGATK {
+    this.logging_level = "INFO";
+    this.jarFile = gatkJarFile;
+    this.memoryLimit = 2
+  }
+
+  def initializeTestDataFiles() = {
+    //
+    // Standard evaluation files for indel
+    //
+    b37 = new Reference("b37", new File("/Users/depristo/Desktop/broadLocal/localData/human_g1k_v37.fasta"))
+    hg18 = new Reference("hg18", new File("/Users/depristo/Desktop/broadLocal/localData/Homo_sapiens_assembly18.fasta"))
+    exampleFASTA = new Reference("exampleFASTA", new File("public/testdata/exampleFASTA.fasta"))
+    refs = List(b37, hg18, exampleFASTA)
+
+    val DATAROOT = "/Users/depristo/Desktop/broadLocal/localData/"
+    //addResource(new Resource(DATAROOT + "human_g1k_v37.fasta", "human_g1k_v37.fasta", b37, false))
+    addResource(new Resource(DATAROOT + "1000G.snp.validation.b37.vcf", "1000G.snp.validation", b37))
+    addResource(new Resource(DATAROOT + "dbsnp_132_b37.vcf", "dbsnp_132", b37, true, false))
+
+    addResource(new Resource(exampleFASTA.file, "exampleFASTA", exampleFASTA, false))
+    addResource(new Resource("public/testdata/exampleBAM.bam", "exampleBAM", exampleFASTA, false, false, false))
+  }
+
+  def initializeStandardDataFiles() = {
+    //
+    // references
+    //
+    hg19 = new Reference("hg19", new File("/humgen/gsa-hpprojects/GATK/data/ucsc.hg19/ucsc.hg19.fasta"))
+    b37 = new Reference("b37", new File("/humgen/1kg/reference/human_g1k_v37.fasta"))
+    hg18 = new Reference("hg18", new File("/seq/references/Homo_sapiens_assembly18/v0/Homo_sapiens_assembly18.fasta"))
+    b36 = new Reference("b36", new File("/humgen/1kg/reference/human_b36_both.fasta"))
+    exampleFASTA = new Reference("exampleFASTA", new File("public/testdata/exampleFASTA.fasta"))
+    refs = List(hg19, b37, hg18, b36, exampleFASTA)
+
+    addResource(new Resource(b37.file, "", b37, false))
+    addResource(new Resource(b36.file, "", b36, false))
+    addResource(new Resource(hg19.file, "", hg19, false))
+    addResource(new Resource(hg18.file, "", hg18, false))
+
+    //
+    // The b37_decoy reference
+    //
+    addResource(new Resource("/humgen/1kg/reference/human_g1k_v37_decoy.fasta",
+          "IGNORE", b37, false, false))
+
+    //
+    // standard VCF files.  Will be lifted to each reference
+    //
+    addResource(new Resource("/humgen/gsa-hpprojects/GATK/data/Comparisons/Validated/dbSNP/dbsnp_138_b37.leftAligned.vcf",
+      "dbsnp_138", b37, true, false))
+
+    addResource(new Resource("/humgen/gsa-hpprojects/GATK/data/Comparisons/Validated/Omni2.5_chip/Omni25_sites_2141_samples.b37.vcf",
+      "1000G_omni2.5", b37, true, false))
+
+    addResource(new Resource("/humgen/gsa-hpprojects/GATK/data/Comparisons/Validated/HapMap/3.3/sites_r27_nr.b37_fwd.vcf",
+      "hapmap_3.3", b37, true, false))
+
+    addResource(new Resource("/humgen/1kg/DCC/ftp/technical/working/20120312_phase1_v2_indel_cleaned_sites_list/ALL.wgs.phase1_release_v2.20101123.official_indel_calls.20120312.sites.vcf",
+      "1000G_phase1.indels", b37, true, false))
+
+    addResource(new Resource("/humgen/1kg/processing/official_release/phase1/projectConsensus/phase1.wgs.projectConsensus.v2b.recal.highQuality.vcf",
+      "1000G_phase1.snps.high_confidence", b37, true, false))
+
+    addResource(new Resource("/humgen/gsa-hpprojects/GATK/data/Comparisons/Unvalidated/GoldStandardIndel/gold.standard.indel.MillsAnd1000G.b37.vcf",
+      "Mills_and_1000G_gold_standard.indels", b37, true, false))
+
+    //
+    // CEU trio (NA12878,NA12891,NA12892) best practices results
+    //
+
+    addResource(new Resource("/humgen/1kg/processing/production_wgs_final/trio/CEU/CEU.wgs.HaplotypeCaller.20131118.snps_indels.high_coverage_pcr_free.genotypes.vcf",
+      "CEUTrio.HiSeq.WGS.b37.bestPractices",b37,true,false))
+
+    //
+    // NA12878 knowledgebase snapshot
+    //
+
+    addResource(new Resource("/humgen/gsa-hpprojects/NA12878Collection/knowledgeBase/snapshots/NA12878.wgs.broad_truth_set.20131119.snps_and_indels.genotypes.vcf",
+      "NA12878.knowledgebase.snapshot.20131119",b37,true,false))
+
+    //
+    // example call set for documentation guide tutorial
+    //
+    addResource(new Resource("/humgen/gsa-hpprojects/NA12878Collection/exampleCalls/NA12878.HiSeq.WGS.bwa.cleaned.raw.b37.subset.vcf",
+      "NA12878.HiSeq.WGS.bwa.cleaned.raw.subset", b37, true, true))
+
+    //
+    // Test BAM file, only for the b37 reference
+    //
+    addResource(new Resource("/humgen/gsa-hpprojects/NA12878Collection/bams/CEUTrio.HiSeq.WGS.b37.NA12878.bam",
+      "IGNORE", b37, false, false))
+
+    //
+    // Exome targets file, only for the b37 reference
+    //
+    addResource(new Resource("/seq/references/HybSelOligos/HybSelOligos/whole_exome_agilent_1.1_refseq_plus_3_boosters/whole_exome_agilent_1.1_refseq_plus_3_boosters.Homo_sapiens_assembly19.targets.interval_list",
+      "Broad.human.exome", b37, true, false, false))
+
+    //
+    // refGene files specific to each reference
+    //
+    addResource(new Resource("/humgen/gsa-hpprojects/GATK/data/refGene_b37.sorted.txt",
+      "refGene", b37, true, false))
+
+    addResource(new Resource("public/chainFiles/hg18tob37.chain", "", hg18, false, false))
+    addResource(new Resource("public/chainFiles/b36tob37.chain", "", b36, false, false))
+
+    // todo -- chain files?
+    // todo 1000G SNP and indel call sets?
+
+    //
+    // exampleFASTA file
+    //
+    addResource(new Resource(exampleFASTA.file, "exampleFASTA", exampleFASTA, false))
+    addResource(new Resource("public/testdata/exampleBAM.bam", "exampleBAM", exampleFASTA, false, false, false))
+  }
+
+  def createBundleDirectories(dir: File) = {
+    if ( ! dir.exists ) dir.mkdirs()
+
+    for ( ref <- refs ) {
+      val refDir = new File(dir + "/" + ref.name)
+      if ( ! refDir.exists ) refDir.mkdirs()
+    }
+  }
+
+  def createCurrentLink(bundleDir: File) = {
+
+    val currentLink = new File(BUNDLE_ROOT + "/current")
+
+    if ( currentLink.exists ) add(new deleteLink(currentLink))
+
+    add(new linkFile(bundleDir, currentLink))
+  }
+
+  def script = {
+    if ( TEST )
+      initializeTestDataFiles();
+    else
+      initializeStandardDataFiles();
+
+    if ( ! DO_DOWNLOAD ) {
+      // create destination directory structure
+      createBundleDirectories(BUNDLE_DIR)
+
+      for ( resource: Resource <- RESOURCES ) {
+        if ( isFASTA(resource.file) ) {
+          copyBundleFasta(resource, resource.ref)
+        } else if ( isBAM(resource.file) ) {
+          val f = copyBundleFile(resource, resource.ref)
+          add(new IndexBAM(f))
+	  if ( resource.makeCallsIfBam ) {
+            @Output val outvcf: File = swapExt(f.getParent, f, ".bam", ".vcf")
+            add(new UG(resource.file, resource.ref.file, outvcf))
+	  }
+        } else if ( isVCF(resource.file) ) {
+          for ( destRef <- refs ) {
+            val out = destFile(BUNDLE_DIR, destRef, resource.destname(destRef))
+            var continue = true
+
+            // copy or lift over the original vcf
+            if ( resource.ref == destRef ) {
+              add(new cpFile(resource.file, out))
+            } else {
+              val clf = liftover(resource.file, resource.ref, out, destRef)
+              if ( clf != null ) {
+                add(clf)
+              } else {
+                continue = false
+              }
+            }
+
+            if ( continue ) {
+              add(new IndexVCF(out, destRef.file))
+
+              if ( resource.makeSites ) {
+                val sites: Resource = new Resource(swapExt(out.getParent, out, ".vcf", "." + SITES_EXT + ".vcf"), "", destRef, false)
+                add(new JustSites(out, sites.file))
+                add(new IndexVCF(sites.file, destRef.file))
+              }
+
+              if ( resource.name.contains("dbsnp") ) {
+                val dbsnp129: Resource = new Resource(swapExt(out.getParent, out, ".vcf", ".excluding_sites_after_129.vcf"), "", destRef, false)
+                add(new MakeDBSNP129(out, destRef.file, dbsnp129.file))
+                add(new IndexVCF(dbsnp129.file, destRef.file))
+              }
+            }
+          }
+        } else if ( isIntervalList(resource.file) ) {
+            val out = destFile(BUNDLE_DIR, resource.ref, resource.destname(resource.ref))
+            add(new cpFile(resource.file, out))
+        } else {
+          //throw new ReviewedStingException("Unknown file type: " + resource)
+        }
+      }
+
+    } else {
+      createCurrentLink(BUNDLE_DIR)
+      createBundleDirectories(DOWNLOAD_DIR)
+      createDownloadsFromBundle(BUNDLE_DIR, DOWNLOAD_DIR)
+    }
+  }
+
+
+  def createDownloadsFromBundle(in: File, out: File) {
+    Console.printf("Visiting %s%n", in)
+    if (! in.getName.startsWith(".")) {
+      if ( in.isDirectory ) {
+        out.mkdirs
+
+        for ( child: File <- in.listFiles ) {
+          createDownloadsFromBundle(child, out + "/" + child.getName)
+        }
+      } else {
+        if ( isBAM(in) ) {
+          add(new cpFile(in, out))
+          add(new md5sum(out))
+        } else if ( !isOUT(in) ) {
+          add(new GzipFile(in, out + ".gz"))
+          add(new md5sum(out + ".gz"))
+        }
+
+      }
+    }
+  }
+
+  def copyBundleFasta(res: Resource, ref: Reference) {
+    val out = destFile(BUNDLE_DIR, ref, res.destname(ref))
+    add(new cpFile(res.file, out))
+
+    val oldRefDict = swapExt(res.file.getParent, res.file, ".fasta", ".dict")
+    val newRefDict = swapExt(out.getParent, out, ".fasta", ".dict")
+
+    val oldRefFai = swapExt(res.file.getParent, res.file, ".fasta", ".fasta.fai")
+    val newRefFai = swapExt(out.getParent, out, ".fasta", ".fasta.fai")
+
+    add(new cpFile(oldRefDict, newRefDict))
+    add(new cpFile(oldRefFai, newRefFai))
+  }
+
+  def copyBundleFile(res: Resource, ref: Reference): File = {
+    val out = destFile(BUNDLE_DIR, ref, res.destname(ref))
+    add(new cpFile(res.file, out))
+    return out
+  }
+
+  def destFile(dir: File, ref: Reference, f: File): File = {
+    return destFile(dir, ref, f.getName)
+  }
+
+  def destFile(dir: File, ref: Reference, name: String): File = {
+    return new File(dir + "/" + ref.name + "/" + name)
+  }
+
+  /**
+   * A command line (cut) that removes all genotyping information from a file
+   */
+  class JustSites(@Input(doc="foo") in: File, @Output(doc="foo") out: File) extends CommandLineFunction {
+    def commandLine = "cut -f 1-8 %s > %s".format(in, out)
+  }
+
+  class GzipFile(@Input val in: File, @Output val out: File) extends CommandLineFunction {
+    def commandLine = "gzip -c %s > %s".format(in.getAbsolutePath, out.getAbsolutePath)
+  }
+
+  class cpFile(@Input val in: File, @Output val out: File) extends CommandLineFunction {
+    def commandLine = "cp %s %s".format(in.getAbsolutePath, out.getAbsolutePath)
+  }
+
+  class deleteLink(@Input val in: File) extends CommandLineFunction {
+    def commandLine = "rm %s".format(in.getAbsolutePath)
+  }
+
+  class linkFile(@Input val in: File, @Output val out: File) extends CommandLineFunction {
+    def commandLine = "ln -s %s %s".format(in.getAbsolutePath, out.getAbsolutePath)
+  }
+
+  class md5sum(@Input val in: File) extends CommandLineFunction {
+    @Output val o: File = new File(in.getAbsolutePath + ".md5")
+    def commandLine = "md5sum %s > %s".format(in.getAbsolutePath, o)
+  }
+
+  class IndexBAM(bamIn: File) extends SamtoolsIndexFunction {
+    bamFile = bamIn
+  }
+
+  class IndexVCF(@Input vcf: File, @Input ref: File) extends CountRODs with UNIVERSAL_GATK_ARGS {
+    //@Output val vcfIndex: File = swapExt(vcf.getParent, vcf, ".vcf", ".vcf.idx")
+    this.rod :+= vcf
+    this.reference_sequence = ref
+  }
+
+  class UG(@Input bam: File, @Input ref: File, @Input outVCF: File) extends UnifiedGenotyper with UNIVERSAL_GATK_ARGS {
+    this.input_file = List(bam)
+    this.reference_sequence = ref
+    this.intervalsString ++= List("20");
+    this.out = outVCF
+  }
+
+  class MakeDBSNP129(@Input dbsnp: File, @Input ref: File, @Output dbsnp129: File) extends SelectVariants with UNIVERSAL_GATK_ARGS {
+    this.variant = dbsnp
+    this.select ++= List("dbSNPBuildID <= 129")
+    this.reference_sequence = ref
+    this.out = dbsnp129
+  }
+
+  class LiftOverPerl(@Input val in: File, @Output val out: File, @Input val chain: File, oldRef: Reference, newRef: Reference) extends CommandLineFunction {
+    this.memoryLimit = 12
+    def commandLine = ("%s -vcf %s -chain %s -out %s " +
+      "-gatk ./ -newRef %s -oldRef %s -tmp %s").format(liftOverPerl, in.getAbsolutePath, chain,
+      out.getAbsolutePath, newRef.file.replace(".fasta", ""),
+      oldRef.file.replace(".fasta", ""), jobTempDir)
+  }
+
+  def getExtension(f: File): String = {
+    val i = f.getName.lastIndexOf('.');
+    if (i > 0 && i < f.getName.length() - 1)
+      return f.getName.substring(i+1).toLowerCase();
+    else
+      return "";
+  }
+}
+
diff --git a/public/gatk-queue-extensions-public/src/main/qscripts/org/broadinstitute/gatk/queue/qscripts/examples/ExampleCountLoci.scala b/public/gatk-queue-extensions-public/src/main/qscripts/org/broadinstitute/gatk/queue/qscripts/examples/ExampleCountLoci.scala
new file mode 100644
index 0000000..e988a42
--- /dev/null
+++ b/public/gatk-queue-extensions-public/src/main/qscripts/org/broadinstitute/gatk/queue/qscripts/examples/ExampleCountLoci.scala
@@ -0,0 +1,56 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.queue.qscripts.examples
+
+import org.broadinstitute.gatk.queue.QScript
+import org.broadinstitute.gatk.queue.extensions.gatk._
+
+/**
+ * An introductory pipeline with integration tests testing the MD5 of the @Output.
+ */
+class ExampleCountLoci extends QScript {
+  @Input(doc="The reference file for the bam files.", shortName="R")
+  var referenceFile: File = null
+
+  @Input(doc="One or more bam files.", shortName="I")
+  var bamFiles: List[File] = Nil
+
+  @Input(doc="Intervals to traverse.", shortName="L", required=false)
+  var intervals: List[String] = Nil
+
+  @Output
+  var out: File = _
+
+  def script() {
+    val countLoci = new CountLoci
+    countLoci.reference_sequence = referenceFile
+    countLoci.input_file = bamFiles
+    countLoci.intervalsString = intervals
+    countLoci.out = out
+    countLoci.memoryLimit = 1
+    add(countLoci)
+  }
+}
diff --git a/public/gatk-queue-extensions-public/src/main/qscripts/org/broadinstitute/gatk/queue/qscripts/examples/ExampleCountReads.scala b/public/gatk-queue-extensions-public/src/main/qscripts/org/broadinstitute/gatk/queue/qscripts/examples/ExampleCountReads.scala
new file mode 100644
index 0000000..55711c0
--- /dev/null
+++ b/public/gatk-queue-extensions-public/src/main/qscripts/org/broadinstitute/gatk/queue/qscripts/examples/ExampleCountReads.scala
@@ -0,0 +1,87 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.queue.qscripts.examples
+
+import org.broadinstitute.gatk.queue.QScript
+import org.broadinstitute.gatk.queue.extensions.gatk._
+
+/**
+ * An introductory pipeline for Queue.
+ * Runs the GATK CountReads individually and across a set of bams.
+ * All bams must have the same reference.
+ */
+class ExampleCountReads extends QScript {
+  @Input(doc="The reference file for the bam files.", shortName="R")
+  var referenceFile: File = null
+
+  // NOTE: Do not initialize List, Set, or Option to null
+  // as you won't be able to update the collection.
+  // By default set:
+  //   List[T] = Nil
+  //   Set[T] = Set.empty[T]
+  //   Option[T] = None
+  @Input(doc="One or more bam files.", shortName="I")
+  var bamFiles: List[File] = Nil
+
+  /**
+   * In script, you create and then add() functions to the pipeline.
+   */
+  def script() {
+
+    // Run CountReads for all bams jointly.
+
+    // Create a new CountReads from the Queue GATK Extensions.
+    // The names of walkers are the same as you would use for '-T <WalkerName>'
+    val jointCountReads = new CountReads
+
+    // Each field in the extensions is based off of the full form of the arguments.
+    // To get the list of arguments and their descriptions run
+    // java -jar <path to GenomeAnalysisTK.jar> -T <WalkerName> -help
+    jointCountReads.reference_sequence = referenceFile
+
+    // GATK inputs that take more than one file will have a singular name which
+    // matches the full form of the argument, but will actually be a scala List[]
+    jointCountReads.input_file = bamFiles
+
+    // Set the memory limit. Also acts as a memory request on LSF and GridEngine.
+    jointCountReads.memoryLimit = 1
+
+    // Add the newly created function to the pipeline.
+    add(jointCountReads)
+
+    // If there is more than one BAM, also run CountReads once for each bam.
+    if (bamFiles.size > 1) {
+      for (bamFile <- bamFiles) {
+        val singleCountReads = new CountReads
+        singleCountReads.reference_sequence = referenceFile
+        // ':+' is the scala List append operator
+        singleCountReads.input_file :+= bamFile
+        singleCountReads.memoryLimit = 1
+        add(singleCountReads)
+      }
+    }
+  }
+}
diff --git a/public/gatk-queue-extensions-public/src/main/qscripts/org/broadinstitute/gatk/queue/qscripts/examples/ExampleCustomWalker.scala b/public/gatk-queue-extensions-public/src/main/qscripts/org/broadinstitute/gatk/queue/qscripts/examples/ExampleCustomWalker.scala
new file mode 100644
index 0000000..e38ba3e
--- /dev/null
+++ b/public/gatk-queue-extensions-public/src/main/qscripts/org/broadinstitute/gatk/queue/qscripts/examples/ExampleCustomWalker.scala
@@ -0,0 +1,73 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.queue.qscripts.examples
+
+import org.broadinstitute.gatk.queue.QScript
+import org.broadinstitute.gatk.queue.extensions.gatk._
+
+/**
+ * A pipeline for Queue that runs a custom walker on the classpath.
+ * NOTE: This code is an unsupported example for soliciting feedback on how to improve Queue.
+ * Future syntax will simplify running the GATK so please expect the syntax below to change significantly.
+ */
+class ExampleCustomWalker extends QScript {
+  @Input(doc="The reference file for the bam files.", shortName="R")
+  var referenceFile: File = null
+
+  // NOTE: Do not initialize List, Set, or Option to null
+  // as you won't be able to update the collection.
+  // By default set:
+  //   List[T] = Nil
+  //   Set[T] = Set.empty[T]
+  //   Option[T] = None
+  @Input(doc="One or more bam files.", shortName="I")
+  var bamFiles: List[File] = Nil
+
+  /**
+   * In script, you create and then add() functions to the pipeline.
+   */
+  def script() {
+    val customWalker = new CommandLineGATK {
+      // Set the name of your walker, for example this will be passed as -T MyCustomWalker
+      this.analysis_type = "MyCustomWalker"
+
+      // If your walker is already on the classpath you shouldn't need to do anything else
+
+      // If your walker is in a GATK jar that is for some reason NOT on the classpath
+      // nor referenced in the Queue.jar's, specify the jar file here
+      //this.jarFile = "myGATK.jar"
+
+      // If your walker needs a custom classpath, specify it here
+      //this.javaClasspath = List("myClasses")
+    }
+
+    customWalker.reference_sequence = referenceFile
+    customWalker.input_file = bamFiles
+
+    // Add the newly created function to the pipeline.
+    add(customWalker)
+  }
+}
diff --git a/public/gatk-queue-extensions-public/src/main/qscripts/org/broadinstitute/gatk/queue/qscripts/examples/ExamplePrintReads.scala b/public/gatk-queue-extensions-public/src/main/qscripts/org/broadinstitute/gatk/queue/qscripts/examples/ExamplePrintReads.scala
new file mode 100644
index 0000000..440b6f2
--- /dev/null
+++ b/public/gatk-queue-extensions-public/src/main/qscripts/org/broadinstitute/gatk/queue/qscripts/examples/ExamplePrintReads.scala
@@ -0,0 +1,53 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.queue.qscripts.examples
+
+import org.broadinstitute.gatk.queue.QScript
+import org.broadinstitute.gatk.queue.extensions.gatk._
+
+/**
+ * Script used for testing output to /dev/null, deleting .bai files, etc.
+ */
+class ExamplePrintReads extends QScript {
+  @Input(doc="The reference file for the bam files.", shortName="R")
+  var referenceFile: File = _
+
+  @Input(doc="Bam file to genotype.", shortName="I")
+  var bamFile: File = _
+
+  @Output(doc="Bam output", shortName="out")
+  var outFile: File = _
+
+  def script() {
+    val printReads = new PrintReads
+    printReads.reference_sequence = referenceFile
+    printReads.memoryLimit = 2
+    printReads.scatterCount = 3
+    printReads.input_file :+= bamFile
+    printReads.out = outFile
+    add(printReads)
+  }
+}
diff --git a/public/gatk-queue-extensions-public/src/main/qscripts/org/broadinstitute/gatk/queue/qscripts/examples/ExampleReadFilter.scala b/public/gatk-queue-extensions-public/src/main/qscripts/org/broadinstitute/gatk/queue/qscripts/examples/ExampleReadFilter.scala
new file mode 100644
index 0000000..f736406
--- /dev/null
+++ b/public/gatk-queue-extensions-public/src/main/qscripts/org/broadinstitute/gatk/queue/qscripts/examples/ExampleReadFilter.scala
@@ -0,0 +1,48 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.queue.qscripts.examples
+
+import org.broadinstitute.gatk.queue.QScript
+import org.broadinstitute.gatk.queue.extensions.gatk._
+
+/**
+ * Script used for testing inclusion of a read filter
+ */
+class ExampleReadFilter extends QScript {
+  @Input(doc="The reference file for the bam files.", shortName="R")
+  var referenceFile: File = _
+
+  @Input(doc="Bam file to genotype.", shortName="I")
+  var bamFile: File = _
+
+  def script() {
+    val printReads = new PrintReads with BadMate
+    printReads.reference_sequence = referenceFile
+    printReads.memoryLimit = 2
+    printReads.input_file :+= bamFile
+    add(printReads)
+  }
+}
diff --git a/public/gatk-queue-extensions-public/src/main/qscripts/org/broadinstitute/gatk/queue/qscripts/examples/ExampleRetryMemoryLimit.scala b/public/gatk-queue-extensions-public/src/main/qscripts/org/broadinstitute/gatk/queue/qscripts/examples/ExampleRetryMemoryLimit.scala
new file mode 100644
index 0000000..71e0094
--- /dev/null
+++ b/public/gatk-queue-extensions-public/src/main/qscripts/org/broadinstitute/gatk/queue/qscripts/examples/ExampleRetryMemoryLimit.scala
@@ -0,0 +1,53 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.queue.qscripts.examples
+
+import org.broadinstitute.gatk.queue.function.RetryMemoryLimit
+import org.broadinstitute.gatk.queue.QScript
+import org.broadinstitute.gatk.queue.extensions.gatk._
+
+class ExampleRetryMemoryLimit extends QScript {
+  @Input(doc="The reference file for the bam files.", shortName="R")
+  var referenceFile: File = _
+
+  @Input(doc="Bam file to print.", shortName="I")
+  var bamFile: File = _
+
+  def script() {
+    for (scatterCount <- 1 to 2) {
+      val printReads = new PrintReads with RetryMemoryLimit
+      // First run with 1m
+      printReads.memoryLimit = .001
+      // On retry run with 1g
+      printReads.retryMemoryFunction = (d => d * 1000)
+      printReads.reference_sequence = referenceFile
+      printReads.input_file = Seq(bamFile)
+      printReads.out = swapExt(bamFile, ".bam", ".out.scattered_%d.bam".format(scatterCount))
+      printReads.scatterCount = scatterCount
+      add(printReads)
+    }
+  }
+}
diff --git a/public/gatk-queue-extensions-public/src/main/qscripts/org/broadinstitute/gatk/queue/qscripts/examples/HelloWorld.scala b/public/gatk-queue-extensions-public/src/main/qscripts/org/broadinstitute/gatk/queue/qscripts/examples/HelloWorld.scala
new file mode 100644
index 0000000..c095169
--- /dev/null
+++ b/public/gatk-queue-extensions-public/src/main/qscripts/org/broadinstitute/gatk/queue/qscripts/examples/HelloWorld.scala
@@ -0,0 +1,36 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.queue.qscripts.examples
+
+import org.broadinstitute.gatk.queue.QScript
+
+class HelloWorld extends QScript {
+  def script() {
+    add(new CommandLineFunction {
+      def commandLine = "echo hello world"
+    })
+  }
+}
diff --git a/public/gatk-queue-extensions-public/src/main/qscripts/org/broadinstitute/gatk/queue/qscripts/lib/ChunkVCF.scala b/public/gatk-queue-extensions-public/src/main/qscripts/org/broadinstitute/gatk/queue/qscripts/lib/ChunkVCF.scala
new file mode 100644
index 0000000..ab687c0
--- /dev/null
+++ b/public/gatk-queue-extensions-public/src/main/qscripts/org/broadinstitute/gatk/queue/qscripts/lib/ChunkVCF.scala
@@ -0,0 +1,115 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.queue.qscripts.lib
+
+import org.broadinstitute.gatk.queue.QScript
+import org.broadinstitute.gatk.queue.library.ipf.vcf.VCFExtractIntervals
+import scala.collection.JavaConversions._
+import org.broadinstitute.gatk.utils.text.XReadLines
+import java.io.PrintStream
+import org.broadinstitute.gatk.queue.extensions.gatk.SelectVariants
+
+/**
+ * Created by IntelliJ IDEA.
+ * User: chartl
+ * Date: 2/2/12
+ * Time: 12:13 PM
+ * To change this template use File | Settings | File Templates.
+ */
+
+class ChunkVCF extends QScript {
+
+  @Input(shortName="V",fullName="VCF",doc="The VCF you want to chunk",required=true)
+  var inVCF : File = _
+
+  @Input(shortName="N",fullName="numEntriesInChunk",doc="The number of variants per chunk",required=true)
+  var numEntries : Int = _
+
+  @Input(shortName="I",fullName="Intervals",doc="The SNP interval list to chunk. If not provided, one will be created for you to provide in a second run.",required=false)
+  var intervals : File = _
+
+  @Input(fullName="preserveChromosomes",doc="Restrict chunks to one chromosome (smaller chunk at end of chromosome)",required=false)
+  var preserve : Boolean = false
+
+  @Input(fullName="reference",doc="The reference file",required=false)
+  var ref : File = new File("/humgen/1kg/reference/human_g1k_v37.fasta")
+
+  @Input(fullName="samples",doc="A file of sample IDs to condense VCF file to",required=false)
+  var extractSamples : File = _
+
+  val tmpdir : File = System.getProperty("java.io.tmpdir")
+
+  def script = {
+    if ( intervals == null ) {
+      // create an interval list from the VCF
+      val ivals : File = swapExt(inVCF,".vcf",".intervals.list")
+      val extract : VCFExtractIntervals = new VCFExtractIntervals(inVCF,ivals,false)
+      add(extract)
+    } else {
+      var chunkNum = 1
+      var numLinesInChunk = 0
+      var chromosome : String = asScalaIterator(new XReadLines(intervals)).next().split(":")(0)
+      var chunkFile : File = new File(tmpdir,"ChunkVCF.chunk%d.intervals.list".format(chunkNum))
+      var chunkWriter = new PrintStream(chunkFile)
+      asScalaIterator(new XReadLines(intervals)).foreach( int => {
+        // check new chromosome or full chunk
+        if ( ( preserve && ! int.split(":")(0).equals(chromosome) ) || numLinesInChunk > numEntries ) {
+          chunkWriter.close()
+          val chunkSelect : SelectVariants = new SelectVariants
+          chunkSelect.variant = inVCF
+          chunkSelect.reference_sequence = ref
+          chunkSelect.memoryLimit = 2
+          chunkSelect.intervals :+= chunkFile
+          if ( extractSamples != null )
+            chunkSelect.sample_file :+= extractSamples
+          chunkSelect.out = swapExt(inVCF,".vcf",".chunk%d.vcf".format(chunkNum))
+          add(chunkSelect)
+          chunkNum += 1
+          numLinesInChunk = 0
+          chromosome = int.split(":")(0)
+          chunkFile = new File(tmpdir,"ChunkVCF.chunk%d.intervals.list".format(chunkNum))
+          chunkWriter = new PrintStream(chunkFile)
+        }
+        chunkWriter.printf("%s%n",int)
+        numLinesInChunk += 1
+      })
+      // last chunk
+      if ( numLinesInChunk > 0 ) {
+        // some work to do
+        val chunkSelect : SelectVariants = new SelectVariants
+        chunkSelect.variant = inVCF
+        chunkSelect.reference_sequence = ref
+        chunkSelect.memoryLimit = 2
+        chunkSelect.intervals :+= chunkFile
+        chunkWriter.close()
+        if ( extractSamples != null )
+          chunkSelect.sample_file :+= extractSamples
+        chunkSelect.out = swapExt(inVCF,".vcf",".chunk%d.vcf".format(chunkNum))
+        add(chunkSelect)
+      }
+    }
+  }
+}
\ No newline at end of file
diff --git a/public/gatk-queue-extensions-public/src/main/qscripts/org/broadinstitute/gatk/queue/qscripts/lib/Vcf2Table.scala b/public/gatk-queue-extensions-public/src/main/qscripts/org/broadinstitute/gatk/queue/qscripts/lib/Vcf2Table.scala
new file mode 100755
index 0000000..eb57d2e
--- /dev/null
+++ b/public/gatk-queue-extensions-public/src/main/qscripts/org/broadinstitute/gatk/queue/qscripts/lib/Vcf2Table.scala
@@ -0,0 +1,55 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.queue.qscripts.lib
+
+import org.broadinstitute.sting.commandline.Hidden
+import org.broadinstitute.sting.queue.extensions.gatk.{RodBind, VariantsToTable}
+import org.broadinstitute.sting.queue.QScript
+import collection.JavaConversions._
+
+class Vcf2Table extends QScript {
+  @Argument(shortName="vcf",doc="VCF file",required=true) var vcf : File = _
+  @Argument(shortName="f",doc="Info fields to extract",required=false) var fields : java.util.List[String] = new java.util.ArrayList[String]
+  @Argument(shortName="o",doc="Output file",required=true) var output : File = _
+  @Argument(shortName="useFilters",doc="Use filtered sites?",required=false) var useFilters : Boolean = false
+  @Argument(shortName="r",doc="Reference file") var ref : File = _
+  @Argument(shortName="i",doc="Intervals",required=false) var ints : java.util.List[File] = new java.util.ArrayList[File]
+  @Argument(shortName="g",doc="gatk jar",required=true) var gatk: File = _
+
+
+  def script = {
+    var vcf2table : VariantsToTable = new VariantsToTable
+    vcf2table.rodBind :+= new RodBind("variant","vcf",vcf)
+    vcf2table.reference_sequence = ref
+    vcf2table.intervals = ints.toList
+    vcf2table.raw = useFilters
+    vcf2table.out = output
+    vcf2table.F = fields.toList
+    vcf2table.jarFile = gatk
+    add(vcf2table)
+
+  }
+}
\ No newline at end of file
diff --git a/public/gatk-queue-extensions-public/src/main/qscripts/org/broadinstitute/gatk/queue/qscripts/lib/VcfToPed.scala b/public/gatk-queue-extensions-public/src/main/qscripts/org/broadinstitute/gatk/queue/qscripts/lib/VcfToPed.scala
new file mode 100644
index 0000000..962d495
--- /dev/null
+++ b/public/gatk-queue-extensions-public/src/main/qscripts/org/broadinstitute/gatk/queue/qscripts/lib/VcfToPed.scala
@@ -0,0 +1,225 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.queue.qscripts.lib
+
+import org.broadinstitute.gatk.queue.QScript
+import org.broadinstitute.gatk.utils.commandline.Input
+import org.broadinstitute.gatk.queue.library.ipf.vcf.VCFExtractIntervals
+import org.broadinstitute.gatk.utils.text.XReadLines
+import collection.JavaConversions._
+import java.io._
+import org.broadinstitute.gatk.queue.extensions.gatk.{SelectVariants, VariantsToPed}
+
+/**
+ * Created by IntelliJ IDEA.
+ * User: chartl
+ * Date: 1/31/12
+ * Time: 10:46 PM
+ * To change this template use File | Settings | File Templates.
+ */
+
+class VcfToPed extends QScript {
+
+  @Input(shortName = "V", fullName="Variants", required=true,doc="VCF to convert to ped")
+  var variants : File = _
+
+  @Output(shortName = "B", fullName="Bed",required=true,doc="Name of the ped output file (fam and bim will use the root of this file)")
+  var bed : File = _
+
+  @Input(shortName = "M", fullName="Meta",required=true,doc="The sample metadata file, can be a .fam or [NAME]\\tkey1=val1;key2=val2")
+  var meta : File = _
+
+  @Input(shortName = "Int", fullName="Intervals",required=false,doc="Intervals. If not specified script will produce them and exit.")
+  var intervals : File = _
+
+  @Argument(shortName="R",fullName="Ref",required=false,doc="Reference file")
+  var ref : File = new File("/humgen/1kg/reference/human_g1k_v37.fasta")
+
+  @Argument(shortName="D",fullName="dbsnp",required=false,doc="dbsnp file")
+  var dbsnp : File = new File("/humgen/gsa-hpprojects/GATK/data/dbsnp_129_b37.vcf")
+
+  @Argument(shortName="sf",fullName="sampleFile",required=false,doc="sample file")
+  var samFile : File = _
+
+  val tmpdir : File = System.getProperty("java.io.tmpdir")
+
+  def script = {
+    if ( intervals == null ) {
+      val ivals : File = swapExt(variants,".vcf",".intervals.list")
+      val extract : VCFExtractIntervals = new VCFExtractIntervals(variants,ivals,false)
+      add(extract)
+    } else {
+      val IS_GZ : Boolean = variants.getName.endsWith(".vcf.gz")
+      var iXRL = new XReadLines(intervals)
+      var chunk = 1;
+      var subListFile : File = null
+      if ( IS_GZ )
+        subListFile = swapExt(tmpdir,variants,".vcf.gz",".chunk%d.list".format(chunk))
+      else
+        subListFile = swapExt(tmpdir,variants,".vcf",".chunk%d.list".format(chunk))
+      var subList = new PrintStream(subListFile)
+      var nL = 0;
+      var bedOuts : List[File] = Nil;
+      var bimOuts : List[File] = Nil
+      var lastFam : File = null;
+      while ( iXRL.hasNext ) {
+        subList.printf("%s%n",iXRL.next())
+        nL = nL + 1
+        if ( nL > 10000 ) {
+          val toPed : VariantsToPed = new VariantsToPed
+          toPed.memoryLimit = 2
+          toPed.reference_sequence = ref
+          toPed.intervals :+= subListFile
+          toPed.dbsnp = dbsnp
+          if ( samFile != null ) {
+            val base : String = bed.getName.stripSuffix(".bed")+"_%d".format(chunk)
+            val extract : SelectVariants = new SelectVariants
+            extract.reference_sequence = ref
+            extract.memoryLimit = 2
+            extract.intervals :+= subListFile
+            extract.variant = variants
+            extract.out = new File(tmpdir,base+"_extract%d.vcf".format(chunk))
+            extract.sample_file :+= samFile
+            add(extract)
+            toPed.variant = extract.out
+          } else {
+            toPed.variant = variants
+          }
+          toPed.metaData = meta
+          val base : String = bed.getName.stripSuffix(".bed")+"_%d".format(chunk)
+          val tBed = new File(tmpdir,base+".bed")
+          val bim = new File(tmpdir,base+".bim")
+          val fam = new File(tmpdir,base+".fam")
+          toPed.bed = tBed
+          toPed.bim = bim
+          toPed.fam = fam
+          add(toPed)
+          subList.close()
+          chunk = chunk + 1
+          if ( IS_GZ  )
+            subListFile = swapExt(tmpdir,variants,".vcf.gz",".chunk%d.list".format(chunk))
+          else
+            subListFile = swapExt(tmpdir,variants,".vcf",".chunk%d.list".format(chunk))
+          subList = new PrintStream(subListFile)
+          bedOuts :+= tBed
+          bimOuts :+= bim
+          lastFam = fam
+          nL = 0;
+        }
+      }
+
+      if ( nL > 0 ) {
+        val toPed : VariantsToPed = new VariantsToPed
+        toPed.reference_sequence = ref
+        toPed.intervals :+= new File(subListFile)
+        toPed.dbsnp = dbsnp
+        if ( samFile != null ) {
+          val base : String = bed.getName.stripSuffix(".bed")+"_%d".format(chunk)
+          val extract : SelectVariants = new SelectVariants
+          extract.reference_sequence = ref
+          extract.memoryLimit = 2
+          extract.intervals :+= subListFile
+          extract.variant = variants
+          extract.out = new File(tmpdir,base+"_extract%d.vcf".format(chunk))
+          extract.sample_file :+= samFile
+          add(extract)
+          toPed.variant = extract.out
+        } else {
+          toPed.variant = variants
+        }
+        toPed.metaData = meta
+        toPed.memoryLimit = 2
+        val base : String = bed.getName.stripSuffix(".bed")+"_%d".format(chunk)
+        val tBed = new File(tmpdir,base+".bed")
+        val bim = new File(tmpdir,base+".bim")
+        val fam = new File(tmpdir,base+".fam")
+        toPed.bed = tBed
+        toPed.bim = bim
+        toPed.fam = fam
+        lastFam = fam
+        add(toPed)
+        subList.close()
+        bedOuts :+= tBed
+        bimOuts :+= bim
+      }
+
+      var gatherUP = new MyPedGather
+      gatherUP.binPed = bedOuts
+      gatherUP.bim = bimOuts
+      gatherUP.outPed = bed
+      gatherUP.outBim = swapExt(bed,".bed",".bim")
+
+      add(gatherUP)
+
+      class copyFam extends InProcessFunction {
+        @Input(doc="fam") var inFam = lastFam
+        @Output(doc="fam") var outFam = swapExt(bed,".bed",".fam")
+
+        def run = {
+          var stream = new PrintStream(outFam)
+          asScalaIterator(new XReadLines(inFam)).foreach( u => {
+            stream.printf("%s%n",u)
+          })
+          stream.close()
+        }
+      }
+
+      add(new copyFam)
+    }
+
+  }
+
+   class MyPedGather extends InProcessFunction {
+    @Input(doc="Peds to be merged") var binPed: List[File] = Nil
+    @Input(doc="Bims to be merged") var bim : List[File] = Nil
+    @Output(doc="The final Ped to write to") var outPed : File = _
+    @Output(doc="The final bim to write to") var outBim : File = _
+
+    def run : Unit = {
+      var stream : PrintStream = new PrintStream(outPed)
+      stream.write((List[Byte](0x6c.toByte,0x1b.toByte,0x1.toByte)).toArray)
+      binPed.map(u => new FileInputStream(u) ).foreach( u => {
+        u.skip(3)
+        var b = -1
+        do {
+          b = u.read()
+          stream.write(b.toByte)
+        } while ( b != -1 )
+      })
+      stream.close()
+
+     stream = new PrintStream(outBim)
+     bim.map(u => new XReadLines(u)).foreach( u => {
+       asScalaIterator(u).foreach( x => {
+         stream.printf("%s%n",x)
+       })
+     })
+
+      stream.close()
+    }
+  }
+
+}
\ No newline at end of file
diff --git a/public/gatk-queue-extensions-public/src/main/scala/org/broadinstitute/gatk/queue/extensions/cancer/MuTect.scala b/public/gatk-queue-extensions-public/src/main/scala/org/broadinstitute/gatk/queue/extensions/cancer/MuTect.scala
new file mode 100644
index 0000000..36031d9
--- /dev/null
+++ b/public/gatk-queue-extensions-public/src/main/scala/org/broadinstitute/gatk/queue/extensions/cancer/MuTect.scala
@@ -0,0 +1,420 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.queue.extensions.cancer
+
+import java.io.File
+import org.broadinstitute.gatk.utils.commandline.Argument
+import org.broadinstitute.gatk.utils.commandline.Gather
+import org.broadinstitute.gatk.utils.commandline.Input
+import org.broadinstitute.gatk.utils.commandline.Output
+import org.broadinstitute.gatk.queue.function.scattergather.ScatterGatherableFunction
+import org.broadinstitute.gatk.queue.extensions.gatk.{TaggedFile, VcfGatherFunction, LocusScatterFunction}
+
+class MuTect extends org.broadinstitute.gatk.queue.extensions.gatk.CommandLineGATK with ScatterGatherableFunction {
+  analysisName = "MuTect"
+  analysis_type = "MuTect"
+  scatterClass = classOf[LocusScatterFunction]
+
+  /** used for debugging, basically exit as soon as we get the reads */
+  @Argument(fullName="noop", shortName="", doc="used for debugging, basically exit as soon as we get the reads", required=false, exclusiveOf="", validation="")
+  var noop: Boolean = _
+
+  /** add many additional columns of statistics to the output file */
+  @Argument(fullName="enable_extended_output", shortName="", doc="add many additional columns of statistics to the output file", required=false, exclusiveOf="", validation="")
+  var enable_extended_output: Boolean = _
+
+  /** used when running the caller on a normal (as if it were a tumor) to detect artifacts */
+  @Argument(fullName="artifact_detection_mode", shortName="", doc="used when running the caller on a normal (as if it were a tumor) to detect artifacts", required=false, exclusiveOf="", validation="")
+  var artifact_detection_mode: Boolean = _
+
+  /** name to use for tumor in output files */
+  @Argument(fullName="tumor_sample_name", shortName="", doc="name to use for tumor in output files", required=false, exclusiveOf="", validation="")
+  var tumor_sample_name: String = _
+
+  /** if the tumor bam contains multiple samples, only use read groups with SM equal to this value */
+  @Argument(fullName="bam_tumor_sample_name", shortName="", doc="if the tumor bam contains multiple samples, only use read groups with SM equal to this value", required=false, exclusiveOf="", validation="")
+  var bam_tumor_sample_name: String = _
+
+  /** name to use for normal in output files */
+  @Argument(fullName="normal_sample_name", shortName="", doc="name to use for normal in output files", required=false, exclusiveOf="", validation="")
+  var normal_sample_name: String = _
+
+  /** force output for each site */
+  @Argument(fullName="force_output", shortName="", doc="force output for each site", required=false, exclusiveOf="", validation="")
+  var force_output: Boolean = _
+
+  /** force output for all alleles at each site */
+  @Argument(fullName="force_alleles", shortName="", doc="force output for all alleles at each site", required=false, exclusiveOf="", validation="")
+  var force_alleles: Boolean = _
+
+  /** only emit passing calls */
+  @Argument(fullName="only_passing_calls", shortName="", doc="only emit passing calls", required=false, exclusiveOf="", validation="")
+  var only_passing_calls: Boolean = _
+
+  /** Initial LOD threshold for calling tumor variant */
+  @Argument(fullName="initial_tumor_lod", shortName="", doc="Initial LOD threshold for calling tumor variant", required=false, exclusiveOf="", validation="")
+  var initial_tumor_lod: Option[Float] = None
+
+  /** Format string for initial_tumor_lod */
+  @Argument(fullName="initial_tumor_lodFormat", shortName="", doc="Format string for initial_tumor_lod", required=false, exclusiveOf="", validation="")
+  var initial_tumor_lodFormat: String = "%s"
+
+  /** LOD threshold for calling tumor variant */
+  @Argument(fullName="tumor_lod", shortName="", doc="LOD threshold for calling tumor variant", required=false, exclusiveOf="", validation="")
+  var tumor_lod: Option[Float] = None
+
+  /** Format string for tumor_lod */
+  @Argument(fullName="tumor_lodFormat", shortName="", doc="Format string for tumor_lod", required=false, exclusiveOf="", validation="")
+  var tumor_lodFormat: String = "%s"
+
+  /** estimate of fraction (0-1) of physical contamination with other unrelated samples */
+  @Argument(fullName="fraction_contamination", shortName="", doc="estimate of fraction (0-1) of physical contamination with other unrelated samples", required=false, exclusiveOf="", validation="")
+  var fraction_contamination: Option[Float] = None
+
+  /** Format string for fraction_contamination */
+  @Argument(fullName="fraction_contaminationFormat", shortName="", doc="Format string for fraction_contamination", required=false, exclusiveOf="", validation="")
+  var fraction_contaminationFormat: String = "%s"
+
+  /** minimum fraction of cells which are presumed to have a mutation, used to handle non-clonality and contamination */
+  @Argument(fullName="minimum_mutation_cell_fraction", shortName="", doc="minimum fraction of cells which are presumed to have a mutation, used to handle non-clonality and contamination", required=false, exclusiveOf="", validation="")
+  var minimum_mutation_cell_fraction: Option[Float] = None
+
+  /** Format string for minimum_mutation_cell_fraction */
+  @Argument(fullName="minimum_mutation_cell_fractionFormat", shortName="", doc="Format string for minimum_mutation_cell_fraction", required=false, exclusiveOf="", validation="")
+  var minimum_mutation_cell_fractionFormat: String = "%s"
+
+  /** LOD threshold for calling normal non-germline */
+  @Argument(fullName="normal_lod", shortName="", doc="LOD threshold for calling normal non-germline", required=false, exclusiveOf="", validation="")
+  var normal_lod: Option[Float] = None
+
+  /** Format string for normal_lod */
+  @Argument(fullName="normal_lodFormat", shortName="", doc="Format string for normal_lod", required=false, exclusiveOf="", validation="")
+  var normal_lodFormat: String = "%s"
+
+  /** LOD threshold for calling normal non-variant */
+  @Argument(fullName="normal_artifact_lod", shortName="", doc="LOD threshold for calling normal non-variant", required=false, exclusiveOf="", validation="")
+  var normal_artifact_lod: Option[Float] = None
+
+  /** Format string for normal_artifact_lod */
+  @Argument(fullName="normal_artifact_lodFormat", shortName="", doc="Format string for normal_artifact_lod", required=false, exclusiveOf="", validation="")
+  var normal_artifact_lodFormat: String = "%s"
+
+  /** LOD threshold for calling strand bias */
+  @Argument(fullName="strand_artifact_lod", shortName="", doc="LOD threshold for calling strand bias", required=false, exclusiveOf="", validation="")
+  var strand_artifact_lod: Option[Float] = None
+
+  /** Format string for strand_artifact_lod */
+  @Argument(fullName="strand_artifact_lodFormat", shortName="", doc="Format string for strand_artifact_lod", required=false, exclusiveOf="", validation="")
+  var strand_artifact_lodFormat: String = "%s"
+
+  /** power threshold for calling strand bias */
+  @Argument(fullName="strand_artifact_power_threshold", shortName="", doc="power threshold for calling strand bias", required=false, exclusiveOf="", validation="")
+  var strand_artifact_power_threshold: Option[Float] = None
+
+  /** Format string for strand_artifact_power_threshold */
+  @Argument(fullName="strand_artifact_power_thresholdFormat", shortName="", doc="Format string for strand_artifact_power_threshold", required=false, exclusiveOf="", validation="")
+  var strand_artifact_power_thresholdFormat: String = "%s"
+
+  /** LOD threshold for calling normal non-variant at dbsnp sites */
+  @Argument(fullName="dbsnp_normal_lod", shortName="", doc="LOD threshold for calling normal non-variant at dbsnp sites", required=false, exclusiveOf="", validation="")
+  var dbsnp_normal_lod: Option[Float] = None
+
+  /** Format string for dbsnp_normal_lod */
+  @Argument(fullName="dbsnp_normal_lodFormat", shortName="", doc="Format string for dbsnp_normal_lod", required=false, exclusiveOf="", validation="")
+  var dbsnp_normal_lodFormat: String = "%s"
+
+  /** Power threshold for normal to determine germline vs variant */
+  @Argument(fullName="somatic_classification_normal_power_threshold", shortName="", doc="Power threshold for normal to determine germline vs variant", required=false, exclusiveOf="", validation="")
+  var somatic_classification_normal_power_threshold: Option[Float] = None
+
+  /** Format string for somatic_classification_normal_power_threshold */
+  @Argument(fullName="somatic_classification_normal_power_thresholdFormat", shortName="", doc="Format string for somatic_classification_normal_power_threshold", required=false, exclusiveOf="", validation="")
+  var somatic_classification_normal_power_thresholdFormat: String = "%s"
+
+  /** minimum allele fraction to be considered in normal, useful for normal sample contaminated with tumor */
+  @Argument(fullName="minimum_normal_allele_fraction", shortName="", doc="minimum allele fraction to be considered in normal, useful for normal sample contaminated with tumor", required=false, exclusiveOf="", validation="")
+  var minimum_normal_allele_fraction: Option[Float] = None
+
+  /** Format string for minimum_normal_allele_fraction */
+  @Argument(fullName="minimum_normal_allele_fractionFormat", shortName="", doc="Format string for minimum_normal_allele_fraction", required=false, exclusiveOf="", validation="")
+  var minimum_normal_allele_fractionFormat: String = "%s"
+
+  /** for computational efficiency, reject sites with allelic fraction below this threshold */
+  @Argument(fullName="tumor_f_pretest", shortName="", doc="for computational efficiency, reject sites with allelic fraction below this threshold", required=false, exclusiveOf="", validation="")
+  var tumor_f_pretest: Option[Float] = None
+
+  /** Format string for tumor_f_pretest */
+  @Argument(fullName="tumor_f_pretestFormat", shortName="", doc="Format string for tumor_f_pretest", required=false, exclusiveOf="", validation="")
+  var tumor_f_pretestFormat: String = "%s"
+
+  /** threshold for minimum base quality score */
+  @Argument(fullName="min_qscore", shortName="", doc="threshold for minimum base quality score", required=false, exclusiveOf="", validation="")
+  var min_qscore: Option[Int] = None
+
+  /** how many gapped events (ins/del) are allowed in proximity to this candidate */
+  @Argument(fullName="gap_events_threshold", shortName="", doc="how many gapped events (ins/del) are allowed in proximity to this candidate", required=false, exclusiveOf="", validation="")
+  var gap_events_threshold: Option[Int] = None
+
+  /** if this fraction or more of the bases in a read are soft/hard clipped, do not use this read for mutation calling */
+  @Argument(fullName="heavily_clipped_read_fraction", shortName="", doc="if this fraction or more of the bases in a read are soft/hard clipped, do not use this read for mutation calling", required=false, exclusiveOf="", validation="")
+  var heavily_clipped_read_fraction: Option[Float] = None
+
+  /** Format string for heavily_clipped_read_fraction */
+  @Argument(fullName="heavily_clipped_read_fractionFormat", shortName="", doc="Format string for heavily_clipped_read_fraction", required=false, exclusiveOf="", validation="")
+  var heavily_clipped_read_fractionFormat: String = "%s"
+
+  /** pvalue threshold for fishers exact test of clipping bias in mutant reads vs ref reads */
+  @Argument(fullName="clipping_bias_pvalue_threshold", shortName="", doc="pvalue threshold for fishers exact test of clipping bias in mutant reads vs ref reads", required=false, exclusiveOf="", validation="")
+  var clipping_bias_pvalue_threshold: Option[Float] = None
+
+  /** Format string for clipping_bias_pvalue_threshold */
+  @Argument(fullName="clipping_bias_pvalue_thresholdFormat", shortName="", doc="Format string for clipping_bias_pvalue_threshold", required=false, exclusiveOf="", validation="")
+  var clipping_bias_pvalue_thresholdFormat: String = "%s"
+
+  /** threshold for determining if there is relatedness between the alt and ref allele read piles */
+  @Argument(fullName="fraction_mapq0_threshold", shortName="", doc="threshold for determining if there is relatedness between the alt and ref allele read piles", required=false, exclusiveOf="", validation="")
+  var fraction_mapq0_threshold: Option[Float] = None
+
+  /** Format string for fraction_mapq0_threshold */
+  @Argument(fullName="fraction_mapq0_thresholdFormat", shortName="", doc="Format string for fraction_mapq0_threshold", required=false, exclusiveOf="", validation="")
+  var fraction_mapq0_thresholdFormat: String = "%s"
+
+  /** threshold for clustered read position artifact median */
+  @Argument(fullName="pir_median_threshold", shortName="", doc="threshold for clustered read position artifact median", required=false, exclusiveOf="", validation="")
+  var pir_median_threshold: Option[Double] = None
+
+  /** Format string for pir_median_threshold */
+  @Argument(fullName="pir_median_thresholdFormat", shortName="", doc="Format string for pir_median_threshold", required=false, exclusiveOf="", validation="")
+  var pir_median_thresholdFormat: String = "%s"
+
+  /** threshold for clustered read position artifact MAD */
+  @Argument(fullName="pir_mad_threshold", shortName="", doc="threshold for clustered read position artifact MAD", required=false, exclusiveOf="", validation="")
+  var pir_mad_threshold: Option[Double] = None
+
+  /** Format string for pir_mad_threshold */
+  @Argument(fullName="pir_mad_thresholdFormat", shortName="", doc="Format string for pir_mad_threshold", required=false, exclusiveOf="", validation="")
+  var pir_mad_thresholdFormat: String = "%s"
+
+  /** required minimum value for tumor alt allele maximum mapping quality score */
+  @Argument(fullName="required_maximum_alt_allele_mapping_quality_score", shortName="", doc="required minimum value for tumor alt allele maximum mapping quality score", required=false, exclusiveOf="", validation="")
+  var required_maximum_alt_allele_mapping_quality_score: Option[Int] = None
+
+  /** threshold for maximum alternate allele counts in normal */
+  @Argument(fullName="max_alt_alleles_in_normal_count", shortName="", doc="threshold for maximum alternate allele counts in normal", required=false, exclusiveOf="", validation="")
+  var max_alt_alleles_in_normal_count: Option[Int] = None
+
+  /** threshold for maximum alternate allele quality score sum in normal */
+  @Argument(fullName="max_alt_alleles_in_normal_qscore_sum", shortName="", doc="threshold for maximum alternate allele quality score sum in normal", required=false, exclusiveOf="", validation="")
+  var max_alt_alleles_in_normal_qscore_sum: Option[Int] = None
+
+  /** threshold for maximum alternate allele fraction in normal */
+  @Argument(fullName="max_alt_allele_in_normal_fraction", shortName="", doc="threshold for maximum alternate allele fraction in normal", required=false, exclusiveOf="", validation="")
+  var max_alt_allele_in_normal_fraction: Option[Double] = None
+
+  /** Format string for max_alt_allele_in_normal_fraction */
+  @Argument(fullName="max_alt_allele_in_normal_fractionFormat", shortName="", doc="Format string for max_alt_allele_in_normal_fraction", required=false, exclusiveOf="", validation="")
+  var max_alt_allele_in_normal_fractionFormat: String = "%s"
+
+  /** Phred scale quality score constant to use in power calculations */
+  @Argument(fullName="power_constant_qscore", shortName="", doc="Phred scale quality score constant to use in power calculations", required=false, exclusiveOf="", validation="")
+  var power_constant_qscore: Option[Int] = None
+
+  /** Absolute Copy Number Data, as defined by Absolute, to use in power calculations */
+  @Argument(fullName="absolute_copy_number_data", shortName="", doc="Absolute Copy Number Data, as defined by Absolute, to use in power calculations", required=false, exclusiveOf="", validation="")
+  var absolute_copy_number_data: File = _
+
+  /** Allelic fraction constant to use in power calculations */
+  @Argument(fullName="power_constant_af", shortName="", doc="Allelic fraction constant to use in power calculations", required=false, exclusiveOf="", validation="")
+  var power_constant_af: Option[Double] = None
+
+  /** Format string for power_constant_af */
+  @Argument(fullName="power_constant_afFormat", shortName="", doc="Format string for power_constant_af", required=false, exclusiveOf="", validation="")
+  var power_constant_afFormat: String = "%s"
+
+  /** Call-stats output */
+  @Output(fullName="out", shortName="o", doc="Call-stats output", required=false, exclusiveOf="", validation="")
+  @Gather(classOf[org.broadinstitute.gatk.queue.function.scattergather.SimpleTextGatherFunction])
+  var out: File = _
+
+  /**
+   * Short name of out
+   * @return Short name of out
+   */
+  def o = this.out
+
+  /**
+   * Short name of out
+   * @param value Short name of out
+   */
+  def o_=(value: File) { this.out = value }
+
+  /** VCF output of mutation candidates */
+  @Output(fullName="vcf", shortName="vcf", doc="VCF output of mutation candidates", required=false, exclusiveOf="", validation="")
+  @Gather(classOf[VcfGatherFunction])
+  var vcf: File = _
+
+  /** Automatically generated index for vcf */
+  @Output(fullName="vcfIndex", shortName="", doc="Automatically generated index for vcf", required=false, exclusiveOf="", validation="")
+  @Gather(enabled=false)
+  private var vcfIndex: File = _
+
+  /** VCF file of DBSNP information */
+  @Input(fullName="dbsnp", shortName="dbsnp", doc="VCF file of DBSNP information", required=false, exclusiveOf="", validation="")
+  var dbsnp: Seq[File] = Nil
+
+  /** Dependencies on any indexes of dbsnp */
+  @Input(fullName="dbsnpIndexes", shortName="", doc="Dependencies on any indexes of dbsnp", required=false, exclusiveOf="", validation="")
+  private var dbsnpIndexes: Seq[File] = Nil
+
+  /** VCF file of COSMIC sites */
+  @Input(fullName="cosmic", shortName="cosmic", doc="VCF file of COSMIC sites", required=false, exclusiveOf="", validation="")
+  var cosmic: Seq[File] = Nil
+
+  /** Dependencies on any indexes of cosmic */
+  @Input(fullName="cosmicIndexes", shortName="", doc="Dependencies on any indexes of cosmic", required=false, exclusiveOf="", validation="")
+  private var cosmicIndexes: Seq[File] = Nil
+
+  /** VCF file of sites observed in normal */
+  @Input(fullName="normal_panel", shortName="normal_panel", doc="VCF file of sites observed in normal", required=false, exclusiveOf="", validation="")
+  var normal_panel: Seq[File] = Nil
+
+  /** Dependencies on any indexes of normal_panel */
+  @Input(fullName="normal_panelIndexes", shortName="", doc="Dependencies on any indexes of normal_panel", required=false, exclusiveOf="", validation="")
+  private var normal_panelIndexes: Seq[File] = Nil
+
+  /** write out coverage in WIGGLE format to this file */
+  @Output(fullName="coverage_file", shortName="cov", doc="write out coverage in WIGGLE format to this file", required=false, exclusiveOf="", validation="")
+  @Gather(classOf[org.broadinstitute.gatk.queue.function.scattergather.SimpleTextGatherFunction])
+  var coverage_file: File = _
+
+  /**
+   * Short name of coverage_file
+   * @return Short name of coverage_file
+   */
+  def cov = this.coverage_file
+
+  /**
+   * Short name of coverage_file
+   * @param value Short name of coverage_file
+   */
+  def cov_=(value: File) { this.coverage_file = value }
+
+  /** write out 20x of Q20 coverage in WIGGLE format to this file */
+  @Output(fullName="coverage_20_q20_file", shortName="cov_q20", doc="write out 20x of Q20 coverage in WIGGLE format to this file", required=false, exclusiveOf="", validation="")
+  @Gather(classOf[org.broadinstitute.gatk.queue.function.scattergather.SimpleTextGatherFunction])
+  var coverage_20_q20_file: File = _
+
+  /**
+   * Short name of coverage_20_q20_file
+   * @return Short name of coverage_20_q20_file
+   */
+  def cov_q20 = this.coverage_20_q20_file
+
+  /**
+   * Short name of coverage_20_q20_file
+   * @param value Short name of coverage_20_q20_file
+   */
+  def cov_q20_=(value: File) { this.coverage_20_q20_file = value }
+
+  /** write out power in WIGGLE format to this file */
+  @Output(fullName="power_file", shortName="pow", doc="write out power in WIGGLE format to this file", required=false, exclusiveOf="", validation="")
+  @Gather(classOf[org.broadinstitute.gatk.queue.function.scattergather.SimpleTextGatherFunction])
+  var power_file: File = _
+
+  /**
+   * Short name of power_file
+   * @return Short name of power_file
+   */
+  def pow = this.power_file
+
+  /**
+   * Short name of power_file
+   * @param value Short name of power_file
+   */
+  def pow_=(value: File) { this.power_file = value }
+
+  /** write out tumor read depth in WIGGLE format to this file */
+  @Output(fullName="tumor_depth_file", shortName="tdf", doc="write out tumor read depth in WIGGLE format to this file", required=false, exclusiveOf="", validation="")
+  @Gather(classOf[org.broadinstitute.gatk.queue.function.scattergather.SimpleTextGatherFunction])
+  var tumor_depth_file: File = _
+
+  /**
+   * Short name of tumor_depth_file
+   * @return Short name of tumor_depth_file
+   */
+  def tdf = this.tumor_depth_file
+
+  /**
+   * Short name of tumor_depth_file
+   * @param value Short name of tumor_depth_file
+   */
+  def tdf_=(value: File) { this.tumor_depth_file = value }
+
+  /** write out normal read depth in WIGGLE format to this file */
+  @Output(fullName="normal_depth_file", shortName="ndf", doc="write out normal read depth in WIGGLE format to this file", required=false, exclusiveOf="", validation="")
+  @Gather(classOf[org.broadinstitute.gatk.queue.function.scattergather.SimpleTextGatherFunction])
+  var normal_depth_file: File = _
+
+  /**
+   * Short name of normal_depth_file
+   * @return Short name of normal_depth_file
+   */
+  def ndf = this.normal_depth_file
+
+  /**
+   * Short name of normal_depth_file
+   * @param value Short name of normal_depth_file
+   */
+  def ndf_=(value: File) { this.normal_depth_file = value }
+
+  /** if a read has mismatching number of bases and base qualities, filter out the read instead of blowing up. */
+  @Argument(fullName="filter_mismatching_base_and_quals", shortName="filterMBQ", doc="if a read has mismatching number of bases and base qualities, filter out the read instead of blowing up.", required=false, exclusiveOf="", validation="")
+  var filter_mismatching_base_and_quals: Boolean = _
+
+  /**
+   * Short name of filter_mismatching_base_and_quals
+   * @return Short name of filter_mismatching_base_and_quals
+   */
+  def filterMBQ = this.filter_mismatching_base_and_quals
+
+  /**
+   * Short name of filter_mismatching_base_and_quals
+   * @param value Short name of filter_mismatching_base_and_quals
+   */
+  def filterMBQ_=(value: Boolean) { this.filter_mismatching_base_and_quals = value }
+
+  override def freezeFieldValues() {
+    super.freezeFieldValues()
+    if (vcf != null && !org.broadinstitute.gatk.utils.io.IOUtils.isSpecialFile(vcf))
+      if (!org.broadinstitute.gatk.engine.io.stubs.VCFWriterArgumentTypeDescriptor.isCompressed(vcf.getPath))
+        vcfIndex = new File(vcf.getPath + ".idx")
+    dbsnpIndexes ++= dbsnp.filter(orig => orig != null).map(orig => new File(orig.getPath + ".idx"))
+    cosmicIndexes ++= cosmic.filter(orig => orig != null).map(orig => new File(orig.getPath + ".idx"))
+    normal_panelIndexes ++= normal_panel.filter(orig => orig != null).map(orig => new File(orig.getPath + ".idx"))
+  }
+
+  override def commandLine = super.commandLine + conditional(noop, "--noop", escape=true, format="%s") + conditional(enable_extended_output, "--enable_extended_output", escape=true, format="%s") + conditional(artifact_detection_mode, "--artifact_detection_mode", escape=true, format="%s") + optional("--tumor_sample_name", tumor_sample_name, spaceSeparated=true, escape=true, format="%s") + optional("--bam_tumor_sample_name", bam_tumor_sample_name, spaceSeparated=true, escape=true, format=" [...]
+}
diff --git a/public/gatk-queue-extensions-public/src/main/scala/org/broadinstitute/gatk/queue/extensions/gatk/BamGatherFunction.scala b/public/gatk-queue-extensions-public/src/main/scala/org/broadinstitute/gatk/queue/extensions/gatk/BamGatherFunction.scala
new file mode 100644
index 0000000..5388510
--- /dev/null
+++ b/public/gatk-queue-extensions-public/src/main/scala/org/broadinstitute/gatk/queue/extensions/gatk/BamGatherFunction.scala
@@ -0,0 +1,57 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.queue.extensions.gatk
+
+import org.broadinstitute.gatk.queue.function.scattergather.GatherFunction
+import org.broadinstitute.gatk.queue.extensions.picard.MergeSamFiles
+import org.broadinstitute.gatk.queue.function.RetryMemoryLimit
+import java.io.File
+
+/**
+ * Merges BAM files using htsjdk.samtools.MergeSamFiles.
+ */
+class BamGatherFunction extends MergeSamFiles with GatherFunction with RetryMemoryLimit {
+  this.assumeSorted = Some(true)
+
+  override def freezeFieldValues() {
+    this.input = this.gatherParts
+    this.output = this.originalOutput
+    //Left to its own devices (ie, MergeSamFiles.freezeFieldValues), outputIndex
+    //will be in the gather directory.  Ensure that it actually matches this.output
+    if (output != null)
+      outputIndex = new File(output.getParentFile, output.getName.stripSuffix(".bam") + ".bai")
+    
+    val originalGATK = originalFunction.asInstanceOf[CommandLineGATK]
+
+    // Whatever the original function can handle, merging *should* do less.
+    this.memoryLimit = originalFunction.memoryLimit
+    this.compressionLevel = originalGATK.bam_compression
+    this.createIndex = Some(!originalGATK.disable_bam_indexing)
+    this.createMD5 = Some(originalGATK.generate_md5)
+
+    super.freezeFieldValues()
+  }
+}
diff --git a/public/gatk-queue-extensions-public/src/main/scala/org/broadinstitute/gatk/queue/extensions/gatk/CatVariantsGatherer.scala b/public/gatk-queue-extensions-public/src/main/scala/org/broadinstitute/gatk/queue/extensions/gatk/CatVariantsGatherer.scala
new file mode 100644
index 0000000..fd91e53
--- /dev/null
+++ b/public/gatk-queue-extensions-public/src/main/scala/org/broadinstitute/gatk/queue/extensions/gatk/CatVariantsGatherer.scala
@@ -0,0 +1,59 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.queue.extensions.gatk
+
+import org.broadinstitute.gatk.queue.function.RetryMemoryLimit
+import org.broadinstitute.gatk.queue.function.scattergather.GatherFunction
+
+
+/**
+ *
+ * Currently this is the default gather for VCFs.
+ * One can set a specific gatherer to use by adding @Gather before any output argument.
+ * For example (used to be part of UG):
+ *           @Gather(className = "org.broadinstitute.gatk.queue.extensions.gatk.CatVariantsGatherer")
+ *           @Output(doc="File to which variants should be written",required=true)
+ *           protected VariantContextWriter writer = null;
+ */
+class CatVariantsGatherer extends CatVariants with GatherFunction with RetryMemoryLimit{
+  this.assumeSorted = true
+
+  private lazy val originalGATK = this.originalFunction.asInstanceOf[CommandLineGATK]
+
+  override def freezeFieldValues() {
+    this.reference = originalGATK.reference_sequence
+    this.variant = this.gatherParts.zipWithIndex map { case (input, index) => new TaggedFile(input, "input"+index) }
+    this.outputFile = this.originalOutput
+    this.assumeSorted = true
+    this.variant_index_type = originalGATK.variant_index_type
+    this.variant_index_parameter = originalGATK.variant_index_parameter
+
+    super.freezeFieldValues()
+  }
+
+
+
+}
diff --git a/public/gatk-queue-extensions-public/src/main/scala/org/broadinstitute/gatk/queue/extensions/gatk/ContigScatterFunction.scala b/public/gatk-queue-extensions-public/src/main/scala/org/broadinstitute/gatk/queue/extensions/gatk/ContigScatterFunction.scala
new file mode 100644
index 0000000..7eff645
--- /dev/null
+++ b/public/gatk-queue-extensions-public/src/main/scala/org/broadinstitute/gatk/queue/extensions/gatk/ContigScatterFunction.scala
@@ -0,0 +1,50 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.queue.extensions.gatk
+
+import collection.JavaConversions._
+import org.broadinstitute.gatk.utils.interval.IntervalUtils
+import org.broadinstitute.gatk.queue.function.InProcessFunction
+
+/**
+ * Splits intervals by contig instead of evenly.
+ */
+class ContigScatterFunction extends GATKScatterFunction with InProcessFunction {
+  // Include unmapped reads by default.
+  this.includeUnmapped = true
+
+  override def scatterCount = if (intervalFilesExist) super.scatterCount min this.maxIntervals else super.scatterCount
+
+  protected override def maxIntervals = {
+    GATKScatterFunction.getGATKIntervals(this.originalGATK).contigs.size
+  }
+
+  def run() {
+    val gi = GATKScatterFunction.getGATKIntervals(this.originalGATK)
+    IntervalUtils.scatterContigIntervals(gi.samFileHeader, gi.locs, this.scatterOutputFiles)
+  }
+}
+
diff --git a/public/gatk-queue-extensions-public/src/main/scala/org/broadinstitute/gatk/queue/extensions/gatk/DistributedScatterFunction.scala b/public/gatk-queue-extensions-public/src/main/scala/org/broadinstitute/gatk/queue/extensions/gatk/DistributedScatterFunction.scala
new file mode 100644
index 0000000..f4ad993
--- /dev/null
+++ b/public/gatk-queue-extensions-public/src/main/scala/org/broadinstitute/gatk/queue/extensions/gatk/DistributedScatterFunction.scala
@@ -0,0 +1,52 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.queue.extensions.gatk
+
+import java.io.File
+import org.broadinstitute.gatk.queue.function.InProcessFunction
+import org.broadinstitute.gatk.queue.function.scattergather.{ScatterFunction, CloneFunction}
+import org.broadinstitute.gatk.utils.commandline.Output
+import util.Random
+
+/**
+ * An scatter function that uses the Distributed GATK.
+ */
+class DistributedScatterFunction extends ScatterFunction with InProcessFunction {
+  @Output(doc="processingTracker")
+  var processingTracker: File = _
+
+  override def init() {
+    this.processingTracker = new File(this.commandDirectory, "processingTracker.%8d".format(Random.nextInt(100000000)))
+  }
+
+  override def initCloneInputs(cloneFunction: CloneFunction, index: Int) {
+    cloneFunction.setFieldValue("processingTracker", this.processingTracker)
+  }
+
+  def run() {
+    /* doesn't actually need to run. */
+  }
+}
diff --git a/public/gatk-queue-extensions-public/src/main/scala/org/broadinstitute/gatk/queue/extensions/gatk/DoC/package.scala b/public/gatk-queue-extensions-public/src/main/scala/org/broadinstitute/gatk/queue/extensions/gatk/DoC/package.scala
new file mode 100644
index 0000000..fd54be6
--- /dev/null
+++ b/public/gatk-queue-extensions-public/src/main/scala/org/broadinstitute/gatk/queue/extensions/gatk/DoC/package.scala
@@ -0,0 +1,242 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.queue.extensions.gatk
+
+import java.io.{PrintStream, PrintWriter, File}
+import org.broadinstitute.gatk.queue.function.scattergather.ScatterGatherableFunction
+import org.broadinstitute.gatk.engine.downsampling.DownsampleType
+import org.broadinstitute.gatk.utils.commandline.{Input, Gather, Output}
+import org.broadinstitute.gatk.queue.function.{InProcessFunction, CommandLineFunction}
+import org.broadinstitute.gatk.tools.walkers.coverage.CoverageUtils
+import scala.collection.JavaConversions._
+import scala.Some
+import org.broadinstitute.gatk.utils.text.XReadLines
+import org.broadinstitute.gatk.queue.util.VCF_BAM_utilities
+
+// Minimal refactor from a package object to a file full of classes/objects
+// due to ongoing bugs with inner classes/objects in package objects:
+//   https://issues.scala-lang.org/browse/SI-4344
+//   https://issues.scala-lang.org/browse/SI-5954
+  class DoC(val bams: List[File], val DoC_output: File, val countType: CoverageUtils.CountPileupType, val MAX_DEPTH: Int, val minMappingQuality: Int, val minBaseQuality: Int, val scatterCountInput: Int, val START_BIN: Int, val NUM_BINS: Int, val minCoverageCalcs: Seq[Int], val sampleRenameMappingFile: Option[File] = None) extends CommandLineGATK with ScatterGatherableFunction {
+    val DOC_OUTPUT_SUFFIX: String = ".sample_interval_summary"
+
+    // So that the output files of this DoC run get deleted once they're used further downstream:
+    this.isIntermediate = true
+
+    this.analysis_type = "DepthOfCoverage"
+
+    this.input_file = bams
+    if (sampleRenameMappingFile.isDefined)
+      this.sample_rename_mapping_file = sampleRenameMappingFile.get
+
+    this.downsample_to_coverage = Some(MAX_DEPTH)
+    this.downsampling_type = DownsampleType.BY_SAMPLE
+
+    this.scatterCount = scatterCountInput
+    this.scatterClass = classOf[IntervalScatterFunction]
+
+    // HACK for DoC to work properly within Queue:
+    @Output
+    @Gather(classOf[org.broadinstitute.gatk.queue.function.scattergather.SimpleTextGatherFunction])
+    var intervalSampleOut: File = new File(DoC_output.getPath + DOC_OUTPUT_SUFFIX)
+
+    override def commandLine = super.commandLine +
+      " --omitDepthOutputAtEachBase" +
+      " --omitLocusTable" +
+      " --minMappingQuality " + minMappingQuality +
+      " --minBaseQuality " + minBaseQuality +
+      optional("--countType", countType, spaceSeparated=true, escape=true, format="%s") +
+      " --start " + START_BIN + " --stop " + MAX_DEPTH + " --nBins " + NUM_BINS +
+      (if (!minCoverageCalcs.isEmpty) minCoverageCalcs.map(cov => " --summaryCoverageThreshold " + cov).reduceLeft(_ + "" + _) else "") +
+      " --includeRefNSites" +
+      " -o " + DoC_output
+
+    override def shortDescription = "DoC: " + DoC_output
+  }
+
+  class DoCwithDepthOutputAtEachBase(bams: List[File], DoC_output: File, countType: CoverageUtils.CountPileupType, MAX_DEPTH: Int, minMappingQuality: Int, minBaseQuality: Int, scatterCountInput: Int, START_BIN: Int, NUM_BINS: Int, minCoverageCalcs: Seq[Int], sampleRenameMappingFile: Option[File] = None) extends DoC(bams, DoC_output, countType: CoverageUtils.CountPileupType, MAX_DEPTH: Int, minMappingQuality, minBaseQuality, scatterCountInput, START_BIN, NUM_BINS, minCoverageCalcs, sample [...]
+    // HACK for DoC to work properly within Queue:
+    @Output
+    @Gather(classOf[org.broadinstitute.gatk.queue.function.scattergather.SimpleTextGatherFunction])
+    var outPrefix = DoC_output
+
+    override def commandLine = super.commandLine.replaceAll(" --omitDepthOutputAtEachBase", "")
+  }
+
+  // A group has a list of samples and bam files to use for DoC
+  class Group(val name: String, val outputBase: File, val samples: List[String], val bams: List[File]) {
+    // getName() just includes the file name WITHOUT the path:
+    val groupOutputName = name + "." + outputBase.getName
+
+    // Comment this out, so that when jobs are scattered in DoC class below, they do not scatter into outputs at directories that don't exist!!! :
+    //def DoC_output = new File(outputBase.getParentFile(), groupOutputName)
+
+    def DoC_output = new File(groupOutputName)
+
+    override def toString(): String = String.format("[Group %s [%s] with samples %s against bams %s]", name, DoC_output, samples, bams)
+  }
+
+  class MergeGATKdepths(DoCsToCombine: List[File], outFile: String, columnSuffix: String, xhmmExec: File, rdPrecisionArg: Option[Int], outputTargetsBySamples: Boolean, sampleIDsMap: String = "", sampleIDsMapFromColumn: Int = 1, sampleIDsMapToColumn: Int = 2) extends CommandLineFunction {
+    @Input(doc = "")
+    var inputDoCfiles: List[File] = DoCsToCombine
+
+    @Output
+    val mergedDoC: File = new File(outFile)
+    var command: String =
+      xhmmExec + " --mergeGATKdepths" +
+        inputDoCfiles.map(input => " --GATKdepths " + input).reduceLeft(_ + "" + _) +
+        " --columnSuffix " + columnSuffix +
+        " -o " + mergedDoC
+    if (sampleIDsMap != "")
+      command += " --sampleIDmap " + sampleIDsMap + " --fromID " + sampleIDsMapFromColumn + " --toID " + sampleIDsMapToColumn
+    rdPrecisionArg match {
+      case Some(rdPrecision) => {
+        command += " --rdPrecision " + rdPrecision
+      }
+      case None => {}
+    }
+    if (outputTargetsBySamples)
+      command += " --outputTargetsBySamples"
+
+    def commandLine = command
+
+    override def description = "Combines DoC outputs for multiple samples (at same loci): " + command
+  }
+
+  class PrepareTargets(intervalsIn: List[File], outIntervals: String, val xhmmExec: File, val referenceFile: File) extends CommandLineFunction {
+    @Input(doc = "List of files containing targeted intervals to be prepared and merged")
+    var inIntervals: List[File] = intervalsIn
+
+    @Output(doc = "The merged intervals file to write to")
+    var out: File = new File(outIntervals)
+
+    var command: String =
+      xhmmExec + " --prepareTargets" +
+        " -F " + referenceFile +
+        inIntervals.map(intervFile => " --targets " + intervFile).reduceLeft(_ + "" + _) +
+        " --mergedTargets " + out
+
+    def commandLine = command
+
+    override def description = "Sort all target intervals, merge overlapping ones, and print the resulting interval list: " + command
+  }
+
+  class ParsedBamListWithOptionalSampleMappings(bamsFile: File) {
+    var bams = bamsFile
+
+    var allBams = List[File]()
+    var bamsWithoutSampleMapping = List[File]()
+    var userMappedSampleToBams = scala.collection.mutable.Map.empty[String, scala.collection.mutable.Set[File]]
+
+    var sampleToBams = scala.collection.mutable.Map.empty[String, scala.collection.mutable.Set[File]]
+  }
+
+object DoC {
+  def buildDoCgroups(samples: List[String], sampleToBams: scala.collection.mutable.Map[String, scala.collection.mutable.Set[File]], samplesPerJob: Int, outputBase: File): List[Group] = {
+    var l: List[Group] = Nil
+
+    var remaining = samples
+    var subsamples: List[String] = Nil
+    var count = 1
+
+    while (!remaining.isEmpty) {
+      val splitRes = (remaining splitAt samplesPerJob)
+      subsamples = splitRes._1
+      remaining = splitRes._2
+      l ::= new Group("group" + count, outputBase, subsamples, VCF_BAM_utilities.findBAMsForSamples(subsamples, sampleToBams))
+      count = count + 1
+    }
+
+    return l
+  }
+
+  def parseBamListWithOptionalSampleMappings(bamsFile: File): ParsedBamListWithOptionalSampleMappings = {
+    val r = new ParsedBamListWithOptionalSampleMappings(bamsFile)
+
+    val rows = asScalaIterator(new XReadLines(r.bams))
+
+    while (rows.hasNext) {
+      val line = rows.next
+      val splitLine = line.split("\\t")
+
+      if (splitLine.length < 1 || splitLine.length > 2)
+        throw new Exception("Invalid row in " + bamsFile.getPath + " : " + line)
+
+      val bam = splitLine(0)
+      val bamFile = new File(bam)
+      r.allBams ::= bamFile
+
+      if (splitLine.length == 2) {
+        val sampleName = splitLine(1)
+
+        if (r.userMappedSampleToBams.contains(sampleName))
+          throw new Exception("Cannot map multiple BAM files to the same sample name: " + sampleName)
+
+        r.userMappedSampleToBams += sampleName -> (scala.collection.mutable.Set.empty[File] + bamFile)
+      }
+      else {
+        r.bamsWithoutSampleMapping ::= bamFile
+      }
+    }
+
+    val autoMappedSampleToBams = VCF_BAM_utilities.getMapOfBAMsForSample(r.bamsWithoutSampleMapping)
+
+    val overlappingSamples = autoMappedSampleToBams.keys.toList.intersect(r.userMappedSampleToBams.keys.toList)
+    if (overlappingSamples.nonEmpty)
+      throw new Exception("Cannot have the same sample mapped to different BAMs: " + overlappingSamples.toString)
+
+    r.sampleToBams = autoMappedSampleToBams
+    r.userMappedSampleToBams.foreach{ keyVal => {r.sampleToBams += keyVal._1 -> keyVal._2} }
+
+
+    return r
+  }
+}
+
+  class ProcessBamListWithOptionalSampleMappings(parsedBamList: ParsedBamListWithOptionalSampleMappings, outputBase: String) extends InProcessFunction {
+    @Input(doc="")
+    var bams: File = parsedBamList.bams
+
+    @Output(doc="")
+    var bamsList: File = new File(outputBase + ".bam.list")
+
+    @Output(doc="")
+    var bamSampleMap: File = new File(outputBase + ".bam_sample.txt")
+
+    def run = {
+      val bamsListWriter = new PrintWriter(new PrintStream(bamsList))
+      for (bam <- parsedBamList.allBams) {
+        bamsListWriter.printf("%s%n", bam)
+      }
+      bamsListWriter.close
+
+      val bamSampleMapWriter = new PrintWriter(new PrintStream(bamSampleMap))
+      for ((sampleName, sampleNameBams) <- parsedBamList.userMappedSampleToBams) {
+        sampleNameBams.foreach { bam => bamSampleMapWriter.printf("%s\t%s%n", bam, sampleName) }
+      }
+      bamSampleMapWriter.close
+    }
+  }
diff --git a/public/gatk-queue-extensions-public/src/main/scala/org/broadinstitute/gatk/queue/extensions/gatk/GATKIntervals.scala b/public/gatk-queue-extensions-public/src/main/scala/org/broadinstitute/gatk/queue/extensions/gatk/GATKIntervals.scala
new file mode 100644
index 0000000..0e568b6
--- /dev/null
+++ b/public/gatk-queue-extensions-public/src/main/scala/org/broadinstitute/gatk/queue/extensions/gatk/GATKIntervals.scala
@@ -0,0 +1,98 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.queue.extensions.gatk
+
+import java.io.File
+import collection.JavaConversions._
+import org.broadinstitute.gatk.utils.interval.{IntervalSetRule, IntervalMergingRule, IntervalUtils}
+import org.broadinstitute.gatk.engine.datasources.reference.ReferenceDataSource
+import htsjdk.samtools.SAMFileHeader
+import org.broadinstitute.gatk.utils.GenomeLoc
+import org.broadinstitute.gatk.utils.commandline._
+import htsjdk.tribble.Feature
+
+case class GATKIntervals(reference: File, intervals: Seq[File], intervalsString: Seq[String],
+                         intervalSetRule: IntervalSetRule, intervalMergingRule: IntervalMergingRule, intervalPadding: Option[Int],
+                         excludeIntervals: Seq[File], excludeIntervalsString: Seq[String]) {
+
+  def this(gatk: CommandLineGATK) = this(
+    gatk.reference_sequence,
+    gatk.intervals, gatk.intervalsString,
+    gatk.interval_set_rule, gatk.interval_merging, gatk.interval_padding,
+    gatk.excludeIntervals, gatk.excludeIntervalsString)
+
+  private lazy val referenceDataSource = new ReferenceDataSource(reference)
+
+  lazy val samFileHeader = {
+    val header = new SAMFileHeader
+    header.setSequenceDictionary(referenceDataSource.getReference.getSequenceDictionary)
+    header
+  }
+
+  lazy val locs: java.util.List[GenomeLoc] = {
+    val includeIntervalBindings = this.intervals.map(GATKIntervals.createBinding(_, "intervals")) ++
+      this.intervalsString.map(GATKIntervals.createBinding(_, "intervalsString"))
+    val excludeIntervalBindings = this.excludeIntervals.map(GATKIntervals.createBinding(_, "excludeIntervals")) ++
+      this.excludeIntervalsString.map(GATKIntervals.createBinding(_, "excludeIntervalsString"))
+
+    IntervalUtils.parseIntervalBindings(
+      referenceDataSource,
+      includeIntervalBindings,
+      intervalSetRule, intervalMergingRule, intervalPadding.getOrElse(0),
+      excludeIntervalBindings).toList
+  }
+
+  lazy val contigs = locs.map(_.getContig).distinct.toSeq
+}
+
+object GATKIntervals {
+  def copyIntervalArguments(src: CommandLineGATK, dst: CommandLineGATK) {
+    dst.reference_sequence = src.reference_sequence
+    dst.intervals = src.intervals
+    dst.intervalsString = src.intervalsString
+    dst.interval_set_rule = src.interval_set_rule
+    dst.interval_merging = src.interval_merging
+    dst.interval_padding = src.interval_padding
+    dst.excludeIntervals = src.excludeIntervals
+    dst.excludeIntervalsString = src.excludeIntervalsString
+  }
+
+  private def createBinding(interval: File, argumentName: String): IntervalBinding[Feature] = {
+    val tags = interval match {
+      case taggedFile: TaggedFile => ParsingMethod.parseTags(argumentName, taggedFile.tag)
+      case file: File => new Tags
+    }
+    createBinding(interval.getAbsolutePath, argumentName, tags)
+  }
+
+  private def createBinding(interval: String, argumentName: String): IntervalBinding[Feature] = {
+    createBinding(interval, argumentName, new Tags)
+  }
+
+  private def createBinding(interval: String, argumentName: String, tags: Tags): IntervalBinding[Feature] = {
+    ArgumentTypeDescriptor.parseBinding(new ArgumentMatchStringValue(interval), classOf[Feature], classOf[IntervalBinding[Feature]], argumentName, tags, argumentName).asInstanceOf[IntervalBinding[Feature]]
+  }
+}
diff --git a/public/gatk-queue-extensions-public/src/main/scala/org/broadinstitute/gatk/queue/extensions/gatk/GATKScatterFunction.scala b/public/gatk-queue-extensions-public/src/main/scala/org/broadinstitute/gatk/queue/extensions/gatk/GATKScatterFunction.scala
new file mode 100644
index 0000000..01075c3
--- /dev/null
+++ b/public/gatk-queue-extensions-public/src/main/scala/org/broadinstitute/gatk/queue/extensions/gatk/GATKScatterFunction.scala
@@ -0,0 +1,111 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.queue.extensions.gatk
+
+import org.broadinstitute.gatk.utils.interval.IntervalUtils
+import java.io.File
+import org.broadinstitute.gatk.utils.io.IOUtils
+import org.broadinstitute.gatk.queue.function.scattergather.{CloneFunction, ScatterFunction}
+import org.broadinstitute.gatk.utils.commandline._
+
+trait GATKScatterFunction extends ScatterFunction {
+  /* The runtime field to set for specifying intervals. */
+  private final val intervalsField = "intervals"
+  private final val intervalsStringField = "intervalsString"
+  private final val excludeIntervalsField = "excludeIntervals"
+  private final val excludeIntervalsStringField = "excludeIntervalsString"
+  private final val intervalsSetRuleField = "interval_set_rule"
+  private final val intervalMergingField = "interval_merging"
+  private final val intervalPaddingField = "interval_padding"
+
+  @Output(doc="Scatter function outputs")
+  var scatterOutputFiles: Seq[File] = Nil
+
+  /** The original GATK function. */
+  protected var originalGATK: CommandLineGATK = _
+
+  /** Whether the last scatter job should also include any unmapped reads. */
+  protected var includeUnmapped: Boolean = _
+
+  override def init() {
+    this.originalGATK = this.originalFunction.asInstanceOf[CommandLineGATK]
+    // If intervals have been specified check if unmapped is included
+    if (this.originalGATK.intervals.size + this.originalGATK.intervalsString.size > 0)
+      this.includeUnmapped = this.originalGATK.intervalsString.exists(interval => IntervalUtils.isUnmapped(interval))
+  }
+
+  override def isScatterGatherable = {
+    this.originalGATK.reference_sequence != null
+  }
+
+  override def initCloneInputs(cloneFunction: CloneFunction, index: Int) {
+    cloneFunction.setFieldValue(this.intervalsField, Seq(new File("scatter.intervals")))
+    if (index == this.scatterCount && this.includeUnmapped)
+      cloneFunction.setFieldValue(this.intervalsStringField, Seq("unmapped"))
+    else
+      cloneFunction.setFieldValue(this.intervalsStringField, Seq.empty[String])
+
+    cloneFunction.setFieldValue(this.intervalsSetRuleField, null)
+    cloneFunction.setFieldValue(this.intervalMergingField, null)
+    cloneFunction.setFieldValue(this.intervalPaddingField, None)
+    cloneFunction.setFieldValue(this.excludeIntervalsField, Seq.empty[File])
+    cloneFunction.setFieldValue(this.excludeIntervalsStringField, Seq.empty[String])
+  }
+
+  override def bindCloneInputs(cloneFunction: CloneFunction, index: Int) {
+    val scatterPart = cloneFunction.getFieldValue(this.intervalsField)
+            .asInstanceOf[Seq[File]]
+            .map(file => IOUtils.absolute(cloneFunction.commandDirectory, file))
+    cloneFunction.setFieldValue(this.intervalsField, scatterPart)
+    this.scatterOutputFiles ++= scatterPart
+  }
+
+  /**
+   * @return true if all interval files exist.
+   */
+  protected def intervalFilesExist = {
+    !(this.originalGATK.intervals ++ this.originalGATK.excludeIntervals).exists(interval => !interval.exists())
+  }
+
+  /**
+   * @return the maximum number of intervals or this.scatterCount if the maximum can't be determined ahead of time.
+   */
+  protected def maxIntervals: Int
+}
+
+object GATKScatterFunction {
+  var gatkIntervalsCache = Seq.empty[GATKIntervals]
+
+  def getGATKIntervals(originalFunction: CommandLineGATK) = {
+    val gatkIntervals = new GATKIntervals(originalFunction)
+    gatkIntervalsCache.find(_ == gatkIntervals) match {
+      case Some(existingGatkIntervals) => existingGatkIntervals
+      case None =>
+        gatkIntervalsCache :+= gatkIntervals
+        gatkIntervals
+    }
+  }
+}
diff --git a/public/gatk-queue-extensions-public/src/main/scala/org/broadinstitute/gatk/queue/extensions/gatk/IntervalScatterFunction.scala b/public/gatk-queue-extensions-public/src/main/scala/org/broadinstitute/gatk/queue/extensions/gatk/IntervalScatterFunction.scala
new file mode 100644
index 0000000..99454d4
--- /dev/null
+++ b/public/gatk-queue-extensions-public/src/main/scala/org/broadinstitute/gatk/queue/extensions/gatk/IntervalScatterFunction.scala
@@ -0,0 +1,46 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.queue.extensions.gatk
+
+import collection.JavaConversions._
+import org.broadinstitute.gatk.utils.interval.IntervalUtils
+import org.broadinstitute.gatk.queue.function.InProcessFunction
+
+/**
+ * An interval scatter function.
+ */
+class IntervalScatterFunction extends GATKScatterFunction with InProcessFunction {
+  protected override def maxIntervals =
+    GATKScatterFunction.getGATKIntervals(this.originalGATK).locs.size
+
+  override def scatterCount = if (intervalFilesExist) super.scatterCount min this.maxIntervals else super.scatterCount
+
+  def run() {
+    val gi = GATKScatterFunction.getGATKIntervals(this.originalGATK)
+    val splits = IntervalUtils.splitFixedIntervals(gi.locs, this.scatterOutputFiles.size)
+    IntervalUtils.scatterFixedIntervals(gi.samFileHeader, splits, this.scatterOutputFiles)
+  }
+}
diff --git a/public/gatk-queue-extensions-public/src/main/scala/org/broadinstitute/gatk/queue/extensions/gatk/LocusScatterFunction.scala b/public/gatk-queue-extensions-public/src/main/scala/org/broadinstitute/gatk/queue/extensions/gatk/LocusScatterFunction.scala
new file mode 100644
index 0000000..5d71d35
--- /dev/null
+++ b/public/gatk-queue-extensions-public/src/main/scala/org/broadinstitute/gatk/queue/extensions/gatk/LocusScatterFunction.scala
@@ -0,0 +1,43 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.queue.extensions.gatk
+
+import collection.JavaConversions._
+import org.broadinstitute.gatk.utils.interval.IntervalUtils
+import org.broadinstitute.gatk.queue.function.InProcessFunction
+
+/**
+ * A scatter function that divides down to the locus level.
+ */
+class LocusScatterFunction extends GATKScatterFunction with InProcessFunction {
+  protected override def maxIntervals = scatterCount
+
+  def run() {
+    val gi = GATKScatterFunction.getGATKIntervals(this.originalGATK)
+    val splits = IntervalUtils.splitLocusIntervals(gi.locs, this.scatterOutputFiles.size)
+    IntervalUtils.scatterFixedIntervals(gi.samFileHeader, splits, this.scatterOutputFiles)
+  }
+}
\ No newline at end of file
diff --git a/public/gatk-queue-extensions-public/src/main/scala/org/broadinstitute/gatk/queue/extensions/gatk/ReadScatterFunction.scala b/public/gatk-queue-extensions-public/src/main/scala/org/broadinstitute/gatk/queue/extensions/gatk/ReadScatterFunction.scala
new file mode 100644
index 0000000..01e9eed
--- /dev/null
+++ b/public/gatk-queue-extensions-public/src/main/scala/org/broadinstitute/gatk/queue/extensions/gatk/ReadScatterFunction.scala
@@ -0,0 +1,57 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.queue.extensions.gatk
+
+/*
+ * Copyright (c) 2011, 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.
+ */
+
+/**
+ * Currently ReadScatterFunction only does ContigScattering, but it
+ * could in principle do something more aggressive.
+ */
+class ReadScatterFunction extends ContigScatterFunction { }
+
diff --git a/public/gatk-queue-extensions-public/src/main/scala/org/broadinstitute/gatk/queue/extensions/gatk/TaggedFile.scala b/public/gatk-queue-extensions-public/src/main/scala/org/broadinstitute/gatk/queue/extensions/gatk/TaggedFile.scala
new file mode 100644
index 0000000..e161209
--- /dev/null
+++ b/public/gatk-queue-extensions-public/src/main/scala/org/broadinstitute/gatk/queue/extensions/gatk/TaggedFile.scala
@@ -0,0 +1,58 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.queue.extensions.gatk
+
+import java.io.File
+import org.broadinstitute.gatk.utils.io.FileExtension
+import org.broadinstitute.gatk.queue.util.ShellUtils
+
+/**
+ * Used to provide tagged -I input_file arguments to the GATK.
+ */
+class TaggedFile(path: String, val tag: String) extends File(path) with FileExtension {
+  def this(file: File, tag: String) =
+    this(file.getPath, tag)
+  def withPath(path: String) = new TaggedFile(path, tag)
+}
+
+/**
+ * Used to provide -I input_file arguments to the GATK.
+ */
+object TaggedFile {
+  def apply(path: String, tag: String) = new TaggedFile(path, tag)
+  def apply(file: File, tag: String) = new TaggedFile(file, tag)
+
+  def formatCommandLineParameter(cmdLineParam: String, value: Any) = {
+    value match {
+      case taggedFile: TaggedFile if (taggedFile.tag != null) =>
+        "%s:%s".format(cmdLineParam, taggedFile.tag)
+      case file: File =>
+        cmdLineParam
+      case x =>
+        ""
+    }
+  }
+}
diff --git a/public/gatk-queue-extensions-public/src/main/scala/org/broadinstitute/gatk/queue/extensions/gatk/VcfGatherFunction.scala b/public/gatk-queue-extensions-public/src/main/scala/org/broadinstitute/gatk/queue/extensions/gatk/VcfGatherFunction.scala
new file mode 100644
index 0000000..68664c3
--- /dev/null
+++ b/public/gatk-queue-extensions-public/src/main/scala/org/broadinstitute/gatk/queue/extensions/gatk/VcfGatherFunction.scala
@@ -0,0 +1,53 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.queue.extensions.gatk
+
+import org.broadinstitute.gatk.queue.function.scattergather.GatherFunction
+import org.broadinstitute.gatk.queue.function.RetryMemoryLimit
+
+/**
+ * Merges a vcf text file.
+ */
+class VcfGatherFunction extends CombineVariants with GatherFunction with RetryMemoryLimit {
+  this.assumeIdenticalSamples = true
+  this.suppressCommandLineHeader = true
+
+  private lazy val originalGATK = this.originalFunction.asInstanceOf[CommandLineGATK]
+
+  override def freezeFieldValues() {
+    this.variant = this.gatherParts.zipWithIndex map { case (input, index) => new TaggedFile(input, "input"+index) }
+    this.out = this.originalOutput
+    GATKIntervals.copyIntervalArguments(this.originalGATK, this)
+
+    this.no_cmdline_in_header = originalGATK.no_cmdline_in_header
+    this.sites_only = originalGATK.sites_only
+
+    // ensure that the gather function receives the same unsafe parameter as the scattered function
+    this.unsafe = this.originalGATK.unsafe
+
+    super.freezeFieldValues()
+  }
+}
diff --git a/public/gatk-queue-extensions-public/src/main/scala/org/broadinstitute/gatk/queue/extensions/gatk/WriteFlankingIntervalsFunction.scala b/public/gatk-queue-extensions-public/src/main/scala/org/broadinstitute/gatk/queue/extensions/gatk/WriteFlankingIntervalsFunction.scala
new file mode 100644
index 0000000..290eff9
--- /dev/null
+++ b/public/gatk-queue-extensions-public/src/main/scala/org/broadinstitute/gatk/queue/extensions/gatk/WriteFlankingIntervalsFunction.scala
@@ -0,0 +1,49 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.queue.extensions.gatk
+
+import org.broadinstitute.gatk.queue.function.InProcessFunction
+import org.broadinstitute.gatk.utils.commandline.{Output, Argument, Input}
+import java.io.File
+import org.broadinstitute.gatk.utils.interval.IntervalUtils
+
+class WriteFlankingIntervalsFunction extends InProcessFunction {
+  @Input(doc="The reference sequence")
+  var reference : File = _
+
+  @Input(doc="The interval list to flank")
+  var inputIntervals : File = _
+
+  @Output(doc="The output intervals file to write to")
+  var outputIntervals: File = _
+
+  @Argument(doc="Number of base pair to flank the input intervals")
+  var flankSize : Int = _
+
+  def run() {
+    IntervalUtils.writeFlankingIntervals(reference, inputIntervals, outputIntervals, flankSize)
+  }
+}
diff --git a/public/gatk-queue-extensions-public/src/main/scala/org/broadinstitute/gatk/queue/extensions/picard/AddOrReplaceReadGroups.scala b/public/gatk-queue-extensions-public/src/main/scala/org/broadinstitute/gatk/queue/extensions/picard/AddOrReplaceReadGroups.scala
new file mode 100644
index 0000000..6b70d2f
--- /dev/null
+++ b/public/gatk-queue-extensions-public/src/main/scala/org/broadinstitute/gatk/queue/extensions/picard/AddOrReplaceReadGroups.scala
@@ -0,0 +1,90 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.queue.extensions.picard
+
+import org.broadinstitute.gatk.utils.commandline._
+
+import java.io.File
+
+/*
+ * Created by IntelliJ IDEA.
+ * User: carneiro
+ * Date: 6/22/11
+ * Time: 10:35 AM
+ */
+class AddOrReplaceReadGroups extends org.broadinstitute.gatk.queue.function.JavaCommandLineFunction with PicardBamFunction {
+  analysisName = "AddOrReplaceReadGroups"
+  javaMainClass = "picard.sam.AddOrReplaceReadGroups"
+
+  @Input(doc="The input SAM or BAM files to analyze.  Must be coordinate sorted.", shortName = "input", fullName = "input_bam_files", required = true)
+  var input: Seq[File] = Nil
+
+  @Output(doc="The output BAM file with the modified/added read groups", shortName = "output", fullName = "output_bam_file", required = true)
+  var output: File = _
+
+  @Output(doc="The output bam index", shortName = "out_index", fullName = "output_bam_index_file", required = false)
+  var outputIndex: File = _
+
+  @Argument(doc="Read group ID", shortName = "id", fullName = "read_group_id", required = true)
+  var RGID: String = _
+
+  @Argument(doc = "Read group library", shortName = "lb", fullName = "read_group_library", required = true)
+  var RGLB: String = _
+
+  @Argument(doc = "Read group platform (e.g. illumina, solid)", shortName = "pl", fullName ="read_group_platform", required=true)
+  var RGPL: String = _
+
+  @Argument(doc = "Read group platform unit (e.g. run barcode)", shortName = "pu", fullName = "read_group_platform_unit", required = true)
+  var RGPU: String = _
+
+  @Argument(doc = "Read group sample name", shortName = "sm", fullName = "read_group_sample_name", required = true)
+  var RGSM: String = _
+
+  @Argument(doc = "Read group center name", shortName = "cn", fullName = "read_group_center_name", required = false)
+  var RGCN: String = ""
+
+  @Argument(doc = "Read group description", shortName = "ds", fullName = "read_group_description", required = false)
+  var RGDS: String = ""
+
+  override def freezeFieldValues() {
+    super.freezeFieldValues()
+    if (outputIndex == null && output != null)
+      outputIndex = new File(output.getName.stripSuffix(".bam") + ".bai")
+  }
+
+
+  override def inputBams = input
+  override def outputBam = output
+  this.createIndex = Some(true)
+  override def commandLine = super.commandLine +
+                             required("RGID=" + RGID) +
+                             required("RGLB=" + RGLB) +
+                             required("RGPL=" + RGPL) +
+                             required("RGPU=" + RGPU) +
+                             required("RGSM=" + RGSM) +
+                             conditional(RGCN != null && !RGCN.isEmpty, "RGCN=" + RGCN) +
+                             conditional(RGDS != null && !RGDS.isEmpty, "RGDS=" + RGDS)
+}
\ No newline at end of file
diff --git a/public/gatk-queue-extensions-public/src/main/scala/org/broadinstitute/gatk/queue/extensions/picard/CalculateHsMetrics.scala b/public/gatk-queue-extensions-public/src/main/scala/org/broadinstitute/gatk/queue/extensions/picard/CalculateHsMetrics.scala
new file mode 100644
index 0000000..68c4ca7
--- /dev/null
+++ b/public/gatk-queue-extensions-public/src/main/scala/org/broadinstitute/gatk/queue/extensions/picard/CalculateHsMetrics.scala
@@ -0,0 +1,68 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.queue.extensions.picard
+
+import org.broadinstitute.gatk.utils.commandline.{Argument, Output, Input}
+import java.io.File
+import picard.analysis.MetricAccumulationLevel
+
+/**
+ * Created with IntelliJ IDEA.
+ * User: delangel
+ * Date: 10/9/12
+ * Time: 5:59 PM
+ * To change this template use File | Settings | File Templates.
+ */
+class CalculateHsMetrics extends org.broadinstitute.gatk.queue.function.JavaCommandLineFunction with PicardMetricsFunction {
+  analysisName = "CalculateHsMetrics"
+  javaMainClass = "picard.analysis.directed.CalculateHsMetrics"
+
+  @Input(doc="The input SAM or BAM files to analyze.  Must be coordinate sorted.", shortName = "input", fullName = "input_bam_files", required = true)
+  var input: Seq[File] = Nil
+
+  @Output(doc="The output file to write statistics to", shortName = "output", fullName = "output_file", required = true)
+  var output: File = _
+
+  @Argument(doc="Interval list with targets", shortName = "targets", fullName = "target_list", required = true)
+  var targets: File = _
+
+  @Argument(doc="Interval list with baits", shortName = "baits", fullName = "bait_list", required = true)
+  var baits: File = _
+
+  @Argument(doc="Reference file", shortName = "reference", fullName = "reference", required = true)
+  var reference: File = _
+
+  @Argument(doc="The level(s) at which to accumulate metrics. Possible values: {ALL_READS, SAMPLE, LIBRARY, READ_GROUP} This option may be specified 0 or more times.", shortName = "level", fullName = "metric_accumulation_level", required = false)
+  var level: Seq[picard.analysis.MetricAccumulationLevel] = Seq(MetricAccumulationLevel.SAMPLE)
+
+  override def inputBams = input
+  override def outputFile = output
+  override def commandLine = super.commandLine +
+    required("BAIT_INTERVALS=" + baits) +
+    required("TARGET_INTERVALS=" + targets) +
+    required("REFERENCE_SEQUENCE=" + reference) +
+    repeat("METRIC_ACCUMULATION_LEVEL=", level, spaceSeparated=false, escape=true, format="%s")
+}
diff --git a/public/gatk-queue-extensions-public/src/main/scala/org/broadinstitute/gatk/queue/extensions/picard/CollectGcBiasMetrics.scala b/public/gatk-queue-extensions-public/src/main/scala/org/broadinstitute/gatk/queue/extensions/picard/CollectGcBiasMetrics.scala
new file mode 100644
index 0000000..f0d2300
--- /dev/null
+++ b/public/gatk-queue-extensions-public/src/main/scala/org/broadinstitute/gatk/queue/extensions/picard/CollectGcBiasMetrics.scala
@@ -0,0 +1,57 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.queue.extensions.picard
+
+import org.broadinstitute.gatk.utils.commandline.{Argument, Output, Input}
+import java.io.File
+
+/**
+ * Created with IntelliJ IDEA.
+ * User: delangel
+ * Date: 10/10/12
+ * Time: 10:37 AM
+ * To change this template use File | Settings | File Templates.
+ */
+class CollectGcBiasMetrics extends org.broadinstitute.gatk.queue.function.JavaCommandLineFunction with PicardMetricsFunction {
+  analysisName = "CollectGcBiasMetrics"
+  javaMainClass = "picard.analysis.CollectGcBiasMetrics"
+
+  @Input(doc="The input SAM or BAM files to analyze.  Must be coordinate sorted.", shortName = "input", fullName = "input_bam_files", required = true)
+  var input: Seq[File] = Nil
+
+  @Output(doc="The output file to write statistics to", shortName = "output", fullName = "output_file", required = true)
+  var output: File = _
+
+  @Argument(doc="Reference file", shortName = "reference", fullName = "reference", required = true)
+  var reference: File = _
+
+  override def inputBams = input
+  override def outputFile = output
+  override def commandLine = super.commandLine +
+    required("SUMMARY_OUTPUT=" + output) +
+    required("CHART_OUTPUT=" + output+".pdf") +
+    required("REFERENCE_SEQUENCE=" + reference)
+}
diff --git a/public/gatk-queue-extensions-public/src/main/scala/org/broadinstitute/gatk/queue/extensions/picard/CollectMultipleMetrics.scala b/public/gatk-queue-extensions-public/src/main/scala/org/broadinstitute/gatk/queue/extensions/picard/CollectMultipleMetrics.scala
new file mode 100644
index 0000000..1507366
--- /dev/null
+++ b/public/gatk-queue-extensions-public/src/main/scala/org/broadinstitute/gatk/queue/extensions/picard/CollectMultipleMetrics.scala
@@ -0,0 +1,61 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.queue.extensions.picard
+
+import org.broadinstitute.gatk.utils.commandline.{Argument, Output, Input}
+import java.io.File
+
+/**
+ * Created with IntelliJ IDEA.
+ * User: delangel
+ * Date: 10/10/12
+ * Time: 10:37 AM
+ * To change this template use File | Settings | File Templates.
+ */
+class CollectMultipleMetrics extends org.broadinstitute.gatk.queue.function.JavaCommandLineFunction with PicardMetricsFunction{
+  analysisName = "CollectMultipleMetrics"
+  javaMainClass = "picard.analysis.CollectMultipleMetrics"
+
+  @Input(doc="The input SAM or BAM files to analyze.  Must be coordinate sorted.", shortName = "input", fullName = "input_bam_files", required = true)
+  var input: Seq[File] = Nil
+
+  @Output(doc="The output file to write statistics to", shortName = "output", fullName = "output_file", required = true)
+  var output: File = _
+
+  @Argument(doc="Reference file", shortName = "reference", fullName = "reference", required = true)
+  var reference: File = _
+
+  override def inputBams = input
+  override def outputFile = output
+  override def commandLine = super.commandLine +
+    required("REFERENCE_SEQUENCE=" + reference) +
+    required("ASSUME_SORTED=true") +
+    required("PROGRAM=QualityScoreDistribution") +
+    required("PROGRAM=MeanQualityByCycle") +
+    required("PROGRAM=CollectAlignmentSummaryMetrics" )
+
+
+}
diff --git a/public/gatk-queue-extensions-public/src/main/scala/org/broadinstitute/gatk/queue/extensions/picard/FastqToSam.scala b/public/gatk-queue-extensions-public/src/main/scala/org/broadinstitute/gatk/queue/extensions/picard/FastqToSam.scala
new file mode 100644
index 0000000..44e10af
--- /dev/null
+++ b/public/gatk-queue-extensions-public/src/main/scala/org/broadinstitute/gatk/queue/extensions/picard/FastqToSam.scala
@@ -0,0 +1,104 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.queue.extensions.picard
+
+/*
+* Copyright (c) 2012 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.
+*/
+
+import org.broadinstitute.gatk.utils.commandline._
+
+import java.io.File
+
+class FastqToSam extends org.broadinstitute.gatk.queue.function.JavaCommandLineFunction /*with PicardBamFunction*/ {
+  analysisName = "FastqToSam"
+  javaMainClass = "picard.sam.FastqToSam"
+
+  @Input(shortName = "fq1", fullName = "input_fq_file1", required = true, doc = "Input Fastq file to extract reads from (single-end fastq or, if paired, first end of the pair fastq)")
+  var fastq: File = _
+
+  @Input(shortName = "fq2", fullName = "input_fq_file2", required = false, doc = "Input Fastq file to extract reads from (if paired, second end of the pair fastq).")
+  var secondEndFastQ: File = _
+
+  @Output(shortName = "bam", fullName = "output_bam_file", required = true, doc = "Output bam file .")
+  var bam: File = _
+
+  @Argument(shortName = "SM", fullName = "SM", required = false, doc = "SM")
+  var SM: String = "SM"
+
+  @Argument(shortName = "LIB", fullName = "LIB", required = false, doc = "LIB")
+  var LIB: String = "LIB"
+
+  @Argument(shortName = "PU", fullName = "PU", required = false, doc = "PU")
+  var PU: String = "PU"
+
+  @Argument(shortName = "RG", fullName = "RG", required = false, doc = "RG")
+  var RG: String = "RG"
+
+  @Argument(shortName = "PL", fullName = "PL", required = false, doc = "PL")
+  var PL: String = "illumina"
+
+  @Argument(shortName = "CN", fullName = "CN", required = false, doc = "CN")
+  var CN: String = "CN"
+
+
+//  override def inputBams = Seq(fastq)
+//  override def outputBam = bam
+//  this.sortOrder = null
+  val createIndex:Boolean = true
+  override def commandLine = super.commandLine +
+    required("FASTQ=" + fastq) +
+    optional("FASTQ2=", secondEndFastQ, spaceSeparated=false) +
+    required("OUTPUT=" + bam) +
+    optional("READ_GROUP_NAME=", RG, spaceSeparated=false) +
+    required("SAMPLE_NAME=" + SM) +
+    optional("LIBRARY_NAME=", LIB, spaceSeparated=false) +
+    optional("PLATFORM_UNIT=", PU, spaceSeparated=false) +
+    optional("PLATFORM=", PL, spaceSeparated=false) +
+    optional("CREATE_INDEX=", createIndex, spaceSeparated=false) +
+    optional("SEQUENCING_CENTER=", CN, spaceSeparated=false)
+}
\ No newline at end of file
diff --git a/public/gatk-queue-extensions-public/src/main/scala/org/broadinstitute/gatk/queue/extensions/picard/MarkDuplicates.scala b/public/gatk-queue-extensions-public/src/main/scala/org/broadinstitute/gatk/queue/extensions/picard/MarkDuplicates.scala
new file mode 100644
index 0000000..66460b6
--- /dev/null
+++ b/public/gatk-queue-extensions-public/src/main/scala/org/broadinstitute/gatk/queue/extensions/picard/MarkDuplicates.scala
@@ -0,0 +1,79 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.queue.extensions.picard
+
+import org.broadinstitute.gatk.utils.commandline._
+
+import java.io.File
+
+/*
+ * Created by IntelliJ IDEA.
+ * User: carneiro
+ * Date: 6/22/11
+ * Time: 10:35 AM
+ */
+class MarkDuplicates extends org.broadinstitute.gatk.queue.function.JavaCommandLineFunction with PicardBamFunction {
+  analysisName = "MarkDuplicates"
+  javaMainClass = "picard.sam.MarkDuplicates"
+
+  @Input(doc="The input SAM or BAM files to analyze.  Must be coordinate sorted.", shortName = "input", fullName = "input_bam_files", required = true)
+  var input: Seq[File] = Nil
+
+  @Output(doc="The output file to write marked records to", shortName = "output", fullName = "output_bam_file", required = true)
+  var output: File = _
+
+  @Output(doc="The output bam index", shortName = "out_index", fullName = "output_bam_index_file", required = false)
+  var outputIndex: File = _
+
+  @Output(doc="File to write duplication metrics to", shortName = "out_metrics", fullName = "output_metrics_file", required = true)
+  var metrics: File = new File(output + ".metrics")
+
+  @Argument(doc="If true do not write duplicates to the output file instead of writing them with appropriate flags set.", shortName = "remdup", fullName = "remove_duplicates", required = false)
+  var REMOVE_DUPLICATES: Boolean = false
+
+  @Argument(doc = "Maximum number of file handles to keep open when spilling read ends to disk.  Set this number a little lower than the per-process maximum number of file that may be open.  This number can be found by executing the 'ulimit -n' command on a Unix system.", shortName = "max_file_handles", fullName ="max_file_handles_for_read_ends_maps", required=false)
+  var MAX_FILE_HANDLES_FOR_READ_ENDS_MAP: Int = -1;
+
+  @Argument(doc = "This number, plus the maximum RAM available to the JVM, determine the memory footprint used by some of the sorting collections.  If you are running out of memory, try reducing this number.", shortName = "sorting_ratio", fullName = "sorting_collection_size_ratio", required = false)
+  var SORTING_COLLECTION_SIZE_RATIO: Double = -1
+
+  override def freezeFieldValues() {
+    super.freezeFieldValues()
+    if (outputIndex == null && output != null)
+      outputIndex = new File(output.getName.stripSuffix(".bam") + ".bai")
+  }
+
+
+  override def inputBams = input
+  override def outputBam = output
+  this.sortOrder = null
+  this.createIndex = Some(true)
+  override def commandLine = super.commandLine +
+                             required("M=" + metrics) +
+                             conditional(REMOVE_DUPLICATES, "REMOVE_DUPLICATES=true") +
+                             conditional(MAX_FILE_HANDLES_FOR_READ_ENDS_MAP > 0, "MAX_FILE_HANDLES_FOR_READ_ENDS_MAP=" + MAX_FILE_HANDLES_FOR_READ_ENDS_MAP.toString) +
+                             conditional(SORTING_COLLECTION_SIZE_RATIO > 0, "SORTING_COLLECTION_SIZE_RATIO=" + SORTING_COLLECTION_SIZE_RATIO.toString)
+}
\ No newline at end of file
diff --git a/public/gatk-queue-extensions-public/src/main/scala/org/broadinstitute/gatk/queue/extensions/picard/MergeSamFiles.scala b/public/gatk-queue-extensions-public/src/main/scala/org/broadinstitute/gatk/queue/extensions/picard/MergeSamFiles.scala
new file mode 100644
index 0000000..1b25a8e
--- /dev/null
+++ b/public/gatk-queue-extensions-public/src/main/scala/org/broadinstitute/gatk/queue/extensions/picard/MergeSamFiles.scala
@@ -0,0 +1,74 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.queue.extensions.picard
+
+import org.broadinstitute.gatk.utils.commandline._
+
+import java.io.File
+
+/*
+ * Created by IntelliJ IDEA.
+ * User: carneiro
+ * Date: 6/22/11
+ * Time: 10:35 AM
+ */
+class MergeSamFiles extends org.broadinstitute.gatk.queue.function.JavaCommandLineFunction with PicardBamFunction {
+  analysisName = "MergeSamFiles"
+  javaMainClass = "picard.sam.MergeSamFiles"
+
+  @Input(doc="The input SAM or BAM files to analyze.  Must be coordinate sorted.", shortName = "input", fullName = "input_bam_files", required = true)
+  var input: Seq[File] = Nil
+
+  @Output(doc="The output merged BAM file", shortName = "output", fullName = "output_bam_file", required = true)
+  var output: File = _
+
+  @Output(doc="The output bam index", shortName = "out_index", fullName = "output_bam_index_file", required = false)
+  var outputIndex: File = _
+
+  @Argument(doc="Merge the seqeunce dictionaries Default value: false. This option can be set to 'null' to clear the default value.", shortName = "merge_dict", fullName = "merge_sequence_dictionaries", required = false)
+  var MERGE_SEQUENCE_DICTIONARIES: Boolean = false
+
+  @Argument(doc = "Option to enable a simple two-thread producer consumer version of the merge algorithm that uses one thread to read and merge the records from the input files and another thread to encode, compress and write to disk the output file. The threaded version uses about 20% more CPU and decreases runtime by ~20% when writing out a compressed BAM file. ", shortName = "thread", fullName ="use_threading", required=false)
+  var USE_THREADING: Boolean = false;
+
+  @Argument(doc = "Comments to include in the merged output file's header.", shortName = "com", fullName = "comments", required = false)
+  var COMMENT: String = ""
+
+  override def freezeFieldValues() {
+    super.freezeFieldValues()
+    if (outputIndex == null && output != null)
+      outputIndex = new File(output.getName.stripSuffix(".bam") + ".bai")
+  }
+
+
+  override def inputBams = input
+  override def outputBam = output
+  this.createIndex = Some(true)
+  override def commandLine = super.commandLine +
+                             conditional(MERGE_SEQUENCE_DICTIONARIES, "MERGE_SEQUENCE_DICTIONARIES=true") +
+                             conditional(USE_THREADING, "USE_THREADING=true") +
+                             conditional(COMMENT != null && !COMMENT.isEmpty, "COMMENT=" + COMMENT)
+}
\ No newline at end of file
diff --git a/public/gatk-queue-extensions-public/src/main/scala/org/broadinstitute/gatk/queue/extensions/picard/PicardBamFunction.scala b/public/gatk-queue-extensions-public/src/main/scala/org/broadinstitute/gatk/queue/extensions/picard/PicardBamFunction.scala
new file mode 100644
index 0000000..80a60c5
--- /dev/null
+++ b/public/gatk-queue-extensions-public/src/main/scala/org/broadinstitute/gatk/queue/extensions/picard/PicardBamFunction.scala
@@ -0,0 +1,63 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.queue.extensions.picard
+
+import java.io.File
+import org.broadinstitute.gatk.queue.function.JavaCommandLineFunction
+import htsjdk.samtools.ValidationStringency
+import htsjdk.samtools.SAMFileHeader.SortOrder
+
+/**
+ * Wraps a Picard function that operates on BAM files.
+ * See http://picard.sourceforge.net/ for more info.
+ *
+ * Since the various BAM utilities take slightly different arguments
+ * some values are optional.
+ */
+trait PicardBamFunction extends JavaCommandLineFunction {
+  var validationStringency = ValidationStringency.SILENT
+  var sortOrder = SortOrder.coordinate
+  var compressionLevel: Option[Int] = None
+  var createIndex: Option[Boolean] = None
+  var createMD5: Option[Boolean] = None
+  var maxRecordsInRam: Option[Int] = None
+  var assumeSorted: Option[Boolean] = None
+
+  protected def inputBams: Seq[File]
+  protected def outputBam: File
+
+  abstract override def commandLine = super.commandLine +
+    repeat("INPUT=", inputBams, spaceSeparated=false) +
+    required("TMP_DIR=" + jobTempDir) +
+    optional("OUTPUT=", outputBam, spaceSeparated=false) +
+    optional("COMPRESSION_LEVEL=", compressionLevel, spaceSeparated=false) +
+    optional("VALIDATION_STRINGENCY=", validationStringency, spaceSeparated=false) +
+    optional("SO=", sortOrder, spaceSeparated=false) +
+    optional("MAX_RECORDS_IN_RAM=", maxRecordsInRam, spaceSeparated=false) +
+    optional("ASSUME_SORTED=", assumeSorted, spaceSeparated=false) +
+    optional("CREATE_INDEX=", createIndex, spaceSeparated=false) +
+    optional("CREATE_MD5_FILE=", createMD5, spaceSeparated=false)
+}
diff --git a/public/gatk-queue-extensions-public/src/main/scala/org/broadinstitute/gatk/queue/extensions/picard/PicardMetricsFunction.scala b/public/gatk-queue-extensions-public/src/main/scala/org/broadinstitute/gatk/queue/extensions/picard/PicardMetricsFunction.scala
new file mode 100644
index 0000000..b9885a9
--- /dev/null
+++ b/public/gatk-queue-extensions-public/src/main/scala/org/broadinstitute/gatk/queue/extensions/picard/PicardMetricsFunction.scala
@@ -0,0 +1,54 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.queue.extensions.picard
+
+import java.io.File
+import org.broadinstitute.gatk.queue.function.JavaCommandLineFunction
+import htsjdk.samtools.ValidationStringency
+import htsjdk.samtools.SAMFileHeader.SortOrder
+
+/**
+ * Wraps a Picard function that operates on BAM files but doesn't output a new BAM file (i.e. QC metric files).
+ * See http://picard.sourceforge.net/ for more info.
+ *
+ * Since the various BAM utilities take slightly different arguments
+ * some values are optional.
+ */
+trait PicardMetricsFunction extends JavaCommandLineFunction {
+  var validationStringency = ValidationStringency.SILENT
+  var maxRecordsInRam: Option[Int] = None
+  var assumeSorted: Option[Boolean] = None
+  protected def inputBams: Seq[File]
+  protected def outputFile: File
+
+  abstract override def commandLine = super.commandLine +
+    repeat("INPUT=", inputBams, spaceSeparated=false) +
+    required("TMP_DIR=" + jobTempDir) +
+    optional("VALIDATION_STRINGENCY=", validationStringency, spaceSeparated=false) +
+    optional("OUTPUT=", outputFile, spaceSeparated=false) +
+    optional("MAX_RECORDS_IN_RAM=", maxRecordsInRam, spaceSeparated=false) +
+    optional("ASSUME_SORTED=", assumeSorted, spaceSeparated=false)
+}
diff --git a/public/gatk-queue-extensions-public/src/main/scala/org/broadinstitute/gatk/queue/extensions/picard/ReorderSam.scala b/public/gatk-queue-extensions-public/src/main/scala/org/broadinstitute/gatk/queue/extensions/picard/ReorderSam.scala
new file mode 100644
index 0000000..1813694
--- /dev/null
+++ b/public/gatk-queue-extensions-public/src/main/scala/org/broadinstitute/gatk/queue/extensions/picard/ReorderSam.scala
@@ -0,0 +1,73 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.queue.extensions.picard
+
+import org.broadinstitute.gatk.utils.commandline._
+
+import java.io.File
+/*
+ * Created by IntelliJ IDEA.
+ * User: carneiro
+ * Date: 6/22/11
+ * Time: 10:35 AM
+ */
+class ReorderSam extends org.broadinstitute.gatk.queue.function.JavaCommandLineFunction with PicardBamFunction {
+  analysisName = "ReorderSam"
+  javaMainClass = "picard.sam.ReorderSam"
+
+  @Input(doc="Input file (bam or sam) to extract reads from.", shortName = "input", fullName = "input_bam_files", required = true)
+  var input: Seq[File] = Nil
+
+  @Output(doc="Output file (bam or sam) to write extracted reads to.", shortName = "output", fullName = "output_bam_file", required = true)
+  var output: File = _
+
+  @Output(doc="The output bam index", shortName = "out_index", fullName = "output_bam_index_file", required = false)
+  var outputIndex: File = _
+
+  @Argument(doc="Reference sequence to reorder reads to match.", shortName = "ref", fullName = "sort_reference", required = true)
+  var sortReference: File = _
+
+  @Argument(doc="If true, then allows only a partial overlap of the BAM contigs with the new reference sequence contigs. By default, this tool requires a corresponding contig in the new reference for each read contig.", shortName = "aic", fullName = "allow_incomplete_concordance", required = false)
+  var ALLOW_INCOMPLETE_DICT_CONCORDANCE: Boolean = _
+
+  @Argument(doc="If true, then permits mapping from a read contig to a new reference contig with the same name but a different length. Highly dangerous, only use if you know what you are doing.", shortName = "acld", fullName = "allow_contig_length_discordance", required = false)
+  var ALLOW_CONTIG_LENGTH_DISCORDANCE: Boolean = _
+
+  override def freezeFieldValues() {
+    super.freezeFieldValues()
+    if (outputIndex == null && output != null)
+      outputIndex = new File(output.getName.stripSuffix(".bam") + ".bai")
+  }
+
+  override def inputBams = input
+  override def outputBam = output
+  this.createIndex = Some(true)
+  this.sortOrder = null
+  override def commandLine = super.commandLine +
+                             required("REFERENCE=" + sortReference) +
+                             optional("ALLOW_INCOMPLETE_DICT_CONCORDANCE=", ALLOW_INCOMPLETE_DICT_CONCORDANCE, spaceSeparated=false)
+                             optional("ALLOW_CONTIG_LENGTH_DISCORDANCE=", ALLOW_CONTIG_LENGTH_DISCORDANCE, spaceSeparated=false)
+}
\ No newline at end of file
diff --git a/public/gatk-queue-extensions-public/src/main/scala/org/broadinstitute/gatk/queue/extensions/picard/RevertSam.scala b/public/gatk-queue-extensions-public/src/main/scala/org/broadinstitute/gatk/queue/extensions/picard/RevertSam.scala
new file mode 100644
index 0000000..2012b54
--- /dev/null
+++ b/public/gatk-queue-extensions-public/src/main/scala/org/broadinstitute/gatk/queue/extensions/picard/RevertSam.scala
@@ -0,0 +1,86 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.queue.extensions.picard
+
+import org.broadinstitute.gatk.utils.commandline._
+
+import java.io.File
+
+/*
+ * Created by IntelliJ IDEA.
+ * User: carneiro
+ * Date: 6/22/11
+ * Time: 10:35 AM
+ */
+class RevertSam extends org.broadinstitute.gatk.queue.function.JavaCommandLineFunction with PicardBamFunction {
+  analysisName = "RevertSam"
+  javaMainClass = "picard.sam.RevertSam"
+
+  @Input(shortName = "input", fullName = "input_bam_files", required = true, doc = "The input SAM or BAM files to revert.")
+  var input: Seq[File] = Nil
+
+  @Output(shortName = "output", fullName = "output_bam_file", required = true, doc = "The reverted BAM or SAM output file.")
+  var output: File = _
+
+  @Output(shortName = "out_index", fullName = "output_bam_index_file", required = false, doc = "The output bam index")
+  var outputIndex: File = _
+
+  @Argument(shortName = "roq", fullName = "restore_original_qualities", required = false, doc = "True to restore original qualities from the OQ field to the QUAL field if available.")
+  var restoreOriginalQualities: Boolean = true
+
+  @Argument(shortName = "rdi", fullName = "remove_duplicate_information", required = false, doc = "Remove duplicate read flags from all reads. Note that if this is true and REMOVE_ALIGNMENT_INFORMATION==false, the output may have the unusual but sometimes desirable trait of having unmapped reads that are marked as duplicates.")
+  var removeDuplicateInformation: Boolean = true
+
+  @Argument(shortName = "rai", fullName = "remove_alignment_information", required = false, doc = "Remove all alignment information from the file.")
+  var removeAlignmentInformation: Boolean = true
+
+  @Argument(shortName = "atc", fullName = "attributes_to_clear", required = false, doc = "When removing alignment information, the set of optional tags to remove.")
+  var attributesToClear: Seq[String] = Nil
+
+  @Argument(shortName = "sa", fullName = "sample_alias", required = false, doc = "The sample alias to use in the reverted output file. This will override the existing sample alias in the file and is used only if all the read groups in the input file have the same sample alias.")
+  var sampleAlias: String = null
+
+  @Argument(shortName = "ln", fullName = "library_name", required = false, doc = "The library name to use in the reverted output file. This will override the existing sample alias in the file and is used only if all the read groups in the input file have the same sample alias.")
+  var libraryName: String = null
+
+  override def freezeFieldValues() {
+    super.freezeFieldValues()
+    if (outputIndex == null && output != null)
+      outputIndex = new File(output.getName.stripSuffix(".bam") + ".bai")
+  }
+
+
+  override def inputBams = input
+  override def outputBam = output
+  this.createIndex = Some(true)
+  override def commandLine = super.commandLine +
+                             conditional(!restoreOriginalQualities, "RESTORE_ORIGINAL_QUALITIES=false") +
+                             conditional(!removeDuplicateInformation, "REMOVE_DUPLICATE_INFORMATION=false") +
+                             conditional(!removeAlignmentInformation, "REMOVE_ALIGNMENT_INFORMATION=false") +
+                             repeat("ATTRIBUTE_TO_CLEAR=", attributesToClear, spaceSeparated=false) +   // repeat() returns "" for null/empty list
+                             conditional(sampleAlias != null, "SAMPLE_ALIAS=" + sampleAlias) +
+                             conditional(libraryName != null, "LIBRARY_NAME=" + libraryName)
+}
\ No newline at end of file
diff --git a/public/gatk-queue-extensions-public/src/main/scala/org/broadinstitute/gatk/queue/extensions/picard/SamToFastq.scala b/public/gatk-queue-extensions-public/src/main/scala/org/broadinstitute/gatk/queue/extensions/picard/SamToFastq.scala
new file mode 100644
index 0000000..e5624fc
--- /dev/null
+++ b/public/gatk-queue-extensions-public/src/main/scala/org/broadinstitute/gatk/queue/extensions/picard/SamToFastq.scala
@@ -0,0 +1,107 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.queue.extensions.picard
+
+import org.broadinstitute.gatk.utils.commandline._
+
+import java.io.File
+
+/*
+ * Created by IntelliJ IDEA.
+ * User: carneiro
+ * Date: 6/22/11
+ * Time: 10:35 AM
+ */
+class SamToFastq extends org.broadinstitute.gatk.queue.function.JavaCommandLineFunction with PicardBamFunction {
+  analysisName = "SamToFastq"
+  javaMainClass = "picard.sam.SamToFastq"
+
+  @Input(shortName = "input", fullName = "input_bam_files", required = true, doc = "Input SAM/BAM file to extract reads from.")
+  var input: Seq[File] = Nil
+
+  @Output(shortName = "fastq", fullName = "output_fastq_file", required = true, doc = "Output fastq file (single-end fastq or, if paired, first end of the pair fastq).")
+  var fastq: File = _
+
+  @Output(shortName = "se", fullName = "second_end_fastq", required = false, doc = "Output fastq file (if paired, second end of the pair fastq).")
+  var secondEndFastQ: File = _
+
+  @Argument(shortName = "opg", fullName = "output_per_readgroup", required = false, doc = "Output a fastq file per read group (two fastq files per read group if the group is paired).")
+  var outputPerReadGroup: Boolean = false
+
+  @Argument(shortName = "od", fullName = "output_dir", required = false, doc = "Directory in which to output the fastq file(s). Used only when OUTPUT_PER_RG is true.")
+  var outputDir: File = _
+
+  @Argument(shortName = "rr", fullName = "re_reverse", required = false, doc = "Re-reverse bases and qualities of reads with negative strand flag set before writing them to fastq.")
+  var reReverse: Boolean = true
+
+  @Argument(shortName = "nonpf", fullName = "include_non_pf_reads", required = false, doc = "Include non-PF reads from the SAM file into the output FASTQ files.")
+  var includeNonPFReads: Boolean = false
+
+  @Argument(shortName = "cat", fullName = "clipping_attribute", required = false, doc = "The attribute that stores the position at which the SAM record should be clipped.")
+  var clippingAttribute: String = null
+
+  @Argument(shortName = "cac", fullName = "clipping_action", required = false, doc = "The action that should be taken with clipped reads: 'X' means the reads and qualities should be trimmed at the clipped position; 'N' means the bases should be changed to Ns in the clipped region; and any integer means that the base qualities should be set to that value in the clipped region.")
+  var clippingAction: String = null
+
+  @Argument(shortName = "r1t", fullName = "read_one_trim", required = false, doc = "The number of bases to trim from the beginning of read 1.")
+  var readOneTrim: Int = -1
+
+  @Argument(shortName = "r1mbtw", fullName = "read_one_max_bases_to_write", required = false, doc = "The maximum number of bases to write from read 1 after trimming. If there are fewer than this many bases left after trimming, all will be written. If this value is null then all bases left after trimming will be written.")
+  var readOneMaxBasesToWrite: Int = -1
+
+  @Argument(shortName = "r2t", fullName = "read_two_trim", required = false, doc = "The number of bases to trim from the beginning of read 2.")
+  var readTwoTrim: Int = -1
+
+  @Argument(shortName = "r2mbtw", fullName = "read_two_max_bases_to_write", required = false, doc = "The maximum number of bases to write from read 2 after trimming. If there are fewer than this many bases left after trimming, all will be written. If this value is null then all bases left after trimming will be written.")
+  var readTwoMaxBasesToWrite: Int = -1
+
+  @Argument(shortName = "inpa", fullName = "include_non_primary_alignments", required = false, doc = "If true, include non-primary alignments in the output. Support of non-primary alignments in SamToFastq is not comprehensive, so there may be exceptions if this is set to true and there are paired reads with non-primary alignments.")
+  var includeNonPrimaryAlignments: Boolean = false
+
+  @Argument(shortName = "il", fullName = "interleave", required = false, doc = "Will generate an interleaved fastq if paired, each line will have /1 or /2 to describe which end it came from")
+  var interleave: Boolean = false
+
+  override def inputBams = input
+  override def outputBam = null
+  this.sortOrder = null
+
+  override def commandLine = super.commandLine +
+                             required("FASTQ=" + fastq) +
+                             optional("SECOND_END_FASTQ=", secondEndFastQ, spaceSeparated=false) +
+                             conditional(outputPerReadGroup, "OUTPUT_PER_RG=" + outputPerReadGroup) +
+                             optional("OUTPUT_DIR=", outputDir, spaceSeparated=false) +
+                             conditional(!reReverse, "RE_REVERSE=" + reReverse) +
+                             conditional(includeNonPFReads, "INCLUDE_NON_PF_READS=" + includeNonPFReads) +
+                             optional("CLIPPING_ATTRIBUTE=", clippingAttribute, spaceSeparated=false) +
+                             optional("CLIPPING_ACTION=", clippingAction, spaceSeparated=false) +
+                             conditional(readOneTrim >= 0, "READ1_TRIM=" + readOneTrim) +
+                             conditional(readOneMaxBasesToWrite >= 0, "READ1_MAX_BASES_TO_WRITE=" + readOneMaxBasesToWrite) +
+                             conditional(readTwoTrim >= 0, "READ2_TRIM=" + readTwoTrim) +
+                             conditional(readTwoMaxBasesToWrite >= 0, "READ2_MAX_BASES_TO_WRITE=" + readTwoMaxBasesToWrite) +
+                             conditional(includeNonPrimaryAlignments, "INCLUDE_NON_PRIMARY_ALIGNMENTS=" + includeNonPrimaryAlignments) +
+                             conditional(interleave, "INTERLEAVE=" + interleave)
+
+}
\ No newline at end of file
diff --git a/public/gatk-queue-extensions-public/src/main/scala/org/broadinstitute/gatk/queue/extensions/picard/SortSam.scala b/public/gatk-queue-extensions-public/src/main/scala/org/broadinstitute/gatk/queue/extensions/picard/SortSam.scala
new file mode 100644
index 0000000..847ed92
--- /dev/null
+++ b/public/gatk-queue-extensions-public/src/main/scala/org/broadinstitute/gatk/queue/extensions/picard/SortSam.scala
@@ -0,0 +1,63 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.queue.extensions.picard
+
+import org.broadinstitute.gatk.utils.commandline._
+
+import java.io.File
+
+/*
+ * Created by IntelliJ IDEA.
+ * User: carneiro
+ * Date: 6/22/11
+ * Time: 10:35 AM
+ */
+class SortSam extends org.broadinstitute.gatk.queue.function.JavaCommandLineFunction with PicardBamFunction {
+  analysisName = "SortSam"
+  javaMainClass = "picard.sam.SortSam"
+
+  @Input(doc="The input SAM or BAM files to sort.", shortName = "input", fullName = "input_bam_files", required = true)
+  var input: Seq[File] = Nil
+
+  @Output(doc="The sorted BAM or SAM output file.", shortName = "output", fullName = "output_bam_file", required = true)
+  var output: File = _
+
+  @Output(doc="The output bam index", shortName = "out_index", fullName = "output_bam_index_file", required = false)
+  var outputIndex: File = _
+
+  override def freezeFieldValues() {
+    super.freezeFieldValues()
+    if (outputIndex == null && output != null)
+      outputIndex = new File(output.getAbsolutePath.stripSuffix(".bam") + ".bai")
+  }
+
+
+
+  override def inputBams = input
+  override def outputBam = output
+  this.createIndex = Some(true)
+  override def commandLine = super.commandLine
+}
\ No newline at end of file
diff --git a/public/gatk-queue-extensions-public/src/main/scala/org/broadinstitute/gatk/queue/extensions/picard/ValidateSamFile.scala b/public/gatk-queue-extensions-public/src/main/scala/org/broadinstitute/gatk/queue/extensions/picard/ValidateSamFile.scala
new file mode 100644
index 0000000..e9ad097
--- /dev/null
+++ b/public/gatk-queue-extensions-public/src/main/scala/org/broadinstitute/gatk/queue/extensions/picard/ValidateSamFile.scala
@@ -0,0 +1,85 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.queue.extensions.picard
+
+import org.broadinstitute.gatk.utils.commandline._
+
+import picard.sam.ValidateSamFile.Mode
+
+import java.io.File
+
+/*
+ * Created by IntelliJ IDEA.
+ * User: carneiro
+ * Date: 6/22/11
+ * Time: 10:35 AM
+ */
+class ValidateSamFile extends org.broadinstitute.gatk.queue.function.JavaCommandLineFunction with PicardBamFunction {
+  analysisName = "ValidateSamFile"
+  javaMainClass = "picard.sam.ValidateSamFile"
+
+  @Input(doc="The input SAM or BAM files to analyze.  Must be coordinate sorted.", shortName = "input", fullName = "input_bam_files", required = true)
+  var input: Seq[File] = Nil
+
+  @Output(doc="Send output to a file instead of stdout", shortName = "output", fullName = "output_file", required = false)
+  var output: File = _
+
+  @Argument(doc="Mode of output", shortName = "mode", fullName = "mode_of_output", required = false)
+  var MODE: Mode = Mode.VERBOSE
+
+  @Argument(doc="List of validation error types to ignore.", shortName = "ignore", fullName = "ignore_error_types", required = false)
+  var IGNORE: Seq[String] = Nil
+
+  @Argument(doc = "The maximum number of lines output in verbose mode.", shortName = "max", fullName = "max_output", required = false)
+  var MAX_OUTPUT: Int = 100
+
+  @Argument(doc = "Reference sequence file, the NM tag check will be skipped if this is missing.", shortName = "ref", fullName ="reference_sequence", required=false)
+  var REFERENCE_SEQUENCE: File = _
+
+  @Argument(doc = "If true, only report errors, and ignore warnings.", shortName = "iw", fullName = "ignore_warnings", required = false)
+  var IGNORE_WARNINGS: Boolean = false
+
+  @Argument(doc = "If true and input is a BAM file with an index file, also validates the index.", shortName = "vi", fullName = "validate_index", required = false)
+  var VALIDATE_INDEX: Boolean = true
+
+  @Argument(doc = "Whether the SAM or BAM file consists of bisulfite sequenced reads. If so, C->T is not counted as an error in computing the value of the NM tag.", shortName = "bs", fullName = "is_bisulfite_sequenced", required = false)
+  var IS_BISULFITE_SEQUENCED: Boolean = false
+
+  @Argument(doc = "Relevant for a coordinate-sorted file containing read pairs only. Maximum number of file handles to keep open when spilling mate info to disk. Set this number a little lower than the per-process maximum number of file that may be open. This number can be found by executing the 'ulimit -n' command on a Unix system.", shortName = "max_files", fullName = "max_open_temp_files", required = false)
+  var MAX_OPEN_TEMP_FILES: Int = 8000
+
+  this.sortOrder = null
+  override def inputBams = input
+  override def outputBam = output
+  override def commandLine = super.commandLine +
+                             required("MODE=" + MODE) +
+                             required("MAX_OUTPUT=" + MAX_OUTPUT) +
+                             required("MAX_OPEN_TEMP_FILES=" + MAX_OPEN_TEMP_FILES) +
+                             conditional(!VALIDATE_INDEX, "VALIDATE_INDEX=false") +
+                             conditional(IGNORE_WARNINGS, "IGNORE_WARNINGS=true") +
+                             conditional(IS_BISULFITE_SEQUENCED, "IS_BISULFITE_SEQUENCED=true") +
+                             repeat("IGNORE=", IGNORE, spaceSeparated=false)  // repeat() returns "" for null/empty list
+}
\ No newline at end of file
diff --git a/public/gatk-queue-extensions-public/src/main/scala/org/broadinstitute/gatk/queue/extensions/samtools/SamtoolsCommandLineFunction.scala b/public/gatk-queue-extensions-public/src/main/scala/org/broadinstitute/gatk/queue/extensions/samtools/SamtoolsCommandLineFunction.scala
new file mode 100644
index 0000000..a7e6030
--- /dev/null
+++ b/public/gatk-queue-extensions-public/src/main/scala/org/broadinstitute/gatk/queue/extensions/samtools/SamtoolsCommandLineFunction.scala
@@ -0,0 +1,37 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.queue.extensions.samtools
+
+import org.broadinstitute.gatk.queue.function.CommandLineFunction
+import org.broadinstitute.gatk.utils.commandline.Argument
+
+/**
+ * samtools command line function
+ */
+abstract class SamtoolsCommandLineFunction extends CommandLineFunction {
+  @Argument(doc="samtools path")
+  var samtools: String = "samtools"
+}
diff --git a/public/gatk-queue-extensions-public/src/main/scala/org/broadinstitute/gatk/queue/extensions/samtools/SamtoolsIndexFunction.scala b/public/gatk-queue-extensions-public/src/main/scala/org/broadinstitute/gatk/queue/extensions/samtools/SamtoolsIndexFunction.scala
new file mode 100644
index 0000000..cb55c06
--- /dev/null
+++ b/public/gatk-queue-extensions-public/src/main/scala/org/broadinstitute/gatk/queue/extensions/samtools/SamtoolsIndexFunction.scala
@@ -0,0 +1,56 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.queue.extensions.samtools
+
+import java.io.File
+import org.broadinstitute.gatk.utils.commandline.{Output, Input}
+
+/**
+ * Indexes a BAM file using samtools.
+ */
+class SamtoolsIndexFunction extends SamtoolsCommandLineFunction {
+  analysisName = "samtools index"
+
+  @Input(doc="BAM file to index")
+  var bamFile: File = _
+
+  @Output(doc="BAM file index to output", required=false)
+  var bamFileIndex: File = _
+
+  /**
+   * Sets the bam file index to the bam file name + ".bai".
+   */
+  override def freezeFieldValues() {
+    super.freezeFieldValues()
+    if (bamFileIndex == null && bamFile != null)
+      bamFileIndex = new File(bamFile.getPath + ".bai")
+  }
+
+  def commandLine = required(samtools) +
+                    required("index") +
+                    required(bamFile) +
+                    required(bamFileIndex)
+}
diff --git a/public/gatk-queue-extensions-public/src/main/scala/org/broadinstitute/gatk/queue/extensions/samtools/SamtoolsMergeFunction.scala b/public/gatk-queue-extensions-public/src/main/scala/org/broadinstitute/gatk/queue/extensions/samtools/SamtoolsMergeFunction.scala
new file mode 100644
index 0000000..4d7c0c6
--- /dev/null
+++ b/public/gatk-queue-extensions-public/src/main/scala/org/broadinstitute/gatk/queue/extensions/samtools/SamtoolsMergeFunction.scala
@@ -0,0 +1,64 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.queue.extensions.samtools
+
+import java.io.File
+import org.broadinstitute.gatk.utils.commandline.{Argument, Output, Input}
+
+/**
+ * Merges BAM files using samtools.
+ */
+class SamtoolsMergeFunction extends SamtoolsCommandLineFunction {
+  analysisName = "samtools merge"
+
+  @Input(doc="BAM file input")
+  var inputBams: Seq[File] = Nil
+
+  @Output(doc="BAM file output")
+  var outputBam: File = _
+
+  @Argument(doc="region", required=false)
+  var region: String = _
+
+  @Input(doc="BAM file input indexes")
+  var inputBamIndexes: Seq[File] = Nil
+
+  override def freezeFieldValues() {
+    super.freezeFieldValues()
+    inputBamIndexes ++= inputBams
+      .filter(orig => orig != null && orig.getName.endsWith(".bam"))
+      .flatMap(orig => Array(
+        new File(orig.getPath + ".bai"),
+        new File(orig.getPath.stripSuffix(".bam") + ".bai")
+      ))
+  }
+
+  def commandLine = required(samtools) +
+                    required("merge") +
+                    optional("-R", region) +
+                    required(outputBam) +
+                    repeat(inputBams)
+}
diff --git a/public/gatk-queue-extensions-public/src/main/scala/org/broadinstitute/gatk/queue/extensions/snpeff/SnpEff.scala b/public/gatk-queue-extensions-public/src/main/scala/org/broadinstitute/gatk/queue/extensions/snpeff/SnpEff.scala
new file mode 100644
index 0000000..ae316bc
--- /dev/null
+++ b/public/gatk-queue-extensions-public/src/main/scala/org/broadinstitute/gatk/queue/extensions/snpeff/SnpEff.scala
@@ -0,0 +1,68 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.queue.extensions.snpeff
+
+import org.broadinstitute.gatk.queue.function.JavaCommandLineFunction
+import java.io.File
+import org.broadinstitute.gatk.utils.commandline.{Argument, Output, Input}
+
+/**
+ * Basic snpEff support.
+ * See: http://www.broadinstitute.org/gatk/guide/article?id=50
+ */
+class SnpEff extends JavaCommandLineFunction {
+  javaMainClass = "ca.mcgill.mcb.pcingola.snpEffect.commandLine.SnpEff"
+
+  @Input(doc="snp vcf4 file")
+  var inVcf: File = _
+
+  @Input(doc="config file with path to data dir", required=false)
+  var config: File = _
+
+  @Argument(doc="genome version")
+  var genomeVersion: String = _
+
+  @Argument(doc="verbose", required=false)
+  var verbose = true
+
+  @Argument(doc="onlyCoding", required=false)
+  var onlyCoding = true
+
+  @Output(doc="snp eff output")
+  var outVcf: File = _
+
+  override def commandLine = super.commandLine +
+                             required("eff") +
+                             conditional(verbose, "-v") +
+                             required("-onlyCoding", onlyCoding.toString) +
+                             optional("-c", config) +
+                             required("-i", "vcf") +
+                             required("-o", "vcf") +
+                             required(genomeVersion) +
+                             required(inVcf) +
+                             required(">", escape=false) +
+                             required(outVcf)
+}
diff --git a/public/gatk-queue-extensions-public/src/test/scala/org/broadinstitute/gatk/queue/extensions/gatk/GATKIntervalsUnitTest.scala b/public/gatk-queue-extensions-public/src/test/scala/org/broadinstitute/gatk/queue/extensions/gatk/GATKIntervalsUnitTest.scala
new file mode 100644
index 0000000..f2ec8a9
--- /dev/null
+++ b/public/gatk-queue-extensions-public/src/test/scala/org/broadinstitute/gatk/queue/extensions/gatk/GATKIntervalsUnitTest.scala
@@ -0,0 +1,154 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.queue.extensions.gatk
+
+import java.io.File
+import org.testng.Assert
+import org.testng.annotations.{DataProvider, Test}
+import org.broadinstitute.gatk.utils.BaseTest
+import org.broadinstitute.gatk.engine.datasources.reference.ReferenceDataSource
+import org.broadinstitute.gatk.utils.fasta.CachingIndexedFastaSequenceFile
+import org.broadinstitute.gatk.utils.{GenomeLocSortedSet, GenomeLocParser}
+import collection.JavaConversions._
+import org.broadinstitute.gatk.utils.interval.IntervalUtils
+import org.broadinstitute.gatk.utils.exceptions.UserException
+
+class GATKIntervalsUnitTest {
+  private final lazy val hg18Reference = new File(BaseTest.hg18Reference)
+  private final lazy val hg18GenomeLocParser = new GenomeLocParser(new CachingIndexedFastaSequenceFile(hg18Reference))
+  private final lazy val hg18ReferenceLocs = GenomeLocSortedSet.
+    createSetFromSequenceDictionary(new ReferenceDataSource(hg18Reference).getReference.getSequenceDictionary).toList
+  private final lazy val hg19GenomeLocParser = new GenomeLocParser(new CachingIndexedFastaSequenceFile(hg19Reference))
+
+  private final lazy val hg19Reference = new File(BaseTest.hg19Reference)
+
+  @Test
+  def testWithIntervals() {
+    val chr1 = hg18GenomeLocParser.parseGenomeLoc("chr1:1-1")
+    val chr2 = hg18GenomeLocParser.parseGenomeLoc("chr2:2-3")
+    val chr3 = hg18GenomeLocParser.parseGenomeLoc("chr3:3-5")
+
+    val gi = createGATKIntervals(hg18Reference, Seq("chr1:1-1", "chr2:2-3", "chr3:3-5"))
+    Assert.assertEquals(gi.locs.toSeq, Seq(chr1, chr2, chr3))
+    Assert.assertEquals(gi.contigs, Seq("chr1", "chr2", "chr3"))
+  }
+
+  @Test(timeOut = 30000L)
+  def testIntervalFile() {
+    val gi = createGATKIntervals(hg19Reference, Seq(BaseTest.hg19Intervals))
+    Assert.assertEquals(gi.locs.size, 189894)
+    // Timeout check is because of bad:
+    //   for(Item item: javaConvertedScalaList)
+    // This for loop is actually an O(N^2) operation as the iterator calls the
+    // O(N) javaConvertedScalaList.size() for each iteration of the loop.
+    Assert.assertEquals(IntervalUtils.splitFixedIntervals(gi.locs, 189894).size(), 189894)
+    Assert.assertEquals(gi.contigs.size, 24)
+  }
+
+  @Test
+  def testEmptyIntervals() {
+    val gi = createGATKIntervals(hg18Reference, Nil)
+    Assert.assertEquals(gi.locs, hg18ReferenceLocs)
+    Assert.assertEquals(gi.contigs.size, hg18ReferenceLocs.size)
+  }
+
+  @Test
+  def testContigCounts() {
+    Assert.assertEquals(createGATKIntervals(hg18Reference, Nil).contigs, hg18ReferenceLocs.map(_.getContig))
+    Assert.assertEquals(createGATKIntervals(hg18Reference, Seq("chr1", "chr2", "chr3")).contigs, Seq("chr1", "chr2", "chr3"))
+    Assert.assertEquals(createGATKIntervals(hg18Reference, Seq("chr1:1-2", "chr1:4-5", "chr2:1-1", "chr3:2-2")).contigs, Seq("chr1", "chr2", "chr3"))
+  }
+
+  @DataProvider(name="sortAndMergeIntervals")
+  def getSortAndMergeIntervals: Array[Array[AnyRef]] = {
+    Array(
+      Array(Seq("chr1:1-10", "chr1:1-10", "chr1:1-10"), Seq("chr1:1-10")),
+      Array(Seq("chr1:1-10", "chr1:1-11", "chr1:1-12"), Seq("chr1:1-12")),
+      Array(Seq("chr1:1-10", "chr1:11-20", "chr1:21-30"), Seq("chr1:1-30")),
+      Array(Seq("chr1:1-10", "chr1:10-20", "chr1:21-30"), Seq("chr1:1-30")),
+      Array(Seq("chr1:1-9", "chr1:21-30", "chr1:11-20"), Seq("chr1:1-9", "chr1:11-30"))
+    ).asInstanceOf[Array[Array[AnyRef]]]
+  }
+
+  @Test(dataProvider="sortAndMergeIntervals")
+  def testSortAndMergeIntervals(unmerged: Seq[String], expected: Seq[String]) {
+    Assert.assertEquals(createGATKIntervals(hg18Reference, unmerged).locs.toSeq, expected.map(hg18GenomeLocParser.parseGenomeLoc(_)))
+  }
+
+  @DataProvider(name="taggedFiles")
+  def getTaggedFiles: Array[Array[AnyRef]] = {
+    Array(
+      Array(hg18Reference, BaseTest.privateTestDir + "small_unmerged_gatk_intervals.list", null, Seq("chr1:1-10")),
+      Array(hg18Reference, BaseTest.privateTestDir + "small_unmerged_gatk_intervals.list", "", Seq("chr1:1-10")),
+      Array(hg18Reference, BaseTest.privateTestDir + "small_unmerged_gatk_intervals.list", "myList", Seq("chr1:1-10")),
+      Array(hg19Reference, BaseTest.privateTestDir + "small.indel.test.vcf", null, Seq("1:897475-897481", "1:10001292")),
+      Array(hg19Reference, BaseTest.privateTestDir + "small.indel.test.vcf", "", Seq("1:897475-897481", "1:10001292")),
+      Array(hg19Reference, BaseTest.privateTestDir + "small.indel.test.vcf", "myVcf", Seq("1:897475-897481", "1:10001292")),
+      Array(hg19Reference, BaseTest.privateTestDir + "small.indel.test.vcf", "VCF", Seq("1:897475-897481", "1:10001292")),
+      Array(hg19Reference, BaseTest.privateTestDir + "small.indel.test.vcf", "myVcf,VCF", Seq("1:897475-897481", "1:10001292")),
+      Array(hg19Reference, BaseTest.privateTestDir + "sampleBedFile.bed", null, Seq("20:1-999", "20:1002-2000", "22:1001-6000")),
+      Array(hg19Reference, BaseTest.privateTestDir + "sampleBedFile.bed", "", Seq("20:1-999", "20:1002-2000", "22:1001-6000")),
+      Array(hg19Reference, BaseTest.privateTestDir + "sampleBedFile.bed", "myBed", Seq("20:1-999", "20:1002-2000", "22:1001-6000")),
+      Array(hg19Reference, BaseTest.privateTestDir + "sampleBedFile.bed", "BED", Seq("20:1-999", "20:1002-2000", "22:1001-6000")),
+      Array(hg19Reference, BaseTest.privateTestDir + "sampleBedFile.bed", "myBed,BED", Seq("20:1-999", "20:1002-2000", "22:1001-6000"))
+    )
+  }
+
+  @Test(dataProvider="taggedFiles")
+  def testTaggedFiles(reference: File, file: String, tags: String, expected: Seq[String]) {
+    val gatk = new CommandLineGATK
+    gatk.reference_sequence = reference
+    gatk.intervals = Seq(new TaggedFile(file, tags))
+    val parser = if (reference == hg18Reference) hg18GenomeLocParser else hg19GenomeLocParser
+    Assert.assertEquals(new GATKIntervals(gatk).locs.toSeq, expected.map(parser.parseGenomeLoc(_)))
+  }
+
+  @DataProvider(name="badTaggedFiles")
+  def getBadTaggedFiles: Array[Array[AnyRef]] = {
+    Array(
+      Array(hg18Reference, BaseTest.privateTestDir + "small_unmerged_gatk_intervals.list", "VCF"),
+      Array(hg18Reference, BaseTest.privateTestDir + "small_unmerged_gatk_intervals.list", "too,many,tags"),
+      Array(hg19Reference, BaseTest.privateTestDir + "small.indel.test.vcf", "BED"),
+      Array(hg19Reference, BaseTest.privateTestDir + "small.indel.test.vcf", "VCF,myVCF"),
+      Array(hg19Reference, BaseTest.privateTestDir + "small.indel.test.vcf", "myVCF,VCF,extra"),
+      Array(hg19Reference, BaseTest.privateTestDir + "sampleBedFile.bed", "VCF"),
+      Array(hg19Reference, BaseTest.privateTestDir + "sampleBedFile.bed", "BED,myBed"),
+      Array(hg19Reference, BaseTest.privateTestDir + "sampleBedFile.bed", "myBed,BED,extra")
+    ).asInstanceOf[Array[Array[AnyRef]]]
+  }
+
+  @Test(dataProvider = "badTaggedFiles", expectedExceptions = Array(classOf[UserException]))
+  def testBadTaggedFiles(reference: File, file: String, tags: String) {
+    testTaggedFiles(reference, file, tags, Nil)
+  }
+
+  private def createGATKIntervals(reference: File, intervals: Seq[String]) = {
+    val gatk = new CommandLineGATK
+    gatk.reference_sequence = reference
+    gatk.intervalsString = intervals
+    new GATKIntervals(gatk)
+  }
+}
diff --git a/public/gatk-queue-extensions-public/src/test/scala/org/broadinstitute/gatk/queue/pipeline/examples/ExampleCountLociQueueTest.scala b/public/gatk-queue-extensions-public/src/test/scala/org/broadinstitute/gatk/queue/pipeline/examples/ExampleCountLociQueueTest.scala
new file mode 100644
index 0000000..f6cc746
--- /dev/null
+++ b/public/gatk-queue-extensions-public/src/test/scala/org/broadinstitute/gatk/queue/pipeline/examples/ExampleCountLociQueueTest.scala
@@ -0,0 +1,46 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.queue.pipeline.examples
+
+import org.testng.annotations.Test
+import org.broadinstitute.gatk.queue.pipeline.{QueueTest, QueueTestSpec}
+import org.broadinstitute.gatk.utils.BaseTest
+
+class ExampleCountLociQueueTest {
+  @Test(timeOut=36000000)
+  def testCountLoci() {
+    val testOut = "count.out"
+    val spec = new QueueTestSpec
+    spec.name = "countloci"
+    spec.args = Array(
+      " -S " + QueueTest.publicQScriptsPackageDir + "examples/ExampleCountLoci.scala",
+      " -R " + BaseTest.publicTestDir + "exampleFASTA.fasta",
+      " -I " + BaseTest.publicTestDir + "exampleBAM.bam",
+      " -o " + testOut).mkString
+    spec.fileMD5s += testOut -> "ade93df31a6150321c1067e749cae9be"
+    QueueTest.executeTest(spec)
+  }
+}
\ No newline at end of file
diff --git a/public/gatk-queue-extensions-public/src/test/scala/org/broadinstitute/gatk/queue/pipeline/examples/ExampleCountReadsQueueTest.scala b/public/gatk-queue-extensions-public/src/test/scala/org/broadinstitute/gatk/queue/pipeline/examples/ExampleCountReadsQueueTest.scala
new file mode 100644
index 0000000..e79ea8a
--- /dev/null
+++ b/public/gatk-queue-extensions-public/src/test/scala/org/broadinstitute/gatk/queue/pipeline/examples/ExampleCountReadsQueueTest.scala
@@ -0,0 +1,43 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.queue.pipeline.examples
+
+import org.testng.annotations.Test
+import org.broadinstitute.gatk.queue.pipeline.{QueueTest, QueueTestSpec}
+import org.broadinstitute.gatk.utils.BaseTest
+
+class ExampleCountReadsQueueTest {
+  @Test(timeOut=36000000)
+  def testCountReads() {
+    val spec = new QueueTestSpec
+    spec.name = "countreads"
+    spec.args = Array(
+      " -S " + QueueTest.publicQScriptsPackageDir + "examples/ExampleCountReads.scala",
+      " -R " + BaseTest.publicTestDir + "exampleFASTA.fasta",
+      " -I " + BaseTest.publicTestDir + "exampleBAM.bam").mkString
+    QueueTest.executeTest(spec)
+  }
+}
diff --git a/public/gatk-queue-extensions-public/src/test/scala/org/broadinstitute/gatk/queue/pipeline/examples/ExamplePrintReadsQueueTest.scala b/public/gatk-queue-extensions-public/src/test/scala/org/broadinstitute/gatk/queue/pipeline/examples/ExamplePrintReadsQueueTest.scala
new file mode 100644
index 0000000..fcaf0d7
--- /dev/null
+++ b/public/gatk-queue-extensions-public/src/test/scala/org/broadinstitute/gatk/queue/pipeline/examples/ExamplePrintReadsQueueTest.scala
@@ -0,0 +1,83 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.queue.pipeline.examples
+
+/*
+ * Copyright (c) 2011, 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.
+ */
+
+import org.testng.annotations.Test
+import org.broadinstitute.gatk.queue.pipeline.{QueueTest, QueueTestSpec}
+import org.broadinstitute.gatk.utils.BaseTest
+
+class ExamplePrintReadsQueueTest {
+  @Test(timeOut=36000000)
+  def testDevNullOutput() {
+    val spec = new QueueTestSpec
+    spec.name = "devnulloutput"
+    spec.args = Array(
+      " -S " + QueueTest.publicQScriptsPackageDir + "examples/ExamplePrintReads.scala",
+      " -R " + BaseTest.publicTestDir + "exampleFASTA.fasta",
+      " -I " + BaseTest.publicTestDir + "exampleBAM.bam",
+      " -out /dev/null").mkString
+    spec.jobRunners = QueueTest.allJobRunners
+    QueueTest.executeTest(spec)
+  }
+
+  @Test(timeOut=36000000)
+  def testCleanupBai() {
+    val spec = new QueueTestSpec
+    spec.name = "cleanupbai"
+    spec.args = Array(
+      " -S " + QueueTest.publicQScriptsPackageDir + "examples/ExamplePrintReads.scala",
+      " -R " + BaseTest.publicTestDir + "exampleFASTA.fasta",
+      " -I " + BaseTest.publicTestDir + "exampleBAM.bam",
+      " -out exampleOut.bam").mkString
+    spec.jobRunners = QueueTest.allJobRunners
+    spec.unexpectedFilePaths :+= ".queue/scatterGather/ExamplePrintReads-1-sg/temp_1_of_1/exampleOut.bai"
+    QueueTest.executeTest(spec)
+  }
+}
diff --git a/public/gatk-queue-extensions-public/src/test/scala/org/broadinstitute/gatk/queue/pipeline/examples/ExampleReadFilterQueueTest.scala b/public/gatk-queue-extensions-public/src/test/scala/org/broadinstitute/gatk/queue/pipeline/examples/ExampleReadFilterQueueTest.scala
new file mode 100644
index 0000000..af70174
--- /dev/null
+++ b/public/gatk-queue-extensions-public/src/test/scala/org/broadinstitute/gatk/queue/pipeline/examples/ExampleReadFilterQueueTest.scala
@@ -0,0 +1,91 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.queue.pipeline.examples
+
+/*
+ * Copyright (c) 2012, 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.
+ */
+
+/*
+ * Copyright (c) 2011, 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.
+ */
+
+import org.testng.annotations.Test
+import org.broadinstitute.gatk.queue.pipeline.{QueueTest, QueueTestSpec}
+import org.broadinstitute.gatk.utils.BaseTest
+
+class ExampleReadFilterQueueTest {
+  @Test(timeOut=36000000)
+  def testExampleReadFilter() {
+    val spec = new QueueTestSpec
+    spec.name = "examplereadfilter"
+    spec.args = Array(
+      " -S " + QueueTest.publicQScriptsPackageDir + "examples/ExampleReadFilter.scala",
+      " -R " + BaseTest.publicTestDir + "exampleFASTA.fasta",
+      " -I " + BaseTest.publicTestDir + "exampleBAM.bam").mkString
+    QueueTest.executeTest(spec)
+  }
+}
diff --git a/public/gatk-queue-extensions-public/src/test/scala/org/broadinstitute/gatk/queue/pipeline/examples/ExampleRetryMemoryLimitQueueTest.scala b/public/gatk-queue-extensions-public/src/test/scala/org/broadinstitute/gatk/queue/pipeline/examples/ExampleRetryMemoryLimitQueueTest.scala
new file mode 100644
index 0000000..dddccaa
--- /dev/null
+++ b/public/gatk-queue-extensions-public/src/test/scala/org/broadinstitute/gatk/queue/pipeline/examples/ExampleRetryMemoryLimitQueueTest.scala
@@ -0,0 +1,47 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.queue.pipeline.examples
+
+import org.testng.annotations.Test
+import org.broadinstitute.gatk.queue.pipeline.{QueueTest, QueueTestSpec}
+import org.broadinstitute.gatk.utils.BaseTest
+
+class ExampleRetryMemoryLimitQueueTest {
+
+  // This test is currently disabled due to unexplained intermittent failures (see GSA-943)
+  @Test(timeOut=36000000,enabled = false)
+  def testRetryMemoryLimit() {
+    val spec = new QueueTestSpec
+    spec.name = "RetryMemoryLimit"
+    spec.args = Array(
+      " -S " + QueueTest.publicQScriptsPackageDir + "examples/ExampleRetryMemoryLimit.scala",
+      " -R " + BaseTest.publicTestDir + "exampleFASTA.fasta",
+      " -I " + BaseTest.publicTestDir + "exampleBAM.bam",
+      " -retry 1").mkString
+    spec.jobRunners = QueueTest.allJobRunners
+    QueueTest.executeTest(spec)
+  }
+}
diff --git a/public/gatk-queue-extensions-public/src/test/scala/org/broadinstitute/gatk/queue/pipeline/examples/HelloWorldQueueTest.scala b/public/gatk-queue-extensions-public/src/test/scala/org/broadinstitute/gatk/queue/pipeline/examples/HelloWorldQueueTest.scala
new file mode 100644
index 0000000..093050a
--- /dev/null
+++ b/public/gatk-queue-extensions-public/src/test/scala/org/broadinstitute/gatk/queue/pipeline/examples/HelloWorldQueueTest.scala
@@ -0,0 +1,152 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.queue.pipeline.examples
+
+import org.testng.annotations.Test
+import org.broadinstitute.gatk.queue.pipeline.{QueueTest, QueueTestSpec}
+
+class HelloWorldQueueTest {
+  @Test(timeOut=36000000)
+  def testHelloWorld() {
+    val spec = new QueueTestSpec
+    spec.name = "HelloWorld"
+    spec.args = "-S " + QueueTest.publicQScriptsPackageDir + "examples/HelloWorld.scala"
+    spec.jobRunners = QueueTest.allJobRunners
+    QueueTest.executeTest(spec)
+  }
+
+  @Test(timeOut=36000000)
+  def testHelloWorldWithRunName() {
+    val spec = new QueueTestSpec
+    spec.name = "HelloWorldWithRunName"
+    spec.args = "-S " + QueueTest.publicQScriptsPackageDir + "examples/HelloWorld.scala" +
+      " -runName HelloWorld"
+    spec.jobRunners = QueueTest.allJobRunners
+    QueueTest.executeTest(spec)
+  }
+
+  @Test(timeOut=36000000)
+  def testHelloWorldWithMemoryLimit() {
+    val spec = new QueueTestSpec
+    spec.name = "HelloWorldMemoryLimit"
+    spec.args = "-S " + QueueTest.publicQScriptsPackageDir + "examples/HelloWorld.scala" +
+      " -memLimit 1.25"
+    spec.jobRunners = QueueTest.allJobRunners
+    QueueTest.executeTest(spec)
+  }
+
+  @Test(timeOut=36000000)
+  def testHelloWorldWithPriority() {
+    val spec = new QueueTestSpec
+    spec.name = "HelloWorldWithPriority"
+    spec.args = "-S " + QueueTest.publicQScriptsPackageDir + "examples/HelloWorld.scala" +
+      " -jobPriority 100"
+    spec.jobRunners = QueueTest.allJobRunners
+    QueueTest.executeTest(spec)
+  }
+
+  @Test(timeOut=36000000)
+  def testHelloWorldWithLsfResource() {
+    val spec = new QueueTestSpec
+    spec.name = "HelloWorldWithLsfResource"
+    spec.args = "-S " + QueueTest.publicQScriptsPackageDir + "examples/HelloWorld.scala" +
+      " -jobResReq rusage[iodine_io=1] -jobResReq select[swp>0] -jobResReq order[swp]"
+    spec.jobRunners = Seq("Lsf706")
+    QueueTest.executeTest(spec)
+  }
+
+  @Test(timeOut=36000000)
+  def testHelloWorldWithLsfResourceAndMemoryLimit() {
+    val spec = new QueueTestSpec
+    spec.name = "HelloWorldWithLsfResourceAndMemoryLimit"
+    spec.args = "-S " + QueueTest.publicQScriptsPackageDir + "examples/HelloWorld.scala" +
+      " -memLimit 1.25 -jobResReq rusage[iodine_io=1] -jobResReq select[swp>0] -jobResReq order[swp]"
+    spec.jobRunners = Seq("Lsf706")
+    QueueTest.executeTest(spec)
+  }
+
+  @Test(timeOut=36000000)
+  def testHelloWorldWithLsfEnvironment() {
+    val spec = new QueueTestSpec
+    spec.name = "HelloWorldWithLsfEnvironment"
+    spec.args = "-S " + QueueTest.publicQScriptsPackageDir + "examples/HelloWorld.scala" +
+      " -jobEnv tv"
+    spec.jobRunners = Seq("Lsf706")
+    QueueTest.executeTest(spec)
+  }
+
+  @Test(timeOut=36000000)
+  def testHelloWorldWithGridEngineResource() {
+    val spec = new QueueTestSpec
+    spec.name = "HelloWorldWithGridEngineResource"
+    spec.args = "-S " + QueueTest.publicQScriptsPackageDir + "examples/HelloWorld.scala" +
+      " -jobResReq s_core=1000M"
+    spec.jobRunners = Seq("GridEngine")
+    QueueTest.executeTest(spec)
+  }
+
+  @Test(timeOut=36000000)
+  def testHelloWorldWithGridEngineResourceAndMemoryLimit() {
+    val spec = new QueueTestSpec
+    spec.name = "HelloWorldWithGridEngineResourceAndMemoryLimit"
+    spec.args = "-S " + QueueTest.publicQScriptsPackageDir + "examples/HelloWorld.scala" +
+      " -memLimit 1.25 -jobResReq s_core=1000M"
+    spec.jobRunners = Seq("GridEngine")
+    QueueTest.executeTest(spec)
+  }
+
+  @Test(timeOut=36000000)
+  def testHelloWorldWithGridEngineEnvironment() {
+    val spec = new QueueTestSpec
+    spec.name = "HelloWorldWithGridEngineEnvironment"
+    spec.args = "-S " + QueueTest.publicQScriptsPackageDir + "examples/HelloWorld.scala" +
+      " -jobEnv \"make 1\""
+    spec.jobRunners = Seq("GridEngine")
+    QueueTest.executeTest(spec)
+  }
+
+  // disabled because our DRMAA implementation doesn't support wallTime
+  @Test(enabled=false, timeOut=36000000)
+  def testHelloWorldWithWalltime() {
+    val spec = new QueueTestSpec
+    spec.name = "HelloWorldWithWalltime"
+    spec.args = "-S " + QueueTest.publicQScriptsPackageDir + "examples/HelloWorld.scala" +
+      " -wallTime 100"
+    spec.jobRunners = QueueTest.allJobRunners
+    QueueTest.executeTest(spec)
+  }
+
+  @Test(timeOut=36000000)
+  def testHelloWorldWithLogDirectory() {
+    val spec = new QueueTestSpec
+    spec.name = "HelloWorldWithLogDirectory"
+    spec.args = "-S " + QueueTest.publicQScriptsPackageDir + "examples/HelloWorld.scala" +
+      " -logDir pipelineLogDir"
+    spec.jobRunners = QueueTest.allJobRunners
+    spec.expectedFilePaths = Seq("pipelineLogDir/HelloWorld-1.out")
+    QueueTest.executeTest(spec)
+  }
+}
diff --git a/public/gatk-queue/pom.xml b/public/gatk-queue/pom.xml
new file mode 100644
index 0000000..05ce207
--- /dev/null
+++ b/public/gatk-queue/pom.xml
@@ -0,0 +1,107 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+    <modelVersion>4.0.0</modelVersion>
+
+    <parent>
+        <groupId>org.broadinstitute.gatk</groupId>
+        <artifactId>gatk-aggregator</artifactId>
+        <version>3.3</version>
+        <relativePath>../..</relativePath>
+    </parent>
+
+    <artifactId>gatk-queue</artifactId>
+    <packaging>jar</packaging>
+    <name>GATK Queue</name>
+
+    <properties>
+        <gatk.basedir>${project.basedir}/../..</gatk.basedir>
+        <gatk.packagetests.artifactId>gatk-queue-package-distribution</gatk.packagetests.artifactId>
+    </properties>
+
+    <dependencies>
+        <dependency>
+            <groupId>${project.groupId}</groupId>
+            <artifactId>gatk-tools-public</artifactId>
+            <version>${project.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>org.scala-lang</groupId>
+            <artifactId>scala-compiler</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>log4j</groupId>
+            <artifactId>log4j</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>net.sf.jgrapht</groupId>
+            <artifactId>jgrapht</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.commons</groupId>
+            <artifactId>commons-email</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>javax.mail</groupId>
+            <artifactId>mail</artifactId>
+        </dependency>
+
+        <dependency>
+            <groupId>${project.groupId}</groupId>
+            <artifactId>gatk-tools-public</artifactId>
+            <version>${project.version}</version>
+            <type>test-jar</type>
+            <scope>test</scope>
+        </dependency>
+    </dependencies>
+
+    <build>
+        <plugins>
+            <plugin>
+                <groupId>org.scala-tools</groupId>
+                <artifactId>maven-scala-plugin</artifactId>
+            </plugin>
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-resources-plugin</artifactId>
+                <executions>
+                    <execution>
+                        <id>copy-resource-bundle-log4j</id>
+                        <phase>prepare-package</phase>
+                    </execution>
+                </executions>
+            </plugin>
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-javadoc-plugin</artifactId>
+                <executions>
+                    <execution>
+                        <id>extract-resource-bundle</id>
+                        <phase>prepare-package</phase>
+                    </execution>
+                </executions>
+            </plugin>
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-invoker-plugin</artifactId>
+                <executions>
+                    <execution>
+                        <id>package-unittests</id>
+                    </execution>
+                    <execution>
+                        <id>package-integrationtests</id>
+                    </execution>
+                    <execution>
+                        <id>package-largescaletests</id>
+                    </execution>
+                    <execution>
+                        <id>package-knowledgebasetests</id>
+                    </execution>
+                    <execution>
+                        <id>package-queuetests</id>
+                    </execution>
+                </executions>
+            </plugin>
+        </plugins>
+    </build>
+
+</project>
diff --git a/public/gatk-queue/src/main/java/org/broadinstitute/gatk/queue/QueueVersion.java b/public/gatk-queue/src/main/java/org/broadinstitute/gatk/queue/QueueVersion.java
new file mode 100644
index 0000000..e5e9dcb
--- /dev/null
+++ b/public/gatk-queue/src/main/java/org/broadinstitute/gatk/queue/QueueVersion.java
@@ -0,0 +1,32 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.queue;
+
+/**
+ * Generates the Queue version in the GATKText.properties by working around http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4492654
+ */
+public class QueueVersion {
+}
diff --git a/public/gatk-queue/src/main/java/org/broadinstitute/gatk/queue/package-info.java b/public/gatk-queue/src/main/java/org/broadinstitute/gatk/queue/package-info.java
new file mode 100644
index 0000000..755b696
--- /dev/null
+++ b/public/gatk-queue/src/main/java/org/broadinstitute/gatk/queue/package-info.java
@@ -0,0 +1,26 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.queue;
diff --git a/public/gatk-queue/src/main/resources/org/broadinstitute/gatk/queue/util/queueJobReport.R b/public/gatk-queue/src/main/resources/org/broadinstitute/gatk/queue/util/queueJobReport.R
new file mode 100644
index 0000000..70d3c78
--- /dev/null
+++ b/public/gatk-queue/src/main/resources/org/broadinstitute/gatk/queue/util/queueJobReport.R
@@ -0,0 +1,240 @@
+library(gsalib)
+library(ggplot2)
+library(gplots)
+library(tools)
+library(reshape)
+library(plyr)
+
+#
+# Standard command line switch.  Can we loaded interactively for development
+# or executed with RScript
+#
+args = commandArgs(TRUE)
+onCMDLine = ! is.na(args[1])
+if ( onCMDLine ) {
+  inputFileName = args[1]
+  outputPDF = args[2]
+} else {
+  inputFileName = "~/workspaces/scratch/SingleSample_VQSRwNewSOR.jobreport.txt"
+  #inputFileName = "/humgen/gsa-hpprojects/dev/depristo/oneOffProjects/Q-25718 at node1149.jobreport.txt"
+  #inputFileName = "/humgen/gsa-hpprojects/dev/depristo/oneOffProjects/rodPerformanceGoals/history/report.082711.txt"
+  outputPDF = NA
+}
+
+RUNTIME_UNITS = "(hours)"
+ORIGINAL_UNITS_TO_RUNTIME_UNITS = 1/1000/60/60
+
+# 
+# Helper function to aggregate all of the jobs in the report across all tables
+#
+allJobsFromReport <- function(report) {
+  names <- c("jobName", "startTime", "analysisName", "doneTime", "exechosts", "runtime")
+  sub <- lapply(report, function(table) table[,names])
+  do.call("rbind", sub)
+}
+
+#
+# Creates segmentation plots of time (x) vs. job (y) with segments for the duration of the job
+#
+plotJobsGantt <- function(gatkReport, sortOverall, title, includeText) {
+  allJobs = allJobsFromReport(gatkReport)
+  if ( sortOverall ) {
+    allJobs = allJobs[order(allJobs$analysisName, allJobs$startTime, decreasing=T), ]
+  } else {
+    allJobs = allJobs[order(allJobs$startTime, decreasing=T), ]
+  }
+  allJobs$index = 1:nrow(allJobs)
+  minTime = min(allJobs$startTime)
+  allJobs$relStartTime = allJobs$startTime - minTime 
+  allJobs$relDoneTime = allJobs$doneTime - minTime
+  allJobs$ganttName = paste(allJobs$jobName, "@", allJobs$exechosts)
+  maxRelTime = max(allJobs$relDoneTime)
+  p <- ggplot(data=allJobs, aes(x=relStartTime, y=index, color=analysisName))
+  p <- p + theme_bw()
+  p <- p + geom_segment(aes(xend=relDoneTime, yend=index), size=1, arrow=arrow(length = unit(0.1, "cm")))
+  if ( includeText )
+    p <- p + geom_text(aes(x=relStartTime, label=ganttName, hjust=0, vjust=-1), size=2)
+  p <- p + xlim(0, maxRelTime * 1.3)
+  p <- p + xlab(paste("Start time, relative to first job", RUNTIME_UNITS))
+  p <- p + ylab("Job number")
+  p <- p + ggtitle(title)
+  print(p)
+}
+
+#
+# Plots scheduling efficiency at job events
+#
+plotProgressByTime <- function(gatkReport) {
+  allJobs = allJobsFromReport(gatkReport)
+  nJobs = dim(allJobs)[1]
+  allJobs = allJobs[order(allJobs$startTime, decreasing=F),]
+  allJobs$index = 1:nrow(allJobs)
+
+  minTime = min(allJobs$startTime)
+  allJobs$relStartTime = allJobs$startTime - minTime
+  allJobs$relDoneTime = allJobs$doneTime - minTime
+
+  times = sort(c(allJobs$relStartTime, allJobs$relDoneTime))
+
+  countJobs <- function(p) {
+    s = allJobs$relStartTime
+    e = allJobs$relDoneTime
+    x = c() # I wish I knew how to make this work with apply
+    for ( time in times )
+      x = c(x, sum(p(s, e, time)))
+    x
+  }
+
+  pending = countJobs(function(s, e, t) s > t)
+  done = countJobs(function(s, e, t) e < t)
+  running = nJobs - pending - done
+
+  d = data.frame(times=times, pending=pending, running=running, done=done)
+  
+  p <- ggplot(data=melt(d, id.vars=c("times")), aes(x=times, y=value, color=variable))
+  p <- p + facet_grid(variable ~ ., scales="free")
+  p <- p + geom_line(size=2)
+  p <- p + xlab(paste("Time since start of first job", RUNTIME_UNITS))
+  p <- p + ggtitle("Job scheduling")
+  print(p)
+}
+
+# 
+# Creates tables for each job in this group
+#
+standardColumns = c("jobName", "startTime", "formattedStartTime", "analysisName", "intermediate", "exechosts", "formattedDoneTime", "doneTime", "runtime")
+plotGroup <- function(groupTable) {
+  name = unique(groupTable$analysisName)[1]
+  groupAnnotations = setdiff(names(groupTable), standardColumns)  
+  sub = groupTable[,c("jobName", groupAnnotations, "runtime")]
+  sub = sub[order(sub$iteration, sub$jobName, decreasing=F), ]
+  
+  # create a table showing each job and all annotations
+  textplot(sub, show.rownames=F)
+  title(paste("Job summary for", name, "full itemization"), cex=3)
+
+  # create the table for each combination of values in the group, listing iterations in the columns
+  sum = cast(melt(sub, id.vars=groupAnnotations, measure.vars=c("runtime")), ... ~ iteration, fun.aggregate=mean)
+  textplot(as.data.frame(sum), show.rownames=F)
+  title(paste("Job summary for", name, "itemizing each iteration"), cex=3)
+
+  # histogram of job times by groupAnnotations
+  if ( length(groupAnnotations) == 1 && dim(sub)[1] > 1 ) {
+    # todo -- how do we group by annotations?
+    p <- ggplot(data=sub, aes(x=runtime)) + geom_histogram()
+    p <- p + xlab(paste("runtime", RUNTIME_UNITS)) + ylab("No. of jobs")
+    p <- p + ggtitle(paste("Job runtime histogram for", name))
+    print(p)
+  }
+  
+  # as above, but averaging over all iterations
+  groupAnnotationsNoIteration = setdiff(groupAnnotations, "iteration")
+  if ( dim(sub)[1] > 1 ) {
+    try({ # need a try here because we will fail to reduce when there's just a single iteration
+      sum = cast(melt(sub, id.vars=groupAnnotationsNoIteration, measure.vars=c("runtime")), ... ~ ., fun.aggregate=c(mean, sd))
+      textplot(as.data.frame(sum), show.rownames=F)
+      title(paste("Job summary for", name, "averaging over all iterations"), cex=3)
+    }, silent=T)
+  }
+}
+    
+# print out some useful basic information
+print("Report")
+print(paste("Project          :", inputFileName))
+
+convertUnits <- function(gatkReportData) {
+  convertGroup <- function(g) {
+    g$runtime = g$runtime * ORIGINAL_UNITS_TO_RUNTIME_UNITS
+    g$startTime = g$startTime * ORIGINAL_UNITS_TO_RUNTIME_UNITS
+    g$doneTime = g$doneTime * ORIGINAL_UNITS_TO_RUNTIME_UNITS
+    g
+  }
+  lapply(gatkReportData, convertGroup)
+}
+
+#
+# Plots runtimes by analysis name and exechosts
+#
+# Useful to understand the performance of analysis jobs by hosts, 
+# and to debug problematic nodes
+# 
+plotTimeByHost <- function(gatkReportData) {
+  fields = c("analysisName", "exechosts", "runtime")
+  
+  runtimes = data.frame()
+  for ( report in gatkReportData ) {
+    runtimes = rbind(runtimes, report[,fields])
+  }
+  
+  plotMe <- function(name, vis) {
+    p = ggplot(data=runtimes, aes(x=exechosts, y=runtime, group=exechosts, color=exechosts))
+    p = p + facet_grid(analysisName ~ ., scale="free")
+    p = p + vis()
+    p = p + xlab("Job execution host")
+    p = p + ggtitle(paste(name, "of job runtimes by analysis name and execution host"))
+    p = p + ylab(paste("Distribution of runtimes", RUNTIME_UNITS))
+    p = p + theme(axis.text.x=element_text(angle=45, hjust=1, vjust=1))
+    print(p)
+  }
+  
+  plotMe("Boxplot", geom_boxplot)
+  plotMe("Jittered points", geom_jitter)
+}
+
+mergeScattersForAnalysis <- function(table) {
+  #allJobs$ganttName = paste(allJobs$jobName, "@", allJobs$exechosts)
+  
+  ddply(table, .(analysisName, iteration), summarize,
+        jobName = analysisName[1],
+        exechosts = paste(length(exechosts), "hosts"),
+        formattedStartTime = "NA",
+        formattedDoneTime = "NA",
+        intermediate = intermediate[1],
+        startTime = min(startTime),
+        doneTime = min(startTime) + sum(runtime),
+        runtime = sum(runtime))
+}
+
+mergeScatters <- function(report) {
+  newReport = list()
+  for ( name in names(gatkReportData) ) {
+    newReport[[name]] = mergeScattersForAnalysis(gatkReportData[[name]])
+  }
+  newReport
+}
+  
+# read the table
+gatkReportData <- gsa.read.gatkreport(inputFileName)
+gatkReportData <- convertUnits(gatkReportData)
+#print(summary(gatkReportData))
+
+if ( ! is.na(outputPDF) ) {
+  pdf(outputPDF, height=8.5, width=11)
+} 
+
+plotJobsGantt(gatkReportData, T, "All jobs, by analysis, by start time", F)
+plotJobsGantt(gatkReportData, F, "All jobs, sorted by start time", F)
+plotProgressByTime(gatkReportData)
+
+# plots summarizing overall costs, merging scattered counts
+merged.by.scatter = mergeScatters(gatkReportData) 
+plotJobsGantt(merged.by.scatter, F, "Jobs merged by scatter by start time", T)
+
+merged.as.df = do.call(rbind.data.frame, merged.by.scatter)[,c("analysisName", "runtime")]
+merged.as.df$percent = merged.as.df$runtime / sum(merged.as.df$runtime) * 100
+merged.as.df.formatted = data.frame(analysisName=merged.as.df$analysisName,runtime=prettyNum(merged.as.df$runtime), percent=prettyNum(merged.as.df$percent,digits=2))
+textplot(merged.as.df.formatted[order(merged.as.df$runtime),], show.rownames=F)
+title("Total runtime for each analysis")
+
+plotTimeByHost(gatkReportData)
+for ( group in gatkReportData ) {
+  #print(group)
+  plotGroup(group)
+}
+  
+if ( ! is.na(outputPDF) ) {
+  dev.off()
+  if (exists("compactPDF")) {
+    compactPDF(outputPDF)
+  }
+}
diff --git a/public/gatk-queue/src/main/scala/org/broadinstitute/gatk/queue/QCommandLine.scala b/public/gatk-queue/src/main/scala/org/broadinstitute/gatk/queue/QCommandLine.scala
new file mode 100644
index 0000000..297e10b
--- /dev/null
+++ b/public/gatk-queue/src/main/scala/org/broadinstitute/gatk/queue/QCommandLine.scala
@@ -0,0 +1,295 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.queue
+
+import java.io.File
+import org.broadinstitute.gatk.utils.commandline._
+import org.broadinstitute.gatk.queue.util._
+import org.broadinstitute.gatk.queue.engine.{QStatusMessenger, QGraphSettings, QGraph}
+import collection.JavaConversions._
+import org.broadinstitute.gatk.utils.classloader.PluginManager
+import org.broadinstitute.gatk.utils.exceptions.UserException
+import org.broadinstitute.gatk.utils.io.IOUtils
+import org.broadinstitute.gatk.utils.help.ApplicationDetails
+import java.util.{ResourceBundle, Arrays}
+import org.broadinstitute.gatk.utils.text.TextFormattingUtils
+import org.apache.commons.io.FilenameUtils
+
+/**
+ * Entry point of Queue.  Compiles and runs QScripts passed in to the command line.
+ */
+object QCommandLine extends Logging {
+  /**
+   * Main.
+   * @param argv Arguments.
+   */
+  def main(argv: Array[String]) {
+    val qCommandLine = new QCommandLine
+
+    val shutdownHook = new Thread {
+      override def run() {
+        logger.info("Shutting down jobs. Please wait...")
+        qCommandLine.shutdown()
+      }
+    }
+
+    Runtime.getRuntime.addShutdownHook(shutdownHook)
+
+    try {
+      CommandLineProgram.start(qCommandLine, argv)
+      try {
+        Runtime.getRuntime.removeShutdownHook(shutdownHook)
+        qCommandLine.shutdown()
+      } catch {
+        case e: Exception => /* ignore, example 'java.lang.IllegalStateException: Shutdown in progress' */
+      }
+      if (CommandLineProgram.result != 0)
+        System.exit(CommandLineProgram.result)
+    } catch {
+      case e: Exception => CommandLineProgram.exitSystemWithError(e)
+    }
+  }
+}
+
+/**
+ * Entry point of Queue.  Compiles and runs QScripts passed in to the command line.
+ */
+class QCommandLine extends CommandLineProgram with Logging {
+  @Input(fullName="script", shortName="S", doc="QScript scala file", required=true)
+  @ClassType(classOf[File])
+  var scripts = Seq.empty[File]
+
+  @ArgumentCollection
+  val settings = new QGraphSettings
+
+  private val qScriptManager = new QScriptManager
+  private val qGraph = new QGraph
+  private var qScriptClasses: File = _
+  private var shuttingDown = false
+
+  private lazy val qScriptPluginManager = {
+    qScriptClasses = IOUtils.tempDir("Q-Classes-", "", settings.qSettings.tempDirectory)
+    qScriptManager.loadScripts(scripts, qScriptClasses)
+    new PluginManager[QScript](qPluginType, Seq(qScriptClasses.toURI.toURL))
+  }
+
+  private lazy val qCommandPlugin = {
+    new PluginManager[QCommandPlugin](classOf[QCommandPlugin])
+  }
+
+  private lazy val allCommandPlugins = qCommandPlugin.createAllTypes()
+
+  private lazy val qPluginType: Class[_ <: QScript] = {
+    allCommandPlugins.map(_.qScriptClass).headOption.getOrElse(classOf[QScript])
+  }
+
+  /**
+   * Takes the QScripts passed in, runs their script() methods, retrieves their generated
+   * functions, and then builds and runs a QGraph based on the dependencies.
+   */
+  def execute = {
+    var success = false
+    var result = 1
+    var functionsAndStatusSize = 0
+    try {
+      ClassFieldCache.parsingEngine = this.parser
+
+      if (settings.qSettings.runName == null)
+        settings.qSettings.runName = FilenameUtils.removeExtension(scripts.head.getName)
+      if (IOUtils.isDefaultTempDir(settings.qSettings.tempDirectory))
+        settings.qSettings.tempDirectory = IOUtils.absolute(settings.qSettings.runDirectory, ".queue/tmp")
+      qGraph.initializeWithSettings(settings)
+
+      for (commandPlugin <- allCommandPlugins) {
+        loadArgumentsIntoObject(commandPlugin)
+      }
+
+      for (commandPlugin <- allCommandPlugins) {
+        if (commandPlugin.statusMessenger != null)
+          commandPlugin.statusMessenger.started()
+      }
+
+      qGraph.messengers = allCommandPlugins.filter(_.statusMessenger != null).map(_.statusMessenger).toSeq
+
+      // TODO: Default command plugin argument?
+      val remoteFileConverter = (
+        for (commandPlugin <- allCommandPlugins if (commandPlugin.remoteFileConverter != null))
+        yield commandPlugin.remoteFileConverter
+        ).headOption.getOrElse(null)
+
+      if (remoteFileConverter != null)
+        loadArgumentsIntoObject(remoteFileConverter)
+
+      val allQScripts = qScriptPluginManager.createAllTypes()
+      for (script <- allQScripts) {
+        logger.info("Scripting " + qScriptPluginManager.getName(script.getClass.asSubclass(classOf[QScript])))
+        loadArgumentsIntoObject(script)
+        allCommandPlugins.foreach(_.initScript(script))
+        // TODO: Pulling inputs can be time/io expensive! Some scripts are using the files to generate functions-- even for dry runs-- so pull it all down for now.
+        //if (settings.run)
+        script.pullInputs()
+        script.qSettings = settings.qSettings
+        try {
+          script.script()
+        } catch {
+          case e: Exception =>
+            throw new UserException.CannotExecuteQScript(script.getClass.getSimpleName + ".script() threw the following exception: " + e, e)
+        }
+
+        if (remoteFileConverter != null) {
+          if (remoteFileConverter.convertToRemoteEnabled)
+            script.mkRemoteOutputs(remoteFileConverter)
+        }
+
+        script.functions.foreach(qGraph.add(_))
+        logger.info("Added " + script.functions.size + " functions")
+      }
+      // Execute the job graph
+      qGraph.run()
+
+      val functionsAndStatus = qGraph.getFunctionsAndStatus
+
+      // walk over each script, calling onExecutionDone
+      for (script <- allQScripts) {
+        val scriptFunctions = functionsAndStatus.filterKeys(f => script.functions.contains(f))
+        script.onExecutionDone(scriptFunctions, success)
+      }
+      functionsAndStatusSize = functionsAndStatus.size
+
+      // write the final complete job report
+      logger.info("Writing final jobs report...")
+      qGraph.writeJobsReport()
+
+      if (qGraph.success) {
+        if (settings.run) {
+          allQScripts.foreach(_.pushOutputs())
+          for (commandPlugin <- allCommandPlugins)
+            if (commandPlugin.statusMessenger != null) {
+              val allInputs = allQScripts.map(_.remoteInputs)
+              val allOutputs = allQScripts.map(_.remoteOutputs)
+              commandPlugin.statusMessenger.done(allInputs, allOutputs)
+            }
+        }
+        success = true
+        result = 0
+      }
+    } finally {
+      if (!success) {
+        logger.info("Done with errors")
+        qGraph.logFailed()
+        if (settings.run) {
+          for (commandPlugin <- allCommandPlugins)
+            if (commandPlugin.statusMessenger != null)
+              commandPlugin.statusMessenger.exit("Done with errors: %s".format(qGraph.formattedStatusCounts))
+        }
+      }
+    }
+    if (success)
+      logger.info("Script completed successfully with %d total jobs".format(functionsAndStatusSize))
+    else
+      logger.info("Script failed: %s".format(qGraph.formattedStatusCounts))
+    result
+  }
+
+  /**
+   * Returns true as QScripts are located and compiled.
+   * @return true
+   */
+  override def canAddArgumentsDynamically = true
+
+  /**
+   * Returns the list of QScripts passed in via -S and other plugins
+   * so that their arguments can be inspected before QScript.script is called.
+   * @return Array of dynamic sources
+   */
+  override def getArgumentSources = {
+    var plugins = Seq.empty[Class[_]]
+    plugins ++= qScriptPluginManager.getPlugins
+    plugins ++= qCommandPlugin.getPlugins
+    plugins.toArray
+  }
+
+  /**
+   * Returns the name of a script/plugin
+   * @return The name of a script/plugin
+   */
+  override def getArgumentSourceName(source: Class[_]) = {
+    if (classOf[QScript].isAssignableFrom(source))
+      qScriptPluginManager.getName(source.asSubclass(classOf[QScript]))
+    else if (classOf[QCommandPlugin].isAssignableFrom(source))
+      qCommandPlugin.getName(source.asSubclass(classOf[QCommandPlugin]))
+    else
+      null
+  }
+
+  /**
+   * Returns a ScalaCompoundArgumentTypeDescriptor that can parse argument sources into scala collections.
+   * @return a ScalaCompoundArgumentTypeDescriptor
+   */
+  override def getArgumentTypeDescriptors =
+    Arrays.asList(new ScalaCompoundArgumentTypeDescriptor)
+
+  override def getApplicationDetails : ApplicationDetails = {
+    new ApplicationDetails(createQueueHeader(),
+                           Seq.empty[String],
+                           ApplicationDetails.createDefaultRunningInstructions(getClass.asInstanceOf[Class[CommandLineProgram]]),
+                           "")
+  }
+
+  private def createQueueHeader() : Seq[String] = {
+    Seq(String.format("Queue v%s, Compiled %s", getQueueVersion, getBuildTimestamp),
+         "Copyright (c) 2012 The Broad Institute",
+         "For support and documentation go to http://www.broadinstitute.org/gatk")
+  }
+
+  private def getQueueVersion : String = {
+    val stingResources : ResourceBundle = TextFormattingUtils.loadResourceBundle("GATKText")
+
+    if ( stingResources.containsKey("org.broadinstitute.gatk.queue.QueueVersion.version") ) {
+      stingResources.getString("org.broadinstitute.gatk.queue.QueueVersion.version")
+    }
+    else {
+      "<unknown>"
+    }
+  }
+
+  private def getBuildTimestamp : String = {
+    val stingResources : ResourceBundle = TextFormattingUtils.loadResourceBundle("GATKText")
+
+    if ( stingResources.containsKey("build.timestamp") ) {
+      stingResources.getString("build.timestamp")
+    }
+    else {
+      "<unknown>"
+    }
+  }
+
+  def shutdown() = {
+    shuttingDown = true
+    qGraph.shutdown()
+    if (qScriptClasses != null) IOUtils.tryDelete(qScriptClasses)
+  }
+}
diff --git a/public/gatk-queue/src/main/scala/org/broadinstitute/gatk/queue/QCommandPlugin.scala b/public/gatk-queue/src/main/scala/org/broadinstitute/gatk/queue/QCommandPlugin.scala
new file mode 100644
index 0000000..6df8b3c
--- /dev/null
+++ b/public/gatk-queue/src/main/scala/org/broadinstitute/gatk/queue/QCommandPlugin.scala
@@ -0,0 +1,36 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.queue
+
+import engine.QStatusMessenger
+import util.RemoteFileConverter
+
+trait QCommandPlugin {
+  def statusMessenger: QStatusMessenger = null
+  def remoteFileConverter: RemoteFileConverter = null
+  def qScriptClass: Class[_ <: QScript] = classOf[QScript]
+  def initScript(script: QScript) {}
+}
diff --git a/public/gatk-queue/src/main/scala/org/broadinstitute/gatk/queue/QException.scala b/public/gatk-queue/src/main/scala/org/broadinstitute/gatk/queue/QException.scala
new file mode 100644
index 0000000..1ae41e9
--- /dev/null
+++ b/public/gatk-queue/src/main/scala/org/broadinstitute/gatk/queue/QException.scala
@@ -0,0 +1,31 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.queue
+
+import org.broadinstitute.gatk.utils.exceptions.GATKException
+
+class QException(private val message: String, private val throwable: Throwable = null)
+  extends GATKException(message, throwable)
diff --git a/public/gatk-queue/src/main/scala/org/broadinstitute/gatk/queue/QScript.scala b/public/gatk-queue/src/main/scala/org/broadinstitute/gatk/queue/QScript.scala
new file mode 100644
index 0000000..f010445
--- /dev/null
+++ b/public/gatk-queue/src/main/scala/org/broadinstitute/gatk/queue/QScript.scala
@@ -0,0 +1,184 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.queue
+
+import engine.JobRunInfo
+import org.broadinstitute.gatk.queue.function.QFunction
+import annotation.target.field
+import util._
+import org.broadinstitute.gatk.utils.commandline.ArgumentSource
+
+/**
+ * Defines a Queue pipeline as a collection of CommandLineFunctions.
+ */
+trait QScript extends Logging with PrimitiveOptionConversions with StringFileConversions  {
+
+  // Type aliases so users don't have to import
+  type File = java.io.File
+  type CommandLineFunction = org.broadinstitute.gatk.queue.function.CommandLineFunction
+  type InProcessFunction = org.broadinstitute.gatk.queue.function.InProcessFunction
+  type ScatterGatherableFunction = org.broadinstitute.gatk.queue.function.scattergather.ScatterGatherableFunction
+  type SimpleTextGatherFunction = org.broadinstitute.gatk.queue.function.scattergather.SimpleTextGatherFunction
+
+  // Make sure annotations can be used in class constructors but target the fields
+  // ex: class MyClass(@Input var myVar: File) {}
+  // This was implicitly enabled in 2.8.0-RC2 and then updated to this new syntax:
+  // http://lampsvn.epfl.ch/trac/scala/ticket/3596
+  // http://lampsvn.epfl.ch/trac/scala/ticket/3421
+  type Input = org.broadinstitute.gatk.utils.commandline.Input @field
+  type Output = org.broadinstitute.gatk.utils.commandline.Output @field
+  type Argument = org.broadinstitute.gatk.utils.commandline.Argument @field
+  type ArgumentCollection = org.broadinstitute.gatk.utils.commandline.ArgumentCollection @field
+  type Gather = org.broadinstitute.gatk.utils.commandline.Gather @field
+
+  /**
+   * Default settings for QFunctions
+   */
+  var qSettings: QSettings = _
+
+  /**
+   * Builds the CommandLineFunctions that will be used to run this script and adds them to this.functions directly or using the add() utility method.
+   */
+  def script()
+
+  /**
+   * A default handler for the onExecutionDone() function.  By default this doesn't do anything
+   */
+  def onExecutionDone(jobs: Map[QFunction, JobRunInfo], success: Boolean) {
+  }
+
+  /**
+   * The command line functions that will be executed for this QScript.
+   */
+  var functions = Seq.empty[QFunction]
+
+  /**
+   * Exchanges the extension on a file.
+   * @param file File to look for the extension.
+   * @param oldExtension Old extension to strip off, if present.
+   * @param newExtension New extension to append.
+   * @return new File with the new extension in the current directory.
+   */
+  protected def swapExt(file: File, oldExtension: String, newExtension: String) =
+    new File(file.getName.stripSuffix(oldExtension) + newExtension)
+
+  /**
+   * Exchanges the extension on a file.
+   * @param dir New directory for the file.
+   * @param file File to look for the extension.
+   * @param oldExtension Old extension to strip off, if present.
+   * @param newExtension New extension to append.
+   * @return new File with the new extension in dir.
+   */
+  protected def swapExt(dir: File, file: File, oldExtension: String, newExtension: String) =
+    new File(dir, file.getName.stripSuffix(oldExtension) + newExtension)
+
+  /**
+   * Adds one or more command line functions to be run.
+   * @param functions Functions to add.
+   */
+  def add(functions: QFunction*) {
+    functions.foreach(function => function.addOrder = QScript.nextAddOrder)
+    this.functions ++= functions
+  }
+
+  def addAll(functions: Traversable[QFunction]) {
+    functions.foreach( f => add(f) )
+  }
+
+  /**
+   * Convert all @Output files to remote output files.
+   * @param remoteFileConverter Converter for files to remote files.
+   */
+  def mkRemoteOutputs(remoteFileConverter: RemoteFileConverter) {
+    for (field <- outputFields) {
+      val fieldFile = ClassFieldCache.getFieldFile(this, field)
+      if (fieldFile != null && !fieldFile.isInstanceOf[RemoteFile]) {
+        val fieldName = ClassFieldCache.fullName(field)
+        val remoteFile = remoteFileConverter.convertToRemote(fieldFile, fieldName)
+        ClassFieldCache.setFieldValue(this, field, remoteFile)
+      }
+    }
+  }
+
+  /**
+   * Pull all remote files to the local disk
+   */
+  def pullInputs() {
+    val inputs = ClassFieldCache.getFieldFiles(this, inputFields)
+    for (remoteFile <- filterRemoteFiles(inputs)) {
+      logger.info("Pulling %s from %s".format(remoteFile.getAbsolutePath, remoteFile.remoteDescription))
+      remoteFile.pullToLocal()
+    }
+  }
+
+  /**
+   * Push all remote files from the local disk
+   */
+  def pushOutputs() {
+    val outputs = ClassFieldCache.getFieldFiles(this, outputFields)
+    for (remoteFile <- filterRemoteFiles(outputs)) {
+      logger.info("Pushing %s to %s".format(remoteFile.getAbsolutePath, remoteFile.remoteDescription))
+      remoteFile.pushToRemote()
+    }
+  }
+
+  private def filterRemoteFiles(fields: Seq[File]): Seq[RemoteFile] =
+    fields.filter(field => field != null && field.isInstanceOf[RemoteFile]).map(_.asInstanceOf[RemoteFile])
+  /**
+   * @return the inputs or null if there are no inputs
+   */
+  def remoteInputs: AnyRef = null
+
+  /**
+   * @return the outputs or null if there are no outputs
+   */
+  def remoteOutputs: AnyRef = null
+
+  /** The complete list of fields. */
+  def functionFields: Seq[ArgumentSource] = ClassFieldCache.classFunctionFields(this.getClass)
+  /** The @Input fields. */
+  def inputFields: Seq[ArgumentSource] = ClassFieldCache.classInputFields(this.getClass)
+  /** The @Output fields. */
+  def outputFields: Seq[ArgumentSource] = ClassFieldCache.classOutputFields(this.getClass)
+  /** The @Argument fields. */
+  def argumentFields: Seq[ArgumentSource] = ClassFieldCache.classArgumentFields(this.getClass)
+}
+
+object QScript {
+  private var addOrder = 0
+  private def nextAddOrder = {
+    addOrder += 1
+    Seq(addOrder)
+  }
+
+  /**
+   * Resets the add order back to zero. Useful for testing purposes.
+   */
+  def resetAddOrder() {
+    addOrder = 0
+  }
+}
diff --git a/public/gatk-queue/src/main/scala/org/broadinstitute/gatk/queue/QScriptManager.scala b/public/gatk-queue/src/main/scala/org/broadinstitute/gatk/queue/QScriptManager.scala
new file mode 100644
index 0000000..8df12c2
--- /dev/null
+++ b/public/gatk-queue/src/main/scala/org/broadinstitute/gatk/queue/QScriptManager.scala
@@ -0,0 +1,168 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.queue
+
+import scala.tools.nsc.{Global, Settings}
+import scala.tools.nsc.io.PlainFile
+import org.broadinstitute.gatk.queue.util.Logging
+import collection.JavaConversions._
+import java.io.File
+import scala.tools.nsc.reporters.AbstractReporter
+import java.lang.String
+import org.apache.log4j.Level
+import org.broadinstitute.gatk.queue.util.TextFormatUtils._
+import org.broadinstitute.gatk.utils.classloader.JVMUtils
+import scala.reflect.internal.util.{FakePos, NoPosition, Position, StringOps}
+import org.broadinstitute.gatk.utils.exceptions.UserException
+
+/**
+ * Plugin manager for QScripts which loads QScripts into the current class loader.
+ */
+class QScriptManager() extends Logging {
+  /**
+   * Compiles and loads the scripts in the files into the current classloader.
+   * Heavily based on scala/src/compiler/scala/tools/ant/Scalac.scala
+   */
+  def loadScripts(scripts: Seq[File], tempDir: File) {
+    // Make sure the scripts actually exist.
+    scripts.foreach{
+        file => if( !file.exists()) throw new UserException.CouldNotReadInputFile(file, "it does not exist.")
+    }
+
+    if (scripts.size > 0) {
+      val settings = new Settings((error: String) => logger.error(error))
+      settings.deprecation.value = true
+      settings.outdir.value = tempDir.getPath
+
+      // Set the classpath to the current class path.
+      JVMUtils.getClasspathURLs.foreach(url => {
+          settings.bootclasspath.append(url.getPath)
+          settings.classpath.append(url.getPath)
+      })
+
+      val reporter = new QScriptManager.Log4JReporter(settings)
+
+      val compiler = new Global(settings, reporter)
+      val run = new compiler.Run
+
+      logger.info("Compiling %s QScript%s".format(scripts.size, plural(scripts.size)))
+      logger.debug("Compilation directory: " + settings.outdir.value)
+      run.compileFiles(scripts.toList.map(new PlainFile(_)))
+
+      reporter.printSummary()
+      if (reporter.hasErrors) {
+        val msg = "Compile of %s failed with %d error%s".format(
+          scripts.mkString(", "), reporter.ERROR.count, plural(reporter.ERROR.count))
+        throw new QException(msg)
+      }
+      else if (reporter.WARNING.count > 0)
+        logger.warn("Compile succeeded with %d warning%s".format(
+          reporter.WARNING.count, plural(reporter.WARNING.count)))
+      else
+        logger.info("Compilation complete")
+    }
+  }
+}
+
+/**
+ * Plugin manager for QScripts which loads QScripts into the current classloader.
+ */
+object QScriptManager extends Logging {
+
+  /**
+   * NSC (New Scala Compiler) reporter which logs to Log4J.
+   * Heavily based on scala/src/compiler/scala/tools/nsc/reporters/ConsoleReporter.scala
+   */
+  private class Log4JReporter(val settings: Settings) extends AbstractReporter {
+    def displayPrompt() { throw new UnsupportedOperationException("Unable to prompt the user.  Prompting should be off.") }
+
+    /**
+     * Displays the message at position with severity.
+     * @param posIn Position of the event in the file that generated the message.
+     * @param msg Message to display.
+     * @param severity Severity of the event.
+     */
+    def display(posIn: Position, msg: String, severity: Severity) {
+      severity.count += 1
+      val level = severity match {
+        case INFO => Level.INFO
+        case WARNING => Level.WARN
+        case ERROR => Level.ERROR
+      }
+      val pos = if (posIn eq null) NoPosition
+                else if (posIn.isDefined) posIn.inUltimateSource(posIn.source)
+                else posIn
+      pos match {
+        case FakePos(fmsg) =>
+          printMessage(level, fmsg+" "+msg)
+        case NoPosition =>
+          printMessage(level, msg)
+        case _ =>
+          val file = pos.source.file
+          printMessage(level, file.name+":"+pos.line+": "+msg)
+          printSourceLine(level, pos)
+      }
+    }
+
+    /**
+     * Prints a summary count of warnings and errors.
+     */
+    def printSummary() {
+      if (WARNING.count > 0)
+        printMessage(Level.WARN, StringOps.countElementsAsString(WARNING.count, "warning") + " found")
+      if (ERROR.count > 0)
+        printMessage(Level.ERROR, StringOps.countElementsAsString(ERROR.count, "error") + " found")
+    }
+
+    /**
+     * Prints the source code line of an event followed by a pointer within the line to the error.
+     * @param level Severity level.
+     * @param pos Position in the file of the event.
+     */
+    private def printSourceLine(level: Level, pos: Position) {
+      printMessage(level, pos.lineContent.stripLineEnd)
+      printColumnMarker(level, pos)
+    }
+
+    /**
+     * Prints the column marker of the given position.
+     * @param level Severity level.
+     * @param pos Position in the file of the event.
+     */
+    private def printColumnMarker(level: Level, pos: Position) {
+      if (pos.isDefined) { printMessage(level, " " * (pos.column - 1) + "^") }
+    }
+
+    /**
+     * Prints the message at the severity level.
+     * @param level Severity level.
+     * @param message Message content.
+     */
+    private def printMessage(level: Level, message: String) {
+      logger.log(level, message)
+    }
+  }
+}
diff --git a/public/gatk-queue/src/main/scala/org/broadinstitute/gatk/queue/QSettings.scala b/public/gatk-queue/src/main/scala/org/broadinstitute/gatk/queue/QSettings.scala
new file mode 100644
index 0000000..86457fb
--- /dev/null
+++ b/public/gatk-queue/src/main/scala/org/broadinstitute/gatk/queue/QSettings.scala
@@ -0,0 +1,101 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.queue
+
+import java.io.File
+import org.broadinstitute.gatk.utils.commandline.{ClassType, Argument}
+
+/**
+ * Default settings settable on the command line and passed to CommandLineFunctions.
+ */
+class QSettings {
+  @Argument(fullName="run_name", shortName="runName", doc="A name for this run used for various status messages.", required=false)
+  var runName: String = _
+
+  @Argument(fullName="job_project", shortName="jobProject", doc="Default project for compute farm jobs.", required=false)
+  var jobProject: String = _
+
+  @Argument(fullName="job_queue", shortName="jobQueue", doc="Default queue for compute farm jobs.", required=false)
+  var jobQueue: String = _
+
+  @Argument(fullName="job_priority", shortName="jobPriority", doc="Default priority for jobs. Min = 0, Max = 100", required=false)
+  @ClassType(classOf[Int])
+  var jobPriority: Option[Int] = None
+
+  @Argument(fullName="job_native_arg", shortName="jobNative", doc="Native arguments to pass to the job runner.", required=false)
+  var jobNativeArgs: Seq[String] = Nil
+
+  @Argument(fullName="job_resource_request", shortName="jobResReq", doc="Resource requests to pass to the job runner.", required=false)
+  var jobResourceRequests: Seq[String] = Nil
+
+  @Argument(fullName="job_environment_name", shortName="jobEnv", doc="Environment names for the job runner.", required=false)
+  var jobEnvironmentNames: Seq[String] = Nil
+
+  @Argument(fullName="memory_limit", shortName="memLimit", doc="Default memory limit for jobs, in gigabytes. If not set defaults to 2GB.", required=false)
+  @ClassType(classOf[Double])
+  var memoryLimit: Option[Double] = Some(2)
+
+  @Argument(fullName="memory_limit_threshold", shortName="memLimitThresh", doc="After passing this threshold stop increasing memory limit for jobs, in gigabytes.", required=false)
+  @ClassType(classOf[Double])
+  var memoryLimitThreshold: Option[Double] = None
+
+  @Argument(fullName="resident_memory_limit", shortName="resMemLimit", doc="Default resident memory limit for jobs, in gigabytes.", required=false)
+  @ClassType(classOf[Double])
+  var residentLimit: Option[Double] = None
+
+  @Argument(fullName="resident_memory_request", shortName="resMemReq", doc="Default resident memory request for jobs, in gigabytes.", required=false)
+  @ClassType(classOf[Double])
+  var residentRequest: Option[Double] = None
+
+  @Argument(fullName="resident_memory_request_parameter", shortName="resMemReqParam", doc="Parameter for resident memory requests. By default not requested.", required=false)
+  var residentRequestParameter: String = _
+
+  @Argument(fullName="job_walltime", shortName="wallTime", doc="Setting the required DRMAA walltime or LSF run limit.", required=false)
+  @ClassType(classOf[Long])
+  var jobWalltime: Option[Long] = None
+
+  /** The name of the parallel environment (required for SGE, for example) */
+  @Argument(fullName="job_parallel_env", shortName="jobParaEnv", doc="An SGE style parallel environment to use for jobs requesting more than 1 core.  Equivalent to submitting jobs with -pe ARG nt for jobs with nt > 1", required=false)
+  var parallelEnvironmentName: String = "smp_pe" // Broad default
+
+  @Argument(fullName="dontRequestMultipleCores", shortName="multiCoreJerk", doc="If provided, Queue will not request multiple processors for jobs using multiple processors.  Sometimes you eat the bear, sometimes the bear eats you.", required=false)
+  var dontRequestMultipleCores: Boolean = false
+
+  @Argument(fullName="disableDefaultJavaGCOptimizations", shortName="noGCOpt", doc="If provided, Queue will not ensure that java GC threads are limited and that the a minimum amount of time is spent in GC.")
+  var disableDefaultJavaGCOptimizations = false
+
+  @Argument(fullName="run_directory", shortName="runDir", doc="Root directory to run functions from.", required=false)
+  var runDirectory = new File(".")
+
+  @Argument(fullName="temp_directory", shortName="tempDir", doc="Temp directory to pass to functions.", required=false)
+  var tempDirectory = new File(System.getProperty("java.io.tmpdir"))
+
+  @Argument(fullName="job_scatter_gather_directory", shortName="jobSGDir", doc="Default directory to place scatter gather output for compute farm jobs.", required=false)
+  var jobScatterGatherDirectory: File = _
+  
+  @Argument(fullName="log_directory", shortName="logDir", doc="Directory to write log files into.", required=false)
+  var logDirectory: File = _
+}
diff --git a/public/gatk-queue/src/main/scala/org/broadinstitute/gatk/queue/engine/CommandLineJobManager.scala b/public/gatk-queue/src/main/scala/org/broadinstitute/gatk/queue/engine/CommandLineJobManager.scala
new file mode 100644
index 0000000..a3b004c
--- /dev/null
+++ b/public/gatk-queue/src/main/scala/org/broadinstitute/gatk/queue/engine/CommandLineJobManager.scala
@@ -0,0 +1,35 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.queue.engine
+
+import org.broadinstitute.gatk.queue.function.CommandLineFunction
+
+/**
+ * Creates and stops CommandLineJobRunners
+ */
+trait CommandLineJobManager[TRunner <: CommandLineJobRunner] extends JobManager[CommandLineFunction, TRunner] {
+  def functionType = classOf[CommandLineFunction]
+}
diff --git a/public/gatk-queue/src/main/scala/org/broadinstitute/gatk/queue/engine/CommandLineJobRunner.scala b/public/gatk-queue/src/main/scala/org/broadinstitute/gatk/queue/engine/CommandLineJobRunner.scala
new file mode 100644
index 0000000..e5c2594
--- /dev/null
+++ b/public/gatk-queue/src/main/scala/org/broadinstitute/gatk/queue/engine/CommandLineJobRunner.scala
@@ -0,0 +1,107 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.queue.engine
+
+import org.broadinstitute.gatk.queue.function.CommandLineFunction
+import java.io.File
+import org.broadinstitute.gatk.queue.util.Logging
+import org.broadinstitute.gatk.utils.io.IOUtils
+
+/**
+ * Runs a command line function.
+ */
+trait CommandLineJobRunner extends JobRunner[CommandLineFunction] with Logging {
+
+  /** The string representation of the identifier of the running job. */
+  def jobIdString: String = null
+
+  /** A generated exec shell script. */
+  protected var jobScript: File = _
+
+  /** Which directory to use for the job status files. */
+  protected def jobStatusDir = function.jobTempDir
+
+  /** Amount of time a job can go without status before giving up. */
+  private val unknownStatusMaxSeconds = 5 * 60
+
+  /** Last known status */
+  protected var lastStatus: RunnerStatus.Value = _
+
+  /** The last time the status was updated */
+  protected var lastStatusUpdate: Long = _
+
+  /** The runner specific priority for a minimum priority job */
+  protected val minRunnerPriority = 0
+
+  /** The runner specific priority for a maximum priority job */
+  protected val maxRunnerPriority = 0
+
+  /** The priority of the function in the range defined by the runner */
+  protected def functionPriority = {
+    function.jobPriority.map { priority =>
+      (((priority / 100D) * (maxRunnerPriority - minRunnerPriority)) + minRunnerPriority).
+        round.intValue() min maxRunnerPriority max minRunnerPriority
+    }
+  }
+
+  final override def status = this.lastStatus
+
+  override def init() {
+    super.init()
+    val exec = new StringBuilder
+    
+    var dirs = Set.empty[File]
+    for (dir <- function.jobDirectories)
+      dirs += IOUtils.dirLevel(dir, 2)
+    if (dirs.size > 0) {
+      // prepend "cd '<dir_1>' [&& cd '<dir_n>']" to automount the directories.
+      exec.append(dirs.mkString("cd '", "' && cd '", "'"))
+      exec.append(" && cd '%s' && \\%n".format(function.commandDirectory))
+    }
+    exec.append(function.commandLine)
+
+    this.jobScript = IOUtils.writeTempFile(exec.toString(), ".exec", "", jobStatusDir)
+  }
+
+  protected def updateStatus(updatedStatus: RunnerStatus.Value) {
+    this.lastStatus = updatedStatus
+    this.lastStatusUpdate = System.currentTimeMillis
+  }
+
+  override def checkUnknownStatus() {
+    val unknownStatusMillis = (System.currentTimeMillis - lastStatusUpdate)
+    if (unknownStatusMillis > (unknownStatusMaxSeconds * 1000L)) {
+      // Unknown status has been returned for a while now.
+      updateStatus(RunnerStatus.FAILED)
+      logger.error("Unable to read status for %0.2f minutes: job id %d: %s".format(unknownStatusMillis/(60 * 1000D), jobIdString, function.description))
+    }
+  }
+
+  override def cleanup() {
+    super.cleanup()
+    IOUtils.tryDelete(jobScript)
+  }
+}
diff --git a/public/gatk-queue/src/main/scala/org/broadinstitute/gatk/queue/engine/CommandLinePluginManager.scala b/public/gatk-queue/src/main/scala/org/broadinstitute/gatk/queue/engine/CommandLinePluginManager.scala
new file mode 100644
index 0000000..3931c5f
--- /dev/null
+++ b/public/gatk-queue/src/main/scala/org/broadinstitute/gatk/queue/engine/CommandLinePluginManager.scala
@@ -0,0 +1,33 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.queue.engine
+
+import org.broadinstitute.gatk.utils.classloader.PluginManager
+
+class CommandLinePluginManager extends
+  PluginManager[CommandLineJobManager[CommandLineJobRunner]](
+    classOf[CommandLineJobManager[CommandLineJobRunner]], "JobManager", "JobManager") {
+}
diff --git a/public/gatk-queue/src/main/scala/org/broadinstitute/gatk/queue/engine/FunctionEdge.scala b/public/gatk-queue/src/main/scala/org/broadinstitute/gatk/queue/engine/FunctionEdge.scala
new file mode 100644
index 0000000..1b02f5d
--- /dev/null
+++ b/public/gatk-queue/src/main/scala/org/broadinstitute/gatk/queue/engine/FunctionEdge.scala
@@ -0,0 +1,211 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.queue.engine
+
+import org.broadinstitute.gatk.queue.function.QFunction
+import java.io.{StringWriter, PrintWriter}
+import org.broadinstitute.gatk.queue.util.Logging
+import org.broadinstitute.gatk.utils.io.IOUtils
+import org.apache.commons.io.FileUtils
+import org.apache.commons.lang.StringUtils
+
+/**
+ * An edge in the QGraph that runs a QFunction.
+ * The edge is created first to determine inter-node dependencies,
+ * and then the runner is specified later when the time comes to
+ * execute the function in the edge.
+ */
+class FunctionEdge(val function: QFunction, val inputs: QNode, val outputs: QNode) extends QEdge with Logging {
+  var runner: JobRunner[_] =_
+
+  /**
+   * The depth of this edge in the graph.
+   */
+  var depth = -1
+
+  val myRunInfo: JobRunInfo = JobRunInfo.default // purely for dryRun testing
+
+  /**
+   * When using reset status this variable tracks the old status
+   */
+  var resetFromStatus: RunnerStatus.Value = null
+
+  /**
+   * Initializes with the current status of the function.
+   */
+  private var currentStatus = {
+    if (function.isFail)
+      RunnerStatus.FAILED
+    else if (function.isDone)
+      RunnerStatus.DONE
+    else
+      RunnerStatus.PENDING
+  }
+
+  def start() {
+    try {
+      if (logger.isDebugEnabled) {
+        logger.debug("Starting: " + function.commandDirectory + " > " + function.description)
+      } else {
+        logger.info("Starting: " + function.description)
+      }
+      logger.info("Output written to " + function.jobOutputFile)
+      if (function.jobErrorFile != null)
+        logger.info("Errors written to " + function.jobErrorFile)
+
+      function.deleteLogs()
+      function.deleteOutputs()
+      function.mkOutputDirectories()
+
+      runner.init()
+      runner.start()
+    } catch {
+      case e: Throwable =>
+        currentStatus = RunnerStatus.FAILED
+        try {
+          runner.cleanup()
+          function.failOutputs.foreach(_.createNewFile())
+          writeStackTrace(e)
+        } catch {
+          case _: Throwable => /* ignore errors in the exception handler */
+        }
+        logger.error("Error: " + function.description, e)
+    }
+  }
+
+  /**
+   * Returns the current status of the edge.
+   */
+  def status = {
+    if (currentStatus == RunnerStatus.PENDING || currentStatus == RunnerStatus.RUNNING) {
+      if (runner != null) {
+        try {
+          currentStatus = runner.status
+
+          if (currentStatus == RunnerStatus.FAILED) {
+            try {
+              runner.cleanup()
+              function.failOutputs.foreach(_.createNewFile())
+            } catch {
+              case _: Throwable => /* ignore errors in the error handler */
+            }
+            logger.error("Error: " + function.description)
+            tailError()
+          } else if (currentStatus == RunnerStatus.DONE) {
+            try {
+              runner.cleanup()
+              function.doneOutputs.foreach(_.createNewFile())
+            } catch {
+              case _: Throwable => /* ignore errors in the done handler */
+            }
+            logger.info("Done: " + function.description)
+          }
+        } catch {
+          case e: Throwable =>
+            currentStatus = RunnerStatus.FAILED
+            try {
+              runner.cleanup()
+              function.failOutputs.foreach(_.createNewFile())
+              writeStackTrace(e)
+            } catch {
+              case _: Throwable => /* ignore errors in the exception handler */
+            }
+            logger.error("Error retrieving status: " + function.description, e)
+        }
+      }
+    }
+
+    currentStatus
+  }
+
+  /**
+   * Explicitly sets the status of the runner to done..
+   */
+  def markAsDone() {
+    currentStatus = RunnerStatus.DONE
+  }
+
+  /**
+   * Marks this edge as skipped as it is not needed for the current run.
+   */
+  def markAsSkipped() {
+    currentStatus = RunnerStatus.SKIPPED
+  }
+
+  /**
+   * Resets the edge to pending status.
+   */
+  def resetToPending(cleanOutputs: Boolean) {
+    if (resetFromStatus == null)
+      resetFromStatus = currentStatus
+    currentStatus = RunnerStatus.PENDING
+    if (cleanOutputs)
+      function.deleteOutputs()
+    function.jobErrorLines = Nil
+    runner = null
+  }
+
+  override def shortDescription = function.shortDescription
+
+  /**
+   * Returns the path to the file to use for logging errors.
+   * @return the path to the file to use for logging errors.
+   */
+  private def functionErrorFile = if (function.jobErrorFile != null) function.jobErrorFile else function.jobOutputFile
+
+  /**
+   * Outputs the last lines of the error logs.
+   */
+  private def tailError() {
+    val errorFile = functionErrorFile
+    if (IOUtils.waitFor(errorFile, 120)) {
+      val maxLines = 100
+      val tailLines = IOUtils.tail(errorFile, maxLines)
+      val nl = "%n".format()
+      val summary = if (tailLines.size > maxLines) "Last %d lines".format(maxLines) else "Contents"
+      this.function.jobErrorLines = collection.JavaConversions.collectionAsScalaIterable(tailLines).toSeq
+      logger.error("%s of %s:%n%s".format(summary, errorFile, StringUtils.join(tailLines, nl)))
+    } else {
+      logger.error("Unable to access log file: %s".format(errorFile))
+    }
+  }
+
+  /**
+   * Writes the stack trace to the error file.
+   */
+  private def writeStackTrace(e: Throwable) {
+    val stackTrace = new StringWriter
+    val printWriter = new PrintWriter(stackTrace)
+    printWriter.println(function.description)
+    e.printStackTrace(printWriter)
+    printWriter.close()
+    FileUtils.writeStringToFile(functionErrorFile, stackTrace.toString)
+  }
+
+  def getRunInfo = {
+    if ( runner == null ) myRunInfo else runner.getRunInfo
+  }
+}
diff --git a/public/gatk-queue/src/main/scala/org/broadinstitute/gatk/queue/engine/InProcessJobManager.scala b/public/gatk-queue/src/main/scala/org/broadinstitute/gatk/queue/engine/InProcessJobManager.scala
new file mode 100644
index 0000000..aa7d069
--- /dev/null
+++ b/public/gatk-queue/src/main/scala/org/broadinstitute/gatk/queue/engine/InProcessJobManager.scala
@@ -0,0 +1,34 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.queue.engine
+
+import org.broadinstitute.gatk.queue.function.InProcessFunction
+
+class InProcessJobManager extends JobManager[InProcessFunction, InProcessRunner] {
+  def runnerType = classOf[InProcessRunner]
+  def functionType = classOf[InProcessFunction]
+  def create(function: InProcessFunction) = new InProcessRunner(function)
+}
diff --git a/public/gatk-queue/src/main/scala/org/broadinstitute/gatk/queue/engine/InProcessRunner.scala b/public/gatk-queue/src/main/scala/org/broadinstitute/gatk/queue/engine/InProcessRunner.scala
new file mode 100644
index 0000000..bb8896d
--- /dev/null
+++ b/public/gatk-queue/src/main/scala/org/broadinstitute/gatk/queue/engine/InProcessRunner.scala
@@ -0,0 +1,66 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.queue.engine
+
+import org.broadinstitute.gatk.queue.function.InProcessFunction
+import java.util.Date
+import org.broadinstitute.gatk.utils.Utils
+import org.apache.commons.io.{IOUtils, FileUtils}
+import java.io.PrintStream
+
+/**
+ * Runs a function that executes in process and does not fork out an external process.
+ */
+class InProcessRunner(val function: InProcessFunction) extends JobRunner[InProcessFunction] {
+  private var runStatus: RunnerStatus.Value = _
+
+  def start() {
+    getRunInfo.startTime = new Date()
+    getRunInfo.exechosts = Utils.resolveHostname()
+    runStatus = RunnerStatus.RUNNING
+
+    function.jobOutputStream = new PrintStream(FileUtils.openOutputStream(function.jobOutputFile))
+    function.jobErrorStream = {
+      if (function.jobErrorFile != null)
+        new PrintStream(FileUtils.openOutputStream(function.jobErrorFile))
+      else
+        function.jobOutputStream
+    }
+    try {
+      function.run()
+      function.jobOutputStream.println("%s%nDone.".format(function.description))
+    } finally {
+      IOUtils.closeQuietly(function.jobOutputStream)
+      if (function.jobErrorFile != null)
+        IOUtils.closeQuietly(function.jobErrorStream)
+    }
+
+    runStatus = RunnerStatus.DONE
+    getRunInfo.doneTime = new Date()
+  }
+
+  def status = runStatus
+}
diff --git a/public/gatk-queue/src/main/scala/org/broadinstitute/gatk/queue/engine/JobManager.scala b/public/gatk-queue/src/main/scala/org/broadinstitute/gatk/queue/engine/JobManager.scala
new file mode 100644
index 0000000..e8fb1f0
--- /dev/null
+++ b/public/gatk-queue/src/main/scala/org/broadinstitute/gatk/queue/engine/JobManager.scala
@@ -0,0 +1,60 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.queue.engine
+
+import org.broadinstitute.gatk.queue.function.QFunction
+
+/**
+ * Creates and stops JobRunners
+ */
+trait JobManager[TFunction <: QFunction, TRunner <: JobRunner[TFunction]] {
+  def init() {}
+  def exit() {}
+
+  /** The class type of the runner.  Available at runtime even after erasure. */
+  def functionType: Class[TFunction]
+
+  /** The class type of the functions processed by the runner.  Available at runtime even after erasure. */
+  def runnerType: Class[TRunner]
+
+  /** Creates a new runner.
+   * @param function Function for the runner.
+   */
+  def create(function: TFunction): TRunner
+
+  /**
+   * Updates the status on a list of functions.
+   * @param runners Runners to update.
+   * @return runners which were updated.
+   */
+  def updateStatus(runners: Set[TRunner]): Set[TRunner] = Set.empty
+
+  /**
+   * Stops a list of functions.
+   * @param runners Runners to stop.
+   */
+  def tryStop(runners: Set[TRunner]) {}
+}
diff --git a/public/gatk-queue/src/main/scala/org/broadinstitute/gatk/queue/engine/JobRunInfo.scala b/public/gatk-queue/src/main/scala/org/broadinstitute/gatk/queue/engine/JobRunInfo.scala
new file mode 100644
index 0000000..20a536e
--- /dev/null
+++ b/public/gatk-queue/src/main/scala/org/broadinstitute/gatk/queue/engine/JobRunInfo.scala
@@ -0,0 +1,79 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.queue.engine
+
+import java.text.SimpleDateFormat
+
+/**
+ * Class containing tracked information about a job run.
+ */
+  // todo -- it might be nice to have the hostname
+class JobRunInfo {
+  /** constant date format */
+  val formatter = new SimpleDateFormat("yy-MM-dd H:mm:ss:SSS");
+
+  /** The start time with millisecond resolution of this job */
+  var startTime: java.util.Date   = _
+  /** The done time with millisecond resolution of this job */
+  var doneTime: java.util.Date = _
+  var exechosts: String = "localhost"
+
+  def getStartTime: String = getTime(startTime)
+  def getDoneTime: String = getTime(doneTime)
+  def getFormattedStartTime = formatTime(startTime)
+  def getFormattedDoneTime = formatTime(doneTime)
+
+  /** Helper function that returns the time of the date */
+  private def getTime(d: java.util.Date): String = if ( d != null ) d.getTime.toString else "null"
+
+  /** Helper function that pretty prints the date */
+  private def formatTime(d: java.util.Date): String = if ( d != null ) formatter.format(d) else "null"
+
+  def getExecHosts = exechosts
+
+  /**
+   * Was any information set for this jobInfo?  JobInfo can be unset because
+   * the job never ran or because it already completed.
+   */
+  def isFilledIn = startTime != null && doneTime != null
+
+  /**
+   * How long did the job run (in wall time)?  Returns -1 if this jobInfo isn't filled in
+   */
+  def getRuntimeInMs: Long = {
+    if ( isFilledIn )
+      doneTime.getTime - startTime.getTime
+    else
+      -1
+  }
+
+  override def toString: String =
+    "started %s ended %s runtime %s".format(getFormattedStartTime, getFormattedDoneTime, getRuntimeInMs)
+}
+
+object JobRunInfo {
+  def default: JobRunInfo = new JobRunInfo()
+}
\ No newline at end of file
diff --git a/public/gatk-queue/src/main/scala/org/broadinstitute/gatk/queue/engine/JobRunner.scala b/public/gatk-queue/src/main/scala/org/broadinstitute/gatk/queue/engine/JobRunner.scala
new file mode 100644
index 0000000..d7e4868
--- /dev/null
+++ b/public/gatk-queue/src/main/scala/org/broadinstitute/gatk/queue/engine/JobRunner.scala
@@ -0,0 +1,89 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.queue.engine
+
+import org.broadinstitute.gatk.queue.function.QFunction
+
+/**
+ * Base interface for job runners.
+ */
+trait JobRunner[TFunction <: QFunction] {
+
+  /**
+   * Initializes this job.
+   */
+  def init() {
+  }
+
+  /**
+   * Runs the function.
+   * After the function returns the status of the function should
+   * be RUNNING, FAILED, or DONE.
+   * @param function Command to run.
+   */
+  def start()
+
+  /**
+   * Returns the current run status.
+   * Must only be called AFTER start().
+   * @return RUNNING, DONE, or FAILED.
+   */
+  def status: RunnerStatus.Value
+
+  /**
+   * Checks if the status has been unknown for an extended period of time.
+   */
+  def checkUnknownStatus() {}
+
+  /**
+   * Returns the function to be run.
+   */
+  def function: TFunction
+
+  /**
+   * Cleans up after the function is run.
+   * For example removing all temporary files.
+   */
+  def cleanup() {
+  }
+
+  /**
+   * Must be overloaded
+   */
+  val runInfo = JobRunInfo.default
+  def getRunInfo = runInfo
+
+  /**
+   * Calls back to a hook that an expert user can setup to modify a job.
+   * @param value Value to modify.
+   */
+  protected def updateJobRun(value: Any) {
+    val updater = function.updateJobRun
+    if (updater != null)
+      if (updater.isDefinedAt(value))
+        updater(value)
+  }
+}
diff --git a/public/gatk-queue/src/main/scala/org/broadinstitute/gatk/queue/engine/MappingEdge.scala b/public/gatk-queue/src/main/scala/org/broadinstitute/gatk/queue/engine/MappingEdge.scala
new file mode 100644
index 0000000..af51602
--- /dev/null
+++ b/public/gatk-queue/src/main/scala/org/broadinstitute/gatk/queue/engine/MappingEdge.scala
@@ -0,0 +1,39 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.queue.engine
+
+/**
+ * Utility class to map a set of inputs to set of outputs.
+ * The QGraph uses this function internally to map between user defined functions.
+ */
+class MappingEdge(val inputs: QNode, val outputs: QNode) extends QEdge {
+  /**
+   * For debugging purposes returns <map>.
+   * @return <map>
+   */
+  override def toString = "<map>"
+  override def shortDescription = ""
+}
diff --git a/public/gatk-queue/src/main/scala/org/broadinstitute/gatk/queue/engine/QEdge.scala b/public/gatk-queue/src/main/scala/org/broadinstitute/gatk/queue/engine/QEdge.scala
new file mode 100644
index 0000000..d3f2f4b
--- /dev/null
+++ b/public/gatk-queue/src/main/scala/org/broadinstitute/gatk/queue/engine/QEdge.scala
@@ -0,0 +1,57 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.queue.engine
+
+/**
+ * An edge in the QGraph
+ */
+trait QEdge {
+  /**
+   * List of inputs for this function sorted by path.
+   */
+  def inputs: QNode
+
+  /**
+   * List of outputs for this function sorted by path.
+   */
+  def outputs: QNode
+
+  /**
+   * The short description
+   */
+  def shortDescription = ""
+
+  override def hashCode = inputs.hashCode + outputs.hashCode
+
+  override def equals(obj: Any) = {
+    obj match {
+      case other: QEdge =>
+        this.inputs == other.inputs &&
+        this.outputs == other.outputs
+      case _ => false
+    }
+  }
+}
diff --git a/public/gatk-queue/src/main/scala/org/broadinstitute/gatk/queue/engine/QGraph.scala b/public/gatk-queue/src/main/scala/org/broadinstitute/gatk/queue/engine/QGraph.scala
new file mode 100644
index 0000000..7d09bf5
--- /dev/null
+++ b/public/gatk-queue/src/main/scala/org/broadinstitute/gatk/queue/engine/QGraph.scala
@@ -0,0 +1,1228 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.queue.engine
+
+import org.jgrapht.traverse.TopologicalOrderIterator
+import org.jgrapht.graph.SimpleDirectedGraph
+import scala.collection.JavaConversions._
+import org.jgrapht.alg.CycleDetector
+import org.jgrapht.EdgeFactory
+import org.jgrapht.ext.DOTExporter
+import org.jgrapht.event.{TraversalListenerAdapter, EdgeTraversalEvent}
+import org.broadinstitute.gatk.queue.QException
+import org.broadinstitute.gatk.queue.function.{InProcessFunction, CommandLineFunction, QFunction}
+import org.apache.commons.lang.StringUtils
+import org.broadinstitute.gatk.queue.util._
+import collection.immutable.{TreeSet, TreeMap}
+import org.broadinstitute.gatk.queue.function.scattergather.{ScatterFunction, CloneFunction, GatherFunction, ScatterGatherableFunction}
+import java.util.Date
+import org.broadinstitute.gatk.utils.Utils
+import org.apache.commons.io.{FilenameUtils, FileUtils, IOUtils}
+import java.io.{OutputStreamWriter, File}
+
+/**
+ * The internal dependency tracker between sets of function input and output files.
+ */
+class QGraph extends Logging {
+  var settings: QGraphSettings = _
+  var messengers: Seq[QStatusMessenger] = Nil
+
+  private def dryRun = !settings.run
+  private var numMissingValues = 0
+
+  private val jobGraph = newGraph
+  private val functionOrdering = Ordering.by[FunctionEdge, Iterable[Int]](edge => -graphDepth(edge) +: edge.function.addOrder)
+  private val fileOrdering = Ordering.by[File,String](_.getAbsolutePath)
+  // A map of nodes by list of files.
+  private var nodeMap = TreeMap.empty[Iterable[File], QNode](Ordering.Iterable(fileOrdering))
+  // The next unique id for a node if not found in the nodeMap.
+  private var nextNodeId = 0
+
+  private var running = true
+  private val runningLock = new Object
+  private var runningJobs = Set.empty[FunctionEdge]
+  private var cleanupJobs = Set.empty[FunctionEdge]
+
+  private val nl = "%n".format()
+
+  private val commandLinePluginManager = new CommandLinePluginManager
+  private var commandLineManager: CommandLineJobManager[CommandLineJobRunner] = _
+  private val inProcessManager = new InProcessJobManager
+  private def managers = Seq[Any](inProcessManager, commandLineManager)
+
+  /**
+   * If true, we will write out incremental job reports
+   */
+  private val INCREMENTAL_JOBS_REPORT = true
+
+  /**
+   * Holds the optional jobInfoReporter structure
+   */
+  private var jobInfoReporter: QJobsReporter = null
+
+  private class StatusCounts {
+    var pending = 0
+    var running = 0
+    var failed = 0
+    var done = 0
+  }
+  private val statusCounts = new StatusCounts
+
+  /**
+   * Final initialization step of this QGraph -- tell it runtime setting information
+   *
+   * The settings aren't necessarily available until after this QGraph object has been constructed, so
+   * this function must be called once the QGraphSettings have been filled in.
+   *
+   * @param settings QGraphSettings
+   */
+  def initializeWithSettings(settings: QGraphSettings) {
+    this.settings = settings
+    this.jobInfoReporter = createJobsReporter()
+  }
+
+  /**
+   * Adds a QScript created CommandLineFunction to the graph.
+   * @param command Function to add to the graph.
+   */
+  def add(command: QFunction) {
+    try {
+      runningLock.synchronized {
+        if (running) {
+          command.qSettings = settings.qSettings
+          command.freeze()
+          val inputFiles = command.inputs
+          var outputFiles = command.outputs
+          outputFiles :+= command.jobOutputFile
+          if (command.jobErrorFile != null)
+            outputFiles :+= command.jobErrorFile
+          val inputs = getQNode(inputFiles.sorted(fileOrdering))
+          val outputs = getQNode(outputFiles.sorted(fileOrdering))
+          addEdge(new FunctionEdge(command, inputs, outputs))
+        }
+      }
+    } catch {
+      case e: Exception =>
+        throw new QException("Error adding function: " + command, e)
+    }
+  }
+
+  /**
+   * Checks the functions for missing values and the graph for cyclic dependencies and then runs the functions in the graph.
+   */
+  def run() {
+    runningLock.synchronized {
+      if (running) {
+        org.broadinstitute.gatk.utils.io.IOUtils.checkTempDir(settings.qSettings.tempDirectory)
+        fillGraph()
+        val isReady = numMissingValues == 0
+
+        if (this.jobGraph.edgeSet.isEmpty) {
+          logger.warn("Nothing to run! Were any Functions added?")
+        } else if (settings.getStatus) {
+          logger.info("Checking pipeline status.")
+          logStatus()
+        } else if (this.dryRun) {
+          dryRunJobs()
+          if (running && isReady) {
+            logger.info("Dry run completed successfully!")
+            logger.info("Re-run with \"-run\" to execute the functions.")
+          }
+        } else if (isReady) {
+          logger.info("Running jobs.")
+          runJobs()
+        }
+
+        if (numMissingValues > 0) {
+          logger.error("Total missing values: " + numMissingValues)
+        }
+      }
+    }
+  }
+
+  private def fillGraph() {
+    logger.info("Generating graph.")
+    fill()
+    if (settings.graphvizFile != null)
+      renderGraph(settings.graphvizFile)
+    validate()
+
+    if (running && numMissingValues == 0) {
+      val scatterGathers = jobGraph.edgeSet.filter(edge => scatterGatherable(edge))
+      if (!scatterGathers.isEmpty) {
+        logger.info("Generating scatter gather jobs.")
+
+        var addedFunctions = Seq.empty[QFunction]
+        for (scatterGather <- scatterGathers) {
+          val functions = scatterGather.asInstanceOf[FunctionEdge]
+                  .function.asInstanceOf[ScatterGatherableFunction]
+                  .generateFunctions()
+          addedFunctions ++= functions
+        }
+
+        logger.info("Removing original jobs.")
+        this.jobGraph.removeAllEdges(scatterGathers)
+        prune()
+
+        logger.info("Adding scatter gather jobs.")
+        addedFunctions.foreach(function => if (running) this.add(function))
+
+        logger.info("Regenerating graph.")
+        fill()
+        val scatterGatherDotFile = if (settings.graphvizScatterGatherFile != null) settings.graphvizScatterGatherFile else settings.graphvizFile
+        if (scatterGatherDotFile != null)
+          renderGraph(scatterGatherDotFile)
+        validate()
+      }
+    }
+  }
+
+  private def scatterGatherable(edge: QEdge) = {
+    edge match {
+      case functionEdge: FunctionEdge => {
+        functionEdge.function match {
+          case scatterGather: ScatterGatherableFunction if (scatterGather.scatterGatherable) => true
+          case _ => false
+        }
+      }
+      case _ => false
+    }
+  }
+
+  /**
+   * Walks up the graph looking for the previous function edges.
+   * @param edge Graph edge to examine for the previous functions.
+   * @return A list of prior function edges.
+   */
+  private def previousFunctions(edge: QEdge): Seq[FunctionEdge] = {
+    var previous = Seq.empty[FunctionEdge]
+    val source = this.jobGraph.getEdgeSource(edge)
+    for (incomingEdge <- this.jobGraph.incomingEdgesOf(source)) {
+      incomingEdge match {
+
+        // Stop recursing when we find a function edge and return it
+        case functionEdge: FunctionEdge => previous :+= functionEdge
+
+        // For any other type of edge find the jobs preceding the edge
+        case edge: QEdge => previous ++= previousFunctions(edge)
+      }
+    }
+    previous
+  }
+
+  /**
+   * Walks up the graph looking for the next function edges.
+   * @param edge Graph edge to examine for the next functions.
+   * @return A list of prior function edges.
+   */
+  private def nextFunctions(edge: QEdge): Seq[FunctionEdge] = {
+    var next = Seq.empty[FunctionEdge]
+    val target = this.jobGraph.getEdgeTarget(edge)
+    for (outgoingEdge <- this.jobGraph.outgoingEdgesOf(target)) {
+      outgoingEdge match {
+
+        // Stop recursing when we find a function edge and return it
+        case functionEdge: FunctionEdge => next :+= functionEdge
+
+        // For any other type of edge find the jobs following the edge
+        case edge: QEdge => next ++= nextFunctions(edge)
+      }
+    }
+    next
+  }
+
+  /**
+   * Fills in the graph using mapping functions, then removes out of date
+   * jobs, then cleans up mapping functions and nodes that aren't need.
+   */
+  private def fill() {
+    fillIn()
+    prune()
+  }
+
+  /**
+   * Looks through functions with multiple inputs and outputs and adds mapping functions for single inputs and outputs.
+   */
+  private def fillIn() {
+    // clone since edgeSet is backed by the graph
+    asScalaSet(jobGraph.edgeSet).clone().foreach(edge => {
+      if (running) edge match {
+        case cmd: FunctionEdge => {
+          addCollectionOutputs(cmd.outputs)
+          addCollectionInputs(cmd.inputs)
+        }
+        case map: MappingEdge => /* do nothing for mapping edges */
+      }
+    })
+  }
+
+  private def getReadyJobs: Set[FunctionEdge] = {
+    jobGraph.edgeSet.filter{
+      case f: FunctionEdge =>
+        this.previousFunctions(f).forall(_.status == RunnerStatus.DONE) && f.status == RunnerStatus.PENDING
+      case _ => false
+    }.toSet.asInstanceOf[Set[FunctionEdge]]
+  }
+
+  /**
+   *  Removes mapping edges that aren't being used, and nodes that don't belong to anything.
+   */
+  private def prune() {
+    var pruning = true
+    while (pruning) {
+      pruning = false
+      val filler = jobGraph.edgeSet.filter(isFiller(_))
+      if (filler.size > 0) {
+        jobGraph.removeAllEdges(filler)
+        pruning = running
+      }
+    }
+
+    if (running) {
+      for (orphan <- jobGraph.vertexSet.filter(isOrphan(_))) {
+        jobGraph.removeVertex(orphan)
+        nodeMap -= orphan.files
+      }
+    }
+  }
+
+  /**
+   * Validates that the functions in the graph have no missing values and that there are no cycles.
+   */
+  private def validate() {
+    asScalaSet(jobGraph.edgeSet).foreach(
+      edge =>
+        if (running) edge match
+        {
+          case cmd: FunctionEdge =>
+            val missingFieldValues = cmd.function.missingFields
+            if (missingFieldValues.size > 0) {
+              numMissingValues += missingFieldValues.size
+              logger.error("Missing %s values for function: %s".format(missingFieldValues.size, cmd.function.description))
+              for (missing <- missingFieldValues)
+                logger.error("  " + missing)
+            }
+          case map: MappingEdge => /* do nothing for mapping edges */
+        }
+    )
+
+    val detector = new CycleDetector(jobGraph)
+    if (detector.detectCycles) {
+      logger.error("Cycles were detected in the graph:")
+      for (cycle <- detector.findCycles)
+        logger.error("  " + cycle)
+      throw new QException("Cycles were detected in the graph.")
+    }
+  }
+
+  /**
+   * Dry-runs the jobs by traversing the graph.
+   */
+  private def dryRunJobs() {
+    if (settings.startFromScratch)
+      logger.info("Will remove outputs from previous runs.")
+
+    updateGraphStatus(cleanOutputs = false)
+
+    var readyJobs = getReadyJobs
+    while (running && readyJobs.size > 0) {
+      logger.debug("+++++++")
+      foreachFunction(readyJobs.toSeq, edge => {
+        if (running) {
+          edge.myRunInfo.startTime = new Date()
+          edge.getRunInfo.exechosts = Utils.resolveHostname()
+          logEdge(edge)
+          edge.myRunInfo.doneTime = new Date()
+          edge.markAsDone()
+        }
+      })
+      readyJobs = getReadyJobs
+    }
+  }
+
+  private def logEdge(edge: FunctionEdge) {
+    logger.info("-------")
+    logger.info("%-8s %s".format(StringUtils.capitalize(edge.status.toString) + ":", edge.function.description))
+    if (logger.isDebugEnabled) {
+      logger.debug("Inputs:  " + edge.inputs)
+      logger.debug("Outputs: " + edge.outputs)
+      logger.debug("Done+:   " + edge.function.doneOutputs.filter(_.exists()))
+      logger.debug("Done-:   " + edge.function.doneOutputs.filterNot(_.exists()))
+      logger.debug("CmdDir:  " + edge.function.commandDirectory)
+      logger.debug("Temp?:   " + edge.function.isIntermediate)
+      logger.debug("Prev:    " +
+        (if (edge.resetFromStatus == null) "none" else StringUtils.capitalize(edge.resetFromStatus.toString)) +
+        " (reset = " + (edge.resetFromStatus != null && edge.resetFromStatus != edge.status) + ")" )
+    }
+    logger.info("Log:     " + edge.function.jobOutputFile.getAbsolutePath)
+    if (edge.function.jobErrorFile != null)
+      logger.info("Error:   " + edge.function.jobErrorFile.getAbsolutePath)
+  }
+
+  /**
+   * Logs job statuses by traversing the graph and looking for status-related files
+   */
+  private def logStatus() {
+    updateGraphStatus(cleanOutputs = false)
+    doStatus(status => logger.info(status))
+  }
+
+  /**
+   * Runs the jobs by traversing the graph.
+   */
+  private def runJobs() {
+    try {
+      if (settings.bsub)
+        settings.jobRunner = "Lsf706"
+      else if (settings.qsub)
+        settings.jobRunner = "GridEngine"
+      else if (settings.jobRunner == null)
+        settings.jobRunner = "Shell"
+      commandLineManager = commandLinePluginManager.createByName(settings.jobRunner)
+
+      for (mgr <- managers) {
+        if (mgr != null) {
+          val manager = mgr.asInstanceOf[JobManager[QFunction,JobRunner[QFunction]]]
+          manager.init()
+        }
+      }
+
+      if (settings.startFromScratch)
+        logger.info("Removing outputs from previous runs.")
+
+      updateGraphStatus(cleanOutputs = true)
+
+      var readyJobs = TreeSet.empty[FunctionEdge](functionOrdering)
+      readyJobs ++= getReadyJobs
+      runningJobs = Set.empty[FunctionEdge]
+      var lastRunningCheck = System.currentTimeMillis
+      var logNextStatusCounts = true
+      var startedJobsToEmail = Set.empty[FunctionEdge]
+
+      while (running && readyJobs.size + runningJobs.size > 0) {
+
+        var startedJobs = Set.empty[FunctionEdge]
+        var doneJobs = Set.empty[FunctionEdge]
+        var failedJobs = Set.empty[FunctionEdge]
+
+        while (running && readyJobs.size > 0 && !readyRunningCheck(lastRunningCheck)) {
+          val edge = readyJobs.head
+          edge.runner = newRunner(edge.function)
+          edge.start()
+          messengers.foreach(_.started(jobShortName(edge.function)))
+          startedJobs += edge
+          readyJobs -= edge
+          logNextStatusCounts = true
+        }
+
+        runningJobs ++= startedJobs
+        startedJobsToEmail ++= startedJobs
+        statusCounts.pending -= startedJobs.size
+        statusCounts.running += startedJobs.size
+
+        if (logNextStatusCounts)
+          logStatusCounts()
+        logNextStatusCounts = false
+
+        deleteCleanup(lastRunningCheck)
+
+        if (running && startedJobs.size > 0 && !readyRunningCheck(lastRunningCheck)) {
+          emailStartedJobs(startedJobsToEmail)
+          startedJobsToEmail = Set.empty[FunctionEdge]
+        }
+
+        if (readyJobs.size == 0 && runningJobs.size > 0) {
+          runningLock.synchronized {
+            if (running) {
+              val timeout = nextRunningCheck(lastRunningCheck)
+              if (timeout > 0)
+                runningLock.wait(timeout)
+            }
+          }
+        }
+
+        lastRunningCheck = System.currentTimeMillis
+        updateStatus()
+
+        runningJobs.foreach(edge => edge.status match {
+          case RunnerStatus.DONE => {
+            doneJobs += edge
+            messengers.foreach(_.done(jobShortName(edge.function)))
+          }
+          case RunnerStatus.FAILED => {
+            failedJobs += edge
+            messengers.foreach(_.exit(jobShortName(edge.function), edge.function.jobErrorLines.mkString("%n".format())))
+          }
+          case RunnerStatus.RUNNING => /* do nothing while still running */
+        })
+
+        runningJobs --= doneJobs
+        runningJobs --= failedJobs
+
+        startedJobsToEmail &~= failedJobs
+
+        addCleanup(doneJobs)
+
+        statusCounts.running -= doneJobs.size
+        statusCounts.running -= failedJobs.size
+        statusCounts.done += doneJobs.size
+        statusCounts.failed += failedJobs.size
+
+        if (doneJobs.size > 0 || failedJobs.size > 0)
+          logNextStatusCounts = true
+
+        if (running && failedJobs.size > 0) {
+          emailFailedJobs(failedJobs)
+          checkRetryJobs(failedJobs)
+        }
+
+        // incremental
+        if ( logNextStatusCounts && INCREMENTAL_JOBS_REPORT ) {
+          logger.info("Writing incremental jobs reports...")
+          writeJobsReport(plot = false)
+        }
+
+        readyJobs ++= getReadyJobs
+      }
+
+      logStatusCounts()
+      deleteCleanup(-1)
+    } catch {
+      case e: Throwable =>
+        logger.error("Uncaught error running jobs.", e)
+        throw e
+    } finally {
+      emailStatus()
+    }
+  }
+
+  private def readyRunningCheck(lastRunningCheck: Long) =
+    lastRunningCheck > 0 && nextRunningCheck(lastRunningCheck) <= 0
+
+  private def nextRunningCheck(lastRunningCheck: Long) =
+    ((30 * 1000L) - (System.currentTimeMillis - lastRunningCheck))
+
+  def formattedStatusCounts: String = {
+    "%d Pend, %d Run, %d Fail, %d Done".format(
+      statusCounts.pending, statusCounts.running, statusCounts.failed, statusCounts.done)
+  }
+
+  private def logStatusCounts() {
+    logger.info(formattedStatusCounts)
+  }
+
+  /**
+   * Updates the status of edges in the graph.
+   * @param cleanOutputs If true will delete outputs when setting edges to pending.
+   */
+  private def updateGraphStatus(cleanOutputs: Boolean) {
+    if (settings.startFromScratch)
+      foreachFunction(edge => edge.resetToPending(cleanOutputs))
+    else
+      traverseFunctions(edge => checkDone(edge, cleanOutputs))
+    traverseFunctions(edge => recheckDone(edge))
+  }
+
+  // TODO: Yet another field to add (with overloads) to QFunction?
+  private def jobShortName(function: QFunction): String = {
+    var name = function.analysisName
+    if (function.isInstanceOf[CloneFunction]) {
+      val cloneFunction = function.asInstanceOf[CloneFunction]
+      name += " %d of %d".format(cloneFunction.cloneIndex, cloneFunction.cloneCount)
+    }
+    name
+  }
+
+  /**
+   * First pass that checks if an edge is done or if it's an intermediate edge if it can be skipped.
+   * This function may modify the status of previous edges if it discovers that the edge passed in
+   * is dependent jobs that were previously marked as skipped.
+   * @param edge Edge to check to see if it's done or can be skipped.
+   * @param cleanOutputs If true will delete outputs when setting edges to pending.
+   */
+  private def checkDone(edge: FunctionEdge, cleanOutputs: Boolean) {
+    if (edge.function.isIntermediate) {
+      // By default we do not need to run intermediate edges.
+      // Mark any intermediate edges as skipped, if they're not already done.
+      if (edge.status != RunnerStatus.DONE)
+        edge.markAsSkipped()
+    } else {
+      val previous = this.previousFunctions(edge)
+      val isDone = edge.status == RunnerStatus.DONE &&
+              previous.forall(edge => edge.status == RunnerStatus.DONE || edge.status == RunnerStatus.SKIPPED)
+      if (!isDone) {
+        edge.resetToPending(cleanOutputs)
+        resetPreviousSkipped(edge, previous, cleanOutputs)
+      }
+    }
+  }
+
+  /**
+   * Second pass which
+   * a) Updates the status counts based on the function statuses
+   * b) Checks if the edge is a completed intermediate edge then adds it to the set of candidates for cleanup
+   * @param edge Edge to check to see if it's done or skipped.
+   */
+  private def recheckDone(edge: FunctionEdge) {
+    edge.status match {
+      case RunnerStatus.PENDING => statusCounts.pending += 1
+      case RunnerStatus.FAILED => statusCounts.failed += 1
+      case RunnerStatus.DONE => statusCounts.done += 1
+      case RunnerStatus.SKIPPED => statusCounts.done += 1
+    }
+    
+    if (edge.status == RunnerStatus.DONE || edge.status == RunnerStatus.SKIPPED) {
+      if (logger.isDebugEnabled)
+        logEdge(edge)
+      addCleanup(edge)
+    }
+  }
+
+  /**
+   * Checks if the functions should have their outptus removed after they finish running
+   * @param edges Functions to check
+   */
+  private def addCleanup(edges: Traversable[FunctionEdge]) {
+    edges.foreach(addCleanup(_))
+  }
+
+  /**
+   * Checks if the function should have their outputs removed after they finish running
+   * @param edge Function to check
+   */
+  private def addCleanup(edge: FunctionEdge) {
+    if (!settings.keepIntermediates)
+      if (edge.function.isIntermediate)
+        cleanupJobs += edge
+  }
+
+  /**
+   * Continues deleting the outputs of intermediate jobs that are no longer needed until it's time to recheck running status.
+   * @param lastRunningCheck The last time the status was checked.
+   */
+  private def deleteCleanup(lastRunningCheck: Long) {
+    var doneJobs = Set.empty[FunctionEdge]
+
+    for (edge <- cleanupJobs) {
+      val nextDone = nextFunctions(edge).forall(next => {
+        val status = next.status
+        (status == RunnerStatus.DONE || status == RunnerStatus.SKIPPED)
+      })
+
+      if (nextDone)
+        doneJobs += edge
+    }
+
+    for (edge <- doneJobs) {
+      if (running && !readyRunningCheck(lastRunningCheck)) {
+        logger.debug("Deleting intermediates:" + edge.function.description)
+        edge.function.deleteOutputs()
+        cleanupJobs -= edge
+      }
+    }
+  }
+
+  /**
+   * Returns the graph depth for the function.
+   * @param edge Function edge to get the edge for.
+   * @return the graph depth for the function.
+   */
+  private def graphDepth(edge: FunctionEdge): Int = {
+    if (edge.depth < 0) {
+      val previous = previousFunctions(edge)
+      if (previous.size == 0)
+        edge.depth = 0
+      else
+        edge.depth = previous.map(f => graphDepth(f)).max + 1
+    }
+    edge.depth
+  }
+
+  /**
+   * From the previous edges, resets any that are marked as skipped to pending.
+   * If those that are reset have skipped edges, those skipped edges are recursively also set
+   * to pending.
+   * Any edges after this edge are also reset to pending.
+   * @param edge Dependent edge.
+   * @param previous Previous edges that provide inputs to edge.
+   * @param cleanOutputs If true will clean up the output files when resetting jobs to pending.
+   */
+  private def resetPreviousSkipped(edge: FunctionEdge, previous: Seq[FunctionEdge], cleanOutputs: Boolean) {
+    val edges = previous.filter(_.status == RunnerStatus.SKIPPED) ++ this.nextFunctions(edge).filter(_.status != RunnerStatus.PENDING)
+    for (resetEdge <- edges) {
+      resetEdge.resetToPending(cleanOutputs)
+      resetPreviousSkipped(resetEdge, this.previousFunctions(resetEdge), cleanOutputs)
+    }
+  }
+
+  private def newRunner(f: QFunction) = {
+    f match {
+      case cmd: CommandLineFunction =>
+        commandLineManager.create(cmd)
+      case inProc: InProcessFunction =>
+        inProcessManager.create(inProc)
+      case _ =>
+        throw new QException("Unexpected function: " + f)
+    }
+  }
+
+  private def emailStartedJobs(started: Set[FunctionEdge]) {
+    if (settings.statusEmailTo.size > 0) {
+      val emailMessage = new EmailMessage
+      emailMessage.from = settings.statusEmailFrom
+      emailMessage.to = settings.statusEmailTo
+      emailMessage.subject = "Queue function: Started: " + settings.qSettings.runName
+      addStartedFunctions(emailMessage, started.toSeq)
+      emailMessage.trySend(settings.emailSettings)
+    }
+  }
+
+  private def emailFailedJobs(failed: Set[FunctionEdge]) {
+    if (settings.statusEmailTo.size > 0) {
+      val emailMessage = new EmailMessage
+      emailMessage.from = settings.statusEmailFrom
+      emailMessage.to = settings.statusEmailTo
+      emailMessage.subject = "Queue function: Failure: " + settings.qSettings.runName
+      addFailedFunctions(emailMessage, failed.toSeq)
+      emailMessage.trySend(settings.emailSettings)
+    }
+  }
+
+  private def checkRetryJobs(failed: Set[FunctionEdge]) {
+    if (settings.retries > 0) {
+      for (failedJob <- failed) {
+        if (failedJob.function.jobRestartable && failedJob.function.retries < settings.retries) {
+          failedJob.function.retries += 1
+          failedJob.function.setupRetry()
+          failedJob.resetToPending(cleanOutputs = true)
+          logger.info("Reset for retry attempt %d of %d: %s".format(
+            failedJob.function.retries, settings.retries, failedJob.function.description))
+          statusCounts.failed -= 1
+          statusCounts.pending += 1
+        } else {
+          logger.info("Giving up after retrying %d times: %s".format(
+            settings.retries, failedJob.function.description))
+        }
+      }
+    }
+  }
+
+  private def emailStatus() {
+    if (running && settings.statusEmailTo.size > 0) {
+      var failed = Seq.empty[FunctionEdge]
+      foreachFunction(edge => {
+        if (edge.status == RunnerStatus.FAILED) {
+          failed :+= edge
+        }
+      })
+
+      val emailMessage = new EmailMessage
+      emailMessage.from = settings.statusEmailFrom
+      emailMessage.to = settings.statusEmailTo
+      emailMessage.body = getStatus + nl
+      if (failed.size == 0) {
+        emailMessage.subject = "Queue run: Success: " + settings.qSettings.runName
+      } else {
+        emailMessage.subject = "Queue run: Failure: " + settings.qSettings.runName
+        addFailedFunctions(emailMessage, failed)
+      }
+      emailMessage.trySend(settings.emailSettings)
+    }
+  }
+
+  private def addStartedFunctions(emailMessage: EmailMessage, started: Seq[FunctionEdge]) {
+    if (emailMessage.body == null)
+      emailMessage.body = ""
+    emailMessage.body += """
+    |Started functions:
+    |
+    |%s
+    |""".stripMargin.trim.format(
+      started.map(edge => emailDescription(edge)).mkString(nl+nl))
+  }
+
+  private def addFailedFunctions(emailMessage: EmailMessage, failed: Seq[FunctionEdge]) {
+    val logs = failed.flatMap(edge => logFiles(edge))
+
+    if (emailMessage.body == null)
+      emailMessage.body = ""
+    emailMessage.body += """
+    |Failed functions:
+    |
+    |%s
+    |
+    |Logs:
+    |%s%n
+    |""".stripMargin.trim.format(
+      failed.map(edge => emailDescription(edge)).mkString(nl+nl),
+      logs.map(_.getAbsolutePath).mkString(nl))
+
+    emailMessage.attachments = logs
+  }
+
+  private def emailDescription(edge: FunctionEdge) = {
+    val description = new StringBuilder
+    if (settings.retries > 0)
+      description.append("Attempt %d of %d.%n".format(edge.function.retries + 1, settings.retries + 1))
+    description.append(edge.function.description)
+    description.toString()
+  }
+
+  private def logFiles(edge: FunctionEdge) = {
+    var failedOutputs = Seq.empty[File]
+    failedOutputs :+= edge.function.jobOutputFile
+    if (edge.function.jobErrorFile != null)
+      failedOutputs :+= edge.function.jobErrorFile
+    failedOutputs.filter(file => file != null && file.exists)
+  }
+
+  /**
+   * Tracks analysis status.
+   */
+  private class AnalysisStatus(val analysisName: String) {
+    val jobs = new GroupStatus
+    val scatter = new GroupStatus
+    val gather = new GroupStatus
+
+    def total = jobs.total + scatter.total + gather.total
+    def done = jobs.done + scatter.done + gather.done
+    def failed = jobs.failed + scatter.failed + gather.failed
+    def skipped = jobs.skipped + scatter.skipped + gather.skipped
+  }
+
+  /**
+   * Tracks status of a group of jobs.
+   */
+  private class GroupStatus {
+    var total = 0
+    var done = 0
+    var failed = 0
+    var skipped = 0
+  }
+
+  /**
+   * Gets job statuses by traversing the graph and looking for status-related files
+   */
+  private def getStatus = {
+    val buffer = new StringBuilder
+    doStatus(status => buffer.append(status).append(nl))
+    buffer.toString()
+  }
+
+  /**
+   * Gets job statuses by traversing the graph and looking for status-related files
+   */
+  private def doStatus(statusFunc: String => Unit) {
+    var statuses = Seq.empty[AnalysisStatus]
+    var maxWidth = 0
+    foreachFunction(edge => {
+      val name = edge.function.analysisName
+      if (name != null) {
+        updateAnalysisStatus(statuses.find(_.analysisName == name) match {
+          case Some(status) => status
+          case None =>
+            val status = new AnalysisStatus(name)
+            maxWidth = maxWidth max name.length
+            statuses :+= status
+            status
+        }, edge)
+      }
+    })
+
+    statuses.foreach(status => {
+      val total = status.total
+      val done = status.done
+      val failed = status.failed
+      val skipped = status.skipped
+      val jobsTotal = status.jobs.total
+      val jobsDone = status.jobs.done
+      val gatherTotal = status.gather.total
+      val gatherDone = status.gather.done
+
+      var summaryStatus = RunnerStatus.PENDING
+      if (failed > 0)
+        summaryStatus = RunnerStatus.FAILED
+      else if (gatherDone == gatherTotal && jobsDone == jobsTotal)
+        summaryStatus = RunnerStatus.DONE
+      else if (done + skipped == total)
+        summaryStatus = RunnerStatus.SKIPPED
+      else if (done > 0)
+        summaryStatus = RunnerStatus.RUNNING
+
+      var info = ("%-" + maxWidth + "s %7s")
+              .format(status.analysisName, "[" + summaryStatus.toString + "]")
+      if (status.jobs.total > 1) {
+        info += formatGroupStatus(status.jobs)
+      }
+      if (status.scatter.total + status.gather.total > 1) {
+        info += formatGroupStatus(status.scatter, "s:")
+        info += formatGroupStatus(status.gather, "g:")
+      }
+      statusFunc(info)
+    })
+  }
+
+  /**
+   * Updates a status map with scatter/gather status information (e.g. counts)
+   */
+  private def updateAnalysisStatus(stats: AnalysisStatus, edge: FunctionEdge) {
+    if (edge.function.isInstanceOf[ScatterFunction]) {
+      updateGroupStatus(stats.scatter, edge)
+    } else if (edge.function.isInstanceOf[CloneFunction]) {
+      updateGroupStatus(stats.scatter, edge)
+    } else if (edge.function.isInstanceOf[GatherFunction]) {
+      updateGroupStatus(stats.gather, edge)
+    } else {
+      updateGroupStatus(stats.jobs, edge)
+    }
+  }
+
+  private def updateGroupStatus(groupStatus: GroupStatus, edge: FunctionEdge) {
+    groupStatus.total += 1
+    edge.status match {
+      case RunnerStatus.DONE => groupStatus.done += 1
+      case RunnerStatus.FAILED => groupStatus.failed += 1
+      case RunnerStatus.SKIPPED => groupStatus.skipped += 1
+      /* can't tell the difference between pending and running right now! */
+      case RunnerStatus.PENDING =>
+      case RunnerStatus.RUNNING =>
+    }
+  }
+
+  /**
+   * Formats a status into nice strings
+   */
+  private def formatGroupStatus(stats: GroupStatus, prefix: String = "") = {
+    " %s%dt/%dd/%df".format(
+      prefix, stats.total, stats.done, stats.failed)
+  }
+
+  /**
+   *   Creates a new graph where if new edges are needed (for cyclic dependency checking) they can be automatically created using a generic MappingFunction.
+   * @return A new graph
+   */
+  private def newGraph = new SimpleDirectedGraph[QNode, QEdge](new EdgeFactory[QNode, QEdge] {
+    def createEdge(input: QNode, output: QNode) = new MappingEdge(input, output)})
+
+  private def getQNode(files: Seq[File]) = {
+    nodeMap.get(files) match {
+      case Some(node) =>
+        node
+      case None =>
+        if (nextNodeId % 100 == 0)
+          logger.debug("adding QNode: " + nextNodeId)
+        val node = new QNode(nextNodeId, files)
+        nextNodeId += 1
+        jobGraph.addVertex(node)
+        nodeMap += files -> node
+        node
+    }
+  }
+
+  private def addEdge(edge: QEdge) {
+    jobGraph.removeAllEdges(edge.inputs, edge.outputs)
+    jobGraph.addEdge(edge.inputs, edge.outputs, edge)
+  }
+
+  /**
+   * Adds input mappings between the node's files and the individual files.
+   * @param inputs Input node.
+   */
+  private def addCollectionInputs(inputs: QNode) {
+    if (inputs.files.size > 1)
+      for (file <- inputs.files) {
+        if (running) {
+          val input = getQNode(Seq(file))
+          if (!jobGraph.containsEdge(input, inputs))
+            addEdge(new MappingEdge(input, inputs))
+        }
+      }
+  }
+
+  /**
+   * Adds output mappings between the node's files and the individual files.
+   * @param outputs Output node.
+   */
+  private def addCollectionOutputs(outputs: QNode) {
+    if (outputs.files.size > 1)
+      for (file <- outputs.files) {
+        if (running) {
+          val output = getQNode(Seq(file))
+          if (!jobGraph.containsEdge(outputs, output))
+            addEdge(new MappingEdge(outputs, output))
+        }
+      }
+  }
+
+  /**
+   * Returns true if the edge is mapping edge that is not needed because it does
+   * not direct input or output from a user generated CommandLineFunction.
+   * @param edge Edge to check.
+   * @return true if the edge is not needed in the graph.
+   */
+  private def isFiller(edge: QEdge) = {
+    edge match {
+      case mapping: MappingEdge =>
+        jobGraph.outgoingEdgesOf(jobGraph.getEdgeTarget(edge)).size == 0 &&
+          jobGraph.incomingEdgesOf(jobGraph.getEdgeSource(edge)).size == 0
+      case _ => false
+    }
+  }
+
+  /**
+   * Returns true if the node is not connected to any edges.
+   * @param node Node (set of files) to check.
+   * @return true if this set of files is not needed in the graph.
+   */
+  private def isOrphan(node: QNode) = {
+    jobGraph.incomingEdgesOf(node).size == 0 &&
+      jobGraph.outgoingEdgesOf(node).size == 0
+  }
+
+  /**
+   * Utility function for running a method over all function edges.
+   * @param f Function to run for each FunctionEdge.
+   */
+  private def foreachFunction(f: (FunctionEdge) => Unit) {
+    foreachFunction(jobGraph.edgeSet.toSeq.filter(_.isInstanceOf[FunctionEdge]).asInstanceOf[Seq[FunctionEdge]], f)
+  }
+
+  /**
+   * Utility function for running a method over a list of function edges.
+   * @param edges Edges to traverse.
+   * @param f Function to run for each FunctionEdge.
+   */
+  private def foreachFunction(edges: Seq[FunctionEdge], f: (FunctionEdge) => Unit) {
+    edges.sorted(functionOrdering).foreach(edge => if (running) f(edge))
+  }
+
+  /**
+   * Utility function returning all function edges.
+   */
+  private def getFunctionEdges: Seq[FunctionEdge] = {
+    jobGraph.edgeSet.toSeq.filter(_.isInstanceOf[FunctionEdge]).asInstanceOf[Seq[FunctionEdge]]
+  }
+
+  /**
+   * Utility function for running a method over all functions, but traversing the nodes in order of dependency.
+   * @param f Function to run for each FunctionEdge.
+   */
+  private def traverseFunctions(f: (FunctionEdge) => Unit) {
+    val iterator = new TopologicalOrderIterator(this.jobGraph)
+    iterator.addTraversalListener(new TraversalListenerAdapter[QNode, QEdge] {
+      override def edgeTraversed(event: EdgeTraversalEvent[QNode, QEdge]) {
+        if (running) {
+          event.getEdge match {
+            case functionEdge: FunctionEdge => f(functionEdge)
+            case map: MappingEdge => /* do nothing for mapping functions */
+          }
+        }
+      }
+    })
+    iterator.foreach(_ => {})
+  }
+
+  /**
+   * Outputs the graph to a .gv DOT file.
+   * http://www.graphviz.org/Documentation.php
+   * http://en.wikipedia.org/wiki/DOT_language
+   * @param file Path to output the .gv file.
+   */
+  private def renderGraph(file: java.io.File) {
+    val vertexIDProvider = new org.jgrapht.ext.VertexNameProvider[QNode] {
+      def getVertexName(node: QNode) = node.id.toString
+    }
+
+    val vertexLabelProvider = new org.jgrapht.ext.VertexNameProvider[QNode] {
+      // The QGraph fills in with single file nodes between nodes that contain more than one file.
+      // We only need to display the single element nodes.
+      def getVertexName(node: QNode) = {
+        if (!node.files.isEmpty && node.files.tail.isEmpty)
+          node.files.head.getName
+        else
+          ""
+      }
+    }
+
+    val edgeNameProvider = new org.jgrapht.ext.EdgeNameProvider[QEdge] {
+      def getEdgeName(edge: QEdge) = {
+        if (edge.shortDescription != null)
+          edge.shortDescription.replace("\"", "\\\"")
+        else
+          ""
+      }
+    }
+
+    val exporter = new DOTExporter(vertexIDProvider, vertexLabelProvider, edgeNameProvider)
+
+    val out = new OutputStreamWriter(FileUtils.openOutputStream(file))
+    try {
+      exporter.export(out, jobGraph)
+    } finally {
+      IOUtils.closeQuietly(out)
+    }
+  }
+
+  /**
+   * Returns true if no functions have missing values nor a status of failed.
+   * @return true if no functions have missing values nor a status of failed.
+   */
+  def success = {
+    if (numMissingValues > 0) {
+      false
+    } else if (this.dryRun) {
+      true
+    } else {
+      !this.jobGraph.edgeSet.exists(edge => {
+        if (edge.isInstanceOf[FunctionEdge]) {
+          val status = edge.asInstanceOf[FunctionEdge].status
+          (status == RunnerStatus.PENDING || status == RunnerStatus.RUNNING || status == RunnerStatus.FAILED)
+        } else {
+          false
+        }
+      })
+    }
+  }
+
+  def logFailed() {
+    foreachFunction(edge => {
+      if (edge.status == RunnerStatus.FAILED)
+        logEdge(edge)
+    })
+  }
+
+
+  private def updateStatus() {
+    val runners = runningJobs.map(_.runner)
+    for (mgr <- managers) {
+      if (mgr != null) {
+        val manager = mgr.asInstanceOf[JobManager[QFunction,JobRunner[QFunction]]]
+        val managerRunners = runners
+          .filter(runner => manager.runnerType.isAssignableFrom(runner.getClass))
+          .asInstanceOf[Set[JobRunner[QFunction]]]
+        if (managerRunners.size > 0)
+          try {
+            val updatedRunners = manager.updateStatus(managerRunners)
+            for (runner <- managerRunners.diff(updatedRunners)) {
+              runner.checkUnknownStatus()
+            }
+          } catch {
+            case e: Throwable => /* ignore */
+          }
+      }
+    }
+  }
+
+  /**
+   * Create the jobsReporter for this QGraph, based on the settings data.
+   *
+   * Must be called after settings has been initialized properly
+   *
+   * @return
+   */
+  private def createJobsReporter(): QJobsReporter = {
+    val jobStringName = if (settings.jobReportFile != null)
+      settings.jobReportFile
+    else
+      settings.qSettings.runName + ".jobreport.txt"
+
+    val reportFile = org.broadinstitute.gatk.utils.io.IOUtils.absolute(settings.qSettings.runDirectory, jobStringName)
+
+    val pdfFile = if ( settings.run )
+      Some(org.broadinstitute.gatk.utils.io.IOUtils.absolute(settings.qSettings.runDirectory, FilenameUtils.removeExtension(jobStringName) + ".pdf"))
+    else
+      None
+
+    new QJobsReporter(settings.disableJobReport, reportFile, pdfFile)
+  }
+
+  /**
+   * Write, if possible, the jobs report
+   */
+  def writeJobsReport(plot: Boolean = true) {
+    // note: the previous logic didn't write the job report if the system was shutting down, but I don't
+    // see any reason not to write the job report
+    if ( jobInfoReporter != null )
+      jobInfoReporter.write(this, plot)
+  }
+
+  /**
+   * Returns true if the graph was shutdown instead of exiting on its own.
+   */
+  def isShutdown = !running
+
+  def getFunctionsAndStatus: Map[QFunction, JobRunInfo] = {
+    getFunctionEdges.map(edge => (edge.function, edge.getRunInfo)).toMap
+  }
+
+  /**
+   * Kills any forked jobs still running.
+   */
+  def shutdown() {
+    // Signal the main thread to shutdown.
+    running = false
+
+    // Try and wait for the thread to finish and exit normally.
+    runningLock.synchronized {
+      runningLock.notify()
+    }
+
+    // Start killing jobs.
+    runningLock.synchronized {
+      val runners = runningJobs.map(_.runner)
+      runningJobs = Set.empty[FunctionEdge]
+      for (mgr <- managers) {
+        if (mgr != null) {
+          val manager = mgr.asInstanceOf[JobManager[QFunction,JobRunner[QFunction]]]
+          try {
+            val managerRunners = runners
+              .filter(runner => manager.runnerType.isAssignableFrom(runner.getClass))
+              .asInstanceOf[Set[JobRunner[QFunction]]]
+            if (managerRunners.size > 0)
+              try {
+                manager.tryStop(managerRunners)
+              } catch {
+                case e: Throwable => /* ignore */
+              }
+            for (runner <- managerRunners) {
+              try {
+                runner.cleanup()
+              } catch {
+                case e: Throwable => /* ignore */
+              }
+            }
+          } finally {
+            try {
+              manager.exit()
+            } catch {
+              case e: Throwable => /* ignore */
+            }
+          }
+        }
+      }
+    }
+  }
+}
diff --git a/public/gatk-queue/src/main/scala/org/broadinstitute/gatk/queue/engine/QGraphSettings.scala b/public/gatk-queue/src/main/scala/org/broadinstitute/gatk/queue/engine/QGraphSettings.scala
new file mode 100644
index 0000000..49dace9
--- /dev/null
+++ b/public/gatk-queue/src/main/scala/org/broadinstitute/gatk/queue/engine/QGraphSettings.scala
@@ -0,0 +1,85 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.queue.engine
+
+import java.io.File
+import org.broadinstitute.gatk.queue.QSettings
+import org.broadinstitute.gatk.queue.util.{EmailSettings, SystemUtils}
+import org.broadinstitute.gatk.utils.commandline.{Advanced, ArgumentCollection, Argument}
+
+/**
+ * Command line options for a QGraph.
+ */
+class QGraphSettings {
+  @Argument(fullName="run_scripts", shortName="run", doc="Run QScripts.  Without this flag set only performs a dry run.", required=false)
+  var run = false
+
+  @Argument(fullName="job_runner", shortName="jobRunner", doc="Use the specified job runner to dispatch command line jobs", required=false)
+  var jobRunner: String = _
+
+  @Argument(fullName="bsub", shortName="bsub", doc="Equivalent to -jobRunner Lsf706", required=false)
+  var bsub = false
+
+  @Argument(fullName="qsub", shortName="qsub", doc="Equivalent to -jobRunner GridEngine", required=false)
+  var qsub = false
+
+  @Argument(fullName="status",shortName="status",doc="Get status of jobs for the qscript",required=false)
+  var getStatus = false
+
+  @Argument(fullName="retry_failed", shortName="retry", doc="Retry the specified number of times after a command fails.  Defaults to no retries.", required=false)
+  var retries = 0
+
+  @Argument(fullName="start_from_scratch", shortName="startFromScratch", doc="Runs all command line functions even if the outputs were previously output successfully.", required=false)
+  var startFromScratch = false
+
+  @Argument(fullName="keep_intermediate_outputs", shortName="keepIntermediates", doc="After a successful run keep the outputs of any Function marked as intermediate.", required=false)
+  var keepIntermediates = false
+
+  @Argument(fullName="status_email_to", shortName="statusTo", doc="Email address to send emails to upon completion or on error.", required=false)
+  var statusEmailTo: Seq[String] = Nil
+
+  @Argument(fullName="status_email_from", shortName="statusFrom", doc="Email address to send emails from upon completion or on error.", required=false)
+  var statusEmailFrom: String = System.getProperty("user.name") + "@" + SystemUtils.mailName
+
+  @Argument(fullName="graphviz", shortName="gv", doc="Outputs the queue graph to a Graphviz .gv file. See: http://www.graphviz.org/Documentation.php", required=false)
+  var graphvizFile: File = _
+
+  @Argument(fullName="graphviz_scatter_gather", shortName="gvsg", doc="Outputs the scatter/gather queue graph to a Graphviz .gv file.  Otherwise overwrites the --graphviz file.", required=false)
+  var graphvizScatterGatherFile: File = _
+
+  @Argument(fullName="jobReport", shortName="jobReport", doc="File where we will write the Queue job report", required=false)
+  var jobReportFile: String = _
+
+  @Advanced
+  @Argument(fullName="disableJobReport", shortName="disabpleJobReport", doc="If provided, we will not create a job report", required=false)
+  var disableJobReport: Boolean = false
+
+  @ArgumentCollection
+  val emailSettings = new EmailSettings
+
+  @ArgumentCollection
+  val qSettings = new QSettings
+}
diff --git a/public/gatk-queue/src/main/scala/org/broadinstitute/gatk/queue/engine/QNode.scala b/public/gatk-queue/src/main/scala/org/broadinstitute/gatk/queue/engine/QNode.scala
new file mode 100644
index 0000000..5751a72
--- /dev/null
+++ b/public/gatk-queue/src/main/scala/org/broadinstitute/gatk/queue/engine/QNode.scala
@@ -0,0 +1,45 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.queue.engine
+
+import java.io.File
+
+/**
+ * Represents a state between QFunctions the directed acyclic QGraph
+ * @param files The list of files that represent this node state ordered by file name.
+ */
+class QNode (val id: Int, val files: Seq[File]) {
+  override def equals(obj: Any) = {
+    obj match {
+      case other: QNode => this.id == other.id
+      case _ => false
+    }
+  }
+
+  override def hashCode = id
+
+  override def toString = files.toString()
+}
diff --git a/public/gatk-queue/src/main/scala/org/broadinstitute/gatk/queue/engine/QStatusMessenger.scala b/public/gatk-queue/src/main/scala/org/broadinstitute/gatk/queue/engine/QStatusMessenger.scala
new file mode 100644
index 0000000..14e4082
--- /dev/null
+++ b/public/gatk-queue/src/main/scala/org/broadinstitute/gatk/queue/engine/QStatusMessenger.scala
@@ -0,0 +1,41 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.queue.engine
+
+import org.broadinstitute.gatk.queue.util.RemoteFile
+
+/**
+ * Plugin to sends QStatus messages
+ */
+trait QStatusMessenger {
+  def started()
+  def done(inputs: Seq[_], outputs: Seq[_])
+  def exit(message: String)
+
+  def started(job: String)
+  def done(job: String)
+  def exit(job: String, message: String)
+}
diff --git a/public/gatk-queue/src/main/scala/org/broadinstitute/gatk/queue/engine/RunnerStatus.scala b/public/gatk-queue/src/main/scala/org/broadinstitute/gatk/queue/engine/RunnerStatus.scala
new file mode 100644
index 0000000..93c9fde
--- /dev/null
+++ b/public/gatk-queue/src/main/scala/org/broadinstitute/gatk/queue/engine/RunnerStatus.scala
@@ -0,0 +1,34 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.queue.engine
+
+object RunnerStatus extends Enumeration {
+  val PENDING = Value("pending")
+  val RUNNING = Value("running")
+  val FAILED = Value("failed")
+  val DONE = Value("done")
+  val SKIPPED = Value("skipped")
+}
diff --git a/public/gatk-queue/src/main/scala/org/broadinstitute/gatk/queue/engine/drmaa/DrmaaJobManager.scala b/public/gatk-queue/src/main/scala/org/broadinstitute/gatk/queue/engine/drmaa/DrmaaJobManager.scala
new file mode 100644
index 0000000..02cf34e
--- /dev/null
+++ b/public/gatk-queue/src/main/scala/org/broadinstitute/gatk/queue/engine/drmaa/DrmaaJobManager.scala
@@ -0,0 +1,62 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.queue.engine.drmaa
+
+import org.broadinstitute.gatk.queue.function.CommandLineFunction
+import org.broadinstitute.gatk.queue.engine.CommandLineJobManager
+import org.broadinstitute.gatk.utils.jna.drmaa.v1_0.JnaSessionFactory
+import org.ggf.drmaa.Session
+
+/**
+ * Runs jobs using DRMAA
+ */
+class DrmaaJobManager extends CommandLineJobManager[DrmaaJobRunner] {
+  protected var session: Session = _
+
+  protected def newSession() = new JnaSessionFactory().getSession
+  protected def contact = null
+
+  override def init() {
+    session = newSession()
+    session.init(contact)
+  }
+
+  override def exit() {
+    session.exit()
+  }
+
+  def runnerType = classOf[DrmaaJobRunner]
+  def create(function: CommandLineFunction) = new DrmaaJobRunner(session, function)
+
+  override def updateStatus(runners: Set[DrmaaJobRunner]) = {
+    var updatedRunners = Set.empty[DrmaaJobRunner]
+    runners.foreach(runner => if (runner.updateJobStatus()) {updatedRunners += runner})
+    updatedRunners
+  }
+  override def tryStop(runners: Set[DrmaaJobRunner]) {
+    runners.foreach(_.tryStop())
+  }
+}
diff --git a/public/gatk-queue/src/main/scala/org/broadinstitute/gatk/queue/engine/drmaa/DrmaaJobRunner.scala b/public/gatk-queue/src/main/scala/org/broadinstitute/gatk/queue/engine/drmaa/DrmaaJobRunner.scala
new file mode 100644
index 0000000..aa19bfa
--- /dev/null
+++ b/public/gatk-queue/src/main/scala/org/broadinstitute/gatk/queue/engine/drmaa/DrmaaJobRunner.scala
@@ -0,0 +1,169 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.queue.engine.drmaa
+
+import org.broadinstitute.gatk.queue.QException
+import org.broadinstitute.gatk.queue.util.{Logging,Retry}
+import org.broadinstitute.gatk.queue.function.CommandLineFunction
+import org.broadinstitute.gatk.queue.engine.{RunnerStatus, CommandLineJobRunner}
+import org.ggf.drmaa._
+import java.util.{Date, Collections}
+
+/**
+ * Runs jobs using DRMAA.
+ */
+class DrmaaJobRunner(val session: Session, val function: CommandLineFunction) extends CommandLineJobRunner with Logging {
+  /** Job Id of the currently executing job. */
+  var jobId: String = _
+  override def jobIdString = jobId
+
+  // Set the display name to < 512 characters of the description
+  // NOTE: Not sure if this is configuration specific?
+  protected val jobNameLength = 500
+  protected val jobNameFilter = """[^A-Za-z0-9_]"""
+  protected def functionNativeSpec = function.jobNativeArgs.mkString(" ")
+
+  def start() {
+    session.synchronized {
+      val drmaaJob: JobTemplate = session.createJobTemplate
+
+      drmaaJob.setJobName(function.jobRunnerJobName.take(jobNameLength).replaceAll(jobNameFilter, "_"))
+
+      // Set the current working directory
+      drmaaJob.setWorkingDirectory(function.commandDirectory.getPath)
+
+      // Set the output file for stdout
+      drmaaJob.setOutputPath(":" + function.jobOutputFile.getPath)
+
+      // If the error file is set specify the separate output for stderr
+      // Otherwise join with stdout
+      if (function.jobErrorFile != null) {
+        drmaaJob.setErrorPath(":" + function.jobErrorFile.getPath)
+      } else {
+        drmaaJob.setJoinFiles(true)
+      }
+
+      if(!function.wallTime.isEmpty)
+    	  drmaaJob.setHardWallclockTimeLimit(function.wallTime.get)      
+      
+      drmaaJob.setNativeSpecification(functionNativeSpec)
+
+      // Instead of running the function.commandLine, run "sh <jobScript>"
+      drmaaJob.setRemoteCommand("sh")
+      drmaaJob.setArgs(Collections.singletonList(jobScript.toString))
+
+      // Allow advanced users to update the request via QFunction.updateJobRun()
+      updateJobRun(drmaaJob)
+
+      updateStatus(RunnerStatus.RUNNING)
+
+      // Start the job and store the id so it can be killed in tryStop
+      try {
+        Retry.attempt(() => {
+          try {
+            jobId = session.runJob(drmaaJob)
+          } catch {
+            case de: DrmaaException => throw new QException("Unable to submit job: " + de.getLocalizedMessage)
+          }
+        }, 1, 5, 10)
+      } finally {
+        // Prevent memory leaks
+        session.deleteJobTemplate(drmaaJob)
+      }
+      logger.info("Submitted job id: " + jobId)
+    }
+  }
+
+  def updateJobStatus() = {
+    session.synchronized {
+      var returnStatus: RunnerStatus.Value = null
+
+      try {
+        val jobStatus = session.getJobProgramStatus(jobId);
+        jobStatus match {
+          case Session.QUEUED_ACTIVE => returnStatus = RunnerStatus.RUNNING
+          case Session.DONE =>
+            val jobInfo: JobInfo = session.wait(jobId, Session.TIMEOUT_NO_WAIT)
+
+            // Update jobInfo
+            def convertDRMAATime(key: String): Date = {
+              val v = jobInfo.getResourceUsage.get(key)
+              if ( v != null ) new Date(v.toString.toDouble.toLong * 1000) else null;
+            }
+            if ( jobInfo.getResourceUsage != null ) {
+              getRunInfo.startTime = convertDRMAATime("start_time")
+              getRunInfo.doneTime = convertDRMAATime("end_time")
+              getRunInfo.exechosts = "unknown"
+            }
+
+            if ((jobInfo.hasExited && jobInfo.getExitStatus != 0)
+                || jobInfo.hasSignaled
+                || jobInfo.wasAborted)
+              returnStatus = RunnerStatus.FAILED
+            else
+              returnStatus = RunnerStatus.DONE
+          case Session.FAILED => returnStatus = RunnerStatus.FAILED
+          case Session.UNDETERMINED => logger.warn("Unable to determine status of job id " + jobId)
+          case _ => returnStatus = RunnerStatus.RUNNING
+        }
+      } catch {
+        // getJobProgramStatus will throw an exception once wait has run, as the
+        // job will be reaped.  If the status is currently DONE or FAILED, return
+        // the status.
+        case de: DrmaaException =>
+          if (lastStatus == RunnerStatus.DONE || lastStatus == RunnerStatus.FAILED)
+            returnStatus = lastStatus
+          else
+            logger.warn("Unable to determine status of job id " + jobId, de)
+      }
+
+      if (returnStatus != null) {
+        updateStatus(returnStatus)
+        true
+      } else {
+        false
+      }
+    }
+  }
+
+  def tryStop() {
+    session.synchronized {
+      // Assumes that after being set the job may be
+      // reassigned but will not be reset back to null
+      if (jobId != null) {
+        try {
+          // Stop runners. SIGTERM(15) is preferred to SIGKILL(9).
+          // Only way to send SIGTERM is for the Sys Admin set the terminate_method
+          // resource of the designated queue to SIGTERM
+          session.control(jobId, Session.TERMINATE)
+        } catch {
+          case e: Exception =>
+            logger.error("Unable to kill job " + jobId, e)
+        }
+      }
+    }
+  }
+}
diff --git a/public/gatk-queue/src/main/scala/org/broadinstitute/gatk/queue/engine/gridengine/GridEngineJobManager.scala b/public/gatk-queue/src/main/scala/org/broadinstitute/gatk/queue/engine/gridengine/GridEngineJobManager.scala
new file mode 100644
index 0000000..eb60cb3
--- /dev/null
+++ b/public/gatk-queue/src/main/scala/org/broadinstitute/gatk/queue/engine/gridengine/GridEngineJobManager.scala
@@ -0,0 +1,33 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.queue.engine.gridengine
+
+import org.broadinstitute.gatk.queue.function.CommandLineFunction
+import org.broadinstitute.gatk.queue.engine.drmaa.DrmaaJobManager
+
+class GridEngineJobManager extends DrmaaJobManager {
+  override def create(function: CommandLineFunction) = new GridEngineJobRunner(session, function)
+}
diff --git a/public/gatk-queue/src/main/scala/org/broadinstitute/gatk/queue/engine/gridengine/GridEngineJobRunner.scala b/public/gatk-queue/src/main/scala/org/broadinstitute/gatk/queue/engine/gridengine/GridEngineJobRunner.scala
new file mode 100644
index 0000000..b21f43b
--- /dev/null
+++ b/public/gatk-queue/src/main/scala/org/broadinstitute/gatk/queue/engine/gridengine/GridEngineJobRunner.scala
@@ -0,0 +1,88 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.queue.engine.gridengine
+
+import org.broadinstitute.gatk.queue.util.Logging
+import org.broadinstitute.gatk.queue.function.CommandLineFunction
+import org.broadinstitute.gatk.queue.engine.drmaa.DrmaaJobRunner
+import org.ggf.drmaa.Session
+
+/**
+ * Runs jobs on a Grid Engine compute cluster.
+ */
+class GridEngineJobRunner(session: Session, function: CommandLineFunction) extends DrmaaJobRunner(session, function) with Logging {
+  // Grid Engine disallows certain characters from being in job names.
+  // This replaces all illegal characters with underscores
+  protected override val jobNameFilter = """[\s/:,@\\*?]"""
+  protected override val minRunnerPriority = -1023
+  protected override val maxRunnerPriority = 0
+
+  override protected def functionNativeSpec = {
+    // Force the remote environment to inherit local environment settings
+    var nativeSpec: String = "-V"
+
+    // If a project name is set specify the project name
+    if (function.jobProject != null)
+      nativeSpec += " -P " + function.jobProject
+
+    // If the job queue is set specify the job queue
+    if (function.jobQueue != null)
+      nativeSpec += " -q " + function.jobQueue
+
+    // If the resident set size is requested pass on the memory request
+    // mem_free is the standard, but may also be virtual_free or even not available
+    if (function.qSettings.residentRequestParameter != null && function.residentRequest.isDefined)
+      nativeSpec += " -l %s=%dM".format(function.qSettings.residentRequestParameter, function.residentRequest.map(_ * 1024).get.ceil.toInt)
+
+    // If the resident set size limit is defined specify the memory limit
+    if (function.residentLimit.isDefined)
+      nativeSpec += " -l h_rss=%dM".format(function.residentLimit.map(_ * 1024).get.ceil.toInt)
+
+    // If more than 1 core is requested, set the proper request
+    // if we aren't being jerks and just stealing cores (previous behavior)
+    if ( function.nCoresRequest.getOrElse(1) > 1 ) {
+      if ( function.qSettings.dontRequestMultipleCores )
+        logger.warn("Sending multicore job %s to farm without requesting appropriate number of cores (%d)".format(
+          function.shortDescription, function.nCoresRequest.get))
+      else
+        nativeSpec += " -pe %s %d".format(function.qSettings.parallelEnvironmentName, function.nCoresRequest.get)
+    }
+
+    // Pass on any job resource requests
+    nativeSpec += function.jobResourceRequests.map(" -l " + _).mkString
+
+    // Pass on any job environment names
+    nativeSpec += function.jobEnvironmentNames.map(" -pe " + _).mkString
+
+    // If the priority is set specify the priority
+    val priority = functionPriority
+    if (priority.isDefined)
+      nativeSpec += " -p " + priority.get
+
+    logger.debug("Native spec is: %s".format(nativeSpec))
+    (nativeSpec + " " + super.functionNativeSpec).trim()
+  }
+}
diff --git a/public/gatk-queue/src/main/scala/org/broadinstitute/gatk/queue/engine/lsf/Lsf706JobManager.scala b/public/gatk-queue/src/main/scala/org/broadinstitute/gatk/queue/engine/lsf/Lsf706JobManager.scala
new file mode 100644
index 0000000..dbe2536
--- /dev/null
+++ b/public/gatk-queue/src/main/scala/org/broadinstitute/gatk/queue/engine/lsf/Lsf706JobManager.scala
@@ -0,0 +1,40 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.queue.engine.lsf
+
+import org.broadinstitute.gatk.queue.function.CommandLineFunction
+import org.broadinstitute.gatk.queue.engine.CommandLineJobManager
+
+/**
+ * Creates and stops Lsf706JobRunners
+ */
+class Lsf706JobManager extends CommandLineJobManager[Lsf706JobRunner] {
+  def runnerType = classOf[Lsf706JobRunner]
+  def create(function: CommandLineFunction) = new Lsf706JobRunner(function)
+
+  override def updateStatus(runners: Set[Lsf706JobRunner]) = { Lsf706JobRunner.updateStatus(runners) }
+  override def tryStop(runners: Set[Lsf706JobRunner]) { Lsf706JobRunner.tryStop(runners) }
+}
diff --git a/public/gatk-queue/src/main/scala/org/broadinstitute/gatk/queue/engine/lsf/Lsf706JobRunner.scala b/public/gatk-queue/src/main/scala/org/broadinstitute/gatk/queue/engine/lsf/Lsf706JobRunner.scala
new file mode 100644
index 0000000..eeb82a3
--- /dev/null
+++ b/public/gatk-queue/src/main/scala/org/broadinstitute/gatk/queue/engine/lsf/Lsf706JobRunner.scala
@@ -0,0 +1,421 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.queue.engine.lsf
+
+import org.broadinstitute.gatk.queue.function.CommandLineFunction
+import org.broadinstitute.gatk.queue.util._
+import org.broadinstitute.gatk.queue.QException
+import org.broadinstitute.gatk.utils.jna.lsf.v7_0_6.{LibLsf, LibBat}
+import org.broadinstitute.gatk.utils.Utils
+import org.broadinstitute.gatk.utils.jna.clibrary.LibC
+import org.broadinstitute.gatk.utils.jna.lsf.v7_0_6.LibBat.{submitReply, submit}
+import org.broadinstitute.gatk.queue.engine.{RunnerStatus, CommandLineJobRunner}
+import java.util.regex.Pattern
+import java.lang.StringBuffer
+import java.util.Date
+import com.sun.jna.{Pointer, Structure, StringArray, NativeLong}
+import com.sun.jna.ptr.IntByReference
+
+/**
+ * Runs jobs on an LSF compute cluster.
+ */
+class Lsf706JobRunner(val function: CommandLineFunction) extends CommandLineJobRunner with Logging {
+
+  // Run the static initializer for Lsf706JobRunner
+  Lsf706JobRunner
+
+  /** Job Id of the currently executing job. */
+  private var jobId = -1L
+  override def jobIdString = jobId.toString
+
+  protected override val minRunnerPriority = 1
+  protected override val maxRunnerPriority = Lsf706JobRunner.maxUserPriority
+
+  private val selectString = new StringBuffer()
+  private val usageString = new StringBuffer()
+  private val requestString = new StringBuffer()
+  private val spanString = new StringBuffer()
+
+  /**
+   * Dispatches the function on the LSF cluster.
+   */
+  def start() {
+    Lsf706JobRunner.lsfLibLock.synchronized {
+
+      parseResourceRequest()
+
+      val request = new submit
+      for (i <- 0 until LibLsf.LSF_RLIM_NLIMITS)
+        request.rLimits(i) = LibLsf.DEFAULT_RLIMIT;
+
+      request.jobName = function.jobRunnerJobName.take(LibBat.MAX_JOB_NAME_LEN)
+      request.options |= LibBat.SUB_JOB_NAME
+
+      // Set the output file for stdout
+      request.outFile = function.jobOutputFile.getPath
+      request.options |= LibBat.SUB_OUT_FILE
+
+      // Set the current working directory
+      request.cwd = function.commandDirectory.getPath
+      request.options3 |= LibBat.SUB3_CWD
+
+      // If the error file is set specify the separate output for stderr
+      if (function.jobErrorFile != null) {
+        request.errFile = function.jobErrorFile.getPath
+        request.options |= LibBat.SUB_ERR_FILE
+      }
+
+      // If the job queue is set specify the job queue
+      if (function.jobQueue != null) {
+        request.queue = function.jobQueue
+        request.options |= LibBat.SUB_QUEUE
+      }
+
+      // If the resident set size is requested pass on the memory request
+      if (function.residentRequest.isDefined) {
+        val memInUnits = Lsf706JobRunner.convertUnits(function.residentRequest.get)
+        appendRequest("select", selectString, "&&", "mem>%d".format(memInUnits))
+        appendRequest("rusage", usageString, ",", "mem=%d".format(memInUnits))
+      }
+
+      //
+      // Request multiple cores on the same host.  If nCoresRequest > 1, and we
+      // aren't being jerks and stealing cores, set numProcessors and maxNumProcessors
+      // and the span[host=1] parameters to get us exactly the right number of
+      // cores on a single host
+      //
+      if ( function.nCoresRequest.getOrElse(1) > 1 ) {
+        if ( function.qSettings.dontRequestMultipleCores )
+          logger.warn("Sending multicore job %s to farm without requesting appropriate number of cores (%d)".format(
+            function.shortDescription, function.nCoresRequest.get))
+        else {
+          request.numProcessors = function.nCoresRequest.get
+          request.maxNumProcessors = request.numProcessors
+          appendRequest("span", spanString, ",", "hosts=1")
+        }
+      }
+
+      val resReq = getResourceRequest
+      if (resReq.length > 0) {
+        request.resReq = resReq
+        request.options |= LibBat.SUB_RES_REQ
+      }
+
+      // If the resident set size limit is defined specify the memory limit
+      if (function.residentLimit.isDefined) {
+        val memInUnits = Lsf706JobRunner.convertUnits(function.residentLimit.get)
+        request.rLimits(LibLsf.LSF_RLIMIT_RSS) = memInUnits
+      }
+
+      // If the priority is set (user specified Int) specify the priority
+      val priority = functionPriority
+      if (priority.isDefined) {
+        request.userPriority = priority.get
+        request.options2 |= LibBat.SUB2_JOB_PRIORITY
+      }
+
+      // Set the project to either the function or LSF default
+      val project = if (function.jobProject != null) function.jobProject else Lsf706JobRunner.defaultProject
+      if (project != null) {
+        request.projectName = project
+        request.options |= LibBat.SUB_PROJECT_NAME
+      }
+
+      // Set the esub names based on the job envorinment names
+      if (!function.jobEnvironmentNames.isEmpty) {
+        val argv = Array("", "-a", function.jobEnvironmentNames.mkString(" "))
+        val setOptionResult = LibBat.setOption_(argv.length, new StringArray(argv), "a:", request, ~0, ~0, ~0, null);
+        if (setOptionResult == -1)
+          throw new QException("setOption_() returned -1 while setting esub");
+      }
+
+      if(!function.wallTime.isEmpty)
+        request.rLimits(LibLsf.LSF_RLIMIT_RUN) = function.wallTime.get.toInt
+      else
+        // LSF specific: get the max runtime for the jobQueue and pass it for this job
+        request.rLimits(LibLsf.LSF_RLIMIT_RUN) = Lsf706JobRunner.getRlimitRun(function.jobQueue)
+
+      // Run the command as sh <jobScript>
+      request.command = "sh " + jobScript
+
+      // Allow advanced users to update the request via QFunction.updateJobRun()
+      updateJobRun(request)
+
+      updateStatus(RunnerStatus.RUNNING)
+      Retry.attempt(() => {
+        val reply = new submitReply
+        jobId = LibBat.lsb_submit(request, reply)
+        if (jobId < 0)
+          throw new QException(LibBat.lsb_sperror("Unable to submit job"))
+      }, 1, 5, 10)
+      logger.info("Submitted LSF job id: " + jobId)
+    }
+  }
+
+  override def checkUnknownStatus() {
+    // TODO: Need a second pass through either of the two archive logs using lsb_geteventrecbyline() for disappeared jobs.
+    // Can also tell if we wake up and the last time we saw status was greater than lsb_parameterinfo().cleanPeriod
+    // LSB_SHAREDIR/cluster_name/logdir/lsb.acct (man bacct)
+    // LSB_SHAREDIR/cluster_name/logdir/lsb.events (man bhist)
+    logger.debug("Job Id %s status / exitStatus / exitInfo: ??? / ??? / ???".format(jobId))
+    super.checkUnknownStatus()
+  }
+
+  private def parseResourceRequest() {
+    requestString.setLength(0)
+    selectString.setLength(0)
+    usageString.setLength(0)
+    spanString.setLength(0)
+
+    requestString.append(function.jobResourceRequests.mkString(" "))
+    extractSection(requestString, "select", selectString)
+    extractSection(requestString, "rusage", usageString)
+    extractSection(requestString, "span", spanString)
+  }
+
+  private def extractSection(requestString: StringBuffer, section: String, sectionString: StringBuffer) {
+    val pattern = Pattern.compile(section + "\\s*\\[[^\\]]+\\]\\s*");
+    val matcher = pattern.matcher(requestString.toString)
+    if (matcher.find()) {
+      sectionString.setLength(0)
+      sectionString.append(matcher.group().trim())
+
+      val sb = new StringBuffer
+      matcher.appendReplacement(sb, "")
+      matcher.appendTail(sb)
+
+      requestString.setLength(0)
+      requestString.append(sb)
+    }
+  }
+
+  private def appendRequest(section: String, sectionString: StringBuffer, separator: String, request: String) {
+    if (sectionString.length() == 0)
+      sectionString.append(section).append("[").append(request).append("]")
+    else
+      sectionString.insert(sectionString.length() - 1, separator + request)
+  }
+
+  private def getResourceRequest = "%s %s %s %s".format(selectString, usageString, spanString, requestString).trim()
+}
+
+object Lsf706JobRunner extends Logging {
+  private val lsfLibLock = new Object
+  private val SIGTERM = 15
+
+  /** Number of seconds for a non-normal exit status before we give up on expecting LSF to retry the function. */
+  private val retryExpiredSeconds = 5 * 60
+
+  /**
+   * Initialize the Lsf library.
+   */
+  private val (defaultQueue, defaultProject, maxUserPriority) = {
+    lsfLibLock.synchronized {
+      if (LibBat.lsb_init("Queue") < 0)
+        throw new QException(LibBat.lsb_sperror("lsb_init() failed"))
+
+      val parameterInfo = LibBat.lsb_parameterinfo(null, null, 0);
+      var defaultQueue: String = parameterInfo.defaultQueues
+      val defaultProject = parameterInfo.defaultProject
+      val maxUserPriority = parameterInfo.maxUserPriority
+
+      if (defaultQueue != null && defaultQueue.indexOf(' ') > 0)
+        defaultQueue = defaultQueue.split(" ")(0)
+
+      (defaultQueue, defaultProject, maxUserPriority)
+    }
+  }
+
+  /**
+   * Bulk updates job statuses.
+   * @param runners Runners to update.
+   * @return runners which were updated.
+   */
+  def updateStatus(runners: Set[Lsf706JobRunner]) = {
+    var updatedRunners = Set.empty[Lsf706JobRunner]
+
+    Lsf706JobRunner.lsfLibLock.synchronized {
+      val result = LibBat.lsb_openjobinfo(0L, null, null, null, null, LibBat.ALL_JOB)
+      if (result < 0) {
+        logger.error(LibBat.lsb_sperror("Unable to check LSF job info"))
+      } else {
+        try {
+          val more = new IntByReference(result)
+          while (more.getValue > 0) {
+            val jobInfo = LibBat.lsb_readjobinfo(more)
+            if (jobInfo == null) {
+              logger.error(LibBat.lsb_sperror("Unable to read LSF job info"))
+              more.setValue(0)
+            } else {
+              runners.find(runner => runner.jobId == jobInfo.jobId) match {
+                case Some(runner) =>
+                  updateRunnerStatus(runner, jobInfo)
+                  updatedRunners += runner
+                case None => /* not our job */
+              }
+            }
+          }
+        } finally {
+          LibBat.lsb_closejobinfo()
+        }
+      }
+    }
+
+    updatedRunners
+  }
+
+  private def updateRunnerStatus(runner: Lsf706JobRunner, jobInfo: LibBat.jobInfoEnt) {
+    val jobStatus = jobInfo.status
+    val exitStatus = jobInfo.exitStatus
+    val exitInfo = jobInfo.exitInfo
+    val endTime = jobInfo.endTime
+
+    logger.debug("Job Id %s status / exitStatus / exitInfo: 0x%02x / 0x%02x / 0x%02x".format(runner.jobId, jobStatus, exitStatus, exitInfo))
+
+    def updateRunInfo() {
+      // the platform LSF startTimes are in seconds, not milliseconds, so convert to the java convention
+      runner.getRunInfo.startTime = new Date(jobInfo.startTime.longValue * 1000)
+      runner.getRunInfo.doneTime = new Date(jobInfo.endTime.longValue * 1000)
+
+      val exHostsList =
+        if (jobInfo.numExHosts != 1) {
+          // this is necessary because
+          val exHostsString = "multipleHosts_" + jobInfo.numExHosts
+          logger.debug("numExHosts = " + jobInfo.numExHosts + " != 1 for job " + runner.jobId + ", cannot safely get exhosts, setting to " + exHostsString)
+          List(exHostsString)
+        } else {
+          jobInfo.exHosts.getStringArray(0).toSeq
+        }
+
+      //logger.warn("exHostsList = " + exHostsList)
+      val exHosts = exHostsList.reduceLeft(_ + "," + _)
+      //logger.warn("exHosts = " + exHosts)
+      runner.getRunInfo.exechosts = exHosts
+    }
+
+    runner.updateStatus(
+      if (Utils.isFlagSet(jobStatus, LibBat.JOB_STAT_DONE)) {
+        // Done successfully.
+        updateRunInfo()
+        RunnerStatus.DONE
+      } else if (Utils.isFlagSet(jobStatus, LibBat.JOB_STAT_EXIT) && !willRetry(exitInfo, endTime)) {
+        // Exited function that (probably) won't be retried.
+        updateRunInfo()
+        RunnerStatus.FAILED
+      } else {
+        // Note that we still saw the job in the system.
+        RunnerStatus.RUNNING
+      }
+    )
+  }
+
+  /**
+   * Returns true if LSF is expected to retry running the function.
+   * @param exitInfo The reason the job exited.
+   * @param endTime THe time the job exited.
+   * @return true if LSF is expected to retry running the function.
+   */
+  private def willRetry(exitInfo: Int, endTime: NativeLong) = {
+    exitInfo match {
+      case LibBat.EXIT_NORMAL => false
+      case _ => {
+        val seconds = LibC.difftime(LibC.time(null), endTime)
+        (seconds <= retryExpiredSeconds)
+      }
+    }
+  }
+
+  /**
+   * Tries to stop any running jobs.
+   * @param runners Runners to stop.
+   */
+  def tryStop(runners: Set[Lsf706JobRunner]) {
+    lsfLibLock.synchronized {
+      // lsb_killbulkjobs does not seem to forward SIGTERM,
+      // only SIGKILL, so send the Ctrl-C (SIGTERM) one by one.
+      for (runner <- runners.filterNot(_.jobId < 0)) {
+        try {
+          if (LibBat.lsb_signaljob(runner.jobId, SIGTERM) < 0)
+            logger.error(LibBat.lsb_sperror("Unable to kill job " + runner.jobId))
+        } catch {
+          case e: Exception=>
+            logger.error("Unable to kill job " + runner.jobId, e)
+        }
+      }
+    }
+  }
+
+  /** The run limits for each queue. */
+  private var queueRlimitRun = Map.empty[String,Int]
+
+  /**
+   * Returns the run limit in seconds for the queue.
+   * If the queue name is null returns the length of the default queue.
+   * @param queueName Name of the queue or null for the default queue.
+   * @return the run limit in seconds for the queue.
+   */
+  private def getRlimitRun(queueName: String) = {
+    lsfLibLock.synchronized {
+      val queue = if (queueName == null) defaultQueue else queueName
+      queueRlimitRun.get(queue) match {
+        case Some(limit) => limit
+        case None =>
+          // Cache miss.  Go get the run limits from LSF.
+          val queues = new StringArray(Array(queue))
+          val numQueues = new IntByReference(1)
+          val queueInfo = LibBat.lsb_queueinfo(queues, numQueues, null, null, 0)
+          if (queueInfo == null)
+            throw new QException(LibBat.lsb_sperror("Unable to get LSF queue info for queue: " + queue))
+          val limit = queueInfo.rLimits(LibLsf.LSF_RLIMIT_RUN)
+          queueRlimitRun += queue -> limit
+          limit
+      }
+    }
+  }
+
+  private lazy val unitDivisor: Double = {
+    lsfLibLock.synchronized {
+      val unitsParam: Array[LibLsf.config_param] = new LibLsf.config_param().toArray(2).asInstanceOf[Array[LibLsf.config_param]]
+      unitsParam(0).paramName = "LSF_UNIT_FOR_LIMITS"
+
+      Structure.autoWrite(unitsParam.asInstanceOf[Array[Structure]])
+      if (LibLsf.ls_readconfenv(unitsParam(0), null) != 0)
+        throw new QException(LibBat.lsb_sperror("ls_readconfenv() failed"))
+      Structure.autoRead(unitsParam.asInstanceOf[Array[Structure]])
+
+      unitsParam(0).paramValue match {
+        case "MB" => 1 / 1024D
+        case "GB" => 1D
+        case "TB" => 1024D
+        case "PB" => 1024D * 1024
+        case "EB" => 1024D * 1024 * 1024
+        case null => 1 / 1024D
+      }
+    }
+  }
+
+  private def convertUnits(gb: Double) = (gb / unitDivisor).ceil.toInt
+}
diff --git a/public/gatk-queue/src/main/scala/org/broadinstitute/gatk/queue/engine/pbsengine/PbsEngineJobManager.scala b/public/gatk-queue/src/main/scala/org/broadinstitute/gatk/queue/engine/pbsengine/PbsEngineJobManager.scala
new file mode 100644
index 0000000..fb68231
--- /dev/null
+++ b/public/gatk-queue/src/main/scala/org/broadinstitute/gatk/queue/engine/pbsengine/PbsEngineJobManager.scala
@@ -0,0 +1,33 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.queue.engine.pbsengine
+
+import org.broadinstitute.gatk.queue.function.CommandLineFunction
+import org.broadinstitute.gatk.queue.engine.drmaa.DrmaaJobManager
+
+class PbsEngineJobManager extends DrmaaJobManager {
+  override def create(function: CommandLineFunction) = new PbsEngineJobRunner(session, function)
+}
diff --git a/public/gatk-queue/src/main/scala/org/broadinstitute/gatk/queue/engine/pbsengine/PbsEngineJobRunner.scala b/public/gatk-queue/src/main/scala/org/broadinstitute/gatk/queue/engine/pbsengine/PbsEngineJobRunner.scala
new file mode 100644
index 0000000..092152f
--- /dev/null
+++ b/public/gatk-queue/src/main/scala/org/broadinstitute/gatk/queue/engine/pbsengine/PbsEngineJobRunner.scala
@@ -0,0 +1,98 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.queue.engine.pbsengine
+
+import org.broadinstitute.gatk.queue.util.Logging
+import org.broadinstitute.gatk.queue.function.CommandLineFunction
+import org.broadinstitute.gatk.queue.engine.drmaa.DrmaaJobRunner
+import org.ggf.drmaa.Session
+
+/**
+ * Runs jobs on a PBS/Torque Engine compute cluster.
+ * NB - THIS FILE HAS BEEN MODIFIED from the original code
+ * of the GridEngine package
+ */
+class PbsEngineJobRunner(session: Session, function: CommandLineFunction) extends DrmaaJobRunner(session, function) with Logging {
+  // Pbs Engine disallows certain characters from being in job names.
+  // This replaces all illegal characters with underscores
+  protected override val jobNameFilter = """[\n\t\r/:,@\\*?]"""
+  protected override val minRunnerPriority = -1023
+  protected override val maxRunnerPriority = 0
+
+  override protected def functionNativeSpec = {
+  
+  	// create nativeSpec variable
+  		var nativeSpec: String = ""
+
+    // If a project name is set specify the project name
+    if (function.jobProject != null)
+      nativeSpec += " -P " + function.jobProject
+
+    // If the job queue is set specify the job queue
+    if (function.jobQueue != null)
+      nativeSpec += " -q " + function.jobQueue
+
+    // If the resident set size is requested pass on the memory request
+    // mem_free is the standard, but may also be virtual_free or even not available
+    
+    if (function.qSettings.residentRequestParameter != null && function.residentRequest.isDefined)
+      nativeSpec += " -l %s=%dM".format(function.qSettings.residentRequestParameter, function.residentRequest.map(_ * 1024).get.ceil.toInt)
+
+    // If the resident set size limit is defined specify the memory limit
+    if (function.residentLimit.isDefined)
+      nativeSpec += " -l mem=%dM".format(function.residentLimit.map(_ * 1024).get.ceil.toInt)
+
+    // If more than 1 core is requested, set the proper request
+    // the cores will be requested as part of a single node
+    
+    if ( function.nCoresRequest.getOrElse(1) > 1 ) {
+      if ( function.qSettings.dontRequestMultipleCores )
+        logger.warn("Sending multicore job %s to farm without requesting appropriate number of cores (%d)".format(
+          function.shortDescription, function.nCoresRequest.get))
+      else
+        nativeSpec += " -l nodes=1:ppn=%d".format(function.nCoresRequest.get)
+    }
+
+    // Pass on any job resource requests
+    // NB: blank because resource requests in PBS can be preceded by different
+    // arguments, i.e. -l but also -o or -j if they are not exactly "resources" strictly speaking
+    // therefore the user will add them in the request, i.e. -jobResReq "-j oe"
+    // but this will allow more flexibility in setting the options for PBS jobs on different Clusters
+    
+    nativeSpec += function.jobResourceRequests.map(" " + _).mkString
+
+    // Pass on any job environment names
+    nativeSpec += function.jobEnvironmentNames.map(" " + _).mkString
+
+    // If the priority is set specify the priority
+    val priority = functionPriority
+    if (priority.isDefined)
+      nativeSpec += " -p " + priority.get
+
+    logger.debug("Native spec is: %s".format(nativeSpec))
+    (nativeSpec + " " + super.functionNativeSpec).trim()
+  }
+}
diff --git a/public/gatk-queue/src/main/scala/org/broadinstitute/gatk/queue/engine/shell/ShellJobManager.scala b/public/gatk-queue/src/main/scala/org/broadinstitute/gatk/queue/engine/shell/ShellJobManager.scala
new file mode 100644
index 0000000..5645590
--- /dev/null
+++ b/public/gatk-queue/src/main/scala/org/broadinstitute/gatk/queue/engine/shell/ShellJobManager.scala
@@ -0,0 +1,35 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.queue.engine.shell
+
+import org.broadinstitute.gatk.queue.function.CommandLineFunction
+import org.broadinstitute.gatk.queue.engine.CommandLineJobManager
+
+class ShellJobManager extends CommandLineJobManager[ShellJobRunner] {
+  def runnerType = classOf[ShellJobRunner]
+  def create(function: CommandLineFunction) = new ShellJobRunner(function)
+  override def tryStop(runners: Set[ShellJobRunner]) { runners.foreach(_.tryStop()) }
+}
diff --git a/public/gatk-queue/src/main/scala/org/broadinstitute/gatk/queue/engine/shell/ShellJobRunner.scala b/public/gatk-queue/src/main/scala/org/broadinstitute/gatk/queue/engine/shell/ShellJobRunner.scala
new file mode 100644
index 0000000..327be22
--- /dev/null
+++ b/public/gatk-queue/src/main/scala/org/broadinstitute/gatk/queue/engine/shell/ShellJobRunner.scala
@@ -0,0 +1,91 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.queue.engine.shell
+
+import org.broadinstitute.gatk.queue.function.CommandLineFunction
+import org.broadinstitute.gatk.queue.engine.{RunnerStatus, CommandLineJobRunner}
+import java.util.Date
+import org.broadinstitute.gatk.utils.Utils
+import org.broadinstitute.gatk.utils.runtime.{ProcessSettings, OutputStreamSettings, ProcessController}
+
+/**
+ * Runs jobs one at a time locally
+ * @param function Command to run.
+ */
+class ShellJobRunner(val function: CommandLineFunction) extends CommandLineJobRunner {
+  // Controller on the thread that started the job
+  private var controller: ProcessController = null
+
+  /**
+   * Runs the function on the local shell.
+   */
+  def start() {
+    val commandLine = Array("sh", jobScript.getAbsolutePath)
+    val stdoutSettings = new OutputStreamSettings
+    val stderrSettings = new OutputStreamSettings
+    val mergeError = (function.jobErrorFile == null)
+
+    stdoutSettings.setOutputFile(function.jobOutputFile, true)
+    if (function.jobErrorFile != null)
+      stderrSettings.setOutputFile(function.jobErrorFile, true)
+
+    if (logger.isDebugEnabled) {
+      stdoutSettings.printStandard(true)
+      stderrSettings.printStandard(true)
+    }
+
+    val processSettings = new ProcessSettings(
+      commandLine, mergeError, function.commandDirectory, null,
+      null, stdoutSettings, stderrSettings)
+
+    updateJobRun(processSettings)
+
+    getRunInfo.startTime = new Date()
+    getRunInfo.exechosts = Utils.resolveHostname()
+    updateStatus(RunnerStatus.RUNNING)
+    controller = ProcessController.getThreadLocal
+    val exitStatus = controller.exec(processSettings).getExitValue
+    getRunInfo.doneTime = new Date()
+    updateStatus(if (exitStatus == 0) RunnerStatus.DONE else RunnerStatus.FAILED)
+  }
+
+  /**
+   * Possibly invoked from a shutdown thread, find and
+   * stop the controller from the originating thread
+   */
+  def tryStop() {
+    // Assumes that after being set the job may be
+    // reassigned but will not be reset back to null
+    if (controller != null) {
+      try {
+        controller.tryDestroy()
+      } catch {
+        case e: Exception =>
+          logger.error("Unable to kill shell job: " + function.description, e)
+      }
+    }
+  }
+}
diff --git a/public/gatk-queue/src/main/scala/org/broadinstitute/gatk/queue/function/CommandLineFunction.scala b/public/gatk-queue/src/main/scala/org/broadinstitute/gatk/queue/function/CommandLineFunction.scala
new file mode 100644
index 0000000..e1cb7d0
--- /dev/null
+++ b/public/gatk-queue/src/main/scala/org/broadinstitute/gatk/queue/function/CommandLineFunction.scala
@@ -0,0 +1,341 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.queue.function
+
+import org.broadinstitute.gatk.queue.util._
+import org.broadinstitute.gatk.utils.commandline.Argument
+
+/**
+ * A command line that will be run in a pipeline.
+ */
+trait CommandLineFunction extends QFunction with Logging {
+  def commandLine: String
+
+  /** Setting the wall time request for DRMAA / run limit for LSF */
+  var wallTime: Option[Long] = None
+  
+  /** Upper memory limit */
+  @Argument(doc="Memory limit", required=false)
+  var memoryLimit: Option[Double] = None
+
+  /** Resident memory limit */
+  @Argument(doc="Resident memory limit", required=false)
+  var residentLimit: Option[Double] = None
+
+  /** Resident memory request */
+  @Argument(doc="Resident memory request", required=false)
+  var residentRequest: Option[Double] = None
+
+  /** the number of SMP cores this job wants */
+  var nCoresRequest: Option[Int] = None
+
+  /** Job project to run the command */
+  var jobProject: String = _
+
+  /** Job queue to run the command */
+  var jobQueue: String = _
+
+  /** Native arguments to pass to the job runner */
+  var jobNativeArgs: Seq[String] = Nil
+
+  /** Native arguments to pass to the job runner */
+  var jobResourceRequests: Seq[String] = Nil
+
+  /** Environment names to pass to the job runner */
+  var jobEnvironmentNames: Seq[String] = Nil
+
+  override def copySettingsTo(function: QFunction) {
+    super.copySettingsTo(function)
+    function match {
+      case commandLineFunction: CommandLineFunction =>
+        if(commandLineFunction.wallTime.isEmpty)
+          commandLineFunction.wallTime = this.wallTime
+        
+        if (commandLineFunction.memoryLimit.isEmpty)
+          commandLineFunction.memoryLimit = this.memoryLimit
+
+        if (commandLineFunction.residentLimit.isEmpty)
+          commandLineFunction.residentLimit = this.residentLimit
+
+        if (commandLineFunction.residentRequest.isEmpty)
+          commandLineFunction.residentRequest = this.residentRequest
+
+        if (commandLineFunction.nCoresRequest.isEmpty)
+          commandLineFunction.nCoresRequest = this.nCoresRequest
+
+        if (commandLineFunction.jobProject == null)
+          commandLineFunction.jobProject = this.jobProject
+
+        if (commandLineFunction.jobQueue == null)
+          commandLineFunction.jobQueue = this.jobQueue
+
+        if (commandLineFunction.jobNativeArgs.isEmpty)
+          commandLineFunction.jobNativeArgs = this.jobNativeArgs
+
+        if (commandLineFunction.jobResourceRequests.isEmpty)
+          commandLineFunction.jobResourceRequests = this.jobResourceRequests
+
+        if (commandLineFunction.jobEnvironmentNames.isEmpty)
+          commandLineFunction.jobEnvironmentNames = this.jobEnvironmentNames
+
+      case _ => /* ignore */
+    }
+  }
+
+  /**
+   * Returns set of directories required to run the command.
+   * @return Set of directories required to run the command.
+   */
+  def jobDirectories = outputDirectories ++ inputs.map(_.getParentFile)
+
+  override def description = commandLine
+
+  /**
+   * Sets all field values.
+   */
+  override def freezeFieldValues() {
+   
+    if(wallTime.isEmpty)
+      wallTime = qSettings.jobWalltime
+    
+    if (jobQueue == null)
+      jobQueue = qSettings.jobQueue
+
+    if (jobProject == null)
+      jobProject = qSettings.jobProject
+
+    if (jobNativeArgs.isEmpty)
+      jobNativeArgs = qSettings.jobNativeArgs
+
+    if (jobResourceRequests.isEmpty)
+      jobResourceRequests = qSettings.jobResourceRequests
+
+    if (jobEnvironmentNames.isEmpty)
+      jobEnvironmentNames = qSettings.jobEnvironmentNames
+
+    if (memoryLimit.isEmpty)
+      memoryLimit = qSettings.memoryLimit
+
+    if (residentLimit.isEmpty)
+      residentLimit = qSettings.residentLimit
+
+    if (residentRequest.isEmpty)
+      residentRequest = qSettings.residentRequest
+
+    // the default value is 1 core
+    if (nCoresRequest.isEmpty)
+      nCoresRequest = Some(1)
+
+    if (residentRequest.isEmpty)
+      residentRequest = memoryLimit
+
+    if (residentLimit.isEmpty || residentLimit == residentRequest)
+      residentLimit = residentRequest.map(residentLimitBuffer)
+
+    super.freezeFieldValues()
+  }
+
+  /**
+   * @return A function that decides how much memory cushion to add to the residentRequest to create the residentLimit
+   */
+  def residentLimitBuffer: (Double => Double) = (1.2 * _)
+
+  /**
+   * Safely construct a full required command-line argument with consistent quoting, whitespace separation, etc.
+   *
+   * @param prefix Prefix to insert before the argument value (eg., "-f")
+   * @param param The argument value itself
+   * @param suffix Suffix to append after the argument value
+   * @param spaceSeparated If true, insert a space between the prefix, param, and suffix
+   * @param escape If true, quote the generated argument to avoid interpretation by the shell
+   * @param format Format String used to convert param to a String
+   * @return The combined and formatted argument, surrounded by whitespace
+   */
+  protected def required( prefix: String, param: Any, suffix: String = "", spaceSeparated: Boolean = true,
+                          escape: Boolean = true, format: String = "%s" ): String = {
+    " %s ".format(formatArgument(prefix, param, suffix, spaceSeparated, escape, format))
+  }
+
+  /**
+   * Safely construct a one-token required command-line argument with quoting
+   *
+   * @param param The command-line argument value
+   * @return The argument value quoted and surrounded by whitespace
+   */
+  protected def required( param: Any ): String = {
+    required("", param)
+  }
+
+  /**
+   * Safely construct a one-token required command-line argument, and specify whether you want quoting
+   *
+   * @param param The command-line argument value
+   * @param escape If true, quote the generated argument to avoid interpretation by the shell
+   * @return The argument value, quoted if quoting was requested, and surrounded by whitespace
+   */
+  protected def required( param: Any, escape: Boolean ): String = {
+    required("", param, escape=escape)
+  }
+
+  /**
+   * Safely construct a full optional command-line argument with consistent quoting, whitespace separation, etc.
+   * If the argument has no value, returns an empty String.
+   *
+   * @param prefix Prefix to insert before the argument value (eg., "-f")
+   * @param param The argument value itself (if null/empty, the method returns empty String)
+   * @param suffix Suffix to append after the argument value
+   * @param spaceSeparated If true, insert a space between the prefix, param, and suffix
+   * @param escape If true, quote the generated argument to avoid interpretation by the shell
+   * @param format Format String used to convert param to a String
+   * @return The combined and formatted argument, surrounded by whitespace, or an empty String
+   *         if the argument has no value
+   */
+  protected def optional( prefix: String, param: Any, suffix: String = "", spaceSeparated: Boolean = true,
+                          escape: Boolean = true, format: String = "%s" ): String = {
+    if ( hasValue(param) ) " %s ".format(formatArgument(prefix, param, suffix, spaceSeparated, escape, format)) else ""
+  }
+
+  /**
+   * Safely construct a one-token optional command-line argument with quoting.
+   * If the argument has no value, returns an empty String.
+   *
+   * @param param The command-line argument value
+   * @return The argument value quoted and surrounded by whitespace, or an empty String
+   *         if the argument has no value
+   */
+  protected def optional( param: Any ): String = {
+    optional("", param)
+  }
+
+  /**
+   * Safely construct a one-token conditional command-line argument. If the provided condition
+   * is false, an empty String is returned.
+   *
+   * @param condition The condition to check
+   * @param param The command-line argument value
+   * @param escape If true, quote the generated argument to avoid interpretation by the shell
+   * @param format Format String used to convert param to a String
+   * @return The command-line argument value, quoted if quoting was requested and surrounded
+   *         by whitespace, or an empty String if the argument has no value.
+   */
+  protected def conditional( condition: Boolean, param: Any, escape: Boolean = true, format: String = "%s" ): String = {
+    if ( condition ) {
+      " %s ".format(formatArgument("", param, "", spaceSeparated = false, escape = escape, paramFormat = format))
+    }
+    else {
+      ""
+    }
+  }
+
+  /**
+   * Safely construct a series of full command-line arguments with consistent quoting, whitespace separation, etc.
+   *
+   * Each argument value is preceded by a prefix/suffix if they are set. A function can be provided to vary
+   * each prefix for each argument value (eg., -f:tag1 file1 -f:tag2 file2) -- the default is to use
+   * the same prefix for all arguments.
+   *
+   * @param prefix Prefix to insert before each argument value (eg., "-f")
+   * @param params The collection of argument values
+   * @param suffix Suffix to append after each argument value
+   * @param separator Specifies how to separate the various arguments from each other
+   *                  (eg., what should go between '-f' 'file1' and '-f' 'file2'?)
+   *                  Default is one space character.
+   * @param spaceSeparated If true, insert a space between each individual prefix, param, and suffix
+   * @param escape If true, quote the generated argument to avoid interpretation by the shell
+   * @param format Format String used to convert each individual param within params to a String
+   * @param formatPrefix Function mapping (prefix, argumentValue) pairs to prefixes. Can be used to
+   *                     vary each prefix depending on the argument value (useful for tags, etc.).
+   *                     Default is to use the same prefix for all argument values.
+   * @return The series of command-line arguments, quoted and whitespace-delimited as requested,
+   *         or an empty String if params was null/Nil/None.
+   */
+  protected def repeat(prefix: String, params: Traversable[_], suffix: String = "", separator: String = " ",
+                       spaceSeparated: Boolean = true, escape: Boolean = true, format: String = "%s",
+                       formatPrefix: (String, Any) => String = (prefix, value) => prefix): String = {
+    if (CollectionUtils.isNullOrEmpty(params))
+      ""
+    else
+      " %s ".format(params.filter(param => hasValue(param)).map(param => formatArgument(formatPrefix(prefix, param), param, suffix, spaceSeparated, escape, format)).mkString(separator))
+  }
+
+  /**
+   * Safely construct a series of one-token command-line arguments with quoting and space separation.
+   *
+   * @param params The collection of argument values
+   * @return The argument values quoted and space-delimited, or an empty String if params was null/Nil/None
+   */
+  protected def repeat( params: Traversable[_] ): String = {
+    repeat("", params)
+  }
+
+  /**
+   * Given an (optional) prefix, an argument value, and an (optional) suffix, formats a command-line
+   * argument with the specified level of quoting and space-separation.
+   *
+   * Helper method for required(), optional(), conditional(), and repeat() -- do not use this
+   * method directly!
+   *
+   * @param prefix Prefix to insert before the argument value (eg., "-f"). Ignored if empty/null.
+   * @param param The argument value itself. If this is Some(x), it is unwrapped to x before processing.
+   * @param suffix Suffix to append after the argument value. Ignored if empty/null.
+   * @param spaceSeparated If true, insert a space between the prefix, param, and suffix
+   * @param escape If true, quote the generated argument to avoid interpretation by the shell
+   * @param paramFormat Format string used to convert param to a String
+   * @return The combined and formatted argument, NOT surrounded by any whitespace.
+   *         Returns an empty String if param was null/empty.
+   */
+  protected def formatArgument( prefix: String, param: Any, suffix: String, spaceSeparated: Boolean, escape: Boolean,
+                                paramFormat: String ): String = {
+    if (CollectionUtils.isNullOrEmpty(param)) {
+      return ""
+    }
+
+    // Trim leading and trailing whitespace off our three tokens, and unwrap Some(x) to x for the param
+    val trimmedValues : Seq[String] = Seq((if ( prefix != null ) prefix.trim else ""),
+                                            (param match {
+                                              case Some(x) => paramFormat.format(x).trim
+                                              case x => paramFormat.format(x).trim
+                                            }),
+                                            (if ( suffix != null ) suffix.trim else ""))
+    var joinedArgument : String = null
+
+    // If the user requested space-separation, join the tokens with a space, and escape individual
+    // NON-EMPTY tokens if escaping was requested (eg., ("-f", "foo", "") -> "'-f' 'foo'")
+    if ( spaceSeparated ) {
+      joinedArgument = trimmedValues.map(x => if ( x.length > 0 && escape ) ShellUtils.escapeShellArgument(x) else x).mkString(" ").trim()
+    }
+
+    // Otherwise join the tokens without any intervening whitespace, and if quoting was requested
+    // quote the entire concatenated value (eg., ("-Xmx", "4", "G") -> "'-Xmx4G'")
+    else  {
+      joinedArgument = if ( escape ) ShellUtils.escapeShellArgument(trimmedValues.mkString("")) else trimmedValues.mkString("")
+    }
+
+    // If the user requested escaping and we ended up with an empty String after joining, quote the empty
+    // String to preserve the command line token. Otherwise just return the joined argument
+    if ( joinedArgument.length == 0 && escape ) ShellUtils.escapeShellArgument(joinedArgument) else joinedArgument
+  }
+}
diff --git a/public/gatk-queue/src/main/scala/org/broadinstitute/gatk/queue/function/InProcessFunction.scala b/public/gatk-queue/src/main/scala/org/broadinstitute/gatk/queue/function/InProcessFunction.scala
new file mode 100644
index 0000000..5525eeb
--- /dev/null
+++ b/public/gatk-queue/src/main/scala/org/broadinstitute/gatk/queue/function/InProcessFunction.scala
@@ -0,0 +1,48 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.queue.function
+
+import java.io.PrintStream
+
+
+/**
+ * Runs a function in process.
+ */
+trait InProcessFunction extends QFunction {
+  analysisName = this.getClass.getSimpleName
+
+  def run()
+
+  /**
+   * During run() this stream will write to the stdout.
+   */
+  var jobOutputStream: PrintStream = null
+
+  /**
+   * Write errors to this stream run().
+   */
+  var jobErrorStream: PrintStream = null
+}
diff --git a/public/gatk-queue/src/main/scala/org/broadinstitute/gatk/queue/function/JavaCommandLineFunction.scala b/public/gatk-queue/src/main/scala/org/broadinstitute/gatk/queue/function/JavaCommandLineFunction.scala
new file mode 100644
index 0000000..80027a0
--- /dev/null
+++ b/public/gatk-queue/src/main/scala/org/broadinstitute/gatk/queue/function/JavaCommandLineFunction.scala
@@ -0,0 +1,139 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.queue.function
+
+import org.broadinstitute.gatk.utils.commandline.Argument
+import org.broadinstitute.gatk.utils.io.IOUtils
+import java.io.File
+
+/**
+ * Defines a command line function that runs java code.
+ */
+trait JavaCommandLineFunction extends CommandLineFunction {
+  @Argument(doc="jar", exclusiveOf="javaMainClass")
+  var jarFile: File = _
+
+  @Argument(doc="Main class to run from javaClasspath", exclusiveOf="jarFile")
+  var javaMainClass: String = _
+
+  /**
+   * Class path for the main class.
+   * Defaults to the current classpath.
+   */
+  var javaClasspath: Seq[String] = Nil
+
+  /**
+   * Memory limit for the java executable, or if None will use the default memoryLimit.
+   */
+  @Argument(doc="Java memory limit", required=false)
+  var javaMemoryLimit: Option[Double] = None
+
+  /**
+   * Max number of GC threads
+   */
+  var javaGCThreads: Option[Int] = None
+
+  /**
+   * Max percent of time spent in garbage collection
+   */
+  var javaGCTimeLimit: Option[Int] = None
+
+  /**
+   * Min percent of max heap freed during a garbage collection
+   */
+  var javaGCHeapFreeLimit: Option[Int] = None
+
+  override def freezeFieldValues() {
+    super.freezeFieldValues()
+
+    if (javaMemoryLimit.isEmpty && memoryLimit.isDefined)
+      javaMemoryLimit = memoryLimit
+
+    if (javaMainClass != null && javaClasspath.isEmpty)
+      javaClasspath = JavaCommandLineFunction.currentClasspath
+
+    if (!this.qSettings.disableDefaultJavaGCOptimizations) {
+      // By default set the GC threads to 4
+      if (javaGCThreads.isEmpty)
+        javaGCThreads = Some(4)
+
+      // By default exit if more than 50% of time in GC
+      if (javaGCTimeLimit.isEmpty)
+        javaGCTimeLimit = Some(50)
+
+      // By default exit if GC does not free up 10% of the heap
+      if (javaGCHeapFreeLimit.isEmpty)
+        javaGCHeapFreeLimit = Some(10)
+    }
+  }
+
+
+  override def copySettingsTo(function: QFunction) {
+    super.copySettingsTo(function)
+    function match {
+      case java: JavaCommandLineFunction =>
+        if (java.javaMemoryLimit.isEmpty)
+          java.javaMemoryLimit = this.javaMemoryLimit
+        if (java.javaGCThreads.isEmpty)
+          java.javaGCThreads = this.javaGCThreads
+        if (java.javaGCTimeLimit.isEmpty)
+          java.javaGCTimeLimit = this.javaGCTimeLimit
+        if (java.javaGCHeapFreeLimit.isEmpty)
+          java.javaGCHeapFreeLimit = this.javaGCHeapFreeLimit
+      case _ => /* ignore */
+    }
+  }
+
+  /**
+   * Returns the java executable to run.
+   */
+  def javaExecutable: String = {
+    if (jarFile != null)
+      required("-jar", jarFile)
+    else if (javaMainClass != null)
+      required("-cp", javaClasspath.mkString(File.pathSeparator)) +
+      required(javaMainClass)
+    else
+      null
+  }
+
+  def javaOpts = Array(
+    optional("-Xmx", javaMemoryLimit.map(gb => (gb * 1024).ceil.toInt), "m", spaceSeparated=false),
+    conditional(javaGCThreads.isDefined || javaGCTimeLimit.isDefined || javaGCHeapFreeLimit.isDefined, "-XX:+UseParallelOldGC"),
+    optional("-XX:ParallelGCThreads=", javaGCThreads, spaceSeparated=false),
+    optional("-XX:GCTimeLimit=", javaGCTimeLimit, spaceSeparated=false),
+    optional("-XX:GCHeapFreeLimit=", javaGCHeapFreeLimit, spaceSeparated=false),
+    required("-Djava.io.tmpdir=", jobTempDir, spaceSeparated=false)).mkString("")
+
+  def commandLine = required("java") +
+                    javaOpts +
+                    javaExecutable
+}
+
+object JavaCommandLineFunction {
+  val currentClasspath = System.getProperty("java.class.path")
+    .split(File.pathSeparatorChar).map(path => IOUtils.absolute(new File(path)).getPath).toSeq
+}
diff --git a/public/gatk-queue/src/main/scala/org/broadinstitute/gatk/queue/function/ListWriterFunction.scala b/public/gatk-queue/src/main/scala/org/broadinstitute/gatk/queue/function/ListWriterFunction.scala
new file mode 100644
index 0000000..c7450b1
--- /dev/null
+++ b/public/gatk-queue/src/main/scala/org/broadinstitute/gatk/queue/function/ListWriterFunction.scala
@@ -0,0 +1,60 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.queue.function
+
+import org.broadinstitute.gatk.utils.commandline.{Input, Output}
+import java.io.{PrintWriter, File}
+import org.apache.commons.io.IOUtils
+
+/**
+ * Writes a list of inputs to an output file.
+ * Custom formats can override addFile.
+ */
+class ListWriterFunction extends InProcessFunction {
+  analysisName = "WriteList"
+
+  @Input(doc="input files") var inputFiles: Seq[File] = Nil
+  @Output(doc="output file") var listFile: File = _
+
+  def run() {
+    val writer = new PrintWriter(listFile)
+    try {
+      for (inputFile <- inputFiles)
+        addFile(writer, inputFile)
+    } finally {
+      IOUtils.closeQuietly(writer)
+    }
+  }
+
+  /**
+   * Adds the inputFile to the output list.
+   * @param writer Output file.
+   * @param inputFile File to add to the output file.
+   */
+  def addFile(writer: PrintWriter, inputFile: File) {
+    writer.println(inputFile.toString)
+  }
+}
diff --git a/public/gatk-queue/src/main/scala/org/broadinstitute/gatk/queue/function/QFunction.scala b/public/gatk-queue/src/main/scala/org/broadinstitute/gatk/queue/function/QFunction.scala
new file mode 100644
index 0000000..f7e2671
--- /dev/null
+++ b/public/gatk-queue/src/main/scala/org/broadinstitute/gatk/queue/function/QFunction.scala
@@ -0,0 +1,517 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.queue.function
+
+import java.io.File
+import java.lang.annotation.Annotation
+import org.broadinstitute.gatk.utils.commandline._
+import org.broadinstitute.gatk.queue.{QException, QSettings}
+import java.lang.IllegalStateException
+import org.broadinstitute.gatk.queue.util._
+import org.broadinstitute.gatk.utils.io.IOUtils
+import scala.language.reflectiveCalls
+
+/**
+ * The base interface for all functions in Queue.
+ * Inputs and outputs are specified as Sets of values.
+ * Inputs are matched to other outputs by using .equals()
+ */
+trait QFunction extends Logging with QJobReport {
+  /**
+   * A short description of what this class of function does.
+   * By default does not include the output specific to this function.
+   * See shortDescription for a description of what this instance of the function outputs.
+   */
+  var analysisName: String = "<function>"
+
+  /**
+   * The name name of the job, must be file system safe and unique to the graph.
+   * Defaults to "runName-<order_function_added>".
+   * Use shortDescription for an alternative that is display friendly.
+   */
+  var jobName: String = _
+
+  /** Default settings */
+  var qSettings: QSettings = _
+
+  /** Directory to run the command in. */
+  var commandDirectory: File = new File(".")
+
+  /** Temporary directory to write any files. Must be network accessible. */
+  var jobTempDir: File = null
+
+  /**
+   * Local path available on all machines to store LOCAL temporary files. Not an @Input,
+   * nor an @Output. Currently only used for local intermediate files for composite jobs.
+   * Needs to be an annotated field so that it's mutated during cloning.
+   */
+  @Argument(doc="Local path available on all machines to store LOCAL temporary files.")
+  var jobLocalDir: File = _
+
+  /** Order the function was added to the graph. */
+  var addOrder: Seq[Int] = Nil
+
+  /** Job priority */
+  var jobPriority: Option[Int] = None
+
+  /** Whether a job is restartable */
+  var jobRestartable = true
+
+  /**
+   * A callback for modifying the run.
+   * NOTE: This function is for ADVANCED use only and is unsupported.
+   */
+  var updateJobRun: PartialFunction[Any,Unit] = null
+
+  /**
+   * If true, unless another unfinished function is dependent on this function,
+   * this function will NOT be run even if the outputs have not been created.
+   */
+  var isIntermediate = false
+
+  // -------------------------------------------------------
+  //
+  // job run information
+  //
+  // -------------------------------------------------------
+
+  /**
+   * Copies settings from this function to another function.
+   * @param function QFunction to copy values to.
+   */
+  override def copySettingsTo(function: QFunction) {
+    function.qSettings = this.qSettings
+    function.commandDirectory = this.commandDirectory
+    function.jobTempDir = this.jobTempDir
+    function.jobLocalDir = this.jobLocalDir
+    function.addOrder = this.addOrder
+    function.jobPriority = this.jobPriority
+    function.jobRestartable = this.jobRestartable
+    function.updateJobRun = this.updateJobRun
+    function.isIntermediate = this.isIntermediate
+    function.reportGroup = this.reportGroup
+    function.reportFeatures = this.reportFeatures
+  }
+
+  /** File to redirect any output.  Defaults to <jobName>.out */
+  var jobOutputFile: File = _
+
+  /** File to redirect any errors.  Defaults to <jobName>.out */
+  var jobErrorFile: File = _
+
+  /** Errors (if any) from the last failed run of jobErrorFiles. */
+  @Argument(doc="Job error lines", required=false)
+  var jobErrorLines: Seq[String] = Nil
+
+  /**
+   * The number of times this function has previously been run.
+   */
+  @Argument(doc="Job retries", required=false)
+  var retries = 0
+
+  /** Change settings for the next run. Retries will be set to the number of times the function was run and jobErrorLines may contain the error text. */
+  def setupRetry() {
+  }
+
+  /**
+   * Description of this command line function.
+   */
+  def description: String = "%s: %s > %s".format(analysisName, inputs, outputs)
+
+  /**
+   * A short description of the function.
+   */
+  def shortDescription = {
+    firstOutput match {
+      case file: File => analysisName + ": " + file.getName
+      case _ => analysisName
+    }
+  }
+  
+  /**
+   * The name of the job as submitted to the job runner
+   */
+  def jobRunnerJobName = shortDescription
+
+  /**
+   * Returns true if the function is done.
+   */
+  def isDone: Boolean = {
+    val files = doneOutputs
+    if (files.size == 0)
+      throw new IllegalStateException("Function should have at least one output: " + analysisName)
+    files.forall(_.exists)
+  }
+
+  /**
+   * Returns true if the function has failed.
+   */
+  def isFail: Boolean = {
+    val files = failOutputs
+    if (files.size == 0)
+      throw new IllegalStateException("Function should have at least one output: " + analysisName)
+    files.exists(_.exists)
+  }
+
+  /**
+   * Returns files to track for hidden done/fail files.
+   * @return Seq[String] files.
+   */
+  protected def statusPaths = {
+    var paths = outputs
+    paths :+= jobOutputFile
+    if (jobErrorFile != null)
+      paths :+= jobErrorFile
+    paths
+  }
+
+  /**
+   * Returns prefixes for hidden done/fail files.
+   * @return prefixes.
+   */
+  private def statusPrefixes = statusPaths.
+    filter(file => !IOUtils.isSpecialFile(file)).
+    map(file => file.getParentFile + "/." + file.getName)
+
+  /**
+   * Returns the output files for this function.
+   * @return outputs for this function.
+   */
+  def doneOutputs: Seq[File] = statusPrefixes.map(path => new File(path + ".done"))
+
+  /**
+   * Returns the output files for this function.
+   * @return outputs for this function.
+   */
+  def failOutputs: Seq[File] = statusPrefixes.map(path => new File(path + ".fail"))
+
+  /** The complete list of fields on this CommandLineFunction. */
+  def functionFields: Seq[ArgumentSource] = ClassFieldCache.classFunctionFields(this.functionFieldClass)
+  /** The @Input fields on this CommandLineFunction. */
+  def inputFields: Seq[ArgumentSource] = ClassFieldCache.classInputFields(this.functionFieldClass)
+  /** The @Output fields on this CommandLineFunction. */
+  def outputFields: Seq[ArgumentSource] = ClassFieldCache.classOutputFields(this.functionFieldClass)
+  /** The @Argument fields on this CommandLineFunction. */
+  def argumentFields: Seq[ArgumentSource] = ClassFieldCache.classArgumentFields(this.functionFieldClass)
+
+  /**
+   * Returns the class that should be used for looking up fields.
+   */
+  protected def functionFieldClass = this.getClass
+
+  /**
+   * Returns the input files for this function.
+   * @return inputs for this function.
+   */
+  def inputs: Seq[File] = getFieldFiles(inputFields)
+
+  /**
+   * Returns the output files for this function.
+   * @return outputs for this function.
+   */
+  def outputs: Seq[File] = getFieldFiles(outputFields)
+
+  /**
+   * Returns the first output file.
+   * @return first output for this function.
+   */
+  def firstOutput: File = outputs.headOption.getOrElse(null)
+
+  /**
+   * Returns the set of directories where files may be written.
+   */
+  def outputDirectories = {
+    var dirs = Set.empty[File]
+    dirs += commandDirectory
+    dirs += jobTempDir
+    dirs += jobLocalDir
+    dirs += jobOutputFile.getParentFile
+    if (jobErrorFile != null)
+      dirs += jobErrorFile.getParentFile
+    dirs ++= outputs.map(_.getParentFile)
+    dirs
+  }
+
+  /**
+   * Deletes the log files for this function.
+   */
+  def deleteLogs() = {
+    IOUtils.tryDelete(jobOutputFile)
+    if (jobErrorFile != null)
+      IOUtils.tryDelete(jobErrorFile)
+  }
+
+  /**
+   * Deletes the output files and all the status files for this function.
+   */
+  def deleteOutputs() {
+    outputs.filter(file => !IOUtils.isSpecialFile(file)).foreach(file => IOUtils.tryDelete(file))
+    doneOutputs.foreach(file => IOUtils.tryDelete(file))
+    failOutputs.foreach(file => IOUtils.tryDelete(file))
+  }
+
+  /**
+   * Creates the output directories for this function if it doesn't exist.
+   */
+  def mkOutputDirectories() {
+    outputDirectories.foreach(dir => {
+      if (!dir.exists && !dir.mkdirs)
+        throw new QException("Unable to create directory: " + dir)
+    })
+  }
+
+  /**
+   * Returns fields that do not have values which are required.
+   * @return Seq[String] names of fields missing values.
+   */
+  def missingFields: Seq[String] = {
+    val missingInputs = missingFields(inputFields, classOf[Input])
+    val missingOutputs = missingFields(outputFields, classOf[Output])
+    val missingArguments = missingFields(argumentFields, classOf[Argument])
+    (missingInputs ++ missingOutputs ++ missingArguments).distinct.sorted
+  }
+
+  /**
+   * Returns fields that do not have values which are required.
+   * @param sources Fields to check.
+   * @param annotation Annotation.
+   * @return names of fields missing values.
+   */
+  private def missingFields(sources: Seq[ArgumentSource], annotation: Class[_ <: Annotation]): Seq[String] = {
+    var missing: Seq[String] = Nil
+    for (source <- sources) {
+      if (isRequired(source, annotation))
+        if (!hasFieldValue(source))
+          if (!exclusiveOf(source, annotation).exists(otherSource => hasFieldValue(otherSource)))
+            missing :+= "@%s: %s - %s".format(annotation.getSimpleName, source.field.getName, doc(source, annotation))
+    }
+    missing
+  }
+
+  /**
+   *  Gets the files from the fields.  The fields must be a File, a FileExtension, or a Seq or Set of either.
+   * @param fields Fields to get files.
+   * @return for the fields.
+   */
+  private def getFieldFiles(fields: Seq[ArgumentSource]): Seq[File] = {
+    var files: Seq[File] = Nil
+    for (field <- fields)
+      files ++= getFieldFiles(field)
+    files.distinct
+  }
+
+  /**
+   * Gets the files from the field.  The field must be a File, a FileExtension, or a Seq or Set of either.
+   * @param field Field to get files.
+   * @return for the field.
+   */
+  def getFieldFiles(field: ArgumentSource): Seq[File] = {
+    var files: Seq[File] = Nil
+    CollectionUtils.foreach(getFieldValue(field), (fieldValue) => {
+      val file = fieldValueToFile(field, fieldValue)
+      if (file != null)
+        files :+= file
+    })
+    files.distinct
+  }
+
+  /**
+   *  Gets the file from the field.  The field must be a File or a FileExtension and not a Seq or Set.
+   * @param field Field to get the file.
+   * @return for the field.
+   */
+  def getFieldFile(field: ArgumentSource): File =
+    fieldValueToFile(field, getFieldValue(field))
+
+  /**
+   * Converts the field value to a file.  The field must be a File or a FileExtension.
+   * @param field Field to get the file.
+   * @param value Value of the File or FileExtension or null.
+   * @return Null if value is null, otherwise the File.
+   * @throws QException if the value is not a File or FileExtension.
+   */
+  private def fieldValueToFile(field: ArgumentSource, value: Any): File = value match {
+    case file: File => file
+    case null => null
+    case unknown => throw new QException("Non-file found.  Try removing the annotation, change the annotation to @Argument, or extend File with FileExtension: %s: %s".format(field.field, unknown))
+  }
+
+  /**
+   * After a function is frozen no more updates are allowed by the user.
+   * The function is allow to make necessary updates internally to make sure
+   * the inputs and outputs will be equal to other inputs and outputs.
+   */
+  final def freeze() {
+    freezeFieldValues()
+    canonFieldValues()
+  }
+
+  /**
+   * Sets all field values.
+   */
+  def freezeFieldValues() {
+    if (jobName == null)
+      jobName = qSettings.runName + "-" + this.addOrder.mkString("-")
+
+    if (jobOutputFile == null) {
+      /*If the outputFile has been set to an absolute path, respect that.
+        Otherwise, place it in (possibly a subdirectory of) the log directory
+        The relative case is first as it's arguably the most common condition
+      */
+      jobOutputFile = firstOutput match {
+        case file: File if !IOUtils.isSpecialFile(file) && !file.isAbsolute =>
+            val logDir : File = if (file.getParentFile == null) qSettings.logDirectory else new File(qSettings.logDirectory, file.getParent)
+            new File(logDir, file.getName + ".out")
+
+        case file: File if !IOUtils.isSpecialFile(file) && file.isAbsolute =>
+            new File(file.getParentFile, file.getName + ".out")
+
+        case _ =>
+          new File(qSettings.logDirectory, jobName + ".out")
+      }
+    }
+
+    if (jobTempDir == null)
+      jobTempDir = qSettings.tempDirectory
+
+    if (jobLocalDir == null)
+      jobLocalDir = jobTempDir
+
+    if (jobPriority.isEmpty)
+      jobPriority = qSettings.jobPriority
+
+    // Do not set the temp and local dir relative to the command directory
+    jobTempDir = IOUtils.absolute(jobTempDir)
+    jobLocalDir = IOUtils.absolute(jobLocalDir)
+
+    absoluteCommandDirectory()
+  }
+
+  /**
+   * If the command directory is relative, insert the run directory ahead of it.
+   */
+  def absoluteCommandDirectory() {
+    commandDirectory = IOUtils.absolute(qSettings.runDirectory, commandDirectory)
+  }
+
+  /**
+   * Makes all field values canonical so that the graph can match the
+   * inputs of one function to the output of another using equals().
+   */
+  def canonFieldValues() {
+    for (field <- this.functionFields) {
+      var fieldValue = this.getFieldValue(field)
+      fieldValue = CollectionUtils.updated(fieldValue, canon).asInstanceOf[AnyRef]
+      this.setFieldValue(field, fieldValue)
+    }
+
+    this.jobOutputFile = canon(this.jobOutputFile).asInstanceOf[File]
+    if (this.jobErrorFile != null)
+      this.jobErrorFile = canon(this.jobErrorFile).asInstanceOf[File]
+  }
+
+  /**
+   * Set value to a uniform value across functions.
+   * Base implementation changes any relative path to an absolute path.
+   * @param value to be updated
+   * @return the modified value, or a copy if the value is immutable
+   */
+  protected def canon(value: Any) = {
+    value match {
+      case file: File => IOUtils.absolute(commandDirectory, file)
+      case x => x
+    }
+  }
+
+  /**
+   * Scala sugar type for checking annotation required and exclusiveOf.
+   */
+  private type ArgumentAnnotation = {
+    def required(): Boolean
+    def exclusiveOf(): String
+    def doc(): String
+  }
+
+  /**
+   * Returns the isRequired value from the field.
+   * @param field Field to check.
+   * @param annotation Annotation.
+   * @return the isRequired value from the field annotation.
+   */
+  private def isRequired(field: ArgumentSource, annotation: Class[_ <: Annotation]) =
+    ReflectionUtils.getAnnotation(field.field, annotation).asInstanceOf[ArgumentAnnotation].required()
+
+  /**
+   * Returns an array of ArgumentSources from functionFields listed in the exclusiveOf of the original field
+   * @param field Field to check.
+   * @param annotation Annotation.
+   * @return the Array[ArgumentSource] that may be set instead of the field.
+   */
+  private def exclusiveOf(field: ArgumentSource, annotation: Class[_ <: Annotation]) =
+    ReflectionUtils.getAnnotation(field.field, annotation).asInstanceOf[ArgumentAnnotation].exclusiveOf()
+            .split(",").map(_.trim).filter(_.length > 0)
+            .map(fieldName => functionFields.find(fieldName == _.field.getName) match {
+      case Some(x) => x
+      case None => throw new QException("Unable to find exclusion field %s on %s".format(fieldName, this.getClass.getSimpleName))
+    })
+
+  /**
+   * Returns the doc value from the field.
+   * @param field Field to check.
+   * @param annotation Annotation.
+   * @return the doc value from the field annotation.
+   */
+  private def doc(field: ArgumentSource, annotation: Class[_ <: Annotation]) =
+    ReflectionUtils.getAnnotation(field.field, annotation).asInstanceOf[ArgumentAnnotation].doc()
+
+  /**
+   * Returns true if the field has a value.
+   * @param source Field to check for a value.
+   * @return true if the field has a value.
+   */
+  protected def hasFieldValue(source: ArgumentSource) = this.hasValue(this.getFieldValue(source))
+
+  /**
+   * Returns false if the value is null or an empty collection.
+   * @param param Value to test for null, or a collection to test if it is empty.
+   * @return false if the value is null, or false if the collection is empty, otherwise true.
+   */
+  protected def hasValue(param: Any) = CollectionUtils.isNotNullOrNotEmpty(param)
+
+  /**
+   * Gets the value of a field.
+   * @param source Field to get the value for.
+   * @return value of the field.
+   */
+  def getFieldValue(source: ArgumentSource) = ClassFieldCache.getFieldValue(this, source)
+
+  /**
+   * Gets the value of a field.
+   * @param source Field to set the value for.
+   * @return value of the field.
+   */
+  def setFieldValue(source: ArgumentSource, value: Any) = ClassFieldCache.setFieldValue(this, source, value)
+}
diff --git a/public/gatk-queue/src/main/scala/org/broadinstitute/gatk/queue/function/RetryMemoryLimit.scala b/public/gatk-queue/src/main/scala/org/broadinstitute/gatk/queue/function/RetryMemoryLimit.scala
new file mode 100644
index 0000000..9202c2a
--- /dev/null
+++ b/public/gatk-queue/src/main/scala/org/broadinstitute/gatk/queue/function/RetryMemoryLimit.scala
@@ -0,0 +1,103 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.queue.function
+
+import org.broadinstitute.gatk.utils.commandline.Argument
+
+object RetryMemoryLimit {
+  private val defaultRetryMemoryFunction: (Double => Double) = ( 2 * _ )
+  private val defaultMemoryLimitErrorText = Seq("OutOfMemory", "you did not provide enough memory", "TERM_MEMLIMIT")
+}
+
+/** A mixin that on retry increases the memory limit when certain text is found. */
+trait RetryMemoryLimit extends CommandLineFunction {
+
+  /** How to increase the memory. By default doubles the memory. */
+  var retryMemoryFunction: (Double => Double) = RetryMemoryLimit.defaultRetryMemoryFunction
+
+  /** Once the threshold is passed, no more memory will be added to memory limit. */
+  @Argument(doc="threshold to stop doubling the memory", required=false)
+  var memoryLimitThreshold: Option[Double] = None
+
+  /** Various strings to look for to determine we ran out of memory. */
+  @Argument(doc="text to look for in the errors", required = false)
+  var memoryLimitErrorText = RetryMemoryLimit.defaultMemoryLimitErrorText
+
+  override def freezeFieldValues() {
+    super.freezeFieldValues()
+    if (this.memoryLimitThreshold.isEmpty)
+      this.memoryLimitThreshold = this.qSettings.memoryLimitThreshold
+  }
+
+
+  override def copySettingsTo(function: QFunction) {
+    super.copySettingsTo(function)
+    function match {
+      case retryMemoryLimit: RetryMemoryLimit =>
+        if (retryMemoryLimit.memoryLimitThreshold.isEmpty)
+          retryMemoryLimit.memoryLimitThreshold = this.memoryLimitThreshold
+        if (retryMemoryLimit.retryMemoryFunction == RetryMemoryLimit.defaultRetryMemoryFunction)
+          retryMemoryLimit.retryMemoryFunction = this.retryMemoryFunction
+        if (retryMemoryLimit.memoryLimitErrorText == RetryMemoryLimit.defaultMemoryLimitErrorText)
+          retryMemoryLimit.memoryLimitErrorText = this.memoryLimitErrorText
+      case _ => /* ignore */
+    }
+  }
+
+  override def setupRetry() {
+    super.setupRetry()
+    if (this.memoryLimitThreshold.isDefined && this.memoryLimit.isDefined) {
+
+      // NOTE: If we're already at or above the memoryLimit, don't do anything.
+      if (this.memoryLimit.get < this.memoryLimitThreshold.get) {
+          updateMemoryLimits()
+      }
+
+    } else {
+      updateMemoryLimits()
+    }
+  }
+
+  def updateMemoryLimits() {
+    if (isMemoryError) {
+      this.memoryLimit = this.memoryLimit.map(this.retryMemoryFunction)
+      this.residentRequest = this.residentRequest.map(this.retryMemoryFunction)
+      this.residentLimit = this.residentLimit.map(this.retryMemoryFunction)
+
+      // Rebuffer the memory limit if the limit was set exactly to the request
+      if (this.residentLimit == this.residentRequest)
+        this.residentLimit = this.residentRequest.map(this.residentLimitBuffer)
+
+      this match {
+        case java: JavaCommandLineFunction =>
+          java.javaMemoryLimit = java.javaMemoryLimit.map(this.retryMemoryFunction)
+        case _ => /* ignore */
+      }
+    }
+  }
+
+  def isMemoryError = this.jobErrorLines.exists(line => this.memoryLimitErrorText.exists(error => line.contains(error)))
+}
diff --git a/public/gatk-queue/src/main/scala/org/broadinstitute/gatk/queue/function/scattergather/CloneFunction.scala b/public/gatk-queue/src/main/scala/org/broadinstitute/gatk/queue/function/scattergather/CloneFunction.scala
new file mode 100644
index 0000000..ccc9dcf
--- /dev/null
+++ b/public/gatk-queue/src/main/scala/org/broadinstitute/gatk/queue/function/scattergather/CloneFunction.scala
@@ -0,0 +1,111 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.queue.function.scattergather
+
+import org.broadinstitute.gatk.utils.commandline.ArgumentSource
+import org.broadinstitute.gatk.queue.function.CommandLineFunction
+import org.broadinstitute.gatk.queue.util.ClassFieldCache
+
+/**
+ * Shadow clones another command line function.
+ */
+object CloneFunction {
+  private lazy val cloneFunctionFields = ClassFieldCache.classFunctionFields(classOf[CloneFunction])
+}
+
+class CloneFunction extends CommandLineFunction {
+  var originalFunction: ScatterGatherableFunction = _
+  var cloneIndex: Int = _
+  var cloneCount: Int = _
+
+  private var overriddenFields = Map.empty[ArgumentSource, Any]
+  private var withScatterPartCount = 0
+
+  private def withScatterPart[A](f: () => A): A = {
+    var originalValues = Map.empty[ArgumentSource, Any]
+    withScatterPartCount += 1
+    if (withScatterPartCount == 1) {
+      originalFunction.functionFields.foreach {
+        case (field) => {
+          originalValues += field -> originalFunction.getFieldValue(field)
+          originalFunction.setFieldValue(field, getFieldValue(field))
+        }
+      }
+    }
+    try {
+      f()
+    } finally {
+      if (withScatterPartCount == 1) {
+        originalFunction.functionFields.foreach {
+          case (field) => {
+            setFieldValue(field, originalFunction.getFieldValue(field))
+            originalFunction.setFieldValue(field, originalValues(field))
+          }
+        }
+      }
+      withScatterPartCount -= 1
+    }
+  }
+
+  override def description = withScatterPart(() => originalFunction.description)
+  override def shortDescription = withScatterPart(() => originalFunction.shortDescription)
+  override def setupRetry() { withScatterPart(() => originalFunction.setupRetry()) }
+
+  override protected def functionFieldClass = originalFunction.getClass
+
+  def commandLine = withScatterPart(() => originalFunction.commandLine)
+
+  def getFieldValue(field: String): AnyRef = {
+    val source = ClassFieldCache.findField(originalFunction.getClass, field)
+    getFieldValue(source)
+  }
+
+  override def getFieldValue(source: ArgumentSource): AnyRef = {
+    CloneFunction.cloneFunctionFields.find(_.field.getName == source.field.getName) match {
+      case Some(cloneSource) =>
+        super.getFieldValue(cloneSource)
+      case None =>
+        overriddenFields.get(source) match {
+          case Some(value) =>
+            value.asInstanceOf[AnyRef]
+          case None => {
+            val value = originalFunction.getFieldValue(source)
+            overriddenFields += source -> value
+            value
+          }
+        }
+    }
+  }
+
+  def setFieldValue(field: String, value: Any) {
+    val source = ClassFieldCache.findField(originalFunction.getClass, field)
+    setFieldValue(source, value)
+  }
+
+  override def setFieldValue(source: ArgumentSource, value: Any) {
+    overriddenFields += source -> value
+  }
+}
diff --git a/public/gatk-queue/src/main/scala/org/broadinstitute/gatk/queue/function/scattergather/ConcatenateLogsFunction.scala b/public/gatk-queue/src/main/scala/org/broadinstitute/gatk/queue/function/scattergather/ConcatenateLogsFunction.scala
new file mode 100644
index 0000000..b97cee1
--- /dev/null
+++ b/public/gatk-queue/src/main/scala/org/broadinstitute/gatk/queue/function/scattergather/ConcatenateLogsFunction.scala
@@ -0,0 +1,56 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.queue.function.scattergather
+
+import org.broadinstitute.gatk.queue.function.InProcessFunction
+import org.broadinstitute.gatk.queue.QException
+import org.broadinstitute.gatk.utils.commandline.Input
+import org.apache.commons.io.FileUtils
+import java.io.File
+import collection.JavaConversions._
+
+/**
+ * Concatenate log files to the jobOutputFile.
+ */
+class ConcatenateLogsFunction extends InProcessFunction {
+  analysisName = "Concat"
+
+  @Input(doc="Parts to gather back into the original output")
+  var logs: Seq[File] = Nil
+
+  override def description = "%s: %s > %s".format(analysisName, logs, jobOutputFile)
+  override def shortDescription = analysisName + ": " + jobOutputFile.getName
+
+  def run() {
+    val missing = org.broadinstitute.gatk.utils.io.IOUtils.waitFor(logs, 120)
+    if (!missing.isEmpty)
+      throw new QException("Unable to find log: " + missing.mkString(", "))
+    logs.foreach(log => {
+      FileUtils.copyFile(log, this.jobOutputStream)
+      this.jobOutputStream.println()
+    })
+  }
+}
diff --git a/public/gatk-queue/src/main/scala/org/broadinstitute/gatk/queue/function/scattergather/GatherFunction.scala b/public/gatk-queue/src/main/scala/org/broadinstitute/gatk/queue/function/scattergather/GatherFunction.scala
new file mode 100644
index 0000000..7044265
--- /dev/null
+++ b/public/gatk-queue/src/main/scala/org/broadinstitute/gatk/queue/function/scattergather/GatherFunction.scala
@@ -0,0 +1,72 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.queue.function.scattergather
+
+import java.io.File
+import org.broadinstitute.gatk.utils.commandline.{Input, Output}
+import org.broadinstitute.gatk.queue.function.QFunction
+import org.broadinstitute.gatk.queue.QException
+import org.broadinstitute.gatk.utils.io.IOUtils
+import collection.JavaConversions._
+
+/**
+ * Base class for Gather command line functions.
+ */
+trait GatherFunction extends QFunction {
+  analysisName = "Gather"
+
+  var originalFunction: ScatterGatherableFunction = _
+
+  @Output(doc="The original output of the scattered function")
+  var originalOutput: File = _
+
+  @Input(doc="Parts to gather back into the original output")
+  var gatherParts: Seq[File] = Nil
+
+  /**
+   * Called to initialize the gather function values after all other values have been setup for this function.
+   */
+  def init() {}
+
+  /**
+   * Don't include this @Gather's log file when tracking .done.
+   * The done files for original log file being produced will do.
+   *
+   * The logs from the scatter/gather jobs are concatenated together into the original log.
+   * Without removing the logs a .done file would be created for the logs. If a SGF is switched
+   * from scatterCount=1 to >1 then this Gather would be "missing" its logs and re-run.
+   */
+  override protected def statusPaths = outputs
+
+  /**
+   * Waits for gather parts to propagate over NFS or throws an exception.
+   */
+  protected def waitForGatherParts() {
+    val missing = IOUtils.waitFor(gatherParts, 120)
+    if (!missing.isEmpty)
+      throw new QException("Unable to find gather inputs: " + missing.mkString(", "))
+  }
+}
diff --git a/public/gatk-queue/src/main/scala/org/broadinstitute/gatk/queue/function/scattergather/GathererFunction.scala b/public/gatk-queue/src/main/scala/org/broadinstitute/gatk/queue/function/scattergather/GathererFunction.scala
new file mode 100644
index 0000000..4fcc19f
--- /dev/null
+++ b/public/gatk-queue/src/main/scala/org/broadinstitute/gatk/queue/function/scattergather/GathererFunction.scala
@@ -0,0 +1,44 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.queue.function.scattergather
+
+import org.broadinstitute.gatk.utils.commandline.Gatherer
+import org.broadinstitute.gatk.queue.function.InProcessFunction
+import collection.JavaConversions._
+
+/**
+ * Runs a Gatherer in process.
+ */
+class GathererFunction(gathererClass: Class[_ <: Gatherer]) extends InProcessFunction with GatherFunction {
+  analysisName = this.gathererClass.getSimpleName
+
+  def run() {
+    val gatherer = gathererClass.newInstance
+    if (gatherer.waitForInputs)
+      waitForGatherParts()
+    gatherer.gather(this.gatherParts, this.originalOutput)
+  }
+}
diff --git a/public/gatk-queue/src/main/scala/org/broadinstitute/gatk/queue/function/scattergather/ScatterFunction.scala b/public/gatk-queue/src/main/scala/org/broadinstitute/gatk/queue/function/scattergather/ScatterFunction.scala
new file mode 100644
index 0000000..29f8c41
--- /dev/null
+++ b/public/gatk-queue/src/main/scala/org/broadinstitute/gatk/queue/function/scattergather/ScatterFunction.scala
@@ -0,0 +1,78 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.queue.function.scattergather
+
+import java.io.File
+import org.broadinstitute.gatk.utils.commandline.Input
+import org.broadinstitute.gatk.queue.function.QFunction
+
+/**
+ * Base class for Scatter functions.
+ */
+trait ScatterFunction extends QFunction {
+  analysisName = "Scatter"
+
+  var originalFunction: ScatterGatherableFunction = _
+
+  @Input(doc="Original inputs to scatter")
+  var originalInputs: Set[File] = _
+
+  override def shortDescription = analysisName + ": %s ...".format(firstOutput.getName)
+
+  /**
+   * Called to initialize scatter function values after all other values have been setup for this function.
+   */
+  def init() {}
+
+  /**
+   * Returns true if the scatter function can scatter this original function.
+   * @return true if the scatter function can scatter this original function.
+   */
+  def isScatterGatherable = true
+
+  /**
+   * Returns the number of clones that should be created.
+   */
+  def scatterCount: Int = originalFunction.scatterCount
+
+  /**
+   * Initializes the input fields for the clone function.
+   * The input values should be set to their defaults
+   * and may be changed by the user.
+   * @param cloneFunction CloneFunction to initialize.
+   * @param index The one based scatter index.
+   */
+  def initCloneInputs(cloneFunction: CloneFunction, index: Int) {}
+
+  /**
+   * Binds the input fields for the clone function to this scatter function.
+   * The input values should be set to their absolute values and added
+   * to scatter parts.
+   * @param cloneFunction CloneFunction to bind.
+   * @param index The one based scatter index.
+   */
+  def bindCloneInputs(cloneFunction: CloneFunction, index: Int) {}
+}
diff --git a/public/gatk-queue/src/main/scala/org/broadinstitute/gatk/queue/function/scattergather/ScatterGatherableFunction.scala b/public/gatk-queue/src/main/scala/org/broadinstitute/gatk/queue/function/scattergather/ScatterGatherableFunction.scala
new file mode 100644
index 0000000..50ad3cf
--- /dev/null
+++ b/public/gatk-queue/src/main/scala/org/broadinstitute/gatk/queue/function/scattergather/ScatterGatherableFunction.scala
@@ -0,0 +1,376 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.queue.function.scattergather
+
+import java.io.File
+import org.broadinstitute.gatk.queue.util._
+import org.broadinstitute.gatk.utils.commandline.{Gatherer, Gather, ArgumentSource}
+import org.broadinstitute.gatk.queue.function.{QFunction, CommandLineFunction}
+import org.broadinstitute.gatk.queue.QException
+import org.broadinstitute.gatk.utils.io.IOUtils
+import collection.immutable.ListMap
+
+/**
+ * A function that can be run faster by splitting it up into pieces and then joining together the results.
+ */
+trait ScatterGatherableFunction extends CommandLineFunction {
+
+  /** Maximum number of parts to scatter the function into. */
+  var scatterCount: Int = 1
+
+  /** scatter gather directory */
+  var scatterGatherDirectory: File = _
+
+  /** Class to use for scattering.  Defaults to the annotation used in the @Scatter tag. */
+  var scatterClass: Class[_ <: ScatterFunction] = _
+
+  /**
+   * Function that returns the class to use for gathering a directory.  If it returns null then @Gather annotation will be used.
+   * PartialFunction param gatherField Field that is to be gathered.
+   * @return The class of the GatherFunction to be used or null.
+   */
+  var gatherClass: PartialFunction[ArgumentSource, Class[_ <: GatherFunction]] = _
+
+  /**
+   * Allows external modification of the ScatterFunction that will create the scatter pieces in the temporary directories.
+   * PartialFunction param scatterFunction The function that will create the scatter pieces in the temporary directories.
+   */
+  var setupScatterFunction: PartialFunction[ScatterFunction, Unit] = _
+
+  /**
+   * Allows external modification of the GatherFunction that will collect the gather pieces in the temporary directories.
+   * PartialFunction param gatherFunction The function that will merge the gather pieces from the temporary directories.
+   * PartialFunction param gatherField The output field being gathered.
+   */
+  var setupGatherFunction: PartialFunction[(GatherFunction, ArgumentSource), Unit] = _
+
+  /**
+   * Allows external modification of the cloned function.
+   * PartialFunction param cloneFunction A clone wrapper of this ScatterGatherableFunction
+   * PartialFunction param index The one based index (from 1..scatterCount inclusive) of the scatter piece.
+   */
+  var setupCloneFunction: PartialFunction[(CloneFunction, Int), Unit] = _
+
+  /**
+   * Returns true if the function is ready to be scatter / gathered.
+   * The base implementation checks if the scatter count is greater than one,
+   * and that the scatter function can scatter this instance.
+   * @return true if the function is ready to be scatter / gathered.
+   */
+  def scatterGatherable = this.scatterCount > 1 && scatterFunction.isScatterGatherable
+
+  /**
+   * Sets the scatter gather directory to the command directory if it is not already set.
+   */
+  override def freezeFieldValues() {
+    super.freezeFieldValues()
+
+    if (this.scatterGatherDirectory == null) {
+      if (qSettings.jobScatterGatherDirectory != null) {
+        this.scatterGatherDirectory = IOUtils.absolute(qSettings.jobScatterGatherDirectory)
+      } else {
+        this.scatterGatherDirectory = IOUtils.absolute(this.commandDirectory, ".queue/scatterGather")
+      }
+    }
+  }
+
+  /**
+   * The scatter function.
+   */
+  private lazy val scatterFunction = {
+    // Only depend on input fields that have a value
+    val inputFieldsWithValues = this.inputFields.filter(hasFieldValue(_))
+    val inputFiles = inputFieldsWithValues.flatMap(getFieldFiles(_)).toSet
+
+    val scatterFunction = newScatterFunction()
+    this.copySettingsTo(scatterFunction)
+    scatterFunction.originalFunction = this
+    scatterFunction.originalInputs = inputFiles
+    scatterFunction.commandDirectory = this.scatterGatherCommandDir("scatter")
+    scatterFunction.jobOutputFile = new File("scatter.out")
+    scatterFunction.addOrder = this.addOrder :+ 1
+    scatterFunction.isIntermediate = true
+
+    initScatterFunction(scatterFunction)
+    scatterFunction.absoluteCommandDirectory()
+    scatterFunction.init()
+    scatterFunction
+  }
+
+  /**
+   * Returns a list of scatter / gather and clones of this function
+   * that can be run in parallel to produce the same output as this
+   * command line function.
+   * @return Seq[QFunction] to run instead of this function.
+   */
+  def generateFunctions() = {
+    // Ask the scatter function how many clones to create.
+    val numClones = scatterFunction.scatterCount
+
+    // Create the gather functions for each output field
+    var gatherFunctions = ListMap.empty[ArgumentSource, GatherFunction]
+    var gatherOutputs = ListMap.empty[ArgumentSource, File]
+    var gatherAddOrder = numClones + 2
+
+    // Only track fields that will have an output file
+    val outputFieldsWithValues = this.outputFields.
+      filter(hasFieldValue(_)).
+      filter(gatherField => !IOUtils.isSpecialFile(getFieldFile(gatherField)))
+
+    for (gatherField <- outputFieldsWithValues) {
+      gatherOutputs += gatherField -> getFieldFile(gatherField)
+    }
+
+    // Only gather fields that are @Gather(enabled=true)
+    val outputFieldsWithGathers = outputFieldsWithValues.filter(hasGatherFunction(_))
+
+    for (gatherField <- outputFieldsWithGathers) {
+      val gatherOutput = gatherOutputs(gatherField)
+
+      val gatherFunction = this.newGatherFunction(gatherField)
+      this.copySettingsTo(gatherFunction)
+      gatherFunction.originalFunction = this
+      gatherFunction.originalOutput = gatherOutput
+      gatherFunction.commandDirectory = this.scatterGatherCommandDir("gather-" + gatherField.field.getName)
+      gatherFunction.jobOutputFile = new File("gather-" + gatherOutput.getName + ".out")
+      gatherFunction.addOrder = this.addOrder :+ gatherAddOrder
+
+      initGatherFunction(gatherFunction, gatherField)
+      gatherFunction.absoluteCommandDirectory()
+      gatherFunction.init()
+
+      gatherFunctions += gatherField -> gatherFunction
+
+      gatherAddOrder += 1
+    }
+
+    // Create the clone functions for running the parallel jobs
+    var cloneFunctions = Seq.empty[CloneFunction]
+    val dirFormat = "temp_%%0%dd_of_%d".format(numClones.toString.length(), numClones)
+    for (i <- 1 to numClones) {
+      val cloneFunction = this.newCloneFunction()
+
+      this.copySettingsTo(cloneFunction)
+      cloneFunction.originalFunction = this
+      cloneFunction.analysisName = this.analysisName
+      cloneFunction.cloneIndex = i
+      cloneFunction.cloneCount = numClones
+      cloneFunction.commandDirectory = this.scatterGatherCommandDir(dirFormat.format(i))
+      cloneFunction.jobOutputFile = if (IOUtils.isSpecialFile(this.jobOutputFile)) this.jobOutputFile else new File(this.jobOutputFile.getName)
+      if (this.jobErrorFile != null)
+        cloneFunction.jobErrorFile = if (IOUtils.isSpecialFile(this.jobErrorFile)) this.jobErrorFile else new File(this.jobErrorFile.getName)
+      // jic the "local" dir is actually on the network, create different sub local directories for each clone.
+      // This might be better handled with a hook that allows clones to create unique file names. Right now no hook
+      // like freezeFieldValues exists for specifying per cloneFunction fields.
+      cloneFunction.jobLocalDir = this.scatterGatherLocalDir(dirFormat.format(i))
+      cloneFunction.addOrder = this.addOrder :+ (i+1)
+      cloneFunction.isIntermediate = true
+
+      // Setup the fields on the clone function, outputting each as a relative file in the sg directory.
+      scatterFunction.initCloneInputs(cloneFunction, i)
+      for (gatherField <- outputFieldsWithValues) {
+        val gatherPart = new File(gatherOutputs(gatherField).getName)
+        cloneFunction.setFieldValue(gatherField, gatherPart)
+      }
+
+      // Allow the script writer to change the paths to the files.
+      initCloneFunction(cloneFunction, i)
+
+      // If the command directory is relative, insert the run directory ahead of it.
+      cloneFunction.absoluteCommandDirectory()
+
+      // Allow the scatter function to set the specific input for this clone
+      scatterFunction.bindCloneInputs(cloneFunction, i)
+
+      // Set each of the clone outputs to be absolute paths.
+      for (gatherField <- outputFieldsWithValues) {
+        val gatherPart = IOUtils.absolute(cloneFunction.commandDirectory, cloneFunction.getFieldFile(gatherField))
+        cloneFunction.setFieldValue(gatherField, gatherPart)
+      }
+
+      // For the outputs that are being gathered add this clone's output to be gathered.
+      for (gatherField <- outputFieldsWithGathers) {
+        gatherFunctions(gatherField).gatherParts :+= cloneFunction.getFieldFile(gatherField)
+      }
+
+      cloneFunctions :+= cloneFunction
+    }
+
+    // Track the functions starting with the scatter function.
+    var functions: Seq[QFunction] = Seq(scatterFunction) ++ cloneFunctions ++ gatherFunctions.values
+
+    // Make all log file paths absolute.
+    for (function <- functions) {
+      function.jobOutputFile = IOUtils.absolute(function.commandDirectory, function.jobOutputFile)
+      if (function.jobErrorFile != null)
+        function.jobErrorFile = IOUtils.absolute(function.commandDirectory, function.jobErrorFile)
+    }
+
+    val jobOutputGather = gatherLogFile(_.jobOutputFile, functions, gatherAddOrder)
+    if (this.jobErrorFile != null) {
+      val jobErrorGather = gatherLogFile(_.jobErrorFile, functions, gatherAddOrder + 1)
+      functions :+= jobErrorGather
+    }
+    functions :+= jobOutputGather
+
+    // Return all the various created functions.
+    functions
+  }
+
+  /**
+   * Creates a new ScatterFunction.
+   * @return A ScatterFunction instantiated scatterClass
+   */
+  protected def newScatterFunction(): ScatterFunction = {
+    if (this.scatterClass == null)
+      throw new QException("scatterClass is null.")
+    this.scatterClass.newInstance.asInstanceOf[ScatterFunction]
+  }
+
+  /**
+   * Initializes the ScatterFunction created by newScatterFunction() that will create the scatter pieces in the temporary directories.
+   * Calls setupScatterFunction with scatterFunction.
+   * @param scatterFunction The function that will create the scatter pieces in the temporary directories.
+   */
+  protected def initScatterFunction(scatterFunction: ScatterFunction) {
+    if (this.setupScatterFunction != null)
+      if (this.setupScatterFunction.isDefinedAt(scatterFunction))
+        this.setupScatterFunction(scatterFunction)
+  }
+
+  /**
+   * Returns true if the field should be gathered.
+   * @param gatherField Field that defined @Gather.
+   * @return true if the field should be gathered.
+   */
+  protected def hasGatherFunction(gatherField: ArgumentSource) : Boolean = {
+    // Check if there is a function that will return the gather class for this field.
+    if (this.gatherClass != null && this.gatherClass.isDefinedAt(gatherField))
+        true
+
+    // Check for an annotation defining the gather class.
+    else if (ReflectionUtils.hasAnnotation(gatherField.field, classOf[Gather]))
+      ReflectionUtils.getAnnotation(gatherField.field, classOf[Gather]).enabled
+
+    // Nothing else to disable this field.
+    else
+      true
+  }
+
+  /**
+   * Creates a new GatherFunction for the gatherField.
+   * @param gatherField Field that defined @Gather.
+   * @return A GatherFunction instantiated from @Gather.
+   */
+  protected def newGatherFunction(gatherField: ArgumentSource) : GatherFunction = {
+    var gatherClass: Class[_] = null
+
+    // Check if there is a function that will return the gather class for this field.
+    if (this.gatherClass != null)
+      if (this.gatherClass.isDefinedAt(gatherField))
+        gatherClass = this.gatherClass(gatherField)
+
+    // Check for an annotation defining the gather class.
+    if (gatherClass == null) {
+      if (ReflectionUtils.hasAnnotation(gatherField.field, classOf[Gather])) {
+        gatherClass = ReflectionUtils.getAnnotation(gatherField.field, classOf[Gather]).value
+      } else {
+        throw new QException("Missing @Gather annotation on %s".format(gatherField.field))
+      }
+    }
+
+    if (gatherClass == classOf[GatherFunction]) {
+      throw new QException("@Gather did not specify class type on %s".format(gatherField.field))
+    } else if (classOf[GatherFunction].isAssignableFrom(gatherClass)) {
+      gatherClass.newInstance.asInstanceOf[GatherFunction]
+    } else if (classOf[Gatherer].isAssignableFrom(gatherClass)) {
+      new GathererFunction(gatherClass.asSubclass(classOf[Gatherer]))
+    } else {
+      throw new QException("Unsupported @Gather class type on %s: %s".format(gatherField.field, gatherClass))
+    }
+  }
+
+  /**
+   * Initializes the GatherFunction created by newGatherFunction() that will collect the gather pieces in the temporary directories.
+   * Calls the gatherFunction.setOriginalFunction with this ScatterGatherableFunction.
+   * Calls setupGatherFunction with gatherFunction.
+   * @param gatherFunction The function that will merge the gather pieces from the temporary directories.
+   * @param gatherField The output field being gathered.
+   */
+  protected def initGatherFunction(gatherFunction: GatherFunction, gatherField: ArgumentSource) {
+    if (this.setupGatherFunction != null)
+      if (this.setupGatherFunction.isDefinedAt(gatherFunction, gatherField))
+        this.setupGatherFunction(gatherFunction, gatherField)
+  }
+
+  /**
+   * Creates a new clone of this ScatterGatherableFunction, setting the scatterCount to 1 so it doesn't infinitely scatter.
+   * @return An uninitialized clone wrapper for ScatterGatherableFunction
+   */
+  protected def newCloneFunction() = new CloneFunction
+
+  /**
+   * Calls setupCloneFunction with cloneFunction.
+   * @param cloneFunction The clone of this ScatterGatherableFunction
+   * @param index The one based index (from 1..scatterCount inclusive) of the scatter piece.
+   */
+  protected def initCloneFunction(cloneFunction: CloneFunction, index: Int) {
+    if (this.setupCloneFunction != null)
+      if (this.setupCloneFunction.isDefinedAt(cloneFunction, index))
+        this.setupCloneFunction(cloneFunction, index)
+  }
+
+  /**
+   * Gathers up the logs files from other functions.
+   * @param logFile Takes the QFunction and return the log file.
+   * @param functions The functions for which the logs will be concatenated.
+   * @param addOrder The order this function should be added in the graph.
+   */
+  private def gatherLogFile(logFile: (QFunction) => File, functions: Seq[QFunction], addOrder: Int) = {
+    val gatherLogFunction = new ConcatenateLogsFunction
+    this.copySettingsTo(gatherLogFunction)
+    gatherLogFunction.logs = functions.map(logFile).filter(_ != null)
+    gatherLogFunction.jobOutputFile = logFile(this)
+    gatherLogFunction.commandDirectory = this.scatterGatherCommandDir()
+    gatherLogFunction.addOrder = this.addOrder :+ addOrder
+    gatherLogFunction.isIntermediate = false
+    gatherLogFunction
+  }
+
+  /**
+   * Returns a temporary directory under this scatter gather directory.
+   * @param subDir directory under the scatter gather directory.
+   * @return temporary directory under this scatter gather directory.
+   */
+  private def scatterGatherCommandDir(subDir: String = "") = IOUtils.absolute(this.scatterGatherDirectory, this.jobName + "-sg/" + subDir)
+
+  /**
+   * Returns a sub directory under this job local directory.
+   * @param subDir directory under the job local directory.
+   * @return absolute path to a directory under the original job local directory.
+   */
+  private def scatterGatherLocalDir(subDir: String = "") = IOUtils.absolute(this.jobLocalDir, this.jobName + "-sg/" + subDir)
+}
diff --git a/public/gatk-queue/src/main/scala/org/broadinstitute/gatk/queue/function/scattergather/SimpleTextGatherFunction.scala b/public/gatk-queue/src/main/scala/org/broadinstitute/gatk/queue/function/scattergather/SimpleTextGatherFunction.scala
new file mode 100644
index 0000000..2c6aa58
--- /dev/null
+++ b/public/gatk-queue/src/main/scala/org/broadinstitute/gatk/queue/function/scattergather/SimpleTextGatherFunction.scala
@@ -0,0 +1,89 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.queue.function.scattergather
+
+import org.broadinstitute.gatk.queue.function.InProcessFunction
+import org.broadinstitute.gatk.queue.QException
+import java.io.PrintWriter
+import org.apache.commons.io.{LineIterator, IOUtils, FileUtils}
+
+/**
+ * Merges a text file.
+ */
+class SimpleTextGatherFunction extends GatherFunction with InProcessFunction {
+  def run() = {
+    waitForGatherParts
+    if (gatherParts.size < 1) {
+      throw new QException("No files to gather to output: " + originalOutput)
+    } else if (gatherParts.size == 1) {
+      FileUtils.copyFile(gatherParts(0), originalOutput)
+    } else {
+      val writer = new PrintWriter(originalOutput)
+      try {
+        var startLine = 0
+
+        val readerA = FileUtils.lineIterator(gatherParts(0))
+        val readerB = FileUtils.lineIterator(gatherParts(1))
+        try {
+          var headersMatch = true
+          while (headersMatch) {
+            if (readerA.hasNext && readerB.hasNext) {
+              val headerA = readerA.nextLine
+              val headerB = readerB.nextLine
+              headersMatch = headerA == headerB
+              if (headersMatch) {
+                startLine += 1
+                writer.println(headerA)
+              }
+            } else {
+              headersMatch = false
+            }
+          }
+        } finally {
+          LineIterator.closeQuietly(readerA)
+          LineIterator.closeQuietly(readerB)
+        }
+
+        for (file <- gatherParts) {
+          val reader = FileUtils.lineIterator(file)
+          try {
+            var lineNum = 0
+            while (reader.hasNext && lineNum < startLine) {
+              reader.nextLine
+              lineNum += 1
+            }
+            while (reader.hasNext)
+              writer.println(reader.nextLine)
+          } finally {
+            LineIterator.closeQuietly(reader)
+          }
+        }
+      } finally {
+        IOUtils.closeQuietly(writer)
+      }
+    }
+  }
+}
diff --git a/public/gatk-queue/src/main/scala/org/broadinstitute/gatk/queue/library/clf/vcf/VCFExtractIntervals.scala b/public/gatk-queue/src/main/scala/org/broadinstitute/gatk/queue/library/clf/vcf/VCFExtractIntervals.scala
new file mode 100644
index 0000000..e3b936f
--- /dev/null
+++ b/public/gatk-queue/src/main/scala/org/broadinstitute/gatk/queue/library/clf/vcf/VCFExtractIntervals.scala
@@ -0,0 +1,46 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.queue.library.clf.vcf
+
+import java.io.File
+import org.broadinstitute.gatk.utils.commandline.{Argument, Output, Input}
+import org.broadinstitute.gatk.queue.function.CommandLineFunction
+
+class VCFExtractIntervals(inVCF: File, outList: File, passOnly: Boolean ) extends CommandLineFunction {
+  def this(vcf: File, list: File ) = this(vcf,list,false)
+  def this(vcf: File) = this(vcf, new File(vcf.getAbsolutePath.replace("vcf","intervals.list")),false)
+  def this(vcf: File, removeFilters: Boolean) = this(vcf, new File(vcf.getAbsolutePath.replace("vcf","intervals.list")), removeFilters)
+
+  @Input(doc="The VCF from which to extract an interval list") var inputVCF : File = inVCF
+  @Output(doc="The file to write the interval list to") var outputList : File = outList
+  @Argument(doc="Whether to use all sites, or only the unfiltered sites") var usePFOnly: Boolean = passOnly
+
+  def commandLine = {
+    if ( usePFOnly ) "grep PASS %s | awk '{print $1\":\"$2}' | uniq > %s".format(inputVCF.getAbsolutePath,outputList.getAbsolutePath)
+    else "grep -v \\\\# %s | awk '{print $1\":\"$2}' | uniq > %s".format(inputVCF.getAbsolutePath,outputList.getAbsolutePath)
+  }
+
+}
\ No newline at end of file
diff --git a/public/gatk-queue/src/main/scala/org/broadinstitute/gatk/queue/library/clf/vcf/VCFExtractSamples.scala b/public/gatk-queue/src/main/scala/org/broadinstitute/gatk/queue/library/clf/vcf/VCFExtractSamples.scala
new file mode 100644
index 0000000..799061a
--- /dev/null
+++ b/public/gatk-queue/src/main/scala/org/broadinstitute/gatk/queue/library/clf/vcf/VCFExtractSamples.scala
@@ -0,0 +1,58 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.queue.library.clf.vcf
+
+import java.io.File
+import collection.JavaConversions._
+import org.broadinstitute.gatk.utils.commandline._
+import org.broadinstitute.gatk.queue.function.CommandLineFunction
+import org.broadinstitute.gatk.utils.text.XReadLines
+
+class VCFExtractSamples(inVCF: File, outVCF: File, samples: List[String]) extends CommandLineFunction {
+  @Input(doc="input VCF from which to extract samples") var inputVCF : File = inVCF
+  @Output(doc="output VCF to write extracted samples to") var outputVCF : File = outVCF
+  @Argument(doc="List of samples to extract from the VCF") var sampleList : List[String] = samples
+
+  var sampleGrep : String = _
+
+  def this(in: File, out: File, samples: File) = this(in,out, (new XReadLines(samples)).readLines.toList)
+
+  override def freezeFieldValues = {
+    this.logger.warn("Note: Using VCFExtractSamples invalidates AC/AF/AN annotations. This is an explicit warning.")
+    sampleGrep = "'" + sampleList.reduceLeft(_ + "|" + _) + "'"
+    super.freezeFieldValues
+  }
+
+  def commandLine = {
+
+    var first : String = "head -n 500 %s | grep \\\\#\\\\# > %s".format(inputVCF.getAbsolutePath,outputVCF.getAbsolutePath)
+    var second : String = "head -n 500 %s | grep \\\\#CHR | tr '\\t' '\\n' | awk '{print ++count\"\\t\"$1}' ".format(inputVCF.getAbsolutePath)
+    second += "| egrep %s | awk '{print $1}' | tr '\\n' ',' | xargs -i cut -f1-9,\\{\\} %s | grep -v \\\\#\\\\# >> %s".format(sampleGrep,inputVCF.getAbsolutePath,outputVCF.getAbsolutePath)
+
+    first+" ; "+second
+  }
+
+}
\ No newline at end of file
diff --git a/public/gatk-queue/src/main/scala/org/broadinstitute/gatk/queue/library/ipf/SortByRef.scala b/public/gatk-queue/src/main/scala/org/broadinstitute/gatk/queue/library/ipf/SortByRef.scala
new file mode 100644
index 0000000..0ee38e9
--- /dev/null
+++ b/public/gatk-queue/src/main/scala/org/broadinstitute/gatk/queue/library/ipf/SortByRef.scala
@@ -0,0 +1,82 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.queue.library.ipf
+
+import collection.JavaConversions._
+import org.broadinstitute.gatk.queue.function.InProcessFunction
+import org.broadinstitute.gatk.utils.commandline._
+import org.broadinstitute.gatk.utils.text.XReadLines
+import java.io.{PrintStream, PrintWriter, File}
+import collection.immutable.HashMap
+
+
+class SortByRef( input: File, reference: File, output: File ) extends InProcessFunction {
+  @Input(doc="The file to be sorted") var inFile: File = input
+  @Input(doc="The reference fasta index") var fai: File = reference
+  @Output(doc="The file to write the sorted file to") var outFile :  File = output
+  @Argument(doc="The character or expression that separates entries") var separator : String = "\t"
+  @Argument(doc="The position of the contig in the file (1-based)") var pos: Int = 1
+  @Argument(doc="Comment characters (lines will be brought to file head)") var comment: List[String] = List("#")
+
+  val COMMENT_STRING = "@#!"
+
+  var contigMap: List[(String,PrintWriter,File)] = Nil;
+
+  def entryToTriplet( line : String ) : (String,PrintWriter,File) = {
+    val ctig : String = line.split("\t",2)(0)
+    val tmpf : File = File.createTempFile("sbr",".tmp")
+    val pw : PrintWriter = new PrintWriter(new PrintStream(tmpf))
+    return (ctig,pw,tmpf)
+  }
+
+  def contigVal( line : String ) : PrintWriter = {
+
+    if ( contigMap.size < 1 ) { // no contigs
+      contigMap :+= entryToTriplet(COMMENT_STRING+"\t.")
+      contigMap ++= ( new XReadLines(fai)).readLines.map( entryToTriplet(_)).toList
+    }
+
+    if ( comment.contains(line.charAt(0).toString) ) {
+      return contigMap.find( u => u._1.equals(COMMENT_STRING)).head._2;
+    }
+
+    val matches = contigMap.find( u => u._1.equals(line.split(separator)(pos-1)))
+    if ( matches.isEmpty ) {
+      System.out.println("Empty match for "+line)
+      return contigMap(0)._2
+    } else { return matches.head._2 }
+  }
+
+  def run = {
+    var w : PrintWriter = new PrintWriter(new PrintStream(outFile))
+    System.out.println("Writing to temp files...")
+    ( new XReadLines(inFile) ).readLines.foreach( u => contigVal(u).println(u) )
+    contigMap.foreach( u => u._2.close )
+    System.out.println("Concatenating...")
+    contigMap.map( u => new XReadLines(u._3) ).foreach( u => asScalaIterator(u).foreach(u => w.println(u)))
+    w.close()
+  }
+}
\ No newline at end of file
diff --git a/public/gatk-queue/src/main/scala/org/broadinstitute/gatk/queue/library/ipf/vcf/VCFExtractIntervals.scala b/public/gatk-queue/src/main/scala/org/broadinstitute/gatk/queue/library/ipf/vcf/VCFExtractIntervals.scala
new file mode 100644
index 0000000..8abcf5b
--- /dev/null
+++ b/public/gatk-queue/src/main/scala/org/broadinstitute/gatk/queue/library/ipf/vcf/VCFExtractIntervals.scala
@@ -0,0 +1,85 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.queue.library.ipf.vcf
+
+import collection.JavaConversions._
+import org.broadinstitute.gatk.queue.function.InProcessFunction
+import org.broadinstitute.gatk.utils.commandline._
+import org.broadinstitute.gatk.utils.text.XReadLines
+import java.io.{PrintStream, PrintWriter, File}
+
+class VCFExtractIntervals(inVCF: File, outList: File, useFilterSites: Boolean) extends InProcessFunction {
+  def this(in : File, out: File) = this(in,out,true)
+  def this(in : File) = this(in,new File(in.getAbsolutePath.replace(".vcf",".intervals.list")),true)
+
+  @Input(doc="The VCF to convert to an interval list") var vcfIn : File = inVCF
+  @Output(doc="The intervals file to write to") var listOut : File = outList
+  @Argument(doc="Keep filtered sites?") var keepFilters : Boolean = useFilterSites
+
+  var out : PrintWriter = _
+
+  def run = {
+    out = new PrintWriter(new PrintStream(listOut))
+    var elems = asScalaIterator(new XReadLines(vcfIn)).map(vcf2int).filter(p => !p.equals(""))
+    var prev : String = null
+    if ( elems.hasNext ) {
+      prev = elems.next
+    }
+    var cur : String = null
+    if ( elems.hasNext ) {
+      cur = elems.next
+      while ( elems.hasNext ) {
+        out.printf("%s%n",prev)
+        while ( cur.equals(prev) && elems.hasNext && !cur.equals("") ) {
+          cur = elems.next
+        }
+
+        if ( ! cur.equals(prev) ) {
+          if ( elems.hasNext ) {
+            prev = cur
+            cur = elems.next
+          }
+        }
+      }
+      out.printf("%s%n",prev)
+      out.printf("%s%n",cur)
+    } else {
+      out.printf("%s%n",prev)
+    }
+
+    out.close
+  }
+
+  def vcf2int( vcfLine: String ) : String = {
+    var spline = vcfLine.split("\t")
+    if ( ! vcfLine.startsWith("#") && (spline(6).equals("PASS") || spline(6).equals(".") || keepFilters) ) {
+      return("%s:%s".format(spline(0),spline(1)))
+    } else {
+      return ""
+    }
+  }
+
+}
\ No newline at end of file
diff --git a/public/gatk-queue/src/main/scala/org/broadinstitute/gatk/queue/library/ipf/vcf/VCFExtractSamples.scala b/public/gatk-queue/src/main/scala/org/broadinstitute/gatk/queue/library/ipf/vcf/VCFExtractSamples.scala
new file mode 100644
index 0000000..99571e9
--- /dev/null
+++ b/public/gatk-queue/src/main/scala/org/broadinstitute/gatk/queue/library/ipf/vcf/VCFExtractSamples.scala
@@ -0,0 +1,62 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.queue.library.ipf.vcf
+
+import org.broadinstitute.gatk.queue.function.InProcessFunction
+import org.broadinstitute.gatk.utils.text.XReadLines
+import collection.JavaConversions._
+import org.broadinstitute.gatk.utils.commandline._
+import java.io.{PrintWriter, PrintStream, File}
+
+class VCFExtractSamples(inVCF: File, outVCF: File, samples: List[String]) extends InProcessFunction {
+  def this(in: File, out: File, samples: File) = this(in,out, (new XReadLines(samples)).readLines.toList)
+
+  @Input(doc="VCF from which to extract samples") var inputVCF : File = inVCF
+  @Output(doc="VCF to which to write the sample-subset vcf") var outputVCF : File = outVCF
+  @Argument(doc="The samples to extract from the VCF") var extractSamples : List[String] = samples
+
+  var out : PrintWriter = _
+  var columns : List[Int] = (0 to 8).toList
+
+  def run = {
+    out = new PrintWriter(new PrintStream(outputVCF))
+    asScalaIterator(new XReadLines(inputVCF)).foreach(subset)
+    out.close
+  }
+
+  def subset( line : String ) {
+    if ( line.startsWith("##") ) {
+      out.print("%s%n".format(line))
+    } else {
+      val spline = line.split("\t")
+      if ( spline(0).equals("#CHROM") ) {
+        columns ++= spline.zipWithIndex.filter( p => samples.contains(p._1) ).map( p => p._2 )
+      }
+
+      out.print("%s%n".format(columns.map(p => spline(p)).reduceLeft(_ + "\t" + _)))
+    }
+  }
+}
\ No newline at end of file
diff --git a/public/gatk-queue/src/main/scala/org/broadinstitute/gatk/queue/library/ipf/vcf/VCFExtractSites.scala b/public/gatk-queue/src/main/scala/org/broadinstitute/gatk/queue/library/ipf/vcf/VCFExtractSites.scala
new file mode 100644
index 0000000..5bd25bf
--- /dev/null
+++ b/public/gatk-queue/src/main/scala/org/broadinstitute/gatk/queue/library/ipf/vcf/VCFExtractSites.scala
@@ -0,0 +1,99 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.queue.library.ipf.vcf
+
+import collection.JavaConversions._
+import org.broadinstitute.gatk.queue.function.InProcessFunction
+import org.broadinstitute.gatk.utils.commandline._
+import org.broadinstitute.gatk.utils.text.XReadLines
+import java.io.{PrintStream, PrintWriter, File}
+
+
+class VCFExtractSites( vcf: File, output: File) extends InProcessFunction {
+  @Input(doc="VCF file from which to extract sites") var inVCF: File = vcf
+  @Output(doc="Sites VCF file to write to") var outVCF: File = output
+  @Argument(doc="Keep non-PASS sites") var keepFilters: Boolean = false
+  @Argument(doc="Keep info field") var keepInfo : Boolean = true
+  @Argument(doc="Keep qual field") var keepQual : Boolean = true
+
+  def lineMap( line: String ) : String = {
+    if ( line.startsWith("##") ) { return line }
+    var spline = line.split("\t",9)
+    if ( spline(0).startsWith("#")) { return spline.slice(0,8).reduceLeft( _+"\t"+_) }
+
+    if ( spline(6) == "PASS" || keepFilters ) {
+      var buf = new StringBuffer(spline.slice(0,5).reduceLeft(_ + "\t" + _ ))
+      if ( keepQual ) {
+        buf.append("\t%s".format(spline(5)))
+      } else {
+        buf.append("\t.")
+      }
+
+      buf.append("\tPASS")
+
+      if ( keepInfo ) {
+        buf.append("\t%s".format(spline(7)))
+      } else {
+        buf.append("\t.")
+      }
+
+      return buf.toString
+    }
+
+    return ""
+  }
+
+  def lineMapDebug( line: String ) : String = {
+    System.out.printf("Input: %s%n ",line)
+    val o = lineMap(line)
+    System.out.printf("Output: %s%n",o)
+
+    return o
+  }
+
+  def debugFilter ( line : String ) : Boolean = {
+    System.out.printf("Filter In: %s%n",line)
+    if ( line != "" ) {
+      System.out.printf("Not filtered %n")
+      return true
+    } else {
+      System.out.printf("Filtered%n")
+      return false
+    }
+  }
+
+  def debugPrint(line: String, k : PrintWriter) : Unit = {
+    System.out.printf("Into print: %s%n",line)
+    k.println(line)
+  }
+
+  def run {
+    var w: PrintWriter = new PrintWriter( new PrintStream(outVCF) )
+    asScalaIterator[String](new XReadLines(inVCF)).map(lineMap).filter( u => u != "" ).foreach( u => w.println(u) )
+    w.close
+  }
+
+}
diff --git a/public/gatk-queue/src/main/scala/org/broadinstitute/gatk/queue/library/ipf/vcf/VCFSimpleMerge.scala b/public/gatk-queue/src/main/scala/org/broadinstitute/gatk/queue/library/ipf/vcf/VCFSimpleMerge.scala
new file mode 100644
index 0000000..b3093c8
--- /dev/null
+++ b/public/gatk-queue/src/main/scala/org/broadinstitute/gatk/queue/library/ipf/vcf/VCFSimpleMerge.scala
@@ -0,0 +1,107 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.queue.library.ipf.vcf
+
+import collection.JavaConversions._
+import org.broadinstitute.gatk.queue.function.InProcessFunction
+import org.broadinstitute.gatk.utils.commandline._
+import org.broadinstitute.gatk.utils.text.XReadLines
+import java.io.{PrintStream, PrintWriter, File}
+import htsjdk.samtools.{SAMSequenceRecord, SAMSequenceDictionary}
+import org.broadinstitute.gatk.utils.{GenomeLocParser, GenomeLoc}
+
+class VCFSimpleMerge extends InProcessFunction {
+  @Input(doc="VCFs to be merged") var vcfs: List[File] = Nil
+  @Input(doc="The reference fasta index") var fai: File = _
+  @Output(doc="The final VCF to write to") var outVCF : File = _
+
+  class PeekableXRL(f : File ) {
+    var xrl : XReadLines = new XReadLines(f)
+    var cur : String = if ( xrl.hasNext ) xrl.next else null
+
+    def hasNext : Boolean = xrl.hasNext || cur != null
+    def next : String = {
+      var toRet : String = cur
+      if ( xrl.hasNext ) {
+        cur = xrl.next
+      } else {
+        cur = null
+      }
+
+      return toRet
+    }
+
+    def peek : String = cur
+
+  }
+
+  def readHeader( xrl : PeekableXRL ) : List[String] = {
+    var toRet : List[String] = Nil
+    while ( xrl.hasNext && xrl.peek.startsWith("#") ) {
+      toRet :+= xrl.next
+    }
+
+    return toRet
+  }
+
+  def genomeLoc(xrl : PeekableXRL, p : GenomeLocParser ) : GenomeLoc = {
+    var slp = xrl.peek.split("\t",3)
+    return p.createGenomeLoc(slp(0),Integer.parseInt(slp(1)),Integer.parseInt(slp(1)))
+  }
+
+  def run = {
+    var ssd : SAMSequenceDictionary = new SAMSequenceDictionary
+    for ( line <- (new XReadLines(fai)).readLines ) {
+      val spl = line.split("\\s+")
+      val ctig = spl(0)
+      val pos = Integer.parseInt(spl(1))
+      ssd.addSequence(new SAMSequenceRecord(ctig,pos))
+    }
+
+    var xrls : List[PeekableXRL] = vcfs.map( new PeekableXRL(_) )
+
+    var w : PrintWriter = new PrintWriter(new PrintStream(outVCF))
+
+    readHeader(xrls(0)).foreach(u => w.println(u) )
+
+    xrls.foreach(readHeader(_))
+
+    val glp : GenomeLocParser = new GenomeLocParser(ssd)
+
+    var last = ""
+    while ( ! xrls.forall( u => ! u.hasNext ) ) {
+      val first = xrls.filter( u => u.hasNext).reduceLeft( (a,b) => if ( genomeLoc(a,glp).isBefore(genomeLoc(b,glp))) a else b )
+      if ( ! first.peek.equals(last) ) {
+        w.println(first.peek)
+      }
+      last = first.next
+    }
+
+    w.close
+
+  }
+
+}
\ No newline at end of file
diff --git a/public/gatk-queue/src/main/scala/org/broadinstitute/gatk/queue/util/ClassFieldCache.scala b/public/gatk-queue/src/main/scala/org/broadinstitute/gatk/queue/util/ClassFieldCache.scala
new file mode 100644
index 0000000..82b8ca5
--- /dev/null
+++ b/public/gatk-queue/src/main/scala/org/broadinstitute/gatk/queue/util/ClassFieldCache.scala
@@ -0,0 +1,219 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.queue.util
+
+import org.broadinstitute.gatk.utils.commandline._
+import scala.Some
+import org.broadinstitute.gatk.queue.QException
+import collection.JavaConversions._
+import java.io.File
+
+/**
+ * Utilities and a static cache of argument fields for various classes populated by the parsingEngine.
+ * Because this class works with the ParsingEngine it can walk @ArgumentCollection hierarchies.
+ */
+object ClassFieldCache {
+  var parsingEngine: ParsingEngine = _
+
+
+  //
+  // Field caching
+  //
+
+  /**
+   * The list of fields defined on a class
+   * @param clazz The class to lookup fields.
+   */
+  private class ClassFields(clazz: Class[_]) {
+    /** The complete list of fields on this CommandLineFunction. */
+    val functionFields: Seq[ArgumentSource] = parsingEngine.extractArgumentSources(clazz).toSeq
+    /** The @Input fields on this CommandLineFunction. */
+    val inputFields: Seq[ArgumentSource] = functionFields.filter(source => ReflectionUtils.hasAnnotation(source.field, classOf[Input]))
+    /** The @Output fields on this CommandLineFunction. */
+    val outputFields: Seq[ArgumentSource] = functionFields.filter(source => ReflectionUtils.hasAnnotation(source.field, classOf[Output]))
+    /** The @Argument fields on this CommandLineFunction. */
+    val argumentFields: Seq[ArgumentSource] = functionFields.filter(source => ReflectionUtils.hasAnnotation(source.field, classOf[Argument]))
+  }
+
+  /**
+   * The mapping from class to fields.
+   */
+  private var classFieldsMap = Map.empty[Class[_], ClassFields]
+
+  /**
+   * Returns the fields for a class.
+   * @param clazz Class to retrieve fields for.
+   * @return the fields for the class.
+   */
+  private def classFields(clazz: Class[_]): ClassFields = {
+    classFieldsMap.get(clazz) match {
+      case Some(classFields) => classFields
+      case None =>
+        val classFields = new ClassFields(clazz)
+        classFieldsMap += clazz -> classFields
+        classFields
+    }
+  }
+
+  /**
+   * Returns the field on clazz.
+   * @param clazz Class to search.
+   * @param name Name of the field to return.
+   * @return Argument source for the field.
+   */
+  def findField(clazz: Class[_], name: String): ArgumentSource = {
+    classFields(clazz).functionFields.find(_.field.getName == name) match {
+      case Some(source) => source
+      case None => throw new QException("Could not find a field on class %s with name %s".format(clazz, name))
+    }
+  }
+
+  /**
+   * Returns the Seq of fields for a QFunction class.
+   * @param clazz Class to retrieve fields for.
+   * @return the fields of the class.
+   */
+  def classFunctionFields(clazz: Class[_]): Seq[ArgumentSource] = classFields(clazz).functionFields
+
+  /**
+   * Returns the Seq of inputs for a QFunction class.
+   * @param clazz Class to retrieve inputs for.
+   * @return the inputs of the class.
+   */
+  def classInputFields(clazz: Class[_]): Seq[ArgumentSource] = classFields(clazz).inputFields
+
+  /**
+   * Returns the Seq of outputs for a QFunction class.
+   * @param clazz Class to retrieve outputs for.
+   * @return the outputs of the class.
+   */
+  def classOutputFields(clazz: Class[_]): Seq[ArgumentSource] = classFields(clazz).outputFields
+
+  /**
+   * Returns the Seq of arguments for a QFunction class.
+   * @param clazz Class to retrieve arguments for.
+   * @return the arguments of the class.
+   */
+  def classArgumentFields(clazz: Class[_]): Seq[ArgumentSource] = classFields(clazz).argumentFields
+
+
+  //
+  // get/set fields as AnyRef
+  //
+
+  /**
+   * Gets the value of a field.
+   * @param obj Top level object storing the source info.
+   * @param source Field to get the value for.
+   * @return value of the field.
+   */
+  def getFieldValue(obj: AnyRef, source: ArgumentSource) = ReflectionUtils.getValue(invokeObj(obj, source), source.field)
+
+  /**
+   * Gets the value of a field.
+   * @param obj Top level object storing the source info.
+   * @param source Field to set the value for.
+   * @return value of the field.
+   */
+  def setFieldValue(obj: AnyRef, source: ArgumentSource, value: Any) = ReflectionUtils.setValue(invokeObj(obj, source), source.field, value)
+
+  /**
+   * Walks gets the fields in this object or any collections in that object
+   * recursively to find the object holding the field to be retrieved or set.
+   * @param obj Top level object storing the source info.
+   * @param source Field find the invoke object for.
+   * @return Object to invoke the field on.
+   */
+  private def invokeObj(obj: AnyRef, source: ArgumentSource) = source.parentFields.foldLeft[AnyRef](obj)(ReflectionUtils.getValue(_, _))
+
+
+  //
+  // get/set fields as java.io.File
+  //
+
+  /**
+   *  Gets the files from the fields.  The fields must be a File, a FileExtension, or a Seq or Set of either.
+   * @param obj Top level object storing the source info.
+   * @param fields Fields to get files.
+   * @return for the fields.
+   */
+  def getFieldFiles(obj: AnyRef, fields: Seq[ArgumentSource]): Seq[File] = {
+    var files: Seq[File] = Nil
+    for (field <- fields)
+      files ++= getFieldFiles(obj, field)
+    files.distinct
+  }
+
+  /**
+   * Gets the files from the field.  The field must be a File, a FileExtension, or a Seq or Set of either.
+   * @param obj Top level object storing the source info.
+   * @param field Field to get files.
+   * @return for the field.
+   */
+  def getFieldFiles(obj: AnyRef, field: ArgumentSource): Seq[File] = {
+    var files: Seq[File] = Nil
+    CollectionUtils.foreach(getFieldValue(obj, field), (fieldValue) => {
+      val file = fieldValueToFile(field, fieldValue)
+      if (file != null)
+        files :+= file
+    })
+    files.distinct
+  }
+
+  /**
+   *  Gets the file from the field.  The field must be a File or a FileExtension and not a Seq or Set.
+   * @param obj Top level object storing the source info.
+   * @param field Field to get the file.
+   * @return for the field.
+   */
+  def getFieldFile(obj: AnyRef, field: ArgumentSource): File =
+    fieldValueToFile(field, getFieldValue(obj, field))
+
+  /**
+   * Converts the field value to a file.  The field must be a File or a FileExtension.
+   * @param field Field to get the file.
+   * @param value Value of the File or FileExtension or null.
+   * @return Null if value is null, otherwise the File.
+   * @throws QException if the value is not a File or FileExtension.
+   */
+  private def fieldValueToFile(field: ArgumentSource, value: Any): File = value match {
+    case file: File => file
+    case null => null
+    case unknown => throw new QException("Non-file found.  Try removing the annotation, change the annotation to @Argument, or extend File with FileExtension: %s: %s".format(field.field, unknown))
+  }
+
+
+  //
+  // other utilities
+  //
+
+  /**
+   * Retrieves the fullName of the argument
+   * @param field ArgumentSource to check
+   * @return Full name of the argument source
+   */
+  def fullName(field: ArgumentSource) = field.createArgumentDefinitions().get(0).fullName
+}
diff --git a/public/gatk-queue/src/main/scala/org/broadinstitute/gatk/queue/util/CollectionUtils.scala b/public/gatk-queue/src/main/scala/org/broadinstitute/gatk/queue/util/CollectionUtils.scala
new file mode 100644
index 0000000..5c0be04
--- /dev/null
+++ b/public/gatk-queue/src/main/scala/org/broadinstitute/gatk/queue/util/CollectionUtils.scala
@@ -0,0 +1,116 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.queue.util
+
+/**
+ * Utilities that try to deeply apply operations to collections, specifically Traversable and Option.
+ */
+object CollectionUtils {
+
+  /**
+   * Loops though a collection running the function f on each value.
+   * @param value The value to run f on, or a collection of values for which f should be run on.
+   * @param f The function to run on value, or to run on the values within the collection.
+   * @return The updated value.
+   */
+  def updated(value: Any, f: Any => Any): Any = {
+    value match {
+      case traversable: Traversable[_] => traversable.map(updated(_, f))
+      case option: Option[_] => option.map(updated(_, f))
+      case x => f(x)
+    }
+  }
+
+  /**
+   * Utility for recursively processing collections.
+   * @param value Initial the collection to be processed
+   * @param f a function that will be called for each (item, collection) in the initial collection
+   */
+  def foreach(value: Any, f: (Any, Any) => Unit): Unit = {
+    value match {
+      case traversable: Traversable[_] =>
+        for (item <- traversable) {
+          f(item, traversable)
+          foreach(item, f)
+        }
+      case option: Option[_] =>
+        for (item <- option) {
+          f(item, option)
+          foreach(item, f)
+        }
+      case _ =>
+    }
+  }
+
+  /**
+   * Utility for recursively processing collections.
+   * @param value Initial the collection to be processed
+   * @param f a function that will be called for each (item, collection) in the initial collection
+   */
+  def foreach(value: Any, f: (Any) => Unit): Unit = {
+    value match {
+      case traversable: Traversable[_] => traversable.foreach(f(_))
+      case option: Option[_] => option.foreach(f(_))
+      case item => f(item)
+    }
+  }
+
+  /**
+   * Removes empty values from collections.
+   * @param value The collection to test.
+   * @return The value if it is not a collection, otherwise the collection with nulls and empties removed.
+   */
+  private def filterNotNullOrNotEmpty[T](value: T): T = {
+    val newValue = value match {
+      case traversable: Traversable[_] => traversable.map(filterNotNullOrNotEmpty(_)).filter(isNotNullOrNotEmpty(_)).asInstanceOf[T]
+      case option: Option[_] => option.map(filterNotNullOrNotEmpty(_)).filter(isNotNullOrNotEmpty(_)).asInstanceOf[T]
+      case x => x
+    }
+    newValue
+  }
+
+
+  /**
+   * Returns true if the value is null or an empty collection.
+   * @param value Value to test for null, or a collection to test if it is empty.
+   * @return true if the value is null, or false if the collection is empty, otherwise true.
+   */
+  def isNullOrEmpty(value: Any): Boolean = !isNotNullOrNotEmpty(value)
+
+  /**
+   * Returns false if the value is null or an empty collection.
+   * @param value Value to test for null, or a collection to test if it is empty.
+   * @return false if the value is null, or false if the collection is empty, otherwise true.
+   */
+  def isNotNullOrNotEmpty(value: Any): Boolean = {
+    val result = value match {
+      case traversable: Traversable[_] => !filterNotNullOrNotEmpty(traversable).isEmpty
+      case option: Option[_] => !filterNotNullOrNotEmpty(option).isEmpty
+      case x => x != null
+    }
+    result
+  }
+}
diff --git a/public/gatk-queue/src/main/scala/org/broadinstitute/gatk/queue/util/EmailMessage.scala b/public/gatk-queue/src/main/scala/org/broadinstitute/gatk/queue/util/EmailMessage.scala
new file mode 100644
index 0000000..e38183a
--- /dev/null
+++ b/public/gatk-queue/src/main/scala/org/broadinstitute/gatk/queue/util/EmailMessage.scala
@@ -0,0 +1,140 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.queue.util
+
+import org.apache.commons.mail.{MultiPartEmail, EmailAttachment}
+import java.io.{IOException, FileReader, File}
+import javax.mail.internet.InternetAddress
+import scala.collection.JavaConversions._
+
+/**
+ * Encapsulates a message to be sent over email.
+ */
+class EmailMessage extends Logging {
+  var from: String = _
+  var to: Seq[String] = Nil
+  var cc: Seq[String] = Nil
+  var bcc: Seq[String] = Nil
+  var subject: String = _
+  var body: String = _
+  var attachments: Seq[File] = Nil
+
+  /**
+   * Sends the email and throws an exception if the email can't be sent.
+   * @param settings The server settings for the email.
+   */
+  def send(settings: EmailSettings) = {
+    val email = new MultiPartEmail
+
+    email.setHostName(settings.host)
+    email.setSmtpPort(settings.port)
+    email.setTLS(settings.tls)
+    if (settings.ssl) {
+      email.setSSL(true)
+      email.setSslSmtpPort(settings.port.toString)
+    }
+
+    if (settings.username != null && (settings.password != null || settings.passwordFile != null)) {
+      val password = {
+        if (settings.passwordFile != null) {
+          val reader = new FileReader(settings.passwordFile)
+          try {
+            org.apache.commons.io.IOUtils.toString(reader).replaceAll("\\r|\\n", "")
+          } finally {
+            org.apache.commons.io.IOUtils.closeQuietly(reader)
+          }
+        } else {
+          settings.password
+        }
+      }
+      email.setAuthentication(settings.username, password)
+    }
+
+    email.setFrom(this.from)
+    if (this.subject != null)
+      email.setSubject(this.subject)
+    if (this.body != null)
+      email.setMsg(this.body)
+    if (this.to.size > 0)
+      email.setTo(convert(this.to))
+    if (this.cc.size > 0)
+      email.setCc(convert(this.cc))
+    if (this.bcc.size > 0)
+      email.setBcc(convert(this.bcc))
+
+    for (file <- this.attachments) {
+      val attachment = new EmailAttachment
+      attachment.setDisposition(EmailAttachment.ATTACHMENT)
+      attachment.setPath(file.getAbsolutePath)
+      attachment.setDescription(file.getAbsolutePath)
+      attachment.setName(file.getName)
+      email.attach(attachment)
+    }
+
+    email.send
+  }
+
+  /**
+   * Tries twice 30 seconds apart to send the email.  Then logs the message if it can't be sent.
+   * @param settings The server settings for the email.
+   */
+  def trySend(settings: EmailSettings) = {
+    try {
+      Retry.attempt(() => send(settings), .5)
+    } catch {
+      case e: RetryException=> logger.error("Error sending message: %n%s".format(this.toString), e)
+    }
+  }
+
+  /**
+   * Converts the email addresses to a collection of InternetAddress which can bypass client side validation,
+   * specifically that the domain is specified.
+   * @param addresses Seq of email addresses.
+   * @return java.util.List of InternetAddress'es
+   */
+  private def convert(addresses: Seq[String]): java.util.List[InternetAddress] = {
+    addresses.map(address => new InternetAddress(address, false))
+  }
+
+  override def toString = {
+    """
+    |From: %s
+    |To: %s
+    |Cc: %s
+    |Bcc: %s
+    |Subject: %s
+    |
+    |%s
+    |
+    |Attachments:
+    |%s
+    |""".stripMargin.format(
+      this.from, this.to.mkString(", "),
+      this.cc.mkString(", "), this.bcc.mkString(", "),
+      this.subject, this.body,
+      this.attachments.map(_.getAbsolutePath).mkString("%n".format()))
+  }
+}
diff --git a/public/gatk-queue/src/main/scala/org/broadinstitute/gatk/queue/util/EmailSettings.scala b/public/gatk-queue/src/main/scala/org/broadinstitute/gatk/queue/util/EmailSettings.scala
new file mode 100644
index 0000000..d315410
--- /dev/null
+++ b/public/gatk-queue/src/main/scala/org/broadinstitute/gatk/queue/util/EmailSettings.scala
@@ -0,0 +1,55 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.queue.util
+
+import java.io.File
+import org.broadinstitute.gatk.utils.commandline.Argument
+
+/**
+ * Email server settings.
+ */
+class EmailSettings {
+  @Argument(doc="Email SMTP host. Defaults to localhost.", shortName="emailHost", fullName="emailSmtpHost", required=false)
+  var host = "localhost"
+
+  @Argument(doc="Email SMTP port. Defaults to 465 for ssl, otherwise 25.", shortName="emailPort", fullName="emailSmtpPort", required=false)
+  var port = 25
+
+  @Argument(doc="Email should use TLS. Defaults to false.", shortName="emailTLS", fullName="emailUseTLS", required=false)
+  var tls = false
+
+  @Argument(doc="Email should use SSL. Defaults to false.", shortName="emailSSL", fullName="emailUseSSL", required=false)
+  var ssl = false
+
+  @Argument(doc="Email SMTP username. Defaults to none.", shortName="emailUser", fullName="emailUsername", required=false)
+  var username: String = _
+
+  @Argument(doc="Email SMTP password file. Defaults to none.", shortName="emailPassFile", fullName="emailPasswordFile", required=false)
+  var passwordFile: File = _
+
+  @Argument(doc="Email SMTP password. Defaults to none. Not secure! See emailPassFile.", shortName="emailPass", fullName="emailPassword", required=false)
+  var password: String = _
+}
diff --git a/public/gatk-queue/src/main/scala/org/broadinstitute/gatk/queue/util/Logging.scala b/public/gatk-queue/src/main/scala/org/broadinstitute/gatk/queue/util/Logging.scala
new file mode 100644
index 0000000..3a83a2f
--- /dev/null
+++ b/public/gatk-queue/src/main/scala/org/broadinstitute/gatk/queue/util/Logging.scala
@@ -0,0 +1,62 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.queue.util
+
+import org.apache.log4j._
+import java.lang.{Throwable, String}
+import org.apache.log4j.spi.{ThrowableInformation, LocationInfo, LoggingEvent, LoggerFactory}
+import java.util.Hashtable
+
+/**
+ * A mixin to add logging to a class
+ */
+trait Logging {
+  private val className = this.getClass.getName
+  protected lazy val logger = Logger.getLogger(className, Logging.factory)
+}
+
+object Logging {
+  private object factory extends LoggerFactory {
+    /**
+     * Do not log the scala generated class name after "$".
+     * All these shenanigans can be avoided if we use the format
+     * string c{1} (the name passed to Logger.getLogger)
+     * versus C{1} (the class name of the calling method)
+     */
+    def makeNewLoggerInstance(name: String) = new Logger(name) {
+      override def forcedLog(fqcn: String, level: Priority, message: AnyRef, t: Throwable) = {
+        // Strip off the "$" from the class name.
+        val info = new LocationInfo(new Throwable, fqcn) { override def getClassName = super.getClassName.takeWhile(_ != '$') }
+        // If the following aren't retrieved here, LoggingEvent will NOT lazy load them.
+        val throwable = if (t == null) null else new ThrowableInformation(t)
+        val ndc = NDC.get
+        val mdc = MDC.getContext().asInstanceOf[Hashtable[_,_]];
+        callAppenders(new LoggingEvent(fqcn, this, System.currentTimeMillis,
+          level.asInstanceOf[Level], message, null, throwable, ndc, info, mdc))
+      }
+    }
+  }
+}
diff --git a/public/gatk-queue/src/main/scala/org/broadinstitute/gatk/queue/util/PrimitiveOptionConversions.scala b/public/gatk-queue/src/main/scala/org/broadinstitute/gatk/queue/util/PrimitiveOptionConversions.scala
new file mode 100644
index 0000000..edaf802
--- /dev/null
+++ b/public/gatk-queue/src/main/scala/org/broadinstitute/gatk/queue/util/PrimitiveOptionConversions.scala
@@ -0,0 +1,142 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.queue.util
+
+import scala.language.implicitConversions
+
+/**
+ * An importable object that provides automatic primitive to option conversion.
+ */
+object PrimitiveOptionConversions {
+
+  // Conversion from Option
+  implicit def byteOption2byte(x: Option[Byte]): Byte = x.get
+  implicit def shortOption2short(x: Option[Short]): Short = x.get
+  implicit def charOption2char(x: Option[Char]): Char = x.get
+  implicit def intOption2int(x: Option[Int]): Int = x.get
+  implicit def longOption2long(x: Option[Long]): Long = x.get
+  implicit def floatOption2float(x: Option[Float]): Float = x.get
+  implicit def doubleOption2double(x: Option[Double]): Double = x.get
+  implicit def booleanOption2boolean(x: Option[Boolean]): Boolean = x.get
+
+  // Conversion to Option
+  implicit def byte2byteOption(x: Byte): Option[Byte] = Some(x)
+  implicit def short2shortOption(x: Short): Option[Short] = Some(x)
+  implicit def char2charOption(x: Char): Option[Char] = Some(x)
+  implicit def int2intOption(x: Int): Option[Int] = Some(x)
+  implicit def long2longOption(x: Long): Option[Long] = Some(x)
+  implicit def float2floatOption(x: Float): Option[Float] = Some(x)
+  implicit def double2doubleOption(x: Double): Option[Double] = Some(x)
+  implicit def boolean2booleanOption(x: Boolean): Option[Boolean] = Some(x)
+
+  // Narrowing for constants to byte, short, and float
+  implicit def int2byteOption(x: Int): Option[Byte] = Some(x.toByte)
+  implicit def int2shortOption(x: Int): Option[Short] = Some(x.toShort)
+  implicit def double2floatOption(x: Float): Option[Float] = Some(x.toFloat)
+
+  // Widening
+  implicit def byte2shortOption(x: Byte): Option[Short] = Some(x.toShort)
+  implicit def byte2intOption(x: Byte): Option[Int] = Some(x.toInt)
+  implicit def byte2longOption(x: Byte): Option[Long] = Some(x.toLong)
+  implicit def byte2floatOption(x: Byte): Option[Float] = Some(x.toFloat)
+  implicit def byte2doubleOption(x: Byte): Option[Double] = Some(x.toDouble)
+
+  implicit def short2intOption(x: Short): Option[Int] = Some(x.toInt)
+  implicit def short2longOption(x: Short): Option[Long] = Some(x.toLong)
+  implicit def short2floatOption(x: Short): Option[Float] = Some(x.toFloat)
+  implicit def short2doubleOption(x: Short): Option[Double] = Some(x.toDouble)
+
+  implicit def char2intOption(x: Char): Option[Int] = Some(x.toInt)
+  implicit def char2longOption(x: Char): Option[Long] = Some(x.toLong)
+  implicit def char2floatOption(x: Char): Option[Float] = Some(x.toFloat)
+  implicit def char2doubleOption(x: Char): Option[Double] = Some(x.toDouble)
+
+  implicit def int2longOption(x: Int): Option[Long] = Some(x.toLong)
+  implicit def int2floatOption(x: Int): Option[Float] = Some(x.toFloat)
+  implicit def int2doubleOption(x: Int): Option[Double] = Some(x.toDouble)
+
+  implicit def long2floatOption(x: Long): Option[Float] = Some(x.toFloat)
+  implicit def long2doubleOption(x: Long): Option[Double] = Some(x.toDouble)
+
+  implicit def float2doubleOption(x: Float): Option[Double] = Some(x.toDouble)
+
+}
+
+/**
+ * A trait that exposes the above functions to all sub classes as well.
+ */
+trait PrimitiveOptionConversions {
+  // How to we import these implicit definitions into the trait so that they are seen by objects extending a trait?
+  // import PrimitiveOptionConversion._ inside of a trait does not seem to work?
+  // Declaring them in a trait like this does work but does not seem scala-ish.
+
+  implicit def byteOption2byte(x: Option[Byte]): Byte = PrimitiveOptionConversions.byteOption2byte(x)
+  implicit def shortOption2short(x: Option[Short]): Short = PrimitiveOptionConversions.shortOption2short(x)
+  implicit def charOption2char(x: Option[Char]): Char = PrimitiveOptionConversions.charOption2char(x)
+  implicit def intOption2int(x: Option[Int]): Int = PrimitiveOptionConversions.intOption2int(x)
+  implicit def longOption2long(x: Option[Long]): Long = PrimitiveOptionConversions.longOption2long(x)
+  implicit def floatOption2float(x: Option[Float]): Float = PrimitiveOptionConversions.floatOption2float(x)
+  implicit def doubleOption2double(x: Option[Double]): Double = PrimitiveOptionConversions.doubleOption2double(x)
+  implicit def booleanOption2boolean(x: Option[Boolean]): Boolean = PrimitiveOptionConversions.booleanOption2boolean(x)
+
+  implicit def byte2byteOption(x: Byte): Option[Byte] = PrimitiveOptionConversions.byte2byteOption(x)
+  implicit def short2shortOption(x: Short): Option[Short] = PrimitiveOptionConversions.short2shortOption(x)
+  implicit def char2charOption(x: Char): Option[Char] = PrimitiveOptionConversions.char2charOption(x)
+  implicit def int2intOption(x: Int): Option[Int] = PrimitiveOptionConversions.int2intOption(x)
+  implicit def long2longOption(x: Long): Option[Long] = PrimitiveOptionConversions.long2longOption(x)
+  implicit def float2floatOption(x: Float): Option[Float] = PrimitiveOptionConversions.float2floatOption(x)
+  implicit def double2doubleOption(x: Double): Option[Double] = PrimitiveOptionConversions.double2doubleOption(x)
+  implicit def boolean2booleanOption(x: Boolean): Option[Boolean] = PrimitiveOptionConversions.boolean2booleanOption(x)
+
+  implicit def int2byteOption(x: Int): Option[Byte] = PrimitiveOptionConversions.int2byteOption(x)
+  implicit def int2shortOption(x: Int): Option[Short] = PrimitiveOptionConversions.int2shortOption(x)
+  implicit def double2floatOption(x: Float): Option[Float] = PrimitiveOptionConversions.double2floatOption(x)
+
+  implicit def byte2shortOption(x: Byte): Option[Short] = PrimitiveOptionConversions.byte2shortOption(x)
+  implicit def byte2intOption(x: Byte): Option[Int] = PrimitiveOptionConversions.byte2intOption(x)
+  implicit def byte2longOption(x: Byte): Option[Long] = PrimitiveOptionConversions.byte2longOption(x)
+  implicit def byte2floatOption(x: Byte): Option[Float] = PrimitiveOptionConversions.byte2floatOption(x)
+  implicit def byte2doubleOption(x: Byte): Option[Double] = PrimitiveOptionConversions.byte2doubleOption(x)
+
+  implicit def short2intOption(x: Short): Option[Int] = PrimitiveOptionConversions.short2intOption(x)
+  implicit def short2longOption(x: Short): Option[Long] = PrimitiveOptionConversions.short2longOption(x)
+  implicit def short2floatOption(x: Short): Option[Float] = PrimitiveOptionConversions.short2floatOption(x)
+  implicit def short2doubleOption(x: Short): Option[Double] = PrimitiveOptionConversions.short2doubleOption(x)
+
+  implicit def char2intOption(x: Char): Option[Int] = PrimitiveOptionConversions.char2intOption(x)
+  implicit def char2longOption(x: Char): Option[Long] = PrimitiveOptionConversions.char2longOption(x)
+  implicit def char2floatOption(x: Char): Option[Float] = PrimitiveOptionConversions.char2floatOption(x)
+  implicit def char2doubleOption(x: Char): Option[Double] = PrimitiveOptionConversions.char2doubleOption(x)
+
+  implicit def int2longOption(x: Int): Option[Long] = PrimitiveOptionConversions.int2longOption(x)
+  implicit def int2floatOption(x: Int): Option[Float] = PrimitiveOptionConversions.int2floatOption(x)
+  implicit def int2doubleOption(x: Int): Option[Double] = PrimitiveOptionConversions.int2doubleOption(x)
+
+  implicit def long2floatOption(x: Long): Option[Float] = PrimitiveOptionConversions.long2floatOption(x)
+  implicit def long2doubleOption(x: Long): Option[Double] = PrimitiveOptionConversions.long2doubleOption(x)
+
+  implicit def float2doubleOption(x: Float): Option[Double] = PrimitiveOptionConversions.float2doubleOption(x)
+}
diff --git a/public/gatk-queue/src/main/scala/org/broadinstitute/gatk/queue/util/QJobReport.scala b/public/gatk-queue/src/main/scala/org/broadinstitute/gatk/queue/util/QJobReport.scala
new file mode 100644
index 0000000..be5a17f
--- /dev/null
+++ b/public/gatk-queue/src/main/scala/org/broadinstitute/gatk/queue/util/QJobReport.scala
@@ -0,0 +1,110 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.queue.util
+
+import org.broadinstitute.gatk.queue.function.QFunction
+import org.broadinstitute.gatk.engine.report.GATKReportTable
+import org.broadinstitute.gatk.queue.engine.JobRunInfo
+
+/**
+ * A mixin to add Job info to the class
+ */
+trait QJobReport extends Logging {
+  self: QFunction =>
+
+  protected var reportGroup: String = null
+  protected var userReportFeatures: Map[String, String] = Map()
+  protected var reportFeatures: Map[String, String] = Map()
+  protected var reportEnabled: Boolean = true
+
+  def includeInReport = reportEnabled
+  def enableReport() { reportEnabled = true }
+  def disableReport() { reportEnabled = false }
+
+  def setRunInfo(info: JobRunInfo) {
+    //logger.info("info " + info)
+    val runtimeFeatures = Map(
+      "iteration" -> 1,
+      "analysisName" -> getReportGroup,
+      "jobName" -> QJobReport.workAroundSameJobNames(this),
+      "intermediate" -> self.isIntermediate,
+      "exechosts" -> info.getExecHosts,
+      "startTime" -> info.getStartTime,
+      "doneTime" -> info.getDoneTime,
+      "formattedStartTime" -> info.getFormattedStartTime,
+      "formattedDoneTime" -> info.getFormattedDoneTime,
+      "runtime" -> info.getRuntimeInMs).mapValues((x:Any) => if (x != null) x.toString else "null")
+    reportFeatures = runtimeFeatures ++ userReportFeatures
+    // note -- by adding reportFeatures second we override iteration
+    // (or any other binding) with the user provided value
+  }
+
+  /** The report Group is the analysis name transform to only contain valid GATKReportTable characters */
+  def getReportGroup = self.analysisName.replaceAll(GATKReportTable.INVALID_TABLE_NAME_REGEX, "_")
+
+  def getReportFeatureNames: Seq[String] = reportFeatures.keys.toSeq
+  def getReportFeature(key: String): String = {
+    reportFeatures.get(key) match {
+      case Some(x) => x
+      case None =>
+        logger.warn("getReportFeature called with key %s but no value was found for group %s.  This can be caused by adding user-defined job features to a job with a generic name used elsewhere in the Queue script.  To fix the problem make sure that each group of commands with user-specific features has a unique analysisName".format(key, reportGroup))
+        "NA"
+    }
+  }
+
+  def getReportName: String = getReportFeature("jobName")
+
+  def configureJobReport(features: Map[String, Any]) {
+    this.userReportFeatures = features.mapValues(_.toString)
+  }
+
+  def addJobReportBinding(key: String, value: Any) {
+    this.userReportFeatures += (key -> value.toString)
+  }
+
+  // copy the QJobReport information -- todo : what's the best way to do this?
+  override def copySettingsTo(function: QFunction) {
+    self.copySettingsTo(function)
+    function.userReportFeatures = this.userReportFeatures
+    function.reportFeatures = this.reportFeatures
+  }
+}
+
+object QJobReport {
+  // todo -- fixme to have a unique name for Scatter/gather jobs as well
+  var seenCounter = 1
+  var seenNames = Set[String]()
+
+  def workAroundSameJobNames(func: QFunction):String = {
+    if ( seenNames.apply(func.jobName) ) {
+      seenCounter += 1
+      "%s_%d".format(func.jobName, seenCounter)
+    } else {
+      seenNames += func.jobName
+      func.jobName
+    }
+  }
+}
diff --git a/public/gatk-queue/src/main/scala/org/broadinstitute/gatk/queue/util/QJobsReporter.scala b/public/gatk-queue/src/main/scala/org/broadinstitute/gatk/queue/util/QJobsReporter.scala
new file mode 100644
index 0000000..b3b0b33
--- /dev/null
+++ b/public/gatk-queue/src/main/scala/org/broadinstitute/gatk/queue/util/QJobsReporter.scala
@@ -0,0 +1,122 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.queue.util
+
+import java.io.{PrintStream, File}
+import org.broadinstitute.gatk.utils.io.{Resource}
+import org.broadinstitute.gatk.queue.engine.{JobRunInfo, QGraph}
+import org.broadinstitute.gatk.queue.function.QFunction
+import org.broadinstitute.gatk.utils.R.{RScriptLibrary, RScriptExecutor}
+import org.broadinstitute.gatk.engine.report.{GATKReportTable, GATKReport}
+import org.broadinstitute.gatk.utils.exceptions.UserException
+import org.apache.commons.io.{FileUtils, IOUtils}
+
+/**
+ * Writes out RunInfo to a GATKReport
+ */
+class QJobsReporter(val disabled: Boolean, val reportFile: File, val pdfFile: Option[File]) extends Logging {
+  private val JOB_REPORT_QUEUE_SCRIPT = "queueJobReport.R"
+
+  /**
+   * Write out a job report based on the finished jobs graph
+   * @param jobGraph
+   * @param enabledPlotting if true, we will plot the report as well with the JOB_REPORT_QUEUE_SCRIPT
+   */
+  def write(jobGraph: QGraph, enabledPlotting: Boolean) {
+    if ( ! disabled ) {
+      logger.info("Writing JobLogging GATKReport to file " + reportFile)
+      printReport(jobGraph.getFunctionsAndStatus, reportFile)
+
+      if ( enabledPlotting )
+        pdfFile match {
+          case Some(file) =>
+            logger.info("Plotting JobLogging GATKReport to file " + file)
+            plotReport(reportFile, file)
+          case None =>
+        }
+    }
+  }
+
+  private def printReport(jobsRaw: Map[QFunction, JobRunInfo], dest: File) {
+    val jobs = jobsRaw.filter(_._2.isFilledIn).filter(_._1.includeInReport)
+    jobs foreach {case (qf, info) => qf.setRunInfo(info)}
+    val stream = new PrintStream(FileUtils.openOutputStream(dest))
+    try {
+      printJobLogging(jobs.keys.toSeq, stream)
+    } finally {
+      IOUtils.closeQuietly(stream)
+    }
+  }
+
+  private def plotReport(reportFile: File, pdfFile: File) {
+    val executor = new RScriptExecutor
+    executor.addLibrary(RScriptLibrary.GSALIB)
+    executor.addScript(new Resource(JOB_REPORT_QUEUE_SCRIPT, classOf[QJobReport]))
+    executor.addArgs(reportFile.getAbsolutePath, pdfFile.getAbsolutePath)
+    executor.exec()
+  }
+
+  /**
+   * Prints the JobLogging logs to a GATKReport.  First splits up the
+   * logs by group, and for each group generates a GATKReportTable
+   */
+  private def printJobLogging(logs: Seq[QFunction], stream: PrintStream) {
+    // create the report
+    val report: GATKReport = new GATKReport
+
+    // create a table for each group of logs
+    for ( (group, groupLogs) <- groupLogs(logs) ) {
+      val keys = logKeys(groupLogs)
+      report.addTable(group, "Job logs for " + group, keys.size)
+      val table: GATKReportTable = report.getTable(group)
+
+      // add the columns
+      keys.foreach(table.addColumn(_))
+      for (log <- groupLogs) {
+        for ( key <- keys )
+          table.set(log.getReportName, key, log.getReportFeature(key))
+      }
+    }
+
+    report.print(stream)
+  }
+
+  private def groupLogs(logs: Seq[QFunction]): Map[String, Seq[QFunction]] = {
+    logs.groupBy(_.getReportGroup)
+  }
+
+  private def logKeys(logs: Seq[QFunction]): Set[String] = {
+    // the keys should be the same for each log, but we will check that
+    val keys = Set[String](logs(0).getReportFeatureNames : _*)
+
+    for ( log <- logs )
+      if ( keys.sameElements(Set(log.getReportFeatureNames)) )
+        throw new UserException(("All JobLogging jobs in the same group must have the same set of features.  " +
+          "We found one with %s and another with %s").format(keys, log.getReportFeatureNames))
+
+    keys
+  }
+}
diff --git a/public/gatk-queue/src/main/scala/org/broadinstitute/gatk/queue/util/QScriptUtils.scala b/public/gatk-queue/src/main/scala/org/broadinstitute/gatk/queue/util/QScriptUtils.scala
new file mode 100644
index 0000000..3fbce22
--- /dev/null
+++ b/public/gatk-queue/src/main/scala/org/broadinstitute/gatk/queue/util/QScriptUtils.scala
@@ -0,0 +1,101 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.queue.util
+
+import java.io.File
+import io.Source._
+import htsjdk.samtools.{SAMReadGroupRecord, SAMFileReader}
+
+import collection.JavaConversions._
+
+
+/**
+ * Created by IntelliJ IDEA.
+ * User: carneiro
+ * Date: 7/14/11
+ * Time: 4:57 PM
+ */
+
+object QScriptUtils {
+
+  /**
+   * Takes a bam list file and produces a scala sequence with each file allowing the bam list
+   * to have empty lines and comment lines (lines starting with #).
+   */
+  def createSeqFromFile(in: File):Seq[File] = {
+    // If the file provided ends with .bam, .fasta, fastq or .fq, it is not a bam list, we treat it as a single file.
+    // and return a list with only this file.
+    if (in.toString.toUpperCase.endsWith(".BAM")   ||
+        in.toString.toUpperCase.endsWith(".FASTA") ||
+        in.toString.toUpperCase.endsWith(".FQ")    ||
+        in.toString.toUpperCase.endsWith("FASTQ") )
+      return Seq(in)
+
+    var list: Seq[File] = Seq()
+    for (file <- fromFile(in).getLines())
+      if (!file.startsWith("#") && !file.isEmpty )
+        list :+= new File(file.trim())
+//    list.sortWith(_.compareTo(_) < 0)
+    list
+  }
+
+  /**
+   * Returns the number of contigs in the BAM file header.
+   */
+  def getNumberOfContigs(bamFile: File): Int = {
+    val samReader = new SAMFileReader(bamFile)
+    samReader.getFileHeader.getSequenceDictionary.getSequences.size()
+  }
+
+  /**
+   * Check if there are multiple samples in a BAM file
+   */
+  def hasMultipleSamples(readGroups: Seq[SAMReadGroupRecord]): Boolean = {
+    var sample: String = ""
+    for (r <- readGroups) {
+      if (sample.isEmpty)
+        sample = r.getSample
+      else if (sample != r.getSample)
+          return true
+    }
+    false
+  }
+
+  /**
+   * Returns all distinct samples in the BAM file
+   *
+   * @param bam the bam file
+   * @return    a set with all distinct samples (in no particular order)
+   */
+  def getSamplesFromBAM(bam: File) : Set[String] = {
+    val reader = new SAMFileReader(bam)
+    var samples: Set[String] = Set()
+    for (rg <- reader.getFileHeader.getReadGroups) {
+      samples += rg.getSample
+    }
+    samples
+  }
+}
diff --git a/public/gatk-queue/src/main/scala/org/broadinstitute/gatk/queue/util/ReflectionUtils.scala b/public/gatk-queue/src/main/scala/org/broadinstitute/gatk/queue/util/ReflectionUtils.scala
new file mode 100644
index 0000000..d172e97
--- /dev/null
+++ b/public/gatk-queue/src/main/scala/org/broadinstitute/gatk/queue/util/ReflectionUtils.scala
@@ -0,0 +1,170 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.queue.util
+
+import org.broadinstitute.gatk.queue.QException
+import java.lang.annotation.Annotation
+import java.lang.reflect.{ParameterizedType, Field}
+import org.broadinstitute.gatk.utils.commandline.ClassType
+import org.broadinstitute.gatk.utils.classloader.JVMUtils
+
+/**
+ * A collection of scala extensions to the GATK JVMUtils.
+ */
+object ReflectionUtils {
+
+  /**
+   * Returns true if field has the annotation.
+   * @param field Field to check.
+   * @param annotation Class of the annotation to look for.
+   * @return true if field has the annotation.
+   */
+  def hasAnnotation(field: Field, annotation: Class[_ <: Annotation]) = field.getAnnotation(annotation) != null
+
+  /**
+   * Returns true if clazz or one of its superclasses has the annotation.
+   * @param clazz Class to check.
+   * @param annotation Class of the annotation to look for.
+   * @return true if field has the annotation.
+   */
+  def hasAnnotation(clazz: Class[_], annotation: Class[_ <: Annotation]) = {
+    var foundAnnotation = false
+    while (!foundAnnotation && clazz != null)
+      foundAnnotation = (clazz.getAnnotation(annotation) != null)
+    foundAnnotation
+  }
+
+  /**
+   * Gets the annotation or throws an exception if the annotation is not found.
+   * @param field Field to check.
+   * @param annotation Class of the annotation to look for.
+   * @return The annotation.
+   */
+  def getAnnotation[T <: Annotation](field: Field, annotation: Class[T]): T = {
+    field.getAnnotation(annotation) match {
+      case null =>
+        throw new QException("Field %s is missing annotation %s".format(field, annotation))
+      case fieldAnnotation => fieldAnnotation.asInstanceOf[T]
+    }
+  }
+
+  /**
+   * Gets the annotation or throws an exception if the annotation is not found.
+   * @param clazz Class to check.
+   * @param annotation Class of the annotation to look for.
+   * @return The annotation.
+   */
+  def getAnnotation[T <: Annotation](clazz: Class[_], annotation: Class[T]): T = {
+    var result: T = null.asInstanceOf[T]
+    while (result == null && clazz != null)
+      result = clazz.getAnnotation(annotation)
+    if (result == null)
+      throw new QException("Class %s is missing annotation %s".format(clazz, annotation))
+    result
+  }
+
+  /**
+   * Returns all the declared fields on a class in order of sub type to super type.
+   * @param clazz Base class to start looking for fields.
+   * @return Seq[Field] found on the class and all super classes.
+   */
+  def getAllFields(clazz: Class[_]) = getAllTypes(clazz).map(_.getDeclaredFields).flatMap(_.toSeq)
+
+  /**
+   * Gets all the types on a class in order of sub type to super type.
+   * @param clazz Base class.
+   * @return Seq[Class] including the class and all super classes.
+   */
+  def getAllTypes(clazz: Class[_]) = {
+    var types = Seq.empty[Class[_]]
+    var c = clazz
+    while (c != null) {
+      types :+= c
+      c = c.getSuperclass
+    }
+    types
+  }
+
+  /**
+   * Gets a field value using reflection.
+   * Attempts to use the scala getter then falls back to directly accessing the field.
+   * @param obj Object to inspect.
+   * @param field Field to retrieve.
+   * @return The field value.
+   */
+  def getValue(obj: AnyRef, field: Field): AnyRef =
+    try {
+      field.getDeclaringClass.getMethod(field.getName).invoke(obj)
+    } catch {
+      case e: NoSuchMethodException => JVMUtils.getFieldValue(field, obj)
+    }
+
+  /**
+   * Sets a field value using reflection.
+   * Attempts to use the scala setter then falls back to directly accessing the field.
+   * @param obj Object to inspect.
+   * @param field Field to set.
+   * @param value The new field value.
+   */
+  def setValue(obj: AnyRef, field: Field, value: Any) =
+    try {
+      field.getDeclaringClass.getMethod(field.getName+"_$eq", field.getType).invoke(obj, value.asInstanceOf[AnyRef])
+    } catch {
+      case e: NoSuchMethodException => JVMUtils.setFieldValue(field, obj, value)
+    }
+
+  /**
+   * Returns the collection type of a field or throws an exception if the field contains more than one parameterized type, or the collection type cannot be found.
+   * @param field Field to retrieve the collection type.
+   * @return The collection type for the field.
+   */
+  def getCollectionType(field: Field) = {
+    getGenericTypes(field) match {
+      case Some(classes) =>
+        if (classes.length > 1)
+          throw new IllegalArgumentException("Field contains more than one generic type: " + field)
+        classes(0)
+      case None =>
+        throw new QException("Generic type not set for collection.  Did it declare an @ClassType?: " + field)
+    }
+  }
+
+  /**
+   * Returns the generic types for a field or None.
+   * @param field Field to retrieve the collection type.
+   * @return The array of classes that are in the collection type, or None if the type cannot be found.
+   */
+  private def getGenericTypes(field: Field): Option[Array[Class[_]]] = {
+    // TODO: Refactor: based on java code in org.broadinstitute.gatk.utils.commandline.ArgumentTypeDescriptor
+    // If this is a parameterized collection, find the contained type.  If blow up if only one type exists.
+    if (hasAnnotation(field, classOf[ClassType])) {
+      Some(Array(getAnnotation(field, classOf[ClassType]).value))
+    } else if (field.getGenericType.isInstanceOf[ParameterizedType]) {
+      val parameterizedType = field.getGenericType.asInstanceOf[ParameterizedType]
+      Some(parameterizedType.getActualTypeArguments.map(_.asInstanceOf[Class[_]]))
+    } else None
+  }
+}
diff --git a/public/gatk-queue/src/main/scala/org/broadinstitute/gatk/queue/util/RemoteFile.scala b/public/gatk-queue/src/main/scala/org/broadinstitute/gatk/queue/util/RemoteFile.scala
new file mode 100644
index 0000000..1410813
--- /dev/null
+++ b/public/gatk-queue/src/main/scala/org/broadinstitute/gatk/queue/util/RemoteFile.scala
@@ -0,0 +1,42 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.queue.util
+
+import java.io.File
+import org.broadinstitute.gatk.utils.io.FileExtension
+import java.util.Date
+import java.net.URL
+
+/**
+ * An extension of java.io.File that can be pulled from or pushed to a remote location.
+ */
+trait RemoteFile extends File with FileExtension {
+  def pullToLocal()
+  def pushToRemote()
+  def deleteRemote()
+  def createUrl(expiration: Date): URL
+  def remoteDescription: String
+}
diff --git a/public/gatk-queue/src/main/scala/org/broadinstitute/gatk/queue/util/RemoteFileConverter.scala b/public/gatk-queue/src/main/scala/org/broadinstitute/gatk/queue/util/RemoteFileConverter.scala
new file mode 100644
index 0000000..b38b27a
--- /dev/null
+++ b/public/gatk-queue/src/main/scala/org/broadinstitute/gatk/queue/util/RemoteFileConverter.scala
@@ -0,0 +1,46 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.queue.util
+
+import java.io.File
+
+trait RemoteFileConverter {
+  type RemoteFileType <: RemoteFile
+
+  /**
+   * If this remote file creator is capable of converting to a remote file.
+   * @return true if ready to convert
+   */
+  def convertToRemoteEnabled: Boolean
+
+  /**
+   * Converts to a remote file
+   * @param file The original file
+   * @param name A "name" to use for the remote file
+   * @return The new version of this remote file.
+   */
+  def convertToRemote(file: File, name: String): RemoteFileType
+}
diff --git a/public/gatk-queue/src/main/scala/org/broadinstitute/gatk/queue/util/Retry.scala b/public/gatk-queue/src/main/scala/org/broadinstitute/gatk/queue/util/Retry.scala
new file mode 100644
index 0000000..8d1c1cf
--- /dev/null
+++ b/public/gatk-queue/src/main/scala/org/broadinstitute/gatk/queue/util/Retry.scala
@@ -0,0 +1,70 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.queue.util
+
+import org.broadinstitute.gatk.queue.util.TextFormatUtils._
+
+/**
+ * Utilities for retrying a function and waiting a number of minutes.
+ */
+object Retry extends Logging {
+  /**
+   * Attempt the function and return the value on success.
+   * Each time the function fails the stack trace is logged.
+   * @param f Function to run and return its value.
+   * @param wait The length in minutes to wait before each attempt.
+   * @throws RetryException when all retries are exhausted.
+   * @return The successful result of f.
+   */
+  def attempt[A](f: () => A, wait: Double*): A = {
+    var count = 0
+    var success = false
+    val tries = wait.size + 1
+    var result = null.asInstanceOf[A]
+    while (!success && count < tries) {
+      try {
+        result = f()
+        success = true
+      } catch {
+        case e: Exception=> {
+          count += 1
+          if (count < tries) {
+            val minutes = wait(count-1)
+            logger.error("Caught error during attempt %s of %s."
+                    .format(count, tries), e)
+            logger.error("Retrying in %.1f minute%s.".format(minutes, plural(minutes)))
+            Thread.sleep((minutes * 1000 * 60).toLong)
+          } else {
+            logger.error("Caught error during attempt %s of %s. Giving up."
+                    .format(count, tries), e)
+            throw new RetryException("Gave up after %s attempts.".format(tries), e)
+          }
+        }
+      }
+    }
+    result
+  }
+}
diff --git a/public/gatk-queue/src/main/scala/org/broadinstitute/gatk/queue/util/RetryException.scala b/public/gatk-queue/src/main/scala/org/broadinstitute/gatk/queue/util/RetryException.scala
new file mode 100644
index 0000000..ffd69cc
--- /dev/null
+++ b/public/gatk-queue/src/main/scala/org/broadinstitute/gatk/queue/util/RetryException.scala
@@ -0,0 +1,34 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.queue.util
+
+import org.broadinstitute.gatk.queue.QException
+
+/**
+ * Thrown after giving up on retrying.
+ */
+class RetryException(private val message: String, private val throwable: Throwable)
+        extends QException(message, throwable) {}
diff --git a/public/gatk-queue/src/main/scala/org/broadinstitute/gatk/queue/util/ScalaCompoundArgumentTypeDescriptor.scala b/public/gatk-queue/src/main/scala/org/broadinstitute/gatk/queue/util/ScalaCompoundArgumentTypeDescriptor.scala
new file mode 100644
index 0000000..80ab068
--- /dev/null
+++ b/public/gatk-queue/src/main/scala/org/broadinstitute/gatk/queue/util/ScalaCompoundArgumentTypeDescriptor.scala
@@ -0,0 +1,114 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.queue.util
+
+import collection.JavaConversions._
+import org.broadinstitute.gatk.queue.QException
+import java.lang.Class
+import org.broadinstitute.gatk.utils.commandline.{ArgumentMatches, ArgumentSource, ArgumentTypeDescriptor, ParsingEngine}
+import org.broadinstitute.gatk.utils.exceptions.UserException
+import java.lang.reflect.Type
+
+/**
+ * An ArgumentTypeDescriptor that can parse the scala collections.
+ */
+class ScalaCompoundArgumentTypeDescriptor extends ArgumentTypeDescriptor {
+
+  /**
+   * Checks if the class type is a scala collection.
+   * @param classType Class type to check.
+   * @return true if the class is a Seq, Set, or an Option.
+   */
+  def supports(classType: Class[_]) = isCompound(classType)
+
+  /**
+   * Checks if the class type is a scala collection.
+   * @param source Argument source to check.
+   * @return true if the source is a Seq, Set, or an Option.
+   */
+  override def isMultiValued(source: ArgumentSource) = isCompound(source.field.getType)
+
+  /**
+   * Checks if the class type is a scala collection.
+   * @param classType Class type to check.
+   * @return true if the class is a Seq, Set, or an Option.
+   */
+  private def isCompound(classType: Class[_]) = {
+    classOf[Seq[_]].isAssignableFrom(classType) ||
+    classOf[List[_]].isAssignableFrom(classType) || // see comment below re: List vs. Seq
+    classOf[Set[_]].isAssignableFrom(classType) ||
+    classOf[Option[_]].isAssignableFrom(classType)
+  }
+
+  /**
+   * Parses the argument matches based on the class type of the argument source's field.
+   * @param parsingEngine Parsing engine.
+   * @param source Argument source that contains the field being populated.
+   * @param typeType Type of the argument source's field.
+   * @param argumentMatches The argument match strings that were found for this argument source.
+   * @return The parsed object.
+   */
+  def parse(parsingEngine: ParsingEngine, source: ArgumentSource, typeType: Type, argumentMatches: ArgumentMatches) = {
+    parse(parsingEngine,source, ArgumentTypeDescriptor.makeRawTypeIfNecessary(typeType), argumentMatches)
+  }
+  
+  def parse(parsingEngine: ParsingEngine, source: ArgumentSource, classType: Class[_], argumentMatches: ArgumentMatches) = {
+    val componentType = ReflectionUtils.getCollectionType(source.field)
+    if (componentType == classOf[java.lang.Object])
+      throw new UserException.CannotExecuteQScript("Please also include a @ClassType(classOf[<primitive type>]) annotation on field: " + source.field + ". Example: @ClassType(classOf[Double]). The scala generic type for the field was subjected to java/scala type erasure and is not available via reflection.")
+    val componentArgumentParser = parsingEngine.selectBestTypeDescriptor(componentType)
+
+    if (classOf[Seq[_]].isAssignableFrom(classType)) {
+      var seq = Seq.empty[Any]
+      for (argumentMatch <- argumentMatches)
+        for (value <- argumentMatch)
+          seq :+= componentArgumentParser.parse(parsingEngine, source, componentType, new ArgumentMatches(value))
+      seq
+    } else if (classOf[List[_]].isAssignableFrom(classType)) {
+      // QScripts should be using the interface Seq instead of the class List.
+      // Leaving this here for now for legacy support until the effects of switching have been tested for a while. -ks
+      var list = List.empty[Any]
+      for (argumentMatch <- argumentMatches)
+        for (value <- argumentMatch)
+          list :+= componentArgumentParser.parse(parsingEngine, source, componentType, new ArgumentMatches(value))
+      list
+    } else if (classOf[Set[_]].isAssignableFrom(classType)) {
+      var set = Set.empty[Any]
+      for (argumentMatch <- argumentMatches)
+        for (value <- argumentMatch)
+            set += componentArgumentParser.parse(parsingEngine, source, componentType, new ArgumentMatches(value))
+      set
+    } else if (classOf[Option[_]].isAssignableFrom(classType)) {
+      if (argumentMatches.size > 1)
+        throw new QException("Unable to set Option to multiple values: " + argumentMatches.mkString(" "))
+      else if (argumentMatches.size == 1)
+        Some(componentArgumentParser.parse(parsingEngine, source, componentType, argumentMatches))
+      else
+        None
+    } else
+      throw new QException("Unsupported compound argument type: " + classType)
+  }
+}
diff --git a/public/gatk-queue/src/main/scala/org/broadinstitute/gatk/queue/util/ShellUtils.scala b/public/gatk-queue/src/main/scala/org/broadinstitute/gatk/queue/util/ShellUtils.scala
new file mode 100644
index 0000000..02d767a
--- /dev/null
+++ b/public/gatk-queue/src/main/scala/org/broadinstitute/gatk/queue/util/ShellUtils.scala
@@ -0,0 +1,61 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.queue.util
+
+import java.lang.IllegalArgumentException
+
+object ShellUtils {
+
+  /**
+   * Escapes the String it's passed so that it will be interpreted literally when
+   * parsed by sh/bash. Can correctly escape all characters except \0, \r, and \n
+   *
+   * Replaces all instances of ' with '\'', and then surrounds the resulting String
+   * with single quotes.
+   *
+   * Examples:
+   * ab   ->  'ab'
+   * a'b  ->  'a'\''b'
+   * ''   ->  ''\'''\'''
+   *
+   * Since \' is not supported inside single quotes in the shell (ie., '\'' does not work),
+   * whenever we encounter a single quote we need to terminate the existing single-quoted
+   * string, place the \' outside of single quotes, and then start a new single-quoted
+   * string. As long as we don't insert spaces between the separate strings, the shell will
+   * concatenate them together into a single argument value for us.
+   *
+   * @param str the String to escape
+   * @return the same String quoted so that it will be interpreted literally when
+   *         parsed by sh/bash
+   */
+  def escapeShellArgument ( str : String ) : String = {
+    if ( str == null ) {
+      throw new IllegalArgumentException("escapeShellArgument() was passed a null String")
+    }
+
+    "'" + str.replaceAll("'", "'\\\\''") + "'"
+  }
+}
\ No newline at end of file
diff --git a/public/gatk-queue/src/main/scala/org/broadinstitute/gatk/queue/util/StringFileConversions.scala b/public/gatk-queue/src/main/scala/org/broadinstitute/gatk/queue/util/StringFileConversions.scala
new file mode 100644
index 0000000..ee21380
--- /dev/null
+++ b/public/gatk-queue/src/main/scala/org/broadinstitute/gatk/queue/util/StringFileConversions.scala
@@ -0,0 +1,113 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.queue.util
+
+import java.io.{Serializable, File}
+import scala.language.implicitConversions
+
+/**
+ * Converts String to/from File
+ * The method signatures are based on the compiler errors reported by StringFileConversionsUnitTest.
+ * The implementations are based on the runtime errors reported by StringFileConversionsUnitTest.
+ */
+object StringFileConversions {
+  implicit def stringAsFile(x: String): File = {
+    if (x == null) null else new File(x)
+  }
+
+  implicit def fileAsString(x: File): String = {
+    if (x == null) null else x.getPath
+  }
+
+  // Possible to get the invariants, covariants, contravariants, upper type bounds, lower type bounds
+  // and mixins all correct so this doesn't have to be duplicated with concrete implementations?
+  // http://programming-scala.labs.oreilly.com/ch12.html is your friend.
+
+  implicit def stringsAsFiles(x: Seq[Comparable[_ >: String with File <: Comparable[_ >: String with File <: Serializable] with Serializable] with Serializable]): Seq[File] = {
+    x.map(_ match {
+      case string: String => stringAsFile(string)
+      case file: File => file
+      case null => null
+    })
+  }
+
+  implicit def filesAsStrings(x: Seq[Comparable[_ >: File with String <: Comparable[_ >: File with String <: Serializable] with Serializable] with Serializable]): Seq[String] = {
+    x.map(_ match {
+      case file: File => fileAsString(file)
+      case string: String => string
+      case null => null
+    })
+  }
+
+  implicit def stringsAsFilesList(x: List[Comparable[_ >: String with File <: Comparable[_ >: String with File <: Serializable] with Serializable] with Serializable]): List[File] = {
+    x.map(_ match {
+      case string: String => stringAsFile(string)
+      case file: File => file
+      case null => null
+    })
+  }
+
+  implicit def filesAsStringsList(x: List[Comparable[_ >: File with String <: Comparable[_ >: File with String <: Serializable] with Serializable] with Serializable]): List[String] = {
+    x.map(_ match {
+      case file: File => fileAsString(file)
+      case string: String => string
+      case null => null
+    })
+  }
+
+}
+
+/**
+ * Converts String to/from File
+ * The method signatures are based on the compiler errors reported by StringFileConversionsUnitTest.
+ * The implementations are based on the runtime errors reported by StringFileConversionsUnitTest.
+ */
+trait StringFileConversions {
+  implicit def stringAsFile(x: String): File = {
+    StringFileConversions.stringAsFile(x)
+  }
+
+  implicit def fileAsString(x: File): String = {
+    StringFileConversions.fileAsString(x)
+  }
+
+  implicit def stringsAsFiles(x: Seq[Comparable[_ >: String with File <: Comparable[_ >: String with File <: Serializable] with Serializable] with Serializable]): Seq[File] = {
+    StringFileConversions.stringsAsFiles(x)
+  }
+
+  implicit def filesAsStrings(x: Seq[Comparable[_ >: File with String <: Comparable[_ >: File with String <: Serializable] with Serializable] with Serializable]): Seq[String] = {
+    StringFileConversions.filesAsStrings(x)
+  }
+
+  implicit def stringsAsFilesList(x: List[Comparable[_ >: String with File <: Comparable[_ >: String with File <: Serializable] with Serializable] with Serializable]): List[File] = {
+    StringFileConversions.stringsAsFilesList(x)
+  }
+
+  implicit def filesAsStringsList(x: List[Comparable[_ >: File with String <: Comparable[_ >: File with String <: Serializable] with Serializable] with Serializable]): List[String] = {
+    StringFileConversions.filesAsStringsList(x)
+  }
+
+}
diff --git a/public/gatk-queue/src/main/scala/org/broadinstitute/gatk/queue/util/SystemUtils.scala b/public/gatk-queue/src/main/scala/org/broadinstitute/gatk/queue/util/SystemUtils.scala
new file mode 100644
index 0000000..cf85372
--- /dev/null
+++ b/public/gatk-queue/src/main/scala/org/broadinstitute/gatk/queue/util/SystemUtils.scala
@@ -0,0 +1,67 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.queue.util
+
+import java.net.InetAddress
+import java.io.File
+import io.Source
+
+/**
+ * A collection of various system utilities.
+ */
+object SystemUtils extends Logging {
+  private val localAddress = {
+    try {
+      InetAddress.getLocalHost
+    } catch {
+      case e: Exception =>
+        InetAddress.getLoopbackAddress
+    }
+  }
+  val inetAddress = localAddress.getHostAddress
+  val canonicalHostName = localAddress.getCanonicalHostName
+
+  val hostName = {
+    if (canonicalHostName != inetAddress)
+      canonicalHostName
+    else
+      localAddress.getHostName
+  }
+
+  val mailName = {
+    val mailnameFile = new File("/etc/mailname")
+    if (mailnameFile.exists)
+      try {
+        Source.fromFile(mailnameFile).mkString.trim
+      } catch {
+        case e: Exception =>
+          logger.error("Unabled to read mail domain. Using hostname.", e)
+          hostName.split('.').takeRight(2).mkString(".")
+      }
+    else
+      hostName.split('.').takeRight(2).mkString(".")
+  }
+}
diff --git a/public/gatk-queue/src/main/scala/org/broadinstitute/gatk/queue/util/TextFormatUtils.scala b/public/gatk-queue/src/main/scala/org/broadinstitute/gatk/queue/util/TextFormatUtils.scala
new file mode 100644
index 0000000..c776dd5
--- /dev/null
+++ b/public/gatk-queue/src/main/scala/org/broadinstitute/gatk/queue/util/TextFormatUtils.scala
@@ -0,0 +1,56 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.queue.util
+
+object TextFormatUtils {
+  /**
+   * Returns the string "s" if x is greater than 1.
+   * @param x Value to test.
+   * @return "s" if x is greater than one else "".
+   */
+  def plural(x: Int) = if (x > 1) "s" else ""
+
+  /**
+   * Returns the string "s" if x is greater than 1.
+   * @param x Value to test.
+   * @return "s" if x is greater than one else "".
+   */
+  def plural(x: Long) = if (x > 1) "s" else ""
+
+  /**
+   * Returns the string "s" if x is not equal to 1.
+   * @param x Value to test.
+   * @return "s" if x is greater than one else "".
+   */
+  def plural(x: Float) = if (x != 1) "s" else ""
+
+  /**
+   * Returns the string "s" if x is not equal to 1.
+   * @param x Value to test.
+   * @return "s" if x is greater than one else "".
+   */
+  def plural(x: Double) = if (x != 1) "s" else ""
+}
diff --git a/public/gatk-queue/src/main/scala/org/broadinstitute/gatk/queue/util/VCF_BAM_utilities.scala b/public/gatk-queue/src/main/scala/org/broadinstitute/gatk/queue/util/VCF_BAM_utilities.scala
new file mode 100644
index 0000000..9de4b28
--- /dev/null
+++ b/public/gatk-queue/src/main/scala/org/broadinstitute/gatk/queue/util/VCF_BAM_utilities.scala
@@ -0,0 +1,79 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.queue.util
+
+import java.io.File
+import org.apache.commons.io.FilenameUtils
+import scala.io.Source._
+import htsjdk.samtools.SAMFileReader
+import htsjdk.variant.vcf.{VCFHeader, VCFCodec}
+import scala.collection.JavaConversions._
+import htsjdk.tribble.AbstractFeatureReader
+
+object VCF_BAM_utilities {
+
+  def getSamplesFromVCF(vcfFile: File): List[String] = {
+    AbstractFeatureReader.getFeatureReader(vcfFile.getPath, new VCFCodec()).getHeader.asInstanceOf[VCFHeader].getGenotypeSamples.toList
+  }
+
+  def getSamplesInBAM(bam: File): List[String] = {
+    return new SAMFileReader(bam).getFileHeader().getReadGroups().toList.map(srgr => srgr.getSample()).toSet.toList
+  }
+
+  def parseBAMsInput(bamsIn: File): List[File] = FilenameUtils.getExtension(bamsIn.getPath) match {
+    case "bam" => return List(bamsIn)
+    case "list" => return (for (line <- fromFile(bamsIn).getLines) yield new File(line)).toList
+    case _ => throw new RuntimeException("Unexpected BAM input type: " + bamsIn + "; only permitted extensions are .bam and .list")
+  }
+
+  def getMapOfBAMsForSample(bams: List[File]): scala.collection.mutable.Map[String, scala.collection.mutable.Set[File]] = {
+    var m = scala.collection.mutable.Map.empty[String, scala.collection.mutable.Set[File]]
+
+    for (bam <- bams) {
+      val bamSamples: List[String] = getSamplesInBAM(bam)
+      for (s <- bamSamples) {
+        if (!m.contains(s))
+          m += s -> scala.collection.mutable.Set.empty[File]
+
+        m(s) += bam
+      }
+    }
+
+      return m
+  }
+
+  def findBAMsForSamples(samples: List[String], sampleToBams: scala.collection.mutable.Map[String, scala.collection.mutable.Set[File]]): List[File] = {
+    var s = scala.collection.mutable.Set.empty[File]
+
+    for (sample <- samples) {
+      if (sampleToBams.contains(sample))
+        s ++= sampleToBams(sample)
+    }
+
+    val l: List[File] = Nil
+    return l ++ s
+  }
+}
diff --git a/public/gatk-queue/src/test/scala/org/broadinstitute/gatk/queue/function/CommandLineFunctionUnitTest.scala b/public/gatk-queue/src/test/scala/org/broadinstitute/gatk/queue/function/CommandLineFunctionUnitTest.scala
new file mode 100644
index 0000000..351fb71
--- /dev/null
+++ b/public/gatk-queue/src/test/scala/org/broadinstitute/gatk/queue/function/CommandLineFunctionUnitTest.scala
@@ -0,0 +1,196 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.queue.function
+
+import org.testng.Assert
+import org.testng.annotations.{DataProvider, Test}
+
+// Since "protected" in Scala is subclass-only and doesn't allow package-level access, we need to
+// extend a class if we want to test it
+class CommandLineFunctionUnitTest extends CommandLineFunction {
+  def commandLine = ""
+
+  @DataProvider( name="formatArgumentTestData" )
+  def formatArgumentDataProvider = {
+    Array(Array("", "argvalue", "", true, true, "'argvalue'"),
+          Array("", "argvalue", "", true, false, "argvalue"),
+          Array("", "argvalue", "", false, true, "'argvalue'"),
+          Array("", "argvalue", "", false, false, "argvalue"),
+          Array("-arg", "argvalue", "", true, true, "'-arg' 'argvalue'"),
+          Array("-arg", "argvalue", "", true, false, "-arg argvalue"),
+          Array("ARGNAME=", "ARGVALUE", "", false, true, "'ARGNAME=ARGVALUE'"),
+          Array("ARGNAME=", "ARGVALUE", "", false, false, "ARGNAME=ARGVALUE"),
+          Array("-Xmx", "4", "G", true, true, "'-Xmx' '4' 'G'"),
+          Array("-Xmx", "4", "G", true, false, "-Xmx 4 G"),
+          Array("-Xmx", "4", "G", false, true, "'-Xmx4G'"),
+          Array("-Xmx", "4", "G", false, false, "-Xmx4G"),
+          Array("", "", "", true, true, "''"),
+          Array("", "", "", true, false, ""),
+          Array("", "", "", false, true, "''"),
+          Array("", "", "", false, false, ""),
+          Array("", null, "", true, true, ""),
+          Array("", Nil, "", true, true, ""),
+          Array("", None, "", true, true, ""),
+          Array(null, null, null, true, true, ""),
+          Array("", Some("argvalue"), "", true, true, "'argvalue'")
+         )
+  }
+
+  @Test( dataProvider="formatArgumentTestData" )
+  def testFormatArgument( prefix: String, param: Any, suffix: String, spaceSeparated: Boolean, escape: Boolean, expectedReturnValue: String ) {
+    Assert.assertEquals(formatArgument(prefix, param, suffix, spaceSeparated, escape, "%s"),
+                        expectedReturnValue)
+  }
+
+  @Test
+  def testFormatArgumentCustomFormatString() {
+    Assert.assertEquals(formatArgument("", "argvalue", "", true, true, "%.3s"), "'arg'")
+  }
+
+  @DataProvider( name = "requiredTestData" )
+  def requiredDataProvider = {
+    Array(Array("", "argvalue", "", true, true, " 'argvalue' "),
+          Array("", "argvalue", "", true, false, " argvalue "),
+          Array("", "argvalue", "", false, true, " 'argvalue' "),
+          Array("", "argvalue", "", false, false, " argvalue "),
+          Array("-arg", "argvalue", "", true, true, " '-arg' 'argvalue' "),
+          Array("-arg", "argvalue", "", true, false, " -arg argvalue "),
+          Array("ARGNAME=", "ARGVALUE", "", false, true, " 'ARGNAME=ARGVALUE' "),
+          Array("ARGNAME=", "ARGVALUE", "", false, false, " ARGNAME=ARGVALUE "),
+          Array("-Xmx", "4", "G", true, true, " '-Xmx' '4' 'G' "),
+          Array("-Xmx", "4", "G", true, false, " -Xmx 4 G "),
+          Array("-Xmx", "4", "G", false, true, " '-Xmx4G' "),
+          Array("-Xmx", "4", "G", false, false, " -Xmx4G "),
+          Array("", "", "", true, true, " '' "),
+          Array("", "", "", true, false, "  "),
+          Array("", "", "", false, true, " '' "),
+          Array("", "", "", false, false, "  "),
+          Array("", null, "", true, true, "  "),
+          Array("", Nil, "", true, true, "  "),
+          Array("", None, "", true, true, "  ")
+         )
+  }
+
+  @Test( dataProvider="requiredTestData" )
+  def testRequired( prefix: String, param: Any, suffix: String, spaceSeparated: Boolean, escape: Boolean, expectedReturnValue: String ) {
+    Assert.assertEquals(required(prefix, param, suffix, spaceSeparated, escape),
+                        expectedReturnValue)
+  }
+
+  @DataProvider( name = "optionalTestData" )
+  def optionalDataProvider = {
+    Array(Array("-arg", "argvalue", "", true, true, " '-arg' 'argvalue' "),
+          Array("-arg", null, "", true, true, ""),
+          Array("-arg", Nil, "", true, true, ""),
+          Array("-arg", None, "", true, true, ""),
+          Array("-arg", "", "", true, true, " '-arg' ")
+         )
+  }
+
+  @Test( dataProvider="optionalTestData" )
+  def testOptional( prefix: String, param: Any, suffix: String, spaceSeparated: Boolean, escape: Boolean, expectedReturnValue: String ) {
+    Assert.assertEquals(optional(prefix, param, suffix, spaceSeparated, escape),
+                        expectedReturnValue)
+  }
+
+  @DataProvider( name = "conditionalTestData" )
+  def conditionalDataProvider = {
+    Array(Array(true, "-FLAG", true, " '-FLAG' "),
+          Array(true, "-FLAG", false, " -FLAG "),
+          Array(false, "-FLAG", true, ""),
+          Array(false, "-FLAG", false, ""),
+          Array(true, null, true, "  "),
+          Array(true, Nil, true, "  "),
+          Array(true, None, true, "  "),
+          Array(false, null, true, ""),
+          Array(false, Nil, true, ""),
+          Array(false, None, true, "")
+         )
+  }
+
+  @Test( dataProvider="conditionalTestData" )
+  def testConditional( condition: Boolean, param: Any, escape: Boolean, expectedReturnValue: String ) {
+    Assert.assertEquals(conditional(condition, param, escape),
+                        expectedReturnValue)
+  }
+
+  @DataProvider( name = "repeatTestData" )
+  def repeatDataProvider = {
+    Array(Array("", Seq("a", "bc", "d"), "", " ", true, true, " 'a' 'bc' 'd' "),
+          Array("", Seq("a", "bc", "d"), "", " ", true, false, " a bc d "),
+          Array("", Seq("a", "bc", "d"), "", "", true, true, " 'a''bc''d' "),
+          Array("", Seq("a", "bc", "d"), "", "", true, false, " abcd "),
+          Array("-f", Seq("file1", "file2", "file3"), "", " ", true, true, " '-f' 'file1' '-f' 'file2' '-f' 'file3' "),
+          Array("-f", Seq("file1", "file2", "file3"), "", " ", true, false, " -f file1 -f file2 -f file3 "),
+          Array("-f", Seq("file1", "file2", "file3"), "", " ", false, true, " '-ffile1' '-ffile2' '-ffile3' "),
+          Array("-f", Seq("file1", "file2", "file3"), "", " ", false, false, " -ffile1 -ffile2 -ffile3 "),
+          Array("-f", Seq("file1", "file2", "file3"), "", "", false, true, " '-ffile1''-ffile2''-ffile3' "),
+          Array("-f", Seq("file1", "file2", "file3"), "", "", false, false, " -ffile1-ffile2-ffile3 "),
+          Array("-f", Seq("file1", "file2", "file3"), "suffix", " ", true, true, " '-f' 'file1' 'suffix' '-f' 'file2' 'suffix' '-f' 'file3' 'suffix' "),
+          Array("-f", Seq("file1", "file2", "file3"), "suffix", " ", true, false, " -f file1 suffix -f file2 suffix -f file3 suffix "),
+          Array("-f", Seq("file1", "file2", "file3"), "suffix", " ", false, true, " '-ffile1suffix' '-ffile2suffix' '-ffile3suffix' "),
+          Array("-f", Seq("file1", "file2", "file3"), "suffix", " ", false, false, " -ffile1suffix -ffile2suffix -ffile3suffix "),
+          Array("-f", null, "", " ", true, true, ""),
+          Array("-f", Nil, "", " ", true, true, "")
+         )
+  }
+
+  @Test( dataProvider="repeatTestData" )
+  def testRepeat( prefix: String, params: Traversable[_], suffix: String, separator: String,
+                  spaceSeparated: Boolean, escape: Boolean, expectedReturnValue: String ) {
+    Assert.assertEquals(repeat(prefix, params, suffix, separator, spaceSeparated, escape),
+                        expectedReturnValue)
+  }
+
+  // Need to test None separately due to implicit conversion issues when using None in a TestNG data provider
+  @Test
+  def testRepeatNone() {
+    testRepeat("", None, "", " ", true, true, "")
+  }
+
+  @DataProvider( name = "repeatWithPrefixFormattingTestData" )
+  def repeatWithPrefixFormattingDataProvider = {
+    Array(Array("-f", Seq("file1", "file2", "file3"), "", " ", true, true, (prefix: String, value: Any) => "%s:tag%s".format(prefix, value),
+                " '-f:tagfile1' 'file1' '-f:tagfile2' 'file2' '-f:tagfile3' 'file3' "),
+          Array("-f", Seq("file1", "file2", "file3"), "", " ", true, false, (prefix: String, value: Any) => "%s:tag%s".format(prefix, value),
+                " -f:tagfile1 file1 -f:tagfile2 file2 -f:tagfile3 file3 "),
+          Array("", Seq("file1", "file2", "file3"), "", " ", true, true, (prefix: String, value: Any) => "-%s".format(value),
+                " '-file1' 'file1' '-file2' 'file2' '-file3' 'file3' "),
+          Array("-f", null, "", " ", true, true, (prefix: String, value: Any) => "%s:tag%s".format(prefix, value),
+                ""),
+          Array("-f", Nil, "", " ", true, true, (prefix: String, value: Any) => "%s:tag%s".format(prefix, value),
+                "")
+         )
+  }
+
+  @Test( dataProvider = "repeatWithPrefixFormattingTestData" )
+  def testRepeatWithPrefixFormatting( prefix: String, params: Traversable[_], suffix: String, separator: String,
+                                      spaceSeparated: Boolean, escape: Boolean, formatPrefix: (String, Any) => String,
+                                      expectedReturnValue: String ) {
+    Assert.assertEquals(repeat(prefix, params, suffix, separator, spaceSeparated, escape, "%s", formatPrefix),
+                        expectedReturnValue)
+  }
+}
\ No newline at end of file
diff --git a/public/gatk-queue/src/test/scala/org/broadinstitute/gatk/queue/pipeline/QueueTest.scala b/public/gatk-queue/src/test/scala/org/broadinstitute/gatk/queue/pipeline/QueueTest.scala
new file mode 100644
index 0000000..62ac8e1
--- /dev/null
+++ b/public/gatk-queue/src/test/scala/org/broadinstitute/gatk/queue/pipeline/QueueTest.scala
@@ -0,0 +1,265 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.queue.pipeline
+
+import org.broadinstitute.gatk.utils.Utils
+import org.testng.Assert
+import org.broadinstitute.gatk.utils.commandline.CommandLineProgram
+import java.util.Date
+import java.text.SimpleDateFormat
+import org.broadinstitute.gatk.utils.BaseTest
+import org.broadinstitute.gatk.utils.MD5DB
+import org.broadinstitute.gatk.queue.{QScript, QCommandLine}
+import org.broadinstitute.gatk.queue.util.Logging
+import java.io.{FilenameFilter, File}
+import org.broadinstitute.gatk.engine.report.GATKReport
+import org.apache.commons.io.FileUtils
+import org.apache.commons.io.filefilter.WildcardFileFilter
+
+object QueueTest extends BaseTest with Logging {
+
+  private final val qscriptsSrcDir = "src/main/qscripts/"
+  private final val qscriptsPackageDir = qscriptsSrcDir + "org/broadinstitute/gatk/queue/qscripts/"
+  final val publicQScriptsPackageDir = BaseTest.gatkDirectory + "public/gatk-queue-extensions-public/" + qscriptsPackageDir
+  final val protectedQScriptsPackageDir = BaseTest.gatkDirectory + "protected/gatk-queue-extensions-distribution/" + qscriptsPackageDir
+  final val privateQScriptsPackageDir = BaseTest.gatkDirectory + "private/gatk-queue-extensions-internal/" + qscriptsPackageDir
+
+  private val validationReportsDataLocation = "/humgen/gsa-hpprojects/GATK/validationreports/submitted/"
+  private val md5DB = new MD5DB()
+
+  /**
+   * All the job runners configured to run QueueTests at The Broad.
+   */
+  final val allJobRunners = Seq("Lsf706", "GridEngine", "Shell")
+
+  /**
+   * The default job runners to run.
+   */
+  final val defaultJobRunners = Seq("Lsf706", "GridEngine")
+
+  /**
+   * Returns the top level output path to this test.
+   * @param testName The name of the test passed to QueueTest.executeTest()
+   * @param jobRunner The name of the job manager to run the jobs.
+   * @return the top level output path to this test.
+   */
+  def testDir(testName: String, jobRunner: String) = "queuetests/%s/%s/".format(testName, jobRunner)
+
+  /**
+   * Returns the directory where relative output files will be written for this test.
+   * @param testName The name of the test passed to QueueTest.executeTest()
+   * @param jobRunner The name of the job manager to run the jobs.
+   * @return the directory where relative output files will be written for this test.
+   */
+  private def runDir(testName: String, jobRunner: String) = testDir(testName, jobRunner) + "run/"
+
+  /**
+   * Returns the directory where temp files will be written for this test.
+   * @param testName The name of the test passed to QueueTest.executeTest()
+   * @param jobRunner The name of the job manager to run the jobs.
+   * @return the directory where temp files will be written for this test.
+   */
+  private def tempDir(testName: String, jobRunner: String) = testDir(testName, jobRunner) + "temp/"
+
+  /**
+   * Runs the queueTest.
+   * @param queueTest test to run.
+   */
+  def executeTest(queueTest: QueueTestSpec) {
+    var jobRunners = queueTest.jobRunners
+    if (jobRunners == null)
+      jobRunners = defaultJobRunners
+    jobRunners.foreach(executeTest(queueTest, _))
+  }
+
+  /**
+   * Runs the queueTest.
+   * @param queueTest test to run.
+   * @param jobRunner The name of the job manager to run the jobs.
+   */
+  def executeTest(queueTest: QueueTestSpec, jobRunner: String) {
+    // Reset the order of functions added to the graph.
+    QScript.resetAddOrder()
+
+    val name = queueTest.name
+    if (name == null)
+      Assert.fail("QueueTestSpec.name is null")
+    println(Utils.dupString('-', 80))
+    executeTest(name, queueTest.args, queueTest.jobQueue, queueTest.expectedException, jobRunner)
+    if (BaseTest.queueTestRunModeIsSet) {
+      assertMatchingMD5s(name, queueTest.fileMD5s.map{case (file, md5) => new File(runDir(name, jobRunner), file) -> md5}, queueTest.parameterize)
+      if (queueTest.evalSpec != null)
+        validateEval(name, queueTest.evalSpec, jobRunner)
+      for (path <- queueTest.expectedFilePaths)
+        assertPathExists(runDir(name, jobRunner), path)
+      for (path <- queueTest.unexpectedFilePaths)
+        assertPathDoesNotExist(runDir(name, jobRunner), path)
+      println("  => %s PASSED (%s)".format(name, jobRunner))
+    }
+    else
+      println("  => %s PASSED DRY RUN (%s)".format(name, jobRunner))
+  }
+
+  private def assertMatchingMD5s(name: String, fileMD5s: Traversable[(File, String)], parameterize: Boolean) {
+    var failed = 0
+    for ((file, expectedMD5) <- fileMD5s) {
+      val calculatedMD5 = md5DB.testFileMD5(name, "", file, expectedMD5, parameterize).actualMD5
+      if (!parameterize && expectedMD5 != "" && expectedMD5 != calculatedMD5)
+        failed += 1
+    }
+    if (failed > 0)
+      Assert.fail("%d of %d MD5s did not match".format(failed, fileMD5s.size))
+  }
+
+  private def validateEval(name: String, evalSpec: QueueTestEvalSpec, jobRunner: String) {
+    // write the report to the shared validation data location
+    val formatter = new SimpleDateFormat("yyyy.MM.dd.HH.mm.ss")
+    val reportLocation = "%s%s/%s/validation.%s.eval".format(validationReportsDataLocation, jobRunner, name, formatter.format(new Date))
+    val reportFile = new File(reportLocation)
+
+    FileUtils.copyFile(new File(runDir(name, jobRunner) + evalSpec.evalReport), reportFile)
+
+    val report = new GATKReport(reportFile)
+
+    var allInRange = true
+
+    println()
+    println(name + " validation values:")
+    println("    value (min,target,max) table key metric")
+    for (validation <- evalSpec.validations) {
+      val table = report.getTable(validation.table)
+      val key = table.findRowByData(validation.table +: validation.key.split('.') : _*)
+      val value = String.valueOf(table.get(key, validation.metric))
+      val inRange = if (value == null) false else validation.inRange(value)
+      val flag = if (!inRange) "*" else " "
+      println("  %s %s (%s,%s,%s) %s %s %s".format(flag, value, validation.min, validation.target, validation.max, validation.table, validation.key, validation.metric))
+      allInRange &= inRange
+    }
+
+    if (!allInRange)
+      Assert.fail("Eval outside of expected range")
+  }
+
+  /**
+   * execute the test
+   * @param name the name of the test
+   * @param args the argument list
+   * @param jobQueue the queue to run the job on.  Defaults to hour if jobQueue is null.
+   * @param expectedException the expected exception or null if no exception is expected.
+   * @param jobRunner The name of the job manager to run the jobs.
+   */
+  private def executeTest(name: String, args: String, jobQueue: String, expectedException: Class[_], jobRunner: String) {
+    var command = Utils.escapeExpressions(args)
+
+    // add the logging level to each of the integration test commands
+
+    command = Utils.appendArray(command, "-jobRunner", jobRunner,
+      "-tempDir", tempDir(name, jobRunner), "-runDir", runDir(name, jobRunner))
+
+    if (jobQueue != null)
+      command = Utils.appendArray(command, "-jobQueue", jobQueue)
+
+    if (BaseTest.queueTestRunModeIsSet)
+      command = Utils.appendArray(command, "-run")
+
+    // run the executable
+    var gotAnException = false
+
+    val instance = new QCommandLine
+    runningCommandLines += instance
+    try {
+      println("Executing test %s with Queue arguments: %s".format(name, Utils.join(" ",command)))
+      CommandLineProgram.start(instance, command)
+    } catch {
+      case e: Exception =>
+        gotAnException = true
+        if (expectedException != null) {
+          // we expect an exception
+          println("Wanted exception %s, saw %s".format(expectedException, e.getClass))
+          if (expectedException.isInstance(e)) {
+            // it's the type we expected
+            println(String.format("  => %s PASSED (%s)", name, jobRunner))
+          } else {
+            e.printStackTrace()
+            Assert.fail("Test %s expected exception %s but got %s instead (%s)".format(
+              name, expectedException, e.getClass, jobRunner))
+          }
+        } else {
+          // we didn't expect an exception but we got one :-(
+          throw new RuntimeException(e)
+        }
+    } finally {
+      instance.shutdown()
+      runningCommandLines -= instance
+    }
+
+    // catch failures from the integration test
+    if (expectedException != null) {
+      if (!gotAnException)
+      // we expected an exception but didn't see it
+        Assert.fail("Test %s expected exception %s but none was thrown (%s)".format(name, expectedException.toString, jobRunner))
+    } else {
+      if (CommandLineProgram.result != 0)
+        throw new RuntimeException("Error running Queue with arguments: " + args)
+    }
+  }
+
+  private def assertPathExists(runDir: String, path: String) {
+    val orig = new File(runDir, path)
+    var dir = orig.getParentFile
+    if (dir == null)
+      dir = new File(".")
+    Assert.assertTrue(dir.exists, "Missing directory: " + dir.getAbsolutePath)
+    val filter: FilenameFilter = new WildcardFileFilter(orig.getName)
+    Assert.assertNotEquals(dir.listFiles(filter).length, 0, "Missing file: " + orig.getAbsolutePath)
+  }
+
+  private def assertPathDoesNotExist(runDir: String, path: String) {
+    val orig = new File(runDir, path)
+    var dir = orig.getParentFile
+    if (dir == null)
+      dir = new File(".")
+    if (dir.exists) {
+      val filter: FilenameFilter = new WildcardFileFilter(orig.getName)
+      Assert.assertEquals(dir.listFiles(filter).length, 0,
+        "Found unexpected file(s): " + dir.listFiles().map(_.getAbsolutePath).mkString(", "))
+    }
+  }
+
+  private var runningCommandLines = Set.empty[QCommandLine]
+
+  Runtime.getRuntime.addShutdownHook(new Thread {
+    /** Cleanup as the JVM shuts down. */
+    override def run() {
+      runningCommandLines.foreach(commandLine =>
+        try {
+          commandLine.shutdown()
+        } catch {
+          case _: Throwable => /* ignore */
+        })
+    }
+  })
+}
diff --git a/public/gatk-queue/src/test/scala/org/broadinstitute/gatk/queue/pipeline/QueueTestEvalSpec.scala b/public/gatk-queue/src/test/scala/org/broadinstitute/gatk/queue/pipeline/QueueTestEvalSpec.scala
new file mode 100644
index 0000000..764449c
--- /dev/null
+++ b/public/gatk-queue/src/test/scala/org/broadinstitute/gatk/queue/pipeline/QueueTestEvalSpec.scala
@@ -0,0 +1,59 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.queue.pipeline
+
+/**
+ * Data validations to evaluate on a GATKReport.
+ */
+class QueueTestEvalSpec {
+  /** Eval modules to output. */
+  var evalReport: String = _
+
+  /** Validations to assert. */
+  var validations: Seq[PipelineValidation[_]] = Nil
+}
+
+/** A VariantEval JEXL and range of values to validate. */
+abstract class PipelineValidation[T <: AnyVal](val table: String, val key: String, val metric: String, val target: T, val min: T, val max: T) {
+  def parse(x: String): T
+  def inRange(x: String): Boolean
+}
+
+/** A VariantEval JEXL and target to validate within a 1% tolerance. */
+class IntegerValidation(table: String, key: String, metric: String, target: Int)
+        extends PipelineValidation[Int](table, key, metric, target,
+          (target * .99).floor.toInt, (target * 1.01).ceil.toInt) {
+  def parse(x: String) = x.toInt
+  def inRange(x: String) = parse(x) >= min && parse(x) <= max
+}
+
+/** A VariantEval JEXL and target to validate within a 1% tolerance. */
+class DoubleValidation(table: String, key: String, metric: String, target: Double)
+        extends PipelineValidation(table, key, metric, target,
+          (target * 99).floor / 100, (target * 101).ceil / 100) {
+  def parse(x: String) = x.toDouble
+  def inRange(x: String) = parse(x) >= min && parse(x) <= max
+}
diff --git a/public/gatk-queue/src/test/scala/org/broadinstitute/gatk/queue/pipeline/QueueTestSpec.scala b/public/gatk-queue/src/test/scala/org/broadinstitute/gatk/queue/pipeline/QueueTestSpec.scala
new file mode 100644
index 0000000..4fdcb08
--- /dev/null
+++ b/public/gatk-queue/src/test/scala/org/broadinstitute/gatk/queue/pipeline/QueueTestSpec.scala
@@ -0,0 +1,68 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.queue.pipeline
+
+class QueueTestSpec(var name: String = null) {
+
+  /** The arguments to pass to the Queue test, ex: "-S scala/qscript/examples/HelloWorld.scala" */
+  var args: String = _
+
+  /** Job Queue to run the test.  Default is null which means use hour. */
+  var jobQueue: String = _
+
+  /** Job runners to run the test.  Default is null which means use the default. */
+  var jobRunners: Seq[String] = _
+
+  /** Expected MD5 results for each file path. */
+  var fileMD5s = Map.empty[String, String]
+
+  /** VariantEval validations to run on a VCF after the pipeline has completed. */
+  var evalSpec: QueueTestEvalSpec = _
+
+  /** Expected exception from the test. */
+  var expectedException: Class[_ <: Exception] = null
+
+  /** Expected files. The file name may contain wildcards acceptable by the WildcardFileFilter. */
+  var expectedFilePaths: Seq[String] = Seq.empty
+
+  /** Unexpected files. The file name may contain wildcards acceptable by the WildcardFileFilter. */
+  var unexpectedFilePaths: Seq[String] = Seq.empty
+
+  /** If true will check the MD5s without failing. */
+  var parameterize = false
+
+  def this(args: String, fileMD5s: Traversable[(String, String)]) = {
+    this()
+    this.args = args
+    this.fileMD5s = fileMD5s.toMap
+  }
+
+  def this(args: String, expectedException: Class[_ <: Exception]) = {
+    this()
+    this.args = args
+    this.expectedException = expectedException
+  }
+}
diff --git a/public/gatk-queue/src/test/scala/org/broadinstitute/gatk/queue/util/ShellUtilsUnitTest.scala b/public/gatk-queue/src/test/scala/org/broadinstitute/gatk/queue/util/ShellUtilsUnitTest.scala
new file mode 100644
index 0000000..944cc85
--- /dev/null
+++ b/public/gatk-queue/src/test/scala/org/broadinstitute/gatk/queue/util/ShellUtilsUnitTest.scala
@@ -0,0 +1,82 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.queue.util
+
+import org.testng.annotations.Test
+import org.testng.Assert
+import java.io.{InputStreamReader, BufferedReader}
+
+class ShellUtilsUnitTest {
+
+  @Test
+  def testEscapeShellArgumentOneCharSequences() {
+    // Test all ASCII characters except \0, \n, and \r, which we do not support escaping
+    for ( asciiCode <- 1 to 127 if asciiCode != 10 && asciiCode != 13  ) {
+      val originalString: String = "%c".format(asciiCode.toChar)
+      val quotedString: String = ShellUtils.escapeShellArgument(originalString)
+
+      val child : Process = new ProcessBuilder("/bin/sh", "-c", "printf \"%s\" " + quotedString).start()
+      val childReader : BufferedReader = new BufferedReader(new InputStreamReader(child.getInputStream))
+      val childOutputBuffer : StringBuilder = new StringBuilder
+
+      val childReaderThread : Thread = new Thread(new Runnable() {
+        def run() {
+          var line : String = childReader.readLine()
+
+          while ( line != null ) {
+            childOutputBuffer.append(line)
+            line = childReader.readLine()
+          }
+        }
+      })
+      childReaderThread.start()
+
+      val childReturnValue = child.waitFor()
+      childReaderThread.join()
+
+      childReader.close()
+      val childOutput = childOutputBuffer.toString()
+
+      if ( childReturnValue != 0 ) {
+        Assert.fail("With character ASCII %d, sh child process returned: %d".format(asciiCode, childReturnValue))
+      }
+      else if ( ! originalString.equals(childOutput) ) {
+        Assert.fail("With character ASCII %d, sh child process output \"%s\" instead of the expected \"%s\"".format(
+                    asciiCode, childOutput, originalString))
+      }
+    }
+  }
+
+  @Test(expectedExceptions = Array(classOf[IllegalArgumentException]))
+  def testEscapeShellArgumentNullString() {
+    ShellUtils.escapeShellArgument(null)
+  }
+
+  @Test
+  def testEscapeShellArgumentEmptyString() {
+    Assert.assertEquals(ShellUtils.escapeShellArgument(""), "''")
+  }
+}
\ No newline at end of file
diff --git a/public/gatk-queue/src/test/scala/org/broadinstitute/gatk/queue/util/StringFileConversionsUnitTest.scala b/public/gatk-queue/src/test/scala/org/broadinstitute/gatk/queue/util/StringFileConversionsUnitTest.scala
new file mode 100644
index 0000000..160e040
--- /dev/null
+++ b/public/gatk-queue/src/test/scala/org/broadinstitute/gatk/queue/util/StringFileConversionsUnitTest.scala
@@ -0,0 +1,128 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.queue.util
+
+import org.testng.annotations.Test
+import java.io.File
+import org.testng.Assert
+import StringFileConversions._
+
+class StringFileConversionsUnitTest {
+  @Test
+  def testStringToFile() {
+    var string: String = new File("foo")
+    Assert.assertEquals(string, "foo")
+
+    string = null.asInstanceOf[File]
+    Assert.assertNull(string)
+  }
+
+  @Test
+  def testFileToString() {
+    var file: File = "foo"
+    Assert.assertEquals(file, new File("foo"))
+
+    file = null.asInstanceOf[String]
+    Assert.assertNull(file)
+  }
+
+  @Test
+  def testStringToFileList() {
+    var files = Seq(new File("foo"))
+    files :+= "bar"
+    Assert.assertEquals(files, Seq(new File("foo"), new File("bar")))
+
+    files = Seq(new File("foo"))
+    files :+= null.asInstanceOf[String]
+    Assert.assertEquals(files, Seq(new File("foo"), null))
+
+    files = Seq[File](null)
+    files :+= "foo"
+    Assert.assertEquals(files, Seq(null, new File("foo")))
+
+    files = Seq[File](null)
+    files :+= null.asInstanceOf[String]
+    Assert.assertEquals(files, Seq(null, null))
+  }
+
+  @Test
+  def testFileToStringList() {
+    var strings = Seq("foo")
+    strings :+= new File("bar")
+    Assert.assertEquals(strings, Seq("foo", "bar"))
+
+    strings = Seq("foo")
+    strings :+= null.asInstanceOf[File]
+    Assert.assertEquals(strings, Seq("foo", null))
+
+    strings = Seq[String](null)
+    strings :+= new File("foo")
+    Assert.assertEquals(strings, Seq(null, "foo"))
+
+    strings = Seq[String](null)
+    strings :+= null.asInstanceOf[File]
+    Assert.assertEquals(strings, Seq(null, null))
+  }
+
+  @Test
+  def testStringListToFileList() {
+    var files = Seq(new File("foo"))
+    files ++= Seq("bar")
+    Assert.assertEquals(files, Seq(new File("foo"), new File("bar")))
+
+    files = Seq(new File("foo"))
+    files ++= Seq[String](null)
+    Assert.assertEquals(files, Seq(new File("foo"), null))
+
+    files = Seq[File](null)
+    files ++= Seq("foo")
+    Assert.assertEquals(files, Seq(null, new File("foo")))
+
+    files = Seq[File](null)
+    files ++= Seq[String](null)
+    Assert.assertEquals(files, Seq(null, null))
+  }
+
+  @Test
+  def testFileListToStringList() {
+    var strings = Seq("foo")
+    strings ++= Seq(new File("bar"))
+    Assert.assertEquals(strings, Seq("foo", "bar"))
+
+    strings = Seq("foo")
+    strings ++= Seq[File](null)
+    Assert.assertEquals(strings, Seq("foo", null))
+
+    strings = Seq[String](null)
+    strings ++= Seq(new File("foo"))
+    Assert.assertEquals(strings, Seq(null, "foo"))
+
+    strings = Seq[String](null)
+    strings ++= Seq[File](null)
+    Assert.assertEquals(strings, Seq(null, null))
+  }
+
+}
diff --git a/public/gatk-queue/src/test/scala/org/broadinstitute/gatk/queue/util/SystemUtilsUnitTest.scala b/public/gatk-queue/src/test/scala/org/broadinstitute/gatk/queue/util/SystemUtilsUnitTest.scala
new file mode 100644
index 0000000..2fd78e3
--- /dev/null
+++ b/public/gatk-queue/src/test/scala/org/broadinstitute/gatk/queue/util/SystemUtilsUnitTest.scala
@@ -0,0 +1,44 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.queue.util
+
+import org.testng.annotations.Test
+import org.testng.Assert
+
+class SystemUtilsUnitTest {
+  @Test
+  def testHostInfo {
+    val inetAddress = SystemUtils.inetAddress
+    val hostName = SystemUtils.hostName
+    val mailName = SystemUtils.mailName
+
+    if (inetAddress.split('.').takeRight(2).mkString(".") == mailName)
+      Assert.fail("""Invalid domain name generated:
+      |inetAddress: %s
+      |hostName:    %s
+      |mailName:  %s""".stripMargin.format(inetAddress, hostName, mailName))
+  }
+}
diff --git a/public/gatk-root/pom.xml b/public/gatk-root/pom.xml
new file mode 100644
index 0000000..c9f2517
--- /dev/null
+++ b/public/gatk-root/pom.xml
@@ -0,0 +1,717 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+    <modelVersion>4.0.0</modelVersion>
+
+    <!--
+    This pom is parent for all gatk poms
+    See also:
+      http://maven.apache.org/pom.html#Inheritance_v
+      http://maven.apache.org/guides/introduction/introduction-to-the-pom.html#Project_Inheritance_vs_Project_Aggregation
+      http://stackoverflow.com/questions/1992213/maven-parent-pom-vs-modules-pom
+    -->
+
+    <groupId>org.broadinstitute.gatk</groupId>
+    <artifactId>gatk-root</artifactId>
+    <version>3.3</version>
+    <packaging>pom</packaging>
+    <name>GATK Root</name>
+
+    <prerequisites>
+        <maven>3.0.4</maven>
+    </prerequisites>
+
+    <properties>
+        <sourceEncoding>UTF-8</sourceEncoding>
+        <project.build.sourceEncoding>${sourceEncoding}</project.build.sourceEncoding>
+        <project.reporting.outputEncoding>${sourceEncoding}</project.reporting.outputEncoding>
+        <maven.compiler.source>1.7</maven.compiler.source>
+        <maven.compiler.target>1.7</maven.compiler.target>
+        <maven.build.timestamp.format>yyyy/MM/dd HH:mm:ss</maven.build.timestamp.format>
+        <gatk.basedir>${project.basedir}/../..</gatk.basedir>
+        <gatk.committests.skipped>true</gatk.committests.skipped>
+        <gatk.unittests.skipped>${gatk.committests.skipped}</gatk.unittests.skipped>
+        <gatk.integrationtests.skipped>${gatk.committests.skipped}</gatk.integrationtests.skipped>
+        <gatk.queuetests.skipped>${gatk.committests.skipped}</gatk.queuetests.skipped>
+        <gatk.largescaletests.skipped>true</gatk.largescaletests.skipped>
+        <gatk.knowledgebasetests.skipped>true</gatk.knowledgebasetests.skipped>
+        <gatk.queuetests.run>false</gatk.queuetests.run>
+        <scala.maxmemory>1g</scala.maxmemory>
+        <test.maxmemory>4g</test.maxmemory>
+        <java.gc.threads>4</java.gc.threads>
+        <java.gc.timeLimit>50</java.gc.timeLimit>
+        <java.gc.heapFreeLimit>10</java.gc.heapFreeLimit>
+        <test.args>-Xmx${test.maxmemory} -XX:+UseParallelOldGC -XX:ParallelGCThreads=${java.gc.threads} -XX:GCTimeLimit=${java.gc.timeLimit} -XX:GCHeapFreeLimit=${java.gc.heapFreeLimit}</test.args>
+        <test.listeners>org.testng.reporters.FailedReporter,org.testng.reporters.JUnitXMLReporter,org.broadinstitute.gatk.utils.TestNGTestTransformer,org.broadinstitute.gatk.utils.GATKTextReporter,org.uncommons.reportng.HTMLReporter</test.listeners>
+
+        <!-- Version numbers for picard and htsjdk -->
+        <htsjdk.version>1.120.1620</htsjdk.version>
+        <picard.version>1.120.1579</picard.version>
+    </properties>
+
+    <!-- Dependency configuration (versions, etc.) -->
+    <dependencyManagement>
+        <dependencies>
+            <dependency>
+                <groupId>org.scala-lang</groupId>
+                <artifactId>scala-compiler</artifactId>
+                <version>2.10.2</version>
+            </dependency>
+            <dependency>
+                <groupId>org.scala-lang</groupId>
+                <artifactId>scala-library</artifactId>
+                <version>2.10.2</version>
+            </dependency>
+            <dependency>
+                <groupId>com.google.code.cofoja</groupId>
+                <artifactId>cofoja</artifactId>
+                <version>1.0-r139</version>
+            </dependency>
+            <dependency>
+                <groupId>samtools</groupId>
+                <artifactId>htsjdk</artifactId>
+                <version>${htsjdk.version}</version>
+                <exclusions>
+                    <!-- The jdk15 classfier seems to throw off the normal dependency resolution,
+                    leading to both 6.8 and 5.0-jdk15 on the classpath, then leading to an old
+                    version testng loading, as seen by the super old TestNG4751Configurator.
+                    -->
+                    <exclusion>
+                        <groupId>org.testng</groupId>
+                        <artifactId>testng</artifactId>
+                    </exclusion>
+                </exclusions>
+            </dependency>
+            <dependency>
+                <groupId>picard</groupId>
+                <artifactId>picard</artifactId>
+                <version>${picard.version}</version>
+            </dependency>
+            <dependency>
+                <groupId>log4j</groupId>
+                <artifactId>log4j</artifactId>
+                <version>1.2.15</version>
+                <exclusions>
+                    <exclusion>
+                        <groupId>com.sun.jdmk</groupId>
+                        <artifactId>jmxtools</artifactId>
+                    </exclusion>
+                    <exclusion>
+                        <groupId>javax.jms</groupId>
+                        <artifactId>jms</artifactId>
+                    </exclusion>
+                    <exclusion>
+                        <groupId>com.sun.jmx</groupId>
+                        <artifactId>jmxri</artifactId>
+                    </exclusion>
+                </exclusions>
+            </dependency>
+            <dependency>
+                <groupId>javax.mail</groupId>
+                <artifactId>mail</artifactId>
+                <version>1.4.4</version>
+            </dependency>
+            <dependency>
+                <groupId>colt</groupId>
+                <artifactId>colt</artifactId>
+                <version>1.2.0</version>
+            </dependency>
+            <dependency>
+                <groupId>it.unimi.dsi</groupId>
+                <artifactId>fastutil</artifactId>
+                <version>6.5.3</version>
+            </dependency>
+            <dependency>
+                <groupId>org.simpleframework</groupId>
+                <artifactId>simple-xml</artifactId>
+                <version>2.0.4</version>
+            </dependency>
+            <dependency>
+                <groupId>org.reflections</groupId>
+                <artifactId>reflections</artifactId>
+                <version>0.9.9-RC1</version>
+            </dependency>
+            <dependency>
+                <groupId>org.slf4j</groupId>
+                <artifactId>slf4j-log4j12</artifactId>
+                <version>1.6.1</version>
+            </dependency>
+            <dependency>
+                <groupId>gov.nist.math</groupId>
+                <artifactId>jama</artifactId>
+                <version>1.0.2</version>
+            </dependency>
+            <dependency>
+                <groupId>net.sf.jgrapht</groupId>
+                <artifactId>jgrapht</artifactId>
+                <version>0.8.3</version>
+            </dependency>
+            <dependency>
+                <groupId>org.freemarker</groupId>
+                <artifactId>freemarker</artifactId>
+                <version>2.3.18</version>
+            </dependency>
+            <dependency>
+                <groupId>org.apache.commons</groupId>
+                <artifactId>commons-email</artifactId>
+                <version>1.2</version>
+            </dependency>
+            <dependency>
+                <groupId>org.apache.commons</groupId>
+                <artifactId>commons-jexl</artifactId>
+                <version>2.1.1</version>
+            </dependency>
+            <dependency>
+                <groupId>commons-lang</groupId>
+                <artifactId>commons-lang</artifactId>
+                <version>2.5</version>
+            </dependency>
+            <dependency>
+                <groupId>commons-logging</groupId>
+                <artifactId>commons-logging</artifactId>
+                <version>1.1.1</version>
+            </dependency>
+            <dependency>
+                <groupId>commons-io</groupId>
+                <artifactId>commons-io</artifactId>
+                <version>2.1</version>
+            </dependency>
+            <dependency>
+                <groupId>commons-collections</groupId>
+                <artifactId>commons-collections</artifactId>
+                <version>3.2.1</version>
+            </dependency>
+            <dependency>
+                <groupId>commons-httpclient</groupId>
+                <artifactId>commons-httpclient</artifactId>
+                <version>3.1</version>
+            </dependency>
+            <dependency>
+                <groupId>org.apache.commons</groupId>
+                <artifactId>commons-math</artifactId>
+                <version>2.2</version>
+            </dependency>
+            <dependency>
+                <groupId>net.java.dev.jna</groupId>
+                <artifactId>jna</artifactId>
+                <version>3.2.7</version>
+            </dependency>
+            <dependency>
+                <groupId>net.java.dev.jets3t</groupId>
+                <artifactId>jets3t</artifactId>
+                <version>0.8.1</version>
+            </dependency>
+            <dependency>
+                <groupId>us.levk</groupId>
+                <artifactId>drmaa-gridengine</artifactId>
+                <version>6.2u5</version>
+            </dependency>
+            <dependency>
+                <groupId>net.sf.snpeff</groupId>
+                <artifactId>snpeff</artifactId>
+                <version>2.0.5</version>
+            </dependency>
+            <dependency>
+                <groupId>org.mongodb</groupId>
+                <artifactId>mongo-java-driver</artifactId>
+                <version>2.7.3</version>
+            </dependency>
+            <dependency>
+                <groupId>com.google.code.gson</groupId>
+                <artifactId>gson</artifactId>
+                <version>2.2.2</version>
+            </dependency>
+            <dependency>
+                <groupId>org.apache.httpcomponents</groupId>
+                <artifactId>httpclient</artifactId>
+                <version>4.1.1</version>
+            </dependency>
+
+            <!--
+            For com.sun.javadoc
+            See also: http://sunnytalkstech.blogspot.in/2011/08/maven-dependency-for-toolsjar-in-jdk7.html
+            -->
+            <dependency>
+                <groupId>com.sun</groupId>
+                <artifactId>tools</artifactId>
+                <version>1.4.2</version>
+                <scope>system</scope>
+                <systemPath>${java.home}/../lib/tools.jar</systemPath>
+            </dependency>
+
+            <dependency>
+                <groupId>org.testng</groupId>
+                <artifactId>testng</artifactId>
+                <version>6.8</version>
+                <scope>test</scope>
+            </dependency>
+            <dependency>
+                <groupId>org.uncommons</groupId>
+                <artifactId>reportng</artifactId>
+                <version>1.1.2</version>
+                <scope>test</scope>
+                <exclusions>
+                    <exclusion>
+                        <groupId>org.testng</groupId>
+                        <artifactId>testng</artifactId>
+                    </exclusion>
+                </exclusions>
+            </dependency>
+            <dependency>
+                <groupId>com.google.inject</groupId>
+                <artifactId>guice</artifactId>
+                <version>3.0</version>
+                <scope>test</scope>
+            </dependency>
+            <dependency>
+                <groupId>com.google.caliper</groupId>
+                <artifactId>caliper</artifactId>
+                <version>0.5-rc1</version>
+                <scope>test</scope>
+                <exclusions>
+                    <!--
+                    TODO: After upgrade to caliper 1.0-beta-1 or later, this may need a revisit.
+                    Possibly other modules may need to exclude *their* old guava versions.
+                     -->
+                    <exclusion>
+                        <groupId>com.google.guava</groupId>
+                        <artifactId>guava</artifactId>
+                    </exclusion>
+                </exclusions>
+            </dependency>
+        </dependencies>
+    </dependencyManagement>
+
+    <dependencies>
+        <dependency>
+            <groupId>org.testng</groupId>
+            <artifactId>testng</artifactId>
+            <scope>test</scope>
+        </dependency>
+        <!-- Dependencies for custom testng reports -->
+        <dependency>
+            <groupId>org.uncommons</groupId>
+            <artifactId>reportng</artifactId>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>com.google.inject</groupId>
+            <artifactId>guice</artifactId>
+            <scope>test</scope>
+        </dependency>
+    </dependencies>
+
+    <build>
+        <!-- Plugin configuration -->
+        <pluginManagement>
+            <plugins>
+                <plugin>
+                    <groupId>org.codehaus.mojo</groupId>
+                    <artifactId>exec-maven-plugin</artifactId>
+                    <version>1.2.1</version>
+                </plugin>
+                <plugin>
+                    <groupId>com.lukegb.mojo</groupId>
+                    <artifactId>gitdescribe-maven-plugin</artifactId>
+                    <version>2.0</version>
+                </plugin>
+                <plugin>
+                    <groupId>org.codehaus.mojo</groupId>
+                    <artifactId>build-helper-maven-plugin</artifactId>
+                    <version>1.8</version>
+                </plugin>
+                <plugin>
+                    <groupId>org.apache.maven.plugins</groupId>
+                    <artifactId>maven-clean-plugin</artifactId>
+                    <version>2.5</version>
+                </plugin>
+                <plugin>
+                    <groupId>org.apache.maven.plugins</groupId>
+                    <artifactId>maven-dependency-plugin</artifactId>
+                    <version>2.8</version>
+                </plugin>
+                <plugin>
+                    <groupId>org.apache.maven.plugins</groupId>
+                    <artifactId>maven-resources-plugin</artifactId>
+                    <version>2.6</version>
+                </plugin>
+                <plugin>
+                    <groupId>org.apache.maven.plugins</groupId>
+                    <artifactId>maven-javadoc-plugin</artifactId>
+                    <version>2.9.1</version>
+                </plugin>
+                <plugin>
+                    <groupId>org.apache.maven.plugins</groupId>
+                    <artifactId>maven-compiler-plugin</artifactId>
+                    <version>3.1</version>
+                </plugin>
+                <plugin>
+                    <groupId>org.scala-tools</groupId>
+                    <artifactId>maven-scala-plugin</artifactId>
+                    <version>2.15.2</version>
+                    <configuration>
+                        <jvmArgs>
+                            <jvmArg>-Xmx${scala.maxmemory}</jvmArg>
+                        </jvmArgs>
+                    </configuration>
+                </plugin>
+                <plugin>
+                    <groupId>org.apache.maven.plugins</groupId>
+                    <artifactId>maven-jar-plugin</artifactId>
+                    <version>2.4</version>
+                </plugin>
+                <plugin>
+                    <groupId>org.apache.maven.plugins</groupId>
+                    <artifactId>maven-shade-plugin</artifactId>
+                    <version>2.1</version>
+                </plugin>
+                <plugin>
+                    <groupId>org.apache.maven.plugins</groupId>
+                    <artifactId>maven-assembly-plugin</artifactId>
+                    <version>2.4</version>
+                </plugin>
+                <plugin>
+                    <groupId>org.apache.maven.plugins</groupId>
+                    <artifactId>maven-enforcer-plugin</artifactId>
+                    <version>1.3.1</version>
+                </plugin>
+                <!--
+                surefire/failsafe configurations are global, even across poms
+                not directly aggregated, for example package-tests/pom.xml
+                -->
+
+                <plugin>
+                    <groupId>org.apache.maven.plugins</groupId>
+                    <artifactId>maven-surefire-plugin</artifactId>
+                    <version>2.16</version>
+                    <configuration>
+                        <!-- See explicit executions below -->
+                        <skip>true</skip>
+                        <failIfNoTests>false</failIfNoTests>
+                        <useFile>false</useFile>
+                        <reportFormat>plain</reportFormat>
+                        <argLine>${test.args}</argLine>
+                        <properties>
+                            <property>
+                                <name>usedefaultlisteners</name>
+                                <value>false</value>
+                            </property>
+                            <property>
+                                <name>listener</name>
+                                <value>${test.listeners}</value>
+                            </property>
+                        </properties>
+                        <systemPropertyVariables>
+                            <gatkdir>${gatk.basedir}</gatkdir>
+                            <clover.pertest.coverage>diff</clover.pertest.coverage>
+                            <java.awt.headless>true</java.awt.headless>
+                            <java.io.tmpdir>${java.io.tmpdir}</java.io.tmpdir>
+                        </systemPropertyVariables>
+                    </configuration>
+                    <executions>
+                        <execution>
+                            <id>default-test</id>
+                            <phase>none</phase>
+                        </execution>
+                        <execution>
+                            <!-- run all non integration tests -->
+                            <id>unit-tests</id>
+                            <goals>
+                                <goal>test</goal>
+                            </goals>
+                            <configuration>
+                                <!-- TODO: Re-enable unit tests by default? -->
+                                <skip>${gatk.unittests.skipped}</skip>
+                                <reportsDirectory>${project.build.directory}/surefire-reports/unit/${test}</reportsDirectory>
+                                <includes>
+                                    <include>**/*UnitTest.class</include>
+                                </includes>
+                                <systemPropertyVariables>
+                                    <testType>unit</testType>
+                                </systemPropertyVariables>
+                            </configuration>
+                        </execution>
+                    </executions>
+                </plugin>
+
+                <plugin>
+                    <groupId>org.apache.maven.plugins</groupId>
+                    <artifactId>maven-failsafe-plugin</artifactId>
+                    <version>2.16</version>
+                    <configuration>
+                        <!-- See explicit executions below -->
+                        <skip>true</skip>
+                        <failIfNoTests>false</failIfNoTests>
+                        <useFile>false</useFile>
+                        <reportFormat>plain</reportFormat>
+                        <argLine>${test.args}</argLine>
+                        <properties>
+                            <property>
+                                <name>usedefaultlisteners</name>
+                                <value>false</value>
+                            </property>
+                            <property>
+                                <name>listener</name>
+                                <value>${test.listeners}</value>
+                            </property>
+                        </properties>
+                        <systemPropertyVariables>
+                            <gatkdir>${gatk.basedir}</gatkdir>
+                            <clover.pertest.coverage>diff</clover.pertest.coverage>
+                            <java.awt.headless>true</java.awt.headless>
+                            <!-- TODO: Fix BaseTest to not error out if this property is missing. -->
+                            <pipeline.run>${gatk.queuetests.run}</pipeline.run>
+                            <java.io.tmpdir>${java.io.tmpdir}</java.io.tmpdir>
+                        </systemPropertyVariables>
+                    </configuration>
+                    <executions>
+                        <execution>
+                            <id>integration-tests</id>
+                            <goals>
+                                <goal>integration-test</goal>
+                                <goal>verify</goal>
+                            </goals>
+                            <!-- run integration tests -->
+                            <configuration>
+                                <!-- TODO: Re-enable integration tests by default? -->
+                                <skip>${gatk.integrationtests.skipped}</skip>
+                                <reportsDirectory>${project.build.directory}/failsafe-reports/integration/${it.test}</reportsDirectory>
+                                <summaryFile>${project.build.directory}/failsafe-reports/integration/failsafe-summary-${it.test}.xml</summaryFile>
+                                <includes>
+                                    <include>**/*IntegrationTest.class</include>
+                                </includes>
+                                <systemPropertyVariables>
+                                    <testType>integration</testType>
+                                </systemPropertyVariables>
+                            </configuration>
+                        </execution>
+                        <execution>
+                            <id>queue-tests</id>
+                            <goals>
+                                <goal>integration-test</goal>
+                                <goal>verify</goal>
+                            </goals>
+                            <!-- run queue dry run tests -->
+                            <configuration>
+                                <!-- TODO: Re-enable queue tests by default? -->
+                                <skip>${gatk.queuetests.skipped}</skip>
+                                <reportsDirectory>${project.build.directory}/failsafe-reports/queue/${it.test}</reportsDirectory>
+                                <summaryFile>${project.build.directory}/failsafe-reports/queue/failsafe-summary-${it.test}.xml</summaryFile>
+                                <includes>
+                                    <include>**/*QueueTest.class</include>
+                                </includes>
+                                <systemPropertyVariables>
+                                    <testType>queue</testType>
+                                </systemPropertyVariables>
+                            </configuration>
+                        </execution>
+                        <execution>
+                            <id>large-scale-tests</id>
+                            <goals>
+                                <goal>integration-test</goal>
+                                <goal>verify</goal>
+                            </goals>
+                            <!-- run large scale tests -->
+                            <configuration>
+                                <skip>${gatk.largescaletests.skipped}</skip>
+                                <reportsDirectory>${project.build.directory}/failsafe-reports/largescale/${it.test}</reportsDirectory>
+                                <summaryFile>${project.build.directory}/failsafe-reports/largescale/failsafe-summary-${it.test}.xml</summaryFile>
+                                <includes>
+                                    <include>**/*LargeScaleTest.class</include>
+                                </includes>
+                                <systemPropertyVariables>
+                                    <testType>largescale</testType>
+                                </systemPropertyVariables>
+                            </configuration>
+                        </execution>
+                        <execution>
+                            <id>knowledge-base-tests</id>
+                            <goals>
+                                <goal>integration-test</goal>
+                                <goal>verify</goal>
+                            </goals>
+                            <!-- run knowledge base tests -->
+                            <configuration>
+                                <skip>${gatk.knowledgebasetests.skipped}</skip>
+                                <reportsDirectory>${project.build.directory}/failsafe-reports/knowledgebasetests/${it.test}</reportsDirectory>
+                                <summaryFile>${project.build.directory}/failsafe-reports/knowledgebasetests/failsafe-summary-${it.test}.xml</summaryFile>
+                                <includes>
+                                    <include>**/*KnowledgeBaseTest.class</include>
+                                </includes>
+                                <systemPropertyVariables>
+                                    <testType>knowledgebasetests</testType>
+                                </systemPropertyVariables>
+                            </configuration>
+                        </execution>
+                    </executions>
+                </plugin>
+
+                <plugin>
+                    <groupId>com.google.code.sortpom</groupId>
+                    <artifactId>maven-sortpom-plugin</artifactId>
+                    <version>2.2</version>
+                    <configuration>
+                        <createBackupFile>false</createBackupFile>
+                        <predefinedSortOrder>custom_1</predefinedSortOrder>
+                        <lineSeparator>\n</lineSeparator>
+                        <encoding>${sourceEncoding}</encoding>
+                        <keepBlankLines>true</keepBlankLines>
+                        <sortDependencies>scope</sortDependencies>
+                        <nrOfIndentSpace>4</nrOfIndentSpace>
+                        <expandEmptyElements>false</expandEmptyElements>
+                    </configuration>
+                    <executions>
+                        <execution>
+                            <goals>
+                                <goal>sort</goal>
+                            </goals>
+                            <phase>verify</phase>
+                        </execution>
+                    </executions>
+                </plugin>
+
+                <!-- TODO: Remove temporary symbolic link creation, after fixing test paths to use local resources. -->
+                <plugin>
+                    <groupId>com.pyx4j</groupId>
+                    <artifactId>maven-junction-plugin</artifactId>
+                    <version>1.0.3</version>
+                </plugin>
+                <plugin>
+                    <groupId>org.apache.maven.plugins</groupId>
+                    <artifactId>maven-invoker-plugin</artifactId>
+                    <version>1.8</version>
+                </plugin>
+                <plugin>
+                    <groupId>org.apache.maven.plugins</groupId>
+                    <artifactId>maven-install-plugin</artifactId>
+                    <version>2.5</version>
+                </plugin>
+                <plugin>
+                    <groupId>org.apache.maven.plugins</groupId>
+                    <artifactId>maven-site-plugin</artifactId>
+                    <version>3.3</version>
+                </plugin>
+            </plugins>
+        </pluginManagement>
+
+        <!-- Invoke plugins that always run -->
+        <plugins>
+            <plugin>
+                <groupId>com.lukegb.mojo</groupId>
+                <artifactId>gitdescribe-maven-plugin</artifactId>
+                <configuration>
+                    <extraArguments>
+                        <param>--long</param>
+                    </extraArguments>
+                    <setReactorProjectsProperties>true</setReactorProjectsProperties>
+                    <descriptionProperty>git.version</descriptionProperty>
+                    <failOutput>exported</failOutput>
+                </configuration>
+                <executions>
+                    <execution>
+                        <id>gitdescribe-initialize</id>
+                        <goals>
+                            <goal>gitdescribe</goal>
+                        </goals>
+                        <phase>initialize</phase>
+                    </execution>
+                    <execution>
+                        <id>gitdescribe-presite</id>
+                        <goals>
+                            <goal>gitdescribe</goal>
+                        </goals>
+                        <phase>pre-site</phase>
+                    </execution>
+                </executions>
+            </plugin>
+            <plugin>
+                <groupId>org.codehaus.mojo</groupId>
+                <artifactId>build-helper-maven-plugin</artifactId>
+                <!-- TODO: gitdescribe plugin doesn't allow null prefixes -->
+                <executions>
+                    <execution>
+                        <id>fix-version-initialize</id>
+                        <goals>
+                            <goal>regex-property</goal>
+                        </goals>
+                        <phase>initialize</phase>
+                        <configuration>
+                            <name>build.version</name>
+                            <value>${git.version}</value>
+                            <regex>git-</regex>
+                        </configuration>
+                    </execution>
+                    <execution>
+                        <id>fix-version-pre-site</id>
+                        <goals>
+                            <goal>regex-property</goal>
+                        </goals>
+                        <phase>pre-site</phase>
+                        <configuration>
+                            <name>build.version</name>
+                            <value>${git.version}</value>
+                            <regex>git-</regex>
+                        </configuration>
+                    </execution>
+                </executions>
+            </plugin>
+            <plugin>
+                <groupId>com.google.code.sortpom</groupId>
+                <artifactId>maven-sortpom-plugin</artifactId>
+                <executions>
+                    <execution>
+                        <id>default</id>
+                        <goals>
+                            <goal>sort</goal>
+                        </goals>
+                        <phase>verify</phase>
+                    </execution>
+                </executions>
+            </plugin>
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-install-plugin</artifactId>
+                <executions>
+                    <!--
+                    The pom for com.pyx4j:maven-junction-plugin:1.0.3 points to
+                    sysinternals:junction:1.04:exe. This file is only hosted in the repo
+                    http://www.pyx4me.com/maven2, and the website keeps going down.
+
+                    This file is only used on windows, but the maven-plugin devs never finished
+                    implementing *plugin* dependency exclusions: http://jira.codehaus.org/browse/MNG-2163
+
+                    Until someone updates or replaces this 2007 plugin with a new plugin using Java 7's Files class,
+                    for now we copy over the artifact just in case the website is unavailable.
+
+                    See also: http://docs.oracle.com/javase/7/docs/api/java/nio/file/Files.html#createSymbolicLink(java.nio.file.Path,%20java.nio.file.Path,%20java.nio.file.attribute.FileAttribute...)
+                    -->
+                    <execution>
+                        <id>install-sysinternals-junction</id>
+                        <goals>
+                            <goal>install-file</goal>
+                        </goals>
+                        <phase>initialize</phase>
+                        <inherited>false</inherited>
+                        <configuration>
+                            <file>${gatk.basedir}/public/repo/sysinternals/junction/1.04/junction-1.04.exe</file>
+                            <pomFile>${gatk.basedir}/public/repo/sysinternals/junction/1.04/junction-1.04.pom</pomFile>
+                            <packaging>exe</packaging>
+                        </configuration>
+                    </execution>
+                </executions>
+            </plugin>
+        </plugins>
+    </build>
+
+    <reporting>
+        <excludeDefaults>true</excludeDefaults>
+    </reporting>
+
+    <repositories>
+        <repository>
+            <id>gatk.public.repo.local</id>
+            <name>GATK Public Local Repository</name>
+            <url>file:${gatk.basedir}/public/repo</url>
+        </repository>
+    </repositories>
+
+</project>
diff --git a/public/gatk-tools-public/pom.xml b/public/gatk-tools-public/pom.xml
new file mode 100644
index 0000000..5386b32
--- /dev/null
+++ b/public/gatk-tools-public/pom.xml
@@ -0,0 +1,81 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+    <modelVersion>4.0.0</modelVersion>
+
+    <parent>
+        <groupId>org.broadinstitute.gatk</groupId>
+        <artifactId>gatk-aggregator</artifactId>
+        <version>3.3</version>
+        <relativePath>../..</relativePath>
+    </parent>
+
+    <artifactId>gatk-tools-public</artifactId>
+    <packaging>jar</packaging>
+    <name>GATK Tools Public</name>
+
+    <properties>
+        <gatk.basedir>${project.basedir}/../..</gatk.basedir>
+        <gatk.packagetests.artifactId>gatk-package-distribution</gatk.packagetests.artifactId>
+    </properties>
+
+    <dependencies>
+        <dependency>
+            <groupId>${project.groupId}</groupId>
+            <artifactId>gatk-engine</artifactId>
+            <version>${project.version}</version>
+        </dependency>
+
+        <dependency>
+            <groupId>com.google.caliper</groupId>
+            <artifactId>caliper</artifactId>
+            <scope>test</scope>
+        </dependency>
+    </dependencies>
+
+    <build>
+        <plugins>
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-resources-plugin</artifactId>
+                <executions>
+                    <execution>
+                        <id>copy-resource-bundle-log4j</id>
+                        <phase>prepare-package</phase>
+                    </execution>
+                </executions>
+            </plugin>
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-javadoc-plugin</artifactId>
+                <executions>
+                    <execution>
+                        <id>extract-resource-bundle</id>
+                        <phase>prepare-package</phase>
+                    </execution>
+                </executions>
+            </plugin>
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-invoker-plugin</artifactId>
+                <executions>
+                    <execution>
+                        <id>package-unittests</id>
+                    </execution>
+                    <execution>
+                        <id>package-integrationtests</id>
+                    </execution>
+                    <execution>
+                        <id>package-largescaletests</id>
+                    </execution>
+                    <execution>
+                        <id>package-knowledgebasetests</id>
+                    </execution>
+                    <execution>
+                        <id>package-queuetests</id>
+                    </execution>
+                </executions>
+            </plugin>
+        </plugins>
+    </build>
+
+</project>
diff --git a/public/gatk-tools-public/src/main/java/htsjdk/samtools/GATKBAMFileSpan.java b/public/gatk-tools-public/src/main/java/htsjdk/samtools/GATKBAMFileSpan.java
new file mode 100644
index 0000000..c2a5e80
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/htsjdk/samtools/GATKBAMFileSpan.java
@@ -0,0 +1,308 @@
+/*
+* Copyright (c) 2012 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 htsjdk.samtools;
+
+import htsjdk.samtools.util.PeekableIterator;
+import org.broadinstitute.gatk.utils.exceptions.ReviewedGATKException;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.Iterator;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Queue;
+
+/**
+ * A temporary solution to work around Java access rights issues:
+ * override BAMFileSpan and make it public.
+ * TODO: Eliminate once we determine the final fate of the BAM index reading code.
+ */
+public class GATKBAMFileSpan extends BAMFileSpan {
+    /**
+     * Create a new empty list of chunks.
+     */
+    public GATKBAMFileSpan() {
+        super();
+    }
+
+    /**
+     * Create a new GATKBAMFileSpan from an existing BAMFileSpan.
+     * @param sourceFileSpan
+     */
+    public GATKBAMFileSpan(SAMFileSpan sourceFileSpan) {
+        if(!(sourceFileSpan instanceof BAMFileSpan))
+            throw new SAMException("Unable to create GATKBAMFileSpan from a SAMFileSpan. Please submit a BAMFileSpan instead");
+        BAMFileSpan sourceBAMFileSpan = (BAMFileSpan)sourceFileSpan;
+        for(Chunk chunk: sourceBAMFileSpan.getChunks())
+            add(chunk instanceof GATKChunk ? chunk : new GATKChunk(chunk));
+    }
+
+    /**
+     * Convenience constructor to construct a BAM file span from
+     * a single chunk.
+     * @param chunk Chunk to use as the sole region in this span.
+     */
+    public GATKBAMFileSpan(final Chunk chunk) {
+        super(chunk);
+    }
+
+    /**
+     * Create a new chunk list from the given list of chunks.
+     * @param chunks Constituent chunks.
+     */
+    public GATKBAMFileSpan(final GATKChunk[] chunks) {
+        super(Arrays.<Chunk>asList(chunks));
+    }
+
+    @Override
+    public boolean equals(final Object other) {
+        if(!(other instanceof BAMFileSpan))
+            return false;
+
+        List<Chunk> theseChunks = getChunks();
+        List<Chunk> otherChunks = ((BAMFileSpan)other).getChunks();
+
+        if(theseChunks.size() != otherChunks.size())
+            return false;
+        for(int i = 0; i < theseChunks.size(); i++) {
+            if(!theseChunks.get(i).equals(otherChunks.get(i)))
+                return false;
+        }
+
+        return true;
+    }
+
+    /**
+     * Gets the constituent chunks stored in this span.
+     * @return An unmodifiable list of chunks.
+     */
+    public List<GATKChunk> getGATKChunks() {
+        List<GATKChunk> gatkChunks = new ArrayList<GATKChunk>();
+        for(Chunk chunk: getChunks())
+            gatkChunks.add(new GATKChunk(chunk));
+        return gatkChunks;
+    }
+
+    public String toString() {
+        StringBuilder builder = new StringBuilder();
+        for(GATKChunk chunk: getGATKChunks())
+            builder.append(String.format("%s;",chunk));
+        return builder.toString();
+    }
+
+    /**
+     * Returns an approximation of the number of uncompressed bytes in this
+     * file span.
+     * @return Approximation of uncompressed bytes in filespan.
+     */
+    public long size() {
+        long size = 0L;
+        for(GATKChunk chunk: getGATKChunks())
+            size += chunk.size();
+        return size;
+    }
+
+    /**
+     * Get a GATKChunk representing the "extent" of this file span, from the start of the first
+     * chunk to the end of the last chunk.The chunks list must be sorted in order to use this method.
+     *
+     * @return a GATKChunk representing the extent of this file span, or a GATKChunk representing
+     *         a span of size 0 if there are no chunks
+     */
+    public GATKChunk getExtent() {
+        validateSorted();   // TODO: defensive measure: may be unnecessary
+
+        List<Chunk> chunks = getChunks();
+        if ( chunks.isEmpty() ) {
+            return new GATKChunk(0L, 0L);
+        }
+
+        return new GATKChunk(chunks.get(0).getChunkStart(), chunks.get(chunks.size() - 1).getChunkEnd());
+    }
+
+    /**
+     * Validates the list of chunks to ensure that they appear in sorted order.
+     */
+    private void validateSorted() {
+        List<Chunk> chunks = getChunks();
+        for ( int i = 1; i < chunks.size(); i++ ) {
+            if ( chunks.get(i).getChunkStart() < chunks.get(i-1).getChunkEnd() ) {
+                throw new ReviewedGATKException(String.format("Chunk list is unsorted; chunk %s is before chunk %s", chunks.get(i-1), chunks.get(i)));
+
+            }
+        }
+    }
+
+    /**
+     * Computes the union of two FileSpans.
+     * @param other FileSpan to union with this one.
+     * @return A file span that's been unioned.
+     */
+    public GATKBAMFileSpan union(final GATKBAMFileSpan other) {
+        // No data?  Return an empty file span.
+        if(getGATKChunks().size() == 0 && other.getGATKChunks().size() == 0)
+            return new GATKBAMFileSpan();
+
+        LinkedList<GATKChunk> unmergedUnion = new LinkedList<GATKChunk>();
+        unmergedUnion.addAll(getGATKChunks());
+        unmergedUnion.addAll(other.getGATKChunks());
+        Collections.sort(unmergedUnion);
+
+        List<GATKChunk> mergedUnion = new ArrayList<GATKChunk>();
+        GATKChunk currentChunk = unmergedUnion.remove();
+        while(!unmergedUnion.isEmpty()) {
+
+            // While the current chunk can be merged with the next chunk:
+            while( ! unmergedUnion.isEmpty() &&
+                   (currentChunk.overlaps(unmergedUnion.peek()) || currentChunk.isAdjacentTo(unmergedUnion.peek())) ) {
+
+                // Merge the current chunk with the next chunk:
+                GATKChunk nextChunk = unmergedUnion.remove();
+                currentChunk = currentChunk.merge(nextChunk);
+            }
+            // Add the accumulated range.
+            mergedUnion.add(currentChunk);
+            currentChunk = !unmergedUnion.isEmpty() ? unmergedUnion.remove() : null;
+        }
+
+        // At end of the loop above, the last chunk will be contained in currentChunk and will not yet have been added.  Add it.
+        if(currentChunk !=null)
+            mergedUnion.add(currentChunk);
+
+        return new GATKBAMFileSpan(mergedUnion.toArray(new GATKChunk[mergedUnion.size()]));
+    }
+
+    /**
+     * Intersects two BAM file spans.
+     * @param other File span to intersect with this one.
+     * @return The intersected BAM file span.
+     */
+    public GATKBAMFileSpan intersection(final GATKBAMFileSpan other) {
+        Iterator<GATKChunk> thisIterator = getGATKChunks().iterator();
+        Iterator<GATKChunk> otherIterator = other.getGATKChunks().iterator();
+
+        if(!thisIterator.hasNext() || !otherIterator.hasNext())
+            return new GATKBAMFileSpan();
+
+        GATKChunk thisChunk = thisIterator.next();
+        GATKChunk otherChunk = otherIterator.next();
+
+        List<GATKChunk> intersected = new ArrayList<GATKChunk>();
+
+        while(thisChunk != null && otherChunk != null) {
+            // If this iterator is before other, skip this ahead.
+            if(thisChunk.getChunkEnd() <= otherChunk.getChunkStart()) {
+                thisChunk = thisIterator.hasNext() ? thisIterator.next() : null;
+                continue;
+            }
+
+            // If other iterator is before this, skip other ahead.
+            if(thisChunk.getChunkStart() >= otherChunk.getChunkEnd()) {
+                otherChunk = otherIterator.hasNext() ? otherIterator.next() : null;
+                continue;
+            }
+
+            // If these two chunks overlap, pull out intersection of data and truncated current chunks to point after
+            // the intersection (or next chunk if no such overlap exists).
+            if(thisChunk.overlaps(otherChunk)) {
+                // Determine the chunk constraints
+                GATKChunk firstChunk = thisChunk.getChunkStart() < otherChunk.getChunkStart() ? thisChunk : otherChunk;
+                GATKChunk secondChunk = thisChunk==firstChunk ? otherChunk : thisChunk;
+                GATKChunk intersectedChunk = new GATKChunk(secondChunk.getChunkStart(),Math.min(firstChunk.getChunkEnd(),secondChunk.getChunkEnd()));
+                intersected.add(intersectedChunk);
+
+                if(thisChunk.getChunkEnd() > intersectedChunk.getChunkEnd())
+                    thisChunk = new GATKChunk(intersectedChunk.getChunkEnd(),thisChunk.getChunkEnd());
+                else
+                    thisChunk = thisIterator.hasNext() ? thisIterator.next() : null;
+
+                if(otherChunk.getChunkEnd() > intersectedChunk.getChunkEnd())
+                    otherChunk = new GATKChunk(intersectedChunk.getChunkEnd(),otherChunk.getChunkEnd());
+                else
+                    otherChunk = otherIterator.hasNext() ? otherIterator.next() : null;
+            }
+
+        }
+
+        return new GATKBAMFileSpan(intersected.toArray(new GATKChunk[intersected.size()]));
+    }
+
+    /**
+     * Substracts other file span from this file span.
+     * @param other File span to strike out.
+     * @return This file span minuse the other file span.
+     */
+
+    public GATKBAMFileSpan minus(final GATKBAMFileSpan other) {
+        Iterator<GATKChunk> thisIterator = getGATKChunks().iterator();
+        Iterator<GATKChunk> otherIterator = other.getGATKChunks().iterator();
+
+        if(!thisIterator.hasNext() || !otherIterator.hasNext())
+            return this;
+
+        GATKChunk thisChunk = thisIterator.next();
+        GATKChunk otherChunk = otherIterator.next();
+
+        List<GATKChunk> subtracted = new ArrayList<GATKChunk>();
+
+        while(thisChunk != null && otherChunk != null) {
+            // If this iterator is before the other, add this to the subtracted list and forge ahead.
+            if(thisChunk.getChunkEnd() <= otherChunk.getChunkStart()) {
+                subtracted.add(thisChunk);
+                thisChunk = thisIterator.hasNext() ? thisIterator.next() : null;
+                continue;
+            }
+
+            // If other iterator is before this, skip other ahead.
+            if(thisChunk.getChunkStart() >= otherChunk.getChunkEnd()) {
+                otherChunk = otherIterator.hasNext() ? otherIterator.next() : null;
+                continue;
+            }
+
+            // If these two chunks overlap, pull out intersection of data and truncated current chunks to point after
+            // the intersection (or next chunk if no such overlap exists).
+            if(thisChunk.overlaps(otherChunk)) {
+                // Add in any sort of prefix that this chunk might have over the other.
+                if(thisChunk.getChunkStart() < otherChunk.getChunkStart())
+                    subtracted.add(new GATKChunk(thisChunk.getChunkStart(),otherChunk.getChunkStart()));
+
+                if(thisChunk.getChunkEnd() > otherChunk.getChunkEnd())
+                    thisChunk = new GATKChunk(otherChunk.getChunkEnd(),thisChunk.getChunkEnd());
+                else
+                    thisChunk = thisIterator.hasNext() ? thisIterator.next() : null;
+            }
+        }
+
+        // Finish up any remaining contents of this that didn't make it into the subtracted array.
+        if(thisChunk != null)
+            subtracted.add(thisChunk);
+        while(thisIterator.hasNext())
+            subtracted.add(thisIterator.next());
+
+        return new GATKBAMFileSpan(subtracted.toArray(new GATKChunk[subtracted.size()]));
+    }
+}
diff --git a/public/gatk-tools-public/src/main/java/htsjdk/samtools/GATKBin.java b/public/gatk-tools-public/src/main/java/htsjdk/samtools/GATKBin.java
new file mode 100644
index 0000000..d1e689d
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/htsjdk/samtools/GATKBin.java
@@ -0,0 +1,135 @@
+/*
+* Copyright (c) 2012 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 htsjdk.samtools;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+/**
+ * A temporary solution to work around Java access rights issues:
+ * override GATKBin and make it public.
+ * TODO: Eliminate once we determine the final fate of the BAM index reading code.
+ */
+public class GATKBin implements Comparable<GATKBin> {
+    /**
+     * The reference sequence associated with this bin.
+     */
+    private final int referenceSequence;
+
+    /**
+     * The number of this bin within the BAM file.
+     */
+    private final int binNumber;
+
+    /**
+     * The chunks associated with this bin.
+     */
+    private GATKChunk[] chunkList;
+
+    public GATKBin(Bin bin) {
+        this(bin.getReferenceSequence(),bin.getBinNumber());
+    }
+
+    public GATKBin(final int referenceSequence, final int binNumber) {
+        this.referenceSequence = referenceSequence;
+        this.binNumber = binNumber;
+    }
+
+    public int getReferenceSequence() {
+        return referenceSequence;
+    }
+
+    public int getBinNumber() {
+        return binNumber;
+    }
+
+    /**
+     * Convert this GATKBin to a normal bin, for processing with the standard BAM query interface.
+     * @return
+     */
+    public Bin toBin() {
+        return new Bin(referenceSequence,binNumber);
+    }
+
+    /**
+     * See whether two bins are equal.  If the ref seq and the bin number
+     * are equal, assume equality of the chunk list.
+     * @param other The other Bin to which to compare this.
+     * @return True if the two bins are equal.  False otherwise.
+     */
+    @Override
+    public boolean equals(Object other) {
+        if(other == null) return false;
+        if(!(other instanceof GATKBin)) return false;
+
+        GATKBin otherBin = (GATKBin)other;
+        return this.referenceSequence == otherBin.referenceSequence && this.binNumber == otherBin.binNumber;
+    }
+
+    /**
+     * Compute a unique hash code for the given reference sequence and bin number.
+     * @return A unique hash code.
+     */
+    @Override
+    public int hashCode() {
+        return ((Integer)referenceSequence).hashCode() ^ ((Integer)binNumber).hashCode();
+    }
+
+    /**
+     * Compare two bins to see what ordering they should appear in.
+     * @param other Other bin to which this bin should be compared.
+     * @return -1 if this < other, 0 if this == other, 1 if this > other.
+     */
+    public int compareTo(GATKBin other) {
+        if(other == null)
+            throw new ClassCastException("Cannot compare to a null object");
+
+        // Check the reference sequences first.
+        if(this.referenceSequence != other.referenceSequence)
+            return referenceSequence - other.referenceSequence;
+
+        // Then check the bin ordering.
+        return binNumber - other.binNumber;
+    }
+
+    /**
+     * Sets the chunks associated with this bin
+     */
+    public void setChunkList(GATKChunk[] list){
+        chunkList = list;
+    }
+
+    /**
+     * Gets the list of chunks associated with this bin.
+     * @return the chunks in this bin.  If no chunks are associated, an empty list will be returned.
+     */
+    public GATKChunk[] getChunkList(){
+        if(chunkList == null)
+            return new GATKChunk[0];
+        return chunkList;
+    }
+}
diff --git a/public/gatk-tools-public/src/main/java/htsjdk/samtools/GATKChunk.java b/public/gatk-tools-public/src/main/java/htsjdk/samtools/GATKChunk.java
new file mode 100644
index 0000000..aed7aec
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/htsjdk/samtools/GATKChunk.java
@@ -0,0 +1,116 @@
+/*
+* Copyright (c) 2012 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 htsjdk.samtools;
+
+/**
+ * A temporary solution to work around Java access rights issues:
+ * override chunk and make it public.
+ * TODO: Eliminate once we determine the final fate of the BAM index reading code.
+ */
+public class GATKChunk extends Chunk {
+    /**
+     * The average ratio of compressed block size / uncompressed block size, computed empirically
+     * using the output of org.broadinstitute.gatk.engine.datasources.reads.utilities.PrintBGZFBounds.
+     */
+    private static final double AVERAGE_BAM_COMPRESSION_RATIO = 0.39;
+
+    public GATKChunk(final long start, final long stop) {
+        super(start,stop);
+    }
+
+    public GATKChunk(final long blockStart, final int blockOffsetStart, final long blockEnd, final int blockOffsetEnd) {
+        super(blockStart << 16 | blockOffsetStart,blockEnd << 16 | blockOffsetEnd);
+    }
+
+    public GATKChunk(final Chunk chunk) {
+        super(chunk.getChunkStart(),chunk.getChunkEnd());
+    }
+
+    @Override
+    public GATKChunk clone() {
+        return new GATKChunk(getChunkStart(),getChunkEnd());
+    }
+
+    @Override
+    public long getChunkStart() {
+        return super.getChunkStart();
+    }
+
+    @Override
+    public void setChunkStart(final long value) {
+        super.setChunkStart(value);
+    }
+
+    @Override
+    public long getChunkEnd() {
+        return super.getChunkEnd();
+    }
+
+    @Override
+    public void setChunkEnd(final long value) {
+        super.setChunkEnd(value);
+    }
+
+    public long getBlockStart() {
+        return getChunkStart() >>> 16;
+    }
+
+    public int getBlockOffsetStart() {
+        return (int)(getChunkStart() & 0xFFFF);
+    }
+
+    public long getBlockEnd() {
+        return getChunkEnd() >>> 16;
+    }
+
+    public int getBlockOffsetEnd() {
+        return ((int)getChunkEnd() & 0xFFFF);
+    }
+
+    /**
+     * Computes an approximation of the uncompressed size of the
+     * chunk, in bytes.  Can be used to determine relative weights
+     * of chunk size.
+     * @return An approximation of the chunk size in bytes.
+     */
+    public long size() {
+        final long chunkSpan = Math.round(((getChunkEnd()>>16)-(getChunkStart()>>16))/AVERAGE_BAM_COMPRESSION_RATIO);
+        final int offsetSpan = (int)((getChunkEnd()&0xFFFF)-(getChunkStart()&0xFFFF));
+        return chunkSpan + offsetSpan;
+    }
+
+    /**
+     * Merges two chunks together. The caller is responsible for testing whether the
+     * chunks overlap/are adjacent before calling this method!
+     *
+     * @param other the chunk to merge with this chunk
+     * @return a new chunk representing the union of the two chunks (provided the chunks were
+     *         overlapping/adjacent)
+     */
+    public GATKChunk merge ( GATKChunk other ) {
+        return new GATKChunk(Math.min(getChunkStart(), other.getChunkStart()), Math.max(getChunkEnd(), other.getChunkEnd()));
+    }
+}
diff --git a/public/gatk-tools-public/src/main/java/htsjdk/samtools/PicardNamespaceUtils.java b/public/gatk-tools-public/src/main/java/htsjdk/samtools/PicardNamespaceUtils.java
new file mode 100644
index 0000000..00f65e5
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/htsjdk/samtools/PicardNamespaceUtils.java
@@ -0,0 +1,40 @@
+/*
+* Copyright (c) 2012 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 htsjdk.samtools;
+
+/**
+ * Utils that insist on being in the same package as Picard.
+ */
+public class PicardNamespaceUtils {
+    /**
+     * Private constructor only.  Do not instantiate.
+     */
+    private PicardNamespaceUtils() {}
+
+    public static void setFileSource(final SAMRecord read, final SAMFileSource fileSource) {
+        read.setFileSource(fileSource);
+    }
+}
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/CommandLineExecutable.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/CommandLineExecutable.java
new file mode 100644
index 0000000..b8221bb
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/CommandLineExecutable.java
@@ -0,0 +1,229 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.engine;
+
+import org.apache.log4j.Logger;
+import org.broadinstitute.gatk.utils.commandline.ArgumentTypeDescriptor;
+import org.broadinstitute.gatk.utils.commandline.CommandLineProgram;
+import org.broadinstitute.gatk.engine.arguments.GATKArgumentCollection;
+import org.broadinstitute.gatk.engine.datasources.reads.SAMReaderID;
+import org.broadinstitute.gatk.engine.filters.ReadFilter;
+import org.broadinstitute.gatk.engine.io.stubs.OutputStreamArgumentTypeDescriptor;
+import org.broadinstitute.gatk.engine.io.stubs.SAMFileWriterArgumentTypeDescriptor;
+import org.broadinstitute.gatk.engine.io.stubs.VCFWriterArgumentTypeDescriptor;
+import org.broadinstitute.gatk.engine.phonehome.GATKRunReport;
+import org.broadinstitute.gatk.engine.refdata.utils.RMDTriplet;
+import org.broadinstitute.gatk.engine.walkers.Walker;
+import org.broadinstitute.gatk.utils.crypt.CryptUtils;
+import org.broadinstitute.gatk.utils.crypt.GATKKey;
+import org.broadinstitute.gatk.utils.exceptions.UserException;
+import org.broadinstitute.gatk.utils.text.ListFileUtils;
+
+import java.security.PublicKey;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+
+/**
+ * @author aaron
+ */
+public abstract class CommandLineExecutable extends CommandLineProgram {
+    /**
+     * The actual engine which performs the analysis.
+     */
+    protected GenomeAnalysisEngine engine = new GenomeAnalysisEngine();
+
+    // get the analysis name
+    public abstract String getAnalysisName();
+
+    /**
+     * Gets the GATK argument bundle.
+     * @return A structure consisting of whatever arguments should be used to initialize the GATK engine.
+     */
+    protected abstract GATKArgumentCollection getArgumentCollection();
+
+    /**
+     * A list of all the arguments initially used as sources.
+     */
+    private final Collection<Object> argumentSources = new ArrayList<Object>();
+
+    protected static Logger logger = Logger.getLogger(CommandLineExecutable.class);
+
+    /**
+     * this is the function that the inheriting class can expect to have called
+     * when the command line system has initialized.
+     *
+     * @return the return code to exit the program with
+     */
+    protected int execute() throws Exception {
+        engine.setParser(parser);
+        argumentSources.add(this);
+
+        Walker<?,?> walker = engine.getWalkerByName(getAnalysisName());
+
+        try {
+            // Make sure a valid GATK user key is present, if required.
+            authorizeGATKRun();
+
+            engine.setArguments(getArgumentCollection());
+
+            // File lists can require a bit of additional expansion.  Set these explicitly by the engine. 
+            final Collection<SAMReaderID> bamFileList=ListFileUtils.unpackBAMFileList(getArgumentCollection().samFiles,parser);
+            engine.setSAMFileIDs(bamFileList);
+            if(getArgumentCollection().showFullBamList){
+                logger.info(String.format("Adding the following input SAM Files: %s",bamFileList.toString()));
+            }
+
+            engine.setWalker(walker);
+            walker.setToolkit(engine);
+
+            Collection<ReadFilter> filters = engine.createFilters();
+            engine.setFilters(filters);
+
+            // load the arguments into the walker / filters.
+            // TODO: The fact that this extra load call exists here when all the parsing happens at the engine
+            // TODO: level indicates that we're doing something wrong.  Turn this around so that the GATK can drive
+            // TODO: argument processing.
+            loadArgumentsIntoObject(walker);
+            argumentSources.add(walker);
+
+            Collection<RMDTriplet> rodBindings = ListFileUtils.unpackRODBindings(parser.getRodBindings(), parser);
+            engine.setReferenceMetaDataFiles(rodBindings);
+
+            for (ReadFilter filter: filters) {
+                loadArgumentsIntoObject(filter);
+                argumentSources.add(filter);
+            }
+
+            engine.execute();
+            generateGATKRunReport(walker);
+        } catch ( Exception e ) {
+            generateGATKRunReport(walker, e);
+            throw e;
+        }
+
+        // always return 0
+        return 0;
+    }
+
+    /**
+     * Authorizes this run of the GATK by checking for a valid GATK user key, if required.
+     * Currently, a key is required only if running with the -et NO_ET or -et STDOUT options.
+     */
+    private void authorizeGATKRun() {
+        if ( getArgumentCollection().phoneHomeType == GATKRunReport.PhoneHomeOption.NO_ET ||
+             getArgumentCollection().phoneHomeType == GATKRunReport.PhoneHomeOption.STDOUT ) {
+            if ( getArgumentCollection().gatkKeyFile == null ) {
+                throw new UserException("Running with the -et NO_ET or -et STDOUT option requires a GATK Key file. " +
+                                        "Please see " + UserException.PHONE_HOME_DOCS_URL +
+                                        " for more information and instructions on how to obtain a key.");
+            }
+            else {
+                PublicKey gatkPublicKey = CryptUtils.loadGATKDistributedPublicKey();
+                GATKKey gatkUserKey = new GATKKey(gatkPublicKey, getArgumentCollection().gatkKeyFile);
+
+                if ( ! gatkUserKey.isValid() ) {
+                    throw new UserException.KeySignatureVerificationException(getArgumentCollection().gatkKeyFile);
+                }
+            }
+        }
+    }
+
+    /**
+     * Generate the GATK run report for this walker using the current GATKEngine, if -et is enabled.
+     * This report will be written to either STDOUT or to the run repository, depending on the options
+     * for -et.
+     *
+     * @param e the exception, can be null if no exception occurred
+     */
+    private void generateGATKRunReport(Walker<?,?> walker, Exception e) {
+        if ( getArgumentCollection().phoneHomeType != GATKRunReport.PhoneHomeOption.NO_ET ) {
+            GATKRunReport report = new GATKRunReport(walker, e, engine, getArgumentCollection().phoneHomeType );
+            report.postReport(getArgumentCollection().phoneHomeType);
+        }
+    }
+
+    /**
+     * Convenience method for fully parameterized generateGATKRunReport when an exception has
+     * not occurred
+     *
+     * @param walker
+     */
+    private void generateGATKRunReport(Walker<?,?> walker) {
+        generateGATKRunReport(walker, null);
+    }
+
+    /**
+     * Subclasses of CommandLinePrograms can provide their own types of command-line arguments.
+     * @return A collection of type descriptors generating implementation-dependent placeholders.
+     */
+    protected Collection<ArgumentTypeDescriptor> getArgumentTypeDescriptors() {
+        return Arrays.asList( new VCFWriterArgumentTypeDescriptor(engine,System.out,argumentSources),
+                              new SAMFileWriterArgumentTypeDescriptor(engine,System.out),
+                              new OutputStreamArgumentTypeDescriptor(engine,System.out) );
+    }
+
+    /**
+     * GATK can add arguments dynamically based on analysis type.
+     *
+     * @return true
+     */
+    @Override
+    protected boolean canAddArgumentsDynamically() {
+        return true;
+    }
+
+    /**
+     * GATK provides the walker as an argument source.
+     * @return List of walkers to load dynamically.
+     */
+    @Override
+    protected Class[] getArgumentSources() {
+        // No walker info?  No plugins.
+        if (getAnalysisName() == null) return new Class[] {};
+
+        Collection<Class> argumentSources = new ArrayList<Class>();
+
+        Walker walker = engine.getWalkerByName(getAnalysisName());
+        engine.setArguments(getArgumentCollection());
+        engine.setWalker(walker);
+        walker.setToolkit(engine);
+        argumentSources.add(walker.getClass());
+
+        Collection<ReadFilter> filters = engine.createFilters();
+        for(ReadFilter filter: filters)
+            argumentSources.add(filter.getClass());
+
+        Class[] argumentSourcesAsArray = new Class[argumentSources.size()];
+        return argumentSources.toArray(argumentSourcesAsArray);
+    }
+
+    @Override
+    protected String getArgumentSourceName( Class argumentSource ) {
+        return engine.getWalkerName((Class<Walker>)argumentSource);
+    }
+
+}
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/CommandLineGATK.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/CommandLineGATK.java
new file mode 100644
index 0000000..f88c413
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/CommandLineGATK.java
@@ -0,0 +1,385 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.engine;
+
+import picard.PicardException;
+import htsjdk.samtools.SAMException;
+import htsjdk.tribble.TribbleException;
+import org.broadinstitute.gatk.utils.commandline.Argument;
+import org.broadinstitute.gatk.utils.commandline.ArgumentCollection;
+import org.broadinstitute.gatk.utils.commandline.CommandLineProgram;
+import org.broadinstitute.gatk.engine.arguments.GATKArgumentCollection;
+import org.broadinstitute.gatk.engine.refdata.tracks.FeatureManager;
+import org.broadinstitute.gatk.engine.walkers.Attribution;
+import org.broadinstitute.gatk.engine.walkers.Walker;
+import org.broadinstitute.gatk.utils.exceptions.UserException;
+import org.broadinstitute.gatk.utils.help.*;
+import org.broadinstitute.gatk.utils.text.TextFormattingUtils;
+
+import java.util.*;
+
+/**
+ * All command line parameters accepted by all tools in the GATK.
+ *
+ * <h3>Info for general users</h3>
+ *
+ * <p>This is a list of options and parameters that are generally available to all tools in the GATK.</p>
+ *
+ * <p>There may be a few restrictions, which are indicated in individual argument descriptions. For example the -BQSR
+ * argument is only meant to be used with a subset of tools, and the -pedigree argument will only be effectively used
+ * by a subset of tools as well. Some arguments conflict with others, and some conversely are dependent on others. This
+ * is all indicated in the detailed argument descriptions, so be sure to read those in their entirety rather than just
+ * skimming the one-line summaey in the table.</p>
+ *
+ * <h3>Info for developers</h3>
+ *
+ * <p>This class is the GATK engine itself, which manages map/reduce data access and runs walkers.</p>
+ *
+ * <p>We run command line GATK programs using this class. It gets the command line args, parses them, and hands the
+ * gatk all the parsed out information. Pretty much anything dealing with the underlying system should go here;
+ * the GATK engine should deal with any data related information.</p>
+ */
+ at DocumentedGATKFeature(groupName = HelpConstants.DOCS_CAT_ENGINE)
+public class CommandLineGATK extends CommandLineExecutable {
+    /**
+     * A complete list of tools (sometimes also called walkers because they "walk" through the data to perform analyses)
+     * is available in the online documentation.
+     */
+    @Argument(fullName = "analysis_type", shortName = "T", doc = "Name of the tool to run")
+    private String analysisName = null;
+
+    // our argument collection, the collection of command line args we accept
+    @ArgumentCollection
+    private GATKArgumentCollection argCollection = new GATKArgumentCollection();
+
+    /**
+     * Get pleasing info about the GATK.
+     *
+     * @return A list of Strings that contain pleasant info about the GATK.
+     */
+    @Override
+    protected ApplicationDetails getApplicationDetails() {
+        return new ApplicationDetails(createApplicationHeader(),
+                getAttribution(),
+                ApplicationDetails.createDefaultRunningInstructions(getClass()),
+                getAdditionalHelp());
+    }
+
+    @Override
+    public String getAnalysisName() {
+        return analysisName;
+    }
+
+    @Override
+    protected GATKArgumentCollection getArgumentCollection() {
+        return argCollection;
+    }
+
+    /**
+     * Required main method implementation.
+     */
+    public static void main(String[] argv) {
+        try {
+            CommandLineGATK instance = new CommandLineGATK();
+            start(instance, argv);
+            System.exit(CommandLineProgram.result); // todo -- this is a painful hack
+        } catch (UserException e) {
+            exitSystemWithUserError(e);
+        } catch (TribbleException e) {
+            // We can generate Tribble Exceptions in weird places when e.g. VCF genotype fields are
+            //   lazy loaded, so they aren't caught elsewhere and made into User Exceptions
+            exitSystemWithUserError(e);
+        } catch(PicardException e) {
+            // TODO: Should Picard exceptions be, in general, UserExceptions or ReviewedGATKExceptions?
+            exitSystemWithError(e);
+        } catch (SAMException e) {
+            checkForMaskedUserErrors(e);
+            exitSystemWithSamError(e);
+        } catch (OutOfMemoryError e) {
+            exitSystemWithUserError(new UserException.NotEnoughMemory());
+        } catch (Throwable t) {
+            checkForMaskedUserErrors(t);
+            exitSystemWithError(t);
+        }
+    }
+
+    public static final String PICARD_TEXT_SAM_FILE_ERROR_1 = "Cannot use index file with textual SAM file";
+    public static final String PICARD_TEXT_SAM_FILE_ERROR_2 = "Cannot retrieve file pointers within SAM text files";
+    public static final String NO_SPACE_LEFT_ON_DEVICE_ERROR = "No space left on device";
+    public static final String DISK_QUOTA_EXCEEDED_ERROR = "Disk quota exceeded";
+
+    private static void checkForMaskedUserErrors(final Throwable t) {
+        // masked out of memory error
+        if ( t instanceof OutOfMemoryError )
+            exitSystemWithUserError(new UserException.NotEnoughMemory());
+        // masked user error
+        if ( t instanceof UserException || t instanceof TribbleException )
+            exitSystemWithUserError(new UserException(t.getMessage()));
+
+        // no message means no masked error
+        final String message = t.getMessage();
+        if ( message == null )
+            return;
+
+        // too many open files error
+        if ( message.contains("Too many open files") )
+            exitSystemWithUserError(new UserException.TooManyOpenFiles());
+
+        // malformed BAM looks like a SAM file
+        if ( message.contains(PICARD_TEXT_SAM_FILE_ERROR_1) || message.contains(PICARD_TEXT_SAM_FILE_ERROR_2) )
+            exitSystemWithSamError(t);
+
+        // can't close tribble index when writing
+        if ( message.contains("Unable to close index for") )
+            exitSystemWithUserError(new UserException(t.getCause() == null ? message : t.getCause().getMessage()));
+
+        // disk is full
+        if ( message.contains(NO_SPACE_LEFT_ON_DEVICE_ERROR) || message.contains(DISK_QUOTA_EXCEEDED_ERROR) )
+            exitSystemWithUserError(new UserException.NoSpaceOnDevice());
+
+        // masked error wrapped in another one
+        if ( t.getCause() != null )
+            checkForMaskedUserErrors(t.getCause());
+    }
+
+    /**
+     * Creates the a short blurb about the GATK, copyright info, and where to get documentation.
+     *
+     * @return The application header.
+     */
+    public static List<String> createApplicationHeader() {
+        List<String> header = new ArrayList<String>();
+        header.add(String.format("The Genome Analysis Toolkit (GATK) v%s, Compiled %s",getVersionNumber(), getBuildTime()));
+        header.add("Copyright (c) 2010 The Broad Institute");
+        header.add("For support and documentation go to " + HelpConstants.BASE_GATK_URL);
+        return header;
+    }
+
+    public static String getVersionNumber() {
+        ResourceBundle headerInfo = TextFormattingUtils.loadResourceBundle("GATKText");
+        return headerInfo.containsKey("org.broadinstitute.gatk.tools.version") ? headerInfo.getString("org.broadinstitute.gatk.tools.version") : "<unknown>";
+    }
+
+    public static String getBuildTime() {
+        ResourceBundle headerInfo = TextFormattingUtils.loadResourceBundle("GATKText");
+        return headerInfo.containsKey("build.timestamp") ? headerInfo.getString("build.timestamp") : "<unknown>";
+    }
+
+    /**
+     * If the user supplied any additional attribution, return it here.
+     * @return Additional attribution if supplied by the user.  Empty (non-null) list otherwise.
+     */
+    private List<String> getAttribution() {
+        List<String> attributionLines = new ArrayList<String>();
+
+        // If no analysis name is present, fill in extra help on the walkers.
+        WalkerManager walkerManager = engine.getWalkerManager();
+        String analysisName = getAnalysisName();
+        if(analysisName != null && walkerManager.exists(analysisName)) {
+            Class<? extends Walker> walkerType = walkerManager.getWalkerClassByName(analysisName);
+            if(walkerType.isAnnotationPresent(Attribution.class))
+                attributionLines.addAll(Arrays.asList(walkerType.getAnnotation(Attribution.class).value()));
+        }
+        return attributionLines;
+    }
+
+    /**
+     * Retrieves additional information about GATK walkers.
+     * the code in HelpFormatter and supply it as a helper to this method.
+     *
+     * @return A string summarizing the walkers available in this distribution.
+     */
+    private String getAdditionalHelp() {
+        String additionalHelp;
+
+        // If no analysis name is present, fill in extra help on the walkers.
+        WalkerManager walkerManager = engine.getWalkerManager();
+        String analysisName = getAnalysisName();
+        if(analysisName != null && walkerManager.exists(getAnalysisName()))
+            additionalHelp = getWalkerHelp(walkerManager.getWalkerClassByName(getAnalysisName()));
+        else
+            additionalHelp = getAllWalkerHelp();
+
+        return additionalHelp;
+    }
+
+    private static final int PACKAGE_INDENT = 1;
+    private static final int WALKER_INDENT = 3;
+    private static final String FIELD_SEPARATOR = "  ";
+
+    private String getWalkerHelp(Class<? extends Walker> walkerType) {
+        // Construct a help string to output details on this walker.
+        StringBuilder additionalHelp = new StringBuilder();
+        Formatter formatter = new Formatter(additionalHelp);
+
+        formatter.format("Available Reference Ordered Data types:%n");
+        formatter.format(new FeatureManager().userFriendlyListOfAvailableFeatures());
+        formatter.format("%n");
+
+        formatter.format("For a full description of this walker, see its GATKdocs at:%n");
+        formatter.format("%s%n", GATKDocUtils.helpLinksToGATKDocs(walkerType));
+
+        return additionalHelp.toString();
+    }
+
+    /**
+     * Load in additional help information about all available walkers.
+     * @return A string representation of the additional help.
+     */
+    private String getAllWalkerHelp() {
+        // Construct a help string to output available walkers.
+        StringBuilder additionalHelp = new StringBuilder();
+        Formatter formatter = new Formatter(additionalHelp);
+
+        // Get the list of walker names from the walker manager.
+        WalkerManager walkerManager = engine.getWalkerManager();
+
+        // Build a list sorted by walker display name.  As this information is collected, keep track of the longest
+        // package / walker name for later formatting.
+        SortedSet<HelpEntry> helpText = new TreeSet<HelpEntry>(new HelpEntryComparator());
+        
+        int longestPackageName = 0;
+        int longestWalkerName = 0;
+        for(Map.Entry<String,Collection<Class<? extends Walker>>> walkersByPackage: walkerManager.getWalkerNamesByPackage(true).entrySet()) {
+            // Get the display name.
+            String packageName = walkersByPackage.getKey();
+            String packageDisplayName = walkerManager.getPackageDisplayName(walkersByPackage.getKey());
+            String packageHelpText = walkerManager.getPackageSummaryText(packageName);
+
+            // Compute statistics about which names is longest.
+            longestPackageName = Math.max(longestPackageName,packageDisplayName.length());
+
+            SortedSet<HelpEntry> walkersInPackage = new TreeSet<HelpEntry>(new HelpEntryComparator());
+            for(Class<? extends Walker> walkerType: walkersByPackage.getValue()) {
+                String walkerName = walkerType.getName();
+                String walkerDisplayName = walkerManager.getName(walkerType);
+                String walkerHelpText = walkerManager.getWalkerSummaryText(walkerType);                
+
+                longestWalkerName = Math.max(longestWalkerName,walkerManager.getName(walkerType).length());
+
+                walkersInPackage.add(new HelpEntry(walkerName,walkerDisplayName,walkerHelpText));
+            }
+
+            // Dump the walkers into the sorted set.
+            helpText.add(new HelpEntry(packageName,packageDisplayName,packageHelpText,Collections.unmodifiableSortedSet(walkersInPackage)));
+        }
+
+        final int headerWidth = Math.max(longestPackageName+PACKAGE_INDENT,longestWalkerName+WALKER_INDENT);
+
+
+        for(HelpEntry packageHelp: helpText) {
+            printDescriptorLine(formatter,PACKAGE_INDENT,packageHelp.displayName,headerWidth,FIELD_SEPARATOR,packageHelp.summary,TextFormattingUtils.DEFAULT_LINE_WIDTH);
+            
+            for(HelpEntry walkerHelp: packageHelp.children)
+                printDescriptorLine(formatter,WALKER_INDENT,walkerHelp.displayName,headerWidth,FIELD_SEPARATOR,walkerHelp.summary,TextFormattingUtils.DEFAULT_LINE_WIDTH);
+
+            // Print a blank line between sets of walkers.
+            printDescriptorLine(formatter,0,"",headerWidth,FIELD_SEPARATOR,"", TextFormattingUtils.DEFAULT_LINE_WIDTH);
+        }
+
+        return additionalHelp.toString();
+    }
+
+    private void printDescriptorLine(Formatter formatter,
+                                     int headerIndentWidth,
+                                     String header,
+                                     int headerWidth,
+                                     String fieldSeparator,
+                                     String description,
+                                     int lineWidth) {
+        final int headerPaddingWidth = headerWidth - header.length() - headerIndentWidth;
+        final int descriptionWidth = lineWidth - fieldSeparator.length() - headerWidth;
+        List<String> wordWrappedText = TextFormattingUtils.wordWrap(description,descriptionWidth);
+
+        String headerIndentFormatString  = headerIndentWidth  > 0 ? "%" + headerIndentWidth  + "s" : "%s";
+        String headerPaddingFormatString = headerPaddingWidth > 0 ? "%" + headerPaddingWidth + "s" : "%s";
+        String headerWidthFormatString   = headerWidth        > 0 ? "%" + headerWidth        + "s" : "%s";
+
+        // Output description line.
+        formatter.format(headerIndentFormatString + "%s" + headerPaddingFormatString + "%s%s%n",
+                "", header, "", fieldSeparator, wordWrappedText.size()>0?wordWrappedText.get(0):"");
+        for(int i = 1; i < wordWrappedText.size(); i++)
+            formatter.format(headerWidthFormatString + "%s%s%n", "", fieldSeparator, wordWrappedText.get(i));
+    }
+
+}
+
+/**
+ * Represents a given help entry; contains a display name, a summary and optionally some children.
+ */
+class HelpEntry {
+    public final String uid;
+    public final String displayName;
+    public final String summary;
+    public final SortedSet<HelpEntry> children;
+
+    /**
+     * Create a new help entry with the given display name, summary and children.
+     * @param uid a unique identifier.  Usually, the java package.
+     * @param displayName display name for this help entry.
+     * @param summary summary for this help entry.
+     * @param children children for this help entry.
+     */
+    public HelpEntry(String uid, String displayName, String summary, SortedSet<HelpEntry> children)  {
+        this.uid = uid;
+        this.displayName = displayName;
+        this.summary = summary;
+        this.children = children;
+    }
+
+    /**
+     * Create a new help entry with the given display name, summary and children.
+     * @param uid a unique identifier.  Usually, the java package.
+     * @param displayName display name for this help entry.
+     * @param summary summary for this help entry.
+     */
+    public HelpEntry(String uid, String displayName, String summary) {
+        this(uid,displayName,summary,null);
+    }
+
+}
+
+/**
+ * Compare two help entries by display name.
+ */
+class HelpEntryComparator implements Comparator<HelpEntry> {
+    private static TextFormattingUtils.CaseInsensitiveComparator textComparator = new TextFormattingUtils.CaseInsensitiveComparator();
+
+    /**
+     * Compares the order of lhs to rhs, not taking case into account.
+     * @param lhs First object to compare.
+     * @param rhs Second object to compare.
+     * @return 0 if objects are identical; -1 if lhs is before rhs, 1 if rhs is before lhs.  Nulls are treated as after everything else.
+     */
+    public int compare(HelpEntry lhs, HelpEntry rhs) {
+        if(lhs == null && rhs == null) return 0;
+        if(lhs == null || lhs.displayName.equals("")) return 1;
+        if(rhs == null || rhs.displayName.equals("")) return -1;
+        return lhs.displayName.equals(rhs.displayName) ? textComparator.compare(lhs.uid,rhs.uid) : textComparator.compare(lhs.displayName,rhs.displayName);
+    }
+
+
+}
\ No newline at end of file
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/GenomeAnalysisEngine.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/GenomeAnalysisEngine.java
new file mode 100644
index 0000000..abb6993
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/GenomeAnalysisEngine.java
@@ -0,0 +1,1280 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.engine;
+
+import com.google.java.contract.Ensures;
+import htsjdk.samtools.SAMFileHeader;
+import htsjdk.samtools.SAMRecord;
+import htsjdk.samtools.SAMSequenceDictionary;
+import htsjdk.samtools.reference.IndexedFastaSequenceFile;
+import htsjdk.samtools.reference.ReferenceSequenceFile;
+import htsjdk.variant.vcf.VCFConstants;
+import org.apache.log4j.Logger;
+import org.broadinstitute.gatk.engine.arguments.GATKArgumentCollection;
+import org.broadinstitute.gatk.engine.arguments.ValidationExclusion;
+import org.broadinstitute.gatk.engine.datasources.reads.*;
+import org.broadinstitute.gatk.engine.datasources.reference.ReferenceDataSource;
+import org.broadinstitute.gatk.engine.datasources.rmd.ReferenceOrderedDataSource;
+import org.broadinstitute.gatk.engine.downsampling.DownsamplingMethod;
+import org.broadinstitute.gatk.engine.executive.MicroScheduler;
+import org.broadinstitute.gatk.engine.filters.FilterManager;
+import org.broadinstitute.gatk.engine.filters.ReadFilter;
+import org.broadinstitute.gatk.engine.filters.ReadGroupBlackListFilter;
+import org.broadinstitute.gatk.engine.io.OutputTracker;
+import org.broadinstitute.gatk.engine.io.stubs.SAMFileWriterStub;
+import org.broadinstitute.gatk.engine.io.stubs.Stub;
+import org.broadinstitute.gatk.engine.io.stubs.VariantContextWriterStub;
+import org.broadinstitute.gatk.engine.iterators.ReadTransformer;
+import org.broadinstitute.gatk.engine.iterators.ReadTransformersMode;
+import org.broadinstitute.gatk.engine.phonehome.GATKRunReport;
+import org.broadinstitute.gatk.engine.refdata.tracks.IndexDictionaryUtils;
+import org.broadinstitute.gatk.engine.refdata.tracks.RMDTrackBuilder;
+import org.broadinstitute.gatk.engine.refdata.utils.RMDTriplet;
+import org.broadinstitute.gatk.engine.resourcemanagement.ThreadAllocation;
+import org.broadinstitute.gatk.engine.samples.SampleDB;
+import org.broadinstitute.gatk.engine.samples.SampleDBBuilder;
+import org.broadinstitute.gatk.engine.walkers.*;
+import org.broadinstitute.gatk.tools.walkers.genotyper.IndexedSampleList;
+import org.broadinstitute.gatk.tools.walkers.genotyper.SampleList;
+import org.broadinstitute.gatk.utils.*;
+import org.broadinstitute.gatk.utils.classloader.PluginManager;
+import org.broadinstitute.gatk.utils.commandline.*;
+import org.broadinstitute.gatk.utils.exceptions.ReviewedGATKException;
+import org.broadinstitute.gatk.utils.exceptions.UserException;
+import org.broadinstitute.gatk.utils.interval.IntervalUtils;
+import org.broadinstitute.gatk.utils.progressmeter.ProgressMeter;
+import org.broadinstitute.gatk.utils.recalibration.BQSRArgumentSet;
+import org.broadinstitute.gatk.utils.sam.ReadUtils;
+import org.broadinstitute.gatk.utils.text.XReadLines;
+import org.broadinstitute.gatk.utils.threading.ThreadEfficiencyMonitor;
+
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.util.*;
+import java.util.concurrent.TimeUnit;
+
+import static org.broadinstitute.gatk.utils.DeprecatedToolChecks.getWalkerDeprecationInfo;
+import static org.broadinstitute.gatk.utils.DeprecatedToolChecks.isDeprecatedWalker;
+
+/**
+ * A GenomeAnalysisEngine that runs a specified walker.
+ */
+public class GenomeAnalysisEngine {
+    /**
+     * our log, which we want to capture anything from this class
+     */
+    private static Logger logger = Logger.getLogger(GenomeAnalysisEngine.class);
+    public static final long NO_RUNTIME_LIMIT = -1;
+
+    /**
+     * The GATK command-line argument parsing code.
+     */
+    private ParsingEngine parsingEngine;
+
+    /**
+     * The genomeLocParser can create and parse GenomeLocs.
+     */
+    private GenomeLocParser genomeLocParser;
+
+    /**
+     * Accessor for sharded read data.
+     */
+    private SAMDataSource readsDataSource = null;
+
+    /**
+     * Accessor for sharded reference data.
+     */
+    private ReferenceDataSource referenceDataSource = null;
+
+    /**
+     * Accessor for sample metadata
+     */
+    private SampleDB sampleDB = new SampleDB();
+
+    /**
+     * Accessor for sharded reference-ordered data.
+     */
+    private List<ReferenceOrderedDataSource> rodDataSources;
+
+    // our argument collection
+    private GATKArgumentCollection argCollection;
+
+    /**
+     * Collection of intervals used by the engine.
+     */
+    private GenomeLocSortedSet intervals = null;
+
+    /**
+     * Explicitly assign the interval set to use for this traversal (for unit testing purposes)
+     * @param intervals set of intervals to use for this traversal
+     */
+    public void setIntervals( GenomeLocSortedSet intervals ) {
+        this.intervals = intervals;
+    }
+
+    /**
+     * Collection of inputs used by the engine.
+     */
+    private Map<ArgumentSource, Object> inputs = new HashMap<ArgumentSource, Object>();
+
+    /**
+     * Collection of outputs used by the engine.
+     */
+    private Collection<Stub<?>> outputs = new ArrayList<Stub<?>>();
+
+    /**
+     * Collection of the filters applied to the input data.
+     */
+    private Collection<ReadFilter> filters;
+
+    /**
+     * Collection of the read transformers applied to the reads
+     */
+    private List<ReadTransformer> readTransformers;
+
+    /**
+     * Controls the allocation of threads between CPU vs IO.
+     */
+    private ThreadAllocation threadAllocation;
+
+    private ReadMetrics cumulativeMetrics = null;
+
+    /**
+     * A currently hacky unique name for this GATK instance
+     */
+    private String myName = "GATK_" + Math.abs(getRandomGenerator().nextInt());
+
+    /**
+     * our walker manager
+     */
+    private final WalkerManager walkerManager = new WalkerManager();
+
+    private Walker<?, ?> walker;
+
+    public void setWalker(Walker<?, ?> walker) {
+        this.walker = walker;
+    }
+
+    /**
+     * The short name of the current GATK walker as a string
+     * @return a non-null String
+     */
+    public String getWalkerName() {
+        return getWalkerName(walker.getClass());
+    }
+
+    /**
+     * A processed collection of SAM reader identifiers.
+     */
+    private Collection<SAMReaderID> samReaderIDs = Collections.emptyList();
+
+    /**
+     * Set the SAM/BAM files over which to traverse.
+     * @param samReaderIDs Collection of ids to use during this traversal.
+     */
+    public void setSAMFileIDs(Collection<SAMReaderID> samReaderIDs) {
+        this.samReaderIDs = samReaderIDs;
+    }
+
+    /**
+     * Collection of reference metadata files over which to traverse.
+     */
+    private Collection<RMDTriplet> referenceMetaDataFiles;
+
+    /**
+     * The threading efficiency monitor we use in the GATK to monitor our efficiency.
+     *
+     * May be null if one isn't active, or hasn't be initialized yet
+     */
+    private ThreadEfficiencyMonitor threadEfficiencyMonitor = null;
+
+    /**
+     * The global progress meter we are using to track our progress through the genome
+     */
+    private ProgressMeter progressMeter = null;
+
+    /**
+     * Set the reference metadata files to use for this traversal.
+     * @param referenceMetaDataFiles Collection of files and descriptors over which to traverse.
+     */
+    public void setReferenceMetaDataFiles(Collection<RMDTriplet> referenceMetaDataFiles) {
+        this.referenceMetaDataFiles = referenceMetaDataFiles;
+    }
+
+    /**
+     * The maximum runtime of this engine, in nanoseconds, set during engine initialization
+     * from the GATKArgumentCollection command line value
+     */
+    private long runtimeLimitInNanoseconds = -1;
+
+    /**
+     *  Static random number generator and seed.
+     */
+    private static final long GATK_RANDOM_SEED = 47382911L;
+    private static Random randomGenerator = new Random(GATK_RANDOM_SEED);
+    public static Random getRandomGenerator() { return randomGenerator; }
+    public static void resetRandomGenerator() { randomGenerator.setSeed(GATK_RANDOM_SEED); }
+    public static void resetRandomGenerator(long seed) { randomGenerator.setSeed(seed); }
+
+    /**
+     *  Base Quality Score Recalibration helper object
+     */
+    private BQSRArgumentSet bqsrArgumentSet = null;
+    public BQSRArgumentSet getBQSRArgumentSet() { return bqsrArgumentSet; }
+    public boolean hasBQSRArgumentSet() { return bqsrArgumentSet != null; }
+    public void setBaseRecalibration(final GATKArgumentCollection args) {
+        bqsrArgumentSet = new BQSRArgumentSet(args);
+    }
+
+    /**
+     * Actually run the GATK with the specified walker.
+     *
+     * @return the value of this traversal.
+     */
+    public Object execute() {
+        // first thing is to make sure the AWS keys can be decrypted
+        GATKRunReport.checkAWSAreValid();
+
+        //HeapSizeMonitor monitor = new HeapSizeMonitor();
+        //monitor.start();
+        setStartTime(new java.util.Date());
+
+        final GATKArgumentCollection args = this.getArguments();
+
+        // validate our parameters
+        if (args == null) {
+            throw new ReviewedGATKException("The GATKArgumentCollection passed to GenomeAnalysisEngine can not be null.");
+        }
+
+        // validate our parameters              
+        if (this.walker == null)
+            throw new ReviewedGATKException("The walker passed to GenomeAnalysisEngine can not be null.");
+
+        if (args.nonDeterministicRandomSeed)
+            resetRandomGenerator(System.currentTimeMillis());
+
+        // if the use specified an input BQSR recalibration table then enable on the fly recalibration
+        if (args.BQSR_RECAL_FILE != null)
+            setBaseRecalibration(args);
+
+        // setup the runtime limits
+        setupRuntimeLimits(args);
+
+        // Determine how the threads should be divided between CPU vs. IO.
+        determineThreadAllocation();
+
+        // Prepare the data for traversal.
+        initializeDataSources();
+
+        // initialize and validate the interval list
+        initializeIntervals();
+        validateSuppliedIntervals();
+
+        // check to make sure that all sequence dictionaries are compatible with the reference's sequence dictionary
+        validateDataSourcesAgainstReference(readsDataSource, referenceDataSource.getReference(), rodDataSources);
+
+        // initialize sampleDB
+        initializeSampleDB();
+
+        // our microscheduler, which is in charge of running everything
+        MicroScheduler microScheduler = createMicroscheduler();
+        threadEfficiencyMonitor = microScheduler.getThreadEfficiencyMonitor();
+
+        // create temp directories as necessary
+        initializeTempDirectory();
+
+        // create the output streams
+        initializeOutputStreams(microScheduler.getOutputTracker());
+
+        // Initializing the shard iterator / BAM schedule might take some time, so let the user know vaguely what's going on
+        logger.info("Preparing for traversal" +
+                    (readsDataSource.getReaderIDs().size() > 0 ? String.format(" over %d BAM files", readsDataSource.getReaderIDs().size()) : ""));
+        Iterable<Shard> shardStrategy = getShardStrategy(readsDataSource,microScheduler.getReference(),intervals);
+        logger.info("Done preparing for traversal");
+
+        // execute the microscheduler, storing the results
+        return microScheduler.execute(this.walker, shardStrategy);
+
+        //monitor.stop();
+        //logger.info(String.format("Maximum heap size consumed: %d",monitor.getMaxMemoryUsed()));
+
+        //return result;
+    }
+
+    /**
+     * Retrieves an instance of the walker based on the walker name.
+     *
+     * @param walkerName Name of the walker.  Must not be null.  If the walker cannot be instantiated, an exception will be thrown.
+     * @return An instance of the walker.
+     */
+    public Walker<?, ?> getWalkerByName(String walkerName) {
+        try {
+            return walkerManager.createByName(walkerName);
+        } catch ( UserException e ) {
+            if ( isDeprecatedWalker(walkerName) ) {
+                e = new UserException.DeprecatedWalker(walkerName, getWalkerDeprecationInfo(walkerName));
+            }
+            throw e;
+        }
+    }
+
+    /**
+     * Gets the name of a given walker type.
+     * @param walkerType Type of walker.
+     * @return Name of the walker.
+     */
+    public String getWalkerName(Class<? extends Walker> walkerType) {
+        return walkerManager.getName(walkerType);
+    }
+
+    public String getName() {
+        return myName;
+    }
+
+    /**
+     * Gets a list of the filters to associate with the given walker.  Will NOT initialize the engine with this filters;
+     * the caller must handle that directly.
+     * @return A collection of available filters.
+     */
+    public Collection<ReadFilter> createFilters() {
+        final List<ReadFilter> filters = new LinkedList<>();
+
+        // First add the user requested filters
+        if (this.getArguments().readGroupBlackList != null && this.getArguments().readGroupBlackList.size() > 0)
+            filters.add(new ReadGroupBlackListFilter(this.getArguments().readGroupBlackList));
+        for(final String filterName: this.getArguments().readFilters)
+            filters.add(this.getFilterManager().createByName(filterName));
+
+        // now add the walker default filters.  This ordering is critical important if
+        // users need to apply filters that fix up reads that would be removed by default walker filters
+        filters.addAll(WalkerManager.getReadFilters(walker,this.getFilterManager()));
+
+        return Collections.unmodifiableList(filters);
+    }
+
+    /**
+     * Returns a list of active, initialized read transformers
+     *
+     * @param walker the walker we need to apply read transformers too
+     */
+    public void initializeReadTransformers(final Walker walker) {
+        // keep a list of the active read transformers sorted based on priority ordering
+        List<ReadTransformer> activeTransformers = new ArrayList<ReadTransformer>();
+
+        final ReadTransformersMode overrideMode = WalkerManager.getWalkerAnnotation(walker, ReadTransformersMode.class);
+        final ReadTransformer.ApplicationTime overrideTime = overrideMode != null ? overrideMode.ApplicationTime() : null;
+
+        final PluginManager<ReadTransformer> pluginManager = new PluginManager<ReadTransformer>(ReadTransformer.class);
+
+        for ( final ReadTransformer transformer : pluginManager.createAllTypes() ) {
+            transformer.initialize(overrideTime, this, walker);
+            if ( transformer.enabled() )
+                activeTransformers.add(transformer);
+        }
+
+        setReadTransformers(activeTransformers);
+    }
+
+    public List<ReadTransformer> getReadTransformers() {
+        return readTransformers;
+    }
+
+    /*
+     * Sanity checks that incompatible read transformers are not active together (and throws an exception if they are).
+     *
+     * @param readTransformers   the active read transformers
+     */
+    protected void checkActiveReadTransformers(final List<ReadTransformer> readTransformers) {
+        if ( readTransformers == null )
+            throw new IllegalArgumentException("read transformers cannot be null");
+
+        ReadTransformer sawMustBeFirst = null;
+        ReadTransformer sawMustBeLast  = null;
+
+        for ( final ReadTransformer r : readTransformers ) {
+            if ( r.getOrderingConstraint() == ReadTransformer.OrderingConstraint.MUST_BE_FIRST ) {
+                if ( sawMustBeFirst != null )
+                    throw new UserException.IncompatibleReadFiltersException(sawMustBeFirst.toString(), r.toString());
+                sawMustBeFirst = r;
+            } else if ( r.getOrderingConstraint() == ReadTransformer.OrderingConstraint.MUST_BE_LAST ) {
+                if ( sawMustBeLast != null )
+                    throw new UserException.IncompatibleReadFiltersException(sawMustBeLast.toString(), r.toString());
+                sawMustBeLast = r;
+            }
+        }
+    }
+
+    protected void setReadTransformers(final List<ReadTransformer> readTransformers) {
+        if ( readTransformers == null )
+            throw new ReviewedGATKException("read transformers cannot be null");
+
+        // sort them in priority order
+        Collections.sort(readTransformers, new ReadTransformer.ReadTransformerComparator());
+
+        // make sure we don't have an invalid set of active read transformers
+        checkActiveReadTransformers(readTransformers);
+
+        this.readTransformers = readTransformers;
+    }
+
+    /**
+     * Parse out the thread allocation from the given command-line argument.
+     */
+    private void determineThreadAllocation() {
+        if ( argCollection.numberOfDataThreads < 1 ) throw new UserException.BadArgumentValue("num_threads", "cannot be less than 1, but saw " + argCollection.numberOfDataThreads);
+        if ( argCollection.numberOfCPUThreadsPerDataThread < 1 ) throw new UserException.BadArgumentValue("num_cpu_threads", "cannot be less than 1, but saw " + argCollection.numberOfCPUThreadsPerDataThread);
+        if ( argCollection.numberOfIOThreads < 0 ) throw new UserException.BadArgumentValue("num_io_threads", "cannot be less than 0, but saw " + argCollection.numberOfIOThreads);
+
+        this.threadAllocation = new ThreadAllocation(argCollection.numberOfDataThreads,
+                argCollection.numberOfCPUThreadsPerDataThread,
+                argCollection.numberOfIOThreads,
+                argCollection.monitorThreadEfficiency);
+    }
+
+    public int getTotalNumberOfThreads() {
+        return this.threadAllocation == null ? 1 : threadAllocation.getTotalNumThreads();
+    }
+
+
+
+    /**
+     * Allow subclasses and others within this package direct access to the walker manager.
+     * @return The walker manager used by this package.
+     */
+    protected WalkerManager getWalkerManager() {
+        return walkerManager;
+    }
+    
+    /**
+     * setup a microscheduler
+     *
+     * @return a new microscheduler
+     */
+    private MicroScheduler createMicroscheduler() {
+        // Temporarily require all walkers to have a reference, even if that reference is not conceptually necessary.
+        if ((walker instanceof ReadWalker || walker instanceof DuplicateWalker || walker instanceof ReadPairWalker) &&
+                this.getArguments().referenceFile == null) {
+            throw new UserException.CommandLineException("Read-based traversals require a reference file but none was given");
+        }
+
+        return MicroScheduler.create(this,walker,this.getReadsDataSource(),this.getReferenceDataSource().getReference(),this.getRodDataSources(),threadAllocation);
+    }
+
+    protected DownsamplingMethod getDownsamplingMethod() {
+        GATKArgumentCollection argCollection = this.getArguments();
+
+        DownsamplingMethod commandLineMethod = argCollection.getDownsamplingMethod();
+        DownsamplingMethod walkerMethod = WalkerManager.getDownsamplingMethod(walker);
+
+        DownsamplingMethod method = commandLineMethod != null ? commandLineMethod : walkerMethod;
+        method.checkCompatibilityWithWalker(walker);
+        return method;
+    }
+
+    protected void setDownsamplingMethod(DownsamplingMethod method) {
+        argCollection.setDownsamplingMethod(method);
+    }
+
+    protected boolean includeReadsWithDeletionAtLoci() {
+        return walker.includeReadsWithDeletionAtLoci();
+    }
+
+    /**
+     * Verifies that the supplied set of reads files mesh with what the walker says it requires;
+     * also makes sure that list of SAM files specified on the command line is not empty and contains
+     * no duplicates.
+     */
+    protected void validateSuppliedReads() {
+        GATKArgumentCollection arguments = this.getArguments();
+        final Boolean samFilesArePresent = (arguments.samFiles != null && !arguments.samFiles.isEmpty());
+
+        // Check what the walker says is required against what was provided on the command line.
+        if (WalkerManager.isRequired(walker, DataSource.READS) && !samFilesArePresent)
+            throw new ArgumentException("Walker requires reads but none were provided.");
+
+        // Check what the walker says is allowed against what was provided on the command line.
+        if (samFilesArePresent && !WalkerManager.isAllowed(walker, DataSource.READS))
+            throw new ArgumentException("Walker does not allow reads but reads were provided.");
+
+        //Make sure SAM list specified by the user (if necessary) is not empty
+        if(WalkerManager.isRequired(walker, DataSource.READS) && samFilesArePresent && samReaderIDs.isEmpty() ) {
+            throw new UserException("The list of input files does not contain any BAM files.");
+        }
+
+        // Make sure no SAM files were specified multiple times by the user.
+        checkForDuplicateSamFiles();
+    }
+
+    /**
+     * Checks whether there are SAM files that appear multiple times in the fully unpacked list of
+     * SAM files (samReaderIDs). If there are, throws an ArgumentException listing the files in question.
+     */
+    protected void checkForDuplicateSamFiles() {
+        Set<SAMReaderID> encounteredSamFiles = new HashSet<SAMReaderID>();
+        Set<String> duplicateSamFiles = new LinkedHashSet<String>();
+
+        for ( SAMReaderID samFile : samReaderIDs ) {
+            if ( encounteredSamFiles.contains(samFile) ) {
+                duplicateSamFiles.add(samFile.getSamFilePath());
+            }
+            else {
+                encounteredSamFiles.add(samFile);
+            }
+        }
+
+        if ( duplicateSamFiles.size() > 0 ) {
+            throw new UserException("The following BAM files appear multiple times in the list of input files: " +
+                                    duplicateSamFiles + " BAM files may be specified at most once.");
+        }
+
+    }
+
+    /**
+     * Verifies that the supplied reference file mesh with what the walker says it requires.
+     */
+    protected void validateSuppliedReference() {
+        GATKArgumentCollection arguments = this.getArguments();
+        // Check what the walker says is required against what was provided on the command line.
+        // TODO: Temporarily disabling WalkerManager.isRequired check on the reference because the reference is always required.
+        if (/*WalkerManager.isRequired(walker, DataSource.REFERENCE) &&*/ arguments.referenceFile == null)
+            throw new ArgumentException("Walker requires a reference but none was provided.");
+
+        // Check what the walker says is allowed against what was provided on the command line.
+        if (arguments.referenceFile != null && !WalkerManager.isAllowed(walker, DataSource.REFERENCE))
+            throw new ArgumentException("Walker does not allow a reference but one was provided.");
+    }
+
+    protected void validateSuppliedIntervals() {
+        // Only read walkers support '-L unmapped' intervals.  Trap and validate any other instances of -L unmapped.
+        if(!(walker instanceof ReadWalker)) {
+            GenomeLocSortedSet intervals = getIntervals();
+            if(intervals != null && getIntervals().contains(GenomeLoc.UNMAPPED))
+                throw new ArgumentException("Interval list specifies unmapped region.  Only read walkers may include the unmapped region.");
+        }
+
+        // If intervals is non-null and empty at this point, it means that the list of intervals to process
+        // was filtered down to an empty set (eg., the user specified something like -L chr1 -XL chr1). Since
+        // this was very likely unintentional, the user should be informed of this. Note that this is different
+        // from the case where intervals == null, which indicates that there were no interval arguments.
+        if ( intervals != null && intervals.isEmpty() ) {
+            logger.warn("The given combination of -L and -XL options results in an empty set.  No intervals to process.");
+        }
+
+        // TODO: add a check for ActiveRegion walkers to prevent users from passing an entire contig/chromosome
+    }
+
+    /**
+     * Get the sharding strategy given a driving data source.
+     *
+     * @param readsDataSource readsDataSource
+     * @param drivingDataSource Data on which to shard.
+     * @param intervals intervals
+     * @return the sharding strategy
+     */
+    protected Iterable<Shard> getShardStrategy(SAMDataSource readsDataSource, ReferenceSequenceFile drivingDataSource, GenomeLocSortedSet intervals) {
+        ValidationExclusion exclusions = (readsDataSource != null ? readsDataSource.getReadsInfo().getValidationExclusionList() : null);
+        DownsamplingMethod downsamplingMethod = readsDataSource != null ? readsDataSource.getReadsInfo().getDownsamplingMethod() : null;
+        ReferenceDataSource referenceDataSource = this.getReferenceDataSource();
+
+        // If reads are present, assume that accessing the reads is always the dominant factor and shard based on that supposition.
+        if(!readsDataSource.isEmpty()) {
+            if(!readsDataSource.hasIndex() && !exclusions.contains(ValidationExclusion.TYPE.ALLOW_UNINDEXED_BAM))
+                throw new UserException.CommandLineException("Cannot process the provided BAM file(s) because they were not indexed.  The GATK does offer limited processing of unindexed BAMs in --unsafe mode, but this GATK feature is currently unsupported.");
+            if(!readsDataSource.hasIndex() && intervals != null && !argCollection.allowIntervalsWithUnindexedBAM)
+                throw new UserException.CommandLineException("Cannot perform interval processing when reads are present but no index is available.");
+
+            if(walker instanceof LocusWalker) {
+                if (readsDataSource.getSortOrder() != SAMFileHeader.SortOrder.coordinate)
+                    throw new UserException.MissortedBAM(SAMFileHeader.SortOrder.coordinate, "Locus walkers can only traverse coordinate-sorted data.  Please resort your input BAM file(s) or set the Sort Order tag in the header appropriately.");
+                if(intervals == null)
+                    return readsDataSource.createShardIteratorOverMappedReads(new LocusShardBalancer());
+                else
+                    return readsDataSource.createShardIteratorOverIntervals(intervals,new LocusShardBalancer());
+            } 
+            else if(walker instanceof ActiveRegionWalker) {
+                if (readsDataSource.getSortOrder() != SAMFileHeader.SortOrder.coordinate)
+                    throw new UserException.MissortedBAM(SAMFileHeader.SortOrder.coordinate, "Active region walkers can only traverse coordinate-sorted data.  Please resort your input BAM file(s) or set the Sort Order tag in the header appropriately.");
+                if(intervals == null)
+                    return readsDataSource.createShardIteratorOverMappedReads(new ActiveRegionShardBalancer());
+                else
+                    return readsDataSource.createShardIteratorOverIntervals(((ActiveRegionWalker)walker).extendIntervals(intervals, this.genomeLocParser, this.getReferenceDataSource().getReference()), new ActiveRegionShardBalancer());
+            } 
+            else if(walker instanceof ReadWalker || walker instanceof ReadPairWalker || walker instanceof DuplicateWalker) {
+                // Apply special validation to read pair walkers.
+                if(walker instanceof ReadPairWalker) {
+                    if(readsDataSource.getSortOrder() != SAMFileHeader.SortOrder.queryname)
+                        throw new UserException.MissortedBAM(SAMFileHeader.SortOrder.queryname, "Read pair walkers are exceptions in that they cannot be run on coordinate-sorted BAMs but instead require query name-sorted files.  You will need to resort your input BAM file in query name order to use this walker.");
+                    if(intervals != null && !intervals.isEmpty())
+                        throw new UserException.CommandLineException("Pairs traversal cannot be used in conjunction with intervals.");
+                }
+
+                if(intervals == null)
+                    return readsDataSource.createShardIteratorOverAllReads(new ReadShardBalancer());
+                else
+                    return readsDataSource.createShardIteratorOverIntervals(intervals, new ReadShardBalancer());
+            }
+            else
+                throw new ReviewedGATKException("Unable to determine walker type for walker " + walker.getClass().getName());
+        }
+        else {
+            // TODO -- Determine what the ideal shard size should be here.  Matt suggested that a multiple of 16K might work well
+            // TODO --  (because of how VCF indexes work), but my empirical experience has been simply that the larger the shard
+            // TODO --  size the more efficient the traversal (at least for RODWalkers).  Keeping the previous values for now.  [EB]
+            final int SHARD_SIZE = walker instanceof RodWalker ? 1000000 : 100000;
+            if(intervals == null)
+                return referenceDataSource.createShardsOverEntireReference(readsDataSource,genomeLocParser,SHARD_SIZE);
+            else
+                return referenceDataSource.createShardsOverIntervals(readsDataSource,intervals,SHARD_SIZE);
+        }
+    }
+
+    protected boolean flashbackData() {
+        return walker instanceof ReadWalker;
+    }
+
+    /**
+     * Create the temp directory if it doesn't exist.
+     */
+    private void initializeTempDirectory() {
+        File tempDir = new File(System.getProperty("java.io.tmpdir"));
+        if (!tempDir.exists() && !tempDir.mkdirs())
+            throw new UserException.BadTmpDir("Unable to create directory");
+    }
+
+    /**
+     * Initialize the output streams as specified by the user.
+     *
+     * @param outputTracker the tracker supplying the initialization data.
+     */
+    private void initializeOutputStreams(final OutputTracker outputTracker) {
+        for (final Map.Entry<ArgumentSource, Object> input : getInputs().entrySet())
+            outputTracker.addInput(input.getKey(), input.getValue());
+        for (final Stub<?> stub : getOutputs()) {
+            stub.processArguments(argCollection);
+            outputTracker.addOutput(stub);
+        }
+
+        outputTracker.prepareWalker(walker, getArguments().strictnessLevel);
+    }
+
+    public ReferenceDataSource getReferenceDataSource() {
+        return referenceDataSource;
+    }
+
+    public GenomeLocParser getGenomeLocParser() {
+        return genomeLocParser;
+    }
+
+    /**
+     * Manage lists of filters.
+     */
+    private final FilterManager filterManager = new FilterManager();
+
+    private Date startTime = null; // the start time for execution
+
+    public void setParser(ParsingEngine parsingEngine) {
+        this.parsingEngine = parsingEngine;
+    }
+
+    /**
+     * Explicitly set the GenomeLocParser, for unit testing.
+     * @param genomeLocParser GenomeLocParser to use.
+     */
+    public void setGenomeLocParser(GenomeLocParser genomeLocParser) {
+        this.genomeLocParser = genomeLocParser;
+    }
+
+    /**
+     * Sets the start time when the execute() function was last called
+     * @param startTime the start time when the execute() function was last called
+     */
+    protected void setStartTime(Date startTime) {
+        this.startTime = startTime;
+    }
+
+    /**
+     * @return the start time when the execute() function was last called
+     */
+    public Date getStartTime() {
+        return startTime;
+    }
+
+    /**
+     * Setup the intervals to be processed
+     */
+    protected void initializeIntervals() {
+        intervals = IntervalUtils.parseIntervalArguments(this.referenceDataSource, argCollection.intervalArguments);
+    }
+
+    /**
+     * Add additional, externally managed IO streams for inputs.
+     *
+     * @param argumentSource Field into which to inject the value.
+     * @param value          Instance to inject.
+     */
+    public void addInput(ArgumentSource argumentSource, Object value) {
+        inputs.put(argumentSource, value);
+    }
+
+    /**
+     * Add additional, externally managed IO streams for output.
+     *
+     * @param stub Instance to inject.
+     */
+    public void addOutput(Stub<?> stub) {
+        outputs.add(stub);
+    }
+
+    /**
+     * Returns the tag associated with a given command-line argument.
+     * @param key Object for which to inspect the tag.
+     * @return Tags object associated with the given key, or an empty Tag structure if none are present. 
+     */
+    public Tags getTags(Object key)  {
+        return parsingEngine.getTags(key);
+    }
+
+    protected void initializeDataSources() {
+        logger.info("Strictness is " + argCollection.strictnessLevel);
+
+        validateSuppliedReference();
+        setReferenceDataSource(argCollection.referenceFile);
+
+        validateSuppliedReads();
+        initializeReadTransformers(walker);
+
+        final Map<String, String> sampleRenameMap = argCollection.sampleRenameMappingFile != null ?
+                                                    loadSampleRenameMap(argCollection.sampleRenameMappingFile) :
+                                                    null;
+
+        readsDataSource = createReadsDataSource(argCollection,genomeLocParser,referenceDataSource.getReference(), sampleRenameMap);
+
+        for (ReadFilter filter : filters)
+            filter.initialize(this);
+
+        // set the sequence dictionary of all of Tribble tracks to the sequence dictionary of our reference
+        rodDataSources = getReferenceOrderedDataSources(referenceMetaDataFiles,referenceDataSource.getReference().getSequenceDictionary(),
+                                                        genomeLocParser,argCollection.unsafe,sampleRenameMap);
+    }
+
+    /**
+     * Purely for testing purposes.  Do not use unless you absolutely positively know what you are doing (or
+     * need to absolutely positively kill everyone in the room)
+     * @param dataSource
+     */
+    public void setReadsDataSource(final SAMDataSource dataSource) {
+        this.readsDataSource = dataSource;
+    }
+
+    /**
+     * Entry-point function to initialize the samples database from input data and pedigree arguments
+     */
+    private void initializeSampleDB() {
+        SampleDBBuilder sampleDBBuilder = new SampleDBBuilder(this, argCollection.pedigreeValidationType);
+        sampleDBBuilder.addSamplesFromSAMHeader(getSAMFileHeader());
+        sampleDBBuilder.addSamplesFromSampleNames(SampleUtils.getUniqueSamplesFromRods(this));
+        sampleDBBuilder.addSamplesFromPedigreeFiles(argCollection.pedigreeFiles);
+        sampleDBBuilder.addSamplesFromPedigreeStrings(argCollection.pedigreeStrings);
+        sampleDB = sampleDBBuilder.getFinalSampleDB();
+    }
+
+    /**
+     * Gets a unique identifier for the reader sourcing this read.
+     * @param read Read to examine.
+     * @return A unique identifier for the source file of this read.  Exception if not found.
+     */
+    public SAMReaderID getReaderIDForRead(final SAMRecord read) {
+        return getReadsDataSource().getReaderID(read);
+    }
+
+    /**
+     * Gets the source file for this read.
+     * @param id Unique identifier determining which input file to use.
+     * @return The source filename for this read.
+     */
+    public File getSourceFileForReaderID(final SAMReaderID id) {
+        return getReadsDataSource().getSAMFile(id);
+    }
+
+    /**
+     * Now that all files are open, validate the sequence dictionaries of the reads vs. the reference vrs the reference ordered data (if available).
+     *
+     * @param reads     Reads data source.
+     * @param reference Reference data source.
+     * @param rods    a collection of the reference ordered data tracks
+     */
+    private void validateDataSourcesAgainstReference(SAMDataSource reads, ReferenceSequenceFile reference, Collection<ReferenceOrderedDataSource> rods) {
+        if ((reads.isEmpty() && (rods == null || rods.isEmpty())) || reference == null )
+            return;
+
+        // Compile a set of sequence names that exist in the reference file.
+        SAMSequenceDictionary referenceDictionary = reference.getSequenceDictionary();
+
+        if (!reads.isEmpty()) {
+            // Compile a set of sequence names that exist in the BAM files.
+            SAMSequenceDictionary readsDictionary = reads.getHeader().getSequenceDictionary();
+
+            if (readsDictionary.size() == 0) {
+                logger.info("Reads file is unmapped.  Skipping validation against reference.");
+                return;
+            }
+
+            // compare the reads to the reference
+            SequenceDictionaryUtils.validateDictionaries(logger, getArguments().unsafe, "reads", readsDictionary,
+                                                         "reference", referenceDictionary, true, intervals);
+        }
+
+        for (ReferenceOrderedDataSource rod : rods)
+            IndexDictionaryUtils.validateTrackSequenceDictionary(rod.getName(), rod.getSequenceDictionary(), referenceDictionary, getArguments().unsafe);
+    }
+
+    /**
+     * Gets a data source for the given set of reads.
+     *
+     * @param argCollection arguments
+     * @param genomeLocParser parser
+     * @param refReader reader
+     * @return A data source for the given set of reads.
+     */
+    private SAMDataSource createReadsDataSource(final GATKArgumentCollection argCollection, final GenomeLocParser genomeLocParser,
+                                                final IndexedFastaSequenceFile refReader, final Map<String, String> sampleRenameMap) {
+        DownsamplingMethod downsamplingMethod = getDownsamplingMethod();
+
+        // Synchronize the method back into the collection so that it shows up when
+        // interrogating for the downsampling method during command line recreation.
+        setDownsamplingMethod(downsamplingMethod);
+
+        logger.info(downsamplingMethod);
+
+        if (argCollection.removeProgramRecords && argCollection.keepProgramRecords)
+            throw new UserException.BadArgumentValue("rpr / kpr", "Cannot enable both options");
+
+        boolean removeProgramRecords = argCollection.removeProgramRecords || walker.getClass().isAnnotationPresent(RemoveProgramRecords.class);
+
+        if (argCollection.keepProgramRecords)
+            removeProgramRecords = false;
+
+        final boolean keepReadsInLIBS = walker instanceof ActiveRegionWalker;
+
+        return new SAMDataSource(
+                samReaderIDs,
+                threadAllocation,
+                argCollection.numberOfBAMFileHandles,
+                genomeLocParser,
+                argCollection.useOriginalBaseQualities,
+                argCollection.strictnessLevel,
+                argCollection.readBufferSize,
+                downsamplingMethod,
+                new ValidationExclusion(Arrays.asList(argCollection.unsafe)),
+                filters,
+                readTransformers,
+                includeReadsWithDeletionAtLoci(),
+                argCollection.defaultBaseQualities,
+                removeProgramRecords,
+                keepReadsInLIBS,
+                sampleRenameMap,
+                argCollection.intervalArguments.intervalMerging);
+    }
+
+    /**
+     * Loads a user-provided sample rename map file for use in on-the-fly sample renaming into an in-memory
+     * HashMap. This file must consist of lines with two whitespace-separated fields, the second of which
+     * may contain whitespace:
+     *
+     * absolute_path_to_file    new_sample_name
+     *
+     * The engine will verify that each file contains data from only one sample when the on-the-fly sample
+     * renaming feature is being used. Note that this feature works only with bam and vcf files.
+     *
+     * @param sampleRenameMapFile sample rename map file from which to load data
+     * @return a HashMap containing the contents of the map file, with the keys being the input file paths and
+     *         the values being the new sample names.
+     */
+    protected Map<String, String> loadSampleRenameMap( final File sampleRenameMapFile ) {
+        logger.info("Renaming samples from input files on-the-fly using mapping file " + sampleRenameMapFile.getAbsolutePath());
+
+        final Map<String, String> sampleRenameMap = new HashMap<>((int)sampleRenameMapFile.length() / 50);
+
+        try {
+            for ( final String line : new XReadLines(sampleRenameMapFile) ) {
+                final String[] tokens = line.split("\\s+", 2);
+
+                if ( tokens.length != 2 ) {
+                    throw new UserException.MalformedFile(sampleRenameMapFile,
+                                                          String.format("Encountered a line with %s fields instead of the required 2 fields. Line was: %s",
+                                                                        tokens.length, line));
+                }
+
+                final File inputFile = new File(tokens[0]);
+                final String newSampleName = tokens[1].trim();
+
+                if (newSampleName.contains(VCFConstants.FIELD_SEPARATOR)) {
+                    throw new UserException.MalformedFile(sampleRenameMapFile, String.format(
+                            "Encountered illegal sample name; sample names may not include the VCF field delimiter (%s).  Sample name: %s; line: %s",
+                            VCFConstants.FIELD_SEPARATOR,
+                            newSampleName,
+                            line
+                    ));
+                }
+
+                if ( ! inputFile.isAbsolute() ) {
+                    throw new UserException.MalformedFile(sampleRenameMapFile, "Input file path not absolute at line: " + line);
+                }
+
+                final String inputFilePath = inputFile.getAbsolutePath();
+
+                if ( sampleRenameMap.containsKey(inputFilePath) ) {
+                    throw new UserException.MalformedFile(sampleRenameMapFile,
+                                                          String.format("Input file %s appears more than once", inputFilePath));
+                }
+
+                sampleRenameMap.put(inputFilePath, newSampleName);
+            }
+        }
+        catch ( FileNotFoundException e ) {
+            throw new UserException.CouldNotReadInputFile(sampleRenameMapFile, e);
+        }
+
+        return sampleRenameMap;
+    }
+
+
+    /**
+     * Opens a reference sequence file paired with an index.  Only public for testing purposes
+     *
+     * @param refFile Handle to a reference sequence file.  Non-null.
+     */
+    public void setReferenceDataSource(File refFile) {
+        this.referenceDataSource = new ReferenceDataSource(refFile);
+        genomeLocParser = new GenomeLocParser(referenceDataSource.getReference());
+    }
+
+    /**
+     * Open the reference-ordered data sources.
+     *
+     * @param referenceMetaDataFiles collection of RMD descriptors to load and validate.
+     * @param sequenceDictionary GATK-wide sequnce dictionary to use for validation.
+     * @param genomeLocParser to use when creating and validating GenomeLocs.
+     * @param validationExclusionType potentially indicate which validations to include / exclude.
+     * @param sampleRenameMap map of file -> new sample name used when doing on-the-fly sample renaming
+     *
+     * @return A list of reference-ordered data sources.
+     */
+    private List<ReferenceOrderedDataSource> getReferenceOrderedDataSources(final Collection<RMDTriplet> referenceMetaDataFiles,
+                                                                            final SAMSequenceDictionary sequenceDictionary,
+                                                                            final GenomeLocParser genomeLocParser,
+                                                                            final ValidationExclusion.TYPE validationExclusionType,
+                                                                            final Map<String, String> sampleRenameMap) {
+        final RMDTrackBuilder builder = new RMDTrackBuilder(sequenceDictionary,genomeLocParser, validationExclusionType,
+                                                            getArguments().disableAutoIndexCreationAndLockingWhenReadingRods,
+                                                            sampleRenameMap);
+
+        final List<ReferenceOrderedDataSource> dataSources = new ArrayList<ReferenceOrderedDataSource>();
+        for (RMDTriplet fileDescriptor : referenceMetaDataFiles)
+            dataSources.add(new ReferenceOrderedDataSource(fileDescriptor,
+                                                           builder,
+                                                           sequenceDictionary,
+                                                           genomeLocParser,
+                                                           flashbackData()));
+
+        return dataSources;
+    }
+
+    /**
+     * Returns the SAM File Header from the input reads' data source file
+     * @return the SAM File Header from the input reads' data source file
+     */
+    public SAMFileHeader getSAMFileHeader() {
+        return readsDataSource.getHeader();
+    }
+
+    public boolean lenientVCFProcessing() {
+        return lenientVCFProcessing(argCollection.unsafe);
+    }
+
+    public static boolean lenientVCFProcessing(final ValidationExclusion.TYPE val) {
+        return val == ValidationExclusion.TYPE.ALL
+                || val == ValidationExclusion.TYPE.LENIENT_VCF_PROCESSING;
+    }
+
+    /**
+     * Returns the unmerged SAM file header for an individual reader.
+     * @param reader The reader.
+     * @return Header for that reader or null if not available.
+     */
+    public SAMFileHeader getSAMFileHeader(SAMReaderID reader) {
+        return readsDataSource == null ? null : readsDataSource.getHeader(reader);
+    }
+
+    /**
+     * Returns an ordered list of the unmerged SAM file headers known to this engine.
+     * @return list of header for each input SAM file, in command line order
+     */
+    public List<SAMFileHeader> getSAMFileHeaders() {
+        final List<SAMFileHeader> headers = new ArrayList<SAMFileHeader>();
+        for ( final SAMReaderID id : getReadsDataSource().getReaderIDs() ) {
+            headers.add(getReadsDataSource().getHeader(id));
+        }
+        return headers;
+    }
+
+    /**
+     * Gets the master sequence dictionary for this GATK engine instance
+     * @return a never-null dictionary listing all of the contigs known to this engine instance
+     */
+    public SAMSequenceDictionary getMasterSequenceDictionary() {
+        return getReferenceDataSource().getReference().getSequenceDictionary();
+    }
+
+    /**
+     * Returns data source object encapsulating all essential info and handlers used to traverse
+     * reads; header merger, individual file readers etc can be accessed through the returned data source object.
+     *
+     * @return the reads data source
+     */
+    public SAMDataSource getReadsDataSource() {
+        return this.readsDataSource;
+    }
+
+    /**
+     * Sets the collection of GATK main application arguments.
+     *
+     * @param argCollection the GATK argument collection
+     */
+    public void setArguments(GATKArgumentCollection argCollection) {
+        this.argCollection = argCollection;
+    }
+
+    /**
+     * Gets the collection of GATK main application arguments.
+     *
+     * @return the GATK argument collection
+     */
+    public GATKArgumentCollection getArguments() {
+        return this.argCollection;
+    }
+
+    /**
+     * Get the list of intervals passed to the engine.
+     * @return List of intervals, or null if no intervals are in use
+     */
+    public GenomeLocSortedSet getIntervals() {
+        return this.intervals;
+    }
+
+    /**
+     * Get the list of regions of the genome being processed.  If the user
+     * requested specific intervals, return those, otherwise return regions
+     * corresponding to the entire genome.  Never returns null.
+     *
+     * @return a non-null set of intervals being processed
+     */
+    @Ensures("result != null")
+    public GenomeLocSortedSet getRegionsOfGenomeBeingProcessed() {
+        if ( getIntervals() == null )
+            // if we don't have any intervals defined, create intervals from the reference itself
+            return GenomeLocSortedSet.createSetFromSequenceDictionary(getReferenceDataSource().getReference().getSequenceDictionary());
+        else
+            return getIntervals();
+    }
+
+    /**
+     * Gets the list of filters employed by this engine.
+     * @return Collection of filters (actual instances) used by this engine.
+     */
+    public Collection<ReadFilter> getFilters() {
+        return this.filters;
+    }
+
+    /**
+     * Sets the list of filters employed by this engine.
+     * @param filters Collection of filters (actual instances) used by this engine.
+     */
+    public void setFilters(Collection<ReadFilter> filters) {
+        this.filters = filters;
+    }
+
+    /**
+     * Gets the filter manager for this engine.
+     * @return filter manager for this engine.
+     */
+    protected FilterManager getFilterManager() {
+        return filterManager;
+    }
+
+    /**
+     * Gets the input sources for this engine.
+     * @return input sources for this engine.
+     */
+    protected Map<ArgumentSource, Object> getInputs() {
+        return inputs;
+    }
+
+    /**
+     * Gets the output stubs for this engine.
+     * @return output stubs for this engine.
+     */
+    protected Collection<Stub<?>> getOutputs() {
+        return outputs;
+    }
+
+    /**
+     * Returns data source objects encapsulating all rod data;
+     * individual rods can be accessed through the returned data source objects.
+     *
+     * @return the rods data sources, never {@code null}.
+     */
+    public List<ReferenceOrderedDataSource> getRodDataSources() {
+        return this.rodDataSources;
+    }
+
+    /**
+     * Gets cumulative metrics about the entire run to this point.
+     * Returns a clone of this snapshot in time.
+     * @return cumulative metrics about the entire run at this point.  ReadMetrics object is a unique instance and is
+     *         owned by the caller; the caller can do with the object what they wish.
+     */
+    public ReadMetrics getCumulativeMetrics() {
+        // todo -- probably shouldn't be lazy
+        if ( cumulativeMetrics == null )
+            cumulativeMetrics = readsDataSource == null ? new ReadMetrics() : readsDataSource.getCumulativeReadMetrics();
+        return cumulativeMetrics;
+    }
+
+    /**
+     * Return the global ThreadEfficiencyMonitor, if there is one
+     *
+     * @return the monitor, or null if none is active
+     */
+    public ThreadEfficiencyMonitor getThreadEfficiencyMonitor() {
+        return threadEfficiencyMonitor;
+    }
+
+    // -------------------------------------------------------------------------------------
+    //
+    // code for working with Samples database
+    //
+    // -------------------------------------------------------------------------------------
+
+    public SampleDB getSampleDB() {
+        return this.sampleDB;
+    }
+
+    public Map<String,String> getApproximateCommandLineArguments(Object... argumentProviders) {
+        return CommandLineUtils.getApproximateCommandLineArguments(parsingEngine,argumentProviders);
+    }
+
+    public String createApproximateCommandLineArgumentString(Object... argumentProviders) {
+        return CommandLineUtils.createApproximateCommandLineArgumentString(parsingEngine,argumentProviders);
+    }
+
+    // -------------------------------------------------------------------------------------
+    //
+    // code for working with progress meter
+    //
+    // -------------------------------------------------------------------------------------
+
+    /**
+     * Register the global progress meter with this engine
+     *
+     * Calling this function more than once will result in an IllegalStateException
+     *
+     * @param meter a non-null progress meter
+     */
+    public void registerProgressMeter(final ProgressMeter meter) {
+        if ( meter == null ) throw new IllegalArgumentException("Meter cannot be null");
+        if ( progressMeter != null ) throw new IllegalStateException("Progress meter already set");
+
+        progressMeter = meter;
+    }
+
+    /**
+     * Get the progress meter being used by this engine.  May be null if no meter has been registered yet
+     * @return a potentially null pointer to the progress meter
+     */
+    public ProgressMeter getProgressMeter() {
+        return progressMeter;
+    }
+
+    /**
+     * Does the current runtime in unit exceed the runtime limit, if one has been provided?
+     *
+     * @return false if not limit was requested or if runtime <= the limit, true otherwise
+     */
+    public boolean exceedsRuntimeLimit() {
+        if ( progressMeter == null )
+            // not yet initialized or not set because of testing
+            return false;
+
+        if ( getArguments().maxRuntime == NO_RUNTIME_LIMIT )
+            return false;
+        else {  
+            final long runtime = progressMeter.getRuntimeInNanosecondsUpdatedPeriodically();
+            if ( runtime < 0 ) throw new IllegalArgumentException("runtime must be >= 0 but got " + runtime);
+            final long maxRuntimeNano = getRuntimeLimitInNanoseconds();
+            return runtime > maxRuntimeNano;
+        }
+    }
+
+    /**
+     * @return the runtime limit in nanoseconds, or -1 if no limit was specified
+     */
+    public long getRuntimeLimitInNanoseconds() {
+        return runtimeLimitInNanoseconds;
+    }
+
+    /**
+     * Setup the runtime limits for this engine, updating the runtimeLimitInNanoseconds
+     * as appropriate
+     *
+     * @param args the GATKArgumentCollection to retrieve our runtime limits from
+     */
+    private void setupRuntimeLimits(final GATKArgumentCollection args) {
+        if ( args.maxRuntime == NO_RUNTIME_LIMIT )
+            runtimeLimitInNanoseconds = -1;
+        else if (args.maxRuntime < 0 )
+            throw new UserException.BadArgumentValue("maxRuntime", "must be >= 0 or == -1 (meaning no limit) but received negative value " + args.maxRuntime);
+        else {
+            runtimeLimitInNanoseconds = TimeUnit.NANOSECONDS.convert(args.maxRuntime, args.maxRuntimeUnits);
+        }
+    }
+
+    /**
+     * Returns the sample list including all samples.
+     * @return never {@code null}.
+     */
+    public SampleList getSampleList() {
+        return new IndexedSampleList(getSampleDB().getSampleNames());
+    }
+
+    /**
+     * Returns the sample list including samples in read inputs.
+     * @return never {@code null}.
+     */
+    public SampleList getReadSampleList() {
+        return new IndexedSampleList(SampleUtils.getSAMFileSamples(getSAMFileHeader()));
+    }
+}
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/ReadProperties.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/ReadProperties.java
new file mode 100644
index 0000000..6ee9ad3
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/ReadProperties.java
@@ -0,0 +1,198 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.engine;
+
+import htsjdk.samtools.SAMFileHeader;
+import htsjdk.samtools.SAMFileReader;
+import htsjdk.samtools.ValidationStringency;
+import org.broadinstitute.gatk.engine.arguments.ValidationExclusion;
+import org.broadinstitute.gatk.engine.datasources.reads.SAMReaderID;
+import org.broadinstitute.gatk.engine.downsampling.DownsamplingMethod;
+import org.broadinstitute.gatk.engine.filters.ReadFilter;
+import org.broadinstitute.gatk.engine.iterators.ReadTransformer;
+
+import java.util.Collection;
+import java.util.List;
+/**
+ * User: hanna
+ * Date: May 14, 2009
+ * Time: 4:06:26 PM
+ * BROAD INSTITUTE SOFTWARE COPYRIGHT NOTICE AND AGREEMENT
+ * Software and documentation are copyright 2005 by the Broad Institute.
+ * All rights are reserved.
+ *
+ * Users acknowledge that this software is supplied without any warranty or support.
+ * The Broad Institute is not responsible for its use, misuse, or
+ * functionality.
+ */
+
+/**
+ * A data structure containing information about the reads data sources as well as
+ * information about how they should be downsampled, sorted, and filtered.
+ */
+public class ReadProperties {
+    private final Collection<SAMReaderID> readers;
+    private final SAMFileHeader header;
+    private final SAMFileHeader.SortOrder sortOrder;
+    private final ValidationStringency validationStringency;
+    private final DownsamplingMethod downsamplingMethod;
+    private final ValidationExclusion exclusionList;
+    private final Collection<ReadFilter> supplementalFilters;
+    private final List<ReadTransformer> readTransformers;
+    private final boolean keepUniqueReadListInLIBS;
+    private final boolean includeReadsWithDeletionAtLoci;
+    private final boolean useOriginalBaseQualities;
+    private final byte defaultBaseQualities;
+
+    /**
+     * Return true if the walker wants to see reads that contain deletions when looking at locus pileups
+     * 
+     * @return
+     */
+    public boolean includeReadsWithDeletionAtLoci() {
+        return includeReadsWithDeletionAtLoci;
+    }
+
+    public boolean keepUniqueReadListInLIBS() {
+        return keepUniqueReadListInLIBS;
+    }
+
+    /**
+     * Gets a list of the files acting as sources of reads.
+     * @return A list of files storing reads data.
+     */
+    public Collection<SAMReaderID> getSAMReaderIDs() {
+        return readers;
+    }
+
+    /**
+     * Gets the sam file header
+     * @return the sam file header
+     */
+    public SAMFileHeader getHeader() {
+        return header;
+    }
+
+    /**
+     * Gets the sort order of the reads
+     * @return the sort order of the reads
+     */
+    public SAMFileHeader.SortOrder getSortOrder() {
+        return sortOrder;
+    }
+
+    /**
+     * How strict should validation be?
+     * @return Stringency of validation.
+     */
+    public ValidationStringency getValidationStringency() {
+        return validationStringency;
+    }
+
+    /**
+     * Gets the method and parameters used when downsampling reads.
+     * @return Downsample fraction.
+     */
+    public DownsamplingMethod getDownsamplingMethod() {
+        return downsamplingMethod;
+    }
+
+    /**
+     * Return whether to 'verify' the reads as we pass through them.
+     * @return Whether to verify the reads.
+     */
+    public ValidationExclusion getValidationExclusionList() {
+        return exclusionList;
+    }
+
+    public Collection<ReadFilter> getSupplementalFilters() {
+        return supplementalFilters;
+    }
+
+
+    public List<ReadTransformer> getReadTransformers() {
+        return readTransformers;
+    }
+
+    /**
+     * Return whether to use original base qualities.
+     * @return Whether to use original base qualities.
+     */
+    public boolean useOriginalBaseQualities() {
+        return useOriginalBaseQualities;
+    }
+
+    /**
+     * @return Default base quality value to fill reads missing base quality information.
+     */
+    public byte defaultBaseQualities() {
+        return defaultBaseQualities;
+    }
+
+    /**
+     * Extract the command-line arguments having to do with reads input
+     * files and store them in an easy-to-work-with package.  Constructor
+     * is package protected.
+     * @param samFiles list of reads files.
+     * @param header sam file header.
+     * @param useOriginalBaseQualities True if original base qualities should be used.
+     * @param strictness Stringency of reads file parsing.
+     * @param downsamplingMethod Method for downsampling reads at a given locus.
+     * @param exclusionList what safety checks we're willing to let slide
+     * @param supplementalFilters additional filters to dynamically apply.
+     * @param includeReadsWithDeletionAtLoci if 'true', the base pileups sent to the walker's map() method
+     *         will explicitly list reads with deletion over the current reference base; otherwise, only observed
+     *        bases will be seen in the pileups, and the deletions will be skipped silently.
+     * @param defaultBaseQualities if the reads have incomplete quality scores, set them all to defaultBaseQuality.
+     * @param keepUniqueReadListInLIBS If true, we will tell LocusIteratorByState to track the unique reads it sees
+     *                                 This is really useful for ActiveRegionTraversals
+     */
+    public ReadProperties( Collection<SAMReaderID> samFiles,
+           SAMFileHeader header,
+           SAMFileHeader.SortOrder sortOrder,
+           boolean useOriginalBaseQualities,
+           ValidationStringency strictness,
+           DownsamplingMethod downsamplingMethod,
+           ValidationExclusion exclusionList,
+           Collection<ReadFilter> supplementalFilters,
+           List<ReadTransformer> readTransformers,
+           boolean includeReadsWithDeletionAtLoci,
+           byte defaultBaseQualities,
+           final boolean keepUniqueReadListInLIBS) {
+        this.readers = samFiles;
+        this.header = header;
+        this.sortOrder = sortOrder;
+        this.validationStringency = strictness;
+        this.downsamplingMethod = downsamplingMethod == null ? DownsamplingMethod.NONE : downsamplingMethod;
+        this.exclusionList = exclusionList == null ? new ValidationExclusion() : exclusionList;
+        this.supplementalFilters = supplementalFilters;
+        this.readTransformers = readTransformers;
+        this.includeReadsWithDeletionAtLoci = includeReadsWithDeletionAtLoci;
+        this.useOriginalBaseQualities = useOriginalBaseQualities;
+        this.defaultBaseQualities = defaultBaseQualities;
+        this.keepUniqueReadListInLIBS = keepUniqueReadListInLIBS;
+    }
+}
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/WalkerManager.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/WalkerManager.java
new file mode 100644
index 0000000..fb9d489
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/WalkerManager.java
@@ -0,0 +1,431 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.engine;
+
+import org.broadinstitute.gatk.engine.walkers.*;
+import org.broadinstitute.gatk.utils.commandline.Hidden;
+import org.broadinstitute.gatk.engine.datasources.rmd.ReferenceOrderedDataSource;
+import org.broadinstitute.gatk.engine.downsampling.DownsampleType;
+import org.broadinstitute.gatk.engine.downsampling.DownsamplingMethod;
+import org.broadinstitute.gatk.engine.filters.FilterManager;
+import org.broadinstitute.gatk.engine.filters.ReadFilter;
+import org.broadinstitute.gatk.engine.iterators.ReadTransformer;
+import org.broadinstitute.gatk.utils.classloader.PluginManager;
+import org.broadinstitute.gatk.utils.exceptions.ReviewedGATKException;
+import org.broadinstitute.gatk.utils.help.ResourceBundleExtractorDoclet;
+import org.broadinstitute.gatk.utils.text.TextFormattingUtils;
+
+import java.lang.annotation.Annotation;
+import java.util.*;
+
+/**
+ * Plugin manager that also provides various utilities for inspecting Walkers.
+ */
+public class WalkerManager extends PluginManager<Walker> {
+
+    /**
+     * A collection of help text for walkers and their enclosing packages.
+     */
+    private ResourceBundle helpText;
+
+    public WalkerManager() {
+        super(Walker.class,"walker","");
+        helpText = TextFormattingUtils.loadResourceBundle("GATKText");
+    }
+
+    /**
+     * Get the list of walkers currently available to the GATK, organized
+     * by package.
+     * @param visibleWalkersOnly If true, return only the walker names that aren't hidden.
+     * @return Names of currently available walkers.
+     */
+    public Map<String,Collection<Class<? extends Walker>>> getWalkerNamesByPackage(boolean visibleWalkersOnly) {
+        Map<String,Collection<Class<? extends Walker>>> walkersByPackage = new HashMap<String,Collection<Class<? extends Walker>>>();
+        for(Class<? extends Walker> walker: getPlugins()) {
+            if(visibleWalkersOnly && isHidden(walker))
+                continue;
+
+            // Extract the name for the package; if the walker is in the unnamed package, use the empty string
+            String walkerPackage = walker.getPackage() != null ? walker.getPackage().getName() : "";
+            if(!walkersByPackage.containsKey(walkerPackage))
+                walkersByPackage.put(walkerPackage,new ArrayList<Class<? extends Walker>>());
+            walkersByPackage.get(walkerPackage).add(walker);
+        }
+        return Collections.unmodifiableMap(walkersByPackage);
+    }
+
+    /**
+     * Gets the display name for a given package.
+     * @param packageName Fully qualified package name.
+     * @return A suitable display name for the package.
+     */
+    public String getPackageDisplayName(String packageName) {
+        // ...try to compute the override from the text of the package name, while accounting for
+        // unpackaged walkers.
+        String displayName = packageName.substring(packageName.lastIndexOf('.')+1);
+        if (displayName.trim().equals("")) displayName = "<unpackaged>";
+        return displayName;
+    }
+
+    /**
+     * Gets the help text associated with a given package name.
+     * @param packageName Package for which to search for help text.
+     * @return Package help text, or "" if none exists.
+     */
+    public String getPackageSummaryText(String packageName) {
+        String key = String.format("%s.%s",packageName, ResourceBundleExtractorDoclet.SUMMARY_TAGLET_NAME);
+        if(!helpText.containsKey(key))
+            return "";
+        return helpText.getString(key);
+    }
+
+    /**
+     * Gets the summary help text associated with a given walker type.
+     * @param walkerType Type of walker for which to search for help text.
+     * @return Walker summary description, or "" if none exists.
+     */
+    public String getWalkerSummaryText(Class<? extends Walker> walkerType) {
+        String walkerSummary = String.format("%s.%s",walkerType.getName(), ResourceBundleExtractorDoclet.SUMMARY_TAGLET_NAME);
+        if(!helpText.containsKey(walkerSummary))
+            return "";
+        return helpText.getString(walkerSummary);
+    }
+
+    /**
+     * Gets the summary help text associated with a given walker type.
+     * @param walker Walker for which to search for help text.
+     * @return Walker summary description, or "" if none exists.
+     */
+    public String getWalkerSummaryText(Walker walker) {
+        return getWalkerSummaryText(walker.getClass());
+    }
+
+    /**
+     * Gets the descriptive help text associated with a given walker type.
+     * @param walkerType Type of walker for which to search for help text.
+     * @return Walker full description, or "" if none exists.
+     */
+    public String getWalkerDescriptionText(Class<? extends Walker> walkerType) {
+        String walkerDescription = String.format("%s.%s",walkerType.getName(), ResourceBundleExtractorDoclet.DESCRIPTION_TAGLET_NAME);
+        if(!helpText.containsKey(walkerDescription))
+            return "";
+        return helpText.getString(walkerDescription);
+    }
+
+    /**
+     * Gets the descriptive help text associated with a given walker type.
+     * @param walker Walker for which to search for help text.
+     * @return Walker full description, or "" if none exists.
+     */
+    public String getWalkerDescriptionText(Walker walker) {
+        return getWalkerDescriptionText(walker.getClass());
+    }
+
+    /**
+     * Retrieves the walker class given a walker name.
+     * @param walkerName Name of the walker.
+     * @return Class representing the walker.
+     */
+    public Class<? extends Walker> getWalkerClassByName(String walkerName) {
+        return getPluginsByName().get(walkerName);
+    }
+
+    /**
+     * Gets the data source for the provided walker.
+     * @param walkerClass The class of the walker.
+     * @return Which type of data source to traverse over...reads or reference?
+     */
+    public static DataSource getWalkerDataSource(Class<? extends Walker> walkerClass) {
+        By byDataSource = walkerClass.getAnnotation(By.class);
+        if( byDataSource == null )
+            throw new ReviewedGATKException("Unable to find By annotation for walker class " + walkerClass.getName());
+        return byDataSource.value();
+    }
+
+    /**
+     * Gets the data source for the provided walker.
+     * @param walker The walker.
+     * @return Which type of data source to traverse over...reads or reference?
+     */
+    public static DataSource getWalkerDataSource(Walker walker) {
+        return getWalkerDataSource(walker.getClass());
+    }
+
+    /**
+     * Get a list of RODs allowed by the walker.
+     * @param walkerClass Class of the walker to query.
+     * @return The list of allowed reference meta data.
+     */
+    public static List<RMD> getAllowsMetaData(Class<? extends Walker> walkerClass) {
+        return Collections.<RMD>emptyList();
+    }
+
+    /**
+     * Determine whether the given walker supports the given data source.
+     * @param walkerClass Class of the walker to query.
+     * @param dataSource Source to check for .
+     * @return True if the walker forbids this data type.  False otherwise.
+     */
+    public static boolean isAllowed(Class<? extends Walker> walkerClass, DataSource dataSource) {
+        Allows allowsDataSource = getWalkerAllowed(walkerClass);
+
+        // Allows is less restrictive than requires.  If an allows
+        // clause is not specified, any kind of data is allowed.
+        if( allowsDataSource == null )
+            return true;
+
+        return Arrays.asList(allowsDataSource.value()).contains(dataSource);
+    }
+
+    /**
+     * Determine whether the given walker supports the given data source.
+     * @param walker Walker to query.
+     * @param dataSource Source to check for .
+     * @return True if the walker forbids this data type.  False otherwise.
+     */
+    public static boolean isAllowed(Walker walker, DataSource dataSource) {
+        return isAllowed(walker.getClass(), dataSource);
+    }
+
+    /**
+     * Determine whether the given walker supports the given reference ordered data.
+     * @param walkerClass Class of the walker to query.
+     * @param rod Source to check.
+     * @return True if the walker forbids this data type.  False otherwise.
+     */
+    public static boolean isAllowed(Class<? extends Walker> walkerClass, ReferenceOrderedDataSource rod) {
+        return true;
+    }
+
+    /**
+     * Determine whether the given walker supports the given reference ordered data.
+     * @param walker Walker to query.
+     * @param rod Source to check.
+     * @return True if the walker forbids this data type.  False otherwise.
+     */
+    public static boolean isAllowed(Walker walker, ReferenceOrderedDataSource rod) {
+        return isAllowed(walker.getClass(), rod);
+    }
+
+    /**
+     * Determine whether the given walker requires the given data source.
+     * @param walkerClass Class of the walker to query.
+     * @param dataSource Source to check for.
+     * @return True if the walker allows this data type.  False otherwise.
+     */
+    public static boolean isRequired(Class<? extends Walker> walkerClass, DataSource dataSource) {
+        Requires requiresDataSource = getWalkerRequirements(walkerClass);
+        return Arrays.asList(requiresDataSource.value()).contains(dataSource);
+    }
+
+    /**
+     * Determine whether the given walker requires the given data source.
+     * @param walker Walker to query.
+     * @param dataSource Source to check for.
+     * @return True if the walker allows this data type.  False otherwise.
+     */
+    public static boolean isRequired(Walker walker, DataSource dataSource) {
+        return isRequired(walker.getClass(), dataSource);
+    }
+
+    /**
+     * Get a list of RODs required by the walker.
+     * @param walkerClass Class of the walker to query.
+     * @return The list of required reference meta data.
+     */
+    public static List<RMD> getRequiredMetaData(Class<? extends Walker> walkerClass) {
+        return Collections.emptyList();
+    }
+
+    /**
+     * Get a list of RODs required by the walker.
+     * @param walker Walker to query.
+     * @return The list of required reference meta data.
+     */
+    public static List<RMD> getRequiredMetaData(Walker walker) {
+        return getRequiredMetaData(walker.getClass());
+    }
+
+    /**
+     * Reports whether this walker type is hidden -- in other words, whether it'll appear in the help output.
+     * @param walkerType Class to test for visibility.
+     * @return True if the walker should be hidden.  False otherwise.
+     */
+    public static boolean isHidden(Class<? extends Walker> walkerType) {
+        return walkerType.isAnnotationPresent(Hidden.class);    
+    }
+
+    /**
+     * Extracts filters that the walker has requested be run on the dataset.
+     * @param walkerClass Class of the walker to inspect for filtering requests.
+     * @param filterManager Manages the creation of filters.
+     * @return A non-empty list of filters to apply to the reads.
+     */
+    public static List<ReadFilter> getReadFilters(Class<? extends Walker> walkerClass, FilterManager filterManager) {
+        List<ReadFilter> filters = new ArrayList<ReadFilter>();
+        for(Class<? extends ReadFilter> filterType: getReadFilterTypes(walkerClass))
+            filters.add(filterManager.createFilterByType(filterType));
+        return filters;
+    }
+
+    /**
+     * Extracts filters that the walker has requested be run on the dataset.
+     * @param walker Walker to inspect for filtering requests.
+     * @param filterManager Manages the creation of filters.
+     * @return A non-empty list of filters to apply to the reads.
+     */
+    public static List<ReadFilter> getReadFilters(Walker walker, FilterManager filterManager) {
+        return getReadFilters(walker.getClass(), filterManager);
+    }
+
+    /**
+     * Gets the type of downsampling method requested by the walker.  If an alternative
+     * downsampling method is specified on the command-line, the command-line version will
+     * be used instead.
+     * @param walker The walker to interrogate.
+     * @return The downsampling method, as specified by the walker.  Null if none exists.
+     */
+    public static DownsamplingMethod getDownsamplingMethod( Walker walker ) {
+        return getDownsamplingMethod(walker.getClass());
+    }
+
+    /**
+     * Gets the type of downsampling method requested by the walker.  If an alternative
+     * downsampling method is specified on the command-line, the command-line version will
+     * be used instead.
+     * @param walkerClass The class of the walker to interrogate.
+     * @return The downsampling method, as specified by the walker.  Null if none exists.
+     */
+    public static DownsamplingMethod getDownsamplingMethod( Class<? extends Walker> walkerClass ) {
+        DownsamplingMethod downsamplingMethod = null;
+
+        if( walkerClass.isAnnotationPresent(Downsample.class) ) {
+            Downsample downsampleParameters = walkerClass.getAnnotation(Downsample.class);
+            DownsampleType type = downsampleParameters.by();
+            Integer toCoverage = downsampleParameters.toCoverage() >= 0 ? downsampleParameters.toCoverage() : null;
+            Double toFraction = downsampleParameters.toFraction() >= 0.0d ? downsampleParameters.toFraction() : null;
+            downsamplingMethod = new DownsamplingMethod(type, toCoverage, toFraction);
+        }
+
+        return downsamplingMethod;
+    }
+
+    public static <T extends Annotation> T getWalkerAnnotation(final Walker walker, final Class<T> clazz) {
+        return walker.getClass().getAnnotation(clazz);
+    }
+
+    public static ReadTransformer.ApplicationTime getBAQApplicationTime(Walker walker) {
+        return walker.getClass().getAnnotation(BAQMode.class).ApplicationTime();
+    }    
+
+    /**
+     * Create a name for this type of walker.
+     *
+     * @param walkerType The type of walker.
+     * @return A name for this type of walker.
+     */
+    @Override
+    public String getName(Class walkerType) {
+        String walkerName = "";
+
+        if (walkerType.getAnnotation(WalkerName.class) != null)
+            walkerName = ((WalkerName)walkerType.getAnnotation(WalkerName.class)).value().trim();
+        else
+            walkerName = super.getName(walkerType);
+
+        return walkerName;
+    }
+
+    /**
+     * Utility to get the requires attribute from the walker.
+     * Throws an exception if requirements are missing.
+     * @param walkerClass Class of the walker to query for required data.
+     * @return Required data attribute.
+     */
+    private static Requires getWalkerRequirements(Class<? extends Walker> walkerClass) {
+        Requires requiresDataSource = walkerClass.getAnnotation(Requires.class);
+        if( requiresDataSource == null )
+            throw new ReviewedGATKException( "Unable to find data types required by walker class " + walkerClass.getName());
+        return requiresDataSource;
+    }
+
+    /**
+     * Utility to get the requires attribute from the walker.
+     * Throws an exception if requirements are missing.
+     * @param walker Walker to query for required data.
+     * @return Required data attribute.
+     */
+    private static Requires getWalkerRequirements(Walker walker) {
+        return getWalkerRequirements(walker.getClass());
+    }
+
+    /**
+     * Utility to get the forbidden attribute from the walker.
+     * @param walkerClass Class of the walker to query for required data.
+     * @return Required data attribute.  Null if forbidden info isn't present.
+     */
+    private static Allows getWalkerAllowed(Class<? extends Walker> walkerClass) {
+        Allows allowsDataSource = walkerClass.getAnnotation(Allows.class);
+        return allowsDataSource;
+    }
+
+    /**
+     * Utility to get the forbidden attribute from the walker.
+     * @param walker Walker to query for required data.
+     * @return Required data attribute.  Null if forbidden info isn't present.
+     */
+    private static Allows getWalkerAllowed(Walker walker) {
+        return getWalkerAllowed(walker.getClass());
+    }
+
+    /**
+     * Gets the list of filtering classes specified as walker annotations.
+     * @param walkerClass Class of the walker to inspect.
+     * @return An array of types extending from SamRecordFilter.  Will never be null.
+     */
+    public static Collection<Class<? extends ReadFilter>> getReadFilterTypes(Class<?> walkerClass) {
+        List<Class<? extends ReadFilter>> filterTypes = new ArrayList<Class<? extends ReadFilter>>();
+        while(walkerClass != null) {
+            if(walkerClass.isAnnotationPresent(ReadFilters.class)) {
+                for ( Class c : walkerClass.getAnnotation(ReadFilters.class).value() ) {
+                    if( !filterTypes.contains(c) )
+                        filterTypes.add(c);
+                }
+            }
+            walkerClass = walkerClass.getSuperclass();
+        }
+        return filterTypes;
+    }
+
+    /**
+     * Gets the list of filtering classes specified as walker annotations.
+     * @param walker The walker to inspect.
+     * @return An array of types extending from SamRecordFilter.  Will never be null.
+     */
+    public static Collection<Class<? extends ReadFilter>> getReadFilterTypes(Walker walker) {
+        return getReadFilterTypes(walker.getClass());
+    }
+}
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/alignment/Aligner.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/alignment/Aligner.java
new file mode 100644
index 0000000..e9622c9
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/alignment/Aligner.java
@@ -0,0 +1,74 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.engine.alignment;
+
+import htsjdk.samtools.SAMFileHeader;
+import htsjdk.samtools.SAMRecord;
+
+/**
+ * Create perfect alignments from the read to the genome represented by the given BWT / suffix array. 
+ *
+ * @author mhanna
+ * @version 0.1
+ */
+public interface Aligner {
+    /**
+     * Close this instance of the BWA pointer and delete its resources.
+     */
+    public void close();    
+
+    /**
+     * Allow the aligner to choose one alignment randomly from the pile of best alignments.
+     * @param bases Bases to align.
+     * @return An align
+     */
+    public Alignment getBestAlignment(final byte[] bases);
+
+    /**
+     * Align the read to the reference.
+     * @param read Read to align.
+     * @param header Optional header to drop in place.
+     * @return A list of the alignments.
+     */
+    public SAMRecord align(final SAMRecord read, final SAMFileHeader header);
+
+    /**
+     * Get a iterator of alignments, batched by mapping quality.
+     * @param bases List of bases.
+     * @return Iterator to alignments.
+     */
+    public Iterable<Alignment[]> getAllAlignments(final byte[] bases);
+
+    /**
+     * Get a iterator of aligned reads, batched by mapping quality.
+     * @param read Read to align.
+     * @param newHeader Optional new header to use when aligning the read.  If present, it must be null.
+     * @return Iterator to alignments.
+     */
+    public Iterable<SAMRecord[]> alignAll(final SAMRecord read, final SAMFileHeader newHeader);
+}
+
+
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/alignment/Alignment.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/alignment/Alignment.java
new file mode 100644
index 0000000..02bc06f
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/alignment/Alignment.java
@@ -0,0 +1,246 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.engine.alignment;
+
+import htsjdk.samtools.*;
+import org.broadinstitute.gatk.utils.BaseUtils;
+import org.broadinstitute.gatk.utils.Utils;
+import org.broadinstitute.gatk.utils.exceptions.ReviewedGATKException;
+
+/**
+ * Represents an alignment of a read to a site in the reference genome.
+ *
+ * @author mhanna
+ * @version 0.1
+ */
+public class Alignment {
+    protected int contigIndex;
+    protected long alignmentStart;
+    protected boolean negativeStrand;
+    protected int mappingQuality;
+
+    protected char[] cigarOperators;
+    protected int[] cigarLengths;
+
+    protected int editDistance;
+    protected String mismatchingPositions;
+
+    protected int numMismatches;
+    protected int numGapOpens;
+    protected int numGapExtensions;
+    protected int bestCount;
+    protected int secondBestCount;
+
+    /**
+     * Gets the index of the given contig.
+     * @return the inde
+     */
+    public int getContigIndex() { return contigIndex; }
+
+    /**
+     * Gets the starting position for the given alignment.
+     * @return Starting position.
+     */
+    public long getAlignmentStart() { return alignmentStart; }
+
+    /**
+     * Is the given alignment on the reverse strand?
+     * @return True if the alignment is on the reverse strand.
+     */
+    public boolean isNegativeStrand() { return negativeStrand; }
+
+    /**
+     * Gets the score of this alignment.
+     * @return The score.
+     */
+    public int getMappingQuality() { return mappingQuality; }
+
+    /**
+     * Gets the edit distance; will eventually end up in the NM SAM tag
+     * if this alignment makes it that far.
+     * @return The edit distance.
+     */
+    public int getEditDistance() { return editDistance; }
+
+    /**
+     * A string representation of which positions mismatch; contents of MD tag.
+     * @return String representation of mismatching positions.
+     */
+    public String getMismatchingPositions() { return mismatchingPositions; }
+    
+    /**
+     * Gets the number of mismatches in the read.
+     * @return Number of mismatches.
+     */
+    public int getNumMismatches() { return numMismatches; }
+
+    /**
+     * Get the number of gap opens.
+     * @return Number of gap opens.
+     */
+    public int getNumGapOpens() { return numGapOpens; }
+
+    /**
+     * Get the number of gap extensions.
+     * @return Number of gap extensions.
+     */
+    public int getNumGapExtensions() { return numGapExtensions; }
+
+    /**
+     * Get the number of best alignments.
+     * @return Number of top scoring alignments.
+     */
+    public int getBestCount() { return bestCount; }
+
+    /**
+     * Get the number of second best alignments.
+     * @return Number of second best scoring alignments.
+     */
+    public int getSecondBestCount() { return secondBestCount; }
+
+    /**
+     * Gets the cigar for this alignment.
+     * @return sam-jdk formatted alignment.
+     */
+    public Cigar getCigar() {
+        Cigar cigar = new Cigar();
+        for(int i = 0; i < cigarOperators.length; i++) {
+            CigarOperator operator = CigarOperator.characterToEnum(cigarOperators[i]);
+            cigar.add(new CigarElement(cigarLengths[i],operator));
+        }
+        return cigar;
+    }
+
+    /**
+     * Temporarily implement getCigarString() for debugging; the TextCigarCodec is unfortunately
+     * package-protected.
+     * @return
+     */
+    public String getCigarString() {
+        Cigar cigar = getCigar();
+        if(cigar.isEmpty()) return "*";
+
+        StringBuilder cigarString = new StringBuilder();
+        for(CigarElement element: cigar.getCigarElements()) {
+            cigarString.append(element.getLength());
+            cigarString.append(element.getOperator());
+        }
+        return cigarString.toString();
+    }
+
+    /**
+     * Stub for inheritance.
+     */
+    public Alignment() {}    
+
+    /**
+     * Create a new alignment object.
+     * @param contigIndex The contig to which this read aligned.
+     * @param alignmentStart The point within the contig to which this read aligned.
+     * @param negativeStrand Forward or reverse alignment of the given read.
+     * @param mappingQuality How good does BWA think this mapping is?
+     * @param cigarOperators The ordered operators in the cigar string.
+     * @param cigarLengths The lengths to which each operator applies.
+     * @param editDistance The edit distance (cumulative) of the read.
+     * @param mismatchingPositions String representation of which bases in the read mismatch.
+     * @param numMismatches Number of total mismatches in the read.
+     * @param numGapOpens Number of gap opens in the read.
+     * @param numGapExtensions Number of gap extensions in the read.
+     * @param bestCount Number of best alignments in the read.
+     * @param secondBestCount Number of second best alignments in the read.
+     */
+    public Alignment(int contigIndex,
+                     int alignmentStart,
+                     boolean negativeStrand,
+                     int mappingQuality,
+                     char[] cigarOperators,
+                     int[] cigarLengths,
+                     int editDistance,
+                     String mismatchingPositions,
+                     int numMismatches,
+                     int numGapOpens,
+                     int numGapExtensions,
+                     int bestCount,
+                     int secondBestCount) {
+        this.contigIndex = contigIndex;
+        this.alignmentStart = alignmentStart;
+        this.negativeStrand = negativeStrand;
+        this.mappingQuality = mappingQuality;
+        this.cigarOperators = cigarOperators;
+        this.cigarLengths = cigarLengths;
+        this.editDistance = editDistance;
+        this.mismatchingPositions = mismatchingPositions;
+        this.numMismatches = numMismatches;
+        this.numGapOpens = numGapOpens;
+        this.numGapExtensions = numGapExtensions;
+        this.bestCount = bestCount;
+        this.secondBestCount = secondBestCount;
+    }
+
+    /**
+     * Creates a read directly from an alignment.
+     * @param alignment The alignment to convert to a read.
+     * @param unmappedRead Source of the unmapped read.  Should have bases, quality scores, and flags.
+     * @param newSAMHeader The new SAM header to use in creating this read.  Can be null, but if so, the sequence
+     *                     dictionary in the
+     * @return A mapped alignment.
+     */
+    public static SAMRecord convertToRead(Alignment alignment, SAMRecord unmappedRead, SAMFileHeader newSAMHeader) {
+        SAMRecord read;
+        try {
+            read = (SAMRecord)unmappedRead.clone();
+        }
+        catch(CloneNotSupportedException ex) {
+            throw new ReviewedGATKException("Unable to create aligned read from template.");
+        }
+
+        if(newSAMHeader != null)
+            read.setHeader(newSAMHeader);
+
+        // If we're realigning a previously aligned record, strip out the placement of the alignment.
+        read.setReferenceName(SAMRecord.NO_ALIGNMENT_REFERENCE_NAME);
+        read.setAlignmentStart(SAMRecord.NO_ALIGNMENT_START);
+        read.setMateReferenceName(SAMRecord.NO_ALIGNMENT_REFERENCE_NAME);
+        read.setMateAlignmentStart(SAMRecord.NO_ALIGNMENT_START);        
+
+        if(alignment != null) {
+            read.setReadUnmappedFlag(false);
+            read.setReferenceIndex(alignment.getContigIndex());
+            read.setAlignmentStart((int)alignment.getAlignmentStart());
+            read.setReadNegativeStrandFlag(alignment.isNegativeStrand());
+            read.setMappingQuality(alignment.getMappingQuality());
+            read.setCigar(alignment.getCigar());
+            if(alignment.isNegativeStrand()) {
+                read.setReadBases(BaseUtils.simpleReverseComplement(read.getReadBases()));
+                read.setBaseQualities(Utils.reverse(read.getBaseQualities()));
+            }
+            read.setAttribute("NM",alignment.getEditDistance());
+            read.setAttribute("MD",alignment.getMismatchingPositions());
+        }
+
+        return read;
+    }    
+}
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/alignment/bwa/BWAAligner.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/alignment/bwa/BWAAligner.java
new file mode 100644
index 0000000..2668b8c
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/alignment/bwa/BWAAligner.java
@@ -0,0 +1,63 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.engine.alignment.bwa;
+
+import org.broadinstitute.gatk.engine.alignment.Aligner;
+
+/**
+ * Align reads using BWA.
+ *
+ * @author mhanna
+ * @version 0.1
+ */
+public abstract class BWAAligner implements Aligner {
+    /**
+     * The supporting files used by BWA.
+     */
+    protected BWTFiles bwtFiles;
+
+    /**
+     * The current configuration for the BWA aligner.
+     */
+    protected BWAConfiguration configuration;
+
+    /**
+     * Create a new BWAAligner.  Purpose of this call is to ensure that all BWA constructors accept the correct
+     * parameters.
+     * @param bwtFiles The many files representing BWTs persisted to disk.
+     * @param configuration Configuration parameters for the alignment.
+     */
+    public BWAAligner(BWTFiles bwtFiles, BWAConfiguration configuration) {
+        this.bwtFiles = bwtFiles;
+        this.configuration = configuration;
+    }
+
+    /**
+     * Update the configuration passed to the BWA aligner.
+     * @param configuration New configuration to set.
+     */    
+    public abstract void updateConfiguration(BWAConfiguration configuration);
+}
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/alignment/bwa/BWAConfiguration.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/alignment/bwa/BWAConfiguration.java
new file mode 100644
index 0000000..b533a0d
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/alignment/bwa/BWAConfiguration.java
@@ -0,0 +1,79 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.engine.alignment.bwa;
+
+/**
+ * Configuration for the BWA/C aligner.
+ *
+ * @author mhanna
+ * @version 0.1
+ */
+public class BWAConfiguration {
+    /**
+     * The maximum edit distance used by BWA.
+     */
+    public Float maximumEditDistance = null;
+
+    /**
+     * How many gap opens are acceptable within this alignment?
+     */
+    public Integer maximumGapOpens = null;
+
+    /**
+     * How many gap extensions are acceptable within this alignment?
+     */
+    public Integer maximumGapExtensions = null;
+
+    /**
+     * Do we disallow indels within a certain range from the start / end?
+     */
+    public Integer disallowIndelWithinRange = null;
+
+    /**
+     * What is the scoring penalty for a mismatch?
+     */
+    public Integer mismatchPenalty = null;
+
+    /**
+     * What is the scoring penalty for a gap open?
+     */
+    public Integer gapOpenPenalty = null;
+
+    /**
+     * What is the scoring penalty for a gap extension?
+     */
+    public Integer gapExtensionPenalty = null;
+
+    /**
+     * Enter bwa's 'non-stop' mode (equivalent to bwa aln -N parameter).
+     */
+    public Boolean nonStopMode = false;
+
+    /**
+     * Set the max queue size that bwa will use when searching for matches (equivalent to bwa aln -m parameter).
+     */
+    public Integer maxEntriesInQueue = null;
+}
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/alignment/bwa/BWTFiles.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/alignment/bwa/BWTFiles.java
new file mode 100644
index 0000000..16cc4ad
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/alignment/bwa/BWTFiles.java
@@ -0,0 +1,259 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.engine.alignment.bwa;
+
+import htsjdk.samtools.SAMSequenceDictionary;
+import htsjdk.samtools.SAMSequenceRecord;
+import htsjdk.samtools.util.StringUtil;
+import org.broadinstitute.gatk.engine.alignment.reference.bwt.*;
+import org.broadinstitute.gatk.engine.alignment.reference.packing.PackUtils;
+import org.broadinstitute.gatk.utils.Utils;
+import org.broadinstitute.gatk.utils.exceptions.ReviewedGATKException;
+
+import java.io.File;
+import java.io.IOException;
+
+/**
+ * Support files for BWT.
+ *
+ * @author mhanna
+ * @version 0.1
+ */
+public class BWTFiles {
+    /**
+     * ANN (?) file name.
+     */
+    public final File annFile;
+
+    /**
+     * AMB (?) file name.
+     */
+    public final File ambFile;
+
+    /**
+     * Packed reference sequence file.
+     */
+    public final File pacFile;
+
+    /**
+     * Reverse of packed reference sequence file.
+     */
+    public final File rpacFile;
+
+    /**
+     * Forward BWT file.
+     */
+    public final File forwardBWTFile;
+
+    /**
+     * Forward suffix array file.
+     */
+    public final File forwardSAFile;
+
+    /**
+     * Reverse BWT file.
+     */
+    public final File reverseBWTFile;
+
+    /**
+     * Reverse suffix array file.
+     */
+    public final File reverseSAFile;
+
+    /**
+     * Where these files autogenerated on the fly?
+     */
+    public final boolean autogenerated;
+
+    /**
+     * Create a new BWA configuration file using the given prefix.
+     * @param prefix Prefix to use when creating the configuration.  Must not be null.
+     */
+    public BWTFiles(String prefix) {
+        if(prefix == null)
+            throw new ReviewedGATKException("Prefix must not be null.");
+        annFile = new File(prefix + ".ann");
+        ambFile = new File(prefix + ".amb");
+        pacFile = new File(prefix + ".pac");
+        rpacFile = new File(prefix + ".rpac");
+        forwardBWTFile = new File(prefix + ".bwt");
+        forwardSAFile = new File(prefix + ".sa");
+        reverseBWTFile = new File(prefix + ".rbwt");
+        reverseSAFile = new File(prefix + ".rsa");
+        autogenerated = false;
+    }
+
+    /**
+     * Hand-create a new BWTFiles object, specifying a unique file object for each type.
+     * @param annFile ANN (alternate dictionary) file.
+     * @param ambFile AMB (holes) files.
+     * @param pacFile Packed representation of the forward reference sequence.
+     * @param forwardBWTFile BWT representation of the forward reference sequence.
+     * @param forwardSAFile SA representation of the forward reference sequence.
+     * @param rpacFile Packed representation of the reversed reference sequence.
+     * @param reverseBWTFile BWT representation of the reversed reference sequence.
+     * @param reverseSAFile SA representation of the reversed reference sequence.
+     */
+    private BWTFiles(File annFile,
+                     File ambFile,
+                     File pacFile,
+                     File forwardBWTFile,
+                     File forwardSAFile,
+                     File rpacFile,
+                     File reverseBWTFile,
+                     File reverseSAFile) {
+        this.annFile = annFile;
+        this.ambFile = ambFile;
+        this.pacFile = pacFile;
+        this.forwardBWTFile = forwardBWTFile;
+        this.forwardSAFile = forwardSAFile;
+        this.rpacFile = rpacFile;
+        this.reverseBWTFile = reverseBWTFile;
+        this.reverseSAFile = reverseSAFile;        
+        autogenerated = true;
+    }
+
+    /**
+     * Close out this files object, in the process deleting any temporary filse
+     * that were created.
+     */
+    public void close() {
+        if(autogenerated) {
+            boolean success = true;
+            success = annFile.delete();
+            success &= ambFile.delete();
+            success &= pacFile.delete();
+            success &= forwardBWTFile.delete();
+            success &= forwardSAFile.delete();
+            success &= rpacFile.delete();
+            success &= reverseBWTFile.delete();
+            success &= reverseSAFile.delete();
+
+            if(!success)
+                throw new ReviewedGATKException("Unable to clean up autogenerated representation");
+        }
+    }
+
+    /**
+     * Create a new set of BWT files from the given reference sequence.
+     * @param referenceSequence Sequence from which to build metadata.
+     * @return A new object representing encoded representations of each sequence.
+     */
+    public static BWTFiles createFromReferenceSequence(byte[] referenceSequence) {
+        byte[] normalizedReferenceSequence = new byte[referenceSequence.length];
+        System.arraycopy(referenceSequence,0,normalizedReferenceSequence,0,referenceSequence.length);
+        normalizeReferenceSequence(normalizedReferenceSequence);        
+
+        File annFile,ambFile,pacFile,bwtFile,saFile,rpacFile,rbwtFile,rsaFile;
+        try {
+            // Write the ann and amb for this reference sequence.
+            annFile = File.createTempFile("bwt",".ann");
+            ambFile = File.createTempFile("bwt",".amb");
+
+            SAMSequenceDictionary dictionary = new SAMSequenceDictionary();
+            dictionary.addSequence(new SAMSequenceRecord("autogenerated",normalizedReferenceSequence.length));
+
+            ANNWriter annWriter = new ANNWriter(annFile);
+            annWriter.write(dictionary);
+            annWriter.close();
+
+            AMBWriter ambWriter = new AMBWriter(ambFile);
+            ambWriter.writeEmpty(dictionary);
+            ambWriter.close();
+
+            // Write the encoded files for the forward version of this reference sequence.
+            pacFile = File.createTempFile("bwt",".pac");
+            bwtFile = File.createTempFile("bwt",".bwt");
+            saFile = File.createTempFile("bwt",".sa");
+
+            writeEncodedReferenceSequence(normalizedReferenceSequence,pacFile,bwtFile,saFile);
+
+            // Write the encoded files for the reverse version of this reference sequence.
+            byte[] reverseReferenceSequence = Utils.reverse(normalizedReferenceSequence);
+
+            rpacFile = File.createTempFile("bwt",".rpac");
+            rbwtFile = File.createTempFile("bwt",".rbwt");
+            rsaFile = File.createTempFile("bwt",".rsa");
+
+            writeEncodedReferenceSequence(reverseReferenceSequence,rpacFile,rbwtFile,rsaFile);
+        }
+        catch(IOException ex) {
+            throw new ReviewedGATKException("Unable to write autogenerated reference sequence to temporary files");
+        }
+
+        // Make sure that, at the very least, all temporary files are deleted on exit.
+        annFile.deleteOnExit();
+        ambFile.deleteOnExit();
+        pacFile.deleteOnExit();
+        bwtFile.deleteOnExit();
+        saFile.deleteOnExit();
+        rpacFile.deleteOnExit();
+        rbwtFile.deleteOnExit();
+        rsaFile.deleteOnExit();
+
+        return new BWTFiles(annFile,ambFile,pacFile,bwtFile,saFile,rpacFile,rbwtFile,rsaFile);
+    }
+
+    /**
+     * Write the encoded form of the reference sequence.  In the case of BWA, the encoded reference
+     * sequence is the reference itself in PAC format, the BWT, and the suffix array.
+     * @param referenceSequence The reference sequence to encode.
+     * @param pacFile Target for the PAC-encoded reference.
+     * @param bwtFile Target for the BWT representation of the reference.
+     * @param suffixArrayFile Target for the suffix array encoding of the reference.
+     * @throws java.io.IOException In case of issues writing to the file.
+     */
+    private static void writeEncodedReferenceSequence(byte[] referenceSequence,
+                                               File pacFile,
+                                               File bwtFile,
+                                               File suffixArrayFile) throws IOException {
+        PackUtils.writeReferenceSequence(pacFile,referenceSequence);
+
+        BWT bwt = BWT.createFromReferenceSequence(referenceSequence);
+        BWTWriter bwtWriter = new BWTWriter(bwtFile);
+        bwtWriter.write(bwt);
+        bwtWriter.close();
+
+        SuffixArray suffixArray = SuffixArray.createFromReferenceSequence(referenceSequence);
+        SuffixArrayWriter suffixArrayWriter = new SuffixArrayWriter(suffixArrayFile);
+        suffixArrayWriter.write(suffixArray);
+        suffixArrayWriter.close();
+    }
+
+    /**
+     * Convert the given reference sequence into a form suitable for building into
+     * on-the-fly sequences.
+     * @param referenceSequence The reference sequence to normalize.
+     * @throws org.broadinstitute.gatk.utils.exceptions.ReviewedGATKException if normalized sequence cannot be generated.
+     */
+    private static void normalizeReferenceSequence(byte[] referenceSequence) {
+        StringUtil.toUpperCase(referenceSequence);
+        for(byte base: referenceSequence) {
+            if(base != 'A' && base != 'C' && base != 'G' && base != 'T')
+                throw new ReviewedGATKException(String.format("Base type %c is not supported when building references on-the-fly",(char)base));
+        }
+    }
+}
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/alignment/bwa/java/AlignerTestHarness.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/alignment/bwa/java/AlignerTestHarness.java
new file mode 100644
index 0000000..91e41e5
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/alignment/bwa/java/AlignerTestHarness.java
@@ -0,0 +1,189 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.engine.alignment.bwa.java;
+
+import htsjdk.samtools.reference.IndexedFastaSequenceFile;
+import htsjdk.samtools.*;
+import org.broadinstitute.gatk.engine.alignment.Aligner;
+import org.broadinstitute.gatk.engine.alignment.Alignment;
+import org.broadinstitute.gatk.utils.BaseUtils;
+import org.broadinstitute.gatk.utils.exceptions.ReviewedGATKException;
+
+import java.io.File;
+import java.io.FileNotFoundException;
+
+/**
+ * A test harness to ensure that the perfect aligner works.
+ *
+ * @author mhanna
+ * @version 0.1
+ */
+public class AlignerTestHarness {
+    public static void main( String argv[] ) throws FileNotFoundException {
+        if( argv.length != 6 ) {
+            System.out.println("PerfectAlignerTestHarness <fasta> <bwt> <rbwt> <sa> <rsa> <bam>");
+            System.exit(1);
+        }
+
+        File referenceFile = new File(argv[0]);
+        File bwtFile = new File(argv[1]);
+        File rbwtFile = new File(argv[2]);
+        File suffixArrayFile = new File(argv[3]);
+        File reverseSuffixArrayFile = new File(argv[4]);
+        File bamFile = new File(argv[5]);
+
+        align(referenceFile,bwtFile,rbwtFile,suffixArrayFile,reverseSuffixArrayFile,bamFile);
+    }
+
+    private static void align(File referenceFile, File bwtFile, File rbwtFile, File suffixArrayFile, File reverseSuffixArrayFile, File bamFile) throws FileNotFoundException {
+        Aligner aligner = new BWAJavaAligner(bwtFile,rbwtFile,suffixArrayFile,reverseSuffixArrayFile);
+        int count = 0;
+
+        SAMFileReader reader = new SAMFileReader(bamFile);
+        reader.setValidationStringency(ValidationStringency.SILENT);
+
+        int mismatches = 0;
+        int failures = 0;
+
+        for(SAMRecord read: reader) {
+            count++;
+            if( count > 200000 ) break;
+            //if( count < 366000 ) continue;
+            //if( count > 2 ) break;
+            //if( !read.getReadName().endsWith("SL-XBC:1:82:506:404#0") )
+            //    continue;
+            //if( !read.getReadName().endsWith("SL-XBC:1:36:30:1926#0") )
+            //    continue;
+            //if( !read.getReadName().endsWith("SL-XBC:1:60:1342:1340#0") )
+            //    continue;
+
+            SAMRecord alignmentCleaned = null;
+            try {
+                alignmentCleaned = (SAMRecord)read.clone();
+            }
+            catch( CloneNotSupportedException ex ) {
+                throw new ReviewedGATKException("SAMRecord clone not supported", ex);
+            }
+
+            if( alignmentCleaned.getReadNegativeStrandFlag() )
+                alignmentCleaned.setReadBases(BaseUtils.simpleReverseComplement(alignmentCleaned.getReadBases()));
+
+            alignmentCleaned.setReferenceIndex(SAMRecord.NO_ALIGNMENT_REFERENCE_INDEX);
+            alignmentCleaned.setAlignmentStart(SAMRecord.NO_ALIGNMENT_START);
+            alignmentCleaned.setMappingQuality(SAMRecord.NO_MAPPING_QUALITY);
+            alignmentCleaned.setCigarString(SAMRecord.NO_ALIGNMENT_CIGAR);
+
+            // Clear everything except flags pertaining to pairing and set 'unmapped' status to true.
+            alignmentCleaned.setFlags(alignmentCleaned.getFlags() & 0x00A1 | 0x000C);
+
+            Iterable<Alignment[]> alignments = aligner.getAllAlignments(alignmentCleaned.getReadBases());
+            if(!alignments.iterator().hasNext() ) {
+                //throw new GATKException(String.format("Unable to align read %s to reference; count = %d",read.getReadName(),count));
+                System.out.printf("Unable to align read %s to reference; count = %d%n",read.getReadName(),count);
+                failures++;
+            }
+
+            Alignment foundAlignment = null;
+            for(Alignment[] alignmentsOfQuality: alignments) {
+                for(Alignment alignment: alignmentsOfQuality) {
+                    if( read.getReadNegativeStrandFlag() != alignment.isNegativeStrand() )
+                        continue;
+                    if( read.getAlignmentStart() != alignment.getAlignmentStart() )
+                        continue;
+
+                    foundAlignment = alignment;                    
+                }
+            }
+
+            if( foundAlignment != null ) {
+                //System.out.printf("%s: Aligned read to reference at position %d with %d mismatches, %d gap opens, and %d gap extensions.%n", read.getReadName(), foundAlignment.getAlignmentStart(), foundAlignment.getMismatches(), foundAlignment.getGapOpens(), foundAlignment.getGapExtensions());
+            }
+            else {
+                System.out.printf("Error aligning read %s%n", read.getReadName());
+
+                mismatches++;
+
+                IndexedFastaSequenceFile reference = new IndexedFastaSequenceFile(referenceFile);
+
+                System.out.printf("read          = %s, position = %d, negative strand = %b%n", formatBasesBasedOnCigar(read.getReadString(),read.getCigar(),CigarOperator.DELETION),
+                                                                                               read.getAlignmentStart(),
+                                                                                               read.getReadNegativeStrandFlag());
+                int numDeletions = numDeletionsInCigar(read.getCigar());
+                String expectedRef = new String(reference.getSubsequenceAt(reference.getSequenceDictionary().getSequences().get(0).getSequenceName(),read.getAlignmentStart(),read.getAlignmentStart()+read.getReadLength()+numDeletions-1).getBases());
+                System.out.printf("expected ref  = %s%n", formatBasesBasedOnCigar(expectedRef,read.getCigar(),CigarOperator.INSERTION));
+
+                for(Alignment[] alignmentsOfQuality: alignments) {
+                    for(Alignment alignment: alignmentsOfQuality) {
+                        System.out.println();
+
+                        Cigar cigar = ((BWAAlignment)alignment).getCigar();
+
+                        System.out.printf("read          = %s%n", formatBasesBasedOnCigar(read.getReadString(),cigar,CigarOperator.DELETION));
+
+                        int deletionCount = ((BWAAlignment)alignment).getNumberOfBasesMatchingState(AlignmentState.DELETION);
+                        String alignedRef = new String(reference.getSubsequenceAt(reference.getSequenceDictionary().getSequences().get(0).getSequenceName(),alignment.getAlignmentStart(),alignment.getAlignmentStart()+read.getReadLength()+deletionCount-1).getBases());
+                        System.out.printf("actual ref    = %s, position = %d, negative strand = %b%n", formatBasesBasedOnCigar(alignedRef,cigar,CigarOperator.INSERTION),
+                                alignment.getAlignmentStart(),
+                                alignment.isNegativeStrand());
+                    }
+                }
+
+                //throw new GATKException(String.format("Read %s was placed at incorrect location; count = %d%n",read.getReadName(),count));                
+            }
+
+
+            if( count % 1000 == 0 )
+                System.out.printf("%d reads examined.%n",count);                
+        }
+
+        System.out.printf("%d reads examined; %d mismatches; %d failures.%n",count,mismatches,failures);
+    }
+
+    private static String formatBasesBasedOnCigar( String bases, Cigar cigar, CigarOperator toBlank ) {
+        StringBuilder formatted = new StringBuilder();
+        int readIndex = 0;
+        for(CigarElement cigarElement: cigar.getCigarElements()) {
+            if(cigarElement.getOperator() == toBlank) {
+                int number = cigarElement.getLength();
+                while( number-- > 0 ) formatted.append(' ');
+            }
+            else {
+                int number = cigarElement.getLength();
+                while( number-- > 0 ) formatted.append(bases.charAt(readIndex++));
+            }
+        }
+        return formatted.toString();
+    }
+
+    private static int numDeletionsInCigar( Cigar cigar ) {
+        int numDeletions = 0;
+        for(CigarElement cigarElement: cigar.getCigarElements()) {
+            if(cigarElement.getOperator() == CigarOperator.DELETION)
+                numDeletions += cigarElement.getLength();
+        }
+        return numDeletions;
+    }
+}
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/alignment/bwa/java/AlignmentMatchSequence.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/alignment/bwa/java/AlignmentMatchSequence.java
new file mode 100644
index 0000000..f1148c6
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/alignment/bwa/java/AlignmentMatchSequence.java
@@ -0,0 +1,175 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.engine.alignment.bwa.java;
+
+import htsjdk.samtools.Cigar;
+import htsjdk.samtools.CigarElement;
+import htsjdk.samtools.CigarOperator;
+import org.broadinstitute.gatk.utils.exceptions.ReviewedGATKException;
+
+import java.util.ArrayDeque;
+import java.util.Deque;
+import java.util.Iterator;
+
+/**
+ * Represents a sequence of matches.
+ *
+ * @author mhanna
+ * @version 0.1
+ */
+public class AlignmentMatchSequence implements Cloneable {
+    /**
+     * Stores the particular match entries in the order they occur.
+     */
+    private Deque<AlignmentMatchSequenceEntry> entries = new ArrayDeque<AlignmentMatchSequenceEntry>();
+
+    /**
+     * Clone the given match sequence.
+     * @return A deep copy of the current match sequence.
+     */
+    public AlignmentMatchSequence clone() {
+        AlignmentMatchSequence copy = null;
+        try {
+            copy = (AlignmentMatchSequence)super.clone(); 
+        }
+        catch( CloneNotSupportedException ex ) {
+            throw new ReviewedGATKException("Unable to clone AlignmentMatchSequence.");
+        }
+
+        copy.entries = new ArrayDeque<AlignmentMatchSequenceEntry>();
+        for( AlignmentMatchSequenceEntry entry: entries )
+            copy.entries.add(entry.clone());
+
+        return copy;
+    }
+
+    public Cigar convertToCigar(boolean negativeStrand) {
+        Cigar cigar = new Cigar();
+        Iterator<AlignmentMatchSequenceEntry> iterator = negativeStrand ? entries.descendingIterator() : entries.iterator();
+        while( iterator.hasNext() ) {
+            AlignmentMatchSequenceEntry entry = iterator.next();
+            CigarOperator operator;
+            switch( entry.getAlignmentState() ) {
+                case MATCH_MISMATCH: operator = CigarOperator.MATCH_OR_MISMATCH; break;
+                case INSERTION: operator = CigarOperator.INSERTION; break;
+                case DELETION: operator = CigarOperator.DELETION; break;
+                default: throw new ReviewedGATKException("convertToCigar: cannot process state: " + entry.getAlignmentState());
+            }
+            cigar.add( new CigarElement(entry.count,operator) );
+        }
+        return cigar;
+    }
+
+    /**
+     * All a new alignment of the given state.
+     * @param state State to add to the sequence.
+     */
+    public void addNext( AlignmentState state ) {
+        AlignmentMatchSequenceEntry last = entries.peekLast();
+        // If the last entry is the same as this one, increment it.  Otherwise, add a new entry.
+        if( last != null && last.alignmentState == state )
+            last.increment();
+        else
+            entries.add(new AlignmentMatchSequenceEntry(state));
+    }
+
+    /**
+     * Gets the current state of this alignment (what's the state of the last base?)
+     * @return State of the most recently aligned base.
+     */
+    public AlignmentState getCurrentState() {
+        if( entries.size() == 0 )
+            return AlignmentState.MATCH_MISMATCH;        
+        return entries.peekLast().getAlignmentState();
+    }
+
+    /**
+     * How many bases in the read match the given state.
+     * @param state State to test.
+     * @return number of bases which match that state.
+     */
+    public int getNumberOfBasesMatchingState(AlignmentState state) {
+        int matches = 0;
+        for( AlignmentMatchSequenceEntry entry: entries ) {
+            if( entry.getAlignmentState() == state )
+                matches += entry.count;
+        }
+        return matches;
+    }
+
+    /**
+     * Stores an individual match sequence entry.
+     */
+    private class AlignmentMatchSequenceEntry implements Cloneable {
+        /**
+         * The state of the alignment throughout a given point in the sequence.
+         */
+        private final AlignmentState alignmentState;
+
+        /**
+         * The number of bases having this particular state.
+         */
+        private int count;
+
+        /**
+         * Create a new sequence entry with the given state.
+         * @param alignmentState The state that this sequence should contain.
+         */
+        AlignmentMatchSequenceEntry( AlignmentState alignmentState ) {
+            this.alignmentState = alignmentState;
+            this.count = 1;
+        }
+
+        /**
+         * Clone the given match sequence entry.
+         * @return A deep copy of the current match sequence entry.
+         */
+        public AlignmentMatchSequenceEntry clone() {
+            try {
+                return (AlignmentMatchSequenceEntry)super.clone(); 
+            }
+            catch( CloneNotSupportedException ex ) {
+                throw new ReviewedGATKException("Unable to clone AlignmentMatchSequenceEntry.");
+            }
+        }
+
+        /**
+         * Retrieves the current state of the alignment.
+         * @return The state of the current sequence.
+         */
+        AlignmentState getAlignmentState() {
+            return alignmentState;
+        }
+
+        /**
+         * Increment the count of alignments having this particular state.
+         */
+        void increment() {
+            count++;
+        }
+    }
+}
+
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/alignment/bwa/java/AlignmentState.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/alignment/bwa/java/AlignmentState.java
new file mode 100644
index 0000000..f4ba1bb
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/alignment/bwa/java/AlignmentState.java
@@ -0,0 +1,38 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.engine.alignment.bwa.java;
+
+/**
+ * The state of a given base in the alignment.
+ *
+ * @author mhanna
+ * @version 0.1
+ */
+public enum AlignmentState {
+    MATCH_MISMATCH,
+    INSERTION,
+    DELETION
+}
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/alignment/bwa/java/BWAAlignment.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/alignment/bwa/java/BWAAlignment.java
new file mode 100644
index 0000000..88ef4a5
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/alignment/bwa/java/BWAAlignment.java
@@ -0,0 +1,215 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.engine.alignment.bwa.java;
+
+import htsjdk.samtools.Cigar;
+import org.broadinstitute.gatk.engine.alignment.Alignment;
+import org.broadinstitute.gatk.utils.exceptions.ReviewedGATKException;
+
+/**
+ * An alignment object to be used incrementally as the BWA aligner
+ * inspects the read.
+ *
+ * @author mhanna
+ * @version 0.1
+ */
+public class BWAAlignment extends Alignment implements Cloneable {
+    /**
+     * Track the number of alignments that have been created.
+     */
+    private static long numCreated;
+
+    /**
+     * Which number alignment is this?
+     */
+    private long creationNumber;
+
+    /**
+     * The aligner performing the alignments.
+     */
+    protected BWAJavaAligner aligner;
+
+    /**
+     * The sequence of matches/mismatches/insertions/deletions.
+     */
+    private AlignmentMatchSequence alignmentMatchSequence = new AlignmentMatchSequence();
+
+    /**
+     * Working variable.  How many bases have been matched at this point.
+     */
+    protected int position;
+
+    /**
+     * Working variable.  How many mismatches have been encountered at this point.
+     */
+    private int mismatches;
+
+    /**
+     * Number of gap opens in alignment.
+     */
+    private int gapOpens;
+
+    /**
+     * Number of gap extensions in alignment.
+     */
+    private int gapExtensions;
+
+    /**
+     * Working variable.  The lower bound of the alignment within the BWT.
+     */
+    protected long loBound;
+
+    /**
+     * Working variable.  The upper bound of the alignment within the BWT.
+     */
+    protected long hiBound;
+
+    protected void setAlignmentStart(long position) {
+        this.alignmentStart = position;
+    }
+
+    protected void setNegativeStrand(boolean negativeStrand) {
+        this.negativeStrand = negativeStrand;
+    }
+
+    /**
+     * Cache the score.
+     */
+    private int score;
+
+    public Cigar getCigar() {
+        return alignmentMatchSequence.convertToCigar(isNegativeStrand());
+    }
+
+    /**
+     * Gets the current state of this alignment (state of the last base viewed)..
+     * @return Current state of the alignment.
+     */
+    public AlignmentState getCurrentState() {
+        return alignmentMatchSequence.getCurrentState();
+    }
+
+    /**
+     * Adds the given state to the current alignment.
+     * @param state State to add to the given alignment.
+     */
+    public void addState( AlignmentState state ) {
+        alignmentMatchSequence.addNext(state);    
+    }
+
+    /**
+     * Gets the BWA score of this alignment.
+     * @return BWA-style scores.  0 is best.
+     */
+    public int getScore() {
+        return score;
+    }
+
+    public int getMismatches() { return mismatches; }
+    public int getGapOpens() { return gapOpens; }
+    public int getGapExtensions() { return gapExtensions; }
+
+    public void incrementMismatches() {
+        this.mismatches++;
+        updateScore();
+    }
+
+    public void incrementGapOpens() {
+        this.gapOpens++;
+        updateScore();
+    }
+
+    public void incrementGapExtensions() {
+        this.gapExtensions++;
+        updateScore();
+    }
+
+    /**
+     * Updates the score based on new information about matches / mismatches.
+     */
+    private void updateScore() {
+        score = mismatches*aligner.MISMATCH_PENALTY + gapOpens*aligner.GAP_OPEN_PENALTY + gapExtensions*aligner.GAP_EXTENSION_PENALTY;
+    }
+
+    /**
+     * Create a new alignment with the given parent aligner.
+     * @param aligner Aligner being used.
+     */
+    public BWAAlignment( BWAJavaAligner aligner ) {
+        this.aligner = aligner;
+        this.creationNumber = numCreated++;
+    }
+
+    /**
+     * Clone the alignment.
+     * @return New instance of the alignment.
+     */
+    public BWAAlignment clone() {
+        BWAAlignment newAlignment = null;
+        try {
+            newAlignment = (BWAAlignment)super.clone();
+        }
+        catch( CloneNotSupportedException ex ) {
+            throw new ReviewedGATKException("Unable to clone BWAAlignment.");
+        }
+        newAlignment.creationNumber = numCreated++;
+        newAlignment.alignmentMatchSequence = alignmentMatchSequence.clone();
+
+        return newAlignment;
+    }
+
+    /**
+     * How many bases in the read match the given state.
+     * @param state State to test.
+     * @return number of bases which match that state.
+     */
+    public int getNumberOfBasesMatchingState(AlignmentState state) {
+        return alignmentMatchSequence.getNumberOfBasesMatchingState(state);
+    }
+
+    /**
+     * Compare this alignment to another alignment.
+     * @param rhs Other alignment to which to compare.
+     * @return < 0 if this < other, == 0 if this == other, > 0 if this > other
+     */
+    public int compareTo(Alignment rhs) {
+        BWAAlignment other = (BWAAlignment)rhs;
+
+        // If the scores are different, disambiguate using the score.
+        if(score != other.score)
+            return score > other.score ? 1 : -1;
+
+        // Otherwise, use the order in which the elements were created.
+        if(creationNumber != other.creationNumber)
+            return creationNumber > other.creationNumber ? -1 : 1;
+
+        return 0;
+    }
+
+    public String toString() {
+        return String.format("position: %d, strand: %b, state: %s, mismatches: %d, gap opens: %d, gap extensions: %d, loBound: %d, hiBound: %d, score: %d, creationNumber: %d", position, negativeStrand, alignmentMatchSequence.getCurrentState(), mismatches, gapOpens, gapExtensions, loBound, hiBound, getScore(), creationNumber);
+    }
+}
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/alignment/bwa/java/BWAJavaAligner.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/alignment/bwa/java/BWAJavaAligner.java
new file mode 100644
index 0000000..09a5b45
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/alignment/bwa/java/BWAJavaAligner.java
@@ -0,0 +1,418 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.engine.alignment.bwa.java;
+
+import htsjdk.samtools.SAMFileHeader;
+import htsjdk.samtools.SAMRecord;
+import org.broadinstitute.gatk.engine.alignment.Alignment;
+import org.broadinstitute.gatk.engine.alignment.bwa.BWAAligner;
+import org.broadinstitute.gatk.engine.alignment.bwa.BWAConfiguration;
+import org.broadinstitute.gatk.engine.alignment.reference.bwt.*;
+import org.broadinstitute.gatk.utils.BaseUtils;
+import org.broadinstitute.gatk.utils.Utils;
+
+import java.io.File;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.PriorityQueue;
+
+/**
+ * Create imperfect alignments from the read to the genome represented by the given BWT / suffix array. 
+ *
+ * @author mhanna
+ * @version 0.1
+ */
+public class BWAJavaAligner extends BWAAligner {
+    /**
+     * BWT in the forward direction.
+     */
+    private BWT forwardBWT;
+
+    /**
+     * BWT in the reverse direction.
+     */
+    private BWT reverseBWT;
+
+    /**
+     * Suffix array in the forward direction.
+     */
+    private SuffixArray forwardSuffixArray;
+
+    /**
+     * Suffix array in the reverse direction.
+     */
+    private SuffixArray reverseSuffixArray;
+
+    /**
+     * Maximum edit distance (-n option from original BWA).
+     */
+    private final int MAXIMUM_EDIT_DISTANCE = 4;
+
+    /**
+     * Maximum number of gap opens (-o option from original BWA).
+     */
+    private final int MAXIMUM_GAP_OPENS = 1;
+
+    /**
+     * Maximum number of gap extensions (-e option from original BWA).
+     */
+    private final int MAXIMUM_GAP_EXTENSIONS = 6;
+
+    /**
+     * Penalty for straight mismatches (-M option from original BWA).
+     */
+    public final int MISMATCH_PENALTY = 3;
+
+    /**
+     * Penalty for gap opens (-O option from original BWA).
+     */
+    public final int GAP_OPEN_PENALTY = 11;
+
+    /**
+     * Penalty for gap extensions (-E option from original BWA).
+     */
+    public final int GAP_EXTENSION_PENALTY = 4;
+
+    /**
+     * Skip the ends of indels.
+     */
+    public final int INDEL_END_SKIP = 5;
+
+    public BWAJavaAligner( File forwardBWTFile, File reverseBWTFile, File forwardSuffixArrayFile, File reverseSuffixArrayFile ) {
+        super(null,null);
+        forwardBWT = new BWTReader(forwardBWTFile).read();
+        reverseBWT = new BWTReader(reverseBWTFile).read();
+        forwardSuffixArray = new SuffixArrayReader(forwardSuffixArrayFile,forwardBWT).read();
+        reverseSuffixArray = new SuffixArrayReader(reverseSuffixArrayFile,reverseBWT).read();
+    }
+
+    /**
+     * Close this instance of the BWA pointer and delete its resources.
+     */
+    @Override
+    public void close()  {
+        throw new UnsupportedOperationException("BWA aligner can't currently be closed.");
+    }
+
+    /**
+     * Update the current parameters of this aligner.
+     * @param configuration New configuration to set.
+     */
+    public void updateConfiguration(BWAConfiguration configuration) {
+        throw new UnsupportedOperationException("Configuration of the BWA aligner can't currently be changed.");
+    }
+
+    /**
+     * Allow the aligner to choose one alignment randomly from the pile of best alignments.
+     * @param bases Bases to align.
+     * @return An align
+     */
+    public Alignment getBestAlignment(final byte[] bases) { throw new UnsupportedOperationException("BWAJavaAligner does not yet support the standard Aligner interface."); }
+
+    /**
+     * Align the read to the reference.
+     * @param read Read to align.
+     * @param header Optional header to drop in place.
+     * @return A list of the alignments.
+     */
+    public SAMRecord align(final SAMRecord read, final SAMFileHeader header) { throw new UnsupportedOperationException("BWAJavaAligner does not yet support the standard Aligner interface."); }
+
+    /**
+     * Get a iterator of alignments, batched by mapping quality.
+     * @param bases List of bases.
+     * @return Iterator to alignments.
+     */
+    public Iterable<Alignment[]> getAllAlignments(final byte[] bases) { throw new UnsupportedOperationException("BWAJavaAligner does not yet support the standard Aligner interface."); }
+
+    /**
+     * Get a iterator of aligned reads, batched by mapping quality.
+     * @param read Read to align.
+     * @param newHeader Optional new header to use when aligning the read.  If present, it must be null.
+     * @return Iterator to alignments.
+     */
+    public Iterable<SAMRecord[]> alignAll(final SAMRecord read, final SAMFileHeader newHeader) { throw new UnsupportedOperationException("BWAJavaAligner does not yet support the standard Aligner interface."); }
+
+
+    public List<Alignment> align( SAMRecord read ) {
+        List<Alignment> successfulMatches = new ArrayList<Alignment>();
+
+        Byte[] uncomplementedBases = normalizeBases(read.getReadBases());
+        Byte[] complementedBases = normalizeBases(Utils.reverse(BaseUtils.simpleReverseComplement(read.getReadBases())));
+
+        List<LowerBound> forwardLowerBounds = LowerBound.create(uncomplementedBases,forwardBWT);
+        List<LowerBound> reverseLowerBounds = LowerBound.create(complementedBases,reverseBWT);
+
+        // Seed the best score with any score that won't overflow on comparison.
+        int bestScore = Integer.MAX_VALUE - MISMATCH_PENALTY;
+        int bestDiff = MAXIMUM_EDIT_DISTANCE+1;
+        int maxDiff = MAXIMUM_EDIT_DISTANCE;
+
+        PriorityQueue<BWAAlignment> alignments = new PriorityQueue<BWAAlignment>();
+
+        // Create a fictional initial alignment, with the position just off the end of the read, and the limits
+        // set as the entire BWT.
+        alignments.add(createSeedAlignment(reverseBWT));
+        alignments.add(createSeedAlignment(forwardBWT));
+
+        while(!alignments.isEmpty()) {
+            BWAAlignment alignment = alignments.remove();
+
+            // From bwtgap.c in the original BWT; if the rank is worse than the best score + the mismatch PENALTY, move on.
+            if( alignment.getScore() > bestScore + MISMATCH_PENALTY )
+                break;
+
+            Byte[] bases = alignment.isNegativeStrand() ? complementedBases : uncomplementedBases;
+            BWT bwt = alignment.isNegativeStrand() ? forwardBWT : reverseBWT;
+            List<LowerBound> lowerBounds = alignment.isNegativeStrand() ? reverseLowerBounds : forwardLowerBounds;
+
+            // if z < D(i) then return {}
+            int mismatches = maxDiff - alignment.getMismatches() - alignment.getGapOpens() - alignment.getGapExtensions();
+            if( alignment.position < lowerBounds.size()-1 && mismatches < lowerBounds.get(alignment.position+1).value )
+                continue;
+
+            if(mismatches == 0) {
+                exactMatch(alignment,bases,bwt);
+                if(alignment.loBound > alignment.hiBound)
+                    continue;
+            }
+
+            // Found a valid alignment; store it and move on.
+            if(alignment.position >= read.getReadLength()-1) {
+                for(long bwtIndex = alignment.loBound; bwtIndex <= alignment.hiBound; bwtIndex++) {
+                    BWAAlignment finalAlignment = alignment.clone();
+
+                    if( finalAlignment.isNegativeStrand() )
+                        finalAlignment.setAlignmentStart(forwardSuffixArray.get(bwtIndex) + 1);
+                    else {
+                        int sizeAlongReference = read.getReadLength() -
+                                finalAlignment.getNumberOfBasesMatchingState(AlignmentState.INSERTION) +
+                                finalAlignment.getNumberOfBasesMatchingState(AlignmentState.DELETION);
+                        finalAlignment.setAlignmentStart(reverseBWT.length() - reverseSuffixArray.get(bwtIndex) - sizeAlongReference + 1);
+                    }
+
+                    successfulMatches.add(finalAlignment);
+
+                    bestScore = Math.min(finalAlignment.getScore(),bestScore);
+                    bestDiff = Math.min(finalAlignment.getMismatches()+finalAlignment.getGapOpens()+finalAlignment.getGapExtensions(),bestDiff);
+                    maxDiff = bestDiff + 1;
+                }
+
+                continue;
+            }
+
+            //System.out.printf("Processing alignments; queue size = %d, alignment = %s, bound = %d, base = %s%n", alignments.size(), alignment, lowerBounds.get(alignment.position+1).value, alignment.position >= 0 ? (char)bases[alignment.position].byteValue() : "");
+            /*
+            System.out.printf("#1\t[%d,%d,%d,%c]\t[%d,%d,%d]\t[%d,%d]\t[%d,%d]%n",alignments.size(),
+                                                        alignment.negativeStrand?1:0,
+                                                        bases.length-alignment.position-1,
+                                                        alignment.getCurrentState().toString().charAt(0),
+                                                        alignment.getMismatches(),
+                                                        alignment.getGapOpens(),
+                                                        alignment.getGapExtensions(),
+                                                        lowerBounds.get(alignment.position+1).value,
+                                                        lowerBounds.get(alignment.position+1).width,
+                                                        alignment.loBound,
+                                                        alignment.hiBound);
+                                                        */
+
+            // Temporary -- look ahead to see if the next alignment is bounded.
+            boolean allowDifferences = mismatches > 0;
+            boolean allowMismatches = mismatches > 0;
+
+            if( allowDifferences &&
+                alignment.position+1 >= INDEL_END_SKIP-1+alignment.getGapOpens()+alignment.getGapExtensions() &&
+                read.getReadLength()-1-(alignment.position+1) >= INDEL_END_SKIP+alignment.getGapOpens()+alignment.getGapExtensions() ) {
+                if( alignment.getCurrentState() == AlignmentState.MATCH_MISMATCH ) {
+                    if( alignment.getGapOpens() < MAXIMUM_GAP_OPENS ) {
+                        // Add a potential insertion extension.
+                        BWAAlignment insertionAlignment = createInsertionAlignment(alignment);
+                        insertionAlignment.incrementGapOpens();
+                        alignments.add(insertionAlignment);
+
+                        // Add a potential deletion by marking a deletion and augmenting the position.
+                        List<BWAAlignment> deletionAlignments = createDeletionAlignments(bwt,alignment);
+                        for( BWAAlignment deletionAlignment: deletionAlignments )
+                            deletionAlignment.incrementGapOpens();
+                        alignments.addAll(deletionAlignments);
+                    }
+                }
+                else if( alignment.getCurrentState() == AlignmentState.INSERTION ) {
+                    if( alignment.getGapExtensions() < MAXIMUM_GAP_EXTENSIONS && mismatches > 0 ) {
+                        // Add a potential insertion extension.
+                        BWAAlignment insertionAlignment = createInsertionAlignment(alignment);
+                        insertionAlignment.incrementGapExtensions();
+                        alignments.add(insertionAlignment);
+                    }
+                }
+                else if( alignment.getCurrentState() == AlignmentState.DELETION ) {
+                    if( alignment.getGapExtensions() < MAXIMUM_GAP_EXTENSIONS && mismatches > 0 ) {
+                        // Add a potential deletion by marking a deletion and augmenting the position.
+                        List<BWAAlignment> deletionAlignments = createDeletionAlignments(bwt,alignment);
+                        for( BWAAlignment deletionAlignment: deletionAlignments )
+                            deletionAlignment.incrementGapExtensions();
+                        alignments.addAll(deletionAlignments);
+                    }
+                }
+            }
+
+            // Mismatches
+            alignments.addAll(createMatchedAlignments(bwt,alignment,bases,allowDifferences&&allowMismatches));
+        }
+
+        return successfulMatches;
+    }
+
+    /**
+     * Create an seeding alignment to use as a starting point when traversing.
+     * @param bwt source BWT.
+     * @return Seed alignment.
+     */
+    private BWAAlignment createSeedAlignment(BWT bwt) {
+        BWAAlignment seed = new BWAAlignment(this);
+        seed.setNegativeStrand(bwt == forwardBWT);
+        seed.position = -1;
+        seed.loBound = 0;
+        seed.hiBound = bwt.length();
+        return seed;
+    }
+
+    /**
+     * Creates a new alignments representing direct matches / mismatches.
+     * @param bwt Source BWT with which to work.
+     * @param alignment Alignment for the previous position.
+     * @param bases The bases in the read.
+     * @param allowMismatch Should mismatching bases be allowed?
+     * @return New alignment representing this position if valid; null otherwise.
+     */
+    private List<BWAAlignment> createMatchedAlignments( BWT bwt, BWAAlignment alignment, Byte[] bases, boolean allowMismatch ) {
+        List<BWAAlignment> newAlignments = new ArrayList<BWAAlignment>();
+
+        List<Byte> baseChoices = new ArrayList<Byte>();
+        Byte thisBase = bases[alignment.position+1];
+
+        if( allowMismatch )
+            baseChoices.addAll(Bases.allOf());
+        else
+            baseChoices.add(thisBase);
+
+        if( thisBase != null ) {
+            // Keep rotating the current base to the last position until we've hit the current base.
+            for( ;; ) {
+                baseChoices.add(baseChoices.remove(0));
+                if( thisBase.equals(baseChoices.get(baseChoices.size()-1)) )
+                    break;
+
+            }
+        }
+
+        for(byte base: baseChoices) {
+            BWAAlignment newAlignment = alignment.clone();
+
+            newAlignment.loBound = bwt.counts(base) + bwt.occurrences(base,alignment.loBound-1) + 1;
+            newAlignment.hiBound = bwt.counts(base) + bwt.occurrences(base,alignment.hiBound);
+
+            // If this alignment is valid, skip it.
+            if( newAlignment.loBound > newAlignment.hiBound )
+                continue;
+
+            newAlignment.position++;
+            newAlignment.addState(AlignmentState.MATCH_MISMATCH);
+            if( bases[newAlignment.position] == null || base != bases[newAlignment.position] )
+                newAlignment.incrementMismatches();
+
+            newAlignments.add(newAlignment);
+        }
+
+        return newAlignments;
+    }
+
+    /**
+     * Create a new alignment representing an insertion at this point in the read.
+     * @param alignment Alignment from which to derive the insertion.
+     * @return New alignment reflecting the insertion.
+     */
+    private BWAAlignment createInsertionAlignment( BWAAlignment alignment ) {
+        // Add a potential insertion extension.
+        BWAAlignment newAlignment = alignment.clone();
+        newAlignment.position++;
+        newAlignment.addState(AlignmentState.INSERTION);
+        return newAlignment;
+    }
+
+    /**
+     * Create new alignments representing a deletion at this point in the read.
+     * @param bwt source BWT for inferring deletion info.
+     * @param alignment Alignment from which to derive the deletion.
+     * @return New alignments reflecting all possible deletions.
+     */
+    private List<BWAAlignment> createDeletionAlignments( BWT bwt, BWAAlignment alignment) {
+        List<BWAAlignment> newAlignments = new ArrayList<BWAAlignment>();
+        for(byte base: Bases.instance) {
+            BWAAlignment newAlignment = alignment.clone();
+
+            newAlignment.loBound = bwt.counts(base) + bwt.occurrences(base,alignment.loBound-1) + 1;
+            newAlignment.hiBound = bwt.counts(base) + bwt.occurrences(base,alignment.hiBound);
+
+            // If this alignment is valid, skip it.
+            if( newAlignment.loBound > newAlignment.hiBound )
+                continue;
+
+            newAlignment.addState(AlignmentState.DELETION);
+
+            newAlignments.add(newAlignment);
+        }
+
+        return newAlignments;
+    }
+
+    /**
+     * Exactly match the given alignment against the given BWT.
+     * @param alignment Alignment to match.
+     * @param bases Bases to use.
+     * @param bwt BWT to use.
+     */
+    private void exactMatch( BWAAlignment alignment, Byte[] bases, BWT bwt ) {
+        while( ++alignment.position < bases.length ) {
+            byte base = bases[alignment.position];
+            alignment.loBound = bwt.counts(base) + bwt.occurrences(base,alignment.loBound-1) + 1;
+            alignment.hiBound = bwt.counts(base) + bwt.occurrences(base,alignment.hiBound);
+            if( alignment.loBound > alignment.hiBound )
+                return;
+        }
+    }
+
+    /**
+     * Make each base into A/C/G/T or null if unknown.
+     * @param bases Base string to normalize.
+     * @return Array of normalized bases.
+     */
+    private Byte[] normalizeBases( byte[] bases ) {
+        Byte[] normalBases = new Byte[bases.length];
+        for(int i = 0; i < bases.length; i++)
+            normalBases[i] = Bases.fromASCII(bases[i]);
+        return normalBases;
+    }
+}
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/alignment/bwa/java/LowerBound.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/alignment/bwa/java/LowerBound.java
new file mode 100644
index 0000000..e5e292b
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/alignment/bwa/java/LowerBound.java
@@ -0,0 +1,113 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.engine.alignment.bwa.java;
+
+import org.broadinstitute.gatk.engine.alignment.reference.bwt.BWT;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * At any point along the given read, what is a good lower bound for the
+ * total number of differences?
+ *
+ * @author mhanna
+ * @version 0.1
+ */
+public class LowerBound {
+    /**
+     * Lower bound of the suffix array.
+     */
+    public final long loIndex;
+
+    /**
+     * Upper bound of the suffix array.
+     */
+    public final long hiIndex;
+
+    /**
+     * Width of the bwt from loIndex -> hiIndex, inclusive.
+     */
+    public final long width;
+
+    /**
+     * The lower bound at the given point.
+     */
+    public final int value;
+
+    /**
+     * Create a new lower bound with the given value.
+     * @param loIndex The lower bound of the BWT.
+     * @param hiIndex The upper bound of the BWT.
+     * @param value Value for the lower bound at this site.
+     */
+    private LowerBound(long loIndex, long hiIndex, int value) {
+        this.loIndex = loIndex;
+        this.hiIndex = hiIndex;
+        this.width = hiIndex - loIndex + 1;
+        this.value = value;
+    }
+
+    /**
+     * Create a non-optimal bound according to the algorithm specified in Figure 3 of the BWA paper.
+     * @param bases Bases of the read to use when creating a new BWT.
+     * @param bwt BWT to check against.
+     * @return A list of lower bounds at every point in the reference.
+     *
+     */
+    public static List<LowerBound> create(Byte[] bases, BWT bwt) {
+        List<LowerBound> bounds = new ArrayList<LowerBound>();
+
+        long loIndex = 0, hiIndex = bwt.length();
+        int mismatches = 0;
+        for( int i = bases.length-1; i >= 0; i-- ) {
+            Byte base = bases[i];
+
+            // Ignore non-ACGT bases.
+            if( base != null ) {
+                loIndex = bwt.counts(base) + bwt.occurrences(base,loIndex-1) + 1;
+                hiIndex = bwt.counts(base) + bwt.occurrences(base,hiIndex);            
+            }
+
+            if( base == null || loIndex > hiIndex ) {
+                loIndex = 0;
+                hiIndex = bwt.length();
+                mismatches++;
+            }
+            bounds.add(0,new LowerBound(loIndex,hiIndex,mismatches));
+        }
+
+        return bounds;
+    }
+
+    /**
+     * Create a string representation of this bound.
+     * @return String version of this bound.
+     */
+    public String toString() {
+        return String.format("LowerBound: w = %d, value = %d",width,value);
+    }
+}
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/alignment/package-info.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/alignment/package-info.java
new file mode 100644
index 0000000..5a6d70d
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/alignment/package-info.java
@@ -0,0 +1,26 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.engine.alignment;
\ No newline at end of file
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/alignment/reference/bwt/AMBWriter.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/alignment/reference/bwt/AMBWriter.java
new file mode 100644
index 0000000..b090bab
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/alignment/reference/bwt/AMBWriter.java
@@ -0,0 +1,93 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.engine.alignment.reference.bwt;
+
+import htsjdk.samtools.SAMSequenceDictionary;
+import htsjdk.samtools.SAMSequenceRecord;
+
+import java.io.File;
+import java.io.IOException;
+import java.io.OutputStream;
+import java.io.PrintStream;
+
+/**
+ * Writes .amb files - a file indicating where 'holes' (indeterminant bases)
+ * exist in the contig.  Currently, only empty, placeholder AMBs are supported.
+ *
+ * @author mhanna
+ * @version 0.1
+ */
+public class AMBWriter {
+    /**
+     * Number of holes is fixed at zero.
+     */
+    private static final int NUM_HOLES = 0;
+
+    /**
+     * Input stream from which to read BWT data.
+     */
+    private final PrintStream out;
+
+    /**
+     * Create a new ANNWriter targeting the given file.
+     * @param file file into which ANN data should be written.
+     * @throws java.io.IOException if there is a problem opening the output file.
+     */
+    public AMBWriter(File file) throws IOException {
+        out = new PrintStream(file);
+    }
+
+    /**
+     * Create a new ANNWriter targeting the given OutputStream.
+     * @param stream Stream into which ANN data should be written.
+     */
+    public AMBWriter(OutputStream stream)  {
+        out = new PrintStream(stream);
+    }
+
+    /**
+     * Write the contents of the given dictionary into the AMB file.
+     * Assumes that there are no holes in the dictionary.
+     * @param dictionary Dictionary to write.
+     */
+    public void writeEmpty(SAMSequenceDictionary dictionary) {
+        long genomeLength = 0L;
+        for(SAMSequenceRecord sequence: dictionary.getSequences())
+            genomeLength += sequence.getSequenceLength();
+
+        int sequences = dictionary.getSequences().size();
+
+        // Write the header
+        out.printf("%d %d %d%n",genomeLength,sequences,NUM_HOLES);
+    }
+
+    /**
+     * Close the given output stream.
+     */
+    public void close() {
+        out.close();
+    }
+}
\ No newline at end of file
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/alignment/reference/bwt/ANNWriter.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/alignment/reference/bwt/ANNWriter.java
new file mode 100644
index 0000000..123b3ca
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/alignment/reference/bwt/ANNWriter.java
@@ -0,0 +1,120 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.engine.alignment.reference.bwt;
+
+import htsjdk.samtools.SAMSequenceDictionary;
+import htsjdk.samtools.SAMSequenceRecord;
+
+import java.io.File;
+import java.io.IOException;
+import java.io.OutputStream;
+import java.io.PrintStream;
+
+/**
+ * Writes .ann files - an alternate sequence dictionary format
+ * used by BWA/C.  For best results, the input sequence dictionary
+ * should be created with Picard's CreateSequenceDictionary.jar,
+ * TRUNCATE_NAMES_AT_WHITESPACE=false.
+ *
+ * @author mhanna
+ * @version 0.1
+ */
+public class ANNWriter {
+    /**
+     * BWA uses a fixed seed of 11, written into every file.
+     */
+    private static final int BNS_SEED = 11;
+
+    /**
+     * A seemingly unused value that appears in every contig in the ANN.
+     */
+    private static final int GI = 0;
+
+    /**
+     * Input stream from which to read BWT data.
+     */
+    private final PrintStream out;
+
+    /**
+     * Create a new ANNWriter targeting the given file.
+     * @param file file into which ANN data should be written.
+     * @throws IOException if there is a problem opening the output file.
+     */
+    public ANNWriter(File file) throws IOException {
+        out = new PrintStream(file);
+    }
+
+    /**
+     * Create a new ANNWriter targeting the given OutputStream.
+     * @param stream Stream into which ANN data should be written.
+     */
+    public ANNWriter(OutputStream stream)  {
+        out = new PrintStream(stream);
+    }
+
+    /**
+     * Write the contents of the given dictionary into the ANN file.
+     * Assumes that no ambs (blocks of indeterminate base) are present in the dictionary.
+     * @param dictionary Dictionary to write.
+     */
+    public void write(SAMSequenceDictionary dictionary) {
+        long genomeLength = 0L;
+        for(SAMSequenceRecord sequence: dictionary.getSequences())
+            genomeLength += sequence.getSequenceLength();
+        
+        int sequences = dictionary.getSequences().size();
+
+        // Write the header
+        out.printf("%d %d %d%n",genomeLength,sequences,BNS_SEED);
+
+        for(SAMSequenceRecord sequence: dictionary.getSequences()) {
+            String fullSequenceName = sequence.getSequenceName();
+            String trimmedSequenceName = fullSequenceName;
+            String sequenceComment = "(null)";
+
+            long offset = 0;
+
+            // Separate the sequence name from the sequence comment, based on BWA's definition.
+            // BWA's definition appears to accept a zero-length contig name, so mimic that behavior.
+            if(fullSequenceName.indexOf(' ') >= 0) {
+                trimmedSequenceName = fullSequenceName.substring(0,fullSequenceName.indexOf(' '));
+                sequenceComment = fullSequenceName.substring(fullSequenceName.indexOf(' ')+1);
+            }
+
+            // Write the sequence GI (?), name, and comment.
+            out.printf("%d %s %s%n",GI,trimmedSequenceName,sequenceComment);
+            // Write the sequence offset, length, and ambs (currently fixed at 0).
+            out.printf("%d %d %d%n",offset,sequence.getSequenceLength(),0);
+        }
+    }
+
+    /**
+     * Close the given output stream.
+     */
+    public void close() {
+        out.close();
+    }
+}
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/alignment/reference/bwt/BWT.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/alignment/reference/bwt/BWT.java
new file mode 100644
index 0000000..7d0c43b
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/alignment/reference/bwt/BWT.java
@@ -0,0 +1,197 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.engine.alignment.reference.bwt;
+
+import org.broadinstitute.gatk.engine.alignment.reference.packing.PackUtils;
+import org.broadinstitute.gatk.utils.exceptions.ReviewedGATKException;
+
+/**
+ * Represents the Burrows-Wheeler Transform of a reference sequence.
+ *
+ * @author mhanna
+ * @version 0.1
+ */
+public class BWT {
+    /**
+     * Write an occurrence table after every SEQUENCE_BLOCK_SIZE bases.
+     * For this implementation to behave correctly, SEQUENCE_BLOCK_SIZE % 8 == 0
+     */
+    public static final int SEQUENCE_BLOCK_SIZE = 128;
+
+    /**
+     * The inverse SA, used as a placeholder for determining where the special EOL character sits.
+     */
+    protected final long inverseSA0;
+
+    /**
+     * Cumulative counts for the entire BWT.
+     */
+    protected final Counts counts;
+
+    /**
+     * The individual sequence blocks, modelling how they appear on disk.
+     */
+    protected final SequenceBlock[] sequenceBlocks;
+
+    /**
+     * Creates a new BWT with the given inverse SA, counts, and sequence (in ASCII).
+     * @param inverseSA0 Inverse SA entry for the first element.  Will be missing from the BWT sequence.
+     * @param counts Cumulative count of bases, in A,C,G,T order.
+     * @param sequenceBlocks The full BWT sequence, sans the '$'.
+     */
+    public BWT( long inverseSA0, Counts counts, SequenceBlock[] sequenceBlocks ) {
+        this.inverseSA0 = inverseSA0;
+        this.counts = counts;
+        this.sequenceBlocks = sequenceBlocks;
+    }
+
+    /**
+     * Creates a new BWT with the given inverse SA, occurrences, and sequence (in ASCII).
+     * @param inverseSA0 Inverse SA entry for the first element.  Will be missing from the BWT sequence.
+     * @param counts Count of bases, in A,C,G,T order.
+     * @param sequence The full BWT sequence, sans the '$'.
+     */
+    public BWT( long inverseSA0, Counts counts, byte[] sequence ) {
+        this(inverseSA0,counts,generateSequenceBlocks(sequence));
+    }
+
+    /**
+     * Extract the full sequence from the list of block.
+     * @return The full BWT string as a byte array.
+     */
+    public byte[] getSequence() {
+        byte[] sequence = new byte[(int)counts.getTotal()];
+        for( SequenceBlock block: sequenceBlocks )
+            System.arraycopy(block.sequence,0,sequence,block.sequenceStart,block.sequenceLength);
+        return sequence;
+    }
+
+    /**
+     * Get the total counts of bases lexicographically smaller than the given base, for Ferragina and Manzini's search.
+     * @param base The base.
+     * @return Total counts for all bases lexicographically smaller than this base.
+     */
+    public long counts(byte base) {
+        return counts.getCumulative(base);
+    }
+
+    /**
+     * Get the total counts of bases lexicographically smaller than the given base, for Ferragina and Manzini's search.
+     * @param base The base.
+     * @param index The position to search within the BWT.
+     * @return Total counts for all bases lexicographically smaller than this base.
+     */
+    public long occurrences(byte base,long index) {
+        SequenceBlock block = getSequenceBlock(index);
+        int position = getSequencePosition(index);
+        long accumulator = block.occurrences.get(base);
+        for(int i = 0; i <= position; i++) {
+            if(base == block.sequence[i])
+                accumulator++;
+        }
+        return accumulator;
+    }
+
+    /**
+     * The number of bases in the BWT as a whole.
+     * @return Number of bases.
+     */
+    public long length() {
+        return counts.getTotal();
+    }
+
+    /**
+     * Create a new BWT from the given reference sequence.
+     * @param referenceSequence Sequence from which to derive the BWT.
+     * @return reference sequence-derived BWT.
+     */
+    public static BWT createFromReferenceSequence(byte[] referenceSequence) {
+        SuffixArray suffixArray = SuffixArray.createFromReferenceSequence(referenceSequence);
+
+        byte[] bwt = new byte[(int)suffixArray.length()-1];
+        int bwtIndex = 0;
+        for(long suffixArrayIndex = 0; suffixArrayIndex < suffixArray.length(); suffixArrayIndex++) {
+            if(suffixArray.get(suffixArrayIndex) == 0)
+                continue;
+            bwt[bwtIndex++] = referenceSequence[(int)suffixArray.get(suffixArrayIndex)-1];
+        }
+
+        return new BWT(suffixArray.inverseSA0,suffixArray.occurrences,bwt);
+    }
+
+    /**
+     * Gets the base at a given position in the BWT.
+     * @param index The index to use.
+     * @return The base at that location.
+     */
+    protected byte getBase(long index) {
+        if(index == inverseSA0)
+            throw new ReviewedGATKException(String.format("Base at index %d does not have a text representation",index));
+
+        SequenceBlock block = getSequenceBlock(index);
+        int position = getSequencePosition(index);
+        return block.sequence[position];
+    }
+
+    private SequenceBlock getSequenceBlock(long index) {
+        // If the index is above the SA-1[0], remap it to the appropriate coordinate space.
+        if(index > inverseSA0) index--;
+        return sequenceBlocks[(int)(index/SEQUENCE_BLOCK_SIZE)];
+    }
+
+    private int getSequencePosition(long index) {
+        // If the index is above the SA-1[0], remap it to the appropriate coordinate space.
+        if(index > inverseSA0) index--;
+        return (int)(index%SEQUENCE_BLOCK_SIZE);
+    }
+
+    /**
+     * Create a set of sequence blocks from one long sequence.
+     * @param sequence Sequence from which to derive blocks.
+     * @return Array of sequence blocks containing data from the sequence.
+     */
+    private static SequenceBlock[] generateSequenceBlocks( byte[] sequence ) {
+        Counts occurrences = new Counts();
+
+        int numSequenceBlocks = PackUtils.numberOfPartitions(sequence.length,SEQUENCE_BLOCK_SIZE);
+        SequenceBlock[] sequenceBlocks = new SequenceBlock[numSequenceBlocks];
+
+        for( int block = 0; block < numSequenceBlocks; block++ ) {
+            int blockStart = block*SEQUENCE_BLOCK_SIZE;
+            int blockLength = Math.min(SEQUENCE_BLOCK_SIZE, sequence.length-blockStart);
+            byte[] subsequence = new byte[blockLength];
+
+            System.arraycopy(sequence,blockStart,subsequence,0,blockLength);
+
+            sequenceBlocks[block] = new SequenceBlock(blockStart,blockLength,occurrences.clone(),subsequence);
+
+            for( byte base: subsequence )
+                occurrences.increment(base);
+        }
+
+        return sequenceBlocks;
+    }
+}
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/alignment/reference/bwt/BWTReader.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/alignment/reference/bwt/BWTReader.java
new file mode 100644
index 0000000..9b28e2a
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/alignment/reference/bwt/BWTReader.java
@@ -0,0 +1,114 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.engine.alignment.reference.bwt;
+
+import org.broadinstitute.gatk.engine.alignment.reference.packing.BasePackedInputStream;
+import org.broadinstitute.gatk.engine.alignment.reference.packing.PackUtils;
+import org.broadinstitute.gatk.engine.alignment.reference.packing.UnsignedIntPackedInputStream;
+import org.broadinstitute.gatk.utils.exceptions.ReviewedGATKException;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.nio.ByteOrder;
+/**
+ * Reads a BWT from a given file.
+ *
+ * @author mhanna
+ * @version 0.1
+ */
+public class BWTReader {
+    /**
+     * Input stream from which to read BWT data.
+     */
+    private FileInputStream inputStream;
+
+    /**
+     * Create a new BWT reader.
+     * @param inputFile File in which the BWT is stored.
+     */
+    public BWTReader( File inputFile ) {
+        try {
+            this.inputStream = new FileInputStream(inputFile);
+        }
+        catch( FileNotFoundException ex ) {
+            throw new ReviewedGATKException("Unable to open input file", ex);
+        }
+    }
+
+    /**
+     * Read a BWT from the input stream.
+     * @return The BWT stored in the input stream.
+     */
+    public BWT read() {
+        UnsignedIntPackedInputStream uintPackedInputStream = new UnsignedIntPackedInputStream(inputStream, ByteOrder.LITTLE_ENDIAN);
+        BasePackedInputStream basePackedInputStream = new BasePackedInputStream<Integer>(Integer.class, inputStream, ByteOrder.LITTLE_ENDIAN);
+
+        long inverseSA0;
+        long[] count;
+        SequenceBlock[] sequenceBlocks;
+
+        try {
+            inverseSA0 = uintPackedInputStream.read();
+            count = new long[PackUtils.ALPHABET_SIZE];
+            uintPackedInputStream.read(count);
+
+            long bwtSize = count[PackUtils.ALPHABET_SIZE-1];
+            sequenceBlocks = new SequenceBlock[PackUtils.numberOfPartitions(bwtSize,BWT.SEQUENCE_BLOCK_SIZE)];
+            
+            for( int block = 0; block < sequenceBlocks.length; block++ ) {
+                int sequenceStart = block* BWT.SEQUENCE_BLOCK_SIZE;
+                int sequenceLength = (int)Math.min(BWT.SEQUENCE_BLOCK_SIZE,bwtSize-sequenceStart);
+
+                long[] occurrences = new long[PackUtils.ALPHABET_SIZE];
+                byte[] bwt = new byte[sequenceLength];
+
+                uintPackedInputStream.read(occurrences);
+                basePackedInputStream.read(bwt);
+
+                sequenceBlocks[block] = new SequenceBlock(sequenceStart,sequenceLength,new Counts(occurrences,false),bwt);
+            }
+        }
+        catch( IOException ex ) {
+            throw new ReviewedGATKException("Unable to read BWT from input stream.", ex);
+        }
+
+        return new BWT(inverseSA0, new Counts(count,true), sequenceBlocks);
+    }
+
+    /**
+     * Close the input stream.
+     */
+    public void close() {
+        try {
+            inputStream.close();
+        }
+        catch( IOException ex ) {
+            throw new ReviewedGATKException("Unable to close input file", ex);
+        }
+    }
+}
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/alignment/reference/bwt/BWTSupplementaryFileGenerator.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/alignment/reference/bwt/BWTSupplementaryFileGenerator.java
new file mode 100644
index 0000000..e60a78b
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/alignment/reference/bwt/BWTSupplementaryFileGenerator.java
@@ -0,0 +1,85 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.engine.alignment.reference.bwt;
+
+import htsjdk.samtools.reference.ReferenceSequenceFile;
+import htsjdk.samtools.reference.ReferenceSequenceFileFactory;
+import htsjdk.samtools.SAMSequenceDictionary;
+
+import java.io.File;
+import java.io.IOException;
+
+/**
+ * Generate BWA supplementary files (.ann, .amb) from the command line.
+ *
+ * @author mhanna
+ * @version 0.1
+ */
+public class BWTSupplementaryFileGenerator {
+    enum SupplementaryFileType { ANN, AMB } 
+
+    public static void main(String[] args) throws IOException {
+        if(args.length < 3)
+            usage("Incorrect number of arguments supplied");
+
+        File fastaFile = new File(args[0]);
+        File outputFile = new File(args[1]);
+        SupplementaryFileType outputType = null;
+        try {
+            outputType = Enum.valueOf(SupplementaryFileType.class,args[2]);
+        }
+        catch(IllegalArgumentException ex) {
+            usage("Invalid output type: " + args[2]);
+        }
+
+        ReferenceSequenceFile sequenceFile = ReferenceSequenceFileFactory.getReferenceSequenceFile(fastaFile);
+        SAMSequenceDictionary dictionary = sequenceFile.getSequenceDictionary();
+
+        switch(outputType) {
+            case ANN:
+                ANNWriter annWriter = new ANNWriter(outputFile);
+                annWriter.write(dictionary);
+                annWriter.close();
+                break;
+            case AMB:
+                AMBWriter ambWriter = new AMBWriter(outputFile);
+                ambWriter.writeEmpty(dictionary);
+                ambWriter.close();
+                break;
+            default:
+                usage("Unsupported output type: " + outputType);
+        }
+    }
+
+    /**
+     * Print usage information and exit.
+     */
+    private static void usage(String message) {
+        System.err.println(message);
+        System.err.println("Usage: BWTSupplementaryFileGenerator <fasta> <output file> <output type>");
+        System.exit(1);
+    }
+}
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/alignment/reference/bwt/BWTWriter.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/alignment/reference/bwt/BWTWriter.java
new file mode 100644
index 0000000..4f2a159
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/alignment/reference/bwt/BWTWriter.java
@@ -0,0 +1,96 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.engine.alignment.reference.bwt;
+
+import org.broadinstitute.gatk.engine.alignment.reference.packing.BasePackedOutputStream;
+import org.broadinstitute.gatk.engine.alignment.reference.packing.UnsignedIntPackedOutputStream;
+import org.broadinstitute.gatk.utils.exceptions.ReviewedGATKException;
+
+import java.io.*;
+import java.nio.ByteOrder;
+
+/**
+ * Writes an in-memory BWT to an outputstream.
+ *
+ * @author mhanna
+ * @version 0.1
+ */
+public class BWTWriter {
+    /**
+     * Input stream from which to read BWT data.
+     */
+    private final OutputStream outputStream;
+
+    /**
+     * Create a new BWT writer.
+     * @param outputFile File in which the BWT is stored.
+     */
+    public BWTWriter( File outputFile ) {
+        try {
+            this.outputStream = new BufferedOutputStream(new FileOutputStream(outputFile));
+        }
+        catch( FileNotFoundException ex ) {
+            throw new ReviewedGATKException("Unable to open output file", ex);
+        }
+    }
+
+    /**
+     * Write a BWT to the output stream.
+     * @param bwt Transform to be written to the output stream.
+     */
+    public void write( BWT bwt ) {
+        UnsignedIntPackedOutputStream intPackedOutputStream = new UnsignedIntPackedOutputStream(outputStream, ByteOrder.LITTLE_ENDIAN);
+        BasePackedOutputStream basePackedOutputStream = new BasePackedOutputStream<Integer>(Integer.class, outputStream, ByteOrder.LITTLE_ENDIAN);
+
+        try {
+            intPackedOutputStream.write(bwt.inverseSA0);
+            intPackedOutputStream.write(bwt.counts.toArray(true));
+
+            for( SequenceBlock block: bwt.sequenceBlocks ) {
+                intPackedOutputStream.write(block.occurrences.toArray(false));
+                basePackedOutputStream.write(block.sequence);
+            }
+
+            // The last block is the last set of counts in the structure.
+            intPackedOutputStream.write(bwt.counts.toArray(false));
+        }
+        catch( IOException ex ) {
+            throw new ReviewedGATKException("Unable to read BWT from input stream.", ex);
+        }
+    }
+
+    /**
+     * Close the input stream.
+     */
+    public void close() {
+        try {
+            outputStream.close();
+        }
+        catch( IOException ex ) {
+            throw new ReviewedGATKException("Unable to close input file", ex);
+        }
+    }
+}
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/alignment/reference/bwt/Bases.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/alignment/reference/bwt/Bases.java
new file mode 100644
index 0000000..d0cd849
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/alignment/reference/bwt/Bases.java
@@ -0,0 +1,133 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.engine.alignment.reference.bwt;
+
+import org.broadinstitute.gatk.utils.exceptions.ReviewedGATKException;
+
+import java.util.*;
+
+/**
+ * Enhanced enum representation of a base.
+ *
+ * @author mhanna
+ * @version 0.1
+ */
+public class Bases implements Iterable<Byte>
+{
+    public static final byte A = 'A';
+    public static final byte C = 'C';
+    public static final byte G = 'G';
+    public static final byte T = 'T';
+
+    public static final Bases instance = new Bases();
+
+    private static final List<Byte> allBases;
+
+    /**
+     * Representation of the base broken down by packed value.
+     */
+    private static final Map<Integer,Byte> basesByPack = new HashMap<Integer,Byte>();
+
+    static {
+        List<Byte> bases = new ArrayList<Byte>();
+        bases.add(A);
+        bases.add(C);
+        bases.add(G);
+        bases.add(T);
+        allBases = Collections.unmodifiableList(bases);
+
+        for(int i = 0; i < allBases.size(); i++)
+            basesByPack.put(i,allBases.get(i));
+    }
+
+    /**
+     * Create a new base with the given ascii representation and
+     * pack value.
+     */
+    private Bases() {
+    }
+
+    /**
+     * Return all possible bases.
+     * @return Byte representation of all bases.
+     */
+    public static Collection<Byte> allOf() {
+        return allBases;
+    }
+
+    /**
+     * Gets the number of known bases.
+     * @return The number of known bases.
+     */
+    public static int size() {
+        return allBases.size();
+    }
+
+    /**
+     * Gets an iterator over the total number of known base types.
+     * @return Iterator over all known bases.
+     */
+    public Iterator<Byte> iterator() {
+        return basesByPack.values().iterator();
+    }
+
+    /**
+     * Get the given base from the packed representation.
+     * @param pack Packed representation.
+     * @return base.
+     */
+    public static byte fromPack( int pack ) { return basesByPack.get(pack); }
+
+    /**
+     * Convert the given base to its packed value.
+     * @param ascii ASCII representation of the base.
+     * @return Packed value.
+     */
+    public static int toPack( byte ascii )
+    {
+        for( Map.Entry<Integer,Byte> entry: basesByPack.entrySet() ) {
+            if( entry.getValue().equals(ascii) )
+                return entry.getKey();
+        }
+        throw new ReviewedGATKException(String.format("Base %c is an invalid base to pack", (char)ascii));
+    }
+
+    /**
+     * Convert the ASCII representation of a base to its 'normalized' representation.
+     * @param base The base itself.
+     * @return The byte, if present.  Null if unknown.
+     */
+    public static Byte fromASCII( byte base ) {
+        Byte found = null;
+        for( Byte normalized: allBases ) {
+            if( normalized.equals(base) ) {
+                found = normalized;
+                break;
+            }
+        }
+        return found;
+    }
+}
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/alignment/reference/bwt/Counts.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/alignment/reference/bwt/Counts.java
new file mode 100644
index 0000000..c6684b5
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/alignment/reference/bwt/Counts.java
@@ -0,0 +1,176 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.engine.alignment.reference.bwt;
+
+import org.broadinstitute.gatk.utils.exceptions.ReviewedGATKException;
+
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * Counts of how many bases of each type have been seen.
+ *
+ * @author mhanna
+ * @version 0.1
+ */
+public class Counts implements Cloneable {
+    /**
+     * Internal representation of counts, broken down by ASCII value.
+     */
+    private Map<Byte,Long> counts = new HashMap<Byte,Long>();
+
+    /**
+     * Internal representation of cumulative counts, broken down by ASCII value.
+     */
+    private Map<Byte,Long> cumulativeCounts = new HashMap<Byte,Long>();
+
+    /**
+     * Create an empty Counts object with values A=0,C=0,G=0,T=0.
+     */
+    public Counts()
+    {
+        for(byte base: Bases.instance) {
+            counts.put(base,0L);
+            cumulativeCounts.put(base,0L);
+        }
+    }
+
+    /**
+     * Create a counts data structure with the given initial values. 
+     * @param data Count data, broken down by base.
+     * @param cumulative Whether the counts are cumulative, (count_G=numA+numC+numG,for example).
+     */
+    public Counts( long[] data, boolean cumulative ) {
+        if(cumulative) {
+            long priorCount = 0;
+            for(byte base: Bases.instance) {
+                long count = data[Bases.toPack(base)];
+                counts.put(base,count-priorCount);
+                cumulativeCounts.put(base,priorCount);
+                priorCount = count;
+            }
+        }
+        else {
+            long priorCount = 0;
+            for(byte base: Bases.instance) {
+                long count = data[Bases.toPack(base)];
+                counts.put(base,count);
+                cumulativeCounts.put(base,priorCount);
+                priorCount += count;
+            }
+        }
+    }
+
+    /**
+     * Convert to an array for persistence.
+     * @param cumulative Use a cumulative representation.
+     * @return Array of count values.
+     */
+    public long[] toArray(boolean cumulative) {
+        long[] countArray = new long[counts.size()];
+        if(cumulative) {
+            int index = 0;
+            boolean first = true;
+            for(byte base: Bases.instance) {
+                if(first) {
+                    first = false;
+                    continue;
+                }
+                countArray[index++] = getCumulative(base);
+            }
+            countArray[countArray.length-1] = getTotal();
+        }
+        else {
+            int index = 0;
+            for(byte base: Bases.instance)
+                countArray[index++] = counts.get(base);
+        }
+        return countArray;
+    }
+
+    /**
+     * Create a unique copy of the current object.
+     * @return A duplicate of this object.
+     */
+    public Counts clone() {
+        Counts other;
+        try {
+            other = (Counts)super.clone();
+        }
+        catch(CloneNotSupportedException ex) {
+            throw new ReviewedGATKException("Unable to clone counts object", ex);
+        }
+        other.counts = new HashMap<Byte,Long>(counts);
+        other.cumulativeCounts = new HashMap<Byte,Long>(cumulativeCounts);
+        return other;
+    }
+
+    /**
+     * Increment the number of bases seen at the given location.
+     * @param base Base to increment.
+     */
+    public void increment(byte base) {
+        counts.put(base,counts.get(base)+1);
+        boolean increment = false;
+        for(byte cumulative: Bases.instance) {
+            if(increment) cumulativeCounts.put(cumulative,cumulativeCounts.get(cumulative)+1);
+            increment |= (cumulative == base);
+        }
+    }
+
+    /**
+     * Gets a count of the number of bases seen at a given location.
+     * Note that counts in this case are not cumulative (counts for A,C,G,T
+     * are independent).
+     * @param base Base for which to query counts.
+     * @return Number of bases of this type seen.
+     */
+    public long get(byte base) {
+        return counts.get(base);
+    }
+
+    /**
+     * Gets a count of the number of bases seen before this base.
+     * Note that counts in this case are cumulative.
+     * @param base Base for which to query counts.
+     * @return Number of bases of this type seen.
+     */
+    public long getCumulative(byte base) {
+        return cumulativeCounts.get(base);
+    }
+
+    /**
+     * How many total bases are represented by this count structure?
+     * @return Total bases represented.
+     */
+    public long getTotal() {
+        int accumulator = 0;
+        for(byte base: Bases.instance) {
+            accumulator += get(base);    
+        }
+        return accumulator;
+    }
+}
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/alignment/reference/bwt/CreateBWTFromReference.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/alignment/reference/bwt/CreateBWTFromReference.java
new file mode 100644
index 0000000..baa5ebe
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/alignment/reference/bwt/CreateBWTFromReference.java
@@ -0,0 +1,200 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.engine.alignment.reference.bwt;
+
+import htsjdk.samtools.reference.ReferenceSequence;
+import htsjdk.samtools.reference.ReferenceSequenceFile;
+import htsjdk.samtools.reference.ReferenceSequenceFileFactory;
+import org.broadinstitute.gatk.engine.alignment.reference.packing.PackUtils;
+import org.broadinstitute.gatk.utils.exceptions.ReviewedGATKException;
+
+import java.io.File;
+import java.io.IOException;
+
+/**
+ * Create a suffix array data structure.
+ *
+ * @author mhanna
+ * @version 0.1
+ */
+public class CreateBWTFromReference {
+    private byte[] loadReference( File inputFile ) {
+        // Read in the first sequence in the input file
+        ReferenceSequenceFile reference = ReferenceSequenceFileFactory.getReferenceSequenceFile(inputFile);
+        ReferenceSequence sequence = reference.nextSequence();
+        return sequence.getBases();
+    }
+
+    private byte[] loadReverseReference( File inputFile ) {
+        ReferenceSequenceFile reference = ReferenceSequenceFileFactory.getReferenceSequenceFile(inputFile);
+        ReferenceSequence sequence = reference.nextSequence();
+        PackUtils.reverse(sequence.getBases());
+        return sequence.getBases();
+    }
+
+    private Counts countOccurrences( byte[] sequence ) {
+        Counts occurrences = new Counts();
+        for( byte base: sequence )
+            occurrences.increment(base);
+        return occurrences;
+    }
+
+    private long[] createSuffixArray( byte[] sequence ) {
+        return SuffixArray.createFromReferenceSequence(sequence).sequence;
+    }
+
+    private long[] invertSuffixArray( long[] suffixArray ) {
+        long[] inverseSuffixArray = new long[suffixArray.length];
+        for( int i = 0; i < suffixArray.length; i++ )
+            inverseSuffixArray[(int)suffixArray[i]] = i;
+        return inverseSuffixArray;
+    }
+
+    private long[] createCompressedSuffixArray( int[] suffixArray, int[] inverseSuffixArray ) {
+        long[] compressedSuffixArray = new long[suffixArray.length];
+        compressedSuffixArray[0] = inverseSuffixArray[0];
+        for( int i = 1; i < suffixArray.length; i++ )
+            compressedSuffixArray[i] = inverseSuffixArray[suffixArray[i]+1];
+        return compressedSuffixArray;
+    }
+
+    private long[] createInversedCompressedSuffixArray( int[] compressedSuffixArray ) {
+        long[] inverseCompressedSuffixArray = new long[compressedSuffixArray.length];
+        for( int i = 0; i < compressedSuffixArray.length; i++ )
+            inverseCompressedSuffixArray[compressedSuffixArray[i]] = i;
+        return inverseCompressedSuffixArray;
+    }
+
+    public static void main( String argv[] ) throws IOException {
+        if( argv.length != 5 ) {
+            System.out.println("USAGE: CreateBWTFromReference <input>.fasta <output bwt> <output rbwt> <output sa> <output rsa>");
+            return;
+        }
+
+        String inputFileName = argv[0];
+        File inputFile = new File(inputFileName);
+
+        String bwtFileName = argv[1];
+        File bwtFile = new File(bwtFileName);
+
+        String rbwtFileName = argv[2];
+        File rbwtFile = new File(rbwtFileName);
+
+        String saFileName = argv[3];
+        File saFile = new File(saFileName);
+
+        String rsaFileName = argv[4];
+        File rsaFile = new File(rsaFileName);
+
+        CreateBWTFromReference creator = new CreateBWTFromReference();
+
+        byte[] sequence = creator.loadReference(inputFile);
+        byte[] reverseSequence = creator.loadReverseReference(inputFile);
+
+        // Count the occurences of each given base.
+        Counts occurrences = creator.countOccurrences(sequence);
+        System.out.printf("Occurrences: a=%d, c=%d, g=%d, t=%d%n",occurrences.getCumulative(Bases.A),
+                                                                  occurrences.getCumulative(Bases.C),
+                                                                  occurrences.getCumulative(Bases.G),
+                                                                  occurrences.getCumulative(Bases.T));
+
+        // Generate the suffix array and print diagnostics.
+        long[] suffixArrayData = creator.createSuffixArray(sequence);
+        long[] reverseSuffixArrayData = creator.createSuffixArray(reverseSequence);
+
+        // Invert the suffix array and print diagnostics.
+        long[] inverseSuffixArray = creator.invertSuffixArray(suffixArrayData);
+        long[] reverseInverseSuffixArray = creator.invertSuffixArray(reverseSuffixArrayData);
+
+        SuffixArray suffixArray = new SuffixArray( inverseSuffixArray[0], occurrences, suffixArrayData );
+        SuffixArray reverseSuffixArray = new SuffixArray( reverseInverseSuffixArray[0], occurrences, reverseSuffixArrayData );
+
+        /*
+        // Create the data structure for the compressed suffix array and print diagnostics.
+        int[] compressedSuffixArray = creator.createCompressedSuffixArray(suffixArray.sequence,inverseSuffixArray);
+        int reconstructedInverseSA = compressedSuffixArray[0];
+        for( int i = 0; i < 8; i++ ) {
+            System.out.printf("compressedSuffixArray[%d] = %d (SA-1[%d] = %d)%n", i, compressedSuffixArray[i], i, reconstructedInverseSA);
+            reconstructedInverseSA = compressedSuffixArray[reconstructedInverseSA];
+        }
+
+        // Create the data structure for the inverse compressed suffix array and print diagnostics.
+        int[] inverseCompressedSuffixArray = creator.createInversedCompressedSuffixArray(compressedSuffixArray);
+        for( int i = 0; i < 8; i++ ) {
+            System.out.printf("inverseCompressedSuffixArray[%d] = %d%n", i, inverseCompressedSuffixArray[i]);
+        }
+        */
+
+        // Create the BWT.
+        BWT bwt = BWT.createFromReferenceSequence(sequence);
+        BWT reverseBWT = BWT.createFromReferenceSequence(reverseSequence);
+
+        byte[] bwtSequence = bwt.getSequence();
+        System.out.printf("BWT: %s... (length = %d)%n", new String(bwtSequence,0,80),bwt.length());
+
+        BWTWriter bwtWriter = new BWTWriter(bwtFile);
+        bwtWriter.write(bwt);
+        bwtWriter.close();
+
+        BWTWriter reverseBWTWriter = new BWTWriter(rbwtFile);
+        reverseBWTWriter.write(reverseBWT);
+        reverseBWTWriter.close();
+
+        /*
+        SuffixArrayWriter saWriter = new SuffixArrayWriter(saFile);
+        saWriter.write(suffixArray);
+        saWriter.close();
+
+        SuffixArrayWriter reverseSAWriter = new SuffixArrayWriter(rsaFile);
+        reverseSAWriter.write(reverseSuffixArray);
+        reverseSAWriter.close();
+        */
+
+        File existingBWTFile = new File(inputFileName+".bwt");
+        BWTReader existingBWTReader = new BWTReader(existingBWTFile);
+        BWT existingBWT = existingBWTReader.read();
+
+        byte[] existingBWTSequence = existingBWT.getSequence();
+        System.out.printf("Existing BWT: %s... (length = %d)%n",new String(existingBWTSequence,0,80),existingBWT.length());
+
+        for( int i = 0; i < bwt.length(); i++ ) {
+            if( bwtSequence[i] != existingBWTSequence[i] )
+                throw new ReviewedGATKException("BWT mismatch at " + i);
+        }
+
+        File existingSAFile = new File(inputFileName+".sa");
+        SuffixArrayReader existingSuffixArrayReader = new SuffixArrayReader(existingSAFile,existingBWT);
+        SuffixArray existingSuffixArray = existingSuffixArrayReader.read();
+
+        for(int i = 0; i < suffixArray.length(); i++) {
+            if( i % 10000 == 0 )
+                System.out.printf("Validating suffix array entry %d%n", i);
+            if( suffixArray.get(i) != existingSuffixArray.get(i) )
+                throw new ReviewedGATKException(String.format("Suffix array mismatch at %d; SA is %d; should be %d",i,existingSuffixArray.get(i),suffixArray.get(i)));
+        }
+    }
+
+}
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/alignment/reference/bwt/SequenceBlock.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/alignment/reference/bwt/SequenceBlock.java
new file mode 100644
index 0000000..555e7cc
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/alignment/reference/bwt/SequenceBlock.java
@@ -0,0 +1,66 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.engine.alignment.reference.bwt;
+
+/**
+ * Models a block of bases within the BWT.
+ */
+public class SequenceBlock {
+    /**
+     * Start position of this sequence within the BWT.
+     */
+    public final int sequenceStart;
+
+    /**
+     * Length of this sequence within the BWT.
+     */
+    public final int sequenceLength;
+
+
+    /**
+     * Occurrences of each letter up to this sequence block.
+     */
+    public final Counts occurrences;
+
+    /**
+     * Sequence for this segment.
+     */
+    public final byte[] sequence;
+
+    /**
+     * Create a new block within this BWT.
+     * @param sequenceStart Starting position of this sequence within the BWT.
+     * @param sequenceLength Length of this sequence.
+     * @param occurrences How many of each base has been seen before this sequence began.
+     * @param sequence The actual sequence from the BWT.
+     */
+    public SequenceBlock( int sequenceStart, int sequenceLength, Counts occurrences, byte[] sequence ) {
+        this.sequenceStart = sequenceStart;
+        this.sequenceLength = sequenceLength;
+        this.occurrences = occurrences;
+        this.sequence = sequence;
+    }
+}
\ No newline at end of file
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/alignment/reference/bwt/SuffixArray.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/alignment/reference/bwt/SuffixArray.java
new file mode 100644
index 0000000..d1edfe5
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/alignment/reference/bwt/SuffixArray.java
@@ -0,0 +1,183 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.engine.alignment.reference.bwt;
+
+import htsjdk.samtools.util.StringUtil;
+import org.broadinstitute.gatk.utils.exceptions.ReviewedGATKException;
+
+import java.util.Comparator;
+import java.util.TreeSet;
+
+/**
+ * An in-memory representation of a suffix array.
+ *
+ * @author mhanna
+ * @version 0.1
+ */
+public class SuffixArray {
+    public final long inverseSA0;
+    public final Counts occurrences;
+
+    /**
+     * The elements of the sequence actually stored in memory.
+     */
+    protected final long[] sequence;
+
+    /**
+     * How often are individual elements in the sequence actually stored
+     * in memory, as opposed to being calculated on the fly?
+     */
+    protected final int sequenceInterval;
+
+    /**
+     * The BWT used to calculate missing portions of the sequence.
+     */
+    protected final BWT bwt;
+
+    public SuffixArray(long inverseSA0, Counts occurrences, long[] sequence) {
+        this(inverseSA0,occurrences,sequence,1,null);
+    }
+
+    /**
+     * Creates a new sequence array with the given inverse SA, occurrences, and values.
+     * @param inverseSA0 Inverse SA entry for the first element.
+     * @param occurrences Cumulative number of occurrences of A,C,G,T, in order.
+     * @param sequence The full suffix array.
+     * @param sequenceInterval How frequently is the sequence interval stored.
+     * @param bwt bwt used to infer the remaining entries in the BWT.
+     */
+    public SuffixArray(long inverseSA0, Counts occurrences, long[] sequence, int sequenceInterval, BWT bwt) {
+        this.inverseSA0 = inverseSA0;
+        this.occurrences = occurrences;
+        this.sequence = sequence;
+        this.sequenceInterval = sequenceInterval;
+        this.bwt = bwt;
+
+        if(sequenceInterval != 1 && bwt == null)
+            throw new ReviewedGATKException("A BWT must be provided if the sequence interval is not 1");
+    }
+
+    /**
+     * Retrieves the length of the sequence array.
+     * @return Length of the suffix array.
+     */
+    public long length() {
+        if( bwt != null )
+            return bwt.length()+1;
+        else
+            return sequence.length;
+    }
+
+    /**
+     * Get the suffix array value at a given sequence.
+     * @param index Index at which to retrieve the suffix array vaule.
+     * @return The suffix array value at that entry.
+     */
+    public long get(long index) {
+        int iterations = 0;
+        while(index%sequenceInterval != 0) {
+            // The inverseSA0 ('$') doesn't have a usable ASCII representation; it must be treated as a special case.
+            if(index == inverseSA0)
+                index = 0;
+            else {
+                byte base = bwt.getBase(index);
+                index = bwt.counts(base) + bwt.occurrences(base,index);
+            }
+            iterations++;
+        }
+        return (sequence[(int)(index/sequenceInterval)]+iterations) % length();
+    }
+
+    /**
+     * Create a suffix array from a given reference sequence.
+     * @param sequence The reference sequence to use when building the suffix array.
+     * @return a constructed suffix array.
+     */
+    public static SuffixArray createFromReferenceSequence(byte[] sequence) {
+        // The builder for the suffix array.  Use an integer in this case because
+        // Java arrays can only hold an integer.
+        TreeSet<Integer> suffixArrayBuilder = new TreeSet<Integer>(new SuffixArrayComparator(sequence));
+
+        Counts occurrences = new Counts();
+        for( byte base: sequence )
+            occurrences.increment(base);
+
+        // Build out the suffix array using a custom comparator.
+        for( int i = 0; i <= sequence.length; i++ )
+            suffixArrayBuilder.add(i);
+
+        // Copy the suffix array into an array.
+        long[] suffixArray = new long[suffixArrayBuilder.size()];
+        int i = 0;
+        for( Integer element: suffixArrayBuilder )
+            suffixArray[i++] = element;
+
+        // Find the first element in the inverse suffix array.
+        long inverseSA0 = -1;
+        for(i = 0; i < suffixArray.length; i++) {
+            if(suffixArray[i] == 0)
+                inverseSA0 = i;
+        }
+        if(inverseSA0 < 0)
+            throw new ReviewedGATKException("Unable to find first inverse SA entry in generated suffix array.");
+
+        return new SuffixArray(inverseSA0,occurrences,suffixArray);
+    }    
+
+    /**
+     * Compares two suffix arrays of the given sequence.  Will return whichever string appears
+     * first in lexicographic order.
+     */
+    private static class SuffixArrayComparator implements Comparator<Integer> {
+        /**
+         * The data source for all suffix arrays.
+         */
+        private final String sequence;
+
+        /**
+         * Create a new comparator.
+         * @param sequence Reference sequence to use as basis for comparison.
+         */
+        public SuffixArrayComparator( byte[] sequence ) {
+            // Processing the suffix array tends to be easier as a string.
+            this.sequence = StringUtil.bytesToString(sequence);
+        }
+
+        /**
+         * Compare the two given suffix arrays.  Criteria for comparison is the lexicographic order of
+         * the two substrings sequence[lhs:], sequence[rhs:].
+         * @param lhs Left-hand side of comparison.
+         * @param rhs Right-hand side of comparison.
+         * @return How the suffix arrays represented by lhs, rhs compare.
+         */
+        public int compare( Integer lhs, Integer rhs ) {
+            String lhsSuffixArray = sequence.substring(lhs);
+            String rhsSuffixArray = sequence.substring(rhs);
+            return lhsSuffixArray.compareTo(rhsSuffixArray);
+        }
+    }
+
+}
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/alignment/reference/bwt/SuffixArrayReader.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/alignment/reference/bwt/SuffixArrayReader.java
new file mode 100644
index 0000000..dc8cdc0
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/alignment/reference/bwt/SuffixArrayReader.java
@@ -0,0 +1,110 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.engine.alignment.reference.bwt;
+
+import org.broadinstitute.gatk.engine.alignment.reference.packing.PackUtils;
+import org.broadinstitute.gatk.engine.alignment.reference.packing.UnsignedIntPackedInputStream;
+import org.broadinstitute.gatk.utils.exceptions.ReviewedGATKException;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.nio.ByteOrder;
+
+/**
+ * A reader for suffix arrays in permanent storage.
+ *
+ * @author mhanna
+ * @version 0.1
+ */
+public class SuffixArrayReader {
+    /**
+     * Input stream from which to read suffix array data.
+     */
+    private FileInputStream inputStream;
+
+    /**
+     * BWT to use to fill in missing data.
+     */
+    private BWT bwt;
+
+    /**
+     * Create a new suffix array reader.
+     * @param inputFile File in which the suffix array is stored.
+     * @param bwt BWT to use when filling in missing data.
+     */
+    public SuffixArrayReader(File inputFile, BWT bwt) {
+        try {
+            this.inputStream = new FileInputStream(inputFile);
+            this.bwt = bwt;
+        }
+        catch( FileNotFoundException ex ) {
+            throw new ReviewedGATKException("Unable to open input file", ex);
+        }
+    }
+
+    /**
+     * Read a suffix array from the input stream.
+     * @return The suffix array stored in the input stream.
+     */
+    public SuffixArray read() {
+        UnsignedIntPackedInputStream uintPackedInputStream = new UnsignedIntPackedInputStream(inputStream, ByteOrder.LITTLE_ENDIAN);
+
+        long inverseSA0;
+        long[] occurrences;
+        long[] suffixArray;
+        int suffixArrayInterval;
+
+        try {
+            inverseSA0 = uintPackedInputStream.read();
+            occurrences = new long[PackUtils.ALPHABET_SIZE];
+            uintPackedInputStream.read(occurrences);
+            // Throw away the suffix array size in bytes and use the occurrences table directly.
+            suffixArrayInterval = (int)uintPackedInputStream.read();
+            suffixArray = new long[(int)((occurrences[occurrences.length-1]+suffixArrayInterval-1)/suffixArrayInterval)];
+            uintPackedInputStream.read(suffixArray);
+        }
+        catch( IOException ex ) {
+            throw new ReviewedGATKException("Unable to read BWT from input stream.", ex);
+        }
+
+        return new SuffixArray(inverseSA0, new Counts(occurrences,true), suffixArray, suffixArrayInterval, bwt);
+    }
+
+
+    /**
+     * Close the input stream.
+     */
+    public void close() {
+        try {
+            inputStream.close();
+        }
+        catch( IOException ex ) {
+            throw new ReviewedGATKException("Unable to close input file", ex);
+        }
+    }    
+}
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/alignment/reference/bwt/SuffixArrayWriter.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/alignment/reference/bwt/SuffixArrayWriter.java
new file mode 100644
index 0000000..df152b9
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/alignment/reference/bwt/SuffixArrayWriter.java
@@ -0,0 +1,92 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.engine.alignment.reference.bwt;
+
+import org.broadinstitute.gatk.engine.alignment.reference.packing.UnsignedIntPackedOutputStream;
+import org.broadinstitute.gatk.utils.exceptions.ReviewedGATKException;
+
+import java.io.*;
+import java.nio.ByteOrder;
+
+/**
+ * Javadoc goes here.
+ *
+ * @author mhanna
+ * @version 0.1
+ */
+public class SuffixArrayWriter {
+    /**
+     * Input stream from which to read suffix array data.
+     */
+    private OutputStream outputStream;
+
+    /**
+     * Create a new suffix array reader.
+     * @param outputFile File in which the suffix array is stored.
+     */
+    public SuffixArrayWriter( File outputFile ) {
+        try {
+            this.outputStream = new BufferedOutputStream(new FileOutputStream(outputFile));
+        }
+        catch( FileNotFoundException ex ) {
+            throw new ReviewedGATKException("Unable to open input file", ex);
+        }
+    }
+
+    /**
+     * Write a suffix array to the output stream.
+     * @param suffixArray suffix array to write.
+     */
+    public void write(SuffixArray suffixArray) {
+        UnsignedIntPackedOutputStream uintPackedOutputStream = new UnsignedIntPackedOutputStream(outputStream, ByteOrder.LITTLE_ENDIAN);
+
+        try {
+            uintPackedOutputStream.write(suffixArray.inverseSA0);
+            uintPackedOutputStream.write(suffixArray.occurrences.toArray(true));
+            // How frequently the suffix array entry is placed.
+            uintPackedOutputStream.write(1);
+            // Length of the suffix array.
+            uintPackedOutputStream.write(suffixArray.length()-1);
+            uintPackedOutputStream.write(suffixArray.sequence,1,suffixArray.sequence.length-1);
+        }
+        catch( IOException ex ) {
+            throw new ReviewedGATKException("Unable to read BWT from input stream.", ex);
+        }
+    }
+
+
+    /**
+     * Close the input stream.
+     */
+    public void close() {
+        try {
+            outputStream.close();
+        }
+        catch( IOException ex ) {
+            throw new ReviewedGATKException("Unable to close input file", ex);
+        }
+    }
+}
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/alignment/reference/packing/BasePackedInputStream.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/alignment/reference/packing/BasePackedInputStream.java
new file mode 100644
index 0000000..727a378
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/alignment/reference/packing/BasePackedInputStream.java
@@ -0,0 +1,120 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.engine.alignment.reference.packing;
+
+import org.broadinstitute.gatk.utils.exceptions.ReviewedGATKException;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.nio.ByteBuffer;
+import java.nio.ByteOrder;
+import java.nio.channels.FileChannel;
+
+/**
+ * Reads a packed version of the input stream.
+ *
+ * @author mhanna
+ * @version 0.1
+ */
+public class BasePackedInputStream<T> {
+    /**
+     * Type of object to unpack.
+     */
+    private final Class<T> type;
+
+    /**
+     * Ultimate source for packed bases.
+     */
+    private final FileInputStream targetInputStream;
+
+    /**
+     * Channel source for packed bases.
+     */
+    private final FileChannel targetInputChannel;
+
+    /**
+     * A fixed-size buffer for word-packed data.
+     */
+    private final ByteOrder byteOrder;
+
+    /**
+     * How many bases are in a given packed word.
+     */
+    private final int basesPerPackedWord = PackUtils.bitsInType(Integer.class)/PackUtils.BITS_PER_BASE;
+
+    /**
+     * How many bytes in an integer?
+     */
+    private final int bytesPerInteger = PackUtils.bitsInType(Integer.class)/PackUtils.BITS_PER_BYTE;
+
+
+    public BasePackedInputStream( Class<T> type, File inputFile, ByteOrder byteOrder ) throws FileNotFoundException {
+        this(type,new FileInputStream(inputFile),byteOrder);
+    }
+
+    public BasePackedInputStream( Class<T> type, FileInputStream inputStream, ByteOrder byteOrder ) {
+        if( type != Integer.class )
+            throw new ReviewedGATKException("Only bases packed into 32-bit words are currently supported by this input stream.  Type specified: " + type.getName());
+        this.type = type;
+        this.targetInputStream = inputStream;
+        this.targetInputChannel = inputStream.getChannel();
+        this.byteOrder = byteOrder;
+    }
+
+    /**
+     * Read the entire contents of the input stream.
+     * @param bwt array into which bases should be read.
+     * @throws IOException if an I/O error occurs.
+     */
+    public void read(byte[] bwt) throws IOException {
+        read(bwt,0,bwt.length);
+    }
+
+    /**
+     * Read the next <code>length</code> bases into the bwt array, starting at the given offset.
+     * @param bwt array holding the given data.
+     * @param offset target position in the bases array into which bytes should be written.
+     * @param length number of bases to read from the stream.
+     * @throws IOException if an I/O error occurs.
+     */
+    public void read(byte[] bwt, int offset, int length) throws IOException {
+        int bufferWidth = ((bwt.length+basesPerPackedWord-1)/basesPerPackedWord)*bytesPerInteger;
+        ByteBuffer buffer = ByteBuffer.allocate(bufferWidth).order(byteOrder);
+        targetInputChannel.read(buffer);
+        targetInputChannel.position(targetInputChannel.position()+buffer.remaining());
+        buffer.flip();
+
+        int packedWord = 0;
+        int i = 0;
+        while(i < length) {
+            if(i % basesPerPackedWord == 0) packedWord = buffer.getInt();
+            int position = basesPerPackedWord - i%basesPerPackedWord - 1;
+            bwt[offset+i++] = PackUtils.unpackBase((byte)((packedWord >> position*PackUtils.BITS_PER_BASE) & 0x3));            
+        }
+    }
+}
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/alignment/reference/packing/BasePackedOutputStream.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/alignment/reference/packing/BasePackedOutputStream.java
new file mode 100644
index 0000000..b3dbba8
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/alignment/reference/packing/BasePackedOutputStream.java
@@ -0,0 +1,165 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.engine.alignment.reference.packing;
+
+import org.broadinstitute.gatk.utils.exceptions.ReviewedGATKException;
+
+import java.io.*;
+import java.nio.ByteBuffer;
+import java.nio.ByteOrder;
+
+/**
+ * A general-purpose stream for writing packed bases.
+ *
+ * @author mhanna
+ * @version 0.1
+ */
+public class BasePackedOutputStream<T> {
+    /**
+     * Type of object to pack.
+     */
+    private final Class<T> type;
+
+    /**
+     * How many bases can be stored in the given data structure?
+     */
+    private final int basesPerType;
+
+    /**
+     * Ultimate target for the packed bases.
+     */
+    private final OutputStream targetOutputStream;
+
+    /**
+     * A fixed-size buffer for word-packed data.
+     */
+    private final ByteBuffer buffer;
+
+    public BasePackedOutputStream( Class<T> type, File outputFile, ByteOrder byteOrder ) throws FileNotFoundException {
+        this(type,new BufferedOutputStream(new FileOutputStream(outputFile)),byteOrder);
+    }
+
+    /**
+     * Write packed bases to the given output stream.
+     * @param type Type of data to pack bases into.
+     * @param outputStream Output stream to which to write packed bases.
+     * @param byteOrder Switch between big endian / little endian when reading / writing files.
+     */
+    public BasePackedOutputStream( Class<T> type, OutputStream outputStream, ByteOrder byteOrder) {
+        this.targetOutputStream = outputStream;
+        this.type = type;
+        basesPerType = PackUtils.bitsInType(type)/PackUtils.BITS_PER_BASE;
+        this.buffer = ByteBuffer.allocate(basesPerType/PackUtils.ALPHABET_SIZE).order(byteOrder);
+    }
+
+    /**
+     * Writes the given base to the output stream.  Will write only this base; no packing will be performed.
+     * @param base List of bases to write.
+     * @throws IOException if an I/O error occurs.
+     */
+    public void write( int base ) throws IOException {
+        write( new byte[] { (byte)base } );
+    }
+
+    /**
+     * Writes an array of bases to the target output stream.
+     * @param bases List of bases to write.
+     * @throws IOException if an I/O error occurs.
+     */
+    public void write( byte[] bases ) throws IOException {
+        write(bases,0,bases.length);
+    }
+
+    /**
+     * Writes a subset of the array of bases to the output stream.
+     * @param bases List of bases to write.
+     * @param offset site at which to start writing.
+     * @param length number of bases to write.
+     * @throws IOException if an I/O error occurs.
+     */
+    public void write( byte[] bases, int offset, int length ) throws IOException {
+        int packedBases = 0;
+        int positionInPack = 0;
+
+        for( int base = offset; base < offset+length; base++ ) {
+            packedBases = packBase(bases[base], packedBases, positionInPack);
+
+            // Increment the packed counter.  If all possible bases have been squeezed into this byte, write it out.
+            positionInPack = ++positionInPack % basesPerType;
+            if( positionInPack == 0 ) {
+                writePackedBases(packedBases);
+                packedBases = 0;
+            }
+        }
+
+        if( positionInPack > 0 )
+            writePackedBases(packedBases);
+    }
+
+    /**
+     * Flush the contents of the OutputStream to disk.
+     * @throws IOException if an I/O error occurs.
+     */
+    public void flush() throws IOException {
+        targetOutputStream.flush();
+    }
+
+    /**
+     * Closes the given output stream.
+     * @throws IOException if an I/O error occurs.
+     */
+    public void close() throws IOException {
+        targetOutputStream.close();
+    }
+
+    /**
+     * Pack the given base into the basepack.
+     * @param base The base to pack.
+     * @param basePack Target for the pack operation.
+     * @param position Position within the pack to which to add the base.
+     * @return The packed integer.
+     */
+    private int packBase( byte base, int basePack, int position ) {
+        basePack |= (PackUtils.packBase(base) << 2*(basesPerType-position-1));
+        return basePack;
+    }    
+
+    /**
+     * Write the given packed base structure to the output file.
+     * @param packedBases Packed bases to write.
+     * @throws IOException on error writing to the file.
+     */
+    private void writePackedBases(int packedBases) throws IOException {
+        buffer.rewind();
+        if( type == Integer.class )
+            buffer.putInt(packedBases);
+        else if( type == Byte.class )
+            buffer.put((byte)packedBases);
+        else
+            throw new ReviewedGATKException("Cannot pack bases into type " + type.getName());
+        targetOutputStream.write(buffer.array());        
+    }
+}
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/alignment/reference/packing/CreatePACFromReference.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/alignment/reference/packing/CreatePACFromReference.java
new file mode 100644
index 0000000..fac3d92
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/alignment/reference/packing/CreatePACFromReference.java
@@ -0,0 +1,64 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.engine.alignment.reference.packing;
+
+import htsjdk.samtools.reference.ReferenceSequence;
+import htsjdk.samtools.reference.ReferenceSequenceFile;
+import htsjdk.samtools.reference.ReferenceSequenceFileFactory;
+
+import java.io.File;
+import java.io.IOException;
+
+/**
+ * Generate a .PAC file from a given reference.
+ *
+ * @author hanna
+ * @version 0.1
+ */
+
+public class CreatePACFromReference {
+    public static void main( String argv[] ) throws IOException {
+        if( argv.length != 3 ) {
+            System.out.println("USAGE: CreatePACFromReference <input>.fasta <output pac> <output rpac>");
+            return;
+        }
+
+        // Read in the first sequence in the input file
+        String inputFileName = argv[0];
+        File inputFile = new File(inputFileName);
+        ReferenceSequenceFile reference = ReferenceSequenceFileFactory.getReferenceSequenceFile(inputFile);
+        ReferenceSequence sequence = reference.nextSequence();
+
+        // Target file for output
+        PackUtils.writeReferenceSequence( new File(argv[1]), sequence.getBases() );
+
+        // Reverse the bases in the reference
+        PackUtils.reverse(sequence.getBases());
+
+        // Target file for output
+        PackUtils.writeReferenceSequence( new File(argv[2]), sequence.getBases() );
+    }
+}
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/alignment/reference/packing/PackUtils.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/alignment/reference/packing/PackUtils.java
new file mode 100644
index 0000000..e60780a
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/alignment/reference/packing/PackUtils.java
@@ -0,0 +1,160 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.engine.alignment.reference.packing;
+
+import org.broadinstitute.gatk.utils.exceptions.ReviewedGATKException;
+
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.OutputStream;
+import java.nio.ByteOrder;
+
+/**
+ * Utilities designed for packing / unpacking bases.
+ *
+ * @author mhanna
+ * @version 0.1
+ */
+public class PackUtils {
+    /**
+     * How many possible bases can be encoded?
+     */
+    public static final int ALPHABET_SIZE = 4;
+
+    /**
+     * How many bits does it take to store a single base?
+     */
+    public static final int BITS_PER_BASE = (int)(Math.log(ALPHABET_SIZE)/Math.log(2));
+
+    /**
+     * How many bits fit into a single byte?
+     */
+    public static final int BITS_PER_BYTE = 8;
+
+    /**
+     * Writes a reference sequence to a PAC file.
+     * @param outputFile Filename for the PAC file.
+     * @param referenceSequence Reference sequence to write.
+     * @throws IOException If there's a problem writing to the output file.
+     */
+    public static void writeReferenceSequence( File outputFile, byte[] referenceSequence ) throws IOException {
+        OutputStream outputStream = new FileOutputStream(outputFile);
+
+        BasePackedOutputStream<Byte> basePackedOutputStream = new BasePackedOutputStream<Byte>(Byte.class, outputStream, ByteOrder.BIG_ENDIAN);
+        basePackedOutputStream.write(referenceSequence);
+
+        outputStream.write(referenceSequence.length%PackUtils.ALPHABET_SIZE);
+
+        outputStream.close();
+    }
+
+
+    /**
+     * How many bits can a given type hold?
+     * @param type Type to test.
+     * @return Number of bits that the given type can hold.
+     */
+    public static int bitsInType( Class<?> type ) {
+        try {
+            long typeSize = type.getField("MAX_VALUE").getLong(null) - type.getField("MIN_VALUE").getLong(null)+1;
+            long intTypeSize = (long)Integer.MAX_VALUE - (long)Integer.MIN_VALUE + 1;
+            if( typeSize > intTypeSize )
+                throw new ReviewedGATKException("Cannot determine number of bits available in type: " + type.getName());
+            return (int)(Math.log(typeSize)/Math.log(2));
+        }
+        catch( NoSuchFieldException ex ) {
+            throw new ReviewedGATKException("Cannot determine number of bits available in type: " + type.getName(),ex);
+        }
+        catch( IllegalAccessException ex ) {
+            throw new ReviewedGATKException("Cannot determine number of bits available in type: " + type.getName(),ex);
+        }
+    }
+
+    /**
+     * Gets the two-bit representation of a base.  A=00b, C=01b, G=10b, T=11b.
+     * @param base ASCII value for the base to pack.
+     * @return A byte from 0-3 indicating the base's packed value.
+     */
+    public static byte packBase(byte base) {
+        switch( base ) {
+            case 'A':
+                return 0;
+            case 'C':
+                return 1;
+            case 'G':
+                return 2;
+            case 'T':
+                return 3;
+            default:
+                throw new ReviewedGATKException("Unknown base type: " + base);
+        }
+    }
+
+    /**
+     * Converts a two-bit representation of a base into an ASCII representation of a base. 
+     * @param pack Byte from 0-3 indicating which base is represented.
+     * @return An ASCII value representing the packed base.
+     */
+    public static byte unpackBase(byte pack) {
+        switch( pack ) {
+            case 0:
+                return 'A';
+            case 1:
+                return 'C';
+            case 2:
+                return 'G';
+            case 3:
+                return 'T';
+            default:
+                throw new ReviewedGATKException("Unknown pack type: " + pack);
+        }
+    }
+
+    /**
+     * Reverses an unpacked sequence of bases.
+     * @param bases bases to reverse.
+     */
+    public static void reverse( byte[] bases ) {
+        for( int i = 0, j = bases.length-1; i < j; i++, j-- ) {
+            byte temp = bases[j];
+            bases[j] = bases[i];
+            bases[i] = temp;
+        }        
+    }
+
+    /**
+     * Given a structure of size <code>size</code> that should be split
+     * into <code>partitionSize</code> partitions, how many partitions should
+     * be created?  Size of last partition will be <= partitionSize.
+     * @param size Total size of the data structure.
+     * @param partitionSize Size of an individual partition.
+     * @return Number of partitions that would be created.
+     */
+    public static int numberOfPartitions( long size, long partitionSize ) {
+        return (int)((size+partitionSize-1) / partitionSize);    
+    }
+}
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/alignment/reference/packing/UnsignedIntPackedInputStream.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/alignment/reference/packing/UnsignedIntPackedInputStream.java
new file mode 100644
index 0000000..0600500
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/alignment/reference/packing/UnsignedIntPackedInputStream.java
@@ -0,0 +1,129 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.engine.alignment.reference.packing;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.nio.ByteBuffer;
+import java.nio.ByteOrder;
+import java.nio.channels.FileChannel;
+
+/**
+ * Read a set of integers packed into 
+ *
+ * @author mhanna
+ * @version 0.1
+ */
+public class UnsignedIntPackedInputStream {
+    /**
+     * Ultimate target for the occurrence array.
+     */
+    private final FileInputStream targetInputStream;
+
+    /**
+     * Target channel from which to pull file data.
+     */
+    private final FileChannel targetInputChannel;
+
+    /**
+     * The byte order in which integer input data appears.
+     */
+    private final ByteOrder byteOrder;
+
+    /**
+     * How many bytes are required to store an integer?
+     */
+    private final int bytesPerInteger = PackUtils.bitsInType(Integer.class)/PackUtils.BITS_PER_BYTE;
+
+    /**
+     * Create a new PackedIntInputStream, writing to the given target file.
+     * @param inputFile target input file.
+     * @param byteOrder Endianness to use when writing a list of integers.
+     * @throws java.io.IOException if an I/O error occurs.
+     */
+    public UnsignedIntPackedInputStream(File inputFile, ByteOrder byteOrder) throws IOException {
+        this(new FileInputStream(inputFile),byteOrder);
+    }
+
+    /**
+     * Read  ints from the given InputStream.
+     * @param inputStream Input stream from which to read ints.
+     * @param byteOrder Endianness to use when writing a list of integers.
+     */
+    public UnsignedIntPackedInputStream(FileInputStream inputStream, ByteOrder byteOrder) {
+        this.targetInputStream = inputStream;
+        this.targetInputChannel = inputStream.getChannel();
+        this.byteOrder = byteOrder;
+    }
+
+    /**
+     * Read a datum from the input stream.
+     * @return The next input datum in the stream.
+     * @throws IOException if an I/O error occurs.
+     */
+    public long read() throws IOException {
+        long[] data = new long[1];
+        read(data);
+        return data[0];
+    }
+
+    /**
+     * Read the data from the input stream.
+     * @param data placeholder for input data.
+     * @throws IOException if an I/O error occurs.
+     */
+    public void read( long[] data ) throws IOException {
+        read( data, 0, data.length );
+    }
+
+    /**
+     * Read the data from the input stream, starting at the given offset.
+     * @param data placeholder for input data.
+     * @param offset place in the array to start reading in data.
+     * @param length number of ints to read in. 
+     * @throws IOException if an I/O error occurs.
+     */
+    public void read( long[] data, int offset, int length ) throws IOException {
+        ByteBuffer readBuffer = ByteBuffer.allocate(bytesPerInteger*length).order(byteOrder);
+
+        targetInputChannel.read(readBuffer,targetInputChannel.position());
+        readBuffer.flip();
+        targetInputChannel.position(targetInputChannel.position()+readBuffer.remaining());
+
+        int i = 0;
+        while(i < length)
+            data[offset+i++] = readBuffer.getInt() & 0xFFFFFFFFL;
+    }
+
+    /**
+     * Closes the given output stream.
+     * @throws IOException if an I/O error occurs.
+     */
+    public void close() throws IOException {
+        targetInputStream.close();
+    }
+}
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/alignment/reference/packing/UnsignedIntPackedOutputStream.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/alignment/reference/packing/UnsignedIntPackedOutputStream.java
new file mode 100644
index 0000000..44c462b
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/alignment/reference/packing/UnsignedIntPackedOutputStream.java
@@ -0,0 +1,121 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.engine.alignment.reference.packing;
+
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.OutputStream;
+import java.nio.ByteBuffer;
+import java.nio.ByteOrder;
+
+/**
+ * Writes an list of integers to the output file.
+ *
+ * @author mhanna
+ * @version 0.1
+ */
+public class UnsignedIntPackedOutputStream {
+    /**
+     * Ultimate target for the occurrence array.
+     */
+    private final OutputStream targetOutputStream;
+
+    /**
+     * A fixed-size buffer for int-packed data.
+     */
+    private final ByteBuffer buffer;
+
+    /**
+     * Create a new PackedIntOutputStream, writing to the given target file.
+     * @param outputFile target output file.
+     * @param byteOrder Endianness to use when writing a list of integers.
+     * @throws IOException if an I/O error occurs.
+     */
+    public UnsignedIntPackedOutputStream(File outputFile, ByteOrder byteOrder) throws IOException {
+        this(new FileOutputStream(outputFile),byteOrder);
+    }
+
+    /**
+     * Write packed ints to the given OutputStream.
+     * @param outputStream Output stream to which to write packed ints.
+     * @param byteOrder Endianness to use when writing a list of integers.
+     */
+    public UnsignedIntPackedOutputStream(OutputStream outputStream, ByteOrder byteOrder) {
+        this.targetOutputStream = outputStream;
+        buffer = ByteBuffer.allocate(PackUtils.bitsInType(Integer.class)/PackUtils.BITS_PER_BYTE).order(byteOrder);
+    }
+
+    /**
+     * Write the data to the output stream.
+     * @param datum datum to write. 
+     * @throws IOException if an I/O error occurs.
+     */
+    public void write( long datum ) throws IOException {
+        buffer.rewind();
+        buffer.putInt((int)datum);
+        targetOutputStream.write(buffer.array());
+    }
+
+    /**
+     * Write the data to the output stream.
+     * @param data data to write.  occurrences.length must match alphabet size.
+     * @throws IOException if an I/O error occurs.
+     */
+    public void write( long[] data ) throws IOException {
+        for(long datum: data)
+            write(datum);
+    }
+
+    /**
+     * Write the given chunk of data to the input stream.
+     * @param data data to write.
+     * @param offset position at which to start.
+     * @param length number of ints to write.
+     * @throws IOException if an I/O error occurs.
+     */
+    public void write( long[] data, int offset, int length ) throws IOException {
+        for( int i = offset; i < offset+length; i++ )
+            write(data[i]);
+    }
+
+    /**
+     * Flush the contents of the OutputStream to disk.
+     * @throws IOException if an I/O error occurs.
+     */
+    public void flush() throws IOException {
+        targetOutputStream.flush();
+    }    
+
+    /**
+     * Closes the given output stream.
+     * @throws IOException if an I/O error occurs.
+     */
+    public void close() throws IOException {
+        targetOutputStream.close();
+    }
+
+}
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/arguments/DbsnpArgumentCollection.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/arguments/DbsnpArgumentCollection.java
new file mode 100644
index 0000000..05ebffa
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/arguments/DbsnpArgumentCollection.java
@@ -0,0 +1,46 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.engine.arguments;
+
+
+import org.broadinstitute.gatk.utils.commandline.Input;
+import org.broadinstitute.gatk.utils.commandline.RodBinding;
+import htsjdk.variant.variantcontext.VariantContext;
+
+/**
+ * @author ebanks
+ * @version 1.0
+ */
+public class DbsnpArgumentCollection {
+
+    /**
+     * A dbSNP VCF file.
+     */
+    @Input(fullName="dbsnp", shortName = "D", doc="dbSNP file", required=false)
+    public RodBinding<VariantContext> dbsnp;
+
+}
+
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/arguments/GATKArgumentCollection.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/arguments/GATKArgumentCollection.java
new file mode 100644
index 0000000..05834f7
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/arguments/GATKArgumentCollection.java
@@ -0,0 +1,628 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.engine.arguments;
+
+import htsjdk.samtools.ValidationStringency;
+import org.broadinstitute.gatk.utils.commandline.*;
+import org.broadinstitute.gatk.engine.GenomeAnalysisEngine;
+import org.broadinstitute.gatk.engine.downsampling.DownsampleType;
+import org.broadinstitute.gatk.engine.downsampling.DownsamplingMethod;
+import org.broadinstitute.gatk.engine.phonehome.GATKRunReport;
+import org.broadinstitute.gatk.engine.samples.PedigreeValidationType;
+import org.broadinstitute.gatk.utils.QualityUtils;
+import org.broadinstitute.gatk.utils.baq.BAQ;
+import org.broadinstitute.gatk.utils.variant.GATKVCFIndexType;
+import org.broadinstitute.gatk.utils.variant.GATKVCFUtils;
+
+import java.io.File;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.concurrent.TimeUnit;
+
+/**
+ * @author aaron
+ * @version 1.0
+ */
+public class GATKArgumentCollection {
+
+    /** the constructor */
+    public GATKArgumentCollection() {
+    }
+
+    // parameters and their defaults
+    /**
+     * An input file containing sequence data mapped to a reference, in SAM or BAM format, or a text file containing a
+     * list of input files (with extension .list). Note that the GATK requires an accompanying index for each SAM or
+     * BAM file. Please see our online documentation for more details on input formatting requirements.
+     */
+    @Input(fullName = "input_file", shortName = "I", doc = "Input file containing sequence data (SAM or BAM)", required = false)
+    public List<String> samFiles = new ArrayList<>();
+
+    @Hidden
+    @Argument(fullName = "showFullBamList",doc="Emit a log entry (level INFO) containing the full list of sequence data files to be included in the analysis (including files inside .bam.list files).")
+    public Boolean showFullBamList = false;
+
+    @Argument(fullName = "read_buffer_size", shortName = "rbs", doc="Number of reads per SAM file to buffer in memory", required = false, minValue = 0)
+    public Integer readBufferSize = null;
+
+    // --------------------------------------------------------------------------------------------------------------
+    //
+    // GATKRunReport options
+    //
+    // --------------------------------------------------------------------------------------------------------------
+
+    /**
+     * By default, GATK generates a run report that is uploaded to a cloud-based service. This report contains basic
+     * statistics about the run (which tool was used, whether the run was successful etc.) that help us for debugging
+     * and development. Up to version 3.2-2 the run report contains a record of the username and hostname associated
+     * with the run, but it does **NOT** contain any information that could be used to identify patient data.
+     * Nevertheless, if your data is subject to stringent confidentiality clauses (no outside communication) or if your
+     * run environment is not connected to the internet, you can disable the reporting system by seeting this option to
+     * "NO_ET". You will also need to request a key using the online request form on our website (se FAQs).
+     */
+    @Argument(fullName = "phone_home", shortName = "et", doc="Run reporting mode", required = false)
+    public GATKRunReport.PhoneHomeOption phoneHomeType = GATKRunReport.PhoneHomeOption.AWS;
+    /**
+     * Please see the "phone_home" argument below and the online documentation FAQs for more details on the key system
+     * and how to request a key.
+     */
+    @Argument(fullName = "gatk_key", shortName = "K", doc="GATK key file required to run with -et NO_ET", required = false)
+    public File gatkKeyFile = null;
+
+    /**
+     * The GATKRunReport supports (as of GATK 2.2) tagging GATK runs with an arbitrary tag that can be
+     * used to group together runs during later analysis.  One use of this capability is to tag runs as GATK
+     * performance tests, so that the performance of the GATK over time can be assessed from the logs directly.
+     *
+     * Note that the tags do not conform to any ontology, so you are free to use any tags that you might find
+     * meaningful.
+     */
+    @Argument(fullName = "tag", shortName = "tag", doc="Tag to identify this GATK run as part of a group of runs", required = false)
+    public String tag = "NA";
+
+    // --------------------------------------------------------------------------------------------------------------
+    //
+    // General features
+    //
+    // --------------------------------------------------------------------------------------------------------------
+
+    /**
+     * Reads that fail the specified filters will not be used in the analysis. Multiple filters can be specified separately,
+     * e.g. you can do -rf MalformedRead -rf BadCigar and so on. Available read filters are listed in the online tool
+     * documentation. Note that the read name format is e.g. MalformedReadFilter, but at the command line the filter
+     * name should be given without the Filter suffix; e.g. -rf MalformedRead (NOT -rf MalformedReadFilter, which is not
+     * recognized by the program). Note also that some read filters are applied by default for some analysis tools; this
+     * is specified in each tool's documentation. The default filters cannot be disabled.
+     */
+    @Argument(fullName = "read_filter", shortName = "rf", doc = "Filters to apply to reads before analysis", required = false)
+    public final List<String> readFilters = new ArrayList<>();
+
+    @ArgumentCollection
+    public IntervalArgumentCollection intervalArguments = new IntervalArgumentCollection();
+    /**
+     * The reference genome against which the sequence data was mapped. The GATK requires an index file and a dictionary
+     * file accompanying the reference (please see the online documentation FAQs for more details on these files). Although
+     * this argument is indicated as being optional, almost all GATK tools require a reference in order to run.
+     * Note also that while GATK can in theory process genomes from any organism with any number of chromosomes or contigs,
+     * it is not designed to process draft genome assemblies and performance will decrease as the number of contigs in
+     * the reference increases. We strongly discourage the use of unfinished genome assemblies containing more than a few
+     * hundred contigs. Contig numbers in the thousands will most probably cause memory-related crashes.
+     */
+    @Input(fullName = "reference_sequence", shortName = "R", doc = "Reference sequence file", required = false)
+    public File referenceFile = null;
+    /**
+     * If this flag is enabled, the random numbers generated will be different in every run, causing GATK to behave non-deterministically.
+     */
+    @Argument(fullName = "nonDeterministicRandomSeed", shortName = "ndrs", doc = "Use a non-deterministic random seed", required = false)
+    public boolean nonDeterministicRandomSeed = false;
+    /**
+     * To be used in the testing framework where dynamic parallelism can result in differing numbers of calls to the random generator.
+     */
+    @Hidden
+    @Argument(fullName = "disableDithering",doc="Completely eliminates randomized dithering from rank sum tests.")
+    public boolean disableDithering = false;
+    /**
+     * This will truncate the run but without exiting with a failure. By default the value is interpreted in minutes, but this can be changed with the maxRuntimeUnits argument.
+     */
+    @Argument(fullName = "maxRuntime", shortName = "maxRuntime", doc="Stop execution cleanly as soon as maxRuntime has been reached", required = false)
+    public long maxRuntime = GenomeAnalysisEngine.NO_RUNTIME_LIMIT;
+
+    @Argument(fullName = "maxRuntimeUnits", shortName = "maxRuntimeUnits", doc="Unit of time used by maxRuntime", required = false)
+    public TimeUnit maxRuntimeUnits = TimeUnit.MINUTES;
+
+    // --------------------------------------------------------------------------------------------------------------
+    //
+    // Downsampling Arguments
+    //
+    // --------------------------------------------------------------------------------------------------------------
+    /**
+     * There are several ways to downsample reads, i.e. to removed reads from the pile of reads that will be used for analysis.
+     * See the documentation of the individual downsampling options for details on how they work. Note that Many GATK tools
+     * specify a default downsampling type and target, but this behavior can be overridden from command line using the
+     * downsampling arguments.
+     */
+    @Argument(fullName = "downsampling_type", shortName="dt", doc="Type of read downsampling to employ at a given locus", required = false)
+    public DownsampleType downsamplingType = null;
+    /**
+     * Reads will be downsampled so the specified fraction remains; e.g. if you specify -dfrac 0.25, three-quarters of
+     * the reads will be removed, and the remaining one quarter will be used in the analysis. This method of downsampling
+     * is truly unbiased and random. It is typically used to simulate the effect of generating different amounts of
+     * sequence data for a given sample. For example, you can use this in a pilot experiment to evaluate how much target
+     * coverage you need to aim for in order to obtain enough coverage in all loci of interest.
+     */
+    @Argument(fullName = "downsample_to_fraction", shortName = "dfrac", doc = "Fraction of reads to downsample to", required = false, minValue = 0.0, maxValue = 1.0)
+    public Double downsampleFraction = null;
+
+    /**
+     * The principle of this downsampling type is to downsample reads to a given capping threshold coverage. Its purpose is to
+     * get rid of excessive coverage, because above a certain depth, having additional data is not informative and imposes
+     * unreasonable computational costs. The downsampling process takes two different forms depending on the type of
+     * analysis it is used with.
+     *
+     * For locus-based traversals (LocusWalkers like UnifiedGenotyper and ActiveRegionWalkers like HaplotypeCaller),
+     * downsample_to_coverage controls the maximum depth of coverage at each locus. For read-based traversals
+     * (ReadWalkers like BaseRecalibrator), it controls the maximum number of reads sharing the same alignment start
+     * position. For ReadWalkers you will typically need to use much lower dcov values than you would with LocusWalkers
+     * to see an effect. Note that this downsampling option does not produce an unbiased random sampling from all available
+     * reads at each locus: instead, the primary goal of the to-coverage downsampler is to maintain an even representation
+     * of reads from all alignment start positions when removing excess coverage. For a truly unbiased random sampling of
+     * reads, use -dfrac instead. Also note that the coverage target is an approximate goal that is not guaranteed to be
+     * met exactly: the downsampling algorithm will under some circumstances retain slightly more or less coverage than
+     * requested.
+     */
+    @Argument(fullName = "downsample_to_coverage", shortName = "dcov",
+              doc = "Target coverage threshold for downsampling to coverage",
+              required = false, minValue = 0)
+    public Integer downsampleCoverage = null;
+
+    /**
+     * Gets the downsampling method explicitly specified by the user. If the user didn't specify
+     * a default downsampling mechanism, return the default.
+     * @return The explicitly specified downsampling mechanism, or the default if none exists.
+     */
+    public DownsamplingMethod getDownsamplingMethod() {
+        if ( downsamplingType == null && downsampleFraction == null && downsampleCoverage == null )
+            return null;
+
+        return new DownsamplingMethod(downsamplingType, downsampleCoverage, downsampleFraction);
+    }
+
+    /**
+     * Set the downsampling method stored in the argument collection so that it is read back out when interrogating the command line arguments.
+     * @param method The downsampling mechanism.
+     */
+    public void setDownsamplingMethod(DownsamplingMethod method) {
+        if (method == null)
+            throw new IllegalArgumentException("method is null");
+
+        downsamplingType = method.type;
+        downsampleCoverage = method.toCoverage;
+        downsampleFraction = method.toFraction;
+    }
+
+    // --------------------------------------------------------------------------------------------------------------
+    //
+    // BAQ arguments
+    //
+    // --------------------------------------------------------------------------------------------------------------
+    @Argument(fullName = "baq", shortName="baq", doc="Type of BAQ calculation to apply in the engine", required = false)
+    public BAQ.CalculationMode BAQMode = BAQ.CalculationMode.OFF;
+    /**
+     *  Phred-scaled gap open penalty for BAQ calculation. Although the default value is 40, a value of 30 may be better for whole genome call sets.
+     */
+    @Argument(fullName = "baqGapOpenPenalty", shortName="baqGOP", doc="BAQ gap open penalty", required = false, minValue = 0)
+    public double BAQGOP = BAQ.DEFAULT_GOP;
+
+    // --------------------------------------------------------------------------------------------------------------
+    //
+    // refactor NDN cigar string arguments
+    //
+    // --------------------------------------------------------------------------------------------------------------
+    /**
+     * This flag tells GATK to refactor cigar string with NDN elements to one element. It intended primarily for use in
+     * a RNAseq pipeline since the problem might come up when using RNAseq aligner such as Tophat2 with provided transcriptoms.
+     * You should only use this if you know that your reads have that problem.
+     */
+    @Argument(fullName = "refactor_NDN_cigar_string", shortName = "fixNDN", doc = "refactor cigar string with NDN elements to one element", required = false)
+    public boolean REFACTOR_NDN_CIGAR_READS = false;
+
+    // --------------------------------------------------------------------------------------------------------------
+    //
+    // quality encoding checking arguments
+    //
+    // --------------------------------------------------------------------------------------------------------------
+
+    /**
+     * By default the GATK assumes that base quality scores start at Q0 == ASCII 33 according to the SAM specification.
+     * However, encoding in some datasets (especially older Illumina ones) starts at Q64. This argument will fix the
+     * encodings on the fly (as the data is read in) by subtracting 31 from every quality score. Note that this argument should
+     * NEVER be used by default; you should only use it when you have confirmed that the quality scores in your data are
+     * not in the correct encoding.
+     */
+    @Argument(fullName = "fix_misencoded_quality_scores", shortName="fixMisencodedQuals", doc="Fix mis-encoded base quality scores", required = false)
+    public boolean FIX_MISENCODED_QUALS = false;
+    /**
+     * This flag tells GATK to ignore warnings when encountering base qualities that are too high and that seemingly
+     * indicate a problem with the base quality encoding of the BAM file. You should only use this if you really know
+     * what you are doing; otherwise you could seriously mess up your data and ruin your analysis.
+     */
+    @Argument(fullName = "allow_potentially_misencoded_quality_scores", shortName="allowPotentiallyMisencodedQuals", doc="Ignore warnings about base quality score encoding", required = false)
+    public boolean ALLOW_POTENTIALLY_MISENCODED_QUALS = false;
+    /**
+     * This flag tells GATK to use the original base qualities (that were in the data before BQSR/recalibration) which
+     * are stored in the OQ tag, if they are present, rather than use the post-recalibration quality scores. If no OQ
+     * tag is present for a read, the standard qual score will be used.
+     */
+    @Argument(fullName="useOriginalQualities", shortName = "OQ", doc = "Use the base quality scores from the OQ tag", required=false)
+    public Boolean useOriginalBaseQualities = false;
+    /**
+     * If reads are missing some or all base quality scores, this value will be used for all base quality scores.
+     * By default this is set to -1 to disable default base quality assignment.
+     */
+    @Argument(fullName="defaultBaseQualities", shortName = "DBQ", doc = "Assign a default base quality", required=false, minValue = 0, maxValue = Byte.MAX_VALUE)
+    public byte defaultBaseQualities = -1;
+
+    // --------------------------------------------------------------------------------------------------------------
+    //
+    // performance log arguments
+    //
+    // --------------------------------------------------------------------------------------------------------------
+
+    /**
+     * The file name for the GATK performance log output, or null if you don't want to generate the
+     * detailed performance logging table.  This table is suitable for importing into R or any
+     * other analysis software that can read tsv files.
+     */
+    @Argument(fullName = "performanceLog", shortName="PF", doc="Write GATK runtime performance log to this file", required = false)
+    public File performanceLog = null;
+
+    // --------------------------------------------------------------------------------------------------------------
+    //
+    // BQSR arguments
+    //
+    // --------------------------------------------------------------------------------------------------------------
+
+    /**
+     * Enables on-the-fly recalibrate of base qualities, intended primarily for use with BaseRecalibrator and PrintReads
+     * (see Best Practices workflow documentation). The covariates tables are produced by the BaseRecalibrator tool.
+     * Please be aware that you should only run recalibration with the covariates file created on the same input bam(s).
+     */
+    @Input(fullName="BQSR", shortName="BQSR", required=false, doc="Input covariates table file for on-the-fly base quality score recalibration")
+    public File BQSR_RECAL_FILE = null;
+
+    /**
+     * Turns on the base quantization module. It requires a recalibration report (-BQSR).
+     *
+     * A value of 0 here means "do not quantize".
+     * Any value greater than zero will be used to recalculate the quantization using that many levels.
+     * Negative values mean that we should quantize using the recalibration report's quantization level.
+     */
+    @Hidden
+    @Argument(fullName="quantize_quals", shortName = "qq", doc = "Quantize quality scores to a given number of levels (with -BQSR)", required=false)
+    public int quantizationLevels = 0;
+
+    /**
+     * Turns off printing of the base insertion and base deletion tags when using the -BQSR argument. Only the base substitution qualities will be produced.
+     */
+    @Argument(fullName="disable_indel_quals", shortName = "DIQ", doc = "Disable printing of base insertion and deletion tags (with -BQSR)", required=false)
+    public boolean disableIndelQuals = false;
+
+    /**
+     * By default, the OQ tag in not emitted when using the -BQSR argument. Use this flag to include OQ tags in the output BAM file.
+     * Note that this may results in significant file size increase.
+     */
+    @Argument(fullName="emit_original_quals", shortName = "EOQ", doc = "Emit the OQ tag with the original base qualities (with -BQSR)", required=false)
+    public boolean emitOriginalQuals = false;
+
+    /**
+     * This flag tells GATK not to modify quality scores less than this value. Instead they will be written out unmodified in the recalibrated BAM file.
+     * In general it's unsafe to change qualities scores below < 6, since base callers use these values to indicate random or bad bases.
+     * For example, Illumina writes Q2 bases when the machine has really gone wrong. This would be fine in and of itself,
+     * but when you select a subset of these reads based on their ability to align to the reference and their dinucleotide effect,
+     * your Q2 bin can be elevated to Q8 or Q10, leading to issues downstream.
+     */
+    @Argument(fullName = "preserve_qscores_less_than", shortName = "preserveQ", doc = "Don't recalibrate bases with quality scores less than this threshold (with -BQSR)", required = false, minValue = 0, minRecommendedValue = QualityUtils.MIN_USABLE_Q_SCORE)
+    public int PRESERVE_QSCORES_LESS_THAN = QualityUtils.MIN_USABLE_Q_SCORE;
+    /**
+     * If specified, this value will be used as the prior for all mismatch quality scores instead of the actual reported quality score.
+     */
+    @Argument(fullName = "globalQScorePrior", shortName = "globalQScorePrior", doc = "Global Qscore Bayesian prior to use for BQSR", required = false)
+    public double globalQScorePrior = -1.0;
+
+
+    // --------------------------------------------------------------------------------------------------------------
+    //
+    // Other utility arguments
+    //
+    // --------------------------------------------------------------------------------------------------------------
+
+    /**
+     * Keep in mind that if you set this to LENIENT, we may refuse to provide you with support if anything goes wrong.
+     */
+    @Argument(fullName = "validation_strictness", shortName = "S", doc = "How strict should we be with validation", required = false)
+    public ValidationStringency strictnessLevel = ValidationStringency.SILENT;
+    /**
+     * Some tools keep program records in the SAM header by default. Use this argument to override that behavior and discard program records for the SAM header.
+     */
+    @Argument(fullName = "remove_program_records", shortName = "rpr", doc = "Remove program records from the SAM header", required = false)
+    public boolean removeProgramRecords = false;
+    /**
+     * Some tools discard program records from the SAM header by default. Use this argument to override that behavior and keep program records in the SAM header.
+     */
+    @Argument(fullName = "keep_program_records", shortName = "kpr", doc = "Keep program records in the SAM header", required = false)
+    public boolean keepProgramRecords = false;
+
+    /**
+     * On-the-fly sample renaming works only with single-sample BAM and VCF files. Each line of the mapping file must
+     * contain the absolute path to a BAM or VCF file, followed by whitespace, followed by the new sample name for that
+     * BAM or VCF file. The sample name may contain non-tab whitespace, but leading or trailing whitespace will be 
+     * ignored. The engine will verify at runtime that each BAM/VCF targeted for sample renaming has only a single 
+     * sample specified in its header (though, in the case of BAM files, there may be multiple read groups for that 
+     * sample).
+     */
+    @Advanced
+    @Argument(fullName = "sample_rename_mapping_file", shortName = "sample_rename_mapping_file", doc = "Rename sample IDs on-the-fly at runtime using the provided mapping file", required = false)
+    public File sampleRenameMappingFile = null;
+
+    /**
+     * For expert users only who know what they are doing. We do not support usage of this argument, so we may refuse to help you if you use it and something goes wrong. The one exception to this rule is ALLOW_N_CIGAR_READS, which is necessary for RNAseq analysis.
+     */
+    @Argument(fullName = "unsafe", shortName = "U", doc = "Enable unsafe operations: nothing will be checked at runtime", required = false)
+    public ValidationExclusion.TYPE unsafe;
+    /**
+     * UNSAFE FOR GENERAL USE (FOR TEST SUITE USE ONLY). Disable both auto-generation of index files and index file locking
+     * when reading VCFs and other rods and an index isn't present or is out-of-date. The file locking necessary for auto index
+     * generation to work safely is prone to random failures/hangs on certain platforms, which makes it desirable to disable it
+     * for situations like test suite runs where the indices are already known to exist, however this option is unsafe in general
+     * because it allows reading from index files without first acquiring a lock.
+     */
+    @Hidden
+    @Advanced
+    @Argument(fullName = "disable_auto_index_creation_and_locking_when_reading_rods", shortName = "disable_auto_index_creation_and_locking_when_reading_rods",
+              doc = "Disable both auto-generation of index files and index file locking",
+              required = false)
+    public boolean disableAutoIndexCreationAndLockingWhenReadingRods = false;
+
+    @Hidden
+    @Argument(fullName = "no_cmdline_in_header", shortName = "no_cmdline_in_header", doc = "Don't output the usual VCF header tag with the command line. FOR DEBUGGING PURPOSES ONLY. This option is required in order to pass integration tests.",
+              required = false)
+    public boolean disableCommandLineInVCF = false;
+
+    @Argument(fullName = "sites_only", shortName = "sites_only", doc = "Just output sites without genotypes (i.e. only the first 8 columns of the VCF)",
+              required = false)
+    public boolean sitesOnlyVCF = false;
+
+    /**
+     * <p>The VCF specification permits missing records to be dropped from the end of FORMAT fields, so long as GT is always output.
+     * This option prevents GATK from performing that trimming.</p>
+     *
+     * <p>For example, given a FORMAT of <pre>GT:AD:DP:PL</pre>, GATK will by default emit <pre>./.</pre> for a variant with
+     * no reads present (ie, the AD, DP, and PL fields are trimmed).  If you specify -writeFullFormat, this record
+     * would be emitted as <pre>./.:.:.:.</pre></p>
+     */
+    @Argument(fullName = "never_trim_vcf_format_field", shortName = "writeFullFormat", doc = "Always output all the records in VCF FORMAT fields, even if some are missing",
+              required = false)
+    public boolean neverTrimVCFFormatField = false;
+
+    @Hidden
+    @Argument(fullName = "bcf", shortName = "bcf", doc = "Force BCF output, regardless of the file's extension",
+              required = false)
+    public boolean forceBCFOutput = false;
+
+    @Advanced
+    @Argument(fullName = "bam_compression", shortName = "compress", doc = "Compression level to use for writing BAM files (0 - 9, higher is more compressed)",
+              minValue = 0, maxValue = 9, required = false)
+    public Integer bamCompression = null;
+
+    @Advanced
+    @Argument(fullName = "simplifyBAM", shortName = "simplifyBAM",
+              doc = "If provided, output BAM files will be simplified to include just key reads for downstream variation discovery analyses (removing duplicates, PF-, non-primary reads), as well stripping all extended tags from the kept reads except the read group identifier",
+              required = false)
+    public boolean simplifyBAM = false;
+
+    @Argument(fullName = "disable_bam_indexing", doc = "Turn off on-the-fly creation of indices for output BAM files.",
+            required = false)
+    public boolean disableBAMIndexing = false;
+
+    @Argument(fullName = "generate_md5", doc = "Enable on-the-fly creation of md5s for output BAM files.",
+            required = false)
+    public boolean enableBAMmd5 = false;
+
+    // --------------------------------------------------------------------------------------------------------------
+    //
+    // Multi-threading arguments
+    //
+    // --------------------------------------------------------------------------------------------------------------
+
+    /**
+     * Data threads contains N cpu threads per data thread, and act as completely data parallel processing, increasing
+     * the memory usage of GATK by M data threads. Data threads generally scale extremely effectively, up to 24 cores.
+     * See online documentation FAQs for more information.
+     */
+    @Argument(fullName = "num_threads", shortName = "nt", doc = "Number of data threads to allocate to this analysis", required = false, minValue = 1)
+    public Integer numberOfDataThreads = 1;
+
+    /**
+     * Each CPU thread operates the map cycle independently, but may run into earlier scaling problems with IO than
+     * data threads. Has the benefit of not requiring X times as much memory per thread as data threads do, but rather
+     * only a constant overhead. See online documentation FAQs for more information.
+     */
+    @Argument(fullName="num_cpu_threads_per_data_thread", shortName = "nct", doc="Number of CPU threads to allocate per data thread", required = false, minValue = 1)
+    public int numberOfCPUThreadsPerDataThread = 1;
+
+    @Argument(fullName="num_io_threads", shortName = "nit", doc="Number of given threads to allocate to IO", required = false, minValue = 0)
+    @Hidden
+    public int numberOfIOThreads = 0;
+
+    /**
+     * Enable GATK to monitor its own threading efficiency, at an itsy-bitsy tiny
+     * cost (< 0.1%) in runtime because of turning on the JavaBean.  This is largely for
+     * debugging purposes. Note that this argument is not compatible with -nt, it only works with -nct.
+     */
+    @Argument(fullName = "monitorThreadEfficiency", shortName = "mte", doc = "Enable threading efficiency monitoring", required = false)
+    public Boolean monitorThreadEfficiency = false;
+
+    @Argument(fullName = "num_bam_file_handles", shortName = "bfh", doc="Total number of BAM file handles to keep open simultaneously", required=false, minValue = 1)
+    public Integer numberOfBAMFileHandles = null;
+    /**
+     * This will filter out read groups matching <TAG>:<STRING> (e.g. SM:sample1) or a .txt file containing the filter strings one per line.
+     */
+    @Input(fullName = "read_group_black_list", shortName="rgbl", doc="Exclude read groups based on tags", required = false)
+    public List<String> readGroupBlackList = null;
+
+    // --------------------------------------------------------------------------------------------------------------
+    //
+    // PED (pedigree) support
+    //
+    // --------------------------------------------------------------------------------------------------------------
+
+    /**
+     * <p>Reads PED file-formatted tabular text files describing meta-data about the samples being
+     * processed in the GATK.</p>
+     *
+     * <ul>
+     *  <li>see <a href="http://www.broadinstitute.org/mpg/tagger/faq.html">http://www.broadinstitute.org/mpg/tagger/faq.html</a></li>
+     *  <li>see <a href="http://pngu.mgh.harvard.edu/~purcell/plink/data.shtml#ped">http://pngu.mgh.harvard.edu/~purcell/plink/data.shtml#ped</a></li>
+     * </ul>
+     *
+     * <p>The PED file is a white-space (space or tab) delimited file: the first six columns are mandatory:</p>
+     *
+     * <ul>
+     *  <li>Family ID</li>
+     *  <li>Individual ID</li>
+     *  <li>Paternal ID</li>
+     *  <li>Maternal ID</li>
+     *  <li>Sex (1=male; 2=female; other=unknown)</li>
+     *  <li>Phenotype</li>
+     * </ul>
+     *
+     *  <p>The IDs are alphanumeric: the combination of family and individual ID should uniquely identify a person.
+     *  A PED file must have 1 and only 1 phenotype in the sixth column. The phenotype can be either a
+     *  quantitative trait or an affection status column: GATK will automatically detect which type
+     *  (i.e. based on whether a value other than 0, 1, 2 or the missing genotype code is observed).</p>
+     *
+     *  <p>If an individual's sex is unknown, then any character other than 1 or 2 can be used.</p>
+     *
+     *  <p>You can add a comment to a PED or MAP file by starting the line with a # character. The rest of that
+     *  line will be ignored. Do not start any family IDs with this character therefore.</p>
+     *
+     *  <p>Affection status should be coded:</p>
+     *
+     * <ul>
+     *  <li>-9 missing</li>
+     *   <li>0 missing</li>
+     *   <li>1 unaffected</li>
+     *   <li>2 affected</li>
+     * </ul>
+     *
+     * <p>If any value outside of -9,0,1,2 is detected than the samples are assumed
+     * to phenotype values are interpreted as string phenotype values.  In this case -9 uniquely
+     * represents the missing value.</p>
+     *
+     * <p>Genotypes (column 7 onwards) cannot be specified to the GATK.</p>
+     *
+     * <p>For example, here are two individuals (one row = one person):</p>
+     *
+     * <pre>
+     *   FAM001  1  0 0  1  2
+     *   FAM001  2  0 0  1  2
+     * </pre>
+     *
+     * <p>Each -ped argument can be tagged with NO_FAMILY_ID, NO_PARENTS, NO_SEX, NO_PHENOTYPE to
+     * tell the GATK PED parser that the corresponding fields are missing from the ped file.</p>
+     *
+     * <p>Note that most GATK walkers do not use pedigree information.  Walkers that require pedigree
+     * data should clearly indicate so in their arguments and will throw errors if required pedigree
+     * information is missing.</p>
+     */
+    @Argument(fullName="pedigree", shortName = "ped", doc="Pedigree files for samples",required=false)
+    public List<File> pedigreeFiles = Collections.emptyList();
+
+    /**
+     * Inline PED records (see -ped argument).  Each -pedString STRING can contain one or more
+     * valid PED records (see -ped) separated by semi-colons.  Supports all tags for each pedString
+     * as -ped supports
+     */
+    @Argument(fullName="pedigreeString", shortName = "pedString", doc="Pedigree string for samples",required=false)
+    public List<String> pedigreeStrings = Collections.emptyList();
+
+    /**
+     * How strict should we be in parsing the PED files?
+     */
+    @Argument(fullName="pedigreeValidationType", shortName = "pedValidationType", doc="Validation strictness for pedigree information",required=false)
+    public PedigreeValidationType pedigreeValidationType = PedigreeValidationType.STRICT;
+
+    // --------------------------------------------------------------------------------------------------------------
+    //
+    // BAM indexing and sharding arguments
+    //
+    // --------------------------------------------------------------------------------------------------------------
+    /**
+     * NO INTEGRATION TESTS are available.  Use at your own risk.
+     */
+    @Argument(fullName="allow_intervals_with_unindexed_bam",doc="Allow interval processing with an unsupported BAM",required=false)
+    @Hidden
+    public boolean allowIntervalsWithUnindexedBAM = false;
+
+    // --------------------------------------------------------------------------------------------------------------
+    //
+    // testing BCF2
+    //
+    // --------------------------------------------------------------------------------------------------------------
+    /**
+     * If provided, whenever we create a VCFWriter we will also write out a BCF file alongside it, for testing purposes.
+     */
+    @Argument(fullName="generateShadowBCF",shortName = "generateShadowBCF",doc="Write a BCF copy of the output VCF",required=false)
+    @Hidden
+    public boolean generateShadowBCF = false;
+    // TODO -- remove all code tagged with TODO -- remove me when argument generateShadowBCF is removed
+
+    // --------------------------------------------------------------------------------------------------------------
+    //
+    // VCF/BCF index parameters
+    //
+    // --------------------------------------------------------------------------------------------------------------
+
+    /**
+     * Specify the Tribble indexing strategy to use for VCFs.
+     *
+     * LINEAR creates a LinearIndex with bins of equal width, specified by the Bin Width parameter
+     * INTERVAL creates an IntervalTreeIndex with bins with an equal amount of features, specified by the Features Per Bin parameter
+     * DYNAMIC_SEEK attempts to optimize for minimal seek time by choosing an appropriate strategy and parameter (user-supplied parameter is ignored)
+     * DYNAMIC_SIZE attempts to optimize for minimal index size by choosing an appropriate strategy and parameter (user-supplied parameter is ignored)
+     */
+    @Argument(fullName="variant_index_type",shortName = "variant_index_type",doc="Type of IndexCreator to use for VCF/BCF indices",required=false)
+    @Advanced
+    public GATKVCFIndexType variant_index_type = GATKVCFUtils.DEFAULT_INDEX_TYPE;
+    /**
+     * This is either the bin width or the number of features per bin, depending on the indexing strategy
+     */
+    @Argument(fullName="variant_index_parameter",shortName = "variant_index_parameter",doc="Parameter to pass to the VCF/BCF IndexCreator",required=false)
+    @Advanced
+    public int variant_index_parameter = GATKVCFUtils.DEFAULT_INDEX_PARAMETER;
+}
+
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/arguments/StandardVariantContextInputArgumentCollection.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/arguments/StandardVariantContextInputArgumentCollection.java
new file mode 100644
index 0000000..331029f
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/arguments/StandardVariantContextInputArgumentCollection.java
@@ -0,0 +1,48 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.engine.arguments;
+
+
+import org.broadinstitute.gatk.utils.commandline.Input;
+import org.broadinstitute.gatk.utils.commandline.RodBinding;
+import htsjdk.variant.variantcontext.VariantContext;
+
+/**
+ * @author ebanks
+ * @version 1.0
+ */
+public class StandardVariantContextInputArgumentCollection {
+
+    /**
+     * Variants from this VCF file are used by this tool as input.
+     * The file must at least contain the standard VCF header lines, but
+     * can be empty (i.e., no variants are contained in the file).
+     */
+    @Input(fullName="variant", shortName = "V", doc="Input VCF file", required=true)
+    public RodBinding<VariantContext> variants;
+
+}
+
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/arguments/ValidationExclusion.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/arguments/ValidationExclusion.java
new file mode 100644
index 0000000..ccd4fdc
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/arguments/ValidationExclusion.java
@@ -0,0 +1,67 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.engine.arguments;
+
+import org.broadinstitute.gatk.utils.commandline.EnumerationArgumentDefault;
+
+import java.util.ArrayList;
+import java.util.List;
+
+
+public class ValidationExclusion {
+
+    // our validation options
+
+    public enum TYPE {
+        ALLOW_N_CIGAR_READS,    // ignore the presence of N operators in CIGARs: do not blow up and process reads that contain one or more N operators.
+                                // This exclusion does not have effect on reads that get filtered {@see MalformedReadFilter}.
+        ALLOW_UNINDEXED_BAM,        // allow bam files that do not have an index; we'll traverse them using monolithic shard
+        ALLOW_UNSET_BAM_SORT_ORDER, // assume that the bam is sorted, even if the SO (sort-order) flag is not set
+        NO_READ_ORDER_VERIFICATION, // do not validate that the reads are in order as we take them from the bam file
+        ALLOW_SEQ_DICT_INCOMPATIBILITY, // allow dangerous, but not fatal, sequence dictionary incompabilities
+        LENIENT_VCF_PROCESSING,         // allow non-standard values for standard VCF header lines.  Don't worry about size differences between header and values, etc.
+        @EnumerationArgumentDefault // set the ALL value to the default value, so if they specify just -U, we get the ALL
+        ALL                         // do not check for all of the above conditions, DEFAULT
+    }
+
+    // a storage for the passed in exclusions
+    List<TYPE> exclusions = new ArrayList<TYPE>();
+
+    public ValidationExclusion(List<TYPE> exclusionsList) {
+        exclusions.addAll(exclusionsList);
+    }
+
+    public ValidationExclusion() {}
+    
+    /**
+     * do we contain the exclusion specified, or were we set to ALL
+     * @param t the exclusion case to test for
+     * @return true if we contain the exclusion or if we're set to ALL, false otherwise
+     */
+    public boolean contains(TYPE t) {
+        return (exclusions.contains(TYPE.ALL) || exclusions.contains(t));
+    }
+}
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/contexts/AlignmentContext.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/contexts/AlignmentContext.java
new file mode 100644
index 0000000..6ac2048
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/contexts/AlignmentContext.java
@@ -0,0 +1,154 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.engine.contexts;
+
+import org.broadinstitute.gatk.utils.GenomeLoc;
+import org.broadinstitute.gatk.utils.HasGenomeLocation;
+import org.broadinstitute.gatk.utils.exceptions.ReviewedGATKException;
+import org.broadinstitute.gatk.utils.pileup.ReadBackedPileup;
+import org.broadinstitute.gatk.utils.sam.GATKSAMRecord;
+
+import java.util.List;
+
+/**
+ * Useful class for forwarding on locusContext data from this iterator
+ * 
+ * Created by IntelliJ IDEA.
+ * User: mdepristo
+ * Date: Feb 22, 2009
+ * Time: 3:01:34 PM
+ * To change this template use File | Settings | File Templates.
+ */
+public class AlignmentContext implements HasGenomeLocation {
+    protected GenomeLoc loc = null;
+    protected ReadBackedPileup basePileup = null;
+    protected boolean hasPileupBeenDownsampled;
+
+    /**
+     * The number of bases we've skipped over in the reference since the last map invocation.
+     * Only filled in by RodTraversals right now.  By default, nothing is being skipped, so skippedBases == 0.
+     */
+    private long skippedBases = 0;
+
+    public AlignmentContext(GenomeLoc loc, ReadBackedPileup basePileup) {
+        this(loc, basePileup, 0, false);
+    }
+
+    public AlignmentContext(GenomeLoc loc, ReadBackedPileup basePileup, boolean hasPileupBeenDownsampled) {
+        this(loc, basePileup, 0, hasPileupBeenDownsampled);
+    }
+
+    public AlignmentContext(GenomeLoc loc, ReadBackedPileup basePileup, long skippedBases) {
+        this(loc, basePileup, skippedBases, false);
+    }
+
+    public AlignmentContext(GenomeLoc loc, ReadBackedPileup basePileup, long skippedBases,boolean hasPileupBeenDownsampled ) {
+        if ( loc == null ) throw new ReviewedGATKException("BUG: GenomeLoc in Alignment context is null");
+        if ( basePileup == null ) throw new ReviewedGATKException("BUG: ReadBackedPileup in Alignment context is null");
+        if ( skippedBases < 0 ) throw new ReviewedGATKException("BUG: skippedBases is -1 in Alignment context");
+
+        this.loc = loc;
+        this.basePileup = basePileup;
+        this.skippedBases = skippedBases;
+        this.hasPileupBeenDownsampled = hasPileupBeenDownsampled;
+    }
+
+    /** Returns base pileup over the current genomic location. Deprectated. Use getBasePileup() to make your intentions
+     * clear.
+     * @return
+     */
+    @Deprecated
+    public ReadBackedPileup getPileup() { return basePileup; }
+
+    /** Returns base pileup over the current genomic location. May return null if this context keeps only
+     * extended event (indel) pileup.
+     * @return
+     */
+    public ReadBackedPileup getBasePileup() {
+        return basePileup;
+    }
+
+    /**
+     * Returns true if any reads have been filtered out of the pileup due to excess DoC.
+     * @return True if reads have been filtered out.  False otherwise.
+     */
+    public boolean hasPileupBeenDownsampled() { return hasPileupBeenDownsampled; }
+
+    /**
+     * get all of the reads within this context
+     * 
+     * @return
+     */
+    @Deprecated
+    //todo: unsafe and tailored for current usage only; both pileups can be null or worse, bot can be not null in theory
+    public List<GATKSAMRecord> getReads() { return ( basePileup.getReads() ); }
+
+    /**
+     * Are there any reads associated with this locus?
+     *
+     * @return
+     */
+    public boolean hasReads() {
+        return basePileup != null && basePileup.getNumberOfElements() > 0 ;
+    }
+
+    /**
+     * How many reads cover this locus?
+     * @return
+     */
+    public int size() {
+        return basePileup.getNumberOfElements();
+    }
+
+    /**
+     * get a list of the equivalent positions within in the reads at Pos
+     *
+     * @return
+     */
+    @Deprecated
+    public List<Integer> getOffsets() {
+        return basePileup.getOffsets();
+    }
+
+    public String getContig() { return getLocation().getContig(); }
+    public long getPosition() { return getLocation().getStart(); }
+    public GenomeLoc getLocation() { return loc; }
+
+    public void downsampleToCoverage(int coverage) {
+        basePileup = basePileup.getDownsampledPileup(coverage);
+        hasPileupBeenDownsampled = true;
+    }
+
+    /**
+     * Returns the number of bases we've skipped over in the reference since the last map invocation.
+     * Only filled in by RodTraversals right now.  A value of 0 indicates that no bases were skipped.
+     *
+     * @return the number of skipped bases
+     */
+    public long getSkippedBases() {
+        return skippedBases;
+    }
+}
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/contexts/AlignmentContextUtils.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/contexts/AlignmentContextUtils.java
new file mode 100644
index 0000000..afeb1e7
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/contexts/AlignmentContextUtils.java
@@ -0,0 +1,150 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.engine.contexts;
+
+import htsjdk.samtools.SAMReadGroupRecord;
+import org.broadinstitute.gatk.utils.GenomeLoc;
+import org.broadinstitute.gatk.utils.exceptions.ReviewedGATKException;
+import org.broadinstitute.gatk.utils.exceptions.UserException;
+import org.broadinstitute.gatk.utils.pileup.*;
+
+import java.util.*;
+
+/**
+ * Useful utilities for storing different AlignmentContexts
+ * User: ebanks
+ */
+public class AlignmentContextUtils {
+
+    // Definitions:
+    //   COMPLETE = full alignment context
+    //   FORWARD  = reads on forward strand
+    //   REVERSE  = reads on forward strand
+    //
+    public enum ReadOrientation { COMPLETE, FORWARD, REVERSE }
+
+    private AlignmentContextUtils() {
+        // cannot be instantiated
+    }
+
+    /**
+     * Returns a potentially derived subcontext containing only forward, reverse, or in fact all reads
+     * in alignment context context.
+     *
+     * @param context
+     * @param type
+     * @return
+     */
+    public static AlignmentContext stratify(AlignmentContext context, ReadOrientation type) {
+        switch(type) {
+            case COMPLETE:
+                return context;
+            case FORWARD:
+                return new AlignmentContext(context.getLocation(),context.getPileup().getPositiveStrandPileup());
+            case REVERSE:
+                return new AlignmentContext(context.getLocation(),context.getPileup().getNegativeStrandPileup());
+            default:
+                throw new ReviewedGATKException("Unable to get alignment context for type = " + type);
+        }
+    }
+
+    public static Map<String, AlignmentContext> splitContextBySampleName(AlignmentContext context) {
+        return splitContextBySampleName(context, null);
+    }
+
+    /**
+     * Splits the given AlignmentContext into a StratifiedAlignmentContext per sample, but referencd by sample name instead
+     * of sample object.
+     *
+     * @param context                the original pileup
+     *
+     * @return a Map of sample name to StratifiedAlignmentContext
+     *
+     **/
+    public static Map<String, AlignmentContext> splitContextBySampleName(AlignmentContext context, String assumedSingleSample) {
+        GenomeLoc loc = context.getLocation();
+        HashMap<String, AlignmentContext> contexts = new HashMap<String, AlignmentContext>();
+
+        for(String sample: context.getPileup().getSamples()) {
+            ReadBackedPileup pileupBySample = context.getPileup().getPileupForSample(sample);
+
+            // Don't add empty pileups to the split context.
+            if(pileupBySample.getNumberOfElements() == 0)
+                continue;
+
+            if(sample != null)
+                contexts.put(sample, new AlignmentContext(loc, pileupBySample));
+            else {
+                if(assumedSingleSample == null) {
+                    throw new UserException.ReadMissingReadGroup(pileupBySample.iterator().next().getRead());
+                }
+                contexts.put(assumedSingleSample,new AlignmentContext(loc, pileupBySample));
+            }
+        }
+
+        return contexts;
+    }
+
+    /**
+     * Splits the AlignmentContext into one context per read group
+     *
+     * @param context the original pileup
+     * @return a Map of ReadGroup to AlignmentContext, or an empty map if context has no base pileup
+     *
+     **/
+    public static Map<SAMReadGroupRecord, AlignmentContext> splitContextByReadGroup(AlignmentContext context, Collection<SAMReadGroupRecord> readGroups) {
+        HashMap<SAMReadGroupRecord, AlignmentContext> contexts = new HashMap<SAMReadGroupRecord, AlignmentContext>();
+
+        for (SAMReadGroupRecord rg : readGroups) {
+            ReadBackedPileup rgPileup = context.getBasePileup().getPileupForReadGroup(rg.getReadGroupId());
+            if ( rgPileup != null ) // there we some reads for RG
+                contexts.put(rg, new AlignmentContext(context.getLocation(), rgPileup));
+        }
+
+        return contexts;
+    }
+
+    public static Map<String, AlignmentContext> splitContextBySampleName(ReadBackedPileup pileup) {
+        return splitContextBySampleName(new AlignmentContext(pileup.getLocation(), pileup));
+    }
+
+
+    public static AlignmentContext joinContexts(Collection<AlignmentContext> contexts) {
+        // validation
+        GenomeLoc loc = contexts.iterator().next().getLocation();
+        for(AlignmentContext context: contexts) {
+            if(!loc.equals(context.getLocation()))
+                throw new ReviewedGATKException("Illegal attempt to join contexts from different genomic locations");
+        }
+
+        List<PileupElement> pe = new ArrayList<PileupElement>();
+        for(AlignmentContext context: contexts) {
+            for(PileupElement pileupElement: context.basePileup)
+                pe.add(pileupElement);
+        }
+        return new AlignmentContext(loc, new ReadBackedPileupImpl(loc,pe));
+    }
+}
\ No newline at end of file
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/contexts/ReferenceContext.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/contexts/ReferenceContext.java
new file mode 100644
index 0000000..201ea49
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/contexts/ReferenceContext.java
@@ -0,0 +1,217 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.engine.contexts;
+
+import com.google.java.contract.Ensures;
+import com.google.java.contract.Requires;
+import org.broadinstitute.gatk.utils.BaseUtils;
+import org.broadinstitute.gatk.utils.GenomeLoc;
+import org.broadinstitute.gatk.utils.GenomeLocParser;
+
+/**
+ * The section of the reference that overlaps with the given
+ * read / locus. 
+ *
+ * @author hanna
+ * @version 0.1
+ */
+public class ReferenceContext {
+    /**
+     * Facilitates creation of new GenomeLocs.
+     */
+    final private GenomeLocParser genomeLocParser;
+
+    /**
+     * The locus.
+     */
+    final private GenomeLoc locus;
+
+    /**
+     * The window of reference information around the current locus.
+     */
+    final private GenomeLoc window;
+
+    /**
+     * The bases in the window around the current locus.  If null, then bases haven't been fetched yet.
+     * Bases are always upper cased
+     */
+    private byte[] basesCache = null;
+
+    /**
+     * Lazy loader to fetch reference bases
+     */
+    final private ReferenceContextRefProvider basesProvider;
+
+    /**
+     * Interface to create byte[] contexts for lazy loading of the reference
+     */
+    public static interface ReferenceContextRefProvider {
+        /**
+         * You must provide a routine that gets the byte[] bases that would have been passed into the
+         * ReferenceContext.  The RC will handling caching.  The value of this interface and routine is
+         * that it is only called when the bytes are actually requested by the walker, not up front.  So
+         * if the walker doesn't need the refBases for whatever reason, there's no overhead to
+         * provide them.
+         *
+         * @return
+         */
+        @Ensures({"result != null"})
+        public byte[] getBases();
+    }
+
+    private static class ForwardingProvider implements ReferenceContextRefProvider {
+        byte[] bases;
+
+        public ForwardingProvider( byte base ) {
+            this(new byte[] { base });
+        }
+
+        public ForwardingProvider( byte[] bases ) {
+            this.bases = bases;
+        }
+
+        public byte[] getBases() { return bases; }
+    }
+
+    /**
+     * Contructor for a simple, windowless reference context.
+     * @param locus locus of interest.
+     * @param base reference base at that locus.
+     */
+    @Requires({
+            "genomeLocParser != null",
+            "locus != null",
+            "locus.size() > 0"})
+    public ReferenceContext( GenomeLocParser genomeLocParser, GenomeLoc locus, byte base ) {
+        this( genomeLocParser, locus, locus, new ForwardingProvider(base) );
+    }
+
+    @Requires({
+            "genomeLocParser != null",
+            "locus != null",
+            "locus.size() > 0",
+            "window != null",
+            "window.size() > 0",
+            "bases != null && bases.length > 0"})
+    public ReferenceContext( GenomeLocParser genomeLocParser, GenomeLoc locus, GenomeLoc window, byte[] bases ) {
+        this( genomeLocParser, locus, window, new ForwardingProvider(bases) );
+    }
+
+    @Requires({
+            "genomeLocParser != null",
+            "locus != null",
+            "locus.size() > 0",
+            "window != null",
+            "window.size() > 0",
+            "basesProvider != null"})
+    public ReferenceContext( GenomeLocParser genomeLocParser, GenomeLoc locus, GenomeLoc window, ReferenceContextRefProvider basesProvider ) {
+        this.genomeLocParser = genomeLocParser;
+        this.locus = locus;
+        this.window = window;
+        this.basesProvider = basesProvider;
+    }
+
+    /**
+     * Utility function to load bases from the provider to the cache, if necessary
+     */
+    @Ensures({
+            "basesCache != null",
+            "old(basesCache) == null || old(basesCache) == basesCache"})
+    private void fetchBasesFromProvider() {
+        if ( basesCache == null ) {
+            basesCache = basesProvider.getBases();
+
+            // must be an assertion that only runs when the bases are fetch to run in a reasonable amount of time
+            assert BaseUtils.isUpperCase(basesCache);
+        }
+    }
+
+    /**
+     * @return The genome loc parser associated with this reference context
+     */
+    @Ensures("result != null")
+    public GenomeLocParser getGenomeLocParser() {
+        return genomeLocParser;
+    }
+
+    /**
+     * The locus currently being examined.
+     * @return The current locus.
+     */
+    @Ensures("result != null")
+    public GenomeLoc getLocus() {
+        return locus;
+    }
+
+    @Ensures("result != null")
+    public GenomeLoc getWindow() {
+        return window;
+    }
+
+    /**
+     * Get the base at the given locus.
+     * @return The base at the given locus from the reference.
+     */
+    public byte getBase() {
+        return getBases()[(locus.getStart() - window.getStart())];
+    }
+
+    /**
+     * All the bases in the window currently being examined.
+     * @return All bases available.  If the window is of size [0,0], the array will
+     *         contain only the base at the given locus.
+     */
+    @Ensures({"result != null", "result.length > 0"})
+    public byte[] getBases() {
+        fetchBasesFromProvider();
+        return basesCache;
+    }
+
+    /**
+     * All the bases in the window from the current base forward to the end of the window.
+     */
+    @Ensures({"result != null", "result.length > 0"})
+    public byte[] getForwardBases() {
+        final byte[] bases = getBases();
+        final int mid = locus.getStart() - window.getStart();
+        // todo -- warning of performance problem, especially if this is called over and over
+        return new String(bases).substring(mid).getBytes();
+    }
+
+    @Deprecated
+    public char getBaseAsChar() {
+        return (char)getBase();
+    }
+
+    /**
+     * Get the base at the given locus.
+     * @return The base at the given locus from the reference.
+     */
+    @Deprecated()
+    public int getBaseIndex() {
+        return BaseUtils.simpleBaseToBaseIndex(getBase());
+    }
+}
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/datasources/package-info.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/datasources/package-info.java
new file mode 100644
index 0000000..680da25
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/datasources/package-info.java
@@ -0,0 +1,26 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.engine.datasources;
\ No newline at end of file
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/datasources/providers/AllLocusView.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/datasources/providers/AllLocusView.java
new file mode 100644
index 0000000..56ecce2
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/datasources/providers/AllLocusView.java
@@ -0,0 +1,169 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.engine.datasources.providers;
+
+import org.broadinstitute.gatk.engine.contexts.AlignmentContext;
+import org.broadinstitute.gatk.engine.iterators.GenomeLocusIterator;
+import org.broadinstitute.gatk.utils.GenomeLoc;
+import org.broadinstitute.gatk.utils.pileup.ReadBackedPileupImpl;
+import org.broadinstitute.gatk.utils.sam.GATKSAMRecord;
+
+import java.util.Collections;
+import java.util.List;
+import java.util.NoSuchElementException;
+/**
+ * User: hanna
+ * Date: May 13, 2009
+ * Time: 3:32:30 PM
+ * BROAD INSTITUTE SOFTWARE COPYRIGHT NOTICE AND AGREEMENT
+ * Software and documentation are copyright 2005 by the Broad Institute.
+ * All rights are reserved.
+ *
+ * Users acknowledge that this software is supplied without any warranty or support.
+ * The Broad Institute is not responsible for its use, misuse, or
+ * functionality.
+ */
+
+/**
+ * A LocusView over which the user can iterate.
+ */
+
+public class AllLocusView extends LocusView {
+    private GenomeLocusIterator locusIterator;
+
+    /**
+     * Gets the next position in the view: next call to next() will jump there.
+     * Note that both nextPosition and nextLocus are PRE-read and cached.
+     */
+    private GenomeLoc nextPosition = null;
+
+    /**
+     * What's the next available context?
+     */
+    private AlignmentContext nextLocus = null;
+
+    /**
+     * Signal not to advance the iterator because we're currently sitting at the next element.
+     */
+    private boolean atNextElement = false;
+
+    /**
+     * Create a new queue of locus contexts.
+     *
+     * @param provider
+     */
+    public AllLocusView(LocusShardDataProvider provider) {
+        super(provider);
+        // Seed the state tracking members with the first possible seek position and the first possible locus context.
+        locusIterator = new GenomeLocusIterator(genomeLocParser, provider.getLocus());
+    }
+
+    public boolean hasNext() {
+        advance();
+        return nextPosition != null;
+    }
+
+    public AlignmentContext next() {
+        advance();
+
+        if (nextPosition == null)
+            throw new NoSuchElementException("No next is available in the all locus view");
+
+        // Flag to the iterator that no data is waiting in the queue to be processed.
+        atNextElement = false;
+
+        AlignmentContext currentLocus;
+
+        // If actual data is present, return it.  Otherwise, return empty data.
+        if (nextLocus != null && nextLocus.getLocation().equals(nextPosition))
+            currentLocus = nextLocus;
+        else
+            currentLocus = createEmptyLocus(nextPosition);
+
+        return currentLocus;
+    }
+
+    private void advance() {
+        // Already at the next element?  Don't move forward.
+        if (atNextElement)
+            return;
+
+        // Out of elements?
+        if (nextPosition == null && !locusIterator.hasNext())
+            return;
+
+        // If nextLocus has been consumed, clear it out to make room for the next incoming locus.
+        if (nextPosition != null && nextLocus != null && !nextLocus.getLocation().isPast(nextPosition)) {
+            nextLocus = null;
+
+            // Determine the next locus. The trick is that we may have more than one alignment context at the same
+            // reference position (regular base pileup, then extended pileup). If next alignment context (that we just pre-read)
+            // is still at the current position, we do not increment current position and wait for next call to next() to return
+            // that context. If we know that next context is past the current position, we are done with current
+            // position
+            if (hasNextLocus()) {
+                nextLocus = nextLocus();
+                if (nextPosition.equals(nextLocus.getLocation())) {
+                    atNextElement = true;
+                    return;
+                }
+            }
+        }
+
+        // No elements left in queue?  Clear out the position state tracker and return.
+        if (!locusIterator.hasNext()) {
+            nextPosition = null;
+            return;
+        }
+
+        // Actually fill the next position.
+        nextPosition = locusIterator.next();
+        atNextElement = true;
+
+        // Crank the iterator to (if possible) or past the next context.  Be careful not to hold a reference to nextLocus
+        // while using the hasNextLocus() / nextLocus() machinery; this will cause us to use more memory than is optimal. 
+        while (nextLocus == null || nextLocus.getLocation().isBefore(nextPosition)) {
+            nextLocus = null;
+            if (!hasNextLocus())
+                break;
+            nextLocus = nextLocus();
+        }
+    }
+
+    /**
+     * Creates a blank locus context at the specified location.
+     *
+     * @param site Site at which to create the blank locus context.
+     * @return empty context.
+     */
+    private final static List<GATKSAMRecord> EMPTY_PILEUP_READS = Collections.emptyList();
+    private final static List<Integer> EMPTY_PILEUP_OFFSETS = Collections.emptyList();
+    private final static List<Boolean> EMPTY_DELETION_STATUS = Collections.emptyList();
+
+    private AlignmentContext createEmptyLocus(GenomeLoc site) {
+        return new AlignmentContext(site, new ReadBackedPileupImpl(site, EMPTY_PILEUP_READS, EMPTY_PILEUP_OFFSETS));
+    }
+}
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/datasources/providers/CoveredLocusView.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/datasources/providers/CoveredLocusView.java
new file mode 100644
index 0000000..900612a
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/datasources/providers/CoveredLocusView.java
@@ -0,0 +1,63 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.engine.datasources.providers;
+
+import org.broadinstitute.gatk.engine.contexts.AlignmentContext;
+/**
+ * User: hanna
+ * Date: May 12, 2009
+ * Time: 11:24:42 AM
+ * BROAD INSTITUTE SOFTWARE COPYRIGHT NOTICE AND AGREEMENT
+ * Software and documentation are copyright 2005 by the Broad Institute.
+ * All rights are reserved.
+ *
+ * Users acknowledge that this software is supplied without any warranty or support.
+ * The Broad Institute is not responsible for its use, misuse, or
+ * functionality.
+ */
+
+/**
+ * A queue of locus contexts.  Provides unidirectional seek.  Stripped down
+ * implementation of java.util.Queue interface.
+ */
+
+public class CoveredLocusView extends LocusView {
+    /**
+     * Create a new queue of locus contexts.
+     * @param provider
+     */
+    public CoveredLocusView(LocusShardDataProvider provider) {
+        super(provider);
+    }
+
+    public boolean hasNext() {
+        return hasNextLocus();
+    }
+
+    public AlignmentContext next() {
+        return nextLocus();
+    }
+}
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/datasources/providers/IntervalOverlappingRODsFromStream.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/datasources/providers/IntervalOverlappingRODsFromStream.java
new file mode 100644
index 0000000..9100905
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/datasources/providers/IntervalOverlappingRODsFromStream.java
@@ -0,0 +1,168 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.engine.datasources.providers;
+
+import com.google.java.contract.Ensures;
+import com.google.java.contract.Requires;
+import htsjdk.samtools.util.PeekableIterator;
+import org.broadinstitute.gatk.engine.refdata.RODRecordListImpl;
+import org.broadinstitute.gatk.engine.refdata.utils.GATKFeature;
+import org.broadinstitute.gatk.engine.refdata.utils.RODRecordList;
+import org.broadinstitute.gatk.utils.GenomeLoc;
+
+import java.util.Collection;
+import java.util.LinkedList;
+import java.util.ListIterator;
+
+/**
+ * Key algorithmic helper for ReadBasedReferenceOrderedData
+ *
+ * Takes a single iterator of features, and provides a single capability that returns
+ * the list of RODs that overlap an interval.  Allows sequential getOverlapping calls
+ * from intervals provided that these intervals always have increasing getStart() values.
+ *
+ */
+class IntervalOverlappingRODsFromStream {
+    /**
+     * Only held for QC purposes
+     */
+    GenomeLoc lastQuery = null;
+
+    private final String name;
+    private final LinkedList<GATKFeature> currentFeatures = new LinkedList<GATKFeature>();
+    private final PeekableIterator<RODRecordList> futureFeatures;
+
+    /**
+     * Create a new IntervalOverlappingRODsFromStream that reads elements from futureFeatures and
+     * returns RODRecordLists having name
+     *
+     * @param name
+     * @param futureFeatures
+     */
+    IntervalOverlappingRODsFromStream(final String name, final PeekableIterator<RODRecordList> futureFeatures) {
+        if ( futureFeatures == null ) throw new IllegalArgumentException("futureFeatures cannot be null");
+
+        this.name = name;
+        this.futureFeatures = futureFeatures;
+    }
+
+    /**
+     * Get the list of RODs overlapping loc from this stream of RODs.
+     *
+     * @param loc the interval to query
+     * @return a non-null RODRecordList containing the overlapping RODs, which may be empty
+     */
+    @Ensures({"overlaps(loc, result)",
+            "! futureFeatures.hasNext() || futureFeatures.peek().getLocation().isPast(loc)",
+            "result != null"})
+    public RODRecordList getOverlapping(final GenomeLoc loc) {
+        if ( lastQuery != null && loc.getStart() < lastQuery.getStart() )
+            throw new IllegalArgumentException(String.format("BUG: query interval (%s) starts before the previous interval %s", loc, lastQuery));
+
+        readOverlappingFutureFeatures(loc);
+        return new RODRecordListImpl(name, subsetToOverlapping(loc, currentFeatures), loc);
+    }
+
+
+    /**
+     * For contract assurance.  Checks that all bindings in loc overlap
+     *
+     * @param loc
+     * @param bindings
+     * @return
+     */
+    @Requires({"loc != null", "bindings != null"})
+    private boolean overlaps(final GenomeLoc loc, final RODRecordList bindings) {
+        for ( final GATKFeature feature : bindings )
+            if ( ! feature.getLocation().overlapsP(loc) )
+                return false;
+        return true;
+    }
+
+    /**
+     * Subset the features in all to those that overlap with loc
+     *
+     * The current features list contains everything read that cannot be thrown away yet, but not
+     * everything in there necessarily overlaps with loc.  Subset to just those that do overlap
+     *
+     * @param loc the location that features must overlap
+     * @param all the list of all features
+     * @return a subset of all that overlaps with loc
+     */
+    @Requires({"loc != null", "all != null"})
+    @Ensures("result.size() <= all.size()")
+    private Collection<GATKFeature> subsetToOverlapping(final GenomeLoc loc, final Collection<GATKFeature> all) {
+        final LinkedList<GATKFeature> overlapping = new LinkedList<GATKFeature>();
+        for ( final GATKFeature feature : all )
+            if ( feature.getLocation().overlapsP(loc) )
+                overlapping.add(feature);
+        return overlapping;
+    }
+
+    /**
+     * Update function.  Remove all elements of currentFeatures that end before loc
+     *
+     * Must be called by clients periodically when they know they they will never ask for data before
+     * loc, so that the running cache of RODs doesn't grow out of control.
+     *
+     * @param loc the location to use
+     */
+    @Requires("loc != null")
+    @Ensures("currentFeatures.size() <= old(currentFeatures.size())")
+    public void trimCurrentFeaturesToLoc(final GenomeLoc loc) {
+        final ListIterator<GATKFeature> it = currentFeatures.listIterator();
+        while ( it.hasNext() ) {
+            final GATKFeature feature = it.next();
+            if ( feature.getLocation().isBefore(loc) )
+                it.remove();
+        }
+    }
+
+    /**
+     * Update function: Read all elements from futureFeatures that overlap with loc
+     *
+     * Stops at the first element that starts before the end of loc, or the stream empties
+     *
+     * @param loc
+     */
+    @Requires("loc != null")
+    @Ensures("currentFeatures.size() >= old(currentFeatures.size())")
+    private void readOverlappingFutureFeatures(final GenomeLoc loc) {
+        while ( futureFeatures.hasNext() ) {
+            final GenomeLoc nextLoc = futureFeatures.peek().getLocation();
+            if ( nextLoc.isBefore(loc) ) {
+                futureFeatures.next(); // next rod element is before loc, throw it away and keep looking
+            } else if ( nextLoc.isPast(loc) ) {
+                break; // next element is past loc, stop looking but don't pop it
+            } else if ( nextLoc.overlapsP(loc) ) {
+                // add overlapping elements to our current features, removing from stream
+                for ( final GATKFeature feature : futureFeatures.next() ) {
+                    currentFeatures.add(feature);
+                }
+            }
+        }
+    }
+}
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/datasources/providers/IntervalReferenceOrderedView.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/datasources/providers/IntervalReferenceOrderedView.java
new file mode 100644
index 0000000..23f4f73
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/datasources/providers/IntervalReferenceOrderedView.java
@@ -0,0 +1,184 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.engine.datasources.providers;
+
+import htsjdk.samtools.util.PeekableIterator;
+import org.broadinstitute.gatk.engine.contexts.ReferenceContext;
+import org.broadinstitute.gatk.engine.datasources.reads.ReadShard;
+import org.broadinstitute.gatk.engine.datasources.rmd.ReferenceOrderedDataSource;
+import org.broadinstitute.gatk.engine.refdata.RefMetaDataTracker;
+import org.broadinstitute.gatk.engine.refdata.utils.LocationAwareSeekableRODIterator;
+import org.broadinstitute.gatk.engine.refdata.utils.RODRecordList;
+import org.broadinstitute.gatk.utils.GenomeLoc;
+import org.broadinstitute.gatk.utils.GenomeLocParser;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+
+/**
+ * a ROD view that allows for requests for RODs that overlap intervals on the genome to produce a RefMetaDataTracker
+ */
+public class IntervalReferenceOrderedView implements ReferenceOrderedView {
+    /** a list of the RMDDataState (location->iterators) */
+    private final List<RMDDataState> states = new ArrayList<>(1);
+
+    /**
+     * Used to get genome locs for reads
+     */
+    protected final GenomeLocParser genomeLocParser;
+
+    /**
+     * The total extent of all reads in this span.  We create iterators from our RODs
+     * from the start of this span, to the end.
+     */
+    private final GenomeLoc shardSpan;
+
+    /**
+     * Create a new IntervalReferenceOrderedView taking data from provider and capable of
+     * servicing ROD overlap requests within the genomic interval span
+     *
+     * @param provider a ShardDataProvider to give us data
+     * @param span a GenomeLoc span, or null indicating take the entire genome
+     */
+    public IntervalReferenceOrderedView(final ShardDataProvider provider, final GenomeLoc span) {
+        if ( provider == null ) throw new IllegalArgumentException("provider cannot be null");
+        if ( provider.hasReferenceOrderedData() && span == null ) throw new IllegalArgumentException("span cannot be null when provider has reference ordered data");
+
+        this.genomeLocParser = provider.getGenomeLocParser();
+        this.shardSpan = span;
+        provider.register(this);
+
+        // conditional to optimize the case where we don't have any ROD data
+        if ( provider.hasReferenceOrderedData() && ! shardSpan.isUnmapped() ) {
+            for (final ReferenceOrderedDataSource dataSource : provider.getReferenceOrderedData())
+                states.add(new RMDDataState(dataSource, dataSource.seek(shardSpan)));
+        }
+    }
+
+    /**
+     * Testing constructor
+     */
+    protected IntervalReferenceOrderedView(final GenomeLocParser genomeLocParser,
+                                           final GenomeLoc shardSpan,
+                                           final List<String> names,
+                                           final List<PeekableIterator<RODRecordList>> featureSources) {
+        this.genomeLocParser = genomeLocParser;
+        this.shardSpan = shardSpan;
+        for ( int i = 0; i < names.size(); i++ )
+            states.add(new RMDDataState(names.get(i), featureSources.get(i)));
+    }
+
+    public Collection<Class<? extends View>> getConflictingViews() {
+        List<Class<? extends View>> classes = new ArrayList<>();
+        classes.add(ManagingReferenceOrderedView.class);
+        return classes;
+    }
+
+    /**
+     * Get a RefMetaDataTracker containing bindings for all RODs overlapping the start position of loc
+     * @param loc a GenomeLoc of size == 1
+     * @return a non-null RefMetaDataTracker
+     */
+    @Override
+    public RefMetaDataTracker getReferenceOrderedDataAtLocus(GenomeLoc loc) {
+        if ( loc == null ) throw new IllegalArgumentException("loc cannot be null");
+        if ( loc.size() != 1 ) throw new IllegalArgumentException("GenomeLoc must have size == 1 but got " + loc);
+        return getReferenceOrderedDataForInterval(loc);
+    }
+
+    /**
+     * Get a RefMetaDataTracker containing bindings for all RODs overlapping interval
+     *
+     * @param interval a non=null interval
+     * @return a non-null RefMetaDataTracker
+     */
+    public RefMetaDataTracker getReferenceOrderedDataForInterval(final GenomeLoc interval) {
+        if ( interval == null ) throw new IllegalArgumentException("Interval cannot be null");
+
+        if ( states.isEmpty() || shardSpan.isUnmapped() ) // optimization for no bindings (common for read walkers)
+            return RefMetaDataTracker.EMPTY_TRACKER;
+        else {
+            final List<RODRecordList> bindings = new ArrayList<>(states.size());
+            for ( final RMDDataState state : states )
+                bindings.add(state.stream.getOverlapping(interval));
+            return new RefMetaDataTracker(bindings);
+        }
+    }
+
+    /**
+     * Trim down all of the ROD managers so that they only hold ROD bindings wit start >= startOfDataToKeep.getStart()
+     *
+     * @param startOfDataToKeep a non-null genome loc
+     */
+    public void trimCurrentFeaturesToLoc(final GenomeLoc startOfDataToKeep) {
+        if ( startOfDataToKeep == null ) throw new IllegalArgumentException("startOfDataToKeep cannot be null");
+
+        for ( final RMDDataState state : states )
+            state.stream.trimCurrentFeaturesToLoc(startOfDataToKeep);
+    }
+
+    /**
+     * Closes the current view.
+     */
+    public void close() {
+        for (final RMDDataState state : states)
+            state.close();
+
+        // Clear out the existing data so that post-close() accesses to this data will fail-fast.
+        states.clear();
+    }
+
+    /**
+     * Models the traversal state of a given ROD lane.
+     */
+    private static class RMDDataState {
+        public final ReferenceOrderedDataSource dataSource;
+        public final IntervalOverlappingRODsFromStream stream;
+        private final LocationAwareSeekableRODIterator iterator;
+
+        public RMDDataState(ReferenceOrderedDataSource dataSource, LocationAwareSeekableRODIterator iterator) {
+            this.dataSource = dataSource;
+            this.iterator = iterator;
+            this.stream = new IntervalOverlappingRODsFromStream(dataSource.getName(), new PeekableIterator<>(iterator));
+        }
+
+        /**
+         * For testing
+         */
+        public RMDDataState(final String name, final PeekableIterator<RODRecordList> iterator) {
+            this.dataSource = null;
+            this.iterator = null;
+            this.stream = new IntervalOverlappingRODsFromStream(name, new PeekableIterator<>(iterator));
+        }
+
+        public void close() {
+            if ( dataSource != null )
+                dataSource.close( iterator );
+        }
+    }
+}
+
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/datasources/providers/InvalidPositionException.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/datasources/providers/InvalidPositionException.java
new file mode 100644
index 0000000..997435d
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/datasources/providers/InvalidPositionException.java
@@ -0,0 +1,46 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.engine.datasources.providers;
+
+/**
+ * Created by IntelliJ IDEA.
+ * User: hanna
+ * Date: Apr 16, 2009
+ * Time: 4:11:40 PM
+ *
+ * Thrown to indicate invalid positions passed to the providers.
+ * Extend from RuntimeException to make it easier on our walker writers; don't make
+ * them catch every exception that comes their way.
+ */
+public class InvalidPositionException extends RuntimeException {
+    public InvalidPositionException(String message) {
+        super(message);
+    }
+
+    public InvalidPositionException(String message, Throwable throwable) {
+        super(message,throwable);
+    }
+}
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/datasources/providers/LocusReferenceView.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/datasources/providers/LocusReferenceView.java
new file mode 100644
index 0000000..b535050
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/datasources/providers/LocusReferenceView.java
@@ -0,0 +1,236 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.engine.datasources.providers;
+
+import htsjdk.samtools.reference.ReferenceSequence;
+import org.broadinstitute.gatk.engine.contexts.ReferenceContext;
+import org.broadinstitute.gatk.engine.walkers.Reference;
+import org.broadinstitute.gatk.engine.walkers.Walker;
+import org.broadinstitute.gatk.engine.walkers.Window;
+import org.broadinstitute.gatk.utils.GenomeLoc;
+import org.broadinstitute.gatk.utils.exceptions.ReviewedGATKException;
+/*
+ * 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.
+ */
+
+/**
+ * Provides access to the portion of the reference covering a single locus.
+ */
+public class LocusReferenceView extends ReferenceView {
+    /**
+     * Bound the reference view to make sure all accesses are within the shard.
+     */
+    private GenomeLoc bounds;
+
+    /**
+     * Start of the expanded window for which the reference context should be provided,
+     * relative to the locus in question.
+     */
+    private final int windowStart;
+
+
+    /**
+     * Start of the expanded window for which the reference context should be provided,
+     * relative to the locus in question.
+     */
+    private final int windowStop;
+
+    /**
+     * Track the reference sequence and the last point accessed.  Used to
+     * track state when traversing over the reference.
+     */
+    private ReferenceSequence referenceSequence;
+
+    /**
+     * Create a LocusReferenceView given no other contextual information about
+     * the walkers, etc.
+     * @param provider  source for locus data.
+     */
+    public LocusReferenceView( LocusShardDataProvider provider ) {
+        super(provider);
+        initializeBounds(provider);
+        windowStart = windowStop = 0;
+        initializeReferenceSequence(bounds);
+    }
+
+    /**
+     * Create a new locus reference view.
+     * @param provider source for locus data.
+     */
+    public LocusReferenceView( Walker walker, LocusShardDataProvider provider ) {
+        super( provider );
+        initializeBounds(provider);
+
+        // Retrieve information about the window being accessed.
+        if( walker.getClass().isAnnotationPresent(Reference.class) ) {
+            Window window = walker.getClass().getAnnotation(Reference.class).window();
+
+            if( window.start() > 0 ) throw new ReviewedGATKException( "Reference window starts after current locus" );
+            if( window.stop() < 0 ) throw new ReviewedGATKException( "Reference window ends before current locus" );
+
+            windowStart = window.start();
+            windowStop = window.stop();
+        }
+        else {
+            windowStart = 0;
+            windowStop = 0;
+        }
+
+        if(bounds != null) {
+            int expandedStart = getWindowStart( bounds );
+            int expandedStop  = getWindowStop( bounds );
+            initializeReferenceSequence(genomeLocParser.createGenomeLoc(bounds.getContig(), bounds.getContigIndex(), expandedStart, expandedStop));
+        }
+    }
+
+    /**
+     * Initialize the bounds of this shard, trimming the bounds so that they match the reference.
+     * @param provider Provider covering the appropriate locus.
+     */
+    private void initializeBounds(LocusShardDataProvider provider) {
+        if(provider.getLocus() != null) {
+            int sequenceLength = reference.getSequenceDictionary().getSequence(provider.getLocus().getContig()).getSequenceLength();
+            bounds = genomeLocParser.createGenomeLoc(provider.getLocus().getContig(),
+                    Math.max(provider.getLocus().getStart(),1),
+                    Math.min(provider.getLocus().getStop(),sequenceLength));
+        }
+        else
+            bounds = null;
+    }
+
+    /**
+     * Initialize reference sequence data using the given locus.
+     * @param locus
+     */
+    private void initializeReferenceSequence( GenomeLoc locus ) {
+        this.referenceSequence = reference.getSubsequenceAt( locus.getContig(), locus.getStart(), locus.getStop() );
+    }
+
+    protected GenomeLoc trimToBounds(GenomeLoc l) {
+        int expandedStart = getWindowStart( bounds );
+        int expandedStop  = getWindowStop( bounds );
+        if ( l.getStart() < expandedStart ) l = genomeLocParser.setStart(l, expandedStart);
+        if ( l.getStop() > expandedStop  ) l = genomeLocParser.setStop(l, expandedStop);
+        return l;
+    }
+
+    public class Provider implements ReferenceContext.ReferenceContextRefProvider {
+        int refStart, len;
+
+        public Provider( int refStart, int len ) {
+            this.refStart = refStart;
+            this.len = len;
+        }
+
+        public byte[] getBases() {
+            //System.out.printf("Getting bases for location%n");
+            byte[] bases = new byte[len];
+            System.arraycopy(referenceSequence.getBases(), refStart, bases, 0, len);
+            return bases;
+        }
+    }
+
+    /**
+     * Gets the reference context associated with this particular point or extended interval on the genome.
+     * @param genomeLoc Region for which to retrieve the base(s). If region spans beyond contig end or beyond current bounds, it will be trimmed down.
+     * @return The base at the position represented by this genomeLoc.
+     */
+    public ReferenceContext getReferenceContext( GenomeLoc genomeLoc ) {
+        //validateLocation( genomeLoc );
+
+        GenomeLoc window = genomeLocParser.createGenomeLoc( genomeLoc.getContig(), genomeLoc.getContigIndex(),
+                getWindowStart(genomeLoc), getWindowStop(genomeLoc) );
+
+        int refStart = -1;
+        if (bounds != null) {
+            window = trimToBounds(window);
+            refStart = (int)(window.getStart() - getWindowStart(bounds));
+        }
+        else {
+            if(referenceSequence == null || referenceSequence.getContigIndex() != genomeLoc.getContigIndex())
+                referenceSequence = reference.getSequence(genomeLoc.getContig());
+            refStart = (int)window.getStart()-1;
+        }
+
+        int len = (int)window.size();
+        return new ReferenceContext( genomeLocParser, genomeLoc, window, new Provider(refStart, len));
+    }
+
+    /**
+     * Allow the user to pull reference info from any arbitrary region of the reference.
+     * @param genomeLoc The locus.
+     * @return A list of the bases starting at the start of the locus (inclusive) and ending
+     *         at the end of the locus (inclusive).
+     */
+    public byte[] getReferenceBases( GenomeLoc genomeLoc ) {
+        return super.getReferenceBases(genomeLoc);
+    }
+
+    /**
+     * Gets the start of the expanded window, bounded if necessary by the contig.
+     * @param locus The locus to expand.
+     * @return The expanded window.
+     */
+    private int getWindowStart( GenomeLoc locus ) {
+        // If the locus is not within the bounds of the contig it allegedly maps to, expand only as much as we can.
+        if(locus.getStart() < 1) return 1;
+//        if(locus.getStart() < 1) return locus.getStart();
+        return Math.max( locus.getStart() + windowStart, 1 );
+    }
+
+    /**
+     * Gets the stop of the expanded window, bounded if necessary by the contig.
+     * @param locus The locus to expand.
+     * @return The expanded window.
+     */    
+    private int getWindowStop( GenomeLoc locus ) {
+        // If the locus is not within the bounds of the contig it allegedly maps to, expand only as much as we can.
+        int sequenceLength = reference.getSequenceDictionary().getSequence(locus.getContig()).getSequenceLength();
+        if(locus.getStop() > sequenceLength) return sequenceLength;
+        return Math.min( locus.getStop() + windowStop, sequenceLength );
+    }
+}
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/datasources/providers/LocusShardDataProvider.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/datasources/providers/LocusShardDataProvider.java
new file mode 100644
index 0000000..7dc589d
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/datasources/providers/LocusShardDataProvider.java
@@ -0,0 +1,100 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.engine.datasources.providers;
+
+import htsjdk.samtools.reference.IndexedFastaSequenceFile;
+import org.broadinstitute.gatk.engine.ReadProperties;
+import org.broadinstitute.gatk.engine.datasources.reads.Shard;
+import org.broadinstitute.gatk.engine.datasources.rmd.ReferenceOrderedDataSource;
+import org.broadinstitute.gatk.utils.locusiterator.LocusIterator;
+import org.broadinstitute.gatk.utils.GenomeLoc;
+import org.broadinstitute.gatk.utils.GenomeLocParser;
+
+import java.util.Collection;
+
+/**
+ * Presents data sharded by locus to the traversal engine.
+ *
+ * @author mhanna
+ * @version 0.1
+ */
+public class LocusShardDataProvider extends ShardDataProvider {
+    /**
+     * Information about the source of the read data.
+     */
+    private final ReadProperties sourceInfo;
+
+    /**
+     * The particular locus for which data is provided.  Should be contained within shard.getGenomeLocs().
+     */
+    private final GenomeLoc locus;
+
+    /**
+     * The raw collection of reads.
+     */
+    private final LocusIterator locusIterator;
+
+    /**
+     * Create a data provider for the shard given the reads and reference.
+     * @param shard The chunk of data over which traversals happen.
+     * @param reference A getter for a section of the reference.
+     */
+    public LocusShardDataProvider(Shard shard, ReadProperties sourceInfo, GenomeLocParser genomeLocParser, GenomeLoc locus, LocusIterator locusIterator, IndexedFastaSequenceFile reference, Collection<ReferenceOrderedDataSource> rods) {
+        super(shard,genomeLocParser,reference,rods);
+        this.sourceInfo = sourceInfo;
+        this.locus = locus;
+        this.locusIterator = locusIterator;
+    }
+
+    /**
+     * Returns information about the source of the reads.
+     * @return Info about the source of the reads.
+     */
+    public ReadProperties getSourceInfo() {
+        return sourceInfo;
+    }
+
+    /**
+     * Gets the locus associated with this shard data provider.
+     * @return The locus.
+     */
+    public GenomeLoc getLocus() {
+        return locus;
+    }
+
+    /**
+     * Gets an iterator over all the reads bound by this shard.
+     * @return An iterator over all reads in this shard.
+     */
+    public LocusIterator getLocusIterator() {
+        return locusIterator;
+    }        
+
+    @Override
+    public void close() {
+        super.close();
+    }
+}
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/datasources/providers/LocusView.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/datasources/providers/LocusView.java
new file mode 100644
index 0000000..9bc37e5
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/datasources/providers/LocusView.java
@@ -0,0 +1,220 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.engine.datasources.providers;
+
+import org.broadinstitute.gatk.engine.downsampling.DownsampleType;
+import org.broadinstitute.gatk.engine.ReadProperties;
+import org.broadinstitute.gatk.engine.contexts.AlignmentContext;
+import org.broadinstitute.gatk.utils.locusiterator.LocusIterator;
+import org.broadinstitute.gatk.utils.GenomeLoc;
+import org.broadinstitute.gatk.utils.GenomeLocParser;
+import org.broadinstitute.gatk.utils.locusiterator.LocusIteratorByState;
+
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.NoSuchElementException;
+
+/**
+ * User: hanna
+ * Date: May 13, 2009
+ * Time: 3:30:16 PM
+ * BROAD INSTITUTE SOFTWARE COPYRIGHT NOTICE AND AGREEMENT
+ * Software and documentation are copyright 2005 by the Broad Institute.
+ * All rights are reserved.
+ *
+ * Users acknowledge that this software is supplied without any warranty or support.
+ * The Broad Institute is not responsible for its use, misuse, or
+ * functionality.
+ */
+
+/**
+ * The two goals of the LocusView are as follows:
+ * 1) To provide a 'trigger track' iteration interface so that TraverseLoci can easily switch
+ *    between iterating over all bases in a region, only covered bases in a region covered by
+ *    reads, only bases in a region covered by RODs, or any other sort of trigger track
+ *    implementation one can think of.
+ * 2) To manage the copious number of iterators that have to be jointly pulled through the
+ *    genome to make a locus traversal function.
+ */
+public abstract class LocusView extends LocusIterator implements View {
+    /**
+     * The locus bounding this view.
+     */
+    protected GenomeLoc locus;
+
+    /**
+     * The GenomeLocParser, used to create new genome locs.
+     */
+    protected GenomeLocParser genomeLocParser;
+
+    /**
+     * Source info for this view.  Informs the class about downsampling requirements.
+     */
+    private ReadProperties sourceInfo;
+
+    /**
+     * The actual locus context iterator.
+     */
+    private LocusIterator loci;
+
+    /**
+     * The next locus context from the iterator.  Lazy loaded: if nextLocus is null and advance() doesn't
+     * populate it, the iterator is exhausted.  If populated, this is the value that should be returned by
+     * next(). 
+     */
+    private AlignmentContext nextLocus = null;
+
+    public LocusView(LocusShardDataProvider provider) {
+        this.locus = provider.getLocus();
+        
+        this.sourceInfo = provider.getSourceInfo();
+        this.genomeLocParser = provider.getGenomeLocParser();
+        this.loci = provider.getLocusIterator();
+
+        advance();
+
+        provider.register(this);
+    }
+
+    /**
+     * Only one view of the locus is supported at any given time.
+     * @return A list consisting of all other locus views.
+     */
+    public Collection<Class<? extends View>> getConflictingViews() {
+        return Arrays.<Class<? extends View>>asList(LocusView.class,ReadView.class);
+    }
+
+    /**
+     * Close this view.
+     */
+    public void close() {
+        // Set everything to null with the hope of failing fast.
+        locus = null;
+        sourceInfo = null;
+        loci = null;
+
+        super.close();
+    }
+
+    /**
+     * Is there another covered locus context bounded by this view.
+     * @return True if another covered locus context exists.  False otherwise.
+     */
+    public abstract boolean hasNext();
+
+    /**
+     * Returns the next covered locus context in the shard.
+     * @return Next covered locus context in the shard.
+     * @throw NoSuchElementException if no such element exists.
+     */
+    public abstract AlignmentContext next();
+
+    /**
+     * Unsupported.
+     * @throw UnsupportedOperationException always.
+     */
+    public void remove() {
+        throw new UnsupportedOperationException("Unable to remove elements from this queue.");
+    }
+
+    /**
+     * Is there another locus context bounded by this shard.
+     * @return True if another locus context is bounded by this shard.
+     */
+    protected boolean hasNextLocus() {
+        advance();
+        return nextLocus != null;
+    }
+
+    /**
+     * Get the next locus context bounded by this shard.
+     * @return Next locus context bounded by this shard.
+     * @throw NoSuchElementException if the next element is missing.
+     */
+    protected AlignmentContext nextLocus() {
+        advance();
+        if(nextLocus == null)
+            throw new NoSuchElementException("No more elements remain in locus context queue.");
+
+        // Cache the current and apply filtering.
+        AlignmentContext current = nextLocus;
+
+        // Indicate that the next operation will need to advance.
+        nextLocus = null;
+        
+        return current;
+    }
+
+    /**
+     * Seed the nextLocus variable with the contents of the next locus (if one exists).
+     */
+    private void advance() {
+        // Already an unclaimed locus present
+        if(nextLocus != null)
+            return;
+
+        //System.out.printf("loci is %s%n", loci);
+        if( !loci.hasNext() ) {
+            nextLocus = null;
+            return;
+        }
+
+        nextLocus = loci.next();
+
+        // If the location of this shard is available, trim the data stream to match the shard.
+        // TODO: Much of this functionality is being replaced by the WindowMaker.
+        if(locus != null) {
+            // Iterate through any elements not contained within this shard.
+            while( nextLocus != null && !isContainedInShard(nextLocus.getLocation()) && loci.hasNext() )
+                nextLocus = loci.next();
+
+            // If nothing in the shard was found, indicate that by setting nextLocus to null.
+            if( nextLocus != null && !isContainedInShard(nextLocus.getLocation()) )
+                nextLocus = null;
+        }
+    }
+
+    /**
+     * Is this location contained in the given shard.
+     * @param location Location to check.
+     * @return True if the given location is contained within the shard.  False otherwise.
+     */
+    private boolean isContainedInShard(GenomeLoc location) {
+        return locus.containsP(location);
+    }
+
+    /**
+     * {@inheritDoc}
+     *
+     * Since this class has an actual LIBS, so this function will never throw an exception
+     *
+     * @return the LocusIteratorByState used by this view to get pileups
+     */
+    @Override
+    public LocusIteratorByState getLIBS() {
+        return loci.getLIBS();
+    }
+}
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/datasources/providers/ManagingReferenceOrderedView.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/datasources/providers/ManagingReferenceOrderedView.java
new file mode 100644
index 0000000..2dd42c1
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/datasources/providers/ManagingReferenceOrderedView.java
@@ -0,0 +1,117 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.engine.datasources.providers;
+
+import org.broadinstitute.gatk.engine.contexts.ReferenceContext;
+import org.broadinstitute.gatk.engine.datasources.rmd.ReferenceOrderedDataSource;
+import org.broadinstitute.gatk.engine.refdata.RefMetaDataTracker;
+import org.broadinstitute.gatk.engine.refdata.utils.LocationAwareSeekableRODIterator;
+import org.broadinstitute.gatk.engine.refdata.utils.RODRecordList;
+import org.broadinstitute.gatk.utils.GenomeLoc;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.List;
+/**
+ * User: hanna
+ * Date: May 21, 2009
+ * Time: 2:49:17 PM
+ * BROAD INSTITUTE SOFTWARE COPYRIGHT NOTICE AND AGREEMENT
+ * Software and documentation are copyright 2005 by the Broad Institute.
+ * All rights are reserved.
+ *
+ * Users acknowledge that this software is supplied without any warranty or support.
+ * The Broad Institute is not responsible for its use, misuse, or
+ * functionality.
+ */
+
+/**
+ * A view into the reference-ordered data in the provider.
+ */
+public class ManagingReferenceOrderedView implements ReferenceOrderedView {
+    /**
+     * The data sources along with their current states.
+     */
+    private List<ReferenceOrderedDataState> states = new ArrayList<ReferenceOrderedDataState>();
+
+    /**
+     * Create a new view of reference-ordered data.
+     * @param provider
+     */
+    public ManagingReferenceOrderedView( LocusShardDataProvider provider ) {
+        for( ReferenceOrderedDataSource dataSource: provider.getReferenceOrderedData() )
+            states.add(new ReferenceOrderedDataState(dataSource, dataSource.seek(provider.getLocus())));
+
+        provider.register(this);
+    }
+
+    public Collection<Class<? extends View>> getConflictingViews() { return Collections.emptyList(); }
+
+    /**
+     * Gets an object which can track the reference-ordered data at every locus.
+     * @param loc Locus at which to track.
+     * @return A tracker containing information about this locus.
+     */
+    @Override
+    public RefMetaDataTracker getReferenceOrderedDataAtLocus( GenomeLoc loc ) {
+        if ( states.isEmpty() )
+            return RefMetaDataTracker.EMPTY_TRACKER;
+        else {
+            List<RODRecordList> bindings = new ArrayList<RODRecordList>(states.size());
+
+            for ( ReferenceOrderedDataState state: states )
+                // todo -- warning, I removed the reference to the name from states
+                bindings.add( state.iterator.seekForward(loc) );
+
+            return new RefMetaDataTracker(bindings);
+        }
+    }
+
+    /**
+     * Closes the current view.
+     */
+    public void close() {
+        for( ReferenceOrderedDataState state: states )
+            state.dataSource.close( state.iterator );
+
+        // Clear out the existing data so that post-close() accesses to this data will fail-fast.
+        states = null;
+    }
+}
+
+/**
+ * Models the traversal state of a given ROD lane.
+ */
+class ReferenceOrderedDataState {
+    public final ReferenceOrderedDataSource dataSource;
+    public final LocationAwareSeekableRODIterator iterator;
+
+    public ReferenceOrderedDataState( ReferenceOrderedDataSource dataSource, LocationAwareSeekableRODIterator iterator ) {
+        this.dataSource = dataSource;
+        this.iterator = iterator;
+    }
+}
\ No newline at end of file
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/datasources/providers/RODMetaDataContainer.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/datasources/providers/RODMetaDataContainer.java
new file mode 100644
index 0000000..f244e50
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/datasources/providers/RODMetaDataContainer.java
@@ -0,0 +1,83 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.engine.datasources.providers;
+
+import org.broadinstitute.gatk.engine.refdata.utils.GATKFeature;
+import org.broadinstitute.gatk.utils.collections.Pair;
+
+import java.util.*;
+
+
+/**
+ * 
+ * @author aaron 
+ * 
+ * Class RODMetaDataContainer
+ *
+ * stores both the name and the class for each ROD.  This class assumes that:
+ *
+ * -Names must be unique
+ * -Classes are allowed to have duplicates
+ *
+ * This class encapsulates the ref data associations, and provides lookup by name and by
+ * class type.
+ *
+ */
+public class RODMetaDataContainer {
+    // we only allow non-duplicate ROD names, a HashMap is fine
+    private final HashMap<String, GATKFeature> nameMap = new HashMap<String, GATKFeature>();
+
+    // we do allow duplicate class entries, so we need to store pairs of data
+    private final List<Pair<Class, GATKFeature>> classMap = new ArrayList<Pair<Class, GATKFeature>>();
+
+    public void addEntry(GATKFeature data) {
+        nameMap.put(data.getName(),data);
+        classMap.add(new Pair<Class, GATKFeature>(data.getClass(),data));
+    }
+
+    public Collection<GATKFeature> getSet(String name) {
+        if (name == null) return getSet();
+        Set<GATKFeature> set = new HashSet<GATKFeature>();
+        if (nameMap.containsKey(name)) set.add(nameMap.get(name));
+        return set;
+    }
+
+    /**
+     * get the feature contents of this container; the unfiltered set without their name association
+     * @return
+     */
+    public Collection<GATKFeature> getSet() {
+        return new ArrayList<GATKFeature>(nameMap.values());
+    }
+
+    // the brute force (n) search ended up being faster than sorting and binary search in all but the most extreme cases (thousands of RODs at a location).
+    public Collection<GATKFeature> getSet(Class cls) {
+        Collection<GATKFeature> ret = new ArrayList<GATKFeature>();
+        for (Pair<Class, GATKFeature> pair: classMap)
+            if (pair.first.equals(cls)) ret.add(pair.second);
+        return ret;
+    }
+}
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/datasources/providers/ReadBasedReferenceOrderedView.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/datasources/providers/ReadBasedReferenceOrderedView.java
new file mode 100644
index 0000000..1d73501
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/datasources/providers/ReadBasedReferenceOrderedView.java
@@ -0,0 +1,69 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.engine.datasources.providers;
+
+import com.google.java.contract.Ensures;
+import com.google.java.contract.Requires;
+import htsjdk.samtools.util.PeekableIterator;
+import htsjdk.samtools.SAMRecord;
+import org.broadinstitute.gatk.engine.datasources.reads.ReadShard;
+import org.broadinstitute.gatk.engine.datasources.rmd.ReferenceOrderedDataSource;
+import org.broadinstitute.gatk.engine.refdata.RefMetaDataTracker;
+import org.broadinstitute.gatk.engine.refdata.utils.LocationAwareSeekableRODIterator;
+import org.broadinstitute.gatk.engine.refdata.utils.RODRecordList;
+import org.broadinstitute.gatk.utils.GenomeLoc;
+import org.broadinstitute.gatk.utils.GenomeLocParser;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+
+/** a ROD view for reads. This provides the Read traversals a way of getting a RefMetaDataTracker */
+public class ReadBasedReferenceOrderedView extends IntervalReferenceOrderedView {
+    public ReadBasedReferenceOrderedView(final ShardDataProvider provider) {
+        super(provider, provider.hasReferenceOrderedData() ? ((ReadShard)provider.getShard()).getReadsSpan() : null);
+    }
+
+    /**
+     * create a RefMetaDataTracker given the current read
+     *
+     * @param rec the read
+     *
+     * @return a RefMetaDataTracker for the read, from which you can get ROD -> read alignments
+     */
+    @Requires("rec != null")
+    @Ensures("result != null")
+    public RefMetaDataTracker getReferenceOrderedDataForRead(final SAMRecord rec) {
+        if ( rec.getReadUnmappedFlag() )
+            return RefMetaDataTracker.EMPTY_TRACKER;
+        else {
+            final GenomeLoc readSpan = genomeLocParser.createGenomeLoc(rec);
+            trimCurrentFeaturesToLoc(readSpan);
+            return getReferenceOrderedDataForInterval(readSpan);
+        }
+    }
+}
+
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/datasources/providers/ReadReferenceView.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/datasources/providers/ReadReferenceView.java
new file mode 100644
index 0000000..14d5827
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/datasources/providers/ReadReferenceView.java
@@ -0,0 +1,102 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.engine.datasources.providers;
+
+import htsjdk.samtools.SAMRecord;
+import org.broadinstitute.gatk.engine.contexts.ReferenceContext;
+import org.broadinstitute.gatk.utils.GenomeLoc;
+/*
+ * 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.
+ */
+
+/**
+ * User: hanna
+ * Date: May 22, 2009
+ * Time: 12:36:14 PM
+ *
+ */
+
+/** Provides access to the reference over a single read. */
+
+public class ReadReferenceView extends ReferenceView {
+    /**
+     * Create a view of the reference with respect to a single read.
+     *
+     * @param provider
+     */
+    public ReadReferenceView( ShardDataProvider provider ) {
+        super(provider);
+    }
+
+    protected ReferenceContext.ReferenceContextRefProvider getReferenceBasesProvider( GenomeLoc genomeLoc ) {
+        return new Provider(genomeLoc);
+    }
+
+    public class Provider implements ReferenceContext.ReferenceContextRefProvider {
+        GenomeLoc loc;
+
+        public Provider( GenomeLoc loc ) {
+            this.loc = loc;
+        }
+
+        public byte[] getBases() {
+            return getReferenceBases(loc);
+        }
+    }
+
+    /**
+     * Return a reference context appropriate for the span of read
+     *
+     * @param read the mapped read to test
+     * @return
+     */
+    public ReferenceContext getReferenceContext( final SAMRecord read ) {
+        GenomeLoc loc = genomeLocParser.createGenomeLoc(read);
+        return new ReferenceContext( genomeLocParser, loc, loc, getReferenceBasesProvider(loc) );
+    }
+
+}
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/datasources/providers/ReadShardDataProvider.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/datasources/providers/ReadShardDataProvider.java
new file mode 100644
index 0000000..8acfad0
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/datasources/providers/ReadShardDataProvider.java
@@ -0,0 +1,82 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.engine.datasources.providers;
+
+import htsjdk.samtools.reference.IndexedFastaSequenceFile;
+import org.broadinstitute.gatk.engine.datasources.reads.Shard;
+import org.broadinstitute.gatk.engine.datasources.rmd.ReferenceOrderedDataSource;
+import org.broadinstitute.gatk.engine.iterators.GATKSAMIterator;
+import org.broadinstitute.gatk.utils.GenomeLocParser;
+
+import java.util.Collection;
+
+/**
+ * Present data sharded by read to a traversal engine.
+ *
+ * @author mhanna
+ * @version 0.1
+ */
+public class ReadShardDataProvider extends ShardDataProvider {
+    /**
+     * The raw collection of reads.
+     */
+    private final GATKSAMIterator reads;
+
+    /**
+     * Create a data provider for the shard given the reads and reference.
+     * @param shard The chunk of data over which traversals happen.
+     * @param reference A getter for a section of the reference.
+     */
+    public ReadShardDataProvider(Shard shard, GenomeLocParser genomeLocParser, GATKSAMIterator reads, IndexedFastaSequenceFile reference, Collection<ReferenceOrderedDataSource> rods) {
+        super(shard,genomeLocParser,reference,rods);
+        this.reads = reads;
+    }
+
+    /**
+     * Can this data source provide reads?
+     * @return True if reads are available, false otherwise.
+     */
+    public boolean hasReads() {
+        return reads != null;
+    }    
+
+    /**
+     * Gets an iterator over all the reads bound by this shard.
+     * @return An iterator over all reads in this shard.
+     */
+    public GATKSAMIterator getReadIterator() {
+        return reads;
+    }
+
+    @Override
+    public void close() {
+        super.close();
+        
+        if(reads != null)
+            reads.close();
+    }
+
+}
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/datasources/providers/ReadView.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/datasources/providers/ReadView.java
new file mode 100644
index 0000000..160dbd5
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/datasources/providers/ReadView.java
@@ -0,0 +1,88 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.engine.datasources.providers;
+
+import htsjdk.samtools.SAMRecord;
+import org.broadinstitute.gatk.engine.iterators.GATKSAMIterator;
+
+import java.util.Arrays;
+import java.util.Collection;
+/**
+ * User: hanna
+ * Date: May 22, 2009
+ * Time: 12:06:54 PM
+ * BROAD INSTITUTE SOFTWARE COPYRIGHT NOTICE AND AGREEMENT
+ * Software and documentation are copyright 2005 by the Broad Institute.
+ * All rights are reserved.
+ *
+ * Users acknowledge that this software is supplied without any warranty or support.
+ * The Broad Institute is not responsible for its use, misuse, or
+ * functionality.
+ */
+
+/**
+ * A view into the reads that a provider can provide. 
+ */
+public class ReadView implements View, Iterable<SAMRecord> {
+    /**
+     * The iterator into the reads supplied by this provider.
+     */
+    private GATKSAMIterator reads;
+
+    /**
+     * Create a new view of the reads given the current data set.
+     * @param provider Source for the data.
+     */
+    public ReadView( ReadShardDataProvider provider ) {
+        reads = provider.getReadIterator();
+    }
+
+    /**
+     * Other reads and loci conflict with this view.
+     * @return Array of reads and loci.
+     */
+    public Collection<Class<? extends View>> getConflictingViews() {
+        return Arrays.<Class<? extends View>>asList(ReadView.class, LocusView.class);
+    }
+
+    /**
+     * Close the view over these reads.  Note that this method closes just
+     * the view into the reads, not the reads themselves.
+     */
+    public void close() {
+        // Don't close the reads.  The provider is responsible for this.
+        // Just dispose of the pointer.
+        reads = null;
+    }
+
+    /**
+     * Gets an iterator into the reads supplied by this provider.
+     * @return Iterator into the reads that this provider covers.
+     */
+    public GATKSAMIterator iterator() {
+        return reads;    
+    }
+}
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/datasources/providers/ReferenceOrderedView.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/datasources/providers/ReferenceOrderedView.java
new file mode 100644
index 0000000..9f3db51
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/datasources/providers/ReferenceOrderedView.java
@@ -0,0 +1,33 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.engine.datasources.providers;
+
+import org.broadinstitute.gatk.engine.refdata.RefMetaDataTracker;
+import org.broadinstitute.gatk.utils.GenomeLoc;
+
+public interface ReferenceOrderedView extends View {
+    RefMetaDataTracker getReferenceOrderedDataAtLocus( GenomeLoc loc );
+}
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/datasources/providers/ReferenceView.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/datasources/providers/ReferenceView.java
new file mode 100644
index 0000000..2eade15
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/datasources/providers/ReferenceView.java
@@ -0,0 +1,131 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.engine.datasources.providers;
+
+import htsjdk.samtools.reference.IndexedFastaSequenceFile;
+import htsjdk.samtools.reference.ReferenceSequence;
+import htsjdk.samtools.SAMRecord;
+import htsjdk.samtools.SAMSequenceRecord;
+import org.broadinstitute.gatk.utils.GenomeLoc;
+import org.broadinstitute.gatk.utils.GenomeLocParser;
+import org.broadinstitute.gatk.utils.exceptions.ReviewedGATKException;
+
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Collections;
+/**
+ * User: hanna
+ * Date: May 22, 2009
+ * Time: 12:19:17 PM
+ * BROAD INSTITUTE SOFTWARE COPYRIGHT NOTICE AND AGREEMENT
+ * Software and documentation are copyright 2005 by the Broad Institute.
+ * All rights are reserved.
+ *
+ * Users acknowledge that this software is supplied without any warranty or support.
+ * The Broad Institute is not responsible for its use, misuse, or
+ * functionality.
+ */
+
+/**
+ * A view into the reference backing this shard.
+ */
+public class ReferenceView implements View {
+    /**
+     * The parser, used to create and parse GenomeLocs.
+     */
+    protected final GenomeLocParser genomeLocParser;
+
+    /**
+     * The source of reference data.
+     */
+    protected IndexedFastaSequenceFile reference = null;
+
+    /**
+     * Create a new ReferenceView.
+     * @param provider
+     */
+    public ReferenceView( ShardDataProvider provider ) {
+        this.genomeLocParser = provider.getGenomeLocParser();
+        this.reference = provider.getReference();
+    }
+
+    /**
+     * Reference views don't conflict with anything else.
+     * @return Empty list.
+     */
+    public Collection<Class<? extends View>> getConflictingViews() { return Collections.emptyList(); }
+
+    /**
+     * Deinitialize pointers for fast fail.  Someone else will handle file management.
+     */
+    public void close() {
+        reference = null;
+    }
+
+    /**
+     * Allow the user to pull reference info from any arbitrary region of the reference.
+     * If parts of the reference don't exist, mark them in the char array with 'X'es.
+     * @param genomeLoc The locus.
+     * @return A list of the bases starting at the start of the locus (inclusive) and ending
+     *         at the end of the locus (inclusive).
+     */
+    final static int BUFFER = 10000;
+    final static byte[] Xs = new byte[BUFFER];
+    static {
+        Arrays.fill(Xs, (byte)'X');
+    }
+
+    protected byte[] getReferenceBases( SAMRecord read ) {
+        return getReferenceBases(genomeLocParser.createGenomeLoc(read));
+
+    }
+
+    protected byte[] getReferenceBases( GenomeLoc genomeLoc ) {
+        SAMSequenceRecord sequenceInfo = reference.getSequenceDictionary().getSequence(genomeLoc.getContig());
+
+        long start = genomeLoc.getStart();
+        long stop = Math.min( genomeLoc.getStop(), sequenceInfo.getSequenceLength() );
+
+        // Read with no aligned bases?  Return an empty array.
+        if(stop - start + 1 == 0)
+            return new byte[0];
+
+        ReferenceSequence subsequence = reference.getSubsequenceAt(genomeLoc.getContig(), start, stop);
+
+        int overhang = (int)(genomeLoc.getStop() - stop);
+        if ( overhang > 0 ) {
+            if ( overhang > BUFFER ) // todo -- this is a bit dangerous
+                throw new ReviewedGATKException("Insufficient buffer size for Xs overhanging genome -- expand BUFFER");
+            byte[] all = new byte[subsequence.getBases().length + overhang];
+            System.arraycopy(subsequence.getBases(), 0, all, 0, subsequence.getBases().length);
+            System.arraycopy(Xs, 0, all, subsequence.getBases().length, overhang);
+            return all;
+        } else {
+            // fast path
+            return subsequence.getBases();
+        }
+    }
+}
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/datasources/providers/RodLocusView.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/datasources/providers/RodLocusView.java
new file mode 100644
index 0000000..21cb3ef
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/datasources/providers/RodLocusView.java
@@ -0,0 +1,197 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.engine.datasources.providers;
+
+import org.broadinstitute.gatk.engine.contexts.AlignmentContext;
+import org.broadinstitute.gatk.engine.contexts.ReferenceContext;
+import org.broadinstitute.gatk.engine.datasources.rmd.ReferenceOrderedDataSource;
+import org.broadinstitute.gatk.engine.refdata.RefMetaDataTracker;
+import org.broadinstitute.gatk.engine.refdata.utils.LocationAwareSeekableRODIterator;
+import org.broadinstitute.gatk.engine.refdata.utils.RODRecordList;
+import org.broadinstitute.gatk.utils.GenomeLoc;
+import org.broadinstitute.gatk.utils.collections.RODMergingIterator;
+import org.broadinstitute.gatk.utils.pileup.ReadBackedPileupImpl;
+
+import java.util.*;
+
+/**
+ * A view into the reference-ordered data in the provider.
+ */
+public class RodLocusView extends LocusView implements ReferenceOrderedView {
+    /**
+     * The data sources along with their current states.
+     */
+    private RODMergingIterator rodQueue = null;
+
+    Collection<RODRecordList> allTracksHere;
+
+    GenomeLoc lastLoc = null;
+    RODRecordList interval = null;
+
+    /**
+     * The data sources along with their current states.
+     */
+    private List<ReferenceOrderedDataState> states = new ArrayList<ReferenceOrderedDataState>();    
+
+    /**
+     * Enable debugging output -- todo remove me
+     */
+    final static boolean DEBUG = false;
+
+    final static String INTERVAL_ROD_NAME = "interval";
+
+    /**
+     * Create a new view of reference-ordered data.
+     *
+     * @param provider
+     */
+    public RodLocusView( LocusShardDataProvider provider ) {
+        super(provider);
+
+        GenomeLoc loc = provider.getLocus();
+
+        List< Iterator<RODRecordList> > iterators = new LinkedList< Iterator<RODRecordList> >();
+        for( ReferenceOrderedDataSource dataSource: provider.getReferenceOrderedData() ) {
+            if ( DEBUG ) System.out.printf("Shard is %s%n", provider.getLocus());
+
+            // grab the ROD iterator from the data source, and compute the first location in this shard, forwarding
+            // the iterator to immediately before it, so that it can be added to the merging iterator primed for
+            // next() to return the first real ROD in this shard
+            LocationAwareSeekableRODIterator it = dataSource.seek(provider.getLocus());
+            it.seekForward(genomeLocParser.createGenomeLoc(loc.getContig(), loc.getStart()-1));
+
+            states.add(new ReferenceOrderedDataState(dataSource,it));            
+
+            // we need to special case the interval so we don't always think there's a rod at the first location
+            if ( dataSource.getName().equals(INTERVAL_ROD_NAME) ) {
+                if ( interval != null )
+                    throw new RuntimeException("BUG: interval local variable already assigned " + interval);
+                interval = it.next();
+            } else {
+                iterators.add( it );
+            }
+        }
+
+        rodQueue = new RODMergingIterator(iterators);
+    }
+
+    @Override
+    public RefMetaDataTracker getReferenceOrderedDataAtLocus( GenomeLoc loc ) {
+        // special case the interval again -- add it into the ROD
+        if ( interval != null ) { allTracksHere.add(interval); }
+        return new RefMetaDataTracker(allTracksHere);
+    }
+
+    public boolean hasNext() {
+        if ( ! rodQueue.hasNext() )
+            return false;
+        else {
+            return ! rodQueue.peekLocation().isPast(locus);
+        }
+    }
+
+    /**
+     * Returns the next covered locus context in the shard.
+     * @return Next covered locus context in the shard.
+     * @throw NoSuchElementException if no such element exists.
+     */
+    public AlignmentContext next() {
+        if ( DEBUG ) System.out.printf("In RodLocusView.next()...%n");
+        RODRecordList datum = rodQueue.next();
+        if ( DEBUG ) System.out.printf("In RodLocusView.next(); datum = %s...%n", datum.getLocation());
+
+        if ( DEBUG ) System.out.printf("In RodLocusView.next(): creating tracker...%n");
+
+        allTracksHere = getSpanningTracks(datum);
+        GenomeLoc rodSite = datum.getLocation();
+        GenomeLoc site = genomeLocParser.createGenomeLoc( rodSite.getContig(), rodSite.getStart(), rodSite.getStart());
+
+        if ( DEBUG ) System.out.printf("rodLocusView.next() is at %s%n", site);
+
+        // calculate the number of skipped bases, and update lastLoc so we can do that again in the next()
+        long skippedBases = getSkippedBases( rodSite );
+        lastLoc = site;
+        return new AlignmentContext(site, new ReadBackedPileupImpl(site), skippedBases);
+    }
+
+    private Collection<RODRecordList> getSpanningTracks(RODRecordList marker) {
+        return rodQueue.allElementsLTE(marker);
+    }
+
+    /**
+     * Returns the number of reference bases that have been skipped:
+     *
+     * 1 -- since the last processed location if we have one
+     * 2 -- from the beginning of the shard if this is the first loc
+     * 3 -- from the last location to the current position
+     *
+     * @param currentPos
+     * @return
+     */
+    private long getSkippedBases( GenomeLoc currentPos ) {
+        // the minus - is because if lastLoc == null, you haven't yet seen anything in this interval, so it should also be counted as skipped
+        Integer compStop = lastLoc == null ? locus.getStart() - 1 : lastLoc.getStop();
+        long skippedBases = currentPos.getStart() - compStop  - 1;
+
+        if ( skippedBases < -1 ) { // minus 1 value is ok
+            throw new RuntimeException(String.format("BUG: skipped bases=%d is < 0: cur=%s vs. last=%s, shard=%s",
+                    skippedBases, currentPos, lastLoc, locus));
+        }
+        return Math.max(skippedBases, 0);
+    }
+
+    /**
+     * Get the location one after the last position we will traverse through
+     * @return
+     */
+    public GenomeLoc getLocOneBeyondShard() {
+        return genomeLocParser.createGenomeLoc(locus.getContig(),locus.getStop()+1);
+    }
+
+    /**
+     * How many bases are we skipping from the current location to the end of the interval / shard
+     * if we have no more elements
+     *
+     * @return
+     */
+    public long getLastSkippedBases() {
+        if ( hasNext() )
+            throw new RuntimeException("BUG: getLastSkippedBases called when there are elements remaining.");
+
+        return getSkippedBases(getLocOneBeyondShard());
+    }
+
+    /**
+     * Closes the current view.
+     */
+    public void close() {
+        for( ReferenceOrderedDataState state: states )
+            state.dataSource.close( state.iterator );
+
+        rodQueue = null;
+        allTracksHere = null;
+    }
+}
\ No newline at end of file
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/datasources/providers/ShardDataProvider.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/datasources/providers/ShardDataProvider.java
new file mode 100644
index 0000000..a36bee5
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/datasources/providers/ShardDataProvider.java
@@ -0,0 +1,197 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.engine.datasources.providers;
+
+import htsjdk.samtools.reference.IndexedFastaSequenceFile;
+import org.broadinstitute.gatk.engine.datasources.reads.Shard;
+import org.broadinstitute.gatk.engine.datasources.rmd.ReferenceOrderedDataSource;
+import org.broadinstitute.gatk.utils.GenomeLocParser;
+import org.broadinstitute.gatk.utils.exceptions.ReviewedGATKException;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+/**
+ * User: hanna
+ * Date: May 8, 2009
+ * Time: 3:09:57 PM
+ * BROAD INSTITUTE SOFTWARE COPYRIGHT NOTICE AND AGREEMENT
+ * Software and documentation are copyright 2005 by the Broad Institute.
+ * All rights are reserved.
+ *
+ * Users acknowledge that this software is supplied without any warranty or support.
+ * The Broad Institute is not responsible for its use, misuse, or
+ * functionality.
+ */
+
+/**
+ * An umbrella class that examines the data passed to the microscheduler and
+ * tries to assemble as much as possible with it. 
+ */
+public abstract class ShardDataProvider {
+    /**
+     * An ArrayList of all the views that are examining this data.
+     */
+    private List<View> registeredViews = new ArrayList<View>();
+
+    /**
+     * The shard over which we're providing data.
+     */
+    private final Shard shard;
+
+    /**
+     * The parser, used to create and build new GenomeLocs.
+     */
+    private final GenomeLocParser genomeLocParser;
+
+    /**
+     * Provider of reference data for this particular shard.
+     */
+    private final IndexedFastaSequenceFile reference;
+
+    /**
+     * Sources of reference-ordered data.
+     */
+    private final Collection<ReferenceOrderedDataSource> referenceOrderedData;
+
+    /**
+     * Returns the GenomeLocParser associated with this traversal.
+     * @return The associated parser.
+     */
+    public GenomeLocParser getGenomeLocParser() {
+        return genomeLocParser;
+    }
+
+    /**
+     * Retrieves the shard associated with this data provider.
+     * @return The shard associated with this data provider.
+     */
+    public Shard getShard() {
+        return shard;
+    }
+
+    /**
+     * Can this data source provide reference information?
+     * @return True if possible, false otherwise.
+     */
+    public boolean hasReference() {
+        return reference != null;
+    }
+
+
+    /**
+     * Gets a pointer into the given indexed fasta sequence file.
+     * @return The indexed fasta sequence file.
+     */
+    IndexedFastaSequenceFile getReference() {
+        return reference;        
+    }
+
+    /**
+     * Gets a window into the reference-ordered data.  Package protected so that only
+     * views can access it.
+     * @return List of reference-ordered data sources.
+     */
+    Collection<ReferenceOrderedDataSource> getReferenceOrderedData() {
+        return referenceOrderedData;        
+    }
+
+    /**
+     * @return true if reference ordered data will be provided by this shard
+     */
+    public boolean hasReferenceOrderedData() {
+        return ! getReferenceOrderedData().isEmpty();
+    }
+
+    /**
+     * Create a data provider for the shard given the reads and reference.
+     * @param shard The chunk of data over which traversals happen.
+     * @param reference A getter for a section of the reference.
+     */
+    public ShardDataProvider(Shard shard,GenomeLocParser genomeLocParser,IndexedFastaSequenceFile reference,Collection<ReferenceOrderedDataSource> rods) {
+        this.shard = shard;
+        this.genomeLocParser = genomeLocParser;
+        this.reference = reference;
+        this.referenceOrderedData = rods;
+    }
+
+    /**
+     * Skeletal, package protected constructor for unit tests which require a ShardDataProvider.
+     * @param shard the shard
+     */
+    ShardDataProvider(Shard shard,GenomeLocParser genomeLocParser) {
+        this(shard,genomeLocParser,null,null);
+    }
+
+    /**
+     * Register this view with the shard provider, and make sure it has no conflicts with any other views.
+     * @param view The new view.
+     */
+    void register( View view ) {
+        // Check all registered classes to see whether a conflict exists.
+        for( View registeredView: registeredViews ) {
+            Collection<Class<? extends View>> conflicts = registeredView.getConflictingViews();
+            for( Class<? extends View> conflict: conflicts ) {
+                if( conflict.isInstance(view) )
+                    throw new ReviewedGATKException(String.format("Tried to register two conflicting views: %s and %s",
+                                                           registeredView.getClass().getSimpleName(),
+                                                           view.getClass().getSimpleName()));
+            }
+        }
+
+        // Check whether this class has any objection to any other classes.
+        for( Class<? extends View> conflict: view.getConflictingViews() ) {
+            for( View registeredView: registeredViews ) {
+                if( conflict.isInstance(registeredView) )
+                    throw new ReviewedGATKException(String.format("Tried to register two conflicting views: %s and %s",
+                                                           registeredView.getClass().getSimpleName(),
+                                                           view.getClass().getSimpleName()));
+            }
+        }
+
+        this.registeredViews.add(view);
+    }
+
+    /**
+     * Retire this shard.
+     */
+    public void close() {
+        for( View view: registeredViews )
+            view.close();
+
+        // Explicitly purge registered views to ensure that we don't end up with circular references
+        // to views, which can in turn hold state.
+        registeredViews.clear();
+
+        if(shard != null)
+            shard.close();
+    }
+
+    @Override
+    public String toString() {
+        return shard.toString();
+    }
+}
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/datasources/providers/View.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/datasources/providers/View.java
new file mode 100644
index 0000000..f628bb4
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/datasources/providers/View.java
@@ -0,0 +1,55 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.engine.datasources.providers;
+
+import java.util.Collection;
+/**
+ * User: hanna
+ * Date: May 21, 2009
+ * Time: 3:14:56 PM
+ * BROAD INSTITUTE SOFTWARE COPYRIGHT NOTICE AND AGREEMENT
+ * Software and documentation are copyright 2005 by the Broad Institute.
+ * All rights are reserved.
+ *
+ * Users acknowledge that this software is supplied without any warranty or support.
+ * The Broad Institute is not responsible for its use, misuse, or
+ * functionality.
+ */
+
+/**
+ * Represents a view into given data.
+ */
+public interface View {
+    /**
+     * Gets a list of all types of views which can conflict with this view.
+     */
+    public Collection<Class<? extends View>> getConflictingViews();
+
+    /**
+     * Inform this view that the data provided to it no longer exists.
+     */
+    public void close();
+}
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/datasources/providers/package-info.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/datasources/providers/package-info.java
new file mode 100644
index 0000000..bc8a602
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/datasources/providers/package-info.java
@@ -0,0 +1,26 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.engine.datasources.providers;
\ No newline at end of file
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/datasources/reads/ActiveRegionShardBalancer.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/datasources/reads/ActiveRegionShardBalancer.java
new file mode 100644
index 0000000..efe6336
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/datasources/reads/ActiveRegionShardBalancer.java
@@ -0,0 +1,85 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.engine.datasources.reads;
+
+import java.util.Iterator;
+import java.util.LinkedList;
+import java.util.List;
+
+/**
+ * ActiveRegionShardBalancer
+ *
+ * Merges all of the file pointer information for a single contig index into a single
+ * combined shard.  The purpose of doing this is to ensure that the HaplotypeCaller, which
+ * doesn't support TreeReduction by construction, gets all of the data on a single
+ * contig together so the the NanoSchedule runs efficiently
+ */
+public class ActiveRegionShardBalancer extends ShardBalancer {
+    /**
+     * Convert iterators of file pointers into balanced iterators of shards.
+     * @return An iterator over balanced shards.
+     */
+    public Iterator<Shard> iterator() {
+        return new Iterator<Shard>() {
+            public boolean hasNext() {
+                return filePointers.hasNext();
+            }
+
+            public Shard next() {
+                FilePointer current = getCombinedFilePointersOnSingleContig();
+
+                // FilePointers have already been combined as necessary at the IntervalSharder level. No
+                // need to do so again here.
+
+                return new LocusShard(parser,readsDataSource,current.getLocations(),current.fileSpans);
+            }
+
+            public void remove() {
+                throw new UnsupportedOperationException("Unable to remove from shard balancing iterator");
+            }
+        };
+    }
+
+    /**
+     * Combine all of the file pointers in the filePointers iterator into a single combined
+     * FilePointer that spans all of the file pointers on a single contig
+     * @return a non-null FilePointer
+     */
+    private FilePointer getCombinedFilePointersOnSingleContig() {
+        FilePointer current = filePointers.next();
+
+        final List<FilePointer> toCombine = new LinkedList<>();
+        toCombine.add(current);
+
+        while ( filePointers.hasNext() &&
+                current.isRegionUnmapped == filePointers.peek().isRegionUnmapped &&
+                (current.getContigIndex() == filePointers.peek().getContigIndex() || current.isRegionUnmapped) ) {
+            toCombine.add(filePointers.next());
+        }
+
+        return FilePointer.union(toCombine, parser);
+    }
+}
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/datasources/reads/BAMAccessPlan.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/datasources/reads/BAMAccessPlan.java
new file mode 100644
index 0000000..1e30d6c
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/datasources/reads/BAMAccessPlan.java
@@ -0,0 +1,170 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.engine.datasources.reads;
+
+import htsjdk.samtools.util.PeekableIterator;
+import htsjdk.samtools.GATKBAMFileSpan;
+import htsjdk.samtools.GATKChunk;
+import htsjdk.samtools.util.BlockCompressedFilePointerUtil;
+import org.broadinstitute.gatk.utils.exceptions.ReviewedGATKException;
+
+import java.util.LinkedList;
+import java.util.List;
+
+/**
+* Created by IntelliJ IDEA.
+* User: mhanna
+* Date: 10/14/11
+* Time: 10:47 PM
+* To change this template use File | Settings | File Templates.
+*/
+class BAMAccessPlan {
+    private final SAMReaderID reader;
+    private final BlockInputStream inputStream;
+
+    private final List<GATKChunk> positions;
+    private PeekableIterator<GATKChunk> positionIterator;
+
+    /**
+     * Stores the next block address to read, or -1 if no such block is available.
+     */
+    private long nextBlockAddress;
+
+
+    BAMAccessPlan(final SAMReaderID reader, final BlockInputStream inputStream, GATKBAMFileSpan fileSpan) {
+        this.reader = reader;
+        this.inputStream = inputStream;
+
+        this.positions = fileSpan.getGATKChunks();
+        initialize();
+    }
+
+    public SAMReaderID getReader() {
+        return reader;
+    }
+
+    public BlockInputStream getInputStream() {
+        return inputStream;
+    }
+
+    /**
+     * Retrieves the next block address to be read.
+     * @return Next block address to be read.
+     */
+    public long getBlockAddress() {
+        return nextBlockAddress;
+    }
+
+    /**
+     * Retrieves the first offset of interest in the block returned by getBlockAddress().
+     * @return First block of interest in this segment.
+     */
+    public int getFirstOffsetInBlock() {
+        return (nextBlockAddress == positionIterator.peek().getBlockStart()) ? positionIterator.peek().getBlockOffsetStart() : 0;
+    }
+
+    /**
+     * Gets the spans overlapping the given block; used to copy the contents of the block into the circular buffer.
+     * @param blockAddress Block address for which to search.
+     * @param filePosition Block address at which to terminate the last chunk if the last chunk goes beyond this span.
+     * @return list of chunks containing that block.
+     */
+    public List<GATKChunk> getSpansOverlappingBlock(long blockAddress, long filePosition) {
+        List<GATKChunk> spansOverlapping = new LinkedList<GATKChunk>();
+        // While the position iterator overlaps the given block, pull out spans to report.
+        while(positionIterator.hasNext() && positionIterator.peek().getBlockStart() <= blockAddress) {
+            // Create a span over as much of the block as is covered by this chunk.
+            int blockOffsetStart = (blockAddress == positionIterator.peek().getBlockStart()) ? positionIterator.peek().getBlockOffsetStart() : 0;
+
+            // Calculate the end of this span.  If the span extends past this block, cap it using the current file position.
+            long blockEnd;
+            int blockOffsetEnd;
+            if(blockAddress < positionIterator.peek().getBlockEnd()) {
+                blockEnd = filePosition;
+                blockOffsetEnd = 0;
+            }
+            else {
+                blockEnd = positionIterator.peek().getBlockEnd();
+                blockOffsetEnd = positionIterator.peek().getBlockOffsetEnd();
+            }
+
+            GATKChunk newChunk = new GATKChunk(blockAddress,blockOffsetStart,blockEnd,blockOffsetEnd);
+
+            if(newChunk.getChunkStart() <= newChunk.getChunkEnd())
+                spansOverlapping.add(new GATKChunk(blockAddress,blockOffsetStart,blockEnd,blockOffsetEnd));
+
+            // If the value currently stored in the position iterator ends past the current block, we must be done.  Abort.
+            if(!positionIterator.hasNext() ||  positionIterator.peek().getBlockEnd() > blockAddress)
+                break;
+
+            // If the position iterator ends before the block ends, pull the position iterator forward.
+            if(positionIterator.peek().getBlockEnd() <= blockAddress)
+                positionIterator.next();
+        }
+
+        return spansOverlapping;
+    }
+
+    public void reset() {
+        initialize();
+    }
+
+    /**
+     * Resets the SAM reader position to its original state.
+     */
+    private void initialize() {
+        this.positionIterator = new PeekableIterator<GATKChunk>(positions.iterator());
+        if(positionIterator.hasNext())
+            nextBlockAddress = positionIterator.peek().getBlockStart();
+        else
+            nextBlockAddress = -1;
+    }
+
+    /**
+     * Advances the current position to the next block to read, given the current position in the file.
+     * @param filePosition The current position within the file.
+     */
+    void advancePosition(final long filePosition) {
+        nextBlockAddress = BlockCompressedFilePointerUtil.getBlockAddress(filePosition);
+
+        // Check the current file position against the iterator; if the iterator is before the current file position,
+        // draw the iterator forward.  Remember when performing the check that coordinates are half-open!
+        while(positionIterator.hasNext() && isFilePositionPastEndOfChunk(filePosition,positionIterator.peek()))
+            positionIterator.next();
+
+        // If the block iterator has shot past the file pointer, bring the file pointer flush with the start of the current block.
+        if(positionIterator.hasNext() && filePosition < positionIterator.peek().getChunkStart())
+            nextBlockAddress = positionIterator.peek().getBlockStart();
+
+        // If we've shot off the end of the block pointer, notify consumers that iteration is complete.
+        if(!positionIterator.hasNext())
+            nextBlockAddress = -1;
+    }
+
+    private boolean isFilePositionPastEndOfChunk(final long filePosition, final GATKChunk chunk) {
+        return filePosition >= chunk.getChunkEnd();
+    }
+}
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/datasources/reads/BAMSchedule.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/datasources/reads/BAMSchedule.java
new file mode 100644
index 0000000..a80b0a4
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/datasources/reads/BAMSchedule.java
@@ -0,0 +1,530 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.engine.datasources.reads;
+
+import htsjdk.samtools.util.PeekableIterator;
+import htsjdk.samtools.Bin;
+import htsjdk.samtools.GATKBAMFileSpan;
+import htsjdk.samtools.GATKChunk;
+import htsjdk.samtools.util.CloseableIterator;
+import org.broadinstitute.gatk.utils.GenomeLoc;
+import org.broadinstitute.gatk.utils.exceptions.ReviewedGATKException;
+import org.broadinstitute.gatk.utils.exceptions.GATKException;
+import org.broadinstitute.gatk.utils.exceptions.UserException;
+
+import java.io.File;
+import java.io.IOException;
+import java.io.RandomAccessFile;
+import java.nio.ByteBuffer;
+import java.nio.ByteOrder;
+import java.nio.channels.FileChannel;
+import java.util.*;
+
+/**
+ * Writes schedules for a single BAM file to a target output file.
+ */
+public class BAMSchedule implements CloseableIterator<BAMScheduleEntry> {
+    /**
+     * File in which to store schedule data.
+     */
+    private File scheduleFile;
+
+    /**
+     * File channel for the schedule file.
+     */
+    private FileChannel scheduleFileChannel;
+
+    /**
+     * The definitive, sorted list of reader IDs.  Order is important here: the order
+     * in which the reader IDs are presented here maps to the order in which they appear in the file. 
+     */
+    private final List<SAMReaderID> readerIDs = new ArrayList<SAMReaderID>();
+
+    /**
+     * Iterators over the schedule.  Stored in the same order as readerIDs, above.
+     */
+    private final List<PeekableIterator<BAMScheduleEntry>> scheduleIterators = new ArrayList<PeekableIterator<BAMScheduleEntry>>();
+
+    /**
+     * Next schedule entry to be returned.  Null if no additional entries are present.
+     */
+    private BAMScheduleEntry nextScheduleEntry;
+
+    /**
+     * Reference sequence for which to write the schedule.
+     */
+    private final int referenceSequence;
+
+    /**
+     * Sizes of ints and longs in bytes.
+     */
+    private static final int INT_SIZE_IN_BYTES = Integer.SIZE / 8;
+    private static final int LONG_SIZE_IN_BYTES = Long.SIZE / 8;    
+
+    /**
+     * Create a new BAM schedule based on the given index.
+     * @param dataSource The SAM data source to use.
+     * @param intervals List of 
+     */
+    public BAMSchedule(final SAMDataSource dataSource, final List<GenomeLoc> intervals) {
+        if(intervals.isEmpty())
+            throw new ReviewedGATKException("Tried to write schedule for empty interval list.");
+
+        referenceSequence = dataSource.getHeader().getSequence(intervals.get(0).getContig()).getSequenceIndex();
+
+        createScheduleFile();
+
+        readerIDs.addAll(dataSource.getReaderIDs());
+
+        for(final SAMReaderID reader: readerIDs) {
+            final GATKBAMIndex index = dataSource.getIndex(reader);
+            final GATKBAMIndexData indexData = index.readReferenceSequence(referenceSequence);
+
+            int currentBinInLowestLevel = GATKBAMIndex.getFirstBinInLevel(GATKBAMIndex.getNumIndexLevels()-1);
+            Iterator<GenomeLoc> locusIterator = intervals.iterator();
+            GenomeLoc currentLocus = locusIterator.next();
+
+            final long readerStartOffset = position();
+
+            int maxChunkCount = 0;
+
+            while(currentBinInLowestLevel < GATKBAMIndex.MAX_BINS && currentLocus != null) {
+                final Bin bin = new Bin(referenceSequence,currentBinInLowestLevel);
+                final int binStart = index.getFirstLocusInBin(bin);
+                final int binStop = index.getLastLocusInBin(bin);
+
+                // In required, pull bin iterator ahead to the point of the next GenomeLoc.
+                if(binStop < currentLocus.getStart()) {
+                    currentBinInLowestLevel++;
+                    continue;
+                }
+
+                // At this point, the bin stop is guaranteed to be >= the start of the locus.
+                // If the bins have gone past the current locus, update the current locus if at all possible.
+                if(binStart > currentLocus.getStop()) {
+                    currentLocus = locusIterator.hasNext() ? locusIterator.next() : null;
+                    continue;
+                }
+
+                // Code at this point knows that the current bin is neither before nor after the current locus,
+                // so it must overlap.  Add this region to the filesystem.
+                final GATKBAMFileSpan fileSpan = indexData.getSpanOverlapping(bin);
+
+                if(!fileSpan.isEmpty()) {
+                    // File format is binary in little endian; start of region, end of region, num chunks, then the chunks themselves.
+                    ByteBuffer buffer = allocateByteBuffer(2*INT_SIZE_IN_BYTES + INT_SIZE_IN_BYTES + fileSpan.getGATKChunks().size()*LONG_SIZE_IN_BYTES*2);
+                    buffer.putInt(binStart);
+                    buffer.putInt(binStop);
+                    buffer.putInt(fileSpan.getGATKChunks().size());
+                    for(GATKChunk chunk: fileSpan.getGATKChunks()) {
+                        buffer.putLong(chunk.getChunkStart());
+                        buffer.putLong(chunk.getChunkEnd());
+                    }
+                    maxChunkCount = Math.max(maxChunkCount,fileSpan.getGATKChunks().size());
+
+                    // Prepare buffer for writing
+                    buffer.flip();
+
+                    // And write.
+                    write(buffer);
+                }
+
+                currentBinInLowestLevel++;
+            }
+
+            final long readerStopOffset = position();
+
+            scheduleIterators.add(new PeekableIterator<BAMScheduleEntry>(new BAMScheduleIterator(reader,readerStartOffset,readerStopOffset,maxChunkCount)));
+
+            // Iterator initialization might move the file pointer.  Make sure it gets reset back to where it was before iterator initialization.
+            position(readerStopOffset);
+        }
+
+        advance();
+    }
+
+    /**
+     * Determine whether more ScheduleEntries are present in the iterator.
+     * @return Next schedule entry to parse.
+     */
+    @Override
+    public boolean hasNext() {
+        return nextScheduleEntry != null;    
+    }
+
+    /**
+     * Retrieve the next schedule entry in the list.
+     * @return next schedule entry in the queue.
+     */
+    @Override
+    public BAMScheduleEntry next() {
+        BAMScheduleEntry currentScheduleEntry = nextScheduleEntry;
+        advance();
+        return currentScheduleEntry;
+    }
+
+    /**
+     * Close down and delete the file.
+     */
+    @Override
+    public void close() {
+        try {
+            scheduleFileChannel.close();
+        }
+        catch(IOException ex) {
+            throw makeIOFailureException(true, "Unable to close schedule file.", ex);
+        }
+    }
+
+    /**
+     * Convenience routine for creating UserExceptions
+     * @param wasWriting
+     * @param message
+     * @param e
+     * @return
+     */
+    private final GATKException makeIOFailureException(final boolean wasWriting, final String message, final Exception e) {
+        if ( wasWriting ) {
+            if ( e == null )
+                return new UserException.CouldNotCreateOutputFile(scheduleFile, message);
+            else
+                return new UserException.CouldNotCreateOutputFile(scheduleFile, message, e);
+        } else {
+            if ( e == null )
+                return new UserException.CouldNotReadInputFile(scheduleFile, message);
+            else
+                return new UserException.CouldNotReadInputFile(scheduleFile, message, e);
+        }
+    }
+
+    /**
+     * Advance to the next schedule entry.
+     */
+    private void advance() {
+        nextScheduleEntry = null;
+
+        BitSet selectedIterators = new BitSet(readerIDs.size());
+        int currentStart = Integer.MAX_VALUE;
+        int currentStop = Integer.MAX_VALUE;
+
+        // Select every iterator whose next element is the lowest element in the list.
+        for(int reader = 0; reader < scheduleIterators.size(); reader++) {
+            PeekableIterator<BAMScheduleEntry> scheduleIterator = scheduleIterators.get(reader);
+            if(!scheduleIterator.hasNext())
+                continue;
+
+            // If the iterator starts after this one, skip over it.
+            if(scheduleIterator.peek().start > currentStart)
+                continue;
+
+            // If the iterator starts at the same point as this one, add it to the list.
+            if(scheduleIterator.peek().start == currentStart) {
+                selectedIterators.set(reader);
+                currentStop = Math.min(scheduleIterator.peek().stop,currentStop);
+                continue;
+            }
+
+            // If the iterator is less than anything seen before it, purge the selections and make this one current.
+            if(scheduleIterator.peek().start < currentStart) {
+                selectedIterators.clear();
+                selectedIterators.set(reader);
+                currentStart = scheduleIterator.peek().start;
+                currentStop = scheduleIterator.peek().stop;
+            }
+        }
+
+        // Out of iterators?  Abort early.
+        if(selectedIterators.isEmpty())
+            return;
+
+        // Create the target schedule entry
+        BAMScheduleEntry mergedScheduleEntry = new BAMScheduleEntry(currentStart,currentStop);
+
+        // For each schedule entry with data, load the data into the merged schedule.
+        for (int reader = selectedIterators.nextSetBit(0); reader >= 0; reader = selectedIterators.nextSetBit(reader+1)) {
+            PeekableIterator<BAMScheduleEntry> scheduleIterator = scheduleIterators.get(reader);
+            BAMScheduleEntry individualScheduleEntry = scheduleIterator.peek();
+            mergedScheduleEntry.mergeInto(individualScheduleEntry);
+
+            // If the schedule iterator ends after this entry, consume it.
+            if(individualScheduleEntry.stop <= currentStop)
+                scheduleIterator.next();
+        }
+
+        // For each schedule entry without data, add a blank entry.
+        for (int reader = selectedIterators.nextClearBit(0); reader < readerIDs.size(); reader = selectedIterators.nextClearBit(reader+1)) {
+            mergedScheduleEntry.addFileSpan(readerIDs.get(reader),new GATKBAMFileSpan());
+        }
+
+        nextScheduleEntry = mergedScheduleEntry;
+    }
+
+    @Override
+    public void remove() { throw new UnsupportedOperationException("Unable to remove from a schedule iterator."); }
+
+    /**
+     * Create a new schedule file, containing schedule information for all BAM files being dynamically merged.
+     */
+    private void createScheduleFile() {
+        try {
+            scheduleFile = File.createTempFile("bamschedule."+referenceSequence,null);
+            scheduleFileChannel = new RandomAccessFile(scheduleFile,"rw").getChannel();
+        }
+        catch(IOException ex) {
+            throw new UserException("Unable to create a temporary BAM schedule file.  Please make sure Java can write to the default temp directory or use -Djava.io.tmpdir= to instruct it to use a different temp directory instead.",ex);
+        }
+        scheduleFile.deleteOnExit();
+
+    }
+
+    /**
+     * Creates a new byte buffer of the given size.
+     * @param size the size of buffer to allocate.
+     * @return Newly allocated byte buffer.
+     */
+    private ByteBuffer allocateByteBuffer(final int size) {
+        ByteBuffer buffer = ByteBuffer.allocate(size);
+        buffer.order(ByteOrder.LITTLE_ENDIAN);
+        return buffer;
+    }
+
+    /**
+     * Reads the contents at the current position on disk into the given buffer.
+     * @param buffer buffer to fill.
+     */
+    private int read(final ByteBuffer buffer) {
+        try {
+            return scheduleFileChannel.read(buffer);
+        }
+        catch(IOException ex) {
+            throw makeIOFailureException(false, "Unable to read data from BAM schedule file.", ex);
+        }
+    }
+
+    private void write(final ByteBuffer buffer) {
+        try {
+            scheduleFileChannel.write(buffer);
+            if(buffer.remaining() > 0)
+                throw makeIOFailureException(true, "Unable to write entire buffer to file.", null);
+        }
+        catch(IOException ex) {
+            throw makeIOFailureException(true, "Unable to write data to BAM schedule file.", ex);
+        }
+    }
+
+    /**
+     * Reads the current position from the file channel.
+     * @return Current position within file channel.
+     */
+    private long position() {
+        try {
+            return scheduleFileChannel.position();
+        }
+        catch(IOException ex) {
+            throw makeIOFailureException(false, "Unable to retrieve position of BAM schedule file.", ex);
+        }
+    }
+
+    /**
+     * Reposition the file channel to the specified offset wrt the start of the file.
+     * @param position The position.
+     */
+    private void position(final long position) {
+        try {
+            scheduleFileChannel.position(position);
+        }
+        catch(IOException ex) {
+            throw makeIOFailureException(false, "Unable to position BAM schedule file.",ex);
+        }
+    }
+
+    /**
+     * An iterator over the schedule for a single BAM file.
+     */
+    private class BAMScheduleIterator implements Iterator<BAMScheduleEntry> {
+        /**
+         * ID of the reader associated with the given schedule.
+         */
+        private final SAMReaderID reader;
+
+        /**
+         * Current position in the file.
+         */
+        private long currentPosition;
+
+        /**
+         * Stopping file position of last bin in file for this reader, exclusive.
+         */
+        private final long stopPosition;
+
+        /**
+         * Byte buffer used to store BAM header info.
+         */
+        private final ByteBuffer binHeader;
+
+        /**
+         * Byte buffer used to store chunk data.
+         */
+        private final ByteBuffer chunkData;
+
+        public BAMScheduleIterator(final SAMReaderID reader, final long startPosition, final long stopPosition, final int maxChunkCount) {
+            this.reader = reader;
+            this.currentPosition = startPosition;
+            this.stopPosition = stopPosition;
+            binHeader = allocateByteBuffer(INT_SIZE_IN_BYTES*3);
+            chunkData = allocateByteBuffer(maxChunkCount*LONG_SIZE_IN_BYTES*2);
+        }
+
+        @Override
+        public boolean hasNext() {
+            return currentPosition < stopPosition;
+        }
+
+        @Override
+        public BAMScheduleEntry next() {
+            position(currentPosition);
+
+            // Read data.
+            int binHeaderBytesRead = read(binHeader);
+
+            // Make sure we read in a complete bin header:
+            if ( binHeaderBytesRead < INT_SIZE_IN_BYTES * 3 ) {
+                throw new ReviewedGATKException(String.format("Unable to read a complete bin header from BAM schedule file %s for BAM file %s. " +
+                                                               "The BAM schedule file is likely incomplete/corrupt.",
+                                                               scheduleFile.getAbsolutePath(), reader.getSamFilePath()));
+            }
+
+            // Decode contents.
+            binHeader.flip();
+            final int start = binHeader.getInt();
+            final int stop = binHeader.getInt();
+            final int numChunks = binHeader.getInt();
+
+            // Prepare bin buffer for next read.
+            binHeader.flip();
+
+            // Prepare a target buffer for chunks.
+            GATKChunk[] chunks = new GATKChunk[numChunks];
+
+            // Read all chunk data.
+            chunkData.limit(numChunks*LONG_SIZE_IN_BYTES*2);
+            long bytesRead = read(chunkData);
+            if(bytesRead != numChunks*LONG_SIZE_IN_BYTES*2)
+                throw new ReviewedGATKException("Unable to read all chunks from file");
+
+            // Prepare for reading.
+            chunkData.flip();
+
+            for(int i = 0; i < numChunks; i++)
+                chunks[i] = new GATKChunk(chunkData.getLong(),chunkData.getLong());
+
+            // Prepare chunk buffer for next read.
+            chunkData.flip();
+
+            BAMScheduleEntry nextScheduleEntry = new BAMScheduleEntry(start,stop);
+            nextScheduleEntry.addFileSpan(reader,new GATKBAMFileSpan(chunks));
+
+            // Reset the position of the iterator at the next contig.
+            currentPosition = position();
+
+            return nextScheduleEntry;
+        }
+
+        /**
+         * Not supported.
+         */
+        @Override
+        public void remove() {
+            throw new UnsupportedOperationException("Unable to remove from a BAMScheduleIterator");
+        }
+
+    }
+}
+
+/**
+ * A single proto-shard to be processed.
+ */
+class BAMScheduleEntry {
+    /**
+     * Starting position for the genomic entry.
+     */
+    public final int start;
+
+    /**
+     * Ending position for the genomic entry.
+     */
+    public final int stop;
+
+    /**
+     * The spans representing the given region.
+     */
+    public final Map<SAMReaderID,GATKBAMFileSpan> fileSpans = new HashMap<SAMReaderID,GATKBAMFileSpan>();
+
+    BAMScheduleEntry(final int start, final int stop) {
+        this.start = start;
+        this.stop = stop;
+    }
+
+    /**
+     * Add a new file span to this schedule.
+     * @param reader Reader associated with the span.
+     * @param fileSpan Blocks to read in the given reader.
+     */
+    public void addFileSpan(final SAMReaderID reader, final GATKBAMFileSpan fileSpan) {
+        fileSpans.put(reader,fileSpan);
+    }
+
+    /**
+     * A naive merge operation.  Merge the fileSpans in other into this, blowing up if conflicts are
+     * detected. Completely ignores merging start and stop.
+     * @param other Other schedule entry to merging into this one.
+     */
+    public void mergeInto(final BAMScheduleEntry other) {
+        final int thisSize = fileSpans.size();
+        final int otherSize = other.fileSpans.size();
+        fileSpans.putAll(other.fileSpans);
+        if(fileSpans.size() != thisSize+otherSize)
+            throw new ReviewedGATKException("Unable to handle overlaps when merging BAM schedule entries.");
+    }
+
+    /**
+     * Returns true if the location of this bin tree is before the given position.
+     * @param locus Locus to test.
+     * @return True if this bin sits completely before the given locus; false otherwise.
+     */
+    public boolean isBefore(final GenomeLoc locus) {
+        return stop < locus.getStart();
+    }
+
+    /**
+     * Checks overlap between this bin tree and other bin trees.
+     * @param position the position over which to detect overlap.
+     * @return True if the segment overlaps.  False otherwise.
+     */
+    public boolean overlaps(final GenomeLoc position) {
+        return !(position.getStop() < start || position.getStart() > stop);
+    }
+}
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/datasources/reads/BAMScheduler.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/datasources/reads/BAMScheduler.java
new file mode 100644
index 0000000..1ea8d39
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/datasources/reads/BAMScheduler.java
@@ -0,0 +1,320 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.engine.datasources.reads;
+
+import htsjdk.samtools.util.PeekableIterator;
+import htsjdk.samtools.GATKBAMFileSpan;
+import htsjdk.samtools.GATKChunk;
+import htsjdk.samtools.SAMSequenceRecord;
+import org.broadinstitute.gatk.utils.GenomeLoc;
+import org.broadinstitute.gatk.utils.GenomeLocParser;
+import org.broadinstitute.gatk.utils.GenomeLocSortedSet;
+import org.broadinstitute.gatk.utils.exceptions.ReviewedGATKException;
+import org.broadinstitute.gatk.utils.exceptions.UserException;
+import org.broadinstitute.gatk.utils.interval.IntervalMergingRule;
+import org.broadinstitute.gatk.utils.sam.ReadUtils;
+
+import java.util.*;
+
+/**
+ * Assign intervals to the most appropriate blocks, keeping as little as possible in memory at once.
+ */
+public class BAMScheduler implements Iterator<FilePointer> {
+    private final SAMDataSource dataSource;
+
+    private final Map<SAMReaderID,GATKBAMIndex> indexFiles = new HashMap<SAMReaderID,GATKBAMIndex>();
+
+    private FilePointer nextFilePointer = null;
+
+    private GenomeLocSortedSet loci;
+    private PeekableIterator<GenomeLoc> locusIterator;
+    private GenomeLoc currentLocus;
+    private IntervalMergingRule intervalMergingRule;
+
+    /*
+     * Creates BAMScheduler using contigs from the given BAM data source.
+     *
+     * @param dataSource    BAM source
+     * @return non-null BAM scheduler
+     */
+    public static BAMScheduler createOverMappedReads(final SAMDataSource dataSource) {
+        final BAMScheduler scheduler = new BAMScheduler(dataSource, IntervalMergingRule.ALL);
+        final GenomeLocSortedSet intervals = GenomeLocSortedSet.createSetFromSequenceDictionary(dataSource.getHeader().getSequenceDictionary());
+        scheduler.populateFilteredIntervalList(intervals);
+        return scheduler;
+    }
+
+    public static BAMScheduler createOverAllReads(final SAMDataSource dataSource, final GenomeLocParser parser) {
+        BAMScheduler scheduler = new BAMScheduler(dataSource, IntervalMergingRule.ALL);
+        scheduler.populateUnfilteredIntervalList(parser);
+        return scheduler;
+    }
+
+    public static BAMScheduler createOverIntervals(final SAMDataSource dataSource, final IntervalMergingRule mergeRule, final GenomeLocSortedSet loci) {
+        BAMScheduler scheduler = new BAMScheduler(dataSource, mergeRule);
+        scheduler.populateFilteredIntervalList(loci);
+        return scheduler;
+    }
+
+
+    private BAMScheduler(final SAMDataSource dataSource, final IntervalMergingRule mergeRule) {
+        this.dataSource = dataSource;
+        this.intervalMergingRule = mergeRule;
+        for(SAMReaderID reader: dataSource.getReaderIDs()) {
+            GATKBAMIndex index = dataSource.getIndex(reader);
+            if(index != null)
+                indexFiles.put(reader,dataSource.getIndex(reader));
+        }
+    }
+
+    /**
+     * The consumer has asked for a bounded set of locations.  Prepare an iterator over those locations.
+     * @param loci The list of locations to search and iterate over.
+     */
+    private void populateFilteredIntervalList(final GenomeLocSortedSet loci) {
+        this.loci = loci;
+        if(!indexFiles.isEmpty()) {
+            // If index data is available, start up the iterator.
+            locusIterator = new PeekableIterator<GenomeLoc>(loci.iterator());
+            if(locusIterator.hasNext())
+                currentLocus = locusIterator.next();
+            advance();
+        }
+        else {
+            // Otherwise, seed the iterator with a single file pointer over the entire region.
+            nextFilePointer = generatePointerOverEntireFileset();
+            for(GenomeLoc locus: loci)
+                nextFilePointer.addLocation(locus);
+            locusIterator = new PeekableIterator<GenomeLoc>(Collections.<GenomeLoc>emptyList().iterator());
+        }
+    }
+
+    /**
+     * The consumer has provided null, meaning to iterate over all available data.  Create a file pointer stretching
+     * from just before the start of the region to the end of the region.
+     */
+    private void populateUnfilteredIntervalList(final GenomeLocParser parser) {
+        this.loci = new GenomeLocSortedSet(parser);
+        locusIterator = new PeekableIterator<GenomeLoc>(Collections.<GenomeLoc>emptyList().iterator());
+        nextFilePointer = generatePointerOverEntireFileset();
+    }
+
+    /**
+     * Generate a span that runs from the end of the BAM header to the end of the fle.
+     * @return A file pointer over the specified region.
+     */
+    private FilePointer generatePointerOverEntireFileset() {
+        FilePointer filePointer = new FilePointer(intervalMergingRule);
+
+        // This is a "monolithic" FilePointer representing all regions in all files we will ever visit, and is
+        // the only FilePointer we will create. This allows us to have this FilePointer represent regions from
+        // multiple contigs
+        filePointer.setIsMonolithic(true);
+
+        Map<SAMReaderID,GATKBAMFileSpan> currentPosition;
+
+        currentPosition = dataSource.getInitialReaderPositions();
+
+        for(SAMReaderID reader: dataSource.getReaderIDs())
+            filePointer.addFileSpans(reader,createSpanToEndOfFile(currentPosition.get(reader).getGATKChunks().get(0).getChunkStart()));
+        return filePointer;
+    }
+
+    public boolean hasNext() {
+        return nextFilePointer != null;
+    }
+
+    public FilePointer next() {
+        if(!hasNext())
+            throw new NoSuchElementException("No next element available in interval sharder");
+        FilePointer currentFilePointer = nextFilePointer;
+        nextFilePointer = null;
+        advance();
+
+        return currentFilePointer;
+    }
+
+    public void remove() {
+        throw new UnsupportedOperationException("Unable to remove FilePointers from an IntervalSharder");
+    }
+
+    private void advance() {
+        if(loci.isEmpty())
+            return;
+
+        while(nextFilePointer == null && currentLocus != null) {
+            // special case handling of the unmapped shard.
+            if(currentLocus == GenomeLoc.UNMAPPED) {
+                nextFilePointer = new FilePointer(intervalMergingRule, GenomeLoc.UNMAPPED);
+                for(SAMReaderID id: dataSource.getReaderIDs())
+                    nextFilePointer.addFileSpans(id,createSpanToEndOfFile(indexFiles.get(id).getStartOfLastLinearBin()));
+                currentLocus = null;
+                continue;
+            }
+
+            nextFilePointer = new FilePointer(intervalMergingRule);
+
+            int coveredRegionStart = 1;
+            int coveredRegionStop = Integer.MAX_VALUE;
+            GenomeLoc coveredRegion = null;
+
+            BAMScheduleEntry scheduleEntry = getNextOverlappingBAMScheduleEntry(currentLocus);
+
+            // No overlapping data at all.
+            if(scheduleEntry != null) {
+                coveredRegionStart = Math.max(coveredRegionStart,scheduleEntry.start);
+                coveredRegionStop = Math.min(coveredRegionStop,scheduleEntry.stop);
+                coveredRegion = loci.getGenomeLocParser().createGenomeLoc(currentLocus.getContig(),coveredRegionStart,coveredRegionStop);
+
+                nextFilePointer.addFileSpans(scheduleEntry.fileSpans);
+            }
+            else {
+                // Always create a file span, whether there was covered data or not.  If there was no covered data, then the binTree is empty.
+                for(SAMReaderID reader: indexFiles.keySet())
+                    nextFilePointer.addFileSpans(reader,new GATKBAMFileSpan());
+            }
+
+            // Early exit if no bins were found.
+            if(coveredRegion == null) {
+                // for debugging only: maximum split is 16384.                
+                nextFilePointer.addLocation(currentLocus);
+                currentLocus = locusIterator.hasNext() ? locusIterator.next() : null;
+                continue;
+            }
+
+            // Early exit if only part of the first interval was found.
+            if(currentLocus.startsBefore(coveredRegion)) {
+                int splitPoint = Math.min(coveredRegion.getStart()-currentLocus.getStart(),16384)+currentLocus.getStart();
+                GenomeLoc[] splitContigs = currentLocus.split(splitPoint);
+                nextFilePointer.addLocation(splitContigs[0]);
+                currentLocus = splitContigs[1];
+                continue;
+            }
+
+            // Define the initial range of the file pointer, aka the region where the locus currently being processed intersects the BAM list.
+            GenomeLoc initialLocation = currentLocus.intersect(coveredRegion);
+            nextFilePointer.addLocation(initialLocation);
+
+            // See whether the BAM regions discovered overlap the next set of intervals in the interval list.  If so, include every overlapping interval.
+            if(!nextFilePointer.locations.isEmpty()) {
+                while(locusIterator.hasNext() && locusIterator.peek().overlapsP(coveredRegion)) {
+                    currentLocus = locusIterator.next();
+                    nextFilePointer.addLocation(currentLocus.intersect(coveredRegion));
+                }
+
+                // Chop off the uncovered portion of the locus.  Since we know that the covered region overlaps the current locus,
+                  // we can simplify the interval creation process to the end of the covered region to the stop of the given interval.
+                if(coveredRegionStop < currentLocus.getStop())
+                    currentLocus = loci.getGenomeLocParser().createGenomeLoc(currentLocus.getContig(),coveredRegionStop+1,currentLocus.getStop());
+                else if(locusIterator.hasNext())
+                    currentLocus = locusIterator.next();
+                else
+                    currentLocus = null;
+            }
+
+        }
+    }
+
+    
+    /**
+     * The last reference sequence processed by this iterator.
+     */
+    private Integer lastReferenceSequenceLoaded = null;
+
+    /**
+     * The stateful iterator used to progress through the genoem.
+     */
+    private PeekableIterator<BAMScheduleEntry> bamScheduleIterator = null;
+
+    /**
+     * Clean up underlying BAMSchedule file handles.
+     */
+    public void close() {
+        if(bamScheduleIterator != null)
+            bamScheduleIterator.close();
+    }
+
+    /**
+     * Get the next overlapping tree of bins associated with the given BAM file.
+     * @param currentLocus The actual locus for which to check overlap.
+     * @return The next schedule entry overlapping with the given list of loci.
+     */
+    private BAMScheduleEntry getNextOverlappingBAMScheduleEntry(final GenomeLoc currentLocus) {
+        // Make sure that we consult the BAM header to ensure that we're using the correct contig index for this contig name.
+        // This will ensure that if the two sets of contigs don't quite match (b36 male vs female ref, hg19 Epstein-Barr), then
+        // we'll be using the correct contig index for the BAMs.
+        // TODO: Warning: assumes all BAMs use the same sequence dictionary!  Get around this with contig aliasing.
+        SAMSequenceRecord currentContigSequenceRecord = dataSource.getHeader().getSequence(currentLocus.getContig());
+        if ( currentContigSequenceRecord == null ) {
+            throw new UserException(String.format("Contig %s not present in sequence dictionary for merged BAM header: %s",
+                                                  currentLocus.getContig(),
+                                                  ReadUtils.prettyPrintSequenceRecords(dataSource.getHeader().getSequenceDictionary())));
+        }
+
+        final int currentContigIndex = currentContigSequenceRecord.getSequenceIndex();
+
+        // Stale reference sequence or first invocation.  (Re)create the binTreeIterator.
+        if(lastReferenceSequenceLoaded == null || lastReferenceSequenceLoaded != currentContigIndex) {
+            if(bamScheduleIterator != null)
+                bamScheduleIterator.close();
+            lastReferenceSequenceLoaded = currentContigIndex;
+
+            // Naive algorithm: find all elements in current contig for proper schedule creation.
+            List<GenomeLoc> lociInContig = new LinkedList<GenomeLoc>();
+            for(GenomeLoc locus: loci) {
+                if (!GenomeLoc.isUnmapped(locus) && dataSource.getHeader().getSequence(locus.getContig()) == null)
+                    throw new ReviewedGATKException("BAM file(s) do not have the contig: " + locus.getContig() + ". You are probably using a different reference than the one this file was aligned with");
+
+                if (!GenomeLoc.isUnmapped(locus) && dataSource.getHeader().getSequence(locus.getContig()).getSequenceIndex() == lastReferenceSequenceLoaded)
+                    lociInContig.add(locus);
+            }
+
+            bamScheduleIterator = new PeekableIterator<BAMScheduleEntry>(new BAMSchedule(dataSource,lociInContig));
+        }
+
+        if(!bamScheduleIterator.hasNext())
+            return null;
+
+        // Peek the iterator along until finding the first binTree at or following the current locus.
+        BAMScheduleEntry bamScheduleEntry = bamScheduleIterator.peek();
+        while(bamScheduleEntry != null && bamScheduleEntry.isBefore(currentLocus)) {
+            bamScheduleIterator.next();
+            bamScheduleEntry = bamScheduleIterator.hasNext() ? bamScheduleIterator.peek() : null;
+        }                                   
+
+        return (bamScheduleEntry != null && bamScheduleEntry.overlaps(currentLocus)) ? bamScheduleEntry : null;
+    }
+
+    /**
+     * Create a span from the given start point to the end of the file.
+     * @param startOfRegion Start of the region, in encoded coordinates (block start << 16 & block offset).
+     * @return A file span from the given point to the end of the file.
+     */
+    private GATKBAMFileSpan createSpanToEndOfFile(final long startOfRegion) {
+      return new GATKBAMFileSpan(new GATKChunk(startOfRegion,Long.MAX_VALUE));
+    }
+
+}
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/datasources/reads/BGZFBlockLoadingDispatcher.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/datasources/reads/BGZFBlockLoadingDispatcher.java
new file mode 100644
index 0000000..cc1d9e9
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/datasources/reads/BGZFBlockLoadingDispatcher.java
@@ -0,0 +1,86 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.engine.datasources.reads;
+
+import org.broadinstitute.gatk.utils.exceptions.ReviewedGATKException;
+
+import java.util.LinkedList;
+import java.util.Queue;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+
+/**
+ * Preloads BGZF blocks in preparation for unzipping and data processing.
+ * TODO: Right now, the block loader has all threads blocked waiting for a work request.  Ultimately this should
+ * TODO: be replaced with a central thread management strategy.
+ */
+public class BGZFBlockLoadingDispatcher {
+    /**
+     * The file handle cache, used when allocating blocks from the dispatcher.
+     */
+    private final FileHandleCache fileHandleCache;
+
+    private final ExecutorService threadPool;
+
+    private final Queue<BAMAccessPlan> inputQueue;
+
+    public BGZFBlockLoadingDispatcher(final int numThreads, final int numFileHandles) {
+        threadPool = Executors.newFixedThreadPool(numThreads);
+        fileHandleCache = new FileHandleCache(numFileHandles);
+        inputQueue = new LinkedList<BAMAccessPlan>();
+
+        threadPool.execute(new BlockLoader(this,fileHandleCache,true));
+    }
+
+    /**
+     * Initiates a request for a new block load.
+      * @param readerPosition Position at which to load.
+     */
+    void queueBlockLoad(final BAMAccessPlan readerPosition) {
+        synchronized(inputQueue) {
+            inputQueue.add(readerPosition);
+            inputQueue.notify();
+        }
+    }
+
+    /**
+     * Claims the next work request from the queue.
+     * @return The next work request, or null if none is available.
+     */
+    BAMAccessPlan claimNextWorkRequest() {
+        synchronized(inputQueue) {
+            while(inputQueue.isEmpty()) {
+                try {
+                    inputQueue.wait();
+                }
+                catch(InterruptedException ex) {
+                    throw new ReviewedGATKException("Interrupt occurred waiting for next block reader work item");
+                }
+            }
+            return inputQueue.poll();
+        }
+    }
+}
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/datasources/reads/BlockInputStream.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/datasources/reads/BlockInputStream.java
new file mode 100644
index 0000000..11fecb6
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/datasources/reads/BlockInputStream.java
@@ -0,0 +1,450 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.engine.datasources.reads;
+
+import htsjdk.samtools.GATKBAMFileSpan;
+import htsjdk.samtools.GATKChunk;
+import htsjdk.samtools.util.BlockCompressedInputStream;
+import org.broadinstitute.gatk.utils.exceptions.ReviewedGATKException;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.nio.ByteBuffer;
+import java.nio.ByteOrder;
+import java.util.Arrays;
+import java.util.LinkedList;
+import java.util.List;
+
+/**
+ * Presents decompressed blocks to the SAMFileReader.
+ */
+public class BlockInputStream extends InputStream {
+    /**
+     * Mechanism for triggering block loads.
+     */
+    private final BGZFBlockLoadingDispatcher dispatcher;
+
+    /**
+     * The reader whose data is supplied by this input stream.
+     */
+    private final SAMReaderID reader;
+
+    /**
+     * Length of the input stream.
+     */
+    private final long length;
+
+    /**
+     * The latest error reported by an asynchronous block load.
+     */
+    private Throwable error;
+
+    /**
+     * Current accessPlan.
+     */
+    private BAMAccessPlan accessPlan;
+
+    /**
+     * A stream of compressed data blocks.
+     */
+    private final ByteBuffer buffer;
+
+    /**
+     * Offsets of the given blocks in the buffer.
+     */
+    private LinkedList<Integer> blockOffsets = new LinkedList<Integer>();
+
+    /**
+     * Source positions of the given blocks in the buffer.
+     */
+    private LinkedList<Long> blockPositions = new LinkedList<Long>();
+
+    /**
+     * Provides a lock to wait for more data to arrive.
+     */
+    private final Object lock = new Object();
+
+    /**
+     * An input stream to use when comparing data back to what it should look like.
+     */
+    private final BlockCompressedInputStream validatingInputStream;
+
+    /**
+     * Create a new block presenting input stream with a dedicated buffer.
+     * @param dispatcher the block loading messenger.
+     * @param reader the reader for which to load data.
+     * @param validate validates the contents read into the buffer against the contents of a Picard BlockCompressedInputStream.
+     */
+    BlockInputStream(final BGZFBlockLoadingDispatcher dispatcher, final SAMReaderID reader, final boolean validate) {
+        this.reader = reader;
+        this.length = reader.samFile.length();
+
+        buffer = ByteBuffer.wrap(new byte[64*1024]);
+        buffer.order(ByteOrder.LITTLE_ENDIAN);
+
+        // The state of the buffer assumes that the range of data written into the buffer appears in the range
+        // [position,limit), while extra capacity exists in the range [limit,capacity)
+        buffer.limit(0);
+
+        this.dispatcher = dispatcher;
+        // TODO: Kill the region when all we want to do is start at the beginning of the stream and run to the end of the stream.
+        this.accessPlan = new BAMAccessPlan(reader,this,new GATKBAMFileSpan(new GATKChunk(0,Long.MAX_VALUE)));
+
+        // The block offsets / block positions guarantee that the ending offset/position in the data structure maps to
+        // the point in the file just following the last read.  These two arrays should never be empty; initializing
+        // to 0 to match the position above.
+        this.blockOffsets.add(0);
+        this.blockPositions.add(0L);
+
+        try {
+            if(validate) {
+                System.out.printf("BlockInputStream %s: BGZF block validation mode activated%n",this);
+                validatingInputStream = new BlockCompressedInputStream(reader.samFile);
+                // A bug in ValidatingInputStream means that calling getFilePointer() immediately after initialization will result in an NPE.
+                // Poke the stream to start reading data.
+                validatingInputStream.available();
+            }
+            else
+                validatingInputStream = null;
+        }
+        catch(IOException ex) {
+            throw new ReviewedGATKException("Unable to validate against Picard input stream",ex);
+        }
+    }
+
+    public long length() {
+        return length;
+    }
+
+    public long getFilePointer() {
+        long filePointer;
+        synchronized(lock) {
+            // Find the current block within the input stream.
+            int blockIndex;
+            for(blockIndex = 0; blockIndex+1 < blockOffsets.size() && buffer.position() > blockOffsets.get(blockIndex+1); blockIndex++)
+                ;
+            filePointer = blockPositions.get(blockIndex) + (buffer.position()-blockOffsets.get(blockIndex));
+        }
+
+//        if(validatingInputStream != null && filePointer != validatingInputStream.getFilePointer())
+//            throw new ReviewedGATKException(String.format("Position of input stream is invalid; expected (block address, block offset) = (%d,%d), got (%d,%d)",
+//                    BlockCompressedFilePointerUtil.getBlockAddress(validatingInputStream.getFilePointer()),BlockCompressedFilePointerUtil.getBlockOffset(validatingInputStream.getFilePointer()),
+//                    BlockCompressedFilePointerUtil.getBlockAddress(filePointer),BlockCompressedFilePointerUtil.getBlockOffset(filePointer)));
+
+        return filePointer;
+    }
+
+    private void clearBuffers() {
+        this.accessPlan.reset();
+
+        // Buffer semantics say that outside of a lock, buffer should always be prepared for reading.
+        // Indicate no data to be read.
+        buffer.clear();
+        buffer.limit(0);
+
+        // Clear everything except the last block offset / position
+        blockOffsets.clear();
+        blockOffsets.add(0);
+        while(blockPositions.size() > 1)
+            blockPositions.removeFirst();
+    }
+
+    public boolean eof() {
+        synchronized(lock) {
+            // TODO: Handle multiple empty BGZF blocks at end of the file.
+            return accessPlan != null && (accessPlan.getBlockAddress() < 0 || accessPlan.getBlockAddress() >= length);
+        }
+    }
+
+    /**
+     * Submits a new access plan for the given dataset and seeks to the given point.
+     * @param accessPlan The next seek point for BAM data in this reader.
+     */
+    public void submitAccessPlan(final BAMAccessPlan accessPlan) {
+        //System.out.printf("Thread %s: submitting access plan for block at position: %d%n",Thread.currentThread().getId(),position.getBlockAddress());
+        this.accessPlan = accessPlan;
+        accessPlan.reset();
+
+        clearBuffers();
+
+        // Pull the iterator past any oddball chunks at the beginning of the shard (chunkEnd < chunkStart, empty chunks, etc).
+        // TODO: Don't pass these empty chunks in.
+        accessPlan.advancePosition(makeFilePointer(accessPlan.getBlockAddress(),0));
+
+        if(accessPlan.getBlockAddress() >= 0) {
+            waitForBufferFill();
+        }
+
+        if(validatingInputStream != null) {
+            try {
+                validatingInputStream.seek(makeFilePointer(accessPlan.getBlockAddress(),0));
+            }
+            catch(IOException ex) {
+                throw new ReviewedGATKException("Unable to validate against Picard input stream",ex);
+            }
+        }
+
+    }
+
+
+    private void compactBuffer() {
+        // Compact buffer to maximize storage space.
+        int bytesToRemove = 0;
+
+        // Look ahead to see if we can compact away the first blocks in the series.
+        while(blockOffsets.size() > 1 && buffer.position() >= blockOffsets.get(1)) {
+            blockOffsets.remove();
+            blockPositions.remove();
+            bytesToRemove = blockOffsets.peek();
+        }
+
+        // If we end up with an empty block at the end of the series, compact this as well.
+        if(buffer.remaining() == 0 && blockOffsets.size() > 1 && buffer.position() >= blockOffsets.peek()) {
+            bytesToRemove += buffer.position();
+            blockOffsets.remove();
+            blockPositions.remove();
+        }
+
+        int finalBufferStart = buffer.position() - bytesToRemove;
+        int finalBufferSize = buffer.remaining();
+
+        // Position the buffer to remove the unneeded data, and compact it away.
+        buffer.position(bytesToRemove);
+        buffer.compact();
+
+        // Reset the limits for reading.
+        buffer.position(finalBufferStart);
+        buffer.limit(finalBufferStart+finalBufferSize);
+
+        // Shift everything in the offset buffer down to accommodate the bytes removed from the buffer.
+        for(int i = 0; i < blockOffsets.size(); i++)
+            blockOffsets.set(i,blockOffsets.get(i)-bytesToRemove);
+    }
+
+    /**
+     * Push contents of incomingBuffer into the end of this buffer.
+     * MUST be called from a thread that is NOT the reader thread.
+     * @param incomingBuffer The data being pushed into this input stream.
+     * @param accessPlan target access plan for the data.
+     * @param filePosition the current position of the file pointer
+     */
+    public void copyIntoBuffer(final ByteBuffer incomingBuffer, final BAMAccessPlan accessPlan, final long filePosition) {
+        synchronized(lock) {
+            try {
+                if(validatingInputStream != null) {
+                    byte[] validBytes = new byte[incomingBuffer.remaining()];
+
+                    byte[] currentBytes = new byte[incomingBuffer.remaining()];
+                    int pos = incomingBuffer.position();
+                    int lim = incomingBuffer.limit();
+                    incomingBuffer.get(currentBytes);
+
+                    incomingBuffer.limit(lim);
+                    incomingBuffer.position(pos);
+
+                    long currentFilePointer = validatingInputStream.getFilePointer();
+                    validatingInputStream.seek(makeFilePointer(accessPlan.getBlockAddress(), 0));
+                    validatingInputStream.read(validBytes);
+                    validatingInputStream.seek(currentFilePointer);
+
+                    if(!Arrays.equals(validBytes,currentBytes))
+                        throw new ReviewedGATKException(String.format("Bytes being inserted into BlockInputStream %s are incorrect",this));
+                }
+
+                compactBuffer();
+                // Open up the buffer for more reading.
+                buffer.limit(buffer.capacity());
+
+                // Get the spans overlapping this particular block...
+                List<GATKChunk> spansOverlapping = accessPlan.getSpansOverlappingBlock(accessPlan.getBlockAddress(),filePosition);
+
+                // ...and advance the block
+                this.accessPlan = accessPlan;
+                accessPlan.advancePosition(makeFilePointer(filePosition, 0));
+
+                if(buffer.remaining() < incomingBuffer.remaining())
+                    lock.wait();
+
+                final int bytesInIncomingBuffer = incomingBuffer.limit();
+
+                for(GATKChunk spanOverlapping: spansOverlapping) {
+                    // Clear out the endcap tracking state and add in the starting position for this transfer.
+                    blockOffsets.removeLast();
+                    blockOffsets.add(buffer.position());
+                    blockPositions.removeLast();
+                    blockPositions.add(spanOverlapping.getChunkStart());
+
+                    // Stream the buffer into the data stream.
+                    incomingBuffer.limit((spanOverlapping.getBlockEnd() > spanOverlapping.getBlockStart()) ? bytesInIncomingBuffer : spanOverlapping.getBlockOffsetEnd());
+                    incomingBuffer.position(spanOverlapping.getBlockOffsetStart());
+                    buffer.put(incomingBuffer);
+
+                    // Add the endcap for this transfer.
+                    blockOffsets.add(buffer.position());
+                    blockPositions.add(spanOverlapping.getChunkEnd());
+                }
+
+                // Set up the buffer for reading.
+                buffer.flip();
+
+                lock.notify();
+            }
+            catch(Exception ex) {
+                reportException(ex);
+                lock.notify();
+            }
+        }
+    }
+
+    void reportException(Throwable t) {
+        synchronized(lock) {
+            this.error = t;
+            lock.notify();
+        }
+    }
+
+    private void checkForErrors() {
+        synchronized(lock) {
+            if(error != null) {
+                ReviewedGATKException toThrow = new ReviewedGATKException(String.format("Thread %s, BlockInputStream %s: Unable to retrieve BAM data from disk",Thread.currentThread().getId(),this),error);
+                toThrow.setStackTrace(error.getStackTrace());
+                throw toThrow;
+            }
+        }
+    }
+
+    /**
+     * Reads the next byte of data from the input stream.
+     * @return Next byte of data, from 0->255, as an int.
+     */
+    @Override
+    public int read() {
+        byte[] singleByte = new byte[1];
+        read(singleByte);
+        return singleByte[0];
+    }
+
+    /**
+     * Fills the given byte array to the extent possible.
+     * @param bytes byte array to be filled.
+     * @return The number of bytes actually read.
+     */
+    @Override
+    public int read(byte[] bytes) {
+        return read(bytes,0,bytes.length);
+    }
+
+    @Override
+    public int read(byte[] bytes, final int offset, final int length) {
+        int remaining = length;
+        synchronized(lock) {
+            while(remaining > 0) {
+                // Check for error conditions during last read.
+                checkForErrors();
+
+                // If completely out of space, queue up another buffer fill.
+                waitForBufferFill();
+
+                // Couldn't manage to load any data at all; abort and return what's available.
+                if(buffer.remaining() == 0)
+                    break;
+
+                int numBytesToCopy = Math.min(buffer.remaining(),remaining);
+                buffer.get(bytes,length-remaining+offset,numBytesToCopy);
+                remaining -= numBytesToCopy;
+
+                //if(remaining > 0)
+                //    System.out.printf("Thread %s: read the first %d bytes of a %d byte request%n",Thread.currentThread().getId(),length-remaining,length);
+                // TODO: Assert that we don't copy across a block boundary
+            }
+
+            // Notify any waiting threads that some of the contents of the buffer were removed.
+            if(length-remaining > 0)
+                lock.notify();
+        }
+
+//        if(validatingInputStream != null) {
+//            byte[] validBytes = new byte[length];
+//            try {
+//                validatingInputStream.read(validBytes,offset,length);
+//                for(int i = offset; i < offset+length; i++) {
+//                    if(bytes[i] != validBytes[i])
+//                        throw new ReviewedGATKException(String.format("Thread %s: blockInputStream %s attempting to return wrong set of bytes; mismatch at offset %d",Thread.currentThread().getId(),this,i));
+//                }
+//            }
+//            catch(IOException ex) {
+//                throw new ReviewedGATKException("Unable to validate against Picard input stream",ex);
+//            }
+//        }
+
+        // If any data was copied into the buffer, return the amount of data copied.
+        if(remaining < length)
+            return length - remaining;
+
+        // Otherwise, return -1.
+        return -1;
+    }
+
+    public void close() {
+        if(validatingInputStream != null) {
+            try {
+                validatingInputStream.close();
+            }
+            catch(IOException ex) {
+                throw new ReviewedGATKException("Unable to validate against Picard input stream",ex);
+            }
+        }
+    }
+
+    public String getSource() {
+        return reader.getSamFilePath();
+    }
+
+    private void waitForBufferFill() {
+        synchronized(lock) {
+            if(buffer.remaining() == 0 && !eof()) {
+                //System.out.printf("Thread %s is waiting for a buffer fill from position %d to buffer %s%n",Thread.currentThread().getId(),position.getBlockAddress(),this);
+                dispatcher.queueBlockLoad(accessPlan);
+                try {
+                    lock.wait();
+                }
+                catch(InterruptedException ex) {
+                    throw new ReviewedGATKException("Interrupt occurred waiting for buffer to fill",ex);
+                }
+            }
+        }
+    }
+
+    /**
+     * Create an encoded BAM file pointer given the address of a BGZF block and an offset.
+     * @param blockAddress Physical address on disk of a BGZF block.
+     * @param blockOffset Offset into the uncompressed data stored in the BGZF block.
+     * @return 64-bit pointer encoded according to the BAM spec.
+     */
+    public static long makeFilePointer(final long blockAddress, final int blockOffset) {
+        return blockAddress << 16 | blockOffset;
+    }
+}
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/datasources/reads/BlockLoader.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/datasources/reads/BlockLoader.java
new file mode 100644
index 0000000..09a0cab
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/datasources/reads/BlockLoader.java
@@ -0,0 +1,189 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.engine.datasources.reads;
+
+import htsjdk.samtools.util.BlockCompressedStreamConstants;
+import org.broadinstitute.gatk.utils.exceptions.ReviewedGATKException;
+
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.nio.ByteBuffer;
+import java.nio.ByteOrder;
+import java.nio.channels.FileChannel;
+import java.util.zip.DataFormatException;
+import java.util.zip.Inflater;
+
+/**
+ * An engine for loading blocks.
+ */
+class BlockLoader implements Runnable {
+    /**
+     * Coordinates the input queue.
+     */
+    private BGZFBlockLoadingDispatcher dispatcher;
+
+    /**
+     * A cache from which to retrieve open file handles.
+     */
+    private final FileHandleCache fileHandleCache;
+
+    /**
+     * Whether asynchronous decompression should happen.
+     */
+    private final boolean decompress;
+
+    /**
+     * An direct input buffer for incoming data from disk.
+     */
+    private final ByteBuffer inputBuffer;
+
+    public BlockLoader(final BGZFBlockLoadingDispatcher dispatcher, final FileHandleCache fileHandleCache, final boolean decompress) {
+        this.dispatcher = dispatcher;
+        this.fileHandleCache = fileHandleCache;
+        this.decompress = decompress;
+
+        this.inputBuffer = ByteBuffer.allocateDirect(64*1024 + BlockCompressedStreamConstants.EMPTY_GZIP_BLOCK.length);
+        inputBuffer.order(ByteOrder.LITTLE_ENDIAN);
+    }
+
+    public void run() {
+        for(;;) {
+            BAMAccessPlan accessPlan = null;
+            try {
+                accessPlan = dispatcher.claimNextWorkRequest();
+                FileInputStream inputStream = fileHandleCache.claimFileInputStream(accessPlan.getReader());
+
+                //long blockAddress = readerPosition.getBlockAddress();
+                //System.out.printf("Thread %s: BlockLoader: copying bytes from %s at position %d into %s%n",Thread.currentThread().getId(),inputStream,blockAddress,readerPosition.getInputStream());
+
+                ByteBuffer compressedBlock = readBGZFBlock(inputStream,accessPlan.getBlockAddress());
+                long nextBlockAddress = position(inputStream);
+                fileHandleCache.releaseFileInputStream(accessPlan.getReader(),inputStream);
+
+                ByteBuffer block = decompress ? decompressBGZFBlock(compressedBlock) : compressedBlock;
+                int bytesCopied = block.remaining();
+
+                BlockInputStream bamInputStream = accessPlan.getInputStream();
+                bamInputStream.copyIntoBuffer(block,accessPlan,nextBlockAddress);
+
+                //System.out.printf("Thread %s: BlockLoader: copied %d bytes from %s at position %d into %s%n",Thread.currentThread().getId(),bytesCopied,inputStream,blockAddress,readerPosition.getInputStream());
+            }
+            catch(Throwable error) {
+                if(accessPlan != null && accessPlan.getInputStream() != null)
+                    accessPlan.getInputStream().reportException(error);
+            }
+        }
+
+    }
+
+    private ByteBuffer readBGZFBlock(final FileInputStream inputStream, final long blockAddress) throws IOException {
+        FileChannel channel = inputStream.getChannel();
+
+        // Read the block header
+        channel.position(blockAddress);
+
+        int uncompressedDataSize = 0;
+        int bufferSize = 0;
+
+        do {
+            inputBuffer.clear();
+            inputBuffer.limit(BlockCompressedStreamConstants.BLOCK_HEADER_LENGTH);
+            channel.read(inputBuffer);
+
+            // Read out the size of the full BGZF block into a two bit short container, then 'or' that
+            // value into an int buffer to transfer the bitwise contents into an int.
+            inputBuffer.flip();
+            if(inputBuffer.remaining() != BlockCompressedStreamConstants.BLOCK_HEADER_LENGTH)
+                throw new ReviewedGATKException("BUG: unable to read a the complete block header in one pass.");
+
+            // Verify that the file was read at a valid point.
+            if(unpackUByte8(inputBuffer,0) != BlockCompressedStreamConstants.GZIP_ID1 ||
+                    unpackUByte8(inputBuffer,1) != BlockCompressedStreamConstants.GZIP_ID2 ||
+                    unpackUByte8(inputBuffer,3) != BlockCompressedStreamConstants.GZIP_FLG ||
+                    unpackUInt16(inputBuffer,10) != BlockCompressedStreamConstants.GZIP_XLEN ||
+                    unpackUByte8(inputBuffer,12) != BlockCompressedStreamConstants.BGZF_ID1 ||
+                    unpackUByte8(inputBuffer,13) != BlockCompressedStreamConstants.BGZF_ID2) {
+                throw new ReviewedGATKException("BUG: Started reading compressed block at incorrect position");
+            }
+
+            inputBuffer.position(BlockCompressedStreamConstants.BLOCK_LENGTH_OFFSET);
+            bufferSize = unpackUInt16(inputBuffer,BlockCompressedStreamConstants.BLOCK_LENGTH_OFFSET)+1;
+
+            // Adjust buffer limits and finish reading the block.  Also read the next header, just in case there's a 0-byte block.
+            inputBuffer.limit(bufferSize);
+            inputBuffer.position(BlockCompressedStreamConstants.BLOCK_HEADER_LENGTH);
+            channel.read(inputBuffer);
+
+            // Check the uncompressed length.  If 0 and not at EOF, we'll want to check the next block.
+            uncompressedDataSize = inputBuffer.getInt(inputBuffer.limit()-4);
+            //System.out.printf("Uncompressed block size of the current block (at position %d) is %d%n",channel.position()-inputBuffer.limit(),uncompressedDataSize);
+        }
+        while(uncompressedDataSize == 0 && channel.position() < channel.size());
+
+        // Prepare the buffer for reading.
+        inputBuffer.flip();
+
+        return inputBuffer;
+    }
+
+    private ByteBuffer decompressBGZFBlock(final ByteBuffer bgzfBlock) throws DataFormatException {
+        final int compressedBufferSize = bgzfBlock.remaining();
+
+        // Determine the uncompressed buffer size (
+        bgzfBlock.position(bgzfBlock.limit()-4);
+        int uncompressedBufferSize = bgzfBlock.getInt();
+        byte[] uncompressedContent = new byte[uncompressedBufferSize];
+
+        // Bound the CDATA section of the buffer.
+        bgzfBlock.limit(compressedBufferSize-BlockCompressedStreamConstants.BLOCK_FOOTER_LENGTH);
+        bgzfBlock.position(BlockCompressedStreamConstants.BLOCK_HEADER_LENGTH);
+        byte[] compressedContent = new byte[bgzfBlock.remaining()];
+        ByteBuffer.wrap(compressedContent).put(bgzfBlock);
+
+        // Decompress the buffer.
+        final Inflater inflater = new Inflater(true);
+        inflater.setInput(compressedContent);
+        int bytesUncompressed = inflater.inflate(uncompressedContent);
+        if(bytesUncompressed != uncompressedBufferSize)
+            throw new ReviewedGATKException("Error decompressing block");
+
+        return ByteBuffer.wrap(uncompressedContent);
+    }
+
+    private long position(final FileInputStream inputStream) throws IOException {
+        return inputStream.getChannel().position();
+    }
+
+    private int unpackUByte8(final ByteBuffer buffer,final int position) {
+        return buffer.get(position) & 0xFF;
+    }
+
+    private int unpackUInt16(final ByteBuffer buffer,final int position) {
+        // Read out the size of the full BGZF block into a two bit short container, then 'or' that
+        // value into an int buffer to transfer the bitwise contents into an int.
+        return buffer.getShort(position) & 0xFFFF;
+    }
+}
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/datasources/reads/FileHandleCache.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/datasources/reads/FileHandleCache.java
new file mode 100644
index 0000000..8d5ab3b
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/datasources/reads/FileHandleCache.java
@@ -0,0 +1,232 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.engine.datasources.reads;
+
+import org.broadinstitute.gatk.utils.exceptions.ReviewedGATKException;
+import org.broadinstitute.gatk.utils.exceptions.GATKException;
+
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.LinkedHashMap;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+import java.util.Queue;
+
+/**
+ * Caches frequently used  file handles.  Right now, caches only a single file handle.
+ * TODO: Generalize to support arbitrary file handle caches.
+ */
+public class FileHandleCache {
+    /**
+     * The underlying data structure storing file handles.
+     */
+    private final FileHandleStorage fileHandleStorage;
+
+    /**
+     * How many file handles should be kept open at once.
+     */
+    private final int cacheSize;
+
+    /**
+     * A uniquifier: assign a unique ID to every instance of a file handle.
+     */
+    private final Map<SAMReaderID,Integer> keyCounter = new HashMap<SAMReaderID,Integer>();
+
+    /**
+     * A shared lock, private so that outside users cannot notify it.
+     */
+    private final Object lock = new Object();
+
+    /**
+     * Indicates how many file handles are outstanding at this point.
+     */
+    private int numOutstandingFileHandles = 0;
+
+    /**
+     * Create a new file handle cache of the given cache size.
+     * @param cacheSize how many readers to hold open at once.
+     */
+    public FileHandleCache(final int cacheSize) {
+        this.cacheSize = cacheSize;
+        fileHandleStorage = new FileHandleStorage();
+    }
+
+    /**
+     * Retrieves or opens a file handle for the given reader ID.
+     * @param key The ke
+     * @return A file input stream from the cache, if available, or otherwise newly opened.
+     */
+    public FileInputStream claimFileInputStream(final SAMReaderID key) {
+        synchronized(lock) {
+            FileInputStream inputStream = findExistingEntry(key);
+            if(inputStream == null) {
+                try {
+                    // If the cache is maxed out, wait for another file handle to emerge.
+                    if(numOutstandingFileHandles >= cacheSize)
+                        lock.wait();
+                }
+                catch(InterruptedException ex) {
+                    throw new ReviewedGATKException("Interrupted while waiting for a file handle");
+                }
+                inputStream = openInputStream(key);
+            }
+            numOutstandingFileHandles++;
+
+            //System.out.printf("Handing input stream %s to thread %s%n",inputStream,Thread.currentThread().getId());
+            return inputStream;
+        }
+    }
+
+    /**
+     * Releases the current reader and returns it to the cache.
+     * @param key The reader.
+     * @param inputStream The stream being used.
+     */
+    public void releaseFileInputStream(final SAMReaderID key, final FileInputStream inputStream) {
+        synchronized(lock) {
+            numOutstandingFileHandles--;
+            UniqueKey newID = allocateKey(key);
+            fileHandleStorage.put(newID,inputStream);
+            // Let any listeners know that another file handle has become available.
+            lock.notify();
+        }
+    }
+
+    /**
+     * Finds an existing entry in the storage mechanism.
+     * @param key Reader.
+     * @return a cached stream, if available.  Otherwise,
+     */
+    private FileInputStream findExistingEntry(final SAMReaderID key) {
+        int existingHandles = getMostRecentUniquifier(key);
+
+        // See if any of the keys currently exist in the repository.
+        for(int i = 0; i <= existingHandles; i++) {
+            UniqueKey uniqueKey = new UniqueKey(key,i);
+            if(fileHandleStorage.containsKey(uniqueKey))
+                return fileHandleStorage.remove(uniqueKey);
+        }
+
+        return null;
+    }
+
+    /**
+     * Gets the most recent uniquifier used for the given reader.
+     * @param reader Reader for which to determine uniqueness.
+     * @return
+     */
+    private int getMostRecentUniquifier(final SAMReaderID reader) {
+        if(keyCounter.containsKey(reader))
+            return keyCounter.get(reader);
+        else return -1;
+    }
+
+    private UniqueKey allocateKey(final SAMReaderID reader) {
+        int uniquifier = getMostRecentUniquifier(reader)+1;
+        keyCounter.put(reader,uniquifier);
+        return new UniqueKey(reader,uniquifier);
+    }
+
+    private FileInputStream openInputStream(final SAMReaderID reader) {
+        try {
+            return new FileInputStream(reader.getSamFilePath());
+        }
+        catch(IOException ex) {
+            throw new GATKException("Unable to open input file");
+        }
+    }
+
+    private void closeInputStream(final FileInputStream inputStream) {
+        try {
+            inputStream.close();
+        }
+        catch(IOException ex) {
+            throw new GATKException("Unable to open input file");
+        }
+    }
+
+    /**
+     * Actually contains the file handles, purging them as they get too old.
+     */
+    private class FileHandleStorage extends LinkedHashMap<UniqueKey,FileInputStream> {
+        /**
+         * Remove the oldest entry
+         * @param entry Entry to consider removing.
+         * @return True if the cache size has been exceeded.  False otherwise.
+         */
+        @Override
+        protected boolean removeEldestEntry(Map.Entry<UniqueKey,FileInputStream> entry) {
+            synchronized (lock) {
+                if(size() > cacheSize) {
+                    keyCounter.put(entry.getKey().key,keyCounter.get(entry.getKey().key)-1);
+                    closeInputStream(entry.getValue());
+
+                    return true;
+                }
+            }
+            return false;
+        }
+    }
+
+    /**
+     * Uniquifies a key by adding a numerical uniquifier.
+     */
+    private class UniqueKey {
+        /**
+         * The file handle's key.
+         */
+        private final SAMReaderID key;
+
+        /**
+         * A uniquifier, so that multiple of the same reader can exist in the cache.
+         */
+        private final int uniqueID;
+
+        public UniqueKey(final SAMReaderID reader, final int uniqueID) {
+            this.key = reader;
+            this.uniqueID = uniqueID;
+        }
+
+        @Override
+        public boolean equals(Object other) {
+            if(!(other instanceof UniqueKey))
+                return false;
+            UniqueKey otherUniqueKey = (UniqueKey)other;
+            return key.equals(otherUniqueKey.key) && this.uniqueID == otherUniqueKey.uniqueID;
+        }
+
+        @Override
+        public int hashCode() {
+            return key.hashCode();
+        }
+    }
+
+
+
+}
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/datasources/reads/FilePointer.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/datasources/reads/FilePointer.java
new file mode 100644
index 0000000..99d9def
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/datasources/reads/FilePointer.java
@@ -0,0 +1,436 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.engine.datasources.reads;
+
+import htsjdk.samtools.util.PeekableIterator;
+import htsjdk.samtools.GATKBAMFileSpan;
+import htsjdk.samtools.GATKChunk;
+import htsjdk.samtools.SAMFileSpan;
+import htsjdk.samtools.SAMRecord;
+import org.broadinstitute.gatk.utils.GenomeLoc;
+import org.broadinstitute.gatk.utils.GenomeLocParser;
+import org.broadinstitute.gatk.utils.Utils;
+import org.broadinstitute.gatk.utils.exceptions.ReviewedGATKException;
+import org.broadinstitute.gatk.utils.interval.IntervalMergingRule;
+import org.broadinstitute.gatk.utils.interval.IntervalUtils;
+
+import java.util.*;
+
+/**
+ * Represents a small section of a BAM file, and every associated interval.
+ */
+public class FilePointer {
+    protected final SortedMap<SAMReaderID,SAMFileSpan> fileSpans = new TreeMap<SAMReaderID,SAMFileSpan>();
+    protected final List<GenomeLoc> locations = new ArrayList<GenomeLoc>();
+    protected final IntervalMergingRule intervalMergingRule;
+
+    /**
+     * Does this file pointer point into an unmapped region?
+     */
+    protected final boolean isRegionUnmapped;
+
+    /**
+     * Is this FilePointer "monolithic"? That is, does it represent all regions in all files that we will
+     * ever visit during this GATK run? If this is set to true, the engine will expect to see only this
+     * one FilePointer during the entire run, and this FilePointer will be allowed to contain intervals
+     * from more than one contig.
+     */
+    private boolean isMonolithic = false;
+
+    /**
+     * Index of the contig covered by this FilePointer. Only meaningful for non-monolithic, mapped FilePointers
+     */
+    private Integer contigIndex = null;
+
+
+    public FilePointer( final IntervalMergingRule mergeRule, final List<GenomeLoc> locations ) {
+        this.intervalMergingRule = mergeRule;
+        this.locations.addAll(locations);
+        this.isRegionUnmapped = checkUnmappedStatus();
+
+        validateAllLocations();
+        if ( locations.size() > 0 ) {
+            contigIndex = locations.get(0).getContigIndex();
+        }
+    }
+
+    public FilePointer( final IntervalMergingRule mergeRule, final GenomeLoc... locations ) {
+        this(mergeRule, Arrays.asList(locations));
+    }
+
+    public FilePointer( final Map<SAMReaderID,SAMFileSpan> fileSpans, final IntervalMergingRule mergeRule, final List<GenomeLoc> locations ) {
+        this(mergeRule, locations);
+        this.fileSpans.putAll(fileSpans);
+    }
+
+    private boolean checkUnmappedStatus() {
+        boolean foundMapped = false, foundUnmapped = false;
+
+        for( GenomeLoc location: locations ) {
+            if ( GenomeLoc.isUnmapped(location) )
+                foundUnmapped = true;
+            else
+                foundMapped = true;
+        }
+        if ( foundMapped && foundUnmapped )
+            throw new ReviewedGATKException("BUG: File pointers cannot be mixed mapped/unmapped.");
+
+        return foundUnmapped;
+    }
+
+    private void validateAllLocations() {
+        // Unmapped and monolithic FilePointers are exempted from the one-contig-only restriction
+        if ( isRegionUnmapped || isMonolithic ) {
+            return;
+        }
+
+        Integer previousContigIndex = null;
+
+        for ( GenomeLoc location : locations ) {
+            if ( previousContigIndex != null && previousContigIndex != location.getContigIndex() ) {
+                throw new ReviewedGATKException("Non-monolithic file pointers must contain intervals from at most one contig");
+            }
+
+            previousContigIndex = location.getContigIndex();
+        }
+    }
+
+    private void validateLocation( GenomeLoc location ) {
+        if ( isRegionUnmapped != GenomeLoc.isUnmapped(location) ) {
+            throw new ReviewedGATKException("BUG: File pointers cannot be mixed mapped/unmapped.");
+        }
+        if ( ! isRegionUnmapped && ! isMonolithic && contigIndex != null && contigIndex != location.getContigIndex() ) {
+            throw new ReviewedGATKException("Non-monolithic file pointers must contain intervals from at most one contig");
+        }
+    }
+
+    /**
+     * Returns an immutable view of this FilePointer's file spans
+     *
+     * @return an immutable view of this FilePointer's file spans
+     */
+    public Map<SAMReaderID, SAMFileSpan> getFileSpans() {
+        return Collections.unmodifiableMap(fileSpans);
+    }
+
+    /**
+     * Returns an immutable variant of the list of locations.
+     * @return
+     */
+    public List<GenomeLoc> getLocations() {
+        return Collections.unmodifiableList(locations);
+    }
+
+    /**
+     * Returns the index of the contig into which this FilePointer points (a FilePointer can represent
+     * regions in at most one contig).
+     *
+     * @return the index of the contig into which this FilePointer points
+     */
+    public int getContigIndex() {
+        return locations.size() > 0 ? locations.get(0).getContigIndex() : SAMRecord.NO_ALIGNMENT_REFERENCE_INDEX;
+    }
+
+    /**
+     * Returns the IntervalMergingRule used by this FilePointer to merge adjacent locations
+     *
+     * @return the IntervalMergingRule used by this FilePointer (never null)
+     */
+    public IntervalMergingRule getIntervalMergingRule() {
+        return intervalMergingRule;
+    }
+
+    /**
+     * Is this FilePointer "monolithic"? That is, does it represent all regions in all files that we will
+     * ever visit during this GATK run? If this is set to true, the engine will expect to see only this
+     * one FilePointer during the entire run, and this FilePointer will be allowed to contain intervals
+     * from more than one contig.
+     *
+     * @return true if this FP is a monolithic FP representing all regions in all files, otherwise false
+     */
+    public boolean isMonolithic() {
+        return isMonolithic;
+    }
+
+    /**
+     * Set this FP's "monolithic" status to true or false. An FP is monolithic if it represents all
+     * regions in all files that we will ever visit, and is the only FP we will ever create. A monolithic
+     * FP may contain intervals from more than one contig.
+     *
+     * @param isMonolithic set this FP's monolithic status to this value
+     */
+    public void setIsMonolithic( boolean isMonolithic ) {
+        this.isMonolithic = isMonolithic;
+    }
+
+    @Override
+    public boolean equals(final Object other) {
+        if(!(other instanceof FilePointer))
+            return false;
+        FilePointer otherFilePointer = (FilePointer)other;
+
+        // intervals
+        if(this.locations.size() != otherFilePointer.locations.size())
+            return false;
+        for(int i = 0; i < locations.size(); i++) {
+            if(!this.locations.get(i).equals(otherFilePointer.locations.get(i)))
+                return false;
+        }
+
+        // fileSpans
+        if(this.fileSpans.size() != otherFilePointer.fileSpans.size())
+            return false;
+        Iterator<Map.Entry<SAMReaderID,SAMFileSpan>> thisEntries = this.fileSpans.entrySet().iterator();
+        Iterator<Map.Entry<SAMReaderID,SAMFileSpan>> otherEntries = otherFilePointer.fileSpans.entrySet().iterator();
+        while(thisEntries.hasNext() || otherEntries.hasNext()) {
+            if(!thisEntries.next().equals(otherEntries.next()))
+                return false;
+        }
+        
+        return true;
+    }
+
+    public void addLocation(final GenomeLoc location) {
+        validateLocation(location);
+
+        this.locations.add(location);
+        if ( contigIndex == null ) {
+            contigIndex = location.getContigIndex();
+        }
+    }
+
+    public void addFileSpans(final SAMReaderID id, final SAMFileSpan fileSpan) {
+        this.fileSpans.put(id,fileSpan);
+    }
+
+    public void addFileSpans(final Map<SAMReaderID, GATKBAMFileSpan> fileSpans) {
+        this.fileSpans.putAll(fileSpans);
+    }
+
+
+    /**
+     * Computes the size of this file span, in uncompressed bytes.
+     * @return Size of the file span.
+     */
+    public long size() {
+        long size = 0L;
+        for(SAMFileSpan fileSpan: fileSpans.values())
+            size += ((GATKBAMFileSpan)fileSpan).size();
+        return size;
+    }
+
+    /**
+     * Returns the difference in size between two filespans.
+     * @param other Other filespan against which to measure.
+     * @return The difference in size between the two file pointers.
+     */
+    public long minus(final FilePointer other) {
+        long difference = 0;
+        PeekableIterator<Map.Entry<SAMReaderID,SAMFileSpan>> thisIterator = new PeekableIterator<Map.Entry<SAMReaderID,SAMFileSpan>>(this.fileSpans.entrySet().iterator());
+        PeekableIterator<Map.Entry<SAMReaderID,SAMFileSpan>> otherIterator = new PeekableIterator<Map.Entry<SAMReaderID,SAMFileSpan>>(other.fileSpans.entrySet().iterator());
+
+        while(thisIterator.hasNext()) {
+            // If there are no elements left in the 'other' iterator, spin out this iterator.
+            if(!otherIterator.hasNext()) {
+                GATKBAMFileSpan nextSpan = (GATKBAMFileSpan)thisIterator.next().getValue();
+                difference += nextSpan.size();
+                continue;
+            }
+
+            // Otherwise, compare the latest value.
+            int compareValue = thisIterator.peek().getKey().compareTo(otherIterator.peek().getKey());
+
+            if(compareValue < 0) {
+                // This before other.
+                difference += ((GATKBAMFileSpan)thisIterator.next().getValue()).size();
+            }
+            else if(compareValue > 0) {
+                // Other before this.
+                difference += ((GATKBAMFileSpan)otherIterator.next().getValue()).size();
+            }
+            else {
+                // equality; difference the values.
+                GATKBAMFileSpan thisRegion = (GATKBAMFileSpan)thisIterator.next().getValue();
+                GATKBAMFileSpan otherRegion = (GATKBAMFileSpan)otherIterator.next().getValue();
+                difference += Math.abs(thisRegion.minus(otherRegion).size());
+            }
+        }
+        return difference;
+    }
+
+    /**
+     * Combines two file pointers into one.
+     * @param parser The genomelocparser to use when manipulating intervals.
+     * @param other File pointer to combine into this one.
+     * @return A completely new file pointer that is the combination of the two.
+     */
+    public FilePointer combine(final GenomeLocParser parser, final FilePointer other) {
+        FilePointer combined = new FilePointer(intervalMergingRule);
+
+        List<GenomeLoc> intervals = new ArrayList<GenomeLoc>();
+        intervals.addAll(locations);
+        intervals.addAll(other.locations);
+        for(GenomeLoc interval: IntervalUtils.sortAndMergeIntervals(parser,intervals,intervalMergingRule))
+            combined.addLocation(interval);
+
+        PeekableIterator<Map.Entry<SAMReaderID,SAMFileSpan>> thisIterator = new PeekableIterator<Map.Entry<SAMReaderID,SAMFileSpan>>(this.fileSpans.entrySet().iterator());
+        PeekableIterator<Map.Entry<SAMReaderID,SAMFileSpan>> otherIterator = new PeekableIterator<Map.Entry<SAMReaderID,SAMFileSpan>>(other.fileSpans.entrySet().iterator());
+
+        while(thisIterator.hasNext() || otherIterator.hasNext()) {
+            int compareValue;
+            if(!otherIterator.hasNext()) {
+                compareValue = -1;
+            }
+            else if(!thisIterator.hasNext())
+                compareValue = 1;
+            else
+                compareValue = thisIterator.peek().getKey().compareTo(otherIterator.peek().getKey());
+
+            // This before other.
+            if(compareValue < 0)
+                mergeElementsInto(combined,thisIterator);
+            // Other before this.
+            else if(compareValue > 0)
+                mergeElementsInto(combined,otherIterator);
+            // equality; union the values.
+            else
+                mergeElementsInto(combined,thisIterator,otherIterator);
+        }
+        return combined;
+    }
+
+    /**
+     * Roll the next element in the iterator into the combined entry.
+     * @param combined Entry into which to roll the next element.
+     * @param iterators Sources of next elements.
+     */
+    private void mergeElementsInto(final FilePointer combined, Iterator<Map.Entry<SAMReaderID,SAMFileSpan>>... iterators) {
+        if(iterators.length == 0)
+            throw new ReviewedGATKException("Tried to add zero elements to an existing file pointer.");
+        Map.Entry<SAMReaderID,SAMFileSpan> initialElement = iterators[0].next();
+        GATKBAMFileSpan fileSpan = (GATKBAMFileSpan)initialElement.getValue();
+        for(int i = 1; i < iterators.length; i++)
+            fileSpan = fileSpan.union((GATKBAMFileSpan)iterators[i].next().getValue());
+        combined.addFileSpans(initialElement.getKey(),fileSpan);
+    }
+
+    /**
+     * Efficiently generate the union of the n FilePointers passed in. Much more efficient than
+     * combining two FilePointers at a time using the combine() method above.
+     *
+     * IMPORTANT: the FilePointers to be unioned must either all represent regions on the
+     * same contig, or all be unmapped, since we cannot create FilePointers with a mix of
+     * contigs or with mixed mapped/unmapped regions.
+     *
+     * @param filePointers the FilePointers to union
+     * @param parser our GenomeLocParser
+     * @return the union of the FilePointers passed in
+     */
+    public static FilePointer union( List<FilePointer> filePointers, GenomeLocParser parser ) {
+        if ( filePointers == null || filePointers.isEmpty() ) {
+            return new FilePointer(IntervalMergingRule.ALL);
+        }
+
+        Map<SAMReaderID, List<GATKChunk>> fileChunks = new HashMap<SAMReaderID, List<GATKChunk>>();
+        List<GenomeLoc> locations = new ArrayList<GenomeLoc>();
+        IntervalMergingRule mergeRule = filePointers.get(0).getIntervalMergingRule();
+
+        // First extract all intervals and file chunks from the FilePointers into unsorted, unmerged collections
+        for ( FilePointer filePointer : filePointers ) {
+            locations.addAll(filePointer.getLocations());
+            if (mergeRule != filePointer.getIntervalMergingRule())
+                throw new ReviewedGATKException("All FilePointers in FilePointer.union() must have use the same IntervalMergeRule");
+
+            for ( Map.Entry<SAMReaderID, SAMFileSpan> fileSpanEntry : filePointer.getFileSpans().entrySet() ) {
+                GATKBAMFileSpan fileSpan = (GATKBAMFileSpan)fileSpanEntry.getValue();
+
+                if ( fileChunks.containsKey(fileSpanEntry.getKey()) ) {
+                    fileChunks.get(fileSpanEntry.getKey()).addAll(fileSpan.getGATKChunks());
+                }
+                else {
+                    fileChunks.put(fileSpanEntry.getKey(), fileSpan.getGATKChunks());
+                }
+            }
+        }
+
+        // Now sort and merge the intervals
+        List<GenomeLoc> sortedMergedLocations = new ArrayList<GenomeLoc>();
+        sortedMergedLocations.addAll(IntervalUtils.sortAndMergeIntervals(parser, locations, mergeRule));
+
+        // For each BAM file, convert from an unsorted, unmerged list of chunks to a GATKBAMFileSpan containing
+        // the sorted, merged union of the chunks for that file
+        Map<SAMReaderID, SAMFileSpan> mergedFileSpans = new HashMap<SAMReaderID, SAMFileSpan>(fileChunks.size());
+        for ( Map.Entry<SAMReaderID, List<GATKChunk>> fileChunksEntry : fileChunks.entrySet() ) {
+            List<GATKChunk> unmergedChunks = fileChunksEntry.getValue();
+            mergedFileSpans.put(fileChunksEntry.getKey(),
+                                (new GATKBAMFileSpan(unmergedChunks.toArray(new GATKChunk[unmergedChunks.size()]))).union(new GATKBAMFileSpan()));
+        }
+
+        return new FilePointer(mergedFileSpans, mergeRule, sortedMergedLocations);
+    }
+
+    /**
+     * Returns true if any of the file spans in this FilePointer overlap their counterparts in
+     * the other FilePointer. "Overlap" is defined as having an overlapping extent (the region
+     * from the start of the first chunk to the end of the last chunk).
+     *
+     * @param other the FilePointer against which to check overlap with this FilePointer
+     * @return true if any file spans overlap their counterparts in other, otherwise false
+     */
+    public boolean hasFileSpansOverlappingWith( FilePointer other ) {
+        for ( Map.Entry<SAMReaderID, SAMFileSpan> thisFilePointerEntry : fileSpans.entrySet() ) {
+            GATKBAMFileSpan thisFileSpan = new GATKBAMFileSpan(thisFilePointerEntry.getValue());
+
+            SAMFileSpan otherEntry = other.fileSpans.get(thisFilePointerEntry.getKey());
+            if ( otherEntry == null ) {
+                continue;  // no counterpart for this file span in other
+            }
+            GATKBAMFileSpan otherFileSpan = new GATKBAMFileSpan(otherEntry);
+
+            if ( thisFileSpan.getExtent().overlaps(otherFileSpan.getExtent()) ) {
+                return true;
+            }
+        }
+
+        return false;
+    }
+
+    @Override
+    public String toString() {
+        StringBuilder builder = new StringBuilder();
+        builder.append("FilePointer:\n");
+        builder.append("\tlocations = {");
+        builder.append(Utils.join(";",locations));
+        builder.append("}\n\tregions = \n");
+        for(Map.Entry<SAMReaderID,SAMFileSpan> entry: fileSpans.entrySet()) {
+            builder.append(entry.getKey());
+            builder.append("= {");
+            builder.append(entry.getValue());
+            builder.append("}");
+        }
+        return builder.toString();
+    }
+}
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/datasources/reads/GATKBAMIndex.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/datasources/reads/GATKBAMIndex.java
new file mode 100644
index 0000000..17afd58
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/datasources/reads/GATKBAMIndex.java
@@ -0,0 +1,468 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.engine.datasources.reads;
+
+import htsjdk.samtools.Bin;
+import htsjdk.samtools.GATKBin;
+import htsjdk.samtools.GATKChunk;
+import htsjdk.samtools.LinearIndex;
+import htsjdk.samtools.seekablestream.SeekableBufferedStream;
+import htsjdk.samtools.seekablestream.SeekableFileStream;
+import org.broadinstitute.gatk.utils.exceptions.ReviewedGATKException;
+import org.broadinstitute.gatk.utils.exceptions.UserException;
+
+import java.io.File;
+import java.io.IOException;
+import java.nio.ByteBuffer;
+import java.nio.ByteOrder;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+/**
+ * A basic interface for querying BAM indices.
+ * Very much not thread-safe.
+ *
+ * @author mhanna
+ * @version 0.1
+ */
+public class GATKBAMIndex {
+    /**
+     * BAM index file magic number.
+     */
+    private static final byte[] BAM_INDEX_MAGIC = "BAI\1".getBytes();
+
+    /**
+     * Reports the total amount of genomic data that any bin can index.
+     */
+    protected static final int BIN_GENOMIC_SPAN = 512*1024*1024;
+
+    /**
+     * What is the starting bin for each level?
+     */
+    private static final int[] LEVEL_STARTS = {0,1,9,73,585,4681};
+
+    /**
+     * Reports the maximum number of bins that can appear in a BAM file.
+     */
+    public static final int MAX_BINS = 37450;   // =(8^6-1)/7+1
+
+    private final File mFile;
+
+    //TODO: figure out a good value for this buffer size
+    private final int BUFFERED_STREAM_BUFFER_SIZE = 8192;
+
+    /**
+     * Number of sequences stored in this index.
+     */
+    private final int sequenceCount;
+
+    /**
+     * A cache of the starting positions of the sequences.
+     */
+    private final long[] sequenceStartCache;
+
+    private SeekableFileStream fileStream;
+    private SeekableBufferedStream bufferedStream;
+    private long fileLength;
+
+    public GATKBAMIndex(final File file) {
+        mFile = file;
+        // Open the file stream.
+        openIndexFile();
+
+        // Verify the magic number.
+        seek(0);
+        final byte[] buffer = readBytes(4);
+        if (!Arrays.equals(buffer, BAM_INDEX_MAGIC)) {
+            throw new ReviewedGATKException("Invalid file header in BAM index " + mFile +
+                                       ": " + new String(buffer));
+        }
+
+        seek(4);
+
+        sequenceCount = readInteger();
+
+        // Create a cache of the starting position of each sequence.  Initialize it to -1.
+        sequenceStartCache = new long[sequenceCount];
+        for(int i = 1; i < sequenceCount; i++)
+            sequenceStartCache[i] = -1;
+
+        // Seed the first element in the array with the current position.
+        if(sequenceCount > 0)
+            sequenceStartCache[0] = position();
+
+        closeIndexFile();
+    }
+
+    public GATKBAMIndexData readReferenceSequence(final int referenceSequence) {
+        openIndexFile();
+
+        if (referenceSequence >= sequenceCount)
+            throw new ReviewedGATKException("Invalid sequence number " + referenceSequence + " in index file " + mFile);
+
+        skipToSequence(referenceSequence);
+
+        int binCount = readInteger();
+        List<GATKBin> bins = new ArrayList<GATKBin>();
+        for (int binNumber = 0; binNumber < binCount; binNumber++) {
+            final int indexBin = readInteger();
+            final int nChunks = readInteger();
+
+            List<GATKChunk> chunks = new ArrayList<GATKChunk>(nChunks);
+            long[] rawChunkData = readLongs(nChunks*2);
+            for (int ci = 0; ci < nChunks; ci++) {
+                final long chunkBegin = rawChunkData[ci*2];
+                final long chunkEnd = rawChunkData[ci*2+1];
+                chunks.add(new GATKChunk(chunkBegin, chunkEnd));
+            }
+            GATKBin bin = new GATKBin(referenceSequence, indexBin);
+            bin.setChunkList(chunks.toArray(new GATKChunk[chunks.size()]));
+            while(indexBin >= bins.size())
+                bins.add(null);
+            bins.set(indexBin,bin);
+        }
+
+        final int nLinearBins = readInteger();
+        long[] linearIndexEntries = readLongs(nLinearBins);
+
+        LinearIndex linearIndex = new LinearIndex(referenceSequence,0,linearIndexEntries);
+
+        closeIndexFile();
+
+        return new GATKBAMIndexData(this,referenceSequence,bins,linearIndex);
+    }
+
+    /**
+     * Get the number of levels employed by this index.
+     * @return Number of levels in this index.
+     */
+    public static int getNumIndexLevels() {
+        return LEVEL_STARTS.length;
+    }
+
+    /**
+     * Gets the first bin in the given level.
+     * @param levelNumber Level number.  0-based.
+     * @return The first bin in this level.
+     */
+    public static int getFirstBinInLevel(final int levelNumber) {
+        return LEVEL_STARTS[levelNumber];
+    }
+
+    /**
+     * Gets the number of bins in the given level.
+     * @param levelNumber Level number.  0-based.
+     * @return The size (number of possible bins) of the given level.
+     */
+    public int getLevelSize(final int levelNumber) {
+        if(levelNumber == getNumIndexLevels()-1)
+            return MAX_BINS-LEVEL_STARTS[levelNumber]-1;
+        else
+            return LEVEL_STARTS[levelNumber+1]-LEVEL_STARTS[levelNumber];
+    }
+
+    /**
+     * Gets the level associated with the given bin number.
+     * @param bin The bin  for which to determine the level.
+     * @return the level associated with the given bin number.
+     */
+    public int getLevelForBin(final Bin bin) {
+        GATKBin gatkBin = new GATKBin(bin);
+        if(gatkBin.getBinNumber() >= MAX_BINS)
+            throw new ReviewedGATKException("Tried to get level for invalid bin in index file " + mFile);
+        for(int i = getNumIndexLevels()-1; i >= 0; i--) {
+            if(gatkBin.getBinNumber() >= LEVEL_STARTS[i])
+                return i;
+        }
+        throw new ReviewedGATKException("Unable to find correct bin for bin " + bin + " in index file " + mFile);
+    }
+
+    /**
+     * Gets the first locus that this bin can index into.
+     * @param bin The bin to test.
+     * @return The last position that the given bin can represent.
+     */
+    public int getFirstLocusInBin(final Bin bin) {
+        final int level = getLevelForBin(bin);
+        final int levelStart = LEVEL_STARTS[level];
+        final int levelSize = ((level==getNumIndexLevels()-1) ? MAX_BINS-1 : LEVEL_STARTS[level+1]) - levelStart;
+        return (new GATKBin(bin).getBinNumber() - levelStart)*(BIN_GENOMIC_SPAN /levelSize)+1;
+    }
+
+    /**
+     * Gets the last locus that this bin can index into.
+     * @param bin The bin to test.
+     * @return The last position that the given bin can represent.
+     */
+    public int getLastLocusInBin(final Bin bin) {
+        final int level = getLevelForBin(bin);
+        final int levelStart = LEVEL_STARTS[level];
+        final int levelSize = ((level==getNumIndexLevels()-1) ? MAX_BINS-1 : LEVEL_STARTS[level+1]) - levelStart;
+        return (new GATKBin(bin).getBinNumber()-levelStart+1)*(BIN_GENOMIC_SPAN /levelSize);
+    }
+
+    /**
+     * Use to get close to the unmapped reads at the end of a BAM file.
+     * @return The file offset of the first record in the last linear bin, or -1
+     * if there are no elements in linear bins (i.e. no mapped reads).
+     */
+    public long getStartOfLastLinearBin() {
+        openIndexFile();
+
+        seek(4);
+
+        final int sequenceCount = readInteger();
+        // Because no reads may align to the last sequence in the sequence dictionary,
+        // grab the last element of the linear index for each sequence, and return
+        // the last one from the last sequence that has one.
+        long lastLinearIndexPointer = -1;
+        for (int i = 0; i < sequenceCount; i++) {
+            // System.out.println("# Sequence TID: " + i);
+            final int nBins = readInteger();
+            // System.out.println("# nBins: " + nBins);
+            for (int j1 = 0; j1 < nBins; j1++) {
+                // Skip bin #
+                skipBytes(4);
+                final int nChunks = readInteger();
+                // Skip chunks
+                skipBytes(16 * nChunks);
+            }
+            final int nLinearBins = readInteger();
+            if (nLinearBins > 0) {
+                // Skip to last element of list of linear bins
+                skipBytes(8 * (nLinearBins - 1));
+                lastLinearIndexPointer = readLongs(1)[0];
+            }
+        }
+
+        closeIndexFile();
+
+        return lastLinearIndexPointer;
+    }
+
+    /**
+     * Gets the possible number of bins for a given reference sequence.
+     * @return How many bins could possibly be used according to this indexing scheme to index a single contig.
+     */
+    protected int getMaxAddressibleGenomicLocation() {
+        return BIN_GENOMIC_SPAN;
+    }
+
+    protected void skipToSequence(final int referenceSequence) {
+        // Find the offset in the file of the last sequence whose position has been determined.  Start here
+        // when searching the sequence for the next value to read.  (Note that sequenceStartCache[0] will always
+        // be present, so no extra stopping condition is necessary.
+        int sequenceIndex = referenceSequence;
+        while(sequenceStartCache[sequenceIndex] == -1)
+            sequenceIndex--;
+
+        // Advance to the most recently found position.
+        seek(sequenceStartCache[sequenceIndex]);
+
+        for (int i = sequenceIndex; i < referenceSequence; i++) {
+            sequenceStartCache[i] = position();
+            // System.out.println("# Sequence TID: " + i);
+            final int nBins = readInteger();
+            // System.out.println("# nBins: " + nBins);
+            for (int j = 0; j < nBins; j++) {
+                final int bin = readInteger();
+                final int nChunks = readInteger();
+                // System.out.println("# bin[" + j + "] = " + bin + ", nChunks = " + nChunks);
+                skipBytes(16 * nChunks);
+            }
+            final int nLinearBins = readInteger();
+            // System.out.println("# nLinearBins: " + nLinearBins);
+            skipBytes(8 * nLinearBins);
+
+        }
+
+        sequenceStartCache[referenceSequence] = position();
+    }
+
+
+
+    private void openIndexFile() {
+        try {
+            fileStream = new SeekableFileStream(mFile);
+            bufferedStream = new SeekableBufferedStream(fileStream,BUFFERED_STREAM_BUFFER_SIZE);
+            fileLength=bufferedStream.length();
+        }
+        catch (IOException exc) {
+            throw new ReviewedGATKException("Unable to open index file (" + exc.getMessage() +")" + mFile, exc);
+        }
+    }
+
+    private void closeIndexFile() {
+        try {
+            bufferedStream.close();
+            fileStream.close();
+            fileLength = -1;
+        }
+        catch (IOException exc) {
+            throw new ReviewedGATKException("Unable to close index file " + mFile, exc);
+        }
+    }
+
+    private static final int INT_SIZE_IN_BYTES = Integer.SIZE / 8;
+    private static final int LONG_SIZE_IN_BYTES = Long.SIZE / 8;
+
+    private byte[] readBytes(int count) {
+        ByteBuffer buffer = getBuffer(count);
+        read(buffer);
+        buffer.flip();
+        byte[] contents = new byte[count];
+        buffer.get(contents);
+        return contents;
+    }
+
+    private int readInteger() {
+        ByteBuffer buffer = getBuffer(INT_SIZE_IN_BYTES);
+        read(buffer);
+        buffer.flip();
+        return buffer.getInt();
+    }
+
+    /**
+     * Reads an array of <count> longs from the file channel, returning the results as an array.
+     * @param count Number of longs to read.
+     * @return An array of longs.  Size of array should match count.
+     */
+    private long[] readLongs(final int count) {
+        ByteBuffer buffer = getBuffer(count*LONG_SIZE_IN_BYTES);
+        read(buffer);
+        buffer.flip();
+        long[] result = new long[count];
+        for(int i = 0; i < count; i++)
+            result[i] = buffer.getLong();
+        return result;
+    }
+
+    private void read(final ByteBuffer buffer) {
+        final int bytesRequested = buffer.limit();
+
+        try {
+
+           //BufferedInputStream cannot read directly into a byte buffer, so we read into an array
+            //and put the result into the bytebuffer after the if statement.
+
+            // We have a rigid expectation here to read in exactly the number of bytes we've limited
+            // our buffer to -- if there isn't enough data in the file, the index
+            // must be truncated or otherwise corrupt:
+            if(bytesRequested > fileLength - bufferedStream.position()){
+                throw new UserException.MalformedFile(mFile, String.format("Premature end-of-file while reading BAM index file %s. " +
+                        "It's likely that this file is truncated or corrupt -- " +
+                        "Please try re-indexing the corresponding BAM file.",
+                        mFile));
+            }
+
+            int totalBytesRead = 0;
+            // This while loop must terminate since we demand that we read at least one byte from the file at each iteration
+           while (totalBytesRead < bytesRequested) {
+                //  bufferedStream.read may return less than the requested amount of byte despite
+                // not reaching the end of the file, hence the loop.
+                int bytesRead = bufferedStream.read(byteArray, totalBytesRead, bytesRequested-totalBytesRead);
+
+                // We have a rigid expectation here to read in exactly the number of bytes we've limited
+                // our buffer to -- if we encounter EOF (-1), the index
+                // must be truncated or otherwise corrupt:
+                if (bytesRead <= 0) {
+                throw new UserException.MalformedFile(mFile, String.format("Premature end-of-file while reading BAM index file %s. " +
+                                                                           "It's likely that this file is truncated or corrupt -- " +
+                                                                           "Please try re-indexing the corresponding BAM file.",
+                                                                           mFile));
+                }
+                totalBytesRead += bytesRead;
+            }
+            if(totalBytesRead != bytesRequested)
+                throw new RuntimeException("Read amount different from requested amount. This should not happen.");
+
+            buffer.put(byteArray, 0, bytesRequested);
+        }
+        catch(IOException ex) {
+            throw new ReviewedGATKException("Index: unable to read bytes from index file " + mFile);
+        }
+    }
+
+
+    /**
+     * A reusable buffer for use by this index generator.
+     * TODO: Should this be a SoftReference?
+     */
+    private ByteBuffer buffer = null;
+
+    //BufferedStream don't read into ByteBuffers, so we need this temporary array
+    private byte[] byteArray=null;
+    private ByteBuffer getBuffer(final int size) {
+        if(buffer == null || buffer.capacity() < size) {
+            // Allocate a new byte buffer.  For now, make it indirect to make sure it winds up on the heap for easier debugging.
+            buffer = ByteBuffer.allocate(size);
+            byteArray = new byte[size];
+            buffer.order(ByteOrder.LITTLE_ENDIAN);
+        }
+        buffer.clear();
+        buffer.limit(size);
+        return buffer;
+    }
+
+    private void skipBytes(final int count) {
+        try {
+
+            //try to skip forward the requested amount.
+            long skipped =  bufferedStream.skip(count);
+
+            if( skipped != count ) { //if not managed to skip the requested amount
+		throw new ReviewedGATKException("Index: unable to reposition file channel of index file " + mFile);
+            }
+        }
+        catch(IOException ex) {
+            throw new ReviewedGATKException("Index: unable to reposition file channel of index file " + mFile);
+        }
+    }
+
+    private void seek(final long position) {
+        try {
+            //to seek a new position, move the fileChannel, and reposition the bufferedStream
+            bufferedStream.seek(position);
+        }
+        catch(IOException ex) {
+            throw new ReviewedGATKException("Index: unable to reposition of file channel of index file " + mFile);
+        }
+    }
+
+    /**
+     * Retrieve the position from the current file channel.
+     * @return position of the current file channel.
+     */
+    private long position() {
+        try {
+            return bufferedStream.position();
+        }
+        catch (IOException exc) {
+            throw new ReviewedGATKException("Unable to read position from index file " + mFile, exc);
+        }
+    }
+}
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/datasources/reads/GATKBAMIndexData.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/datasources/reads/GATKBAMIndexData.java
new file mode 100644
index 0000000..f1d6203
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/datasources/reads/GATKBAMIndexData.java
@@ -0,0 +1,121 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.engine.datasources.reads;
+
+import htsjdk.samtools.*;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+/**
+ * Stores and processes a single reference worth of GATK data.
+ */
+public class GATKBAMIndexData {
+    private final GATKBAMIndex index;
+    private final int referenceSequence;
+    private final List<GATKBin> bins;
+    private final LinearIndex linearIndex;
+
+    public GATKBAMIndexData(final GATKBAMIndex index, final int referenceSequence, final List<GATKBin> bins, final LinearIndex linearIndex) {
+        this.index = index;
+        this.referenceSequence = referenceSequence;
+        this.bins = bins;
+        this.linearIndex = linearIndex;
+    }
+
+    public int getReferenceSequence() {
+        return referenceSequence;
+    }
+
+    /**
+     * Perform an overlapping query of all bins bounding the given location.
+     * @param bin The bin over which to perform an overlapping query.
+     * @return The file pointers
+     */
+    public GATKBAMFileSpan getSpanOverlapping(final Bin bin) {
+        if(bin == null)
+            return null;
+
+        GATKBin gatkBin = new GATKBin(bin);
+
+        final int binLevel = index.getLevelForBin(bin);
+        final int firstLocusInBin = index.getFirstLocusInBin(bin);
+
+        // Add the specified bin to the tree if it exists.
+        List<GATKBin> binTree = new ArrayList<GATKBin>();
+        if(gatkBin.getBinNumber() < bins.size() && bins.get(gatkBin.getBinNumber()) != null)
+            binTree.add(bins.get(gatkBin.getBinNumber()));
+
+        int currentBinLevel = binLevel;
+        while(--currentBinLevel >= 0) {
+            final int binStart = index.getFirstBinInLevel(currentBinLevel);
+            final int binWidth = index.getMaxAddressibleGenomicLocation()/index.getLevelSize(currentBinLevel);
+            final int binNumber = firstLocusInBin/binWidth + binStart;
+            if(binNumber < bins.size() && bins.get(binNumber) != null)
+                binTree.add(bins.get(binNumber));
+        }
+
+        List<GATKChunk> chunkList = new ArrayList<GATKChunk>();
+        for(GATKBin coveringBin: binTree) {
+            for(GATKChunk chunk: coveringBin.getChunkList())
+                chunkList.add(chunk.clone());
+        }
+
+        final int start = index.getFirstLocusInBin(bin);
+        chunkList = optimizeChunkList(chunkList,linearIndex.getMinimumOffset(start));
+        return new GATKBAMFileSpan(chunkList.toArray(new GATKChunk[chunkList.size()]));
+    }
+
+    private List<GATKChunk> optimizeChunkList(final List<GATKChunk> chunks, final long minimumOffset) {
+        GATKChunk lastChunk = null;
+        Collections.sort(chunks);
+        final List<GATKChunk> result = new ArrayList<GATKChunk>();
+        for (final GATKChunk chunk : chunks) {
+            if (chunk.getChunkEnd() <= minimumOffset) {
+                continue;               // linear index optimization
+            }
+            if (result.isEmpty()) {
+                result.add(chunk);
+                lastChunk = chunk;
+                continue;
+            }
+            // Coalesce chunks that are in adjacent file blocks.
+            // This is a performance optimization.
+            if (!lastChunk.overlaps(chunk) && !lastChunk.isAdjacentTo(chunk)) {
+                result.add(chunk);
+                lastChunk = chunk;
+            } else {
+                if (chunk.getChunkEnd() > lastChunk.getChunkEnd()) {
+                    lastChunk.setChunkEnd(chunk.getChunkEnd());
+                }
+            }
+        }
+        return result;
+    }
+
+
+}
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/datasources/reads/IntervalOverlapFilteringIterator.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/datasources/reads/IntervalOverlapFilteringIterator.java
new file mode 100644
index 0000000..c272e0a
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/datasources/reads/IntervalOverlapFilteringIterator.java
@@ -0,0 +1,205 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.engine.datasources.reads;
+
+import htsjdk.samtools.SAMRecord;
+import htsjdk.samtools.util.CloseableIterator;
+import org.broadinstitute.gatk.utils.GenomeLoc;
+import org.broadinstitute.gatk.utils.exceptions.ReviewedGATKException;
+import org.broadinstitute.gatk.utils.sam.AlignmentUtils;
+
+import java.util.List;
+import java.util.NoSuchElementException;
+
+/**
+ * High efficiency filtering iterator designed to filter out reads only included
+ * in the query results due to the granularity of the BAM index.
+ *
+ * Built into the BAM index is a notion of 16kbase granularity -- an index query for
+ * two regions contained within a 16kbase chunk (say, chr1:5-10 and chr1:11-20) will
+ * return exactly the same regions within the BAM file.  This iterator is optimized
+ * to subtract out reads which do not at all overlap the interval list passed to the
+ * constructor.
+ *
+ * Example:
+ * interval list: chr20:6-10
+ * Reads that would pass through the filter: chr20:6-10, chr20:1-15, chr20:1-7, chr20:8-15.
+ * Reads that would be discarded by the filter: chr20:1-5, chr20:11-15.
+ */
+class IntervalOverlapFilteringIterator implements CloseableIterator<SAMRecord> {
+    /**
+     * The wrapped iterator.
+     */
+    private CloseableIterator<SAMRecord> iterator;
+
+    /**
+     * The next read, queued up and ready to go.
+     */
+    private SAMRecord nextRead;
+
+    /**
+     * Rather than using the straight genomic bounds, use filter out only mapped reads.
+     */
+    private boolean keepOnlyUnmappedReads;
+
+    /**
+     * Custom representation of interval bounds.
+     * Makes it simpler to track current position.
+     */
+    private int[] intervalContigIndices;
+    private int[] intervalStarts;
+    private int[] intervalEnds;
+
+    /**
+     * Position within the interval list.
+     */
+    private int currentBound = 0;
+
+    public IntervalOverlapFilteringIterator(CloseableIterator<SAMRecord> iterator, List<GenomeLoc> intervals) {
+        this.iterator = iterator;
+
+        // Look at the interval list to detect whether we should worry about unmapped reads.
+        // If we find a mix of mapped/unmapped intervals, throw an exception.
+        boolean foundMappedIntervals = false;
+        for(GenomeLoc location: intervals) {
+            if(! GenomeLoc.isUnmapped(location))
+                foundMappedIntervals = true;
+            keepOnlyUnmappedReads |= GenomeLoc.isUnmapped(location);
+        }
+
+
+        if(foundMappedIntervals) {
+            if(keepOnlyUnmappedReads)
+                throw new ReviewedGATKException("Tried to apply IntervalOverlapFilteringIterator to a mixed of mapped and unmapped intervals.  Please apply this filter to only mapped or only unmapped reads");
+            this.intervalContigIndices = new int[intervals.size()];
+            this.intervalStarts = new int[intervals.size()];
+            this.intervalEnds = new int[intervals.size()];
+            int i = 0;
+            for(GenomeLoc interval: intervals) {
+                intervalContigIndices[i] = interval.getContigIndex();
+                intervalStarts[i] = interval.getStart();
+                intervalEnds[i] = interval.getStop();
+                i++;
+            }
+        }
+
+        advance();
+    }
+
+    public boolean hasNext() {
+        return nextRead != null;
+    }
+
+    public SAMRecord next() {
+        if(nextRead == null)
+            throw new NoSuchElementException("No more reads left in this iterator.");
+        SAMRecord currentRead = nextRead;
+        advance();
+        return currentRead;
+    }
+
+    public void remove() {
+        throw new UnsupportedOperationException("Cannot remove from an IntervalOverlapFilteringIterator");
+    }
+
+
+    public void close() {
+        iterator.close();
+    }
+
+    private void advance() {
+        nextRead = null;
+
+        if(!iterator.hasNext())
+            return;
+
+        SAMRecord candidateRead = iterator.next();
+        while(nextRead == null && (keepOnlyUnmappedReads || currentBound < intervalStarts.length)) {
+            if(!keepOnlyUnmappedReads) {
+                // Mapped read filter; check against GenomeLoc-derived bounds.
+                if(readEndsOnOrAfterStartingBound(candidateRead)) {
+                    // This read ends after the current interval begins.
+                    // Promising, but this read must be checked against the ending bound.
+                    if(readStartsOnOrBeforeEndingBound(candidateRead)) {
+                        // Yes, this read is within both bounds.  This must be our next read.
+                        nextRead = candidateRead;
+                        break;
+                    }
+                    else {
+                        // Oops, we're past the end bound.  Increment the current bound and try again.
+                        currentBound++;
+                        continue;
+                    }
+                }
+            }
+            else {
+                // Found a -L UNMAPPED read. NOTE: this is different than just being flagged as unmapped! We're done.
+                if(AlignmentUtils.isReadGenomeLocUnmapped(candidateRead)) {
+                    nextRead = candidateRead;
+                    break;
+                }
+            }
+
+            // No more reads available.  Stop the search.
+            if(!iterator.hasNext())
+                break;
+
+            // No reasonable read found; advance the iterator.
+            candidateRead = iterator.next();
+        }
+    }
+
+    /**
+     * Check whether the read lies after the start of the current bound.  If the read is unmapped but placed, its
+     * end will be distorted, so rely only on the alignment start.
+     * @param read The read to position-check.
+     * @return True if the read starts after the current bounds.  False otherwise.
+     */
+    private boolean readEndsOnOrAfterStartingBound(final SAMRecord read) {
+        return
+                // Read ends on a later contig, or...
+                read.getReferenceIndex() > intervalContigIndices[currentBound] ||
+                        // Read ends of this contig...
+                        (read.getReferenceIndex() == intervalContigIndices[currentBound] &&
+                                // either after this location, or...
+                                (read.getAlignmentEnd() >= intervalStarts[currentBound] ||
+                                        // read is unmapped but positioned and alignment start is on or after this start point.
+                                        (read.getReadUnmappedFlag() && read.getAlignmentStart() >= intervalStarts[currentBound])));
+    }
+
+    /**
+     * Check whether the read lies before the end of the current bound.
+     * @param read The read to position-check.
+     * @return True if the read starts after the current bounds.  False otherwise.
+     */
+    private boolean readStartsOnOrBeforeEndingBound(final SAMRecord read) {
+        return
+                // Read starts on a prior contig, or...
+                read.getReferenceIndex() < intervalContigIndices[currentBound] ||
+                        // Read starts on this contig and the alignment start is registered before this end point.
+                        (read.getReferenceIndex() == intervalContigIndices[currentBound] && read.getAlignmentStart() <= intervalEnds[currentBound]);
+    }
+}
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/datasources/reads/IntervalSharder.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/datasources/reads/IntervalSharder.java
new file mode 100644
index 0000000..e355c7e
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/datasources/reads/IntervalSharder.java
@@ -0,0 +1,93 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.engine.datasources.reads;
+
+import htsjdk.samtools.util.PeekableIterator;
+import org.broadinstitute.gatk.utils.GenomeLocParser;
+import org.broadinstitute.gatk.utils.GenomeLocSortedSet;
+import org.broadinstitute.gatk.utils.interval.IntervalMergingRule;
+
+import java.util.Iterator;
+
+/**
+ * Handles the process of aggregating BAM intervals into individual shards.
+ * TODO: The task performed by IntervalSharder is now better performed by LocusShardBalancer.  Merge BAMScheduler and IntervalSharder.
+ */
+public class IntervalSharder implements Iterator<FilePointer> {
+    /**
+     * The iterator actually laying out the data for BAM scheduling.
+     */
+    private final PeekableIterator<FilePointer> wrappedIterator;
+
+    /**
+     * The parser, for interval manipulation.
+     */
+    private final GenomeLocParser parser;
+
+    public static IntervalSharder shardOverAllReads(final SAMDataSource dataSource, final GenomeLocParser parser) {
+        return new IntervalSharder(BAMScheduler.createOverAllReads(dataSource,parser),parser);
+    }
+
+    public static IntervalSharder shardOverMappedReads(final SAMDataSource dataSource, final GenomeLocParser parser) {
+        return new IntervalSharder(BAMScheduler.createOverMappedReads(dataSource),parser);
+    }
+
+    public static IntervalSharder shardOverIntervals(final SAMDataSource dataSource, final GenomeLocSortedSet loci, final IntervalMergingRule intervalMergeRule) {
+        return new IntervalSharder(BAMScheduler.createOverIntervals(dataSource,intervalMergeRule,loci),loci.getGenomeLocParser());
+    }
+
+    private IntervalSharder(final BAMScheduler scheduler, final GenomeLocParser parser) {
+        wrappedIterator = new PeekableIterator<FilePointer>(scheduler);
+        this.parser = parser;
+    }
+    public void close() {
+      wrappedIterator.close();
+    }
+
+    public boolean hasNext() {
+        return wrappedIterator.hasNext();
+    }
+
+    /**
+     * Accumulate shards where there's no additional cost to processing the next shard in the sequence.
+     * @return The next file pointer to process.
+     */
+    public FilePointer next() {
+        FilePointer current = wrappedIterator.next();
+
+        while ( wrappedIterator.hasNext() &&
+                current.isRegionUnmapped == wrappedIterator.peek().isRegionUnmapped &&
+                (current.getContigIndex() == wrappedIterator.peek().getContigIndex() || current.isRegionUnmapped) &&
+                current.minus(wrappedIterator.peek()) == 0 ) {
+
+            current = current.combine(parser,wrappedIterator.next());
+        }
+
+        return current;
+    }
+
+    public void remove() { throw new UnsupportedOperationException("Unable to remove from an interval sharder."); }
+}
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/datasources/reads/LocusShard.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/datasources/reads/LocusShard.java
new file mode 100644
index 0000000..28d4faf
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/datasources/reads/LocusShard.java
@@ -0,0 +1,60 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.engine.datasources.reads;
+
+import htsjdk.samtools.SAMFileSpan;
+import org.broadinstitute.gatk.utils.GenomeLoc;
+import org.broadinstitute.gatk.utils.GenomeLocParser;
+import org.broadinstitute.gatk.utils.Utils;
+
+import java.util.List;
+import java.util.Map;
+
+/**
+ * Handles locus shards of BAM information.
+ * @author aaron
+ * @version 1.0
+ * @date Apr 7, 2009
+ */
+public class LocusShard extends Shard {
+    /**
+     * Create a new locus shard, divided by index.
+     * @param intervals List of intervals to process.
+     * @param fileSpans File spans associated with that interval.
+     */
+    public LocusShard(GenomeLocParser parser, SAMDataSource dataSource, List<GenomeLoc> intervals, Map<SAMReaderID,SAMFileSpan> fileSpans) {
+        super(parser, ShardType.LOCUS, intervals, dataSource, fileSpans, false);
+    }
+
+    /**
+     * String representation of this shard.
+     * @return A string representation of the boundaries of this shard.
+     */
+    @Override
+    public String toString() {
+        return Utils.join(";",getGenomeLocs());
+    }
+}
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/datasources/reads/LocusShardBalancer.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/datasources/reads/LocusShardBalancer.java
new file mode 100644
index 0000000..6fb4d48
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/datasources/reads/LocusShardBalancer.java
@@ -0,0 +1,58 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.engine.datasources.reads;
+
+import java.util.Iterator;
+
+/**
+ * Batch granular file pointers into potentially larger shards.
+ */
+public class LocusShardBalancer extends ShardBalancer {
+    /**
+     * Convert iterators of file pointers into balanced iterators of shards.
+     * @return An iterator over balanced shards.
+     */
+    public Iterator<Shard> iterator() {
+        return new Iterator<Shard>() {
+            public boolean hasNext() {
+                return filePointers.hasNext();
+            }
+
+            public Shard next() {
+                FilePointer current = filePointers.next();
+
+                // FilePointers have already been combined as necessary at the IntervalSharder level. No
+                // need to do so again here.
+
+                return new LocusShard(parser,readsDataSource,current.getLocations(),current.fileSpans);
+            }
+
+            public void remove() {
+                throw new UnsupportedOperationException("Unable to remove from shard balancing iterator");
+            }
+        };
+    }
+}
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/datasources/reads/ReadShard.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/datasources/reads/ReadShard.java
new file mode 100644
index 0000000..d4321da
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/datasources/reads/ReadShard.java
@@ -0,0 +1,271 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.engine.datasources.reads;
+
+import htsjdk.samtools.util.PeekableIterator;
+import htsjdk.samtools.*;
+import htsjdk.samtools.util.CloseableIterator;
+import org.broadinstitute.gatk.engine.iterators.GATKSAMIterator;
+import org.broadinstitute.gatk.engine.iterators.GATKSAMIteratorAdapter;
+import org.broadinstitute.gatk.utils.GenomeLoc;
+import org.broadinstitute.gatk.utils.GenomeLocParser;
+import org.broadinstitute.gatk.utils.exceptions.ReviewedGATKException;
+
+import java.util.*;
+
+/**
+ *
+ * User: aaron
+ * Date: Apr 10, 2009
+ * Time: 5:03:13 PM
+ *
+ * The Broad Institute
+ * SOFTWARE COPYRIGHT NOTICE AGREEMENT 
+ * This software and its documentation are copyright 2009 by the
+ * Broad Institute/Massachusetts Institute of Technology. All rights are reserved.
+ *
+ * This software is supplied without any warranty or guaranteed support whatsoever. Neither
+ * the Broad Institute nor MIT can be responsible for its use, misuse, or functionality.
+ *
+ */
+
+/**
+ * Expresses a shard of read data in block format.
+ *
+ * @author mhanna
+ * @version 0.1
+ */
+public class ReadShard extends Shard {
+
+    /**
+     * Default read shard buffer size
+     */
+    public static final int DEFAULT_MAX_READS = 10000;
+
+    /**
+     * What is the maximum number of reads per BAM file which should go into a read shard.
+     *
+     * TODO: this non-final static variable should either be made final or turned into an
+     * TODO: instance variable somewhere -- as both static and mutable it wreaks havoc
+     * TODO: with tests that use multiple instances of SAMDataSource (since SAMDataSource
+     * TODO: changes this value)
+     */
+    public static int MAX_READS = DEFAULT_MAX_READS;
+
+    /**
+     * The reads making up this shard.
+     */
+    private final Collection<SAMRecord> reads = new ArrayList<SAMRecord>(MAX_READS);
+
+    public ReadShard(GenomeLocParser parser, SAMDataSource readsDataSource, Map<SAMReaderID,SAMFileSpan> fileSpans, List<GenomeLoc> loci, boolean isUnmapped) {
+        super(parser, ShardType.READ, loci, readsDataSource, fileSpans, isUnmapped);
+    }
+
+    /**
+     * Sets the maximum number of reads buffered in a read shard.  Implemented as a weirdly static interface
+     * until we know what effect tuning this parameter has.
+     *
+     * TODO: this mutable static interface is awful and breaks tests -- need to refactor
+     *
+     * @param bufferSize New maximum number
+     */
+    static void setReadBufferSize(final int bufferSize) {
+        MAX_READS = bufferSize;
+    }
+
+    /**
+     * What read buffer size are we using?
+     *
+     * @return
+     */
+    public static int getReadBufferSize() {
+        return MAX_READS;
+    }
+
+    /**
+     * Returns true if this shard is meant to buffer reads, rather
+     * than just holding pointers to their locations.
+     * @return True if this shard can buffer reads.  False otherwise.
+     */
+    public boolean buffersReads() {
+        return true;
+    }
+
+    /**
+     * Returns true if the read buffer is currently full.
+     * @return True if this shard's buffer is full (and the shard can buffer reads).
+     */
+    public boolean isBufferEmpty() {
+        return reads.size() == 0;
+    }
+
+    /**
+     * Returns true if the read buffer is currently full.
+     * @return True if this shard's buffer is full (and the shard can buffer reads).
+     */
+    public boolean isBufferFull() {
+        return reads.size() > ReadShard.MAX_READS;
+    }
+
+    /**
+     * Adds a read to the read buffer.
+     * @param read Add a read to the internal shard buffer.
+     */
+    public void addRead(SAMRecord read) {
+        // DO NOT validate that the buffer is full.  Paired read sharding will occasionally have to stuff another
+        // read or two into the buffer.
+        reads.add(read);
+    }
+
+    /**
+     * Fills this shard's buffer with reads from the iterator passed in
+     *
+     * @param readIter Iterator from which to draw the reads to fill the shard
+     */
+    @Override
+    public void fill( PeekableIterator<SAMRecord> readIter ) {
+        if( ! buffersReads() )
+            throw new ReviewedGATKException("Attempting to fill a non-buffering shard.");
+
+        SAMFileHeader.SortOrder sortOrder = getReadProperties().getSortOrder();
+        SAMRecord read = null;
+
+        while( ! isBufferFull() && readIter.hasNext() ) {
+            final SAMRecord nextRead = readIter.peek();
+            if ( read == null || (nextRead.getReferenceIndex().equals(read.getReferenceIndex())) ) {
+                // only add reads to the shard if they are on the same contig
+                read = readIter.next();
+                addRead(read);
+            } else {
+                break;
+            }
+        }
+
+        // If the reads are sorted in coordinate order, ensure that all reads
+        // having the same alignment start become part of the same shard, to allow
+        // downsampling to work better across shard boundaries. Note that because our
+        // read stream has already been fed through the positional downsampler, which
+        // ensures that at each alignment start position there are no more than dcov
+        // reads, we're in no danger of accidentally creating a disproportionately huge
+        // shard
+        if ( sortOrder == SAMFileHeader.SortOrder.coordinate ) {
+            while ( readIter.hasNext() ) {
+                SAMRecord additionalRead = readIter.peek();
+
+                // Stop filling the shard as soon as we encounter a read having a different
+                // alignment start or contig from the last read added in the earlier loop
+                // above, or an unmapped read
+                if ( read == null ||
+                     additionalRead.getReadUnmappedFlag() ||
+                     ! additionalRead.getReferenceIndex().equals(read.getReferenceIndex()) ||
+                     additionalRead.getAlignmentStart() != read.getAlignmentStart() ) {
+                    break;
+                }
+
+                addRead(readIter.next());
+            }
+        }
+
+        // If the reads are sorted in queryname order, ensure that all reads
+        // having the same queryname become part of the same shard.
+        if( sortOrder == SAMFileHeader.SortOrder.queryname ) {
+            while( readIter.hasNext() ) {
+                SAMRecord nextRead = readIter.peek();
+                if( read == null || ! read.getReadName().equals(nextRead.getReadName()) )
+                    break;
+                addRead(readIter.next());
+            }
+        }
+    }
+
+    /**
+     * Creates an iterator over reads stored in this shard's read cache.
+     * @return
+     */
+    public GATKSAMIterator iterator() {
+        return GATKSAMIteratorAdapter.adapt(reads.iterator());
+    }
+
+    /**
+     * String representation of this shard.
+     * @return A string representation of the boundaries of this shard.
+     */
+    @Override
+    public String toString() {
+        StringBuilder sb = new StringBuilder();
+        for(Map.Entry<SAMReaderID,SAMFileSpan> entry: getFileSpans().entrySet()) {
+            sb.append(entry.getKey());
+            sb.append(": ");
+            sb.append(entry.getValue());
+            sb.append(' ');
+        }
+        return sb.toString();
+    }
+
+    /**
+     * Get the full span from the start of the left most read to the end of the right most one
+     *
+     * Note this may be different than the getLocation() of the shard, as this reflects the
+     * targeted span, not the actual span of reads
+     *
+     * @return the genome loc representing the span of these reads on the genome
+     */
+    public GenomeLoc getReadsSpan() {
+        if ( isUnmapped() || super.getGenomeLocs() == null || reads.isEmpty() )
+            return super.getLocation();
+        else {
+            int start = Integer.MAX_VALUE;
+            int stop = Integer.MIN_VALUE;
+            String contig = null;
+            boolean foundMapped = false;
+
+            for ( final SAMRecord read : reads ) {
+                if ( contig != null && ! read.getReferenceName().equals(contig) )
+                    throw new ReviewedGATKException("ReadShard contains reads spanning contig boundaries, which is no longer allowed. "
+                            + "First contig is " + contig + " next read was " + read.getReferenceName() );
+                contig = read.getReferenceName();
+
+                // Even if this shard as a *whole* is not "unmapped", we can still encounter *individual* unmapped mates
+                // of mapped reads within this shard's buffer. In fact, if we're very unlucky with shard boundaries,
+                // this shard might consist *only* of unmapped mates! We need to refrain from using the alignment
+                // starts/stops of these unmapped mates, and detect the case where the shard has been filled *only*
+                // with unmapped mates.
+                if ( ! read.getReadUnmappedFlag() ) {
+                    foundMapped = true;
+                    if ( read.getAlignmentStart() < start ) start = read.getAlignmentStart();
+                    if ( read.getAlignmentEnd() > stop ) stop = read.getAlignmentEnd();
+                }
+            }
+
+            assert contig != null;
+
+            if ( ! foundMapped || contig.equals("*") ) // all reads are unmapped
+                return GenomeLoc.UNMAPPED;
+            else
+                return parser.createGenomeLoc(contig, start, stop);
+        }
+    }
+}
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/datasources/reads/ReadShardBalancer.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/datasources/reads/ReadShardBalancer.java
new file mode 100644
index 0000000..4a27219
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/datasources/reads/ReadShardBalancer.java
@@ -0,0 +1,231 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.engine.datasources.reads;
+
+import htsjdk.samtools.util.PeekableIterator;
+import htsjdk.samtools.SAMRecord;
+import org.apache.log4j.Logger;
+import org.broadinstitute.gatk.utils.exceptions.ReviewedGATKException;
+
+import java.util.*;
+
+/**
+ * Convert from an unbalanced iterator over FilePointers to a balanced iterator over Shards.
+ *
+ * When processing FilePointers, our strategy is to aggregate all FilePointers for each contig
+ * together into one monolithic FilePointer, create one persistent set of read iterators over
+ * that monolithic FilePointer, and repeatedly use that persistent set of read iterators to
+ * fill read shards with reads.
+ *
+ * This strategy has several important advantages:
+ *
+ * 1. We avoid issues with file span overlap. FilePointers that are more granular than a whole
+ *    contig will have regions that overlap with other FilePointers on the same contig, due
+ *    to the limited granularity of BAM index data. By creating only one FilePointer per contig,
+ *    we avoid having to track how much of each file region we've visited (as we did in the
+ *    former implementation), we avoid expensive non-sequential access patterns in the files,
+ *    and we avoid having to repeatedly re-create our iterator chain for every small region
+ *    of interest.
+ *
+ * 2. We avoid boundary issues with the engine-level downsampling. Since we create a single
+ *    persistent set of read iterators (which include the downsampling iterator(s)) per contig,
+ *    the downsampling process is never interrupted by FilePointer or Shard boundaries, and never
+ *    loses crucial state information while downsampling within a contig.
+ *
+ * TODO: There is also at least one important disadvantage:
+ *
+ * 1. We load more BAM index data into memory at once, and this work is done upfront before processing
+ *    the next contig, creating a delay before traversal of each contig. This delay may be
+ *    compensated for by the gains listed in #1 above, and we may be no worse off overall in
+ *    terms of total runtime, but we need to verify this empirically.
+ *
+ * @author David Roazen
+ */
+public class ReadShardBalancer extends ShardBalancer {
+
+    private static Logger logger = Logger.getLogger(ReadShardBalancer.class);
+
+    /**
+     * Convert iterators of file pointers into balanced iterators of shards.
+     * @return An iterator over balanced shards.
+     */
+    public Iterator<Shard> iterator() {
+        return new Iterator<Shard>() {
+            /**
+             * The cached shard to be returned next.  Prefetched in the peekable iterator style.
+             */
+            private Shard nextShard = null;
+
+            /**
+             * The file pointer currently being processed.
+             */
+            private FilePointer currentContigFilePointer = null;
+
+            /**
+             * Iterator over the reads from the current contig's file pointer. The same iterator will be
+             * used to fill all shards associated with a given file pointer
+             */
+            private PeekableIterator<SAMRecord> currentContigReadsIterator = null;
+
+            /**
+             * How many FilePointers have we pulled from the filePointers iterator?
+             */
+            private int totalFilePointersConsumed = 0;
+
+            /**
+             * Have we encountered a monolithic FilePointer?
+             */
+            private boolean encounteredMonolithicFilePointer = false;
+
+
+            {
+                createNextContigFilePointer();
+                advance();
+            }
+
+            public boolean hasNext() {
+                return nextShard != null;
+            }
+
+            public Shard next() {
+                if ( ! hasNext() )
+                    throw new NoSuchElementException("No next read shard available");
+                Shard currentShard = nextShard;
+                advance();
+                return currentShard;
+            }
+
+            private void advance() {
+                nextShard = null;
+
+                // May need multiple iterations to fill the next shard if all reads in current file spans get filtered/downsampled away
+                while ( nextShard == null && currentContigFilePointer != null ) {
+
+                    // If we've exhausted the current file pointer of reads, move to the next file pointer (if there is one):
+                    if ( currentContigReadsIterator != null && ! currentContigReadsIterator.hasNext() ) {
+
+                        // Close the old, exhausted chain of iterators to release resources
+                        currentContigReadsIterator.close();
+
+                        // Advance to the FilePointer for the next contig
+                        createNextContigFilePointer();
+
+                        // We'll need to create a fresh iterator for this file pointer when we create the first
+                        // shard for it below.
+                        currentContigReadsIterator = null;
+                    }
+
+                    // At this point our currentContigReadsIterator may be null or non-null depending on whether or not
+                    // this is our first shard for this file pointer.
+                    if ( currentContigFilePointer != null ) {
+                        Shard shard = new ReadShard(parser,readsDataSource, currentContigFilePointer.fileSpans, currentContigFilePointer.locations, currentContigFilePointer.isRegionUnmapped);
+
+                        // Create a new reads iterator only when we've just advanced to the file pointer for the next
+                        // contig. It's essential that the iterators persist across all shards that share the same contig
+                        // to allow the downsampling to work properly.
+                        if ( currentContigReadsIterator == null ) {
+                            currentContigReadsIterator = new PeekableIterator<SAMRecord>(readsDataSource.getIterator(shard));
+                        }
+
+                        if ( currentContigReadsIterator.hasNext() ) {
+                            shard.fill(currentContigReadsIterator);
+                            nextShard = shard;
+                        }
+                    }
+                }
+            }
+
+            /**
+             * Aggregate all FilePointers for the next contig together into one monolithic FilePointer
+             * to avoid boundary issues with visiting the same file regions more than once (since more
+             * granular FilePointers will have regions that overlap with other nearby FilePointers due
+             * to the nature of BAM indices).
+             *
+             * By creating one persistent set of iterators per contig we also avoid boundary artifacts
+             * in the engine-level downsampling.
+             *
+             * TODO: This FilePointer aggregation should ideally be done at the BAMSchedule level for
+             * TODO: read traversals, as there's little point in the BAMSchedule emitting extremely
+             * TODO: granular FilePointers if we're just going to union them. The BAMSchedule should
+             * TODO: emit one FilePointer per contig for read traversals (but, crucially, NOT for
+             * TODO: locus traversals).
+             */
+            private void createNextContigFilePointer() {
+                currentContigFilePointer = null;
+                List<FilePointer> nextContigFilePointers = new ArrayList<FilePointer>();
+
+                if ( filePointers.hasNext() ) {
+                    logger.info("Loading BAM index data");
+                }
+
+                while ( filePointers.hasNext() ) {
+
+                    // Make sure that if we see a monolithic FilePointer (representing all regions in all files) that
+                    // it is the ONLY FilePointer we ever encounter
+                    if ( encounteredMonolithicFilePointer ) {
+                        throw new ReviewedGATKException("Bug: encountered additional FilePointers after encountering a monolithic FilePointer");
+                    }
+                    if ( filePointers.peek().isMonolithic() ) {
+                        if ( totalFilePointersConsumed > 0 ) {
+                            throw new ReviewedGATKException("Bug: encountered additional FilePointers before encountering a monolithic FilePointer");
+                        }
+                        encounteredMonolithicFilePointer = true;
+                        logger.debug(String.format("Encountered monolithic FilePointer: %s", filePointers.peek()));
+                    }
+
+                    // If this is the first FP we've seen, or we're dealing with mapped regions and the next FP is on the
+                    // same contig as previous FPs, or all our FPs are unmapped, add the next FP to the list of FPs to merge
+                    if ( nextContigFilePointers.isEmpty() ||
+                             (! nextContigFilePointers.get(0).isRegionUnmapped && ! filePointers.peek().isRegionUnmapped &&
+                             nextContigFilePointers.get(0).getContigIndex() == filePointers.peek().getContigIndex()) ||
+                                 (nextContigFilePointers.get(0).isRegionUnmapped && filePointers.peek().isRegionUnmapped) ) {
+
+                        nextContigFilePointers.add(filePointers.next());
+                        totalFilePointersConsumed++;
+                    }
+                    else {
+                        break; // next FilePointer is on a different contig or has different mapped/unmapped status,
+                               // save it for next time
+                    }
+                }
+
+                if ( ! nextContigFilePointers.isEmpty() ) {
+                    currentContigFilePointer = FilePointer.union(nextContigFilePointers, parser);
+                }
+
+                if ( currentContigFilePointer != null ) {
+                    logger.info("Done loading BAM index data");
+                    logger.debug(String.format("Next FilePointer: %s", currentContigFilePointer));
+                }
+            }
+
+            public void remove() {
+                throw new UnsupportedOperationException("Unable to remove from shard balancing iterator");
+            }
+        };
+    }
+
+}
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/datasources/reads/SAMDataSource.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/datasources/reads/SAMDataSource.java
new file mode 100644
index 0000000..0fc06fc
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/datasources/reads/SAMDataSource.java
@@ -0,0 +1,1179 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.engine.datasources.reads;
+
+import htsjdk.samtools.MergingSamRecordIterator;
+import htsjdk.samtools.SamFileHeaderMerger;
+import htsjdk.samtools.*;
+import htsjdk.samtools.util.CloseableIterator;
+import htsjdk.samtools.util.RuntimeIOException;
+import org.apache.log4j.Logger;
+import org.broadinstitute.gatk.engine.ReadMetrics;
+import org.broadinstitute.gatk.engine.ReadProperties;
+import org.broadinstitute.gatk.engine.arguments.ValidationExclusion;
+import org.broadinstitute.gatk.engine.downsampling.*;
+import org.broadinstitute.gatk.engine.filters.CountingFilteringIterator;
+import org.broadinstitute.gatk.engine.filters.ReadFilter;
+import org.broadinstitute.gatk.engine.iterators.*;
+import org.broadinstitute.gatk.engine.resourcemanagement.ThreadAllocation;
+import org.broadinstitute.gatk.utils.GenomeLocParser;
+import org.broadinstitute.gatk.utils.GenomeLocSortedSet;
+import org.broadinstitute.gatk.utils.SimpleTimer;
+import org.broadinstitute.gatk.utils.baq.ReadTransformingIterator;
+import org.broadinstitute.gatk.utils.exceptions.ReviewedGATKException;
+import org.broadinstitute.gatk.utils.exceptions.UserException;
+import org.broadinstitute.gatk.utils.interval.IntervalMergingRule;
+import org.broadinstitute.gatk.utils.sam.GATKSAMReadGroupRecord;
+import org.broadinstitute.gatk.utils.sam.GATKSamRecordFactory;
+
+import java.io.File;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.util.*;
+import java.util.concurrent.Callable;
+
+/**
+ * User: aaron
+ * Date: Mar 26, 2009
+ * Time: 2:36:16 PM
+ * <p/>
+ * Converts shards to SAM iterators over the specified region
+ */
+public class SAMDataSource {
+    final private static GATKSamRecordFactory factory = new GATKSamRecordFactory();
+
+    /** Backing support for reads. */
+    protected final ReadProperties readProperties;
+
+    /**
+     * Runtime metrics of reads filtered, etc.
+     */
+    private final ReadMetrics readMetrics;
+
+    /**
+     * Tools for parsing GenomeLocs, for verifying BAM ordering against general ordering.
+     */
+    protected final GenomeLocParser genomeLocParser;
+
+    /**
+     * Identifiers for the readers driving this data source.
+     */
+    private final Collection<SAMReaderID> readerIDs;
+
+    /**
+     * How strict are the readers driving this data source.
+     */
+    private final ValidationStringency validationStringency;
+
+    /**
+     * Do we want to remove the program records from this data source?
+     */
+    private final boolean removeProgramRecords;
+
+    /**
+     * Store BAM indices for each reader present.
+     */
+    private final Map<SAMReaderID,GATKBAMIndex> bamIndices = new HashMap<SAMReaderID,GATKBAMIndex>();
+
+    /**
+     * The merged header.
+     */
+    private final SAMFileHeader mergedHeader;
+
+    /**
+     * The constituent headers of the unmerged files.
+     */
+    private final Map<SAMReaderID,SAMFileHeader> headers = new HashMap<SAMReaderID,SAMFileHeader>();
+
+    /**
+     * The sort order of the BAM files.  Files without a sort order tag are assumed to be
+     * in coordinate order.
+     */
+    private SAMFileHeader.SortOrder sortOrder = null;
+
+    /**
+     * Whether the read groups in overlapping files collide.
+     */
+    private final boolean hasReadGroupCollisions;
+
+    /**
+     * Maps the SAM readers' merged read group ids to their original ids. Since merged read group ids
+     * are always unique, we can simply use a map here, no need to stratify by reader.
+     */
+    private final ReadGroupMapping mergedToOriginalReadGroupMappings = new ReadGroupMapping();
+
+    /**
+     * Maps the SAM readers' original read group ids to their revised ids. This mapping must be stratified
+     * by readers, since there can be readgroup id collision: different bam files (readers) can list the
+     * same read group id, which will be disambiguated when these input streams are merged.
+     */
+    private final Map<SAMReaderID,ReadGroupMapping> originalToMergedReadGroupMappings = new HashMap<SAMReaderID,ReadGroupMapping>();
+
+    /**
+     * Mapping from input file path to new sample name. Used only when doing on-the-fly sample renaming.
+     */
+    private Map<String, String> sampleRenameMap = null;
+
+    /** our log, which we want to capture anything from this class */
+    private static Logger logger = Logger.getLogger(SAMDataSource.class);
+
+    /**
+     * A collection of readers driving the merging process.
+     */
+    private final SAMResourcePool resourcePool;
+
+    /**
+     * Asynchronously loads BGZF blocks.
+     */
+    private final BGZFBlockLoadingDispatcher dispatcher;
+
+    /**
+     * How are threads allocated.
+     */
+    private final ThreadAllocation threadAllocation;
+
+    /**
+     * How are adjacent intervals merged by the sharder?
+     */
+    private final IntervalMergingRule intervalMergingRule;
+
+    /**
+     * Static set of unsupported programs that create bam files.
+     * The key is the PG record ID and the value is the name of the tool that created it
+     */
+    private static Map<String, String> unsupportedPGs = new HashMap<>();
+    static {
+        unsupportedPGs.put("GATK ReduceReads", "ReduceReads");
+    }
+
+    /**
+     * Create a new SAM data source given the supplied read metadata.
+     *
+     * For testing purposes
+     *
+     * @param samFiles list of reads files.
+     */
+    public SAMDataSource(Collection<SAMReaderID> samFiles, ThreadAllocation threadAllocation, Integer numFileHandles, GenomeLocParser genomeLocParser) {
+        this(
+                samFiles,
+                threadAllocation,
+                numFileHandles,
+                genomeLocParser,
+                false,
+                ValidationStringency.STRICT,
+                null,
+                null,
+                new ValidationExclusion(),
+                new ArrayList<ReadFilter>(),
+                false);
+    }
+
+    /**
+     * See complete constructor.  Does not enable BAQ by default.
+     *
+     * For testing purposes
+     */
+    public SAMDataSource(
+            Collection<SAMReaderID> samFiles,
+            ThreadAllocation threadAllocation,
+            Integer numFileHandles,
+            GenomeLocParser genomeLocParser,
+            boolean useOriginalBaseQualities,
+            ValidationStringency strictness,
+            Integer readBufferSize,
+            DownsamplingMethod downsamplingMethod,
+            ValidationExclusion exclusionList,
+            Collection<ReadFilter> supplementalFilters,
+            boolean includeReadsWithDeletionAtLoci) {
+        this(   samFiles,
+                threadAllocation,
+                numFileHandles,
+                genomeLocParser,
+                useOriginalBaseQualities,
+                strictness,
+                readBufferSize,
+                downsamplingMethod,
+                exclusionList,
+                supplementalFilters,
+                Collections.<ReadTransformer>emptyList(),
+                includeReadsWithDeletionAtLoci,
+                (byte) -1,
+                false,
+                false,
+                null,
+                IntervalMergingRule.ALL);
+    }
+
+    /**
+     * Create a new SAM data source given the supplied read metadata.
+     * @param samFiles list of reads files.
+     * @param useOriginalBaseQualities True if original base qualities should be used.
+     * @param strictness Stringency of reads file parsing.
+     * @param readBufferSize Number of reads to hold in memory per BAM.
+     * @param downsamplingMethod Method for downsampling reads at a given locus.
+     * @param exclusionList what safety checks we're willing to let slide
+     * @param supplementalFilters additional filters to dynamically apply.
+     * @param includeReadsWithDeletionAtLoci if 'true', the base pileups sent to the walker's map() method
+     *         will explicitly list reads with deletion over the current reference base; otherwise, only observed
+     *        bases will be seen in the pileups, and the deletions will be skipped silently.
+     * @param defaultBaseQualities if the reads have incomplete quality scores, set them all to defaultBaseQuality.
+     * @param keepReadsInLIBS should we keep a unique list of reads in LIBS?
+     * @param sampleRenameMap Map of BAM file to new sample ID used during on-the-fly runtime sample renaming.
+     *                        Will be null if we're not doing sample renaming.
+     * @param intervalMergingRule how are adjacent intervals merged by the sharder
+     */
+    public SAMDataSource(
+            Collection<SAMReaderID> samFiles,
+            ThreadAllocation threadAllocation,
+            Integer numFileHandles,
+            GenomeLocParser genomeLocParser,
+            boolean useOriginalBaseQualities,
+            ValidationStringency strictness,
+            Integer readBufferSize,
+            DownsamplingMethod downsamplingMethod,
+            ValidationExclusion exclusionList,
+            Collection<ReadFilter> supplementalFilters,
+            List<ReadTransformer> readTransformers,
+            boolean includeReadsWithDeletionAtLoci,
+            byte defaultBaseQualities,
+            boolean removeProgramRecords,
+            final boolean keepReadsInLIBS,
+            final Map<String, String> sampleRenameMap,
+            final IntervalMergingRule intervalMergingRule) {
+
+        this.readMetrics = new ReadMetrics();
+        this.genomeLocParser = genomeLocParser;
+        this.intervalMergingRule = intervalMergingRule;
+
+        readerIDs = samFiles;
+
+        this.threadAllocation = threadAllocation;
+        // TODO: Consider a borrowed-thread dispatcher implementation.
+        if(this.threadAllocation.getNumIOThreads() > 0) {
+            logger.info("Running in asynchronous I/O mode; number of threads = " + this.threadAllocation.getNumIOThreads());
+            dispatcher = new BGZFBlockLoadingDispatcher(this.threadAllocation.getNumIOThreads(), numFileHandles != null ? numFileHandles : 1);
+        }
+        else
+            dispatcher = null;
+
+        validationStringency = strictness;
+        this.removeProgramRecords = removeProgramRecords;
+        if(readBufferSize != null)
+            ReadShard.setReadBufferSize(readBufferSize);   // TODO: use of non-final static variable here is just awful, especially for parallel tests
+        else {
+            // Choose a sensible default for the read buffer size.
+            // Previously we we're picked 100000 reads per BAM per shard with a max cap of 250K reads in memory at once.
+            // Now we are simply setting it to 100K reads
+            ReadShard.setReadBufferSize(100000);
+        }
+
+        this.sampleRenameMap = sampleRenameMap;
+
+        resourcePool = new SAMResourcePool(Integer.MAX_VALUE);
+        SAMReaders readers = resourcePool.getAvailableReaders();
+
+        // Determine the sort order.
+        for(SAMReaderID readerID: readerIDs) {
+            if (! readerID.samFile.canRead() )
+                throw new UserException.CouldNotReadInputFile(readerID.samFile,"file is not present or user does not have appropriate permissions.  " +
+                        "Please check that the file is present and readable and try again.");
+
+            // Get the sort order, forcing it to coordinate if unsorted.
+            SAMFileReader reader = readers.getReader(readerID);
+            SAMFileHeader header = reader.getFileHeader();
+
+            headers.put(readerID,header);
+
+            if ( header.getReadGroups().isEmpty() ) {
+                throw new UserException.MalformedBAM(readers.getReaderID(reader).samFile,
+                        "SAM file doesn't have any read groups defined in the header.  The GATK no longer supports SAM files without read groups");
+            }
+
+            SAMFileHeader.SortOrder sortOrder = header.getSortOrder() != SAMFileHeader.SortOrder.unsorted ? header.getSortOrder() : SAMFileHeader.SortOrder.coordinate;
+
+            // Validate that all input files are sorted in the same order.
+            if(this.sortOrder != null && this.sortOrder != sortOrder)
+                throw new UserException.MissortedBAM(String.format("Attempted to process mixed of files sorted as %s and %s.",this.sortOrder,sortOrder));
+
+            // Update the sort order.
+            this.sortOrder = sortOrder;
+        }
+
+        mergedHeader = readers.getMergedHeader();
+        hasReadGroupCollisions = readers.hasReadGroupCollisions();
+
+        readProperties = new ReadProperties(
+                samFiles,
+                mergedHeader,
+                sortOrder,
+                useOriginalBaseQualities,
+                strictness,
+                downsamplingMethod,
+                exclusionList,
+                supplementalFilters,
+                readTransformers,
+                includeReadsWithDeletionAtLoci,
+                defaultBaseQualities,
+                keepReadsInLIBS);
+
+        // cache the read group id (original) -> read group id (merged)
+        // and read group id (merged) -> read group id (original) mappings.
+        for(SAMReaderID id: readerIDs) {
+            SAMFileReader reader = readers.getReader(id);
+
+            ReadGroupMapping mappingToMerged = new ReadGroupMapping();
+
+            List<SAMReadGroupRecord> readGroups = reader.getFileHeader().getReadGroups();
+            for(SAMReadGroupRecord readGroup: readGroups) {
+                if(hasReadGroupCollisions) {
+                    mappingToMerged.put(readGroup.getReadGroupId(),readers.getReadGroupId(id,readGroup.getReadGroupId()));
+                    mergedToOriginalReadGroupMappings.put(readers.getReadGroupId(id,readGroup.getReadGroupId()),readGroup.getReadGroupId());
+                } else {
+                    mappingToMerged.put(readGroup.getReadGroupId(),readGroup.getReadGroupId());
+                    mergedToOriginalReadGroupMappings.put(readGroup.getReadGroupId(),readGroup.getReadGroupId());
+                }
+            }
+
+            originalToMergedReadGroupMappings.put(id,mappingToMerged);
+        }
+
+        for(SAMReaderID id: readerIDs) {
+            File indexFile = findIndexFile(id.samFile);
+            if(indexFile != null)
+                bamIndices.put(id,new GATKBAMIndex(indexFile));
+        }
+
+        resourcePool.releaseReaders(readers);
+    }
+
+    /**
+     * Checks whether the provided SAM header if from a reduced bam file.
+     * @param header the SAM header for a given file
+     * @throws UserException if the header is from a reduced bam
+     */
+    private void checkForUnsupportedBamFile(final SAMFileHeader header) {
+        for ( final SAMProgramRecord PGrecord : header.getProgramRecords() ) {
+            if ( unsupportedPGs.containsKey(PGrecord.getId()) )
+                throw new UserException("The GATK no longer supports running off of BAMs produced by " + unsupportedPGs.get(PGrecord.getId()));
+        }
+    }
+
+    public void close() {
+        SAMReaders readers = resourcePool.getAvailableReaders();
+        for(SAMReaderID readerID: readerIDs) {
+            SAMFileReader reader = readers.getReader(readerID);
+            reader.close();
+        }
+    }
+
+    /**
+     * Returns Reads data structure containing information about the reads data sources placed in this pool as well as
+     * information about how they are downsampled, sorted, and filtered
+     * @return
+     */
+    public ReadProperties getReadsInfo() { return readProperties; }
+
+    /**
+     * Checks to see whether any reads files are supplying data.
+     * @return True if no reads files are supplying data to the traversal; false otherwise.
+     */
+    public boolean isEmpty() {
+        return readProperties.getSAMReaderIDs().size() == 0;
+    }
+
+    /**
+     * Gets the SAM file associated with a given reader ID.
+     * @param id The reader for which to retrieve the source file.
+     * @return the file actually associated with the id.
+     */
+    public File getSAMFile(SAMReaderID id) {
+        return id.samFile;
+    }
+
+    /**
+     * Returns readers used by this data source.
+     * @return A list of SAM reader IDs.
+     */
+    public Collection<SAMReaderID> getReaderIDs() {
+        return readerIDs;
+    }
+
+    /**
+     * Retrieves the id of the reader which built the given read.
+     * @param read The read to test.
+     * @return ID of the reader.
+     */
+    public SAMReaderID getReaderID(SAMRecord read) {
+        return resourcePool.getReaderID(read.getFileSource().getReader());
+    }
+
+    /**
+     * Gets the merged header from the SAM file.
+     * @return The merged header.
+     */
+    public SAMFileHeader getHeader() {
+        return mergedHeader;
+    }
+
+    public SAMFileHeader getHeader(SAMReaderID id) {
+        return headers.get(id);
+    }
+
+    /**
+     * Gets the revised read group id mapped to this 'original' read group id.
+     * @param reader for which to grab a read group.
+     * @param originalReadGroupId ID of the original read group.
+     * @return Merged read group ID.
+     */
+    public String getReadGroupId(final SAMReaderID reader, final String originalReadGroupId) {
+        return originalToMergedReadGroupMappings.get(reader).get(originalReadGroupId);
+    }
+
+    /**
+     * Gets the original read group id (as it was specified in the original input bam file) that maps onto
+     * this 'merged' read group id.
+     * @param mergedReadGroupId 'merged' ID of the read group (as it is presented by the read received from merged input stream).
+     * @return Merged read group ID.
+     */
+    public String getOriginalReadGroupId(final String mergedReadGroupId) {
+        return mergedToOriginalReadGroupMappings.get(mergedReadGroupId);
+    }
+
+    /**
+     * True if all readers have an index.
+     * @return True if all readers have an index.
+     */
+    public boolean hasIndex() {
+        return readerIDs.size() == bamIndices.size();
+    }
+
+    /**
+     * Gets the index for a particular reader.  Always preloaded.
+     * @param id Id of the reader.
+     * @return The index.  Will preload the index if necessary.
+     */
+    public GATKBAMIndex getIndex(final SAMReaderID id) {
+        return bamIndices.get(id);
+    }
+
+    /**
+     * Retrieves the sort order of the readers.
+     * @return Sort order.  Can be unsorted, coordinate order, or query name order.
+     */
+    public SAMFileHeader.SortOrder getSortOrder() {
+        return sortOrder;
+    }
+
+    /**
+     * Gets the cumulative read metrics for shards already processed.
+     * @return Cumulative read metrics.
+     */
+    public ReadMetrics getCumulativeReadMetrics() {
+        // don't return a clone here because the engine uses a pointer to this object
+        return readMetrics;
+    }
+
+    /**
+     * Incorporate the given read metrics into the cumulative read metrics.
+     * @param readMetrics The 'incremental' read metrics, to be incorporated into the cumulative metrics.
+     */
+    public void incorporateReadMetrics(final ReadMetrics readMetrics) {
+        this.readMetrics.incrementMetrics(readMetrics);
+    }
+
+    public GATKSAMIterator seek(Shard shard) {
+        if(shard.buffersReads()) {
+            return shard.iterator();
+        }
+        else {
+            return getIterator(shard);
+        }
+    }
+
+    /**
+     * Gets the reader associated with the given read.
+     * @param readers Available readers.
+     * @param read
+     * @return
+     */
+    private SAMReaderID getReaderID(SAMReaders readers, SAMRecord read) {
+        for(SAMReaderID id: getReaderIDs()) {
+            if(readers.getReader(id) == read.getFileSource().getReader())
+                return id;
+        }
+        throw new ReviewedGATKException("Unable to find id for reader associated with read " + read.getReadName());
+    }
+
+    /**
+     * Get the initial reader positions across all BAM files
+     *
+     * @return the start positions of the first chunk of reads for all BAM files
+     */
+    protected Map<SAMReaderID, GATKBAMFileSpan> getInitialReaderPositions() {
+        Map<SAMReaderID, GATKBAMFileSpan> initialPositions = new HashMap<SAMReaderID, GATKBAMFileSpan>();
+        SAMReaders readers = resourcePool.getAvailableReaders();
+
+        for ( SAMReaderID id: getReaderIDs() ) {
+            initialPositions.put(id, new GATKBAMFileSpan(readers.getReader(id).getFilePointerSpanningReads()));
+        }
+
+        resourcePool.releaseReaders(readers);
+        return initialPositions;
+    }
+
+    /**
+     * Get an iterator over the data types specified in the shard.
+     *
+     * @param shard The shard specifying the data limits.
+     * @return An iterator over the selected data.
+     */
+    protected GATKSAMIterator getIterator( Shard shard ) {
+        return getIterator(resourcePool.getAvailableReaders(), shard, shard instanceof ReadShard);
+    }
+
+    /**
+     * Get an iterator over the data types specified in the shard.
+     * @param readers Readers from which to load data.
+     * @param shard The shard specifying the data limits.
+     * @param enableVerification True to verify.  For compatibility with old sharding strategy.
+     * @return An iterator over the selected data.
+     */
+    private GATKSAMIterator getIterator(SAMReaders readers, Shard shard, boolean enableVerification) {
+        // Set up merging to dynamically merge together multiple BAMs.
+        Map<SAMFileReader,CloseableIterator<SAMRecord>> iteratorMap = new HashMap<SAMFileReader,CloseableIterator<SAMRecord>>();
+
+        for(SAMReaderID id: getReaderIDs()) {
+            CloseableIterator<SAMRecord> iterator = null;
+
+            // TODO: null used to be the signal for unmapped, but we've replaced that with a simple index query for the last bin.
+            // TODO: Kill this check once we've proven that the design elements are gone.
+            if(shard.getFileSpans().get(id) == null)
+                throw new ReviewedGATKException("SAMDataSource: received null location for reader " + id + ", but null locations are no longer supported.");
+
+            try {
+                if(threadAllocation.getNumIOThreads() > 0) {
+                    BlockInputStream inputStream = readers.getInputStream(id);
+                    inputStream.submitAccessPlan(new BAMAccessPlan(id, inputStream, (GATKBAMFileSpan) shard.getFileSpans().get(id)));
+                    BAMRecordCodec codec = new BAMRecordCodec(getHeader(id),factory);
+                    codec.setInputStream(inputStream);
+                    iterator = new BAMCodecIterator(inputStream,readers.getReader(id),codec);
+                }
+                else {
+                    iterator = readers.getReader(id).iterator(shard.getFileSpans().get(id));
+                }
+            } catch ( RuntimeException e ) { // we need to catch RuntimeExceptions here because the Picard code is throwing them (among SAMFormatExceptions) sometimes
+                throw new UserException.MalformedBAM(id.samFile, e.getMessage());
+            }
+
+            iterator = new MalformedBAMErrorReformatingIterator(id.samFile, iterator);
+            if(shard.getGenomeLocs().size() > 0)
+                iterator = new IntervalOverlapFilteringIterator(iterator,shard.getGenomeLocs());
+
+            iteratorMap.put(readers.getReader(id), iterator);
+        }
+
+        MergingSamRecordIterator mergingIterator = readers.createMergingIterator(iteratorMap);
+
+        // The readMetrics object being passed in should be that of this dataSource and NOT the shard: the dataSource's
+        // metrics is intended to keep track of the reads seen (and hence passed to the CountingFilteringIterator when
+        // we apply the decorators), whereas the shard's metrics is used to keep track the "records" seen.
+        return applyDecoratingIterators(readMetrics,
+                enableVerification,
+                readProperties.useOriginalBaseQualities(),
+                new ReleasingIterator(readers,GATKSAMIteratorAdapter.adapt(mergingIterator)),
+                readProperties.getValidationExclusionList().contains(ValidationExclusion.TYPE.NO_READ_ORDER_VERIFICATION),
+                readProperties.getSupplementalFilters(),
+                readProperties.getReadTransformers(),
+                readProperties.defaultBaseQualities(),
+                shard instanceof LocusShard);
+    }
+
+    private class BAMCodecIterator implements CloseableIterator<SAMRecord> {
+        private final BlockInputStream inputStream;
+        private final SAMFileReader reader;
+        private final BAMRecordCodec codec;
+        private SAMRecord nextRead;
+
+        private BAMCodecIterator(final BlockInputStream inputStream, final SAMFileReader reader, final BAMRecordCodec codec) {
+            this.inputStream = inputStream;
+            this.reader = reader;
+            this.codec = codec;
+            advance();
+        }
+
+        public boolean hasNext() {
+            return nextRead != null;
+        }
+
+        public SAMRecord next() {
+            if(!hasNext())
+                throw new NoSuchElementException("Unable to retrieve next record from BAMCodecIterator; input stream is empty");
+            SAMRecord currentRead = nextRead;
+            advance();
+            return currentRead;
+        }
+
+        public void close() {
+            // NO-OP.
+        }
+
+        public void remove() {
+            throw new UnsupportedOperationException("Unable to remove from BAMCodecIterator");
+        }
+
+        private void advance() {
+            final long startCoordinate = inputStream.getFilePointer();
+            nextRead = codec.decode();
+            final long stopCoordinate = inputStream.getFilePointer();
+
+            if(reader != null && nextRead != null)
+                PicardNamespaceUtils.setFileSource(nextRead, new SAMFileSource(reader, new GATKBAMFileSpan(new GATKChunk(startCoordinate, stopCoordinate))));
+        }
+    }
+
+    /**
+     * Filter reads based on user-specified criteria.
+     *
+     * @param readMetrics metrics to track when using this iterator.
+     * @param enableVerification Verify the order of reads.
+     * @param useOriginalBaseQualities True if original base qualities should be used.
+     * @param wrappedIterator the raw data source.
+     * @param noValidationOfReadOrder Another trigger for the verifying iterator?  TODO: look into this.
+     * @param supplementalFilters additional filters to apply to the reads.
+     * @param defaultBaseQualities if the reads have incomplete quality scores, set them all to defaultBaseQuality.
+     * @param isLocusBasedTraversal true if we're dealing with a read stream from a LocusShard
+     * @return An iterator wrapped with filters reflecting the passed-in parameters.  Will not be null.
+     */
+    protected GATKSAMIterator applyDecoratingIterators(ReadMetrics readMetrics,
+                                                        boolean enableVerification,
+                                                        boolean useOriginalBaseQualities,
+                                                        GATKSAMIterator wrappedIterator,
+                                                        Boolean noValidationOfReadOrder,
+                                                        Collection<ReadFilter> supplementalFilters,
+                                                        List<ReadTransformer> readTransformers,
+                                                        byte defaultBaseQualities,
+                                                        boolean isLocusBasedTraversal ) {
+
+        // Always apply the ReadFormattingIterator before both ReadFilters and ReadTransformers. At a minimum,
+        // this will consolidate the cigar strings into canonical form. This has to be done before the read
+        // filtering, because not all read filters will behave correctly with things like zero-length cigar
+        // elements. If useOriginalBaseQualities is true or defaultBaseQualities >= 0, this iterator will also
+        // modify the base qualities.
+        wrappedIterator = new ReadFormattingIterator(wrappedIterator, useOriginalBaseQualities, defaultBaseQualities);
+
+        // Read Filters: these are applied BEFORE downsampling, so that we downsample within the set of reads
+        // that actually survive filtering. Otherwise we could get much less coverage than requested.
+        wrappedIterator = GATKSAMIteratorAdapter.adapt(new CountingFilteringIterator(readMetrics,wrappedIterator,supplementalFilters));
+
+        // Downsampling:
+
+        // For locus traversals where we're downsampling to coverage by sample, assume that the downsamplers
+        // will be invoked downstream from us in LocusIteratorByState. This improves performance by avoiding
+        // splitting/re-assembly of the read stream at this stage, and also allows for partial downsampling
+        // of individual reads.
+        boolean assumeDownstreamLIBSDownsampling = isLocusBasedTraversal &&
+                                                   readProperties.getDownsamplingMethod().type == DownsampleType.BY_SAMPLE &&
+                                                   readProperties.getDownsamplingMethod().toCoverage != null;
+
+        // Apply downsampling iterators here only in cases where we know that LocusIteratorByState won't be
+        // doing any downsampling downstream of us
+        if ( ! assumeDownstreamLIBSDownsampling ) {
+            wrappedIterator = applyDownsamplingIterator(wrappedIterator);
+        }
+
+        // unless they've said not to validate read ordering (!noValidationOfReadOrder) and we've enabled verification,
+        // verify the read ordering by applying a sort order iterator
+        if (!noValidationOfReadOrder && enableVerification)
+            wrappedIterator = new VerifyingSamIterator(wrappedIterator);
+
+        // Read transformers: these are applied last, so that we don't bother transforming reads that get discarded
+        // by the read filters or downsampler.
+        for ( final ReadTransformer readTransformer : readTransformers ) {
+            if ( readTransformer.enabled() && readTransformer.getApplicationTime() == ReadTransformer.ApplicationTime.ON_INPUT )
+                wrappedIterator = new ReadTransformingIterator(wrappedIterator, readTransformer);
+        }
+
+        return wrappedIterator;
+    }
+
+    protected GATKSAMIterator applyDownsamplingIterator( GATKSAMIterator wrappedIterator ) {
+        if ( readProperties.getDownsamplingMethod() == null ||
+             readProperties.getDownsamplingMethod().type == DownsampleType.NONE ) {
+            return wrappedIterator;
+        }
+
+        if ( readProperties.getDownsamplingMethod().toFraction != null ) {
+
+            // If we're downsampling to a fraction of reads, there's no point in paying the cost of
+            // splitting/re-assembling the read stream by sample to run the FractionalDownsampler on
+            // reads from each sample separately, since the result would be the same as running the
+            // FractionalDownsampler on the entire stream. So, ALWAYS use the DownsamplingReadsIterator
+            // rather than the PerSampleDownsamplingReadsIterator, even if BY_SAMPLE downsampling
+            // was requested.
+
+            return new DownsamplingReadsIterator(wrappedIterator,
+                                                 new FractionalDownsampler<SAMRecord>(readProperties.getDownsamplingMethod().toFraction));
+        }
+        else if ( readProperties.getDownsamplingMethod().toCoverage != null ) {
+
+            // If we're downsampling to coverage, we DO need to pay the cost of splitting/re-assembling
+            // the read stream to run the downsampler on the reads for each individual sample separately if
+            // BY_SAMPLE downsampling was requested.
+
+            if ( readProperties.getDownsamplingMethod().type == DownsampleType.BY_SAMPLE ) {
+                return new PerSampleDownsamplingReadsIterator(wrappedIterator,
+                                                              new SimplePositionalDownsamplerFactory<SAMRecord>(readProperties.getDownsamplingMethod().toCoverage));
+            }
+            else if ( readProperties.getDownsamplingMethod().type == DownsampleType.ALL_READS ) {
+                return new DownsamplingReadsIterator(wrappedIterator,
+                                                     new SimplePositionalDownsampler<SAMRecord>(readProperties.getDownsamplingMethod().toCoverage));
+            }
+        }
+
+        return wrappedIterator;
+    }
+
+
+    private class SAMResourcePool {
+        /**
+         * How many entries can be cached in this resource pool?
+         */
+        private final int maxEntries;
+
+        /**
+         * All iterators of this reference-ordered data.
+         */
+        private List<SAMReaders> allResources = new ArrayList<SAMReaders>();
+
+        /**
+         * All iterators that are not currently in service.
+         */
+        private List<SAMReaders> availableResources = new ArrayList<SAMReaders>();
+
+        public SAMResourcePool(final int maxEntries) {
+            this.maxEntries = maxEntries;
+        }
+
+        /**
+         * Choose a set of readers from the pool to use for this query.  When complete,
+         * @return
+         */
+        public synchronized SAMReaders getAvailableReaders() {
+            if(availableResources.size() == 0)
+                createNewResource();
+            SAMReaders readers = availableResources.get(0);
+            availableResources.remove(readers);
+            return readers;
+        }
+
+        public synchronized void releaseReaders(SAMReaders readers) {
+            if(!allResources.contains(readers))
+                throw new ReviewedGATKException("Tried to return readers from the pool that didn't originate in the pool.");
+            availableResources.add(readers);
+        }
+
+        /**
+         * Gets the reader id for the given reader.
+         * @param reader Reader for which to determine the id.
+         * @return id of the given reader.
+         */
+        protected synchronized SAMReaderID getReaderID(SamReader reader) {
+            for(SAMReaders readers: allResources) {
+                SAMReaderID id = readers.getReaderID(reader);
+                if(id != null)
+                    return id;
+            }
+            throw new ReviewedGATKException("No such reader id is available");
+        }
+
+        private synchronized void createNewResource() {
+            if(allResources.size() > maxEntries)
+                throw new ReviewedGATKException("Cannot create a new resource pool.  All resources are in use.");
+            SAMReaders readers = new SAMReaders(readerIDs, validationStringency, removeProgramRecords);
+            allResources.add(readers);
+            availableResources.add(readers);
+        }
+
+    }
+
+    /**
+     * A collection of readers derived from a reads metadata structure.
+     */
+    private class SAMReaders implements Iterable<SAMFileReader> {
+        /**
+         * Cached representation of the merged header used to generate a merging iterator.
+         */
+        private final SamFileHeaderMerger headerMerger;
+
+        /**
+         * Internal storage for a map of id -> reader.
+         */
+        private final Map<SAMReaderID,SAMFileReader> readers = new LinkedHashMap<SAMReaderID,SAMFileReader>();
+
+        /**
+         * The inptu streams backing
+         */
+        private final Map<SAMReaderID,BlockInputStream> inputStreams = new LinkedHashMap<SAMReaderID,BlockInputStream>();
+
+        /**
+         * Derive a new set of readers from the Reads metadata.
+         * @param readerIDs reads to load.
+         * TODO: validationStringency is not used here
+         * @param validationStringency validation stringency.
+         * @param removeProgramRecords indicate whether to clear program records from the readers
+         */
+        public SAMReaders(Collection<SAMReaderID> readerIDs, ValidationStringency validationStringency, boolean removeProgramRecords) {
+            final int totalNumberOfFiles = readerIDs.size();
+            int readerNumber = 1;
+            final SimpleTimer timer = new SimpleTimer().start();
+
+            if ( totalNumberOfFiles > 0 ) logger.info("Initializing SAMRecords in serial");
+            final int tickSize = 50;
+            int nExecutedTotal = 0;
+            long lastTick = timer.currentTime();
+            for(final SAMReaderID readerID: readerIDs) {
+                final ReaderInitializer init = new ReaderInitializer(readerID).call();
+
+                checkForUnsupportedBamFile(init.reader.getFileHeader());
+
+                if (removeProgramRecords) {
+                    init.reader.getFileHeader().setProgramRecords(new ArrayList<SAMProgramRecord>());
+                }
+
+                if (threadAllocation.getNumIOThreads() > 0) {
+                    inputStreams.put(init.readerID, init.blockInputStream); // get from initializer
+                }
+
+                logger.debug(String.format("Processing file (%d of %d) %s...", readerNumber++, totalNumberOfFiles,  readerID.samFile));
+                readers.put(init.readerID,init.reader);
+                if ( ++nExecutedTotal % tickSize == 0) {
+                    double tickInSec = (timer.currentTime() - lastTick) / 1000.0;
+                    printReaderPerformance(nExecutedTotal, tickSize, totalNumberOfFiles, timer, tickInSec);
+                    lastTick = timer.currentTime();
+                }
+            }
+
+            if ( totalNumberOfFiles > 0 ) logger.info(String.format("Done initializing BAM readers: total time %.2f", timer.getElapsedTime()));
+
+            Collection<SAMFileHeader> headers = new LinkedList<SAMFileHeader>();
+
+            // Examine the bam headers, perform any requested sample renaming on them, and add
+            // them to the list of headers to pass to the Picard SamFileHeaderMerger:
+            for ( final Map.Entry<SAMReaderID, SAMFileReader> readerEntry : readers.entrySet() ) {
+                final SAMReaderID readerID = readerEntry.getKey();
+                final SAMFileReader reader = readerEntry.getValue();
+                final SAMFileHeader header = reader.getFileHeader();
+
+                // The remappedSampleName will be null if either no on-the-fly sample renaming was requested,
+                // or the user's sample rename map file didn't contain an entry for this bam file:
+                final String remappedSampleName = sampleRenameMap != null ? sampleRenameMap.get(readerID.getSamFilePath()) : null;
+
+                // If we've been asked to rename the sample for this bam file, do so now. We'll check to
+                // make sure this bam only contains reads from one sample before proceeding.
+                //
+                // IMPORTANT: relies on the fact that the Picard SamFileHeaderMerger makes a copy of
+                //            the existing read group attributes (including sample name) when merging
+                //            headers, regardless of whether there are read group collisions or not.
+                if ( remappedSampleName != null ) {
+                    remapSampleName(readerID, header, remappedSampleName);
+                }
+
+                headers.add(header);
+            }
+
+            headerMerger = new SamFileHeaderMerger(SAMFileHeader.SortOrder.coordinate,headers,true);
+
+            // update all read groups to GATKSAMRecordReadGroups
+            final List<SAMReadGroupRecord> gatkReadGroups = new LinkedList<SAMReadGroupRecord>();
+            for ( final SAMReadGroupRecord rg : headerMerger.getMergedHeader().getReadGroups() ) {
+                gatkReadGroups.add(new GATKSAMReadGroupRecord(rg));
+            }
+            headerMerger.getMergedHeader().setReadGroups(gatkReadGroups);
+        }
+
+        /**
+         * Changes the sample name in the read groups for the provided bam file header to match the
+         * remappedSampleName. Blows up with a UserException if the header contains more than one
+         * sample name.
+         *
+         * @param readerID ID for the bam file from which the provided header came from
+         * @param header The bam file header. Will be modified by this call.
+         * @param remappedSampleName New sample name to replace the existing sample attribute in the
+         *                           read groups for the header.
+         */
+        private void remapSampleName( final SAMReaderID readerID, final SAMFileHeader header, final String remappedSampleName ) {
+            String firstEncounteredSample = null;
+
+            for ( final SAMReadGroupRecord readGroup : header.getReadGroups() ) {
+                final String thisReadGroupSample = readGroup.getSample();
+
+                if ( thisReadGroupSample == null ) {
+                    throw new UserException(String.format("On-the fly sample renaming was requested for bam file %s, however this " +
+                                                          "bam file contains a read group (id: %s) with a null sample attribute",
+                                                          readerID.getSamFilePath(), readGroup.getId()));
+                }
+                else if ( firstEncounteredSample == null ) {
+                    firstEncounteredSample = thisReadGroupSample;
+                }
+                else if ( ! firstEncounteredSample.equals(thisReadGroupSample) ) {
+                    throw new UserException(String.format("On-the-fly sample renaming was requested for bam file %s, " +
+                                                          "however this bam file contains reads from more than one sample " +
+                                                          "(encountered samples %s and %s in the bam header). The GATK requires that " +
+                                                          "all bams for which on-the-fly sample renaming is requested " +
+                                                          "contain reads from only a single sample per bam.",
+                                                          readerID.getSamFilePath(), firstEncounteredSample, thisReadGroupSample));
+                }
+
+                readGroup.setSample(remappedSampleName);
+            }
+        }
+
+        final private void printReaderPerformance(final int nExecutedTotal,
+                                                  final int nExecutedInTick,
+                                                  final int totalNumberOfFiles,
+                                                  final SimpleTimer timer,
+                                                  final double tickDurationInSec) {
+            final int pendingSize = totalNumberOfFiles - nExecutedTotal;
+            final double totalTimeInSeconds = timer.getElapsedTime();
+            final double nTasksPerSecond = nExecutedTotal / (1.0*totalTimeInSeconds);
+            final int nRemaining = pendingSize;
+            final double estTimeToComplete = pendingSize / nTasksPerSecond;
+            logger.info(String.format("Init %d BAMs in last %.2f s, %d of %d in %.2f s / %.2f m (%.2f tasks/s).  %d remaining with est. completion in %.2f s / %.2f m",
+                    nExecutedInTick, tickDurationInSec,
+                    nExecutedTotal, totalNumberOfFiles, totalTimeInSeconds, totalTimeInSeconds / 60, nTasksPerSecond,
+                    nRemaining, estTimeToComplete, estTimeToComplete / 60));
+        }
+
+        /**
+         * Return the header derived from the merging of these BAM files.
+         * @return the merged header.
+         */
+        public SAMFileHeader getMergedHeader() {
+            return headerMerger.getMergedHeader();
+        }
+
+        /**
+         * Do multiple read groups collide in this dataset?
+         * @return True if multiple read groups collide; false otherwis.
+         */
+        public boolean hasReadGroupCollisions() {
+            return headerMerger.hasReadGroupCollisions();
+        }
+
+        /**
+         * Get the newly mapped read group ID for the given read group.
+         * @param readerID Reader for which to discern the transformed ID.
+         * @param originalReadGroupID Original read group.
+         * @return Remapped read group.
+         */
+        public String getReadGroupId(final SAMReaderID readerID, final String originalReadGroupID) {
+            SAMFileHeader header = readers.get(readerID).getFileHeader();
+            return headerMerger.getReadGroupId(header,originalReadGroupID);
+        }
+
+        /**
+         * Creates a new merging iterator from the given map, with the given header.
+         * @param iteratorMap A map of readers to iterators.
+         * @return An iterator which will merge those individual iterators.
+         */
+        public MergingSamRecordIterator createMergingIterator(final Map<SAMFileReader,CloseableIterator<SAMRecord>> iteratorMap) {
+            return new MergingSamRecordIterator(headerMerger,iteratorMap,true);
+        }
+
+        /**
+         * Retrieve the reader from the data structure.
+         * @param id The ID of the reader to retrieve.
+         * @return the reader associated with the given id.
+         */
+        public SAMFileReader getReader(SAMReaderID id) {
+            if(!readers.containsKey(id))
+                throw new NoSuchElementException("No reader is associated with id " + id);
+            return readers.get(id);
+        }
+
+        /**
+         * Retrieve the input stream backing a reader.
+         * @param id The ID of the reader to retrieve.
+         * @return the reader associated with the given id.
+         */
+        public BlockInputStream getInputStream(final SAMReaderID id) {
+            return inputStreams.get(id);
+        }
+
+        /**
+         * Searches for the reader id of this reader.
+         * @param reader Reader for which to search.
+         * @return The id associated the given reader, or null if the reader is not present in this collection.
+         */
+        protected SAMReaderID getReaderID(SamReader reader) {
+            for(Map.Entry<SAMReaderID,SAMFileReader> entry: readers.entrySet()) {
+                if(reader == entry.getValue())
+                    return entry.getKey();
+            }
+            // Not found? return null.
+            return null;
+        }
+
+        /**
+         * Returns an iterator over all readers in this structure.
+         * @return An iterator over readers.
+         */
+        public Iterator<SAMFileReader> iterator() {
+            return readers.values().iterator();
+        }
+
+        /**
+         * Returns whether any readers are present in this structure.
+         * @return
+         */
+        public boolean isEmpty() {
+            return readers.isEmpty();
+        }
+    }
+
+    class ReaderInitializer implements Callable<ReaderInitializer> {
+        final SAMReaderID readerID;
+        BlockInputStream blockInputStream = null;
+        SAMFileReader reader;
+
+        public ReaderInitializer(final SAMReaderID readerID) {
+            this.readerID = readerID;
+        }
+
+        public ReaderInitializer call() {
+            final File indexFile = findIndexFile(readerID.samFile);
+            try {
+                if (threadAllocation.getNumIOThreads() > 0)
+                    blockInputStream = new BlockInputStream(dispatcher,readerID,false);
+                reader = new SAMFileReader(readerID.samFile,indexFile,false);
+            } catch ( RuntimeIOException e ) {
+                throw new UserException.CouldNotReadInputFile(readerID.samFile, e);
+            } catch ( SAMFormatException e ) {
+                throw new UserException.MalformedBAM(readerID.samFile, e.getMessage());
+            }
+            // Picard is throwing a RuntimeException here when BAMs are malformed with bad headers (and so look like SAM files).
+            // Let's keep this separate from the SAMFormatException (which ultimately derives from RuntimeException) case,
+            // just in case we want to change this behavior later.
+            catch ( RuntimeException e ) {
+                throw new UserException.MalformedBAM(readerID.samFile, e.getMessage());
+            }
+            reader.setSAMRecordFactory(factory);
+            reader.enableFileSource(true);
+            reader.setValidationStringency(validationStringency);
+            return this;
+        }
+    }
+
+    private class ReleasingIterator implements GATKSAMIterator {
+        /**
+         * The resource acting as the source of the data.
+         */
+        private final SAMReaders resource;
+
+        /**
+         * The iterator to wrap.
+         */
+        private final GATKSAMIterator wrappedIterator;
+
+        public ReleasingIterator(SAMReaders resource, GATKSAMIterator wrapped) {
+            this.resource = resource;
+            this.wrappedIterator = wrapped;
+        }
+
+        public ReleasingIterator iterator() {
+            return this;
+        }
+
+        public void remove() {
+            throw new UnsupportedOperationException("Can't remove from a GATKSAMIterator");
+        }
+
+        public void close() {
+            wrappedIterator.close();
+            resourcePool.releaseReaders(resource);
+        }
+
+        public boolean hasNext() {
+            return wrappedIterator.hasNext();
+        }
+
+        public SAMRecord next() {
+            return wrappedIterator.next();
+        }
+    }
+
+    /**
+     * Maps read groups in the original SAMFileReaders to read groups in
+     */
+    private class ReadGroupMapping extends HashMap<String,String> {}
+
+    /**
+     * Locates the index file alongside the given BAM, if present.
+     * @param bamFile The data file to use.
+     * @return A File object if the index file is present; null otherwise.
+     */
+    private File findIndexFile(File bamFile) {
+        return SamFiles.findIndex(bamFile);
+    }
+
+    /**
+     * Creates a BAM schedule over all reads in the BAM file, both mapped and unmapped.  The outgoing stream
+     * will be as granular as possible given our current knowledge of the best ways to split up BAM files.
+     * @return An iterator that spans all reads in all BAM files.
+     */
+    public Iterable<Shard> createShardIteratorOverAllReads(final ShardBalancer shardBalancer) {
+        shardBalancer.initialize(this,IntervalSharder.shardOverAllReads(this,genomeLocParser),genomeLocParser);
+        return shardBalancer;
+    }
+
+    /**
+     * Creates a BAM schedule over all mapped reads in the BAM file, when a 'mapped' read is defined as any
+     * read that has been assigned
+     *
+     * @param   shardBalancer  shard balancer object
+     * @return non-null initialized version of the shard balancer
+     */
+    public Iterable<Shard> createShardIteratorOverMappedReads(final ShardBalancer shardBalancer) {
+        shardBalancer.initialize(this,IntervalSharder.shardOverMappedReads(this,genomeLocParser),genomeLocParser);
+        return shardBalancer;
+    }
+
+    /**
+     * Create a schedule for processing the initialized BAM file using the given interval list.
+     * The returned schedule should be as granular as possible.
+     * @param intervals The list of intervals for which to create the schedule.
+     * @return A granular iterator over file pointers.
+     */
+    public Iterable<Shard> createShardIteratorOverIntervals(final GenomeLocSortedSet intervals,final ShardBalancer shardBalancer) {
+        if(intervals == null)
+            throw new ReviewedGATKException("Unable to create schedule from intervals; no intervals were provided.");
+        shardBalancer.initialize(this,IntervalSharder.shardOverIntervals(SAMDataSource.this,intervals,intervalMergingRule),genomeLocParser);
+        return shardBalancer;
+    }
+}
+
+
+
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/datasources/reads/SAMReaderID.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/datasources/reads/SAMReaderID.java
new file mode 100644
index 0000000..ef5aaa0
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/datasources/reads/SAMReaderID.java
@@ -0,0 +1,125 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.engine.datasources.reads;
+
+import org.broadinstitute.gatk.utils.commandline.Tags;
+
+import java.io.File;
+
+/**
+ * Uniquely identifies a SAM file reader.
+ *
+ * @author mhanna
+ * @version 0.1
+ */
+public class SAMReaderID implements Comparable {
+    /**
+     * The SAM file at the heart of this reader.  SAMReaderID
+     * currently supports only file-based readers.
+     */
+    protected final File samFile;
+
+    /**
+     * A list of tags associated with this BAM file.
+     */
+    protected final Tags tags;
+
+    /**
+     * Creates an identifier for a SAM file based on read.
+     * @param samFile The source file for SAM data.
+     * @param tags tags to use when creating a reader ID.
+     */
+    public SAMReaderID(File samFile, Tags tags) {
+        this.samFile = samFile;
+        this.tags = tags;
+    }
+
+    /**
+     * Creates an identifier for a SAM file based on read.
+     * @param samFileName The source filename for SAM data.
+     * @param tags tags to use when creating a reader ID.
+     */
+    public SAMReaderID(String samFileName, Tags tags) {
+        this(new File(samFileName),tags);        
+    }
+
+    /**
+     * Gets the absolute pathname of this SAM file
+     * @return  The absolute pathname of this reader's SAM file,
+     *          or null if this reader has no associated SAM file
+     */
+    public String getSamFilePath() {
+        if ( samFile == null ) {
+            return null;
+        }
+
+        return samFile.getAbsolutePath();
+    }
+
+    /**
+     * Gets the tags associated with the given BAM file.
+     * @return A collection of the tags associated with this file.
+     */
+    public Tags getTags() {
+        return tags;
+    }
+
+    /**
+     * Compare two IDs to see whether they're equal.
+     * @param other The other identifier.
+     * @return True iff the two readers point to the same file.
+     */
+    @Override
+    public boolean equals(Object other) {
+        if(other == null) return false;
+        if(!(other instanceof SAMReaderID)) return false;
+
+        SAMReaderID otherID = (SAMReaderID)other;
+        return this.getSamFilePath().equals(otherID.getSamFilePath());
+    }
+
+    /**
+     * Generate a hash code for this object.
+     * @return A hash code, based solely on the file name at this point.
+     */
+    @Override
+    public int hashCode() {
+        return samFile.getAbsolutePath().hashCode();
+    }
+
+    /**
+     * Best string representation for a SAM file reader is the path of the source file.
+     */
+    @Override
+    public String toString() {
+        return getSamFilePath();
+    }
+
+    @Override
+    public int compareTo(Object other) {
+        return this.samFile.getAbsolutePath().compareTo(((SAMReaderID)other).samFile.getAbsolutePath());
+    }
+}
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/datasources/reads/Shard.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/datasources/reads/Shard.java
new file mode 100644
index 0000000..cc8944c
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/datasources/reads/Shard.java
@@ -0,0 +1,253 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.engine.datasources.reads;
+
+import htsjdk.samtools.util.PeekableIterator;
+import htsjdk.samtools.SAMFileSpan;
+import htsjdk.samtools.SAMRecord;
+import org.broadinstitute.gatk.engine.ReadMetrics;
+import org.broadinstitute.gatk.engine.ReadProperties;
+import org.broadinstitute.gatk.engine.iterators.GATKSAMIterator;
+import org.broadinstitute.gatk.utils.GenomeLoc;
+import org.broadinstitute.gatk.utils.GenomeLocParser;
+import org.broadinstitute.gatk.utils.HasGenomeLocation;
+
+import java.util.Collections;
+import java.util.List;
+import java.util.Map;
+/**
+ *
+ * User: aaron
+ * Date: Apr 10, 2009
+ * Time: 5:00:27 PM
+ *
+ * The Broad Institute
+ * SOFTWARE COPYRIGHT NOTICE AGREEMENT 
+ * This software and its documentation are copyright 2009 by the
+ * Broad Institute/Massachusetts Institute of Technology. All rights are reserved.
+ *
+ * This software is supplied without any warranty or guaranteed support whatsoever. Neither
+ * the Broad Institute nor MIT can be responsible for its use, misuse, or functionality.
+ *
+ */
+
+/**
+ * @author aaron
+ * @version 1.0
+ * @date Apr 10, 2009
+ * <p/>
+ * Interface Shard
+ * <p/>
+ * The base abstract class for shards.
+ */
+public abstract class Shard implements HasGenomeLocation {
+    public enum ShardType {
+        READ, LOCUS
+    }
+
+    protected final GenomeLocParser parser; // incredibly annoying!
+
+    /**
+     * What type of shard is this?  Read or locus?
+     */
+    protected final ShardType shardType;
+
+    /**
+     * Locations.
+     */
+    protected final List<GenomeLoc> locs;
+
+    /**
+     * Whether the current location is unmapped.
+     */
+    private final boolean isUnmapped;
+
+    /**
+     * Reads data, if applicable.
+     */
+    private final SAMDataSource readsDataSource;
+
+    /**
+     * The data backing the next chunks to deliver to the traversal engine.
+     */
+    private final Map<SAMReaderID,SAMFileSpan> fileSpans;
+
+    /**
+     * Lazy-calculated span of all of the genome locs in this shard
+     */
+    private GenomeLoc spanningLocation = null;
+
+    /**
+     * Statistics about which reads in this shards were used and which were filtered away.
+     */
+    protected final ReadMetrics readMetrics = new ReadMetrics();
+
+    /**
+     * Whether this shard points to an unmapped region.
+     * Some shard types conceptually be unmapped (e.g. LocusShards).  In
+     * this case, isUnmapped should always return false.
+     * @return True if this shard is unmapped.  False otherwise.
+     */
+    public boolean isUnmapped() {
+        return isUnmapped;
+    }    
+
+    public Shard(GenomeLocParser parser,
+                 ShardType shardType,
+                 List<GenomeLoc> locs,
+                 SAMDataSource readsDataSource,
+                 Map<SAMReaderID,SAMFileSpan> fileSpans,
+                 boolean isUnmapped) {
+        this.locs = locs;
+        this.parser = parser;
+        this.shardType = shardType;
+        this.readsDataSource = readsDataSource;
+        this.fileSpans = fileSpans;
+        this.isUnmapped = isUnmapped;        
+    }
+
+    /**
+     * If isUnmapped is true, than getGenomeLocs by
+     * definition will return a singleton list with a GenomeLoc.UNMAPPED
+     *
+     * Can return null, indicating that the entire genome is covered.
+     *
+     * @return the genome location represented by this shard
+     */
+    public List<GenomeLoc> getGenomeLocs() {
+        return locs;
+    }
+
+    /**
+     * Get the list of chunks delimiting this shard.
+     * @return a list of chunks that contain data for this shard.
+     */
+    public Map<SAMReaderID,SAMFileSpan> getFileSpans() {
+        return Collections.unmodifiableMap(fileSpans);
+    }    
+
+    /**
+     * Returns the span of the genomeLocs comprising this shard
+     * @return a GenomeLoc that starts as the first position in getGenomeLocs() and stops at the stop of the last
+     *    position in getGenomeLocs()
+     */
+    public GenomeLoc getLocation() {
+        if ( spanningLocation == null ) {
+            if ( getGenomeLocs() == null )
+                spanningLocation = GenomeLoc.WHOLE_GENOME;
+            else if ( getGenomeLocs().size() == 0 ) {
+                spanningLocation = getGenomeLocs().get(0);
+            } else {
+                int start = Integer.MAX_VALUE;
+                int stop = Integer.MIN_VALUE;
+                String contig = null;
+
+                for ( GenomeLoc loc : getGenomeLocs() ) {
+                    if ( GenomeLoc.isUnmapped(loc) )
+                        // special case the unmapped region marker, just abort out
+                        return loc;
+                    contig = loc.getContig();
+                    if ( loc.getStart() < start ) start = loc.getStart();
+                    if ( loc.getStop() > stop ) stop = loc.getStop();
+                }
+
+                spanningLocation = parser.createGenomeLoc(contig, start, stop);
+            }
+        }
+
+        return spanningLocation;
+    }
+
+
+    /**
+     * what kind of shard do we return
+     * @return ShardType, indicating the type
+     */
+    public ShardType getShardType() {
+        return shardType;
+    }
+
+    /**
+     * Does any releasing / aggregation required when the shard is through being processed.
+     */
+    public void close() {
+        readsDataSource.incorporateReadMetrics(readMetrics);
+    }
+
+    /**
+     * Gets key read validation and filtering properties.
+     * @return set of read properties associated with this shard.
+     */
+    public ReadProperties getReadProperties() {
+        return readsDataSource.getReadsInfo();
+    }
+
+    /**
+     * Gets the runtime metrics associated with this shard.
+     * Retrieves a storage space of metrics about number of reads included, filtered, etc.
+     * @return Storage space for metrics.
+     */
+    public ReadMetrics getReadMetrics() {
+        return readMetrics;
+    }
+
+    /**
+     * Returns true if this shard is meant to buffer reads, rather
+     * than just holding pointers to their locations.
+     * @return True if this shard can buffer reads.  False otherwise.
+     */
+    public boolean buffersReads() { return false; }
+
+    /**
+     * Returns true if the read buffer is currently full.
+     * @return True if this shard's buffer is full (and the shard can buffer reads).
+     */
+    public boolean isBufferEmpty() { throw new UnsupportedOperationException("This shard does not buffer reads."); }
+
+    /**
+     * Returns true if the read buffer is currently full.
+     * @return True if this shard's buffer is full (and the shard can buffer reads).
+     */
+    public boolean isBufferFull() { throw new UnsupportedOperationException("This shard does not buffer reads."); }
+
+    /**
+     * Adds a read to the read buffer.
+     * @param read Add a read to the internal shard buffer.
+     */
+    public void addRead(SAMRecord read) { throw new UnsupportedOperationException("This shard does not buffer reads."); }
+
+    /**
+     * Fills the shard with reads. Can only do this with shards that buffer reads
+     * @param readIter Iterator from which to draw the reads to fill the shard
+     */
+    public void fill( PeekableIterator<SAMRecord> readIter ) { throw new UnsupportedOperationException("This shard does not buffer reads."); }
+
+    /**
+     * Gets the iterator over the elements cached in the shard.
+     * @return
+     */
+    public GATKSAMIterator iterator() { throw new UnsupportedOperationException("This shard does not buffer reads."); }    
+}
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/datasources/reads/ShardBalancer.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/datasources/reads/ShardBalancer.java
new file mode 100644
index 0000000..237a380
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/datasources/reads/ShardBalancer.java
@@ -0,0 +1,49 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.engine.datasources.reads;
+
+import htsjdk.samtools.util.PeekableIterator;
+import org.broadinstitute.gatk.utils.GenomeLocParser;
+
+import java.util.Iterator;
+
+/**
+ * Balances maximally granular file pointers into shards of reasonable size.
+ */
+public abstract class ShardBalancer implements Iterable<Shard> {
+    protected SAMDataSource readsDataSource;
+    protected PeekableIterator<FilePointer> filePointers;
+    protected GenomeLocParser parser;
+
+    public void initialize(final SAMDataSource readsDataSource, final Iterator<FilePointer> filePointers, final GenomeLocParser parser) {
+        this.readsDataSource = readsDataSource;
+        this.filePointers = new PeekableIterator<FilePointer>(filePointers);
+        this.parser = parser;
+    }
+    public void close() {
+      this.filePointers.close();
+    }
+}
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/datasources/reads/package-info.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/datasources/reads/package-info.java
new file mode 100644
index 0000000..f3506f2
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/datasources/reads/package-info.java
@@ -0,0 +1,26 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.engine.datasources.reads;
\ No newline at end of file
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/datasources/reads/utilities/BAMFileStat.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/datasources/reads/utilities/BAMFileStat.java
new file mode 100644
index 0000000..95e0341
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/datasources/reads/utilities/BAMFileStat.java
@@ -0,0 +1,185 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.engine.datasources.reads.utilities;
+
+import htsjdk.samtools.BAMIndex;
+import htsjdk.samtools.SAMFileReader;
+import htsjdk.samtools.ValidationStringency;
+import org.broadinstitute.gatk.utils.commandline.Argument;
+import org.broadinstitute.gatk.utils.commandline.CommandLineProgram;
+import org.broadinstitute.gatk.utils.exceptions.ReviewedGATKException;
+import org.broadinstitute.gatk.utils.instrumentation.Sizeof;
+
+import java.io.File;
+import java.lang.reflect.Field;
+import java.util.List;
+import java.util.Map;
+
+/**
+ *
+ *
+ * @author mhanna
+ * @version 0.1
+ */
+public class BAMFileStat extends CommandLineProgram {
+    public enum CommandType { ShowBlocks, ShowIndex }
+
+    @Argument(doc="Which operation to run.",required=true)
+    private CommandType command;
+
+    @Argument(doc="The BAM file to inspect.",required=true)
+    private String bamFileName;
+
+    @Argument(doc="The range to inspect.",required=false)
+    private String range;
+
+    public int execute() {
+        switch(command) {
+            case ShowBlocks:
+                throw new ReviewedGATKException("The BAM block inspector has been disabled.");
+            case ShowIndex:
+                showIndexBins(new File(bamFileName),range);
+                break;
+        }
+        return 0;
+    }
+
+    /**
+     * Required main method implementation.
+     * @param argv Command-line arguments.
+     */
+    public static void main(String[] argv) {
+        try {
+            BAMFileStat instance = new BAMFileStat();
+            start(instance, argv);
+            System.exit(CommandLineProgram.result);
+        } catch (Exception e) {
+            exitSystemWithError(e);
+        }
+    }
+
+    private void showIndexBins(File bamFile,String contigName) {
+        SAMFileReader reader;
+        BAMIndex index;
+
+        reader = new SAMFileReader(bamFile);
+        reader.setValidationStringency(ValidationStringency.SILENT);
+        reader.enableIndexCaching(true);
+        index = reader.getIndex();
+
+        reader.queryOverlapping(contigName,1,reader.getFileHeader().getSequence(contigName).getSequenceLength()).close();
+
+        int numBins = 0;
+        int numChunks = 0;
+        int numLinearIndexEntries = 0;
+
+        try {
+            Field[] fields = index.getClass().getDeclaredFields();
+            for(Field field: fields) {
+                if(field.getName().equals("mLastReferenceRetrieved")) {
+                    field.setAccessible(true);
+                    Integer lastReferenceRetrieved = (Integer)field.get(index);
+                    System.out.printf("Last reference retrieved: %d%n", lastReferenceRetrieved);
+                }
+
+                if(field.getName().equals("mQueriesByReference")) {
+                    field.setAccessible(true);
+                    Map<Integer,Object> cachedQueries = (Map<Integer,Object>)field.get(index);
+
+                    for(Object bamIndexContent: cachedQueries.values()) {
+                        List<Object> bins = null;
+                        Map<Object,Object> binToChunkMap = null;
+                        Object linearIndex = null;
+
+                        Field[] indexContentFields = bamIndexContent.getClass().getDeclaredFields();
+                        for(Field indexContentField: indexContentFields) {
+                            if(indexContentField.getName().equals("mReferenceSequence")) {
+                                indexContentField.setAccessible(true);
+                                System.out.printf("Reference sequence: %d%n", indexContentField.getInt(bamIndexContent));
+                            }
+
+                            if(indexContentField.getName().equals("mBins")) {
+                                indexContentField.setAccessible(true);
+                                bins = (List<Object>)indexContentField.get(bamIndexContent);
+                            }
+
+                            if(indexContentField.getName().equals("mBinToChunks")) {
+                                indexContentField.setAccessible(true);
+                                binToChunkMap = (Map<Object,Object>)indexContentField.get(bamIndexContent);
+                            }
+
+                            if(indexContentField.getName().equals("mLinearIndex")) {
+                                indexContentField.setAccessible(true);
+                                linearIndex = indexContentField.get(bamIndexContent);
+                            }
+                        }
+
+                        numBins = bins.size();
+                        for(Object bin: bins) {
+                            int binNumber;
+
+                            Field[] binFields = bin.getClass().getDeclaredFields();
+                            for(Field binField: binFields) {
+                                if(binField.getName().equals("binNumber")) {
+                                    binField.setAccessible(true);
+                                    binNumber = binField.getInt(bin);
+                                    List<Object> chunks = (List<Object>)binToChunkMap.get(bin);
+                                    System.out.printf("\tBin: %d, number of chunks: %d%n",binNumber,chunks.size());
+                                    for(Object chunk: chunks)
+                                        System.out.printf("\t\tChunk: %s%n",chunk);
+                                    numChunks += chunks.size();
+                                }
+                            }
+                        }
+
+                        Field[] linearIndexFields = linearIndex.getClass().getDeclaredFields();
+                        for(Field linearIndexField: linearIndexFields) {
+                            if(linearIndexField.getName().equals("mIndexEntries")) {
+                                linearIndexField.setAccessible(true);
+                                long[] linearIndexEntries = (long[])linearIndexField.get(linearIndex);
+                                System.out.printf("\t\tIndex entries: %d", linearIndexEntries.length);
+                                for(long indexEntry: linearIndexEntries)
+                                    System.out.printf("%d,",indexEntry);
+                                System.out.printf("%n");
+                                numLinearIndexEntries = linearIndexEntries.length;
+                            }
+                        }
+                    }
+                }
+            }
+        }
+        catch(IllegalAccessException ex) {
+            throw new ReviewedGATKException("Unable to examine cached index",ex);
+        }
+
+        System.out.printf("%nOverall: %d bins, %d chunks, %d linear index entries",numBins,numChunks,numLinearIndexEntries);
+        if(Sizeof.isEnabled())
+            System.out.printf(", total index size in bytes: %d",Sizeof.getObjectGraphSize(index));
+        System.out.println();
+
+        reader.close();
+    }
+}
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/datasources/reads/utilities/BAMTagRenamer.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/datasources/reads/utilities/BAMTagRenamer.java
new file mode 100644
index 0000000..bde44a0
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/datasources/reads/utilities/BAMTagRenamer.java
@@ -0,0 +1,100 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.engine.datasources.reads.utilities;
+
+import htsjdk.samtools.SAMFileReader;
+import htsjdk.samtools.SAMFileWriter;
+import htsjdk.samtools.SAMFileWriterFactory;
+import htsjdk.samtools.SAMRecord;
+import org.broadinstitute.gatk.utils.commandline.Argument;
+import org.broadinstitute.gatk.utils.commandline.CommandLineProgram;
+
+import java.io.File;
+
+/**
+ * A simple utility written directly in Picard that will rename tags
+ * from one name to another.
+ *
+ * @author hanna
+ * @version 0.1
+ */
+
+public class BAMTagRenamer extends CommandLineProgram {
+    @Argument(fullName="input",shortName="I",doc="Input file to process",required=true)
+    private File input = null;
+
+    @Argument(fullName="output",shortName="O",doc="Output file to create",required=true)
+    private File output = null;
+
+    @Argument(fullName="bam_compression",shortName="compress",doc="Compression level to use when writing the BAM file.",required=false)
+    private int compressionLevel = 5;
+
+    @Argument(fullName="original_tag_name",shortName="otn",doc="Tag name to be replaced.",required=true)
+    private String sourceTagName = null;
+
+    @Argument(fullName="replacement_tag_name",shortName="rtn",doc="Tag name to be used as a replacement.",required=true)
+    private String targetTagName = null;
+
+    public int execute() {
+        long readsWritten = 0;
+        long readsAltered = 0;
+
+        SAMFileReader reader = new SAMFileReader(input);
+        SAMFileWriter writer = new SAMFileWriterFactory().makeBAMWriter(reader.getFileHeader(),true,output,compressionLevel);
+
+        for(SAMRecord read: reader) {
+            Object value = read.getAttribute(sourceTagName);
+            if(value != null) {
+                read.setAttribute(sourceTagName,null);
+                read.setAttribute(targetTagName,value);
+                readsAltered++;
+            }
+            writer.addAlignment(read);
+            readsWritten++;
+            if(readsWritten % 1000000 == 0)
+                System.out.printf("%d reads written.  %d tag names updated from %s to %s.%n",readsWritten,readsAltered,sourceTagName,targetTagName);
+        }
+
+        writer.close();
+        System.out.printf("%d reads written.  %d tag names updated from %s to %s.%n",readsWritten,readsAltered,sourceTagName,targetTagName);        
+
+        return 0;
+    }
+
+    /**
+     * Required main method implementation.
+     */
+    public static void main(String[] argv) {
+        BAMTagRenamer instance = new BAMTagRenamer();
+        try {
+            start(instance, argv);
+        } catch (Exception e) {
+            throw new RuntimeException(e);
+        }
+
+        System.exit(CommandLineProgram.result);
+    }
+}
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/datasources/reads/utilities/FindLargeShards.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/datasources/reads/utilities/FindLargeShards.java
new file mode 100644
index 0000000..9105b4c
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/datasources/reads/utilities/FindLargeShards.java
@@ -0,0 +1,192 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.engine.datasources.reads.utilities;
+
+import htsjdk.samtools.reference.IndexedFastaSequenceFile;
+import org.apache.log4j.Logger;
+import org.broadinstitute.gatk.utils.commandline.CommandLineProgram;
+import org.broadinstitute.gatk.utils.commandline.Input;
+import org.broadinstitute.gatk.utils.commandline.Output;
+import org.broadinstitute.gatk.engine.datasources.reads.FilePointer;
+import org.broadinstitute.gatk.engine.datasources.reads.IntervalSharder;
+import org.broadinstitute.gatk.engine.datasources.reads.SAMDataSource;
+import org.broadinstitute.gatk.engine.datasources.reads.SAMReaderID;
+import org.broadinstitute.gatk.engine.resourcemanagement.ThreadAllocation;
+import org.broadinstitute.gatk.utils.GenomeLoc;
+import org.broadinstitute.gatk.utils.GenomeLocParser;
+import org.broadinstitute.gatk.utils.GenomeLocSortedSet;
+import org.broadinstitute.gatk.utils.interval.IntervalMergingRule;
+import org.broadinstitute.gatk.utils.interval.IntervalUtils;
+import org.broadinstitute.gatk.utils.text.ListFileUtils;
+
+import java.io.File;
+import java.io.IOException;
+import java.io.PrintStream;
+import java.math.BigInteger;
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Traverses a region in a dataset looking for outliers.
+ */
+public class FindLargeShards extends CommandLineProgram {
+    private static Logger logger = Logger.getLogger(FindLargeShards.class);
+
+    @Input(fullName = "input_file", shortName = "I", doc = "SAM or BAM file(s)", required = false)
+    public List<String> samFiles = new ArrayList<String>();
+
+    @Input(fullName = "reference_sequence", shortName = "R", doc = "Reference sequence file", required = false)
+    public File referenceFile = null;
+
+    @Input(fullName = "intervals", shortName = "L", doc = "A list of genomic intervals over which to operate. Can be explicitly specified on the command line or in a file.",required=false)
+    public List<String> intervals = null;
+
+    @Output(required=false)
+    public PrintStream out = System.out;
+
+    /**
+     * The square of the sum of all uncompressed data.  Based on the BAM spec, the size of this could be
+     * up to (2^64)^2.
+     */
+    private BigInteger sumOfSquares = BigInteger.valueOf(0);
+
+    /**
+     * The running sum of all uncompressed data.  Based on the BAM spec, the BAM must be less than Long.MAX_LONG
+     * when compressed -- in other words, the sum of the sizes of all BGZF blocks must be < 2^64.
+     */
+    private BigInteger sum = BigInteger.valueOf(0);
+
+    /**
+     * The number of shards viewed.
+     */
+    private long numberOfShards;
+
+
+    @Override
+    public int execute() throws IOException {
+        // initialize reference
+        IndexedFastaSequenceFile refReader = new IndexedFastaSequenceFile(referenceFile);
+        GenomeLocParser genomeLocParser = new GenomeLocParser(refReader);        
+
+        // initialize reads
+        List<SAMReaderID> bamReaders = ListFileUtils.unpackBAMFileList(samFiles,parser);
+        SAMDataSource dataSource = new SAMDataSource(bamReaders,new ThreadAllocation(),null,genomeLocParser);
+
+        // intervals
+        final GenomeLocSortedSet intervalSortedSet;
+        if ( intervals != null )
+            intervalSortedSet = IntervalUtils.sortAndMergeIntervals(genomeLocParser, IntervalUtils.parseIntervalArguments(genomeLocParser, intervals), IntervalMergingRule.ALL);
+        else
+            intervalSortedSet = GenomeLocSortedSet.createSetFromSequenceDictionary(refReader.getSequenceDictionary());
+
+        logger.info(String.format("PROGRESS: Calculating mean and variance: Contig\tRegion.Start\tRegion.Stop\tSize"));        
+
+        IntervalSharder sharder = IntervalSharder.shardOverIntervals(dataSource,intervalSortedSet,IntervalMergingRule.ALL);
+        while(sharder.hasNext()) {
+            FilePointer filePointer = sharder.next();
+
+            // Size of the file pointer.
+            final long size = filePointer.size();            
+
+            BigInteger bigSize = BigInteger.valueOf(size);
+            sumOfSquares = sumOfSquares.add(bigSize.pow(2));
+            sum = sum.add(bigSize);
+            numberOfShards++;
+
+            if(numberOfShards % 1000 == 0) {
+                GenomeLoc boundingRegion = getBoundingRegion(filePointer,genomeLocParser);
+                logger.info(String.format("PROGRESS: Calculating mean and variance: %s\t%d\t%d\t%d",boundingRegion.getContig(),boundingRegion.getStart(),boundingRegion.getStop(),size));
+            }
+
+        }
+
+        // Print out the stddev: (sum(x^2) - (1/N)*sum(x)^2)/N
+        long mean = sum.divide(BigInteger.valueOf(numberOfShards)).longValue();
+        long stddev = (long)(Math.sqrt(sumOfSquares.subtract(sum.pow(2).divide(BigInteger.valueOf(numberOfShards))).divide(BigInteger.valueOf(numberOfShards)).doubleValue()));
+        logger.info(String.format("Number of shards: %d; mean uncompressed size = %d; stddev uncompressed size  = %d%n",numberOfShards,mean,stddev));
+
+        // Crank through the shards again, this time reporting on the shards significantly larger than the mean.
+        long threshold = mean + stddev*5;
+        logger.warn(String.format("PROGRESS: Searching for large shards: Contig\tRegion.Start\tRegion.Stop\tSize"));
+        out.printf("Contig\tRegion.Start\tRegion.Stop\tSize%n");
+
+        sharder =  IntervalSharder.shardOverIntervals(dataSource,intervalSortedSet,IntervalMergingRule.ALL);
+        while(sharder.hasNext()) {
+            FilePointer filePointer = sharder.next();
+
+            // Bounding region.
+            GenomeLoc boundingRegion = getBoundingRegion(filePointer,genomeLocParser);
+
+            // Size of the file pointer.
+            final long size = filePointer.size();            
+
+            numberOfShards++;
+
+            if(filePointer.size() <= threshold) {
+                if(numberOfShards % 1000 == 0) 
+                    logger.info(String.format("PROGRESS: Searching for large shards: %s\t%d\t%d\t%d",boundingRegion.getContig(),boundingRegion.getStart(),boundingRegion.getStop(),size));
+                continue;
+            }
+
+            out.printf("%s\t%d\t%d\t%d%n",boundingRegion.getContig(),boundingRegion.getStart(),boundingRegion.getStop(),size);
+        }
+
+        return 0;
+    }
+
+    private GenomeLoc getBoundingRegion(final FilePointer filePointer, final GenomeLocParser genomeLocParser) {
+        List<GenomeLoc> regions = filePointer.getLocations();
+
+        // The region contained by this FilePointer.
+        final String contig = regions.get(0).getContig();
+        final int start = regions.get(0).getStart();
+        final int stop = regions.get(regions.size()-1).getStop();
+
+        return genomeLocParser.createGenomeLoc(contig,start,stop);
+    }
+
+    /**
+     * Required main method implementation.
+     * @param argv Command-line argument text.
+     * @throws Exception on error.
+     */
+    public static void main(String[] argv) throws Exception {
+        int returnCode = 0;
+        try {
+            FindLargeShards instance = new FindLargeShards();
+            start(instance, argv);
+            returnCode = 0;
+        }
+        catch(Exception ex) {
+            returnCode = 1;
+            ex.printStackTrace();
+            throw ex;
+        }
+        finally {
+            System.exit(returnCode);
+        }
+    }    
+}
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/datasources/reads/utilities/PrintBAMRegion.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/datasources/reads/utilities/PrintBAMRegion.java
new file mode 100644
index 0000000..b0842e1
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/datasources/reads/utilities/PrintBAMRegion.java
@@ -0,0 +1,113 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.engine.datasources.reads.utilities;
+
+import htsjdk.samtools.*;
+import org.broadinstitute.gatk.utils.commandline.Argument;
+import org.broadinstitute.gatk.utils.commandline.CommandLineProgram;
+import org.broadinstitute.gatk.utils.exceptions.UserException;
+
+import java.io.File;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+/**
+ * Created by IntelliJ IDEA.
+ * User: mhanna
+ * Date: Feb 25, 2011
+ * Time: 3:25:13 PM
+ * To change this template use File | Settings | File Templates.
+ */
+public class PrintBAMRegion extends CommandLineProgram {
+    @Argument(fullName="input",shortName="I",doc="Input file to process",required=true)
+    private File input = null;
+
+    @Argument(fullName="region",shortName="R",doc="BAM region to process, in chunk format (mmmm:nn-xxxx:yy)",required=true)
+    private String region;
+
+    private static final long MIN_BLOCK_SIZE = 0;
+    private static final long MAX_BLOCK_SIZE = (long)Math.pow(2,48)-1;
+    private static final int MIN_OFFSET_SIZE = 0;
+    private static final int MAX_OFFSET_SIZE = (int)Math.pow(2,16)-1;
+
+    public int execute() {
+        SAMFileReader reader = new SAMFileReader(input);
+        reader.setValidationStringency(ValidationStringency.SILENT);
+
+        Pattern regionPattern = Pattern.compile("(\\d+):(\\d+)-(\\d+):(\\d+)");
+        Matcher matcher = regionPattern.matcher(region);
+        if(!matcher.matches())
+            throw new UserException("BAM region to process must be in chunk format (mmmm:nn-xxxx:yy)");
+
+        long firstBlock = Long.parseLong(matcher.group(1));
+        int firstOffset = Integer.parseInt(matcher.group(2));
+        long lastBlock = Long.parseLong(matcher.group(3));
+        int lastOffset = Integer.parseInt(matcher.group(4));
+
+        if(firstBlock < MIN_BLOCK_SIZE || firstBlock > MAX_BLOCK_SIZE)
+            throw new UserException(String.format("First block is invalid; must be between %d and %d; actually is %d",MIN_BLOCK_SIZE,MAX_BLOCK_SIZE,firstBlock));
+        if(lastBlock < MIN_BLOCK_SIZE || lastBlock > MAX_BLOCK_SIZE)
+            throw new UserException(String.format("Last block is invalid; must be between %d and %d; actually is %d",MIN_BLOCK_SIZE,MAX_BLOCK_SIZE,lastBlock));
+        if(firstOffset < MIN_OFFSET_SIZE || firstOffset > MAX_OFFSET_SIZE)
+            throw new UserException(String.format("First offset is invalid; must be between %d and %d; actually is %d",MIN_OFFSET_SIZE,MAX_OFFSET_SIZE,firstOffset));
+        if(lastOffset < MIN_OFFSET_SIZE || lastOffset > MAX_OFFSET_SIZE)
+            throw new UserException(String.format("Last offset is invalid; must be between %d and %d; actually is %d",MIN_OFFSET_SIZE,MAX_OFFSET_SIZE,lastOffset));
+
+        GATKChunk chunk = new GATKChunk(firstBlock<<16 | firstOffset,lastBlock<<16 | lastOffset);
+        GATKBAMFileSpan fileSpan = new GATKBAMFileSpan(chunk);
+
+        SAMRecordIterator iterator = reader.iterator(fileSpan);
+        long readCount = 0;
+        while(iterator.hasNext()) {
+            System.out.printf("%s%n",iterator.next().format());
+            readCount++;
+        }
+        System.out.printf("%d reads shown.",readCount);
+
+        iterator.close();
+        reader.close();
+
+        return 0;
+    }
+
+
+    /**
+     * Required main method implementation.
+     * @param argv Command-line argument text.
+     * @throws Exception on error.
+     */
+    public static void main(String[] argv) throws Exception {
+        try {
+            PrintBAMRegion instance = new PrintBAMRegion();
+            start(instance, argv);
+            System.exit(0);
+        }
+        catch(Exception ex) {
+            ex.printStackTrace();
+            System.exit(1);
+        }
+    }
+}
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/datasources/reads/utilities/PrintBGZFBounds.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/datasources/reads/utilities/PrintBGZFBounds.java
new file mode 100644
index 0000000..807e038
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/datasources/reads/utilities/PrintBGZFBounds.java
@@ -0,0 +1,137 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.engine.datasources.reads.utilities;
+
+import org.broadinstitute.gatk.utils.commandline.Argument;
+import org.broadinstitute.gatk.utils.commandline.CommandLineProgram;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.nio.ByteBuffer;
+import java.nio.ByteOrder;
+
+/**
+ * Calculates the bounds of each BGZF block in a BAM index file, along with
+ */
+public class PrintBGZFBounds extends CommandLineProgram {
+    @Argument(fullName="input",shortName="I",doc="Input bai file to process",required=true)
+    private File input = null;
+
+    private final int BYTE_SIZE_IN_BYTES = Byte.SIZE / 8;
+    private final int INT_SIZE_IN_BYTES = Integer.SIZE / 8;
+    private final int SHORT_SIZE_IN_BYTES = INT_SIZE_IN_BYTES / 2;
+
+    /**
+     * ID1 + ID2 + CM + FLG + MTIME + XFL + OS + XLEN.
+     */
+    private final int HEADER_SIZE = BYTE_SIZE_IN_BYTES*4+INT_SIZE_IN_BYTES+BYTE_SIZE_IN_BYTES*2+SHORT_SIZE_IN_BYTES + BYTE_SIZE_IN_BYTES*2 + SHORT_SIZE_IN_BYTES*2;;
+
+    /**
+     * CRC32 + ISIZE
+     */
+    private final int FOOTER_SIZE = INT_SIZE_IN_BYTES*2;
+
+    @Override
+    public int execute() throws IOException {
+        FileInputStream fis = new FileInputStream(input);
+        ByteBuffer headerBuffer = allocateBuffer(HEADER_SIZE);
+        ByteBuffer footerBuffer = allocateBuffer(FOOTER_SIZE);
+
+        float compressedSize = 0;
+        float uncompressedSize = 0;
+        long totalBlocks = 0;
+
+        //SAMFileReader reader = new SAMFileReader(input);
+
+        while(true) {
+            final long blockStart = fis.getChannel().position();
+
+            int totalRead = fis.getChannel().read(headerBuffer);
+            if(totalRead <= 0)
+                break;
+            headerBuffer.flip();
+
+            // Read out header information, including subfield IDs.
+            headerBuffer.position(headerBuffer.capacity()-BYTE_SIZE_IN_BYTES*2);
+            final int cDataSize = headerBuffer.getShort()-HEADER_SIZE-FOOTER_SIZE+1;
+            compressedSize += cDataSize;
+
+            // Skip past body.
+            fis.getChannel().position(fis.getChannel().position()+cDataSize);
+
+            // Read the footer
+            fis.getChannel().read(footerBuffer);
+            footerBuffer.flip();
+
+            // Retrieve the uncompressed size from the footer.
+            footerBuffer.position(footerBuffer.capacity()-INT_SIZE_IN_BYTES);
+            uncompressedSize += footerBuffer.getInt();
+
+            // Reset buffers for subsequent reads.
+            headerBuffer.flip();
+            footerBuffer.flip();
+
+            totalBlocks++;
+
+            final long blockStop = fis.getChannel().position() - 1;
+
+            System.out.printf("BGZF block %d: [%d-%d]%n",totalBlocks,blockStart,blockStop);
+        }
+
+        System.out.printf("SUCCESS!  Average compressed block size = %f, average uncompressed size = %f, compressed/uncompressed ratio: %f%n",compressedSize/totalBlocks,uncompressedSize/totalBlocks,compressedSize/uncompressedSize);
+
+        return 0;
+    }
+
+    private ByteBuffer allocateBuffer(final int size) {
+        ByteBuffer buffer = ByteBuffer.allocate(size);
+        buffer.order(ByteOrder.LITTLE_ENDIAN);
+        return buffer;
+    }
+
+    /**
+     * Required main method implementation.
+     * @param argv Command-line argument text.
+     * @throws Exception on error.
+     */
+    public static void main(String[] argv) throws Exception {
+        int returnCode = 0;
+        try {
+            PrintBGZFBounds instance = new PrintBGZFBounds();
+            start(instance, argv);
+            returnCode = 0;
+        }
+        catch(Exception ex) {
+            returnCode = 1;
+            ex.printStackTrace();
+            throw ex;
+        }
+        finally {
+            System.exit(returnCode);
+        }
+    }
+}
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/datasources/reads/utilities/UnzipSingleBlock.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/datasources/reads/utilities/UnzipSingleBlock.java
new file mode 100644
index 0000000..d65b779
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/datasources/reads/utilities/UnzipSingleBlock.java
@@ -0,0 +1,89 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.engine.datasources.reads.utilities;
+
+import htsjdk.samtools.util.BlockGunzipper;
+import org.broadinstitute.gatk.utils.commandline.CommandLineProgram;
+import org.broadinstitute.gatk.utils.commandline.Input;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+
+/**
+ * Test decompression of a single BGZF block.
+ */
+public class UnzipSingleBlock extends CommandLineProgram {
+    @Input(fullName = "block_file", shortName = "b", doc = "block file over which to test unzipping", required = true)
+    private File blockFile;
+
+    @Input(fullName = "compressed_block_size", shortName = "cbs", doc = "size of compressed block", required = true)
+    private int compressedBufferSize;
+
+    public int execute() throws IOException, NoSuchMethodException, IllegalAccessException, InvocationTargetException {
+        byte[] compressedBuffer = new byte[(int)blockFile.length()];
+        byte[] uncompressedBuffer = new byte[65536];
+
+        FileInputStream fis = new FileInputStream(blockFile);
+        fis.read(compressedBuffer);
+        fis.close();
+
+        BlockGunzipper gunzipper = new BlockGunzipper();
+        gunzipper.setCheckCrcs(true);
+        Method unzipBlock = BlockGunzipper.class.getDeclaredMethod("unzipBlock",byte[].class,byte[].class,Integer.TYPE);
+        unzipBlock.setAccessible(true);
+
+        unzipBlock.invoke(gunzipper,uncompressedBuffer,compressedBuffer,compressedBufferSize);
+
+        System.out.printf("SUCCESS!%n");
+
+        return 0;
+    }
+
+    /**
+     * Required main method implementation.
+     * @param argv Command-line argument text.
+     * @throws Exception on error.
+     */
+    public static void main(String[] argv) throws Exception {
+        int returnCode = 0;
+        try {
+            UnzipSingleBlock instance = new UnzipSingleBlock();
+            start(instance, argv);
+            returnCode = 0;
+        }
+        catch(Exception ex) {
+            returnCode = 1;
+            ex.printStackTrace();
+            throw ex;
+        }
+        finally {
+            System.exit(returnCode);
+        }
+    }
+}
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/datasources/reads/utilities/package-info.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/datasources/reads/utilities/package-info.java
new file mode 100644
index 0000000..65a909a
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/datasources/reads/utilities/package-info.java
@@ -0,0 +1,26 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.engine.datasources.reads.utilities;
\ No newline at end of file
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/datasources/reference/ReferenceDataSource.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/datasources/reference/ReferenceDataSource.java
new file mode 100644
index 0000000..6fdbea3
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/datasources/reference/ReferenceDataSource.java
@@ -0,0 +1,199 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.engine.datasources.reference;
+
+import htsjdk.samtools.reference.IndexedFastaSequenceFile;
+import htsjdk.samtools.SAMSequenceRecord;
+import org.broadinstitute.gatk.engine.datasources.reads.LocusShard;
+import org.broadinstitute.gatk.engine.datasources.reads.SAMDataSource;
+import org.broadinstitute.gatk.engine.datasources.reads.Shard;
+import org.broadinstitute.gatk.utils.GenomeLoc;
+import org.broadinstitute.gatk.utils.GenomeLocParser;
+import org.broadinstitute.gatk.utils.GenomeLocSortedSet;
+import org.broadinstitute.gatk.utils.exceptions.UserException;
+import org.broadinstitute.gatk.utils.fasta.CachingIndexedFastaSequenceFile;
+
+import java.io.File;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+/**
+ * Loads reference data from fasta file
+ * Looks for fai and dict files, and tries to create them if they don't exist
+ */
+public class ReferenceDataSource {
+    private IndexedFastaSequenceFile reference;
+
+    /** our log, which we want to capture anything from this class */
+    protected static final org.apache.log4j.Logger logger = org.apache.log4j.Logger.getLogger(ReferenceDataSource.class);
+
+    /**
+     * Create reference data source from fasta file
+     * @param fastaFile Fasta file to be used as reference
+     */
+    public ReferenceDataSource(File fastaFile) {
+        // does the fasta file exist? check that first...
+        if (!fastaFile.exists())
+            throw new UserException("The fasta file you specified (" + fastaFile.getAbsolutePath() + ") does not exist.");
+
+        final boolean isGzipped = fastaFile.getAbsolutePath().endsWith(".gz");
+        if ( isGzipped ) {
+            throw new UserException.CannotHandleGzippedRef();
+        }
+
+        final File indexFile = new File(fastaFile.getAbsolutePath() + ".fai");
+
+        // determine the name for the dict file
+        final String fastaExt = fastaFile.getAbsolutePath().endsWith("fa") ? "\\.fa$" : "\\.fasta$";
+        final File dictFile = new File(fastaFile.getAbsolutePath().replaceAll(fastaExt, ".dict"));
+
+        // It's an error if either the fai or dict file does not exist. The user is now responsible
+        // for creating these files.
+        if (!indexFile.exists()) {
+            throw new UserException.MissingReferenceFaiFile(indexFile, fastaFile);
+        }
+        if (!dictFile.exists()) {
+            throw new UserException.MissingReferenceDictFile(dictFile, fastaFile);
+        }
+
+        // Read reference data by creating an IndexedFastaSequenceFile.
+        try {
+            reference = new CachingIndexedFastaSequenceFile(fastaFile);
+        }
+        catch (IllegalArgumentException e) {
+            throw new UserException.CouldNotReadInputFile(fastaFile, "Could not read reference sequence.  The FASTA must have either a .fasta or .fa extension", e);
+        }
+        catch (Exception e) {
+            throw new UserException.CouldNotReadInputFile(fastaFile, e);
+        }
+    }
+
+    /**
+     * Get indexed fasta file
+     * @return IndexedFastaSequenceFile that was created from file
+     */
+    public IndexedFastaSequenceFile getReference() {
+        return this.reference;
+    }
+
+    /**
+     * Creates an iterator for processing the entire reference.
+     * @param readsDataSource the reads datasource to embed in the locus shard.
+     * @param parser used to generate/regenerate intervals.  TODO: decouple the creation of the shards themselves from the creation of the driving iterator so that datasources need not be passed to datasources.
+     * @param maxShardSize The maximum shard size which can be used to create this list.
+     * @return Creates a schedule for performing a traversal over the entire reference.
+     */
+    public Iterable<Shard> createShardsOverEntireReference(final SAMDataSource readsDataSource, final GenomeLocParser parser, final int maxShardSize) {
+        List<Shard> shards = new ArrayList<Shard>();
+        for(SAMSequenceRecord refSequenceRecord: reference.getSequenceDictionary().getSequences()) {
+            for(int shardStart = 1; shardStart <= refSequenceRecord.getSequenceLength(); shardStart += maxShardSize) {
+                final int shardStop = Math.min(shardStart+maxShardSize-1, refSequenceRecord.getSequenceLength());
+                shards.add(new LocusShard(parser,
+                        readsDataSource,
+                        Collections.singletonList(parser.createGenomeLoc(refSequenceRecord.getSequenceName(),shardStart,shardStop)),
+                        null));
+            }
+        }
+        return shards;
+    }
+
+
+    public Iterable<Shard> createShardsOverIntervals(final SAMDataSource readsDataSource, final GenomeLocSortedSet intervals, final int maxShardSize) {
+        List<Shard> shards = new ArrayList<Shard>();
+
+        for(GenomeLoc interval: intervals) {
+            while(interval.size() > maxShardSize) {
+                shards.add(new LocusShard(intervals.getGenomeLocParser(),
+                        readsDataSource,
+                        Collections.singletonList(intervals.getGenomeLocParser().createGenomeLoc(interval.getContig(),interval.getStart(),interval.getStart()+maxShardSize-1)),
+                        null));
+                interval = intervals.getGenomeLocParser().createGenomeLoc(interval.getContig(),interval.getStart()+maxShardSize,interval.getStop());
+            }
+            shards.add(new LocusShard(intervals.getGenomeLocParser(),
+                    readsDataSource,
+                    Collections.singletonList(interval),
+                    null));
+        }
+
+        return shards;
+    }
+
+
+    /**
+     * Creates an iterator for processing the entire reference.
+     * @param readsDataSource  the reads datasource to embed in the locus shard.  TODO: decouple the creation of the shards themselves from the creation of the driving iterator so that datasources need not be passed to datasources.
+     * @param intervals        the list of intervals to use when processing the reference.
+     * @param targetShardSize  the suggested - and maximum - shard size which can be used to create this list; we will merge intervals greedily so that we generate shards up to but not greater than the target size.
+     * @return Creates a schedule for performing a traversal over the entire reference.
+     */
+/*
+    public Iterable<Shard> createShardsOverIntervals(final SAMDataSource readsDataSource, final GenomeLocSortedSet intervals, final int targetShardSize) {
+        final List<Shard> shards = new ArrayList<Shard>();
+        final GenomeLocParser parser = intervals.getGenomeLocParser();
+        LinkedList<GenomeLoc> currentIntervals = new LinkedList<GenomeLoc>();
+
+        for(GenomeLoc interval: intervals) {
+            // if the next interval is too big, we can safely shard currentInterval and then break down this one
+            if (interval.size() > targetShardSize) {
+                if (!currentIntervals.isEmpty())
+                    shards.add(createShardFromInterval(currentIntervals, readsDataSource, parser));
+                while(interval.size() > targetShardSize) {
+                    final GenomeLoc partialInterval = parser.createGenomeLoc(interval.getContig(), interval.getStart(), interval.getStart()+targetShardSize-1);
+                    shards.add(createShardFromInterval(Collections.singletonList(partialInterval), readsDataSource, parser));
+                    interval = parser.createGenomeLoc(interval.getContig(), interval.getStart() + targetShardSize, interval.getStop());
+                }
+                currentIntervals = new LinkedList<GenomeLoc>();
+                currentIntervals.add(interval);
+            }
+            // otherwise, we need to check whether we can merge this interval with currentInterval (and either shard currentInterval or merge accordingly)
+            else {
+                if (currentIntervals.isEmpty()) {
+                    currentIntervals.add(interval);
+                }
+                else {
+                    if (currentIntervals.getLast().compareContigs(interval) != 0 || interval.getStop() - currentIntervals.getLast().getStart() + 1 > targetShardSize) {
+                        shards.add(createShardFromInterval(currentIntervals, readsDataSource, parser));
+                        currentIntervals = new LinkedList<GenomeLoc>();
+                    }
+                    currentIntervals.add(interval);
+                }
+            }
+        }
+        if (!currentIntervals.isEmpty())
+            shards.add(createShardFromInterval(currentIntervals, readsDataSource, parser));
+        return shards;
+    }
+
+    private static Shard createShardFromInterval(final List<GenomeLoc> intervals, final SAMDataSource readsDataSource, final GenomeLocParser parser) {
+        //logger.debug("Adding shard " + interval);
+        return new LocusShard(parser,
+                readsDataSource,
+                intervals,
+                null);
+    }
+*/
+}
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/datasources/reference/package-info.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/datasources/reference/package-info.java
new file mode 100644
index 0000000..581d213
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/datasources/reference/package-info.java
@@ -0,0 +1,26 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.engine.datasources.reference;
\ No newline at end of file
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/datasources/rmd/DataStreamSegment.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/datasources/rmd/DataStreamSegment.java
new file mode 100644
index 0000000..2543c42
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/datasources/rmd/DataStreamSegment.java
@@ -0,0 +1,32 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.engine.datasources.rmd;
+
+/**
+ * Marker interface that represents an arbitrary consecutive segment within a data stream.
+ */
+interface DataStreamSegment {
+}
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/datasources/rmd/EntireStream.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/datasources/rmd/EntireStream.java
new file mode 100644
index 0000000..eba5b53
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/datasources/rmd/EntireStream.java
@@ -0,0 +1,32 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.engine.datasources.rmd;
+
+/**
+ * Models the entire stream of data.
+ */
+class EntireStream implements DataStreamSegment {
+}
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/datasources/rmd/MappedStreamSegment.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/datasources/rmd/MappedStreamSegment.java
new file mode 100644
index 0000000..0344ff0
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/datasources/rmd/MappedStreamSegment.java
@@ -0,0 +1,48 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.engine.datasources.rmd;
+
+import org.broadinstitute.gatk.utils.GenomeLoc;
+import org.broadinstitute.gatk.utils.HasGenomeLocation;
+
+/**
+ * Models a mapped position within a stream of GATK input data.
+ */
+class MappedStreamSegment implements DataStreamSegment, HasGenomeLocation {
+    public final GenomeLoc locus;
+
+    /**
+     * Retrieves the first location covered by a mapped stream segment.
+     * @return Location of the first base in this segment.
+     */
+    public GenomeLoc getLocation() {
+        return locus;
+    }
+
+    public MappedStreamSegment(GenomeLoc locus) {
+        this.locus = locus;
+    }
+}
\ No newline at end of file
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/datasources/rmd/ReferenceOrderedDataPool.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/datasources/rmd/ReferenceOrderedDataPool.java
new file mode 100644
index 0000000..762eb0b
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/datasources/rmd/ReferenceOrderedDataPool.java
@@ -0,0 +1,153 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.engine.datasources.rmd;
+
+import htsjdk.samtools.SAMSequenceDictionary;
+import org.broadinstitute.gatk.engine.refdata.SeekableRODIterator;
+import org.broadinstitute.gatk.engine.refdata.tracks.RMDTrack;
+import org.broadinstitute.gatk.engine.refdata.tracks.RMDTrackBuilder;
+import org.broadinstitute.gatk.engine.refdata.utils.FlashBackIterator;
+import org.broadinstitute.gatk.engine.refdata.utils.LocationAwareSeekableRODIterator;
+import org.broadinstitute.gatk.engine.refdata.utils.RMDTriplet;
+import org.broadinstitute.gatk.utils.GenomeLoc;
+import org.broadinstitute.gatk.utils.GenomeLocParser;
+import org.broadinstitute.gatk.utils.exceptions.ReviewedGATKException;
+
+import java.util.List;
+
+/**
+ * A pool of reference-ordered data iterators.
+ */
+class ReferenceOrderedDataPool extends ResourcePool<LocationAwareSeekableRODIterator, LocationAwareSeekableRODIterator> {
+    // the reference-ordered data itself.
+    private final RMDTriplet fileDescriptor;
+
+    // our tribble track builder
+    private final RMDTrackBuilder builder;
+
+    /**
+     * The header from this RMD, if present.
+     */
+    private final Object header;
+
+    /**
+     * The sequence dictionary from this ROD.  If no sequence dictionary is present, this dictionary will be the same as the reference's.
+     */
+    private final SAMSequenceDictionary sequenceDictionary;
+
+    boolean flashbackData = false;
+    public ReferenceOrderedDataPool(RMDTriplet fileDescriptor,RMDTrackBuilder builder,SAMSequenceDictionary sequenceDictionary, GenomeLocParser genomeLocParser,boolean flashbackData) {
+        super(sequenceDictionary,genomeLocParser);
+        this.fileDescriptor = fileDescriptor;
+        this.builder = builder;
+        this.flashbackData = flashbackData;
+
+        // prepopulate one RMDTrack
+        LocationAwareSeekableRODIterator iterator = createNewResource();
+        this.addNewResource(iterator);
+
+        // Pull the proper header and sequence dictionary from the prepopulated track.
+        this.header = iterator.getHeader();
+        this.sequenceDictionary = iterator.getSequenceDictionary();
+    }
+
+    /**
+     * Gets the header used by this resource pool.
+     * @return Header used by this resource pool.
+     */
+    public Object getHeader() {
+        return header;
+    }
+
+    /**
+     * Gets the sequence dictionary built into the ROD index file.
+     * @return Sequence dictionary from the index file.
+     */
+    public SAMSequenceDictionary getSequenceDictionary() {
+        return sequenceDictionary;
+    }
+
+    /**
+     * Create a new iterator from the existing reference-ordered data.  This new iterator is expected
+     * to be completely independent of any other iterator.
+     * @return The newly created resource.
+     */
+    public LocationAwareSeekableRODIterator createNewResource() {
+        if(numIterators() > 0)
+            throw new ReviewedGATKException("BUG: Tried to create multiple iterators over streaming ROD interface");
+        RMDTrack track = builder.createInstanceOfTrack(fileDescriptor);
+        LocationAwareSeekableRODIterator iter = new SeekableRODIterator(track.getHeader(),track.getSequenceDictionary(),referenceSequenceDictionary,genomeLocParser,track.getIterator());
+        return (flashbackData) ? new FlashBackIterator(iter) : iter;
+    }
+
+    /**
+     * Finds the best existing ROD iterator from the pool.  In this case, the best existing ROD is defined as
+     * the first one encountered that is at or before the given position.
+     * @param segment @{inheritedDoc}
+     * @param resources @{inheritedDoc}
+     * @return @{inheritedDoc}
+     */
+    public LocationAwareSeekableRODIterator selectBestExistingResource( DataStreamSegment segment, List<LocationAwareSeekableRODIterator> resources ) {
+        if(segment instanceof MappedStreamSegment) {
+            GenomeLoc position = ((MappedStreamSegment)segment).getLocation();
+
+            for( LocationAwareSeekableRODIterator RODIterator : resources ) {
+
+                if( (RODIterator.position() == null && RODIterator.hasNext()) ||
+                    (RODIterator.position() != null && RODIterator.position().isBefore(position)) )
+                    return RODIterator;
+                if (RODIterator.position() != null && RODIterator instanceof FlashBackIterator && ((FlashBackIterator)RODIterator).canFlashBackTo(position)) {
+                    ((FlashBackIterator)RODIterator).flashBackTo(position);
+                    return RODIterator;
+                }
+
+            }
+            return null;
+        }
+        else if(segment instanceof EntireStream) {
+            // Asking for a segment over the entire stream, so by definition, there is no best existing resource.
+            // Force the system to create a new one.
+            return null;
+        }
+        else {
+            throw new ReviewedGATKException("Unable to find a ROD iterator for segments of type " + segment.getClass());
+        }
+    }
+
+    /**
+     * In this case, the iterator is the resource.  Pass it through.
+     */
+    public LocationAwareSeekableRODIterator createIteratorFromResource( DataStreamSegment segment, LocationAwareSeekableRODIterator resource ) {
+        return resource;
+    }
+
+    /**
+     * kill the buffers in the iterator
+     */
+    public void closeResource( LocationAwareSeekableRODIterator resource ) {
+        if (resource instanceof FlashBackIterator) ((FlashBackIterator)resource).close();
+    }
+}
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/datasources/rmd/ReferenceOrderedDataSource.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/datasources/rmd/ReferenceOrderedDataSource.java
new file mode 100644
index 0000000..9d9e7c8
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/datasources/rmd/ReferenceOrderedDataSource.java
@@ -0,0 +1,256 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.engine.datasources.rmd;
+
+import htsjdk.samtools.SAMSequenceDictionary;
+import org.broadinstitute.gatk.utils.commandline.Tags;
+import org.broadinstitute.gatk.engine.refdata.SeekableRODIterator;
+import org.broadinstitute.gatk.engine.refdata.tracks.RMDTrack;
+import org.broadinstitute.gatk.engine.refdata.tracks.RMDTrackBuilder;
+import org.broadinstitute.gatk.engine.refdata.utils.LocationAwareSeekableRODIterator;
+import org.broadinstitute.gatk.engine.refdata.utils.RMDTriplet;
+import org.broadinstitute.gatk.utils.GenomeLoc;
+import org.broadinstitute.gatk.utils.GenomeLocParser;
+import org.broadinstitute.gatk.utils.exceptions.ReviewedGATKException;
+import org.broadinstitute.gatk.utils.exceptions.UserException;
+
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.lang.reflect.Type;
+import java.util.List;
+
+/**
+ * A data source which provides a single type of reference-ordered data.
+ */
+public class ReferenceOrderedDataSource {
+    /**
+     * The reference-ordered data itself.
+     */
+    private final RMDTriplet fileDescriptor;
+
+    /**
+     * The header associated with this VCF, if any.
+     */
+    private final Object header;
+
+    /**
+     * The private sequence dictionary associated with this RMD.
+     */
+    private final SAMSequenceDictionary sequenceDictionary;
+
+    /**
+     * The builder to use when constructing new reference-ordered data readers.
+     */
+    private final RMDTrackBuilder builder;
+
+    /**
+     * A pool of iterators for navigating through the genome.
+     */
+    private final ResourcePool<?,LocationAwareSeekableRODIterator> iteratorPool;
+
+    /**
+     * Create a new reference-ordered data source.
+     */
+    public ReferenceOrderedDataSource(RMDTriplet fileDescriptor,
+                                      RMDTrackBuilder builder,
+                                      SAMSequenceDictionary referenceSequenceDictionary,
+                                      GenomeLocParser genomeLocParser,
+                                      boolean flashbackData ) {
+        this.fileDescriptor = fileDescriptor;
+        this.builder = builder;
+
+        // TODO: Unify the two blocks of code below by creating a ReferenceOrderedDataPool base class of a coherent type (not RMDTrack for one and SeekableIterator for the other).
+        if (fileDescriptor.getStorageType() != RMDTriplet.RMDStorageType.STREAM) {
+            iteratorPool = new ReferenceOrderedQueryDataPool(fileDescriptor,
+                                                             builder,
+                                                             referenceSequenceDictionary,
+                                                             genomeLocParser);
+            this.header = ((ReferenceOrderedQueryDataPool)iteratorPool).getHeader();
+            this.sequenceDictionary = ((ReferenceOrderedQueryDataPool)iteratorPool).getSequenceDictionary();
+        }
+        else {
+            iteratorPool = new ReferenceOrderedDataPool(fileDescriptor,
+                                                        builder,
+                                                        referenceSequenceDictionary,
+                                                        genomeLocParser,
+                                                        flashbackData);
+            this.header = ((ReferenceOrderedDataPool)iteratorPool).getHeader();
+            this.sequenceDictionary = ((ReferenceOrderedDataPool)iteratorPool).getSequenceDictionary();
+        }
+    }
+
+    /**
+     * Return the name of the underlying reference-ordered data.
+     * @return Name of the underlying rod.
+     */
+    public String getName() {
+        return fileDescriptor.getName();
+    }
+
+    public Class getType() {
+        return builder.getFeatureManager().getByTriplet(fileDescriptor).getCodecClass();
+    }
+
+    public Class getRecordType() {
+        return builder.getFeatureManager().getByTriplet(fileDescriptor).getFeatureClass();
+    }
+
+    public File getFile() {
+        return new File(fileDescriptor.getFile());
+    }
+
+    public Object getHeader() {
+        return header;
+    }
+
+    public Tags getTags() {
+        return fileDescriptor.getTags();
+    }
+    
+    public String getTagValue( final String key ) {
+        return fileDescriptor.getTags().getValue( key );
+    }
+
+
+    /**
+     * Retrieves the sequence dictionary created by this ROD.
+     * @return
+     */
+    public SAMSequenceDictionary getSequenceDictionary() {
+        return sequenceDictionary;
+    }
+
+    /**
+     * helper function for determining if we are the same track based on name and record type
+     *
+     * @param name the name to match
+     * @param type the type to match
+     *
+     * @return true on a match, false if the name or type is different
+     */
+    public boolean matchesNameAndRecordType(String name, Type type) {
+        return (name.equals(fileDescriptor.getName()) && (type.getClass().isAssignableFrom(getType().getClass())));
+    }
+
+    /**
+     * Seek to the specified position and return an iterator through the data.
+     *
+     * @param loc GenomeLoc that points to the selected position.
+     *
+     * @return Iterator through the data.
+     */
+    public LocationAwareSeekableRODIterator seek(GenomeLoc loc) {
+        DataStreamSegment dataStreamSegment = loc != null ? new MappedStreamSegment(loc) : new EntireStream();
+        return iteratorPool.iterator(dataStreamSegment);
+    }
+
+
+    /**
+     * Close the specified iterator, returning it to the pool.
+     * @param iterator Iterator to close.
+     */
+    public void close( LocationAwareSeekableRODIterator iterator ) {
+        iteratorPool.release(iterator);
+    }
+
+}
+
+/**
+ * a data pool for the new query based RODs
+ */
+class ReferenceOrderedQueryDataPool extends ResourcePool<RMDTrack,LocationAwareSeekableRODIterator> {
+    // the reference-ordered data itself.
+    private final RMDTriplet fileDescriptor;
+
+    // our tribble track builder
+    private final RMDTrackBuilder builder;
+
+    /**
+     * The header from this RMD, if present.
+     */
+    private final Object header;
+
+    /**
+     * The sequence dictionary from this ROD.  If no sequence dictionary is present, this dictionary will be the same as the reference's.
+     */
+    private final SAMSequenceDictionary sequenceDictionary;
+
+    public ReferenceOrderedQueryDataPool(RMDTriplet fileDescriptor, RMDTrackBuilder builder, SAMSequenceDictionary referenceSequenceDictionary, GenomeLocParser genomeLocParser) {
+        super(referenceSequenceDictionary,genomeLocParser);
+        this.fileDescriptor = fileDescriptor;
+        this.builder = builder;
+
+        // prepopulate one RMDTrack
+        RMDTrack track = builder.createInstanceOfTrack(fileDescriptor);
+        this.addNewResource(track);
+
+        // Pull the proper header and sequence dictionary from the prepopulated track.
+        this.header = track.getHeader();
+        this.sequenceDictionary = track.getSequenceDictionary();
+    }
+
+    public Object getHeader() {
+        return header;
+    }
+
+    public SAMSequenceDictionary getSequenceDictionary() {
+        return sequenceDictionary;
+    }
+
+    @Override
+    protected RMDTrack createNewResource() {
+        return builder.createInstanceOfTrack(fileDescriptor);
+    }
+
+    @Override
+    protected RMDTrack selectBestExistingResource(DataStreamSegment segment, List<RMDTrack> availableResources) {
+        for (RMDTrack reader : availableResources)
+            if (reader != null) return reader;
+        return null;
+    }
+
+    @Override
+    protected LocationAwareSeekableRODIterator createIteratorFromResource(DataStreamSegment position, RMDTrack track) {
+        try {
+            if (position instanceof MappedStreamSegment) {
+                GenomeLoc pos = ((MappedStreamSegment) position).locus;
+                return new SeekableRODIterator(header,sequenceDictionary,referenceSequenceDictionary,genomeLocParser,track.query(pos));
+            } else {
+                return new SeekableRODIterator(header,sequenceDictionary,referenceSequenceDictionary,genomeLocParser,track.getIterator());
+            }
+        } catch (FileNotFoundException e) {
+            throw new UserException.CouldNotReadInputFile(fileDescriptor.getName(), "it could not be found");
+        } catch (IOException e) {
+            throw new ReviewedGATKException("Unable to create iterator for rod named " + fileDescriptor.getName(),e);
+        }
+    }
+
+    @Override
+    protected void closeResource(RMDTrack track) {
+        track.close();
+    }
+}
\ No newline at end of file
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/datasources/rmd/ResourcePool.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/datasources/rmd/ResourcePool.java
new file mode 100644
index 0000000..7d6e9c0
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/datasources/rmd/ResourcePool.java
@@ -0,0 +1,188 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.engine.datasources.rmd;
+
+import htsjdk.samtools.SAMSequenceDictionary;
+import htsjdk.samtools.util.CloseableIterator;
+import org.broadinstitute.gatk.utils.GenomeLocParser;
+import org.broadinstitute.gatk.utils.exceptions.ReviewedGATKException;
+
+import java.util.*;
+
+/**
+ * A pool of open resources, all of which can create a closeable iterator.
+ */
+abstract class ResourcePool <T,I extends CloseableIterator> {
+    /**
+     * Sequence dictionary.
+     */
+    protected final SAMSequenceDictionary referenceSequenceDictionary;
+
+    /**
+     * Builder/parser for GenomeLocs.
+     */
+    protected final GenomeLocParser genomeLocParser;
+
+    /**
+     * All iterators of this reference-ordered data.
+     */
+    private List<T> allResources = new ArrayList<T>();
+
+    /**
+     * All iterators that are not currently in service.
+     */
+    private List<T> availableResources = new ArrayList<T>();
+
+    /**
+     * Which iterators are assigned to which pools.
+     */
+    private Map<I,T> resourceAssignments = new HashMap<I,T>();
+
+    protected ResourcePool(SAMSequenceDictionary referenceSequenceDictionary,GenomeLocParser genomeLocParser) {
+        this.referenceSequenceDictionary = referenceSequenceDictionary;
+        this.genomeLocParser = genomeLocParser;
+    }
+
+    /**
+     * Get an iterator whose position is before the specified location.  Create a new one if none exists.
+     * @param segment Target position for the iterator.
+     * @return An iterator that can traverse the selected region.  Should be able to iterate concurrently with other
+     *         iterators from tihs pool.
+     */
+    public I iterator( DataStreamSegment segment ) {
+        // Grab the first iterator in the list whose position is before the requested position.
+        T selectedResource = null;
+        synchronized (this) {
+            selectedResource = selectBestExistingResource(segment, availableResources);
+
+            // No iterator found?  Create another.  It is expected that
+            // each iterator created will have its own file handle.
+            if (selectedResource == null) {
+                selectedResource = createNewResource();
+                addNewResource(selectedResource);
+            }
+
+            // Remove the iterator from the list of available iterators.
+            availableResources.remove(selectedResource);
+        }
+
+
+        I iterator = createIteratorFromResource(segment, selectedResource);
+
+        // also protect the resource assignment
+        synchronized (this) {
+            // Make a note of this assignment for proper releasing later.
+            resourceAssignments.put(iterator, selectedResource);
+        }
+
+        return iterator;
+    }
+
+    /**
+     * Release the lock on the given iterator, returning it to the pool.
+     * @param iterator Iterator to return to the pool.
+     */
+    public void release( I iterator ) {
+        synchronized(this) {
+            // Find and remove the resource from the list of allocated resources.
+            T resource = resourceAssignments.get( iterator );
+            Object obj = resourceAssignments.remove(iterator);
+
+            // Close the iterator.
+            iterator.close();
+
+            // make sure we actually removed the assignment
+            if (obj == null)
+                    throw new ReviewedGATKException("Failed to remove resource assignment; target key had no associated value in the resource assignment map");
+            // Return the resource to the pool.
+            if( !allResources.contains(resource) )
+                throw new ReviewedGATKException("Iterator does not belong to the given pool.");
+            availableResources.add(resource);
+        }
+    }
+
+    /**
+     * Add a resource to the list of available resources.  Useful if derived classes
+     * want to seed the pool with a set of at a given time (like at initialization).
+     * @param resource The new resource to add.
+     */
+    protected void addNewResource( T resource ) {
+        synchronized(this) {
+            allResources.add(resource);
+            availableResources.add(resource);
+        }
+    }
+
+    /**
+     * If no appropriate resources are found in the pool, the system can create a new resource.
+     * Delegate the creation of the resource to the subclass.
+     * @return The new resource created.
+     */
+    protected abstract T createNewResource();
+
+    /**
+     * Find the most appropriate resource to acquire the specified data.
+     * @param segment The data over which the resource is required.
+     * @param availableResources A list of candidate resources to evaluate.
+     * @return The best choice of the availableResources, or null if no resource meets the criteria.
+     */
+    protected abstract T selectBestExistingResource( DataStreamSegment segment, List<T> availableResources );
+
+    /**
+     * Create an iterator over the specified resource.
+     * @param position The bounds of iteration.  The first element of the iterator through the last element should all
+     *                 be in the range described by position.
+     * @param resource The resource from which to derive the iterator.
+     * @return A new iterator over the given data.
+     */
+    protected abstract I createIteratorFromResource( DataStreamSegment position, T resource );
+
+    /**
+     * Retire this resource from service.
+     * @param resource The resource to retire.
+     */
+    protected abstract void closeResource(T resource);
+
+    /**
+     * Operating stats...get the number of total iterators.  Package-protected
+     * for unit testing.
+     * @return An integer number of total iterators.
+     */
+    int numIterators() {
+        return allResources.size();
+    }
+
+    /**
+     * Operating stats...get the number of available iterators.  Package-protected
+     * for unit testing.
+     * @return An integer number of available iterators.
+     */
+    int numAvailableIterators() {
+        return availableResources.size();
+    }
+
+}
+
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/datasources/rmd/package-info.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/datasources/rmd/package-info.java
new file mode 100644
index 0000000..41b7e53
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/datasources/rmd/package-info.java
@@ -0,0 +1,26 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.engine.datasources.rmd;
\ No newline at end of file
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/downsampling/AlleleBiasedDownsamplingUtils.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/downsampling/AlleleBiasedDownsamplingUtils.java
new file mode 100644
index 0000000..0bcf4ee
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/downsampling/AlleleBiasedDownsamplingUtils.java
@@ -0,0 +1,369 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.engine.downsampling;
+
+import org.apache.log4j.Logger;
+import org.broadinstitute.gatk.utils.BaseUtils;
+import org.broadinstitute.gatk.utils.MathUtils;
+import org.broadinstitute.gatk.utils.collections.DefaultHashMap;
+import org.broadinstitute.gatk.utils.exceptions.GATKException;
+import org.broadinstitute.gatk.utils.exceptions.UserException;
+import org.broadinstitute.gatk.utils.pileup.PileupElement;
+import org.broadinstitute.gatk.utils.pileup.ReadBackedPileup;
+import org.broadinstitute.gatk.utils.pileup.ReadBackedPileupImpl;
+import org.broadinstitute.gatk.utils.sam.GATKSAMRecord;
+import org.broadinstitute.gatk.utils.text.XReadLines;
+import htsjdk.variant.variantcontext.Allele;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.*;
+
+public class AlleleBiasedDownsamplingUtils {
+
+    // define this class so that we can use Java generics below
+    private final static class PileupElementList extends ArrayList<PileupElement> {}
+
+    /**
+     * Computes an allele biased version of the given pileup
+     *
+     * @param pileup                    the original pileup
+     * @param downsamplingFraction      the fraction of total reads to remove per allele
+     * @return allele biased pileup
+     */
+    public static ReadBackedPileup createAlleleBiasedBasePileup(final ReadBackedPileup pileup, final double downsamplingFraction) {
+        // special case removal of all or no reads
+        if ( downsamplingFraction <= 0.0 )
+            return pileup;
+        if ( downsamplingFraction >= 1.0 )
+            return new ReadBackedPileupImpl(pileup.getLocation(), new ArrayList<PileupElement>());
+
+        final PileupElementList[] alleleStratifiedElements = new PileupElementList[4];
+        for ( int i = 0; i < 4; i++ )
+            alleleStratifiedElements[i] = new PileupElementList();
+
+        // start by stratifying the reads by the alleles they represent at this position
+        for ( final PileupElement pe : pileup ) {
+            final int baseIndex = BaseUtils.simpleBaseToBaseIndex(pe.getBase());
+            if ( baseIndex != -1 )
+                alleleStratifiedElements[baseIndex].add(pe);
+        }
+
+        // make a listing of allele counts and calculate the total count
+        final int[] alleleCounts = calculateAlleleCounts(alleleStratifiedElements);
+        final int totalAlleleCount = (int)MathUtils.sum(alleleCounts);
+
+        // do smart down-sampling
+        final int numReadsToRemove = (int)(totalAlleleCount * downsamplingFraction); // floor
+        final int[] targetAlleleCounts = runSmartDownsampling(alleleCounts, numReadsToRemove);
+
+        final HashSet<PileupElement> readsToRemove = new HashSet<PileupElement>(numReadsToRemove);
+        for ( int i = 0; i < 4; i++ ) {
+            final PileupElementList alleleList = alleleStratifiedElements[i];
+            // if we don't need to remove any reads, then don't
+            if ( alleleCounts[i] > targetAlleleCounts[i] )
+                readsToRemove.addAll(downsampleElements(alleleList, alleleCounts[i], alleleCounts[i] - targetAlleleCounts[i]));
+        }
+
+        // we need to keep the reads sorted because the FragmentUtils code will expect them in coordinate order and will fail otherwise
+        final List<PileupElement> readsToKeep = new ArrayList<PileupElement>(totalAlleleCount - numReadsToRemove);
+        for ( final PileupElement pe : pileup ) {
+            if ( !readsToRemove.contains(pe) ) {
+                readsToKeep.add(pe);
+            }
+        }
+
+        return new ReadBackedPileupImpl(pileup.getLocation(), new ArrayList<PileupElement>(readsToKeep));
+    }
+
+    /**
+     * Calculates actual allele counts for each allele (which can be different than the list size when reduced reads are present)
+     *
+     * @param alleleStratifiedElements       pileup elements stratified by allele
+     * @return non-null int array representing allele counts
+     */
+    private static int[] calculateAlleleCounts(final PileupElementList[] alleleStratifiedElements) {
+        final int[] alleleCounts = new int[alleleStratifiedElements.length];
+        for ( int i = 0; i < alleleStratifiedElements.length; i++ ) {
+            alleleCounts[i] = alleleStratifiedElements[i].size();
+        }
+        return alleleCounts;
+    }
+
+    private static int scoreAlleleCounts(final int[] alleleCounts) {
+        if ( alleleCounts.length < 2 )
+            return 0;
+
+        // sort the counts (in ascending order)
+        final int[] alleleCountsCopy = alleleCounts.clone();
+        Arrays.sort(alleleCountsCopy);
+
+        final int maxCount = alleleCountsCopy[alleleCounts.length - 1];
+        final int nextBestCount = alleleCountsCopy[alleleCounts.length - 2];
+
+        int remainderCount = 0;
+        for ( int i = 0; i < alleleCounts.length - 2; i++ )
+            remainderCount += alleleCountsCopy[i];
+
+        // try to get the best score:
+        //    - in the het case the counts should be equal with nothing else
+        //    - in the hom case the non-max should be zero
+        return Math.min(maxCount - nextBestCount + remainderCount, Math.abs(nextBestCount + remainderCount));
+    }
+
+    /**
+     * Computes an allele biased version of the allele counts for a given pileup
+     *
+     * @param alleleCounts              the allele counts for the original pileup
+     * @param numReadsToRemove          number of total reads to remove per allele
+     * @return non-null array of new counts needed per allele
+     */
+    protected static int[] runSmartDownsampling(final int[] alleleCounts, final int numReadsToRemove) {
+        final int numAlleles = alleleCounts.length;
+
+        int maxScore = scoreAlleleCounts(alleleCounts);
+        int[] alleleCountsOfMax = alleleCounts;
+
+        final int numReadsToRemovePerAllele = numReadsToRemove / 2;
+
+        for ( int i = 0; i < numAlleles; i++ ) {
+            for ( int j = i; j < numAlleles; j++ ) {
+                final int[] newCounts = alleleCounts.clone();
+
+                // split these cases so we don't lose on the floor (since we divided by 2)
+                if ( i == j ) {
+                    newCounts[i] = Math.max(0, newCounts[i] - numReadsToRemove);
+                } else {
+                    newCounts[i] = Math.max(0, newCounts[i] - numReadsToRemovePerAllele);
+                    newCounts[j] = Math.max(0, newCounts[j] - numReadsToRemovePerAllele);
+                }
+
+                final int score = scoreAlleleCounts(newCounts);
+
+                if ( score < maxScore ) {
+                    maxScore = score;
+                    alleleCountsOfMax = newCounts;
+                }
+            }
+        }
+
+        return alleleCountsOfMax;
+    }
+
+    /**
+     * Performs allele biased down-sampling on a pileup and computes the list of elements to remove
+     *
+     * @param elements                  original list of pileup elements
+     * @param originalElementCount      original count of elements (taking reduced reads into account)
+     * @param numElementsToRemove       the number of records to remove
+     * @return the list of pileup elements TO REMOVE
+     */
+    protected static List<PileupElement> downsampleElements(final List<PileupElement> elements, final int originalElementCount, final int numElementsToRemove) {
+        // are there no elements to remove?
+        if ( numElementsToRemove == 0 )
+            return Collections.<PileupElement>emptyList();
+
+        final ArrayList<PileupElement> elementsToRemove = new ArrayList<PileupElement>(numElementsToRemove);
+
+        // should we remove all of the elements?
+        if ( numElementsToRemove >= originalElementCount ) {
+            elementsToRemove.addAll(elements);
+            return elementsToRemove;
+        }
+
+        // create a bitset describing which elements to remove
+        final BitSet itemsToRemove = new BitSet(originalElementCount);
+        for ( final Integer selectedIndex : MathUtils.sampleIndicesWithoutReplacement(originalElementCount, numElementsToRemove) ) {
+            itemsToRemove.set(selectedIndex);
+        }
+
+        int currentBitSetIndex = 0;
+        for ( final PileupElement element : elements ) {
+            if ( itemsToRemove.get(currentBitSetIndex++) ) {
+                elementsToRemove.add(element);
+            }
+        }
+
+        return elementsToRemove;
+    }
+
+    /**
+     * Computes reads to remove based on an allele biased down-sampling
+     *
+     * @param alleleReadMap             original list of records per allele
+     * @param downsamplingFraction      the fraction of total reads to remove per allele
+     * @return list of reads TO REMOVE from allele biased down-sampling
+     */
+    public static <A extends Allele> List<GATKSAMRecord> selectAlleleBiasedReads(final Map<A, List<GATKSAMRecord>> alleleReadMap, final double downsamplingFraction) {
+        int totalReads = 0;
+        for ( final List<GATKSAMRecord> reads : alleleReadMap.values() )
+            totalReads += reads.size();
+
+        int numReadsToRemove = (int)(totalReads * downsamplingFraction);
+
+        // make a listing of allele counts
+        final List<Allele> alleles = new ArrayList<Allele>(alleleReadMap.keySet());
+        alleles.remove(Allele.NO_CALL);    // ignore the no-call bin
+        final int numAlleles = alleles.size();
+
+        final int[] alleleCounts = new int[numAlleles];
+        for ( int i = 0; i < numAlleles; i++ )
+            alleleCounts[i] = alleleReadMap.get(alleles.get(i)).size();
+
+        // do smart down-sampling
+        final int[] targetAlleleCounts = runSmartDownsampling(alleleCounts, numReadsToRemove);
+
+        final List<GATKSAMRecord> readsToRemove = new ArrayList<GATKSAMRecord>(numReadsToRemove);
+        for ( int i = 0; i < numAlleles; i++ ) {
+            if ( alleleCounts[i] > targetAlleleCounts[i] ) {
+                readsToRemove.addAll(downsampleElements(alleleReadMap.get(alleles.get(i)), alleleCounts[i] - targetAlleleCounts[i]));
+            }
+        }
+
+        return readsToRemove;
+    }
+
+    /**
+     * Performs allele biased down-sampling on a pileup and computes the list of elements to remove
+     *
+     * @param reads                     original list of records
+     * @param numElementsToRemove       the number of records to remove
+     * @return the list of pileup elements TO REMOVE
+     */
+    protected static List<GATKSAMRecord> downsampleElements(final List<GATKSAMRecord> reads, final int numElementsToRemove) {
+        // are there no elements to remove?
+        if ( numElementsToRemove == 0 )
+            return Collections.<GATKSAMRecord>emptyList();
+
+        final ArrayList<GATKSAMRecord> elementsToRemove = new ArrayList<GATKSAMRecord>(numElementsToRemove);
+        final int originalElementCount = reads.size();
+
+        // should we remove all of the elements?
+        if ( numElementsToRemove >= originalElementCount ) {
+            elementsToRemove.addAll(reads);
+            return elementsToRemove;
+        }
+
+        // create a bitset describing which elements to remove
+        final BitSet itemsToRemove = new BitSet(originalElementCount);
+        for ( final Integer selectedIndex : MathUtils.sampleIndicesWithoutReplacement(originalElementCount, numElementsToRemove) ) {
+            itemsToRemove.set(selectedIndex);
+        }
+
+        int currentBitSetIndex = 0;
+        for ( final GATKSAMRecord read : reads ) {
+            if ( itemsToRemove.get(currentBitSetIndex++) )
+                elementsToRemove.add(read);
+        }
+
+        return elementsToRemove;
+    }
+
+    /**
+     * Create sample-contamination maps from file
+     *
+     * @param ContaminationFractionFile   Filename containing two columns: SampleID and Contamination
+     * @param AvailableSampleIDs          Set of Samples of interest (no reason to include every sample in file) or null to turn off checking
+     * @param logger                      for logging output
+     * @return sample-contamination Map
+     */
+
+    public static DefaultHashMap<String, Double> loadContaminationFile(File ContaminationFractionFile, final Double defaultContaminationFraction, final Set<String> AvailableSampleIDs, Logger logger) throws GATKException {
+        DefaultHashMap<String, Double> sampleContamination = new DefaultHashMap<String, Double>(defaultContaminationFraction);
+        Set<String> nonSamplesInContaminationFile = new HashSet<String>(sampleContamination.keySet());
+        try {
+
+            XReadLines reader = new XReadLines(ContaminationFractionFile, true);
+            for (String line : reader) {
+
+                if (line.length() == 0) {
+                    continue;
+                }
+
+                StringTokenizer st = new StringTokenizer(line,"\t");
+
+                String fields[] = new String[2];
+                try {
+                    fields[0] = st.nextToken();
+                    fields[1] = st.nextToken();
+                } catch(NoSuchElementException e){
+                    throw new UserException.MalformedFile("Contamination file must have exactly two, tab-delimited columns. Offending line:\n" + line);
+                }
+                if(st.hasMoreTokens()) {
+                    throw new UserException.MalformedFile("Contamination file must have exactly two, tab-delimited columns. Offending line:\n" + line);
+                }
+
+                if (fields[0].length() == 0 || fields[1].length() == 0) {
+                    throw new UserException.MalformedFile("Contamination file can not have empty strings in either column. Offending line:\n" + line);
+                }
+
+                if (sampleContamination.containsKey(fields[0])) {
+                    throw new UserException.MalformedFile("Contamination file contains duplicate entries for input name " + fields[0]);
+                }
+
+                try {
+                    final Double contamination = Double.valueOf(fields[1]);
+                    if (contamination < 0 || contamination > 1){
+                        throw new UserException.MalformedFile("Contamination file contains unacceptable contamination value (must be 0<=x<=1): " + line);
+                    }
+                    if (AvailableSampleIDs==null || AvailableSampleIDs.contains(fields[0])) {// only add samples if they are in the sampleSet (or if it is null)
+                        sampleContamination.put(fields[0], contamination);
+                    }
+                    else {
+                        nonSamplesInContaminationFile.add(fields[0]);
+                    }
+                } catch (NumberFormatException e) {
+                    throw new UserException.MalformedFile("Contamination file contains unparsable double in the second field. Offending line: " + line);
+                }
+            }
+
+
+            //output to the user info lines telling which samples are in the Contamination File
+            if (sampleContamination.size() > 0) {
+                logger.info(String.format("The following samples were found in the Contamination file and will be processed at the contamination level therein: %s", sampleContamination.keySet().toString()));
+
+                //output to the user info lines telling which samples are NOT in the Contamination File
+                if(AvailableSampleIDs!=null){
+                    Set<String> samplesNotInContaminationFile = new HashSet<String>(AvailableSampleIDs);
+                    samplesNotInContaminationFile.removeAll(sampleContamination.keySet());
+                    if (samplesNotInContaminationFile.size() > 0)
+                        logger.info(String.format("The following samples were NOT found in the Contamination file and will be processed at the default contamination level: %s", samplesNotInContaminationFile.toString()));
+                }
+            }
+
+            //output to the user Samples that do not have lines in the Contamination File
+            if (nonSamplesInContaminationFile.size() > 0) {
+                logger.info(String.format("The following entries were found in the Contamination file but were not SAMPLEIDs. They will be ignored: %s", nonSamplesInContaminationFile.toString()));
+            }
+
+            return sampleContamination;
+
+        } catch (IOException e) {
+            throw new GATKException("I/O Error while reading sample-contamination file " + ContaminationFractionFile.getName() + ": " + e.getMessage());
+        }
+
+    }
+}
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/downsampling/DownsampleType.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/downsampling/DownsampleType.java
new file mode 100644
index 0000000..715ef6e
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/downsampling/DownsampleType.java
@@ -0,0 +1,39 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.engine.downsampling;
+
+/**
+ * Type of downsampling method to invoke.
+ *
+ * @author hanna
+ * @version 0.1
+ */
+
+public enum DownsampleType {
+    NONE,
+    ALL_READS,
+    BY_SAMPLE
+}
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/downsampling/Downsampler.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/downsampling/Downsampler.java
new file mode 100644
index 0000000..8ab0198
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/downsampling/Downsampler.java
@@ -0,0 +1,161 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.engine.downsampling;
+
+import java.util.Collection;
+import java.util.List;
+
+/**
+ * The basic downsampler API, with no reads-specific operations.
+ *
+ * Downsamplers that extend this class rather than the ReadsDownsampler class can handle
+ * any kind of item, however they cannot be wrapped within a DownsamplingReadsIterator or a
+ * PerSampleDownsamplingReadsIterator.
+ *
+ * @author David Roazen
+ */
+public abstract class Downsampler<T> {
+
+    /**
+     * Number of items discarded by this downsampler since the last call to resetStats()
+     */
+    protected int numDiscardedItems = 0;
+
+    /**
+     * Submit one item to the downsampler for consideration. Some downsamplers will be able to determine
+     * immediately whether the item survives the downsampling process, while others will need to see
+     * more items before making that determination.
+     *
+     * @param item the individual item to submit to the downsampler for consideration
+     */
+    public abstract void submit( final T item );
+
+    /**
+     * Submit a collection of items to the downsampler for consideration. Should be equivalent to calling
+     * submit() on each individual item in the collection.
+     *
+     * @param items the collection of items to submit to the downsampler for consideration
+     */
+    public void submit( final Collection<T> items ) {
+        if ( items == null ) {
+            throw new IllegalArgumentException("submitted items must not be null");
+        }
+
+        for ( final T item : items ) {
+            submit(item);
+        }
+    }
+
+    /**
+     * Are there items that have survived the downsampling process waiting to be retrieved?
+     *
+     * @return true if this downsampler has > 0 finalized items, otherwise false
+     */
+    public abstract boolean hasFinalizedItems();
+
+    /**
+     * Return (and *remove*) all items that have survived downsampling and are waiting to be retrieved.
+     *
+     * @return a list of all finalized items this downsampler contains, or an empty list if there are none
+     */
+    public abstract List<T> consumeFinalizedItems();
+
+    /**
+     * Are there items stored in this downsampler that it doesn't yet know whether they will
+     * ultimately survive the downsampling process?
+     *
+     * @return true if this downsampler has > 0 pending items, otherwise false
+     */
+    public abstract boolean hasPendingItems();
+
+    /**
+     * Peek at the first finalized item stored in this downsampler (or null if there are no finalized items)
+     *
+     * @return the first finalized item in this downsampler (the item is not removed from the downsampler by this call),
+     *         or null if there are none
+     */
+    public abstract T peekFinalized();
+
+    /**
+     * Peek at the first pending item stored in this downsampler (or null if there are no pending items)
+     *
+     * @return the first pending item stored in this downsampler (the item is not removed from the downsampler by this call),
+     *         or null if there are none
+     */
+    public abstract T peekPending();
+
+    /**
+     * Get the current number of items in this downsampler
+     *
+     * This should be the best estimate of the total number of elements that will come out of the downsampler
+     * were consumeFinalizedItems() to be called immediately after this call.  In other words it should
+     * be number of finalized items + estimate of number of pending items that will ultimately be included as well.
+     *
+     * @return a positive integer
+     */
+    public abstract int size();
+
+    /**
+     * Returns the number of items discarded (so far) during the downsampling process
+     *
+     * @return the number of items that have been submitted to this downsampler and discarded in the process of
+     *         downsampling
+     */
+    public int getNumberOfDiscardedItems() {
+        return numDiscardedItems;
+    }
+
+    /**
+     * Used to tell the downsampler that no more items will be submitted to it, and that it should
+     * finalize any pending items.
+     */
+    public abstract void signalEndOfInput();
+
+    /**
+     * Empty the downsampler of all finalized/pending items
+     */
+    public abstract void clearItems();
+
+    /**
+     * Reset stats in the downsampler such as the number of discarded items *without* clearing the downsampler of items
+     */
+    public void resetStats() {
+        numDiscardedItems = 0;
+    }
+
+    /**
+     * Indicates whether an item should be excluded from elimination during downsampling. By default,
+     * all items representing reduced reads are excluded from downsampling, but individual downsamplers
+     * may override if they are able to handle reduced reads correctly. Downsamplers should check
+     * the return value of this method before discarding an item.
+     *
+     * @param item The item to test
+     * @return true if the item should not be subject to elimination during downsampling, otherwise false
+     */
+    protected boolean doNotDiscardItem( final Object item ) {
+        return false;
+    }
+}
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/downsampling/DownsamplingMethod.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/downsampling/DownsamplingMethod.java
new file mode 100644
index 0000000..94a3cc7
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/downsampling/DownsamplingMethod.java
@@ -0,0 +1,142 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.engine.downsampling;
+
+import org.broadinstitute.gatk.engine.walkers.ActiveRegionWalker;
+import org.broadinstitute.gatk.engine.walkers.LocusWalker;
+import org.broadinstitute.gatk.engine.walkers.Walker;
+import org.broadinstitute.gatk.utils.exceptions.UserException;
+
+/**
+ * Describes the method for downsampling reads at a given locus.
+ */
+
+public class DownsamplingMethod {
+    /**
+     * Type of downsampling to perform.
+     */
+    public final DownsampleType type;
+
+    /**
+     * Actual downsampling target is specified as an integer number of reads.
+     */
+    public final Integer toCoverage;
+
+    /**
+     * Actual downsampling target is specified as a fraction of total available reads.
+     */
+    public final Double toFraction;
+
+    /**
+     * Expresses no downsampling applied at all.
+     */
+    public static final DownsamplingMethod NONE = new DownsamplingMethod(DownsampleType.NONE, null, null);
+
+    /**
+     * Default type to use if no type is specified
+     */
+    public static final DownsampleType DEFAULT_DOWNSAMPLING_TYPE = DownsampleType.BY_SAMPLE;
+
+    /**
+     * Don't allow dcov values below this threshold for locus-based traversals (ie., Locus
+     * and ActiveRegion walkers), as they can result in problematic downsampling artifacts
+     */
+    public static final int MINIMUM_SAFE_COVERAGE_TARGET_FOR_LOCUS_BASED_TRAVERSALS = 200;
+
+
+    public DownsamplingMethod( DownsampleType type, Integer toCoverage, Double toFraction ) {
+        this.type = type != null ? type : DEFAULT_DOWNSAMPLING_TYPE;
+
+        if ( type == DownsampleType.NONE ) {
+            this.toCoverage = null;
+            this.toFraction = null;
+        }
+        else {
+            this.toCoverage = toCoverage;
+            this.toFraction = toFraction;
+        }
+
+        validate();
+    }
+
+    private void validate() {
+        // Can't leave toFraction and toCoverage null unless type is NONE
+        if ( type != DownsampleType.NONE && toFraction == null && toCoverage == null )
+            throw new UserException("Must specify either toFraction or toCoverage when downsampling.");
+
+        // Fraction and coverage cannot both be specified.
+        if ( toFraction != null && toCoverage != null )
+            throw new UserException("Downsampling coverage and fraction are both specified. Please choose only one.");
+
+        // toCoverage must be > 0 when specified
+        if ( toCoverage != null && toCoverage <= 0 ) {
+            throw new UserException("toCoverage must be > 0 when downsampling to coverage");
+        }
+
+        // toFraction must be >= 0.0 and <= 1.0 when specified
+        if ( toFraction != null && (toFraction < 0.0 || toFraction > 1.0) ) {
+            throw new UserException("toFraction must be >= 0.0 and <= 1.0 when downsampling to a fraction of reads");
+        }
+    }
+
+    public void checkCompatibilityWithWalker( Walker walker ) {
+        boolean isLocusTraversal = walker instanceof LocusWalker || walker instanceof ActiveRegionWalker;
+
+        if ( isLocusTraversal && type == DownsampleType.ALL_READS && toCoverage != null ) {
+            throw new UserException("Downsampling to coverage with the ALL_READS method for locus-based traversals (eg., LocusWalkers) is not currently supported (though it is supported for ReadWalkers).");
+        }
+
+        // For locus traversals, ensure that the dcov value (if present) is not problematically low
+        if ( isLocusTraversal && type != DownsampleType.NONE && toCoverage != null &&
+             toCoverage < MINIMUM_SAFE_COVERAGE_TARGET_FOR_LOCUS_BASED_TRAVERSALS ) {
+            throw new UserException(String.format("Locus-based traversals (ie., Locus and ActiveRegion walkers) require " +
+                                                  "a minimum -dcov value of %d when downsampling to coverage. Values less " +
+                                                  "than this can produce problematic downsampling artifacts while providing " +
+                                                  "only insignificant improvements in memory usage in most cases.",
+                                                  MINIMUM_SAFE_COVERAGE_TARGET_FOR_LOCUS_BASED_TRAVERSALS));
+        }
+    }
+
+    public String toString() {
+        StringBuilder builder = new StringBuilder("Downsampling Settings: ");
+
+        if ( type == DownsampleType.NONE ) {
+            builder.append("No downsampling");
+        }
+        else {
+            builder.append(String.format("Method: %s, ", type));
+
+            if ( toCoverage != null ) {
+                builder.append(String.format("Target Coverage: %d", toCoverage));
+            }
+            else {
+                builder.append(String.format("Target Fraction: %.2f", toFraction));
+            }
+        }
+
+        return builder.toString();
+    }
+}
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/downsampling/DownsamplingReadsIterator.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/downsampling/DownsamplingReadsIterator.java
new file mode 100644
index 0000000..6b398ab
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/downsampling/DownsamplingReadsIterator.java
@@ -0,0 +1,116 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.engine.downsampling;
+
+import htsjdk.samtools.SAMRecord;
+import org.broadinstitute.gatk.engine.iterators.GATKSAMIterator;
+
+import java.util.Collection;
+import java.util.Iterator;
+import java.util.NoSuchElementException;
+
+
+/**
+ * GATKSAMIterator wrapper around our generic reads downsampler interface. Converts the push-style
+ * downsampler interface to a pull model.
+ *
+ * @author David Roazen
+ */
+public class DownsamplingReadsIterator implements GATKSAMIterator {
+
+    private GATKSAMIterator nestedSAMIterator;
+    private ReadsDownsampler<SAMRecord> downsampler;
+    private Collection<SAMRecord> downsampledReadsCache;
+    private SAMRecord nextRead = null;
+    private Iterator<SAMRecord> downsampledReadsCacheIterator = null;
+
+    /**
+     * @param iter wrapped iterator from which this iterator will pull reads
+     * @param downsampler downsampler through which the reads will be fed
+     */
+    public DownsamplingReadsIterator( GATKSAMIterator iter, ReadsDownsampler<SAMRecord> downsampler ) {
+        nestedSAMIterator = iter;
+        this.downsampler = downsampler;
+
+        advanceToNextRead();
+    }
+
+    public boolean hasNext() {
+        return nextRead != null;
+    }
+
+    public SAMRecord next() {
+        if ( nextRead == null ) {
+            throw new NoSuchElementException("next() called when there are no more items");
+        }
+
+        SAMRecord toReturn = nextRead;
+        advanceToNextRead();
+
+        return toReturn;
+    }
+
+    private void advanceToNextRead() {
+        if ( ! readyToReleaseReads() && ! fillDownsampledReadsCache() ) {
+            nextRead = null;
+        }
+        else {
+            nextRead = downsampledReadsCacheIterator.next();
+        }
+    }
+
+    private boolean readyToReleaseReads() {
+        return downsampledReadsCacheIterator != null && downsampledReadsCacheIterator.hasNext();
+    }
+
+    private boolean fillDownsampledReadsCache() {
+        while ( nestedSAMIterator.hasNext() && ! downsampler.hasFinalizedItems() ) {
+            downsampler.submit(nestedSAMIterator.next());
+        }
+
+        if ( ! nestedSAMIterator.hasNext() ) {
+            downsampler.signalEndOfInput();
+        }
+
+        // use returned collection directly rather than make a copy, for speed
+        downsampledReadsCache = downsampler.consumeFinalizedItems();
+        downsampledReadsCacheIterator = downsampledReadsCache.iterator();
+
+        return downsampledReadsCacheIterator.hasNext();
+    }
+
+    public void remove() {
+        throw new UnsupportedOperationException("Can not remove records from a SAM file via an iterator!");
+    }
+
+    public void close() {
+        nestedSAMIterator.close();
+    }
+
+    public Iterator<SAMRecord> iterator() {
+        return this;
+    }
+}
\ No newline at end of file
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/downsampling/DownsamplingUtils.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/downsampling/DownsamplingUtils.java
new file mode 100644
index 0000000..bd236c0
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/downsampling/DownsamplingUtils.java
@@ -0,0 +1,107 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.engine.downsampling;
+
+import org.broadinstitute.gatk.utils.sam.GATKSAMRecord;
+import org.broadinstitute.gatk.utils.sam.ReadUtils;
+
+import java.util.*;
+
+/**
+ * Utilities for using the downsamplers for common tasks
+ *
+ * User: depristo
+ * Date: 3/6/13
+ * Time: 4:26 PM
+ */
+public class DownsamplingUtils {
+    private DownsamplingUtils() { }
+
+    /**
+     * Level the coverage of the reads in each sample to no more than downsampleTo reads, no reducing
+     * coverage at any read start to less than minReadsPerAlignmentStart
+     *
+     * This algorithm can be used to handle the situation where you have lots of coverage in some interval, and
+     * want to reduce the coverage of the big peak down without removing the many reads at the edge of this
+     * interval that are in fact good
+     *
+     * This algorithm separately operates on the reads for each sample independently.
+     *
+     * @param reads a sorted list of reads
+     * @param downsampleTo the targeted number of reads we want from reads per sample
+     * @param minReadsPerAlignmentStart don't reduce the number of reads starting at a specific alignment start
+     *                                  to below this.  That is, if this value is 2, we'll never reduce the number
+     *                                  of reads starting at a specific start site to less than 2
+     * @return a sorted list of reads
+     */
+    public static List<GATKSAMRecord> levelCoverageByPosition(final List<GATKSAMRecord> reads, final int downsampleTo, final int minReadsPerAlignmentStart) {
+        if ( reads == null ) throw new IllegalArgumentException("reads must not be null");
+
+        final List<GATKSAMRecord> downsampled = new ArrayList<GATKSAMRecord>(reads.size());
+
+        final Map<String, Map<Integer, List<GATKSAMRecord>>> readsBySampleByStart = partitionReadsBySampleAndStart(reads);
+        for ( final Map<Integer, List<GATKSAMRecord>> readsByPosMap : readsBySampleByStart.values() ) {
+            final LevelingDownsampler<List<GATKSAMRecord>, GATKSAMRecord> downsampler = new LevelingDownsampler<List<GATKSAMRecord>, GATKSAMRecord>(downsampleTo, minReadsPerAlignmentStart);
+            downsampler.submit(readsByPosMap.values());
+            downsampler.signalEndOfInput();
+            for ( final List<GATKSAMRecord> downsampledReads : downsampler.consumeFinalizedItems())
+                downsampled.addAll(downsampledReads);
+        }
+
+        return ReadUtils.sortReadsByCoordinate(downsampled);
+    }
+
+    /**
+     * Build the data structure mapping for each sample -> (position -> reads at position)
+     *
+     * Note that the map position -> reads isn't ordered in any meaningful way
+     *
+     * @param reads a list of sorted reads
+     * @return a map containing the list of reads at each start location, for each sample independently
+     */
+    private static Map<String, Map<Integer, List<GATKSAMRecord>>> partitionReadsBySampleAndStart(final List<GATKSAMRecord> reads) {
+        final Map<String, Map<Integer, List<GATKSAMRecord>>> readsBySampleByStart = new LinkedHashMap<String, Map<Integer, List<GATKSAMRecord>>>();
+
+        for ( final GATKSAMRecord read : reads ) {
+            Map<Integer, List<GATKSAMRecord>> readsByStart = readsBySampleByStart.get(read.getReadGroup().getSample());
+
+            if ( readsByStart == null ) {
+                readsByStart = new LinkedHashMap<Integer, List<GATKSAMRecord>>();
+                readsBySampleByStart.put(read.getReadGroup().getSample(), readsByStart);
+            }
+
+            List<GATKSAMRecord> readsAtStart = readsByStart.get(read.getAlignmentStart());
+            if ( readsAtStart == null ) {
+                readsAtStart = new LinkedList<GATKSAMRecord>();
+                readsByStart.put(read.getAlignmentStart(), readsAtStart);
+            }
+
+            readsAtStart.add(read);
+        }
+
+        return readsBySampleByStart;
+    }
+}
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/downsampling/FractionalDownsampler.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/downsampling/FractionalDownsampler.java
new file mode 100644
index 0000000..a2d613c
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/downsampling/FractionalDownsampler.java
@@ -0,0 +1,129 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.engine.downsampling;
+
+import htsjdk.samtools.SAMRecord;
+import org.broadinstitute.gatk.engine.GenomeAnalysisEngine;
+import org.broadinstitute.gatk.utils.exceptions.ReviewedGATKException;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Fractional Downsampler: selects a specified fraction of the reads for inclusion.
+ *
+ * Since the selection is done randomly, the actual fraction of reads retained may be slightly
+ * more or less than the requested fraction, depending on the total number of reads submitted.
+ *
+ * @author David Roazen
+ */
+public class FractionalDownsampler<T extends SAMRecord> extends ReadsDownsampler<T> {
+
+    private ArrayList<T> selectedReads;
+
+    private final int cutoffForInclusion;
+
+    private static final int RANDOM_POOL_SIZE = 10000;
+
+    /**
+     * Construct a FractionalDownsampler
+     *
+     * @param fraction Fraction of reads to preserve, between 0.0 (inclusive) and 1.0 (inclusive).
+     *                 Actual number of reads preserved may differ randomly.
+     */
+    public FractionalDownsampler( final double fraction ) {
+        if ( fraction < 0.0 || fraction > 1.0 ) {
+            throw new ReviewedGATKException("Fraction of reads to include must be between 0.0 and 1.0, inclusive");
+        }
+
+        cutoffForInclusion = (int)(fraction * RANDOM_POOL_SIZE);
+        clearItems();
+        resetStats();
+    }
+
+    @Override
+    public void submit( final T newRead ) {
+        if ( GenomeAnalysisEngine.getRandomGenerator().nextInt(10000) < cutoffForInclusion || doNotDiscardItem(newRead) ) {
+            selectedReads.add(newRead);
+        }
+        else {
+            numDiscardedItems++;
+        }
+    }
+
+    @Override
+    public boolean hasFinalizedItems() {
+        return selectedReads.size() > 0;
+    }
+
+    @Override
+    public List<T> consumeFinalizedItems() {
+        // pass by reference rather than make a copy, for speed
+        List<T> downsampledItems = selectedReads;
+        clearItems();
+        return downsampledItems;
+    }
+
+    @Override
+    public boolean hasPendingItems() {
+        return false;
+    }
+
+    @Override
+    public T peekFinalized() {
+        return selectedReads.isEmpty() ? null : selectedReads.get(0);
+    }
+
+    @Override
+    public T peekPending() {
+        return null;
+    }
+
+    @Override
+    public int size() {
+        return selectedReads.size();
+    }
+
+    @Override
+    public void signalEndOfInput() {
+        // NO-OP
+    }
+
+    @Override
+    public void clearItems() {
+        selectedReads = new ArrayList<T>();
+    }
+
+    @Override
+    public boolean requiresCoordinateSortOrder() {
+        return false;
+    }
+
+    @Override
+    public void signalNoMoreReadsBefore( final T read ) {
+        // NO-OP
+    }
+}
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/downsampling/FractionalDownsamplerFactory.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/downsampling/FractionalDownsamplerFactory.java
new file mode 100644
index 0000000..4ddf8dd
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/downsampling/FractionalDownsamplerFactory.java
@@ -0,0 +1,46 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.engine.downsampling;
+
+import htsjdk.samtools.SAMRecord;
+
+/**
+ * Factory for creating FractionalDownsamplers on demand
+ *
+ * @author David Roazen
+ */
+public class FractionalDownsamplerFactory<T extends SAMRecord> implements ReadsDownsamplerFactory<T> {
+
+    private double fraction;
+
+    public FractionalDownsamplerFactory( double fraction ) {
+        this.fraction = fraction;
+    }
+
+    public ReadsDownsampler<T> newInstance() {
+        return new FractionalDownsampler<T>(fraction);
+    }
+}
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/downsampling/LevelingDownsampler.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/downsampling/LevelingDownsampler.java
new file mode 100644
index 0000000..4ae7bc5
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/downsampling/LevelingDownsampler.java
@@ -0,0 +1,242 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.engine.downsampling;
+
+import org.broadinstitute.gatk.utils.MathUtils;
+
+import java.util.*;
+
+/**
+ * Leveling Downsampler: Given a set of Lists of arbitrary items and a target size, removes items from
+ * the Lists in an even fashion until the total size of all Lists is <= the target size. Leveling
+ * does not occur until all Lists have been submitted and signalEndOfInput() is called.
+ *
+ * The Lists should be LinkedLists for maximum efficiency during item removal, however other
+ * kinds of Lists are also accepted (albeit at a slight performance penalty).
+ *
+ * Since this downsampler extends the Downsampler interface rather than the ReadsDownsampler interface,
+ * the Lists need not contain reads. However this downsampler may not be wrapped within one of the
+ * DownsamplingReadsIterators
+ *
+ * @param <T> the List type representing the stacks to be leveled
+ * @param <E> the type of the elements of each List
+ *
+ * @author David Roazen
+ */
+public class LevelingDownsampler<T extends List<E>, E> extends Downsampler<T> {
+    private final int minElementsPerStack;
+
+    private final int targetSize;
+
+    private List<T> groups;
+
+    private boolean groupsAreFinalized;
+
+    /**
+     * Construct a LevelingDownsampler
+     *
+     * Uses the default minElementsPerStack of 1
+     *
+     * @param targetSize the sum of the sizes of all individual Lists this downsampler is fed may not exceed
+     *                   this value -- if it does, items are removed from Lists evenly until the total size
+     *                   is <= this value
+     */
+    public LevelingDownsampler( final int targetSize ) {
+        this(targetSize, 1);
+    }
+
+    /**
+     * Construct a LevelingDownsampler
+     *
+     * @param targetSize the sum of the sizes of all individual Lists this downsampler is fed may not exceed
+     *                   this value -- if it does, items are removed from Lists evenly until the total size
+     *                   is <= this value
+     * @param minElementsPerStack no stack will be reduced below this size during downsampling.  That is,
+     *                            if a stack has only 3 elements and minElementsPerStack is 3, no matter what
+     *                            we'll not reduce this stack below 3.
+     */
+    public LevelingDownsampler( final int targetSize, final int minElementsPerStack ) {
+        if ( targetSize < 0 ) throw new IllegalArgumentException("targetSize must be >= 0 but got " + targetSize);
+        if ( minElementsPerStack < 0 ) throw new IllegalArgumentException("minElementsPerStack must be >= 0 but got " + minElementsPerStack);
+
+        this.targetSize = targetSize;
+        this.minElementsPerStack = minElementsPerStack;
+        clearItems();
+        resetStats();
+    }
+
+    @Override
+    public void submit( final T item ) {
+        groups.add(item);
+    }
+
+    @Override
+    public void submit( final Collection<T> items ){
+        groups.addAll(items);
+    }
+
+    @Override
+    public boolean hasFinalizedItems() {
+        return groupsAreFinalized && groups.size() > 0;
+    }
+
+    @Override
+    public List<T> consumeFinalizedItems() {
+        if ( ! hasFinalizedItems() ) {
+            return new ArrayList<T>();
+        }
+
+        // pass by reference rather than make a copy, for speed
+        final List<T> toReturn = groups;
+        clearItems();
+        return toReturn;
+    }
+
+    @Override
+    public boolean hasPendingItems() {
+        return ! groupsAreFinalized && groups.size() > 0;
+    }
+
+    @Override
+    public T peekFinalized() {
+        return hasFinalizedItems() ? groups.get(0) : null;
+    }
+
+    @Override
+    public T peekPending() {
+        return hasPendingItems() ? groups.get(0) : null;
+    }
+
+    @Override
+    public int size() {
+        int s = 0;
+        for ( final List<E> l : groups ) {
+            s += l.size();
+        }
+        return s;
+    }
+
+    @Override
+    public void signalEndOfInput() {
+        levelGroups();
+        groupsAreFinalized = true;
+    }
+
+    @Override
+    public void clearItems() {
+        groups = new ArrayList<T>();
+        groupsAreFinalized = false;
+    }
+
+    private void levelGroups() {
+        final int[] groupSizes = new int[groups.size()];
+        int totalSize = 0;
+        int currentGroupIndex = 0;
+
+        for ( final T group : groups ) {
+            groupSizes[currentGroupIndex] = group.size();
+            totalSize += groupSizes[currentGroupIndex];
+            currentGroupIndex++;
+        }
+
+        if ( totalSize <= targetSize ) {
+            return;    // no need to eliminate any items
+        }
+
+        // We will try to remove exactly this many items, however we will refuse to allow any
+        // one group to fall below size 1, and so might end up removing fewer items than this
+        int numItemsToRemove = totalSize - targetSize;
+
+        currentGroupIndex = 0;
+        int numConsecutiveUmodifiableGroups = 0;
+
+        // Continue until we've either removed all the items we wanted to, or we can't
+        // remove any more items without violating the constraint that all groups must
+        // be left with at least one item
+        while ( numItemsToRemove > 0 && numConsecutiveUmodifiableGroups < groupSizes.length ) {
+            if ( groupSizes[currentGroupIndex] > minElementsPerStack ) {
+                groupSizes[currentGroupIndex]--;
+                numItemsToRemove--;
+                numConsecutiveUmodifiableGroups = 0;
+            }
+            else {
+                numConsecutiveUmodifiableGroups++;
+            }
+
+            currentGroupIndex = (currentGroupIndex + 1) % groupSizes.length;
+        }
+
+        // Now we actually go through and reduce each group to its new count as specified in groupSizes
+        currentGroupIndex = 0;
+        for ( final T group : groups ) {
+            downsampleOneGroup(group, groupSizes[currentGroupIndex]);
+            currentGroupIndex++;
+        }
+    }
+
+    private void downsampleOneGroup( final T group, final int numItemsToKeep ) {
+        if ( numItemsToKeep >= group.size() ) {
+            return;
+        }
+
+        final BitSet itemsToKeep = new BitSet(group.size());
+        for ( Integer selectedIndex : MathUtils.sampleIndicesWithoutReplacement(group.size(), numItemsToKeep) ) {
+            itemsToKeep.set(selectedIndex);
+        }
+
+        int currentIndex = 0;
+
+        // If our group is a linked list, we can remove the desired items in a single O(n) pass with an iterator
+        if ( group instanceof LinkedList ) {
+            final Iterator<E> iter = group.iterator();
+            while ( iter.hasNext() ) {
+                final E item = iter.next();
+
+                if ( ! itemsToKeep.get(currentIndex) && ! doNotDiscardItem(item) ) {
+                    iter.remove();
+                    numDiscardedItems++;
+                }
+
+                currentIndex++;
+            }
+        }
+        // If it's not a linked list, it's more efficient to copy the desired items into a new list and back rather
+        // than suffer O(n^2) of item shifting
+        else {
+            final List<E> keptItems = new ArrayList<E>(group.size());
+
+            for ( final E item : group ) {
+                if ( itemsToKeep.get(currentIndex) || doNotDiscardItem(item) ) {
+                    keptItems.add(item);
+                }
+                currentIndex++;
+            }
+            numDiscardedItems += group.size() - keptItems.size();
+            group.clear();
+            group.addAll(keptItems);
+        }
+    }
+}
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/downsampling/PassThroughDownsampler.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/downsampling/PassThroughDownsampler.java
new file mode 100644
index 0000000..a5fdf24
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/downsampling/PassThroughDownsampler.java
@@ -0,0 +1,111 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.engine.downsampling;
+
+import htsjdk.samtools.SAMRecord;
+
+import java.util.LinkedList;
+import java.util.List;
+
+/**
+ * Pass-Through Downsampler: Implementation of the ReadsDownsampler interface that does no
+ * downsampling whatsoever, and instead simply "passes-through" all the reads it's given.
+ * Useful for situations where you want to disable downsampling, but still need to use
+ * the downsampler interface.
+ *
+ * @author David Roazen
+ */
+public class PassThroughDownsampler<T extends SAMRecord> extends ReadsDownsampler<T> {
+
+    private LinkedList<T> selectedReads;
+
+    public PassThroughDownsampler() {
+        clearItems();
+    }
+
+    @Override
+    public void submit( T newRead ) {
+        // All reads pass-through, no reads get downsampled
+        selectedReads.add(newRead);
+    }
+
+    @Override
+    public boolean hasFinalizedItems() {
+        return ! selectedReads.isEmpty();
+    }
+
+    /**
+     * Note that this list is a linked list and so doesn't support fast random access
+     * @return
+     */
+    @Override
+    public List<T> consumeFinalizedItems() {
+        // pass by reference rather than make a copy, for speed
+        final List<T> downsampledItems = selectedReads;
+        clearItems();
+        return downsampledItems;
+    }
+
+    @Override
+    public boolean hasPendingItems() {
+        return false;
+    }
+
+    @Override
+    public T peekFinalized() {
+        return selectedReads.isEmpty() ? null : selectedReads.getFirst();
+    }
+
+    @Override
+    public T peekPending() {
+        return null;
+    }
+
+    @Override
+    public int size() {
+        return selectedReads.size();
+    }
+
+    @Override
+    public void signalEndOfInput() {
+        // NO-OP
+    }
+
+    @Override
+    public void clearItems() {
+        selectedReads = new LinkedList<T>();
+    }
+
+    @Override
+    public boolean requiresCoordinateSortOrder() {
+        return false;
+    }
+
+    @Override
+    public void signalNoMoreReadsBefore( T read ) {
+        // NO-OP
+    }
+}
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/downsampling/PerSampleDownsamplingReadsIterator.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/downsampling/PerSampleDownsamplingReadsIterator.java
new file mode 100644
index 0000000..118bbbb
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/downsampling/PerSampleDownsamplingReadsIterator.java
@@ -0,0 +1,207 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.engine.downsampling;
+
+import htsjdk.samtools.SAMRecord;
+import htsjdk.samtools.SAMRecordComparator;
+import htsjdk.samtools.SAMRecordCoordinateComparator;
+import org.broadinstitute.gatk.engine.iterators.GATKSAMIterator;
+
+import java.util.*;
+
+
+/**
+ * GATKSAMIterator wrapper around our generic reads downsampler interface
+ * that downsamples reads for each sample independently, and then re-assembles
+ * the reads back into a single merged stream.
+ *
+ * @author David Roazen
+ */
+public class PerSampleDownsamplingReadsIterator implements GATKSAMIterator {
+
+    private GATKSAMIterator nestedSAMIterator;
+    private ReadsDownsamplerFactory<SAMRecord> downsamplerFactory;
+    private Map<String, ReadsDownsampler<SAMRecord>> perSampleDownsamplers;
+    private PriorityQueue<SAMRecord> orderedDownsampledReadsCache;
+    private SAMRecord nextRead = null;
+    private SAMRecordComparator readComparator = new SAMRecordCoordinateComparator();
+    private SAMRecord earliestPendingRead = null;
+    private ReadsDownsampler<SAMRecord> earliestPendingDownsampler = null;
+
+    // Initial size of our cache of finalized reads
+    private static final int DOWNSAMPLED_READS_INITIAL_CACHE_SIZE = 4096;
+
+    // The number of positional changes that can occur in the read stream before all downsamplers
+    // should be informed of the current position (guards against samples with relatively sparse reads
+    // getting stuck in a pending state):
+    private static final int DOWNSAMPLER_POSITIONAL_UPDATE_INTERVAL = 3;   // TODO: experiment with this value
+
+    /**
+     * @param iter wrapped iterator from which this iterator will pull reads
+     * @param downsamplerFactory factory used to create new downsamplers as needed
+     */
+    public PerSampleDownsamplingReadsIterator( GATKSAMIterator iter, ReadsDownsamplerFactory<SAMRecord> downsamplerFactory ) {
+        nestedSAMIterator = iter;
+        this.downsamplerFactory = downsamplerFactory;
+        perSampleDownsamplers = new HashMap<String, ReadsDownsampler<SAMRecord>>();
+        orderedDownsampledReadsCache = new PriorityQueue<SAMRecord>(DOWNSAMPLED_READS_INITIAL_CACHE_SIZE, readComparator);
+
+        advanceToNextRead();
+    }
+
+    public boolean hasNext() {
+        return nextRead != null;
+    }
+
+    public SAMRecord next() {
+        if ( nextRead == null ) {
+            throw new NoSuchElementException("next() called when there are no more items");
+        }
+
+        SAMRecord toReturn = nextRead;
+        advanceToNextRead();
+
+        return toReturn;
+    }
+
+    private void advanceToNextRead() {
+        if ( ! readyToReleaseReads() && ! fillDownsampledReadsCache() ) {
+            nextRead = null;
+        }
+        else {
+            nextRead = orderedDownsampledReadsCache.poll();
+        }
+    }
+
+    private boolean readyToReleaseReads() {
+        if ( orderedDownsampledReadsCache.isEmpty() ) {
+            return false;
+        }
+
+        return earliestPendingRead == null ||
+               readComparator.compare(orderedDownsampledReadsCache.peek(), earliestPendingRead) <= 0;
+    }
+
+    private boolean fillDownsampledReadsCache() {
+        SAMRecord prevRead = null;
+        int numPositionalChanges = 0;
+
+        // Continue submitting reads to the per-sample downsamplers until the read at the top of the priority queue
+        // can be released without violating global sort order
+        while ( nestedSAMIterator.hasNext() && ! readyToReleaseReads() ) {
+            SAMRecord read = nestedSAMIterator.next();
+            String sampleName = read.getReadGroup() != null ? read.getReadGroup().getSample() : null;
+
+            ReadsDownsampler<SAMRecord> thisSampleDownsampler = perSampleDownsamplers.get(sampleName);
+            if ( thisSampleDownsampler == null ) {
+                thisSampleDownsampler = downsamplerFactory.newInstance();
+                perSampleDownsamplers.put(sampleName, thisSampleDownsampler);
+            }
+
+            thisSampleDownsampler.submit(read);
+            processFinalizedAndPendingItems(thisSampleDownsampler);
+
+            if ( prevRead != null && prevRead.getAlignmentStart() != read.getAlignmentStart() ) {
+                numPositionalChanges++;
+            }
+
+            // Periodically inform all downsamplers of the current position in the read stream. This is
+            // to prevent downsamplers for samples with sparser reads than others from getting stuck too
+            // long in a pending state.
+            if ( numPositionalChanges > 0 && numPositionalChanges % DOWNSAMPLER_POSITIONAL_UPDATE_INTERVAL == 0 ) {
+                for ( ReadsDownsampler<SAMRecord> perSampleDownsampler : perSampleDownsamplers.values() ) {
+                    perSampleDownsampler.signalNoMoreReadsBefore(read);
+                    processFinalizedAndPendingItems(perSampleDownsampler);
+                }
+            }
+
+            prevRead = read;
+        }
+
+        if ( ! nestedSAMIterator.hasNext() ) {
+            for ( ReadsDownsampler<SAMRecord> perSampleDownsampler : perSampleDownsamplers.values() ) {
+                perSampleDownsampler.signalEndOfInput();
+                if ( perSampleDownsampler.hasFinalizedItems() ) {
+                    orderedDownsampledReadsCache.addAll(perSampleDownsampler.consumeFinalizedItems());
+                }
+            }
+            earliestPendingRead = null;
+            earliestPendingDownsampler = null;
+        }
+
+        return readyToReleaseReads();
+    }
+
+    private void updateEarliestPendingRead( ReadsDownsampler<SAMRecord> currentDownsampler ) {
+        // If there is no recorded earliest pending read and this downsampler has pending items,
+        // then this downsampler's first pending item becomes the new earliest pending read:
+        if ( earliestPendingRead == null && currentDownsampler.hasPendingItems() ) {
+            earliestPendingRead = currentDownsampler.peekPending();
+            earliestPendingDownsampler = currentDownsampler;
+        }
+        // In all other cases, we only need to update the earliest pending read when the downsampler
+        // associated with it experiences a change in its pending reads, since by assuming a sorted
+        // read stream we're assured that each downsampler's earliest pending read will only increase
+        // in genomic position over time.
+        //
+        // TODO: An occasional O(samples) linear search seems like a better option than keeping the downsamplers
+        // TODO: sorted by earliest pending read, which would cost at least O(total_reads * (samples + log(samples))),
+        // TODO: but need to verify this empirically.
+        else if ( currentDownsampler == earliestPendingDownsampler &&
+                  (! currentDownsampler.hasPendingItems() || readComparator.compare(currentDownsampler.peekPending(), earliestPendingRead) != 0) ) {
+
+            earliestPendingRead = null;
+            earliestPendingDownsampler = null;
+            for ( ReadsDownsampler<SAMRecord> perSampleDownsampler : perSampleDownsamplers.values() ) {
+                if ( perSampleDownsampler.hasPendingItems() &&
+                     (earliestPendingRead == null || readComparator.compare(perSampleDownsampler.peekPending(), earliestPendingRead) < 0) ) {
+
+                    earliestPendingRead = perSampleDownsampler.peekPending();
+                    earliestPendingDownsampler = perSampleDownsampler;
+                }
+            }
+        }
+    }
+
+    private void processFinalizedAndPendingItems( ReadsDownsampler<SAMRecord> currentDownsampler ) {
+        if ( currentDownsampler.hasFinalizedItems() ) {
+            orderedDownsampledReadsCache.addAll(currentDownsampler.consumeFinalizedItems());
+        }
+        updateEarliestPendingRead(currentDownsampler);
+    }
+
+    public void remove() {
+        throw new UnsupportedOperationException("Can not remove records from a SAM file via an iterator!");
+    }
+
+    public void close() {
+        nestedSAMIterator.close();
+    }
+
+    public Iterator<SAMRecord> iterator() {
+        return this;
+    }
+}
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/downsampling/ReadsDownsampler.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/downsampling/ReadsDownsampler.java
new file mode 100644
index 0000000..9263920
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/downsampling/ReadsDownsampler.java
@@ -0,0 +1,56 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.engine.downsampling;
+
+import htsjdk.samtools.SAMRecord;
+
+/**
+ * An extension of the basic downsampler API with reads-specific operations
+ *
+ * @author David Roazen
+ */
+public abstract class ReadsDownsampler<T extends SAMRecord> extends Downsampler<T> {
+
+    /**
+     * Does this downsampler require that reads be fed to it in coordinate order?
+     *
+     * @return true if reads must be submitted to this downsampler in coordinate order, otherwise false
+     */
+    public abstract boolean requiresCoordinateSortOrder();
+
+    /**
+     * Tell this downsampler that no more reads located before the provided read (according to
+     * the sort order of the read stream) will be fed to it.
+     *
+     * Allows position-aware downsamplers to finalize pending reads earlier than they would
+     * otherwise be able to, particularly when doing per-sample downsampling and reads for
+     * certain samples are sparser than average.
+     *
+     * @param read the downsampler will assume that no reads located before this read will ever
+     *             be submitted to it in the future
+     */
+    public abstract void signalNoMoreReadsBefore( final T read );
+}
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/downsampling/ReadsDownsamplerFactory.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/downsampling/ReadsDownsamplerFactory.java
new file mode 100644
index 0000000..9ef847e
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/downsampling/ReadsDownsamplerFactory.java
@@ -0,0 +1,38 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.engine.downsampling;
+
+import htsjdk.samtools.SAMRecord;
+
+/**
+ * A ReadsDownsamplerFactory can be used to create an arbitrary number of instances of a particular
+ * downsampler, all sharing the same construction parameters.
+ *
+ * @author David Roazen
+ */
+public interface ReadsDownsamplerFactory<T extends SAMRecord> {
+    public ReadsDownsampler<T> newInstance();
+}
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/downsampling/ReservoirDownsampler.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/downsampling/ReservoirDownsampler.java
new file mode 100644
index 0000000..99a0bbd
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/downsampling/ReservoirDownsampler.java
@@ -0,0 +1,219 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.engine.downsampling;
+
+import htsjdk.samtools.SAMRecord;
+import org.broadinstitute.gatk.engine.GenomeAnalysisEngine;
+import org.broadinstitute.gatk.utils.exceptions.ReviewedGATKException;
+
+import java.util.*;
+
+/**
+ * Reservoir Downsampler: Selects n reads out of a stream whose size is not known in advance, with
+ * every read in the stream having an equal chance of being selected for inclusion.
+ *
+ * An implementation of "Algorithm R" from the paper "Random Sampling with a Reservoir" (Jeffrey Scott Vitter, 1985)
+ *
+ * @author David Roazen
+ */
+public class ReservoirDownsampler<T extends SAMRecord> extends ReadsDownsampler<T> {
+
+    /**
+     * size of our reservoir -- ie., the maximum number of reads from the stream that will be retained
+     * (not including any undiscardable items)
+     */
+    private final int targetSampleSize;
+
+    /**
+     * if true, this downsampler will be optimized for the case
+     * where most of the time we won't fill up anything like the
+     * targetSampleSize elements.  If this is false, we will allocate
+     * internal buffers to targetSampleSize initially, which minimizes
+     * the cost of allocation if we often use targetSampleSize or more
+     * elements.
+     */
+    private final boolean expectFewOverflows;
+
+    /**
+     * At times this can be a linked list or an array list, depending on how we're accessing the
+     * data and whether or not we're expecting few overflows
+     */
+    private List<T> reservoir;
+
+    /**
+     * Certain items (eg., reduced reads) cannot be discarded at all during downsampling. We store
+     * these items separately so as not to impact the fair selection of items for inclusion in the
+     * reservoir. These items are returned (and cleared) along with any items in the reservoir in
+     * calls to consumeFinalizedItems().
+     */
+    private List<T> undiscardableItems;
+
+    /**
+     * Are we currently using a linked list for the reservoir?
+     */
+    private boolean isLinkedList;
+
+    /**
+     * Count of the number of reads seen that were actually eligible for discarding. Used by the reservoir downsampling
+     * algorithm to ensure that all discardable reads have an equal chance of making it into the reservoir.
+     */
+    private int totalDiscardableReadsSeen;
+
+
+    /**
+     * Construct a ReservoirDownsampler
+     *
+     * @param targetSampleSize Size of the reservoir used by this downsampler. Number of items retained
+     *                         after downsampling will be min(totalDiscardableReads, targetSampleSize) + any
+     *                         undiscardable reads (eg., reduced reads).
+     *
+     * @param expectFewOverflows if true, this downsampler will be optimized for the case
+     *                           where most of the time we won't fill up anything like the
+     *                           targetSampleSize elements.  If this is false, we will allocate
+     *                           internal buffers to targetSampleSize initially, which minimizes
+     *                           the cost of allocation if we often use targetSampleSize or more
+     *                           elements.
+     */
+    public ReservoirDownsampler ( final int targetSampleSize, final boolean expectFewOverflows ) {
+        if ( targetSampleSize <= 0 ) {
+            throw new ReviewedGATKException("Cannot do reservoir downsampling with a sample size <= 0");
+        }
+
+        this.targetSampleSize = targetSampleSize;
+        this.expectFewOverflows = expectFewOverflows;
+        clearItems();
+        resetStats();
+    }
+
+    /**
+     * Construct a ReservoirDownsampler
+     *
+     * @param targetSampleSize Size of the reservoir used by this downsampler. Number of items retained
+     *                         after downsampling will be min(totalReads, targetSampleSize)
+     */
+    public ReservoirDownsampler ( final int targetSampleSize ) {
+        this(targetSampleSize, false);
+    }
+
+    @Override
+    public void submit ( final T newRead ) {
+        if ( doNotDiscardItem(newRead) ) {
+            undiscardableItems.add(newRead);
+            return;
+        }
+
+        // Only count reads that are actually eligible for discarding for the purposes of the reservoir downsampling algorithm
+        totalDiscardableReadsSeen++;
+
+        if ( totalDiscardableReadsSeen <= targetSampleSize ) {
+            reservoir.add(newRead);
+        }
+        else {
+            if ( isLinkedList ) {
+                reservoir = new ArrayList<T>(reservoir);
+                isLinkedList = false;
+            }
+
+            final int randomSlot = GenomeAnalysisEngine.getRandomGenerator().nextInt(totalDiscardableReadsSeen);
+            if ( randomSlot < targetSampleSize ) {
+                reservoir.set(randomSlot, newRead);
+            }
+            numDiscardedItems++;
+        }
+    }
+
+    @Override
+    public boolean hasFinalizedItems() {
+        return ! reservoir.isEmpty() || ! undiscardableItems.isEmpty();
+    }
+
+    @Override
+    public List<T> consumeFinalizedItems() {
+        if ( ! hasFinalizedItems() ) {
+            // if there's nothing here, don't bother allocating a new list
+            return Collections.emptyList();
+        } else {
+            // pass reservoir by reference rather than make a copy, for speed
+            final List<T> downsampledItems = reservoir;
+            downsampledItems.addAll(undiscardableItems);
+            clearItems();
+            return downsampledItems;
+        }
+    }
+
+    @Override
+    public boolean hasPendingItems() {
+        return false;
+    }
+
+    @Override
+    public T peekFinalized() {
+        return ! reservoir.isEmpty() ? reservoir.get(0) : (! undiscardableItems.isEmpty() ? undiscardableItems.get(0) : null);
+    }
+
+    @Override
+    public T peekPending() {
+        return null;
+    }
+
+    @Override
+    public int size() {
+        return reservoir.size() + undiscardableItems.size();
+    }
+
+    @Override
+    public void signalEndOfInput() {
+        // NO-OP
+    }
+
+    /**
+     * Clear the data structures used to hold information
+     */
+    @Override
+    public void clearItems() {
+        // if we aren't expecting many overflows, allocate a linked list not an arraylist
+        reservoir = expectFewOverflows ? new LinkedList<T>() : new ArrayList<T>(targetSampleSize);
+
+        // there's no possibility of overflow with the undiscardable items, so we always use a linked list for them
+        undiscardableItems = new LinkedList<>();
+
+        // it's a linked list if we allocate one
+        isLinkedList = expectFewOverflows;
+
+        // an internal stat used by the downsampling process, so not cleared by resetStats() below
+        totalDiscardableReadsSeen = 0;
+    }
+
+    @Override
+    public boolean requiresCoordinateSortOrder() {
+        return false;
+    }
+
+    @Override
+    public void signalNoMoreReadsBefore( T read ) {
+        // NO-OP
+    }
+}
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/downsampling/ReservoirDownsamplerFactory.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/downsampling/ReservoirDownsamplerFactory.java
new file mode 100644
index 0000000..c825bae
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/downsampling/ReservoirDownsamplerFactory.java
@@ -0,0 +1,46 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.engine.downsampling;
+
+import htsjdk.samtools.SAMRecord;
+
+/**
+ * Factory for creating ReservoirDownsamplers on demand
+ *
+ * @author David Roazen
+ */
+public class ReservoirDownsamplerFactory<T extends SAMRecord> implements ReadsDownsamplerFactory<T> {
+
+    private int targetSampleSize;
+
+    public ReservoirDownsamplerFactory( int targetSampleSize ) {
+        this.targetSampleSize = targetSampleSize;
+    }
+
+    public ReadsDownsampler<T> newInstance() {
+        return new ReservoirDownsampler<T>(targetSampleSize);
+    }
+}
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/downsampling/SimplePositionalDownsampler.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/downsampling/SimplePositionalDownsampler.java
new file mode 100644
index 0000000..af0aa54
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/downsampling/SimplePositionalDownsampler.java
@@ -0,0 +1,171 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.engine.downsampling;
+
+import htsjdk.samtools.SAMRecord;
+
+import java.util.*;
+
+/**
+ * Simple Positional Downsampler: Downsample each stack of reads at each alignment start to a size <= a target coverage
+ * using a Reservoir downsampler. Stores only O(target coverage) reads in memory at any given time.
+ *
+ * @author David Roazen
+ */
+public class SimplePositionalDownsampler<T extends SAMRecord> extends ReadsDownsampler<T> {
+
+    private final int targetCoverage;
+
+    private final ReservoirDownsampler<T> reservoir;
+
+    private int currentContigIndex;
+
+    private int currentAlignmentStart;
+
+    private boolean positionEstablished;
+
+    private boolean unmappedReadsReached;
+
+    private ArrayList<T> finalizedReads;
+
+
+    /**
+     * Construct a SimplePositionalDownsampler
+     *
+     * @param targetCoverage Maximum number of reads that may share any given alignment start position
+     */
+    public SimplePositionalDownsampler( final int targetCoverage ) {
+        this.targetCoverage = targetCoverage;
+        reservoir = new ReservoirDownsampler<T>(targetCoverage);
+        finalizedReads = new ArrayList<T>();
+        clearItems();
+        resetStats();
+    }
+
+    @Override
+    public void submit( final T newRead ) {
+        updatePositionalState(newRead);
+
+        if ( unmappedReadsReached ) {    // don't downsample the unmapped reads at the end of the stream
+            finalizedReads.add(newRead);
+        }
+        else {
+            final int reservoirPreviouslyDiscardedItems = reservoir.getNumberOfDiscardedItems();
+            // our reservoir downsampler will call doNotDiscardItem() for us to exclude items from elimination as appropriate
+            reservoir.submit(newRead);
+            numDiscardedItems += reservoir.getNumberOfDiscardedItems() - reservoirPreviouslyDiscardedItems;
+        }
+    }
+
+    @Override
+    public boolean hasFinalizedItems() {
+        return finalizedReads.size() > 0;
+    }
+
+    @Override
+    public List<T> consumeFinalizedItems() {
+        // pass by reference rather than make a copy, for speed
+        final List<T> toReturn = finalizedReads;
+        finalizedReads = new ArrayList<T>();
+        return toReturn;
+    }
+
+    @Override
+    public boolean hasPendingItems() {
+        return reservoir.hasFinalizedItems();
+    }
+
+    @Override
+    public T peekFinalized() {
+        return finalizedReads.isEmpty() ? null : finalizedReads.get(0);
+    }
+
+    @Override
+    public T peekPending() {
+        return reservoir.peekFinalized();
+    }
+
+    @Override
+    public int size() {
+        return finalizedReads.size() + reservoir.size();
+    }
+
+    @Override
+    public void signalEndOfInput() {
+        finalizeReservoir();
+    }
+
+    @Override
+    public void clearItems() {
+        reservoir.clearItems();
+        reservoir.resetStats();
+        finalizedReads.clear();
+        positionEstablished = false;
+        unmappedReadsReached = false;
+    }
+
+    @Override
+    public boolean requiresCoordinateSortOrder() {
+        return true;
+    }
+
+    @Override
+    public void signalNoMoreReadsBefore( final T read ) {
+        updatePositionalState(read);
+    }
+
+    private void updatePositionalState( final T newRead ) {
+        if ( readIsPastCurrentPosition(newRead) ) {
+            if ( reservoir.hasFinalizedItems() ) {
+                finalizeReservoir();
+            }
+
+            setCurrentPosition(newRead);
+
+            if ( newRead.getReadUnmappedFlag() ) {
+                unmappedReadsReached = true;
+            }
+        }
+    }
+
+    private void setCurrentPosition( final T read ) {
+        currentContigIndex = read.getReferenceIndex();
+        currentAlignmentStart = read.getAlignmentStart();
+        positionEstablished = true;
+    }
+
+    private boolean readIsPastCurrentPosition( final T read ) {
+        return ! positionEstablished ||
+               read.getReferenceIndex() > currentContigIndex ||
+               read.getAlignmentStart() > currentAlignmentStart ||
+               (read.getReadUnmappedFlag() && ! unmappedReadsReached);
+    }
+
+    private void finalizeReservoir() {
+        finalizedReads.addAll(reservoir.consumeFinalizedItems());
+        reservoir.resetStats();
+    }
+}
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/downsampling/SimplePositionalDownsamplerFactory.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/downsampling/SimplePositionalDownsamplerFactory.java
new file mode 100644
index 0000000..3fc66ca
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/downsampling/SimplePositionalDownsamplerFactory.java
@@ -0,0 +1,46 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.engine.downsampling;
+
+import htsjdk.samtools.SAMRecord;
+
+/**
+ * Factory for creating SimplePositionalDownsamplers on demand
+ *
+ * @author David Roazen
+ */
+public class SimplePositionalDownsamplerFactory<T extends SAMRecord> implements ReadsDownsamplerFactory<T> {
+
+    private int targetCoverage;
+
+    public SimplePositionalDownsamplerFactory( int targetCoverage ) {
+        this.targetCoverage = targetCoverage;
+    }
+
+    public ReadsDownsampler<T> newInstance() {
+        return new SimplePositionalDownsampler<T>(targetCoverage);
+    }
+}
\ No newline at end of file
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/executive/Accumulator.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/executive/Accumulator.java
new file mode 100644
index 0000000..9276331
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/executive/Accumulator.java
@@ -0,0 +1,211 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.engine.executive;
+
+import org.broadinstitute.gatk.engine.GenomeAnalysisEngine;
+import org.broadinstitute.gatk.engine.datasources.providers.LocusShardDataProvider;
+import org.broadinstitute.gatk.engine.datasources.providers.ShardDataProvider;
+import org.broadinstitute.gatk.engine.walkers.Walker;
+import org.broadinstitute.gatk.utils.GenomeLoc;
+import org.broadinstitute.gatk.utils.GenomeLocSortedSet;
+import org.broadinstitute.gatk.utils.collections.Pair;
+import org.broadinstitute.gatk.utils.exceptions.ReviewedGATKException;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+/**
+ * Manages the
+ */
+
+public abstract class Accumulator {
+    /**
+     * The walker for which to accumulate.
+     */
+    protected final Walker walker;
+
+    /**
+     * Create a new Accumulator.  Forbid outside classes from performing this operation.
+     * @param walker
+     */
+    protected Accumulator( Walker walker ) {
+        this.walker = walker;
+    }
+
+    /**
+     * Creates an accumulator suitable for accumulating results of the given walker.
+     * @param walker Walker for which to build an accumulator.
+     * @return Accumulator suitable for this walker.s
+     */
+    public static Accumulator create( GenomeAnalysisEngine engine, Walker walker ) {
+        if( walker.isReduceByInterval() && engine.getIntervals() != null)
+            return new IntervalAccumulator( walker, engine.getIntervals() );
+        else
+            return new StandardAccumulator( walker );
+    }
+
+    /**
+     * Gets the appropriate reduce initializer for this accumulator.
+     * @return Traversal reduce init to feed into traversal engine. 
+     */
+    public abstract Object getReduceInit();
+
+    /**
+     * Roll this traversal result into the given accumulator.
+     * @param result Result of the most recent accumulation.
+     * @return the newest accumulation of the given data.
+     */
+    public abstract void accumulate( ShardDataProvider provider, Object result );
+
+    /**
+     * Finishes off the traversal.  Submits accumulated results to
+     * the walker and returns them.
+     * TODO: Its a bit funky to delegate the finishing of the traversal
+     *       to an accumulator, but we're doing it for type safety so the
+     *       right Walker override gets called.  Clean this up.
+     * @return Final result of accumulation.
+     */
+    public abstract Object finishTraversal();
+
+    /**
+     * Accumulates in the 'standard' fashion; basically funnels
+     * the reduce result back into the reduce init and relies on
+     * the user-supplied reduce to handle the accumulation.
+     */
+    private static class StandardAccumulator extends Accumulator {
+        private Object accumulator = null;
+        private boolean initialized = false;
+
+        protected StandardAccumulator( Walker walker ) {
+            super(walker);
+        }
+
+        /**
+         * Standard accumulator returns reduceInit first, then the
+         * results of the previous accumulation. 
+         */
+        public Object getReduceInit() {
+            if( !initialized ) {
+                initialized = true;
+                return walker.reduceInit();
+            }
+            else
+                return accumulator;
+        }
+
+        /**
+         * The result of the accumulator in a non-intervals walker
+         * already takes the accumulation into account.  return the result. 
+         */
+        public void accumulate( ShardDataProvider provider, Object result ) { this.accumulator = result; }
+
+        /**
+         * The result of the traversal is the list of accumulated intervals.
+         */
+        public Object finishTraversal() {
+            walker.onTraversalDone(getReduceInit());  // must call getReduceInit to ensure that we get the accumulator value or the reduceInit value
+            return this.accumulator;
+        }
+    }
+
+    /**
+     * An interval-based accumulator.  Treats each reduce result independently,
+     * and aggregates those results into a single list.
+     */
+    private static class IntervalAccumulator extends Accumulator {
+        /**
+         * True if a new interval is being started.  This flag is used to
+         * ensure that reduceInit() is not called unnecessarily.
+         */
+        private boolean startingNewInterval = true;
+
+        /**
+         * An iterator through all intervals in the series.
+         */
+        private final Iterator<GenomeLoc> intervalIterator;
+
+        /**
+         * For which interval is the accumulator currently accumulating?
+         */
+        private GenomeLoc currentInterval = null;
+
+        /**
+         * The actual mapping of interval to accumulator.
+         */
+        private final List<Pair<GenomeLoc,Object>> intervalAccumulator = new ArrayList<Pair<GenomeLoc,Object>>();
+
+        /**
+         * Holds the next value to be passed in as the reduce result.
+         */
+        private Object nextReduceInit = null;
+
+        protected IntervalAccumulator(Walker walker, GenomeLocSortedSet intervals) {
+            super(walker);
+            this.intervalIterator = intervals.iterator();
+            if(intervalIterator.hasNext()) currentInterval = intervalIterator.next();
+        }
+
+        /**
+         * Interval accumulator always feeds reduceInit into every new traversal.
+         */
+        public Object getReduceInit() {
+            if(startingNewInterval) {
+                startingNewInterval = false;
+                nextReduceInit = walker.reduceInit();
+            }
+            return nextReduceInit;
+        }
+
+        /**
+         * Create a holder for interval results if none exists.  Add the result to the holder.
+         */
+        public void accumulate( ShardDataProvider provider, Object result ) {
+            if(!(provider instanceof LocusShardDataProvider))
+                throw new ReviewedGATKException("Unable to reduce by interval on reads traversals at this time.");
+
+            GenomeLoc location = ((LocusShardDataProvider)provider).getLocus();
+
+            // Pull the interval iterator ahead to the interval overlapping this shard fragment.
+            while((currentInterval == null || currentInterval.isBefore(location)) && intervalIterator.hasNext())
+                currentInterval = intervalIterator.next();
+
+            if(currentInterval != null && currentInterval.getContig().equals(location.getContig()) && currentInterval.getStop() == location.getStop()) {
+                intervalAccumulator.add(new Pair<GenomeLoc,Object>(currentInterval,result));
+                startingNewInterval = true;
+            }
+            else
+                nextReduceInit = result;
+        }
+
+        /**
+         * The result of the traversal is the list of accumulated intervals.
+         */
+        public Object finishTraversal() {
+            walker.onTraversalDone(intervalAccumulator);
+            return intervalAccumulator;
+        }
+    }
+}
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/executive/HierarchicalMicroScheduler.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/executive/HierarchicalMicroScheduler.java
new file mode 100644
index 0000000..f7e3dbc
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/executive/HierarchicalMicroScheduler.java
@@ -0,0 +1,495 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.engine.executive;
+
+import htsjdk.samtools.reference.IndexedFastaSequenceFile;
+import htsjdk.tribble.TribbleException;
+import org.broadinstitute.gatk.engine.GenomeAnalysisEngine;
+import org.broadinstitute.gatk.engine.datasources.reads.SAMDataSource;
+import org.broadinstitute.gatk.engine.datasources.reads.Shard;
+import org.broadinstitute.gatk.engine.datasources.rmd.ReferenceOrderedDataSource;
+import org.broadinstitute.gatk.engine.io.OutputTracker;
+import org.broadinstitute.gatk.engine.io.ThreadGroupOutputTracker;
+import org.broadinstitute.gatk.engine.resourcemanagement.ThreadAllocation;
+import org.broadinstitute.gatk.engine.walkers.TreeReducible;
+import org.broadinstitute.gatk.engine.walkers.Walker;
+import org.broadinstitute.gatk.utils.MultiThreadedErrorTracker;
+import org.broadinstitute.gatk.utils.exceptions.ReviewedGATKException;
+import org.broadinstitute.gatk.utils.exceptions.UserException;
+import org.broadinstitute.gatk.utils.threading.ThreadPoolMonitor;
+
+import java.util.Collection;
+import java.util.Iterator;
+import java.util.LinkedList;
+import java.util.Queue;
+import java.util.concurrent.*;
+
+/**
+ * A microscheduler that schedules shards according to a tree-like structure.
+ * Requires a special walker tagged with a 'TreeReducible' interface.
+ */
+public class HierarchicalMicroScheduler extends MicroScheduler implements HierarchicalMicroSchedulerMBean, ReduceTree.TreeReduceNotifier {
+    /**
+     * How many outstanding output merges are allowed before the scheduler stops
+     * allowing new processes and starts merging flat-out.
+     */
+    private static final int MAX_OUTSTANDING_OUTPUT_MERGES = 50;
+
+    /** Manage currently running threads. */
+    private ExecutorService threadPool;
+
+    /**
+     * A thread local output tracker for managing output per-thread.
+     */
+    private ThreadGroupOutputTracker outputTracker = new ThreadGroupOutputTracker();
+
+    private final Queue<TreeReduceTask> reduceTasks = new LinkedList<TreeReduceTask>();
+
+    /**
+     * An exception that's occurred in this traversal.  If null, no exception has occurred.
+     */
+    final MultiThreadedErrorTracker errorTracker = new MultiThreadedErrorTracker();
+
+    /**
+     * Queue of incoming shards.
+     */
+    private Iterator<Shard> traversalTasks;
+
+    /**
+     * Keep a queue of shard traversals, and constantly monitor it to see what output
+     * merge tasks remain.
+     * TODO: Integrate this into the reduce tree.
+     */
+    private final Queue<ShardTraverser> outputMergeTasks = new LinkedList<ShardTraverser>();
+
+    /** How many shard traversals have run to date? */
+    private int totalCompletedTraversals = 0;
+
+    /** What is the total time spent traversing shards? */
+    private long totalShardTraverseTime = 0;
+
+    /** What is the total time spent tree reducing shard output? */
+    private long totalTreeReduceTime = 0;
+
+    /** How many tree reduces have been completed? */
+    private long totalCompletedTreeReduces = 0;
+
+    /** What is the total time spent merging output? */
+    private long totalOutputMergeTime = 0;
+
+    /**
+     * Create a new hierarchical microscheduler to process the given reads and reference.
+     *
+     * @param walker           the walker used to process the dataset.
+     * @param reads            Reads file(s) to process.
+     * @param reference        Reference for driving the traversal.
+     * @param threadAllocation How should we apply multi-threaded execution?
+     */
+    protected HierarchicalMicroScheduler(final GenomeAnalysisEngine engine,
+                                         final Walker walker,
+                                         final SAMDataSource reads,
+                                         final IndexedFastaSequenceFile reference,
+                                         final Collection<ReferenceOrderedDataSource> rods,
+                                         final ThreadAllocation threadAllocation) {
+        super(engine, walker, reads, reference, rods, threadAllocation);
+
+        final int nThreadsToUse = threadAllocation.getNumDataThreads();
+        if ( threadAllocation.monitorThreadEfficiency() ) {
+            throw new UserException.BadArgumentValue("nt", "Cannot monitor thread efficiency with -nt, sorry");
+        }
+
+        this.threadPool = Executors.newFixedThreadPool(nThreadsToUse, new UniqueThreadGroupThreadFactory());
+    }
+
+    /**
+     * Creates threads for HMS each with a unique thread group.  Critical to
+     * track outputs via the ThreadGroupOutputTracker.
+     */
+    private static class UniqueThreadGroupThreadFactory implements ThreadFactory {
+        int counter = 0;
+
+        @Override
+        public Thread newThread(Runnable r) {
+            final ThreadGroup group = new ThreadGroup("HMS-group-" + counter++);
+            return new Thread(group, r);
+        }
+    }
+
+    public Object execute( Walker walker, Iterable<Shard> shardStrategy ) {
+        super.startingExecution();
+
+        // Fast fail for walkers not supporting TreeReducible interface.
+        if (!( walker instanceof TreeReducible ))
+            throw new IllegalArgumentException("The GATK can currently run in parallel only with TreeReducible walkers");
+
+        this.traversalTasks = shardStrategy.iterator();
+
+        final ReduceTree reduceTree = new ReduceTree(this);
+        initializeWalker(walker);
+
+        while (! abortExecution() && (isShardTraversePending() || isTreeReducePending())) {
+            // Check for errors during execution.
+            errorTracker.throwErrorIfPending();
+
+            // Too many files sitting around taking up space?  Merge them.
+            if (isMergeLimitExceeded())
+                mergeExistingOutput(false);
+
+            // Wait for the next slot in the queue to become free.
+            waitForFreeQueueSlot();
+
+            // Pick the next most appropriate task and run it.  In the interest of
+            // memory conservation, hierarchical reduces always run before traversals.
+            if (isTreeReduceReady())
+                queueNextTreeReduce(walker);
+            else if (isShardTraversePending())
+                queueNextShardTraverse(walker, reduceTree);
+        }
+
+        errorTracker.throwErrorIfPending();
+
+        threadPool.shutdown();
+
+        // Merge any lingering output files.  If these files aren't ready,
+        // sit around and wait for them, then merge them.
+        mergeExistingOutput(true);
+
+        Object result = null;
+        try {
+            result = reduceTree.getResult().get();
+            notifyTraversalDone(walker,result);
+        } catch (ReviewedGATKException ex) {
+            throw ex;
+        } catch ( ExecutionException ex ) {
+            // the thread died and we are failing to get the result, rethrow it as a runtime exception
+            throw notifyOfTraversalError(ex.getCause());
+        } catch (Exception ex) {
+            throw new ReviewedGATKException("Unable to retrieve result", ex);
+        }
+
+        // do final cleanup operations
+        outputTracker.close();
+        cleanup();
+        executionIsDone();
+
+        return result;
+    }
+
+    /**
+     * Run the initialize method of the walker.  Ensure that any calls
+     * to the output stream will bypass thread local storage and write
+     * directly to the output file.
+     * @param walker Walker to initialize.
+     */
+    protected void initializeWalker(Walker walker) {
+        outputTracker.bypassThreadLocalStorage(true);
+        try {
+            walker.initialize();
+        }
+        finally {
+            outputTracker.bypassThreadLocalStorage(false);
+        }
+    }
+
+    /**
+     * Run the initialize method of the walker.  Ensure that any calls
+     * to the output stream will bypass thread local storage and write
+     * directly to the output file.
+     * @param walker Walker to initialize.
+     */
+    protected void notifyTraversalDone(Walker walker, Object result) {
+        outputTracker.bypassThreadLocalStorage(true);
+        try {
+            walker.onTraversalDone(result);
+        }
+        finally {
+            outputTracker.bypassThreadLocalStorage(false);
+        }
+    }
+
+    /**
+     * @{inheritDoc}
+     */
+    public OutputTracker getOutputTracker() {
+        return outputTracker;
+    }
+
+    /**
+     * Returns true if there are unscheduled shard traversal waiting to run.
+     *
+     * @return true if a shard traversal is waiting; false otherwise.
+     */
+    protected boolean isShardTraversePending() {
+        return traversalTasks.hasNext();
+    }
+
+    /**
+     * Returns true if there are tree reduces that can be run without
+     * blocking.
+     *
+     * @return true if a tree reduce is ready; false otherwise.
+     */
+    protected boolean isTreeReduceReady() {
+        if (reduceTasks.size() == 0)
+            return false;
+        return reduceTasks.peek().isReadyForReduce();
+    }
+
+    /**
+     * Returns true if there are tree reduces that need to be run before
+     * the computation is complete.  Returns true if any entries are in the queue,
+     * blocked or otherwise.
+     *
+     * @return true if a tree reduce is pending; false otherwise.
+     */
+    protected boolean isTreeReducePending() {
+        return reduceTasks.size() > 0;
+    }
+
+    /**
+     * Returns whether the maximum number of files is sitting in the temp directory
+     * waiting to be merged back in.
+     *
+     * @return True if the merging needs to take priority.  False otherwise.
+     */
+    protected boolean isMergeLimitExceeded() {
+        int pendingTasks = 0;
+        for( ShardTraverser shardTraverse: outputMergeTasks ) {
+            if( !shardTraverse.isComplete() )
+                break;
+            pendingTasks++;
+        }
+        return (outputMergeTasks.size() >= MAX_OUTSTANDING_OUTPUT_MERGES);
+    }
+
+    /**
+     * Merging all output that's sitting ready in the OutputMerger queue into
+     * the final data streams.
+     */
+    protected void mergeExistingOutput( boolean wait ) {
+        long startTime = System.currentTimeMillis();
+
+//        logger.warn("MergingExistingOutput");
+//        printOutputMergeTasks();
+
+        // Create a list of the merge tasks that will be performed in this run of the mergeExistingOutput().
+        Queue<ShardTraverser> mergeTasksInSession = new LinkedList<ShardTraverser>();
+        while( !outputMergeTasks.isEmpty() ) {
+            ShardTraverser traverser = outputMergeTasks.peek();
+
+            // If the next traversal isn't done and we're not supposed to wait, we've found our working set.  Continue.
+            if( !traverser.isComplete() && !wait )
+                break;
+
+            outputMergeTasks.remove();
+            mergeTasksInSession.add(traverser);
+        }
+
+//        logger.warn("Selected things to merge:");
+//        printOutputMergeTasks(mergeTasksInSession);
+
+        // Actually run through, merging the tasks in the working queue.
+        for( ShardTraverser traverser: mergeTasksInSession ) {
+            //logger.warn("*** Merging " + traverser.getIntervalsString());
+            if( !traverser.isComplete() )
+                traverser.waitForComplete();
+
+            OutputMergeTask mergeTask = traverser.getOutputMergeTask();
+            if( mergeTask != null ) {
+                try {
+                    mergeTask.merge();
+                }
+                catch(TribbleException ex) {
+                    // Specifically catch Tribble I/O exceptions and rethrow them as Reviewed.  We don't expect
+                    // any issues here because we created the Tribble output file mere moments ago and expect it to
+                    // be completely valid.
+                    throw new ReviewedGATKException("Unable to merge temporary Tribble output file.",ex);
+                }
+            }
+        }
+
+        long endTime = System.currentTimeMillis();
+
+        totalOutputMergeTime += ( endTime - startTime );
+    }
+
+    /**
+     * Queues the next traversal of a walker from the traversal tasks queue.
+     *
+     * @param walker     Walker to apply to the dataset.
+     * @param reduceTree Tree of reduces to which to add this shard traverse.
+     */
+    protected void queueNextShardTraverse( Walker walker, ReduceTree reduceTree ) {
+        if (!traversalTasks.hasNext())
+            throw new IllegalStateException("Cannot traverse; no pending traversals exist.");
+
+        final Shard shard = traversalTasks.next();
+
+        // todo -- add ownership claim here
+
+        final ShardTraverser traverser = new ShardTraverser(this, walker, shard, outputTracker);
+
+        final Future traverseResult = threadPool.submit(traverser);
+
+        // Add this traverse result to the reduce tree.  The reduce tree will call a callback to throw its entries on the queue.
+        reduceTree.addEntry(traverseResult);
+        outputMergeTasks.add(traverser);
+
+//        logger.warn("adding merge task");
+//        printOutputMergeTasks();
+
+        // No more data?  Let the reduce tree know so it can finish processing what it's got.
+        if (!isShardTraversePending())
+            reduceTree.complete();
+    }
+
+    private synchronized void printOutputMergeTasks() {
+        printOutputMergeTasks(outputMergeTasks);
+    }
+
+    private synchronized void printOutputMergeTasks(final Queue<ShardTraverser> tasks) {
+        logger.info("Output merge tasks " + tasks.size());
+        for ( final ShardTraverser traverser : tasks )
+            logger.info(String.format("\t%s: complete? %b", traverser.getIntervalsString(), traverser.isComplete()));
+    }
+
+    /** Pulls the next reduce from the queue and runs it. */
+    protected void queueNextTreeReduce( Walker walker ) {
+        if (reduceTasks.size() == 0)
+            throw new IllegalStateException("Cannot reduce; no pending reduces exist.");
+        final TreeReduceTask reducer = reduceTasks.remove();
+        reducer.setWalker((TreeReducible) walker);
+
+        threadPool.submit(reducer);
+    }
+
+    /** Blocks until a free slot appears in the thread queue. */
+    protected void waitForFreeQueueSlot() {
+        final ThreadPoolMonitor monitor = new ThreadPoolMonitor();
+        synchronized (monitor) {
+            threadPool.submit(monitor);
+            monitor.watch();
+        }
+    }
+
+    /**
+     * Callback for adding reduce tasks to the run queue.
+     *
+     * @return A new, composite future of the result of this reduce.
+     */
+    public Future notifyReduce( final Future lhs, final Future rhs ) {
+        final TreeReduceTask reducer = new TreeReduceTask(new TreeReducer(this, lhs, rhs));
+        reduceTasks.add(reducer);
+        return reducer;
+    }
+
+    /**
+     * Allows other threads to notify of an error during traversal.
+     */
+    protected synchronized RuntimeException notifyOfTraversalError(Throwable error) {
+        return errorTracker.notifyOfError(error);
+    }
+
+    /** A small wrapper class that provides the TreeReducer interface along with the FutureTask semantics. */
+    private class TreeReduceTask extends FutureTask {
+        final private TreeReducer treeReducer;
+
+        public TreeReduceTask( TreeReducer treeReducer ) {
+            super(treeReducer);
+            this.treeReducer = treeReducer;
+        }
+
+        public void setWalker( TreeReducible walker ) {
+            treeReducer.setWalker(walker);
+        }
+
+        public boolean isReadyForReduce() {
+            return treeReducer.isReadyForReduce();
+        }
+    }
+
+    /**
+     * Used by the ShardTraverser to report time consumed traversing a given shard.
+     *
+     * @param shardTraversalTime Elapsed time traversing a given shard.
+     */
+    synchronized void reportShardTraverseTime( long shardTraversalTime ) {
+        totalShardTraverseTime += shardTraversalTime;
+        totalCompletedTraversals++;
+    }
+
+    /**
+     * Used by the TreeReducer to report time consumed reducing two shards.
+     *
+     * @param treeReduceTime Elapsed time reducing two shards.
+     */
+    synchronized void reportTreeReduceTime( long treeReduceTime ) {
+        totalTreeReduceTime += treeReduceTime;
+        totalCompletedTreeReduces++;
+
+    }
+
+    /** {@inheritDoc} */
+    public int getNumberOfTasksInReduceQueue() {
+        return reduceTasks.size();
+    }
+
+    /** {@inheritDoc} */
+    public int getNumberOfTasksInIOQueue() {
+        synchronized( outputMergeTasks ) {
+            return outputMergeTasks.size();
+        }
+    }
+
+    /** {@inheritDoc} */
+    public long getTotalShardTraverseTimeMillis() {
+        return totalShardTraverseTime;
+    }
+
+    /** {@inheritDoc} */
+    public long getAvgShardTraverseTimeMillis() {
+        if (totalCompletedTraversals == 0)
+            return 0;
+        return totalShardTraverseTime / totalCompletedTraversals;
+    }
+
+    /** {@inheritDoc} */
+    public long getTotalTreeReduceTimeMillis() {
+        return totalTreeReduceTime;
+    }
+
+    /** {@inheritDoc} */
+    public long getAvgTreeReduceTimeMillis() {
+        if (totalCompletedTreeReduces == 0)
+            return 0;
+        return totalTreeReduceTime / totalCompletedTreeReduces;
+    }
+
+    /** {@inheritDoc} */
+    public long getTotalOutputMergeTimeMillis() {
+        return totalOutputMergeTime;
+    }
+}
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/executive/HierarchicalMicroSchedulerMBean.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/executive/HierarchicalMicroSchedulerMBean.java
new file mode 100644
index 0000000..30e03c6
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/executive/HierarchicalMicroSchedulerMBean.java
@@ -0,0 +1,86 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.engine.executive;
+/**
+ * User: hanna
+ * Date: May 29, 2009
+ * Time: 4:05:27 PM
+ * BROAD INSTITUTE SOFTWARE COPYRIGHT NOTICE AND AGREEMENT
+ * Software and documentation are copyright 2005 by the Broad Institute.
+ * All rights are reserved.
+ *
+ * Users acknowledge that this software is supplied without any warranty or support.
+ * The Broad Institute is not responsible for its use, misuse, or
+ * functionality.
+ */
+
+/**
+ * An interface for retrieving runtime statistics about how the hierarchical
+ * microscheduler is behaving. 
+ */
+public interface HierarchicalMicroSchedulerMBean {
+    /**
+     * How many tree reduces are waiting in the tree reduce queue?
+     * @return Total number of reduces waiting in the tree reduce queue?
+     */
+    public int getNumberOfTasksInReduceQueue();
+
+    /**
+     * How many pending I/O combining tasks are waiting in the queue?
+     * @return Total number of I/O tasks waiting in the I/O queue.
+     */
+    public int getNumberOfTasksInIOQueue();
+
+    /**
+     * What is the total time spent running traversals?
+     * @return Total time spent traversing shards; 0 if none have been traversed.
+     */
+    public long getTotalShardTraverseTimeMillis();
+
+    /**
+     * What is the average time spent running traversals?
+     * @return Average time spent traversing shards; 0 if none have been traversed.
+     */
+    public long getAvgShardTraverseTimeMillis();
+
+    /**
+     * What is the total time spent merging output?
+     */
+    public long getTotalOutputMergeTimeMillis();
+
+    /**
+     * What is the total time spent running tree reduces?
+     * @return Total time spent running tree reduces; 0 if none have been run.
+     */
+    public long getTotalTreeReduceTimeMillis();
+
+    /**
+     * What is the average time spent running tree reduces?
+     * @return Average time spent running tree reduces; 0 if none have been run.
+     */
+    public long getAvgTreeReduceTimeMillis();
+}
+
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/executive/LinearMicroScheduler.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/executive/LinearMicroScheduler.java
new file mode 100644
index 0000000..293bb1c
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/executive/LinearMicroScheduler.java
@@ -0,0 +1,130 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.engine.executive;
+
+import htsjdk.samtools.reference.IndexedFastaSequenceFile;
+import org.broadinstitute.gatk.engine.GenomeAnalysisEngine;
+import org.broadinstitute.gatk.engine.datasources.providers.LocusShardDataProvider;
+import org.broadinstitute.gatk.engine.datasources.providers.ReadShardDataProvider;
+import org.broadinstitute.gatk.engine.datasources.providers.ShardDataProvider;
+import org.broadinstitute.gatk.engine.datasources.reads.SAMDataSource;
+import org.broadinstitute.gatk.engine.datasources.reads.Shard;
+import org.broadinstitute.gatk.engine.datasources.rmd.ReferenceOrderedDataSource;
+import org.broadinstitute.gatk.engine.io.DirectOutputTracker;
+import org.broadinstitute.gatk.engine.io.OutputTracker;
+import org.broadinstitute.gatk.engine.resourcemanagement.ThreadAllocation;
+import org.broadinstitute.gatk.engine.traversals.TraversalEngine;
+import org.broadinstitute.gatk.engine.walkers.Walker;
+import org.broadinstitute.gatk.utils.SampleUtils;
+import org.broadinstitute.gatk.utils.threading.ThreadEfficiencyMonitor;
+
+import java.util.Collection;
+
+
+/** A micro-scheduling manager for single-threaded execution of a traversal. */
+public class LinearMicroScheduler extends MicroScheduler {
+
+    /**
+     * A direct output tracker for directly managing output.
+     */
+    private DirectOutputTracker outputTracker = new DirectOutputTracker();
+
+    /**
+     * Create a new linear microscheduler to process the given reads and reference.
+     *
+     * @param walker    Walker for the traversal.
+     * @param reads     Reads file(s) to process.
+     * @param reference Reference for driving the traversal.
+     * @param rods      Reference-ordered data.
+     */
+    protected LinearMicroScheduler(final GenomeAnalysisEngine engine,
+                                   final Walker walker,
+                                   final SAMDataSource reads,
+                                   final IndexedFastaSequenceFile reference,
+                                   final Collection<ReferenceOrderedDataSource> rods,
+                                   final ThreadAllocation threadAllocation) {
+        super(engine, walker, reads, reference, rods, threadAllocation);
+
+        if ( threadAllocation.monitorThreadEfficiency() )
+            setThreadEfficiencyMonitor(new ThreadEfficiencyMonitor());
+    }
+
+    /**
+     * Run this traversal over the specified subsection of the dataset.
+     *
+     * @param walker    Computation to perform over dataset.
+     * @param shardStrategy A strategy for sharding the data.
+     */
+    public Object execute(Walker walker, Iterable<Shard> shardStrategy) {
+        super.startingExecution();
+        walker.initialize();
+        Accumulator accumulator = Accumulator.create(engine,walker);
+
+        boolean done = walker.isDone();
+        int counter = 0;
+
+        final TraversalEngine traversalEngine = borrowTraversalEngine(this);
+        for (Shard shard : shardStrategy ) {
+            if ( abortExecution() || done || shard == null ) // we ran out of shards that aren't owned
+                break;
+
+            if(shard.getShardType() == Shard.ShardType.LOCUS) {
+                WindowMaker windowMaker = new WindowMaker(shard, engine.getGenomeLocParser(),
+                        getReadIterator(shard), shard.getGenomeLocs(), SampleUtils.getSAMFileSamples(engine));
+                for(WindowMaker.WindowMakerIterator iterator: windowMaker) {
+                    ShardDataProvider dataProvider = new LocusShardDataProvider(shard,iterator.getSourceInfo(),engine.getGenomeLocParser(),iterator.getLocus(),iterator,reference,rods);
+                    Object result = traversalEngine.traverse(walker, dataProvider, accumulator.getReduceInit());
+                    accumulator.accumulate(dataProvider,result);
+                    dataProvider.close();
+                    if ( walker.isDone() ) break;
+                }
+                windowMaker.close();
+            }
+            else {
+                ShardDataProvider dataProvider = new ReadShardDataProvider(shard,engine.getGenomeLocParser(),getReadIterator(shard),reference,rods);
+                Object result = traversalEngine.traverse(walker, dataProvider, accumulator.getReduceInit());
+                accumulator.accumulate(dataProvider,result);
+                dataProvider.close();
+            }
+
+            done = walker.isDone();
+        }
+
+        Object result = accumulator.finishTraversal();
+
+        outputTracker.close();
+        returnTraversalEngine(this, traversalEngine);
+        cleanup();
+        executionIsDone();
+
+        return accumulator;
+    }
+
+    /**
+     * @{inheritDoc}
+     */
+    public OutputTracker getOutputTracker() { return outputTracker; }
+}
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/executive/MicroScheduler.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/executive/MicroScheduler.java
new file mode 100644
index 0000000..e192b9a
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/executive/MicroScheduler.java
@@ -0,0 +1,463 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.engine.executive;
+
+import com.google.java.contract.Ensures;
+import htsjdk.samtools.reference.IndexedFastaSequenceFile;
+import org.apache.log4j.Logger;
+import org.broadinstitute.gatk.engine.GenomeAnalysisEngine;
+import org.broadinstitute.gatk.engine.ReadMetrics;
+import org.broadinstitute.gatk.engine.datasources.reads.SAMDataSource;
+import org.broadinstitute.gatk.engine.datasources.reads.Shard;
+import org.broadinstitute.gatk.engine.datasources.rmd.ReferenceOrderedDataSource;
+import org.broadinstitute.gatk.engine.io.OutputTracker;
+import org.broadinstitute.gatk.engine.iterators.NullSAMIterator;
+import org.broadinstitute.gatk.engine.iterators.GATKSAMIterator;
+import org.broadinstitute.gatk.engine.resourcemanagement.ThreadAllocation;
+import org.broadinstitute.gatk.engine.traversals.*;
+import org.broadinstitute.gatk.engine.walkers.*;
+import org.broadinstitute.gatk.utils.AutoFormattingTime;
+import org.broadinstitute.gatk.utils.MathUtils;
+import org.broadinstitute.gatk.utils.exceptions.ReviewedGATKException;
+import org.broadinstitute.gatk.utils.exceptions.UserException;
+import org.broadinstitute.gatk.utils.progressmeter.ProgressMeter;
+import org.broadinstitute.gatk.utils.threading.ThreadEfficiencyMonitor;
+
+import javax.management.JMException;
+import javax.management.MBeanServer;
+import javax.management.ObjectName;
+import java.io.File;
+import java.lang.management.ManagementFactory;
+import java.util.*;
+
+
+/**
+ * Created by IntelliJ IDEA.
+ * User: mhanna
+ * Date: Apr 26, 2009
+ * Time: 12:37:23 PM
+ *
+ * General base class for all scheduling algorithms
+ * Shards and schedules data in manageable chunks.
+ *
+ * Creates N TraversalEngines for each data thread for the MicroScheduler.  This is necessary
+ * because in the HMS case you have multiple threads executing a traversal engine independently, and
+ * these engines may need to create separate resources for efficiency or implementation reasons.  For example,
+ * the nanoScheduler creates threads to implement the traversal, and this creation is instance specific.
+ * So each HMS thread needs to have it's own distinct copy of the traversal engine if it wants to have
+ * N data threads x M nano threads => N * M threads total.  These are borrowed from this microscheduler
+ * and returned when done.  Also allows us to tracks all created traversal engines so this microscheduler
+ * can properly shut them all down when the scheduling is done.
+ *
+ */
+public abstract class MicroScheduler implements MicroSchedulerMBean {
+    protected static final Logger logger = Logger.getLogger(MicroScheduler.class);
+
+    /**
+     * The list of all Traversal engines we've created in this micro scheduler
+     */
+    final List<TraversalEngine> allCreatedTraversalEngines = new LinkedList<TraversalEngine>();
+
+    /**
+     * All available engines.  Engines are borrowed and returned when a subclass is actually
+     * going to execute the engine on some data.  This allows us to have N copies for
+     * N data parallel executions, but without the dangerous code of having local
+     * ThreadLocal variables.
+     */
+    final LinkedList<TraversalEngine> availableTraversalEngines = new LinkedList<TraversalEngine>();
+
+    /**
+     * Engines that have been allocated to a key already.
+     */
+    final HashMap<Object, TraversalEngine> allocatedTraversalEngines = new HashMap<Object, TraversalEngine>();
+
+    /**
+     * Counts the number of instances of the class that are currently alive.
+     */
+    private static int instanceNumber = 0;
+
+    /**
+     * The engine invoking this scheduler.
+     */
+    protected final GenomeAnalysisEngine engine;
+
+    protected final IndexedFastaSequenceFile reference;
+
+    private final SAMDataSource reads;
+    protected final Collection<ReferenceOrderedDataSource> rods;
+
+    private final MBeanServer mBeanServer;
+    private final ObjectName mBeanName;
+
+    /**
+     * Threading efficiency monitor for tracking the resource utilization of the GATK
+     *
+     * may be null
+     */
+    ThreadEfficiencyMonitor threadEfficiencyMonitor = null;
+
+    /**
+     * MicroScheduler factory function.  Create a microscheduler appropriate for reducing the
+     * selected walker.
+     *
+     * @param walker        Which walker to use.
+     * @param reads         the informations associated with the reads
+     * @param reference     the reference file
+     * @param rods          the rods to include in the traversal
+     * @param threadAllocation Number of threads to utilize.
+     *
+     * @return The best-fit microscheduler.
+     */
+    public static MicroScheduler create(GenomeAnalysisEngine engine, Walker walker, SAMDataSource reads, IndexedFastaSequenceFile reference, Collection<ReferenceOrderedDataSource> rods, ThreadAllocation threadAllocation) {
+        if ( threadAllocation.isRunningInParallelMode() ) {
+            logger.info(String.format("Running the GATK in parallel mode with %d total threads, " +
+                    "%d CPU thread(s) for each of %d data thread(s), of %d processors available on this machine",
+                    threadAllocation.getTotalNumThreads(),
+                    threadAllocation.getNumCPUThreadsPerDataThread(),
+                    threadAllocation.getNumDataThreads(),
+                    Runtime.getRuntime().availableProcessors()));
+            if ( threadAllocation.getTotalNumThreads() > Runtime.getRuntime().availableProcessors() )
+                logger.warn(String.format("Number of requested GATK threads %d is more than the number of " +
+                        "available processors on this machine %d", threadAllocation.getTotalNumThreads(),
+                        Runtime.getRuntime().availableProcessors()));
+        }
+
+        if ( threadAllocation.getNumDataThreads() > 1 ) {
+            if (walker.isReduceByInterval())
+                throw new UserException.BadArgumentValue("nt", String.format("This run of %s is set up to aggregate results by interval.  Due to a current limitation of the GATK, analyses of this type do not currently support parallel execution.  Please run your analysis without the -nt option or check if this tool has an option to disable per-interval calculations.", engine.getWalkerName(walker.getClass())));
+
+            if ( ! (walker instanceof TreeReducible) ) {
+                throw badNT("nt", engine, walker);
+            }
+        }
+
+        if ( threadAllocation.getNumCPUThreadsPerDataThread() > 1 && ! (walker instanceof NanoSchedulable) ) {
+            throw badNT("nct", engine, walker);
+        }
+
+        if ( threadAllocation.getNumDataThreads() > 1 ) {
+            return new HierarchicalMicroScheduler(engine, walker, reads, reference, rods, threadAllocation);
+        } else {
+            return new LinearMicroScheduler(engine, walker, reads, reference, rods, threadAllocation);
+        }
+    }
+
+    private static UserException badNT(final String parallelArg, final GenomeAnalysisEngine engine, final Walker walker) {
+        throw new UserException.BadArgumentValue(parallelArg,
+                String.format("The analysis %s currently does not support parallel execution with %s.  " +
+                        "Please run your analysis without the %s option.", engine.getWalkerName(walker.getClass()), parallelArg, parallelArg));
+    }
+
+    /**
+     * Create a microscheduler given the reads and reference.
+     *
+     * @param walker  the walker to execute with
+     * @param reads   The reads.
+     * @param reference The reference.
+     * @param rods    the rods to include in the traversal
+     * @param threadAllocation the allocation of threads to use in the underlying traversal
+     */
+    protected MicroScheduler(final GenomeAnalysisEngine engine,
+                             final Walker walker,
+                             final SAMDataSource reads,
+                             final IndexedFastaSequenceFile reference,
+                             final Collection<ReferenceOrderedDataSource> rods,
+                             final ThreadAllocation threadAllocation) {
+        this.engine = engine;
+        this.reads = reads;
+        this.reference = reference;
+        this.rods = rods;
+
+        final File progressLogFile = engine.getArguments() == null ? null : engine.getArguments().performanceLog;
+
+        // Creates uninitialized TraversalEngines appropriate for walker and threadAllocation,
+        // and adds it to the list of created engines for later shutdown.
+        for ( int i = 0; i < threadAllocation.getNumDataThreads(); i++ ) {
+            final TraversalEngine traversalEngine = createTraversalEngine(walker, threadAllocation);
+            allCreatedTraversalEngines.add(traversalEngine);
+            availableTraversalEngines.add(traversalEngine);
+        }
+
+        // Create the progress meter, and register it with the analysis engine
+        engine.registerProgressMeter(new ProgressMeter(progressLogFile,
+                availableTraversalEngines.peek().getTraversalUnits(),
+                engine.getRegionsOfGenomeBeingProcessed()));
+
+        // Now that we have a progress meter, go through and initialize the traversal engines
+        for ( final TraversalEngine traversalEngine : allCreatedTraversalEngines )
+            traversalEngine.initialize(engine, walker, engine.getProgressMeter());
+
+        // JMX does not allow multiple instances with the same ObjectName to be registered with the same platform MXBean.
+        // To get around this limitation and since we have no job identifier at this point, register a simple counter that
+        // will count the number of instances of this object that have been created in this JVM.
+        int thisInstance = instanceNumber++;
+        mBeanServer = ManagementFactory.getPlatformMBeanServer();
+        try {
+            mBeanName = new ObjectName("org.broadinstitute.gatk.engine.executive:type=MicroScheduler,instanceNumber="+thisInstance);
+            mBeanServer.registerMBean(this, mBeanName);
+        }
+        catch (JMException ex) {
+            throw new ReviewedGATKException("Unable to register microscheduler with JMX", ex);
+        }
+    }
+
+    /**
+     * Really make us a traversal engine of the appropriate type for walker and thread allocation
+     *
+     * @return a non-null uninitialized traversal engine
+     */
+    @Ensures("result != null")
+    private TraversalEngine createTraversalEngine(final Walker walker, final ThreadAllocation threadAllocation) {
+        if (walker instanceof ReadWalker) {
+            return new TraverseReadsNano(threadAllocation.getNumCPUThreadsPerDataThread());
+        } else if (walker instanceof LocusWalker) {
+            return new TraverseLociNano(threadAllocation.getNumCPUThreadsPerDataThread());
+        } else if (walker instanceof DuplicateWalker) {
+            return new TraverseDuplicates();
+        } else if (walker instanceof ReadPairWalker) {
+            return new TraverseReadPairs();
+        } else if (walker instanceof ActiveRegionWalker) {
+            return new TraverseActiveRegions(threadAllocation.getNumCPUThreadsPerDataThread());
+        } else {
+            throw new UnsupportedOperationException("Unable to determine traversal type, the walker is an unknown type.");
+        }
+    }
+
+
+    /**
+     * Return the ThreadEfficiencyMonitor we are using to track our resource utilization, if there is one
+     *
+     * @return the monitor, or null if none is active
+     */
+    public ThreadEfficiencyMonitor getThreadEfficiencyMonitor() {
+        return threadEfficiencyMonitor;
+    }
+
+    /**
+     * Inform this Microscheduler to use the efficiency monitor used to create threads in subclasses
+     *
+     * @param threadEfficiencyMonitor
+     */
+    public void setThreadEfficiencyMonitor(final ThreadEfficiencyMonitor threadEfficiencyMonitor) {
+        this.threadEfficiencyMonitor = threadEfficiencyMonitor;
+    }
+
+    /**
+     * Should we stop all execution work and exit gracefully?
+     *
+     * Returns true in the case where some external signal or time limit has been received, indicating
+     * that this GATK shouldn't continue executing.  This isn't a kill signal, it is really a "shutdown
+     * gracefully at the next opportunity" signal.  Concrete implementations of the MicroScheduler
+     * examine this value as often as reasonable and, if it returns true, stop what they are doing
+     * at the next available opportunity, shutdown their resources, call notify done, and return.
+     *
+     * @return true if we should abort execution, or false otherwise
+     */
+    protected boolean abortExecution() {
+        final boolean abort = engine.exceedsRuntimeLimit();
+        if ( abort ) {
+            final AutoFormattingTime aft = new AutoFormattingTime(engine.getRuntimeLimitInNanoseconds(), -1, 4);
+            logger.info("Aborting execution (cleanly) because the runtime has exceeded the requested maximum " + aft);
+        }
+        return abort;
+    }
+
+    /**
+     * Walks a walker over the given list of intervals.
+     *
+     * @param walker        Computation to perform over dataset.
+     * @param shardStrategy A strategy for sharding the data.
+     *
+     * @return the return type of the walker
+     */
+    public abstract Object execute(Walker walker, Iterable<Shard> shardStrategy);
+
+    /**
+     * Tells this MicroScheduler that the execution of one of the subclass of this object as started
+     *
+     * Must be called when the implementation of execute actually starts up
+     *
+     * Currently only starts the progress meter timer running, but other start up activities could be incorporated
+     */
+    protected void startingExecution() {
+        engine.getProgressMeter().start();
+    }
+
+    /**
+     * Retrieves the object responsible for tracking and managing output.
+     * @return An output tracker, for loading data in and extracting results.  Will not be null.
+     */
+    public abstract OutputTracker getOutputTracker();
+
+    /**
+     * Gets the an iterator over the given reads, which will iterate over the reads in the given shard.
+     * @param shard the shard to use when querying reads.
+     * @return an iterator over the reads specified in the shard.
+     */
+    protected GATKSAMIterator getReadIterator(Shard shard) {
+        return (!reads.isEmpty()) ? reads.seek(shard) : new NullSAMIterator();
+    }
+
+    /**
+     * Must be called by subclasses when execute is done
+     */
+    protected void executionIsDone() {
+        engine.getProgressMeter().notifyDone(engine.getCumulativeMetrics().getNumIterations());
+        printReadFilteringStats();
+        shutdownTraversalEngines();
+
+        // Print out the threading efficiency of this HMS, if state monitoring is enabled
+        if ( threadEfficiencyMonitor != null ) {
+            // include the master thread information
+            threadEfficiencyMonitor.threadIsDone(Thread.currentThread());
+            threadEfficiencyMonitor.printUsageInformation(logger);
+        }
+    }
+
+    /**
+     * Shutdown all of the created engines, and clear the list of created engines, dropping
+     * pointers to the traversal engines
+     */
+    public synchronized void shutdownTraversalEngines() {
+        for ( final TraversalEngine te : allCreatedTraversalEngines)
+            te.shutdown();
+
+        allCreatedTraversalEngines.clear();
+        availableTraversalEngines.clear();
+    }
+
+    /**
+     * Prints out information about number of reads observed and filtering, if any reads were used in the traversal
+     *
+     * Looks like:
+     *
+     * INFO  10:40:47,370 MicroScheduler - 22 reads were filtered out during traversal out of 101 total (21.78%)
+     * INFO  10:40:47,370 MicroScheduler -   -> 1 reads (0.99% of total) failing BadMateFilter
+     * INFO  10:40:47,370 MicroScheduler -   -> 20 reads (19.80% of total) failing DuplicateReadFilter
+     * INFO  10:40:47,370 MicroScheduler -   -> 1 reads (0.99% of total) failing FailsVendorQualityCheckFilter
+     */
+    private void printReadFilteringStats() {
+        final ReadMetrics cumulativeMetrics = engine.getCumulativeMetrics();
+        if ( cumulativeMetrics.getNumReadsSeen() > 0 ) {
+            // count up the number of skipped reads by summing over all filters
+            long nSkippedReads = 0L;
+            for ( final long countsByFilter : cumulativeMetrics.getCountsByFilter().values())
+                nSkippedReads += countsByFilter;
+
+            logger.info(String.format("%d reads were filtered out during the traversal out of approximately %d total reads (%.2f%%)",
+                    nSkippedReads,
+                    cumulativeMetrics.getNumReadsSeen(),
+                    100.0 * MathUtils.ratio(nSkippedReads, cumulativeMetrics.getNumReadsSeen())));
+
+            for ( final Map.Entry<String, Long> filterCounts : cumulativeMetrics.getCountsByFilter().entrySet() ) {
+                long count = filterCounts.getValue();
+                logger.info(String.format("  -> %d reads (%.2f%% of total) failing %s",
+                        count, 100.0 * MathUtils.ratio(count,cumulativeMetrics.getNumReadsSeen()), filterCounts.getKey()));
+            }
+        }
+    }
+
+    /**
+     * Gets the engine that created this microscheduler.
+     * @return The engine owning this microscheduler.
+     */
+    public GenomeAnalysisEngine getEngine() { return engine; }
+
+    /**
+     * Returns data source maintained by this scheduler
+     * @return
+     */
+    public SAMDataSource getSAMDataSource() { return reads; }
+
+    /**
+     * Returns the reference maintained by this scheduler.
+     * @return The reference maintained by this scheduler.
+     */
+    public IndexedFastaSequenceFile getReference() { return reference; }
+
+    protected void cleanup() {
+        try {
+            mBeanServer.unregisterMBean(mBeanName);
+        }
+        catch (JMException ex) {
+            throw new ReviewedGATKException("Unable to unregister microscheduler with JMX", ex);
+        }
+    }
+
+    /**
+     * Returns a traversal engine suitable for use, associated with key
+     *
+     * Key is an arbitrary object that is used to retrieve the same traversal
+     * engine over and over.  This can be important in the case where the
+     * traversal engine has data associated with it in some other context,
+     * and we need to ensure that the context always sees the same traversal
+     * engine.  This happens in the HierarchicalMicroScheduler, where you want
+     * the a thread executing traversals to retrieve the same engine each time,
+     * as outputs are tracked w.r.t. that engine.
+     *
+     * If no engine is associated with key yet, pops the next available engine
+     * from the available ones maintained by this
+     * microscheduler.  Note that it's a runtime error to pop a traversal engine
+     * from this scheduler if there are none available.  Callers that
+     * once pop'd an engine for use must return it with returnTraversalEngine
+     *
+     * @param key the key to associate with this engine
+     * @return a non-null TraversalEngine suitable for execution in this scheduler
+     */
+    @Ensures("result != null")
+    protected synchronized TraversalEngine borrowTraversalEngine(final Object key) {
+        if ( key == null ) throw new IllegalArgumentException("key cannot be null");
+
+        final TraversalEngine engine = allocatedTraversalEngines.get(key);
+        if ( engine == null ) {
+            if ( availableTraversalEngines.isEmpty() )
+                throw new IllegalStateException("no traversal engines were available");
+            allocatedTraversalEngines.put(key, availableTraversalEngines.pop());
+            return allocatedTraversalEngines.get(key);
+        } else {
+            return engine;
+        }
+    }
+
+    /**
+     * Return a borrowed traversal engine to this MicroScheduler, for later use
+     * in another traversal execution
+     *
+     * @param key the key used to id the engine, provided to the borrowTraversalEngine function
+     * @param traversalEngine the borrowed traversal engine.  Must have been previously borrowed.
+     */
+    protected synchronized void returnTraversalEngine(final Object key, final TraversalEngine traversalEngine) {
+        if ( traversalEngine == null )
+            throw new IllegalArgumentException("Attempting to push a null traversal engine");
+        if ( ! allCreatedTraversalEngines.contains(traversalEngine) )
+            throw new IllegalArgumentException("Attempting to push a traversal engine not created by this MicroScheduler" + engine);
+        if ( ! allocatedTraversalEngines.containsKey(key) )
+            throw new IllegalArgumentException("No traversal engine was never checked out with key " + key);
+
+        // note there's nothing to actually do here, but a function implementation
+        // might want to do something
+    }
+}
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/executive/MicroSchedulerMBean.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/executive/MicroSchedulerMBean.java
new file mode 100644
index 0000000..772fe01
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/executive/MicroSchedulerMBean.java
@@ -0,0 +1,37 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.engine.executive;
+
+/**
+ * Created by IntelliJ IDEA.
+ * User: mhanna
+ * Date: Jan 12, 2011
+ * Time: 9:19:27 PM
+ * To change this template use File | Settings | File Templates.
+ */
+public interface MicroSchedulerMBean {
+    // has nothing because we don't have anything we currently track
+}
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/executive/OutputMergeTask.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/executive/OutputMergeTask.java
new file mode 100644
index 0000000..4e5ef9f
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/executive/OutputMergeTask.java
@@ -0,0 +1,102 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.engine.executive;
+
+import org.broadinstitute.gatk.engine.io.storage.Storage;
+
+import java.util.ArrayList;
+import java.util.Collection;
+
+/**
+ * User: hanna
+ * Date: Apr 30, 2009
+ * Time: 4:04:38 PM
+ * BROAD INSTITUTE SOFTWARE COPYRIGHT NOTICE AND AGREEMENT
+ * Software and documentation are copyright 2005 by the Broad Institute.
+ * All rights are reserved.
+ *
+ * Users acknowledge that this software is supplied without any warranty or support.
+ * The Broad Institute is not responsible for its use, misuse, or
+ * functionality.
+ */
+
+/**
+ * Hold pointers to the output and error streams, and state to indicate whether
+ * a write is complete.  Not generally thread-safe.  Calls to isComplete()/complete()
+ * can be made at any time from any thread, but complete() should be called on the
+ * thread which is doing the writing. 
+ */
+public class OutputMergeTask {
+    /**
+     * The output streams which should be written to.
+     */
+    private final Collection<MergeOperation<?>> mergeOperations = new ArrayList<MergeOperation<?>>();
+
+    /**
+     * Add a new merge operation to this merge task.
+     * @param targetStream Target for stream output.
+     * @param temporaryStorage Temporary storage.
+     * @param <StreamType> Type of the output stream.
+     */
+    public <StreamType> void addMergeOperation( StreamType targetStream, Storage<StreamType> temporaryStorage ) {
+        mergeOperations.add( new MergeOperation<StreamType>(targetStream,temporaryStorage) );
+    }
+
+    /**
+     * Merge data from output streams into target storage.
+     */
+    public synchronized void merge() {
+        for( MergeOperation mergeOperation: mergeOperations )
+            mergeOperation.temporaryStorage.mergeInto(mergeOperation.targetStream);
+    }
+
+    /**
+     * Represents a single file needed to be merged.
+     * @param <StreamType> Type of the file to be merged.
+     */
+    private class MergeOperation<StreamType> {
+        /**
+         * Destination for the temporary file's output.
+         */
+        public final StreamType targetStream;
+
+        /**
+         * Temporary storage location for the file.
+         */
+        public final Storage<StreamType> temporaryStorage;
+
+        /**
+         * Create a new merge file object with the given output stream and storage placeholder.
+         * @param targetStream Target for temporary data.
+         * @param temporaryStorage The temporary data itself.
+         */
+        public MergeOperation( StreamType targetStream, Storage<StreamType> temporaryStorage ) {
+            this.targetStream = targetStream;
+            this.temporaryStorage = temporaryStorage;
+        }
+    }
+}
+
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/executive/ReduceTree.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/executive/ReduceTree.java
new file mode 100644
index 0000000..e02b846
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/executive/ReduceTree.java
@@ -0,0 +1,187 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.engine.executive;
+
+import java.util.ArrayList;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Queue;
+import java.util.concurrent.Future;
+/**
+ * User: hanna
+ * Date: Apr 28, 2009
+ * Time: 11:09:29 AM
+ * BROAD INSTITUTE SOFTWARE COPYRIGHT NOTICE AND AGREEMENT
+ * Software and documentation are copyright 2005 by the Broad Institute.
+ * All rights are reserved.
+ *
+ * Users acknowledge that this software is supplied without any warranty or support.
+ * The Broad Institute is not responsible for its use, misuse, or
+ * functionality.
+ */
+
+/**
+ * A tree for organizing reduce results and detecting when enough dependencies
+ * are resolved for a reduce to be scheduled.  The tree can trigger a callback
+ * whenever it believes a reduce operation is pending.
+ *
+ * Not thread-safe.  All calls should be made sequentially from the same thread.
+ */
+public class ReduceTree {
+    /**
+     * Data structure for the tree.  Each entry in the outer list represents a level
+     * of the tree, and each entry in the inner queues represent nodes in that level.
+     *
+     * Whenever a reduce can happen, the entries to be reduced are pulled out of
+     * their slots in level n of the tree and the composite entry is added to level n+1.
+     */
+    private List<Queue<Future>> treeNodes = new ArrayList<Queue<Future>>();
+
+    /**
+     * The entire contents have been added to the tree.  Completely schedule the reductions.
+     */
+    private boolean treeComplete = false;
+
+    /**
+     * Called to indicate that all data required to perform a given reduce has been scheduled.
+     */
+    private TreeReduceNotifier treeReduceNotifier = null;
+
+    /**
+     * Creates a ReduceTree.
+     * @param notifier A callback indicating that all data required to perform a given reduce has been scheduled.
+     */
+    public ReduceTree( TreeReduceNotifier notifier ) {
+        this.treeReduceNotifier = notifier;
+    }
+
+    /**
+     * A callback indicating that all computations have been scheduled to complete the given reduce.
+     */
+    public interface TreeReduceNotifier {
+        /**
+         * Indicates that a reduce is ready to happen.
+         * @param lhs Left-hand side of the tree reduce.
+         * @param rhs Right-hand side of the tree reduce.
+         * @return The future result of the computation reduce(lhs,rhs)
+         */
+        Future notifyReduce( Future lhs, Future rhs );
+    }
+
+    /**
+     * Add an entry to the list of data to be reduced.  The results of entry.get() will
+     * be scheduled for reduction with neighboring elements.
+     * @param entry Entry to be paired with other elements.
+     */
+    public void addEntry( Future entry ) {
+        addNodeAtLevel( entry, 0 );
+    }
+
+    /**
+     * Signal to the ReduceTree that all possible data has been added and it should reduce
+     * as much as is possible.
+     */
+    public void complete() {
+        treeComplete = true;
+        reduce();
+    }
+
+    /**
+     * Gets the placeholder for the final result of the tree reduce.
+     * @return Future whose get() method will return the final result.  Null if nothing has been added.
+     */
+    public Future getResult() {
+        if( !treeComplete )
+            throw new IllegalStateException( "Cannot get the final result for an incomplete tree.");
+
+        // If nothing has been added to the tree, return null.
+        if( treeNodes.size() == 0 )
+            return null;
+
+        // Assert that there aren't any pending computations that were forgotten along the way.
+        for( int i = 0; i < treeNodes.size() - 2; i++ ) {
+            if( treeNodes.get(i).size() > 0 )
+                throw new IllegalStateException( "Some inner reduces were missed along the way.");
+        }
+
+        Queue<Future> lastLevel = treeNodes.get(treeNodes.size() - 1);
+
+        // Assert that there's only one reduce left at the last level.
+        if( lastLevel.size() != 1 )
+            throw new IllegalStateException( "Invalid number of entries at the tip of the tree: " + lastLevel.size() );
+
+        // Get the placeholder for the last result.
+        return lastLevel.element();
+    }
+
+    /**
+     * Recursively collapse the tree whereever possible.
+     */
+    protected void reduce() {
+        reduce( 0 );
+    }
+
+    /**
+     * Recursively collapse the tree, starting at the specified level.
+     * @param level Level at which to start reducing.
+     */
+    private void reduce( int level ) {
+        // base case for recursion.
+        if( treeNodes.size() <= level )
+            return;
+
+        Queue<Future> treeLevel = treeNodes.get(level);
+
+        while( treeLevel.size() >= 2 ) {
+            addNodeAtLevel( treeReduceNotifier.notifyReduce( treeLevel.remove(), treeLevel.remove() ), level + 1 );
+        }
+
+        if( treeLevel.size() == 1 && treeComplete && !isDeepestLevel(level) ) {
+            Future element = treeLevel.remove();
+            addNodeAtLevel( element, level + 1 );
+        }
+
+        reduce( level + 1 );
+    }
+
+    private boolean isDeepestLevel( int level ) {
+        return level == (treeNodes.size() - 1);
+    }
+
+    /**
+     * Add the given node to the tree at the corresponding level.  Create the level
+     * if it doesn't exist.
+     * @param node Node to add.  Must not be null.
+     * @param level Level number at which to add.  0-based index into treeNodes list.
+     */
+    protected void addNodeAtLevel( Future node, int level ) {
+        while( treeNodes.size() <= level )
+            treeNodes.add( new LinkedList<Future>() );
+        treeNodes.get(level).add(node);
+        reduce(level);
+    }
+
+}
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/executive/ShardTraverser.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/executive/ShardTraverser.java
new file mode 100644
index 0000000..443fdf7
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/executive/ShardTraverser.java
@@ -0,0 +1,163 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.engine.executive;
+
+import org.apache.log4j.Logger;
+import org.broadinstitute.gatk.engine.datasources.providers.LocusShardDataProvider;
+import org.broadinstitute.gatk.engine.datasources.providers.ShardDataProvider;
+import org.broadinstitute.gatk.engine.datasources.reads.Shard;
+import org.broadinstitute.gatk.engine.io.ThreadGroupOutputTracker;
+import org.broadinstitute.gatk.engine.traversals.TraversalEngine;
+import org.broadinstitute.gatk.engine.walkers.Walker;
+import org.broadinstitute.gatk.utils.Utils;
+import org.broadinstitute.gatk.utils.exceptions.ReviewedGATKException;
+
+import java.util.concurrent.Callable;
+/**
+ * User: hanna
+ * Date: Apr 29, 2009
+ * Time: 4:40:38 PM
+ * BROAD INSTITUTE SOFTWARE COPYRIGHT NOTICE AND AGREEMENT
+ * Software and documentation are copyright 2005 by the Broad Institute.
+ * All rights are reserved.
+ *
+ * Users acknowledge that this software is supplied without any warranty or support.
+ * The Broad Institute is not responsible for its use, misuse, or
+ * functionality.
+ */
+/**
+ * Carries the walker over a given shard, in a callable interface.
+ */
+public class ShardTraverser implements Callable {
+    final private HierarchicalMicroScheduler microScheduler;
+    final private Walker walker;
+    final private Shard shard;
+    final private ThreadGroupOutputTracker outputTracker;
+    private OutputMergeTask outputMergeTask;
+
+    /** our log, which we want to capture anything from this class */
+    final protected static Logger logger = Logger.getLogger(ShardTraverser.class);
+
+    /**
+     * Is this traversal complete?
+     */
+    private boolean complete = false;
+
+    public ShardTraverser( HierarchicalMicroScheduler microScheduler,
+                           Walker walker,
+                           Shard shard,
+                           ThreadGroupOutputTracker outputTracker) {
+        this.microScheduler = microScheduler;
+        this.walker = walker;
+        this.shard = shard;
+        this.outputTracker = outputTracker;
+    }
+
+    public Object call() {
+        final Object traversalEngineKey = Thread.currentThread();
+        final TraversalEngine traversalEngine = microScheduler.borrowTraversalEngine(traversalEngineKey);
+
+        try {
+            final long startTime = System.currentTimeMillis();
+
+            // this is CRITICAL -- initializes output maps in this master thread,
+            // so that any subthreads created by the traversal itself can access this map
+            outputTracker.initializeStorage();
+
+            Object accumulator = walker.reduceInit();
+            final WindowMaker windowMaker = new WindowMaker(shard,microScheduler.getEngine().getGenomeLocParser(),
+                    microScheduler.getReadIterator(shard),
+                    shard.getGenomeLocs(),
+                    microScheduler.engine.getSampleDB().getSampleNames()); // todo: microScheduler.engine is protected - is it okay to user it here?
+
+            for(WindowMaker.WindowMakerIterator iterator: windowMaker) {
+                final ShardDataProvider dataProvider = new LocusShardDataProvider(shard,iterator.getSourceInfo(),microScheduler.getEngine().getGenomeLocParser(),iterator.getLocus(),iterator,microScheduler.reference,microScheduler.rods);
+                accumulator = traversalEngine.traverse(walker, dataProvider, accumulator);
+                dataProvider.close();
+            }
+
+            windowMaker.close();
+            outputMergeTask = outputTracker.closeStorage();
+
+            final long endTime = System.currentTimeMillis();
+
+            microScheduler.reportShardTraverseTime(endTime-startTime);
+
+            return accumulator;
+        } catch(Throwable t) {
+            // Notify that an exception has occurred and rethrow it.
+            throw microScheduler.notifyOfTraversalError(t);
+        } finally {
+            synchronized(this) {
+                complete = true;
+                microScheduler.returnTraversalEngine(traversalEngineKey, traversalEngine);
+                notifyAll();
+            }
+        }
+    }
+
+    /**
+     * Return a human readable string describing the intervals this traverser is operating on
+     * @return
+     */
+    public String getIntervalsString() {
+        return Utils.join(",", shard.getGenomeLocs());
+    }
+
+    /**
+     * Has this traversal completed?
+     * @return True if completed, false otherwise.
+     */
+    public boolean isComplete() {
+        synchronized(this) {
+            return complete;
+        }
+    }
+
+   /**
+     * Waits for any the given OutputMerger to be ready for merging.
+     */
+    public void waitForComplete() {
+        try {
+            synchronized(this) {
+                if( isComplete() )
+                    return;
+                wait();
+            }
+        }
+        catch( InterruptedException ex ) {
+            throw new ReviewedGATKException("Interrupted while waiting for more output to be finalized.",ex);
+        }
+    }
+
+    /**
+     * Gets the output merge task associated with the given shard.
+     * @return OutputMergeTask if one exists; null if nothing needs to be merged.
+     */
+    public OutputMergeTask getOutputMergeTask() {
+        return outputMergeTask;
+    }
+}
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/executive/TreeReducer.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/executive/TreeReducer.java
new file mode 100644
index 0000000..270b06f
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/executive/TreeReducer.java
@@ -0,0 +1,127 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.engine.executive;
+
+import org.broadinstitute.gatk.engine.walkers.TreeReducible;
+import org.broadinstitute.gatk.utils.exceptions.ReviewedGATKException;
+
+import java.util.concurrent.Callable;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.Future;
+/**
+ * User: hanna
+ * Date: Apr 29, 2009
+ * Time: 4:47:35 PM
+ * BROAD INSTITUTE SOFTWARE COPYRIGHT NOTICE AND AGREEMENT
+ * Software and documentation are copyright 2005 by the Broad Institute.
+ * All rights are reserved.
+ *
+ * Users acknowledge that this software is supplied without any warranty or support.
+ * The Broad Institute is not responsible for its use, misuse, or
+ * functionality.
+ */
+
+/**
+ * Represents a future reduce...a reduce that will be ready at some point in the future.
+ * Provides services for indicating when all data is prepared for the reduce a callable
+ * interface to force the reduce.
+ */
+public class TreeReducer implements Callable {
+    final private HierarchicalMicroScheduler microScheduler;
+    private TreeReducible walker;
+    private Future lhs;
+    private Future rhs;
+
+    /**
+     * Create a full tree reduce.  Combine this two results using an unspecified walker at some point in the future.
+     * @param microScheduler The parent hierarchical microscheduler for this reducer.
+     * @param lhs Left-hand side of the reduce.
+     * @param rhs Right-hand side of the reduce.
+     */
+    public TreeReducer( HierarchicalMicroScheduler microScheduler, Future lhs, Future rhs ) {
+        this.microScheduler = microScheduler;
+        this.lhs = lhs;
+        this.rhs = rhs;
+    }
+
+    /**
+     * Provide a walker for the future reduce.
+     * @param walker walker to use when performing the reduce.
+     */
+    public void setWalker( TreeReducible walker ) {
+        this.walker = walker;
+    }
+
+    /**
+     * Is the data ready for reduce?  True if lhs and rhs have already been resolved.
+     * @return True if data is ready and waiting, false otherwise.
+     */
+    public boolean isReadyForReduce() {
+        if( lhs == null )
+            throw new IllegalStateException(String.format("Insufficient data on which to reduce; lhs = %s, rhs = %s", lhs, rhs) );
+
+        return lhs.isDone() && (rhs == null || rhs.isDone());
+    }
+
+    /**
+     * Returns the value of the reduce.  If not isReadyForReduce(), this call will until all entries become ready.
+     * @return Result of the reduce.
+     */
+    public Object call() {
+        Object result;
+
+        final long startTime = System.currentTimeMillis();
+
+        try {
+            if( lhs == null )
+                result = null;
+                // todo -- what the hell is this above line?  Shouldn't it be the two below?
+//            if( lhs == null )
+//                throw new IllegalStateException(String.format("Insufficient data on which to reduce; lhs = %s, rhs = %s", lhs, rhs) );
+            else
+                result = walker.treeReduce( lhs.get(), rhs.get() );
+        }
+        catch( InterruptedException ex ) {
+            microScheduler.notifyOfTraversalError(ex);
+            throw new ReviewedGATKException("Hierarchical reduce interrupted", ex);
+        }
+        catch( ExecutionException ex ) {
+            microScheduler.notifyOfTraversalError(ex);
+            throw new ReviewedGATKException("Hierarchical reduce failed", ex);
+        }
+
+        final long endTime = System.currentTimeMillis();
+
+        // Constituent bits of this tree reduces are no longer required.  Throw them away.
+        this.lhs = null;
+        this.rhs = null;
+
+        microScheduler.reportTreeReduceTime( endTime - startTime );
+
+        return result;
+    }
+}
+
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/executive/WindowMaker.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/executive/WindowMaker.java
new file mode 100644
index 0000000..c848329
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/executive/WindowMaker.java
@@ -0,0 +1,217 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.engine.executive;
+
+import htsjdk.samtools.util.PeekableIterator;
+import org.broadinstitute.gatk.engine.ReadProperties;
+import org.broadinstitute.gatk.engine.contexts.AlignmentContext;
+import org.broadinstitute.gatk.engine.datasources.reads.Shard;
+import org.broadinstitute.gatk.engine.iterators.GATKSAMRecordIterator;
+import org.broadinstitute.gatk.engine.iterators.GATKSAMIterator;
+import org.broadinstitute.gatk.utils.GenomeLoc;
+import org.broadinstitute.gatk.utils.GenomeLocParser;
+import org.broadinstitute.gatk.utils.exceptions.ReviewedGATKException;
+import org.broadinstitute.gatk.utils.locusiterator.LocusIterator;
+import org.broadinstitute.gatk.utils.locusiterator.LocusIteratorByState;
+import org.broadinstitute.gatk.utils.sam.GATKSAMRecord;
+
+import java.util.Collection;
+import java.util.Iterator;
+import java.util.List;
+import java.util.NoSuchElementException;
+
+/**
+ * Transforms an iterator of reads which overlap the given interval list into an iterator of covered single-base loci
+ * completely contained within the interval list.  To do this, it creates a LocusIteratorByState which will emit a single-bp
+ * locus for every base covered by the read iterator, then uses the WindowMakerIterator.advance() to filter down that stream of
+ * loci to only those covered by the given interval list.
+ *
+ * Example:
+ * Incoming stream of reads: A:chr20:1-5, B:chr20:2-6, C:chr20:2-7, D:chr20:3-8, E:chr20:5-10
+ * Incoming intervals: chr20:3-7
+ *
+ * Locus iterator by state will produce the following stream of data:
+ *  chr1:1 {A}, chr1:2 {A,B,C}, chr1:3 {A,B,C,D}, chr1:4 {A,B,C,D}, chr1:5 {A,B,C,D,E},
+ *  chr1:6 {B,C,D,E}, chr1:7 {C,D,E}, chr1:8 {D,E}, chr1:9 {E}, chr1:10 {E}
+ *
+ * WindowMakerIterator will then filter the incoming stream, emitting the following stream:
+ *  chr1:3 {A,B,C,D}, chr1:4 {A,B,C,D}, chr1:5 {A,B,C,D,E}, chr1:6 {B,C,D,E}, chr1:7 {C,D,E}
+ *
+ * @author mhanna
+ * @version 0.1
+ */
+public class WindowMaker implements Iterable<WindowMaker.WindowMakerIterator>, Iterator<WindowMaker.WindowMakerIterator> {
+    /**
+     * Source information for iteration.
+     */
+    private final ReadProperties sourceInfo;
+
+    /**
+     * Hold the read iterator so that it can be closed later.
+     */
+    private final GATKSAMRecordIterator readIterator;
+
+    /**
+     * The data source for reads.  Will probably come directly from the BAM file.
+     */
+    private final PeekableIterator<AlignmentContext> sourceIterator;
+
+    /**
+     * Stores the sequence of intervals that the windowmaker should be tracking.
+     */
+    private final PeekableIterator<GenomeLoc> intervalIterator;
+
+    /**
+     * In the case of monolithic sharding, this case returns whether the only shard has been generated.
+     */
+    private boolean shardGenerated = false;
+
+    /**
+     * The alignment context to return from this shard's iterator.  Lazy implementation: the iterator will not find the
+     * currentAlignmentContext until absolutely required to do so.   If currentAlignmentContext is null and advance()
+     * doesn't populate it, no more elements are available.  If currentAlignmentContext is non-null, currentAlignmentContext
+     * should be returned by next().
+     */
+    private AlignmentContext currentAlignmentContext;
+
+    /**
+     * Create a new window maker with the given iterator as a data source, covering
+     * the given intervals.
+     * @param iterator The data source for this window.
+     * @param intervals The set of intervals over which to traverse.
+     * @param sampleNames The complete set of sample names in the reads in shard
+     */
+
+    private final LocusIteratorByState libs;
+
+    public WindowMaker(Shard shard, GenomeLocParser genomeLocParser, GATKSAMIterator iterator, List<GenomeLoc> intervals, Collection<String> sampleNames) {
+        this.sourceInfo = shard.getReadProperties();
+        this.readIterator = new GATKSAMRecordIterator(iterator);
+
+        this.libs = new LocusIteratorByState(readIterator,sourceInfo,genomeLocParser,sampleNames);
+        this.sourceIterator = new PeekableIterator<AlignmentContext>(libs);
+
+        this.intervalIterator = intervals.size()>0 ? new PeekableIterator<GenomeLoc>(intervals.iterator()) : null;
+    }
+
+    public WindowMaker(Shard shard, GenomeLocParser genomeLocParser, GATKSAMIterator iterator, List<GenomeLoc> intervals ) {
+        this(shard, genomeLocParser, iterator, intervals, LocusIteratorByState.sampleListForSAMWithoutReadGroups());
+    }
+
+    public Iterator<WindowMakerIterator> iterator() {
+        return this;
+    }
+
+    public boolean hasNext() {
+        return (intervalIterator != null && intervalIterator.hasNext()) || !shardGenerated;
+    }
+
+    public WindowMakerIterator next() {
+        shardGenerated = true;
+        return new WindowMakerIterator(intervalIterator != null ? intervalIterator.next() : null);
+    }
+
+    public void remove() {
+        throw new UnsupportedOperationException("Cannot remove from a window maker.");
+    }
+
+    public void close() {
+        this.readIterator.close();
+    }
+
+    public class WindowMakerIterator extends LocusIterator {
+        /**
+         * The locus for which this iterator is currently returning reads.
+         */
+        private final GenomeLoc locus;
+
+        public WindowMakerIterator(GenomeLoc locus) {
+            this.locus = locus;
+            advance();
+        }
+
+        public ReadProperties getSourceInfo() {
+            return sourceInfo;
+        }
+
+        public GenomeLoc getLocus() {
+            return locus;
+        }
+
+        public WindowMakerIterator iterator() {
+            return this;
+        }
+
+        public boolean hasNext() {
+            advance();
+            return currentAlignmentContext != null;
+        }
+
+        public AlignmentContext next() {
+            if(!hasNext()) throw new NoSuchElementException("WindowMakerIterator is out of elements for this interval.");
+
+            // Consume this alignment context.
+            AlignmentContext toReturn = currentAlignmentContext;
+            currentAlignmentContext = null;
+
+            // Return the current element.
+            return toReturn;
+        }
+
+        private void advance() {
+            // Need to find the next element that is not past shard boundaries.  If we travel past the edge of
+            // shard boundaries, stop and let the next interval pick it up.
+            while(currentAlignmentContext == null && sourceIterator.hasNext()) {
+                // Advance the iterator and try again.
+                AlignmentContext candidateAlignmentContext = sourceIterator.peek();
+
+                if(locus == null) {
+                    // No filter present.  Return everything that LocusIteratorByState provides us.
+                    currentAlignmentContext = sourceIterator.next();
+                }
+                else if(locus.isPast(candidateAlignmentContext.getLocation()))
+                    // Found a locus before the current window; claim this alignment context and throw it away.
+                    sourceIterator.next();
+                else if(locus.containsP(candidateAlignmentContext.getLocation())) {
+                    // Found a locus within the current window; claim this alignment context and call it the next entry.
+                    currentAlignmentContext = sourceIterator.next();
+                }
+                else if(locus.isBefore(candidateAlignmentContext.getLocation())) {
+                    // Whoops.  Skipped passed the end of the region.  Iteration for this window is complete.  Do
+                    // not claim this alignment context in case it is part of the next shard.
+                    break;
+                }
+                else
+                    throw new ReviewedGATKException("BUG: filtering locus does not contain, is not before, and is not past the given alignment context");
+            }
+        }
+
+        @Override
+        public LocusIteratorByState getLIBS() {
+            return libs;
+        }
+    }
+}
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/executive/package-info.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/executive/package-info.java
new file mode 100644
index 0000000..c0d6e9d
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/executive/package-info.java
@@ -0,0 +1,26 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.engine.executive;
\ No newline at end of file
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/filters/BadCigarFilter.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/filters/BadCigarFilter.java
new file mode 100644
index 0000000..fce3a71
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/filters/BadCigarFilter.java
@@ -0,0 +1,122 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.engine.filters;
+
+import htsjdk.samtools.Cigar;
+import htsjdk.samtools.CigarElement;
+import htsjdk.samtools.CigarOperator;
+import htsjdk.samtools.SAMRecord;
+
+import java.util.Iterator;
+
+/**
+ * Filter out reads with wonky cigar strings.
+ *
+ *  - No reads with Hard/Soft clips in the middle of the cigar
+ *  - No reads starting with deletions (with or without preceding clips)
+ *  - No reads ending in deletions (with or without follow-up clips)
+ *  - No reads that are fully hard or soft clipped
+ *  - No reads that have consecutive indels in the cigar (II, DD, ID or DI)
+ *
+ *  ps: apparently an empty cigar is okay...
+ *
+ * @author ebanks
+ * @version 0.1
+ */
+
+public class BadCigarFilter extends ReadFilter {
+
+    public boolean filterOut(final SAMRecord rec) {
+        final Cigar c = rec.getCigar();
+
+        // if there is no Cigar then it can't be bad
+        if( c.isEmpty() ) {
+            return false;
+        }
+
+        Iterator<CigarElement> elementIterator = c.getCigarElements().iterator();
+
+        CigarOperator firstOp = CigarOperator.H;
+        while (elementIterator.hasNext() && (firstOp == CigarOperator.H || firstOp == CigarOperator.S)) {
+            CigarOperator op = elementIterator.next().getOperator();
+
+            // No reads with Hard/Soft clips in the middle of the cigar
+            if (firstOp != CigarOperator.H && op == CigarOperator.H) {
+                    return true;
+            }
+            firstOp = op;
+        }
+
+        // No reads starting with deletions (with or without preceding clips)
+        if (firstOp == CigarOperator.D) {
+            return true;
+        }
+
+        boolean hasMeaningfulElements = (firstOp != CigarOperator.H && firstOp != CigarOperator.S);
+        boolean previousElementWasIndel = firstOp == CigarOperator.I;
+        CigarOperator lastOp = firstOp;
+        CigarOperator previousOp = firstOp;
+
+        while (elementIterator.hasNext()) {
+            CigarOperator op = elementIterator.next().getOperator();
+
+            if (op != CigarOperator.S && op != CigarOperator.H) {
+
+                // No reads with Hard/Soft clips in the middle of the cigar
+                if (previousOp == CigarOperator.S || previousOp == CigarOperator.H)
+                    return true;
+
+                lastOp = op;
+
+                if (!hasMeaningfulElements && op.consumesReadBases()) {
+                    hasMeaningfulElements = true;
+                }
+
+                if (op == CigarOperator.I || op == CigarOperator.D) {
+
+                    // No reads that have consecutive indels in the cigar (II, DD, ID or DI)
+                    if (previousElementWasIndel) {
+                        return true;
+                    }
+                    previousElementWasIndel = true;
+                }
+                else {
+                    previousElementWasIndel = false;
+                }
+            }
+            // No reads with Hard/Soft clips in the middle of the cigar
+            else if (op == CigarOperator.S && previousOp == CigarOperator.H) {
+                return true;
+            }
+
+            previousOp = op;
+        }
+
+        // No reads ending in deletions (with or without follow-up clips)
+        // No reads that are fully hard or soft clipped
+        return lastOp == CigarOperator.D || !hasMeaningfulElements;
+    }
+}
\ No newline at end of file
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/filters/BadMateFilter.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/filters/BadMateFilter.java
new file mode 100644
index 0000000..c25d8d9
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/filters/BadMateFilter.java
@@ -0,0 +1,47 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.engine.filters;
+
+import htsjdk.samtools.SAMRecord;
+
+/**
+ * Filter out reads whose mate maps to a different contig.
+ *
+ * @author ebanks
+ * @version 0.1
+ */
+
+public class BadMateFilter extends ReadFilter {
+
+    public boolean filterOut(final SAMRecord rec) {
+        return hasBadMate(rec);
+    }
+
+    public static boolean hasBadMate(final SAMRecord rec) {
+        return (rec.getReadPairedFlag() && !rec.getMateUnmappedFlag() && !rec.getReferenceIndex().equals(rec.getMateReferenceIndex()));
+    }
+
+}
\ No newline at end of file
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/filters/CountingFilteringIterator.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/filters/CountingFilteringIterator.java
new file mode 100644
index 0000000..8717f1f
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/filters/CountingFilteringIterator.java
@@ -0,0 +1,150 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.engine.filters;
+
+import htsjdk.samtools.filter.SamRecordFilter;
+import htsjdk.samtools.SAMRecord;
+import htsjdk.samtools.util.CloseableIterator;
+import htsjdk.samtools.util.CloserUtil;
+import org.broadinstitute.gatk.engine.ReadMetrics;
+
+import java.util.*;
+
+/**
+ * Filtering Iterator which takes a filter and an iterator and iterates
+ * through only those records which are not rejected by the filter.
+ * @author Mark DePristo
+ */
+public class CountingFilteringIterator implements CloseableIterator<SAMRecord> {
+    private final ReadMetrics globalRuntimeMetrics;
+    private final ReadMetrics privateRuntimeMetrics;
+    private final Iterator<SAMRecord> iterator;
+    private final List<CountingReadFilter> filters = new ArrayList<>();
+    private SAMRecord next = null;
+
+    // wrapper around ReadFilters to count the number of filtered reads
+    private final class CountingReadFilter extends ReadFilter {
+        protected final ReadFilter readFilter;
+        protected long counter = 0L;
+
+        public CountingReadFilter(final ReadFilter readFilter) {
+            this.readFilter = readFilter;
+        }
+
+        @Override
+        public boolean filterOut(final SAMRecord record) {
+            final boolean result = readFilter.filterOut(record);
+            if ( result )
+                counter++;
+            return result;
+        }
+    }
+
+    /**
+     * Constructor
+     *
+     * @param metrics   metrics to accumulate on the nature of filtered reads.
+     * @param iterator  the backing iterator
+     * @param filters    the filter (which may be a FilterAggregator)
+     */
+    public CountingFilteringIterator(ReadMetrics metrics, Iterator<SAMRecord> iterator, Collection<ReadFilter> filters) {
+        this.globalRuntimeMetrics = metrics;
+        privateRuntimeMetrics = new ReadMetrics();
+        this.iterator = iterator;
+        for ( final ReadFilter filter : filters )
+            this.filters.add(new CountingReadFilter(filter));
+        next = getNextRecord();
+    }
+
+    /**
+     * Returns true if the iteration has more elements.
+     *
+     * @return  true if the iteration has more elements.  Otherwise returns false.
+     */
+    public boolean hasNext() {
+        return next != null;
+    }
+
+    /**
+     * Returns the next element in the iteration.
+     *
+     * @return  the next element in the iteration
+     * @throws java.util.NoSuchElementException
+     */
+    public SAMRecord next() {
+        if (next == null) {
+            throw new NoSuchElementException("Iterator has no more elements.");
+        }
+        final SAMRecord result = next;
+        next = getNextRecord();
+        return result;
+    }
+
+    /**
+     * Required method for Iterator API.
+     *
+     * @throws UnsupportedOperationException
+     */
+    public void remove() {
+        throw new UnsupportedOperationException("Remove() not supported by CountingFilteringIterator");
+    }
+
+    public void close() {
+        CloserUtil.close(iterator);
+
+        for ( final CountingReadFilter filter : filters )
+            privateRuntimeMetrics.setFilterCount(filter.readFilter.getClass().getSimpleName(), filter.counter);
+        // update the global metrics with all the data we collected here
+        globalRuntimeMetrics.incrementMetrics(privateRuntimeMetrics);
+    }
+
+    /**
+     * Gets the next record from the underlying iterator that passes the filter
+     *
+     * @return SAMRecord    the next filter-passing record
+     */
+    private SAMRecord getNextRecord() {
+        while (iterator.hasNext()) {
+            SAMRecord record = iterator.next();
+
+            // update only the private copy of the metrics so that we don't need to worry about race conditions
+            // that can arise when trying to update the global copy; it was agreed that this is the cleanest solution.
+            privateRuntimeMetrics.incrementNumReadsSeen();
+
+            boolean filtered = false;
+            for(SamRecordFilter filter: filters) {
+                if(filter.filterOut(record)) {
+                    filtered = true;
+                    break;
+                }
+            }
+
+            if(!filtered) return record;
+        }
+
+        return null;
+    }
+}
\ No newline at end of file
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/filters/DuplicateReadFilter.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/filters/DuplicateReadFilter.java
new file mode 100644
index 0000000..52861e2
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/filters/DuplicateReadFilter.java
@@ -0,0 +1,66 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.engine.filters;
+
+import htsjdk.samtools.SAMRecord;
+
+/*
+ * 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.
+ */
+
+/**
+ * Filter out duplicate reads.
+ *
+ * @author rpoplin
+ * @since Dec 9, 2009
+ */
+
+public class DuplicateReadFilter extends ReadFilter {
+    public boolean filterOut( final SAMRecord read ) {
+        return read.getDuplicateReadFlag();
+    }
+}
\ No newline at end of file
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/filters/FailsVendorQualityCheckFilter.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/filters/FailsVendorQualityCheckFilter.java
new file mode 100644
index 0000000..2cc5e2a
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/filters/FailsVendorQualityCheckFilter.java
@@ -0,0 +1,41 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.engine.filters;
+
+import htsjdk.samtools.SAMRecord;
+
+/**
+ * Filter out reads that fail the vendor quality check.
+ *
+ * @author rpoplin
+ * @since Jul 19, 2010
+ */
+
+public class FailsVendorQualityCheckFilter extends ReadFilter {
+    public boolean filterOut( final SAMRecord read ) {
+        return read.getReadFailsVendorQualityCheckFlag();
+    }
+}
\ No newline at end of file
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/filters/FilterManager.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/filters/FilterManager.java
new file mode 100644
index 0000000..59c3f15
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/filters/FilterManager.java
@@ -0,0 +1,95 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.engine.filters;
+
+import org.broadinstitute.gatk.utils.classloader.PluginManager;
+import org.broadinstitute.gatk.utils.help.GATKDocUtils;
+import org.broadinstitute.gatk.utils.help.HelpConstants;
+
+import java.util.Collection;
+import java.util.List;
+
+/**
+ * Manage filters and filter options.  Any requests for basic filtering classes
+ * should ultimately be made through this class.
+ *
+ * @author mhanna
+ * @version 0.1
+ */
+public class FilterManager extends PluginManager<ReadFilter> {
+    public FilterManager() {
+        super(ReadFilter.class,"filter","Filter");
+    }
+
+    /**
+     * Instantiate a filter of the given type.  Along the way, scream bloody murder if
+     * the filter is not available.
+     * @param filterType The type of the filter
+     * @return The filter
+     */
+    public ReadFilter createFilterByType(Class<? extends ReadFilter> filterType) {
+        return this.createByName(getName(filterType));
+    }
+
+    public Collection<Class<? extends ReadFilter>> getValues() {
+        return this.getPlugins();
+    }
+
+    /**
+     * Rather than use the default error message, print out a list of read filters as well.
+     * @param pluginCategory - string, the category of the plugin (e.g. read filter)
+     * @param pluginName - string, what we were trying to match (but failed to)
+     * @return - A wall of text with the default message, followed by a listing of available read filters
+     */
+    @Override
+    protected String formatErrorMessage(String pluginCategory, String pluginName) {
+        List<Class<? extends ReadFilter>> availableFilters = this.getPluginsImplementing(ReadFilter.class);
+
+
+        return String.format("Read filter %s not found. Available read filters:%n%n%s%n%n%s",pluginName,
+                userFriendlyListofReadFilters(availableFilters),
+                "Please consult the GATK Documentation (" + HelpConstants.GATK_DOCS_URL + ") for more information.");
+    }
+
+    private String userFriendlyListofReadFilters(List<Class<? extends ReadFilter>> filters) {
+        final String headName = "FilterName", headDoc = "Documentation";
+        int longestNameLength = -1;
+        for ( Class < ? extends ReadFilter> filter : filters ) {
+            longestNameLength = Math.max(longestNameLength,this.getName(filter).length());
+        }
+        String format = "   %"+longestNameLength+"s        %s%n";
+
+        StringBuilder listBuilder = new StringBuilder();
+        listBuilder.append(String.format(format,headName,headDoc));
+        for ( Class<? extends ReadFilter> filter : filters ) {
+            String helpLink = GATKDocUtils.helpLinksToGATKDocs(filter);
+            String filterName = this.getName(filter);
+            listBuilder.append(String.format(format,filterName,helpLink));
+        }
+
+        return listBuilder.toString();
+    }
+}
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/filters/LibraryReadFilter.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/filters/LibraryReadFilter.java
new file mode 100644
index 0000000..8b0f076
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/filters/LibraryReadFilter.java
@@ -0,0 +1,49 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.engine.filters;
+
+import htsjdk.samtools.SAMReadGroupRecord;
+import htsjdk.samtools.SAMRecord;
+import org.broadinstitute.gatk.utils.commandline.Argument;
+import org.broadinstitute.gatk.engine.filters.ReadFilter;
+
+/**
+ * Only use reads from the specified library
+ *
+ * @author kcibul
+ * @since Aug 15, 2012
+ *
+ */
+
+public class LibraryReadFilter extends ReadFilter {
+    @Argument(fullName = "library", shortName = "library", doc="The name of the library to keep, filtering out all others", required=true)
+    private String LIBRARY_TO_KEEP = null;
+
+    public boolean filterOut( final SAMRecord read ) {
+        final SAMReadGroupRecord readGroup = read.getReadGroup();
+        return ( readGroup == null || readGroup.getLibrary() == null || !readGroup.getLibrary().equals( LIBRARY_TO_KEEP ) );
+    }
+}
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/filters/MalformedReadFilter.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/filters/MalformedReadFilter.java
new file mode 100644
index 0000000..1b59a06
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/filters/MalformedReadFilter.java
@@ -0,0 +1,260 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.engine.filters;
+
+import htsjdk.samtools.*;
+import org.broadinstitute.gatk.utils.commandline.Argument;
+import org.broadinstitute.gatk.engine.GenomeAnalysisEngine;
+import org.broadinstitute.gatk.engine.ReadProperties;
+import org.broadinstitute.gatk.engine.arguments.ValidationExclusion;
+import org.broadinstitute.gatk.engine.datasources.reads.SAMDataSource;
+import org.broadinstitute.gatk.utils.exceptions.UserException;
+
+import java.util.Collections;
+
+/**
+ * Filter out malformed reads.
+ *
+ * @author mhanna
+ * @version 0.1
+ */
+public class MalformedReadFilter extends ReadFilter {
+
+
+    private static final String FILTER_READS_WITH_N_CIGAR_ARGUMENT_FULL_NAME = "filter_reads_with_N_cigar" ;
+
+    private SAMFileHeader header;
+
+    @Argument(fullName = FILTER_READS_WITH_N_CIGAR_ARGUMENT_FULL_NAME, shortName = "filterRNC", doc = "filter out reads with CIGAR containing the N operator, instead of stop processing and report an error.", required = false)
+    boolean filterReadsWithNCigar = false;
+
+
+    @Argument(fullName = "filter_mismatching_base_and_quals", shortName = "filterMBQ", doc = "if a read has mismatching number of bases and base qualities, filter out the read instead of blowing up.", required = false)
+    boolean filterMismatchingBaseAndQuals = false;
+
+    @Argument(fullName = "filter_bases_not_stored", shortName = "filterNoBases", doc = "if a read has no stored bases (i.e. a '*'), filter out the read instead of blowing up.", required = false)
+    boolean filterBasesNotStored = false;
+
+    /**
+     * Indicates the applicable validation exclusions
+     */
+    private boolean allowNCigars;
+
+    @Override
+    public void initialize(final GenomeAnalysisEngine engine) {
+        header = engine.getSAMFileHeader();
+        ValidationExclusion validationExclusions = null;
+        final SAMDataSource rds = engine.getReadsDataSource();
+        if (rds != null) {
+          final ReadProperties rps = rds.getReadsInfo();
+          if (rps != null) {
+            validationExclusions = rps.getValidationExclusionList();
+          }
+        }
+        if (validationExclusions == null) {
+            allowNCigars = false;
+        } else {
+            allowNCigars = validationExclusions.contains(ValidationExclusion.TYPE.ALLOW_N_CIGAR_READS);
+        }
+    }
+
+    public boolean filterOut(final SAMRecord read) {
+        // slowly changing the behavior to blow up first and filtering out if a parameter is explicitly provided
+        return  !checkInvalidAlignmentStart(read) ||
+                !checkInvalidAlignmentEnd(read) ||
+                !checkAlignmentDisagreesWithHeader(this.header,read) ||
+                !checkHasReadGroup(read) ||
+                !checkMismatchingBasesAndQuals(read, filterMismatchingBaseAndQuals) ||
+                !checkCigarDisagreesWithAlignment(read) ||
+                !checkSeqStored(read, filterBasesNotStored) ||
+                !checkCigarIsSupported(read,filterReadsWithNCigar,allowNCigars);
+    }
+
+    private static boolean checkHasReadGroup(final SAMRecord read) {
+        if ( read.getReadGroup() == null ) {
+            // there are 2 possibilities: either the RG tag is missing or it is not defined in the header
+            final String rgID = (String)read.getAttribute(SAMTagUtil.getSingleton().RG);
+            if ( rgID == null )
+                throw new UserException.ReadMissingReadGroup(read);
+            throw new UserException.ReadHasUndefinedReadGroup(read, rgID);
+        }
+        return true;
+    }
+
+    /**
+     * Check for the case in which the alignment start is inconsistent with the read unmapped flag.
+     * @param read The read to validate.
+     * @return true if read start is valid, false otherwise.
+     */
+    private static boolean checkInvalidAlignmentStart(final SAMRecord read ) {
+        // read is not flagged as 'unmapped', but alignment start is NO_ALIGNMENT_START
+        if( !read.getReadUnmappedFlag() && read.getAlignmentStart() == SAMRecord.NO_ALIGNMENT_START )
+            return false;
+        // Read is not flagged as 'unmapped', but alignment start is -1
+        if( !read.getReadUnmappedFlag() && read.getAlignmentStart() == -1 )
+            return false;
+        return true;
+    }
+
+    /**
+     * Check for invalid end of alignments.
+     * @param read The read to validate.
+     * @return true if read end is valid, false otherwise.
+     */
+    private static boolean checkInvalidAlignmentEnd(final SAMRecord read ) {
+        // Alignment aligns to negative number of bases in the reference.
+        if( !read.getReadUnmappedFlag() && read.getAlignmentEnd() != -1 && (read.getAlignmentEnd()-read.getAlignmentStart()+1)<0 )
+            return false;
+        return true;
+    }
+
+    /**
+     * Check to ensure that the alignment makes sense based on the contents of the header.
+     * @param header The SAM file header.
+     * @param read The read to verify.
+     * @return true if alignment agrees with header, false othrewise.
+     */
+    private static boolean checkAlignmentDisagreesWithHeader(final SAMFileHeader header, final SAMRecord read ) {
+        // Read is aligned to nonexistent contig
+        if( read.getReferenceIndex() == SAMRecord.NO_ALIGNMENT_REFERENCE_INDEX && read.getAlignmentStart() != SAMRecord.NO_ALIGNMENT_START )
+            return false;
+        final SAMSequenceRecord contigHeader = header.getSequence( read.getReferenceIndex() );
+        // Read is aligned to a point after the end of the contig
+        if( !read.getReadUnmappedFlag() && read.getAlignmentStart() > contigHeader.getSequenceLength() )
+            return false;
+        return true;
+    }
+
+    /**
+     * Check for inconsistencies between the cigar string and the
+     * @param read The read to validate.
+     * @return true if cigar agrees with alignment, false otherwise.
+     */
+    private static boolean checkCigarDisagreesWithAlignment(final SAMRecord read) {
+        // Read has a valid alignment start, but the CIGAR string is empty
+        if( !read.getReadUnmappedFlag() &&
+            read.getAlignmentStart() != -1 &&
+            read.getAlignmentStart() != SAMRecord.NO_ALIGNMENT_START &&
+            read.getAlignmentBlocks().size() < 0 )
+            return false;
+        return true;
+    }
+
+    /**
+     * Check for unsupported CIGAR operators.
+     * Currently the N operator is not supported.
+     * @param read The read to validate.
+     * @param filterReadsWithNCigar whether the offending read should just
+     *                              be silently filtered or not.
+     * @param allowNCigars whether reads that contain N operators in their CIGARs
+     *                     can be processed or an exception should be thrown instead.
+     * @throws UserException.UnsupportedCigarOperatorException
+     *   if {@link #filterReadsWithNCigar} is <code>false</code> and
+     *   the input read has some unsupported operation.
+     * @return <code>true</code> if the read CIGAR operations are
+     * fully supported, otherwise <code>false</code>, as long as
+     * no exception has been thrown.
+     */
+    private static boolean checkCigarIsSupported(final SAMRecord read, final boolean filterReadsWithNCigar, final boolean allowNCigars) {
+        if( containsNOperator(read)) {
+            if (! filterReadsWithNCigar && !allowNCigars) {
+                throw new UserException.UnsupportedCigarOperatorException(
+                        CigarOperator.N,read,
+                        "Perhaps you are"
+                        + " trying to use RNA-Seq data?"
+                        + " While we are currently actively working to"
+                        + " support this data type unfortunately the"
+                        + " GATK cannot be used with this data in its"
+                        + " current form. You have the option of either"
+                        + " filtering out all reads with operator "
+                        + CigarOperator.N + " in their CIGAR string"
+                        + " (please add --"
+                        +  FILTER_READS_WITH_N_CIGAR_ARGUMENT_FULL_NAME
+                        + " to your command line) or"
+                        + " assume the risk of processing those reads as they"
+                        + " are including the pertinent unsafe flag (please add -U"
+                        + ' ' + ValidationExclusion.TYPE.ALLOW_N_CIGAR_READS
+                        + " to your command line). Notice however that if you were"
+                        + " to choose the latter, an unspecified subset of the"
+                        + " analytical outputs of an unspecified subset of the tools"
+                        + " will become unpredictable. Consequently the GATK team"
+                        + " might well not be able to provide you with the usual support"
+                        + " with any issue regarding any output");
+            }
+            return ! filterReadsWithNCigar;
+        }
+        return true;
+    }
+
+    private static boolean containsNOperator(final SAMRecord read) {
+        final Cigar cigar = read.getCigar();
+        if (cigar == null)   {
+            return false;
+        }
+        for (final CigarElement ce : cigar.getCigarElements()) {
+            if (ce.getOperator() == CigarOperator.N) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    /**
+     * Check if the read has the same number of bases and base qualities
+     * @param read the read to validate
+     * @return true if they have the same number. False otherwise.
+     */
+    private static boolean checkMismatchingBasesAndQuals(final SAMRecord read, final boolean filterMismatchingBaseAndQuals) {
+        final boolean result;
+        if (read.getReadLength() == read.getBaseQualities().length)
+            result = true;
+        else if (filterMismatchingBaseAndQuals)
+            result = false;
+        else
+            throw new UserException.MalformedBAM(read,
+                    String.format("BAM file has a read with mismatching number of bases and base qualities. Offender: %s [%d bases] [%d quals].%s",
+                            read.getReadName(), read.getReadLength(), read.getBaseQualities().length,
+                            read.getBaseQualities().length == 0 ? " You can use --defaultBaseQualities to assign a default base quality for all reads, but this can be dangerous in you don't know what you are doing." : ""));
+
+        return result;
+    }
+
+    /**
+     * Check if the read has its base sequence stored
+     * @param read the read to validate
+     * @return true if the sequence is stored and false otherwise ("*" in the SEQ field).
+     */
+    protected static boolean checkSeqStored(final SAMRecord read, final boolean filterBasesNotStored) {
+
+        if ( read.getReadBases() != SAMRecord.NULL_SEQUENCE )
+            return true;
+
+        if ( filterBasesNotStored )
+            return false;
+
+        throw new UserException.MalformedBAM(read, String.format("the BAM file has a read with no stored bases (i.e. it uses '*') which is not supported in the GATK; see the --filter_bases_not_stored argument. Offender: %s", read.getReadName()));
+    }
+}
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/filters/MappingQualityFilter.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/filters/MappingQualityFilter.java
new file mode 100644
index 0000000..67c62b9
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/filters/MappingQualityFilter.java
@@ -0,0 +1,46 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.engine.filters;
+
+import htsjdk.samtools.SAMRecord;
+import org.broadinstitute.gatk.utils.commandline.Argument;
+
+/**
+ * Filter out reads with low mapping qualities.
+ *
+ * @author ebanks
+ * @version 0.1
+ */
+
+public class MappingQualityFilter extends ReadFilter {
+
+    @Argument(fullName = "min_mapping_quality_score", shortName = "mmq", doc = "Minimum read mapping quality required to consider a read for calling", required = false)
+    public int MIN_MAPPING_QUALTY_SCORE = 10;
+
+    public boolean filterOut(SAMRecord rec) {
+        return (rec.getMappingQuality() < MIN_MAPPING_QUALTY_SCORE);
+    }
+}
\ No newline at end of file
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/filters/MappingQualityUnavailableFilter.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/filters/MappingQualityUnavailableFilter.java
new file mode 100644
index 0000000..05df7fb
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/filters/MappingQualityUnavailableFilter.java
@@ -0,0 +1,43 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.engine.filters;
+
+import htsjdk.samtools.SAMRecord;
+import org.broadinstitute.gatk.utils.QualityUtils;
+
+/**
+ * Filter out mapping quality zero reads.
+ *
+ * @author ebanks
+ * @version 0.1
+ */
+
+public class MappingQualityUnavailableFilter extends ReadFilter {
+    public boolean filterOut(SAMRecord rec) {
+        return (rec.getMappingQuality() == QualityUtils.MAPPING_QUALITY_UNAVAILABLE);
+    }
+}
+
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/filters/MappingQualityZeroFilter.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/filters/MappingQualityZeroFilter.java
new file mode 100644
index 0000000..f3f7032
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/filters/MappingQualityZeroFilter.java
@@ -0,0 +1,42 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.engine.filters;
+
+import htsjdk.samtools.SAMRecord;
+
+/**
+ * Filter out mapping quality zero reads.
+ *
+ * @author hanna
+ * @version 0.1
+ */
+
+public class MappingQualityZeroFilter extends ReadFilter {
+    public boolean filterOut(SAMRecord rec) {
+        return (rec.getMappingQuality() == 0);
+    }
+}
+
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/filters/MateSameStrandFilter.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/filters/MateSameStrandFilter.java
new file mode 100644
index 0000000..0818f8f
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/filters/MateSameStrandFilter.java
@@ -0,0 +1,42 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.engine.filters;
+
+import htsjdk.samtools.SAMRecord;
+
+/**
+ * Filter out reads that are not paired, have their mate unmapped, are duplicates, fail vendor quality check or both mate and read are in the same strand.
+ *
+ * @author chartl
+ * @since 5/18/11
+ */
+public class MateSameStrandFilter extends ReadFilter {
+
+    public boolean filterOut(SAMRecord read) {
+        return (! read.getReadPairedFlag() ) || read.getMateUnmappedFlag() || read.getDuplicateReadFlag() ||
+                read.getReadFailsVendorQualityCheckFlag() || read.getMateNegativeStrandFlag() != read.getReadNegativeStrandFlag();
+    }
+}
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/filters/MaxInsertSizeFilter.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/filters/MaxInsertSizeFilter.java
new file mode 100644
index 0000000..cca05eb
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/filters/MaxInsertSizeFilter.java
@@ -0,0 +1,44 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.engine.filters;
+
+import htsjdk.samtools.SAMRecord;
+import org.broadinstitute.gatk.utils.commandline.Argument;
+
+/**
+ * Filter out reads that exceed a given max insert size
+ *
+ * @author chartl
+ * @since 5/2/11
+ */
+public class MaxInsertSizeFilter extends ReadFilter {
+    @Argument(fullName = "maxInsertSize", shortName = "maxInsert", doc="Discard reads with insert size greater than the specified value, defaults to 1000000", required=false)
+    private int maxInsertSize = 1000000;
+
+    public boolean filterOut(SAMRecord record) {
+        return (record.getReadPairedFlag() && (record.getInferredInsertSize() > maxInsertSize || record.getInferredInsertSize() < -1*maxInsertSize));
+    }
+}
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/filters/MissingReadGroupFilter.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/filters/MissingReadGroupFilter.java
new file mode 100644
index 0000000..21b291b
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/filters/MissingReadGroupFilter.java
@@ -0,0 +1,41 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.engine.filters;
+
+import htsjdk.samtools.SAMRecord;
+
+/**
+ * Filter out reads without read groups.
+ *
+ * @author ebanks
+ * @version 0.1
+ */
+
+public class MissingReadGroupFilter extends ReadFilter {
+    public boolean filterOut(SAMRecord rec) {
+        return rec.getReadGroup() == null;
+    }
+}
\ No newline at end of file
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/filters/NDNCigarReadTransformer.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/filters/NDNCigarReadTransformer.java
new file mode 100644
index 0000000..65bf1eb
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/filters/NDNCigarReadTransformer.java
@@ -0,0 +1,118 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.engine.filters;
+
+import htsjdk.samtools.Cigar;
+import htsjdk.samtools.CigarElement;
+import htsjdk.samtools.CigarOperator;
+import htsjdk.samtools.SAMRecord;
+import org.broadinstitute.gatk.engine.GenomeAnalysisEngine;
+import org.broadinstitute.gatk.engine.iterators.RNAReadTransformer;
+import org.broadinstitute.gatk.engine.iterators.ReadTransformer;
+import org.broadinstitute.gatk.engine.walkers.Walker;
+import org.broadinstitute.gatk.utils.exceptions.UserException;
+import org.broadinstitute.gatk.utils.sam.GATKSAMRecord;
+
+/**
+ * A read transformer that refactor NDN cigar elements to one N element.
+ *
+ *  <p>
+ *     This read transformer will refactor cigar strings that contain N-D-N elements to one N element (with total length of the three refactored elements).
+ *     This is intended primarily for users of RNA-Seq data handling programs such as TopHat2.
+ *     Currently we consider that the internal N-D-N motif is illegal and we error out when we encounter it. By refactoring the cigar string of
+ *     those specific reads, users of TopHat and other tools can circumvent this problem without affecting the rest of their dataset.
+ *
+ *     NOTE: any walker that need that functionality should apply that read transformer in its map function, since it won't be activated by the GATK engine.
+ *
+ *     The engine parameter that activate this read transformer is --refactor_NDN_cigar_string or -fixNDN
+ *  </p>
+ *
+ *
+ *
+ * @author ami
+ * @since 04/22/14
+ */
+
+public class NDNCigarReadTransformer extends RNAReadTransformer {
+
+    private boolean refactorReads;
+
+    @Override
+    public ApplicationTime initializeSub(final GenomeAnalysisEngine engine, final Walker walker) {
+        refactorReads = engine.getArguments().REFACTOR_NDN_CIGAR_READS;
+
+        return ApplicationTime.HANDLED_IN_WALKER;   //  NOTE: any walker that need that functionality should apply that read transformer in its map function, since it won't be activated by the GATK engine.
+    }
+
+    @Override
+    public GATKSAMRecord apply(final GATKSAMRecord read) {
+        if(read == null)
+            throw new UserException.BadInput("try to transform a null GATKSAMRecord");
+        final Cigar originalCigar = read.getCigar();
+        if (originalCigar.isValid(read.getReadName(),-1) != null)
+            throw new UserException.BadInput("try to transform a read with non-valid cigar string: readName: "+read.getReadName()+" Cigar String: "+originalCigar);
+        read.setCigar(refactorNDNtoN(originalCigar));
+        return read;
+    }
+
+    @Override
+    public boolean enabled() {
+        return refactorReads;
+    }
+
+
+
+    protected Cigar refactorNDNtoN(final Cigar originalCigar) {
+        final Cigar refactoredCigar = new Cigar();
+        final int cigarLength = originalCigar.numCigarElements();
+        for(int i = 0; i < cigarLength; i++){
+            final CigarElement element = originalCigar.getCigarElement(i);
+            if(element.getOperator() == CigarOperator.N && thereAreAtLeast2MoreElements(i,cigarLength)){
+                final CigarElement nextElement = originalCigar.getCigarElement(i+1);
+                final CigarElement nextNextElement = originalCigar.getCigarElement(i+2);
+
+                // if it is N-D-N replace with N (with the total length) otherwise just add the first N.
+                if(nextElement.getOperator() == CigarOperator.D && nextNextElement.getOperator() == CigarOperator.N){
+                    final int threeElementsLength = element.getLength() + nextElement.getLength() + nextNextElement.getLength();
+                    final CigarElement refactoredElement = new CigarElement(threeElementsLength,CigarOperator.N);
+                    refactoredCigar.add(refactoredElement);
+                    i += 2; //skip the elements that were refactored
+                }
+                else
+                    refactoredCigar.add(element);  // add only the first N
+            }
+            else
+                refactoredCigar.add(element);  // add any non-N element
+        }
+        return refactoredCigar;
+    }
+
+    private boolean thereAreAtLeast2MoreElements(final int index, final int cigarLength){
+        return index < cigarLength - 2;
+    }
+
+}
+
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/filters/NoOriginalQualityScoresFilter.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/filters/NoOriginalQualityScoresFilter.java
new file mode 100644
index 0000000..8297903
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/filters/NoOriginalQualityScoresFilter.java
@@ -0,0 +1,65 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.engine.filters;
+
+import htsjdk.samtools.SAMRecord;
+
+/*
+ * 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.
+ */
+
+/**
+ * Filter out reads that don't have base an original quality quality score tag (usually added by BQSR)
+ *
+ * @author rpoplin
+ * @since Nov 19, 2009
+ */
+public class NoOriginalQualityScoresFilter extends ReadFilter {
+    public boolean filterOut( final SAMRecord read ) {
+        return (read.getAttribute("OQ") == null);
+    }
+}
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/filters/NotPrimaryAlignmentFilter.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/filters/NotPrimaryAlignmentFilter.java
new file mode 100644
index 0000000..b09e1f6
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/filters/NotPrimaryAlignmentFilter.java
@@ -0,0 +1,41 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.engine.filters;
+
+import htsjdk.samtools.SAMRecord;
+
+/**
+ * Filter out duplicate reads.
+ *
+ * @author rpoplin
+ * @since Dec 9, 2009
+ */
+
+public class NotPrimaryAlignmentFilter extends ReadFilter {
+    public boolean filterOut( final SAMRecord read ) {
+        return read.getNotPrimaryAlignmentFlag();
+    }
+}
\ No newline at end of file
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/filters/Platform454Filter.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/filters/Platform454Filter.java
new file mode 100644
index 0000000..79f16a5
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/filters/Platform454Filter.java
@@ -0,0 +1,43 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.engine.filters;
+
+import htsjdk.samtools.SAMRecord;
+import org.broadinstitute.gatk.utils.sam.GATKSAMRecord;
+import org.broadinstitute.gatk.utils.sam.ReadUtils;
+
+/**
+ * Filter out 454 reads.
+ *
+ * @author ebanks
+ * @version 0.1
+ */
+
+public class Platform454Filter extends ReadFilter {
+    public boolean filterOut(SAMRecord rec) {
+        return (ReadUtils.is454Read((GATKSAMRecord)rec));
+    }
+}
\ No newline at end of file
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/filters/PlatformFilter.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/filters/PlatformFilter.java
new file mode 100644
index 0000000..8236cc2
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/filters/PlatformFilter.java
@@ -0,0 +1,49 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.engine.filters;
+
+import htsjdk.samtools.SAMRecord;
+import org.broadinstitute.gatk.utils.commandline.Argument;
+import org.broadinstitute.gatk.utils.sam.GATKSAMRecord;
+import org.broadinstitute.gatk.utils.sam.ReadUtils;
+
+/**
+ * Filter out PL matching reads.
+ *
+ * @author ebanks
+ * @version 0.1
+ */
+public class PlatformFilter extends ReadFilter {
+    @Argument(fullName = "PLFilterName", shortName = "PLFilterName", doc="Discard reads with RG:PL attribute containing this string", required=false)
+    protected String[] PLFilterNames;
+
+    public boolean filterOut(SAMRecord rec) {
+        for ( String name : PLFilterNames )
+            if ( ReadUtils.isPlatformRead((GATKSAMRecord)rec, name.toUpperCase() ))
+                return true;
+        return false;
+    }
+}
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/filters/PlatformUnitFilter.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/filters/PlatformUnitFilter.java
new file mode 100644
index 0000000..4a6781f
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/filters/PlatformUnitFilter.java
@@ -0,0 +1,86 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.engine.filters;
+
+import htsjdk.samtools.SAMReadGroupRecord;
+import htsjdk.samtools.SAMRecord;
+import org.broadinstitute.gatk.utils.exceptions.UserException;
+
+import java.util.HashSet;
+import java.util.Set;
+
+/**
+ * Filter out reads that have blacklisted platform unit tags. (See code documentation for how to create the blacklist).
+ *
+ * @author asivache
+ * @since Sep 21, 2009
+ */
+public class PlatformUnitFilter extends ReadFilter {
+    // a hack: use static in order to be able to fill it with the data from command line at runtime
+    static private Set<String> blackListedLanes = new HashSet<String>();
+
+    public boolean filterOut(SAMRecord samRecord) {
+
+        if ( blackListedLanes.size() == 0 ) return false; // no filters set, nothing to do
+
+        Object pu_attr = samRecord.getAttribute("PU");
+
+        if ( pu_attr == null ) {
+            // no platform unit in the record, go get from read group
+            SAMReadGroupRecord rgr = samRecord.getReadGroup();
+            if ( rgr == null ) throw new UserException.MalformedBAM(samRecord, "Read " + samRecord.getReadName() +" has NO associated read group record");
+            pu_attr = rgr.getAttribute("PU") ;
+        }
+        if ( pu_attr == null ) return false; // could not get PU, forget about the filtering...
+        return blackListedLanes.contains((String)pu_attr);
+    }
+
+    /**
+     * The argument is interpreted as a comma-separated list of lanes (platform units) to be filtered
+     * out. All the specified names will be registered with the filter and filterOut(r) for any SAMRecord r
+     * belonging to one of the specified lanes will thereafter return true.
+     * The names can be surrounded by additional spaces, the latters will be trimmed by this method.
+     * This method can be called multiple times to add more lanes. Re-registering the same lane again is safe.
+     * @param arg
+     */
+    public static void setBlackListedLanes(String arg) {
+        String[] lanes = arg.split(",");
+        for ( int i = 0; i < lanes.length ; i++ ) {
+            blackListedLanes.add(lanes[i].trim());
+        }
+    }
+
+    /**
+     * Adds a single name of a lane (platform unit) to be filtered out by this filter. The name can be surrounded
+     * by spaces, the latters will be trimmed out. This method can be called multiple times to add more lanes.
+     * Re-registering the same lane again is safe.
+     * @param arg
+     */
+    public static void addBlackListedLane(String arg) {
+        blackListedLanes.add(arg.trim());
+    }
+
+}
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/filters/PlatformUnitFilterHelper.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/filters/PlatformUnitFilterHelper.java
new file mode 100644
index 0000000..428806d
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/filters/PlatformUnitFilterHelper.java
@@ -0,0 +1,87 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.engine.filters;
+
+import org.broadinstitute.gatk.utils.exceptions.UserException;
+import org.broadinstitute.gatk.utils.text.XReadLines;
+
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.util.regex.Pattern;
+
+/**
+ * This is a utility class, its sole purpose is to populate PlatformUnitFilter with data. When a command line argument
+ * (@Argument) of the type PlatformUnitFilterHelper is declared in an application (walker), its constuctor
+ * PlatformUnitFilterHelper(String) automatically called by the argument system will parse its String argument
+ * and set up static fields of PlatformUnitFilter object.
+ *
+ * The String argument can be either a name of existing file, or a list of comma-separated lane (Platform Unit) names.
+ * First, the constructor will check if a file with specified name exists. If it does, then it is assumed that each line
+ * in the file contains one name of a lane (Platfor Unit) to filter out. If such file does not exist, then the argument is
+ * interpreted as a comma-separated list. Blank spaces around lane names are allowed in both cases and will be trimmed out.
+ *
+ * In other words, all it takes to request filtering out reads from specific lane(s) is
+ *
+ * 1) declare filter usage in the walker
+ *
+ * @ReadFilters({PlatformUnitFilter.class,...})
+ *
+ * 2) specify the argument that will take the list of lanes to filter:
+ *
+ * @Argument(fullName="filterLanes", shortName="FL", doc="all specified lanes will be ignored", required=false)
+ *   PlatformUnitFilterHelper dummy;
+ *
+ * After that, the walker can be invoked with "--filterLanes 302UBAAXX090508.8,302YAAAXX090427.8" argument.
+ *
+ * Created by IntelliJ IDEA.
+ * User: asivache
+ * Date: Sep 22, 2009
+ * Time: 11:11:48 AM
+ * To change this template use File | Settings | File Templates.
+ */
+public class PlatformUnitFilterHelper {
+    final public static Pattern EMPTYLINE_PATTERN = Pattern.compile("^\\s*$");
+
+    public PlatformUnitFilterHelper(String arg) {
+         File f = new File(arg);
+
+         if ( f.exists() ) {
+             try {
+                 XReadLines reader = new XReadLines(f);
+                 for ( String line : reader ) {
+                     if ( EMPTYLINE_PATTERN.matcher(line).matches() ) continue; // skip empty lines
+                     PlatformUnitFilter.addBlackListedLane(line); // PlatformUnitFilter will trim the line as needed
+                 }
+             } catch ( FileNotFoundException e) { throw new UserException.CouldNotReadInputFile(f, e); } // this should NEVER happen
+             return;
+         }
+
+        // no such file, must be a comma-separated list:
+
+        PlatformUnitFilter.setBlackListedLanes(arg); // PlatformUnitFilter will split on commas and trim as needed
+
+    }
+}
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/filters/ReadFilter.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/filters/ReadFilter.java
new file mode 100644
index 0000000..a2102a8
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/filters/ReadFilter.java
@@ -0,0 +1,60 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.engine.filters;
+
+import htsjdk.samtools.filter.SamRecordFilter;
+import htsjdk.samtools.SAMRecord;
+import org.broadinstitute.gatk.engine.GenomeAnalysisEngine;
+import org.broadinstitute.gatk.utils.help.DocumentedGATKFeature;
+import org.broadinstitute.gatk.utils.help.HelpConstants;
+
+/**
+ * A SamRecordFilter that also depends on the header.
+ */
+ at DocumentedGATKFeature(
+        groupName = HelpConstants.DOCS_CAT_RF,
+        summary = "GATK Engine arguments that filter or transfer incoming SAM/BAM data files" )
+public abstract class ReadFilter implements SamRecordFilter {
+    /**
+     * Sets the header for use by this filter.
+     * @param engine the engine.
+     */
+    public void initialize(GenomeAnalysisEngine engine) {}
+
+
+    /**
+     * Determines whether a pair of SAMRecord matches this filter
+     *
+     * @param first  the first SAMRecord to evaluate
+     * @param second the second SAMRecord to evaluate
+     *
+     * @return true if the SAMRecords matches the filter, otherwise false
+     * @throws UnsupportedOperationException when paired filter not implemented
+     */
+    public boolean filterOut(final SAMRecord first, final SAMRecord second) {
+        throw new UnsupportedOperationException("Paired filter not implemented: " + this.getClass());
+    }
+}
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/filters/ReadGroupBlackListFilter.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/filters/ReadGroupBlackListFilter.java
new file mode 100644
index 0000000..7c6bfb0
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/filters/ReadGroupBlackListFilter.java
@@ -0,0 +1,120 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.engine.filters;
+
+import htsjdk.samtools.SAMReadGroupRecord;
+import htsjdk.samtools.SAMRecord;
+import org.broadinstitute.gatk.utils.exceptions.UserException;
+import org.broadinstitute.gatk.utils.text.XReadLines;
+
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.util.*;
+import java.util.Map.Entry;
+
+/**
+ * Removes records matching the read group tag and exact match string.
+ * For example, this filter value:
+ *   PU:1000G-mpimg-080821-1_1
+ * would filter out a read with the read group PU:1000G-mpimg-080821-1_1
+ */
+public class ReadGroupBlackListFilter extends ReadFilter {
+    private Set<Entry<String, Collection<String>>> filterEntries;
+
+    public ReadGroupBlackListFilter(List<String> blackLists) {
+        Map<String, Collection<String>> filters = new TreeMap<String, Collection<String>>();
+        for (String blackList : blackLists)
+            addFilter(filters, blackList, null, 0);
+        this.filterEntries = filters.entrySet();
+    }
+
+    public boolean filterOut(SAMRecord samRecord) {
+        for (Entry<String, Collection<String>> filterEntry : filterEntries) {
+            String attributeType = filterEntry.getKey();
+
+            SAMReadGroupRecord samReadGroupRecord = samRecord.getReadGroup();
+            if (samReadGroupRecord != null) {
+                Object attribute;
+                if ("ID".equals(attributeType) || "RG".equals(attributeType))
+                    attribute = samReadGroupRecord.getId();
+                else
+                    attribute = samReadGroupRecord.getAttribute(attributeType);
+                if (attribute != null && filterEntry.getValue().contains(attribute))
+                    return true;
+            }
+        }
+
+        return false;
+    }
+
+    private void addFilter(Map<String, Collection<String>> filters, String filter, File parentFile, int parentLineNum) {
+        if (filter.toLowerCase().endsWith(".list") || filter.toLowerCase().endsWith(".txt")) {
+            File file = new File(filter);
+            try {
+                int lineNum = 0;
+                XReadLines lines = new XReadLines(file);
+                for (String line : lines) {
+                    lineNum++;
+
+                    if (line.trim().length() == 0)
+                        continue;
+
+                    if (line.startsWith("#"))
+                        continue;
+
+                    addFilter(filters, line, file, lineNum);
+                }
+            } catch (FileNotFoundException e) {
+                String message = "Error loading black list: " + file.getAbsolutePath();
+                if (parentFile != null) {
+                    message += ", " + parentFile.getAbsolutePath() + ":" + parentLineNum;
+                }
+                throw new UserException(message);
+            }
+        } else {
+            String[] filterEntry = filter.split(":", 2);
+
+            String message = null;
+            if (filterEntry.length != 2) {
+                message = "Invalid read group filter: " + filter;
+            } else if (filterEntry[0].length() != 2) {
+                message = "Tag is not two characters: " + filter;
+            }
+
+            if (message != null) {
+                if (parentFile != null) {
+                    message += ", " + parentFile.getAbsolutePath() + ":" + parentLineNum;
+                }
+                message += ", format is <TAG>:<SUBSTRING>";
+                throw new UserException(message);
+            }
+
+            if (!filters.containsKey(filterEntry[0]))
+                filters.put(filterEntry[0], new TreeSet<String>());
+            filters.get(filterEntry[0]).add(filterEntry[1]);
+        }
+    }
+}
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/filters/ReadLengthFilter.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/filters/ReadLengthFilter.java
new file mode 100644
index 0000000..1e44df8
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/filters/ReadLengthFilter.java
@@ -0,0 +1,48 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.engine.filters;
+
+import htsjdk.samtools.SAMRecord;
+import org.broadinstitute.gatk.utils.commandline.Argument;
+
+/**
+ * Filters out reads whose length is >= some value or < some value.
+ *
+ * @author mhanna
+ * @version 0.1
+ */
+public class ReadLengthFilter extends ReadFilter {
+    @Argument(fullName = "maxReadLength", shortName = "maxRead", doc="Discard reads with length greater than the specified value", required=true)
+    private int maxReadLength;
+
+    @Argument(fullName = "minReadLength", shortName = "minRead", doc="Discard reads with length shorter than the specified value", required=true)
+    private int minReadLength = 1;
+    public boolean filterOut(SAMRecord read) {
+        // check the length
+        return read.getReadLength() > maxReadLength || read.getReadLength() < minReadLength;
+    }
+
+}
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/filters/ReadNameFilter.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/filters/ReadNameFilter.java
new file mode 100644
index 0000000..23a5151
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/filters/ReadNameFilter.java
@@ -0,0 +1,44 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.engine.filters;
+
+import htsjdk.samtools.SAMRecord;
+import org.broadinstitute.gatk.utils.commandline.Argument;
+
+/**
+ * Filter out all reads except those with this read name
+ *
+ * @author chartl
+ * @since 9/19/11
+ */
+public class ReadNameFilter extends ReadFilter {
+     @Argument(fullName = "readName", shortName = "rn", doc="Filter out all reads except those with this read name", required=true)
+    private String readName;
+
+    public boolean filterOut(final SAMRecord rec) {
+        return ! rec.getReadName().equals(readName);
+    }
+}
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/filters/ReadStrandFilter.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/filters/ReadStrandFilter.java
new file mode 100644
index 0000000..fd28766
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/filters/ReadStrandFilter.java
@@ -0,0 +1,46 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.engine.filters;
+
+import htsjdk.samtools.SAMRecord;
+import org.broadinstitute.gatk.utils.commandline.Argument;
+
+/**
+ * Filters out reads whose strand is negative or positive
+ *
+ * @author chartl
+ * @version 0.1
+ */
+public class ReadStrandFilter extends ReadFilter {
+    @Argument(fullName = "filterPositive", shortName = "fp", doc="Discard reads on the forward strand",required=false)
+	boolean filterForward = false;
+    
+    public boolean filterOut(SAMRecord read) {
+        // check the length
+        return read.getReadNegativeStrandFlag() != filterForward;
+    }
+
+}
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/filters/ReassignMappingQualityFilter.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/filters/ReassignMappingQualityFilter.java
new file mode 100644
index 0000000..0c8a93a
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/filters/ReassignMappingQualityFilter.java
@@ -0,0 +1,86 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.engine.filters;
+
+import htsjdk.samtools.SAMRecord;
+import org.broadinstitute.gatk.utils.commandline.Argument;
+
+/**
+ * A read filter (transformer) that sets all reads mapping quality to a given value.
+ *
+ *  <p>
+ *     If a BAM file contains erroneous or missing mapping qualities (MAPQ), this read transformer will set all your
+ *     mapping qualities to a given value (see arguments list for default value).
+ *  </p>
+ *
+ * <h3>See also</h3>
+ *
+ * <p>ReassignOneMappingQualityFilter: reassigns a single MAPQ value, as opposed to all those found in the BAM file.</p>
+ *
+ * <h3>Caveats</h3>
+ *
+ * <p>Note that due to the order of operations involved in applying filters, it is possible that other read filters
+ * (determined either at command-line or internally by the tool you are using) will be applied to your data before
+ * this read transformation can be applied. If one of those other filters acts on the read mapping quality (MAPQ),
+ * then you may not obtain the expected results. Unfortunately it is currently not possible to change the order of
+ * operations from command line. To avoid the problem, we recommend applying this filter separately from any other
+ * analysis, using PrintReads.</p>
+ *
+ *
+ * <h3>Input</h3>
+ *  <p>
+ *	    BAM file(s)
+ *  </p>
+ *
+ *
+ * <h3>Output</h3>
+ *  <p>
+ *      BAM file(s) with all reads mapping qualities reassigned
+ *  </p>
+ *
+ * <h3>Examples</h3>
+ *  <pre>
+ *  java -jar GenomeAnalysisTK.jar \
+ *      -T PrintReads \
+ *      -rf ReassignMappingQuality \
+ *      -DMQ 35
+ *  </pre>
+ *
+ * @author carneiro
+ * @since 8/8/11
+ */
+
+public class ReassignMappingQualityFilter extends ReadFilter {
+
+    @Argument(fullName = "default_mapping_quality", shortName = "DMQ", doc = "Default read mapping quality to assign to all reads", required = false)
+    public int defaultMappingQuality = 60;
+
+    public boolean filterOut(SAMRecord rec) {
+        rec.setMappingQuality(defaultMappingQuality);
+        return false;
+    }
+}
+
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/filters/ReassignOneMappingQualityFilter.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/filters/ReassignOneMappingQualityFilter.java
new file mode 100644
index 0000000..f07f197
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/filters/ReassignOneMappingQualityFilter.java
@@ -0,0 +1,87 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.engine.filters;
+
+import htsjdk.samtools.SAMRecord;
+import org.broadinstitute.gatk.utils.commandline.Argument;
+
+/**
+ * A read filter (transformer) that changes a given read mapping quality to a different value.
+ *
+ *  <p>
+ *     This read transformer will change a certain read mapping quality to a different value without affecting reads that
+ *     have other mapping qualities. This is intended primarily for users of RNA-Seq data handling programs such
+ *     as TopHat, which use MAPQ = 255 to designate uniquely aligned reads. According to convention, 255 normally
+ *     designates "unknown" quality, and most GATK tools automatically ignore such reads. By reassigning a different
+ *     mapping quality to those specific reads, users of TopHat and other tools can circumvent this problem without
+ *     affecting the rest of their dataset.
+ *  </p>
+ *
+ *  <p>
+ *     This differs from the ReassignMappingQuality filter by its selectivity -- only one mapping quality is targeted.
+ *     ReassignMappingQuality will change ALL mapping qualities to a single one, and is typically used for datasets
+ *     that have no assigned mapping qualities.
+ *  </p>
+ *
+ * <h3>Input</h3>
+ *  <p>
+ *	    BAM file(s)
+ *  </p>
+ *
+ *
+ * <h3>Output</h3>
+ *  <p>
+ *      BAM file(s) with one read mapping quality selectively reassigned as desired
+ *  </p>
+ *
+ * <h3>Examples</h3>
+ *  <pre>
+ *    java -jar GenomeAnalysisTK.jar
+ *      -T PrintReads
+ *      -rf ReassignOneMappingQuality
+ *      -RMQF 255
+ *      -RMQT 60
+ *  </pre>
+ *
+ * @author vdauwera
+ * @since 2/19/13
+ */
+
+public class ReassignOneMappingQualityFilter extends ReadFilter {
+
+    @Argument(fullName = "reassign_mapping_quality_from", shortName = "RMQF", doc = "Original mapping quality", required = false)
+    public int reassignMappingQualityFrom = 255;
+
+    @Argument(fullName = "reassign_mapping_quality_to", shortName = "RMQT", doc = "Desired mapping quality", required = false)
+    public int reassignMappingQualityTo = 60;
+
+    public boolean filterOut(SAMRecord rec) {
+        if (rec.getMappingQuality() == reassignMappingQualityFrom)
+        rec.setMappingQuality(reassignMappingQualityTo);
+        return false;
+    }
+}
+
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/filters/SampleFilter.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/filters/SampleFilter.java
new file mode 100644
index 0000000..2ec0112
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/filters/SampleFilter.java
@@ -0,0 +1,45 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.engine.filters;
+
+import htsjdk.samtools.SAMReadGroupRecord;
+import htsjdk.samtools.SAMRecord;
+import org.broadinstitute.gatk.utils.commandline.Argument;
+
+import java.util.Set;
+
+/**
+ * Filter out all reads except those with this sample
+ */
+public class SampleFilter extends ReadFilter {
+    @Argument(fullName = "sample_to_keep", shortName = "goodSM", doc="The name of the sample(s) to keep, filtering out all others", required=true)
+    private Set SAMPLES_TO_KEEP = null;
+
+    public boolean filterOut( final SAMRecord read ) {
+        final SAMReadGroupRecord readGroup = read.getReadGroup();
+        return !( readGroup != null && SAMPLES_TO_KEEP.contains(readGroup.getSample()) );
+    }
+}
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/filters/SingleReadGroupFilter.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/filters/SingleReadGroupFilter.java
new file mode 100644
index 0000000..5a9d214
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/filters/SingleReadGroupFilter.java
@@ -0,0 +1,48 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.engine.filters;
+
+import htsjdk.samtools.SAMReadGroupRecord;
+import htsjdk.samtools.SAMRecord;
+import org.broadinstitute.gatk.utils.commandline.Argument;
+
+/**
+ * Only use reads from the specified read group.
+ *
+ * @author rpoplin
+ * @since Nov 27, 2009
+ *
+ */
+
+public class SingleReadGroupFilter extends ReadFilter {
+    @Argument(fullName = "read_group_to_keep", shortName = "goodRG", doc="The name of the read group to keep, filtering out all others", required=true)
+    private String READ_GROUP_TO_KEEP = null;
+
+    public boolean filterOut( final SAMRecord read ) {
+        final SAMReadGroupRecord readGroup = read.getReadGroup();
+        return !( readGroup != null && readGroup.getReadGroupId().equals( READ_GROUP_TO_KEEP ) );
+    }
+}
\ No newline at end of file
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/filters/UnmappedReadFilter.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/filters/UnmappedReadFilter.java
new file mode 100644
index 0000000..e9cc302
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/filters/UnmappedReadFilter.java
@@ -0,0 +1,41 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.engine.filters;
+
+import htsjdk.samtools.SAMRecord;
+
+/**
+ * Filter out unmapped reads.
+ *
+ * @author rpoplin
+ * @since Dec 9, 2009
+ */
+
+public class UnmappedReadFilter extends ReadFilter {
+    public boolean filterOut( final SAMRecord read ) {
+        return read.getReadUnmappedFlag() || read.getAlignmentStart() == SAMRecord.NO_ALIGNMENT_START;
+    }
+}
\ No newline at end of file
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/filters/package-info.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/filters/package-info.java
new file mode 100644
index 0000000..7e36ffb
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/filters/package-info.java
@@ -0,0 +1,26 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.engine.filters;
\ No newline at end of file
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/io/DirectOutputTracker.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/io/DirectOutputTracker.java
new file mode 100644
index 0000000..96c9cb2
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/io/DirectOutputTracker.java
@@ -0,0 +1,48 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.engine.io;
+
+import org.broadinstitute.gatk.engine.io.storage.Storage;
+import org.broadinstitute.gatk.engine.io.storage.StorageFactory;
+import org.broadinstitute.gatk.engine.io.stubs.Stub;
+
+/**
+ * Maps creation of storage directly to output streams in parent.
+ *
+ * @author mhanna
+ * @version 0.1
+ */
+public class DirectOutputTracker extends OutputTracker {
+    public <T> T getStorage( Stub<T> stub ) {
+        Storage target = outputs.get(stub);
+        if( target == null ) {
+            target = StorageFactory.createStorage(stub);
+            outputs.put(stub, target);
+        }
+        return (T)target;
+    }
+
+}
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/io/FastqFileWriter.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/io/FastqFileWriter.java
new file mode 100644
index 0000000..772c327
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/io/FastqFileWriter.java
@@ -0,0 +1,77 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.engine.io;
+
+import org.broadinstitute.gatk.utils.exceptions.ReviewedGATKException;
+import org.broadinstitute.gatk.utils.sam.GATKSAMRecord;
+import org.broadinstitute.gatk.utils.sam.ReadUtils;
+
+import java.io.FileNotFoundException;
+import java.io.PrintStream;
+
+/**
+ * User: carneiro
+ * Date: 1/27/13
+ * Time: 12:54 AM
+ */
+public class FastqFileWriter {
+    private PrintStream output;
+
+    public FastqFileWriter(String filename) {
+        try {
+            this.output = new PrintStream(filename);
+        } catch (FileNotFoundException e) {
+            throw new ReviewedGATKException("Can't open file " + filename);
+        }
+    }
+
+    public void addAlignment(GATKSAMRecord read) {
+        output.println("@" + read.getReadName());
+
+        if (read.getReadNegativeStrandFlag()) {
+            output.println(ReadUtils.getBasesReverseComplement(read));
+            output.println("+");
+            output.println(ReadUtils.convertReadQualToString(invertQuals(read.getBaseQualities())));
+        } else {
+            output.println(ReadUtils.convertReadBasesToString(read));
+            output.println("+");
+            output.println(ReadUtils.convertReadQualToString(read));
+        }
+    }
+
+    public void close() {
+        this.output.close();
+    }
+
+    private byte[] invertQuals (byte[] quals) {
+        final int l = quals.length;
+        byte[] invertedQuals = new byte[l];
+        for (int i=0; i<l; i++) {
+            invertedQuals[l-1-i] = quals[i];
+        }
+        return invertedQuals;
+    }
+}
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/io/GATKSAMFileWriter.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/io/GATKSAMFileWriter.java
new file mode 100644
index 0000000..c60aae8
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/io/GATKSAMFileWriter.java
@@ -0,0 +1,56 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.engine.io;
+
+import htsjdk.samtools.SAMFileHeader;
+import htsjdk.samtools.SAMFileWriter;
+
+/**
+ * A writer that will allow unsorted BAM files to be written
+ * and sorted on-the-fly.
+ *
+ * @author mhanna
+ * @version 0.1
+ */
+public interface GATKSAMFileWriter extends SAMFileWriter {
+    /**
+     * Writes the given custom header to SAM file output.
+     * @param header The header to write.
+     */
+    public void writeHeader(SAMFileHeader header);
+
+    /**
+     * Set Whether the BAM file to create is actually presorted.
+     * @param presorted True if the BAM file is presorted.  False otherwise.
+     */    
+    public void setPresorted(boolean presorted);
+
+    /**
+     * Set how many records in RAM the BAM file stores when sorting on-the-fly.
+     * @param maxRecordsInRam Max number of records in RAM.
+     */
+    public void setMaxRecordsInRam(int maxRecordsInRam);
+}
\ No newline at end of file
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/io/OutputTracker.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/io/OutputTracker.java
new file mode 100644
index 0000000..8f2fbe3
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/io/OutputTracker.java
@@ -0,0 +1,178 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.engine.io;
+
+import htsjdk.samtools.SAMFileReader;
+import htsjdk.samtools.ValidationStringency;
+import org.broadinstitute.gatk.utils.commandline.ArgumentSource;
+import org.broadinstitute.gatk.engine.io.storage.Storage;
+import org.broadinstitute.gatk.engine.io.storage.StorageFactory;
+import org.broadinstitute.gatk.engine.io.stubs.OutputStreamStub;
+import org.broadinstitute.gatk.engine.io.stubs.Stub;
+import org.broadinstitute.gatk.engine.walkers.Walker;
+import org.broadinstitute.gatk.utils.classloader.JVMUtils;
+import org.broadinstitute.gatk.utils.exceptions.ReviewedGATKException;
+import org.broadinstitute.gatk.utils.exceptions.UserException;
+import org.broadinstitute.gatk.utils.io.IOUtils;
+import org.broadinstitute.gatk.utils.sam.SAMFileReaderBuilder;
+
+import java.io.File;
+import java.io.OutputStream;
+import java.lang.reflect.Field;
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * Manages the output and err streams that are created specifically for walker
+ * output.
+ */
+public abstract class OutputTracker {
+    /**
+     * The streams to which walker users should be reading directly.
+     */
+    protected Map<ArgumentSource, Object> inputs = new HashMap<ArgumentSource,Object>();
+
+    /**
+     * The streams to which walker users should be writing directly.
+     */
+    protected Map<Stub,Storage> outputs = new HashMap<Stub,Storage>();
+
+    /**
+     * Special-purpose stub.  Provides a connection to output streams.
+     */
+    protected OutputStreamStub outStub = null;
+
+    /**
+     * Special-purpose stream.  Provides a connection to error streams.
+     */
+    protected OutputStreamStub errStub = null;
+
+    /**
+     * Gets the output storage associated with a given stub.
+     * @param stub The stub for which to find / create the right output stream.
+     * @param <T> Type of the stream to create.
+     * @return Storage object with a facade of type T.
+     */
+    public abstract <T> T getStorage( Stub<T> stub );
+
+    public void prepareWalker( Walker walker, ValidationStringency strictnessLevel ) {
+        for( Map.Entry<ArgumentSource,Object> io: inputs.entrySet() ) {
+            ArgumentSource targetField = io.getKey();
+            Object targetValue = io.getValue();
+
+            // Ghastly hack: reaches in and finishes building out the SAMFileReader.
+            // TODO: Generalize this, and move it to its own initialization step.
+            if( targetValue instanceof SAMFileReaderBuilder) {
+                SAMFileReaderBuilder builder = (SAMFileReaderBuilder)targetValue;
+                builder.setValidationStringency(strictnessLevel);
+                targetValue = builder.build();
+            }
+
+            JVMUtils.setFieldValue( targetField.field, walker, targetValue );
+        }
+    }
+
+    /**
+     * Provide a mechanism for injecting supplemental streams for external management.
+     * @param argumentSource source Class / field into which to inject this stream.
+     * @param stub Stream to manage.
+     */
+    public void addInput( ArgumentSource argumentSource, Object stub ) {
+        inputs.put(argumentSource,stub);
+    }
+
+    /**
+     * Provide a mechanism for injecting supplemental streams for external management.
+     * @param stub Stream to manage.
+     */
+    public <T> void addOutput(Stub<T> stub) {
+        addOutput(stub,null);
+    }
+
+    /**
+     * Provide a mechanism for injecting supplemental streams for external management.
+     * @param stub Stream to manage.
+     */
+    public <T> void addOutput(Stub<T> stub, Storage<T> storage) {
+        stub.register(this);
+        outputs.put(stub,storage);
+        validateOutputPath(stub);
+    }
+
+    /**
+     * Close down all existing output streams.
+     */
+    public void close() {
+        for( Stub stub: outputs.keySet() ) {
+            // If the stream hasn't yet been created, create it so that there's at least an empty file present.
+            if( outputs.get(stub) == null )
+                getTargetStream(stub);
+
+            // Close down the storage.
+            outputs.get(stub).close();
+        }
+    }
+
+    /**
+     * Collects the target stream for this data.
+     * @param stub The stub for this stream.
+     * @param <T> type of stub.
+     * @return An instantiated file into which data can be written.
+     */
+    protected <T> T getTargetStream( Stub<T> stub ) {
+        if( !outputs.containsKey(stub) )
+            throw new ReviewedGATKException("OutputTracker was not notified that this stub exists: " + stub);
+        Storage<T> storage = outputs.get(stub);
+        if( storage == null ) {
+            storage = StorageFactory.createStorage(stub);
+            outputs.put(stub,storage);
+        }
+        return (T)storage;
+    }
+
+    /**
+     * Ensures that the File associated with this stub (if any) is in a writable location
+     * @param stub
+     */
+    protected <T> void validateOutputPath(final Stub<T> stub) {
+        if (stub.getOutputFile() != null && !(IOUtils.isSpecialFile(stub.getOutputFile()))) {
+            final File parentDir = stub.getOutputFile().getAbsoluteFile().getParentFile();
+            if (! (parentDir.canWrite() && parentDir.canExecute()))
+                throw new UserException.CouldNotCreateOutputFile(stub.getOutputFile(),
+                        "either the containing directory doesn't exist or it isn't writable");
+        }
+    }
+
+    /**
+     * Install an OutputStreamStub into the given fieldName of the given walker.
+     * @param walker Walker into which to inject the field name.
+     * @param fieldName Name of the field into which to inject the stub.
+     */
+    private void installStub( Walker walker, String fieldName, OutputStream outputStream ) {
+        Field field = JVMUtils.findField( walker.getClass(), fieldName );
+        JVMUtils.setFieldValue( field, walker, outputStream );
+    }    
+}
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/io/ThreadGroupOutputTracker.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/io/ThreadGroupOutputTracker.java
new file mode 100644
index 0000000..fdb5fd2
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/io/ThreadGroupOutputTracker.java
@@ -0,0 +1,170 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.engine.io;
+
+import org.broadinstitute.gatk.engine.executive.OutputMergeTask;
+import org.broadinstitute.gatk.engine.io.storage.Storage;
+import org.broadinstitute.gatk.engine.io.storage.StorageFactory;
+import org.broadinstitute.gatk.engine.io.stubs.Stub;
+import org.broadinstitute.gatk.utils.exceptions.ReviewedGATKException;
+import org.broadinstitute.gatk.utils.exceptions.UserException;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * An output tracker that can either track its output per-thread or directly.
+ *
+ * This output tracker doesn't use thread local values, but rather looks up the
+ * storage map via the thread's group.  This is necessary in the case where
+ * there's a master thread that creates the output map, and spawns subthreads
+ * that actually do work.  As long as those subthreads are spawned in the
+ * thread group of the master thread, this tracker will properly find the
+ * storage map associated with the master thread in the group, and return
+ * the map to all subthreads.
+ *
+ * @author mhanna, depristo
+ * @version 0.2
+ */
+public class ThreadGroupOutputTracker extends OutputTracker {
+    /**
+     * A map from thread ID of the master thread to the storage map from
+     * Stub to Storage objects
+     */
+    private Map<ThreadGroup, Map<Stub, Storage>> threadsToStorage = new HashMap<ThreadGroup, Map<Stub, Storage>>();
+
+    /**
+     * A total hack.  If bypass = true, bypass thread local storage and write directly
+     * to the target file.  Used to handle output during initialize() and onTraversalDone().
+     */
+    private boolean bypass = false;
+    public void bypassThreadLocalStorage(boolean bypass) {
+        this.bypass = bypass;
+    }
+
+    /**
+     * Initialize the storage map for this thread.
+     *
+     * Checks if there's a thread local binding for this thread, and if
+     * not initializes the map for it.  This map is then
+     * populated with stub -> storage bindings according to the
+     * superclasses' outputs map.
+     *
+     * Must be called within the master thread to create a map associated with
+     * the master thread ID.
+     */
+    public synchronized void initializeStorage() {
+        final ThreadGroup group = Thread.currentThread().getThreadGroup();
+        Map<Stub,Storage> threadLocalOutputStreams = threadsToStorage.get(group);
+
+        if( threadLocalOutputStreams == null ) {
+            threadLocalOutputStreams = new HashMap<Stub,Storage>();
+            threadsToStorage.put( group, threadLocalOutputStreams );
+        }
+
+        for ( final Stub stub : outputs.keySet() ) {
+            final Storage target = StorageFactory.createStorage(stub, createTempFile(stub));
+            threadLocalOutputStreams.put(stub, target);
+        }
+    }
+
+    @Override
+    public <T> T getStorage( final Stub<T> stub ) {
+        Storage target;
+
+        if (bypass) {
+            target = outputs.get(stub);
+            if( target == null ) {
+                target = StorageFactory.createStorage(stub);
+                outputs.put(stub, target);
+            }
+        }
+        else {
+            final Map<Stub,Storage> threadLocalOutputStreams = findStorage(Thread.currentThread());
+            target = threadLocalOutputStreams.get(stub);
+
+            // make sure something hasn't gone wrong, and we somehow find a map that doesn't include our stub
+            if ( target == null )
+                throw new ReviewedGATKException("target isn't supposed to be null for " + Thread.currentThread()
+                        + " id " + Thread.currentThread().getId() + " map is " + threadLocalOutputStreams);
+        }
+
+        return (T)target;
+    }
+
+
+    private synchronized Map<Stub,Storage> findStorage(final Thread thread) {
+        final Map<Stub, Storage> map = threadsToStorage.get(thread.getThreadGroup());
+
+        if ( map != null ) {
+            return map;
+        } else {
+            // something is terribly wrong, we have a storage lookup for a thread that doesn't have
+            // any map data associated with it!
+            throw new ReviewedGATKException("Couldn't find storage map associated with thread " + thread + " in group " + thread.getThreadGroup());
+        }
+    }
+
+    /**
+     * Close down any existing temporary files which have been opened.
+     */
+    public synchronized OutputMergeTask closeStorage() {
+        final Map<Stub,Storage> threadLocalOutputStreams = findStorage(Thread.currentThread());
+
+        if( threadLocalOutputStreams == null || threadLocalOutputStreams.isEmpty() )
+            return null;
+
+        final OutputMergeTask outputMergeTask = new OutputMergeTask();
+        for( Map.Entry<Stub,Storage> entry: threadLocalOutputStreams.entrySet() ) {
+            final Stub stub = entry.getKey();
+            final Storage storageEntry = entry.getValue();
+
+            storageEntry.close();
+            outputMergeTask.addMergeOperation(getTargetStream(stub), storageEntry);
+        }
+
+//        logger.info("Closing " + Thread.currentThread().getId() + " => " + threadLocalOutputStreams);
+        threadLocalOutputStreams.clear();
+
+        return outputMergeTask;
+    }
+
+    /**
+     * Creates a temporary file for a stub of the given type.
+     * @param stub Stub for which to create a temporary file.
+     * @param <T> Type of the stub to accept.
+     * @return A temp file, or throw an exception if the temp file cannot be created.
+     */
+    private <T> File createTempFile( Stub<T> stub ) {
+        try {
+            return File.createTempFile( stub.getClass().getName(), null );
+        } catch( IOException ex ) {
+            throw new UserException.BadTmpDir("Unable to create temporary file for stub: " + stub.getClass().getName() );
+        }
+    }
+}
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/io/storage/OutputStreamStorage.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/io/storage/OutputStreamStorage.java
new file mode 100644
index 0000000..ac348a2
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/io/storage/OutputStreamStorage.java
@@ -0,0 +1,144 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.engine.io.storage;
+
+import org.broadinstitute.gatk.engine.io.stubs.OutputStreamStub;
+import org.broadinstitute.gatk.utils.exceptions.ReviewedGATKException;
+import org.broadinstitute.gatk.utils.exceptions.UserException;
+
+import java.io.*;
+import java.nio.channels.Channels;
+import java.nio.channels.FileChannel;
+import java.nio.channels.WritableByteChannel;
+
+public class OutputStreamStorage extends OutputStream implements Storage<OutputStream> {
+    /**
+     * File to which data will temporarily be written.
+     */
+    private final File file;
+
+    /**
+     * Stream to which data in this shard will be written.
+     */
+    private final OutputStream outputStream;
+
+    /**
+     * Create a new storage area with the given stub.
+     * @param stub
+     */
+    public OutputStreamStorage( OutputStreamStub stub ) {
+        if( stub.getOutputFile() != null ) {
+            this.file = stub.getOutputFile();
+            this.outputStream = initializeOutputStream(stub.getOutputFile());
+        }
+        else if( stub.getOutputStream() != null ) {
+            this.file = null;
+            this.outputStream = stub.getOutputStream();           
+        }
+        else
+            throw new ReviewedGATKException("Not enough information to create storage for an OutputStream; need either a file or an existing output stream");
+    }
+
+    public OutputStreamStorage( OutputStreamStub stub, File file ) {
+        this.file = file;
+        this.outputStream = initializeOutputStream(file);
+    }
+
+    private OutputStream initializeOutputStream( File file ) {
+        try {
+            return new FileOutputStream( file );
+        }
+        catch(FileNotFoundException ex) {
+            throw new UserException.CouldNotCreateOutputFile(file, "Unable to open output stream for file", ex);
+        }
+    }
+
+    /**
+     * @{inheritDoc}
+     */
+    public void flush() throws IOException {
+        outputStream.flush();
+    }
+
+    /**
+     * @{inheritDoc}
+     */
+    public void close() {
+        // Don't close System.out or System.err; this'll cause trouble
+        // with subsequent code running in this VM.
+        if( outputStream == System.out || outputStream == System.err )
+            return;
+        
+        try {
+            outputStream.close();
+        }
+        catch( IOException ex ) {
+            throw new UserException.CouldNotCreateOutputFile(file, "Unable to close output stream", ex );
+        }
+    }
+
+    /**
+     * @{inheritDoc}
+     */
+    public void write( byte[] b ) throws IOException {
+        outputStream.write(b);
+    }
+
+    /**
+     * @{inheritDoc}
+     */
+    public void write( byte[] b, int off, int len ) throws IOException {
+        outputStream.write(b, off, len);
+    }
+
+    /**
+     * @{inheritDoc}
+     */
+    public void write( int b ) throws IOException {
+        outputStream.write(b);
+    }
+
+
+    public void mergeInto( OutputStream targetStream ) {
+        FileInputStream sourceStream = null;
+        try {
+            sourceStream = new FileInputStream( file );
+            FileChannel sourceChannel = sourceStream.getChannel();
+
+            WritableByteChannel targetChannel = Channels.newChannel( targetStream );
+            sourceChannel.transferTo( 0, sourceChannel.size(), targetChannel );
+
+            sourceStream.close();
+            file.delete();
+        }
+        catch( FileNotFoundException ex ) {
+            throw new UserException.CouldNotReadInputFile(file, "Unable to open input stream for file", ex);
+        }
+        catch( IOException ex ) {
+            throw new UserException.CouldNotReadInputFile(file, "Unable to transfer contents of file", ex);
+        }
+    }
+}
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/io/storage/SAMFileWriterStorage.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/io/storage/SAMFileWriterStorage.java
new file mode 100644
index 0000000..3956e6e
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/io/storage/SAMFileWriterStorage.java
@@ -0,0 +1,157 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.engine.io.storage;
+
+import htsjdk.samtools.*;
+import htsjdk.samtools.util.CloseableIterator;
+import htsjdk.samtools.util.ProgressLoggerInterface;
+import htsjdk.samtools.util.RuntimeIOException;
+import org.apache.log4j.Logger;
+import org.broadinstitute.gatk.engine.io.stubs.SAMFileWriterStub;
+import org.broadinstitute.gatk.utils.exceptions.UserException;
+import org.broadinstitute.gatk.utils.sam.SimplifyingSAMFileWriter;
+
+import java.io.File;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+
+/**
+ * Provides temporary storage for SAMFileWriters.
+ *
+ * @author mhanna
+ * @version 0.1
+ */
+public class SAMFileWriterStorage implements SAMFileWriter, Storage<SAMFileWriter> {
+    private final File file;
+    private SAMFileWriter writer;
+
+    private static Logger logger = Logger.getLogger(SAMFileWriterStorage.class);
+
+    public SAMFileWriterStorage( SAMFileWriterStub stub ) {
+        this(stub,stub.getOutputFile());
+    }
+
+    public SAMFileWriterStorage( SAMFileWriterStub stub, File file ) {
+        this.file = file;
+        SAMFileWriterFactory factory = new SAMFileWriterFactory();
+        // Enable automatic index creation for pre-sorted BAMs.
+        if (stub.getFileHeader().getSortOrder().equals(SAMFileHeader.SortOrder.coordinate) && stub.getIndexOnTheFly())
+            factory.setCreateIndex(true);
+        if (stub.getGenerateMD5())
+            factory.setCreateMd5File(true);
+        // Adjust max records in RAM.
+        // TODO -- this doesn't actually work because of a bug in Picard; do not use until fixed
+        if(stub.getMaxRecordsInRam() != null)
+            factory.setMaxRecordsInRam(stub.getMaxRecordsInRam());
+
+        if(stub.getOutputFile() != null) {
+            try {
+                this.writer = createBAMWriter(factory,stub.getFileHeader(),stub.isPresorted(),file,stub.getCompressionLevel());
+            }
+            catch(RuntimeIOException ex) {
+                throw new UserException.CouldNotCreateOutputFile(file,"file could not be created",ex);
+            }
+        }
+        else if(stub.getOutputStream() != null){
+            this.writer = factory.makeSAMWriter( stub.getFileHeader(), stub.isPresorted(), stub.getOutputStream());
+        }
+        else
+            throw new UserException("Unable to write to SAM file; neither a target file nor a stream has been specified");
+
+        // if we want to send the BAM file through the simplifying writer, wrap it here
+        if ( stub.simplifyBAM() ) {
+            this.writer = new SimplifyingSAMFileWriter(this.writer);
+        }
+    }
+
+    public SAMFileHeader getFileHeader() {
+        return writer.getFileHeader();
+    }
+
+    public void addAlignment( SAMRecord read ) {
+        writer.addAlignment(read);
+    }
+
+    public void close() {
+        try {
+            writer.close();
+        } catch (RuntimeIOException e) {
+            throw new UserException.ErrorWritingBamFile(e.getMessage());
+        }
+    }
+
+    public void mergeInto( SAMFileWriter targetStream ) {
+        SAMFileReader reader = new SAMFileReader( file );
+        try {
+            CloseableIterator<SAMRecord> iterator = reader.iterator();
+            while( iterator.hasNext() )
+                targetStream.addAlignment( iterator.next() );
+            iterator.close();
+        }
+        finally {
+            reader.close();
+            file.delete();
+        }
+    }
+
+    private SAMFileWriter createBAMWriter(final SAMFileWriterFactory factory,
+                                 final SAMFileHeader header,
+                                 final boolean presorted,
+                                 final File outputFile,
+                                 final Integer compressionLevel) {
+        SAMFileWriter writer;
+        if(compressionLevel != null)
+            writer = factory.makeBAMWriter(header, presorted, outputFile, compressionLevel);
+        else
+            writer = factory.makeBAMWriter(header, presorted, outputFile);
+
+        // mhanna - 1 Mar 2011 - temporary hack until Picard generates an index file for empty BAMs --
+        //                     - do a pre-initialization of the BAM file.
+        try {
+            Method prepareToWriteAlignmentsMethod = writer.getClass().getDeclaredMethod("prepareToWriteAlignments");
+            if(prepareToWriteAlignmentsMethod != null) {
+                prepareToWriteAlignmentsMethod.setAccessible(true);
+                prepareToWriteAlignmentsMethod.invoke(writer);
+            }
+        }
+        catch(NoSuchMethodException ex) {
+            logger.info("Unable to call prepareToWriteAlignments method; this should be reviewed when Picard is updated.");
+        }
+        catch(IllegalAccessException ex) {
+            logger.info("Unable to access prepareToWriteAlignments method; this should be reviewed when Picard is updated.");
+        }
+        catch(InvocationTargetException ex) {
+            logger.info("Unable to invoke prepareToWriteAlignments method; this should be reviewed when Picard is updated.");
+        }
+
+        return writer;
+    }
+
+    @Override
+    public void setProgressLogger(final ProgressLoggerInterface logger) {
+        writer.setProgressLogger(logger);
+    }
+}
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/io/storage/Storage.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/io/storage/Storage.java
new file mode 100644
index 0000000..363b70f
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/io/storage/Storage.java
@@ -0,0 +1,45 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.engine.io.storage;
+
+/**
+ * An interface representing the temporary storage of data.
+ *
+ * @author mhanna
+ * @version 0.1
+ */
+public interface Storage<StreamType> {
+    /**
+     * Writing to the temporary storage is done.  Close down the file.
+     */
+    public void close();
+
+    /**
+     * Merges the stream backing up this temporary storage into the target.
+     * @param target Target stream for the temporary storage.  May not be null.
+     */
+    public void mergeInto( StreamType target );
+}
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/io/storage/StorageFactory.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/io/storage/StorageFactory.java
new file mode 100644
index 0000000..3396006
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/io/storage/StorageFactory.java
@@ -0,0 +1,92 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.engine.io.storage;
+
+import org.broadinstitute.gatk.engine.io.stubs.OutputStreamStub;
+import org.broadinstitute.gatk.engine.io.stubs.SAMFileWriterStub;
+import org.broadinstitute.gatk.engine.io.stubs.Stub;
+import org.broadinstitute.gatk.engine.io.stubs.VariantContextWriterStub;
+import org.broadinstitute.gatk.utils.exceptions.ReviewedGATKException;
+
+import java.io.File;
+
+/**
+ * Construct storage of the required type.
+ *
+ * @author mhanna
+ * @version 0.1
+ */
+public class StorageFactory {
+    /**
+     * Disable storage factory construction.
+     */
+    private StorageFactory() {}
+
+    /**
+     * Gets the output storage associated with a given stub.
+     * @param stub The stub for which to find / create the right output stream.
+     * @param <T> Type of the stream to create.
+     * @return Storage object with a facade of type T.
+     */
+    public static <T> Storage<T> createStorage( Stub<T> stub ) {
+        return createStorage( stub, null );
+    }
+
+    /**
+     * Gets the output storage associated with a given stub.
+     * @param stub The stub for which to find / create the right output stream.
+     * @param file The filename to which to write the file.
+     * @param <T> Type of the stream to create.
+     * @return Storage object with a facade of type T.
+     */
+     public static <T> Storage<T> createStorage( Stub<T> stub, File file ) {
+        Storage storage;
+
+        if(stub instanceof OutputStreamStub) {
+            if( file != null )
+                storage = new OutputStreamStorage((OutputStreamStub)stub,file);
+            else
+                storage = new OutputStreamStorage((OutputStreamStub)stub);
+        }
+        else if(stub instanceof SAMFileWriterStub) {
+            if( file != null )
+                storage = new SAMFileWriterStorage((SAMFileWriterStub)stub,file);
+            else
+                storage = new SAMFileWriterStorage((SAMFileWriterStub)stub);
+        }
+        else if(stub instanceof VariantContextWriterStub) {
+            VariantContextWriterStub vcfWriterStub = (VariantContextWriterStub)stub;
+            if( file != null )
+                storage = new VariantContextWriterStorage(vcfWriterStub,file);
+            else
+                storage = new VariantContextWriterStorage(vcfWriterStub);
+        }
+        else
+            throw new ReviewedGATKException("Unsupported stub type: " + stub.getClass().getName());
+
+        return storage;
+    }
+}
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/io/storage/VariantContextWriterStorage.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/io/storage/VariantContextWriterStorage.java
new file mode 100644
index 0000000..c4f7769
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/io/storage/VariantContextWriterStorage.java
@@ -0,0 +1,228 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.engine.io.storage;
+
+import htsjdk.samtools.util.BlockCompressedOutputStream;
+import org.apache.log4j.Logger;
+import htsjdk.tribble.AbstractFeatureReader;
+import htsjdk.tribble.Feature;
+import htsjdk.tribble.FeatureCodec;
+import org.broadinstitute.gatk.engine.io.stubs.VariantContextWriterStub;
+import org.broadinstitute.gatk.engine.refdata.tracks.FeatureManager;
+import org.broadinstitute.gatk.utils.exceptions.ReviewedGATKException;
+import org.broadinstitute.gatk.utils.exceptions.UserException;
+import htsjdk.variant.bcf2.BCF2Utils;
+import htsjdk.variant.variantcontext.VariantContext;
+import htsjdk.variant.variantcontext.writer.Options;
+import htsjdk.variant.variantcontext.writer.VariantContextWriter;
+import htsjdk.variant.variantcontext.writer.VariantContextWriterFactory;
+import htsjdk.variant.vcf.VCFHeader;
+
+import java.io.*;
+import java.util.Arrays;
+import java.util.EnumSet;
+import java.util.List;
+
+/**
+ * Provides temporary and permanent storage for genotypes in VCF format.
+ *
+ * @author mhanna
+ * @version 0.1
+ */
+public class VariantContextWriterStorage implements Storage<VariantContextWriterStorage>, VariantContextWriter {
+    /**
+     * our log, which we want to capture anything from this class
+     */
+    private static Logger logger = Logger.getLogger(VariantContextWriterStorage.class);
+
+    private final static int BUFFER_SIZE = 1048576;
+
+    protected final File file;
+    protected OutputStream stream;
+    protected final VariantContextWriter writer;
+    boolean closed = false;
+
+    /**
+     * Constructs an object which will write directly into the output file provided by the stub.
+     * Intentionally delaying the writing of the header -- this should be filled in by the walker.
+     *
+     * Respecs the isCompressed() request in stub, so if isCompressed() is true then this
+     * will create a storage output that dumps output to a BlockCompressedOutputStream.
+     *
+     * @param stub Stub to use when constructing the output file.
+     */
+    public VariantContextWriterStorage(VariantContextWriterStub stub)  {
+        if ( stub.getOutputFile() != null ) {
+            this.file = stub.getOutputFile();
+            writer = vcfWriterToFile(stub,stub.getOutputFile(),true,true);
+        }
+        else if ( stub.getOutputStream() != null ) {
+            this.file = null;
+            this.stream = stub.getOutputStream();
+            writer = VariantContextWriterFactory.create(stream,
+                    stub.getMasterSequenceDictionary(), stub.getWriterOptions(false));
+        }
+        else
+            throw new ReviewedGATKException("Unable to create target to which to write; storage was provided with neither a file nor a stream.");
+    }
+
+    /**
+     * Constructs an object which will redirect into a different file.
+     *
+     * Note that this function does not respect the isCompressed() request from the stub, in order
+     * to ensure that tmp. files can be read back in by the Tribble system, and merged with the mergeInto function.
+     *
+     * @param stub Stub to use when synthesizing file / header info.
+     * @param tempFile File into which to direct the output data.
+     */
+    public VariantContextWriterStorage(VariantContextWriterStub stub, File tempFile) {
+        //logger.debug("Creating temporary output file " + tempFile.getAbsolutePath() + " for VariantContext output.");
+        this.file = tempFile;
+        this.writer = vcfWriterToFile(stub, file, false, false);
+        writer.writeHeader(stub.getVCFHeader());
+    }
+
+    /**
+     * common initialization routine for multiple constructors
+     * @param stub Stub to use when constructing the output file.
+     * @param file Target file into which to write VCF records.
+     * @param indexOnTheFly true to index the file on the fly.  NOTE: will be forced to false for compressed files.
+     * @param allowCompressed if false, we won't compress the output, even if the stub requests it.  Critical
+     *                        for creating temp. output files that will be subsequently merged, as these do not
+     *                        support compressed output
+     * @return A VCF writer for use with this class
+     */
+    private VariantContextWriter vcfWriterToFile(final VariantContextWriterStub stub,
+                                                 final File file,
+                                                 final boolean indexOnTheFly,
+                                                 final boolean allowCompressed) {
+        try {
+            // we cannot merge compressed outputs, so don't compress if allowCompressed is false,
+            // which is the case when we have a temporary output file for later merging
+            if ( allowCompressed && stub.isCompressed() )
+                stream = new BlockCompressedOutputStream(file);
+            else
+                stream = new PrintStream(new BufferedOutputStream(new FileOutputStream(file), BUFFER_SIZE));
+        }
+        catch(IOException ex) {
+            throw new UserException.CouldNotCreateOutputFile(file, "Unable to open target output stream", ex);
+        }
+
+        EnumSet<Options> options = stub.getWriterOptions(indexOnTheFly);
+        VariantContextWriter writer = VariantContextWriterFactory.create(file, this.stream, stub.getMasterSequenceDictionary(), stub.getIndexCreator(), options);
+
+        // if the stub says to test BCF, create a secondary writer to BCF and an 2 way out writer to send to both
+        // TODO -- remove me when argument generateShadowBCF is removed
+        if ( stub.alsoWriteBCFForTest() && ! VariantContextWriterFactory.isBCFOutput(file, options)) {
+            final File bcfFile = BCF2Utils.shadowBCF(file);
+            if ( bcfFile != null ) {
+                FileOutputStream bcfStream;
+                try {
+                    bcfStream = new FileOutputStream(bcfFile);
+                } catch (FileNotFoundException e) {
+                    throw new RuntimeException(bcfFile + ": Unable to create BCF writer", e);
+                }
+
+                VariantContextWriter bcfWriter = VariantContextWriterFactory.create(bcfFile, bcfStream, stub.getMasterSequenceDictionary(), stub.getIndexCreator(), options);
+                writer = new TestWriter(writer, bcfWriter);
+            }
+        }
+
+        return writer;
+    }
+
+    private final static class TestWriter implements VariantContextWriter {
+        final List<VariantContextWriter> writers;
+
+        private TestWriter(final VariantContextWriter ... writers) {
+            this.writers = Arrays.asList(writers);
+        }
+
+        @Override
+        public void writeHeader(final VCFHeader header) {
+            for ( final VariantContextWriter writer : writers ) writer.writeHeader(header);
+        }
+
+        @Override
+        public void close() {
+            for ( final VariantContextWriter writer : writers ) writer.close();
+        }
+
+        @Override
+        public void add(final VariantContext vc) {
+            for ( final VariantContextWriter writer : writers ) writer.add(vc);
+        }
+    }
+
+    public void add(VariantContext vc) {
+        if ( closed ) throw new ReviewedGATKException("Attempting to write to a closed VariantContextWriterStorage " + vc.getStart() + " storage=" + this);
+        writer.add(vc);
+    }
+
+    /**
+     * initialize this VCF header
+     *
+     * @param header  the header
+     */
+    public void writeHeader(VCFHeader header) {
+        writer.writeHeader(header);
+    }
+
+    /**
+     * Close the VCF storage object.
+     */
+    public void close() {
+        writer.close();
+        closed = true;
+    }
+
+    public void mergeInto(VariantContextWriterStorage target) {
+        try {
+            if ( ! closed )
+                throw new ReviewedGATKException("Writer not closed, but we are merging into the file!");
+            final String targetFilePath = target.file != null ? target.file.getAbsolutePath() : "/dev/stdin";
+            logger.debug(String.format("Merging VariantContextWriterStorage from %s into %s", file.getAbsolutePath(), targetFilePath));
+
+            // use the feature manager to determine the right codec for the tmp file
+            // that way we don't assume it's a specific type
+            final FeatureManager.FeatureDescriptor fd = new FeatureManager().getByFiletype(file);
+            if ( fd == null )
+                throw new UserException.LocalParallelizationProblem(file);
+
+            final FeatureCodec codec = fd.getCodec();
+            final AbstractFeatureReader<Feature, ?> source = AbstractFeatureReader.getFeatureReader(file.getAbsolutePath(), codec, false);
+
+            for ( final Feature vc : source.iterator() ) {
+                target.writer.add((VariantContext) vc);
+            }
+
+            source.close();
+            file.delete(); // this should be last to aid in debugging when the process fails
+        } catch (IOException e) {
+            throw new UserException.CouldNotReadInputFile(file, "Error reading file in VCFWriterStorage: ", e);
+        }
+    }
+}
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/io/stubs/OutputStreamArgumentTypeDescriptor.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/io/stubs/OutputStreamArgumentTypeDescriptor.java
new file mode 100644
index 0000000..89b8b59
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/io/stubs/OutputStreamArgumentTypeDescriptor.java
@@ -0,0 +1,134 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.engine.io.stubs;
+
+import org.broadinstitute.gatk.utils.commandline.*;
+import org.broadinstitute.gatk.engine.GenomeAnalysisEngine;
+import org.broadinstitute.gatk.utils.exceptions.DynamicClassResolutionException;
+import org.broadinstitute.gatk.utils.exceptions.ReviewedGATKException;
+
+import java.io.File;
+import java.io.OutputStream;
+import java.lang.reflect.Constructor;
+import java.lang.reflect.Type;
+
+/**
+ * Insert an OutputStreamStub instead of a full-fledged concrete OutputStream implementations.
+ */
+public class OutputStreamArgumentTypeDescriptor extends ArgumentTypeDescriptor {
+    /**
+     * The engine into which output stubs should be fed.
+     */
+    private final GenomeAnalysisEngine engine;
+
+    /**
+     * The default output stream to write to write this info if
+     */
+    private final OutputStream defaultOutputStream;
+
+    /**
+     * Create a new OutputStream argument, notifying the given engine when that argument has been created.
+     * @param engine Engine to add SAMFileWriter output to.
+     * @param defaultOutputStream Default target for output file.
+     */
+    public OutputStreamArgumentTypeDescriptor(GenomeAnalysisEngine engine,OutputStream defaultOutputStream) {
+        this.engine = engine;
+        this.defaultOutputStream = defaultOutputStream;
+    }
+
+    @Override
+    public boolean supports( Class type ) {
+        return getConstructorForClass(type) != null;
+    }
+
+    @Override
+    public boolean createsTypeDefault(ArgumentSource source) {
+        return !source.isRequired() && source.defaultsToStdout();
+    }
+
+    @Override
+    public String typeDefaultDocString(ArgumentSource source) {
+        return "stdout";
+    }
+
+    @Override
+    public Object createTypeDefault(ParsingEngine parsingEngine,ArgumentSource source, Type type) {
+        if(source.isRequired() || !source.defaultsToStdout())
+            throw new ReviewedGATKException("BUG: tried to create type default for argument type descriptor that can't support a type default.");
+        OutputStreamStub stub = new OutputStreamStub(defaultOutputStream);
+        engine.addOutput(stub);
+        return createInstanceOfClass((Class)type,stub);
+    }
+
+    @Override
+    public Object parse( ParsingEngine parsingEngine, ArgumentSource source, Type type, ArgumentMatches matches )  {
+        ArgumentDefinition definition = createDefaultArgumentDefinition(source);
+        String fileName = getArgumentValue( definition, matches ).asString();
+
+        // This parser has been passed a null filename and the GATK is not responsible for creating a type default for the object;
+        // therefore, the user must have failed to specify a type default
+        if(fileName == null && source.isRequired())
+            throw new MissingArgumentValueException(definition);
+
+        OutputStreamStub stub = new OutputStreamStub(new File(fileName));
+
+        engine.addOutput(stub);
+
+        Object result = createInstanceOfClass(makeRawTypeIfNecessary(type),stub);
+        // WARNING: Side effects required by engine!
+        parsingEngine.addTags(result,getArgumentTags(matches));
+        
+        return result;
+    }
+
+    /**
+     * Retrieves the constructor for an object that takes exactly one argument: an output stream.
+     * @param type Type for which to go constructor spelunking.
+     * @return Constructor, if available.  Null, if not.
+     */
+    private Constructor<OutputStream> getConstructorForClass( Class type ) {
+        try {
+            return type.getConstructor( OutputStream.class );
+        }
+        catch( NoSuchMethodException ex ) {
+            return null;
+        }
+    }
+
+    /**
+     * Creat a new instance of the class accepting a single outputstream constructor.
+     * @param type Type of object to create.
+     * @param outputStream resulting output stream.
+     * @return A new instance of the outputstream-derived class.
+     */
+    private Object createInstanceOfClass(Class type,OutputStream outputStream) {
+        try {
+            return getConstructorForClass(type).newInstance(outputStream);
+        } catch (Exception e) {
+            throw new DynamicClassResolutionException(type, e);
+        }
+    }
+}
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/io/stubs/OutputStreamStub.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/io/stubs/OutputStreamStub.java
new file mode 100644
index 0000000..2f64dc2
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/io/stubs/OutputStreamStub.java
@@ -0,0 +1,142 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.engine.io.stubs;
+
+import org.broadinstitute.gatk.engine.arguments.GATKArgumentCollection;
+import org.broadinstitute.gatk.engine.io.OutputTracker;
+
+import java.io.File;
+import java.io.IOException;
+import java.io.OutputStream;
+
+/**
+ * A stub for routing and management of anything backed by an OutputStream.
+ *
+ * @author mhanna
+ * @version 0.1
+ */
+public class OutputStreamStub extends OutputStream implements Stub<OutputStream> {
+    /**
+     * The file that this stub should write to.  Should be passed along to
+     * whatever happens to create storage for this stub.  Might be null, if
+     * this stub connects directly to an existing stream.
+     */
+    private final File targetFile;
+
+    /**
+     * The stream that this stub should write to.  Should be passed along to
+     * whatever happens to create storage for this stub.  Might be null, if
+     * this stub connects directly to an existing stream.
+     */
+    private final OutputStream targetStream;
+    
+    /**
+     * Connects this stub with an external stream capable of serving the
+     * requests of the consumer of this stub.
+     */
+    private OutputTracker outputTracker = null;
+
+    /**
+     * Specify that this target output stream should write to the given file.
+     * @param targetFile Target file to which to write.  Should not be null.
+     */
+    public OutputStreamStub( File targetFile ) {
+        this.targetFile = targetFile;
+        this.targetStream = null;
+    }
+
+    /**
+     * Specify that this target output stream should write to the given stream.
+     * @param targetStream Target stream to which to write.  Should not be null.
+     */
+    public OutputStreamStub( OutputStream targetStream ) {
+        this.targetFile = null;
+        this.targetStream = targetStream;
+    }
+
+
+    /**
+     * Return the target file to which this data should be written.
+     * @return Target file.  No sanity checking will have been performed by the file object.
+     */
+    public File getOutputFile() {
+        return targetFile;
+    }
+
+    /**
+     * Return the target stream to which this data should be written.
+     * @return Target stream.  No sanity checking will have been performed by the file object.
+     */
+    public OutputStream getOutputStream() {
+        return targetStream;
+    }
+
+    /**
+     * Registers the given streamConnector with this stub.
+     * @param outputTracker The connector used to provide an appropriate stream.
+     */
+    public void register( OutputTracker outputTracker ) {
+        this.outputTracker = outputTracker;
+    }
+
+    @Override
+    public void processArguments( final GATKArgumentCollection argumentCollection ) {}
+
+    /**
+     * @{inheritDoc}
+     */
+    public void flush() throws IOException {
+        outputTracker.getStorage(this).flush();
+    }
+
+    /**
+     * @{inheritDoc}
+     */
+    public void close() throws IOException {
+        outputTracker.getStorage(this).close();
+    }
+
+    /**
+     * @{inheritDoc}
+     */
+    public void write( byte[] b ) throws IOException {
+        outputTracker.getStorage(this).write(b);
+    }
+
+    /**
+     * @{inheritDoc}
+     */
+    public void write( byte[] b, int off, int len ) throws IOException {
+        outputTracker.getStorage(this).write(b, off, len);
+    }
+
+    /**
+     * @{inheritDoc}
+     */
+    public void write( int b ) throws IOException {
+        outputTracker.getStorage(this).write(b);
+    }
+}
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/io/stubs/SAMFileReaderArgumentTypeDescriptor.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/io/stubs/SAMFileReaderArgumentTypeDescriptor.java
new file mode 100644
index 0000000..42397cb
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/io/stubs/SAMFileReaderArgumentTypeDescriptor.java
@@ -0,0 +1,77 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.engine.io.stubs;
+
+import htsjdk.samtools.SAMFileReader;
+import org.broadinstitute.gatk.utils.commandline.*;
+import org.broadinstitute.gatk.engine.GenomeAnalysisEngine;
+import org.broadinstitute.gatk.utils.exceptions.UserException;
+import org.broadinstitute.gatk.utils.sam.SAMFileReaderBuilder;
+
+import java.lang.reflect.Type;
+
+/**
+ * Describe how to parse SAMFileReaders.
+ */
+public class SAMFileReaderArgumentTypeDescriptor extends ArgumentTypeDescriptor {
+    /**
+     * The engine into which output stubs should be fed.
+     */
+    private GenomeAnalysisEngine engine;
+
+    /**
+     * Create a new SAMFileReader argument, notifying the given engine when that argument has been created.
+     * @param engine engine
+     */
+    public SAMFileReaderArgumentTypeDescriptor( GenomeAnalysisEngine engine ) {
+        this.engine = engine;
+    }
+
+    @Override
+    public boolean supports( Class type ) {
+        return SAMFileReader.class.isAssignableFrom(type);
+    }
+
+    @Override
+    public Object parse( ParsingEngine parsingEngine, ArgumentSource source, Type type, ArgumentMatches matches ) {
+        SAMFileReaderBuilder builder = new SAMFileReaderBuilder();
+
+        ArgumentMatchValue readerFileName = getArgumentValue( createDefaultArgumentDefinition(source), matches );
+
+        if( readerFileName == null )
+            throw new UserException.CommandLineException("SAM file compression was supplied, but no associated writer was supplied with it.");
+
+        builder.setSAMFile(readerFileName.asFile());
+
+        // WARNING: Skipping required side-effect because stub is impossible to generate.
+        engine.addInput(source, builder);
+
+        // MASSIVE KLUDGE!  SAMFileReader is tricky to implement and we don't yet have a stub.  Return null, then
+        // let the output tracker load it in.
+        // TODO: Add a stub for SAMFileReader.
+        return null;
+    }
+}
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/io/stubs/SAMFileWriterArgumentTypeDescriptor.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/io/stubs/SAMFileWriterArgumentTypeDescriptor.java
new file mode 100644
index 0000000..c454324
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/io/stubs/SAMFileWriterArgumentTypeDescriptor.java
@@ -0,0 +1,106 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.engine.io.stubs;
+
+import htsjdk.samtools.SAMFileWriter;
+import org.broadinstitute.gatk.utils.commandline.*;
+import org.broadinstitute.gatk.engine.GenomeAnalysisEngine;
+import org.broadinstitute.gatk.engine.io.GATKSAMFileWriter;
+import org.broadinstitute.gatk.utils.exceptions.ReviewedGATKException;
+
+import java.io.OutputStream;
+import java.lang.reflect.Type;
+
+/**
+ * Insert a SAMFileWriterStub  instead of a full-fledged concrete OutputStream implementations.
+ */
+public class SAMFileWriterArgumentTypeDescriptor extends ArgumentTypeDescriptor {
+
+    /**
+     * The engine into which output stubs should be fed.
+     */
+    private final GenomeAnalysisEngine engine;
+
+    /**
+     * The default location to which data should be written if the user specifies no such location.
+     */
+    private final OutputStream defaultOutputStream;
+
+    /**
+     * Create a new SAMFileWriter argument, notifying the given engine when that argument has been created.
+     * @param engine Engine to add SAMFileWriter output to.
+     * @param defaultOutputStream the target for the data
+     */
+    public SAMFileWriterArgumentTypeDescriptor( GenomeAnalysisEngine engine, OutputStream defaultOutputStream ) {
+        this.engine = engine;
+        this.defaultOutputStream = defaultOutputStream;
+    }
+
+    @Override
+    public boolean supports( Class type ) {
+        return SAMFileWriter.class.equals(type) || GATKSAMFileWriter.class.equals(type);
+    }
+
+    @Override
+    public boolean createsTypeDefault(ArgumentSource source) {
+        return !source.isRequired() && source.defaultsToStdout();
+    }
+
+    @Override
+    public String typeDefaultDocString(ArgumentSource source) {
+        return "stdout";
+    }
+
+    @Override
+    public Object createTypeDefault(ParsingEngine parsingEngine,ArgumentSource source, Type type) {
+        if(source.isRequired() || !source.defaultsToStdout())
+            throw new ReviewedGATKException("BUG: tried to create type default for argument type descriptor that can't support a type default.");
+        SAMFileWriterStub stub = new SAMFileWriterStub(engine,defaultOutputStream);
+        engine.addOutput(stub);
+        return stub;
+    }
+
+    @Override
+    public Object parse( ParsingEngine parsingEngine, ArgumentSource source, Type type, ArgumentMatches matches )  {
+        // Extract all possible parameters that could be passed to a BAM file writer?
+        ArgumentDefinition bamArgumentDefinition = createDefaultArgumentDefinition(source);
+        ArgumentMatchValue writerFileName = getArgumentValue( bamArgumentDefinition, matches );
+
+        // Create the stub
+        SAMFileWriterStub stub = null;      // stub = new SAMFileWriterStub(engine, defaultOutputStream);
+
+        if (writerFileName != null &&  writerFileName.asFile() != null ) {
+            stub = new SAMFileWriterStub(engine, writerFileName.asFile());
+
+            // WARNING: Side effects required by engine!
+            parsingEngine.addTags(stub,getArgumentTags(matches));
+            engine.addOutput(stub);
+        }
+
+        return stub;
+    }
+
+}
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/io/stubs/SAMFileWriterStub.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/io/stubs/SAMFileWriterStub.java
new file mode 100644
index 0000000..cc814e9
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/io/stubs/SAMFileWriterStub.java
@@ -0,0 +1,336 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.engine.io.stubs;
+
+import htsjdk.samtools.SAMFileHeader;
+import htsjdk.samtools.SAMFileWriter;
+import htsjdk.samtools.SAMRecord;
+import htsjdk.samtools.util.ProgressLoggerInterface;
+import org.broadinstitute.gatk.engine.GenomeAnalysisEngine;
+import org.broadinstitute.gatk.engine.arguments.GATKArgumentCollection;
+import org.broadinstitute.gatk.engine.io.OutputTracker;
+import org.broadinstitute.gatk.engine.io.GATKSAMFileWriter;
+import org.broadinstitute.gatk.engine.iterators.ReadTransformer;
+import org.broadinstitute.gatk.utils.baq.BAQ;
+import org.broadinstitute.gatk.utils.exceptions.ReviewedGATKException;
+import org.broadinstitute.gatk.utils.exceptions.UserException;
+import org.broadinstitute.gatk.utils.sam.GATKSAMRecord;
+
+import java.io.File;
+import java.io.OutputStream;
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * A stub for routing and management of SAM file reading and writing.
+ *
+ * @author mhanna
+ * @version 0.1
+ */
+public class SAMFileWriterStub implements Stub<SAMFileWriter>, GATKSAMFileWriter {
+    /**
+     * Engine to use for collecting attributes for the output SAM file.
+     */
+    private final GenomeAnalysisEngine engine;
+
+    /**
+     * A header supplied by the user that overrides the merged header from the input BAM.
+     */
+    private SAMFileHeader headerOverride = null;
+
+    /**
+     * The sam file that this stub should write to.  Should be passed along to
+     * whatever happens to create the StreamConnector.
+     */
+    private final File samFile;
+
+    /**
+     * The target output stream, to be used in place of the SAM file.
+     */
+    private final OutputStream samOutputStream;
+
+    /**
+     * The validation stringency to apply when reading this file.
+     */
+    private Integer compressionLevel = null;
+
+    /**
+     * Should the GATK index the output BAM on-the-fly?
+     */
+    private boolean indexOnTheFly = false;
+
+    /**
+     * Should the GATK generate an md5 for the output BAM?
+     */
+    private boolean generateMD5 = false;
+
+    /**
+     * Should this BAM be presorted?
+     */
+    private boolean presorted = true;
+
+    /**
+     * How many records should the BAM writer store in RAM while
+     * sorting the BAM on-the-fly?
+     */
+    private Integer maxRecordsInRam = null;
+
+    /**
+     * Connects this stub with an external stream capable of serving the
+     * requests of the consumer of this stub.
+     */
+    private OutputTracker outputTracker = null;
+
+    /**
+     * Has the write started?  If so, throw an exception if someone tries to
+     * change write parameters to the file (compression level, presorted flag,
+     * header, etc).
+     */
+    private boolean writeStarted = false;
+
+
+    /**
+     * HMM for BAQ, if needed
+     */
+    BAQ baqHMM = new BAQ();
+
+    /**
+     * Should we simplify the BAM file while writing it out?
+     */
+    private boolean simplifyBAM = false;
+
+    private List<ReadTransformer> onOutputReadTransformers = null;
+
+    /**
+     * Create a new stub given the requested SAM file and compression level.
+     * @param engine source of header data, maybe other data about input files.
+     * @param samFile SAM file to (ultimately) create.
+     */
+    public SAMFileWriterStub( GenomeAnalysisEngine engine, File samFile ) {
+        this(engine, samFile, null);
+    }
+
+    /**
+     * Create a new stub given the requested SAM file and compression level.
+     * @param engine source of header data, maybe other data about input files.
+     * @param stream Output stream to which data should be written.
+     */
+    public SAMFileWriterStub( GenomeAnalysisEngine engine, OutputStream stream ) {
+        this(engine, null, stream);
+    }
+
+    private SAMFileWriterStub(final GenomeAnalysisEngine engine, final File samFile, final OutputStream stream) {
+        this.engine = engine;
+        this.samFile = samFile;
+        this.samOutputStream = stream;
+    }
+
+    /**
+     * Retrieves the SAM file to (ultimately) be created.
+     * @return The SAM file.  Must not be null.
+     */
+    public File getOutputFile() {
+        return samFile;
+    }
+
+    public boolean simplifyBAM() {
+        return simplifyBAM;
+    }
+
+    public void setSimplifyBAM(boolean v) {
+        simplifyBAM = v;
+    }
+
+    public OutputStream getOutputStream() {
+        return samOutputStream;
+    }
+
+    /**
+     * Retrieves the header to use when creating the new SAM file.
+     * @return header to use when creating the new SAM file.
+     */
+    public SAMFileHeader getFileHeader() {
+        return headerOverride != null ? headerOverride : engine.getSAMFileHeader();
+    }
+
+    /**
+     * Retrieves the desired compression level for 
+     * @return The current compression level.  Could be null if the user doesn't care.
+     */
+    public Integer getCompressionLevel() {
+        return compressionLevel;
+    }
+
+    /**
+     * Sets the desired compression level.
+     * @param compressionLevel The suggested compression level.
+     */
+    public void setCompressionLevel( Integer compressionLevel ) {
+        if(writeStarted)
+            throw new ReviewedGATKException("Attempted to change the compression level of a file with alignments already in it.");
+        this.compressionLevel = compressionLevel;
+    }
+
+    /**
+     * Gets whether to index this output stream on-the-fly.
+     * @return True means create an index.  False means skip index creation.
+     */
+    public Boolean getIndexOnTheFly() {
+        return indexOnTheFly;
+    }
+
+    /**
+     * Controls whether to index this output stream on-the-fly.
+     * @param indexOnTheFly True means create an index.  False means skip index creation.
+     */
+    public void setIndexOnTheFly( boolean indexOnTheFly ) {
+        if(writeStarted)
+            throw new UserException("Attempted to index a BAM on the fly of a file with alignments already in it.");
+        this.indexOnTheFly = indexOnTheFly;
+    }
+
+    /**
+     * Gets whether to generate an md5 on-the-fly for this BAM.
+     * @return True generates the md5.  False means skip writing the file.
+     */
+    public Boolean getGenerateMD5() {
+        return generateMD5;
+    }
+
+    /**
+     * Gets whether to generate an md5 on-the-fly for this BAM.
+     * @param generateMD5   True generates the md5.  False means skip writing the file.
+     */
+    public void setGenerateMD5(boolean generateMD5) {
+        if(writeStarted)
+            throw new UserException("Attempted to turn on md5 generation for BAM file with alignments already in it.");        
+        this.generateMD5 = generateMD5;
+    }
+
+    /**
+     * Whether the BAM file to create is actually presorted.
+     * @return True if the BAM file is presorted.  False otherwise.
+     */
+    public boolean isPresorted() {
+        return this.presorted;
+    }
+
+    /**
+     * Set Whether the BAM file to create is actually presorted.
+     * @param presorted True if the BAM file is presorted.  False otherwise.
+     */
+    public void setPresorted(boolean presorted) {
+        if(writeStarted)
+            throw new ReviewedGATKException("Attempted to change the presorted state of a file with alignments already in it.");
+        this.presorted = presorted;
+    }
+
+    /**
+     * Get the maximum number of reads to hold in RAM when sorting a BAM on-the-fly.
+     * @return Max records in RAM, or null if unset.
+     */
+    public Integer getMaxRecordsInRam() {
+        return this.maxRecordsInRam;
+    }
+
+    /**
+     * Sets the maximum number of reads to hold in RAM when sorting a BAM on-the-fly.
+     * @param maxRecordsInRam Max number of records in RAM.
+     */
+    public void setMaxRecordsInRam(int maxRecordsInRam) {
+        if(writeStarted)
+            throw new ReviewedGATKException("Attempted to change the max records in RAM of a file with alignments already in it.");
+        this.maxRecordsInRam = maxRecordsInRam;
+    }
+
+    /**
+     * Registers the given streamConnector with this stub.
+     * @param outputTracker The connector used to provide an appropriate stream.
+     */
+    public void register( OutputTracker outputTracker ) {
+        this.outputTracker = outputTracker;
+    }
+
+    @Override
+    public void processArguments( final GATKArgumentCollection argumentCollection ) {
+        if (argumentCollection.bamCompression != null)
+            setCompressionLevel(argumentCollection.bamCompression);
+        setGenerateMD5(argumentCollection.enableBAMmd5);
+        setIndexOnTheFly(!argumentCollection.disableBAMIndexing);
+        setSimplifyBAM(argumentCollection.simplifyBAM);
+
+    }
+
+    /**
+     * Use the given header as the target for this writer.
+     * @param header The header to write.
+     */
+    public void writeHeader(SAMFileHeader header) {
+        if(writeStarted)
+            throw new ReviewedGATKException("Attempted to change the header of a file with alignments already in it.");
+        this.headerOverride = header;
+    }
+
+    private void initializeReadTransformers() {
+        this.onOutputReadTransformers = new ArrayList<>(engine.getReadTransformers().size());
+        for ( final ReadTransformer transformer : engine.getReadTransformers() ) {
+            if ( transformer.getApplicationTime() == ReadTransformer.ApplicationTime.ON_OUTPUT )
+                onOutputReadTransformers.add(transformer);
+        }
+    }
+
+    /**
+     * @{inheritDoc}
+     */
+    public void addAlignment( final SAMRecord readIn ) {
+        if ( onOutputReadTransformers == null )
+            initializeReadTransformers();
+
+        GATKSAMRecord workingRead = (GATKSAMRecord)readIn;
+
+        // run on output read transformers
+        for ( final ReadTransformer transform : onOutputReadTransformers )
+            workingRead = transform.apply(workingRead);
+
+        writeStarted = true;
+        outputTracker.getStorage(this).addAlignment(workingRead);
+    }
+
+    /**
+     * @{inheritDoc}
+     */
+    public void close() {
+        outputTracker.getStorage(this).close();    
+    }
+
+    /**
+     * @throws java.lang.UnsupportedOperationException No progress logging in this implementation.
+     */
+    @Override
+    public void setProgressLogger(final ProgressLoggerInterface logger) {
+        throw new UnsupportedOperationException("Progress logging not supported");
+    }
+}
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/io/stubs/Stub.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/io/stubs/Stub.java
new file mode 100644
index 0000000..8a00007
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/io/stubs/Stub.java
@@ -0,0 +1,69 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.engine.io.stubs;
+
+import org.broadinstitute.gatk.engine.arguments.GATKArgumentCollection;
+import org.broadinstitute.gatk.engine.io.OutputTracker;
+
+import java.io.File;
+import java.io.OutputStream;
+
+/**
+ * A stub used for managing IO. Acts as a proxy for IO streams
+ * not yet created or streams that need significant external
+ * management.
+ *
+ * @author mhanna
+ * @version 0.1
+ */
+public interface Stub<StreamType> {
+    /**
+     * Provides a facility to register this stream with the given
+     * StreamConnector.  The stub should route each output method
+     * to the specified connector.
+     * @param outputTracker The connector used to provide an appropriate stream.
+     */
+    public void register( OutputTracker outputTracker );
+
+    /**
+     * Provides a mechanism for uniformly processing command-line arguments
+     * that are important for file processing.  For example, this method
+     * might pass on the compression value specified by the user to
+     * a SAMFileWriter
+     * @param argumentCollection The arguments to be processed
+     */
+    public void processArguments( final GATKArgumentCollection argumentCollection );
+
+    /**
+     * Returns the OutputStream represented by this stub or null if not available.
+     */
+    public OutputStream getOutputStream();
+
+    /**
+     * Returns the File represented by this stub or null if not available.
+     */
+    public File getOutputFile();
+}
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/io/stubs/VCFWriterArgumentTypeDescriptor.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/io/stubs/VCFWriterArgumentTypeDescriptor.java
new file mode 100644
index 0000000..6861339
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/io/stubs/VCFWriterArgumentTypeDescriptor.java
@@ -0,0 +1,148 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.engine.io.stubs;
+
+import htsjdk.tribble.AbstractFeatureReader;
+import org.broadinstitute.gatk.utils.commandline.*;
+import org.broadinstitute.gatk.engine.GenomeAnalysisEngine;
+import htsjdk.variant.variantcontext.writer.VariantContextWriter;
+import org.broadinstitute.gatk.utils.exceptions.ReviewedGATKException;
+
+import java.io.File;
+import java.io.OutputStream;
+import java.lang.reflect.Type;
+import java.util.Collection;
+
+/**
+ * Injects new command-line arguments into the system providing support for the genotype writer.
+ *
+ * @author mhanna
+ * @version 0.1
+ */
+public class VCFWriterArgumentTypeDescriptor extends ArgumentTypeDescriptor {
+
+    /**
+     * The engine into which output stubs should be fed.
+     */
+    private final GenomeAnalysisEngine engine;
+
+    /**
+      * The default location to which data should be written if the user specifies no such location.
+      */
+    private final OutputStream defaultOutputStream;
+
+    /**
+     * The sources into which arguments were injected.
+     */
+    private final Collection<Object> argumentSources;
+
+    /**
+     * Create a new GenotypeWriter argument, notifying the given engine when that argument has been created.
+     * @param engine the engine to be notified.
+     * @param defaultOutputStream the default output stream to be written to if nothing else is specified.
+     * @param argumentSources sources from which command-line arguments should be derived.
+     */
+    public VCFWriterArgumentTypeDescriptor(GenomeAnalysisEngine engine, OutputStream defaultOutputStream, Collection<Object> argumentSources) {
+        this.engine = engine;
+        this.defaultOutputStream = defaultOutputStream;
+        this.argumentSources = argumentSources;
+    }
+
+    /**
+     * Reports whether this ArgumentTypeDescriptor supports the given type.
+     * @param type The type to check.
+     * @return True if the argument is a GenotypeWriter.
+     */
+    @Override
+    public boolean supports( Class type ) {
+        return VariantContextWriter.class.equals(type);
+    }
+
+    /**
+     * This command-line argument descriptor does want to override the provided default value.
+     * @return true always.
+     */
+    @Override
+    public boolean createsTypeDefault(ArgumentSource source) {
+        return !source.isRequired() && source.defaultsToStdout();
+    }
+
+    @Override
+    public String typeDefaultDocString(ArgumentSource source) {
+        return "stdout";
+    }
+
+    @Override
+    public Object createTypeDefault(ParsingEngine parsingEngine, ArgumentSource source, Type type) {
+        if(source.isRequired() || !source.defaultsToStdout())
+            throw new ReviewedGATKException("BUG: tried to create type default for argument type descriptor that can't support a type default.");        
+        VariantContextWriterStub stub = new VariantContextWriterStub(engine, defaultOutputStream, argumentSources);
+        engine.addOutput(stub);
+        return stub;
+    }
+
+    /**
+     * Convert the given argument matches into a single object suitable for feeding into the ArgumentSource.
+     * @param source Source for this argument.
+     * @param type not used
+     * @param matches Matches that match with this argument.
+     * @return Transform from the matches into the associated argument.
+     */
+    @Override
+    public Object parse( ParsingEngine parsingEngine, ArgumentSource source, Type type, ArgumentMatches matches )  {
+        ArgumentDefinition defaultArgumentDefinition = createDefaultArgumentDefinition(source);
+        // Get the filename for the genotype file, if it exists.  If not, we'll need to send output to out.
+        ArgumentMatchValue writerFileName = getArgumentValue(defaultArgumentDefinition,matches);
+        File writerFile = writerFileName != null ? writerFileName.asFile() : null;
+
+        // This parser has been passed a null filename and the GATK is not responsible for creating a type default for the object;
+        // therefore, the user must have failed to specify a type default
+        if(writerFile == null && source.isRequired())
+            throw new MissingArgumentValueException(defaultArgumentDefinition);
+
+        // Create a stub for the given object.
+        final VariantContextWriterStub stub = (writerFile != null)
+                ? new VariantContextWriterStub(engine, writerFile, argumentSources)
+                : new VariantContextWriterStub(engine, defaultOutputStream, argumentSources);
+
+        stub.setCompressed(isCompressed(writerFileName == null ? null: writerFileName.asString()));
+
+        // WARNING: Side effects required by engine!
+        parsingEngine.addTags(stub,getArgumentTags(matches));
+        engine.addOutput(stub);
+
+        return stub;
+    }
+
+    /**
+     * Returns true if the file will be compressed.
+     * @param writerFileName Name of the file
+     * @return true if the file will be compressed.
+     */
+    public static boolean isCompressed(String writerFileName) {
+        return writerFileName != null && AbstractFeatureReader.hasBlockCompressedExtension(writerFileName);
+    }
+}
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/io/stubs/VariantContextWriterStub.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/io/stubs/VariantContextWriterStub.java
new file mode 100644
index 0000000..f40ede5
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/io/stubs/VariantContextWriterStub.java
@@ -0,0 +1,301 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.engine.io.stubs;
+
+import htsjdk.samtools.SAMSequenceDictionary;
+import htsjdk.tribble.index.IndexCreator;
+import org.broadinstitute.gatk.engine.GenomeAnalysisEngine;
+import org.broadinstitute.gatk.engine.arguments.GATKArgumentCollection;
+import org.broadinstitute.gatk.engine.io.OutputTracker;
+import org.broadinstitute.gatk.utils.variant.GATKVCFUtils;
+import htsjdk.variant.variantcontext.VariantContext;
+import htsjdk.variant.variantcontext.writer.Options;
+import htsjdk.variant.variantcontext.writer.VariantContextWriter;
+import htsjdk.variant.variantcontext.writer.VariantContextWriterFactory;
+import htsjdk.variant.vcf.VCFHeader;
+import htsjdk.variant.vcf.VCFHeaderLine;
+
+import java.io.File;
+import java.io.OutputStream;
+import java.io.PrintStream;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.EnumSet;
+import java.util.List;
+
+/**
+ * A stub for routing and management of genotype reading and writing.
+ *
+ * @author ebanks
+ * @version 0.1
+ */
+public class VariantContextWriterStub implements Stub<VariantContextWriter>, VariantContextWriter {
+    public final static boolean UPDATE_CONTIG_HEADERS = true;
+
+    /**
+     * The engine, central to the GATK's processing.
+     */
+    private final GenomeAnalysisEngine engine;
+
+    /**
+     * The file that this stub should write to.  Should be mutually
+     * exclusive with genotypeStream.
+     */
+    private final File genotypeFile;
+
+    /**
+     * The output stream to which stub data should be written.  Will be
+     * mutually exclusive with genotypeFile.
+     */
+    private final PrintStream genotypeStream;
+
+    /**
+     * A hack: push the argument sources into the VCF header so that the VCF header
+     * can rebuild the command-line arguments.
+     */
+    private final Collection<Object> argumentSources;
+
+    /**
+     * Which IndexCreator to use
+     */
+    private final IndexCreator indexCreator;
+
+    /**
+     * The cached VCF header (initialized to null)
+     */
+    private VCFHeader vcfHeader = null;
+
+    /**
+     * Should we emit a compressed output stream?
+     */
+    private boolean isCompressed = false;
+
+    /**
+     * Should the header be written out?  A hidden argument.
+     */
+    private boolean skipWritingCommandLineHeader = false;
+
+    /**
+     * Should we not write genotypes even when provided?
+     */
+    private boolean doNotWriteGenotypes = false;
+
+    /**
+     * Should we force BCF writing regardless of the file extension?
+     */
+    private boolean forceBCF = false;
+
+    /**
+     * Should we write all of the fields in the FORMAT field, even if missing fields could be trimmed?
+     */
+    private boolean writeFullFormatField = false;
+
+    /**
+     * Connects this stub with an external stream capable of serving the
+     * requests of the consumer of this stub.
+     */
+    protected OutputTracker outputTracker = null;
+
+    /**
+     * Create a new stub given the requested file.
+     *
+     * @param engine engine.
+     * @param genotypeFile  file to (ultimately) create.
+     * @param argumentSources sources.
+     */
+    public VariantContextWriterStub(GenomeAnalysisEngine engine, File genotypeFile, Collection<Object> argumentSources) {
+        this.engine = engine;
+        this.genotypeFile = genotypeFile;
+        this.genotypeStream = null;
+        this.indexCreator = GATKVCFUtils.getIndexCreator(engine.getArguments().variant_index_type, engine.getArguments().variant_index_parameter, genotypeFile);
+        this.argumentSources = argumentSources;
+    }
+
+    /**
+     * Create a new stub given the requested file.
+     *
+     * @param engine engine.
+     * @param genotypeStream  stream to (ultimately) write.
+     * @param argumentSources sources.
+     */
+    public VariantContextWriterStub(GenomeAnalysisEngine engine, OutputStream genotypeStream, Collection<Object> argumentSources) {
+        this.engine = engine;
+        this.genotypeFile = null;
+        this.genotypeStream = new PrintStream(genotypeStream);
+        this.indexCreator = null;
+        this.argumentSources = argumentSources;
+    }
+
+    /**
+     * Retrieves the file to (ultimately) be created.
+     * @return The file.  Can be null if genotypeStream is not.
+     */
+    public File getOutputFile() {
+        return genotypeFile;
+    }
+
+    /**
+     * Retrieves the output stream to which to (ultimately) write.
+     * @return The file.  Can be null if genotypeFile is not.
+     */
+    public OutputStream getOutputStream() {
+        return genotypeStream;
+    }
+
+    public boolean isCompressed() {
+        return isCompressed;
+    }
+
+    public void setCompressed(final boolean compressed) {
+        isCompressed = compressed;
+    }
+
+    public void setSkipWritingCommandLineHeader(final boolean skipWritingCommandLineHeader) {
+        this.skipWritingCommandLineHeader = skipWritingCommandLineHeader;
+    }
+
+    public void setDoNotWriteGenotypes(final boolean doNotWriteGenotypes) {
+        this.doNotWriteGenotypes = doNotWriteGenotypes;
+    }
+
+    public void setForceBCF(final boolean forceBCF) {
+        this.forceBCF = forceBCF;
+    }
+
+    public void setWriteFullFormatField(final boolean writeFullFormatField) {
+        this.writeFullFormatField = writeFullFormatField;
+    }
+
+    public IndexCreator getIndexCreator() {
+        return indexCreator;
+    }
+
+    /**
+     * Gets the master sequence dictionary from the engine associated with this stub
+     * @link GenomeAnalysisEngine.getMasterSequenceDictionary
+     * @return the master sequence dictionary from the engine associated with this stub
+     */
+    public SAMSequenceDictionary getMasterSequenceDictionary() {
+        return engine.getMasterSequenceDictionary();
+    }
+
+    public EnumSet<Options> getWriterOptions() {
+        return getWriterOptions(false);
+    }
+
+    public EnumSet<Options> getWriterOptions(boolean indexOnTheFly) {
+        final List<Options> options = new ArrayList<>();
+
+        if ( doNotWriteGenotypes ) options.add(Options.DO_NOT_WRITE_GENOTYPES);
+        if ( engine.lenientVCFProcessing() ) options.add(Options.ALLOW_MISSING_FIELDS_IN_HEADER);
+        if ( indexOnTheFly) options.add(Options.INDEX_ON_THE_FLY);
+        if ( writeFullFormatField ) options.add(Options.WRITE_FULL_FORMAT_FIELD);
+
+        if ( forceBCF || (getOutputFile() != null && VariantContextWriterFactory.isBCFOutput(getOutputFile())) )
+            options.add(Options.FORCE_BCF);
+
+        return options.isEmpty() ? EnumSet.noneOf(Options.class) : EnumSet.copyOf(options);
+    }
+
+    /**
+     * Retrieves the header to use when creating the new file.
+     * @return header to use when creating the new file.
+     */
+    public VCFHeader getVCFHeader() {
+        return vcfHeader;
+    }
+
+    /**
+     * Registers the given streamConnector with this stub.
+     * @param outputTracker The connector used to provide an appropriate stream.
+     */
+    public void register( OutputTracker outputTracker ) {
+        this.outputTracker = outputTracker;
+    }
+
+    @Override
+    public void processArguments( final GATKArgumentCollection argumentCollection ) {
+        setDoNotWriteGenotypes(argumentCollection.sitesOnlyVCF);
+        setSkipWritingCommandLineHeader(argumentCollection.disableCommandLineInVCF);
+        setForceBCF(argumentCollection.forceBCFOutput);
+        setWriteFullFormatField(argumentCollection.neverTrimVCFFormatField);
+    }
+
+    public void writeHeader(VCFHeader header) {
+        vcfHeader = header;
+
+        if ( header.isWriteEngineHeaders() ) {
+            // skip writing the command line header if requested
+            if ( ! skipWritingCommandLineHeader && header.isWriteCommandLine() ) {
+                // Always add the header line, as the current format allows multiple entries
+                final VCFHeaderLine commandLineArgHeaderLine = GATKVCFUtils.getCommandLineArgumentHeaderLine(engine, argumentSources);
+                vcfHeader.addMetaDataLine(commandLineArgHeaderLine);
+            }
+
+            if ( UPDATE_CONTIG_HEADERS )
+                vcfHeader = GATKVCFUtils.withUpdatedContigs(vcfHeader, engine);
+        }
+
+        outputTracker.getStorage(this).writeHeader(vcfHeader);
+    }
+
+    /**
+     * @{inheritDoc}
+     */
+    public void add(VariantContext vc) {
+        outputTracker.getStorage(this).add(vc);
+    }
+
+    /**
+     * @{inheritDoc}
+     */
+    public void close() {
+        outputTracker.getStorage(this).close();
+    }
+
+    /**
+     * Gets a string representation of this object.
+     * @return a string representation of this object.
+     */
+    @Override
+    public String toString() {
+        return getClass().getName();
+    }
+
+    /**
+     * Should we also write a BCF file alongside our VCF file for testing
+     *
+     * TODO -- remove me when argument generateShadowBCF is removed
+     *
+     * @return
+     */
+    public boolean alsoWriteBCFForTest() {
+        return engine.getArguments().numberOfDataThreads == 1 && // only works single threaded
+                ! isCompressed() && // for non-compressed outputs
+                getOutputFile() != null && // that are going to disk
+                engine.getArguments().generateShadowBCF; // and we actually want to do it
+    }
+}
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/iterators/BoundedReadIterator.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/iterators/BoundedReadIterator.java
new file mode 100644
index 0000000..cb696e5
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/iterators/BoundedReadIterator.java
@@ -0,0 +1,159 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.engine.iterators;
+
+import htsjdk.samtools.MergingSamRecordIterator;
+import htsjdk.samtools.SAMFileHeader;
+import htsjdk.samtools.SAMRecord;
+
+import java.util.Iterator;
+
+/*
+ * 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.
+ */
+
+
+/**
+ * @author aaron
+ * @version 1.0
+ * @date Apr 14, 2009
+ * <p/>
+ * Class BoundedReadIterator
+ * <p/>
+ * This class implements a read iterator that is bounded by the number of reads
+ * it will produce over the iteration.
+ */
+public class BoundedReadIterator implements GATKSAMIterator {
+
+    // the genome loc we're bounding
+    final private long readCount;
+    private long currentCount = 0;
+
+    // the iterator we want to decorate
+    private final GATKSAMIterator iterator;
+
+    // our unmapped read flag
+    private boolean doNotUseThatUnmappedReadPile = false;
+
+    /**
+     * The next read that we've buffered.  Null indicates that there's
+     * nothing in the buffer (not that there isn't a next read).
+     */
+    private SAMRecord record = null;
+
+    /**
+     * constructor
+     * @param iter
+     * @param readCount
+     */
+    public BoundedReadIterator(GATKSAMIterator iter, long readCount) {
+        this.iterator = iter;
+        this.readCount = readCount;
+    }
+
+    public void useUnmappedReads(boolean useThem) {
+        this.doNotUseThatUnmappedReadPile = useThem;
+    }
+
+    public SAMFileHeader getHeader() {
+        // todo: this is bad, we need an iterface out there for samrecords that supports getting the header,
+        // regardless of the merging
+        if (iterator instanceof MergingSamRecordIterator)
+            return ((MergingSamRecordIterator)iterator).getMergedHeader();
+        else
+            return null;
+    }
+
+    /**
+     * Do we have a next? If the iterator has a read and we're not over the read
+     * count, then yes
+     * @return
+     */
+    public boolean hasNext() {
+        if( record != null )
+            return true;
+
+        if (iterator.hasNext() && currentCount < readCount) {
+            record = iterator.next();
+            ++currentCount;
+            if (record.getAlignmentStart() == 0 && doNotUseThatUnmappedReadPile) {
+                return false;
+            }
+            return true;
+        } else {
+            return false;
+        }
+    }
+
+    /**
+     * get the next SAMRecord
+     * @return SAMRecord representing the next read
+     */
+    public SAMRecord next() {
+        SAMRecord cached = record;
+        record = null;
+        return cached;
+    }
+
+    /**
+     * this is unsupported on SAMRecord iterators
+     */
+    public void remove() {
+        throw new UnsupportedOperationException("You cannot use an iterator to remove a SAMRecord");
+    }
+
+    /**
+     * close the iterator
+     */
+    public void close() {
+        iterator.close();
+    }
+
+    public Iterator<SAMRecord> iterator() {
+        return this;
+    }
+}
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/iterators/GATKSAMIterator.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/iterators/GATKSAMIterator.java
new file mode 100644
index 0000000..8ca5cfd
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/iterators/GATKSAMIterator.java
@@ -0,0 +1,56 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.engine.iterators;
+
+import htsjdk.samtools.SAMRecord;
+import htsjdk.samtools.util.CloseableIterator;
+/**
+ *
+ * User: aaron
+ * Date: May 6, 2009
+ * Time: 5:30:41 PM
+ *
+ * The Broad Institute
+ * SOFTWARE COPYRIGHT NOTICE AGREEMENT 
+ * This software and its documentation are copyright 2009 by the
+ * Broad Institute/Massachusetts Institute of Technology. All rights are reserved.
+ *
+ * This software is supplied without any warranty or guaranteed support whatsoever. Neither
+ * the Broad Institute nor MIT can be responsible for its use, misuse, or functionality.
+ *
+ */
+
+/**
+ * @author aaron
+ * @version 1.0
+ * @date May 6, 2009
+ * <p/>
+ * Interface GATKSAMIterator
+ * <p/>
+ * This is the standard interface for all iterators in the GATK package that iterate over SAMRecords
+ */
+public interface GATKSAMIterator extends CloseableIterator<SAMRecord>, Iterable<SAMRecord> {
+}
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/iterators/GATKSAMIteratorAdapter.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/iterators/GATKSAMIteratorAdapter.java
new file mode 100644
index 0000000..0dc3e62
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/iterators/GATKSAMIteratorAdapter.java
@@ -0,0 +1,136 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.engine.iterators;
+
+import htsjdk.samtools.SAMRecord;
+import htsjdk.samtools.util.CloseableIterator;
+
+import java.util.Iterator;
+
+/**
+ *
+ * User: aaron
+ * Date: May 13, 2009
+ * Time: 6:33:15 PM
+ *
+ * The Broad Institute
+ * SOFTWARE COPYRIGHT NOTICE AGREEMENT 
+ * This software and its documentation are copyright 2009 by the
+ * Broad Institute/Massachusetts Institute of Technology. All rights are reserved.
+ *
+ * This software is supplied without any warranty or guaranteed support whatsoever. Neither
+ * the Broad Institute nor MIT can be responsible for its use, misuse, or functionality.
+ *
+ */
+
+
+/**
+ * @author aaron
+ * @version 1.0
+ * @date May 13, 2009
+ * <p/>
+ * Class GATKSAMIteratorAdapter
+ * <p/>
+ * This class adapts other SAMRecord iterators to the GATKSAMIterator
+ */
+public class GATKSAMIteratorAdapter {  
+
+    public static GATKSAMIterator adapt(Iterator<SAMRecord> iter) {
+        return new PrivateStringSAMIterator(iter);
+    }
+
+    public static GATKSAMIterator adapt(CloseableIterator<SAMRecord> iter) {
+        return new PrivateStringSAMCloseableIterator(iter);
+    }
+
+}
+
+
+/**
+ * this class wraps iterators<SAMRecord> in a GATKSAMIterator, which means just adding the
+ * methods that implement the iterable<> interface and the close() method from CloseableIterator
+ */
+class PrivateStringSAMIterator implements GATKSAMIterator {
+    private Iterator<SAMRecord> iter = null;
+
+    PrivateStringSAMIterator(Iterator<SAMRecord> iter) {
+        this.iter = iter;
+    }
+
+    public void close() {
+        // do nothing, we can't close the iterator anyway.
+    }
+
+    public boolean hasNext() {
+        return iter.hasNext();
+    }
+
+    public SAMRecord next() {
+        return iter.next();
+    }
+
+    public void remove() {
+        throw new UnsupportedOperationException("GATKSAMIterator's don't allow remove()ing");
+    }
+
+    public Iterator<SAMRecord> iterator() {
+        return iter;
+    }
+}
+
+
+/**
+ * this class wraps closeable iterators<SAMRecord> in a GATKSAMIterator, which means adding the
+ * methods that implement the iterable<> interface.
+ */
+class PrivateStringSAMCloseableIterator implements GATKSAMIterator {
+    private CloseableIterator<SAMRecord> iter = null;
+
+    PrivateStringSAMCloseableIterator(CloseableIterator<SAMRecord> iter) {
+        this.iter = iter;
+    }
+
+    public void close() {
+        iter.close();
+    }
+
+    public boolean hasNext() {
+        return iter.hasNext();
+    }
+
+    public SAMRecord next() {
+        return iter.next();
+    }
+
+    public void remove() {
+        throw new UnsupportedOperationException("GATKSAMIterator's don't allow remove()ing");
+    }
+
+    public Iterator<SAMRecord> iterator() {
+        return iter;
+    }
+}
+
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/iterators/GATKSAMRecordIterator.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/iterators/GATKSAMRecordIterator.java
new file mode 100644
index 0000000..6d02acd
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/iterators/GATKSAMRecordIterator.java
@@ -0,0 +1,57 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.engine.iterators;
+
+import htsjdk.samtools.SAMRecord;
+import htsjdk.samtools.util.CloseableIterator;
+import org.broadinstitute.gatk.utils.sam.GATKSAMRecord;
+
+import java.util.Iterator;
+
+/**
+ * Temporarily hack to convert SAMRecords to GATKSAMRecords
+ *
+ * User: depristo
+ * Date: 1/11/13
+ * Time: 1:19 PM
+ */
+public class GATKSAMRecordIterator implements CloseableIterator<GATKSAMRecord>, Iterable<GATKSAMRecord> {
+    final CloseableIterator<SAMRecord> it;
+
+    public GATKSAMRecordIterator(final CloseableIterator<SAMRecord> it) {
+        this.it = it;
+    }
+
+    public GATKSAMRecordIterator(final GATKSAMIterator it) {
+        this.it = it;
+    }
+
+    @Override public boolean hasNext() { return it.hasNext(); }
+    @Override public GATKSAMRecord next() { return (GATKSAMRecord)it.next(); }
+    @Override public void remove() { it.remove(); }
+    @Override public void close() { it.close(); }
+    @Override public Iterator<GATKSAMRecord> iterator() { return this; }
+}
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/iterators/GenomeLocusIterator.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/iterators/GenomeLocusIterator.java
new file mode 100644
index 0000000..c76a07e
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/iterators/GenomeLocusIterator.java
@@ -0,0 +1,100 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.engine.iterators;
+
+import org.broadinstitute.gatk.utils.GenomeLoc;
+import org.broadinstitute.gatk.utils.GenomeLocParser;
+
+import java.util.Iterator;
+import java.util.NoSuchElementException;
+/**
+ * User: hanna
+ * Date: May 12, 2009
+ * Time: 10:52:47 AM
+ * BROAD INSTITUTE SOFTWARE COPYRIGHT NOTICE AND AGREEMENT
+ * Software and documentation are copyright 2005 by the Broad Institute.
+ * All rights are reserved.
+ *
+ * Users acknowledge that this software is supplied without any warranty or support.
+ * The Broad Institute is not responsible for its use, misuse, or
+ * functionality.
+ */
+
+/**
+ * Iterates through all of the loci provided in the reference.
+ */
+public class GenomeLocusIterator implements Iterator<GenomeLoc> {
+    /**
+     * Builds individual loci.
+     */
+    private GenomeLocParser parser;
+
+    /**
+     * The entire region over which we're iterating.
+     */
+    private GenomeLoc completeLocus;
+
+    /**
+     * The current position in the traversal.
+     */
+    private GenomeLoc currentLocus;
+
+    /**
+     * Creates an iterator that can traverse over the entire
+     * reference specified in the given ShardDataProvider.
+     * @param completeLocus Data provider to use as a backing source.
+     *                 Provider must have a reference (hasReference() == true).
+     */
+    public GenomeLocusIterator( GenomeLocParser parser, GenomeLoc completeLocus ) {
+        this.parser = parser;
+        this.completeLocus = completeLocus;
+        this.currentLocus = parser.createGenomeLoc(completeLocus.getContig(),completeLocus.getStart());
+    }
+
+    /**
+     * Is the iterator still within the locus?
+     * @return True if the iterator has more elements.  False otherwise. 
+     */
+    public boolean hasNext() {
+        return !currentLocus.isPast(completeLocus);    
+    }
+
+    /**
+     * Get the next single-base locus context bounded by the iterator.
+     * @return GenomeLoc representing the next single-base locus context.
+     */
+    public GenomeLoc next() {
+        if( !hasNext() )
+            throw new NoSuchElementException("No elements remaining in bounded reference region.");
+        GenomeLoc toReturn = currentLocus;
+        currentLocus = parser.incPos(currentLocus);
+        return toReturn;
+    }
+
+    public void remove() {
+        throw new UnsupportedOperationException( "ReferenceLocusIterator is read-only" );
+    }
+}
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/iterators/IterableIterator.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/iterators/IterableIterator.java
new file mode 100644
index 0000000..bf8b697
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/iterators/IterableIterator.java
@@ -0,0 +1,40 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.engine.iterators;
+
+import java.util.Iterator;
+
+public class IterableIterator<T> implements Iterable<T> {
+    private Iterator<T> iter;
+
+    public IterableIterator(Iterator<T> iter) {
+        this.iter = iter;
+    }
+
+    public Iterator<T> iterator() {
+        return iter;
+    }
+}
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/iterators/MalformedBAMErrorReformatingIterator.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/iterators/MalformedBAMErrorReformatingIterator.java
new file mode 100644
index 0000000..d3a6bdc
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/iterators/MalformedBAMErrorReformatingIterator.java
@@ -0,0 +1,69 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.engine.iterators;
+
+import htsjdk.samtools.SAMRecord;
+import htsjdk.samtools.util.CloseableIterator;
+import org.broadinstitute.gatk.utils.exceptions.UserException;
+
+import java.io.File;
+import java.util.Iterator;
+
+/**
+ * Traps BAM formatting errors in underlying iterator and rethrows meaningful GATK UserExceptions
+ */
+public class MalformedBAMErrorReformatingIterator implements CloseableIterator<SAMRecord> {
+    File source;
+    CloseableIterator<SAMRecord> it;
+
+    public MalformedBAMErrorReformatingIterator(final File source, final CloseableIterator<SAMRecord> it) {
+        this.it = it;
+        this.source = source;
+    }
+
+    public boolean hasNext() {
+        try {
+            return this.it.hasNext();
+        } catch ( RuntimeException e ) { // we need to catch RuntimeExceptions here because the Picard code is throwing them (among SAMFormatExceptions) sometimes
+            throw new UserException.MalformedBAM(source, e.getMessage());
+        }
+    }
+
+    public SAMRecord next() {
+        try {
+            return it.next();
+        } catch ( RuntimeException e ) { // we need to catch RuntimeExceptions here because the Picard code is throwing them (among SAMFormatExceptions) sometimes
+            throw new UserException.MalformedBAM(source, e.getMessage());
+        }
+    }
+
+    public void remove() {
+        throw new UnsupportedOperationException("Can not remove records from a SAM file via an iterator!");
+    }
+
+    public void close() { it.close(); }
+    public Iterator<SAMRecord> iterator() { return this; }
+}
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/iterators/NullSAMIterator.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/iterators/NullSAMIterator.java
new file mode 100644
index 0000000..fa130f9
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/iterators/NullSAMIterator.java
@@ -0,0 +1,57 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.engine.iterators;
+
+import htsjdk.samtools.SAMRecord;
+
+import java.util.Iterator;
+import java.util.NoSuchElementException;
+/**
+ * User: hanna
+ * Date: May 19, 2009
+ * Time: 6:47:16 PM
+ * BROAD INSTITUTE SOFTWARE COPYRIGHT NOTICE AND AGREEMENT
+ * Software and documentation are copyright 2005 by the Broad Institute.
+ * All rights are reserved.
+ *
+ * Users acknowledge that this software is supplied without any warranty or support.
+ * The Broad Institute is not responsible for its use, misuse, or
+ * functionality.
+ */
+
+/**
+ * A placeholder for an iterator with no data.
+ */
+public class NullSAMIterator implements GATKSAMIterator {
+    public NullSAMIterator() {}
+
+    public Iterator<SAMRecord> iterator() { return this; }
+    public void close() { /* NO-OP */ }
+
+    public boolean hasNext() { return false; }
+    public SAMRecord next() { throw new NoSuchElementException("No next element is available."); }
+    public void remove() { throw new UnsupportedOperationException("Cannot remove from a GATKSAMIterator"); }
+}
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/iterators/PeekingIterator.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/iterators/PeekingIterator.java
new file mode 100644
index 0000000..f46fb0c
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/iterators/PeekingIterator.java
@@ -0,0 +1,65 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.engine.iterators;
+
+
+/*
+ * 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.
+ */
+
+/**
+ * @author aaron
+ *         <p/>
+ *         Class PeekingIterator
+ *         <p/>
+ *         a peekable interface, that requires a peek() method
+ */
+public interface PeekingIterator<T> {
+
+    /** @return returns a peeked value */
+    public T peek();
+}
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/iterators/PositionTrackingIterator.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/iterators/PositionTrackingIterator.java
new file mode 100644
index 0000000..2eba344
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/iterators/PositionTrackingIterator.java
@@ -0,0 +1,105 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.engine.iterators;
+
+import htsjdk.samtools.SAMRecord;
+import htsjdk.samtools.util.CloseableIterator;
+
+/**
+ * Iterates through a list of elements, tracking the number of elements it has seen.
+ * @author hanna
+ * @version 0.1
+ */
+public class PositionTrackingIterator implements GATKSAMIterator {
+    /**
+     * The iterator being tracked.
+     */
+    private CloseableIterator<SAMRecord> iterator;
+
+    /**
+     * Current position within the tracked iterator.
+     */
+    private long position;
+
+    /**
+     * Retrieves the current position of the iterator.  The 'current position' of the iterator is defined as
+     * the coordinate of the read that will be returned if next() is called.
+     * @return The current position of the iterator.
+     */
+    public long getPosition() {
+        return position;
+    }
+
+    /**
+     * Create a new iterator wrapping the given position, assuming that the reader is <code>position</code> reads
+     * into the sequence.
+     * @param iterator Iterator to wraps.
+     * @param position Non-negative position where the iterator currently sits.
+     */
+    public PositionTrackingIterator(CloseableIterator<SAMRecord> iterator, long position ) {
+        this.iterator = iterator;
+        this.position = position;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public boolean hasNext() {
+        return iterator.hasNext();
+    }
+
+    /**
+     * Try to get the next read in the list.  If a next read is available, increment the position.
+     * @return next read in the list, if available.
+     */
+    public SAMRecord next() {
+        try {
+            return iterator.next();
+        }
+        finally {
+            position++;
+        }
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public GATKSAMIterator iterator() {
+        return this;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public void close() {
+        iterator.close();
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public void remove() { throw new UnsupportedOperationException("Cannot remove from a GATKSAMIterator"); }
+}
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/iterators/PushbackIterator.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/iterators/PushbackIterator.java
new file mode 100644
index 0000000..0bb545b
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/iterators/PushbackIterator.java
@@ -0,0 +1,82 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.engine.iterators;
+
+import java.util.Iterator;
+
+public class PushbackIterator<T> implements Iterator<T>, Iterable<T> {
+    Iterator<T> underlyingIterator;
+    T pushedElement = null;
+
+    public PushbackIterator(final Iterator<T> underlyingIterator) {
+        this.underlyingIterator = underlyingIterator;
+    }
+
+    public boolean hasNext() {
+        return pushedElement != null || underlyingIterator.hasNext();
+    }
+
+    public Iterator<T> iterator() {
+        return this;
+    }
+
+    /**
+     * Retrieves, but does not remove, the head of this iterator.
+     * @return T the next element in the iterator
+     */
+    public T element() {
+        T x = next();
+        pushback(x);
+        return x;
+    }
+
+    /**
+     * @return the next element in the iteration.
+     */
+    public T next() {
+        if (pushedElement != null) {
+            final T ret = pushedElement;
+            pushedElement = null;
+            return ret;
+        } else {
+            return underlyingIterator.next();
+        }
+    }
+
+    public void pushback(T elt) {
+        assert(pushedElement == null);
+        
+        pushedElement = elt;
+    }
+
+    public void remove() {
+        throw new UnsupportedOperationException();
+    }
+
+    public Iterator<T> getUnderlyingIterator() {
+        return underlyingIterator;
+    }
+}
\ No newline at end of file
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/iterators/RNAReadTransformer.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/iterators/RNAReadTransformer.java
new file mode 100644
index 0000000..4cc2a82
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/iterators/RNAReadTransformer.java
@@ -0,0 +1,37 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.engine.iterators;
+
+/**
+ *
+ * A baseclass for RNAseq read transformer
+ *
+ * @author ami
+ * @since 4/28/14.
+ */
+public abstract class RNAReadTransformer extends ReadTransformer{
+    public boolean isRNAReadTransformer(){return true;}
+}
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/iterators/ReadFormattingIterator.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/iterators/ReadFormattingIterator.java
new file mode 100644
index 0000000..4922279
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/iterators/ReadFormattingIterator.java
@@ -0,0 +1,140 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.engine.iterators;
+
+import htsjdk.samtools.SAMRecord;
+import org.apache.log4j.Logger;
+import org.broadinstitute.gatk.utils.sam.AlignmentUtils;
+
+/**
+ * An iterator which does post-processing of a read, including potentially wrapping
+ * the read in something with a compatible interface or replacing the read entirely.
+ *
+ * @author mhanna
+ * @version 0.1
+ */
+public class ReadFormattingIterator implements GATKSAMIterator {
+    /**
+     * Logger.
+     */
+    final protected static Logger logger = Logger.getLogger(ReadFormattingIterator.class);    
+
+    /**
+     * Iterator to which to pass
+     */
+    private GATKSAMIterator wrappedIterator;
+
+    /**
+     * True if original base qualities should be used.
+     */
+    private final boolean useOriginalBaseQualities;
+
+    /**
+      * Positive if there is a default Base Quality value to fill in the reads with.
+      */
+     private final byte defaultBaseQualities;
+
+
+    /**
+     * Decorate the given iterator inside a ReadWrappingIterator.
+     * @param wrappedIterator iterator
+     * @param useOriginalBaseQualities true if original base qualities should be used
+     * @param defaultBaseQualities if the reads have incomplete quality scores, set them all to defaultBaseQuality.  
+     */
+    public ReadFormattingIterator(GATKSAMIterator wrappedIterator, boolean useOriginalBaseQualities, byte defaultBaseQualities) {
+        this.wrappedIterator = wrappedIterator;
+        this.useOriginalBaseQualities = useOriginalBaseQualities;
+        this.defaultBaseQualities = defaultBaseQualities;
+
+    }
+
+    /**
+     * Convenience function for use in foreach loops.  Dangerous because it does not actually
+     * reset the iterator.
+     * @return An iterator through the current data stream.
+     */
+    public GATKSAMIterator iterator() {
+        // NOTE: this iterator doesn't perform any kind of reset operation; it just returns itself.
+        //       can we do something better?  Do we really have to provide support for the Iterable interface?
+        return this;
+    }
+
+    /**
+     * Close this iterator.
+     */
+    public void close() {
+        wrappedIterator.close();
+    }
+
+    /**
+     * Does the iterator contain more values?
+     * @return True if there are more left to return, false otherwise.
+     */
+    public boolean hasNext() {
+        return wrappedIterator.hasNext();
+    }
+
+    /**
+     * Get the next value in the sequence.
+     * @return Next value in the sequence.  By convention, a NoSuchElementException should be thrown if
+     *         no next exists.
+     */
+    public SAMRecord next() {
+        SAMRecord rec = wrappedIterator.next();
+
+        // Always consolidate the cigar string into canonical form, collapsing zero-length / repeated cigar elements.
+        // Downstream code (like LocusIteratorByState) cannot necessarily handle non-consolidated cigar strings.
+        rec.setCigar(AlignmentUtils.consolidateCigar(rec.getCigar()));
+
+        // if we are using default quals, check if we need them, and add if necessary.
+        // 1. we need if reads are lacking or have incomplete quality scores
+        // 2. we add if defaultBaseQualities has a positive value
+        if (defaultBaseQualities >= 0) {
+            byte reads [] = rec.getReadBases();
+            byte quals [] = rec.getBaseQualities();
+            if (quals == null || quals.length < reads.length) {
+                byte new_quals [] = new byte [reads.length];
+                for (int i=0; i<reads.length; i++)
+                    new_quals[i] = defaultBaseQualities;
+                rec.setBaseQualities(new_quals);
+            }
+        }
+
+        // if we are using original quals, set them now if they are present in the record
+        if ( useOriginalBaseQualities ) {
+            byte[] originalQuals = rec.getOriginalBaseQualities();
+            if ( originalQuals != null )
+                rec.setBaseQualities(originalQuals);
+        }
+
+        return rec;
+    }
+
+    /**
+     * Remove the current element from the list.  Unsupported in this wrapper.
+     */
+    public void remove() { throw new UnsupportedOperationException("Cannot remove from a ReadWrappingIterator"); }
+}
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/iterators/ReadTransformer.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/iterators/ReadTransformer.java
new file mode 100644
index 0000000..b7db505
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/iterators/ReadTransformer.java
@@ -0,0 +1,205 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.engine.iterators;
+
+import com.google.java.contract.Ensures;
+import com.google.java.contract.Requires;
+import org.broadinstitute.gatk.engine.GenomeAnalysisEngine;
+import org.broadinstitute.gatk.engine.walkers.Walker;
+import org.broadinstitute.gatk.utils.sam.GATKSAMRecord;
+
+import java.util.Comparator;
+
+/**
+ * Baseclass used to describe a read transformer like BAQ and BQSR
+ *
+ * Read transformers are plugable infrastructure that modify read state
+ * either on input, on output, or within walkers themselves.
+ *
+ * The function apply() is called on each read seen by the GATK (after passing
+ * all ReadFilters) and it can do as it sees fit (without modifying the alignment)
+ * to the read to change qualities, add tags, etc.
+ *
+ * Initialize is called once right before the GATK traversal begins providing
+ * the ReadTransformer with the ability to collect and initialize data from the
+ * engine.
+ *
+ * Note that all ReadTransformers within the classpath are created and initialized.  If one
+ * shouldn't be run it should look at the command line options of the engine and override
+ * the enabled.
+ *
+ * @since 8/31/12
+ * @author depristo
+ */
+abstract public class ReadTransformer {
+    /**
+     * When should this read transform be applied?
+     */
+    private ApplicationTime applicationTime;
+
+    /**
+     * Keep track of whether we've been initialized already, and ensure it's not called more than once.
+     */
+    private boolean initialized = false;
+
+    protected ReadTransformer() {}
+
+    /*
+     * @return the ordering constraint for the given read transformer
+     */
+    public OrderingConstraint getOrderingConstraint() { return OrderingConstraint.DO_NOT_CARE; }
+
+    /**
+     * Master initialization routine.  Called to setup a ReadTransform, using it's overloaded initializeSub routine.
+     *
+     * @param overrideTime if not null, we will run this ReadTransform at the time provided, regardless of the timing of this read transformer itself
+     * @param engine the engine, for initializing values
+     * @param walker the walker we intend to run
+     */
+    @Requires({"initialized == false", "engine != null", "walker != null"})
+    @Ensures("initialized == true")
+    public final void initialize(final ApplicationTime overrideTime, final GenomeAnalysisEngine engine, final Walker walker) {
+        if ( engine == null ) throw new IllegalArgumentException("engine cannot be null");
+        if ( walker == null ) throw new IllegalArgumentException("walker cannot be null");
+
+        this.applicationTime = initializeSub(engine, walker);
+        if ( overrideTime != null ) this.applicationTime = overrideTime;
+        initialized = true;
+    }
+
+    /**
+     * Subclasses must override this to initialize themselves
+     *
+     * @param engine the engine, for initializing values
+     * @param walker the walker we intend to run
+     * @return the point of time we'd like this read transform to be run
+     */
+    @Requires({"engine != null", "walker != null"})
+    @Ensures("result != null")
+    protected abstract ApplicationTime initializeSub(final GenomeAnalysisEngine engine, final Walker walker);
+
+    /**
+     * Should this ReadTransformer be activated?  Called after initialize, which allows this
+     * read transformer to look at its arguments and decide if it should be active.  All
+     * ReadTransformers must override this, as by default they are not enabled.
+     *
+     * @return true if this ReadTransformer should be used on the read stream
+     */
+    public boolean enabled() {
+        return false;
+    }
+
+    /**
+     * Has this transformer been initialized?
+     *
+     * @return true if it has
+     */
+    public final boolean isInitialized() {
+        return initialized;
+    }
+
+    /**
+     * When should we apply this read transformer?
+     *
+     * @return true if yes
+     */
+    public final ApplicationTime getApplicationTime() {
+        return applicationTime;
+    }
+
+    /**
+     * Primary interface function for a read transform to actually do some work
+     *
+     * The function apply() is called on each read seen by the GATK (after passing
+     * all ReadFilters) and it can do as it sees fit (without modifying the alignment)
+     * to the read to change qualities, add tags, etc.
+     *
+     * @param read the read to transform
+     * @return the transformed read
+     */
+    @Requires("read != null")
+    @Ensures("result != null")
+    abstract public GATKSAMRecord apply(final GATKSAMRecord read);
+
+    @Override
+    public String toString() {
+        return getClass().getSimpleName();
+    }
+
+    /**
+     * When should a read transformer be applied?
+     */
+    public static enum ApplicationTime {
+        /**
+         * Walker does not tolerate this read transformer
+         */
+        FORBIDDEN,
+
+        /**
+         * apply the transformation to the incoming reads, the default
+         */
+        ON_INPUT,
+
+        /**
+         * apply the transformation to the outgoing read stream
+         */
+        ON_OUTPUT,
+
+        /**
+         * the walker will deal with the calculation itself
+         */
+        HANDLED_IN_WALKER
+    }
+
+    /*
+     * This enum specifies the constraints that the given read transformer has relative to any other read transformers being used
+     */
+    public enum OrderingConstraint {
+        /*
+         * If 2 read transformers are both active and MUST_BE_FIRST, then an error will be generated
+         */
+        MUST_BE_FIRST,
+
+        /*
+         * No constraints on the ordering for this read transformer
+         */
+        DO_NOT_CARE,
+
+        /*
+         * If 2 read transformers are both active and MUST_BE_LAST, then an error will be generated
+         */
+        MUST_BE_LAST
+    }
+
+    public static class ReadTransformerComparator implements Comparator<ReadTransformer> {
+
+        public int compare(final ReadTransformer r1, final ReadTransformer r2) {
+            if ( r1.getOrderingConstraint() == r2.getOrderingConstraint() )
+                return 0;
+            return ( r1.getOrderingConstraint() == OrderingConstraint.MUST_BE_FIRST || r2.getOrderingConstraint() == OrderingConstraint.MUST_BE_LAST ) ? -1 : 1;
+        }
+    }
+}
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/iterators/ReadTransformersMode.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/iterators/ReadTransformersMode.java
new file mode 100644
index 0000000..3fa18c4
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/iterators/ReadTransformersMode.java
@@ -0,0 +1,53 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.engine.iterators;
+
+import java.lang.annotation.*;
+
+/**
+ * User: hanna
+ * Date: May 14, 2009
+ * Time: 1:51:22 PM
+ * BROAD INSTITUTE SOFTWARE COPYRIGHT NOTICE AND AGREEMENT
+ * Software and documentation are copyright 2005 by the Broad Institute.
+ * All rights are reserved.
+ *
+ * Users acknowledge that this software is supplied without any warranty or support.
+ * The Broad Institute is not responsible for its use, misuse, or
+ * functionality.
+ */
+
+/**
+ * Allows the walker to indicate what type of data it wants to consume.
+ */
+
+ at Documented
+ at Inherited
+ at Retention(RetentionPolicy.RUNTIME)
+ at Target(ElementType.TYPE)
+public @interface ReadTransformersMode {
+    public abstract ReadTransformer.ApplicationTime ApplicationTime() default ReadTransformer.ApplicationTime.ON_INPUT;
+}
\ No newline at end of file
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/iterators/VerifyingSamIterator.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/iterators/VerifyingSamIterator.java
new file mode 100644
index 0000000..a34d4de
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/iterators/VerifyingSamIterator.java
@@ -0,0 +1,90 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.engine.iterators;
+
+import htsjdk.samtools.SAMRecord;
+import org.broadinstitute.gatk.utils.GenomeLocParser;
+import org.broadinstitute.gatk.utils.exceptions.UserException;
+
+import java.util.Iterator;
+
+/**
+ * Verifies that the incoming stream of reads is correctly sorted
+ */
+public class VerifyingSamIterator implements GATKSAMIterator {
+    GATKSAMIterator it;
+    SAMRecord last = null;
+    boolean checkOrderP = true;
+
+    public VerifyingSamIterator(GATKSAMIterator it) {
+        this.it = it;
+    }
+
+    public boolean hasNext() { return this.it.hasNext(); }
+    public SAMRecord next() {
+
+        SAMRecord cur = it.next();
+        if ( last != null )
+            verifyRecord(last, cur);
+        if ( ! cur.getReadUnmappedFlag() )
+            last = cur;
+        return cur;
+    }
+
+    private void verifyRecord( final SAMRecord last, final SAMRecord cur ) {
+        if ( checkOrderP && isOutOfOrder(last, cur) ) {
+            this.last = null;
+            throw new UserException.MissortedBAM(String.format("reads are out of order:%nlast:%n%s%ncurrent:%n%s%n", last.format(), cur.format()) );
+        }
+    }
+
+    private boolean isOutOfOrder( final SAMRecord last, final SAMRecord cur ) {
+        if ( last == null || cur.getReadUnmappedFlag() )
+            return false;
+        else {
+            if(last.getReferenceIndex() == SAMRecord.NO_ALIGNMENT_REFERENCE_INDEX || last.getAlignmentStart() == SAMRecord.NO_ALIGNMENT_START)
+                throw new UserException.MalformedBAM(last,String.format("read %s has inconsistent mapping information.",last.format()));
+            if(cur.getReferenceIndex() == SAMRecord.NO_ALIGNMENT_REFERENCE_INDEX || cur.getAlignmentStart() == SAMRecord.NO_ALIGNMENT_START)
+                throw new UserException.MalformedBAM(last,String.format("read %s has inconsistent mapping information.",cur.format()));
+
+            return (last.getReferenceIndex() > cur.getReferenceIndex()) ||
+                    (last.getReferenceIndex().equals(cur.getReferenceIndex()) &&
+                            last.getAlignmentStart() > cur.getAlignmentStart());
+        }
+    }
+
+    public void remove() {
+        throw new UnsupportedOperationException("Can not remove records from a SAM file via an iterator!");
+    }
+
+    public void close() {
+        it.close();
+    }
+
+    public Iterator<SAMRecord> iterator() {
+        return this;
+    }
+}
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/iterators/package-info.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/iterators/package-info.java
new file mode 100644
index 0000000..3387890
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/iterators/package-info.java
@@ -0,0 +1,26 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.engine.iterators;
\ No newline at end of file
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/phonehome/GATKRunReport.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/phonehome/GATKRunReport.java
new file mode 100644
index 0000000..f8126b9
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/phonehome/GATKRunReport.java
@@ -0,0 +1,786 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.engine.phonehome;
+
+import com.google.java.contract.Ensures;
+import com.google.java.contract.Requires;
+import org.apache.log4j.Level;
+import org.apache.log4j.Logger;
+import org.broadinstitute.gatk.engine.CommandLineGATK;
+import org.broadinstitute.gatk.engine.GenomeAnalysisEngine;
+import org.broadinstitute.gatk.engine.walkers.Walker;
+import org.broadinstitute.gatk.utils.Utils;
+import org.broadinstitute.gatk.utils.crypt.CryptUtils;
+import org.broadinstitute.gatk.utils.exceptions.ReviewedGATKException;
+import org.broadinstitute.gatk.utils.io.IOUtils;
+import org.broadinstitute.gatk.utils.io.Resource;
+import org.broadinstitute.gatk.utils.threading.ThreadEfficiencyMonitor;
+import org.jets3t.service.S3Service;
+import org.jets3t.service.S3ServiceException;
+import org.jets3t.service.impl.rest.httpclient.RestS3Service;
+import org.jets3t.service.model.S3Object;
+import org.jets3t.service.security.AWSCredentials;
+import org.simpleframework.xml.Element;
+import org.simpleframework.xml.Serializer;
+import org.simpleframework.xml.core.Persister;
+
+import java.io.*;
+import java.security.NoSuchAlgorithmException;
+import java.security.PublicKey;
+import java.text.DateFormat;
+import java.text.SimpleDateFormat;
+import java.util.Arrays;
+import java.util.Date;
+import java.util.concurrent.atomic.AtomicBoolean;
+import java.util.zip.GZIPInputStream;
+import java.util.zip.GZIPOutputStream;
+
+
+/**
+ * A detailed description of a GATK run, and error if applicable.  Simply create a GATKRunReport
+ * with the constructor, providing the walker that was run and the fully instantiated GenomeAnalysisEngine
+ * <b>after the run finishes</b> and the GATKRunReport will collect all of the report information
+ * into this object.  Call postReport to write out the report, as an XML document, to either STDOUT,
+ * a file (in which case the output is gzipped), or with no arguments the report will be posted to the
+ * GATK run report database.
+ *
+ * @author depristo
+ * @since 2010
+ */
+public class GATKRunReport {
+    protected static final String REPORT_BUCKET_NAME = "broad.gsa.gatk.run.reports";
+    protected static final String TEST_REPORT_BUCKET_NAME = "broad.gsa.gatk.run.reports.test";
+    protected final static String AWS_ACCESS_KEY_MD5 = "34d4a26eb2062b3f06e833b28f9a38c6";
+    protected final static String AWS_SECRET_KEY_MD5 = "83f2332eec99ef1d7425d5dc5d4b514a";
+
+    private static final DateFormat DATE_FORMAT = new SimpleDateFormat("yyyy/MM/dd HH.mm.ss");
+
+    /**
+     * our log
+     */
+    protected static final Logger logger = Logger.getLogger(GATKRunReport.class);
+
+    /**
+     * Default value for the number of milliseconds before an S3 put operation is timed-out.
+     * Can be overridden via a constructor argument.
+     */
+    private static final long S3_DEFAULT_PUT_TIME_OUT_IN_MILLISECONDS = 30 * 1000;
+
+    /**
+     * Number of milliseconds before an S3 put operation is timed-out.
+     */
+    private long s3PutTimeOutInMilliseconds = S3_DEFAULT_PUT_TIME_OUT_IN_MILLISECONDS;
+
+    // -----------------------------------------------------------------
+    // elements captured for the report
+    // -----------------------------------------------------------------
+
+    @Element(required = false, name = "id")
+    private String id;
+
+    @Element(required = false, name = "exception")
+    private GATKRunReportException mException;
+
+    @Element(required = true, name = "start-time")
+    private String startTime = "ND";
+
+    @Element(required = true, name = "end-time")
+    private String endTime;
+
+    @Element(required = true, name = "run-time")
+    private long runTime = 0;
+
+    @Element(required = true, name = "walker-name")
+    private String walkerName;
+
+    @Element(required = true, name = "svn-version")
+    private String svnVersion;
+
+    @Element(required = true, name = "total-memory")
+    private long totalMemory;
+
+    @Element(required = true, name = "max-memory")
+    private long maxMemory;
+
+    @Element(required = true, name = "user-name")
+    private String userName;
+
+    @Element(required = true, name = "host-name")
+    private String hostName;
+
+    @Element(required = true, name = "java")
+    private String javaVersion;
+
+    @Element(required = true, name = "machine")
+    private String machine;
+
+    @Element(required = true, name = "iterations")
+    private long nIterations;
+
+    @Element(required = true, name = "tag")
+    private String tag;
+
+    @Element(required = true, name = "num-threads")
+    private int numThreads;
+    @Element(required = true, name = "percent-time-running")
+    private String percentTimeRunning;
+    @Element(required = true, name = "percent-time-waiting")
+    private String percentTimeWaiting;
+    @Element(required = true, name = "percent-time-blocking")
+    private String percentTimeBlocking;
+    @Element(required = true, name = "percent-time-waiting-for-io")
+    private String percentTimeWaitingForIO;
+
+    /** The error message, if one occurred, or null if none did */
+    public String errorMessage = null;
+    /** The error that occurred, if one did, or null if none did */
+    public Throwable errorThrown = null;
+
+    /**
+     * How should the GATK report its usage?
+     */
+    public enum PhoneHomeOption {
+        /** Disable phone home */
+        NO_ET,
+        /** Forces the report to go to S3 */
+        AWS,
+        /** Force output to STDOUT.  For debugging only */
+        STDOUT
+    }
+
+    /**
+     * To allow us to deserial reports from XML
+     */
+    private GATKRunReport() { }
+
+    /**
+     * Read a GATKRunReport from the serialized XML representation in String reportAsXML
+     * @param stream an input stream containing a serialized XML report
+     * @return a reconstituted GATKRunReport from reportAsXML
+     * @throws Exception if parsing fails for any reason
+     */
+    @Ensures("result != null")
+    protected static GATKRunReport deserializeReport(final InputStream stream) throws Exception {
+        final Serializer serializer = new Persister();
+        return serializer.read(GATKRunReport.class, stream);
+    }
+
+    /**
+     * Create a new GATKRunReport from a report on S3
+     *
+     * Assumes that s3Object has already been written to S3, and this function merely
+     * fetches it from S3 and deserializes it.  The access keys must have permission to
+     * GetObject from S3.
+     *
+     * @param downloaderAccessKey AWS access key with permission to GetObject from bucketName
+     * @param downloaderSecretKey AWS secret key with permission to GetObject from bucketName
+     * @param bucketName the name of the bucket holding the report
+     * @param s3Object the s3Object we wrote to S3 in bucketName that we want to get back and decode
+     * @return a deserialized report derived from s3://bucketName/s3Object.getName()
+     * @throws Exception
+     */
+    @Ensures("result != null")
+    protected static GATKRunReport deserializeReport(final String downloaderAccessKey,
+                                                     final String downloaderSecretKey,
+                                                     final String bucketName,
+                                                     final S3Object s3Object) throws Exception {
+        final S3Service s3Service = initializeAWSService(downloaderAccessKey, downloaderSecretKey);
+
+        // Retrieve the whole data object we created previously
+        final S3Object objectComplete = s3Service.getObject(bucketName, s3Object.getName());
+
+        // Read the data from the object's DataInputStream using a loop, and print it out.
+        return deserializeReport(new GZIPInputStream(objectComplete.getDataInputStream()));
+    }
+
+    /**
+     * Create a new RunReport and population all of the fields with values from the walker and engine.
+     * Allows the S3 put timeout to be explicitly set.
+     *
+     * @param walker the GATK walker that we ran
+     * @param e the exception caused by running this walker, or null if we completed successfully
+     * @param engine the GAE we used to run the walker, so we can fetch runtime, args, etc
+     * @param type the GATK phone home setting
+     * @param s3PutTimeOutInMilliseconds number of milliseconds to wait before timing out an S3 put operation
+     */
+    public GATKRunReport(final Walker<?,?> walker, final Exception e, final GenomeAnalysisEngine engine, final PhoneHomeOption type,
+                         final long s3PutTimeOutInMilliseconds) {
+        this(walker, e, engine, type);
+        this.s3PutTimeOutInMilliseconds = s3PutTimeOutInMilliseconds;
+    }
+
+    /**
+     * Create a new RunReport and population all of the fields with values from the walker and engine.
+     * Leaves the S3 put timeout set to the default value of S3_DEFAULT_PUT_TIME_OUT_IN_MILLISECONDS.
+     *
+     * @param walker the GATK walker that we ran
+     * @param e the exception caused by running this walker, or null if we completed successfully
+     * @param engine the GAE we used to run the walker, so we can fetch runtime, args, etc
+     * @param type the GATK phone home setting
+     */
+    public GATKRunReport(final Walker<?,?> walker, final Exception e, final GenomeAnalysisEngine engine, final PhoneHomeOption type) {
+        if ( type == PhoneHomeOption.NO_ET )
+            throw new ReviewedGATKException("Trying to create a run report when type is NO_ET!");
+
+        logger.debug("Aggregating data for run report");
+
+        // what did we run?
+        id = org.apache.commons.lang.RandomStringUtils.randomAlphanumeric(32);
+        walkerName = engine.getWalkerName(walker.getClass());
+        svnVersion = CommandLineGATK.getVersionNumber();
+
+        // runtime performance metrics
+        Date end = new java.util.Date();
+        endTime = DATE_FORMAT.format(end);
+        if ( engine.getStartTime() != null ) { // made it this far during initialization
+            startTime = DATE_FORMAT.format(engine.getStartTime());
+            runTime = (end.getTime() - engine.getStartTime().getTime()) / 1000L; // difference in seconds
+        }
+
+        // deal with memory usage
+        Runtime.getRuntime().gc(); // call GC so totalMemory is ~ used memory
+        maxMemory = Runtime.getRuntime().maxMemory();
+        totalMemory = Runtime.getRuntime().totalMemory();
+
+        // we can only do some operations if an error hasn't occurred
+        if ( engine.getCumulativeMetrics() != null ) {
+            // it's possible we aborted so early that these data structures arent initialized
+            nIterations = engine.getCumulativeMetrics().getNumIterations();
+        }
+
+        tag = engine.getArguments().tag;
+
+        // user and hostname -- information about the runner of the GATK
+        userName = System.getProperty("user.name");
+        hostName = Utils.resolveHostname();
+
+        // basic java information
+        javaVersion = Utils.join("-", Arrays.asList(System.getProperty("java.vendor"), System.getProperty("java.version")));
+        machine = Utils.join("-", Arrays.asList(System.getProperty("os.name"), System.getProperty("os.arch")));
+
+        // if there was an exception, capture it
+        this.mException = e == null ? null : new GATKRunReportException(e);
+
+        numThreads = engine.getTotalNumberOfThreads();
+        percentTimeRunning = getThreadEfficiencyPercent(engine, ThreadEfficiencyMonitor.State.USER_CPU);
+        percentTimeBlocking = getThreadEfficiencyPercent(engine, ThreadEfficiencyMonitor.State.BLOCKING);
+        percentTimeWaiting = getThreadEfficiencyPercent(engine, ThreadEfficiencyMonitor.State.WAITING);
+        percentTimeWaitingForIO = getThreadEfficiencyPercent(engine, ThreadEfficiencyMonitor.State.WAITING_FOR_IO);
+    }
+
+    /**
+     * Get the random alpha-numeric ID of this GATKRunReport
+     * @return a non-null string ID
+     */
+    @Ensures("result != null")
+    public String getID() {
+        return id;
+    }
+
+    /**
+     * Return a string representing the percent of time the GATK spent in state, if possible.  Otherwise return NA
+     *
+     * @param engine the GATK engine whose threading efficiency info we will use
+     * @param state the state whose occupancy we wish to know
+     * @return a string representation of the percent occupancy of state, or NA is not possible
+     */
+    @Requires({"engine != null", "state != null"})
+    @Ensures("result != null")
+    private String getThreadEfficiencyPercent(final GenomeAnalysisEngine engine, final ThreadEfficiencyMonitor.State state) {
+        final ThreadEfficiencyMonitor tem = engine.getThreadEfficiencyMonitor();
+        return tem == null ? "NA" : String.format("%.2f", tem.getStatePercent(state));
+    }
+
+    /**
+     * Get a filename (no path) appropriate for this report
+     *
+     * @return a non-null string filename
+     */
+    @Ensures("result != null")
+    protected String getReportFileName() {
+        return getID() + ".report.xml.gz";
+    }
+
+    // ---------------------------------------------------------------------------
+    //
+    // Main public interface method for posting reports
+    //
+    // ---------------------------------------------------------------------------
+
+    /**
+     * Post this GATK report to the destination implied by the PhoneHomeOption type
+     *
+     * Guaranteed to never throw an exception (exception noted below) and to return
+     * with a reasonable (~10 seconds) time regardless of successful writing of the report.
+     *
+     * @throws IllegalArgumentException if type == null
+     * @param type the type of phoning home we want to do
+     * @return true if a report was successfully written, false otherwise
+     */
+    public boolean postReport(final PhoneHomeOption type) {
+        if ( type == null ) throw new IllegalArgumentException("type cannot be null");
+
+        logger.debug("Posting report of type " + type);
+        switch (type) {
+            case NO_ET: // don't do anything
+                return false;
+            case AWS:
+                wentToAWS = true;
+                return postReportToAWSS3() != null;
+            case STDOUT:
+                return postReportToStream(System.out);
+            default:
+                exceptDuringRunReport("BUG: unexpected PhoneHomeOption ");
+                return false;
+        }
+    }
+
+    // ---------------------------------------------------------------------------
+    //
+    // Code for sending reports to local files
+    //
+    // ---------------------------------------------------------------------------
+
+    /**
+     * Write an XML representation of this report to the stream, throwing a GATKException if the marshalling
+     * fails for any reason.
+     *
+     * @param stream an output stream to write the report to
+     */
+    @Requires("stream != null")
+    protected boolean postReportToStream(final OutputStream stream) {
+        final Serializer serializer = new Persister();
+        try {
+            serializer.write(this, stream);
+            return true;
+        } catch (Exception e) {
+            return false;
+        }
+    }
+
+    // ---------------------------------------------------------------------------
+    //
+    // Code for sending reports to s3
+    //
+    // ---------------------------------------------------------------------------
+
+    /**
+     * Get the name of the S3 bucket where we should upload this report
+     *
+     * @return the string name of the s3 bucket
+     */
+    @Ensures("result != null")
+    protected String getS3ReportBucket() {
+        return s3ReportBucket;
+    }
+
+    /**
+     * Decrypts encrypted AWS key from encryptedKeySource
+     * @param encryptedKeySource a file containing an encrypted AWS key
+     * @return a decrypted AWS key as a String
+     */
+    @Ensures("result != null")
+    public static String decryptAWSKey(final File encryptedKeySource) throws FileNotFoundException {
+        if ( encryptedKeySource == null ) throw new IllegalArgumentException("encryptedKeySource cannot be null");
+        return decryptAWSKey(new FileInputStream(encryptedKeySource));
+    }
+
+    /**
+     * @see #decryptAWSKey(java.io.File) but with input from an inputstream
+     */
+    @Requires("encryptedKeySource != null")
+    @Ensures("result != null")
+    private static String decryptAWSKey(final InputStream encryptedKeySource) {
+        final PublicKey key = CryptUtils.loadGATKDistributedPublicKey();
+        final byte[] fromDisk = IOUtils.readStreamIntoByteArray(encryptedKeySource);
+        final byte[] decrypted = CryptUtils.decryptData(fromDisk, key);
+        return new String(decrypted);
+    }
+
+    /**
+     * Get the decrypted AWS key sorted in the resource directories of name
+     * @param name the name of the file containing the needed AWS key
+     * @return a non-null GATK
+     */
+    @Requires("name != null")
+    @Ensures("result != null")
+    private static String getAWSKey(final String name) {
+        final Resource resource = new Resource(name, GATKRunReport.class);
+        return decryptAWSKey(resource.getResourceContentsAsStream());
+    }
+
+    /**
+     * Get the AWS access key for the GATK user
+     * @return a non-null AWS access key for the GATK user
+     */
+    @Ensures("result != null")
+    protected static String getAWSUploadAccessKey() {
+        return getAWSKey("resources/GATK_AWS_access.key");
+    }
+
+    /**
+     * Get the AWS secret key for the GATK user
+     * @return a non-null AWS secret key for the GATK user
+     */
+    @Ensures("result != null")
+    protected static String getAWSUploadSecretKey() {
+        return getAWSKey("resources/GATK_AWS_secret.key");
+    }
+
+    /**
+     * Check that the AWS keys can be decrypted and are what we expect them to be
+     *
+     * @throws ReviewedGATKException if anything goes wrong
+     */
+    public static void checkAWSAreValid() {
+        try {
+            final String accessKeyMD5 = Utils.calcMD5(getAWSUploadAccessKey());
+            final String secretKeyMD5 = Utils.calcMD5(getAWSUploadSecretKey());
+
+            if ( ! AWS_ACCESS_KEY_MD5.equals(accessKeyMD5) ) {
+                throw new ReviewedGATKException("Invalid AWS access key found, expected MD5 " + AWS_ACCESS_KEY_MD5 + " but got " + accessKeyMD5);
+            }
+            if ( ! AWS_SECRET_KEY_MD5.equals(secretKeyMD5) ) {
+                throw new ReviewedGATKException("Invalid AWS secret key found, expected MD5 " + AWS_SECRET_KEY_MD5 + " but got " + secretKeyMD5);
+            }
+
+        } catch ( Exception e ) {
+            throw new ReviewedGATKException("Couldn't decrypt AWS keys, something is wrong with the GATK distribution");
+        }
+    }
+
+    /**
+     * Get an initialized S3Service for use in communicating with AWS/s3
+     *
+     * @param awsAccessKey our AWS access key to use
+     * @param awsSecretKey our AWS secret key to use
+     * @return an initialized S3Service object that can be immediately used to interact with S3
+     * @throws S3ServiceException
+     */
+    @Requires({"awsAccessKey != null", "awsSecretKey != null"})
+    @Ensures("result != null")
+    protected static S3Service initializeAWSService(final String awsAccessKey, final String awsSecretKey) throws S3ServiceException {
+        // To communicate with S3, create a class that implements an S3Service. We will use the REST/HTTP
+        // implementation based on HttpClient, as this is the most robust implementation provided with JetS3t.
+        final AWSCredentials awsCredentials = new AWSCredentials(awsAccessKey, awsSecretKey);
+        return new RestS3Service(awsCredentials);
+    }
+
+    /**
+     * A runnable that pushes this GATKReport up to s3.
+     *
+     * Should be run in a separate thread so we can time it out if something is taking too long
+     */
+    private class S3PutRunnable implements Runnable {
+        /** Was the upload operation successful? */
+        public final AtomicBoolean isSuccess;
+        /** The name of this report */
+        private final String filename;
+        /** The contents of this report */
+        private final byte[] contents;
+
+        /** The s3Object that we created to upload, or null if it failed */
+        public S3Object s3Object = null;
+
+        @Requires({"filename != null", "contents != null"})
+        public S3PutRunnable(final String filename, final byte[] contents){
+            this.isSuccess = new AtomicBoolean();
+            this.filename = filename;
+            this.contents = contents;
+        }
+
+        public void run() {
+            try {
+                switch ( awsMode ) {
+                    case FAIL_WITH_EXCEPTION:
+                        throw new IllegalStateException("We are throwing an exception for testing purposes");
+                    case TIMEOUT:
+                        try {
+                            Thread.sleep(s3PutTimeOutInMilliseconds * 100);
+                        } catch ( InterruptedException e ) {
+                            // supposed to be empty
+                        }
+                        break;
+                    case NORMAL:
+                        // IAM GATK user credentials -- only right is to PutObject into broad.gsa.gatk.run.reports bucket
+                        final S3Service s3Service = initializeAWSService(getAWSUploadAccessKey(), getAWSUploadSecretKey());
+
+                        // Create an S3Object based on a file, with Content-Length set automatically and
+                        // Content-Type set based on the file's extension (using the Mimetypes utility class)
+                        final S3Object fileObject = new S3Object(filename, contents);
+                        //logger.info("Created S3Object" + fileObject);
+                        //logger.info("Uploading " + localFile + " to AWS bucket");
+                        s3Object = s3Service.putObject(getS3ReportBucket(), fileObject);
+                        isSuccess.set(true);
+                        break;
+                    default:
+                        throw new IllegalStateException("Unexpected AWS exception");
+                }
+            } catch ( S3ServiceException e ) {
+                exceptDuringRunReport("S3 exception occurred", e);
+            } catch ( NoSuchAlgorithmException e ) {
+                exceptDuringRunReport("Couldn't calculate MD5", e);
+            } catch ( IOException e ) {
+                exceptDuringRunReport("Couldn't read report file", e);
+            } catch ( Exception e ) {
+                exceptDuringRunReport("An unexpected exception occurred during posting", e);
+            }
+        }
+    }
+
+    /**
+     * Post this GATK report to the AWS s3 GATK_Run_Report log
+     *
+     * @return the s3Object pointing to our pushed report, or null if we failed to push
+     */
+    protected S3Object postReportToAWSS3() {
+        // modifying example code from http://jets3t.s3.amazonaws.com/toolkit/code-samples.html
+        this.hostName = Utils.resolveHostname(); // we want to fill in the host name
+        final String key = getReportFileName();
+        logger.debug("Generating GATK report to AWS S3 with key " + key);
+
+        try {
+            // create an byte output stream so we can capture the output as a byte[]
+            final ByteArrayOutputStream byteStream = new ByteArrayOutputStream(8096);
+            final OutputStream outputStream = new GZIPOutputStream(byteStream);
+            postReportToStream(outputStream);
+            outputStream.close();
+            final byte[] report = byteStream.toByteArray();
+
+            // stop us from printing the annoying, and meaningless, mime types warning
+            final Logger mimeTypeLogger = Logger.getLogger(org.jets3t.service.utils.Mimetypes.class);
+            mimeTypeLogger.setLevel(Level.FATAL);
+
+            // Set the S3 upload on its own thread with timeout:
+            final S3PutRunnable s3run = new S3PutRunnable(key,report);
+            final Thread s3thread = new Thread(s3run);
+            s3thread.setDaemon(true);
+            s3thread.setName("S3Put-Thread");
+            s3thread.start();
+
+            s3thread.join(s3PutTimeOutInMilliseconds);
+
+            if(s3thread.isAlive()){
+                s3thread.interrupt();
+                exceptDuringRunReport("Run statistics report upload to AWS S3 timed-out");
+            } else if(s3run.isSuccess.get()) {
+                logger.info("Uploaded run statistics report to AWS S3");
+                logger.debug("Uploaded to AWS: " + s3run.s3Object);
+                return s3run.s3Object;
+            } else {
+                // an exception occurred, the thread should have already invoked the exceptDuringRunReport function
+            }
+        } catch ( IOException e ) {
+            exceptDuringRunReport("Couldn't read report file", e);
+        } catch ( InterruptedException e) {
+            exceptDuringRunReport("Run statistics report upload interrupted", e);
+        }
+
+        return null;
+    }
+
+    // ---------------------------------------------------------------------------
+    //
+    // Error handling code
+    //
+    // ---------------------------------------------------------------------------
+
+    /**
+     * Note that an exception occurred during creating or writing this report
+     * @param msg the message to print
+     * @param e the exception that occurred
+     */
+    @Ensures("exceptionOccurredDuringPost()")
+    private void exceptDuringRunReport(final String msg, final Throwable e) {
+        this.errorMessage = msg;
+        this.errorThrown = e;
+        logger.debug("A problem occurred during GATK run reporting [*** everything is fine, but no report could be generated; please do not post this to the support forum ***].  Message is: " + msg + ".  Error message is: " + e.getMessage());
+    }
+
+    /**
+     * Note that an exception occurred during creating or writing this report
+     * @param msg the message to print
+     */
+    @Ensures("exceptionOccurredDuringPost()")
+    private void exceptDuringRunReport(final String msg) {
+        this.errorMessage = msg;
+        logger.debug("A problem occurred during GATK run reporting [*** everything is fine, but no report could be generated; please do not post this to the support forum ***].  Message is " + msg);
+    }
+
+    /**
+     * Did an error occur during the posting of this run report?
+     * @return true if so, false if not
+     */
+    public boolean exceptionOccurredDuringPost() {
+        return getErrorMessage() != null;
+    }
+
+    /**
+     * If an error occurred during posting of this report, retrieve the message of the error that occurred, or null if
+     * no error occurred
+     * @return a string describing the error that occurred, or null if none did
+     */
+    public String getErrorMessage() {
+        return errorMessage;
+    }
+
+    /**
+     * Get the throwable that caused the exception during posting of this message, or null if none was available
+     *
+     * Note that getting a null valuable from this function doesn't not imply that no error occurred.  Some
+     * errors that occurred many not have generated a throwable.
+     *
+     * @return the Throwable that caused the error, or null if no error occurred or was not caused by a throwable
+     */
+    public Throwable getErrorThrown() {
+        return errorThrown;
+    }
+
+    /**
+     * Helper method to format the exception that occurred during posting, or a string saying none occurred
+     * @return a non-null string
+     */
+    @Ensures("result != null")
+    protected String formatError() {
+        return exceptionOccurredDuringPost()
+                ? String.format("Exception message=%s with cause=%s", getErrorMessage(), getErrorThrown())
+                : "No exception occurred";
+    }
+
+    // ---------------------------------------------------------------------------
+    //
+    // Equals and hashcode -- purely for comparing reports for testing
+    //
+    // ---------------------------------------------------------------------------
+
+    @Override
+    public boolean equals(Object o) {
+        if (this == o) return true;
+        if (o == null || getClass() != o.getClass()) return false;
+
+        GATKRunReport that = (GATKRunReport) o;
+
+        if (maxMemory != that.maxMemory) return false;
+        if (nIterations != that.nIterations) return false;
+        if (numThreads != that.numThreads) return false;
+        if (runTime != that.runTime) return false;
+        if (totalMemory != that.totalMemory) return false;
+        if (endTime != null ? !endTime.equals(that.endTime) : that.endTime != null) return false;
+        if (hostName != null ? !hostName.equals(that.hostName) : that.hostName != null) return false;
+        if (id != null ? !id.equals(that.id) : that.id != null) return false;
+        if (javaVersion != null ? !javaVersion.equals(that.javaVersion) : that.javaVersion != null) return false;
+        if (mException != null ? !mException.equals(that.mException) : that.mException != null) return false;
+        if (machine != null ? !machine.equals(that.machine) : that.machine != null) return false;
+        if (percentTimeBlocking != null ? !percentTimeBlocking.equals(that.percentTimeBlocking) : that.percentTimeBlocking != null)
+            return false;
+        if (percentTimeRunning != null ? !percentTimeRunning.equals(that.percentTimeRunning) : that.percentTimeRunning != null)
+            return false;
+        if (percentTimeWaiting != null ? !percentTimeWaiting.equals(that.percentTimeWaiting) : that.percentTimeWaiting != null)
+            return false;
+        if (percentTimeWaitingForIO != null ? !percentTimeWaitingForIO.equals(that.percentTimeWaitingForIO) : that.percentTimeWaitingForIO != null)
+            return false;
+        if (startTime != null ? !startTime.equals(that.startTime) : that.startTime != null) return false;
+        if (svnVersion != null ? !svnVersion.equals(that.svnVersion) : that.svnVersion != null) return false;
+        if (tag != null ? !tag.equals(that.tag) : that.tag != null) return false;
+        if (userName != null ? !userName.equals(that.userName) : that.userName != null) return false;
+        if (walkerName != null ? !walkerName.equals(that.walkerName) : that.walkerName != null) return false;
+
+        return true;
+    }
+
+    @Override
+    public int hashCode() {
+        int result = id != null ? id.hashCode() : 0;
+        result = 31 * result + (mException != null ? mException.hashCode() : 0);
+        result = 31 * result + (startTime != null ? startTime.hashCode() : 0);
+        result = 31 * result + (endTime != null ? endTime.hashCode() : 0);
+        result = 31 * result + (int) (runTime ^ (runTime >>> 32));
+        result = 31 * result + (walkerName != null ? walkerName.hashCode() : 0);
+        result = 31 * result + (svnVersion != null ? svnVersion.hashCode() : 0);
+        result = 31 * result + (int) (totalMemory ^ (totalMemory >>> 32));
+        result = 31 * result + (int) (maxMemory ^ (maxMemory >>> 32));
+        result = 31 * result + (userName != null ? userName.hashCode() : 0);
+        result = 31 * result + (hostName != null ? hostName.hashCode() : 0);
+        result = 31 * result + (javaVersion != null ? javaVersion.hashCode() : 0);
+        result = 31 * result + (machine != null ? machine.hashCode() : 0);
+        result = 31 * result + (int) (nIterations ^ (nIterations >>> 32));
+        result = 31 * result + (tag != null ? tag.hashCode() : 0);
+        result = 31 * result + numThreads;
+        result = 31 * result + (percentTimeRunning != null ? percentTimeRunning.hashCode() : 0);
+        result = 31 * result + (percentTimeWaiting != null ? percentTimeWaiting.hashCode() : 0);
+        result = 31 * result + (percentTimeBlocking != null ? percentTimeBlocking.hashCode() : 0);
+        result = 31 * result + (percentTimeWaitingForIO != null ? percentTimeWaitingForIO.hashCode() : 0);
+        return result;
+    }
+
+    // ---------------------------------------------------------------------------
+    //
+    // Code specifically for testing the GATKRunReport
+    //
+    // ---------------------------------------------------------------------------
+
+    /**
+     * Enum specifying how the S3 uploader should behave.  Must be normal by default.  Purely for testing purposes
+     */
+    protected enum AWSMode {
+        NORMAL, // write normally to AWS
+        FAIL_WITH_EXCEPTION, // artificially fail during writing
+        TIMEOUT // sleep, so we time out
+    }
+    /** Our AWS mode */
+    private AWSMode awsMode = AWSMode.NORMAL;
+    /** The bucket were we send the GATK report on AWS/s3 */
+    private String s3ReportBucket = REPORT_BUCKET_NAME;
+    /** Did we send the report to AWS? */
+    private boolean wentToAWS = false;
+
+    /**
+     * Send the report to the AWS test bucket -- for testing only
+     */
+    protected void sendAWSToTestBucket() {
+        s3ReportBucket = TEST_REPORT_BUCKET_NAME;
+    }
+
+    /**
+     * Has the report been written to AWS?
+     *
+     * Does not imply anything about the success of the send, just that it was attempted
+     *
+     * @return true if the report has been sent to AWS, false otherwise
+     */
+    protected boolean wentToAWS() {
+        return wentToAWS;
+    }
+
+    /**
+     * Purely for testing purposes.  Tells the AWS uploader whether to actually upload or simulate errors
+     * @param mode what we want to do
+     */
+    @Requires("mode != null")
+    protected void setAwsMode(final AWSMode mode) {
+        this.awsMode = mode;
+    }
+}
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/phonehome/GATKRunReportException.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/phonehome/GATKRunReportException.java
new file mode 100644
index 0000000..4de344e
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/phonehome/GATKRunReportException.java
@@ -0,0 +1,99 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.engine.phonehome;
+
+import org.broadinstitute.gatk.utils.exceptions.UserException;
+import org.simpleframework.xml.Element;
+import org.simpleframework.xml.ElementList;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * A helper class for formatting in XML the throwable chain starting at e.
+ */
+class GATKRunReportException {
+    @Element(required = false, name = "message")
+    String message = null;
+
+    @ElementList(required = false, name = "stacktrace")
+    final List<String> stackTrace = new ArrayList<String>();
+
+    @Element(required = false, name = "cause")
+    GATKRunReportException cause = null;
+
+    @Element(required = false, name = "is-user-exception")
+    Boolean isUserException;
+
+    @Element(required = false, name = "exception-class")
+    Class exceptionClass;
+
+    /**
+     * Allow us to deserialize from XML
+     */
+    public GATKRunReportException() { }
+
+    public GATKRunReportException(Throwable e) {
+        message = e.getMessage();
+        exceptionClass = e.getClass();
+        isUserException = e instanceof UserException;
+        for (StackTraceElement element : e.getStackTrace()) {
+            stackTrace.add(element.toString());
+        }
+
+        if ( e.getCause() != null ) {
+            cause = new GATKRunReportException(e.getCause());
+        }
+    }
+
+    @Override
+    public boolean equals(Object o) {
+        if (this == o) return true;
+        if (o == null || getClass() != o.getClass()) return false;
+
+        GATKRunReportException that = (GATKRunReportException) o;
+
+        if (cause != null ? !cause.equals(that.cause) : that.cause != null) return false;
+        if (exceptionClass != null ? !exceptionClass.equals(that.exceptionClass) : that.exceptionClass != null)
+            return false;
+        if (isUserException != null ? !isUserException.equals(that.isUserException) : that.isUserException != null)
+            return false;
+        if (message != null ? !message.equals(that.message) : that.message != null) return false;
+        if (stackTrace != null ? !stackTrace.equals(that.stackTrace) : that.stackTrace != null) return false;
+
+        return true;
+    }
+
+    @Override
+    public int hashCode() {
+        int result = message != null ? message.hashCode() : 0;
+        result = 31 * result + (stackTrace != null ? stackTrace.hashCode() : 0);
+        result = 31 * result + (cause != null ? cause.hashCode() : 0);
+        result = 31 * result + (isUserException != null ? isUserException.hashCode() : 0);
+        result = 31 * result + (exceptionClass != null ? exceptionClass.hashCode() : 0);
+        return result;
+    }
+}
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/refdata/RODRecordListImpl.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/refdata/RODRecordListImpl.java
new file mode 100644
index 0000000..7296c39
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/refdata/RODRecordListImpl.java
@@ -0,0 +1,129 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.engine.refdata;
+
+import org.broadinstitute.gatk.engine.refdata.utils.GATKFeature;
+import org.broadinstitute.gatk.engine.refdata.utils.RODRecordList;
+import org.broadinstitute.gatk.utils.GenomeLoc;
+import org.broadinstitute.gatk.utils.HasGenomeLocation;
+import org.broadinstitute.gatk.utils.exceptions.ReviewedGATKException;
+
+import java.util.*;
+
+/**
+ * Created by IntelliJ IDEA.
+ * User: asivache
+ * Date: Sep 10, 2009
+ * Time: 6:10:48 PM
+ * To change this template use File | Settings | File Templates.
+ */
+public class RODRecordListImpl extends AbstractList<GATKFeature> implements Comparable<RODRecordList>, Cloneable, RODRecordList, HasGenomeLocation {
+    private List<GATKFeature> records;
+    private GenomeLoc location = null;
+    private String name = null;
+
+    public RODRecordListImpl(String name) {
+        records = new ArrayList<GATKFeature>();
+        this.name = name;
+    }
+
+    /**
+     * Fully qualified constructor: instantiates a new GATKFeatureRecordList object with specified GATKFeature track name, location on the
+     * reference, and list of associated GATKFeatures. This is a knee-deep COPY constructor: passed name, loc, and data element
+     * objects will be referenced from the created GATKFeatureRecordList (so that changing them from outside will affect data
+     * in this object), however, the data elements will be copied into a newly
+     * allocated list, so that the 'data' collection argument can be modified afterwards without affecting the state
+     * of this record list. WARNING: this constructor is (semi-)validating: passed name and location
+     * are allowed to be nulls (although it maybe unsafe, use caution), but if they are not nulls, then passed non-null GATKFeature data
+     * elements must have same track name, and their locations must overlap with the passed 'location' argument. Null
+     * data elements or null 'data' collection argument are allowed as well.
+     * @param name the name of the track
+     * @param data the collection of features at this location
+     * @param loc the location
+     */
+    public RODRecordListImpl(String name, Collection<GATKFeature> data, GenomeLoc loc) {
+        this.records = new ArrayList<GATKFeature>(data==null?0:data.size());
+        this.name = name;
+        this.location = loc;
+        if ( data == null || data.size() == 0 ) return; // empty dataset, nothing to do
+        for ( GATKFeature r : data ) {
+            records.add(r);
+            if ( r == null ) continue;
+            if ( ! this.name.equals(r.getName() ) ) {
+                throw new ReviewedGATKException("Attempt to add GATKFeature with non-matching name "+r.getName()+" to the track "+name);
+            }
+            if ( location != null && ! location.overlapsP(r.getLocation()) ) {
+                    throw new ReviewedGATKException("Attempt to add GATKFeature that lies outside of specified interval "+location+"; offending GATKFeature:\n"+r.toString());
+            }
+        }
+    }
+
+
+    public GenomeLoc getLocation() { return location; }
+    public String getName() { return name; }
+    public Iterator<GATKFeature> iterator() { return records.iterator() ; }
+    public void clear() { records.clear(); }
+    public boolean isEmpty() { return records.isEmpty(); }
+
+    public boolean add(GATKFeature record) { add(record, false); return true;}
+
+    @Override
+    public GATKFeature get(int i) {
+        return records.get(i);
+    }
+
+    public void add(GATKFeature record, boolean allowNameMismatch) {
+        if ( record != null ) {
+            if ( ! allowNameMismatch && ! name.equals(record.getName() ) )
+                throw new ReviewedGATKException("Attempt to add GATKFeature with non-matching name "+record.getName()+" to the track "+name);
+        }
+        records.add(record);
+    }
+
+    public void add(RODRecordList records ) { add( records, false ); }
+
+    public void add(RODRecordList records, boolean allowNameMismatch) {
+        for ( GATKFeature record : records )
+            add(record, allowNameMismatch);
+    }    
+
+    public int size() { return records.size() ; }
+
+    /**
+     * Compares this object with the specified object for order.  Returns a
+     * negative integer, zero, or a positive integer as this object is less
+     * than, equal to, or greater than the specified object.
+     *
+     * @param that the object to be compared.
+     * @return a negative integer, zero, or a positive integer as this object
+     *         is less than, equal to, or greater than the specified object.
+     * @throws ClassCastException if the specified object's type prevents it
+     *                            from being compared to this object.
+     */
+    public int compareTo(RODRecordList that) {
+        return getLocation().compareTo(that.getLocation());  //To change body of implemented methods use File | Settings | File Templates.
+    }
+}
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/refdata/RefMetaDataTracker.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/refdata/RefMetaDataTracker.java
new file mode 100644
index 0000000..7ccf6e5
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/refdata/RefMetaDataTracker.java
@@ -0,0 +1,497 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.engine.refdata;
+
+import com.google.java.contract.Ensures;
+import com.google.java.contract.Requires;
+import org.apache.log4j.Logger;
+import htsjdk.tribble.Feature;
+import org.broadinstitute.gatk.utils.commandline.RodBinding;
+import org.broadinstitute.gatk.engine.refdata.utils.GATKFeature;
+import org.broadinstitute.gatk.engine.refdata.utils.RODRecordList;
+import org.broadinstitute.gatk.utils.GenomeLoc;
+import org.broadinstitute.gatk.utils.exceptions.UserException;
+
+import java.util.*;
+
+/**
+ * This class represents the Reference Metadata available at a particular site in the genome.  It can be
+ * used to conveniently lookup the RMDs at this site, as well just getting a list of all of the RMDs
+ *
+ * The standard interaction model is:
+ *
+ * Traversal system arrives at a site, which has a bunch of RMDs covering it
+ * Traversal passes creates a tracker and passes it to the walker
+ * walker calls get(rodBinding) to obtain the RMDs values at this site for the track
+ * associated with rodBinding.
+ *
+ * Note that this is an immutable class.  Once created the underlying data structures
+ * cannot be modified
+ *
+ * User: mdepristo
+ * Date: Apr 3, 2009
+ * Time: 3:05:23 PM
+ */
+public class RefMetaDataTracker {
+    // TODO: this should be a list, not a bindings, actually
+    private final static RODRecordList EMPTY_ROD_RECORD_LIST = new RODRecordListImpl("EMPTY");
+
+    final Map<String, RODRecordList> bindings;
+    final protected static Logger logger = Logger.getLogger(RefMetaDataTracker.class);
+    public final static RefMetaDataTracker EMPTY_TRACKER = new RefMetaDataTracker();
+
+    // ------------------------------------------------------------------------------------------
+    //
+    //
+    // Special ENGINE interaction functions
+    //
+    //
+    // ------------------------------------------------------------------------------------------
+
+    /**
+     * Create an tracker with no bindings
+     */
+    public RefMetaDataTracker() {
+        bindings = Collections.emptyMap();
+    }
+
+    public RefMetaDataTracker(final Collection<RODRecordList> allBindings) {
+        // set up the bindings
+        if ( allBindings.isEmpty() )
+            bindings = Collections.emptyMap();
+        else {
+            final Map<String, RODRecordList> tmap = new HashMap<String, RODRecordList>(allBindings.size());
+            for ( RODRecordList rod : allBindings ) {
+                if ( rod != null && ! rod.isEmpty() )
+                    tmap.put(canonicalName(rod.getName()), rod);
+            }
+
+            // ensure that no one modifies the bindings itself
+            bindings = Collections.unmodifiableMap(tmap);
+        }
+    }
+
+    // ------------------------------------------------------------------------------------------
+    //
+    //
+    // Generic accessors
+    //
+    //
+    // ------------------------------------------------------------------------------------------
+
+    /**
+     * Gets all of the Tribble features spanning this locus, returning them as a list of specific
+     * type T extending Feature.  This function looks across all tracks to find the Features, so
+     * if you have two tracks A and B each containing 1 Feature, then getValues will return
+     * a list containing both features.
+     *
+     * Note that this function assumes that all of the bound features are instances of or
+     * subclasses of T.  A ClassCastException will occur if this isn't the case.  If you want
+     * to get all Features without any danger of such an exception use the root Tribble
+     * interface Feature.
+     *
+     * @param type The type of the underlying objects bound here
+     * @param <T> as above
+     * @return A freshly allocated list of all of the bindings, or an empty list if none are bound.
+     */
+    @Requires({"type != null"})
+    @Ensures("result != null")
+    public <T extends Feature> List<T> getValues(final Class<T> type) {
+        return addValues(bindings.keySet(), type, new ArrayList<T>(), null, false, false);
+    }
+
+    /**
+     * Provides the same functionality as @link #getValues(Class<T>) but will only include
+     * Features that start as the GenomeLoc provide onlyAtThisLoc.
+     *
+     * @param type The type of the underlying objects bound here
+     * @param onlyAtThisLoc
+     * @param <T> as above
+     * @return A freshly allocated list of all of the bindings, or an empty list if none are bound.
+     */
+    @Requires({"type != null", "onlyAtThisLoc != null"})
+    @Ensures("result != null")
+    public <T extends Feature> List<T> getValues(final Class<T> type, final GenomeLoc onlyAtThisLoc) {
+        return addValues(bindings.keySet(), type, new ArrayList<T>(), onlyAtThisLoc, true, false);
+    }
+
+    /**
+     * Uses the same logic as @link #getValues(Class) but arbitrary select one of the resulting
+     * elements of the list to return.  That is, if there would be two elements in the result of
+     * @link #getValues(Class), one of these two is selected, and which one it will be isn't
+     * specified.  Consequently, this method is only really safe if (1) you absolutely know
+     * that only one binding will meet the constraints of @link #getValues(Class) or (2)
+     * you truly don't care which of the multiple bindings available you are going to examine.
+     *
+     * If there are no bindings here, getFirstValue() return null
+     *
+     * @param type The type of the underlying objects bound here
+     * @param <T> as above
+     * @return A random single element the RODs bound here, or null if none are bound.
+     */
+    @Requires({"type != null"})
+    public <T extends Feature> T getFirstValue(final Class<T> type) {
+        return safeGetFirst(getValues(type));
+    }
+
+    /**
+     * Uses the same logic as @link #getValue(Class,GenomeLoc) to determine the list
+     * of eligible Features and @link #getFirstValue(Class) to select a single
+     * element from the interval list.
+     *
+     * @param type The type of the underlying objects bound here
+     * @param <T> as above
+     * @param onlyAtThisLoc only Features starting at this site are considered
+     * @return A random single element the RODs bound here starting at onlyAtThisLoc, or null if none are bound.
+     */
+    @Requires({"type != null", "onlyAtThisLoc != null"})
+    public <T extends Feature> T getFirstValue(final Class<T> type, final GenomeLoc onlyAtThisLoc) {
+        return safeGetFirst(getValues(type, onlyAtThisLoc));
+    }
+
+    /**
+     * Same logic as @link #getFirstValue(RodBinding, boolean) but prioritizes records from prioritizeThisLoc if available
+     *
+     * @param rodBindings Only Features coming from the tracks associated with one of rodBindings are fetched
+     * @param <T> The Tribble Feature type of the rodBinding, and consequently the type of the resulting list of Features
+     * @param prioritizeThisLoc only Features starting at this site are considered
+     * @return A freshly allocated list of all of the bindings, or an empty list if none are bound.
+     */
+    @Requires({"rodBindings != null", "prioritizeThisLoc != null"})
+    @Ensures("result != null")
+    public <T extends Feature> List<T> getPrioritizedValue(final Collection<RodBinding<T>> rodBindings, final GenomeLoc prioritizeThisLoc) {
+        final List<T> results = new ArrayList<>();
+
+        for ( final RodBinding<T> rodBinding : rodBindings ) {
+
+            // if there's a value at the prioritized location, take it
+            T value = getFirstValue(rodBinding, prioritizeThisLoc);
+
+            // otherwise, grab any one
+            if ( value == null )
+                value = getFirstValue(rodBinding);
+
+            // add if not null
+            if ( value != null )
+                results.add(value);
+        }
+
+        return results;
+    }
+
+    /**
+     * Gets all of the Tribble features bound to RodBinding spanning this locus, returning them as
+     * a list of specific type T extending Feature.
+     *
+     * Note that this function assumes that all of the bound features are instances of or
+     * subclasses of T.  A ClassCastException will occur if this isn't the case.
+     *
+     * @param rodBinding Only Features coming from the track associated with this rodBinding are fetched
+     * @param <T> The Tribble Feature type of the rodBinding, and consequently the type of the resulting list of Features
+     * @return A freshly allocated list of all of the bindings, or an empty list if none are bound.
+     */
+    @Requires({"rodBinding != null"})
+    @Ensures("result != null")
+    public <T extends Feature> List<T> getValues(final RodBinding<T> rodBinding) {
+        return addValues(rodBinding.getName(), rodBinding.getType(), new ArrayList<T>(1), getTrackDataByName(rodBinding), null, false, false);
+    }
+
+    /**
+     * Gets all of the Tribble features bound to any RodBinding in rodBindings,
+     * spanning this locus, returning them as a list of specific type T extending Feature.
+     *
+     * Note that this function assumes that all of the bound features are instances of or
+     * subclasses of T.  A ClassCastException will occur if this isn't the case.
+     *
+     * @param rodBindings Only Features coming from the tracks associated with one of rodBindings are fetched
+     * @param <T> The Tribble Feature type of the rodBinding, and consequently the type of the resulting list of Features
+     * @return A freshly allocated list of all of the bindings, or an empty list if none are bound.
+     */
+    @Requires({"rodBindings != null"})
+    @Ensures("result != null")
+    public <T extends Feature> List<T> getValues(final Collection<RodBinding<T>> rodBindings) {
+        List<T> results = new ArrayList<T>(1);
+        for ( RodBinding<T> rodBinding : rodBindings )
+            results.addAll(getValues(rodBinding));
+        return results;
+    }
+
+    /**
+     * The same logic as @link #getValues(RodBinding) but enforces that each Feature start at onlyAtThisLoc
+     *
+     * @param rodBinding Only Features coming from the track associated with this rodBinding are fetched
+     * @param <T> The Tribble Feature type of the rodBinding, and consequently the type of the resulting list of Features
+     * @param onlyAtThisLoc only Features starting at this site are considered
+     * @return A freshly allocated list of all of the bindings, or an empty list if none are bound.
+     */
+    @Requires({"rodBinding != null", "onlyAtThisLoc != null"})
+    @Ensures("result != null")
+    public <T extends Feature> List<T> getValues(final RodBinding<T> rodBinding, final GenomeLoc onlyAtThisLoc) {
+        return addValues(rodBinding.getName(), rodBinding.getType(), new ArrayList<T>(1), getTrackDataByName(rodBinding), onlyAtThisLoc, true, false);
+    }
+
+    /**
+     * The same logic as @link #getValues(List) but enforces that each Feature start at onlyAtThisLoc
+     *
+     * @param rodBindings Only Features coming from the tracks associated with one of rodBindings are fetched
+     * @param <T> The Tribble Feature type of the rodBinding, and consequently the type of the resulting list of Features
+     * @param onlyAtThisLoc only Features starting at this site are considered
+     * @return A freshly allocated list of all of the bindings, or an empty list if none are bound.
+     */
+    @Requires({"rodBindings != null", "onlyAtThisLoc != null"})
+    @Ensures("result != null")
+    public <T extends Feature> List<T> getValues(final Collection<RodBinding<T>> rodBindings, final GenomeLoc onlyAtThisLoc) {
+        List<T> results = new ArrayList<T>(1);
+        for ( RodBinding<T> rodBinding : rodBindings )
+            results.addAll(getValues(rodBinding, onlyAtThisLoc));
+        return results;
+    }
+
+    /**
+     * Uses the same logic as @getValues(RodBinding) to determine the list
+     * of eligible Features and select a single element from the resulting set
+     * of eligible features.
+     *
+     * @param rodBinding Only Features coming from the track associated with this rodBinding are fetched
+     * @param <T> as above
+     * @return A random single element the eligible Features found, or null if none are bound.
+     */
+    @Requires({"rodBinding != null"})
+    public <T extends Feature> T getFirstValue(final RodBinding<T> rodBinding) {
+        return safeGetFirst(addValues(rodBinding.getName(), rodBinding.getType(), null, getTrackDataByName(rodBinding), null, false, true));
+    }
+
+    /**
+     * Uses the same logic as @getValues(RodBinding, GenomeLoc) to determine the list
+     * of eligible Features and select a single element from the resulting set
+     * of eligible features.
+     *
+     * @param rodBinding Only Features coming from the track associated with this rodBinding are fetched
+     * @param <T> as above
+     * @param onlyAtThisLoc only Features starting at this site are considered
+     * @return A random single element the eligible Features found, or null if none are bound.
+     */
+    @Requires({"rodBinding != null", "onlyAtThisLoc != null"})
+    public <T extends Feature> T getFirstValue(final RodBinding<T> rodBinding, final GenomeLoc onlyAtThisLoc) {
+        return safeGetFirst(addValues(rodBinding.getName(), rodBinding.getType(), null, getTrackDataByName(rodBinding), onlyAtThisLoc, true, true));
+    }
+
+    /**
+     * Uses the same logic as @getValues(List) to determine the list
+     * of eligible Features and select a single element from the resulting set
+     * of eligible features.
+     *
+     * @param rodBindings Only Features coming from the tracks associated with these rodBindings are fetched
+     * @param <T> as above
+     * @return A random single element the eligible Features found, or null if none are bound.
+     */
+    @Requires({"rodBindings != null"})
+    public <T extends Feature> T getFirstValue(final Collection<RodBinding<T>> rodBindings) {
+        for ( RodBinding<T> rodBinding : rodBindings ) {
+            T val = getFirstValue(rodBinding);
+            if ( val != null )
+                return val;
+        }
+        return null;
+    }
+
+    /**
+     * Uses the same logic as @getValues(RodBinding,GenomeLoc) to determine the list
+     * of eligible Features and select a single element from the resulting set
+     * of eligible features.
+     *
+     * @param rodBindings Only Features coming from the tracks associated with these rodBindings are fetched
+     * @param <T> as above
+     * @param onlyAtThisLoc only Features starting at this site are considered
+     * @return A random single element the eligible Features found, or null if none are bound.
+     */
+    @Requires({"rodBindings != null", "onlyAtThisLoc != null"})
+    public <T extends Feature> T getFirstValue(final Collection<RodBinding<T>> rodBindings, final GenomeLoc onlyAtThisLoc) {
+        for ( RodBinding<T> rodBinding : rodBindings ) {
+            T val = getFirstValue(rodBinding, onlyAtThisLoc);
+            if ( val != null )
+                return val;
+        }
+        return null;
+    }
+
+    /**
+     * Is there a binding at this site to a ROD/track with the specified name?
+     *
+     * @param rodBinding the rod binding we want to know about
+     * @return true if any Features are bound in this tracker to rodBinding
+     */
+    @Requires({"rodBinding != null"})
+    public boolean hasValues(final RodBinding rodBinding) {
+        return bindings.containsKey(canonicalName(rodBinding.getName()));
+    }
+
+    /**
+     * Get all of the RMD tracks at the current site. Each track is returned as a single compound
+     * object (RODRecordList) that may contain multiple RMD records associated with the current site.
+     *
+     * @return List of all tracks
+     */
+    public List<RODRecordList> getBoundRodTracks() {
+        return new ArrayList<RODRecordList>(bindings.values());
+    }
+
+    /**
+     * The number of tracks with at least one value bound here
+     * @return the number of tracks with at least one bound Feature
+     */
+    public int getNTracksWithBoundFeatures() {
+        return bindings.size();
+    }
+
+    // ------------------------------------------------------------------------------------------
+    // Protected accessors using strings for unit testing
+    // ------------------------------------------------------------------------------------------
+
+    protected boolean hasValues(final String name) {
+        return bindings.containsKey(canonicalName(name));
+    }
+
+    protected <T extends Feature> List<T> getValues(final Class<T> type, final String name) {
+        return addValues(name, type, new ArrayList<T>(), getTrackDataByName(name), null, false, false);
+    }
+
+    protected <T extends Feature> List<T> getValues(final Class<T> type, final String name, final GenomeLoc onlyAtThisLoc) {
+        return addValues(name, type, new ArrayList<T>(), getTrackDataByName(name), onlyAtThisLoc, true, false);
+    }
+
+    protected <T extends Feature> T getFirstValue(final Class<T> type, final String name) {
+        return safeGetFirst(getValues(type, name));
+    }
+
+    protected <T extends Feature> T getFirstValue(final Class<T> type, final String name, final GenomeLoc onlyAtThisLoc) {
+        return safeGetFirst(getValues(type, name, onlyAtThisLoc));
+    }
+
+    // ------------------------------------------------------------------------------------------
+    //
+    //
+    // Private utility functions
+    //
+    //
+    // ------------------------------------------------------------------------------------------
+
+    /**
+     * Helper function for getFirst() operations that takes a list of <T> and
+     * returns the first element, or null if no such element exists.
+     *
+     * @param l
+     * @param <T>
+     * @return
+     */
+    @Requires({"l != null"})
+    private <T extends Feature> T safeGetFirst(final List<T> l) {
+        return l.isEmpty() ? null : l.get(0);
+    }
+
+    private <T extends Feature> List<T> addValues(final Collection<String> names,
+                                                  final Class<T> type,
+                                                  List<T> values,
+                                                  final GenomeLoc curLocation,
+                                                  final boolean requireStartHere,
+                                                  final boolean takeFirstOnly ) {
+        for ( String name : names ) {
+            RODRecordList rodList = getTrackDataByName(name); // require that the name is an exact match
+            values = addValues(name, type, values, rodList, curLocation, requireStartHere, takeFirstOnly );
+            if ( takeFirstOnly && ! values.isEmpty() )
+                break;
+        }
+
+        return values;
+    }
+
+
+
+    private <T extends Feature> List<T> addValues(final String name,
+                                                  final Class<T> type,
+                                                  List<T> values,
+                                                  final RODRecordList rodList,
+                                                  final GenomeLoc curLocation,
+                                                  final boolean requireStartHere,
+                                                  final boolean takeFirstOnly ) {
+        for ( GATKFeature rec : rodList ) {
+            if ( ! requireStartHere || rec.getLocation().getStart() == curLocation.getStart() ) {  // ok, we are going to keep this thing
+                Object obj = rec.getUnderlyingObject();
+                if (!(type.isAssignableFrom(obj.getClass())))
+                    throw new UserException.CommandLineException("Unable to cast track named " + name + " to type of " + type.toString()
+                            + " it's of type " + obj.getClass());
+
+                T objT = (T)obj;
+                if ( takeFirstOnly ) {
+                    if ( values == null )
+                        values = Arrays.asList(objT);
+                    else
+                        values.add(objT);
+
+                    break;
+                } else {
+                    if ( values == null )
+                        values = new ArrayList<T>();
+                    values.add(objT);
+                }
+            }
+        }
+
+        return values == null ? Collections.<T>emptyList() : values;
+    }
+
+    /**
+     * Finds the reference metadata track named 'name' and returns all ROD records from that track associated
+     * with the current site as a RODRecordList List object. If no data track with specified name is available,
+     * returns defaultValue wrapped as RODRecordList object. NOTE: if defaultValue is null, it will be wrapped up
+     * with track name set to 'name' and location set to null; otherwise the wrapper object will have name and
+     * location set to defaultValue.getID() and defaultValue.getLocation(), respectively (use caution,
+     * defaultValue.getLocation() may be not equal to what RODRecordList's location would be expected to be otherwise:
+     * for instance, on locus traversal, location is usually expected to be a single base we are currently looking at,
+     * regardless of the presence of "extended" RODs overlapping with that location).
+     * @param name                track name
+     * @return track data for the given rod
+     */
+    private RODRecordList getTrackDataByName(final String name) {
+        final String luName = canonicalName(name);
+        RODRecordList l = bindings.get(luName);
+        return l == null ? EMPTY_ROD_RECORD_LIST : l;
+    }
+
+    private RODRecordList getTrackDataByName(final RodBinding binding) {
+        return getTrackDataByName(binding.getName());
+    }
+
+    /**
+     * Returns the canonical name of the rod name (lowercases it)
+     * @param name the name of the rod
+     * @return canonical name of the rod
+     */
+    private String canonicalName(final String name) {
+        // todo -- remove me after switch to RodBinding syntax
+        return name.toLowerCase();
+    }
+}
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/refdata/ReferenceDependentFeatureCodec.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/refdata/ReferenceDependentFeatureCodec.java
new file mode 100644
index 0000000..9bff00d
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/refdata/ReferenceDependentFeatureCodec.java
@@ -0,0 +1,43 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.engine.refdata;
+
+import htsjdk.tribble.FeatureCodec;
+import org.broadinstitute.gatk.utils.GenomeLocParser;
+
+/**
+ * An interface marking that a given Tribble feature/codec is actually dependent on context within the
+ * reference, rather than having a dependency only on the contig, start, and stop of the given feature.
+ * A HACK.  Tribble should contain all the information in needs to decode the unqualified position of
+ * a feature.
+ */
+public interface ReferenceDependentFeatureCodec {
+    /**
+     * Sets the appropriate GenomeLocParser, providing additional context when decoding larger and more variable features.
+     * @param genomeLocParser The parser to supply. 
+     */
+    public void setGenomeLocParser(GenomeLocParser genomeLocParser);
+}
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/refdata/ReferenceOrderedDatum.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/refdata/ReferenceOrderedDatum.java
new file mode 100644
index 0000000..95de832
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/refdata/ReferenceOrderedDatum.java
@@ -0,0 +1,66 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.engine.refdata;
+
+import org.broadinstitute.gatk.utils.GenomeLoc;
+import org.broadinstitute.gatk.utils.HasGenomeLocation;
+
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+
+/**
+ * Created by IntelliJ IDEA.
+ * User: mdepristo
+ * Date: Feb 27, 2009
+ * Time: 10:49:47 AM
+ * To change this template use File | Settings | File Templates.
+ */
+public interface ReferenceOrderedDatum extends Comparable<ReferenceOrderedDatum>, HasGenomeLocation {
+    public String getName();
+    public boolean parseLine(final Object header, final String[] parts) throws IOException;
+    public String toString();
+    public String toSimpleString();
+    public String repl();
+
+    /**
+     * Used by the ROD system to determine how to split input lines
+     * @return Regex string delimiter separating fields
+     */
+    public String delimiterRegex();
+
+    public GenomeLoc getLocation();
+    public int compareTo( ReferenceOrderedDatum that );
+
+    /**
+     * Backdoor hook to read header, meta-data, etc. associated with the file.  Will be
+     * called by the ROD system before streaming starts
+     *
+     * @param source source data file on disk from which this rod stream will be pulled
+     * @return a header object that will be passed to parseLine command
+     */
+    public Object initialize(final File source) throws FileNotFoundException;
+}
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/refdata/SeekableRODIterator.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/refdata/SeekableRODIterator.java
new file mode 100644
index 0000000..4126214
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/refdata/SeekableRODIterator.java
@@ -0,0 +1,412 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.engine.refdata;
+
+import htsjdk.samtools.SAMSequenceDictionary;
+import htsjdk.samtools.util.CloseableIterator;
+import org.broadinstitute.gatk.engine.iterators.PushbackIterator;
+import org.broadinstitute.gatk.engine.refdata.utils.GATKFeature;
+import org.broadinstitute.gatk.engine.refdata.utils.LocationAwareSeekableRODIterator;
+import org.broadinstitute.gatk.engine.refdata.utils.RODRecordList;
+import org.broadinstitute.gatk.utils.GenomeLoc;
+import org.broadinstitute.gatk.utils.GenomeLocParser;
+import org.broadinstitute.gatk.utils.exceptions.ReviewedGATKException;
+import org.broadinstitute.gatk.utils.exceptions.UserException;
+
+import java.util.Iterator;
+import java.util.LinkedList;
+import java.util.List;
+
+/**
+ * Wrapper class for iterators over ROD objects. It is assumed that the underlying iterator can only
+ * perform standard next() operation, which advances it to the next ROD in the stream (i.e. reads the data file
+ * line by line). This iterator 1) shifts the focus from record-based traversal to position-based traversal,
+ * and 2) adds querying seekForward() method.
+ *
+ * Namely, this iterator's next() method advances not to the next ROD in the underlying stream, but to the next
+ * genomic position covered by (at least one) ROD, and returns all RODs overlapping with that position as a RODRecordList
+ * collection-like object. Similarly, when seekForward(interval) is called, this iterator skips all the RODs from the
+ * underlying stream, until it reaches specified genomic interval, and returns the list of all RODs overlapping with that interval.
+ *
+ * NOTE: this iterator has a STATE: next() operation is not allowed after a seekForward() to a non-point (extended) interval
+ * of length > 1. Such a call would leave the iterator in an inconsistent state. seekForward() can always be called after
+ * either seekForward() or next() (as long as usual ordering criteria are satisfied: the query interval location can neither
+ * start before the current position, nor end before the previous query end). seekForward to an interval of length 1
+ * reenables next() operation. 
+ *
+ * Created by IntelliJ IDEA.
+ * User: asivache
+ * Date: Sep 10, 2009
+ * Time: 6:20:46 PM
+ * To change this template use File | Settings | File Templates.
+ */
+public class SeekableRODIterator implements LocationAwareSeekableRODIterator {
+    /**
+     * Header for the datasource backing this iterator.
+     */
+    private final Object header;
+
+    /**
+     * The parser, used to construct new genome locs.
+     */
+    private final GenomeLocParser parser;
+
+    private final SAMSequenceDictionary sequenceDictionary;
+
+    private PushbackIterator<GATKFeature> it;
+    List<GATKFeature> records = null;  // here we will keep a pile of records overlaping with current position; when we iterate
+                               // and step out of record's scope, we purge it from the list
+    String name = null; // name of the ROD track wrapped by this iterator. Will be pulled from underlying iterator.
+
+    int curr_position = 0; // where the iterator is currently positioned on the genome
+    int max_position = 0;  // the rightmost stop position of currently loaded records
+    String curr_contig = null;   // what contig the iterator is currently on
+    boolean next_is_allowed = true; // see discussion below. next() is illegal after seek-forward queries of length > 1
+
+    // the stop position of the last query. We can query only in forward direction ("seek forward");
+    // it is not only the start position of every successive query that can not be before the start
+    // of the previous one (curr_start), but it is also illegal for a query interval to *end* before
+    // the end of previous query, otherwise we can end up in an inconsistent state
+    int curr_query_end = -1;
+
+    // EXAMPLE of inconsistency curr_query_end guards against:
+    //              record 1      record 2
+    //             ----------     -----------
+    // -------------------------------------------------- REF
+    //         ------------------------- query 1 (interval 1)
+    //               ----------  query 2 (interval 2)
+    //                     --------------- query 3
+    //
+    // If we query first for interval 1, both record 1 and record 2 will be loaded.
+    // Query for interval 2, on the other hand, should return only record 1, but after
+    // query 1 was performed, record 2 is already loaded from the file. If, on the other hand,
+    // we try to un-load it from memory, we won't be able to read it again. Hence query 2 is not
+    // allowed after query 1. Note also, that curr_query_end is not equivalent to max_position:
+    // the latter only tracks where currently loaded records end (and hence helps to re-load records);
+    // after query 1 is performed, max_position will be the end of record 2, but query 3 is still
+    // perfectly legal after query 1.
+    //
+    // IMPORTANT NOTE: it follows from the above discussion and example that next() is illegal after ANY
+    // seek-forward query EXCEPT those that are performed with length-1 intervals (queryInterval.start=queryinteval.stop).
+    // Indeed, in the example above, after, e.g., query 1 is performed, the iterator is "located" at the start
+    // of interval 1, but record1 and record 2 are already loaded. On the other hand, a subsequent call to next() would
+    // need to shift iterator's position by 1 base and return only record 1.
+    //
+    // This implementation tracks the query history and makes next() illegal after a seekforward query of length > 1,
+    // but re-enables next() again after a length-1 query.
+
+    public SeekableRODIterator(Object header,SAMSequenceDictionary rodDictionary,SAMSequenceDictionary referenceDictionary,GenomeLocParser parser,CloseableIterator<GATKFeature> it) {
+        this.header = header;
+        this.parser = parser;
+        this.sequenceDictionary = rodDictionary;
+        this.it = new PushbackIterator<GATKFeature>(it);
+        records = new LinkedList<GATKFeature>();
+        // the following is a trick: we would like the iterator to know the actual name assigned to
+        // the ROD implementing object we are working with. But the only way to do that is to
+        // get an instance of that ROD and query it for its name. Now, the only generic way we have at this point to instantiate
+        // the ROD is to make the underlying stream iterator to do it for us. So we are reading (or rather peeking into)
+        // the first line of the track data file just to get the ROD object created.
+        GATKFeature r = null;
+        if (this.it.hasNext()) r = this.it.element();
+        name = (r==null?null:r.getName());
+
+        curr_contig = referenceDictionary.getSequence(0).getSequenceName();
+    }
+
+    /**
+     * Gets the header associated with the backing input stream.
+     * @return the ROD header.
+     */
+    @Override
+    public Object getHeader() {
+        return header;
+    }
+
+    /**
+     * Gets the sequence dictionary associated with the backing input stream.
+     * @return sequence dictionary from the ROD header.
+     */
+    @Override
+    public SAMSequenceDictionary getSequenceDictionary() {
+        return sequenceDictionary;
+    }
+
+
+    /**
+     * Returns true if the data we iterate over has records associated with (any, not necessarily adjacent)
+     * genomic position farther along the reference.
+     * @return
+     */
+    public boolean hasNext() {
+
+        // if we did not walk to the very end of the interval(s) covered by currently loaded
+        // annotations (records), then we definitely have data for next genomic location
+        if ( curr_position < max_position ) return true;
+
+        // we are past currently loaded stuff; we have next if there are more lines to load:
+        return it.hasNext();
+    }
+
+    // Returns point location (i.e. genome loc of length 1) on the reference, to which this iterator will advance
+    // upon next call to next().
+    public GenomeLoc peekNextLocation() {
+        if ( curr_position + 1 <= max_position ) return parser.createGenomeLoc(curr_contig,curr_position+1);
+
+        // sorry, next reference position is not covered by the RODs we are currently holding. In this case,
+        // the location we will jump to upon next call to next() is the start of the next ROD record that we did
+        // not read yet:
+        if ( it.hasNext() ) {
+            GATKFeature r = it.element(); // peek, do not load!
+            return parser.createGenomeLoc(r.getLocation().getContig(),r.getLocation().getStart());
+        }
+        return null; // underlying iterator has no more records, there is no next location!
+    }
+
+    /** Advances iterator to the next genomic position that has ROD record(s) associated with it,
+     * and returns all the records overlapping with that position as a RODList. The location of the whole
+     * RODList object will be set to the smallest interval subsuming genomic intervals of all returned records.
+     * Note that next() is disabled (will throw an exception) after seekForward() operation with query length > 1.
+     * @return list of all RODs overlapping with the next "covered" genomic position
+     */
+     public RODRecordList next() {
+         if ( ! next_is_allowed )
+             throw new ReviewedGATKException("Illegal use of iterator: Can not advance iterator with next() after seek-forward query of length > 1");
+
+         curr_position++;
+ //        curr_query_end = -1;
+
+         if ( curr_position <= max_position ) {
+
+             // we still have bases covered by at least one currently loaded record;
+             // we have to purge only subset of records, on which we moved past the end
+             purgeOutOfScopeRecords();
+         } else {
+             // ooops, we are past the end of all loaded records - kill them all at once,
+             // load next record and reinitialize by fastforwarding current position to the start of next record
+             records.clear();
+             GATKFeature r = it.next(); // if hasNext() previously returned true, we are guaranteed that this call to reader.next() is safe
+             records.add( r );
+             curr_contig = r.getLocation().getContig();
+             curr_position = r.getLocation().getStart();
+             max_position = r.getLocation().getStop();
+         }
+
+         // current position is ste and at this point 'records' only keeps those annotations, on which we did not reach the end yet
+         // (we might have reloaded records completely if it was necessary); but we are not guaranteed yet that we
+         // hold ALL the records overlapping with the current position. Time to check if we just walked into the interval(s)
+         // covered by new records, so we need to load them too:
+
+         while ( it.hasNext() ) {
+             GATKFeature r = it.element();
+             if ( r == null ) {
+                 it.next();
+                 continue;
+             }
+
+             GenomeLoc currentContig = parser.createOverEntireContig(curr_contig);
+             GenomeLoc thatContig = r.getLocation();
+
+             if ( currentContig.isPast(thatContig) )
+                 throw new UserException("LocationAwareSeekableRODIterator: contig " +r.getLocation().getContig() +
+                         " occurs out of order in track " + r.getName() );
+             if ( currentContig.isBefore(thatContig) ) break; // next record is on a higher contig, we do not need it yet...
+
+             if ( r.getLocation().getStart() < curr_position )
+                 throw new UserException("LocationAwareSeekableRODIterator: track "+r.getName() +
+                         " is out of coordinate order on contig "+r.getLocation() + " compared to " + curr_contig + ":" + curr_position);
+
+             if ( r.getLocation().getStart() > curr_position ) break; // next record starts after the current position; we do not need it yet
+
+             r = it.next(); // we got here only if we do need next record, time to load it for real
+
+             int stop = r.getLocation().getStop();
+             if ( stop < curr_position ) throw new ReviewedGATKException("DEBUG: encountered contig that should have been loaded earlier"); // this should never happen
+             if ( stop > max_position ) max_position = stop; // max_position keeps the rightmost stop position across all loaded records
+             records.add(r);
+         }
+
+         // 'records' and current position are fully updated. Last, we need to set the location of the whole track
+        // (collection of ROD records) to the genomic site we are currently looking at, and return the list
+
+         return new RODRecordListImpl(name,records, parser.createGenomeLoc(curr_contig,curr_position));
+     }
+
+    /**
+     * Removes from the underlying collection the last element returned by the
+     * iterator (optional operation).  This method can be called only once per
+     * call to <tt>next</tt>.  The behavior of an iterator is unspecified if
+     * the underlying collection is modified while the iteration is in
+     * progress in any way other than by calling this method.
+     *
+     * @throws UnsupportedOperationException if the <tt>remove</tt>
+     *                                       operation is not supported by this Iterator.
+     * @throws IllegalStateException         if the <tt>next</tt> method has not
+     *                                       yet been called, or the <tt>remove</tt> method has already
+     *                                       been called after the last call to the <tt>next</tt>
+     *                                       method.
+     */
+    public void remove() {
+        throw new UnsupportedOperationException("LocationAwareSeekableRODIterator does not implement remove() operation");
+    }
+
+
+    /**
+     * Returns the current "position" (not location!! ;) ) of this iterator. This method is used by the sharding
+     * system when it searches for available iterators in the pool that can be reused to resume traversal.
+     * When iterator is advanced using next(), current position
+     * is the same as 'location'. However, after a seekForward() query with extended interval, returned position
+     * will be set to the last position of the query interval, to disable (illegal) attempts to roll the iterator
+     * back and re-start traversal from current location.
+     * @return Current ending position of the iterator, or null if no position exists.
+     */
+    public GenomeLoc position() {
+        if ( curr_contig == null ) return null;
+        if ( curr_query_end > curr_position )  {
+            // do not attempt to reuse this iterator if the position we need it for lies before the end of last query performed
+            return parser.createGenomeLoc(curr_contig,curr_query_end,curr_query_end);
+        }
+        else {
+            return parser.createGenomeLoc(curr_contig,curr_position);
+        }
+    }
+
+    /**
+     * Seeks forward through the file until the specified interval is reached.
+     * The location object <code>interval</code> can be either a single point or an extended interval. All
+     * ROD records overlapping with the whole interval will be returned, or null if no such records exist.
+     *
+     * Query interval must start at or after the iterator's current location, or exception will be thrown.
+     *
+     * Query interval must end at or after the stop position of the previous query, if any, or an exception will
+     * be thrown: subsequent queries that end before the stop of previous ones are illegal.
+     *
+     * If seekForward() is performed to an extended (length > 1 i.e. start != stop) interval, next() operation becomes
+     * illegal (the iterator changes state). Only seekForward() calls are allowed thereafter, until a seekForward() call
+     * to a length-1 interval is performed, which re-enables next(). seekForward() queries with length-1 intervals can
+     * always be safely intermixed with next() (as long as ordering is respected and query intervals are at or after the
+     * current position).
+     *
+     * Note that in contrast to
+     * next() (which always advances current position of the iterator on the reference), this method scrolls
+     * forward ONLY if the specified interval is ahead of the current location of
+     * the iterator. However, if called again with the same 'interval' argument as before, seekForward will NOT
+     * advance, but will simply return the same ROD list as before.
+     *
+     *
+     * @param interval point-like genomic location to fastforward to.
+     * @return ROD object at (or overlapping with) the specified position, or null if no such ROD exists.
+     */
+    public RODRecordList seekForward(GenomeLoc interval) {
+
+        if ( interval.isBefore(parser.createOverEntireContig(curr_contig)) &&
+             !(interval.getStart() == 0 && interval.getStop() == 0 && interval.getContig().equals(curr_contig)) ) // This criteria is syntactic sugar for 'seek to right before curr_contig'
+            throw new ReviewedGATKException("Out of order query: query contig "+interval.getContig()+" is located before "+
+                                     "the iterator's current contig");
+        if ( interval.getContig().equals(curr_contig) ) {
+            if ( interval.getStart() < curr_position )
+                throw new ReviewedGATKException("Out of order query: query position "+interval +" is located before "+
+                        "the iterator's current position "+curr_contig + ":" + curr_position);
+            if ( interval.getStop() < curr_query_end )
+                throw new ReviewedGATKException("Unsupported querying sequence: current query interval " +
+                        interval+" ends before the end of previous query interval ("+curr_query_end+")");
+        }
+
+        curr_position = interval.getStart();
+        curr_query_end = interval.getStop();
+
+        next_is_allowed = ( curr_position == curr_query_end ); // we can call next() later only if interval length is 1
+
+        if (  interval.getContig().equals(curr_contig) &&  curr_position <= max_position ) {
+            // some of the intervals we are currently keeping do overlap with the query interval
+
+            purgeOutOfScopeRecords();
+        } else {
+            // clean up and get ready for fast-forwarding towards the requested position
+            records.clear();
+            max_position = -1;
+            curr_contig = interval.getContig();
+        }
+
+        // curr_contig and curr_position are set to where we asked to scroll to
+
+        while ( it.hasNext() ) {
+            GATKFeature r = it.next();
+            if ( r == null ) continue;
+
+            GenomeLoc currentContig = parser.createOverEntireContig(curr_contig);
+            GenomeLoc thatContig = r.getLocation();
+
+            if ( currentContig.isPast(thatContig) ) continue; // did not reach requested contig yet
+            if ( currentContig.isBefore(thatContig) ) {
+                it.pushback(r); // next record is on the higher contig, we do not need it yet...
+                break;
+            }
+
+            // we get here if we are on the requested contig:
+
+            if ( r.getLocation().getStop() < curr_position ) continue; // did not reach the requested interval yet
+
+            if ( r.getLocation().getStart() > curr_query_end ) {
+                // past the query interval
+                it.pushback(r);
+                break;
+            }
+
+            // we get here only if interval of the record r overlaps with query interval, so the record should be loaded
+            if ( r.getLocation().getStop() > max_position ) max_position = r.getLocation().getStop();
+            records.add(r);
+        }
+
+        if ( records.size() > 0 ) {
+            return new RODRecordListImpl(name,records,interval);
+        } else {
+            return null;
+        }
+
+    }
+
+    /**
+     * Removes records that end before the curr_position from the list of currently kept records. This is a
+     * convenience (private) shortcut that does not perform extensive checking. In particular, it assumes that
+     * curr_position <= max_position, as well as that we are still on the same contig.
+     */
+    private void purgeOutOfScopeRecords() {
+        Iterator<GATKFeature> i = records.iterator();
+        while ( i.hasNext() ) {
+            GATKFeature r = i.next();
+            if ( r.getLocation().getStop() < curr_position ) {
+                i.remove(); // we moved past the end of interval the record r is associated with, purge the record forever
+            }
+        }
+
+    }
+
+    @Override
+    public void close() {
+        if (this.it != null) ((CloseableIterator)this.it.getUnderlyingIterator()).close();
+    }
+
+}
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/refdata/VariantContextAdaptors.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/refdata/VariantContextAdaptors.java
new file mode 100644
index 0000000..82a826c
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/refdata/VariantContextAdaptors.java
@@ -0,0 +1,399 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.engine.refdata;
+
+import htsjdk.samtools.util.SequenceUtil;
+import htsjdk.tribble.Feature;
+import htsjdk.tribble.annotation.Strand;
+import htsjdk.tribble.dbsnp.OldDbSNPFeature;
+import htsjdk.tribble.gelitext.GeliTextFeature;
+import org.broadinstitute.gatk.engine.contexts.ReferenceContext;
+import org.broadinstitute.gatk.utils.GenomeLoc;
+import org.broadinstitute.gatk.utils.classloader.PluginManager;
+import org.broadinstitute.gatk.utils.codecs.hapmap.RawHapMapFeature;
+import org.broadinstitute.gatk.utils.variant.GATKVariantContextUtils;
+import htsjdk.variant.variantcontext.*;
+
+import java.util.*;
+
+/**
+ * A terrible but temporary approach to converting objects to VariantContexts.  If you want to add a converter,
+ * you need to create a adaptor object here and register a converter from your class to this object.  When tribble arrives,
+ * we'll use a better approach.
+ *
+ * To add a new converter:
+ *
+ *   create a subclass of VCAdaptor, overloading the convert operator
+ *   add it to the static map from input type -> converter where the input type is the object.class you want to convert
+ *
+ * That's it 
+ *
+ * @author depristo at broadinstitute.org
+ */
+public class VariantContextAdaptors {
+    // --------------------------------------------------------------------------------------------------------------
+    //
+    // Generic support routines.  Do not modify
+    //
+    // --------------------------------------------------------------------------------------------------------------
+
+    private static Map<Class<? extends Feature>,VCAdaptor> adaptors = new HashMap<Class<? extends Feature>,VCAdaptor>();
+
+    static {
+        PluginManager<VCAdaptor> vcAdaptorManager = new PluginManager<VCAdaptor>(VCAdaptor.class);
+        List<VCAdaptor> adaptorInstances = vcAdaptorManager.createAllTypes();
+        for(VCAdaptor adaptor: adaptorInstances)
+            adaptors.put(adaptor.getAdaptableFeatureType(),adaptor);
+    }
+
+    public static boolean canBeConvertedToVariantContext(Object variantContainingObject) {
+        return adaptors.containsKey(variantContainingObject.getClass());
+    }
+
+    /** generic superclass */
+    public interface VCAdaptor {
+        /**
+         * Gets the type of feature that this adaptor can 'adapt' into a VariantContext.
+         * @return Type of adaptable feature.  Must be a Tribble feature class.
+         */
+        Class<? extends Feature> getAdaptableFeatureType();
+        VariantContext convert(String name, Object input, ReferenceContext ref);
+    }
+
+    public static VariantContext toVariantContext(String name, Object variantContainingObject, ReferenceContext ref) {
+        if ( ! adaptors.containsKey(variantContainingObject.getClass()) )
+            return null;
+        else {
+            return adaptors.get(variantContainingObject.getClass()).convert(name, variantContainingObject, ref);
+        }
+    }
+
+    // --------------------------------------------------------------------------------------------------------------
+    //
+    // From here below you can add adaptor classes for new rods (or other types) to convert to VC
+    //
+    // --------------------------------------------------------------------------------------------------------------
+    private static class VariantContextAdaptor implements VCAdaptor {
+        /**
+         * 'Null' adaptor; adapts variant contexts to variant contexts.
+         * @return VariantContext.
+         */
+        @Override
+        public Class<? extends Feature> getAdaptableFeatureType() { return VariantContext.class; }
+
+        // already a VC, just cast and return it
+        @Override        
+        public VariantContext convert(String name, Object input, ReferenceContext ref) {
+            return (VariantContext)input;
+        }
+    }
+
+    // --------------------------------------------------------------------------------------------------------------
+    //
+    // dbSNP to VariantContext
+    //
+    // --------------------------------------------------------------------------------------------------------------
+
+    private static class DBSnpAdaptor implements VCAdaptor {
+        private static boolean isSNP(OldDbSNPFeature feature) {
+            return feature.getVariantType().contains("single") && feature.getLocationType().contains("exact");
+        }
+
+        private static boolean isMNP(OldDbSNPFeature feature) {
+            return feature.getVariantType().contains("mnp") && feature.getLocationType().contains("range");
+        }
+
+        private static boolean isInsertion(OldDbSNPFeature feature) {
+            return feature.getVariantType().contains("insertion");
+        }
+
+        private static boolean isDeletion(OldDbSNPFeature feature) {
+            return feature.getVariantType().contains("deletion");
+        }
+
+        private static boolean isIndel(OldDbSNPFeature feature) {
+            return isInsertion(feature) || isDeletion(feature) || isComplexIndel(feature);
+        }
+
+        public static boolean isComplexIndel(OldDbSNPFeature feature) {
+            return feature.getVariantType().contains("in-del");
+        }
+
+        /**
+         * gets the alternate alleles.  This method should return all the alleles present at the location,
+         * NOT including the reference base.  This is returned as a string list with no guarantee ordering
+         * of alleles (i.e. the first alternate allele is not always going to be the allele with the greatest
+         * frequency).
+         *
+         * @return an alternate allele list
+         */
+        public static List<String> getAlternateAlleleList(OldDbSNPFeature feature) {
+            List<String> ret = new ArrayList<String>();
+            for (String allele : getAlleleList(feature))
+                if (!allele.equals(String.valueOf(feature.getNCBIRefBase()))) ret.add(allele);
+            return ret;
+        }
+
+        /**
+         * gets the alleles.  This method should return all the alleles present at the location,
+         * including the reference base.  The first allele should always be the reference allele, followed
+         * by an unordered list of alternate alleles.
+         *
+         * @return an alternate allele list
+         */
+        public static List<String> getAlleleList(OldDbSNPFeature feature) {
+            List<String> alleleList = new ArrayList<String>();
+            // add ref first
+            if ( feature.getStrand() == Strand.POSITIVE )
+                alleleList = Arrays.asList(feature.getObserved());
+            else
+                for (String str : feature.getObserved())
+                    alleleList.add(SequenceUtil.reverseComplement(str));
+            if ( alleleList.size() > 0 && alleleList.contains(feature.getNCBIRefBase())
+                    && !alleleList.get(0).equals(feature.getNCBIRefBase()) )
+                Collections.swap(alleleList, alleleList.indexOf(feature.getNCBIRefBase()), 0);
+
+            return alleleList;
+        }
+
+        /**
+         * Converts non-VCF formatted dbSNP records to VariantContext. 
+         * @return OldDbSNPFeature.
+         */
+        @Override
+        public Class<? extends Feature> getAdaptableFeatureType() { return OldDbSNPFeature.class; }
+
+        @Override        
+        public VariantContext convert(String name, Object input, ReferenceContext ref) {
+            OldDbSNPFeature dbsnp = (OldDbSNPFeature)input;
+
+            int index = dbsnp.getStart() - ref.getWindow().getStart() - 1;
+            if ( index < 0 )
+                return null; // we weren't given enough reference context to create the VariantContext
+
+            final byte refBaseForIndel = ref.getBases()[index];
+            final boolean refBaseIsDash = dbsnp.getNCBIRefBase().equals("-");
+
+            boolean addPaddingBase;
+            if ( isSNP(dbsnp) || isMNP(dbsnp) )
+                addPaddingBase = false;
+            else if ( isIndel(dbsnp) || dbsnp.getVariantType().contains("mixed") )
+                addPaddingBase = refBaseIsDash || GATKVariantContextUtils.requiresPaddingBase(stripNullDashes(getAlleleList(dbsnp)));
+            else
+                return null; // can't handle anything else
+
+            Allele refAllele;
+            if ( refBaseIsDash )
+                refAllele = Allele.create(refBaseForIndel, true);
+            else if ( ! Allele.acceptableAlleleBases(dbsnp.getNCBIRefBase()) )
+                return null;
+            else
+                refAllele = Allele.create((addPaddingBase ? (char)refBaseForIndel : "") + dbsnp.getNCBIRefBase(), true);
+
+            final List<Allele> alleles = new ArrayList<Allele>();
+            alleles.add(refAllele);
+
+            // add all of the alt alleles
+            for ( String alt : getAlternateAlleleList(dbsnp) ) {
+                if ( Allele.wouldBeNullAllele(alt.getBytes()))
+                    alt = "";
+                else if ( ! Allele.acceptableAlleleBases(alt) )
+                    return null;
+
+                alleles.add(Allele.create((addPaddingBase ? (char)refBaseForIndel : "") + alt, false));
+            }
+
+            final VariantContextBuilder builder = new VariantContextBuilder();
+            builder.source(name).id(dbsnp.getRsID());
+            builder.loc(dbsnp.getChr(), dbsnp.getStart() - (addPaddingBase ? 1 : 0), dbsnp.getEnd() - (addPaddingBase && refAllele.length() == 1 ? 1 : 0));
+            builder.alleles(alleles);
+            return builder.make();
+        }
+
+        private static List<String> stripNullDashes(final List<String> alleles) {
+            final List<String> newAlleles = new ArrayList<String>(alleles.size());
+            for ( final String allele : alleles ) {
+                if ( allele.equals("-") )
+                    newAlleles.add("");
+                else
+                    newAlleles.add(allele);
+            }
+            return newAlleles;
+        }
+    }
+
+    // --------------------------------------------------------------------------------------------------------------
+    //
+    // GELI to VariantContext
+    //
+    // --------------------------------------------------------------------------------------------------------------
+
+    private static class GeliTextAdaptor implements VCAdaptor {
+        /**
+         * Converts Geli text records to VariantContext. 
+         * @return GeliTextFeature.
+         */
+        @Override
+        public Class<? extends Feature> getAdaptableFeatureType() { return GeliTextFeature.class; }
+
+        /**
+         * convert to a Variant Context, given:
+         * @param name  the name of the ROD
+         * @param input the Rod object, in this case a RodGeliText
+         * @param ref   the reference context
+         * @return a VariantContext object
+         */
+        @Override
+        public VariantContext convert(String name, Object input, ReferenceContext ref) {
+            GeliTextFeature geli = (GeliTextFeature)input;
+            if ( ! Allele.acceptableAlleleBases(String.valueOf(geli.getRefBase())) )
+                return null;
+            Allele refAllele = Allele.create(String.valueOf(geli.getRefBase()), true);
+
+            // make sure we can convert it
+            if ( geli.getGenotype().isHet() || !geli.getGenotype().containsBase(geli.getRefBase())) {
+                // add the reference allele
+                List<Allele> alleles = new ArrayList<Allele>();
+                List<Allele> genotypeAlleles = new ArrayList<Allele>();
+                // add all of the alt alleles
+                for ( char alt : geli.getGenotype().toString().toCharArray() ) {
+                    if ( ! Allele.acceptableAlleleBases(String.valueOf(alt)) ) {
+                        return null;
+                    }
+                    Allele allele = Allele.create(String.valueOf(alt), false);
+                    if (!alleles.contains(allele) && !refAllele.basesMatch(allele.getBases())) alleles.add(allele);
+
+                    // add the allele, first checking if it's reference or not
+                    if (!refAllele.basesMatch(allele.getBases())) genotypeAlleles.add(allele);
+                    else genotypeAlleles.add(refAllele);
+                }
+
+                Map<String, Object> attributes = new HashMap<String, Object>();
+                Collection<Genotype> genotypes = new ArrayList<Genotype>();
+                Genotype call = GenotypeBuilder.create(name, genotypeAlleles);
+
+                // add the call to the genotype list, and then use this list to create a VariantContext
+                genotypes.add(call);
+                alleles.add(refAllele);
+                GenomeLoc loc = ref.getGenomeLocParser().createGenomeLoc(geli.getChr(),geli.getStart());
+                return new VariantContextBuilder(name, loc.getContig(), loc.getStart(), loc.getStop(), alleles).genotypes(genotypes).log10PError(-1 * geli.getLODBestToReference()).attributes(attributes).make();
+            } else
+                return null; // can't handle anything else
+        }
+    }
+
+    // --------------------------------------------------------------------------------------------------------------
+    //
+    // HapMap to VariantContext
+    //
+    // --------------------------------------------------------------------------------------------------------------
+
+    private static class HapMapAdaptor implements VCAdaptor {
+        /**
+         * Converts HapMap records to VariantContext. 
+         * @return HapMapFeature.
+         */
+        @Override
+        public Class<? extends Feature> getAdaptableFeatureType() { return RawHapMapFeature.class; }
+
+        /**
+         * convert to a Variant Context, given:
+         * @param name  the name of the ROD
+         * @param input the Rod object, in this case a RodGeliText
+         * @param ref   the reference context
+         * @return a VariantContext object
+         */
+        @Override        
+        public VariantContext convert(String name, Object input, ReferenceContext ref) {
+            if ( ref == null )
+                throw new UnsupportedOperationException("Conversion from HapMap to VariantContext requires a reference context");
+
+            RawHapMapFeature hapmap = (RawHapMapFeature)input;
+
+            int index = hapmap.getStart() - ref.getWindow().getStart();
+            if ( index < 0 )
+                return null; // we weren't given enough reference context to create the VariantContext
+
+            HashSet<Allele> alleles = new HashSet<Allele>();
+            Allele refSNPAllele = Allele.create(ref.getBase(), true);
+            int deletionLength = -1;
+
+            Map<String, Allele> alleleMap = hapmap.getActualAlleles();
+            // use the actual alleles, if available
+            if ( alleleMap != null ) {
+                alleles.addAll(alleleMap.values());
+                Allele deletionAllele = alleleMap.get(RawHapMapFeature.INSERTION);  // yes, use insertion here (since we want the reference bases)
+                if ( deletionAllele != null && deletionAllele.isReference() )
+                    deletionLength = deletionAllele.length();
+            } else {
+                // add the reference allele for SNPs
+                alleles.add(refSNPAllele);
+            }
+
+            // make a mapping from sample to genotype
+            String[] samples = hapmap.getSampleIDs();
+            String[] genotypeStrings = hapmap.getGenotypes();
+
+            GenotypesContext genotypes = GenotypesContext.create(samples.length);
+            for ( int i = 0; i < samples.length; i++ ) {
+                // ignore bad genotypes
+                if ( genotypeStrings[i].contains("N") )
+                    continue;
+
+                String a1 = genotypeStrings[i].substring(0,1);
+                String a2 = genotypeStrings[i].substring(1);
+                ArrayList<Allele> myAlleles = new ArrayList<Allele>(2);
+
+                // use the mapping to actual alleles, if available
+                if ( alleleMap != null ) {
+                    myAlleles.add(alleleMap.get(a1));
+                    myAlleles.add(alleleMap.get(a2));
+                } else {
+                    // ignore indels (which we can't handle without knowing the alleles)
+                    if ( genotypeStrings[i].contains("I") || genotypeStrings[i].contains("D") )
+                        continue;
+
+                    Allele allele1 = Allele.create(a1, refSNPAllele.basesMatch(a1));
+                    Allele allele2 = Allele.create(a2, refSNPAllele.basesMatch(a2));
+
+                    myAlleles.add(allele1);
+                    myAlleles.add(allele2);
+                    alleles.add(allele1);
+                    alleles.add(allele2);
+                }
+
+                Genotype g = GenotypeBuilder.create(samples[i], myAlleles);
+                genotypes.add(g);
+            }
+
+            long end = hapmap.getEnd();
+            if ( deletionLength > 0 )
+                end += (deletionLength - 1);
+            VariantContext vc = new VariantContextBuilder(name, hapmap.getChr(), hapmap.getStart(), end, alleles).id(hapmap.getName()).genotypes(genotypes).make();
+            return vc;
+       }
+    }
+}
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/refdata/package-info.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/refdata/package-info.java
new file mode 100644
index 0000000..e9e9714
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/refdata/package-info.java
@@ -0,0 +1,26 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.engine.refdata;
\ No newline at end of file
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/refdata/tracks/FeatureManager.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/refdata/tracks/FeatureManager.java
new file mode 100644
index 0000000..d466f3f
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/refdata/tracks/FeatureManager.java
@@ -0,0 +1,280 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.engine.refdata.tracks;
+
+import com.google.java.contract.Ensures;
+import com.google.java.contract.Requires;
+import htsjdk.tribble.Feature;
+import htsjdk.tribble.FeatureCodec;
+import htsjdk.tribble.NameAwareCodec;
+import org.broadinstitute.gatk.engine.refdata.ReferenceDependentFeatureCodec;
+import org.broadinstitute.gatk.engine.refdata.utils.RMDTriplet;
+import org.broadinstitute.gatk.utils.GenomeLocParser;
+import org.broadinstitute.gatk.utils.classloader.PluginManager;
+import htsjdk.variant.vcf.AbstractVCFCodec;
+import org.broadinstitute.gatk.utils.exceptions.ReviewedGATKException;
+import org.broadinstitute.gatk.utils.help.GATKDocUtils;
+
+import java.io.File;
+import java.util.*;
+
+
+/**
+ * Class for managing Tribble Feature readers available to the GATK.  The features
+ * are dynamically determined via a PluginManager.  This class provides convenient
+ * getter methods for obtaining FeatureDescriptor objects that collect all of the
+ * useful information about the Tribble Codec, Feature, and name in one place.
+ *
+ * @author depristo
+ */
+public class FeatureManager  {
+    public static class FeatureDescriptor implements Comparable<FeatureDescriptor> {
+        final String name;
+        final FeatureCodec codec;
+
+        public FeatureDescriptor(final String name, final FeatureCodec codec) {
+            this.name = name;
+            this.codec = codec;
+        }
+
+        public String getName() {
+            return name;
+        }
+        public String getSimpleFeatureName() { return getFeatureClass().getSimpleName(); }
+        public FeatureCodec getCodec() {
+            return codec;
+        }
+        public Class getCodecClass() { return codec.getClass(); }
+        public Class getFeatureClass() { return codec.getFeatureType(); }
+
+        @Override
+        public String toString() {
+            return String.format("FeatureDescriptor name=%s codec=%s feature=%s",
+                    getName(), getCodecClass().getName(), getFeatureClass().getName());
+        }
+
+        @Override
+        public int compareTo(FeatureDescriptor o) {
+            return getName().compareTo(o.getName());
+        }
+    }
+
+    private final PluginManager<FeatureCodec> pluginManager;
+    private final Collection<FeatureDescriptor> featureDescriptors = new TreeSet<FeatureDescriptor>();
+    private final boolean lenientVCFProcessing;
+
+    /**
+     * Construct a FeatureManager without a master VCF header
+     */
+    public FeatureManager() {
+        this(false);
+    }
+
+    public FeatureManager(final boolean lenientVCFProcessing) {
+        this.lenientVCFProcessing = lenientVCFProcessing;
+        pluginManager = new PluginManager<FeatureCodec>(FeatureCodec.class, "Codecs", "Codec");
+
+        for (final String rawName: pluginManager.getPluginsByName().keySet()) {
+            FeatureCodec codec = pluginManager.createByName(rawName);
+            String name = rawName.toUpperCase();
+            FeatureDescriptor featureDescriptor = new FeatureDescriptor(name, codec);
+            featureDescriptors.add(featureDescriptor);
+        }
+    }
+
+    /**
+     * Return the FeatureDescriptor whose getCodecClass().equals(codecClass).
+     *
+     * @param codecClass
+     * @return A FeatureDescriptor or null if none is found
+     */
+    @Requires("codecClass != null")
+    public FeatureDescriptor getByCodec(Class codecClass) {
+        for ( FeatureDescriptor descriptor : featureDescriptors )
+            if ( descriptor.getCodecClass().equals(codecClass) )
+                return descriptor;
+        return null;
+    }
+
+    /**
+     * Returns a collection of FeatureDescriptors that emit records of type featureClass
+     *
+     * @param featureClass
+     * @return A FeatureDescriptor or null if none is found
+     */
+    @Requires("featureClass != null")
+    public <T extends Feature> Collection<FeatureDescriptor> getByFeature(Class<T> featureClass) {
+        Set<FeatureDescriptor> consistentDescriptors = new TreeSet<FeatureDescriptor>();
+
+        if (featureClass == null)
+            throw new IllegalArgumentException("trackRecordType value is null, please pass in an actual class object");
+
+        for ( FeatureDescriptor descriptor : featureDescriptors ) {
+            if ( featureClass.isAssignableFrom(descriptor.getFeatureClass()))
+                consistentDescriptors.add(descriptor);
+        }
+        return consistentDescriptors;
+    }
+
+    /**
+     * Return the FeatureDescriptor with getID().equals(name)
+     *
+     * @param name
+     * @return A FeatureDescriptor or null if none is found
+     */
+    @Requires("name != null")
+    public FeatureDescriptor getByName(String name) {
+        for ( FeatureDescriptor descriptor : featureDescriptors )
+            if ( descriptor.getName().equalsIgnoreCase(name) )
+                return descriptor;
+        return null;
+    }
+
+    /**
+     * Returns the FeatureDescriptor that can read the contexts of File file, is one can be determined
+     *
+     * @param file
+     * @return A FeatureDescriptor or null if none is found
+     */
+    @Requires({"file != null", "file.isFile()", "file.canRead()"})
+    public FeatureDescriptor getByFiletype(File file) {
+        List<FeatureDescriptor> canParse = new ArrayList<FeatureDescriptor>();
+        for ( FeatureDescriptor descriptor : featureDescriptors )
+            if ( descriptor.getCodec().canDecode(file.getPath()) ) {
+                canParse.add(descriptor);
+            }
+
+        if ( canParse.size() == 0 )
+            return null;
+        else if ( canParse.size() > 1 )
+            throw new ReviewedGATKException("BUG: multiple feature descriptors can read file " + file + ": " + canParse);
+        else
+            return canParse.get(0);
+    }
+
+    /**
+     * Returns the FeatureDescriptor associated with the type described by triplet, or null if none is found
+     * @param triplet
+     * @return
+     */
+    @Requires("triplet != null")
+    public FeatureDescriptor getByTriplet(RMDTriplet triplet) {
+        return getByName(triplet.getType());
+    }
+
+    /**
+     * @return all of the FeatureDescriptors available to the GATK.  Never null
+     */
+    @Ensures("result != null")
+    public Collection<FeatureDescriptor> getFeatureDescriptors() {
+        return Collections.unmodifiableCollection(featureDescriptors);
+    }
+
+
+    /**
+     * Returns a list of the available tribble track names (vcf,dbsnp,etc) that we can load
+     * @return
+     */
+    @Ensures("result != null")
+    public String userFriendlyListOfAvailableFeatures() {
+        return userFriendlyListOfAvailableFeatures(Feature.class);
+    }
+
+    /**
+     * Returns a list of the available tribble track names (vcf,dbsnp,etc) that we can load
+     * restricted to only Codecs producting Features consistent with the requiredFeatureType
+     * @return
+     */
+    @Ensures("result != null")
+    public String userFriendlyListOfAvailableFeatures(Class<? extends Feature> requiredFeatureType) {
+        final String nameHeader="Name", featureHeader = "FeatureType", docHeader="Documentation";
+
+        int maxNameLen = nameHeader.length(), maxFeatureNameLen = featureHeader.length();
+        for ( final FeatureDescriptor descriptor : featureDescriptors ) {
+            if ( requiredFeatureType.isAssignableFrom(descriptor.getFeatureClass()) ) {
+                maxNameLen = Math.max(maxNameLen, descriptor.getName().length());
+                maxFeatureNameLen = Math.max(maxFeatureNameLen, descriptor.getSimpleFeatureName().length());
+            }
+        }
+
+        StringBuilder docs = new StringBuilder();
+        String format = "%" + maxNameLen + "s   %" + maxFeatureNameLen + "s   %s%n";
+        docs.append(String.format(format, nameHeader, featureHeader, docHeader));
+        for ( final FeatureDescriptor descriptor : featureDescriptors ) {
+            if ( requiredFeatureType.isAssignableFrom(descriptor.getFeatureClass()) ) {
+                final String DocURL = GATKDocUtils.helpLinksToGATKDocs(descriptor.getCodecClass());
+                final String oneDoc;
+                if ( DocURL.contains("_sting_") ) {
+                    oneDoc = String.format(format,
+                            descriptor.getName(),
+                            descriptor.getSimpleFeatureName(),
+                            DocURL);
+                } else {
+                    oneDoc = String.format(format,
+                            descriptor.getName(),
+                            descriptor.getSimpleFeatureName(),
+                            "(this is an external codec and is not documented within GATK)");
+                }
+
+                docs.append(oneDoc);
+            }
+        }
+
+        return docs.toString();
+    }
+
+    /**
+     * Create a new FeatureCodec of the type described in descriptor, assigning it the
+     * name (if possible) and providing it the genomeLocParser (where necessary)
+     *
+     * @param descriptor FeatureDescriptor of the Tribble FeatureCodec we want to create
+     * @param name the name to assign this codec
+     * @param genomeLocParser GenomeLocParser for ReferenceDependentFeatureCodecs
+     * @param remappedSampleName replacement sample name for single-sample vcfs, or null if we're not performing
+     *                           sample name remapping
+     * @return the feature codec itself
+     */
+    @Requires({"descriptor != null", "name != null", "genomeLocParser != null"})
+    @Ensures("result != null")
+    public FeatureCodec createCodec(final FeatureDescriptor descriptor, final String name, final GenomeLocParser genomeLocParser,
+                                    final String remappedSampleName) {
+        FeatureCodec codex = pluginManager.createByType(descriptor.getCodecClass());
+        if ( codex instanceof NameAwareCodec )
+            ((NameAwareCodec)codex).setName(name);
+        if ( codex instanceof ReferenceDependentFeatureCodec )
+            ((ReferenceDependentFeatureCodec)codex).setGenomeLocParser(genomeLocParser);
+        if ( codex instanceof AbstractVCFCodec ) {
+            if ( lenientVCFProcessing ) {
+                ((AbstractVCFCodec)codex).disableOnTheFlyModifications();
+            }
+            if ( remappedSampleName != null ) {
+                ((AbstractVCFCodec)codex).setRemappedSampleName(remappedSampleName);
+            }
+        }
+
+        return codex;
+    }
+}
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/refdata/tracks/IndexDictionaryUtils.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/refdata/tracks/IndexDictionaryUtils.java
new file mode 100644
index 0000000..5c18d3a
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/refdata/tracks/IndexDictionaryUtils.java
@@ -0,0 +1,114 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.engine.refdata.tracks;
+
+import htsjdk.samtools.SAMSequenceDictionary;
+import htsjdk.samtools.SAMSequenceRecord;
+import org.apache.log4j.Logger;
+import htsjdk.tribble.index.Index;
+import htsjdk.tribble.index.MutableIndex;
+import org.broadinstitute.gatk.engine.arguments.ValidationExclusion;
+import org.broadinstitute.gatk.utils.SequenceDictionaryUtils;
+
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.TreeSet;
+
+/**
+ * Utilities for working with Sequence Dictionaries embedded in tribble indices
+ *
+ * @author Your Name
+ * @since Date created
+ */
+public class IndexDictionaryUtils {
+    private final static Logger logger = Logger.getLogger(IndexDictionaryUtils.class);
+
+    // a constant we use for marking sequence dictionary entries in the Tribble index property list
+    public static final String SequenceDictionaryPropertyPredicate = "DICT:";
+
+    /**
+     * get the sequence dictionary from the track, if available.  If not, make it from the contig list that is always in the index
+     * @param index the index file to use
+     * @return a SAMSequenceDictionary if available, null if unavailable
+     */
+    public static SAMSequenceDictionary getSequenceDictionaryFromProperties(Index index) {
+        SAMSequenceDictionary dict = new SAMSequenceDictionary();
+        for (Map.Entry<String,String> entry : index.getProperties().entrySet()) {
+            if (entry.getKey().startsWith(SequenceDictionaryPropertyPredicate))
+                dict.addSequence(new SAMSequenceRecord(entry.getKey().substring(SequenceDictionaryPropertyPredicate.length() , entry.getKey().length()),
+                        Integer.valueOf(entry.getValue())));
+        }
+        return dict;
+    }
+
+    /**
+     * create the sequence dictionary with the contig list; a backup approach
+     * @param index the index file to use
+     * @param dict the sequence dictionary to add contigs to
+     * @return the filled-in sequence dictionary
+     */
+    static SAMSequenceDictionary createSequenceDictionaryFromContigList(final Index index, final SAMSequenceDictionary dict) {
+        final List<String> seqNames = index.getSequenceNames();
+        if (seqNames == null) {
+            return dict;
+        }
+        for (final String name : seqNames) {
+            SAMSequenceRecord seq = new SAMSequenceRecord(name, 0);
+            dict.addSequence(seq);
+        }
+        return dict;
+    }
+
+    /**
+     *  Sets the sequence dictionary of the given index.  THE INDEX MUST BE MUTABLE (i.e. not Tabix).
+     *
+     * @param index the (mutable) index file to use
+     * @param dict  the dictionary to use
+     */
+    public static void setIndexSequenceDictionary(Index index, SAMSequenceDictionary dict) {
+        for ( SAMSequenceRecord seq : dict.getSequences() ) {
+            final String contig = IndexDictionaryUtils.SequenceDictionaryPropertyPredicate + seq.getSequenceName();
+            final String length = String.valueOf(seq.getSequenceLength());
+            ((MutableIndex)index).addProperty(contig, length);
+        }
+    }
+
+    public static void validateTrackSequenceDictionary(final String trackName,
+                                                       final SAMSequenceDictionary trackDict,
+                                                       final SAMSequenceDictionary referenceDict,
+                                                       final ValidationExclusion.TYPE validationExclusionType ) {
+        // if the sequence dictionary is empty (as well as null which means it doesn't have a dictionary), skip validation
+        if (trackDict == null || trackDict.size() == 0)
+            logger.warn("Track " + trackName + " doesn't have a sequence dictionary built in, skipping dictionary validation");
+        else {
+            Set<String> trackSequences = new TreeSet<String>();
+            for (SAMSequenceRecord dictionaryEntry : trackDict.getSequences())
+                trackSequences.add(dictionaryEntry.getSequenceName());
+            SequenceDictionaryUtils.validateDictionaries(logger, validationExclusionType, trackName, trackDict, "reference", referenceDict, false, null);
+        }
+    }
+}
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/refdata/tracks/RMDTrack.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/refdata/tracks/RMDTrack.java
new file mode 100644
index 0000000..51cb8f4
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/refdata/tracks/RMDTrack.java
@@ -0,0 +1,147 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.engine.refdata.tracks;
+
+import htsjdk.samtools.SAMSequenceDictionary;
+import htsjdk.samtools.util.CloseableIterator;
+import org.apache.log4j.Logger;
+import htsjdk.tribble.AbstractFeatureReader;
+import htsjdk.tribble.CloseableTribbleIterator;
+import htsjdk.tribble.Feature;
+import htsjdk.tribble.FeatureCodec;
+import org.broadinstitute.gatk.engine.refdata.utils.FeatureToGATKFeatureIterator;
+import org.broadinstitute.gatk.engine.refdata.utils.GATKFeature;
+import org.broadinstitute.gatk.utils.GenomeLoc;
+import org.broadinstitute.gatk.utils.GenomeLocParser;
+import org.broadinstitute.gatk.utils.exceptions.UserException;
+
+import java.io.File;
+import java.io.IOException;
+
+
+/**
+ * @author aaron
+ *         <p/>
+ *         Class RMDTrack
+ *         <p/>
+ *         the basics of what a reference metadata track must contain.
+ */
+public class RMDTrack {
+    private final static Logger logger = Logger.getLogger(RMDTrackBuilder.class);
+
+    // the basics of a track:
+    private final Class type;           // our type
+    private final String name;          // the name
+    private final File file;            // the associated file we create the reader from
+
+    // our feature reader - allows queries
+    private AbstractFeatureReader reader;
+
+    // our sequence dictionary, which can be null
+    private final SAMSequenceDictionary dictionary;
+
+    /**
+     * Parser to use when creating/parsing GenomeLocs.
+     */
+    private final GenomeLocParser genomeLocParser;
+
+    // our codec type
+    private final FeatureCodec codec;
+
+    public Class getType() {
+        return type;
+    }
+
+    public String getName() {
+        return name;
+    }
+
+    public File getFile() {
+        return file;
+    }
+
+    /**
+     * Create a track
+     *
+     * @param type the type of track, used for track lookup
+     * @param name the name of this specific track
+     * @param file the associated file, for reference or recreating the reader
+     * @param reader the feature reader to use as the underlying data source
+     * @param dict the sam sequence dictionary
+     * @param codec the feature codec we use to decode this type
+     */
+    public RMDTrack(Class type, String name, File file, AbstractFeatureReader reader, SAMSequenceDictionary dict, GenomeLocParser genomeLocParser, FeatureCodec codec) {
+        this.type = type;
+        this.name = name;
+        this.file = file;
+        this.reader = reader;
+        this.dictionary = dict;
+        this.genomeLocParser = genomeLocParser;
+        this.codec = codec;
+    }
+
+    /**
+     * @return how to get an iterator of the underlying data.  This is all a track has to support,
+     *         but other more advanced tracks support the query interface
+     */
+    public CloseableIterator<GATKFeature> getIterator() {
+        try {
+            return new FeatureToGATKFeatureIterator(genomeLocParser,reader.iterator(),this.getName());
+        } catch (IOException e) {
+            throw new UserException.CouldNotReadInputFile(getFile(), "Unable to read from file", e);
+        }
+    }
+
+    public CloseableIterator<GATKFeature> query(GenomeLoc interval) throws IOException {
+        CloseableTribbleIterator<Feature> iter = reader.query(interval.getContig(),interval.getStart(),interval.getStop());
+        return new FeatureToGATKFeatureIterator(genomeLocParser, iter, this.getName());
+    }
+
+    public void close() {
+        try {
+            reader.close();
+        } catch (IOException e) {
+            throw new UserException.MalformedFile("Unable to close reader " + reader.toString(),e);
+        }
+        reader = null;
+    }
+
+    /**
+     * get the sequence dictionary from the track, if available
+     * @return a SAMSequenceDictionary if available, null if unavailable
+     */
+    public SAMSequenceDictionary getSequenceDictionary() {
+        return dictionary;
+    }
+
+    public Object getHeader() {
+        return reader.getHeader();
+    }
+
+    public FeatureCodec getCodec() {
+        return codec;
+    }
+}
\ No newline at end of file
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/refdata/tracks/RMDTrackBuilder.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/refdata/tracks/RMDTrackBuilder.java
new file mode 100644
index 0000000..dc9e967
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/refdata/tracks/RMDTrackBuilder.java
@@ -0,0 +1,430 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.engine.refdata.tracks;
+
+import htsjdk.samtools.SAMSequenceDictionary;
+import org.apache.log4j.Logger;
+import htsjdk.tribble.AbstractFeatureReader;
+import htsjdk.tribble.FeatureCodec;
+import htsjdk.tribble.Tribble;
+import htsjdk.tribble.TribbleException;
+import htsjdk.tribble.index.Index;
+import htsjdk.tribble.index.IndexFactory;
+import htsjdk.tribble.util.LittleEndianOutputStream;
+import org.broadinstitute.gatk.utils.commandline.Tags;
+import org.broadinstitute.gatk.engine.GenomeAnalysisEngine;
+import org.broadinstitute.gatk.engine.arguments.ValidationExclusion;
+import org.broadinstitute.gatk.engine.io.stubs.VCFWriterArgumentTypeDescriptor;
+import org.broadinstitute.gatk.engine.refdata.utils.RMDTriplet;
+import org.broadinstitute.gatk.engine.refdata.utils.RMDTriplet.RMDStorageType;
+import org.broadinstitute.gatk.utils.GenomeLocParser;
+import org.broadinstitute.gatk.utils.collections.Pair;
+import org.broadinstitute.gatk.utils.exceptions.ReviewedGATKException;
+import org.broadinstitute.gatk.utils.exceptions.UserException;
+import org.broadinstitute.gatk.utils.file.FSLockWithShared;
+import org.broadinstitute.gatk.utils.instrumentation.Sizeof;
+
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.util.Map;
+
+
+/**
+ *
+ * @author aaron
+ *                                           `
+ * Class RMDTrackBuilder
+ *
+ * This class keeps track of the available codecs, and knows how to put together a track of
+ * that gets iterators from the FeatureReader using Tribble.
+ *
+ */
+public class RMDTrackBuilder { // extends PluginManager<FeatureCodec> {
+    /**
+     * our log, which we use to capture anything from this class
+     */
+    private final static Logger logger = Logger.getLogger(RMDTrackBuilder.class);
+
+    // private sequence dictionary we use to set our tracks with
+    private final SAMSequenceDictionary dict;
+
+    /**
+     * Private genome loc parser to use when building out new locs.
+     */
+    private final GenomeLocParser genomeLocParser;
+
+    /**
+     * Validation exclusions, for validating the sequence dictionary.
+     */
+    private ValidationExclusion.TYPE validationExclusionType;
+
+    private final FeatureManager featureManager;
+
+    // If true, do not attempt to create index files if they don't exist or are outdated, and don't
+    // make any file lock acquisition calls on the index files.
+    private final boolean disableAutoIndexCreation;
+
+    // Map of file name -> new sample name used when performing on-the-fly sample renaming
+    private final Map<String, String> sampleRenameMap;
+
+    /**
+     * Construct an RMDTrackerBuilder, allowing the user to define tracks to build after-the-fact.  This is generally
+     * used when walkers want to directly manage the ROD system for whatever reason.  Before using this constructor,
+     * please talk through your approach with the SE team.
+     * @param dict Sequence dictionary to use.
+     * @param genomeLocParser Location parser to use.
+     * @param validationExclusionType Types of validations to exclude, for sequence dictionary verification.
+     * @param disableAutoIndexCreation Do not auto-create index files, and do not use file locking when accessing index files.
+     *                                 UNSAFE in general (because it causes us not to lock index files before reading them) --
+     *                                 suitable only for test suite use.
+     * @param sampleRenameMap Map of file name -> new sample name used when performing on-the-fly sample renaming
+     */
+    public RMDTrackBuilder(final SAMSequenceDictionary dict,
+                           final GenomeLocParser genomeLocParser,
+                           final ValidationExclusion.TYPE validationExclusionType,
+                           final boolean disableAutoIndexCreation,
+                           final Map<String, String> sampleRenameMap) {
+        this.dict = dict;
+        this.validationExclusionType = validationExclusionType;
+        this.genomeLocParser = genomeLocParser;
+        this.featureManager = new FeatureManager(GenomeAnalysisEngine.lenientVCFProcessing(validationExclusionType));
+        this.disableAutoIndexCreation = disableAutoIndexCreation;
+        this.sampleRenameMap = sampleRenameMap;
+    }
+
+    /**
+     * Return the feature manager this RMDTrackBuilder is using the create tribble tracks
+     *
+     * @return
+     */
+    public FeatureManager getFeatureManager() {
+        return featureManager;
+    }
+
+    /**
+     * create a RMDTrack of the specified type
+     *
+     * @param fileDescriptor a description of the type of track to build.
+     *
+     * @return an instance of the track
+     */
+    public RMDTrack createInstanceOfTrack(RMDTriplet fileDescriptor) {
+        String name = fileDescriptor.getName();
+        File inputFile = new File(fileDescriptor.getFile());
+
+        FeatureManager.FeatureDescriptor descriptor = getFeatureManager().getByTriplet(fileDescriptor);
+        if (descriptor == null)
+            throw new UserException.BadArgumentValue("-B",fileDescriptor.getType());
+
+        // return a feature reader track
+        Pair<AbstractFeatureReader, SAMSequenceDictionary> pair;
+        if (VCFWriterArgumentTypeDescriptor.isCompressed(inputFile.toString()))
+            pair = createTabixIndexedFeatureSource(descriptor, name, inputFile);
+        else
+            pair = getFeatureSource(descriptor, name, inputFile, fileDescriptor.getStorageType());
+        if (pair == null) throw new UserException.CouldNotReadInputFile(inputFile, "Unable to make the feature reader for input file");
+        return new RMDTrack(descriptor.getCodecClass(), name, inputFile, pair.first, pair.second, genomeLocParser, createCodec(descriptor, name, inputFile));
+    }
+
+    /**
+     * Convenience method simplifying track creation.  Assume unnamed track based on a file rather than a stream.
+     * @param codecClass Type of Tribble codec class to build.
+     * @param inputFile Input file type to use.
+     * @return An RMDTrack, suitable for accessing reference metadata.
+     */
+    public RMDTrack createInstanceOfTrack(Class codecClass, File inputFile) {
+        final FeatureManager.FeatureDescriptor descriptor = getFeatureManager().getByCodec(codecClass);
+
+        if (descriptor == null)
+            throw new ReviewedGATKException("Unable to find type name for codec class " + codecClass.getName());
+
+        return createInstanceOfTrack(new RMDTriplet("anonymous",descriptor.getName(),inputFile.getAbsolutePath(),RMDStorageType.FILE,new Tags()));
+    }
+
+    /**
+     * create a feature reader, without assuming there exists an index.  This code assumes the feature
+     * reader of the appropriate type will figure out what the right index type is, and determine if it
+     * exists.
+     *
+     * @param descriptor the FeatureDescriptor describing the FeatureCodec we want to create
+     * @param name the name of the track
+     * @param inputFile the file to load
+     * @return a feature reader implementation
+     */
+    private Pair<AbstractFeatureReader, SAMSequenceDictionary> createTabixIndexedFeatureSource(FeatureManager.FeatureDescriptor descriptor, String name, File inputFile) {
+        // we might not know the index type, try loading with the default reader constructor
+        logger.debug("Attempting to load " + inputFile + " as a tabix indexed file without validating it");
+        try {
+            // getFeatureReader will detect that it's Tabix
+            return new Pair<>(AbstractFeatureReader.getFeatureReader(inputFile.getAbsolutePath(), createCodec(descriptor, name, inputFile)), null);
+        } catch (TribbleException e) {
+            throw new UserException(e.getMessage(), e);
+        }
+    }
+
+    /**
+     * add a name to the codec, if it takes one
+     * @param descriptor the class to create a codec for
+     * @param name the name to assign this codec
+     * @param inputFile input file that we will be decoding
+     * @return the feature codec itself
+     */
+    private FeatureCodec createCodec(final FeatureManager.FeatureDescriptor descriptor, final String name, final File inputFile) {
+        // The remappedSampleName will be null if either no on-the-fly sample renaming was requested,
+        // or the user's sample rename map file didn't contain an entry for this file:
+        final String remappedSampleName = sampleRenameMap != null ? sampleRenameMap.get(inputFile.getAbsolutePath()) : null;
+
+        return featureManager.createCodec(descriptor, name, genomeLocParser, remappedSampleName);
+    }
+
+    /**
+     * create a feature source object given:
+     * @param descriptor the FeatureDescriptor describing the FeatureCodec we want to create
+     * @param name the name of the codec
+     * @param inputFile the tribble file to parse
+     * @param storageType How the RMD is streamed into the input file.
+     * @return the input file as a FeatureReader
+     */
+    private Pair<AbstractFeatureReader, SAMSequenceDictionary> getFeatureSource(FeatureManager.FeatureDescriptor descriptor,
+                                                                        String name,
+                                                                        File inputFile,
+                                                                        RMDStorageType storageType) {
+        // Feature source and sequence dictionary to use as the ultimate reference
+        AbstractFeatureReader featureSource = null;
+        SAMSequenceDictionary sequenceDictionary = null;
+
+        // Detect whether or not this source should be indexed.
+        boolean canBeIndexed = (storageType == RMDStorageType.FILE);
+
+        if(canBeIndexed) {
+            try {
+                Index index = loadIndex(inputFile, createCodec(descriptor, name, inputFile));
+                try { logger.info(String.format("  Index for %s has size in bytes %d", inputFile, Sizeof.getObjectGraphSize(index))); }
+                catch (ReviewedGATKException e) { }
+
+                sequenceDictionary = IndexDictionaryUtils.getSequenceDictionaryFromProperties(index);
+
+                // if we don't have a dictionary in the Tribble file, and we've set a dictionary for this builder, set it in the file if they match
+                if (sequenceDictionary.size() == 0 && dict != null) {
+                    validateAndUpdateIndexSequenceDictionary(inputFile, index, dict);
+
+                    if ( ! disableAutoIndexCreation ) {
+                        File indexFile = Tribble.indexFile(inputFile);
+                        try { // re-write the index
+                            writeIndexToDisk(index,indexFile,new FSLockWithShared(indexFile));
+                        } catch (IOException e) {
+                            logger.warn("Unable to update index with the sequence dictionary for file " + indexFile + "; this will not affect your run of the GATK");
+                        }
+                    }
+
+                    sequenceDictionary = IndexDictionaryUtils.getSequenceDictionaryFromProperties(index);
+                }
+
+                featureSource = AbstractFeatureReader.getFeatureReader(inputFile.getAbsolutePath(), createCodec(descriptor, name, inputFile), index);
+            }
+            catch (TribbleException e) {
+                throw new UserException(e.getMessage());
+            }
+            catch (IOException e) {
+                throw new UserException("I/O error loading or writing tribble index file for " + inputFile.getAbsolutePath(), e);
+            }
+        }
+        else {
+            featureSource = AbstractFeatureReader.getFeatureReader(inputFile.getAbsolutePath(), createCodec(descriptor, name, inputFile), false);
+        }
+
+        return new Pair<AbstractFeatureReader,SAMSequenceDictionary>(featureSource,sequenceDictionary);
+    }
+
+    /**
+     * create an index for the input file
+     * @param inputFile the input file
+     * @param codec the codec to use
+     * @return a linear index for the specified type
+     * @throws IOException if we cannot write the index file
+     */
+    public synchronized Index loadIndex( final File inputFile, final FeatureCodec codec) throws IOException {
+        final File indexFile = Tribble.indexFile(inputFile);
+        final FSLockWithShared lock = new FSLockWithShared(indexFile);
+        Index idx = null;
+
+        // If the index file exists and is readable, attempt to load it from disk. We'll get null back
+        // if a problem was discovered with the index file when it was inspected, and we'll get an
+        // in-memory index back in the case where the index file could not be locked.
+        if (indexFile.canRead()) {
+            idx = disableAutoIndexCreation ? loadFromDisk(inputFile, indexFile)  // load without locking if we're in disableAutoIndexCreation mode
+                                           : attemptToLockAndLoadIndexFromDisk(inputFile, codec, indexFile, lock);
+        }
+
+        // If we have an index, it means we either loaded it from disk without issue or we created an in-memory
+        // index due to not being able to acquire a lock.
+        if (idx != null) return idx;
+
+        // We couldn't read the file, or we discovered a problem with the index file, so continue on to making a new index
+        idx = createIndexInMemory(inputFile, codec);
+        if ( ! disableAutoIndexCreation ) {
+            writeIndexToDisk(idx, indexFile, lock);
+        }
+        return idx;
+    }
+
+    /**
+     * Attempt to acquire a shared lock and then load the index from disk. Returns an in-memory index if
+     * a lock could not be obtained. Returns null if a problem was discovered with the index file when it
+     * was examined (eg., it was out-of-date).
+     *
+     * @param inputFile the input file
+     * @param codec the codec to read from
+     * @param indexFile the index file itself
+     * @param lock the lock file
+     * @return an index, or null if we couldn't load one
+     * @throws IOException if we fail for FS issues
+     */
+    protected Index attemptToLockAndLoadIndexFromDisk( final File inputFile, final FeatureCodec codec, final File indexFile, final FSLockWithShared lock ) throws IOException {
+        boolean locked = false;
+        Index idx = null;
+
+        try {
+            locked = lock.sharedLock();
+
+            if ( ! locked ) { // can't lock file
+                logger.info(String.format("Could not acquire a shared lock on index file %s, falling back to using an in-memory index for this GATK run.",
+                                          indexFile.getAbsolutePath()));
+                idx = createIndexInMemory(inputFile, codec);
+            }
+            else {
+                idx = loadFromDisk(inputFile, indexFile);
+            }
+        } finally {
+            if (locked) lock.unlock();
+        }
+        return idx;
+    }
+
+    /**
+     * load the index from disk, checking for out of date indexes and old versions (both of which are deleted)
+     * @param inputFile the input file
+     * @param indexFile the input file, plus the index extension
+     * @return an Index, or null if we're unable to load
+     */
+    protected Index loadFromDisk( final File inputFile, final File indexFile ) {
+        logger.debug("Loading Tribble index from disk for file " + inputFile);
+        Index index = IndexFactory.loadIndex(indexFile.getAbsolutePath());
+
+        // check if the file is up-to date (filestamp and version check)
+        if (index.isCurrentVersion() && indexFile.lastModified() >= inputFile.lastModified())
+            return index;
+        else if (indexFile.lastModified() < inputFile.lastModified())
+            logger.warn("Index file " + indexFile + " is out of date (index older than input file), " +
+                        (disableAutoIndexCreation ? "falling back to an in-memory index" : "deleting and updating the index file"));
+        else // we've loaded an old version of the index, we want to remove it <-- currently not used, but may re-enable
+            logger.warn("Index file " + indexFile + " is out of date (old version), " +
+                        (disableAutoIndexCreation ? "falling back to an in-memory index" : "deleting and updating the index file"));
+
+        if ( ! disableAutoIndexCreation ) {
+            boolean deleted = indexFile.delete();
+            if (!deleted) logger.warn("Index file " + indexFile + " is out of date, but could not be removed; it will not be trusted (we'll try to rebuild an in-memory copy)");
+        }
+
+        return null;
+    }
+
+
+    /**
+     * attempt to write the index to disk
+     * @param index the index to write to disk
+     * @param indexFile the index file location
+     * @param lock the locking object
+     * @throws IOException when unable to create the new index
+     */
+    private void writeIndexToDisk( final Index index, final File indexFile, final FSLockWithShared lock ) throws IOException {
+        if ( disableAutoIndexCreation ) {
+            return;
+        }
+
+        boolean locked = false;
+
+        try {
+            locked = lock.exclusiveLock();
+
+            if (locked) {
+                logger.info("Writing Tribble index to disk for file " + indexFile);
+                LittleEndianOutputStream stream = new LittleEndianOutputStream(new FileOutputStream(indexFile));
+                index.write(stream);
+                stream.close();
+            }
+            else // we can't write it to disk, just store it in memory, tell them this
+                logger.warn("Unable to write to " + indexFile + " for the index file, creating index in memory only");
+
+            try { logger.info(String.format("  Index for %s has size in bytes %d", indexFile, Sizeof.getObjectGraphSize(index))); }
+            catch ( ReviewedGATKException e) { }
+        }
+        finally {
+            if (locked) lock.unlock();
+        }
+
+    }
+
+    /**
+     * create the index in memory, given the input file and feature codec
+     * @param inputFile the input file
+     * @param codec the codec
+     * @return a LinearIndex, given the file location
+     * @throws IOException when unable to create the index in memory
+     */
+    protected Index createIndexInMemory(File inputFile, FeatureCodec codec) {
+        // this can take a while, let them know what we're doing
+        logger.debug("Creating Tribble index in memory for file " + inputFile);
+        Index idx = IndexFactory.createDynamicIndex(inputFile, codec, IndexFactory.IndexBalanceApproach.FOR_SEEK_TIME);
+        validateAndUpdateIndexSequenceDictionary(inputFile, idx, dict);
+        return idx;
+    }
+
+    /**
+     * set the sequence dictionary of the track.  This function checks that the contig listing of the underlying file is compatible.
+     * (that each contig in the index is in the sequence dictionary).
+     * @param inputFile for proper error message formatting.
+     * @param dict the sequence dictionary
+     * @param index the index file
+     */
+    public void validateAndUpdateIndexSequenceDictionary(final File inputFile, final Index index, final SAMSequenceDictionary dict) {
+        if (dict == null) throw new ReviewedGATKException("BUG: dict cannot be null");
+
+        // check that every contig in the RMD contig list is at least in the sequence dictionary we're being asked to set
+        final SAMSequenceDictionary currentDict = IndexDictionaryUtils.createSequenceDictionaryFromContigList(index, new SAMSequenceDictionary());
+        validateTrackSequenceDictionary(inputFile.getAbsolutePath(), currentDict, dict);
+
+        // actually update the dictionary in the index
+        IndexDictionaryUtils.setIndexSequenceDictionary(index, dict);
+    }
+
+    public void validateTrackSequenceDictionary(final String trackName,
+                                                final SAMSequenceDictionary trackDict,
+                                                final SAMSequenceDictionary referenceDict ) {
+        IndexDictionaryUtils.validateTrackSequenceDictionary(trackName, trackDict, referenceDict, validationExclusionType);
+    }
+}
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/refdata/utils/FeatureToGATKFeatureIterator.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/refdata/utils/FeatureToGATKFeatureIterator.java
new file mode 100644
index 0000000..6fb073e
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/refdata/utils/FeatureToGATKFeatureIterator.java
@@ -0,0 +1,74 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.engine.refdata.utils;
+
+import htsjdk.samtools.util.CloseableIterator;
+import htsjdk.tribble.CloseableTribbleIterator;
+import htsjdk.tribble.Feature;
+import org.broadinstitute.gatk.utils.GenomeLocParser;
+
+
+/**
+ * 
+ * @author aaron 
+ * 
+ * Class FeatureToGATKFeatureIterator
+ *
+ * a wrapper on Tribble feature iterators so that they produce GATKFeatures (which produce GenomeLocs)
+ */
+public class FeatureToGATKFeatureIterator implements CloseableIterator<GATKFeature> {
+    private final GenomeLocParser genomeLocParser;
+    private final CloseableTribbleIterator<Feature> iterator;
+    private final String name;
+
+    public FeatureToGATKFeatureIterator(GenomeLocParser genomeLocParser,CloseableTribbleIterator<Feature> iter, String name) {
+        this.genomeLocParser = genomeLocParser;
+        this.name = name;
+        this.iterator = iter;
+    }
+
+    @Override
+    public boolean hasNext() {
+        return iterator.hasNext();
+    }
+
+    @Override
+    public GATKFeature next() {
+        return new GATKFeature.TribbleGATKFeature(genomeLocParser,iterator.next(),name);
+    }
+
+    @Override
+    public void remove() {
+        throw new UnsupportedOperationException("Why does Iterator have this method? We always throw an exception here");
+    }
+
+    @Override
+    public void close() {
+        // The private adapted iterator may not be passed on by the method constructing this object,
+        // leaving only this adapter to close the wrapped iterator.
+        iterator.close();
+    }
+}
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/refdata/utils/FlashBackIterator.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/refdata/utils/FlashBackIterator.java
new file mode 100644
index 0000000..8fc549c
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/refdata/utils/FlashBackIterator.java
@@ -0,0 +1,221 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.engine.refdata.utils;
+
+import htsjdk.samtools.SAMSequenceDictionary;
+import org.broadinstitute.gatk.utils.GenomeLoc;
+import org.broadinstitute.gatk.utils.HasGenomeLocation;
+
+import java.util.Comparator;
+import java.util.LinkedList;
+
+
+/**
+ * 
+ * @author aaron 
+ * 
+ * Class FlashBackIterator
+ *
+ * better than acid washed jeans...more like a Delorean that flies through time
+ *
+ * This iterator buffers a certain amount of ROD data to 'flash back' to.  This
+ * is needed for using ROD's in read traversals, because between shards we sometimes
+ * (actually often) need to go back to before the current iterators location and
+ * get RODs that overlap the current read.
+ */
+public class FlashBackIterator implements LocationAwareSeekableRODIterator {
+    private LocationAwareSeekableRODIterator iterator;
+    private LinkedList<ComparableList> pastQueue = new LinkedList<ComparableList>();
+    private LinkedList<ComparableList> aheadQueue = new LinkedList<ComparableList>();
+    private int MAX_QUEUE = 200;
+
+    /**
+     * create a flashback iterator
+     * @param iterator given a LocationAwareSeekableRODIterator
+     */
+    public FlashBackIterator(LocationAwareSeekableRODIterator iterator) {
+        this.iterator = iterator;
+    }
+
+    /**
+     * Gets the header associated with the backing input stream.
+     * @return the ROD header.
+     */
+    @Override
+    public Object getHeader() {
+        return iterator.getHeader();
+    }
+
+    /**
+     * Gets the sequence dictionary associated with the backing input stream.
+     * @return sequence dictionary from the ROD header.
+     */
+    @Override
+    public SAMSequenceDictionary getSequenceDictionary() {
+        return iterator.getSequenceDictionary();
+    }
+
+
+    /**
+     * peek at the next location
+     * @return
+     */
+    @Override
+    public GenomeLoc peekNextLocation() {
+        return (aheadQueue.size() > 0) ? aheadQueue.getFirst().getLocation() : iterator.peekNextLocation();
+    }
+
+    /**
+     * get the position of this iterator
+     * @return
+     */
+    @Override
+    public GenomeLoc position() {
+        return (aheadQueue.size() > 0) ? aheadQueue.getFirst().getLocation() : iterator.position();
+    }
+
+    /**
+     * seek forward on the iterator
+     * @param interval the interval to seek to
+     * @return a RODRecordList at that location, null otherwise
+     */
+    @Override
+    public RODRecordList seekForward(GenomeLoc interval) {
+
+        RODRecordList lt = iterator.seekForward(interval);
+        createPastRecord(lt);
+        return lt;
+    }
+
+    /**
+     * do we have a next record
+     * @return true if we have another record
+     */
+    @Override
+    public boolean hasNext() {
+        return (aheadQueue.size() > 0 ||  iterator.hasNext());
+    }
+
+    /**
+     * get the next record
+     * @return a RODRecordList
+     */
+    @Override
+    public RODRecordList next() {
+        return getNext();
+    }
+
+    /**
+     * we don't support remove
+     */
+    @Override
+    public void remove() {
+        throw new UnsupportedOperationException("We don't support remove");
+    }
+
+    /**
+     * get the next record, either from the queue or from the iterator
+     * @return a RODRecordList
+     */
+    private RODRecordList getNext() {
+        if (aheadQueue.size() > 0) {
+            RODRecordList ret = aheadQueue.getFirst().getList();
+            aheadQueue.removeFirst();
+            return ret;
+        } else {
+            RODRecordList ret = iterator.next();
+            createPastRecord(ret);
+            return ret;
+        }
+    }
+
+    private void createPastRecord(RODRecordList ret) {
+        ComparableList rec = new ComparableList(ret);
+        if (rec.getLocation() != null) pastQueue.addLast(new ComparableList(ret));
+        if (pastQueue.size() > this.MAX_QUEUE) pastQueue.removeFirst();
+    }
+
+    /**
+     * can we flash back to the specified location?
+     *
+     * @param location the location to try and flash back to
+     *
+     * @return true if we can, false otherwise
+     */
+    public boolean canFlashBackTo(GenomeLoc location) {
+        GenomeLoc farthestBack = (pastQueue.size() > 0) ? pastQueue.getFirst().getLocation() : iterator.peekNextLocation();
+        return (!farthestBack.isPast(location));
+    }
+
+    /**
+     * flashback! Throws an unsupported operation exception
+     *
+     * @param location where to flash back to
+     */
+    public void flashBackTo(GenomeLoc location) {
+        if (!canFlashBackTo(location)) throw new UnsupportedOperationException("we can't flash back to " + location);
+        if (pastQueue.size()==0) return; // the iterator can do it alone
+        while (pastQueue.size() > 0 && !pastQueue.getLast().getLocation().isBefore(location)) {
+            aheadQueue.addFirst(pastQueue.getLast());
+            pastQueue.removeLast();
+        }
+    }
+
+    public void close() {
+        this.aheadQueue.clear();
+        this.pastQueue.clear();
+    }
+}
+
+/**
+ * a list that buffers the location for this rod
+ */
+class ComparableList implements Comparator<ComparableList>, HasGenomeLocation {
+    private RODRecordList list;
+    private GenomeLoc location = null;
+    public ComparableList(RODRecordList list) {
+        this.list = list;
+        if (list != null && list.size() != 0)
+            location = list.getLocation();
+    }
+
+    @Override
+    public int compare(ComparableList list1, ComparableList list2) {
+        if (list1.location == null && list2.location == null)
+            return 0;
+        if (list1.location == null) return 1;
+        if (list2.location == null) return -1;
+        return (list1.location.compareTo(list2.location));
+    }
+
+    public GenomeLoc getLocation() {
+        return location;
+    }
+
+    public RODRecordList getList() {
+        return list;
+    }
+}
\ No newline at end of file
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/refdata/utils/GATKFeature.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/refdata/utils/GATKFeature.java
new file mode 100644
index 0000000..4d08f1b
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/refdata/utils/GATKFeature.java
@@ -0,0 +1,109 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.engine.refdata.utils;
+
+import htsjdk.tribble.Feature;
+import org.broadinstitute.gatk.engine.refdata.ReferenceOrderedDatum;
+import org.broadinstitute.gatk.utils.GenomeLoc;
+import org.broadinstitute.gatk.utils.GenomeLocParser;
+import org.broadinstitute.gatk.utils.HasGenomeLocation;
+
+
+/**
+ * 
+ * @author aaron 
+ * 
+ * Class GATKFeature
+ *
+ * This wraps a Tribble feature or a RODatum so that both present the same interface: a genome loc for position and a
+ * way of retrieving the track name.
+ */
+public abstract class GATKFeature implements Feature, HasGenomeLocation {
+
+    public GATKFeature(String name) {
+        this.name = name;
+    }
+
+    String name;
+
+    protected void setName(String name) {
+        this.name = name;
+    }
+
+    public String getName() {
+        return name;
+    }
+
+    public abstract GenomeLoc getLocation();
+
+    // TODO: this should be a Feature
+    public abstract Object getUnderlyingObject();
+
+    /**
+     * wrapping a Tribble feature in a GATK friendly interface
+     */
+    public static class TribbleGATKFeature extends GATKFeature {
+        private final GenomeLocParser genomeLocParser;
+        private final Feature feature;
+        private GenomeLoc position = null;
+        
+        public TribbleGATKFeature(GenomeLocParser genomeLocParser,Feature f, String name) {
+            super(name);
+            this.genomeLocParser = genomeLocParser;
+            feature = f;
+        }
+        public GenomeLoc getLocation() {
+            if (position == null) position = genomeLocParser.createGenomeLoc(feature.getChr(), feature.getStart(), feature.getEnd());
+            return position;
+        }
+
+        /** Return the features reference sequence name, e.g chromosome or contig */
+        @Override
+        public String getChr() {
+            return feature.getChr();
+        }
+
+        /** Return the start position in 1-based coordinates (first base is 1) */
+        @Override
+        public int getStart() {
+            return feature.getStart();
+        }
+
+        /**
+         * Return the end position following 1-based fully closed conventions.  The length of a feature is
+         * end - start + 1;
+         */
+        @Override
+        public int getEnd() {
+            return feature.getEnd();
+        }
+
+        // TODO: this should be a Feature, actually
+        public Object getUnderlyingObject() {
+            return feature;
+        }
+    }
+}
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/refdata/utils/LocationAwareSeekableRODIterator.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/refdata/utils/LocationAwareSeekableRODIterator.java
new file mode 100644
index 0000000..96c60b9
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/refdata/utils/LocationAwareSeekableRODIterator.java
@@ -0,0 +1,49 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.engine.refdata.utils;
+
+import htsjdk.samtools.SAMSequenceDictionary;
+import htsjdk.samtools.util.CloseableIterator;
+import org.broadinstitute.gatk.utils.GenomeLoc;
+
+/**
+ * @author aaron
+ *         <p/>
+ *         Interface LocationAwareSeekableRODIterator
+ *         <p/>
+ *         combine iteration with a position aware interface
+ */
+public interface LocationAwareSeekableRODIterator extends CloseableIterator<RODRecordList> {
+    public Object getHeader();
+
+    public SAMSequenceDictionary getSequenceDictionary();
+
+    public GenomeLoc peekNextLocation();
+
+    public GenomeLoc position();
+
+    public RODRecordList seekForward(GenomeLoc interval);    
+}
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/refdata/utils/RMDTriplet.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/refdata/utils/RMDTriplet.java
new file mode 100644
index 0000000..9fa3d1e
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/refdata/utils/RMDTriplet.java
@@ -0,0 +1,92 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.engine.refdata.utils;
+
+
+import org.broadinstitute.gatk.utils.commandline.Tags;
+
+/**
+ * a helper class to manage our triplets of data for the -B command line option (name, type, file)
+ * TODO: The presence of four datapoints here suggests that this class' name isn't sufficient to describe its function.  Rename.
+ */
+public class RMDTriplet {
+    public enum RMDStorageType { FILE, STREAM };
+
+    private final String name;
+    private final String type;
+    private final String file;
+    private final RMDStorageType storageType;
+    private final Tags tags;
+
+    public RMDTriplet(final String name, final String type, final String file, final RMDStorageType storageType, final Tags tags) {
+        this.name = name;
+        this.type = type;
+        this.file = file;
+        this.storageType = storageType;
+        this.tags = tags;
+    }
+
+    /**
+     * Gets the name of this track.  RefMetaDataTrackers can use this identifier to retrieve data of a certain type.
+     * @return Name associated with this track.
+     */
+    public String getName() {
+        return name;
+    }
+
+    /**
+     * Gets the type of this track.  Informs the GATK how to parse this file type.
+     * @return Type associated with this track.
+     */
+    public String getType() {
+        return type;
+    }
+
+    /**
+     * Gets the filename representing this track.  Data is loaded from this file.
+     * @return Filename of the RMD.
+     */
+    public String getFile() {
+        return file;
+    }
+
+    /**
+     * The type of storage being used for this metadata track.  Right now, can be either a
+     * file type (can be indexed) or a stream type (can't be indexed).
+     * @return Storage type for this RMD 'triplet'.
+     */
+    public RMDStorageType getStorageType() {
+        return storageType;
+    }
+
+    /**
+     * Gets the key=value tags associated with this track
+     * @return Tags associated with this track.
+     */
+    public Tags getTags() {
+        return tags;
+    }
+}
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/refdata/utils/RODRecordList.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/refdata/utils/RODRecordList.java
new file mode 100644
index 0000000..b859edc
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/refdata/utils/RODRecordList.java
@@ -0,0 +1,45 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.engine.refdata.utils;
+
+import org.broadinstitute.gatk.utils.GenomeLoc;
+import org.broadinstitute.gatk.utils.HasGenomeLocation;
+
+import java.util.List;
+
+
+/**
+ * @author aaron
+ *         <p/>
+ *         Class RODRecordList
+ *         <p/>
+ *         make the RODRecord list an interface, so we can stub in other implementations
+ *         during testing.
+ */
+public interface RODRecordList extends List<GATKFeature>, Comparable<RODRecordList>, HasGenomeLocation {
+    public GenomeLoc getLocation();
+    public String getName();
+}
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/report/GATKReport.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/report/GATKReport.java
new file mode 100644
index 0000000..660ea95
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/report/GATKReport.java
@@ -0,0 +1,376 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.engine.report;
+
+import org.broadinstitute.gatk.utils.exceptions.ReviewedGATKException;
+import org.broadinstitute.gatk.utils.exceptions.UserException;
+
+import java.io.*;
+import java.util.Collection;
+import java.util.List;
+import java.util.Map;
+import java.util.TreeMap;
+
+/**
+ * Container class for GATK report tables
+ */
+public class GATKReport {
+    public static final String GATKREPORT_HEADER_PREFIX = "#:GATKReport.";
+    public static final GATKReportVersion LATEST_REPORT_VERSION = GATKReportVersion.V1_1;
+    private static final String SEPARATOR = ":";
+    private GATKReportVersion version = LATEST_REPORT_VERSION;
+
+    private final TreeMap<String, GATKReportTable> tables = new TreeMap<String, GATKReportTable>();
+
+    /**
+     * Create a new, empty GATKReport.
+     */
+    public GATKReport() {
+    }
+
+    /**
+     * Create a new GATKReport with the contents of a GATKReport on disk.
+     *
+     * @param filename the path to the file to load
+     */
+    public GATKReport(String filename) {
+        this(new File(filename));
+    }
+
+    /**
+     * Create a new GATKReport with the contents of a GATKReport on disk.
+     *
+     * @param file the file to load
+     */
+    public GATKReport(File file) {
+        loadReport(file);
+    }
+
+    /**
+     * Create a new GATK report from GATK report tables
+     * @param tables Any number of tables that you want to add to the report
+     */
+    public GATKReport(GATKReportTable... tables) {
+        for( GATKReportTable table: tables)
+            addTable(table);
+    }
+
+    /**
+     * Load a GATKReport file from disk
+     *
+     * @param file the file to load
+     */
+    private void loadReport(File file) {
+        BufferedReader reader;
+        String reportHeader;
+        try {
+            reader = new BufferedReader(new FileReader(file));
+            reportHeader = reader.readLine();
+        } catch (FileNotFoundException e) {
+            throw new UserException.CouldNotReadInputFile(file, "it does not exist");
+        } catch (IOException e) { 
+            throw new UserException.CouldNotReadInputFile(file, e);
+        }   
+
+
+        // Read the first line for the version and number of tables.
+        version = GATKReportVersion.fromHeader(reportHeader);
+        if (version.equals(GATKReportVersion.V0_1) ||
+                version.equals(GATKReportVersion.V0_2))
+            throw new UserException("The GATK no longer supports reading legacy GATK Reports. Please use v1.0 or newer.");
+
+        int nTables = Integer.parseInt(reportHeader.split(":")[2]);
+
+        // Read each table according ot the number of tables
+        for (int i = 0; i < nTables; i++) {
+            addTable(new GATKReportTable(reader, version));
+        }
+    }
+
+    /**
+     * Add a new, empty table to the report
+     *
+     * @param tableName        the name of the table
+     * @param tableDescription the description of the table
+     * @param numColumns       the number of columns in this table
+     */
+    public void addTable(final String tableName, final String tableDescription, final int numColumns) {
+        addTable(tableName, tableDescription, numColumns, GATKReportTable.TableSortingWay.DO_NOT_SORT);
+    }
+
+    /**
+     * Add a new, empty table to the report
+     *
+     * @param tableName        the name of the table
+     * @param tableDescription the description of the table
+     * @param numColumns       the number of columns in this table
+     * @param sortingWay       way to sort table
+     */
+    public void addTable(final String tableName, final String tableDescription, final int numColumns, final GATKReportTable.TableSortingWay sortingWay) {
+        GATKReportTable table = new GATKReportTable(tableName, tableDescription, numColumns, sortingWay);
+        tables.put(tableName, table);
+    }
+
+    /**
+     * Adds a table, empty or populated, to the report
+     *
+     * @param table the table to add
+     */
+    public void addTable(GATKReportTable table) {
+        tables.put(table.getTableName(), table);
+    }
+
+    public void addTables(List<GATKReportTable> gatkReportTableV2s) {
+        for ( GATKReportTable table : gatkReportTableV2s )
+            addTable(table);
+    }
+
+    /**
+     * Return true if table with a given name exists
+     *
+     * @param tableName the name of the table
+     * @return true if the table exists, false otherwise
+     */
+    public boolean hasTable(String tableName) {
+        return tables.containsKey(tableName);
+    }
+
+    /**
+     * Return a table with a given name
+     *
+     * @param tableName the name of the table
+     * @return the table object
+     */
+    public GATKReportTable getTable(String tableName) {
+        GATKReportTable table = tables.get(tableName);
+        if (table == null)
+            throw new ReviewedGATKException("Table is not in GATKReport: " + tableName);
+        return table;
+    }
+
+    /**
+     * Print all tables contained within this container to a PrintStream
+     *
+     * @param out the PrintStream to which the tables should be written
+     */
+    public void print(PrintStream out) {
+        out.println(GATKREPORT_HEADER_PREFIX + getVersion().toString() + SEPARATOR + getTables().size());
+        for (GATKReportTable table : tables.values())
+            table.write(out);
+    }
+
+    public Collection<GATKReportTable> getTables() {
+        return tables.values();
+    }
+
+    /**
+     * This is the main function is charge of gathering the reports. It checks that the reports are compatible and then
+     * calls the table gathering functions.
+     *
+     * @param input another GATKReport of the same format
+     */
+    public void concat(GATKReport input) {
+
+        if ( !isSameFormat(input) ) {
+            throw new ReviewedGATKException("Failed to combine GATKReport, format doesn't match!");
+        }
+
+        for ( Map.Entry<String, GATKReportTable> table : tables.entrySet() ) {
+            table.getValue().concat(input.getTable(table.getKey()));
+        }
+    }
+
+    public GATKReportVersion getVersion() {
+        return version;
+    }
+
+    /**
+     * Returns whether or not the two reports have the same format, from columns, to tables, to reports, and everything
+     * in between. This does not check if the data inside is the same. This is the check to see if the two reports are
+     * gatherable or reduceable.
+     *
+     * @param report another GATK report
+     * @return true if the the reports are gatherable
+     */
+    public boolean isSameFormat(GATKReport report) {
+        if (!version.equals(report.version)) {
+            return false;
+        }
+        if (!tables.keySet().equals(report.tables.keySet())) {
+            return false;
+        }
+        for (String tableName : tables.keySet()) {
+            if (!getTable(tableName).isSameFormat(report.getTable(tableName)))
+                return false;
+        }
+        return true;
+    }
+
+    /**
+     * Checks that the reports are exactly the same.
+     *
+     * @param report another GATK report
+     * @return true if all field in the reports, tables, and columns are equal.
+     */
+    public boolean equals(GATKReport report) {
+        if (!version.equals(report.version)) {
+            return false;
+        }
+        if (!tables.keySet().equals(report.tables.keySet())) {
+            return false;
+        }
+        for (String tableName : tables.keySet()) {
+            if (!getTable(tableName).equals(report.getTable(tableName)))
+                return false;
+        }
+        return true;
+    }
+
+    /**
+     * The constructor for a simplified GATK Report. Simplified GATK report are designed for reports that do not need
+     * the advanced functionality of a full GATK Report.
+     * <p/>
+     * A simple GATK Report consists of:
+     * <p/>
+     * - A single table
+     * - No primary key ( it is hidden )
+     * <p/>
+     * Optional:
+     * - Only untyped columns. As long as the data is an Object, it will be accepted.
+     * - Default column values being empty strings.
+     * <p/>
+     * Limitations:
+     * <p/>
+     * - A simple GATK report cannot contain multiple tables.
+     * - It cannot contain typed columns, which prevents arithmetic gathering.
+     *
+     * @param tableName The name of your simple GATK report table
+     * @param columns   The names of the columns in your table
+     * @return a simplified GATK report
+     */
+    public static GATKReport newSimpleReport(final String tableName, final String... columns) {
+        return newSimpleReportWithDescription(tableName, "A simplified GATK table report", columns);
+    }
+
+    /**
+     * @see #newSimpleReport(String, String...) but with a customized description
+     * @param tableName
+     * @param desc
+     * @param columns
+     * @return
+     */
+    public static GATKReport newSimpleReportWithDescription(final String tableName, final String desc, final String... columns) {
+        GATKReportTable table = new GATKReportTable(tableName, desc, columns.length);
+
+        for (String column : columns) {
+            table.addColumn(column, "");
+        }
+
+        GATKReport output = new GATKReport();
+        output.addTable(table);
+
+        return output;
+    }
+
+    /**
+     * The constructor for a simplified GATK Report. Simplified GATK report are designed for reports that do not need
+     * the advanced functionality of a full GATK Report.
+     * <p/>
+     * A simple GATK Report consists of:
+     * <p/>
+     * - A single table
+     * - No primary key ( it is hidden )
+     * <p/>
+     * Optional:
+     * - Only untyped columns. As long as the data is an Object, it will be accepted.
+     * - Default column values being empty strings.
+     * <p/>
+     * Limitations:
+     * <p/>
+     * - A simple GATK report cannot contain multiple tables.
+     * - It cannot contain typed columns, which prevents arithmetic gathering.
+     *
+     * @param tableName The name of your simple GATK report table
+     * @param columns   The names of the columns in your table
+     * @return a simplified GATK report
+     */
+    public static GATKReport newSimpleReport(final String tableName, final List<String> columns) {
+        GATKReportTable table = new GATKReportTable(tableName, "A simplified GATK table report", columns.size());
+
+        for (String column : columns) {
+            table.addColumn(column, "");
+        }
+
+        GATKReport output = new GATKReport();
+        output.addTable(table);
+
+        return output;
+    }
+
+    /**
+     * This method provides an efficient way to populate a simplified GATK report. This method will only work on reports
+     * that qualify as simplified GATK reports. See the newSimpleReport() constructor for more information.
+     *
+     * @param values     the row of data to be added to the table.
+     *               Note: the number of arguments must match the columns in the table.
+     */
+    public void addRow(final Object... values) {
+        // Must be a simple report
+        if ( tables.size() != 1 )
+            throw new ReviewedGATKException("Cannot write a row to a complex GATK Report");
+
+        GATKReportTable table = tables.firstEntry().getValue();
+        if ( table.getNumColumns() != values.length )
+            throw new ReviewedGATKException("The number of arguments in writeRow (" + values.length + ") must match the number of columns in the table (" + table.getNumColumns() + ")" );
+
+        final int rowIndex = table.getNumRows();
+        for ( int i = 0; i < values.length; i++ )
+            table.set(rowIndex, i, values[i]);
+    }
+
+    /**
+     * This method provides an efficient way to populate a simplified GATK report. This method will only work on reports
+     * that qualify as simplified GATK reports. See the newSimpleReport() constructor for more information.
+     *
+     * @param values     the row of data to be added to the table.
+     *               Note: the number of arguments must match the columns in the table.
+     */
+    public void addRowList(final List<Object> values) {
+        if ( tables.size() != 1 )
+            throw new ReviewedGATKException("Cannot write a row to a complex GATK Report");
+
+        GATKReportTable table = tables.firstEntry().getValue();
+        if ( table.getNumColumns() != values.size() )
+            throw new ReviewedGATKException("The number of arguments in writeRow() must match the number of columns in the table");
+
+        final int rowIndex = table.getNumRows();
+        int idx = 0;
+        for ( Object value : values ) {
+            table.set(rowIndex,idx,value);
+            idx++;
+        }
+    }
+}
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/report/GATKReportColumn.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/report/GATKReportColumn.java
new file mode 100644
index 0000000..ffdefff
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/report/GATKReportColumn.java
@@ -0,0 +1,147 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.engine.report;
+
+import org.apache.commons.lang.math.NumberUtils;
+
+import java.util.Arrays;
+import java.util.Collection;
+
+/**
+ * column information within a GATK report table
+ */
+public class GATKReportColumn {
+    final private String columnName;
+    final private String format;
+    final private GATKReportDataType dataType;
+
+    private GATKReportColumnFormat columnFormat;
+    private GATKReportColumnFormat.Alignment alignment = GATKReportColumnFormat.Alignment.RIGHT;  // default alignment is to the right unless values added ask for a left alignment
+    private int maxWidth = 0;
+
+    /**
+     * Construct the column object, specifying the column name, default value, whether or not the column should be
+     * displayed, and the format string. This cannot be null.
+     *
+     * @param columnName   the name of the column
+     * @param format       format string
+     */
+    public GATKReportColumn(final String columnName, final String format) {
+        this.columnName = columnName;
+        this.maxWidth = columnName.length();
+        if ( format.equals("") ) {
+            this.format = "%s";
+            this.dataType = GATKReportDataType.Unknown;
+        }
+        else {
+            this.format = format;
+            this.dataType = GATKReportDataType.fromFormatString(format);
+        }
+    }
+
+    /**
+     * Get the display width for this column.  This allows the entire column to be displayed with the appropriate, fixed
+     * width.
+     *
+     * @return the format string for this column
+     */
+    public GATKReportColumnFormat getColumnFormat() {
+        if (columnFormat != null)
+            return columnFormat;
+
+        columnFormat = new GATKReportColumnFormat(maxWidth, alignment);
+        return columnFormat;
+    }
+
+    private static final Collection<String> RIGHT_ALIGN_STRINGS = Arrays.asList(
+            "null",
+            "NA",
+            String.valueOf(Double.POSITIVE_INFINITY),
+            String.valueOf(Double.NEGATIVE_INFINITY),
+            String.valueOf(Double.NaN));
+
+    /**
+     * Check if the value can be right aligned. Does not trim the values before checking if numeric since it assumes
+     * the spaces mean that the value is already padded.
+     *
+     * @param value to check
+     * @return true if the value is a right alignable
+     */
+    protected static boolean isRightAlign(final String value) {
+        return value == null || RIGHT_ALIGN_STRINGS.contains(value) || NumberUtils.isNumber(value.trim());
+    }
+
+    /**
+     * Returns a string version of the values.
+     *
+     * @param obj The object to convert to a string
+     * @return The string representation of the column
+     */
+    private String formatValue(final Object obj) {
+        String value;
+        if (obj == null) {
+            value = "null";
+        }
+        else if ( dataType.equals(GATKReportDataType.Unknown) && (obj instanceof Double || obj instanceof Float) ) {
+            value = String.format("%.8f", obj);
+        }
+        else
+            value = String.format(format, obj);
+
+        return value;
+    }
+
+    public GATKReportDataType getDataType() {
+        return dataType;
+    }
+
+    public String getColumnName() {
+        return columnName;
+    }
+
+    public String getFormat() {
+        return dataType.equals(GATKReportDataType.Unknown) ? "%s" : format;
+    }
+
+    public void updateFormatting(final Object value) {
+        if (value != null) {
+            final String formatted = formatValue(value);
+            if ( formatted.length() > 0 ) {
+                updateMaxWidth(formatted);
+                updateFormat(formatted);
+            }
+        }
+    }
+
+    private void updateMaxWidth(final String formatted) {
+        maxWidth = Math.max(formatted.length(), maxWidth);
+    }
+
+    private void updateFormat(final String formatted) {
+        if (alignment == GATKReportColumnFormat.Alignment.RIGHT)
+            alignment = isRightAlign(formatted) ? GATKReportColumnFormat.Alignment.RIGHT : GATKReportColumnFormat.Alignment.LEFT;
+    }
+}
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/report/GATKReportColumnFormat.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/report/GATKReportColumnFormat.java
new file mode 100644
index 0000000..664b503
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/report/GATKReportColumnFormat.java
@@ -0,0 +1,63 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.engine.report;
+
+/**
+ * Column width and left/right alignment.
+ */
+public class GATKReportColumnFormat {
+    public static enum Alignment { LEFT, RIGHT }
+    private final int width;
+    private final Alignment alignment;
+
+    public GATKReportColumnFormat(int width, Alignment alignment) {
+        this.width = width;
+        this.alignment = alignment;
+    }
+
+    public int getWidth() {
+        return width;
+    }
+
+    public Alignment getAlignment() {
+        return alignment;
+    }
+
+    public String getNameFormat() {
+        return "%-" + width + "s";
+    }
+
+    public String getValueFormat() {
+        switch (alignment) {
+            case LEFT:
+                return "%-" + width + "s";
+            case RIGHT:
+                return "%" + width + "s";
+            default:
+                throw new UnsupportedOperationException("Unknown alignment: " + alignment);
+        }
+    }
+}
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/report/GATKReportDataType.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/report/GATKReportDataType.java
new file mode 100644
index 0000000..acfa74f
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/report/GATKReportDataType.java
@@ -0,0 +1,236 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.engine.report;
+
+import java.util.EnumSet;
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * The gatherable data types acceptable in a GATK report column.
+ */
+public enum GATKReportDataType {
+    /**
+     * The null type should not be used.
+     */
+    Null("Null"),
+
+    /**
+     * The default value when a format string is not present
+     */
+    Unknown("Unknown"),
+
+    /**
+     * Used for boolean values. Will display as true or false in the table.
+     */
+    Boolean("%[Bb]"),
+
+    /**
+     * Used for char values. Will display as a char so use printable values!
+     */
+    Character("%[Cc]"),
+
+    /**
+     * Used for float and double values. Will output a decimal with format %.8f unless otherwise specified.
+     */
+    Decimal("%.*[EeFf]"),
+
+    /**
+     * Used for int, byte, short, and long values. Will display the full number by default.
+     */
+    Integer("%[Dd]"),
+
+    /**
+     * Used for string values. Displays the string itself.
+     */
+    String("%[Ss]");
+
+    private final String dataTypeString;
+
+    private GATKReportDataType(String dataTypeString) {
+        this.dataTypeString = dataTypeString;
+    }
+
+    private static final Map<String, GATKReportDataType> lookup = new HashMap<String, GATKReportDataType>();
+
+    static {
+        for (GATKReportDataType s : EnumSet.allOf(GATKReportDataType.class))
+            lookup.put(s.dataTypeString, s);
+    }
+
+
+    @Override
+    public String toString() {
+        return this.dataTypeString;
+    }
+
+    /**
+     * Returns a GATK report data type from the Object specified. It looks through the list of acceptable classes and
+     * returns the appropriate data type.
+     *
+     * @param object the object ot derive the data type from
+     * @return the appropriate data type
+     */
+    public static GATKReportDataType fromObject(Object object) {
+        GATKReportDataType value;
+        if (object instanceof Boolean) {
+            value = GATKReportDataType.Boolean;
+
+        } else if (object instanceof Character) {
+            value = GATKReportDataType.Character;
+
+        } else if (object instanceof Float ||
+                object instanceof Double) {
+            value = GATKReportDataType.Decimal;
+
+        } else if (object instanceof Integer ||
+                object instanceof Long ||
+                object instanceof Short ||
+                object instanceof Byte ) {
+            value = GATKReportDataType.Integer;
+
+        } else if (object instanceof String) {
+            value = GATKReportDataType.String;
+
+        } else {
+            value = GATKReportDataType.Unknown;
+            //throw new UserException("GATKReport could not convert the data object into a GATKReportDataType. Acceptable data objects are found in the documentation.");
+        }
+        return value;
+    }
+
+    /**
+     * Returns a GATK report data type from the format string specified. It uses regex matching from the enumerated
+     * Strings.
+     *
+     * @param format the format string to derive the data type from
+     * @return the appropriate data type
+     */
+    public static GATKReportDataType fromFormatString(String format) {
+        if (format.equals(""))
+            return Unknown;
+        for (GATKReportDataType type : lookup.values()) {
+            if (format.matches(type.toString()) )
+                return type;
+        }
+        return Unknown;
+    }
+
+    /**
+     * Returns the default value of the data type. It returns an object that matches the class of the data type.
+     *
+     * @return an object that matches the data type
+     */
+    public Object getDefaultValue() {
+        switch (this) {
+            case Decimal:
+                return 0.0D;
+            case Boolean:
+                return false;
+            case Character:
+                return '0';
+            case Integer:
+                return 0L;
+            case String:
+                return "";
+            default:
+                return null;
+        }
+    }
+
+    /**
+     * Checks if the two objects are equal using the appropriate test form the data types.
+     *
+     * @param a an object
+     * @param b another object to check if equal
+     * @return true - the objects are equal, false - the objects are nto equal
+     */
+    public boolean isEqual(Object a, Object b) {
+        switch (this) {
+            case Null:
+                return true;
+            case Decimal:
+            case Boolean:
+            case Integer:
+                return a.toString().equals(b.toString());
+            case Character:
+            case String:
+            default:
+                return a.equals(b);
+        }
+    }
+
+    /**
+     * Converts an input String to the appropriate type using the data type. Used for parsing loading a GATK report from
+     * file.
+     *
+     * @param obj The input string
+     * @return an object that matches the data type.
+     */
+    Object Parse(Object obj) {
+        if (obj instanceof String) {
+            String str = obj.toString();
+            switch (this) {
+                case Decimal:
+                    return Double.parseDouble(str);
+                case Boolean:
+                    return java.lang.Boolean.parseBoolean(str);
+                case Integer:
+                    return Long.parseLong(str);
+                case String:
+                    return str;
+                case Character:
+                    return str.toCharArray()[0];
+                default:
+                    return str;
+            }
+        } else
+            return null;
+    }
+
+    /**
+     * Returns a format string version of the value according to the data type.
+     *
+     * @return The printf string representation of the object according to data type.
+     */
+    public String getDefaultFormatString() {
+        switch (this) {
+            case Decimal:
+                return "%.8f";
+            case Boolean:
+                return "%b";
+            case Integer:
+                return "%d";
+            case String:
+                return "%s";
+            case Character:
+                return "%c";
+            case Null:
+            default:
+                return "%s";
+        }
+    }
+}
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/report/GATKReportGatherer.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/report/GATKReportGatherer.java
new file mode 100644
index 0000000..5f7f767
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/report/GATKReportGatherer.java
@@ -0,0 +1,62 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.engine.report;
+
+import org.broadinstitute.gatk.utils.commandline.Gatherer;
+import org.broadinstitute.gatk.utils.exceptions.UserException;
+
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.PrintStream;
+import java.util.List;
+
+public class GATKReportGatherer extends Gatherer {
+    @Override
+    public void gather(List<File> inputs, File output) {
+        //Combines inputs GATKReport to one output
+
+        PrintStream o;
+        try {
+            o = new PrintStream(output);
+        } catch (FileNotFoundException e) {
+            throw new UserException(String.format("File %s to be output by GATKReportGatherer function was not found", output));
+        }
+
+        GATKReport current = new GATKReport();
+        boolean isFirst = true;
+        for (File input : inputs) {
+            if (isFirst) {
+                current = new GATKReport(input);
+                isFirst = false;
+            } else {
+                current.concat(new GATKReport(input));
+            }
+        }
+
+        current.print(o);
+        o.close();
+    }
+}
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/report/GATKReportTable.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/report/GATKReportTable.java
new file mode 100644
index 0000000..6a1e456
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/report/GATKReportTable.java
@@ -0,0 +1,779 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.engine.report;
+
+import org.broadinstitute.gatk.utils.exceptions.ReviewedGATKException;
+import org.broadinstitute.gatk.utils.text.TextFormattingUtils;
+
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.PrintStream;
+import java.util.*;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+public class GATKReportTable {
+    /**
+     * REGEX that matches any table with an invalid name
+     */
+    public static final String INVALID_TABLE_NAME_REGEX = "[^a-zA-Z0-9_\\-\\.]";
+    private static final String GATKTABLE_HEADER_PREFIX = "#:GATKTable";
+    private static final String SEPARATOR = ":";
+    private static final String ENDLINE = ":;";
+
+    private final String tableName;
+    private final String tableDescription;
+
+    private final TableSortingWay sortingWay;
+
+    private List<Object[]> underlyingData;
+    private final List<GATKReportColumn> columnInfo;
+    private final Map<Object, Integer> columnNameToIndex;
+    private final HashMap<Object, Integer> rowIdToIndex;
+
+    private static final String COULD_NOT_READ_HEADER = "Could not read the header of this file -- ";
+    private static final String COULD_NOT_READ_COLUMN_NAMES = "Could not read the column names of this file -- ";
+    private static final String COULD_NOT_READ_DATA_LINE = "Could not read a data line of this table -- ";
+    private static final String COULD_NOT_READ_EMPTY_LINE = "Could not read the last empty line of this table -- ";
+    private static final String OLD_GATK_TABLE_VERSION = "We no longer support older versions of the GATK Tables";
+
+    private static final int INITITAL_ARRAY_SIZE = 10000;
+    private static final String NUMBER_CONVERSION_EXCEPTION = "String is a number but is not a long or a double: ";
+
+    protected enum TableDataHeaderFields {
+        COLS(2),
+        ROWS(3),
+        FORMAT_START(4);
+
+        private final int index;
+        TableDataHeaderFields(int index) { this.index = index; }
+        public int index() { return index; }
+    }
+
+    public enum TableSortingWay {
+        SORT_BY_ROW,
+        SORT_BY_COLUMN,
+        DO_NOT_SORT
+    }
+
+    protected enum TableNameHeaderFields {
+        NAME(2),
+        DESCRIPTION(3);
+
+        private final int index;
+        TableNameHeaderFields(int index) { this.index = index; }
+        public int index() { return index; }
+    }
+
+    /**
+     * Construct a new GATK report table from the reader
+     * Note that the row ID mappings are just the index -> index
+     *
+     * @param reader        the reader
+     * @param version       the GATK report version
+     */
+    public GATKReportTable(BufferedReader reader, GATKReportVersion version) {
+
+        switch ( version ) {
+            case V1_1:
+                // read in the header lines
+                final String[] tableData, tableNameData;
+                try {
+                    tableData = reader.readLine().split(SEPARATOR);
+                    tableNameData = reader.readLine().split(SEPARATOR);
+                } catch (IOException e) {
+                    throw new ReviewedGATKException(COULD_NOT_READ_HEADER + e.getMessage());
+                }
+
+                // parse the header fields
+                tableName = tableNameData[TableNameHeaderFields.NAME.index()];
+                tableDescription = (tableNameData.length <= TableNameHeaderFields.DESCRIPTION.index()) ? "" : tableNameData[TableNameHeaderFields.DESCRIPTION.index()];                                           // table may have no description! (and that's okay)
+
+                // when reading from a file, we do not re-sort the rows
+                sortingWay = TableSortingWay.DO_NOT_SORT;
+
+                // initialize the data
+                final int nColumns = Integer.parseInt(tableData[TableDataHeaderFields.COLS.index()]);
+                final int nRows = Integer.parseInt(tableData[TableDataHeaderFields.ROWS.index()]);
+                underlyingData = new ArrayList<Object[]>(nRows);
+                columnInfo = new ArrayList<GATKReportColumn>(nColumns);
+                columnNameToIndex = new HashMap<Object, Integer>(nColumns);
+
+                // when reading from a file, the row ID mapping is just the index
+                rowIdToIndex = new HashMap<Object, Integer>();
+                for ( int i = 0; i < nRows; i++ )
+                    rowIdToIndex.put(i, i);
+
+                // read the column names
+                final String columnLine;
+                try {
+                    columnLine = reader.readLine();
+                } catch (IOException e) {
+                    throw new ReviewedGATKException(COULD_NOT_READ_COLUMN_NAMES);
+                }
+
+                final List<Integer> columnStarts = TextFormattingUtils.getWordStarts(columnLine);
+                final String[] columnNames = TextFormattingUtils.splitFixedWidth(columnLine, columnStarts);
+
+                // Put in columns using the format string from the header
+                for ( int i = 0; i < nColumns; i++ ) {
+                    final String format = tableData[TableDataHeaderFields.FORMAT_START.index() + i];
+                    addColumn(columnNames[i], format);
+                }
+
+                // fill in the table
+                try {
+                    for ( int i = 0; i < nRows; i++ ) {
+                        // read a data line
+                        final String dataLine = reader.readLine();
+                        final List<String> lineSplits = Arrays.asList(TextFormattingUtils.splitFixedWidth(dataLine, columnStarts));
+
+                        underlyingData.add(new Object[nColumns]);
+                        for ( int columnIndex = 0; columnIndex < nColumns; columnIndex++ ) {
+
+                            final GATKReportDataType type = columnInfo.get(columnIndex).getDataType();
+                            final String columnName = columnNames[columnIndex];
+                            set(i, columnName, type.Parse(lineSplits.get(columnIndex)));
+
+                        }
+                    }
+                } catch (IOException e) {
+                    throw new ReviewedGATKException(COULD_NOT_READ_DATA_LINE + e.getMessage());
+                }
+
+                try {
+                    reader.readLine();
+                } catch (IOException e) {
+                    throw new ReviewedGATKException(COULD_NOT_READ_EMPTY_LINE + e.getMessage());
+                }
+            break;
+
+            default:
+                throw new ReviewedGATKException(OLD_GATK_TABLE_VERSION);
+        }
+    }
+
+    /**
+     * Construct a new GATK report table with the specified name and description
+     *
+     * @param tableName        the name of the table
+     * @param tableDescription the description of the table
+     * @param numColumns       the number of columns in this table
+     */
+    public GATKReportTable(final String tableName, final String tableDescription, final int numColumns) {
+        this(tableName, tableDescription, numColumns, TableSortingWay.SORT_BY_ROW);
+    }
+
+    /**
+     * Construct a new GATK report table with the specified name and description and whether to sort rows by the row ID.
+     *
+     * @param tableName          the name of the table
+     * @param tableDescription   the description of the table
+     * @param numColumns         the number of columns in this table
+     * @param sortingWay         in what way to sort rows (instead of the order in which they were added)
+     */
+    public GATKReportTable(final String tableName, final String tableDescription, final int numColumns, final TableSortingWay sortingWay) {
+        if ( !isValidName(tableName) ) {
+            throw new ReviewedGATKException("Attempted to set a GATKReportTable name of '" + tableName + "'.  GATKReportTable names must be purely alphanumeric - no spaces or special characters are allowed.");
+        }
+
+        if ( !isValidDescription(tableDescription) ) {
+            throw new ReviewedGATKException("Attempted to set a GATKReportTable description of '" + tableDescription + "'.  GATKReportTable descriptions must not contain newlines.");
+        }
+
+        this.tableName = tableName;
+        this.tableDescription = tableDescription;
+        this.sortingWay = sortingWay;
+
+        underlyingData = new ArrayList<Object[]>(INITITAL_ARRAY_SIZE);
+        columnInfo = new ArrayList<GATKReportColumn>(numColumns);
+        columnNameToIndex = new HashMap<Object, Integer>(numColumns);
+        rowIdToIndex = new HashMap<Object, Integer>();
+    }
+
+    /**
+     * Create a new GATKReportTable with the same structure
+     * @param tableToCopy
+     */
+    public GATKReportTable(final GATKReportTable tableToCopy, final boolean copyData) {
+        this(tableToCopy.getTableName(), tableToCopy.getTableDescription(), tableToCopy.getNumColumns(), tableToCopy.sortingWay);
+        for ( final GATKReportColumn column : tableToCopy.getColumnInfo() )
+            addColumn(column.getColumnName(), column.getFormat());
+        if ( copyData )
+            throw new IllegalArgumentException("sorry, copying data in GATKReportTable isn't supported");
+    }
+
+        /**
+        * Verifies that a table or column name has only alphanumeric characters - no spaces or special characters allowed
+        *
+        * @param name the name of the table or column
+        * @return true if the name is valid, false if otherwise
+        */
+    private boolean isValidName(String name) {
+        Pattern p = Pattern.compile(INVALID_TABLE_NAME_REGEX);
+        Matcher m = p.matcher(name);
+
+        return !m.find();
+    }
+
+    /**
+     * Verifies that a table or column name has only alphanumeric characters - no spaces or special characters allowed
+     *
+     * @param description the name of the table or column
+     * @return true if the name is valid, false if otherwise
+     */
+    private boolean isValidDescription(String description) {
+        Pattern p = Pattern.compile("\\r|\\n");
+        Matcher m = p.matcher(description);
+
+        return !m.find();
+    }
+
+    /**
+     * Add a mapping from ID to the index of a new row added to the table.
+     *
+     * @param ID                    the unique ID
+     */
+    public void addRowID(final String ID) {
+        addRowID(ID, false);
+    }
+
+    /**
+     * Add a mapping from ID to the index of a new row added to the table.
+     *
+     * @param ID                    the unique ID
+     * @param populateFirstColumn   should we automatically populate the first column with the row's ID?
+     */
+    public void addRowID(final String ID, final boolean populateFirstColumn) {
+        addRowIDMapping(ID, underlyingData.size(), populateFirstColumn);
+    }
+
+    /**
+     * Add a mapping from ID to row index.
+     *
+     * @param ID                    the unique ID
+     * @param index                 the index associated with the ID
+     */
+    public void addRowIDMapping(final String ID, final int index) {
+        addRowIDMapping(ID, index, false);
+    }
+
+    /**
+     * Add a mapping from ID to row index.
+     *
+     * @param ID                    the unique ID
+     * @param index                 the index associated with the ID
+     * @param populateFirstColumn   should we automatically populate the first column with the row's ID?
+     */
+    public void addRowIDMapping(final Object ID, final int index, final boolean populateFirstColumn) {
+        expandTo(index, false);
+        rowIdToIndex.put(ID, index);
+
+        if ( populateFirstColumn )
+            set(index, 0, ID);
+    }
+
+    /**
+     * Remove a mapping from ID to row index.
+     *
+     * @param ID   the row ID
+     */
+    public void removeRowIDMapping(final Object ID) {
+        rowIdToIndex.remove(ID);
+    }
+
+    /**
+     * Add a column to the report
+     *
+     * @param columnName   the name of the column
+     */
+    public void addColumn(String columnName) {
+        addColumn(columnName, "");
+    }
+
+    /**
+     * Add a column to the report and the format string used to display the data.
+     *
+     * @param columnName   the name of the column
+     * @param format       the format string used to display data
+     */
+    public void addColumn(String columnName, String format) {
+        columnNameToIndex.put(columnName, columnInfo.size());
+        columnInfo.add(new GATKReportColumn(columnName, format));
+    }
+
+    /**
+     * Check if the requested cell is valid and expand the table if necessary
+     *
+     * @param rowIndex    the row index
+     * @param colIndex    the column index
+     */
+    private void verifyEntry(final int rowIndex, final int colIndex) {
+        if ( rowIndex < 0 || colIndex < 0 || colIndex >= getNumColumns() )
+            throw new ReviewedGATKException("attempted to access a cell that does not exist in table '" + tableName + "'");
+    }
+
+    /**
+     * expand the underlying table if needed to include the given row index
+     *
+     * @param rowIndex        the row index
+     * @param updateRowIdMap  should we update the row ID map?
+     */
+    private void expandTo(final int rowIndex, final boolean updateRowIdMap) {
+        int currentSize = underlyingData.size();
+        if ( rowIndex >= currentSize ) {
+            final int numNewRows = rowIndex - currentSize + 1;
+            for ( int i = 0; i < numNewRows; i++ ) {
+                if ( updateRowIdMap )
+                    rowIdToIndex.put(currentSize, currentSize);
+                underlyingData.add(new Object[getNumColumns()]);
+                currentSize++;
+            }
+        }
+    }
+
+    /**
+     * Set the value for a given position in the table.
+     * If the row ID doesn't exist, it will create a new row in the table with the given ID.
+     *
+     * @param rowID        the row ID
+     * @param columnName   the name of the column
+     * @param value        the value to set
+     */
+    public void set(final Object rowID, final String columnName, final Object value) {
+        if ( !rowIdToIndex.containsKey(rowID) ) {
+            rowIdToIndex.put(rowID, underlyingData.size());
+            expandTo(underlyingData.size(), false);
+        }
+        set(rowIdToIndex.get(rowID), columnNameToIndex.get(columnName), value);
+    }
+
+    /**
+     * Set the value for a given position in the table.
+     * If the row index doesn't exist, it will create new rows in the table accordingly.
+     *
+     * @param rowIndex     the row index
+     * @param colIndex     the column index
+     * @param value        the value to set
+     */
+    public void set(final int rowIndex, final int colIndex, Object value) {
+        expandTo(rowIndex, true);
+        verifyEntry(rowIndex, colIndex);
+        GATKReportColumn column = columnInfo.get(colIndex);
+
+        // We do not accept internal null values
+        if (value == null)
+            value = "null";
+        else
+            value = fixType(value, column);
+
+        if ( column.getDataType().equals(GATKReportDataType.fromObject(value)) || column.getDataType().equals(GATKReportDataType.Unknown) ) {
+            underlyingData.get(rowIndex)[colIndex] = value;
+            column.updateFormatting(value);
+        } else {
+            throw new ReviewedGATKException(String.format("Tried to add an object of type: %s to a column of type: %s", GATKReportDataType.fromObject(value).name(), column.getDataType().name()));
+        }
+    }
+
+    /**
+     * Returns true if the table contains a row mapping with the given ID
+     *
+     * @param rowID        the row ID
+     */
+    public boolean containsRowID(final Object rowID) {
+        return rowIdToIndex.containsKey(rowID);
+    }
+
+    /**
+     * Returns the row mapping IDs
+     *
+     */
+    public Collection<Object> getRowIDs() {
+        return rowIdToIndex.keySet();
+    }
+
+    /**
+    * Increment the value for a given position in the table.
+    * Throws an exception if the value in the cell is not an integer.
+    *
+    * @param rowID        the row ID
+    * @param columnName   the name of the column
+    */
+    public void increment(final Object rowID, final String columnName) {
+        int prevValue;
+        if ( !rowIdToIndex.containsKey(rowID) ) {
+            rowIdToIndex.put(rowID, underlyingData.size());
+            underlyingData.add(new Object[getNumColumns()]);
+            prevValue = 0;
+        } else {
+            Object obj = get(rowID, columnName);
+            if ( !(obj instanceof Integer) )
+                throw new ReviewedGATKException("Attempting to increment a value in a cell that is not an integer");
+            prevValue = (Integer)obj;
+        }
+
+        set(rowIdToIndex.get(rowID), columnNameToIndex.get(columnName), prevValue + 1);
+    }
+
+    /**
+     * Returns the index of the first row matching the column values.
+     * Ex: "CountVariants", "dbsnp", "eval", "called", "all", "novel", "all"
+     *
+     * @param columnValues column values.
+     * @return The index of the first row matching the column values or -1 if no such row exists.
+     */
+    public int findRowByData(final Object... columnValues) {
+        if ( columnValues == null || columnValues.length == 0 || columnValues.length > getNumColumns() )
+            return -1;
+
+        for ( int rowIndex = 0; rowIndex < underlyingData.size(); rowIndex++ ) {
+
+            final Object[] row = underlyingData.get(rowIndex);
+
+            boolean matches = true;
+            for ( int colIndex = 0; colIndex < columnValues.length; colIndex++ ) {
+                if ( !columnValues[colIndex].equals(row[colIndex]) ) {
+                    matches = false;
+                    break;
+                }
+            }
+
+            if ( matches )
+                return rowIndex;
+        }
+
+        return -1;
+    }
+
+    private Object fixType(final Object value, final GATKReportColumn column) {
+        // Below is some code to convert a string into its appropriate type.
+
+        // todo -- Types have to be more flexible. For example, %d should accept Integers, Shorts and Bytes.
+
+        Object newValue = null;
+        if ( value instanceof String && !column.getDataType().equals(GATKReportDataType.String) ) {
+            // Integer case
+            if ( column.getDataType().equals(GATKReportDataType.Integer) ) {
+                try {
+                    newValue = Long.parseLong((String) value);
+                } catch (Exception e) {
+                    /** do nothing */
+                }
+            }
+            if ( column.getDataType().equals(GATKReportDataType.Decimal) ) {
+                try {
+                    newValue = Double.parseDouble((String) value);
+                } catch (Exception e) {
+                    /** do nothing */
+                }
+            }
+            if ( column.getDataType().equals(GATKReportDataType.Character) && ((String) value).length() == 1 ) {
+                newValue = ((String) value).charAt(0);
+            }
+        }
+
+        return  (newValue != null) ? newValue : value;
+    }
+
+    /**
+     * Get a value from the given position in the table
+     *
+     * @param rowID       the row ID
+     * @param columnName  the name of the column
+     * @return the value stored at the specified position in the table
+     */
+    public Object get(final Object rowID, final String columnName) {
+        return get(rowIdToIndex.get(rowID), columnNameToIndex.get(columnName));
+    }
+
+    /**
+     * Get a value from the given position in the table
+     *
+     * @param rowIndex       the row ID
+     * @param columnName  the name of the column
+     * @return the value stored at the specified position in the table
+     */
+    public Object get(final int rowIndex, final String columnName) {
+        return get(rowIndex, columnNameToIndex.get(columnName));
+    }
+
+    /**
+     * Get a value from the given position in the table
+     *
+     * @param rowIndex    the index of the row
+     * @param columnIndex the index of the column
+     * @return the value stored at the specified position in the table
+     */
+    public Object get(int rowIndex, int columnIndex) {
+        verifyEntry(rowIndex, columnIndex);
+        return underlyingData.get(rowIndex)[columnIndex];
+    }
+
+    /**
+     * Write the table to the PrintStream, formatted nicely to be human-readable, AWK-able, and R-friendly.
+     *
+     * @param out the PrintStream to which the table should be written
+     */
+     void write(final PrintStream out) {
+
+         /*
+          * Table header:
+          * #:GATKTable:nColumns:nRows:(DataType for each column):;
+          * #:GATKTable:TableName:Description :;
+          * key   colA  colB
+          * row1  xxxx  xxxxx
+         */
+
+         // write the table definition
+         out.printf(GATKTABLE_HEADER_PREFIX + ":%d:%d", getNumColumns(), getNumRows());
+
+         // write the formats for all the columns
+         for ( final GATKReportColumn column : columnInfo )
+             out.print(SEPARATOR + column.getFormat());
+         out.println(ENDLINE);
+
+         // write the table name & description
+         out.printf(GATKTABLE_HEADER_PREFIX + ":%s:%s\n", tableName, tableDescription);
+
+         // write the column names
+         boolean needsPadding = false;
+         for ( final GATKReportColumn column : columnInfo ) {
+             if ( needsPadding )
+                 out.printf("  ");
+             needsPadding = true;
+
+             out.printf(column.getColumnFormat().getNameFormat(), column.getColumnName());
+         }
+         out.println();
+
+         // write the table body
+         switch (sortingWay) {
+             case SORT_BY_COLUMN:
+                 Collections.sort(underlyingData, new Comparator<Object[]>() {
+                     //INVARIANT the two arrays are of the same length and corresponding elements are of the same type
+                     @Override
+                     public int compare(Object[] objectArr1, Object[] objectArr2) {
+                         final int EQUAL = 0;
+
+                         int result = EQUAL;
+
+                         int l = objectArr1.length;
+                         for (int x = 0; x < l; x++) {
+                             if (objectArr1[x] instanceof Integer) {
+                                 result = ((Integer)objectArr1[x]).compareTo((Integer)objectArr2[x]);
+                             } else if (objectArr1[x] instanceof Double) {
+                                 result = ((Double)objectArr1[x]).compareTo((Double)objectArr2[x]);
+                             } else { // default uses String comparison
+                                 result = objectArr1[x].toString().compareTo(objectArr2[x].toString());
+                             }
+                             if( result  != EQUAL) {
+                                 return result;
+                             }
+                         }
+                         return result;
+                     }
+                 });
+                 for ( final Object[] row : underlyingData )
+                     writeRow(out, row);
+                 break;
+             case SORT_BY_ROW:
+                 // make sure that there are exactly the correct number of ID mappings
+                 if ( rowIdToIndex.size() != underlyingData.size() )
+                     throw new ReviewedGATKException("There isn't a 1-to-1 mapping from row ID to index; this can happen when rows are not created consistently");
+
+                 final TreeMap<Object, Integer> sortedMap;
+                 try {
+                     sortedMap = new TreeMap<Object, Integer>(rowIdToIndex);
+                 } catch (ClassCastException e) {
+                     throw new ReviewedGATKException("Unable to sort the rows based on the row IDs because the ID Objects are of different types");
+                 }
+                 for ( final Map.Entry<Object, Integer> rowKey : sortedMap.entrySet() )
+                     writeRow(out, underlyingData.get(rowKey.getValue()));
+                 break;
+             case DO_NOT_SORT:
+                 for ( final Object[] row : underlyingData )
+                     writeRow(out, row);
+         }
+         out.println();
+     }
+
+    private void writeRow(final PrintStream out, final Object[] row) {
+        boolean needsPadding = false;
+        for ( int i = 0; i < row.length; i++ ) {
+            if ( needsPadding )
+                out.printf("  ");
+            needsPadding = true;
+
+            final Object obj = row[i];
+            final String value;
+
+            final GATKReportColumn info = columnInfo.get(i);
+
+            if ( obj == null )
+                value = "null";
+            else if ( info.getDataType().equals(GATKReportDataType.Unknown) && (obj instanceof Double || obj instanceof Float) )
+                value = String.format("%.8f", obj);
+            else
+                value = String.format(info.getFormat(), obj);
+
+            out.printf(info.getColumnFormat().getValueFormat(), value);
+        }
+
+        out.println();
+    }
+
+    public int getNumRows() {
+        return underlyingData.size();
+    }
+
+    public int getNumColumns() {
+        return columnInfo.size();
+    }
+
+    public List<GATKReportColumn> getColumnInfo() {
+        return columnInfo;
+    }
+
+    public String getTableName() {
+        return tableName;
+    }
+
+    public String getTableDescription() {
+        return tableDescription;
+    }
+
+    /**
+     * Concatenates the rows from the table to this one
+     *
+     * @param table another GATK table
+     */
+    public void concat(final GATKReportTable table) {
+        if ( !isSameFormat(table) )
+            throw new ReviewedGATKException("Error trying to concatenate tables with different formats");
+
+        // add the data
+        underlyingData.addAll(table.underlyingData);
+
+        // update the row index map
+        final int currentNumRows = getNumRows();
+        for ( Map.Entry<Object, Integer> entry : table.rowIdToIndex.entrySet() )
+            rowIdToIndex.put(entry.getKey(), entry.getValue() + currentNumRows);
+    }
+
+    /**
+     * Returns whether or not the two tables have the same format including columns and everything in between. This does
+     * not check if the data inside is the same. This is the check to see if the two tables are gatherable or
+     * reduceable
+     *
+     * @param table another GATK table
+     * @return true if the the tables are gatherable
+     */
+    public boolean isSameFormat(final GATKReportTable table) {
+        if ( !tableName.equals(table.tableName) ||
+                !tableDescription.equals(table.tableDescription) ||
+                columnInfo.size() != table.columnInfo.size() )
+            return false;
+
+        for ( int i = 0; i < columnInfo.size(); i++ ) {
+            if ( !columnInfo.get(i).getFormat().equals(table.columnInfo.get(i).getFormat()) ||
+                    !columnInfo.get(i).getColumnName().equals(table.columnInfo.get(i).getColumnName()) )
+                return false;
+        }
+
+        return true;
+    }
+
+    /**
+     * Checks that the tables are exactly the same.
+     *
+     * @param table another GATK report
+     * @return true if all field in the reports, tables, and columns are equal.
+     */
+    public boolean equals(final GATKReportTable table) {
+        if ( !isSameFormat(table) ||
+                underlyingData.size() != table.underlyingData.size() )
+            return false;
+
+        final List<Object[]> myOrderedRows = getOrderedRows();
+        final List<Object[]> otherOrderedRows = table.getOrderedRows();
+
+        for ( int i = 0; i < underlyingData.size(); i++ ) {
+            final Object[] myData = myOrderedRows.get(i);
+            final Object[] otherData = otherOrderedRows.get(i);
+            for ( int j = 0; j < myData.length; j++ ) {
+                if ( !myData[j].toString().equals(otherData[j].toString()) )       // need to deal with different typing (e.g. Long vs. Integer)
+                    return false;
+            }
+        }
+
+        return true;
+    }
+
+    private List<Object[]> getOrderedRows() {
+
+        switch (sortingWay) {
+            case SORT_BY_COLUMN:
+                Collections.sort(underlyingData, new Comparator<Object[]>() {
+                    //INVARIANT the two arrays are of the same length and corresponding elements are of the same type
+                    @Override
+                    public int compare(Object[] objectArr1, Object[] objectArr2) {
+                        final int EQUAL = 0;
+                        int result = EQUAL;
+                        int l = objectArr1.length;
+                            for (int x = 0; x < l; x++) {
+                                if (objectArr1[x] instanceof Integer) {
+                                    result = ((Integer)objectArr1[x]).compareTo((Integer)objectArr2[x]);
+                                } else if (objectArr1[x] instanceof Double) {
+                                    result = ((Double)objectArr1[x]).compareTo((Double)objectArr2[x]);
+                                } else  { // default uses String comparison
+                                    result = objectArr1[x].toString().compareTo(objectArr2[x].toString());
+                                }
+                                if( result != EQUAL) {
+                                    return result;
+                                }
+                            }
+                            return result;
+                    }
+                });
+                return underlyingData;
+            case SORT_BY_ROW:
+                final TreeMap<Object, Integer> sortedMap;
+                try {
+                    sortedMap = new TreeMap<Object, Integer>(rowIdToIndex);
+                } catch (ClassCastException e) {
+                    return underlyingData;
+                }
+
+                final List<Object[]> orderedData = new ArrayList<Object[]>(underlyingData.size());
+                for ( final int rowKey : sortedMap.values() )
+                    orderedData.add(underlyingData.get(rowKey));
+
+                return orderedData;
+            default:
+                return underlyingData;
+        }
+    }
+}
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/report/GATKReportVersion.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/report/GATKReportVersion.java
new file mode 100644
index 0000000..226365b
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/report/GATKReportVersion.java
@@ -0,0 +1,101 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.engine.report;
+
+import org.broadinstitute.gatk.utils.exceptions.ReviewedGATKException;
+import org.broadinstitute.gatk.utils.exceptions.UserException;
+
+public enum GATKReportVersion {
+    /**
+     * Differences between other versions:
+     * - Does not allow spaces in cells.
+     * - Mostly fixed width but has a bug where the string width of floating point
+     * values was not measured correctly leading to columns that aren't aligned
+     */
+    V0_1("v0.1"),
+
+    /**
+     * Differences between other versions:
+     * - Spaces allowed in cells, for example in sample names with spaces in them ex: "C507/FG-CR 6".
+     * - Fixed width fixed for floating point values
+     */
+    V0_2("v0.2"),
+
+    /*
+    * Differences between v0.x
+    * - Added table and report headers
+    * - Headers changed format, include the number of tables, rows, and metadata for gathering
+    * - IS GATHERABLE
+    */
+    V1_0("v1.0"),
+
+    /*
+    * Differences between v1.0
+    * - column numbers in header reflect the actual count of columns
+    * - primary keys are never displayed
+    */
+    V1_1("v1.1");
+
+    private final String versionString;
+
+    private GATKReportVersion(String versionString) {
+        this.versionString = versionString;
+    }
+
+    @Override
+    public String toString() {
+        return versionString;
+    }
+
+    public boolean equals(GATKReportVersion that) {
+        return (versionString.equals(that.versionString));
+    }
+
+    /**
+     * Returns the GATK Report Version from the file header.
+     *
+     * @param header Header from the file starting with ##:GATKReport.v[version]
+     * @return The version as an enum.
+     */
+    public static GATKReportVersion fromHeader(String header) {
+        if ( header == null )
+            throw new UserException.BadInput("The GATK report has no version specified in the header");
+
+        if (header.startsWith("##:GATKReport.v0.1 "))
+            return GATKReportVersion.V0_1;
+
+        if (header.startsWith("##:GATKReport.v0.2 "))
+            return GATKReportVersion.V0_2;
+
+        if (header.startsWith("#:GATKReport.v1.0"))
+            return GATKReportVersion.V1_0;
+
+        if (header.startsWith("#:GATKReport.v1.1"))
+            return GATKReportVersion.V1_1;
+
+        throw new UserException.BadInput("The GATK report has an unknown/unsupported version in the header: " + header);
+    }
+}
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/resourcemanagement/ThreadAllocation.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/resourcemanagement/ThreadAllocation.java
new file mode 100644
index 0000000..0344135
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/resourcemanagement/ThreadAllocation.java
@@ -0,0 +1,116 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.engine.resourcemanagement;
+
+import org.broadinstitute.gatk.utils.exceptions.ReviewedGATKException;
+
+/**
+ * Models how threads are distributed between various components of the GATK.
+ */
+public class ThreadAllocation {
+    /**
+     * The number of CPU threads to be used by the GATK.
+     */
+    private final int numDataThreads;
+
+    /**
+     * The number of CPU threads per data thread for GATK processing
+     */
+    private final int numCPUThreadsPerDataThread;
+
+    /**
+     * Number of threads to devote exclusively to IO.  Default is 0.
+     */
+    private final int numIOThreads;
+
+    /**
+     * Should we monitor thread efficiency?
+     */
+    private final boolean monitorEfficiency;
+
+    public int getNumDataThreads() {
+        return numDataThreads;
+    }
+
+    public int getNumCPUThreadsPerDataThread() {
+        return numCPUThreadsPerDataThread;
+    }
+
+    public int getNumIOThreads() {
+        return numIOThreads;
+    }
+
+    public boolean monitorThreadEfficiency() {
+        return monitorEfficiency;
+    }
+
+    /**
+     * Are we running in parallel mode?
+     *
+     * @return true if any parallel processing is enabled
+     */
+    public boolean isRunningInParallelMode() {
+        return getTotalNumThreads() > 1;
+    }
+
+    /**
+     * What is the total number of threads in use by the GATK?
+     *
+     * @return the sum of all thread allocations in this object
+     */
+    public int getTotalNumThreads() {
+        return getNumDataThreads() * getNumCPUThreadsPerDataThread() + getNumIOThreads();
+    }
+
+    /**
+     * Construct the default thread allocation.
+     */
+    public ThreadAllocation() {
+        this(1, 1, 0, false);
+    }
+
+    /**
+     * Set up the thread allocation.  Default allocation is 1 CPU thread, 0 IO threads.
+     * (0 IO threads means that no threads are devoted exclusively to IO; they're inline on the CPU thread).
+     * @param numDataThreads Total number of threads allocated to the traversal.
+     * @param numCPUThreadsPerDataThread The number of CPU threads per data thread to allocate
+     * @param numIOThreads Total number of threads allocated exclusively to IO.
+     * @param monitorEfficiency should we monitor threading efficiency in the GATK?
+     */
+    public ThreadAllocation(final int numDataThreads,
+                            final int numCPUThreadsPerDataThread,
+                            final int numIOThreads,
+                            final boolean monitorEfficiency) {
+        if ( numDataThreads < 1 ) throw new ReviewedGATKException("numDataThreads cannot be less than 1, but saw " + numDataThreads);
+        if ( numCPUThreadsPerDataThread < 1 ) throw new ReviewedGATKException("numCPUThreadsPerDataThread cannot be less than 1, but saw " + numCPUThreadsPerDataThread);
+        if ( numIOThreads < 0 ) throw new ReviewedGATKException("numIOThreads cannot be less than 0, but saw " + numIOThreads);
+
+        this.numDataThreads = numDataThreads;
+        this.numCPUThreadsPerDataThread = numCPUThreadsPerDataThread;
+        this.numIOThreads = numIOThreads;
+        this.monitorEfficiency = monitorEfficiency;
+    }
+}
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/samples/Affection.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/samples/Affection.java
new file mode 100644
index 0000000..0e5833b
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/samples/Affection.java
@@ -0,0 +1,47 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.engine.samples;
+
+/**
+ * Categorical sample trait for association and analysis
+ *
+ * Samples can have unknown status, be affected or unaffected by the
+ * categorical trait, or they can be marked as actually having an
+ * other trait value (stored in an associated value in the Sample class)
+ *
+ * @author Mark DePristo
+ * @since Sept. 2011
+ */
+public enum Affection {
+    /** Status is unknown */
+    UNKNOWN,
+    /** Suffers from the disease */
+    AFFECTED,
+    /** Unaffected by the disease */
+    UNAFFECTED,
+    /** An "other" trait: value of the trait is stored elsewhere and is an arbitrary string */
+    OTHER
+}
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/samples/Gender.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/samples/Gender.java
new file mode 100644
index 0000000..0f26bc6
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/samples/Gender.java
@@ -0,0 +1,35 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.engine.samples;
+
+/**
+* ENUM of possible human genders: male, female, or unknown
+*/
+public enum Gender {
+    MALE,
+    FEMALE,
+    UNKNOWN
+}
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/samples/PedReader.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/samples/PedReader.java
new file mode 100644
index 0000000..8946d28
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/samples/PedReader.java
@@ -0,0 +1,311 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.engine.samples;
+
+import org.apache.log4j.Logger;
+import org.broadinstitute.gatk.utils.MathUtils;
+import org.broadinstitute.gatk.utils.exceptions.ReviewedGATKException;
+import org.broadinstitute.gatk.utils.exceptions.UserException;
+import org.broadinstitute.gatk.utils.text.XReadLines;
+
+import java.io.*;
+import java.util.*;
+
+/**
+ * Reads PED file-formatted tabular text files
+ *
+ * See http://www.broadinstitute.org/mpg/tagger/faq.html
+ * See http://pngu.mgh.harvard.edu/~purcell/plink/data.shtml#ped
+ *
+ * The "ped" file format refers to the widely-used format for linkage pedigree data.
+ * Each line describes a single (diploid) individual in the following format:
+ *
+ *      family_ID individual_ID father_ID mother_ID gender phenotype genotype_1 genotype_2 ...
+ *
+ * If your data lacks pedigree information (for example, unrelated case/control individuals),
+ * set the father_ID and mother_ID to 0. sex denotes the individual's gender with 1=male and 2=female.
+ * phenotype refers to the affected status (for association studies) where 0=unknown, 1=unaffected, 2=affected.
+ * Finally, each genotype is written as two (=diploid) integer numbers (separated by whitespace),
+ * where 1=A, 2=C, 3=G, 4=T. No header lines are allowed and all columns must be separated by whitespace.
+ * Check out the information at the PLINK website on the "ped" file format.
+ *
+ * The PED file is a white-space (space or tab) delimited file: the first six columns are mandatory:
+ *  Family ID
+ *  Individual ID
+ *  Paternal ID
+ *  Maternal ID
+ *  Sex (1=male; 2=female; other=unknown)
+ *  Phenotype
+ *
+ *  The IDs are alphanumeric: the combination of family and individual ID should uniquely identify a person.
+ *  A PED file must have 1 and only 1 phenotype in the sixth column. The phenotype can be either a
+ *  quantitative trait or an affection status column: PLINK will automatically detect which type
+ *  (i.e. based on whether a value other than 0, 1, 2 or the missing genotype code is observed).
+ *  Note that the GATK actually supports arbitrary values for quantitative trait -- not just doubles --
+ *  and are actually representing these values as strings instead of doubles
+ *
+ *  NOTE Quantitative traits with decimal points must be coded with a period/full-stop character and
+ *  not a comma, i.e. 2.394 not 2,394
+ *
+ *  If an individual's sex is unknown, then any character other than 1 or 2 can be used.
+ *  When new files are created (PED, FAM, or other which contain sex) then the original coding will be
+ *  preserved. However, these individuals will be dropped from any analyses (i.e. phenotype set to missing also)
+ *  and an error message will arise if an analysis that uses family information is requested and an
+ *  individual of 'unknown' sex is specified as a father or mother.
+ *
+ *
+ *  HINT You can add a comment to a PED or MAP file by starting the line with a # character. The rest of that
+ *  line will be ignored. Do not start any family IDs with this character therefore.
+ *
+ *  Affection status, by default, should be coded:
+ *  -9 missing
+ *   0 missing
+ *   1 unaffected
+ *   2 affected
+ *
+ * If your file is coded 0/1 to represent unaffected/affected, then use the --1 flag:
+ * plink --file mydata --1 which will specify a disease phenotype coded:
+ *
+ *  -9 missing
+ *  0 unaffected
+ *  1 affected
+ *
+ * The missing phenotype value for quantitative traits is, by default, -9 (this can also be used for
+ * disease traits as well as 0). It can be reset by including the --missing-phenotype option:
+ *
+ * Genotypes (column 7 onwards) should also be white-space delimited; they can be any character
+ * (e.g. 1,2,3,4 or A,C,G,T or anything else) except 0 which is, by default, the missing genotype
+ * character. All markers should be biallelic. All SNPs (whether haploid or not) must have two
+ * alleles specified. Either Both alleles should be missing (i.e. 0) or neither.
+ *
+ * No header row should be given. For example, here are two individuals typed for 3 SNPs (one row = one person):
+ *
+ *   FAM001  1  0 0  1  2  A A  G G  A C
+ *   FAM001  2  0 0  1  2  A A  A G  0 0
+ *   ...
+ *
+ * Note that the GATK does not support genotypes in a PED file.
+ *
+ * @author Mark DePristo
+ * @since 2011
+ */
+public class PedReader {
+    private static Logger logger = Logger.getLogger(PedReader.class);
+    final static private Set<String> CATAGORICAL_TRAIT_VALUES = new HashSet<String>(Arrays.asList("-9", "0", "1", "2"));
+    final static private String commentMarker = "#";
+
+    /**
+     * An enum that specifies which, if any, of the standard PED fields are
+     * missing from the input records.  For example, suppose we have the full record:
+     *
+     * "fam1 kid dad mom 1 2"
+     *
+     * indicating a male affected child.  This can be parsed with the -ped x.ped argument
+     * to the GATK.  Suppose we only have:
+     *
+     * "fam1 kid 1"
+     *
+     * we can parse the reduced version of this record with -ped:NO_PARENTS,NO_PHENOTYPE x.ped
+     */
+    public enum MissingPedField {
+        /**
+         * The PED records do not have the first (FAMILY_ID) argument.  The family id
+         * will be set to null / empty.
+         */
+        NO_FAMILY_ID,
+
+        /**
+         * The PED records do not have either the paternal or maternal IDs, so
+         * the corresponding IDs are set to null.
+         */
+        NO_PARENTS,
+
+        /**
+         * The PED records do not have the GENDER field, so the sex of each
+         * sample will be set to UNKNOWN.
+         */
+        NO_SEX,
+
+        /**
+         * The PED records do not have the PHENOTYPE field, so the phenotype
+         * of each sample will be set to UNKNOWN.
+         */
+        NO_PHENOTYPE
+    }
+
+    protected enum Field {
+        FAMILY_ID, INDIVIDUAL_ID, PATERNAL_ID, MATERNAL_ID, GENDER, PHENOTYPE
+    }
+
+    // phenotype
+    private final static String MISSING_VALUE1 = "-9";
+    private final static String MISSING_VALUE2 = "0";
+    private final static String PHENOTYPE_UNAFFECTED = "1";
+    private final static String PHENOTYPE_AFFECTED = "2";
+
+    // Sex
+    private final static String SEX_MALE = "1";
+    private final static String SEX_FEMALE = "2";
+    // other=unknown
+
+    public PedReader() { }
+
+    public final List<Sample> parse(File source, EnumSet<MissingPedField> missingFields, SampleDB sampleDB) throws FileNotFoundException  {
+        logger.info("Reading PED file " + source + " with missing fields: " + missingFields);
+        return parse(new FileReader(source), missingFields, sampleDB);
+    }
+
+    public final List<Sample> parse(final String source, EnumSet<MissingPedField> missingFields, SampleDB sampleDB) {
+        logger.warn("Reading PED string: \"" + source + "\" with missing fields: " + missingFields);
+        return parse(new StringReader(source.replace(";", String.format("%n"))), missingFields, sampleDB);
+    }
+
+    public final List<Sample> parse(Reader reader, EnumSet<MissingPedField> missingFields, SampleDB sampleDB) {
+        final List<String> lines = new XReadLines(reader).readLines();
+
+        // What are the record offsets?
+        final int familyPos = missingFields.contains(MissingPedField.NO_FAMILY_ID) ? -1 : 0;
+        final int samplePos = familyPos + 1;
+        final int paternalPos = missingFields.contains(MissingPedField.NO_PARENTS) ? -1 : samplePos + 1;
+        final int maternalPos = missingFields.contains(MissingPedField.NO_PARENTS) ? -1 : paternalPos + 1;
+        final int sexPos = missingFields.contains(MissingPedField.NO_SEX) ? -1 : Math.max(maternalPos, samplePos) + 1;
+        final int phenotypePos = missingFields.contains(MissingPedField.NO_PHENOTYPE) ? -1 : Math.max(sexPos, Math.max(maternalPos, samplePos)) + 1;
+        final int nExpectedFields = MathUtils.arrayMaxInt(Arrays.asList(samplePos, paternalPos, maternalPos, sexPos, phenotypePos)) + 1;
+
+        // go through once and determine properties
+        int lineNo = 1;
+        boolean isQT = false;
+        final List<String[]> splits = new ArrayList<String[]>(lines.size());
+        for ( final String line : lines ) {
+            if ( line.startsWith(commentMarker)) continue;
+            if ( line.trim().equals("") ) continue;
+
+            final String[] parts = line.split("\\s+");
+
+            if ( parts.length != nExpectedFields )
+                throw new UserException.MalformedFile(reader.toString(), "Bad PED line " + lineNo + ": wrong number of fields");
+
+            if ( phenotypePos != -1 ) {
+                isQT = isQT || ! CATAGORICAL_TRAIT_VALUES.contains(parts[phenotypePos]);
+            }
+
+            splits.add(parts);
+            lineNo++;
+        }
+        logger.info("Phenotype is other? " + isQT);
+
+        // now go through and parse each record
+        lineNo = 1;
+        final List<Sample> samples = new ArrayList<Sample>(splits.size());
+        for ( final String[] parts : splits ) {
+            String familyID = null, individualID, paternalID = null, maternalID = null;
+            Gender sex = Gender.UNKNOWN;
+            String quantitativePhenotype = Sample.UNSET_QT;
+            Affection affection = Affection.UNKNOWN;
+
+            if ( familyPos != -1 ) familyID = maybeMissing(parts[familyPos]);
+            individualID = parts[samplePos];
+            if ( paternalPos != -1 ) paternalID = maybeMissing(parts[paternalPos]);
+            if ( maternalPos != -1 ) maternalID = maybeMissing(parts[maternalPos]);
+
+            if ( sexPos != -1 ) {
+                if ( parts[sexPos].equals(SEX_MALE) ) sex = Gender.MALE;
+                else if ( parts[sexPos].equals(SEX_FEMALE) ) sex = Gender.FEMALE;
+                else sex = Gender.UNKNOWN;
+            }
+
+            if ( phenotypePos != -1 ) {
+                if ( isQT ) {
+                    if ( parts[phenotypePos].equals(MISSING_VALUE1) )
+                        affection = Affection.UNKNOWN;
+                    else {
+                        affection = Affection.OTHER;
+                        quantitativePhenotype = parts[phenotypePos];
+                    }
+                } else {
+                    if ( parts[phenotypePos].equals(MISSING_VALUE1) ) affection = Affection.UNKNOWN;
+                    else if ( parts[phenotypePos].equals(MISSING_VALUE2) ) affection = Affection.UNKNOWN;
+                    else if ( parts[phenotypePos].equals(PHENOTYPE_UNAFFECTED) ) affection = Affection.UNAFFECTED;
+                    else if ( parts[phenotypePos].equals(PHENOTYPE_AFFECTED) ) affection = Affection.AFFECTED;
+                    else throw new ReviewedGATKException("Unexpected phenotype type " + parts[phenotypePos] + " at line " + lineNo);
+                }
+            }
+
+            final Sample s = new Sample(individualID, sampleDB, familyID, paternalID, maternalID, sex, affection, quantitativePhenotype);
+            samples.add(s);
+            sampleDB.addSample(s);
+            lineNo++;
+        }
+
+        for ( final Sample sample : new ArrayList<Sample>(samples) ) {
+            Sample dad = maybeAddImplicitSample(sampleDB, sample.getPaternalID(), sample.getFamilyID(), Gender.MALE);
+            if ( dad != null ) samples.add(dad);
+
+            Sample mom = maybeAddImplicitSample(sampleDB, sample.getMaternalID(), sample.getFamilyID(), Gender.FEMALE);
+            if ( mom != null ) samples.add(mom);
+        }
+
+        return samples;
+    }
+
+    private final static String maybeMissing(final String string) {
+        if ( string.equals(MISSING_VALUE1) || string.equals(MISSING_VALUE2) )
+            return null;
+        else
+            return string;
+    }
+
+    private final Sample maybeAddImplicitSample(SampleDB sampleDB, final String id, final String familyID, final Gender gender) {
+        if ( id != null && sampleDB.getSample(id) == null ) {
+            Sample s = new Sample(id, sampleDB, familyID, null, null, gender, Affection.UNKNOWN, Sample.UNSET_QT);
+            sampleDB.addSample(s);
+            return s;
+        } else
+            return null;
+    }
+
+    /**
+     * Parses a list of tags from the command line, assuming it comes from the GATK Engine
+     * tags, and returns the corresponding EnumSet.
+     *
+     * @param arg the actual engine arg, used for the UserException if there's an error
+     * @param tags a list of string tags that should be converted to the MissingPedField value
+     * @return
+     */
+    public static final EnumSet<MissingPedField> parseMissingFieldTags(final Object arg, final List<String> tags) {
+        final EnumSet<MissingPedField> missingFields = EnumSet.noneOf(MissingPedField.class);
+
+        for ( final String tag : tags ) {
+            try {
+                missingFields.add(MissingPedField.valueOf(tag));
+            } catch ( IllegalArgumentException e ) {
+                throw new UserException.BadArgumentValue(arg.toString(), "Unknown tag " + tag + " allowed values are " + MissingPedField.values());
+            }
+        }
+
+        return missingFields;
+    }
+}
\ No newline at end of file
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/samples/PedigreeValidationType.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/samples/PedigreeValidationType.java
new file mode 100644
index 0000000..14fefd2
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/samples/PedigreeValidationType.java
@@ -0,0 +1,42 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.engine.samples;
+
+/**
+*
+*/
+public enum PedigreeValidationType {
+    /**
+     * Require if a pedigree file is provided at all samples in the VCF or BAM files have a corresponding
+     * entry in the pedigree file(s).
+     */
+    STRICT,
+
+    /**
+     * Do not enforce any overlap between the VCF/BAM samples and the pedigree data
+     * */
+    SILENT
+}
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/samples/Sample.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/samples/Sample.java
new file mode 100644
index 0000000..0d60c39
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/samples/Sample.java
@@ -0,0 +1,259 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.engine.samples;
+
+
+import org.broadinstitute.gatk.utils.exceptions.UserException;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ *
+ */
+public class Sample implements Comparable<Sample> { // implements java.io.Serializable {
+    final private String familyID, paternalID, maternalID;
+    final private Gender gender;
+    final private String otherPhenotype;
+    final private Affection affection;
+    final private String ID;
+    final private SampleDB infoDB;
+    final private Map<String, Object> properties = new HashMap<String, Object>();
+
+    public final static String UNSET_QT = null;
+
+    public Sample(final String ID, final SampleDB infoDB,
+                  final String familyID, final String paternalID, final String maternalID,
+                  final Gender gender, final Affection affection, final String otherPhenotype) {
+        this.familyID = familyID;
+        this.paternalID = paternalID;
+        this.maternalID = maternalID;
+        this.gender = gender;
+        this.otherPhenotype = otherPhenotype;
+        this.affection = affection;
+        this.ID = ID;
+        this.infoDB = infoDB;
+    }
+
+    protected Sample(final String ID,
+                     final String familyID, final String paternalID, final String maternalID,
+                     final Gender gender, final Affection affection, final String otherPhenotype) {
+        this(ID, null, familyID, paternalID, maternalID, gender, affection, otherPhenotype);
+    }
+
+    protected Sample(final String ID,
+                     final String familyID, final String paternalID, final String maternalID,
+                     final Gender gender, final Affection affection) {
+        this(ID, null, familyID, paternalID, maternalID, gender, affection, UNSET_QT);
+    }
+
+
+    public Sample(final String ID, final SampleDB infoDB,
+                  final String familyID, final String paternalID, final String maternalID, final Gender gender) {
+        this(ID, infoDB, familyID, paternalID, maternalID, gender, Affection.UNKNOWN, UNSET_QT);
+    }
+
+    public Sample(final String ID, final SampleDB infoDB, final Affection affection, final String otherPhenotype) {
+        this(ID, infoDB, null, null, null, Gender.UNKNOWN, affection, otherPhenotype);
+    }
+
+    public Sample(String id, SampleDB infoDB) {
+        this(id, infoDB, null, null, null,
+                Gender.UNKNOWN, Affection.UNKNOWN, UNSET_QT);
+    }
+
+    // -------------------------------------------------------------------------------------
+    //
+    // standard property getters
+    //
+    // -------------------------------------------------------------------------------------
+
+    public String getID() {
+        return ID;
+    }
+
+    public String getFamilyID() {
+        return familyID;
+    }
+
+    public String getPaternalID() {
+        return paternalID;
+    }
+
+    public String getMaternalID() {
+        return maternalID;
+    }
+
+    public Affection getAffection() {
+        return affection;
+    }
+
+    public boolean hasOtherPhenotype() {
+        return affection == Affection.OTHER;
+    }
+
+    public String getOtherPhenotype() {
+        return otherPhenotype;
+    }
+
+    /**
+     * Get the sample's mother
+     * @return sample object with relationship mother, if exists, or null
+     */
+    public Sample getMother() {
+        return infoDB.getSample(maternalID);
+    }
+
+    /**
+     * Get the sample's father
+     * @return sample object with relationship father, if exists, or null
+     */
+    public Sample getFather() {
+        return infoDB.getSample(paternalID);
+    }
+
+    public ArrayList<Sample> getParents(){
+        ArrayList<Sample> parents = new ArrayList<Sample>(2);
+        Sample parent = getMother();
+        if(parent != null)
+            parents.add(parent);
+        parent = getFather();
+        if(parent != null)
+            parents.add(parent);
+        return parents;
+    }
+
+    /**
+     * Get gender of the sample
+     * @return property of key "gender" - must be of type Gender
+     */
+    public Gender getGender() {
+        return gender;
+    }
+
+    @Override
+    public int compareTo(final Sample sample) {
+        return ID.compareTo(sample.getID());
+    }
+
+    @Override
+    public String toString() {
+        return String.format("Sample %s fam=%s dad=%s mom=%s gender=%s affection=%s qt=%s props=%s",
+                getID(), getFamilyID(), getPaternalID(), getMaternalID(), getGender(), getAffection(),
+                getOtherPhenotype(), properties);
+    }
+
+//    // -------------------------------------------------------------------------------------
+//    //
+//    // code for working with additional -- none standard -- properites
+//    //
+//    // -------------------------------------------------------------------------------------
+//
+//    public Map<String, Object> getExtraProperties() {
+//        return Collections.unmodifiableMap(properties);
+//    }
+//
+//    /**
+//     * Get one property
+//     * @param key key of property
+//     * @return value of property as generic object
+//     */
+//    public Object getExtraPropertyValue(final String key) {
+//        return properties.get(key);
+//    }
+//
+//    /**
+//     *
+//     * @param key property key
+//     * @return true if sample has this property (even if its value is null)
+//     */
+//    public boolean hasExtraProperty(String key) {
+//        return properties.containsKey(key);
+//    }
+
+    @Override
+    public int hashCode() {
+        return ID.hashCode();
+    }
+
+    @Override
+    public boolean equals(final Object o) {
+        if(o == null)
+            return false;
+        if(o instanceof Sample) {
+            Sample otherSample = (Sample)o;
+            return ID.equals(otherSample.ID) &&
+                    equalOrNull(familyID, otherSample.familyID) &&
+                    equalOrNull(paternalID, otherSample.paternalID) &&
+                    equalOrNull(maternalID, otherSample.maternalID) &&
+                    equalOrNull(gender, otherSample.gender) &&
+                    equalOrNull(otherPhenotype, otherSample.otherPhenotype) &&
+                    equalOrNull(affection, otherSample.affection) &&
+                    equalOrNull(properties, otherSample.properties);
+        }
+        return false;
+    }
+
+    private final static boolean equalOrNull(final Object o1, final Object o2) {
+        if ( o1 == null )
+            return o2 == null;
+        else
+            return o2 == null ? false : o1.equals(o2);
+    }
+
+    private final static <T> T mergeValues(final String name, final String field, final T o1, final T o2, final T emptyValue) {
+        if ( o1 == null || o1.equals(emptyValue) ) {
+            // take o2 if both are null, otherwise keep o2
+            return o2 == null ? null : o2;
+        } else {
+            if ( o2 == null || o2.equals(emptyValue) )
+                return o1; // keep o1, since it's a real value
+            else {
+                // both o1 and o2 have a value
+                if ( o1 == o2 )
+                    return o1;
+                else
+                    throw new UserException("Inconsistent values detected for " + name + " for field " + field + " value1 " + o1 + " value2 " + o2);
+            }
+        }
+    }
+
+    public final static Sample mergeSamples(final Sample prev, final Sample next) {
+        if ( prev.equals(next) )
+            return next;
+        else {
+            return new Sample(prev.getID(), prev.infoDB,
+                    mergeValues(prev.getID(), "Family_ID", prev.getFamilyID(), next.getFamilyID(), null),
+                    mergeValues(prev.getID(), "Paternal_ID", prev.getPaternalID(), next.getPaternalID(), null),
+                    mergeValues(prev.getID(), "Material_ID", prev.getMaternalID(), next.getMaternalID(), null),
+                    mergeValues(prev.getID(), "Gender", prev.getGender(), next.getGender(), Gender.UNKNOWN),
+                    mergeValues(prev.getID(), "Affection", prev.getAffection(), next.getAffection(), Affection.UNKNOWN),
+                    mergeValues(prev.getID(), "OtherPhenotype", prev.getOtherPhenotype(), next.getOtherPhenotype(), UNSET_QT));
+                    //mergeValues(prev.getID(), "ExtraProperties", prev.getExtraProperties(), next.getExtraProperties(), Collections.emptyMap()));
+        }
+    }
+}
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/samples/SampleDB.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/samples/SampleDB.java
new file mode 100644
index 0000000..141f01b
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/samples/SampleDB.java
@@ -0,0 +1,338 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.engine.samples;
+
+import htsjdk.samtools.SAMReadGroupRecord;
+import htsjdk.samtools.SAMRecord;
+import org.broadinstitute.gatk.utils.exceptions.GATKException;
+import htsjdk.variant.variantcontext.Genotype;
+
+import java.util.*;
+
+/**
+ *
+ */
+public class SampleDB {
+    /**
+     * This is where Sample objects are stored. Samples are usually accessed by their ID, which is unique, so
+     * this is stored as a HashMap.
+     */
+    private final HashMap<String, Sample> samples = new HashMap<String, Sample>();
+
+    /**
+     * Constructor takes both a SAM header and sample files because the two must be integrated.
+     */
+    public SampleDB() {
+
+    }
+
+    /**
+     * Protected function to add a single sample to the database
+     *
+     * @param sample to be added
+     */
+    protected SampleDB addSample(Sample sample) {
+        Sample prev = samples.get(sample.getID());
+        if ( prev != null )
+            sample = Sample.mergeSamples(prev, sample);
+        samples.put(sample.getID(), sample);
+        return this;
+    }
+
+    // --------------------------------------------------------------------------------
+    //
+    // Functions for getting a sample from the DB
+    //
+    // --------------------------------------------------------------------------------
+
+    /**
+     * Get a sample by its ID
+     * If an alias is passed in, return the main sample object 
+     * @param id
+     * @return sample Object with this ID, or null if this does not exist
+     */
+    public Sample getSample(String id) {
+        return samples.get(id);
+    }
+
+    /**
+     *
+     * @param read
+     * @return sample Object with this ID, or null if this does not exist
+     */
+    public Sample getSample(final SAMRecord read) {
+        return getSample(read.getReadGroup());
+    }
+
+    /**
+     *
+     * @param rg
+     * @return sample Object with this ID, or null if this does not exist
+     */
+    public Sample getSample(final SAMReadGroupRecord rg) {
+        return getSample(rg.getSample());
+    }
+
+    /**
+     * @param g Genotype
+     * @return sample Object with this ID, or null if this does not exist
+     */
+    public Sample getSample(final Genotype g) {
+        return getSample(g.getSampleName());
+    }
+
+    // --------------------------------------------------------------------------------
+    //
+    // Functions for accessing samples in the DB
+    //
+    // --------------------------------------------------------------------------------
+
+    /**
+     * Get number of sample objects
+     * @return size of samples map
+     */
+    public int sampleCount() {
+        return samples.size();
+    }
+
+    public Set<Sample> getSamples() {
+        return new LinkedHashSet<>(samples.values());
+    }
+
+    public Collection<String> getSampleNames() {
+        return Collections.unmodifiableCollection(samples.keySet());
+    }
+
+
+    /**
+     * Takes a collection of sample names and returns their corresponding sample objects
+     * Note that, since a set is returned, if you pass in a list with duplicates names there will not be any duplicates in the returned set
+     * @param sampleNameList Set of sample names
+     * @return Corresponding set of samples
+     */
+    public Set<Sample> getSamples(Collection<String> sampleNameList) {
+        HashSet<Sample> samples = new HashSet<Sample>();
+        for (String name : sampleNameList) {
+            try {
+                samples.add(getSample(name));
+            }
+            catch (Exception e) {
+                throw new GATKException("Could not get sample with the following ID: " + name, e);
+            }
+        }
+        return samples;
+    }
+
+    // --------------------------------------------------------------------------------
+    //
+    // Higher level pedigree functions
+    //
+    // --------------------------------------------------------------------------------
+
+    /**
+     * Returns a sorted set of the family IDs in all samples (excluding null ids)
+     * @return
+     */
+    public final Set<String> getFamilyIDs() {
+        return getFamilies().keySet();
+    }
+
+    /**
+     * Returns a map from family ID -> set of family members for all samples with
+     * non-null family ids
+     *
+     * @return
+     */
+    public final Map<String, Set<Sample>> getFamilies() {
+        return getFamilies(null);
+    }
+
+    /**
+     * Returns a map from family ID -> set of family members for all samples in sampleIds with
+     * non-null family ids
+     *
+     * @param sampleIds - all samples to include. If null is passed then all samples are returned.
+     * @return
+     */
+    public final Map<String, Set<Sample>> getFamilies(Collection<String> sampleIds) {
+        final Map<String, Set<Sample>> families = new TreeMap<String, Set<Sample>>();
+
+        for ( final Sample sample : samples.values() ) {
+            if(sampleIds == null || sampleIds.contains(sample.getID())){
+                final String famID = sample.getFamilyID();
+                if ( famID != null ) {
+                    if ( ! families.containsKey(famID) )
+                        families.put(famID, new TreeSet<Sample>());
+                    families.get(famID).add(sample);
+                }
+            }
+        }
+        return families;
+    }
+
+    /**
+     * Returns all the trios present in the sample database. The strictOneChild parameter determines
+     * whether multiple children of the same parents resolve to multiple trios, or are excluded
+     * @param strictOneChild - exclude pedigrees with >1 child for parental pair
+     * @return - all of the mother+father=child triplets, subject to strictOneChild
+     */
+    public final Set<Trio> getTrios(boolean strictOneChild) {
+        Set<Trio> trioSet = new HashSet<Trio>();
+        for ( String familyString : getFamilyIDs() ) {
+            Set<Sample> family = getFamily(familyString);
+            for ( Sample sample : family) {
+                if ( sample.getParents().size() == 2 ) {
+                    Trio trio = new Trio(sample.getMother(),sample.getFather(),sample);
+                    trioSet.add(trio);
+                }
+            }
+        }
+
+        if ( strictOneChild )
+            trioSet = removeTriosWithSameParents(trioSet);
+
+        return trioSet;
+    }
+
+    /**
+     * Returns all the trios present in the db. See getTrios(boolean strictOneChild)
+     * @return all the trios present in the samples db.
+     */
+    public final Set<Trio> getTrios() {
+        return getTrios(false);
+    }
+
+    /**
+     * Subsets a set of trios to only those with nonmatching founders. If two (or more) trio objects have
+     * the same mother and father, then both (all) are removed from the returned set.
+     * @param trios - a set of Trio objects
+     * @return those subset of Trio objects in the input set with nonmatching founders
+     */
+    private Set<Trio> removeTriosWithSameParents(final Set<Trio> trios) {
+        Set<Trio> filteredTrios = new HashSet<Trio>();
+        filteredTrios.addAll(trios);
+        Set<Trio> triosWithSameParents = new HashSet<Trio>();
+        for ( Trio referenceTrio : filteredTrios ) {
+            for ( Trio compareTrio : filteredTrios ) {
+                if ( referenceTrio != compareTrio &&
+                     referenceTrio.getFather().equals(compareTrio.getFather()) &&
+                     referenceTrio.getMother().equals(compareTrio.getMother()) ) {
+                    triosWithSameParents.add(referenceTrio);
+                    triosWithSameParents.add(compareTrio);
+                }
+            }
+        }
+        filteredTrios.removeAll(triosWithSameParents);
+        return filteredTrios;
+    }
+
+    /**
+     * Returns the set of all children that have both of their parents.
+     * Note that if a family is composed of more than 1 child, each child is
+     * returned.
+     * @return - all the children that have both of their parents
+     * @deprecated - getTrios() replaces this function
+     */
+    @Deprecated
+    public final Set<Sample> getChildrenWithParents(){
+        return getChildrenWithParents(false);
+    }
+
+    /**
+     * Returns the set of all children that have both of their parents.
+     * Note that if triosOnly = false, a family is composed of more than 1 child, each child is
+     * returned.
+     *
+     * This method can be used wherever trios are needed
+     *
+     * @param triosOnly - if set to true, only strict trios are returned
+     * @return - all the children that have both of their parents
+     * @deprecated - getTrios(boolean strict) replaces this function
+     * @bug -- does not work for extracting multiple generations of trios, e.g.
+     * ..........Mom1------Dad1
+     * ................|
+     * ..............Child1--------Mom2
+     * .......................|
+     * .....................Child2
+     */
+    @Deprecated
+    public final Set<Sample> getChildrenWithParents(boolean triosOnly) {
+
+        Map<String, Set<Sample>> families = getFamilies();
+        final Set<Sample> childrenWithParents = new HashSet<Sample>();
+        Iterator<Sample> sampleIterator;
+
+        for ( Set<Sample> familyMembers: families.values() ) {
+            if(triosOnly && familyMembers.size() != 3)
+                continue;
+
+            sampleIterator = familyMembers.iterator();
+            Sample sample;
+            while(sampleIterator.hasNext()){
+                sample = sampleIterator.next();
+                if(sample.getParents().size() == 2 && familyMembers.containsAll(sample.getParents()))
+                    childrenWithParents.add(sample);
+            }
+
+        }
+        return childrenWithParents;
+    }
+
+    /**
+     * Return all samples with a given family ID
+     * @param familyId
+     * @return
+     */
+    public Set<Sample> getFamily(String familyId) {
+        return getFamilies().get(familyId);
+    }
+
+    /**
+     * Returns all children of a given sample
+     * See note on the efficiency of getFamily() - since this depends on getFamily() it's also not efficient
+     * @param sample
+     * @return
+     */
+    public Set<Sample> getChildren(Sample sample) {
+        final HashSet<Sample> children = new HashSet<Sample>();
+        for ( final Sample familyMember : getFamily(sample.getFamilyID())) {
+            if ( familyMember.getMother() == sample || familyMember.getFather() == sample ) {
+                children.add(familyMember);
+            }
+        }
+        return children;
+    }
+
+    public Set<String> getFounderIds(){
+        Set<String> founders = new HashSet<String>();
+        for(Sample sample : getSamples()){
+            if(sample.getParents().size()<1)
+                founders.add(sample.getID());
+
+        }
+        return founders;
+    }
+}
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/samples/SampleDBBuilder.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/samples/SampleDBBuilder.java
new file mode 100644
index 0000000..6fdb9fa
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/samples/SampleDBBuilder.java
@@ -0,0 +1,161 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.engine.samples;
+
+import htsjdk.samtools.SAMFileHeader;
+import org.broadinstitute.gatk.engine.GenomeAnalysisEngine;
+import org.broadinstitute.gatk.utils.SampleUtils;
+import org.broadinstitute.gatk.utils.exceptions.UserException;
+
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.util.*;
+
+/**
+ *
+ */
+public class SampleDBBuilder {
+    PedigreeValidationType validationStrictness;
+    final SampleDB sampleDB = new SampleDB();
+    final GenomeAnalysisEngine engine;
+
+    Set<Sample> samplesFromDataSources = new HashSet<Sample>();
+    Set<Sample> samplesFromPedigrees = new HashSet<Sample>();
+
+    /** for testing only */
+    protected SampleDBBuilder(PedigreeValidationType validationStrictness) {
+        engine = null;
+        this.validationStrictness = validationStrictness;
+    }
+
+    /**
+     * Constructor takes both a SAM header and sample files because the two must be integrated.
+     */
+    public SampleDBBuilder(GenomeAnalysisEngine engine, PedigreeValidationType validationStrictness) {
+        this.engine = engine;
+        this.validationStrictness = validationStrictness;
+    }
+
+    /**
+     * Hallucinates sample objects for all the samples in the SAM file and stores them
+     */
+    public SampleDBBuilder addSamplesFromSAMHeader(final SAMFileHeader header) {
+        addSamplesFromSampleNames(SampleUtils.getSAMFileSamples(header));
+        return this;
+    }
+
+    public SampleDBBuilder addSamplesFromSampleNames(final Collection<String> sampleNames) {
+        for (final String sampleName : sampleNames) {
+            if (sampleDB.getSample(sampleName) == null) {
+                final Sample newSample = new Sample(sampleName, sampleDB);
+                sampleDB.addSample(newSample);
+                samplesFromDataSources.add(newSample); // keep track of data source samples
+            }
+        }
+        return this;
+    }
+
+    public SampleDBBuilder addSamplesFromPedigreeFiles(final List<File> pedigreeFiles) {
+        for (final File pedFile : pedigreeFiles) {
+            Collection<Sample> samples = addSamplesFromPedigreeArgument(pedFile);
+            samplesFromPedigrees.addAll(samples);
+        }
+
+        return this;
+    }
+
+    public SampleDBBuilder addSamplesFromPedigreeStrings(final List<String> pedigreeStrings) {
+        for (final String pedString : pedigreeStrings) {
+            Collection<Sample> samples = addSamplesFromPedigreeArgument(pedString);
+            samplesFromPedigrees.addAll(samples);
+        }
+
+        return this;
+    }
+
+    /**
+     * Parse one sample file and integrate it with samples that are already there
+     * Fail quickly if we find any errors in the file
+     */
+    private Collection<Sample> addSamplesFromPedigreeArgument(File sampleFile) {
+        final PedReader reader = new PedReader();
+
+        try {
+            return reader.parse(sampleFile, getMissingFields(sampleFile), sampleDB);
+        } catch ( FileNotFoundException e ) {
+            throw new UserException.CouldNotReadInputFile(sampleFile, e);
+        }
+    }
+
+    private Collection<Sample> addSamplesFromPedigreeArgument(final String string) {
+        final PedReader reader = new PedReader();
+        return reader.parse(string, getMissingFields(string), sampleDB);
+    }
+
+    public SampleDB getFinalSampleDB() {
+        validate();
+        return sampleDB;
+    }
+
+    public EnumSet<PedReader.MissingPedField> getMissingFields(final Object engineArg) {
+        if ( engine == null )
+            return EnumSet.noneOf(PedReader.MissingPedField.class);
+        else {
+            final List<String> posTags = engine.getTags(engineArg).getPositionalTags();
+            return PedReader.parseMissingFieldTags(engineArg, posTags);
+        }
+    }
+
+    // --------------------------------------------------------------------------------
+    //
+    // Validation
+    //
+    // --------------------------------------------------------------------------------
+
+    protected final void validate() {
+        validatePedigreeIDUniqueness();
+        if ( validationStrictness != PedigreeValidationType.SILENT ) {
+            // check that samples in data sources are all annotated, if anything is annotated
+            if ( ! samplesFromPedigrees.isEmpty() && ! samplesFromDataSources.isEmpty() ) {
+                final Set<String> sampleNamesFromPedigrees = new HashSet<String>();
+                for ( final Sample pSample : samplesFromPedigrees )
+                    sampleNamesFromPedigrees.add(pSample.getID());
+
+                for ( final Sample dsSample : samplesFromDataSources )
+                    if ( ! sampleNamesFromPedigrees.contains(dsSample.getID()) )
+                        throw new UserException("Sample " + dsSample.getID() + " found in data sources but not in pedigree files with STRICT pedigree validation");
+            }
+        }
+    }
+
+    private void validatePedigreeIDUniqueness() {
+        Set<String> pedigreeIDs = new HashSet<String>();
+        for ( Sample sample : samplesFromPedigrees ) {
+            pedigreeIDs.add(sample.getID());
+        }
+        assert pedigreeIDs.size() == samplesFromPedigrees.size() : "The number of sample IDs extracted from the pedigree does not equal the number of samples in the pedigree. Is a sample associated with multiple families?";
+    }
+}
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/samples/Trio.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/samples/Trio.java
new file mode 100644
index 0000000..b5a698b
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/samples/Trio.java
@@ -0,0 +1,70 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.engine.samples;
+
+/**
+ * A class for imposing a trio structure on three samples; a common paradigm
+ *
+ * todo -- there should probably be an interface or abstract class "Pedigree" that generalizes the notion of
+ *      -- imposing structure on samples. But given how complex pedigrees can quickly become, it's not
+ *      -- clear the best way to do this.
+ */
+public class Trio {
+    private Sample mother;
+    private Sample father;
+    private Sample child;
+
+    public Trio(Sample mom, Sample dad, Sample spawn) {
+        assert mom.getID().equals(spawn.getMaternalID()) && dad.getID().equals(spawn.getPaternalID()) : "Samples passed to trio constructor do not form a trio";
+        mother = mom;
+        father = dad;
+        child = spawn;
+    }
+
+    public Sample getMother() {
+        return mother;
+    }
+
+    public String getMaternalID() {
+        return mother.getID();
+    }
+
+    public Sample getFather() {
+        return father;
+    }
+
+    public String getPaternalID() {
+        return father.getID();
+    }
+
+    public Sample getChild() {
+        return child;
+    }
+
+    public String getChildID() {
+        return child.getID();
+    }
+}
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/traversals/TAROrderedReadCache.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/traversals/TAROrderedReadCache.java
new file mode 100644
index 0000000..d28ea3b
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/traversals/TAROrderedReadCache.java
@@ -0,0 +1,168 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.engine.traversals;
+
+import org.broadinstitute.gatk.engine.downsampling.Downsampler;
+import org.broadinstitute.gatk.engine.downsampling.ReservoirDownsampler;
+import org.broadinstitute.gatk.utils.sam.AlignmentStartComparator;
+import org.broadinstitute.gatk.utils.sam.GATKSAMRecord;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+/**
+ * Subsystem to track a list of all reads currently live in the TraverseActiveRegions system,
+ * while limiting the total number of reads to a maximum capacity.
+ *
+ * User: depristo
+ * Date: 4/7/13
+ * Time: 11:23 AM
+ */
+public class TAROrderedReadCache {
+    private final int maxCapacity;
+    private ArrayList<GATKSAMRecord> undownsampledCache;
+    private Downsampler<GATKSAMRecord> downsampler;
+
+    private static final int UNDOWNSAMPLED_CACHE_MAX_INITIAL_SIZE = 10000;
+
+    /**
+     * Create a new empty ReadCache
+     * @param maxCapacity the max capacity of the read cache.
+     */
+    public TAROrderedReadCache( final int maxCapacity ) {
+        if ( maxCapacity < 0 ) throw new IllegalArgumentException("maxCapacity must be >= 0 but got " + maxCapacity);
+        this.maxCapacity = maxCapacity;
+
+        // The one we're not currently using will always be null:
+        initializeUndownsampledCache();
+        this.downsampler = null;
+    }
+
+    /**
+     * Moves all reads over to the downsampler, causing it to be used from this point on. Should be called
+     * when the undownsampledCache fills up and we need to start discarding reads. Since the
+     * ReservoirDownsampler doesn't preserve relative ordering, pop operations become expensive
+     * after this point, as they require a O(n log n) sort.
+     */
+    private void activateDownsampler() {
+        downsampler = new ReservoirDownsampler<>(maxCapacity, false);
+        downsampler.submit(undownsampledCache);
+        undownsampledCache = null; // preferable to the O(n) clear() method
+    }
+
+    /**
+     * Allocate the undownsampled cache used when we have fewer than maxCapacity items
+     */
+    private void initializeUndownsampledCache() {
+        undownsampledCache = new ArrayList<>(Math.min(maxCapacity + 1, UNDOWNSAMPLED_CACHE_MAX_INITIAL_SIZE));
+    }
+
+    /**
+     * What's the maximum number of reads we'll store in the cache?
+     * @return a positive integer
+     */
+    public int getMaxCapacity() {
+        return maxCapacity;
+    }
+
+    /**
+     * Add a single read to this cache.  Assumed to be in sorted order w.r.t. the previously added reads
+     * @param read a read to add
+     */
+    public void add( final GATKSAMRecord read ) {
+        if ( read == null ) throw new IllegalArgumentException("Read cannot be null");
+
+        if ( downsampler != null ) {
+            downsampler.submit(read);
+        }
+        else {
+            undownsampledCache.add(read);
+
+            // No more room in the undownsampledCache? Time to start downsampling
+            if ( undownsampledCache.size() > maxCapacity ) {
+                activateDownsampler();
+            }
+        }
+    }
+
+    /**
+     * Add a collection of reads to this cache.  Assumed to be in sorted order w.r.t. the previously added reads and each other
+     * @param reads a collection of reads to add
+     */
+    public void addAll( final List<GATKSAMRecord> reads ) {
+        if ( reads == null ) throw new IllegalArgumentException("Reads cannot be null");
+        for ( final GATKSAMRecord read : reads ) {
+            add(read);
+        }
+    }
+
+    /**
+     * How many reads are currently in the cache?
+     * @return a positive integer
+     */
+    public int size() {
+        return downsampler != null ? downsampler.size() : undownsampledCache.size();
+    }
+
+    /**
+     * How many reads were discarded since the last call to popCurrentReads
+     *
+     * @return number of items discarded during downsampling since last pop operation
+     */
+    public int getNumDiscarded() {
+        return downsampler != null ? downsampler.getNumberOfDiscardedItems() : 0;
+    }
+
+    /**
+     * Removes all reads currently in the cache, and returns them in sorted order (w.r.t. alignmentStart)
+     *
+     * Flushes this cache, so after this call the cache will contain no reads, and we'll be in the same
+     * initial state as the constructor would put us in, with a non-null undownsampledCache and a null
+     * downsampler.
+     *
+     * @return a list of GATKSAMRecords in this cache
+     */
+    public List<GATKSAMRecord> popCurrentReads() {
+        final List<GATKSAMRecord> poppedReads;
+
+        if ( downsampler == null ) {
+            poppedReads = undownsampledCache;  // avoid making a copy here, since we're going to allocate a new cache
+        }
+        else {
+            // If we triggered the downsampler, we need to sort the reads before returning them,
+            // since the ReservoirDownsampler is not guaranteed to preserve relative ordering of items.
+            // After consuming the downsampled items in this call to popCurrentReads(), we switch back
+            // to using the undownsampledCache until we fill up again.
+            poppedReads = downsampler.consumeFinalizedItems();  // avoid making a copy here
+            Collections.sort(poppedReads, new AlignmentStartComparator());
+            downsampler = null;
+        }
+
+        initializeUndownsampledCache();
+        return poppedReads;
+    }
+}
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/traversals/TraversalEngine.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/traversals/TraversalEngine.java
new file mode 100644
index 0000000..25abafd
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/traversals/TraversalEngine.java
@@ -0,0 +1,124 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.engine.traversals;
+
+import org.apache.log4j.Logger;
+import org.broadinstitute.gatk.engine.GenomeAnalysisEngine;
+import org.broadinstitute.gatk.engine.ReadMetrics;
+import org.broadinstitute.gatk.engine.datasources.providers.ShardDataProvider;
+import org.broadinstitute.gatk.engine.walkers.Walker;
+import org.broadinstitute.gatk.utils.GenomeLoc;
+import org.broadinstitute.gatk.utils.exceptions.ReviewedGATKException;
+import org.broadinstitute.gatk.utils.progressmeter.ProgressMeter;
+
+public abstract class TraversalEngine<M,T,WalkerType extends Walker<M,T>,ProviderType extends ShardDataProvider> {
+    /** our log, which we want to capture anything from this class */
+    protected static final Logger logger = Logger.getLogger(TraversalEngine.class);
+
+    protected GenomeAnalysisEngine engine;
+    private ProgressMeter progressMeter;
+
+    // ----------------------------------------------------------------------------------------------------
+    //
+    // ABSTRACT METHODS
+    //
+    // ----------------------------------------------------------------------------------------------------
+
+    /**
+     * Gets the named traversal type associated with the given traversal, such as loci, reads, etc.
+     *
+     * @return A user-friendly name for the given traversal type.
+     */
+    public abstract String getTraversalUnits();
+
+    /**
+     * this method must be implemented by all traversal engines
+     *
+     * @param walker       the walker to run with
+     * @param dataProvider the data provider that generates data given the shard
+     * @param sum          the accumulator
+     *
+     * @return an object of the reduce type
+     */
+    public abstract T traverse(WalkerType walker,
+                               ProviderType dataProvider,
+                               T sum);
+
+    /**
+     * Initialize the traversal engine.  After this point traversals can be run over the data
+     *
+     * @param engine GenomeAnalysisEngine for this traversal
+     * @param progressMeter An optional (null == optional) meter to track our progress
+     */
+    public void initialize(final GenomeAnalysisEngine engine, final Walker walker, final ProgressMeter progressMeter) {
+        if ( engine == null )
+            throw new ReviewedGATKException("BUG: GenomeAnalysisEngine cannot be null!");
+
+        this.engine = engine;
+        this.progressMeter = progressMeter;
+    }
+
+    /**
+     * For testing only.  Does not initialize the progress meter
+     *
+     * @param engine
+     */
+    protected void initialize(final GenomeAnalysisEngine engine, final Walker walker) {
+        initialize(engine, walker, null);
+    }
+
+    /**
+     * Called by the MicroScheduler when all work is done and the GATK is shutting down.
+     *
+     * To be used by subclasses that need to free up resources (such as threads)
+     */
+    public void shutdown() {
+        // by default there's nothing to do
+    }
+
+    /**
+     * Update the cumulative traversal metrics according to the data in this shard
+     *
+     * @param singleTraverseMetrics read metrics object containing the information about a single shard's worth
+     *                              of data processing
+     */
+    public void updateCumulativeMetrics(final ReadMetrics singleTraverseMetrics) {
+        engine.getCumulativeMetrics().incrementMetrics(singleTraverseMetrics);
+    }
+
+    /**
+     * Forward request to notifyOfProgress
+     *
+     * Assumes that one cycle has been completed
+     *
+     * @param loc  the location
+     */
+    public void printProgress(final GenomeLoc loc) {
+        if ( progressMeter != null )
+            progressMeter.notifyOfProgress(loc, engine.getCumulativeMetrics().getNumIterations());
+    }
+}
+
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/traversals/TraverseActiveRegions.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/traversals/TraverseActiveRegions.java
new file mode 100644
index 0000000..7d93311
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/traversals/TraverseActiveRegions.java
@@ -0,0 +1,719 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.engine.traversals;
+
+import com.google.java.contract.Ensures;
+import com.google.java.contract.Requires;
+import org.apache.log4j.Logger;
+import org.broadinstitute.gatk.engine.GenomeAnalysisEngine;
+import org.broadinstitute.gatk.engine.contexts.AlignmentContext;
+import org.broadinstitute.gatk.engine.contexts.ReferenceContext;
+import org.broadinstitute.gatk.engine.datasources.providers.*;
+import org.broadinstitute.gatk.engine.refdata.RefMetaDataTracker;
+import org.broadinstitute.gatk.engine.walkers.ActiveRegionTraversalParameters;
+import org.broadinstitute.gatk.engine.walkers.ActiveRegionWalker;
+import org.broadinstitute.gatk.engine.walkers.Walker;
+import org.broadinstitute.gatk.utils.GenomeLoc;
+import org.broadinstitute.gatk.utils.SampleUtils;
+import org.broadinstitute.gatk.utils.Utils;
+import org.broadinstitute.gatk.utils.activeregion.ActiveRegion;
+import org.broadinstitute.gatk.utils.activeregion.ActivityProfile;
+import org.broadinstitute.gatk.utils.activeregion.ActivityProfileState;
+import org.broadinstitute.gatk.utils.activeregion.BandPassActivityProfile;
+import org.broadinstitute.gatk.utils.nanoScheduler.NSMapFunction;
+import org.broadinstitute.gatk.utils.nanoScheduler.NSProgressFunction;
+import org.broadinstitute.gatk.utils.nanoScheduler.NSReduceFunction;
+import org.broadinstitute.gatk.utils.nanoScheduler.NanoScheduler;
+import org.broadinstitute.gatk.utils.progressmeter.ProgressMeter;
+import org.broadinstitute.gatk.utils.sam.GATKSAMRecord;
+
+import java.io.PrintStream;
+import java.util.Collection;
+import java.util.Iterator;
+import java.util.LinkedList;
+import java.util.List;
+
+/**
+ * Implement active region traversal
+ *
+ * User: depristo
+ * Date: 1/9/13
+ * Time: 4:45 PM
+ *
+ * Live region:
+ *
+ *   The ART tracks a thing called the live region.  The live region is a position on a specific contig
+ *   of the alignment start of the last read we processed during this traversal.  Because the
+ *   read stream is sorted, future reads must occurs in the the live region.  Therefore the the dead region
+ *   (everything to the left of the live boundary) cannot have any more read data.  The live / dead
+ *   regions are used to decide when we can safely call map on active regions, as only active regions
+ *   contained completely within the dead region (including extensions) have a complete set of read data
+ *   in the collected read list.  All of the data related to the live region is captured by the local
+ *   variable spanOfLastReadSeen
+ *
+ */
+public final class TraverseActiveRegions<M, T> extends TraversalEngine<M,T,ActiveRegionWalker<M,T>,LocusShardDataProvider> {
+    private final static boolean DEBUG = false;
+    protected final static Logger logger = Logger.getLogger(TraversalEngine.class);
+    protected final static boolean LOG_READ_CARRYING = false;
+
+    // set by the traversal
+    private boolean walkerHasPresetRegions = false;
+    private int activeRegionExtension = -1;
+    private int maxRegionSize = -1;
+    private int minRegionSize = -1;
+
+    private final LinkedList<ActiveRegion> workQueue = new LinkedList<>();
+
+    private TAROrderedReadCache myReads = null;
+
+    private GenomeLoc lastRegionProcessed = null;
+    private GenomeLoc spanOfLastReadSeen = null;
+    private ActivityProfile activityProfile = null;
+    int maxReadsInMemory = 0;
+    ActiveRegionWalker<M, T> walker;
+
+    final NanoScheduler<MapData, M, T> nanoScheduler;
+
+    /**
+     * Data to use in the ActiveRegionWalker.map function produced by the NanoScheduler input iterator
+     */
+    private static class MapData {
+        public ActiveRegion activeRegion;
+        public RefMetaDataTracker tracker;
+
+        private MapData(ActiveRegion activeRegion, RefMetaDataTracker tracker) {
+            this.activeRegion = activeRegion;
+            this.tracker = tracker;
+        }
+    }
+
+    /**
+     * Create a single threaded active region traverser
+     */
+    public TraverseActiveRegions() {
+        this(1);
+    }
+
+    /**
+     * Create an active region traverser that uses nThreads for getting its work done
+     * @param nThreads number of threads
+     */
+    public TraverseActiveRegions(final int nThreads) {
+        nanoScheduler = new NanoScheduler<>(nThreads);
+        nanoScheduler.setProgressFunction(new NSProgressFunction<MapData>() {
+            @Override
+            public void progress(MapData lastActiveRegion) {
+                if ( lastActiveRegion != null )
+                    // note, need to use getStopLocation so we don't give an interval to ProgressMeterDaemon
+                    printProgress(lastActiveRegion.activeRegion.getLocation().getStopLocation());
+            }
+        });
+    }
+
+    /**
+     * Have the debugging output streams been initialized already?
+     *
+     * We have to do lazy initialization because when the initialize() function is called
+     * the streams aren't yet initialized in the GATK walker.
+     */
+    private boolean streamsInitialized = false;
+
+    @Override
+    public void initialize(GenomeAnalysisEngine engine, Walker walker, ProgressMeter progressMeter) {
+        super.initialize(engine, walker, progressMeter);
+
+        this.walker = (ActiveRegionWalker<M,T>)walker;
+        if ( this.walker.wantsExtendedReads() && ! this.walker.wantsNonPrimaryReads() ) {
+            throw new IllegalArgumentException("Active region walker " + this.walker + " requested extended events but not " +
+                    "non-primary reads, an inconsistent state.  Please modify the walker");
+        }
+
+        ActiveRegionTraversalParameters annotation = walker.getClass().getAnnotation(ActiveRegionTraversalParameters.class);
+        this.activeRegionExtension = this.walker.activeRegionExtension == null ? annotation.extension() : this.walker.activeRegionExtension;
+        this.maxRegionSize = this.walker.activeRegionMaxSize == null ? annotation.maxRegion() : this.walker.activeRegionMaxSize;
+        this.minRegionSize = annotation.minRegion();
+        final double bandPassSigma = this.walker.bandPassSigma == null ? annotation.bandPassSigma() : this.walker.bandPassSigma;
+        walkerHasPresetRegions = this.walker.hasPresetActiveRegions();
+
+        activityProfile = new BandPassActivityProfile(engine.getGenomeLocParser(), engine.getIntervals(), this.walker.maxProbPropagationDistance, this.walker.activeProbThreshold,
+                BandPassActivityProfile.MAX_FILTER_SIZE, bandPassSigma);
+
+        final int maxReadsAcrossSamples = annotation.maxReadsToHoldInMemoryPerSample() * SampleUtils.getSAMFileSamples(engine).size();
+        final int maxReadsToHoldInMemory = Math.min(maxReadsAcrossSamples, annotation.maxReadsToHoldTotal());
+        myReads = new TAROrderedReadCache(maxReadsToHoldInMemory);
+    }
+
+    // -------------------------------------------------------------------------------------
+    //
+    // Utility functions
+    //
+    // -------------------------------------------------------------------------------------
+
+    /**
+     * Load in the preset regions for contig into workQueue
+     *
+     * Should be called before starting to process work on contig
+     *
+     * Can only be called when walkerHasPresetRegions is true or an IllegalStateException will be thrown
+     *
+     * @param contig the contig we are about to process
+     */
+    protected void loadPresetRegionsForContigToWorkQueue(final String contig) {
+        if ( ! walkerHasPresetRegions ) throw new IllegalStateException("only appropriate to call when walker has preset regions");
+
+        final GenomeLoc contigSpan = engine.getGenomeLocParser().createOverEntireContig(contig);
+        for ( final GenomeLoc loc : this.walker.getPresetActiveRegions().getOverlapping(contigSpan) ) {
+            workQueue.add(new ActiveRegion(loc, null, true, engine.getGenomeLocParser(), getActiveRegionExtension()));
+        }
+    }
+
+    protected int getActiveRegionExtension() {
+        return activeRegionExtension;
+    }
+
+    protected int getMaxRegionSize() {
+        return maxRegionSize;
+    }
+
+    protected int getMinRegionSize() {
+        return minRegionSize;
+    }
+
+    @Override
+    public String getTraversalUnits() {
+        return "active regions";
+    }
+
+    @Override
+    public String toString() {
+        return "TraverseActiveRegions";
+    }
+
+    /**
+     * Is the loc outside of the intervals being requested for processing by the GATK?
+     * @param loc
+     * @return
+     */
+    protected boolean outsideEngineIntervals(final GenomeLoc loc) {
+        return engine.getIntervals() != null && ! engine.getIntervals().overlaps(loc);
+    }
+
+    // -------------------------------------------------------------------------------------
+    //
+    // Actual traverse function
+    //
+    // -------------------------------------------------------------------------------------
+
+    /**
+     * Did read appear in the last shard?
+     *
+     * When we transition across shard boundaries we see duplicate reads because
+     * each shard contains the reads that *overlap* the shard.  So if we just finished
+     * shard 1-1000 and are now in 1001-2000 we'll see duplicate reads from 1001
+     * that overlapped 1-1000.  This function tests read to determine if we would have
+     * seen it before by asking if read.getAlignmentStart() is less than the
+     * stop position of the last seen read at the start of the traversal.  The reason
+     * we need to use the location of the last read at the start of the traversal
+     * is that we update the lastRead during the traversal, and we only want to filter
+     * out reads whose start is before the last read of the previous shard, not the
+     * current shard.
+     *
+     * @param locOfLastReadAtTraversalStart the location of the last read seen at the start of the traversal
+     * @param read the read we want to test if it's already been seen in the last shard
+     * @return true if read would have appeared in the last shard, false otherwise
+     */
+    @Requires({"read != null"})
+    private boolean appearedInLastShard(final GenomeLoc locOfLastReadAtTraversalStart, final GATKSAMRecord read) {
+        if ( locOfLastReadAtTraversalStart == null )
+            // we're in the first shard, so obviously the answer is no
+            return false;
+        else {
+            // otherwise check to see if the alignment occurred in the previous shard
+            return read.getAlignmentStart() <= locOfLastReadAtTraversalStart.getStart()
+                    // we're on the same contig
+                    && read.getReferenceIndex() == locOfLastReadAtTraversalStart.getContigIndex();
+        }
+
+    }
+
+    @Override
+    public T traverse( final ActiveRegionWalker<M,T> walker,
+                       final LocusShardDataProvider dataProvider,
+                       T sum) {
+        if ( LOG_READ_CARRYING || logger.isDebugEnabled() )
+            logger.info(String.format("TraverseActiveRegions.traverse: Shard is %s", dataProvider));
+
+        nanoScheduler.setDebug(false);
+        final Iterator<MapData> activeRegionIterator = new ActiveRegionIterator(dataProvider);
+        final TraverseActiveRegionMap myMap = new TraverseActiveRegionMap();
+        final TraverseActiveRegionReduce myReduce = new TraverseActiveRegionReduce();
+        final T result = nanoScheduler.execute(activeRegionIterator, myMap, sum, myReduce);
+
+        return result;
+    }
+
+    private class ActiveRegionIterator implements Iterator<MapData> {
+        private final LocusShardDataProvider dataProvider;
+        private LinkedList<MapData> readyActiveRegions = new LinkedList<>();
+        private boolean done = false;
+        private final LocusView locusView;
+        private final LocusReferenceView referenceView;
+        private final GenomeLoc locOfLastReadAtTraversalStart;
+        private final IntervalReferenceOrderedView referenceOrderedDataView;
+        private final GenomeLoc currentWindow;
+        private final boolean processRemainingActiveRegions;
+
+        public ActiveRegionIterator( final LocusShardDataProvider dataProvider ) {
+            this.dataProvider = dataProvider;
+            locusView = new AllLocusView(dataProvider);
+            referenceView = new LocusReferenceView( walker, dataProvider );
+
+            // The data shard may carry a number of locations to process (due to being indexed together).
+            // This value is just the interval we are processing within the entire provider
+            currentWindow = dataProvider.getLocus();
+            final int currentWindowPos = dataProvider.getShard().getGenomeLocs().indexOf(currentWindow);
+            if ( currentWindowPos == -1 ) throw new IllegalStateException("Data provider " + dataProvider + " didn't have our current window in it " + currentWindow);
+            processRemainingActiveRegions = currentWindowPos == dataProvider.getShard().getGenomeLocs().size() - 1;
+
+            // the rodSpan covers all of the bases in the activity profile, including all of the bases
+            // through the current window interval.  This is because we may issue a query to get data for an
+            // active region spanning before the current interval as far back as the start of the current profile,
+            // if we have pending work to do that finalizes in this interval.
+            final GenomeLoc rodSpan = activityProfile.getSpan() == null ? currentWindow : activityProfile.getSpan().endpointSpan(currentWindow);
+            if ( ! dataProvider.getShard().getLocation().containsP(rodSpan) ) throw new IllegalStateException("Rod span " + rodSpan + " isn't contained within the data shard " + dataProvider.getShard().getLocation() + ", meaning we wouldn't get all of the data we need");
+            referenceOrderedDataView = new IntervalReferenceOrderedView( dataProvider, rodSpan );
+
+            // We keep processing while the next reference location is within the interval
+            locOfLastReadAtTraversalStart = spanOfLastSeenRead();
+
+            // load in the workQueue the present regions that span the current contig, if it's different from the last one
+            if ( walkerHasPresetRegions && ( lastRegionProcessed == null || ! currentWindow.onSameContig(lastRegionProcessed)) ) {
+                loadPresetRegionsForContigToWorkQueue(currentWindow.getContig());
+            }
+
+            // remember the last region we processed for sanity checking later
+            lastRegionProcessed = currentWindow;
+        }
+
+        @Override public void remove() { throw new UnsupportedOperationException("Cannot remove from ActiveRegionIterator"); }
+
+        @Override
+        public MapData next() {
+            return readyActiveRegions.pop();
+        }
+        @Override
+        public boolean hasNext() {
+            if ( engine.exceedsRuntimeLimit() ) // too much time has been dedicated to doing work, just stop
+                 return false;
+            if ( ! readyActiveRegions.isEmpty() )
+                return true;
+            if ( done )
+                return false;
+            else {
+
+                while( locusView.hasNext() ) {
+                    final AlignmentContext locus = locusView.next();
+                    final GenomeLoc location = locus.getLocation();
+
+                    rememberLastLocusLocation(location);
+
+                    // get all of the new reads that appear in the current pileup, and them to our list of reads
+                    // provided we haven't seen them before
+                    final Collection<GATKSAMRecord> reads = locusView.getLIBS().transferReadsFromAllPreviousPileups();
+                    for( final GATKSAMRecord read : reads ) {
+                        // note that ActiveRegionShards span entire contigs, so this check is in some
+                        // sense no longer necessary, as any read that appeared in the last shard would now
+                        // by definition be on a different contig.  However, the logic here doesn't hurt anything
+                        // and makes us robust should we decided to provide shards that don't fully span
+                        // contigs at some point in the future
+                        if ( ! appearedInLastShard(locOfLastReadAtTraversalStart, read) ) {
+                            rememberLastReadLocation(read);
+                            myReads.add(read);
+                        }
+                    }
+
+                    // skip this location -- it's not part of our engine intervals
+                    if ( outsideEngineIntervals(location) )
+                        continue;
+
+                    // we've move across some interval boundary, restart profile
+                    final boolean flushProfile = ! activityProfile.isEmpty()
+                            && ( activityProfile.getContigIndex() != location.getContigIndex()
+                            || location.getStart() != activityProfile.getStop() + 1);
+                    final List<MapData> newActiveRegions = prepActiveRegionsForProcessing(walker, flushProfile, false, referenceOrderedDataView);
+
+                    dataProvider.getShard().getReadMetrics().incrementNumIterations();
+
+                    // create reference context. Note that if we have a pileup of "extended events", the context will
+                    // hold the (longest) stretch of deleted reference bases (if deletions are present in the pileup).
+                    final ReferenceContext refContext = referenceView.getReferenceContext(location);
+
+                    // Iterate forward to get all reference ordered data covering this location
+                    final RefMetaDataTracker tracker = referenceOrderedDataView.getReferenceOrderedDataAtLocus(locus.getLocation());
+
+                    // Call the walkers isActive function for this locus and add them to the list to be integrated later
+                    addIsActiveResult(walker, tracker, refContext, locus);
+
+                    maxReadsInMemory = Math.max(myReads.size(), maxReadsInMemory);
+                    printProgress(location);
+
+                    if ( ! newActiveRegions.isEmpty() ) {
+                        readyActiveRegions.addAll(newActiveRegions);
+                        if ( DEBUG )
+                            for ( final MapData region : newActiveRegions )
+                                logger.info("Adding region to queue for processing " + region.activeRegion);
+                        return true;
+                    }
+                }
+
+                if ( processRemainingActiveRegions ) {
+                    // we've run out of stuff to process, and since shards now span entire contig boundaries
+                    // we should finalized our regions.  This allows us to continue to use our referenceOrderedDataView
+                    // which would otherwise be shutdown.  Only followed when the microschedule says that we're
+                    // inside of the last window in the current shard
+                    readyActiveRegions.addAll(prepActiveRegionsForProcessing(walker, true, true, referenceOrderedDataView));
+                }
+
+                return ! readyActiveRegions.isEmpty();
+            }
+        }
+    }
+
+    // -------------------------------------------------------------------------------------
+    //
+    // Functions to manage and interact with the live / dead zone
+    //
+    // -------------------------------------------------------------------------------------
+
+    /**
+     * Update the live region to reflect that the last read we've seen in the traversal is read
+     *
+     * Requires that sequential calls always be provided reads in coordinate sorted order
+     *
+     * @param read the last read we've seen during the traversal
+     */
+    @Requires({"read != null"})
+    protected void rememberLastReadLocation(final GATKSAMRecord read) {
+        final GenomeLoc currentLocation = engine.getGenomeLocParser().createGenomeLoc(read);
+        if ( spanOfLastReadSeen == null )
+            spanOfLastReadSeen = currentLocation;
+        else {
+            if ( currentLocation.isBefore(spanOfLastReadSeen) )
+                throw new IllegalStateException("Updating last read seen in the traversal with read " + read + " with span " + currentLocation + " but this occurs before the previously seen read " + spanOfLastReadSeen);
+            spanOfLastReadSeen = currentLocation;
+        }
+    }
+
+    /**
+     * Update the live region to reflect that we've reached locus
+     *
+     * This function is complementary to #rememberLastReadLocation, but if we don't have any reads for a long
+     * time (e.g., there's no coverage) we will keep active regions around far longer than necessary.
+     *
+     * Only updates the span if it's beyond the last seen
+     *
+     * @param currentLocation the current location we've processed on the genome
+     */
+    protected void rememberLastLocusLocation(final GenomeLoc currentLocation) {
+        if ( spanOfLastReadSeen == null )
+            spanOfLastReadSeen = currentLocation;
+        else {
+            if ( currentLocation.isPast(spanOfLastReadSeen) )
+                spanOfLastReadSeen = currentLocation;
+        }
+    }
+
+
+    /**
+     * Get a GenomeLoc indicating the start (heading to the right) of the live ART region.
+     * @return the left-most position of the live region on the genome
+     */
+    protected GenomeLoc spanOfLastSeenRead() {
+        return spanOfLastReadSeen;
+    }
+
+    /**
+     * Is the active region completely within the traversal's dead zone?
+     *
+     * @param region the region we want to test
+     * @return true if the extended location of region is completely within the current dead zone, false otherwise
+     */
+    protected boolean regionCompletelyWithinDeadZone(final ActiveRegion region) {
+        if ( spanOfLastSeenRead() == null )
+            return false;
+
+        final int contigCmp = region.getExtendedLoc().compareContigs(spanOfLastSeenRead());
+        if ( contigCmp > 0 )
+            throw new IllegalStateException("Active region " + region + " on a contig after last seen read " + spanOfLastSeenRead());
+        else {
+            return contigCmp < 0 || region.getExtendedLoc().getStop() < spanOfLastSeenRead().getStart();
+        }
+    }
+
+    /**
+     * Is the read dead?  That is, can it no longer be in any future active region, and therefore can be discarded?
+     *
+     * read: start |--------> stop ------ stop + extension
+     * region:                      start |-----------------| end
+     *
+     * Since the regions are coming in order, read could potentially be contained in a future interval if
+     * stop + activeRegionExtension >= end.  If, on the other hand, stop + extension is < the end
+     * of this region, then we can discard it, since any future region could only include reads
+     * up to end + 1 - extension.
+     *
+     * Note that this function doesn't care about the dead zone.  We're assuming that by
+     * actually calling this function with an active region that region is already in the dead zone,
+     * so checking that the read is in the dead zone doesn't make sense.
+     *
+     * @param read the read we're testing
+     * @param activeRegion the current active region
+     * @return true if the read is dead, false other
+     */
+    @Requires({"read != null", "activeRegion != null"})
+    private boolean readCannotOccurInAnyMoreActiveRegions(final GATKSAMRecord read, final ActiveRegion activeRegion) {
+        return read.getReferenceIndex() < activeRegion.getLocation().getContigIndex() ||
+                ( read.getReferenceIndex() == activeRegion.getLocation().getContigIndex()
+                        && read.getAlignmentEnd() + getActiveRegionExtension() < activeRegion.getLocation().getStop() );
+    }
+
+    // -------------------------------------------------------------------------------------
+    //
+    // Functions to write out activity profiles and active regions
+    //
+    // -------------------------------------------------------------------------------------
+
+    /**
+     * Initialize the debugging output streams (activity profile and active regions), if not done so already
+     */
+    @Ensures("streamsInitialized == true")
+    private void initializeOutputStreamsIfNecessary() {
+        if ( ! streamsInitialized ) {
+            streamsInitialized = true;
+            if ( walker.activityProfileOutStream != null ) {
+                printIGVFormatHeader(walker.activityProfileOutStream, "line", "ActivityProfile");
+            }
+
+            if ( walker.activeRegionOutStream != null ) {
+                printIGVFormatHeader(walker.activeRegionOutStream, "line", "ActiveRegions");
+            }
+        }
+    }
+
+    /**
+     * Helper function to write out a IGV formatted line to out, at loc, with values
+     *
+     * http://www.broadinstitute.org/software/igv/IGV
+     *
+     * @param out a non-null PrintStream where we'll write our line
+     * @param graphType the type of graph to show in IGV for this track
+     * @param columns the column names for this IGV track
+     */
+    @Requires({
+            "out != null",
+            "graphType != null",
+            "columns.length > 0"
+    })
+    private void printIGVFormatHeader(final PrintStream out, final String graphType, final String ... columns ) {
+        out.printf("#track graphType=%s%n", graphType);
+        out.printf("Chromosome\tStart\tEnd\tFeature\t%s%n", Utils.join("\t", columns));
+
+    }
+
+    /**
+     * Helper function to write out a IGV formatted line to out, at loc, with values
+     *
+     * http://www.broadinstitute.org/software/igv/IGV
+     *
+     * @param out a non-null PrintStream where we'll write our line
+     * @param loc the location of values
+     * @param featureName string name of this feature (see IGV format)
+     * @param values the floating point values to associate with loc and feature name in out
+     */
+    @Requires({
+            "out != null",
+            "loc != null",
+            "values.length > 0"
+    })
+    private void printIGVFormatRow(final PrintStream out, final GenomeLoc loc, final String featureName, final double ... values) {
+        // note that start and stop are 0 based, but the stop is exclusive so we don't subtract 1
+        out.printf("%s\t%d\t%d\t%s", loc.getContig(), loc.getStart() - 1, loc.getStop(), featureName);
+        for ( final double value : values )
+            out.print(String.format("\t%.5f", value));
+        out.println();
+    }
+
+    /**
+     * Write out activity profile information, if requested by the walker
+     *
+     * @param states the states in the current activity profile
+     */
+    @Requires("states != null")
+    private void writeActivityProfile(final List<ActivityProfileState> states) {
+        if ( walker.activityProfileOutStream != null ) {
+            initializeOutputStreamsIfNecessary();
+            for ( final ActivityProfileState state : states ) {
+                printIGVFormatRow(walker.activityProfileOutStream, state.getLoc(), "state", Math.min(state.isActiveProb, 1.0));
+            }
+        }
+    }
+
+    /**
+     * Write out each active region to the walker activeRegionOutStream
+     *
+     * @param region the region we're currently operating on
+     */
+    @Requires("region != null")
+    private void writeActiveRegion(final ActiveRegion region) {
+        if( walker.activeRegionOutStream != null ) {
+            initializeOutputStreamsIfNecessary();
+            printIGVFormatRow(walker.activeRegionOutStream, region.getLocation().getStartLocation(),
+                    "end-marker", 0.0);
+            printIGVFormatRow(walker.activeRegionOutStream, region.getLocation(),
+                    "size=" + region.getLocation().size(), region.isActive() ? 1.0 : -1.0);
+        }
+    }
+
+
+    // -------------------------------------------------------------------------------------
+    //
+    // Functions to process active regions that are ready for map / reduce calls
+    //
+    // -------------------------------------------------------------------------------------
+
+    /**
+     * Invoke the walker isActive function, and incorporate its result into the activity profile
+     *
+     * @param walker the walker we're running
+     * @param tracker the ref meta data tracker to pass on to the isActive function of walker
+     * @param refContext the refContext to pass on to the isActive function of walker
+     * @param locus the AlignmentContext to pass on to the isActive function of walker
+     */
+    private void addIsActiveResult(final ActiveRegionWalker<M, T> walker,
+                                   final RefMetaDataTracker tracker, final ReferenceContext refContext,
+                                   final AlignmentContext locus) {
+        // must be called, even if we won't use the result, to satisfy walker contract
+        final ActivityProfileState state = walker.isActive( tracker, refContext, locus );
+        if ( walker.forceActive) state.isActiveProb = 1.0;
+        if ( ! walkerHasPresetRegions ) {
+            activityProfile.add(state);
+        }
+    }
+
+    /**
+     * Take the individual isActive calls and integrate them into contiguous active regions and
+     * add these blocks of work to the work queue
+     * band-pass filter the list of isActive probabilities and turn into active regions
+     */
+    private List<MapData> prepActiveRegionsForProcessing(final ActiveRegionWalker<M, T> walker,
+                                                              final boolean flushActivityProfile,
+                                                              final boolean forceAllRegionsToBeActive,
+                                                              final IntervalReferenceOrderedView referenceOrderedDataView) {
+        if ( ! walkerHasPresetRegions ) {
+            // We don't have preset regions, so we get our regions from the activity profile
+            final Collection<ActiveRegion> activeRegions = activityProfile.popReadyActiveRegions(getActiveRegionExtension(), getMinRegionSize(), getMaxRegionSize(), flushActivityProfile);
+            workQueue.addAll(activeRegions);
+            if ( ! activeRegions.isEmpty() && logger.isDebugEnabled() ) logger.debug("Integrated " + activityProfile.size() + " isActive calls into " + activeRegions.size() + " regions." );
+        }
+
+        // Since we've traversed sufficiently past this point (or this contig!) in the workQueue we can unload those regions and process them
+        final LinkedList<MapData> readyRegions = new LinkedList<>();
+        while( workQueue.peek() != null ) {
+            final ActiveRegion activeRegion = workQueue.peek();
+            if ( forceAllRegionsToBeActive || regionCompletelyWithinDeadZone(activeRegion) ) {
+                writeActivityProfile(activeRegion.getSupportingStates());
+                writeActiveRegion(activeRegion);
+                readyRegions.add(prepActiveRegionForProcessing(workQueue.remove(), walker, referenceOrderedDataView));
+            } else {
+                break;
+            }
+        }
+
+        return readyRegions;
+
+    }
+
+    private MapData prepActiveRegionForProcessing(final ActiveRegion activeRegion,
+                                                  final ActiveRegionWalker<M, T> walker,
+                                                  final IntervalReferenceOrderedView referenceOrderedDataView) {
+        final List<GATKSAMRecord> stillLive = new LinkedList<>();
+        for ( final GATKSAMRecord read : myReads.popCurrentReads() ) {
+            boolean killed = false;
+            final GenomeLoc readLoc = this.engine.getGenomeLocParser().createGenomeLoc( read );
+
+            if( activeRegion.getLocation().overlapsP( readLoc ) ) {
+                activeRegion.add(read);
+
+                if ( ! walker.wantsNonPrimaryReads() ) {
+                    killed = true;
+                }
+            } else if( walker.wantsExtendedReads() && activeRegion.getExtendedLoc().overlapsP( readLoc )) {
+                activeRegion.add( read );
+            }
+
+            // if the read hasn't already been killed, check if it cannot occur in any more active regions, and maybe kill it
+            if ( ! killed && readCannotOccurInAnyMoreActiveRegions(read, activeRegion) ) {
+                killed = true;
+            }
+
+            // keep track of all of the still live active regions
+            if ( ! killed ) stillLive.add(read);
+        }
+        myReads.addAll(stillLive);
+
+        if ( logger.isDebugEnabled() ) {
+            logger.debug(">> Map call with " + activeRegion.getReads().size() + " " + (activeRegion.isActive() ? "active" : "inactive") + " reads @ " + activeRegion.getLocation() + " with full extent: " + activeRegion.getReadSpanLoc());
+        }
+
+        if ( LOG_READ_CARRYING )
+            logger.info(String.format("Processing region %20s span=%3d active?=%5b with %4d reads.  Overall max reads carried is %s",
+                    activeRegion.getLocation(), activeRegion.getLocation().size(), activeRegion.isActive(), activeRegion.size(), maxReadsInMemory));
+
+        // prepare the RefMetaDataTracker information
+        final GenomeLoc loc = activeRegion.getLocation();
+        // get all of the RODs that cover the active region (without extension)
+        final RefMetaDataTracker tracker = referenceOrderedDataView.getReferenceOrderedDataForInterval(loc);
+        // trim away all of the features that occurred before this location, as we will not need them in the future
+        referenceOrderedDataView.trimCurrentFeaturesToLoc(loc);
+
+        return new MapData(activeRegion, tracker);
+    }
+
+    private class TraverseActiveRegionMap implements NSMapFunction<MapData, M> {
+        @Override
+        public M apply(final MapData mapData) {
+            if ( DEBUG ) logger.info("Executing walker.map for " + mapData.activeRegion + " in thread " + Thread.currentThread().getName());
+            return walker.map(mapData.activeRegion, mapData.tracker);
+        }
+    }
+
+    private class TraverseActiveRegionReduce implements NSReduceFunction<M, T> {
+        @Override
+        public T apply(M one, T sum) {
+            return walker.reduce(one, sum);
+        }
+    }
+}
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/traversals/TraverseDuplicates.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/traversals/TraverseDuplicates.java
new file mode 100644
index 0000000..6cffe94
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/traversals/TraverseDuplicates.java
@@ -0,0 +1,205 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.engine.traversals;
+
+import htsjdk.samtools.SAMRecord;
+import org.apache.log4j.Logger;
+import org.broadinstitute.gatk.engine.contexts.AlignmentContext;
+import org.broadinstitute.gatk.engine.datasources.providers.ReadShardDataProvider;
+import org.broadinstitute.gatk.engine.datasources.providers.ReadView;
+import org.broadinstitute.gatk.engine.iterators.PushbackIterator;
+import org.broadinstitute.gatk.engine.walkers.DuplicateWalker;
+import org.broadinstitute.gatk.utils.GenomeLoc;
+import org.broadinstitute.gatk.utils.pileup.ReadBackedPileupImpl;
+import org.broadinstitute.gatk.utils.sam.GATKSAMRecord;
+
+import java.util.*;
+
+/**
+ * @author Mark DePristo
+ * @version 0.1
+ *          <p/>
+ *          Class TraverseDuplicates
+ *          <p/>
+ *          This class handles traversing lists of duplicate reads in the new shardable style
+ */
+public class TraverseDuplicates<M,T> extends TraversalEngine<M,T,DuplicateWalker<M,T>,ReadShardDataProvider> {
+    /** our log, which we want to capture anything from this class */
+    protected static Logger logger = Logger.getLogger(TraverseDuplicates.class);
+
+    /** Turn this to true to enable logger.debug output */
+    private final boolean DEBUG = false;
+
+    @Override
+    public String getTraversalUnits() {
+        return "dups";
+    }
+
+    private List<GATKSAMRecord> readsAtLoc(final GATKSAMRecord read, PushbackIterator<SAMRecord> iter) {
+        GenomeLoc site = engine.getGenomeLocParser().createGenomeLoc(read);
+        ArrayList<GATKSAMRecord> l = new ArrayList<GATKSAMRecord>();
+
+        l.add(read);
+        for (SAMRecord read2 : iter) {
+            GenomeLoc site2 = engine.getGenomeLocParser().createGenomeLoc(read2);
+
+            // the next read starts too late
+            if (site2.getStart() != site.getStart()) {
+                iter.pushback(read2);
+                break;
+            } else {
+                l.add((GATKSAMRecord) read2);
+            }
+        }
+
+        return l;
+    }
+
+    /**
+     * Creates a set of lists of reads, where each list contains reads from the same underlying molecule according
+     * to their duplicate flag and their (and mate, if applicable) start/end positions.
+     *
+     * @param reads the list of reads to split into unique molecular samples
+     * @return
+     */
+    protected Set<List<GATKSAMRecord>> uniqueReadSets(List<GATKSAMRecord> reads) {
+        Set<List<GATKSAMRecord>> readSets = new LinkedHashSet<List<GATKSAMRecord>>();
+
+        // for each read, find duplicates, and either add the read to its duplicate list or start a new one
+        for ( GATKSAMRecord read : reads ) {
+            List<GATKSAMRecord> readSet = findDuplicateReads(read, readSets);
+
+            if ( readSet == null ) {
+                readSets.add(new ArrayList<GATKSAMRecord>(Arrays.asList(read)));    // copy so I can add to the list
+            } else {
+                readSet.add(read);
+            }
+        }
+
+        return readSets;
+    }
+
+    /**
+     * Find duplicate reads for read in the set of unique reads.  This is effective a duplicate marking algorithm,
+     * but it relies for safety's sake on the file itself being marked by a true duplicate marking algorithm.  Pair
+     * and single-end read aware.
+     *
+     * @param read
+     * @param readSets
+     * @return The list of duplicate reads that read is a member of, or null if it's the only one of its kind
+     */
+    protected List<GATKSAMRecord> findDuplicateReads(GATKSAMRecord read, Set<List<GATKSAMRecord>> readSets ) {
+        if ( read.getReadPairedFlag() ) {
+            // paired
+            final GenomeLoc readMateLoc = engine.getGenomeLocParser().createGenomeLoc(read.getMateReferenceName(), read.getMateAlignmentStart(), read.getMateAlignmentStart());
+
+            for (List<GATKSAMRecord> reads : readSets) {
+                GATKSAMRecord key = reads.get(0);
+
+                // read and key start at the same place, and either the this read and the key
+                // share a mate location or the read is flagged as a duplicate
+                if ( read.getAlignmentStart() == key.getAlignmentStart() && key.getReadPairedFlag() && ( key.getDuplicateReadFlag() || read.getDuplicateReadFlag() ) ) {
+                    // at least one has to be marked as a duplicate
+                    final GenomeLoc keyMateLoc = engine.getGenomeLocParser().createGenomeLoc(key.getMateReferenceName(), key.getMateAlignmentStart(), key.getMateAlignmentStart());
+                    if ( readMateLoc.compareTo(keyMateLoc) == 0 ) {
+                        // we are at the same position as the dup and have the same mat pos, it's a dup
+                        if (DEBUG) logger.debug(String.format("  => Adding read to dups list: %s %d %s vs. %s", read, reads.size(), readMateLoc, keyMateLoc));
+                        return reads;
+                    }
+                }
+            }
+        } else {
+            for (List<GATKSAMRecord> reads : readSets) {
+                GATKSAMRecord key = reads.get(0);
+                boolean v = (! key.getReadPairedFlag()) && read.getAlignmentStart() == key.getAlignmentStart() && ( key.getDuplicateReadFlag() || read.getDuplicateReadFlag() ) && read.getReadLength() == key.getReadLength();
+                //System.out.printf("%s %s %b %b %d %d %d %d => %b%n",
+                //        read.getReadPairedFlag(), key.getReadPairedFlag(), read.getDuplicateReadFlag(), key.getDuplicateReadFlag(),
+                //        read.getAlignmentStart(), key.getAlignmentStart(), read.getReadLength(), key.getReadLength(), v);
+                if ( v ) {
+                    //System.out.printf("Returning reads...%n");
+                    return reads;
+                }
+            }
+        }
+
+        return null;
+    }
+
+    // --------------------------------------------------------------------------------------------------------------
+    //
+    // new style interface to the system
+    //
+    // --------------------------------------------------------------------------------------------------------------
+
+    /**
+     * Traverse by reads, given the data and the walker
+     *
+     * @param walker the walker to execute over
+     * @param sum    of type T, the return from the walker
+     *
+     * @return the result type T, the product of all the reduce calls
+     */
+    public T traverse(DuplicateWalker<M, T> walker,
+                      ReadShardDataProvider dataProvider,
+                      T sum) {
+        PushbackIterator<SAMRecord> iter = new PushbackIterator<SAMRecord>(new ReadView(dataProvider).iterator());
+
+        /**
+         * while we still have more reads:
+         * ok, here's the idea.  We get all the reads that start at the same position in the genome
+         * We then split the list of reads into sublists of reads:
+         *   -> those with the same mate pair position, for paired reads
+         *   -> those flagged as unpaired and duplicated but having the same start and end
+         */
+        boolean done = walker.isDone();
+        for (SAMRecord read : iter) {
+            if ( done ) break;
+            // get the genome loc from the read
+            GenomeLoc site = engine.getGenomeLocParser().createGenomeLoc(read);
+
+            Set<List<GATKSAMRecord>> readSets = uniqueReadSets(readsAtLoc((GATKSAMRecord) read, iter));
+            if ( DEBUG ) logger.debug(String.format("*** TraverseDuplicates.traverse at %s with %d read sets", site, readSets.size()));
+
+            // Jump forward in the reference to this locus location
+            AlignmentContext locus = new AlignmentContext(site, new ReadBackedPileupImpl(site));
+
+            // update the number of duplicate sets we've seen
+            dataProvider.getShard().getReadMetrics().incrementNumIterations();
+
+            // actually call filter and map, accumulating sum
+            final boolean keepMeP = walker.filter(site, locus, readSets);
+            if (keepMeP) {
+                M x = walker.map(site, locus, readSets);
+                sum = walker.reduce(x, sum);
+            }
+
+            printProgress(site.getStopLocation());
+            done = walker.isDone();
+        }
+
+        return sum;
+    }
+}
\ No newline at end of file
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/traversals/TraverseLociNano.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/traversals/TraverseLociNano.java
new file mode 100644
index 0000000..02c1a7e
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/traversals/TraverseLociNano.java
@@ -0,0 +1,304 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.engine.traversals;
+
+import org.broadinstitute.gatk.engine.WalkerManager;
+import org.broadinstitute.gatk.engine.contexts.AlignmentContext;
+import org.broadinstitute.gatk.engine.contexts.ReferenceContext;
+import org.broadinstitute.gatk.engine.datasources.providers.*;
+import org.broadinstitute.gatk.engine.refdata.RefMetaDataTracker;
+import org.broadinstitute.gatk.engine.walkers.DataSource;
+import org.broadinstitute.gatk.engine.walkers.LocusWalker;
+import org.broadinstitute.gatk.engine.walkers.Walker;
+import org.broadinstitute.gatk.utils.GenomeLoc;
+import org.broadinstitute.gatk.utils.nanoScheduler.NSMapFunction;
+import org.broadinstitute.gatk.utils.nanoScheduler.NSProgressFunction;
+import org.broadinstitute.gatk.utils.nanoScheduler.NSReduceFunction;
+import org.broadinstitute.gatk.utils.nanoScheduler.NanoScheduler;
+import org.broadinstitute.gatk.utils.pileup.ReadBackedPileupImpl;
+
+import java.util.Iterator;
+
+/**
+ * A simple solution to iterating over all reference positions over a series of genomic locations.
+ */
+public class TraverseLociNano<M,T> extends TraversalEngine<M,T,LocusWalker<M,T>,LocusShardDataProvider> {
+    /** our log, which we want to capture anything from this class */
+    private static final boolean DEBUG = false;
+
+    final NanoScheduler<MapData, MapResult, T> nanoScheduler;
+
+    public TraverseLociNano(int nThreads) {
+        nanoScheduler = new NanoScheduler<MapData, MapResult, T>(nThreads);
+        nanoScheduler.setProgressFunction(new TraverseLociProgress());
+    }
+
+    @Override
+    public final String getTraversalUnits() {
+        return "sites";
+    }
+
+    protected static class TraverseResults<T> {
+        final int numIterations;
+        final T reduceResult;
+
+        public TraverseResults(int numIterations, T reduceResult) {
+            this.numIterations = numIterations;
+            this.reduceResult = reduceResult;
+        }
+    }
+
+    @Override
+    public T traverse( LocusWalker<M,T> walker,
+                       LocusShardDataProvider dataProvider,
+                       T sum) {
+        logger.debug(String.format("TraverseLoci.traverse: Shard is %s", dataProvider));
+
+        final LocusView locusView = getLocusView( walker, dataProvider );
+
+        if ( locusView.hasNext() ) { // trivial optimization to avoid unnecessary processing when there's nothing here at all
+            //ReferenceOrderedView referenceOrderedDataView = new ReferenceOrderedView( dataProvider );
+            ReferenceOrderedView referenceOrderedDataView = null;
+            if ( WalkerManager.getWalkerDataSource(walker) != DataSource.REFERENCE_ORDERED_DATA )
+                referenceOrderedDataView = new ManagingReferenceOrderedView( dataProvider );
+            else
+                referenceOrderedDataView = (RodLocusView)locusView;
+
+            final LocusReferenceView referenceView = new LocusReferenceView( walker, dataProvider );
+
+            final TraverseResults<T> result = traverse( walker, locusView, referenceView, referenceOrderedDataView, sum );
+            sum = result.reduceResult;
+            dataProvider.getShard().getReadMetrics().incrementNumIterations(result.numIterations);
+        }
+
+        // We have a final map call to execute here to clean up the skipped based from the
+        // last position in the ROD to that in the interval
+        if ( WalkerManager.getWalkerDataSource(walker) == DataSource.REFERENCE_ORDERED_DATA && ! walker.isDone() ) {
+            // only do this if the walker isn't done!
+            final RodLocusView rodLocusView = (RodLocusView)locusView;
+            final long nSkipped = rodLocusView.getLastSkippedBases();
+            if ( nSkipped > 0 ) {
+                final GenomeLoc site = rodLocusView.getLocOneBeyondShard();
+                final AlignmentContext ac = new AlignmentContext(site, new ReadBackedPileupImpl(site), nSkipped);
+                final M x = walker.map(null, null, ac);
+                sum = walker.reduce(x, sum);
+            }
+        }
+
+        return sum;
+    }
+
+    /**
+     * Gets the best view of loci for this walker given the available data.  The view will function as a 'trigger track'
+     * of sorts, providing a consistent interface so that TraverseLoci doesn't need to be reimplemented for any new datatype
+     * that comes along.
+     * @param walker walker to interrogate.
+     * @param dataProvider Data which which to drive the locus view.
+     * @return A view of the locus data, where one iteration of the locus view maps to one iteration of the traversal.
+     */
+    private LocusView getLocusView( Walker<M,T> walker, LocusShardDataProvider dataProvider ) {
+        final DataSource dataSource = WalkerManager.getWalkerDataSource(walker);
+        if( dataSource == DataSource.READS )
+            return new CoveredLocusView(dataProvider);
+        else if( dataSource == DataSource.REFERENCE ) //|| ! GenomeAnalysisEngine.instance.getArguments().enableRodWalkers )
+            return new AllLocusView(dataProvider);
+        else if( dataSource == DataSource.REFERENCE_ORDERED_DATA )
+            return new RodLocusView(dataProvider);
+        else
+            throw new UnsupportedOperationException("Unsupported traversal type: " + dataSource);
+    }
+
+    protected TraverseResults<T> traverse(final LocusWalker<M, T> walker,
+                                          final LocusView locusView,
+                                          final LocusReferenceView referenceView,
+                                          final ReferenceOrderedView referenceOrderedDataView,
+                                          final T sum) {
+        nanoScheduler.setDebug(DEBUG);
+        final TraverseLociMap myMap = new TraverseLociMap(walker);
+        final TraverseLociReduce myReduce = new TraverseLociReduce(walker);
+
+        final MapDataIterator inputIterator = new MapDataIterator(locusView, referenceView, referenceOrderedDataView);
+        final T result = nanoScheduler.execute(inputIterator, myMap, sum, myReduce);
+
+        return new TraverseResults<T>(inputIterator.numIterations, result);
+    }
+
+    /**
+     * Create iterator that provides inputs for all map calls into MapData, to be provided
+     * to NanoScheduler for Map/Reduce
+     */
+    private class MapDataIterator implements Iterator<MapData> {
+        final LocusView locusView;
+        final LocusReferenceView referenceView;
+        final ReferenceOrderedView referenceOrderedDataView;
+        int numIterations = 0;
+
+        private MapDataIterator(LocusView locusView, LocusReferenceView referenceView, ReferenceOrderedView referenceOrderedDataView) {
+            this.locusView = locusView;
+            this.referenceView = referenceView;
+            this.referenceOrderedDataView = referenceOrderedDataView;
+        }
+
+        @Override
+        public boolean hasNext() {
+            return locusView.hasNext() && ! engine.exceedsRuntimeLimit();
+        }
+
+        @Override
+        public MapData next() {
+            final AlignmentContext locus = locusView.next();
+            final GenomeLoc location = locus.getLocation();
+
+            //logger.info("Pulling data from MapDataIterator at " + location);
+
+            // create reference context. Note that if we have a pileup of "extended events", the context will
+            // hold the (longest) stretch of deleted reference bases (if deletions are present in the pileup).
+            final ReferenceContext refContext = referenceView.getReferenceContext(location);
+
+            // Iterate forward to get all reference ordered data covering this location
+            final RefMetaDataTracker tracker = referenceOrderedDataView.getReferenceOrderedDataAtLocus(location);
+
+            numIterations++;
+            return new MapData(locus, refContext,  tracker);
+        }
+
+        @Override
+        public void remove() {
+            throw new UnsupportedOperationException("Cannot remove elements from MapDataIterator");
+        }
+    }
+
+    @Override
+    public void shutdown() {
+        nanoScheduler.shutdown();
+    }
+
+    /**
+     * The input data needed for each map call.  The read, the reference, and the RODs
+     */
+    private class MapData {
+        final AlignmentContext alignmentContext;
+        final ReferenceContext refContext;
+        final RefMetaDataTracker tracker;
+
+        private MapData(final AlignmentContext alignmentContext, ReferenceContext refContext, RefMetaDataTracker tracker) {
+            this.alignmentContext = alignmentContext;
+            this.refContext = refContext;
+            this.tracker = tracker;
+        }
+
+        @Override
+        public String toString() {
+            return "MapData " + alignmentContext.getLocation();
+        }
+    }
+
+    /**
+     * Contains the results of a map call, indicating whether the call was good, filtered, or done
+     */
+    private class MapResult {
+        final M value;
+        final boolean reduceMe;
+
+        /**
+         * Create a MapResult with value that should be reduced
+         *
+         * @param value the value to reduce
+         */
+        private MapResult(final M value) {
+            this.value = value;
+            this.reduceMe = true;
+        }
+
+        /**
+         * Create a MapResult that shouldn't be reduced
+         */
+        private MapResult() {
+            this.value = null;
+            this.reduceMe = false;
+        }
+    }
+
+    /**
+     * A static object that tells reduce that the result of map should be skipped (filtered or done)
+     */
+    private final MapResult SKIP_REDUCE = new MapResult();
+
+    /**
+     * MapFunction for TraverseReads meeting NanoScheduler interface requirements
+     *
+     * Applies walker.map to MapData, returning a MapResult object containing the result
+     */
+    private class TraverseLociMap implements NSMapFunction<MapData, MapResult> {
+        final LocusWalker<M,T> walker;
+
+        private TraverseLociMap(LocusWalker<M, T> walker) {
+            this.walker = walker;
+        }
+
+        @Override
+        public MapResult apply(final MapData data) {
+            if ( ! walker.isDone() ) {
+                final boolean keepMeP = walker.filter(data.tracker, data.refContext, data.alignmentContext);
+                if (keepMeP) {
+                    final M x = walker.map(data.tracker, data.refContext, data.alignmentContext);
+                    return new MapResult(x);
+                }
+            }
+            return SKIP_REDUCE;
+        }
+    }
+
+    /**
+     * NSReduceFunction for TraverseReads meeting NanoScheduler interface requirements
+     *
+     * Takes a MapResult object and applies the walkers reduce function to each map result, when applicable
+     */
+    private class TraverseLociReduce implements NSReduceFunction<MapResult, T> {
+        final LocusWalker<M,T> walker;
+
+        private TraverseLociReduce(LocusWalker<M, T> walker) {
+            this.walker = walker;
+        }
+
+        @Override
+        public T apply(MapResult one, T sum) {
+            if ( one.reduceMe )
+                // only run reduce on values that aren't DONE or FAILED
+                return walker.reduce(one.value, sum);
+            else
+                return sum;
+        }
+    }
+
+    private class TraverseLociProgress implements NSProgressFunction<MapData> {
+        @Override
+        public void progress(MapData lastProcessedMap) {
+            if (lastProcessedMap.alignmentContext != null)
+                printProgress(lastProcessedMap.alignmentContext.getLocation());
+        }
+    }
+}
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/traversals/TraverseReadPairs.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/traversals/TraverseReadPairs.java
new file mode 100644
index 0000000..c68e109
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/traversals/TraverseReadPairs.java
@@ -0,0 +1,129 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.engine.traversals;
+
+import htsjdk.samtools.SAMRecord;
+import htsjdk.samtools.SAMRecordCoordinateComparator;
+import org.apache.log4j.Logger;
+import org.broadinstitute.gatk.engine.datasources.providers.ReadShardDataProvider;
+import org.broadinstitute.gatk.engine.datasources.providers.ReadView;
+import org.broadinstitute.gatk.engine.datasources.reads.Shard;
+import org.broadinstitute.gatk.engine.walkers.DataSource;
+import org.broadinstitute.gatk.engine.walkers.ReadPairWalker;
+import org.broadinstitute.gatk.engine.walkers.Requires;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+/**
+ * Traverse over a collection of read pairs, assuming that a given shard will contain all pairs.
+ *
+ * @author mhanna
+ * @version 0.1
+ */
+ at Requires({DataSource.REFERENCE})
+public class TraverseReadPairs<M,T> extends TraversalEngine<M,T, ReadPairWalker<M,T>,ReadShardDataProvider> {
+
+    /** our log, which we want to capture anything from this class */
+    protected static final Logger logger = Logger.getLogger(TraverseReadPairs.class);
+
+    @Override
+    public String getTraversalUnits() {
+        return "read pairs";
+    }
+
+    /**
+     * Traverse by reads, given the data and the walker
+     *
+     * @param walker the walker to execute over
+     * @param sum    of type T, the return from the walker
+     *
+     * @return the result type T, the product of all the reduce calls
+     */
+    public T traverse(ReadPairWalker<M, T> walker,
+                      ReadShardDataProvider dataProvider,
+                      T sum) {
+        logger.debug(String.format("TraverseReadsPairs.traverse Covered dataset is %s", dataProvider));
+
+        if( !dataProvider.hasReads() )
+            throw new IllegalArgumentException("Unable to traverse reads; no read data is available.");
+
+        ReadView reads = new ReadView(dataProvider);
+        List<SAMRecord> pairs = new ArrayList<SAMRecord>();
+
+        boolean done = walker.isDone();
+        for(SAMRecord read: reads) {
+            if ( done ) break;
+            dataProvider.getShard().getReadMetrics().incrementNumReadsSeen();
+
+            if(pairs.size() == 0 || pairs.get(0).getReadName().equals(read.getReadName())) {
+                // If this read name is the same as the last, accumulate it.
+                pairs.add(read);
+            }
+            else {
+                // Otherwise, walk over the accumulated list, then start fresh with the new read.
+                sum = walkOverPairs(walker,dataProvider.getShard(),pairs,sum);
+                pairs.clear();
+                pairs.add(read);
+
+                printProgress(null);
+            }
+
+            done = walker.isDone();
+        }
+
+        // If any data was left in the queue, process it.
+        if(pairs.size() > 0)
+            sum = walkOverPairs(walker,dataProvider.getShard(),pairs,sum);
+
+        return sum;
+    }
+
+    /**
+     * Filter / map / reduce over a single pair.
+     * @param walker The walker.
+     * @param shard The shard currently being processed.
+     * @param reads The reads in the pair.
+     * @param sum The accumulator.
+     * @return The accumulator after application of the given read pairing.
+     */
+    private T walkOverPairs(ReadPairWalker<M,T> walker, Shard shard, List<SAMRecord> reads, T sum) {
+        // update the number of reads we've seen
+        shard.getReadMetrics().incrementNumIterations();
+
+        // Sort the reads present in coordinate order.
+        Collections.sort(reads,new SAMRecordCoordinateComparator());
+
+        final boolean keepMeP = walker.filter(reads);
+        if (keepMeP) {
+            M x = walker.map(reads);
+            sum = walker.reduce(x, sum);
+        }
+
+        return sum;
+    }
+}
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/traversals/TraverseReadsNano.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/traversals/TraverseReadsNano.java
new file mode 100644
index 0000000..2ce752b
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/traversals/TraverseReadsNano.java
@@ -0,0 +1,256 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.engine.traversals;
+
+import htsjdk.samtools.SAMRecord;
+import org.apache.log4j.Logger;
+import org.broadinstitute.gatk.engine.contexts.ReferenceContext;
+import org.broadinstitute.gatk.engine.datasources.providers.ReadBasedReferenceOrderedView;
+import org.broadinstitute.gatk.engine.datasources.providers.ReadReferenceView;
+import org.broadinstitute.gatk.engine.datasources.providers.ReadShardDataProvider;
+import org.broadinstitute.gatk.engine.datasources.providers.ReadView;
+import org.broadinstitute.gatk.engine.refdata.RefMetaDataTracker;
+import org.broadinstitute.gatk.engine.walkers.ReadWalker;
+import org.broadinstitute.gatk.utils.nanoScheduler.NSMapFunction;
+import org.broadinstitute.gatk.utils.nanoScheduler.NSProgressFunction;
+import org.broadinstitute.gatk.utils.nanoScheduler.NSReduceFunction;
+import org.broadinstitute.gatk.utils.nanoScheduler.NanoScheduler;
+import org.broadinstitute.gatk.utils.sam.GATKSAMRecord;
+
+import java.util.Iterator;
+import java.util.LinkedList;
+
+/**
+ * A nano-scheduling version of TraverseReads.
+ *
+ * Implements the traversal of a walker that accepts individual reads, the reference, and
+ * RODs per map call.  Directly supports shared memory parallelism via NanoScheduler
+ *
+ * @author depristo
+ * @version 1.0
+ * @date 9/2/2012
+ */
+public class TraverseReadsNano<M,T> extends TraversalEngine<M,T,ReadWalker<M,T>,ReadShardDataProvider> {
+    /** our log, which we want to capture anything from this class */
+    private final static boolean PRE_READ_ALL_MAP_DATA = true;
+    protected static final Logger logger = Logger.getLogger(TraverseReadsNano.class);
+    private static final boolean DEBUG = false;
+    final NanoScheduler<MapData, MapResult, T> nanoScheduler;
+
+    public TraverseReadsNano(int nThreads) {
+        nanoScheduler = new NanoScheduler<MapData, MapResult, T>(nThreads);
+        nanoScheduler.setProgressFunction(new NSProgressFunction<MapData>() {
+            @Override
+            public void progress(MapData lastProcessedMap) {
+                if ( lastProcessedMap.refContext != null )
+                    // note, need to use getStopLocation so we don't give an interval to ProgressMeterDaemon
+                    printProgress(lastProcessedMap.refContext.getLocus().getStopLocation());
+            }
+        });
+    }
+
+    @Override
+    public String getTraversalUnits() {
+        return "reads";
+    }
+
+    /**
+     * Traverse by reads, given the data and the walker
+     *
+     * @param walker the walker to traverse with
+     * @param dataProvider the provider of the reads data
+     * @param sum the value of type T, specified by the walker, to feed to the walkers reduce function
+     * @return the reduce variable of the read walker
+     */
+    public T traverse(ReadWalker<M,T> walker,
+                      ReadShardDataProvider dataProvider,
+                      T sum) {
+        if ( logger.isDebugEnabled() )
+            logger.debug(String.format("TraverseReadsNano.traverse Covered dataset is %s", dataProvider));
+
+        if( !dataProvider.hasReads() )
+            throw new IllegalArgumentException("Unable to traverse reads; no read data is available.");
+
+        nanoScheduler.setDebug(DEBUG);
+        final TraverseReadsMap myMap = new TraverseReadsMap(walker);
+        final TraverseReadsReduce myReduce = new TraverseReadsReduce(walker);
+
+        final Iterator<MapData> aggregatedInputs = aggregateMapData(dataProvider);
+        final T result = nanoScheduler.execute(aggregatedInputs, myMap, sum, myReduce);
+
+        return result;
+    }
+
+    /**
+     * Aggregate all of the inputs for all map calls into MapData, to be provided
+     * to NanoScheduler for Map/Reduce
+     *
+     * @param dataProvider the source of our data
+     * @return a linked list of MapData objects holding the read, ref, and ROD info for every map/reduce
+     *          should execute
+     */
+    private Iterator<MapData> aggregateMapData(final ReadShardDataProvider dataProvider) {
+        final Iterator<MapData> it = makeDataIterator(dataProvider);
+        if ( PRE_READ_ALL_MAP_DATA ) {
+            final LinkedList<MapData> l = new LinkedList<MapData>();
+            while ( it.hasNext() ) l.add(it.next());
+            return l.iterator();
+        } else {
+            return it;
+        }
+    }
+
+
+    private Iterator<MapData> makeDataIterator(final ReadShardDataProvider dataProvider) {
+        return new Iterator<MapData> ()  {
+            final ReadView reads = new ReadView(dataProvider);
+            final ReadReferenceView reference = new ReadReferenceView(dataProvider);
+            final ReadBasedReferenceOrderedView rodView = new ReadBasedReferenceOrderedView(dataProvider);
+            final Iterator<SAMRecord> readIterator = reads.iterator();
+
+            @Override public boolean hasNext() { return ! engine.exceedsRuntimeLimit() && readIterator.hasNext(); }
+
+            @Override
+            public MapData next() {
+                final SAMRecord read = readIterator.next();
+                final ReferenceContext refContext = ! read.getReadUnmappedFlag()
+                        ? reference.getReferenceContext(read)
+                        : null;
+
+                // if the read is mapped, create a metadata tracker
+                final RefMetaDataTracker tracker = read.getReferenceIndex() >= 0
+                        ? rodView.getReferenceOrderedDataForRead(read)
+                        : null;
+
+                // update the number of reads we've seen
+                dataProvider.getShard().getReadMetrics().incrementNumIterations();
+
+                return new MapData((GATKSAMRecord)read, refContext, tracker);
+            }
+
+            @Override public void remove() {
+                throw new UnsupportedOperationException("Remove not supported");
+            }
+        };
+    }
+
+    @Override
+    public void shutdown() {
+        nanoScheduler.shutdown();
+    }
+
+    /**
+     * The input data needed for each map call.  The read, the reference, and the RODs
+     */
+    private class MapData {
+        final GATKSAMRecord read;
+        final ReferenceContext refContext;
+        final RefMetaDataTracker tracker;
+
+        private MapData(GATKSAMRecord read, ReferenceContext refContext, RefMetaDataTracker tracker) {
+            this.read = read;
+            this.refContext = refContext;
+            this.tracker = tracker;
+        }
+    }
+
+    /**
+     * Contains the results of a map call, indicating whether the call was good, filtered, or done
+     */
+    private class MapResult {
+        final M value;
+        final boolean reduceMe;
+
+        /**
+         * Create a MapResult with value that should be reduced
+         *
+         * @param value the value to reduce
+         */
+        private MapResult(final M value) {
+            this.value = value;
+            this.reduceMe = true;
+        }
+
+        /**
+         * Create a MapResult that shouldn't be reduced
+         */
+        private MapResult() {
+            this.value = null;
+            this.reduceMe = false;
+        }
+    }
+
+    /**
+     * A static object that tells reduce that the result of map should be skipped (filtered or done)
+     */
+    private final MapResult SKIP_REDUCE = new MapResult();
+
+    /**
+     * MapFunction for TraverseReads meeting NanoScheduler interface requirements
+     *
+     * Applies walker.map to MapData, returning a MapResult object containing the result
+     */
+    private class TraverseReadsMap implements NSMapFunction<MapData, MapResult> {
+        final ReadWalker<M,T> walker;
+
+        private TraverseReadsMap(ReadWalker<M, T> walker) {
+            this.walker = walker;
+        }
+
+        @Override
+        public MapResult apply(final MapData data) {
+            if ( ! walker.isDone() ) {
+                final boolean keepMeP = walker.filter(data.refContext, data.read);
+                if (keepMeP)
+                    return new MapResult(walker.map(data.refContext, data.read, data.tracker));
+            }
+
+            return SKIP_REDUCE;
+        }
+    }
+
+    /**
+     * NSReduceFunction for TraverseReads meeting NanoScheduler interface requirements
+     *
+     * Takes a MapResult object and applies the walkers reduce function to each map result, when applicable
+     */
+    private class TraverseReadsReduce implements NSReduceFunction<MapResult, T> {
+        final ReadWalker<M,T> walker;
+
+        private TraverseReadsReduce(ReadWalker<M, T> walker) {
+            this.walker = walker;
+        }
+
+        @Override
+        public T apply(MapResult one, T sum) {
+            if ( one.reduceMe )
+                // only run reduce on values that aren't DONE or FAILED
+                return walker.reduce(one.value, sum);
+            else
+                return sum;
+        }
+    }
+}
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/traversals/package-info.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/traversals/package-info.java
new file mode 100644
index 0000000..72d1099
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/traversals/package-info.java
@@ -0,0 +1,26 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.engine.traversals;
\ No newline at end of file
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/walkers/ActiveRegionTraversalParameters.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/walkers/ActiveRegionTraversalParameters.java
new file mode 100644
index 0000000..7c428cd
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/walkers/ActiveRegionTraversalParameters.java
@@ -0,0 +1,97 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.engine.walkers;
+
+import org.broadinstitute.gatk.utils.activeregion.BandPassActivityProfile;
+
+import java.lang.annotation.Documented;
+import java.lang.annotation.Inherited;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+
+/**
+ * Describes the parameters that this walker requires of the active region traversal
+ *
+ * User: rpoplin
+ * Date: 1/18/12
+ */
+ at Documented
+ at Inherited
+ at Retention(RetentionPolicy.RUNTIME)
+
+public @interface ActiveRegionTraversalParameters {
+    /**
+     * How far to either side of the active region itself should we include reads?
+     *
+     * That is, if the active region is 10 bp wide, and extension is 5, ART will provide
+     * the walker with active regions 10 bp, with 5 bp of extension on either side, and
+     * all reads that cover the 20 bp of the region + extension.
+     *
+     * @return the size of the active region extension we'd like
+     */
+    public int extension() default 0;
+
+    /**
+     * The minimum number of bp for an active region, when we need to chop it up into pieces because
+     * it's become too big.  This only comes into effect when there's literally no good place to chop
+     * that does make the region smaller than this value.
+     *
+     * @return the min size in bp of regions
+     */
+    public int minRegion() default 50;
+
+    /**
+     * The maximum size in bp of active regions wanted by this walker
+     *
+     * Active regions larger than this value are automatically cut up by ART into smaller
+     * regions of size <= this value.
+     *
+     * @return the max size in bp of regions
+     */
+    public int maxRegion() default 1500;
+
+    /**
+     * The variance value for the Gaussian kernel of the band pass filter employed by ART
+     * @return the breadth of the band pass gaussian kernel we want for our traversal
+     */
+    public double bandPassSigma() default BandPassActivityProfile.DEFAULT_SIGMA;
+
+    /**
+     * What is the maximum number of reads we're willing to hold in memory per sample
+     * during the traversal?  This limits our exposure to unusually large amounts
+     * of coverage in the engine.
+     * @return the maximum number of reads we're willing to hold in memory
+     */
+    public int maxReadsToHoldInMemoryPerSample() default 3000;
+
+    /**
+     * No matter what the per sample value says, we will never hold more than this
+     * number of reads in memory at any time.  Provides an upper bound on the total number
+     * of reads in the case where we have a lot of samples.
+     * @return the maximum number of reads to hold in memory
+     */
+    public int maxReadsToHoldTotal() default 1000000;
+}
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/walkers/ActiveRegionWalker.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/walkers/ActiveRegionWalker.java
new file mode 100644
index 0000000..9ff68bc
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/walkers/ActiveRegionWalker.java
@@ -0,0 +1,196 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.engine.walkers;
+
+import com.google.java.contract.Ensures;
+import htsjdk.samtools.reference.IndexedFastaSequenceFile;
+import htsjdk.tribble.Feature;
+import org.broadinstitute.gatk.utils.commandline.*;
+import org.broadinstitute.gatk.engine.contexts.AlignmentContext;
+import org.broadinstitute.gatk.engine.contexts.ReferenceContext;
+import org.broadinstitute.gatk.engine.downsampling.DownsampleType;
+import org.broadinstitute.gatk.engine.filters.*;
+import org.broadinstitute.gatk.engine.refdata.RefMetaDataTracker;
+import org.broadinstitute.gatk.utils.GenomeLoc;
+import org.broadinstitute.gatk.utils.GenomeLocParser;
+import org.broadinstitute.gatk.utils.GenomeLocSortedSet;
+import org.broadinstitute.gatk.utils.activeregion.ActiveRegion;
+import org.broadinstitute.gatk.utils.activeregion.ActiveRegionReadState;
+import org.broadinstitute.gatk.utils.activeregion.ActivityProfileState;
+import org.broadinstitute.gatk.utils.interval.IntervalMergingRule;
+import org.broadinstitute.gatk.utils.interval.IntervalSetRule;
+import org.broadinstitute.gatk.utils.interval.IntervalUtils;
+
+import java.io.PrintStream;
+import java.util.*;
+
+/**
+ * Base class for all the Active Region Walkers.
+ * User: rpoplin
+ * Date: 12/7/11
+ */
+
+ at By(DataSource.READS)
+ at Requires({DataSource.READS, DataSource.REFERENCE})
+ at PartitionBy(PartitionType.READ)
+ at ActiveRegionTraversalParameters(extension=50,maxRegion=1500)
+ at ReadFilters({UnmappedReadFilter.class, NotPrimaryAlignmentFilter.class, DuplicateReadFilter.class, FailsVendorQualityCheckFilter.class, MappingQualityUnavailableFilter.class})
+ at Downsample(by = DownsampleType.BY_SAMPLE, toCoverage = 1000)
+ at RemoveProgramRecords
+public abstract class ActiveRegionWalker<MapType, ReduceType> extends Walker<MapType, ReduceType> {
+    /**
+     * If provided, this walker will write out its activity profile (per bp probabilities of being active)
+     * to this file in the IGV formatted TAB deliminated output:
+     *
+     * http://www.broadinstitute.org/software/igv/IGV
+     *
+     * Intended to make debugging the activity profile calculations easier
+     */
+    @Output(fullName="activityProfileOut", shortName="APO", doc="Output the raw activity profile results in IGV format", required = false, defaultToStdout = false)
+    public PrintStream activityProfileOutStream = null;
+
+    /**
+     * If provided, this walker will write out its active and inactive regions
+     * to this file in the IGV formatted TAB deliminated output:
+     *
+     * http://www.broadinstitute.org/software/igv/IGV
+     *
+     * Intended to make debugging the active region calculations easier
+     */
+    @Output(fullName="activeRegionOut", shortName="ARO", doc="Output the active region to this IGV formatted file", required = false, defaultToStdout = false)
+    public PrintStream activeRegionOutStream = null;
+
+    @Advanced
+    @Input(fullName="activeRegionIn", shortName="AR", doc="Use this interval list file as the active regions to process", required = false)
+    protected List<IntervalBinding<Feature>> activeRegionBindings = null;
+
+    @Advanced
+    @Argument(fullName="activeRegionExtension", shortName="activeRegionExtension", doc="The active region extension; if not provided defaults to Walker annotated default", required = false)
+    public Integer activeRegionExtension = null;
+
+    /**
+     * For the active region walker to treat all bases as active.  Useful for debugging when you want to force something like
+     * the HaplotypeCaller to process a specific interval you provide the GATK
+     */
+    @Advanced
+    @Argument(fullName="forceActive", shortName="forceActive", doc="If provided, all bases will be tagged as active", required = false)
+    public boolean forceActive = false;
+
+    @Advanced
+    @Argument(fullName="activeRegionMaxSize", shortName="activeRegionMaxSize", doc="The active region maximum size; if not provided defaults to Walker annotated default", required = false)
+    public Integer activeRegionMaxSize = null;
+
+    @Advanced
+    @Argument(fullName="bandPassSigma", shortName="bandPassSigma", doc="The sigma of the band pass filter Gaussian kernel; if not provided defaults to Walker annotated default", required = false)
+    public Double bandPassSigma = null;
+
+    /*
+     * For active region limits in ActivityProfile
+*   */
+    @Hidden
+    @Argument(fullName = "maxProbPropagationDistance", shortName = "maxProbPropDist", minValue = 0, doc="Region probability propagation distance beyond it's maximum size.", required = false)
+    public Integer maxProbPropagationDistance = 50;
+
+    @Advanced
+    @Argument(fullName = "activeProbabilityThreshold", shortName = "ActProbThresh", minValue = 0.0, maxValue = 1.0, doc="Threshold for the probability of a profile state being active.", required = false)
+    public Double activeProbThreshold = 0.002;
+
+    private GenomeLocSortedSet presetActiveRegions = null;
+
+    @Override
+    public void initialize() {
+        if( activeRegionBindings == null ) { return; }
+        List<GenomeLoc> allIntervals = new ArrayList<GenomeLoc>(0);
+        for ( IntervalBinding intervalBinding : activeRegionBindings ) {
+            List<GenomeLoc> intervals = intervalBinding.getIntervals(this.getToolkit());
+
+            if ( intervals.isEmpty() ) {
+                logger.warn("The interval file " + intervalBinding.getSource() + " contains no intervals that could be parsed.");
+            }
+
+            allIntervals = IntervalUtils.mergeListsBySetOperator(intervals, allIntervals, IntervalSetRule.UNION);
+        }
+
+        presetActiveRegions = IntervalUtils.sortAndMergeIntervals(this.getToolkit().getGenomeLocParser(), allIntervals, IntervalMergingRule.ALL);
+    }
+
+    /**
+     * Does this walker want us to use a set of preset action regions instead of dynamically using the result of isActive?
+     * @return true if yes, false if no
+     */
+    public boolean hasPresetActiveRegions() {
+        return presetActiveRegions != null;
+    }
+
+    /**
+     * Get the set of preset active regions, or null if none were provided
+     * @return a set of genome locs specifying fixed active regions requested by the walker, or null if none exist
+     */
+    public GenomeLocSortedSet getPresetActiveRegions() {
+        return presetActiveRegions;
+    }
+
+    // Do we actually want to operate on the context?
+    public boolean filter(final RefMetaDataTracker tracker, final ReferenceContext ref, final AlignmentContext context) {
+        return true;    // We are keeping all the reads
+    }
+
+    public EnumSet<ActiveRegionReadState> desiredReadStates() {
+        return EnumSet.of(ActiveRegionReadState.PRIMARY);
+    }
+
+    public final boolean wantsNonPrimaryReads() {
+        return desiredReadStates().contains(ActiveRegionReadState.NONPRIMARY);
+    }
+
+    public boolean wantsExtendedReads() {
+        return desiredReadStates().contains(ActiveRegionReadState.EXTENDED);
+    }
+
+    public boolean wantsUnmappedReads() {
+        return desiredReadStates().contains(ActiveRegionReadState.UNMAPPED);
+    }
+
+    // Determine probability of active status over the AlignmentContext
+    @Ensures({"result.isActiveProb >= 0.0", "result.isActiveProb <= 1.0"})
+    public abstract ActivityProfileState isActive(final RefMetaDataTracker tracker, final ReferenceContext ref, final AlignmentContext context);
+
+    // Map over the ActiveRegion
+    public abstract MapType map(final ActiveRegion activeRegion, final RefMetaDataTracker metaDataTracker);
+
+    public final GenomeLocSortedSet extendIntervals( final GenomeLocSortedSet intervals, final GenomeLocParser genomeLocParser, IndexedFastaSequenceFile reference ) {
+        final int activeRegionExtension = this.getClass().getAnnotation(ActiveRegionTraversalParameters.class).extension();
+        final List<GenomeLoc> allIntervals = new ArrayList<GenomeLoc>();
+        for( final GenomeLoc interval : intervals.toList() ) {
+            final int start = Math.max( 1, interval.getStart() - activeRegionExtension );
+            final int stop = Math.min( reference.getSequenceDictionary().getSequence(interval.getContig()).getSequenceLength(), interval.getStop() + activeRegionExtension );
+            allIntervals.add( genomeLocParser.createGenomeLoc(interval.getContig(), start, stop) );
+        }
+        return IntervalUtils.sortAndMergeIntervals(genomeLocParser, allIntervals, IntervalMergingRule.ALL);
+    }
+
+
+}
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/walkers/Allows.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/walkers/Allows.java
new file mode 100644
index 0000000..7188fd0
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/walkers/Allows.java
@@ -0,0 +1,51 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.engine.walkers;
+
+import java.lang.annotation.*;
+/**
+ * User: hanna
+ * Date: May 19, 2009
+ * Time: 10:05:01 AM
+ * BROAD INSTITUTE SOFTWARE COPYRIGHT NOTICE AND AGREEMENT
+ * Software and documentation are copyright 2005 by the Broad Institute.
+ * All rights are reserved.
+ *
+ * Users acknowledge that this software is supplied without any warranty or support.
+ * The Broad Institute is not responsible for its use, misuse, or
+ * functionality.
+ */
+
+/**
+ * Determines what data sources are allowed by a given walker.
+ */
+ at Documented
+ at Inherited
+ at Retention(RetentionPolicy.RUNTIME)
+ at Target(ElementType.TYPE)
+public @interface Allows {
+    DataSource[] value();
+}
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/walkers/Attribution.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/walkers/Attribution.java
new file mode 100644
index 0000000..ded2941
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/walkers/Attribution.java
@@ -0,0 +1,39 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.engine.walkers;
+
+import java.lang.annotation.*;
+
+/**
+ * Allow users to provide attribution text that will appear prominently in the log output.
+ */
+ at Documented
+ at Inherited
+ at Retention(RetentionPolicy.RUNTIME)
+ at Target(ElementType.TYPE)
+public @interface Attribution {
+    public String[] value();
+}
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/walkers/BAQMode.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/walkers/BAQMode.java
new file mode 100644
index 0000000..931381e
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/walkers/BAQMode.java
@@ -0,0 +1,56 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.engine.walkers;
+
+import org.broadinstitute.gatk.engine.iterators.ReadTransformer;
+
+import java.lang.annotation.*;
+
+/**
+ * User: hanna
+ * Date: May 14, 2009
+ * Time: 1:51:22 PM
+ * BROAD INSTITUTE SOFTWARE COPYRIGHT NOTICE AND AGREEMENT
+ * Software and documentation are copyright 2005 by the Broad Institute.
+ * All rights are reserved.
+ *
+ * Users acknowledge that this software is supplied without any warranty or support.
+ * The Broad Institute is not responsible for its use, misuse, or
+ * functionality.
+ */
+
+/**
+ * Allows the walker to indicate what type of data it wants to consume.
+ */
+
+ at Documented
+ at Inherited
+ at Retention(RetentionPolicy.RUNTIME)
+ at Target(ElementType.TYPE)
+public @interface BAQMode {
+    public abstract org.broadinstitute.gatk.utils.baq.BAQ.QualityMode QualityMode() default org.broadinstitute.gatk.utils.baq.BAQ.QualityMode.OVERWRITE_QUALS;
+    public abstract ReadTransformer.ApplicationTime ApplicationTime() default ReadTransformer.ApplicationTime.ON_INPUT;
+}
\ No newline at end of file
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/walkers/By.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/walkers/By.java
new file mode 100644
index 0000000..3962c98
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/walkers/By.java
@@ -0,0 +1,53 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.engine.walkers;
+
+import java.lang.annotation.*;
+/**
+ * User: hanna
+ * Date: May 14, 2009
+ * Time: 1:51:22 PM
+ * BROAD INSTITUTE SOFTWARE COPYRIGHT NOTICE AND AGREEMENT
+ * Software and documentation are copyright 2005 by the Broad Institute.
+ * All rights are reserved.
+ *
+ * Users acknowledge that this software is supplied without any warranty or support.
+ * The Broad Institute is not responsible for its use, misuse, or
+ * functionality.
+ */
+
+/**
+ * Allows the walker to indicate what type of data it wants to consume.
+ */
+
+ at Documented
+ at Inherited
+ at Retention(RetentionPolicy.RUNTIME)
+ at Target(ElementType.TYPE)
+public @interface By {
+    DataSource value();
+}
+
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/walkers/DataSource.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/walkers/DataSource.java
new file mode 100644
index 0000000..fab9840
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/walkers/DataSource.java
@@ -0,0 +1,58 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.engine.walkers;
+/**
+ * User: hanna
+ * Date: May 14, 2009
+ * Time: 2:12:33 PM
+ * BROAD INSTITUTE SOFTWARE COPYRIGHT NOTICE AND AGREEMENT
+ * Software and documentation are copyright 2005 by the Broad Institute.
+ * All rights are reserved.
+ *
+ * Users acknowledge that this software is supplied without any warranty or support.
+ * The Broad Institute is not responsible for its use, misuse, or
+ * functionality.
+ */
+
+/**
+ * Allow user to choose between a number of different data sources.
+ */
+public enum DataSource {
+    /**
+     * Does this walker require read (BAM) data to work?
+     */
+    READS,
+
+    /**
+     * Does this walker require reference data to work?
+     */
+    REFERENCE,
+
+    /**
+     * Does this walker require reference order data (VCF) to work?
+     */
+    REFERENCE_ORDERED_DATA
+}
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/walkers/Downsample.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/walkers/Downsample.java
new file mode 100644
index 0000000..c112d7d
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/walkers/Downsample.java
@@ -0,0 +1,47 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.engine.walkers;
+
+import org.broadinstitute.gatk.engine.downsampling.DownsampleType;
+
+import java.lang.annotation.*;
+
+/**
+ * Specifies a method for downsampling the reads passed to a given
+ * walker based on the input from that walker.
+ *
+ * @author hanna
+ * @version 0.1
+ */
+ at Documented
+ at Inherited
+ at Retention(RetentionPolicy.RUNTIME)
+ at Target(ElementType.TYPE)
+public @interface Downsample {
+    DownsampleType by();
+    int toCoverage() default -1;
+    double toFraction() default -1.0F;
+}
\ No newline at end of file
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/walkers/DuplicateWalker.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/walkers/DuplicateWalker.java
new file mode 100644
index 0000000..96d2d5d
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/walkers/DuplicateWalker.java
@@ -0,0 +1,57 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.engine.walkers;
+
+import org.broadinstitute.gatk.engine.contexts.AlignmentContext;
+import org.broadinstitute.gatk.engine.filters.NotPrimaryAlignmentFilter;
+import org.broadinstitute.gatk.engine.filters.UnmappedReadFilter;
+import org.broadinstitute.gatk.utils.GenomeLoc;
+import org.broadinstitute.gatk.utils.sam.GATKSAMRecord;
+
+import java.util.List;
+import java.util.Set;
+
+/**
+ * Created by IntelliJ IDEA.
+ * User: mdepristo
+ * Date: Feb 22, 2009
+ * Time: 2:52:28 PM
+ * To change this template use File | Settings | File Templates.
+ */
+ at Requires({DataSource.READS,DataSource.REFERENCE})
+ at ReadFilters({UnmappedReadFilter.class,NotPrimaryAlignmentFilter.class})
+public abstract class DuplicateWalker<MapType, ReduceType> extends Walker<MapType, ReduceType> {
+    // Do we actually want to operate on the context?
+    public boolean filter(GenomeLoc loc, AlignmentContext context, Set<List<GATKSAMRecord>> readSets ) {
+        return true;    // We are keeping all the reads
+    }
+
+    public abstract MapType map(GenomeLoc loc, AlignmentContext context, Set<List<GATKSAMRecord>> readSets );
+
+    // Given result of map function
+    public abstract ReduceType reduceInit();
+    public abstract ReduceType reduce(MapType value, ReduceType sum);
+}
\ No newline at end of file
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/walkers/LocusWalker.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/walkers/LocusWalker.java
new file mode 100644
index 0000000..1e7b0e5
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/walkers/LocusWalker.java
@@ -0,0 +1,58 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.engine.walkers;
+
+import org.broadinstitute.gatk.engine.contexts.AlignmentContext;
+import org.broadinstitute.gatk.engine.contexts.ReferenceContext;
+import org.broadinstitute.gatk.engine.downsampling.DownsampleType;
+import org.broadinstitute.gatk.engine.filters.DuplicateReadFilter;
+import org.broadinstitute.gatk.engine.filters.FailsVendorQualityCheckFilter;
+import org.broadinstitute.gatk.engine.filters.NotPrimaryAlignmentFilter;
+import org.broadinstitute.gatk.engine.filters.UnmappedReadFilter;
+import org.broadinstitute.gatk.engine.refdata.RefMetaDataTracker;
+
+/**
+ * Created by IntelliJ IDEA.
+ * User: mdepristo
+ * Date: Feb 22, 2009
+ * Time: 2:52:28 PM
+ * To change this template use File | Settings | File Templates.
+ */
+ at By(DataSource.READS)
+ at Requires({DataSource.READS,DataSource.REFERENCE})
+ at PartitionBy(PartitionType.LOCUS)
+ at ReadFilters({UnmappedReadFilter.class,NotPrimaryAlignmentFilter.class,DuplicateReadFilter.class,FailsVendorQualityCheckFilter.class})
+ at Downsample(by = DownsampleType.BY_SAMPLE, toCoverage = 1000)
+ at RemoveProgramRecords
+public abstract class LocusWalker<MapType, ReduceType> extends Walker<MapType, ReduceType> {
+    // Do we actually want to operate on the context?
+    public boolean filter(RefMetaDataTracker tracker, ReferenceContext ref, AlignmentContext context) {
+        return true;    // We are keeping all the reads
+    }
+
+    // Map over the org.broadinstitute.gatk.engine.contexts.AlignmentContext
+    public abstract MapType map(RefMetaDataTracker tracker, ReferenceContext ref, AlignmentContext context);
+}
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/walkers/Multiplex.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/walkers/Multiplex.java
new file mode 100644
index 0000000..e771d1e
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/walkers/Multiplex.java
@@ -0,0 +1,44 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.engine.walkers;
+
+import java.lang.annotation.*;
+
+/**
+ * Indicates that the class should be multiplexed according to the rules
+ * specified in the multiplexer.
+ *
+ * @author mhanna
+ * @version 0.1
+ */
+ at Documented
+ at Inherited
+ at Retention(RetentionPolicy.RUNTIME)
+ at Target({ElementType.FIELD})
+public @interface Multiplex {
+    public Class<? extends Multiplexer> value();
+    public String[] arguments() default {};
+}
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/walkers/Multiplexer.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/walkers/Multiplexer.java
new file mode 100644
index 0000000..969e288
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/walkers/Multiplexer.java
@@ -0,0 +1,52 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.engine.walkers;
+
+import java.util.Collection;
+
+/**
+ * An interface for multiplexing output streams.
+ *
+ * @author mhanna
+ * @version 0.1
+ */
+public interface Multiplexer<T> {
+    /**
+     * Generate a list of the potential outputs that can be created as a function of the other
+     * command-line arguments in this class.
+     * @return A collection of unique identifiers for the file multiplex.
+     */
+    public Collection<T> multiplex();
+
+    /**
+     * Transform the given command-line argument into a suitable form specific to this filename.
+     * @param multiplexedEntry Identifies the individual component of the multiplex.  Will be a value in the collection
+     *        passed back by multiplex().
+     * @param argument The actual command-line argument, supplied for transformation.
+     * @return A transformed representation of the command-line argument.
+     */
+    public String transformArgument(final T multiplexedEntry, final String argument);
+}
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/walkers/NanoSchedulable.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/walkers/NanoSchedulable.java
new file mode 100644
index 0000000..5852b77
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/walkers/NanoSchedulable.java
@@ -0,0 +1,34 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.engine.walkers;
+
+/**
+ * Root parallelism interface.  Walkers that implement this
+ * declare that their map function is thread-safe and so multiple
+ * map calls can be run in parallel in the same JVM instance.
+ */
+public interface NanoSchedulable {
+}
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/walkers/PartitionBy.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/walkers/PartitionBy.java
new file mode 100644
index 0000000..346f7c4
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/walkers/PartitionBy.java
@@ -0,0 +1,39 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.engine.walkers;
+
+import java.lang.annotation.*;
+
+/**
+ * Allows the walker to indicate how to partition data it wants to consume.
+ */
+ at Documented
+ at Inherited
+ at Retention(RetentionPolicy.RUNTIME)
+ at Target(ElementType.TYPE)
+public @interface PartitionBy {
+    PartitionType value();
+}
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/walkers/PartitionType.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/walkers/PartitionType.java
new file mode 100644
index 0000000..2c738e1
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/walkers/PartitionType.java
@@ -0,0 +1,61 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.engine.walkers;
+
+/**
+ * Defines the ways walkers inputs can be partitioned before
+ * being passed to multiple instances of the walker.
+ */
+public enum PartitionType {
+    /**
+     * Do not partition the walker inputs.
+     */
+    NONE,
+
+    /**
+     * The walker inputs can be chunked down to individual
+     * reads.
+     */
+    READ,
+
+    /**
+     * The walker inputs can be chunked down to the
+     * per-locus level.
+     */
+    LOCUS,
+
+    /**
+     * The walker inputs should be processed as complete
+     * intervals defined -L or the reference contigs.
+     */
+    INTERVAL,
+
+    /**
+     * The walker inputs should always be processed as complete
+     * contigs, even if there are multiple intervals per contig.
+     */
+    CONTIG
+}
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/walkers/RMD.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/walkers/RMD.java
new file mode 100644
index 0000000..a2ee8d0
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/walkers/RMD.java
@@ -0,0 +1,56 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.engine.walkers;
+
+import htsjdk.tribble.Feature;
+
+import java.lang.annotation.Documented;
+import java.lang.annotation.Inherited;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+/**
+ * User: hanna
+ * Date: May 19, 2009
+ * Time: 1:34:15 PM
+ * BROAD INSTITUTE SOFTWARE COPYRIGHT NOTICE AND AGREEMENT
+ * Software and documentation are copyright 2005 by the Broad Institute.
+ * All rights are reserved.
+ *
+ * Users acknowledge that this software is supplied without any warranty or support.
+ * The Broad Institute is not responsible for its use, misuse, or
+ * functionality.
+ */
+
+/**
+ * A data type representing reference-ordered data.
+ */
+ at Documented
+ at Inherited
+ at Retention(RetentionPolicy.RUNTIME)
+public @interface RMD {
+    String name();    
+    Class type() default Feature.class;
+}
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/walkers/ReadFilters.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/walkers/ReadFilters.java
new file mode 100644
index 0000000..eac5715
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/walkers/ReadFilters.java
@@ -0,0 +1,45 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.engine.walkers;
+
+import htsjdk.samtools.filter.SamRecordFilter;
+import org.broadinstitute.gatk.utils.help.DocumentedGATKFeature;
+
+import java.lang.annotation.*;
+
+/**
+ * An annotation to describe what kind of data will be filtered out.
+ *
+ * @author hanna
+ * @version 0.1
+ */
+ at Documented
+ at Inherited
+ at Retention(RetentionPolicy.RUNTIME)
+ at Target(ElementType.TYPE)
+public @interface ReadFilters {
+    public Class<? extends SamRecordFilter>[] value() default {};
+}
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/walkers/ReadPairWalker.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/walkers/ReadPairWalker.java
new file mode 100644
index 0000000..67eae69
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/walkers/ReadPairWalker.java
@@ -0,0 +1,63 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.engine.walkers;
+
+import htsjdk.samtools.SAMRecord;
+
+import java.util.Collection;
+
+/**
+ * Walks over all pairs/collections of reads in a BAM file sorted by
+ * read name.
+ *
+ * @author mhanna
+ * @version 0.1
+ */
+ at Requires({DataSource.READS})
+public abstract class ReadPairWalker<MapType,ReduceType> extends Walker<MapType,ReduceType> {
+
+    /**
+     * Optionally filters out read pairs.
+     * @param reads collections of all reads with the same read name.
+     * @return True to process the reads with map/reduce; false otherwise.
+     */
+    public boolean filter(Collection<SAMRecord> reads) {
+        // Keep all pairs by default.
+        return true;
+    }
+
+    /**
+     * Maps a read pair to a given reduce of type MapType.  Semantics determined by subclasser.
+     * @param reads Collection of reads having the same name.
+     * @return Semantics defined by implementer.
+     */
+    public abstract MapType map(Collection<SAMRecord> reads);
+
+    // Given result of map function
+    public abstract ReduceType reduceInit();
+    public abstract ReduceType reduce(MapType value, ReduceType sum);
+
+}
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/walkers/ReadWalker.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/walkers/ReadWalker.java
new file mode 100644
index 0000000..9528cf1
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/walkers/ReadWalker.java
@@ -0,0 +1,55 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.engine.walkers;
+
+import org.broadinstitute.gatk.engine.contexts.ReferenceContext;
+import org.broadinstitute.gatk.engine.refdata.RefMetaDataTracker;
+import org.broadinstitute.gatk.utils.sam.GATKSAMRecord;
+
+/**
+ * Created by IntelliJ IDEA.
+ * User: mdepristo
+ * Date: Feb 22, 2009
+ * Time: 2:52:28 PM
+ * To change this template use File | Settings | File Templates.
+ */
+ at Requires({DataSource.READS, DataSource.REFERENCE})
+ at PartitionBy(PartitionType.READ)
+public abstract class ReadWalker<MapType, ReduceType> extends Walker<MapType, ReduceType> {
+    public boolean requiresOrderedReads() { return false; }
+    
+    // Do we actually want to operate on the context?
+    /** Must return true for reads that need to be processed. Reads, for which this method return false will
+     * be skipped by the engine and never passed to the walker.
+     */
+    public boolean filter(ReferenceContext ref, GATKSAMRecord read) {
+        // We are keeping all the reads
+        return true;
+    }
+
+    // Map over the org.broadinstitute.gatk.engine.contexts.AlignmentContext
+    public abstract MapType map(ReferenceContext ref, GATKSAMRecord read, RefMetaDataTracker metaDataTracker);
+}
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/walkers/RefWalker.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/walkers/RefWalker.java
new file mode 100644
index 0000000..90c10c5
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/walkers/RefWalker.java
@@ -0,0 +1,39 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.engine.walkers;
+
+/**
+ * Created by IntelliJ IDEA.
+ * User: mdepristo
+ * Date: Feb 22, 2009
+ * Time: 2:52:28 PM
+ * To change this template use File | Settings | File Templates.
+ */
+ at By(DataSource.REFERENCE)
+ at Requires({DataSource.REFERENCE})
+ at Allows(DataSource.REFERENCE)
+public abstract class RefWalker<MapType, ReduceType> extends LocusWalker<MapType, ReduceType> {
+}
\ No newline at end of file
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/walkers/Reference.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/walkers/Reference.java
new file mode 100644
index 0000000..3598cf5
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/walkers/Reference.java
@@ -0,0 +1,47 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.engine.walkers;
+
+import java.lang.annotation.*;
+
+/**
+ * Describes presentation, capabilities, and limitations of the reference
+ * provided to the GATK.
+ *
+ * @author mhanna
+ * @version 0.1
+ */
+ at Documented
+ at Inherited
+ at Retention(RetentionPolicy.RUNTIME)
+ at Target(ElementType.TYPE)
+public @interface Reference {
+    /**
+     * Specifies the window expansion for the current walker.
+     * @return The window to which the reference should be expanded.  Defaults to [0,0] (no expansion).
+     */
+    public Window window() default @Window;
+}
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/walkers/RemoveProgramRecords.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/walkers/RemoveProgramRecords.java
new file mode 100644
index 0000000..ad945f2
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/walkers/RemoveProgramRecords.java
@@ -0,0 +1,46 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.engine.walkers;
+
+/**
+ * Created with IntelliJ IDEA.
+ * User: thibault
+ * Date: 8/2/12
+ * Time: 1:58 PM
+ * To change this template use File | Settings | File Templates.
+ */
+
+import java.lang.annotation.*;
+
+/**
+ * Indicates that program records should be removed from SAM headers by default for this walker
+ */
+ at Documented
+ at Inherited
+ at Retention(RetentionPolicy.RUNTIME)
+ at Target(ElementType.TYPE)
+public @interface RemoveProgramRecords {
+}
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/walkers/Requires.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/walkers/Requires.java
new file mode 100644
index 0000000..5a16a67
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/walkers/Requires.java
@@ -0,0 +1,52 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.engine.walkers;
+
+import java.lang.annotation.*;
+/**
+ * User: hanna
+ * Date: May 19, 2009
+ * Time: 10:06:47 AM
+ * BROAD INSTITUTE SOFTWARE COPYRIGHT NOTICE AND AGREEMENT
+ * Software and documentation are copyright 2005 by the Broad Institute.
+ * All rights are reserved.
+ *
+ * Users acknowledge that this software is supplied without any warranty or support.
+ * The Broad Institute is not responsible for its use, misuse, or
+ * functionality.
+ */
+
+/**
+ * Determines what data sources are mandated by a given walker.
+ */
+ at Documented
+ at Inherited
+ at Retention(RetentionPolicy.RUNTIME)
+ at Target(ElementType.TYPE)
+public @interface Requires {
+    DataSource[] value();
+    RMD[] referenceMetaData() default {};
+}
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/walkers/RodWalker.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/walkers/RodWalker.java
new file mode 100644
index 0000000..88a1eaa
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/walkers/RodWalker.java
@@ -0,0 +1,39 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.engine.walkers;
+
+/**
+ * Created by IntelliJ IDEA.
+ * User: mdepristo
+ * Date: Feb 22, 2009
+ * Time: 2:52:28 PM
+ * To change this template use File | Settings | File Templates.
+ */
+ at By(DataSource.REFERENCE_ORDERED_DATA)
+ at Requires({DataSource.REFERENCE, DataSource.REFERENCE_ORDERED_DATA})
+ at Allows({DataSource.REFERENCE, DataSource.REFERENCE_ORDERED_DATA})
+public abstract class RodWalker<MapType, ReduceType> extends LocusWalker<MapType, ReduceType> {
+}
\ No newline at end of file
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/walkers/TreeReducible.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/walkers/TreeReducible.java
new file mode 100644
index 0000000..c170f3d
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/walkers/TreeReducible.java
@@ -0,0 +1,49 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.engine.walkers;
+
+/**
+ * Created by IntelliJ IDEA.
+ * User: mhanna
+ * Date: Apr 26, 2009
+ * Time: 5:34:11 PM
+ * To change this template use File | Settings | File Templates.
+ */
+
+/**
+ * Indicates that a class is tree reducible, aka that any two adjacent
+ * shards of the data can reduce with each other, and the composite result
+ * can be reduced with other composite results.
+ */
+public interface TreeReducible<ReduceType> {
+    /**
+     * A composite, 'reduce of reduces' function.
+     * @param lhs 'left-most' portion of data in the composite reduce.
+     * @param rhs 'right-most' portion of data in the composite reduce.
+     * @return The composite reduce type.
+     */
+    ReduceType treeReduce(ReduceType lhs, ReduceType rhs);
+}
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/walkers/Walker.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/walkers/Walker.java
new file mode 100644
index 0000000..31472fd
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/walkers/Walker.java
@@ -0,0 +1,177 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.engine.walkers;
+
+import htsjdk.samtools.SAMSequenceDictionary;
+import org.apache.log4j.Logger;
+import org.broadinstitute.gatk.engine.CommandLineGATK;
+import org.broadinstitute.gatk.engine.GenomeAnalysisEngine;
+import org.broadinstitute.gatk.engine.downsampling.DownsampleType;
+import org.broadinstitute.gatk.engine.filters.MalformedReadFilter;
+import org.broadinstitute.gatk.engine.iterators.ReadTransformer;
+import org.broadinstitute.gatk.engine.samples.Sample;
+import org.broadinstitute.gatk.engine.samples.SampleDB;
+import org.broadinstitute.gatk.utils.GenomeLoc;
+import org.broadinstitute.gatk.utils.baq.BAQ;
+import org.broadinstitute.gatk.utils.collections.Pair;
+import org.broadinstitute.gatk.utils.help.DocumentedGATKFeature;
+import org.broadinstitute.gatk.utils.recalibration.BQSRMode;
+
+import java.util.List;
+
+/**
+ * Created by IntelliJ IDEA.
+ * User: hanna
+ * Date: Mar 17, 2009
+ * Time: 1:53:31 PM
+ * To change this template use File | Settings | File Templates.
+ */
+ at ReadFilters(MalformedReadFilter.class)
+ at PartitionBy(PartitionType.NONE)
+ at Downsample(by = DownsampleType.NONE)
+ at BAQMode(QualityMode = BAQ.QualityMode.OVERWRITE_QUALS, ApplicationTime = ReadTransformer.ApplicationTime.ON_INPUT)
+ at BQSRMode(ApplicationTime = ReadTransformer.ApplicationTime.ON_INPUT)
+ at DocumentedGATKFeature(groupName = "Uncategorized", extraDocs = {CommandLineGATK.class})
+public abstract class Walker<MapType, ReduceType> {
+    final protected static Logger logger = Logger.getLogger(Walker.class);
+    private GenomeAnalysisEngine toolkit;
+
+    protected Walker() {
+    }
+
+    /**
+     * Set the toolkit, for peering into internal structures that can't
+     * otherwise be read.
+     * @param toolkit The genome analysis toolkit.
+     */
+    public void setToolkit(GenomeAnalysisEngine toolkit) {
+        this.toolkit = toolkit;
+    }
+
+    /**
+     * Retrieve the toolkit, for peering into internal structures that can't
+     * otherwise be read.  Use sparingly, and discuss uses with software engineering
+     * team.
+     * @return The genome analysis toolkit.
+     */
+    protected GenomeAnalysisEngine getToolkit() {
+        return toolkit;
+    }
+
+    /**
+     * Gets the master sequence dictionary for this walker
+     * @link GenomeAnalysisEngine.getMasterSequenceDictionary
+     * @return
+     */
+    protected SAMSequenceDictionary getMasterSequenceDictionary() {
+        return getToolkit().getMasterSequenceDictionary();
+    }
+
+    public SampleDB getSampleDB() {
+        return getToolkit().getSampleDB();
+    }
+
+    protected Sample getSample(final String id) {
+        return getToolkit().getSampleDB().getSample(id);
+    }
+
+    /**
+     * (conceptual static) method that states whether you want to see reads piling up at a locus
+     * that contain a deletion at the locus.
+     *
+     * ref:   ATCTGA
+     * read1: ATCTGA
+     * read2: AT--GA
+     *
+     * Normally, the locus iterator only returns a list of read1 at this locus at position 3, but
+     * if this function returns true, then the system will return (read1, read2) with offsets
+     * of (3, -1).  The -1 offset indicates a deletion in the read.
+     *
+     * @return false if you don't want to see deletions, or true if you do
+     */
+    public boolean includeReadsWithDeletionAtLoci() { 
+        return false;
+    }
+
+    public void initialize() { }
+
+    /**
+     * A function for overloading in subclasses providing a mechanism to abort early from a walker.
+     *
+     * If this ever returns true, then the Traversal engine will stop executing map calls
+     * and start the process of shutting down the walker in an orderly fashion.
+     * @return
+     */
+    public boolean isDone() {
+        return false;
+    }
+
+    /**
+     * Provide an initial value for reduce computations.
+     * @return Initial value of reduce.
+     */
+    public abstract ReduceType reduceInit();
+
+    /**
+     * Reduces a single map with the accumulator provided as the ReduceType.
+     * @param value result of the map.
+     * @param sum accumulator for the reduce.
+     * @return accumulator with result of the map taken into account.
+     */
+    public abstract ReduceType reduce(MapType value, ReduceType sum);    
+
+    public void onTraversalDone(ReduceType result) {
+        logger.info("[REDUCE RESULT] Traversal result is: " + result);
+    }
+
+    /**
+     * General interval reduce routine called after all of the traversals are done
+     * @param results interval reduce results
+     */
+    public void onTraversalDone(List<Pair<GenomeLoc, ReduceType>> results) {
+        for ( Pair<GenomeLoc, ReduceType> result : results ) {
+            logger.info(String.format("[INTERVAL REDUCE RESULT] at %s ", result.getFirst()));
+            this.onTraversalDone(result.getSecond());
+        }
+    }
+
+    /**
+     * Return true if your walker wants to reduce each interval separately.  Default is false.
+     *
+     * If you set this flag, several things will happen.
+     *
+     * The system will invoke reduceInit() once for each interval being processed, starting a fresh reduce
+     * Reduce will accumulate normally at each map unit in the interval
+     * However, onTraversalDone(reduce) will be called after each interval is processed.
+     * The system will call onTraversalDone( GenomeLoc -> reduce ), after all reductions are done,
+     *   which is overloaded here to call onTraversalDone(reduce) for each location
+     *
+     * @return true if your walker wants to reduce each interval separately.
+     */
+    public boolean isReduceByInterval() {
+        return false;
+    }
+}
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/walkers/WalkerName.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/walkers/WalkerName.java
new file mode 100644
index 0000000..9e02bf1
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/walkers/WalkerName.java
@@ -0,0 +1,42 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.engine.walkers;
+
+import java.lang.annotation.*;
+
+/**
+ * Created by IntelliJ IDEA.
+ * User: hanna
+ * Date: Mar 26, 2009
+ * Time: 3:00:16 PM
+ * To change this template use File | Settings | File Templates.
+ */
+ at Documented
+ at Retention(RetentionPolicy.RUNTIME)
+ at Target(ElementType.TYPE)
+public @interface WalkerName {
+    public String value() default "";
+}
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/walkers/Window.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/walkers/Window.java
new file mode 100644
index 0000000..66205b9
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/walkers/Window.java
@@ -0,0 +1,57 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.engine.walkers;
+
+import java.lang.annotation.Documented;
+import java.lang.annotation.Inherited;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+
+/**
+ * Describes the size of the window into the genome.  Has differing semantics based on
+ * the data this annotation is used to describe.
+ *
+ * @author mhanna
+ * @version 0.1
+ */
+ at Documented
+ at Inherited
+ at Retention(RetentionPolicy.RUNTIME)
+public @interface Window {
+    /**
+     * Controls where the window should start and stop relative to
+     * the locus currently being processed.
+     * @return start point; default is 0, indicating 'supply only the reference base at the current locus'.
+     */
+    public int start() default 0;
+
+    /**
+     * Controls where the window should start and stop relative to
+     * the locus currently being processed.
+     * @return stop point; default is 0, indicating 'supply only the reference base at the current locus'.
+     */
+    public int stop() default 0;
+}
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/walkers/diffengine/BAMDiffableReader.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/walkers/diffengine/BAMDiffableReader.java
new file mode 100644
index 0000000..2c8cc7a
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/walkers/diffengine/BAMDiffableReader.java
@@ -0,0 +1,119 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.engine.walkers.diffengine;
+
+import htsjdk.samtools.SAMFileReader;
+import htsjdk.samtools.SAMRecord;
+import htsjdk.samtools.SAMRecordIterator;
+import htsjdk.samtools.ValidationStringency;
+import htsjdk.samtools.util.BlockCompressedInputStream;
+
+import java.io.*;
+import java.util.Arrays;
+
+
+/**
+ * Created by IntelliJ IDEA.
+ * User: depristo
+ * Date: 7/4/11
+ * Time: 1:09 PM
+ *
+ * Class implementing diffnode reader for VCF
+ */
+public class BAMDiffableReader implements DiffableReader {
+    @Override
+    public String getName() { return "BAM"; }
+
+    @Override
+    public DiffElement readFromFile(File file, int maxElementsToRead) {
+        final SAMFileReader reader = new SAMFileReader(file, null); // null because we don't want it to look for the index
+        reader.setValidationStringency(ValidationStringency.SILENT);
+
+        DiffNode root = DiffNode.rooted(file.getName());
+        SAMRecordIterator iterator = reader.iterator();
+
+        int count = 0;
+        while ( iterator.hasNext() ) {
+            final SAMRecord record = iterator.next();
+
+            // name is the read name + first of pair
+            String name = record.getReadName().replace('.', '_');
+            if ( record.getReadPairedFlag() ) {
+                name += record.getFirstOfPairFlag() ? "_1" : "_2";
+            }
+
+            DiffNode readRoot = DiffNode.empty(name, root);
+
+            // add fields
+            readRoot.add("NAME", record.getReadName());
+            readRoot.add("FLAGS", record.getFlags());
+            readRoot.add("RNAME", record.getReferenceName());
+            readRoot.add("POS", record.getAlignmentStart());
+            readRoot.add("MAPQ", record.getMappingQuality());
+            readRoot.add("CIGAR", record.getCigarString());
+            readRoot.add("RNEXT", record.getMateReferenceName());
+            readRoot.add("PNEXT", record.getMateAlignmentStart());
+            readRoot.add("TLEN", record.getInferredInsertSize());
+            readRoot.add("SEQ", record.getReadString());
+            readRoot.add("QUAL", record.getBaseQualityString());
+
+            for ( SAMRecord.SAMTagAndValue xt : record.getAttributes() ) {
+                readRoot.add(xt.tag, xt.value);
+            }
+
+            // add record to root
+            if ( ! root.hasElement(name) )
+                // protect ourselves from malformed files
+                root.add(readRoot);
+            count += readRoot.size();
+            if ( count > maxElementsToRead && maxElementsToRead != -1)
+                break;
+        }
+
+        reader.close();
+
+        return root.getBinding();
+    }
+
+    @Override
+    public boolean canRead(File file) {
+        final byte[] BAM_MAGIC = "BAM\1".getBytes();
+        final byte[] buffer = new byte[BAM_MAGIC.length];
+        try {
+            InputStream fstream = new BufferedInputStream(new FileInputStream(file));
+            if ( !BlockCompressedInputStream.isValidFile(fstream) )
+                return false;
+            final BlockCompressedInputStream BCIS = new BlockCompressedInputStream(fstream);
+            BCIS.read(buffer, 0, BAM_MAGIC.length);
+            BCIS.close();
+            return Arrays.equals(buffer, BAM_MAGIC);
+        } catch ( IOException e ) {
+            return false;
+        } catch ( htsjdk.samtools.FileTruncatedException e ) {
+            return false;
+        }
+    }
+}
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/walkers/diffengine/DiffElement.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/walkers/diffengine/DiffElement.java
new file mode 100644
index 0000000..ebed914
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/walkers/diffengine/DiffElement.java
@@ -0,0 +1,125 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.engine.walkers.diffengine;
+
+import com.google.java.contract.Ensures;
+import com.google.java.contract.Invariant;
+import com.google.java.contract.Requires;
+import org.broadinstitute.gatk.utils.Utils;
+import org.broadinstitute.gatk.utils.exceptions.ReviewedGATKException;
+
+/**
+ * Created by IntelliJ IDEA.
+ * User: depristo
+ * Date: 7/4/11
+ * Time: 12:55 PM
+ *
+ * An interface that must be implemented to allow us to calculate differences
+ * between structured objects
+ */
+ at Invariant({
+        "name != null",
+        "value != null",
+        "parent != null || name.equals(\"ROOT\")",
+        "value == null || value.getBinding() == this"})
+public class DiffElement {
+    public final static DiffElement ROOT = new DiffElement();
+
+    final private String name;
+    final private DiffElement parent;
+    final private DiffValue value;
+
+    /**
+     * For ROOT only
+     */
+    private DiffElement() {
+        this.name = "ROOT";
+        this.parent = null;
+        this.value = new DiffValue(this, "ROOT");
+    }
+
+    @Requires({"name != null", "parent != null", "value != null"})
+    public DiffElement(String name, DiffElement parent, DiffValue value) {
+        if ( name.equals("ROOT") ) throw new IllegalArgumentException("Cannot use reserved name ROOT");
+        this.name = name;
+        this.parent = parent;
+        this.value = value;
+        this.value.setBinding(this);
+    }
+
+    @Ensures({"result != null"})
+    public String getName() {
+        return name;
+    }
+
+    public DiffElement getParent() {
+        return parent;
+    }
+
+    @Ensures({"result != null"})
+    public DiffValue getValue() {
+        return value;
+    }
+
+    public boolean isRoot() { return this == ROOT; }
+
+    @Ensures({"result != null"})
+    @Override
+    public String toString() {
+        return getName() + "=" + getValue().toString();
+    }
+
+    public String toString(int offset) {
+        return (offset > 0 ? Utils.dupString(' ', offset) : 0) + getName() + "=" + getValue().toString(offset);
+    }
+
+    @Ensures({"result != null"})
+    public final String fullyQualifiedName() {
+        if ( isRoot() )
+            return "";
+        else if ( parent.isRoot() )
+            return name;
+        else
+            return parent.fullyQualifiedName() + "." + name;
+    }
+
+    @Ensures({"result != null"})
+    public String toOneLineString() {
+        return getName() + "=" + getValue().toOneLineString();
+    }
+
+    @Ensures({"result != null"})
+    public DiffNode getValueAsNode() {
+        if ( getValue().isCompound() )
+            return (DiffNode)getValue();
+        else
+            throw new ReviewedGATKException("Illegal request conversion of a DiffValue into a DiffNode: " + this);
+    }
+
+    public int size() {
+        return 1 + getValue().size();
+    }
+}
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/walkers/diffengine/DiffEngine.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/walkers/diffengine/DiffEngine.java
new file mode 100644
index 0000000..d10cfea
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/walkers/diffengine/DiffEngine.java
@@ -0,0 +1,437 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.engine.walkers.diffengine;
+
+import org.apache.log4j.Logger;
+import org.broadinstitute.gatk.engine.report.GATKReport;
+import org.broadinstitute.gatk.engine.report.GATKReportTable;
+import org.broadinstitute.gatk.utils.Utils;
+import org.broadinstitute.gatk.utils.classloader.PluginManager;
+import org.broadinstitute.gatk.utils.exceptions.ReviewedGATKException;
+import org.broadinstitute.gatk.utils.exceptions.UserException;
+
+import java.io.File;
+import java.io.PrintStream;
+import java.util.*;
+
+/**
+ * Created by IntelliJ IDEA.
+ * User: depristo
+ * Date: 7/4/11
+ * Time: 12:51 PM
+ * A generic engine for comparing tree-structured objects
+ *
+ */
+public class DiffEngine {
+    final protected static Logger logger = Logger.getLogger(DiffEngine.class);
+
+    private final Map<String, DiffableReader> readers = new HashMap<String, DiffableReader>();
+
+    public DiffEngine() {
+        loadDiffableReaders();
+    }
+
+    // --------------------------------------------------------------------------------
+    //
+    // difference calculation
+    //
+    // --------------------------------------------------------------------------------
+
+    public List<Difference> diff(DiffElement master, DiffElement test) {
+        DiffValue masterValue = master.getValue();
+        DiffValue testValue = test.getValue();
+
+        if ( masterValue.isCompound() && masterValue.isCompound() ) {
+            return diff(master.getValueAsNode(), test.getValueAsNode());
+        } else if ( masterValue.isAtomic() && testValue.isAtomic() ) {
+            return diff(masterValue, testValue);
+        } else {
+            // structural difference in types.  one is node, other is leaf
+            return Arrays.asList(new Difference(master, test));
+        }
+    }
+
+    public List<Difference> diff(DiffNode master, DiffNode test) {
+        Set<String> allNames = new HashSet<String>(master.getElementNames());
+        allNames.addAll(test.getElementNames());
+        List<Difference> diffs = new ArrayList<Difference>();
+
+        for ( String name : allNames ) {
+            DiffElement masterElt = master.getElement(name);
+            DiffElement testElt = test.getElement(name);
+            if ( masterElt == null && testElt == null ) {
+                throw new ReviewedGATKException("BUG: unexpectedly got two null elements for field: " + name);
+            } else if ( masterElt == null || testElt == null ) { // if either is null, we are missing a value
+                // todo -- should one of these be a special MISSING item?
+                diffs.add(new Difference(masterElt, testElt));
+            } else {
+                diffs.addAll(diff(masterElt, testElt));
+            }
+        }
+
+        return diffs;
+    }
+
+    public List<Difference> diff(DiffValue master, DiffValue test) {
+        if ( master.getValue().equals(test.getValue()) ) {
+            return Collections.emptyList();
+        } else {
+            return Arrays.asList(new Difference(master.getBinding(), test.getBinding()));
+        }
+    }
+
+    // --------------------------------------------------------------------------------
+    //
+    // Summarizing differences
+    //
+    // --------------------------------------------------------------------------------
+
+    /**
+     * Emits a summary of the diffs to out.  Suppose you have the following three differences:
+     *
+     *   A.X.Z:1!=2
+     *   A.Y.Z:3!=4
+     *   B.X.Z:5!=6
+     *
+     * The above is the itemized list of the differences.  The summary looks for common differences
+     * in the name hierarchy, counts those shared elements, and emits the differences that occur
+     * in order of decreasing counts.
+     *
+     * So, in the above example, what are the shared elements?
+     *
+     * A.X.Z and B.X.Z share X.Z, so there's a *.X.Z with count 2
+     * A.X.Z, A.Y.Z, and B.X.Z all share *.*.Z, with count 3
+     * Each of A.X.Z, A.Y.Z, and B.X.Z are individually unique, with count 1
+     *
+     * So we would emit the following summary:
+     *
+     * *.*.Z: 3
+     * *.X.Z: 2
+     * A.X.Z: 1 [specific difference: 1!=2]
+     * A.Y.Z: 1 [specific difference: 3!=4]
+     * B.X.Z: 1 [specific difference: 5!=6]
+     *
+     * The algorithm to accomplish this calculation is relatively simple. Start with all of the
+     * concrete differences.  For each pair of differences A1.A2....AN and B1.B2....BN:
+     *
+     * find the longest common subsequence Si.Si+1...SN where Ai = Bi = Si
+     * If i == 0, then there's no shared substructure
+     * If i > 0, then generate the summarized value X = *.*...Si.Si+1...SN
+     * if X is a known summary, increment it's count, otherwise set its count to 1
+     *
+     * Not that only pairs of the same length are considered as potentially equivalent
+     *
+     * @param params determines how we display the items
+     * @param diffs the list of differences to summarize
+     */
+    public void reportSummarizedDifferences(List<Difference> diffs, SummaryReportParams params ) {
+        printSummaryReport(summarizedDifferencesOfPaths(diffs, params.doPairwise, params.maxRawDiffsToSummarize), params );
+    }
+
+    final protected static String[] diffNameToPath(String diffName) {
+        return diffName.split("\\.");
+    }
+
+    protected List<Difference> summarizedDifferencesOfPathsFromString(List<String> singletonDiffs) {
+        List<Difference> diffs = new ArrayList<Difference>();
+
+        for ( String diff : singletonDiffs ) {
+            diffs.add(new Difference(diff));
+        }
+
+        return summarizedDifferencesOfPaths(diffs, true, -1);
+    }
+
+    /**
+     * Computes a minimum set of potential differences between all singleton differences
+     * in singletonDiffs.  Employs an expensive pairwise O(n^2) algorithm.
+     *
+     * @param singletonDiffs
+     * @param maxRawDiffsToSummarize
+     * @return
+     */
+    private Map<String, Difference> initialPairwiseSummaries(final List<? extends Difference> singletonDiffs,
+                                                             final int maxRawDiffsToSummarize) {
+        Map<String, Difference> summaries = new HashMap<String, Difference>();
+
+        // create the initial set of differences
+        for ( int i = 0; i < singletonDiffs.size(); i++ ) {
+            for ( int j = 0; j <= i; j++ ) {
+                Difference diffPath1 = singletonDiffs.get(i);
+                Difference diffPath2 = singletonDiffs.get(j);
+                if ( diffPath1.length() == diffPath2.length() ) {
+                    int lcp = longestCommonPostfix(diffPath1.getParts(), diffPath2.getParts());
+                    String path = diffPath2.getPath();
+                    if ( lcp != 0 && lcp != diffPath1.length() )
+                        path = summarizedPath(diffPath2.getParts(), lcp);
+                    Difference sumDiff = new Difference(path, diffPath2.getMaster(), diffPath2.getTest());
+                    sumDiff.setCount(0);
+                    addSummaryIfMissing(summaries, sumDiff);
+
+                    if ( maxRawDiffsToSummarize != -1 && summaries.size() > maxRawDiffsToSummarize)
+                        return summaries;
+                }
+            }
+        }
+
+        return summaries;
+    }
+
+    /**
+     * Computes the possible leaf differences among the singleton diffs.
+     *
+     * The leaf differences are all of the form *.*...*.X where all internal
+     * differences are wildcards and the only summarized difference considered
+     * interesting to compute is
+     *
+     * @param singletonDiffs
+     * @param maxRawDiffsToSummarize
+     * @return
+     */
+    private Map<String, Difference> initialLeafSummaries(final List<? extends Difference> singletonDiffs,
+                                                         final int maxRawDiffsToSummarize) {
+        Map<String, Difference> summaries = new HashMap<String, Difference>();
+
+        // create the initial set of differences
+        for ( final Difference d : singletonDiffs ) {
+            final String path = summarizedPath(d.getParts(), 1);
+            Difference sumDiff = new Difference(path, d.getMaster(), d.getTest());
+            sumDiff.setCount(0);
+            addSummaryIfMissing(summaries, sumDiff);
+
+            if ( maxRawDiffsToSummarize != -1 && summaries.size() > maxRawDiffsToSummarize)
+                return summaries;
+        }
+
+        return summaries;
+    }
+
+    protected List<Difference> summarizedDifferencesOfPaths(final List<? extends Difference> singletonDiffs,
+                                                            final boolean doPairwise,
+                                                            final int maxRawDiffsToSummarize) {
+        final Map<String, Difference> summaries = doPairwise
+                ? initialPairwiseSummaries(singletonDiffs, maxRawDiffsToSummarize)
+                : initialLeafSummaries(singletonDiffs, maxRawDiffsToSummarize);
+
+        // count differences
+        for ( Difference diffPath : singletonDiffs ) {
+            for ( Difference sumDiff : summaries.values() ) {
+                if ( sumDiff.matches(diffPath.getParts()) )
+                    sumDiff.incCount();
+            }
+        }
+
+        List<Difference> sortedSummaries = new ArrayList<Difference>(summaries.values());
+        Collections.sort(sortedSummaries);
+        return sortedSummaries;
+    }
+
+    protected void addSummaryIfMissing(Map<String, Difference> summaries, Difference diff) {
+        if ( ! summaries.containsKey(diff.getPath()) ) {
+            summaries.put(diff.getPath(), diff);
+        }
+    }
+
+    protected void printSummaryReport(List<Difference> sortedSummaries, SummaryReportParams params ) {
+        List<Difference> toShow = new ArrayList<Difference>();
+        int count = 0, count1 = 0;
+        for ( Difference diff : sortedSummaries ) {
+            if ( diff.getCount() < params.minSumDiffToShow )
+                // in order, so break as soon as the count is too low
+                break;
+
+            if ( params.maxItemsToDisplay != 0 && count++ > params.maxItemsToDisplay )
+                break;
+
+            if ( diff.getCount() == 1 ) {
+                count1++;
+                if ( params.maxCountOneItems != 0 && count1 > params.maxCountOneItems )
+                    break;
+            }
+
+            toShow.add(diff);
+        }
+
+        // if we want it in descending order, reverse the list
+        if ( ! params.descending ) {
+            Collections.reverse(toShow);
+        }
+
+        // now that we have a specific list of values we want to show, display them
+        GATKReport report = new GATKReport();
+        final String tableName = "differences";
+        report.addTable(tableName, "Summarized differences between the master and test files. See http://www.broadinstitute.org/gatk/guide/article?id=1299 for more information", 3);
+        final GATKReportTable table = report.getTable(tableName);
+        table.addColumn("Difference");
+        table.addColumn("NumberOfOccurrences");
+        table.addColumn("ExampleDifference");
+        for ( final Difference diff : toShow ) {
+            final String key = diff.getPath();
+            table.addRowID(key, true);
+            table.set(key, "NumberOfOccurrences", diff.getCount());
+            table.set(key, "ExampleDifference", diff.valueDiffString());
+        }
+        GATKReport output = new GATKReport(table);
+        output.print(params.out);
+    }
+
+    protected static int longestCommonPostfix(String[] diffPath1, String[] diffPath2) {
+        int i = 0;
+        for ( ; i < diffPath1.length; i++ ) {
+            int j = diffPath1.length - i - 1;
+            if ( ! diffPath1[j].equals(diffPath2[j]) )
+                break;
+        }
+        return i;
+    }
+
+    /**
+     * parts is [A B C D]
+     * commonPostfixLength: how many parts are shared at the end, suppose its 2
+     * We want to create a string *.*.C.D
+     *
+     * @param parts the separated path values [above without .]
+     * @param commonPostfixLength
+     * @return
+     */
+    protected static String summarizedPath(String[] parts, int commonPostfixLength) {
+        int stop = parts.length - commonPostfixLength;
+        if ( stop > 0 ) parts = parts.clone();
+        for ( int i = 0; i < stop; i++ ) {
+            parts[i] = "*";
+        }
+        return Utils.join(".", parts);
+    }
+
+    // --------------------------------------------------------------------------------
+    //
+    // plugin manager
+    //
+    // --------------------------------------------------------------------------------
+
+    public void loadDiffableReaders() {
+        List<Class<? extends DiffableReader>> drClasses = new PluginManager<DiffableReader>( DiffableReader.class ).getPlugins();
+
+        logger.info("Loading diffable modules:");
+        for (Class<? extends DiffableReader> drClass : drClasses ) {
+            logger.info("\t" + drClass.getSimpleName());
+
+            try {
+                DiffableReader dr = drClass.newInstance();
+                readers.put(dr.getName(), dr);
+            } catch (InstantiationException e) {
+                throw new ReviewedGATKException("Unable to instantiate module '" + drClass.getSimpleName() + "'");
+            } catch (IllegalAccessException e) {
+                throw new ReviewedGATKException("Illegal access error when trying to instantiate '" + drClass.getSimpleName() + "'");
+            }
+        }
+    }
+
+    protected Map<String, DiffableReader> getReaders() {
+        return readers;
+    }
+
+    protected DiffableReader getReader(String name) {
+        return readers.get(name);
+    }
+
+    /**
+     * Returns a reader appropriate for this file, or null if no such reader exists
+     * @param file
+     * @return
+     */
+    public DiffableReader findReaderForFile(File file) {
+        for ( DiffableReader reader : readers.values() )
+            if (reader.canRead(file) )
+                return reader;
+
+        return null;
+    }
+
+    /**
+     * Returns true if reader appropriate for this file, or false if no such reader exists
+     * @param file
+     * @return
+     */
+    public boolean canRead(File file) {
+        return findReaderForFile(file) != null;
+    }
+
+
+    public DiffElement createDiffableFromFile(File file) {
+        return createDiffableFromFile(file, -1);
+    }
+
+    public DiffElement createDiffableFromFile(File file, int maxElementsToRead) {
+        DiffableReader reader = findReaderForFile(file);
+        if ( reader == null )
+            throw new UserException("Unsupported file type: " + file);
+        else
+            return reader.readFromFile(file, maxElementsToRead);
+    }
+
+    public static boolean simpleDiffFiles(File masterFile, File testFile, int maxElementsToRead, DiffEngine.SummaryReportParams params) {
+        DiffEngine diffEngine = new DiffEngine();
+
+        if ( diffEngine.canRead(masterFile) && diffEngine.canRead(testFile) ) {
+            DiffElement master = diffEngine.createDiffableFromFile(masterFile, maxElementsToRead);
+            DiffElement test = diffEngine.createDiffableFromFile(testFile, maxElementsToRead);
+            List<Difference> diffs = diffEngine.diff(master, test);
+            diffEngine.reportSummarizedDifferences(diffs, params);
+            return true;
+        } else {
+            return false;
+        }
+    }
+
+    public static class SummaryReportParams {
+        final PrintStream out;
+        final int maxItemsToDisplay;
+        final int maxCountOneItems;
+        final int minSumDiffToShow;
+        final int maxRawDiffsToSummarize;
+        final boolean doPairwise;
+        boolean descending = true;
+
+        public SummaryReportParams(PrintStream out,
+                                   int maxItemsToDisplay,
+                                   int maxCountOneItems,
+                                   int minSumDiffToShow,
+                                   int maxRawDiffsToSummarize,
+                                   final boolean doPairwise) {
+            this.out = out;
+            this.maxItemsToDisplay = maxItemsToDisplay;
+            this.maxCountOneItems = maxCountOneItems;
+            this.minSumDiffToShow = minSumDiffToShow;
+            this.maxRawDiffsToSummarize = maxRawDiffsToSummarize;
+            this.doPairwise = doPairwise;
+        }
+
+        public void setDescending(boolean descending) {
+            this.descending = descending;
+        }
+    }
+}
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/walkers/diffengine/DiffNode.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/walkers/diffengine/DiffNode.java
new file mode 100644
index 0000000..dde9ca5
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/walkers/diffengine/DiffNode.java
@@ -0,0 +1,249 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.engine.walkers.diffengine;
+
+import com.google.java.contract.Requires;
+import org.broadinstitute.gatk.utils.Utils;
+import org.broadinstitute.gatk.utils.exceptions.ReviewedGATKException;
+
+import java.util.*;
+
+/**
+ * Created by IntelliJ IDEA.
+ * User: depristo
+ * Date: 7/4/11
+ * Time: 12:55 PM
+ *
+ * An interface that must be implemented to allow us to calculate differences
+ * between structured objects
+ */
+public class DiffNode extends DiffValue {
+    private Map<String, DiffElement> getElementMap() {
+        return (Map<String, DiffElement>)super.getValue();
+    }
+    private static Map<String, DiffElement> emptyElements() { return new HashMap<String, DiffElement>(); }
+
+    private DiffNode(Map<String, DiffElement> elements) {
+        super(elements);
+    }
+
+    private DiffNode(DiffElement binding, Map<String, DiffElement> elements) {
+        super(binding, elements);
+    }
+
+    // ---------------------------------------------------------------------------
+    //
+    // constructors
+    //
+    // ---------------------------------------------------------------------------
+
+    public static DiffNode rooted(String name) {
+        return empty(name, DiffElement.ROOT);
+    }
+
+    public static DiffNode empty(String name, DiffElement parent) {
+        DiffNode df = new DiffNode(emptyElements());
+        DiffElement elt = new DiffElement(name, parent, df);
+        df.setBinding(elt);
+        return df;
+    }
+
+    public static DiffNode empty(String name, DiffValue parent) {
+        return empty(name, parent.getBinding());
+    }
+
+    // ---------------------------------------------------------------------------
+    //
+    // accessors
+    //
+    // ---------------------------------------------------------------------------
+
+    @Override
+    public boolean isAtomic() { return false; }
+
+    public Collection<String> getElementNames() {
+        return getElementMap().keySet();
+    }
+
+    public Collection<DiffElement> getElements() {
+        return getElementMap().values();
+    }
+
+    private Collection<DiffElement> getElements(boolean atomicOnly) {
+        List<DiffElement> elts = new ArrayList<DiffElement>();
+        for ( DiffElement elt : getElements() )
+            if ( (atomicOnly && elt.getValue().isAtomic()) || (! atomicOnly && elt.getValue().isCompound()))
+                elts.add(elt);
+        return elts;
+    }
+
+    public Collection<DiffElement> getAtomicElements() {
+        return getElements(true);
+    }
+
+    public Collection<DiffElement> getCompoundElements() {
+        return getElements(false);
+    }
+
+    /**
+     * Returns the element bound to name, or null if no such binding exists
+     * @param name
+     * @return
+     */
+    public DiffElement getElement(String name) {
+        return getElementMap().get(name);
+    }
+
+    /**
+     * Returns true if name is bound in this node
+     * @param name
+     * @return
+     */
+    public boolean hasElement(String name) {
+        return getElement(name) != null;
+    }
+
+    // ---------------------------------------------------------------------------
+    //
+    // add
+    //
+    // ---------------------------------------------------------------------------
+
+    @Requires("elt != null")
+    public void add(DiffElement elt) {
+        if ( getElementMap().containsKey(elt.getName()) )
+            throw new IllegalArgumentException("Attempting to rebind already existing binding: " + elt + " node=" + this);
+        getElementMap().put(elt.getName(), elt);
+    }
+
+    @Requires("elt != null")
+    public void add(DiffValue elt) {
+        add(elt.getBinding());
+    }
+
+    @Requires("elts != null")
+    public void add(Collection<DiffElement> elts) {
+        for ( DiffElement e : elts )
+            add(e);
+    }
+
+    public void add(String name, Object value) {
+        add(new DiffElement(name, this.getBinding(), new DiffValue(value)));
+    }
+
+    public int size() {
+        int count = 0;
+        for ( DiffElement value : getElements() )
+            count += value.size();
+        return count;
+    }
+
+    // ---------------------------------------------------------------------------
+    //
+    // toString
+    //
+    // ---------------------------------------------------------------------------
+
+    @Override
+    public String toString() {
+        return toString(0);
+    }
+
+    @Override
+    public String toString(int offset) {
+        String off = offset > 0 ? Utils.dupString(' ', offset) : "";
+        StringBuilder b = new StringBuilder();
+
+        b.append("(").append("\n");
+        Collection<DiffElement> atomicElts = getAtomicElements();
+        for ( DiffElement elt : atomicElts ) {
+            b.append(elt.toString(offset + 2)).append('\n');
+        }
+
+        for ( DiffElement elt : getCompoundElements() ) {
+            b.append(elt.toString(offset + 4)).append('\n');
+        }
+        b.append(off).append(")").append("\n");
+
+        return b.toString();
+    }
+
+    @Override
+    public String toOneLineString() {
+        StringBuilder b = new StringBuilder();
+
+        b.append('(');
+        List<String> parts = new ArrayList<String>();
+        for ( DiffElement elt : getElements() )
+            parts.add(elt.toOneLineString());
+        b.append(Utils.join(" ", parts));
+        b.append(')');
+
+        return b.toString();
+    }
+
+    // --------------------------------------------------------------------------------
+    //
+    // fromString and toOneLineString
+    //
+    // --------------------------------------------------------------------------------
+
+    public static DiffElement fromString(String tree) {
+        return fromString(tree, DiffElement.ROOT);
+    }
+
+    /**
+     * Doesn't support full tree structure parsing
+     * @param tree
+     * @param parent
+     * @return
+     */
+    private static DiffElement fromString(String tree, DiffElement parent) {
+        // X=(A=A B=B C=(D=D))
+        String[] parts = tree.split("=", 2);
+        if ( parts.length != 2 )
+            throw new ReviewedGATKException("Unexpected tree structure: " + tree);
+        String name = parts[0];
+        String value = parts[1];
+
+        if ( value.length() == 0 )
+            throw new ReviewedGATKException("Illegal tree structure: " + value + " at " + tree);
+
+        if ( value.charAt(0) == '(' ) {
+            if ( ! value.endsWith(")") )
+                throw new ReviewedGATKException("Illegal tree structure.  Missing ): " + value + " at " + tree);
+            String subtree = value.substring(1, value.length()-1);
+            DiffNode rec = DiffNode.empty(name, parent);
+            String[] subParts = subtree.split(" ");
+            for ( String subPart : subParts ) {
+                rec.add(fromString(subPart, rec.getBinding()));
+            }
+            return rec.getBinding();
+        } else {
+            return new DiffValue(name, parent, value).getBinding();
+        }
+    }
+}
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/walkers/diffengine/DiffObjects.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/walkers/diffengine/DiffObjects.java
new file mode 100644
index 0000000..c622e24
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/walkers/diffengine/DiffObjects.java
@@ -0,0 +1,276 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.engine.walkers.diffengine;
+
+import org.broadinstitute.gatk.utils.commandline.Argument;
+import org.broadinstitute.gatk.utils.commandline.Input;
+import org.broadinstitute.gatk.utils.commandline.Output;
+import org.broadinstitute.gatk.engine.CommandLineGATK;
+import org.broadinstitute.gatk.engine.contexts.AlignmentContext;
+import org.broadinstitute.gatk.engine.contexts.ReferenceContext;
+import org.broadinstitute.gatk.engine.refdata.RefMetaDataTracker;
+import org.broadinstitute.gatk.engine.walkers.RodWalker;
+import org.broadinstitute.gatk.utils.help.DocumentedGATKFeature;
+import org.broadinstitute.gatk.utils.help.HelpConstants;
+
+import java.io.File;
+import java.io.PrintStream;
+import java.util.List;
+
+/**
+ * A generic engine for comparing tree-structured objects
+ *
+ * <p>
+ *      Compares two record-oriented files, itemizing specific difference between equivalent
+ *      records in the two files.  Reports both itemized and summarized differences.
+ * </p>
+ *
+ * <h3>What are the summarized differences and the DiffObjectsWalker?</h3>
+ *
+ * <p>
+ *     The GATK contains a summarizing difference engine that compares hierarchical data structures to emit:
+ *      <ul>
+ *          <li>A list of specific differences between the two data structures.  This is similar to saying the value in field A in record 1 in file F differences from the value in field A in record 1 in file G.
+ *          <li>A summarized list of differences ordered by frequency of the difference.  This output is similar to saying field A in 50 records in files F and G differed.
+ *      </ul>
+ * </p>
+ *
+ * <p>
+ *      The GATK contains a private walker DiffObjects that allows you access to the DiffEngine capabilities on the command line.  Simply provide the walker with the master and test files and it will emit summarized differences for you.
+ * </p>
+ *
+ * <h3>Why?</h3>
+ *
+ * <p>
+ *      The reason for this system is that it allows you to compare two structured files -- such as BAMs and VCFs -- for common differences among them.  This is primarily useful in regression testing or optimization, where you want to ensure that the differences are those that you expect and not any others.
+ * </p>
+ *
+ * <h3>Input</h3>
+ * <p>
+ *      The DiffObjectsWalker works with BAM or VCF files.
+ * </p>
+ *
+ * <h3>Output</h3>
+ * <p>
+ *      The DiffEngine system compares to two hierarchical data structures for specific differences in the values of named
+ *      nodes.  Suppose I have two trees:
+ * <pre>
+ *     Tree1=(A=1 B=(C=2 D=3))
+ *     Tree2=(A=1 B=(C=3 D=3 E=4))
+ *     Tree3=(A=1 B=(C=4 D=3 E=4))
+ * </pre>
+ * <p>
+ *     where every node in the tree is named, or is a raw value (here all leaf values are integers).  The DiffEngine
+ *      traverses these data structures by name, identifies equivalent nodes by fully qualified names
+ *      (Tree1.A is distinct from Tree2.A, and determines where their values are equal (Tree1.A=1, Tree2.A=1, so they are).
+ *      These itemized differences are listed as:
+ * <pre>
+ *     Tree1.B.C=2 != Tree2.B.C=3
+ *     Tree1.B.C=2 != Tree3.B.C=4
+ *     Tree2.B.C=3 != Tree3.B.C=4
+ *     Tree1.B.E=MISSING != Tree2.B.E=4
+ * </pre>
+ *
+ * <p>
+ *      This conceptually very similar to the output of the unix command line tool diff.  What's nice about DiffEngine though
+ *      is that it computes similarity among the itemized differences and displays the count of differences names
+ *      in the system.  In the above example, the field C is not equal three times, while the missing E in Tree1 occurs
+ *      only once.  So the summary is:
+ *
+ * <pre>
+ *     *.B.C : 3
+ *     *.B.E : 1
+ * </pre>
+ *
+ * <p>
+ *      where the * operator indicates that any named field matches.  This output is sorted by counts, and provides an
+ *      immediate picture of the commonly occurring differences among the files.
+ * <p>
+ *      Below is a detailed example of two VCF fields that differ because of a bug in the AC, AF, and AN counting routines,
+ *      detected by the integrationtest integration (more below).  You can see that in the although there are many specific
+ *      instances of these differences between the two files, the summarized differences provide an immediate picture that
+ *      the AC, AF, and AN fields are the major causes of the differences.
+ * <p>
+ *
+ * <pre>
+ [testng] path                                                             count
+ [testng] *.*.*.AC                                                         6
+ [testng] *.*.*.AF                                                         6
+ [testng] *.*.*.AN                                                         6
+ [testng] 64b991fd3850f83614518f7d71f0532f.integrationtest.20:10000000.AC  1
+ [testng] 64b991fd3850f83614518f7d71f0532f.integrationtest.20:10000000.AF  1
+ [testng] 64b991fd3850f83614518f7d71f0532f.integrationtest.20:10000000.AN  1
+ [testng] 64b991fd3850f83614518f7d71f0532f.integrationtest.20:10000117.AC  1
+ [testng] 64b991fd3850f83614518f7d71f0532f.integrationtest.20:10000117.AF  1
+ [testng] 64b991fd3850f83614518f7d71f0532f.integrationtest.20:10000117.AN  1
+ [testng] 64b991fd3850f83614518f7d71f0532f.integrationtest.20:10000211.AC  1
+ [testng] 64b991fd3850f83614518f7d71f0532f.integrationtest.20:10000211.AF  1
+ [testng] 64b991fd3850f83614518f7d71f0532f.integrationtest.20:10000211.AN  1
+ [testng] 64b991fd3850f83614518f7d71f0532f.integrationtest.20:10000598.AC  1
+ </pre>
+ *
+ * <h3>Caveat</h3>
+ * <p>Because this is a walker, it requires that you pass a reference file. However the reference is not actually used, so it does not matter what you pass as reference.</p>
+ *
+ *
+ * @author Mark DePristo
+ * @since 7/4/11
+ */
+ at DocumentedGATKFeature( groupName = HelpConstants.DOCS_CAT_QC, extraDocs = {CommandLineGATK.class} )
+public class DiffObjects extends RodWalker<Integer, Integer> {
+    /**
+     * Writes out a file of the DiffEngine format:
+     *
+     *     See http://www.broadinstitute.org/gatk/guide/article?id=1299 for details.
+     */
+    @Output(doc="File to which results should be written")
+    protected PrintStream out;
+
+    /**
+     * The master file against which we will compare test.  This is one of the two required
+     * files to do the comparison.  Conceptually master is the original file contained the expected
+     * results, but this doesn't currently have an impact on the calculations, but might in the future.
+     */
+    @Input(fullName="master", shortName="m", doc="Master file: expected results", required=true)
+    File masterFile;
+
+    /**
+     * The test file against which we will compare to the master.  This is one of the two required
+     * files to do the comparison.  Conceptually test is the derived file from master, but this
+     * doesn't currently have an impact on the calculations, but might in the future.
+     */
+    @Input(fullName="test", shortName="t", doc="Test file: new results to compare to the master file", required=true)
+    File testFile;
+
+    /**
+     * The engine will read at most this number of objects from each of master and test files.  This reduces
+     * the memory requirements for DiffObjects but does limit you to comparing at most this number of objects
+     */
+    @Argument(fullName="maxObjectsToRead", shortName="motr", doc="Max. number of objects to read from the files.  -1 [default] means unlimited", required=false)
+    int MAX_OBJECTS_TO_READ = -1;
+
+    @Argument(fullName="maxRawDiffsToSummarize", shortName="maxRawDiffsToSummarize", doc="Max. number of differences to include in the summary.  -1 [default] means unlimited", required=false)
+    int maxRawDiffsToSummary = -1;
+
+    @Argument(fullName="doPairwise", shortName="doPairwise", doc="If provided, we will compute the minimum pairwise differences to summary, which can be extremely expensive", required=false)
+    boolean doPairwise = false;
+
+    /**
+     * The max number of differences to display when summarizing.  For example, if there are 10M differences, but
+     * maxDiffs is 10, then the comparison aborts after first ten summarized differences are shown.  Note that
+     * the system shows differences sorted by frequency, so these 10 would be the most common between the two files.
+     * A value of 0 means show all possible differences.
+     */
+    @Argument(fullName="maxDiffs", shortName="M", doc="Max. number of diffs to process", required=false)
+    int MAX_DIFFS = 0;
+
+    /**
+     * The maximum number of singleton (occurs exactly once between the two files) to display when writing out
+     * the summary.  Only applies if maxDiffs hasn't been exceeded.  For example, if maxDiffs is 10 and maxCount1Diffs
+     * is 2 and there are 20 diffs with count > 1, then only 10 are shown, all of which have count above 1.
+     */
+    @Argument(fullName="maxCount1Diffs", shortName="M1", doc="Max. number of diffs occuring exactly once in the file to process", required=false)
+    int MAX_COUNT1_DIFFS = 0;
+
+    /**
+     * Only differences that occur more than minCountForDiff are displayed.  For example, if minCountForDiff is 10, then
+     * a difference must occur at least 10 times between the two files to be shown.
+     */
+    @Argument(fullName="minCountForDiff", shortName="MCFD", doc="Min number of observations for a records to display", required=false)
+    int minCountForDiff = 1;
+
+    /**
+     * If provided, the system will write out the summarized, individual differences.  May lead to enormous outputs,
+     * depending on how many differences are found.  Note these are not sorted in any way, so if you have 10M
+     * common differences in the files, you will see 10M records, whereas the final summarize will just list the
+     * difference and its count of 10M.
+     */
+    @Argument(fullName="showItemizedDifferences", shortName="SID", doc="Should we enumerate all differences between the files?", required=false)
+    boolean showItemizedDifferences = false;
+
+    @Argument(fullName="iterations", doc="Number of iterations to perform, should be 1 unless you are doing memory testing", required=false)
+    int iterations = 1;
+
+    DiffEngine diffEngine;
+
+    @Override
+    public void initialize() {
+        this.diffEngine = new DiffEngine();
+    }
+
+    @Override
+    public Integer map(RefMetaDataTracker tracker, ReferenceContext ref, AlignmentContext context) {
+        return 0;
+    }
+
+    @Override
+    public Integer reduceInit() {
+        return 0;
+    }
+
+    @Override
+    public Integer reduce(Integer counter, Integer sum) {
+        return counter + sum;
+    }
+
+    @Override
+    public void onTraversalDone(Integer sum) {
+        if ( iterations > 1 ) {
+            for ( int i = 0; i < iterations; i++ ) {
+                DiffEngine.SummaryReportParams params = new DiffEngine.SummaryReportParams(out, 20, 10, 0, -1, false);
+                boolean success = DiffEngine.simpleDiffFiles(masterFile, testFile, MAX_OBJECTS_TO_READ, params);
+                logger.info("Iteration " + i + " success " + success);
+            }
+        } else {
+            //out.printf("Reading master file %s%n", masterFile);
+            DiffElement master = diffEngine.createDiffableFromFile(masterFile, MAX_OBJECTS_TO_READ);
+            logger.info(String.format("Read %d objects", master.size()));
+            //out.printf("Reading test file %s%n", testFile);
+            DiffElement test = diffEngine.createDiffableFromFile(testFile, MAX_OBJECTS_TO_READ);
+            logger.info(String.format("Read %d objects", test.size()));
+
+//        out.printf("Master diff objects%n");
+//        out.println(master.toString());
+//        out.printf("Test diff objects%n");
+//        out.println(test.toString());
+
+            List<Difference> diffs = diffEngine.diff(master, test);
+            logger.info(String.format("Done computing diff with %d differences found", diffs.size()));
+            if ( showItemizedDifferences ) {
+                out.printf("Itemized results%n");
+                for ( Difference diff : diffs )
+                    out.printf("DIFF: %s%n", diff.toString());
+            }
+
+            DiffEngine.SummaryReportParams params = new DiffEngine.SummaryReportParams(out,
+                    MAX_DIFFS, MAX_COUNT1_DIFFS, minCountForDiff,
+                    maxRawDiffsToSummary, doPairwise);
+            params.setDescending(false);
+            diffEngine.reportSummarizedDifferences(diffs, params);
+            logger.info(String.format("Done summarizing differences"));
+        }
+    }
+}
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/walkers/diffengine/DiffValue.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/walkers/diffengine/DiffValue.java
new file mode 100644
index 0000000..acec383
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/walkers/diffengine/DiffValue.java
@@ -0,0 +1,90 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.engine.walkers.diffengine;
+
+/**
+ * Created by IntelliJ IDEA.
+ * User: depristo
+ * Date: 7/4/11
+ * Time: 12:55 PM
+ *
+ * An interface that must be implemented to allow us to calculate differences
+ * between structured objects
+ */
+public class DiffValue {
+    private DiffElement binding = null;
+    final private Object value;
+
+    public DiffValue(Object value) {
+        this.value = value;
+    }
+
+    public DiffValue(DiffElement binding, Object value) {
+        this.binding = binding;
+        this.value = value;
+    }
+
+    public DiffValue(DiffValue parent, Object value) {
+        this(parent.getBinding(), value);
+    }
+
+    public DiffValue(String name, DiffElement parent, Object value) {
+        this.binding = new DiffElement(name, parent, this);
+        this.value = value;
+    }
+
+    public DiffValue(String name, DiffValue parent, Object value) {
+        this(name, parent.getBinding(), value);
+    }
+
+    public DiffElement getBinding() {
+        return binding;
+    }
+
+    protected void setBinding(DiffElement binding) {
+        this.binding = binding;
+    }
+
+    public Object getValue() {
+        return value;
+    }
+
+    public String toString() {
+        return getValue().toString();
+    }
+
+    public String toString(int offset) {
+        return toString();
+    }
+
+    public String toOneLineString() {
+        return getValue().toString();
+    }
+
+    public boolean isAtomic() { return true; }
+    public boolean isCompound() { return ! isAtomic(); }
+    public int size() { return 1; }
+}
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/walkers/diffengine/DiffableReader.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/walkers/diffengine/DiffableReader.java
new file mode 100644
index 0000000..903a073
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/walkers/diffengine/DiffableReader.java
@@ -0,0 +1,66 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.engine.walkers.diffengine;
+
+import com.google.java.contract.Ensures;
+import com.google.java.contract.Requires;
+
+import java.io.File;
+
+/**
+ * Created by IntelliJ IDEA.
+ * User: depristo
+ * Date: 7/4/11
+ * Time: 1:09 PM
+ *
+ * Interface for readers creating diffable objects from a file
+ */
+public interface DiffableReader {
+    @Ensures("result != null")
+    /**
+     * Return the name of this DiffableReader type.  For example, the VCF reader returns 'VCF' and the
+     * bam reader 'BAM'
+     */
+    public String getName();
+
+    @Ensures("result != null")
+    @Requires("file != null")
+    /**
+     * Read up to maxElementsToRead DiffElements from file, and return them.
+     */
+    public DiffElement readFromFile(File file, int maxElementsToRead);
+
+    /**
+     * Return true if the file can be read into DiffElement objects with this reader. This should
+     * be uniquely true/false for all readers, as the system will use the first reader that can read the
+     * file.  This routine should never throw an exception.  The VCF reader, for example, looks at the
+     * first line of the file for the ##format=VCF4.1 header, and the BAM reader for the BAM_MAGIC value
+     * @param file
+     * @return
+     */
+    @Requires("file != null")
+    public boolean canRead(File file);
+}
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/walkers/diffengine/Difference.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/walkers/diffengine/Difference.java
new file mode 100644
index 0000000..c8794a7
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/walkers/diffengine/Difference.java
@@ -0,0 +1,137 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.engine.walkers.diffengine;
+
+public class Difference implements Comparable<Difference> {
+    final String path; // X.Y.Z
+    final String[] parts;
+    int count = 1;
+    DiffElement master = null , test = null;
+
+    public Difference(String path) {
+        this.path = path;
+        this.parts = DiffEngine.diffNameToPath(path);
+    }
+
+    public Difference(DiffElement master, DiffElement test) {
+        this(createPath(master, test), master, test);
+    }
+
+    public Difference(String path, DiffElement master, DiffElement test) {
+        this(path);
+        this.master = master;
+        this.test = test;
+    }
+
+    public String[] getParts() {
+        return parts;
+    }
+
+    public void incCount() { count++; }
+
+    public int getCount() {
+        return count;
+    }
+
+    public void setCount(int count) {
+        this.count = count;
+    }
+
+    /**
+     * The fully qualified path object A.B.C etc
+     * @return
+     */
+    public String getPath() {
+        return path;
+    }
+
+    /**
+     * @return the length of the parts of this summary
+     */
+    public int length() {
+        return this.parts.length;
+    }
+
+    /**
+     * Returns true if the string parts matches this summary.  Matches are
+     * must be equal() everywhere where this summary isn't *.
+     * @param otherParts
+     * @return
+     */
+    public boolean matches(String[] otherParts) {
+        if ( otherParts.length != length() )
+            return false;
+
+        // TODO optimization: can start at right most non-star element
+        for ( int i = 0; i < length(); i++ ) {
+            String part = parts[i];
+            if ( ! part.equals("*") && ! part.equals(otherParts[i]) )
+                return false;
+        }
+
+        return true;
+    }
+
+    @Override
+    public String toString() {
+        return String.format("%s:%d:%s", getPath(), getCount(), valueDiffString());
+    }
+
+    @Override
+    public int compareTo(Difference other) {
+        // sort first highest to lowest count, then by lowest to highest path
+        int countCmp = Integer.valueOf(count).compareTo(other.count);
+        return countCmp != 0 ? -1 * countCmp : path.compareTo(other.path);
+    }
+
+    public String valueDiffString() {
+        if ( hasSpecificDifference() ) {
+            return String.format("%s!=%s", getOneLineString(master), getOneLineString(test));
+        } else {
+            return "N/A";
+        }
+    }
+
+    private static String createPath(DiffElement master, DiffElement test) {
+        return (master == null ? test : master).fullyQualifiedName();
+    }
+
+    private static String getOneLineString(DiffElement elt) {
+        return elt == null ? "MISSING" : elt.getValue().toOneLineString();
+    }
+
+    public boolean hasSpecificDifference() {
+        return master != null || test != null;
+    }
+
+    public DiffElement getMaster() {
+        return master;
+    }
+
+    public DiffElement getTest() {
+        return test;
+    }
+}
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/walkers/diffengine/GATKReportDiffableReader.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/walkers/diffengine/GATKReportDiffableReader.java
new file mode 100644
index 0000000..4a78448
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/walkers/diffengine/GATKReportDiffableReader.java
@@ -0,0 +1,104 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.engine.walkers.diffengine;
+
+import org.broadinstitute.gatk.engine.report.GATKReport;
+import org.broadinstitute.gatk.engine.report.GATKReportColumn;
+import org.broadinstitute.gatk.engine.report.GATKReportTable;
+
+import java.io.File;
+import java.io.FileReader;
+import java.io.IOException;
+
+
+/**
+ * Class implementing diffnode reader for GATKReports
+ */
+
+// TODO Version check to be added at the report level
+
+public class GATKReportDiffableReader implements DiffableReader {
+    @Override
+    public String getName() {
+        return "GATKReport";
+    }
+
+    @Override
+    public DiffElement readFromFile(File file, int maxElementsToRead) {
+        DiffNode root = DiffNode.rooted(file.getName());
+        try {
+            // one line reads the whole thing into memory
+            GATKReport report = new GATKReport(file);
+
+            for (GATKReportTable table : report.getTables()) {
+                root.add(tableToNode(table, root));
+            }
+
+            return root.getBinding();
+        } catch (Exception e) {
+            return null;
+        }
+    }
+
+    private DiffNode tableToNode(GATKReportTable table, DiffNode root) {
+        DiffNode tableRoot = DiffNode.empty(table.getTableName(), root);
+
+        tableRoot.add("Description", table.getTableDescription());
+        tableRoot.add("NumberOfRows", table.getNumRows());
+
+        for ( GATKReportColumn column : table.getColumnInfo() ) {
+            DiffNode columnRoot = DiffNode.empty(column.getColumnName(), tableRoot);
+
+            columnRoot.add("Width", column.getColumnFormat().getWidth());
+            // NOTE: as the values are trimmed during parsing left/right alignment is not currently preserved
+            columnRoot.add("Displayable", true);
+
+            for ( int i = 0; i < table.getNumRows(); i++ ) {
+                String name = column.getColumnName() + (i+1);
+                columnRoot.add(name, table.get(i, column.getColumnName()).toString());
+            }
+
+            tableRoot.add(columnRoot);
+        }
+
+        return tableRoot;
+    }
+
+    @Override
+    public boolean canRead(File file) {
+        try {
+            final String HEADER = GATKReport.GATKREPORT_HEADER_PREFIX;
+            final char[] buff = new char[HEADER.length()];
+            final FileReader FR = new FileReader(file);
+            FR.read(buff, 0, HEADER.length());
+            FR.close();
+            String firstLine = new String(buff);
+            return firstLine.startsWith(HEADER);
+        } catch (IOException e) {
+            return false;
+        }
+    }
+}
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/walkers/diffengine/VCFDiffableReader.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/walkers/diffengine/VCFDiffableReader.java
new file mode 100644
index 0000000..23b213e
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/engine/walkers/diffengine/VCFDiffableReader.java
@@ -0,0 +1,145 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.engine.walkers.diffengine;
+
+import org.apache.log4j.Logger;
+import htsjdk.tribble.AbstractFeatureReader;
+import htsjdk.tribble.FeatureReader;
+import org.broadinstitute.gatk.utils.Utils;
+import htsjdk.variant.vcf.*;
+import htsjdk.variant.variantcontext.Genotype;
+import htsjdk.variant.variantcontext.VariantContext;
+
+import java.io.*;
+import java.util.Iterator;
+import java.util.Map;
+
+
+/**
+ * Created by IntelliJ IDEA.
+ * User: depristo
+ * Date: 7/4/11
+ * Time: 1:09 PM
+ *
+ * Class implementing diffnode reader for VCF
+ */
+public class VCFDiffableReader implements DiffableReader {
+    private static Logger logger = Logger.getLogger(VCFDiffableReader.class);
+
+    @Override
+    public String getName() { return "VCF"; }
+
+    @Override
+    public DiffElement readFromFile(File file, int maxElementsToRead) {
+        DiffNode root = DiffNode.rooted(file.getName());
+        try {
+            // read the version line from the file
+            BufferedReader br = new BufferedReader(new FileReader(file));
+            final String version = br.readLine();
+            root.add("VERSION", version);
+            br.close();
+
+            final VCFCodec vcfCodec = new VCFCodec();
+            vcfCodec.disableOnTheFlyModifications(); // must be read as state is stored in reader itself
+
+            FeatureReader<VariantContext> reader = AbstractFeatureReader.getFeatureReader(file.getAbsolutePath(), vcfCodec, false);
+            VCFHeader header = (VCFHeader)reader.getHeader();
+            for ( VCFHeaderLine headerLine : header.getMetaDataInInputOrder() ) {
+                String key = headerLine.getKey();
+                if ( headerLine instanceof VCFIDHeaderLine)
+                    key += "_" + ((VCFIDHeaderLine) headerLine).getID();
+                if ( root.hasElement(key) )
+                    logger.warn("Skipping duplicate header line: file=" + file + " line=" + headerLine.toString());
+                else
+                    root.add(key, headerLine.toString());
+            }
+
+            int count = 0, nRecordsAtPos = 1;
+            String prevName = "";
+            Iterator<VariantContext> it = reader.iterator();
+            while ( it.hasNext() ) {
+                VariantContext vc = it.next();
+                String name = vc.getChr() + ":" + vc.getStart();
+                if ( name.equals(prevName) ) {
+                    name += "_" + ++nRecordsAtPos;
+                } else {
+                    prevName = name;
+                }
+                DiffNode vcRoot = DiffNode.empty(name, root);
+
+                // add fields
+                vcRoot.add("CHROM", vc.getChr());
+                vcRoot.add("POS", vc.getStart());
+                vcRoot.add("ID", vc.getID());
+                vcRoot.add("REF", vc.getReference());
+                vcRoot.add("ALT", vc.getAlternateAlleles());
+                vcRoot.add("QUAL", vc.hasLog10PError() ? vc.getLog10PError() * -10 : VCFConstants.MISSING_VALUE_v4);
+                vcRoot.add("FILTER", ! vc.filtersWereApplied() // needs null to differentiate between PASS and .
+                        ? VCFConstants.MISSING_VALUE_v4
+                        : ( vc.getFilters().isEmpty() ? VCFConstants.PASSES_FILTERS_v4 : vc.getFilters()) );
+
+                // add info fields
+                for (Map.Entry<String, Object> attribute : vc.getAttributes().entrySet()) {
+                    if ( ! attribute.getKey().startsWith("_") )
+                        vcRoot.add(attribute.getKey(), attribute.getValue());
+                }
+
+                for (Genotype g : vc.getGenotypes() ) {
+                    DiffNode gRoot = DiffNode.empty(g.getSampleName(), vcRoot);
+                    gRoot.add("GT", g.getGenotypeString());
+                    if ( g.hasGQ() ) gRoot.add("GQ", g.getGQ() );
+                    if ( g.hasDP() ) gRoot.add("DP", g.getDP() );
+                    if ( g.hasAD() ) gRoot.add("AD", Utils.join(",", g.getAD()));
+                    if ( g.hasPL() ) gRoot.add("PL", Utils.join(",", g.getPL()));
+                    if ( g.getFilters() != null ) gRoot.add("FT", g.getFilters());
+
+                    for (Map.Entry<String, Object> attribute : g.getExtendedAttributes().entrySet()) {
+                        if ( ! attribute.getKey().startsWith("_") )
+                            gRoot.add(attribute.getKey(), attribute.getValue());
+                    }
+
+                    vcRoot.add(gRoot);
+                }
+
+                root.add(vcRoot);
+                count += vcRoot.size();
+                if ( count > maxElementsToRead && maxElementsToRead != -1)
+                    break;
+            }
+
+            reader.close();
+        } catch ( IOException e ) {
+            return null;
+        }
+
+        return root.getBinding();
+    }
+
+    @Override
+    public boolean canRead(File file) {
+        return AbstractVCFCodec.canDecodeFile(file.getPath(), VCFCodec.VCF4_MAGIC_HEADER);
+    }
+}
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/tools/CatVariants.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/tools/CatVariants.java
new file mode 100644
index 0000000..43403ab
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/tools/CatVariants.java
@@ -0,0 +1,338 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.tools;
+
+import htsjdk.samtools.reference.ReferenceSequenceFile;
+import htsjdk.samtools.reference.ReferenceSequenceFileFactory;
+import org.apache.log4j.BasicConfigurator;
+import org.apache.log4j.Level;
+import htsjdk.tribble.AbstractFeatureReader;
+import htsjdk.tribble.FeatureReader;
+import htsjdk.tribble.index.IndexCreator;
+import org.broadinstitute.gatk.utils.commandline.Argument;
+import org.broadinstitute.gatk.utils.commandline.Input;
+import org.broadinstitute.gatk.utils.commandline.Output;
+import org.broadinstitute.gatk.utils.commandline.CommandLineProgram;
+import org.broadinstitute.gatk.utils.help.DocumentedGATKFeature;
+import org.broadinstitute.gatk.utils.help.HelpConstants;
+import org.broadinstitute.gatk.utils.text.XReadLines;
+import org.broadinstitute.gatk.utils.variant.GATKVCFIndexType;
+import org.broadinstitute.gatk.utils.variant.GATKVCFUtils;
+import htsjdk.variant.bcf2.BCF2Codec;
+import org.broadinstitute.gatk.utils.collections.Pair;
+import htsjdk.variant.vcf.VCFCodec;
+import htsjdk.variant.vcf.VCFHeader;
+import org.broadinstitute.gatk.utils.exceptions.UserException;
+import htsjdk.variant.variantcontext.VariantContext;
+import htsjdk.variant.variantcontext.writer.Options;
+import htsjdk.variant.variantcontext.writer.VariantContextWriter;
+import htsjdk.variant.variantcontext.writer.VariantContextWriterFactory;
+
+import java.io.*;
+import java.util.*;
+
+/**
+ *
+ * Concatenates VCF files of non-overlapped genome intervals, all with the same set of samples
+ *
+ * <p>
+ * The main purpose of this tool is to speed up the gather function when using scatter-gather parallelization.
+ * This tool concatenates the scattered output VCF files. It assumes that:
+ * - All the input VCFs (or BCFs) contain the same samples in the same order.
+ * - The variants in each input file are from non-overlapping (scattered) intervals.
+ *
+ * When the input files are already sorted based on the intervals start positions, use -assumeSorted.
+ *
+ * Note: Currently the tool is more efficient when working with VCFs; we will work to make it as efficient for BCFs.
+ *
+ * </p>
+ *
+ * <h3>Input</h3>
+ * <p>
+ * One or more variant sets to combine. They should be of non-overlapping genome intervals and with the same samples (in the same order).
+ * If the files are ordered according to the appearance of intervals in the ref genome, then one can use the -assumeSorted flag.
+ * </p>
+ *
+ * <h3>Output</h3>
+ * <p>
+ * A combined VCF or BCF. The output file should have the same extension as the input(s).
+ * <\p>
+ *
+ * <h3>Important note</h3>
+ * <p>This is a command-line utility that bypasses the GATK engine. As a result, the command-line you must use to
+ * invoke it is a little different from other GATK tools (see example below), and it does not accept any of the
+ * classic "CommandLineGATK" arguments.</p>
+ *
+ * <h3>Example</h3>
+ * <pre>
+ * java -cp GenomeAnalysisTK.jar org.broadinstitute.gatk.tools.CatVariants \
+ *    -R ref.fasta \
+ *    -V input1.vcf \
+ *    -V input2.vcf \
+ *    -out output.vcf \
+ *    -assumeSorted
+ * </pre>
+ *
+ * @author Ami Levy Moonshine
+ * @since Jan 2012
+ */
+
+ at DocumentedGATKFeature( groupName = HelpConstants.DOCS_CAT_VARMANIP )
+public class CatVariants extends CommandLineProgram {
+    // setup the logging system, used by some codecs
+    private static org.apache.log4j.Logger logger = org.apache.log4j.Logger.getRootLogger();
+
+    @Input(fullName = "reference", shortName = "R", doc = "genome reference file <name>.fasta", required = true)
+    private File refFile = null;
+
+    /**
+     * The VCF or BCF files to merge together
+     *
+     * CatVariants can take any number of -V arguments on the command line.  Each -V argument
+     * will be included in the final merged output VCF/BCF. The order of arguments does not matter, but it runs more
+     * efficiently if they are sorted based on the intervals and the assumeSorted argument is used.
+     *
+     */
+    @Input(fullName="variant", shortName="V", doc="Input VCF file/s", required = true)
+    private List<File> variant = null;
+
+    @Output(fullName = "outputFile", shortName = "out", doc = "output file", required = true)
+    private File outputFile = null;
+
+    @Argument(fullName = "assumeSorted", shortName = "assumeSorted", doc = "assumeSorted should be true if the input files are already sorted (based on the position of the variants)", required = false)
+    private Boolean assumeSorted = false;
+
+    @Argument(fullName = "variant_index_type", doc = "which type of IndexCreator to use for VCF/BCF indices", required = false)
+    private GATKVCFIndexType variant_index_type = GATKVCFUtils.DEFAULT_INDEX_TYPE;
+
+    @Argument(fullName = "variant_index_parameter", doc = "the parameter (bin width or features per bin) to pass to the VCF/BCF IndexCreator", required = false)
+    private Integer variant_index_parameter = GATKVCFUtils.DEFAULT_INDEX_PARAMETER;
+
+    /*
+     * print usage information
+     */
+    private static void printUsage() {
+        System.err.println("Usage: java -cp target/GenomeAnalysisTK.jar org.broadinstitute.gatk.tools.CatVariants --reference <reference> --variant <input VCF or BCF file; can specify --variant multiple times> --outputFile <outputFile> [--assumeSorted]");
+        System.err.println("    The output file must be of the same type as all input files.");
+        System.err.println("    If the input files are already sorted, then indicate that with --assumeSorted to improve performance.");
+    }
+
+    private enum FileType {
+        VCF,
+        BCF,
+        BLOCK_COMPRESSED_VCF,
+        INVALID
+    }
+
+    private FileType fileExtensionCheck(File inFile, File outFile) {
+        final String inFileName = inFile.toString().toLowerCase();
+        final String outFileName = outFile.toString().toLowerCase();
+
+        FileType inFileType = FileType.INVALID;
+
+        if (inFileName.endsWith(".vcf")) {
+            inFileType = FileType.VCF;
+            if (outFileName.endsWith(".vcf"))
+                return inFileType;
+        }
+
+        if (inFileName.endsWith(".bcf")) {
+            inFileType = FileType.BCF;
+            if (outFileName.endsWith(".bcf"))
+                return inFileType;
+        }
+
+        for (String extension : AbstractFeatureReader.BLOCK_COMPRESSED_EXTENSIONS) {
+            if (inFileName.endsWith(".vcf" + extension)) {
+                inFileType = FileType.BLOCK_COMPRESSED_VCF;
+                if (outFileName.endsWith(".vcf" + extension))
+                    return inFileType;
+            }
+        }
+
+        if (inFileType == FileType.INVALID)
+            System.err.println(String.format("File extension for input file %s is not valid for CatVariants", inFile));
+        else
+            System.err.println(String.format("File extension mismatch between input %s and output %s", inFile, outFile));
+
+        printUsage();
+        return FileType.INVALID;
+    }
+
+    private FeatureReader<VariantContext> getFeatureReader(final FileType fileType, final File file) {
+        FeatureReader<VariantContext> reader = null;
+        switch(fileType) {
+            case VCF:
+            case BLOCK_COMPRESSED_VCF:
+                // getFeatureReader will handle both block-compressed and plain text VCFs
+                reader = AbstractFeatureReader.getFeatureReader(file.getAbsolutePath(), new VCFCodec(), false);
+                break;
+            case BCF:
+                reader = AbstractFeatureReader.getFeatureReader(file.getAbsolutePath(), new BCF2Codec(), false);
+                break;
+        }
+        return reader;
+    }
+
+    /**
+     * Replaces any .list files in rawFileList with the files named in said .list file
+     * @param rawFileList the original file list, possibly including .list files
+     * @return a new List, with .list files replaced
+     */
+    private List<File> parseVariantList(final List<File> rawFileList) {
+        final List<File> result = new ArrayList<>(rawFileList.size());
+        for (final File rawFile : rawFileList) {
+            if (rawFile.getName().endsWith(".list")) {
+                try {
+                    for (final String line : new XReadLines(rawFile, true))
+                        result.add(new File(line));
+                } catch (IOException e) {
+                    throw new UserException.CouldNotReadInputFile(rawFile, e);
+                }
+            } else {
+                result.add(rawFile);
+            }
+        }
+        return result;
+    }
+
+    @Override
+    protected int execute() throws Exception {
+        BasicConfigurator.configure();
+        logger.setLevel(Level.INFO);
+
+        final ReferenceSequenceFile ref;
+        try {
+            ref = ReferenceSequenceFileFactory.getReferenceSequenceFile(refFile);
+        } catch ( Exception e ) {
+            throw new UserException("Couldn't load provided reference sequence file " + refFile, e);
+        }
+
+        variant = parseVariantList(variant);
+
+        Comparator<Pair<Integer,File>> positionComparator = new PositionComparator();
+
+        Queue<Pair<Integer,File>> priorityQueue;
+        if (assumeSorted)
+            priorityQueue = new LinkedList<>();
+        else
+            priorityQueue = new PriorityQueue<>(10000, positionComparator);
+
+        FileType fileType = FileType.INVALID;
+        for (File file : variant) {
+            // if it returns a valid type, it will be the same for all files
+            fileType = fileExtensionCheck(file, outputFile);
+            if (fileType == FileType.INVALID)
+                return 1;
+
+            if (assumeSorted){
+                priorityQueue.add(new Pair<>(0,file));
+            }
+            else{
+                if (!file.exists()) {
+                    throw new UserException(String.format("File %s doesn't exist",file.getAbsolutePath()));
+                }
+                FeatureReader<VariantContext> reader = getFeatureReader(fileType, file);
+                Iterator<VariantContext> it = reader.iterator();
+                if(!it.hasNext()){
+                    System.err.println(String.format("File %s is empty. This file will be ignored",file.getAbsolutePath()));
+                    continue;
+                }
+                VariantContext vc = it.next();
+                int firstPosition = vc.getStart();
+                reader.close();
+                priorityQueue.add(new Pair<>(firstPosition,file));
+            }
+
+        }
+
+        FileOutputStream outputStream = new FileOutputStream(outputFile);
+        EnumSet<Options> options = EnumSet.of(Options.INDEX_ON_THE_FLY);
+        final IndexCreator idxCreator = GATKVCFUtils.getIndexCreator(variant_index_type, variant_index_parameter, outputFile, ref.getSequenceDictionary());
+        final VariantContextWriter outputWriter = VariantContextWriterFactory.create(outputFile, outputStream, ref.getSequenceDictionary(), idxCreator, options);
+
+        boolean firstFile = true;
+        int count = 0;
+        while(!priorityQueue.isEmpty() ){
+            count++;
+            File file = priorityQueue.remove().getSecond();
+            if (!file.exists()) {
+                throw new UserException(String.format("File %s doesn't exist",file.getAbsolutePath()));
+            }
+            FeatureReader<VariantContext> reader = getFeatureReader(fileType, file);
+
+            if(count%10 ==0)
+                System.out.print(count);
+            else
+                System.out.print(".");
+            if (firstFile){
+                VCFHeader header = (VCFHeader)reader.getHeader();
+                outputWriter.writeHeader(header);
+                firstFile = false;
+            }
+
+            Iterator<VariantContext> it = reader.iterator();
+
+            while (it.hasNext()){
+                VariantContext vc = it.next();
+                outputWriter.add(vc);
+            }
+
+            reader.close();
+
+        }
+        System.out.println();
+
+        outputWriter.close();
+
+        return 0;
+    }
+
+    public static void main(String[] args){
+        try {
+            CatVariants instance = new CatVariants();
+            start(instance, args);
+            System.exit(CommandLineProgram.result);
+        } catch ( UserException e ) {
+            printUsage();
+            exitSystemWithUserError(e);
+        } catch ( Exception e ) {
+            exitSystemWithError(e);
+        }
+    }
+
+    private static class PositionComparator implements Comparator<Pair<Integer,File>> {
+
+        @Override
+        public int compare(Pair<Integer,File> p1, Pair<Integer,File> p2) {
+            int startPositionP1 = p1.getFirst();
+            int startPositionP2 = p2.getFirst();
+            if (startPositionP1  == startPositionP2)
+                return 0;
+            return startPositionP1 < startPositionP2 ? -1 : 1 ;
+        }
+    }
+}
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/tools/ListAnnotations.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/tools/ListAnnotations.java
new file mode 100644
index 0000000..72d30de
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/tools/ListAnnotations.java
@@ -0,0 +1,85 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.tools;
+
+import org.broadinstitute.gatk.utils.commandline.CommandLineProgram;
+import org.broadinstitute.gatk.utils.exceptions.UserException;
+import org.broadinstitute.gatk.utils.help.DocumentedGATKFeature;
+import org.broadinstitute.gatk.utils.help.HelpConstants;
+import org.broadinstitute.gatk.utils.help.HelpUtils;
+
+/**
+ * Utility program to print a list of available annotations
+ *
+ * <p>This is a very simple utility tool that retrieves available annotations for use with tools such as
+ * UnifiedGenotyper, HaplotypeCaller and VariantAnnotator.</p>
+ *
+ * <h3>Important note</h3>
+ * <p>This is a command-line utility that bypasses the GATK engine. As a result, the command-line you must use to
+ * invoke it is a little different from other GATK tools (see usage below), and it does not accept any of the
+ * classic "CommandLineGATK" arguments.</p>
+ *
+ * <h3>Usage</h3>
+ * <pre>java -cp GenomeAnalysisTK.jar org.broadinstitute.gatk.tools.ListAnnotations</pre>
+ *
+ * @author vdauwera
+ * @since 3/14/13
+ */
+ at DocumentedGATKFeature( groupName = HelpConstants.DOCS_CAT_HELPUTILS )
+public class ListAnnotations extends CommandLineProgram {
+
+    /*
+     * Print usage information
+     *
+     * TODO: would be more convenient if we could just call the program by name instead of the full classpath
+     */
+    private static void printUsage() {
+        System.err.println("Usage: java -cp dist/GenomeAnalysisTK.jar org.broadinstitute.gatk.tools.ListAnnotations");
+        System.err.println("    Prints a list of available annotations and exits.");
+    }
+
+    // TODO: override CommandLineProgram bit that offers version, logging etc arguments. We don't need that stuff here and it makes the doc confusing.
+
+    @Override
+    protected int execute() throws Exception {
+
+        HelpUtils.listAnnotations();
+        return 0;
+    }
+
+    public static void main(String[] args){
+        try {
+            ListAnnotations instance = new ListAnnotations();
+            start(instance, args);
+            System.exit(CommandLineProgram.result);
+        } catch ( UserException e ) {
+            printUsage();
+            exitSystemWithUserError(e);
+        } catch ( Exception e ) {
+            exitSystemWithError(e);
+        }
+    }
+}
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/tools/walkers/annotator/AlleleBalance.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/tools/walkers/annotator/AlleleBalance.java
new file mode 100644
index 0000000..9127b5e
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/tools/walkers/annotator/AlleleBalance.java
@@ -0,0 +1,218 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.tools.walkers.annotator;
+
+
+import htsjdk.variant.variantcontext.Allele;
+import htsjdk.variant.variantcontext.Genotype;
+import htsjdk.variant.variantcontext.GenotypesContext;
+import htsjdk.variant.variantcontext.VariantContext;
+import htsjdk.variant.vcf.VCFHeaderLineType;
+import htsjdk.variant.vcf.VCFInfoHeaderLine;
+import org.broadinstitute.gatk.engine.contexts.AlignmentContext;
+import org.broadinstitute.gatk.engine.contexts.ReferenceContext;
+import org.broadinstitute.gatk.engine.refdata.RefMetaDataTracker;
+import org.broadinstitute.gatk.tools.walkers.annotator.interfaces.AnnotatorCompatible;
+import org.broadinstitute.gatk.tools.walkers.annotator.interfaces.InfoFieldAnnotation;
+import org.broadinstitute.gatk.utils.MathUtils;
+import org.broadinstitute.gatk.utils.genotyper.PerReadAlleleLikelihoodMap;
+import org.broadinstitute.gatk.utils.pileup.ReadBackedPileup;
+
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+
+/**
+ * Allele balance across all samples
+ *
+ * <p> This is an experimental annotation that attempts to estimate whether the data supporting a variant call fits allelic ratio expectations, or whether there might be some bias in the data. Each sample will contribute its allelic read depth (from the AD annotation) to either ABHom or ABHet depending on its genotype call: ABHom if the call is homozygous (REF/REF or ALT/ALT), and ABHet if the call is heterozygous (REF/ALT). Additionally, reads that support something other than the genot [...]
+ * <h3>Calculations</h3>
+ * <p> $$ ABHom = \frac{# ALT alleles}{total # alleles} $$ <br />
+ *     $$ ABHet = \frac{# REF alleles}{# total alleles} $$ <br />
+ *     $$ OND = \frac{# genotyped alleles}{# alleles + # non-alleles} $$
+ * </p>
+ * <p> For ABHom, the value should be close to 1.00 because ideally, all the reads should support a single allele. For ABHet, the value should be close to 0.5, so half of the alleles support the ref allele and half of the alleles support the alt allele. Divergence from these expected ratios may indicate that there is some bias in favor of one allele. Note the caveats below regarding cancer and RNAseq analysis. </p>
+ * <h3>Caveats</h3>
+ * <ul>
+ *     <li>This annotation will only work properly for biallelic variants where all samples are called heterozygous or homozygous.</li>
+ *     <li>This annotation cannot currently be calculated for indels.</li>
+ *     <li>tThe reasoning underlying this annotation only applies to germline variants in DNA sequencing data. In somatic/cancer analysis, divergent ratios are expected due to tumor heterogeneity. In RNAseq analysis, divergent ratios may indicate differential allele expression.</li>
+ *     <li>As stated above, this annotation is experimental and should be interpreted with caution as we cannot guarantee that it is appropriate. Basically, use it at your own risk.</li>
+ * </ul>
+ * <h3>Related annotations</h3>
+ * <ul>
+ *     <li><b><a href="https://www.broadinstitute.org/gatk/guide/tooldocs/org_broadinstitute_gatk_tools_walkers_annotator_AlleleBalanceBySample.php">AlleleBallanceBySample</a></b> calculates allele balance for each individual sample.</li>
+ *     <li><b><a href="https://www.broadinstitute.org/gatk/guide/tooldocs/org_broadinstitute_gatk_tools_walkers_annotator_DepthPerAlleleBySample.php">DepthPerAlleleBySample</a></b> calculates depth of coverage for each allele per sample.</li>
+ * </ul>
+ */
+
+public class AlleleBalance extends InfoFieldAnnotation {
+
+    public Map<String, Object> annotate(final RefMetaDataTracker tracker,
+                                        final AnnotatorCompatible walker,
+                                        final ReferenceContext ref,
+                                        final Map<String, AlignmentContext> stratifiedContexts,
+                                        final VariantContext vc,
+                                        final Map<String, PerReadAlleleLikelihoodMap> stratifiedPerReadAlleleLikelihoodMap) {
+        //if ( stratifiedContexts.size() == 0 )
+        //    return null;
+
+        if ( !vc.isBiallelic() )
+            return null;
+        final GenotypesContext genotypes = vc.getGenotypes();
+        if ( !vc.hasGenotypes() )
+            return null;
+
+        double ratioHom = 0.0;
+        double ratioHet = 0.0;
+        double weightHom = 0.0;
+        double weightHet = 0.0;
+        double overallNonDiploid = 0.0;
+        for ( Genotype genotype : genotypes ) {
+
+            if ( vc.isSNP() ) {
+
+                final int[] counts = getCounts(genotype, stratifiedContexts, vc);
+                // If AD was not calculated, we can't continue
+                if(counts == null)
+                    continue;
+
+                final int n_allele = counts.length;
+                int count_sum = 0;
+                for(int i=0; i<n_allele; i++){
+                    count_sum += counts[i];
+                }
+                double pTrue = 1.0 - Math.pow(10.0,-genotype.getGQ() / (double) 10 );
+                if ( genotype.isHet() ) {
+
+                    final int otherCount = count_sum - (counts[0] + counts[1]);
+                    // sanity check
+                    if ( counts[0] + counts[1] == 0 )
+                        continue;
+
+                    // weight the allele balance by genotype quality so that e.g. mis-called homs don't affect the ratio too much
+                    ratioHet += pTrue * ((double)counts[0] / (double)(counts[0] + counts[1]));
+                    weightHet += pTrue;
+                    overallNonDiploid += ( (double) otherCount )/((double) count_sum*genotypes.size());
+                } else if ( genotype.isHom() ) {
+                    final int alleleIdx = genotype.isHomRef() ?  0 : 1 ;
+                    final int alleleCount = counts[alleleIdx];
+                    int bestOtherCount = 0;
+                    for(int i=0; i<n_allele; i++){
+                        if( i == alleleIdx )
+                            continue;
+                        if( counts[i] > bestOtherCount )
+                            bestOtherCount = counts[i];
+                    }
+                    final int otherCount = count_sum - alleleCount;
+                    ratioHom += pTrue*( (double) alleleCount)/((double) (alleleCount+bestOtherCount));
+                    weightHom += pTrue;
+                    overallNonDiploid += ((double ) otherCount)/((double) count_sum*genotypes.size());
+                }
+                // Allele Balance for indels was not being computed correctly (since there was no allele matching).  Instead of
+                // prolonging the life of imperfect code, I've decided to delete it.  If someone else wants to try again from
+                // scratch, be my guest - but make sure it's done correctly!  [EB]
+            }
+        }
+
+        // make sure we had a het genotype
+
+        Map<String, Object> map = new HashMap<>();
+        if ( weightHet > 0.0 ) {
+            map.put("ABHet",ratioHet/weightHet);
+        }
+
+        if ( weightHom > 0.0 ) {
+            map.put("ABHom",ratioHom/weightHom);
+        }
+
+        if ( overallNonDiploid > 0.0 ) {
+            map.put("OND",overallNonDiploid);
+        }
+        return map;
+    }
+
+    /**
+     * Provide a centralized method of getting the number of reads per allele, 
+     * depending on the input given.  Will use the following (in order of preference):
+     * - genotype.getAD()
+     * - reads from an AlignmentContext
+     * - reads from a PerReadAlleleLikelihoodMap (Not yet implemented) 
+     *
+     *
+     * @param genotype The genotype of interest
+     * @param stratifiedContexts A mapping 
+     * @param vc
+     * @return
+     */
+    private int[] getCounts(final Genotype genotype,
+                            final Map<String, AlignmentContext> stratifiedContexts,
+                            final VariantContext vc){
+
+        // Can't do anything without a genotype here
+        if(genotype == null)
+            return null;
+
+        int[] retVal = genotype.getAD();
+        AlignmentContext context;
+
+        if ( retVal == null && stratifiedContexts != null &&
+                (context = stratifiedContexts.get(genotype.getSampleName())) != null){
+            // If we get to this point, the getAD() function returned no information
+            // about AlleleDepth by Sample - perhaps it wasn't annotated?
+            // In that case, let's try to build it up using the algorithm that
+            // was here in v 3.1-1 and earlier
+            // Also, b/c of the assignment check in the if statement above,
+            // we know we have a valid AlignmentContext for this sample!
+
+            final ReadBackedPileup pileup = context.getBasePileup();
+            final String bases = new String(pileup.getBases());
+            List<Allele> alleles = vc.getAlleles();
+            final int n_allele = alleles.size();
+            retVal = new int[n_allele];
+
+            // Calculate the depth for each allele, under the assumption that
+            // the allele is a single base
+            int i=0;
+            for(Allele a : alleles){
+                retVal[i] = MathUtils.countOccurrences(a.toString().charAt(0), bases);
+                i++;
+            }
+
+        }
+
+        return retVal;
+
+    }
+
+    public List<String> getKeyNames() { return Arrays.asList("ABHet","ABHom","OND"); }
+
+    public List<VCFInfoHeaderLine> getDescriptions() { return Arrays.asList(new VCFInfoHeaderLine("ABHet", 1, VCFHeaderLineType.Float, "Allele Balance for heterozygous calls (ref/(ref+alt))"),
+            new VCFInfoHeaderLine("ABHom", 1, VCFHeaderLineType.Float, "Allele Balance for homozygous calls (A/(A+O)) where A is the allele (ref or alt) and O is anything other"),
+            new VCFInfoHeaderLine("OND", 1, VCFHeaderLineType.Float, "Overall non-diploid ratio (alleles/(alleles+non-alleles))")); }
+}
\ No newline at end of file
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/tools/walkers/annotator/AlleleBalanceBySample.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/tools/walkers/annotator/AlleleBalanceBySample.java
new file mode 100644
index 0000000..9f5ee9c
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/tools/walkers/annotator/AlleleBalanceBySample.java
@@ -0,0 +1,181 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.tools.walkers.annotator;
+
+
+import htsjdk.variant.variantcontext.Allele;
+import htsjdk.variant.variantcontext.Genotype;
+import htsjdk.variant.variantcontext.GenotypeBuilder;
+import htsjdk.variant.variantcontext.VariantContext;
+import htsjdk.variant.vcf.VCFFormatHeaderLine;
+import htsjdk.variant.vcf.VCFHeaderLineType;
+import org.broadinstitute.gatk.engine.contexts.AlignmentContext;
+import org.broadinstitute.gatk.engine.contexts.ReferenceContext;
+import org.broadinstitute.gatk.engine.refdata.RefMetaDataTracker;
+import org.broadinstitute.gatk.tools.walkers.annotator.interfaces.AnnotatorCompatible;
+import org.broadinstitute.gatk.tools.walkers.annotator.interfaces.ExperimentalAnnotation;
+import org.broadinstitute.gatk.tools.walkers.annotator.interfaces.GenotypeAnnotation;
+import org.broadinstitute.gatk.utils.genotyper.MostLikelyAllele;
+import org.broadinstitute.gatk.utils.genotyper.PerReadAlleleLikelihoodMap;
+import org.broadinstitute.gatk.utils.pileup.PileupElement;
+import org.broadinstitute.gatk.utils.pileup.ReadBackedPileup;
+import org.broadinstitute.gatk.utils.sam.GATKSAMRecord;
+
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+
+/**
+ * Allele balance per sample
+ *
+ * <p> This is an experimental annotation that attempts to estimate whether the data supporting a heterozygous genotype call fits allelic ratio expectations, or whether there might be some bias in the data.</p>
+ * <h3>Calculation</h3>
+ * <p> $$ AB = \frac{# ALT alleles}{total # alleles} $$ </p>
+ * <p> Ideally, the value of AB should be close to 0.5, so half of the alleles support the ref allele and half of the alleles support the alt allele. Divergence from the expected ratio may indicate that there is some bias in favor of one allele. Note the caveats below regarding cancer and RNAseq analysis. </p>
+ * <h3>Caveats</h3>
+ * <ul>
+ *     <li>This annotation will only work properly for biallelic heterozygous calls.</li>
+ *     <li>This annotation cannot currently be calculated for indels.</li>
+ *     <li>tThe reasoning underlying this annotation only applies to germline variants in DNA sequencing data. In somatic/cancer analysis, divergent ratios are expected due to tumor heterogeneity. In RNAseq analysis, divergent ratios may indicate differential allele expression.</li>
+ *     <li>As stated above, this annotation is experimental and should be interpreted with caution as we cannot guarantee that it is appropriate. Basically, use it at your own risk.</li>
+ * </ul>
+ * <h3>Related annotations</h3>
+ * <ul>
+ *     <li><b><a href="https://www.broadinstitute.org/gatk/guide/tooldocs/org_broadinstitute_gatk_tools_walkers_annotator_AlleleBalance.php">AlleleBallance</a></b> is a generalization of this annotation over all samples.</li>
+ *     <li><b><a href="https://www.broadinstitute.org/gatk/guide/tooldocs/org_broadinstitute_gatk_tools_walkers_annotator_DepthPerAlleleBySample.php">DepthPerAlleleBySample</a></b> calculates depth of coverage for each allele per sample.</li>
+ * </ul>
+ */
+public class AlleleBalanceBySample extends GenotypeAnnotation implements ExperimentalAnnotation {
+
+    public void annotate(final RefMetaDataTracker tracker,
+                         final AnnotatorCompatible walker,
+                         final ReferenceContext ref,
+                         final AlignmentContext stratifiedContext,
+                         final VariantContext vc,
+                         final Genotype g,
+                         final GenotypeBuilder gb,
+                         final PerReadAlleleLikelihoodMap alleleLikelihoodMap){
+
+
+        // We need a heterozygous genotype and either a context or alleleLikelihoodMap
+        if ( g == null || !g.isCalled() || !g.isHet() || ( stratifiedContext == null && alleleLikelihoodMap == null) )
+            return;
+
+        // Test for existence of <NON_REF> allele, and manually check isSNP() 
+        // and isBiallelic() while ignoring the <NON_REF> allele
+        boolean biallelicSNP = vc.isSNP() && vc.isBiallelic();
+
+        if(vc.hasAllele(GVCF_NONREF)){
+            // If we have the GVCF <NON_REF> allele, then the SNP is biallelic
+            // iff there are 3 alleles and both the reference and first alt
+            // allele are length 1.
+            biallelicSNP = vc.getAlleles().size() == 3 &&
+                    vc.getReference().length() == 1 &&
+                    vc.getAlternateAllele(0).length() == 1;
+        }
+
+        if ( !biallelicSNP )
+            return;
+
+        Double ratio;
+        if (alleleLikelihoodMap != null && !alleleLikelihoodMap.isEmpty())
+            ratio = annotateWithLikelihoods(alleleLikelihoodMap, vc);
+        else if ( stratifiedContext != null )
+            ratio = annotateWithPileup(stratifiedContext, vc);
+        else
+            return;
+
+        if (ratio == null)
+            return;
+
+        gb.attribute(getKeyNames().get(0), Double.valueOf(String.format("%.2f", ratio)));
+    }
+
+    private static final Allele GVCF_NONREF = Allele.create("<NON_REF>", false);
+
+    private Double annotateWithPileup(final AlignmentContext stratifiedContext, final VariantContext vc) {
+
+        final HashMap<Byte, Integer> alleleCounts = new HashMap<>();
+        for ( final Allele allele : vc.getAlleles() )
+            alleleCounts.put(allele.getBases()[0], 0);
+
+        final ReadBackedPileup pileup = stratifiedContext.getBasePileup();
+        for ( final PileupElement p : pileup ) {
+            if ( alleleCounts.containsKey(p.getBase()) )
+                alleleCounts.put(p.getBase(), alleleCounts.get(p.getBase())+1);
+        }
+
+        // we need to add counts in the correct order
+        final int[] counts = new int[alleleCounts.size()];
+        counts[0] = alleleCounts.get(vc.getReference().getBases()[0]);
+        for (int i = 0; i < vc.getAlternateAlleles().size(); i++)
+            counts[i+1] = alleleCounts.get(vc.getAlternateAllele(i).getBases()[0]);
+
+        // sanity check
+        if(counts[0] + counts[1] == 0)
+            return null;
+
+        return ((double) counts[0] / (double)(counts[0] + counts[1]));
+    }
+
+    private Double annotateWithLikelihoods(final PerReadAlleleLikelihoodMap perReadAlleleLikelihoodMap, final VariantContext vc) {
+        final Set<Allele> alleles = new HashSet<>(vc.getAlleles());
+
+        // make sure that there's a meaningful relationship between the alleles in the perReadAlleleLikelihoodMap and our VariantContext
+        if ( ! perReadAlleleLikelihoodMap.getAllelesSet().containsAll(alleles) )
+            throw new IllegalStateException("VC alleles " + alleles + " not a strict subset of per read allele map alleles " + perReadAlleleLikelihoodMap.getAllelesSet());
+
+        final HashMap<Allele, Integer> alleleCounts = new HashMap<>();
+        for ( final Allele allele : vc.getAlleles() ) { alleleCounts.put(allele, 0); }
+
+        for ( final Map.Entry<GATKSAMRecord,Map<Allele,Double>> el : perReadAlleleLikelihoodMap.getLikelihoodReadMap().entrySet()) {
+            final MostLikelyAllele a = PerReadAlleleLikelihoodMap.getMostLikelyAllele(el.getValue(), alleles);
+            if (! a.isInformative() ) continue; // read is non-informative
+            final int prevCount = alleleCounts.get(a.getMostLikelyAllele());
+            alleleCounts.put(a.getMostLikelyAllele(), prevCount + 1);
+        }
+
+        final int[] counts = new int[alleleCounts.size()];
+        counts[0] = alleleCounts.get(vc.getReference());
+        for (int i = 0; i < vc.getAlternateAlleles().size(); i++)
+            counts[i+1] = alleleCounts.get( vc.getAlternateAllele(i) );
+
+        // sanity check
+        if(counts[0] + counts[1] == 0)
+            return null;
+
+        return ((double) counts[0] / (double)(counts[0] + counts[1]));
+
+    }
+
+    public List<String> getKeyNames() { return Arrays.asList("AB"); }
+
+    public List<VCFFormatHeaderLine> getDescriptions() { return Arrays.asList(new VCFFormatHeaderLine(getKeyNames().get(0), 1, VCFHeaderLineType.Float, "Allele balance for each het genotype")); }
+}
\ No newline at end of file
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/tools/walkers/annotator/BaseCounts.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/tools/walkers/annotator/BaseCounts.java
new file mode 100644
index 0000000..44579f9
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/tools/walkers/annotator/BaseCounts.java
@@ -0,0 +1,91 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.tools.walkers.annotator;
+
+import org.broadinstitute.gatk.engine.contexts.AlignmentContext;
+import org.broadinstitute.gatk.engine.contexts.ReferenceContext;
+import org.broadinstitute.gatk.engine.refdata.RefMetaDataTracker;
+import org.broadinstitute.gatk.tools.walkers.annotator.interfaces.AnnotatorCompatible;
+import org.broadinstitute.gatk.tools.walkers.annotator.interfaces.InfoFieldAnnotation;
+import org.broadinstitute.gatk.utils.genotyper.PerReadAlleleLikelihoodMap;
+import org.broadinstitute.gatk.utils.BaseUtils;
+import htsjdk.variant.vcf.VCFHeaderLineType;
+import htsjdk.variant.vcf.VCFInfoHeaderLine;
+import htsjdk.variant.variantcontext.VariantContext;
+
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+
+/**
+ * Count of A, C, G, T bases across all samples
+ *
+ * <p> This annotation returns the counts of A, C, G, and T bases across all samples, in that order.</p>
+ * <h3>Example:</h3>
+ *
+ * <pre>BaseCounts=3,0,3,0</pre>
+ *
+ * <p>
+ *     This means the number of A bases seen is 3, the number of T bases seen is 0, the number of G bases seen is 3, and the number of T bases seen is 0.
+ * </p>
+ *
+ * <h3>Related annotations</h3>
+ * <ul>
+ *     <li><b><a href="https://www.broadinstitute.org/gatk/guide/tooldocs/org_broadinstitute_gatk_tools_walkers_annotator_NBaseCount.php">NBaseCount</a></b> counts the percentage of N bases.</li>
+ * </ul>
+ */
+
+ public class BaseCounts extends InfoFieldAnnotation {
+
+    public Map<String, Object> annotate(final RefMetaDataTracker tracker,
+                                        final AnnotatorCompatible walker,
+                                        final ReferenceContext ref,
+                                        final Map<String, AlignmentContext> stratifiedContexts,
+                                        final VariantContext vc,
+                                        final Map<String, PerReadAlleleLikelihoodMap> stratifiedPerReadAlleleLikelihoodMap) {
+        if ( stratifiedContexts.size() == 0 )
+            return null;
+
+        int[] counts = new int[4];
+
+        for ( Map.Entry<String, AlignmentContext> sample : stratifiedContexts.entrySet() ) {
+            for (byte base : sample.getValue().getBasePileup().getBases() ) {
+                int index = BaseUtils.simpleBaseToBaseIndex(base);
+                if ( index != -1 )
+                    counts[index]++;
+            }
+        }
+        Map<String, Object> map = new HashMap<String, Object>();
+        map.put(getKeyNames().get(0), counts);
+        return map;
+    }
+
+    public List<String> getKeyNames() { return Arrays.asList("BaseCounts"); }
+
+    public List<VCFInfoHeaderLine> getDescriptions() { return Arrays.asList(new VCFInfoHeaderLine("BaseCounts", 4, VCFHeaderLineType.Integer, "Counts of each base")); }
+}
\ No newline at end of file
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/tools/walkers/annotator/ChromosomeCountConstants.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/tools/walkers/annotator/ChromosomeCountConstants.java
new file mode 100644
index 0000000..67fc0a4
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/tools/walkers/annotator/ChromosomeCountConstants.java
@@ -0,0 +1,44 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.tools.walkers.annotator;
+
+import htsjdk.variant.vcf.VCFConstants;
+import htsjdk.variant.vcf.VCFInfoHeaderLine;
+import htsjdk.variant.vcf.VCFStandardHeaderLines;
+
+
+/**
+ * Keys and descriptions for the common chromosome count annotations
+ */
+public class ChromosomeCountConstants {
+
+    public static final String[] keyNames = { VCFConstants.ALLELE_NUMBER_KEY, VCFConstants.ALLELE_COUNT_KEY, VCFConstants.ALLELE_FREQUENCY_KEY };
+
+    public static final VCFInfoHeaderLine[] descriptions = {
+            VCFStandardHeaderLines.getInfoLine(VCFConstants.ALLELE_FREQUENCY_KEY),
+            VCFStandardHeaderLines.getInfoLine(VCFConstants.ALLELE_COUNT_KEY),
+            VCFStandardHeaderLines.getInfoLine(VCFConstants.ALLELE_NUMBER_KEY) };
+}
\ No newline at end of file
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/tools/walkers/annotator/LowMQ.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/tools/walkers/annotator/LowMQ.java
new file mode 100644
index 0000000..05054a3
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/tools/walkers/annotator/LowMQ.java
@@ -0,0 +1,91 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.tools.walkers.annotator;
+
+import org.broadinstitute.gatk.engine.contexts.AlignmentContext;
+import org.broadinstitute.gatk.engine.contexts.ReferenceContext;
+import org.broadinstitute.gatk.engine.refdata.RefMetaDataTracker;
+import org.broadinstitute.gatk.tools.walkers.annotator.interfaces.AnnotatorCompatible;
+import org.broadinstitute.gatk.tools.walkers.annotator.interfaces.InfoFieldAnnotation;
+import org.broadinstitute.gatk.utils.genotyper.PerReadAlleleLikelihoodMap;
+import htsjdk.variant.vcf.VCFHeaderLineType;
+import htsjdk.variant.vcf.VCFInfoHeaderLine;
+import org.broadinstitute.gatk.utils.pileup.PileupElement;
+import htsjdk.variant.variantcontext.VariantContext;
+
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+
+/**
+ * Proportion of low quality reads
+ *
+ * <p>This annotation tells you what fraction of reads have a mapping quality of less than the given threshold of 10 (including 0). Note that certain tools may impose a different minimum mapping quality threshold. For example, HaplotypeCaller excludes reads with MAPQ<20.</p>
+ *
+ * <h3>Calculation</h3>
+ * <p> $$ LowMQ = \frac{# reads with MAPQ=0 + # reads with MAPQ<10}{total # reads} $$
+ * </p>
+ *
+ * <h3>Related annotations</h3>
+ * <ul>
+ *     <li><b><a href="https://www.broadinstitute.org/gatk/guide/tooldocs/org_broadinstitute_gatk_tools_walkers_annotator_MappingQualityZero.php">MappingQualityZero</a></b> gives the count of reads with MAPQ=0 across all samples.</li>
+ *     <li><b><a href="https://www.broadinstitute.org/gatk/guide/tooldocs/org_broadinstitute_gatk_tools_walkers_annotator_MappingQualityZeroBySample.php">MappingQualityZeroBySample</a></b> gives the count of reads with MAPQ=0 for each individual sample.</li>
+ * </ul>
+ */
+public class LowMQ extends InfoFieldAnnotation {
+
+    public Map<String, Object> annotate(final RefMetaDataTracker tracker,
+                                        final AnnotatorCompatible walker,
+                                        final ReferenceContext ref,
+                                        final Map<String, AlignmentContext> stratifiedContexts,
+                                        final VariantContext vc,
+                                        final Map<String, PerReadAlleleLikelihoodMap> stratifiedPerReadAlleleLikelihoodMap) {
+        if ( stratifiedContexts.size() == 0 )
+            return null;
+
+        double mq0 = 0;
+		double mq10 = 0;
+		double total = 0;
+        for ( Map.Entry<String, AlignmentContext> sample : stratifiedContexts.entrySet() )
+		{
+            for ( PileupElement p : sample.getValue().getBasePileup() )
+			{
+                if ( p.getMappingQual() == 0 )  { mq0 += 1; }
+                if ( p.getMappingQual() <= 10 ) { mq10 += 1; }
+				total += 1; 
+            }
+        }
+        Map<String, Object> map = new HashMap<String, Object>();
+        map.put(getKeyNames().get(0), String.format("%.04f,%.04f,%.00f", mq0/total, mq10/total, total));
+        return map;
+    }
+
+    public List<String> getKeyNames() { return Arrays.asList("LowMQ"); }
+
+    public List<VCFInfoHeaderLine> getDescriptions() { return Arrays.asList(new VCFInfoHeaderLine(getKeyNames().get(0), 3, VCFHeaderLineType.Float, "3-tuple: <fraction of reads with MQ=0>,<fraction of reads with MQ<=10>,<total number of reads>")); }
+}
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/tools/walkers/annotator/MappingQualityZeroBySample.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/tools/walkers/annotator/MappingQualityZeroBySample.java
new file mode 100644
index 0000000..cf1323f
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/tools/walkers/annotator/MappingQualityZeroBySample.java
@@ -0,0 +1,86 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.tools.walkers.annotator;
+
+import org.broadinstitute.gatk.engine.contexts.AlignmentContext;
+import org.broadinstitute.gatk.engine.contexts.ReferenceContext;
+import org.broadinstitute.gatk.engine.refdata.RefMetaDataTracker;
+import org.broadinstitute.gatk.tools.walkers.annotator.interfaces.AnnotatorCompatible;
+import org.broadinstitute.gatk.tools.walkers.annotator.interfaces.GenotypeAnnotation;
+import org.broadinstitute.gatk.utils.genotyper.PerReadAlleleLikelihoodMap;
+import htsjdk.variant.vcf.VCFConstants;
+import htsjdk.variant.vcf.VCFFormatHeaderLine;
+import htsjdk.variant.vcf.VCFHeaderLineType;
+import org.broadinstitute.gatk.utils.pileup.PileupElement;
+import org.broadinstitute.gatk.utils.pileup.ReadBackedPileup;
+import htsjdk.variant.variantcontext.Genotype;
+import htsjdk.variant.variantcontext.GenotypeBuilder;
+import htsjdk.variant.variantcontext.VariantContext;
+
+import java.util.Arrays;
+import java.util.List;
+
+/**
+ * Count of reads with mapping quality zero for each sample
+ *
+ * <p>This annotation gives you the count of all reads that have MAPQ = 0 for each sample. The count of reads with MAPQ0 can be used for quality control; high counts typically indicate regions where it is difficult to make confident calls.</p>
+ *
+ * <h3>Related annotations</h3>
+ * <ul>
+ *     <li><b><a href="https://www.broadinstitute.org/gatk/guide/tooldocs/org_broadinstitute_gatk_tools_walkers_annotator_MappingQualityZero.php">MappingQualityZero</a></b> gives the count of reads with MAPQ=0 across all samples.</li>
+ *     <li><b><a href="https://www.broadinstitute.org/gatk/guide/tooldocs/org_broadinstitute_gatk_tools_walkers_annotator_LowMQ.php">LowMQ</a></b> gives the proportion of reads with low mapping quality (MAPQ below 10, including 0).</li>
+ * </ul>
+ */
+public class MappingQualityZeroBySample extends GenotypeAnnotation {
+    public void annotate(final RefMetaDataTracker tracker,
+                         final AnnotatorCompatible walker,
+                         final ReferenceContext ref,
+                         final AlignmentContext stratifiedContext,
+                         final VariantContext vc,
+                         final Genotype g,
+                         final GenotypeBuilder gb,
+                         final PerReadAlleleLikelihoodMap alleleLikelihoodMap){
+        if ( g == null || !g.isCalled() || stratifiedContext == null )
+            return;
+
+        int mq0 = 0;
+        final ReadBackedPileup pileup = stratifiedContext.getBasePileup();
+        for (PileupElement p : pileup ) {
+            if ( p.getMappingQual() == 0 )
+                mq0++;
+        }
+
+        gb.attribute(getKeyNames().get(0), mq0);
+    }
+
+    public List<String> getKeyNames() { return Arrays.asList(VCFConstants.MAPPING_QUALITY_ZERO_KEY); }
+
+    public List<VCFFormatHeaderLine> getDescriptions() { return Arrays.asList(
+            new VCFFormatHeaderLine(getKeyNames().get(0), 1,
+                    VCFHeaderLineType.Integer, "Number of Mapping Quality Zero Reads per sample")); }
+
+
+}
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/tools/walkers/annotator/NBaseCount.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/tools/walkers/annotator/NBaseCount.java
new file mode 100644
index 0000000..544feb7
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/tools/walkers/annotator/NBaseCount.java
@@ -0,0 +1,89 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.tools.walkers.annotator;
+
+import org.broadinstitute.gatk.engine.contexts.AlignmentContext;
+import org.broadinstitute.gatk.engine.contexts.ReferenceContext;
+import org.broadinstitute.gatk.engine.refdata.RefMetaDataTracker;
+import org.broadinstitute.gatk.tools.walkers.annotator.interfaces.AnnotatorCompatible;
+import org.broadinstitute.gatk.tools.walkers.annotator.interfaces.InfoFieldAnnotation;
+import org.broadinstitute.gatk.utils.genotyper.PerReadAlleleLikelihoodMap;
+import org.broadinstitute.gatk.utils.BaseUtils;
+import htsjdk.variant.vcf.VCFHeaderLineType;
+import htsjdk.variant.vcf.VCFInfoHeaderLine;
+import org.broadinstitute.gatk.utils.pileup.PileupElement;
+import htsjdk.variant.variantcontext.VariantContext;
+
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * Percentage of N bases
+ *
+ * <p>N occurs in a sequence when the sequencer does not have enough information to determine which base it should call. The presence of many Ns at the same site lowers our confidence in any calls made there, because it suggests that there was some kind of technical difficulty that interfered with the sequencing process.</p>
+ *
+ * <p><b>Note that in GATK versions 3.2 and earlier, this annotation only counted N bases from reads generated with SOLiD technology. This functionality was generalized for all sequencing platforms in GATK version 3.3.</b></p>
+ *
+ * <h3>Related annotations</h3>
+ * <ul>
+ *     <li><b><a href="https://www.broadinstitute.org/gatk/guide/tooldocs/org_broadinstitute_gatk_tools_walkers_annotator_BaseCounts.php">BaseCounts</a></b> counts the number of A, C, G, T bases across all samples.</li>
+ * </ul>
+ *
+ * */
+public class NBaseCount extends InfoFieldAnnotation {
+    public Map<String, Object> annotate(final RefMetaDataTracker tracker,
+                                        final AnnotatorCompatible walker,
+                                        final ReferenceContext ref,
+                                        final Map<String, AlignmentContext> stratifiedContexts,
+                                        final VariantContext vc,
+                                        final Map<String, PerReadAlleleLikelihoodMap> stratifiedPerReadAlleleLikelihoodMap) {
+        if( stratifiedContexts.size() == 0 )
+            return null;
+
+        int countNBase = 0;
+        int countRegularBase = 0;
+
+        for( final AlignmentContext context : stratifiedContexts.values() ) {
+            for( final PileupElement p : context.getBasePileup()) {
+                final String platform = p.getRead().getReadGroup().getPlatform();
+                if( BaseUtils.isNBase( p.getBase() ) ) {
+                    countNBase++;
+                } else if( BaseUtils.isRegularBase( p.getBase() ) ) {
+                    countRegularBase++;
+                }
+            }
+        }
+        final Map<String, Object> map = new HashMap<String, Object>();
+        map.put(getKeyNames().get(0), String.format("%.4f", (double)countNBase / (double)(countNBase + countRegularBase + 1)));
+        return map;
+    }
+
+    public List<String> getKeyNames() { return Arrays.asList("PercentNBase"); }
+
+    public List<VCFInfoHeaderLine> getDescriptions() { return Arrays.asList(new VCFInfoHeaderLine("PercentNBase", 1, VCFHeaderLineType.Float, "Percentage of N bases in the pileup")); }
+}
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/tools/walkers/annotator/SnpEff.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/tools/walkers/annotator/SnpEff.java
new file mode 100644
index 0000000..f514f67
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/tools/walkers/annotator/SnpEff.java
@@ -0,0 +1,586 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.tools.walkers.annotator;
+
+import org.apache.log4j.Logger;
+import org.broadinstitute.gatk.utils.commandline.RodBinding;
+import org.broadinstitute.gatk.engine.GenomeAnalysisEngine;
+import org.broadinstitute.gatk.engine.contexts.AlignmentContext;
+import org.broadinstitute.gatk.engine.contexts.ReferenceContext;
+import org.broadinstitute.gatk.engine.refdata.RefMetaDataTracker;
+import org.broadinstitute.gatk.tools.walkers.annotator.interfaces.AnnotatorCompatible;
+import org.broadinstitute.gatk.tools.walkers.annotator.interfaces.InfoFieldAnnotation;
+import org.broadinstitute.gatk.tools.walkers.annotator.interfaces.RodRequiringAnnotation;
+import org.broadinstitute.gatk.utils.genotyper.PerReadAlleleLikelihoodMap;
+import org.broadinstitute.gatk.utils.Utils;
+import org.broadinstitute.gatk.utils.variant.GATKVCFUtils;
+import htsjdk.variant.vcf.*;
+import org.broadinstitute.gatk.utils.exceptions.UserException;
+import htsjdk.variant.variantcontext.VariantContext;
+
+import java.util.*;
+import java.util.regex.Pattern;
+
+/**
+ * Top effect from SnpEff functional predictions
+ *
+ * <p>This annotation processes the output of the SnpEff functional prediction tool to select only the predicted effect with the highest biological impact. The SnpEff output must be provided on the command line by specifying "--snpEffFile filename.vcf". See <a href="http://snpeff.sourceforge.net/">http://snpeff.sourceforge.net/</a> for more information about the SnpEff tool</p>.
+ *
+ * <h3>Caveats</h3>
+ *
+ * <ul><li>This annotation currently only supports output from SnpEff version 2.0.5.</li></ul>
+ *
+ */
+public class SnpEff extends InfoFieldAnnotation implements RodRequiringAnnotation {
+
+    private static Logger logger = Logger.getLogger(SnpEff.class);
+
+    // We refuse to parse SnpEff output files generated by unsupported versions, or
+    // lacking a SnpEff version number in the VCF header:
+    public static final String[] SUPPORTED_SNPEFF_VERSIONS = { "2.0.5" };
+    public static final String SNPEFF_VCF_HEADER_VERSION_LINE_KEY = "SnpEffVersion";
+    public static final String SNPEFF_VCF_HEADER_COMMAND_LINE_KEY = "SnpEffCmd";
+    public static final String SNPEFF_GATK_COMPATIBILITY_ARGUMENT = "-o gatk";
+    public static final Pattern SNPEFF_GATK_COMPATIBILITY_ARGUMENT_PATTERN = Pattern.compile("-o\\s+gatk");
+
+    // When we write the SnpEff version number and command line to the output VCF, we change
+    // the key name slightly so that the output VCF won't be confused in the future for an
+    // output file produced by SnpEff directly:
+    public static final String OUTPUT_VCF_HEADER_VERSION_LINE_KEY = "Original" + SNPEFF_VCF_HEADER_VERSION_LINE_KEY;
+    public static final String OUTPUT_VCF_HEADER_COMMAND_LINE_KEY = "Original" + SNPEFF_VCF_HEADER_COMMAND_LINE_KEY;
+
+    // SnpEff aggregates all effects (and effect metadata) together into a single INFO
+    // field annotation with the key EFF:
+    public static final String SNPEFF_INFO_FIELD_KEY = "EFF";
+    public static final String SNPEFF_EFFECT_METADATA_DELIMITER = "[()]";
+    public static final String SNPEFF_EFFECT_METADATA_SUBFIELD_DELIMITER = "\\|";
+
+    // Key names for the INFO field annotations we will add to each record, along
+    // with parsing-related information:
+    public enum InfoFieldKey {
+        EFFECT_KEY            ("SNPEFF_EFFECT",           -1),
+        IMPACT_KEY            ("SNPEFF_IMPACT",            0),
+        FUNCTIONAL_CLASS_KEY  ("SNPEFF_FUNCTIONAL_CLASS",  1),
+        CODON_CHANGE_KEY      ("SNPEFF_CODON_CHANGE",      2),
+        AMINO_ACID_CHANGE_KEY ("SNPEFF_AMINO_ACID_CHANGE", 3),
+        GENE_NAME_KEY         ("SNPEFF_GENE_NAME",         4),
+        GENE_BIOTYPE_KEY      ("SNPEFF_GENE_BIOTYPE",      5),
+        TRANSCRIPT_ID_KEY     ("SNPEFF_TRANSCRIPT_ID",     7),
+        EXON_ID_KEY           ("SNPEFF_EXON_ID",           8);
+
+        // Actual text of the key
+        private final String keyName;
+
+        // Index within the effect metadata subfields from the SnpEff EFF annotation
+        // where each key's associated value can be found during parsing.
+        private final int fieldIndex;
+
+        InfoFieldKey ( String keyName, int fieldIndex ) {
+            this.keyName = keyName;
+            this.fieldIndex = fieldIndex;
+        }
+
+        public String getKeyName() {
+            return keyName;
+        }
+
+        public int getFieldIndex() {
+            return fieldIndex;
+        }
+    }
+
+    // Possible SnpEff biological effects. All effect names found in the SnpEff input file
+    // are validated against this list.
+    public enum EffectType {
+        // High-impact effects:
+        SPLICE_SITE_ACCEPTOR,
+        SPLICE_SITE_DONOR,
+        START_LOST,
+        EXON_DELETED,
+        FRAME_SHIFT,
+        STOP_GAINED,
+        STOP_LOST,
+
+        // Moderate-impact effects:
+        NON_SYNONYMOUS_CODING,
+        CODON_CHANGE,
+        CODON_INSERTION,
+        CODON_CHANGE_PLUS_CODON_INSERTION,
+        CODON_DELETION,
+        CODON_CHANGE_PLUS_CODON_DELETION,
+        UTR_5_DELETED,
+        UTR_3_DELETED,
+
+        // Low-impact effects:
+        SYNONYMOUS_START,
+        NON_SYNONYMOUS_START,
+        START_GAINED,
+        SYNONYMOUS_CODING,
+        SYNONYMOUS_STOP,
+        NON_SYNONYMOUS_STOP,
+
+        // Modifiers:
+        NONE,
+        CHROMOSOME,
+        CUSTOM,
+        CDS,
+        GENE,
+        TRANSCRIPT,
+        EXON,
+        INTRON_CONSERVED,
+        UTR_5_PRIME,
+        UTR_3_PRIME,
+        DOWNSTREAM,
+        INTRAGENIC,
+        INTERGENIC,
+        INTERGENIC_CONSERVED,
+        UPSTREAM,
+        REGULATION,
+        INTRON
+    }
+
+    // SnpEff labels each effect as either LOW, MODERATE, or HIGH impact, or as a MODIFIER.
+    public enum EffectImpact {
+        MODIFIER  (0),
+        LOW       (1),
+        MODERATE  (2),
+        HIGH      (3);
+
+        private final int severityRating;
+
+        EffectImpact ( int severityRating ) {
+            this.severityRating = severityRating;
+        }
+
+        public boolean isHigherImpactThan ( EffectImpact other ) {
+            return this.severityRating > other.severityRating;
+        }
+
+        public boolean isSameImpactAs ( EffectImpact other ) {
+            return this.severityRating == other.severityRating;
+        }
+    }
+
+    // SnpEff labels most effects as either CODING or NON_CODING, but sometimes omits this information.
+    public enum EffectCoding {
+        CODING,
+        NON_CODING,
+        UNKNOWN
+    }
+
+    // SnpEff assigns a functional class to each effect.
+    public enum EffectFunctionalClass {
+        NONE     (0),
+        SILENT   (1),
+        MISSENSE (2),
+        NONSENSE (3);
+
+        private final int priority;
+
+        EffectFunctionalClass ( int priority ) {
+            this.priority = priority;
+        }
+
+        public boolean isHigherPriorityThan ( EffectFunctionalClass other ) {
+            return this.priority > other.priority;
+        }
+    }
+
+    public void initialize ( AnnotatorCompatible walker, GenomeAnalysisEngine toolkit, Set<VCFHeaderLine> headerLines ) {
+        // Make sure that we actually have a valid SnpEff rod binding (just in case the user specified -A SnpEff
+        // without providing a SnpEff rod via --snpEffFile):
+        validateRodBinding(walker.getSnpEffRodBinding());
+        RodBinding<VariantContext> snpEffRodBinding = walker.getSnpEffRodBinding();
+
+        // Make sure that the SnpEff version number and command-line header lines are present in the VCF header of
+        // the SnpEff rod, and that the file was generated by a supported version of SnpEff:
+        VCFHeader snpEffVCFHeader = GATKVCFUtils.getVCFHeadersFromRods(toolkit, Arrays.asList(snpEffRodBinding.getName())).get(snpEffRodBinding.getName());
+        VCFHeaderLine snpEffVersionLine = snpEffVCFHeader.getOtherHeaderLine(SNPEFF_VCF_HEADER_VERSION_LINE_KEY);
+        VCFHeaderLine snpEffCommandLine = snpEffVCFHeader.getOtherHeaderLine(SNPEFF_VCF_HEADER_COMMAND_LINE_KEY);
+
+        checkSnpEffVersionAndCommandLine(snpEffVersionLine, snpEffCommandLine);
+
+        // If everything looks ok, add the SnpEff version number and command-line header lines to the
+        // header of the VCF output file, changing the key names so that our output file won't be
+        // mistaken in the future for a SnpEff output file:
+        headerLines.add(new VCFHeaderLine(OUTPUT_VCF_HEADER_VERSION_LINE_KEY, snpEffVersionLine.getValue()));
+        headerLines.add(new VCFHeaderLine(OUTPUT_VCF_HEADER_COMMAND_LINE_KEY, snpEffCommandLine.getValue()));
+    }
+
+    public Map<String, Object> annotate(final RefMetaDataTracker tracker,
+                                        final AnnotatorCompatible walker,
+                                        final ReferenceContext ref,
+                                        final Map<String, AlignmentContext> stratifiedContexts,
+                                        final VariantContext vc,
+                                        final Map<String, PerReadAlleleLikelihoodMap> stratifiedPerReadAlleleLikelihoodMap) {
+        RodBinding<VariantContext> snpEffRodBinding = walker.getSnpEffRodBinding();
+
+        // Get only SnpEff records that start at this locus, not merely span it:
+        List<VariantContext> snpEffRecords = tracker.getValues(snpEffRodBinding, ref.getLocus());
+
+        // Within this set, look for a SnpEff record whose ref/alt alleles match the record to annotate.
+        // If there is more than one such record, we only need to pick the first one, since the biological
+        // effects will be the same across all such records:
+        VariantContext matchingRecord = getMatchingSnpEffRecord(snpEffRecords, vc);
+        if ( matchingRecord == null ) {
+            return null;
+        }
+
+        // Parse the SnpEff INFO field annotation from the matching record into individual effect objects:
+        List<SnpEffEffect> effects = parseSnpEffRecord(matchingRecord);
+        if ( effects.size() == 0 ) {
+            return null;
+        }
+
+        // Add only annotations for one of the most biologically-significant effects from this set:
+        SnpEffEffect mostSignificantEffect = getMostSignificantEffect(effects);
+        return mostSignificantEffect.getAnnotations();
+    }
+
+    private void validateRodBinding ( RodBinding<VariantContext> snpEffRodBinding ) {
+        if ( snpEffRodBinding == null || ! snpEffRodBinding.isBound() ) {
+            throw new UserException("The SnpEff annotator requires that a SnpEff VCF output file be provided " +
+                                    "as a rodbinding on the command line via the --snpEffFile option, but " +
+                                    "no SnpEff rodbinding was found.");
+        }
+    }
+
+    private void checkSnpEffVersionAndCommandLine( final VCFHeaderLine snpEffVersionLine, final VCFHeaderLine snpEffCommandLine ) {
+        if ( snpEffVersionLine == null || snpEffVersionLine.getValue() == null || snpEffVersionLine.getValue().trim().length() == 0 ) {
+            throw new UserException(String.format("Could not find a %s entry in the VCF header for the SnpEff input file, " +
+                                                  "and so could not verify that the file was generated by a supported version of SnpEff (%s)",
+                                                  SNPEFF_VCF_HEADER_VERSION_LINE_KEY, supportedSnpEffVersionsString()));
+        }
+
+        if ( snpEffCommandLine == null || snpEffCommandLine.getValue() == null || snpEffCommandLine.getValue().trim().length() == 0 ) {
+            throw new UserException(String.format("Could not find a %s entry in the VCF header for the SnpEff input file, " +
+                                                  "which should be added by all supported versions of SnpEff (%s)",
+                                                  SNPEFF_VCF_HEADER_COMMAND_LINE_KEY, supportedSnpEffVersionsString()));
+        }
+
+        String snpEffVersionString = snpEffVersionLine.getValue().replaceAll("\"", "").split(" ")[0];
+
+        if ( ! isSupportedSnpEffVersion(snpEffVersionString, snpEffCommandLine.getValue()) ) {
+            throw new UserException(String.format("The version of SnpEff used to generate the SnpEff input file (%s) " +
+                                                  "is not currently supported by the GATK, and was not run in GATK " +
+                                                  "compatibility mode. Supported versions are: %s",
+                                                  snpEffVersionString, supportedSnpEffVersionsString()));
+        }
+    }
+
+    private boolean isSupportedSnpEffVersion( final String versionString, final String commandLine ) {
+        // first check to see if it's an officially-supported version
+        for ( String supportedVersion : SUPPORTED_SNPEFF_VERSIONS ) {
+            if ( supportedVersion.equals(versionString) ) {
+                return true;
+            }
+        }
+
+        // if it's not an officially-supported version, check to see whether the
+        // "-o gatk" compatibility option was specified
+        return SNPEFF_GATK_COMPATIBILITY_ARGUMENT_PATTERN.matcher(commandLine).find();
+    }
+
+    private String supportedSnpEffVersionsString() {
+        return String.format("%s, as well as later versions when run with the option %s",
+                             Arrays.toString(SUPPORTED_SNPEFF_VERSIONS), SNPEFF_GATK_COMPATIBILITY_ARGUMENT);
+    }
+
+    private VariantContext getMatchingSnpEffRecord ( List<VariantContext> snpEffRecords, VariantContext vc ) {
+        for ( VariantContext snpEffRecord : snpEffRecords ) {
+            if ( snpEffRecord.hasSameAlternateAllelesAs(vc) && snpEffRecord.getReference().equals(vc.getReference()) ) {
+                return snpEffRecord;
+            }
+        }
+
+        return null;
+    }
+
+    private List<SnpEffEffect> parseSnpEffRecord ( VariantContext snpEffRecord ) {
+        List<SnpEffEffect> parsedEffects = new ArrayList<SnpEffEffect>();
+
+        Object effectFieldValue = snpEffRecord.getAttribute(SNPEFF_INFO_FIELD_KEY);
+        if ( effectFieldValue == null ) {
+            return parsedEffects;
+        }
+
+        // The VCF codec stores multi-valued fields as a List<String>, and single-valued fields as a String.
+        // We can have either in the case of SnpEff, since there may be one or more than one effect in this record.
+        List<String> individualEffects;
+        if ( effectFieldValue instanceof List ) {
+            individualEffects = (List<String>)effectFieldValue;
+        }
+        else {
+            individualEffects = Arrays.asList((String)effectFieldValue);
+        }
+
+        for ( String effectString : individualEffects ) {
+            String[] effectNameAndMetadata = effectString.split(SNPEFF_EFFECT_METADATA_DELIMITER);
+
+            if ( effectNameAndMetadata.length != 2 ) {
+                logger.warn(String.format("Malformed SnpEff effect field at %s:%d, skipping: %s",
+                                          snpEffRecord.getChr(), snpEffRecord.getStart(), effectString));
+                continue;
+            }
+
+            String effectName = effectNameAndMetadata[0];
+            String[] effectMetadata = effectNameAndMetadata[1].split(SNPEFF_EFFECT_METADATA_SUBFIELD_DELIMITER, -1);
+
+            SnpEffEffect parsedEffect = new SnpEffEffect(effectName, effectMetadata);
+
+            if ( parsedEffect.isWellFormed() ) {
+                parsedEffects.add(parsedEffect);
+            }
+            else {
+                logger.warn(String.format("Skipping malformed SnpEff effect field at %s:%d. Error was: \"%s\". Field was: \"%s\"",
+                                          snpEffRecord.getChr(), snpEffRecord.getStart(), parsedEffect.getParseError(), effectString));
+            }
+        }
+
+        return parsedEffects;
+    }
+
+    private SnpEffEffect getMostSignificantEffect ( List<SnpEffEffect> effects ) {
+        SnpEffEffect mostSignificantEffect = null;
+
+        for ( SnpEffEffect effect : effects ) {
+            if ( mostSignificantEffect == null ||
+                 effect.isHigherImpactThan(mostSignificantEffect) ) {
+
+                mostSignificantEffect = effect;
+            }
+        }
+
+        return mostSignificantEffect;
+    }
+
+    public List<String> getKeyNames() {
+        return Arrays.asList( InfoFieldKey.EFFECT_KEY.getKeyName(),
+                              InfoFieldKey.IMPACT_KEY.getKeyName(),
+                              InfoFieldKey.FUNCTIONAL_CLASS_KEY.getKeyName(),
+                              InfoFieldKey.CODON_CHANGE_KEY.getKeyName(),
+                              InfoFieldKey.AMINO_ACID_CHANGE_KEY.getKeyName(),
+                              InfoFieldKey.GENE_NAME_KEY.getKeyName(),
+                              InfoFieldKey.GENE_BIOTYPE_KEY.getKeyName(),
+                              InfoFieldKey.TRANSCRIPT_ID_KEY.getKeyName(),
+                              InfoFieldKey.EXON_ID_KEY.getKeyName()
+                            );
+    }
+
+    public List<VCFInfoHeaderLine> getDescriptions() {
+        return Arrays.asList(
+            new VCFInfoHeaderLine(InfoFieldKey.EFFECT_KEY.getKeyName(),            1, VCFHeaderLineType.String,  "The highest-impact effect resulting from the current variant (or one of the highest-impact effects, if there is a tie)"),
+            new VCFInfoHeaderLine(InfoFieldKey.IMPACT_KEY.getKeyName(),            1, VCFHeaderLineType.String,  "Impact of the highest-impact effect resulting from the current variant " + Arrays.toString(EffectImpact.values())),
+            new VCFInfoHeaderLine(InfoFieldKey.FUNCTIONAL_CLASS_KEY.getKeyName(),  1, VCFHeaderLineType.String,  "Functional class of the highest-impact effect resulting from the current variant: " + Arrays.toString(EffectFunctionalClass.values())),
+            new VCFInfoHeaderLine(InfoFieldKey.CODON_CHANGE_KEY.getKeyName(),      1, VCFHeaderLineType.String,  "Old/New codon for the highest-impact effect resulting from the current variant"),
+            new VCFInfoHeaderLine(InfoFieldKey.AMINO_ACID_CHANGE_KEY.getKeyName(), 1, VCFHeaderLineType.String,  "Old/New amino acid for the highest-impact effect resulting from the current variant (in HGVS style)"),
+            new VCFInfoHeaderLine(InfoFieldKey.GENE_NAME_KEY.getKeyName(),         1, VCFHeaderLineType.String,  "Gene name for the highest-impact effect resulting from the current variant"),
+            new VCFInfoHeaderLine(InfoFieldKey.GENE_BIOTYPE_KEY.getKeyName(),      1, VCFHeaderLineType.String,  "Gene biotype for the highest-impact effect resulting from the current variant"),
+            new VCFInfoHeaderLine(InfoFieldKey.TRANSCRIPT_ID_KEY.getKeyName(),     1, VCFHeaderLineType.String,  "Transcript ID for the highest-impact effect resulting from the current variant"),
+            new VCFInfoHeaderLine(InfoFieldKey.EXON_ID_KEY.getKeyName(),           1, VCFHeaderLineType.String,  "Exon ID for the highest-impact effect resulting from the current variant")
+        );
+    }
+
+    /**
+     * Helper class to parse, validate, and store a single SnpEff effect and its metadata.
+     */
+    protected static class SnpEffEffect {
+        private EffectType effect;
+        private EffectImpact impact;
+        private EffectFunctionalClass functionalClass;
+        private String codonChange;
+        private String aminoAcidChange;
+        private String geneName;
+        private String geneBiotype;
+        private EffectCoding coding;
+        private String transcriptID;
+        private String exonID;
+
+        private String parseError = null;
+        private boolean isWellFormed = true;
+
+        private static final int EXPECTED_NUMBER_OF_METADATA_FIELDS = 9;
+        private static final int NUMBER_OF_METADATA_FIELDS_UPON_EITHER_WARNING_OR_ERROR = 10;
+        private static final int NUMBER_OF_METADATA_FIELDS_UPON_BOTH_WARNING_AND_ERROR = 11;
+
+        // If there is either a warning OR an error, it will be in the last field. If there is both
+        // a warning AND an error, the warning will be in the second-to-last field, and the error will
+        // be in the last field.
+        private static final int SNPEFF_WARNING_OR_ERROR_FIELD_UPON_SINGLE_ERROR = NUMBER_OF_METADATA_FIELDS_UPON_EITHER_WARNING_OR_ERROR - 1;
+        private static final int SNPEFF_WARNING_FIELD_UPON_BOTH_WARNING_AND_ERROR = NUMBER_OF_METADATA_FIELDS_UPON_BOTH_WARNING_AND_ERROR - 2;
+        private static final int SNPEFF_ERROR_FIELD_UPON_BOTH_WARNING_AND_ERROR = NUMBER_OF_METADATA_FIELDS_UPON_BOTH_WARNING_AND_ERROR - 1;
+
+        // Position of the field indicating whether the effect is coding or non-coding. This field is used
+        // in selecting the most significant effect, but is not included in the annotations we return
+        // since it can be deduced from the SNPEFF_GENE_BIOTYPE field.
+        private static final int SNPEFF_CODING_FIELD_INDEX = 6;
+
+        public SnpEffEffect ( String effectName, String[] effectMetadata ) {
+            parseEffectName(effectName);
+            parseEffectMetadata(effectMetadata);
+        }
+
+        private void parseEffectName ( String effectName ) {
+            try {
+                effect = EffectType.valueOf(effectName);
+            }
+            catch ( IllegalArgumentException e ) {
+                parseError(String.format("%s is not a recognized effect type", effectName));
+            }
+        }
+
+        private void parseEffectMetadata ( String[] effectMetadata ) {
+            if ( effectMetadata.length != EXPECTED_NUMBER_OF_METADATA_FIELDS ) {
+                if ( effectMetadata.length == NUMBER_OF_METADATA_FIELDS_UPON_EITHER_WARNING_OR_ERROR ) {
+                    parseError(String.format("SnpEff issued the following warning or error: \"%s\"",
+                                             effectMetadata[SNPEFF_WARNING_OR_ERROR_FIELD_UPON_SINGLE_ERROR]));
+                }
+                else if ( effectMetadata.length == NUMBER_OF_METADATA_FIELDS_UPON_BOTH_WARNING_AND_ERROR ) {
+                    parseError(String.format("SnpEff issued the following warning: \"%s\", and the following error: \"%s\"",
+                                             effectMetadata[SNPEFF_WARNING_FIELD_UPON_BOTH_WARNING_AND_ERROR],
+                                             effectMetadata[SNPEFF_ERROR_FIELD_UPON_BOTH_WARNING_AND_ERROR]));
+                }
+                else {
+                    parseError(String.format("Wrong number of effect metadata fields. Expected %d but found %d",
+                                             EXPECTED_NUMBER_OF_METADATA_FIELDS, effectMetadata.length));
+                }
+
+                return;
+            }
+
+            // The impact field will never be empty, and should always contain one of the enumerated values:
+            try {
+                impact = EffectImpact.valueOf(effectMetadata[InfoFieldKey.IMPACT_KEY.getFieldIndex()]);
+            }
+            catch ( IllegalArgumentException e ) {
+                parseError(String.format("Unrecognized value for effect impact: %s", effectMetadata[InfoFieldKey.IMPACT_KEY.getFieldIndex()]));
+            }
+
+            // The functional class field will be empty when the effect has no functional class associated with it:
+            if ( effectMetadata[InfoFieldKey.FUNCTIONAL_CLASS_KEY.getFieldIndex()].trim().length() > 0 ) {
+                try {
+                    functionalClass = EffectFunctionalClass.valueOf(effectMetadata[InfoFieldKey.FUNCTIONAL_CLASS_KEY.getFieldIndex()]);
+                }
+                catch ( IllegalArgumentException e ) {
+                    parseError(String.format("Unrecognized value for effect functional class: %s", effectMetadata[InfoFieldKey.FUNCTIONAL_CLASS_KEY.getFieldIndex()]));
+                }
+            }
+            else {
+                functionalClass = EffectFunctionalClass.NONE;
+            }
+
+            codonChange = effectMetadata[InfoFieldKey.CODON_CHANGE_KEY.getFieldIndex()];
+            aminoAcidChange = effectMetadata[InfoFieldKey.AMINO_ACID_CHANGE_KEY.getFieldIndex()];
+            geneName = effectMetadata[InfoFieldKey.GENE_NAME_KEY.getFieldIndex()];
+            geneBiotype = effectMetadata[InfoFieldKey.GENE_BIOTYPE_KEY.getFieldIndex()];
+
+            // The coding field will be empty when SnpEff has no coding info for the effect:
+            if ( effectMetadata[SNPEFF_CODING_FIELD_INDEX].trim().length() > 0 ) {
+                try {
+                    coding = EffectCoding.valueOf(effectMetadata[SNPEFF_CODING_FIELD_INDEX]);
+                }
+                catch ( IllegalArgumentException e ) {
+                    parseError(String.format("Unrecognized value for effect coding: %s", effectMetadata[SNPEFF_CODING_FIELD_INDEX]));
+                }
+            }
+            else {
+                coding = EffectCoding.UNKNOWN;
+            }
+
+            transcriptID = effectMetadata[InfoFieldKey.TRANSCRIPT_ID_KEY.getFieldIndex()];
+            exonID = effectMetadata[InfoFieldKey.EXON_ID_KEY.getFieldIndex()];
+        }
+
+        private void parseError ( String message ) {
+            isWellFormed = false;
+
+            // Cache only the first error encountered:
+            if ( parseError == null ) {
+                parseError = message;
+            }
+        }
+
+        public boolean isWellFormed() {
+            return isWellFormed;
+        }
+
+        public String getParseError() {
+            return parseError == null ? "" : parseError;
+        }
+
+        public boolean isCoding() {
+            return coding == EffectCoding.CODING;
+        }
+
+        public boolean isHigherImpactThan ( SnpEffEffect other ) {
+            // If one effect is within a coding gene and the other is not, the effect that is
+            // within the coding gene has higher impact:
+
+            if ( isCoding() && ! other.isCoding() ) {
+                return true;
+            }
+            else if ( ! isCoding() && other.isCoding() ) {
+                return false;
+            }
+
+            // Otherwise, both effects are either in or not in a coding gene, so we compare the impacts
+            // of the effects themselves. Effects with the same impact are tie-broken using the
+            // functional class of the effect:
+
+            if ( impact.isHigherImpactThan(other.impact) ) {
+                return true;
+            }
+            else if ( impact.isSameImpactAs(other.impact) ) {
+                return functionalClass.isHigherPriorityThan(other.functionalClass);
+            }
+
+            return false;
+        }
+
+        public Map<String, Object> getAnnotations() {
+            Map<String, Object> annotations = new LinkedHashMap<String, Object>(Utils.optimumHashSize(InfoFieldKey.values().length));
+
+            addAnnotation(annotations, InfoFieldKey.EFFECT_KEY.getKeyName(), effect.toString());
+            addAnnotation(annotations, InfoFieldKey.IMPACT_KEY.getKeyName(), impact.toString());
+            addAnnotation(annotations, InfoFieldKey.FUNCTIONAL_CLASS_KEY.getKeyName(), functionalClass.toString());
+            addAnnotation(annotations, InfoFieldKey.CODON_CHANGE_KEY.getKeyName(), codonChange);
+            addAnnotation(annotations, InfoFieldKey.AMINO_ACID_CHANGE_KEY.getKeyName(), aminoAcidChange);
+            addAnnotation(annotations, InfoFieldKey.GENE_NAME_KEY.getKeyName(), geneName);
+            addAnnotation(annotations, InfoFieldKey.GENE_BIOTYPE_KEY.getKeyName(), geneBiotype);
+            addAnnotation(annotations, InfoFieldKey.TRANSCRIPT_ID_KEY.getKeyName(), transcriptID);
+            addAnnotation(annotations, InfoFieldKey.EXON_ID_KEY.getKeyName(), exonID);
+
+            return annotations;
+        }
+
+        private void addAnnotation ( Map<String, Object> annotations, String keyName, String keyValue ) {
+            // Only add annotations for keys associated with non-empty values:
+            if ( keyValue != null && keyValue.trim().length() > 0 ) {
+                annotations.put(keyName, keyValue);
+            }
+        }
+    }
+}
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/tools/walkers/annotator/SnpEffUtil.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/tools/walkers/annotator/SnpEffUtil.java
new file mode 100644
index 0000000..c82a013
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/tools/walkers/annotator/SnpEffUtil.java
@@ -0,0 +1,154 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.tools.walkers.annotator;
+
+import org.broadinstitute.gatk.tools.walkers.annotator.SnpEff.EffectType;
+
+import java.util.*;
+/**
+ * Created with IntelliJ IDEA.
+ * User: farjoun
+ * Date: 6/5/13
+ * Time: 12:06 PM
+ * To change this template use File | Settings | File Templates.
+ */
+
+/* This class holds a tree representation of the annotations used in snpEff, and provides a mechanism for telling if a
+given annotation is a descendant of another.
+The idea is to be able to stratify effects by large branches and not only the specific
+snpEff annotation that a variant might have. For example if we want to know whether a variant is in CDS
+but if it's marked SYNONYMOUS_CODING or NON_SYNONYMOUS_CODING (or many other options) still imply that its in the CDS.
+
+The hierarchy was determined by Yossi Farjoun with input from Pablo (SNPEFF) and Tim Fennel.
+*/
+
+
+public class SnpEffUtil {
+
+    // A map holding for every child, it's parent.
+    // A node that isn't a key node is a root node.
+    static private final Map<EffectType,EffectType> snpEffectGraph = new HashMap<>();
+
+    //A map from each value of EffectType to a set of it's ancestors
+    static private final Map<EffectType,Set<EffectType>> snpEffectAncestorSet = new HashMap<>();
+
+    static {
+
+
+        //INTERGENIC
+        snpEffectGraph.put(EffectType.UPSTREAM,EffectType.INTERGENIC);
+        snpEffectGraph.put(EffectType.DOWNSTREAM,EffectType.INTERGENIC);
+        snpEffectGraph.put(EffectType.INTERGENIC_CONSERVED,EffectType.INTERGENIC);
+
+        //INTRON
+        snpEffectGraph.put(EffectType.INTRON_CONSERVED,EffectType.INTRON);
+        snpEffectGraph.put(EffectType.SPLICE_SITE_ACCEPTOR,EffectType.INTRON);
+        snpEffectGraph.put(EffectType.SPLICE_SITE_DONOR,EffectType.INTRON);
+
+        //CDS
+        snpEffectGraph.put(EffectType.EXON_DELETED,EffectType.CDS);
+        snpEffectGraph.put(EffectType.SYNONYMOUS_CODING,EffectType.CDS);
+        snpEffectGraph.put(EffectType.NON_SYNONYMOUS_CODING,EffectType.CDS);
+
+        //SYNONYMOUS_CODING
+        snpEffectGraph.put(EffectType.SYNONYMOUS_STOP,EffectType.SYNONYMOUS_CODING);
+        snpEffectGraph.put(EffectType.SYNONYMOUS_START,EffectType.SYNONYMOUS_CODING);
+
+        //NON_SYNONYMOUS_CODING
+        snpEffectGraph.put(EffectType.START_LOST,EffectType.NON_SYNONYMOUS_CODING);
+        snpEffectGraph.put(EffectType.STOP_GAINED,EffectType.NON_SYNONYMOUS_CODING);
+        snpEffectGraph.put(EffectType.STOP_LOST,EffectType.NON_SYNONYMOUS_CODING);
+        snpEffectGraph.put(EffectType.CODON_CHANGE,EffectType.NON_SYNONYMOUS_CODING);
+        snpEffectGraph.put(EffectType.CODON_INSERTION,EffectType.NON_SYNONYMOUS_CODING);
+        snpEffectGraph.put(EffectType.CODON_DELETION,EffectType.NON_SYNONYMOUS_CODING);
+        snpEffectGraph.put(EffectType.CODON_CHANGE_PLUS_CODON_DELETION,EffectType.NON_SYNONYMOUS_CODING);
+        snpEffectGraph.put(EffectType.CODON_CHANGE_PLUS_CODON_INSERTION,EffectType.NON_SYNONYMOUS_CODING);
+        snpEffectGraph.put(EffectType.FRAME_SHIFT,EffectType.NON_SYNONYMOUS_CODING);
+
+        //UTRs
+        snpEffectGraph.put(EffectType.UTR_5_DELETED,EffectType.UTR_5_PRIME);
+        snpEffectGraph.put(EffectType.UTR_3_DELETED,EffectType.UTR_3_PRIME);
+        snpEffectGraph.put(EffectType.START_GAINED,EffectType.UTR_5_PRIME);
+
+        //EXON
+        snpEffectGraph.put(EffectType.UTR_5_PRIME,EffectType.EXON);
+        snpEffectGraph.put(EffectType.UTR_3_PRIME,EffectType.EXON);
+        snpEffectGraph.put(EffectType.CDS,EffectType.EXON);
+
+
+        //TRANSCRIPT
+        snpEffectGraph.put(EffectType.INTRON,EffectType.TRANSCRIPT);
+        snpEffectGraph.put(EffectType.EXON,EffectType.TRANSCRIPT);
+
+        //GENE
+        snpEffectGraph.put(EffectType.TRANSCRIPT,EffectType.GENE);
+        snpEffectGraph.put(EffectType.REGULATION,EffectType.GENE);
+
+        //CHROMOSOME
+        snpEffectGraph.put(EffectType.GENE,EffectType.CHROMOSOME);
+        snpEffectGraph.put(EffectType.INTERGENIC,EffectType.CHROMOSOME);
+    }
+
+    //A helper function that gets the parent set of the set of children
+    private static Set<EffectType> getParentSet(final Set<EffectType> children){
+        final Set<EffectType> parents=new HashSet<>();
+        for(EffectType child:children){
+            final EffectType parent = snpEffectGraph.get(child);
+            if(parent!=null) parents.add(parent);
+        }
+        return parents;
+    }
+
+    //builds the total set of ancestors of a given node
+    private static Set<EffectType> getAncestorSet(final EffectType child, final boolean isSelfIncluded){
+
+        final Set<EffectType> ancestors=new HashSet<>();
+        if(isSelfIncluded) ancestors.add(child);
+
+        Set<EffectType> untraversedNodes=Collections.singleton(child);
+
+        while(!untraversedNodes.isEmpty()){
+            final Set<EffectType> putativeParents = getParentSet(untraversedNodes); //get immediate parents of unexamined set
+            putativeParents.removeAll(ancestors); //remove all known parents, remaining with previously unknown parents
+            ancestors.addAll(putativeParents); // add these parents to growing list of ancestors
+            untraversedNodes=putativeParents; //still need to traverse parents of these nodes
+        }
+        return ancestors;
+    }
+
+    //returns true if the child effect is a subType of the parentEffect (including itself)
+    public static boolean isSubTypeOf(final SnpEff.EffectType childEffect, final SnpEff.EffectType parentEffect){
+
+        Set<EffectType> ancestorSet=snpEffectAncestorSet.get(childEffect);
+
+        if(ancestorSet==null) {  //lazy population of map.
+            ancestorSet = new HashSet<>();
+            ancestorSet.addAll(getAncestorSet(childEffect, true)); //"true" so that a type is considered a subtype of itself
+            snpEffectAncestorSet.put(childEffect, ancestorSet);
+        }
+        return ancestorSet.contains(parentEffect);
+    }
+}
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/tools/walkers/annotator/VariantAnnotator.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/tools/walkers/annotator/VariantAnnotator.java
new file mode 100644
index 0000000..042ba48
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/tools/walkers/annotator/VariantAnnotator.java
@@ -0,0 +1,336 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.tools.walkers.annotator;
+
+import org.broadinstitute.gatk.engine.walkers.*;
+import org.broadinstitute.gatk.utils.commandline.*;
+import org.broadinstitute.gatk.engine.CommandLineGATK;
+import org.broadinstitute.gatk.engine.arguments.DbsnpArgumentCollection;
+import org.broadinstitute.gatk.engine.arguments.StandardVariantContextInputArgumentCollection;
+import org.broadinstitute.gatk.engine.contexts.AlignmentContext;
+import org.broadinstitute.gatk.engine.contexts.AlignmentContextUtils;
+import org.broadinstitute.gatk.engine.contexts.ReferenceContext;
+import org.broadinstitute.gatk.engine.downsampling.DownsampleType;
+import org.broadinstitute.gatk.engine.refdata.RefMetaDataTracker;
+import org.broadinstitute.gatk.tools.walkers.annotator.interfaces.*;
+import org.broadinstitute.gatk.utils.help.HelpConstants;
+import org.broadinstitute.gatk.utils.help.HelpUtils;
+import org.broadinstitute.gatk.utils.variant.GATKVCFUtils;
+import org.broadinstitute.gatk.utils.BaseUtils;
+import org.broadinstitute.gatk.utils.SampleUtils;
+import htsjdk.variant.vcf.*;
+import org.broadinstitute.gatk.utils.help.DocumentedGATKFeature;
+import htsjdk.variant.variantcontext.VariantContext;
+import htsjdk.variant.variantcontext.writer.VariantContextWriter;
+import it.unimi.dsi.fastutil.objects.ObjectOpenHashSet;
+
+import java.util.*;
+
+/**
+ * Annotates variant calls with context information.
+ *
+ * <p>
+ * VariantAnnotator is a GATK tool for annotating variant calls based on their context.
+ * The tool is modular; new annotations can be written easily without modifying VariantAnnotator itself.
+ *
+ * <h3>Input</h3>
+ * <p>
+ * A variant set to annotate and optionally one or more BAM files.
+ * </p>
+ *
+ * <h3>Output</h3>
+ * <p>
+ * An annotated VCF.
+ * </p>
+ *
+ * <h3>Examples</h3>
+ * <pre>
+ * java -Xmx2g -jar GenomeAnalysisTK.jar \
+ *   -R ref.fasta \
+ *   -T VariantAnnotator \
+ *   -I input.bam \
+ *   -o output.vcf \
+ *   -A Coverage \
+ *   --variant input.vcf \
+ *   -L input.vcf \
+ *   --dbsnp dbsnp.vcf
+ * </pre>
+ *
+ */
+ at DocumentedGATKFeature( groupName = HelpConstants.DOCS_CAT_VARMANIP, extraDocs = {CommandLineGATK.class} )
+ at Requires(value={})
+ at Allows(value={DataSource.READS, DataSource.REFERENCE})
+ at Reference(window=@Window(start=-50,stop=50))
+ at Downsample(by= DownsampleType.BY_SAMPLE, toCoverage=250)
+ at By(DataSource.REFERENCE)
+public class VariantAnnotator extends RodWalker<Integer, Integer> implements AnnotatorCompatible, TreeReducible<Integer> {
+
+    @ArgumentCollection
+    protected StandardVariantContextInputArgumentCollection variantCollection = new StandardVariantContextInputArgumentCollection();
+
+    /**
+     * The INFO field will be annotated with information on the most biologically significant effect
+     * listed in the SnpEff output file for each variant.
+     */
+    @Input(fullName="snpEffFile", shortName = "snpEffFile", doc="A SnpEff output file from which to add annotations", required=false)
+    public RodBinding<VariantContext> snpEffFile;
+    public RodBinding<VariantContext> getSnpEffRodBinding() { return snpEffFile; }
+
+    /**
+      * rsIDs from this file are used to populate the ID column of the output.  Also, the DB INFO flag will be set when appropriate.
+      */
+    @ArgumentCollection
+    protected DbsnpArgumentCollection dbsnp = new DbsnpArgumentCollection();
+    public RodBinding<VariantContext> getDbsnpRodBinding() { return dbsnp.dbsnp; }
+
+    /**
+      * If a record in the 'variant' track overlaps with a record from the provided comp track, the INFO field will be
+      * annotated as such in the output with the track name (e.g. -comp:FOO will have 'FOO' in the INFO field).
+      * Records that are filtered in the comp track will be ignored. Note that 'dbSNP' has been special-cased
+      * (see the --dbsnp argument).
+      */
+    @Input(fullName="comp", shortName = "comp", doc="comparison VCF file", required=false)
+    public List<RodBinding<VariantContext>> comps = Collections.emptyList();
+    public List<RodBinding<VariantContext>> getCompRodBindings() { return comps; }
+
+    /**
+      * An external resource VCF file or files from which to annotate.
+      *
+      * Use this option to add annotations from a resource file to the output.
+      * For example, if you want to annotate your callset with the AC field value from a VCF file named
+      * 'resource_file.vcf', you tag it with '-resource:my_resource resource_file.vcf' and you additionally specify
+      * '-E my_resource.AC' (-E is short for --expression, also documented on this page). In the resulting output
+      * VCF, any records for which there is a record at the same position in the resource file will be annotated with
+      * 'my_resource.AC=N'. Note that if there are multiple records in the resource file that overlap the given
+      * position, one is chosen randomly.
+      */
+    @Input(fullName="resource", shortName = "resource", doc="External resource VCF file", required=false)
+    public List<RodBinding<VariantContext>> resources = Collections.emptyList();
+    public List<RodBinding<VariantContext>> getResourceRodBindings() { return resources; }
+
+    @Output(doc="File to which variants should be written")
+    protected VariantContextWriter vcfWriter = null;
+
+    /**
+     * See the --list argument to view available annotations.
+     */
+    @Argument(fullName="annotation", shortName="A", doc="One or more specific annotations to apply to variant calls", required=false)
+    protected List<String> annotationsToUse = new ArrayList<>();
+
+    /**
+     * Note that this argument has higher priority than the -A or -G arguments,
+     * so annotations will be excluded even if they are explicitly included with the other options.
+     */
+    @Argument(fullName="excludeAnnotation", shortName="XA", doc="One or more specific annotations to exclude", required=false)
+    protected List<String> annotationsToExclude = new ArrayList<>();
+
+    /**
+     * If specified, all available annotations in the group will be applied. See the VariantAnnotator -list argument
+     * to view available groups. Keep in mind that RODRequiringAnnotations are not intended to be used as a group,
+     * because they require specific ROD inputs.
+     */
+    @Argument(fullName="group", shortName="G", doc="One or more classes/groups of annotations to apply to variant calls", required=false)
+    protected List<String> annotationGroupsToUse = new ArrayList<>();
+
+    /**
+     * This option enables you to add annotations from one VCF to another.
+     *
+     * For example, if you want to annotate your callset with the AC field value from a VCF file named
+     * 'resource_file.vcf', you tag it with '-resource:my_resource resource_file.vcf' (see the -resource argument, also
+     * documented on this page) and you specify '-E my_resource.AC'. In the resulting output VCF, any records for
+     * which there is a record at the same position in the resource file will be annotated with 'my_resource.AC=N'.
+     * Note that if there are multiple records in the resource file that overlap the given position, one is chosen
+     * randomly.
+     */
+    @Argument(fullName="expression", shortName="E", doc="One or more specific expressions to apply to variant calls", required=false)
+    protected Set<String> expressionsToUse = new ObjectOpenHashSet();
+
+    /**
+     * You can use the -XL argument in combination with this one to exclude specific annotations.Note that some
+     * annotations may not be actually applied if they are not applicable to the data provided or if they are
+     * unavailable to the tool (e.g. there are several annotations that are currently not hooked up to
+     * HaplotypeCaller). At present no error or warning message will be provided, the annotation will simply be
+     * skipped silently. You can check the output VCF header to see which annotations were actually applied (although
+     * this does not guarantee that the annotation was applied to all records in the VCF, since some annotations have
+     * additional requirements, e.g. minimum number of samples or heterozygous sites only -- see the documentation
+     * for individual annotations' requirements).
+     */
+    @Argument(fullName="useAllAnnotations", shortName="all", doc="Use all possible annotations (not for the faint of heart)", required=false)
+    protected Boolean USE_ALL_ANNOTATIONS = false;
+
+    /**
+     * Note that the --list argument requires a fully resolved and correct command-line to work. As an alternative, you can use ListAnnotations (see Help Utilities).
+     */
+    @Argument(fullName="list", shortName="ls", doc="List the available annotations and exit", required=false)
+    protected Boolean LIST = false;
+
+    /**
+     * By default, the dbSNP ID is added only when the ID field in the variant VCF is empty (not already annotated).
+     * This argument allows you to override that behavior. This is used in conjuction with the -dbsnp argument.
+     */
+    @Argument(fullName="alwaysAppendDbsnpId", shortName="alwaysAppendDbsnpId", doc="Append the dbSNP ID even when the variant VCF already has the ID field populated", required=false)
+    protected Boolean ALWAYS_APPEND_DBSNP_ID = false;
+    public boolean alwaysAppendDbsnpId() { return ALWAYS_APPEND_DBSNP_ID; }
+
+    @Argument(fullName="MendelViolationGenotypeQualityThreshold",shortName="mvq",required=false,doc="The genotype quality threshold in order to annotate mendelian violation ratio")
+    public double minGenotypeQualityP = 0.0;
+
+    private VariantAnnotatorEngine engine;
+
+    /**
+     * Prepare the output file and the list of available features.
+     */
+    public void initialize() {
+
+        if ( LIST ) {
+            HelpUtils.listAnnotations();
+            System.exit(0);
+        }
+
+        // get the list of all sample names from the variant VCF input rod, if applicable
+        final List<String> rodName = Arrays.asList(variantCollection.variants.getName());
+        final Set<String> samples = SampleUtils.getUniqueSamplesFromRods(getToolkit(), rodName);
+
+        if ( USE_ALL_ANNOTATIONS )
+            engine = new VariantAnnotatorEngine(annotationsToExclude, this, getToolkit());
+        else
+            engine = new VariantAnnotatorEngine(annotationGroupsToUse, annotationsToUse, annotationsToExclude, this, getToolkit());
+        engine.initializeExpressions(expressionsToUse);
+
+        // setup the header fields
+        // note that if any of the definitions conflict with our new ones, then we want to overwrite the old ones
+        final Set<VCFHeaderLine> hInfo = new HashSet<>();
+        hInfo.addAll(engine.getVCFAnnotationDescriptions());
+        for ( final VCFHeaderLine line : GATKVCFUtils.getHeaderFields(getToolkit(), Arrays.asList(variantCollection.variants.getName())) ) {
+            if ( isUniqueHeaderLine(line, hInfo) )
+                hInfo.add(line);
+        }
+        // for the expressions, pull the info header line from the header of the resource rod
+        for ( final VariantAnnotatorEngine.VAExpression expression : engine.getRequestedExpressions() ) {
+            // special case the ID field
+            if ( expression.fieldName.equals("ID") ) {
+                hInfo.add(new VCFInfoHeaderLine(expression.fullName, 1, VCFHeaderLineType.String, "ID field transferred from external VCF resource"));
+                continue;
+            }
+            VCFInfoHeaderLine targetHeaderLine = null;
+            for ( final VCFHeaderLine line : GATKVCFUtils.getHeaderFields(getToolkit(), Arrays.asList(expression.binding.getName())) ) {
+                if ( line instanceof VCFInfoHeaderLine ) {
+                    final VCFInfoHeaderLine infoline = (VCFInfoHeaderLine)line;
+                    if ( infoline.getID().equals(expression.fieldName) ) {
+                        targetHeaderLine = infoline;
+                        break;
+                    }
+                }
+            }
+
+            if ( targetHeaderLine != null ) {
+                if ( targetHeaderLine.getCountType() == VCFHeaderLineCount.INTEGER )
+                    hInfo.add(new VCFInfoHeaderLine(expression.fullName, targetHeaderLine.getCount(), targetHeaderLine.getType(), targetHeaderLine.getDescription()));
+                else
+                    hInfo.add(new VCFInfoHeaderLine(expression.fullName, targetHeaderLine.getCountType(), targetHeaderLine.getType(), targetHeaderLine.getDescription()));
+            } else {
+                hInfo.add(new VCFInfoHeaderLine(expression.fullName, VCFHeaderLineCount.UNBOUNDED, VCFHeaderLineType.String, "Value transferred from another external VCF resource"));
+            }
+        }
+
+        engine.invokeAnnotationInitializationMethods(hInfo);
+
+        VCFHeader vcfHeader = new VCFHeader(hInfo, samples);
+        vcfWriter.writeHeader(vcfHeader);
+    }
+
+    public static boolean isUniqueHeaderLine(VCFHeaderLine line, Set<VCFHeaderLine> currentSet) {
+        if ( !(line instanceof VCFCompoundHeaderLine) )
+            return true;
+
+        for ( VCFHeaderLine hLine : currentSet ) {
+            if ( hLine instanceof VCFCompoundHeaderLine && ((VCFCompoundHeaderLine)line).sameLineTypeAndName((VCFCompoundHeaderLine)hLine) )
+                return false;
+        }
+
+        return true;
+    }
+
+    /**
+     * We want reads that span deletions
+     *
+     * @return true
+     */
+    public boolean includeReadsWithDeletionAtLoci() { return true; }
+
+    /**
+     * For each site of interest, annotate based on the requested annotation types
+     *
+     * @param tracker  the meta-data tracker
+     * @param ref      the reference base
+     * @param context  the context for the given locus
+     * @return 1 if the locus was successfully processed, 0 if otherwise
+     */
+    public Integer map(RefMetaDataTracker tracker, ReferenceContext ref, AlignmentContext context) {
+        if ( tracker == null )
+            return 0;
+
+        Collection<VariantContext> VCs = tracker.getValues(variantCollection.variants, context.getLocation());
+        if ( VCs.size() == 0 )
+            return 0;
+
+        Collection<VariantContext> annotatedVCs = VCs;
+
+        // if the reference base is not ambiguous, we can annotate
+        Map<String, AlignmentContext> stratifiedContexts;
+        if ( BaseUtils.simpleBaseToBaseIndex(ref.getBase()) != -1 ) {
+            stratifiedContexts = AlignmentContextUtils.splitContextBySampleName(context.getBasePileup());
+            annotatedVCs = new ArrayList<>(VCs.size());
+            for ( VariantContext vc : VCs )
+                annotatedVCs.add(engine.annotateContext(tracker, ref, stratifiedContexts, vc));
+        }
+
+        for ( VariantContext annotatedVC : annotatedVCs )
+            vcfWriter.add(annotatedVC);
+
+        return 1;
+    }
+
+    @Override
+    public Integer reduceInit() { return 0; }
+
+    @Override
+    public Integer reduce(Integer value, Integer sum) { return value + sum; }
+
+    @Override
+    public Integer treeReduce(Integer lhs, Integer rhs) {
+        return lhs + rhs;
+    }
+
+    /**
+     * Tell the user the number of loci processed and close out the new variants file.
+     *
+     * @param result  the number of loci seen.
+     */
+    public void onTraversalDone(Integer result) {
+        logger.info("Processed " + result + " loci.\n");
+    }
+}
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/tools/walkers/annotator/VariantAnnotatorEngine.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/tools/walkers/annotator/VariantAnnotatorEngine.java
new file mode 100644
index 0000000..60c8824
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/tools/walkers/annotator/VariantAnnotatorEngine.java
@@ -0,0 +1,304 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.tools.walkers.annotator;
+
+import com.google.java.contract.Ensures;
+import com.google.java.contract.Requires;
+import htsjdk.variant.variantcontext.*;
+import htsjdk.variant.vcf.*;
+import org.broadinstitute.gatk.engine.GenomeAnalysisEngine;
+import org.broadinstitute.gatk.engine.contexts.AlignmentContext;
+import org.broadinstitute.gatk.engine.contexts.ReferenceContext;
+import org.broadinstitute.gatk.engine.refdata.RefMetaDataTracker;
+import org.broadinstitute.gatk.tools.walkers.annotator.interfaces.*;
+import org.broadinstitute.gatk.utils.GenomeLoc;
+import org.broadinstitute.gatk.utils.commandline.RodBinding;
+import org.broadinstitute.gatk.utils.exceptions.UserException;
+import org.broadinstitute.gatk.utils.genotyper.PerReadAlleleLikelihoodMap;
+import org.broadinstitute.gatk.utils.genotyper.ReadLikelihoods;
+
+import java.util.*;
+
+
+public class VariantAnnotatorEngine {
+    private List<InfoFieldAnnotation> requestedInfoAnnotations = Collections.emptyList();
+    private List<GenotypeAnnotation> requestedGenotypeAnnotations = Collections.emptyList();
+    private List<VAExpression> requestedExpressions = new ArrayList<>();
+
+    private final AnnotatorCompatible walker;
+    private final GenomeAnalysisEngine toolkit;
+
+    VariantOverlapAnnotator variantOverlapAnnotator = null;
+
+    protected static class VAExpression {
+
+        public String fullName, fieldName;
+        public RodBinding<VariantContext> binding;
+
+        public VAExpression(String fullExpression, List<RodBinding<VariantContext>> bindings) {
+            final int indexOfDot = fullExpression.lastIndexOf(".");
+            if ( indexOfDot == -1 )
+                throw new UserException.BadArgumentValue(fullExpression, "it should be in rodname.value format");
+
+            fullName = fullExpression;
+            fieldName = fullExpression.substring(indexOfDot+1);
+
+            final String bindingName = fullExpression.substring(0, indexOfDot);
+            for ( final RodBinding<VariantContext> rod : bindings ) {
+                if ( rod.getName().equals(bindingName) ) {
+                    binding = rod;
+                    break;
+                }
+            }
+        }
+    }
+
+    // use this constructor if you want all possible annotations
+    public VariantAnnotatorEngine(List<String> annotationsToExclude, AnnotatorCompatible walker, GenomeAnalysisEngine toolkit) {
+        this.walker = walker;
+        this.toolkit = toolkit;
+        requestedInfoAnnotations = AnnotationInterfaceManager.createAllInfoFieldAnnotations();
+        requestedGenotypeAnnotations = AnnotationInterfaceManager.createAllGenotypeAnnotations();
+        excludeAnnotations(annotationsToExclude);
+        initializeDBs(toolkit);
+    }
+
+    // use this constructor if you want to select specific annotations (and/or interfaces)
+    public VariantAnnotatorEngine(List<String> annotationGroupsToUse, List<String> annotationsToUse, List<String> annotationsToExclude, AnnotatorCompatible walker, GenomeAnalysisEngine toolkit) {
+        this.walker = walker;
+        this.toolkit = toolkit;
+        initializeAnnotations(annotationGroupsToUse, annotationsToUse, annotationsToExclude);
+        initializeDBs(toolkit);
+    }
+
+    // select specific expressions to use
+    public void initializeExpressions(Set<String> expressionsToUse) {
+        // set up the expressions
+        for ( final String expression : expressionsToUse )
+            requestedExpressions.add(new VAExpression(expression, walker.getResourceRodBindings()));
+    }
+
+    protected List<VAExpression> getRequestedExpressions() { return requestedExpressions; }
+
+    private void initializeAnnotations(List<String> annotationGroupsToUse, List<String> annotationsToUse, List<String> annotationsToExclude) {
+        AnnotationInterfaceManager.validateAnnotations(annotationGroupsToUse, annotationsToUse);
+        requestedInfoAnnotations = AnnotationInterfaceManager.createInfoFieldAnnotations(annotationGroupsToUse, annotationsToUse);
+        requestedGenotypeAnnotations = AnnotationInterfaceManager.createGenotypeAnnotations(annotationGroupsToUse, annotationsToUse);
+        excludeAnnotations(annotationsToExclude);
+    }
+
+    private void excludeAnnotations(List<String> annotationsToExclude) {
+        if ( annotationsToExclude.size() == 0 )
+            return;
+
+        final List<InfoFieldAnnotation> tempRequestedInfoAnnotations = new ArrayList<>(requestedInfoAnnotations.size());
+        for ( final InfoFieldAnnotation annotation : requestedInfoAnnotations ) {
+            if ( !annotationsToExclude.contains(annotation.getClass().getSimpleName()) )
+                tempRequestedInfoAnnotations.add(annotation);
+        }
+        requestedInfoAnnotations = tempRequestedInfoAnnotations;
+
+        final List<GenotypeAnnotation> tempRequestedGenotypeAnnotations = new ArrayList<>(requestedGenotypeAnnotations.size());
+        for ( final GenotypeAnnotation annotation : requestedGenotypeAnnotations ) {
+            if ( !annotationsToExclude.contains(annotation.getClass().getSimpleName()) )
+                tempRequestedGenotypeAnnotations.add(annotation);
+        }
+        requestedGenotypeAnnotations = tempRequestedGenotypeAnnotations;
+    }
+
+    private void initializeDBs(final GenomeAnalysisEngine engine) {
+        // check to see whether comp rods were included
+        RodBinding<VariantContext> dbSNPBinding = walker.getDbsnpRodBinding();
+        if ( dbSNPBinding != null && ! dbSNPBinding.isBound() )
+            dbSNPBinding = null;
+
+        final Map<RodBinding<VariantContext>, String> overlapBindings = new LinkedHashMap<>();
+        for ( final RodBinding<VariantContext> b : walker.getCompRodBindings())
+            if ( b.isBound() ) overlapBindings.put(b, b.getName());
+        if ( dbSNPBinding != null && ! overlapBindings.keySet().contains(VCFConstants.DBSNP_KEY) )
+            overlapBindings.put(dbSNPBinding, VCFConstants.DBSNP_KEY); // add overlap detection with DBSNP by default
+
+        variantOverlapAnnotator = new VariantOverlapAnnotator(dbSNPBinding, overlapBindings, engine.getGenomeLocParser());
+    }
+
+    public void invokeAnnotationInitializationMethods( final Set<VCFHeaderLine> headerLines ) {
+        for ( final VariantAnnotatorAnnotation annotation : requestedInfoAnnotations ) {
+            annotation.initialize(walker, toolkit, headerLines);
+        }
+
+        for ( final VariantAnnotatorAnnotation annotation : requestedGenotypeAnnotations ) {
+            annotation.initialize(walker, toolkit, headerLines);
+        }
+    }
+
+    public Set<VCFHeaderLine> getVCFAnnotationDescriptions() {
+        final Set<VCFHeaderLine> descriptions = new HashSet<>();
+
+        for ( final InfoFieldAnnotation annotation : requestedInfoAnnotations )
+            descriptions.addAll(annotation.getDescriptions());
+        for ( final GenotypeAnnotation annotation : requestedGenotypeAnnotations )
+            descriptions.addAll(annotation.getDescriptions());
+        for ( final String db : variantOverlapAnnotator.getOverlapNames() ) {
+            if ( VCFStandardHeaderLines.getInfoLine(db, false) != null )
+                descriptions.add(VCFStandardHeaderLines.getInfoLine(db));
+            else
+                descriptions.add(new VCFInfoHeaderLine(db, 0, VCFHeaderLineType.Flag, db + " Membership"));
+        }
+
+        return descriptions;
+    }
+
+    public VariantContext annotateContext(final RefMetaDataTracker tracker,
+                                          final ReferenceContext ref,
+                                          final Map<String, AlignmentContext> stratifiedContexts,
+                                          final VariantContext vc) {
+        return annotateContext(tracker, ref, stratifiedContexts, vc, null);
+    }
+
+    public VariantContext annotateContext(final RefMetaDataTracker tracker,
+                                          final ReferenceContext ref,
+                                          final Map<String, AlignmentContext> stratifiedContexts,
+                                          final VariantContext vc,
+                                          final Map<String,PerReadAlleleLikelihoodMap> perReadAlleleLikelihoodMap) {
+        final Map<String, Object> infoAnnotations = new LinkedHashMap<>(vc.getAttributes());
+
+        // annotate expressions where available
+        annotateExpressions(tracker, ref.getLocus(), infoAnnotations);
+
+        // go through all the requested info annotationTypes
+        for ( final InfoFieldAnnotation annotationType : requestedInfoAnnotations ) {
+            final Map<String, Object> annotationsFromCurrentType = annotationType.annotate(tracker, walker, ref, stratifiedContexts, vc, perReadAlleleLikelihoodMap);
+            if ( annotationsFromCurrentType != null )
+                infoAnnotations.putAll(annotationsFromCurrentType);
+        }
+
+        // generate a new annotated VC
+        final VariantContextBuilder builder = new VariantContextBuilder(vc).attributes(infoAnnotations);
+
+        // annotate genotypes, creating another new VC in the process
+        final VariantContext annotated = builder.genotypes(annotateGenotypes(tracker, ref, stratifiedContexts, vc, perReadAlleleLikelihoodMap)).make();
+
+        // annotate db occurrences
+        return annotateDBs(tracker, annotated);
+    }
+
+    public VariantContext annotateContextForActiveRegion(final RefMetaDataTracker tracker,
+                                                         final ReadLikelihoods<Allele> readLikelihoods,
+                                                         final VariantContext vc) {
+        //TODO we transform the read-likelihood into the Map^2 previous version for the sake of not changing of not changing annotation interface.
+        //TODO should we change those interfaces?
+        final Map<String, PerReadAlleleLikelihoodMap> annotationLikelihoods = readLikelihoods.toPerReadAlleleLikelihoodMap();
+        return annotateContextForActiveRegion(tracker, annotationLikelihoods, vc);
+    }
+
+    public VariantContext annotateContextForActiveRegion(final RefMetaDataTracker tracker,
+                                                         final Map<String, PerReadAlleleLikelihoodMap> perReadAlleleLikelihoodMap,
+                                                         final VariantContext vc) {
+        final Map<String, Object> infoAnnotations = new LinkedHashMap<>(vc.getAttributes());
+
+        // go through all the requested info annotationTypes
+        for ( final InfoFieldAnnotation annotationType : requestedInfoAnnotations ) {
+            if ( !(annotationType instanceof ActiveRegionBasedAnnotation) )
+                continue;
+
+            final Map<String, Object> annotationsFromCurrentType = annotationType.annotate(perReadAlleleLikelihoodMap, vc);
+            if ( annotationsFromCurrentType != null ) {
+                infoAnnotations.putAll(annotationsFromCurrentType);
+            }
+        }
+
+        // generate a new annotated VC
+        final VariantContextBuilder builder = new VariantContextBuilder(vc).attributes(infoAnnotations);
+
+        // annotate genotypes, creating another new VC in the process
+        final VariantContext annotated = builder.genotypes(annotateGenotypes(null, null, null, vc, perReadAlleleLikelihoodMap)).make();
+
+        // annotate db occurrences
+        return annotateDBs(tracker, annotated);
+    }
+
+    /**
+     * Annotate the ID field and other DBs for the given Variant Context
+     *
+     * @param tracker  ref meta data tracker (cannot be null)
+     * @param vc       variant context to annotate
+     * @return non-null annotated version of vc
+     */
+    @Requires({"tracker != null && loc != null && vc != null && infoAnnotations != null"})
+    @Ensures("result != null")
+    private VariantContext annotateDBs(final RefMetaDataTracker tracker, VariantContext vc) {
+        return variantOverlapAnnotator.annotateOverlaps(tracker, variantOverlapAnnotator.annotateRsID(tracker, vc));
+    }
+
+    private void annotateExpressions(final RefMetaDataTracker tracker, final GenomeLoc loc, final Map<String, Object> infoAnnotations) {
+        for ( final VAExpression expression : requestedExpressions ) {
+            final Collection<VariantContext> VCs = tracker.getValues(expression.binding, loc);
+            if ( VCs.size() == 0 )
+                continue;
+
+            final VariantContext vc = VCs.iterator().next();
+            // special-case the ID field
+            if ( expression.fieldName.equals("ID") ) {
+                if ( vc.hasID() )
+                    infoAnnotations.put(expression.fullName, vc.getID());
+            } else if (expression.fieldName.equals("ALT")) {
+                infoAnnotations.put(expression.fullName, vc.getAlternateAllele(0).getDisplayString());
+
+            } else if ( vc.hasAttribute(expression.fieldName) ) {
+                    infoAnnotations.put(expression.fullName, vc.getAttribute(expression.fieldName));
+
+            }
+        }
+    }
+
+
+    private GenotypesContext annotateGenotypes(final RefMetaDataTracker tracker,
+                                               final ReferenceContext ref, final Map<String, AlignmentContext> stratifiedContexts,
+                                               final VariantContext vc,
+                                               final Map<String,PerReadAlleleLikelihoodMap> stratifiedPerReadAlleleLikelihoodMap) {
+        if ( requestedGenotypeAnnotations.isEmpty() )
+            return vc.getGenotypes();
+
+        final GenotypesContext genotypes = GenotypesContext.create(vc.getNSamples());
+        for ( final Genotype genotype : vc.getGenotypes() ) {
+            AlignmentContext context = null;
+            PerReadAlleleLikelihoodMap perReadAlleleLikelihoodMap = null;
+            if (stratifiedContexts != null)
+                context = stratifiedContexts.get(genotype.getSampleName());
+            if (stratifiedPerReadAlleleLikelihoodMap != null)
+                perReadAlleleLikelihoodMap = stratifiedPerReadAlleleLikelihoodMap.get(genotype.getSampleName());
+
+
+            final GenotypeBuilder gb = new GenotypeBuilder(genotype);
+            for ( final GenotypeAnnotation annotation : requestedGenotypeAnnotations ) {
+                annotation.annotate(tracker, walker, ref, context, vc, genotype, gb, perReadAlleleLikelihoodMap);
+            }
+            genotypes.add(gb.make());
+        }
+
+        return genotypes;
+    }
+}
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/tools/walkers/annotator/VariantOverlapAnnotator.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/tools/walkers/annotator/VariantOverlapAnnotator.java
new file mode 100644
index 0000000..03f707f
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/tools/walkers/annotator/VariantOverlapAnnotator.java
@@ -0,0 +1,224 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.tools.walkers.annotator;
+
+import org.broadinstitute.gatk.utils.commandline.RodBinding;
+import org.broadinstitute.gatk.engine.refdata.RefMetaDataTracker;
+import org.broadinstitute.gatk.utils.GenomeLoc;
+import org.broadinstitute.gatk.utils.GenomeLocParser;
+import htsjdk.variant.variantcontext.Allele;
+import htsjdk.variant.variantcontext.VariantContext;
+import htsjdk.variant.variantcontext.VariantContextBuilder;
+import htsjdk.variant.vcf.VCFConstants;
+
+import java.util.*;
+
+/**
+ * Annotate the ID field and attribute overlap FLAGs for a VariantContext against a RefMetaDataTracker or a list
+ * of VariantContexts
+ */
+public final class VariantOverlapAnnotator {
+    final RodBinding<VariantContext> dbSNPBinding;
+    final Map<RodBinding<VariantContext>, String> overlapBindings;
+    final GenomeLocParser genomeLocParser;
+
+    /**
+     * Create a new VariantOverlapAnnotator without overall bindings
+     *
+     * @see #VariantOverlapAnnotator(org.broadinstitute.gatk.utils.commandline.RodBinding, java.util.Map, org.broadinstitute.gatk.utils.GenomeLocParser)
+     */
+    public VariantOverlapAnnotator(RodBinding<VariantContext> dbSNPBinding, GenomeLocParser genomeLocParser) {
+        this(dbSNPBinding, Collections.<RodBinding<VariantContext>, String>emptyMap(), genomeLocParser);
+    }
+
+    /**
+     * Create a new VariantOverlapAnnotator
+     *
+     * @param dbSNPBinding the RodBinding to use for updating ID field values, or null if that behavior isn't desired
+     * @param overlapBindings a map of RodBindings / name to use for overlap annotation.  Each binding will be used to
+     *                        add name => true for variants that overlap with variants found to a
+     *                        RefMetaDataTracker at each location.  Can be empty but not null
+     * @param genomeLocParser the genome loc parser we'll use to create GenomeLocs for VariantContexts
+     */
+    public VariantOverlapAnnotator(RodBinding<VariantContext> dbSNPBinding, Map<RodBinding<VariantContext>, String> overlapBindings, GenomeLocParser genomeLocParser) {
+        if ( overlapBindings == null ) throw new IllegalArgumentException("overlapBindings cannot be null");
+        if ( genomeLocParser == null ) throw new IllegalArgumentException("genomeLocParser cannot be null");
+
+        this.dbSNPBinding = dbSNPBinding;
+        this.overlapBindings = overlapBindings;
+        this.genomeLocParser = genomeLocParser;
+    }
+
+    /**
+     * Update rsID in vcToAnnotate with rsIDs from dbSNPBinding fetched from tracker
+     * @see #annotateOverlap(java.util.List, String, htsjdk.variant.variantcontext.VariantContext)
+     *
+     * @param tracker non-null tracker, which we will use to update the rsID of vcToAnnotate
+     *                for VariantContexts bound to dbSNPBinding that start at vcToAnnotate
+     * @param vcToAnnotate a variant context to annotate
+     * @return a VariantContext (may be == to vcToAnnotate) with updated rsID value
+     */
+    public VariantContext annotateRsID(final RefMetaDataTracker tracker, final VariantContext vcToAnnotate) {
+        if ( dbSNPBinding != null ) {
+            final GenomeLoc loc = getLoc(vcToAnnotate);
+            return annotateRsID(tracker.getValues(dbSNPBinding, loc), vcToAnnotate);
+        } else {
+            return vcToAnnotate;
+        }
+    }
+
+    /**
+     * Update rsID of vcToAnnotate with rsID match found in vcsAtLoc, if one exists
+     *
+     * @param vcsAtLoc a list of variant contexts starting at this location to use as sources for rsID values
+     * @param vcToAnnotate a variant context to annotate
+     * @return a VariantContext (may be == to vcToAnnotate) with updated rsID value
+     */
+    public VariantContext annotateRsID(final List<VariantContext> vcsAtLoc, final VariantContext vcToAnnotate ) {
+        final String rsID = getRsID(vcsAtLoc, vcToAnnotate);
+
+        // add the ID if appropriate
+        if ( rsID != null ) {
+            final VariantContextBuilder vcb = new VariantContextBuilder(vcToAnnotate);
+
+            if ( ! vcToAnnotate.hasID() ) {
+                return vcb.id(rsID).make();
+            } else if ( ! vcToAnnotate.getID().contains(rsID) ) {
+                return vcb.id(vcToAnnotate.getID() + VCFConstants.ID_FIELD_SEPARATOR + rsID).make();
+            } // falling through to return VC lower down
+        }
+
+        // nothing to do, just return vc
+        return vcToAnnotate;
+    }
+
+    private GenomeLoc getLoc(final VariantContext vc) {
+        return genomeLocParser.createGenomeLoc(vc);
+    }
+
+    /**
+     * Add overlap attributes to vcToAnnotate against all overlapBindings in tracker
+     *
+     * @see #annotateOverlap(java.util.List, String, htsjdk.variant.variantcontext.VariantContext)
+     * for more information
+     *
+     * @param tracker non-null tracker, which we will use to update the rsID of vcToAnnotate
+     *                for VariantContexts bound to dbSNPBinding that start at vcToAnnotate
+     * @param vcToAnnotate a variant context to annotate
+     * @return a VariantContext (may be == to vcToAnnotate) with updated overlaps update fields value
+     */
+    public VariantContext annotateOverlaps(final RefMetaDataTracker tracker, final VariantContext vcToAnnotate) {
+        if ( overlapBindings.isEmpty() ) return vcToAnnotate;
+
+        VariantContext annotated = vcToAnnotate;
+        final GenomeLoc loc = getLoc(vcToAnnotate);
+        for ( final Map.Entry<RodBinding<VariantContext>, String> overlapBinding : overlapBindings.entrySet() ) {
+            annotated = annotateOverlap(tracker.getValues(overlapBinding.getKey(), loc), overlapBinding.getValue(), annotated);
+        }
+
+        return annotated;
+    }
+
+    /**
+     * Add overlaps flag attributes to vcToAnnotate binding overlapTestVCs.getSource() => true if
+     * an overlapping variant context can be found in overlapTestVCs with vcToAnnotate
+     *
+     * Overlaps here means that the reference alleles are the same and at least one alt
+     * allele in vcToAnnotate is equals to one of the alt alleles in overlapTestVCs
+     *
+     * @param overlapTestVCs a non-null list of potential overlaps that start at vcToAnnotate
+     * @param attributeKey the key to set to true in the attribute map for vcToAnnotate if it overlaps
+     * @param vcToAnnotate a non-null VariantContext to annotate
+     * @return
+     */
+    public VariantContext annotateOverlap(final List<VariantContext> overlapTestVCs, final String attributeKey, VariantContext vcToAnnotate) {
+        if ( overlapBindings.isEmpty() ) return vcToAnnotate;
+
+        final boolean overlaps = overlaps(overlapTestVCs, vcToAnnotate);
+        if ( overlaps ) {
+            return new VariantContextBuilder(vcToAnnotate).attribute(attributeKey, true).make();
+        } else {
+            return vcToAnnotate;
+        }
+    }
+
+    /**
+     * Returns the ID field of the first VariantContext in rsIDSourceVCs that has the same reference allele
+     * as vcToAnnotate and all of the alternative alleles in vcToAnnotate.
+     *
+     * Doesn't require vcToAnnotate to be a complete match, so
+     *
+     * A/C/G in VC in rsIDSourceVCs
+     *
+     * would match the a VC with A/C but not A/T.  Also we don't require all alleles to match
+     * so we would also match A/C/T to A/C/G.
+     *
+     * Will only match rsIDSourceVCs that aren't failing filters.
+     *
+     * @param rsIDSourceVCs a non-null list of potential overlaps that start at vcToAnnotate
+     * @param vcToAnnotate a non-null VariantContext to annotate
+     * @return a String to use for the rsID from rsIDSourceVCs if one matches, or null if none matches
+     */
+    private String getRsID(final List<VariantContext> rsIDSourceVCs, final VariantContext vcToAnnotate) {
+        if ( rsIDSourceVCs == null ) throw new IllegalArgumentException("rsIDSourceVCs cannot be null");
+        if ( vcToAnnotate == null ) throw new IllegalArgumentException("vcToAnnotate cannot be null");
+
+        for ( final VariantContext vcComp : rsIDSourceVCs ) {
+            if ( vcComp.isFiltered() ) continue; // don't process any failed VCs
+
+            if ( ! vcComp.getChr().equals(vcToAnnotate.getChr()) || vcComp.getStart() != vcToAnnotate.getStart() )
+                throw new IllegalArgumentException("source rsID VariantContext " + vcComp + " doesn't start at the same position as vcToAnnotate " + vcToAnnotate);
+
+            if ( vcToAnnotate.getReference().equals(vcComp.getReference()) ) {
+                for ( final Allele allele : vcToAnnotate.getAlternateAlleles() ) {
+                    if ( vcComp.getAlternateAlleles().contains(allele) )
+                        return vcComp.getID();
+                }
+            }
+        }
+
+        return null;
+    }
+
+    /**
+     * Does vcToAnnotate overlap with any of the records in potentialOverlaps?
+     *
+     * @param potentialOverlaps a non-null list of potential overlaps that start at vcToAnnotate
+     * @param vcToAnnotate a non-null VariantContext to annotate
+     * @return true if vcToAnnotate overlaps (position and all alt alleles) with some variant in potentialOverlaps
+     */
+    private boolean overlaps(final List<VariantContext> potentialOverlaps, final VariantContext vcToAnnotate) {
+        return getRsID(potentialOverlaps, vcToAnnotate) != null;
+    }
+
+    /**
+     * Get the collection of the RodBinding names for those being used for overlap detection
+     * @return a non-null collection of Strings
+     */
+    public Collection<String> getOverlapNames() {
+        return overlapBindings.values();
+    }
+}
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/tools/walkers/annotator/interfaces/ActiveRegionBasedAnnotation.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/tools/walkers/annotator/interfaces/ActiveRegionBasedAnnotation.java
new file mode 100644
index 0000000..8a32ae1
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/tools/walkers/annotator/interfaces/ActiveRegionBasedAnnotation.java
@@ -0,0 +1,42 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.tools.walkers.annotator.interfaces;
+
+import org.broadinstitute.gatk.utils.genotyper.PerReadAlleleLikelihoodMap;
+import htsjdk.variant.vcf.VCFInfoHeaderLine;
+import htsjdk.variant.variantcontext.VariantContext;
+
+import java.util.List;
+import java.util.Map;
+
+// TODO -- make this an abstract class when we move away from InfoFieldAnnotation
+public interface ActiveRegionBasedAnnotation extends AnnotationType {
+    // return annotations for the given contexts split by sample and then read likelihood
+    public abstract Map<String, Object> annotate(final Map<String,PerReadAlleleLikelihoodMap> stratifiedContexts, final VariantContext vc);
+
+    // return the descriptions used for the VCF INFO meta field
+    public abstract List<VCFInfoHeaderLine> getDescriptions();
+}
\ No newline at end of file
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/tools/walkers/annotator/interfaces/AnnotationInterfaceManager.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/tools/walkers/annotator/interfaces/AnnotationInterfaceManager.java
new file mode 100644
index 0000000..37b570c
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/tools/walkers/annotator/interfaces/AnnotationInterfaceManager.java
@@ -0,0 +1,140 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.tools.walkers.annotator.interfaces;
+
+import org.broadinstitute.gatk.utils.DeprecatedToolChecks;
+import org.broadinstitute.gatk.utils.classloader.PluginManager;
+import org.broadinstitute.gatk.utils.exceptions.UserException;
+
+import java.util.*;
+
+public class AnnotationInterfaceManager {
+    private static final String NULL_ANNOTATION_NAME = "none";
+    private static final String NULL_ANNOTATION_GROUP_NAME = "none";
+
+    private static PluginManager<InfoFieldAnnotation> infoFieldAnnotationPluginManager = new PluginManager<InfoFieldAnnotation>(InfoFieldAnnotation.class);
+    private static PluginManager<GenotypeAnnotation> genotypeAnnotationPluginManager = new PluginManager<GenotypeAnnotation>(GenotypeAnnotation.class);
+    private static PluginManager<AnnotationType> annotationTypePluginManager = new PluginManager<AnnotationType>(AnnotationType.class);
+
+    public static List<InfoFieldAnnotation> createAllInfoFieldAnnotations() {
+        return infoFieldAnnotationPluginManager.createAllTypes();
+    }
+
+    public static List<GenotypeAnnotation> createAllGenotypeAnnotations() {
+        return genotypeAnnotationPluginManager.createAllTypes();
+    }
+
+    public static void validateAnnotations(List<String> annotationGroupsToUse, List<String> annotationsToUse) {
+        HashMap<String, Class> classMap = new HashMap<String, Class>();
+        for ( Class c : infoFieldAnnotationPluginManager.getPlugins() )
+            classMap.put(c.getSimpleName(), c);
+        for ( Class c : genotypeAnnotationPluginManager.getPlugins() )
+            classMap.put(c.getSimpleName(), c);
+        for ( Class c : annotationTypePluginManager.getInterfaces() )
+            classMap.put(c.getSimpleName(), c);
+
+        if ( annotationGroupsToUse.size() != 1 || !NULL_ANNOTATION_GROUP_NAME.equals(annotationGroupsToUse.get(0)) ) {
+            for ( String group : annotationGroupsToUse ) {
+                Class interfaceClass = classMap.get(group);
+                if ( interfaceClass == null )
+                    interfaceClass = classMap.get(group + "Annotation");
+                if ( interfaceClass == null )
+                    throw new UserException.BadArgumentValue("group", "Annotation group " + group + " was not found; please check that you have specified the group name correctly");
+            }
+        }
+
+        // validate the specific classes provided
+        if ( annotationsToUse.size() != 1 || !NULL_ANNOTATION_NAME.equals(annotationsToUse.get(0)) ) {
+            for (String annotation : annotationsToUse) {
+                Class annotationClass = classMap.get(annotation);
+                if (annotationClass == null)
+                    annotationClass = classMap.get(annotation + "Annotation");
+                if (annotationClass == null) {
+                    if (DeprecatedToolChecks.isDeprecatedAnnotation(annotation)) {
+                        throw new UserException.DeprecatedAnnotation(annotation, DeprecatedToolChecks.getAnnotationDeprecationInfo(annotation));
+                    } else {
+                        throw new UserException.BadArgumentValue("annotation", "Annotation " + annotation + " was not found; please check that you have specified the annotation name correctly");
+                    }
+                }
+            }
+        }
+    }
+
+    public static List<InfoFieldAnnotation> createInfoFieldAnnotations(List<String> annotationGroupsToUse, List<String> annotationsToUse) {
+        return createAnnotations(infoFieldAnnotationPluginManager, annotationGroupsToUse, annotationsToUse);
+    }
+
+    public static List<GenotypeAnnotation> createGenotypeAnnotations(List<String> annotationGroupsToUse, List<String> annotationsToUse) {
+        return createAnnotations(genotypeAnnotationPluginManager, annotationGroupsToUse, annotationsToUse);
+    }
+
+    private static <T> List<T> createAnnotations(PluginManager<T> pluginManager, List<String> annotationGroupsToUse, List<String> annotationsToUse) {
+        // get the instances
+        List<T> annotations = new ArrayList<T>();
+
+        // get the classes from the provided groups (interfaces)
+        // create a map for all annotation classes which implement our top-level interfaces
+        HashMap<String, Class> classMap = new HashMap<String, Class>();
+        for ( Class c : pluginManager.getPlugins() )
+            classMap.put(c.getSimpleName(), c);
+        for ( Class c : annotationTypePluginManager.getInterfaces() )
+            classMap.put(c.getSimpleName(), c);
+
+        // use a TreeSet so that classes are returned deterministically (the plugin manager apparently isn't deterministic)
+        TreeSet<Class> classes = new TreeSet<Class>(new Comparator<Class>() {
+            public int compare(Class o1, Class o2) {
+                return o1.getSimpleName().compareTo(o2.getSimpleName());
+            }
+        });
+
+        if ( annotationGroupsToUse.size() != 1 || !NULL_ANNOTATION_GROUP_NAME.equals(annotationGroupsToUse.get(0)) ) {
+            for ( String group : annotationGroupsToUse ) {
+                Class interfaceClass = classMap.get(group);
+                if ( interfaceClass == null )
+                    interfaceClass = classMap.get(group + "Annotation");
+                if ( interfaceClass != null )
+                    classes.addAll(pluginManager.getPluginsImplementing(interfaceClass));
+            }
+        }
+
+        // get the specific classes provided
+        if ( annotationsToUse.size() != 1 || !NULL_ANNOTATION_NAME.equals(annotationsToUse.get(0)) ) {
+            for (String annotation : annotationsToUse) {
+                Class annotationClass = classMap.get(annotation);
+                if (annotationClass == null)
+                    annotationClass = classMap.get(annotation + "Annotation");
+                if (annotationClass != null)
+                    classes.add(annotationClass);
+            }
+        }
+
+        // note that technically an annotation can work on both the INFO and FORMAT fields
+        for ( Class c : classes )
+            annotations.add(pluginManager.createByType(c));
+
+        return annotations;
+    }
+}
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/tools/walkers/annotator/interfaces/AnnotationType.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/tools/walkers/annotator/interfaces/AnnotationType.java
new file mode 100644
index 0000000..0051c97
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/tools/walkers/annotator/interfaces/AnnotationType.java
@@ -0,0 +1,28 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.tools.walkers.annotator.interfaces;
+
+public interface AnnotationType {}
\ No newline at end of file
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/tools/walkers/annotator/interfaces/AnnotatorCompatible.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/tools/walkers/annotator/interfaces/AnnotatorCompatible.java
new file mode 100644
index 0000000..f1aeede
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/tools/walkers/annotator/interfaces/AnnotatorCompatible.java
@@ -0,0 +1,41 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.tools.walkers.annotator.interfaces;
+
+import org.broadinstitute.gatk.utils.commandline.RodBinding;
+import htsjdk.variant.variantcontext.VariantContext;
+
+import java.util.List;
+
+public interface AnnotatorCompatible {
+
+    // getter methods for various used bindings
+    public abstract RodBinding<VariantContext> getSnpEffRodBinding();
+    public abstract RodBinding<VariantContext> getDbsnpRodBinding();
+    public abstract List<RodBinding<VariantContext>> getCompRodBindings();
+    public abstract List<RodBinding<VariantContext>> getResourceRodBindings();
+    public abstract boolean alwaysAppendDbsnpId();
+}
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/tools/walkers/annotator/interfaces/ExperimentalAnnotation.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/tools/walkers/annotator/interfaces/ExperimentalAnnotation.java
new file mode 100644
index 0000000..9ed24db
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/tools/walkers/annotator/interfaces/ExperimentalAnnotation.java
@@ -0,0 +1,28 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.tools.walkers.annotator.interfaces;
+
+public interface ExperimentalAnnotation extends AnnotationType {}
\ No newline at end of file
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/tools/walkers/annotator/interfaces/GenotypeAnnotation.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/tools/walkers/annotator/interfaces/GenotypeAnnotation.java
new file mode 100644
index 0000000..a6a81d7
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/tools/walkers/annotator/interfaces/GenotypeAnnotation.java
@@ -0,0 +1,54 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.tools.walkers.annotator.interfaces;
+
+import org.broadinstitute.gatk.engine.contexts.AlignmentContext;
+import org.broadinstitute.gatk.engine.contexts.ReferenceContext;
+import org.broadinstitute.gatk.engine.refdata.RefMetaDataTracker;
+import org.broadinstitute.gatk.utils.genotyper.PerReadAlleleLikelihoodMap;
+import htsjdk.variant.vcf.VCFFormatHeaderLine;
+import htsjdk.variant.variantcontext.Genotype;
+import htsjdk.variant.variantcontext.GenotypeBuilder;
+import htsjdk.variant.variantcontext.VariantContext;
+
+import java.util.List;
+
+public abstract class GenotypeAnnotation extends VariantAnnotatorAnnotation {
+
+    // return annotations for the given contexts/genotype split by sample
+    public abstract void annotate(final RefMetaDataTracker tracker,
+                                  final AnnotatorCompatible walker,
+                                  final ReferenceContext ref,
+                                  final AlignmentContext stratifiedContext,
+                                  final VariantContext vc,
+                                  final Genotype g,
+                                  final GenotypeBuilder gb,
+                                  final PerReadAlleleLikelihoodMap alleleLikelihoodMap);
+
+    // return the descriptions used for the VCF FORMAT meta field
+    public abstract List<VCFFormatHeaderLine> getDescriptions();
+
+}
\ No newline at end of file
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/tools/walkers/annotator/interfaces/InfoFieldAnnotation.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/tools/walkers/annotator/interfaces/InfoFieldAnnotation.java
new file mode 100644
index 0000000..55a30d8
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/tools/walkers/annotator/interfaces/InfoFieldAnnotation.java
@@ -0,0 +1,62 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.tools.walkers.annotator.interfaces;
+
+import org.broadinstitute.gatk.engine.contexts.AlignmentContext;
+import org.broadinstitute.gatk.engine.contexts.ReferenceContext;
+import org.broadinstitute.gatk.engine.refdata.RefMetaDataTracker;
+import org.broadinstitute.gatk.utils.genotyper.PerReadAlleleLikelihoodMap;
+import htsjdk.variant.vcf.VCFInfoHeaderLine;
+import htsjdk.variant.variantcontext.VariantContext;
+
+import java.util.List;
+import java.util.Map;
+
+public abstract class InfoFieldAnnotation extends VariantAnnotatorAnnotation {
+    // return annotations for the given contexts split by sample
+    public Map<String, Object> annotate(final RefMetaDataTracker tracker,
+                                        final AnnotatorCompatible walker,
+                                        final ReferenceContext ref,
+                                        final Map<String, AlignmentContext> stratifiedContexts,
+                                        final VariantContext vc) {
+        return annotate(tracker, walker, ref, stratifiedContexts, vc, null);
+    }
+
+    public Map<String, Object> annotate(Map<String, PerReadAlleleLikelihoodMap> perReadAlleleLikelihoodMap, VariantContext vc) {
+        return annotate(null, null, null, null, vc, perReadAlleleLikelihoodMap);
+    }
+
+
+    public abstract Map<String, Object> annotate(final RefMetaDataTracker tracker,
+                                                 final AnnotatorCompatible walker,
+                                                 final ReferenceContext ref,
+                                                 final Map<String, AlignmentContext> stratifiedContexts,
+                                                 final VariantContext vc,
+                                                 final Map<String, PerReadAlleleLikelihoodMap> stratifiedPerReadAlleleLikelihoodMap);
+
+    // return the descriptions used for the VCF INFO meta field
+    public abstract List<VCFInfoHeaderLine> getDescriptions();
+}
\ No newline at end of file
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/tools/walkers/annotator/interfaces/RodRequiringAnnotation.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/tools/walkers/annotator/interfaces/RodRequiringAnnotation.java
new file mode 100644
index 0000000..04e545a
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/tools/walkers/annotator/interfaces/RodRequiringAnnotation.java
@@ -0,0 +1,28 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.tools.walkers.annotator.interfaces;
+
+public interface RodRequiringAnnotation extends AnnotationType {}
\ No newline at end of file
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/tools/walkers/annotator/interfaces/StandardAnnotation.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/tools/walkers/annotator/interfaces/StandardAnnotation.java
new file mode 100644
index 0000000..247af00
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/tools/walkers/annotator/interfaces/StandardAnnotation.java
@@ -0,0 +1,28 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.tools.walkers.annotator.interfaces;
+
+public interface StandardAnnotation extends AnnotationType {}
\ No newline at end of file
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/tools/walkers/annotator/interfaces/VariantAnnotatorAnnotation.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/tools/walkers/annotator/interfaces/VariantAnnotatorAnnotation.java
new file mode 100644
index 0000000..0c68955
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/tools/walkers/annotator/interfaces/VariantAnnotatorAnnotation.java
@@ -0,0 +1,43 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.tools.walkers.annotator.interfaces;
+
+import org.broadinstitute.gatk.engine.GenomeAnalysisEngine;
+import org.broadinstitute.gatk.utils.help.HelpConstants;
+import htsjdk.variant.vcf.VCFHeaderLine;
+import org.broadinstitute.gatk.utils.help.DocumentedGATKFeature;
+
+import java.util.List;
+import java.util.Set;
+
+ at DocumentedGATKFeature(enable = true, groupName = HelpConstants.DOCS_CAT_ANNOT, summary = "Annotations available to VariantAnnotator and the variant callers (some restrictions apply)")
+public abstract class VariantAnnotatorAnnotation {
+    // return the INFO keys
+    public abstract List<String> getKeyNames();
+
+    // initialization method (optional for subclasses, and therefore non-abstract)
+    public void initialize ( AnnotatorCompatible walker, GenomeAnalysisEngine toolkit, Set<VCFHeaderLine> headerLines ) { }
+}
\ No newline at end of file
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/tools/walkers/annotator/interfaces/WorkInProgressAnnotation.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/tools/walkers/annotator/interfaces/WorkInProgressAnnotation.java
new file mode 100644
index 0000000..9daab43
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/tools/walkers/annotator/interfaces/WorkInProgressAnnotation.java
@@ -0,0 +1,28 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.tools.walkers.annotator.interfaces;
+
+public interface WorkInProgressAnnotation extends AnnotationType {}
\ No newline at end of file
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/tools/walkers/beagle/BeagleOutputToVCF.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/tools/walkers/beagle/BeagleOutputToVCF.java
new file mode 100644
index 0000000..726ea9b
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/tools/walkers/beagle/BeagleOutputToVCF.java
@@ -0,0 +1,392 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.tools.walkers.beagle;
+
+import org.broadinstitute.gatk.utils.commandline.*;
+import org.broadinstitute.gatk.engine.CommandLineGATK;
+import org.broadinstitute.gatk.engine.arguments.StandardVariantContextInputArgumentCollection;
+import org.broadinstitute.gatk.engine.contexts.AlignmentContext;
+import org.broadinstitute.gatk.engine.contexts.ReferenceContext;
+import org.broadinstitute.gatk.engine.refdata.RefMetaDataTracker;
+import org.broadinstitute.gatk.engine.walkers.RodWalker;
+import org.broadinstitute.gatk.utils.GenomeLoc;
+import org.broadinstitute.gatk.utils.SampleUtils;
+import org.broadinstitute.gatk.utils.codecs.beagle.BeagleFeature;
+import org.broadinstitute.gatk.utils.help.HelpConstants;
+import org.broadinstitute.gatk.utils.variant.GATKVCFUtils;
+import htsjdk.variant.vcf.*;
+import org.broadinstitute.gatk.utils.help.DocumentedGATKFeature;
+import htsjdk.variant.variantcontext.*;
+import htsjdk.variant.variantcontext.writer.VariantContextWriter;
+
+import java.util.*;
+
+import static java.lang.Math.log10;
+
+
+/**
+ * Takes files produced by Beagle imputation engine and creates a vcf with modified annotations.
+ *
+ * <p>This walker is intended to be run after Beagle has successfully executed. The full calling sequence for using Beagle along with the GATK is:      </p>
+ *
+ * <p>1. Run ProduceBeagleInputWalker.  </p>
+ * <p>2. Run Beagle</p>
+ * <p>3. Uncompress output files</p>
+ * <p>4. Run BeagleOutputToVCFWalker.</p>
+ *
+ *
+ * Note that this walker requires all input files produced by Beagle.
+ *
+ *
+ * <h3>Example</h3>
+ * <pre>
+ *     java -Xmx4000m -jar dist/GenomeAnalysisTK.jar \
+ *      -R reffile.fasta -T BeagleOutputToVCF \
+ *      -V input_vcf.vcf \
+ *      -beagleR2:BEAGLE /myrun.beagle_output.r2 \
+ *      -beaglePhased:BEAGLE /myrun.beagle_output.phased \
+ *      -beagleProbs:BEAGLE /myrun.beagle_output.gprobs \
+ *      -o output_vcf.vcf
+ *      </pre>
+
+ <p> Note that Beagle produces some of these files compressed as .gz, so gunzip must be run on them before walker is run in order to decompress them </p>
+
+ */
+ at DocumentedGATKFeature( groupName = HelpConstants.DOCS_CAT_VARDISC, extraDocs = {CommandLineGATK.class} )
+public class BeagleOutputToVCF extends RodWalker<Integer, Integer> {
+
+    @ArgumentCollection
+    protected StandardVariantContextInputArgumentCollection variantCollection = new StandardVariantContextInputArgumentCollection();
+
+    /**
+     * If this argument is present, the original allele frequencies and counts from this vcf are added as annotations ACH,AFH and ANH. at each record present in this vcf
+     */
+    @Input(fullName="comp", shortName = "comp", doc="Comparison VCF file", required=false)
+    public RodBinding<VariantContext> comp;
+
+
+    /**
+     * This required argument is used to annotate each site in the vcf INFO field with R2 annotation. Will be NaN if Beagle determined there are no variant samples.
+     */
+    @Input(fullName="beagleR2", shortName = "beagleR2", doc="Beagle-produced .r2 file containing R^2 values for all markers", required=true)
+    public RodBinding<BeagleFeature> beagleR2;
+
+    /**
+     * These values will populate the GL field for each sample and contain the posterior probability of each genotype given the data after phasing and imputation.
+     */
+    @Input(fullName="beagleProbs", shortName = "beagleProbs", doc="Beagle-produced .probs file containing posterior genotype probabilities", required=true)
+    public RodBinding<BeagleFeature> beagleProbs;
+
+    /**
+     * By default, all genotypes will be marked in the VCF as "phased", using the "|" separator after Beagle.
+     */
+    @Input(fullName="beaglePhased", shortName = "beaglePhased", doc="Beagle-produced .phased file containing phased genotypes", required=true)
+    public RodBinding<BeagleFeature> beaglePhased;
+
+    @Output(doc="VCF File to which variants should be written")
+    protected VariantContextWriter vcfWriter = null;
+
+    /**
+     * If this argument is absent, and if Beagle determines that there is no sample in a site that has a variant genotype, the site will be marked as filtered (Default behavior).
+     * If the argument is present, the site won't be marked as filtered under this condition even if there are no variant genotypes.
+     */
+    @Argument(fullName="dont_mark_monomorphic_sites_as_filtered", shortName="keep_monomorphic", doc="If provided, we won't filter sites that beagle tags as monomorphic.  Useful for imputing a sample's genotypes from a reference panel" ,required=false)
+    public boolean DONT_FILTER_MONOMORPHIC_SITES = false;
+
+    /**
+     * Value between 0 and 1. If the probability of getting a genotype correctly (based on the posterior genotype probabilities and the actual genotype) is below this threshold,
+     * a genotype will be substitute by a no-call.
+     */
+    @Argument(fullName="no" +
+            "call_threshold", shortName="ncthr", doc="Threshold of confidence at which a genotype won't be called", required=false)
+    private double noCallThreshold = 0.0;
+
+    protected static String line = null;
+
+    private final double MIN_PROB_ERROR = 0.000001;
+    private final double MAX_GENOTYPE_QUALITY = -6.0;
+
+    private final static String BEAGLE_MONO_FILTER_STRING = "BGL_SET_TO_MONOMORPHIC";
+    private final static String ORIGINAL_ALT_ALLELE_INFO_KEY = "OriginalAltAllele";
+
+    public void initialize() {
+
+        // setup the header fields
+
+        final Set<VCFHeaderLine> hInfo = new HashSet<VCFHeaderLine>();
+        hInfo.addAll(GATKVCFUtils.getHeaderFields(getToolkit()));
+        hInfo.add(new VCFFormatHeaderLine("OG",1, VCFHeaderLineType.String, "Original Genotype input to Beagle"));
+        hInfo.add(new VCFInfoHeaderLine("R2", 1, VCFHeaderLineType.Float, "r2 Value reported by Beagle on each site"));
+        hInfo.add(new VCFInfoHeaderLine("NumGenotypesChanged", 1, VCFHeaderLineType.Integer, "The number of genotypes changed by Beagle"));
+        hInfo.add(new VCFInfoHeaderLine(ORIGINAL_ALT_ALLELE_INFO_KEY, 1, VCFHeaderLineType.String, "The original alt allele for a site set to monomorphic by Beagle"));
+        hInfo.add(new VCFFilterHeaderLine(BEAGLE_MONO_FILTER_STRING, "This site was set to monomorphic by Beagle"));
+
+        if ( comp.isBound() ) {
+            hInfo.add(new VCFInfoHeaderLine("ACH", 1, VCFHeaderLineType.Integer, "Allele Count from Comparison ROD at this site"));
+            hInfo.add(new VCFInfoHeaderLine("ANH", 1, VCFHeaderLineType.Integer, "Allele Frequency from Comparison ROD at this site"));
+            hInfo.add(new VCFInfoHeaderLine("AFH", 1, VCFHeaderLineType.Float, "Allele Number from Comparison ROD at this site"));
+        }
+
+        Set<String> samples = SampleUtils.getSampleListWithVCFHeader(getToolkit(), Arrays.asList(variantCollection.variants.getName()));
+
+        final VCFHeader vcfHeader = new VCFHeader(hInfo, samples);
+        vcfWriter.writeHeader(vcfHeader);
+    }
+
+    public Integer map( RefMetaDataTracker tracker, ReferenceContext ref, AlignmentContext context ) {
+
+        if ( tracker == null )
+            return 0;
+
+        GenomeLoc loc = context.getLocation();
+        VariantContext vc_input = tracker.getFirstValue(variantCollection.variants, loc);
+
+        VariantContext vc_comp = tracker.getFirstValue(comp, loc);
+
+        if ( vc_input == null  )
+            return 0;
+
+        if (vc_input.isFiltered()) {
+            vcfWriter.add(vc_input);
+            return 1;
+        }
+
+        BeagleFeature beagleR2Feature = tracker.getFirstValue(beagleR2);
+        BeagleFeature beagleProbsFeature = tracker.getFirstValue(beagleProbs);
+        BeagleFeature beaglePhasedFeature = tracker.getFirstValue(beaglePhased);
+
+        // ignore places where we don't have a variant
+        if ( beagleR2Feature == null || beagleProbsFeature == null ||  beaglePhasedFeature == null)
+        {
+            vcfWriter.add(vc_input);
+            return 1;
+        }
+
+
+        // get reference base for current position
+        byte refByte = ref.getBase();
+
+        // make new Genotypes based on Beagle results
+        GenotypesContext genotypes = GenotypesContext.create(vc_input.getGenotypes().size());
+
+        // for each genotype, create a new object with Beagle information on it
+
+        int numGenotypesChangedByBeagle = 0;
+        Integer alleleCountH = 0, chrCountH = 0;
+        Double alleleFrequencyH = 0.0;
+        int beagleVarCounts = 0;
+
+        GenotypesContext hapmapGenotypes = null;
+
+        if (vc_comp != null) {
+            hapmapGenotypes = vc_comp.getGenotypes();
+        }
+
+        for ( final Genotype g : vc_input.getGenotypes() ) {
+            boolean genotypeIsPhased = true;
+            String sample = g.getSampleName();
+
+            // If we have  a Hapmap (comp) ROD, compute Hapmap AC, AN and AF
+            // use sample as key into genotypes structure
+            if (vc_comp != null) {
+
+                if (vc_input.getGenotypes().containsSample(sample) && hapmapGenotypes.containsSample(sample))  {
+
+                    Genotype hapmapGenotype = hapmapGenotypes.get(sample);
+                    if (hapmapGenotype.isCalled()){
+                        chrCountH += 2;
+                        if (hapmapGenotype.isHet()) {
+                            alleleCountH += 1;
+                        }    else if (hapmapGenotype.isHomVar()) {
+                            alleleCountH += 2;
+                        }
+                    }
+                }
+            }
+
+            ArrayList<String> beagleProbabilities = beagleProbsFeature.getProbLikelihoods().get(sample);
+            ArrayList<String> beagleGenotypePairs = beaglePhasedFeature.getGenotypes().get(sample);
+
+            // original alleles at this genotype
+            Allele originalAlleleA = g.getAllele(0);
+
+            Allele originalAlleleB = (g.getAlleles().size() == 2) ? g.getAllele(1) : g.getAllele(0); // hack to deal with no-call genotypes
+
+
+            // We have phased genotype in hp. Need to set the isRef field in the allele.
+            List<Allele> alleles = new ArrayList<Allele>();
+
+            String alleleA = beagleGenotypePairs.get(0);
+            String alleleB = beagleGenotypePairs.get(1);
+
+            if ( alleleA.equals("null") || alleleB.equals("null") ) {
+                logger.warn("Beagle produced 'null' alleles at location "+ref.getLocus().toString()+". Ignoring.");
+                return 0;
+            }
+
+            // Beagle always produces genotype strings based on the strings we input in the likelihood file.
+            String refString = vc_input.getReference().getDisplayString();
+
+            Allele bglAlleleA, bglAlleleB;
+
+            if (alleleA.matches(refString))
+                bglAlleleA = Allele.create(alleleA,true);
+            else
+                bglAlleleA = Allele.create(alleleA,false);
+
+            if (alleleB.matches(refString))
+                bglAlleleB = Allele.create(alleleB,true);
+            else
+                bglAlleleB = Allele.create(alleleB,false);
+
+
+            alleles.add(bglAlleleA);
+            alleles.add(bglAlleleB);
+
+            // Compute new GQ field = -10*log10Pr(Genotype call is wrong)
+            // Beagle gives probability that genotype is AA, AB and BB.
+            // Which, by definition, are prob of hom ref, het and hom var.
+            double probWrongGenotype, genotypeQuality;
+            Double homRefProbability = Double.valueOf(beagleProbabilities.get(0));
+            Double hetProbability = Double.valueOf(beagleProbabilities.get(1));
+            Double homVarProbability = Double.valueOf(beagleProbabilities.get(2));
+
+            if (bglAlleleA.isReference() && bglAlleleB.isReference()) // HomRef call
+                probWrongGenotype = hetProbability + homVarProbability;
+            else if ((bglAlleleB.isReference() && bglAlleleA.isNonReference()) || (bglAlleleA.isReference() && bglAlleleB.isNonReference()))
+                probWrongGenotype = homRefProbability + homVarProbability;
+            else // HomVar call
+                probWrongGenotype = hetProbability + homRefProbability;
+
+            // deal with numerical errors coming from limited formatting value on Beagle output files
+            if (probWrongGenotype > 1 - MIN_PROB_ERROR)
+                probWrongGenotype = 1 - MIN_PROB_ERROR;
+
+            if (1-probWrongGenotype < noCallThreshold) {
+                // quality is bad: don't call genotype
+                alleles.clear();
+                alleles.add(originalAlleleA);
+                alleles.add(originalAlleleB);
+                genotypeIsPhased = false;
+            }
+
+            if (probWrongGenotype < MIN_PROB_ERROR)
+                genotypeQuality = MAX_GENOTYPE_QUALITY;
+            else
+                genotypeQuality = log10(probWrongGenotype);
+
+            HashMap<String,Object> originalAttributes = new HashMap<String,Object>(g.getExtendedAttributes());
+
+            // get original encoding and add to keynotype attributes
+            String a1, a2, og;
+            if (originalAlleleA.isNoCall())
+                a1 = ".";
+            else if (originalAlleleA.isReference())
+                a1 = "0";
+            else
+                a1 = "1";
+
+            if (originalAlleleB.isNoCall())
+                a2 = ".";
+            else if (originalAlleleB.isReference())
+                a2 = "0";
+            else
+                a2 = "1";
+
+            og = a1+"/"+a2;
+
+            // See if Beagle switched genotypes
+            if (! originalAlleleA.equals(Allele.NO_CALL) && beagleSwitchedGenotypes(bglAlleleA,originalAlleleA,bglAlleleB,originalAlleleB)){
+                originalAttributes.put("OG",og);
+                numGenotypesChangedByBeagle++;
+            }
+            else {
+                originalAttributes.put("OG",".");
+            }
+            Genotype imputedGenotype = new GenotypeBuilder(g).alleles(alleles).log10PError(genotypeQuality).attributes(originalAttributes).phased(genotypeIsPhased).make();
+            if ( imputedGenotype.isHet() || imputedGenotype.isHomVar() ) {
+                beagleVarCounts++;
+            }
+
+            genotypes.add(imputedGenotype);
+        }
+
+        final VariantContextBuilder builder = new VariantContextBuilder(vc_input).source("outputvcf").genotypes(genotypes);
+        if ( ! ( beagleVarCounts > 0 || DONT_FILTER_MONOMORPHIC_SITES ) ) {
+            builder.attribute(ORIGINAL_ALT_ALLELE_INFO_KEY, vc_input.getAlternateAllele(0));
+            builder.alleles(Collections.singleton(vc_input.getReference())).filter(BEAGLE_MONO_FILTER_STRING);
+        }
+
+        // re-compute chromosome counts
+        VariantContextUtils.calculateChromosomeCounts(builder, false);
+
+        // Get Hapmap AC and AF
+        if (vc_comp != null) {
+            builder.attribute("ACH", alleleCountH.toString() );
+            builder.attribute("ANH", chrCountH.toString() );
+            builder.attribute("AFH", String.format("%4.2f", (double)alleleCountH/chrCountH) );
+
+        }
+
+        builder.attribute("NumGenotypesChanged", numGenotypesChangedByBeagle );
+        if( !beagleR2Feature.getR2value().equals(Double.NaN) ) {
+            builder.attribute("R2", beagleR2Feature.getR2value().toString() );
+        }
+
+        vcfWriter.add(builder.make());
+
+        return 1;
+    }
+
+    private boolean beagleSwitchedGenotypes(Allele bglAlleleA, Allele originalAlleleA, Allele bglAlleleB, Allele originalAlleleB) {
+       return !((bglAlleleA.equals(originalAlleleA) && bglAlleleB.equals(originalAlleleB) ||
+                    (bglAlleleA.equals(originalAlleleB) && bglAlleleB.equals(originalAlleleA))));
+    }
+
+    public Integer reduceInit() {
+        return 0; // Nothing to do here
+    }
+
+    /**
+     * Increment the number of loci processed.
+     *
+     * @param value result of the map.
+     * @param sum   accumulator for the reduce.
+     * @return the new number of loci processed.
+     */
+    public Integer reduce(Integer value, Integer sum) {
+        return sum + value;
+    }
+
+    /**
+     * Tell the user the number of loci processed and close out the new variants file.
+     *
+     * @param result  the number of loci seen.
+     */
+    public void onTraversalDone(Integer result) {
+        System.out.printf("Processed %d loci.\n", result);
+    }
+}
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/tools/walkers/beagle/ProduceBeagleInput.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/tools/walkers/beagle/ProduceBeagleInput.java
new file mode 100644
index 0000000..dab5d16
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/tools/walkers/beagle/ProduceBeagleInput.java
@@ -0,0 +1,463 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.tools.walkers.beagle;
+
+import org.broadinstitute.gatk.utils.commandline.*;
+import org.broadinstitute.gatk.engine.CommandLineGATK;
+import org.broadinstitute.gatk.engine.GenomeAnalysisEngine;
+import org.broadinstitute.gatk.engine.arguments.StandardVariantContextInputArgumentCollection;
+import org.broadinstitute.gatk.engine.contexts.AlignmentContext;
+import org.broadinstitute.gatk.engine.contexts.ReferenceContext;
+import org.broadinstitute.gatk.engine.refdata.RefMetaDataTracker;
+import org.broadinstitute.gatk.engine.samples.Gender;
+import org.broadinstitute.gatk.engine.walkers.RodWalker;
+import org.broadinstitute.gatk.tools.walkers.variantrecalibration.VQSRCalibrationCurve;
+import org.broadinstitute.gatk.utils.GenomeLoc;
+import org.broadinstitute.gatk.utils.MathUtils;
+import org.broadinstitute.gatk.utils.SampleUtils;
+import org.broadinstitute.gatk.utils.help.HelpConstants;
+import org.broadinstitute.gatk.utils.variant.GATKVCFUtils;
+import org.broadinstitute.gatk.utils.variant.GATKVariantContextUtils;
+import htsjdk.variant.vcf.VCFFilterHeaderLine;
+import htsjdk.variant.vcf.VCFHeader;
+import htsjdk.variant.vcf.VCFHeaderLine;
+import org.broadinstitute.gatk.utils.exceptions.GATKException;
+import org.broadinstitute.gatk.utils.help.DocumentedGATKFeature;
+import htsjdk.variant.variantcontext.*;
+import htsjdk.variant.variantcontext.writer.VariantContextWriter;
+
+import java.io.File;
+import java.io.PrintStream;
+import java.util.*;
+
+/**
+ *  Converts the input VCF into a format accepted by the Beagle imputation/analysis program.
+ * <p>
+ *
+ * <h3>Input</h3>
+ * <p>
+ * A VCF with variants to convert to Beagle format
+ * </p>
+ *
+ * <h2>Outputs</h2>
+ * <p>
+ * A single text file which can be fed to Beagle
+ * </p>
+ * <p>
+ * Optional: A file with a list of markers
+ * </p>
+  *
+ * <h3>Examples</h3>
+ * <pre>
+ *     java -Xmx2g -jar dist/GenomeAnalysisTK.jar -L 20 \
+ *      -R reffile.fasta -T ProduceBeagleInput \
+ *      -V path_to_input_vcf/inputvcf.vcf -o path_to_beagle_output/beagle_output
+ * </pre>
+ *
+ */
+
+ at DocumentedGATKFeature( groupName = HelpConstants.DOCS_CAT_VARDISC, extraDocs = {CommandLineGATK.class} )
+public class ProduceBeagleInput extends RodWalker<Integer, Integer> {
+
+    @ArgumentCollection protected StandardVariantContextInputArgumentCollection variantCollection = new StandardVariantContextInputArgumentCollection();
+
+    @Hidden
+    @Input(fullName="validation", shortName = "validation", doc="Validation VCF file", required=false)
+    public RodBinding<VariantContext> validation;
+
+
+    @Output(doc="File to which BEAGLE input should be written")
+    protected PrintStream  beagleWriter = null;
+
+    @Hidden
+    @Output(doc="File to which BEAGLE markers should be written", shortName="markers", fullName = "markers", required = false, defaultToStdout = false)
+    protected PrintStream  markers = null;
+    int markerCounter = 1;
+
+    @Hidden
+    @Input(doc="VQSqual calibration file", shortName = "cc", required=false)
+    protected File VQSRCalibrationFile = null;
+    protected VQSRCalibrationCurve VQSRCalibrator = null;
+
+    @Hidden
+    @Argument(doc="VQSqual key", shortName = "vqskey", required=false)
+    protected String VQSLOD_KEY = "VQSqual";
+
+    @Hidden
+     @Argument(fullName = "inserted_nocall_rate", shortName = "nc_rate", doc = "Rate (0-1) at which genotype no-calls will be randomly inserted, for testing", required = false)
+    public double insertedNoCallRate  = 0;
+    @Hidden
+     @Argument(fullName = "validation_genotype_ptrue", shortName = "valp", doc = "Flat probability to assign to validation genotypes. Will override GL field.", required = false)
+    public double validationPrior = -1.0;
+    @Hidden
+     @Argument(fullName = "validation_bootstrap", shortName = "bs", doc = "Proportion of records to be used in bootstrap set", required = false)
+    public double bootstrap = 0.0;
+    @Hidden
+     @Argument(fullName = "bootstrap_vcf",shortName = "bvcf", doc = "Output a VCF with the records used for bootstrapping filtered out", required = false)
+    VariantContextWriter bootstrapVCFOutput = null;
+
+    /**
+     * If sample gender is known, this flag should be set to true to ensure that Beagle treats male Chr X properly.
+     */
+    @Argument(fullName = "checkIsMaleOnChrX", shortName = "checkIsMaleOnChrX", doc = "Set to true when Beagle-ing chrX and want to ensure male samples don't have heterozygous calls.", required = false)
+    public boolean CHECK_IS_MALE_ON_CHR_X = false;
+
+    @Hidden
+    @Argument(fullName = "variant_genotype_ptrue", shortName = "varp", doc = "Flat probability prior to assign to variant (not validation) genotypes. Does not override GL field.", required = false)
+    public double variantPrior = 0.96;
+
+    private Set<String> samples = null;
+    private Set<String> BOOTSTRAP_FILTER = new HashSet<String>( Arrays.asList("bootstrap") );
+    private int bootstrapSetSize = 0;
+    private int testSetSize = 0;
+    private CachingFormatter formatter = new CachingFormatter("%5.4f ", 100000);
+    private int certainFPs = 0;
+
+    public void initialize() {
+
+        samples = SampleUtils.getSampleListWithVCFHeader(getToolkit(), Arrays.asList(variantCollection.variants.getName()));
+
+        beagleWriter.print("marker alleleA alleleB");
+        for ( String sample : samples )
+            beagleWriter.print(String.format(" %s %s %s", sample, sample, sample));
+
+        beagleWriter.println();
+
+        if ( bootstrapVCFOutput != null ) {
+            initializeVcfWriter();
+        }
+
+        if ( VQSRCalibrationFile != null ) {
+            VQSRCalibrator = VQSRCalibrationCurve.readFromFile(VQSRCalibrationFile);
+            logger.info("Read calibration curve");
+            VQSRCalibrator.printInfo(logger);
+        }
+    }
+
+    public Integer map( RefMetaDataTracker tracker, ReferenceContext ref, AlignmentContext context ) {
+        if( tracker != null ) {
+            GenomeLoc loc = context.getLocation();
+            VariantContext variant_eval = tracker.getFirstValue(variantCollection.variants, loc);
+            VariantContext validation_eval = tracker.getFirstValue(validation, loc);
+
+            if ( goodSite(variant_eval,validation_eval) ) {
+                if ( useValidation(validation_eval, ref) ) {
+                    writeBeagleOutput(validation_eval, variant_eval, true, validationPrior);
+                    return 1;
+                } else {
+                    if ( goodSite(variant_eval) ) {
+                        writeBeagleOutput(variant_eval,validation_eval,false,variantPrior);
+                        return 1;
+                    } else { // todo -- if the variant site is bad, validation is good, but not in bootstrap set -- what do?
+                        return 0;
+                    }
+                }
+            } else {
+                return 0;
+            }
+        } else {
+            return 0;
+        }
+    }
+
+    public boolean goodSite(VariantContext a, VariantContext b) {
+        return goodSite(a) || goodSite(b);
+    }
+
+    public boolean goodSite(VariantContext v) {
+        if ( canBeOutputToBeagle(v) ) {
+            if ( VQSRCalibrator != null && VQSRCalibrator.certainFalsePositive(VQSLOD_KEY, v) ) {
+                certainFPs++;
+                return false;
+            } else {
+                return true;
+            }
+        } else {
+            return false;
+        }
+    }
+
+    public static boolean canBeOutputToBeagle(VariantContext v) {
+        return v != null && ! v.isFiltered() && v.isBiallelic() && v.hasGenotypes();
+    }
+
+    public boolean useValidation(VariantContext validation, ReferenceContext ref) {
+        if( goodSite(validation) ) {
+            // if using record keeps us below expected proportion, use it
+            logger.debug(String.format("boot: %d, test: %d, total: %d", bootstrapSetSize, testSetSize, bootstrapSetSize+testSetSize+1));
+            if ( (bootstrapSetSize+1.0)/(1.0+bootstrapSetSize+testSetSize) <= bootstrap ) {
+                if ( bootstrapVCFOutput != null ) {
+                    bootstrapVCFOutput.add(new VariantContextBuilder(validation).filters(BOOTSTRAP_FILTER).make());
+                }
+                bootstrapSetSize++;
+                return true;
+            } else {
+                if ( bootstrapVCFOutput != null ) {
+                    bootstrapVCFOutput.add(validation);
+                }
+                testSetSize++;
+                return false;
+            }
+        } else {
+            if ( validation != null && bootstrapVCFOutput != null ) {
+                bootstrapVCFOutput.add(validation);
+            }
+            return false;
+        }
+    }
+
+    private final static double[] HAPLOID_FLAT_LOG10_LIKELIHOODS = MathUtils.toLog10(new double[]{ 0.5, 0.0, 0.5 });
+    private final static double[] DIPLOID_FLAT_LOG10_LIKELIHOODS = MathUtils.toLog10(new double[]{ 0.33, 0.33, 0.33 });
+
+    public void writeBeagleOutput(VariantContext preferredVC, VariantContext otherVC, boolean isValidationSite, double prior) {
+        GenomeLoc currentLoc = GATKVariantContextUtils.getLocation(getToolkit().getGenomeLocParser(), preferredVC);
+        StringBuffer beagleOut = new StringBuffer();
+
+        String marker = String.format("%s:%d ",currentLoc.getContig(),currentLoc.getStart());
+        beagleOut.append(marker);
+        if ( markers != null ) markers.append(marker).append("\t").append(Integer.toString(markerCounter++)).append("\t");
+        for ( Allele allele : preferredVC.getAlleles() ) {
+            String bglPrintString;
+            if (allele.isNoCall())
+                bglPrintString = "-";
+            else
+                bglPrintString = allele.getBaseString();  // get rid of * in case of reference allele
+
+            beagleOut.append(String.format("%s ", bglPrintString));
+            if ( markers != null ) markers.append(bglPrintString).append("\t");
+        }
+        if ( markers != null ) markers.append("\n");
+
+        GenotypesContext preferredGenotypes = preferredVC.getGenotypes();
+        GenotypesContext otherGenotypes = goodSite(otherVC) ? otherVC.getGenotypes() : null;
+        for ( String sample : samples ) {
+            boolean isMaleOnChrX = CHECK_IS_MALE_ON_CHR_X && getSample(sample).getGender() == Gender.MALE;
+
+            Genotype genotype;
+            boolean isValidation;
+            // use sample as key into genotypes structure
+            if ( preferredGenotypes.containsSample(sample) ) {
+                genotype = preferredGenotypes.get(sample);
+                isValidation = isValidationSite;
+            } else if ( otherGenotypes != null && otherGenotypes.containsSample(sample) ) {
+                genotype = otherGenotypes.get(sample);
+                isValidation = ! isValidationSite;
+            } else {
+                // there is magically no genotype for this sample.
+                throw new GATKException("Sample "+sample+" arose with no genotype in variant or validation VCF. This should never happen.");
+            }
+
+            /*
+             * Use likelihoods if: is validation, prior is negative; or: is not validation, has genotype key
+             */
+            double [] log10Likelihoods = null;
+            if ( (isValidation && prior < 0.0) || genotype.hasLikelihoods() ) {
+                log10Likelihoods = genotype.getLikelihoods().getAsVector();
+
+                // see if we need to randomly mask out genotype in this position.
+                if ( GenomeAnalysisEngine.getRandomGenerator().nextDouble() <= insertedNoCallRate ) {
+                    // we are masking out this genotype
+                    log10Likelihoods = isMaleOnChrX ? HAPLOID_FLAT_LOG10_LIKELIHOODS : DIPLOID_FLAT_LOG10_LIKELIHOODS;
+                }
+
+                if( isMaleOnChrX ) {
+                    log10Likelihoods[1] = -255;  // todo -- warning this is dangerous for multi-allele case
+                }
+            }
+            /**
+             * otherwise, use the prior uniformly
+             */
+            else if (! isValidation && genotype.isCalled() && ! genotype.hasLikelihoods() ) {
+                // hack to deal with input VCFs with no genotype likelihoods.  Just assume the called genotype
+                // is confident.  This is useful for Hapmap and 1KG release VCFs.
+                double AA = (1.0-prior)/2.0;
+                double AB = (1.0-prior)/2.0;
+                double BB = (1.0-prior)/2.0;
+
+                if (genotype.isHomRef()) { AA = prior; }
+                else if (genotype.isHet()) { AB = prior; }
+                else if (genotype.isHomVar()) { BB = prior; }
+
+                log10Likelihoods = MathUtils.toLog10(new double[]{ AA, isMaleOnChrX ? 0.0 : AB, BB });
+            }
+            else  {
+                log10Likelihoods = isMaleOnChrX ? HAPLOID_FLAT_LOG10_LIKELIHOODS : DIPLOID_FLAT_LOG10_LIKELIHOODS;
+            }
+
+            writeSampleLikelihoods(beagleOut, preferredVC, log10Likelihoods);
+        }
+
+        beagleWriter.println(beagleOut.toString());
+    }
+
+    private void writeSampleLikelihoods( StringBuffer out, VariantContext vc, double[] log10Likelihoods ) {
+        if ( VQSRCalibrator != null ) {
+            log10Likelihoods = VQSRCalibrator.includeErrorRateInLikelihoods(VQSLOD_KEY, vc, log10Likelihoods);
+        }
+
+        double[] normalizedLikelihoods = MathUtils.normalizeFromLog10(log10Likelihoods);
+        // see if we need to randomly mask out genotype in this position.
+        for (double likeVal: normalizedLikelihoods) {
+            out.append(formatter.format(likeVal));
+//            out.append(String.format("%5.4f ",likeVal));
+        }
+    }
+
+
+    public Integer reduceInit() {
+        return 0; // Nothing to do here
+    }
+
+    public Integer reduce( Integer value, Integer sum ) {
+        return value + sum; // count up the sites
+    }
+
+    public void onTraversalDone( Integer includedSites ) {
+        logger.info("Sites included in beagle likelihoods file             : " + includedSites);
+        logger.info(String.format("Certain false positive found from recalibration curve : %d (%.2f%%)",
+                certainFPs, (100.0 * certainFPs) / (Math.max(certainFPs + includedSites, 1))));
+    }
+
+    private void initializeVcfWriter() {
+        final List<String> inputNames = Arrays.asList(validation.getName());
+
+        // setup the header fields
+        Set<VCFHeaderLine> hInfo = new HashSet<VCFHeaderLine>();
+        hInfo.addAll(GATKVCFUtils.getHeaderFields(getToolkit(), inputNames));
+        hInfo.add(new VCFFilterHeaderLine("bootstrap","This site used for genotype bootstrapping with ProduceBeagleInputWalker"));
+
+        bootstrapVCFOutput.writeHeader(new VCFHeader(hInfo, SampleUtils.getUniqueSamplesFromRods(getToolkit(), inputNames)));
+    }
+
+    public static class CachingFormatter {
+        private String format;
+        private LRUCache<Double, String> cache;
+
+        public String getFormat() {
+            return format;
+        }
+
+        public String format(double value) {
+            String f = cache.get(value);
+            if ( f == null ) {
+                f = String.format(format, value);
+                cache.put(value, f);
+//                if ( cache.usedEntries() < maxCacheSize ) {
+//                    System.out.printf("CACHE size %d%n", cache.usedEntries());
+//                } else {
+//                    System.out.printf("CACHE is full %f%n", value);
+//                }
+//            }
+//            } else {
+//                System.out.printf("CACHE hit %f%n", value);
+//            }
+            }
+
+            return f;
+        }
+
+        public CachingFormatter(String format, int maxCacheSize) {
+            this.format = format;
+            this.cache = new LRUCache<Double, String>(maxCacheSize);
+        }
+    }
+
+    /**
+    * An LRU cache, based on <code>LinkedHashMap</code>.
+    *
+    * <p>
+    * This cache has a fixed maximum number of elements (<code>cacheSize</code>).
+    * If the cache is full and another entry is added, the LRU (least recently used) entry is dropped.
+    *
+    * <p>
+    * This class is thread-safe. All methods of this class are synchronized.
+    *
+    * <p>
+    * Author: Christian d'Heureuse, Inventec Informatik AG, Zurich, Switzerland<br>
+    * Multi-licensed: EPL / LGPL / GPL / AL / BSD.
+    */
+    public static class LRUCache<K,V> {
+
+    private static final float   hashTableLoadFactor = 0.75f;
+
+    private LinkedHashMap<K,V>   map;
+    private int                  cacheSize;
+
+    /**
+    * Creates a new LRU cache.
+    * @param cacheSize the maximum number of entries that will be kept in this cache.
+    */
+    public LRUCache (int cacheSize) {
+       this.cacheSize = cacheSize;
+       int hashTableCapacity = (int)Math.ceil(cacheSize / hashTableLoadFactor) + 1;
+       map = new LinkedHashMap<K,V>(hashTableCapacity, hashTableLoadFactor, true) {
+          // (an anonymous inner class)
+          private static final long serialVersionUID = 1;
+          @Override protected boolean removeEldestEntry (Map.Entry<K,V> eldest) {
+             return size() > LRUCache.this.cacheSize; }}; }
+
+    /**
+    * Retrieves an entry from the cache.<br>
+    * The retrieved entry becomes the MRU (most recently used) entry.
+    * @param key the key whose associated value is to be returned.
+    * @return    the value associated to this key, or null if no value with this key exists in the cache.
+    */
+    public synchronized V get (K key) {
+       return map.get(key); }
+
+    /**
+    * Adds an entry to this cache.
+    * The new entry becomes the MRU (most recently used) entry.
+    * If an entry with the specified key already exists in the cache, it is replaced by the new entry.
+    * If the cache is full, the LRU (least recently used) entry is removed from the cache.
+    * @param key    the key with which the specified value is to be associated.
+    * @param value  a value to be associated with the specified key.
+    */
+    public synchronized void put (K key, V value) {
+       map.put (key, value); }
+
+    /**
+    * Clears the cache.
+    */
+    public synchronized void clear() {
+       map.clear(); }
+
+    /**
+    * Returns the number of used entries in the cache.
+    * @return the number of entries currently in the cache.
+    */
+    public synchronized int usedEntries() {
+       return map.size(); }
+
+    /**
+    * Returns a <code>Collection</code> that contains a copy of all cache entries.
+    * @return a <code>Collection</code> with a copy of the cache content.
+    */
+    public synchronized Collection<Map.Entry<K,V>> getAll() {
+       return new ArrayList<Map.Entry<K,V>>(map.entrySet()); }
+
+    } // end class LRUCache
+}
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/tools/walkers/beagle/VariantsToBeagleUnphased.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/tools/walkers/beagle/VariantsToBeagleUnphased.java
new file mode 100644
index 0000000..c45ceb2
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/tools/walkers/beagle/VariantsToBeagleUnphased.java
@@ -0,0 +1,184 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.tools.walkers.beagle;
+
+import org.broadinstitute.gatk.utils.commandline.Argument;
+import org.broadinstitute.gatk.utils.commandline.Input;
+import org.broadinstitute.gatk.utils.commandline.Output;
+import org.broadinstitute.gatk.utils.commandline.RodBinding;
+import org.broadinstitute.gatk.engine.CommandLineGATK;
+import org.broadinstitute.gatk.engine.contexts.AlignmentContext;
+import org.broadinstitute.gatk.engine.contexts.ReferenceContext;
+import org.broadinstitute.gatk.engine.refdata.RefMetaDataTracker;
+import org.broadinstitute.gatk.engine.walkers.RodWalker;
+import org.broadinstitute.gatk.utils.GenomeLoc;
+import org.broadinstitute.gatk.utils.SampleUtils;
+import org.broadinstitute.gatk.utils.help.HelpConstants;
+import org.broadinstitute.gatk.utils.variant.GATKVariantContextUtils;
+import htsjdk.variant.vcf.VCFHeader;
+import htsjdk.variant.vcf.VCFHeaderLine;
+import org.broadinstitute.gatk.utils.variant.GATKVCFUtils;
+import org.broadinstitute.gatk.utils.exceptions.UserException;
+import org.broadinstitute.gatk.utils.help.DocumentedGATKFeature;
+import htsjdk.variant.variantcontext.Allele;
+import htsjdk.variant.variantcontext.Genotype;
+import htsjdk.variant.variantcontext.VariantContext;
+import htsjdk.variant.variantcontext.writer.VariantContextWriter;
+
+import java.io.PrintStream;
+import java.util.Arrays;
+import java.util.Set;
+
+/**
+ * Produces an input file to Beagle imputation engine, listing unphased, hard-called genotypes for a single sample
+ * in input variant file.  Will additionally hold back a fraction of the sites for evaluation, marking the
+ * genotypes at that sites as missing, and writing the truth of these sites to a second VCF file
+ */
+ at DocumentedGATKFeature( groupName = HelpConstants.DOCS_CAT_VARDISC, extraDocs = {CommandLineGATK.class} )
+public class VariantsToBeagleUnphased extends RodWalker<Integer, Integer> {
+    @Input(fullName="variants", shortName = "V", doc="Input VCF file", required=true)
+    public RodBinding<VariantContext> variants;
+
+    @Output(doc="File to which BEAGLE unphased genotypes should be written")
+    protected PrintStream  beagleWriter = null;
+
+    @Argument(fullName = "bootstrap_fraction", shortName = "bs", doc = "Proportion of records to be used in bootstrap set", required = false)
+    public double bootstrap = 0.0;
+
+    @Argument(fullName = "bootstrap_vcf",shortName = "bsvcf", doc = "Output a VCF with the records used for bootstrapping filtered out", required = false)
+    VariantContextWriter bootstrapVCFOutput = null;
+
+    @Argument(fullName = "missing", shortName = "missing", doc = "String to identify missing data in beagle output", required = false)
+    public String MISSING = "?";
+
+    private Set<String> samples = null;
+    private int bootstrapSetSize = 0;
+    private int testSetSize = 0;
+
+    public void initialize() {
+        samples = SampleUtils.getSampleListWithVCFHeader(getToolkit(), Arrays.asList(variants.getName()));
+
+        beagleWriter.print("I marker alleleA alleleB");
+        for ( String sample : samples )
+            beagleWriter.print(String.format(" %s %s", sample, sample));
+
+        beagleWriter.println();
+
+        if ( bootstrap < 0.0 | bootstrap > 1.0 )
+            throw new UserException.BadArgumentValue("bootstrap", "Bootstrap value must be fraction between 0 and 1");
+
+        if ( bootstrapVCFOutput != null ) {
+            Set<VCFHeaderLine> hInfo = GATKVCFUtils.getHeaderFields(getToolkit());
+            bootstrapVCFOutput.writeHeader(new VCFHeader(hInfo, SampleUtils.getUniqueSamplesFromRods(getToolkit())));
+        }
+    }
+
+    /**
+     * Iterate over each site, emitting the BEAGLE unphased genotypes file format
+     * @param tracker
+     * @param ref
+     * @param context
+     * @return
+     */
+    public Integer map( RefMetaDataTracker tracker, ReferenceContext ref, AlignmentContext context ) {
+        if( tracker != null ) {
+            GenomeLoc loc = context.getLocation();
+            VariantContext vc = tracker.getFirstValue(variants, loc);
+
+            if ( ProduceBeagleInput.canBeOutputToBeagle(vc) ) {
+                // do we want to hold back this site?
+                boolean makeMissing = dropSite(vc);
+
+                // if we are holding it back and we are writing a bootstrap VCF, write it out
+                if ( makeMissing && bootstrapVCFOutput != null ) {
+                    bootstrapVCFOutput.add(vc);
+                }
+
+                // regardless, all sites are written to the unphased genotypes file, marked as missing if appropriate
+                writeUnphasedBeagleOutput(vc, makeMissing);
+            }
+        }
+
+        return 0;
+    }
+
+    /**
+     * Do we want to hold back this site for bootstrap?  Considers the bootstrap fraction member variable
+     *
+     * @param vc
+     * @return
+     */
+    public boolean dropSite(VariantContext vc) {
+        if ( (bootstrapSetSize+1.0)/(1.0+bootstrapSetSize+testSetSize) <= bootstrap ) {
+            bootstrapSetSize++;
+            return true;
+        } else {
+            testSetSize++;
+            return false;
+        }
+    }
+
+    public void writeUnphasedBeagleOutput(VariantContext vc, boolean makeMissing) {
+        GenomeLoc currentLoc = GATKVariantContextUtils.getLocation(getToolkit().getGenomeLocParser(), vc);
+        StringBuffer beagleOut = new StringBuffer();
+
+        String marker = String.format("%s:%d ",currentLoc.getContig(), currentLoc.getStart());
+        beagleOut.append("M ").append(marker);
+
+        // write out the alleles at this site
+        for ( Allele allele : vc.getAlleles() ) {
+            beagleOut.append(allele.isNoCall() ? "-" : allele.getBaseString()).append(" ");
+        }
+
+        // write out sample level genotypes
+        for ( String sample : samples ) {
+            Genotype genotype = vc.getGenotype(sample);
+            if ( ! makeMissing && genotype.isCalled() ) {
+                addAlleles(beagleOut, genotype);
+            } else {
+                addAlleles(beagleOut, MISSING, MISSING);
+            }
+        }
+
+        beagleWriter.println(beagleOut.toString());
+    }
+
+    private void addAlleles(StringBuffer buf, Genotype g) {
+        addAlleles(buf, g.getAllele(0).getBaseString(), g.getAllele(1).getBaseString());
+
+    }
+
+    private void addAlleles(StringBuffer buf, String a, String b) {
+        buf.append(a).append(" ").append(b);
+    }
+
+    public Integer reduceInit() { return 0; }
+    public Integer reduce( Integer value, Integer sum ) { return value + sum; }
+
+    public void onTraversalDone( Integer includedSites ) {
+        logger.info("Sites included in beagle genotypes file : " + includedSites);
+    }
+}
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/tools/walkers/coverage/CallableLoci.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/tools/walkers/coverage/CallableLoci.java
new file mode 100644
index 0000000..1757e7b
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/tools/walkers/coverage/CallableLoci.java
@@ -0,0 +1,396 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.tools.walkers.coverage;
+
+import org.broadinstitute.gatk.utils.commandline.Advanced;
+import org.broadinstitute.gatk.utils.commandline.Argument;
+import org.broadinstitute.gatk.utils.commandline.Output;
+import org.broadinstitute.gatk.engine.CommandLineGATK;
+import org.broadinstitute.gatk.engine.contexts.AlignmentContext;
+import org.broadinstitute.gatk.engine.contexts.ReferenceContext;
+import org.broadinstitute.gatk.engine.refdata.RefMetaDataTracker;
+import org.broadinstitute.gatk.engine.walkers.By;
+import org.broadinstitute.gatk.engine.walkers.DataSource;
+import org.broadinstitute.gatk.engine.walkers.LocusWalker;
+import org.broadinstitute.gatk.utils.*;
+import org.broadinstitute.gatk.utils.exceptions.UserException;
+import org.broadinstitute.gatk.utils.help.DocumentedGATKFeature;
+import org.broadinstitute.gatk.utils.help.HelpConstants;
+import org.broadinstitute.gatk.utils.pileup.PileupElement;
+
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.PrintStream;
+
+
+/**
+ * Emits a data file containing information about callable, uncallable, poorly mapped, and other parts of the genome
+ * <p/>
+ * <p>
+ * A very common question about a NGS set of reads is what areas of the genome are considered callable. The system
+ * considers the coverage at each locus and emits either a per base state or a summary interval BED file that
+ * partitions the genomic intervals into the following callable states:
+ * <dl>
+ * <dt>REF_N</dt>
+ * <dd>the reference base was an N, which is not considered callable the GATK</dd>
+ * <dt>PASS</dt>
+ * <dd>the base satisfied the min. depth for calling but had less than maxDepth to avoid having EXCESSIVE_COVERAGE</dd>
+ * <dt>NO_COVERAGE</dt>
+ * <dd>absolutely no reads were seen at this locus, regardless of the filtering parameters</dd>
+ * <dt>LOW_COVERAGE</dt>
+ * <dd>there were less than min. depth bases at the locus, after applying filters</dd>
+ * <dt>EXCESSIVE_COVERAGE</dt>
+ * <dd>more than -maxDepth read at the locus, indicating some sort of mapping problem</dd>
+ * <dt>POOR_MAPPING_QUALITY</dt>
+ * <dd>more than --maxFractionOfReadsWithLowMAPQ at the locus, indicating a poor mapping quality of the reads</dd>
+ * </dl>
+ * </p>
+ * <p/>
+ * <h3>Input</h3>
+ * <p>
+ * A BAM file containing <b>exactly one sample</b>.
+ * </p>
+ * <p/>
+ * <h3>Output</h3>
+ * <p>
+ * <ul>
+ * <li>-o: a OutputFormatted (recommended BED) file with the callable status covering each base</li>
+ * <li>-summary: a table of callable status x count of all examined bases</li>
+ * </ul>
+ * </p>
+ * <p/>
+ * <h3>Examples</h3>
+ * <pre>
+ *  java -jar GenomeAnalysisTK.jar \
+ *     -T CallableLoci \
+ *     -I my.bam \
+ *     -summary my.summary \
+ *     -o my.bed
+ * </pre>
+ * <p/>
+ * would produce a BED file (my.bed) that looks like:
+ * <p/>
+ * <pre>
+ *     20 10000000 10000864 PASS
+ *     20 10000865 10000985 POOR_MAPPING_QUALITY
+ *     20 10000986 10001138 PASS
+ *     20 10001139 10001254 POOR_MAPPING_QUALITY
+ *     20 10001255 10012255 PASS
+ *     20 10012256 10012259 POOR_MAPPING_QUALITY
+ *     20 10012260 10012263 PASS
+ *     20 10012264 10012328 POOR_MAPPING_QUALITY
+ *     20 10012329 10012550 PASS
+ *     20 10012551 10012551 LOW_COVERAGE
+ *     20 10012552 10012554 PASS
+ *     20 10012555 10012557 LOW_COVERAGE
+ *     20 10012558 10012558 PASS
+ *     et cetera...
+ * </pre>
+ * as well as a summary table that looks like:
+ * <p/>
+ * <pre>
+ *                        state nBases
+ *                        REF_N 0
+ *                     PASS 996046
+ *                  NO_COVERAGE 121
+ *                 LOW_COVERAGE 928
+ *           EXCESSIVE_COVERAGE 0
+ *         POOR_MAPPING_QUALITY 2906
+ * </pre>
+ *
+ * @author Mark DePristo
+ * @since May 7, 2010
+ */
+ at DocumentedGATKFeature( groupName = HelpConstants.DOCS_CAT_QC, extraDocs = {CommandLineGATK.class} )
+ at By(DataSource.REFERENCE)
+public class CallableLoci extends LocusWalker<CallableLoci.CallableBaseState, CallableLoci.Integrator> {
+    @Output
+    PrintStream out;
+
+    /**
+     * Callable loci summary counts (see outputs) will be written to this file.
+     */
+    @Output(fullName = "summary", shortName = "summary", doc = "Name of file for output summary", required = true)
+    File summaryFile;
+
+    /**
+     * The gap between this value and mmq are reads that are not sufficiently well mapped for calling but
+     * aren't indicative of mapping problems.  For example, if maxLowMAPQ = 1 and mmq = 20, then reads with
+     * MAPQ == 0 are poorly mapped, MAPQ >= 20 are considered as contributing to calling, where
+     * reads with MAPQ >= 1 and < 20 are not bad in and of themselves but aren't sufficiently good to contribute to
+     * calling.  In effect this reads are invisible, driving the base to the NO_ or LOW_COVERAGE states
+     */
+    @Argument(fullName = "maxLowMAPQ", shortName = "mlmq", doc = "Maximum value for MAPQ to be considered a problematic mapped read.", required = false)
+    byte maxLowMAPQ = 1;
+
+    /**
+     * Reads with MAPQ > minMappingQuality are treated as usable for variation detection, contributing to the PASS
+     * state.
+     */
+    @Argument(fullName = "minMappingQuality", shortName = "mmq", doc = "Minimum mapping quality of reads to count towards depth.", required = false)
+    byte minMappingQuality = 10;
+
+    /**
+     * Bases with less than minBaseQuality are viewed as not sufficiently high quality to contribute to the PASS state
+     */
+    @Argument(fullName = "minBaseQuality", shortName = "mbq", doc = "Minimum quality of bases to count towards depth.", required = false)
+    byte minBaseQuality = 20;
+
+    /**
+     * If the number of QC+ bases (on reads with MAPQ > minMappingQuality and with base quality > minBaseQuality) exceeds this
+     * value and is less than maxDepth the site is considered PASS.
+     */
+    @Advanced
+    @Argument(fullName = "minDepth", shortName = "minDepth", doc = "Minimum QC+ read depth before a locus is considered callable", required = false)
+    int minDepth = 4;
+
+    /**
+     * If the QC+ depth exceeds this value the site is considered to have EXCESSIVE_DEPTH
+     */
+    @Argument(fullName = "maxDepth", shortName = "maxDepth", doc = "Maximum read depth before a locus is considered poorly mapped", required = false)
+    int maxDepth = -1;
+
+    /**
+     * We don't want to consider a site as POOR_MAPPING_QUALITY just because it has two reads, and one is MAPQ.  We
+     * won't assign a site to the POOR_MAPPING_QUALITY state unless there are at least minDepthForLowMAPQ reads
+     * covering the site.
+     */
+    @Advanced
+    @Argument(fullName = "minDepthForLowMAPQ", shortName = "mdflmq", doc = "Minimum read depth before a locus is considered a potential candidate for poorly mapped", required = false)
+    int minDepthLowMAPQ = 10;
+
+    /**
+     * If the number of reads at this site is greater than minDepthForLowMAPQ and the fraction of reads with low mapping quality
+     * exceeds this fraction then the site has POOR_MAPPING_QUALITY.
+     */
+    @Argument(fullName = "maxFractionOfReadsWithLowMAPQ", shortName = "frlmq", doc = "If the fraction of reads at a base with low mapping quality exceeds this value, the site may be poorly mapped", required = false)
+    double maxLowMAPQFraction = 0.1;
+
+    /**
+     * The output of this walker will be written in this format.  The recommended option is BED.
+     */
+    @Advanced
+    @Argument(fullName = "format", shortName = "format", doc = "Output format", required = false)
+    OutputFormat outputFormat = OutputFormat.BED;
+
+    public enum OutputFormat {
+        /**
+         * The output will be written as a BED file.  There's a BED element for each
+         * continuous run of callable states (i.e., PASS, REF_N, etc).  This is the recommended
+         * format
+         */
+        BED,
+
+        /**
+         * Emit chr start stop state quads for each base.  Produces a potentially disasterously
+         * large amount of output.
+         */
+        STATE_PER_BASE
+    }
+
+    public enum CalledState {
+        /**
+         * the reference base was an N, which is not considered callable the GATK
+         */
+        REF_N,
+        /**
+         * the base satisfied the min. depth for calling but had less than maxDepth to avoid having EXCESSIVE_COVERAGE
+         */
+        CALLABLE,
+        /**
+         * absolutely no reads were seen at this locus, regardless of the filtering parameters
+         */
+        NO_COVERAGE,
+        /**
+         * there were less than min. depth bases at the locus, after applying filters
+         */
+        LOW_COVERAGE,
+        /**
+         * more than -maxDepth read at the locus, indicating some sort of mapping problem
+         */
+        EXCESSIVE_COVERAGE,
+        /**
+         * more than --maxFractionOfReadsWithLowMAPQ at the locus, indicating a poor mapping quality of the reads
+         */
+        POOR_MAPPING_QUALITY
+    }
+
+    ////////////////////////////////////////////////////////////////////////////////////
+    // STANDARD WALKER METHODS
+    ////////////////////////////////////////////////////////////////////////////////////
+
+    @Override
+    public boolean includeReadsWithDeletionAtLoci() {
+        return true;
+    }
+
+    @Override
+    public void initialize() {
+        if (getSampleDB().getSamples().size() != 1) {
+            throw new UserException.BadArgumentValue("-I", "CallableLoci only works for a single sample, but multiple samples were found in the provided BAM files: " + getSampleDB().getSamples());
+        }
+
+        try {
+            PrintStream summaryOut = new PrintStream(summaryFile);
+            summaryOut.close();
+        } catch (FileNotFoundException e) {
+            throw new UserException.CouldNotCreateOutputFile(summaryFile, e);
+        }
+    }
+
+    protected static class Integrator {
+        final long counts[] = new long[CalledState.values().length];
+        CallableBaseState state = null;
+    }
+
+    protected static class CallableBaseState implements HasGenomeLocation {
+        final public GenomeLocParser genomeLocParser;
+        public GenomeLoc loc;
+        final public CalledState state;
+
+        public CallableBaseState(GenomeLocParser genomeLocParser, GenomeLoc loc, CalledState state) {
+            this.genomeLocParser = genomeLocParser;
+            this.loc = loc;
+            this.state = state;
+        }
+
+        public GenomeLoc getLocation() {
+            return loc;
+        }
+
+        public CalledState getState() {
+            return state;
+        }
+
+        // update routines
+        public boolean changingState(CalledState newState) {
+            return state != newState;
+        }
+
+        /**
+         * Updating the location of this CalledBaseState by the new stop location
+         *
+         * @param newStop
+         */
+        public void update(GenomeLoc newStop) {
+            loc = genomeLocParser.createGenomeLoc(loc.getContig(), loc.getStart(), newStop.getStop());
+        }
+
+        public String toString() {
+            return String.format("%s\t%d\t%d\t%s", loc.getContig(), loc.getStart()-1, loc.getStop(), state);
+        }
+    }
+
+    @Override
+    public CallableBaseState map(RefMetaDataTracker tracker, ReferenceContext ref, AlignmentContext context) {
+        CalledState state;
+
+        if ( BaseUtils.isNBase(ref.getBase())) {
+            state = CalledState.REF_N;
+        } else {
+            // count up the depths of all and QC+ bases
+            int rawDepth = 0, QCDepth = 0, lowMAPQDepth = 0;
+            for (PileupElement e : context.getBasePileup()) {
+                rawDepth++;
+
+                if (e.getMappingQual() <= maxLowMAPQ)
+                    lowMAPQDepth++;
+
+                if (e.getMappingQual() >= minMappingQuality && (e.getQual() >= minBaseQuality || e.isDeletion())) {
+                    QCDepth++;
+                }
+            }
+
+            //System.out.printf("%s rawdepth = %d QCDepth = %d lowMAPQ = %d%n", context.getLocation(), rawDepth, QCDepth, lowMAPQDepth);
+            if (rawDepth == 0) {
+                state = CalledState.NO_COVERAGE;
+            } else if (rawDepth >= minDepthLowMAPQ && MathUtils.ratio(lowMAPQDepth, rawDepth) >= maxLowMAPQFraction) {
+                state = CalledState.POOR_MAPPING_QUALITY;
+            } else if (QCDepth < minDepth) {
+                state = CalledState.LOW_COVERAGE;
+            } else if (rawDepth >= maxDepth && maxDepth != -1) {
+                state = CalledState.EXCESSIVE_COVERAGE;
+            } else {
+                state = CalledState.CALLABLE;
+            }
+        }
+
+        return new CallableBaseState(getToolkit().getGenomeLocParser(), context.getLocation(), state);
+    }
+
+    @Override
+    public Integrator reduceInit() {
+        return new Integrator();
+    }
+
+    @Override
+    public Integrator reduce(CallableBaseState state, Integrator integrator) {
+        // update counts
+        integrator.counts[state.getState().ordinal()]++;
+
+        if (outputFormat == OutputFormat.STATE_PER_BASE) {
+            out.println(state.toString());
+        }
+
+        // format is integrating
+        if (integrator.state == null)
+            integrator.state = state;
+        else if (state.getLocation().getStart() != integrator.state.getLocation().getStop() + 1 ||
+                integrator.state.changingState(state.getState())) {
+            out.println(integrator.state.toString());
+            integrator.state = state;
+        } else {
+            integrator.state.update(state.getLocation());
+        }
+
+        return integrator;
+    }
+
+
+    ////////////////////////////////////////////////////////////////////////////////////
+    // INTERVAL ON TRAVERSAL DONE
+    ////////////////////////////////////////////////////////////////////////////////////
+
+    @Override
+    public void onTraversalDone(Integrator result) {
+        // print out the last state
+        if (result != null) {
+            if (outputFormat == OutputFormat.BED)  // get the last interval
+                out.println(result.state.toString());
+
+            try {
+                PrintStream summaryOut = new PrintStream(summaryFile);
+                summaryOut.printf("%30s %s%n", "state", "nBases");
+                for (CalledState state : CalledState.values()) {
+                    summaryOut.printf("%30s %d%n", state, result.counts[state.ordinal()]);
+                }
+                summaryOut.close();
+            } catch (FileNotFoundException e) {
+                throw new UserException.CouldNotCreateOutputFile(summaryFile, e);
+            }
+        }
+    }
+}
\ No newline at end of file
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/tools/walkers/coverage/CompareCallableLoci.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/tools/walkers/coverage/CompareCallableLoci.java
new file mode 100644
index 0000000..9ab8555
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/tools/walkers/coverage/CompareCallableLoci.java
@@ -0,0 +1,143 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.tools.walkers.coverage;
+
+import htsjdk.tribble.bed.BEDFeature;
+import org.broadinstitute.gatk.utils.commandline.Argument;
+import org.broadinstitute.gatk.utils.commandline.Input;
+import org.broadinstitute.gatk.utils.commandline.Output;
+import org.broadinstitute.gatk.utils.commandline.RodBinding;
+import org.broadinstitute.gatk.engine.CommandLineGATK;
+import org.broadinstitute.gatk.engine.contexts.AlignmentContext;
+import org.broadinstitute.gatk.engine.contexts.ReferenceContext;
+import org.broadinstitute.gatk.engine.refdata.RefMetaDataTracker;
+import org.broadinstitute.gatk.engine.walkers.RodWalker;
+import org.broadinstitute.gatk.utils.GenomeLoc;
+import org.broadinstitute.gatk.utils.exceptions.UserException;
+import org.broadinstitute.gatk.utils.help.DocumentedGATKFeature;
+import org.broadinstitute.gatk.utils.help.HelpConstants;
+
+import java.io.PrintStream;
+import java.util.Arrays;
+import java.util.List;
+
+/**
+ * Test routine for new VariantContext object
+ */
+ at DocumentedGATKFeature( groupName = HelpConstants.DOCS_CAT_QC, extraDocs = {CommandLineGATK.class} )
+public class CompareCallableLoci extends RodWalker<List<CallableLoci.CallableBaseState>, long[][]> {
+    @Output
+    protected PrintStream out;
+
+    @Input(fullName="comp1", shortName = "comp1", doc="First comparison track name", required=true)
+    public RodBinding<BEDFeature> compTrack1;
+
+    @Input(fullName="comp2", shortName = "comp2", doc="Second comparison track name", required=true)
+    public RodBinding<BEDFeature> compTrack2;
+
+    @Argument(shortName="printState", doc="If provided, prints sites satisfying this state pair", required=false)
+    protected String printState = null;
+
+    CallableLoci.CalledState printState1 = CallableLoci.CalledState.REF_N;
+    CallableLoci.CalledState printState2 = CallableLoci.CalledState.REF_N;
+
+    // --------------------------------------------------------------------------------------------------------------
+    //
+    // initialize
+    //
+    // --------------------------------------------------------------------------------------------------------------
+
+    public void initialize() {
+        if ( printState != null ) {
+            String[] states = printState.split(",");
+            printState1 = CallableLoci.CalledState.valueOf(states[0]);
+            printState2 = CallableLoci.CalledState.valueOf(states[1]);
+        }
+    }
+
+
+    // --------------------------------------------------------------------------------------------------------------
+    //
+    // map
+    //
+    // --------------------------------------------------------------------------------------------------------------
+    public List<CallableLoci.CallableBaseState> map(RefMetaDataTracker tracker, ReferenceContext ref, AlignmentContext context) {
+        if ( tracker != null ) {
+            CallableLoci.CallableBaseState comp1 = getCallableBaseState(tracker, compTrack1);
+            CallableLoci.CallableBaseState comp2 = getCallableBaseState(tracker, compTrack2);
+
+            if ( printState != null && comp1.getState() == printState1 && comp2.getState() == printState2 ) {
+                out.printf("%s %s %s %s%n", comp1.getLocation(), comp1.getState(), comp2.getLocation(), comp2.getState());
+            }
+
+            return Arrays.asList(comp1, comp2);
+        } else {
+            return null;
+        }
+    }
+
+    private CallableLoci.CallableBaseState getCallableBaseState(RefMetaDataTracker tracker, RodBinding<BEDFeature> rodBinding) {
+        //System.out.printf("tracker %s%n", tracker);
+        List<BEDFeature> bindings = tracker.getValues(rodBinding);
+        if ( bindings.size() != 1 ) {
+            throw new UserException.MalformedFile(String.format("%s track isn't a properly formated CallableBases object!", rodBinding.getName()));
+        }
+
+        BEDFeature bed = bindings.get(0);
+        GenomeLoc loc = getToolkit().getGenomeLocParser().createGenomeLoc(bed.getChr(), bed.getStart(), bed.getEnd());
+        CallableLoci.CalledState state = CallableLoci.CalledState.valueOf(bed.getName());
+        return new CallableLoci.CallableBaseState(getToolkit().getGenomeLocParser(),loc, state);
+    }
+
+    // --------------------------------------------------------------------------------------------------------------
+    //
+    // reduce
+    //
+    // --------------------------------------------------------------------------------------------------------------
+    public long[][] reduceInit() {
+        int n = CallableLoci.CalledState.values().length;
+        return new long[n][n];
+    }
+
+    public long[][] reduce(List<CallableLoci.CallableBaseState> comps, long[][] sum) {
+        if ( comps != null ) {
+            CallableLoci.CallableBaseState comp1 = comps.get(0);
+            CallableLoci.CallableBaseState comp2 = comps.get(1);
+
+            sum[comp1.getState().ordinal()][comp2.getState().ordinal()]++;
+        }
+
+        return sum;
+    }
+
+    public void onTraversalDone(long[][] result) {
+        for ( CallableLoci.CalledState state1 : CallableLoci.CalledState.values() ) {
+            for ( CallableLoci.CalledState state2 : CallableLoci.CalledState.values() ) {
+                out.printf("%s %s %s %s %d%n", compTrack1.getName(), compTrack2.getName(), state1, state2, result[state1.ordinal()][state2.ordinal()]);
+            }
+        }
+    }
+}
\ No newline at end of file
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/tools/walkers/coverage/CoverageUtils.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/tools/walkers/coverage/CoverageUtils.java
new file mode 100644
index 0000000..7514fa5
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/tools/walkers/coverage/CoverageUtils.java
@@ -0,0 +1,241 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.tools.walkers.coverage;
+
+import htsjdk.samtools.SAMReadGroupRecord;
+import htsjdk.samtools.SAMRecord;
+import org.broadinstitute.gatk.engine.contexts.AlignmentContext;
+import org.broadinstitute.gatk.utils.BaseUtils;
+import org.broadinstitute.gatk.utils.exceptions.ReviewedGATKException;
+import org.broadinstitute.gatk.utils.exceptions.UserException;
+import org.broadinstitute.gatk.utils.fragments.FragmentCollection;
+import org.broadinstitute.gatk.utils.pileup.PileupElement;
+
+import java.util.*;
+
+/**
+ * IF THERE IS NO JAVADOC RIGHT HERE, YELL AT chartl
+ *
+ * @Author chartl
+ * @Date Mar 3, 2010
+ */
+public class CoverageUtils {
+
+    public enum CountPileupType {
+        /**
+         * Count all reads independently (even if from the same fragment).
+         */
+        COUNT_READS,
+        /**
+         * Count all fragments (even if the reads that compose the fragment are not consistent at that base).
+         */
+        COUNT_FRAGMENTS,
+        /**
+         * Count all fragments (but only if the reads that compose the fragment are consistent at that base).
+         */
+        COUNT_FRAGMENTS_REQUIRE_SAME_BASE
+    }
+
+    /**
+     * Returns the counts of bases from reads with MAPQ > minMapQ and base quality > minBaseQ in the context
+     * as an array of ints, indexed by the index fields of BaseUtils
+     *
+     * @param context
+     * @param minMapQ
+     * @param minBaseQ
+     * @return
+     */
+    public static int[] getBaseCounts(AlignmentContext context, int minMapQ, int minBaseQ) {
+        int[] counts = new int[6];
+
+        for (PileupElement e : context.getBasePileup()) {
+            if ( e.getMappingQual() >= minMapQ && ( e.getQual() >= minBaseQ || e.isDeletion() ) ) {
+                updateCounts(counts,e);
+            }
+        }
+
+        return counts;
+    }
+
+    public static String getTypeID( SAMReadGroupRecord r, DoCOutputType.Partition type ) {
+        if ( type == DoCOutputType.Partition.sample ) {
+            return r.getSample();
+        } else if ( type == DoCOutputType.Partition.readgroup ) {
+            return String.format("%s_rg_%s",r.getSample(),r.getReadGroupId());
+        } else if ( type == DoCOutputType.Partition.library ) {
+            return r.getLibrary();
+        } else if ( type == DoCOutputType.Partition.center ) {
+            return r.getSequencingCenter();
+        } else if ( type == DoCOutputType.Partition.platform ) {
+            return r.getPlatform();
+        } else if ( type == DoCOutputType.Partition.sample_by_center ) {
+            return String.format("%s_cn_%s",r.getSample(),r.getSequencingCenter());
+        } else if ( type == DoCOutputType.Partition.sample_by_platform) {
+            return String.format("%s_pl_%s",r.getSample(),r.getPlatform());
+        } else if ( type == DoCOutputType.Partition.sample_by_platform_by_center ) {
+            return String.format("%s_pl_%s_cn_%s",r.getSample(),r.getPlatform(),r.getSequencingCenter());
+        } else {
+            throw new ReviewedGATKException("Invalid type ID sent to getTypeID. This is a BUG!");
+        }
+    }
+
+    public static Map<DoCOutputType.Partition,Map<String,int[]>>
+                    getBaseCountsByPartition(AlignmentContext context, int minMapQ, int maxMapQ, byte minBaseQ, byte maxBaseQ, CountPileupType countType, Collection<DoCOutputType.Partition> types) {
+
+        Map<DoCOutputType.Partition,Map<String,int[]>> countsByIDByType = new HashMap<DoCOutputType.Partition,Map<String,int[]>>();
+        Map<SAMReadGroupRecord,int[]> countsByRG = getBaseCountsByReadGroup(context,minMapQ,maxMapQ,minBaseQ,maxBaseQ,countType);
+        for (DoCOutputType.Partition t : types ) {
+            // iterate through the read group counts and build the type associations
+            for ( Map.Entry<SAMReadGroupRecord,int[]> readGroupCountEntry : countsByRG.entrySet() ) {
+                String typeID = getTypeID(readGroupCountEntry.getKey(),t);
+
+                if ( ! countsByIDByType.keySet().contains(t) ) {
+                    countsByIDByType.put(t,new HashMap<String,int[]>());
+                }
+
+                if ( ! countsByIDByType.get(t).keySet().contains(typeID) ) {
+                    countsByIDByType.get(t).put(typeID,readGroupCountEntry.getValue().clone());
+                } else {
+                    addCounts(countsByIDByType.get(t).get(typeID),readGroupCountEntry.getValue());
+                }
+            }
+        }
+
+
+        return countsByIDByType;
+    }
+
+    public static void addCounts(int[] updateMe, int[] leaveMeAlone ) {
+        for ( int index = 0; index < leaveMeAlone.length; index++ ) {
+            updateMe[index] += leaveMeAlone[index];
+        }
+    }
+
+    public static Map<SAMReadGroupRecord,int[]> getBaseCountsByReadGroup(AlignmentContext context, int minMapQ, int maxMapQ, byte minBaseQ, byte maxBaseQ, CountPileupType countType) {
+        Map<SAMReadGroupRecord, int[]> countsByRG = new HashMap<SAMReadGroupRecord,int[]>();
+
+        List<PileupElement> countPileup = new LinkedList<PileupElement>();
+        FragmentCollection<PileupElement> fpile;
+
+        switch (countType) {
+
+            case COUNT_READS:
+                for (PileupElement e : context.getBasePileup())
+                    if (countElement(e, minMapQ, maxMapQ, minBaseQ, maxBaseQ))
+                        countPileup.add(e);
+                break;
+
+            case COUNT_FRAGMENTS: // ignore base identities and put in FIRST base that passes filters:
+                fpile = context.getBasePileup().getStartSortedPileup().toFragments();
+
+                for (PileupElement e : fpile.getSingletonReads())
+                    if (countElement(e, minMapQ, maxMapQ, minBaseQ, maxBaseQ))
+                        countPileup.add(e);
+
+                for (List<PileupElement> overlappingPair : fpile.getOverlappingPairs()) {
+                    // iterate over all elements in fragment:
+                    for (PileupElement e : overlappingPair) {
+                        if (countElement(e, minMapQ, maxMapQ, minBaseQ, maxBaseQ)) {
+                            countPileup.add(e); // add the first passing element per fragment
+                            break;
+                        }
+                    }
+                }
+                break;
+
+            case COUNT_FRAGMENTS_REQUIRE_SAME_BASE:
+                fpile = context.getBasePileup().getStartSortedPileup().toFragments();
+
+                for (PileupElement e : fpile.getSingletonReads())
+                    if (countElement(e, minMapQ, maxMapQ, minBaseQ, maxBaseQ))
+                        countPileup.add(e);
+
+                for (List<PileupElement> overlappingPair : fpile.getOverlappingPairs()) {
+                    PileupElement firstElem = null;
+                    PileupElement addElem = null;
+
+                    // iterate over all elements in fragment:
+                    for (PileupElement e : overlappingPair) {
+                        if (firstElem == null)
+                            firstElem = e;
+                        else if (e.getBase() != firstElem.getBase()) {
+                            addElem = null;
+                            break;
+                        }
+
+                        // will add the first passing element per base-consistent fragment:
+                        if (addElem == null && countElement(e, minMapQ, maxMapQ, minBaseQ, maxBaseQ))
+                            addElem = e;
+                    }
+
+                    if (addElem != null)
+                        countPileup.add(addElem);
+                }
+                break;
+
+            default:
+                throw new UserException("Must use valid CountPileupType");
+        }
+
+        for (PileupElement e : countPileup) {
+            SAMReadGroupRecord readGroup = getReadGroup(e.getRead());
+            if (!countsByRG.keySet().contains(readGroup))
+                countsByRG.put(readGroup, new int[6]);
+
+            updateCounts(countsByRG.get(readGroup), e);
+        }
+
+        return countsByRG;
+    }
+
+    private static boolean countElement(PileupElement e, int minMapQ, int maxMapQ, byte minBaseQ, byte maxBaseQ) {
+        return (e.getMappingQual() >= minMapQ && e.getMappingQual() <= maxMapQ && ( e.getQual() >= minBaseQ && e.getQual() <= maxBaseQ || e.isDeletion() ));
+    }
+
+    private static void updateCounts(int[] counts, PileupElement e) {
+        if ( e.isDeletion() ) {
+            counts[BaseUtils.Base.D.ordinal()]++;
+        } else if ( BaseUtils.basesAreEqual(BaseUtils.Base.N.base, e.getBase()) ) {
+            counts[BaseUtils.Base.N.ordinal()]++;
+        } else {
+            try {
+                counts[BaseUtils.simpleBaseToBaseIndex(e.getBase())]++;
+            } catch (ArrayIndexOutOfBoundsException exc) {
+                throw new ReviewedGATKException("Expected a simple base, but actually received"+(char)e.getBase());
+            }
+        }
+    }
+
+    private static SAMReadGroupRecord getReadGroup(SAMRecord r) {
+        SAMReadGroupRecord rg = r.getReadGroup();
+        if ( rg == null ) {
+            String msg = "Read "+r.getReadName()+" lacks read group information; Please associate all reads with read groups";
+            throw new UserException.MalformedBAM(r, msg);
+        }
+
+        return rg;
+    }
+}
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/tools/walkers/coverage/DepthOfCoverage.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/tools/walkers/coverage/DepthOfCoverage.java
new file mode 100644
index 0000000..3fc2e59
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/tools/walkers/coverage/DepthOfCoverage.java
@@ -0,0 +1,1110 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.tools.walkers.coverage;
+
+import htsjdk.samtools.SAMReadGroupRecord;
+import org.broadinstitute.gatk.engine.walkers.*;
+import org.broadinstitute.gatk.utils.commandline.Advanced;
+import org.broadinstitute.gatk.utils.commandline.Argument;
+import org.broadinstitute.gatk.utils.commandline.Output;
+import org.broadinstitute.gatk.engine.CommandLineGATK;
+import org.broadinstitute.gatk.engine.downsampling.DownsampleType;
+import org.broadinstitute.gatk.engine.contexts.AlignmentContext;
+import org.broadinstitute.gatk.engine.contexts.ReferenceContext;
+import org.broadinstitute.gatk.engine.refdata.RefMetaDataTracker;
+import org.broadinstitute.gatk.engine.refdata.SeekableRODIterator;
+import org.broadinstitute.gatk.engine.refdata.tracks.RMDTrack;
+import org.broadinstitute.gatk.engine.refdata.tracks.RMDTrackBuilder;
+import org.broadinstitute.gatk.engine.refdata.utils.GATKFeature;
+import org.broadinstitute.gatk.engine.refdata.utils.LocationAwareSeekableRODIterator;
+import org.broadinstitute.gatk.engine.refdata.utils.RODRecordList;
+import org.broadinstitute.gatk.utils.BaseUtils;
+import org.broadinstitute.gatk.utils.GenomeLoc;
+import org.broadinstitute.gatk.utils.SampleUtils;
+import org.broadinstitute.gatk.utils.codecs.refseq.RefSeqCodec;
+import org.broadinstitute.gatk.utils.codecs.refseq.RefSeqFeature;
+import org.broadinstitute.gatk.utils.collections.Pair;
+import org.broadinstitute.gatk.utils.exceptions.ReviewedGATKException;
+import org.broadinstitute.gatk.utils.exceptions.UserException;
+import org.broadinstitute.gatk.utils.help.DocumentedGATKFeature;
+import org.broadinstitute.gatk.utils.help.HelpConstants;
+
+import java.io.File;
+import java.io.PrintStream;
+import java.util.*;
+
+/**
+ * Assess sequence coverage by a wide array of metrics, partitioned by sample, read group, or library
+ *
+ * <p>
+ * This tool processes a set of bam files to determine coverage at different levels of partitioning and
+ * aggregation. Coverage can be analyzed per locus, per interval, per gene, or in total; can be partitioned by
+ * sample, by read group, by technology, by center, or by library; and can be summarized by mean, median, quartiles,
+ * and/or percentage of bases covered to or beyond a threshold.
+ * Additionally, reads and bases can be filtered by mapping or base quality score.
+ *
+ * <h3>Input</h3>
+ * <p>
+ * One or more bam files (with proper headers) to be analyzed for coverage statistics
+ * </p>
+ * <p>
+ *(Optional) A REFSEQ Rod to aggregate coverage to the gene level
+ * <p>
+ * (for information about creating the REFSEQ Rod, please consult the online documentation)
+ *</p></p>
+ * <h3>Output</h3>
+ * <p>
+ * Tables pertaining to different coverage summaries. Suffix on the table files declares the contents:
+ * </p><p>
+ *  - no suffix: per locus coverage
+ * </p><p>
+ *  - _summary: total, mean, median, quartiles, and threshold proportions, aggregated over all bases
+ * </p><p>
+ *  - _statistics: coverage histograms (# locus with X coverage), aggregated over all bases
+ * </p><p>
+ *  - _interval_summary: total, mean, median, quartiles, and threshold proportions, aggregated per interval
+ * </p><p>
+ *  - _interval_statistics: 2x2 table of # of intervals covered to >= X depth in >=Y samples
+ * </p><p>
+ *  - _gene_summary: total, mean, median, quartiles, and threshold proportions, aggregated per gene
+ * </p><p>
+ *  - _gene_statistics: 2x2 table of # of genes covered to >= X depth in >= Y samples
+ * </p><p>
+ *  - _cumulative_coverage_counts: coverage histograms (# locus with >= X coverage), aggregated over all bases
+ * </p><p>
+ *  - _cumulative_coverage_proportions: proprotions of loci with >= X coverage, aggregated over all bases
+ * </p>
+ *
+ * <h3>Examples</h3>
+ * <pre>
+ * java -Xmx2g -jar GenomeAnalysisTK.jar \
+ *   -R ref.fasta \
+ *   -T DepthOfCoverage \
+ *   -o file_name_base \
+ *   -I input_bams.list
+ *   [-geneList refSeq.sorted.txt] \
+ *   [-pt readgroup] \
+ *   [-ct 4 -ct 6 -ct 10] \
+ *   [-L my_capture_genes.interval_list]
+ * </pre>
+ *
+ */
+// todo -- cache the map from sample names to means in the print functions, rather than regenerating each time
+// todo -- support for granular histograms for total depth; maybe n*[start,stop], bins*sqrt(n)
+// todo -- alter logarithmic scaling to spread out bins more
+// todo -- allow for user to set linear binning (default is logarithmic)
+// todo -- formatting --> do something special for end bins in getQuantile(int[] foo), this gets mushed into the end+-1 bins for now
+ at DocumentedGATKFeature( groupName = HelpConstants.DOCS_CAT_QC, extraDocs = {CommandLineGATK.class}, gotoDev = HelpConstants.MC)
+ at By(DataSource.REFERENCE)
+ at PartitionBy(PartitionType.NONE)
+ at Downsample(by= DownsampleType.NONE, toCoverage=Integer.MAX_VALUE)
+public class DepthOfCoverage extends LocusWalker<Map<DoCOutputType.Partition,Map<String,int[]>>, CoveragePartitioner> implements TreeReducible<CoveragePartitioner> {
+    @Output
+    @Multiplex(value=DoCOutputMultiplexer.class,arguments={"partitionTypes","refSeqGeneList","omitDepthOutput","omitIntervals","omitSampleSummary","omitLocusTable"})
+    Map<DoCOutputType,PrintStream> out;
+    /**
+     * Reads with mapping quality values lower than this threshold will be skipped. This is set to -1 by default to disable the evaluation and ignore this threshold.
+     */
+    @Argument(fullName = "minMappingQuality", shortName = "mmq", doc = "Minimum mapping quality of reads to count towards depth", required = false, minValue = 0, maxValue = Integer.MAX_VALUE)
+    int minMappingQuality = -1;
+    /**
+     * Reads with mapping quality values higher than this threshold will be skipped. The default value is the largest number that can be represented as an integer by the program.
+     */
+    @Argument(fullName = "maxMappingQuality", doc = "Maximum mapping quality of reads to count towards depth", required = false, minValue = 0, maxValue = Integer.MAX_VALUE)
+    int maxMappingQuality = Integer.MAX_VALUE;
+    /**
+     * Bases with quality scores lower than this threshold will be skipped. This is set to -1 by default to disable the evaluation and ignore this threshold.
+     */
+    @Argument(fullName = "minBaseQuality", shortName = "mbq", doc = "Minimum quality of bases to count towards depth", required = false, minValue = 0, maxValue = Byte.MAX_VALUE)
+    byte minBaseQuality = -1;
+    /**
+     * Bases with quality scores higher than this threshold will be skipped. The default value is the largest number that can be represented as a byte.
+     */
+    @Argument(fullName = "maxBaseQuality", doc = "Maximum quality of bases to count towards depth", required = false, minValue = 0, maxValue = Byte.MAX_VALUE)
+    byte maxBaseQuality = Byte.MAX_VALUE;
+
+    @Argument(fullName = "countType", doc = "How should overlapping reads from the same fragment be handled?", required = false)
+    CoverageUtils.CountPileupType countType = CoverageUtils.CountPileupType.COUNT_READS;
+
+    /**
+     * Instead of reporting depth, the program will report the base pileup at each locus
+     */
+    @Argument(fullName = "printBaseCounts", shortName = "baseCounts", doc = "Add base counts to per-locus output", required = false)
+    boolean printBaseCounts = false;
+
+    /**
+     * Disabling the tabulation of locus statistics (# loci covered by sample by coverage) should speed up processing.
+     */
+    @Argument(fullName = "omitLocusTable", shortName = "omitLocusTable", doc = "Do not calculate per-sample per-depth counts of loci", required = false)
+    boolean omitLocusTable = false;
+
+    /**
+     * Disabling the tabulation of interval statistics (mean, median, quartiles AND # intervals by sample by coverage) should speed up processing. This option is required in order to use -nt parallelism.
+     */
+    @Argument(fullName = "omitIntervalStatistics", shortName = "omitIntervals", doc = "Do not calculate per-interval statistics", required = false)
+    boolean omitIntervals = false;
+    /**
+     * Disabling the tabulation of total coverage at every base should speed up processing.
+     */
+    @Argument(fullName = "omitDepthOutputAtEachBase", shortName = "omitBaseOutput", doc = "Do not output depth of coverage at each base", required = false)
+    boolean omitDepthOutput = false;
+
+    /**
+     * Specify a RefSeq file for use in aggregating coverage statistics over genes.
+     */
+    @Argument(fullName = "calculateCoverageOverGenes", shortName = "geneList", doc = "Calculate coverage statistics over this list of genes", required = false)
+    File refSeqGeneList = null;
+
+    /**
+     * Output file format (e.g. csv, table, rtable); defaults to r-readable table.
+     */
+    @Argument(fullName = "outputFormat", doc = "The format of the output file", required = false)
+    String outputFormat = "rtable";
+
+
+    // ---------------------------------------------------------------------------
+    //
+    // Advanced arguments
+    //
+    // ---------------------------------------------------------------------------
+
+    /**
+     * Normally, sites where the reference is N (or another non-canonical base) are skipped. If this option is enabled, these sites will be included in DoC calculations if there is coverage from neighboring reads.
+     */
+    @Advanced
+    @Argument(fullName = "includeRefNSites", doc = "Include sites where the reference is N", required = false)
+    boolean includeRefNBases = false;
+    /**
+     * Use this option to calibrate what bins you want before performing full calculations on your data.
+     */
+    @Advanced
+    @Argument(fullName = "printBinEndpointsAndExit", doc = "Print the bin values and exit immediately", required = false)
+    boolean printBinEndpointsAndExit = false;
+    /**
+     * Sets the low-coverage cutoff for granular binning. All loci with depth < START are counted in the first bin.
+     */
+    @Advanced
+    @Argument(fullName = "start", doc = "Starting (left endpoint) for granular binning", required = false, minValue = 0)
+    int start = 1;
+    /**
+     * Sets the high-coverage cutoff for granular binning. All loci with depth > STOP are counted in the last bin.
+     */
+    @Advanced
+    @Argument(fullName = "stop", doc = "Ending (right endpoint) for granular binning", required = false, minValue = 1)
+    int stop = 500;
+    /**
+     * Sets the number of bins for granular binning
+     */
+    @Advanced
+    @Argument(fullName = "nBins", doc = "Number of bins to use for granular binning", required = false, minValue = 0, minRecommendedValue = 1)
+    int nBins = 499;
+
+    /**
+     * This option simply disables writing separate files for per-sample summary statistics (total, mean, median, quartile coverage per sample). These statistics are still calculated internally, so enabling this option will not improve runtime.
+     */
+    @Argument(fullName = "omitPerSampleStats", shortName = "omitSampleSummary", doc = "Do not output the summary files per-sample", required = false)
+    boolean omitSampleSummary = false;
+    /**
+     * By default, coverage is partitioning by sample, but it can be any combination of sample, readgroup and/or library.
+     */
+    @Argument(fullName = "partitionType", shortName = "pt", doc = "Partition type for depth of coverage", required = false)
+    Set<DoCOutputType.Partition> partitionTypes = EnumSet.of(DoCOutputType.Partition.sample);
+
+    /**
+     * Consider a spanning deletion as contributing to coverage. Also enables deletion counts in per-base output.
+     */
+    @Advanced
+    @Argument(fullName = "includeDeletions", shortName = "dels", doc = "Include information on deletions", required = false)
+    boolean includeDeletions = false;
+
+    @Advanced
+    @Argument(fullName = "ignoreDeletionSites", doc = "Ignore sites consisting only of deletions", required = false)
+    boolean ignoreDeletionSites = false;
+    
+    /**
+     * For summary file outputs, report the percentage of bases covered to an amount equal to or greater than this number  (e.g. % bases >= CT for each sample). Defaults to 15; can take multiple arguments.
+     */
+    @Advanced
+    @Argument(fullName = "summaryCoverageThreshold", shortName = "ct", doc = "Coverage threshold (in percent) for summarizing statistics", required = false)
+    int[] coverageThresholds = {15};
+
+    String[] OUTPUT_FORMATS = {"table","rtable","csv"};
+    String separator = "\t";
+    Map<DoCOutputType.Partition,List<String>> orderCheck = new HashMap<DoCOutputType.Partition,List<String>>();
+
+    ////////////////////////////////////////////////////////////////////////////////////
+    // STANDARD WALKER METHODS
+    ////////////////////////////////////////////////////////////////////////////////////
+
+    public boolean includeReadsWithDeletionAtLoci() { return includeDeletions && ! ignoreDeletionSites; }
+
+    public void initialize() {
+
+        if ( printBinEndpointsAndExit ) {
+            int[] endpoints = DepthOfCoverageStats.calculateBinEndpoints(start,stop,nBins);
+            System.out.print("[ ");
+            for ( int e : endpoints ) {
+                System.out.print(e+" ");
+            }
+            System.out.println("]");
+            System.exit(0);
+        }
+
+        // Check the output format
+        boolean goodOutputFormat = false;
+        for ( String f : OUTPUT_FORMATS ) {
+            goodOutputFormat = goodOutputFormat || f.equals(outputFormat);
+        }
+
+        if ( ! goodOutputFormat ) {
+            throw new IllegalArgumentException("Improper output format. Can be one of table,rtable,csv. Was "+outputFormat);
+        }
+
+        if ( outputFormat.equals("csv") ) {
+            separator = ",";
+        }
+
+        if ( ! omitDepthOutput ) { // print header
+            PrintStream out = getCorrectStream(null, DoCOutputType.Aggregation.locus, DoCOutputType.FileType.summary);
+            out.printf("%s\t%s","Locus","Total_Depth");
+            for (DoCOutputType.Partition type : partitionTypes ) {
+                out.printf("\t%s_%s","Average_Depth",type.toString());
+            }
+            
+            // get all the samples
+            HashSet<String> allSamples = getSamplesFromToolKit(partitionTypes);
+            ArrayList<String> allSampleList = new ArrayList<String>(allSamples.size());
+            for ( String s : allSamples ) {
+                allSampleList.add(s);
+            }
+            Collections.sort(allSampleList);
+
+            for ( String s : allSampleList) {
+                out.printf("\t%s_%s","Depth_for",s);
+                if ( printBaseCounts ) {
+                    out.printf("\t%s_%s",s,"base_counts");
+                }
+            }
+
+            out.printf("%n");
+
+        } else {
+            logger.info("Per-Locus Depth of Coverage output was omitted");
+        }
+
+        for (DoCOutputType.Partition type : partitionTypes ) {
+            orderCheck.put(type,new ArrayList<String>());
+            for ( String id : getSamplesFromToolKit(type) ) {
+                orderCheck.get(type).add(id);
+            }
+            Collections.sort(orderCheck.get(type));
+        }
+    }
+
+    private HashSet<String> getSamplesFromToolKit( Collection<DoCOutputType.Partition> types ) {
+        HashSet<String> partitions = new HashSet<String>(); // since the DOCS object uses a HashMap, this will be in the same order
+        for (DoCOutputType.Partition t : types ) {
+            partitions.addAll(getSamplesFromToolKit(t));
+        }
+
+        return partitions;
+    }
+
+    private HashSet<String> getSamplesFromToolKit(DoCOutputType.Partition type) {
+        HashSet<String> partition = new HashSet<String>();
+        if ( type == DoCOutputType.Partition.sample ) {
+            partition.addAll(SampleUtils.getSAMFileSamples(getToolkit()));
+        } else if ( type == DoCOutputType.Partition.readgroup ) {
+            for ( SAMReadGroupRecord rg : getToolkit().getSAMFileHeader().getReadGroups() ) {
+                partition.add(rg.getSample()+"_rg_"+rg.getReadGroupId());
+            }
+        } else if ( type == DoCOutputType.Partition.library ) {
+            for ( SAMReadGroupRecord rg : getToolkit().getSAMFileHeader().getReadGroups() ) {
+                partition.add(rg.getLibrary());
+            }
+        } else if ( type == DoCOutputType.Partition.center ) {
+            for ( SAMReadGroupRecord rg : getToolkit().getSAMFileHeader().getReadGroups() ) {
+                partition.add(rg.getSequencingCenter());
+            }
+        } else if ( type == DoCOutputType.Partition.platform ) {
+            for ( SAMReadGroupRecord rg : getToolkit().getSAMFileHeader().getReadGroups() ) {
+                partition.add(rg.getPlatform());
+            }
+        } else if ( type == DoCOutputType.Partition.sample_by_center ) {
+            for ( SAMReadGroupRecord rg : getToolkit().getSAMFileHeader().getReadGroups() ) {
+                partition.add(String.format("%s_cn_%s",rg.getSample(),rg.getSequencingCenter()));
+            }
+        } else if ( type == DoCOutputType.Partition.sample_by_platform ) {
+            for ( SAMReadGroupRecord rg : getToolkit().getSAMFileHeader().getReadGroups() ) {
+                partition.add(String.format("%s_pl_%s",rg.getSample(),rg.getPlatform()));
+            }
+        } else if ( type == DoCOutputType.Partition.sample_by_platform_by_center ) {
+            for ( SAMReadGroupRecord rg : getToolkit().getSAMFileHeader().getReadGroups() ) {
+                partition.add(String.format("%s_pl_%s_cn_%s",rg.getSample(),rg.getPlatform(),rg.getSequencingCenter()));
+            }
+        } else {
+            throw new ReviewedGATKException("Invalid aggregation type sent to getSamplesFromToolKit");
+        }
+
+        return partition;
+    }
+
+    public boolean isReduceByInterval() {
+        return ( ! omitIntervals );
+    }
+
+    public CoveragePartitioner reduceInit() {
+        CoveragePartitioner aggro = new CoveragePartitioner(partitionTypes,start,stop,nBins);
+        for (DoCOutputType.Partition t : partitionTypes ) {
+            aggro.addIdentifiers(t,getSamplesFromToolKit(t));
+        }
+        aggro.initialize(includeDeletions,omitLocusTable);
+        checkOrder(aggro);
+        return aggro;
+    }
+
+    public Map<DoCOutputType.Partition,Map<String,int[]>> map(RefMetaDataTracker tracker, ReferenceContext ref, AlignmentContext context) {
+        if (includeRefNBases || BaseUtils.isRegularBase(ref.getBase())) {
+            if ( ! omitDepthOutput ) {
+                getCorrectStream(null, DoCOutputType.Aggregation.locus, DoCOutputType.FileType.summary).printf("%s",ref.getLocus()); // yes: print locus in map, and the rest of the info in reduce (for eventual cumulatives)
+                //System.out.printf("\t[log]\t%s",ref.getLocus());
+            }
+
+            return CoverageUtils.getBaseCountsByPartition(context,minMappingQuality,maxMappingQuality,minBaseQuality,maxBaseQuality,countType,partitionTypes);
+        } else {
+            return null;
+        }
+    }
+
+    public CoveragePartitioner reduce(Map<DoCOutputType.Partition,Map<String,int[]>> thisMap, CoveragePartitioner prevReduce) {
+        if ( thisMap != null ) { // skip sites we didn't want to include in the calculation (ref Ns)
+            if ( ! omitDepthOutput ) {
+                //checkOrder(prevReduce); // tests prevReduce.getIdentifiersByType().get(t) against the initialized header order
+                printDepths(getCorrectStream(null, DoCOutputType.Aggregation.locus, DoCOutputType.FileType.summary),thisMap,prevReduce.getIdentifiersByType());
+                // this is an additional iteration through thisMap, plus dealing with IO, so should be much slower without
+                // turning on omit
+            }
+
+            prevReduce.update(thisMap); // note that in "useBoth" cases, this method alters the thisMap object
+        }
+
+        return prevReduce;
+    }
+
+    public CoveragePartitioner treeReduce(CoveragePartitioner left, CoveragePartitioner right) {
+        left.merge(right);
+        return left;
+    }
+
+    ////////////////////////////////////////////////////////////////////////////////////
+    // INTERVAL ON TRAVERSAL DONE
+    ////////////////////////////////////////////////////////////////////////////////////
+
+    public void onTraversalDone( List<Pair<GenomeLoc, CoveragePartitioner>> statsByInterval ) {
+        if ( refSeqGeneList != null && partitionTypes.contains(DoCOutputType.Partition.sample) ) {
+            printGeneStats(statsByInterval);
+        }
+
+        if ( statsByInterval.size() > 0 ) {
+            for(DoCOutputType.Partition partition: partitionTypes) {
+                if ( checkType(statsByInterval.get(0).getSecond().getCoverageByAggregationType(partition) ,partition) ) {
+                    printIntervalStats(statsByInterval,
+                            getCorrectStream(partition, DoCOutputType.Aggregation.interval, DoCOutputType.FileType.summary),
+                            getCorrectStream(partition, DoCOutputType.Aggregation.interval, DoCOutputType.FileType.statistics),
+                            partition);
+                } else {
+                    throw new ReviewedGATKException("Partition type "+partition.toString()+" had no entries. Please check that your .bam header has all appropriate partition types.");
+                }
+            }
+        } else {
+            throw new UserException.CommandLineException("Cannot reduce by interval without a list of intervals. Please provide an interval list using the -L argument.");
+        }
+
+        onTraversalDone(mergeAll(statsByInterval));
+
+    }
+
+    public CoveragePartitioner mergeAll(List<Pair<GenomeLoc, CoveragePartitioner>> stats) {
+        CoveragePartitioner first = stats.remove(0).second;
+        for ( Pair<GenomeLoc, CoveragePartitioner> iStat : stats ) {
+            treeReduce(first,iStat.second);
+        }
+
+        return first;
+    }
+
+    private DepthOfCoverageStats printIntervalStats(List<Pair<GenomeLoc, CoveragePartitioner>> statsByInterval, PrintStream summaryOut, PrintStream statsOut, DoCOutputType.Partition type) {
+        Pair<GenomeLoc, CoveragePartitioner> firstPair = statsByInterval.get(0);
+        CoveragePartitioner firstAggregator = firstPair.second;
+        DepthOfCoverageStats firstStats = firstAggregator.getCoverageByAggregationType(type);
+
+        StringBuilder summaryHeader = new StringBuilder();
+        summaryHeader.append("Target");
+        summaryHeader.append(separator);
+        summaryHeader.append("total_coverage");
+        summaryHeader.append(separator);
+        summaryHeader.append("average_coverage");
+
+        for ( String s : firstStats.getAllSamples() ) {
+            summaryHeader.append(separator);
+            summaryHeader.append(s);
+            summaryHeader.append("_total_cvg");
+            summaryHeader.append(separator);
+            summaryHeader.append(s);
+            summaryHeader.append("_mean_cvg");
+            summaryHeader.append(separator);
+            summaryHeader.append(s);
+            summaryHeader.append("_granular_Q1");
+            summaryHeader.append(separator);
+            summaryHeader.append(s);
+            summaryHeader.append("_granular_median");
+            summaryHeader.append(separator);
+            summaryHeader.append(s);
+            summaryHeader.append("_granular_Q3");
+            for ( int thresh : coverageThresholds ) {
+                summaryHeader.append(separator);
+                summaryHeader.append(s);
+                summaryHeader.append("_%_above_");
+                summaryHeader.append(thresh);
+            }
+        }
+
+        summaryOut.printf("%s%n",summaryHeader);
+
+        int[][] nTargetsByAvgCvgBySample = new int[firstStats.getHistograms().size()][firstStats.getEndpoints().length+1];
+
+        for ( Pair<GenomeLoc, CoveragePartitioner> targetAggregator : statsByInterval ) {
+
+            Pair<GenomeLoc,DepthOfCoverageStats> targetStats = new Pair<GenomeLoc,DepthOfCoverageStats>(
+                    targetAggregator.first, targetAggregator.second.getCoverageByAggregationType(type));
+            printTargetSummary(summaryOut,targetStats);
+            updateTargetTable(nTargetsByAvgCvgBySample,targetStats.second);
+        }
+
+        printIntervalTable(statsOut,nTargetsByAvgCvgBySample,firstStats.getEndpoints());
+
+        return firstStats;
+    }
+
+    private void printGeneStats(List<Pair<GenomeLoc, CoveragePartitioner>> statsByTarget) {
+        logger.debug("statsByTarget size is "+Integer.toString(statsByTarget.size()));
+        logger.debug("Initializing refseq...");
+        LocationAwareSeekableRODIterator refseqIterator = initializeRefSeq();
+        logger.debug("Refseq init done.");
+        List<Pair<String,DepthOfCoverageStats>> statsByGene = new ArrayList<Pair<String,DepthOfCoverageStats>>();// maintains order
+        Map<String,DepthOfCoverageStats> geneNamesToStats = new HashMap<String,DepthOfCoverageStats>(); // allows indirect updating of objects in list
+
+        for ( Pair<GenomeLoc, CoveragePartitioner> targetStats : statsByTarget ) {
+            String gene = getGeneName(targetStats.first,refseqIterator);
+            if ( geneNamesToStats.keySet().contains(gene) ) {
+                logger.debug("Merging "+geneNamesToStats.get(gene).toString()+" and "+targetStats.second.getCoverageByAggregationType(DoCOutputType.Partition.sample).toString());
+                geneNamesToStats.get(gene).merge(targetStats.second.getCoverageByAggregationType(DoCOutputType.Partition.sample));
+            } else {
+                DepthOfCoverageStats merger = new DepthOfCoverageStats(targetStats.second.getCoverageByAggregationType(DoCOutputType.Partition.sample));
+                geneNamesToStats.put(gene,merger);
+                statsByGene.add(new Pair<String,DepthOfCoverageStats>(gene,merger));
+            }
+        }
+
+        PrintStream geneSummaryOut = getCorrectStream(DoCOutputType.Partition.sample, DoCOutputType.Aggregation.gene, DoCOutputType.FileType.summary);
+        StringBuilder summaryHeader = new StringBuilder();
+        summaryHeader.append("Gene");
+        summaryHeader.append(separator);
+        summaryHeader.append("total_coverage");
+        summaryHeader.append(separator);
+        summaryHeader.append("average_coverage");
+
+        for ( String s : statsByTarget.get(0).second.getCoverageByAggregationType(DoCOutputType.Partition.sample).getAllSamples() ) {
+            summaryHeader.append(separator);
+            summaryHeader.append(s);
+            summaryHeader.append("_total_cvg");
+            summaryHeader.append(separator);
+            summaryHeader.append(s);
+            summaryHeader.append("_mean_cvg");
+            summaryHeader.append(separator);
+            summaryHeader.append(s);
+            summaryHeader.append("_granular_Q1");
+            summaryHeader.append(separator);
+            summaryHeader.append(s);
+            summaryHeader.append("_granular_median");
+            summaryHeader.append(separator);
+            summaryHeader.append(s);
+            summaryHeader.append("_granular_Q3");
+            for ( int thresh : coverageThresholds ) {
+                summaryHeader.append(separator);
+                summaryHeader.append(s);
+                summaryHeader.append("_%_above_");
+                summaryHeader.append(thresh);
+            }
+        }
+
+        geneSummaryOut.printf("%s%n",summaryHeader);
+
+        for ( Pair<String,DepthOfCoverageStats> geneStats : statsByGene ) {
+            printTargetSummary(geneSummaryOut,geneStats);
+        }
+    }
+
+    //blatantly stolen from Andrew Kernytsky
+    private String getGeneName(GenomeLoc target, LocationAwareSeekableRODIterator refseqIterator) {
+        logger.debug("Examining "+target.toString());
+        if (refseqIterator == null) { return "UNKNOWN"; }
+
+        RODRecordList annotationList = refseqIterator.seekForward(target);
+        logger.debug("Annotation list is " + (annotationList == null ? "null" : annotationList.getName()));
+        if (annotationList == null) { return "UNKNOWN"; }
+
+        for(GATKFeature rec : annotationList) {
+            if ( ((RefSeqFeature)rec.getUnderlyingObject()).overlapsExonP(target) ) {
+                logger.debug("We do overlap "+ rec.getUnderlyingObject().toString());
+                return ((RefSeqFeature)rec.getUnderlyingObject()).getGeneName();
+            }
+            logger.debug("No overlap");
+        }
+
+        return "UNKNOWN";
+
+    }
+
+    private LocationAwareSeekableRODIterator initializeRefSeq() {
+        RMDTrackBuilder builder = new RMDTrackBuilder(getToolkit().getReferenceDataSource().getReference().getSequenceDictionary(),
+                                                      getToolkit().getGenomeLocParser(),
+                                                      getToolkit().getArguments().unsafe,
+                                                      getToolkit().getArguments().disableAutoIndexCreationAndLockingWhenReadingRods,
+                                                      null);
+        RMDTrack refseq = builder.createInstanceOfTrack(RefSeqCodec.class,refSeqGeneList);
+        return new SeekableRODIterator(refseq.getHeader(),refseq.getSequenceDictionary(),getToolkit().getReferenceDataSource().getReference().getSequenceDictionary(),
+                getToolkit().getGenomeLocParser(),refseq.getIterator());
+    }
+
+    private void printTargetSummary(PrintStream output, Pair<?,DepthOfCoverageStats> intervalStats) {
+        DepthOfCoverageStats stats = intervalStats.second;
+        int[] bins = stats.getEndpoints();
+
+        StringBuilder targetSummary = new StringBuilder();
+        targetSummary.append(intervalStats.first.toString());
+        targetSummary.append(separator);
+        targetSummary.append(stats.getTotalCoverage());
+        targetSummary.append(separator);
+        targetSummary.append(String.format("%.2f",stats.getTotalMeanCoverage()));
+
+        for ( String s : stats.getAllSamples() ) {
+            targetSummary.append(separator);
+            targetSummary.append(stats.getTotals().get(s));
+            targetSummary.append(separator);
+            targetSummary.append(String.format("%.2f", stats.getMeans().get(s)));
+            targetSummary.append(separator);
+            int median = getQuantile(stats.getHistograms().get(s),0.5);
+            int q1 = getQuantile(stats.getHistograms().get(s),0.25);
+            int q3 = getQuantile(stats.getHistograms().get(s),0.75);
+            targetSummary.append(formatBin(bins,q1));
+            targetSummary.append(separator);
+            targetSummary.append(formatBin(bins,median));
+            targetSummary.append(separator);
+            targetSummary.append(formatBin(bins,q3));
+            for ( int thresh : coverageThresholds ) {
+                targetSummary.append(String.format("%s%.1f",separator,getPctBasesAbove(stats.getHistograms().get(s),stats.value2bin(thresh))));
+            }
+
+        }
+
+        output.printf("%s%n", targetSummary);
+    }
+
+    private String formatBin(int[] bins, int quartile) {
+        if ( quartile >= bins.length ) {
+            return String.format(">%d",bins[bins.length-1]);
+        } else if ( quartile < 0 ) {
+            return String.format("<%d",bins[0]);
+        } else {
+            return String.format("%d",bins[quartile]);
+        }
+    }
+
+    private void printIntervalTable(PrintStream output, int[][] intervalTable, int[] cutoffs) {
+        String colHeader = outputFormat.equals("rtable") ? "" : "Number_of_sources";
+        output.printf(colHeader + separator+"depth>=%d",0);
+        for ( int col = 0; col < intervalTable[0].length-1; col ++ ) {
+            output.printf(separator+"depth>=%d",cutoffs[col]);
+        }
+
+        output.printf(String.format("%n"));
+        for ( int row = 0; row < intervalTable.length; row ++ ) {
+            output.printf("At_least_%d_samples",row+1);
+            for ( int col = 0; col < intervalTable[0].length; col++ ) {
+                output.printf(separator+"%d",intervalTable[row][col]);
+            }
+            output.printf(String.format("%n"));
+        }
+    }
+
+    /*
+     * @updateTargetTable
+     * The idea is to have counts for how many *targets* have at least K samples with
+     * median coverage of at least X.
+     * To that end:
+     * Iterate over the samples the DOCS object, determine how many there are with
+     * median coverage > leftEnds[0]; how many with median coverage > leftEnds[1]
+     * and so on. Then this target has at least N, N-1, N-2, ... 1, 0 samples covered
+     * to leftEnds[0] and at least M,M-1,M-2,...1,0 samples covered to leftEnds[1]
+     * and so on.
+     */
+    private void updateTargetTable(int[][] table, DepthOfCoverageStats stats) {
+        int[] cutoffs = stats.getEndpoints();
+        int[] countsOfMediansAboveCutoffs = new int[cutoffs.length+1]; // 0 bin to catch everything
+        for ( int i = 0; i < countsOfMediansAboveCutoffs.length; i ++) {
+            countsOfMediansAboveCutoffs[i]=0;
+        }
+
+        for ( String s : stats.getAllSamples() ) {
+            int medianBin = getQuantile(stats.getHistograms().get(s),0.5);
+            for ( int i = 0; i <= medianBin; i ++) {
+                countsOfMediansAboveCutoffs[i]++;
+            }
+        }
+
+        for ( int medianBin = 0; medianBin < countsOfMediansAboveCutoffs.length; medianBin++) {
+            for ( ; countsOfMediansAboveCutoffs[medianBin] > 0; countsOfMediansAboveCutoffs[medianBin]-- ) {
+                table[countsOfMediansAboveCutoffs[medianBin]-1][medianBin]++;
+                // the -1 is due to counts being 1-based and offsets being 0-based
+            }
+        }
+    }
+
+    ////////////////////////////////////////////////////////////////////////////////////
+    // FINAL ON TRAVERSAL DONE
+    ////////////////////////////////////////////////////////////////////////////////////
+
+    public void onTraversalDone(CoveragePartitioner coverageProfiles) {
+        ///////////////////
+        // OPTIONAL OUTPUTS
+        //////////////////
+
+        if ( ! omitSampleSummary ) {
+            logger.info("Printing summary info");
+            for (DoCOutputType.Partition type : partitionTypes ) {
+                outputSummaryFiles(coverageProfiles,type);
+            }
+        }
+
+        if ( ! omitLocusTable ) {
+            logger.info("Printing locus summary");
+            for (DoCOutputType.Partition type : partitionTypes ) {
+                outputLocusFiles(coverageProfiles,type);
+            }
+        }
+    }
+
+    private void outputLocusFiles(CoveragePartitioner coverageProfiles, DoCOutputType.Partition type ) {
+        printPerLocus(getCorrectStream(type, DoCOutputType.Aggregation.cumulative, DoCOutputType.FileType.coverage_counts),
+                getCorrectStream(type, DoCOutputType.Aggregation.cumulative, DoCOutputType.FileType.coverage_proportions),
+                coverageProfiles.getCoverageByAggregationType(type),type);
+    }
+
+    private void outputSummaryFiles(CoveragePartitioner coverageProfiles, DoCOutputType.Partition type ) {
+        printPerSample(getCorrectStream(type, DoCOutputType.Aggregation.cumulative, DoCOutputType.FileType.statistics),coverageProfiles.getCoverageByAggregationType(type));
+        printSummary(getCorrectStream(type, DoCOutputType.Aggregation.cumulative, DoCOutputType.FileType.summary),coverageProfiles.getCoverageByAggregationType(type));
+    }
+
+    ////////////////////////////////////////////////////////////////////////////////////
+    // HELPER OUTPUT METHODS
+    ////////////////////////////////////////////////////////////////////////////////////
+
+    private void printPerSample(PrintStream output,DepthOfCoverageStats stats) {
+        int[] leftEnds = stats.getEndpoints();
+
+        StringBuilder hBuilder = new StringBuilder();
+        if ( ! outputFormat.equals("rTable")) {
+            hBuilder.append("Source_of_reads");
+        }
+        hBuilder.append(separator);
+        hBuilder.append(String.format("from_0_to_%d)%s",leftEnds[0],separator));
+        for ( int i = 1; i < leftEnds.length; i++ )
+            hBuilder.append(String.format("from_%d_to_%d)%s",leftEnds[i-1],leftEnds[i],separator));
+        hBuilder.append(String.format("from_%d_to_inf%n",leftEnds[leftEnds.length-1]));
+        output.print(hBuilder.toString());
+        Map<String,long[]> histograms = stats.getHistograms();
+
+        for ( Map.Entry<String, long[]> p : histograms.entrySet() ) {
+            StringBuilder sBuilder = new StringBuilder();
+            sBuilder.append(String.format("sample_%s",p.getKey()));
+            for ( long count : p.getValue() ) {
+                sBuilder.append(String.format("%s%d",separator,count));
+            }
+            sBuilder.append(String.format("%n"));
+            output.print(sBuilder.toString());
+        }
+    }
+
+    private void printPerLocus(PrintStream output, PrintStream coverageOut, DepthOfCoverageStats stats, DoCOutputType.Partition partitionType) {
+        int[] endpoints = stats.getEndpoints();
+        int samples = stats.getHistograms().size();
+
+        long[][] baseCoverageCumDist = stats.getLocusCounts();
+
+        // rows - # of samples
+        // columns - depth of coverage
+
+        boolean printSampleColumnHeader = outputFormat.equals("csv") || outputFormat.equals("table");
+
+        StringBuilder header = new StringBuilder();
+        if ( printSampleColumnHeader ) {
+            // mhanna 22 Aug 2010 - Deliberately force this header replacement to make sure integration tests pass.
+            // TODO: Update integration tests and get rid of this.
+            header.append(partitionType == DoCOutputType.Partition.readgroup ? "read_group" : partitionType.toString());
+        }
+        header.append(String.format("%sgte_0",separator));
+        for ( int d : endpoints ) {
+            header.append(String.format("%sgte_%d",separator,d));
+        }
+        header.append(String.format("%n"));
+
+        output.print(header);
+        coverageOut.print(header);
+
+        for ( int row = 0; row < samples; row ++ ) {
+            output.printf("%s_%d","NSamples",row+1);
+            for ( int depthBin = 0; depthBin < baseCoverageCumDist[0].length; depthBin ++ ) {
+                output.printf("%s%d",separator,baseCoverageCumDist[row][depthBin]);
+            }
+            output.printf("%n");
+        }
+
+        for ( String sample : stats.getAllSamples() ) {
+            coverageOut.printf("%s",sample);
+            double[] coverageDistribution = stats.getCoverageProportions(sample);
+            for ( int bin = 0; bin < coverageDistribution.length; bin ++ ) {
+                coverageOut.printf("%s%.2f",separator,coverageDistribution[bin]);
+            }
+            coverageOut.printf("%n");
+        }
+    }
+
+    private PrintStream getCorrectStream(DoCOutputType.Partition partition, DoCOutputType.Aggregation aggregation, DoCOutputType.FileType fileType) {
+        DoCOutputType outputType = new DoCOutputType(partition,aggregation,fileType);
+        if(!out.containsKey(outputType))
+            throw new UserException.CommandLineException(String.format("Unable to find appropriate stream for partition = %s, aggregation = %s, file type = %s",partition,aggregation,fileType));
+        return out.get(outputType);
+    }
+
+    private void printSummary(PrintStream output, DepthOfCoverageStats stats) {
+        if ( ! outputFormat.equals("csv") ) {
+            output.printf("%s\t%s\t%s\t%s\t%s\t%s","sample_id","total","mean","granular_third_quartile","granular_median","granular_first_quartile");
+        } else {
+            output.printf("%s,%s,%s,%s,%s,%s","sample_id","total","mean","granular_third_quartile","granular_median","granular_first_quartile");
+        }
+
+        for ( int thresh : coverageThresholds ) {
+            output.printf("%s%s%d",separator,"%_bases_above_",thresh);
+        }
+
+        output.printf("%n");
+
+        Map<String,long[]> histograms = stats.getHistograms();
+        Map<String,Double> means = stats.getMeans();
+        Map<String,Long> totals = stats.getTotals();
+        int[] leftEnds = stats.getEndpoints();
+
+        for ( Map.Entry<String, long[]> p : histograms.entrySet() ) {
+            String s = p.getKey();
+            long[] histogram = p.getValue();
+            int median = getQuantile(histogram,0.5);
+            int q1 = getQuantile(histogram,0.25);
+            int q3 = getQuantile(histogram,0.75);
+            // if any of these are larger than the higest bin, put the median as in the largest bin
+            median =  median == histogram.length-1 ? histogram.length-2 : median;
+            q1 = q1 == histogram.length-1 ? histogram.length-2 : q1;
+            q3 = q3 == histogram.length-1 ? histogram.length-2 : q3;
+            if ( ! outputFormat.equals("csv") ) {
+                output.printf("%s\t%d\t%.2f\t%d\t%d\t%d",s,totals.get(s),means.get(s),leftEnds[q3],leftEnds[median],leftEnds[q1]);
+            } else {
+                output.printf("%s,%d,%.2f,%d,%d,%d",s,totals.get(s),means.get(s),leftEnds[q3],leftEnds[median],leftEnds[q1]);
+            }
+
+            for ( int thresh : coverageThresholds ) {
+                output.printf("%s%.1f",separator,getPctBasesAbove(histogram,stats.value2bin(thresh)));
+            }
+
+            output.printf("%n");
+        }
+
+        if ( ! outputFormat.equals("csv") ) {
+            output.printf("%s\t%d\t%.2f\t%s\t%s\t%s%n","Total",stats.getTotalCoverage(),stats.getTotalMeanCoverage(),"N/A","N/A","N/A");
+        } else {
+            output.printf("%s,%d,%.2f,%s,%s,%s%n","Total",stats.getTotalCoverage(),stats.getTotalMeanCoverage(),"N/A","N/A","N/A");
+        }
+    }
+
+    private int getQuantile(long[] histogram, double prop) {
+        int total = 0;
+
+        for ( int i = 0; i < histogram.length; i ++ ) {
+            total += histogram[i];
+        }
+
+        int counts = 0;
+        int bin = -1;
+        while ( counts < prop*total ) {
+            counts += histogram[bin+1];
+            bin++;
+        }
+
+        return bin == -1 ? 0 : bin;
+    }
+
+    private double getPctBasesAbove(long[] histogram, int bin) {
+        long below = 0l;
+        long above = 0l;
+        for ( int index = 0; index < histogram.length; index++) {
+            if ( index < bin ) {
+                below+=histogram[index];
+            } else {
+                above+=histogram[index];
+            }
+        }
+
+        return 100*( (double) above )/( above + below );
+    }
+
+    private void printDepths(PrintStream stream, Map<DoCOutputType.Partition,Map<String,int[]>> countsBySampleByType, Map<DoCOutputType.Partition,List<String>> identifiersByType) {
+        // get the depths per sample and build up the output string while tabulating total and average coverage
+        StringBuilder perSampleOutput = new StringBuilder();
+        int tDepth = 0;
+        boolean depthCounted = false;
+        for (DoCOutputType.Partition type : partitionTypes ) {
+            Map<String,int[]> countsByID = countsBySampleByType.get(type);
+            for ( String s : identifiersByType.get(type) ) {
+                perSampleOutput.append(separator);
+                long dp = (countsByID != null && countsByID.keySet().contains(s)) ? sumArray(countsByID.get(s)) : 0 ;
+                perSampleOutput.append(dp);
+                if ( printBaseCounts ) {
+                    perSampleOutput.append(separator);
+                    perSampleOutput.append(baseCounts(countsByID != null ? countsByID.get(s) : null ));
+                }
+                if ( ! depthCounted ) {
+                    tDepth += dp;
+                }
+            }
+            depthCounted = true; // only sum the total depth once
+        }
+
+        // remember -- genome locus was printed in map()
+        stream.printf("%s%d",separator,tDepth);
+        for (DoCOutputType.Partition type : partitionTypes ) {
+            stream.printf("%s%.2f",separator, ( (double) tDepth / identifiersByType.get(type).size() ) );
+        }
+        stream.printf("%s%n",perSampleOutput);
+    }
+
+    private long sumArray(int[] array) {
+        long i = 0;
+        for ( int j : array ) {
+            i += j;
+        }
+        return i;
+    }
+
+    private String baseCounts(int[] counts) {
+        if ( counts == null ) {
+            counts = new int[6];
+        }
+        StringBuilder s = new StringBuilder();
+        int nbases = 0;
+        for ( byte b : BaseUtils.EXTENDED_BASES ) {
+            nbases++;
+            if ( includeDeletions || b != BaseUtils.Base.D.base ) {
+                s.append((char)b);
+                s.append(":");
+                s.append(counts[BaseUtils.extendedBaseToBaseIndex(b)]);
+                if ( nbases < 6 ) {
+                    s.append(" ");
+                }
+            }
+        }
+
+        return s.toString();
+    }
+
+    private void checkOrder(CoveragePartitioner ag) {
+        // make sure the ordering stored at initialize() is propagated along reduce
+        for (DoCOutputType.Partition t : partitionTypes ) {
+            List<String> order = orderCheck.get(t);
+            List<String> namesInAg = ag.getIdentifiersByType().get(t);
+
+            // todo -- chris check me
+            Set<String> namesInDOCS = ag.getCoverageByAggregationType(t).getAllSamples();
+            int index = 0;
+            for ( String s : namesInAg ) {
+                if ( ! s.equalsIgnoreCase(order.get(index)) ) {
+                    throw new ReviewedGATKException("IDs are out of order for type "+t+"! Aggregator has different ordering");
+                }
+                index++;
+            }
+        }
+    }
+
+    public boolean checkType(DepthOfCoverageStats stats, DoCOutputType.Partition type ) {
+        if ( stats.getHistograms().size() < 1 ) {
+            logger.warn("The histogram per partition type "+type.toString()+" was empty\n"+
+                    "Do your read groups have this type? (Check your .bam header).");
+            return false;
+        } else {
+            return true;
+        }
+    }
+
+}
+
+class DoCOutputMultiplexer implements Multiplexer<DoCOutputType> {
+    private final Set<DoCOutputType.Partition> partitions;
+    private final File refSeqGeneList;
+    private final boolean omitDepthOutput;
+    private final boolean omitIntervals;
+    private final boolean omitSampleSummary;
+    private final boolean omitLocusTable;
+
+    /**
+     * Create a new multiplexer type using the values of all variable fields.
+     * @param partitions
+     * @param refSeqGeneList
+     * @param omitDepthOutput
+     * @param omitIntervals
+     * @param omitSampleSummary
+     * @param omitLocusTable
+     */
+    public DoCOutputMultiplexer(final Set<DoCOutputType.Partition> partitions,
+                                final File refSeqGeneList,
+                                final boolean omitDepthOutput,
+                                final boolean omitIntervals,
+                                final boolean omitSampleSummary,
+                                final boolean omitLocusTable) {
+        this.partitions = partitions;
+        this.refSeqGeneList = refSeqGeneList;
+        this.omitDepthOutput = omitDepthOutput;
+        this.omitIntervals = omitIntervals;
+        this.omitSampleSummary = omitSampleSummary;
+        this.omitLocusTable = omitLocusTable;
+    }
+
+    public Collection<DoCOutputType> multiplex() {
+        List<DoCOutputType> outputs = new ArrayList<DoCOutputType>();
+        if(!omitDepthOutput) outputs.add(new DoCOutputType(null, DoCOutputType.Aggregation.locus, DoCOutputType.FileType.summary));
+
+        if(!omitIntervals) {
+            for(DoCOutputType.Partition partition: partitions) {
+                outputs.add(new DoCOutputType(partition, DoCOutputType.Aggregation.interval, DoCOutputType.FileType.summary));
+                outputs.add(new DoCOutputType(partition, DoCOutputType.Aggregation.interval, DoCOutputType.FileType.statistics));
+            }
+        }
+
+        if(refSeqGeneList != null && partitions.contains(DoCOutputType.Partition.sample)) {
+            DoCOutputType geneSummaryOut = new DoCOutputType(DoCOutputType.Partition.sample, DoCOutputType.Aggregation.gene, DoCOutputType.FileType.summary);
+            outputs.add(geneSummaryOut);
+        }
+
+        if(!omitSampleSummary) {
+            for(DoCOutputType.Partition partition: partitions) {
+                outputs.add(new DoCOutputType(partition, DoCOutputType.Aggregation.cumulative, DoCOutputType.FileType.summary));
+                outputs.add(new DoCOutputType(partition, DoCOutputType.Aggregation.cumulative, DoCOutputType.FileType.statistics));
+            }
+        }
+
+        if(!omitLocusTable) {
+            for(DoCOutputType.Partition partition: partitions) {
+                outputs.add(new DoCOutputType(partition, DoCOutputType.Aggregation.cumulative, DoCOutputType.FileType.coverage_counts));
+                outputs.add(new DoCOutputType(partition, DoCOutputType.Aggregation.cumulative, DoCOutputType.FileType.coverage_proportions));
+            }
+        }
+
+        return outputs;
+    }
+
+    public String transformArgument(final DoCOutputType outputType, final String argument) {
+        return outputType.getFileName(argument);
+    }
+
+}
+
+class CoveragePartitioner {
+    private Collection<DoCOutputType.Partition> types;
+    private Map<DoCOutputType.Partition,DepthOfCoverageStats> coverageProfiles;
+    private Map<DoCOutputType.Partition,List<String>> identifiersByType;
+    private Set<String> allIdentifiers;
+    public CoveragePartitioner(Collection<DoCOutputType.Partition> typesToUse, int start, int stop, int nBins) {
+        coverageProfiles = new TreeMap<DoCOutputType.Partition,DepthOfCoverageStats>();
+        identifiersByType = new HashMap<DoCOutputType.Partition,List<String>>();
+        types = typesToUse;
+        for ( DoCOutputType.Partition type : types ) {
+            coverageProfiles.put(type,new DepthOfCoverageStats(DepthOfCoverageStats.calculateBinEndpoints(start,stop,nBins)));
+            identifiersByType.put(type,new ArrayList<String>());
+        }
+        allIdentifiers = new HashSet<String>();
+    }
+
+    public void merge(CoveragePartitioner otherAggregator) {
+        for ( DoCOutputType.Partition type : types ) {
+            this.coverageProfiles.get(type).merge(otherAggregator.coverageProfiles.get(type));
+        }
+    }
+
+    public DepthOfCoverageStats getCoverageByAggregationType(DoCOutputType.Partition t) {
+        return coverageProfiles.get(t);
+    }
+
+    public void addIdentifiers(DoCOutputType.Partition t, Set<String> ids) {
+        for ( String s : ids ) {
+            coverageProfiles.get(t).addSample(s);
+            identifiersByType.get(t).add(s);
+            allIdentifiers.add(s);
+        }
+        Collections.sort(identifiersByType.get(t));
+    }
+
+    public void initialize(boolean useDels, boolean omitLocusTable) {
+        for ( DoCOutputType.Partition t : types ) {
+            if ( useDels ) {
+                coverageProfiles.get(t).initializeDeletions();
+            }
+            if ( ! omitLocusTable ) {
+                coverageProfiles.get(t).initializeLocusCounts();
+            }
+        }
+    }
+
+    public void update(Map<DoCOutputType.Partition,Map<String,int[]>> countsByIdentifierByType) {
+        for ( DoCOutputType.Partition t : types ) {
+            coverageProfiles.get(t).update(countsByIdentifierByType.get(t));
+        }
+    }
+
+    public Set<String> getAllIdentifiers() {
+        return allIdentifiers;
+    }
+
+    public Map<DoCOutputType.Partition,List<String>> getIdentifiersByType() {
+        return identifiersByType;
+    }
+}
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/tools/walkers/coverage/DepthOfCoverageStats.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/tools/walkers/coverage/DepthOfCoverageStats.java
new file mode 100644
index 0000000..c8a4356
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/tools/walkers/coverage/DepthOfCoverageStats.java
@@ -0,0 +1,352 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.tools.walkers.coverage;
+
+import org.broadinstitute.gatk.utils.BaseUtils;
+import org.broadinstitute.gatk.utils.exceptions.UserException;
+
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Set;
+import java.util.TreeMap;
+
+/**
+ * IF THERE IS NO JAVADOC RIGHT HERE, YELL AT chartl
+ *
+ * @Author chartl
+ * @Date Feb 26, 2010
+ */
+public class DepthOfCoverageStats {
+    ////////////////////////////////////////////////////////////////////////////////////
+    // STATIC DATA
+    ////////////////////////////////////////////////////////////////////////////////////
+
+    /* none so far */
+
+    ////////////////////////////////////////////////////////////////////////////////////
+    // STANDARD DATA
+    ////////////////////////////////////////////////////////////////////////////////////
+
+    private Map<String,long[]> granularHistogramBySample; // holds the counts per each bin
+    private Map<String,Long> totalCoverages; // holds total coverage per sample
+    private int[] binLeftEndpoints; // describes the left endpoint for each bin
+    private long[][] locusCoverageCounts; // holds counts of number of bases with >=X samples at >=Y coverage
+    private boolean tabulateLocusCounts = false;
+    private long nLoci; // number of loci seen
+    private long totalDepthOfCoverage;
+    private boolean includeDeletions = false;
+
+    ////////////////////////////////////////////////////////////////////////////////////
+    // TEMPORARY DATA ( not worth re-instantiating )
+    ////////////////////////////////////////////////////////////////////////////////////
+
+    private int[] locusHistogram; // holds a histogram for each locus; reset after each update() call
+    private int totalLocusDepth; // holds the total depth of coverage for each locus; reset after each update() call
+
+    ////////////////////////////////////////////////////////////////////////////////////
+    // STATIC METHODS
+    ////////////////////////////////////////////////////////////////////////////////////
+
+    public static int[] calculateBinEndpoints(int lower, int upper, int bins) {
+        if ( bins > upper - lower || lower < 1 ) {
+            throw new UserException.BadInput("the start must be at least 1 and the number of bins may not exceed stop - start");
+        }
+
+        int[] binLeftEndpoints = new int[bins+1];
+        binLeftEndpoints[0] = lower;
+
+        int length = upper - lower;
+        double scale = Math.log10((double) length)/bins;
+
+        for ( int b = 1; b < bins ; b++ ) {
+            int leftEnd = lower + (int) Math.floor(Math.pow(10.0,(b-1.0)*scale));
+            // todo -- simplify to length^(scale/bins); make non-constant to put bin ends in more "useful"
+            // todo -- positions on the number line
+            while ( leftEnd <= binLeftEndpoints[b-1] ) {
+                leftEnd++;
+            }
+
+            binLeftEndpoints[b] = leftEnd;
+        }
+
+        binLeftEndpoints[binLeftEndpoints.length-1] = upper;
+
+        return binLeftEndpoints;
+    }
+
+    ////////////////////////////////////////////////////////////////////////////////////
+    // INITIALIZATION METHODS
+    ////////////////////////////////////////////////////////////////////////////////////
+
+    public DepthOfCoverageStats(int[] leftEndpoints) {
+        this.binLeftEndpoints = leftEndpoints;
+        granularHistogramBySample = new HashMap<String,long[]>();
+        totalCoverages = new HashMap<String,Long>();
+        nLoci = 0;
+        totalLocusDepth = 0;
+        totalDepthOfCoverage = 0;
+    }
+
+    public DepthOfCoverageStats(DepthOfCoverageStats cloneMe) {
+        this.binLeftEndpoints = cloneMe.binLeftEndpoints;
+        granularHistogramBySample = new TreeMap<String,long[]>();
+        totalCoverages = new TreeMap<String,Long>();
+        for ( String s : cloneMe.getAllSamples() ) {
+            granularHistogramBySample.put(s,new long[cloneMe.getHistograms().get(s).length]);
+            for ( int i = 0; i < granularHistogramBySample.get(s).length; i++ ) {
+                granularHistogramBySample.get(s)[i] = cloneMe.getHistograms().get(s)[i];
+            }
+            totalCoverages.put(s,cloneMe.totalCoverages.get(s));
+        }
+
+        this.includeDeletions = cloneMe.includeDeletions;
+        if ( cloneMe.tabulateLocusCounts ) {
+            this.locusCoverageCounts = new long[cloneMe.locusCoverageCounts.length][cloneMe.locusCoverageCounts[0].length];
+        }
+        //this.granularHistogramBySample = cloneMe.granularHistogramBySample;
+        //this.totalCoverages = cloneMe.totalCoverages;
+        this.nLoci = cloneMe.nLoci;
+        this.totalDepthOfCoverage = cloneMe.totalDepthOfCoverage;
+        this.tabulateLocusCounts = cloneMe.tabulateLocusCounts;
+    }
+
+    public void addSample(String sample) {
+        if ( granularHistogramBySample.containsKey(sample) ) {
+            return;
+        }
+
+        long[] binCounts = new long[this.binLeftEndpoints.length+1];
+        for ( int b = 0; b < binCounts.length; b ++ ) {
+            binCounts[b] = 0;
+        }
+
+        granularHistogramBySample.put(sample,binCounts);
+        totalCoverages.put(sample,0l);
+    }
+
+    public void initializeLocusCounts() {
+        locusCoverageCounts = new long[granularHistogramBySample.size()][binLeftEndpoints.length+1];
+        locusHistogram = new int[binLeftEndpoints.length+1];
+        for ( int b = 0; b < binLeftEndpoints.length+1; b ++ ) {
+            for ( int a = 0; a < granularHistogramBySample.size(); a ++ ) {
+                locusCoverageCounts[a][b] = 0;
+            }
+            locusHistogram[b] = 0;
+        }
+
+        tabulateLocusCounts = true;
+    }
+
+    public void initializeDeletions() {
+        includeDeletions = true;
+    }
+
+    ////////////////////////////////////////////////////////////////////////////////////
+    // UPDATE METHODS
+    ////////////////////////////////////////////////////////////////////////////////////
+
+    public void updateDepths(Map<String,Integer> depthBySample) {
+        int b;
+        for ( String sample : granularHistogramBySample.keySet() ) {
+            if ( depthBySample.containsKey(sample) ) {
+                b = updateSample(sample,depthBySample.get(sample));
+                totalLocusDepth += depthBySample.get(sample);
+            } else {
+                b = updateSample(sample,0);
+            }
+
+            if ( tabulateLocusCounts ) {
+                for ( int i = 0; i <= b; i ++ ) {
+                    locusHistogram[i]++;
+                }
+            }
+        }
+        updateLocusCounts(locusHistogram);
+
+        nLoci++;
+        totalDepthOfCoverage += totalLocusDepth;
+        totalLocusDepth = 0;
+    }
+
+    public void update(Map<String,int[]> countsBySample) {
+        if ( countsBySample == null ) {
+            this.updateDepths(new HashMap<String,Integer>(1));
+            return;
+        }
+        // todo -- do we want to do anything special regarding base count or deletion statistics?
+        HashMap<String,Integer> depthBySample = new HashMap<String,Integer>();
+        // todo -- needs fixing with advent of new baseutils functionality using ENUMS and handling N,D
+        for ( String s : countsBySample.keySet() ) {
+            int total = 0;
+            int[] counts = countsBySample.get(s);
+            for ( byte base : BaseUtils.EXTENDED_BASES ) {
+                if ( includeDeletions || ! ( base == BaseUtils.Base.D.base) ) { // note basesAreEqual assigns TRUE to (N,D) as both have simple index -1
+                    total += counts[BaseUtils.extendedBaseToBaseIndex(base)];
+                }
+            }
+            depthBySample.put(s,total);
+        }
+        
+        this.updateDepths(depthBySample);
+    }
+
+    private int updateSample(String sample, int depth) {
+        totalCoverages.put(sample,totalCoverages.get(sample)+depth);
+
+        long[] granularBins = granularHistogramBySample.get(sample);
+        for ( int b = 0; b < binLeftEndpoints.length; b ++ ) {
+            if ( depth < binLeftEndpoints[b] ) {
+                granularBins[b]++;
+                return b;
+            }
+        }
+
+        granularBins[binLeftEndpoints.length]++; // greater than all left-endpoints
+        return binLeftEndpoints.length;
+    }
+
+    public void merge(DepthOfCoverageStats newStats) {
+        this.mergeSamples(newStats);
+        if ( this.tabulateLocusCounts && newStats.tabulateLocusCounts ) {
+            this.mergeLocusCounts(newStats.getLocusCounts());
+        }
+        nLoci += newStats.getTotalLoci();
+        totalDepthOfCoverage += newStats.getTotalCoverage();
+    }
+
+    private void mergeSamples(DepthOfCoverageStats otherStats) {
+        Map<String,long[]> otherHistogram = otherStats.getHistograms();
+        Map<String,Double> otherMeans = otherStats.getMeans();
+        for ( String s : this.getAllSamples() ) {
+            long[] internalCounts = granularHistogramBySample.get(s);
+            long[] externalCounts = otherHistogram.get(s);
+            for ( int b = 0; b < internalCounts.length; b++ ) {
+                internalCounts[b] += externalCounts[b];
+            }
+
+            this.totalCoverages.put(s, this.totalCoverages.get(s) + otherStats.totalCoverages.get(s));
+        }
+    }
+
+    private void mergeLocusCounts( long[][] otherCounts ) {
+        for ( int a = 0; a < locusCoverageCounts.length; a ++ ) {
+            for ( int b = 0; b < locusCoverageCounts[0].length; b ++ ) {
+                locusCoverageCounts[a][b] += otherCounts[a][b];
+            }
+        }
+    }
+
+    /*
+     * Update locus counts -- takes an array in which the number of samples
+     * with depth ABOVE [i] is held. So if the bin left endpoints were 2, 5, 10
+     * then we'd have an array that represented:
+     * [# samples with depth 0 - inf], [# samples with depth 2 - inf],
+     * [# samples with depth 5 - inf], [# samples with depth 10-inf];
+     *
+     * this is
+     * @argument cumulativeSamplesByDepthBin - see above
+     */
+    private void updateLocusCounts(int[] cumulativeSamplesByDepthBin) {
+        if ( tabulateLocusCounts ) {
+            for ( int bin = 0; bin < cumulativeSamplesByDepthBin.length; bin ++ ) {
+                int numSamples = cumulativeSamplesByDepthBin[bin];
+                for ( int i = 0; i < numSamples; i ++ ) {
+                    locusCoverageCounts[i][bin]++;
+                }
+
+                cumulativeSamplesByDepthBin[bin] = 0; // reset counts in advance of next update()
+            }
+        }
+    }
+
+    ////////////////////////////////////////////////////////////////////////////////////
+    // ACCESSOR METHODS
+    ////////////////////////////////////////////////////////////////////////////////////
+
+    public Map<String,long[]> getHistograms() {
+        return granularHistogramBySample;
+    }
+
+    public long[][] getLocusCounts() {
+        return locusCoverageCounts;
+    }
+
+    public int[] getEndpoints() {
+        return binLeftEndpoints;
+    }
+
+    public Map<String,Double> getMeans() {
+        HashMap<String,Double> means = new HashMap<String,Double>();
+        for ( String s : getAllSamples() ) {
+            means.put(s,( (double)totalCoverages.get(s))/( (double) nLoci ));
+        }
+
+        return means;
+    }
+
+    public Map<String,Long> getTotals() {
+        return totalCoverages;
+    }
+
+    public long getTotalLoci() {
+        return nLoci;
+    }
+
+    public Set<String> getAllSamples() {
+        return granularHistogramBySample.keySet();
+    }
+
+    public double getTotalMeanCoverage() {
+        return ( (double) totalDepthOfCoverage )/ ( (double) nLoci );
+    }
+
+    public long getTotalCoverage() {
+        return totalDepthOfCoverage;
+    }
+
+    public double[] getCoverageProportions(String sample) {
+        long[] hist = granularHistogramBySample.get(sample);
+        double[] distribution = new double[hist.length];
+        long count = 0;
+        for ( int i = hist.length-1; i >= 0; i -- ) {
+            count += hist[i];
+            distribution[i] = ( (double) count) / nLoci;
+        }
+
+        return distribution;
+    }
+
+    public int value2bin(int value) {
+        for ( int index = 0; index < binLeftEndpoints.length; index++ ) {
+            if ( binLeftEndpoints[index] > value ) {
+                return index;
+            }
+        }
+
+        return binLeftEndpoints.length-1;
+    }
+
+}
\ No newline at end of file
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/tools/walkers/coverage/DoCOutputType.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/tools/walkers/coverage/DoCOutputType.java
new file mode 100644
index 0000000..6e2266d
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/tools/walkers/coverage/DoCOutputType.java
@@ -0,0 +1,89 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.tools.walkers.coverage;
+
+/**
+ * Models a single output file in the DoC walker.
+ *
+ * @author mhanna
+ * @version 0.1
+ */
+public class DoCOutputType {
+    public enum Partition { readgroup, sample, library, platform, center, sample_by_platform, sample_by_center, sample_by_platform_by_center }
+    public enum Aggregation { locus, interval, gene, cumulative }
+    public enum FileType { summary, statistics, coverage_counts, coverage_proportions }
+
+    private final Partition partition;
+    private final Aggregation aggregation;
+    private final FileType fileType;
+
+    public DoCOutputType(final Partition partition,
+                         final Aggregation aggregation,
+                         final FileType fileType) {
+        this.partition = partition;
+        this.aggregation = aggregation;
+        this.fileType = fileType;
+    }
+
+    public String getFileName(final String baseName) {
+        // main output
+        if(partition == null)
+            return baseName;
+
+        if(baseName.trim().equals("/dev/null"))
+            return "/dev/null";
+
+        // mhanna 22 Aug 2010 - Deliberately force this header replacement to make sure integration tests pass.
+        // TODO: Update integration tests and get rid of this.
+        String partitionType = (partition == DoCOutputType.Partition.readgroup ? "read_group" : partition.toString());        
+
+        if(fileType == FileType.coverage_counts || fileType == FileType.coverage_proportions) {
+            // coverage counts / proportions files always include aggregation.
+            return baseName + "." +
+                    partitionType + "_" +
+                    aggregation + "_" +
+                    fileType;
+        }
+
+        return  baseName + "." +
+                partitionType + "_" +
+                (aggregation == Aggregation.interval || aggregation == Aggregation.gene ? aggregation + "_" : "") +
+                fileType;
+    }
+
+    public int hashCode() {
+        return (partition!=null?partition.ordinal()+1:0) * aggregation.ordinal() * fileType.ordinal();
+    }
+
+    public boolean equals(Object other) {
+        if(!(other instanceof DoCOutputType))
+            return false;
+        DoCOutputType otherOutputType = (DoCOutputType)other;
+        return partition == otherOutputType.partition &&
+                aggregation == otherOutputType.aggregation &&
+                fileType == otherOutputType.fileType;
+    }
+}
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/tools/walkers/coverage/GCContentByInterval.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/tools/walkers/coverage/GCContentByInterval.java
new file mode 100644
index 0000000..a23cfe3
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/tools/walkers/coverage/GCContentByInterval.java
@@ -0,0 +1,106 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.tools.walkers.coverage;
+
+import org.broadinstitute.gatk.engine.walkers.*;
+import org.broadinstitute.gatk.utils.commandline.Output;
+import org.broadinstitute.gatk.engine.CommandLineGATK;
+import org.broadinstitute.gatk.engine.contexts.AlignmentContext;
+import org.broadinstitute.gatk.engine.contexts.ReferenceContext;
+import org.broadinstitute.gatk.engine.refdata.RefMetaDataTracker;
+import org.broadinstitute.gatk.utils.BaseUtils;
+import org.broadinstitute.gatk.utils.GenomeLoc;
+import org.broadinstitute.gatk.utils.collections.Pair;
+import org.broadinstitute.gatk.utils.help.DocumentedGATKFeature;
+import org.broadinstitute.gatk.utils.help.HelpConstants;
+
+import java.io.PrintStream;
+import java.util.List;
+
+/**
+ * Walks along reference and calculates the GC content for each interval.
+ *
+ *
+ * <h3>Input</h3>
+ * <p>
+ *  A reference file
+ * </p>
+ *
+ * <h3>Output</h3>
+ * <p>
+ *  GC content calculations per interval.
+ * </p>
+ *
+ * <h3>Example</h3>
+ * <pre>
+ * java -Xmx2g -jar GenomeAnalysisTK.jar \
+ *   -T GCContentByInterval \
+ *   -R ref.fasta \
+ *   -o output.txt \
+ *   -L input.intervals
+ * </pre>
+ *
+ */
+ at DocumentedGATKFeature( groupName = HelpConstants.DOCS_CAT_QC, extraDocs = {CommandLineGATK.class} )
+ at Allows(value = {DataSource.REFERENCE})
+ at Requires(value = {DataSource.REFERENCE})
+ at By(DataSource.REFERENCE)
+public class GCContentByInterval extends LocusWalker<Long, Long> {
+    @Output
+    protected PrintStream out;
+
+    public boolean isReduceByInterval() {
+        return true;
+    }
+
+    public void initialize() {
+    }
+
+    public Long reduceInit() {
+        return 0L;
+    }
+
+    public Long map(RefMetaDataTracker tracker, ReferenceContext ref, AlignmentContext context) {
+        if (tracker == null)
+            return null;
+        int baseIndex = ref.getBaseIndex();
+        return (baseIndex == BaseUtils.Base.G.ordinal() || baseIndex == BaseUtils.Base.C.ordinal()) ? 1L : 0L;
+    }
+
+    public Long reduce(Long toAdd, Long runningCount) {
+        return runningCount + toAdd;
+    }
+
+    public void onTraversalDone(List<Pair<GenomeLoc, Long>> results) {
+        for (Pair<GenomeLoc, Long> result : results ) {
+            GenomeLoc loc = result.getFirst();
+            Long gcCount = result.getSecond();
+
+            double gcContent = (double) gcCount / loc.size();
+            out.println(loc + "\t" + gcContent);
+        }
+    }
+}
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/tools/walkers/diagnostics/CoveredByNSamplesSites.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/tools/walkers/diagnostics/CoveredByNSamplesSites.java
new file mode 100644
index 0000000..370cea2
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/tools/walkers/diagnostics/CoveredByNSamplesSites.java
@@ -0,0 +1,154 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.tools.walkers.diagnostics;
+
+
+import org.broadinstitute.gatk.engine.walkers.By;
+import org.broadinstitute.gatk.engine.walkers.DataSource;
+import org.broadinstitute.gatk.engine.walkers.RodWalker;
+import org.broadinstitute.gatk.engine.walkers.TreeReducible;
+import org.broadinstitute.gatk.utils.commandline.Argument;
+import org.broadinstitute.gatk.utils.commandline.ArgumentCollection;
+import org.broadinstitute.gatk.utils.commandline.Output;
+import org.broadinstitute.gatk.engine.CommandLineGATK;
+import org.broadinstitute.gatk.engine.arguments.StandardVariantContextInputArgumentCollection;
+import org.broadinstitute.gatk.engine.contexts.AlignmentContext;
+import org.broadinstitute.gatk.engine.contexts.ReferenceContext;
+import org.broadinstitute.gatk.engine.refdata.RefMetaDataTracker;
+import org.broadinstitute.gatk.utils.GenomeLoc;
+import org.broadinstitute.gatk.utils.help.DocumentedGATKFeature;
+import org.broadinstitute.gatk.utils.help.HelpConstants;
+import htsjdk.variant.variantcontext.Genotype;
+import htsjdk.variant.variantcontext.GenotypesContext;
+import htsjdk.variant.variantcontext.VariantContext;
+
+
+import java.io.*;
+import java.util.Collection;
+
+/**
+ * Print intervals file with all the variant sites for which most of the samples have good coverage
+ *
+ * <p>
+ * CoveredByNSamplesSites is a GATK tool for filtering out sites based on their coverage.
+ * The sites that pass the filter are printed out to an intervals file.
+ *
+ * See argument defaults for what constitutes "most" samples and "good" coverage. These parameters can be modified from the command line.
+ * </p>
+ *
+ * <h3>Input</h3>
+ * <p>
+ * A variant file and optionally min coverage and sample percentage values.
+ * </p>
+ *
+ * <h3>Output</h3>
+ * <p>
+ * An intervals file.
+ * </p>
+ *
+ * <h3>Example</h3>
+ * <pre>
+ * java -Xmx2g -jar GenomeAnalysisTK.jar \
+ *   -R ref.fasta \
+ *   -T CoveredByNSamplesSites \
+ *   -V input.vcf \
+ *   -out output.intervals \
+ *   -minCov 15
+ * </pre>
+ *
+ */
+ at DocumentedGATKFeature( groupName = HelpConstants.DOCS_CAT_QC, extraDocs = {CommandLineGATK.class} )
+ at By(DataSource.REFERENCE_ORDERED_DATA)
+public class CoveredByNSamplesSites extends RodWalker<GenomeLoc, Integer> implements TreeReducible<Integer> {
+
+    @Output(fullName = "OutputIntervals", shortName = "out", doc = "Name of file for output intervals")
+    PrintStream outputStream;
+
+    @ArgumentCollection
+    protected StandardVariantContextInputArgumentCollection variantCollection = new StandardVariantContextInputArgumentCollection();
+
+    @Argument(fullName = "minCoverage", shortName = "minCov",doc = "only samples that have coverage bigger than minCoverage will be counted",required = false)
+    int minCoverage = 10;
+
+    @Argument(fullName = "percentageOfSamples", shortName = "percentage", doc = "only sites where at least percentageOfSamples of the samples have good coverage, will be emitted", required = false)
+    double percentageOfSamples = 0.9;
+
+    @Override
+    public GenomeLoc map(RefMetaDataTracker tracker, ReferenceContext ref, AlignmentContext context) {
+        if ( tracker == null )
+            return null;
+
+        Collection<VariantContext> VCs = tracker.getValues(variantCollection.variants, context.getLocation());
+        if ( VCs.size() == 0 )
+            return null;
+
+        boolean emitSite = false;
+        for(VariantContext vc : VCs){
+            int coveredSamples = 0;
+            final GenotypesContext genotypes = vc.getGenotypes();
+            final int numOfGenotypes = genotypes.size();
+            for(Genotype g : genotypes){
+                if(g.getDP() >= minCoverage)
+                    coveredSamples++;
+            }
+            if((double)coveredSamples/numOfGenotypes > percentageOfSamples){
+                emitSite = true;
+            }
+        }
+        if (emitSite)
+            return ref.getLocus();
+        else
+            return null;
+    }
+
+    @Override
+    public Integer reduceInit() { return 0; }
+
+    @Override
+    public Integer reduce(GenomeLoc value, Integer sum) {
+        if ( value != null ) {
+            outputStream.println(value);
+            sum++;
+        }
+        return sum;
+    }
+
+    @Override
+    public Integer treeReduce(Integer lhs, Integer rhs) {
+        return lhs + rhs;
+    }
+
+    /**
+     *
+     * @param result the number of sites that passed the filter.
+     */
+    public void onTraversalDone(Integer result) {
+        logger.info(result+" sites that have "+(percentageOfSamples*100)+"% of the samples with at least "+minCoverage+" coverage.\n");
+    }
+
+
+
+}
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/tools/walkers/diagnostics/ErrorRatePerCycle.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/tools/walkers/diagnostics/ErrorRatePerCycle.java
new file mode 100644
index 0000000..910afa4
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/tools/walkers/diagnostics/ErrorRatePerCycle.java
@@ -0,0 +1,215 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.tools.walkers.diagnostics;
+
+import org.broadinstitute.gatk.utils.commandline.Argument;
+import org.broadinstitute.gatk.utils.commandline.Output;
+import org.broadinstitute.gatk.engine.CommandLineGATK;
+import org.broadinstitute.gatk.engine.contexts.AlignmentContext;
+import org.broadinstitute.gatk.engine.contexts.ReferenceContext;
+import org.broadinstitute.gatk.engine.refdata.RefMetaDataTracker;
+import org.broadinstitute.gatk.engine.report.GATKReport;
+import org.broadinstitute.gatk.engine.report.GATKReportTable;
+import org.broadinstitute.gatk.engine.walkers.LocusWalker;
+import org.broadinstitute.gatk.utils.BaseUtils;
+import org.broadinstitute.gatk.utils.QualityUtils;
+import org.broadinstitute.gatk.utils.help.DocumentedGATKFeature;
+import org.broadinstitute.gatk.utils.help.HelpConstants;
+import org.broadinstitute.gatk.utils.pileup.PileupElement;
+import org.broadinstitute.gatk.utils.sam.GATKSAMRecord;
+
+import java.io.PrintStream;
+
+/**
+ * Compute the read error rate per position
+ *
+ * <p>This tool computes the read error rate per position in sequence reads. It does this in the original 5'->3'
+ * orientation that the read had coming off the machine. It then emits a GATKReport containing readgroup, cycle,
+ * mismatches, counts, qual, and error rate for each read group in the input BAMs.</p>
+ *
+ * <h3>Input</h3>
+ *  <p>
+ *      Any number of BAM files
+ *  </p>
+ *
+ * <h3>Output</h3>
+ *  <p>
+ *      A GATKReport containing readgroup, cycle, mismatches, counts, qual, and error rate.
+ *
+ *      For example, running this tool on the NA12878 data sets yields the following table:
+ *
+ *      <pre>
+ *      ##:GATKReport.v0.2 ErrorRatePerCycle : The error rate per sequenced position in the reads
+ *      readgroup  cycle  mismatches  counts  qual  errorrate
+ *      20FUK.1        0          80   23368    25   3.47e-03
+ *      20FUK.1        1          40   23433    28   1.75e-03
+ *      20FUK.1        2          36   23453    28   1.58e-03
+ *      20FUK.1        3          26   23476    29   1.15e-03
+ *      20FUK.1        4          32   23495    29   1.40e-03
+ *      up to 101 cycles
+ *      20FUK.2        0          77   20886    24   3.73e-03
+ *      20FUK.2        1          28   20920    29   1.39e-03
+ *      20FUK.2        2          24   20931    29   1.19e-03
+ *      20FUK.2        3          30   20940    28   1.48e-03
+ *      20FUK.2        4          25   20948    29   1.24e-03
+ *      up to 101 cycles
+ *      20FUK.3        0          78   22038    24   3.58e-03
+ *      20FUK.3        1          40   22091    27   1.86e-03
+ *      20FUK.3        2          23   22108    30   1.09e-03
+ *      20FUK.3        3          36   22126    28   1.67e-03
+ *      </pre>
+ *  </p>
+ *
+ * <h3>Example</h3>
+ *  <pre>
+ *    java
+ *      -jar GenomeAnalysisTK.jar
+ *      -T ErrorRatePerCycle
+ *      -R human_g1k_v37.fasta
+ *      -I my_sequence_reads.bam
+ *      -o error_rates.gatkreport.txt
+ *  </pre>
+ *
+ * <h3>Caveat</h3>
+ *
+ * <p>Note that when it is run on paired-end sequence data, this tool only uses the first read in a pair.</p>
+ *
+ * @author Kiran Garimella, Mark DePristo
+ */
+ at DocumentedGATKFeature( groupName = HelpConstants.DOCS_CAT_QC, extraDocs = {CommandLineGATK.class} )
+public class ErrorRatePerCycle extends LocusWalker<Integer, Integer> {
+    @Output PrintStream out;
+    @Argument(fullName="min_base_quality_score", shortName="mbq", doc="Minimum base quality required to consider a base for calling", required=false)
+    public Integer MIN_BASE_QUAL = 0;
+    @Argument(fullName="min_mapping_quality_score", shortName="mmq", doc="Minimum read mapping quality required to consider a read for calling", required=false)
+    public Integer MIN_MAPPING_QUAL = 20;
+
+    private GATKReport report;
+    private GATKReportTable table;
+    private final static String reportName = "ErrorRatePerCycle";
+    private final static String reportDescription = "The error rate per sequenced position in the reads";
+
+    /**
+     * Allows us to use multiple records for the key (read group x cycle)
+     */
+    private static class TableKey implements Comparable<TableKey> {
+        final String readGroup;
+        final int cycle;
+
+        private TableKey(final String readGroup, final int cycle) {
+            this.readGroup = readGroup;
+            this.cycle = cycle;
+        }
+
+        // Must overload hashCode and equals to properly work with GATKReportColumn
+        @Override
+        public int hashCode() {
+            return readGroup.hashCode() + 33 * cycle;
+        }
+
+        @Override
+        public boolean equals(final Object o) {
+            if (this == o) return true;
+            if (o == null || getClass() != o.getClass()) return false;
+
+            final TableKey oKey = (TableKey) o;
+
+            if ( cycle != oKey.cycle ) return false;
+            if ( !readGroup.equals(oKey.readGroup) ) return false;
+
+            return true;
+        }
+
+        @Override
+        public int compareTo(final TableKey tableKey) {
+            final int scmp = readGroup.compareTo(tableKey.readGroup);
+            if ( scmp == 0 )
+                return Integer.valueOf(cycle).compareTo(tableKey.cycle);
+            else
+                return scmp;
+        }
+    }
+
+    public void initialize() {
+        report = new GATKReport();
+        report.addTable(reportName, reportDescription, 6, GATKReportTable.TableSortingWay.SORT_BY_ROW);
+        table = report.getTable(reportName);
+        table.addColumn("readgroup");
+        table.addColumn("cycle");
+        table.addColumn("mismatches");
+        table.addColumn("counts");
+        table.addColumn("qual");
+        table.addColumn("errorrate", "%.2e");
+    }
+
+    public Integer map(RefMetaDataTracker tracker, ReferenceContext ref, AlignmentContext context) {
+        for ( final PileupElement p : context.getBasePileup() ) {
+            final GATKSAMRecord read = p.getRead();
+            final int offset = p.getOffset();
+            final boolean firstOfPair = ! read.getReadPairedFlag() || read.getFirstOfPairFlag();
+
+            if ( firstOfPair && read.getMappingQuality() >= MIN_MAPPING_QUAL && p.getQual() >= MIN_BASE_QUAL ) {
+                final byte readBase = p.getBase();
+                final byte refBase = ref.getBase();
+                final int cycle = offset;
+
+                if ( BaseUtils.isRegularBase(readBase) && BaseUtils.isRegularBase(refBase) ) {
+                    final TableKey key = new TableKey(read.getReadGroup().getReadGroupId(), cycle);
+
+                    if ( ! table.containsRowID(key) ) {
+                        table.set(key, "cycle", cycle);
+                        table.set(key, "readgroup", read.getReadGroup().getReadGroupId());
+                        table.set(key, "counts", 0);
+                        table.set(key, "mismatches", 0);
+                    }
+
+                    table.increment(key, "counts");
+                    if (readBase != refBase)
+                        table.increment(key, "mismatches");
+                }
+            }
+        }
+
+        return null;
+    }
+
+    public Integer reduceInit() { return null; }
+
+    public Integer reduce(Integer value, Integer sum) { return null; }
+
+    public void onTraversalDone(Integer sum) {
+        for ( Object key : table.getRowIDs() ) {
+            final int mismatches = (Integer)table.get(key, "mismatches");
+            final int count = (Integer)table.get(key, "counts");
+            final double errorRate = (mismatches + 1) / (1.0*(count + 1));
+            final int qual = QualityUtils.errorProbToQual(errorRate);
+            table.set(key, "qual", qual);
+            table.set(key, "errorrate", errorRate);
+        }
+
+        report.print(out);
+    }
+}
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/tools/walkers/diagnostics/ReadGroupProperties.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/tools/walkers/diagnostics/ReadGroupProperties.java
new file mode 100644
index 0000000..e9856de
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/tools/walkers/diagnostics/ReadGroupProperties.java
@@ -0,0 +1,229 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.tools.walkers.diagnostics;
+
+import htsjdk.samtools.SAMReadGroupRecord;
+import org.broadinstitute.gatk.utils.commandline.Argument;
+import org.broadinstitute.gatk.utils.commandline.Output;
+import org.broadinstitute.gatk.engine.CommandLineGATK;
+import org.broadinstitute.gatk.engine.contexts.ReferenceContext;
+import org.broadinstitute.gatk.engine.refdata.RefMetaDataTracker;
+import org.broadinstitute.gatk.engine.report.GATKReport;
+import org.broadinstitute.gatk.engine.report.GATKReportTable;
+import org.broadinstitute.gatk.engine.walkers.ReadWalker;
+import org.broadinstitute.gatk.utils.Median;
+import org.broadinstitute.gatk.utils.help.DocumentedGATKFeature;
+import org.broadinstitute.gatk.utils.help.HelpConstants;
+import org.broadinstitute.gatk.utils.sam.GATKSAMRecord;
+
+import java.io.PrintStream;
+import java.text.DateFormat;
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * Emits a GATKReport containing read group, sample, library, platform, center, sequencing data,
+ * paired end status, simple read type name (e.g. 2x76) median insert size and median read length
+ * for each read group in every provided BAM file
+ *
+ * Note that this walker stops when all read groups have been observed at least a few thousand times so that
+ * the median statistics are well determined.  It is safe to run it WG and it'll finish in an appropriate
+ * timeframe.
+ *
+ * <h3>Input</h3>
+ *  <p>
+ *      Any number of BAM files
+ *  </p>
+ *
+ * <h3>Output</h3>
+ *  <p>
+ *      GATKReport containing read group, sample, library, platform, center, median insert size and median read length.
+ *
+ *      For example, running this tool on the NA12878 data sets:
+ *
+ *      <pre>
+ *      ##:GATKReport.v0.2 ReadGroupProperties : Table of read group properties
+ *      readgroup  sample   library       platform  center  date     has.any.reads  is.paired.end  n.reads.analyzed  simple.read.type  median.read.length  median.insert.size
+ *      20FUK.1    NA12878  Solexa-18483  illumina  BI      2/2/10   true           true                        498  2x101                            101                 386
+ *      20FUK.2    NA12878  Solexa-18484  illumina  BI      2/2/10   true           true                        476  2x101                            101                 417
+ *      20FUK.3    NA12878  Solexa-18483  illumina  BI      2/2/10   true           true                        407  2x101                            101                 387
+ *      20FUK.4    NA12878  Solexa-18484  illumina  BI      2/2/10   true           true                        389  2x101                            101                 415
+ *      20FUK.5    NA12878  Solexa-18483  illumina  BI      2/2/10   true           true                        433  2x101                            101                 386
+ *      20FUK.6    NA12878  Solexa-18484  illumina  BI      2/2/10   true           true                        480  2x101                            101                 418
+ *      20FUK.7    NA12878  Solexa-18483  illumina  BI      2/2/10   true           true                        450  2x101                            101                 386
+ *      20FUK.8    NA12878  Solexa-18484  illumina  BI      2/2/10   true           true                        438  2x101                            101                 418
+ *      20GAV.1    NA12878  Solexa-18483  illumina  BI      1/26/10  true           true                        490  2x101                            101                 391
+ *      20GAV.2    NA12878  Solexa-18484  illumina  BI      1/26/10  true           true                        485  2x101                            101                 417
+ *      20GAV.3    NA12878  Solexa-18483  illumina  BI      1/26/10  true           true                        460  2x101                            101                 392
+ *      20GAV.4    NA12878  Solexa-18484  illumina  BI      1/26/10  true           true                        434  2x101                            101                 415
+ *      20GAV.5    NA12878  Solexa-18483  illumina  BI      1/26/10  true           true                        479  2x101                            101                 389
+ *      20GAV.6    NA12878  Solexa-18484  illumina  BI      1/26/10  true           true                        461  2x101                            101                 416
+ *      20GAV.7    NA12878  Solexa-18483  illumina  BI      1/26/10  true           true                        509  2x101                            101                 386
+ *      20GAV.8    NA12878  Solexa-18484  illumina  BI      1/26/10  true           true                        476  2x101                            101                 410                           101                 414
+ *      </pre>
+ *  </p>
+ *
+ * <h3>Examples</h3>
+ *  <pre>
+ *    java
+ *      -jar GenomeAnalysisTK.jar
+ *      -T ReadGroupProperties
+ *      -I example1.bam -I example2.bam etc
+ *      -R reference.fasta
+ *      -o example.gatkreport.txt
+ *  </pre>
+ *
+ * @author Mark DePristo
+ */
+ at DocumentedGATKFeature( groupName = HelpConstants.DOCS_CAT_QC, extraDocs = {CommandLineGATK.class} )
+public class ReadGroupProperties extends ReadWalker<Integer, Integer> {
+    @Output
+    public PrintStream out;
+
+    @Argument(shortName="maxElementsForMedian", doc="Calculate median from the first maxElementsForMedian values observed", required=false)
+    public int MAX_VALUES_FOR_MEDIAN = 10000;
+
+    private final static String TABLE_NAME = "ReadGroupProperties";
+    private final Map<String, PerReadGroupInfo> readGroupInfo = new HashMap<String, PerReadGroupInfo>();
+
+    private class PerReadGroupInfo {
+        public final Median<Integer> readLength = new Median<Integer>(MAX_VALUES_FOR_MEDIAN);
+        public final Median<Integer> insertSize = new Median<Integer>(MAX_VALUES_FOR_MEDIAN);
+        public int nReadsSeen = 0, nReadsPaired = 0;
+
+        public boolean needsMoreData() {
+            return ! readLength.isFull() || ! insertSize.isFull();
+        }
+    }
+
+    @Override
+    public void initialize() {
+        for ( final SAMReadGroupRecord rg : getToolkit().getSAMFileHeader().getReadGroups() ) {
+            readGroupInfo.put(rg.getId(), new PerReadGroupInfo());
+        }
+    }
+
+    @Override
+    public boolean filter(ReferenceContext ref, GATKSAMRecord read) {
+        return ! (read.getReadFailsVendorQualityCheckFlag() || read.getReadUnmappedFlag());
+    }
+
+    @Override
+    public boolean isDone() {
+        for ( PerReadGroupInfo info : readGroupInfo.values() ) {
+            if ( info.needsMoreData() )
+                return false;
+        }
+
+        return true;
+    }
+
+    @Override
+    public Integer map(ReferenceContext referenceContext, GATKSAMRecord read, RefMetaDataTracker RefMetaDataTracker) {
+        final String rgID = read.getReadGroup().getId();
+        final PerReadGroupInfo info = readGroupInfo.get(rgID);
+
+        if ( info.needsMoreData() ) {
+            info.readLength.add(read.getReadLength());
+            info.nReadsSeen++;
+            if ( read.getReadPairedFlag() ) {
+                info.nReadsPaired++;
+                if ( read.getInferredInsertSize() != 0) {
+                    info.insertSize.add(Math.abs(read.getInferredInsertSize()));
+                }
+            }
+        }
+
+        return null;
+    }
+
+    @Override
+    public Integer reduceInit() {
+        return null;
+    }
+
+    @Override
+    public Integer reduce(Integer integer, Integer integer1) {
+        return null;
+    }
+
+    @Override
+    public void onTraversalDone(Integer sum) {
+        final GATKReport report = new GATKReport();
+        report.addTable(TABLE_NAME, "Table of read group properties", 12);
+        GATKReportTable table = report.getTable(TABLE_NAME);
+        DateFormat dateFormatter = DateFormat.getDateInstance(DateFormat.SHORT);
+
+        table.addColumn("readgroup");
+        //* Emits a GATKReport containing read group, sample, library, platform, center, median insert size and
+        //* median read length for each read group in every BAM file.
+        table.addColumn("sample", "%s");
+        table.addColumn("library", "%s");
+        table.addColumn("platform", "%s");
+        table.addColumn("center", "%s");
+        table.addColumn("date", "%s");
+        table.addColumn("has.any.reads");
+        table.addColumn("is.paired.end");
+        table.addColumn("n.reads.analyzed", "%d");
+        table.addColumn("simple.read.type", "%s");
+        table.addColumn("median.read.length");
+        table.addColumn("median.insert.size");
+
+        for ( final SAMReadGroupRecord rg : getToolkit().getSAMFileHeader().getReadGroups() ) {
+            final String rgID = rg.getId();
+            table.addRowID(rgID, true);
+            PerReadGroupInfo info = readGroupInfo.get(rgID);
+
+            // we are paired if > 25% of reads are paired
+            final boolean isPaired = info.nReadsPaired / (1.0 * (info.nReadsSeen+1)) > 0.25;
+            final boolean hasAnyReads = info.nReadsSeen > 0;
+            final int readLength = info.readLength.getMedian(0);
+
+            setTableValue(table, rgID, "sample", rg.getSample());
+            setTableValue(table, rgID, "library", rg.getLibrary());
+            setTableValue(table, rgID, "platform", rg.getPlatform());
+            setTableValue(table, rgID, "center", rg.getSequencingCenter());
+            try {
+                setTableValue(table, rgID, "date", rg.getRunDate() != null ? dateFormatter.format(rg.getRunDate()) : "NA");
+            } catch ( NullPointerException e ) {
+                // TODO: remove me when bug in Picard is fixed that causes NPE when date isn't present
+                setTableValue(table, rgID, "date", "NA");
+            }
+            setTableValue(table, rgID, "has.any.reads", hasAnyReads);
+            setTableValue(table, rgID, "is.paired.end", isPaired);
+            setTableValue(table, rgID, "n.reads.analyzed", info.nReadsSeen);
+            setTableValue(table, rgID, "simple.read.type", hasAnyReads ? String.format("%dx%d", isPaired ? 2 : 1, readLength) : "NA");
+            setTableValue(table, rgID, "median.read.length", hasAnyReads ? readLength : "NA" );
+            setTableValue(table, rgID, "median.insert.size", hasAnyReads && isPaired ? info.insertSize.getMedian(0) : "NA" );
+        }
+
+        report.print(out);
+    }
+
+    private final void setTableValue(GATKReportTable table, final String rgID, final String key, final Object value) {
+        table.set(rgID, key, value == null ? "NA" : value);
+    }
+}
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/tools/walkers/diagnostics/ReadLengthDistribution.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/tools/walkers/diagnostics/ReadLengthDistribution.java
new file mode 100644
index 0000000..a632f25
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/tools/walkers/diagnostics/ReadLengthDistribution.java
@@ -0,0 +1,180 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.tools.walkers.diagnostics;
+
+import htsjdk.samtools.SAMReadGroupRecord;
+import org.broadinstitute.gatk.utils.commandline.Output;
+import org.broadinstitute.gatk.engine.CommandLineGATK;
+import org.broadinstitute.gatk.engine.contexts.ReferenceContext;
+import org.broadinstitute.gatk.engine.refdata.RefMetaDataTracker;
+import org.broadinstitute.gatk.engine.report.GATKReport;
+import org.broadinstitute.gatk.engine.report.GATKReportTable;
+import org.broadinstitute.gatk.engine.walkers.ReadWalker;
+import org.broadinstitute.gatk.utils.help.DocumentedGATKFeature;
+import org.broadinstitute.gatk.utils.help.HelpConstants;
+import org.broadinstitute.gatk.utils.sam.GATKSAMRecord;
+
+import java.io.PrintStream;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.TreeMap;
+
+/**
+ * Outputs the read lengths of all the reads in a file.
+ *
+ *  <p>
+ *     Generates a table with the read lengths categorized per sample. If the file has no sample information
+ *     (no read groups) it considers all reads to come from the same sample.
+ *  </p>
+ *
+ *
+ * <h3>Input</h3>
+ *  <p>
+ *      A BAM file.
+ *  </p>
+ *
+ * <h3>Output</h3>
+ *  <p>
+ *      A human/R readable table of tab separated values with one column per sample and one row per read.
+ *  </p>
+ *
+ * <h3>Examples</h3>
+ *  <pre>
+ *    java
+ *      -jar GenomeAnalysisTK.jar
+ *      -T ReadLengthDistribution
+ *      -I example.bam
+ *      -R reference.fasta
+ *      -o example.tbl
+ *  </pre>
+ *
+ * @author Kiran Garimela
+ */
+
+ at DocumentedGATKFeature( groupName = HelpConstants.DOCS_CAT_QC, extraDocs = {CommandLineGATK.class} )
+public class ReadLengthDistribution extends ReadWalker<Integer, Integer> {
+    @Output
+    public PrintStream out;
+
+    //A map from RG to its column number (its index in an int[] array)
+    private Map<SAMReadGroupRecord,Integer> readGroupsLocation;
+    //Each line in the table is a read length and each column it the number of reads of a specific RG with that length. Thus a table is a map between read lengths to array of values (one for each RG).
+    private Map<Integer,int[]> table;
+    private List<SAMReadGroupRecord> readGroups;
+
+    public void initialize() {
+        readGroups = getToolkit().getSAMFileHeader().getReadGroups();
+        readGroupsLocation = new HashMap<>();
+        table = new TreeMap<>();
+        int readGroupsNum = 0;
+
+        if (!readGroups.isEmpty()){
+            for (SAMReadGroupRecord rg : readGroups){
+                readGroupsLocation.put(rg,readGroupsNum);
+                readGroupsNum++;
+            }
+        }
+    }
+
+    @Override
+    public Integer map(final ReferenceContext referenceContext,final GATKSAMRecord samRecord,final RefMetaDataTracker RefMetaDataTracker) {
+
+        final int length = Math.abs(samRecord.getReadLength());
+        final SAMReadGroupRecord rg = samRecord.getReadGroup();
+
+        increment(table,length, rg);
+
+        return null;
+    }
+
+    final private void increment(final Map<Integer,int[]> table,final int length,final SAMReadGroupRecord rg){
+        if(readGroupsLocation.isEmpty()){
+            if(table.containsKey(length))
+                table.get(length)[0]++;
+            else{
+                final int[] newLength = {1};
+                table.put(length,newLength);
+            }
+        }
+        else{
+            final int rgLocation = readGroupsLocation.get(rg);
+            if(table.containsKey(length))
+                table.get(length)[rgLocation]++;
+            else{
+                table.put(length,new int[readGroupsLocation.size()]);
+                table.get(length)[rgLocation]++;
+            }
+        }
+    }
+
+    @Override
+    public Integer reduceInit() {
+        return null;
+    }
+
+    @Override
+    public Integer reduce(final Integer integer,final Integer integer1) {
+        return null;
+    }
+
+    public void onTraversalDone(final Integer sum) {
+        final GATKReport report = createGATKReport();
+        report.print(out);
+    }
+
+    final private GATKReport createGATKReport(){
+        final GATKReport report = new GATKReport();
+        report.addTable("ReadLengthDistribution", "Table of read length distributions", 1 + (readGroupsLocation.isEmpty() ? 1 : readGroupsLocation.size()));
+        final GATKReportTable tableReport = report.getTable("ReadLengthDistribution");
+
+        tableReport.addColumn("readLength");
+
+        if (readGroupsLocation.isEmpty()){
+            tableReport.addColumn("SINGLE_SAMPLE");
+            int rowIndex = 0;
+            for (Integer length : table.keySet()){
+                tableReport.set(rowIndex,0,length);
+                tableReport.set(rowIndex,1,table.get(length)[0]);
+                rowIndex++;
+            }
+        }
+        else{
+            for (SAMReadGroupRecord rg : readGroups)
+                tableReport.addColumn(rg.getSample());
+            int rowIndex = 0;
+            for (Integer length : table.keySet()){
+                tableReport.set(rowIndex,0,length);
+                for (int i=0; i < readGroupsLocation.size(); i++)
+                    tableReport.set(rowIndex,i+1,table.get(length)[i]);
+                rowIndex++;
+            }
+
+        }
+
+        return report;
+    }
+}
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/tools/walkers/examples/GATKDocsExample.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/tools/walkers/examples/GATKDocsExample.java
new file mode 100644
index 0000000..80fca67
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/tools/walkers/examples/GATKDocsExample.java
@@ -0,0 +1,83 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.tools.walkers.examples;
+
+import org.broadinstitute.gatk.utils.commandline.Argument;
+import org.broadinstitute.gatk.utils.commandline.Hidden;
+import org.broadinstitute.gatk.engine.contexts.AlignmentContext;
+import org.broadinstitute.gatk.engine.contexts.ReferenceContext;
+import org.broadinstitute.gatk.engine.refdata.RefMetaDataTracker;
+import org.broadinstitute.gatk.engine.walkers.RodWalker;
+
+/**
+ * [Short one sentence description of this walker]
+ *
+ * <p>
+ * [Functionality of this walker]
+ * </p>
+ *
+ * <h3>Input</h3>
+ * <p>
+ * [Input description]
+ * </p>
+ *
+ * <h3>Output</h3>
+ * <p>
+ * [Output description]
+ * </p>
+ *
+ * <h3>Examples</h3>
+ * <pre>
+ *    java
+ *      -jar GenomeAnalysisTK.jar
+ *      -T $WalkerName
+ *  </pre>
+ *
+ * @author Your Name
+ * @since Date created
+ */
+ at Hidden
+public class GATKDocsExample extends RodWalker<Integer, Integer> {
+    /**
+     * Put detailed documentation about the argument here.  No need to duplicate the summary information
+     * in doc annotation field, as that will be added before this text in the documentation page.
+     *
+     * Notes:
+     * <ul>
+     *     <li>This field can contain HTML as a normal javadoc</li>
+     *     <li>Don't include information about the default value, as gatkdocs adds this automatically</li>
+     *     <li>Try your best to describe in detail the behavior of the argument, as ultimately confusing
+     *          docs here will just result in user posts on the forum</li>
+     * </ul>
+     */
+    @Argument(fullName="full", shortName="short", doc="Brief summary of argument [~ 80 characters of text]", required=false)
+    private boolean myWalkerArgument = false;
+
+    public Integer map(RefMetaDataTracker tracker, ReferenceContext ref, AlignmentContext context) { return 0; }
+    public Integer reduceInit() { return 0; }
+    public Integer reduce(Integer value, Integer sum) { return value + sum; }
+    public void onTraversalDone(Integer result) { }
+}
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/tools/walkers/examples/GATKPaperGenotyper.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/tools/walkers/examples/GATKPaperGenotyper.java
new file mode 100644
index 0000000..8cfc14e
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/tools/walkers/examples/GATKPaperGenotyper.java
@@ -0,0 +1,273 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.tools.walkers.examples;
+
+import org.broadinstitute.gatk.utils.commandline.Argument;
+import org.broadinstitute.gatk.utils.commandline.Output;
+import org.broadinstitute.gatk.engine.CommandLineGATK;
+import org.broadinstitute.gatk.engine.contexts.AlignmentContext;
+import org.broadinstitute.gatk.engine.contexts.ReferenceContext;
+import org.broadinstitute.gatk.engine.refdata.RefMetaDataTracker;
+import org.broadinstitute.gatk.engine.walkers.LocusWalker;
+import org.broadinstitute.gatk.engine.walkers.TreeReducible;
+import org.broadinstitute.gatk.utils.genotyper.DiploidGenotype;
+import org.broadinstitute.gatk.utils.MathUtils;
+import org.broadinstitute.gatk.utils.help.DocumentedGATKFeature;
+import org.broadinstitute.gatk.utils.help.HelpConstants;
+import org.broadinstitute.gatk.utils.pileup.ReadBackedPileup;
+
+import java.io.PrintStream;
+import java.util.Arrays;
+import java.util.Comparator;
+
+/**
+ * A simple Bayesian genotyper, that outputs a text based call format. Intended to be used only as an
+ * example in the GATK publication.
+ *
+ * @author aaron
+ */
+ at DocumentedGATKFeature( groupName = HelpConstants.DOCS_CAT_TOY, extraDocs = {CommandLineGATK.class} )
+public class GATKPaperGenotyper extends LocusWalker<Integer,Long> implements TreeReducible<Long> {
+
+    public static final double HUMAN_SNP_HETEROZYGOSITY = 1e-3;
+
+    // the possible diploid genotype strings
+    private static enum GENOTYPE { AA, AC, AG, AT, CC, CG, CT, GG, GT, TT }
+
+    @Output
+    private PrintStream out;
+
+    @Argument(fullName = "log_odds_score", shortName = "LOD", doc = "The LOD threshold for us to call confidently a genotype", required = false)
+    private double LODScore = 3.0;
+
+    /**
+     * our map function, which takes the reads spanning this locus, any associated reference ordered data,
+     * and the reference information.  We output a simple genotype call as the result of this function
+     *
+     * @param tracker the reference ordered data tracker
+     * @param ref     the reference information
+     * @param context the locus context, which contains all of the read information
+     * @return a SimpleCall, which stores the genotype we're calling and the LOD score
+     */
+    public Integer map(RefMetaDataTracker tracker, ReferenceContext ref, AlignmentContext context) {
+        if (ref.getBase() == 'N' || ref.getBase() == 'n') return null; // we don't deal with the N ref base case
+
+        ReadBackedPileup pileup = context.getBasePileup().getPileupWithoutMappingQualityZeroReads();
+        double likelihoods[] = getReferencePolarizedPriors(ref.getBase(),
+                HUMAN_SNP_HETEROZYGOSITY,
+                0.01);
+        // get the bases and qualities from the pileup
+        byte bases[] = pileup.getBases();
+        byte quals[] = pileup.getQuals();
+
+        // for each genotype, determine it's likelihood value
+        for (GENOTYPE genotype : GENOTYPE.values())
+            for (int index = 0; index < bases.length; index++) {
+                // our epsilon is the de-Phred scored base quality
+                double epsilon = Math.pow(10, quals[index] / -10.0);
+
+                byte pileupBase = bases[index];
+                double p = 0;
+                for (char r : genotype.toString().toCharArray())
+                    p += r == pileupBase ? 1 - epsilon : epsilon / 3;
+                likelihoods[genotype.ordinal()] += Math.log10(p / genotype.toString().length());
+            }
+
+        Integer sortedList[] = sortPermutation(likelihoods);
+
+        // create call using the best genotype (GENOTYPE.values()[sortedList[9]].toString())
+        // and calculate the LOD score from best - next best (9 and 8 in the sorted list, since the best likelihoods are closest to zero)
+        GENOTYPE selectedGenotype = GENOTYPE.values()[sortedList[sortedList.length-1]];
+        double lod = likelihoods[sortedList[sortedList.length-1]] - likelihoods[sortedList[sortedList.length-2]];
+
+        if (lod > LODScore) {
+            out.printf("%s\t%s\t%.4f\t%c%n", context.getLocation(), selectedGenotype, lod, (char)ref.getBase());
+            return 1;
+        }
+
+        return 0;
+    }
+
+    private static Integer[] sortPermutation(final double[] A) {
+        class comparator implements Comparator<Integer> {
+            public int compare(Integer a, Integer b) {
+                if (A[a.intValue()] < A[b.intValue()]) {
+                    return -1;
+                }
+                if (A[a.intValue()] == A[b.intValue()]) {
+                    return 0;
+                }
+                if (A[a.intValue()] > A[b.intValue()]) {
+                    return 1;
+                }
+                return 0;
+            }
+        }
+        Integer[] permutation = new Integer[A.length];
+        for (int i = 0; i < A.length; i++) {
+            permutation[i] = i;
+        }
+        Arrays.sort(permutation, new comparator());
+        return permutation;
+    }
+
+    /**
+     * Takes reference base, and three priors for hom-ref, het, hom-var, and fills in the priors vector
+     * appropriately.
+     *
+     * Suppose A is the reference base, and we are given the probability of being hom-ref, het, and hom-var,
+     * and that pTriSateGenotype is the true probability of observing reference A and a true genotype of B/C
+     * then this sets the priors to:
+     *
+     * AA = hom-ref
+     * AC = AG = AT = (het - pTriStateGenotype) / 3
+     * CC = GG = TT = hom-var / 3
+     * CG = CT = GT = pTriStateGenotype / 3
+     *
+     * So that we get:
+     *
+     * hom-ref + 3 * (het - pTriStateGenotype) / 3 + 3 * hom-var / 3 + 3 * pTriStateGenotype
+     * hom-ref + het - pTriStateGenotype + hom-var + pTriStateGenotype
+     * hom-ref + het + hom-var
+     * = 1
+     *
+     * @param ref
+     * @param heterozyosity
+     * @param pRefError
+     */
+    public static double[] getReferencePolarizedPriors(byte ref, double heterozyosity, double pRefError ) {
+        if ( ! MathUtils.isBounded(pRefError, 0.0, 0.01) ) {
+            throw new RuntimeException(String.format("BUG: p Reference error is out of bounds (0.0 - 0.01) is allow range %f", pRefError));
+        }
+
+        double pTriStateGenotype = heterozyosity * pRefError;
+//        if ( pTriStateGenotype >= heterozyosity ) {
+//            throw new RuntimeException(String.format("p Tristate genotype %f is greater than the heterozygosity %f", pTriStateGenotype, heterozyosity));
+//        }
+
+        double pHomRef = heterozygosity2HomRefProbability(heterozyosity);
+        double pHet    = heterozygosity2HetProbability(heterozyosity);
+        double pHomVar = heterozygosity2HomVarProbability(heterozyosity);
+
+        if (MathUtils.compareDoubles(pHomRef + pHet + pHomVar, 1.0) != 0) {
+            throw new RuntimeException(String.format("BUG: Prior probabilities don't sum to one => %f, %f, %f", pHomRef, pHet, pHomVar));
+        }
+
+        double[] priors = new double[DiploidGenotype.values().length];
+
+        for ( DiploidGenotype g : DiploidGenotype.values() ) {
+            double POfG;
+
+            final double nOnRefHets = 3;
+            final double nOffRefHets = 3;
+            final double nHomVars = 3;
+
+            if ( g.isHomRef(ref) )      { POfG = pHomRef; }
+            else if ( g.isHomVar(ref) ) { POfG = pHomVar / nHomVars; }
+            else if ( g.isHetRef(ref) ) { POfG = (pHet - pTriStateGenotype ) / nOnRefHets; }
+            else                        { POfG = pTriStateGenotype / nOffRefHets; }
+
+            priors[g.ordinal()] = Math.log10(POfG);
+        }
+
+        return priors;
+    }
+
+    /**
+     *
+     * @param h
+     * @return
+     */
+    public static double heterozygosity2HomRefProbability(double h) {
+        if (MathUtils.isNegative(h)) {
+            throw new RuntimeException(String.format("Heterozygous value is bad %f", h));
+        }
+
+        double v = 1.0 - (3.0 * h / 2.0);
+        if (MathUtils.isNegative(v)) {
+            throw new RuntimeException(String.format("Heterozygous value is bad %f", h));
+        }
+
+        return v;
+    }
+
+    public static double heterozygosity2HetProbability(double h) {
+        if (MathUtils.isNegative(h)) {
+            throw new RuntimeException(String.format("Heterozygous value is bad %f", h));
+        }
+
+        return h;
+    }
+
+    public static double heterozygosity2HomVarProbability(double h) {
+        if (MathUtils.isNegative(h)) {
+            throw new RuntimeException(String.format("Heterozygous value is bad %f", h));
+        }
+
+        return h / 2.0;
+    }
+
+    /**
+        * Provide an initial value for reduce computations. In this case we simply return an empty list
+        *
+        * @return Initial value of reduce.
+        */
+    public Long reduceInit() {
+        return 0L;
+    }
+
+    /**
+     * Outputs the number of genotypes called.
+     *
+     * @param value result of the map.
+     * @param sum   accumulator for the reduce.
+     * @return accumulator with result of the map taken into account.
+     */
+    public Long reduce(Integer value, Long sum) {
+        return value + sum;
+    }
+
+    /**
+     * A composite, 'reduce of reduces' function.
+     *
+     * @param lhs 'left-most' portion of data in the composite reduce.
+     * @param rhs 'right-most' portion of data in the composite reduce.
+     * @return The composite reduce type.
+     */
+    public Long treeReduce(Long lhs, Long rhs) {
+        return lhs + rhs;
+    }
+
+    /**
+     * when we finish traversing, close the result list
+     * @param result the final reduce result
+     */
+    public void onTraversalDone(Integer result) {
+        out.println("Simple Genotyper genotyped " + result + "Loci.");
+    }
+}
+
+
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/tools/walkers/fasta/FastaAlternateReferenceMaker.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/tools/walkers/fasta/FastaAlternateReferenceMaker.java
new file mode 100644
index 0000000..8fd4152
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/tools/walkers/fasta/FastaAlternateReferenceMaker.java
@@ -0,0 +1,187 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.tools.walkers.fasta;
+
+import org.broadinstitute.gatk.utils.commandline.Argument;
+import org.broadinstitute.gatk.utils.commandline.ArgumentCollection;
+import org.broadinstitute.gatk.utils.commandline.Input;
+import org.broadinstitute.gatk.utils.commandline.RodBinding;
+import org.broadinstitute.gatk.engine.CommandLineGATK;
+import org.broadinstitute.gatk.engine.arguments.StandardVariantContextInputArgumentCollection;
+import org.broadinstitute.gatk.engine.contexts.AlignmentContext;
+import org.broadinstitute.gatk.engine.contexts.ReferenceContext;
+import org.broadinstitute.gatk.engine.refdata.RefMetaDataTracker;
+import org.broadinstitute.gatk.engine.walkers.*;
+import org.broadinstitute.gatk.utils.BaseUtils;
+import org.broadinstitute.gatk.utils.GenomeLoc;
+import org.broadinstitute.gatk.utils.SampleUtils;
+import org.broadinstitute.gatk.utils.collections.Pair;
+import org.broadinstitute.gatk.utils.exceptions.UserException;
+import org.broadinstitute.gatk.utils.help.DocumentedGATKFeature;
+import org.broadinstitute.gatk.utils.help.HelpConstants;
+import htsjdk.variant.variantcontext.Genotype;
+import htsjdk.variant.variantcontext.VariantContext;
+
+import java.util.Arrays;
+import java.util.List;
+import java.util.Set;
+
+
+/**
+ * Generates an alternative reference sequence over the specified interval.
+ *
+ * <p>
+ * Given variant tracks, it replaces the reference bases at variation sites with the bases supplied by the ROD(s).
+ * Additionally, allows for one or more "snpmask" VCFs to set overlapping bases to 'N'.
+ *
+ * The output format can be partially controlled using the provided command-line arguments.
+ * Specify intervals with the usual -L argument to output only the reference bases within your intervals.
+ * Overlapping intervals are automatically merged; reference bases for each disjoint interval will be output as a
+ * separate fasta sequence (named numerically in order).
+ *
+ * Several important notes:
+ * 1) if there are multiple variants that start at a site, it chooses one of them randomly.
+ * 2) when there are overlapping indels (but with different start positions) only the first will be chosen.
+ * 3) this tool works only for SNPs and for simple indels (but not for things like complex substitutions).
+ * Reference bases for each interval will be output as a separate fasta sequence (named numerically in order).
+ *
+ * <h3>Input</h3>
+ * <p>
+ * The reference, requested intervals, and any number of variant rod files.
+ * </p>
+ *
+ * <h3>Output</h3>
+ * <p>
+ * A fasta file representing the requested intervals.
+ * </p>
+ *
+ * <h3>Examples</h3>
+ * <pre>
+ * java -Xmx2g -jar GenomeAnalysisTK.jar \
+ *   -R ref.fasta \
+ *   -T FastaAlternateReferenceMaker \
+ *   -o output.fasta \
+ *   -L input.intervals \
+ *   --variant input.vcf \
+ *   [--snpmask mask.vcf]
+ * </pre>
+ *
+ */
+ at DocumentedGATKFeature( groupName = HelpConstants.DOCS_CAT_REFUTILS, extraDocs = {CommandLineGATK.class} )
+ at Reference(window=@Window(start=-1,stop=50))
+ at Requires(value={DataSource.REFERENCE})
+public class FastaAlternateReferenceMaker extends FastaReferenceMaker {
+
+    /**
+     * Variants from this input file are used by this tool to construct an alternate reference.
+     */
+    @ArgumentCollection
+    protected StandardVariantContextInputArgumentCollection variantCollection = new StandardVariantContextInputArgumentCollection();
+
+    /**
+     * Snps from this file are used as a mask (inserting N's in the sequence) when constructing the alternate reference
+     * (regardless of whether they overlap a variant site).
+     */
+    @Input(fullName="snpmask", shortName = "snpmask", doc="SNP mask VCF file", required=false)
+    protected RodBinding<VariantContext> snpmask;
+
+    /**
+     * This option will generate an error if the specified sample does not exist in the VCF.
+     * Non-diploid (or non-called) genotypes are ignored.
+     */
+    @Argument(fullName="use_IUPAC_sample", shortName="IUPAC", doc = "If specified, heterozygous SNP sites will be output using IUPAC ambiguity codes given the genotypes for this sample", required=false)
+    private String iupacSample = null;
+
+    private int deletionBasesRemaining = 0;
+
+    @Override
+    public void initialize() {
+        super.initialize();
+        if ( iupacSample != null ) {
+            final List<String> rodName = Arrays.asList(variantCollection.variants.getName());
+            final Set<String> samples = SampleUtils.getUniqueSamplesFromRods(getToolkit(), rodName);
+            if ( !samples.contains(iupacSample) )
+                throw new UserException.BadInput("the IUPAC sample specified is not present in the provided VCF file");
+        }
+    }
+
+    @Override
+    public Pair<GenomeLoc, String> map(final RefMetaDataTracker tracker, final ReferenceContext ref, final AlignmentContext context) {
+
+        if (deletionBasesRemaining > 0) {
+            deletionBasesRemaining--;
+            return new Pair<>(context.getLocation(), "");
+        }
+
+        final String refBase = String.valueOf((char)ref.getBase());
+
+        // Check to see if we have a called snp
+        for ( final VariantContext vc : tracker.getValues(variantCollection.variants, ref.getLocus()) ) {
+            if ( vc.isFiltered() )
+                continue;
+
+            if ( vc.isSimpleDeletion()) {
+                deletionBasesRemaining = vc.getReference().length() - 1;
+                // delete the next n bases, not this one
+                return new Pair<>(context.getLocation(), refBase);
+            } else if ( vc.isSimpleInsertion()) {
+                return new Pair<>(context.getLocation(), vc.getAlternateAllele(0).toString());
+            } else if (vc.isSNP()) {
+                final String base = (iupacSample != null) ? getIUPACbase(vc.getGenotype(iupacSample), refBase) : vc.getAlternateAllele(0).toString();
+                return new Pair<>(context.getLocation(), base);
+            }
+        }
+
+        // if we don't have a called site, and we have a mask at this site, mask it
+        for ( final VariantContext vc : tracker.getValues(snpmask) ) {
+            if ( vc.isSNP()) {
+                return new Pair<>(context.getLocation(), "N");
+            }
+        }
+
+        // if we got here then we're just ref
+        return new Pair<>(context.getLocation(), refBase);
+    }
+
+    /**
+     * Returns the IUPAC encoding for the given genotype or the reference base if not possible
+     *
+     * @param genotype  the genotype to encode
+     * @param ref       the reference base
+     * @return non-null, non-empty String
+     */
+    private String getIUPACbase(final Genotype genotype, final String ref) {
+        if ( genotype == null )
+            throw new IllegalStateException("The genotype is null for sample " + iupacSample);
+
+        if ( !genotype.isHet() )
+            return genotype.isHom() ? genotype.getAllele(0).getBaseString() : ref;
+
+        final byte allele1 = genotype.getAllele(0).getBases()[0];
+        final byte allele2 = genotype.getAllele(1).getBases()[0];
+        return new String(new byte[] {BaseUtils.basesToIUPAC(allele1, allele2)});
+    }
+}
\ No newline at end of file
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/tools/walkers/fasta/FastaReferenceMaker.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/tools/walkers/fasta/FastaReferenceMaker.java
new file mode 100644
index 0000000..8459506
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/tools/walkers/fasta/FastaReferenceMaker.java
@@ -0,0 +1,127 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.tools.walkers.fasta;
+
+import org.broadinstitute.gatk.utils.commandline.Argument;
+import org.broadinstitute.gatk.utils.commandline.Output;
+import org.broadinstitute.gatk.engine.CommandLineGATK;
+import org.broadinstitute.gatk.engine.contexts.AlignmentContext;
+import org.broadinstitute.gatk.engine.contexts.ReferenceContext;
+import org.broadinstitute.gatk.engine.refdata.RefMetaDataTracker;
+import org.broadinstitute.gatk.engine.walkers.RefWalker;
+import org.broadinstitute.gatk.utils.GenomeLoc;
+import org.broadinstitute.gatk.utils.collections.Pair;
+import org.broadinstitute.gatk.utils.help.DocumentedGATKFeature;
+import org.broadinstitute.gatk.utils.help.HelpConstants;
+
+import java.io.PrintStream;
+
+/**
+ * Renders a new reference in FASTA format consisting of only those loci provided in the input data set.
+ *
+ * <p>
+ * The output format can be partially controlled using the provided command-line arguments.
+ * Specify intervals with the usual -L argument to output only the reference bases within your intervals.
+ * Overlapping intervals are automatically merged; reference bases for each disjoint interval will be output as a
+ * separate fasta sequence (named numerically in order).
+ *
+ * <h3>Input</h3>
+ * <p>
+ * The reference and requested intervals.
+ * </p>
+ *
+ * <h3>Output</h3>
+ * <p>
+ * A fasta file representing the requested intervals.
+ * </p>
+ *
+ * <h3>Examples</h3>
+ * <pre>
+ * java -Xmx2g -jar GenomeAnalysisTK.jar \
+ *   -R ref.fasta \
+ *   -T FastaReferenceMaker \
+ *   -o output.fasta \
+ *   -L input.intervals
+ * </pre>
+ *
+ */
+ at DocumentedGATKFeature( groupName = HelpConstants.DOCS_CAT_REFUTILS, extraDocs = {CommandLineGATK.class} )
+public class FastaReferenceMaker extends RefWalker<Pair<GenomeLoc, String>, GenomeLoc> {
+
+    @Output PrintStream out;
+
+    @Argument(fullName="lineWidth", shortName="lw", doc="Maximum length of sequence to write per line", required=false)
+    public int fastaLineWidth=60;
+
+    /**
+     *  Please note that when using this argument adjacent intervals will automatically be merged.
+     */
+    @Argument(fullName="rawOnelineSeq", shortName="raw", doc="Print sequences with no FASTA header lines, one line per interval (i.e. lineWidth = infinity)", required=false)
+    public boolean fastaRawSeqs=false;
+
+    protected FastaSequence fasta;
+
+    public void initialize() {
+        if (fastaRawSeqs) fastaLineWidth = Integer.MAX_VALUE;
+        fasta = new FastaSequence(out, fastaLineWidth, fastaRawSeqs);
+    }
+
+	public Pair<GenomeLoc, String> map(RefMetaDataTracker rodData, ReferenceContext ref, AlignmentContext context) {
+        return new Pair<GenomeLoc, String>(context.getLocation(), String.valueOf((char)ref.getBase()));
+	}
+
+    public GenomeLoc reduceInit() {
+        return null;
+    }
+
+	public GenomeLoc reduce(Pair<GenomeLoc, String> value, GenomeLoc sum) {
+        if ( value == null )
+            return sum;
+
+        // if there is no interval to the left, then this is the first one
+        if ( sum == null ) {
+            sum = value.first;
+            fasta.append(value.second);
+        }
+        // if the intervals don't overlap, print out the leftmost one and start a new one
+        // (end of contig or new interval)
+        else if ( value.first.getStart() != sum.getStop() + 1 ) {
+            fasta.flush();
+            sum = value.first;
+            fasta.append(value.second);
+        }
+        // otherwise, merge them
+        else {
+            sum = getToolkit().getGenomeLocParser().setStop(sum, value.first.getStop());
+            fasta.append(value.second);
+        }
+		return sum;
+	}
+
+    public void onTraversalDone(GenomeLoc sum) {
+        fasta.flush();
+    }
+}
\ No newline at end of file
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/tools/walkers/fasta/FastaSequence.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/tools/walkers/fasta/FastaSequence.java
new file mode 100644
index 0000000..013e356
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/tools/walkers/fasta/FastaSequence.java
@@ -0,0 +1,101 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.tools.walkers.fasta;
+
+import org.broadinstitute.gatk.utils.exceptions.ReviewedGATKException;
+
+import java.io.PrintStream;
+
+// fasta sequence holder class
+
+public class FastaSequence {
+
+    private PrintStream out;
+    private StringBuffer sb = new StringBuffer();
+    private long sequenceCounter = 1;
+    private boolean printedHeader = false;
+    private String name = null;
+    private int lineWidth = -1;
+    private boolean noHeader = false;
+
+	public FastaSequence(PrintStream out, int lineWidth, boolean noHeader) {
+        this.out = out;
+        this.lineWidth = lineWidth;
+        this.noHeader = noHeader;
+    }
+
+    public void setName(String name) {
+        if ( printedHeader ) throw new ReviewedGATKException("Can not set name for FASTA record: header is already printed.");
+        this.name = name;
+    }
+
+    public String getName() {
+        if ( name != null ) return name;
+        else return getCurrentID();                        
+    }
+    
+    public void append(String s) {
+        sb.append(s);
+        printFasta(false);
+    }
+
+    public void flush() {
+        printFasta(true);
+        printedHeader = false;
+        name = null;
+        sequenceCounter++;
+    }
+
+    public long getCurrentCount() {
+        return sequenceCounter;
+    }
+
+    public String getCurrentID() {
+        return String.valueOf(sequenceCounter);
+    }
+
+    private void printFasta(boolean printAll) {
+        if ( sb.length() == 0 || (!printAll && sb.length() < lineWidth) )
+            return;
+        if ( !printedHeader && !noHeader) {
+            if ( name == null ) out.println(">" + sequenceCounter);
+            else out.println(">" + name);
+            printedHeader = true;
+        }
+        int lines = sb.length() / lineWidth;
+        int currentStart = 0;
+        for (int i=0; i < lines; i++) {
+            out.println(sb.substring(currentStart, currentStart+lineWidth));
+            currentStart += lineWidth;
+        }
+        if ( printAll ) {
+            out.println(sb.substring(currentStart));
+            sb.setLength(0);
+        } else {
+            sb.delete(0, currentStart);
+        }
+    }
+}
\ No newline at end of file
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/tools/walkers/fasta/FastaStats.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/tools/walkers/fasta/FastaStats.java
new file mode 100644
index 0000000..22a592b
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/tools/walkers/fasta/FastaStats.java
@@ -0,0 +1,93 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.tools.walkers.fasta;
+
+import org.broadinstitute.gatk.utils.commandline.Output;
+import org.broadinstitute.gatk.engine.CommandLineGATK;
+import org.broadinstitute.gatk.engine.contexts.AlignmentContext;
+import org.broadinstitute.gatk.engine.contexts.ReferenceContext;
+import org.broadinstitute.gatk.engine.refdata.RefMetaDataTracker;
+import org.broadinstitute.gatk.engine.walkers.RefWalker;
+import org.broadinstitute.gatk.utils.BaseUtils;
+import org.broadinstitute.gatk.utils.help.DocumentedGATKFeature;
+import org.broadinstitute.gatk.utils.help.HelpConstants;
+
+import java.io.PrintStream;
+
+/**
+ * Calculate basic statistics about the reference sequence itself
+ *
+ * <p>These are very basic statistics: total number of bases and number of "regular" bases (i.e. A, C, T or G).</p>
+ *
+ * <h3>Input</h3>
+ * <p>
+ * A FASTA reference file.
+ * </p>
+ *
+ * <h3>Output</h3>
+ * <p>
+ * Base counts are written to file if an output file name is given (with -o), otherwise output to stdout.
+ * </p>
+ *
+ * <h3>Example</h3>
+ * <pre>
+ * java -Xmx2g -jar GenomeAnalysisTK.jar \
+ *   -T FastaStats \
+ *   -R ref.fasta \
+ *   [-o output.txt]
+ * </pre>
+ */
+ at DocumentedGATKFeature( groupName = HelpConstants.DOCS_CAT_QC, extraDocs = {CommandLineGATK.class} )
+public class FastaStats extends RefWalker<Byte, FastaStats.FastaStatistics> {
+    @Output PrintStream out;
+
+    protected class FastaStatistics {
+        long nBases = 0, nRegBases = 0;
+    }
+
+    @Override
+	public Byte map(RefMetaDataTracker rodData, ReferenceContext ref, AlignmentContext context) {
+        return ref.getBase();
+	}
+
+    @Override
+    public FastaStatistics reduceInit() {
+        return new FastaStatistics();
+    }
+
+    @Override
+	public FastaStatistics reduce(Byte base, FastaStatistics stats) {
+        stats.nBases++;
+        if (BaseUtils.isRegularBase(base)) stats.nRegBases++;
+        return stats;
+	}
+
+    @Override
+    public void onTraversalDone(FastaStatistics sum) {
+        out.printf("Total bases   %d%n", sum.nBases);
+        out.printf("Regular bases %d%n", sum.nRegBases);
+    }
+}
\ No newline at end of file
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/tools/walkers/filters/ClusteredSnps.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/tools/walkers/filters/ClusteredSnps.java
new file mode 100644
index 0000000..97bde83
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/tools/walkers/filters/ClusteredSnps.java
@@ -0,0 +1,81 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.tools.walkers.filters;
+
+import org.broadinstitute.gatk.utils.GenomeLoc;
+import org.broadinstitute.gatk.utils.GenomeLocParser;
+import org.broadinstitute.gatk.utils.exceptions.UserException;
+import org.broadinstitute.gatk.utils.variant.GATKVariantContextUtils;
+
+public class ClusteredSnps {
+    private GenomeLocParser genomeLocParser;
+    private int window = 10;
+    private int snpThreshold = 3;
+
+    public ClusteredSnps(GenomeLocParser genomeLocParser,int snpThreshold, int window) {
+        this.genomeLocParser = genomeLocParser;
+        this.window = window;
+        this.snpThreshold = snpThreshold;
+        if ( window < 1 || snpThreshold < 1 )
+            throw new IllegalArgumentException("Window and threshold values need to be positive values");
+    }
+
+    public boolean filter(FiltrationContextWindow contextWindow) {
+
+        FiltrationContext[] variants = contextWindow.getWindow(snpThreshold-1, snpThreshold-1);
+        for (int i = 0; i < snpThreshold; i++) {
+            // ignore positions at the beginning or end of the overall interval (where there aren't enough records)
+            if ( variants[i] == null || variants[i+snpThreshold-1] == null )
+                continue;
+
+            // note: the documentation tells users we'll blow up if ref calls are present.
+            //   if we ever get a windowed rod context that isn't a hack, we can actually allow this...
+            if ( !variants[i].getVariantContext().isVariant() )
+                throw new UserException.BadInput("The clustered SNPs filter does not work in the presence of non-variant records; see the documentation for more details");
+
+            // find the nth variant
+            GenomeLoc left = GATKVariantContextUtils.getLocation(genomeLocParser, variants[i].getVariantContext());
+            GenomeLoc right = null;
+            int snpsSeen = 1;
+
+            int currentIndex = i;
+            while ( ++currentIndex < variants.length ) {
+                if ( variants[currentIndex] != null && variants[currentIndex].getVariantContext() != null && variants[currentIndex].getVariantContext().isVariant() ) {
+                    if ( ++snpsSeen == snpThreshold ) {
+                        right = GATKVariantContextUtils.getLocation(genomeLocParser, variants[currentIndex].getVariantContext());
+                        break;
+                    }
+                }
+            }
+
+            if ( right != null &&
+                 left.getContigIndex() == right.getContigIndex() &&
+                 Math.abs(right.getStart() - left.getStart()) <= window )
+                return true;
+        }
+        return false;
+    }
+}
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/tools/walkers/filters/FiltrationContext.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/tools/walkers/filters/FiltrationContext.java
new file mode 100644
index 0000000..513763b
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/tools/walkers/filters/FiltrationContext.java
@@ -0,0 +1,47 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.tools.walkers.filters;
+
+import org.broadinstitute.gatk.engine.contexts.ReferenceContext;
+import htsjdk.variant.variantcontext.VariantContext;
+
+
+public class FiltrationContext {
+
+    private ReferenceContext ref;
+    private VariantContext vc;
+
+    public FiltrationContext(ReferenceContext ref, VariantContext vc) {
+        this.ref = ref;
+        this.vc = vc;
+    }
+
+    public ReferenceContext getReferenceContext() { return ref; }
+
+    public VariantContext getVariantContext() { return vc; }
+
+    public void setVariantContext(VariantContext newVC) { vc = newVC; }
+}
\ No newline at end of file
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/tools/walkers/filters/FiltrationContextWindow.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/tools/walkers/filters/FiltrationContextWindow.java
new file mode 100644
index 0000000..731b1a3
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/tools/walkers/filters/FiltrationContextWindow.java
@@ -0,0 +1,104 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.tools.walkers.filters;
+
+import org.broadinstitute.gatk.utils.exceptions.ReviewedGATKException;
+
+import java.util.LinkedList;
+import java.util.List;
+import java.util.ListIterator;
+
+/**
+ * A window of variants surrounding the current variant being investigated
+ *
+ * @author ebanks
+ * @version 0.1
+ */
+
+public class FiltrationContextWindow {
+
+    /**
+     * The variants.
+     */
+    private LinkedList<FiltrationContext> window = new LinkedList<FiltrationContext>();
+    private int currentContext;
+
+    /**
+     * Contructor for a variant context.
+     * @param firstVariants  the first set of variants, comprising the right half of the window
+     */
+    public FiltrationContextWindow(List<FiltrationContext> firstVariants) {
+        int windowSize = (firstVariants == null ? 1 : 2 * firstVariants.size() + 1);
+        currentContext = (firstVariants == null ? 0 : firstVariants.size());
+        window.addAll(firstVariants);
+        while ( window.size() < windowSize )
+            window.addFirst(null);
+    }
+
+    /**
+     * The context currently being examined.
+     * @return The current context.
+     */
+    public FiltrationContext getContext() {
+        return window.get(currentContext);
+    }
+
+    /**
+     * The maximum number of elements that can be requested on either end of the current context.
+     * @return max.
+     */
+    public int maxWindowElements() {
+        return currentContext;
+    }
+
+    /**
+     * The window around the context currently being examined.
+     * @param elementsToLeft number of earlier contexts to return ()
+     * @param elementsToRight number of later contexts to return   ()
+     * @return The current context window.
+     */
+    public FiltrationContext[] getWindow(int elementsToLeft, int elementsToRight) {
+        if ( elementsToLeft > maxWindowElements() || elementsToRight > maxWindowElements() )
+            throw new ReviewedGATKException("Too large a window requested");
+        if ( elementsToLeft < 0 || elementsToRight < 0 )
+            throw new ReviewedGATKException("Window size cannot be negative");
+
+        FiltrationContext[] array = new FiltrationContext[elementsToLeft + elementsToRight + 1];
+        ListIterator<FiltrationContext> iter = window.listIterator(currentContext - elementsToLeft);
+        for (int i = 0; i < elementsToLeft + elementsToRight + 1; i++)
+            array[i] = iter.next();
+        return array;
+    }
+
+    /**
+     * Move the window along to the next context
+     * @param context The new rightmost context
+     */
+    public void moveWindow(FiltrationContext context) {
+        window.removeFirst();
+        window.addLast(context);
+    }
+}
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/tools/walkers/filters/VariantFiltration.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/tools/walkers/filters/VariantFiltration.java
new file mode 100644
index 0000000..3988498
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/tools/walkers/filters/VariantFiltration.java
@@ -0,0 +1,400 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.tools.walkers.filters;
+
+import htsjdk.tribble.Feature;
+import org.broadinstitute.gatk.utils.commandline.*;
+import org.broadinstitute.gatk.engine.CommandLineGATK;
+import org.broadinstitute.gatk.engine.arguments.StandardVariantContextInputArgumentCollection;
+import org.broadinstitute.gatk.engine.contexts.AlignmentContext;
+import org.broadinstitute.gatk.engine.contexts.ReferenceContext;
+import org.broadinstitute.gatk.engine.refdata.RefMetaDataTracker;
+import org.broadinstitute.gatk.engine.walkers.Reference;
+import org.broadinstitute.gatk.engine.walkers.RodWalker;
+import org.broadinstitute.gatk.engine.walkers.Window;
+import org.broadinstitute.gatk.utils.GenomeLoc;
+import org.broadinstitute.gatk.utils.SampleUtils;
+import org.broadinstitute.gatk.utils.help.HelpConstants;
+import org.broadinstitute.gatk.utils.variant.GATKVCFUtils;
+import htsjdk.variant.vcf.*;
+import org.broadinstitute.gatk.utils.exceptions.UserException;
+import org.broadinstitute.gatk.utils.help.DocumentedGATKFeature;
+import htsjdk.variant.variantcontext.*;
+import htsjdk.variant.variantcontext.writer.VariantContextWriter;
+
+import java.util.*;
+
+
+/**
+ * Filters variant calls using a number of user-selectable, parameterizable criteria.
+ *
+ * <p>
+ * VariantFiltration is a GATK tool for hard-filtering variant calls based on certain criteria.
+ * Records are hard-filtered by changing the value in the FILTER field to something other than PASS.
+ *
+ * <h3>Input</h3>
+ * <p>
+ * A variant set to filter.
+ * </p>
+ *
+ * <h3>Output</h3>
+ * <p>
+ * A filtered VCF.
+ * </p>
+ *
+ * <h3>Examples</h3>
+ * <pre>
+ * java -Xmx2g -jar GenomeAnalysisTK.jar \
+ *   -R ref.fasta \
+ *   -T VariantFiltration \
+ *   -o output.vcf \
+ *   --variant input.vcf \
+ *   --filterExpression "AB < 0.2 || MQ0 > 50" \
+ *   --filterName "Nov09filters" \
+ *   --mask mask.vcf \
+ *   --maskName InDel
+ * </pre>
+ *
+ */
+ at DocumentedGATKFeature( groupName = HelpConstants.DOCS_CAT_VARMANIP, extraDocs = {CommandLineGATK.class} )
+ at Reference(window=@Window(start=-50,stop=50))
+public class VariantFiltration extends RodWalker<Integer, Integer> {
+
+    @ArgumentCollection
+    protected StandardVariantContextInputArgumentCollection variantCollection = new StandardVariantContextInputArgumentCollection();
+
+    /**
+     * Any variant which overlaps entries from the provided mask rod will be filtered. If the user wants logic to be reversed,
+     * i.e. filter variants that do not overlap with provided mask, then argument -filterNotInMask can be used.
+     * Note that it is up to the user to adapt the name of the mask to make it clear that the reverse logic was used
+     * (e.g. if masking against Hapmap, use -maskName=hapmap for the normal masking and -maskName=not_hapmap for the reverse masking).
+     */
+    @Input(fullName="mask", shortName="mask", doc="Input ROD mask", required=false)
+    public RodBinding<Feature> mask;
+
+    @Output(doc="File to which variants should be written")
+    protected VariantContextWriter writer = null;
+
+    /**
+     * VariantFiltration accepts any number of JEXL expressions (so you can have two named filters by using
+     * --filterName One --filterExpression "X < 1" --filterName Two --filterExpression "X > 2").
+     */
+    @Argument(fullName="filterExpression", shortName="filter", doc="One or more expression used with INFO fields to filter", required=false)
+    protected ArrayList<String> FILTER_EXPS = new ArrayList<String>();
+
+    /**
+     * This name is put in the FILTER field for variants that get filtered.  Note that there must be a 1-to-1 mapping between filter expressions and filter names.
+     */
+    @Argument(fullName="filterName", shortName="filterName", doc="Names to use for the list of filters", required=false)
+    protected ArrayList<String> FILTER_NAMES = new ArrayList<String>();
+
+    /**
+     * Similar to the INFO field based expressions, but used on the FORMAT (genotype) fields instead.
+     * VariantFiltration will add the sample-level FT tag to the FORMAT field of filtered samples (this does not affect the record's FILTER tag).
+     * One can filter normally based on most fields (e.g. "GQ < 5.0"), but the GT (genotype) field is an exception. We have put in convenience
+     * methods so that one can now filter out hets ("isHet == 1"), refs ("isHomRef == 1"), or homs ("isHomVar == 1"). Also available are
+     * expressions isCalled, isNoCall, isMixed, and isAvailable, in accordance with the methods of the Genotype object.
+     */
+    @Argument(fullName="genotypeFilterExpression", shortName="G_filter", doc="One or more expression used with FORMAT (sample/genotype-level) fields to filter (see documentation guide for more info)", required=false)
+    protected ArrayList<String> GENOTYPE_FILTER_EXPS = new ArrayList<String>();
+
+    /**
+     * Similar to the INFO field based expressions, but used on the FORMAT (genotype) fields instead.
+     */
+    @Argument(fullName="genotypeFilterName", shortName="G_filterName", doc="Names to use for the list of sample/genotype filters (must be a 1-to-1 mapping); this name is put in the FILTER field for variants that get filtered", required=false)
+    protected ArrayList<String> GENOTYPE_FILTER_NAMES = new ArrayList<String>();
+
+    /**
+     * Works together with the --clusterWindowSize argument.
+     */
+    @Argument(fullName="clusterSize", shortName="cluster", doc="The number of SNPs which make up a cluster", required=false)
+    protected Integer clusterSize = 3;
+
+    /**
+     * Works together with the --clusterSize argument.  To disable the clustered SNP filter, set this value to less than 1.
+     */
+    @Argument(fullName="clusterWindowSize", shortName="window", doc="The window size (in bases) in which to evaluate clustered SNPs", required=false)
+    protected Integer clusterWindow = 0;
+
+    @Argument(fullName="maskExtension", shortName="maskExtend", doc="How many bases beyond records from a provided 'mask' rod should variants be filtered", required=false)
+    protected Integer MASK_EXTEND = 0;
+
+    /**
+     * When using the -mask argument, the maskName will be annotated in the variant record.
+     * Note that when using the -filterNotInMask argument to reverse the masking logic,
+     * it is up to the user to adapt the name of the mask to make it clear that the reverse logic was used
+     * (e.g. if masking against Hapmap, use -maskName=hapmap for the normal masking and -maskName=not_hapmap for the reverse masking).
+     */
+    @Argument(fullName="maskName", shortName="maskName", doc="The text to put in the FILTER field if a 'mask' rod is provided and overlaps with a variant call", required=false)
+    protected String MASK_NAME = "Mask";
+
+    /**
+     * By default, if the -mask argument is used, any variant falling in a mask will be filtered.
+     * If this argument is used, logic is reversed, and variants falling outside a given mask will be filtered.
+     * Use case is, for example, if we have an interval list or BED file with "good" sites.
+     * Note that it is up to the user to adapt the name of the mask to make it clear that the reverse logic was used
+     * (e.g. if masking against Hapmap, use -maskName=hapmap for the normal masking and -maskName=not_hapmap for the reverse masking).
+     */
+    @Argument(fullName="filterNotInMask", shortName="filterNotInMask", doc="Filter records NOT in given input mask.", required=false)
+    protected boolean filterRecordsNotInMask = false;
+
+    /**
+     * By default, if JEXL cannot evaluate your expression for a particular record because one of the annotations is not present, the whole expression evaluates as PASSing.
+     * Use this argument to have it evaluate as failing filters instead for these cases.
+     */
+    @Argument(fullName="missingValuesInExpressionsShouldEvaluateAsFailing", doc="When evaluating the JEXL expressions, missing values should be considered failing the expression", required=false)
+    protected Boolean FAIL_MISSING_VALUES = false;
+
+    /**
+     * Invalidate previous filters applied to the VariantContext, applying only the filters here
+     */
+    @Argument(fullName="invalidatePreviousFilters",doc="Remove previous filters applied to the VCF",required=false)
+    boolean invalidatePrevious = false;
+
+    // JEXL expressions for the filters
+    List<VariantContextUtils.JexlVCMatchExp> filterExps;
+    List<VariantContextUtils.JexlVCMatchExp> genotypeFilterExps;
+
+    public static final String CLUSTERED_SNP_FILTER_NAME = "SnpCluster";
+    private ClusteredSnps clusteredSNPs = null;
+    private GenomeLoc previousMaskPosition = null;
+
+    // the structures necessary to initialize and maintain a windowed context
+    private FiltrationContextWindow variantContextWindow;
+    private static final int windowSize = 10;  // 10 variants on either end of the current one
+    private ArrayList<FiltrationContext> windowInitializer = new ArrayList<FiltrationContext>();
+
+    private void initializeVcfWriter() {
+
+        final List<String> inputNames = Arrays.asList(variantCollection.variants.getName());
+
+        // setup the header fields
+        Set<VCFHeaderLine> hInfo = new HashSet<VCFHeaderLine>();
+        hInfo.addAll(GATKVCFUtils.getHeaderFields(getToolkit(), inputNames));
+
+        if ( clusterWindow > 0 )
+            hInfo.add(new VCFFilterHeaderLine(CLUSTERED_SNP_FILTER_NAME, "SNPs found in clusters"));
+
+        if ( genotypeFilterExps.size() > 0 )
+            hInfo.add(VCFStandardHeaderLines.getFormatLine(VCFConstants.GENOTYPE_FILTER_KEY));
+
+        try {
+            for ( VariantContextUtils.JexlVCMatchExp exp : filterExps )
+                hInfo.add(new VCFFilterHeaderLine(exp.name, exp.exp.toString()));
+            for ( VariantContextUtils.JexlVCMatchExp exp : genotypeFilterExps )
+                hInfo.add(new VCFFilterHeaderLine(exp.name, exp.exp.toString()));
+
+            if ( mask.isBound() ) {
+                if (filterRecordsNotInMask)
+                    hInfo.add(new VCFFilterHeaderLine(MASK_NAME, "Doesn't overlap a user-input mask"));
+                else hInfo.add(new VCFFilterHeaderLine(MASK_NAME, "Overlaps a user-input mask"));
+            }
+        } catch (IllegalArgumentException e) {
+            throw new UserException.BadInput(e.getMessage());
+        }
+
+        writer.writeHeader(new VCFHeader(hInfo, SampleUtils.getUniqueSamplesFromRods(getToolkit(), inputNames)));
+    }
+
+    public void initialize() {
+        if ( clusterWindow > 0 )
+            clusteredSNPs = new ClusteredSnps(getToolkit().getGenomeLocParser(),clusterSize, clusterWindow);
+
+        if ( MASK_EXTEND < 0 )
+             throw new UserException.BadArgumentValue("maskExtension", "negative values are not allowed");
+
+        if (filterRecordsNotInMask && !mask.isBound())
+            throw new UserException.BadArgumentValue("filterNotInMask","argument not allowed if mask argument is not provided");
+        filterExps = VariantContextUtils.initializeMatchExps(FILTER_NAMES, FILTER_EXPS);
+        genotypeFilterExps = VariantContextUtils.initializeMatchExps(GENOTYPE_FILTER_NAMES, GENOTYPE_FILTER_EXPS);
+
+        VariantContextUtils.engine.get().setSilent(true);
+
+        initializeVcfWriter();
+    }
+
+    public Integer reduceInit() { return 0; }
+
+    /**
+     *
+     * @param tracker  the meta-data tracker
+     * @param ref      the reference base
+     * @param context  the context for the given locus
+     * @return 1 if the locus was successfully processed, 0 if otherwise
+     */
+    public Integer map(RefMetaDataTracker tracker, ReferenceContext ref, AlignmentContext context) {
+        if ( tracker == null )
+            return 0;
+
+        Collection<VariantContext> VCs = tracker.getValues(variantCollection.variants, context.getLocation());
+
+        // is there a SNP mask present?
+        boolean hasMask = (tracker.hasValues(mask) && !filterRecordsNotInMask) || (filterRecordsNotInMask && !tracker.hasValues(mask));
+        if ( hasMask )
+            previousMaskPosition = ref.getLocus();  // multi-base masks will get triggered over all bases of the mask
+
+        for ( VariantContext vc : VCs ) {
+
+            if ( invalidatePrevious ) {
+                vc = (new VariantContextBuilder(vc)).filters(new HashSet<String>()).make();
+            }
+            // filter based on previous mask position
+            if ( previousMaskPosition != null &&                                       // we saw a previous mask site
+                 previousMaskPosition.getContig().equals(vc.getChr()) &&               // it's on the same contig
+                 vc.getStart() - previousMaskPosition.getStop() <= MASK_EXTEND &&      // it's within the mask area (multi-base masks that overlap this site will always give a negative distance)
+                 (vc.getFilters() == null || !vc.getFilters().contains(MASK_NAME)) ) { // the filter hasn't already been applied
+                Set<String> filters = new LinkedHashSet<String>(vc.getFilters());
+                filters.add(MASK_NAME);
+                vc = new VariantContextBuilder(vc).filters(filters).make();
+            }
+
+            FiltrationContext varContext = new FiltrationContext(ref, vc);
+
+            // if we're still initializing the context, do so
+            if ( windowInitializer != null ) {
+
+                // if this is a mask position, filter previous records
+                if ( hasMask ) {
+                    for ( FiltrationContext prevVC : windowInitializer )
+                        prevVC.setVariantContext(checkMaskForPreviousLocation(prevVC.getVariantContext(), ref.getLocus()));
+                }
+
+                windowInitializer.add(varContext);
+                if ( windowInitializer.size() == windowSize ) {
+                    variantContextWindow = new FiltrationContextWindow(windowInitializer);
+                    windowInitializer = null;
+                }
+            } else {
+
+                // if this is a mask position, filter previous records
+                if ( hasMask ) {
+                    for ( FiltrationContext prevVC : variantContextWindow.getWindow(10, 10) ) {
+                        if ( prevVC != null )
+                            prevVC.setVariantContext(checkMaskForPreviousLocation(prevVC.getVariantContext(), ref.getLocus()));
+                    }
+                }
+
+                variantContextWindow.moveWindow(varContext);
+                filter();
+            }
+        }
+
+        return 1;
+    }
+
+    private VariantContext checkMaskForPreviousLocation(VariantContext vc, GenomeLoc maskLoc) {
+        if ( maskLoc.getContig().equals(vc.getChr()) &&               // it's on the same contig
+             maskLoc.getStart() - vc.getEnd() <= MASK_EXTEND &&       // it's within the mask area (multi-base VCs that overlap this site will always give a negative distance)
+             (vc.getFilters() == null || !vc.getFilters().contains(MASK_NAME)) ) { // the filter hasn't already been applied
+            Set<String> filters = new LinkedHashSet<String>(vc.getFilters());
+            filters.add(MASK_NAME);
+            vc = new VariantContextBuilder(vc).filters(filters).make();
+        }
+
+        return vc;
+    }
+
+    private void filter() {
+        // get the current context
+        FiltrationContext context = variantContextWindow.getContext();
+        if ( context == null )
+            return;
+
+        final VariantContext vc = context.getVariantContext();
+        final VariantContextBuilder builder = new VariantContextBuilder(vc);
+
+        // make new Genotypes based on filters
+        if ( genotypeFilterExps.size() > 0 ) {
+            GenotypesContext genotypes = GenotypesContext.create(vc.getGenotypes().size());
+
+            // for each genotype, check filters then create a new object
+            for ( final Genotype g : vc.getGenotypes() ) {
+                if ( g.isCalled() ) {
+                    final List<String> filters = new ArrayList<String>();
+                    if ( g.isFiltered() ) filters.add(g.getFilters());
+
+                    for ( VariantContextUtils.JexlVCMatchExp exp : genotypeFilterExps ) {
+                        if ( VariantContextUtils.match(vc, g, exp) )
+                            filters.add(exp.name);
+                    }
+
+                    genotypes.add(new GenotypeBuilder(g).filters(filters).make());
+                } else {
+                    genotypes.add(g);
+                }
+            }
+
+            builder.genotypes(genotypes);
+        }
+
+        // make a new variant context based on filters
+        Set<String> filters = new LinkedHashSet<String>(vc.getFilters());
+
+        // test for clustered SNPs if requested
+        if ( clusteredSNPs != null && clusteredSNPs.filter(variantContextWindow) )
+            filters.add(CLUSTERED_SNP_FILTER_NAME);
+
+        for ( VariantContextUtils.JexlVCMatchExp exp : filterExps ) {
+            try {
+                if ( VariantContextUtils.match(vc, exp) )
+                    filters.add(exp.name);
+            } catch (Exception e) {
+                // do nothing unless specifically asked to; it just means that the expression isn't defined for this context
+                if ( FAIL_MISSING_VALUES )
+                    filters.add(exp.name);                         
+            }
+        }
+
+        if ( filters.isEmpty() )
+            builder.passFilters();
+        else
+            builder.filters(filters);
+
+        writer.add(builder.make());
+    }
+
+    public Integer reduce(Integer value, Integer sum) {
+        return sum + value;
+    }
+
+    /**
+     * Tell the user the number of loci processed and close out the new variants file.
+     *
+     * @param result  the number of loci seen.
+     */
+    public void onTraversalDone(Integer result) {
+        // move the window over so that we can filter the last few variants
+        if ( windowInitializer != null ) {
+            while ( windowInitializer.size() < windowSize )
+                windowInitializer.add(null);
+            variantContextWindow = new FiltrationContextWindow(windowInitializer);
+        }
+        for (int i=0; i < windowSize; i++) {
+            variantContextWindow.moveWindow(null);
+            filter();
+        }
+    }
+}
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/tools/walkers/genotyper/AlleleList.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/tools/walkers/genotyper/AlleleList.java
new file mode 100644
index 0000000..3b0aded
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/tools/walkers/genotyper/AlleleList.java
@@ -0,0 +1,41 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.tools.walkers.genotyper;
+
+import htsjdk.variant.variantcontext.Allele;
+
+/**
+ * Created by valentin on 5/12/14.
+ */
+public interface AlleleList<A extends Allele> {
+
+    public int alleleCount();
+
+    public int alleleIndex(final A allele);
+
+    public A alleleAt(final int index);
+
+}
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/tools/walkers/genotyper/AlleleListPermutation.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/tools/walkers/genotyper/AlleleListPermutation.java
new file mode 100644
index 0000000..8d95fa4
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/tools/walkers/genotyper/AlleleListPermutation.java
@@ -0,0 +1,35 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.tools.walkers.genotyper;
+
+import htsjdk.variant.variantcontext.Allele;
+import org.broadinstitute.gatk.utils.collections.Permutation;
+
+/**
+ * Marks allele list permutation implementation classes.
+ */
+public interface AlleleListPermutation<A extends Allele> extends Permutation<A>, AlleleList<A> {
+}
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/tools/walkers/genotyper/AlleleListUtils.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/tools/walkers/genotyper/AlleleListUtils.java
new file mode 100644
index 0000000..4f40f51
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/tools/walkers/genotyper/AlleleListUtils.java
@@ -0,0 +1,334 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.tools.walkers.genotyper;
+
+import htsjdk.variant.variantcontext.Allele;
+
+import java.util.AbstractList;
+import java.util.List;
+
+/**
+ * Utils operations on {@link AlleleList} instances.
+ *
+ * @author Valentin Ruano-Rubio <valentin at broadinstitute.org>
+ */
+public class AlleleListUtils {
+
+    @SuppressWarnings("unchecked")
+    private static final AlleleList EMPTY_LIST = new AlleleList() {
+        @Override
+        public int alleleCount() {
+            return 0;
+        }
+
+        @Override
+        public int alleleIndex(final Allele allele) {
+            return -1;
+        }
+
+        @Override
+        public Allele alleleAt(final int index) {
+            throw new IllegalArgumentException("allele index is out of range");
+        }
+    };
+
+    /**
+     * Checks whether two allele lists are in fact the same.
+     * @param first one list to compare.
+     * @param second another list to compare.
+     *
+     * @throws IllegalArgumentException if if either list is {@code null}.
+     *
+     * @return {@code true} iff both list are equal.
+     */
+    public static <A extends Allele> boolean equals(final AlleleList<A> first, final AlleleList<A> second) {
+        if (first == null || second == null)
+            throw new IllegalArgumentException("no null list allowed");
+        final int alleleCount = first.alleleCount();
+        if (alleleCount != second.alleleCount())
+            return false;
+
+        for (int i = 0; i < alleleCount; i++) {
+            final A firstSample = first.alleleAt(i);
+            if (firstSample == null)
+                throw new IllegalStateException("no null samples allowed in sample-lists: first list at " + i);
+            final A secondSample = second.alleleAt(i);
+            if (secondSample == null)
+                throw new IllegalArgumentException("no null samples allowed in sample-list: second list at " + i);
+            if (!firstSample.equals(secondSample))
+                return false;
+        }
+
+        return true;
+    }
+
+    /**
+     * Resolves the index of the reference allele in an allele-list.
+     *
+     * <p>
+     *     If there is no reference allele, it returns -1. If there is more than one reference allele,
+     *     it returns the first occurrence (lowest index).
+     * </p>
+     *
+     * @param list the search allele-list.
+     * @param <A> allele component type.
+     *
+     * @throws IllegalArgumentException if {@code list} is {@code null}.
+     *
+     * @return -1 if there is no reference allele, or a values in [0,{@code list.alleleCount()}).
+     */
+    public static <A extends Allele> int indexOfReference(final AlleleList<A> list) {
+        if (list == null)
+            throw new IllegalArgumentException("the input list cannot be null");
+        final int alleleCount = list.alleleCount();
+        for (int i = 0; i < alleleCount; i++)
+            if (list.alleleAt(i).isReference())
+                return i;
+        return -1;
+    }
+
+
+    /**
+     * Returns a {@link java.util.List} unmodifiable view of a allele-list
+     * @param list the sample-list to wrap.
+     *
+     * @throws IllegalArgumentException if {@code list} is {@code null}.
+     *
+     * @return never {@code null}.
+     */
+    public static <A extends Allele> List<A> asList(final AlleleList<A> list) {
+        if (list == null)
+            throw new IllegalArgumentException("the list cannot be null");
+        return new AsList(list);
+    }
+
+    /**
+     * Returns an unmodifiable empty allele-list.
+     * @param <A> the allele class.
+     * @return never {@code null}.
+     */
+    @SuppressWarnings("unchecked")
+    public static final <A extends Allele> AlleleList<A> emptyList() {
+        return EMPTY_LIST;
+    }
+
+    /**
+     * Simple list view of a sample-list.
+     */
+    private static class AsList<A extends Allele> extends AbstractList<A> {
+
+        private final AlleleList<A> list;
+
+        private AsList(final AlleleList<A> list) {
+            this.list = list;
+
+        }
+
+        @Override
+        public A get(int index) {
+            return list.alleleAt(index);
+        }
+
+        @Override
+        public int size() {
+            return list.alleleCount();
+        }
+    }
+
+
+    /**
+     * Returns a permutation between two allele lists.
+     * @param original the original allele list.
+     * @param target the target allele list.
+     * @param <A> the allele type.
+     *
+     * @throws IllegalArgumentException if {@code original} or {@code target} is {@code null}, or
+     * elements in {@code target} is not contained in {@code original}
+     *
+     * @return never {@code null}
+     */
+    public static <A extends Allele> AlleleListPermutation<A> permutation(final AlleleList<A> original, final AlleleList<A> target) {
+        if (equals(original,target))
+            return new NonPermutation<>(original);
+        else
+            return new ActualPermutation<>(original,target);
+    }
+
+    private static class NonPermutation<A extends Allele> implements AlleleListPermutation<A> {
+
+        private final AlleleList<A> list;
+
+        public NonPermutation(final AlleleList<A> original) {
+            list = original;
+        }
+
+        @Override
+        public boolean isPartial() {
+            return false;
+        }
+
+        @Override
+        public boolean isNonPermuted() {
+            return true;
+        }
+
+        @Override
+        public int toIndex(int fromIndex) {
+            return fromIndex;
+        }
+
+        @Override
+        public int fromIndex(int toIndex) {
+            return toIndex;
+        }
+
+        @Override
+        public int fromSize() {
+            return list.alleleCount();
+        }
+
+        @Override
+        public int toSize() {
+            return list.alleleCount();
+        }
+
+        @Override
+        public List<A> fromList() {
+            return asList(list);
+        }
+
+        @Override
+        public java.util.List<A> toList() {
+            return asList(list);
+        }
+
+
+        @Override
+        public int alleleCount() {
+            return list.alleleCount();
+        }
+
+        @Override
+        public int alleleIndex(final A allele) {
+            return list.alleleIndex(allele);
+        }
+
+        @Override
+        public A alleleAt(final int index) {
+            return list.alleleAt(index);
+        }
+    }
+
+    private static class ActualPermutation<A extends Allele> implements AlleleListPermutation<A> {
+
+        private final AlleleList<A> from;
+
+        private final AlleleList<A> to;
+
+        private final int[] fromIndex;
+
+        private final boolean nonPermuted;
+
+        private final boolean isPartial;
+
+        private ActualPermutation(final AlleleList<A> original, final AlleleList<A> target) {
+            this.from = original;
+            this.to = target;
+            final int toSize = target.alleleCount();
+            final int fromSize = original.alleleCount();
+            if (fromSize < toSize)
+                throw new IllegalArgumentException("target allele list is not a permutation of the original allele list");
+
+            fromIndex = new int[toSize];
+            boolean nonPermuted = fromSize == toSize;
+            this.isPartial = !nonPermuted;
+            for (int i = 0; i < toSize; i++) {
+                final int originalIndex = original.alleleIndex(target.alleleAt(i));
+                if (originalIndex < 0)
+                    throw new IllegalArgumentException("target allele list is not a permutation of the original allele list");
+                fromIndex[i] = originalIndex;
+                nonPermuted &= originalIndex == i;
+            }
+
+            this.nonPermuted = nonPermuted;
+        }
+
+        @Override
+        public boolean isPartial() {
+            return isPartial;
+        }
+
+        @Override
+        public boolean isNonPermuted() {
+            return nonPermuted;
+        }
+
+        @Override
+        public int toIndex(int fromIndex) {
+            return to.alleleIndex(from.alleleAt(fromIndex));
+        }
+
+        @Override
+        public int fromIndex(int toIndex) {
+            return fromIndex[toIndex];
+        }
+
+        @Override
+        public int fromSize() {
+            return from.alleleCount();
+        }
+
+        @Override
+        public int toSize() {
+            return to.alleleCount();
+        }
+
+        @Override
+        public List<A> fromList() {
+            return asList(from);
+        }
+
+        @Override
+        public List<A> toList() {
+            return asList(to);
+        }
+
+        @Override
+        public int alleleCount() {
+            return to.alleleCount();
+        }
+
+        @Override
+        public int alleleIndex(final A allele) {
+            return to.alleleIndex(allele);
+        }
+
+        @Override
+        public A alleleAt(final int index) {
+            return to.alleleAt(index);
+        }
+    }
+}
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/tools/walkers/genotyper/IndexedAlleleList.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/tools/walkers/genotyper/IndexedAlleleList.java
new file mode 100644
index 0000000..9238af7
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/tools/walkers/genotyper/IndexedAlleleList.java
@@ -0,0 +1,95 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.tools.walkers.genotyper;
+
+import htsjdk.variant.variantcontext.Allele;
+import org.broadinstitute.gatk.utils.collections.IndexedSet;
+
+import java.util.Collection;
+
+/**
+ * Allele list implementation using and indexed-set.
+ *
+ * @author Valentin Ruano-Rubio <valentin at broadinstitute.org>
+ */
+public class IndexedAlleleList<A extends Allele> implements AlleleList<A> {
+
+    private final IndexedSet<A> alleles;
+
+    /**
+     * Constructs a new empty allele-list
+     */
+    public IndexedAlleleList() {
+        alleles = new IndexedSet<>();
+    }
+
+    /**
+     * Constructs a new allele-list from an array of alleles.
+     *
+     * <p>
+     *     Repeats in the input array will be ignored (keeping the first one). The order of alleles in the
+     *     resulting list is the same as in the natural traversal of the input collection.
+     *
+     * </p>
+     * @param alleles the original allele array
+     *
+     * @throws java.lang.IllegalArgumentException if {@code alleles} is {@code null} or contains {@code null}s.
+     */
+    public IndexedAlleleList(final A ... alleles) {
+        this.alleles = new IndexedSet<>(alleles);
+    }
+
+    /**
+     * Constructs a new allele-list from a collection of alleles.
+     *
+     * <p>
+     *     Repeats in the input collection will be ignored (keeping the first one). The order of alleles in the
+     *     resulting list is the same as in the natural traversal of the input collection.
+     *
+     * </p>
+     * @param alleles the original allele collection
+     *
+     * @throws java.lang.IllegalArgumentException if {@code alleles} is {@code null} or contains {@code null}s.
+     */
+    public IndexedAlleleList(final Collection<A> alleles) {
+        this.alleles = new IndexedSet<>(alleles);
+    }
+
+    @Override
+    public int alleleCount() {
+        return alleles.size();
+    }
+
+    @Override
+    public int alleleIndex(final A allele) {
+        return alleles.indexOf(allele);
+    }
+
+    @Override
+    public A alleleAt(final int index) {
+        return alleles.get(index);
+    }
+}
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/tools/walkers/genotyper/IndexedSampleList.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/tools/walkers/genotyper/IndexedSampleList.java
new file mode 100644
index 0000000..94022c8
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/tools/walkers/genotyper/IndexedSampleList.java
@@ -0,0 +1,96 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.tools.walkers.genotyper;
+
+import org.broadinstitute.gatk.utils.collections.IndexedSet;
+
+import java.util.Collection;
+
+/**
+ * Simple implementation of a sample-list using and indexed-set.
+ *
+ * @author Valentin Ruano-Rubio <valentin at broadinstitute.org>
+ */
+public class IndexedSampleList implements SampleList {
+
+    private final IndexedSet<String> samples;
+
+    /**
+     * Constructs an empty sample-list.
+     */
+    public IndexedSampleList() {
+        samples = new IndexedSet<>(0);
+    }
+
+    /**
+     * Constructs a sample-list from a collection of samples.
+     *
+     * <p>
+     *     Repeats in the input collection are ignored (just the first occurrence is kept).
+     *     Sample names will be sorted based on the traversal order
+     *     of the original collection.
+     * </p>
+     *
+     * @param samples input sample collection.
+     *
+     * @throws IllegalArgumentException if {@code samples} is {@code null} or it contains {@code nulls}.
+     */
+    public IndexedSampleList(final Collection<String> samples) {
+        this.samples = new IndexedSet<>(samples);
+    }
+
+    /**
+     * Constructs a sample-list from an array of samples.
+     *
+     * <p>
+     *     Repeats in the input array are ignored (just the first occurrence is kept).
+     *     Sample names will be sorted based on the traversal order
+     *     of the original array.
+     * </p>
+     *
+     * @param samples input sample array.
+     *
+     * @throws IllegalArgumentException if {@code samples} is {@code null} or it contains {@code nulls}.
+     */
+    public IndexedSampleList(final String ... samples) {
+        this.samples = new IndexedSet<>(samples);
+    }
+
+    @Override
+    public int sampleCount() {
+        return samples.size();
+    }
+
+    @Override
+    public int sampleIndex(final String sample) {
+        return samples.indexOf(sample);
+    }
+
+    @Override
+    public String sampleAt(int sampleIndex) {
+        return samples.get(sampleIndex);
+    }
+}
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/tools/walkers/genotyper/SampleList.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/tools/walkers/genotyper/SampleList.java
new file mode 100644
index 0000000..29cb428
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/tools/walkers/genotyper/SampleList.java
@@ -0,0 +1,42 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.tools.walkers.genotyper;
+
+/**
+ * A indexed set of samples.
+ *
+ * <p>
+ *     Implementing classes must guarantee that the sample list will remain <b>constant</b> through the life of the object.
+ * </p>
+ */
+public interface SampleList  {
+
+    public int sampleCount();
+
+    public int sampleIndex(final String sample);
+
+    public String sampleAt(final int sampleIndex);
+}
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/tools/walkers/genotyper/SampleListUtils.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/tools/walkers/genotyper/SampleListUtils.java
new file mode 100644
index 0000000..2071f5d
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/tools/walkers/genotyper/SampleListUtils.java
@@ -0,0 +1,224 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.tools.walkers.genotyper;
+
+import java.util.*;
+
+/**
+ * Some utility operations on sample lists.
+ *
+ * @author Valentin Ruano-Rubio <valentin at broadinstitute.org>
+ */
+public class SampleListUtils {
+
+    private static final SampleList EMPTY_LIST = new SampleList() {
+
+        @Override
+        public int sampleCount() {
+            return 0;
+        }
+
+        @Override
+        public int sampleIndex(String sample) {
+            return -1;
+        }
+
+        @Override
+        public String sampleAt(final int sampleIndex) {
+            throw new IllegalArgumentException("index is out of valid range");
+        }
+    };
+
+    /**
+     * Empty list.
+     *
+     * @return never {@code null}
+     */
+    public static SampleList emptyList() {
+        return EMPTY_LIST;
+    }
+
+    /**
+     * Checks whether two sample lists are in fact the same.
+     * @param first one list to compare.
+     * @param second another list to compare.
+     *
+     * @throws IllegalArgumentException if if either list is {@code null}.
+     *
+     * @return {@code true} iff both list are equal.
+     */
+    public static boolean equals(final SampleList first, final SampleList second) {
+        if (first == null || second == null)
+            throw new IllegalArgumentException("no null list allowed");
+        final int sampleCount = first.sampleCount();
+        if (sampleCount != second.sampleCount())
+            return false;
+
+        for (int i = 0; i < sampleCount; i++) {
+            final String firstSample = first.sampleAt(i);
+            if (firstSample == null)
+                throw new IllegalStateException("no null samples allowed in sample-lists: first list at " + i);
+            final String secondSample = second.sampleAt(i);
+            if (secondSample == null)
+                throw new IllegalArgumentException("no null samples allowed in sample-list: second list at " + i);
+            if (!firstSample.equals(secondSample))
+                return false;
+        }
+        return true;
+    }
+
+    /**
+     * Returns a {@link List} unmodifiable view of a sample-list
+     * @param list the sample-list to wrap.
+     *
+     * @throws IllegalArgumentException if {@code list} is {@code null}.
+     *
+     * @return never {@code null}.
+     */
+    public static List<String> asList(final SampleList list) {
+        if (list == null)
+            throw new IllegalArgumentException("the list cannot be null");
+        return new AsList(list);
+    }
+
+    /**
+     * Returns a {@link Set} unmodifiable view of the sample-list
+     *
+     * @param list the sample-list to wrap.
+     *
+     * @throws IllegalArgumentException if {@code list} is {@code null}
+     */
+    public static Set<String> asSet(final SampleList list) {
+        if (list == null)
+            throw new IllegalArgumentException("the list cannot be null");
+        return new AsSet(list);
+    }
+
+    /**
+     * Creates a list with a single sample.
+     *
+     * @param sampleName the sample name.
+     * @return never {@code sampleName}
+     */
+    public static SampleList singletonList(final String sampleName) {
+        if (sampleName == null)
+            throw new IllegalArgumentException("the sample name cannot be null");
+        return new SampleList() {
+
+            @Override
+            public int sampleCount() {
+                return 1;
+            }
+
+            @Override
+            public int sampleIndex(final String sample) {
+                return sampleName.equals(sample) ? 0 : -1;
+            }
+
+            @Override
+            public String sampleAt(int sampleIndex) {
+                if (sampleIndex == 0)
+                    return sampleName;
+                throw new IllegalArgumentException("index is out of bounds");
+            }
+        };
+    }
+
+    /**
+     * Simple list view of a sample-list.
+     */
+    private static class AsList extends AbstractList<String> {
+
+        private final SampleList list;
+
+        private AsList(final SampleList list) {
+            this.list = list;
+
+        }
+
+        @Override
+        public String get(int index) {
+            return list.sampleAt(index);
+        }
+
+        @Override
+        public int size() {
+            return list.sampleCount();
+        }
+    }
+
+    /**
+     * Simple set view of a sample-list
+     */
+    private static class AsSet extends AbstractSet<String> {
+
+        private final SampleList list;
+
+        private AsSet(final SampleList list) {
+            this.list = list;
+
+        }
+
+        @Override
+        public Iterator<String> iterator() {
+            return new Iterator<String>() {
+                private int index = 0;
+
+                @Override
+                public boolean hasNext() {
+                    return index < list.sampleCount();
+                }
+
+                @Override
+                public String next() {
+                    if (index >= list.sampleCount())
+                        throw new NoSuchElementException("iterating beyond sample list end");
+                    return list.sampleAt(index++);
+                }
+
+                @Override
+                public void remove() {
+                    throw new UnsupportedOperationException("unsupported operation exception");
+                }
+            };
+        }
+
+        @Override
+        public int size() {
+            return list.sampleCount();
+        }
+
+        @Override
+        public boolean contains(final Object obj) {
+            if (obj == null)
+                return false;
+            else if (obj instanceof String)
+                return list.sampleIndex(((String)obj)) >= 0;
+            else
+                return false;
+        }
+    }
+}
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/tools/walkers/haplotypecaller/HCMappingQualityFilter.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/tools/walkers/haplotypecaller/HCMappingQualityFilter.java
new file mode 100644
index 0000000..ce6fe06
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/tools/walkers/haplotypecaller/HCMappingQualityFilter.java
@@ -0,0 +1,54 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.tools.walkers.haplotypecaller;
+
+import htsjdk.samtools.SAMRecord;
+import org.apache.log4j.Logger;
+import org.broadinstitute.gatk.utils.commandline.Argument;
+import org.broadinstitute.gatk.engine.GenomeAnalysisEngine;
+import org.broadinstitute.gatk.engine.filters.ReadFilter;
+
+/**
+ * Filter out reads with low mapping qualities.
+ *
+ * @author mdepristo
+ */
+public class HCMappingQualityFilter extends ReadFilter {
+    private final static Logger logger = Logger.getLogger(HCMappingQualityFilter.class);
+
+    @Argument(fullName = "min_mapping_quality_score", shortName = "mmq", doc = "Minimum read mapping quality required to consider a read for analysis with the HaplotypeCaller", required = false)
+    public int MIN_MAPPING_QUALTY_SCORE = 20;
+
+    @Override
+    public void initialize(GenomeAnalysisEngine engine) {
+        if ( MIN_MAPPING_QUALTY_SCORE > 0 )
+            logger.info("Filtering out reads with MAPQ < " + MIN_MAPPING_QUALTY_SCORE);
+    }
+
+    public boolean filterOut(SAMRecord rec) {
+        return (rec.getMappingQuality() < MIN_MAPPING_QUALTY_SCORE);
+    }
+}
\ No newline at end of file
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/tools/walkers/package-info.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/tools/walkers/package-info.java
new file mode 100644
index 0000000..4201ef0
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/tools/walkers/package-info.java
@@ -0,0 +1,26 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.tools.walkers;
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/tools/walkers/qc/CheckPileup.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/tools/walkers/qc/CheckPileup.java
new file mode 100644
index 0000000..a3848dc
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/tools/walkers/qc/CheckPileup.java
@@ -0,0 +1,258 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.tools.walkers.qc;
+
+import org.broadinstitute.gatk.utils.commandline.Argument;
+import org.broadinstitute.gatk.utils.commandline.Input;
+import org.broadinstitute.gatk.utils.commandline.Output;
+import org.broadinstitute.gatk.utils.commandline.RodBinding;
+import org.broadinstitute.gatk.engine.CommandLineGATK;
+import org.broadinstitute.gatk.engine.contexts.AlignmentContext;
+import org.broadinstitute.gatk.engine.contexts.ReferenceContext;
+import org.broadinstitute.gatk.engine.refdata.RefMetaDataTracker;
+import org.broadinstitute.gatk.engine.walkers.DataSource;
+import org.broadinstitute.gatk.engine.walkers.LocusWalker;
+import org.broadinstitute.gatk.engine.walkers.Requires;
+import org.broadinstitute.gatk.engine.walkers.TreeReducible;
+import org.broadinstitute.gatk.utils.GenomeLoc;
+import org.broadinstitute.gatk.utils.codecs.sampileup.SAMPileupFeature;
+import org.broadinstitute.gatk.utils.exceptions.ReviewedGATKException;
+import org.broadinstitute.gatk.utils.exceptions.UserException;
+import org.broadinstitute.gatk.utils.help.DocumentedGATKFeature;
+import org.broadinstitute.gatk.utils.help.HelpConstants;
+import org.broadinstitute.gatk.utils.pileup.ReadBackedPileup;
+
+import java.io.PrintStream;
+import java.util.Arrays;
+
+/**
+ * Compare GATK's internal pileup to a reference Samtools pileup
+ *
+ * <p>At every locus in the input set, compares the pileup data (reference base, aligned base from
+ * each overlapping read, and quality score) generated internally by GATK to a reference pileup data generated
+ * by Samtools. Note that the pileup program has been replaced in Samtools by mpileup, which produces a slightly
+ * different output format by default.
+ * </p>
+ *
+ * <h3>Format</h3>
+ * <p>There are two versions of the original pileup format: the current 6-column format produced by Samtools, and the old
+ * 10-column "consensus" format which could be obtained by using the -c argument, now deprecated.</p>
+ * <h4>Simple pileup: 6-column format</h4>
+ * <p>
+ *     Each line consists of chromosome, 1-based coordinate, reference base, the
+ *     number of reads covering the site, read bases and base qualities. At the
+ *     read base column, a dot stands for a match to the reference base on the
+ *     forward strand, a comma for a match on the reverse strand, `ACGTN' for a mismatch
+ *     on the forward strand and `acgtn' for a mismatch on the reverse strand.
+ *     A pattern `\+[0-9]+[ACGTNacgtn]+' indicates there is an insertion between
+ *     this reference position and the next reference position. The length of the
+ *     insertion is given by the integer in the pattern, followed by the inserted sequence.
+ * </p>
+ * <pre>
+ *     seq1 272 T 24  ,.$.....,,.,.,...,,,.,..^+. <<<+;<<<<<<<<<<<=<;<;7<&
+ *     seq1 273 T 23  ,.....,,.,.,...,,,.,..A <<<;<<<<<<<<<3<=<<<;<<+
+ *     seq1 274 T 23  ,.$....,,.,.,...,,,.,...    7<7;<;<<<<<<<<<=<;<;<<6
+ *     seq1 275 A 23  ,$....,,.,.,...,,,.,...^l.  <+;9*<<<<<<<<<=<<:;<<<<
+ *     seq1 276 G 22  ...T,,.,.,...,,,.,....  33;+<<7=7<<7<&<<1;<<6<
+ *     seq1 277 T 22  ....,,.,.,.C.,,,.,..G.  +7<;<<<<<<<&<=<<:;<<&<
+ *     seq1 278 G 23  ....,,.,.,...,,,.,....^k.   %38*<<;<7<<7<=<<<;<<<<<
+ *     seq1 279 C 23  A..T,,.,.,...,,,.,..... ;75&<<<<<<<<<=<<<9<<:<<
+ * </pre>
+ * <p>
+ *     See the <a href="http://samtools.sourceforge.net/pileup.shtml">Pileup format documentation</a> for more details.
+ * </p>
+ *
+ * <h4>Consensus pileup: 10/13-column format</h4>
+ * <p>The "consensus" or extended pileup consists of the following:
+ *  <ul>
+ *      <li>original 6 columns as described above</li>
+ *      <li>4 extra columns representing consensus values (consensus base, consensus quality, variant quality and maximum mapping quality of the
+ * reads covering the sites) for all sites, inserted before the bases and quality strings</li>
+ *      <li>3 extra columns indicating counts of reads supporting indels (just for indel sites)</li>
+ *  </ul>
+ * </p>
+ * <h4>Example of consensus pileup for SNP or non-variant sites</h4>
+ * <pre>
+ *     seq1  60  T  T  66  0  99  13  ...........^~.^~.   9<<55<;<<<<<<
+ *     seq1  61  G  G  72  0  99  15  .............^~.^y. (;975&;<<<<<<<<
+ *     seq1  62  T  T  72  0  99  15  .$..............    <;;,55;<<<<<<<<
+ *     seq1  63  G  G  72  0  99  15  .$.............^~.  4;2;<7:+<<<<<<<
+ *     seq1  64  G  G  69  0  99  14  ..............  9+5<;;;<<<<<<<
+ *     seq1  65  A  A  69  0  99  14  .$............. <5-2<;;<<<<<<;
+ *     seq1  66  C  C  66  0  99  13  .............   &*<;;<<<<<<8<
+ *     seq1  67  C  C  69  0  99  14  .............^~.    ,75<.4<<<<<-<<
+ *     seq1  68  C  C  69  0  99  14  ..............  576<;7<<<<<8<< *
+ * </pre>
+ *
+ * <h4>Example of consensus pileup for indels</h4>
+ * <pre>
+ *     Escherichia_coli_K12	3995037	*	*\/*	430	0	37	144	*	+A	143	1	0
+ *     Escherichia_coli_K12	3995279	*	*\/*	202	0	36	68	*	+A	67	1	0
+ *     Escherichia_coli_K12	3995281	*	*\/*	239	0	36	67	*	-CG	66	1	0
+ * </pre>
+ * <p>
+ *     See <a href="http://samtools.sourceforge.net/cns0.shtml/">Consensus pileup format (deprecated)</a> for more details.
+ * </p>
+ *
+ * <h3>Input</h3>
+ * <p>A BAM file conatining your aligned sequence data and a pileup file generated by Samtools covering the region you
+ * want to examine.</p>
+ *
+ * <h3>Output</h3>
+ * <p>A text file listing mismatches between the input pileup and the GATK's internal pileup. If there are no mismatches, the output file is empty.</p>
+ *
+ * <h3>Example</h3>
+ * <pre>
+ * java -jar GenomeAnalysisTK.jar \
+ *   -T CheckPileup \
+ *   -R ref.fasta \
+ *   -I your_data.bam \
+ *   --pileup:SAMPileup pileup_file.txt \
+ *   -L chr1:257-275 \
+ *   -o output_file_name
+ * </pre>
+ */
+ at DocumentedGATKFeature( groupName = HelpConstants.DOCS_CAT_QC, extraDocs = {CommandLineGATK.class} )
+ at Requires(value={DataSource.READS,DataSource.REFERENCE})
+public class CheckPileup extends LocusWalker<Integer, CheckPileupStats> implements TreeReducible<CheckPileupStats> {
+    /**
+     * This is the existing pileup against which we'll compare GATK's internal pileup at each genome position in the desired interval.
+     */
+    @Input(fullName = "pileup", shortName = "pileup", doc="Pileup generated by Samtools", required = true)
+    RodBinding<SAMPileupFeature> pileup;
+
+    @Output
+    private PrintStream out;
+    /**
+     * By default the program will quit if it encounters an error (such as missing truth data for a given position).
+     * Use this flag to override the default behavior; the program will then simply print an error message and move on
+     * to the next position.
+     */
+    @Argument(fullName="continue_after_error",doc="Continue after encountering an error",required=false)
+    public boolean CONTINUE_AFTER_AN_ERROR = false;
+
+    public Integer map(RefMetaDataTracker tracker, ReferenceContext ref, AlignmentContext context) {
+        ReadBackedPileup pileup = context.getBasePileup();
+        SAMPileupFeature truePileup = getTruePileup( tracker );
+
+        if ( truePileup == null ) {
+            out.printf("No truth pileup data available at %s%n", pileup.getPileupString(ref.getBaseAsChar()));
+            if ( ! CONTINUE_AFTER_AN_ERROR ) {
+                throw new UserException.BadInput(String.format("No pileup data available at %s given GATK's output of %s -- this walker requires samtools pileup data over all bases",
+                        context.getLocation(), new String(pileup.getBases())));
+            }
+        } else {
+            String pileupDiff = pileupDiff(pileup, truePileup, true);
+            if ( pileupDiff != null ) {
+                out.printf("%s vs. %s%n", pileup.getPileupString(ref.getBaseAsChar()), truePileup.getPileupString());
+                if ( ! CONTINUE_AFTER_AN_ERROR ) {
+                    throw new UserException.BadInput(String.format("The input pileup doesn't match the GATK's internal pileup: %s", pileupDiff));
+                }
+            }
+        }
+
+        return pileup.getNumberOfElements();
+    }
+
+    private static String maybeSorted( final String x, boolean sortMe )
+    {
+        if ( sortMe ) {
+            byte[] bytes = x.getBytes();
+            Arrays.sort(bytes);
+            return new String(bytes);
+        }
+        else
+            return x;
+    }
+
+    public String pileupDiff(final ReadBackedPileup a, final SAMPileupFeature b, boolean orderDependent)
+    {
+        if ( a.getNumberOfElements() != b.size() )
+            return "Sizes not equal";
+        GenomeLoc featureLocation = getToolkit().getGenomeLocParser().createGenomeLoc(b.getChr(),b.getStart(),b.getEnd());
+        if ( a.getLocation().compareTo(featureLocation) != 0 )
+            return "Locations not equal";
+
+        String aBases = maybeSorted(new String(a.getBases()), ! orderDependent );
+        String bBases = maybeSorted(b.getBasesAsString(), ! orderDependent );
+        if ( ! aBases.toUpperCase().equals(bBases.toUpperCase()) )
+            return "Bases not equal";
+
+        String aQuals = maybeSorted(new String(a.getQuals()), ! orderDependent );
+        String bQuals = maybeSorted(new String(b.getQuals()), ! orderDependent );
+        if ( ! aQuals.equals(bQuals) )
+            return "Quals not equal";
+
+        return null;
+    }
+
+    // Given result of map function
+    public CheckPileupStats reduceInit() { return new CheckPileupStats(); }
+    public CheckPileupStats reduce(Integer value, CheckPileupStats sum) {
+        sum.nLoci++;
+        sum.nBases += value;
+        return sum;
+    }
+
+    public CheckPileupStats treeReduce( CheckPileupStats lhs, CheckPileupStats rhs ) {
+        CheckPileupStats combined = new CheckPileupStats();
+        combined.nLoci = lhs.nLoci + rhs.nLoci;
+        combined.nBases = lhs.nBases + rhs.nBases;
+        return combined;
+    }
+
+    /**
+     * Extracts the true pileup data from the given rodSAMPileup.  Note that this implementation
+     * assumes that the genotype will only be point or indel.
+     * @param tracker ROD tracker from which to extract pileup data.
+     * @return True pileup data.
+     */
+    private SAMPileupFeature getTruePileup( RefMetaDataTracker tracker ) {
+        SAMPileupFeature pileupArg = tracker.getFirstValue(pileup);
+
+        if( pileupArg == null)
+            return null;
+
+        if( pileupArg.hasPointGenotype() )
+            return pileupArg.getPointGenotype();
+        else if( pileupArg.hasIndelGenotype() )
+            return pileupArg.getIndelGenotype();
+        else
+            throw new ReviewedGATKException("Unsupported pileup type: " + pileupArg);
+    }
+}
+
+class CheckPileupStats {
+    public long nLoci = 0;
+    public long nBases = 0;
+
+    public CheckPileupStats() {
+    }
+
+    public String toString() {
+        return String.format("Validated %d sites covered by %d bases%n", nLoci, nBases);
+    }
+}
\ No newline at end of file
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/tools/walkers/qc/CountBases.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/tools/walkers/qc/CountBases.java
new file mode 100644
index 0000000..1500ce3
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/tools/walkers/qc/CountBases.java
@@ -0,0 +1,74 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.tools.walkers.qc;
+
+import org.broadinstitute.gatk.engine.CommandLineGATK;
+import org.broadinstitute.gatk.engine.contexts.ReferenceContext;
+import org.broadinstitute.gatk.engine.refdata.RefMetaDataTracker;
+import org.broadinstitute.gatk.engine.walkers.DataSource;
+import org.broadinstitute.gatk.engine.walkers.ReadWalker;
+import org.broadinstitute.gatk.engine.walkers.Requires;
+import org.broadinstitute.gatk.utils.help.DocumentedGATKFeature;
+import org.broadinstitute.gatk.utils.help.HelpConstants;
+import org.broadinstitute.gatk.utils.sam.GATKSAMRecord;
+
+/**
+ * Walks over the input data set, calculating the number of bases seen for diagnostic purposes.
+ *
+ * <h3>Input</h3>
+ * <p>
+ * One or more BAM files.
+ * </p>
+ *
+ * <h3>Output</h3>
+ * <p>
+ * Number of bases seen.
+ * </p>
+ *
+ * <h3>Examples</h3>
+ * <pre>
+ * java -Xmx2g -jar GenomeAnalysisTK.jar \
+ *   -R ref.fasta \
+ *   -T CountBases \
+ *   -I input.bam \
+ *   [-L input.intervals]
+ * </pre>
+ *
+ */
+ at DocumentedGATKFeature( groupName = HelpConstants.DOCS_CAT_QC, extraDocs = {CommandLineGATK.class} )
+ at Requires({DataSource.READS, DataSource.REFERENCE})
+public class CountBases extends ReadWalker<Integer, Long> {
+    public Integer map(ReferenceContext ref, GATKSAMRecord read, RefMetaDataTracker tracker) {
+
+        return read.getReadLength();
+    }
+
+    public Long reduceInit() { return 0L; }
+
+    public Long reduce(Integer value, Long sum) {
+        return (long) value + sum;
+    }
+}
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/tools/walkers/qc/CountIntervals.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/tools/walkers/qc/CountIntervals.java
new file mode 100644
index 0000000..221c4a9
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/tools/walkers/qc/CountIntervals.java
@@ -0,0 +1,128 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.tools.walkers.qc;
+
+import htsjdk.tribble.Feature;
+import org.broadinstitute.gatk.utils.commandline.Argument;
+import org.broadinstitute.gatk.utils.commandline.Input;
+import org.broadinstitute.gatk.utils.commandline.Output;
+import org.broadinstitute.gatk.utils.commandline.RodBinding;
+import org.broadinstitute.gatk.engine.CommandLineGATK;
+import org.broadinstitute.gatk.engine.contexts.AlignmentContext;
+import org.broadinstitute.gatk.engine.contexts.ReferenceContext;
+import org.broadinstitute.gatk.engine.refdata.RefMetaDataTracker;
+import org.broadinstitute.gatk.engine.walkers.RefWalker;
+import org.broadinstitute.gatk.utils.GenomeLoc;
+import org.broadinstitute.gatk.utils.collections.Pair;
+import org.broadinstitute.gatk.utils.help.DocumentedGATKFeature;
+import org.broadinstitute.gatk.utils.help.HelpConstants;
+
+import java.io.PrintStream;
+import java.util.Collections;
+import java.util.List;
+
+/**
+ * Count contiguous regions in an interval list.
+ *
+ * <p>When the GATK reads in intervals from an intervals list, any intervals that overlap each other get merged into
+ * a single interval spanning the original ones. For example, if you have the following intervals:
+ * <ul><li>
+ *     20:1-2000
+ * </li><li>
+ *     20:1500-3000
+ * </li></ul>
+ * They will be merged into a single interval:
+ * <ul><li>20:1-3000</li></ul>
+ *
+ * This tool allows you to check, for a given list of intervals, how many separate intervals the GATK will actually
+ * distinguish at runtime.
+ * </p>
+ *
+ * <h3>Input</h3>
+ * <p>
+ * One or more rod files containing intervals to check.
+ * </p>
+ *
+ * <h3>Output</h3>
+ * <p>
+ * Number of separate intervals identified by GATK after merging overlapping intervals.
+ * </p>
+ *
+ * You can use the -numOverlaps argument to find out how many cases you have of a specific number of overlaps.
+ *
+ * <h3>Example</h3>
+ * <pre>
+ * java -Xmx2g -jar GenomeAnalysisTK.jar \
+ *   -T CountIntervals \
+ *   -R ref.fasta \
+ *   -0 output.txt \
+ *   -check intervals.list
+ * </pre>
+ */
+ at DocumentedGATKFeature( groupName = HelpConstants.DOCS_CAT_QC, extraDocs = {CommandLineGATK.class} )
+public class CountIntervals extends RefWalker<Long, Long> {
+    @Output
+    PrintStream out;
+
+    @Input(fullName="check", shortName = "check", doc="Any number of RODs", required=false)
+    public List<RodBinding<Feature>> features = Collections.emptyList();
+
+    @Argument(fullName="numOverlaps",shortName="no",doc="Count all occurrences of X or more overlapping intervals; defaults to 2", required=false)
+    int numOverlaps = 2;
+
+    public Long reduceInit() {
+        return 0l;
+    }
+
+    public boolean isReduceByInterval() { return true; }
+
+    public Long map(RefMetaDataTracker tracker, ReferenceContext ref, AlignmentContext context) {
+        if ( tracker == null ) {
+            return null;
+        }
+
+        List<Feature> checkIntervals = tracker.getValues(features);
+        return (long) checkIntervals.size();
+    }
+
+    public Long reduce(Long loc, Long prev) {
+        if ( loc == null ) {
+            return 0l;
+        } else {
+            return Math.max(prev,loc);
+        }
+    }
+
+    public void onTraversalDone(List<Pair<GenomeLoc,Long>> finalReduce) {
+        long count = 0;
+        for ( Pair<GenomeLoc,Long> g : finalReduce ) {
+            if ( g.second >= numOverlaps) {
+                count ++;
+            }
+        }
+        out.printf("Number of contiguous intervals: %d",count);
+    }
+}
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/tools/walkers/qc/CountLoci.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/tools/walkers/qc/CountLoci.java
new file mode 100644
index 0000000..51c1617
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/tools/walkers/qc/CountLoci.java
@@ -0,0 +1,96 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.tools.walkers.qc;
+
+import org.broadinstitute.gatk.utils.commandline.Output;
+import org.broadinstitute.gatk.engine.CommandLineGATK;
+import org.broadinstitute.gatk.engine.contexts.AlignmentContext;
+import org.broadinstitute.gatk.engine.contexts.ReferenceContext;
+import org.broadinstitute.gatk.engine.refdata.RefMetaDataTracker;
+import org.broadinstitute.gatk.engine.walkers.LocusWalker;
+import org.broadinstitute.gatk.engine.walkers.NanoSchedulable;
+import org.broadinstitute.gatk.engine.walkers.TreeReducible;
+import org.broadinstitute.gatk.utils.help.DocumentedGATKFeature;
+import org.broadinstitute.gatk.utils.help.HelpConstants;
+
+import java.io.PrintStream;
+
+/**
+ * Walks over the input data set, calculating the total number of covered loci for diagnostic purposes.
+ *
+ * <p>
+ * This is the simplest example of a locus walker.
+ * </p>
+ *
+ * <h3>Input</h3>
+ * <p>
+ * One or more BAM files.
+ * </p>
+ *
+ * <h3>Output</h3>
+ * <p>
+ * Number of loci traversed. If an output file name is provided, then the result will be written to that file.
+ * Otherwise it will be sent to standard console output.
+ * </p>
+ *
+ * <h3>Examples</h3>
+ * <pre>
+ * java -Xmx2g -jar GenomeAnalysisTK.jar \
+ *   -T CountLoci \
+ *   -R ref.fasta \
+ *   -I input.bam \
+ *   -o output.txt \
+ *   [-L input.intervals]
+ * </pre>
+ *
+ */
+ at DocumentedGATKFeature( groupName = HelpConstants.DOCS_CAT_QC, extraDocs = {CommandLineGATK.class} )
+public class CountLoci extends LocusWalker<Integer, Long> implements TreeReducible<Long>, NanoSchedulable {
+    @Output
+    PrintStream out;
+
+    public Integer map(RefMetaDataTracker tracker, ReferenceContext ref, AlignmentContext context) {
+        return 1;
+    }
+
+    public Long reduceInit() { return 0l; }
+
+    public Long reduce(Integer value, Long sum) {
+        return value + sum;
+    }
+
+    /**
+     * Reduces two subtrees together.  In this case, the implementation of the tree reduce
+     * is exactly the same as the implementation of the single reduce.
+     */
+    public Long treeReduce(Long lhs, Long rhs) {
+        return lhs + rhs;
+    }
+
+    public void onTraversalDone( Long c ) {
+        out.println(c);
+    }
+}
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/tools/walkers/qc/CountMales.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/tools/walkers/qc/CountMales.java
new file mode 100644
index 0000000..d665e61
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/tools/walkers/qc/CountMales.java
@@ -0,0 +1,85 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.tools.walkers.qc;
+
+import org.broadinstitute.gatk.utils.commandline.Output;
+import org.broadinstitute.gatk.engine.CommandLineGATK;
+import org.broadinstitute.gatk.engine.contexts.ReferenceContext;
+import org.broadinstitute.gatk.engine.refdata.RefMetaDataTracker;
+import org.broadinstitute.gatk.engine.samples.Gender;
+import org.broadinstitute.gatk.engine.samples.Sample;
+import org.broadinstitute.gatk.engine.walkers.DataSource;
+import org.broadinstitute.gatk.engine.walkers.ReadWalker;
+import org.broadinstitute.gatk.engine.walkers.Requires;
+import org.broadinstitute.gatk.utils.help.DocumentedGATKFeature;
+import org.broadinstitute.gatk.utils.help.HelpConstants;
+import org.broadinstitute.gatk.utils.sam.GATKSAMRecord;
+
+import java.io.PrintStream;
+
+/**
+ * Walks over the input data set, calculating the number of reads seen from male samples for diagnostic purposes.
+ *
+ * <h3>Input</h3>
+ * <p>
+ * One or more BAM files.
+ * </p>
+ *
+ * <h3>Output</h3>
+ * <p>
+ * Number of reads seen from male samples.
+ * </p>
+ *
+ * <h3>Examples</h3>
+ * <pre>
+ * java -Xmx2g -jar GenomeAnalysisTK.jar \
+ *   -T CountMales \
+ *   -R ref.fasta \
+ *   -I samples.bam \
+ *   -o output.txt
+ * </pre>
+ */
+ at DocumentedGATKFeature( groupName = HelpConstants.DOCS_CAT_QC, extraDocs = {CommandLineGATK.class} )
+ at Requires({DataSource.READS, DataSource.REFERENCE})
+public class CountMales extends ReadWalker<Integer, Integer> {
+    @Output
+    public PrintStream out;
+
+    public Integer map(ReferenceContext ref, GATKSAMRecord read, RefMetaDataTracker tracker) {
+        Sample sample = getSampleDB().getSample(read);
+        return sample.getGender() == Gender.MALE ? 1 : 0;
+    }
+
+    public Integer reduceInit() { return 0; }
+
+    public Integer reduce(Integer value, Integer sum) {
+        return value + sum;
+    }
+
+    public void onTraversalDone( Integer c ) {
+        out.println(c);
+    }
+}                                       
\ No newline at end of file
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/tools/walkers/qc/CountRODs.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/tools/walkers/qc/CountRODs.java
new file mode 100644
index 0000000..e068ff7
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/tools/walkers/qc/CountRODs.java
@@ -0,0 +1,214 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.tools.walkers.qc;
+
+import htsjdk.samtools.SAMSequenceDictionary;
+import htsjdk.samtools.SAMSequenceRecord;
+import htsjdk.tribble.Feature;
+import org.broadinstitute.gatk.utils.commandline.Argument;
+import org.broadinstitute.gatk.utils.commandline.Input;
+import org.broadinstitute.gatk.utils.commandline.Output;
+import org.broadinstitute.gatk.utils.commandline.RodBinding;
+import org.broadinstitute.gatk.engine.CommandLineGATK;
+import org.broadinstitute.gatk.engine.contexts.AlignmentContext;
+import org.broadinstitute.gatk.engine.contexts.ReferenceContext;
+import org.broadinstitute.gatk.engine.refdata.RefMetaDataTracker;
+import org.broadinstitute.gatk.engine.refdata.utils.RODRecordList;
+import org.broadinstitute.gatk.engine.walkers.NanoSchedulable;
+import org.broadinstitute.gatk.engine.walkers.RodWalker;
+import org.broadinstitute.gatk.engine.walkers.TreeReducible;
+import org.broadinstitute.gatk.utils.GenomeLoc;
+import org.broadinstitute.gatk.utils.Utils;
+import org.broadinstitute.gatk.utils.collections.ExpandingArrayList;
+import org.broadinstitute.gatk.utils.collections.Pair;
+import org.broadinstitute.gatk.utils.help.DocumentedGATKFeature;
+import org.broadinstitute.gatk.utils.help.HelpConstants;
+
+import java.io.PrintStream;
+import java.util.*;
+
+/**
+ * Prints out counts of the number of reference ordered data objects encountered.
+ *
+ * <p>CountRods is a RODWalker, and so traverses the data by ROD. For example if the ROD passed to it is a VCF file,
+ * it will count the variants in the file.</p>
+ *
+ * <p>Note that this tool is different from CountRodsByRef which is a RefWalker, and so traverses the data by
+ * position along the reference. CountRodsByRef can count ROD elements (such as, but not limited to, variants) found
+ * at each position or within specific intervals if you use the -L argument (see CommandLineGATK).</p>
+ *
+ * <p>Both these tools are different from CountVariants in that they are more generic (they can also count RODs that
+ * are not variants) and CountVariants is more detailed, in that it computes additional statistics (type of variants
+ * being indels vs. SNPs etc). </p>
+ *
+ * <h3>Input</h3>
+ * <p>
+ * One or more rod files.
+ * </p>
+ *
+ * <h3>Output</h3>
+ * <p>
+ * Number of rods seen.
+ * </p>
+ *
+ * <h3>Example</h3>
+ * <pre>
+ * java -Xmx2g -jar GenomeAnalysisTK.jar \
+ *   -T CountRODs \
+ *   -R ref.fasta \
+ *   -o output.txt \
+ *   --rod input.vcf
+ * </pre>
+ *
+ */
+ at DocumentedGATKFeature( groupName = HelpConstants.DOCS_CAT_QC, extraDocs = {CommandLineGATK.class} )
+public class CountRODs extends RodWalker<CountRODs.Datum, Pair<ExpandingArrayList<Long>, Long>> implements TreeReducible<Pair<ExpandingArrayList<Long>, Long>>, NanoSchedulable {
+    @Output
+    public PrintStream out;
+
+    /**
+     * One or more input rod files
+     */
+    @Input(fullName="rod", shortName = "rod", doc="Input VCF file(s)", required=true)
+    public List<RodBinding<Feature>> rods = Collections.emptyList();
+
+    @Argument(fullName = "verbose", shortName = "v", doc="If true, this tool will print out detailed information about the rods it finds and locations", required = false)
+    public boolean verbose = false;
+
+    @Argument(fullName = "showSkipped", shortName = "s", doc="If true, this tool will print out the skipped locations", required = false)
+    public boolean showSkipped = false;
+
+    @Override
+    public Pair<ExpandingArrayList<Long>, Long> treeReduce(Pair<ExpandingArrayList<Long>, Long> lhs, Pair<ExpandingArrayList<Long>, Long> rhs) {
+        ExpandingArrayList<Long> nt = new ExpandingArrayList<Long>();
+        nt.addAll(lhs.first);
+        int index = 0;
+        for (Long l : rhs.first) {
+            if (nt.get(index) == null)
+                nt.add(l);
+            else
+                nt.set(index,nt.get(index) + l);
+            index++;
+        }
+        return new Pair<ExpandingArrayList<Long>, Long>(nt, lhs.second + rhs.second);
+    }
+
+    public class Datum {
+        public long nRodsAtThisLocation = 0;
+        public long nSkippedBases =0;
+        public long nTotalBases = 0;
+
+        public Datum( long nRodsAtThisLocation, long nSkippedBases, long nTotalBases ) {
+            this.nRodsAtThisLocation = nRodsAtThisLocation;
+            this.nSkippedBases = nSkippedBases;
+            this.nTotalBases = nTotalBases;
+        }
+
+        public String toString() {
+            return String.format("<%d %d %d>", nRodsAtThisLocation, nSkippedBases, nTotalBases);
+        }
+    }
+
+    public Datum map(RefMetaDataTracker tracker, ReferenceContext ref, AlignmentContext context) {
+        GenomeLoc cur = context.getLocation();
+
+        if ( verbose && showSkipped ) {
+            for(long i = context.getSkippedBases(); i >= 0; i--) {
+                SAMSequenceDictionary dictionary = getToolkit().getReferenceDataSource().getReference().getSequenceDictionary();
+                SAMSequenceRecord contig = dictionary.getSequence(cur.getContig());
+                if(cur.getStop() < contig.getSequenceLength())
+                    cur = getToolkit().getGenomeLocParser().incPos(cur,1);
+                else
+                    cur = getToolkit().getGenomeLocParser().createGenomeLoc(dictionary.getSequence(contig.getSequenceIndex()+1).getSequenceName(),1,1);
+                out.printf("%s: skipped%n", cur);
+
+            }
+        }
+
+        long nRodsHere = 0;
+        long nTotalBases = 0;
+
+        if ( ref == null ) {
+            // we're getting the last skipped update
+            if ( verbose )
+                out.printf("Last position was %s: skipping %d bases%n",
+                        context.getLocation(), context.getSkippedBases() );
+            nRodsHere = -1; // don't update this
+            nTotalBases = context.getSkippedBases();
+        } else {
+            Collection<RODRecordList> rods = new LinkedList<RODRecordList>();
+            for ( RODRecordList rod : tracker.getBoundRodTracks() ) {
+                //System.out.printf("Considering rod %s%n", rod);
+                if ( rod.getLocation().getStart() == context.getLocation().getStart() && ! rod.getName().equals("interval") ) {
+                    // only consider the first element
+                    //System.out.printf("adding it%n");
+                    rods.add(rod);
+                }
+            }
+
+            nRodsHere = rods.size();
+
+            if ( nRodsHere > 0 ) {
+                if ( verbose ) {
+                    List<String> names = new ArrayList<String>();
+                    for ( RODRecordList rod : rods ) {
+                        names.add(rod.getName());
+                    }
+
+                    //System.out.printf("context is %s", context.getSkippedBases());
+                    out.printf("At %s: found %d rod(s) [%s] after skipping %d bases%n",
+                            context.getLocation(), nRodsHere, Utils.join(",", names), context.getSkippedBases() );
+                }
+            }
+
+            nTotalBases = context.getSkippedBases() + 1;
+        }
+
+        return new Datum(nRodsHere, context.getSkippedBases(), nTotalBases);
+    }
+
+    public Pair<ExpandingArrayList<Long>, Long> reduceInit() {
+        return new Pair<ExpandingArrayList<Long>, Long>(new ExpandingArrayList<Long>(), 0l);
+    }
+
+    private void updateCounts(ExpandingArrayList<Long> counts, long nRods, long nObs) {
+        if ( nRods >= 0 ) {
+            long prev = counts.get((int)nRods) == null ? 0l : counts.get((int)nRods);
+            counts.set((int)nRods, nObs + prev);
+        }
+    }
+
+    public Pair<ExpandingArrayList<Long>, Long> reduce(Datum point, Pair<ExpandingArrayList<Long>, Long> sum) {
+        ExpandingArrayList<Long> counts = sum.getFirst();
+        updateCounts(counts, point.nRodsAtThisLocation, 1);
+        updateCounts(counts, 0, point.nSkippedBases);
+
+        Pair<ExpandingArrayList<Long>, Long> r = new Pair<ExpandingArrayList<Long>, Long>(counts, point.nTotalBases + sum.getSecond());
+
+        //System.out.printf("Reduce: %s %s => %s%n", point, sum, r);
+        return r;
+    }
+}
\ No newline at end of file
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/tools/walkers/qc/CountRODsByRef.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/tools/walkers/qc/CountRODsByRef.java
new file mode 100644
index 0000000..40471b5
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/tools/walkers/qc/CountRODsByRef.java
@@ -0,0 +1,112 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.tools.walkers.qc;
+
+import htsjdk.tribble.Feature;
+import org.broadinstitute.gatk.utils.commandline.Argument;
+import org.broadinstitute.gatk.utils.commandline.Input;
+import org.broadinstitute.gatk.utils.commandline.RodBinding;
+import org.broadinstitute.gatk.engine.CommandLineGATK;
+import org.broadinstitute.gatk.engine.contexts.AlignmentContext;
+import org.broadinstitute.gatk.engine.contexts.ReferenceContext;
+import org.broadinstitute.gatk.engine.refdata.RefMetaDataTracker;
+import org.broadinstitute.gatk.engine.walkers.RefWalker;
+import org.broadinstitute.gatk.utils.collections.ExpandingArrayList;
+import org.broadinstitute.gatk.utils.collections.Pair;
+import org.broadinstitute.gatk.utils.help.DocumentedGATKFeature;
+import org.broadinstitute.gatk.utils.help.HelpConstants;
+
+import java.util.Collections;
+import java.util.List;
+
+/**
+ * Prints out counts of the number of reference ordered data objects encountered along the reference.
+ *
+ * <p>CountRodsByRef is a RefWalker, and so traverses the data by position along the reference. It counts ROD
+ * elements (such as, but not limited to, variants) found at each position or within specific intervals if you use
+ * the -L argument (see CommandLineGATK).</p>
+ *
+ * <p>Note that this tool is different from the basic CountRods, which is a RODWalker, and so traverses the data by
+ * ROD. For example if the ROD passed to it is a VCF file, CountRods will simply count the variants in the file.</p>
+ *
+ * <p>Both these tools are different from CountVariants in that they are more generic (they can also count RODs that
+ * are not variants) and CountVariants is more detailed, in that it computes additional statistics (type of variants
+ * being indels vs. SNPs etc). </p>
+ *
+ * <h3>Input</h3>
+ * <p>
+ * One or more rod files.
+ * </p>
+ *
+ * <h3>Output</h3>
+ * <p>
+ * Number of rods seen.
+ * </p>
+ *
+ * <h3>Examples</h3>
+ * <pre>
+ * java -Xmx2g -jar GenomeAnalysisTK.jar \
+ *   -T CountRODsByRef \
+ *   -R ref.fasta \
+ *   -o output.txt \
+ *   --rod input.vcf
+ * </pre>
+ *
+ */
+ at DocumentedGATKFeature( groupName = HelpConstants.DOCS_CAT_QC, extraDocs = {CommandLineGATK.class} )
+public class CountRODsByRef extends RefWalker<CountRODs.Datum, Pair<ExpandingArrayList<Long>, Long>> {
+
+    /**
+     * One or more input rod files
+     */
+    @Input(fullName="rod", shortName = "rod", doc="Input VCF file(s)", required=false)
+    public List<RodBinding<Feature>> rods = Collections.emptyList();
+
+    @Argument(fullName = "verbose", shortName = "v", doc="If true, this tool will print out detailed information about the rods it finds and locations", required = false)
+    public boolean verbose = false;
+
+    @Argument(fullName = "showSkipped", shortName = "s", doc="If true, this tool will print out the skipped locations", required = false)
+    public boolean showSkipped = false;
+
+    CountRODs crw = new CountRODs();
+
+    public void initialize() {
+        crw.verbose = verbose;
+        crw.showSkipped = showSkipped;
+    }
+
+    public CountRODs.Datum map(RefMetaDataTracker tracker, ReferenceContext ref, AlignmentContext context) {
+        return crw.map(tracker, ref, context);
+    }
+
+    public Pair<ExpandingArrayList<Long>, Long> reduceInit() {
+        return crw.reduceInit();
+    }
+
+    public Pair<ExpandingArrayList<Long>, Long> reduce(CountRODs.Datum point, Pair<ExpandingArrayList<Long>, Long> sum) {
+        return crw.reduce(point, sum);
+    }
+}
\ No newline at end of file
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/tools/walkers/qc/CountReadEvents.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/tools/walkers/qc/CountReadEvents.java
new file mode 100644
index 0000000..998448e
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/tools/walkers/qc/CountReadEvents.java
@@ -0,0 +1,121 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.tools.walkers.qc;
+
+import htsjdk.samtools.CigarOperator;
+import org.broadinstitute.gatk.utils.commandline.Output;
+import org.broadinstitute.gatk.engine.CommandLineGATK;
+import org.broadinstitute.gatk.engine.contexts.ReferenceContext;
+import org.broadinstitute.gatk.engine.refdata.RefMetaDataTracker;
+import org.broadinstitute.gatk.engine.report.GATKReport;
+import org.broadinstitute.gatk.engine.walkers.DataSource;
+import org.broadinstitute.gatk.engine.walkers.ReadWalker;
+import org.broadinstitute.gatk.engine.walkers.Requires;
+import org.broadinstitute.gatk.utils.help.DocumentedGATKFeature;
+import org.broadinstitute.gatk.utils.help.HelpConstants;
+import org.broadinstitute.gatk.utils.sam.GATKSAMRecord;
+import org.broadinstitute.gatk.utils.sam.ReadUtils;
+
+import java.io.PrintStream;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * Walks over the input data set, counting the number of read events (from the CIGAR operator)
+ *
+ * <h3>Input</h3>
+ * <p>
+ * One or more BAM files.
+ * </p>
+ *
+ * <h3>Output</h3>
+ * <p>
+ * Number of read events for each category, formatted as a GATKReport table.
+ *
+ * <h3>Examples</h3>
+ * <pre>
+ * java -Xmx2g -jar GenomeAnalysisTK.jar \
+ *   -T CountReadEvents \
+ *   -R ref.fasta \
+ *   -I input.bam \
+ *   -o output.grp \
+ *   [-L input.intervals]
+ * </pre>
+ */
+
+ at DocumentedGATKFeature( groupName = HelpConstants.DOCS_CAT_QC, extraDocs = {CommandLineGATK.class} )
+ at Requires({DataSource.READS, DataSource.REFERENCE})
+public class CountReadEvents extends ReadWalker<Map<CigarOperator, ArrayList<Integer>> , Map<Integer, Map<CigarOperator, Long>>> {
+    @Output
+    PrintStream out;
+
+    public Map<CigarOperator, ArrayList<Integer>> map(ReferenceContext ref, GATKSAMRecord read, RefMetaDataTracker tracker) {
+        return ReadUtils.getCigarOperatorForAllBases(read);
+    }
+
+    public Map<Integer, Map<CigarOperator, Long>> reduceInit() {
+        return new HashMap<Integer, Map<CigarOperator, Long>>();
+    }
+
+    public Map<Integer, Map<CigarOperator, Long>> reduce(Map<CigarOperator, ArrayList<Integer>> value, Map<Integer, Map<CigarOperator, Long>> sum) {
+        for (Map.Entry<CigarOperator, ArrayList<Integer>> entry : value.entrySet()) {
+            CigarOperator op = entry.getKey();
+            ArrayList<Integer> positions = entry.getValue();
+
+            for (int p : positions) {
+                Map<CigarOperator, Long> operatorCount = sum.get(p);
+                if (operatorCount == null) {
+                    operatorCount = new HashMap<CigarOperator, Long>();
+                    sum.put(p, operatorCount);
+                }
+
+                Long count = operatorCount.get(op);
+                if (count == null)
+                    count = 0L;
+                count++;
+                operatorCount.put(op, count);
+            }
+        }
+        return sum;
+    }
+
+    @Override
+    public void onTraversalDone(Map<Integer, Map<CigarOperator, Long>> result) {
+        GATKReport report = GATKReport.newSimpleReport("Events", "Position", "Event", "Observations");
+        for (Map.Entry<Integer, Map<CigarOperator, Long>> entry : result.entrySet()) {
+            int position = entry.getKey();
+            Map<CigarOperator, Long> operatorCount = entry.getValue();
+
+            for (Map.Entry<CigarOperator, Long> subEntry: operatorCount.entrySet()) {
+                String operator = subEntry.getKey().name();
+                Long observations = subEntry.getValue();
+                report.addRow(position, operator, observations);
+            }
+        }
+        report.print(out);
+    }
+}
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/tools/walkers/qc/CountReads.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/tools/walkers/qc/CountReads.java
new file mode 100644
index 0000000..33d22ca
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/tools/walkers/qc/CountReads.java
@@ -0,0 +1,81 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.tools.walkers.qc;
+
+import org.broadinstitute.gatk.engine.CommandLineGATK;
+import org.broadinstitute.gatk.engine.contexts.ReferenceContext;
+import org.broadinstitute.gatk.engine.refdata.RefMetaDataTracker;
+import org.broadinstitute.gatk.engine.walkers.DataSource;
+import org.broadinstitute.gatk.engine.walkers.NanoSchedulable;
+import org.broadinstitute.gatk.engine.walkers.ReadWalker;
+import org.broadinstitute.gatk.engine.walkers.Requires;
+import org.broadinstitute.gatk.utils.help.DocumentedGATKFeature;
+import org.broadinstitute.gatk.utils.help.HelpConstants;
+import org.broadinstitute.gatk.utils.sam.GATKSAMRecord;
+
+/**
+ * Walks over the input data set, calculating the number of reads seen for diagnostic purposes.
+ *
+ * <p>
+ * Can also count the number of reads matching a given criterion using read filters (see the
+ * --read-filter command line argument).  Simplest example of a read-backed analysis.
+ *
+ *
+ * <h3>Input</h3>
+ * <p>
+ * One or more BAM files.
+ * </p>
+ *
+ * <h3>Output</h3>
+ * <p>
+ * Number of reads seen.
+ * </p>
+ *
+ * <h3>Examples</h3>
+ * <pre>
+ * java -Xmx2g -jar GenomeAnalysisTK.jar \
+ *   -R ref.fasta \
+ *   -T CountReads \
+ *   -I input.bam \
+ *   [-L input.intervals]
+ * </pre>
+ *
+ */
+ at DocumentedGATKFeature( groupName = HelpConstants.DOCS_CAT_QC, extraDocs = {CommandLineGATK.class} )
+ at Requires({DataSource.READS, DataSource.REFERENCE})
+public class CountReads extends ReadWalker<Integer, Long> implements NanoSchedulable {
+    public Integer map(ReferenceContext ref, GATKSAMRecord read, RefMetaDataTracker tracker) {
+        return 1;
+    }
+
+    @Override public Long reduceInit() { return 0L; }
+
+    public Long reduce(Integer value, Long sum) { return (long) value + sum; }
+
+    public void onTraversalDone(Long result) {
+        logger.info("CountReads counted " + result + " reads in the traversal");
+    }
+}
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/tools/walkers/qc/CountTerminusEvent.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/tools/walkers/qc/CountTerminusEvent.java
new file mode 100644
index 0000000..90a131c
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/tools/walkers/qc/CountTerminusEvent.java
@@ -0,0 +1,104 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.tools.walkers.qc;
+
+import htsjdk.samtools.CigarElement;
+import htsjdk.samtools.CigarOperator;
+import org.broadinstitute.gatk.utils.commandline.Output;
+import org.broadinstitute.gatk.engine.CommandLineGATK;
+import org.broadinstitute.gatk.engine.contexts.ReferenceContext;
+import org.broadinstitute.gatk.engine.refdata.RefMetaDataTracker;
+import org.broadinstitute.gatk.engine.walkers.DataSource;
+import org.broadinstitute.gatk.engine.walkers.ReadWalker;
+import org.broadinstitute.gatk.engine.walkers.Requires;
+import org.broadinstitute.gatk.utils.collections.Pair;
+import org.broadinstitute.gatk.utils.exceptions.UserException;
+import org.broadinstitute.gatk.utils.help.DocumentedGATKFeature;
+import org.broadinstitute.gatk.utils.help.HelpConstants;
+import org.broadinstitute.gatk.utils.sam.GATKSAMRecord;
+
+import java.io.PrintStream;
+import java.util.List;
+
+/**
+ * Walks over the input data set, counting the number of reads ending in insertions/deletions or soft-clips
+ *
+ * <h3>Input</h3>
+ * <p>
+ * One or more BAM files.
+ * </p>
+ *
+ * <h3>Output</h3>
+ * <p>
+ * Number of reads ending in each category.
+ * </p>
+ *
+ * <h3>Examples</h3>
+ * <pre>
+ * java -Xmx2g -jar GenomeAnalysisTK.jar \
+ *   -R ref.fasta \
+ *   -T CountTerminusEvent \
+ *   -o output.txt \
+ *   -I input.bam \
+ *   [-L input.intervals]
+ * </pre>
+ */
+ at DocumentedGATKFeature( groupName = HelpConstants.DOCS_CAT_QC, extraDocs = {CommandLineGATK.class} )
+ at Requires({DataSource.READS, DataSource.REFERENCE})
+public class CountTerminusEvent extends ReadWalker<Pair<Long, Long>, Pair<Long, Long>> {
+    @Output
+    public PrintStream out;
+
+    public Pair<Long, Long> map(ReferenceContext ref, GATKSAMRecord read, RefMetaDataTracker tracker) {
+        List<CigarElement> cigarElements = read.getCigar().getCigarElements();
+
+        CigarElement lastElement = null;
+        for (CigarElement element : cigarElements) {
+            if (element.getOperator() != CigarOperator.HARD_CLIP)
+                lastElement = element;
+        }
+
+        if (lastElement == null)
+            throw new UserException.MalformedBAM(read, "read does not have any bases, it's all hard clips");
+
+        long endsInIndel = lastElement.getOperator() == CigarOperator.INSERTION || lastElement.getOperator() == CigarOperator.DELETION? 1 : 0;
+        long endsInSC = lastElement.getOperator() == CigarOperator.SOFT_CLIP ? 1 : 0;
+
+        return new Pair<Long, Long>(endsInIndel, endsInSC);
+    }
+
+    public Pair<Long, Long> reduceInit() { return new Pair<Long, Long>(0L, 0L); }
+
+    public Pair<Long, Long> reduce(Pair<Long, Long> value, Pair<Long, Long> sum) {
+        sum.set(sum.getFirst() + value.getFirst(), sum.getSecond() + value.getSecond());
+        return sum;
+    }
+
+    @Override
+    public void onTraversalDone(Pair<Long, Long> result) {
+        out.println(String.format("\tReads ending in indels : %d\n\tReads ending in soft-clips: %d\n", result.getFirst(), result.getSecond()));
+    }
+}
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/tools/walkers/qc/DocumentationTest.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/tools/walkers/qc/DocumentationTest.java
new file mode 100644
index 0000000..b5a1e74
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/tools/walkers/qc/DocumentationTest.java
@@ -0,0 +1,117 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.tools.walkers.qc;
+
+import htsjdk.tribble.Feature;
+import org.broadinstitute.gatk.utils.commandline.*;
+import org.broadinstitute.gatk.engine.arguments.DbsnpArgumentCollection;
+import org.broadinstitute.gatk.engine.arguments.StandardVariantContextInputArgumentCollection;
+import org.broadinstitute.gatk.engine.contexts.AlignmentContext;
+import org.broadinstitute.gatk.engine.contexts.ReferenceContext;
+import org.broadinstitute.gatk.engine.refdata.RefMetaDataTracker;
+import org.broadinstitute.gatk.engine.walkers.RodWalker;
+import htsjdk.variant.variantcontext.writer.VariantContextWriter;
+import htsjdk.variant.variantcontext.VariantContext;
+
+import java.util.*;
+
+/**
+ * Summary test
+ *
+ * <p>Body test</p>
+ */
+ at Hidden
+public class DocumentationTest extends RodWalker<Integer, Integer> {
+    // the docs for the arguments are in the collection
+    @ArgumentCollection protected StandardVariantContextInputArgumentCollection variantCollection = new StandardVariantContextInputArgumentCollection();
+
+    /**
+     * dbSNP comparison VCF.  By default, the dbSNP file is used to specify the set of "known" variants.
+     * Other sets can be specified with the -knownName (--known_names) argument.
+     */
+    @ArgumentCollection
+    protected DbsnpArgumentCollection dbsnp = new DbsnpArgumentCollection();
+
+    /**
+     * detailed documentation about the argument goes here.
+     */
+    @Input(fullName="listofRodBinding", shortName = "disc", doc="Output variants that were not called in this Feature comparison track", required=false)
+    private List<RodBinding<VariantContext>> listOfRodBinding = Collections.emptyList();
+
+    @Input(fullName="optionalRodBinding", shortName = "conc", doc="Output variants that were also called in this Feature comparison track", required=false)
+    private RodBinding<VariantContext> concordanceTrack;
+
+    @Input(fullName="optionalRodBindingWithoutDefault", shortName = "optionalRodBindingWithoutDefault", doc="Output variants that were also called in this Feature comparison track", required=false)
+    private RodBinding<VariantContext> noDefaultOptionalRodBinding;
+
+    @Input(fullName="optionalRodBindingWithoutDefaultNull", shortName = "shortTest", doc="Output variants that were also called in this Feature comparison track", required=false)
+    private RodBinding<VariantContext> noDefaultOptionalRodBindingNull = null;
+
+    @Input(fullName="featureArg", shortName = "featureArg", doc="A RodBinding of feature", required=false)
+    private RodBinding<Feature> featureArg = null;
+
+    @Output(doc="VCFWriter")
+    protected VariantContextWriter vcfWriter = null;
+
+    @Advanced
+    @Argument(fullName="setString", shortName="sn", doc="Sample name to be included in the analysis. Can be specified multiple times.", required=false)
+    public Set<String> sampleNames;
+
+    @Argument(fullName="setStringInitialized", shortName="setStringInitialized", doc="Sample name to be included in the analysis. Can be specified multiple times.", required=false)
+    public Set<String> setStringInitialized = new HashSet<String>();
+
+    @Argument(shortName="optionalArgWithMissinglessDefault", doc="One or more criteria to use when selecting the data.  Evaluated *after* the specified samples are extracted and the INFO-field annotations are updated.", required=false)
+    public ArrayList<String> SELECT_EXPRESSIONS = new ArrayList<String>();
+
+    @Argument(shortName="AAAAA", fullName = "AAAAA", doc="Should be the first argument", required=false)
+    public boolean FIRST_ARG = false;
+
+    @Advanced
+    @Argument(fullName="booleanArg", shortName="env", doc="Don't include loci found to be non-variant after the subsetting procedure.", required=false)
+    private boolean EXCLUDE_NON_VARIANTS = false;
+
+    @Advanced
+    @Argument(fullName="booleanArray", shortName="booleanArray", doc="x", required=false)
+    private boolean[] boolArray = null;
+
+    @Argument(fullName="enumTest", shortName="enumTest", doc="Test enum", required=false)
+    private TestEnum TestEnumArg = TestEnum.ENUM2;
+    public enum TestEnum {
+        /** Docs for enum1 */
+        ENUM1,
+        /** Docs for enum2 */
+        ENUM2
+    }
+
+    @Hidden
+    @Argument(fullName="hiddenArg", shortName="keepAF", doc="Don't include loci found to be non-variant after the subsetting procedure.", required=false)
+    private boolean KEEP_AF_SPECTRUM = false;
+
+    public Integer map(RefMetaDataTracker tracker, ReferenceContext ref, AlignmentContext context) { return 0; }
+    public Integer reduceInit() { return 0; }
+    public Integer reduce(Integer value, Integer sum) { return value + sum; }
+    public void onTraversalDone(Integer result) { }
+}
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/tools/walkers/qc/ErrorThrowing.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/tools/walkers/qc/ErrorThrowing.java
new file mode 100644
index 0000000..6e872e3
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/tools/walkers/qc/ErrorThrowing.java
@@ -0,0 +1,110 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.tools.walkers.qc;
+
+import org.broadinstitute.gatk.utils.commandline.Argument;
+import org.broadinstitute.gatk.utils.commandline.Input;
+import org.broadinstitute.gatk.engine.CommandLineGATK;
+import org.broadinstitute.gatk.engine.contexts.AlignmentContext;
+import org.broadinstitute.gatk.engine.contexts.ReferenceContext;
+import org.broadinstitute.gatk.engine.refdata.RefMetaDataTracker;
+import org.broadinstitute.gatk.engine.walkers.NanoSchedulable;
+import org.broadinstitute.gatk.engine.walkers.RefWalker;
+import org.broadinstitute.gatk.engine.walkers.TreeReducible;
+import org.broadinstitute.gatk.utils.exceptions.ReviewedGATKException;
+import org.broadinstitute.gatk.utils.exceptions.UserException;
+import org.broadinstitute.gatk.utils.help.DocumentedGATKFeature;
+import org.broadinstitute.gatk.utils.help.HelpConstants;
+
+/**
+ * A walker that simply throws errors.  Allows us to test that the engine is behaving as expected with error handling
+ */
+ at DocumentedGATKFeature( groupName = HelpConstants.DOCS_CAT_TOY, extraDocs = {CommandLineGATK.class} )
+public class ErrorThrowing extends RefWalker<Integer,Integer> implements TreeReducible<Integer>, NanoSchedulable {
+    @Input(fullName="exception", shortName = "E", doc="Java class of exception to throw", required=true)
+    public String exceptionToThrow;
+
+    @Argument(fullName = "failMethod", shortName = "fail", doc = "Determines which method to fail in", required = false)
+    public FailMethod failMethod = FailMethod.MAP;
+
+    public enum FailMethod {
+          MAP,
+          REDUCE,
+          TREE_REDUCE
+    }
+
+    //
+    // Template code to allow us to build the walker, doesn't actually do anything
+    //
+    @Override
+    public Integer map(RefMetaDataTracker tracker, ReferenceContext ref, AlignmentContext context) {
+        if ( ref == null ) // only throw exception when we are in proper map, not special map(null) call
+            return null;
+
+        if ( failMethod == FailMethod.MAP )
+            fail();
+
+        return 0;
+    }
+
+    @Override
+    public Integer reduceInit() {
+        return 0;
+    }
+
+    @Override
+    public Integer reduce(Integer value, Integer sum) {
+        if ( value != null && failMethod == FailMethod.REDUCE )
+            fail();
+        return sum;
+    }
+
+    public Integer treeReduce(final Integer lhs, final Integer rhs) {
+        if ( failMethod == FailMethod.TREE_REDUCE )
+            fail();
+        return rhs;
+    }
+
+    private void fail() {
+        if ( exceptionToThrow.equals("UserException") ) {
+            throw new UserException("UserException");
+        } else if ( exceptionToThrow.equals("NullPointerException") ) {
+            throw new NullPointerException();
+        } else if ( exceptionToThrow.equals("ReviewedGATKException") ) {
+            throw new ReviewedGATKException("ReviewedGATKException");
+        } else if ( exceptionToThrow.equals("SamError1") ) {
+            throw new RuntimeException(CommandLineGATK.PICARD_TEXT_SAM_FILE_ERROR_1);
+        } else if ( exceptionToThrow.equals("SamError2") ) {
+            throw new RuntimeException(CommandLineGATK.PICARD_TEXT_SAM_FILE_ERROR_2);
+        } else if ( exceptionToThrow.equals("NoSpace1") ) {
+            throw new htsjdk.samtools.util.RuntimeIOException(new java.io.IOException("No space left on device java.io.FileOutputStream.writeBytes(Native Method)"));
+        } else if ( exceptionToThrow.equals("NoSpace2") ) {
+            throw new htsjdk.samtools.SAMException("Exception writing BAM index file", new java.io.IOException("No space left on device java.io.FileOutputStream.writeBytes(Native Method)"));
+        } else {
+            throw new UserException.BadArgumentValue("exception", "exception isn't a recognized value " + exceptionToThrow);
+        }
+    }
+}
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/tools/walkers/qc/FlagStat.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/tools/walkers/qc/FlagStat.java
new file mode 100644
index 0000000..83c2cc4
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/tools/walkers/qc/FlagStat.java
@@ -0,0 +1,225 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.tools.walkers.qc;
+
+import org.broadinstitute.gatk.utils.commandline.Output;
+import org.broadinstitute.gatk.engine.CommandLineGATK;
+import org.broadinstitute.gatk.engine.contexts.ReferenceContext;
+import org.broadinstitute.gatk.engine.refdata.RefMetaDataTracker;
+import org.broadinstitute.gatk.engine.walkers.DataSource;
+import org.broadinstitute.gatk.engine.walkers.NanoSchedulable;
+import org.broadinstitute.gatk.engine.walkers.ReadWalker;
+import org.broadinstitute.gatk.engine.walkers.Requires;
+import org.broadinstitute.gatk.utils.help.DocumentedGATKFeature;
+import org.broadinstitute.gatk.utils.help.HelpConstants;
+import org.broadinstitute.gatk.utils.sam.GATKSAMRecord;
+
+import java.io.PrintStream;
+import java.text.DecimalFormat;
+import java.text.NumberFormat;
+
+/**
+ * A reimplementation of the 'samtools flagstat' subcommand in the GATK
+ *
+ * <p>This tool walks over all input data, accumulating statistics such as total number of reads,
+ * reads with QC failure flag set, number of duplicates, percentage mapped, etc.</p>
+ *
+ * <h3>Input</h3>
+ * <p>
+ * A BAM file containing the sequence data.
+ * </p>
+ *
+ * <h3>Output</h3>
+ * <p>
+ * Resulting stats are written to file if an output file name is given (with -o), otherwise output to stdout.
+ * </p>
+ *
+ * <h3>Example</h3>
+ * <pre>
+ * java -Xmx2g -jar GenomeAnalysisTK.jar \
+ *   -T FlagStat \
+ *   -R ref.fasta \
+ *   -I reads.bam \
+ *   [-o output.txt]
+ * </pre>
+ *
+ * @author aaron
+ */
+ at DocumentedGATKFeature( groupName = HelpConstants.DOCS_CAT_QC, extraDocs = {CommandLineGATK.class} )
+ at Requires({DataSource.READS})
+public class FlagStat extends ReadWalker<FlagStat.FlagStatus, FlagStat.FlagStatus> implements NanoSchedulable {
+    @Output
+    PrintStream out;
+
+    // what comes out of the flagstat
+    public final static class FlagStatus {
+        long readCount = 0L;
+        long QC_failure = 0L;
+        long duplicates = 0L;
+        long mapped = 0L;
+        long paired_in_sequencing = 0L;
+        long read1 = 0L;
+        long read2 = 0L;
+        long properly_paired = 0L;
+        long with_itself_and_mate_mapped = 0L;
+        long singletons = 0L;
+        long with_mate_mapped_to_a_different_chr = 0L;
+        long with_mate_mapped_to_a_different_chr_maq_greaterequal_than_5 = 0L;
+
+        public String toString() {
+            String ret = "";
+            StringBuilder builder = new StringBuilder(ret);
+            NumberFormat percentFormatter = new DecimalFormat("#0.00");
+            builder.append(readCount);
+            builder.append(" in total\n");
+
+            builder.append(QC_failure);
+            builder.append(" QC failure\n");
+
+
+            builder.append(duplicates);
+            builder.append(" duplicates\n");
+
+            builder.append(mapped);
+            builder.append(" mapped (");
+            builder.append(percentFormatter.format(( (float)mapped / (float)readCount ) * 100.0));
+            builder.append("%)\n");
+
+            builder.append(paired_in_sequencing);
+            builder.append(" paired in sequencing\n");
+
+
+            builder.append(read1);
+            builder.append(" read1\n");
+
+            builder.append(read2);
+            builder.append(" read2\n");
+
+            builder.append(properly_paired);
+            builder.append(" properly paired (");
+            builder.append(percentFormatter.format(( (float)properly_paired / (float)readCount ) * 100.0));
+            builder.append("%)\n");
+
+
+            builder.append(with_itself_and_mate_mapped);
+            builder.append(" with itself and mate mapped\n");
+
+            builder.append(singletons);
+            builder.append(" singletons (");
+            builder.append(percentFormatter.format(( (float)singletons / (float)readCount ) * 100.0));
+                        builder.append("%)\n");
+
+
+            builder.append(with_mate_mapped_to_a_different_chr);
+            builder.append(" with mate mapped to a different chr\n");
+
+            builder.append(with_mate_mapped_to_a_different_chr_maq_greaterequal_than_5);
+            builder.append(" with mate mapped to a different chr (mapQ>=5)");
+
+            return builder.toString();
+        }
+
+        public FlagStatus add(final FlagStatus other) {
+            readCount += other.readCount;
+            QC_failure += other.QC_failure;
+            duplicates += other.duplicates;
+            mapped += other.mapped;
+            paired_in_sequencing += other.paired_in_sequencing;
+            read1 += other.read1;
+            read2 += other.read2;
+            properly_paired += other.properly_paired;
+            with_itself_and_mate_mapped += other.with_itself_and_mate_mapped;
+            singletons += other.singletons;
+            with_mate_mapped_to_a_different_chr += other.with_mate_mapped_to_a_different_chr;
+            with_mate_mapped_to_a_different_chr_maq_greaterequal_than_5 += other.with_mate_mapped_to_a_different_chr_maq_greaterequal_than_5;
+
+            return this;
+        }
+
+        public FlagStatus add(final GATKSAMRecord read) {
+            this.readCount++;
+
+            if (read.getReadFailsVendorQualityCheckFlag()) {
+                this.QC_failure++;
+            }
+            if (read.getDuplicateReadFlag()) {
+                this.duplicates++;
+            }
+            if (!read.getReadUnmappedFlag()) {
+                this.mapped++;
+            }
+            if (read.getReadPairedFlag()) {
+                this.paired_in_sequencing++;
+
+                if (read.getSecondOfPairFlag()) {
+                    this.read2++;
+                } else if (read.getReadPairedFlag()) {
+                    this.read1++;
+                }
+                if (read.getProperPairFlag()) {
+                    this.properly_paired++;
+                }
+                if (!read.getReadUnmappedFlag() && !read.getMateUnmappedFlag()) {
+                    this.with_itself_and_mate_mapped++;
+
+                    if (!read.getReferenceIndex().equals(read.getMateReferenceIndex())) {
+                        this.with_mate_mapped_to_a_different_chr++;
+
+                        if (read.getMappingQuality() >= 5) {
+                            this.with_mate_mapped_to_a_different_chr_maq_greaterequal_than_5++;
+                        }
+                    }
+                }
+                if (!read.getReadUnmappedFlag() && read.getMateUnmappedFlag()) {
+                    this.singletons++;
+                }
+            }
+
+            return this;
+        }
+    }
+
+
+    @Override
+    public FlagStatus map( final ReferenceContext ref, final GATKSAMRecord read, final RefMetaDataTracker metaDataTracker ) {
+        return new FlagStatus().add(read);
+   }
+
+    @Override
+    public FlagStatus reduceInit() {
+        return new FlagStatus();
+    }
+
+    @Override
+    public FlagStatus reduce(final FlagStatus value, final FlagStatus sum) {
+        return sum.add(value);
+    }
+
+    @Override
+    public void onTraversalDone(final FlagStatus result) {
+        out.println(result.toString());
+    }
+}
\ No newline at end of file
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/tools/walkers/qc/Pileup.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/tools/walkers/qc/Pileup.java
new file mode 100644
index 0000000..322cea6
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/tools/walkers/qc/Pileup.java
@@ -0,0 +1,217 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.tools.walkers.qc;
+
+import htsjdk.tribble.Feature;
+import org.broadinstitute.gatk.utils.commandline.*;
+import org.broadinstitute.gatk.engine.CommandLineGATK;
+import org.broadinstitute.gatk.engine.contexts.AlignmentContext;
+import org.broadinstitute.gatk.engine.contexts.ReferenceContext;
+import org.broadinstitute.gatk.engine.refdata.RefMetaDataTracker;
+import org.broadinstitute.gatk.engine.walkers.LocusWalker;
+import org.broadinstitute.gatk.engine.walkers.NanoSchedulable;
+import org.broadinstitute.gatk.engine.walkers.TreeReducible;
+import org.broadinstitute.gatk.utils.Utils;
+import org.broadinstitute.gatk.utils.help.DocumentedGATKFeature;
+import org.broadinstitute.gatk.utils.help.HelpConstants;
+import org.broadinstitute.gatk.utils.pileup.PileupElement;
+import org.broadinstitute.gatk.utils.pileup.ReadBackedPileup;
+
+import java.io.PrintStream;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+/**
+ * Emulates the samtools pileup command to print aligned reads
+ *
+ * <p>Prints the alignment in something similar to the Samtools pileup format (see the
+ * <a href="http://samtools.sourceforge.net/pileup.shtml">Pileup format documentation</a> for more details about
+ * the original format). There is one line per genomic position, listing the chromosome name, coordinate, reference
+ * base, read bases, and read qualities. In addition to these default fields, additional information can be added to
+ * the output as extra columns; see options detailed below.</p>
+ *
+ * <h4>Emulated command:</h4>
+ * <pre>
+ *  samtools pileup -f in.ref.fasta -l in.site_list input.bam
+ * </pre>
+
+ *
+ * <h3>Input</h3>
+ * <p>
+ * A BAM file and the interval to print.
+ * </p>
+ *
+ * <h3>Output</h3>
+ * <p>
+ *  Alignment of reads formatted in the Pileup style.
+ * </p>
+ *
+ * <h3>Example</h3>
+ * <pre>
+ * java -Xmx2g -jar GenomeAnalysisTK.jar \
+ *   -T Pileup \
+ *   -R exampleFASTA.fasta \
+ *   -I exampleBAM.bam \
+ *   -L chr1:257-267
+ *   -o output.txt
+ * </pre>
+ * <h4>Expected output</h4>
+ * <pre>
+ *     chr1 257 A CAA '&=
+ *     chr1 258 C TCC A:=
+ *     chr1 259 C CCC )A=
+ *     chr1 260 C ACC (=<
+ *     chr1 261 T TCT '44
+ *     chr1 262 A AAA '?:
+ *     chr1 263 A AGA 1'6
+ *     chr1 264 C TCC 987
+ *     chr1 265 C CCC (@(
+ *     chr1 266 C GCC ''=
+ *     chr1 267 T AAT 7%>
+ * </pre>
+ *
+ */
+ at DocumentedGATKFeature( groupName = HelpConstants.DOCS_CAT_QC, extraDocs = {CommandLineGATK.class} )
+public class Pileup extends LocusWalker<String, Integer> implements TreeReducible<Integer>, NanoSchedulable {
+
+    private static final String verboseDelimiter = "@"; // it's ugly to use "@" but it's literally the only usable character not allowed in read names
+
+    @Output
+    PrintStream out;
+
+    /**
+     * In addition to the standard pileup output, adds 'verbose' output too. The verbose output contains the number of spanning deletions,
+     * and for each read in the pileup it has the read name, offset in the base string, read length, and read mapping quality.  These per
+     * read items are delimited with an '@' character.
+     */
+    @Argument(fullName="showVerbose",shortName="verbose",doc="Add an extra verbose section to the pileup output", required=false)
+    public boolean SHOW_VERBOSE = false;
+    /**
+     * This enables annotating the pileup to show overlaps with metadata from a ROD file.
+     * For example, if you provide a VCF and there is a SNP at a given location covered by the pileup, the pileup
+     * output at that position will be annotated with the corresponding source ROD identifier.
+     */
+    @Input(fullName="metadata",shortName="metadata",doc="ROD file containing metadata", required=false)
+    public List<RodBinding<Feature>> rods = Collections.emptyList();
+    /**
+     * Adds the length of the insert each base comes from to the output pileup. Here, "insert" refers to the DNA insert
+     * produced during library generation before sequencing.
+     */
+    @Hidden
+    @Argument(fullName="outputInsertLength",shortName = "outputInsertLength",doc="Output insert length",required=false)
+    public boolean outputInsertLength=false;
+
+    @Override
+    public String map(RefMetaDataTracker tracker, ReferenceContext ref, AlignmentContext context) {
+        final String rods = getReferenceOrderedData( tracker );
+
+        ReadBackedPileup basePileup = context.getBasePileup();
+
+        final StringBuilder s = new StringBuilder();
+        s.append(String.format("%s %s", basePileup.getPileupString((char)ref.getBase()), rods));
+        if ( outputInsertLength )
+            s.append(" ").append(insertLengthOutput(basePileup));
+        if ( SHOW_VERBOSE )
+            s.append(" ").append(createVerboseOutput(basePileup));
+        s.append("\n");
+
+        return s.toString();
+    }
+
+    // Given result of map function
+    @Override
+    public Integer reduceInit() { return 0; }
+
+    @Override
+    public Integer reduce(String value, Integer sum) {
+        out.print(value);
+        return sum + 1;
+    }
+
+    @Override
+    public Integer treeReduce(Integer lhs, Integer rhs) {
+        return lhs + rhs;
+    }
+
+    /**
+     * Get a string representation the reference-ordered data.
+     * @param tracker Container for the reference-ordered data.
+     * @return String representation of the reference-ordered data.
+     */
+    private String getReferenceOrderedData( RefMetaDataTracker tracker ) {
+        ArrayList<String> rodStrings = new ArrayList<String>();
+        for ( Feature datum : tracker.getValues(rods) ) {
+            rodStrings.add(datum.toString());
+        }
+        String rodString = Utils.join(", ", rodStrings);
+
+        if ( !rodString.equals("") )
+            rodString = "[ROD: " + rodString + "]";
+
+        return rodString;
+    }
+    private static String insertLengthOutput(final ReadBackedPileup pileup) {
+
+        Integer[] insertSizes=new Integer[pileup.depthOfCoverage()];
+
+        int i=0;
+        for ( PileupElement p : pileup ) {
+            insertSizes[i]=p.getRead().getInferredInsertSize();
+            ++i;
+        }
+        return Utils.join(",",insertSizes);
+    }
+
+
+    private static String createVerboseOutput(final ReadBackedPileup pileup) {
+        final StringBuilder sb = new StringBuilder();
+        boolean isFirst = true;
+
+        sb.append(pileup.getNumberOfDeletions());
+        sb.append(" ");
+
+        for ( PileupElement p : pileup ) {
+            if ( isFirst )
+                isFirst = false;
+            else
+                sb.append(",");
+            sb.append(p.getRead().getReadName());
+            sb.append(verboseDelimiter);
+            sb.append(p.getOffset());
+            sb.append(verboseDelimiter);
+            sb.append(p.getRead().getReadLength());
+            sb.append(verboseDelimiter);
+            sb.append(p.getRead().getMappingQuality());
+        }
+        return sb.toString();
+    }
+
+    @Override
+    public void onTraversalDone(Integer result) {
+        out.println("[REDUCE RESULT] Traversal result is: " + result);
+    }    
+}
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/tools/walkers/qc/PrintRODs.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/tools/walkers/qc/PrintRODs.java
new file mode 100644
index 0000000..22ab7d1
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/tools/walkers/qc/PrintRODs.java
@@ -0,0 +1,91 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.tools.walkers.qc;
+
+import htsjdk.tribble.Feature;
+import org.broadinstitute.gatk.utils.commandline.Input;
+import org.broadinstitute.gatk.utils.commandline.Output;
+import org.broadinstitute.gatk.utils.commandline.RodBinding;
+import org.broadinstitute.gatk.engine.CommandLineGATK;
+import org.broadinstitute.gatk.engine.contexts.AlignmentContext;
+import org.broadinstitute.gatk.engine.contexts.ReferenceContext;
+import org.broadinstitute.gatk.engine.refdata.RefMetaDataTracker;
+import org.broadinstitute.gatk.engine.walkers.RodWalker;
+import org.broadinstitute.gatk.utils.help.DocumentedGATKFeature;
+import org.broadinstitute.gatk.utils.help.HelpConstants;
+
+import java.io.PrintStream;
+
+/**
+ * Prints out all of the RODs in the input data set. Data is rendered using the toString() method
+ * of the given ROD.
+ */
+ at DocumentedGATKFeature( groupName = HelpConstants.DOCS_CAT_QC, extraDocs = {CommandLineGATK.class} )
+public class PrintRODs extends RodWalker<Integer, Integer> {
+    @Input(fullName="input", shortName = "input", doc="The input ROD which should be printed out.", required=true)
+    public RodBinding<Feature> input;
+
+    @Output
+    PrintStream out;
+
+    /**
+     * Initialize the number of loci processed to zero.
+     *
+     * @return 0
+     */
+    public Integer reduceInit() { return 0; }
+
+    /**
+     *
+     * @param tracker  the meta-data tracker
+     * @param ref      the reference base
+     * @param context  the context for the given locus
+     * @return 1 if the locus was successfully processed, 0 if otherwise
+     */
+    public Integer map(RefMetaDataTracker tracker, ReferenceContext ref, AlignmentContext context) {
+        if ( tracker == null )
+            return 0;
+
+        for ( Feature feature : tracker.getValues(Feature.class, context.getLocation()) ) {
+            out.println(feature.toString());
+        }
+
+        return 1;
+    }
+
+    /**
+     * Increment the number of rods processed.
+     *
+     * @param value result of the map.
+     * @param sum   accumulator for the reduce.
+     * @return the new number of rods processed.
+     */
+    public Integer reduce(Integer value, Integer sum) {
+        return sum + value;
+    }
+
+    public void onTraversalDone(Integer result) {}    
+}
\ No newline at end of file
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/tools/walkers/qc/QCRef.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/tools/walkers/qc/QCRef.java
new file mode 100644
index 0000000..ee8b68f
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/tools/walkers/qc/QCRef.java
@@ -0,0 +1,142 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.tools.walkers.qc;
+
+import htsjdk.samtools.reference.IndexedFastaSequenceFile;
+import htsjdk.samtools.reference.ReferenceSequence;
+import org.broadinstitute.gatk.utils.commandline.Output;
+import org.broadinstitute.gatk.engine.CommandLineGATK;
+import org.broadinstitute.gatk.engine.contexts.AlignmentContext;
+import org.broadinstitute.gatk.engine.contexts.ReferenceContext;
+import org.broadinstitute.gatk.engine.refdata.RefMetaDataTracker;
+import org.broadinstitute.gatk.engine.walkers.RefWalker;
+import org.broadinstitute.gatk.utils.BaseUtils;
+import org.broadinstitute.gatk.utils.exceptions.GATKException;
+import org.broadinstitute.gatk.utils.help.DocumentedGATKFeature;
+import org.broadinstitute.gatk.utils.help.HelpConstants;
+
+import java.io.PrintStream;
+
+/**
+ * Quality control for the reference fasta
+ *
+ *
+ * <h3>Input</h3>
+ * <p>
+ * One reference file only.  And optionally -L intervals
+ * </p>
+ *
+ * <h3>Output</h3>
+ * <p>
+ *     If ok, nothing, else will throw an exception at the site where there's been a problem
+ * </p>
+ *
+ * <h3>Examples</h3>
+ * <pre>
+ * java -Xmx2g -jar GenomeAnalysisTK.jar \
+ *   -R ref.fasta \
+ *   -T QCRef
+ * </pre>
+ *
+ */
+ at DocumentedGATKFeature( groupName = HelpConstants.DOCS_CAT_QC, extraDocs = {CommandLineGATK.class} )
+public class QCRef extends RefWalker<Integer, Integer> {
+    @Output
+    public PrintStream out;
+
+    String contigName = "";
+    int contigStart, contigEnd;
+    IndexedFastaSequenceFile uncachedRef;
+    byte[] uncachedBases;
+
+    @Override
+    public void initialize() {
+        super.initialize();    //To change body of overridden methods use File | Settings | File Templates.
+        uncachedRef = getToolkit().getReferenceDataSource().getReference();
+    }
+
+    private final void throwError(ReferenceContext ref, String message) {
+        throw new GATKException(String.format("Site %s failed: %s", ref.getLocus(), message));
+    }
+
+    public Integer map(RefMetaDataTracker tracker, ReferenceContext ref, AlignmentContext context) {
+        final String locusContigName = ref.getLocus().getContig();
+        if ( ! locusContigName.equals(contigName) ) {
+            contigName = locusContigName;
+            ReferenceSequence refSeq = uncachedRef.getSequence(contigName);
+            contigStart = 1;
+            contigEnd = contigStart + refSeq.length() - 1;
+            uncachedBases = uncachedRef.getSubsequenceAt(contigName, contigStart, contigEnd).getBases();
+            logger.info(String.format("Loading contig %s (%d-%d)", contigName, contigStart, contigEnd));
+        }
+
+        final byte refBase = ref.getBase();
+        if (! ( BaseUtils.isRegularBase(refBase) || isExtendFastaBase(refBase) ) )
+            throwError(ref, String.format("Refbase isn't a regular base (%d %c)", refBase, (char)refBase));
+
+        // check bases are equal
+        final int pos = (int)context.getPosition() - contigStart;
+        if ( pos > contigEnd )
+            throwError(ref, String.format("off contig (len=%d)", contigEnd));
+        final byte uncachedBase = uncachedBases[pos];
+
+        if ( uncachedBase != refBase )
+            throwError(ref, String.format("Provided refBase (%d %c) not equal to uncached one (%d %c)",
+                    refBase, (char)refBase, uncachedBase, (char)uncachedBase));
+
+        return 1;
+    }
+
+    private static final boolean isExtendFastaBase(final byte b) {
+        switch ( b ) {
+            case 'U':
+            case 'R':
+            case 'Y':
+            case 'K':
+            case 'M':
+            case 'S':
+            case 'W':
+            case 'B':
+            case 'D':
+            case 'H':
+            case 'V':
+            case 'N':
+            case 'X':
+            case '-':
+                return true;
+            default:
+                return false;
+        }
+    }
+
+    public Integer reduceInit() {
+        return 0;
+    }
+
+    public Integer reduce(Integer one, Integer sum) {
+        return one + sum;
+    }
+}
\ No newline at end of file
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/tools/walkers/qc/ReadClippingStats.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/tools/walkers/qc/ReadClippingStats.java
new file mode 100644
index 0000000..14a1de5
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/tools/walkers/qc/ReadClippingStats.java
@@ -0,0 +1,157 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.tools.walkers.qc;
+
+import htsjdk.samtools.CigarElement;
+import htsjdk.samtools.SAMReadGroupRecord;
+import org.broadinstitute.gatk.utils.commandline.Advanced;
+import org.broadinstitute.gatk.utils.commandline.Argument;
+import org.broadinstitute.gatk.utils.commandline.Output;
+import org.broadinstitute.gatk.engine.CommandLineGATK;
+import org.broadinstitute.gatk.engine.contexts.ReferenceContext;
+import org.broadinstitute.gatk.engine.refdata.RefMetaDataTracker;
+import org.broadinstitute.gatk.engine.walkers.DataSource;
+import org.broadinstitute.gatk.engine.walkers.ReadWalker;
+import org.broadinstitute.gatk.engine.walkers.Requires;
+import org.broadinstitute.gatk.utils.MathUtils;
+import org.broadinstitute.gatk.utils.Utils;
+import org.broadinstitute.gatk.utils.exceptions.UserException;
+import org.broadinstitute.gatk.utils.help.DocumentedGATKFeature;
+import org.broadinstitute.gatk.utils.help.HelpConstants;
+import org.broadinstitute.gatk.utils.sam.AlignmentUtils;
+import org.broadinstitute.gatk.utils.sam.GATKSAMRecord;
+
+import java.io.PrintStream;
+import java.util.Arrays;
+
+/**
+ * Read clipping statistics for all reads.
+ *
+ * Walks over the input reads, printing out statistics about the read length, number of clipping events, and length
+ * of the clipping to the output stream.
+ *
+ * Note: Ignores N's in the Cigar string.
+ *
+ * <h3>Input</h3>
+ * One or more BAM files
+ *
+ * <h3>Output</h3>
+ * A simple tabulated text file with read length and clipping statistics for every read (or every N reads if the "skip"
+ * option is used)
+ *
+ * User: depristo
+ * Date: May 5, 2010
+ * Time: 12:16:41 PM
+ */
+
+ at DocumentedGATKFeature( groupName = HelpConstants.DOCS_CAT_QC, extraDocs = {CommandLineGATK.class} )
+ at Requires({DataSource.READS})
+public class ReadClippingStats extends ReadWalker<ReadClippingStats.ReadClippingInfo,Integer> {
+    @Output
+    protected PrintStream out;
+
+    /**
+     * when this flag is set (default), statistics will be collected on unmapped reads as well. The default behavior
+     * is to ignore unmapped reads."
+     */
+    @Argument(fullName="include_unmapped", shortName="u", doc="Include unmapped reads in the analysis", required=false)
+    protected boolean INCLUDE_UNMAPPED = false;
+
+    /**
+     * print every read whose read number is divisible by SKIP. READ_NUMBER % SKIP == 0. First read in the file has read number = 1,
+     * second is 2, third is 3, ... A value of 1 means print every read. A value of 1000 means print every 1000th read.
+     */
+    @Advanced
+    @Argument(fullName="skip", shortName="skip", doc="Do not print all reads, skip some.", required=false)
+    protected int SKIP = 1;
+
+    public class ReadClippingInfo {
+        SAMReadGroupRecord rg;
+        int readLength, nClippingEvents, nClippedBases;
+    }
+
+    public ReadClippingInfo map(ReferenceContext ref, GATKSAMRecord read, RefMetaDataTracker metaDataTracker) {
+        if ( AlignmentUtils.isReadUnmapped(read) && !INCLUDE_UNMAPPED)
+            return null;
+
+        ReadClippingInfo info = new ReadClippingInfo();
+        info.rg = read.getReadGroup();
+
+        if ( info.rg == null ) throw new UserException.ReadMissingReadGroup(read);
+
+        for ( CigarElement elt : read.getCigar().getCigarElements() ) {
+            switch ( elt.getOperator()) {
+                case H : // ignore hard clips
+                case S : // soft clip
+                    info.nClippingEvents++;
+                    info.nClippedBases += elt.getLength();
+                    break;
+                case M :
+                case D : // deletion w.r.t. the reference
+                case P : // ignore pads
+                case I : // insertion w.r.t. the reference
+                case N : // reference skip (looks and gets processed just like a "deletion", just different logical meaning)
+                    break;
+                default : throw new IllegalStateException("Case statement didn't deal with cigar op: " + elt.getOperator());
+            }
+            info.readLength = read.getReadLength();
+        }
+
+        return info;  //To change body of implemented methods use File | Settings | File Templates.
+    }
+
+    /**
+     * Provide an initial value for reduce computations.
+     *
+     * @return Initial value of reduce.
+     */
+    public Integer reduceInit() {
+        out.println(Utils.join(" \t", Arrays.asList("ReadGroup", "ReadLength", "NClippingEvents", "NClippedBases", "PercentClipped")));
+        return 0;
+    }
+
+    /**
+     * Reduces a single map with the accumulator provided as the ReduceType.
+     *
+     * @param info  result of the map.
+     * @param sum   accumulator for the reduce.
+     * @return accumulator with result of the map taken into account.
+     */
+    public Integer reduce(ReadClippingInfo info, Integer sum) {
+        if ( info != null ) {
+            if ( sum % SKIP == 0 ) {
+                String id = info.rg.getReadGroupId();
+                out.printf("%s\t %d\t %d\t %d\t %.2f%n",
+                        id, info.readLength, info.nClippingEvents, info.nClippedBases,
+                        100.0 * MathUtils.ratio(info.nClippedBases, info.readLength));
+            }
+            return sum + 1;
+        } else {
+            return sum;
+        }
+    }
+
+}
\ No newline at end of file
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/tools/walkers/qc/RodSystemValidation.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/tools/walkers/qc/RodSystemValidation.java
new file mode 100644
index 0000000..5f1d396
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/tools/walkers/qc/RodSystemValidation.java
@@ -0,0 +1,182 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.tools.walkers.qc;
+
+import org.broadinstitute.gatk.utils.commandline.*;
+import org.broadinstitute.gatk.engine.contexts.AlignmentContext;
+import org.broadinstitute.gatk.engine.contexts.ReferenceContext;
+import org.broadinstitute.gatk.engine.datasources.rmd.ReferenceOrderedDataSource;
+import org.broadinstitute.gatk.engine.refdata.RefMetaDataTracker;
+import org.broadinstitute.gatk.engine.refdata.utils.RODRecordList;
+import org.broadinstitute.gatk.engine.walkers.Reference;
+import org.broadinstitute.gatk.engine.walkers.RodWalker;
+import org.broadinstitute.gatk.engine.walkers.Window;
+import org.broadinstitute.gatk.utils.exceptions.ReviewedGATKException;
+import htsjdk.variant.variantcontext.VariantContext;
+
+import java.io.*;
+import java.math.BigInteger;
+import java.security.MessageDigest;
+import java.security.NoSuchAlgorithmException;
+import java.util.Collection;
+import java.util.List;
+
+/**
+ * a walker for validating (in the style of validating pile-up) the ROD system.
+ */
+ at Hidden
+ at Reference(window=@Window(start=-40,stop=40))
+public class RodSystemValidation extends RodWalker<Integer,Integer> {
+
+    // the divider to use in some of the text output
+    private static final String DIVIDER = ",";
+
+    @Input(fullName="eval", shortName = "eval", doc="Input VCF eval file", required=true)
+    public List<RodBinding<VariantContext>> eval;
+
+    @Output
+    public PrintStream out;
+
+    @Argument(fullName="PerLocusEqual",required=false,doc="Should we check that all records at the same site produce equivilent variant contexts")
+    public boolean allRecordsVariantContextEquivalent = false;
+    
+    // used to calculate the MD5 of a file
+    MessageDigest digest = null;
+
+    // we sometimes need to know what rods the engine's seen
+    List<ReferenceOrderedDataSource> rodList;
+
+    /**
+     * emit the md5 sums for each of the input ROD files (will save up a lot of time if and when the ROD files change
+     * underneath us).
+     */
+    public void initialize() {
+        // setup the MD5-er
+        try {
+            digest = MessageDigest.getInstance("MD5");
+        } catch (NoSuchAlgorithmException e) {
+            throw new ReviewedGATKException("Unable to find MD5 checksumer");
+        }
+        out.println("Header:");
+        // enumerate the list of ROD's we've loaded
+        rodList = this.getToolkit().getRodDataSources();
+        for (ReferenceOrderedDataSource rod : rodList) {
+            out.println(rod.getName() + DIVIDER + rod.getType());
+            out.println(rod.getName() + DIVIDER + rod.getFile().getName());
+            out.println(rod.getName() + DIVIDER + md5sum(rod.getFile()));
+        }
+        out.println("Data:");
+    }
+
+    /**
+     *
+     * @param tracker the ref meta data tracker to get RODs
+     * @param ref reference context
+     * @param context the reads
+     * @return an 1 for each site with a rod(s), 0 otherwise
+     */
+    @Override
+    public Integer map(RefMetaDataTracker tracker, ReferenceContext ref, AlignmentContext context) {
+        int ret = 0;
+        if (tracker != null && tracker.getNTracksWithBoundFeatures() > 0) {
+            out.print(context.getLocation() + DIVIDER);
+            for (RODRecordList rod: tracker.getBoundRodTracks())
+                out.print(rod.getName() + DIVIDER);
+            out.println(";");
+            ret++;
+        }
+
+        // if the argument was set, check for equivalence
+        if (allRecordsVariantContextEquivalent && tracker != null) {
+            Collection<VariantContext> col = tracker.getValues(eval);
+            VariantContext con = null;
+            for (VariantContext contextInList : col)
+                if (con == null) con = contextInList;
+                else if (!con.equals(col)) out.println("FAIL: context " + col + " doesn't match " + con);
+        }
+        return ret;
+    }
+
+    /**
+     * Provide an initial value for reduce computations.
+     *
+     * @return Initial value of reduce.
+     */
+    @Override
+    public Integer reduceInit() {
+        return 0;
+    }
+
+    /**
+     * Reduces a single map with the accumulator provided as the ReduceType.
+     *
+     * @param value result of the map.
+     * @param sum   accumulator for the reduce.
+     * @return accumulator with result of the map taken into account.
+     */
+    @Override
+    public Integer reduce(Integer value, Integer sum) {
+        return value + sum;
+    }
+
+    @Override
+    public void onTraversalDone(Integer result) {
+        // Double check traversal result to make count is the same.
+        // TODO: Is this check necessary?
+        out.println("[REDUCE RESULT] Traversal result is: " + result);
+    }        
+
+    // shamelessly absconded and adapted from http://www.javalobby.org/java/forums/t84420.html
+    private String md5sum(File f) {
+        InputStream is;
+        try {
+            is = new FileInputStream(f);
+        } catch (FileNotFoundException e) {
+            return "Not a file";
+        }
+        byte[] buffer = new byte[8192];
+        int read = 0;
+        try {
+            while ((read = is.read(buffer)) > 0) {
+                digest.update(buffer, 0, read);
+            }
+            byte[] md5sum = digest.digest();
+            BigInteger bigInt = new BigInteger(1, md5sum);
+            return bigInt.toString(16);
+        }
+        catch (IOException e) {
+            throw new RuntimeException("Unable to process file for MD5", e);
+        }
+        finally {
+            try {
+                is.close();
+            }
+            catch (IOException e) {
+                throw new RuntimeException("Unable to close input stream for MD5 calculation", e);
+            }
+        }
+    }
+}
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/tools/walkers/readutils/ClipReads.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/tools/walkers/readutils/ClipReads.java
new file mode 100644
index 0000000..de3c0dc
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/tools/walkers/readutils/ClipReads.java
@@ -0,0 +1,607 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.tools.walkers.readutils;
+
+import htsjdk.samtools.reference.ReferenceSequence;
+import htsjdk.samtools.reference.ReferenceSequenceFile;
+import htsjdk.samtools.reference.ReferenceSequenceFileFactory;
+import htsjdk.samtools.util.StringUtil;
+import org.broadinstitute.gatk.utils.commandline.Advanced;
+import org.broadinstitute.gatk.utils.commandline.Argument;
+import org.broadinstitute.gatk.utils.commandline.Hidden;
+import org.broadinstitute.gatk.utils.commandline.Output;
+import org.broadinstitute.gatk.engine.CommandLineGATK;
+import org.broadinstitute.gatk.engine.contexts.ReferenceContext;
+import org.broadinstitute.gatk.engine.io.GATKSAMFileWriter;
+import org.broadinstitute.gatk.engine.refdata.RefMetaDataTracker;
+import org.broadinstitute.gatk.engine.walkers.DataSource;
+import org.broadinstitute.gatk.engine.walkers.ReadWalker;
+import org.broadinstitute.gatk.engine.walkers.Requires;
+import org.broadinstitute.gatk.utils.BaseUtils;
+import org.broadinstitute.gatk.utils.Utils;
+import org.broadinstitute.gatk.utils.clipping.ClippingOp;
+import org.broadinstitute.gatk.utils.clipping.ClippingRepresentation;
+import org.broadinstitute.gatk.utils.clipping.ReadClipper;
+import org.broadinstitute.gatk.utils.collections.Pair;
+import org.broadinstitute.gatk.utils.help.DocumentedGATKFeature;
+import org.broadinstitute.gatk.utils.help.HelpConstants;
+import org.broadinstitute.gatk.utils.sam.GATKSAMRecord;
+
+import java.io.File;
+import java.io.PrintStream;
+import java.util.*;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+/**
+ * Read clipping based on quality, position or sequence matching
+ *
+ * <p>This tool provides simple, powerful read clipping capabilities that allow you to remove low quality strings of bases, sections of reads, and reads containing user-provided sequences.</p> 
+ *
+ * <p>There are three options for clipping (quality, position and sequence), which can be used alone or in combination. In addition, you can also specify a clipping representation, which determines exactly how ClipReads applies clips to the reads (soft clips, writing Q0 base quality scores, etc.). Please note that you MUST specify at least one of the three clipping options, and specifying a clipping representation is not sufficient. If you do not specify a clipping option, the program wi [...]
+ *
+ * <dl>
+ *     <dt>Quality score based clipping</dt>
+ *     <dd>
+ *         Clip bases from the read in clipper from
+ *         <pre>argmax_x{ \sum{i = x + 1}^l (qTrimmingThreshold - qual)</pre>
+ *         to the end of the read.  This is copied from BWA.
+ *
+ *         Walk through the read from the end (in machine cycle order) to the beginning, calculating the
+ *         running sum of qTrimmingThreshold - qual.  While we do this, we track the maximum value of this
+ *         sum where the delta > 0.  After the loop, clipPoint is either -1 (don't do anything) or the
+ *         clipping index in the read (from the end).
+ *     </dd><br />
+ *     <dt>Cycle based clipping</dt>
+ *     <dd>Clips machine cycles from the read. Accepts a string of ranges of the form start1-end1,start2-end2, etc.
+ *     For each start/end pair, removes bases in machine cycles from start to end, inclusive. These are 1-based values (positions).
+ *     For example, 1-5,10-12 clips the first 5 bases, and then three bases at cycles 10, 11, and 12.
+ *     </dd><br />
+ *     <dt>Sequence matching</dt>
+ *     <dd>Clips bases from that exactly match one of a number of base sequences. This employs an exact match algorithm,
+ *     filtering only bases whose sequence exactly matches SEQ.</dd>
+ * </dl>
+ *
+ *
+ * <h3>Input</h3>
+ * <p>
+ *     Any number of BAM files.
+ * </p>
+ *
+ * <h3>Output</h3>
+ * <p>
+ *     A new BAM file containing all of the reads from the input BAMs with the user-specified clipping
+ *     operation applied to each read.
+ * </p>
+ * <p>
+ *     <h4>Summary output (console)</h4>
+ *     <pre>
+ *     Number of examined reads              13
+ *     Number of clipped reads               13
+ *     Percent of clipped reads              100.00
+ *     Number of examined bases              988
+ *     Number of clipped bases               126
+ *     Percent of clipped bases              12.75
+ *     Number of quality-score clipped bases 126
+ *     Number of range clipped bases         0
+ *     Number of sequence clipped bases      0
+ *     </pre>
+ * </p>
+ *
+ * <h3>Example</h3>
+ * <pre>
+ *   java -jar GenomeAnalysisTK.jar \
+ *     -T ClipReads \
+ *     -R reference.fasta \
+ *     -I original.bam \
+ *     -o clipped.bam \
+ *     -XF seqsToClip.fasta \
+ *     -X CCCCC \
+ *     -CT "1-5,11-15" \
+ *     -QT 10
+ * </pre>
+ * <p>The command line shown above will apply all three options in combination. See the detailed examples below to see how the choice of clipping representation affects the output.</p>
+ *
+ *     <h4>Detailed clipping examples</h4>
+ *     <p>Suppose we are given this read:</p>
+ *     <pre>
+ *     314KGAAXX090507:1:19:1420:1123#0        16      chrM    3116    29      76M     *       *       *
+ *          TAGGACCCGGGCCCCCCTCCCCAATCCTCCAACGCATATAGCGGCCGCGCCTTCCCCCGTAAATGATATCATCTCA
+ *          #################4?6/?2135;;;'1/=/<'B9;12;68?A79@,@==@9?=AAA3;A at B;A?B54;?ABA
+ *     </pre>
+ *
+ *     <p>If we are clipping reads with -QT 10 and -CR WRITE_NS, we get:</p>
+ *
+ *     <pre>
+ *     314KGAAXX090507:1:19:1420:1123#0        16      chrM    3116    29      76M     *       *       *
+ *          NNNNNNNNNNNNNNNNNTCCCCAATCCTCCAACGCATATAGCGGCCGCGCCTTCCCCCGTAAATGATATCATCTCA
+ *          #################4?6/?2135;;;'1/=/<'B9;12;68?A79@,@==@9?=AAA3;A at B;A?B54;?ABA
+ *     </pre>
+ *
+ *     <p>Whereas with -QT 10 -CR WRITE_Q0S:</p>
+ *     <pre>
+ *     314KGAAXX090507:1:19:1420:1123#0        16      chrM    3116    29      76M     *       *       *
+ *          TAGGACCCGGGCCCCCCTCCCCAATCCTCCAACGCATATAGCGGCCGCGCCTTCCCCCGTAAATGATATCATCTCA
+ *          !!!!!!!!!!!!!!!!!4?6/?2135;;;'1/=/<'B9;12;68?A79@,@==@9?=AAA3;A at B;A?B54;?ABA
+ *     </pre>
+ *
+ *     <p>Or -QT 10 -CR SOFTCLIP_BASES:</p>
+ *     <pre>
+ *     314KGAAXX090507:1:19:1420:1123#0        16      chrM    3133    29      17S59M  *       *       *
+ *          TAGGACCCGGGCCCCCCTCCCCAATCCTCCAACGCATATAGCGGCCGCGCCTTCCCCCGTAAATGATATCATCTCA
+ *          #################4?6/?2135;;;'1/=/<'B9;12;68?A79@,@==@9?=AAA3;A at B;A?B54;?ABA
+ *     </pre>
+ *
+
+ * @author Mark DePristo
+ * @since 2010
+ */
+ at DocumentedGATKFeature( groupName = HelpConstants.DOCS_CAT_DATA, extraDocs = {CommandLineGATK.class} )
+ at Requires({DataSource.READS})
+public class ClipReads extends ReadWalker<ClipReads.ReadClipperWithData, ClipReads.ClippingData> {
+    /**
+     * If provided, ClipReads will write summary statistics about the clipping operations applied to the reads in this file.
+     */
+    @Output(fullName = "outputStatistics", shortName = "os", doc = "File to output statistics", required = false, defaultToStdout = false)
+    PrintStream out = null;
+
+    /**
+     * The output SAM/BAM file will be written here
+     */
+    @Output(doc = "Write BAM output here")
+    GATKSAMFileWriter outputBam;
+
+    /**
+     * If a value > 0 is provided, then the quality score based read clipper will be applied to the reads using this
+     * quality score threshold.
+     */
+    @Argument(fullName = "qTrimmingThreshold", shortName = "QT", doc = "If provided, the Q-score clipper will be applied", required = false)
+    int qTrimmingThreshold = -1;
+
+    /**
+     * Clips machine cycles from the read. Accepts a string of ranges of the form start1-end1,start2-end2, etc.
+     * For each start/end pair, removes bases in machine cycles from start to end, inclusive. These are 1-based
+     * values (positions). For example, 1-5,10-12 clips the first 5 bases, and then three bases at cycles 10, 11,
+     * and 12.
+     */
+    @Argument(fullName = "cyclesToTrim", shortName = "CT", doc = "String indicating machine cycles to clip from the reads", required = false)
+    String cyclesToClipArg = null;
+
+    /**
+     * Reads the sequences in the provided FASTA file, and clip any bases that exactly match any of the
+     * sequences in the file.
+     */
+    @Argument(fullName = "clipSequencesFile", shortName = "XF", doc = "Remove sequences within reads matching the sequences in this FASTA file", required = false)
+    String clipSequenceFile = null;
+
+    /**
+     * Clips bases from the reads matching the provided SEQ.  Can be provided any number of times on the command line
+     */
+    @Argument(fullName = "clipSequence", shortName = "X", doc = "Remove sequences within reads matching this sequence", required = false)
+    String[] clipSequencesArgs = null;
+
+    /**
+     * The different values for this argument determines how ClipReads applies clips to the reads.  This can range
+     * from writing Ns over the clipped bases to hard clipping away the bases from the BAM.
+     */
+    @Argument(fullName = "clipRepresentation", shortName = "CR", doc = "How should we actually clip the bases?", required = false)
+    ClippingRepresentation clippingRepresentation = ClippingRepresentation.WRITE_NS;
+
+    @Hidden
+    @Advanced
+    @Argument(fullName="read", doc="", required=false)
+    String onlyDoRead = null;
+
+    /**
+     * List of sequence that should be clipped from the reads
+     */
+    List<SeqToClip> sequencesToClip = new ArrayList<SeqToClip>();
+
+    /**
+     * List of cycle start / stop pairs (0-based, stop is included in the cycle to remove) to clip from the reads
+     */
+    List<Pair<Integer, Integer>> cyclesToClip = null;
+
+    /**
+     * The initialize function.
+     */
+    public void initialize() {
+        if (qTrimmingThreshold >= 0) {
+            logger.info(String.format("Creating Q-score clipper with threshold %d", qTrimmingThreshold));
+        }
+
+        //
+        // Initialize the sequences to clip
+        //
+        if (clipSequencesArgs != null) {
+            int i = 0;
+            for (String toClip : clipSequencesArgs) {
+                i++;
+                ReferenceSequence rs = new ReferenceSequence("CMDLINE-" + i, -1, StringUtil.stringToBytes(toClip));
+                addSeqToClip(rs.getName(), rs.getBases());
+            }
+        }
+
+        if (clipSequenceFile != null) {
+            ReferenceSequenceFile rsf = ReferenceSequenceFileFactory.getReferenceSequenceFile(new File(clipSequenceFile));
+
+            while (true) {
+                ReferenceSequence rs = rsf.nextSequence();
+                if (rs == null)
+                    break;
+                else {
+                    addSeqToClip(rs.getName(), rs.getBases());
+                }
+            }
+        }
+
+
+        //
+        // Initialize the cycle ranges to clip
+        //
+        if (cyclesToClipArg != null) {
+            cyclesToClip = new ArrayList<Pair<Integer, Integer>>();
+            for (String range : cyclesToClipArg.split(",")) {
+                try {
+                    String[] elts = range.split("-");
+                    int start = Integer.parseInt(elts[0]) - 1;
+                    int stop = Integer.parseInt(elts[1]) - 1;
+
+                    if (start < 0) throw new Exception();
+                    if (stop < start) throw new Exception();
+
+                    logger.info(String.format("Creating cycle clipper %d-%d", start, stop));
+                    cyclesToClip.add(new Pair<Integer, Integer>(start, stop));
+                } catch (Exception e) {
+                    throw new RuntimeException("Badly formatted cyclesToClip argument: " + cyclesToClipArg);
+                }
+            }
+        }
+
+        if (outputBam != null) {
+            EnumSet<ClippingRepresentation> presorted = EnumSet.of(ClippingRepresentation.WRITE_NS, ClippingRepresentation.WRITE_NS_Q0S, ClippingRepresentation.WRITE_Q0S);
+            outputBam.setPresorted(presorted.contains(clippingRepresentation));
+        }
+    }
+
+    /**
+     * Helper function that adds a seq with name and bases (as bytes) to the list of sequences to be clipped
+     *
+     * @param name
+     * @param bases
+     */
+    private void addSeqToClip(String name, byte[] bases) {
+        SeqToClip clip = new SeqToClip(name, StringUtil.bytesToString(bases));
+        sequencesToClip.add(clip);
+        logger.info(String.format("Creating sequence clipper %s: %s/%s", clip.name, clip.seq, clip.revSeq));
+    }
+
+    /**
+     * The reads map function.
+     *
+     *
+     * @param ref  the reference bases that correspond to our read, if a reference was provided
+     * @param read the read itself, as a GATKSAMRecord
+     * @return the ReadClipper object describing what should be done to clip this read
+     */
+    public ReadClipperWithData map(ReferenceContext ref, GATKSAMRecord read, RefMetaDataTracker metaDataTracker) {
+        if ( onlyDoRead == null || read.getReadName().equals(onlyDoRead) ) {
+            if ( clippingRepresentation == ClippingRepresentation.HARDCLIP_BASES || clippingRepresentation == ClippingRepresentation.REVERT_SOFTCLIPPED_BASES )
+                read = ReadClipper.revertSoftClippedBases(read);
+            ReadClipperWithData clipper = new ReadClipperWithData(read, sequencesToClip);
+
+            //
+            // run all three clipping modules
+            //
+            clipBadQualityScores(clipper);
+            clipCycles(clipper);
+            clipSequences(clipper);
+            return clipper;
+        }
+
+        return null;
+    }
+
+    /**
+     * clip sequences from the reads that match all of the sequences in the global sequencesToClip variable.
+     * Adds ClippingOps for each clip to clipper.
+     *
+     * @param clipper
+     */
+    private void clipSequences(ReadClipperWithData clipper) {
+        if (sequencesToClip != null) {                // don't bother if we don't have any sequences to clip
+            GATKSAMRecord read = clipper.getRead();
+            ClippingData data = clipper.getData();
+
+            for (SeqToClip stc : sequencesToClip) {
+                // we have a pattern for both the forward and the reverse strands
+                Pattern pattern = read.getReadNegativeStrandFlag() ? stc.revPat : stc.fwdPat;
+                String bases = read.getReadString();
+                Matcher match = pattern.matcher(bases);
+
+                // keep clipping until match.find() says it can't find anything else
+                boolean found = true;   // go through at least once
+                while (found) {
+                    found = match.find();
+                    //System.out.printf("Matching %s against %s/%s => %b%n", bases, stc.seq, stc.revSeq, found);
+                    if (found) {
+                        int start = match.start();
+                        int stop = match.end() - 1;
+                        //ClippingOp op = new ClippingOp(ClippingOp.ClippingType.MATCHES_CLIP_SEQ, start, stop, stc.seq);
+                        ClippingOp op = new ClippingOp(start, stop);
+                        clipper.addOp(op);
+                        data.incSeqClippedBases(stc.seq, op.getLength());
+                    }
+                }
+            }
+            clipper.setData(data);
+        }
+    }
+
+    /**
+     * Convenence function that takes a read and the start / stop clipping positions based on the forward
+     * strand, and returns start/stop values appropriate for the strand of the read.
+     *
+     * @param read
+     * @param start
+     * @param stop
+     * @return
+     */
+    private Pair<Integer, Integer> strandAwarePositions(GATKSAMRecord read, int start, int stop) {
+        if (read.getReadNegativeStrandFlag())
+            return new Pair<Integer, Integer>(read.getReadLength() - stop - 1, read.getReadLength() - start - 1);
+        else
+            return new Pair<Integer, Integer>(start, stop);
+    }
+
+    /**
+     * clip bases at cycles between the ranges in cyclesToClip by adding appropriate ClippingOps to clipper.
+     *
+     * @param clipper
+     */
+    private void clipCycles(ReadClipperWithData clipper) {
+        if (cyclesToClip != null) {
+            GATKSAMRecord read = clipper.getRead();
+            ClippingData data = clipper.getData();
+
+            for (Pair<Integer, Integer> p : cyclesToClip) {   // iterate over each cycle range
+                int cycleStart = p.first;
+                int cycleStop = p.second;
+
+                if (cycleStart < read.getReadLength()) {
+                    // only try to clip if the cycleStart is less than the read's length
+                    if (cycleStop >= read.getReadLength())
+                        // we do tolerate [for convenience) clipping when the stop is beyond the end of the read
+                        cycleStop = read.getReadLength() - 1;
+
+                    Pair<Integer, Integer> startStop = strandAwarePositions(read, cycleStart, cycleStop);
+                    int start = startStop.first;
+                    int stop = startStop.second;
+
+                    //ClippingOp op = new ClippingOp(ClippingOp.ClippingType.WITHIN_CLIP_RANGE, start, stop, null);
+                    ClippingOp op = new ClippingOp(start, stop);
+                    clipper.addOp(op);
+                    data.incNRangeClippedBases(op.getLength());
+                }
+            }
+            clipper.setData(data);
+        }
+    }
+
+    /**
+     * Clip bases from the read in clipper from
+     * <p/>
+     * argmax_x{ \sum{i = x + 1}^l (qTrimmingThreshold - qual)
+     * <p/>
+     * to the end of the read.  This is blatantly stolen from BWA.
+     * <p/>
+     * Walk through the read from the end (in machine cycle order) to the beginning, calculating the
+     * running sum of qTrimmingThreshold - qual.  While we do this, we track the maximum value of this
+     * sum where the delta > 0.  After the loop, clipPoint is either -1 (don't do anything) or the
+     * clipping index in the read (from the end).
+     *
+     * @param clipper
+     */
+    private void clipBadQualityScores(ReadClipperWithData clipper) {
+        GATKSAMRecord read = clipper.getRead();
+        ClippingData data = clipper.getData();
+        int readLen = read.getReadBases().length;
+        byte[] quals = read.getBaseQualities();
+
+
+        int clipSum = 0, lastMax = -1, clipPoint = -1; // -1 means no clip
+        for (int i = readLen - 1; i >= 0; i--) {
+            int baseIndex = read.getReadNegativeStrandFlag() ? readLen - i - 1 : i;
+            byte qual = quals[baseIndex];
+            clipSum += (qTrimmingThreshold - qual);
+            if (clipSum >= 0 && (clipSum >= lastMax)) {
+                lastMax = clipSum;
+                clipPoint = baseIndex;
+            }
+        }
+
+        if (clipPoint != -1) {
+            int start = read.getReadNegativeStrandFlag() ? 0 : clipPoint;
+            int stop = read.getReadNegativeStrandFlag() ? clipPoint : readLen - 1;
+            //clipper.addOp(new ClippingOp(ClippingOp.ClippingType.LOW_Q_SCORES, start, stop, null));
+            ClippingOp op = new ClippingOp(start, stop);
+            clipper.addOp(op);
+            data.incNQClippedBases(op.getLength());
+        }
+        clipper.setData(data);
+    }
+
+    /**
+     * reduceInit is called once before any calls to the map function.  We use it here to setup the output
+     * bam file, if it was specified on the command line
+     *
+     * @return
+     */
+    public ClippingData reduceInit() {
+        return new ClippingData(sequencesToClip);
+    }
+
+    public ClippingData reduce(ReadClipperWithData clipper, ClippingData data) {
+        if ( clipper == null )
+            return data;
+
+        GATKSAMRecord clippedRead = clipper.clipRead(clippingRepresentation);
+        if (outputBam != null) {
+            outputBam.addAlignment(clippedRead);
+        } else {
+            out.println(clippedRead.format());
+        }
+
+        data.nTotalReads++;
+        data.nTotalBases += clipper.getRead().getReadLength();
+        if (clipper.wasClipped()) {
+            data.nClippedReads++;
+            data.addData(clipper.getData());
+        }
+        return data;
+    }
+
+    public void onTraversalDone(ClippingData data) {
+        if ( out != null )
+            out.printf(data.toString());
+    }
+
+    // --------------------------------------------------------------------------------------------------------------
+    //
+    // utility classes
+    //
+    // --------------------------------------------------------------------------------------------------------------
+
+    private static class SeqToClip {
+        String name;
+        String seq, revSeq;
+        Pattern fwdPat, revPat;
+
+        public SeqToClip(String name, String seq) {
+            this.name = name;
+            this.seq = seq;
+            this.fwdPat = Pattern.compile(seq, Pattern.CASE_INSENSITIVE);
+            this.revSeq = BaseUtils.simpleReverseComplement(seq);
+            this.revPat = Pattern.compile(revSeq, Pattern.CASE_INSENSITIVE);
+        }
+    }
+
+    public static class ClippingData {
+        public long nTotalReads = 0;
+        public long nTotalBases = 0;
+        public long nClippedReads = 0;
+        public long nClippedBases = 0;
+        public long nQClippedBases = 0;
+        public long nRangeClippedBases = 0;
+        public long nSeqClippedBases = 0;
+
+        HashMap<String, Long> seqClipCounts = new HashMap<String, Long>();
+
+        public ClippingData(List<SeqToClip> clipSeqs) {
+            for (SeqToClip clipSeq : clipSeqs) {
+                seqClipCounts.put(clipSeq.seq, 0L);
+            }
+        }
+
+        public void incNQClippedBases(int n) {
+            nQClippedBases += n;
+            nClippedBases += n;
+        }
+
+        public void incNRangeClippedBases(int n) {
+            nRangeClippedBases += n;
+            nClippedBases += n;
+        }
+
+        public void incSeqClippedBases(final String seq, int n) {
+            nSeqClippedBases += n;
+            nClippedBases += n;
+            seqClipCounts.put(seq, seqClipCounts.get(seq) + n);
+        }
+
+        public void addData (ClippingData data) {
+            nTotalReads += data.nTotalReads;
+            nTotalBases += data.nTotalBases;
+            nClippedReads += data.nClippedReads;
+            nClippedBases += data.nClippedBases;
+            nQClippedBases += data.nQClippedBases;
+            nRangeClippedBases += data.nRangeClippedBases;
+            nSeqClippedBases += data.nSeqClippedBases;
+
+            for (String seqClip : data.seqClipCounts.keySet()) {
+                Long count = data.seqClipCounts.get(seqClip);
+                if (seqClipCounts.containsKey(seqClip))
+                    count += seqClipCounts.get(seqClip);
+                seqClipCounts.put(seqClip, count);
+            }
+        }
+
+        public String toString() {
+            StringBuilder s = new StringBuilder();
+
+            s.append(Utils.dupString('-', 80) + "\n");
+            s.append(String.format("Number of examined reads              %d%n", nTotalReads));
+            s.append(String.format("Number of clipped reads               %d%n", nClippedReads));
+            s.append(String.format("Percent of clipped reads              %.2f%n", (100.0 * nClippedReads) / nTotalReads));
+            s.append(String.format("Number of examined bases              %d%n", nTotalBases));
+            s.append(String.format("Number of clipped bases               %d%n", nClippedBases));
+            s.append(String.format("Percent of clipped bases              %.2f%n", (100.0 * nClippedBases) / nTotalBases));
+            s.append(String.format("Number of quality-score clipped bases %d%n", nQClippedBases));
+            s.append(String.format("Number of range clipped bases         %d%n", nRangeClippedBases));
+            s.append(String.format("Number of sequence clipped bases      %d%n", nSeqClippedBases));
+
+            for (Map.Entry<String, Long> elt : seqClipCounts.entrySet()) {
+                s.append(String.format("  %8d clip sites matching %s%n", elt.getValue(), elt.getKey()));
+            }
+
+            s.append(Utils.dupString('-', 80) + "\n");
+            return s.toString();
+        }
+    }
+
+    public static class ReadClipperWithData extends ReadClipper {
+        private ClippingData data;
+
+        public ReadClipperWithData(GATKSAMRecord read, List<SeqToClip> clipSeqs) {
+            super(read);
+            data = new ClippingData(clipSeqs);
+        }
+
+        public ClippingData getData() {
+            return data;
+        }
+
+        public void setData(ClippingData data) {
+            this.data = data;
+        }
+
+        public void addData(ClippingData data) {
+            this.data.addData(data);
+        }
+    }
+
+
+}
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/tools/walkers/readutils/PrintReads.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/tools/walkers/readutils/PrintReads.java
new file mode 100644
index 0000000..f271fe9
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/tools/walkers/readutils/PrintReads.java
@@ -0,0 +1,316 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.tools.walkers.readutils;
+
+import htsjdk.samtools.SAMFileHeader;
+import htsjdk.samtools.SAMFileWriter;
+import htsjdk.samtools.SAMReadGroupRecord;
+import org.broadinstitute.gatk.engine.walkers.*;
+import org.broadinstitute.gatk.utils.commandline.Argument;
+import org.broadinstitute.gatk.utils.commandline.Hidden;
+import org.broadinstitute.gatk.utils.commandline.Output;
+import org.broadinstitute.gatk.engine.CommandLineGATK;
+import org.broadinstitute.gatk.engine.GenomeAnalysisEngine;
+import org.broadinstitute.gatk.engine.contexts.ReferenceContext;
+import org.broadinstitute.gatk.engine.io.GATKSAMFileWriter;
+import org.broadinstitute.gatk.engine.iterators.ReadTransformer;
+import org.broadinstitute.gatk.engine.iterators.ReadTransformersMode;
+import org.broadinstitute.gatk.engine.refdata.RefMetaDataTracker;
+import org.broadinstitute.gatk.utils.SampleUtils;
+import org.broadinstitute.gatk.utils.Utils;
+import org.broadinstitute.gatk.utils.baq.BAQ;
+import org.broadinstitute.gatk.utils.exceptions.UserException;
+import org.broadinstitute.gatk.utils.help.DocumentedGATKFeature;
+import org.broadinstitute.gatk.utils.help.HelpConstants;
+import org.broadinstitute.gatk.utils.sam.GATKSAMRecord;
+
+import java.io.File;
+import java.util.*;
+
+/**
+ * Renders, in SAM/BAM format, all reads from the input data set in the order in which they appear in the input file.
+ *
+ * <p>
+ * PrintReads can dynamically merge the contents of multiple input BAM files, resulting
+ * in merged output sorted in coordinate order.  Can also optionally filter reads based on the
+ * --read_filter command line argument.
+ * </p>
+ *
+ * <p>
+ * Note that when PrintReads is used as part of the Base Quality Score Recalibration workflow,
+ * it takes the --BQSR engine argument, which is listed under Inherited Arguments > CommandLineGATK below.
+ * </p>
+ *
+ * <h3>Input</h3>
+ * <p>
+ * One or more bam files.
+ * </p>
+ *
+ * <h3>Output</h3>
+ * <p>
+ * A single processed bam file.
+ * </p>
+ *
+ * <h3>Examples</h3>
+ * <pre>
+ * java -Xmx2g -jar GenomeAnalysisTK.jar \
+ *   -R ref.fasta \
+ *   -T PrintReads \
+ *   -o output.bam \
+ *   -I input1.bam \
+ *   -I input2.bam \
+ *   --read_filter MappingQualityZero
+ *
+ * // Prints the first 2000 reads in the BAM file
+ * java -Xmx2g -jar GenomeAnalysisTK.jar \
+ *   -R ref.fasta \
+ *   -T PrintReads \
+ *   -o output.bam \
+ *   -I input.bam \
+ *   -n 2000
+ *
+ * // Downsamples BAM file to 25%
+ * java -Xmx2g -jar GenomeAnalysisTK.jar \
+ *   -R ref.fasta \
+ *   -T PrintReads \
+ *   -o output.bam \
+ *   -I input.bam \
+ *   -dfrac 0.25
+ * </pre>
+ *
+ */
+ at DocumentedGATKFeature( groupName = HelpConstants.DOCS_CAT_DATA, extraDocs = {CommandLineGATK.class} )
+ at ReadTransformersMode(ApplicationTime = ReadTransformer.ApplicationTime.HANDLED_IN_WALKER)
+ at BAQMode(QualityMode = BAQ.QualityMode.ADD_TAG, ApplicationTime = ReadTransformer.ApplicationTime.HANDLED_IN_WALKER)
+ at Requires({DataSource.READS, DataSource.REFERENCE})
+public class PrintReads extends ReadWalker<GATKSAMRecord, SAMFileWriter> implements NanoSchedulable {
+
+    @Output(doc="Write output to this BAM filename instead of STDOUT")
+    GATKSAMFileWriter out;
+
+    @Argument(fullName = "readGroup", shortName = "readGroup", doc="Exclude all reads with this read group from the output", required = false)
+    String readGroup = null;
+
+    /**
+     * For example, --platform ILLUMINA or --platform 454.
+     */
+    @Argument(fullName = "platform", shortName = "platform", doc="Exclude all reads with this platform from the output", required = false)
+    String platform = null;
+
+    /**
+     * Only prints the first n reads of the file
+     */
+    @Argument(fullName = "number", shortName = "n", doc="Print the first n reads from the file, discarding the rest", required = false)
+    int nReadsToPrint = -1;
+
+    /**
+     * Only reads from samples listed in the provided file(s) will be included in the output.
+     */
+    @Argument(fullName="sample_file", shortName="sf", doc="File containing a list of samples (one per line). Can be specified multiple times", required=false)
+    public Set<File> sampleFile = new TreeSet<>();
+
+    /**
+     * Only reads from the sample(s) will be included in the output.
+     */
+    @Argument(fullName="sample_name", shortName="sn", doc="Sample name to be included in the analysis. Can be specified multiple times.", required=false)
+    public Set<String> sampleNames = new TreeSet<>();
+
+    /**
+     * Erase all extra attributes in the read but keep the read group information 
+     */
+    @Argument(fullName="simplify", shortName="s", doc="Simplify all reads.", required=false)
+    public boolean simplifyReads = false;
+
+    @Hidden
+    @Argument(fullName = "no_pg_tag", shortName = "npt", doc ="", required = false)
+    public boolean NO_PG_TAG = false;
+
+    List<ReadTransformer> readTransformers = Collections.emptyList();
+    private Set<String> readGroupsToKeep = Collections.emptySet();
+
+    public static final String PROGRAM_RECORD_NAME = "GATK PrintReads";   // The name that will go in the @PG tag
+    
+    Random random;
+
+
+    /**
+     * The initialize function.
+     */
+    public void initialize() {
+        final GenomeAnalysisEngine toolkit = getToolkit();
+
+        if ( toolkit != null )
+            readTransformers = toolkit.getReadTransformers();
+
+        //Sample names are case-insensitive
+        final TreeSet<String> samplesToChoose = new TreeSet<>(new Comparator<String>() {
+            @Override
+            public int compare(String a, String b) {
+                return a.compareToIgnoreCase(b);
+            }
+        });
+        Collection<String> samplesFromFile;
+        if (!sampleFile.isEmpty())  {
+            samplesFromFile = SampleUtils.getSamplesFromFiles(sampleFile);
+            samplesToChoose.addAll(samplesFromFile);
+        }
+
+        if (!sampleNames.isEmpty())
+            samplesToChoose.addAll(sampleNames);
+
+        random = GenomeAnalysisEngine.getRandomGenerator();
+
+        if (toolkit != null) {
+            final SAMFileHeader outputHeader = toolkit.getSAMFileHeader().clone();
+            readGroupsToKeep = determineReadGroupsOfInterest(outputHeader, samplesToChoose);
+
+            //If some read groups are to be excluded, remove them from the output header
+            pruneReadGroups(outputHeader);
+
+            //Add the program record (if appropriate) and set up the writer
+            final boolean preSorted = true;
+            if (toolkit.getArguments().BQSR_RECAL_FILE != null && !NO_PG_TAG ) {
+                Utils.setupWriter(out, toolkit, outputHeader, preSorted, this, PROGRAM_RECORD_NAME);
+            } else {
+                out.writeHeader(outputHeader);
+                out.setPresorted(preSorted);
+            }
+
+        }
+
+    }
+
+    /**
+     * The reads filter function.
+     *
+     * @param ref  the reference bases that correspond to our read, if a reference was provided
+     * @param read the read itself, as a GATKSAMRecord
+     * @return true if the read passes the filter, false if it doesn't
+     */
+    public boolean filter(ReferenceContext ref, GATKSAMRecord read) {
+        // check that the read belongs to an RG that we need to keep
+        if (!readGroupsToKeep.isEmpty()) {
+            final SAMReadGroupRecord readGroup = read.getReadGroup();
+            if (!readGroupsToKeep.contains(readGroup.getReadGroupId()))
+                return false;
+        }
+
+        // check if we've reached the output limit
+        if ( nReadsToPrint == 0 ) {
+            return false;          // n == 0 means we've printed all we needed.
+        }
+        else if (nReadsToPrint > 0) {
+            nReadsToPrint--;       // n > 0 means there are still reads to be printed.
+        }
+
+        return true;
+    }
+
+    /**
+     * The reads map function.
+     *
+     * @param ref  the reference bases that correspond to our read, if a reference was provided
+     * @param readIn the read itself, as a GATKSAMRecord
+     * @return the read itself
+     */
+    public GATKSAMRecord map( ReferenceContext ref, GATKSAMRecord readIn, RefMetaDataTracker metaDataTracker ) {
+        GATKSAMRecord workingRead = readIn;
+
+        for ( final ReadTransformer transformer : readTransformers ) {
+            workingRead = transformer.apply(workingRead);
+        }
+
+        if ( simplifyReads ) workingRead = workingRead.simplify();
+
+        return workingRead;
+    }
+
+    /**
+     * reduceInit is called once before any calls to the map function.  We use it here to setup the output
+     * bam file, if it was specified on the command line
+     *
+     * @return SAMFileWriter, set to the BAM output file if the command line option was set, null otherwise
+     */
+    public SAMFileWriter reduceInit() {
+        return out;
+    }
+
+    /**
+     * given a read and a output location, reduce by emitting the read
+     *
+     * @param read   the read itself
+     * @param output the output source
+     * @return the SAMFileWriter, so that the next reduce can emit to the same source
+     */
+    public SAMFileWriter reduce( GATKSAMRecord read, SAMFileWriter output ) {
+        output.addAlignment(read);
+        return output;
+    }
+
+    /**
+     * Determines the list of read groups that meet the user's criteria for inclusion (based on id, platform, or sample)
+     * @param header         the merged header for all input files
+     * @param samplesToKeep  the list of specific samples specified by the user
+     * @return               a Set of read group IDs that meet the user's criteria, empty if all RGs should be included
+     */
+    private Set<String> determineReadGroupsOfInterest(final SAMFileHeader header, final Set<String> samplesToKeep) {
+        //If no filter options that use read group information have been supplied, exit early
+        if (platform == null && readGroup == null && samplesToKeep.isEmpty())
+            return Collections.emptySet();
+
+        if  ( platform != null )
+            platform = platform.toUpperCase();
+
+        final Set<String> result = new HashSet<>();
+        for (final SAMReadGroupRecord rg : header.getReadGroups()) {
+            // To be eligible for output, a read group must:
+            //  NOT have an id that is blacklisted on the command line (note that String.equals(null) is false)
+            //  AND NOT have a platform that contains the blacklisted platform from the command line
+            //  AND have a sample that is whitelisted on the command line
+            if (!rg.getReadGroupId().equals(readGroup) &&
+                    (platform == null || !rg.getPlatform().toUpperCase().contains(platform)) &&
+                    (samplesToKeep.isEmpty() || samplesToKeep.contains(rg.getSample())))
+                result.add(rg.getReadGroupId());
+        }
+
+        if (result.isEmpty())
+            throw new UserException.BadArgumentValue("-sn/-sf/-platform/-readGroup", "No read groups remain after pruning based on the supplied parameters");
+
+        return result;
+    }
+
+    private void pruneReadGroups(final SAMFileHeader header) {
+        if (readGroupsToKeep.isEmpty())
+            return;
+
+        final List<SAMReadGroupRecord> readGroups = new ArrayList<>();
+        for (final SAMReadGroupRecord rg : header.getReadGroups()) {
+            if (readGroupsToKeep.contains(rg.getReadGroupId()))
+                readGroups.add(rg);
+        }
+        header.setReadGroups(readGroups);
+    }
+}
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/tools/walkers/readutils/ReadAdaptorTrimmer.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/tools/walkers/readutils/ReadAdaptorTrimmer.java
new file mode 100644
index 0000000..6f0ee85
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/tools/walkers/readutils/ReadAdaptorTrimmer.java
@@ -0,0 +1,395 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.tools.walkers.readutils;
+
+import com.google.java.contract.Ensures;
+import com.google.java.contract.Requires;
+import htsjdk.samtools.SAMFileWriter;
+import org.apache.log4j.Logger;
+import org.broadinstitute.gatk.engine.walkers.NanoSchedulable;
+import org.broadinstitute.gatk.engine.walkers.PartitionBy;
+import org.broadinstitute.gatk.engine.walkers.PartitionType;
+import org.broadinstitute.gatk.engine.walkers.ReadWalker;
+import org.broadinstitute.gatk.utils.commandline.Advanced;
+import org.broadinstitute.gatk.utils.commandline.Argument;
+import org.broadinstitute.gatk.utils.commandline.Hidden;
+import org.broadinstitute.gatk.utils.commandline.Output;
+import org.broadinstitute.gatk.engine.CommandLineGATK;
+import org.broadinstitute.gatk.engine.contexts.ReferenceContext;
+import org.broadinstitute.gatk.engine.refdata.RefMetaDataTracker;
+import org.broadinstitute.gatk.utils.BaseUtils;
+import org.broadinstitute.gatk.utils.collections.Pair;
+import org.broadinstitute.gatk.utils.help.DocumentedGATKFeature;
+import org.broadinstitute.gatk.utils.help.HelpConstants;
+import org.broadinstitute.gatk.utils.sam.GATKSAMRecord;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+/**
+ * Utility tool to blindly strip base adaptors. Main application is for FASTQ/unaligned BAM pre-processing where libraries
+ * have very short inserts, and hence a substantial part of the sequencing data will have adaptor sequence present.
+ * <p>
+ * By design, tool will only work for Illumina-like library constructs, where the typical library architecture is:
+ * [Adaptor 1]-[Genomic Insert]-[Adaptor 2 (index/barcode)]
+ * <p>
+ * It is assumed that when data is paired, one read will span the forward strand and one read will span the reverse strand.
+ * Hence, when specifying adaptors they should be specified as both forward and reverse-complement to make sure they're removed in all cases.
+ * By design, as well, "circular" constructions where a read can have an insert, then adaptor, then more genomic insert, are not supported.
+ * When an adaptor is detected, all bases downstream from it (i.e. in the 3' direction) will be removed.
+ * Adaptor detection is carried out by looking for overlaps between forward and reverse reads in a pair.
+ * If a sufficiently high overlap is found, the insert size is computed and if insert size < read lengths adaptor bases are removed from reads.
+ *
+ * Advantages over ReadClipper:
+ * - No previous knowledge of adaptors or library structure is necessary
+ *
+ * Advantages over 3rd party tools like SeqPrep:
+ * - Can do BAM streaming instead of having to convert to fastq
+ * - No need to merge reads - merging reads can have some advantages, but complicates downstream processing and loses information that can be used,
+ *   e.g. in variant calling
+ * <p>
+ *
+ * <h2>Input</h2>
+ * <p>
+ * The input read data in BAM format. Read data MUST be in query name ordering as produced, for example with Picard's FastqToBam
+ *
+ * <h2>Output</h2>
+ * <p>
+ * A merged BAM file with unaligned reads
+ * </p>
+ *
+ * <h2>Examples</h2>
+ * <pre>
+ * java -Xmx4g -jar GenomeAnalysisTK.jar \
+ *   -T ReadAdaptorTrimmer \
+ *   -I my_reads.bam \
+ *   -R resources/Homo_sapiens_assembly18.fasta \
+ *   -o trimmed_Reads.bam
+ * </pre>
+ */
+
+ at DocumentedGATKFeature( groupName = HelpConstants.DOCS_CAT_DATA, extraDocs = {CommandLineGATK.class} )
+ at PartitionBy(PartitionType.READ)
+public class ReadAdaptorTrimmer extends ReadWalker<List<GATKSAMRecord>, SAMFileWriter> implements NanoSchedulable {
+    @Output(doc="Write output to this BAM filename instead of STDOUT", required = false)
+    SAMFileWriter out;
+
+     /**
+     * Only prints the first n reads of the file - for short testing
+     */
+     @Hidden
+    @Argument(fullName = "number", shortName = "n", doc="Print the first n reads from the file, discarding the rest", required = false)
+    int nReadsToPrint = -1;
+
+    /**
+     * Argument to control strictness of match between forward and reverse reads - by default, we require 15 matches between them to declare
+     * an overlap.
+     */
+    @Advanced
+    @Argument(fullName = "minMatches", shortName = "minMatches", doc="Minimum number of substring matches to detect pair overlaps", required = false)
+    int minMatchesForOverlap = 15;
+
+
+    /**
+     * If true, this argument will make the walker discard unpaired reads instead of erroring out.
+     */
+    @Advanced
+    @Argument(fullName = "removeUnpairedReads", shortName = "removeUnpairedReads", doc="Remove unpaired reads instead of erroring out", required = false)
+    boolean cleanUnpairedReads = false;
+
+     /**
+     * private class members
+     */
+    private GATKSAMRecord firstReadInPair;
+    private TrimStats trimStats = new TrimStats();
+
+    static class TrimStats {
+        long numReadsProcessed;
+        long numReadsWithAdaptorTrimmed;
+        long numUnpairedReadsFound;
+    }
+
+   /**
+     * The reads filter function.
+     *
+     * @param ref  the reference bases that correspond to our read, if a reference was provided
+     * @param read the read itself, as a GATKSAMRecord
+     * @return true if the read passes the filter, false if it doesn't
+     */
+    public boolean filter(ReferenceContext ref, GATKSAMRecord read) {
+         // check if we've reached the output limit
+        if ( nReadsToPrint == 0 ) {
+            return false;          // n == 0 means we've printed all we needed.
+        }
+        else if (nReadsToPrint > 0) {
+            nReadsToPrint--;       // n > 0 means there are still reads to be printed.
+        }
+        return true;
+    }
+    /**
+     * reduceInit is called once before any calls to the map function.  We use it here to setup the output
+     * bam file, if it was specified on the command line
+     *
+     * @return SAMFileWriter, set to the BAM output file if the command line option was set, null otherwise
+     */
+    public SAMFileWriter reduceInit() {
+        return out;
+    }
+
+    public List<GATKSAMRecord> map( final ReferenceContext ref, final GATKSAMRecord readIn, final RefMetaDataTracker metaDataTracker ) {
+
+
+        final List<GATKSAMRecord> readsToEmit = new ArrayList<GATKSAMRecord>();
+
+
+        // cache first read in pair if flag set.
+        if (readIn.getFirstOfPairFlag()) {
+            firstReadInPair = GATKSAMRecord.emptyRead(readIn);
+            firstReadInPair.setReadString(readIn.getReadString());
+            firstReadInPair.setReadName(readIn.getReadName());
+            firstReadInPair.setBaseQualities(readIn.getBaseQualities());
+        }
+        else {
+            if (!readIn.getReadName().equals(firstReadInPair.getReadName()))  {
+                if (cleanUnpairedReads) {
+                    trimStats.numUnpairedReadsFound++;
+                    return readsToEmit;
+                }
+                else // by default require that reads be completely paired
+                    throw new IllegalStateException("Second read in pair must follow first read in pair: data not ordered?");
+            }
+
+            final int oldLength1 = firstReadInPair.getReadLength();
+            final int oldLength2 = readIn.getReadLength();
+            // try to strip any adaptor sequence in read pair
+            final Integer result = trimReads(firstReadInPair, readIn, minMatchesForOverlap, logger);
+
+            if (logger.isDebugEnabled()) {
+                if (result == null)
+                    logger.debug("No overlap found, insert size cannot be computed");
+                else
+                    logger.debug("Insert size estimate = " + result);
+
+            }
+
+
+            readsToEmit.add(firstReadInPair);
+            readsToEmit.add(readIn);
+
+            if (oldLength1 != firstReadInPair.getReadLength())
+                trimStats.numReadsWithAdaptorTrimmed++;
+            if (oldLength2 != readIn.getReadLength())
+                trimStats.numReadsWithAdaptorTrimmed++;
+
+         }
+
+
+        trimStats.numReadsProcessed++;
+        return readsToEmit;
+
+    }
+
+    /**
+     * given a read and a output location, reduce by emitting the read
+     *
+     * @param readsToEmit   the read itself
+     * @param output the output source
+     * @return the SAMFileWriter, so that the next reduce can emit to the same source
+     */
+    public SAMFileWriter reduce( final List<GATKSAMRecord> readsToEmit, final SAMFileWriter output ) {
+        for (final GATKSAMRecord read : readsToEmit)
+             output.addAlignment(read);
+
+        return output;
+    }
+
+    @Override
+    public void onTraversalDone(SAMFileWriter output) {
+
+        logger.info("Finished Trimming:");
+        logger.info("Number of processed reads:                     "+ trimStats.numReadsProcessed);
+        logger.info("Number of reads with adaptor sequence trimmed: "+ trimStats.numReadsWithAdaptorTrimmed);
+        if (cleanUnpairedReads)
+            logger.info("Number of unpaired reads thrown out: "+ trimStats.numUnpairedReadsFound);
+    }
+
+
+    /**
+     *
+     * Workhorse routines...
+     *
+     */
+        /**
+         * Core routine that does most underlying work for walker. Takes two reads and looks for overlaps in them.
+         * An overlap is defined as a contiguous chunk of N bases that matches reverse-complement between reads.
+         * Currently, the only insert structure that it will look for overlaps is as follows:
+         * CASE 1: Insert shorter than read length:
+         * 3' XXXXXXXXXXXXXXXX 5'            (second read)
+         * 5'      YYYYYYYYYYYYYYYY 3'       (first read)
+         *         ***********
+         *
+         * In this case, if X and Y are complements at the 11 positions marked by *, routine will do the following
+         * iff minMatchesForOverlap <= 11:
+         *  a) Cleave adaptor from end of second read (leftmost dangling part in diagram above)
+         *  b) Cleave adaptor from end of first read (rightmost part in diagram).
+         *
+         * CASE 2: Insert size >= read length:
+         * 3'             XXXXXXXXXXXXXXXX 5'           (second read)
+         * 5'      YYYYYYYYYYYYYYYY 3'                  (first read)
+         *                *********                        (overlap)
+         *
+         * In this case, no trimming is done and reads are left unchanged
+         * @param first                      (I/O) First read in pair - read contents (bases/quals) can be modified if adaptor is detected
+         * @param second                     (I/O) Second read in pair - read contents (bases/quals) can be modified if adaptor is detected
+         * @param minMatchesForOverlap       Reads need to match in these # of bases to be joined
+         * @return                           Offset between second and first read.
+         *                                   If there's no detectable offset, return Null
+         */
+    @Requires({"first != null","second != null","minMatchesForOverlap>0"})
+    protected static Integer trimReads(final GATKSAMRecord first,
+                                       final GATKSAMRecord second,
+                                       final int minMatchesForOverlap,
+                                       final Logger logger) {
+
+        final Integer insertSize = estimateInsertSize(first.getReadBases(), second.getReadBases(),
+                minMatchesForOverlap, logger);
+
+        if (insertSize == null)
+            return insertSize;
+        if (insertSize < first.getReadLength()) {
+            // trim adaptor sequence from read
+            first.setReadBases(Arrays.copyOfRange(first.getReadBases(),0,insertSize));
+            first.setBaseQualities(Arrays.copyOfRange(first.getBaseQualities(),0,insertSize));
+        }
+        if (insertSize < second.getReadLength()) {
+            // trim adaptor sequence from read
+            second.setReadBases(Arrays.copyOfRange(second.getReadBases(),0,insertSize));
+            second.setBaseQualities(Arrays.copyOfRange(second.getBaseQualities(),0,insertSize));
+        }
+        return insertSize;
+    }
+
+    /**
+    * Brain-dead implementation of an aligner of two sequences, where it's assumed that there might be an overlap
+    * from the first into the second. From this, an estimate of insert size is performed and returned
+    * Assumes that reads come in reverse direction, so one of the base sequences needs to be reverse-complemented.]
+    *
+    * @param firstRead                           Bytes from first read
+    * @param secondRead                          Bytes from second read (reverse direction)
+    * @return                                  Estimated insert size based on offset between first and second read.
+    *                                          If no overlap can be detected, return null
+    */
+
+    @Requires({"firstRead != null","secondRead != null","minMatches>0","firstRead.length == secondRead.length"})
+    protected static Integer estimateInsertSize(final byte[] firstRead,
+                                                                final byte[] secondRead,
+                                                                final int minMatches,
+                                                                final Logger logger) {
+        final byte[] firstBases = firstRead;
+        final byte[] secondBases = BaseUtils.simpleReverseComplement(secondRead);
+
+        final Pair<Integer,Integer> overlaps = findOverlappingSequence(firstBases, secondBases);
+        final int bestOffset = overlaps.first;
+        final int maxScore = overlaps.second;
+        if ( logger.isDebugEnabled()) {
+            String sb="", s1 = new String(firstBases), s2 = new String(secondBases);
+            for (int k=0; k < Math.abs(bestOffset); k++) sb+=" ";
+            if (maxScore >= minMatches) {
+                logger.debug(String.format("Match, Max Score = %d, best offset = %d\n",maxScore, bestOffset));
+                if (bestOffset>0)
+                    s2 = sb+s2;
+                else
+                    s1 = sb+s1;
+            }
+            else logger.debug("NoMatch:");
+            logger.debug("R1:"+s1);
+            logger.debug("R2:"+s2);
+
+
+        }
+
+        if (maxScore < minMatches)
+            return null; // no overlap detected
+
+        return bestOffset+secondRead.length;
+
+
+    }
+
+
+     /**
+     * Tries to find overlapping sequence between two reads, and computes offset between them
+      * For each possible offset, computes matching score, which is = MATCH_SCORE*Num_matches + MISMATCH_SCORE*num_mismatches
+      * (like SW with infinite gap penalties).
+     * @param first                              First read bytes
+     * @param second                             Second read bytes
+     * @return                                   Pair of integers (x,y). x = best offset between reads, y = corresponding score
+     */
+    @Requires({"first != null","second != null"})
+    @Ensures("result != null")
+    protected static Pair<Integer,Integer> findOverlappingSequence(final byte[] first,
+                                                 final byte[] second) {
+        final int MATCH_SCORE = 1;
+        final int MISMATCH_SCORE = -1;
+        // try every possible offset - O(N^2) algorithm
+
+        // In case of following structure,
+        //      111111111
+        // 222222222
+        // computed offset will be negative (=-5 in this case).
+        // If however,
+        //   111111111
+        //      222222222
+        // then offset will be positive (=3 in this case)
+        int maxScore = 0, bestOffset =0;
+        for (int offset = -second.length; offset < first.length; offset++) {
+            int score = 0;
+            // compute start index for each array
+            int ind1 = (offset<0)?0:offset;
+            int ind2 = (offset<0)?-offset:0;
+            for (int k=0; k < Math.min(first.length, second.length) ; k++) {
+                if (ind1 >= first.length)
+                    break;
+                if (ind2 >= second.length )
+                    break;
+                if (first[ind1] != 'N' && second[ind2] != 'N')  {
+                    if (first[ind1] == second[ind2])
+                        score += MATCH_SCORE;
+                    else
+                        score += MISMATCH_SCORE;
+                }
+                ind1++;
+                ind2++;
+            }
+            if (score > maxScore) {
+                maxScore = score;
+                bestOffset = offset;
+            }
+        }
+        return new Pair<Integer, Integer>(bestOffset,maxScore);
+    }
+
+}
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/tools/walkers/readutils/SplitSamFile.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/tools/walkers/readutils/SplitSamFile.java
new file mode 100644
index 0000000..f4ee4a4
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/tools/walkers/readutils/SplitSamFile.java
@@ -0,0 +1,151 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.tools.walkers.readutils;
+
+import htsjdk.samtools.SAMFileHeader;
+import htsjdk.samtools.SAMFileWriter;
+import htsjdk.samtools.SAMReadGroupRecord;
+import htsjdk.samtools.SAMRecord;
+import org.apache.log4j.Logger;
+import org.broadinstitute.gatk.utils.commandline.Argument;
+import org.broadinstitute.gatk.engine.CommandLineGATK;
+import org.broadinstitute.gatk.engine.contexts.ReferenceContext;
+import org.broadinstitute.gatk.engine.refdata.RefMetaDataTracker;
+import org.broadinstitute.gatk.engine.walkers.DataSource;
+import org.broadinstitute.gatk.engine.walkers.ReadWalker;
+import org.broadinstitute.gatk.engine.walkers.Requires;
+import org.broadinstitute.gatk.engine.walkers.WalkerName;
+import org.broadinstitute.gatk.utils.help.DocumentedGATKFeature;
+import org.broadinstitute.gatk.utils.help.HelpConstants;
+import org.broadinstitute.gatk.utils.sam.GATKSAMRecord;
+import org.broadinstitute.gatk.utils.sam.ReadUtils;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * Divides the input data set into separate BAM files, one for each sample in the input data set.  The split
+ * files are named concatenating the sample name to the end of the provided outputRoot command-line argument.
+ */
+ at DocumentedGATKFeature( groupName = HelpConstants.DOCS_CAT_DATA, extraDocs = {CommandLineGATK.class} )
+ at WalkerName("SplitSamFile")
+ at Requires({DataSource.READS})
+public class SplitSamFile extends ReadWalker<SAMRecord, Map<String, SAMFileWriter>> {
+    @Argument(fullName="outputRoot", doc="output BAM file", required=false)
+    public String outputRoot = "";
+
+    private static final Logger logger = Logger.getLogger(SplitSamFile.class);
+    private static final String VERSION = "0.0.1";
+
+    @Override
+    public void initialize() {
+        logger.info("SplitSamFile version: " + VERSION);
+    }
+
+    @Override
+    public SAMRecord map(ReferenceContext ref, GATKSAMRecord read, RefMetaDataTracker metaDataTracker) {
+        return read;
+    }
+
+    // --------------------------------------------------------------------------------------------------------------
+    //
+    // Standard I/O routines
+    //
+    // --------------------------------------------------------------------------------------------------------------
+    @Override
+    public void onTraversalDone(Map<String, SAMFileWriter> outputs) {
+        for ( SAMFileWriter output : outputs.values() ) {
+            output.close();
+        }
+    }
+
+    @Override
+    public Map<String, SAMFileWriter> reduceInit() {
+        HashMap<String, SAMFileHeader> headers = new HashMap<>();
+        for ( SAMReadGroupRecord readGroup : this.getToolkit().getSAMFileHeader().getReadGroups()) {
+            final String sample = readGroup.getSample();
+            if ( ! headers.containsKey(sample) ) {
+                SAMFileHeader header = duplicateSAMFileHeader(this.getToolkit().getSAMFileHeader());
+                logger.debug(String.format("Creating BAM header for sample %s", sample));
+                ArrayList<SAMReadGroupRecord> readGroups = new ArrayList<>();
+                header.setReadGroups(readGroups);
+                headers.put(sample, header);
+            }
+
+            SAMFileHeader header = headers.get(sample);
+            List<SAMReadGroupRecord> newReadGroups = new ArrayList<>(header.getReadGroups());
+            newReadGroups.add(readGroup);
+            header.setReadGroups(newReadGroups);
+        }
+
+        HashMap<String, SAMFileWriter> outputs = new HashMap<>();
+        for ( Map.Entry<String, SAMFileHeader> elt : headers.entrySet() ) {
+            final String sample = elt.getKey();
+            final String filename = outputRoot + sample + ".bam";
+            logger.info(String.format("Creating BAM output file %s for sample %s", filename, sample));
+
+            final SAMFileWriter output = ReadUtils.createSAMFileWriter(filename, getToolkit(), elt.getValue());
+            outputs.put(sample, output);
+        }
+
+        return outputs;
+    }
+
+    /**
+     * Write out the read
+     */
+    @Override
+    public Map<String, SAMFileWriter> reduce(SAMRecord read, Map<String, SAMFileWriter> outputs) {
+        final String sample = read.getReadGroup().getSample();
+        SAMFileWriter output = outputs.get(sample);
+
+        if ( output != null ) {
+            output.addAlignment(read);
+        } else {
+            throw new RuntimeException(String.format("Read group %s not present in header but found in read %s", read.getReadGroup().getReadGroupId(), read.getReadName()));
+        }
+
+        return outputs;
+    }
+
+    public static SAMFileHeader duplicateSAMFileHeader(SAMFileHeader toCopy) {
+        SAMFileHeader copy = new SAMFileHeader();
+
+        copy.setSortOrder(toCopy.getSortOrder());
+        copy.setGroupOrder(toCopy.getGroupOrder());
+        copy.setProgramRecords(toCopy.getProgramRecords());
+        copy.setReadGroups(toCopy.getReadGroups());
+        copy.setSequenceDictionary(toCopy.getSequenceDictionary());
+
+        for (Map.Entry<String, String> e : toCopy.getAttributes())
+            copy.setAttribute(e.getKey(), e.getValue());
+
+        return copy;
+    }
+
+}
\ No newline at end of file
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/tools/walkers/varianteval/VariantEval.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/tools/walkers/varianteval/VariantEval.java
new file mode 100644
index 0000000..67c1fcb
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/tools/walkers/varianteval/VariantEval.java
@@ -0,0 +1,666 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.tools.walkers.varianteval;
+
+import com.google.java.contract.Requires;
+import htsjdk.samtools.reference.IndexedFastaSequenceFile;
+import htsjdk.samtools.util.IntervalTree;
+import htsjdk.samtools.SAMSequenceRecord;
+import org.apache.log4j.Logger;
+import htsjdk.tribble.Feature;
+import org.broadinstitute.gatk.engine.walkers.*;
+import org.broadinstitute.gatk.utils.commandline.*;
+import org.broadinstitute.gatk.engine.CommandLineGATK;
+import org.broadinstitute.gatk.engine.GenomeAnalysisEngine;
+import org.broadinstitute.gatk.engine.arguments.DbsnpArgumentCollection;
+import org.broadinstitute.gatk.engine.contexts.AlignmentContext;
+import org.broadinstitute.gatk.engine.contexts.ReferenceContext;
+import org.broadinstitute.gatk.engine.refdata.RefMetaDataTracker;
+import org.broadinstitute.gatk.tools.walkers.varianteval.evaluators.VariantEvaluator;
+import org.broadinstitute.gatk.tools.walkers.varianteval.stratifications.IntervalStratification;
+import org.broadinstitute.gatk.tools.walkers.varianteval.stratifications.VariantStratifier;
+import org.broadinstitute.gatk.tools.walkers.varianteval.stratifications.manager.StratificationManager;
+import org.broadinstitute.gatk.tools.walkers.varianteval.util.EvaluationContext;
+import org.broadinstitute.gatk.tools.walkers.varianteval.util.SortableJexlVCMatchExp;
+import org.broadinstitute.gatk.tools.walkers.varianteval.util.VariantEvalUtils;
+import org.broadinstitute.gatk.utils.GenomeLoc;
+import org.broadinstitute.gatk.utils.SampleUtils;
+import org.broadinstitute.gatk.utils.help.HelpConstants;
+import org.broadinstitute.gatk.utils.variant.GATKVCFUtils;
+import org.broadinstitute.gatk.utils.variant.GATKVariantContextUtils;
+import htsjdk.variant.vcf.VCFHeader;
+import org.broadinstitute.gatk.utils.exceptions.ReviewedGATKException;
+import org.broadinstitute.gatk.utils.exceptions.UserException;
+import org.broadinstitute.gatk.utils.help.DocumentedGATKFeature;
+import htsjdk.variant.variantcontext.Allele;
+import htsjdk.variant.variantcontext.VariantContext;
+import htsjdk.variant.variantcontext.VariantContextBuilder;
+import htsjdk.variant.variantcontext.VariantContextUtils;
+
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.PrintStream;
+import java.util.*;
+
+/**
+ * General-purpose tool for variant evaluation (% in dbSNP, genotype concordance, Ti/Tv ratios, and a lot more)
+ *
+ * <p>
+ * Given a variant callset, it is common to calculate various quality control metrics. These metrics include the number of
+ * raw or filtered SNP counts; ratio of transition mutations to transversions; concordance of a particular sample's calls
+ * to a genotyping chip; number of singletons per sample; etc. Furthermore, it is often useful to stratify these metrics
+ * by various criteria like functional class (missense, nonsense, silent), whether the site is CpG site, the amino acid
+ * degeneracy of the site, etc. VariantEval facilitates these calculations in two ways: by providing several built-in
+ * evaluation and stratification modules, and by providing a framework that permits the easy development of new evaluation
+ * and stratification modules.
+ *
+ * <h3>Input</h3>
+ * <p>
+ * One or more variant sets to evaluate plus any number of comparison sets.
+ * </p>
+ *
+ * <h3>Output</h3>
+ * <p>
+ * Evaluation tables detailing the results of the eval modules which were applied.
+ * For example:
+ * <pre>
+ * output.eval.gatkreport:
+ * ##:GATKReport.v0.1 CountVariants : Counts different classes of variants in the sample
+ * CountVariants  CompRod   CpG      EvalRod  JexlExpression  Novelty  nProcessedLoci  nCalledLoci  nRefLoci  nVariantLoci  variantRate ...
+ * CountVariants  dbsnp     CpG      eval     none            all      65900028        135770       0         135770        0.00206024  ...
+ * CountVariants  dbsnp     CpG      eval     none            known    65900028        47068        0         47068         0.00071423  ...
+ * CountVariants  dbsnp     CpG      eval     none            novel    65900028        88702        0         88702         0.00134601  ...
+ * CountVariants  dbsnp     all      eval     none            all      65900028        330818       0         330818        0.00502000  ...
+ * CountVariants  dbsnp     all      eval     none            known    65900028        120685       0         120685        0.00183133  ...
+ * CountVariants  dbsnp     all      eval     none            novel    65900028        210133       0         210133        0.00318866  ...
+ * CountVariants  dbsnp     non_CpG  eval     none            all      65900028        195048       0         195048        0.00295976  ...
+ * CountVariants  dbsnp     non_CpG  eval     none            known    65900028        73617        0         73617         0.00111710  ...
+ * CountVariants  dbsnp     non_CpG  eval     none            novel    65900028        121431       0         121431        0.00184265  ...
+ * ...
+ * </pre>
+ * </p>
+ *
+ * <h3>Examples</h3>
+ * <pre>
+ * java -Xmx2g -jar GenomeAnalysisTK.jar \
+ *   -R ref.fasta \
+ *   -T VariantEval \
+ *   -o output.eval.gatkreport \
+ *   --eval:set1 set1.vcf \
+ *   --eval:set2 set2.vcf \
+ *   [--comp comp.vcf]
+ * </pre>
+ *
+ * <h3>Caveat</h3>
+ *
+ * <p>Some stratifications and evaluators are incompatible with each other due to their respective memory requirements, such as AlleleCount and VariantSummary, or Sample and VariantSummary.
+ * If you specify such a combination, the program will output an error message and ask you to disable one of these options.
+ * We do not currently provide an exhaustive list of incompatible combinations, so we recommend trying out combinations that you are interested in on a dummy command line, to rapidly ascertain whether it will work or not.</p>
+ *
+ */
+ at DocumentedGATKFeature( groupName = HelpConstants.DOCS_CAT_VARMANIP, extraDocs = {CommandLineGATK.class} )
+ at Reference(window=@Window(start=-50, stop=50))
+ at PartitionBy(PartitionType.NONE)
+public class VariantEval extends RodWalker<Integer, Integer> implements TreeReducible<Integer> {
+    public static final String IS_SINGLETON_KEY = "ISSINGLETON";
+
+    @Output
+    protected PrintStream out;
+
+    /**
+     * The variant file(s) to evaluate.
+     */
+    @Input(fullName="eval", shortName = "eval", doc="Input evaluation file(s)", required=true)
+    public List<RodBinding<VariantContext>> evals;
+
+    /**
+     * The variant file(s) to compare against.
+     */
+    @Input(fullName="comp", shortName = "comp", doc="Input comparison file(s)", required=false)
+    public List<RodBinding<VariantContext>> compsProvided = Collections.emptyList();
+    private List<RodBinding<VariantContext>> comps = new ArrayList<RodBinding<VariantContext>>();
+
+    /**
+     * dbSNP comparison VCF.  By default, the dbSNP file is used to specify the set of "known" variants.
+     * Other sets can be specified with the -knownName (--known_names) argument.
+     */
+    @ArgumentCollection
+    protected DbsnpArgumentCollection dbsnp = new DbsnpArgumentCollection();
+
+    /**
+     * Some analyses want to count overlap not with dbSNP (which is in general very open) but
+     * actually want to itemize their overlap specifically with a set of gold standard sites
+     * such as HapMap, OMNI, or the gold standard indels.  This argument provides a mechanism
+     * for communicating which file to use
+     */
+    @Input(fullName="goldStandard", shortName = "gold", doc="Evaluations that count calls at sites of true variation (e.g., indel calls) will use this argument as their gold standard for comparison", required=false)
+    public RodBinding<VariantContext> goldStandard = null;
+
+    /**
+     * Note that the --list argument requires a fully resolved and correct command-line to work.
+     */
+    @Argument(fullName="list", shortName="ls", doc="List the available eval modules and exit", required=false)
+    protected Boolean LIST = false;
+
+    // Partitioning the data arguments
+    @Argument(shortName="select", doc="One or more stratifications to use when evaluating the data", required=false)
+    protected ArrayList<String> SELECT_EXPS = new ArrayList<String>();
+
+    @Argument(shortName="selectName", doc="Names to use for the list of stratifications (must be a 1-to-1 mapping)", required=false)
+    protected ArrayList<String> SELECT_NAMES = new ArrayList<String>();
+
+    @Argument(fullName="sample", shortName="sn", doc="Derive eval and comp contexts using only these sample genotypes, when genotypes are available in the original context", required=false)
+    protected Set<String> SAMPLE_EXPRESSIONS;
+
+    /**
+     * List of rod tracks to be used for specifying "known" variants other than dbSNP.
+     */
+    @Argument(shortName="knownName", doc="Name of ROD bindings containing variant sites that should be treated as known when splitting eval rods into known and novel subsets", required=false)
+    protected HashSet<String> KNOWN_NAMES = new HashSet<String>();
+    List<RodBinding<VariantContext>> knowns = new ArrayList<RodBinding<VariantContext>>();
+
+    // Stratification arguments
+    @Argument(fullName="stratificationModule", shortName="ST", doc="One or more specific stratification modules to apply to the eval track(s) (in addition to the standard stratifications, unless -noS is specified)", required=false)
+    protected String[] STRATIFICATIONS_TO_USE = {};
+
+    @Argument(fullName="doNotUseAllStandardStratifications", shortName="noST", doc="Do not use the standard stratification modules by default (instead, only those that are specified with the -S option)", required=false)
+    protected Boolean NO_STANDARD_STRATIFICATIONS = false;
+
+    /**
+     * See the -list argument to view available modules.
+     */
+    @Argument(fullName="evalModule", shortName="EV", doc="One or more specific eval modules to apply to the eval track(s) (in addition to the standard modules, unless -noEV is specified)", required=false)
+    protected String[] MODULES_TO_USE = {};
+
+    @Argument(fullName="doNotUseAllStandardModules", shortName="noEV", doc="Do not use the standard modules by default (instead, only those that are specified with the -EV option)", required=false)
+    protected Boolean NO_STANDARD_MODULES = false;
+
+    @Argument(fullName="minPhaseQuality", shortName="mpq", doc="Minimum phasing quality", required=false)
+    protected double MIN_PHASE_QUALITY = 10.0;
+
+    @Argument(shortName="mvq", fullName="mendelianViolationQualThreshold", doc="Minimum genotype QUAL score for each trio member required to accept a site as a violation. Default is 50.", required=false)
+    protected double MENDELIAN_VIOLATION_QUAL_THRESHOLD = 50;
+
+    @Argument(shortName="ploidy", fullName="samplePloidy", doc="Per-sample ploidy (number of chromosomes per sample)", required=false)
+    protected int ploidy = GATKVariantContextUtils.DEFAULT_PLOIDY;
+
+    @Argument(fullName="ancestralAlignments", shortName="aa", doc="Fasta file with ancestral alleles", required=false)
+    private File ancestralAlignmentsFile = null;
+
+    @Argument(fullName="requireStrictAlleleMatch", shortName="strict", doc="If provided only comp and eval tracks with exactly matching reference and alternate alleles will be counted as overlapping", required=false)
+    private boolean requireStrictAlleleMatch = false;
+
+    @Argument(fullName="keepAC0", shortName="keepAC0", doc="If provided, modules that track polymorphic sites will not require that a site have AC > 0 when the input eval has genotypes", required=false)
+    private boolean keepSitesWithAC0 = false;
+
+    @Hidden
+    @Argument(fullName="numSamples", shortName="numSamples", doc="If provided, modules that track polymorphic sites will not require that a site have AC > 0 when the input eval has genotypes", required=false)
+    private int numSamplesFromArgument = 0;
+
+    /**
+     * If true, VariantEval will treat -eval 1 -eval 2 as separate tracks from the same underlying
+     * variant set, and evaluate the union of the results.  Useful when you want to do -eval chr1.vcf -eval chr2.vcf etc.
+     */
+    @Argument(fullName="mergeEvals", shortName="mergeEvals", doc="If provided, all -eval tracks will be merged into a single eval track", required=false)
+    public boolean mergeEvals = false;
+
+    /**
+     * File containing tribble-readable features for the IntervalStratificiation
+     */
+    @Input(fullName="stratIntervals", shortName="stratIntervals", doc="File containing tribble-readable features for the IntervalStratificiation", required=false)
+    public IntervalBinding<Feature> intervalsFile = null;
+
+    /**
+     * File containing tribble-readable features containing known CNVs.  For use with VariantSummary table.
+     */
+    @Input(fullName="knownCNVs", shortName="knownCNVs", doc="File containing tribble-readable features describing a known list of copy number variants", required=false)
+    public IntervalBinding<Feature> knownCNVsFile = null;
+    Map<String, IntervalTree<GenomeLoc>> knownCNVsByContig = Collections.emptyMap();
+
+    // Variables
+    private Set<SortableJexlVCMatchExp> jexlExpressions = new TreeSet<SortableJexlVCMatchExp>();
+
+    private boolean isSubsettingSamples;
+    private Set<String> sampleNamesForEvaluation = new LinkedHashSet<String>();
+    private Set<String> sampleNamesForStratification = new LinkedHashSet<String>();
+
+    // important stratifications
+    private boolean byFilterIsEnabled = false;
+    private boolean perSampleIsEnabled = false;
+
+    // Public constants
+    private static String ALL_SAMPLE_NAME = "all";
+
+    // the number of processed bp for this walker
+    long nProcessedLoci = 0;
+
+    // Utility class
+    private final VariantEvalUtils variantEvalUtils = new VariantEvalUtils(this);
+
+    // Ancestral alignments
+    private IndexedFastaSequenceFile ancestralAlignments = null;
+
+    // The set of all possible evaluation contexts
+    StratificationManager<VariantStratifier, EvaluationContext> stratManager;
+    //Set<DynamicStratification> dynamicStratifications = Collections.emptySet();
+
+    /**
+     * Initialize the stratifications, evaluations, evaluation contexts, and reporting object
+     */
+    public void initialize() {
+        // Just list the modules, and exit quickly.
+        if (LIST) { variantEvalUtils.listModulesAndExit(); }
+
+        // maintain the full list of comps
+        comps.addAll(compsProvided);
+        if ( dbsnp.dbsnp.isBound() ) {
+            comps.add(dbsnp.dbsnp);
+            knowns.add(dbsnp.dbsnp);
+        }
+
+        // Add a dummy comp track if none exists
+        if ( comps.size() == 0 )
+            comps.add(new RodBinding<VariantContext>(VariantContext.class, "none", "UNBOUND", "", new Tags()));
+
+        // Set up set of additional knowns
+        for ( RodBinding<VariantContext> compRod : comps ) {
+            if ( KNOWN_NAMES.contains(compRod.getName()) )
+                knowns.add(compRod);
+        }
+
+        // Now that we have all the rods categorized, determine the sample list from the eval rods.
+        Map<String, VCFHeader> vcfRods = GATKVCFUtils.getVCFHeadersFromRods(getToolkit(), evals);
+        Set<String> vcfSamples = SampleUtils.getSampleList(vcfRods, GATKVariantContextUtils.GenotypeMergeType.REQUIRE_UNIQUE);
+
+        // Load the sample list, using an intermediate tree set to sort the samples
+        final Set<String> allSampleNames = SampleUtils.getSamplesFromCommandLineInput(vcfSamples);
+        sampleNamesForEvaluation.addAll(new TreeSet<String>(SampleUtils.getSamplesFromCommandLineInput(vcfSamples, SAMPLE_EXPRESSIONS)));
+        isSubsettingSamples = ! sampleNamesForEvaluation.containsAll(allSampleNames);
+
+        if (Arrays.asList(STRATIFICATIONS_TO_USE).contains("Sample")) {
+            sampleNamesForStratification.addAll(sampleNamesForEvaluation);
+        }
+        sampleNamesForStratification.add(ALL_SAMPLE_NAME);
+
+        // Initialize select expressions
+        for (VariantContextUtils.JexlVCMatchExp jexl : VariantContextUtils.initializeMatchExps(SELECT_NAMES, SELECT_EXPS)) {
+            SortableJexlVCMatchExp sjexl = new SortableJexlVCMatchExp(jexl.name, jexl.exp);
+            jexlExpressions.add(sjexl);
+        }
+
+        // Initialize the set of stratifications and evaluations to use
+        // The list of stratifiers and evaluators to use
+        final List<VariantStratifier> stratificationObjects = variantEvalUtils.initializeStratificationObjects(NO_STANDARD_STRATIFICATIONS, STRATIFICATIONS_TO_USE);
+        final Set<Class<? extends VariantEvaluator>> evaluationClasses = variantEvalUtils.initializeEvaluationObjects(NO_STANDARD_MODULES, MODULES_TO_USE);
+
+        checkForIncompatibleEvaluatorsAndStratifiers(stratificationObjects, evaluationClasses);
+
+        for ( VariantStratifier vs : stratificationObjects ) {
+            if ( vs.getName().equals("Filter") )
+                byFilterIsEnabled = true;
+            else if ( vs.getName().equals("Sample") )
+                perSampleIsEnabled = true;
+        }
+
+        if ( intervalsFile != null ) {
+            boolean fail = true;
+            for ( final VariantStratifier vs : stratificationObjects ) {
+                if ( vs.getClass().equals(IntervalStratification.class) )
+                    fail = false;
+            }
+            if ( fail )
+                throw new UserException.BadArgumentValue("ST", "stratIntervals argument provided but -ST IntervalStratification not provided");
+        }
+
+        // Initialize the evaluation contexts
+        createStratificationStates(stratificationObjects, evaluationClasses);
+
+        // Load ancestral alignments
+        if (ancestralAlignmentsFile != null) {
+            try {
+                ancestralAlignments = new IndexedFastaSequenceFile(ancestralAlignmentsFile);
+            } catch (FileNotFoundException e) {
+                throw new ReviewedGATKException(String.format("The ancestral alignments file, '%s', could not be found", ancestralAlignmentsFile.getAbsolutePath()));
+            }
+        }
+
+        // initialize CNVs
+        if ( knownCNVsFile != null ) {
+            knownCNVsByContig = createIntervalTreeByContig(knownCNVsFile);
+        }
+    }
+
+    final void checkForIncompatibleEvaluatorsAndStratifiers( final List<VariantStratifier> stratificationObjects,
+                                                             Set<Class<? extends VariantEvaluator>> evaluationClasses) {
+        for ( final VariantStratifier vs : stratificationObjects ) {
+            for ( Class<? extends VariantEvaluator> ec : evaluationClasses )
+                if ( vs.getIncompatibleEvaluators().contains(ec) )
+                    throw new UserException.BadArgumentValue("ST and ET", 
+                            "The selected stratification " + vs.getName() + 
+                                    " and evaluator " + ec.getSimpleName() +
+                                    " are incompatible due to combinatorial memory requirements." +
+                                    " Please disable one");
+        }
+    }
+    
+    final void createStratificationStates(final List<VariantStratifier> stratificationObjects, final Set<Class<? extends VariantEvaluator>> evaluationObjects) {
+        final List<VariantStratifier> strats = new ArrayList<VariantStratifier>(stratificationObjects);
+        stratManager = new StratificationManager<VariantStratifier, EvaluationContext>(strats);
+
+        logger.info("Creating " + stratManager.size() + " combinatorial stratification states");
+        for ( int i = 0; i < stratManager.size(); i++ ) {
+            EvaluationContext ec = new EvaluationContext(this, evaluationObjects);
+            stratManager.set(i, ec);
+        }
+    }    
+    
+    public final Map<String, IntervalTree<GenomeLoc>> createIntervalTreeByContig(final IntervalBinding<Feature> intervals) {
+        final Map<String, IntervalTree<GenomeLoc>> byContig = new HashMap<String, IntervalTree<GenomeLoc>>();
+
+        final List<GenomeLoc> locs = intervals.getIntervals(getToolkit());
+
+        // set up the map from contig -> interval tree
+        for ( final String contig : getContigNames() )
+            byContig.put(contig, new IntervalTree<GenomeLoc>());
+
+        for ( final GenomeLoc loc : locs ) {
+            byContig.get(loc.getContig()).put(loc.getStart(), loc.getStop(), loc);
+        }
+
+        return byContig;
+    }
+
+    /**
+     * Collect relevant information from each variant in the supplied VCFs
+     */
+    @Override
+    public Integer map(RefMetaDataTracker tracker, ReferenceContext ref, AlignmentContext context) {
+        // we track the processed bp and expose this for modules instead of wasting CPU power on calculating
+        // the same thing over and over in evals that want the processed bp
+        synchronized (this) {
+            nProcessedLoci += context.getSkippedBases() + (ref == null ? 0 : 1);
+        }
+
+        if (tracker != null) {
+            String aastr = (ancestralAlignments == null) ? null : new String(ancestralAlignments.getSubsequenceAt(ref.getLocus().getContig(), ref.getLocus().getStart(), ref.getLocus().getStop()).getBases());
+
+//            // update the dynamic stratifications
+//            for (final VariantContext vc : tracker.getValues(evals, ref.getLocus())) {
+//                // don't worry -- DynamicStratification only work with one eval object
+//                for ( final DynamicStratification ds :  dynamicStratifications ) {
+//                    ds.update(vc);
+//                }
+//            }
+
+            //      --------- track ---------           sample  - VariantContexts -
+            HashMap<RodBinding<VariantContext>, HashMap<String, Collection<VariantContext>>> evalVCs = variantEvalUtils.bindVariantContexts(tracker, ref, evals, byFilterIsEnabled, true, perSampleIsEnabled, mergeEvals);
+            HashMap<RodBinding<VariantContext>, HashMap<String, Collection<VariantContext>>> compVCs = variantEvalUtils.bindVariantContexts(tracker, ref, comps, byFilterIsEnabled, false, false, false);
+
+            // for each eval track
+            for ( final RodBinding<VariantContext> evalRod : evals ) {
+                final Map<String, Collection<VariantContext>> emptyEvalMap = Collections.emptyMap();
+                final Map<String, Collection<VariantContext>> evalSet = evalVCs.containsKey(evalRod) ? evalVCs.get(evalRod) : emptyEvalMap;
+
+                // for each sample stratifier
+                for ( final String sampleName : sampleNamesForStratification ) {
+                    Collection<VariantContext> evalSetBySample = evalSet.get(sampleName);
+                    if ( evalSetBySample == null ) {
+                        evalSetBySample = new HashSet<VariantContext>(1);
+                        evalSetBySample.add(null);
+                    }
+
+                    // for each eval in the track
+                    for ( VariantContext eval : evalSetBySample ) {
+                        // deal with ancestral alleles if requested
+                        if ( eval != null && aastr != null ) {
+                            eval = new VariantContextBuilder(eval).attribute("ANCESTRALALLELE", aastr).make();
+                        }
+
+                        // for each comp track
+                        for ( final RodBinding<VariantContext> compRod : comps ) {
+                            // no sample stratification for comps
+                            final HashMap<String, Collection<VariantContext>> compSetHash = compVCs.get(compRod);
+                            final Collection<VariantContext> compSet = (compSetHash == null || compSetHash.size() == 0) ? Collections.<VariantContext>emptyList() : compVCs.get(compRod).values().iterator().next();
+
+                            // find the comp
+                            final VariantContext comp = findMatchingComp(eval, compSet);
+
+                            for ( EvaluationContext nec : getEvaluationContexts(tracker, ref, eval, evalRod.getName(), comp, compRod.getName(), sampleName) ) {
+
+                                // eval against the comp
+                                synchronized (nec) {
+                                    nec.apply(tracker, ref, context, comp, eval);
+                                }
+
+                                // eval=null against all comps of different type that aren't bound to another eval
+                                for ( VariantContext otherComp : compSet ) {
+                                    if ( otherComp != comp && ! compHasMatchingEval(otherComp, evalSetBySample) ) {
+                                        synchronized (nec) {
+                                            nec.apply(tracker, ref, context, otherComp, null);
+                                        }
+                                    }
+                                }
+                            }
+                        }
+                    }
+                }
+
+                if ( mergeEvals ) break; // stop processing the eval tracks
+            }
+        }
+
+        return null;
+    }
+
+    /**
+     * Given specific eval and comp VCs and the sample name, return an iterable
+     * over all of the applicable state keys.
+     *
+     * this code isn't structured yet for efficiency.  Here we currently are
+     * doing the following inefficient algorithm:
+     *
+     * for each strat:
+     *   get list of relevant states that eval and comp according to strat
+     *   add this list of states to a list of list states
+     *
+     * then
+     *
+     * ask the strat manager to look up all of the keys associated with the combinations
+     * of these states.  For example, suppose we have a single variant S.  We have active
+     * strats EvalRod, CompRod, and Novelty.  We produce a list that looks like:
+     *
+     *   L = [[Eval], [Comp], [All, Novel]]
+     *
+     * We then go through the strat manager tree to produce the keys associated with these states:
+     *
+     *   K = [0, 1] where EVAL x COMP x ALL = 0 and EVAL x COMP x NOVEL = 1
+     *
+     * It's clear that a better
+     *
+     * TODO -- create an inline version that doesn't create the intermediate list of list
+     *
+     * @param tracker
+     * @param ref
+     * @param eval
+     * @param evalName
+     * @param comp
+     * @param compName
+     * @param sampleName
+     * @return
+     */
+    protected Collection<EvaluationContext> getEvaluationContexts(final RefMetaDataTracker tracker,
+                                                                  final ReferenceContext ref,
+                                                                  final VariantContext eval,
+                                                                  final String evalName,
+                                                                  final VariantContext comp,
+                                                                  final String compName,
+                                                                  final String sampleName ) {
+        final List<List<Object>> states = new LinkedList<List<Object>>();
+        for ( final VariantStratifier vs : stratManager.getStratifiers() ) {
+            states.add(vs.getRelevantStates(ref, tracker, comp, compName, eval, evalName, sampleName));
+        }
+        return stratManager.values(states);
+    }
+
+
+    @Requires({"comp != null", "evals != null"})
+    private boolean compHasMatchingEval(final VariantContext comp, final Collection<VariantContext> evals) {
+        // find all of the matching comps
+        for ( final VariantContext eval : evals ) {
+            if ( eval != null && doEvalAndCompMatch(comp, eval, requireStrictAlleleMatch) != EvalCompMatchType.NO_MATCH )
+                return true;
+        }
+
+        // nothing matched
+        return false;
+    }
+
+    private enum EvalCompMatchType { NO_MATCH, STRICT, LENIENT }
+
+    @Requires({"eval != null", "comp != null"})
+    private EvalCompMatchType doEvalAndCompMatch(final VariantContext eval, final VariantContext comp, boolean requireStrictAlleleMatch) {
+        if ( comp.getType() == VariantContext.Type.NO_VARIATION || eval.getType() == VariantContext.Type.NO_VARIATION )
+            // if either of these are NO_VARIATION they are LENIENT matches
+            return EvalCompMatchType.LENIENT;
+
+        if ( comp.getType() != eval.getType() )
+            return EvalCompMatchType.NO_MATCH;
+
+        // find the comp which matches both the reference allele and alternate allele from eval
+        final Allele altEval = eval.getAlternateAlleles().size() == 0 ? null : eval.getAlternateAllele(0);
+        final Allele altComp = comp.getAlternateAlleles().size() == 0 ? null : comp.getAlternateAllele(0);
+        if ((altEval == null && altComp == null) || (altEval != null && altEval.equals(altComp) && eval.getReference().equals(comp.getReference())))
+            return EvalCompMatchType.STRICT;
+        else
+            return requireStrictAlleleMatch ? EvalCompMatchType.NO_MATCH : EvalCompMatchType.LENIENT;
+    }
+
+    private VariantContext findMatchingComp(final VariantContext eval, final Collection<VariantContext> comps) {
+        // if no comps, return null
+        if ( comps == null || comps.isEmpty() )
+            return null;
+
+        // if no eval, return any comp
+        if ( eval == null )
+            return comps.iterator().next();
+
+        // find all of the matching comps
+        VariantContext lenientMatch = null;
+        for ( final VariantContext comp : comps ) {
+            switch ( doEvalAndCompMatch(comp, eval, requireStrictAlleleMatch) ) {
+                case STRICT:
+                    return comp;
+                case LENIENT:
+                    if ( lenientMatch == null ) lenientMatch = comp;
+                    break;
+                case NO_MATCH:
+                    // do nothing
+            }
+        }
+
+        // nothing matched, just return lenientMatch, which might be null
+        return lenientMatch;
+    }
+
+    public Integer treeReduce(Integer lhs, Integer rhs) { return null; }
+
+    @Override
+    public Integer reduceInit() { return null; }
+
+    @Override
+    public Integer reduce(Integer value, Integer sum) { return null; }
+
+    /**
+     * Output the finalized report
+     *
+     * @param result  an integer that doesn't get used for anything
+     */
+    public void onTraversalDone(Integer result) {
+        logger.info("Finalizing variant report");
+        
+        // go through the evaluations and finalize them
+        for ( final EvaluationContext nec : stratManager.values() )
+            for ( final VariantEvaluator ve : nec.getVariantEvaluators() )
+                ve.finalizeEvaluation();
+        
+        VariantEvalReportWriter.writeReport(out, stratManager, stratManager.getStratifiers(), stratManager.get(0).getVariantEvaluators());
+    }
+
+    // Accessors
+    public Logger getLogger() { return logger; }
+
+    public double getMinPhaseQuality() { return MIN_PHASE_QUALITY; }
+
+    public int getSamplePloidy() { return ploidy; }
+    public double getMendelianViolationQualThreshold() { return MENDELIAN_VIOLATION_QUAL_THRESHOLD; }
+
+    public static String getAllSampleName() { return ALL_SAMPLE_NAME; }
+
+    public List<RodBinding<VariantContext>> getKnowns() { return knowns; }
+
+    public List<RodBinding<VariantContext>> getEvals() { return evals; }
+
+    public boolean isSubsettingToSpecificSamples() { return isSubsettingSamples; }
+    public Set<String> getSampleNamesForEvaluation() { return sampleNamesForEvaluation; }
+
+    public int getNumberOfSamplesForEvaluation() {
+        if (sampleNamesForEvaluation!= null &&  !sampleNamesForEvaluation.isEmpty())
+            return sampleNamesForEvaluation.size();
+        else {
+            return numSamplesFromArgument;
+        }
+
+    }
+    public Set<String> getSampleNamesForStratification() { return sampleNamesForStratification; }
+
+    public List<RodBinding<VariantContext>> getComps() { return comps; }
+
+    public Set<SortableJexlVCMatchExp> getJexlExpressions() { return jexlExpressions; }
+
+    public long getnProcessedLoci() {
+        return nProcessedLoci;
+    }
+
+    public Set<String> getContigNames() {
+        final TreeSet<String> contigs = new TreeSet<String>();
+        for( final SAMSequenceRecord r :  getToolkit().getReferenceDataSource().getReference().getSequenceDictionary().getSequences()) {
+            contigs.add(r.getSequenceName());
+        }
+        return contigs;
+    }
+
+    /**
+     * getToolkit is protected, so we have to pseudo-overload it here so eval / strats can get the toolkit
+     * @return
+     */
+    public GenomeAnalysisEngine getToolkit() {
+        return super.getToolkit();
+    }
+
+    public boolean ignoreAC0Sites() {
+        return ! keepSitesWithAC0;
+    }
+}
\ No newline at end of file
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/tools/walkers/varianteval/VariantEvalReportWriter.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/tools/walkers/varianteval/VariantEvalReportWriter.java
new file mode 100644
index 0000000..7244a94
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/tools/walkers/varianteval/VariantEvalReportWriter.java
@@ -0,0 +1,203 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.tools.walkers.varianteval;
+
+import org.broadinstitute.gatk.engine.report.GATKReport;
+import org.broadinstitute.gatk.engine.report.GATKReportTable;
+import org.broadinstitute.gatk.tools.walkers.varianteval.evaluators.VariantEvaluator;
+import org.broadinstitute.gatk.tools.walkers.varianteval.stratifications.VariantStratifier;
+import org.broadinstitute.gatk.tools.walkers.varianteval.stratifications.manager.StratificationManager;
+import org.broadinstitute.gatk.tools.walkers.varianteval.util.Analysis;
+import org.broadinstitute.gatk.tools.walkers.varianteval.util.AnalysisModuleScanner;
+import org.broadinstitute.gatk.tools.walkers.varianteval.util.DataPoint;
+import org.broadinstitute.gatk.tools.walkers.varianteval.util.EvaluationContext;
+import org.broadinstitute.gatk.utils.collections.Pair;
+import org.broadinstitute.gatk.utils.exceptions.ReviewedGATKException;
+import org.broadinstitute.gatk.utils.exceptions.GATKException;
+
+import java.io.PrintStream;
+import java.lang.reflect.Field;
+import java.util.Collection;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * Class for writing the GATKReport for VariantEval
+ *
+ * Accepts a fulled evaluated (i.e., there's no more data coming) set of stratifications and evaluators
+ * and supports writing out the data in these evaluators to a GATKReport.
+ */
+public class VariantEvalReportWriter {
+
+    protected VariantEvalReportWriter() {}  // no public access
+
+    /**
+     * The business end of the class.  Writes out the data in the provided stratManager
+     * to the PrintStream out
+     *
+     * @param out            the output stream
+     * @param stratManager   the stratification manager
+     * @param stratifiers    the stratifiers
+     * @param evaluators     the evaluators
+     */
+    public static void writeReport(final PrintStream out,
+                                   final StratificationManager<VariantStratifier, EvaluationContext> stratManager,
+                                   final Collection<VariantStratifier> stratifiers,
+                                   final Collection<VariantEvaluator> evaluators) {
+
+        final GATKReport report = initializeGATKReport(stratifiers, evaluators);
+
+        for ( int key = 0; key < stratManager.size(); key++ ) {
+            final String stratStateString = stratManager.getStratsAndStatesStringForKey(key);
+            final List<Pair<VariantStratifier, Object>> stratsAndStates = stratManager.getStratsAndStatesForKey(key);
+            final EvaluationContext nec = stratManager.get(key);
+
+            for ( final VariantEvaluator ve : nec.getVariantEvaluators() ) {
+                final GATKReportTable table = report.getTable(ve.getSimpleName());
+
+                final AnalysisModuleScanner scanner = new AnalysisModuleScanner(ve);
+                final Map<Field, DataPoint> datamap = scanner.getData();
+                try {
+                    if ( scanner.hasMoltenField() ) {
+                        final Field field = scanner.getMoltenField();
+                        final Object fieldValue = field.get(ve);
+
+                        if ( fieldValue == null || ! (fieldValue instanceof Map) )
+                            throw new ReviewedGATKException("BUG field " + field.getName() + " must be a non-null instance of Map in " + scanner.getAnalysis().name());
+                        final Map<Object, Object> map = (Map<Object, Object>)fieldValue;
+                        if ( map.isEmpty() )
+                            throw new ReviewedGATKException("BUG: map is null or empty in analysis " + scanner.getAnalysis());
+                        
+                        int counter = 0; // counter is used to ensure printing order is as defined by entrySet
+                        for ( Map.Entry<Object, Object> keyValue : map.entrySet() ) {
+                            // "%05d" is a terrible hack to ensure sort order
+                            final String moltenStratStateString = stratStateString + String.format("%05d", counter++);
+                            setStratificationColumns(table, moltenStratStateString, stratsAndStates);
+                            table.set(moltenStratStateString, scanner.getMoltenAnnotation().variableName(), keyValue.getKey());
+                            table.set(moltenStratStateString, scanner.getMoltenAnnotation().valueName(), keyValue.getValue());
+                        }
+                    } else {
+                        setStratificationColumns(table, stratStateString, stratsAndStates);
+                        for ( final Field field : datamap.keySet()) {
+                            table.set(stratStateString, field.getName(), field.get(ve));
+                        }
+                    }
+                } catch (IllegalAccessException e) {
+                    throw new ReviewedGATKException("BUG: analysis field not public: " + e);
+                }
+            }
+        }
+
+        report.print(out);
+    }
+
+    /**
+     * Common utility to configure a GATKReportTable columns
+     *
+     * Sets the column names to the strat names in stratsAndStates for the primary key in table
+     *
+     * @param table
+     * @param primaryKey
+     * @param stratsAndStates
+     */
+    private static void setStratificationColumns(final GATKReportTable table,
+                                                 final String primaryKey,
+                                                 final List<Pair<VariantStratifier, Object>> stratsAndStates) {
+        table.set(primaryKey, table.getTableName(), table.getTableName());
+        for ( final Pair<VariantStratifier, Object> stratAndState : stratsAndStates ) {
+            final VariantStratifier vs = stratAndState.getFirst();
+            final String columnName = vs.getName();
+            final Object strat = stratAndState.getSecond();
+            if ( columnName == null || strat == null )
+                throw new ReviewedGATKException("Unexpected null variant stratifier state at " + table + " key = " + primaryKey);
+            table.set(primaryKey, columnName, strat);
+        }
+    }
+
+    /**
+     * Initialize the output report
+     *
+     * We have a set of stratifiers and evaluation objects.  We need to create tables that look like:
+     *
+     * strat1 strat2 ... stratN eval1.field1 eval1.field2 ... eval1.fieldM
+     *
+     * for each eval.
+     *
+     * Note that this procedure doesn't support the creation of the old TableType system.  As the
+     * VariantEvaluators are effectively tables themselves, we require authors to just create new
+     * evaluation modules externally instead of allow them to embed them in other evaluation modules
+     *
+     * @return an initialized report object
+     */
+    private static GATKReport initializeGATKReport(final Collection<VariantStratifier> stratifiers,
+                                                   final Collection<VariantEvaluator> evaluators) {
+        final GATKReport report = new GATKReport();
+
+        for (final VariantEvaluator ve : evaluators) {
+            final AnalysisModuleScanner scanner = new AnalysisModuleScanner(ve);
+            final Map<Field, DataPoint> datamap = scanner.getData();
+
+            // create the table
+            final String tableName = ve.getSimpleName();
+            final String tableDesc = ve.getClass().getAnnotation(Analysis.class).description();
+            report.addTable(tableName, tableDesc, 1 + stratifiers.size() + (scanner.hasMoltenField() ? 2 : datamap.size()), GATKReportTable.TableSortingWay.SORT_BY_ROW);
+
+            // grab the table, and add the columns we need to it
+            final GATKReportTable table = report.getTable(tableName);
+            table.addColumn(tableName, tableName);
+
+            // first create a column to hold each stratifier state
+            for (final VariantStratifier vs : stratifiers) {
+                final String columnName = vs.getName();
+                table.addColumn(columnName, vs.getFormat());
+            }
+
+            if ( scanner.hasMoltenField() ) {
+                // deal with molten data
+                table.addColumn(scanner.getMoltenAnnotation().variableName(), scanner.getMoltenAnnotation().variableFormat());
+                table.addColumn(scanner.getMoltenAnnotation().valueName(), scanner.getMoltenAnnotation().valueFormat());
+            } else {
+                if ( datamap.isEmpty() )
+                    throw new ReviewedGATKException("Datamap is empty for analysis " + scanner.getAnalysis());
+                
+                // add DataPoint's for each field marked as such
+                for (final Map.Entry<Field, DataPoint> field : datamap.entrySet()) {
+                    try {
+                        field.getKey().setAccessible(true);
+
+                        // this is an atomic value, add a column for it
+                        final String format = field.getValue().format();
+                        table.addColumn(field.getKey().getName(), format);
+                    } catch (SecurityException e) {
+                        throw new GATKException("SecurityException: " + e);
+                    }
+                }
+            }
+        }
+
+        return report;
+    }
+}
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/tools/walkers/varianteval/evaluators/CompOverlap.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/tools/walkers/varianteval/evaluators/CompOverlap.java
new file mode 100644
index 0000000..7ebf96e
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/tools/walkers/varianteval/evaluators/CompOverlap.java
@@ -0,0 +1,109 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.tools.walkers.varianteval.evaluators;
+
+import org.broadinstitute.gatk.engine.contexts.AlignmentContext;
+import org.broadinstitute.gatk.engine.contexts.ReferenceContext;
+import org.broadinstitute.gatk.engine.refdata.RefMetaDataTracker;
+import org.broadinstitute.gatk.tools.walkers.varianteval.util.Analysis;
+import org.broadinstitute.gatk.tools.walkers.varianteval.util.DataPoint;
+import htsjdk.variant.variantcontext.Allele;
+import htsjdk.variant.variantcontext.VariantContext;
+
+/**
+ * The Broad Institute
+ * SOFTWARE COPYRIGHT NOTICE AGREEMENT
+ * This software and its documentation are copyright 2009 by the
+ * Broad Institute/Massachusetts Institute of Technology. All rights are reserved.
+ * <p/>
+ * This software is supplied without any warranty or guaranteed support whatsoever. Neither
+ * the Broad Institute nor MIT can be responsible for its use, misuse, or functionality.
+ */
+ at Analysis(description = "The overlap between eval and comp sites")
+public class CompOverlap extends VariantEvaluator implements StandardEval {
+    @DataPoint(description = "number of eval variant sites", format = "%d")
+    public long nEvalVariants = 0;
+
+    @DataPoint(description = "number of eval sites outside of comp sites", format = "%d")
+    public long novelSites = 0;
+
+    @DataPoint(description = "number of eval sites at comp sites", format = "%d")
+    public long nVariantsAtComp = 0;
+
+    @DataPoint(description = "percentage of eval sites at comp sites", format = "%.2f" )
+    public double compRate = 0.0;
+
+    @DataPoint(description = "number of concordant sites", format = "%d")
+    public long nConcordant = 0;
+
+    @DataPoint(description = "the concordance rate", format = "%.2f")
+    public double concordantRate = 0.0;
+
+    public int getComparisonOrder() {
+        return 2;   // we need to see each eval track and each comp track
+    }
+
+    public long nNovelSites() { return nEvalVariants - nVariantsAtComp; }
+    public double compRate() { return rate(nVariantsAtComp, nEvalVariants); }
+    public double concordanceRate() { return rate(nConcordant, nVariantsAtComp); }
+
+    public void finalizeEvaluation() {
+        compRate = 100 * compRate();
+        concordantRate = 100 * concordanceRate();
+        novelSites = nNovelSites();
+    }
+
+    /**
+     * Returns true if every allele in eval is also in comp
+     *
+     * @param eval  eval context
+     * @param comp db context
+     * @return true if eval and db are discordant
+     */
+    public boolean discordantP(VariantContext eval, VariantContext comp) {
+        for (Allele a : eval.getAlleles()) {
+            if (!comp.hasAllele(a, true))
+                return true;
+        }
+
+        return false;
+    }
+
+    public void update2(VariantContext eval, VariantContext comp, RefMetaDataTracker tracker, ReferenceContext ref, AlignmentContext context) {
+        boolean evalIsGood = eval != null && eval.isPolymorphicInSamples();
+        boolean compIsGood = comp != null && comp.isNotFiltered();
+
+        if (evalIsGood) nEvalVariants++;           // count the number of eval events
+
+        if (compIsGood && evalIsGood) {
+            nVariantsAtComp++;
+
+            if (!discordantP(eval, comp)) {    // count whether we're concordant or not with the comp value
+                nConcordant++;
+            }
+        }
+    }
+}
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/tools/walkers/varianteval/evaluators/CountVariants.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/tools/walkers/varianteval/evaluators/CountVariants.java
new file mode 100644
index 0000000..89b37f0
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/tools/walkers/varianteval/evaluators/CountVariants.java
@@ -0,0 +1,219 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.tools.walkers.varianteval.evaluators;
+
+import org.broadinstitute.gatk.engine.contexts.AlignmentContext;
+import org.broadinstitute.gatk.engine.contexts.ReferenceContext;
+import org.broadinstitute.gatk.engine.refdata.RefMetaDataTracker;
+import org.broadinstitute.gatk.tools.walkers.varianteval.util.Analysis;
+import org.broadinstitute.gatk.tools.walkers.varianteval.util.DataPoint;
+import org.broadinstitute.gatk.utils.exceptions.ReviewedGATKException;
+import htsjdk.variant.variantcontext.Genotype;
+import htsjdk.variant.variantcontext.VariantContext;
+
+ at Analysis(description = "Counts different classes of variants in the sample")
+public class CountVariants extends VariantEvaluator implements StandardEval {
+    // the following fields are in output order:
+
+    // basic counts on various rates found
+    @DataPoint(description = "Number of processed loci", format = "%d")
+    public long nProcessedLoci = 0;
+    @DataPoint(description = "Number of called loci", format = "%d")
+    public long nCalledLoci = 0;
+    @DataPoint(description = "Number of reference loci", format = "%d")
+    public long nRefLoci = 0;
+    @DataPoint(description = "Number of variant loci", format = "%d")
+    public long nVariantLoci = 0;
+
+    // the following two calculations get set in the finalizeEvaluation
+    @DataPoint(description = "Variants per loci rate", format = "%.8f")
+    public double variantRate = 0;
+    @DataPoint(description = "Number of variants per base", format = "%.8f")
+    public double variantRatePerBp = 0;
+
+    @DataPoint(description = "Number of snp loci", format = "%d")
+    public long nSNPs = 0;
+    @DataPoint(description = "Number of mnp loci", format = "%d")
+    public long nMNPs = 0;
+    @DataPoint(description = "Number of insertions", format = "%d")
+    public long nInsertions = 0;
+    @DataPoint(description = "Number of deletions", format = "%d")
+    public long nDeletions = 0;
+    @DataPoint(description = "Number of complex indels", format = "%d")
+    public long nComplex = 0;
+    @DataPoint(description = "Number of symbolic events", format = "%d")
+    public long nSymbolic = 0;
+
+    @DataPoint(description = "Number of mixed loci (loci that can't be classified as a SNP, Indel or MNP)", format = "%d")
+    public long nMixed = 0;
+
+    @DataPoint(description = "Number of no calls loci", format = "%d")
+    public long nNoCalls = 0;
+    @DataPoint(description = "Number of het loci", format = "%d")
+    public long nHets = 0;
+    @DataPoint(description = "Number of hom ref loci", format = "%d")
+    public long nHomRef = 0;
+    @DataPoint(description = "Number of hom var loci", format = "%d")
+    public long nHomVar = 0;
+    @DataPoint(description = "Number of singletons", format = "%d")
+    public long nSingletons = 0;
+    @DataPoint(description = "Number of derived homozygotes", format = "%d")
+    public long nHomDerived = 0;
+
+    // calculations that get set in the finalizeEvaluation method
+    @DataPoint(description = "heterozygosity per locus rate", format = "%.2e")
+    public double heterozygosity = 0;
+    @DataPoint(description = "heterozygosity per base pair", format = "%.2f")
+    public double heterozygosityPerBp = 0;
+    @DataPoint(description = "heterozygosity to homozygosity ratio", format = "%.2f")
+    public double hetHomRatio = 0;
+    @DataPoint(description = "indel rate (insertion count + deletion count)", format = "%.2e")
+    public double indelRate = 0;
+    @DataPoint(description = "indel rate per base pair", format = "%.2f")
+    public double indelRatePerBp = 0;
+    @DataPoint(description = "insertion  to deletion ratio", format = "%.2f")
+    public double insertionDeletionRatio = 0;
+    
+    private double perLocusRate(long n) {
+        return rate(n, nProcessedLoci);
+    }
+
+    private long perLocusRInverseRate(long n) {
+        return inverseRate(n, nProcessedLoci);
+    }
+
+
+    public int getComparisonOrder() {
+        return 1;   // we only need to see each eval track
+    }
+
+    public void update1(VariantContext vc1, RefMetaDataTracker tracker, ReferenceContext ref, AlignmentContext context) {
+        nCalledLoci++;
+
+        // Note from Eric:
+        // This is really not correct.  What we really want here is a polymorphic vs. monomorphic count (i.e. on the Genotypes).
+        // So in order to maintain consistency with the previous implementation (and the intention of the original author), I've
+        // added in a proxy check for monomorphic status here.
+        // Protect against case when vc only as no-calls too - can happen if we strafity by sample and sample as a single no-call.
+       if ( getWalker().ignoreAC0Sites() && vc1.isMonomorphicInSamples() ) {
+            nRefLoci++;
+        } else {
+             switch (vc1.getType()) {
+                case NO_VARIATION:
+                    // shouldn't get here
+                    break;
+                case SNP:
+                    nVariantLoci++;
+                    nSNPs++;
+                    if (variantWasSingleton(vc1)) nSingletons++;
+                    break;
+                case MNP:
+                    nVariantLoci++;
+                    nMNPs++;
+                    if (variantWasSingleton(vc1)) nSingletons++;
+                    break;
+                case INDEL:
+                    nVariantLoci++;
+                    if (vc1.isSimpleInsertion())
+                        nInsertions++;
+                    else if (vc1.isSimpleDeletion())
+                        nDeletions++;
+                    else
+                        nComplex++;
+                    break;
+                case MIXED:
+                    nVariantLoci++;
+                    nMixed++;
+                    break;
+                case SYMBOLIC:
+                    nSymbolic++;
+                    break;
+                default:
+                    throw new ReviewedGATKException("Unexpected VariantContext type " + vc1.getType());
+            }
+        }
+
+        // these operations are ordered to ensure that we don't get the base string of the ref unless we need it
+        final String aaStr = vc1.hasAttribute("ANCESTRALALLELE") ? vc1.getAttributeAsString("ANCESTRALALLELE", null).toUpperCase() : null;
+        final String refStr = aaStr != null ? vc1.getReference().getBaseString().toUpperCase() : null;
+
+        // ref  aa  alt  class
+        // A    C   A    der homozygote
+        // A    C   C    anc homozygote
+
+        // A    A   A    ref homozygote
+        // A    A   C
+        // A    C   A
+        // A    C   C
+
+        for (final Genotype g : vc1.getGenotypes()) {
+            final String altStr = vc1.getAlternateAlleles().size() > 0 ? vc1.getAlternateAllele(0).getBaseString().toUpperCase() : null;
+
+            switch (g.getType()) {
+                case NO_CALL:
+                    nNoCalls++;
+                    break;
+                case HOM_REF:
+                    nHomRef++;
+
+                    if ( aaStr != null && altStr != null && !refStr.equalsIgnoreCase(aaStr) ) {
+                        nHomDerived++;
+                    }
+
+                    break;
+                case HET:
+                    nHets++;
+                    break;
+                case HOM_VAR:
+                    nHomVar++;
+
+                    if ( aaStr != null && altStr != null && !altStr.equalsIgnoreCase(aaStr) ) {
+                        nHomDerived++;
+                    }
+
+                    break;
+                case MIXED:
+                    break;
+                case UNAVAILABLE:
+                    break;
+                default:
+                    throw new ReviewedGATKException("BUG: Unexpected genotype type: " + g);
+            }
+        }
+    }
+
+    public void finalizeEvaluation() {
+        nProcessedLoci = getWalker().getnProcessedLoci();
+        variantRate = perLocusRate(nVariantLoci);
+        variantRatePerBp = perLocusRInverseRate(nVariantLoci);
+        heterozygosity = perLocusRate(nHets);
+        heterozygosityPerBp = perLocusRInverseRate(nHets);
+        hetHomRatio = ratio(nHets, nHomVar);
+        indelRate = perLocusRate(nDeletions + nInsertions + nComplex);
+        indelRatePerBp = perLocusRInverseRate(nDeletions + nInsertions + nComplex);
+        insertionDeletionRatio = ratio(nInsertions, nDeletions);
+    }
+}
\ No newline at end of file
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/tools/walkers/varianteval/evaluators/IndelLengthHistogram.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/tools/walkers/varianteval/evaluators/IndelLengthHistogram.java
new file mode 100644
index 0000000..8e202a7
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/tools/walkers/varianteval/evaluators/IndelLengthHistogram.java
@@ -0,0 +1,123 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.tools.walkers.varianteval.evaluators;
+
+import org.broadinstitute.gatk.engine.contexts.AlignmentContext;
+import org.broadinstitute.gatk.engine.contexts.ReferenceContext;
+import org.broadinstitute.gatk.engine.refdata.RefMetaDataTracker;
+import org.broadinstitute.gatk.tools.walkers.varianteval.util.Analysis;
+import org.broadinstitute.gatk.tools.walkers.varianteval.util.Molten;
+import org.broadinstitute.gatk.utils.exceptions.ReviewedGATKException;
+import htsjdk.variant.variantcontext.Allele;
+import htsjdk.variant.variantcontext.VariantContext;
+
+import java.util.*;
+
+/**
+ * Simple utility for histogramming indel lengths
+ *
+ * Based on code from chartl
+ *
+ * @author Mark DePristo
+ * @since 3/21/12
+ */
+ at Analysis(description = "Indel length histogram", molten = true)
+public class IndelLengthHistogram extends VariantEvaluator implements StandardEval {
+    private final Map<Integer, Integer> counts = new HashMap<Integer, Integer>();
+    private final static boolean asFrequencies = true;
+    int nIndels = 0;
+
+    @Molten(variableName = "Length", valueName = "Freq", variableFormat = "%d", valueFormat = "%.2f")
+    public TreeMap<Object, Object> results;
+    
+    public final static int MAX_SIZE_FOR_HISTOGRAM = 10;
+    private final static boolean INCLUDE_LONG_EVENTS_AT_MAX_SIZE = false;
+
+    public IndelLengthHistogram() {
+        initializeCounts(MAX_SIZE_FOR_HISTOGRAM);
+    }
+
+    private void initializeCounts(int size) {
+        for ( int i = -size; i <= size; i++ ) {
+            if ( i != 0 ) counts.put(i, 0);
+        }
+    }
+
+    @Override
+    public void finalizeEvaluation() {
+        if ( asFrequencies ) {
+            results = new TreeMap<Object, Object>();
+            for ( final int len : counts.keySet() ) {
+                final double value = nIndels == 0 ? 0.0 : counts.get(len) / (1.0 * nIndels);
+                results.put(len, value);
+            }
+        } else {
+            results = new TreeMap<Object, Object>(results);
+        }
+    }
+
+    @Override
+    public int getComparisonOrder() {
+        return 1;
+    }
+
+    @Override
+    public void update1(final VariantContext eval, final RefMetaDataTracker tracker, final ReferenceContext ref, final AlignmentContext context) {
+        if ( eval.isIndel() && ! eval.isComplexIndel() ) {
+            if ( ! ( getWalker().ignoreAC0Sites() && eval.isMonomorphicInSamples() )) {
+                // only if we are actually polymorphic in the subsetted samples should we count the allele
+                for ( Allele alt : eval.getAlternateAlleles() ) {
+                    final int alleleSize = alt.length() - eval.getReference().length();
+                    if ( alleleSize == 0 ) throw new ReviewedGATKException("Allele size not expected to be zero for indel: alt = " + alt + " ref = " + eval.getReference());
+                    updateLengthHistogram(eval.getReference(), alt);
+                }
+            }
+        }
+    }
+
+    /**
+     * Update the histogram with the implied length of the indel allele between ref and alt (alt.len - ref.len).
+     *
+     * If this size is outside of MAX_SIZE_FOR_HISTOGRAM, the size is capped to MAX_SIZE_FOR_HISTOGRAM,
+     * if INCLUDE_LONG_EVENTS_AT_MAX_SIZE is set.
+     *
+     * @param ref
+     * @param alt
+     */
+    public void updateLengthHistogram(final Allele ref, final Allele alt) {
+        int len = alt.length() - ref.length();
+        if ( INCLUDE_LONG_EVENTS_AT_MAX_SIZE ) {
+            if ( len > MAX_SIZE_FOR_HISTOGRAM ) len = MAX_SIZE_FOR_HISTOGRAM;
+            if ( len < -MAX_SIZE_FOR_HISTOGRAM ) len = -MAX_SIZE_FOR_HISTOGRAM;
+        }
+        
+        if ( Math.abs(len) > MAX_SIZE_FOR_HISTOGRAM )
+            return;
+        
+        nIndels++;
+        counts.put(len, counts.get(len) + 1);
+    }
+}
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/tools/walkers/varianteval/evaluators/IndelSummary.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/tools/walkers/varianteval/evaluators/IndelSummary.java
new file mode 100644
index 0000000..484541e
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/tools/walkers/varianteval/evaluators/IndelSummary.java
@@ -0,0 +1,259 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.tools.walkers.varianteval.evaluators;
+
+import org.apache.log4j.Logger;
+import org.broadinstitute.gatk.engine.contexts.AlignmentContext;
+import org.broadinstitute.gatk.engine.contexts.ReferenceContext;
+import org.broadinstitute.gatk.engine.refdata.RefMetaDataTracker;
+import org.broadinstitute.gatk.tools.walkers.varianteval.util.Analysis;
+import org.broadinstitute.gatk.tools.walkers.varianteval.util.DataPoint;
+import org.broadinstitute.gatk.utils.Utils;
+import org.broadinstitute.gatk.utils.exceptions.ReviewedGATKException;
+import htsjdk.variant.variantcontext.Allele;
+import htsjdk.variant.variantcontext.Genotype;
+import htsjdk.variant.variantcontext.VariantContext;
+
+ at Analysis(description = "Evaluation summary for indels")
+public class IndelSummary extends VariantEvaluator implements StandardEval {
+    final protected static Logger logger = Logger.getLogger(IndelSummary.class);
+
+    //
+    // counts of snps and indels
+    //
+    @DataPoint(description = "Number of SNPs", format = "%d")
+    public int n_SNPs = 0;
+
+    @DataPoint(description = "Number of singleton SNPs", format = "%d")
+    public int n_singleton_SNPs = 0;
+
+    @DataPoint(description = "Number of indels", format = "%d")
+    public int n_indels = 0;
+
+    @DataPoint(description = "Number of singleton indels", format = "%d")
+    public int n_singleton_indels = 0;
+
+    //
+    // gold standard
+    //
+    @DataPoint(description = "Number of Indels overlapping gold standard sites", format = "%d")
+    public int n_indels_matching_gold_standard = 0;
+
+    @DataPoint(description = "Percent of indels overlapping gold standard sites")
+    public String gold_standard_matching_rate;
+
+    //
+    // multi-allelics
+    //
+    // Number of Indels Sites (counts one for any number of alleles at site)
+    public int nIndelSites = 0;
+
+    @DataPoint(description = "Number of sites with where the number of alleles is greater than 2")
+    public int n_multiallelic_indel_sites = 0;
+
+    @DataPoint(description = "Percent of indel sites that are multi-allelic")
+    public String percent_of_sites_with_more_than_2_alleles;
+
+    //
+    // snp : indel ratios
+    //
+    @DataPoint(description = "SNP to indel ratio")
+    public String SNP_to_indel_ratio;
+
+    @DataPoint(description = "Singleton SNP to indel ratio")
+    public String SNP_to_indel_ratio_for_singletons;
+
+    //
+    // novelty
+    //
+    @DataPoint(description = "Number of novel indels", format = "%d")
+    public int n_novel_indels = 0;
+
+    @DataPoint(description = "Indel novelty rate")
+    public String indel_novelty_rate;
+
+    //
+    // insertions to deletions
+    //
+    @DataPoint(description = "Number of insertion indels")
+    public int n_insertions = 0;
+
+    @DataPoint(description = "Number of deletion indels")
+    public int n_deletions = 0;
+
+    @DataPoint(description = "Insertion to deletion ratio")
+    public String insertion_to_deletion_ratio;
+
+    @DataPoint(description = "Number of large (>10 bp) deletions")
+    public int n_large_deletions = 0;
+
+    @DataPoint(description = "Number of large (>10 bp) insertions")
+    public int n_large_insertions = 0;
+
+    @DataPoint(description = "Ratio of large (>10 bp) insertions to deletions")
+    public String insertion_to_deletion_ratio_for_large_indels;
+
+    //
+    // Frameshifts
+    //
+    @DataPoint(description = "Number of indels in protein-coding regions labeled as frameshift")
+    public int n_coding_indels_frameshifting = 0;
+
+    @DataPoint(description = "Number of indels in protein-coding regions not labeled as frameshift")
+    public int n_coding_indels_in_frame = 0;
+
+    @DataPoint(description = "Frameshift percent")
+    public String frameshift_rate_for_coding_indels;
+
+    //
+    // Het : hom ratios
+    //
+    @DataPoint(description = "Het to hom ratio for SNPs")
+    public String SNP_het_to_hom_ratio;
+
+    @DataPoint(description = "Het to hom ratio for indels")
+    public String indel_het_to_hom_ratio;
+    
+    int nSNPHets = 0, nSNPHoms = 0, nIndelHets = 0, nIndelHoms = 0;
+
+    int[] insertionCountByLength = new int[]{0, 0, 0, 0}; // note that the first element isn't used
+    int[] deletionCountByLength = new int[]{0, 0, 0, 0}; // note that the first element isn't used
+
+    // - Since 1 & 2 bp insertions and 1 & 2 bp deletions are equally likely to cause a
+    // downstream frameshift, if we make the simplifying assumptions that 3 bp ins
+    // and 3bp del (adding/subtracting 1 AA in general) are roughly comparably
+    // selected against, we should see a consistent 1+2 : 3 bp ratio for insertions
+    // as for deletions, and certainly would expect consistency between in/dels that
+    // multiple methods find and in/dels that are unique to one method  (since deletions
+    // are more common and the artifacts differ, it is probably worth looking at the totals,
+    // overlaps and ratios for insertions and deletions separately in the methods
+    // comparison and in this case don't even need to make the simplifying in = del functional assumption
+
+    @DataPoint(description = "ratio of 1 and 2 bp insertions to 3 bp insertions")
+    public String ratio_of_1_and_2_to_3_bp_insertions;
+
+    @DataPoint(description = "ratio of 1 and 2 bp deletions to 3 bp deletions")
+    public String ratio_of_1_and_2_to_3_bp_deletions;
+
+    public final static int LARGE_INDEL_SIZE_THRESHOLD = 10;
+
+    @Override public int getComparisonOrder() { return 2; }
+
+    public void update2(VariantContext eval, VariantContext comp, RefMetaDataTracker tracker, ReferenceContext ref, AlignmentContext context) {
+        if ( eval == null || (getWalker().ignoreAC0Sites() && eval.isMonomorphicInSamples()) )
+            return;
+
+        // update counts
+        switch ( eval.getType() ) {
+            case SNP:
+                n_SNPs += eval.getNAlleles() - 1; // -1 for ref
+                if ( variantWasSingleton(eval) ) n_singleton_SNPs++;
+
+                // collect information about het / hom ratio
+                for ( final Genotype g : eval.getGenotypes() ) {
+                    if ( g.isHet() ) nSNPHets++;
+                    if ( g.isHomVar() ) nSNPHoms++;
+                }
+                break;
+            case INDEL:
+                final VariantContext gold = getWalker().goldStandard == null ? null : tracker.getFirstValue(getWalker().goldStandard);
+
+                nIndelSites++;
+                if ( ! eval.isBiallelic() ) n_multiallelic_indel_sites++;
+
+                // collect information about het / hom ratio
+                for ( final Genotype g : eval.getGenotypes() ) {
+                    if ( g.isHet() ) nIndelHets++;
+                    if ( g.isHomVar() ) nIndelHoms++;
+                }
+
+                for ( Allele alt : eval.getAlternateAlleles() ) {
+                    n_indels++; // +1 for each alt allele
+                    if ( variantWasSingleton(eval) ) n_singleton_indels++;
+                    if ( comp == null ) n_novel_indels++; // TODO -- make this test allele specific?
+                    if ( gold != null ) n_indels_matching_gold_standard++;
+
+                    // ins : del ratios
+                    final int alleleSize = alt.length() - eval.getReference().length();
+                    if ( alleleSize == 0 ) throw new ReviewedGATKException("Allele size not expected to be zero for indel: alt = " + alt + " ref = " + eval.getReference());
+                    if ( alleleSize > 0 ) n_insertions++;
+                    if ( alleleSize < 0 ) n_deletions++;
+
+                    // requires snpEFF annotations
+                    if ( eval.getAttributeAsString("SNPEFF_GENE_BIOTYPE", "missing").equals("protein_coding") ) {
+                        final String effect = eval.getAttributeAsString("SNPEFF_EFFECT", "missing");
+                        if ( effect.equals("missing") ) 
+                            throw new ReviewedGATKException("Saw SNPEFF_GENE_BIOTYPE but unexpected no SNPEFF_EFFECT at " + eval);
+                        if ( effect.equals("FRAME_SHIFT") )
+                            n_coding_indels_frameshifting++;
+                        else if ( effect.startsWith("CODON") )
+                            n_coding_indels_in_frame++;
+                        else
+                            ; // lots of protein coding effects that shouldn't be counted, such as INTRON
+                    }
+
+                    if ( alleleSize > LARGE_INDEL_SIZE_THRESHOLD )
+                        n_large_insertions++;
+                    else if ( alleleSize < -LARGE_INDEL_SIZE_THRESHOLD )
+                        n_large_deletions++;
+                    
+                    // update the baby histogram
+                    final int[] countByLength = alleleSize < 0 ? deletionCountByLength : insertionCountByLength;
+                    final int absSize = Math.abs(alleleSize);
+                    if ( absSize < countByLength.length ) countByLength[absSize]++;
+
+                }
+
+                break;
+            default:
+                // TODO - MIXED, SYMBOLIC, and MNP records are skipped over
+                //throw new UserException.BadInput("Unexpected variant context type: " + eval);
+                break;
+        }
+
+        return;
+    }
+
+    public void finalizeEvaluation() {
+        percent_of_sites_with_more_than_2_alleles = Utils.formattedPercent(n_multiallelic_indel_sites, nIndelSites);
+        SNP_to_indel_ratio = Utils.formattedRatio(n_SNPs, n_indels);
+        SNP_to_indel_ratio_for_singletons = Utils.formattedRatio(n_singleton_SNPs, n_singleton_indels);
+
+        gold_standard_matching_rate = Utils.formattedPercent(n_indels_matching_gold_standard, n_indels);
+        indel_novelty_rate = Utils.formattedNoveltyRate(n_indels - n_novel_indels, n_indels);
+        frameshift_rate_for_coding_indels = Utils.formattedPercent(n_coding_indels_frameshifting, n_coding_indels_in_frame + n_coding_indels_frameshifting);
+
+        ratio_of_1_and_2_to_3_bp_deletions = Utils.formattedRatio(deletionCountByLength[1] + deletionCountByLength[2], deletionCountByLength[3]);
+        ratio_of_1_and_2_to_3_bp_insertions = Utils.formattedRatio(insertionCountByLength[1] + insertionCountByLength[2], insertionCountByLength[3]);
+
+        SNP_het_to_hom_ratio = Utils.formattedRatio(nSNPHets, nSNPHoms);
+        indel_het_to_hom_ratio = Utils.formattedRatio(nIndelHets, nIndelHoms);
+
+        insertion_to_deletion_ratio = Utils.formattedRatio(n_insertions, n_deletions);
+        insertion_to_deletion_ratio_for_large_indels = Utils.formattedRatio(n_large_insertions, n_large_deletions);
+
+    }
+}
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/tools/walkers/varianteval/evaluators/MendelianViolationEvaluator.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/tools/walkers/varianteval/evaluators/MendelianViolationEvaluator.java
new file mode 100644
index 0000000..c01aae1
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/tools/walkers/varianteval/evaluators/MendelianViolationEvaluator.java
@@ -0,0 +1,187 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.tools.walkers.varianteval.evaluators;
+
+import org.broadinstitute.gatk.engine.contexts.AlignmentContext;
+import org.broadinstitute.gatk.engine.contexts.ReferenceContext;
+import org.broadinstitute.gatk.engine.refdata.RefMetaDataTracker;
+import org.broadinstitute.gatk.engine.samples.Sample;
+import org.broadinstitute.gatk.tools.walkers.varianteval.VariantEval;
+import org.broadinstitute.gatk.tools.walkers.varianteval.util.Analysis;
+import org.broadinstitute.gatk.tools.walkers.varianteval.util.DataPoint;
+import org.broadinstitute.gatk.utils.MendelianViolation;
+import htsjdk.variant.variantcontext.VariantContext;
+
+import java.util.Map;
+import java.util.Set;
+
+/**
+ * Mendelian violation detection and counting
+ * <p/>
+ * a violation looks like:
+ * Suppose dad = A/B and mom = C/D
+ * The child can be [A or B] / [C or D].
+ * If the child doesn't match this, the site is a violation
+ * <p/>
+ * Some examples:
+ * <p/>
+ * mom = A/A, dad = C/C
+ * child can be A/C only
+ * <p/>
+ * mom = A/C, dad = C/C
+ * child can be A/C or C/C
+ * <p/>
+ * mom = A/C, dad = A/C
+ * child can be A/A, A/C, C/C
+ * <p/>
+ * The easiest way to do this calculation is to:
+ * <p/>
+ * Get alleles for mom => A/B
+ * Get alleles for dad => C/D
+ * Make allowed genotypes for child: A/C, A/D, B/C, B/D
+ * Check that the child is one of these.
+ */
+ at Analysis(name = "Mendelian Violation Evaluator", description = "Mendelian Violation Evaluator")
+public class MendelianViolationEvaluator extends VariantEvaluator {
+
+    @DataPoint(description = "Number of variants found with at least one family having genotypes", format = "%d")
+    public long nVariants;
+    @DataPoint(description = "Number of variants found with no family having genotypes -- these sites do not count in the nNoCall", format = "%d")
+    public long nSkipped;
+    @DataPoint(description="Number of variants x families called (no missing genotype or lowqual)", format = "%d")
+    public long nFamCalled;
+    @DataPoint(description="Number of variants x families called (no missing genotype or lowqual) that contain at least one var allele.", format = "%d")
+    public long nVarFamCalled;
+    @DataPoint(description="Number of variants x families discarded as low quality", format = "%d")
+    public long nLowQual;
+    @DataPoint(description="Number of variants x families discarded as no call", format = "%d")
+    public long nNoCall;
+    @DataPoint(description="Number of loci with mendelian violations", format = "%d")
+    public long nLociViolations;
+    @DataPoint(description = "Number of mendelian violations found", format = "%d")
+    public long nViolations;
+
+    @DataPoint(description="Number of mendelian violations of the type HOM_REF/HOM_REF -> HOM_VAR", format = "%d")
+    public long mvRefRef_Var;
+    @DataPoint(description="Number of mendelian violations of the type HOM_REF/HOM_REF -> HET", format = "%d")
+    public long mvRefRef_Het;
+    @DataPoint(description="Number of mendelian violations of the type HOM_REF/HET -> HOM_VAR", format = "%d")
+    public long mvRefHet_Var;
+    @DataPoint(description="Number of mendelian violations of the type HOM_REF/HOM_VAR -> HOM_VAR", format = "%d")
+    public long mvRefVar_Var;
+    @DataPoint(description="Number of mendelian violations of the type HOM_REF/HOM_VAR -> HOM_REF", format = "%d")
+    public long mvRefVar_Ref;
+    @DataPoint(description="Number of mendelian violations of the type HOM_VAR/HET -> HOM_REF", format = "%d")
+    public long mvVarHet_Ref;
+    @DataPoint(description="Number of mendelian violations of the type HOM_VAR/HOM_VAR -> HOM_REF", format = "%d")
+    public long mvVarVar_Ref;
+    @DataPoint(description="Number of mendelian violations of the type HOM_VAR/HOM_VAR -> HET", format = "%d")
+    public long mvVarVar_Het;
+
+    @DataPoint(description="Number of HomRef/HomRef/HomRef trios", format = "%d")
+    public long HomRefHomRef_HomRef;
+    @DataPoint(description="Number of Het/Het/Het trios", format = "%d")
+    public long HetHet_Het;
+    @DataPoint(description="Number of Het/Het/HomRef trios", format = "%d")
+    public long HetHet_HomRef;
+    @DataPoint(description="Number of Het/Het/HomVar trios", format = "%d")
+    public long HetHet_HomVar;
+    @DataPoint(description="Number of HomVar/HomVar/HomVar trios", format = "%d")
+    public long HomVarHomVar_HomVar;
+    @DataPoint(description="Number of HomRef/HomVar/Het trios", format = "%d")
+    public long HomRefHomVAR_Het;
+    @DataPoint(description="Number of ref alleles inherited from het/het parents", format = "%d")
+    public long HetHet_inheritedRef;
+    @DataPoint(description="Number of var alleles inherited from het/het parents", format = "%d")
+    public long HetHet_inheritedVar;
+    @DataPoint(description="Number of ref alleles inherited from homRef/het parents", format = "%d")
+    public long HomRefHet_inheritedRef;
+    @DataPoint(description="Number of var alleles inherited from homRef/het parents", format = "%d")
+    public long HomRefHet_inheritedVar;
+    @DataPoint(description="Number of ref alleles inherited from homVar/het parents", format = "%d")
+    public long HomVarHet_inheritedRef;
+    @DataPoint(description="Number of var alleles inherited from homVar/het parents", format = "%d")
+    public long HomVarHet_inheritedVar;
+
+    MendelianViolation mv;
+    Map<String,Set<Sample>> families;
+
+    public void initialize(VariantEval walker) {
+        super.initialize(walker);
+        mv = new MendelianViolation(walker.getMendelianViolationQualThreshold(),false);
+        families = walker.getSampleDB().getFamilies();
+    }
+
+    public String getName() {
+        return "mendelian_violations";
+    }
+
+    public int getComparisonOrder() {
+        return 1;   // we only need to see each eval track
+    }
+
+    public void update1(VariantContext vc, RefMetaDataTracker tracker, ReferenceContext ref, AlignmentContext context) {
+        if (vc.isBiallelic() && vc.hasGenotypes()) { // todo -- currently limited to biallelic loci
+
+            if(mv.countViolations(families,vc)>0){
+                nLociViolations++;
+                nViolations += mv.getViolationsCount();
+                mvRefRef_Var += mv.getParentsRefRefChildVar();
+                mvRefRef_Het += mv.getParentsRefRefChildHet();
+                mvRefHet_Var += mv.getParentsRefHetChildVar();
+                mvRefVar_Var += mv.getParentsRefVarChildVar();
+                mvRefVar_Ref += mv.getParentsRefVarChildRef();
+                mvVarHet_Ref += mv.getParentsVarHetChildRef();
+                mvVarVar_Ref += mv.getParentsVarVarChildRef();
+                mvVarVar_Het += mv.getParentsVarVarChildHet();
+
+            }
+            HomRefHomRef_HomRef += mv.getRefRefRef();
+            HetHet_Het += mv.getHetHetHet();
+            HetHet_HomRef += mv.getHetHetHomRef();
+            HetHet_HomVar += mv.getHetHetHomVar();
+            HomVarHomVar_HomVar += mv.getVarVarVar();
+            HomRefHomVAR_Het += mv.getRefVarHet();
+            HetHet_inheritedRef += mv.getParentsHetHetInheritedRef();
+            HetHet_inheritedVar += mv.getParentsHetHetInheritedVar();
+            HomRefHet_inheritedRef += mv.getParentsRefHetInheritedRef();
+            HomRefHet_inheritedVar += mv.getParentsRefHetInheritedVar();
+            HomVarHet_inheritedRef += mv.getParentsVarHetInheritedRef();
+            HomVarHet_inheritedVar += mv.getParentsVarHetInheritedVar();
+
+            if(mv.getFamilyCalledCount()>0){
+                nVariants++;
+                nFamCalled += mv.getFamilyCalledCount();
+                nLowQual += mv.getFamilyLowQualsCount();
+                nNoCall += mv.getFamilyNoCallCount();
+                nVarFamCalled += mv.getVarFamilyCalledCount();
+            }
+            else{
+                nSkipped++;
+            }
+        }
+    }
+}
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/tools/walkers/varianteval/evaluators/MultiallelicSummary.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/tools/walkers/varianteval/evaluators/MultiallelicSummary.java
new file mode 100644
index 0000000..88543b5
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/tools/walkers/varianteval/evaluators/MultiallelicSummary.java
@@ -0,0 +1,164 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.tools.walkers.varianteval.evaluators;
+
+import org.apache.log4j.Logger;
+import org.broadinstitute.gatk.engine.contexts.AlignmentContext;
+import org.broadinstitute.gatk.engine.contexts.ReferenceContext;
+import org.broadinstitute.gatk.engine.refdata.RefMetaDataTracker;
+import org.broadinstitute.gatk.tools.walkers.varianteval.util.Analysis;
+import org.broadinstitute.gatk.tools.walkers.varianteval.util.DataPoint;
+import org.broadinstitute.gatk.utils.Utils;
+import org.broadinstitute.gatk.utils.variant.GATKVariantContextUtils;
+import htsjdk.variant.variantcontext.Allele;
+import htsjdk.variant.variantcontext.VariantContext;
+
+ at Analysis(description = "Evaluation summary for multi-allelic variants")
+public class MultiallelicSummary extends VariantEvaluator implements StandardEval {
+    final protected static Logger logger = Logger.getLogger(MultiallelicSummary.class);
+
+    public enum Type {
+        SNP, INDEL
+    }
+
+    // basic counts on various rates found
+    @DataPoint(description = "Number of processed loci", format = "%d")
+    public long nProcessedLoci = 0;
+
+    @DataPoint(description = "Number of SNPs", format = "%d")
+    public int nSNPs = 0;
+    @DataPoint(description = "Number of multi-allelic SNPs", format = "%d")
+    public int nMultiSNPs = 0;
+    @DataPoint(description = "% processed sites that are multi-allelic SNPs", format = "%.5f")
+    public double processedMultiSnpRatio = 0;
+    @DataPoint(description = "% SNP sites that are multi-allelic", format = "%.3f")
+    public double variantMultiSnpRatio = 0;
+
+    @DataPoint(description = "Number of Indels", format = "%d")
+    public int nIndels = 0;
+    @DataPoint(description = "Number of multi-allelic Indels", format = "%d")
+    public int nMultiIndels = 0;
+    @DataPoint(description = "% processed sites that are multi-allelic Indels", format = "%.5f")
+    public double processedMultiIndelRatio = 0;
+    @DataPoint(description = "% Indel sites that are multi-allelic", format = "%.3f")
+    public double variantMultiIndelRatio = 0;
+
+    @DataPoint(description = "Number of Transitions", format = "%d")
+    public int nTi = 0;
+    @DataPoint(description = "Number of Transversions", format = "%d")
+    public int nTv = 0;
+    @DataPoint(description = "Overall TiTv ratio", format = "%.2f")
+    public double TiTvRatio = 0;
+
+    @DataPoint(description = "Multi-allelic SNPs partially known", format = "%d")
+    public int knownSNPsPartial = 0;
+    @DataPoint(description = "Multi-allelic SNPs completely known", format = "%d")
+    public int knownSNPsComplete = 0;
+    @DataPoint(description = "Multi-allelic SNP Novelty Rate")
+    public String SNPNoveltyRate = "NA";
+
+    //TODO -- implement me
+    //@DataPoint(description = "Multi-allelic Indels partially known", format = "%d")
+    public int knownIndelsPartial = 0;
+    //@DataPoint(description = "Multi-allelic Indels completely known", format = "%d")
+    public int knownIndelsComplete = 0;
+    //@DataPoint(description = "Multi-allelic Indel Novelty Rate")
+    public String indelNoveltyRate = "NA";
+
+
+    @Override public int getComparisonOrder() { return 2; }
+
+    public void update2(VariantContext eval, VariantContext comp, RefMetaDataTracker tracker, ReferenceContext ref, AlignmentContext context) {
+        if ( eval == null || (getWalker().ignoreAC0Sites() && eval.isMonomorphicInSamples()) )
+            return;
+
+        // update counts
+        switch ( eval.getType() ) {
+            case SNP:
+                nSNPs++;
+                if ( !eval.isBiallelic() ) {
+                    nMultiSNPs++;
+                    calculatePairwiseTiTv(eval);
+                    calculateSNPPairwiseNovelty(eval, comp);
+                }
+                break;
+            case INDEL:
+                nIndels++;
+                if ( !eval.isBiallelic() ) {
+                    nMultiIndels++;
+                    calculateIndelPairwiseNovelty(eval, comp);
+                }
+                break;
+            default:
+                //throw new UserException.BadInput("Unexpected variant context type: " + eval);
+                break;
+        }
+
+        return;
+    }
+
+    private void calculatePairwiseTiTv(VariantContext vc) {
+        for ( Allele alt : vc.getAlternateAlleles() ) {
+            if ( GATKVariantContextUtils.isTransition(vc.getReference(), alt) )
+                nTi++;
+            else
+                nTv++;
+        }
+    }
+
+    private void calculateSNPPairwiseNovelty(VariantContext eval, VariantContext comp) {
+        if ( comp == null )
+            return;
+
+        int knownAlleles = 0;
+        for ( Allele alt : eval.getAlternateAlleles() ) {
+            if ( comp.getAlternateAlleles().contains(alt) )
+                knownAlleles++;
+        }
+
+        if ( knownAlleles == eval.getAlternateAlleles().size() )
+            knownSNPsComplete++;
+        else if ( knownAlleles > 0 )
+            knownSNPsPartial++;
+    }
+
+    private void calculateIndelPairwiseNovelty(VariantContext eval, VariantContext comp) {
+        // TODO -- implement me
+    }
+
+    public void finalizeEvaluation() {
+        nProcessedLoci = getWalker().getnProcessedLoci();
+        processedMultiSnpRatio = (double)nMultiSNPs / (double)nProcessedLoci;
+        variantMultiSnpRatio = (double)nMultiSNPs / (double)nSNPs;
+        processedMultiIndelRatio = (double)nMultiIndels / (double)nProcessedLoci;
+        variantMultiIndelRatio = (double)nMultiIndels / (double)nIndels;
+
+        TiTvRatio = (double)nTi / (double)nTv;
+
+        SNPNoveltyRate = Utils.formattedNoveltyRate(knownSNPsPartial + knownSNPsComplete, nMultiSNPs);
+        indelNoveltyRate = Utils.formattedNoveltyRate(knownIndelsPartial + knownIndelsComplete, nMultiSNPs);
+    }
+}
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/tools/walkers/varianteval/evaluators/PrintMissingComp.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/tools/walkers/varianteval/evaluators/PrintMissingComp.java
new file mode 100644
index 0000000..0d3d4cf
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/tools/walkers/varianteval/evaluators/PrintMissingComp.java
@@ -0,0 +1,57 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.tools.walkers.varianteval.evaluators;
+
+import org.broadinstitute.gatk.engine.contexts.AlignmentContext;
+import org.broadinstitute.gatk.engine.contexts.ReferenceContext;
+import org.broadinstitute.gatk.engine.refdata.RefMetaDataTracker;
+import org.broadinstitute.gatk.tools.walkers.varianteval.util.Analysis;
+import org.broadinstitute.gatk.tools.walkers.varianteval.util.DataPoint;
+import htsjdk.variant.variantcontext.VariantContext;
+
+ at Analysis(name = "PrintMissingComp", description = "the overlap between eval and comp sites")
+public class PrintMissingComp extends VariantEvaluator {
+    @DataPoint(description = "number of eval sites outside of comp sites", format = "%d")
+    public long nMissing = 0;
+
+    public String getName() {
+        return "PrintMissingComp";
+    }
+
+    public int getComparisonOrder() {
+        return 2;   // we need to see each eval track and each comp track
+    }
+
+    public void update2(VariantContext eval, VariantContext comp, RefMetaDataTracker tracker, ReferenceContext ref, AlignmentContext context) {
+        final boolean compIsGood = comp != null && comp.isNotFiltered() && comp.isSNP();
+        final boolean evalIsGood = eval != null && eval.isSNP();
+
+        if ( compIsGood & ! evalIsGood ) {
+            nMissing++;
+            super.getWalker().getLogger().info("MissingFrom" + eval.toString() + " is missing from " + comp.getSource());
+        }
+    }
+}
\ No newline at end of file
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/tools/walkers/varianteval/evaluators/StandardEval.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/tools/walkers/varianteval/evaluators/StandardEval.java
new file mode 100644
index 0000000..c3b75c1
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/tools/walkers/varianteval/evaluators/StandardEval.java
@@ -0,0 +1,28 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.tools.walkers.varianteval.evaluators;
+
+public interface StandardEval {}
\ No newline at end of file
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/tools/walkers/varianteval/evaluators/ThetaVariantEvaluator.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/tools/walkers/varianteval/evaluators/ThetaVariantEvaluator.java
new file mode 100644
index 0000000..60a4881
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/tools/walkers/varianteval/evaluators/ThetaVariantEvaluator.java
@@ -0,0 +1,143 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.tools.walkers.varianteval.evaluators;
+
+import org.broadinstitute.gatk.engine.contexts.AlignmentContext;
+import org.broadinstitute.gatk.engine.contexts.ReferenceContext;
+import org.broadinstitute.gatk.engine.refdata.RefMetaDataTracker;
+import org.broadinstitute.gatk.tools.walkers.varianteval.util.Analysis;
+import org.broadinstitute.gatk.tools.walkers.varianteval.util.DataPoint;
+import htsjdk.variant.variantcontext.Allele;
+import htsjdk.variant.variantcontext.Genotype;
+import htsjdk.variant.variantcontext.VariantContext;
+
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ConcurrentMap;
+
+ at Analysis(description = "Computes different estimates of theta based on variant sites and genotypes")
+public class ThetaVariantEvaluator extends VariantEvaluator {
+    @DataPoint(description = "Average heterozygosity at variant sites; note that missing genotypes are ignored when computing this value", format = "%.8f")
+    public double avgHet = 0.0;
+    @DataPoint(description = "Average pairwise differences at aligned sequences; averaged over both number of sequeneces and number of variant sites; note that missing genotypes are ignored when computing this value", format = "%.8f")
+    public double avgAvgDiffs = 0.0;
+    @DataPoint(description = "Sum of heterozygosity over all variant sites; divide this by total target to get estimate of per base theta", format = "%.8f")
+    public double totalHet = 0.0;
+    @DataPoint(description = "Sum of pairwise diffs over all variant sites; divide this by total target to get estimate of per base theta", format = "%.8f")
+    public double totalAvgDiffs = 0.0;
+    @DataPoint(description = "Theta for entire region estimated based on number of segregating sites; divide ths by total target to get estimate of per base theta", format = "%.8f")
+    public double thetaRegionNumSites = 0.0;
+
+    //helper variables
+    double numSites = 0;
+
+    public int getComparisonOrder() {
+        return 1;
+    }
+
+    public void update1(VariantContext vc, RefMetaDataTracker tracker, ReferenceContext ref, AlignmentContext context) {
+        if (vc == null || !vc.isSNP() || (getWalker().ignoreAC0Sites() && vc.isMonomorphicInSamples())) {
+            return;
+        }
+
+        //this maps allele to a count
+        ConcurrentMap<String, Integer> alleleCounts = new ConcurrentHashMap<String, Integer>();
+
+        int numHetsHere = 0;
+        int numGenosHere = 0;
+        int numIndsHere = 0;
+
+        for (final Genotype genotype : vc.getGenotypes()) {
+            numIndsHere++;
+            if (!genotype.isNoCall()) {
+                //increment stats for heterozygosity
+                if (genotype.isHet()) {
+                    numHetsHere++;
+                }
+
+                numGenosHere++;
+                //increment stats for pairwise mismatches
+
+                for (Allele allele : genotype.getAlleles()) {
+                    if (allele.isCalled()) {
+                        String alleleString = allele.toString();
+                        alleleCounts.putIfAbsent(alleleString, 0);
+                        alleleCounts.put(alleleString, alleleCounts.get(alleleString) + 1);
+                    }
+                }
+            }
+        }
+        if (numGenosHere > 0) {
+            //only if have one called genotype at least
+            this.numSites++;
+
+            this.totalHet += numHetsHere / (double)numGenosHere;
+
+            //compute based on num sites
+            float harmonicFactor = 0;
+            for (int i = 1; i <= numIndsHere; i++) {
+                harmonicFactor += 1.0 / i;
+            }
+            this.thetaRegionNumSites += 1.0 / harmonicFactor;
+
+            //now compute pairwise mismatches
+            float numPairwise = 0;
+            int numDiffs = 0;
+            for (String allele1 : alleleCounts.keySet()) {
+                int allele1Count = alleleCounts.get(allele1);
+
+                for (String allele2 : alleleCounts.keySet()) {
+                    if (allele1.compareTo(allele2) < 0) {
+                        continue;
+                    }
+                    if (allele1 .compareTo(allele2) == 0) {
+                        numPairwise += allele1Count * (allele1Count - 1) * .5;
+
+                    }
+                    else {
+                        int allele2Count = alleleCounts.get(allele2);
+                        numPairwise += allele1Count * allele2Count;
+                        numDiffs += allele1Count * allele2Count;
+                    }
+                }
+            }
+
+            if (numPairwise > 0) {
+                this.totalAvgDiffs += numDiffs / numPairwise;
+            }
+        }
+    }
+
+    @Override
+    public void finalizeEvaluation() {
+
+        if (this.numSites > 0) {
+
+            this.avgHet = this.totalHet / this.numSites;
+            this.avgAvgDiffs = this.totalAvgDiffs / this.numSites;
+
+        }
+    }
+}
\ No newline at end of file
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/tools/walkers/varianteval/evaluators/TiTvVariantEvaluator.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/tools/walkers/varianteval/evaluators/TiTvVariantEvaluator.java
new file mode 100644
index 0000000..1919c5f
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/tools/walkers/varianteval/evaluators/TiTvVariantEvaluator.java
@@ -0,0 +1,100 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.tools.walkers.varianteval.evaluators;
+
+import org.broadinstitute.gatk.engine.contexts.AlignmentContext;
+import org.broadinstitute.gatk.engine.contexts.ReferenceContext;
+import org.broadinstitute.gatk.engine.refdata.RefMetaDataTracker;
+import org.broadinstitute.gatk.tools.walkers.varianteval.util.Analysis;
+import org.broadinstitute.gatk.tools.walkers.varianteval.util.DataPoint;
+import org.broadinstitute.gatk.utils.BaseUtils;
+import org.broadinstitute.gatk.utils.variant.GATKVariantContextUtils;
+import htsjdk.variant.variantcontext.VariantContext;
+
+ at Analysis(description = "Ti/Tv Variant Evaluator")
+public class TiTvVariantEvaluator extends VariantEvaluator implements StandardEval {
+    @DataPoint(description = "number of transition loci", format = "%d")
+    public long nTi = 0;
+    @DataPoint(description = "number of transversion loci", format = "%d")
+    public long nTv = 0;
+    @DataPoint(description = "the transition to transversion ratio", format = "%.2f")
+    public double tiTvRatio = 0.0;
+    @DataPoint(description = "number of comp transition sites", format = "%d")
+    public long nTiInComp = 0;
+    @DataPoint(description = "number of comp transversion sites", format = "%d")
+    public long nTvInComp = 0;
+    @DataPoint(description = "the transition to transversion ratio for comp sites", format = "%.2f")
+    public double TiTvRatioStandard = 0.0;
+    @DataPoint(description = "number of derived transition loci", format = "%d")
+    public long nTiDerived = 0;
+    @DataPoint(description = "number of derived transversion loci", format = "%d")
+    public long nTvDerived = 0;
+    @DataPoint(description = "the derived transition to transversion ratio", format = "%.2f")
+    public double tiTvDerivedRatio = 0.0;
+
+    public int getComparisonOrder() {
+        return 2;   // we only need to see each eval track
+    }
+
+    public void updateTiTv(VariantContext vc, boolean updateStandard) {
+        if (vc != null && vc.isSNP() && vc.isBiallelic() && vc.isPolymorphicInSamples()) {
+            if ( GATKVariantContextUtils.isTransition(vc)) {
+                if (updateStandard) nTiInComp++;
+                else nTi++;
+            } else {                                
+                if (updateStandard) nTvInComp++;
+                else nTv++;
+            }
+
+            if (vc.hasAttribute("ANCESTRALALLELE")) {
+                final String aaStr = vc.getAttributeAsString("ANCESTRALALLELE", "null").toUpperCase();
+                if ( ! aaStr.equals(".") ) {
+                    switch ( BaseUtils.SNPSubstitutionType(aaStr.getBytes()[0], vc.getAlternateAllele(0).getBases()[0] ) ) {
+                        case TRANSITION: nTiDerived++; break;
+                        case TRANSVERSION: nTvDerived++; break;
+                        default: break;
+                    }
+                }
+            }
+        }
+    }
+
+    @Override
+    public void update2(VariantContext eval, VariantContext comp, RefMetaDataTracker tracker, ReferenceContext ref, AlignmentContext context) {
+        if (eval != null)
+            updateTiTv(eval, false);
+        if (comp != null)
+            updateTiTv(comp, true);
+    }
+
+    @Override
+    public void finalizeEvaluation() {
+        // the ti/tv ratio needs to be set (it's not calculated per-variant).
+        this.tiTvRatio = rate(nTi,nTv);
+        this.tiTvDerivedRatio = rate(nTiDerived,nTvDerived);
+        this.TiTvRatioStandard = rate(nTiInComp, nTvInComp);
+    }
+}
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/tools/walkers/varianteval/evaluators/ValidationReport.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/tools/walkers/varianteval/evaluators/ValidationReport.java
new file mode 100644
index 0000000..664e5f2
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/tools/walkers/varianteval/evaluators/ValidationReport.java
@@ -0,0 +1,183 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.tools.walkers.varianteval.evaluators;
+
+import org.broadinstitute.gatk.engine.contexts.AlignmentContext;
+import org.broadinstitute.gatk.engine.contexts.ReferenceContext;
+import org.broadinstitute.gatk.engine.refdata.RefMetaDataTracker;
+import org.broadinstitute.gatk.tools.walkers.varianteval.util.Analysis;
+import org.broadinstitute.gatk.tools.walkers.varianteval.util.DataPoint;
+import htsjdk.variant.vcf.VCFConstants;
+import org.broadinstitute.gatk.utils.exceptions.ReviewedGATKException;
+import htsjdk.variant.variantcontext.Allele;
+import htsjdk.variant.variantcontext.VariantContext;
+
+import java.util.Collection;
+import java.util.Set;
+
+/**
+ * The Broad Institute
+ * SOFTWARE COPYRIGHT NOTICE AGREEMENT
+ * This software and its documentation are copyright 2009 by the
+ * Broad Institute/Massachusetts Institute of Technology. All rights are reserved.
+ * <p/>
+ * This software is supplied without any warranty or guaranteed support whatsoever. Neither
+ * the Broad Institute nor MIT can be responsible for its use, misuse, or functionality.
+ */
+ at Analysis(description = "Assess site accuracy and sensitivity of callset against follow-up validation assay")
+public class ValidationReport extends VariantEvaluator implements StandardEval {
+    // todo -- note this isn't strictly allele away.  It's really focused on sites.  A/T call at a validated A/G site is currently counted as a TP
+    @DataPoint(description = "nComp", format = "%d") public int nComp = 0;
+    @DataPoint(description = "TP", format = "%d") public int TP = 0;
+    @DataPoint(description = "FP", format = "%d") public int FP = 0;
+    @DataPoint(description = "FN", format = "%d") public int FN = 0;
+    @DataPoint(description = "TN", format = "%d") public int TN = 0;
+
+    @DataPoint(description = "Sensitivity", format = "%.2f") public double sensitivity = 0;
+    @DataPoint(description = "Specificity", format = "%.2f") public double specificity = 0;
+    @DataPoint(description = "PPV", format = "%.2f") public double PPV = 0;
+    @DataPoint(description = "FDR", format = "%.2f") public double FDR = 0;
+
+    @DataPoint(description = "CompMonoEvalNoCall", format = "%d") public int CompMonoEvalNoCall = 0;
+    @DataPoint(description = "CompMonoEvalFiltered", format = "%d") public int CompMonoEvalFiltered = 0;
+    @DataPoint(description = "CompMonoEvalMono", format = "%d") public int CompMonoEvalMono = 0;
+    @DataPoint(description = "CompMonoEvalPoly", format = "%d") public int CompMonoEvalPoly = 0;
+
+    @DataPoint(description = "CompPolyEvalNoCall", format = "%d") public int CompPolyEvalNoCall = 0;
+    @DataPoint(description = "CompPolyEvalFiltered", format = "%d") public int CompPolyEvalFiltered = 0;
+    @DataPoint(description = "CompPolyEvalMono", format = "%d") public int CompPolyEvalMono = 0;
+    @DataPoint(description = "CompPolyEvalPoly", format = "%d") public int CompPolyEvalPoly = 0;
+
+    @DataPoint(description = "CompFiltered", format = "%d") public int CompFiltered = 0;
+    @DataPoint(description = "Eval and comp have different alleles", format = "%d") public int nDifferentAlleleSites = 0;
+
+    private static final boolean TREAT_ALL_SITES_IN_EVAL_VCF_AS_CALLED = true;
+    private static final boolean REQUIRE_IDENTICAL_ALLELES = false;
+
+    private enum SiteStatus { NO_CALL, FILTERED, MONO, POLY }
+
+    // Counts of ValidationSiteStatus x CallSiteStatus
+    final int[][] counts = new int[SiteStatus.values().length][SiteStatus.values().length];
+
+    @Override public int getComparisonOrder() { return 2; }
+
+    @Override
+    public void finalizeEvaluation() {
+        for ( SiteStatus x : SiteStatus.values() )
+            CompFiltered += getCounts(SiteStatus.FILTERED, x);
+
+        CompMonoEvalNoCall = getCounts(SiteStatus.MONO, SiteStatus.NO_CALL);
+        CompMonoEvalFiltered = getCounts(SiteStatus.MONO, SiteStatus.FILTERED);
+        CompMonoEvalMono = getCounts(SiteStatus.MONO, SiteStatus.MONO);
+        CompMonoEvalPoly = getCounts(SiteStatus.MONO, SiteStatus.POLY);
+
+        CompPolyEvalNoCall = getCounts(SiteStatus.POLY, SiteStatus.NO_CALL);
+        CompPolyEvalFiltered = getCounts(SiteStatus.POLY, SiteStatus.FILTERED);
+        CompPolyEvalMono = getCounts(SiteStatus.POLY, SiteStatus.MONO);
+        CompPolyEvalPoly = getCounts(SiteStatus.POLY, SiteStatus.POLY);
+
+        TP = CompPolyEvalPoly;
+        FN = CompPolyEvalNoCall + CompPolyEvalFiltered + CompPolyEvalMono;
+        FP = CompMonoEvalPoly;
+        TN = CompMonoEvalNoCall + CompMonoEvalFiltered + CompMonoEvalMono;
+
+        for ( SiteStatus x : SiteStatus.values() )
+            for ( SiteStatus y : SiteStatus.values() )
+                nComp += getCounts(x, y);
+
+        if ( nComp != TP + FN + FP + TN + CompFiltered )
+            throw new ReviewedGATKException("BUG: nComp != TP + FN + FP + TN + CompFiltered!");
+
+        sensitivity = (100.0 * TP) / (TP + FN);
+        specificity = (TN+FP > 0) ? (100.0 * TN) / (TN + FP) : 100.0;
+        PPV = (100.0 * TP) / (TP + FP);
+        FDR = (100.0 * FP) / (FP + TP);
+    }
+
+    private int getCounts(SiteStatus comp, SiteStatus eval) {
+        return counts[comp.ordinal()][eval.ordinal()];
+    }
+
+    @Override
+    public void update2(VariantContext eval, VariantContext comp, RefMetaDataTracker tracker, ReferenceContext ref, AlignmentContext context) {
+        if ( comp != null ) { // we only need to consider sites in comp
+            if ( REQUIRE_IDENTICAL_ALLELES && (eval != null && haveDifferentAltAlleles(eval, comp)))
+                nDifferentAlleleSites++;
+            else {
+                SiteStatus evalStatus = calcSiteStatus(eval);
+                final Set<String> evalSamples = getWalker().getSampleNamesForEvaluation();
+                if ( comp.hasGenotypes() && ! evalSamples.isEmpty() && comp.hasGenotypes(evalSamples) )
+                    // if we have genotypes in both eval and comp, subset comp down just the samples in eval
+                    comp = comp.subContextFromSamples(evalSamples, false);
+                SiteStatus compStatus = calcSiteStatus(comp);
+                counts[compStatus.ordinal()][evalStatus.ordinal()]++;
+            }
+        }
+    }
+
+    //
+    // helper routines
+    //
+    private SiteStatus calcSiteStatus(VariantContext vc) {
+        if ( vc == null ) return SiteStatus.NO_CALL;
+        if ( vc.isFiltered() ) return SiteStatus.FILTERED;
+        if ( vc.isMonomorphicInSamples() ) return SiteStatus.MONO;
+        if ( vc.hasGenotypes() ) return SiteStatus.POLY;  // must be polymorphic if isMonomorphicInSamples was false and there are genotypes
+
+        if ( vc.hasAttribute(VCFConstants.ALLELE_COUNT_KEY) ) {
+            int ac = 0;
+            if ( vc.getNAlleles() > 2 ) {
+                return SiteStatus.POLY;
+            }
+            else
+                ac = vc.getAttributeAsInt(VCFConstants.ALLELE_COUNT_KEY, 0);
+            return ac > 0 ? SiteStatus.POLY : SiteStatus.MONO;
+        } else {
+            return TREAT_ALL_SITES_IN_EVAL_VCF_AS_CALLED ? SiteStatus.POLY : SiteStatus.NO_CALL; // we can't figure out what to do
+        }
+    }
+
+
+
+    private boolean haveDifferentAltAlleles(VariantContext eval, VariantContext comp) {
+        Collection<Allele> evalAlts = eval.getAlternateAlleles();
+        Collection<Allele> compAlts = comp.getAlternateAlleles();
+        if ( evalAlts.size() != compAlts.size() ) {
+            return true;
+        } else {
+            // same size => every alt from eval must be in comp
+            for ( Allele a : evalAlts ) {
+                if ( ! compAlts.contains(a) ) {
+//                    System.out.printf("Different alleles: %s:%d eval=%s comp=%s\n\t\teval=%s\n\t\tcomp=%s%n",
+//                            eval.getChr(), eval.getStart(), eval.getAlleles(), comp.getAlleles(), eval, comp);
+                    return true;
+                }
+            }
+
+            return false;
+        }
+    }
+}
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/tools/walkers/varianteval/evaluators/VariantEvaluator.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/tools/walkers/varianteval/evaluators/VariantEvaluator.java
new file mode 100644
index 0000000..0984a2e
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/tools/walkers/varianteval/evaluators/VariantEvaluator.java
@@ -0,0 +1,133 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.tools.walkers.varianteval.evaluators;
+
+import org.broadinstitute.gatk.engine.contexts.AlignmentContext;
+import org.broadinstitute.gatk.engine.contexts.ReferenceContext;
+import org.broadinstitute.gatk.engine.refdata.RefMetaDataTracker;
+import org.broadinstitute.gatk.tools.walkers.varianteval.VariantEval;
+import org.broadinstitute.gatk.utils.exceptions.ReviewedGATKException;
+import htsjdk.variant.variantcontext.VariantContext;
+
+public abstract class VariantEvaluator implements Comparable<VariantEvaluator> {
+    private VariantEval walker;
+    private final String simpleName;
+
+    protected VariantEvaluator() {
+        this.simpleName = getClass().getSimpleName();
+    }
+
+    public void initialize(VariantEval walker) {
+        this.walker = walker;
+    }
+
+    public VariantEval getWalker() {
+        return walker;
+    }
+
+    // Should return the number of VariantContexts expected as inputs to update.  Can be 1 or 2
+    public abstract int getComparisonOrder();
+
+    // called at all sites, regardless of eval context itself; useful for counting processed bases
+    // No longer available.  The processed bp is kept in VEW itself for performance reasons
+    //    public void update0(RefMetaDataTracker tracker, ReferenceContext ref, AlignmentContext context) {
+
+    public void update1(VariantContext eval, RefMetaDataTracker tracker, ReferenceContext ref, AlignmentContext context) {
+    }
+
+    public void update2(VariantContext eval, VariantContext comp, RefMetaDataTracker tracker, ReferenceContext ref, AlignmentContext context) {
+    }
+
+    public void finalizeEvaluation() {}
+
+    protected double rate(long n, long d) {
+        return n / (1.0 * Math.max(d, 1));
+    }
+
+    protected long inverseRate(long n, long d) {
+        return n == 0 ? 0 : d / Math.max(n, 1);
+    }
+
+    protected double ratio(long num, long denom) {
+        return ((double)num) / (Math.max(denom, 1));
+    }
+
+    /**
+     * Returns true if the variant in vc was a singleton in the original input evaluation
+     * set, regardless of variant context subsetting that has occurred.
+     * @param eval the VariantContext being assessed for this previous status as a singleton
+     * @return true if eval was originally a singleton site
+     */
+    protected static boolean variantWasSingleton(final VariantContext eval) {
+        return eval.getAttributeAsBoolean(VariantEval.IS_SINGLETON_KEY, false);
+    }
+
+    public final String getSimpleName() {
+        return simpleName;
+    }
+
+    @Override
+    public int compareTo(final VariantEvaluator variantEvaluator) {
+        return getSimpleName().compareTo(variantEvaluator.getSimpleName());
+    }
+
+    /**
+     * Evaluation modules that override this function to indicate that they support
+     * combining the results of two independent collections of eval data into
+     * a single meaningful result.  The purpose of this interface is to
+     * allow us to cut up the input data into many independent stratifications, and then
+     * at the end of the eval run decide which stratifications to combine.  This is
+     * important in the case of AC, where you may have thousands of distinct AC
+     * values that chop up the number of variants to too small a number of variants,
+     * and you'd like to combine the AC values into ranges containing some percent
+     * of the data.
+     *
+     * For example, suppose you have an eval that
+     * counts variants in a variable nVariants.  If you want to be able to combine
+     * multiple evaluations of this type, overload the combine function
+     * with a function that sets this.nVariants += other.nVariants.
+     *
+     * Add in the appropriate fields of the VariantEvaluator T
+     * (of the same type as this object) to the values of this object.
+     *
+     * The values in this and other are implicitly independent, so that
+     * the values can be added together.
+     *
+     * @param other a VariantEvaluator of the same type of this object
+     */
+    public void combine(final VariantEvaluator other) {
+        throw new ReviewedGATKException(getSimpleName() + " doesn't support combining results, sorry");
+    }
+
+    /**
+     * Must be overloaded to return true for evaluation modules that support the combine operation
+     *
+     * @return
+     */
+    public boolean supportsCombine() {
+        return false;
+    }
+}
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/tools/walkers/varianteval/evaluators/VariantSummary.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/tools/walkers/varianteval/evaluators/VariantSummary.java
new file mode 100644
index 0000000..9147330
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/tools/walkers/varianteval/evaluators/VariantSummary.java
@@ -0,0 +1,277 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.tools.walkers.varianteval.evaluators;
+
+import htsjdk.samtools.util.IntervalTree;
+import org.apache.log4j.Logger;
+import org.broadinstitute.gatk.engine.contexts.AlignmentContext;
+import org.broadinstitute.gatk.engine.contexts.ReferenceContext;
+import org.broadinstitute.gatk.engine.refdata.RefMetaDataTracker;
+import org.broadinstitute.gatk.tools.walkers.varianteval.VariantEval;
+import org.broadinstitute.gatk.tools.walkers.varianteval.util.Analysis;
+import org.broadinstitute.gatk.tools.walkers.varianteval.util.DataPoint;
+import org.broadinstitute.gatk.utils.GenomeLoc;
+import org.broadinstitute.gatk.utils.Utils;
+import org.broadinstitute.gatk.utils.variant.GATKVariantContextUtils;
+import htsjdk.variant.vcf.VCFConstants;
+import org.broadinstitute.gatk.utils.interval.IntervalUtils;
+import htsjdk.variant.variantcontext.Genotype;
+import htsjdk.variant.variantcontext.VariantContext;
+
+import java.util.*;
+
+ at Analysis(description = "1000 Genomes Phase I summary of variants table")
+public class VariantSummary extends VariantEvaluator implements StandardEval {
+    final protected static Logger logger = Logger.getLogger(VariantSummary.class);
+
+    /** Indels with size greater than this value are tallied in the CNV column */
+    private final static int MAX_INDEL_LENGTH = 50;
+    private final static double MIN_CNV_OVERLAP = 0.5;
+
+    public enum Type {
+        SNP, INDEL, CNV
+    }
+
+    Map<String, IntervalTree<GenomeLoc>> knownCNVs = null;
+
+    // basic counts on various rates found
+    @DataPoint(description = "Number of samples", format = "%d")
+    public long nSamples = 0;
+
+    @DataPoint(description = "Number of processed loci", format = "%d")
+    public long nProcessedLoci = 0;
+
+    @DataPoint(description = "Number of SNPs", format = "%d")
+    public long nSNPs = 0;
+    @DataPoint(description = "Overall TiTv ratio", format = "%.2f")
+    public double TiTvRatio = 0;
+    @DataPoint(description = "SNP Novelty Rate", format = "%s")
+    public String SNPNoveltyRate = "NA";
+    @DataPoint(description = "Mean number of SNPs per individual", format = "%d")
+    public long nSNPsPerSample = 0;
+    @DataPoint(description = "Mean TiTv ratio per individual", format = "%.2f")
+    public double TiTvRatioPerSample = 0;
+    @DataPoint(description = "Mean depth of coverage per sample at SNPs", format = "%.1f")
+    public double SNPDPPerSample = 0;
+
+    @DataPoint(description = "Number of Indels", format = "%d")
+    public long nIndels = 0;
+    @DataPoint(description = "Indel Novelty Rate", format = "%s")
+    public String IndelNoveltyRate = "NA";
+    @DataPoint(description = "Mean number of Indels per individual", format = "%d")
+    public long nIndelsPerSample = 0;
+    @DataPoint(description = "Mean depth of coverage per sample at Indels", format = "%.1f")
+    public double IndelDPPerSample = 0;
+
+    @DataPoint(description = "Number of SVs", format = "%d")
+    public long nSVs = 0;
+    @DataPoint(description = "SV Novelty Rate", format = "%s")
+    public String SVNoveltyRate = "NA";
+    @DataPoint(description = "Mean number of SVs per individual", format = "%d")
+    public long nSVsPerSample = 0;
+
+    TypeSampleMap allVariantCounts, knownVariantCounts;
+    TypeSampleMap countsPerSample;
+    TypeSampleMap transitionsPerSample, transversionsPerSample;
+    TypeSampleMap depthPerSample;
+
+    private final static String ALL = "ALL";
+
+    private class TypeSampleMap extends EnumMap<Type, Map<String, Integer>> {
+        public TypeSampleMap(final Collection<String> samples) {
+            super(Type.class);
+            for ( Type type : Type.values() ) {
+                Map<String, Integer> bySample = new HashMap<String, Integer>(samples.size());
+                for ( final String sample : samples ) {
+                    bySample.put(sample, 0);
+                }
+                bySample.put(ALL, 0);
+                this.put(type, bySample);
+            }
+        }
+
+        public final void inc(final Type type, final String sample) {
+            final int count = this.get(type).get(sample);
+            get(type).put(sample, count + 1);
+        }
+
+        public final int all(Type type) {
+            return get(type).get(ALL);
+        }
+
+        public final int meanValue(Type type) {
+            long sum = 0;
+            int n = 0;
+            for ( final Map.Entry<String, Integer> pair : get(type).entrySet() ) {
+                if ( pair.getKey() != ALL)  { // truly must be string ==
+                    n++;
+                    sum += pair.getValue();
+                }
+            }
+            return (int)(Math.round(sum / (1.0 * n)));
+        }
+
+        public final double ratioValue(Type type, TypeSampleMap denoms, boolean allP) {
+            double sum = 0;
+            int n = 0;
+            for ( final String sample : get(type).keySet() ) {
+                if ( (allP && sample == ALL) || (!allP && sample != ALL) ) { // truly must be string ==
+                    final long num = get(type).get(sample);
+                    final long denom = denoms.get(type).get(sample);
+                    sum += ratio(num, denom);
+                    n++;
+                }
+            }
+
+            return n > 0 ? sum / (1.0 * n) : 0.0;
+        }
+    }
+
+
+    public void initialize(VariantEval walker) {
+        super.initialize(walker);
+
+        nSamples = walker.getSampleNamesForEvaluation().size();
+        countsPerSample = new TypeSampleMap(walker.getSampleNamesForEvaluation());
+        transitionsPerSample = new TypeSampleMap(walker.getSampleNamesForEvaluation());
+        transversionsPerSample = new TypeSampleMap(walker.getSampleNamesForEvaluation());
+        allVariantCounts = new TypeSampleMap(walker.getSampleNamesForEvaluation());
+        knownVariantCounts = new TypeSampleMap(walker.getSampleNamesForEvaluation());
+        depthPerSample = new TypeSampleMap(walker.getSampleNamesForEvaluation());
+
+        if ( walker.knownCNVsFile != null ) {
+            knownCNVs = walker.createIntervalTreeByContig(walker.knownCNVsFile);
+            final List<GenomeLoc> locs = walker.knownCNVsFile.getIntervals(walker.getToolkit());
+            logger.info(String.format("Creating known CNV list %s containing %d intervals covering %d bp",
+                    walker.knownCNVsFile.getSource(), locs.size(), IntervalUtils.intervalSize(locs)));
+        }
+    }
+
+    public int getComparisonOrder() {
+        return 2;   // we only need to see each eval track
+    }
+
+    private Type getType(VariantContext vc) {
+        switch (vc.getType()) {
+            case SNP:
+                return Type.SNP;
+            case INDEL:
+                for ( int l : vc.getIndelLengths() )
+                    if ( Math.abs(l) > MAX_INDEL_LENGTH )
+                        return Type.CNV;
+                return Type.INDEL;
+            case SYMBOLIC:
+                return Type.CNV;
+            default:
+                //throw new UserException.BadInput("Unexpected variant context type: " + vc);
+                return null;
+        }
+    }
+
+    private boolean overlapsKnownCNV(VariantContext cnv) {
+        if ( knownCNVs != null ) {
+            final GenomeLoc loc = getWalker().getToolkit().getGenomeLocParser().createGenomeLoc(cnv);
+            IntervalTree<GenomeLoc> intervalTree = knownCNVs.get(loc.getContig());
+
+            final Iterator<IntervalTree.Node<GenomeLoc>> nodeIt = intervalTree.overlappers(loc.getStart(), loc.getStop());
+            while ( nodeIt.hasNext() ) {
+                final double overlapP = loc.reciprocialOverlapFraction(nodeIt.next().getValue());
+                if ( overlapP > MIN_CNV_OVERLAP )
+                    return true;
+            }
+        }
+
+        return false;
+    }
+
+    public void update2(VariantContext eval, VariantContext comp, RefMetaDataTracker tracker, ReferenceContext ref, AlignmentContext context) {
+        if ( eval == null || (getWalker().ignoreAC0Sites() && eval.isMonomorphicInSamples()) )
+            return;
+
+        final Type type = getType(eval);
+        if ( type == null )
+            return;
+
+        TypeSampleMap titvTable = null;
+
+        // update DP, if possible
+        if ( eval.hasAttribute(VCFConstants.DEPTH_KEY) )
+            depthPerSample.inc(type, ALL);
+
+        // update counts
+        allVariantCounts.inc(type, ALL);
+
+        // type specific calculations
+        if ( type == Type.SNP && eval.isBiallelic() ) {
+            titvTable = GATKVariantContextUtils.isTransition(eval) ? transitionsPerSample : transversionsPerSample;
+            titvTable.inc(type, ALL);
+        }
+
+        // novelty calculation
+        if ( comp != null || (type == Type.CNV && overlapsKnownCNV(eval)))
+            knownVariantCounts.inc(type, ALL);
+
+        // per sample metrics
+        for (final Genotype g : eval.getGenotypes()) {
+            if ( ! g.isNoCall() && ! g.isHomRef() ) {
+                countsPerSample.inc(type, g.getSampleName());
+
+                // update transition / transversion ratio
+                if ( titvTable != null ) titvTable.inc(type, g.getSampleName());
+
+                if ( g.hasDP() )
+                    depthPerSample.inc(type, g.getSampleName());
+            }
+        }
+    }
+
+    private String noveltyRate(Type type) {
+        final int all = allVariantCounts.all(type);
+        final int known = knownVariantCounts.all(type);
+        return Utils.formattedNoveltyRate(known, all);
+    }
+
+    public void finalizeEvaluation() {
+        nProcessedLoci = getWalker().getnProcessedLoci();
+        nSNPs = allVariantCounts.all(Type.SNP);
+        nIndels = allVariantCounts.all(Type.INDEL);
+        nSVs = allVariantCounts.all(Type.CNV);
+
+        TiTvRatio = transitionsPerSample.ratioValue(Type.SNP, transversionsPerSample, true);
+        TiTvRatioPerSample = transitionsPerSample.ratioValue(Type.SNP, transversionsPerSample, false);
+
+        nSNPsPerSample = countsPerSample.meanValue(Type.SNP);
+        nIndelsPerSample = countsPerSample.meanValue(Type.INDEL);
+        nSVsPerSample = countsPerSample.meanValue(Type.CNV);
+
+        SNPNoveltyRate = noveltyRate(Type.SNP);
+        IndelNoveltyRate = noveltyRate(Type.INDEL);
+        SVNoveltyRate = noveltyRate(Type.CNV);
+
+        SNPDPPerSample = depthPerSample.meanValue(Type.SNP);
+        IndelDPPerSample = depthPerSample.meanValue(Type.INDEL);
+    }
+}
\ No newline at end of file
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/tools/walkers/varianteval/stratifications/AlleleCount.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/tools/walkers/varianteval/stratifications/AlleleCount.java
new file mode 100644
index 0000000..1f7ed14
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/tools/walkers/varianteval/stratifications/AlleleCount.java
@@ -0,0 +1,114 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.tools.walkers.varianteval.stratifications;
+
+import org.broadinstitute.gatk.engine.contexts.ReferenceContext;
+import org.broadinstitute.gatk.engine.refdata.RefMetaDataTracker;
+import org.broadinstitute.gatk.tools.walkers.varianteval.evaluators.VariantEvaluator;
+import org.broadinstitute.gatk.tools.walkers.varianteval.evaluators.VariantSummary;
+import htsjdk.variant.vcf.VCFConstants;
+import org.broadinstitute.gatk.utils.exceptions.UserException;
+import htsjdk.variant.variantcontext.Allele;
+import htsjdk.variant.variantcontext.VariantContext;
+
+import java.util.*;
+
+/**
+ * Stratifies the eval RODs by the allele count of the alternate allele
+ *
+ * Looks first at the MLEAC value in the INFO field, and uses that value if present.
+ * If not present, it then looks for the AC value in the INFO field.  If both are absent,
+ * it computes the AC from the genotypes themselves.  If no AC can be computed, 0 is used.
+ */
+public class AlleleCount extends VariantStratifier {
+    int nchrom;
+
+    @Override
+    public void initialize() {
+        // we can only work with a single eval VCF, and it must have genotypes
+        if ( getVariantEvalWalker().getEvals().size() != 1 && !getVariantEvalWalker().mergeEvals )
+            throw new UserException.BadArgumentValue("AlleleCount", "AlleleCount stratification only works with a single eval vcf");
+
+        // There are ploidy x n sample chromosomes
+        // TODO -- generalize to handle multiple ploidy
+        nchrom = getVariantEvalWalker().getNumberOfSamplesForEvaluation() * getVariantEvalWalker().getSamplePloidy();
+        if ( nchrom < 2 )
+            throw new UserException.BadArgumentValue("AlleleCount", "AlleleCount stratification requires an eval vcf with at least one sample");
+
+        // create an array containing each of the allele counts
+        for( int ac = 0; ac <= nchrom; ac++ ) {
+            states.add(ac);
+        }
+
+        getVariantEvalWalker().getLogger().info("AlleleCount using " + nchrom + " chromosomes");
+    }
+
+    public List<Object> getRelevantStates(ReferenceContext ref, RefMetaDataTracker tracker, VariantContext comp, String compName, VariantContext eval, String evalName, String sampleName) {
+        if (eval != null) {
+            int AC = 0; // by default, the site is considered monomorphic
+
+            try {
+                if ( eval.isBiallelic() ) {
+                    if ( eval.hasAttribute(VCFConstants.MLE_ALLELE_COUNT_KEY) ) {
+                        // the MLEAC is allowed to be larger than the AN (e.g. in the case of all PLs being 0, the GT is ./. but the exact model may arbitrarily choose an AC>1)
+                        AC = Math.min(eval.getAttributeAsInt(VCFConstants.MLE_ALLELE_COUNT_KEY, 0), nchrom);
+                    } else if ( eval.hasAttribute(VCFConstants.ALLELE_COUNT_KEY) ) {
+                        AC = eval.getAttributeAsInt(VCFConstants.ALLELE_COUNT_KEY, 0);
+                    }
+                }
+            } catch ( ClassCastException e ) {
+                // protect ourselves from bad inputs
+                // TODO -- fully decode VC
+            }
+
+            if ( AC == 0 && eval.isVariant() ) {
+                // fall back to the direct calculation
+                for (Allele allele : eval.getAlternateAlleles())
+                    AC = Math.max(AC, eval.getCalledChrCount(allele));
+            }
+
+            // make sure that the AC isn't invalid
+            if ( AC > nchrom )
+                throw new UserException.MalformedVCF(String.format("The AC value (%d) at position %s:%d " +
+                        "is larger than the number of chromosomes over all samples (%d)", AC,
+                        eval.getChr(), eval.getStart(), nchrom));
+
+            return Collections.singletonList((Object) AC);
+        } else {
+            return Collections.emptyList();
+        }
+    }
+
+    @Override
+    public Set<Class<? extends VariantEvaluator>> getIncompatibleEvaluators() {
+        return new HashSet<Class<? extends VariantEvaluator>>(Arrays.asList(VariantSummary.class));
+    }
+
+    @Override
+    public String getFormat() {
+        return "%d";
+    }
+}
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/tools/walkers/varianteval/stratifications/AlleleFrequency.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/tools/walkers/varianteval/stratifications/AlleleFrequency.java
new file mode 100644
index 0000000..349979a
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/tools/walkers/varianteval/stratifications/AlleleFrequency.java
@@ -0,0 +1,61 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.tools.walkers.varianteval.stratifications;
+
+import org.broadinstitute.gatk.engine.contexts.ReferenceContext;
+import org.broadinstitute.gatk.engine.refdata.RefMetaDataTracker;
+import org.broadinstitute.gatk.utils.MathUtils;
+import htsjdk.variant.variantcontext.VariantContext;
+
+import java.util.Collections;
+import java.util.List;
+
+/**
+ * Stratifies the eval RODs by the allele frequency of the alternate allele
+ *
+ * Uses a constant 0.005 frequency grid, and projects the AF INFO field value.  Requires
+ * that AF be present in every ROD, otherwise this stratification throws an exception
+ */
+public class AlleleFrequency extends VariantStratifier {
+    @Override
+    public void initialize() {
+        for( double a = 0.000; a <= 1.005; a += 0.005 ) {
+            states.add(String.format("%.3f", a));
+        }
+    }
+
+    public List<Object> getRelevantStates(ReferenceContext ref, RefMetaDataTracker tracker, VariantContext comp, String compName, VariantContext eval, String evalName, String sampleName) {
+        if (eval != null) {
+            try {
+                return Collections.singletonList((Object)String.format("%.3f", (5.0 * MathUtils.round(eval.getAttributeAsDouble("AF", 0.0) / 5.0, 3))));
+            } catch (Exception e) {
+                return Collections.emptyList();
+            }
+        }
+
+        return Collections.emptyList();
+    }
+}
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/tools/walkers/varianteval/stratifications/CompRod.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/tools/walkers/varianteval/stratifications/CompRod.java
new file mode 100644
index 0000000..f131ca7
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/tools/walkers/varianteval/stratifications/CompRod.java
@@ -0,0 +1,51 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.tools.walkers.varianteval.stratifications;
+
+import org.broadinstitute.gatk.utils.commandline.RodBinding;
+import org.broadinstitute.gatk.engine.contexts.ReferenceContext;
+import org.broadinstitute.gatk.engine.refdata.RefMetaDataTracker;
+import htsjdk.variant.variantcontext.VariantContext;
+
+import java.util.Collections;
+import java.util.List;
+
+
+/**
+ * Required stratification grouping output by each comp ROD
+ */
+public class CompRod extends VariantStratifier implements RequiredStratification {
+    @Override
+    public void initialize() {
+        for ( RodBinding<VariantContext> rod : getVariantEvalWalker().getComps() ) {
+            states.add(rod.getName());
+        }
+    }
+
+    public List<Object> getRelevantStates(ReferenceContext ref, RefMetaDataTracker tracker, VariantContext comp, String compName, VariantContext eval, String evalName, String sampleName) {
+        return Collections.singletonList((Object)compName);
+    }
+}
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/tools/walkers/varianteval/stratifications/Contig.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/tools/walkers/varianteval/stratifications/Contig.java
new file mode 100644
index 0000000..f90e7c5
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/tools/walkers/varianteval/stratifications/Contig.java
@@ -0,0 +1,54 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.tools.walkers.varianteval.stratifications;
+
+import org.broadinstitute.gatk.engine.contexts.ReferenceContext;
+import org.broadinstitute.gatk.engine.refdata.RefMetaDataTracker;
+import htsjdk.variant.variantcontext.VariantContext;
+
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+
+/**
+ * Stratifies the evaluation by each contig in the reference sequence
+ */
+public class Contig extends VariantStratifier {
+    @Override
+    public void initialize() {
+        states.addAll(getVariantEvalWalker().getContigNames());
+        states.add("all");
+    }
+
+    @Override
+    public List<Object> getRelevantStates(ReferenceContext ref, RefMetaDataTracker tracker, VariantContext comp, String compName, VariantContext eval, String evalName, String sampleName) {
+        if (eval != null) {
+            return Arrays.asList((Object)"all", eval.getChr());
+        } else {
+            return Collections.emptyList();
+        }
+    }
+}
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/tools/walkers/varianteval/stratifications/CpG.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/tools/walkers/varianteval/stratifications/CpG.java
new file mode 100644
index 0000000..97e5e72
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/tools/walkers/varianteval/stratifications/CpG.java
@@ -0,0 +1,76 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.tools.walkers.varianteval.stratifications;
+
+import org.broadinstitute.gatk.engine.contexts.ReferenceContext;
+import org.broadinstitute.gatk.engine.refdata.RefMetaDataTracker;
+import htsjdk.variant.variantcontext.VariantContext;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * CpG is a stratification module for VariantEval that divides the input data by within/not within a CpG site
+ *
+ * <p>
+ * It is a three-state stratification:
+ * <ul>
+ *     <li>The locus is a CpG site ("CpG")
+ *     <li>The locus is not a CpG site ("non_CpG")
+ *     <li>The locus is either a CpG or not a CpG site ("all")
+ * </ul>
+ * A CpG site is defined as a site where the reference base at a locus is a C and the adjacent reference base in the 3' direction is a G.
+ */
+public class CpG extends VariantStratifier {
+    @Override
+    public void initialize() {
+        states.add("all");
+        states.add("CpG");
+        states.add("non_CpG");
+    }
+
+    @Override
+    public List<Object> getRelevantStates(ReferenceContext ref, RefMetaDataTracker tracker, VariantContext comp, String compName, VariantContext eval, String evalName, String sampleName) {
+        boolean isCpG = false;
+        if (ref != null && ref.getBases() != null) {
+            String fwRefBases = new String(ref.getBases());
+
+            //String leftFlank = fwRefBases.substring((fwRefBases.length()/2) - 1, (fwRefBases.length()/2) + 1);
+            String rightFlank = fwRefBases.substring((fwRefBases.length()/2), (fwRefBases.length()/2) + 2);
+
+            //if (leftFlank.equalsIgnoreCase("CG") || leftFlank.equalsIgnoreCase("GC") || rightFlank.equalsIgnoreCase("CG") || rightFlank.equalsIgnoreCase("GC")) {
+            if (rightFlank.equalsIgnoreCase("CG")) {
+                isCpG = true;
+            }
+        }
+
+        ArrayList<Object> relevantStates = new ArrayList<Object>(2);
+        relevantStates.add("all");
+        relevantStates.add(isCpG ? "CpG" : "non_CpG");
+
+        return relevantStates;
+    }
+}
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/tools/walkers/varianteval/stratifications/Degeneracy.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/tools/walkers/varianteval/stratifications/Degeneracy.java
new file mode 100644
index 0000000..03cba8c
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/tools/walkers/varianteval/stratifications/Degeneracy.java
@@ -0,0 +1,158 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.tools.walkers.varianteval.stratifications;
+
+import org.broadinstitute.gatk.engine.contexts.ReferenceContext;
+import org.broadinstitute.gatk.engine.refdata.RefMetaDataTracker;
+import htsjdk.variant.variantcontext.VariantContext;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+
+/**
+ * Experimental stratification by the degeneracy of an amino acid, according to VCF annotation.  Not safe
+ */
+public class Degeneracy extends VariantStratifier {
+    private HashMap<String, HashMap<Integer, String>> degeneracies;
+
+    @Override
+    public void initialize() {
+        states.add("1-fold");
+        states.add("2-fold");
+        states.add("3-fold");
+        states.add("4-fold");
+        states.add("6-fold");
+        states.add("all");
+
+        HashMap<String, String[]> aminoAcids = new HashMap<String, String[]>();
+        aminoAcids.put("Ile",  new String[]{"ATT", "ATC", "ATA"});
+        aminoAcids.put("Leu",  new String[]{"CTT", "CTC", "CTA", "CTG", "TTA", "TTG"});
+        aminoAcids.put("Val",  new String[]{"GTT", "GTC", "GTA", "GTG"});
+        aminoAcids.put("Phe",  new String[]{"TTT", "TTC"});
+        aminoAcids.put("Met",  new String[]{"ATG"});
+        aminoAcids.put("Cys",  new String[]{"TGT", "TGC"});
+        aminoAcids.put("Ala",  new String[]{"GCT", "GCC", "GCA", "GCG"});
+        aminoAcids.put("Gly",  new String[]{"GGT", "GGC", "GGA", "GGG"});
+        aminoAcids.put("Pro",  new String[]{"CCT", "CCC", "CCA", "CCG"});
+        aminoAcids.put("Thr",  new String[]{"ACT", "ACC", "ACA", "ACG"});
+        aminoAcids.put("Ser",  new String[]{"TCT", "TCC", "TCA", "TCG", "AGT", "AGC"});
+        aminoAcids.put("Tyr",  new String[]{"TAT", "TAC"});
+        aminoAcids.put("Trp",  new String[]{"TGG"});
+        aminoAcids.put("Glu",  new String[]{"CAA", "CAG"});
+        aminoAcids.put("Asn",  new String[]{"AAT", "AAC"});
+        aminoAcids.put("His",  new String[]{"CAT", "CAC"});
+        aminoAcids.put("Gln",  new String[]{"GAA", "GAG"});
+        aminoAcids.put("Asp",  new String[]{"GAT", "GAC"});
+        aminoAcids.put("Lys",  new String[]{"AAA", "AAG"});
+        aminoAcids.put("Arg",  new String[]{"CGT", "CGC", "CGA", "CGG", "AGA", "AGG"});
+        aminoAcids.put("Stop", new String[]{"TAA", "TAG", "TGA"});
+
+        degeneracies = new HashMap<String, HashMap<Integer, String>>();
+
+        for (String aminoAcid : aminoAcids.keySet()) {
+            String[] codons = aminoAcids.get(aminoAcid);
+
+            for (int pos = 0; pos < 3; pos++) {
+                HashSet<Character> alleles = new HashSet<Character>();
+
+                for (String codon : codons) {
+                    alleles.add(codon.charAt(pos));
+                }
+
+                String degeneracy;
+                switch (alleles.size()) {
+                    case 1:  degeneracy = "1-fold"; break;
+                    case 2:  degeneracy = "2-fold"; break;
+                    case 3:  degeneracy = "3-fold"; break;
+                    case 4:  degeneracy = "4-fold"; break;
+                    case 6:  degeneracy = "6-fold"; break;
+                    default: degeneracy = "1-fold"; break;
+                }
+
+                if (!degeneracies.containsKey(aminoAcid)) {
+                    degeneracies.put(aminoAcid, new HashMap<Integer, String>());
+                }
+
+                degeneracies.get(aminoAcid).put(pos, degeneracy);
+            }
+        }
+    }
+
+    public List<Object> getRelevantStates(ReferenceContext ref, RefMetaDataTracker tracker, VariantContext comp, String compName, VariantContext eval, String evalName, String sampleName) {
+        ArrayList<Object> relevantStates = new ArrayList<Object>();
+
+        relevantStates.add("all");
+
+        if (eval != null && eval.isVariant()) {
+            String type = null;
+            String aa = null;
+            Integer frame = null;
+
+            if (eval.hasAttribute("refseq.functionalClass")) {
+                aa = eval.getAttributeAsString("refseq.variantAA", null);
+                frame = eval.getAttributeAsInt("refseq.frame", 0);
+            } else if (eval.hasAttribute("refseq.functionalClass_1")) {
+                int annotationId = 1;
+                String key;
+
+                do {
+                    key = String.format("refseq.functionalClass_%d", annotationId);
+
+                    String newtype = eval.getAttributeAsString(key, null);
+
+                    if ( newtype != null &&
+                            ( type == null ||
+                                    ( type.equals("silent") && !newtype.equals("silent") ) ||
+                                    ( type.equals("missense") && newtype.equals("nonsense") ) )
+                            ) {
+                        type = newtype;
+
+                        String aakey = String.format("refseq.variantAA_%d", annotationId);
+                        aa = eval.getAttributeAsString(aakey, null);
+
+                        if (aa != null) {
+                            String framekey = String.format("refseq.frame_%d", annotationId);
+
+                            if (eval.hasAttribute(framekey)) {
+                                frame = eval.getAttributeAsInt(framekey, 0);
+                            }
+                        }
+                    }
+
+                    annotationId++;
+                } while (eval.hasAttribute(key));
+            }
+
+            if (aa != null && degeneracies.containsKey(aa) && frame != null) {
+                relevantStates.add(degeneracies.get(aa).get(frame));
+            }
+        }
+
+        return relevantStates;
+    }
+}
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/tools/walkers/varianteval/stratifications/DynamicStratification.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/tools/walkers/varianteval/stratifications/DynamicStratification.java
new file mode 100644
index 0000000..1c42898
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/tools/walkers/varianteval/stratifications/DynamicStratification.java
@@ -0,0 +1,66 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.tools.walkers.varianteval.stratifications;
+
+import htsjdk.variant.variantcontext.VariantContext;
+
+/**
+ * Tag this stratification as dynamically determining the final strat based on the input data
+ *
+ * The paradigm here is simple.  We upfront create a strat with N states that reflect the finest grained
+ * possible division of the data.  The data is processed, and statistics collected for each of the N states.
+ * An update call is made to the stratification for evaluation VariantContext during each map call,
+ * allowing the strat to collect data about the usage of each state.  A final call requests that
+ * the stratification map down the N states into M states (typically less than N, not necessarily
+ * a subset of N).  This is provided by returning a map from each of M state -> N states and
+ * the VariantEval walker will combine all of the evaluations for N into a single value for
+ * each M.
+ *
+ * For example, suppose I have a dynamic strat called AC, adopting 7 possible values 0,1,2,3,4,5,6.  This
+ * strats tracks the number of eval vcs for each state, with final counts 0=1, 1=100, 2=10, 3=5, 4=3, 5=2, 6=1.
+ * The stratification attempts to combine the strats down to so that each state has approximately the same
+ * fraction of the data in each bin.  Overall there is 1+100+10+5+3+2+1=124 observations and 7 bins so we really
+ * want ~ 18 observations in each bin.  So we merge 3-6 with 5+3+2+1 = 11 and keep 2, 1, and 0 as distinct bins.  We
+ * return a map from 0 -> 0, 1 -> 1, 2 -> 2, 3-6 -> {3,4,5,6}.
+ *
+ * TODO - some open implementation questions
+ * -- We should only create one stratifier overall.  How do we track this?  When we create the stratifiers
+ *    perhaps we can look at them and create a tracker?
+ * -- How do we create a new stratifier based on the finalStratifications() given the framework?  Conceptually
+ *    this new thing is itself a stratifier, just like before, but it's states are determined at the end.  We'd
+ *    then like to call not getRelevantStates but a different function that accepts an old state and returns
+ *    the new state.  Perhaps the process should look like:
+ *          finalizeStratification -> new Stratifier whose states are the final ones
+ *          getNewState(old state) -> new state (one of those in getFinalStratification)
+ *
+ * @author Mark DePristo
+ * @since 4/9/12
+ */
+public interface DynamicStratification {
+    public void update(final VariantContext eval);
+    public VariantStratifier finalizeStratification();
+    public Object getFinalState(final Object oldState);
+}
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/tools/walkers/varianteval/stratifications/EvalRod.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/tools/walkers/varianteval/stratifications/EvalRod.java
new file mode 100644
index 0000000..8fdd007
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/tools/walkers/varianteval/stratifications/EvalRod.java
@@ -0,0 +1,52 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.tools.walkers.varianteval.stratifications;
+
+import org.broadinstitute.gatk.utils.commandline.RodBinding;
+import org.broadinstitute.gatk.engine.contexts.ReferenceContext;
+import org.broadinstitute.gatk.engine.refdata.RefMetaDataTracker;
+import htsjdk.variant.variantcontext.VariantContext;
+
+import java.util.Arrays;
+import java.util.List;
+
+/**
+ * Required stratification grouping output by each eval ROD
+ */
+public class EvalRod extends VariantStratifier implements RequiredStratification {
+    @Override
+    public void initialize() {
+        for ( RodBinding<VariantContext> rod : getVariantEvalWalker().getEvals() ) {
+            states.add(rod.getName());
+            if ( getVariantEvalWalker().mergeEvals )
+                break;
+        }
+    }
+
+    public List<Object> getRelevantStates(ReferenceContext ref, RefMetaDataTracker tracker, VariantContext comp, String compName, VariantContext eval, String evalName, String sampleName) {
+        return Arrays.asList((Object)evalName);
+    }
+}
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/tools/walkers/varianteval/stratifications/Filter.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/tools/walkers/varianteval/stratifications/Filter.java
new file mode 100644
index 0000000..c37f003
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/tools/walkers/varianteval/stratifications/Filter.java
@@ -0,0 +1,56 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.tools.walkers.varianteval.stratifications;
+
+import org.broadinstitute.gatk.engine.contexts.ReferenceContext;
+import org.broadinstitute.gatk.engine.refdata.RefMetaDataTracker;
+import htsjdk.variant.variantcontext.VariantContext;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Stratifies by the FILTER status (PASS, FAIL) of the eval records
+ */
+public class Filter extends VariantStratifier {
+    @Override
+    public void initialize() {
+        states.add("called");
+        states.add("filtered");
+        states.add("raw");
+    }
+
+    public List<Object> getRelevantStates(ReferenceContext ref, RefMetaDataTracker tracker, VariantContext comp, String compName, VariantContext eval, String evalName, String sampleName) {
+        ArrayList<Object> relevantStates = new ArrayList<Object>();
+
+        relevantStates.add("raw");
+        if (eval != null) {
+            relevantStates.add(eval.isFiltered() ? "filtered" : "called");
+        }
+
+        return relevantStates;
+    }
+}
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/tools/walkers/varianteval/stratifications/FunctionalClass.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/tools/walkers/varianteval/stratifications/FunctionalClass.java
new file mode 100644
index 0000000..08ff9d4
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/tools/walkers/varianteval/stratifications/FunctionalClass.java
@@ -0,0 +1,110 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.tools.walkers.varianteval.stratifications;
+
+import org.broadinstitute.gatk.engine.contexts.ReferenceContext;
+import org.broadinstitute.gatk.engine.refdata.RefMetaDataTracker;
+import org.broadinstitute.gatk.tools.walkers.annotator.SnpEff;
+import htsjdk.variant.variantcontext.VariantContext;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Stratifies by nonsense, missense, silent, and all annotations in the input ROD, from the INFO field annotation.
+ */
+public class FunctionalClass extends VariantStratifier {
+
+    public enum FunctionalType {
+        silent,
+        missense,
+        nonsense
+    }
+
+
+    @Override
+    public void initialize() {
+        states.add("all");
+        for ( FunctionalType type : FunctionalType.values() )
+            states.add(type.name());
+    }
+
+
+    public List<Object> getRelevantStates(ReferenceContext ref, RefMetaDataTracker tracker, VariantContext comp, String compName, VariantContext eval, String evalName, String sampleName) {
+        ArrayList<Object> relevantStates = new ArrayList<Object>();
+
+        relevantStates.add("all");
+
+        if (eval != null && eval.isVariant()) {
+            FunctionalType type = null;
+
+            if (eval.hasAttribute("refseq.functionalClass")) {
+                try {
+                    type = FunctionalType.valueOf(eval.getAttributeAsString("refseq.functionalClass", null));
+                } catch ( Exception e ) {} // don't error out if the type isn't supported
+            } else if (eval.hasAttribute("refseq.functionalClass_1")) {
+                int annotationId = 1;
+                String key;
+
+                do {
+                    key = String.format("refseq.functionalClass_%d", annotationId);
+
+                    String newtypeStr = eval.getAttributeAsString(key, null);
+                    if ( newtypeStr != null && !newtypeStr.equalsIgnoreCase("null") ) {
+                        try {
+                            FunctionalType newType = FunctionalType.valueOf(newtypeStr);
+                            if ( type == null ||
+                                    ( type == FunctionalType.silent && newType != FunctionalType.silent ) ||
+                                    ( type == FunctionalType.missense && newType == FunctionalType.nonsense ) ) {
+                                type = newType;
+                            }
+                        } catch ( Exception e ) {} // don't error out if the type isn't supported
+                    }
+
+                    annotationId++;
+                } while (eval.hasAttribute(key));
+
+            } else if ( eval.hasAttribute(SnpEff.InfoFieldKey.FUNCTIONAL_CLASS_KEY.getKeyName()) ) {
+                try {
+                    SnpEff.EffectFunctionalClass snpEffFunctionalClass = SnpEff.EffectFunctionalClass.valueOf(eval.getAttribute(SnpEff.InfoFieldKey.FUNCTIONAL_CLASS_KEY.getKeyName()).toString());
+                    if ( snpEffFunctionalClass == SnpEff.EffectFunctionalClass.NONSENSE )
+                        type = FunctionalType.nonsense;
+                    else if ( snpEffFunctionalClass == SnpEff.EffectFunctionalClass.MISSENSE )
+                        type = FunctionalType.missense;
+                    else if ( snpEffFunctionalClass == SnpEff.EffectFunctionalClass.SILENT )
+                        type = FunctionalType.silent;
+                }
+                catch ( Exception e ) {} // don't error out if the type isn't supported
+            }
+
+            if ( type != null ) {
+                relevantStates.add(type.name());
+            }
+        }
+
+        return relevantStates;
+    }
+}
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/tools/walkers/varianteval/stratifications/IndelSize.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/tools/walkers/varianteval/stratifications/IndelSize.java
new file mode 100644
index 0000000..e5cb240
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/tools/walkers/varianteval/stratifications/IndelSize.java
@@ -0,0 +1,78 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.tools.walkers.varianteval.stratifications;
+
+import org.broadinstitute.gatk.engine.contexts.ReferenceContext;
+import org.broadinstitute.gatk.engine.refdata.RefMetaDataTracker;
+import htsjdk.variant.variantcontext.VariantContext;
+
+import java.util.Collections;
+import java.util.List;
+
+/**
+ * Stratifies the eval RODs by the indel size
+ *
+ * Indel sizes are stratified from sizes -100 to +100. Sizes greater than this are lumped in the +/- 100 bin
+ * This stratification ignores multi-allelic indels (whose size is not defined uniquely)
+ */
+public class IndelSize extends VariantStratifier {
+    static final int MAX_INDEL_SIZE = 100;
+
+    @Override
+    public void initialize() {
+        for( int a=-MAX_INDEL_SIZE; a <=MAX_INDEL_SIZE; a++ ) {
+            states.add(a);
+        }
+    }
+
+    public List<Object> getRelevantStates(ReferenceContext ref, RefMetaDataTracker tracker, VariantContext comp, String compName, VariantContext eval, String evalName, String sampleName) {
+        if (eval != null && eval.isIndel() && eval.isBiallelic()) {
+            try {
+                int eventLength = 0;
+                if ( eval.isSimpleInsertion() ) {
+                    eventLength = eval.getAlternateAllele(0).length();
+                } else if ( eval.isSimpleDeletion() ) {
+                    eventLength = -eval.getReference().length();
+                }
+
+                if (eventLength > MAX_INDEL_SIZE)
+                    eventLength = MAX_INDEL_SIZE;
+                else if (eventLength < -MAX_INDEL_SIZE)
+                    eventLength = -MAX_INDEL_SIZE;
+
+                return Collections.singletonList((Object)eventLength);
+            } catch (Exception e) {
+                return Collections.emptyList();
+            }
+        }
+
+        return Collections.emptyList();
+    }
+    @Override
+    public String getFormat() {
+        return "%d";
+    }
+}
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/tools/walkers/varianteval/stratifications/IntervalStratification.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/tools/walkers/varianteval/stratifications/IntervalStratification.java
new file mode 100644
index 0000000..8ee4e79
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/tools/walkers/varianteval/stratifications/IntervalStratification.java
@@ -0,0 +1,92 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.tools.walkers.varianteval.stratifications;
+
+import htsjdk.samtools.util.IntervalTree;
+import org.apache.log4j.Logger;
+import org.broadinstitute.gatk.engine.contexts.ReferenceContext;
+import org.broadinstitute.gatk.engine.refdata.RefMetaDataTracker;
+import org.broadinstitute.gatk.utils.GenomeLoc;
+import org.broadinstitute.gatk.utils.exceptions.UserException;
+import org.broadinstitute.gatk.utils.interval.IntervalUtils;
+import htsjdk.variant.variantcontext.VariantContext;
+
+import java.util.*;
+
+/**
+ * Stratifies the variants by whether they overlap an interval in the set provided on the command line.
+ *
+ * The primary use of this stratification is to provide a mechanism to divide asssessment of a call set up
+ * by whether a variant overlaps an interval or not.  I use this to differentiate between variants occurring
+ * in CCDS exons vs. those in non-coding regions, in the 1000G call set, using a command line that looks like:
+ *
+ * -T VariantEval -R human_g1k_v37.fasta -eval 1000G.vcf -stratIntervals:BED ccds.bed -ST IntervalStratification
+ *
+ * Note that the overlap algorithm properly handles symbolic alleles with an INFO field END value.  In order to
+ * safely use this module you should provide entire contigs worth of variants, and let the interval strat decide
+ * overlap, as opposed to using -L which will not properly work with symbolic variants.
+ */
+public class IntervalStratification extends VariantStratifier {
+    final protected static Logger logger = Logger.getLogger(IntervalStratification.class);
+    Map<String, IntervalTree<GenomeLoc>> intervalTreeByContig = null;
+
+    final List<Object> OVERLAPPING = Arrays.asList((Object)"all", (Object)"overlaps.intervals");
+    final List<Object> NOT_OVERLAPPING = Arrays.asList((Object)"all", (Object)"outside.intervals");
+
+    
+    @Override
+    public void initialize() {
+        if ( getVariantEvalWalker().intervalsFile == null )
+            throw new UserException.MissingArgument("stratIntervals", "Must be provided when IntervalStratification is enabled");
+
+        final List<GenomeLoc> locs = getVariantEvalWalker().intervalsFile.getIntervals(getVariantEvalWalker().getToolkit());
+
+        if ( locs.isEmpty() )
+            throw new UserException.BadArgumentValue("stratIntervals", "Contains no intervals.  Perhaps the file is malformed or empty?");
+
+        intervalTreeByContig = getVariantEvalWalker().createIntervalTreeByContig(getVariantEvalWalker().intervalsFile);
+
+        logger.info(String.format("Creating IntervalStratification %s containing %d intervals covering %d bp",
+                getVariantEvalWalker().intervalsFile.getSource(), locs.size(), IntervalUtils.intervalSize(locs)));
+
+        states.addAll(Arrays.asList("all", "overlaps.intervals", "outside.intervals"));
+    }
+
+    public List<Object> getRelevantStates(ReferenceContext ref, RefMetaDataTracker tracker, VariantContext comp, String compName, VariantContext eval, String evalName, String sampleName) {
+        if (eval != null) {
+            final GenomeLoc loc = getVariantEvalWalker().getToolkit().getGenomeLocParser().createGenomeLoc(eval);
+            IntervalTree<GenomeLoc> intervalTree = intervalTreeByContig.get(loc.getContig());
+            IntervalTree.Node<GenomeLoc> node = intervalTree.minOverlapper(loc.getStart(), loc.getStop());
+            //logger.info(String.format("Overlap %s found %s", loc, node));
+            if ( node != null )
+                return OVERLAPPING;
+            else
+                return NOT_OVERLAPPING;
+        }
+
+        return Collections.emptyList();
+    }
+}
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/tools/walkers/varianteval/stratifications/JexlExpression.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/tools/walkers/varianteval/stratifications/JexlExpression.java
new file mode 100644
index 0000000..00fec2a
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/tools/walkers/varianteval/stratifications/JexlExpression.java
@@ -0,0 +1,69 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.tools.walkers.varianteval.stratifications;
+
+import org.broadinstitute.gatk.engine.contexts.ReferenceContext;
+import org.broadinstitute.gatk.engine.refdata.RefMetaDataTracker;
+import org.broadinstitute.gatk.tools.walkers.varianteval.util.SortableJexlVCMatchExp;
+import htsjdk.variant.variantcontext.VariantContext;
+import htsjdk.variant.variantcontext.VariantContextUtils;
+
+import java.util.List;
+import java.util.ArrayList;
+import java.util.Set;
+
+/**
+ * Stratifies the eval RODs by user-supplied JEXL expressions
+ *
+ * See http://gatkforums.broadinstitute.org/discussion/1255/what-are-jexl-expressions-and-how-can-i-use-them-with-the-gatk for more details
+ */
+public class JexlExpression extends VariantStratifier implements StandardStratification {
+    // needs to know the jexl expressions
+    private Set<SortableJexlVCMatchExp> jexlExpressions;
+
+    @Override
+    public void initialize() {
+        jexlExpressions = getVariantEvalWalker().getJexlExpressions();
+
+        states.add("none");
+        for ( SortableJexlVCMatchExp jexlExpression : jexlExpressions ) {
+            states.add(jexlExpression.name);
+        }
+    }
+
+    public List<Object> getRelevantStates(ReferenceContext ref, RefMetaDataTracker tracker, VariantContext comp, String compName, VariantContext eval, String evalName, String sampleName) {
+        ArrayList<Object> relevantStates = new ArrayList<Object>();
+        relevantStates.add("none");
+
+        for ( SortableJexlVCMatchExp jexlExpression : jexlExpressions ) {
+            if (eval != null && VariantContextUtils.match(eval, jexlExpression)) {
+                relevantStates.add(jexlExpression.name);
+            }
+        }
+
+        return relevantStates;
+    }
+}
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/tools/walkers/varianteval/stratifications/Novelty.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/tools/walkers/varianteval/stratifications/Novelty.java
new file mode 100644
index 0000000..0114bf2
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/tools/walkers/varianteval/stratifications/Novelty.java
@@ -0,0 +1,64 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.tools.walkers.varianteval.stratifications;
+
+import org.broadinstitute.gatk.utils.commandline.RodBinding;
+import org.broadinstitute.gatk.engine.contexts.ReferenceContext;
+import org.broadinstitute.gatk.engine.refdata.RefMetaDataTracker;
+import htsjdk.variant.variantcontext.VariantContext;
+
+import java.util.*;
+
+/**
+ * Stratifies by whether a site in in the list of known RODs (e.g., dbsnp by default)
+ */
+public class Novelty extends VariantStratifier implements StandardStratification {
+    // needs the variant contexts and known names
+    private List<RodBinding<VariantContext>> knowns;
+
+    private final static List<Object> KNOWN_STATES = Arrays.asList((Object)"all", (Object)"known");
+    private final static List<Object> NOVEL_STATES = Arrays.asList((Object)"all", (Object)"novel");
+
+    @Override
+    public void initialize() {
+        states.addAll(Arrays.asList("all", "known", "novel"));
+        knowns = getVariantEvalWalker().getKnowns();
+    }
+
+    public List<Object> getRelevantStates(ReferenceContext ref, RefMetaDataTracker tracker, VariantContext comp, String compName, VariantContext eval, String evalName, String sampleName) {
+        if (tracker != null && eval != null) {
+            final Collection<VariantContext> knownComps = tracker.getValues(knowns, ref.getLocus());
+            for ( final VariantContext c : knownComps ) {
+                // loop over sites, looking for something that matches the type eval
+                if ( eval.getType() == c.getType() || eval.getType() == VariantContext.Type.NO_VARIATION ) {
+                    return KNOWN_STATES;
+                }
+            }
+        } 
+        
+        return NOVEL_STATES;
+    }
+}
\ No newline at end of file
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/tools/walkers/varianteval/stratifications/OneBPIndel.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/tools/walkers/varianteval/stratifications/OneBPIndel.java
new file mode 100644
index 0000000..7ad45e0
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/tools/walkers/varianteval/stratifications/OneBPIndel.java
@@ -0,0 +1,59 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.tools.walkers.varianteval.stratifications;
+
+import org.broadinstitute.gatk.engine.contexts.ReferenceContext;
+import org.broadinstitute.gatk.engine.refdata.RefMetaDataTracker;
+import htsjdk.variant.variantcontext.VariantContext;
+
+import java.util.Arrays;
+import java.util.List;
+
+/**
+ * Stratifies the eval RODs into sites where the indel is 1 bp in length and those where the event is 2+.
+ * all non indel events go into all bins, so that SNP counts can be used as contrasts in eval modules.
+ */
+public class OneBPIndel extends VariantStratifier {
+    private final static List<Object> ALL = Arrays.asList((Object)"all", (Object)"one.bp", (Object)"two.plus.bp");
+    private final static List<Object> ONE_BP = Arrays.asList((Object)"all", (Object)"one.bp");
+    private final static List<Object> TWO_PLUS_BP = Arrays.asList((Object)"all", (Object)"two.plus.bp");
+
+    @Override
+    public void initialize() {
+        states.addAll(ALL);
+    }
+
+    @Override
+    public List<Object> getRelevantStates(ReferenceContext ref, RefMetaDataTracker tracker, VariantContext comp, String compName, VariantContext eval, String evalName, String sampleName) {
+        if (eval != null && eval.isIndel()) {
+            for ( int l : eval.getIndelLengths() )
+                if ( Math.abs(l) > 1 )
+                    return TWO_PLUS_BP; // someone is too long
+            return ONE_BP; // all lengths are one
+        } else
+            return ALL;
+    }
+}
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/tools/walkers/varianteval/stratifications/RequiredStratification.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/tools/walkers/varianteval/stratifications/RequiredStratification.java
new file mode 100644
index 0000000..946c723
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/tools/walkers/varianteval/stratifications/RequiredStratification.java
@@ -0,0 +1,28 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.tools.walkers.varianteval.stratifications;
+
+public interface RequiredStratification {}
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/tools/walkers/varianteval/stratifications/Sample.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/tools/walkers/varianteval/stratifications/Sample.java
new file mode 100644
index 0000000..bd0b6f1
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/tools/walkers/varianteval/stratifications/Sample.java
@@ -0,0 +1,57 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.tools.walkers.varianteval.stratifications;
+
+import org.broadinstitute.gatk.engine.contexts.ReferenceContext;
+import org.broadinstitute.gatk.engine.refdata.RefMetaDataTracker;
+import org.broadinstitute.gatk.tools.walkers.varianteval.evaluators.VariantEvaluator;
+import org.broadinstitute.gatk.tools.walkers.varianteval.evaluators.VariantSummary;
+import htsjdk.variant.variantcontext.VariantContext;
+
+import java.util.*;
+
+/**
+ * Stratifies the eval RODs by each sample in the eval ROD.
+ *
+ * This allows the system to analyze each sample separately.  Since many evaluations
+ * only consider non-reference sites, stratifying by sample results in meaningful
+ * calculations for CompOverlap
+ */
+public class Sample extends VariantStratifier {
+    @Override
+    public void initialize() {
+        states.addAll(getVariantEvalWalker().getSampleNamesForStratification());
+    }
+
+    public List<Object> getRelevantStates(ReferenceContext ref, RefMetaDataTracker tracker, VariantContext comp, String compName, VariantContext eval, String evalName, String sampleName) {
+        return Collections.singletonList((Object) sampleName);
+    }
+
+    @Override
+    public Set<Class<? extends VariantEvaluator>> getIncompatibleEvaluators() {
+        return new HashSet<Class<? extends VariantEvaluator>>(Arrays.asList(VariantSummary.class));
+    }
+}
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/tools/walkers/varianteval/stratifications/SnpEffPositionModifier.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/tools/walkers/varianteval/stratifications/SnpEffPositionModifier.java
new file mode 100644
index 0000000..c2ddd80
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/tools/walkers/varianteval/stratifications/SnpEffPositionModifier.java
@@ -0,0 +1,86 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.tools.walkers.varianteval.stratifications;
+
+import org.broadinstitute.gatk.engine.contexts.ReferenceContext;
+import org.broadinstitute.gatk.engine.refdata.RefMetaDataTracker;
+import org.broadinstitute.gatk.tools.walkers.annotator.SnpEff;
+import org.broadinstitute.gatk.tools.walkers.annotator.SnpEff.EffectType;
+import org.broadinstitute.gatk.tools.walkers.annotator.SnpEff.InfoFieldKey;
+import org.broadinstitute.gatk.tools.walkers.annotator.SnpEffUtil;
+import htsjdk.variant.variantcontext.VariantContext;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Stratifies variants as genes or coding regions, according to the effect modifier, as indicated by snpEff.
+ * The 'gene' category includes category 'coding region', and additionally includes introns. 'Coding regions'
+ * includes transcripts and, implicitly, UTRs.
+ */
+public class SnpEffPositionModifier extends VariantStratifier {
+
+	public enum PositionModifier {
+		GENE,          // EXON
+		CODING_REGION, // CDS
+		SPLICE_SITE,   // not a straight translation -- see getRelevantStates
+		STOP_GAINED,   // STOP_GAINED
+		STOP_LOST      // STOP_LOST
+	}
+
+	@Override
+	public void initialize() {
+		for (final PositionModifier type : PositionModifier.values()) states.add(type.name());
+	}
+
+	@Override
+	public List<Object> getRelevantStates(
+			final ReferenceContext ref,
+			final RefMetaDataTracker tracker,
+			final VariantContext comp,
+			final String compName,
+			final VariantContext eval,
+			final String evalName,
+			final String sampleName)
+	{
+		final List<Object> relevantStates = new ArrayList<Object>();
+		if (eval != null && eval.isVariant() && eval.hasAttribute(InfoFieldKey.EFFECT_KEY.getKeyName())) {
+			final SnpEff.EffectType effectType = SnpEff.EffectType.valueOf(
+					eval.getAttribute(InfoFieldKey.EFFECT_KEY.getKeyName()).toString());
+
+			if (SnpEffUtil.isSubTypeOf(effectType, EffectType.EXON))        relevantStates.add(PositionModifier.GENE.name());
+			if (SnpEffUtil.isSubTypeOf(effectType, EffectType.CDS))         relevantStates.add(PositionModifier.CODING_REGION.name());
+			if (SnpEffUtil.isSubTypeOf(effectType, EffectType.STOP_GAINED)) relevantStates.add(PositionModifier.STOP_GAINED.name());
+			if (SnpEffUtil.isSubTypeOf(effectType, EffectType.STOP_LOST))   relevantStates.add(PositionModifier.STOP_LOST.name());
+
+			if (SnpEffUtil.isSubTypeOf(effectType, EffectType.SPLICE_SITE_ACCEPTOR) ||
+				SnpEffUtil.isSubTypeOf(effectType, EffectType.SPLICE_SITE_DONOR))
+					relevantStates.add(PositionModifier.SPLICE_SITE.name());
+		}
+
+		return relevantStates;
+	}
+}
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/tools/walkers/varianteval/stratifications/StandardStratification.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/tools/walkers/varianteval/stratifications/StandardStratification.java
new file mode 100644
index 0000000..41c52c2
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/tools/walkers/varianteval/stratifications/StandardStratification.java
@@ -0,0 +1,29 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.tools.walkers.varianteval.stratifications;
+
+public interface StandardStratification {
+}
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/tools/walkers/varianteval/stratifications/TandemRepeat.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/tools/walkers/varianteval/stratifications/TandemRepeat.java
new file mode 100644
index 0000000..6eba4b4
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/tools/walkers/varianteval/stratifications/TandemRepeat.java
@@ -0,0 +1,67 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.tools.walkers.varianteval.stratifications;
+
+import org.broadinstitute.gatk.engine.contexts.ReferenceContext;
+import org.broadinstitute.gatk.engine.refdata.RefMetaDataTracker;
+import org.broadinstitute.gatk.utils.variant.GATKVariantContextUtils;
+import htsjdk.variant.variantcontext.VariantContext;
+
+import java.util.Arrays;
+import java.util.List;
+
+/**
+ * Stratifies the eval RODs into sites that are tandem repeats
+ */
+public class TandemRepeat extends VariantStratifier {
+    private final static List<Object> JUST_ALL = Arrays.asList((Object)"all");
+    private final static List<Object> ALL = Arrays.asList((Object)"all", (Object)"is.repeat", (Object)"not.repeat");
+    private final static List<Object> REPEAT = Arrays.asList((Object)"all", (Object)"is.repeat");
+    private final static List<Object> NOT_REPEAT = Arrays.asList((Object)"all", (Object)"not.repeat");
+
+    @Override
+    public void initialize() {
+        states.addAll(ALL);
+    }
+
+    @Override
+    public List<Object> getRelevantStates(ReferenceContext ref, RefMetaDataTracker tracker, VariantContext comp, String compName, VariantContext eval, String evalName, String sampleName) {
+        if ( eval == null || ! eval.isIndel() )
+            return ALL;
+        else if ( GATKVariantContextUtils.isTandemRepeat(eval, ref.getForwardBases()) ) {
+            print("REPEAT", eval, ref);
+            return REPEAT;
+        } else {
+            print("NOT A REPEAT", eval, ref);
+            return NOT_REPEAT;
+        }
+    }
+    
+    private final void print(String prefix, VariantContext eval, ReferenceContext ref) {
+//        String alleles = ParsingUtils.sortList(eval.getAlleles()).toString();
+//        this.getVariantEvalWalker().getLogger().info(prefix + ": " + "pos=" + eval.getStart() + " alleles=" + alleles + " ref=" + new String(ref.getForwardBases()));
+    }
+}
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/tools/walkers/varianteval/stratifications/VariantStratifier.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/tools/walkers/varianteval/stratifications/VariantStratifier.java
new file mode 100644
index 0000000..0832ebd
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/tools/walkers/varianteval/stratifications/VariantStratifier.java
@@ -0,0 +1,110 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.tools.walkers.varianteval.stratifications;
+
+import org.broadinstitute.gatk.engine.contexts.ReferenceContext;
+import org.broadinstitute.gatk.engine.refdata.RefMetaDataTracker;
+import org.broadinstitute.gatk.tools.walkers.varianteval.VariantEval;
+import org.broadinstitute.gatk.tools.walkers.varianteval.evaluators.VariantEvaluator;
+import org.broadinstitute.gatk.tools.walkers.varianteval.stratifications.manager.Stratifier;
+import htsjdk.variant.variantcontext.VariantContext;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.Set;
+
+public abstract class VariantStratifier implements Comparable<VariantStratifier>, Stratifier {
+    private VariantEval variantEvalWalker;
+    final private String name;
+    final protected ArrayList<Object> states = new ArrayList<Object>();
+
+    protected VariantStratifier() {
+        name = this.getClass().getSimpleName();
+    }
+
+    // -------------------------------------------------------------------------------------
+    //
+    // to be overloaded
+    //
+    // -------------------------------------------------------------------------------------
+
+    public abstract void initialize();
+
+    public abstract List<Object> getRelevantStates(ReferenceContext ref, RefMetaDataTracker tracker, VariantContext comp, String compName, VariantContext eval, String evalName, String sampleName);
+
+    // -------------------------------------------------------------------------------------
+    //
+    // final capabilities
+    //
+    // -------------------------------------------------------------------------------------
+
+    /**
+     * @return a reference to the parent VariantEvalWalker running this stratification
+     */
+    public final VariantEval getVariantEvalWalker() {
+        return variantEvalWalker;
+    }
+
+    /**
+     * Should only be called by VariantEvalWalker itself
+     * @param variantEvalWalker
+     */
+    public final void setVariantEvalWalker(VariantEval variantEvalWalker) {
+        this.variantEvalWalker = variantEvalWalker;
+    }
+
+    public final int compareTo(VariantStratifier o1) {
+        return this.getName().compareTo(o1.getName());
+    }
+
+    @Override
+    public String toString() {
+        return getName();
+    }
+
+    public final String getName() {
+        return name;
+    }
+    
+    public String getFormat() { return "%s"; }
+    
+    public final ArrayList<Object> getAllStates() {
+        return states;
+    }
+
+
+    /**
+     * The way for a stratifier to specify that it's incompatible with specific evaluations.  For
+     * example, VariantSummary includes a per-sample metric, and so cannot be used safely with Sample
+     * or AlleleCount stratifications as this introduces an O(n^2) memory and cpu cost.
+     *
+     * @return the set of VariantEvaluators that cannot be active with this Stratification
+     */
+    public Set<Class<? extends VariantEvaluator>> getIncompatibleEvaluators() {
+        return Collections.emptySet();
+    }
+}
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/tools/walkers/varianteval/stratifications/VariantType.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/tools/walkers/varianteval/stratifications/VariantType.java
new file mode 100644
index 0000000..0ba5b60
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/tools/walkers/varianteval/stratifications/VariantType.java
@@ -0,0 +1,49 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.tools.walkers.varianteval.stratifications;
+
+import org.broadinstitute.gatk.engine.contexts.ReferenceContext;
+import org.broadinstitute.gatk.engine.refdata.RefMetaDataTracker;
+import htsjdk.variant.variantcontext.VariantContext;
+
+import java.util.Collections;
+import java.util.List;
+
+/**
+ * Stratifies the eval variants by their type (SNP, INDEL, ETC)
+ */
+public class VariantType extends VariantStratifier {
+    @Override
+    public void initialize() {
+        for (VariantContext.Type t : VariantContext.Type.values())
+            states.add(t.toString());
+    }
+
+    public List<Object> getRelevantStates(ReferenceContext ref, RefMetaDataTracker tracker, VariantContext comp, String compName, VariantContext eval, String evalName, String sampleName) {
+        return eval == null ? Collections.emptyList() : Collections.singletonList((Object)eval.getType().toString());
+    }
+
+}
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/tools/walkers/varianteval/stratifications/manager/StratNode.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/tools/walkers/varianteval/stratifications/manager/StratNode.java
new file mode 100644
index 0000000..0db9370
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/tools/walkers/varianteval/stratifications/manager/StratNode.java
@@ -0,0 +1,166 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.tools.walkers.varianteval.stratifications.manager;
+
+import com.google.java.contract.Ensures;
+import com.google.java.contract.Invariant;
+import com.google.java.contract.Requires;
+import org.broadinstitute.gatk.utils.exceptions.ReviewedGATKException;
+
+import java.util.*;
+
+/**
+ * Helper class representing a tree of stratification splits, where leaf nodes
+ * are given a unique integer key starting at 0 and incrementing up to the
+ * number of leaves in the tree.  This allows you to use this tree to produce
+ * a key to map into an array index mapped data structure.
+ *
+ * Suppose I have to strats, each with two values: A = 1, 2 and B = 3, 4
+ *
+ * This data structure creates a tree such as:
+ *
+ * root -> A -> 1 -> B -> 3  : 0
+ *                |- B -> 4  : 1
+ *      |- A -> 2 -> B -> 3  : 2
+ *                |- B -> 4  : 3
+ *
+ * This code allows us to efficiently look up a state key (A=2, B=3) and map it
+ * to a specific key (an integer) that's unique over the tree
+ *
+ * Note the structure of this tree is that the keys are -1 for all internal nodes, and
+ * leafs are the only nodes with meaningful keys.  So for a tree with 2N nodes N of these
+ * will be internal, with no keys, and meaningful maps from states -> subtrees.  The
+ * other N nodes are leafs, with meaningful keys, empty maps, and null stratification objects
+ *
+ * @author Mark DePristo
+ * @since 3/27/12
+ */
+ at Invariant({
+        "(isLeaf() && stratifier == null && subnodes.isEmpty()) || (!isLeaf() && stratifier != null && !subnodes.isEmpty())"})
+class StratNode<T extends Stratifier> implements Iterable<StratNode<T>> {
+    int key = -1;
+    final T stratifier;
+    final Map<Object, StratNode<T>> subnodes; // NOTE, because we don't iterate our best option is a HashMap
+
+    protected StratNode() {
+        this.subnodes = Collections.emptyMap();
+        this.stratifier = null;
+    }
+
+    protected StratNode(final T stratifier, final Map<Object, StratNode<T>> subnodes) {
+        this.stratifier = stratifier;
+        // important to reallocate an unmodififable hashmap with this specific size for space and safety
+        this.subnodes = Collections.unmodifiableMap(new HashMap<Object, StratNode<T>>(subnodes));
+    }
+
+    @Requires("key >= 0")
+    public void setKey(final int key) {
+        if ( ! isLeaf() )
+            throw new ReviewedGATKException("Cannot set key of non-leaf node");
+        this.key = key;
+    }
+
+    @Requires({
+            "states != null",
+            "offset >= 0",
+            "offset <= states.size()"
+            })
+    public int find(final List<Object> states, int offset) {
+        if ( isLeaf() ) // we're here!
+            return key;
+        else {
+            final Object state = states.get(offset);
+            StratNode<T> subnode = subnodes.get(state);
+            if ( subnode == null )
+                return -1;
+            else
+                return subnode.find(states, offset+1);
+        }
+    }
+
+    @Requires({
+            "multipleStates != null",
+            "offset >= 0",
+            "offset <= multipleStates.size()",
+            "keys != null",
+            "offset == multipleStates.size() || multipleStates.get(offset) != null"})
+    public void find(final List<List<Object>> multipleStates, final int offset, final HashSet<Integer> keys) {
+        if ( isLeaf() ) // we're here!
+            keys.add(key);
+        else {
+            for ( final Object state : multipleStates.get(offset) ) {
+                // loop over all of the states at this offset
+                final StratNode<T> subnode = subnodes.get(state);
+                if ( subnode == null )
+                    throw new ReviewedGATKException("Couldn't find state for " + state + " at node " + this);
+                else
+                    subnode.find(multipleStates, offset+1, keys);
+            }
+        }
+    }
+
+    @Ensures("result >= 0")
+    public int getKey() {
+        if ( ! isLeaf() )
+            throw new ReviewedGATKException("Cannot get key of non-leaf node");
+        else
+            return key;
+    }
+
+    protected Map<Object, StratNode<T>> getSubnodes() {
+        return subnodes;
+    }
+
+    @Ensures("result >= 0")
+    public int size() {
+        if ( isLeaf() )
+            return 1;
+        else {
+            return subnodes.values().iterator().next().size() * subnodes.size();
+        }
+    }
+
+    public T getSetOfStates() {
+        return stratifier;
+    }
+
+    /**
+     * @return true if this node is a leaf
+     */
+    public boolean isLeaf() {
+        return stratifier == null;
+    }
+
+    /**
+     * Returns an iterator over this node and all subnodes including internal and leaf nodes
+     * @return
+     */
+    @Override
+    @Ensures("result != null")
+    public Iterator<StratNode<T>> iterator() {
+        return new StratNodeIterator<T>(this);
+    }
+}
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/tools/walkers/varianteval/stratifications/manager/StratNodeIterator.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/tools/walkers/varianteval/stratifications/manager/StratNodeIterator.java
new file mode 100644
index 0000000..a789b70
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/tools/walkers/varianteval/stratifications/manager/StratNodeIterator.java
@@ -0,0 +1,69 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.tools.walkers.varianteval.stratifications.manager;
+
+import org.broadinstitute.gatk.utils.exceptions.ReviewedGATKException;
+
+import java.util.*;
+
+/**
+ * Helper class for creating iterators over all nodes in the stratification tree
+ *
+ * @author Mark DePristo
+ * @since 3/27/12
+ */
+class StratNodeIterator<T extends Stratifier> implements Iterator<StratNode<T>> {
+    Queue<Iterator<StratNode<T>>> iterators = new LinkedList<Iterator<StratNode<T>>>();
+    Iterator<StratNode<T>> currentIterator;
+
+    StratNodeIterator(final StratNode<T> root) {
+        currentIterator = Collections.singleton(root).iterator();
+        for ( final StratNode<T> subNode : root.subnodes.values() )
+            iterators.add(new StratNodeIterator<T>(subNode));
+    }
+
+    @Override
+    public boolean hasNext() {
+        return currentIterator.hasNext() || ! iterators.isEmpty();
+    }
+
+    @Override
+    public StratNode<T> next() {
+        if ( currentIterator.hasNext() )
+            return currentIterator.next();
+        else if ( ! iterators.isEmpty() ) {
+            currentIterator = iterators.poll();
+            return next();
+        } else {
+            throw new IllegalStateException("Next called on empty iterator");
+        }
+    }
+
+    @Override
+    public void remove() {
+        throw new ReviewedGATKException("Cannot remove from StratNode iterator");
+    }
+}
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/tools/walkers/varianteval/stratifications/manager/StratificationManager.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/tools/walkers/varianteval/stratifications/manager/StratificationManager.java
new file mode 100644
index 0000000..7290016
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/tools/walkers/varianteval/stratifications/manager/StratificationManager.java
@@ -0,0 +1,426 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.tools.walkers.varianteval.stratifications.manager;
+
+import com.google.java.contract.Ensures;
+import com.google.java.contract.Requires;
+import org.broadinstitute.gatk.utils.Utils;
+import org.broadinstitute.gatk.utils.collections.Pair;
+import org.broadinstitute.gatk.utils.exceptions.ReviewedGATKException;
+
+import java.util.*;
+
+/**
+ * Represents the full state space of all stratification combinations
+ *
+ * @author Mark DePristo
+ * @since 3/27/12
+ */
+public class StratificationManager<K extends Stratifier, V> implements Map<List<Object>, V> {
+    private final StratNode<K> root;
+    private final int size;
+
+    private final ArrayList<K> stratifiers;
+
+    // values associated with each key
+    private final ArrayList<V> valuesByKey;
+    private final ArrayList<List<Object>> stratifierValuesByKey;
+    private final ArrayList<String> keyStrings;
+
+    // -------------------------------------------------------------------------------------
+    //
+    // creating the manager
+    //
+    // -------------------------------------------------------------------------------------
+
+    /**
+     * Create a new StratificationManager with nodes to store data for all combinations
+     * of the ordered list of strats
+     *
+     * @param strats ordered list of stratifications to representation
+     */
+    @Requires("!strats.isEmpty()")
+    public StratificationManager(final List<K> strats) {
+        this.stratifiers = new ArrayList<K>(strats);
+
+        // construct and store the full tree of strats
+        this.root = buildStratificationTree(new LinkedList<K>(strats));
+        // assign the linear key ordering to the leafs
+        assignKeys(root);
+
+        // cache the size, and check for a bad state
+        this.size = root.size();
+        if ( this.size == 0 )
+            throw new ReviewedGATKException("Size == 0 in StratificationManager");
+
+        // prepare the assocated data vectors mapping from key -> data
+        this.valuesByKey = new ArrayList<V>(size());
+        this.stratifierValuesByKey = new ArrayList<List<Object>>(size());
+        this.keyStrings = new ArrayList<String>(size());
+        for ( int i = 0; i < size(); i++ ) {
+            this.valuesByKey.add(null);
+            this.stratifierValuesByKey.add(null);
+            this.keyStrings.add(null);
+        }
+
+        assignStratifierValuesByKey(root);
+    }
+
+    /**
+     * Recursive construction helper for main constructor that fills into the
+     * complete tree of StratNodes.  This function returns the complete tree
+     * suitable for associating data with each combinatino of keys.  Note
+     * that the tree is not fully complete as the keys are not yet set for
+     * each note (see assignStratifierValuesByKey)
+     *
+     * @param strats
+     * @return
+     */
+    private StratNode<K> buildStratificationTree(final Queue<K> strats) {
+        final K first = strats.poll();
+        if ( first == null ) {
+            // we are at a leaf
+            return new StratNode<K>();
+        } else {
+            // we are in the middle of the tree
+            final Collection<Object> states = first.getAllStates();
+            
+            if ( states.isEmpty() )
+                throw new ReviewedGATKException("State " + first + " is empty!");
+            
+            final LinkedHashMap<Object, StratNode<K>> subNodes = new LinkedHashMap<Object, StratNode<K>>(states.size());
+            for ( final Object state : states ) {
+                // have to copy because poll modifies the queue
+                final Queue<K> copy = new LinkedList<K>(strats);
+                subNodes.put(state, buildStratificationTree(copy));
+            }
+            return new StratNode<K>(first, subNodes);
+        }
+    }
+
+    /**
+     * Set the key for each leaf from root, in order from 0 to N - 1 for N leaves in the tree
+     * @param root
+     */
+    @Requires("root == this.root")
+    private void assignKeys(final StratNode<K> root) {
+        int key = 0;
+        for ( final StratNode<K> node : root ) {
+            if ( node.isLeaf() )
+                node.setKey(key++);
+        }
+    }
+
+    /**
+     * Entry point to recursive tool that fills in the list of state values corresponding
+     * to each key.  After this function is called you can map from key -> List of StateValues
+     * instead of walking the tree to find the key and reading the list of state values
+     *
+     * @param root
+     */
+    private void assignStratifierValuesByKey(final StratNode<K> root) {
+        assignStratifierValuesByKey(root, new LinkedList<Object>());
+
+        // do a last sanity check that no key has null value after assigning
+        for ( List<Object> stateValues : stratifierValuesByKey )
+            if ( stateValues == null )
+                throw new ReviewedGATKException("Found a null state value set that's null");
+    }
+
+    private void assignStratifierValuesByKey(final StratNode<K> node, final LinkedList<Object> states) {
+        if ( node.isLeaf() ) { // we're here!
+            if ( states.isEmpty() )
+                throw new ReviewedGATKException("Found a leaf node with an empty state values vector");
+            stratifierValuesByKey.set(node.getKey(), Collections.unmodifiableList(new ArrayList<Object>(states)));
+        } else {
+            for ( Map.Entry<Object, StratNode<K>> entry : node.getSubnodes().entrySet() ) {
+                final LinkedList<Object> newStates = new LinkedList<Object>(states);
+                newStates.addLast(entry.getKey());
+                assignStratifierValuesByKey(entry.getValue(), newStates);
+            }
+        }
+    }
+    
+    // -------------------------------------------------------------------------------------
+    //
+    // simple accessors
+    //
+    // -------------------------------------------------------------------------------------
+
+    /**
+     * How many states are held in this stratification manager?
+     * @return
+     */
+    @Ensures("result >= 0")
+    public int size() {
+        return size;
+    }
+
+    @Ensures("result != null")
+    protected StratNode<K> getRoot() {
+        return root;
+    }
+
+    @Ensures("result != null")
+    public List<K> getStratifiers() {
+        return stratifiers;
+    }
+
+    // -------------------------------------------------------------------------------------
+    //
+    // mapping from states -> keys
+    //
+    // -------------------------------------------------------------------------------------
+
+    @Requires("states != null")
+    @Ensures("result >= -1")
+    public int getKey(final List<Object> states) {
+        return root.find(states, 0);
+    }
+
+    @Requires("allStates != null")
+    @Ensures("result != null")
+    public Set<Integer> getKeys(final List<List<Object>> allStates) {
+        final HashSet<Integer> keys = new HashSet<Integer>();
+        root.find(allStates, 0, keys);
+        return keys;
+    }
+
+    public List<Object> getStatesForKey(final int key) {
+        final List<Object> states = new ArrayList<Object>(stratifiers.size());
+        for ( int i = 0; i < stratifiers.size(); i++ ) {
+            final Object stratValue = stratifierValuesByKey.get(key).get(i);
+            states.add(stratValue);
+        }
+        return states;
+    }
+
+    public List<Pair<K, Object>> getStratsAndStatesForKey(final int key) {
+        final List<Pair<K, Object>> states = new ArrayList<Pair<K, Object>>(stratifiers.size());
+        for ( int i = 0; i < stratifiers.size(); i++ ) {
+            final K strat = stratifiers.get(i);
+            final Object stratValue = stratifierValuesByKey.get(key).get(i);
+            states.add(new Pair<K, Object>(strat, stratValue));
+        }
+        return states;
+    }
+
+    public String getStratsAndStatesStringForKey(final int key) {
+        if ( keyStrings.get(key) == null ) {
+            StringBuilder b = new StringBuilder();
+            for ( int i = 0; i < stratifiers.size(); i++ ) {
+                final K strat = stratifiers.get(i);
+                final Object stratValue = stratifierValuesByKey.get(key).get(i);
+                b.append(strat.toString()).append(":").append(stratValue.toString());
+            }
+            keyStrings.set(key, b.toString());
+        }
+        
+        return keyStrings.get(key);
+    }
+
+    // -------------------------------------------------------------------------------------
+    //
+    // valuesByKey
+    //
+    // -------------------------------------------------------------------------------------
+
+    @Override
+    @Ensures("result != null")
+    public ArrayList<V> values() {
+        return valuesByKey;
+    }
+    
+    public Collection<V> values(List<List<Object>> states) {
+        // TODO -- SHOULD BE INLINE TO AVOID CREATING LIST OF KEYS JUST TO ITERATE OVER IT
+        Collection<V> vals = new LinkedList<V>();
+        for ( int key : getKeys(states) ) 
+            vals.add(get(key));
+        return vals;
+    }
+
+    @Requires("key >= 0 && key <= size()")
+    @Ensures("get(key) == value")
+    public void set(final int key, final V value) {
+        valuesByKey.set(key, value);
+    }
+
+    @Requires("key >= 0 && key <= size()")
+    public V get(final int key) {
+        return valuesByKey.get(key);
+    }
+
+    @Requires("getKey(states) != -1")
+    public V get(final List<Object> states) {
+        return get(getKey(states));
+    }
+
+    @Override
+    public V get(final Object o) {
+        return get((List<Object>)o);
+    }
+
+    @Override
+    public boolean isEmpty() {
+        return false;
+    }
+
+    public boolean containsKey(final List<Object> o) {
+        return getKey(o) != -1;
+    }
+
+    @Override
+    public boolean containsKey(final Object o) {
+        return containsKey((List<Object>)o);
+    }
+
+    @Override
+    public boolean containsValue(final Object o) {
+        throw new ReviewedGATKException("containsValue() not implemented for StratificationManager");
+    }
+
+    @Override
+    public V put(final List<Object> objects, final V v) {
+        throw new ReviewedGATKException("put() not implemented for StratificationManager");
+    }
+
+    @Override
+    public V remove(final Object o) {
+        throw new ReviewedGATKException("remove() not implemented for StratificationManager");
+    }
+
+    @Override
+    public void putAll(final Map<? extends List<Object>, ? extends V> map) {
+        throw new ReviewedGATKException("clear() not implemented for StratificationManager");
+    }
+
+    @Override
+    public void clear() {
+        throw new ReviewedGATKException("clear() not implemented for StratificationManager");
+    }
+
+    @Override
+    public Set<List<Object>> keySet() {
+        throw new ReviewedGATKException("Not yet implemented");
+    }
+
+    @Override
+    public Set<Entry<List<Object>, V>> entrySet() {
+        throw new ReviewedGATKException("Not yet implemented");
+    }
+
+    // -------------------------------------------------------------------------------------
+    //
+    // utilities
+    //
+    // -------------------------------------------------------------------------------------
+
+    public static List<List<Object>> combineStates(final List<Object> first, final List<Object> second) {
+        final List<List<Object>> combined = new ArrayList<List<Object>>(first.size());
+        for ( int i = 0; i < first.size(); i++ ) {
+            final Object firstI = first.get(i);
+            final Object secondI = second.get(i);
+            if ( firstI.equals(secondI) ) 
+                combined.add(Collections.singletonList(firstI));
+            else 
+                combined.add(Arrays.asList(firstI, secondI));
+        }
+        return combined;
+    }
+
+    public interface Combiner<V> {
+        /** take two values of type V and return a combined value of type V */
+        public V combine(final V lhs, final V rhs);
+    }
+
+    /**
+     * Remaps the stratifications from one stratification set to another, combining
+     * the values in V according to the combiner function.
+     *
+     * stratifierToReplace defines a set of states S1, while newStratifier defines
+     * a new set S2.  remappedStates is a map from all of S1 into at least some of
+     * S2.  This function creates a new, fully initialized manager where all of the
+     * data in this new manager is derived from the original data in this object
+     * combined according to the mapping remappedStates.  When multiple
+     * elements of S1 can map to the same value in S2, these are sequentially
+     * combined by the function combiner.  Suppose for example at states s1, s2, and
+     * s3 all map to N1.  Eventually the value associated with state N1 would be
+     *
+     *   value(N1) = combine(value(s1), combine(value(s2), value(s3))
+     *
+     * in some order for s1, s2, and s3, which is not defined.  Note that this function
+     * only supports combining one stratification at a time, but in principle a loop over
+     * stratifications and this function could do the multi-dimensional collapse.
+     *
+     * @param stratifierToReplace
+     * @param newStratifier
+     * @param combiner
+     * @param remappedStates
+     * @return
+     */
+    public StratificationManager<K, V> combineStrats(final K stratifierToReplace,
+                                                     final K newStratifier,
+                                                     final Combiner<V> combiner,
+                                                     final Map<Object, Object> remappedStates) {
+        // make sure the mapping is reasonable
+        if ( ! newStratifier.getAllStates().containsAll(remappedStates.values()) )
+            throw new ReviewedGATKException("combineStrats: remapped states contains states not found in newStratifer state set");
+
+        if ( ! remappedStates.keySet().containsAll(stratifierToReplace.getAllStates()) )
+            throw new ReviewedGATKException("combineStrats: remapped states missing mapping for some states");
+
+        // the new strats are the old ones with the single replacement
+        final List<K> newStrats = new ArrayList<K>(getStratifiers());
+        final int stratOffset = newStrats.indexOf(stratifierToReplace);
+        if ( stratOffset == -1 )
+            throw new ReviewedGATKException("Could not find strat to replace " + stratifierToReplace + " in existing strats " + newStrats);
+        newStrats.set(stratOffset, newStratifier);
+
+        // create an empty but fully initialized new manager
+        final StratificationManager<K, V> combined = new StratificationManager<K, V>(newStrats);
+
+        // for each key, get its state, update it according to the map, and update the combined manager
+        for ( int key = 0; key < size(); key++ ) {
+            // the new state is just the old one with the replacement
+            final List<Object> newStates = new ArrayList<Object>(getStatesForKey(key));
+            final Object oldState = newStates.get(stratOffset);
+            final Object newState = remappedStates.get(oldState);
+            newStates.set(stratOffset, newState);
+
+            // look up the new key given the new state
+            final int combinedKey = combined.getKey(newStates);
+            if ( combinedKey == -1 ) throw new ReviewedGATKException("Couldn't find key for states: " + Utils.join(",", newStates));
+
+            // combine the old value with whatever new value is in combined already
+            final V combinedValue = combiner.combine(combined.get(combinedKey), get(key));
+
+            // update the value associated with combined key
+            combined.set(combinedKey, combinedValue);
+        }
+
+        return combined;
+    }
+}
\ No newline at end of file
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/tools/walkers/varianteval/stratifications/manager/Stratifier.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/tools/walkers/varianteval/stratifications/manager/Stratifier.java
new file mode 100644
index 0000000..b096db9
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/tools/walkers/varianteval/stratifications/manager/Stratifier.java
@@ -0,0 +1,41 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.tools.walkers.varianteval.stratifications.manager;
+
+import java.util.List;
+
+/**
+ * A basic interface for a class to be used with the StratificationManager system
+ *
+ * @author Mark DePristo
+ * @since 3/28/12
+ */
+public interface Stratifier<Object> {
+    /**
+     * @return a list of all objects states that may be provided by this States provider
+     */
+    public List<Object> getAllStates();
+}
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/tools/walkers/varianteval/util/Analysis.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/tools/walkers/varianteval/util/Analysis.java
new file mode 100644
index 0000000..67dc187
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/tools/walkers/varianteval/util/Analysis.java
@@ -0,0 +1,36 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.tools.walkers.varianteval.util;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+
+ at Retention(RetentionPolicy.RUNTIME)
+public @interface Analysis {
+    String name() default ""; // its description, required
+    String description(); // its description, required
+    boolean molten() default false; // if true we'll look for a @Molten map
+}
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/tools/walkers/varianteval/util/AnalysisModuleScanner.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/tools/walkers/varianteval/util/AnalysisModuleScanner.java
new file mode 100644
index 0000000..411394b
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/tools/walkers/varianteval/util/AnalysisModuleScanner.java
@@ -0,0 +1,154 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.tools.walkers.varianteval.util;
+
+import org.broadinstitute.gatk.utils.exceptions.ReviewedGATKException;
+
+import java.lang.annotation.Annotation;
+import java.lang.reflect.Field;
+import java.util.HashMap;
+import java.util.LinkedHashMap;
+import java.util.Map;
+
+
+/**
+ * @author aaron
+ *         <p/>
+ *         Class AnalysisModuleScanner
+ *         <p/>
+ *         Given an analysis, find the annotated fields and methods.  Given this module and
+ *         the object, a Mashalling object can serialize or deserialize a analysis module.
+ */
+public class AnalysisModuleScanner {
+    final private static Map<String, Annotation[]> annotationCache = new HashMap<String, Annotation[]>();
+
+    // what we extracted from the class
+    private Map<Field, DataPoint> datums = new LinkedHashMap<Field, DataPoint>();   // the data we've discovered
+    private Analysis analysis;  // the analysis annotation
+    
+    private Field moltenField = null;
+    private Molten moltenAnnotation = null;
+    
+    // private storage of the class type
+    private final Class cls;
+
+    /**
+     * create a report scanner from the passed in class
+     * @param cls the target class, annotated with the @Analysis annotation
+     */
+    public AnalysisModuleScanner(Class cls) {
+        this.cls = cls;
+        scan(); // scan the passed in class
+    }
+
+    /**
+     * create a report scanner from the passed in class
+     * @param obj the target object, annotated with the @Analysis annotation
+     */
+    public AnalysisModuleScanner(Object obj) {
+        this.cls = obj.getClass();
+        scan(); // scan the passed in class
+    }
+
+    /** scan the class and find all appropriate fields and tables */
+    public void scan() {
+        if (cls == null || !cls.isAnnotationPresent(Analysis.class))
+            throw new ReviewedGATKException("The class passed in cannot be null, " + "" +
+                                     "and must contain the @Analysis annotation, class " + cls + " was the input");
+
+        // get the annotation off of the class
+        analysis = (Analysis) cls.getAnnotation(Analysis.class);
+        scanFields();
+    }
+
+    /**
+     * scan the fields of the class, extracting parameters and table annotations and their associated fields
+     */
+    private void scanFields() {
+        // get the fields from the class, and extract
+        for ( Class superCls = cls; superCls != null; superCls=superCls.getSuperclass() ) {
+            for (Field f : superCls.getDeclaredFields()) {
+                for (Annotation annotation : getAnnotations(f)) {
+                    if (annotation.annotationType().equals(DataPoint.class))
+                        datums.put(f,(DataPoint) annotation);
+                    if ( annotation.annotationType().equals(Molten.class)) {
+                        if ( hasMoltenField() )
+                            throw new ReviewedGATKException("Analysis " + analysis.name() + " has multiple @Molten fields, which is forbidden");
+                        moltenField = f;
+                        moltenAnnotation = (Molten)annotation;
+                    }
+                }
+            }
+        }
+        
+        if ( hasMoltenField() ) {
+            if ( datums.size() > 0 )
+                throw new ReviewedGATKException("Analysis " + analysis.name() + " has an @Molten field as well as @DataPoint fields, which is forbidden");
+        }
+    }
+
+    public Field getMoltenField() {
+        return moltenField;
+    }
+
+    public Molten getMoltenAnnotation() {
+        return moltenAnnotation;
+    }
+
+    public boolean hasMoltenField() {
+        return getMoltenField() != null;
+    }
+
+    private Annotation[] getAnnotations(final Field field) {
+        final String fieldName = field.toString();
+        Annotation[] annotations = annotationCache.get(fieldName);
+        if ( annotations == null ) {
+            annotations = field.getAnnotations();
+            annotationCache.put(fieldName, annotations);
+        }
+        return annotations;
+    }
+
+    /**
+     *
+     * @return a map of the datum annotations found
+     */
+    public Map<Field, DataPoint> getData() {
+        return datums;
+    }
+
+    /**
+     *
+     * @return the analysis annotation found
+     */
+    public Analysis getAnalysis() {
+        return analysis;
+    }
+
+    public Class getModuleClass() {
+        return cls;
+    }
+}
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/tools/walkers/varianteval/util/DataPoint.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/tools/walkers/varianteval/util/DataPoint.java
new file mode 100644
index 0000000..0805cb5
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/tools/walkers/varianteval/util/DataPoint.java
@@ -0,0 +1,35 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.tools.walkers.varianteval.util;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+
+ at Retention(RetentionPolicy.RUNTIME)
+public @interface DataPoint {
+    String description() default ""; // the description, optional
+    String format() default "";
+}
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/tools/walkers/varianteval/util/EvaluationContext.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/tools/walkers/varianteval/util/EvaluationContext.java
new file mode 100644
index 0000000..7e9f2da
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/tools/walkers/varianteval/util/EvaluationContext.java
@@ -0,0 +1,115 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.tools.walkers.varianteval.util;
+
+import org.broadinstitute.gatk.engine.contexts.AlignmentContext;
+import org.broadinstitute.gatk.engine.contexts.ReferenceContext;
+import org.broadinstitute.gatk.engine.refdata.RefMetaDataTracker;
+import org.broadinstitute.gatk.tools.walkers.varianteval.VariantEval;
+import org.broadinstitute.gatk.tools.walkers.varianteval.evaluators.VariantEvaluator;
+import org.broadinstitute.gatk.tools.walkers.varianteval.stratifications.manager.StratificationManager;
+import org.broadinstitute.gatk.utils.exceptions.ReviewedGATKException;
+import htsjdk.variant.variantcontext.VariantContext;
+
+import java.util.ArrayList;
+import java.util.Set;
+import java.util.TreeSet;
+
+public final class EvaluationContext {
+    // NOTE: must be hashset to avoid O(log n) cost of iteration in the very frequently called apply function
+    final VariantEval walker;
+    private final ArrayList<VariantEvaluator> evaluationInstances;
+    private final Set<Class<? extends VariantEvaluator>> evaluationClasses;
+
+    public EvaluationContext(final VariantEval walker, final Set<Class<? extends VariantEvaluator>> evaluationClasses) {
+        this(walker, evaluationClasses, true);
+    }
+
+    private EvaluationContext(final VariantEval walker, final Set<Class<? extends VariantEvaluator>> evaluationClasses, final boolean doInitialize) {
+        this.walker = walker;
+        this.evaluationClasses = evaluationClasses;
+        this.evaluationInstances = new ArrayList<VariantEvaluator>(evaluationClasses.size());
+
+        for ( final Class<? extends VariantEvaluator> c : evaluationClasses ) {
+            try {
+                final VariantEvaluator eval = c.newInstance();
+                if ( doInitialize ) eval.initialize(walker);
+                evaluationInstances.add(eval);
+            } catch (InstantiationException e) {
+                throw new ReviewedGATKException("Unable to instantiate eval module '" + c.getSimpleName() + "'", e);
+            } catch (IllegalAccessException e) {
+                throw new ReviewedGATKException("Illegal access error when trying to instantiate eval module '" + c.getSimpleName() + "'", e);
+            }
+        }
+    }
+
+    /**
+     * Returns a sorted set of VariantEvaluators
+     *
+     * @return
+     */
+    public final TreeSet<VariantEvaluator> getVariantEvaluators() {
+        return new TreeSet<VariantEvaluator>(evaluationInstances);
+    }
+
+    public final void apply(RefMetaDataTracker tracker, ReferenceContext ref, AlignmentContext context, VariantContext comp, VariantContext eval) {
+        for ( final VariantEvaluator evaluation : evaluationInstances ) {
+            // the other updateN methods don't see a null context
+            if ( tracker == null )
+                continue;
+
+            // now call the single or paired update function
+            switch ( evaluation.getComparisonOrder() ) {
+                case 1:
+                    if (eval != null) {
+                        evaluation.update1(eval, tracker, ref, context);
+                    }
+                    break;
+                case 2:
+                    evaluation.update2(eval, comp, tracker, ref, context);
+                    break;
+                default:
+                    throw new ReviewedGATKException("BUG: Unexpected evaluation order " + evaluation);
+            }
+        }
+    }
+
+    public void combine(final EvaluationContext rhs) {
+        for ( int i = 0; i < evaluationInstances.size(); i++ )
+            evaluationInstances.get(i).combine(rhs.evaluationInstances.get(i));
+    }
+
+    public final static EvaluationContextCombiner COMBINER = new EvaluationContext.EvaluationContextCombiner();
+    private static class EvaluationContextCombiner implements StratificationManager.Combiner<EvaluationContext> {
+        @Override
+        public EvaluationContext combine(EvaluationContext lhs, final EvaluationContext rhs) {
+            if ( lhs == null )
+                lhs = new EvaluationContext(rhs.walker, rhs.evaluationClasses, false);
+            lhs.combine(rhs);
+            return lhs;
+        }
+    }
+}
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/tools/walkers/varianteval/util/Molten.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/tools/walkers/varianteval/util/Molten.java
new file mode 100644
index 0000000..57c4fbc
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/tools/walkers/varianteval/util/Molten.java
@@ -0,0 +1,64 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.tools.walkers.varianteval.util;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+
+/**
+ * Molten for @Analysis modules.
+ *
+ * If you are flagged as a molten analysis, then there must be one and
+ * only one annotation in that evaluation module: @Molten which
+ * must have time Map<Object, Object>.  This data set will then
+ * be represented in the VE output as:
+ *
+ * variable value
+ * key1     value1
+ * key2     value1
+ * ...
+ * keyN     valueN
+ *
+ * in the output table.  The names of these two fields can be override via annotation values.
+ */
+ at Retention(RetentionPolicy.RUNTIME)
+public @interface Molten {
+    String description() default ""; // the description, optional
+
+    /**
+     * The name to use for the molten variable field in the output table.
+     * @return
+     */
+    String variableName() default "variable";
+    String variableFormat() default "";
+
+    /**
+     * The name to use for the molten value field in the output table.
+     * @return
+     */
+    String valueName() default "value";
+    String valueFormat() default "";
+}
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/tools/walkers/varianteval/util/SortableJexlVCMatchExp.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/tools/walkers/varianteval/util/SortableJexlVCMatchExp.java
new file mode 100644
index 0000000..a759eb2
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/tools/walkers/varianteval/util/SortableJexlVCMatchExp.java
@@ -0,0 +1,45 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.tools.walkers.varianteval.util;
+
+import org.apache.commons.jexl2.Expression;
+import htsjdk.variant.variantcontext.VariantContextUtils;
+
+public class SortableJexlVCMatchExp extends VariantContextUtils.JexlVCMatchExp implements Comparable<SortableJexlVCMatchExp> {
+    /**
+     * Create a new matcher expression with name and JEXL expression exp
+     *
+     * @param name name
+     * @param exp  expression
+     */
+    public SortableJexlVCMatchExp(String name, Expression exp) {
+        super(name, exp);
+    }
+
+    public int compareTo(SortableJexlVCMatchExp sortableJexlVCMatchExp) {
+        return this.name.compareTo(sortableJexlVCMatchExp.name);
+    }
+}
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/tools/walkers/varianteval/util/VariantEvalUtils.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/tools/walkers/varianteval/util/VariantEvalUtils.java
new file mode 100644
index 0000000..6f623d4
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/tools/walkers/varianteval/util/VariantEvalUtils.java
@@ -0,0 +1,311 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.tools.walkers.varianteval.util;
+
+import org.apache.log4j.Logger;
+import org.broadinstitute.gatk.utils.commandline.RodBinding;
+import org.broadinstitute.gatk.engine.contexts.ReferenceContext;
+import org.broadinstitute.gatk.engine.refdata.RefMetaDataTracker;
+import org.broadinstitute.gatk.tools.walkers.varianteval.VariantEval;
+import org.broadinstitute.gatk.tools.walkers.varianteval.evaluators.StandardEval;
+import org.broadinstitute.gatk.tools.walkers.varianteval.evaluators.VariantEvaluator;
+import org.broadinstitute.gatk.tools.walkers.varianteval.stratifications.RequiredStratification;
+import org.broadinstitute.gatk.tools.walkers.varianteval.stratifications.StandardStratification;
+import org.broadinstitute.gatk.tools.walkers.varianteval.stratifications.VariantStratifier;
+import org.broadinstitute.gatk.utils.classloader.PluginManager;
+import htsjdk.variant.vcf.VCFConstants;
+import org.broadinstitute.gatk.utils.exceptions.GATKException;
+import org.broadinstitute.gatk.utils.exceptions.UserException;
+import htsjdk.variant.variantcontext.VariantContext;
+import htsjdk.variant.variantcontext.VariantContextBuilder;
+import htsjdk.variant.variantcontext.VariantContextUtils;
+
+import java.util.*;
+
+public class VariantEvalUtils {
+    private final VariantEval variantEvalWalker;
+    Logger logger;
+
+    public VariantEvalUtils(VariantEval variantEvalWalker) {
+        this.variantEvalWalker = variantEvalWalker;
+        this.logger = variantEvalWalker.getLogger();
+    }
+
+    /**
+     * List all of the available evaluation modules, then exit successfully
+     */
+    public void listModulesAndExit() {
+        List<Class<? extends VariantStratifier>> vsClasses = new PluginManager<VariantStratifier>(VariantStratifier.class).getPlugins();
+        List<Class<? extends VariantEvaluator>> veClasses = new PluginManager<VariantEvaluator>(VariantEvaluator.class).getPlugins();
+
+        logger.info("Available stratification modules:");
+        logger.info("(Standard modules are starred)");
+        for (Class<? extends VariantStratifier> vsClass : vsClasses) {
+            logger.info("\t" + vsClass.getSimpleName() + (RequiredStratification.class.isAssignableFrom(vsClass) || StandardStratification.class.isAssignableFrom(vsClass) ? "*" : ""));
+        }
+        logger.info("");
+
+        logger.info("Available evaluation modules:");
+        logger.info("(Standard modules are starred)");
+        for (Class<? extends VariantEvaluator> veClass : veClasses) {
+            logger.info("\t" + veClass.getSimpleName() + (StandardEval.class.isAssignableFrom(veClass) ? "*" : ""));
+        }
+        logger.info("");
+
+        System.exit(0);
+    }
+
+    /**
+     * Initialize required, standard and user-specified stratification objects
+     *
+     * @param noStandardStrats  don't use the standard stratifications
+     * @param modulesToUse      the list of stratification modules to use
+     * @return set of stratifications to use
+     */
+    public List<VariantStratifier> initializeStratificationObjects(boolean noStandardStrats, String[] modulesToUse) {
+        TreeSet<VariantStratifier> strats = new TreeSet<VariantStratifier>();
+        Set<String> stratsToUse = new HashSet<String>();
+
+        // Create a map for all stratification modules for easy lookup.
+        HashMap<String, Class<? extends VariantStratifier>> classMap = new HashMap<String, Class<? extends VariantStratifier>>();
+        for (Class<? extends VariantStratifier> c : new PluginManager<VariantStratifier>(VariantStratifier.class).getPlugins()) {
+            classMap.put(c.getSimpleName(), c);
+        }
+
+        // We must use all required stratification modules.
+        for (Class<? extends RequiredStratification> reqClass : new PluginManager<RequiredStratification>(RequiredStratification.class).getPlugins()) {
+            if (classMap.containsKey(reqClass.getSimpleName())) {
+                stratsToUse.add(reqClass.getSimpleName());
+            }
+        }
+
+        // By default, use standard stratification modules.
+        if (!noStandardStrats) {
+            for (Class<? extends StandardStratification> stdClass : new PluginManager<StandardStratification>(StandardStratification.class).getPlugins()) {
+                if (classMap.containsKey(stdClass.getSimpleName())) {
+                    stratsToUse.add(stdClass.getSimpleName());
+                }
+            }
+        }
+
+        // Now add the user-selected modules
+        stratsToUse.addAll(Arrays.asList(modulesToUse));
+
+        // Instantiate the stratifications
+        for (String module : stratsToUse) {
+            if (!classMap.containsKey(module)) {
+                throw new UserException.CommandLineException("Module " + module + " could not be found; please check that you have specified the class name correctly");
+            }
+
+            if (classMap.containsKey(module)) {
+                Class<? extends VariantStratifier> c = classMap.get(module);
+
+                try {
+                    VariantStratifier vs = c.newInstance();
+                    vs.setVariantEvalWalker(variantEvalWalker);
+                    vs.initialize();
+
+                    strats.add(vs);
+                } catch (InstantiationException e) {
+                    throw new GATKException("Unable to instantiate stratification module '" + c.getSimpleName() + "'");
+                } catch (IllegalAccessException e) {
+                    throw new GATKException("Illegal access error when trying to instantiate stratification module '" + c.getSimpleName() + "'");
+                }
+            }
+        }
+
+        return new ArrayList<VariantStratifier>(strats);
+    }
+
+    /**
+     * Initialize required, standard and user-specified evaluation objects
+     *
+     * @param noStandardEvals don't use the standard evaluations
+     * @param modulesToUse    the list of evaluation modules to use
+     * @return set of evaluations to use
+     */
+    public Set<Class<? extends VariantEvaluator>> initializeEvaluationObjects(boolean noStandardEvals, String[] modulesToUse) {
+        Set<Class<? extends VariantEvaluator>> evals = new HashSet<Class<? extends VariantEvaluator>>();
+
+        // Create a map for all eval modules for easy lookup.
+        HashMap<String, Class<? extends VariantEvaluator>> classMap = new HashMap<String, Class<? extends VariantEvaluator>>();
+        for (Class<? extends VariantEvaluator> c : new PluginManager<VariantEvaluator>(VariantEvaluator.class).getPlugins()) {
+            classMap.put(c.getSimpleName(), c);
+        }
+
+        // By default, use standard eval modules.
+        if (!noStandardEvals) {
+            for (Class<? extends StandardEval> stdClass : new PluginManager<StandardEval>(StandardEval.class).getPlugins()) {
+                if (classMap.containsKey(stdClass.getSimpleName())) {
+                    evals.add(classMap.get(stdClass.getSimpleName()));
+                }
+            }
+        }
+
+        // Get the specific classes provided.
+        for (String module : modulesToUse) {
+            if (!classMap.containsKey(module)) {
+                throw new UserException.CommandLineException("Module " + module + " could not be found; please check that you have specified the class name correctly");
+            }
+
+            if (classMap.containsKey(module)) {
+                evals.add(classMap.get(module));
+            }
+        }
+
+        return evals;
+    }
+
+    /**
+     * Subset a VariantContext to a single sample
+     *
+     * @param vc         the VariantContext object containing multiple samples
+     * @param sampleName the sample to pull out of the VariantContext
+     * @return a new VariantContext with just the requested sample
+     */
+    public VariantContext getSubsetOfVariantContext(VariantContext vc, String sampleName) {
+        return getSubsetOfVariantContext(vc, Collections.singleton(sampleName));
+    }
+
+    /**
+     * Subset a VariantContext to a set of samples
+     *
+     * @param vc          the VariantContext object containing multiple samples
+     * @param sampleNames the samples to pull out of the VariantContext
+     * @return a new VariantContext with just the requested samples
+     */
+    public VariantContext getSubsetOfVariantContext(VariantContext vc, Set<String> sampleNames) {
+        // if we want to preserve AC0 sites as polymorphic we need to not rederive alleles
+        final boolean deriveAlleles = variantEvalWalker.ignoreAC0Sites();
+        return ensureAnnotations(vc, vc.subContextFromSamples(sampleNames, deriveAlleles));
+    }
+
+    public VariantContext ensureAnnotations(final VariantContext vc, final VariantContext vcsub) {
+        final int originalAlleleCount = vc.getHetCount() + 2 * vc.getHomVarCount();
+        final int newAlleleCount = vcsub.getHetCount() + 2 * vcsub.getHomVarCount();
+        final boolean isSingleton = originalAlleleCount == newAlleleCount && newAlleleCount == 1;
+        final boolean hasChrCountAnnotations = vcsub.hasAttribute(VCFConstants.ALLELE_COUNT_KEY) &&
+                vcsub.hasAttribute(VCFConstants.ALLELE_FREQUENCY_KEY) &&
+                vcsub.hasAttribute(VCFConstants.ALLELE_NUMBER_KEY);
+
+        if ( ! isSingleton && hasChrCountAnnotations ) {
+            // nothing to update
+            return vcsub;
+        } else {
+            // have to do the work
+            VariantContextBuilder builder = new VariantContextBuilder(vcsub);
+
+            if ( isSingleton )
+                builder.attribute(VariantEval.IS_SINGLETON_KEY, true);
+
+            if ( ! hasChrCountAnnotations )
+                VariantContextUtils.calculateChromosomeCounts(builder, true);
+
+            return builder.make();
+        }
+    }
+
+    /**
+     * For a list of track names, bind the variant contexts to a trackName->sampleName->VariantContext mapping.
+     * Additional variant contexts per sample are automatically generated and added to the map unless the sample name
+     * matches the ALL_SAMPLE_NAME constant.
+     *
+     * @param tracker        the metadata tracker
+     * @param ref            the reference context
+     * @param tracks         the list of tracks to process
+     * @param byFilter       if false, only accept PASSing VariantContexts.  Otherwise, accept both PASSing and filtered
+     *                       sites
+     * @param subsetBySample if false, do not separate the track into per-sample VCs
+     * @param trackPerSample if false, don't stratify per sample (and don't cut up the VariantContext like we would need
+     *                       to do this)
+     * @return the mapping of track to VC list that should be populated
+     */
+    public HashMap<RodBinding<VariantContext>, HashMap<String, Collection<VariantContext>>>
+    bindVariantContexts(RefMetaDataTracker tracker,
+                        ReferenceContext ref,
+                        List<RodBinding<VariantContext>> tracks,
+                        boolean byFilter,
+                        boolean subsetBySample,
+                        boolean trackPerSample,
+                        boolean mergeTracks) {
+        if (tracker == null)
+            return null;
+
+        HashMap<RodBinding<VariantContext>, HashMap<String, Collection<VariantContext>>> bindings = new HashMap<RodBinding<VariantContext>, HashMap<String, Collection<VariantContext>>>();
+
+        RodBinding<VariantContext> firstTrack = tracks.isEmpty() ? null : tracks.get(0);
+        for (RodBinding<VariantContext> track : tracks) {
+            HashMap<String, Collection<VariantContext>> mapping = new HashMap<String, Collection<VariantContext>>();
+
+            for (VariantContext vc : tracker.getValues(track, ref.getLocus())) {
+
+                // First, filter the VariantContext to represent only the samples for evaluation
+                VariantContext vcsub = vc;
+
+                if (subsetBySample && vc.hasGenotypes())
+                    vcsub = getSubsetOfVariantContext(vc, variantEvalWalker.getSampleNamesForEvaluation());
+
+                if ((byFilter || !vcsub.isFiltered())) {
+                    addMapping(mapping, VariantEval.getAllSampleName(), vcsub);
+                }
+
+                // Now, if stratifying, split the subsetted vc per sample and add each as a new context
+                if (vc.hasGenotypes() && trackPerSample) {
+                    for (String sampleName : variantEvalWalker.getSampleNamesForEvaluation()) {
+                        VariantContext samplevc = getSubsetOfVariantContext(vc, sampleName);
+
+                        if (byFilter || !samplevc.isFiltered()) {
+                            addMapping(mapping, sampleName, samplevc);
+                        }
+                    }
+                }
+            }
+
+            if (mergeTracks && bindings.containsKey(firstTrack)) {
+                // go through each binding of sample -> value and add all of the bindings from this entry
+                HashMap<String, Collection<VariantContext>> firstMapping = bindings.get(firstTrack);
+                for (Map.Entry<String, Collection<VariantContext>> elt : mapping.entrySet()) {
+                    Collection<VariantContext> firstMappingSet = firstMapping.get(elt.getKey());
+                    if (firstMappingSet != null) {
+                        firstMappingSet.addAll(elt.getValue());
+                    } else {
+                        firstMapping.put(elt.getKey(), elt.getValue());
+                    }
+                }
+            } else {
+                bindings.put(track, mapping);
+            }
+        }
+
+        return bindings;
+    }
+
+    private void addMapping(HashMap<String, Collection<VariantContext>> mappings, String sample, VariantContext vc) {
+        if (!mappings.containsKey(sample))
+            mappings.put(sample, new ArrayList<VariantContext>(1));
+        mappings.get(sample).add(vc);
+    }
+}
\ No newline at end of file
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/tools/walkers/variantrecalibration/VQSRCalibrationCurve.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/tools/walkers/variantrecalibration/VQSRCalibrationCurve.java
new file mode 100644
index 0000000..355441d
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/tools/walkers/variantrecalibration/VQSRCalibrationCurve.java
@@ -0,0 +1,160 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.tools.walkers.variantrecalibration;
+
+import org.apache.log4j.Logger;
+import org.broadinstitute.gatk.utils.exceptions.ReviewedGATKException;
+import org.broadinstitute.gatk.utils.exceptions.UserException;
+import org.broadinstitute.gatk.utils.text.XReadLines;
+import htsjdk.variant.variantcontext.VariantContext;
+
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Created by IntelliJ IDEA.
+ * User: depristo
+ * Date: 3/11/11
+ * Time: 10:33 AM
+ * To change this template use File | Settings | File Templates.
+ */
+public class VQSRCalibrationCurve {
+    private final static boolean DEBUG = false;
+    List<VQSRRange> points;
+    public static final double CERTAIN_FALSE_POSITIVE = -1;
+
+    private static class VQSRRange {
+        double start, stop, truePositiveRate;
+
+        public double getStart() {
+            return start;
+        }
+
+        public double getStop() {
+            return stop;
+        }
+
+        public double getTruePositiveRate() {
+            return truePositiveRate;
+        }
+
+        private VQSRRange(double start, double stop, double truePositiveRate) {
+            this.start = start;
+            this.stop = stop;
+            this.truePositiveRate = truePositiveRate;
+        }
+    }
+
+    public static VQSRCalibrationCurve readFromFile(File source) {
+        List<VQSRRange> points = new ArrayList<VQSRRange>();
+
+        try {
+            for ( String line : new XReadLines(source).readLines() ) {
+                if ( ! line.trim().isEmpty() ) {
+                    String[] parts = line.split("\\s+");
+                    double fpRate = Double.parseDouble(parts[2]);
+                    double tpRate = fpRate >= 1.0 ? CERTAIN_FALSE_POSITIVE : 1.0 - fpRate;
+                    points.add(new VQSRRange(Double.parseDouble(parts[0]), Double.parseDouble(parts[1]), tpRate));
+                }
+            }
+        } catch ( FileNotFoundException e ) {
+            throw new UserException.CouldNotReadInputFile(source, e);
+        }
+
+        // ensure that the entire range gets caught
+        points.get(0).start = Double.POSITIVE_INFINITY;
+        points.get(points.size()-1).stop = Double.NEGATIVE_INFINITY;
+
+        return new VQSRCalibrationCurve(points);
+    }
+
+    protected VQSRCalibrationCurve(List<VQSRRange> points) {
+        this.points = points;
+    }
+
+    public boolean certainFalsePositive(String VQSRQualKey, VariantContext vc) {
+        return probTrueVariant(VQSRQualKey, vc) == CERTAIN_FALSE_POSITIVE;
+    }
+
+
+    public double probTrueVariant(double VQSRqual) {
+        for ( VQSRRange r : points ) {
+            if ( VQSRqual <= r.getStart() && VQSRqual > r.getStop() )
+                return r.getTruePositiveRate();
+        }
+
+        throw new ReviewedGATKException("BUG: should not be able to reach this code");
+    }
+
+    public double probTrueVariant(String VQSRQualKey, VariantContext vc) {
+        if ( vc.isFiltered() )
+            return 0.0;
+        else if ( vc.hasAttribute(VQSRQualKey) ) {
+            double qual = vc.getAttributeAsDouble(VQSRQualKey, 0.0);
+            return probTrueVariant(qual);
+        } else {
+            throw new UserException.VariantContextMissingRequiredField(VQSRQualKey, vc);
+        }
+    }
+
+    /**
+     * Returns a likelihoods vector adjusted by the probability that the site is an error.  Returns a
+     * null vector if the probability of the site being real is 0.0
+     * @param VQSRQualKey
+     * @param vc
+     * @param log10Likelihoods
+     * @return
+     */
+    public double[] includeErrorRateInLikelihoods(String VQSRQualKey, VariantContext vc, double[] log10Likelihoods) {
+        double[] updated = new double[log10Likelihoods.length];
+
+        double alpha = probTrueVariant(VQSRQualKey, vc);
+
+        if ( alpha == CERTAIN_FALSE_POSITIVE )
+            return null;
+        else {
+            double noInfoPr = 1.0 / 3;
+            if ( DEBUG ) System.out.printf("------------------------------%n");
+            for ( int i = 0; i < log10Likelihoods.length; i++) {
+                double p = Math.pow(10, log10Likelihoods[i]);
+                double q = alpha * p + (1-alpha) * noInfoPr;
+                if ( DEBUG ) System.out.printf("  vqslod = %.2f, p = %.2e, alpha = %.2e, q = %.2e%n", vc.getAttributeAsDouble(VQSRQualKey, 0.0), p, alpha, q);
+                updated[i] = Math.log10(q);
+            }
+
+            return updated;
+        }
+    }
+
+
+    public void printInfo(Logger logger) {
+        for ( VQSRRange r : points ) {
+            logger.info(String.format("  start=%f stop=%f TPrate=%.6e", r.getStart(), r.getStop(), r.getTruePositiveRate()));
+        }
+    }
+}
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/tools/walkers/variantutils/CombineVariants.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/tools/walkers/variantutils/CombineVariants.java
new file mode 100644
index 0000000..aa69693
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/tools/walkers/variantutils/CombineVariants.java
@@ -0,0 +1,371 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.tools.walkers.variantutils;
+
+import org.broadinstitute.gatk.utils.commandline.*;
+import org.broadinstitute.gatk.engine.CommandLineGATK;
+import org.broadinstitute.gatk.engine.contexts.AlignmentContext;
+import org.broadinstitute.gatk.engine.contexts.ReferenceContext;
+import org.broadinstitute.gatk.engine.io.stubs.VariantContextWriterStub;
+import org.broadinstitute.gatk.engine.refdata.RefMetaDataTracker;
+import org.broadinstitute.gatk.engine.walkers.Reference;
+import org.broadinstitute.gatk.engine.walkers.RodWalker;
+import org.broadinstitute.gatk.engine.walkers.TreeReducible;
+import org.broadinstitute.gatk.engine.walkers.Window;
+import org.broadinstitute.gatk.tools.walkers.annotator.ChromosomeCountConstants;
+import org.broadinstitute.gatk.utils.SampleUtils;
+import org.broadinstitute.gatk.utils.help.HelpConstants;
+import org.broadinstitute.gatk.utils.variant.GATKVCFUtils;
+import org.broadinstitute.gatk.utils.variant.GATKVariantContextUtils;
+import htsjdk.variant.vcf.*;
+import org.broadinstitute.gatk.utils.exceptions.UserException;
+import org.broadinstitute.gatk.utils.help.DocumentedGATKFeature;
+import htsjdk.variant.variantcontext.VariantContext;
+import htsjdk.variant.variantcontext.VariantContextBuilder;
+import htsjdk.variant.variantcontext.VariantContextUtils;
+import htsjdk.variant.variantcontext.writer.Options;
+import htsjdk.variant.variantcontext.writer.VariantContextWriter;
+
+import java.util.*;
+
+/**
+ * Combines VCF records from different sources.
+ *
+ * <p>
+ * CombineVariants combines VCF records from different sources. Any (unique) name can be used to bind your rod data
+ * and any number of sources can be input. This tool currently supports two different combination types for each of
+ * variants (the first 8 fields of the VCF) and genotypes (the rest).
+ * Merge: combines multiple records into a single one; if sample names overlap then they are uniquified.
+ * Union: assumes each rod represents the same set of samples (although this is not enforced); using the
+ * priority list (if provided), it emits a single record instance at every position represented in the rods.
+ *
+ * CombineVariants will include a record at every site in all of your input VCF files, and annotate which input ROD
+ * bindings the record is present, pass, or filtered in in the set attribute in the INFO field. In effect,
+ * CombineVariants always produces a union of the input VCFs.  However, any part of the Venn of the N merged VCFs
+ * can be exacted using JEXL expressions on the set attribute using SelectVariants.  If you want to extract just
+ * the records in common between two VCFs, you would first run CombineVariants on the two files to generate a single
+ * VCF and then run SelectVariants to extract the common records with -select 'set == "Intersection"', as worked out
+ * in the detailed example in the documentation guide.
+ *
+ * Note that CombineVariants supports multi-threaded parallelism (8/15/12).  This is particularly useful
+ * when converting from VCF to BCF2, which can be expensive.  In this case each thread spends CPU time
+ * doing the conversion, and the GATK engine is smart enough to merge the partial BCF2 blocks together
+ * efficiency.  However, since this merge runs in only one thread, you can quickly reach diminishing
+ * returns with the number of parallel threads.  -nt 4 works well but -nt 8 may be too much.
+ *
+ * Some fine details about the merging algorithm:
+ *   <ul>
+ *   <li> As of GATK 2.1, when merging multiple VCF records at a site, the combined VCF record has the QUAL of
+ *      the first VCF record with a non-MISSING QUAL value.  The previous behavior was to take the
+ *      max QUAL, which resulted in sometime strange downstream confusion</li>
+ *   </ul>
+ *
+ * <h3>Input</h3>
+ * <p>
+ * One or more variant sets to combine.
+ * </p>
+ *
+ * <h3>Output</h3>
+ * <p>
+ * A combined VCF.
+ * </p>
+ *
+ * <h3>Examples</h3>
+ * <pre>
+ * java -Xmx2g -jar GenomeAnalysisTK.jar \
+ *   -R ref.fasta \
+ *   -T CombineVariants \
+ *   --variant input1.vcf \
+ *   --variant input2.vcf \
+ *   -o output.vcf \
+ *   -genotypeMergeOptions UNIQUIFY
+ *
+ * java -Xmx2g -jar GenomeAnalysisTK.jar \
+ *   -R ref.fasta \
+ *   -T CombineVariants \
+ *   --variant:foo input1.vcf \
+ *   --variant:bar input2.vcf \
+ *   -o output.vcf \
+ *   -genotypeMergeOptions PRIORITIZE
+ *   -priority foo,bar
+ * </pre>
+ *
+ */
+ at DocumentedGATKFeature( groupName = HelpConstants.DOCS_CAT_VARMANIP, extraDocs = {CommandLineGATK.class} )
+ at Reference(window=@Window(start=-50,stop=50))
+public class CombineVariants extends RodWalker<Integer, Integer> implements TreeReducible<Integer> {
+    /**
+     * The VCF files to merge together
+     *
+     * variants can take any number of arguments on the command line.  Each -V argument
+     * will be included in the final merged output VCF.  If no explicit name is provided,
+     * the -V arguments will be named using the default algorithm: variants, variants2, variants3, etc.
+     * The user can override this by providing an explicit name -V:name,vcf for each -V argument,
+     * and each named argument will be labeled as such in the output (i.e., set=name rather than
+     * set=variants2).  The order of arguments does not matter unless except for the naming, so
+     * if you provide an rod priority list and no explicit names than variants, variants2, etc
+     * are technically order dependent.  It is strongly recommended to provide explicit names when
+     * a rod priority list is provided.
+     */
+    @Input(fullName="variant", shortName = "V", doc="Input VCF file", required=true)
+    public List<RodBindingCollection<VariantContext>> variantCollections;
+    final private List<RodBinding<VariantContext>> variants = new ArrayList<>();
+
+    @Output(doc="File to which variants should be written")
+    protected VariantContextWriter vcfWriter = null;
+
+    @Argument(shortName="genotypeMergeOptions", doc="Determines how we should merge genotype records for samples shared across the ROD files", required=false)
+    public GATKVariantContextUtils.GenotypeMergeType genotypeMergeOption = null;
+
+    @Argument(shortName="filteredRecordsMergeType", doc="Determines how we should handle records seen at the same site in the VCF, but with different FILTER fields", required=false)
+    public GATKVariantContextUtils.FilteredRecordMergeType filteredRecordsMergeType = GATKVariantContextUtils.FilteredRecordMergeType.KEEP_IF_ANY_UNFILTERED;
+
+    @Hidden
+    @Argument(shortName="multipleAllelesMergeType", doc="Determines how we should handle records seen at the same site in the VCF, but with different allele types (for example, SNP vs. indel)", required=false)
+    public GATKVariantContextUtils.MultipleAllelesMergeType multipleAllelesMergeType = GATKVariantContextUtils.MultipleAllelesMergeType.BY_TYPE;
+
+    /**
+     * Used when taking the union of variants that contain genotypes.  A complete priority list MUST be provided.
+     */
+    @Argument(fullName="rod_priority_list", shortName="priority", doc="A comma-separated string describing the priority ordering for the genotypes as far as which record gets emitted", required=false)
+    public String PRIORITY_STRING = null;
+
+    @Argument(fullName="printComplexMerges", shortName="printComplexMerges", doc="Print out interesting sites requiring complex compatibility merging", required=false)
+    public boolean printComplexMerges = false;
+
+    @Argument(fullName="filteredAreUncalled", shortName="filteredAreUncalled", doc="If true, then filtered VCFs are treated as uncalled, so that filtered set annotations don't appear in the combined VCF", required=false)
+    public boolean filteredAreUncalled = false;
+
+    /**
+     * Used to generate a sites-only file.
+     */
+    @Argument(fullName="minimalVCF", shortName="minimalVCF", doc="If true, then the output VCF will contain no INFO or genotype FORMAT fields", required=false)
+    public boolean minimalVCF = false;
+
+    @Argument(fullName="excludeNonVariants", shortName="env", doc="Don't include loci found to be non-variant after the combining procedure", required=false)
+    public boolean EXCLUDE_NON_VARIANTS = false;
+
+    /**
+     * Set to 'null' if you don't want the set field emitted.
+     */
+    @Argument(fullName="setKey", shortName="setKey", doc="Key used in the INFO key=value tag emitted describing which set the combined VCF record came from", required=false)
+    public String SET_KEY = "set";
+
+    /**
+     * This option allows the user to perform a simple merge (concatenation) to combine the VCFs, drastically reducing the runtime.
+     */
+    @Argument(fullName="assumeIdenticalSamples", shortName="assumeIdenticalSamples", doc="If true, assume input VCFs have identical sample sets and disjoint calls", required=false)
+    public boolean ASSUME_IDENTICAL_SAMPLES = false;
+
+    @Argument(fullName="minimumN", shortName="minN", doc="Combine variants and output site only if the variant is present in at least N input files.", required=false)
+    public int minimumN = 1;
+
+    /**
+     * This option allows the suppression of the command line in the VCF header. This is most often usefully when combining variants for dozens or hundreds of smaller VCFs.
+     */
+    @Argument(fullName="suppressCommandLineHeader", shortName="suppressCommandLineHeader", doc="If true, do not output the header containing the command line used", required=false)
+    public boolean SUPPRESS_COMMAND_LINE_HEADER = false;
+
+    @Argument(fullName="mergeInfoWithMaxAC", shortName="mergeInfoWithMaxAC", doc="If true, when VCF records overlap the info field is taken from the one with the max AC instead of only taking the fields which are identical across the overlapping records.", required=false)
+    public boolean MERGE_INFO_WITH_MAX_AC = false;
+
+    private List<String> priority = null;
+
+    /** Optimization to strip out genotypes before merging if we are doing a sites_only output */
+    private boolean sitesOnlyVCF = false;
+    private Set<String> samples;
+
+    public void initialize() {
+        Map<String, VCFHeader> vcfRods = GATKVCFUtils.getVCFHeadersFromRods(getToolkit());
+
+        if ( vcfWriter instanceof VariantContextWriterStub) {
+            sitesOnlyVCF = ((VariantContextWriterStub)vcfWriter).getWriterOptions().contains(Options.DO_NOT_WRITE_GENOTYPES);
+            if ( sitesOnlyVCF ) logger.info("Pre-stripping genotypes for performance");
+        } else
+            logger.warn("VCF output file not an instance of VCFWriterStub; cannot enable sites only output option");
+
+        validateAnnotateUnionArguments();
+
+        final boolean sampleNamesAreUnique = SampleUtils.verifyUniqueSamplesNames(vcfRods);
+
+        if (genotypeMergeOption == null) {
+            if (!sampleNamesAreUnique)
+                throw new UserException("Duplicate sample names were discovered but no genotypemergeoption was supplied. " +
+                    "To combine samples without merging specify --genotypemergeoption UNIQUIFY. Merging duplicate samples " +
+                    "without specified priority is unsupported, but can be achieved by specifying --genotypemergeoption UNSORTED.");
+            else
+                genotypeMergeOption = GATKVariantContextUtils.GenotypeMergeType.UNSORTED;
+        }
+
+        if ( PRIORITY_STRING == null && genotypeMergeOption == GATKVariantContextUtils.GenotypeMergeType.PRIORITIZE) {
+            //PRIORITY_STRING = Utils.join(",", vcfRods.keySet());  Deleted by Ami (7/10/12)
+            logger.info("Priority string is not provided, using arbitrary genotyping order: "+priority);
+        }
+
+        if (genotypeMergeOption == GATKVariantContextUtils.GenotypeMergeType.REQUIRE_UNIQUE &&
+                !sampleNamesAreUnique)
+            throw new IllegalStateException("REQUIRE_UNIQUE sample names is true but duplicate names were discovered.");
+
+        samples = sitesOnlyVCF ? Collections.<String>emptySet() : SampleUtils.getSampleList(vcfRods, genotypeMergeOption);
+
+        if ( SET_KEY.toLowerCase().equals("null") )
+            SET_KEY = null;
+
+        Set<VCFHeaderLine> headerLines = VCFUtils.smartMergeHeaders(vcfRods.values(), true);
+        if ( SET_KEY != null )
+            headerLines.add(new VCFInfoHeaderLine(SET_KEY, 1, VCFHeaderLineType.String, "Source VCF for the merged record in CombineVariants"));
+        if ( !ASSUME_IDENTICAL_SAMPLES )
+             headerLines.addAll(Arrays.asList(ChromosomeCountConstants.descriptions));
+        VCFHeader vcfHeader = new VCFHeader(headerLines, samples);
+        vcfHeader.setWriteCommandLine(!SUPPRESS_COMMAND_LINE_HEADER);
+        vcfWriter.writeHeader(vcfHeader);
+
+        // collect the actual rod bindings into a list for use later
+        for ( final RodBindingCollection<VariantContext> variantCollection : variantCollections )
+            variants.addAll(variantCollection.getRodBindings());
+    }
+
+    private void validateAnnotateUnionArguments() {
+        Set<String> rodNames = SampleUtils.getRodNamesWithVCFHeader(getToolkit(), null);
+
+        if ( genotypeMergeOption == GATKVariantContextUtils.GenotypeMergeType.PRIORITIZE && PRIORITY_STRING == null )
+            throw new UserException.MissingArgument("rod_priority_list", "Priority string must be provided if you want to prioritize genotypes");
+
+        if ( PRIORITY_STRING != null){
+            priority = new ArrayList<>(Arrays.asList(PRIORITY_STRING.split(",")));
+            if ( rodNames.size() != priority.size() )
+                throw new UserException.BadArgumentValue("rod_priority_list", "The priority list must contain exactly one rod binding per ROD provided to the GATK: rodNames=" + rodNames + " priority=" + priority);
+
+            if ( ! rodNames.containsAll(priority) )
+                throw new UserException.BadArgumentValue("rod_priority_list", "Not all priority elements provided as input RODs: " + PRIORITY_STRING);
+        }
+
+    }
+
+    public Integer map(RefMetaDataTracker tracker, ReferenceContext ref, AlignmentContext context) {
+        if ( tracker == null ) // RodWalkers can make funky map calls
+            return 0;
+
+        final Set<String> rodNames = SampleUtils.getRodNamesWithVCFHeader(getToolkit(), null);
+        // get all of the vcf rods at this locus
+        // Need to provide reference bases to simpleMerge starting at current locus
+        Collection<VariantContext> vcs = tracker.getValues(variants, context.getLocation());
+
+        if ( sitesOnlyVCF ) {
+            vcs = VariantContextUtils.sitesOnlyVariantContexts(vcs);
+        }
+
+        if ( ASSUME_IDENTICAL_SAMPLES ) {
+            for ( final VariantContext vc : vcs ) {
+                vcfWriter.add(vc);
+            }
+
+            return vcs.isEmpty() ? 0 : 1;
+        }
+
+        int numFilteredRecords = 0;
+        for (final VariantContext vc : vcs) {
+            if (vc.filtersWereApplied() && vc.isFiltered())
+                numFilteredRecords++;
+        }
+
+        if (minimumN > 1 && (vcs.size() - numFilteredRecords < minimumN))
+            return 0;
+
+        final List<VariantContext> mergedVCs = new ArrayList<>();
+
+        if (multipleAllelesMergeType == GATKVariantContextUtils.MultipleAllelesMergeType.BY_TYPE) {
+            final Map<VariantContext.Type, List<VariantContext>> VCsByType = GATKVariantContextUtils.separateVariantContextsByType(vcs);
+
+            // TODO -- clean this up in a refactoring
+            // merge NO_VARIATION into another type of variant (based on the ordering in VariantContext.Type)
+            if ( VCsByType.containsKey(VariantContext.Type.NO_VARIATION) && VCsByType.size() > 1 ) {
+                final List<VariantContext> refs = VCsByType.remove(VariantContext.Type.NO_VARIATION);
+                for ( final VariantContext.Type type : VariantContext.Type.values() ) {
+                    if ( VCsByType.containsKey(type) ) {
+                        VCsByType.get(type).addAll(refs);
+                        break;
+                    }
+                }
+            }
+
+            // iterate over the types so that it's deterministic
+            for (final VariantContext.Type type : VariantContext.Type.values()) {
+                // make sure that it is a variant or in case it is not, that we want to include the sites with no variants
+                if (!EXCLUDE_NON_VARIANTS || !type.equals(VariantContext.Type.NO_VARIATION)) {
+                    if (VCsByType.containsKey(type)) {
+                        mergedVCs.add(GATKVariantContextUtils.simpleMerge(VCsByType.get(type), priority, rodNames.size(),
+                                filteredRecordsMergeType, genotypeMergeOption, true, printComplexMerges,
+                                SET_KEY, filteredAreUncalled, MERGE_INFO_WITH_MAX_AC));
+                    }
+                }
+            }
+        }
+        else if (multipleAllelesMergeType == GATKVariantContextUtils.MultipleAllelesMergeType.MIX_TYPES) {
+            mergedVCs.add(GATKVariantContextUtils.simpleMerge(vcs, priority, rodNames.size(), filteredRecordsMergeType,
+                    genotypeMergeOption, true, printComplexMerges, SET_KEY, filteredAreUncalled, MERGE_INFO_WITH_MAX_AC));
+        }
+        else {
+            logger.warn("Ignoring all records at site " + ref.getLocus());
+        }
+
+        for ( final VariantContext mergedVC : mergedVCs ) {
+            // only operate at the start of events
+            if ( mergedVC == null )
+                continue;
+
+            if ( mergedVC.hasAllele(GATKVariantContextUtils.NON_REF_SYMBOLIC_ALLELE) )
+                throw new UserException("CombineVariants should not be used to merge gVCFs produced by the HaplotypeCaller; use CombineGVCFs instead");
+
+            final VariantContextBuilder builder = new VariantContextBuilder(mergedVC);
+            // re-compute chromosome counts
+            VariantContextUtils.calculateChromosomeCounts(builder, false);
+
+            if ( minimalVCF )
+                GATKVariantContextUtils.pruneVariantContext(builder, Arrays.asList(SET_KEY));
+            final VariantContext vc = builder.make();
+            if( !EXCLUDE_NON_VARIANTS || vc.isPolymorphicInSamples() )
+                vcfWriter.add(builder.make());
+        }
+
+        return vcs.isEmpty() ? 0 : 1;
+    }
+
+    public Integer reduceInit() {
+        return 0;
+    }
+
+    public Integer reduce(Integer counter, Integer sum) {
+        return counter + sum;
+    }
+
+    @Override
+    public Integer treeReduce(Integer lhs, Integer rhs) {
+        return reduce(lhs, rhs);
+    }
+
+    public void onTraversalDone(Integer sum) {}
+}
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/tools/walkers/variantutils/ConcordanceMetrics.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/tools/walkers/variantutils/ConcordanceMetrics.java
new file mode 100644
index 0000000..2b1897c
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/tools/walkers/variantutils/ConcordanceMetrics.java
@@ -0,0 +1,369 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.tools.walkers.variantutils;
+
+import com.google.java.contract.Requires;
+import org.broadinstitute.gatk.utils.exceptions.ReviewedGATKException;
+import org.broadinstitute.gatk.utils.exceptions.UserException;
+import org.broadinstitute.gatk.utils.variant.GATKVariantContextUtils;
+import htsjdk.variant.variantcontext.*;
+import htsjdk.variant.vcf.VCFHeader;
+
+import java.io.PrintStream;
+import java.util.*;
+
+/**
+ * A class for tabulating and evaluating a callset-by-callset genotype concordance table
+ * */
+public class ConcordanceMetrics {
+
+    final private Map<String,GenotypeConcordanceTable> perSampleGenotypeConcordance;
+    final private GenotypeConcordanceTable overallGenotypeConcordance;
+    final private SiteConcordanceTable overallSiteConcordance;
+    final PrintStream sitesFile;
+
+    public ConcordanceMetrics(VCFHeader evaluate, VCFHeader truth, PrintStream inputSitesFile) {
+        HashSet<String> overlappingSamples = new HashSet<String>(evaluate.getGenotypeSamples());
+        overlappingSamples.retainAll(truth.getGenotypeSamples());
+        perSampleGenotypeConcordance = new HashMap<String, GenotypeConcordanceTable>(overlappingSamples.size());
+        for ( String sample : overlappingSamples ) {
+            perSampleGenotypeConcordance.put(sample,new GenotypeConcordanceTable());
+        }
+        overallGenotypeConcordance = new GenotypeConcordanceTable();
+        overallSiteConcordance = new SiteConcordanceTable();
+        sitesFile = inputSitesFile;
+        if (sitesFile != null) printSitesFileHeader();
+    }
+
+    private void printSitesFileHeader() {
+        sitesFile.println("Locus\tSample\tTruth Genotype\tEval Genotype");
+    }
+
+    public GenotypeConcordanceTable getOverallGenotypeConcordance() {
+        return overallGenotypeConcordance;
+    }
+
+    public SiteConcordanceTable getOverallSiteConcordance() {
+        return overallSiteConcordance;
+    }
+
+    public GenotypeConcordanceTable getGenotypeConcordance(String sample) {
+        GenotypeConcordanceTable table = perSampleGenotypeConcordance.get(sample);
+        if ( table == null )
+            throw new ReviewedGATKException("Attempted to request the concordance table for sample "+sample+" on which it was not calculated");
+        return table;
+    }
+
+    public Map<String,GenotypeConcordanceTable> getPerSampleGenotypeConcordance() {
+        return Collections.unmodifiableMap(perSampleGenotypeConcordance);
+    }
+
+    public Map<String,Double> getPerSampleNRD() {
+        Map<String,Double> nrd = new HashMap<String,Double>(perSampleGenotypeConcordance.size());
+        for ( Map.Entry<String,GenotypeConcordanceTable> sampleTable : perSampleGenotypeConcordance.entrySet() ) {
+            nrd.put(sampleTable.getKey(),calculateNRD(sampleTable.getValue()));
+        }
+
+        return Collections.unmodifiableMap(nrd);
+    }
+
+    public Map<String,Double> getPerSampleOGC() {
+        Map<String,Double> ogc = new HashMap<String,Double>(perSampleGenotypeConcordance.size());
+        for ( Map.Entry<String,GenotypeConcordanceTable> sampleTable : perSampleGenotypeConcordance.entrySet() ) {
+            ogc.put(sampleTable.getKey(),calculateOGC(sampleTable.getValue()));
+        }
+
+        return Collections.unmodifiableMap(ogc);
+    }
+
+    public Double getOverallNRD() {
+        return calculateNRD(overallGenotypeConcordance);
+    }
+
+    public Double getOverallOGC() {
+        return calculateOGC(overallGenotypeConcordance);
+    }
+
+    public Map<String,Double> getPerSampleNRS() {
+        Map<String,Double> nrs = new HashMap<String,Double>(perSampleGenotypeConcordance.size());
+        for ( Map.Entry<String,GenotypeConcordanceTable> sampleTable : perSampleGenotypeConcordance.entrySet() ) {
+            nrs.put(sampleTable.getKey(),calculateNRS(sampleTable.getValue()));
+        }
+
+        return Collections.unmodifiableMap(nrs);
+    }
+
+    public Double getOverallNRS() {
+        return calculateNRS(overallGenotypeConcordance);
+    }
+
+    @Requires({"eval != null","truth != null"})
+    public void update(VariantContext eval, VariantContext truth) {
+        boolean doPrint = false;
+        overallSiteConcordance.update(eval,truth);
+        Set<String> alleleTruth = new HashSet<String>(8);
+        String truthRef = truth.getReference().getBaseString();
+        alleleTruth.add(truthRef);
+        for ( Allele a : truth.getAlternateAlleles() ) {
+            alleleTruth.add(a.getBaseString());
+        }
+        for ( String sample : perSampleGenotypeConcordance.keySet() ) {
+            Genotype evalGenotype = eval.getGenotype(sample);
+            Genotype truthGenotype = truth.getGenotype(sample);
+            // ensure genotypes are either no-call ("."), missing (empty alleles), or diploid
+            if ( ( ! evalGenotype.isNoCall() && evalGenotype.getPloidy() != 2 && evalGenotype.getPloidy() > 0) ||
+                 ( ! truthGenotype.isNoCall() && truthGenotype.getPloidy() != 2 && truthGenotype.getPloidy() > 0) ) {
+                throw new UserException(String.format("Concordance Metrics is currently only implemented for DIPLOID genotypes, found eval ploidy: %d, comp ploidy: %d",evalGenotype.getPloidy(),truthGenotype.getPloidy()));
+            }
+            perSampleGenotypeConcordance.get(sample).update(evalGenotype,truthGenotype,alleleTruth,truthRef);
+            doPrint = overallGenotypeConcordance.update(evalGenotype,truthGenotype,alleleTruth,truthRef);
+            if(sitesFile != null && doPrint)
+                sitesFile.println(eval.getChr() + ":" + eval.getStart() + "\t" + sample + "\t" + truthGenotype.getType() + "\t" + evalGenotype.getType());
+        }
+    }
+
+    private static double calculateNRD(GenotypeConcordanceTable table) {
+        return calculateNRD(table.getTable());
+    }
+
+    private static double calculateNRD(int[][] concordanceCounts) {
+        int correct = 0;
+        int total = 0;
+        correct += concordanceCounts[GenotypeType.HET.ordinal()][GenotypeType.HET.ordinal()];
+        correct += concordanceCounts[GenotypeType.HOM_VAR.ordinal()][GenotypeType.HOM_VAR.ordinal()];
+        total += correct;
+        total += concordanceCounts[GenotypeType.HOM_REF.ordinal()][GenotypeType.HET.ordinal()];
+        total += concordanceCounts[GenotypeType.HOM_REF.ordinal()][GenotypeType.HOM_VAR.ordinal()];
+        total += concordanceCounts[GenotypeType.HET.ordinal()][GenotypeType.HOM_REF.ordinal()];
+        total += concordanceCounts[GenotypeType.HET.ordinal()][GenotypeType.HOM_VAR.ordinal()];
+        total += concordanceCounts[GenotypeType.HOM_VAR.ordinal()][GenotypeType.HOM_REF.ordinal()];
+        total += concordanceCounts[GenotypeType.HOM_VAR.ordinal()][GenotypeType.HET.ordinal()];
+        // NRD is by definition incorrec/total = 1.0-correct/total
+        // note: if there are no observations (so the ratio is NaN), set this to 100%
+        return total == 0 ? 1.0 : 1.0 - ( (double) correct)/( (double) total);
+    }
+
+    private static double calculateOGC(int[][] concordanceCounts) {
+        int correct = 0;
+        int total = 0;
+        correct += concordanceCounts[GenotypeType.HOM_REF.ordinal()][GenotypeType.HOM_REF.ordinal()];
+        correct += concordanceCounts[GenotypeType.HET.ordinal()][GenotypeType.HET.ordinal()];
+        correct += concordanceCounts[GenotypeType.HOM_VAR.ordinal()][GenotypeType.HOM_VAR.ordinal()];
+        total += correct;
+        total += concordanceCounts[GenotypeType.HOM_REF.ordinal()][GenotypeType.HET.ordinal()];
+        total += concordanceCounts[GenotypeType.HOM_REF.ordinal()][GenotypeType.HOM_VAR.ordinal()];
+        total += concordanceCounts[GenotypeType.HET.ordinal()][GenotypeType.HOM_REF.ordinal()];
+        total += concordanceCounts[GenotypeType.HET.ordinal()][GenotypeType.HOM_VAR.ordinal()];
+        total += concordanceCounts[GenotypeType.HOM_VAR.ordinal()][GenotypeType.HOM_REF.ordinal()];
+        total += concordanceCounts[GenotypeType.HOM_VAR.ordinal()][GenotypeType.HET.ordinal()];
+        // OGC is by definition correct/total
+        // note: if there are no observations (so the ratio is NaN), set this to 100%
+        return total == 0 ? 1.0 : ( (double) correct)/( (double) total);
+    }
+
+    private static double calculateNRS(GenotypeConcordanceTable table) {
+        return calculateNRS(table.getTable());
+    }
+
+    private static double calculateOGC(GenotypeConcordanceTable table) {
+        return calculateOGC(table.getTable());
+    }
+
+    private static double calculateNRS(int[][] concordanceCounts) {
+        long confirmedVariant = 0;
+        long unconfirmedVariant = 0;
+        for ( GenotypeType truthState : Arrays.asList(GenotypeType.HET,GenotypeType.HOM_VAR) ) {
+            for ( GenotypeType evalState : GenotypeType.values() ) {
+                if ( evalState == GenotypeType.MIXED )
+                    continue;
+                if ( evalState.equals(GenotypeType.HET) || evalState.equals(GenotypeType.HOM_VAR) )
+                    confirmedVariant += concordanceCounts[evalState.ordinal()][truthState.ordinal()];
+                else
+                    unconfirmedVariant += concordanceCounts[evalState.ordinal()][truthState.ordinal()];
+            }
+        }
+
+        long total = confirmedVariant + unconfirmedVariant;
+        // note: if there are no observations (so the ratio is NaN) set this to 0%
+        return total == 0l ? 0.0 : ( (double) confirmedVariant ) / ( (double) ( total ) );
+    }
+
+
+    class GenotypeConcordanceTable {
+
+        private int[][] genotypeCounts;
+        private int nMismatchingAlt;
+
+        public GenotypeConcordanceTable() {
+            genotypeCounts = new int[GenotypeType.values().length][GenotypeType.values().length];
+            nMismatchingAlt = 0;
+        }
+
+        @Requires({"eval!=null","truth != null","truthAlleles != null"})
+        public Boolean update(Genotype eval, Genotype truth, Set<String> truthAlleles, String truthRef) {
+            // this is slow but correct.
+
+            // NOTE: a reference call in "truth" is a special case, the eval can match *any* of the truth alleles
+            // that is, if the reference base is C, and a sample is C/C in truth, A/C, A/A, T/C, T/T will
+            // all match, so long as A and T are alleles in the truth callset.
+            boolean matchingAlt = true;
+            int evalGT, truthGT;
+            if ( eval.isCalled() && truth.isCalled() && truth.isHomRef() ) {
+                // by default, no-calls "match" between alleles, so if
+                // one or both sites are no-call or unavailable, the alt alleles match
+                // otherwise, check explicitly: if the eval has an allele that's not ref, no-call, or present in truth
+                // the alt allele is mismatching - regardless of whether the genotype is correct.
+                for ( Allele evalAllele : eval.getAlleles() ) {
+                    matchingAlt &= truthAlleles.contains(evalAllele.getBaseString());
+                }
+            } else if ( eval.isCalled() && truth.isCalled() ) {
+                // otherwise, the eval genotype has to match either the alleles in the truth genotype, or the truth reference allele
+                // todo -- this can be sped up by caching the truth allele sets
+                Set<String> genoAlleles = new HashSet<String>(3);
+                genoAlleles.add(truthRef);
+                for ( Allele truthGenoAl : truth.getAlleles() ) {
+                    genoAlleles.add(truthGenoAl.getBaseString());
+                }
+                for ( Allele evalAllele : eval.getAlleles() ) {
+                    matchingAlt &= genoAlleles.contains(evalAllele.getBaseString());
+                }
+            }
+
+            if ( matchingAlt ) {
+                evalGT = eval.getType().ordinal();
+                truthGT = truth.getType().ordinal();
+                genotypeCounts[evalGT][truthGT]++;
+                if(evalGT != truthGT)  //report variants where genotypes don't match
+                    return true;
+            } else {
+                nMismatchingAlt++;
+                return false;
+                //return true; //alternatively, report variants where alt alleles don't match
+            }
+            return false;
+        }
+
+        public int[][] getTable() {
+            return genotypeCounts;
+        }
+
+        public int getnMismatchingAlt() {
+            return nMismatchingAlt;
+        }
+
+        public int getnEvalGenotypes(GenotypeType type) {
+            int nGeno = 0;
+            for ( GenotypeType comptype : GenotypeType.values() )
+                nGeno += genotypeCounts[type.ordinal()][comptype.ordinal()];
+            return nGeno;
+        }
+
+        public int getnCalledEvalGenotypes() {
+            int nGeno = 0;
+            for ( GenotypeType evalType : Arrays.asList(GenotypeType.HOM_REF,GenotypeType.HOM_VAR,GenotypeType.HET) ) {
+                nGeno += getnEvalGenotypes(evalType);
+            }
+
+            return nGeno + nMismatchingAlt;
+        }
+
+        public int getnCompGenotypes(GenotypeType type) {
+            int nGeno = 0;
+            for ( GenotypeType evaltype : GenotypeType.values() )
+                nGeno += genotypeCounts[evaltype.ordinal()][type.ordinal()];
+            return nGeno;
+        }
+
+        public int getnCalledCompGenotypes() {
+            int nGeno = 0;
+            for ( GenotypeType compType : Arrays.asList(GenotypeType.HOM_REF,GenotypeType.HOM_VAR,GenotypeType.HET) ) {
+                nGeno += getnCompGenotypes(compType);
+            }
+            return nGeno;
+        }
+
+        public int get(GenotypeType evalType, GenotypeType compType) {
+            return genotypeCounts[evalType.ordinal()][compType.ordinal()];
+        }
+    }
+
+    class SiteConcordanceTable {
+
+        private int[] siteConcordance;
+
+        public SiteConcordanceTable() {
+            siteConcordance = new int[SiteConcordanceType.values().length];
+        }
+
+        public void update(VariantContext evalVC, VariantContext truthVC) {
+            SiteConcordanceType matchType = getMatchType(evalVC,truthVC);
+            siteConcordance[matchType.ordinal()]++;
+        }
+
+        @Requires({"evalVC != null","truthVC != null"})
+        private SiteConcordanceType getMatchType(VariantContext evalVC, VariantContext truthVC) {
+            return SiteConcordanceType.getConcordanceType(evalVC,truthVC);
+        }
+
+        public int[] getSiteConcordance() {
+            return siteConcordance;
+        }
+
+        public int get(SiteConcordanceType type) {
+            return getSiteConcordance()[type.ordinal()];
+        }
+    }
+
+    enum SiteConcordanceType {
+        ALLELES_MATCH,
+        EVAL_SUPERSET_TRUTH,
+        EVAL_SUBSET_TRUTH,
+        ALLELES_DO_NOT_MATCH,
+        EVAL_ONLY,
+        TRUTH_ONLY;
+
+        public static SiteConcordanceType getConcordanceType(VariantContext eval, VariantContext truth) {
+            if ( eval.isMonomorphicInSamples() )
+                return TRUTH_ONLY;
+            if ( truth.isMonomorphicInSamples() )
+                return EVAL_ONLY;
+
+            boolean evalSubsetTruth = GATKVariantContextUtils.allelesAreSubset(eval, truth);
+            boolean truthSubsetEval = GATKVariantContextUtils.allelesAreSubset(truth, eval);
+
+            if ( evalSubsetTruth && truthSubsetEval )
+                return ALLELES_MATCH;
+
+            if ( evalSubsetTruth )
+                return EVAL_SUBSET_TRUTH;
+
+            if ( truthSubsetEval )
+                return EVAL_SUPERSET_TRUTH;
+
+            return ALLELES_DO_NOT_MATCH;
+        }
+    }
+}
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/tools/walkers/variantutils/FilterLiftedVariants.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/tools/walkers/variantutils/FilterLiftedVariants.java
new file mode 100644
index 0000000..73995bf
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/tools/walkers/variantutils/FilterLiftedVariants.java
@@ -0,0 +1,136 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.tools.walkers.variantutils;
+
+import org.broadinstitute.gatk.engine.walkers.Reference;
+import org.broadinstitute.gatk.engine.walkers.RodWalker;
+import org.broadinstitute.gatk.engine.walkers.Window;
+import org.broadinstitute.gatk.utils.commandline.ArgumentCollection;
+import org.broadinstitute.gatk.utils.commandline.Output;
+import org.broadinstitute.gatk.engine.CommandLineGATK;
+import org.broadinstitute.gatk.engine.arguments.StandardVariantContextInputArgumentCollection;
+import org.broadinstitute.gatk.engine.contexts.AlignmentContext;
+import org.broadinstitute.gatk.engine.contexts.ReferenceContext;
+import org.broadinstitute.gatk.engine.refdata.RefMetaDataTracker;
+import org.broadinstitute.gatk.utils.SampleUtils;
+import org.broadinstitute.gatk.utils.help.HelpConstants;
+import htsjdk.variant.vcf.VCFHeader;
+import htsjdk.variant.vcf.VCFHeaderLine;
+import org.broadinstitute.gatk.utils.variant.GATKVCFUtils;
+import org.broadinstitute.gatk.utils.help.DocumentedGATKFeature;
+import htsjdk.variant.variantcontext.writer.VariantContextWriter;
+import htsjdk.variant.variantcontext.VariantContext;
+
+import java.util.*;
+
+/**
+ * Filters a lifted-over VCF file for ref bases that have been changed.
+ *
+ * "Lifting over" variants means adjusting variant calls from one reference to another. Specifically, the process adjusts the position of the call to match the corresponding position on the target reference.
+ * For example, if you have variants called from reads aligned to the hg19 reference, and you want to compare them to calls made based on the b37 reference, you need to liftover one of the callsets to the other reference.
+ *
+ * FilteredLiftedVariants is intended to be the second of two processing steps for the liftover process. The first step is to run LiftoverVariants on your VCF file.
+ * The second step is to run FilterLiftedVariants on the output of LiftoverVariants. This will produce valid well-behaved VCF files, where you'll see that the contig names in the header have all been correctly replaced.
+ *
+ */
+ at DocumentedGATKFeature( groupName = HelpConstants.DOCS_CAT_VARMANIP, extraDocs = {CommandLineGATK.class} )
+ at Reference(window=@Window(start=0,stop=100))
+public class FilterLiftedVariants extends RodWalker<Integer, Integer> {
+
+    @ArgumentCollection
+    protected StandardVariantContextInputArgumentCollection variantCollection = new StandardVariantContextInputArgumentCollection();
+
+    private static final int MAX_VARIANT_SIZE = 100;
+
+    @Output(doc="File to which variants should be written")
+    protected VariantContextWriter writer = null;
+
+    private long failedLocs = 0, totalLocs = 0;
+
+    public void initialize() {
+        String trackName = variantCollection.variants.getName();
+        Set<String> samples = SampleUtils.getSampleListWithVCFHeader(getToolkit(), Arrays.asList(trackName));
+        Map<String, VCFHeader> vcfHeaders = GATKVCFUtils.getVCFHeadersFromRods(getToolkit(), Arrays.asList(trackName));
+
+        final VCFHeader vcfHeader = new VCFHeader(vcfHeaders.containsKey(trackName) ? vcfHeaders.get(trackName).getMetaDataInSortedOrder() : Collections.<VCFHeaderLine>emptySet(), samples);
+        writer.writeHeader(vcfHeader);
+    }
+
+    /**
+     * Determines whether records should be filtered; if not, writes them to the output
+     *
+     * @param ref   the reference context
+     * @param vc    the VariantContext to process
+     * @return true if the record is not filtered, false otherwise
+     */
+    protected boolean filterOrWrite(final byte[] ref, final VariantContext vc) {
+	if ( ref == null ) throw new IllegalArgumentException("Cannot filter based on a null reference array");
+	if ( vc == null ) throw new IllegalArgumentException("Cannot filter a null Variant Context");
+
+        totalLocs++;
+
+        boolean filter = false;
+        final byte[] recordRef = vc.getReference().getBases();
+
+        // this can happen for records that get placed at the ends of chromosomes
+        if ( recordRef.length > ref.length ) {
+            filter = true;
+        } else {
+            for (int i = 0; i < recordRef.length && i < MAX_VARIANT_SIZE; i++) {
+                if ( recordRef[i] != ref[i] ) {
+                    filter = true;
+                    break;
+                }
+            }
+        }
+
+        if ( filter )
+            failedLocs++;
+        else
+            writer.add(vc);
+
+        return !filter;
+    }
+
+    public Integer map(RefMetaDataTracker tracker, ReferenceContext ref, AlignmentContext context) {
+        if ( tracker == null )
+            return 0;
+
+        final Collection<VariantContext> VCs = tracker.getValues(variantCollection.variants, context.getLocation());
+        for ( final VariantContext vc : VCs )
+            filterOrWrite(ref.getBases(), vc);
+
+        return 0;
+    }
+
+    public Integer reduceInit() { return 0; }
+
+    public Integer reduce(Integer value, Integer sum) { return 0; }
+
+    public void onTraversalDone(Integer result) {
+        System.out.println("Filtered " + failedLocs + " records out of " + totalLocs + " total records.");
+    }
+}
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/tools/walkers/variantutils/GenotypeConcordance.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/tools/walkers/variantutils/GenotypeConcordance.java
new file mode 100644
index 0000000..d2f251a
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/tools/walkers/variantutils/GenotypeConcordance.java
@@ -0,0 +1,675 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.tools.walkers.variantutils;
+
+import org.broadinstitute.gatk.utils.commandline.*;
+import org.broadinstitute.gatk.engine.CommandLineGATK;
+import org.broadinstitute.gatk.engine.contexts.AlignmentContext;
+import org.broadinstitute.gatk.engine.contexts.ReferenceContext;
+import org.broadinstitute.gatk.engine.refdata.RefMetaDataTracker;
+import org.broadinstitute.gatk.engine.report.GATKReport;
+import org.broadinstitute.gatk.engine.report.GATKReportTable;
+import org.broadinstitute.gatk.engine.walkers.RodWalker;
+import org.broadinstitute.gatk.utils.collections.Pair;
+import org.broadinstitute.gatk.utils.help.DocumentedGATKFeature;
+import org.broadinstitute.gatk.utils.help.HelpConstants;
+import org.broadinstitute.gatk.utils.variant.GATKVCFUtils;
+import htsjdk.variant.variantcontext.*;
+import htsjdk.variant.vcf.VCFHeader;
+
+import java.io.PrintStream;
+import java.util.*;
+
+/**
+ * Genotype concordance (per-sample and aggregate counts and frequencies, NRD/NRS and site allele overlaps) between two callsets
+ *
+ * <p>
+ *  GenotypeConcordance takes in two callsets (vcfs) and tabulates the number of sites which overlap and share alleles,
+ *  and for each sample, the genotype-by-genotype counts (e.g. the number of sites at which a sample was
+ *  called homozygous-reference in the EVAL callset, but homozygous-variant in the COMP callset). It outputs these
+ *  counts as well as convenient proportions (such as the proportion of het calls in the EVAL which were called REF in
+ *  the COMP) and metrics (such as NRD and NRS).
+ *  </p>
+ *
+ *  <h3>Input</h3>
+ *  <p>
+ *  Genotype concordance requires two callsets (as it does a comparison): an EVAL and a COMP callset, specified via
+ *  the -eval and -comp arguments. Typically, the EVAL callset is an experimental set you want to evaluate, while the
+ *  COMP callset is a previously existing set used as a standard for comparison (taken to represent "truth").
+ *  </p>
+ *  <p>
+ *  (Optional) Jexl expressions for genotype-level filtering of EVAL or COMP genotypes, specified via the -gfe and
+ *  -cfe arguments, respectively.
+ *  </p>
+ *
+ *  <h3>Output</h3>
+ *  <p>
+ *  Genotype Concordance writes a GATK report to the specified file (via -o), consisting of multiple tables of counts
+ *  and proportions. These tables are constructed on a per-sample basis, and include counts of EVAL vs COMP genotype
+ *  states.
+ *  </p>
+ *  <h4>Tables</h4>
+ *  <p>
+ *  Headers for the (non-moltenized -- see below) GenotypeConcordance counts and proportions tables give the genotype of
+ *  the COMP callset followed by the genotype of the EVAL callset. For example the value corresponding to HOM_REF_HET
+ *  reflects variants called HOM_REF in the COMP callset and HET in the EVAL callset. Variants for which the alternate
+ *  alleles between the EVAL and COMP sample did not match are excluded from genotype comparisons and given in the
+ *  "Mismatching_Alleles" field.
+ *  </p>
+ *  <p>
+ *  It may be informative to reshape rows of the GenotypeConcordance counts and proportions tables into separate row-major tables
+ *  where the columns indicate the COMP genotype and the rows indicate the EVAL genotype for easy comparison between the
+ *  two callsets. This can be done with a command similar to d <- matrix(sampleRow,nrow=6,byrow=T) in R where sampleRow is the 36-value row corresponding to the sample of interest, excluding "Mismatching_Alleles".
+ *  In Excel this can be accomplished using the OFFSET function.
+ *  </p>
+ *  <ul>
+ *      <li><i>GenotypeConcordance_CompProportions</i>: Gives the proportion of variants in each category normalized to the total number of called genotypes in the COMP callset</li>
+ *      <li><i>GenotypeConcordance_Counts</i>: Gives the counts for number of genotypes in each category</li>
+ *      <li><i>GenotypeConcordance_EvalProportions</i>: Gives the proportion of genotypes in each category normalized to the total number of called genotypes in the EVAL callset</li>
+ *      <li><i>GenotypeConcordance_Summary</i>: Summary statistics for the sum of all samples and each sample individually. See below for definitions.</li>
+ *      <li><i>SiteConcordance_Summary</i>: Gives comparison counts of called genotypes and their alleles between the two callsets. See below for definitions.</li>
+ *  </ul>
+ *  </p>
+ *
+ *  <h4>Term and metrics definitions</h4>
+ * <p>
+ * <ul>
+ *          <li><i>GenotypeConcordance_CompProportions</i>, <i>GenotypeConcordance_Counts</i>, and <i>GenotypeConcordance_EvalProportions</i></li>
+ *          <ul>
+ *               <li>NO_CALL: reported genotype is ./., indicating not enough data to call</li>
+ *               <li>HET: heterozygous</li>
+ *               <li>HOM_REF: homozygous reference</li>
+ *               <li>HOM_VAR: homozygous variant</li>
+ *               <li>UNAVAILABLE: variant is not called in this callset</li>
+ *               <li>MIXED: something like ./1</li>
+ *          </ul>
+ *          <li><i>GenotypeConcordance_Summary</i></li>
+ *          <ul>
+ *               <li>Non-Reference_Sensitivity (NRS): sensitivity of the EVAL calls to polymorphic calls in the COMP set, calculated by (# true positive)/(# true polymorphic)</li>
+ *               <li>Non-Reference_Discrepancy (NRD): genotype discordance excluding concordant reference sites, calculated by (# discordant sites)/(total excluding # HOM_REF_HOM_REF) = 1.0-(# HOM_VAR_HOM_VAR + # HET_HET)/(total excluding # HOM_REF_HOM_REF)</li>
+ *               <li>Overall_Genotype_Concordance: overall concordance calculated by (# concordant genotypes)/(# genotypes)</li>
+ *          </ul>
+ *          <li><i>SiteConcordance_Summary</i></li>
+ *          <ul>
+ *               <li>ALLELES_MATCH: counts of calls at the same site where the alleles match</li>
+ *               <li>ALLELES_DO_NOT_MATCH: counts of calls at the same location with different alleles, such as the EVAL set calling a 'G' alternate allele, and the comp set calling a 'T' alternate allele</li>
+ *               <li>EVAL_SUBSET_TRUTH: (multi-alleleic sites only) ALT alleles for EVAL are a subset of ALT alleles for COMP. See also below.</li>
+ *               <li>EVAL_SUPERSET_TRUTH: (multi-allelic sites only) ALT alleles for COMP are a subset of ALT alleles for EVAL. See also below.</li>
+ *               <li>EVAL_ONLY: counts of sites present only in the EVAL set, not in the COMP set</li>
+ *               <li>TRUTH_ONLY: counts of sites present only in the COMP set, not in the EVAL set</li>
+ *          </ul>
+ * </ul>
+ * </p>
+ *
+ * <h4>Site-level allelic concordance</h4>
+ *
+ * <p>
+ *  For strictly bi-allelic VCFs, only the ALLELES_MATCH, EVAL_ONLY, TRUTH_ONLY fields will be populated,
+ *  but where multi-allelic sites are involved counts for EVAL_SUBSET_TRUTH and EVAL_SUPERSET_TRUTH will be generated.
+ * </p>
+ * <p>
+ *  For example, in the following situation
+ *  <pre>
+ *    eval:  ref - A   alt - C
+ *    comp:  ref - A   alt - C,T
+ *  </pre>
+ *  then the site is tabulated as EVAL_SUBSET_TRUTH. Were the situation reversed, it would be EVAL_SUPERSET_TRUTH.
+ *  However, in the case where EVAL has both C and T alternate alleles, both must be observed in the genotypes
+ *  (that is, there must be at least one of (0/1,1/1) and at least one of (0/2,1/2,2/2) in the genotype field). If
+ *  one of the alleles has no observations in the genotype fields of the EVAL, the site-level concordance is
+ *  tabulated as though that allele were not present in the record.
+ * </p>
+ *
+ *  <h4>Monomorphic Records</h4>
+ *  <p>
+ *  A site which has an alternate allele, but which is monomorphic in samples, is treated as not having been
+ *  discovered, and will be recorded in the TRUTH_ONLY column (if a record exists in the COMP set), or not at all
+ *  (if no record exists in the COMP set).
+ *  </p>
+ *  <p>
+ *  That is, in the situation
+ *  <pre>
+ *   eval:  ref - A   alt - C   genotypes - 0/0  0/0  0/0 ... 0/0
+ *   comp:  ref - A   alt - C   ...         0/0  0/0  ...
+ *  </pre>
+ *  is equivalent to
+ *  <pre>
+ *   eval:  ref - A   alt - .   genotypes - 0/0  0/0  0/0 ... 0/0
+ *   comp:  ref - A   alt - C   ...         0/0  0/0  ...
+ *  </pre>
+ *  </p>
+ *  <p>
+ *  When a record is present in the COMP set the *genotypes* for the monomorphic site will still be used to evaluate
+ *  per-sample genotype concordance counts.
+ * </p>
+ *
+ *  <h4>Filtered Records</h4>
+ *  Filtered records are treated as though they were not present in the VCF, unless -ignoreSiteFilters is provided,
+ *  in which case all records are used. There is currently no way to assess concordance metrics on filtered sites
+ *  exclusively. SelectVariants can be used to extract filtered sites, and VariantFiltration used to un-filter them.
+ *
+ * <h4>Moltenized tables</h4>
+ *
+ * <p>These tables may be optionally moltenized via the -moltenize argument. That is, the standard table
+ *
+ *  <pre>
+ *  Sample   NO_CALL_HOM_REF  NO_CALL_HET  NO_CALL_HOM_VAR   (...)
+ *  NA12878       0.003        0.001            0.000        (...)
+ *  NA12891       0.005        0.000            0.000        (...)
+ *  </pre>
+ *
+ *  would instead be displayed
+ *
+ * <pre>
+ *  NA12878  NO_CALL_HOM_REF   0.003
+ *  NA12878  NO_CALL_HET       0.001
+ *  NA12878  NO_CALL_HOM_VAR   0.000
+ *  NA12891  NO_CALL_HOM_REF   0.005
+ *  NA12891  NO_CALL_HET       0.000
+ *  NA12891  NO_CALL_HOM_VAR   0.000
+ *  (...)
+ *  </pre>
+
+ */
+ at DocumentedGATKFeature( groupName = HelpConstants.DOCS_CAT_VARMANIP, extraDocs = {CommandLineGATK.class} )
+public class GenotypeConcordance extends RodWalker<List<Pair<VariantContext,VariantContext>>,ConcordanceMetrics> {
+
+    /**
+     * The callset you want to evaluate, typically this is where you'd put 'unassessed' callsets.
+     */
+    @Input(fullName="eval",shortName="eval",doc="The variants and genotypes to evaluate",required=true)
+    RodBinding<VariantContext> evalBinding;
+
+    /**
+     * The callset you want to treat as 'truth'. Can also be of unknown quality for the sake of callset comparisons.
+     */
+    @Input(fullName="comp",shortName="comp",doc="The variants and genotypes to compare against",required=true)
+    RodBinding<VariantContext> compBinding;
+
+    /**
+     * The FILTER field of the eval and comp VCFs will be ignored. If this flag is not included, all FILTER sites will
+     * be treated as not being present in the VCF. (That is, the genotypes will be assigned UNAVAILABLE, as distinct
+     * from NO_CALL).
+     */
+    @Argument(fullName="ignoreFilters",doc="Filters will be ignored",required=false)
+    boolean ignoreFilters = false;
+
+    /**
+     * A genotype level JEXL expression to apply to eval genotypes. Genotypes filtered in this way will be replaced by NO_CALL.
+     * For instance: -gfe 'GQ<20' will set to no-call any genotype with genotype quality less than 20.
+     */
+    @Argument(shortName="gfe", fullName="genotypeFilterExpressionEval", doc="One or more criteria to use to set EVAL genotypes to no-call. "+
+            "These genotype-level filters are only applied to the EVAL rod.", required=false)
+    public ArrayList<String> genotypeFilterExpressionsEval = new ArrayList<String>();
+
+    /**
+     * Identical to -gfe except the filter is applied to genotypes in the comp rod.
+     */
+    @Argument(shortName="gfc", fullName="genotypeFilterExpressionComp", doc="One or more criteria to use to set COMP genotypes to no-call. "+
+            "These genotype-level filters are only applied to the COMP rod.", required=false)
+    public ArrayList<String> genotypeFilterExpressionsComp = new ArrayList<String>();
+
+    /**
+     * Moltenize the count and proportion tables. Rather than moltenizing per-sample data into a 2x2 table, it is fully
+     * moltenized into elements. That is, WITHOUT this argument, each row of the table begins with the sample name and
+     * proceeds directly with counts/proportions of eval/comp counts (for instance HOM_REF/HOM_REF, HOM_REF/NO_CALL).
+     *
+     * If the Moltenize argument is given, the output will begin with a sample name, followed by the contrastive genotype
+     * type (such as HOM_REF/HOM_REF), followed by the count or proportion. This will significantly increase the number of
+     * rows.
+     */
+    @Argument(shortName="moltenize",fullName="moltenize",doc="Molten rather than tabular output")
+    public boolean moltenize = false;
+
+    /**
+     * Print sites where genotypes are mismatched between callsets along with annotations giving the genotype of each callset
+     * to the given filename
+     *
+     */
+
+    @Argument(shortName = "sites",required = false,fullName = "printInterestingSites", doc="File to output the discordant sites and genotypes.")
+    private PrintStream sitesFile = null;
+
+    @Output
+    PrintStream out;
+
+    private List<String> evalSamples;
+    private List<String> compSamples;
+    private List<VariantContextUtils.JexlVCMatchExp> evalJexls = null;
+    private List<VariantContextUtils.JexlVCMatchExp> compJexls = null;
+
+    // todo -- table with "proportion of overlapping sites" (not just eval/comp margins) [e.g. drop no-calls]
+    //  (this will break all the integration tests of course, due to new formatting)
+
+    public void initialize() {
+        evalJexls = initializeJexl(genotypeFilterExpressionsEval);
+        compJexls = initializeJexl(genotypeFilterExpressionsComp);
+    }
+
+    private List<VariantContextUtils.JexlVCMatchExp> initializeJexl(ArrayList<String> genotypeFilterExpressions) {
+        ArrayList<String> dummyNames = new ArrayList<String>(genotypeFilterExpressions.size());
+        int expCount = 1;
+        for ( String exp : genotypeFilterExpressions ) {
+            dummyNames.add(String.format("gfe%d",expCount++));
+        }
+        return VariantContextUtils.initializeMatchExps(dummyNames, genotypeFilterExpressions);
+    }
+
+    public ConcordanceMetrics reduceInit() {
+        Map<String,VCFHeader> headerMap = GATKVCFUtils.getVCFHeadersFromRods(getToolkit(), Arrays.asList(evalBinding,compBinding));
+        VCFHeader evalHeader = headerMap.get(evalBinding.getName());
+        evalSamples = evalHeader.getGenotypeSamples();
+        VCFHeader compHeader = headerMap.get(compBinding.getName());
+        compSamples = compHeader.getGenotypeSamples();
+        return new ConcordanceMetrics(evalHeader,compHeader, sitesFile);
+    }
+
+
+    public List<Pair<VariantContext,VariantContext>> map(RefMetaDataTracker tracker, ReferenceContext ref, AlignmentContext context) {
+        List<Pair<VariantContext,VariantContext>> evalCompPair = new ArrayList<Pair<VariantContext,VariantContext>>(3);
+        if ( tracker != null && (
+                tracker.getValues(evalBinding,ref.getLocus()).size() > 0 ||
+                        tracker.getValues(compBinding,ref.getLocus()).size() > 0 ) ) {
+
+            List<VariantContext> eval = tracker.getValues(evalBinding,ref.getLocus());
+            List<VariantContext> comp = tracker.getValues(compBinding,ref.getLocus());
+            if ( eval.size() > 1 || comp.size() > 1 ) {
+                if ( noDuplicateTypes(eval) && noDuplicateTypes(comp) ) {
+                    logger.info("Eval or Comp Rod at position " + ref.getLocus().toString() + " has multiple records. Resolving.");
+                    evalCompPair = resolveMultipleRecords(eval,comp);
+                } else {
+                    logger.warn("Eval or Comp Rod at position "+ref.getLocus().toString()+" has multiple records of the same type. This locus will be skipped.");
+                }
+            } else {
+                // if a rod is missing, explicitly create a variant context with 'missing' genotypes. Slow, but correct.
+                // note that if there is no eval rod there must be a comp rod, and also the reverse
+                VariantContext evalContext = eval.size() == 1 ? eval.get(0) : createEmptyContext(comp.get(0),evalSamples);
+                VariantContext compContext = comp.size() == 1 ? comp.get(0) : createEmptyContext(eval.get(0),compSamples);
+                evalContext = filterGenotypes(evalContext,ignoreFilters,evalJexls);
+                compContext = filterGenotypes(compContext,ignoreFilters,compJexls);
+                evalCompPair.add(new Pair<VariantContext, VariantContext>(evalContext,compContext));
+            }
+        }
+
+        return evalCompPair;
+    }
+
+    private boolean noDuplicateTypes(List<VariantContext> vcList) {
+        HashSet<VariantContext.Type> types = new HashSet<VariantContext.Type>(vcList.size());
+        for ( VariantContext vc : vcList ) {
+            VariantContext.Type type = vc.getType();
+            if ( types.contains(type) )
+                return false;
+            types.add(type);
+        }
+
+        return true;
+    }
+
+    /**
+     * The point of this method is to match up pairs of evals and comps by their type (or alternate alleles for mixed).
+     * Basically multiple records could exist for a site such as:
+     * Eval: 20   4000     A     C
+     * Eval: 20   4000     A    AC
+     * Comp: 20   4000     A     C
+     * So for each eval, loop through the comps. If the types match, or for mixed types if eval alleles (non-emptily)
+     * intersect the comp alleles, pair them up and remove that comp records.
+     * Continue until we're out of evals or comps. This is n^2, but should rarely actually happen.
+     *
+     * The remaining unpaired records get paird with an empty contexts. So in the example above we'd get a list of:
+     *  1 - (20,4000,A/C  |  20,4000,A/C)
+     *  2 - (20,4000,A/AC |    Empty    )
+     * @param evalList - list of eval variant contexts
+     * @param compList - list of comp variant contexts
+     * @return resolved pairs of the input lists
+     */
+    private List<Pair<VariantContext,VariantContext>> resolveMultipleRecords(List<VariantContext> evalList, List<VariantContext> compList) {
+        List<Pair<VariantContext,VariantContext>> resolvedPairs = new ArrayList<Pair<VariantContext,VariantContext>>(evalList.size()+compList.size()); // oversized but w/e
+        List<VariantContext> pairedEval = new ArrayList<VariantContext>(evalList.size());
+        for ( VariantContext eval : evalList ) {
+            VariantContext.Type evalType = eval.getType();
+            Set<Allele> evalAlleles = new HashSet<Allele>(eval.getAlternateAlleles());
+            VariantContext pairedComp = null;
+            for ( VariantContext comp : compList ) {
+                if ( evalType.equals(comp.getType()) ) {
+                    pairedComp = comp;
+                    break;
+                } else if ( eval.isMixed() || comp.isMixed() ) {
+                    for ( Allele compAllele : comp.getAlternateAlleles() ) {
+                        if ( evalAlleles.contains(compAllele) ) {
+                            pairedComp = comp;
+                            break;
+                        }
+                    }
+                }
+            }
+            if ( pairedComp != null ) {
+                compList.remove(pairedComp);
+                resolvedPairs.add(new Pair<VariantContext, VariantContext>(filterGenotypes(eval,ignoreFilters,evalJexls),filterGenotypes(pairedComp,ignoreFilters,compJexls)));
+                pairedEval.add(eval);
+                if ( compList.size() < 1 )
+                    break;
+            }
+        }
+        evalList.removeAll(pairedEval);
+        for ( VariantContext unpairedEval : evalList ) {
+            resolvedPairs.add(new Pair<VariantContext, VariantContext>(filterGenotypes(unpairedEval,ignoreFilters,evalJexls),createEmptyContext(unpairedEval,compSamples)));
+        }
+
+        for ( VariantContext unpairedComp : compList ) {
+            resolvedPairs.add(new Pair<VariantContext, VariantContext>(createEmptyContext(unpairedComp,evalSamples),filterGenotypes(unpairedComp,ignoreFilters,compJexls)));
+        }
+
+        return resolvedPairs;
+    }
+
+    public ConcordanceMetrics reduce(List<Pair<VariantContext,VariantContext>> evalCompList, ConcordanceMetrics metrics) {
+        for ( Pair<VariantContext,VariantContext> evalComp : evalCompList){
+            metrics.update(evalComp.getFirst(),evalComp.getSecond());
+
+        }
+        return metrics;
+    }
+
+    private static double repairNaN(double d) {
+     if ( Double.isNaN(d) ) {
+      return 0.0;
+     }
+     return d;
+    }
+
+    public void onTraversalDone(ConcordanceMetrics metrics) {
+        // todo -- this is over 200 lines of code just to format the output and could use some serious cleanup
+        GATKReport report = new GATKReport();
+        GATKReportTable concordanceCounts = new GATKReportTable("GenotypeConcordance_Counts","Per-sample concordance tables: comparison counts",2+GenotypeType.values().length*GenotypeType.values().length);
+        GATKReportTable concordanceEvalProportions = new GATKReportTable("GenotypeConcordance_EvalProportions", "Per-sample concordance tables: proportions of genotypes called in eval",2+GenotypeType.values().length*GenotypeType.values().length);
+        GATKReportTable concordanceCompProportions = new GATKReportTable("GenotypeConcordance_CompProportions", "Per-sample concordance tables: proportions of genotypes called in comp",2+GenotypeType.values().length*GenotypeType.values().length);
+        GATKReportTable concordanceSummary = new GATKReportTable("GenotypeConcordance_Summary","Per-sample summary statistics: NRS, NRD, and OGC",2);
+        GATKReportTable siteConcordance = new GATKReportTable("SiteConcordance_Summary","Site-level summary statistics",ConcordanceMetrics.SiteConcordanceType.values().length);
+        if ( moltenize ) {
+            concordanceCompProportions.addColumn("Sample","%s");
+            concordanceCounts.addColumn("Sample","%s");
+            concordanceEvalProportions.addColumn("Sample","%s");
+            concordanceSummary.addColumn("Sample","%s");
+
+            concordanceCompProportions.addColumn("Eval_Genotype","%s");
+            concordanceCounts.addColumn("Eval_Genotype","%s");
+            concordanceEvalProportions.addColumn("Eval_Genotype","%s");
+            concordanceSummary.addColumn("Non-Reference_Discrepancy","%.3f");
+
+            concordanceCompProportions.addColumn("Comp_Genotype","%s");
+            concordanceCounts.addColumn("Comp_Genotype","%s");
+            concordanceEvalProportions.addColumn("Comp_Genotype","%s");
+            concordanceSummary.addColumn("Non-Reference_Sensitivity","%.3f");
+
+            concordanceCompProportions.addColumn("Proportion","%.3f");
+            concordanceCounts.addColumn("Count","%d");
+            concordanceEvalProportions.addColumn("Proportion","%.3f");
+            concordanceSummary.addColumn("Overall_Genotype_Concordance","%.3f");
+
+            for ( Map.Entry<String,ConcordanceMetrics.GenotypeConcordanceTable> entry : metrics.getPerSampleGenotypeConcordance().entrySet() ) {
+                ConcordanceMetrics.GenotypeConcordanceTable table = entry.getValue();
+                for ( GenotypeType evalType : GenotypeType.values() ) {
+                    for ( GenotypeType compType : GenotypeType.values() ) {
+                        String rowKey = String.format("%s_%s_%s",entry.getKey(),evalType.toString(),compType.toString());
+                        concordanceCounts.set(rowKey,"Sample",entry.getKey());
+                        concordanceCounts.set(rowKey,"Eval_Genotype",evalType.toString());
+                        concordanceCounts.set(rowKey,"Comp_Genotype",compType.toString());
+                        int count = table.get(evalType, compType);
+                        concordanceCounts.set(rowKey,"Count",count);
+                        if ( evalType == GenotypeType.HET || evalType == GenotypeType.HOM_REF || evalType == GenotypeType.HOM_VAR) {
+                            concordanceEvalProportions.set(rowKey,"Sample",entry.getKey());
+                            concordanceEvalProportions.set(rowKey,"Eval_Genotype",evalType.toString());
+                            concordanceEvalProportions.set(rowKey,"Comp_Genotype",compType.toString());
+                            concordanceEvalProportions.set(rowKey,"Proportion",repairNaN(( (double) count)/table.getnEvalGenotypes(evalType)));
+                        }
+                        if ( compType == GenotypeType.HET || compType == GenotypeType.HOM_VAR || compType == GenotypeType.HOM_REF ) {
+                            concordanceCompProportions.set(rowKey,"Sample",entry.getKey());
+                            concordanceCompProportions.set(rowKey,"Eval_Genotype",evalType.toString());
+                            concordanceCompProportions.set(rowKey,"Comp_Genotype",compType.toString());
+                            concordanceCompProportions.set(rowKey,"Proportion",repairNaN(( (double) count)/table.getnCompGenotypes(compType)));
+                        }
+                    }
+                }
+                String mismatchKey = String.format("%s_%s",entry.getKey(),"Mismatching");
+                concordanceCounts.set(mismatchKey,"Sample",entry.getKey());
+                concordanceCounts.set(mismatchKey,"Eval_Genotype","Mismatching_Alleles");
+                concordanceCounts.set(mismatchKey,"Comp_Genotype","Mismatching_Alleles");
+                concordanceEvalProportions.set(mismatchKey,"Sample",entry.getKey());
+                concordanceEvalProportions.set(mismatchKey,"Eval_Genotype","Mismatching_Alleles");
+                concordanceEvalProportions.set(mismatchKey,"Comp_Genotype","Mismatching_Alleles");
+                concordanceCompProportions.set(mismatchKey,"Sample",entry.getKey());
+                concordanceCompProportions.set(mismatchKey,"Eval_Genotype","Mismatching_Alleles");
+                concordanceCompProportions.set(mismatchKey,"Comp_Genotype","Mismatching_Alleles");
+                concordanceEvalProportions.set(mismatchKey,"Proportion", repairNaN(( (double) table.getnMismatchingAlt() )/table.getnCalledEvalGenotypes()));
+                concordanceCompProportions.set(mismatchKey,"Proportion", repairNaN(( (double) table.getnMismatchingAlt() )/table.getnCalledCompGenotypes()));
+                concordanceCounts.set(mismatchKey,"Count",table.getnMismatchingAlt());
+            }
+
+            String sampleKey = "ALL";
+            ConcordanceMetrics.GenotypeConcordanceTable table = metrics.getOverallGenotypeConcordance();
+            for ( GenotypeType evalType : GenotypeType.values() ) {
+                for ( GenotypeType compType : GenotypeType.values() ) {
+                    String rowKey = String.format("%s_%s_%s",sampleKey,evalType.toString(),compType.toString());
+                    concordanceCounts.set(rowKey,"Sample",sampleKey);
+                    concordanceCounts.set(rowKey,"Eval_Genotype",evalType.toString());
+                    concordanceCounts.set(rowKey,"Comp_Genotype",compType.toString());
+                    int count = table.get(evalType, compType);
+                    concordanceCounts.set(rowKey,"Count",count);
+                    if ( evalType == GenotypeType.HET || evalType == GenotypeType.HOM_REF || evalType == GenotypeType.HOM_VAR) {
+                        concordanceEvalProportions.set(rowKey,"Sample",sampleKey);
+                        concordanceEvalProportions.set(rowKey,"Eval_Genotype",evalType.toString());
+                        concordanceEvalProportions.set(rowKey,"Comp_Genotype",compType.toString());
+                        concordanceEvalProportions.set(rowKey,"Proportion",repairNaN(( (double) count)/table.getnEvalGenotypes(evalType)));
+                    }
+                    if ( compType == GenotypeType.HET || compType == GenotypeType.HOM_VAR || compType == GenotypeType.HOM_REF ) {
+                        concordanceCompProportions.set(rowKey,"Sample",sampleKey);
+                        concordanceCompProportions.set(rowKey,"Eval_Genotype",evalType.toString());
+                        concordanceCompProportions.set(rowKey,"Comp_Genotype",compType.toString());
+                        concordanceCompProportions.set(rowKey,"Proportion",repairNaN(( (double) count)/table.getnCompGenotypes(compType)));
+                    }
+                }
+            }
+            String rowKey = String.format("%s_%s",sampleKey,"Mismatching");
+            concordanceCounts.set(rowKey,"Sample",sampleKey);
+            concordanceCounts.set(rowKey,"Eval_Genotype","Mismatching_Alleles");
+            concordanceCounts.set(rowKey,"Comp_Genotype","Mismatching_Alleles");
+            concordanceEvalProportions.set(rowKey,"Sample",sampleKey);
+            concordanceEvalProportions.set(rowKey,"Eval_Genotype","Mismatching_Alleles");
+            concordanceEvalProportions.set(rowKey,"Comp_Genotype","Mismatching_Alleles");
+            concordanceCompProportions.set(rowKey,"Sample",sampleKey);
+            concordanceCompProportions.set(rowKey,"Eval_Genotype","Mismatching_Alleles");
+            concordanceCompProportions.set(rowKey,"Comp_Genotype","Mismatching_Alleles");
+            concordanceEvalProportions.set(rowKey,"Proportion", repairNaN(( (double) table.getnMismatchingAlt() )/table.getnCalledEvalGenotypes()));
+            concordanceCompProportions.set(rowKey,"Proportion", repairNaN(( (double) table.getnMismatchingAlt() )/table.getnCalledCompGenotypes()));
+            concordanceCounts.set(rowKey,"Count",table.getnMismatchingAlt());
+
+            for ( Map.Entry<String,Double> nrsEntry : metrics.getPerSampleNRS().entrySet() ) {
+                concordanceSummary.set(nrsEntry.getKey(),"Sample",nrsEntry.getKey());
+                concordanceSummary.set(nrsEntry.getKey(),"Non-Reference_Sensitivity",nrsEntry.getValue());
+            }
+            for ( Map.Entry<String,Double> nrdEntry : metrics.getPerSampleNRD().entrySet() ) {
+                concordanceSummary.set(nrdEntry.getKey(),"Non-Reference_Discrepancy",nrdEntry.getValue());
+            }
+            for ( Map.Entry<String,Double> ogcEntry : metrics.getPerSampleOGC().entrySet() ) {
+                concordanceSummary.set(ogcEntry.getKey(),"Overall_Genotype_Concordance",ogcEntry.getValue());
+            }
+            concordanceSummary.set("ALL_NRS_NRD","Sample","ALL");
+            concordanceSummary.set("ALL_NRS_NRD","Non-Reference_Sensitivity",metrics.getOverallNRS());
+            concordanceSummary.set("ALL_NRS_NRD","Non-Reference_Discrepancy",metrics.getOverallNRD());
+            concordanceSummary.set("ALL_NRS_NRD","Overall_Genotype_Concordance",metrics.getOverallOGC());
+
+
+            for (ConcordanceMetrics.SiteConcordanceType type : ConcordanceMetrics.SiteConcordanceType.values() ) {
+                siteConcordance.addColumn(type.toString(),"%d");
+            }
+
+            for (ConcordanceMetrics.SiteConcordanceType type : ConcordanceMetrics.SiteConcordanceType.values() ) {
+                siteConcordance.set("Comparison",type.toString(),metrics.getOverallSiteConcordance().get(type));
+            }
+
+        } else {
+            concordanceCompProportions.addColumn("Sample","%s");
+            concordanceCounts.addColumn("Sample","%s");
+            concordanceEvalProportions.addColumn("Sample","%s");
+            concordanceSummary.addColumn("Sample","%s");
+            for ( GenotypeType evalType : GenotypeType.values() ) {
+                for ( GenotypeType compType : GenotypeType.values() ) {
+                    String colKey = String.format("%s_%s", evalType.toString(), compType.toString());
+                    concordanceCounts.addColumn(colKey,"%d");
+                    if ( evalType == GenotypeType.HET || evalType == GenotypeType.HOM_REF || evalType == GenotypeType.HOM_VAR)
+                        concordanceEvalProportions.addColumn(colKey,"%.3f");
+                    if ( compType == GenotypeType.HET || compType == GenotypeType.HOM_VAR || compType == GenotypeType.HOM_REF )
+                        concordanceCompProportions.addColumn(colKey,"%.3f");
+                }
+            }
+            concordanceEvalProportions.addColumn("Mismatching_Alleles","%.3f");
+            concordanceCompProportions.addColumn("Mismatching_Alleles","%.3f");
+            concordanceCounts.addColumn("Mismatching_Alleles","%d");
+            concordanceSummary.addColumn("Non-Reference Sensitivity","%.3f");
+            concordanceSummary.addColumn("Non-Reference Discrepancy","%.3f");
+            concordanceSummary.addColumn("Overall_Genotype_Concordance","%.3f");
+            for (ConcordanceMetrics.SiteConcordanceType type : ConcordanceMetrics.SiteConcordanceType.values() ) {
+                siteConcordance.addColumn(type.toString(),"%d");
+            }
+
+            for ( Map.Entry<String,ConcordanceMetrics.GenotypeConcordanceTable> entry : metrics.getPerSampleGenotypeConcordance().entrySet() ) {
+                ConcordanceMetrics.GenotypeConcordanceTable table = entry.getValue();
+                concordanceEvalProportions.set(entry.getKey(),"Sample",entry.getKey());
+                concordanceCompProportions.set(entry.getKey(),"Sample",entry.getKey());
+                concordanceCounts.set(entry.getKey(),"Sample",entry.getKey());
+                for ( GenotypeType evalType : GenotypeType.values() ) {
+                    for ( GenotypeType compType : GenotypeType.values() ) {
+                        String colKey = String.format("%s_%s",evalType.toString(),compType.toString());
+                        int count = table.get(evalType, compType);
+                        concordanceCounts.set(entry.getKey(),colKey,count);
+                        if ( evalType == GenotypeType.HET || evalType == GenotypeType.HOM_REF || evalType == GenotypeType.HOM_VAR)
+                            concordanceEvalProportions.set(entry.getKey(),colKey,repairNaN(( (double) count)/table.getnEvalGenotypes(evalType)));
+                        if ( compType == GenotypeType.HET || compType == GenotypeType.HOM_VAR || compType == GenotypeType.HOM_REF )
+                            concordanceCompProportions.set(entry.getKey(),colKey,repairNaN(( (double) count)/table.getnCompGenotypes(compType)));
+                    }
+                }
+                concordanceEvalProportions.set(entry.getKey(),"Mismatching_Alleles", repairNaN(( (double) table.getnMismatchingAlt() )/table.getnCalledEvalGenotypes()));
+                concordanceCompProportions.set(entry.getKey(),"Mismatching_Alleles", repairNaN(( (double) table.getnMismatchingAlt() )/table.getnCalledCompGenotypes()));
+                concordanceCounts.set(entry.getKey(),"Mismatching_Alleles",table.getnMismatchingAlt());
+            }
+
+            String rowKey = "ALL";
+            concordanceCompProportions.set(rowKey,"Sample",rowKey);
+            concordanceEvalProportions.set(rowKey,"Sample",rowKey);
+            concordanceCounts.set(rowKey,"Sample",rowKey);
+            ConcordanceMetrics.GenotypeConcordanceTable table = metrics.getOverallGenotypeConcordance();
+            for ( GenotypeType evalType : GenotypeType.values() ) {
+                for ( GenotypeType compType : GenotypeType.values() ) {
+                    String colKey = String.format("%s_%s",evalType.toString(),compType.toString());
+                    int count = table.get(evalType,compType);
+                    concordanceCounts.set(rowKey,colKey,count);
+                    if ( evalType == GenotypeType.HET || evalType == GenotypeType.HOM_REF || evalType == GenotypeType.HOM_VAR)
+                        concordanceEvalProportions.set(rowKey,colKey,repairNaN(( (double) count)/table.getnEvalGenotypes(evalType)));
+                    if ( compType == GenotypeType.HET || compType == GenotypeType.HOM_VAR || compType == GenotypeType.HOM_REF )
+                        concordanceCompProportions.set(rowKey,colKey,repairNaN(( (double) count)/table.getnCompGenotypes(compType)));
+                }
+            }
+            concordanceEvalProportions.set(rowKey,"Mismatching_Alleles", repairNaN(( (double) table.getnMismatchingAlt() )/table.getnCalledEvalGenotypes()));
+            concordanceCompProportions.set(rowKey,"Mismatching_Alleles", repairNaN(( (double) table.getnMismatchingAlt() )/table.getnCalledCompGenotypes()));
+            concordanceCounts.set(rowKey,"Mismatching_Alleles",table.getnMismatchingAlt());
+
+            for ( Map.Entry<String,Double> nrsEntry : metrics.getPerSampleNRS().entrySet() ) {
+                concordanceSummary.set(nrsEntry.getKey(),"Sample",nrsEntry.getKey());
+                concordanceSummary.set(nrsEntry.getKey(),"Non-Reference Sensitivity",nrsEntry.getValue());
+            }
+            for ( Map.Entry<String,Double> nrdEntry : metrics.getPerSampleNRD().entrySet() ) {
+                concordanceSummary.set(nrdEntry.getKey(),"Non-Reference Discrepancy",nrdEntry.getValue());
+            }
+            for ( Map.Entry<String,Double> ogcEntry : metrics.getPerSampleOGC().entrySet() ) {
+                concordanceSummary.set(ogcEntry.getKey(),"Overall_Genotype_Concordance",ogcEntry.getValue());
+            }
+            concordanceSummary.set("ALL","Sample","ALL");
+            concordanceSummary.set("ALL","Non-Reference Sensitivity",metrics.getOverallNRS());
+            concordanceSummary.set("ALL","Non-Reference Discrepancy",metrics.getOverallNRD());
+            concordanceSummary.set("ALL","Overall_Genotype_Concordance",metrics.getOverallOGC());
+
+            for (ConcordanceMetrics.SiteConcordanceType type : ConcordanceMetrics.SiteConcordanceType.values() ) {
+                siteConcordance.set("Comparison",type.toString(),metrics.getOverallSiteConcordance().get(type));
+            }
+        }
+
+        report.addTable(concordanceCompProportions);
+        report.addTable(concordanceEvalProportions);
+        report.addTable(concordanceCounts);
+        report.addTable(concordanceSummary);
+        report.addTable(siteConcordance);
+
+        report.print(out);
+    }
+
+    public VariantContext createEmptyContext(VariantContext other, List<String> samples) {
+        VariantContextBuilder builder = new VariantContextBuilder();
+        // set the alleles to be the same
+        builder.alleles(other.getAlleles());
+        builder.loc(other.getChr(),other.getStart(),other.getEnd());
+        // set all genotypes to empty
+        List<Genotype> genotypes = new ArrayList<Genotype>(samples.size());
+        for ( String sample : samples )
+            genotypes.add(GenotypeBuilder.create(sample, new ArrayList<Allele>(0)));
+        builder.genotypes(genotypes);
+        return builder.make();
+    }
+
+    public VariantContext filterGenotypes(VariantContext context, boolean ignoreSiteFilter, List<VariantContextUtils.JexlVCMatchExp> exps) {
+        if ( ! context.isFiltered() || ignoreSiteFilter ) {
+            List<Genotype> filteredGenotypes = new ArrayList<Genotype>(context.getNSamples());
+            for ( Genotype g : context.getGenotypes() ) {
+                Map<VariantContextUtils.JexlVCMatchExp, Boolean> matchMap = VariantContextUtils.match(context, g, exps);
+                boolean filtered = false;
+                for ( Boolean b : matchMap.values() ) {
+                    if ( b ) {
+                        filtered = true;
+                        break;
+                    }
+                }
+                if ( filtered ) {
+                    filteredGenotypes.add(GenotypeBuilder.create(g.getSampleName(),Arrays.asList(Allele.NO_CALL,Allele.NO_CALL),g.getExtendedAttributes()));
+                } else {
+                    filteredGenotypes.add(g);
+                }
+            }
+            VariantContextBuilder builder = new VariantContextBuilder(context);
+            builder.genotypes(filteredGenotypes);
+            return builder.make();
+        }
+
+        VariantContextBuilder builder = new VariantContextBuilder();
+        builder.alleles(Arrays.asList(context.getReference()));
+        builder.loc(context.getChr(),context.getStart(),context.getEnd());
+        List<Genotype> newGeno = new ArrayList<Genotype>(context.getNSamples());
+        for ( Genotype g : context.getGenotypes().iterateInSampleNameOrder() ) {
+            newGeno.add(GenotypeBuilder.create(g.getSampleName(),new ArrayList<Allele>()));
+        }
+        builder.genotypes(newGeno);
+        return builder.make();
+    }
+}
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/tools/walkers/variantutils/LeftAlignAndTrimVariants.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/tools/walkers/variantutils/LeftAlignAndTrimVariants.java
new file mode 100644
index 0000000..6410478
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/tools/walkers/variantutils/LeftAlignAndTrimVariants.java
@@ -0,0 +1,303 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.tools.walkers.variantutils;
+
+import com.google.java.contract.Ensures;
+import com.google.java.contract.Requires;
+import htsjdk.samtools.Cigar;
+import htsjdk.samtools.CigarElement;
+import htsjdk.samtools.CigarOperator;
+import org.broadinstitute.gatk.utils.commandline.Argument;
+import org.broadinstitute.gatk.utils.commandline.ArgumentCollection;
+import org.broadinstitute.gatk.utils.commandline.Output;
+import org.broadinstitute.gatk.engine.CommandLineGATK;
+import org.broadinstitute.gatk.engine.arguments.StandardVariantContextInputArgumentCollection;
+import org.broadinstitute.gatk.engine.contexts.AlignmentContext;
+import org.broadinstitute.gatk.engine.contexts.ReferenceContext;
+import org.broadinstitute.gatk.engine.refdata.RefMetaDataTracker;
+import org.broadinstitute.gatk.engine.walkers.Reference;
+import org.broadinstitute.gatk.engine.walkers.RodWalker;
+import org.broadinstitute.gatk.engine.walkers.Window;
+import org.broadinstitute.gatk.utils.SampleUtils;
+import org.broadinstitute.gatk.utils.collections.Pair;
+import org.broadinstitute.gatk.utils.help.HelpConstants;
+import org.broadinstitute.gatk.utils.variant.GATKVariantContextUtils;
+import htsjdk.variant.vcf.VCFHeader;
+import htsjdk.variant.vcf.VCFHeaderLine;
+import org.broadinstitute.gatk.utils.variant.GATKVCFUtils;
+import org.broadinstitute.gatk.utils.help.DocumentedGATKFeature;
+import org.broadinstitute.gatk.utils.sam.AlignmentUtils;
+import htsjdk.variant.variantcontext.*;
+import htsjdk.variant.variantcontext.writer.VariantContextWriter;
+import htsjdk.variant.variantcontext.writer.VariantContextWriterFactory;
+
+import java.util.*;
+
+/**
+ * Left-aligns indels from a variants file.
+ *
+ * <p>
+ * LeftAlignAndTrimVariants is a tool that takes a VCF file and left-aligns the indels inside it.  The same indel can often be
+ * placed at multiple positions and still represent the same haplotype.  While the standard convention with VCF is to
+ * place an indel at the left-most position this doesn't always happen, so this tool can be used to left-align them.
+ * Note that this tool cannot handle anything other than bi-allelic, simple indels.  Complex events are written out unchanged.
+ * Optionally, the tool will also trim common bases from indels, leaving them with a minimum representation.
+ *
+ * <h3>Input</h3>
+ * <p>
+ * A variant set to left-align and trim.
+ * </p>
+ *
+ * <h3>Output</h3>
+ * <p>
+ * A left-aligned VCF.
+ * </p>
+ *
+ * <h3>Examples</h3>
+ * <pre>
+ * java -Xmx2g -jar GenomeAnalysisTK.jar \
+ *   -R ref.fasta \
+ *   -T LeftAlignAndTrimVariants \
+ *   --variant input.vcf \
+ *   -o output.vcf
+ * </pre>
+ *
+ */
+ at DocumentedGATKFeature( groupName = HelpConstants.DOCS_CAT_VARMANIP, extraDocs = {CommandLineGATK.class} )
+ at Reference(window=@Window(start=-200,stop=200))    // WARNING: if this changes,MAX_INDEL_LENGTH needs to change as well!
+public class LeftAlignAndTrimVariants extends RodWalker<Integer, Integer> {
+
+    @ArgumentCollection
+    protected StandardVariantContextInputArgumentCollection variantCollection = new StandardVariantContextInputArgumentCollection();
+
+    /**
+     * If this argument is set, bases common to all alleles will be removed, leaving only their minimal representation.
+     */
+    @Argument(fullName="trimAlleles", shortName="trim", doc="Trim alleles to remove bases common to all of them", required=false)
+    protected boolean trimAlleles = false;
+
+    /**
+     * If this argument is set, split multiallelic records and left-align individual alleles.
+     * If this argument is not set, multiallelic records are not attempted to left-align and will be copied as is.
+     */
+    @Argument(fullName="splitMultiallelics", shortName="split", doc="Split multiallelic records and left-align individual alleles", required=false)
+    protected boolean splitMultiallelics = false;
+
+
+    @Output(doc="File to which variants should be written")
+    protected VariantContextWriter baseWriter = null;
+
+    private VariantContextWriter writer;
+
+    private static final int MAX_INDEL_LENGTH = 200; // needs to match reference window size!
+    public void initialize() {
+        String trackName = variantCollection.variants.getName();
+        Set<String> samples = SampleUtils.getSampleListWithVCFHeader(getToolkit(), Arrays.asList(trackName));
+        Map<String, VCFHeader> vcfHeaders = GATKVCFUtils.getVCFHeadersFromRods(getToolkit(), Arrays.asList(trackName));
+
+        Set<VCFHeaderLine> headerLines = vcfHeaders.get(trackName).getMetaDataInSortedOrder();
+        baseWriter.writeHeader(new VCFHeader(headerLines, samples));
+
+        writer = VariantContextWriterFactory.sortOnTheFly(baseWriter, 200);
+    }
+
+    public Integer map(RefMetaDataTracker tracker, ReferenceContext ref, AlignmentContext context) {
+        if ( tracker == null )
+            return 0;
+
+        Collection<VariantContext> VCs = tracker.getValues(variantCollection.variants, context.getLocation());
+
+        int changedSites = 0;
+        for ( final VariantContext vc : VCs ) {
+            // split first into biallelics, and optionally trim alleles to minimal representation
+            Pair<VariantContext,Integer> result = new Pair<VariantContext, Integer>(vc,0); // default value
+            if (splitMultiallelics) {
+                final List<VariantContext> vcList = GATKVariantContextUtils.splitVariantContextToBiallelics(vc);
+                for (final VariantContext biallelicVC: vcList) {
+                    final VariantContext v = (trimAlleles ? GATKVariantContextUtils.trimAlleles(biallelicVC,true,true) : biallelicVC);
+                    result = alignAndWrite(v, ref);
+
+                    // strip out PLs and AD if we've subsetted the alleles
+                    if ( vcList.size() > 1 )
+                        result.first = new VariantContextBuilder(result.first).genotypes(GATKVariantContextUtils.stripPLsAndAD(result.first.getGenotypes())).make();
+
+                    writer.add(result.first);
+                    changedSites += result.second;
+                }
+            }
+            else {
+                if (trimAlleles)
+                    result = alignAndWrite(GATKVariantContextUtils.trimAlleles(vc,true,true), ref);
+                else
+                    result = alignAndWrite(vc,ref);
+                writer.add(result.first);
+                changedSites += result.second;
+
+            }
+
+        }
+
+        return changedSites;
+    }
+
+    public Integer reduceInit() { return 0; }
+
+    public Integer reduce(Integer value, Integer sum) {
+        return sum + value;
+    }
+
+    public void onTraversalDone(Integer result) {
+        writer.close();
+        System.out.println(result + " variants were aligned");
+    }
+
+    /**
+     * Main routine workhorse. By definitio, it will only take biallelic vc's. Splitting into multiple alleles has to be
+     * handled by calling routine.
+     * @param vc                  Input VC with variants to left align
+     * @param ref                 Reference context
+     * @return                    # of records left-aligned (0 or 1) and new VC.
+     */
+    @Requires({"vc != null","ref != null", "vc.isBiallelic() == true","ref.getBases().length>=2*MAX_INDEL_LENGTH+1"})
+    @Ensures({"result != null","result.first != null", "result.second >=0"})
+    protected static Pair<VariantContext,Integer>  alignAndWrite(final VariantContext vc, final ReferenceContext ref) {
+
+        final Pair<VariantContext, Integer> retValue =  new Pair<VariantContext, Integer>(vc,0);
+        if (!vc.isIndel() || vc.isComplexIndel() ) {
+            return retValue;
+        }
+
+        // get the indel length
+        final int indelLength;
+        if ( vc.isSimpleDeletion() )
+            indelLength = vc.getReference().length() - 1;
+        else
+            indelLength = vc.getAlternateAllele(0).length() - 1;
+
+        if ( indelLength > MAX_INDEL_LENGTH )
+            return retValue;
+
+         if (vc.getReference().getBases()[0] != vc.getAlternateAllele(0).getBases()[0])
+            return retValue;
+
+        final byte[] refSeq = ref.getBases();
+
+        // create an indel haplotype.
+        //
+        final int originalIndex = vc.getStart() - ref.getWindow().getStart() + 1;
+        if (originalIndex < 0 || originalIndex >= ref.getBases().length)
+            return retValue;
+
+        final byte[] originalIndel = makeHaplotype(vc, refSeq, originalIndex, indelLength);
+
+        // create a CIGAR string to represent the event
+        ArrayList<CigarElement> elements = new ArrayList<CigarElement>();
+        elements.add(new CigarElement(originalIndex, CigarOperator.M));
+        elements.add(new CigarElement(indelLength, vc.isSimpleDeletion() ? CigarOperator.D : CigarOperator.I));
+        elements.add(new CigarElement(refSeq.length - originalIndex, CigarOperator.M));
+        Cigar originalCigar = new Cigar(elements);
+
+        // left align the CIGAR
+        Cigar newCigar = AlignmentUtils.leftAlignIndel(originalCigar, refSeq, originalIndel, 0, 0, true);
+
+        // update if necessary and write
+        if ( !newCigar.equals(originalCigar) && newCigar.numCigarElements() > 1 ) {
+            int difference = originalIndex - newCigar.getCigarElement(0).getLength();
+            VariantContext newVC = new VariantContextBuilder(vc).start(vc.getStart()-difference).stop(vc.getEnd()-difference).make();
+            //System.out.println("Moving record from " + vc.getChr()+":"+vc.getStart() + " to " + vc.getChr()+":"+(vc.getStart()-difference));
+
+            final int indelIndex = originalIndex-difference;
+            final byte[] newBases = new byte[indelLength + 1];
+            newBases[0] = refSeq[indelIndex-1];
+            System.arraycopy((vc.isSimpleDeletion() ? refSeq : originalIndel), indelIndex, newBases, 1, indelLength);
+            final Allele newAllele = Allele.create(newBases, vc.isSimpleDeletion());
+            newVC = updateAllele(newVC, newAllele);
+            // overwrite default return value with new left-aligned VC
+            retValue.first = newVC;
+            retValue.second = 1;
+
+        }
+        return retValue;
+    }
+
+    /**
+     * Make a haplotype from a given alt allele, using bases in input reference, index of an input reference
+     * @param vc                                Input VC - will use only alt allele from it
+     * @param ref                               Ref bases
+     * @param indexOfRef                        Index in ref where to create indel
+     * @param indelLength                       Indel length
+     * @return
+     */
+    @Requires({"vc != null","ref != null", "indexOfRef +indelLength < ref.length", "vc.getNAlleles() == 2"})
+    @Ensures("result != null")
+    private static byte[] makeHaplotype(VariantContext vc, byte[] ref, int indexOfRef, int indelLength) {
+        byte[] hap = new byte[ref.length + (indelLength * (vc.isSimpleDeletion() ? -1 : 1))];
+
+        // add the bases before the indel
+        System.arraycopy(ref, 0, hap, 0, indexOfRef);
+        int currentPos = indexOfRef;
+
+        // take care of the indel
+        if ( vc.isSimpleDeletion() ) {
+            indexOfRef += indelLength;
+        } else {
+            System.arraycopy(vc.getAlternateAllele(0).getBases(), 1, hap, currentPos, indelLength);
+            currentPos += indelLength;
+        }
+
+        // add the bases after the indel
+        System.arraycopy(ref, indexOfRef, hap, currentPos, ref.length - indexOfRef);
+
+        return hap;
+    }
+
+    public static VariantContext updateAllele(final VariantContext vc, final Allele newAllele) {
+        // create a mapping from original allele to new allele
+        HashMap<Allele, Allele> alleleMap = new HashMap<Allele, Allele>(vc.getAlleles().size());
+        if ( newAllele.isReference() ) {
+            alleleMap.put(vc.getReference(), newAllele);
+            alleleMap.put(vc.getAlternateAllele(0), Allele.create(newAllele.getBases()[0], false));
+        } else {
+            alleleMap.put(vc.getReference(), Allele.create(newAllele.getBases()[0], true));
+            alleleMap.put(vc.getAlternateAllele(0), newAllele);
+        }
+
+        // create new Genotype objects
+        GenotypesContext newGenotypes = GenotypesContext.create(vc.getNSamples());
+        for ( final Genotype genotype : vc.getGenotypes() ) {
+            List<Allele> newAlleles = new ArrayList<Allele>();
+            for ( Allele allele : genotype.getAlleles() ) {
+                Allele newA = alleleMap.get(allele);
+                if ( newA == null )
+                    newA = Allele.NO_CALL;
+                newAlleles.add(newA);
+            }
+            newGenotypes.add(new GenotypeBuilder(genotype).alleles(newAlleles).make());
+        }
+
+        return new VariantContextBuilder(vc).alleles(alleleMap.values()).genotypes(newGenotypes).make();
+    }
+}
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/tools/walkers/variantutils/LiftoverVariants.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/tools/walkers/variantutils/LiftoverVariants.java
new file mode 100644
index 0000000..710aad5
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/tools/walkers/variantutils/LiftoverVariants.java
@@ -0,0 +1,179 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.tools.walkers.variantutils;
+
+import htsjdk.samtools.liftover.LiftOver;
+import htsjdk.samtools.util.Interval;
+import htsjdk.samtools.SAMFileHeader;
+import htsjdk.samtools.SAMFileReader;
+import org.broadinstitute.gatk.utils.commandline.Argument;
+import org.broadinstitute.gatk.utils.commandline.ArgumentCollection;
+import org.broadinstitute.gatk.utils.commandline.Output;
+import org.broadinstitute.gatk.engine.CommandLineGATK;
+import org.broadinstitute.gatk.engine.arguments.StandardVariantContextInputArgumentCollection;
+import org.broadinstitute.gatk.engine.contexts.AlignmentContext;
+import org.broadinstitute.gatk.engine.contexts.ReferenceContext;
+import org.broadinstitute.gatk.engine.refdata.RefMetaDataTracker;
+import org.broadinstitute.gatk.engine.walkers.RodWalker;
+import org.broadinstitute.gatk.utils.SampleUtils;
+import org.broadinstitute.gatk.utils.help.HelpConstants;
+import org.broadinstitute.gatk.utils.variant.GATKVCFUtils;
+import org.broadinstitute.gatk.utils.variant.GATKVariantContextUtils;
+import htsjdk.variant.variantcontext.writer.Options;
+import htsjdk.variant.vcf.*;
+import org.broadinstitute.gatk.utils.exceptions.UserException;
+import org.broadinstitute.gatk.utils.help.DocumentedGATKFeature;
+import htsjdk.variant.variantcontext.VariantContext;
+import htsjdk.variant.variantcontext.VariantContextBuilder;
+import htsjdk.variant.variantcontext.writer.VariantContextWriter;
+import htsjdk.variant.variantcontext.writer.VariantContextWriterFactory;
+
+import java.io.File;
+import java.util.*;
+
+/**
+ * Lifts a VCF file over from one build to another.
+ *
+ * "Lifting over" variants means adjusting variant calls from one reference to another. Specifically, the process adjusts the position of the call to match the corresponding position on the target reference.
+ * For example, if you have variants called from reads aligned to the hg19 reference, and you want to compare them to calls made based on the b37 reference, you need to liftover one of the callsets to the other reference.
+ *
+ * LiftoverVariants is intended to be the first of two processing steps for the liftover process.
+ * The second step is to run FilterLiftedVariants on the output of LiftoverVariants. This will produce valid well-behaved VCF files, where you'll see that the contig names in the header have all been correctly replaced.
+ *
+ * To be clear, the VCF resulting from the LiftoverVariants run is not guaranteed to be valid according to the official specification.  The file could
+ * possibly be mis-sorted and the header may not be complete. That is why you need to run FilterLiftedVariants on it.
+ */
+ at DocumentedGATKFeature( groupName = HelpConstants.DOCS_CAT_VARMANIP, extraDocs = {CommandLineGATK.class} )
+public class LiftoverVariants extends RodWalker<Integer, Integer> {
+
+    @ArgumentCollection
+    protected StandardVariantContextInputArgumentCollection variantCollection = new StandardVariantContextInputArgumentCollection();
+
+    @Output(doc="File to which variants should be written", required=true, defaultToStdout=false)
+    protected File file = null;
+    protected VariantContextWriter writer = null;
+
+    @Argument(fullName="chain", shortName="chain", doc="Chain file", required=true)
+    protected File CHAIN = null;
+
+    @Argument(fullName="newSequenceDictionary", shortName="dict", doc="Sequence .dict file for the new build", required=true)
+    protected File NEW_SEQ_DICT = null;
+
+    @Argument(fullName="recordOriginalLocation", shortName="recordOriginalLocation", doc="Should we record what the original location was in the INFO field?", required=false)
+    protected Boolean RECORD_ORIGINAL_LOCATION = false;
+
+    private LiftOver liftOver;
+
+    private long successfulIntervals = 0, failedIntervals = 0;
+
+    public void initialize() {
+        try {
+            liftOver = new LiftOver(CHAIN);
+        } catch (RuntimeException e) {
+            throw new UserException.BadInput("there is a problem with the chain file you are using: " + e.getMessage());
+        }
+
+        liftOver.setLiftOverMinMatch(LiftOver.DEFAULT_LIFTOVER_MINMATCH);
+
+        try {
+            final SAMFileHeader toHeader = new SAMFileReader(NEW_SEQ_DICT).getFileHeader();
+            liftOver.validateToSequences(toHeader.getSequenceDictionary());
+        } catch (RuntimeException e) {
+            throw new UserException.BadInput("the chain file you are using is not compatible with the reference you are trying to lift over to; please use the appropriate chain file for the given reference");    
+        }
+
+        String trackName = variantCollection.variants.getName();
+        Set<String> samples = SampleUtils.getSampleListWithVCFHeader(getToolkit(), Arrays.asList(trackName));
+        Map<String, VCFHeader> vcfHeaders = GATKVCFUtils.getVCFHeadersFromRods(getToolkit(), Arrays.asList(trackName));
+
+        Set<VCFHeaderLine> metaData = new HashSet<VCFHeaderLine>();
+        if ( vcfHeaders.containsKey(trackName) )
+            metaData.addAll(vcfHeaders.get(trackName).getMetaDataInSortedOrder());
+        if ( RECORD_ORIGINAL_LOCATION ) {
+            metaData.add(new VCFInfoHeaderLine("OriginalChr", 1, VCFHeaderLineType.String, "Original contig name for the record"));
+            metaData.add(new VCFInfoHeaderLine("OriginalStart", 1, VCFHeaderLineType.Integer, "Original start position for the record"));
+        }
+
+
+        final VCFHeader vcfHeader = new VCFHeader(metaData, samples);
+        writer = VariantContextWriterFactory.create(file, getMasterSequenceDictionary(), EnumSet.of(Options.ALLOW_MISSING_FIELDS_IN_HEADER));
+        writer.writeHeader(vcfHeader);
+    }
+
+    private void convertAndWrite(VariantContext vc, ReferenceContext ref) {
+
+        final Interval fromInterval = new Interval(vc.getChr(), vc.getStart(), vc.getStart(), false, String.format("%s:%d", vc.getChr(), vc.getStart()));
+        final int length = vc.getEnd() - vc.getStart();
+        final Interval toInterval = liftOver.liftOver(fromInterval);
+        VariantContext originalVC = vc;
+
+        if ( toInterval != null ) {
+            // check whether the strand flips, and if so reverse complement everything
+            if ( fromInterval.isPositiveStrand() != toInterval.isPositiveStrand() && vc.isPointEvent() ) {
+                vc = GATKVariantContextUtils.reverseComplement(vc);
+            }
+
+            vc = new VariantContextBuilder(vc).loc(toInterval.getSequence(), toInterval.getStart(), toInterval.getStart() + length).make();
+
+            if ( RECORD_ORIGINAL_LOCATION ) {
+                vc = new VariantContextBuilder(vc)
+                        .attribute("OriginalChr", fromInterval.getSequence())
+                        .attribute("OriginalStart", fromInterval.getStart()).make();
+            }
+
+            if ( originalVC.isSNP() && originalVC.isBiallelic() && GATKVariantContextUtils.getSNPSubstitutionType(originalVC) != GATKVariantContextUtils.getSNPSubstitutionType(vc) ) {
+                logger.warn(String.format("VCF at %s / %d => %s / %d is switching substitution type %s/%s to %s/%s",
+                        originalVC.getChr(), originalVC.getStart(), vc.getChr(), vc.getStart(),
+                        originalVC.getReference(), originalVC.getAlternateAllele(0), vc.getReference(), vc.getAlternateAllele(0)));
+            }
+
+            writer.add(vc);
+            successfulIntervals++;
+        } else {
+            failedIntervals++;
+        }
+    }
+
+    public Integer map(RefMetaDataTracker tracker, ReferenceContext ref, AlignmentContext context) {
+        if ( tracker == null )
+            return 0;
+
+        Collection<VariantContext> VCs = tracker.getValues(variantCollection.variants, context.getLocation());
+        for ( VariantContext vc : VCs )
+            convertAndWrite(vc, ref);
+
+        return 0;
+    }
+
+    public Integer reduceInit() { return 0; }
+
+    public Integer reduce(Integer value, Integer sum) { return 0; }
+
+    public void onTraversalDone(Integer result) {
+        System.out.println("Converted " + successfulIntervals + " records; failed to convert " + failedIntervals + " records.");
+        writer.close();
+    }
+}
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/tools/walkers/variantutils/RandomlySplitVariants.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/tools/walkers/variantutils/RandomlySplitVariants.java
new file mode 100644
index 0000000..d50b4f2
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/tools/walkers/variantutils/RandomlySplitVariants.java
@@ -0,0 +1,165 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.tools.walkers.variantutils;
+
+import org.broadinstitute.gatk.utils.commandline.Argument;
+import org.broadinstitute.gatk.utils.commandline.ArgumentCollection;
+import org.broadinstitute.gatk.utils.commandline.Output;
+import org.broadinstitute.gatk.engine.CommandLineGATK;
+import org.broadinstitute.gatk.engine.GenomeAnalysisEngine;
+import org.broadinstitute.gatk.engine.arguments.StandardVariantContextInputArgumentCollection;
+import org.broadinstitute.gatk.engine.contexts.AlignmentContext;
+import org.broadinstitute.gatk.engine.contexts.ReferenceContext;
+import org.broadinstitute.gatk.engine.refdata.RefMetaDataTracker;
+import org.broadinstitute.gatk.engine.walkers.RodWalker;
+import org.broadinstitute.gatk.utils.SampleUtils;
+import org.broadinstitute.gatk.utils.help.HelpConstants;
+import org.broadinstitute.gatk.utils.variant.GATKVCFUtils;
+import htsjdk.variant.vcf.VCFHeader;
+import htsjdk.variant.vcf.VCFHeaderLine;
+import org.broadinstitute.gatk.utils.exceptions.UserException;
+import org.broadinstitute.gatk.utils.help.DocumentedGATKFeature;
+import htsjdk.variant.variantcontext.VariantContext;
+import htsjdk.variant.variantcontext.writer.VariantContextWriter;
+import htsjdk.variant.variantcontext.writer.VariantContextWriterFactory;
+
+import java.io.File;
+import java.util.*;
+
+/**
+ * Takes a VCF file, randomly splits variants into two different sets, and outputs 2 new VCFs with the results.
+ */
+ at DocumentedGATKFeature( groupName = HelpConstants.DOCS_CAT_VARMANIP, extraDocs = {CommandLineGATK.class} )
+public class RandomlySplitVariants extends RodWalker<Integer, Integer> {
+
+    @ArgumentCollection
+    protected StandardVariantContextInputArgumentCollection variantCollection = new StandardVariantContextInputArgumentCollection();
+
+    @Output(fullName="out1", shortName="o1", doc="File #1 to which variants should be written", required=false, exclusiveOf = "splitToManyFiles")
+    protected VariantContextWriter vcfWriter1 = null;
+
+    @Output(fullName="out2", shortName="o2", doc="File #2 to which variants should be written", required=false, exclusiveOf = "splitToManyFiles")
+    // there's a reported bug in the GATK where we can't have 2 @Output writers
+    protected File file2 = null;
+    protected VariantContextWriter vcfWriter2 = null;
+
+    @Argument(fullName="fractionToOut1", shortName="fraction", doc="Fraction of records to be placed in out1 (must be 0 >= fraction <= 1); all other records are placed in out2", required=false)
+    protected double fraction = 0.5;
+
+    @Argument(fullName="splitToManyFiles", shortName = "splitToMany", doc="split (with uniform distribution) to more than 2 files. numOfFiles and baseOutputName parameters are required", required = false)
+    protected boolean splitToMany = false;
+
+    @Argument(fullName = "numOfOutputVCFFiles", shortName = "N", doc = "number of output VCF files. Only works with SplitToMany = true", required = false, maxRecommendedValue = 20, minValue = 2)
+    protected int numOfFiles = -1;
+
+    @Argument(fullName = "prefixForAllOutputFileNames", shortName = "baseOutputName", doc = "the name of the output VCF file will be: <baseOutputName>.split.<number>.vcf. Required with SplitToMany option", required = false)
+    protected String baseFileName = null;
+
+    private VariantContextWriter[] writers = null;
+
+    /**
+     * Set up the VCF writer, the sample expressions and regexs, and the JEXL matcher
+     */
+    public void initialize() {
+        if ( fraction < 0.0 || fraction > 1.0 )
+            throw new UserException.BadArgumentValue("fractionToOut1", "this value needs to be a number between 0 and 1");
+
+        if (splitToMany){
+            if (numOfFiles < 2)
+                throw new UserException.BadArgumentValue("numOfFiles", "this value must be greater than 2 when using the splitToMany option");
+            if (baseFileName == null)
+                throw new UserException.BadArgumentValue("baseFileName", "this value cannot be null (unprovided) when using the splitToMany option");
+        }
+        else{
+            if(vcfWriter1 == null || vcfWriter2 == null)
+                throw new UserException.BadArgumentValue("out1 or out2", "this value cannot be null (unprovided) unless you are using the splitToMany option");
+        }
+
+        // setup the header info
+        final List<String> inputNames = Arrays.asList(variantCollection.variants.getName());
+        final Set<String> samples = SampleUtils.getUniqueSamplesFromRods(getToolkit(), inputNames);
+        final Set<VCFHeaderLine> hInfo = new HashSet<>();
+        hInfo.addAll(GATKVCFUtils.getHeaderFields(getToolkit(), inputNames));
+
+
+        if(splitToMany){
+            writers = new VariantContextWriter[numOfFiles];
+            for(int i = 0; i<writers.length; i++){
+                writers[i] = VariantContextWriterFactory.create(new File(baseFileName+".split."+i+".vcf"), getMasterSequenceDictionary());
+                writers[i].writeHeader(new VCFHeader(hInfo,samples));
+            }
+
+        }
+        else {
+            vcfWriter1.writeHeader(new VCFHeader(hInfo, samples));
+            vcfWriter2 = VariantContextWriterFactory.create(file2, getMasterSequenceDictionary());
+            vcfWriter2.writeHeader(new VCFHeader(hInfo, samples));
+        }
+    }
+
+    /**
+     * Subset VC record if necessary and emit the modified record (provided it satisfies criteria for printing)
+     *
+     * @param  tracker   the ROD tracker
+     * @param  ref       reference information
+     * @param  context   alignment info
+     * @return 1 if the record was printed to the output file, 0 if otherwise
+     */
+    public Integer map(final RefMetaDataTracker tracker, final ReferenceContext ref, final AlignmentContext context) {
+        if ( tracker == null )
+            return 0;
+
+        final Collection<VariantContext> vcs = tracker.getValues(variantCollection.variants, context.getLocation());
+        for ( final VariantContext vc : vcs ) {
+            final double random = GenomeAnalysisEngine.getRandomGenerator().nextDouble();
+            if(splitToMany){
+                final int index = (int)(numOfFiles * random);
+                writers[index].add(vc);
+            }
+            else{
+                if ( random < fraction )
+                    vcfWriter1.add(vc);
+                else
+                    vcfWriter2.add(vc);
+            }
+        }
+
+        return 1;
+    }
+
+    public Integer reduceInit() { return 0; }
+
+    public Integer reduce(final Integer value, final Integer sum) { return value + sum; }
+
+    public void onTraversalDone(final Integer result) {
+        logger.info(result + " records processed.");
+        if(splitToMany)
+            for(final VariantContextWriter writer: writers)
+                writer.close();
+        else
+            vcfWriter2.close();
+    }
+}
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/tools/walkers/variantutils/SelectHeaders.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/tools/walkers/variantutils/SelectHeaders.java
new file mode 100644
index 0000000..c9842c8
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/tools/walkers/variantutils/SelectHeaders.java
@@ -0,0 +1,278 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.tools.walkers.variantutils;
+
+import org.apache.commons.io.FilenameUtils;
+import htsjdk.tribble.Feature;
+import org.broadinstitute.gatk.utils.commandline.*;
+import org.broadinstitute.gatk.engine.CommandLineGATK;
+import org.broadinstitute.gatk.engine.arguments.StandardVariantContextInputArgumentCollection;
+import org.broadinstitute.gatk.engine.contexts.AlignmentContext;
+import org.broadinstitute.gatk.engine.contexts.ReferenceContext;
+import org.broadinstitute.gatk.engine.refdata.RefMetaDataTracker;
+import org.broadinstitute.gatk.engine.walkers.RodWalker;
+import org.broadinstitute.gatk.engine.walkers.TreeReducible;
+import org.broadinstitute.gatk.utils.SampleUtils;
+import org.broadinstitute.gatk.utils.help.HelpConstants;
+import org.broadinstitute.gatk.utils.interval.IntervalMergingRule;
+import org.broadinstitute.gatk.utils.interval.IntervalSetRule;
+import org.broadinstitute.gatk.utils.variant.GATKVCFUtils;
+import org.broadinstitute.gatk.utils.variant.GATKVariantContextUtils;
+import htsjdk.variant.vcf.*;
+import org.broadinstitute.gatk.utils.help.DocumentedGATKFeature;
+import htsjdk.variant.variantcontext.writer.VariantContextWriter;
+import org.broadinstitute.gatk.utils.text.ListFileUtils;
+import htsjdk.variant.variantcontext.VariantContext;
+
+import java.io.File;
+import java.util.*;
+
+/**
+ * Selects headers from a VCF source.
+ * <p/>
+ * <p>
+ * Often, a VCF containing many headers will need to be subset in order to facilitate certain formatting guidelines.
+ * SelectHeaders can be used for this purpose. Given a single VCF file, one or more headers can be extracted from the
+ * file (based on a complete header name or a pattern match).
+ * <p/>
+ * <h3>Input</h3>
+ * <p>
+ * A set of VCFs.
+ * </p>
+ * <p/>
+ * <h3>Output</h3>
+ * <p>
+ * A header selected VCF.
+ * </p>
+ * <p/>
+ * <h3>Examples</h3>
+ * <pre>
+ * Select only the FILTER, FORMAT, and INFO headers:
+ * java -Xmx2g -jar GenomeAnalysisTK.jar \
+ *   -R ref.fasta \
+ *   -T SelectHeaders \
+ *   --variant input.vcf \
+ *   -o output.vcf \
+ *   -hn FILTER \
+ *   -hn FORMAT \
+ *   -hn INFO
+ *
+ * Select only the FILTER, FORMAT, and INFO headers and add in the reference file names:
+ * java -Xmx2g -jar GenomeAnalysisTK.jar \
+ *   -R ref.fasta \
+ *   -T SelectHeaders \
+ *   --variant input.vcf \
+ *   -o output.vcf \
+ *   -hn FILTER \
+ *   -hn FORMAT \
+ *   -hn INFO \
+ *   -irn \
+ *   -iln
+ *
+ * Select only the FILTER, FORMAT, and INFO headers, plus any headers with SnpEff:
+ * java -Xmx2g -jar GenomeAnalysisTK.jar \
+ *   -R ref.fasta \
+ *   -T SelectHeaders \
+ *   --variant input.vcf \
+ *   -o output.vcf \
+ *   -hn FILTER \
+ *   -hn FORMAT \
+ *   -hn INFO \
+ *   -he '.*SnpEff.*'
+ * </pre>
+ */
+ at SuppressWarnings("unused")
+ at DocumentedGATKFeature( groupName = HelpConstants.DOCS_CAT_VARMANIP, extraDocs = {CommandLineGATK.class} )
+public class SelectHeaders extends RodWalker<Integer, Integer> implements TreeReducible<Integer> {
+    @ArgumentCollection
+    protected StandardVariantContextInputArgumentCollection variantCollection = new StandardVariantContextInputArgumentCollection();
+
+    @Output(doc = "File to which variants should be written")
+    protected VariantContextWriter vcfWriter;
+
+    @Argument(fullName = "header_name", shortName = "hn", doc = "Include header. Can be specified multiple times", required = false)
+    public Set<String> headerNames;
+
+    @Argument(fullName = "header_expression", shortName = "he", doc = "Regular expression to select many headers from the tracks provided. Can be specified multiple times", required = false)
+    public Set<String> headerExpressions;
+
+    /**
+     * Note that header exclusion takes precedence over inclusion, so that if a header is in both lists it will be excluded.
+     */
+    @Argument(fullName = "exclude_header_name", shortName = "xl_hn", doc = "Exclude header. Can be specified multiple times", required = false)
+    public Set<String> XLheaderNames;
+
+    /**
+     * Note that interval name inclusion takes precedence over other header matching. If set other interval lines may be excluded but the intervals will still be added.
+     */
+    @Argument(fullName = "include_interval_names", shortName = "iln", doc = "If set the interval file name minus the file extension, or the command line intervals, will be added to the headers", required = false)
+    public boolean includeIntervals;
+
+    /**
+     * Note that engine header inclusion takes precedence over other header matching. If set other engine lines may be excluded but the intervals will still be added.
+     */
+    @Hidden // TODO: Determine if others find this valuable and either remove @Hidden or remove -ieh.
+    @Argument(fullName = "include_engine_headers", shortName = "ieh", doc = "If set the headers normally output by the engine will be added to the headers", required = false)
+    public boolean includeEngineHeaders;
+
+    private static final ListFileUtils.StringConverter<VCFHeaderLine> headerKey = new ListFileUtils.StringConverter<VCFHeaderLine>() {
+        @Override
+        public String convert(VCFHeaderLine value) {
+            return value.getKey();
+        }
+    };
+
+    /**
+     * Set up the VCF writer, the header expressions and regexps
+     */
+    @Override
+    public void initialize() {
+        // Get list of samples to include in the output
+        List<String> rodNames = Arrays.asList(variantCollection.variants.getName());
+
+        Map<String, VCFHeader> vcfRods = GATKVCFUtils.getVCFHeadersFromRods(getToolkit(), rodNames);
+        Set<VCFHeaderLine> headerLines = VCFUtils.smartMergeHeaders(vcfRods.values(), true);
+
+        headerLines.add(new VCFHeaderLine(VCFHeader.SOURCE_KEY, "SelectHeaders"));
+
+        // Select only the headers requested by name or expression.
+        headerLines = new LinkedHashSet<VCFHeaderLine>(getSelectedHeaders(headerLines));
+
+        // Optionally add in the intervals.
+        if (includeIntervals) {
+            IntervalArgumentCollection intervalArguments = getToolkit().getArguments().intervalArguments;
+            if (intervalArguments.intervals != null) {
+                for (IntervalBinding<Feature> intervalBinding : intervalArguments.intervals) {
+                    String source = intervalBinding.getSource();
+                    if (source == null)
+                        continue;
+                    File file = new File(source);
+                    if (file.exists()) {
+                        headerLines.add(new VCFHeaderLine(VCFHeader.INTERVALS_KEY, FilenameUtils.getBaseName(file.getName())));
+                    } else {
+                        headerLines.add(new VCFHeaderLine(VCFHeader.INTERVALS_KEY, source));
+                    }
+                }
+            }
+
+            if (intervalArguments.excludeIntervals != null) {
+                for (IntervalBinding<Feature> intervalBinding : intervalArguments.excludeIntervals) {
+                    String source = intervalBinding.getSource();
+                    if (source == null)
+                        continue;
+                    File file = new File(source);
+                    if (file.exists()) {
+                        headerLines.add(new VCFHeaderLine(VCFHeader.EXCLUDE_INTERVALS_KEY, FilenameUtils.getBaseName(file.getName())));
+                    } else {
+                        headerLines.add(new VCFHeaderLine(VCFHeader.EXCLUDE_INTERVALS_KEY, source));
+                    }
+                }
+            }
+
+            if (intervalArguments.intervalMerging != IntervalMergingRule.ALL) {
+                headerLines.add(new VCFHeaderLine(VCFHeader.INTERVAL_MERGING_KEY, String.valueOf(intervalArguments.intervalMerging)));
+            }
+
+            if (intervalArguments.intervalSetRule != IntervalSetRule.UNION) {
+                headerLines.add(new VCFHeaderLine(VCFHeader.INTERVAL_SET_RULE_KEY, String.valueOf(intervalArguments.intervalSetRule)));
+            }
+
+            if (intervalArguments.intervalPadding != 0) {
+                headerLines.add(new VCFHeaderLine(VCFHeader.INTERVAL_PADDING_KEY, String.valueOf(intervalArguments.intervalPadding)));
+            }
+        }
+
+        TreeSet<String> vcfSamples = new TreeSet<String>(SampleUtils.getSampleList(vcfRods, GATKVariantContextUtils.GenotypeMergeType.REQUIRE_UNIQUE));
+        VCFHeader vcfHeader = new VCFHeader(headerLines, vcfSamples);
+        vcfHeader.setWriteEngineHeaders(includeEngineHeaders);
+        vcfWriter.writeHeader(vcfHeader);
+    }
+
+    private Set<VCFHeaderLine> getSelectedHeaders(Set<VCFHeaderLine> headerLines) {
+        Set<VCFHeaderLine> selectedHeaders = new TreeSet<VCFHeaderLine>();
+        if (headerNames == null && headerExpressions == null) {
+            // Include everything if nothing was explicitly included.
+            selectedHeaders.addAll(headerLines);
+        } else {
+            // Only include the selected headers.
+            if (headerNames != null)
+                selectedHeaders.addAll(ListFileUtils.includeMatching(headerLines, headerKey, headerNames, true));
+            if (headerExpressions != null)
+                selectedHeaders.addAll(ListFileUtils.includeMatching(headerLines, headerKey, headerExpressions, false));
+        }
+
+        // Remove any excluded headers.
+        if (XLheaderNames != null)
+            selectedHeaders = ListFileUtils.excludeMatching(selectedHeaders, headerKey, XLheaderNames, true);
+
+        // always include the contig lines
+        selectedHeaders = VCFUtils.withUpdatedContigsAsLines(selectedHeaders, getToolkit().getArguments().referenceFile, getToolkit().getMasterSequenceDictionary(), true);
+        return selectedHeaders;
+    }
+
+    /**
+     * Pass through the VC record
+     *
+     * @param tracker the ROD tracker
+     * @param ref     reference information
+     * @param context alignment info
+     * @return number of records processed
+     */
+    @Override
+    public Integer map(RefMetaDataTracker tracker, ReferenceContext ref, AlignmentContext context) {
+        int count = 0;
+        if (tracker != null) {
+            Collection<VariantContext> vcs = tracker.getValues(variantCollection.variants, context.getLocation());
+            if (vcs != null) {
+                for (VariantContext vc : vcs) {
+                    vcfWriter.add(vc);
+                    count++;
+                }
+            }
+        }
+        return count;
+    }
+
+    @Override
+    public Integer reduceInit() {
+        return 0;
+    }
+
+    @Override
+    public Integer reduce(Integer value, Integer sum) {
+        return value + sum;
+    }
+
+    @Override
+    public Integer treeReduce(Integer lhs, Integer rhs) {
+        return lhs + rhs;
+    }
+
+    @Override
+    public void onTraversalDone(Integer result) {
+        logger.info(result + " records processed.");
+    }
+}
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/tools/walkers/variantutils/SelectVariants.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/tools/walkers/variantutils/SelectVariants.java
new file mode 100644
index 0000000..db9d082
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/tools/walkers/variantutils/SelectVariants.java
@@ -0,0 +1,801 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.tools.walkers.variantutils;
+
+import org.broadinstitute.gatk.utils.commandline.*;
+import org.broadinstitute.gatk.engine.CommandLineGATK;
+import org.broadinstitute.gatk.engine.GenomeAnalysisEngine;
+import org.broadinstitute.gatk.engine.arguments.StandardVariantContextInputArgumentCollection;
+import org.broadinstitute.gatk.engine.contexts.AlignmentContext;
+import org.broadinstitute.gatk.engine.contexts.ReferenceContext;
+import org.broadinstitute.gatk.engine.refdata.RefMetaDataTracker;
+import org.broadinstitute.gatk.engine.walkers.RodWalker;
+import org.broadinstitute.gatk.engine.walkers.TreeReducible;
+import org.broadinstitute.gatk.tools.walkers.annotator.ChromosomeCountConstants;
+import org.broadinstitute.gatk.utils.MendelianViolation;
+import org.broadinstitute.gatk.utils.SampleUtils;
+import org.broadinstitute.gatk.utils.Utils;
+import org.broadinstitute.gatk.utils.help.HelpConstants;
+import org.broadinstitute.gatk.utils.variant.GATKVCFUtils;
+import org.broadinstitute.gatk.utils.variant.GATKVariantContextUtils;
+import htsjdk.variant.vcf.*;
+import org.broadinstitute.gatk.utils.exceptions.UserException;
+import org.broadinstitute.gatk.utils.help.DocumentedGATKFeature;
+import org.broadinstitute.gatk.utils.text.XReadLines;
+import htsjdk.variant.variantcontext.*;
+import htsjdk.variant.variantcontext.writer.VariantContextWriter;
+
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.util.*;
+
+/**
+ * Selects variants from a VCF source.
+ *
+ * <p>
+ * Often, a VCF containing many samples and/or variants will need to be subset in order to facilitate certain analyses
+ * (e.g. comparing and contrasting cases vs. controls; extracting variant or non-variant loci that meet certain
+ * requirements, displaying just a few samples in a browser like IGV, etc.). SelectVariants can be used for this purpose.
+ * Given a single VCF file, one or more samples can be extracted from the file (based on a complete sample name or a
+ * pattern match).  Variants can be further selected by specifying criteria for inclusion, i.e. "DP > 1000" (depth of
+ * coverage greater than 1000x), "AF < 0.25" (sites with allele frequency less than 0.25).  These JEXL expressions are
+ * documented in the Using JEXL expressions section (http://www.broadinstitute.org/gatk/guide/article?id=1255).
+ * One can optionally include concordance or discordance tracks for use in selecting overlapping variants.
+ *
+ * <h3>Input</h3>
+ * <p>
+ * A variant set to select from.
+ * </p>
+ *
+ * <h3>Output</h3>
+ * <p>
+ * A selected VCF.
+ * </p>
+ *
+ * <h3>Examples</h3>
+ * <pre>
+ * Select two samples out of a VCF with many samples:
+ * java -Xmx2g -jar GenomeAnalysisTK.jar \
+ *   -R ref.fasta \
+ *   -T SelectVariants \
+ *   --variant input.vcf \
+ *   -o output.vcf \
+ *   -sn SAMPLE_A_PARC \
+ *   -sn SAMPLE_B_ACTG
+ *
+ * Select two samples and any sample that matches a regular expression:
+ * java -Xmx2g -jar GenomeAnalysisTK.jar \
+ *   -R ref.fasta \
+ *   -T SelectVariants \
+ *   --variant input.vcf \
+ *   -o output.vcf \
+ *   -sn SAMPLE_1_PARC \
+ *   -sn SAMPLE_1_ACTG \
+ *   -se 'SAMPLE.+PARC'
+ *
+ * Select any sample that matches a regular expression and sites where the QD annotation is more than 10:
+ * java -Xmx2g -jar GenomeAnalysisTK.jar \
+ *   -R ref.fasta \
+ *   -T SelectVariants \
+ *   --variant input.vcf \
+ *   -o output.vcf \
+ *   -se 'SAMPLE.+PARC'
+ *   -select "QD > 10.0"
+ *
+ * Select a sample and exclude non-variant loci and filtered loci:
+ * java -Xmx2g -jar GenomeAnalysisTK.jar \
+ *   -R ref.fasta \
+ *   -T SelectVariants \
+ *   --variant input.vcf \
+ *   -o output.vcf \
+ *   -sn SAMPLE_1_ACTG \
+ *   -env \
+ *   -ef
+ *
+ * Select a sample and restrict the output vcf to a set of intervals:
+ * java -Xmx2g -jar GenomeAnalysisTK.jar \
+ *   -R ref.fasta \
+ *   -T SelectVariants \
+ *   --variant input.vcf \
+ *   -o output.vcf \
+ *   -L /path/to/my.interval_list \
+ *   -sn SAMPLE_1_ACTG
+ *
+ * Select all calls missed in my vcf, but present in HapMap (useful to take a look at why these variants weren't called by this dataset):
+ * java -Xmx2g -jar GenomeAnalysisTK.jar \
+ *   -R ref.fasta \
+ *   -T SelectVariants \
+ *   --variant hapmap.vcf \
+ *   --discordance myCalls.vcf
+ *   -o output.vcf \
+ *   -sn mySample
+ *
+ * Select all calls made by both myCalls and hisCalls (useful to take a look at what is consistent between the two callers):
+ * java -Xmx2g -jar GenomeAnalysisTK.jar \
+ *   -R ref.fasta \
+ *   -T SelectVariants \
+ *   --variant myCalls.vcf \
+ *   --concordance hisCalls.vcf
+ *   -o output.vcf \
+ *   -sn mySample
+ *
+ * Generating a VCF of all the variants that are mendelian violations:
+ * java -Xmx2g -jar GenomeAnalysisTK.jar \
+ *   -R ref.fasta \
+ *   -T SelectVariants \
+ *   --variant input.vcf \
+ *   -ped family.ped \
+ *   -mvq 50 \
+ *   -o violations.vcf
+ *
+ * Creating a set with 50% of the total number of variants in the variant VCF:
+ * java -Xmx2g -jar GenomeAnalysisTK.jar \
+ *   -R ref.fasta \
+ *   -T SelectVariants \
+ *   --variant input.vcf \
+ *   -o output.vcf \
+ *   -fraction 0.5
+ *
+ * Select only indels from a VCF:
+ * java -Xmx2g -jar GenomeAnalysisTK.jar \
+ *   -R ref.fasta \
+ *   -T SelectVariants \
+ *   --variant input.vcf \
+ *   -o output.vcf \
+ *   -selectType INDEL
+ *
+ * Select only multi-allelic SNPs and MNPs from a VCF (i.e. SNPs with more than one allele listed in the ALT column):
+ * java -Xmx2g -jar GenomeAnalysisTK.jar \
+ *   -R ref.fasta \
+ *   -T SelectVariants \
+ *   --variant input.vcf \
+ *   -o output.vcf \
+ *   -selectType SNP -selectType MNP \
+ *   -restrictAllelesTo MULTIALLELIC
+ *
+ * </pre>
+ *
+ */
+ at DocumentedGATKFeature( groupName = HelpConstants.DOCS_CAT_VARMANIP, extraDocs = {CommandLineGATK.class} )
+public class SelectVariants extends RodWalker<Integer, Integer> implements TreeReducible<Integer> {
+    @ArgumentCollection protected StandardVariantContextInputArgumentCollection variantCollection = new StandardVariantContextInputArgumentCollection();
+
+    /**
+     * A site is considered discordant if there exists some sample in the variant track that has a non-reference genotype
+     * and either the site isn't present in this track, the sample isn't present in this track,
+     * or the sample is called reference in this track.
+     */
+    @Input(fullName="discordance", shortName = "disc", doc="Output variants that were not called in this comparison track", required=false)
+    protected RodBinding<VariantContext> discordanceTrack;
+
+    /**
+     * A site is considered concordant if (1) we are not looking for specific samples and there is a variant called
+     * in both the variant and concordance tracks or (2) every sample present in the variant track is present in the
+     * concordance track and they have the sample genotype call.
+     */
+    @Input(fullName="concordance", shortName = "conc", doc="Output variants that were also called in this comparison track", required=false)
+    protected RodBinding<VariantContext> concordanceTrack;
+
+    @Output(doc="File to which variants should be written")
+    protected VariantContextWriter vcfWriter = null;
+
+    @Argument(fullName="sample_name", shortName="sn", doc="Include genotypes from this sample. Can be specified multiple times", required=false)
+    public Set<String> sampleNames = new HashSet<String>(0);
+
+    @Argument(fullName="sample_expressions", shortName="se", doc="Regular expression to select many samples from the ROD tracks provided. Can be specified multiple times", required=false)
+    public Set<String> sampleExpressions ;
+
+    @Input(fullName="sample_file", shortName="sf", doc="File containing a list of samples (one per line) to include. Can be specified multiple times", required=false)
+    public Set<File> sampleFiles;
+
+    /**
+     * Note that sample exclusion takes precedence over inclusion, so that if a sample is in both lists it will be excluded.
+     */
+    @Argument(fullName="exclude_sample_name", shortName="xl_sn", doc="Exclude genotypes from this sample. Can be specified multiple times", required=false)
+    public Set<String> XLsampleNames = new HashSet<String>(0);
+
+    /**
+     * Note that sample exclusion takes precedence over inclusion, so that if a sample is in both lists it will be excluded.
+     */
+    @Input(fullName="exclude_sample_file", shortName="xl_sf", doc="File containing a list of samples (one per line) to exclude. Can be specified multiple times", required=false)
+    public Set<File> XLsampleFiles = new HashSet<File>(0);
+
+    /**
+     * Note that these expressions are evaluated *after* the specified samples are extracted and the INFO field annotations are updated.
+     */
+    @Argument(shortName="select", doc="One or more criteria to use when selecting the data", required=false)
+    public ArrayList<String> SELECT_EXPRESSIONS = new ArrayList<String>();
+
+    @Argument(fullName="excludeNonVariants", shortName="env", doc="Don't include loci found to be non-variant after the subsetting procedure", required=false)
+    protected boolean EXCLUDE_NON_VARIANTS = false;
+
+    @Argument(fullName="excludeFiltered", shortName="ef", doc="Don't include filtered loci in the analysis", required=false)
+    protected boolean EXCLUDE_FILTERED = false;
+
+    /**
+     * When this argument is used, we can choose to include only multiallelic or biallelic sites, depending on how many alleles are listed in the ALT column of a vcf.
+     * For example, a multiallelic record such as:
+     * 1    100 .   A   AAA,AAAAA
+     * will be excluded if "-restrictAllelesTo BIALLELIC" is included, because there are two alternate alleles, whereas a record such as:
+     * 1    100 .   A  T
+     * will be included in that case, but would be excluded if "-restrictAllelesTo MULTIALLELIC
+     */
+    @Argument(fullName="restrictAllelesTo", shortName="restrictAllelesTo", doc="Select only variants of a particular allelicity. Valid options are ALL (default), MULTIALLELIC or BIALLELIC", required=false)
+    private  NumberAlleleRestriction alleleRestriction = NumberAlleleRestriction.ALL;
+
+    @Argument(fullName="keepOriginalAC", shortName="keepOriginalAC", doc="Store the original AC, AF, and AN values in the INFO field after selecting (using keys AC_Orig, AF_Orig, and AN_Orig)", required=false)
+    private boolean KEEP_ORIGINAL_CHR_COUNTS = false;
+
+    /**
+     * This activates the mendelian violation module that will select all variants that correspond to a mendelian violation following the rules given by the family structure.
+     */
+    @Argument(fullName="mendelianViolation", shortName="mv", doc="output mendelian violation sites only", required=false)
+    private Boolean MENDELIAN_VIOLATIONS = false;
+
+    @Argument(fullName="mendelianViolationQualThreshold", shortName="mvq", doc="Minimum genotype QUAL score for each trio member required to accept a site as a violation", required=false)
+    protected double MENDELIAN_VIOLATION_QUAL_THRESHOLD = 0;
+
+    /**
+     * This routine is based on probability, so the final result is not guaranteed to carry the exact fraction.  Can be used for large fractions.
+     */
+    @Argument(fullName="select_random_fraction", shortName="fraction", doc="Selects a fraction (a number between 0 and 1) of the total variants at random from the variant track", required=false)
+    protected double fractionRandom = 0;
+
+    @Argument(fullName="remove_fraction_genotypes", shortName="fractionGenotypes", doc="Selects a fraction (a number between 0 and 1) of the total genotypes at random from the variant track and sets them to nocall", required=false)
+    protected double fractionGenotypes = 0;
+
+    /**
+     * This argument select particular kinds of variants out of a list. If left empty, there is no type selection and all variant types are considered for other selection criteria.
+     * When specified one or more times, a particular type of variant is selected.
+     *
+     */
+    @Argument(fullName="selectTypeToInclude", shortName="selectType", doc="Select only a certain type of variants from the input file. Valid types are INDEL, SNP, MIXED, MNP, SYMBOLIC, NO_VARIATION. Can be specified multiple times", required=false)
+    private List<VariantContext.Type> TYPES_TO_INCLUDE = new ArrayList<VariantContext.Type>();
+
+    /**
+     * If provided, we will only include variants whose ID field is present in this list of ids.  The matching
+     * is exact string matching.  The file format is just one ID per line
+     *
+     */
+    @Argument(fullName="keepIDs", shortName="IDs", doc="Only emit sites whose ID is found in this file (one ID per line)", required=false)
+    private File rsIDFile = null;
+
+
+    @Hidden
+    @Argument(fullName="fullyDecode", doc="If true, the incoming VariantContext will be fully decoded", required=false)
+    private boolean fullyDecode = false;
+
+    @Hidden
+    @Argument(fullName="forceGenotypesDecode", doc="If true, the incoming VariantContext will have its genotypes forcibly decoded by computing AC across all genotypes.  For efficiency testing only", required=false)
+    private boolean forceGenotypesDecode = false;
+
+    @Hidden
+    @Argument(fullName="justRead", doc="If true, we won't actually write the output file.  For efficiency testing only", required=false)
+    private boolean justRead = false;
+
+    @Argument(doc="indel size select",required=false,fullName="maxIndelSize")
+    private int maxIndelSize = Integer.MAX_VALUE;
+
+    @Argument(doc="Allow samples other than those in the VCF to be specified on the command line. These samples will be ignored.",required=false,fullName="ALLOW_NONOVERLAPPING_COMMAND_LINE_SAMPLES")
+    private boolean ALLOW_NONOVERLAPPING_COMMAND_LINE_SAMPLES = false;
+
+
+    public enum NumberAlleleRestriction {
+        ALL,
+        BIALLELIC,
+        MULTIALLELIC
+    }
+
+    private ArrayList<VariantContext.Type> selectedTypes = new ArrayList<VariantContext.Type>();
+    private ArrayList<String> selectNames = new ArrayList<String>();
+    private List<VariantContextUtils.JexlVCMatchExp> jexls = null;
+
+    private TreeSet<String> samples = new TreeSet<String>();
+    private boolean NO_SAMPLES_SPECIFIED = false;
+
+    private boolean DISCORDANCE_ONLY = false;
+    private boolean CONCORDANCE_ONLY = false;
+
+    private MendelianViolation mv;
+
+
+    /* variables used by the SELECT RANDOM modules */
+    private boolean SELECT_RANDOM_FRACTION = false;
+
+    //Random number generator for the genotypes to remove
+    private Random randomGenotypes = new Random();
+
+    private Set<String> IDsToKeep = null;
+    private Map<String, VCFHeader> vcfRods;
+
+    /**
+     * Set up the VCF writer, the sample expressions and regexs, and the JEXL matcher
+     */
+    public void initialize() {
+        // Get list of samples to include in the output
+        List<String> rodNames = Arrays.asList(variantCollection.variants.getName());
+
+        vcfRods = GATKVCFUtils.getVCFHeadersFromRods(getToolkit(), rodNames);
+        TreeSet<String> vcfSamples = new TreeSet<String>(SampleUtils.getSampleList(vcfRods, GATKVariantContextUtils.GenotypeMergeType.REQUIRE_UNIQUE));
+
+        Collection<String> samplesFromFile = SampleUtils.getSamplesFromFiles(sampleFiles);
+        Collection<String> samplesFromExpressions = SampleUtils.matchSamplesExpressions(vcfSamples, sampleExpressions);
+
+        // first, check overlap between requested and present samples
+        Set<String> commandLineUniqueSamples = new HashSet<String>(samplesFromFile.size()+samplesFromExpressions.size()+sampleNames.size());
+        commandLineUniqueSamples.addAll(samplesFromFile);
+        commandLineUniqueSamples.addAll(samplesFromExpressions);
+        commandLineUniqueSamples.addAll(sampleNames);
+        commandLineUniqueSamples.removeAll(vcfSamples);
+
+        // second, add the requested samples
+        samples.addAll(sampleNames);
+        samples.addAll(samplesFromExpressions);
+        samples.addAll(samplesFromFile);
+
+        logger.debug(Utils.join(",",commandLineUniqueSamples));
+
+        if ( commandLineUniqueSamples.size() > 0 && ALLOW_NONOVERLAPPING_COMMAND_LINE_SAMPLES ) {
+            logger.warn("Samples present on command line input that are not present in the VCF. These samples will be ignored.");
+            samples.removeAll(commandLineUniqueSamples);
+        } else if (commandLineUniqueSamples.size() > 0 ) {
+            throw new UserException.BadInput(String.format("%s%n%n%s%n%n%s%n%n%s",
+                    "Samples entered on command line (through -sf or -sn) that are not present in the VCF.",
+                    "A list of these samples:",
+                    Utils.join(",",commandLineUniqueSamples),
+                    "To ignore these samples, run with --ALLOW_NONOVERLAPPING_COMMAND_LINE_SAMPLES"));
+        }
+
+
+        // if none were requested, we want all of them
+        if ( samples.isEmpty() ) {
+            samples.addAll(vcfSamples);
+            NO_SAMPLES_SPECIFIED = true;
+        }
+
+        // now, exclude any requested samples
+        final Collection<String> XLsamplesFromFile = SampleUtils.getSamplesFromFiles(XLsampleFiles);
+        samples.removeAll(XLsamplesFromFile);
+        samples.removeAll(XLsampleNames);
+        NO_SAMPLES_SPECIFIED = NO_SAMPLES_SPECIFIED && XLsampleNames.isEmpty() && XLsamplesFromFile.isEmpty();
+
+        if ( samples.size() == 0 && !NO_SAMPLES_SPECIFIED )
+            throw new UserException("All samples requested to be included were also requested to be excluded.");
+
+        if ( ! NO_SAMPLES_SPECIFIED )
+            for ( String sample : samples )
+            logger.info("Including sample '" + sample + "'");
+
+        // if user specified types to include, add these, otherwise, add all possible variant context types to list of vc types to include
+        if (TYPES_TO_INCLUDE.isEmpty()) {
+
+            for (VariantContext.Type t : VariantContext.Type.values())
+                selectedTypes.add(t);
+
+        }
+        else {
+            for (VariantContext.Type t : TYPES_TO_INCLUDE)
+                selectedTypes.add(t);
+
+        }
+        // Initialize VCF header
+        Set<VCFHeaderLine> headerLines = VCFUtils.smartMergeHeaders(vcfRods.values(), true);
+        headerLines.add(new VCFHeaderLine("source", "SelectVariants"));
+
+        if (KEEP_ORIGINAL_CHR_COUNTS) {
+            headerLines.add(new VCFInfoHeaderLine("AC_Orig", VCFHeaderLineCount.A, VCFHeaderLineType.Integer, "Original AC"));
+            headerLines.add(new VCFInfoHeaderLine("AF_Orig", VCFHeaderLineCount.A, VCFHeaderLineType.Float, "Original AF"));
+            headerLines.add(new VCFInfoHeaderLine("AN_Orig", 1, VCFHeaderLineType.Integer, "Original AN"));
+        }
+        headerLines.addAll(Arrays.asList(ChromosomeCountConstants.descriptions));
+        headerLines.add(VCFStandardHeaderLines.getInfoLine(VCFConstants.DEPTH_KEY));
+
+        for (int i = 0; i < SELECT_EXPRESSIONS.size(); i++) {
+            // It's not necessary that the user supply select names for the JEXL expressions, since those
+            // expressions will only be needed for omitting records.  Make up the select names here.
+            selectNames.add(String.format("select-%d", i));
+        }
+
+        jexls = VariantContextUtils.initializeMatchExps(selectNames, SELECT_EXPRESSIONS);
+
+        // Look at the parameters to decide which analysis to perform
+        DISCORDANCE_ONLY = discordanceTrack.isBound();
+        if (DISCORDANCE_ONLY) logger.info("Selecting only variants discordant with the track: " + discordanceTrack.getName());
+
+        CONCORDANCE_ONLY = concordanceTrack.isBound();
+        if (CONCORDANCE_ONLY) logger.info("Selecting only variants concordant with the track: " + concordanceTrack.getName());
+
+        if (MENDELIAN_VIOLATIONS) {
+            mv = new MendelianViolation(MENDELIAN_VIOLATION_QUAL_THRESHOLD,false,true);
+        }
+
+        SELECT_RANDOM_FRACTION = fractionRandom > 0;
+        if (SELECT_RANDOM_FRACTION) logger.info("Selecting approximately " + 100.0*fractionRandom + "% of the variants at random from the variant track");
+
+        /** load in the IDs file to a hashset for matching */
+        if ( rsIDFile != null ) {
+            IDsToKeep = new HashSet<String>();
+            try {
+                for ( final String line : new XReadLines(rsIDFile).readLines() ) {
+                    IDsToKeep.add(line.trim());
+                }
+                logger.info("Selecting only variants with one of " + IDsToKeep.size() + " IDs from " + rsIDFile);
+            } catch ( FileNotFoundException e ) {
+                throw new UserException.CouldNotReadInputFile(rsIDFile, e);
+            }
+        }
+
+        vcfWriter.writeHeader(new VCFHeader(headerLines, samples));
+    }
+
+    /**
+     * Subset VC record if necessary and emit the modified record (provided it satisfies criteria for printing)
+     *
+     * @param  tracker   the ROD tracker
+     * @param  ref       reference information
+     * @param  context   alignment info
+     * @return 1 if the record was printed to the output file, 0 if otherwise
+     */
+    @Override
+    public Integer map(RefMetaDataTracker tracker, ReferenceContext ref, AlignmentContext context) {
+        if ( tracker == null )
+            return 0;
+
+        Collection<VariantContext> vcs = tracker.getValues(variantCollection.variants, context.getLocation());
+
+        if ( vcs == null || vcs.size() == 0) {
+            return 0;
+        }
+
+        for (VariantContext vc : vcs) {
+            // an option for performance testing only
+            if ( fullyDecode )
+                vc = vc.fullyDecode(vcfRods.get(vc.getSource()), getToolkit().lenientVCFProcessing() );
+
+            // an option for performance testing only
+            if ( forceGenotypesDecode ) {
+                final int x = vc.getCalledChrCount();
+                //logger.info("forceGenotypesDecode with getCalledChrCount() = " + );
+            }
+
+            if ( IDsToKeep != null && ! IDsToKeep.contains(vc.getID()) )
+                continue;
+
+            if (MENDELIAN_VIOLATIONS && mv.countViolations(this.getSampleDB().getFamilies(samples),vc) < 1)
+                break;
+
+            if (DISCORDANCE_ONLY) {
+                Collection<VariantContext> compVCs = tracker.getValues(discordanceTrack, context.getLocation());
+                if (!isDiscordant(vc, compVCs))
+                    continue;
+            }
+            if (CONCORDANCE_ONLY) {
+                Collection<VariantContext> compVCs = tracker.getValues(concordanceTrack, context.getLocation());
+                if (!isConcordant(vc, compVCs))
+                    continue;
+            }
+
+            if (alleleRestriction.equals(NumberAlleleRestriction.BIALLELIC) && !vc.isBiallelic())
+                continue;
+
+            if (alleleRestriction.equals(NumberAlleleRestriction.MULTIALLELIC) && vc.isBiallelic())
+                continue;
+
+            if (!selectedTypes.contains(vc.getType()))
+                continue;
+
+            if ( containsIndelLargerThan(vc, maxIndelSize) )
+                continue;
+
+            VariantContext sub = subsetRecord(vc, EXCLUDE_NON_VARIANTS);
+
+            if ( (!EXCLUDE_NON_VARIANTS || sub.isPolymorphicInSamples()) && (!EXCLUDE_FILTERED || !sub.isFiltered()) ) {
+                boolean failedJexlMatch = false;
+                try {
+                    for (VariantContextUtils.JexlVCMatchExp jexl : jexls) {
+                        if (!VariantContextUtils.match(sub, jexl)) {
+                            failedJexlMatch = true;
+                            break;
+                        }
+                    }
+                } catch (IllegalArgumentException e) {
+                    /*The IAE thrown by htsjdk already includes an informative error message ("Invalid JEXL
+                      expression detected...")*/
+                    throw new UserException(e.getMessage());
+                }
+                if ( !failedJexlMatch &&
+                        !justRead &&
+                        ( !SELECT_RANDOM_FRACTION || GenomeAnalysisEngine.getRandomGenerator().nextDouble() < fractionRandom ) ) {
+                    vcfWriter.add(sub);
+                }
+            }
+        }
+
+        return 1;
+    }
+
+    /*
+     * Determines if any of the alternate alleles are greater than the max indel size
+     *
+     * @param vc            the variant context to check
+     * @param maxIndelSize  the maximum size of allowed indels
+     * @return true if the VC contains an indel larger than maxIndelSize and false otherwise
+     */
+    protected static boolean containsIndelLargerThan(final VariantContext vc, final int maxIndelSize) {
+        final List<Integer> lengths = vc.getIndelLengths();
+        if ( lengths == null )
+            return false;
+
+        for ( Integer indelLength : lengths ) {
+            if ( Math.abs(indelLength) > maxIndelSize )
+                return true;
+        }
+
+        return false;
+    }
+
+    /**
+     * Checks if vc has a variant call for (at least one of) the samples.
+     * @param vc the variant rod VariantContext. Here, the variant is the dataset you're looking for discordances to (e.g. HapMap)
+     * @param compVCs the comparison VariantContext (discordance
+     * @return true if is discordant
+     */
+    private boolean isDiscordant (VariantContext vc, Collection<VariantContext> compVCs) {
+        if (vc == null)
+            return false;
+
+        // if we're not looking at specific samples then the absence of a compVC means discordance
+        if (NO_SAMPLES_SPECIFIED)
+            return (compVCs == null || compVCs.isEmpty());
+
+        // check if we find it in the variant rod
+        GenotypesContext genotypes = vc.getGenotypes(samples);
+        for (final Genotype g : genotypes) {
+            if (sampleHasVariant(g)) {
+                // There is a variant called (or filtered with not exclude filtered option set) that is not HomRef for at least one of the samples.
+                if (compVCs == null)
+                    return true;
+                // Look for this sample in the all vcs of the comp ROD track.
+                boolean foundVariant = false;
+                for (VariantContext compVC : compVCs) {
+                    if (haveSameGenotypes(g, compVC.getGenotype(g.getSampleName()))) {
+                        foundVariant = true;
+                        break;
+                    }
+                }
+                // if (at least one sample) was not found in all VCs of the comp ROD, we have discordance
+                if (!foundVariant)
+                    return true;
+            }
+        }
+        return false; // we only get here if all samples have a variant in the comp rod.
+    }
+
+    private boolean isConcordant (VariantContext vc, Collection<VariantContext> compVCs) {
+        if (vc == null || compVCs == null || compVCs.isEmpty())
+            return false;
+
+        // if we're not looking for specific samples then the fact that we have both VCs is enough to call it concordant.
+        if (NO_SAMPLES_SPECIFIED)
+            return true;
+
+        // make a list of all samples contained in this variant VC that are being tracked by the user command line arguments.
+        Set<String> variantSamples = vc.getSampleNames();
+        variantSamples.retainAll(samples);
+
+        // check if we can find all samples from the variant rod in the comp rod.
+        for (String sample : variantSamples) {
+            boolean foundSample = false;
+            for (VariantContext compVC : compVCs) {
+                Genotype varG = vc.getGenotype(sample);
+                Genotype compG = compVC.getGenotype(sample);
+                if (haveSameGenotypes(varG, compG)) {
+                    foundSample = true;
+                    break;
+                }
+            }
+            // if at least one sample doesn't have the same genotype, we don't have concordance
+            if (!foundSample) {
+                return false;
+            }
+        }
+        return true;
+    }
+
+    private boolean sampleHasVariant(Genotype g) {
+        return (g !=null && !g.isHomRef() && (g.isCalled() || (g.isFiltered() && !EXCLUDE_FILTERED)));
+    }
+
+    private boolean haveSameGenotypes(final Genotype g1, final Genotype g2) {
+        if ( g1 == null || g2 == null )
+            return false;
+
+        if ((g1.isCalled() && g2.isFiltered()) ||
+                (g2.isCalled() && g1.isFiltered()) ||
+                (g1.isFiltered() && g2.isFiltered() && EXCLUDE_FILTERED))
+            return false;
+
+        List<Allele> a1s = g1.getAlleles();
+        List<Allele> a2s = g2.getAlleles();
+        return (a1s.containsAll(a2s) && a2s.containsAll(a1s));
+    }
+    @Override
+    public Integer reduceInit() { return 0; }
+
+    @Override
+    public Integer reduce(Integer value, Integer sum) { return value + sum; }
+
+    @Override
+    public Integer treeReduce(Integer lhs, Integer rhs) {
+        return lhs + rhs;
+    }
+
+    public void onTraversalDone(Integer result) {
+        logger.info(result + " records processed.");
+    }
+
+
+
+    /**
+     * Helper method to subset a VC record, modifying some metadata stored in the INFO field (i.e. AN, AC, AF).
+     *
+     * @param vc       the VariantContext record to subset
+     * @param excludeNonVariants should we exclude sites that have AC=0 for any alternate alleles?
+     * @return the subsetted VariantContext
+     */
+    private VariantContext subsetRecord(final VariantContext vc, final boolean excludeNonVariants) {
+        if ( NO_SAMPLES_SPECIFIED || samples.isEmpty() )
+            return vc;
+
+        final VariantContext sub = vc.subContextFromSamples(samples, excludeNonVariants); // strip out the alternate alleles that aren't being used
+
+        final VariantContextBuilder builder = new VariantContextBuilder(sub);
+
+        // if there are fewer alternate alleles now in the selected VC, we need to fix the PL and AD values
+        GenotypesContext newGC = GATKVariantContextUtils.updatePLsAndAD(sub, vc);
+
+        // if we have fewer samples in the selected VC than in the original VC, we need to strip out the MLE tags
+        if ( vc.getNSamples() != sub.getNSamples() ) {
+            builder.rmAttribute(VCFConstants.MLE_ALLELE_COUNT_KEY);
+            builder.rmAttribute(VCFConstants.MLE_ALLELE_FREQUENCY_KEY);
+        }
+
+        // Remove a fraction of the genotypes if needed
+        if ( fractionGenotypes > 0 ){
+            final ArrayList<Genotype> genotypes = new ArrayList<>();
+            for ( Genotype genotype : newGC ) {
+                //Set genotype to no call if it falls in the fraction.
+                if(fractionGenotypes>0 && randomGenotypes.nextDouble()<fractionGenotypes){
+                    final List<Allele> alleles = Arrays.asList(Allele.NO_CALL, Allele.NO_CALL);
+                    genotypes.add(new GenotypeBuilder(genotype).alleles(alleles).noGQ().make());
+                }
+                else{
+                    genotypes.add(genotype);
+                }
+            }
+            newGC = GenotypesContext.create(genotypes);
+        }
+
+        builder.genotypes(newGC);
+
+        addAnnotations(builder, vc, sub.getSampleNames());
+
+        return builder.make();
+    }
+
+    /*
+     * Add annotations to the new VC
+     *
+     * @param builder     the new VC to annotate
+     * @param originalVC  the original VC
+     * @param selectedSampleNames the post-selection list of sample names
+     */
+    private void addAnnotations(final VariantContextBuilder builder, final VariantContext originalVC, final Set<String> selectedSampleNames) {
+        if ( fullyDecode ) return; // TODO -- annotations are broken with fully decoded data
+
+        if ( KEEP_ORIGINAL_CHR_COUNTS ) {
+            final int[] indexOfOriginalAlleleForNewAllele;
+            final List<Allele> newAlleles = builder.getAlleles();
+            final int numOriginalAlleles = originalVC.getNAlleles();
+
+            // if the alleles already match up, we can just copy the previous list of counts
+            if ( numOriginalAlleles == newAlleles.size() ) {
+                indexOfOriginalAlleleForNewAllele = null;
+            }
+            // otherwise we need to parse them and select out the correct ones
+            else {
+                indexOfOriginalAlleleForNewAllele = new int[newAlleles.size() - 1];
+                Arrays.fill(indexOfOriginalAlleleForNewAllele, -1);
+
+                // note that we don't care about the reference allele at position 0
+                for ( int newI = 1; newI < newAlleles.size(); newI++ ) {
+                    final Allele newAlt = newAlleles.get(newI);
+                    for ( int oldI = 0; oldI < numOriginalAlleles - 1; oldI++ ) {
+                        if ( newAlt.equals(originalVC.getAlternateAllele(oldI), false) ) {
+                            indexOfOriginalAlleleForNewAllele[newI - 1] = oldI;
+                            break;
+                        }
+                    }
+                }
+            }
+
+            if ( originalVC.hasAttribute(VCFConstants.ALLELE_COUNT_KEY) )
+                builder.attribute("AC_Orig", getReorderedAttributes(originalVC.getAttribute(VCFConstants.ALLELE_COUNT_KEY), indexOfOriginalAlleleForNewAllele));
+            if ( originalVC.hasAttribute(VCFConstants.ALLELE_FREQUENCY_KEY) )
+                builder.attribute("AF_Orig", getReorderedAttributes(originalVC.getAttribute(VCFConstants.ALLELE_FREQUENCY_KEY), indexOfOriginalAlleleForNewAllele));
+            if ( originalVC.hasAttribute(VCFConstants.ALLELE_NUMBER_KEY) )
+                builder.attribute("AN_Orig", originalVC.getAttribute(VCFConstants.ALLELE_NUMBER_KEY));
+        }
+
+        VariantContextUtils.calculateChromosomeCounts(builder, false);
+
+        boolean sawDP = false;
+        int depth = 0;
+        for ( final String sample : selectedSampleNames ) {
+            Genotype g = originalVC.getGenotype(sample);
+
+            if ( ! g.isFiltered() ) {
+                if ( g.hasDP() ) {
+                    depth += g.getDP();
+                    sawDP = true;
+                }
+            }
+        }
+
+        if ( sawDP )
+            builder.attribute("DP", depth);
+    }
+
+    /**
+     * Pulls out the appropriate tokens from the old ordering of an attribute to the new ordering
+     *
+     * @param attribute               the non-null attribute (from the INFO field)
+     * @param oldToNewIndexOrdering   the mapping from new to old ordering
+     * @return non-null Object attribute
+     */
+    private Object getReorderedAttributes(final Object attribute, final int[] oldToNewIndexOrdering) {
+        // if the ordering is the same, then just use the original attribute
+        if ( oldToNewIndexOrdering == null )
+            return attribute;
+
+        // break the original attributes into separate tokens; unfortunately, this means being smart about class types
+        final Object[] tokens;
+        if ( attribute.getClass().isArray() )
+            tokens = (Object[])attribute;
+        else if ( List.class.isAssignableFrom(attribute.getClass()) )
+            tokens = ((List)attribute).toArray();
+        else
+            tokens = attribute.toString().split(VCFConstants.INFO_FIELD_ARRAY_SEPARATOR);
+
+        final List<Object> result = new ArrayList<>();
+        for ( final int index : oldToNewIndexOrdering ) {
+            if ( index >= tokens.length )
+                throw new IllegalArgumentException("the old attribute has an incorrect number of elements: " + attribute);
+            result.add(tokens[index]);
+        }
+        return result;
+    }
+}
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/tools/walkers/variantutils/ValidateVariants.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/tools/walkers/variantutils/ValidateVariants.java
new file mode 100644
index 0000000..6b6e6ca
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/tools/walkers/variantutils/ValidateVariants.java
@@ -0,0 +1,301 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.tools.walkers.variantutils;
+
+import htsjdk.tribble.TribbleException;
+import org.broadinstitute.gatk.utils.commandline.Argument;
+import org.broadinstitute.gatk.utils.commandline.ArgumentCollection;
+import org.broadinstitute.gatk.engine.CommandLineGATK;
+import org.broadinstitute.gatk.engine.arguments.DbsnpArgumentCollection;
+import org.broadinstitute.gatk.engine.arguments.StandardVariantContextInputArgumentCollection;
+import org.broadinstitute.gatk.engine.contexts.AlignmentContext;
+import org.broadinstitute.gatk.engine.contexts.ReferenceContext;
+import org.broadinstitute.gatk.engine.refdata.RefMetaDataTracker;
+import org.broadinstitute.gatk.engine.walkers.Reference;
+import org.broadinstitute.gatk.engine.walkers.RodWalker;
+import org.broadinstitute.gatk.engine.walkers.Window;
+import org.broadinstitute.gatk.utils.exceptions.UserException;
+import org.broadinstitute.gatk.utils.help.DocumentedGATKFeature;
+import org.broadinstitute.gatk.utils.help.HelpConstants;
+import htsjdk.variant.variantcontext.Allele;
+import htsjdk.variant.variantcontext.VariantContext;
+import htsjdk.variant.vcf.VCFConstants;
+
+import java.io.File;
+import java.util.*;
+
+
+/**
+ * Validates a VCF file with an extra strict set of criteria.
+ *
+ * <p>
+ * ValidateVariants is a GATK tool that takes a VCF file and validates much of the information inside it.
+ * In addition to standard adherence to the VCF specification, this tool performs extra strict validations to ensure
+ * the information contained within the file is correct. These include:
+ * </p><p>
+ * <dl>
+ *   <dt>REF</dt><dd>the correctness of the reference base(s).</dd>
+ *   <dt>CHR_COUNTS</dt><dd>accuracy of AC & AN values.</dd>
+ *   <dt>IDS</dt><dd>tests against rsIDs when a dbSNP file is provided. Notice that for this one to work, you need
+ *    to provide a reference to the dbsnp variant containing file using the <code>--dbsnp</code> as show in examples below.</dd>
+ *   <dt>ALLELES</dt><dd>and that all alternate alleles are present in at least one sample.</dd>
+ * </dl>
+ *
+ * </p>
+ *
+ * <p>
+ *     By default it will apply all the strict validations unless you indicate which one you want you want to exclude
+ *     using <code>-Xtype|--validationTypeToExclude <<i>code</i>></code>, where <i>code</i> is one of the listed above. You
+ *     can exclude as many types as you want
+ * <p>
+ *     Yo can exclude all strict validations with the special code <code><b>ALL</b></code>. In this case the tool will only
+ *     test the adherence to the VCF specification.
+ * </p>
+ *
+ * <h3>Input</h3>
+ * <p>
+ * A variant set to validate using <code>-V</code> or <code>--variant</code> as shown below.
+ * </p>
+ *
+ * <h3>Examples</h3>
+ *
+ * <p>To perform VCF format and all strict validations: </p>
+ *
+ * <pre>
+ * java -Xmx2g -jar GenomeAnalysisTK.jar \
+ *   -R ref.fasta \
+ *   -T ValidateVariants \
+ *   --variant input.vcf \
+ *   --dbsnp dbsnp.vcf
+ * </pre>
+ *
+ * <p>To perform only VCF format tests:</p>
+ *
+ * <pre>
+ * java -Xmx2g -jar GenomeAnalysisTK.jar \
+ *   -R ref.fasta \
+ *   -T ValidateVariants \
+ *   <b>--validationTypeToExclude ALL</b> \
+ *   --variant input.vcf
+ * </pre>
+ *
+ * <p>To perform all validations except the strict <i>ALLELE</i> validation:</p>
+ *
+ * <pre>
+ * java -Xmx2g -jar GenomeAnalysisTK.jar \
+ *   -R ref.fasta \
+ *   -T ValidateVariants \
+ *   <b>--validationTypeToExclude ALLELES</b>
+ *   --variant input.vcf \
+ *   --dbsnp dbsnp.vcf
+ * </pre>
+ *
+ */
+ at DocumentedGATKFeature( groupName = HelpConstants.DOCS_CAT_VALIDATION, extraDocs = {CommandLineGATK.class} )
+ at Reference(window=@Window(start=0,stop=100))
+public class ValidateVariants extends RodWalker<Integer, Integer> {
+
+    @ArgumentCollection
+    protected StandardVariantContextInputArgumentCollection variantCollection = new StandardVariantContextInputArgumentCollection();
+
+    @ArgumentCollection
+    protected DbsnpArgumentCollection dbsnp = new DbsnpArgumentCollection();
+
+    public enum ValidationType {
+
+        /**
+         * Makes reference to all extra-strict tests listed below.
+         */
+        ALL,
+
+        /**
+         * Check whether the reported reference base in the VCF is the same as the corresponding base in the
+         * actual reference.
+         */
+        REF,
+
+        /**
+         * Checks whether the variant IDs exists, only relevant if the user indicates a DBSNP vcf file (see {@link #dbsnp}).
+         */
+        IDS,
+
+        /**
+         * Check whether all alternative alleles participate in a genotype call of at least on sample.
+         */
+        ALLELES,
+
+        /**
+         * Check that the AN and AC annotations are consistent with the number of calls, alleles and then number these
+         * are called across samples.
+         */
+        CHR_COUNTS;
+
+        /**
+         * Unmodifiable set of concrete validation types.
+         *
+         * <p>These are all types except {@link #ALL}.</p>
+         */
+        public final static Set<ValidationType> CONCRETE_TYPES;
+
+        static {
+            final Set<ValidationType> cts = new LinkedHashSet<>(values().length - 1);
+            for (final ValidationType v : values())
+                if (v != ALL)
+                    cts.add(v);
+            CONCRETE_TYPES = Collections.unmodifiableSet(cts);
+        }
+    }
+
+    @Argument(fullName = "validationTypeToExclude", shortName = "Xtype", doc = "which validation type to exclude from a full strict validation", required = false)
+    protected List<ValidationType> excludeTypes = new ArrayList<>();
+
+    /**
+     * By default, even filtered records are validated.
+     */
+    @Argument(fullName = "doNotValidateFilteredRecords", shortName = "doNotValidateFilteredRecords", doc = "skip validation on filtered records", required = false)
+    protected Boolean DO_NOT_VALIDATE_FILTERED = false;
+
+    @Argument(fullName = "warnOnErrors", shortName = "warnOnErrors", doc = "just emit warnings on errors instead of terminating the run at the first instance", required = false)
+    protected Boolean WARN_ON_ERROR = false;
+
+    private long numErrors = 0;
+
+    private File file = null;
+
+    /**
+     * Contains final set of validation to apply.
+     */
+    private Collection<ValidationType> validationTypes;
+
+    public void initialize() {
+        file = new File(variantCollection.variants.getSource());
+        validationTypes = calculateValidationTypesToApply(excludeTypes);
+    }
+
+    public Integer map(RefMetaDataTracker tracker, ReferenceContext ref, AlignmentContext context) {
+        if ( tracker == null )
+            return 0;
+
+        Collection<VariantContext> VCs = tracker.getValues(variantCollection.variants, context.getLocation());
+        for ( VariantContext vc : VCs )
+            validate(vc, tracker, ref);
+
+        return VCs.size();
+    }
+
+    public Integer reduceInit() { return 0; }
+
+    public Integer reduce(Integer value, Integer sum) { return sum+value; }
+
+    public void onTraversalDone(Integer result) {
+        if ( numErrors == 0 )
+            System.out.println("Successfully validated the input file.  Checked " + result + " records with no failures.");
+        else
+            System.out.println("Found " + numErrors + " records with failures.");                     
+    }
+
+    private void validate(VariantContext vc, RefMetaDataTracker tracker, ReferenceContext ref) {
+        if ( DO_NOT_VALIDATE_FILTERED && vc.isFiltered() )
+            return;
+
+        // get the true reference allele
+        final Allele reportedRefAllele = vc.getReference();
+        final int refLength = reportedRefAllele.length();
+        if ( refLength > 100 ) {
+            logger.info(String.format("Reference allele is too long (%d) at position %s:%d; skipping that record.", refLength, vc.getChr(), vc.getStart()));
+            return;
+        }
+
+        final byte[] observedRefBases = new byte[refLength];
+        System.arraycopy(ref.getBases(), 0, observedRefBases, 0, refLength);
+        final Allele observedRefAllele = Allele.create(observedRefBases);
+
+        // get the RS IDs
+        Set<String> rsIDs = null;
+        if ( tracker.hasValues(dbsnp.dbsnp) ) {
+            rsIDs = new HashSet<String>();
+            for ( VariantContext rsID : tracker.getValues(dbsnp.dbsnp, ref.getLocus()) )
+                rsIDs.addAll(Arrays.asList(rsID.getID().split(VCFConstants.ID_FIELD_SEPARATOR)));
+        }
+
+        try {
+            for (final ValidationType t : validationTypes)
+                applyValidationType(vc, reportedRefAllele, observedRefAllele, rsIDs, t);
+        } catch (TribbleException e) {
+            if ( WARN_ON_ERROR ) {
+                numErrors++;
+                logger.warn("***** " + e.getMessage() + " *****");
+            } else {
+                throw new UserException.FailsStrictValidation(file, e.getMessage());
+            }
+        }
+    }
+
+    /**
+     * Given the validation type and exclusion type, calculate the final set of type to validate.
+     * @param excludeTypes types to exclude.
+     *
+     * @throws UserException.BadArgumentValue if the user combines any validation type except 'ALL' and some exclude types.
+     *
+     * @return never {@code null} but perhaps an empty set.
+     */
+    private Collection<ValidationType> calculateValidationTypesToApply(final List<ValidationType> excludeTypes) {
+        if (excludeTypes.size() == 0)
+            return Collections.singleton(ValidationType.ALL);
+        final Set<ValidationType> excludeTypeSet = new LinkedHashSet<>(excludeTypes);
+        if (excludeTypes.size() != excludeTypeSet.size())
+            logger.warn("found repeat redundant validation types listed using the --validationTypeToExclude argument");
+        if (excludeTypeSet.contains(ValidationType.ALL)) {
+            if (excludeTypeSet.size() > 1)
+                logger.warn("found ALL in the --validationTypeToExclude list together with other concrete type exclusions that are redundant");
+            return Collections.emptyList();
+        } else {
+           final Set<ValidationType> result = new LinkedHashSet<>(ValidationType.CONCRETE_TYPES);
+           result.removeAll(excludeTypeSet);
+           return result;
+        }
+    }
+
+    private void applyValidationType(VariantContext vc, Allele reportedRefAllele, Allele observedRefAllele, Set<String> rsIDs, ValidationType t) {
+        switch( t ) {
+            case ALL:
+                vc.extraStrictValidation(reportedRefAllele, observedRefAllele, rsIDs);
+                break;
+            case REF:
+                vc.validateReferenceBases(reportedRefAllele, observedRefAllele);
+                break;
+            case IDS:
+                vc.validateRSIDs(rsIDs);
+                break;
+            case ALLELES:
+                vc.validateAlternateAlleles();
+                break;
+            case CHR_COUNTS:
+                vc.validateChromosomeCounts();
+                break;
+        }
+    }
+}
\ No newline at end of file
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/tools/walkers/variantutils/VariantValidationAssessor.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/tools/walkers/variantutils/VariantValidationAssessor.java
new file mode 100644
index 0000000..9031bf7
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/tools/walkers/variantutils/VariantValidationAssessor.java
@@ -0,0 +1,304 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.tools.walkers.variantutils;
+
+import org.broadinstitute.gatk.engine.walkers.Reference;
+import org.broadinstitute.gatk.engine.walkers.RodWalker;
+import org.broadinstitute.gatk.engine.walkers.Window;
+import org.broadinstitute.gatk.utils.commandline.*;
+import org.broadinstitute.gatk.engine.CommandLineGATK;
+import org.broadinstitute.gatk.engine.arguments.StandardVariantContextInputArgumentCollection;
+import org.broadinstitute.gatk.engine.contexts.AlignmentContext;
+import org.broadinstitute.gatk.engine.contexts.ReferenceContext;
+import org.broadinstitute.gatk.engine.refdata.RefMetaDataTracker;
+import org.broadinstitute.gatk.utils.QualityUtils;
+import org.broadinstitute.gatk.utils.SampleUtils;
+import org.broadinstitute.gatk.utils.help.HelpConstants;
+import org.broadinstitute.gatk.utils.variant.GATKVCFUtils;
+import org.broadinstitute.gatk.utils.variant.GATKVariantContextUtils;
+import htsjdk.variant.vcf.*;
+import org.broadinstitute.gatk.utils.help.DocumentedGATKFeature;
+import htsjdk.variant.variantcontext.writer.VariantContextWriter;
+import htsjdk.variant.variantcontext.Allele;
+import htsjdk.variant.variantcontext.VariantContext;
+import htsjdk.variant.variantcontext.VariantContextBuilder;
+
+import java.util.*;
+
+/**
+ * Annotates a validation (from Sequenom for example) VCF with QC metrics (HW-equilibrium, % failed probes)
+ *
+ * <p>
+ * The Variant Validation Assessor is a tool for vetting/assessing validation data (containing genotypes).
+ * The tool produces a VCF that is annotated with information pertaining to plate quality control and by
+ * default is soft-filtered by high no-call rate or low Hardy-Weinberg probability.
+ * If you have .ped files, please first convert them to VCF format.
+ *
+ * <h3>Input</h3>
+ * <p>
+ * A validation VCF to annotate.
+ * </p>
+ *
+ * <h3>Output</h3>
+ * <p>
+ * An annotated VCF.  Additionally, a table like the following will be output:
+ * <pre>
+ *     Total number of samples assayed:                  185
+ *     Total number of records processed:                152
+ *     Number of Hardy-Weinberg violations:              34 (22%)
+ *     Number of no-call violations:                     12 (7%)
+ *     Number of homozygous variant violations:          0 (0%)
+ *     Number of records passing all filters:            106 (69%)
+ *     Number of passing records that are polymorphic:   98 (92%)
+ * </pre>
+ * </p>
+ *
+ * <h3>Examples</h3>
+ * <pre>
+ * java -Xmx2g -jar GenomeAnalysisTK.jar \
+ *   -R ref.fasta \
+ *   -T VariantValidationAssessor \
+ *   --variant input.vcf \
+ *   -o output.vcf
+ * </pre>
+ *
+ */
+ at DocumentedGATKFeature( groupName = HelpConstants.DOCS_CAT_VALIDATION, extraDocs = {CommandLineGATK.class} )
+ at Reference(window=@Window(start=0,stop=40))
+public class VariantValidationAssessor extends RodWalker<VariantContext,Integer> {
+
+    @ArgumentCollection
+    protected StandardVariantContextInputArgumentCollection variantCollection = new StandardVariantContextInputArgumentCollection();
+
+    @Output(doc="File to which variants should be written")
+    protected VariantContextWriter vcfwriter = null;
+
+    @Argument(fullName="maxHardy", doc="Maximum phred-scaled Hardy-Weinberg violation pvalue to consider an assay valid", required=false)
+    protected double maxHardy = 20.0;
+
+    /**
+     * To disable, set to a value greater than 1.
+     */
+    @Argument(fullName="maxNoCall", doc="Maximum no-call rate (as a fraction) to consider an assay valid", required=false)
+    protected double maxNoCall = 0.05;
+
+    /**
+     * To disable, set to a value greater than 1.
+     */
+    @Argument(fullName="maxHomVar", doc="Maximum homozygous variant rate (as a fraction) to consider an assay valid", required=false)
+    protected double maxHomNonref = 1.1;
+
+    //@Argument(fullName="populationFile", shortName="populations", doc="A tab-delimited file relating individuals to populations,"+
+    //          "used for smart Hardy-Weinberg annotation",required = false)
+    //private File popFile = null;
+
+    // sample names
+    private TreeSet<String> sampleNames = null;
+
+    // variant context records
+    private ArrayList<VariantContext> records = new ArrayList<VariantContext>();
+
+    // statistics
+    private int numRecords = 0;
+    private int numHWViolations = 0;
+    private int numNoCallViolations = 0;
+    private int numHomVarViolations = 0;
+    private int numTrueVariants = 0;
+
+    //private HashMap<String,String> samplesToPopulation;
+
+    public void initialize() {
+        //if ( popFile != null ) {
+        //    samplesToPopulation = parsePopulationFile(popFile);
+        //}
+    }
+
+    public Integer reduceInit() {
+        return 0;
+    }
+
+    public VariantContext map(RefMetaDataTracker tracker, ReferenceContext ref, AlignmentContext context) {
+        if ( tracker == null )
+            return null;
+
+        VariantContext vc = tracker.getFirstValue(variantCollection.variants, ref.getLocus());
+        // ignore places where we don't have a variant
+        if ( vc == null )
+            return null;
+
+        if ( sampleNames == null )
+            sampleNames = new TreeSet<String>(vc.getSampleNames());        
+
+        return addVariantInformationToCall(vc);
+    }
+
+    public Integer reduce(VariantContext call, Integer numVariants) {
+        if ( call != null ) {
+            numVariants++;
+            records.add(call);
+        }
+        return numVariants;                        
+    }
+
+    public void onTraversalDone(Integer finalReduce) {
+        final List<String> inputNames = Arrays.asList(variantCollection.variants.getName());
+
+        // setup the header fields
+        Set<VCFHeaderLine> hInfo = new HashSet<VCFHeaderLine>();
+        hInfo.addAll(GATKVCFUtils.getHeaderFields(getToolkit(), inputNames));
+
+        // set up the info and filter headers
+        hInfo.add(new VCFInfoHeaderLine("NoCallPct", 1, VCFHeaderLineType.Float, "Percent of no-calls"));
+        hInfo.add(new VCFInfoHeaderLine("HomRefPct", 1, VCFHeaderLineType.Float, "Percent of homozygous reference genotypes"));
+        hInfo.add(new VCFInfoHeaderLine("HetPct", 1, VCFHeaderLineType.Float, "Percent of heterozygous genotypes"));
+        hInfo.add(new VCFInfoHeaderLine("HomVarPct", 1, VCFHeaderLineType.Float, "Percent homozygous variant genotypes"));
+        hInfo.add(new VCFInfoHeaderLine("HW", 1, VCFHeaderLineType.Float, "Phred-scaled Hardy-Weinberg violation p-value"));
+        hInfo.add(VCFStandardHeaderLines.getInfoLine(VCFConstants.ALLELE_COUNT_KEY));
+        hInfo.add(VCFStandardHeaderLines.getInfoLine(VCFConstants.ALLELE_NUMBER_KEY));
+        hInfo.add(new VCFFilterHeaderLine("HardyWeinbergViolation", "The validation is in Hardy-Weinberg violation"));
+        hInfo.add(new VCFFilterHeaderLine("HighNoCallRate", "The validation no-call rate is too high"));
+        hInfo.add(new VCFFilterHeaderLine("TooManyHomVars", "The validation homozygous variant rate is too high"));
+
+        // print out (and add to headers) the validation metrics
+        System.out.println(String.format("Total number of samples assayed:\t\t\t%d", sampleNames.size()));
+        hInfo.add(new VCFHeaderLine("ValidationMetrics_SamplesAssayed", String.format("%d", sampleNames.size())));
+        System.out.println(String.format("Total number of records processed:\t\t\t%d", numRecords));
+        hInfo.add(new VCFHeaderLine("ValidationMetrics_RecordsProcessed", String.format("%d", numRecords)));
+        if ( numRecords > 0 ) {
+            System.out.println(String.format("Number of Hardy-Weinberg violations:\t\t\t%d (%d%%)", numHWViolations, 100*numHWViolations/numRecords));
+            hInfo.add(new VCFHeaderLine("ValidationMetrics_HardyWeinbergViolations", String.format("\"%d (%d%%)\"", numHWViolations, 100*numHWViolations/numRecords)));
+            System.out.println(String.format("Number of no-call violations:\t\t\t\t%d (%d%%)", numNoCallViolations, 100*numNoCallViolations/numRecords));
+            hInfo.add(new VCFHeaderLine("ValidationMetrics_NoCallViolations", String.format("\"%d (%d%%)\"", numNoCallViolations, 100*numNoCallViolations/numRecords)));
+            System.out.println(String.format("Number of homozygous variant violations:\t\t%d (%d%%)", numHomVarViolations, 100*numHomVarViolations/numRecords));
+            hInfo.add(new VCFHeaderLine("ValidationMetrics_HomVarViolations", String.format("\"%d (%d%%)\"", numHomVarViolations, 100*numHomVarViolations/numRecords)));
+            int goodRecords = numRecords - numHWViolations - numNoCallViolations - numHomVarViolations;
+            System.out.println(String.format("Number of records passing all filters:\t\t\t%d (%d%%)", goodRecords, 100*goodRecords/numRecords));
+            hInfo.add(new VCFHeaderLine("ValidationMetrics_RecordsPassingFilters", String.format("\"%d (%d%%)\"", goodRecords, 100*goodRecords/numRecords)));
+            if ( goodRecords > 0 ) {
+                System.out.println(String.format("Number of passing records that are polymorphic:\t\t%d (%d%%)", numTrueVariants, 100*numTrueVariants/goodRecords));
+                hInfo.add(new VCFHeaderLine("ValidationMetrics_PolymorphicPassingRecords", String.format("\"%d (%d%%)\"", numTrueVariants, 100*numTrueVariants/goodRecords)));
+            }
+        }
+        
+        vcfwriter.writeHeader(new VCFHeader(hInfo, SampleUtils.getUniqueSamplesFromRods(getToolkit(), inputNames)));
+
+        for ( VariantContext record : records )
+            vcfwriter.add(record);
+    }
+
+
+    private VariantContext addVariantInformationToCall(VariantContext vContext) {
+
+        // check possible filters
+        double hwPvalue = hardyWeinbergCalculation(vContext);
+        double hwScore = Math.abs(QualityUtils.phredScaleErrorRate(hwPvalue));
+        double noCallProp = (double)vContext.getNoCallCount() / (double)vContext.getNSamples();
+        double homRefProp = (double)vContext.getHomRefCount() / (double)vContext.getNSamples();
+        double hetProp = (double)vContext.getHetCount() / (double)vContext.getNSamples();
+        double homVarProp = (double)vContext.getHomVarCount() / (double)vContext.getNSamples();
+
+        boolean isViolation = false;
+        Set<String> filters = new HashSet<String>();
+        if ( noCallProp > maxNoCall ) {
+            filters.add("HighNoCallRate");
+            numNoCallViolations++;
+            isViolation = true;
+        } else if ( hwScore > maxHardy ) {
+            filters.add("HardyWeinbergViolation");
+            numHWViolations++;
+            isViolation = true;
+        } else if ( homVarProp > maxHomNonref) {
+            filters.add("TooManyHomVars");
+            numHomVarViolations++;
+            isViolation = true;
+        }
+
+        VariantContextBuilder builder = new VariantContextBuilder(vContext).filters(filters);
+        numRecords++;
+
+        // add the info fields
+        builder.attribute("NoCallPct", String.format("%.1f", 100.0 * noCallProp));
+        builder.attribute("HomRefPct", String.format("%.1f", 100.0 * homRefProp));
+        builder.attribute("HomVarPct", String.format("%.1f", 100.0 * homVarProp));
+        builder.attribute("HetPct", String.format("%.1f", 100.0 * hetProp));
+        builder.attribute("HW", String.format("%.2f", hwScore));
+        Collection<Allele> altAlleles = vContext.getAlternateAlleles();
+        int altAlleleCount = altAlleles.size() == 0 ? 0 : vContext.getCalledChrCount(altAlleles.iterator().next());
+        if ( !isViolation && altAlleleCount > 0 )
+            numTrueVariants++;
+        builder.attribute(VCFConstants.ALLELE_COUNT_KEY, String.format("%d", altAlleleCount));
+        builder.attribute(VCFConstants.ALLELE_NUMBER_KEY, String.format("%d", vContext.getCalledChrCount()));
+
+        return builder.make();
+    }
+
+    private double hardyWeinbergCalculation(VariantContext vc) {
+        //if ( popFile != null ) {
+        //    throw new GATKException("We still need to implement this!");
+        //} else {
+        return GATKVariantContextUtils.computeHardyWeinbergPvalue(vc);
+        //}
+    }
+
+    // TODO -- REWRITE THIS TO WORK WITH VARIANT CONTEXT
+    /******
+
+    private String smartHardy(ReferenceContext ref, VCFRecord rec) {
+        HashMap<String,ArrayList<Genotype>> genotypesByPopulation = new HashMap<String,ArrayList<Genotype>>(10);
+        HashMap<String,String> hardyWeinbergByPopulation = new HashMap<String,String>(10);
+
+        for ( String population : samplesToPopulation.values() ) {
+            genotypesByPopulation.put(population,new ArrayList<Genotype>());
+        }
+
+        //for ( String name : sampleNames ) {
+        //    String pop = samplesToPopulation.get(name);
+        //    if ( rec.getGenotype(name) != null ) {
+        //        genotypesByPopulation.get(pop).add(rec.getGenotype(name));
+        //    }
+        //}
+
+        for ( String population : samplesToPopulation.values() ) {
+            VCFVariationCall v = new VCFVariationCall(ref.getBase(),ref.getLocus(),VCFVariationCall.VARIANT_TYPE.SNP);
+            v.setGenotypeCalls(genotypesByPopulation.get(population));
+            hardyWeinbergByPopulation.put(population,HWCalc.annotate(null,ref,null,v));
+        }
+
+        return smartHardyString(hardyWeinbergByPopulation);
+    }
+
+    private String smartHardyString(HashMap<String,String> hwByPop) {
+        // for now just return the maximum:
+        int maxH = -100;
+        for ( String pop : samplesToPopulation.values() ) {
+            maxH = Integer.parseInt(hwByPop.get(pop)) > maxH ? Integer.parseInt(hwByPop.get(pop)) : maxH;
+        }
+
+        return String.format("%s",maxH);
+    }
+
+    *********/
+}
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/tools/walkers/variantutils/VariantsToAllelicPrimitives.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/tools/walkers/variantutils/VariantsToAllelicPrimitives.java
new file mode 100644
index 0000000..1f7b20c
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/tools/walkers/variantutils/VariantsToAllelicPrimitives.java
@@ -0,0 +1,140 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.tools.walkers.variantutils;
+
+import com.google.java.contract.Requires;
+import org.broadinstitute.gatk.utils.commandline.ArgumentCollection;
+import org.broadinstitute.gatk.utils.commandline.Output;
+import org.broadinstitute.gatk.engine.CommandLineGATK;
+import org.broadinstitute.gatk.engine.arguments.StandardVariantContextInputArgumentCollection;
+import org.broadinstitute.gatk.engine.contexts.AlignmentContext;
+import org.broadinstitute.gatk.engine.contexts.ReferenceContext;
+import org.broadinstitute.gatk.engine.refdata.RefMetaDataTracker;
+import org.broadinstitute.gatk.engine.walkers.RodWalker;
+import org.broadinstitute.gatk.utils.SampleUtils;
+import org.broadinstitute.gatk.utils.help.DocumentedGATKFeature;
+import org.broadinstitute.gatk.utils.help.HelpConstants;
+import org.broadinstitute.gatk.utils.variant.GATKVCFUtils;
+import org.broadinstitute.gatk.utils.variant.GATKVariantContextUtils;
+import htsjdk.variant.variantcontext.*;
+import htsjdk.variant.variantcontext.writer.VariantContextWriter;
+import htsjdk.variant.variantcontext.writer.VariantContextWriterFactory;
+import htsjdk.variant.vcf.VCFHeader;
+import htsjdk.variant.vcf.VCFHeaderLine;
+
+import java.util.*;
+
+/**
+ * Takes alleles from a variants file and breaks them up (if possible) into more basic/primitive alleles.
+ *
+ * <p>
+ * For now this tool modifies only multi-nucleotide polymorphisms (MNPs) and leaves SNPs, indels, and complex substitutions as is,
+ * although one day it may be extended to handle the complex substitution case.
+ *
+ * This tool will take an MNP (e.g. ACCCA -> TCCCG) and break it up into separate records for each component part (A-T and A->G).
+ *
+ * Note that this tool modifies only bi-allelic variants.
+ *
+ * <h2>Input</h2>
+ * <p>
+ * A variant set with any type of alleles.
+ * </p>
+ *
+ * <h2>Output</h2>
+ * <p>
+ * A VCF with alleles broken into primitive types.
+ * </p>
+ *
+ * <h2>Examples</h2>
+ * <pre>
+ * java -Xmx2g -jar GenomeAnalysisTK.jar \
+ *   -R ref.fasta \
+ *   -T VariantsToAllelicPrimitives \
+ *   --variant input.vcf \
+ *   -o output.vcf
+ * </pre>
+ *
+ */
+ at DocumentedGATKFeature( groupName = HelpConstants.DOCS_CAT_VARMANIP, extraDocs = {CommandLineGATK.class} )
+public class VariantsToAllelicPrimitives extends RodWalker<Integer, Integer> {
+
+    @ArgumentCollection
+    protected StandardVariantContextInputArgumentCollection variantCollection = new StandardVariantContextInputArgumentCollection();
+
+    @Output(doc="File to which variants should be written")
+    protected VariantContextWriter baseWriter = null;
+
+    private VariantContextWriter vcfWriter;
+
+    public void initialize() {
+        final String trackName = variantCollection.variants.getName();
+        final Set<String> samples = SampleUtils.getSampleListWithVCFHeader(getToolkit(), Arrays.asList(trackName));
+
+        final Map<String, VCFHeader> vcfHeaders = GATKVCFUtils.getVCFHeadersFromRods(getToolkit(), Arrays.asList(trackName));
+        final Set<VCFHeaderLine> headerLines = vcfHeaders.get(trackName).getMetaDataInSortedOrder();
+
+        baseWriter.writeHeader(new VCFHeader(headerLines, samples));
+
+        vcfWriter = VariantContextWriterFactory.sortOnTheFly(baseWriter, 200);
+    }
+
+    public Integer map(RefMetaDataTracker tracker, ReferenceContext ref, AlignmentContext context) {
+        if ( tracker == null )
+            return 0;
+
+        final Collection<VariantContext> VCs = tracker.getValues(variantCollection.variants, context.getLocation());
+
+        int changedSites = 0;
+        for ( final VariantContext vc : VCs )
+            changedSites += writeVariants(vc);
+
+        return changedSites;
+    }
+
+    public Integer reduceInit() { return 0; }
+
+    public Integer reduce(Integer value, Integer sum) {
+        return sum + value;
+    }
+
+    public void onTraversalDone(Integer result) {
+        System.out.println(result + " MNPs were broken up into primitives");
+        vcfWriter.close();
+    }
+
+    @Requires("vc != null")
+    private int writeVariants(final VariantContext vc) {
+        // for now, we modify only bi-allelic MNPs; update docs above if this changes
+        if ( vc.isBiallelic() && vc.isMNP() ) {
+            for ( final VariantContext splitVC : GATKVariantContextUtils.splitIntoPrimitiveAlleles(vc) )
+                vcfWriter.add(splitVC);
+            return 1;
+        } else {
+            vcfWriter.add(vc);
+            return 0;
+        }
+    }
+}
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/tools/walkers/variantutils/VariantsToBinaryPed.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/tools/walkers/variantutils/VariantsToBinaryPed.java
new file mode 100644
index 0000000..b51349a
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/tools/walkers/variantutils/VariantsToBinaryPed.java
@@ -0,0 +1,550 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.tools.walkers.variantutils;
+
+import htsjdk.tribble.TribbleException;
+import org.broadinstitute.gatk.utils.commandline.*;
+import org.broadinstitute.gatk.engine.CommandLineGATK;
+import org.broadinstitute.gatk.engine.arguments.DbsnpArgumentCollection;
+import org.broadinstitute.gatk.engine.arguments.StandardVariantContextInputArgumentCollection;
+import org.broadinstitute.gatk.engine.contexts.AlignmentContext;
+import org.broadinstitute.gatk.engine.contexts.ReferenceContext;
+import org.broadinstitute.gatk.engine.refdata.RefMetaDataTracker;
+import org.broadinstitute.gatk.engine.walkers.Reference;
+import org.broadinstitute.gatk.engine.walkers.RodWalker;
+import org.broadinstitute.gatk.engine.walkers.Window;
+import org.broadinstitute.gatk.utils.help.HelpConstants;
+import org.broadinstitute.gatk.utils.QualityUtils;
+import org.broadinstitute.gatk.utils.variant.GATKVCFUtils;
+import htsjdk.variant.vcf.VCFHeader;
+import org.broadinstitute.gatk.utils.exceptions.ReviewedGATKException;
+import org.broadinstitute.gatk.utils.exceptions.UserException;
+import org.broadinstitute.gatk.utils.help.DocumentedGATKFeature;
+import org.broadinstitute.gatk.utils.text.XReadLines;
+import htsjdk.variant.variantcontext.*;
+
+import java.io.*;
+import java.util.*;
+
+/**
+ * Converts a VCF file to a binary plink Ped file (.bed/.bim/.fam)
+ */
+ at DocumentedGATKFeature( groupName = HelpConstants.DOCS_CAT_VARMANIP, extraDocs = {CommandLineGATK.class} )
+ at Reference(window=@Window(start=0,stop=100))
+public class VariantsToBinaryPed extends RodWalker<Integer,Integer> {
+    @ArgumentCollection
+    protected StandardVariantContextInputArgumentCollection variantCollection = new StandardVariantContextInputArgumentCollection();
+
+    @ArgumentCollection
+    protected DbsnpArgumentCollection dbsnp = new DbsnpArgumentCollection();
+
+    /**
+     * The metaData file can take two formats, the first of which is the first 6 lines of the standard ped file. This
+     * is what Plink describes as a fam file. An example fam file is (note that there is no header):
+     * <p><p>
+     * CEUTrio NA12878 NA12891 NA12892 2 -9</p><p>
+     * CEUTrio NA12891 UNKN1 UNKN2 2 -9</p><p>
+     * CEUTrio NA12892 UNKN3 UNKN4 1 -9</p><p>
+     * </p>
+     * where the entries are (FamilyID IndividualID DadID MomID Phenotype Sex)
+     * <p>
+     * An alternate format is a two-column key-value file
+     * </p><p><p>
+     * NA12878        fid=CEUTrio;dad=NA12891;mom=NA12892;sex=2;phenotype=-9</p><p>
+     * NA12891        fid=CEUTrio;sex=2;phenotype=-9</p><p>
+     * NA12892        fid=CEUTrio;sex=1;phenotype=-9</p><p>
+     * </p><p>
+     * wherein unknown parents needn't be specified. The columns are the individual ID, and a list of key-value pairs.
+     * </p><p>
+     * Regardless of which file is specified, the walker will output a .fam file alongside the bed file. If the
+     * command line has "-md [name].fam", the fam file will be subset and reordered to match the sample content and ordering
+     * of the VCF. However, if a metadata file of the alternate format is passed by "-md [name].txt", the walker will
+     * construct a formatted .fam file from the data.
+     * </p>
+     */
+    @Input(shortName="m",fullName = "metaData",required=true,doc="Sample metadata file. You may specify a .fam file " +
+            "(in which case it will be copied to the file you provide as fam output).")
+    File metaDataFile;
+
+    @Input(shortName="mode",fullName="outputMode",required=false,doc="The output file mode (SNP major or individual major)")
+    OutputMode mode = OutputMode.INDIVIDUAL_MAJOR;
+
+    @Output(shortName="bed",fullName = "bed",required=true,doc="output ped file")
+    PrintStream outBed;
+
+    @Output(shortName="bim",fullName="bim",required=true,doc="output map file")
+    PrintStream outBim;
+
+    @Output(shortName="fam",fullName="fam",required=true,doc="output fam file")
+    PrintStream outFam;
+
+    @Argument(shortName="mgq",fullName="minGenotypeQuality",required=true,doc="If genotype quality is lower than this value, output NO_CALL")
+    int minGenotypeQuality = 0;
+
+    @Argument(fullName="majorAlleleFirst",required=false,doc="Sets the major allele to be 'reference' for the bim file, rather than the ref allele")
+    boolean majorAlleleFirst = false;
+
+    @Argument(fullName="checkAlternateAlleles",required=false,doc="Checks that alternate alleles actually appear in samples, erroring out if they do not")
+    boolean checkAlternateAlleles = false;
+
+    enum OutputMode { INDIVIDUAL_MAJOR,SNP_MAJOR }
+
+    private static double APPROX_CM_PER_BP = 1000000.0/750000.0;
+
+    private static final byte HOM_REF = 0x0;
+    private static final byte HOM_VAR = 0x3;
+    private static final byte HET =     0x2;
+    private static final byte NO_CALL = 0x1;
+
+    private static final int BUFFER_SIZE = 1000; //4k genotypes per sample = Nmb for N*1000 samples
+
+    private static final String PLINK_DELETION_MARKER = "-";
+
+    // note that HET and NO_CALL are flipped from the documentation: that's because
+    // plink actually reads these in backwards; and we want to use a shift operator
+    // to put these in the appropriate location
+
+    private Map<String,OutputStream> printMap = new HashMap<String,OutputStream>();
+    private Map<String,File> tempFiles = new HashMap<String,File>();
+    private Map<String,byte[]> genotypeBuffer = new HashMap<String,byte[]>();
+    private int genotypeCount = 0;
+    private int byteCount = 0;
+    private List<String> famOrder = new ArrayList<String>();
+    private long totalByteCount = 0l;
+    private long totalGenotypeCount = 0l;
+
+    public void initialize() {
+        writeBedHeader();
+        Map<String,Map<String,String>> sampleMetaValues = parseMetaData();
+        // create temporary output streams and buffers
+
+        // family ID, individual ID, Paternal ID, Maternal ID, Sex, Phenotype
+        int dummyID = 0; // increments for dummy parental and family IDs used
+        // want to be especially careful to maintain order here
+        Map<String,VCFHeader> headers = GATKVCFUtils.getVCFHeadersFromRods(getToolkit());
+        for ( Map.Entry<String,VCFHeader> header : headers.entrySet() ) {
+            if ( ! header.getKey().equals(variantCollection.variants.getName()) && ! metaDataFile.getAbsolutePath().endsWith(".fam") ) {
+                continue;
+            }
+            for ( String sample : header.getValue().getGenotypeSamples() ) {
+                if ( ! metaDataFile.getAbsolutePath().endsWith(".fam") ) {
+                    Map<String,String> mVals = sampleMetaValues.get(sample);
+                    if ( mVals == null ) {
+                        throw new UserException("No metadata provided for sample "+sample);
+                    }
+                    if ( ! mVals.containsKey("phenotype") ) {
+                        throw new UserException("No phenotype data provided for sample "+sample);
+                    }
+                    String fid = mVals.containsKey("fid") ? mVals.get("fid") : String.format("dummy_%d",++dummyID);
+                    String pid = mVals.containsKey("dad") ? mVals.get("dad") : String.format("dummy_%d",++dummyID);
+                    String mid = mVals.containsKey("mom") ? mVals.get("mom") : String.format("dummy_%d",++dummyID);
+                    String sex = mVals.containsKey("sex") ? mVals.get("sex") : "3";
+                    String pheno = mVals.get("phenotype");
+                    outFam.printf("%s\t%s\t%s\t%s\t%s\t%s%n",fid,sample,pid,mid,sex,pheno);
+                } else {
+                    // even if a fam file is input, we can't diverge the bed file from the fam file, which
+                    // could lead to a malformed plink trio. Fail fast if there's any extra sample in the VCF.
+                    if ( ! sampleMetaValues.containsKey(sample) ) {
+                        throw new UserException("No metadata provided for sample "+sample);
+                    }
+                    Map<String,String> mVals = sampleMetaValues.get(sample);
+                    String fid = mVals.containsKey("fid") ? mVals.get("fid") : String.format("dummy_%d",++dummyID);
+                    String pid = mVals.containsKey("dad") ? mVals.get("dad") : String.format("dummy_%d",++dummyID);
+                    String mid = mVals.containsKey("mom") ? mVals.get("mom") : String.format("dummy_%d",++dummyID);
+                    String sex = mVals.containsKey("sex") ? mVals.get("sex") : "3";
+                    String pheno = mVals.containsKey("phenotype") ? mVals.get("phenotype") : "-1";
+                    outFam.printf("%s\t%s\t%s\t%s\t%s\t%s%n",fid,sample,pid,mid,sex,pheno);
+                }
+                if ( mode == OutputMode.INDIVIDUAL_MAJOR ) {
+                    // only need to instantiate the files and buffers if in individual major.
+                    // Cut down on memory.
+                    try {
+                        File temp = File.createTempFile("VariantsToBPed_"+sample, ".tmp");
+                        temp.deleteOnExit();
+                        printMap.put(sample,new PrintStream(temp));
+                        tempFiles.put(sample,temp);
+                    } catch (IOException e) {
+                        throw new ReviewedGATKException("Error creating temporary file",e);
+                    }
+                    genotypeBuffer.put(sample,new byte[BUFFER_SIZE]);
+                }
+                famOrder.add(sample);
+            }
+        }
+    }
+
+    public Integer map(RefMetaDataTracker tracker, ReferenceContext ref, AlignmentContext context) {
+        if ( tracker == null ) {
+            return 0;
+        }
+
+        VariantContext vc = tracker.getFirstValue(variantCollection.variants,context.getLocation());
+        if ( vc == null || vc.isFiltered() || ! vc.isBiallelic() ) {
+            return 0;
+        }
+        try {
+            validateVariantSite(vc,ref,context);
+        } catch (TribbleException e) {
+            throw new UserException("Input VCF file is invalid; we cannot guarantee the resulting ped file. "+
+            "Please run ValidateVariants for more detailed information. This error is: "+e.getMessage());
+        }
+
+        String refOut;
+        String altOut;
+        String vcRef = getReferenceAllele(vc);
+        String vcAlt = getAlternateAllele(vc);
+        boolean altMajor;
+        if ( majorAlleleFirst ) {
+            // want to use the major allele as ref
+            HashMap<String,Object> ats = new HashMap<String,Object>(vc.getAttributes());
+            if ( ! vc.hasAttribute("AF") ) {
+                VariantContextUtils.calculateChromosomeCounts(vc,ats,true);
+            }
+            if ( getAF(ats.get("AF")) > 0.5 ) {
+                refOut = vcAlt;
+                altOut = vcRef;
+                altMajor = true;
+            } else {
+                refOut = vcRef;
+                altOut = vcAlt;
+                altMajor = false;
+            }
+        } else {
+            refOut = vcRef;
+            altOut = vcAlt;
+            altMajor = false;
+        }
+        // write an entry into the map file
+        outBim.printf("%s\t%s\t%.2f\t%d\t%s\t%s%n",vc.getChr(),getID(vc),APPROX_CM_PER_BP*vc.getStart(),vc.getStart(),
+                refOut,altOut);
+        if ( mode == OutputMode.INDIVIDUAL_MAJOR ) {
+            writeIndividualMajor(vc,altMajor);
+        } else {
+            writeSNPMajor(vc,altMajor);
+        }
+
+
+        return 1;
+    }
+
+    public void writeIndividualMajor(VariantContext vc, boolean altMajor) {
+        // store genotypes per sample into the buffer
+        for ( Genotype g : vc.getGenotypes() ) {
+            ++totalGenotypeCount;
+            String sample = g.getSampleName();
+            byte[] samBuf = genotypeBuffer.get(sample);
+            byte enc = getEncoding(g,genotypeCount,altMajor);
+            samBuf[byteCount] |= enc;
+        }
+
+        genotypeCount++;
+        if ( genotypeCount % 4 == 0 ) {
+            byteCount++;
+            if ( byteCount >= BUFFER_SIZE ) {
+                // dump the buffer to the print streams
+                for ( String sample : printMap.keySet() ) {
+                    OutputStream samOut = printMap.get(sample);
+                    // print the buffer for this sample
+                    try {
+                        samOut.write(genotypeBuffer.get(sample));
+                    } catch ( IOException e ) {
+                        throw new ReviewedGATKException("Error writing to temporary bed file.",e);
+                    }
+                    // reset the buffer for this sample
+                    genotypeBuffer.put(sample,new byte[BUFFER_SIZE]);
+                }
+                byteCount = 0;
+            }
+            genotypeCount = 0;
+        }
+    }
+
+    public void writeSNPMajor(VariantContext vc, boolean altMajor) {
+        // for each sample, write the genotype into the bed file, in the
+        // order of the fam file
+        genotypeCount = 0;
+        byteCount = 0;
+        byte[] bytes = new byte[(3+famOrder.size())/4]; // this exploits java integer fractions, which round down by default (1-4) -> 1, (5-8) -> 2
+        for ( Genotype g : vc.getGenotypesOrderedBy(famOrder) ) {
+            byte enc = getEncoding(g,genotypeCount,altMajor);
+            bytes[byteCount] |= enc;
+            genotypeCount++;
+            if ( genotypeCount % 4 == 0 ) {
+                byteCount++;
+                genotypeCount = 0;
+            }
+        }
+        totalGenotypeCount += famOrder.size();
+        totalByteCount += bytes.length;
+        try {
+            outBed.write(bytes);
+        } catch (IOException e) {
+            throw new ReviewedGATKException("Error writing to output bed file",e);
+        }
+    }
+
+    public Integer reduce(Integer m, Integer r) {
+        return r + m;
+    }
+
+    public Integer reduceInit() {
+        return 0;
+    }
+
+    public void onTraversalDone(Integer numSites) {
+        logger.info(String.format("%d sites processed for a total of %d genotypes encoded in %d bytes",numSites,totalGenotypeCount,totalByteCount));
+
+        if ( mode == OutputMode.INDIVIDUAL_MAJOR ) {
+            mergeGenotypeTempFiles(numSites);
+        }
+
+    }
+
+    private void mergeGenotypeTempFiles(int numSites) {
+        // push out the remaining genotypes and close stream
+        for ( String sample : printMap.keySet() ) {
+            try {
+                int lim = byteCount + (genotypeCount > 0 ? 1 : 0);
+                printMap.get(sample).write(genotypeBuffer.get(sample),0,lim);
+            } catch (IOException e) {
+                throw new ReviewedGATKException("Error closing temporary file.",e);
+            }
+
+            try {
+               printMap.get(sample).close();
+            } catch (IOException e) {
+                throw new ReviewedGATKException("Error closing temporary file.",e);
+            }
+        }
+        for ( String sample : famOrder ) {
+            logger.info("Merging genotypes for "+sample);
+            FileInputStream inStream;
+            try {
+                inStream = new FileInputStream(tempFiles.get(sample));
+            } catch (IOException e) {
+                throw new ReviewedGATKException("Error opening temp file for input.",e);
+            }
+
+
+            try {
+                int ttr = numSites/4 + (genotypeCount > 0 ? 1 : 0);
+                for ( ; ttr > BUFFER_SIZE ; ttr -= BUFFER_SIZE ) {
+                    byte[] readGenotypes = new byte[BUFFER_SIZE];
+                    inStream.read(readGenotypes);
+                    outBed.write(readGenotypes);
+                    totalByteCount += BUFFER_SIZE;
+                }
+                if ( ttr > 0 ) {
+                    byte[] readGenotypes = new byte[ttr];
+                    inStream.read(readGenotypes);
+                    outBed.write(readGenotypes);
+                    totalByteCount += ttr;
+                }
+                inStream.close();
+            } catch (IOException e) {
+                throw new ReviewedGATKException("Error reading form temp file for input.",e);
+            }
+        }
+    }
+
+    private byte getEncoding(Genotype g, int offset, boolean altMajor) {
+        if ( ! altMajor ) {
+            return getStandardEncoding(g,offset);
+        }
+
+        return getFlippedEncoding(g,offset);
+    }
+
+    private byte getStandardEncoding(Genotype g, int offset) {
+        byte b;
+        if ( ! checkGQIsGood(g) ) {
+            b = NO_CALL;
+        } else if ( g.isHomRef() ) {
+            b = HOM_REF;
+        } else if ( g.isHomVar() ) {
+            b = HOM_VAR;
+        } else if ( g.isHet() ) {
+            b = HET;
+        } else {
+            b = NO_CALL;
+        }
+
+        return (byte) (b << (2*offset));
+    }
+
+    private byte getFlippedEncoding(Genotype g, int offset) {
+        byte b;
+        if ( ! checkGQIsGood(g) ) {
+            b = NO_CALL;
+        } else if ( g.isHomRef() ) {
+            b = HOM_VAR;
+        } else if ( g.isHomVar() ) {
+            b = HOM_REF;
+        } else if ( g.isHet() ) {
+            b = HET;
+        } else {
+            b = NO_CALL;
+        }
+
+        return (byte) (b << (2*offset));
+    }
+
+    private boolean checkGQIsGood(Genotype genotype) {
+        if ( genotype.hasGQ() ) {
+            return genotype.getGQ() >= minGenotypeQuality;
+        } else if ( genotype.hasLikelihoods() ) {
+            double log10gq = GenotypeLikelihoods.getGQLog10FromLikelihoods(genotype.getType().ordinal()-1,genotype.getLikelihoods().getAsVector());
+            return QualityUtils.phredScaleLog10ErrorRate(log10gq) >= minGenotypeQuality;
+        }
+
+        return minGenotypeQuality <= 0;
+    }
+
+    private static String getID(VariantContext v) {
+        if ( v.hasID() ) {
+            return v.getID();
+        } else {
+            return String.format("Var-%s-%d",v.getChr(),v.getStart());
+        }
+    }
+
+    private double getAF(Object o) {
+        if ( (o instanceof String) ) {
+            return Double.parseDouble((String) o);
+        } else if ( (o instanceof Double) ) {
+            return (Double) o;
+        } else {
+            throw new UserException("Allele frequency appears to be neither String nor Double. Please check the header of your VCF.");
+        }
+    }
+
+    private void writeBedHeader() {
+        // write magic bits into the ped file
+        try {
+            outBed.write(new byte[] { (byte) 0x6c, (byte) 0x1b, (byte) (mode == OutputMode.INDIVIDUAL_MAJOR ? 0x0 : 0x1)});
+            // ultimately, the bed will be in individual-major mode
+        } catch (IOException e) {
+            throw new ReviewedGATKException("error writing to output file.");
+        }
+    }
+
+    private Map<String,Map<String,String>> parseMetaData() {
+        // write to the fam file, the first six columns of the standard ped file
+        // first, load data from the input meta data file
+        Map<String,Map<String,String>> metaValues = new HashMap<String,Map<String,String>>();
+        logger.debug("Reading in metadata...");
+        try {
+            if ( metaDataFile.getAbsolutePath().endsWith(".fam") ) {
+                for ( String line : new XReadLines(metaDataFile) ) {
+                    String[] famSplit = line.split("\\s+");
+                    if ( famSplit.length != 6 ) {
+                        throw new UserException("Line of the fam file is malformatted. Expected 6 entries. Line is "+line);
+                    }
+                    String sid = famSplit[1];
+                    String fid = famSplit[0];
+                    String mom = famSplit[2];
+                    String dad = famSplit[3];
+                    String sex = famSplit[4];
+                    String pheno = famSplit[5];
+                    HashMap<String,String> values = new HashMap<String, String>();
+                    values.put("mom",mom);
+                    values.put("dad",dad);
+                    values.put("fid",fid);
+                    values.put("sex",sex);
+                    values.put("phenotype",pheno);
+                    metaValues.put(sid,values);
+                }
+            } else {
+                for ( String line : new XReadLines(metaDataFile) ) {
+                    logger.debug(line);
+                    String[] split = line.split("\\s+");
+                    String sampleID = split[0];
+                    String keyVals = split[1];
+                    HashMap<String,String> values = new HashMap<String, String>();
+                    for ( String kvp : keyVals.split(";") ) {
+                        String[] kvp_split = kvp.split("=");
+                        values.put(kvp_split[0],kvp_split[1]);
+                    }
+                    metaValues.put(sampleID,values);
+                }
+            }
+        } catch (FileNotFoundException e) {
+            throw new UserException("Meta data file not found: "+metaDataFile.getAbsolutePath(),e);
+        }
+
+        return metaValues;
+    }
+
+    private void validateVariantSite(VariantContext vc, ReferenceContext ref, AlignmentContext context) {
+        final Allele reportedRefAllele = vc.getReference();
+        final int refLength = reportedRefAllele.length();
+        if ( refLength > 100 ) {
+            logger.info(String.format("Reference allele is too long (%d) at position %s:%d; skipping that record.", refLength, vc.getChr(), vc.getStart()));
+            return;
+        }
+
+        final byte[] observedRefBases = new byte[refLength];
+        System.arraycopy(ref.getBases(), 0, observedRefBases, 0, refLength);
+        final Allele observedRefAllele = Allele.create(observedRefBases);
+        vc.validateReferenceBases(reportedRefAllele, observedRefAllele);
+        if ( checkAlternateAlleles )
+            vc.validateAlternateAlleles();
+    }
+
+    private String getReferenceAllele(VariantContext vc) {
+        if ( vc.isSimpleInsertion() ) {
+            // bi-allelic, so we just have "-" for ped output
+            return PLINK_DELETION_MARKER;
+        }
+        if ( vc.isSymbolic() ) {
+            // either symbolic or really long alleles. Plink alleles are allowed to be 1 or 2. Reference will just be 1.
+            return "1";
+        }
+        if ( vc.isSimpleDeletion() ) {
+            // bi-allelic. Want to take the standard representation and strip off the leading base.
+            return vc.getReference().getBaseString().substring(1);
+        }
+        // snp or mnp
+        return vc.getReference().getBaseString();
+    }
+
+    private String getAlternateAllele(VariantContext vc ) {
+        if ( vc.isSimpleInsertion() ) {
+            // bi-allelic. Want to take the standard representation and strip off the leading base.
+            return vc.getAlternateAllele(0).getBaseString().substring(1);
+        }
+        if ( vc.isSymbolic() ) {
+            // either symbolic or really long alleles. Plink alleles are allowed to be 1 or 2. Alt will just be 2.
+            return "2";
+        }
+        if ( vc.isSimpleDeletion() ) {
+            // bi-allelic, so we just have "-" for ped output
+            return PLINK_DELETION_MARKER;
+        }
+        // snp or mnp
+        return vc.getAlternateAllele(0).getBaseString();
+    }
+}
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/tools/walkers/variantutils/VariantsToTable.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/tools/walkers/variantutils/VariantsToTable.java
new file mode 100644
index 0000000..9a65a70
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/tools/walkers/variantutils/VariantsToTable.java
@@ -0,0 +1,460 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.tools.walkers.variantutils;
+
+import org.broadinstitute.gatk.utils.commandline.*;
+import org.broadinstitute.gatk.engine.CommandLineGATK;
+import org.broadinstitute.gatk.utils.SampleUtils;
+import org.broadinstitute.gatk.utils.help.HelpConstants;
+import org.broadinstitute.gatk.utils.variant.GATKVCFUtils;
+import org.broadinstitute.gatk.utils.variant.GATKVariantContextUtils;
+import htsjdk.variant.vcf.VCFConstants;
+import htsjdk.variant.vcf.VCFHeader;
+import org.broadinstitute.gatk.utils.help.DocumentedGATKFeature;
+import htsjdk.variant.variantcontext.Allele;
+import htsjdk.variant.variantcontext.VariantContext;
+import org.broadinstitute.gatk.engine.contexts.AlignmentContext;
+import org.broadinstitute.gatk.engine.contexts.ReferenceContext;
+import org.broadinstitute.gatk.engine.refdata.RefMetaDataTracker;
+import org.broadinstitute.gatk.engine.walkers.RodWalker;
+import org.broadinstitute.gatk.utils.Utils;
+import org.broadinstitute.gatk.utils.exceptions.UserException;
+
+import java.io.PrintStream;
+import java.lang.reflect.Array;
+import java.util.*;
+
+/**
+ * Emits specific fields from a VCF file to a tab-deliminated table
+ *
+ * <p>
+ * This walker accepts a single VCF file and writes out user-selected fields from the
+ * VCF as a header-containing, tab-deliminated file.  The user specifies one or more
+ * fields to print with the -F NAME, each of which appears as a single column in
+ * the output file, with a header named NAME, and the value of this field in the VCF
+ * one per line.  NAME can be any standard VCF column (CHROM, ID, QUAL) or any binding
+ * in the INFO field (AC=10).  In addition, there are specially supported values like
+ * EVENTLENGTH (length of the event), TRANSITION (for SNPs), HET (count of het genotypes),
+ * HOM-REF (count of homozygous reference genotypes), HOM-VAR (count of homozygous variant
+ * genotypes), NO-CALL (count of no-call genotypes), TYPE (the type of event), VAR (count of
+ * non-reference genotypes), NSAMPLES (number of samples), NCALLED (number of called samples),
+ * GQ (from the genotype field; works only for a file with a single sample), and MULTI-ALLELIC
+ * (is the record from a multi-allelic site).  Note that if a VCF record is missing a value, then the tool by
+ * default throws an error, but the special value NA can be emitted instead with
+ * appropriate tool arguments.
+ *
+ * </p>
+ *
+ * <h3>Input</h3>
+ * <p>
+ * <ul>
+ *     <li>A VCF file</li>
+ *     <li>A list of -F fields to write</li>
+ * </ul>
+ * </p>
+ *
+ * <h3>Output</h3>
+ * <p>
+ * A tab-delimited file containing the values of the requested fields in the VCF file
+ * </p>
+ *
+ * <h3>Examples</h3>
+ * <pre>
+ *     java -jar GenomeAnalysisTK.jar \
+ *     -R reference.fasta
+ *     -T VariantsToTable \
+ *     -V file.vcf \
+ *     -F CHROM -F POS -F ID -F QUAL -F AC \
+ *     -o results.table
+ *
+ *     would produce a file that looks like:
+ *
+ *     CHROM    POS ID      QUAL    AC
+ *     1        10  .       50      1
+ *     1        20  rs10    99      10
+ *     et cetera...
+ * </pre>
+ *
+ * @author Mark DePristo
+ * @since 2010
+ */
+ at DocumentedGATKFeature( groupName = HelpConstants.DOCS_CAT_VARMANIP, extraDocs = {CommandLineGATK.class} )
+public class VariantsToTable extends RodWalker<Integer, Integer> {
+    /**
+     * Variants from this VCF file are used by this tool as input.
+     * The file must at least contain the standard VCF header lines, but
+     * can be empty (i.e., no variants are contained in the file).
+     */
+    @Input(fullName="variant", shortName = "V", doc="Input VCF file", required=true)
+    public List<RodBinding<VariantContext>> variants;
+
+    @Output(doc="File to which results should be written")
+    protected PrintStream out;
+
+    /**
+     * -F NAME can be any standard VCF column (CHROM, ID, QUAL) or any binding in the INFO field (e.g., AC=10).
+     * Note that to capture GENOTYPE (FORMAT) field values, see the GF argument.  This argument accepts any number
+     * of inputs.  So -F CHROM -F POS is allowed.
+     */
+    @Argument(fullName="fields", shortName="F", doc="The name of each field to capture for output in the table", required=false)
+    public List<String> fieldsToTake = new ArrayList<String>();
+
+    /**
+     * -GF NAME can be any binding in the FORMAT field (e.g., GQ, PL).
+     * Note this argument accepts any number of inputs.  So -GF GQ -GF PL is allowed.
+     */
+    @Argument(fullName="genotypeFields", shortName="GF", doc="The name of each genotype field to capture for output in the table", required=false)
+    public List<String> genotypeFieldsToTake = new ArrayList<String>();
+    
+    /**
+     * By default this tool only emits values for fields where the FILTER field is either PASS or . (unfiltered).
+     * Throwing this flag will cause VariantsToTable to emit values regardless of the FILTER field value.
+     */
+    @Advanced
+    @Argument(fullName="showFiltered", shortName="raw", doc="If provided, field values from filtered records will be included in the output", required=false)
+    public boolean showFiltered = false;
+
+    /**
+     * If provided, then this tool will exit with success after this number of VCF records have been emitted to the file.
+     */
+    @Argument(fullName="maxRecords", shortName="M", doc="If provided, we will emit at most maxRecord records to the table", required=false)
+    public int MAX_RECORDS = -1;
+    long nRecords = 0L;
+
+    /**
+     * By default, records with multiple ALT alleles will comprise just one line of output; note that in general this can make your resulting file
+     * unreadable/malformed for certain tools like R, as the representation of multi-allelic INFO field values are often comma-separated lists
+     * of values.  Using the flag will cause multi-allelic records to be split into multiple lines of output (one for each allele in the ALT field);
+     * INFO field values that are not lists are copied for each of the output records while only the appropriate entry is used for lists.
+     */
+    @Argument(fullName="splitMultiAllelic", shortName="SMA", doc="If provided, we will split multi-allelic records into multiple lines of output", required=false)
+    public boolean splitMultiAllelic = false;
+
+    /**
+     * By default, this tool emits one line per usable VCF record (or per allele if the -SMA flag is provided).  Using the -moltenize flag
+     * will cause records to be split into multiple lines of output: one for each field provided with -F or one for each combination of sample
+     * and field provided with -GF.  Note that the "Sample" column for -F fields will always be "site".
+     */
+    @Advanced
+    @Argument(fullName="moltenize", shortName="moltenize", doc="If provided, we will produce molten output", required=false)
+    public boolean moltenizeOutput = false;
+
+    /**
+     * By default, this tool throws a UserException when it encounters a field without a value in some record.  This
+     * is generally useful when you mistype -F CHROM, so that you get a friendly warning about CHROM not being
+     * found before the tool runs through 40M 1000G records.  However, in some cases you genuinely want to allow such
+     * fields (e.g., AC not being calculated for filtered records, if included).  When provided, this argument
+     * will cause VariantsToTable to write out NA values for missing fields instead of throwing an error.
+     */
+    @Advanced
+    @Argument(fullName="allowMissingData", shortName="AMD", doc="If provided, we will not require every record to contain every field", required=false)
+    public boolean ALLOW_MISSING_DATA = false;
+    private final static String MISSING_DATA = "NA";
+
+    private final List<String> samples = new ArrayList<String>();
+
+    public void initialize() {
+
+        if ( !genotypeFieldsToTake.isEmpty() ) {
+            Map<String, VCFHeader> vcfRods = GATKVCFUtils.getVCFHeadersFromRods(getToolkit(), variants);
+            TreeSet<String> vcfSamples = new TreeSet<String>(SampleUtils.getSampleList(vcfRods, GATKVariantContextUtils.GenotypeMergeType.REQUIRE_UNIQUE));
+            samples.addAll(vcfSamples);
+
+            // optimization: if there are no samples, we don't have to worry about any genotype fields
+            if ( samples.isEmpty() )
+                genotypeFieldsToTake.clear();
+        }
+
+        // print out the header
+        if ( moltenizeOutput ) {
+            out.println("RecordID\tSample\tVariable\tValue");
+        } else {
+            final String baseHeader = Utils.join("\t", fieldsToTake);
+            final String genotypeHeader = createGenotypeHeader(genotypeFieldsToTake, samples);
+            final String separator = (!baseHeader.isEmpty() && !genotypeHeader.isEmpty()) ? "\t" : "";
+            out.println(baseHeader + separator + genotypeHeader);
+        }
+    }
+
+    public Integer map(RefMetaDataTracker tracker, ReferenceContext ref, AlignmentContext context) {
+        if ( tracker == null ) // RodWalkers can make funky map calls
+            return 0;
+
+        for ( VariantContext vc : tracker.getValues(variants, context.getLocation())) {
+            if ( showFiltered || vc.isNotFiltered() ) {
+                nRecords++;
+                for ( final List<String> record : extractFields(vc, fieldsToTake, genotypeFieldsToTake, samples, ALLOW_MISSING_DATA, splitMultiAllelic) ) {
+                    if ( moltenizeOutput )
+                        emitMoltenizedOutput(record);
+                    else
+                        out.println(Utils.join("\t", record));
+                }
+            }
+        }
+        
+        return 1;
+    }
+
+    @Override
+    public boolean isDone() {
+        return (MAX_RECORDS != -1 && nRecords >= MAX_RECORDS);
+    }
+
+    private static final boolean isWildCard(String s) {
+        return s.endsWith("*");
+    }
+
+    private static String createGenotypeHeader(final List<String> genotypeFieldsToTake, final List<String> samples) {
+        boolean firstEntry = true;
+
+        final StringBuilder sb = new StringBuilder();
+        for ( final String sample : samples ) {
+            for ( final String gf : genotypeFieldsToTake ) {
+                if ( firstEntry )
+                    firstEntry = false;
+                else
+                    sb.append("\t");
+                // spaces in sample names are legal but wreak havoc in R data frames
+                sb.append(sample.replace(" ","_"));
+                sb.append(".");
+                sb.append(gf);
+            }
+        }
+        return sb.toString();
+    }
+
+    private void emitMoltenizedOutput(final List<String> record) {
+        int index = 0;
+        for ( final String field : fieldsToTake ) {
+            out.println(String.format("%d\tsite\t%s\t%s", nRecords, field, record.get(index++)));
+        }
+        for ( final String sample : samples ) {
+            for ( final String gf : genotypeFieldsToTake ) {
+                out.println(String.format("%d\t%s\t%s\t%s", nRecords, sample.replace(" ","_"), gf, record.get(index++)));
+            }
+        }
+    }
+
+    /**
+     * Utility function that returns the list of values for each field in fields from vc.
+     *
+     * @param vc                the VariantContext whose field values we can to capture
+     * @param fields            a non-null list of fields to capture from VC
+     * @param genotypeFields    a (possibly null) list of fields to capture from each genotype
+     * @param samples           list of samples in vc
+     * @param allowMissingData  if false, then throws a UserException if any field isn't found in vc.  Otherwise provides a value of NA
+     * @param splitMultiAllelic if true, multiallelic variants are to be split into multiple records
+     * @return List of lists of field values
+     */
+    private static List<List<String>> extractFields(final VariantContext vc,
+                                                    final List<String> fields,
+                                                    final List<String> genotypeFields,
+                                                    final List<String> samples,
+                                                    final boolean allowMissingData,
+                                                    final boolean splitMultiAllelic) {
+        
+        final int numRecordsToProduce = splitMultiAllelic ? vc.getAlternateAlleles().size() : 1;
+        final List<List<String>> records = new ArrayList<List<String>>(numRecordsToProduce);
+
+        int numFields = fields.size();
+        final boolean addGenotypeFields = genotypeFields != null && !genotypeFields.isEmpty();
+        if ( addGenotypeFields )
+            numFields += genotypeFields.size() * samples.size();
+
+        for ( int i = 0; i < numRecordsToProduce; i++ )
+            records.add(new ArrayList<String>(numFields));
+
+        for ( String field : fields ) {
+
+            if ( splitMultiAllelic && field.equals("ALT") ) { // we need to special case the ALT field when splitting out multi-allelic records
+                addFieldValue(splitAltAlleles(vc), records);
+            } else if ( getters.containsKey(field) ) {
+                addFieldValue(getters.get(field).get(vc), records);
+            } else if ( vc.hasAttribute(field) ) {
+                addFieldValue(vc.getAttribute(field, null), records);
+            } else if ( isWildCard(field) ) {
+                Set<String> wildVals = new HashSet<String>();
+                for ( Map.Entry<String,Object> elt : vc.getAttributes().entrySet()) {
+                    if ( elt.getKey().startsWith(field.substring(0, field.length() - 1)) ) {
+                        wildVals.add(elt.getValue().toString());
+                    }
+                }
+
+                String val = MISSING_DATA;
+                if ( wildVals.size() > 0 ) {
+                    List<String> toVal = new ArrayList<String>(wildVals);
+                    Collections.sort(toVal);
+                    val = Utils.join(",", toVal);
+                }
+
+                addFieldValue(val, records);
+            } else if ( ! allowMissingData ) {
+                throw new UserException(String.format("Missing field %s in vc %s at %s", field, vc.getSource(), vc));
+            } else {
+                addFieldValue(MISSING_DATA, records);
+            }
+        }
+
+        if ( addGenotypeFields ) {
+            for ( final String sample : samples ) {
+                for ( final String gf : genotypeFields ) {
+                    if ( vc.hasGenotype(sample) && vc.getGenotype(sample).hasAnyAttribute(gf) ) {
+                        if ( gf.equals(VCFConstants.GENOTYPE_KEY) )
+                            addFieldValue(vc.getGenotype(sample).getGenotypeString(true), records);
+                        else
+                            addFieldValue(vc.getGenotype(sample).getAnyAttribute(gf), records);
+                    }
+                    else
+                        addFieldValue(MISSING_DATA, records);
+                }
+            }
+        }
+
+        return records;
+    }
+
+    private static void addFieldValue(final Object val, final List<List<String>> result) {
+        final int numResultRecords = result.size();
+        
+        // if we're trying to create a single output record, add it
+        if ( numResultRecords == 1 ) {
+            result.get(0).add(prettyPrintObject(val));
+        }
+        // if this field is a list of the proper size, add the appropriate entry to each record
+        else if ( (val instanceof List) && ((List)val).size() == numResultRecords ) {
+            final List list = (List)val;
+            for ( int i = 0; i < numResultRecords; i++ )
+                result.get(i).add(list.get(i).toString());
+        }
+        // otherwise, add the original value to all of the records
+        else {
+            final String valStr = val.toString();
+            for ( List<String> record : result )
+                record.add(valStr);
+        }
+    }
+
+    private static String prettyPrintObject(final Object val) {
+        if ( val instanceof List )
+            return prettyPrintObject(((List)val).toArray());
+
+        if ( !val.getClass().isArray() )
+            return val.toString();
+
+        final int length = Array.getLength(val);
+        if ( length == 0 )
+            return "";
+
+        final StringBuilder sb = new StringBuilder(prettyPrintObject(Array.get(val, 0)));
+        for ( int i = 1; i < length; i++ ) {
+            sb.append(",");
+            sb.append(prettyPrintObject(Array.get(val, i)));
+        }
+        return sb.toString();
+    }
+
+
+    public static List<List<String>> extractFields(VariantContext vc, List<String> fields, boolean allowMissingData) {
+        return extractFields(vc, fields, null, null, allowMissingData, false);
+    }
+    //
+    // default reduce -- doesn't do anything at all
+    //
+    public Integer reduceInit() { return 0; }
+    public Integer reduce(Integer counter, Integer sum) { return counter + sum; }
+    public void onTraversalDone(Integer sum) {}
+
+    // ----------------------------------------------------------------------------------------------------
+    //
+    // static system for getting values from VC by name.
+    //
+    // ----------------------------------------------------------------------------------------------------
+
+    public static abstract class Getter { public abstract String get(VariantContext vc); }
+    public static final Map<String, Getter> getters = new HashMap<String, Getter>();
+
+    static {
+        // #CHROM  POS     ID      REF     ALT     QUAL    FILTER  INFO    FORMAT
+        getters.put("CHROM", new Getter() { public String get(VariantContext vc) { return vc.getChr(); } });
+        getters.put("POS", new Getter() { public String get(VariantContext vc) { return Integer.toString(vc.getStart()); } });
+        getters.put("REF", new Getter() {
+            public String get(VariantContext vc) {
+                StringBuilder x = new StringBuilder();
+                x.append(vc.getReference().getDisplayString());
+                return x.toString();
+            }
+        });
+        getters.put("ALT", new Getter() {
+            public String get(VariantContext vc) {
+                StringBuilder x = new StringBuilder();
+                int n = vc.getAlternateAlleles().size();
+                if ( n == 0 ) return ".";
+
+                for ( int i = 0; i < n; i++ ) {
+                    if ( i != 0 ) x.append(",");
+                    x.append(vc.getAlternateAllele(i));
+                }
+                return x.toString();
+            }
+        });
+        getters.put("EVENTLENGTH", new Getter() { public String get(VariantContext vc) {
+            int maxLength = 0;
+            for ( final Allele a : vc.getAlternateAlleles() ) {
+                final int length = a.length() - vc.getReference().length();
+                if( Math.abs(length) > Math.abs(maxLength) ) { maxLength = length; }
+            }
+            return Integer.toString(maxLength);
+        }});
+        getters.put("QUAL", new Getter() { public String get(VariantContext vc) { return Double.toString(vc.getPhredScaledQual()); } });
+        getters.put("TRANSITION", new Getter() { public String get(VariantContext vc) {
+            if ( vc.isSNP() && vc.isBiallelic() )
+                return GATKVariantContextUtils.isTransition(vc) ? "1" : "0";
+            else
+                return "-1";
+        }});
+        getters.put("FILTER", new Getter() { public String get(VariantContext vc) {
+            return vc.isNotFiltered() ? "PASS" : Utils.join(",", vc.getFilters()); }
+        });
+        getters.put("ID", new Getter() { public String get(VariantContext vc) { return vc.getID(); } });
+        getters.put("HET", new Getter() { public String get(VariantContext vc) { return Integer.toString(vc.getHetCount()); } });
+        getters.put("HOM-REF", new Getter() { public String get(VariantContext vc) { return Integer.toString(vc.getHomRefCount()); } });
+        getters.put("HOM-VAR", new Getter() { public String get(VariantContext vc) { return Integer.toString(vc.getHomVarCount()); } });
+        getters.put("NO-CALL", new Getter() { public String get(VariantContext vc) { return Integer.toString(vc.getNoCallCount()); } });
+        getters.put("TYPE", new Getter() { public String get(VariantContext vc) { return vc.getType().toString(); } });
+        getters.put("VAR", new Getter() { public String get(VariantContext vc) { return Integer.toString(vc.getHetCount() + vc.getHomVarCount()); } });
+        getters.put("NSAMPLES", new Getter() { public String get(VariantContext vc) { return Integer.toString(vc.getNSamples()); } });
+        getters.put("NCALLED", new Getter() { public String get(VariantContext vc) { return Integer.toString(vc.getNSamples() - vc.getNoCallCount()); } });
+        getters.put("MULTI-ALLELIC", new Getter() { public String get(VariantContext vc) { return Boolean.toString(vc.getAlternateAlleles().size() > 1); } });
+    }
+    
+    private static Object splitAltAlleles(VariantContext vc) {
+        final int numAltAlleles = vc.getAlternateAlleles().size();
+        if ( numAltAlleles == 1 )
+            return vc.getAlternateAllele(0);
+
+        return vc.getAlternateAlleles();
+    }
+}
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/tools/walkers/variantutils/VariantsToVCF.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/tools/walkers/variantutils/VariantsToVCF.java
new file mode 100644
index 0000000..3e0e2ab
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/tools/walkers/variantutils/VariantsToVCF.java
@@ -0,0 +1,271 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.tools.walkers.variantutils;
+
+import htsjdk.samtools.util.CloseableIterator;
+import htsjdk.tribble.Feature;
+import org.broadinstitute.gatk.utils.commandline.*;
+import org.broadinstitute.gatk.engine.CommandLineGATK;
+import org.broadinstitute.gatk.engine.arguments.DbsnpArgumentCollection;
+import org.broadinstitute.gatk.engine.contexts.AlignmentContext;
+import org.broadinstitute.gatk.engine.contexts.ReferenceContext;
+import org.broadinstitute.gatk.engine.refdata.RefMetaDataTracker;
+import org.broadinstitute.gatk.engine.refdata.VariantContextAdaptors;
+import org.broadinstitute.gatk.engine.refdata.tracks.RMDTrackBuilder;
+import org.broadinstitute.gatk.engine.refdata.utils.GATKFeature;
+import org.broadinstitute.gatk.engine.walkers.Reference;
+import org.broadinstitute.gatk.engine.walkers.RodWalker;
+import org.broadinstitute.gatk.engine.walkers.Window;
+import org.broadinstitute.gatk.tools.walkers.annotator.VariantOverlapAnnotator;
+import org.broadinstitute.gatk.utils.BaseUtils;
+import org.broadinstitute.gatk.utils.GenomeLoc;
+import org.broadinstitute.gatk.utils.SampleUtils;
+import org.broadinstitute.gatk.utils.codecs.hapmap.RawHapMapFeature;
+import org.broadinstitute.gatk.utils.help.HelpConstants;
+import org.broadinstitute.gatk.utils.variant.GATKVCFUtils;
+import org.broadinstitute.gatk.utils.variant.GATKVariantContextUtils;
+import htsjdk.variant.vcf.*;
+import org.broadinstitute.gatk.utils.exceptions.UserException;
+import org.broadinstitute.gatk.utils.help.DocumentedGATKFeature;
+import htsjdk.variant.variantcontext.*;
+import htsjdk.variant.variantcontext.writer.VariantContextWriter;
+import htsjdk.variant.variantcontext.writer.VariantContextWriterFactory;
+
+import java.io.File;
+import java.util.*;
+
+/**
+ * Converts variants from other file formats to VCF format.
+ *
+ * <p>
+ * Note that there must be a Tribble feature/codec for the file format as well as an adaptor.
+ *
+ * <h3>Input</h3>
+ * <p>
+ * A variant file to filter.
+ * </p>
+ *
+ * <h3>Output</h3>
+ * <p>
+ * A VCF file.
+ * </p>
+ *
+ * <h3>Examples</h3>
+ * <pre>
+ * java -Xmx2g -jar GenomeAnalysisTK.jar \
+ *   -R ref.fasta \
+ *   -T VariantsToVCF \
+ *   -o output.vcf \
+ *   --variant:RawHapMap input.hapmap \
+ *   --dbsnp dbsnp.vcf
+ * </pre>
+ *
+ */
+ at DocumentedGATKFeature( groupName = HelpConstants.DOCS_CAT_VARMANIP, extraDocs = {CommandLineGATK.class} )
+ at Reference(window=@Window(start=-40,stop=40))
+public class VariantsToVCF extends RodWalker<Integer, Integer> {
+
+    @Output(doc="File to which variants should be written")
+    protected VariantContextWriter baseWriter = null;
+    private VariantContextWriter vcfwriter; // needed because hapmap/dbsnp indel records move
+
+    /**
+     * Variants from this input file are used by this tool as input.
+     */
+    @Input(fullName="variant", shortName = "V", doc="Input variant file", required=true)
+    public RodBinding<Feature> variants;
+
+    @ArgumentCollection
+    protected DbsnpArgumentCollection dbsnp = new DbsnpArgumentCollection();
+
+    /**
+     * This argument is used for data (like GELI) with genotypes but no sample names encoded within.
+     */
+    @Argument(fullName="sample", shortName="sample", doc="The sample name represented by the variant rod", required=false)
+    protected String sampleName = null;
+
+    private Set<String> allowedGenotypeFormatStrings = new HashSet<String>();
+    private boolean wroteHeader = false;
+    private Set<String> samples;
+
+    // for dealing with indels in hapmap
+    CloseableIterator<GATKFeature> dbsnpIterator = null;
+    VariantOverlapAnnotator variantOverlapAnnotator = null;
+
+    public void initialize() {
+        vcfwriter = VariantContextWriterFactory.sortOnTheFly(baseWriter, 40, false);
+        variantOverlapAnnotator = new VariantOverlapAnnotator(dbsnp.dbsnp, getToolkit().getGenomeLocParser());
+    }
+
+    public Integer map(RefMetaDataTracker tracker, ReferenceContext ref, AlignmentContext context) {
+        if ( tracker == null || !BaseUtils.isRegularBase(ref.getBase()) )
+            return 0;
+
+        Collection<VariantContext> contexts = getVariantContexts(tracker, ref);
+
+        for ( VariantContext vc : contexts ) {
+            VariantContextBuilder builder = new VariantContextBuilder(vc);
+
+            // set the appropriate sample name if necessary
+            if ( sampleName != null && vc.hasGenotypes() && vc.hasGenotype(variants.getName()) ) {
+                Genotype g = new GenotypeBuilder(vc.getGenotype(variants.getName())).name(sampleName).make();
+                builder.genotypes(g);
+            }
+
+            final VariantContext withID = variantOverlapAnnotator.annotateRsID(tracker, builder.make());
+            writeRecord(withID, tracker, ref.getLocus());
+        }
+
+        return 1;
+    }
+
+    private Collection<VariantContext> getVariantContexts(RefMetaDataTracker tracker, ReferenceContext ref) {
+
+        List<Feature> features = tracker.getValues(variants, ref.getLocus());
+        List<VariantContext> VCs = new ArrayList<VariantContext>(features.size());
+
+        for ( Feature record : features ) {
+            if ( VariantContextAdaptors.canBeConvertedToVariantContext(record) ) {
+                // we need to special case the HapMap format because indels aren't handled correctly
+                if ( record instanceof RawHapMapFeature) {
+
+                    // is it an indel?
+                    RawHapMapFeature hapmap = (RawHapMapFeature)record;
+                    if ( hapmap.getAlleles()[0].equals(RawHapMapFeature.NULL_ALLELE_STRING) || hapmap.getAlleles()[1].equals(RawHapMapFeature.NULL_ALLELE_STRING) ) {
+                        // get the dbsnp object corresponding to this record (needed to help us distinguish between insertions and deletions)
+                        VariantContext dbsnpVC = getDbsnp(hapmap.getName());
+                        if ( dbsnpVC == null || dbsnpVC.isMixed() )
+                            continue;
+
+                        Map<String, Allele> alleleMap = new HashMap<String, Allele>(2);
+                        alleleMap.put(RawHapMapFeature.DELETION, Allele.create(ref.getBase(), dbsnpVC.isSimpleInsertion()));
+                        alleleMap.put(RawHapMapFeature.INSERTION, Allele.create((char)ref.getBase() + ((RawHapMapFeature)record).getAlleles()[1], !dbsnpVC.isSimpleInsertion()));
+                        hapmap.setActualAlleles(alleleMap);
+
+                        // also, use the correct positioning for insertions
+                        hapmap.updatePosition(dbsnpVC.getStart());
+
+                        if ( hapmap.getStart() < ref.getWindow().getStart() ) {
+                            logger.warn("Hapmap record at " + ref.getLocus() + " represents an indel too large to be converted; skipping...");
+                            continue;
+                        }
+                    }
+                }
+
+                // ok, we might actually be able to turn this record in a variant context
+                VariantContext vc = VariantContextAdaptors.toVariantContext(variants.getName(), record, ref);
+
+                if ( vc != null ) // sometimes the track has odd stuff in it that can't be converted
+                    VCs.add(vc);
+            }
+        }
+
+        return VCs;
+    }
+
+    private VariantContext getDbsnp(String rsID) {
+        if ( dbsnpIterator == null ) {
+
+            if ( dbsnp == null )
+                throw new UserException.BadInput("No dbSNP rod was provided, but one is needed to decipher the correct indel alleles from the HapMap records");
+
+            RMDTrackBuilder builder = new RMDTrackBuilder(getToolkit().getReferenceDataSource().getReference().getSequenceDictionary(),
+                                                          getToolkit().getGenomeLocParser(),
+                                                          getToolkit().getArguments().unsafe,
+                                                          getToolkit().getArguments().disableAutoIndexCreationAndLockingWhenReadingRods,
+                                                          null);
+            dbsnpIterator = builder.createInstanceOfTrack(VCFCodec.class, new File(dbsnp.dbsnp.getSource())).getIterator();
+            // Note that we should really use some sort of seekable iterator here so that the search doesn't take forever
+            // (but it's complicated because the hapmap location doesn't match the dbsnp location, so we don't know where to seek to)
+        }
+
+        while ( dbsnpIterator.hasNext() ) {
+            GATKFeature feature = dbsnpIterator.next();
+            VariantContext vc = (VariantContext)feature.getUnderlyingObject();
+            if ( vc.getID().equals(rsID) )
+                return vc;
+        }
+
+        return null;
+    }
+
+    private void writeRecord(VariantContext vc, RefMetaDataTracker tracker, GenomeLoc loc) {
+        if ( !wroteHeader ) {
+            wroteHeader = true;
+
+            // setup the header fields
+            Set<VCFHeaderLine> hInfo = new HashSet<VCFHeaderLine>();
+            hInfo.addAll(GATKVCFUtils.getHeaderFields(getToolkit(), Arrays.asList(variants.getName())));
+            hInfo.add(VCFStandardHeaderLines.getFormatLine(VCFConstants.GENOTYPE_KEY));
+
+            allowedGenotypeFormatStrings.add(VCFConstants.GENOTYPE_KEY);
+            for ( VCFHeaderLine field : hInfo ) {
+                if ( field instanceof VCFFormatHeaderLine) {
+                    allowedGenotypeFormatStrings.add(((VCFFormatHeaderLine)field).getID());
+                }
+            }
+
+            samples = new LinkedHashSet<String>();
+            if ( sampleName != null ) {
+                samples.add(sampleName);
+            } else {
+                // try VCF first
+                samples = SampleUtils.getSampleListWithVCFHeader(getToolkit(), Arrays.asList(variants.getName()));
+
+                if ( samples.isEmpty() ) {
+                    List<Feature> features = tracker.getValues(variants, loc);
+                    if ( features.size() == 0 )
+                        throw new IllegalStateException("No rod data is present, but we just created a VariantContext");
+
+                    Feature f = features.get(0);
+                    if ( f instanceof RawHapMapFeature )
+                        samples.addAll(Arrays.asList(((RawHapMapFeature)f).getSampleIDs()));
+                    else
+                        samples.addAll(vc.getSampleNames());
+                }
+            }
+
+            vcfwriter.writeHeader(new VCFHeader(hInfo, samples));
+        }
+
+        vc = GATKVariantContextUtils.purgeUnallowedGenotypeAttributes(vc, allowedGenotypeFormatStrings);
+        vcfwriter.add(vc);
+    }
+
+    public Integer reduceInit() {
+        return 0;
+    }
+
+    public Integer reduce(Integer value, Integer sum) {
+        return value + sum;
+    }
+
+    public void onTraversalDone(Integer sum) {
+        if ( dbsnpIterator != null )
+            dbsnpIterator.close();
+        vcfwriter.close();
+    }
+}
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/AutoFormattingTime.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/AutoFormattingTime.java
new file mode 100644
index 0000000..31032e3
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/AutoFormattingTime.java
@@ -0,0 +1,185 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.utils;
+
+import java.util.concurrent.TimeUnit;
+
+/**
+ * Conveniently print a time with an automatically determined time unit
+ *
+ * For example, if the amount of time is 10^6 seconds, instead of printing
+ * out 10^6 seconds, prints out 11.57 days instead.
+ *
+ * Dynamically uses time units:
+ *
+ *   - seconds: s
+ *   - minutes: m
+ *   - hours  : h
+ *   - days   : d
+ *   - weeks  : w
+ *
+ * @author depristo
+ * @since 2009
+ */
+public class AutoFormattingTime {
+    private static final double NANOSECONDS_PER_SECOND = 1e9;
+
+    /**
+     * Width a la format's %WIDTH.PERCISIONf
+     */
+    private final int width; // for format
+
+    /**
+     * Precision a la format's %WIDTH.PERCISIONf
+     */
+    private final int precision;      // for format
+
+    /**
+     * The elapsed time in nanoseconds
+     */
+    private final long nanoTime;
+
+    /**
+     * Create a new autoformatting time with elapsed time nanoTime in nanoseconds
+     * @param nanoTime the elapsed time in nanoseconds
+     * @param width the width >= 0 (a la format's %WIDTH.PERCISIONf) to use to display the format, or -1 if none is required
+     * @param precision the precision to display the time at.  Must be >= 0;
+     */
+    public AutoFormattingTime(final long nanoTime, final int width, int precision) {
+        if ( width < -1 ) throw new IllegalArgumentException("Width " + width + " must be >= -1");
+        if ( precision < 0 ) throw new IllegalArgumentException("Precision " + precision + " must be >= 0");
+
+        this.width = width;
+        this.nanoTime = nanoTime;
+        this.precision = precision;
+    }
+
+    /**
+     * @see #AutoFormattingTime(long, int, int) but with default width and precision
+     * @param nanoTime
+     */
+    public AutoFormattingTime(final long nanoTime) {
+        this(nanoTime, 6, 1);
+    }
+
+    /**
+     * @see #AutoFormattingTime(long, int, int) but with time specificied as a double in seconds
+     */
+    public AutoFormattingTime(final double timeInSeconds, final int width, final int precision) {
+        this(secondsToNano(timeInSeconds), width, precision);
+    }
+
+    /**
+     * @see #AutoFormattingTime(long) but with time specificied as a double in seconds
+     */
+    public AutoFormattingTime(double timeInSeconds) {
+        this(timeInSeconds, 6, 1);
+    }
+
+    /**
+     * Precomputed format string suitable for string.format with the required width and precision
+     */
+    private String getFormatString() {
+        final StringBuilder b = new StringBuilder("%");
+        if ( width != -1 )
+            b.append(width);
+        b.append(".").append(precision).append("f %s");
+        return b.toString();
+    }
+
+    /**
+     * Get the time associated with this object in nanoseconds
+     * @return the time in nanoseconds
+     */
+    public long getTimeInNanoSeconds() {
+        return nanoTime;
+    }
+
+    /**
+     * Get the time associated with this object in seconds, as a double
+     * @return time in seconds as a double
+     */
+    public double getTimeInSeconds() {
+        return TimeUnit.NANOSECONDS.toSeconds(getTimeInNanoSeconds());
+    }
+
+    /**
+     * @return the precision (a la format's %WIDTH.PERCISIONf)
+     */
+    public int getWidth() {
+        return width;
+    }
+
+    /**
+     * @return the precision (a la format's %WIDTH.PERCISIONf)
+     */
+    public int getPrecision() {
+        return precision;
+    }
+
+    /**
+     * Get a string representation of this time, automatically converting the time
+     * to a human readable unit with width and precision provided during construction
+     * @return a non-null string
+     */
+    public String toString() {
+        double unitTime = getTimeInSeconds();
+        String unit = "s";
+
+        if ( unitTime > 120 ) {
+            unitTime /= 60; // minutes
+            unit = "m";
+
+            if ( unitTime > 120 ) {
+                unitTime /= 60; // hours
+                unit = "h";
+
+                if ( unitTime > 100 ) {
+                    unitTime /= 24; // days
+                    unit = "d";
+
+                    if ( unitTime > 20 ) {
+                        unitTime /= 7; // weeks
+                        unit = "w";
+                    }
+                }
+            }
+        }
+
+        return String.format(getFormatString(), unitTime, unit);
+    }
+
+
+    /**
+     * Convert a time in seconds as a double into nanoseconds as a long
+     * @param timeInSeconds an elapsed time in seconds, as a double
+     * @return an equivalent value in nanoseconds as a long
+     */
+    private static long secondsToNano(final double timeInSeconds) {
+        return (long)(NANOSECONDS_PER_SECOND * timeInSeconds);
+    }
+
+}
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/BaseUtils.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/BaseUtils.java
new file mode 100644
index 0000000..194db68
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/BaseUtils.java
@@ -0,0 +1,672 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.utils;
+
+import htsjdk.samtools.util.StringUtil;
+import org.broadinstitute.gatk.engine.GenomeAnalysisEngine;
+import org.broadinstitute.gatk.utils.exceptions.ReviewedGATKException;
+import org.broadinstitute.gatk.utils.exceptions.UserException;
+
+import java.util.Arrays;
+import java.util.Comparator;
+import java.util.Random;
+
+/**
+ * BaseUtils contains some basic utilities for manipulating nucleotides.
+ */
+public class BaseUtils {
+
+    public enum Base {
+        A ('A'),
+        C ('C'),
+        G ('G'),
+        T ('T'),
+        N ('N'),
+        D ('D');
+
+        public byte base;
+
+        private Base(final char base) {
+            this.base = (byte)base;
+        }
+    }
+
+    // todo -- add this to the generalized base abstraction using the Base enum.
+    public final static byte[] BASES = {'A', 'C', 'G', 'T'};
+    public final static byte[] EXTENDED_BASES = {'A', 'C', 'G', 'T', 'N', 'D'};
+
+    static private final int[] baseIndexMap = new int[256];
+    static {
+        Arrays.fill(baseIndexMap, -1);
+        baseIndexMap['A'] = Base.A.ordinal();
+        baseIndexMap['a'] = Base.A.ordinal();
+        baseIndexMap['*'] = Base.A.ordinal();    // the wildcard character counts as an A
+        baseIndexMap['C'] = Base.C.ordinal();
+        baseIndexMap['c'] = Base.C.ordinal();
+        baseIndexMap['G'] = Base.G.ordinal();
+        baseIndexMap['g'] = Base.G.ordinal();
+        baseIndexMap['T'] = Base.T.ordinal();
+        baseIndexMap['t'] = Base.T.ordinal();
+    }
+
+    static private final int[] baseIndexWithIupacMap = baseIndexMap.clone();
+    static {
+        baseIndexWithIupacMap['*'] = -1;    // the wildcard character is bad
+        baseIndexWithIupacMap['N'] = Base.N.ordinal();
+        baseIndexWithIupacMap['n'] = Base.N.ordinal();
+        baseIndexWithIupacMap['R'] = Base.N.ordinal();
+        baseIndexWithIupacMap['r'] = Base.N.ordinal();
+        baseIndexWithIupacMap['Y'] = Base.N.ordinal();
+        baseIndexWithIupacMap['y'] = Base.N.ordinal();
+        baseIndexWithIupacMap['M'] = Base.N.ordinal();
+        baseIndexWithIupacMap['m'] = Base.N.ordinal();
+        baseIndexWithIupacMap['K'] = Base.N.ordinal();
+        baseIndexWithIupacMap['k'] = Base.N.ordinal();
+        baseIndexWithIupacMap['W'] = Base.N.ordinal();
+        baseIndexWithIupacMap['w'] = Base.N.ordinal();
+        baseIndexWithIupacMap['S'] = Base.N.ordinal();
+        baseIndexWithIupacMap['s'] = Base.N.ordinal();
+        baseIndexWithIupacMap['B'] = Base.N.ordinal();
+        baseIndexWithIupacMap['b'] = Base.N.ordinal();
+        baseIndexWithIupacMap['D'] = Base.N.ordinal();
+        baseIndexWithIupacMap['d'] = Base.N.ordinal();
+        baseIndexWithIupacMap['H'] = Base.N.ordinal();
+        baseIndexWithIupacMap['h'] = Base.N.ordinal();
+        baseIndexWithIupacMap['V'] = Base.N.ordinal();
+        baseIndexWithIupacMap['v'] = Base.N.ordinal();
+    }
+
+    /// In genetics, a transition is a mutation changing a purine to another purine nucleotide (A <-> G) or
+    // a pyrimidine to another pyrimidine nucleotide (C <-> T).
+    // Approximately two out of every three single nucleotide polymorphisms (SNPs) are transitions.
+    public enum BaseSubstitutionType {
+        TRANSITION,         // A <-> G or C <-> T
+        TRANSVERSION
+    }
+
+    /**
+     * Returns the base substitution type of the 2 state SNP
+     *
+     * @param base1
+     * @param base2
+     * @return
+     */
+    public static BaseSubstitutionType SNPSubstitutionType(byte base1, byte base2) {
+        BaseSubstitutionType t = isTransition(base1, base2) ? BaseSubstitutionType.TRANSITION : BaseSubstitutionType.TRANSVERSION;
+        //System.out.printf("SNPSubstitutionType( char %c, char %c ) => %s%n", base1, base2, t);
+        return t;
+    }
+
+    public static boolean isTransition(byte base1, byte base2) {
+        final int b1 = simpleBaseToBaseIndex(base1);
+        final int b2 = simpleBaseToBaseIndex(base2);
+        return b1 == Base.A.ordinal() && b2 == Base.G.ordinal() || b1 == Base.G.ordinal() && b2 == Base.A.ordinal() ||
+                b1 == Base.C.ordinal() && b2 == Base.T.ordinal() || b1 == Base.T.ordinal() && b2 == Base.C.ordinal();
+    }
+
+    public static boolean isTransversion(byte base1, byte base2) {
+        return !isTransition(base1, base2);
+    }
+
+    /**
+     * Private constructor.  No instantiating this class!
+     */
+    private BaseUtils() {}
+
+    static public boolean basesAreEqual(byte base1, byte base2) {
+        return simpleBaseToBaseIndex(base1) == simpleBaseToBaseIndex(base2);
+    }
+
+    /**
+     * Checks whether to bases are the same in fact ignore ambiguous 'N' bases.
+     *
+     * @param base1 first base to compare.
+     * @param base2 second base to compare.
+     * @return true if {@code base1 == base2} or either is an 'N', false otherwise.
+     */
+    static public boolean basesAreEqualIgnoreAmbiguous(final byte base1, final byte base2) {
+        if (base1 == base2) return true;
+        else if (base1 == 'n' || base1 == 'N' || base2 == 'N' || base2 == 'n') return true;
+        else return false;
+    }
+
+    /**
+     * Compare to base arrays ranges checking whether they contain the same bases.
+     *
+     * <p>
+     *     By default two array have equal bases, i.e. {@code length == 0} results results in {@code true}.
+     * </p>
+     *
+     * @param bases1 first base array to compare.
+     * @param offset1 position of the first base in bases1 to compare.
+     * @param bases2 second base array to compare.
+     * @param offset2 position of the first base in bases2 to compare.
+     * @param length number of bases to compare.
+     *
+     * @throws NullPointerException if {@code bases1} or {@code bases2} is {@code null}.
+     * @throws ArrayIndexOutOfBoundsException if:
+     * <ul>
+     *      <li>{@code offset1} is not within the range [0,{@code bases1.length}) or</li>
+     *     <li>{@code offset2} is not within the range [0,{@code bases2.length}) or</li>
+     *     <li>{@code offset1 + length} is not within the range [0,{@code bases1.length}) or </li>
+     *     <li>{@code offset2 + length} is not within the range [0,{@code bases2.length})</li>
+     * </ul>
+     * @return
+     */
+    static public boolean basesAreEqualIgnoreAmbiguous(final byte[] bases1, final int offset1, final byte[] bases2, final int offset2, final int length) {
+        for (int i = 0; i < length; i++)
+            if (!basesAreEqualIgnoreAmbiguous(bases1[offset1 + i],bases2[offset2 + i])) return false;
+        return true;
+    }
+
+    static public boolean extendedBasesAreEqual(byte base1, byte base2) {
+        return extendedBaseToBaseIndex(base1) == extendedBaseToBaseIndex(base2);
+    }
+
+    /**
+     * @return true iff the bases array contains at least one instance of base
+     */
+    static public boolean containsBase(final byte[] bases, final byte base) {
+        for ( final byte b : bases ) {
+            if ( b == base )
+                return true;
+        }
+        return false;
+    }
+
+    public static boolean isUpperCase(final byte[] bases) {
+        for ( byte base : bases )
+            if ( ! isUpperCase(base) )
+                return false;
+        return true;
+    }
+
+    public static boolean isUpperCase(final byte base) {
+        return base >= 'A' && base <= 'Z';
+    }
+
+    public static byte[] convertIUPACtoN(final byte[] bases, final boolean errorOnBadReferenceBase, final boolean ignoreConversionOfFirstByte) {
+        final int length = bases.length;
+        final int start = ignoreConversionOfFirstByte ? 1 : 0;
+
+        for ( int i = start; i < length; i++ ) {
+            final int baseIndex = baseIndexWithIupacMap[bases[i]];
+            if ( baseIndex == Base.N.ordinal() ) {
+                bases[i] = 'N';
+            } else if ( errorOnBadReferenceBase && baseIndex == -1 ) {
+                throw new UserException.BadInput("We encountered a non-standard non-IUPAC base in the provided reference: '" + bases[i] + "'");
+            }
+        }
+        return bases;
+    }
+
+    /**
+     * Converts a IUPAC nucleotide code to a pair of bases
+     *
+     * @param code
+     * @return 0, 1, 2, 3, or -1 if the base can't be understood
+     */
+    @Deprecated
+    static public char[] iupacToBases(char code) {
+        char[] bases = new char[2];
+        switch (code) {
+            case '*':               // the wildcard character counts as an A
+            case 'A':
+            case 'a':
+                bases[0] = bases[1] = 'A';
+                break;
+            case 'C':
+            case 'c':
+                bases[0] = bases[1] = 'C';
+                break;
+            case 'G':
+            case 'g':
+                bases[0] = bases[1] = 'G';
+                break;
+            case 'T':
+            case 't':
+                bases[0] = bases[1] = 'T';
+                break;
+            case 'R':
+            case 'r':
+                bases[0] = 'A';
+                bases[1] = 'G';
+                break;
+            case 'Y':
+            case 'y':
+                bases[0] = 'C';
+                bases[1] = 'T';
+                break;
+            case 'S':
+            case 's':
+                bases[0] = 'G';
+                bases[1] = 'C';
+                break;
+            case 'W':
+            case 'w':
+                bases[0] = 'A';
+                bases[1] = 'T';
+                break;
+            case 'K':
+            case 'k':
+                bases[0] = 'G';
+                bases[1] = 'T';
+                break;
+            case 'M':
+            case 'm':
+                bases[0] = 'A';
+                bases[1] = 'C';
+                break;
+            default:
+                bases[0] = bases[1] = 'N';
+        }
+        return bases;
+    }
+
+    /**
+     * Converts a pair of bases to their IUPAC ambiguity code
+     *
+     * @param base1  1st base
+     * @param base2  2nd base
+     * @return byte
+     */
+    static public byte basesToIUPAC(final byte base1, final byte base2) {
+        // ensure that the bases come in order
+        if ( base2 < base1 )
+            return basesToIUPAC(base2, base1);
+
+        // ensure that the bases are regular ones
+        if ( !isRegularBase(base1) || !isRegularBase(base2) )
+            return Base.N.base;
+
+        // IUPAC codes are not needed if the bases are identical
+        if ( basesAreEqual(base1, base2) )
+            return base1;
+
+        if ( base1 == Base.A.base )
+            return (byte)(base2 == Base.C.base ? 'M' : (base2 == Base.G.base ? 'R' : 'W'));
+
+        if ( base1 == Base.C.base )
+            return (byte)(base2 == Base.G.base ? 'S' : 'Y');
+
+        // the only possibility left is G/T
+        return 'K';
+    }
+
+    /**
+     * Converts a simple base to a base index
+     *
+     * @param base [AaCcGgTt]
+     * @return 0, 1, 2, 3, or -1 if the base can't be understood
+     */
+    static public int simpleBaseToBaseIndex(final byte base) {
+        if ( base < 0 || base >= 256 )
+            throw new UserException.BadInput("Non-standard bases were encountered in either the input reference or BAM file(s)");
+        return baseIndexMap[base];
+    }
+
+    /**
+     * Converts a simple base to a base index
+     *
+     * @param base [AaCcGgTt]
+     * @return 0, 1, 2, 3, or -1 if the base can't be understood
+     */
+    @Deprecated
+    static public int simpleBaseToBaseIndex(char base) {
+        return baseIndexMap[base];
+    }
+
+    static public int extendedBaseToBaseIndex(byte base) {
+        switch (base) {
+            case 'd':
+            case 'D':
+                return Base.D.ordinal();
+            case 'n':
+            case 'N':
+                return Base.N.ordinal();
+
+            default:
+                return simpleBaseToBaseIndex(base);
+        }
+    }
+
+    @Deprecated
+    static public boolean isRegularBase( final char base ) {
+        return simpleBaseToBaseIndex(base) != -1;
+    }
+
+    static public boolean isRegularBase( final byte base ) {
+        return simpleBaseToBaseIndex(base) != -1;
+    }
+
+    static public boolean isAllRegularBases( final byte[] bases ) {
+        for( final byte base : bases) {
+            if( !isRegularBase(base) ) { return false; }
+        }
+        return true;
+    }
+
+    static public boolean isNBase(byte base) {
+        return base == 'N' || base == 'n';
+    }
+
+    /**
+     * Converts a base index to a simple base
+     *
+     * @param baseIndex 0, 1, 2, 3
+     * @return A, C, G, T, or '.' if the index can't be understood
+     */
+    static public byte baseIndexToSimpleBase(int baseIndex) {
+        switch (baseIndex) {
+            case 0:
+                return 'A';
+            case 1:
+                return 'C';
+            case 2:
+                return 'G';
+            case 3:
+                return 'T';
+            default:
+                return '.';
+        }
+    }
+
+    /**
+     * Return the complement (A <-> T or C <-> G) of a base, or the specified base if it can't be complemented (i.e. an ambiguous base).
+     *
+     * @param base the base [AaCcGgTt]
+     * @return the complementary base, or the input base if it's not one of the understood ones
+     */
+    static public byte simpleComplement(byte base) {
+        switch (base) {
+            case 'A':
+            case 'a':
+                return 'T';
+            case 'C':
+            case 'c':
+                return 'G';
+            case 'G':
+            case 'g':
+                return 'C';
+            case 'T':
+            case 't':
+                return 'A';
+            default:
+                return base;
+        }
+    }
+
+    @Deprecated
+    static private char simpleComplement(char base) {
+        return (char) simpleComplement((byte) base);
+    }
+
+    /**
+     * Reverse complement a byte array of bases (that is, chars casted to bytes, *not* base indices in byte form)
+     *
+     * @param bases the byte array of bases
+     * @return the reverse complement of the base byte array
+     */
+    static public byte[] simpleReverseComplement(byte[] bases) {
+        byte[] rcbases = new byte[bases.length];
+
+        for (int i = 0; i < bases.length; i++) {
+            rcbases[i] = simpleComplement(bases[bases.length - 1 - i]);
+        }
+
+        return rcbases;
+    }
+
+    /**
+     * Reverse complement a char array of bases
+     *
+     * @param bases the char array of bases
+     * @return the reverse complement of the char byte array
+     */
+    @Deprecated
+    static public char[] simpleReverseComplement(char[] bases) {
+        char[] rcbases = new char[bases.length];
+
+        for (int i = 0; i < bases.length; i++) {
+            rcbases[i] = simpleComplement(bases[bases.length - 1 - i]);
+        }
+
+        return rcbases;
+    }
+
+    /**
+     * Reverse complement a String of bases.  Preserves ambiguous bases.
+     *
+     * @param bases the String of bases
+     * @return the reverse complement of the String
+     */
+    @Deprecated
+    static public String simpleReverseComplement(String bases) {
+        return new String(simpleReverseComplement(bases.getBytes()));
+    }
+
+    /**
+     * Returns the uppercased version of the bases
+     *
+     * @param bases   the bases
+     * @return the upper cased version
+     */
+    static public void convertToUpperCase(final byte[] bases) {
+        StringUtil.toUpperCase(bases);
+    }
+
+    /**
+     * Returns the index of the most common base in the basecounts array. To be used with
+     * pileup.getBaseCounts.
+     *
+     * @param baseCounts counts of a,c,g,t in order.
+     * @return the index of the most common base
+     */
+    static public int mostFrequentBaseIndex(int[] baseCounts) {
+        int mostFrequentBaseIndex = 0;
+        for (int baseIndex = 1; baseIndex < 4; baseIndex++) {
+            if (baseCounts[baseIndex] > baseCounts[mostFrequentBaseIndex]) {
+                mostFrequentBaseIndex = baseIndex;
+            }
+        }
+        return mostFrequentBaseIndex;
+    }
+
+    static public int mostFrequentBaseIndexNotRef(int[] baseCounts, int refBaseIndex) {
+        int tmp = baseCounts[refBaseIndex];
+        baseCounts[refBaseIndex] = -1;
+        int result = mostFrequentBaseIndex(baseCounts);
+        baseCounts[refBaseIndex] = tmp;
+        return result;
+    }
+
+    static public int mostFrequentBaseIndexNotRef(int[] baseCounts, byte refSimpleBase) {
+        return mostFrequentBaseIndexNotRef(baseCounts, simpleBaseToBaseIndex(refSimpleBase));
+    }
+
+    /**
+     * Returns the most common base in the basecounts array. To be used with pileup.getBaseCounts.
+     *
+     * @param baseCounts counts of a,c,g,t in order.
+     * @return the most common base
+     */
+    static public byte mostFrequentSimpleBase(int[] baseCounts) {
+        return baseIndexToSimpleBase(mostFrequentBaseIndex(baseCounts));
+    }
+
+    /**
+     * For the most frequent base in the sequence, return the percentage of the read it constitutes.
+     *
+     * @param sequence the read sequence
+     * @return the percentage of the read that's made up of the most frequent base
+     */
+    static public double mostFrequentBaseFraction(byte[] sequence) {
+        int[] baseCounts = new int[4];
+
+        for (byte base : sequence) {
+            int baseIndex = simpleBaseToBaseIndex(base);
+
+            if (baseIndex >= 0) {
+                baseCounts[baseIndex]++;
+            }
+        }
+
+        int mostFrequentBaseIndex = mostFrequentBaseIndex(baseCounts);
+
+        return ((double) baseCounts[mostFrequentBaseIndex]) / ((double) sequence.length);
+    }
+
+    // --------------------------------------------------------------------------------
+    //
+    // random bases
+    //
+    // --------------------------------------------------------------------------------
+
+    /**
+     * Return a random base index (A=0, C=1, G=2, T=3).
+     *
+     * @return a random base index (A=0, C=1, G=2, T=3)
+     */
+    static public int getRandomBaseIndex() {
+        return getRandomBaseIndex(-1);
+    }
+
+    /**
+     * Return random bases.
+     *
+     * @param length base count and length of returned array.
+     *
+     * @throws IllegalArgumentException if {@code length} is less than 0.
+     *
+     * @return never {@code null}
+     */
+    @SuppressWarnings("unused")
+    public static byte[] getRandomBases(final int length) {
+        if (length < 0)
+            throw new IllegalArgumentException("length must zero or greater");
+        final byte[] result = new byte[length];
+        fillWithRandomBases(result);
+        return result;
+    }
+
+    /**
+     * Fills an array with random bases.
+     *
+     * @param dest the array to fill.
+     *
+     * @throws IllegalArgumentException if {@code result} is {@code null}.
+     */
+    public static void fillWithRandomBases(final byte[] dest) {
+        fillWithRandomBases(dest,0,dest.length);
+    }
+
+    /**
+     * Fill an array section with random bases.
+     *
+     * @param dest array to fill.
+     * @param fromIndex first index to be filled (inclusive).
+     * @param toIndex index after last to be filled (exclusive).
+     *
+     * @throws IllegalArgumentException if {@code dest} is {@code null},
+     *              {@code fromIndex} or {@code toIndex} is negative,
+     *              {@code fromIndex} or {@code toIndex} are greater than {@code dest} length,
+     *              or {@code fromIndex} greater than {@code toIndex}.
+     */
+    public static void fillWithRandomBases(final byte[] dest, final int fromIndex, final int toIndex) {
+        final Random rnd = GenomeAnalysisEngine.getRandomGenerator();
+        if (dest == null)
+            throw new IllegalArgumentException("the dest array cannot be null");
+        if (fromIndex > toIndex)
+            throw new IllegalArgumentException("fromIndex cannot be larger than toIndex");
+        if (fromIndex < 0)
+            throw new IllegalArgumentException("both indexes must be positive");
+        if (toIndex > dest.length)
+            throw new IllegalArgumentException("both indexes must be less or equal to the destination array length");
+
+        for (int i = fromIndex; i < toIndex; i++)
+            dest[i] = baseIndexToSimpleBase(rnd.nextInt(4));
+    }
+
+    /**
+     * Return a random base index, excluding some base index.
+     *
+     * @param excludeBaseIndex the base index to exclude
+     * @return a random base index, excluding the one specified (A=0, C=1, G=2, T=3)
+     */
+    static public int getRandomBaseIndex(int excludeBaseIndex) {
+        int randomBaseIndex = excludeBaseIndex;
+
+        while (randomBaseIndex == excludeBaseIndex) {
+            randomBaseIndex = GenomeAnalysisEngine.getRandomGenerator().nextInt(4);
+        }
+
+        return randomBaseIndex;
+    }
+
+    public static byte getComplement(byte base) {
+        switch(base) {
+            case 'a':
+            case 'A':
+                return 'T';
+            case 'c':
+            case 'C':
+                return 'G';
+            case 'g':
+            case 'G':
+                return 'C';
+            case 't':
+            case 'T':
+                return 'A';
+            case 'n':
+            case 'N':
+                return 'N';
+            default:
+                throw new ReviewedGATKException("base must be A, C, G or T. " + (char) base + " is not a valid base.");
+        }
+    }
+
+
+    /**
+     * Lexicographical sorting of base arrays {@link Comparator}.
+     */
+    public static final Comparator<byte[]> BASES_COMPARATOR = new Comparator<byte[]> (){
+
+        @Override
+        public int compare(final byte[] o1,final byte[] o2) {
+            final int minLength = Math.min(o1.length,o2.length);
+            for (int i = 0; i < minLength; i++) {
+                final int cmp = Byte.compare(o1[i],o2[i]);
+                if (cmp != 0) return cmp;
+            }
+            if (o1.length == o2.length)
+                return 0;
+            else if (o1.length == minLength)
+                return -1;
+            else
+                return 1;
+        }
+    };
+}
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/BitSetUtils.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/BitSetUtils.java
new file mode 100644
index 0000000..a9ab00d
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/BitSetUtils.java
@@ -0,0 +1,134 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.utils;
+
+import java.util.BitSet;
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * Utilities for bitset conversion
+ *
+ * @author Mauricio Carneiro
+ * @since 3/5/12
+ */
+public class BitSetUtils {
+
+    static final private byte NBITS_LONG_REPRESENTATION = 64;                   // the number of bits used in the long version to represent the bit set (necessary for the two's complement representation of negative numbers)
+    static final private byte NBITS_SHORT_REPRESENTATION = 16;                  // the number of bits used in the short version to represent the bit set (necessary for the two's complement representation of negative numbers)
+
+    /**
+     * Creates an long out of a bitset
+     *
+     * @param bitSet the bitset
+     * @return a long from the bitset representation
+     */
+    public static long longFrom(final BitSet bitSet) {
+        return longFrom(bitSet, NBITS_LONG_REPRESENTATION);
+    }
+
+    /**
+     * Creates a short integer from a bitset
+     *
+     * @param bitSet the bitset
+     * @return a short from the bitset representation
+     */
+    public static short shortFrom(final BitSet bitSet) {
+        return (short) longFrom(bitSet, NBITS_SHORT_REPRESENTATION);
+    }
+
+    /**
+     * Cretes an integer with any number of bits (up to 64 -- long precision) from a bitset
+     *
+     * @param bitSet the bitset
+     * @param nBits  the number of bits to be used for this representation
+     * @return an integer with nBits from the bitset representation
+     */
+    public static long longFrom(final BitSet bitSet, final int nBits) {
+        long number = 0;
+        for (int bitIndex = bitSet.nextSetBit(0); bitIndex >= 0 && bitIndex <= nBits; bitIndex = bitSet.nextSetBit(bitIndex + 1))
+            number |= 1L << bitIndex;
+
+        return number;
+    }
+
+    /**
+     * Creates a BitSet representation of a given long
+     *
+     * @param number the number to turn into a bitset
+     * @return a bitset representation of the long
+     */
+    public static BitSet bitSetFrom(long number) {
+        return bitSetFrom(number, NBITS_LONG_REPRESENTATION);
+    }
+
+    /**
+     * Creates a BitSet representation of a given short
+     *
+     * @param number the number to turn into a bitset
+     * @return a bitset representation of the short
+     */
+    public static BitSet bitSetFrom(short number) {
+        BitSet result = shortCache.get(number);
+        if (result == null) {
+            result = bitSetFrom(number, NBITS_SHORT_REPRESENTATION);
+            shortCache.put(number, result);
+        }
+        return result;
+    }
+    // use a static cache for shorts (but not for longs, because there could be a lot of entries)
+    private static final Map<Short, BitSet> shortCache = new HashMap<Short, BitSet>(2 * Short.MAX_VALUE);
+
+    /**
+     * Creates a BitSet representation of an arbitrary integer (number of bits capped at 64 -- long precision)
+     *
+     * @param number the number to turn into a bitset
+     * @param nBits  the number of bits to use as precision for this conversion
+     * @return a bitset representation of the integer
+     */
+    public static BitSet bitSetFrom(long number, int nBits) {
+        BitSet bitSet = new BitSet(nBits);
+        boolean isNegative = number < 0;
+        int bitIndex = 0;
+        while (number != 0) {
+            if (number % 2 != 0)
+                bitSet.set(bitIndex);
+            bitIndex++;
+            number /= 2;
+        }
+        if (isNegative) {
+            boolean foundFirstSetBit = false;
+            for (int i = bitSet.nextSetBit(0); i < nBits && i >= 0; i++) {
+                boolean bit = bitSet.get(i);
+                if (!foundFirstSetBit && bit)
+                    foundFirstSetBit = true;    // maintain all bits until the first 1 is found (inclusive)
+                else if (foundFirstSetBit)
+                    bitSet.flip(i);             // flip every other bit up to NBITS_REPRESENTATION
+            }
+        }
+        return bitSet;
+    }
+}
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/ContigComparator.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/ContigComparator.java
new file mode 100644
index 0000000..f3f93b4
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/ContigComparator.java
@@ -0,0 +1,80 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.utils;
+
+import htsjdk.samtools.SAMSequenceDictionary;
+
+import java.util.Comparator;
+import java.util.Set;
+import java.util.TreeSet;
+
+/**
+ * Created by IntelliJ IDEA.
+ * User: carneiro
+ * Date: 7/23/11
+ * Time: 6:07 PM
+ *
+ * Contig comparator -- sorting contigs like Picard
+ *
+ *   This is very useful if you want to output your text files or manipulate data in the usual chromosome ordering :
+ *    1
+ *    2
+ *    3
+ *    ...
+ *    21
+ *    22
+ *    X
+ *    Y
+ *    GL***
+ *    ...
+ * Just use this comparator in any SortedSet class constructor and your data will be sorted like in the BAM file.
+ */
+public class ContigComparator implements Comparator<String> {
+    final SAMSequenceDictionary dict;
+
+    public ContigComparator(final SAMSequenceDictionary dict) {
+        if ( dict == null ) throw new IllegalArgumentException("dict cannot be null");
+        this.dict = dict;
+    }
+
+    @Override
+    public int compare(final String chr1, final String chr2) {
+        final int index1 = getIndex(chr1);
+        final int index2 = getIndex(chr2);
+        return Integer.valueOf(index1).compareTo(index2);
+    }
+
+    /**
+     * Convert contig to its index in the dict, or throw an exception if it's not found or is null
+     * @param chr the contig
+     */
+    private int getIndex(final String chr) {
+        if ( chr == null ) throw new IllegalArgumentException("chr is null");
+        final int index = dict.getSequenceIndex(chr);
+        if ( index == -1 ) throw new IllegalArgumentException("Unknown contig " + chr);
+        return index;
+    }
+}
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/DeprecatedToolChecks.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/DeprecatedToolChecks.java
new file mode 100644
index 0000000..9fcd848
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/DeprecatedToolChecks.java
@@ -0,0 +1,96 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.utils;
+
+import it.unimi.dsi.fastutil.objects.Object2ObjectMap;
+import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap;
+
+import java.util.*;
+
+/**
+ * Utility class for handling deprecated tools gracefully
+ *
+ * @author vdauwera
+ * @since 3/11/13
+ */
+public class DeprecatedToolChecks {
+
+    // Mapping from walker name to major version number where the walker first disappeared and optional replacement options
+    private static Object2ObjectMap deprecatedGATKWalkers = new Object2ObjectOpenHashMap();
+    static {
+        // Indicate recommended replacement in parentheses if applicable
+        deprecatedGATKWalkers.put("ReduceReads", "3.0 (use recommended best practices pipeline with the HaplotypeCaller)");
+        deprecatedGATKWalkers.put("CountCovariates", "2.0 (use BaseRecalibrator instead; see documentation for usage)");
+        deprecatedGATKWalkers.put("TableRecalibration", "2.0 (use PrintReads with -BQSR instead; see documentation for usage)");
+        deprecatedGATKWalkers.put("AlignmentWalker", "2.2 (no replacement)");
+        deprecatedGATKWalkers.put("CountBestAlignments", "2.2 (no replacement)");
+        deprecatedGATKWalkers.put("SomaticIndelDetector", "2.0 (replaced by the standalone tool Indelocator; see Cancer Tools documentation)");
+    }
+
+    // Mapping from walker name to major version number where the walker first disappeared and optional replacement options
+    private static Object2ObjectMap deprecatedGATKAnnotations = new Object2ObjectOpenHashMap();
+    static {
+        // Same comments as for walkers
+        deprecatedGATKAnnotations.put("DepthOfCoverage", "2.4 (renamed to Coverage)");
+    }
+
+    /**
+     * Utility method to check whether a given walker has been deprecated in a previous GATK release
+     *
+     * @param walkerName   the walker class name (not the full package) to check
+     */
+    public static boolean isDeprecatedWalker(final String walkerName) {
+        return deprecatedGATKWalkers.containsKey(walkerName);
+    }
+
+    /**
+     * Utility method to check whether a given annotation has been deprecated in a previous GATK release
+     *
+     * @param annotationName   the annotation class name (not the full package) to check
+     */
+    public static boolean isDeprecatedAnnotation(final String annotationName) {
+        return deprecatedGATKAnnotations.containsKey(annotationName);
+    }
+
+    /**
+     * Utility method to pull up the version number at which a walker was deprecated and the suggested replacement, if any
+     *
+     * @param walkerName   the walker class name (not the full package) to check
+     */
+    public static String getWalkerDeprecationInfo(final String walkerName) {
+        return deprecatedGATKWalkers.get(walkerName).toString();
+    }
+
+    /**
+     * Utility method to pull up the version number at which an annotation was deprecated and the suggested replacement, if any
+     *
+     * @param annotationName   the annotation class name (not the full package) to check
+     */
+    public static String getAnnotationDeprecationInfo(final String annotationName) {
+        return deprecatedGATKAnnotations.get(annotationName).toString();
+    }
+
+}
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/GenomeLocParser.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/GenomeLocParser.java
new file mode 100644
index 0000000..55e6624
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/GenomeLocParser.java
@@ -0,0 +1,622 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.utils;
+
+import com.google.java.contract.Ensures;
+import com.google.java.contract.Requires;
+import com.google.java.contract.ThrowEnsures;
+import htsjdk.samtools.reference.ReferenceSequenceFile;
+import htsjdk.samtools.SAMRecord;
+import htsjdk.samtools.SAMSequenceDictionary;
+import htsjdk.samtools.SAMSequenceRecord;
+import org.apache.log4j.Logger;
+import htsjdk.tribble.Feature;
+import org.broadinstitute.gatk.utils.exceptions.ReviewedGATKException;
+import org.broadinstitute.gatk.utils.exceptions.UserException;
+
+/**
+ * Factory class for creating GenomeLocs
+ */
+public final class GenomeLocParser {
+    private static Logger logger = Logger.getLogger(GenomeLocParser.class);
+
+    /**
+     * How much validation should we do at runtime with this parser?
+     */
+    public enum ValidationLevel {
+        /** Do the standard amount of validation */
+        STANDARD,
+        /** Don't do any real checking at all */
+        NONE
+    }
+
+    // --------------------------------------------------------------------------------------------------------------
+    //
+    // Ugly global variable defining the optional ordering of contig elements
+    //
+    // --------------------------------------------------------------------------------------------------------------
+
+    /**
+     * This single variable holds the underlying SamSequenceDictionary used by the GATK.  We assume
+     * it is thread safe.
+     */
+    final private SAMSequenceDictionary SINGLE_MASTER_SEQUENCE_DICTIONARY;
+
+    /**
+     * A thread-local CachingSequenceDictionary
+     */
+    private final ThreadLocal<MRUCachingSAMSequenceDictionary> contigInfoPerThread =
+            new ThreadLocal<MRUCachingSAMSequenceDictionary>() {
+                @Override
+                protected MRUCachingSAMSequenceDictionary initialValue() {
+                    return new MRUCachingSAMSequenceDictionary(SINGLE_MASTER_SEQUENCE_DICTIONARY);
+                }
+            };
+
+    /**
+     * How much validation are we doing at runtime with this GenomeLocParser?
+     */
+    private final ValidationLevel validationLevel;
+
+    /**
+     * @return a caching sequence dictionary appropriate for this thread
+     */
+    private MRUCachingSAMSequenceDictionary getContigInfo() {
+        return contigInfoPerThread.get();
+    }
+
+    /**
+     * set our internal reference contig order
+     * @param refFile the reference file
+     */
+    @Requires("refFile != null")
+    public GenomeLocParser(final ReferenceSequenceFile refFile) {
+        this(refFile.getSequenceDictionary());
+    }
+
+    /**
+     * Create a new GenomeLocParser based on seqDictionary with the standard validation level
+     * @param seqDict a non-null sequence dictionary
+     */
+    public GenomeLocParser(SAMSequenceDictionary seqDict) {
+        this(seqDict, ValidationLevel.STANDARD);
+    }
+
+    /**
+     * Create a genome loc parser based on seqDict with the specified level of validation
+     * @param seqDict the sequence dictionary to use when creating genome locs
+     * @param validationLevel how much validation should we do of the genome locs at runtime? Purely for testing purposes
+     */
+    protected GenomeLocParser(SAMSequenceDictionary seqDict, final ValidationLevel validationLevel) {
+        if (validationLevel == null)
+            throw new IllegalArgumentException("validation level cannot be null");
+        if (seqDict == null) { // we couldn't load the reference dictionary
+            //logger.info("Failed to load reference dictionary, falling back to lexicographic order for contigs");
+            throw new UserException.CommandLineException("Failed to load reference dictionary");
+        }
+
+        this.validationLevel = validationLevel;
+        this.SINGLE_MASTER_SEQUENCE_DICTIONARY = seqDict;
+        if ( logger.isDebugEnabled() ) {
+            logger.debug(String.format("Prepared reference sequence contig dictionary"));
+            for (SAMSequenceRecord contig : seqDict.getSequences()) {
+                logger.debug(String.format(" %s (%d bp)", contig.getSequenceName(), contig.getSequenceLength()));
+            }
+        }
+    }
+
+    /**
+     * Determines whether the given contig is valid with respect to the sequence dictionary
+     * already installed in the GenomeLoc.
+     *
+     * @param contig a potentially null string name for the contig
+     * @return True if the contig is valid.  False otherwise.
+     */
+    public final boolean contigIsInDictionary(final String contig) {
+        return contig != null && getContigInfo().hasContig(contig);
+    }
+
+    /**
+     * get the contig's SAMSequenceRecord
+     *
+     * @param contig the string name of the contig
+     *
+     * @return the sam sequence record
+     */
+    @Ensures("result != null")
+    @ThrowEnsures({"UserException.MalformedGenomeLoc", "!contigIsInDictionary(contig) || contig == null"})
+    public final SAMSequenceRecord getContigInfo(final String contig) {
+        if ( contig == null || ! contigIsInDictionary(contig) )
+            throw new UserException.MalformedGenomeLoc(String.format("Contig %s given as location, but this contig isn't present in the Fasta sequence dictionary", contig));
+        return getContigInfo().getSequence(contig);
+    }
+
+    /**
+     * Returns the contig index of a specified string version of the contig
+     *
+     * @param contig the contig string
+     *
+     * @return the contig index, -1 if not found
+     */
+    @Ensures("result >= 0")
+    @ThrowEnsures({"UserException.MalformedGenomeLoc", "!contigIsInDictionary(contig) || contig == null"})
+    public final int getContigIndex(final String contig) {
+        return getContigInfo(contig).getSequenceIndex();
+    }
+
+    @Requires("contig != null")
+    protected int getContigIndexWithoutException(final String contig) {
+        if ( contig == null || ! getContigInfo().hasContig(contig) )
+            return -1;
+        return getContigInfo().getSequenceIndex(contig);
+    }
+
+    /**
+     * Return the master sequence dictionary used within this GenomeLocParser
+     * @return
+     */
+    public final SAMSequenceDictionary getContigs() {
+        return getContigInfo().getDictionary();
+    }
+
+    // --------------------------------------------------------------------------------------------------------------
+    //
+    // Low-level creation functions
+    //
+    // --------------------------------------------------------------------------------------------------------------
+
+    /**
+     * @see #createGenomeLoc(String, int, int, int, boolean) for exact details of the creation.
+     *
+     * Note that because this function doesn't take the contig index as an argument for contig, it
+     * has a slight performance penalty over the version that does take the contig index.  Does not
+     * require the created genome loc on the reference genome
+     */
+    @Ensures("result != null")
+    @ThrowEnsures({"UserException.MalformedGenomeLoc", "!isValidGenomeLoc(contig, start, stop)"})
+    public GenomeLoc createGenomeLoc(String contig, final int start, final int stop) {
+        return createGenomeLoc(contig, getContigIndex(contig), start, stop);
+    }
+
+    /**
+     * @see #createGenomeLoc(String, int, int, int, boolean) for exact details of the creation.
+     *
+     * Note that because this function doesn't take the contig index as an argument for contig, it
+     * has a slight performance penalty over the version that does take the contig index.
+     */
+    public GenomeLoc createGenomeLoc(final String contig, final int start, final int stop, boolean mustBeOnReference) {
+        return createGenomeLoc(contig, getContigIndex(contig), start, stop, mustBeOnReference);
+    }
+
+    /**
+     * @see #createGenomeLoc(String, int, int, int, boolean) for exact details of the creation.
+     *
+     * Doesn't require the start and stop to be on the genome
+     */
+    @ThrowEnsures({"UserException.MalformedGenomeLoc", "!isValidGenomeLoc(contig, start, stop, false)"})
+    public GenomeLoc createGenomeLoc(String contig, int index, final int start, final int stop) {
+        return createGenomeLoc(contig, index, start, stop, false);
+    }
+
+    /**
+     * Create a GenomeLoc on contig, starting at start and ending (inclusive) at stop.
+     *
+     * @param contig the contig name
+     * @param index the index into the GATK's SAMSequencingDictionary of contig (passed for efficiency to avoid the lookup)
+     * @param start the starting position
+     * @param stop  the stop position of this loc, inclusive
+     * @param mustBeOnReference if true, this factory will throw a UserException.MalformedGenomeLoc if start or stop isn't on the contig
+     *
+     * @return a non-null GenomeLoc
+     */
+    @ThrowEnsures({"UserException.MalformedGenomeLoc", "!isValidGenomeLoc(contig, start, stop,mustBeOnReference)"})
+    @Ensures("result != null")
+    public GenomeLoc createGenomeLoc(final String contig, int index, final int start, final int stop, boolean mustBeOnReference) {
+        // optimization: by interning the string we ensure that future comparisons use == not the full string comp
+        final String interned = validateGenomeLoc(contig, index, start, stop, mustBeOnReference);
+        return new GenomeLoc(interned, index, start, stop);
+    }
+
+    /**
+     * Create a new GenomeLoc, on contig, including the single position pos.
+     *
+     * Pos is not required to be on the reference
+     *
+     * @see #createGenomeLoc(String, int, int, int, boolean) for exact details of the creation.
+     *
+     * @param contig the contig name
+     * @param pos    the start and stop of the created genome loc
+     *
+     * @return a genome loc representing a single base at the specified postion on the contig
+     */
+    @Ensures("result != null")
+    @ThrowEnsures({"UserException.MalformedGenomeLoc", "!isValidGenomeLoc(contig, pos, pos, true)"})
+    public GenomeLoc createGenomeLoc(final String contig, final int pos) {
+        return createGenomeLoc(contig, getContigIndex(contig), pos, pos);
+    }
+
+    /**
+     * validate a position or interval on the genome as valid
+     *
+     * Requires that contig exist in the master sequence dictionary, and that contig index be valid as well.  Requires
+     * that start <= stop.
+     *
+     * if mustBeOnReference is true,
+     * performs boundary validation for genome loc INTERVALS:
+     * start and stop are on contig and start <= stop
+     *
+     * @param contig the contig name
+     * @param start  the start position
+     * @param stop   the stop position
+     *
+     * @return the interned contig name, an optimization that ensures that contig == the string in the sequence dictionary
+     */
+    protected String validateGenomeLoc(final String contig, final int contigIndex, final int start, final int stop, final boolean mustBeOnReference) {
+        if ( validationLevel == ValidationLevel.NONE )
+            return contig;
+        else {
+            if (stop < start)
+                vglHelper(String.format("The stop position %d is less than start %d in contig %s", stop, start, contig));
+
+            final SAMSequenceRecord contigInfo = getContigInfo().getSequence(contig);
+            if ( contigInfo.getSequenceIndex() != contigIndex )
+                vglHelper(String.format("The contig index %d is bad, doesn't equal the contig index %d of the contig from a string %s",
+                        contigIndex, contigInfo.getSequenceIndex(), contig));
+
+            if ( mustBeOnReference ) {
+                if (start < 1)
+                    vglHelper(String.format("The start position %d is less than 1", start));
+
+                if (stop < 1)
+                    vglHelper(String.format("The stop position %d is less than 1", stop));
+
+                final int contigSize = contigInfo.getSequenceLength();
+                if (start > contigSize || stop > contigSize)
+                    vglHelper(String.format("The genome loc coordinates %d-%d exceed the contig size (%d)", start, stop, contigSize));
+            }
+
+            return contigInfo.getSequenceName();
+        }
+    }
+
+    /**
+     * Would a genome loc created with the given parameters be valid w.r.t. the master sequence dictionary?
+     * @param contig the contig we'd use
+     * @param start the start position
+     * @param stop the stop
+     * @param mustBeOnReference should we require the resulting genome loc to be completely on the reference genome?
+     * @return true if this would produce a valid genome loc, false otherwise
+     */
+    public boolean isValidGenomeLoc(String contig, int start, int stop, boolean mustBeOnReference ) {
+        try {
+            validateGenomeLoc(contig, getContigIndexWithoutException(contig), start, stop, mustBeOnReference);
+            return true;
+        } catch ( ReviewedGATKException e) {
+            return false;
+        }
+    }
+
+    /**
+     * @see #isValidGenomeLoc(String, int, int) with mustBeOnReference == true
+     */
+    public boolean isValidGenomeLoc(String contig, int start, int stop ) {
+        return isValidGenomeLoc(contig, start, stop, true);
+    }
+
+    private void vglHelper(final String msg) {
+        throw new UserException.MalformedGenomeLoc("Parameters to GenomeLocParser are incorrect:" + msg);
+    }
+
+    // --------------------------------------------------------------------------------------------------------------
+    //
+    // Parsing genome locs
+    //
+    // --------------------------------------------------------------------------------------------------------------
+
+    /**
+     * parse a genome interval, from a location string
+     *
+     * Performs interval-style validation:
+     *
+     * contig is valid; start and stop less than the end; start <= stop, and start/stop are on the contig
+     * @param str the string to parse
+     *
+     * @return a GenomeLoc representing the String
+     *
+     */
+    @Requires("str != null")
+    @Ensures("result != null")
+    public GenomeLoc parseGenomeLoc(final String str) {
+        // 'chr2', 'chr2:1000000' or 'chr2:1,000,000-2,000,000'
+        //System.out.printf("Parsing location '%s'%n", str);
+
+        String contig = null;
+        int start = 1;
+        int stop = -1;
+
+        final int colonIndex = str.lastIndexOf(":");
+        if(colonIndex == -1) {
+            contig = str.substring(0, str.length());  // chr1
+            stop = Integer.MAX_VALUE;
+        } else {
+            contig = str.substring(0, colonIndex);
+            final int dashIndex = str.indexOf('-', colonIndex);
+            try {
+                if(dashIndex == -1) {
+                    if(str.charAt(str.length() - 1) == '+') {
+                        start = parsePosition(str.substring(colonIndex + 1, str.length() - 1));  // chr:1+
+                        stop = Integer.MAX_VALUE;
+                    } else {
+                        start = parsePosition(str.substring(colonIndex + 1));   // chr1:1
+                        stop = start;
+                    }
+                } else {
+                    start = parsePosition(str.substring(colonIndex + 1, dashIndex));  // chr1:1-1
+                    stop = parsePosition(str.substring(dashIndex + 1));
+                }
+            } catch(Exception e) {
+                throw new UserException("Failed to parse Genome Location string: " + str, e);
+            }
+        }
+
+        // is the contig valid?
+        if (!contigIsInDictionary(contig))
+            throw new UserException.MalformedGenomeLoc("Contig '" + contig + "' does not match any contig in the GATK sequence dictionary derived from the reference; are you sure you are using the correct reference fasta file?");
+
+        if (stop == Integer.MAX_VALUE)
+            // lookup the actually stop position!
+            stop = getContigInfo(contig).getSequenceLength();
+
+        return createGenomeLoc(contig, getContigIndex(contig), start, stop, true);
+    }
+
+    /**
+     * Parses a number like 1,000,000 into a long.
+     * @param pos
+     */
+    @Requires("pos != null")
+    @Ensures("result >= 0")
+    protected int parsePosition(final String pos) {
+        if(pos.indexOf('-') != -1) {
+            throw new NumberFormatException("Position: '" + pos + "' can't contain '-'." );
+        }
+
+        if(pos.indexOf(',') != -1) {
+            final StringBuilder buffer = new StringBuilder();
+            for(int i = 0; i < pos.length(); i++) {
+                final char c = pos.charAt(i);
+
+                if(c == ',') {
+                    continue;
+                } else if(c < '0' || c > '9') {
+                    throw new NumberFormatException("Position: '" + pos + "' contains invalid chars." );
+                } else {
+                    buffer.append(c);
+                }
+            }
+            return Integer.parseInt(buffer.toString());
+        } else {
+            return Integer.parseInt(pos);
+        }
+    }
+
+    // --------------------------------------------------------------------------------------------------------------
+    //
+    // Parsing string representations
+    //
+    // --------------------------------------------------------------------------------------------------------------
+
+    /**
+     * Create a genome loc, given a read. If the read is unmapped, *and* yet the read has a contig and start position,
+     * then a GenomeLoc is returned for contig:start-start, otherwise an UNMAPPED GenomeLoc is returned.
+     *
+     * @param read the read from which to create a genome loc
+     *
+     * @return the GenomeLoc that was created
+     */
+    @Requires("read != null")
+    @Ensures("result != null")
+    public GenomeLoc createGenomeLoc(final SAMRecord read) {
+        if ( read.getReadUnmappedFlag() && read.getReferenceIndex() == -1 )
+            // read is unmapped and not placed anywhere on the genome
+            return GenomeLoc.UNMAPPED;
+        else {
+            // Use Math.max to ensure that end >= start (Picard assigns the end to reads that are entirely within an insertion as start-1)
+            final int end = read.getReadUnmappedFlag() ? read.getAlignmentStart() : Math.max(read.getAlignmentEnd(), read.getAlignmentStart());
+            return createGenomeLoc(read.getReferenceName(), read.getReferenceIndex(), read.getAlignmentStart(), end, false);
+        }
+    }
+
+    /**
+     * Create a genome loc, given a read using its unclipped alignment. If the read is unmapped, *and* yet the read has a contig and start position,
+     * then a GenomeLoc is returned for contig:start-start, otherwise an UNMAPPED GenomeLoc is returned.
+     *
+     * @param read the read from which to create a genome loc
+     *
+     * @return the GenomeLoc that was created
+     */
+    @Requires("read != null")
+    @Ensures("result != null")
+    public GenomeLoc createGenomeLocUnclipped(final SAMRecord read) {
+        if ( read.getReadUnmappedFlag() && read.getReferenceIndex() == -1 )
+            // read is unmapped and not placed anywhere on the genome
+            return GenomeLoc.UNMAPPED;
+        else {
+            // Use Math.max to ensure that end >= start (Picard assigns the end to reads that are entirely within an insertion as start-1)
+            final int end = read.getReadUnmappedFlag() ? read.getUnclippedEnd() : Math.max(read.getUnclippedEnd(), read.getUnclippedStart());
+            return createGenomeLoc(read.getReferenceName(), read.getReferenceIndex(), read.getUnclippedStart(), end, false);
+        }
+    }
+
+    /**
+     * Creates a GenomeLoc from a Tribble feature
+     * @param feature
+     * @return
+     */
+    public GenomeLoc createGenomeLoc(final Feature feature) {
+        return createGenomeLoc(feature.getChr(), feature.getStart(), feature.getEnd());
+    }
+
+    /**
+     * @see GenomeLoc.setStart
+     */
+    @Deprecated
+    public GenomeLoc setStart(final GenomeLoc loc, final int start) {
+        return createGenomeLoc(loc.getContig(), loc.getContigIndex(), start, loc.getStop());
+    }
+
+    /**
+     * @see GenomeLoc.setStop
+     */
+    @Deprecated
+    public GenomeLoc setStop(final GenomeLoc loc, final int stop) {
+        return createGenomeLoc(loc.getContig(), loc.getContigIndex(), loc.start, stop);
+    }
+
+    /**
+     * @see GenomeLoc.incPos
+     */
+    @Deprecated
+    public GenomeLoc incPos(final GenomeLoc loc) {
+        return incPos(loc, 1);
+    }
+
+    /**
+     * @see GenomeLoc.incPos
+     */
+    @Deprecated
+    public GenomeLoc incPos(final GenomeLoc loc, final int by) {
+        return createGenomeLoc(loc.getContig(), loc.getContigIndex(), loc.start + by, loc.stop + by);
+    }
+
+    /**
+     * Creates a GenomeLoc than spans the entire contig.
+     * @param contigName Name of the contig.
+     * @return A locus spanning the entire contig.
+     */
+    @Requires("contigName != null")
+    @Ensures("result != null")
+    public GenomeLoc createOverEntireContig(final String contigName) {
+        SAMSequenceRecord contig = getContigInfo().getSequence(contigName);
+        return createGenomeLoc(contigName,contig.getSequenceIndex(),1,contig.getSequenceLength(), true);
+    }
+
+    /**
+     * Creates a loc to the left (starting at the loc start + 1) of maxBasePairs size.
+     * @param loc The original loc
+     * @param maxBasePairs The maximum number of basePairs
+     * @return The contiguous loc of up to maxBasePairs length or null if the loc is already at the start of the contig.
+     */
+    @Requires({"loc != null", "maxBasePairs > 0"})
+    public GenomeLoc createGenomeLocAtStart(final GenomeLoc loc, final int maxBasePairs) {
+        if (GenomeLoc.isUnmapped(loc))
+            return null;
+        final String contigName = loc.getContig();
+        final SAMSequenceRecord contig = getContigInfo().getSequence(contigName);
+        final int contigIndex = contig.getSequenceIndex();
+
+        int start = loc.getStart() - maxBasePairs;
+        int stop = loc.getStart() - 1;
+
+        if (start < 1)
+            start = 1;
+        if (stop < 1)
+            return null;
+
+        return createGenomeLoc(contigName, contigIndex, start, stop, true);
+    }
+
+    /**
+     * Creates a loc padded in both directions by maxBasePairs size (if possible).
+     * @param loc      The original loc
+     * @param padding  The number of base pairs to pad on either end
+     * @return The contiguous loc of length up to the original length + 2*padding (depending on the start/end of the contig).
+     */
+    @Requires({"loc != null", "padding >= 0"})
+    public GenomeLoc createPaddedGenomeLoc(final GenomeLoc loc, final int padding) {
+        if (GenomeLoc.isUnmapped(loc) || padding == 0)
+            return loc;
+        else
+            return createGenomeLocOnContig(loc.getContig(), loc.getContigIndex(), loc.getStart() - padding, loc.getStop() + padding);
+    }
+
+    /**
+     * Creates a loc to the right (starting at the loc stop + 1) of maxBasePairs size.
+     * @param loc The original loc
+     * @param maxBasePairs The maximum number of basePairs
+     * @return The contiguous loc of up to maxBasePairs length or null if the loc is already at the end of the contig.
+     */
+    @Requires({"loc != null", "maxBasePairs > 0"})
+    public GenomeLoc createGenomeLocAtStop(final GenomeLoc loc, final int maxBasePairs) {
+        if (GenomeLoc.isUnmapped(loc))
+            return null;
+        String contigName = loc.getContig();
+        SAMSequenceRecord contig = getContigInfo().getSequence(contigName);
+        int contigIndex = contig.getSequenceIndex();
+        int contigLength = contig.getSequenceLength();
+
+        int start = loc.getStop() + 1;
+        int stop = loc.getStop() + maxBasePairs;
+
+        if (start > contigLength)
+            return null;
+        if (stop > contigLength)
+            stop = contigLength;
+
+        return createGenomeLoc(contigName, contigIndex, start, stop, true);
+    }
+
+    /**
+     * @see #createGenomeLocOnContig(String, int, int, int) with the contig index looked up from contig
+     */
+    public GenomeLoc createGenomeLocOnContig(final String contig, final int start, final int stop) {
+        return createGenomeLocOnContig(contig, getContigIndex(contig), start, stop);
+    }
+
+    /**
+     * Create a new genome loc, bounding start and stop by the start and end of contig
+     *
+     * This function will return null if start and stop cannot be adjusted in any reasonable way
+     * to be on the contig.  For example, if start and stop are both past the end of the contig,
+     * there's no way to fix this, and null will be returned.
+     *
+     * @param contig our contig
+     * @param start our start as an arbitrary integer (may be negative, etc)
+     * @param stop our stop as an arbitrary integer (may be negative, etc)
+     * @return a valid genome loc over contig, or null if a meaningful genome loc cannot be created
+     */
+    public GenomeLoc createGenomeLocOnContig(final String contig, final int contigIndex, final int start, final int stop) {
+        final int contigLength = getContigInfo().getSequence(contigIndex).getSequenceLength();
+        final int boundedStart = Math.max(1, start);
+        final int boundedStop = Math.min(contigLength, stop);
+
+        if ( boundedStart > contigLength || boundedStop < 1 )
+            // there's no meaningful way to create this genome loc, as the start and stop are off the contig
+            return null;
+        else
+            return createGenomeLoc(contig, contigIndex, boundedStart, boundedStop);
+    }
+}
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/GenomeLocSortedSet.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/GenomeLocSortedSet.java
new file mode 100644
index 0000000..694c271
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/GenomeLocSortedSet.java
@@ -0,0 +1,476 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.utils;
+
+import htsjdk.samtools.SAMSequenceDictionary;
+import htsjdk.samtools.SAMSequenceRecord;
+import org.apache.log4j.Logger;
+import org.broadinstitute.gatk.utils.exceptions.ReviewedGATKException;
+import org.broadinstitute.gatk.utils.interval.IntervalMergingRule;
+import org.broadinstitute.gatk.utils.interval.IntervalUtils;
+
+import java.util.*;
+
+/**
+ *         <p/>
+ *         Class GenomeLocCollection
+ *         <p/>
+ *         a set of genome locations. This collection is self sorting,
+ *         and will merge genome locations that are overlapping. The remove function
+ *         will also remove a region from the list, if the region to remove is a
+ *         partial interval of a region in the collection it will remove the region from
+ *         that element.
+ *
+ * @author aaron
+ * Date: May 22, 2009
+ * Time: 10:54:40 AM
+ */
+public class GenomeLocSortedSet extends AbstractSet<GenomeLoc> {
+    private static Logger logger = Logger.getLogger(GenomeLocSortedSet.class);
+
+    private GenomeLocParser genomeLocParser;
+
+    // our private storage for the GenomeLoc's
+    private final List<GenomeLoc> mArray = new ArrayList<GenomeLoc>();
+
+    // cache this to make overlap checking much more efficient
+    private int previousOverlapSearchIndex = -1;
+
+    /**
+     * Create a new, empty GenomeLocSortedSet
+     *
+     * @param parser a non-null the parser we use to create genome locs
+     */
+    public GenomeLocSortedSet(final GenomeLocParser parser) {
+        if ( parser == null ) throw new IllegalArgumentException("parser cannot be null");
+        this.genomeLocParser = parser;
+    }
+
+    /**
+     * Create a new GenomeLocSortedSet containing location e
+     *
+     * @param parser a non-null the parser we use to create genome locs
+     * @param e a single genome locs to add to this set
+     */
+    public GenomeLocSortedSet(final GenomeLocParser parser, final GenomeLoc e) {
+        this(parser);
+        add(e);
+    }
+
+    /**
+     * Create a new GenomeLocSortedSet containing locations l
+     *
+     * The elements in l can be in any order, and can be overlapping.  They will be sorted first and
+     * overlapping (but not contiguous) elements will be merged
+     *
+     * @param parser a non-null the parser we use to create genome locs
+     * @param l a collection of genome locs to add to this set
+     */
+    public GenomeLocSortedSet(final GenomeLocParser parser, final Collection<GenomeLoc> l) {
+        this(parser);
+
+        final ArrayList<GenomeLoc> sorted = new ArrayList<GenomeLoc>(l);
+        Collections.sort(sorted);
+        mArray.addAll(IntervalUtils.mergeIntervalLocations(sorted, IntervalMergingRule.OVERLAPPING_ONLY));
+    }
+
+    /**
+     * Gets the GenomeLocParser used to create this sorted set.
+     * @return The parser.  Will never be null.
+     */
+    public GenomeLocParser getGenomeLocParser() {
+        return genomeLocParser;
+    }
+
+    /**
+     * get an iterator over this collection
+     *
+     * @return an iterator<GenomeLoc>
+     */
+    public Iterator<GenomeLoc> iterator() {
+        return mArray.iterator();
+    }
+
+    /**
+     * return the size of the collection
+     *
+     * @return the size of the collection
+     */
+    public int size() {
+        return mArray.size();
+    }
+
+    /**
+     * Return the size, in bp, of the genomic regions by all of the regions in this set
+     * @return size in bp of the covered regions
+     */
+    public long coveredSize() {
+        long s = 0;
+        for ( GenomeLoc e : this )
+            s += e.size();
+        return s;
+    }
+
+    /**
+     * Return the number of bps before loc in the sorted set
+     *
+     * @param loc the location before which we are counting bases
+     * @return the number of base pairs over all previous intervals
+     */
+    public long sizeBeforeLoc(GenomeLoc loc) {
+        long s = 0;
+
+        for ( GenomeLoc e : this ) {
+            if ( e.isBefore(loc) )
+                s += e.size();
+            else if ( e.isPast(loc) )
+                break; // we are done
+            else // loc is inside of s
+                s += loc.getStart() - e.getStart();
+        }
+
+        return s;
+    }
+
+    /**
+     * determine if the collection is empty
+     *
+     * @return true if we have no elements
+     */
+    public boolean isEmpty() {
+        return mArray.isEmpty();
+    }
+
+    /**
+     * Determine if the given loc overlaps any loc in the sorted set
+     *
+     * @param loc the location to test
+     * @return trip if the location overlaps any loc
+     */
+    public boolean overlaps(final GenomeLoc loc) {
+        // edge condition
+        if ( mArray.isEmpty() )
+            return false;
+
+        // use the cached version first
+        if ( previousOverlapSearchIndex != -1 && overlapsAtOrImmediatelyAfterCachedIndex(loc, true) )
+            return true;
+
+        // update the cached index
+        previousOverlapSearchIndex = Collections.binarySearch(mArray, loc);
+
+        // if it matches an interval exactly, we are done
+        if ( previousOverlapSearchIndex >= 0 )
+            return true;
+
+        // check whether it overlaps the interval before or after the insertion point
+        previousOverlapSearchIndex = Math.max(0, -1 * previousOverlapSearchIndex - 2);
+        return overlapsAtOrImmediatelyAfterCachedIndex(loc, false);
+    }
+
+    private boolean overlapsAtOrImmediatelyAfterCachedIndex(final GenomeLoc loc, final boolean updateCachedIndex) {
+        // check the cached entry
+        if ( mArray.get(previousOverlapSearchIndex).overlapsP(loc) )
+            return true;
+
+        // check the entry after the cached entry since we may have moved to it
+        boolean returnValue = false;
+        if ( previousOverlapSearchIndex < mArray.size() - 1 ) {
+            returnValue = mArray.get(previousOverlapSearchIndex + 1).overlapsP(loc);
+            if ( updateCachedIndex )
+                previousOverlapSearchIndex++;
+        }
+
+        return returnValue;
+    }
+
+    /**
+     * Return a list of intervals overlapping loc
+     *
+     * @param loc the location we want overlapping intervals
+     * @return a non-null list of locations that overlap loc
+     */
+    public List<GenomeLoc> getOverlapping(final GenomeLoc loc) {
+        // the max ensures that if loc would be the first element, that we start searching at the first element
+        final int index = Collections.binarySearch(mArray, loc);
+        if ( index >= 0 )
+            // we can safely return a singleton because overlapping regions are merged and loc is exactly in
+            // the set already
+            return Collections.singletonList(loc);
+
+        // if loc isn't in the list index is (-(insertion point) - 1). The insertion point is defined as the point at
+        // which the key would be inserted into the list: the index of the first element greater than the key, or list.size()
+        // -ins - 1 = index => -ins = index + 1 => ins = -(index + 1)
+        // Note that we look one before the index in this case, as loc might occur after the previous overlapping interval
+        final int start = Math.max(-(index + 1) - 1, 0);
+        final int size = mArray.size();
+
+        final List<GenomeLoc> overlapping = new LinkedList<GenomeLoc>();
+        for ( int i = start; i < size; i++ ) {
+            final GenomeLoc myLoc = mArray.get(i);
+            if ( loc.overlapsP(myLoc) )
+                overlapping.add(myLoc);
+            else if ( myLoc.isPast(loc) )
+                // since mArray is ordered, if myLoc is past loc that means all future
+                // intervals cannot overlap loc either.  So we can safely abort the search
+                // note that we need to be a bit conservative on our tests since index needs to start
+                // at -1 the position of index, so it's possible that myLoc and loc don't overlap but the next
+                // position might
+                break;
+        }
+
+        return overlapping;
+    }
+
+    /**
+     * Return a list of intervals overlapping loc by enumerating all locs and testing for overlap
+     *
+     * Purely for testing purposes -- this is way to slow for any production code
+     *
+     * @param loc the location we want overlapping intervals
+     * @return a non-null list of locations that overlap loc
+     */
+    protected List<GenomeLoc> getOverlappingFullSearch(final GenomeLoc loc) {
+        final List<GenomeLoc> overlapping = new LinkedList<GenomeLoc>();
+
+        // super slow, but definitely works
+        for ( final GenomeLoc myLoc : mArray ) {
+            if ( loc.overlapsP(myLoc) )
+                overlapping.add(myLoc);
+        }
+
+        return overlapping;
+    }
+
+    /**
+     * Adds a GenomeLoc to the collection, inserting at the correct sorted position into the set.
+     * Throws an exception if the loc overlaps another loc already in the set.
+     *
+     * @param loc the GenomeLoc to add
+     *
+     * @return true if the loc was added or false otherwise (if the loc was null)
+     */
+    public boolean add(final GenomeLoc loc) {
+        return add(loc, false);
+    }
+
+    /**
+     * Adds a GenomeLoc to the collection, merging it if it overlaps another region.
+     * If it's not overlapping then we insert it at the correct sorted position into the set.
+     *
+     * @param loc the GenomeLoc to add
+     *
+     * @return true if the loc was added or false otherwise (if the loc was null)
+     */
+    public boolean addRegion(final GenomeLoc loc) {
+        return add(loc, true);
+    }
+
+    /**
+     * Adds a GenomeLoc to the collection, inserting at the correct sorted position into the set.
+     *
+     * @param loc                      the GenomeLoc to add
+     * @param mergeIfIntervalOverlaps  if true we merge the interval if it overlaps another one already in the set, otherwise we throw an exception
+     *
+     * @return true if the loc was added or false otherwise (if the loc was null or an exact duplicate)
+     */
+    public boolean add(final GenomeLoc loc, final boolean mergeIfIntervalOverlaps) {
+        if ( loc == null )
+            return false;
+
+        // if we have no other intervals yet or if the new loc is past the last one in the list (which is usually the
+        // case because locs are generally added in order) then be extra efficient and just add the loc to the end
+        if ( mArray.size() == 0 || loc.isPast(mArray.get(mArray.size() - 1)) ) {
+            return mArray.add(loc);
+        }
+
+        // find where in the list the new loc belongs
+        final int binarySearchIndex = Collections.binarySearch(mArray,loc);
+
+        // if it already exists in the list, return or throw an exception as needed
+        if ( binarySearchIndex >= 0 ) {
+            if ( mergeIfIntervalOverlaps )
+                return false;
+            throw new IllegalArgumentException("GenomeLocSortedSet already contains the GenomeLoc " + loc);
+        }
+
+        // if it overlaps a loc already in the list merge or throw an exception as needed
+        final int insertionIndex = -1 * (binarySearchIndex + 1);
+        if ( ! mergeOverlappingIntervalsFromAdd(loc, insertionIndex, !mergeIfIntervalOverlaps) ) {
+            // it does not overlap any current intervals, so add it to the set
+            mArray.add(insertionIndex, loc);
+        }
+
+        return true;
+    }
+
+    /*
+     * If the provided GenomeLoc overlaps another already in the set, merge them (or throw an exception if requested)
+     *
+     * @param loc                          the GenomeLoc to add
+     * @param insertionIndex               the index in the sorted set to add the new loc
+     * @param throwExceptionIfOverlapping  if true we throw an exception if there's overlap, otherwise we merge them
+     *
+     * @return true if the loc was added or false otherwise
+     */
+    private boolean mergeOverlappingIntervalsFromAdd(final GenomeLoc loc, final int insertionIndex, final boolean throwExceptionIfOverlapping) {
+        // try merging with the previous index
+        if ( insertionIndex != 0 && loc.overlapsP(mArray.get(insertionIndex - 1)) ) {
+            if ( throwExceptionIfOverlapping )
+                throw new IllegalArgumentException(String.format("GenomeLocSortedSet contains a GenomeLoc (%s) that overlaps with the provided one (%s)", mArray.get(insertionIndex - 1).toString(), loc.toString()));
+            mArray.set(insertionIndex - 1, mArray.get(insertionIndex - 1).merge(loc));
+            return true;
+        }
+
+        // try merging with the following index
+        if ( insertionIndex < mArray.size() && loc.overlapsP(mArray.get(insertionIndex)) ) {
+            if ( throwExceptionIfOverlapping )
+                throw new IllegalArgumentException(String.format("GenomeLocSortedSet contains a GenomeLoc (%s) that overlaps with the provided one (%s)", mArray.get(insertionIndex).toString(), loc.toString()));
+            mArray.set(insertionIndex, mArray.get(insertionIndex).merge(loc));
+            return true;
+        }
+
+        return false;
+    }
+
+    public GenomeLocSortedSet subtractRegions(GenomeLocSortedSet toRemoveSet) {
+        LinkedList<GenomeLoc> good = new LinkedList<GenomeLoc>();
+        Stack<GenomeLoc> toProcess = new Stack<GenomeLoc>();
+        Stack<GenomeLoc> toExclude = new Stack<GenomeLoc>();
+
+        // initialize the stacks
+        toProcess.addAll(mArray);
+        Collections.reverse(toProcess);
+        toExclude.addAll(toRemoveSet.mArray);
+        Collections.reverse(toExclude);
+
+        int i = 0;
+        while ( ! toProcess.empty() ) {    // while there's still stuff to process
+            if ( toExclude.empty() ) {
+                good.addAll(toProcess);         // no more excludes, all the processing stuff is good
+                break;
+            }
+
+            GenomeLoc p = toProcess.peek();
+            GenomeLoc e = toExclude.peek();
+
+            if ( p.overlapsP(e) ) {
+                toProcess.pop();
+                for ( GenomeLoc newP : p.subtract(e) )
+                    toProcess.push(newP);
+            } else if ( p.compareContigs(e) < 0 ) {
+                good.add(toProcess.pop());         // p is now good
+            } else if ( p.compareContigs(e) > 0 ) {
+                toExclude.pop();                 // e can't effect anything
+            } else if ( p.getStop() < e.getStart() ) {
+                good.add(toProcess.pop());         // p stops before e starts, p is good
+            } else if ( e.getStop() < p.getStart() ) {
+                toExclude.pop();                 // p starts after e stops, e is done
+            } else {
+                throw new ReviewedGATKException("BUG: unexpected condition: p=" + p + ", e=" + e);
+            }
+
+            if ( i++ % 10000 == 0 )
+                logger.debug("removeRegions operation: i = " + i);
+        }
+
+        return createSetFromList(genomeLocParser,good);
+    }
+
+
+    /**
+     * a simple removal of an interval contained in this list.  The interval must be identical to one in the list (no partial locations or overlapping)
+     * @param location the GenomeLoc to remove
+     */
+    public void remove(GenomeLoc location) {
+        if (!mArray.contains(location)) throw new IllegalArgumentException("Unable to remove location: " + location + ", not in the list");
+        mArray.remove(location);
+    }
+
+    /**
+     * create a list of genomic locations, given a reference sequence
+     *
+     * @param dict the sequence dictionary to create a collection from
+     *
+     * @return the GenomeLocSet of all references sequences as GenomeLoc's
+     */
+    public static GenomeLocSortedSet createSetFromSequenceDictionary(final SAMSequenceDictionary dict) {
+        final GenomeLocParser parser = new GenomeLocParser(dict);
+        final GenomeLocSortedSet returnSortedSet = new GenomeLocSortedSet(parser);
+        for ( final SAMSequenceRecord sequence : dict.getSequences() ) {
+            returnSortedSet.add(parser.createOverEntireContig(sequence.getSequenceName()));
+        }
+        return returnSortedSet;
+    }
+
+    /**
+     * Create a sorted genome location set from a list of GenomeLocs.
+     *
+     * @param locs the list<GenomeLoc>
+     *
+     * @return the sorted genome loc list
+     */
+    public static GenomeLocSortedSet createSetFromList(GenomeLocParser parser,List<GenomeLoc> locs) {
+        GenomeLocSortedSet set = new GenomeLocSortedSet(parser);
+        set.addAll(locs);
+        return set;
+    }
+
+
+    /**
+     * return a deep copy of this collection.
+     *
+     * @return a new GenomeLocSortedSet, identical to the current GenomeLocSortedSet.
+     */
+    public GenomeLocSortedSet clone() {
+        GenomeLocSortedSet ret = new GenomeLocSortedSet(genomeLocParser);
+        for (GenomeLoc loc : this.mArray) {
+            // ensure a deep copy
+            ret.mArray.add(genomeLocParser.createGenomeLoc(loc.getContig(), loc.getStart(), loc.getStop()));
+        }
+        return ret;
+    }
+
+    /**
+     * convert this object to a list
+     * @return the lists
+     */
+    public List<GenomeLoc> toList() {
+        return this.mArray;
+    }
+
+    public String toString() {
+        StringBuilder s = new StringBuilder();
+        s.append("[");
+        for ( GenomeLoc e : this ) {
+            s.append(" ");
+            s.append(e.toString());
+        }
+        s.append("]");
+
+        return s.toString();
+    }
+}
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/HeapSizeMonitor.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/HeapSizeMonitor.java
new file mode 100644
index 0000000..041bf76
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/HeapSizeMonitor.java
@@ -0,0 +1,107 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.utils;
+
+import org.broadinstitute.gatk.utils.exceptions.ReviewedGATKException;
+
+import java.lang.management.ManagementFactory;
+import java.lang.management.MemoryMXBean;
+
+/**
+ * Monitor the current heap size, allowing the application to programmatically
+ * access the data.
+ *
+ * @author mhanna
+ * @version 0.1
+ */
+public class HeapSizeMonitor {
+    private final int monitorFrequencyMillis;
+    private final MonitorRunnable monitorRunnable;
+
+    private Thread monitorThread;
+
+    public HeapSizeMonitor() {
+        this(1000);
+    }
+
+    public HeapSizeMonitor(final int monitorFrequencyMillis) {
+        this.monitorFrequencyMillis = monitorFrequencyMillis;
+        this.monitorRunnable = new MonitorRunnable();
+    }
+
+    public long getMaxMemoryUsed() {
+        return monitorRunnable.getMaxMemoryUsed();
+    }
+
+    public void start() {
+        monitorThread = new Thread(monitorRunnable);
+        monitorThread.start();
+    }
+
+    public void stop() {
+        monitorRunnable.stop = true;
+        try {
+            monitorThread.join();
+        }
+        catch(InterruptedException ex) {
+            throw new ReviewedGATKException("Unable to connect to monitor thread");
+        }
+        monitorThread = null;        
+    }
+
+    private class MonitorRunnable implements Runnable {
+        private MemoryMXBean monitor;
+
+        private long maxMemoryUsed;
+        private boolean stop;
+
+        public MonitorRunnable() {
+            monitor = ManagementFactory.getMemoryMXBean();   
+        }
+
+        public void reset() {
+            maxMemoryUsed = 0L;
+            stop = false;
+        }
+
+        public long getMaxMemoryUsed() {
+            return maxMemoryUsed;
+        }
+
+        public void run() {
+            while(!stop) {
+                System.gc();
+                maxMemoryUsed = Math.max(monitor.getHeapMemoryUsage().getUsed(),maxMemoryUsed);
+                try {
+                    Thread.sleep(monitorFrequencyMillis);
+                }
+                catch(InterruptedException ex) {
+                    throw new ReviewedGATKException("Unable to continue monitoring heap consumption",ex);
+                }
+            }
+        }
+    }
+}
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/IndelUtils.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/IndelUtils.java
new file mode 100644
index 0000000..81a2bdc
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/IndelUtils.java
@@ -0,0 +1,262 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.utils;
+
+import org.broadinstitute.gatk.engine.contexts.ReferenceContext;
+import org.broadinstitute.gatk.utils.exceptions.ReviewedGATKException;
+import htsjdk.variant.variantcontext.VariantContext;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+
+/**
+ * Created by IntelliJ IDEA.
+ * User: delangel
+ * Date: Feb 3, 2011
+ * Time: 2:44:22 PM
+ * To change this template use File | Settings | File Templates.
+ */
+public class IndelUtils {
+    protected final static String[] COLUMN_KEYS;
+
+
+
+    static {
+        COLUMN_KEYS= new String[51];
+        COLUMN_KEYS[0] = "Novel_A";
+        COLUMN_KEYS[1] = "Novel_C";
+        COLUMN_KEYS[2] = "Novel_G";
+        COLUMN_KEYS[3] = "Novel_T";
+        COLUMN_KEYS[4]  = "NOVEL_1";
+        COLUMN_KEYS[5]  = "NOVEL_2";
+        COLUMN_KEYS[6]  = "NOVEL_3";
+        COLUMN_KEYS[7]  = "NOVEL_4";
+        COLUMN_KEYS[8]  = "NOVEL_5";
+        COLUMN_KEYS[9]  = "NOVEL_6";
+        COLUMN_KEYS[10] = "NOVEL_7";
+        COLUMN_KEYS[11] = "NOVEL_8";
+        COLUMN_KEYS[12] = "NOVEL_9";
+        COLUMN_KEYS[13] = "NOVEL_10orMore";
+        COLUMN_KEYS[14] = "RepeatExpansion_A";
+        COLUMN_KEYS[15] = "RepeatExpansion_C";
+        COLUMN_KEYS[16] = "RepeatExpansion_G";
+        COLUMN_KEYS[17] = "RepeatExpansion_T";
+        COLUMN_KEYS[18] = "RepeatExpansion_AC";
+        COLUMN_KEYS[19] = "RepeatExpansion_AG";
+        COLUMN_KEYS[20] = "RepeatExpansion_AT";
+        COLUMN_KEYS[21] = "RepeatExpansion_CA";
+        COLUMN_KEYS[22] = "RepeatExpansion_CG";
+        COLUMN_KEYS[23] = "RepeatExpansion_CT";
+        COLUMN_KEYS[24] = "RepeatExpansion_GA";
+        COLUMN_KEYS[25] = "RepeatExpansion_GC";
+        COLUMN_KEYS[26] = "RepeatExpansion_GT";
+        COLUMN_KEYS[27] = "RepeatExpansion_TA";
+        COLUMN_KEYS[28] = "RepeatExpansion_TC";
+        COLUMN_KEYS[29] = "RepeatExpansion_TG";
+        COLUMN_KEYS[30] = "EventLength_1";
+        COLUMN_KEYS[31] = "EventLength_2";
+        COLUMN_KEYS[32] = "EventLength_3";
+        COLUMN_KEYS[33] = "EventLength_4";
+        COLUMN_KEYS[34] = "EventLength_5";
+        COLUMN_KEYS[35] = "EventLength_6";
+        COLUMN_KEYS[36] = "EventLength_7";
+        COLUMN_KEYS[37] = "EventLength_8";
+        COLUMN_KEYS[38] = "EventLength_9";
+        COLUMN_KEYS[39] = "EventLength_10orMore";
+        COLUMN_KEYS[40] = "NumRepetitions_1";
+        COLUMN_KEYS[41] = "NumRepetitions_2";
+        COLUMN_KEYS[42] = "NumRepetitions_3";
+        COLUMN_KEYS[43] = "NumRepetitions_4";
+        COLUMN_KEYS[44] = "NumRepetitions_5";
+        COLUMN_KEYS[45] = "NumRepetitions_6";
+        COLUMN_KEYS[46] = "NumRepetitions_7";
+        COLUMN_KEYS[47] = "NumRepetitions_8";
+        COLUMN_KEYS[48] = "NumRepetitions_9";
+        COLUMN_KEYS[49] = "NumRepetitions_10orMore";
+        COLUMN_KEYS[50] = "Other";
+
+    }
+
+    private static final int START_IND_NOVEL = 4;
+    private static final int STOP_IND_NOVEL = 13;
+    private static final int START_IND_FOR_REPEAT_EXPANSION_1 = 14;
+    private static final int IND_FOR_REPEAT_EXPANSION_A = 14;
+    private static final int IND_FOR_REPEAT_EXPANSION_C = 15;
+    private static final int IND_FOR_REPEAT_EXPANSION_G = 16;
+    private static final int IND_FOR_REPEAT_EXPANSION_T = 17;
+    private static final int STOP_IND_FOR_REPEAT_EXPANSION_2 = 29;
+    private static final int START_IND_FOR_REPEAT_EXPANSION_COUNTS = 30;
+    private static final int STOP_IND_FOR_REPEAT_EXPANSION_COUNTS = 39;
+    private static final int START_IND_FOR_NUM_REPETITION_COUNTS = 40;
+    private static final int STOP_IND_FOR_NUM_REPETITION_COUNTS = 49;
+    private static final int IND_FOR_OTHER_EVENT = 50;
+    private static final int START_IND_NOVEL_PER_BASE = 0;
+    private static final int STOP_IND_NOVEL_PER_BASE = 3;
+
+    private static String findMinimalEvent(String eventString) {
+
+        // for each length up to given string length, see if event string is a repetition of units of size N
+        String minEvent = eventString;
+        for (int k=1; k < eventString.length(); k++) {
+            if (eventString.length() % k > 0)
+                continue;
+            String str = eventString.substring(0,k);
+            // now see if event string is a repetition of str
+            int numReps = eventString.length() / k;
+            String r = "";
+            for (int j=0; j < numReps; j++)
+                r = r.concat(str);
+
+            if (r.matches(eventString)) {
+                minEvent = str;
+                break;
+            }
+
+        }
+        return minEvent;
+    }
+
+    public static ArrayList<Integer> findEventClassificationIndex(VariantContext vc, ReferenceContext ref) {
+        int eventLength;
+
+        String indelAlleleString;
+        boolean done = false;
+
+        ArrayList<Integer> inds = new ArrayList<Integer>();
+        if ( vc.isSimpleInsertion() ) {
+            indelAlleleString = vc.getAlternateAllele(0).getDisplayString().substring(1);
+        } else if ( vc.isSimpleDeletion() ) {
+            indelAlleleString = vc.getReference().getDisplayString().substring(1);
+        }
+        else {
+            inds.add(IND_FOR_OTHER_EVENT);
+            return inds;
+        }
+
+        byte[] refBases = ref.getBases();
+
+        indelAlleleString = findMinimalEvent(indelAlleleString);
+        eventLength = indelAlleleString.length();
+
+        // See first if indel is a repetition of bases before current
+        int indStart = refBases.length/2-eventLength+1;
+
+        int numRepetitions = 0;
+        while (!done) {
+            if (indStart < 0)
+                done = true;
+            else {
+                String refPiece = new String(Arrays.copyOfRange(refBases,indStart,indStart+eventLength));
+                if (refPiece.matches(indelAlleleString))
+                {
+                    numRepetitions++;
+                    indStart = indStart - eventLength;
+                }
+                else
+                    done = true;
+
+            }
+        }
+
+        // now do it forward
+        done = false;
+        indStart = refBases.length/2+1;
+        while (!done) {
+            if (indStart + eventLength >= refBases.length)
+                break;
+            else {
+                String refPiece = new String(Arrays.copyOfRange(refBases,indStart,indStart+eventLength));
+                if (refPiece.matches(indelAlleleString))
+                {
+                    numRepetitions++;
+                    indStart = indStart + eventLength;
+                }
+                else
+                    done = true;
+
+            }
+        }
+
+        if (numRepetitions == 0) {
+            //unrepeated sequence from surroundings
+            int ind = START_IND_NOVEL + (eventLength-1);
+            if (ind > STOP_IND_NOVEL)
+                ind = STOP_IND_NOVEL;
+            inds.add(ind);
+
+            if (eventLength == 1) {
+                // log single base indels additionally by base
+                String keyStr = "Novel_" + indelAlleleString;
+                int k;
+                for (k=START_IND_NOVEL_PER_BASE; k <= STOP_IND_NOVEL_PER_BASE; k++) {
+                    if (keyStr.matches(COLUMN_KEYS[k]))
+                        break;
+                }
+                inds.add(k);
+            }
+        }
+        else {
+            // log number of repetition counts
+            int ind = START_IND_FOR_NUM_REPETITION_COUNTS + (numRepetitions-1);
+            if (ind > STOP_IND_FOR_NUM_REPETITION_COUNTS)
+                ind = STOP_IND_FOR_NUM_REPETITION_COUNTS;
+            inds.add(ind);
+
+            ind = START_IND_FOR_REPEAT_EXPANSION_COUNTS + (eventLength - 1);
+            if (ind > STOP_IND_FOR_REPEAT_EXPANSION_COUNTS)
+                    ind = STOP_IND_FOR_REPEAT_EXPANSION_COUNTS;
+            inds.add(ind);
+            
+            // log event length
+            if (eventLength<=2) {
+                // for single or dinucleotide indels, we further log the base in which they occurred
+                String keyStr = "RepeatExpansion_" + indelAlleleString;
+                int k;
+                for (k=START_IND_FOR_REPEAT_EXPANSION_1; k <= STOP_IND_FOR_REPEAT_EXPANSION_2; k++) {
+                    if (keyStr.matches(COLUMN_KEYS[k]))
+                        break;
+                }
+                // log now event
+                inds.add(k);
+            }
+
+
+        }
+
+        return inds;
+    }
+
+    public static String getIndelClassificationName(int k) {
+        if (k >=0 && k < COLUMN_KEYS.length)
+            return COLUMN_KEYS[k];
+        else
+            throw new ReviewedGATKException("Invalid index when trying to get indel classification name");
+    }
+
+    public static boolean isInsideExtendedIndel(VariantContext vc, ReferenceContext ref) {
+        return (vc.getStart() != ref.getLocus().getStart());
+    }
+}
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/LRUCache.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/LRUCache.java
new file mode 100644
index 0000000..df2e829
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/LRUCache.java
@@ -0,0 +1,45 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.utils;
+
+import java.util.LinkedHashMap;
+import java.util.Map;
+
+/**
+ * An LRU cache implemented as an extension to LinkedHashMap
+ */
+public class LRUCache<K,V> extends LinkedHashMap<K,V> {
+    private int capacity; // Maximum number of items in the cache.
+
+    public LRUCache(int capacity) {
+        super(capacity+1, 1.0f, true); // Pass 'true' for accessOrder.
+        this.capacity = capacity;
+    }
+
+    protected boolean removeEldestEntry(final Map.Entry entry) {
+        return (size() > this.capacity);
+    }
+}
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/MRUCachingSAMSequenceDictionary.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/MRUCachingSAMSequenceDictionary.java
new file mode 100644
index 0000000..2f9a3b0
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/MRUCachingSAMSequenceDictionary.java
@@ -0,0 +1,186 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.utils;
+
+import com.google.java.contract.Ensures;
+import com.google.java.contract.Requires;
+import htsjdk.samtools.SAMSequenceDictionary;
+import htsjdk.samtools.SAMSequenceRecord;
+import org.broadinstitute.gatk.utils.exceptions.ReviewedGATKException;
+
+/**
+ * A wrapper class that provides efficient most recently used caching for the global
+ * SAMSequenceDictionary underlying all of the GATK engine capabilities.  It is essential
+ * that these class be as efficient as possible.  It doesn't need to be thread-safe, as
+ * GenomeLocParser uses a thread-local variable to ensure that each thread gets its own MRU
+ * cache.
+ *
+ * The MRU elements are the SAMSequenceRecord, the lastContig, and the lastIndex.  The
+ * cached value is the actual SAMSequenceRecord of the most recently accessed value from
+ * getSequence, along with local variables for the contig index and contig string.
+ */
+final class MRUCachingSAMSequenceDictionary {
+    /**
+     * Our sequence dictionary
+     */
+    private final SAMSequenceDictionary dict;
+
+    SAMSequenceRecord lastSSR = null;
+    String lastContig = "";
+    int lastIndex = -1;
+
+    /**
+     * Create a new MRUCachingSAMSequenceDictionary that provides information about sequences in dict
+     * @param dict a non-null, non-empty sequencing dictionary
+     */
+    @Ensures("lastSSR == null")
+    public MRUCachingSAMSequenceDictionary(final SAMSequenceDictionary dict) {
+        if ( dict == null ) throw new IllegalArgumentException("Dictionary cannot be null");
+        if ( dict.size() == 0 ) throw new IllegalArgumentException("Dictionary cannot have size zero");
+
+        this.dict = dict;
+    }
+
+    /**
+     * Get our sequence dictionary
+     * @return a non-null SAMSequenceDictionary
+     */
+    @Ensures("result != null")
+    public SAMSequenceDictionary getDictionary() {
+        return dict;
+    }
+
+    /**
+     * Is contig present in the dictionary?  Efficiently caching.
+     * @param contig a non-null contig we want to test
+     * @return true if contig is in dictionary, false otherwise
+     */
+    @Requires("contig != null")
+    public final boolean hasContig(final String contig) {
+        return contig.equals(lastContig) || dict.getSequence(contig) != null;
+    }
+
+    /**
+     * Is contig index present in the dictionary?  Efficiently caching.
+     * @param contigIndex an integer offset that might map to a contig in this dictionary
+     * @return true if contigIndex is in dictionary, false otherwise
+     */
+    @Requires("contigIndex >= 0")
+    public final boolean hasContigIndex(final int contigIndex) {
+        return lastIndex == contigIndex || dict.getSequence(contigIndex) != null;
+    }
+
+    /**
+     * Same as SAMSequenceDictionary.getSequence but uses a MRU cache for efficiency
+     *
+     * @param contig the contig name we want to get the sequence record of
+     * @throws ReviewedGATKException if contig isn't present in the dictionary
+     * @return the sequence record for contig
+     */
+    @Requires("contig != null")
+    @Ensures("result != null")
+    public final SAMSequenceRecord getSequence(final String contig) {
+        if ( isCached(contig) )
+            return lastSSR;
+        else
+            return updateCache(contig, -1);
+    }
+
+    /**
+     * Same as SAMSequenceDictionary.getSequence but uses a MRU cache for efficiency
+     *
+     * @param index the contig index we want to get the sequence record of
+     * @throws ReviewedGATKException if contig isn't present in the dictionary
+     * @return the sequence record for contig
+     */
+    @Requires("index >= 0")
+    @Ensures("result != null")
+    public final SAMSequenceRecord getSequence(final int index) {
+        if ( isCached(index) )
+            return lastSSR;
+        else
+            return updateCache(null, index);
+    }
+
+    /**
+     * Same as SAMSequenceDictionary.getSequenceIndex but uses a MRU cache for efficiency
+     *
+     * @param contig the contig we want to get the sequence record of
+     * @throws ReviewedGATKException if index isn't present in the dictionary
+     * @return the sequence record index for contig
+     */
+    @Requires("contig != null")
+    @Ensures("result >= 0")
+    public final int getSequenceIndex(final String contig) {
+        if ( ! isCached(contig) ) {
+            updateCache(contig, -1);
+        }
+
+        return lastIndex;
+    }
+
+    /**
+     * Is contig the MRU cached contig?
+     * @param contig the contig to test
+     * @return true if contig is the currently cached contig, false otherwise
+     */
+    @Requires({"contig != null"})
+    protected boolean isCached(final String contig) {
+        return contig.equals(lastContig);
+    }
+
+    /**
+     * Is the contig index index the MRU cached index?
+     * @param index the contig index to test
+     * @return true if contig index is the currently cached contig index, false otherwise
+     */
+    protected boolean isCached(final int index) {
+        return lastIndex == index;
+    }
+
+    /**
+     * The key algorithm.  Given a new record, update the last used record, contig
+     * name, and index.
+     *
+     * @param contig the contig we want to look up.  If null, index is used instead
+     * @param index the contig index we want to look up.  Only used if contig is null
+     * @throws ReviewedGATKException if index isn't present in the dictionary
+     * @return the SAMSequenceRecord for contig / index
+     */
+    @Requires("contig != null || index >= 0")
+    @Ensures("result != null")
+    private SAMSequenceRecord updateCache(final String contig, int index ) {
+        SAMSequenceRecord rec = contig == null ? dict.getSequence(index) : dict.getSequence(contig);
+        if ( rec == null ) {
+            throw new ReviewedGATKException("BUG: requested unknown contig=" + contig + " index=" + index);
+        } else {
+            lastSSR = rec;
+            lastContig = rec.getSequenceName();
+            lastIndex = rec.getSequenceIndex();
+            return rec;
+        }
+    }
+}
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/MannWhitneyU.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/MannWhitneyU.java
new file mode 100644
index 0000000..a918c0a
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/MannWhitneyU.java
@@ -0,0 +1,508 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.utils;
+
+import cern.jet.math.Arithmetic;
+import cern.jet.random.Normal;
+import com.google.java.contract.Ensures;
+import com.google.java.contract.Requires;
+import org.apache.commons.math.MathException;
+import org.apache.commons.math.distribution.NormalDistribution;
+import org.apache.commons.math.distribution.NormalDistributionImpl;
+import org.broadinstitute.gatk.engine.GenomeAnalysisEngine;
+import org.broadinstitute.gatk.utils.collections.Pair;
+import org.broadinstitute.gatk.utils.exceptions.GATKException;
+
+import java.io.Serializable;
+import java.util.Comparator;
+import java.util.TreeSet;
+
+/**
+ * Created by IntelliJ IDEA.
+ * User: chartl
+ */
+public class MannWhitneyU {
+
+    private static Normal STANDARD_NORMAL = new Normal(0.0,1.0,null);
+    private static NormalDistribution APACHE_NORMAL = new NormalDistributionImpl(0.0,1.0,1e-2);
+    private static double LNSQRT2PI = Math.log(Math.sqrt(2.0*Math.PI));
+
+    private TreeSet<Pair<Number,USet>> observations;
+    private int sizeSet1;
+    private int sizeSet2;
+    private ExactMode exactMode;
+
+    public MannWhitneyU(ExactMode mode, boolean dither) {
+        if ( dither )
+            observations = new TreeSet<Pair<Number,USet>>(new DitheringComparator());
+        else
+            observations = new TreeSet<Pair<Number,USet>>(new NumberedPairComparator());
+        sizeSet1 = 0;
+        sizeSet2 = 0;
+        exactMode = mode;
+    }
+
+    public MannWhitneyU() {
+        this(ExactMode.POINT,true);
+    }
+
+    public MannWhitneyU(boolean dither) {
+        this(ExactMode.POINT,dither);
+    }
+
+    public MannWhitneyU(ExactMode mode) {
+        this(mode,true);
+    }
+
+    /**
+     * Add an observation into the observation tree
+     * @param n: the observation (a number)
+     * @param set: whether the observation comes from set 1 or set 2
+     */
+    public void add(Number n, USet set) {
+        observations.add(new Pair<Number,USet>(n,set));
+        if ( set == USet.SET1 ) {
+            ++sizeSet1;
+        } else {
+            ++sizeSet2;
+        }
+    }
+
+    public Pair<Long,Long> getR1R2() {
+        long u1 = calculateOneSidedU(observations,MannWhitneyU.USet.SET1);
+        long n1 = sizeSet1*(sizeSet1+1)/2;
+        long r1 = u1 + n1;
+        long n2 = sizeSet2*(sizeSet2+1)/2;
+        long u2 = n1*n2-u1;
+        long r2 = u2 + n2;
+
+        return new Pair<Long,Long>(r1,r2);
+    }
+
+    /**
+     * Runs the one-sided test under the hypothesis that the data in set "lessThanOther" stochastically
+     * dominates the other set
+     * @param lessThanOther - either Set1 or Set2
+     * @return - u-based z-approximation, and p-value associated with the test (p-value is exact for small n,m)
+     */
+    @Requires({"lessThanOther != null"})
+    @Ensures({"validateObservations(observations) || Double.isNaN(result.getFirst())","result != null", "! Double.isInfinite(result.getFirst())", "! Double.isInfinite(result.getSecond())"})
+    public Pair<Double,Double> runOneSidedTest(USet lessThanOther) {
+        long u = calculateOneSidedU(observations, lessThanOther);
+        int n = lessThanOther == USet.SET1 ? sizeSet1 : sizeSet2;
+        int m = lessThanOther == USet.SET1 ? sizeSet2 : sizeSet1;
+        if ( n == 0 || m == 0 ) {
+            // test is uninformative as one or both sets have no observations
+            return new Pair<Double,Double>(Double.NaN,Double.NaN);
+        }
+
+        // the null hypothesis is that {N} is stochastically less than {M}, so U has counted
+        // occurrences of {M}s before {N}s. We would expect that this should be less than (n*m+1)/2 under
+        // the null hypothesis, so we want to integrate from K=0 to K=U for cumulative cases. Always.
+        return calculateP(n, m, u, false, exactMode);
+    }
+
+    /**
+     * Runs the standard two-sided test,
+     * returns the u-based z-approximate and p values.
+     * @return a pair holding the u and p-value.
+     */
+    @Ensures({"result != null", "! Double.isInfinite(result.getFirst())", "! Double.isInfinite(result.getSecond())"})
+    //@Requires({"validateObservations(observations)"})
+    public Pair<Double,Double> runTwoSidedTest() {
+        Pair<Long,USet> uPair = calculateTwoSidedU(observations);
+        long u = uPair.first;
+        int n = uPair.second == USet.SET1 ? sizeSet1 : sizeSet2;
+        int m = uPair.second == USet.SET1 ? sizeSet2 : sizeSet1;
+        if ( n == 0 || m == 0 ) {
+            // test is uninformative as one or both sets have no observations
+            return new Pair<Double,Double>(Double.NaN,Double.NaN);
+        }
+        return calculateP(n, m, u, true, exactMode);
+    }
+
+    /**
+     * Given a u statistic, calculate the p-value associated with it, dispatching to approximations where appropriate
+     * @param n - The number of entries in the stochastically smaller (dominant) set
+     * @param m - The number of entries in the stochastically larger (dominated) set
+     * @param u - the Mann-Whitney U value
+     * @param twoSided - is the test twosided
+     * @return the (possibly approximate) p-value associated with the MWU test, and the (possibly approximate) z-value associated with it
+     * todo -- there must be an approximation for small m and large n
+     */
+    @Requires({"m > 0","n > 0"})
+    @Ensures({"result != null", "! Double.isInfinite(result.getFirst())", "! Double.isInfinite(result.getSecond())"})
+    protected static Pair<Double,Double> calculateP(int n, int m, long u, boolean twoSided, ExactMode exactMode) {
+        Pair<Double,Double> zandP;
+        if ( n > 8 && m > 8 ) {
+            // large m and n - normal approx
+            zandP = calculatePNormalApproximation(n,m,u, twoSided);
+        } else if ( n > 5 && m > 7 ) {
+            // large m, small n - sum uniform approx
+            // todo -- find the appropriate regimes where this approximation is actually better enough to merit slowness
+            // pval = calculatePUniformApproximation(n,m,u);
+            zandP = calculatePNormalApproximation(n, m, u, twoSided);
+        } else if ( n > 8 || m > 8 ) {
+            zandP = calculatePFromTable(n, m, u, twoSided);
+        } else {
+            // small m and n - full approx
+            zandP = calculatePRecursively(n,m,u,twoSided,exactMode);
+        }
+
+        return zandP;
+    }
+
+    public static Pair<Double,Double> calculatePFromTable(int n, int m, long u, boolean twoSided) {
+        // todo -- actually use a table for:
+        // todo      - n large, m small
+        return calculatePNormalApproximation(n,m,u, twoSided);
+    }
+
+    /**
+     * Uses a normal approximation to the U statistic in order to return a cdf p-value. See Mann, Whitney [1947]
+     * @param n - The number of entries in the stochastically smaller (dominant) set
+     * @param m - The number of entries in the stochastically larger (dominated) set
+     * @param u - the Mann-Whitney U value
+     * @param twoSided - whether the test should be two sided
+     * @return p-value associated with the normal approximation
+     */
+    @Requires({"m > 0","n > 0"})
+    @Ensures({"result != null", "! Double.isInfinite(result.getFirst())", "! Double.isInfinite(result.getSecond())"})
+    public static Pair<Double,Double> calculatePNormalApproximation(int n,int m,long u, boolean twoSided) {
+        double z = getZApprox(n,m,u);
+        if ( twoSided ) {
+            return new Pair<Double,Double>(z,2.0*(z < 0 ? STANDARD_NORMAL.cdf(z) : 1.0-STANDARD_NORMAL.cdf(z)));
+        } else {
+            return new Pair<Double,Double>(z,STANDARD_NORMAL.cdf(z));
+        }
+    }
+
+    /**
+     * Calculates the Z-score approximation of the u-statistic
+     * @param n - The number of entries in the stochastically smaller (dominant) set
+     * @param m - The number of entries in the stochastically larger (dominated) set
+     * @param u - the Mann-Whitney U value
+     * @return the asymptotic z-approximation corresponding to the MWU p-value for n < m
+     */
+    @Requires({"m > 0","n > 0"})
+    @Ensures({"! Double.isNaN(result)", "! Double.isInfinite(result)"})
+    private static double getZApprox(int n, int m, long u) {
+        double mean = ( ((long)m)*n+1.0)/2;
+        double var = (((long) n)*m*(n+m+1.0))/12;
+        double z = ( u - mean )/Math.sqrt(var);
+        return z;
+    }
+
+    /**
+     * Uses a sum-of-uniform-0-1 random variable approximation to the U statistic in order to return an approximate
+     * p-value. See Buckle, Kraft, van Eeden [1969] (approx) and Billingsly [1995] or Stephens, MA [1966, biometrika] (sum of uniform CDF)
+     * @param n - The number of entries in the stochastically smaller (dominant) set
+     * @param m - The number of entries in the stochastically larger (dominated) set
+     * @param u - mann-whitney u value
+     * @return p-value according to sum of uniform approx
+     * todo -- this is currently not called due to not having a good characterization of where it is significantly more accurate than the
+     * todo -- normal approxmation (e.g. enough to merit the runtime hit)
+     */
+    public static double calculatePUniformApproximation(int n, int m, long u) {
+        long R = u + (n*(n+1))/2;
+        double a = Math.sqrt(m*(n+m+1));
+        double b = (n/2.0)*(1-Math.sqrt((n+m+1)/m));
+        double z = b + ((double)R)/a;
+        if ( z < 0 ) { return 1.0; }
+        else if ( z > n ) { return 0.0; }
+        else {
+            if ( z > ((double) n) /2 ) {
+                return 1.0-1/(Arithmetic.factorial(n))*uniformSumHelper(z, (int) Math.floor(z), n, 0);
+            } else {
+                return 1/(Arithmetic.factorial(n))*uniformSumHelper(z, (int) Math.floor(z), n, 0);
+            }
+        }
+    }
+
+    /**
+     * Helper function for the sum of n uniform random variables
+     * @param z - value at which to compute the (un-normalized) cdf
+     * @param m - a cutoff integer (defined by m <= z < m + 1)
+     * @param n - the number of uniform random variables
+     * @param k - holder variable for the recursion (alternatively, the index of the term in the sequence)
+     * @return the (un-normalized) cdf for the sum of n random variables
+     */
+    private static double uniformSumHelper(double z, int m, int n, int k) {
+        if ( k > m ) { return 0; }
+        int coef = (k % 2 == 0) ? 1 : -1;
+        return coef*Arithmetic.binomial(n,k)*Math.pow(z-k,n) + uniformSumHelper(z,m,n,k+1);
+    }
+
+    /**
+     * Calculates the U-statistic associated with a two-sided test (e.g. the RV from which one set is drawn
+     * stochastically dominates the RV from which the other set is drawn); two-sidedness is accounted for
+     * later on simply by multiplying the p-value by 2.
+     *
+     * Recall: If X stochastically dominates Y, the test is for occurrences of Y before X, so the lower value of u is chosen
+     * @param observed - the observed data
+     * @return the minimum of the U counts (set1 dominates 2, set 2 dominates 1)
+     */
+    @Requires({"observed != null", "observed.size() > 0"})
+    @Ensures({"result != null","result.first > 0"})
+    public static Pair<Long,USet> calculateTwoSidedU(TreeSet<Pair<Number,USet>> observed) {
+        int set1SeenSoFar = 0;
+        int set2SeenSoFar = 0;
+        long uSet1DomSet2 = 0;
+        long uSet2DomSet1 = 0;
+        USet previous = null;
+        for ( Pair<Number,USet> dataPoint : observed ) {
+
+            if ( dataPoint.second == USet.SET1 ) {
+                ++set1SeenSoFar;
+            } else {
+                ++set2SeenSoFar;
+            }
+
+            if ( previous != null ) {
+                if ( dataPoint.second == USet.SET1 ) {
+                    uSet2DomSet1 += set2SeenSoFar;
+                } else {
+                    uSet1DomSet2 += set1SeenSoFar;
+                }
+            }
+
+            previous = dataPoint.second;
+        }
+
+        return uSet1DomSet2 < uSet2DomSet1 ? new Pair<Long,USet>(uSet1DomSet2,USet.SET1) : new Pair<Long,USet>(uSet2DomSet1,USet.SET2);
+    }
+
+    /**
+     * Calculates the U-statistic associated with the one-sided hypothesis that "dominator" stochastically dominates
+     * the other U-set. Note that if S1 dominates S2, we want to count the occurrences of points in S2 coming before points in S1.
+     * @param observed - the observed data points, tagged by each set
+     * @param dominator - the set that is hypothesized to be stochastically dominating
+     * @return the u-statistic associated with the hypothesis that dominator stochastically dominates the other set
+     */
+    @Requires({"observed != null","dominator != null","observed.size() > 0"})
+    @Ensures({"result >= 0"})
+    public static long calculateOneSidedU(TreeSet<Pair<Number,USet>> observed,USet dominator) {
+        long otherBeforeDominator = 0l;
+        int otherSeenSoFar = 0;
+        for ( Pair<Number,USet> dataPoint : observed ) {
+            if ( dataPoint.second != dominator ) {
+                ++otherSeenSoFar;
+            } else {
+                otherBeforeDominator += otherSeenSoFar;
+            }
+        }
+
+        return otherBeforeDominator;
+    }
+
+    /**
+     * The Mann-Whitney U statistic follows a recursive equation (that enumerates the proportion of possible
+     * binary strings of "n" zeros, and "m" ones, where a one precedes a zero "u" times). This accessor
+     * calls into that recursive calculation.
+     * @param n: number of set-one entries (hypothesis: set one is stochastically less than set two)
+     * @param m: number of set-two entries
+     * @param u: number of set-two entries that precede set-one entries (e.g. 0,1,0,1,0 -> 3 )
+     * @param twoSided: whether the test is two sided or not. The recursive formula is symmetric, multiply by two for two-sidedness.
+     * @param  mode: whether the mode is a point probability, or a cumulative distribution
+     * @return the probability under the hypothesis that all sequences are equally likely of finding a set-two entry preceding a set-one entry "u" times.
+     */
+    @Requires({"m > 0","n > 0","u >= 0"})
+    @Ensures({"result != null","! Double.isInfinite(result.getFirst())", "! Double.isInfinite(result.getSecond())"})
+    public static Pair<Double,Double> calculatePRecursively(int n, int m, long u, boolean twoSided, ExactMode mode) {
+        if ( m > 8 && n > 5 ) { throw new GATKException(String.format("Please use the appropriate (normal or sum of uniform) approximation. Values n: %d, m: %d",n,m)); }
+        double p = mode == ExactMode.POINT ? cpr(n,m,u) : cumulativeCPR(n,m,u);
+        //p *= twoSided ? 2.0 : 1.0;
+        double z;
+        try {
+
+            if ( mode == ExactMode.CUMULATIVE ) {
+                z = APACHE_NORMAL.inverseCumulativeProbability(p);
+            } else {
+                double sd = Math.sqrt((1.0+1.0/(1+n+m))*(n*m)*(1.0+n+m)/12); // biased variance empirically better fit to distribution then asymptotic variance
+                //System.out.printf("SD is %f and Max is %f and prob is %f%n",sd,1.0/Math.sqrt(sd*sd*2.0*Math.PI),p);
+                if ( p > 1.0/Math.sqrt(sd*sd*2.0*Math.PI) ) { // possible for p-value to be outside the range of the normal. Happens at the mean, so z is 0.
+                    z = 0.0;
+                } else {
+                    if ( u >= n*m/2 ) {
+                        z = Math.sqrt(-2.0*(Math.log(sd)+Math.log(p)+LNSQRT2PI));
+                    } else {
+                        z = -Math.sqrt(-2.0*(Math.log(sd)+Math.log(p)+LNSQRT2PI));
+                    }
+                }
+            }
+
+        } catch (MathException me) {
+            throw new GATKException("A math exception occurred in inverting the probability",me);
+        }
+
+        return new Pair<Double,Double>(z,(twoSided ? 2.0*p : p));
+    }
+
+    /**
+     * Hook into CPR with sufficient warning (for testing purposes)
+     * calls into that recursive calculation.
+     * @param n: number of set-one entries (hypothesis: set one is stochastically less than set two)
+     * @param m: number of set-two entries
+     * @param u: number of set-two entries that precede set-one entries (e.g. 0,1,0,1,0 -> 3 )
+     * @return same as cpr
+     */
+    protected static double calculatePRecursivelyDoNotCheckValuesEvenThoughItIsSlow(int n, int m, long u) {
+        return cpr(n,m,u);
+    }
+
+    /**
+     * For testing
+     *
+     * @param n: number of set-one entries (hypothesis: set one is stochastically less than set two)
+     * @param m: number of set-two entries
+     * @param u: number of set-two entries that precede set-one entries (e.g. 0,1,0,1,0 -> 3 )
+     */
+    protected static long countSequences(int n, int m, long u) {
+        if ( u < 0 ) { return 0; }
+        if ( m == 0 || n == 0 ) { return u == 0 ? 1 : 0; }
+
+        return countSequences(n-1,m,u-m) + countSequences(n,m-1,u);
+    }
+
+    /**
+     * : just a shorter name for calculatePRecursively. See Mann, Whitney, [1947]
+     * @param n: number of set-1 entries
+     * @param m: number of set-2 entries
+     * @param u: number of times a set-2 entry as preceded a set-1 entry
+     * @return recursive p-value
+     */
+    private static double cpr(int n, int m, long u) {
+        if ( u < 0 ) {
+            return 0.0;
+        }
+        if ( m == 0 || n == 0 ) {
+            // there are entries in set 1 or set 2, so no set-2 entry can precede a set-1 entry; thus u must be zero.
+            // note that this exists only for edification, as when we reach this point, the coefficient on this term is zero anyway
+            return ( u == 0 ) ? 1.0 : 0.0;
+        }
+
+
+        return (((double)n)/(n+m))*cpr(n-1,m,u-m) + (((double)m)/(n+m))*cpr(n,m-1,u);
+    }
+
+    private static double cumulativeCPR(int n, int m, long u ) {
+        // from above:
+        // the null hypothesis is that {N} is stochastically less than {M}, so U has counted
+        // occurrences of {M}s before {N}s. We would expect that this should be less than (n*m+1)/2 under
+        // the null hypothesis, so we want to integrate from K=0 to K=U for cumulative cases. Always.
+        double p = 0.0;
+        // optimization using symmetry, use the least amount of sums possible
+        long uSym = ( u <= n*m/2 ) ? u : ((long)n)*m-u;
+        for ( long uu = 0; uu < uSym; uu++ ) {
+            p += cpr(n,m,uu);
+        }
+        // correct by 1.0-p if the optimization above was used (e.g. 1-right tail = left tail)
+        return (u <= n*m/2) ? p : 1.0-p;
+    }
+
+    /**
+     * hook into the data tree, for testing purposes only
+     * @return  observations
+     */
+    protected TreeSet<Pair<Number,USet>> getObservations() {
+        return observations;
+    }
+
+    /**
+     * hook into the set sizes, for testing purposes only
+     * @return size set 1, size set 2
+     */
+    protected Pair<Integer,Integer> getSetSizes() {
+        return new Pair<Integer,Integer>(sizeSet1,sizeSet2);
+    }
+
+    /**
+     * Validates that observations are in the correct format for a MWU test -- this is only called by the contracts API during testing
+     * @param tree - the collection of labeled observations
+     * @return true iff the tree set is valid (no INFs or NaNs, at least one data point in each set)
+     */
+    protected static boolean validateObservations(TreeSet<Pair<Number,USet>> tree) {
+        boolean seen1 = false;
+        boolean seen2 = false;
+        boolean seenInvalid = false;
+        for ( Pair<Number,USet> p : tree) {
+            if ( ! seen1 && p.getSecond() == USet.SET1 ) {
+                seen1 = true;
+            }
+
+            if ( ! seen2 && p.getSecond() == USet.SET2 ) {
+                seen2 = true;
+            }
+
+            if ( Double.isNaN(p.getFirst().doubleValue()) || Double.isInfinite(p.getFirst().doubleValue())) {
+                seenInvalid = true;
+            }
+
+        }
+
+            return ! seenInvalid && seen1 && seen2;
+    }
+
+    /**
+     * A comparator class which uses dithering on tie-breaking to ensure that the internal treeset drops no values
+     * and to ensure that rank ties are broken at random.
+     */
+    private static class DitheringComparator implements Comparator<Pair<Number,USet>>, Serializable {
+
+        public DitheringComparator() {}
+
+        @Override
+        public boolean equals(Object other) { return false; }
+
+        @Override
+        public int compare(Pair<Number,USet> left, Pair<Number,USet> right) {
+            double comp = Double.compare(left.first.doubleValue(),right.first.doubleValue());
+            if ( comp > 0 ) { return 1; }
+            if ( comp < 0 ) { return -1; }
+            return GenomeAnalysisEngine.getRandomGenerator().nextBoolean() ? -1 : 1;
+        }
+    }
+
+    /**
+     * A comparator that reaches into the pair and compares numbers without tie-braking.
+     */
+    private static class NumberedPairComparator implements Comparator<Pair<Number,USet>>, Serializable {
+
+        public NumberedPairComparator() {}
+
+        @Override
+        public boolean equals(Object other) { return false; }
+
+        @Override
+        public int compare(Pair<Number,USet> left, Pair<Number,USet> right ) {
+            return Double.compare(left.first.doubleValue(),right.first.doubleValue());
+        }
+    }
+
+    public enum USet { SET1, SET2 }
+    public enum ExactMode { POINT, CUMULATIVE }
+
+}
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/MathUtils.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/MathUtils.java
new file mode 100644
index 0000000..01aa133
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/MathUtils.java
@@ -0,0 +1,1690 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.utils;
+
+import com.google.java.contract.Ensures;
+import com.google.java.contract.Requires;
+import org.apache.commons.math.distribution.ExponentialDistribution;
+import org.apache.commons.math.distribution.ExponentialDistributionImpl;
+import org.broadinstitute.gatk.engine.GenomeAnalysisEngine;
+import org.broadinstitute.gatk.utils.exceptions.ReviewedGATKException;
+
+import java.math.BigDecimal;
+import java.util.*;
+
+/**
+ * MathUtils is a static class (no instantiation allowed!) with some useful math methods.
+ *
+ * @author Kiran Garimella
+ */
+public class MathUtils {
+
+    /**
+     * Private constructor.  No instantiating this class!
+     */
+    private MathUtils() {
+    }
+
+    /**
+     * The smallest log10 value we'll emit from normalizeFromLog10 and other functions
+     * where the real-space value is 0.0.
+     */
+    public static final double LOG10_P_OF_ZERO = -1000000.0;
+    public static final double FAIR_BINOMIAL_PROB_LOG10_0_5 = Math.log10(0.5);
+    public static final double LOG_ONE_HALF = -Math.log10(2.0);
+    public static final double LOG_ONE_THIRD = -Math.log10(3.0);
+    private static final double NATURAL_LOG_OF_TEN = Math.log(10.0);
+    private static final double SQUARE_ROOT_OF_TWO_TIMES_PI = Math.sqrt(2.0 * Math.PI);
+
+    /**
+     * A helper class to maintain a cache of log10 values
+     */
+    public static class Log10Cache {
+        /**
+         * Get the value of log10(n), expanding the cache as necessary
+         * @param n operand
+         * @return log10(n)
+         */
+        public static double get(final int n) {
+            if (n < 0)
+                throw new ReviewedGATKException(String.format("Can't take the log of a negative number: %d", n));
+            if (n >= cache.length)
+                ensureCacheContains(Math.max(n+10, 2*cache.length));
+            /*
+               Array lookups are not atomic.  It's possible that the reference to cache could be
+               changed between the time the reference is loaded and the data is fetched from the correct
+               offset.  However, the value retrieved can't change, and it's guaranteed to be present in the
+               old reference by the conditional above.
+             */
+            return cache[n];
+        }
+
+        /**
+         * Ensures that the cache contains a value for n.  After completion of ensureCacheContains(n),
+         * #get(n) is guaranteed to return without causing a cache expansion
+         * @param n desired value to be precomputed
+         */
+        public static synchronized void ensureCacheContains(final int n) {
+            if (n < cache.length)
+                return;
+            final double[] newCache = new double[n + 1];
+            System.arraycopy(cache, 0, newCache, 0, cache.length);
+            for (int i=cache.length; i < newCache.length; i++)
+                newCache[i] = Math.log10(i);
+            cache = newCache;
+        }
+
+        //initialize with the special case: log10(0) = NEGATIVE_INFINITY
+        private static double[] cache = new double[] { Double.NEGATIVE_INFINITY };
+    }
+
+    /**
+     * Get a random int between min and max (inclusive) using the global GATK random number generator
+     *
+     * @param min lower bound of the range
+     * @param max upper bound of the range
+     * @return a random int >= min and <= max
+     */
+    public static int randomIntegerInRange( final int min, final int max ) {
+        return GenomeAnalysisEngine.getRandomGenerator().nextInt(max - min + 1) + min;
+    }
+
+    /**
+     * Encapsulates the second term of Jacobian log identity for differences up to MAX_TOLERANCE
+     */
+    private static class JacobianLogTable {
+
+        public static final double MAX_TOLERANCE = 8.0;
+
+        public static double get(final double difference) {
+            if (cache == null)
+                initialize();
+            final int index = fastRound(difference * INV_STEP);
+            return cache[index];
+        }
+
+        private static synchronized void initialize() {
+            if (cache == null) {
+                final int tableSize = (int) (MAX_TOLERANCE / TABLE_STEP) + 1;
+                cache = new double[tableSize];
+                for (int k = 0; k < cache.length; k++)
+                    cache[k] = Math.log10(1.0 + Math.pow(10.0, -((double) k) * TABLE_STEP));
+            }
+        }
+
+        private static final double TABLE_STEP = 0.0001;
+        private static final double INV_STEP = 1.0 / TABLE_STEP;
+        private static double[] cache = null;
+    }
+
+    // A fast implementation of the Math.round() method.  This method does not perform
+    // under/overflow checking, so this shouldn't be used in the general case (but is fine
+    // if one is already make those checks before calling in to the rounding).
+    public static int fastRound(final double d) {
+        return (d > 0.0) ? (int) (d + 0.5d) : (int) (d - 0.5d);
+    }
+
+    public static double approximateLog10SumLog10(final double[] vals) {
+        return approximateLog10SumLog10(vals, vals.length);
+    }
+
+    /**
+     * Calculate the approximate log10 sum of an array range.
+     * @param vals the input values.
+     * @param fromIndex the first inclusive index in the input array.
+     * @param toIndex index following the last element to sum in the input array (exclusive).
+     * @return the approximate sum.
+     * @throws IllegalArgumentException if {@code vals} is {@code null} or  {@code fromIndex} is out of bounds
+     * or if {@code toIndex} is larger than
+     * the length of the input array or {@code fromIndex} is larger than {@code toIndex}.
+     */
+    public static double approximateLog10SumLog10(final double[] vals, final int fromIndex, final int toIndex) {
+        if (fromIndex == toIndex) return Double.NEGATIVE_INFINITY;
+        final int maxElementIndex = MathUtils.maxElementIndex(vals,fromIndex,toIndex);
+        double approxSum = vals[maxElementIndex];
+
+        for (int i = fromIndex; i < toIndex; i++) {
+            final double val;
+            if (i == maxElementIndex || (val = vals[i]) == Double.NEGATIVE_INFINITY)
+                continue;
+            final double diff = approxSum - val;
+            if (diff < JacobianLogTable.MAX_TOLERANCE)
+                approxSum += JacobianLogTable.get(diff);
+        }
+        return approxSum;
+    }
+
+    public static double approximateLog10SumLog10(final double[] vals, final int endIndex) {
+
+        final int maxElementIndex = MathUtils.maxElementIndex(vals, endIndex);
+        double approxSum = vals[maxElementIndex];
+
+        for (int i = 0; i < endIndex; i++) {
+            if (i == maxElementIndex || vals[i] == Double.NEGATIVE_INFINITY)
+                continue;
+
+            final double diff = approxSum - vals[i];
+            if (diff < JacobianLogTable.MAX_TOLERANCE) {
+                // See notes from the 2-inout implementation below
+                approxSum += JacobianLogTable.get(diff);
+            }
+        }
+
+        return approxSum;
+    }
+
+    public static double approximateLog10SumLog10(final double a, final double b, final double c) {
+        return approximateLog10SumLog10(a, approximateLog10SumLog10(b, c));
+    }
+
+    public static double approximateLog10SumLog10(double small, double big) {
+        // make sure small is really the smaller value
+        if (small > big) {
+            final double t = big;
+            big = small;
+            small = t;
+        }
+
+        if (small == Double.NEGATIVE_INFINITY || big == Double.NEGATIVE_INFINITY)
+            return big;
+
+        final double diff = big - small;
+        if (diff >= JacobianLogTable.MAX_TOLERANCE)
+            return big;
+
+        // OK, so |y-x| < tol: we use the following identity then:
+        // we need to compute log10(10^x + 10^y)
+        // By Jacobian logarithm identity, this is equal to
+        // max(x,y) + log10(1+10^-abs(x-y))
+        // we compute the second term as a table lookup with integer quantization
+        // we have pre-stored correction for 0,0.1,0.2,... 10.0
+        return big + JacobianLogTable.get(diff);
+    }
+
+    public static double sum(final double[] values) {
+        double s = 0.0;
+        for (double v : values)
+            s += v;
+        return s;
+    }
+
+    public static long sum(final int[] x) {
+        long total = 0;
+        for (int v : x)
+            total += v;
+        return total;
+    }
+
+    public static int sum(final byte[] x) {
+        int total = 0;
+        for (byte v : x)
+            total += (int)v;
+        return total;
+    }
+
+    public static double percentage(int x, int base) {
+        return (base > 0 ? ((double) x / (double) base) * 100.0 : 0);
+    }
+
+    public static double ratio(final int num, final int denom) {
+        if ( denom > 0 ) {
+            return ((double) num)/denom;
+        } else {
+            if ( num == 0 && denom == 0) {
+                return 0.0;
+            } else {
+                throw new ReviewedGATKException(String.format("The denominator of a ratio cannot be zero or less than zero: %d/%d",num,denom));
+            }
+        }
+    }
+
+    public static double ratio(final long num, final long denom) {
+        if ( denom > 0L ) {
+            return ((double) num)/denom;
+        } else {
+            if ( num == 0L && denom == 0L ) {
+                return 0.0;
+            } else {
+                throw new ReviewedGATKException(String.format("The denominator of a ratio cannot be zero or less than zero: %d/%d",num,denom));
+            }
+        }
+    }
+
+    /**
+     * Converts a real space array of numbers (typically probabilities) into a log10 array
+     *
+     * @param prRealSpace
+     * @return
+     */
+    public static double[] toLog10(final double[] prRealSpace) {
+        double[] log10s = new double[prRealSpace.length];
+        for (int i = 0; i < prRealSpace.length; i++) {
+            log10s[i] = Math.log10(prRealSpace[i]);
+        }
+        return log10s;
+    }
+
+    public static double log10sumLog10(final double[] log10p, final int start) {
+        return log10sumLog10(log10p, start, log10p.length);
+    }
+
+    public static double log10sumLog10(final double[] log10p, final int start, final int finish) {
+
+        if (start >= finish)
+            return Double.NEGATIVE_INFINITY;
+        final int maxElementIndex = MathUtils.maxElementIndex(log10p, start, finish);
+        final double maxValue = log10p[maxElementIndex];
+        if(maxValue == Double.NEGATIVE_INFINITY)
+            return maxValue;
+        double sum = 1.0;
+        for (int i = start; i < finish; i++) {
+            double curVal = log10p[i];
+            double scaled_val = curVal - maxValue;
+            if (i == maxElementIndex || curVal == Double.NEGATIVE_INFINITY) {
+                continue;
+            }
+            else {
+                sum += Math.pow(10.0, scaled_val);
+            }
+        }
+        if ( Double.isNaN(sum) || sum == Double.POSITIVE_INFINITY ) {
+            throw new IllegalArgumentException("log10p: Values must be non-infinite and non-NAN");
+        }
+        return maxValue + (sum != 1.0 ? Math.log10(sum) : 0.0);
+    }
+
+    public static double sumLog10(final double[] log10values) {
+        return Math.pow(10.0, log10sumLog10(log10values));
+    }
+
+    public static double log10sumLog10(final double[] log10values) {
+        return log10sumLog10(log10values, 0);
+    }
+
+    public static boolean wellFormedDouble(final double val) {
+        return !Double.isInfinite(val) && !Double.isNaN(val);
+    }
+
+    public static double bound(final double value, final double minBoundary, final double maxBoundary) {
+        return Math.max(Math.min(value, maxBoundary), minBoundary);
+    }
+
+    public static boolean isBounded(final double val, final double lower, final double upper) {
+        return val >= lower && val <= upper;
+    }
+
+    public static boolean isPositive(final double val) {
+        return !isNegativeOrZero(val);
+    }
+
+    public static boolean isPositiveOrZero(final double val) {
+        return isBounded(val, 0.0, Double.POSITIVE_INFINITY);
+    }
+
+    public static boolean isNegativeOrZero(final double val) {
+        return isBounded(val, Double.NEGATIVE_INFINITY, 0.0);
+    }
+
+    public static boolean isNegative(final double val) {
+        return !isPositiveOrZero(val);
+    }
+
+    /**
+     * Compares double values for equality (within 1e-6), or inequality.
+     *
+     * @param a the first double value
+     * @param b the second double value
+     * @return -1 if a is greater than b, 0 if a is equal to be within 1e-6, 1 if b is greater than a.
+     */
+    public static byte compareDoubles(final double a, final double b) {
+        return compareDoubles(a, b, 1e-6);
+    }
+
+    /**
+     * Compares double values for equality (within epsilon), or inequality.
+     *
+     * @param a       the first double value
+     * @param b       the second double value
+     * @param epsilon the precision within which two double values will be considered equal
+     * @return -1 if a is greater than b, 0 if a is equal to be within epsilon, 1 if b is greater than a.
+     */
+    public static byte compareDoubles(final double a, final double b, final double epsilon) {
+        if (Math.abs(a - b) < epsilon) {
+            return 0;
+        }
+        if (a > b) {
+            return -1;
+        }
+        return 1;
+    }
+
+    /**
+     * Calculate f(x) = Normal(x | mu = mean, sigma = sd)
+     * @param mean the desired mean of the Normal distribution
+     * @param sd the desired standard deviation of the Normal distribution
+     * @param x the value to evaluate
+     * @return a well-formed double
+     */
+    public static double normalDistribution(final double mean, final double sd, final double x) {
+        if( sd < 0 )
+            throw new IllegalArgumentException("sd: Standard deviation of normal must be >0");
+        if ( ! wellFormedDouble(mean) || ! wellFormedDouble(sd) || ! wellFormedDouble(x) )
+            throw new IllegalArgumentException("mean, sd, or, x : Normal parameters must be well formatted (non-INF, non-NAN)");
+        double a = 1.0 / (sd * Math.sqrt(2.0 * Math.PI));
+        double b = Math.exp(-1.0 * (Math.pow(x - mean, 2.0) / (2.0 * sd * sd)));
+        return a * b;
+    }
+
+    /**
+     * Calculate f(x) = log10 ( Normal(x | mu = mean, sigma = sd) )
+     * @param mean the desired mean of the Normal distribution
+     * @param sd the desired standard deviation of the Normal distribution
+     * @param x the value to evaluate
+     * @return a well-formed double
+     */
+
+    public static double normalDistributionLog10(final double mean, final double sd, final double x) {
+        if( sd < 0 )
+            throw new IllegalArgumentException("sd: Standard deviation of normal must be >0");
+        if ( ! wellFormedDouble(mean) || ! wellFormedDouble(sd) || ! wellFormedDouble(x) )
+            throw new IllegalArgumentException("mean, sd, or, x : Normal parameters must be well formatted (non-INF, non-NAN)");
+        final double a = -1.0 * Math.log10(sd * SQUARE_ROOT_OF_TWO_TIMES_PI);
+        final double b = -1.0 * (square(x - mean) / (2.0 * square(sd))) / NATURAL_LOG_OF_TEN;
+        return a + b;
+    }
+
+    /**
+     * Calculate f(x) = x^2
+     * @param x the value to square
+     * @return x * x
+     */
+    public static double square(final double x) {
+        return x * x;
+    }
+
+    /**
+     * Calculates the log10 of the binomial coefficient. Designed to prevent
+     * overflows even with very large numbers.
+     *
+     * @param n total number of trials
+     * @param k number of successes
+     * @return the log10 of the binomial coefficient
+     */
+    public static double binomialCoefficient(final int n, final int k) {
+        return Math.pow(10, log10BinomialCoefficient(n, k));
+    }
+
+    /**
+     * @see #binomialCoefficient(int, int) with log10 applied to result
+     */
+    public static double log10BinomialCoefficient(final int n, final int k) {
+        if ( n < 0 ) {
+            throw new IllegalArgumentException("n: Must have non-negative number of trials");
+        }
+        if ( k > n || k < 0 ) {
+            throw new IllegalArgumentException("k: Must have non-negative number of successes, and no more successes than number of trials");
+        }
+
+        return log10Factorial(n) - log10Factorial(k) - log10Factorial(n - k);
+    }
+
+    /**
+     * Computes a binomial probability.  This is computed using the formula
+     * <p/>
+     * B(k; n; p) = [ n! / ( k! (n - k)! ) ] (p^k)( (1-p)^k )
+     * <p/>
+     * where n is the number of trials, k is the number of successes, and p is the probability of success
+     *
+     * @param n number of Bernoulli trials
+     * @param k number of successes
+     * @param p probability of success
+     * @return the binomial probability of the specified configuration.  Computes values down to about 1e-237.
+     */
+    public static double binomialProbability(final int n, final int k, final double p) {
+        return Math.pow(10, log10BinomialProbability(n, k, Math.log10(p)));
+    }
+
+    /**
+     * @see #binomialProbability(int, int, double) with log10 applied to result
+     */
+    public static double log10BinomialProbability(final int n, final int k, final double log10p) {
+        if ( log10p > 1e-18 )
+            throw new IllegalArgumentException("log10p: Log-probability must be 0 or less");
+        double log10OneMinusP = Math.log10(1 - Math.pow(10, log10p));
+        return log10BinomialCoefficient(n, k) + log10p * k + log10OneMinusP * (n - k);
+    }
+
+    /**
+     * @see #binomialProbability(int, int, double) with p=0.5
+     */
+    public static double binomialProbability(final int n, final int k) {
+        return Math.pow(10, log10BinomialProbability(n, k));
+    }
+
+    /**
+     * @see #binomialProbability(int, int, double) with p=0.5 and log10 applied to result
+     */
+    public static double log10BinomialProbability(final int n, final int k) {
+        return log10BinomialCoefficient(n, k) + (n * FAIR_BINOMIAL_PROB_LOG10_0_5);
+    }
+
+    /** A memoization container for {@link #binomialCumulativeProbability(int, int, int)}.  Synchronized to accomodate multithreading. */
+    private static final Map<Long, Double> BINOMIAL_CUMULATIVE_PROBABILITY_MEMOIZATION_CACHE = 
+            Collections.synchronizedMap(new LRUCache<Long, Double>(10_000)); 
+    
+    /**
+     * Primitive integer-triplet bijection into long.  Returns null when the bijection function fails (in lieu of an exception), which will
+     * happen when: any value is negative or larger than a short.  This method is optimized for speed; it is not intended to serve as a 
+     * utility function.
+     */
+    static Long fastGenerateUniqueHashFromThreeIntegers(final int one, final int two, final int three) {
+        if (one < 0 || two < 0 || three < 0 || Short.MAX_VALUE < one || Short.MAX_VALUE < two || Short.MAX_VALUE < three) {
+            return null;
+        } else {
+            long result = 0;
+            result += (short) one;
+            result <<= 16;
+            result += (short) two;
+            result <<= 16;
+            result += (short) three;
+            return result;
+        }
+    }
+    
+    /**
+     * Performs the cumulative sum of binomial probabilities, where the probability calculation is done in log space.
+     * Assumes that the probability of a successful hit is fair (i.e. 0.5).
+     * 
+     * This pure function is memoized because of its expensive BigDecimal calculations.
+     *
+     * @param n         number of attempts for the number of hits
+     * @param k_start   start (inclusive) of the cumulant sum (over hits)
+     * @param k_end     end (inclusive) of the cumulant sum (over hits)
+     * @return - returns the cumulative probability
+     */
+    public static double binomialCumulativeProbability(final int n, final int k_start, final int k_end) {
+        if ( k_end > n )
+            throw new IllegalArgumentException(String.format("Value for k_end (%d) is greater than n (%d)", k_end, n));
+
+        // Fetch cached value, if applicable.
+        final Long memoizationKey = fastGenerateUniqueHashFromThreeIntegers(n, k_start, k_end);
+        final Double memoizationCacheResult;
+        if (memoizationKey != null) {
+            memoizationCacheResult = BINOMIAL_CUMULATIVE_PROBABILITY_MEMOIZATION_CACHE.get(memoizationKey);
+        } else {
+            memoizationCacheResult = null;
+        }
+
+        final double result;
+        if (memoizationCacheResult != null) {
+            result = memoizationCacheResult;
+        } else {
+            double cumProb = 0.0;
+            double prevProb;
+            BigDecimal probCache = BigDecimal.ZERO;
+
+            for (int hits = k_start; hits <= k_end; hits++) {
+                prevProb = cumProb;
+                final double probability = binomialProbability(n, hits);
+                cumProb += probability;
+                if (probability > 0 && cumProb - prevProb < probability / 2) { // loss of precision
+                    probCache = probCache.add(new BigDecimal(prevProb));
+                    cumProb = 0.0;
+                    hits--; // repeat loop
+                    // prevProb changes at start of loop
+                }
+            }
+
+            result = probCache.add(new BigDecimal(cumProb)).doubleValue();
+            if (memoizationKey != null) {
+                BINOMIAL_CUMULATIVE_PROBABILITY_MEMOIZATION_CACHE.put(memoizationKey, result);
+            }
+        }
+        return result;
+    }
+
+    private static final double LOG1MEXP_THRESHOLD = Math.log(0.5);
+
+    private static final double LN_10 = Math.log(10);
+
+    /**
+     * Calculates {@code log(1-exp(a))} without loosing precision.
+     *
+     * <p>
+     *     This is based on the approach described in:
+     *
+     * </p>
+     * <p>
+     *     Maechler M, Accurately Computing log(1-exp(-|a|)) Assessed by the Rmpfr package, 2012 <br/>
+     *     <a ref="http://cran.r-project.org/web/packages/Rmpfr/vignettes/log1mexp-note.pdf">Online document</a>.
+     *
+     * </p>
+     *
+     * @param a the input exponent.
+     * @return {@link Double#NaN NaN} if {@code a > 0}, otherwise the corresponding value.
+     */
+    public static double log1mexp(final double a) {
+        if (a > 0) return Double.NaN;
+        if (a == 0) return Double.NEGATIVE_INFINITY;
+
+        return (a < LOG1MEXP_THRESHOLD) ? Math.log1p(-Math.exp(a)) : Math.log(-Math.expm1(a));
+    }
+
+    /**
+     * Calculates {@code log10(1-10^a)} without loosing precision.
+     *
+     * <p>
+     *     This is based on the approach described in:
+     *
+     * </p>
+     * <p>
+     *     Maechler M, Accurately Computing log(1-exp(-|a|)) Assessed by the Rmpfr package, 2012 <br/>
+     *     <a ref="http://cran.r-project.org/web/packages/Rmpfr/vignettes/log1mexp-note.pdf">Online document</a>.
+     * </p>
+     *
+     * @param a the input exponent.
+     * @return {@link Double#NaN NaN} if {@code a > 0}, otherwise the corresponding value.
+     */
+    public static double log10OneMinusPow10(final double a) {
+        if (a > 0) return Double.NaN;
+        if (a == 0) return Double.NEGATIVE_INFINITY;
+        final double b = a * LN_10;
+        return log1mexp(b) / LN_10;
+    }
+
+    /**
+     * Calculates the log10 of the multinomial coefficient. Designed to prevent
+     * overflows even with very large numbers.
+     *
+     * @param n total number of trials
+     * @param k array of any size with the number of successes for each grouping (k1, k2, k3, ..., km)
+     * @return {@link Double#NaN NaN} if {@code a > 0}, otherwise the corresponding value.
+     */
+    public static double log10MultinomialCoefficient(final int n, final int[] k) {
+        if ( n < 0 )
+            throw new IllegalArgumentException("n: Must have non-negative number of trials");
+        double denominator = 0.0;
+        int sum = 0;
+        for (int x : k) {
+            if ( x < 0 )
+                throw new IllegalArgumentException("x element of k: Must have non-negative observations of group");
+            if ( x > n )
+                throw new IllegalArgumentException("x element of k, n: Group observations must be bounded by k");
+            denominator += log10Factorial(x);
+            sum += x;
+        }
+        if ( sum != n )
+            throw new IllegalArgumentException("k and n: Sum of observations in multinomial must sum to total number of trials");
+        return log10Factorial(n) - denominator;
+    }
+
+    /**
+     * Computes the log10 of the multinomial distribution probability given a vector
+     * of log10 probabilities. Designed to prevent overflows even with very large numbers.
+     *
+     * @param n      number of trials
+     * @param k      array of number of successes for each possibility
+     * @param log10p array of log10 probabilities
+     * @return
+     */
+    public static double log10MultinomialProbability(final int n, final int[] k, final double[] log10p) {
+        if (log10p.length != k.length)
+            throw new IllegalArgumentException("p and k: Array of log10 probabilities must have the same size as the array of number of sucesses: " + log10p.length + ", " + k.length);
+        double log10Prod = 0.0;
+        for (int i = 0; i < log10p.length; i++) {
+            if ( log10p[i] > 1e-18 )
+                throw new IllegalArgumentException("log10p: Log-probability must be <= 0");
+            log10Prod += log10p[i] * k[i];
+        }
+        return log10MultinomialCoefficient(n, k) + log10Prod;
+    }
+
+    /**
+     * Computes a multinomial coefficient efficiently avoiding overflow even for large numbers.
+     * This is computed using the formula:
+     * <p/>
+     * M(x1,x2,...,xk; n) = [ n! / (x1! x2! ... xk!) ]
+     * <p/>
+     * where xi represents the number of times outcome i was observed, n is the number of total observations.
+     * In this implementation, the value of n is inferred as the sum over i of xi.
+     *
+     * @param k an int[] of counts, where each element represents the number of times a certain outcome was observed
+     * @return the multinomial of the specified configuration.
+     */
+    public static double multinomialCoefficient(final int[] k) {
+        int n = 0;
+        for (int xi : k) {
+            n += xi;
+        }
+
+        return Math.pow(10, log10MultinomialCoefficient(n, k));
+    }
+
+    /**
+     * Computes a multinomial probability efficiently avoiding overflow even for large numbers.
+     * This is computed using the formula:
+     * <p/>
+     * M(x1,x2,...,xk; n; p1,p2,...,pk) = [ n! / (x1! x2! ... xk!) ] (p1^x1)(p2^x2)(...)(pk^xk)
+     * <p/>
+     * where xi represents the number of times outcome i was observed, n is the number of total observations, and
+     * pi represents the probability of the i-th outcome to occur.  In this implementation, the value of n is
+     * inferred as the sum over i of xi.
+     *
+     * @param k an int[] of counts, where each element represents the number of times a certain outcome was observed
+     * @param p a double[] of probabilities, where each element represents the probability a given outcome can occur
+     * @return the multinomial probability of the specified configuration.
+     */
+    public static double multinomialProbability(final int[] k, final double[] p) {
+        if (p.length != k.length)
+            throw new IllegalArgumentException("p and k: Array of log10 probabilities must have the same size as the array of number of sucesses: " + p.length + ", " + k.length);
+
+        int n = 0;
+        double[] log10P = new double[p.length];
+        for (int i = 0; i < p.length; i++) {
+            log10P[i] = Math.log10(p[i]);
+            n += k[i];
+        }
+        return Math.pow(10, log10MultinomialProbability(n, k, log10P));
+    }
+
+    /**
+     * calculate the Root Mean Square of an array of integers
+     *
+     * @param x an byte[] of numbers
+     * @return the RMS of the specified numbers.
+     */
+    public static double rms(final byte[] x) {
+        if (x.length == 0)
+            return 0.0;
+
+        double rms = 0.0;
+        for (int i : x)
+            rms += i * i;
+        rms /= x.length;
+        return Math.sqrt(rms);
+    }
+
+    /**
+     * calculate the Root Mean Square of an array of integers
+     *
+     * @param x an int[] of numbers
+     * @return the RMS of the specified numbers.
+     */
+    public static double rms(final int[] x) {
+        if (x.length == 0)
+            return 0.0;
+
+        double rms = 0.0;
+        for (int i : x)
+            rms += i * i;
+        rms /= x.length;
+        return Math.sqrt(rms);
+    }
+
+    /**
+     * calculate the Root Mean Square of an array of doubles
+     *
+     * @param x a double[] of numbers
+     * @return the RMS of the specified numbers.
+     */
+    public static double rms(final Double[] x) {
+        if (x.length == 0)
+            return 0.0;
+
+        double rms = 0.0;
+        for (Double i : x)
+            rms += i * i;
+        rms /= x.length;
+        return Math.sqrt(rms);
+    }
+
+    public static double rms(final Collection<Integer> l) {
+        if (l.size() == 0)
+            return 0.0;
+
+        double rms = 0.0;
+        for (int i : l)
+            rms += i * i;
+        rms /= l.size();
+        return Math.sqrt(rms);
+    }
+
+    public static double distanceSquared(final double[] x, final double[] y) {
+        double dist = 0.0;
+        for (int iii = 0; iii < x.length; iii++) {
+            dist += (x[iii] - y[iii]) * (x[iii] - y[iii]);
+        }
+        return dist;
+    }
+
+    public static double round(final double num, final int digits) {
+        double result = num * Math.pow(10.0, (double) digits);
+        result = Math.round(result);
+        result = result / Math.pow(10.0, (double) digits);
+        return result;
+    }
+
+    /**
+     * normalizes the log10-based array.  ASSUMES THAT ALL ARRAY ENTRIES ARE <= 0 (<= 1 IN REAL-SPACE).
+     *
+     * @param array             the array to be normalized
+     * @param takeLog10OfOutput if true, the output will be transformed back into log10 units
+     * @return a newly allocated array corresponding the normalized values in array, maybe log10 transformed
+     */
+    public static double[] normalizeFromLog10(final double[] array, final boolean takeLog10OfOutput) {
+        return normalizeFromLog10(array, takeLog10OfOutput, false);
+    }
+
+    /**
+     * See #normalizeFromLog10 but with the additional option to use an approximation that keeps the calculation always in log-space
+     *
+     * @param array
+     * @param takeLog10OfOutput
+     * @param keepInLogSpace
+     *
+     * @return
+     */
+    public static double[] normalizeFromLog10(final double[] array, final boolean takeLog10OfOutput, final boolean keepInLogSpace) {
+        // for precision purposes, we need to add (or really subtract, since they're
+        // all negative) the largest value; also, we need to convert to normal-space.
+        double maxValue = arrayMax(array);
+
+        // we may decide to just normalize in log space without converting to linear space
+        if (keepInLogSpace) {
+            for (int i = 0; i < array.length; i++) {
+                array[i] -= maxValue;
+            }
+            return array;
+        }
+
+        // default case: go to linear space
+        double[] normalized = new double[array.length];
+
+        for (int i = 0; i < array.length; i++)
+            normalized[i] = Math.pow(10, array[i] - maxValue);
+
+        // normalize
+        double sum = 0.0;
+        for (int i = 0; i < array.length; i++)
+            sum += normalized[i];
+        for (int i = 0; i < array.length; i++) {
+            double x = normalized[i] / sum;
+            if (takeLog10OfOutput) {
+                x = Math.log10(x);
+                if ( x < LOG10_P_OF_ZERO || Double.isInfinite(x) )
+                    x = array[i] - maxValue;
+            }
+
+            normalized[i] = x;
+        }
+
+        return normalized;
+    }
+
+    /**
+     * normalizes the log10-based array.  ASSUMES THAT ALL ARRAY ENTRIES ARE <= 0 (<= 1 IN REAL-SPACE).
+     *
+     * @param array the array to be normalized
+     * @return a newly allocated array corresponding the normalized values in array
+     */
+    public static double[] normalizeFromLog10(final double[] array) {
+        return normalizeFromLog10(array, false);
+    }
+
+    /**
+     * normalizes the real-space probability array.
+     *
+     * Does not assume anything about the values in the array, beyond that no elements are below 0.  It's ok
+     * to have values in the array of > 1, or have the sum go above 0.
+     *
+     * @param array the array to be normalized
+     * @return a newly allocated array corresponding the normalized values in array
+     */
+    @Requires("array != null")
+    @Ensures({"result != null"})
+    public static double[] normalizeFromRealSpace(final double[] array) {
+        if ( array.length == 0 )
+            return array;
+
+        final double sum = sum(array);
+        final double[] normalized = new double[array.length];
+        if ( sum < 0.0 ) throw new IllegalArgumentException("Values in probability array sum to a negative number " + sum);
+        for ( int i = 0; i < array.length; i++ ) {
+            normalized[i] = array[i] / sum;
+        }
+        return normalized;
+    }
+
+    public static int maxElementIndex(final double[] array) {
+        return maxElementIndex(array, array.length);
+    }
+
+    public static int maxElementIndex(final double[] array, final int start, final int endIndex) {
+        if (array == null || array.length == 0)
+            throw new IllegalArgumentException("Array cannot be null!");
+
+        if (start > endIndex) {
+           throw new IllegalArgumentException("Start cannot be after end.");
+        }
+
+        int maxI = start;
+        for (int i = (start+1); i < endIndex; i++) {
+            if (array[i] > array[maxI])
+                maxI = i;
+        }
+        return maxI;
+    }
+
+    public static int maxElementIndex(final double[] array, final int endIndex) {
+        return maxElementIndex(array, 0, endIndex);
+    }
+
+    public static int maxElementIndex(final int[] array) {
+        return maxElementIndex(array, array.length);
+    }
+
+    public static int maxElementIndex(final byte[] array) {
+        return maxElementIndex(array, array.length);
+    }
+
+    public static int maxElementIndex(final int[] array, final int endIndex) {
+        if (array == null || array.length == 0)
+            throw new IllegalArgumentException("Array cannot be null!");
+
+        int maxI = 0;
+        for (int i = 1; i < endIndex; i++) {
+            if (array[i] > array[maxI])
+                maxI = i;
+        }
+        return maxI;
+    }
+
+    public static int maxElementIndex(final byte[] array, final int endIndex) {
+        if (array == null || array.length == 0)
+            throw new IllegalArgumentException("Array cannot be null!");
+
+        int maxI = 0;
+        for (int i = 1; i < endIndex; i++) {
+            if (array[i] > array[maxI])
+                maxI = i;
+        }
+
+        return maxI;
+    }
+
+    public static int arrayMax(final int[] array) {
+        return array[maxElementIndex(array)];
+    }
+
+
+    public static double arrayMax(final double[] array) {
+        return array[maxElementIndex(array)];
+    }
+
+    public static double arrayMax(final double[] array, final int endIndex) {
+        return array[maxElementIndex(array, endIndex)];
+    }
+
+    public static double arrayMin(final double[] array) {
+        return array[minElementIndex(array)];
+    }
+
+    public static int arrayMin(final int[] array) {
+        return array[minElementIndex(array)];
+    }
+
+    public static byte arrayMin(final byte[] array) {
+        return array[minElementIndex(array)];
+    }
+
+    /**
+     * Compute the min element of a List<Integer>
+     * @param array a non-empty list of integer
+     * @return the min
+     */
+    public static int arrayMin(final List<Integer> array) {
+        if ( array == null || array.isEmpty() ) throw new IllegalArgumentException("Array must be non-null and non-empty");
+        int min = array.get(0);
+        for ( final int i : array )
+            if ( i < min ) min = i;
+        return min;
+    }
+
+    /**
+     * Compute the median element of the list of integers
+     * @param array a list of integers
+     * @return the median element
+     */
+    public static <T extends Comparable<? super T>> T median(final List<T> array) {
+         /* TODO -- from Valentin
+        the current implementation is not the usual median when the input is of even length. More concretely it returns the ith element of the list where i = floor(input.size() / 2).
+
+        But actually that is not the "usual" definition of a median, as it is supposed to return the average of the two middle values when the sample length is an even number (i.e. median(1,2,3,4,5,6) == 3.5). [Sources: R and wikipedia]
+
+        My suggestion for a solution is then:
+
+        unify median and medianDoubles to public static <T extends Number> T median(Collection<T>)
+        check on null elements and throw an exception if there are any or perhaps return a null; documented in the javadoc.
+        relocate, rename and refactor MathUtils.median(X) to Utils.ithElement(X,X.size()/2)
+        In addition, the current median implementation sorts the whole input list witch is O(n log n). However find out the ith element (thus calculate the median) can be done in O(n)
+        */
+        if ( array == null ) throw new IllegalArgumentException("Array must be non-null");
+        final int size = array.size();
+        if ( size == 0 ) throw new IllegalArgumentException("Array cannot have size 0");
+        else if ( size == 1 ) return array.get(0);
+        else {
+            final ArrayList<T> sorted = new ArrayList<>(array);
+            Collections.sort(sorted);
+            return sorted.get(size / 2);
+        }
+    }
+
+    public static int minElementIndex(final double[] array) {
+        if (array == null || array.length == 0)
+            throw new IllegalArgumentException("Array cannot be null!");
+
+        int minI = 0;
+        for (int i = 1; i < array.length; i++) {
+            if (array[i] < array[minI])
+                minI = i;
+        }
+
+        return minI;
+    }
+
+    public static int minElementIndex(final byte[] array) {
+        if (array == null || array.length == 0)
+            throw new IllegalArgumentException("Array cannot be null!");
+
+        int minI = 0;
+        for (int i = 1; i < array.length; i++) {
+            if (array[i] < array[minI])
+                minI = i;
+        }
+
+        return minI;
+    }
+
+    public static int minElementIndex(final int[] array) {
+        if (array == null || array.length == 0)
+            throw new IllegalArgumentException("Array cannot be null!");
+
+        int minI = 0;
+        for (int i = 1; i < array.length; i++) {
+            if (array[i] < array[minI])
+                minI = i;
+        }
+
+        return minI;
+    }
+
+    public static int arrayMaxInt(final List<Integer> array) {
+        if (array == null)
+            throw new IllegalArgumentException("Array cannot be null!");
+        if (array.size() == 0)
+            throw new IllegalArgumentException("Array size cannot be 0!");
+
+        int m = array.get(0);
+        for (int e : array)
+            m = Math.max(m, e);
+        return m;
+    }
+
+    public static int sum(final List<Integer> list ) {
+        int sum = 0;
+        for ( Integer i : list ) {
+          sum += i;
+        }
+        return sum;
+    }
+
+    public static double average(final List<Long> vals, final int maxI) {
+        long sum = 0L;
+
+        int i = 0;
+        for (long x : vals) {
+            if (i > maxI)
+                break;
+            sum += x;
+            i++;
+        }
+
+        return (1.0 * sum) / i;
+    }
+
+    public static double average(final List<Long> vals) {
+        return average(vals, vals.size());
+    }
+
+    public static int countOccurrences(final char c, final String s) {
+        int count = 0;
+        for (int i = 0; i < s.length(); i++) {
+            count += s.charAt(i) == c ? 1 : 0;
+        }
+        return count;
+    }
+
+    public static <T> int countOccurrences(T x, List<T> l) {
+        int count = 0;
+        for (T y : l) {
+            if (x.equals(y))
+                count++;
+        }
+
+        return count;
+    }
+
+    public static int countOccurrences(byte element, byte[] array) {
+        int count = 0;
+        for (byte y : array) {
+            if (element == y)
+                count++;
+        }
+
+        return count;
+    }
+
+    public static int countOccurrences(final boolean element, final boolean[] array) {
+        int count = 0;
+        for (final boolean b : array) {
+            if (element == b)
+                count++;
+        }
+
+        return count;
+    }
+
+
+    /**
+     * Returns n random indices drawn with replacement from the range 0..(k-1)
+     *
+     * @param n the total number of indices sampled from
+     * @param k the number of random indices to draw (with replacement)
+     * @return a list of k random indices ranging from 0 to (n-1) with possible duplicates
+     */
+    static public ArrayList<Integer> sampleIndicesWithReplacement(final int n, final int k) {
+
+        ArrayList<Integer> chosen_balls = new ArrayList<Integer>(k);
+        for (int i = 0; i < k; i++) {
+            //Integer chosen_ball = balls[rand.nextInt(k)];
+            chosen_balls.add(GenomeAnalysisEngine.getRandomGenerator().nextInt(n));
+            //balls.remove(chosen_ball);
+        }
+
+        return chosen_balls;
+    }
+
+    /**
+     * Returns n random indices drawn without replacement from the range 0..(k-1)
+     *
+     * @param n the total number of indices sampled from
+     * @param k the number of random indices to draw (without replacement)
+     * @return a list of k random indices ranging from 0 to (n-1) without duplicates
+     */
+    static public ArrayList<Integer> sampleIndicesWithoutReplacement(final int n, final int k) {
+        ArrayList<Integer> chosen_balls = new ArrayList<Integer>(k);
+
+        for (int i = 0; i < n; i++) {
+            chosen_balls.add(i);
+        }
+
+        Collections.shuffle(chosen_balls, GenomeAnalysisEngine.getRandomGenerator());
+
+        //return (ArrayList<Integer>) chosen_balls.subList(0, k);
+        return new ArrayList<Integer>(chosen_balls.subList(0, k));
+    }
+
+    /**
+     * Given a list of indices into a list, return those elements of the list with the possibility of drawing list elements multiple times
+     *
+     * @param indices the list of indices for elements to extract
+     * @param list    the list from which the elements should be extracted
+     * @param <T>     the template type of the ArrayList
+     * @return a new ArrayList consisting of the elements at the specified indices
+     */
+    static public <T> ArrayList<T> sliceListByIndices(final List<Integer> indices, final List<T> list) {
+        ArrayList<T> subset = new ArrayList<T>();
+
+        for (int i : indices) {
+            subset.add(list.get(i));
+        }
+
+        return subset;
+    }
+
+    /**
+     * Given two log-probability vectors, compute log of vector product of them:
+     * in Matlab notation, return log10(10.*x'*10.^y)
+     * @param x vector 1
+     * @param y vector 2
+     * @return a double representing log (dotProd(10.^x,10.^y)
+     */
+    public static double logDotProduct(final double [] x, final double[] y) {
+        if (x.length != y.length)
+            throw new ReviewedGATKException("BUG: Vectors of different lengths");
+
+        double tmpVec[] = new double[x.length];
+
+        for (int k=0; k < tmpVec.length; k++ ) {
+            tmpVec[k] = x[k]+y[k];
+        }
+
+        return log10sumLog10(tmpVec);
+
+
+
+    }
+
+    /**
+     * Check that the log10 prob vector vector is well formed
+     *
+     * @param vector
+     * @param expectedSize
+     * @param shouldSumToOne
+     *
+     * @return true if vector is well-formed, false otherwise
+     */
+    public static boolean goodLog10ProbVector(final double[] vector, final int expectedSize, final boolean shouldSumToOne) {
+        if ( vector.length != expectedSize ) return false;
+
+        for ( final double pr : vector ) {
+            if ( ! goodLog10Probability(pr) )
+                return false;
+        }
+
+        if ( shouldSumToOne && compareDoubles(sumLog10(vector), 1.0, 1e-4) != 0 )
+            return false;
+
+        return true; // everything is good
+    }
+
+    /**
+     * Checks that the result is a well-formed log10 probability
+     *
+     * @param result a supposedly well-formed log10 probability value.  By default allows
+     *               -Infinity values, as log10(0.0) == -Infinity.
+     * @return true if result is really well formed
+     */
+    public static boolean goodLog10Probability(final double result) {
+        return goodLog10Probability(result, true);
+    }
+
+    /**
+     * Checks that the result is a well-formed log10 probability
+     *
+     * @param result a supposedly well-formed log10 probability value
+     * @param allowNegativeInfinity should we consider a -Infinity value ok?
+     * @return true if result is really well formed
+     */
+    public static boolean goodLog10Probability(final double result, final boolean allowNegativeInfinity) {
+        return result <= 0.0 && result != Double.POSITIVE_INFINITY && (allowNegativeInfinity || result != Double.NEGATIVE_INFINITY) && ! Double.isNaN(result);
+    }
+
+    /**
+     * Checks that the result is a well-formed probability
+     *
+     * @param result a supposedly well-formed probability value
+     * @return true if result is really well formed
+     */
+    public static boolean goodProbability(final double result) {
+        return result >= 0.0 && result <= 1.0 && ! Double.isInfinite(result) && ! Double.isNaN(result);
+    }
+
+    /**
+     * A utility class that computes on the fly average and standard deviation for a stream of numbers.
+     * The number of observations does not have to be known in advance, and can be also very big (so that
+     * it could overflow any naive summation-based scheme or cause loss of precision).
+     * Instead, adding a new number <code>observed</code>
+     * to a sample with <code>add(observed)</code> immediately updates the instance of this object so that
+     * it contains correct mean and standard deviation for all the numbers seen so far. Source: Knuth, vol.2
+     * (see also e.g. http://www.johndcook.com/standard_deviation.html for online reference).
+     */
+    public static class RunningAverage {
+        private double mean = 0.0;
+        private double s = 0.0;
+        private long obs_count = 0;
+
+        public void add(double obs) {
+            obs_count++;
+            double oldMean = mean;
+            mean += (obs - mean) / obs_count; // update mean
+            s += (obs - oldMean) * (obs - mean);
+        }
+
+        public void addAll(Collection<Number> col) {
+            for (Number o : col) {
+                add(o.doubleValue());
+            }
+        }
+
+        public double mean() {
+            return mean;
+        }
+
+        public double stddev() {
+            return Math.sqrt(s / (obs_count - 1));
+        }
+
+        public double var() {
+            return s / (obs_count - 1);
+        }
+
+        public long observationCount() {
+            return obs_count;
+        }
+
+        public RunningAverage clone() {
+            RunningAverage ra = new RunningAverage();
+            ra.mean = this.mean;
+            ra.s = this.s;
+            ra.obs_count = this.obs_count;
+            return ra;
+        }
+
+        public void merge(RunningAverage other) {
+            if (this.obs_count > 0 || other.obs_count > 0) { // if we have any observations at all
+                this.mean = (this.mean * this.obs_count + other.mean * other.obs_count) / (this.obs_count + other.obs_count);
+                this.s += other.s;
+            }
+            this.obs_count += other.obs_count;
+        }
+    }
+
+    //
+    // useful common utility routines
+    //
+
+    static public double max(double x0, double x1, double x2) {
+        double a = Math.max(x0, x1);
+        return Math.max(a, x2);
+    }
+
+    /**
+     * Converts LN to LOG10
+     *
+     * @param ln log(x)
+     * @return log10(x)
+     */
+    public static double lnToLog10(final double ln) {
+        return ln * Math.log10(Math.E);
+    }
+
+    /**
+     * Constants to simplify the log gamma function calculation.
+     */
+    private static final double zero = 0.0, one = 1.0, half = .5, a0 = 7.72156649015328655494e-02, a1 = 3.22467033424113591611e-01, a2 = 6.73523010531292681824e-02, a3 = 2.05808084325167332806e-02, a4 = 7.38555086081402883957e-03, a5 = 2.89051383673415629091e-03, a6 = 1.19270763183362067845e-03, a7 = 5.10069792153511336608e-04, a8 = 2.20862790713908385557e-04, a9 = 1.08011567247583939954e-04, a10 = 2.52144565451257326939e-05, a11 = 4.48640949618915160150e-05, tc = 1.46163214496836224576e [...]
+
+    /**
+     * Efficient rounding functions to simplify the log gamma function calculation
+     * double to long with 32 bit shift
+     */
+    private static final int HI(final double x) {
+        return (int) (Double.doubleToLongBits(x) >> 32);
+    }
+
+    /**
+     * Efficient rounding functions to simplify the log gamma function calculation
+     * double to long without shift
+     */
+    private static final int LO(final double x) {
+        return (int) Double.doubleToLongBits(x);
+    }
+
+    /**
+     * Most efficent implementation of the lnGamma (FDLIBM)
+     * Use via the log10Gamma wrapper method.
+     */
+    private static double lnGamma(final double x) {
+        double t, y, z, p, p1, p2, p3, q, r, w;
+        int i;
+
+        int hx = HI(x);
+        int lx = LO(x);
+
+        /* purge off +-inf, NaN, +-0, and negative arguments */
+        int ix = hx & 0x7fffffff;
+        if (ix >= 0x7ff00000)
+            return Double.POSITIVE_INFINITY;
+        if ((ix | lx) == 0 || hx < 0)
+            return Double.NaN;
+        if (ix < 0x3b900000) {    /* |x|<2**-70, return -log(|x|) */
+            return -Math.log(x);
+        }
+
+        /* purge off 1 and 2 */
+        if ((((ix - 0x3ff00000) | lx) == 0) || (((ix - 0x40000000) | lx) == 0))
+            r = 0;
+            /* for x < 2.0 */
+        else if (ix < 0x40000000) {
+            if (ix <= 0x3feccccc) {     /* lgamma(x) = lgamma(x+1)-log(x) */
+                r = -Math.log(x);
+                if (ix >= 0x3FE76944) {
+                    y = one - x;
+                    i = 0;
+                }
+                else if (ix >= 0x3FCDA661) {
+                    y = x - (tc - one);
+                    i = 1;
+                }
+                else {
+                    y = x;
+                    i = 2;
+                }
+            }
+            else {
+                r = zero;
+                if (ix >= 0x3FFBB4C3) {
+                    y = 2.0 - x;
+                    i = 0;
+                } /* [1.7316,2] */
+                else if (ix >= 0x3FF3B4C4) {
+                    y = x - tc;
+                    i = 1;
+                } /* [1.23,1.73] */
+                else {
+                    y = x - one;
+                    i = 2;
+                }
+            }
+
+            switch (i) {
+                case 0:
+                    z = y * y;
+                    p1 = a0 + z * (a2 + z * (a4 + z * (a6 + z * (a8 + z * a10))));
+                    p2 = z * (a1 + z * (a3 + z * (a5 + z * (a7 + z * (a9 + z * a11)))));
+                    p = y * p1 + p2;
+                    r += (p - 0.5 * y);
+                    break;
+                case 1:
+                    z = y * y;
+                    w = z * y;
+                    p1 = t0 + w * (t3 + w * (t6 + w * (t9 + w * t12)));    /* parallel comp */
+                    p2 = t1 + w * (t4 + w * (t7 + w * (t10 + w * t13)));
+                    p3 = t2 + w * (t5 + w * (t8 + w * (t11 + w * t14)));
+                    p = z * p1 - (tt - w * (p2 + y * p3));
+                    r += (tf + p);
+                    break;
+                case 2:
+                    p1 = y * (u0 + y * (u1 + y * (u2 + y * (u3 + y * (u4 + y * u5)))));
+                    p2 = one + y * (v1 + y * (v2 + y * (v3 + y * (v4 + y * v5))));
+                    r += (-0.5 * y + p1 / p2);
+            }
+        }
+        else if (ix < 0x40200000) {             /* x < 8.0 */
+            i = (int) x;
+            t = zero;
+            y = x - (double) i;
+            p = y * (s0 + y * (s1 + y * (s2 + y * (s3 + y * (s4 + y * (s5 + y * s6))))));
+            q = one + y * (r1 + y * (r2 + y * (r3 + y * (r4 + y * (r5 + y * r6)))));
+            r = half * y + p / q;
+            z = one;    /* lgamma(1+s) = log(s) + lgamma(s) */
+            switch (i) {
+                case 7:
+                    z *= (y + 6.0);    /* FALLTHRU */
+                case 6:
+                    z *= (y + 5.0);    /* FALLTHRU */
+                case 5:
+                    z *= (y + 4.0);    /* FALLTHRU */
+                case 4:
+                    z *= (y + 3.0);    /* FALLTHRU */
+                case 3:
+                    z *= (y + 2.0);    /* FALLTHRU */
+                    r += Math.log(z);
+                    break;
+            }
+            /* 8.0 <= x < 2**58 */
+        }
+        else if (ix < 0x43900000) {
+            t = Math.log(x);
+            z = one / x;
+            y = z * z;
+            w = w0 + z * (w1 + y * (w2 + y * (w3 + y * (w4 + y * (w5 + y * w6)))));
+            r = (x - half) * (t - one) + w;
+        }
+        else
+            /* 2**58 <= x <= inf */
+            r = x * (Math.log(x) - one);
+        return r;
+    }
+
+    /**
+     * Calculates the log10 of the gamma function for x using the efficient FDLIBM
+     * implementation to avoid overflows and guarantees high accuracy even for large
+     * numbers.
+     *
+     * @param x the x parameter
+     * @return the log10 of the gamma function at x.
+     */
+    public static double log10Gamma(final double x) {
+        return lnToLog10(lnGamma(x));
+    }
+
+    public static double factorial(final int x) {
+        // avoid rounding errors caused by fact that 10^log(x) might be slightly lower than x and flooring may produce 1 less than real value
+        return (double)Math.round(Math.pow(10, log10Factorial(x)));
+    }
+
+    public static double log10Factorial(final int x) {
+        if (x >= Log10FactorialCache.size() || x < 0)
+            return log10Gamma(x + 1);
+        else
+            return Log10FactorialCache.get(x);
+    }
+
+    /**
+     * Wrapper class so that the log10Factorial array is only calculated if it's used
+     */
+    private static class Log10FactorialCache {
+
+        /**
+         * The size of the precomputed cache.  Must be a positive number!
+         */
+        private static final int CACHE_SIZE = 10_000;
+
+        public static int size() { return CACHE_SIZE; }
+
+        public static double get(final int n) {
+            if (cache == null)
+                initialize();
+            return cache[n];
+        }
+
+        private static synchronized void initialize() {
+            if (cache == null) {
+                Log10Cache.ensureCacheContains(CACHE_SIZE);
+                cache = new double[CACHE_SIZE];
+                cache[0] = 0.0;
+                for (int k = 1; k < cache.length; k++)
+                    cache[k] = cache[k-1] + Log10Cache.get(k);
+            }
+        }
+
+        private static double[] cache = null;
+    }
+
+    /**
+     * Adds two arrays together and returns a new array with the sum.
+     *
+     * @param a one array
+     * @param b another array
+     * @return a new array with the sum of a and b
+     */
+    @Requires("a.length == b.length")
+    @Ensures("result.length == a.length")
+    public static int[] addArrays(final int[] a, final int[] b) {
+        int[] c = new int[a.length];
+        for (int i = 0; i < a.length; i++)
+            c[i] = a[i] + b[i];
+        return c;
+    }
+
+    /** Same routine, unboxed types for efficiency
+     *
+     * @param x                 First vector
+     * @param y                 Second vector
+     * @return Vector of same length as x and y so that z[k] = x[k]+y[k]
+     */
+    public static double[] vectorSum(final double[]x, final double[] y) {
+        if (x.length != y.length)
+            throw new ReviewedGATKException("BUG: Lengths of x and y must be the same");
+
+        double[] result = new double[x.length];
+        for (int k=0; k <x.length; k++)
+            result[k] = x[k]+y[k];
+
+        return result;
+    }
+
+    /** Compute Z=X-Y for two numeric vectors X and Y
+     *
+     * @param x                 First vector
+     * @param y                 Second vector
+     * @return Vector of same length as x and y so that z[k] = x[k]-y[k]
+     */
+    public static int[] vectorDiff(final int[]x, final int[] y) {
+        if (x.length != y.length)
+            throw new ReviewedGATKException("BUG: Lengths of x and y must be the same");
+
+        int[] result = new int[x.length];
+        for (int k=0; k <x.length; k++)
+            result[k] = x[k]-y[k];
+
+        return result;
+    }
+
+    /**
+     * Returns a series of integer values between start and stop, inclusive,
+     * expontentially distributed between the two.  That is, if there are
+     * ten values between 0-10 there will be 10 between 10-100.
+     *
+     * WARNING -- BADLY TESTED
+     * @param start
+     * @param stop
+     * @param eps
+     * @return
+     */
+    public static List<Integer> log10LinearRange(final int start, final int stop, final double eps) {
+        final LinkedList<Integer> values = new LinkedList<>();
+        final double log10range = Math.log10(stop - start);
+
+        if ( start == 0 )
+            values.add(0);
+
+        double i = 0.0;
+        while ( i <= log10range ) {
+            final int index = (int)Math.round(Math.pow(10, i)) + start;
+            if ( index < stop && (values.peekLast() == null || values.peekLast() != index ) )
+                values.add(index);
+            i += eps;
+        }
+
+        if ( values.peekLast() == null || values.peekLast() != stop )
+            values.add(stop);
+
+        return values;
+    }
+
+    /**
+     * Compute in a numerical correct way the quantity log10(1-x)
+     *
+     * Uses the approximation log10(1-x) = log10(1/x - 1) + log10(x) to avoid very quick underflow
+     * in 1-x when x is very small
+     *
+     * @param x a positive double value between 0.0 and 1.0
+     * @return an estimate of log10(1-x)
+     */
+    @Requires("x >= 0.0 && x <= 1.0")
+    @Ensures("result <= 0.0")
+    public static double log10OneMinusX(final double x) {
+        if ( x == 1.0 )
+            return Double.NEGATIVE_INFINITY;
+        else if ( x == 0.0 )
+            return 0.0;
+        else {
+            final double d = Math.log10(1 / x - 1) + Math.log10(x);
+            return Double.isInfinite(d) || d > 0.0 ? 0.0 : d;
+        }
+    }
+
+    /**
+     * Draw N random elements from list
+     * @param list - the list from which to draw randomly
+     * @param N - the number of elements to draw
+     */
+    public static <T> List<T> randomSubset(final List<T> list, final int N) {
+        if (list.size() <= N) {
+            return list;
+        }
+
+        return sliceListByIndices(sampleIndicesWithoutReplacement(list.size(),N),list);
+    }
+
+    /**
+    * Draw N random elements from list with replacement
+    * @param list - the list from which to draw randomly
+    * @param N - the number of elements to draw
+    */
+    public static <T> List<T> randomSample(final List<T> list, final int N) {
+        if (list.isEmpty() ) {
+            return list;
+        }
+        return sliceListByIndices(sampleIndicesWithReplacement(list.size(),N),list);
+    }
+
+    /**
+     * Return the likelihood of observing the counts of categories having sampled a population
+     * whose categorial frequencies are distributed according to a Dirichlet distribution
+     * @param dirichletParams - params of the prior dirichlet distribution
+     * @param dirichletSum - the sum of those parameters
+     * @param counts - the counts of observation in each category
+     * @param countSum - the sum of counts (number of trials)
+     * @return - associated likelihood
+     */
+    public static double dirichletMultinomial(final double[] dirichletParams, final double dirichletSum,
+                                              final int[] counts, final int countSum) {
+        if ( dirichletParams.length != counts.length ) {
+            throw new IllegalStateException("The number of dirichlet parameters must match the number of categories");
+        }
+        // todo -- lots of lnGammas here. At some point we can safely switch to x * ( ln(x) - 1)
+        double likelihood = log10MultinomialCoefficient(countSum,counts);
+        likelihood += log10Gamma(dirichletSum);
+        likelihood -= log10Gamma(dirichletSum+countSum);
+        for ( int idx = 0; idx < counts.length; idx++ ) {
+            likelihood += log10Gamma(counts[idx] + dirichletParams[idx]);
+            likelihood -= log10Gamma(dirichletParams[idx]);
+        }
+
+        return likelihood;
+    }
+
+    public static double dirichletMultinomial(double[] params, int[] counts) {
+        return dirichletMultinomial(params,sum(params),counts,(int) sum(counts));
+    }
+
+    public static ExponentialDistribution exponentialDistribution( final double mean ) {
+        return new ExponentialDistributionImpl(mean);
+    }
+}
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/Median.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/Median.java
new file mode 100644
index 0000000..40e41f2
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/Median.java
@@ -0,0 +1,94 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.utils;
+
+import java.util.*;
+
+/**
+ * Utility class for calculating median from a data set, potentially limiting the size of data to a
+ * fixed amount
+ *
+ * @author Your Name
+ * @since Date created
+ */
+public class Median<T extends Comparable> {
+    final List<T> values;
+    final int maxValuesToKeep;
+    boolean sorted = false;
+
+    public Median() {
+        this(Integer.MAX_VALUE);
+    }
+
+    public Median(final int maxValuesToKeep) {
+        this.maxValuesToKeep = maxValuesToKeep;
+        this.values = new ArrayList<T>();
+    }
+
+    public boolean isFull() {
+        return values.size() >= maxValuesToKeep;
+    }
+
+    public int size() {
+        return values.size();
+    }
+
+    public boolean isEmpty() {
+        return values.isEmpty();
+    }
+
+    public T getMedian() {
+        if ( isEmpty() )
+            throw new IllegalStateException("Cannot get median value from empty array");
+        return getMedian(null);  // note that value null will never be used
+    }
+
+    /**
+     * Returns the floor(n + 1 / 2) item from the list of values if the list
+     * has values, or defaultValue is the list is empty.
+     */
+    public T getMedian(final T defaultValue) {
+        if ( isEmpty() )
+            return defaultValue;
+
+        if ( ! sorted ) {
+            sorted = true;
+            Collections.sort(values);
+        }
+
+        final int offset = (int)Math.floor((values.size() + 1) * 0.5) - 1;
+        return values.get(offset);
+    }
+
+    public boolean add(final T value) {
+        if ( ! isFull() ) {
+            sorted = false;
+            return values.add(value);
+        }
+        else
+            return false;
+    }
+}
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/MendelianViolation.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/MendelianViolation.java
new file mode 100644
index 0000000..75666a7
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/MendelianViolation.java
@@ -0,0 +1,460 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.utils;
+
+import org.broadinstitute.gatk.engine.samples.Sample;
+import htsjdk.variant.variantcontext.Genotype;
+import htsjdk.variant.variantcontext.GenotypeType;
+import htsjdk.variant.variantcontext.VariantContext;
+
+import java.util.*;
+
+/**
+ * User: carneiro / lfran
+ * Date: 3/9/11
+ * Time: 12:38 PM
+ *
+ * Class for the identification and tracking of mendelian violation. It can be used in 2 distinct ways:
+ * - Either using an instance of the MendelianViolation class to track mendelian violations for each of the families while
+ * walking over the variants
+ * - Or using the static methods to directly get information about mendelian violation in a family at a given locus
+ *
+ */
+public class MendelianViolation {
+    //List of families with violations
+    private List<String> violationFamilies;
+
+    //Call information
+    private int nocall = 0;
+    private int familyCalled = 0;
+    private int varFamilyCalled = 0;
+    private int lowQual = 0;
+
+    private boolean allCalledOnly = true;
+
+    //Stores occurrences of inheritance
+    private EnumMap<GenotypeType, EnumMap<GenotypeType,EnumMap<GenotypeType,Integer>>> inheritance;
+
+    private int violations_total=0;
+
+    private double minGenotypeQuality;
+
+    private boolean abortOnSampleNotFound;
+
+    //Number of families with genotype information for all members
+    public int getFamilyCalledCount(){
+        return familyCalled;
+    }
+
+    //Number of families with genotype information for all members
+    public int getVarFamilyCalledCount(){
+        return varFamilyCalled;
+    }
+
+    //Number of families missing genotypes for one or more of their members
+    public int getFamilyNoCallCount(){
+        return nocall;
+    }
+
+    //Number of families with genotypes below the set quality threshold
+    public int getFamilyLowQualsCount(){
+        return lowQual;
+    }
+
+    public int getViolationsCount(){
+        return violations_total;
+    }
+
+    //Count of alt alleles inherited from het parents (no violation)
+    public int getParentHetInheritedVar(){
+        return getParentsHetHetInheritedVar() + getParentsRefHetInheritedVar() + getParentsVarHetInheritedVar();
+    }
+
+    //Count of ref alleles inherited from het parents (no violation)
+    public int getParentHetInheritedRef(){
+        return getParentsHetHetInheritedRef() + getParentsRefHetInheritedRef() + getParentsVarHetInheritedRef();
+    }
+
+    //Count of HomRef/HomRef/HomRef trios
+    public int getRefRefRef(){
+        return inheritance.get(GenotypeType.HOM_REF).get(GenotypeType.HOM_REF).get(GenotypeType.HOM_REF);
+    }
+
+    //Count of HomVar/HomVar/HomVar trios
+    public int getVarVarVar(){
+        return inheritance.get(GenotypeType.HOM_VAR).get(GenotypeType.HOM_VAR).get(GenotypeType.HOM_VAR);
+    }
+
+    //Count of HomRef/HomVar/Het trios
+    public int getRefVarHet(){
+        return inheritance.get(GenotypeType.HOM_REF).get(GenotypeType.HOM_VAR).get(GenotypeType.HET) +
+                inheritance.get(GenotypeType.HOM_VAR).get(GenotypeType.HOM_REF).get(GenotypeType.HET);
+    }
+
+    //Count of Het/Het/Het trios
+    public int getHetHetHet(){
+        return inheritance.get(GenotypeType.HET).get(GenotypeType.HET).get(GenotypeType.HET);
+    }
+
+    //Count of Het/Het/HomRef trios
+    public int getHetHetHomRef(){
+        return inheritance.get(GenotypeType.HET).get(GenotypeType.HET).get(GenotypeType.HOM_REF);
+    }
+
+    //Count of Het/Het/HomVar trios
+    public int getHetHetHomVar(){
+        return inheritance.get(GenotypeType.HET).get(GenotypeType.HET).get(GenotypeType.HOM_VAR);
+    }
+
+    //Count of ref alleles inherited from Het/Het parents (no violation)
+    public int getParentsHetHetInheritedRef(){
+        return inheritance.get(GenotypeType.HET).get(GenotypeType.HET).get(GenotypeType.HET)
+               + 2*inheritance.get(GenotypeType.HET).get(GenotypeType.HET).get(GenotypeType.HOM_REF);
+        //return parentsHetHet_childRef;
+    }
+
+    //Count of var alleles inherited from Het/Het parents (no violation)
+    public int getParentsHetHetInheritedVar(){
+        return inheritance.get(GenotypeType.HET).get(GenotypeType.HET).get(GenotypeType.HET)
+               + 2*inheritance.get(GenotypeType.HET).get(GenotypeType.HET).get(GenotypeType.HOM_VAR);
+        //return parentsHetHet_childVar;
+    }
+
+    //Count of ref alleles inherited from HomRef/Het parents (no violation)
+    public int getParentsRefHetInheritedRef(){
+        return inheritance.get(GenotypeType.HOM_REF).get(GenotypeType.HET).get(GenotypeType.HOM_REF)
+               + inheritance.get(GenotypeType.HET).get(GenotypeType.HOM_REF).get(GenotypeType.HOM_REF);
+        //return parentsHomRefHet_childRef;
+    }
+
+    //Count of var alleles inherited from HomRef/Het parents (no violation)
+    public int getParentsRefHetInheritedVar(){
+        return inheritance.get(GenotypeType.HOM_REF).get(GenotypeType.HET).get(GenotypeType.HET)
+               + inheritance.get(GenotypeType.HET).get(GenotypeType.HOM_REF).get(GenotypeType.HET);
+        //return parentsHomRefHet_childVar;
+    }
+
+    //Count of ref alleles inherited from HomVar/Het parents (no violation)
+    public int getParentsVarHetInheritedRef(){
+        return inheritance.get(GenotypeType.HOM_VAR).get(GenotypeType.HET).get(GenotypeType.HET)
+               + inheritance.get(GenotypeType.HET).get(GenotypeType.HOM_VAR).get(GenotypeType.HET);
+        //return parentsHomVarHet_childRef;
+    }
+
+    //Count of var alleles inherited from HomVar/Het parents (no violation)
+    public int getParentsVarHetInheritedVar(){
+        return inheritance.get(GenotypeType.HOM_VAR).get(GenotypeType.HET).get(GenotypeType.HOM_VAR)
+               + inheritance.get(GenotypeType.HET).get(GenotypeType.HOM_VAR).get(GenotypeType.HOM_VAR);
+        //return parentsHomVarHet_childVar;
+    }
+
+    //Count of violations of the type HOM_REF/HOM_REF -> HOM_VAR
+    public int getParentsRefRefChildVar(){
+        return inheritance.get(GenotypeType.HOM_REF).get(GenotypeType.HOM_REF).get(GenotypeType.HOM_VAR);
+    }
+
+    //Count of violations of the type HOM_REF/HOM_REF -> HET
+    public int getParentsRefRefChildHet(){
+        return inheritance.get(GenotypeType.HOM_REF).get(GenotypeType.HOM_REF).get(GenotypeType.HET);
+    }
+
+    //Count of violations of the type HOM_REF/HET -> HOM_VAR
+    public int getParentsRefHetChildVar(){
+        return inheritance.get(GenotypeType.HOM_REF).get(GenotypeType.HET).get(GenotypeType.HOM_VAR)
+                + inheritance.get(GenotypeType.HET).get(GenotypeType.HOM_REF).get(GenotypeType.HOM_VAR);
+    }
+
+    //Count of violations of the type HOM_REF/HOM_VAR -> HOM_VAR
+    public int getParentsRefVarChildVar(){
+        return inheritance.get(GenotypeType.HOM_REF).get(GenotypeType.HOM_VAR).get(GenotypeType.HOM_VAR)
+                + inheritance.get(GenotypeType.HOM_VAR).get(GenotypeType.HOM_REF).get(GenotypeType.HOM_VAR);
+    }
+
+    //Count of violations of the type HOM_REF/HOM_VAR -> HOM_REF
+    public int getParentsRefVarChildRef(){
+        return inheritance.get(GenotypeType.HOM_REF).get(GenotypeType.HOM_VAR).get(GenotypeType.HOM_REF)
+                + inheritance.get(GenotypeType.HOM_VAR).get(GenotypeType.HOM_REF).get(GenotypeType.HOM_REF);
+    }
+
+    //Count of violations of the type HOM_VAR/HET -> HOM_REF
+    public int getParentsVarHetChildRef(){
+        return inheritance.get(GenotypeType.HET).get(GenotypeType.HOM_VAR).get(GenotypeType.HOM_REF)
+                + inheritance.get(GenotypeType.HOM_VAR).get(GenotypeType.HET).get(GenotypeType.HOM_REF);
+    }
+
+    //Count of violations of the type HOM_VAR/HOM_VAR -> HOM_REF
+    public int getParentsVarVarChildRef(){
+        return inheritance.get(GenotypeType.HOM_VAR).get(GenotypeType.HOM_VAR).get(GenotypeType.HOM_REF);
+    }
+
+    //Count of violations of the type HOM_VAR/HOM_VAR -> HET
+    public int getParentsVarVarChildHet(){
+        return inheritance.get(GenotypeType.HOM_VAR).get(GenotypeType.HOM_VAR).get(GenotypeType.HET);
+    }
+
+
+    //Count of violations of the type HOM_VAR/? -> HOM_REF
+    public int getParentVarChildRef(){
+        return getParentsRefVarChildRef() + getParentsVarHetChildRef() +getParentsVarVarChildRef();
+    }
+
+    //Count of violations of the type HOM_REF/? -> HOM_VAR
+    public int getParentRefChildVar(){
+        return getParentsRefVarChildVar() + getParentsRefHetChildVar() +getParentsRefRefChildVar();
+    }
+
+    //Returns a String containing all trios where a Mendelian violation was observed.
+    //The String is formatted "mom1+dad1=child1,mom2+dad2=child2,..."
+    public String getViolationFamiliesString(){
+        if(violationFamilies.isEmpty())
+            return "";
+
+        Iterator<String> it = violationFamilies.iterator();
+        String violationFams = it.next();
+        while(it.hasNext()){
+            violationFams += ","+it.next();
+        }
+        return violationFams;
+    }
+
+    public List<String> getViolationFamilies(){
+        return violationFamilies;
+    }
+
+    static final int[] mvOffsets = new int[] { 1,2,5,6,8,11,15,18,20,21,24,25 };
+    static final int[] nonMVOffsets = new int[]{ 0,3,4,7,9,10,12,13,14,16,17,19,22,23,26 };
+
+    public double getMinGenotypeQuality() {
+        return minGenotypeQuality;
+    }
+
+   /**
+     * Constructor
+     * @param minGenotypeQualityP - the minimum phred scaled genotype quality score necessary to asses mendelian violation
+     *
+     */
+    public MendelianViolation(double minGenotypeQualityP) {
+        this(minGenotypeQualityP,true);
+    }
+
+    /**
+     * Constructor
+     * @param minGenotypeQualityP - the minimum phred scaled genotype quality score necessary to asses mendelian violation
+     * @param abortOnSampleNotFound - Whether to stop execution if a family is passed but no relevant genotypes are found. If false, then the family is ignored.
+     */
+    public MendelianViolation(double minGenotypeQualityP, boolean abortOnSampleNotFound) {
+        minGenotypeQuality = minGenotypeQualityP;
+        this.abortOnSampleNotFound = abortOnSampleNotFound;
+        violationFamilies = new ArrayList<String>();
+        createInheritanceMap();
+    }
+
+    /**
+     * Constructor
+     * @param minGenotypeQualityP - the minimum phred scaled genotype quality score necessary to asses mendelian violation
+     * @param abortOnSampleNotFound - Whether to stop execution if a family is passed but no relevant genotypes are found. If false, then the family is ignored.
+     * @param completeTriosOnly - whether only complete trios are considered or parent/child pairs are too.
+     */
+    public MendelianViolation(double minGenotypeQualityP, boolean abortOnSampleNotFound, boolean completeTriosOnly) {
+        minGenotypeQuality = minGenotypeQualityP;
+        this.abortOnSampleNotFound = abortOnSampleNotFound;
+        violationFamilies = new ArrayList<String>();
+        createInheritanceMap();
+        allCalledOnly = completeTriosOnly;
+    }
+
+    /**
+     * @param families the families to be checked for Mendelian violations
+     * @param vc the variant context to extract the genotypes and alleles for mom, dad and child.
+     * @return whether or not there is a mendelian violation at the site.
+     */
+    public int countViolations(Map<String, Set<Sample>> families, VariantContext vc){
+
+        //Reset counts
+        nocall = 0;
+        lowQual = 0;
+        familyCalled = 0;
+        varFamilyCalled = 0;
+        violations_total=0;
+        violationFamilies.clear();
+        clearInheritanceMap();
+
+        for(Set<Sample> family : families.values()){
+            Iterator<Sample> sampleIterator = family.iterator();
+            Sample sample;
+            while(sampleIterator.hasNext()){
+                sample = sampleIterator.next();
+                if(sample.getParents().size() > 0)
+                    updateViolations(sample.getFamilyID(),sample.getMaternalID(), sample.getPaternalID(), sample.getID() ,vc);
+            }
+        }
+        return violations_total;
+    }
+
+    public boolean isViolation(Sample mother, Sample father, Sample child, VariantContext vc){
+
+        //Reset counts
+        nocall = 0;
+        lowQual = 0;
+        familyCalled = 0;
+        varFamilyCalled = 0;
+        violations_total=0;
+        violationFamilies.clear();
+        clearInheritanceMap();
+        updateViolations(mother.getFamilyID(),mother.getID(),father.getID(),child.getID(),vc);
+        return violations_total>0;
+    }
+
+
+    private void updateViolations(String familyId, String motherId, String fatherId, String childId, VariantContext vc){
+
+            int count;
+            Genotype gMom = vc.getGenotype(motherId);
+            Genotype gDad = vc.getGenotype(fatherId);
+            Genotype gChild = vc.getGenotype(childId);
+
+            if (gMom == null || gDad == null || gChild == null){
+                if(abortOnSampleNotFound)
+                    throw new IllegalArgumentException(String.format("Variant %s:%d: Missing genotypes for family %s: mom=%s dad=%s family=%s", vc.getChr(), vc.getStart(), familyId, motherId, fatherId, childId));
+                else
+                    return;
+            }
+            //Count No calls
+            if(allCalledOnly && (!gMom.isCalled() || !gDad.isCalled() || !gChild.isCalled())){
+                nocall++;
+            }
+            else if (!gMom.isCalled() && !gDad.isCalled() || !gChild.isCalled()){
+                nocall++;
+            }
+            //Count lowQual. Note that if min quality is set to 0, even values with no quality associated are returned
+            else if (minGenotypeQuality>0 && (gMom.getPhredScaledQual()   < minGenotypeQuality ||
+                gDad.getPhredScaledQual()   < minGenotypeQuality ||
+                gChild.getPhredScaledQual() < minGenotypeQuality )) {
+                lowQual++;
+            }
+            else{
+                //Count all families per loci called
+                familyCalled++;
+                //If the family is all homref, not too interesting
+                if(!(gMom.isHomRef() && gDad.isHomRef() && gChild.isHomRef()))
+                {
+                    varFamilyCalled++;
+                    if(isViolation(gMom, gDad, gChild)){
+                        violationFamilies.add(familyId);
+                        violations_total++;
+                    }
+                }
+                count = inheritance.get(gMom.getType()).get(gDad.getType()).get(gChild.getType());
+                inheritance.get(gMom.getType()).get(gDad.getType()).put(gChild.getType(),count+1);
+
+            }
+    }
+
+    /**
+     * Evaluate the genotypes of mom, dad, and child to detect Mendelian violations
+     *
+     * @param gMom
+     * @param gDad
+     * @param gChild
+     * @return true if the three genotypes represent a Mendelian violation; false otherwise
+     */
+    public static boolean isViolation(final Genotype gMom, final Genotype gDad, final Genotype gChild) {
+        //1 parent is no "call
+        if(!gMom.isCalled()){
+            return (gDad.isHomRef() && gChild.isHomVar()) || (gDad.isHomVar() && gChild.isHomRef());
+        }
+        else if(!gDad.isCalled()){
+            return (gMom.isHomRef() && gChild.isHomVar()) || (gMom.isHomVar() && gChild.isHomRef());
+        }
+        //Both parents have genotype information
+        return !(gMom.getAlleles().contains(gChild.getAlleles().get(0)) && gDad.getAlleles().contains(gChild.getAlleles().get(1)) ||
+            gMom.getAlleles().contains(gChild.getAlleles().get(1)) && gDad.getAlleles().contains(gChild.getAlleles().get(0)));
+    }
+
+    private void createInheritanceMap(){
+
+        inheritance = new EnumMap<GenotypeType,EnumMap<GenotypeType,EnumMap<GenotypeType,Integer>>>(GenotypeType.class);
+        for(GenotypeType mType : GenotypeType.values()){
+            inheritance.put(mType, new EnumMap<GenotypeType,EnumMap<GenotypeType,Integer>>(GenotypeType.class));
+            for(GenotypeType dType : GenotypeType.values()){
+                inheritance.get(mType).put(dType, new EnumMap<GenotypeType,Integer>(GenotypeType.class));
+                for(GenotypeType cType : GenotypeType.values()){
+                    inheritance.get(mType).get(dType).put(cType, 0);
+                }
+            }
+        }
+
+    }
+
+    private void clearInheritanceMap(){
+        for(GenotypeType mType : GenotypeType.values()){
+            for(GenotypeType dType : GenotypeType.values()){
+                for(GenotypeType cType : GenotypeType.values()){
+                    inheritance.get(mType).get(dType).put(cType, 0);
+                }
+            }
+        }
+    }
+
+    /**
+     * @return the likelihood ratio for a mendelian violation
+     */
+    public double violationLikelihoodRatio(VariantContext vc, String motherId, String fatherId, String childId) {
+        double[] logLikAssignments = new double[27];
+        // the matrix to set up is
+        // MOM   DAD    CHILD
+        //                    |-  AA
+        //   AA     AA    |    AB
+        //                    |-   BB
+        //                    |- AA
+        //  AA     AB     |   AB
+        //                    |- BB
+        // etc. The leaves are counted as 0-11 for MVs and 0-14 for non-MVs
+        double[] momGL = vc.getGenotype(motherId).getLikelihoods().getAsVector();
+        double[] dadGL = vc.getGenotype(fatherId).getLikelihoods().getAsVector();
+        double[] childGL = vc.getGenotype(childId).getLikelihoods().getAsVector();
+        int offset = 0;
+        for ( int oMom = 0; oMom < 3; oMom++ ) {
+            for ( int oDad = 0; oDad < 3; oDad++ ) {
+                for ( int oChild = 0; oChild < 3; oChild ++ ) {
+                    logLikAssignments[offset++] = momGL[oMom] + dadGL[oDad] + childGL[oChild];
+                }
+            }
+        }
+        double[] mvLiks = new double[12];
+        double[] nonMVLiks = new double[15];
+        for ( int i = 0; i < 12; i ++ ) {
+            mvLiks[i] = logLikAssignments[mvOffsets[i]];
+        }
+
+        for ( int i = 0; i < 15; i++) {
+            nonMVLiks[i] = logLikAssignments[nonMVOffsets[i]];
+        }
+
+        return MathUtils.log10sumLog10(mvLiks) - MathUtils.log10sumLog10(nonMVLiks);
+    }
+
+}
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/MultiThreadedErrorTracker.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/MultiThreadedErrorTracker.java
new file mode 100644
index 0000000..edbf25d
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/MultiThreadedErrorTracker.java
@@ -0,0 +1,105 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.utils;
+
+import org.broadinstitute.gatk.utils.exceptions.ReviewedGATKException;
+
+/**
+ * A utility to track exceptions that occur across threads.
+ *
+ * Uses a notify mechanism so that multiple threads can tell the tracker that an
+ * error has occurred, and a master thread can monitor this object for an error
+ * occurring and take appropriate action.  Only maintains the first
+ * error to reach the tracker.
+ *
+ * Refactored from HierarchicalMicroScheduler
+ *
+ * User: depristo
+ * Date: 9/19/12
+ * Time: 11:20 AM
+ */
+public class MultiThreadedErrorTracker {
+    /**
+     * An exception that's occurred.  If null, no exception has occurred.
+     */
+    private RuntimeException error = null;
+
+    /**
+     * Convenience function to check, and throw, an error is one is pending
+     */
+    public synchronized void throwErrorIfPending() {
+        if (hasAnErrorOccurred())
+            throw getError();
+    }
+
+    /**
+     * Detects whether an execution error has occurred.
+     * @return True if an error has occurred.  False otherwise.
+     */
+    public synchronized boolean hasAnErrorOccurred() {
+        return error != null;
+    }
+
+    /**
+     * Retrieve the error that has occurred.
+     *
+     * @throws ReviewedGATKException if no error has occurred.
+     * @return
+     */
+    public synchronized RuntimeException getError() {
+        if(!hasAnErrorOccurred())
+            throw new ReviewedGATKException("User has attempted to retrieve a traversal error when none exists");
+        return error;
+    }
+
+    /**
+     * Notify this error tracker that an error has occurs.  Only updates the tracked
+     * error if it is currently null (i.e., no error has been already reported).  So
+     * calling this successively with multiple errors only keeps the first, which is the
+     * right thing to do as the initial failure is usually the meaningful one, but
+     * generates a cascade of failures as other subsystems fail.
+     */
+    public synchronized RuntimeException notifyOfError(Throwable error) {
+        if ( this.error == null )
+            this.error = toRuntimeException(error);
+
+        return this.error;
+    }
+
+    /**
+     * Convert error to a Runtime exception, or keep as is if it already is one
+     *
+     * @param error the error that has occurred
+     * @return the potentially converted error
+     */
+    private RuntimeException toRuntimeException(final Throwable error) {
+        // If the error is already a Runtime, pass it along as is.  Otherwise, wrap it.
+        if (error instanceof RuntimeException)
+            return (RuntimeException)error;
+        else
+            return new ReviewedGATKException("An error occurred during the traversal.  Message=" + error.getMessage(), error);
+    }
+}
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/NGSPlatform.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/NGSPlatform.java
new file mode 100644
index 0000000..f0c40a0
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/NGSPlatform.java
@@ -0,0 +1,136 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.utils;
+
+import org.broadinstitute.gatk.utils.sam.GATKSAMReadGroupRecord;
+import org.broadinstitute.gatk.utils.sam.GATKSAMRecord;
+
+import java.util.LinkedList;
+import java.util.List;
+
+/**
+ * A canonical, master list of the standard NGS platforms.  These values
+ * can be obtained (efficiently) from a GATKSAMRecord object with the
+ * getNGSPlatform method.
+ *
+ * @author Mark DePristo
+ * @since 2011
+ */
+public enum NGSPlatform {
+    // note the order of elements here determines the order of matching operations, and therefore the
+    // efficiency of getting a NGSPlatform from a string.
+    ILLUMINA("ILLUMINA", "SLX", "SOLEXA"),
+    SOLID("SOLID"),
+    LS454("454"),
+    COMPLETE_GENOMICS("COMPLETE"),
+    PACBIO("PACBIO"),
+    ION_TORRENT("IONTORRENT"),
+    CAPILLARY("CAPILLARY"),
+    HELICOS("HELICOS"),
+    UNKNOWN("UNKNOWN");
+
+    /**
+     * Array of the prefix names in a BAM file for each of the platforms.
+     */
+    protected final String[] BAM_PL_NAMES;
+
+    NGSPlatform(final String... BAM_PL_NAMES) {
+        if ( BAM_PL_NAMES.length == 0 ) throw new IllegalStateException("Platforms must have at least one name");
+
+        for ( int i = 0; i < BAM_PL_NAMES.length; i++ )
+            BAM_PL_NAMES[i] = BAM_PL_NAMES[i].toUpperCase();
+
+        this.BAM_PL_NAMES = BAM_PL_NAMES;
+    }
+
+    /**
+     * Returns a representative PL string for this platform
+     * @return
+     */
+    public final String getDefaultPlatform() {
+        return BAM_PL_NAMES[0];
+    }
+
+    /**
+     * Convenience get -- get the NGSPlatform from a GATKSAMRecord.
+     *
+     * Just gets the platform from the GATKReadGroupRecord associated with this read.
+     *
+     * @param read a non-null GATKSAMRecord
+     * @return an NGSPlatform object matching the PL field of the header, of UNKNOWN if there was no match,
+     *         if there is no read group for read, or there's no PL field for the read group
+     */
+    public static NGSPlatform fromRead(final GATKSAMRecord read) {
+        if ( read == null ) throw new IllegalArgumentException("read cannot be null");
+        final GATKSAMReadGroupRecord rg = read.getReadGroup();
+        return rg == null ? UNKNOWN : rg.getNGSPlatform();
+    }
+
+    /**
+     * Returns the NGSPlatform corresponding to the PL tag in the read group
+     * @param plFromRG -- the PL field (or equivalent) in a ReadGroup object.  Can be null => UNKNOWN
+     * @return an NGSPlatform object matching the PL field of the header, or UNKNOWN if there was no match or plFromRG is null
+     */
+    public static NGSPlatform fromReadGroupPL(final String plFromRG) {
+        if ( plFromRG == null ) return UNKNOWN;
+
+        // todo -- algorithm could be implemented more efficiently, as the list of all
+        // todo -- names is known upfront, so a decision tree could be used to identify
+        // todo -- a prefix common to PL
+        final String pl = plFromRG.toUpperCase();
+        for ( final NGSPlatform ngsPlatform : NGSPlatform.values() ) {
+            for ( final String bamPLName : ngsPlatform.BAM_PL_NAMES ) {
+                if ( pl.contains(bamPLName) )
+                    return ngsPlatform;
+            }
+        }
+
+        return UNKNOWN;
+    }
+
+    /**
+     * checks whether or not the requested platform is listed in the set (and is not unknown)
+     *
+     * @param platform the read group string that describes the platform used.  can be null
+     * @return true if the platform is known (i.e. it's in the list and is not UNKNOWN)
+     */
+    public static boolean isKnown(final String platform) {
+        return fromReadGroupPL(platform) != UNKNOWN;
+    }
+
+    /**
+     * Get a human-readable list of platform names
+     * @return the list of platform names
+     */
+    public static String knownPlatformsString() {
+        final List<String> names = new LinkedList<String>();
+        for ( final NGSPlatform pl : values() ) {
+            for ( final String name : pl.BAM_PL_NAMES )
+                names.add(name);
+        }
+        return Utils.join(",", names);
+    }
+}
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/PathUtils.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/PathUtils.java
new file mode 100644
index 0000000..ef6d5a0
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/PathUtils.java
@@ -0,0 +1,195 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.utils;
+
+import org.apache.commons.io.comparator.LastModifiedFileComparator;
+import org.apache.log4j.Logger;
+import org.broadinstitute.gatk.utils.exceptions.ReviewedGATKException;
+
+import java.io.File;
+import java.io.FilenameFilter;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.List;
+
+/**
+ * Created by IntelliJ IDEA.
+ * User: hanna
+ * Date: Mar 30, 2009
+ * Time: 5:43:39 PM
+ * To change this template use File | Settings | File Templates.
+ *
+ * A set of static utility methods for common operations on paths.
+ */
+public class PathUtils {
+    private static Logger logger = Logger.getLogger(PathUtils.class);
+
+    /**
+     * Constructor access disallowed...static utility methods only!
+     */
+    private PathUtils() { }
+
+    /**
+     * Find the files in the given directory matching the given extension.
+     *
+     * @param basePath       Path to search.
+     * @param relativePrefix What directory should the given files be presented relative to?
+     * @param extension      Extension for which to search.
+     * @param recursive      Search recursively.  Beware of symlinks!
+     * @return A list of files matching the specified criteria.
+     *         TODO: Test recursive traversal in the presence of a symlink.
+     */
+    public static List<String> findFilesInPath(final File basePath, final String relativePrefix, final String extension, boolean recursive) {
+        List<String> filesInPath = new ArrayList<String>();
+
+        FilenameFilter filter = new OrFilenameFilter(new DirectoryFilter(),
+                new ExtensionFilter(extension));
+        File[] contents = basePath.listFiles( filter );
+        for (File content : contents) {
+            String relativeFileName = relativePrefix.trim().length() != 0 ?
+                    relativePrefix + File.separator + content.getName() :
+                    content.getName();
+            if (relativeFileName.endsWith(extension))
+                filesInPath.add(relativeFileName);
+            else if (content.isDirectory() && recursive)
+                filesInPath.addAll(findFilesInPath(content, relativeFileName, extension, recursive));
+        }
+
+        return filesInPath;
+    }
+
+    /**
+     * Filter files by extension.
+     */
+    public static class ExtensionFilter implements FilenameFilter {
+        private String extensionName = null;
+
+        public ExtensionFilter(String extensionName) {
+            this.extensionName = extensionName;
+        }
+
+        public boolean accept(File f, String s) {
+            return s.endsWith("." + extensionName);
+        }
+    }
+
+    /**
+     * Filter directories from list of files.
+     */
+    public static class DirectoryFilter implements FilenameFilter {
+        public boolean accept(File f, String s) {
+            return new File(f, s).isDirectory();
+        }
+    }
+
+    /**
+     * Join two FilenameFilters together in a logical 'or' operation.
+     */
+    public static class OrFilenameFilter implements FilenameFilter {
+        private FilenameFilter lhs = null, rhs = null;
+
+        public OrFilenameFilter(FilenameFilter lhs, FilenameFilter rhs) {
+            this.lhs = lhs;
+            this.rhs = rhs;
+        }
+
+        public boolean accept(File f, String s) {
+            return lhs.accept(f, s) || rhs.accept(f, s);
+        }
+    }
+
+    /**
+     * Refreshes the volume associated with a given file or directory by attempting to access it
+     * a few times before giving up.  The file need not exist, though the parent directory must.
+     * This method is particularly useful when your job has been dispatched to LSF and you need to
+     * ensure an NSF-mounted volume is actually accessible (many times it isn't for a few seconds,
+     * just enough to cause your program to come crashing down).
+     *
+     * @param file  the file or directory that resides in the volume to be refreshed.
+     */
+    public static void refreshVolume(File file) {
+        File dir = file.isDirectory() ? file : file.getParentFile();
+
+        int sleepCount = 0;
+        while (sleepCount < 3 && dir.listFiles() == null) {
+            try {
+                Thread.sleep((sleepCount + 1)*3000);
+            } catch (InterruptedException e) {
+            }
+
+            sleepCount++;
+        }
+
+        if (dir.listFiles() == null) {
+            throw new ReviewedGATKException("The volume '" + dir.getAbsolutePath() + "' could not be accessed.");
+        }
+    }
+
+
+    /**
+     * Walk over the GATK released directories to find the most recent JAR files corresponding
+     * to the version prefix.  For example, providing input "1.2" will
+     * return the full path to the most recent GenomeAnalysisTK.jar in the GATK_RELEASE_DIR
+     * in directories that match gatkReleaseDir/GenomeAnalysisTK-1.2*
+     *
+     * @param gatkReleaseDir Path to directory containing GATK release binaries (e.g., /humgen/gsa-hpprojects/GATK/bin/)
+     * @param releaseVersionNumber Desired GATK version number (e.g., 1.2)
+     * @return A file pointing to the most recent GATK file in the release directory with GATK release number
+     */
+    public static File findMostRecentGATKVersion(final File gatkReleaseDir, final String releaseVersionNumber) {
+        final String versionString = "GenomeAnalysisTK-" + releaseVersionNumber;
+
+        final List<File> gatkJars = new ArrayList<File>();
+        for ( final String path : gatkReleaseDir.list(new isGATKVersion(versionString)) ) {
+            gatkJars.add(new File(gatkReleaseDir.getAbsolutePath() + "/" + path + "/GenomeAnalysisTK.jar"));
+        }
+
+        if ( gatkJars.isEmpty() )
+            return null;
+        else {
+            Collections.sort(gatkJars, LastModifiedFileComparator.LASTMODIFIED_REVERSE);
+            //for ( File jar : gatkJars ) logger.info(String.format("%s => %d", jar, jar.lastModified()));
+            final File last = gatkJars.get(0);
+            logger.debug(String.format("findMostRecentGATKVersion: Found %d jars for %s, keeping last one %s",
+                    gatkJars.size(), releaseVersionNumber, last));
+            return last;
+        }
+    }
+
+    private final static class isGATKVersion implements FilenameFilter {
+        private final String versionString;
+
+        private isGATKVersion(final String versionString) {
+            this.versionString = versionString;
+        }
+
+        @Override
+        public boolean accept(final File file, final String s) {
+            return s.contains(versionString);
+        }
+    }
+}
\ No newline at end of file
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/QualityUtils.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/QualityUtils.java
new file mode 100644
index 0000000..cd6cfc6
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/QualityUtils.java
@@ -0,0 +1,397 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.utils;
+
+import com.google.java.contract.Ensures;
+import htsjdk.samtools.SAMUtils;
+
+/**
+ * QualityUtils is a static class (no instantiation allowed!) with some utility methods for manipulating
+ * quality scores.
+ *
+ * @author Kiran Garimella, Mark DePristo
+ * @since Way back
+ */
+public class QualityUtils {
+    /**
+     * Maximum quality score that can be encoded in a SAM/BAM file
+     */
+    public final static byte MAX_SAM_QUAL_SCORE = SAMUtils.MAX_PHRED_SCORE;
+
+
+    private final static double RAW_MIN_PHRED_SCALED_QUAL = Math.log10(Double.MIN_VALUE);
+    protected final static double MIN_PHRED_SCALED_QUAL = -10.0 * RAW_MIN_PHRED_SCALED_QUAL;
+
+    /**
+     * bams containing quals above this value are extremely suspicious and we should warn the user
+     */
+    public final static byte MAX_REASONABLE_Q_SCORE = 60;
+
+    /**
+     * The lowest quality score for a base that is considered reasonable for statistical analysis.  This is
+     * because Q 6 => you stand a 25% of being right, which means all bases are equally likely
+     */
+    public final static byte MIN_USABLE_Q_SCORE = 6;
+    public final static int MAPPING_QUALITY_UNAVAILABLE = 255;
+
+    /**
+     * Maximum sense quality value.
+     */
+    public static final int MAX_QUAL = 254;
+
+    /**
+     * Cached values for qual as byte calculations so they are very fast
+     */
+    private static double qualToErrorProbCache[] = new double[MAX_QUAL + 1];
+    private static double qualToProbLog10Cache[] = new double[MAX_QUAL + 1];
+
+
+    static {
+        for (int i = 0; i <= MAX_QUAL; i++) {
+            qualToErrorProbCache[i] = qualToErrorProb((double) i);
+            qualToProbLog10Cache[i] = Math.log10(1.0 - qualToErrorProbCache[i]);
+        }
+    }
+
+    /**
+     * Private constructor.  No instantiating this class!
+     */
+    private QualityUtils() {}
+
+    // ----------------------------------------------------------------------
+    //
+    // These are all functions to convert a phred-scaled quality score to a probability
+    //
+    // ----------------------------------------------------------------------
+
+    /**
+     * Convert a phred-scaled quality score to its probability of being true (Q30 => 0.999)
+     *
+     * This is the Phred-style conversion, *not* the Illumina-style conversion.
+     *
+     * Because the input is a discretized byte value, this function uses a cache so is very efficient
+     *
+     * WARNING -- because this function takes a byte for maxQual, you must be careful in converting
+     * integers to byte.  The appropriate way to do this is ((byte)(myInt & 0xFF))
+     *
+     * @param qual a quality score (0-255)
+     * @return a probability (0.0-1.0)
+     */
+    @Ensures("result >= 0.0 && result <= 1.0")
+    public static double qualToProb(final byte qual) {
+        return 1.0 - qualToErrorProb(qual);
+    }
+
+    /**
+     * Convert a phred-scaled quality score to its probability of being true (Q30 => 0.999)
+     *
+     * This is the Phred-style conversion, *not* the Illumina-style conversion.
+     *
+     * Because the input is a double value, this function must call Math.pow so can be quite expensive
+     *
+     * @param qual a phred-scaled quality score encoded as a double.  Can be non-integer values (30.5)
+     * @return a probability (0.0-1.0)
+     */
+    @Ensures("result >= 0.0 && result <= 1.0")
+    public static double qualToProb(final double qual) {
+        if ( qual < 0.0 ) throw new IllegalArgumentException("qual must be >= 0.0 but got " + qual);
+        return 1.0 - qualToErrorProb(qual);
+    }
+
+    /**
+     * Convert a phred-scaled quality score to its log10 probability of being true (Q30 => log10(0.999))
+     *
+     * This is the Phred-style conversion, *not* the Illumina-style conversion.
+     *
+     * Because the input is a double value, this function must call Math.pow so can be quite expensive
+     *
+     * WARNING -- because this function takes a byte for maxQual, you must be careful in converting
+     * integers to byte.  The appropriate way to do this is ((byte)(myInt & 0xFF))
+     *
+     * @param qual a phred-scaled quality score encoded as a double.  Can be non-integer values (30.5)
+     * @return a probability (0.0-1.0)
+     */
+    @Ensures("result <= 0.0")
+    public static double qualToProbLog10(final byte qual) {
+        return qualToProbLog10Cache[(int)qual & 0xff]; // Map: 127 -> 127; -128 -> 128; -1 -> 255; etc.
+    }
+
+    /**
+     * Convert a phred-scaled quality score to its probability of being wrong (Q30 => 0.001)
+     *
+     * This is the Phred-style conversion, *not* the Illumina-style conversion.
+     *
+     * Because the input is a double value, this function must call Math.pow so can be quite expensive
+     *
+     * @param qual a phred-scaled quality score encoded as a double.  Can be non-integer values (30.5)
+     * @return a probability (0.0-1.0)
+     */
+    @Ensures("result >= 0.0 && result <= 1.0")
+    public static double qualToErrorProb(final double qual) {
+        if ( qual < 0.0 ) throw new IllegalArgumentException("qual must be >= 0.0 but got " + qual);
+        return Math.pow(10.0, qual / -10.0);
+    }
+
+    /**
+     * Convert a phred-scaled quality score to its probability of being wrong (Q30 => 0.001)
+     *
+     * This is the Phred-style conversion, *not* the Illumina-style conversion.
+     *
+     * Because the input is a byte value, this function uses a cache so is very efficient
+     *
+     * WARNING -- because this function takes a byte for maxQual, you must be careful in converting
+     * integers to byte.  The appropriate way to do this is ((byte)(myInt & 0xFF))
+     *
+     * @param qual a phred-scaled quality score encoded as a byte
+     * @return a probability (0.0-1.0)
+     */
+    @Ensures("result >= 0.0 && result <= 1.0")
+    public static double qualToErrorProb(final byte qual) {
+        return qualToErrorProbCache[(int)qual & 0xff]; // Map: 127 -> 127; -128 -> 128; -1 -> 255; etc.
+    }
+
+
+    /**
+     * Convert a phred-scaled quality score to its log10 probability of being wrong (Q30 => log10(0.001))
+     *
+     * This is the Phred-style conversion, *not* the Illumina-style conversion.
+     *
+     * The calculation is extremely efficient
+     *
+     * WARNING -- because this function takes a byte for maxQual, you must be careful in converting
+     * integers to byte.  The appropriate way to do this is ((byte)(myInt & 0xFF))
+     *
+     * @param qual a phred-scaled quality score encoded as a byte
+     * @return a probability (0.0-1.0)
+     */
+    @Ensures("result <= 0.0")
+    public static double qualToErrorProbLog10(final byte qual) {
+        return qualToErrorProbLog10((double)(qual & 0xFF));
+    }
+
+    /**
+     * Convert a phred-scaled quality score to its log10 probability of being wrong (Q30 => log10(0.001))
+     *
+     * This is the Phred-style conversion, *not* the Illumina-style conversion.
+     *
+     * The calculation is extremely efficient
+     *
+     * @param qual a phred-scaled quality score encoded as a double
+     * @return a probability (0.0-1.0)
+     */
+    @Ensures("result <= 0.0")
+    public static double qualToErrorProbLog10(final double qual) {
+        if ( qual < 0.0 ) throw new IllegalArgumentException("qual must be >= 0.0 but got " + qual);
+        return qual / -10.0;
+    }
+
+    // ----------------------------------------------------------------------
+    //
+    // Functions to convert a probability to a phred-scaled quality score
+    //
+    // ----------------------------------------------------------------------
+
+    /**
+     * Convert a probability of being wrong to a phred-scaled quality score (0.01 => 20).
+     *
+     * Note, this function caps the resulting quality score by the public static value MAX_SAM_QUAL_SCORE
+     * and by 1 at the low-end.
+     *
+     * @param errorRate a probability (0.0-1.0) of being wrong (i.e., 0.01 is 1% change of being wrong)
+     * @return a quality score (0-MAX_SAM_QUAL_SCORE)
+     */
+    public static byte errorProbToQual(final double errorRate) {
+        return errorProbToQual(errorRate, MAX_SAM_QUAL_SCORE);
+    }
+
+    /**
+     * Convert a probability of being wrong to a phred-scaled quality score (0.01 => 20).
+     *
+     * Note, this function caps the resulting quality score by the public static value MIN_REASONABLE_ERROR
+     * and by 1 at the low-end.
+     *
+     * WARNING -- because this function takes a byte for maxQual, you must be careful in converting
+     * integers to byte.  The appropriate way to do this is ((byte)(myInt & 0xFF))
+     *
+     * @param errorRate a probability (0.0-1.0) of being wrong (i.e., 0.01 is 1% change of being wrong)
+     * @return a quality score (0-maxQual)
+     */
+    public static byte errorProbToQual(final double errorRate, final byte maxQual) {
+        if ( ! MathUtils.goodProbability(errorRate) ) throw new IllegalArgumentException("errorRate must be good probability but got " + errorRate);
+        final double d = Math.round(-10.0*Math.log10(errorRate));
+        return boundQual((int)d, maxQual);
+    }
+
+    /**
+     * @see #errorProbToQual(double, byte) with proper conversion of maxQual integer to a byte
+     */
+    public static byte errorProbToQual(final double prob, final int maxQual) {
+        if ( maxQual < 0 || maxQual > 255 ) throw new IllegalArgumentException("maxQual must be between 0-255 but got " + maxQual);
+        return errorProbToQual(prob, (byte)(maxQual & 0xFF));
+    }
+
+    /**
+     * Convert a probability of being right to a phred-scaled quality score (0.99 => 20).
+     *
+     * Note, this function caps the resulting quality score by the public static value MAX_SAM_QUAL_SCORE
+     * and by 1 at the low-end.
+     *
+     * @param prob a probability (0.0-1.0) of being right
+     * @return a quality score (0-MAX_SAM_QUAL_SCORE)
+     */
+    public static byte trueProbToQual(final double prob) {
+        return trueProbToQual(prob, MAX_SAM_QUAL_SCORE);
+    }
+
+    /**
+     * Convert a probability of being right to a phred-scaled quality score (0.99 => 20).
+     *
+     * Note, this function caps the resulting quality score by the min probability allowed (EPS).
+     * So for example, if prob is 1e-6, which would imply a Q-score of 60, and EPS is 1e-4,
+     * the result of this function is actually Q40.
+     *
+     * Note that the resulting quality score, regardless of EPS, is capped by MAX_SAM_QUAL_SCORE and
+     * bounded on the low-side by 1.
+     *
+     * WARNING -- because this function takes a byte for maxQual, you must be careful in converting
+     * integers to byte.  The appropriate way to do this is ((byte)(myInt & 0xFF))
+     *
+     * @param trueProb a probability (0.0-1.0) of being right
+     * @param maxQual the maximum quality score we are allowed to emit here, regardless of the error rate
+     * @return a phred-scaled quality score (0-maxQualScore) as a byte
+     */
+    @Ensures("(result & 0xFF) >= 1 && (result & 0xFF) <= (maxQual & 0xFF)")
+    public static byte trueProbToQual(final double trueProb, final byte maxQual) {
+        if ( ! MathUtils.goodProbability(trueProb) ) throw new IllegalArgumentException("trueProb must be good probability but got " + trueProb);
+        final double lp = Math.round(-10.0*MathUtils.log10OneMinusX(trueProb));
+        return boundQual((int)lp, maxQual);
+    }
+
+    /**
+     * @see #trueProbToQual(double, byte) with proper conversion of maxQual to a byte
+     */
+    public static byte trueProbToQual(final double prob, final int maxQual) {
+        if ( maxQual < 0 || maxQual > 255 ) throw new IllegalArgumentException("maxQual must be between 0-255 but got " + maxQual);
+        return trueProbToQual(prob, (byte)(maxQual & 0xFF));
+    }
+
+    /**
+     * Convert a probability of being right to a phred-scaled quality score of being wrong as a double
+     *
+     * This is a very generic method, that simply computes a phred-scaled double quality
+     * score given an error rate.  It has the same precision as a normal double operation
+     *
+     * @param trueRate the probability of being right (0.0-1.0)
+     * @return a phred-scaled version of the error rate implied by trueRate
+     */
+    @Ensures("result >= 0.0")
+    public static double phredScaleCorrectRate(final double trueRate) {
+        return phredScaleLog10ErrorRate(MathUtils.log10OneMinusX(trueRate));
+    }
+
+    /**
+     * Convert a log10 probability of being right to a phred-scaled quality score of being wrong as a double
+     *
+     * This is a very generic method, that simply computes a phred-scaled double quality
+     * score given an error rate.  It has the same precision as a normal double operation
+     *
+     * @param trueRateLog10 the log10 probability of being right (0.0-1.0).  Can be -Infinity to indicate
+     *                      that the result is impossible in which MIN_PHRED_SCALED_QUAL is returned
+     * @return a phred-scaled version of the error rate implied by trueRate
+     */
+    @Ensures("result >= 0.0")
+    public static double phredScaleLog10CorrectRate(final double trueRateLog10) {
+        return phredScaleCorrectRate(Math.pow(10.0, trueRateLog10));
+    }
+
+    /**
+     * Convert a probability of being wrong to a phred-scaled quality score of being wrong as a double
+     *
+     * This is a very generic method, that simply computes a phred-scaled double quality
+     * score given an error rate.  It has the same precision as a normal double operation
+     *
+     * @param errorRate the probability of being wrong (0.0-1.0)
+     * @return a phred-scaled version of the error rate
+     */
+    @Ensures("result >= 0.0")
+    public static double phredScaleErrorRate(final double errorRate) {
+        return phredScaleLog10ErrorRate(Math.log10(errorRate));
+    }
+
+    /**
+     * Convert a log10 probability of being wrong to a phred-scaled quality score of being wrong as a double
+     *
+     * This is a very generic method, that simply computes a phred-scaled double quality
+     * score given an error rate.  It has the same precision as a normal double operation
+     *
+     * @param errorRateLog10 the log10 probability of being wrong (0.0-1.0).  Can be -Infinity, in which case
+     *                       the result is MIN_PHRED_SCALED_QUAL
+     * @return a phred-scaled version of the error rate
+     */
+    @Ensures("result >= 0.0")
+    public static double phredScaleLog10ErrorRate(final double errorRateLog10) {
+        if ( ! MathUtils.goodLog10Probability(errorRateLog10) ) throw new IllegalArgumentException("errorRateLog10 must be good probability but got " + errorRateLog10);
+        // abs is necessary for edge base with errorRateLog10 = 0 producing -0.0 doubles
+        return Math.abs(-10.0 * Math.max(errorRateLog10, RAW_MIN_PHRED_SCALED_QUAL));
+    }
+
+    // ----------------------------------------------------------------------
+    //
+    // Routines to bound a quality score to a reasonable range
+    //
+    // ----------------------------------------------------------------------
+
+    /**
+     * Return a quality score that bounds qual by MAX_SAM_QUAL_SCORE and 1
+     *
+     * @param qual the uncapped quality score as an integer
+     * @return the bounded quality score
+     */
+    @Ensures("(result & 0xFF) >= 1 && (result & 0xFF) <= (MAX_SAM_QUAL_SCORE & 0xFF)")
+    public static byte boundQual(int qual) {
+        return boundQual(qual, MAX_SAM_QUAL_SCORE);
+    }
+
+    /**
+     * Return a quality score that bounds qual by maxQual and 1
+     *
+     * WARNING -- because this function takes a byte for maxQual, you must be careful in converting
+     * integers to byte.  The appropriate way to do this is ((byte)(myInt & 0xFF))
+     *
+     * @param qual the uncapped quality score as an integer.  Can be < 0 (which may indicate an error in the
+     *             client code), which will be brought back to 1, but this isn't an error, as some
+     *             routines may use this functionality (BaseRecalibrator, for example)
+     * @param maxQual the maximum quality score, must be less < 255
+     * @return the bounded quality score
+     */
+    @Ensures("(result & 0xFF) >= 1 && (result & 0xFF) <= (maxQual & 0xFF)")
+    public static byte boundQual(final int qual, final byte maxQual) {
+        return (byte) (Math.max(Math.min(qual, maxQual & 0xFF), 1) & 0xFF);
+    }
+
+    }
+
+
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/R/RScriptExecutor.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/R/RScriptExecutor.java
new file mode 100644
index 0000000..c6c4fba
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/R/RScriptExecutor.java
@@ -0,0 +1,191 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.utils.R;
+
+import org.apache.commons.io.FileUtils;
+import org.apache.commons.lang.StringUtils;
+import org.apache.log4j.Logger;
+import org.broadinstitute.gatk.utils.Utils;
+import org.broadinstitute.gatk.utils.exceptions.GATKException;
+import org.broadinstitute.gatk.utils.exceptions.UserException;
+import org.broadinstitute.gatk.utils.io.IOUtils;
+import org.broadinstitute.gatk.utils.io.Resource;
+import org.broadinstitute.gatk.utils.runtime.ProcessController;
+import org.broadinstitute.gatk.utils.runtime.ProcessSettings;
+import org.broadinstitute.gatk.utils.runtime.RuntimeUtils;
+
+import java.io.File;
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Generic service for executing RScripts
+ */
+public class RScriptExecutor {
+    private static final String RSCRIPT_BINARY = "Rscript";
+    private static final File RSCRIPT_PATH = RuntimeUtils.which(RSCRIPT_BINARY);
+    public static final boolean RSCRIPT_EXISTS = (RSCRIPT_PATH != null);
+    private static final String RSCRIPT_MISSING_MESSAGE = "Please add the Rscript directory to your environment ${PATH}";
+
+    /**
+     * our log
+     */
+    private static Logger logger = Logger.getLogger(RScriptExecutor.class);
+
+    private boolean exceptOnError = false;
+    private final List<RScriptLibrary> libraries = new ArrayList<RScriptLibrary>();
+    private final List<Resource> scriptResources = new ArrayList<Resource>();
+    private final List<File> scriptFiles = new ArrayList<File>();
+    private final List<String> args = new ArrayList<String>();
+
+    public void setExceptOnError(boolean exceptOnError) {
+        this.exceptOnError = exceptOnError;
+    }
+
+    public void addLibrary(RScriptLibrary library) {
+        this.libraries.add(library);
+    }
+
+    public void addScript(Resource script) {
+        this.scriptResources.add(script);
+    }
+
+    public void addScript(File script) {
+        this.scriptFiles.add(script);
+    }
+
+    /**
+     * Adds args to the end of the Rscript command line.
+     * @param args the args.
+     * @throws NullPointerException if any of the args are null.
+     */
+    public void addArgs(Object... args) {
+        for (Object arg: args)
+            this.args.add(arg.toString());
+    }
+
+    public String getApproximateCommandLine() {
+        StringBuilder command = new StringBuilder("Rscript");
+        for (Resource script: this.scriptResources)
+            command.append(" (resource)").append(script.getFullPath());
+        for (File script: this.scriptFiles)
+            command.append(" ").append(script.getAbsolutePath());
+        for (String arg: this.args)
+            command.append(" ").append(arg);
+        return command.toString();
+    }
+
+    public boolean exec() {
+        if (!RSCRIPT_EXISTS) {
+            if (exceptOnError) {
+                throw new UserException.CannotExecuteRScript(RSCRIPT_MISSING_MESSAGE);
+            } else {
+                logger.warn("Skipping: " + getApproximateCommandLine());
+                return false;
+            }
+        }
+
+        List<File> tempFiles = new ArrayList<File>();
+        try {
+            File tempLibSourceDir  = IOUtils.tempDir("RlibSources.", "");
+            File tempLibInstallationDir = IOUtils.tempDir("Rlib.", "");
+            tempFiles.add(tempLibSourceDir);
+            tempFiles.add(tempLibInstallationDir);
+
+            StringBuilder expression = new StringBuilder("tempLibDir = '").append(tempLibInstallationDir).append("';");
+
+            if (this.libraries.size() > 0) {
+                List<String> tempLibraryPaths = new ArrayList<String>();
+                for (RScriptLibrary library: this.libraries) {
+                    File tempLibrary = library.writeLibrary(tempLibSourceDir);
+                    tempFiles.add(tempLibrary);
+                    tempLibraryPaths.add(tempLibrary.getAbsolutePath());
+                }
+
+                expression.append("install.packages(");
+                expression.append("pkgs=c('").append(StringUtils.join(tempLibraryPaths, "', '")).append("'), lib=tempLibDir, repos=NULL, type='source', ");
+                // Install faster by eliminating cruft.
+                expression.append("INSTALL_opts=c('--no-libs', '--no-data', '--no-help', '--no-demo', '--no-exec')");
+                expression.append(");");
+
+                for (RScriptLibrary library: this.libraries) {
+                    expression.append("library('").append(library.getLibraryName()).append("', lib.loc=tempLibDir);");
+                }
+            }
+
+            for (Resource script: this.scriptResources) {
+                File tempScript = IOUtils.writeTempResource(script);
+                tempFiles.add(tempScript);
+                expression.append("source('").append(tempScript.getAbsolutePath()).append("');");
+            }
+
+            for (File script: this.scriptFiles) {
+                expression.append("source('").append(script.getAbsolutePath()).append("');");
+            }
+
+            String[] cmd = new String[this.args.size() + 3];
+            int i = 0;
+            cmd[i++] = RSCRIPT_BINARY;
+            cmd[i++] = "-e";
+            cmd[i++] = expression.toString();
+            for (String arg: this.args)
+                cmd[i++] = arg;
+
+            ProcessSettings processSettings = new ProcessSettings(cmd);
+            if (logger.isDebugEnabled()) {
+                processSettings.getStdoutSettings().printStandard(true);
+                processSettings.getStderrSettings().printStandard(true);
+            }
+
+            ProcessController controller = ProcessController.getThreadLocal();
+
+            if (logger.isDebugEnabled()) {
+                logger.debug("Executing:");
+                for (String arg: cmd)
+                    logger.debug("  " + arg);
+            }
+            int exitValue = controller.exec(processSettings).getExitValue();
+            logger.debug("Result: " + exitValue);
+
+            if (exitValue != 0)
+                throw new RScriptExecutorException(
+                        "RScript exited with " + exitValue +
+                                (logger.isDebugEnabled() ? "" : ". Run with -l DEBUG for more info."));
+
+            return true;
+        } catch (GATKException e) {
+            if (exceptOnError) {
+                throw e;
+            } else {
+                logger.warn(e.getMessage());
+                return false;
+            }
+        } finally {
+            for (File temp: tempFiles)
+                FileUtils.deleteQuietly(temp);
+        }
+    }
+}
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/R/RScriptExecutorException.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/R/RScriptExecutorException.java
new file mode 100644
index 0000000..233ff73
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/R/RScriptExecutorException.java
@@ -0,0 +1,34 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.utils.R;
+
+import org.broadinstitute.gatk.utils.exceptions.ReviewedGATKException;
+
+public class RScriptExecutorException extends ReviewedGATKException {
+    public RScriptExecutorException(String msg) {
+        super(msg);
+    }
+}
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/R/RScriptLibrary.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/R/RScriptLibrary.java
new file mode 100644
index 0000000..390edc7
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/R/RScriptLibrary.java
@@ -0,0 +1,66 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.utils.R;
+
+import org.broadinstitute.gatk.utils.io.IOUtils;
+import org.broadinstitute.gatk.utils.io.Resource;
+
+import java.io.File;
+
+/**
+ * Libraries embedded in the StingUtils package.
+ */
+public enum RScriptLibrary {
+    GSALIB("gsalib");
+
+    private final String name;
+
+    private RScriptLibrary(String name) {
+        this.name = name;
+    }
+
+    public String getLibraryName() {
+        return this.name;
+    }
+
+    public String getResourcePath() {
+        return name + ".tar.gz";
+    }
+
+    /**
+     * Writes the library source code to a temporary tar.gz file and returns the path.
+     * @return The path to the library source code. The caller must delete the code when done.
+     */
+    public File writeTemp() {
+        return IOUtils.writeTempResource(new Resource(getResourcePath(), RScriptLibrary.class));
+    }
+
+    public File writeLibrary(File tempDir) {
+        File libraryFile = new File(tempDir, getLibraryName());
+        IOUtils.writeResource(new Resource(getResourcePath(), RScriptLibrary.class), libraryFile);
+        return libraryFile;
+    }
+}
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/R/RUtils.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/R/RUtils.java
new file mode 100644
index 0000000..80f7313
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/R/RUtils.java
@@ -0,0 +1,91 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.utils.R;
+
+import org.apache.commons.lang.StringUtils;
+
+import java.text.SimpleDateFormat;
+import java.util.Collection;
+import java.util.Date;
+
+public class RUtils {
+    /**
+     * Converts a collection of values to an R compatible list. A null list will return NA,
+     * otherwise the values will be escaped with single quotes and combined with c().
+     * @param list Collection of values
+     * @return The R representation of the list
+     */
+    public static String toStringList(Collection<? extends CharSequence> list) {
+        if (list == null)
+            return "NA";
+        if (list.size() == 0)
+            return "c()";
+        return "c('" + StringUtils.join(list, "','") + "')";
+    }
+
+    /**
+     * Converts a collection of values to an R compatible list. A null list will return NA,
+     * otherwise the values will be combined with c().
+     * @param list Collection of values
+     * @return The R representation of the list
+     */
+    public static String toNumberList(Collection<? extends Number> list) {
+        return list == null ? "NA": "c(" + StringUtils.join(list, ",") + ")";
+    }
+
+    /**
+     * Converts a collection of values to an R compatible list. A null list will return NA,
+     * otherwise the date will be escaped with single quotes and combined with c().
+     * @param list Collection of values
+     * @return The R representation of the list
+     */
+    public static String toDateList(Collection<? extends Date> list) {
+        return toDateList(list, "''yyyy-MM-dd''");
+    }
+
+    /**
+     * Converts a collection of values to an R compatible list formatted by pattern.
+     * @param list Collection of values
+     * @param pattern format pattern string for each date
+     * @return The R representation of the list
+     */
+    public static String toDateList(Collection<? extends Date> list, String pattern) {
+
+        if (list == null)
+            return "NA";
+        SimpleDateFormat format = new SimpleDateFormat(pattern);
+        StringBuilder sb = new StringBuilder();
+        sb.append("c(");
+        boolean first = true;
+        for (Date date : list) {
+            if (!first) sb.append(",");
+            sb.append(format.format(date));
+            first = false;
+        }
+        sb.append(")");
+        return sb.toString();
+    }
+}
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/SampleUtils.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/SampleUtils.java
new file mode 100644
index 0000000..77fc170
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/SampleUtils.java
@@ -0,0 +1,290 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.utils;
+
+import htsjdk.samtools.SAMFileHeader;
+import htsjdk.samtools.SAMReadGroupRecord;
+import org.broadinstitute.gatk.engine.GenomeAnalysisEngine;
+import org.broadinstitute.gatk.utils.exceptions.UserException;
+import org.broadinstitute.gatk.utils.variant.GATKVCFUtils;
+import org.broadinstitute.gatk.utils.variant.GATKVariantContextUtils;
+import org.broadinstitute.gatk.utils.collections.Pair;
+import htsjdk.variant.vcf.VCFHeader;
+import org.broadinstitute.gatk.utils.text.ListFileUtils;
+import org.broadinstitute.gatk.utils.text.XReadLines;
+
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.util.*;
+
+
+/**
+ * SampleUtils is a static class (no instantiation allowed!) with some utility methods for getting samples
+ * quality scores.
+ *
+ * @author ebanks
+ */
+public class SampleUtils {
+    /**
+     * Private constructor.  No instantiating this class!
+     */
+    private SampleUtils() {}
+
+    /**
+     * Pull out the samples from a SAMFileHeader;
+     * note that we use a TreeSet so that they are sorted
+     *
+     * @param header  the sam file header
+     * @return list of strings representing the sample names
+     */
+    public static Set<String> getSAMFileSamples(final SAMFileHeader header) {
+        // get all of the unique sample names
+        final Set<String> samples = new TreeSet<String>();
+        List<SAMReadGroupRecord> readGroups = header.getReadGroups();
+        for ( SAMReadGroupRecord readGroup : readGroups )
+            samples.add(readGroup.getSample());
+        return samples;
+    }
+
+
+    /**
+     * Same as @link getSAMFileSamples but gets all of the samples
+     * in the SAM files loaded by the engine
+     *
+     * @param engine engine
+     * @return samples
+     */
+    public static Set<String> getSAMFileSamples(GenomeAnalysisEngine engine) {
+        return SampleUtils.getSAMFileSamples(engine.getSAMFileHeader());
+    }
+
+    /**
+     * Gets all of the unique sample names from all VCF rods input by the user
+     *
+     * @param toolkit    GATK engine
+     *
+     * @return the set of unique samples
+     */
+    public static Set<String> getUniqueSamplesFromRods(GenomeAnalysisEngine toolkit) {
+        return getUniqueSamplesFromRods(toolkit, null);
+    }
+
+    /**
+     * Gets all of the unique sample names from the set of provided VCF rod names input by the user
+     *
+     * @param toolkit    GATK engine
+     * @param rodNames   list of rods to use; if null, uses all VCF rods
+     *
+     * @return the set of unique samples
+     */
+    public static Set<String> getUniqueSamplesFromRods(GenomeAnalysisEngine toolkit, Collection<String> rodNames) {
+        Set<String> samples = new LinkedHashSet<>();
+
+        for ( VCFHeader header : GATKVCFUtils.getVCFHeadersFromRods(toolkit, rodNames).values() )
+            samples.addAll(header.getGenotypeSamples());
+
+        return samples;
+    }
+
+    public static Set<String> getRodNamesWithVCFHeader(GenomeAnalysisEngine toolkit, Collection<String> rodNames) {
+        return GATKVCFUtils.getVCFHeadersFromRods(toolkit, rodNames).keySet();
+    }
+
+    public static Set<String> getSampleListWithVCFHeader(GenomeAnalysisEngine toolkit, Collection<String> rodNames) {
+        return getSampleList(GATKVCFUtils.getVCFHeadersFromRods(toolkit, rodNames));
+    }
+
+    public static Set<String> getSampleList(Map<String, VCFHeader> headers) {
+        return getSampleList(headers, GATKVariantContextUtils.GenotypeMergeType.PRIORITIZE);
+    }
+
+    public static Set<String> getSampleList(Map<String, VCFHeader> headers, GATKVariantContextUtils.GenotypeMergeType mergeOption) {
+        Set<String> samples = new TreeSet<String>();
+        for ( Map.Entry<String, VCFHeader> val : headers.entrySet() ) {
+            VCFHeader header = val.getValue();
+            for ( String sample : header.getGenotypeSamples() ) {
+                samples.add(GATKVariantContextUtils.mergedSampleName(val.getKey(), sample, mergeOption == GATKVariantContextUtils.GenotypeMergeType.UNIQUIFY));
+            }
+        }
+
+        return samples;
+    }
+
+
+    /**
+     *
+     * @param VCF_Headers
+     * @return false if there are names duplication between the samples names in the VCF headers
+     */
+    public static boolean verifyUniqueSamplesNames(Map<String, VCFHeader> VCF_Headers) {
+        Set<String> samples = new HashSet<String>();
+        for ( Map.Entry<String, VCFHeader> val : VCF_Headers.entrySet() ) {
+            VCFHeader header = val.getValue();
+            for ( String sample : header.getGenotypeSamples() ) {
+                if (samples.contains(sample)){
+
+                    return false;
+                }
+                samples.add(sample);
+            }
+        }
+
+        return true;
+    }
+
+    /**
+     * Gets the sample names from all VCF rods input by the user and uniquifies them if there is overlap
+     * (e.g. sampleX.1, sampleX.2, ...)
+     * When finished, samples contains the uniquified sample names and rodNamesToSampleNames contains a mapping
+     * from rod/sample pairs to the new uniquified names
+     *
+     * @param toolkit    GATK engine
+     * @param samples    set to store the sample names
+     * @param rodNamesToSampleNames mapping of rod/sample pairs to new uniquified sample names
+     */
+    public static void getUniquifiedSamplesFromRods(GenomeAnalysisEngine toolkit, Set<String> samples, Map<Pair<String, String>, String> rodNamesToSampleNames) {
+
+        // keep a map of sample name to occurrences encountered
+        HashMap<String, Integer> sampleOverlapMap = new HashMap<String, Integer>();
+
+        // iterate to get all of the sample names
+
+        for ( Map.Entry<String, VCFHeader> pair : GATKVCFUtils.getVCFHeadersFromRods(toolkit).entrySet() ) {
+            for ( String sample : pair.getValue().getGenotypeSamples() )
+                addUniqueSample(samples, sampleOverlapMap, rodNamesToSampleNames, sample, pair.getKey());
+        }
+    }
+
+    private static void addUniqueSample(Set<String> samples, Map<String, Integer> sampleOverlapMap, Map<Pair<String, String>, String> rodNamesToSampleNames, String newSample, String rodName) {
+
+        // how many occurrences have we seen so far?
+        Integer occurrences = sampleOverlapMap.get(newSample);
+
+        // if this is the first one, just add it to the list of samples
+        if ( occurrences == null ) {
+            samples.add(newSample);
+            rodNamesToSampleNames.put(new Pair<String, String>(rodName, newSample), newSample);
+            sampleOverlapMap.put(newSample, 1);
+        }
+
+        // if it's already been seen multiple times, give it a unique suffix and increment the value
+        else if ( occurrences >= 2 ) {
+            String uniqueName = newSample + "." + rodName;
+            samples.add(uniqueName);
+            rodNamesToSampleNames.put(new Pair<String, String>(rodName, newSample), uniqueName);
+            sampleOverlapMap.put(newSample, occurrences + 1);
+        }
+
+        // if this is the second occurrence of the sample name, uniquify both of them
+        else { // occurrences == 2
+
+            // remove the 1st occurrence, uniquify it, and add it back
+            samples.remove(newSample);
+            String uniqueName1 = null;
+            for ( Map.Entry<Pair<String, String>, String> entry : rodNamesToSampleNames.entrySet() ) {
+                if ( entry.getValue().equals(newSample) ) {
+                    uniqueName1 = newSample + "." + entry.getKey().first;
+                    entry.setValue(uniqueName1);
+                    break;
+                }
+            }
+            samples.add(uniqueName1);
+
+            // add the second one
+            String uniqueName2 = newSample + "." + rodName;
+            samples.add(uniqueName2);
+            rodNamesToSampleNames.put(new Pair<String, String>(rodName, newSample), uniqueName2);
+
+            sampleOverlapMap.put(newSample, 2);
+        }
+
+    }
+
+    /**
+     * Returns a new set of samples, containing a final list of samples expanded from sampleArgs
+     *
+     * Each element E of sampleArgs can either be a literal sample name or a file.  For each E,
+     * we try to read a file named E from disk, and if possible all lines from that file are expanded
+     * into unique sample names.
+     *
+     * @param sampleArgs args
+     * @return samples
+     */
+    public static Set<String> getSamplesFromCommandLineInput(Collection<String> sampleArgs) {
+        if (sampleArgs != null) {
+            return ListFileUtils.unpackSet(sampleArgs);
+        }
+
+        return new HashSet<String>();
+    }
+
+    public static Set<String> getSamplesFromCommandLineInput(Collection<String> vcfSamples, Collection<String> sampleExpressions) {
+        Set<String> samples = ListFileUtils.unpackSet(vcfSamples);
+        if (sampleExpressions == null) {
+            return samples;
+        } else {
+            return ListFileUtils.includeMatching(samples, sampleExpressions, false);
+        }
+    }
+
+    /**
+     * Given a collection of samples and a collection of regular expressions, generates the set of samples that match each expression
+     * @param originalSamples list of samples to select samples from
+     * @param sampleExpressions list of expressions to use for matching samples
+     * @return the set of samples from originalSamples that satisfy at least one of the expressions in sampleExpressions
+     */
+    public static Collection<String> matchSamplesExpressions (Collection<String> originalSamples, Collection<String> sampleExpressions) {
+        // Now, check the expressions that weren't used in the previous step, and use them as if they're regular expressions
+        Set<String> samples = new HashSet<String>();
+        if (sampleExpressions != null) {
+            samples.addAll(ListFileUtils.includeMatching(originalSamples, sampleExpressions, false));
+        }
+        return samples;
+    }
+
+    /**
+     * Given a list of files with sample names it reads all files and creates a list of unique samples from all these files.
+     * @param files list of files with sample names in
+     * @return a collection of unique samples from all files
+     */
+    public static Collection<String> getSamplesFromFiles (Collection<File> files) {
+        Set<String> samplesFromFiles = new HashSet<String>();
+        if (files != null) {
+            for (File file : files) {
+                try {
+                    XReadLines reader = new XReadLines(file);
+                    List<String> lines = reader.readLines();
+                    for (String line : lines) {
+                        samplesFromFiles.add(line);
+                    }
+                } catch (FileNotFoundException e) {
+                    throw new UserException.CouldNotReadInputFile(file, e);
+                }
+            }
+        }
+        return samplesFromFiles;
+    }
+}
\ No newline at end of file
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/SequenceDictionaryUtils.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/SequenceDictionaryUtils.java
new file mode 100644
index 0000000..d869037
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/SequenceDictionaryUtils.java
@@ -0,0 +1,527 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.utils;
+
+import htsjdk.samtools.SAMSequenceDictionary;
+import htsjdk.samtools.SAMSequenceRecord;
+import org.apache.log4j.Logger;
+import org.broadinstitute.gatk.engine.arguments.ValidationExclusion;
+import org.broadinstitute.gatk.utils.exceptions.ReviewedGATKException;
+import org.broadinstitute.gatk.utils.exceptions.UserException;
+
+import java.util.*;
+
+/**
+ * Created by IntelliJ IDEA.
+ * User: depristo
+ * Date: Sep 10, 2010
+ * Time: 1:56:24 PM
+ *
+ * A series of utility functions that enable the GATK to compare two sequence dictionaries -- from the reference,
+ * from BAMs, or from RODs -- for consistency.  The system supports two basic modes: get an enum state that
+ * describes at a high level the consistency between two dictionaries, or a validateDictionaries that will
+ * blow up with a UserException if the dicts are too incompatible.
+ *
+ * Dictionaries are tested for contig name overlaps, consistency in ordering in these overlap set, and length,
+ * if available.  Examines the Engine arguments to decided if the -U option to allow danger seq dict inconsistency
+ * is enabled before it blows up.
+ */
+public class SequenceDictionaryUtils {
+    //
+    // for detecting lexicographically sorted human references
+    //
+    private static final boolean ENABLE_LEXICOGRAPHIC_REQUIREMENT_FOR_HUMAN = true;
+
+    // hg18
+    protected static final SAMSequenceRecord CHR1_HG18 = new SAMSequenceRecord("chr1", 247249719);
+    protected static final SAMSequenceRecord CHR2_HG18 = new SAMSequenceRecord("chr2", 242951149);
+    protected static final SAMSequenceRecord CHR10_HG18 = new SAMSequenceRecord("chr10", 135374737);
+
+    // hg19
+    protected static final SAMSequenceRecord CHR1_HG19 = new SAMSequenceRecord("chr1", 249250621);
+    protected static final SAMSequenceRecord CHR2_HG19 = new SAMSequenceRecord("chr2", 243199373);
+    protected static final SAMSequenceRecord CHR10_HG19 = new SAMSequenceRecord("chr10", 135534747);
+
+    // b36
+    protected static final SAMSequenceRecord CHR1_B36 = new SAMSequenceRecord("1", 247249719);
+    protected static final SAMSequenceRecord CHR2_B36 = new SAMSequenceRecord("2", 242951149);
+    protected static final SAMSequenceRecord CHR10_B36 = new SAMSequenceRecord("10", 135374737);
+
+    // b37
+    protected static final SAMSequenceRecord CHR1_B37 = new SAMSequenceRecord("1", 249250621);
+    protected static final SAMSequenceRecord CHR2_B37 = new SAMSequenceRecord("2", 243199373);
+    protected static final SAMSequenceRecord CHR10_B37 = new SAMSequenceRecord("10", 135534747);
+
+
+    public enum SequenceDictionaryCompatibility {
+        IDENTICAL,                      // the dictionaries are identical
+        COMMON_SUBSET,                  // there exists a common subset of equivalent contigs
+        NO_COMMON_CONTIGS,              // no overlap between dictionaries
+        UNEQUAL_COMMON_CONTIGS,         // common subset has contigs that have the same name but different lengths
+        NON_CANONICAL_HUMAN_ORDER,      // human reference detected but the order of the contigs is non-standard (lexicographic, for examine)
+        OUT_OF_ORDER,                   // the two dictionaries overlap but the overlapping contigs occur in different
+                                        // orders with respect to each other
+        DIFFERENT_INDICES               // the two dictionaries overlap and the overlapping contigs occur in the same
+                                        // order with respect to each other, but one or more of them have different
+                                        // indices in the two dictionaries. Eg., { chrM, chr1, chr2 } vs. { chr1, chr2 }
+    }
+
+    /**
+     * @param validationExclusion exclusions to validation
+     * @return Returns true if the engine is in tolerant mode and we'll let through dangerous but not fatal dictionary inconsistency
+     */
+    private static boolean allowNonFatalIncompabilities(ValidationExclusion.TYPE validationExclusion) {
+        return ( validationExclusion == ValidationExclusion.TYPE.ALLOW_SEQ_DICT_INCOMPATIBILITY ||
+                        validationExclusion == ValidationExclusion.TYPE.ALL );
+    }
+
+    /**
+     * Tests for compatibility between two sequence dictionaries.  If the dictionaries are incompatible, then
+     * UserExceptions are thrown with detailed error messages.  If the engine is in permissive mode, then
+     * logger warnings are generated instead.
+     *
+     * @param logger for warnings
+     * @param validationExclusion exclusions to validation
+     * @param name1 name associated with dict1
+     * @param dict1 the sequence dictionary dict1
+     * @param name2 name associated with dict2
+     * @param dict2 the sequence dictionary dict2
+     * @param isReadsToReferenceComparison true if one of the dictionaries comes from a reads data source (eg., a BAM),
+     *                                     and the other from a reference data source
+     * @param intervals the user-specified genomic intervals: only required when isReadsToReferenceComparison is true,
+     *                  otherwise can be null
+     */
+    public static void validateDictionaries( final Logger logger,
+                                             final ValidationExclusion.TYPE validationExclusion,
+                                             final String name1,
+                                             final SAMSequenceDictionary dict1,
+                                             final String name2,
+                                             final SAMSequenceDictionary dict2,
+                                             final boolean isReadsToReferenceComparison,
+                                             final GenomeLocSortedSet intervals ) {
+
+        final SequenceDictionaryCompatibility type = compareDictionaries(dict1, dict2);
+
+        switch ( type ) {
+            case IDENTICAL:
+                return;
+            case COMMON_SUBSET:
+                 return;
+            case NO_COMMON_CONTIGS:
+                throw new UserException.IncompatibleSequenceDictionaries("No overlapping contigs found", name1, dict1, name2, dict2);
+
+            case UNEQUAL_COMMON_CONTIGS: {
+                List<SAMSequenceRecord> x = findDisequalCommonContigs(getCommonContigsByName(dict1, dict2), dict1, dict2);
+                SAMSequenceRecord elt1 = x.get(0);
+                SAMSequenceRecord elt2 = x.get(1);
+
+                // todo -- replace with toString when SAMSequenceRecord has a nice toString routine
+                UserException ex = new UserException.IncompatibleSequenceDictionaries(String.format("Found contigs with the same name but different lengths:\n  contig %s = %s / %d\n  contig %s = %s / %d",
+                        name1, elt1.getSequenceName(), elt1.getSequenceLength(),
+                        name2, elt2.getSequenceName(), elt2.getSequenceLength()),
+                        name1, dict1, name2, dict2);
+
+                if ( allowNonFatalIncompabilities(validationExclusion) )
+                    logger.warn(ex.getMessage());
+                else
+                    throw ex;
+                break;
+            }
+
+            case NON_CANONICAL_HUMAN_ORDER: {
+                UserException ex;
+                if ( nonCanonicalHumanContigOrder(dict1) )
+                    ex = new UserException.LexicographicallySortedSequenceDictionary(name1, dict1);
+                else
+                    ex = new UserException.LexicographicallySortedSequenceDictionary(name2, dict2);
+                
+                if ( allowNonFatalIncompabilities(validationExclusion) )
+                    logger.warn(ex.getMessage());
+                else
+                    throw ex;
+                break;
+            }
+
+            case OUT_OF_ORDER: {
+                UserException ex = new UserException.IncompatibleSequenceDictionaries("Relative ordering of overlapping contigs differs, which is unsafe", name1, dict1, name2, dict2);
+                if ( allowNonFatalIncompabilities(validationExclusion) )
+                    logger.warn(ex.getMessage());
+                else
+                    throw ex;
+                break;
+            }
+
+            case DIFFERENT_INDICES: {
+                // This is currently only known to be problematic when the index mismatch is between a bam and the
+                // reference AND when the user's intervals actually include one or more of the contigs that are
+                // indexed differently from the reference. In this case, the engine will fail to correctly serve
+                // up the reads from those contigs, so throw an exception unless unsafe operations are enabled.
+                if ( isReadsToReferenceComparison && intervals != null ) {
+
+                     final Set<String> misindexedContigs = findMisindexedContigsInIntervals(intervals, dict1, dict2);
+
+                     if ( ! misindexedContigs.isEmpty() ) {
+                         final String msg = String.format("The following contigs included in the intervals to process have " +
+                                                          "different indices in the sequence dictionaries for the reads vs. " +
+                                                          "the reference: %s.  As a result, the GATK engine will not correctly " +
+                                                          "process reads from these contigs. You should either fix the sequence " +
+                                                          "dictionaries for your reads so that these contigs have the same indices " +
+                                                          "as in the sequence dictionary for your reference, or exclude these contigs " +
+                                                          "from your intervals. This error can be disabled via -U %s, " +
+                                                          "however this is not recommended as the GATK engine will not behave correctly.",
+                                                          misindexedContigs, ValidationExclusion.TYPE.ALLOW_SEQ_DICT_INCOMPATIBILITY);
+                         final UserException ex = new UserException.IncompatibleSequenceDictionaries(msg, name1, dict1, name2, dict2);
+
+                         if ( allowNonFatalIncompabilities(validationExclusion) )
+                             logger.warn(ex.getMessage());
+                         else
+                             throw ex;
+                     }
+                }
+                break;
+            }
+
+            default:
+                throw new ReviewedGATKException("Unexpected SequenceDictionaryComparison type: " + type);
+        }
+    }
+
+    /**
+     * Workhorse routine that takes two dictionaries and returns their compatibility.
+     *
+     * @param dict1 first sequence dictionary
+     * @param dict2 second sequence dictionary
+     * @return A SequenceDictionaryCompatibility enum value describing the compatibility of the two dictionaries
+     */
+    public static SequenceDictionaryCompatibility compareDictionaries( final SAMSequenceDictionary dict1, final SAMSequenceDictionary dict2) {
+        if ( nonCanonicalHumanContigOrder(dict1) || nonCanonicalHumanContigOrder(dict2) )
+            return SequenceDictionaryCompatibility.NON_CANONICAL_HUMAN_ORDER;
+
+        final Set<String> commonContigs = getCommonContigsByName(dict1, dict2);
+
+        if (commonContigs.size() == 0)
+            return SequenceDictionaryCompatibility.NO_COMMON_CONTIGS;
+        else if ( ! commonContigsHaveSameLengths(commonContigs, dict1, dict2) )
+            return SequenceDictionaryCompatibility.UNEQUAL_COMMON_CONTIGS;
+        else if ( ! commonContigsAreInSameRelativeOrder(commonContigs, dict1, dict2) )
+            return SequenceDictionaryCompatibility.OUT_OF_ORDER;
+        else if ( commonContigs.size() == dict1.size() && commonContigs.size() == dict2.size() )
+            return SequenceDictionaryCompatibility.IDENTICAL;
+        else if ( ! commonContigsAreAtSameIndices(commonContigs, dict1, dict2) )
+            return SequenceDictionaryCompatibility.DIFFERENT_INDICES;
+        else {
+            return SequenceDictionaryCompatibility.COMMON_SUBSET;
+        }
+    }
+
+    /**
+     * Utility function that tests whether the commonContigs in both dicts are equivalent.  Equivalence means
+     * that the seq records have the same length, if both are non-zero.
+     *
+     * @param commonContigs
+     * @param dict1
+     * @param dict2
+     * @return true if all of the common contigs are equivalent
+     */
+    private static boolean commonContigsHaveSameLengths(Set<String> commonContigs, SAMSequenceDictionary dict1, SAMSequenceDictionary dict2) {
+        return findDisequalCommonContigs(commonContigs, dict1, dict2) == null;
+    }
+
+    /**
+     * Returns a List(x,y) that contains two disequal sequence records among the common contigs in both dicts.  Returns
+     * null if all common contigs are equivalent
+     *
+     * @param commonContigs
+     * @param dict1
+     * @param dict2
+     * @return
+     */
+    private static List<SAMSequenceRecord> findDisequalCommonContigs(Set<String> commonContigs, SAMSequenceDictionary dict1, SAMSequenceDictionary dict2) {
+        for ( String name : commonContigs ) {
+            SAMSequenceRecord elt1 = dict1.getSequence(name);
+            SAMSequenceRecord elt2 = dict2.getSequence(name);
+            if ( ! sequenceRecordsAreEquivalent(elt1, elt2) )
+                return Arrays.asList(elt1,elt2);
+        }
+
+        return null;
+    }
+
+    /**
+     * Helper routine that returns two sequence records are equivalent, defined as having the same name and
+     * lengths, if both are non-zero
+     *
+     * @param me
+     * @param that
+     * @return
+     */
+    private static boolean sequenceRecordsAreEquivalent(final SAMSequenceRecord me, final SAMSequenceRecord that) {
+        if (me == that) return true;
+        if (that == null) return false;
+
+        if (me.getSequenceLength() != 0 && that.getSequenceLength() != 0 && me.getSequenceLength() != that.getSequenceLength())
+            return false;
+
+            // todo -- reenable if we want to be really strict here
+//        if (me.getExtendedAttribute(SAMSequenceRecord.MD5_TAG) != null && that.getExtendedAttribute(SAMSequenceRecord.MD5_TAG) != null) {
+//            final BigInteger thisMd5 = new BigInteger((String)me.getExtendedAttribute(SAMSequenceRecord.MD5_TAG), 16);
+//            final BigInteger thatMd5 = new BigInteger((String)that.getExtendedAttribute(SAMSequenceRecord.MD5_TAG), 16);
+//            if (!thisMd5.equals(thatMd5)) {
+//                return false;
+//            }
+//        }
+//        else {
+        if (me.getSequenceName() != that.getSequenceName())
+            return false; // Compare using == since we intern() the Strings
+//        }
+
+        return true;
+    }
+
+    /**
+     * A very simple (and naive) algorithm to determine (1) if the dict is a human reference (hg18/hg19) and if it's
+     * lexicographically sorted.  Works by matching lengths of the static chr1, chr10, and chr2, and then if these
+     * are all matched, requiring that the order be chr1, chr2, chr10.
+     *
+     * @param dict
+     * @return
+     */
+    private static boolean nonCanonicalHumanContigOrder(SAMSequenceDictionary dict) {
+        if ( ! ENABLE_LEXICOGRAPHIC_REQUIREMENT_FOR_HUMAN ) // if we don't want to enable this test, just return false
+            return false;
+
+        SAMSequenceRecord chr1 = null, chr2 = null, chr10 = null;
+
+        for ( SAMSequenceRecord elt : dict.getSequences() ) {
+            if ( isHumanSeqRecord(elt, CHR1_HG18, CHR1_HG19 ) ) chr1 = elt;
+            if ( isHumanSeqRecord(elt, CHR2_HG18, CHR2_HG19 ) ) chr2 = elt;
+            if ( isHumanSeqRecord(elt, CHR10_HG18, CHR10_HG19 ) ) chr10 = elt;
+        }
+
+        if ( chr1 != null && chr2 != null && chr10 != null) {
+            // we found them all
+            return ! ( chr1.getSequenceIndex() < chr2.getSequenceIndex() && chr2.getSequenceIndex() < chr10.getSequenceIndex() );
+        } else {
+            return false;
+        }
+    }
+
+    /**
+     * Trivial helper that returns true if elt has the same length as rec1 or rec2
+     * @param elt record to test
+     * @param rec1 first record to test for length equivalence
+     * @param rec2 first record to test for length equivalence
+     * @return true if elt has the same length as either rec1 or rec2
+     */
+    private static boolean isHumanSeqRecord(SAMSequenceRecord elt, SAMSequenceRecord rec1, SAMSequenceRecord rec2 ) {
+        return elt.getSequenceLength() == rec1.getSequenceLength() || elt.getSequenceLength() == rec2.getSequenceLength();
+    }
+
+    /**
+     * Returns true if the common contigs in dict1 and dict2 are in the same relative order, without regard to
+     * absolute index position. This is accomplished by getting the common contigs in both dictionaries, sorting
+     * these according to their indices, and then walking through the sorted list to ensure that each ordered contig
+     * is equivalent
+     *
+     * @param commonContigs names of the contigs common to both dictionaries
+     * @param dict1 first SAMSequenceDictionary
+     * @param dict2 second SAMSequenceDictionary
+     * @return true if the common contigs occur in the same relative order in both dict1 and dict2, otherwise false
+     */
+    private static boolean commonContigsAreInSameRelativeOrder(Set<String> commonContigs, SAMSequenceDictionary dict1, SAMSequenceDictionary dict2) {
+        List<SAMSequenceRecord> list1 = sortSequenceListByIndex(getSequencesOfName(commonContigs, dict1));
+        List<SAMSequenceRecord> list2 = sortSequenceListByIndex(getSequencesOfName(commonContigs, dict2));
+
+        for ( int i = 0; i < list1.size(); i++ ) {
+            SAMSequenceRecord elt1 = list1.get(i);
+            SAMSequenceRecord elt2 = list2.get(i);
+            if ( ! elt1.getSequenceName().equals(elt2.getSequenceName()) )
+                return false;
+        }
+
+        return true;
+    }
+
+    /**
+     * Gets the subset of SAMSequenceRecords in commonContigs in dict
+     *
+     * @param commonContigs
+     * @param dict
+     * @return
+     */
+    private static List<SAMSequenceRecord> getSequencesOfName(Set<String> commonContigs, SAMSequenceDictionary dict) {
+        List<SAMSequenceRecord> l = new ArrayList<SAMSequenceRecord>(commonContigs.size());
+        for ( String name : commonContigs ) {
+            l.add(dict.getSequence(name) );
+        }
+
+        return l;
+    }
+
+    /**
+     * Compares sequence records by their order
+     */
+    private static class CompareSequenceRecordsByIndex implements Comparator<SAMSequenceRecord> {
+        public int compare(SAMSequenceRecord x, SAMSequenceRecord y) {
+            return Integer.valueOf(x.getSequenceIndex()).compareTo(y.getSequenceIndex());
+        }
+    }
+
+    /**
+     * Returns a sorted list of SAMSequenceRecords sorted by their indices.  Note that the
+     * list is modified in place, so the returned list is == to the unsorted list.
+     *
+     * @param unsorted
+     * @return
+     */
+    private static List<SAMSequenceRecord> sortSequenceListByIndex(List<SAMSequenceRecord> unsorted) {
+        Collections.sort(unsorted, new CompareSequenceRecordsByIndex());
+        return unsorted;
+    }
+
+    /**
+     * Checks whether the common contigs in the given sequence dictionaries occur at the same indices
+     * in both dictionaries
+     *
+     * @param commonContigs Set of names of the contigs that occur in both dictionaries
+     * @param dict1 first sequence dictionary
+     * @param dict2 second sequence dictionary
+     * @return true if the contigs common to dict1 and dict2 occur at the same indices in both dictionaries,
+     *         otherwise false
+     */
+    private static boolean commonContigsAreAtSameIndices( final Set<String> commonContigs, final SAMSequenceDictionary dict1, final SAMSequenceDictionary dict2 ) {
+        for ( String commonContig : commonContigs ) {
+            SAMSequenceRecord dict1Record = dict1.getSequence(commonContig);
+            SAMSequenceRecord dict2Record = dict2.getSequence(commonContig);
+
+            // Each common contig must have the same index in both dictionaries
+            if ( dict1Record.getSequenceIndex() != dict2Record.getSequenceIndex() ) {
+                return false;
+            }
+        }
+
+        return true;
+    }
+
+    /**
+     * Gets the set of names of the contigs found in both sequence dictionaries that have different indices
+     * in the two dictionaries.
+     *
+     * @param commonContigs Set of names of the contigs common to both dictionaries
+     * @param dict1 first sequence dictionary
+     * @param dict2 second sequence dictionary
+     * @return a Set containing the names of the common contigs indexed differently in dict1 vs. dict2,
+     *         or an empty Set if there are no such contigs
+     */
+    private static Set<String> getDifferentlyIndexedCommonContigs( final Set<String> commonContigs,
+                                                                   final SAMSequenceDictionary dict1,
+                                                                   final SAMSequenceDictionary dict2 ) {
+
+        final Set<String> differentlyIndexedCommonContigs = new LinkedHashSet<String>(Utils.optimumHashSize(commonContigs.size()));
+
+        for ( String commonContig : commonContigs ) {
+            if ( dict1.getSequence(commonContig).getSequenceIndex() != dict2.getSequence(commonContig).getSequenceIndex() ) {
+                differentlyIndexedCommonContigs.add(commonContig);
+            }
+        }
+
+        return differentlyIndexedCommonContigs;
+    }
+
+    /**
+     * Finds the names of any contigs indexed differently in the two sequence dictionaries that also
+     * occur in the provided set of intervals.
+     *
+     * @param intervals GenomeLocSortedSet containing the intervals to check
+     * @param dict1 first sequence dictionary
+     * @param dict2 second sequence dictionary
+     * @return a Set of the names of the contigs indexed differently in dict1 vs dict2 that also
+     *         occur in the provided intervals, or an empty Set if there are no such contigs
+     */
+    private static Set<String> findMisindexedContigsInIntervals( final GenomeLocSortedSet intervals,
+                                                                 final SAMSequenceDictionary dict1,
+                                                                 final SAMSequenceDictionary dict2 ) {
+
+        final Set<String> differentlyIndexedCommonContigs = getDifferentlyIndexedCommonContigs(getCommonContigsByName(dict1, dict2), dict1, dict2);
+        final Set<String> misindexedContigsInIntervals = new LinkedHashSet<String>(Utils.optimumHashSize(differentlyIndexedCommonContigs.size()));
+
+        // We know differentlyIndexedCommonContigs is a HashSet, so this loop is O(intervals)
+        for ( GenomeLoc interval : intervals ) {
+            if ( differentlyIndexedCommonContigs.contains(interval.getContig()) ) {
+                misindexedContigsInIntervals.add(interval.getContig());
+            }
+        }
+
+        return misindexedContigsInIntervals;
+    }
+
+    /**
+     * Returns the set of contig names found in both dicts.
+     * @param dict1
+     * @param dict2
+     * @return
+     */
+    public static Set<String> getCommonContigsByName(SAMSequenceDictionary dict1, SAMSequenceDictionary dict2) {
+        Set<String> intersectingSequenceNames = getContigNames(dict1);
+        intersectingSequenceNames.retainAll(getContigNames(dict2));
+        return intersectingSequenceNames;
+    }
+
+    public static Set<String> getContigNames(SAMSequenceDictionary dict) {
+        Set<String> contigNames = new HashSet<String>(Utils.optimumHashSize(dict.size()));
+        for (SAMSequenceRecord dictionaryEntry : dict.getSequences())
+            contigNames.add(dictionaryEntry.getSequenceName());
+        return contigNames;
+    }
+
+    /**
+     * Returns a compact String representation of the sequence dictionary it's passed
+     *
+     * The format of the returned String is:
+     * [ contig1Name(length: contig1Length) contig2Name(length: contig2Length) ... ]
+     *
+     * @param dict a non-null SAMSequenceDictionary
+     * @return A String containing all of the contig names and lengths from the sequence dictionary it's passed
+     */
+    public static String getDictionaryAsString( final SAMSequenceDictionary dict ) {
+        if ( dict == null ) {
+            throw new IllegalArgumentException("Sequence dictionary must be non-null");
+        }
+
+        StringBuilder s = new StringBuilder("[ ");
+
+        for ( SAMSequenceRecord dictionaryEntry : dict.getSequences() ) {
+            s.append(dictionaryEntry.getSequenceName());
+            s.append("(length:");
+            s.append(dictionaryEntry.getSequenceLength());
+            s.append(") ");
+        }
+
+        s.append("]");
+
+        return s.toString();
+    }
+}
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/UnvalidatingGenomeLoc.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/UnvalidatingGenomeLoc.java
new file mode 100644
index 0000000..2c3d24b
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/UnvalidatingGenomeLoc.java
@@ -0,0 +1,50 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.utils;
+
+import com.google.java.contract.Requires;
+
+/**
+ * GenomeLocs are very useful objects to keep track of genomic locations and perform set operations
+ * with them.
+ *
+ * However, GenomeLocs are bound to strict validation through the GenomeLocParser and cannot
+ * be created easily for small tasks that do not require the rigors of the GenomeLocParser validation
+ *
+ * UnvalidatingGenomeLoc is a simple utility to create GenomeLocs without going through the parser.
+ *
+ * WARNING: SHOULD BE USED ONLY BY EXPERT USERS WHO KNOW WHAT THEY ARE DOING!
+ *
+ * User: carneiro
+ * Date: 10/16/12
+ * Time: 2:07 PM
+ */
+public class UnvalidatingGenomeLoc extends GenomeLoc {
+
+    public UnvalidatingGenomeLoc(String contigName, int contigIndex, int start, int stop) {
+        super(contigName, contigIndex, start, stop);
+    }
+}
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/Utils.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/Utils.java
new file mode 100644
index 0000000..d664ef6
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/Utils.java
@@ -0,0 +1,1186 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.utils;
+
+import com.google.java.contract.Ensures;
+import com.google.java.contract.Requires;
+import htsjdk.samtools.SAMFileHeader;
+import htsjdk.samtools.SAMProgramRecord;
+import org.apache.log4j.Logger;
+import org.broadinstitute.gatk.engine.GenomeAnalysisEngine;
+import org.broadinstitute.gatk.engine.io.GATKSAMFileWriter;
+import org.broadinstitute.gatk.utils.text.TextFormattingUtils;
+
+import java.lang.reflect.Array;
+import java.math.BigInteger;
+import java.net.InetAddress;
+import java.security.MessageDigest;
+import java.security.NoSuchAlgorithmException;
+import java.util.*;
+
+/**
+ * Created by IntelliJ IDEA.
+ * User: depristo
+ * Date: Feb 24, 2009
+ * Time: 10:12:31 AM
+ * To change this template use File | Settings | File Templates.
+ */
+public class Utils {
+    /** our log, which we want to capture anything from this class */
+    private static Logger logger = Logger.getLogger(Utils.class);
+
+    public static final float JAVA_DEFAULT_HASH_LOAD_FACTOR = 0.75f;
+
+    /**
+     * Boolean xor operation.  Only true if x != y.
+     *
+     * @param x a boolean
+     * @param y a boolean
+     * @return true if x != y
+     */
+    public static boolean xor(final boolean x, final boolean y) {
+        return x != y;
+    }
+
+    /**
+     * Calculates the optimum initial size for a hash table given the maximum number
+     * of elements it will need to hold. The optimum size is the smallest size that
+     * is guaranteed not to result in any rehash/table-resize operations.
+     *
+     * @param maxElements  The maximum number of elements you expect the hash table
+     *                     will need to hold
+     * @return             The optimum initial size for the table, given maxElements
+     */
+    public static int optimumHashSize ( int maxElements ) {
+        return (int)(maxElements / JAVA_DEFAULT_HASH_LOAD_FACTOR) + 2;
+    }
+
+    /**
+     * Compares two objects, either of which might be null.
+     *
+     * @param lhs One object to compare.
+     * @param rhs The other object to compare.
+     *
+     * @return True if the two objects are equal, false otherwise.
+     */
+    public static boolean equals(Object lhs, Object rhs) {
+        return lhs == null && rhs == null || lhs != null && lhs.equals(rhs);
+    }
+
+    public static <T> List<T> cons(final T elt, final List<T> l) {
+        List<T> l2 = new ArrayList<T>();
+        l2.add(elt);
+        if (l != null) l2.addAll(l);
+        return l2;
+    }
+
+    public static void warnUser(final String msg) {
+        warnUser(logger, msg);
+    }
+    
+    public static void warnUser(final Logger logger, final String msg) {
+        logger.warn(String.format("********************************************************************************"));
+        logger.warn(String.format("* WARNING:"));
+        logger.warn(String.format("*"));
+        prettyPrintWarningMessage(logger, msg);
+        logger.warn(String.format("********************************************************************************"));
+    }
+
+    /**
+     * pretty print the warning message supplied
+     *
+     * @param logger logger for the message
+     * @param message the message
+     */
+    private static void prettyPrintWarningMessage(Logger logger, String message) {
+        StringBuilder builder = new StringBuilder(message);
+        while (builder.length() > 70) {
+            int space = builder.lastIndexOf(" ", 70);
+            if (space <= 0) space = 70;
+            logger.warn(String.format("* %s", builder.substring(0, space)));
+            builder.delete(0, space + 1);
+        }
+        logger.warn(String.format("* %s", builder));
+    }
+
+    /**
+     * join the key value pairs of a map into one string, i.e. myMap = [A->1,B->2,C->3] with a call of:
+     * joinMap("-","*",myMap) -> returns A-1*B-2*C-3
+     *
+     * Be forewarned, if you're not using a map that is aware of the ordering (i.e. HashMap instead of LinkedHashMap)
+     * the ordering of the string you get back might not be what you expect! (i.e. C-3*A-1*B-2 vrs A-1*B-2*C-3)
+     *
+     * @param keyValueSeperator the string to seperate the key-value pairs
+     * @param recordSeperator the string to use to seperate each key-value pair from other key-value pairs
+     * @param map the map to draw from
+     * @param <L> the map's key type
+     * @param <R> the map's value type
+     * @return a string representing the joined map
+     */
+    public static <L,R> String joinMap(String keyValueSeperator, String recordSeperator, Map<L,R> map) {
+        if (map.size() < 1) { return null; }
+        String joinedKeyValues[] = new String[map.size()];
+        int index = 0;
+        for (L key : map.keySet()) {
+           joinedKeyValues[index++] = String.format("%s%s%s",key.toString(),keyValueSeperator,map.get(key).toString());
+        }
+        return join(recordSeperator,joinedKeyValues);
+    }
+
+    /**
+     * Splits a String using indexOf instead of regex to speed things up.
+     *
+     * @param str the string to split.
+     * @param delimiter the delimiter used to split the string.
+     * @return an array of tokens.
+     */
+    public static ArrayList<String> split(String str, String delimiter) {
+        return split(str, delimiter, 10);
+    }
+
+    /**
+     * Splits a String using indexOf instead of regex to speed things up.
+     *
+     * @param str the string to split.
+     * @param delimiter the delimiter used to split the string.
+     * @param expectedNumTokens The number of tokens expected. This is used to initialize the ArrayList.
+     * @return an array of tokens.
+     */
+    public static ArrayList<String> split(String str, String delimiter, int expectedNumTokens) {
+        final ArrayList<String> result =  new ArrayList<String>(expectedNumTokens);
+
+        int delimiterIdx = -1;
+        do {
+            final int tokenStartIdx = delimiterIdx + 1;
+            delimiterIdx = str.indexOf(delimiter, tokenStartIdx);
+            final String token = (delimiterIdx != -1 ? str.substring(tokenStartIdx, delimiterIdx) : str.substring(tokenStartIdx) );
+            result.add(token);
+        } while( delimiterIdx != -1 );
+
+        return result;
+    }
+
+
+    /**
+     * join an array of strings given a seperator
+     * @param separator the string to insert between each array element
+     * @param strings the array of strings
+     * @return a string, which is the joining of all array values with the separator
+     */
+    public static String join(String separator, String[] strings) {
+        return join(separator, strings, 0, strings.length);
+    }
+
+    public static String join(String separator, String[] strings, int start, int end) {
+        if ((end - start) == 0) {
+            return "";
+        }
+        StringBuilder ret = new StringBuilder(strings[start]);
+        for (int i = start + 1; i < end; ++i) {
+            ret.append(separator);
+            ret.append(strings[i]);
+        }
+        return ret.toString();
+    }
+
+    public static String join(String separator, int[] ints) {
+        if ( ints == null || ints.length == 0)
+            return "";
+        else {
+            StringBuilder ret = new StringBuilder();
+            ret.append(ints[0]);
+            for (int i = 1; i < ints.length; ++i) {
+                ret.append(separator);
+                ret.append(ints[i]);
+            }
+            return ret.toString();
+        }
+    }
+
+    /**
+     * Create a new list that contains the elements of left along with elements elts
+     * @param left a non-null list of elements
+     * @param elts a varargs vector for elts to append in order to left
+     * @return A newly allocated linked list containing left followed by elts
+     */
+    public static <T> List<T> append(final List<T> left, T ... elts) {
+        final List<T> l = new LinkedList<T>(left);
+        l.addAll(Arrays.asList(elts));
+        return l;
+    }
+
+    /**
+     * Returns a string of the values in joined by separator, such as A,B,C
+     *
+     * @param separator separator character
+     * @param doubles   the array with values
+     * @return a string with the values separated by the separator
+     */
+    public static String join(String separator, double[] doubles) {
+        if ( doubles == null || doubles.length == 0)
+            return "";
+        else {
+            StringBuilder ret = new StringBuilder();
+            ret.append(doubles[0]);
+            for (int i = 1; i < doubles.length; ++i) {
+                ret.append(separator);
+                ret.append(doubles[i]);
+            }
+            return ret.toString();
+        }
+    }
+
+    /**
+     * Returns a string of the form elt1.toString() [sep elt2.toString() ... sep elt.toString()] for a collection of
+     * elti objects (note there's no actual space between sep and the elti elements).  Returns
+     * "" if collection is empty.  If collection contains just elt, then returns elt.toString()
+     *
+     * @param separator the string to use to separate objects
+     * @param objects a collection of objects.  the element order is defined by the iterator over objects
+     * @param <T> the type of the objects
+     * @return a non-null string
+     */
+    public static <T> String join(final String separator, final Collection<T> objects) {
+        if (objects.isEmpty()) { // fast path for empty collection
+            return "";
+        } else {
+            final Iterator<T> iter = objects.iterator();
+            final T first = iter.next();
+
+            if ( ! iter.hasNext() ) // fast path for singleton collections
+                return first.toString();
+            else { // full path for 2+ collection that actually need a join
+                final StringBuilder ret = new StringBuilder(first.toString());
+                while(iter.hasNext()) {
+                    ret.append(separator);
+                    ret.append(iter.next().toString());
+                }
+                return ret.toString();
+            }
+        }
+    }
+
+    /**
+     * Returns a {@link List List<Integer>} representation of an primitive int array.
+     * @param values the primitive int array to represent.
+     * @return never code {@code null}. The returned list will be unmodifiable yet it will reflect changes in values in the original array yet
+     *   you cannot change the values
+     */
+    public static List<Integer> asList(final int ... values) {
+        if (values == null)
+            throw new IllegalArgumentException("the input array cannot be null");
+        return new AbstractList<Integer>() {
+
+            @Override
+            public Integer get(final int index) {
+                return values[index];
+            }
+
+            @Override
+            public int size() {
+                return values.length;
+            }
+        };
+    }
+
+    /**
+     * Returns a {@link List List<Double>} representation of an primitive double array.
+     * @param values the primitive int array to represent.
+     * @return never code {@code null}. The returned list will be unmodifiable yet it will reflect changes in values in the original array yet
+     *   you cannot change the values.
+     */
+    public static List<Double> asList(final double ... values) {
+        if (values == null)
+            throw new IllegalArgumentException("the input array cannot be null");
+        return new AbstractList<Double>() {
+
+            @Override
+            public Double get(final int index) {
+                return values[index];
+            }
+
+            @Override
+            public int size() {
+                return values.length;
+            }
+        };
+    }
+
+    public static <T> String join(final String separator, final T ... objects) {
+        return join(separator, Arrays.asList(objects));
+    }
+
+    /**
+     * Create a new string thats a n duplicate copies of s
+     * @param s the string to duplicate
+     * @param nCopies how many copies?
+     * @return a string
+     */
+    public static String dupString(final String s, int nCopies) {
+        if ( s == null || s.equals("") ) throw new IllegalArgumentException("Bad s " + s);
+        if ( nCopies < 0 ) throw new IllegalArgumentException("nCopies must be >= 0 but got " + nCopies);
+
+        final StringBuilder b = new StringBuilder();
+        for ( int i = 0; i < nCopies; i++ )
+            b.append(s);
+        return b.toString();
+    }
+
+    public static String dupString(char c, int nCopies) {
+        char[] chars = new char[nCopies];
+        Arrays.fill(chars, c);
+        return new String(chars);
+    }
+
+    public static byte[] dupBytes(byte b, int nCopies) {
+        byte[] bytes = new byte[nCopies];
+        Arrays.fill(bytes, b);
+        return bytes;
+    }
+
+    // trim a string for the given character (i.e. not just whitespace)
+    public static String trim(String str, char ch) {
+        char[] array = str.toCharArray();
+
+
+        int start = 0;
+        while ( start < array.length && array[start] == ch )
+            start++;
+
+        int end = array.length - 1;
+        while ( end > start && array[end] == ch )
+            end--;
+
+        return str.substring(start, end+1);
+    }
+
+    /**
+     * Splits expressions in command args by spaces and returns the array of expressions.
+     * Expressions may use single or double quotes to group any individual expression, but not both.
+     * @param args Arguments to parse.
+     * @return Parsed expressions.
+     */
+    public static String[] escapeExpressions(String args) {
+        // special case for ' and " so we can allow expressions
+        if (args.indexOf('\'') != -1)
+            return escapeExpressions(args, "'");
+        else if (args.indexOf('\"') != -1)
+            return escapeExpressions(args, "\"");
+        else
+            return args.trim().split(" +");
+    }
+
+    /**
+     * Splits expressions in command args by spaces and the supplied delimiter and returns the array of expressions.
+     * @param args Arguments to parse.
+     * @param delimiter Delimiter for grouping expressions.
+     * @return Parsed expressions.
+     */
+    private static String[] escapeExpressions(String args, String delimiter) {
+        String[] command = {};
+        String[] split = args.split(delimiter);
+        String arg;
+        for (int i = 0; i < split.length - 1; i += 2) {
+            arg = split[i].trim();
+            if (arg.length() > 0) // if the unescaped arg has a size
+                command = Utils.concatArrays(command, arg.split(" +"));
+            command = Utils.concatArrays(command, new String[]{split[i + 1]});
+        }
+        arg = split[split.length - 1].trim();
+        if (split.length % 2 == 1) // if the command ends with a delimiter
+            if (arg.length() > 0) // if the last unescaped arg has a size
+                command = Utils.concatArrays(command, arg.split(" +"));
+        return command;
+    }
+
+    /**
+     * Concatenates two String arrays.
+     * @param A First array.
+     * @param B Second array.
+     * @return Concatenation of A then B.
+     */
+    public static String[] concatArrays(String[] A, String[] B) {
+       String[] C = new String[A.length + B.length];
+       System.arraycopy(A, 0, C, 0, A.length);
+       System.arraycopy(B, 0, C, A.length, B.length);
+       return C;
+    }
+
+    /**
+     * Concatenates byte arrays
+     * @return a concat of all bytes in allBytes in order
+     */
+    public static byte[] concat(final byte[] ... allBytes) {
+        int size = 0;
+        for ( final byte[] bytes : allBytes ) size += bytes.length;
+
+        final byte[] c = new byte[size];
+        int offset = 0;
+        for ( final byte[] bytes : allBytes ) {
+            System.arraycopy(bytes, 0, c, offset, bytes.length);
+            offset += bytes.length;
+        }
+
+        return c;
+    }
+
+    /**
+     * Appends String(s) B to array A.
+     * @param A First array.
+     * @param B Strings to append.
+     * @return A with B(s) appended.
+     */
+    public static String[] appendArray(String[] A, String... B) {
+        return concatArrays(A, B);
+    }
+
+    public static <T extends Comparable<T>> List<T> sorted(Collection<T> c) {
+        return sorted(c, false);
+    }
+
+    public static <T extends Comparable<T>> List<T> sorted(Collection<T> c, boolean reverse) {
+        List<T> l = new ArrayList<T>(c);
+        Collections.sort(l);
+        if ( reverse ) Collections.reverse(l);
+        return l;
+    }
+
+    public static <T extends Comparable<T>, V> List<V> sorted(Map<T,V> c) {
+        return sorted(c, false);
+    }
+
+    public static <T extends Comparable<T>, V> List<V> sorted(Map<T,V> c, boolean reverse) {
+        List<T> t = new ArrayList<T>(c.keySet());
+        Collections.sort(t);
+        if ( reverse ) Collections.reverse(t);
+
+        List<V> l = new ArrayList<V>();
+        for ( T k : t ) {
+            l.add(c.get(k));
+        }
+        return l;
+    }
+
+    /**
+     * Reverse a byte array of bases
+     *
+     * @param bases  the byte array of bases
+     * @return the reverse of the base byte array
+     */
+    static public byte[] reverse(byte[] bases) {
+        byte[] rcbases = new byte[bases.length];
+
+        for (int i = 0; i < bases.length; i++) {
+            rcbases[i] = bases[bases.length - i - 1];
+        }
+
+        return rcbases;
+    }
+
+    static public <T> List<T> reverse(final List<T> l) {
+        final List<T> newL = new ArrayList<T>(l);
+        Collections.reverse(newL);
+        return newL;
+    }
+
+    /**
+     * Reverse an int array of bases
+     *
+     * @param bases  the int array of bases
+     * @return the reverse of the base int array
+     */
+    static public int[] reverse(int[] bases) {
+        int[] rcbases = new int[bases.length];
+
+        for (int i = 0; i < bases.length; i++) {
+            rcbases[i] = bases[bases.length - i - 1];
+        }
+
+        return rcbases;
+    }
+
+    /**
+     * Reverse (NOT reverse-complement!!) a string
+     *
+     * @param bases  input string
+     * @return the reversed string
+     */
+    static public String reverse(String bases) {
+        return new String( reverse( bases.getBytes() )) ;
+    }
+
+    public static boolean isFlagSet(int value, int flag) {
+        return ((value & flag) == flag);
+    }
+
+    /**
+     * Helper utility that calls into the InetAddress system to resolve the hostname.  If this fails,
+     * unresolvable gets returned instead.
+     */
+    public static String resolveHostname() {
+        try {
+            return InetAddress.getLocalHost().getCanonicalHostName();
+        }
+        catch (java.net.UnknownHostException uhe) { // [beware typo in code sample -dmw]
+            return "unresolvable";
+            // handle exception
+        }
+    }
+
+
+    public static byte [] arrayFromArrayWithLength(byte[] array, int length) {
+        byte [] output = new byte[length];
+        for (int j = 0; j < length; j++)
+            output[j] = array[(j % array.length)];
+        return output;
+    }
+
+    public static void fillArrayWithByte(byte[] array, byte value) {
+        for (int i=0; i<array.length; i++)
+            array[i] = value;
+    }
+
+    /**
+     * Creates a program record for the program, adds it to the list of program records (@PG tags) in the bam file and sets
+     * up the writer with the header and presorted status.
+     *
+     * @param originalHeader      original header
+     * @param programRecord       the program record for this program
+     */
+    public static SAMFileHeader setupWriter(final SAMFileHeader originalHeader, final SAMProgramRecord programRecord) {
+        final SAMFileHeader header = originalHeader.clone();
+        final List<SAMProgramRecord> oldRecords = header.getProgramRecords();
+        final List<SAMProgramRecord> newRecords = new ArrayList<SAMProgramRecord>(oldRecords.size()+1);
+        for ( SAMProgramRecord record : oldRecords )
+            if ( (programRecord != null && !record.getId().startsWith(programRecord.getId())))
+                newRecords.add(record);
+
+        if (programRecord != null) {
+            newRecords.add(programRecord);
+            header.setProgramRecords(newRecords);
+        }
+        return header;
+    }
+
+    /**
+    * Creates a program record for the program, adds it to the list of program records (@PG tags) in the bam file and returns
+    * the new header to be added to the BAM writer.
+    *
+    * @param toolkit             the engine
+    * @param walker              the walker object (so we can extract the command line)
+    * @param PROGRAM_RECORD_NAME the name for the PG tag
+    * @return a pre-filled header for the bam writer
+    */
+    public static SAMFileHeader setupWriter(final GenomeAnalysisEngine toolkit, final SAMFileHeader originalHeader, final Object walker, final String PROGRAM_RECORD_NAME) {
+        final SAMProgramRecord programRecord = createProgramRecord(toolkit, walker, PROGRAM_RECORD_NAME);
+        return setupWriter(originalHeader, programRecord);
+    }
+
+    /**
+     * Creates a program record for the program, adds it to the list of program records (@PG tags) in the bam file and sets
+     * up the writer with the header and presorted status.
+     *
+     * @param writer              BAM file writer
+     * @param toolkit             the engine
+     * @param preSorted           whether or not the writer can assume reads are going to be added are already sorted
+     * @param walker              the walker object (so we can extract the command line)
+     * @param PROGRAM_RECORD_NAME the name for the PG tag
+     */
+    public static void setupWriter(GATKSAMFileWriter writer, GenomeAnalysisEngine toolkit, SAMFileHeader originalHeader, boolean preSorted, Object walker, String PROGRAM_RECORD_NAME) {
+        SAMFileHeader header = setupWriter(toolkit, originalHeader, walker, PROGRAM_RECORD_NAME);
+        writer.writeHeader(header);
+        writer.setPresorted(preSorted);
+    }
+
+
+    /**
+     * Creates a program record (@PG) tag
+     *
+     * @param toolkit             the engine
+     * @param walker              the walker object (so we can extract the command line)
+     * @param PROGRAM_RECORD_NAME the name for the PG tag
+     * @return a program record for the tool
+     */
+    public static SAMProgramRecord createProgramRecord(GenomeAnalysisEngine toolkit, Object walker, String PROGRAM_RECORD_NAME) {
+        final SAMProgramRecord programRecord = new SAMProgramRecord(PROGRAM_RECORD_NAME);
+        final ResourceBundle headerInfo = TextFormattingUtils.loadResourceBundle("GATKText");
+        try {
+            final String version = headerInfo.getString("org.broadinstitute.gatk.tools.version");
+            programRecord.setProgramVersion(version);
+        } catch (MissingResourceException e) {
+            // couldn't care less if the resource is missing...
+        }
+        programRecord.setCommandLine(toolkit.createApproximateCommandLineArgumentString(toolkit, walker));
+        return programRecord;
+    }
+
+    /**
+     * Returns the number of combinations represented by this collection
+     * of collection of options.
+     *
+     * For example, if this is [[A, B], [C, D], [E, F, G]] returns 2 * 2 * 3 = 12
+     */
+    @Requires("options != null")
+    public static <T> int nCombinations(final Collection<T>[] options) {
+        int nStates = 1;
+        for ( Collection<T> states : options ) {
+            nStates *= states.size();
+        }
+        return nStates;
+    }
+
+    @Requires("options != null")
+    public static <T> int nCombinations(final List<List<T>> options) {
+        if ( options.isEmpty() )
+            return 0;
+        else {
+            int nStates = 1;
+            for ( Collection<T> states : options ) {
+                nStates *= states.size();
+            }
+            return nStates;
+        }
+    }
+
+    /**
+     * Make all combinations of N size of objects
+     *
+     * if objects = [A, B, C]
+     * if N = 1 => [[A], [B], [C]]
+     * if N = 2 => [[A, A], [B, A], [C, A], [A, B], [B, B], [C, B], [A, C], [B, C], [C, C]]
+     *
+     * @param objects         list of objects
+     * @param n               size of each combination
+     * @param withReplacement if false, the resulting permutations will only contain unique objects from objects
+     * @return a list with all combinations with size n of objects.
+     */
+    public static <T> List<List<T>> makePermutations(final List<T> objects, final int n, final boolean withReplacement) {
+        final List<List<T>> combinations = new ArrayList<List<T>>();
+
+        if ( n == 1 ) {
+            for ( final T o : objects )
+                combinations.add(Collections.singletonList(o));
+        } else if (n > 1) {
+            final List<List<T>> sub = makePermutations(objects, n - 1, withReplacement);
+            for ( List<T> subI : sub ) {
+                for ( final T a : objects ) {
+                    if ( withReplacement || ! subI.contains(a) )
+                        combinations.add(Utils.cons(a, subI));
+                }
+            }
+        }
+
+        return combinations;
+    }
+
+    /**
+     * Convenience function that formats the novelty rate as a %.2f string
+     *
+     * @param known number of variants from all that are known
+     * @param all number of all variants
+     * @return a String novelty rate, or NA if all == 0
+     */
+    public static String formattedNoveltyRate(final int known, final int all) {
+        return formattedPercent(all - known, all);
+    }
+
+    /**
+     * Convenience function that formats the novelty rate as a %.2f string
+     *
+     * @param x number of objects part of total that meet some criteria
+     * @param total count of all objects, including x
+     * @return a String percent rate, or NA if total == 0
+     */
+    public static String formattedPercent(final long x, final long total) {
+        return total == 0 ? "NA" : String.format("%.2f", (100.0*x) / total);
+    }
+
+    /**
+     * Convenience function that formats a ratio as a %.2f string
+     *
+     * @param num  number of observations in the numerator
+     * @param denom number of observations in the denumerator
+     * @return a String formatted ratio, or NA if all == 0
+     */
+    public static String formattedRatio(final long num, final long denom) {
+        return denom == 0 ? "NA" : String.format("%.2f", num / (1.0 * denom));
+    }
+
+    /**
+     * Adds element from an array into a collection.
+     *
+     * In the event of exception being throw due to some element, <code>dest</code> might have been modified by
+     * the successful addition of element before that one.
+     *
+     * @param dest the destination collection which cannot be <code>null</code> and should be able to accept
+     *             the input elements.
+     * @param elements the element to add to <code>dest</code>
+     * @param <T>  collection type element.
+     * @throws UnsupportedOperationException if the <tt>add</tt> operation
+     *         is not supported by <code>dest</code>.
+     * @throws ClassCastException if the class of any of the elements
+     *         prevents it from being added to <code>dest</code>.
+     * @throws NullPointerException if any of the elements is <code>null</code> and <code>dest</code>
+     *         does not permit <code>null</code> elements
+     * @throws IllegalArgumentException if some property of any of the elements
+     *         prevents it from being added to this collection
+     * @throws IllegalStateException if any of the elements cannot be added at this
+     *         time due to insertion restrictions.
+     * @return <code>true</code> if the collection was modified as a result.
+     */
+    public static <T> boolean addAll(Collection<T> dest, T ... elements) {
+        boolean result = false;
+        for (final T e : elements) {
+            result = dest.add(e) | result;
+        }
+        return result;
+    }
+
+    /**
+     * Create a constant map that maps each value in values to itself
+     */
+    public static <T> Map<T, T> makeIdentityFunctionMap(Collection<T> values) {
+        Map<T,T> map = new HashMap<T, T>(values.size());
+        for ( final T value : values )
+            map.put(value, value);
+        return Collections.unmodifiableMap(map);
+    }
+
+    /**
+     * Divides the input list into a list of sublists, which contains group size elements (except potentially the last one)
+     *
+     * list = [A, B, C, D, E]
+     * groupSize = 2
+     * result = [[A, B], [C, D], [E]]
+     *
+     */
+    public static <T> List<List<T>> groupList(final List<T> list, final int groupSize) {
+        if ( groupSize < 1 ) throw new IllegalArgumentException("groupSize >= 1");
+
+        final List<List<T>> subLists = new LinkedList<List<T>>();
+        int n = list.size();
+        for ( int i = 0; i < n; i += groupSize ) {
+            subLists.add(list.subList(i, Math.min(i + groupSize, n)));
+        }
+        return subLists;
+    }
+
+    /**
+     * @see #calcMD5(byte[])
+     */
+    public static String calcMD5(final String s) {
+        return calcMD5(s.getBytes());
+    }
+
+    /**
+     * Calculate the md5 for bytes, and return the result as a 32 character string
+     *
+     * @param bytes the bytes to calculate the md5 of
+     * @return the md5 of bytes, as a 32-character long string
+     */
+    @Ensures({"result != null", "result.length() == 32"})
+    public static String calcMD5(final byte[] bytes) {
+        if ( bytes == null ) throw new IllegalArgumentException("bytes cannot be null");
+        try {
+            final byte[] thedigest = MessageDigest.getInstance("MD5").digest(bytes);
+            final BigInteger bigInt = new BigInteger(1, thedigest);
+
+            String md5String = bigInt.toString(16);
+            while (md5String.length() < 32) md5String = "0" + md5String; // pad to length 32
+            return md5String;
+        }
+        catch ( NoSuchAlgorithmException e ) {
+            throw new IllegalStateException("MD5 digest algorithm not present");
+        }
+    }
+
+    /**
+     * Does big end with the exact sequence of bytes in suffix?
+     *
+     * @param big a non-null byte[] to test if it a prefix + suffix
+     * @param suffix a non-null byte[] to test if it's a suffix of big
+     * @return true if big is proper byte[] composed of some prefix + suffix
+     */
+    public static boolean endsWith(final byte[] big, final byte[] suffix) {
+        if ( big == null ) throw new IllegalArgumentException("big cannot be null");
+        if ( suffix == null ) throw new IllegalArgumentException("suffix cannot be null");
+        return new String(big).endsWith(new String(suffix));
+    }
+
+    /**
+     * Get the length of the longest common prefix of seq1 and seq2
+     * @param seq1 non-null byte array
+     * @param seq2 non-null byte array
+     * @param maxLength the maximum allowed length to return
+     * @return the length of the longest common prefix of seq1 and seq2, >= 0
+     */
+    public static int longestCommonPrefix(final byte[] seq1, final byte[] seq2, final int maxLength) {
+        if ( seq1 == null ) throw new IllegalArgumentException("seq1 is null");
+        if ( seq2 == null ) throw new IllegalArgumentException("seq2 is null");
+        if ( maxLength < 0 ) throw new IllegalArgumentException("maxLength < 0 " + maxLength);
+
+        final int end = Math.min(seq1.length, Math.min(seq2.length, maxLength));
+        for ( int i = 0; i < end; i++ ) {
+            if ( seq1[i] != seq2[i] )
+                return i;
+        }
+        return end;
+    }
+
+    /**
+     * Get the length of the longest common suffix of seq1 and seq2
+     * @param seq1 non-null byte array
+     * @param seq2 non-null byte array
+     * @param maxLength the maximum allowed length to return
+     * @return the length of the longest common suffix of seq1 and seq2, >= 0
+     */
+    public static int longestCommonSuffix(final byte[] seq1, final byte[] seq2, final int maxLength) {
+        if ( seq1 == null ) throw new IllegalArgumentException("seq1 is null");
+        if ( seq2 == null ) throw new IllegalArgumentException("seq2 is null");
+        if ( maxLength < 0 ) throw new IllegalArgumentException("maxLength < 0 " + maxLength);
+
+        final int end = Math.min(seq1.length, Math.min(seq2.length, maxLength));
+        for ( int i = 0; i < end; i++ ) {
+            if ( seq1[seq1.length - i - 1] != seq2[seq2.length - i - 1] )
+                return i;
+        }
+        return end;
+    }
+
+    /**
+     * Trim any number of bases from the front and/or back of an array
+     *
+     * @param seq                the sequence to trim
+     * @param trimFromFront      how much to trim from the front
+     * @param trimFromBack       how much to trim from the back
+     * @return a non-null array; can be the original array (i.e. not a copy)
+     */
+    public static byte[] trimArray(final byte[] seq, final int trimFromFront, final int trimFromBack) {
+        if ( trimFromFront + trimFromBack > seq.length )
+            throw new IllegalArgumentException("trimming total is larger than the original array");
+
+        // don't perform array copies if we need to copy everything anyways
+        return  ( trimFromFront == 0 && trimFromBack == 0 ) ? seq : Arrays.copyOfRange(seq, trimFromFront, seq.length - trimFromBack);
+    }
+
+    /**
+     * Simple wrapper for sticking elements of a int[] array into a List<Integer>
+     * @param ar - the array whose elements should be listified
+     * @return - a List<Integer> where each element has the same value as the corresponding index in @ar
+     */
+    public static List<Integer> listFromPrimitives(final int[] ar) {
+        final ArrayList<Integer> lst = new ArrayList<>(ar.length);
+        for ( final int d : ar ) {
+            lst.add(d);
+        }
+
+        return lst;
+    }
+
+    /**
+     * Compares sections from to byte arrays to verify whether they contain the same values.
+     *
+     * @param left first array to compare.
+     * @param leftOffset first position of the first array to compare.
+     * @param right second array to compare.
+     * @param rightOffset first position of the second array to compare.
+     * @param length number of positions to compare.
+     *
+     * @throws IllegalArgumentException if <ul>
+     *     <li>either {@code left} or {@code right} is {@code null} or</li>
+     *     <li>any off the offset or length combine point outside any of the two arrays</li>
+     * </ul>
+     * @return {@code true} iff {@code length} is 0 or all the bytes in both ranges are the same two-by-two.
+     */
+    public static boolean equalRange(final byte[] left, final int leftOffset, byte[] right, final int rightOffset, final int length) {
+        if (left == null) throw new IllegalArgumentException("left cannot be null");
+        if (right == null) throw new IllegalArgumentException("right cannot be null");
+        if (length < 0) throw new IllegalArgumentException("the length cannot be negative");
+        if (leftOffset < 0) throw new IllegalArgumentException("left offset cannot be negative");
+        if (leftOffset + length > left.length) throw new IllegalArgumentException("length goes beyond end of left array");
+        if (rightOffset < 0) throw new IllegalArgumentException("right offset cannot be negative");
+        if (rightOffset + length > right.length) throw new IllegalArgumentException("length goes beyond end of right array");
+
+        for (int i = 0; i < length; i++)
+            if (left[leftOffset + i] != right[rightOffset + i])
+                return false;
+        return true;
+    }
+
+    /**
+     * Skims out positions of an array returning a shorter one with the remaning positions in the same order.
+     * @param original the original array to splice.
+     * @param remove for each position in {@code original} indicates whether it should be spliced away ({@code true}),
+     *               or retained ({@code false})
+     *
+     * @param <T> the array type.
+     *
+     * @throws IllegalArgumentException if either {@code original} or {@code remove} is {@code null},
+     *    or {@code remove length is different to {@code original}'s}, or {@code original} is not in
+     *    fact an array.
+     *
+     * @return never {@code null}.
+     */
+    public static <T> T skimArray(final T original, final boolean[] remove) {
+        return skimArray(original,0,null,0,remove,0);
+    }
+
+    /**
+     * Skims out positions of an array returning a shorter one with the remaning positions in the same order.
+     *
+     * <p>
+     *     If the {@code dest} array provide is not long enough a new one will be created and returned with the
+     *     same component type. All elements before {@code destOffset} will be copied from the input to the
+     *     result array. If {@code dest} is {@code null}, a brand-new array large enough will be created where
+     *     the position preceding {@code destOffset} will be left with the default value. The component type
+     *     Will match the one of the {@code source} array.
+     * </p>
+     *
+     * @param source the original array to splice.
+     * @param sourceOffset the first position to skim.
+     * @param dest the destination array.
+     * @param destOffset the first position where to copy the skimed array values.
+     * @param remove for each position in {@code original} indicates whether it should be spliced away ({@code true}),
+     *               or retained ({@code false})
+     * @param removeOffset the first position in the remove index array to consider.
+     *
+     * @param <T> the array type.
+     *
+     * @throws IllegalArgumentException if either {@code original} or {@code remove} is {@code null},
+     *    or {@code remove length is different to {@code original}'s}, or {@code original} is not in
+     *    fact an array.
+     *
+     * @return never {@code null}.
+     */
+    public static <T> T skimArray(final T source, final int sourceOffset, final T dest, final int destOffset, final boolean[] remove, final int removeOffset) {
+        if (source == null)
+            throw new IllegalArgumentException("the source array cannot be null");
+        @SuppressWarnings("unchecked")
+        final Class<T> sourceClazz = (Class<T>) source.getClass();
+
+        if (!sourceClazz.isArray())
+            throw new IllegalArgumentException("the source array is not in fact an array instance");
+        final int length = Array.getLength(source) - sourceOffset;
+        if (length < 0)
+            throw new IllegalArgumentException("the source offset goes beyond the source array length");
+        return skimArray(source,sourceOffset,dest,destOffset,remove,removeOffset,length);
+    }
+
+    /**
+     * Skims out positions of an array returning a shorter one with the remaning positions in the same order.
+     *
+     * <p>
+     *     If the {@code dest} array provide is not long enough a new one will be created and returned with the
+     *     same component type. All elements before {@code destOffset} will be copied from the input to the
+     *     result array. If {@code dest} is {@code null}, a brand-new array large enough will be created where
+     *     the position preceding {@code destOffset} will be left with the default value. The component type
+     *     Will match the one of the {@code source} array.
+     * </p>
+     *
+     * @param source the original array to splice.
+     * @param sourceOffset the first position to skim.
+     * @param dest the destination array.
+     * @param destOffset the first position where to copy the skimed array values.
+     * @param remove for each position in {@code original} indicates whether it should be spliced away ({@code true}),
+     *               or retained ({@code false})
+     * @param removeOffset the first position in the remove index array to consider.
+     * @param length the total number of position in {@code source} to consider. Thus only the {@code sourceOffset} to
+     *               {@code sourceOffset + length - 1} region will be skimmed.
+     *
+     * @param <T> the array type.
+     *
+     * @throws IllegalArgumentException if either {@code original} or {@code remove} is {@code null},
+     *    or {@code remove length is different to {@code original}'s}, or {@code original} is not in
+     *    fact an array.
+     *
+     * @return never {@code null}.
+     */
+    public static <T> T skimArray(final T source, final int sourceOffset, final T dest, final int destOffset,
+                                  final boolean[] remove, final int removeOffset, final int length) {
+        if (source == null)
+            throw new IllegalArgumentException("the source array cannot be null");
+        if (remove == null)
+            throw new IllegalArgumentException("the remove array cannot be null");
+        if (sourceOffset < 0)
+            throw new IllegalArgumentException("the source array offset cannot be negative");
+        if (destOffset < 0)
+            throw new IllegalArgumentException("the destination array offset cannot be negative");
+        if (removeOffset < 0)
+            throw new IllegalArgumentException("the remove array offset cannot be negative");
+        if (length < 0)
+            throw new IllegalArgumentException("the length provided cannot be negative");
+
+        final int removeLength = Math.min(remove.length - removeOffset,length);
+
+        if (removeLength < 0)
+            throw new IllegalArgumentException("the remove offset provided falls beyond the remove array end");
+
+
+        @SuppressWarnings("unchecked")
+        final Class<T> sourceClazz = (Class<T>) source.getClass();
+
+        if (!sourceClazz.isArray())
+            throw new IllegalArgumentException("the source array is not in fact an array instance");
+
+        final Class<T> destClazz = skimArrayDetermineDestArrayClass(dest, sourceClazz);
+
+        final int sourceLength = Array.getLength(source);
+
+        if (sourceLength < length + sourceOffset)
+            throw new IllegalArgumentException("the source array is too small considering length and offset");
+
+        // count how many positions are to be removed.
+
+        int removeCount = 0;
+
+        final int removeEnd = removeLength + removeOffset;
+        for (int i = removeOffset; i < removeEnd; i++)
+            if  (remove[i]) removeCount++;
+
+
+        final int newLength = length - removeCount;
+
+
+        @SuppressWarnings("unchecked")
+        final T result = skimArrayBuildResultArray(dest, destOffset, destClazz, newLength);
+        // No removals, just copy the whole thing.
+
+        if (removeCount == 0)
+            System.arraycopy(source,sourceOffset,result,destOffset,length);
+        else if (length > 0) {  // if length == 0 nothing to do.
+            int nextOriginalIndex = 0;
+            int nextNewIndex = 0;
+            int nextRemoveIndex = removeOffset;
+            while (nextOriginalIndex < length && nextNewIndex < newLength) {
+                while (nextRemoveIndex < removeEnd && remove[nextRemoveIndex++]) { nextOriginalIndex++; } // skip positions to be spliced.
+                // Since we make the nextNewIndex < newLength check in the while condition
+                // there is no need to include the following break, as is guaranteed not to be true:
+                // if (nextOriginalIndex >= length) break; // we reach the final (last positions are to be spliced.
+                final int copyStart = nextOriginalIndex;
+                while (++nextOriginalIndex < length && (nextRemoveIndex >= removeEnd || !remove[nextRemoveIndex])) { nextRemoveIndex++; }
+                final int copyEnd = nextOriginalIndex;
+                final int copyLength = copyEnd - copyStart;
+                System.arraycopy(source, sourceOffset + copyStart, result, destOffset + nextNewIndex, copyLength);
+                nextNewIndex += copyLength;
+            }
+        }
+        return result;
+    }
+
+    private static <T> T skimArrayBuildResultArray(final T dest, final int destOffset, final Class<T> destClazz, final int newLength) {
+        @SuppressWarnings("unchecked")
+        final T result;
+
+        if (dest == null)
+            result = (T) Array.newInstance(destClazz.getComponentType(), newLength + destOffset);
+        else if (Array.getLength(dest) < newLength + destOffset) {
+            result = (T) Array.newInstance(destClazz.getComponentType(),newLength + destOffset);
+            if (destOffset > 0) System.arraycopy(dest,0,result,0,destOffset);
+        } else
+            result = dest;
+        return result;
+    }
+
+    private static <T> Class<T> skimArrayDetermineDestArrayClass(final T dest, Class<T> sourceClazz) {
+        final Class<T> destClazz;
+        if (dest == null)
+            destClazz = sourceClazz;
+        else {
+            destClazz = (Class<T>) dest.getClass();
+            if (destClazz != sourceClazz) {
+                if (!destClazz.isArray())
+                    throw new IllegalArgumentException("the destination array class must be an array");
+                if (sourceClazz.getComponentType().isAssignableFrom(destClazz.getComponentType()))
+                    throw new IllegalArgumentException("the provided destination array class cannot contain values from the source due to type incompatibility");
+            }
+        }
+        return destClazz;
+    }
+
+    /**
+     * Makes a deep clone of the array provided.
+     *
+     * <p>
+     *     When you can use {@link Arrays#copyOf} or an array {@link Object#clone()}  to create a copy of itself,
+     *     if it is multi-dimentional each sub array or matrix would be cloned.
+     * </p>
+     *
+     * <p>
+     *     Notice however that if the base type is an Object type, the base elements themselves wont be cloned.
+     * </p>
+     *
+     * @param array the array to deep-clone.
+     * @param <T> type of the array.
+     *
+     * @throws IllegalArgumentException if {@code array} is {@code null} or is not an array.
+     */
+    public static <T>  T deepCloneArray(final T array) {
+
+        if (array == null)
+            throw new IllegalArgumentException("");
+
+        @SuppressWarnings("unchecked")
+        final Class<T> clazz = (Class<T>) array.getClass();
+
+
+        if (!clazz.isArray())
+            throw new IllegalArgumentException("the input is not an array");
+
+        final int dimension = calculateArrayDimensions(clazz);
+
+        return deepCloneArrayUnchecked(array,clazz, dimension);
+    }
+
+    private static int calculateArrayDimensions(final Class<?> clazz) {
+        if (clazz.isArray())
+            return calculateArrayDimensions(clazz.getComponentType()) + 1;
+        else
+            return 0;
+    }
+
+    private static <T> T deepCloneArrayUnchecked(final T array, final Class<T> clazz, final int dimension) {
+
+
+        final int length = Array.getLength(array);
+
+        final Class componentClass = clazz.getComponentType();
+
+        final T result = (T) Array.newInstance(componentClass,length);
+
+        if (dimension <= 1) {
+            System.arraycopy(array, 0, result, 0, length);
+            return result;
+        }
+
+
+        final int dimensionMinus1 = dimension - 1;
+
+        for (int i = 0; i < length; i++)
+            Array.set(result,i,deepCloneArrayUnchecked(Array.get(array,i),componentClass,dimensionMinus1));
+
+        return result;
+    }
+}
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/activeregion/ActiveRegion.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/activeregion/ActiveRegion.java
new file mode 100644
index 0000000..86a89c1
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/activeregion/ActiveRegion.java
@@ -0,0 +1,500 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.utils.activeregion;
+
+import com.google.java.contract.Ensures;
+import com.google.java.contract.Invariant;
+import htsjdk.samtools.reference.IndexedFastaSequenceFile;
+import org.broadinstitute.gatk.utils.GenomeLoc;
+import org.broadinstitute.gatk.utils.GenomeLocParser;
+import org.broadinstitute.gatk.utils.GenomeLocSortedSet;
+import org.broadinstitute.gatk.utils.HasGenomeLocation;
+import org.broadinstitute.gatk.utils.clipping.ReadClipper;
+import org.broadinstitute.gatk.utils.sam.GATKSAMRecord;
+import org.broadinstitute.gatk.utils.sam.ReadUtils;
+
+import java.util.*;
+
+/**
+ * Represents a single active region created by the Active Region Traversal for processing
+ *
+ * An active region is a single contiguous span of bases on the genome that should be operated
+ * on as a single unit for the active region traversal.  The action may contains a list of
+ * reads that overlap the region (may because there may be no reads in the region).  The region
+ * is tagged as being either active or inactive, depending on the probabilities provided by
+ * the isActiveProb results from the ART walker.  Each region carries with it the
+ * exact span of the region (bases which are the core of the isActiveProbs from the walker) as
+ * well as an extended size, that includes the ART walker's extension size.  Reads in the region
+ * provided by ART include all reads overlapping the extended span, not the raw span.
+ *
+ * User: rpoplin
+ * Date: 1/4/12
+ */
+ at Invariant({
+        "extension >= 0",
+        "activeRegionLoc != null",
+        "genomeLocParser != null",
+        "spanIncludingReads != null",
+        "extendedLoc != null"
+})
+public class ActiveRegion implements HasGenomeLocation {
+    /**
+     * The reads included in this active region.  May be empty upon creation, and expand / contract
+     * as reads are added or removed from this region.
+     */
+    private final List<GATKSAMRecord> reads = new ArrayList<GATKSAMRecord>();
+
+    /**
+     * An ordered list (by genomic coordinate) of the ActivityProfileStates that went
+     * into this active region.  May be empty, which says that no supporting states were
+     * provided when this region was created.
+     */
+    private final List<ActivityProfileState> supportingStates;
+
+    /**
+     * The raw span of this active region, not including the active region extension
+     */
+    private final GenomeLoc activeRegionLoc;
+
+    /**
+     * The span of this active region on the genome, including the active region extension
+     */
+    private final GenomeLoc extendedLoc;
+
+    /**
+     * The extension, in bp, of this active region.
+     */
+    private final int extension;
+
+    /**
+     * A genomeLocParser so we can create genomeLocs
+     */
+    private final GenomeLocParser genomeLocParser;
+
+    /**
+     * Does this region represent an active region (all isActiveProbs above threshold) or
+     * an inactive region (all isActiveProbs below threshold)?
+     */
+    private final boolean isActive;
+
+    /**
+     * The span of this active region, including the bp covered by all reads in this
+     * region.  This union of extensionLoc and the loc of all reads in this region.
+     *
+     * Must be at least as large as extendedLoc, but may be larger when reads
+     * partially overlap this region.
+     */
+    private GenomeLoc spanIncludingReads;
+
+
+    /**
+     * Indicates whether the active region has been finalized
+     */
+    private boolean hasBeenFinalized;
+
+    /**
+     * Create a new ActiveRegion containing no reads
+     *
+     * @param activeRegionLoc the span of this active region
+     * @param supportingStates the states that went into creating this region, or null / empty if none are available.
+     *                         If not empty, must have exactly one state for each bp in activeRegionLoc
+     * @param isActive indicates whether this is an active region, or an inactve one
+     * @param genomeLocParser a non-null parser to let us create new genome locs
+     * @param extension the active region extension to use for this active region
+     */
+    public ActiveRegion( final GenomeLoc activeRegionLoc, final List<ActivityProfileState> supportingStates, final boolean isActive, final GenomeLocParser genomeLocParser, final int extension ) {
+        if ( activeRegionLoc == null ) throw new IllegalArgumentException("activeRegionLoc cannot be null");
+        if ( activeRegionLoc.size() == 0 ) throw new IllegalArgumentException("Active region cannot be of zero size, but got " + activeRegionLoc);
+        if ( genomeLocParser == null ) throw new IllegalArgumentException("genomeLocParser cannot be null");
+        if ( extension < 0 ) throw new IllegalArgumentException("extension cannot be < 0 but got " + extension);
+
+        this.activeRegionLoc = activeRegionLoc;
+        this.supportingStates = supportingStates == null ? Collections.<ActivityProfileState>emptyList() : new ArrayList<ActivityProfileState>(supportingStates);
+        this.isActive = isActive;
+        this.genomeLocParser = genomeLocParser;
+        this.extension = extension;
+        this.extendedLoc = genomeLocParser.createGenomeLocOnContig(activeRegionLoc.getContig(), activeRegionLoc.getStart() - extension, activeRegionLoc.getStop() + extension);
+        this.spanIncludingReads = extendedLoc;
+
+        if ( ! this.supportingStates.isEmpty() ) {
+            if ( this.supportingStates.size() != activeRegionLoc.size() )
+                throw new IllegalArgumentException("Supporting states wasn't empty but it doesn't have exactly one state per bp in the active region: states " + this.supportingStates.size() + " vs. bp in region = " + activeRegionLoc.size());
+            GenomeLoc lastStateLoc = null;
+            for ( final ActivityProfileState state : this.supportingStates ) {
+                if ( lastStateLoc != null ) {
+                    if ( state.getLoc().getStart() != lastStateLoc.getStart() + 1 || state.getLoc().getContigIndex() != lastStateLoc.getContigIndex())
+                        throw new IllegalArgumentException("Supporting state has an invalid sequence: last state was " + lastStateLoc + " but next state was " + state);
+                }
+                lastStateLoc = state.getLoc();
+            }
+        }
+    }
+
+    /**
+     * Simple interface to create an active region that isActive without any profile state
+     */
+    public ActiveRegion( final GenomeLoc activeRegionLoc, final GenomeLocParser genomeLocParser, final int extension ) {
+        this(activeRegionLoc, Collections.<ActivityProfileState>emptyList(), true, genomeLocParser, extension);
+    }
+
+    @Override
+    public String toString() {
+        return "ActiveRegion "  + activeRegionLoc.toString() + " active?=" + isActive() + " nReads=" + reads.size();
+    }
+
+    /**
+     * See #getActiveRegionReference but with padding == 0
+     */
+    public byte[] getActiveRegionReference( final IndexedFastaSequenceFile referenceReader ) {
+        return getActiveRegionReference(referenceReader, 0);
+    }
+
+    /**
+     * Get the reference bases from referenceReader spanned by the extended location of this active region,
+     * including additional padding bp on either side.  If this expanded region would exceed the boundaries
+     * of the active region's contig, the returned result will be truncated to only include on-genome reference
+     * bases
+     * @param referenceReader the source of the reference genome bases
+     * @param padding the padding, in BP, we want to add to either side of this active region extended region
+     * @return a non-null array of bytes holding the reference bases in referenceReader
+     */
+    @Ensures("result != null")
+    public byte[] getActiveRegionReference( final IndexedFastaSequenceFile referenceReader, final int padding ) {
+        return getReference(referenceReader, padding, extendedLoc);
+    }
+
+    /**
+     * See #getActiveRegionReference but using the span including regions not the extended span
+     */
+    public byte[] getFullReference( final IndexedFastaSequenceFile referenceReader ) {
+        return getFullReference(referenceReader, 0);
+    }
+
+    /**
+     * See #getActiveRegionReference but using the span including regions not the extended span
+     */
+    public byte[] getFullReference( final IndexedFastaSequenceFile referenceReader, final int padding ) {
+        return getReference(referenceReader, padding, spanIncludingReads);
+    }
+
+    /**
+     * Get the reference bases from referenceReader spanned by the extended location of this active region,
+     * including additional padding bp on either side.  If this expanded region would exceed the boundaries
+     * of the active region's contig, the returned result will be truncated to only include on-genome reference
+     * bases
+     * @param referenceReader the source of the reference genome bases
+     * @param padding the padding, in BP, we want to add to either side of this active region extended region
+     * @param genomeLoc a non-null genome loc indicating the base span of the bp we'd like to get the reference for
+     * @return a non-null array of bytes holding the reference bases in referenceReader
+     */
+    @Ensures("result != null")
+    public byte[] getReference( final IndexedFastaSequenceFile referenceReader, final int padding, final GenomeLoc genomeLoc ) {
+        if ( referenceReader == null ) throw new IllegalArgumentException("referenceReader cannot be null");
+        if ( padding < 0 ) throw new IllegalArgumentException("padding must be a positive integer but got " + padding);
+        if ( genomeLoc == null ) throw new IllegalArgumentException("genomeLoc cannot be null");
+        if ( genomeLoc.size() == 0 ) throw new IllegalArgumentException("GenomeLoc must have size > 0 but got " + genomeLoc);
+
+        final byte[] reference =  referenceReader.getSubsequenceAt( genomeLoc.getContig(),
+                Math.max(1, genomeLoc.getStart() - padding),
+                Math.min(referenceReader.getSequenceDictionary().getSequence(genomeLoc.getContig()).getSequenceLength(), genomeLoc.getStop() + padding) ).getBases();
+
+        return reference;
+    }
+
+    /**
+     * Get the raw span of this active region (excluding the extension)
+     * @return a non-null genome loc
+     */
+    @Override
+    @Ensures("result != null")
+    public GenomeLoc getLocation() { return activeRegionLoc; }
+
+    /**
+     * Get the span of this active region including the extension value
+     * @return a non-null GenomeLoc
+     */
+    @Ensures("result != null")
+    public GenomeLoc getExtendedLoc() { return extendedLoc; }
+
+    /**
+     * Get the span of this active region including the extension and the projects on the
+     * genome of all reads in this active region.  That is, returns the bp covered by this
+     * region and all reads in the region.
+     * @return a non-null genome loc
+     */
+    @Ensures("result != null")
+    public GenomeLoc getReadSpanLoc() { return spanIncludingReads; }
+
+    /**
+     * Get the active profile states that went into creating this region, if possible
+     * @return an unmodifiable list of states that led to the creation of this region, or an empty
+     *         list if none were provided
+     */
+    @Ensures("result != null")
+    public List<ActivityProfileState> getSupportingStates() {
+        return Collections.unmodifiableList(supportingStates);
+    }
+
+    /**
+     * Get the active region extension applied to this region
+     *
+     * The extension is >= 0 bp in size, and indicates how much padding this art walker wanted for its regions
+     *
+     * @return the size in bp of the region extension
+     */
+    @Ensures("result >= 0")
+    public int getExtension() { return extension; }
+
+    /**
+     * Get an unmodifiable list of reads currently in this active region.
+     *
+     * The reads are sorted by their coordinate position
+     *
+     * @return an unmodifiable list of reads in this active region
+     */
+    @Ensures("result != null")
+    public List<GATKSAMRecord> getReads() {
+        return Collections.unmodifiableList(reads);
+    }
+
+    /**
+     * Get the number of reads currently in this active region
+     * @return an integer >= 0
+     */
+    @Ensures("result >= 0")
+    public int size() { return reads.size(); }
+
+    /**
+     * Add read to this active region
+     *
+     * Read must have alignment start >= than the last read currently in this active region.
+     *
+     * @throws IllegalArgumentException if read doesn't overlap the extended region of this active region
+     *
+     * @param read a non-null GATKSAMRecord
+     */
+    @Ensures("reads.size() == old(reads.size()) + 1")
+    public void add( final GATKSAMRecord read ) {
+        if ( read == null ) throw new IllegalArgumentException("Read cannot be null");
+
+        final GenomeLoc readLoc = genomeLocParser.createGenomeLoc( read );
+        if ( ! readOverlapsRegion(read) )
+            throw new IllegalArgumentException("Read location " + readLoc + " doesn't overlap with active region extended span " + extendedLoc);
+
+        spanIncludingReads = spanIncludingReads.union( readLoc );
+
+        if ( ! reads.isEmpty() ) {
+            final GATKSAMRecord lastRead = reads.get(size() - 1);
+            if ( ! lastRead.getReferenceIndex().equals(read.getReferenceIndex()) )
+                throw new IllegalArgumentException("Attempting to add a read to ActiveRegion not on the same contig as other reads: lastRead " + lastRead + " attempting to add " + read);
+
+            if ( read.getAlignmentStart() < lastRead.getAlignmentStart() )
+                throw new IllegalArgumentException("Attempting to add a read to ActiveRegion out of order w.r.t. other reads: lastRead " + lastRead + " at " + lastRead.getAlignmentStart() + " attempting to add " + read + " at " + read.getAlignmentStart());
+        }
+
+        reads.add( read );
+    }
+
+    /**
+     * Returns true if read would overlap the extended extent of this region
+     * @param read the read we want to test
+     * @return true if read can be added to this region, false otherwise
+     */
+    public boolean readOverlapsRegion(final GATKSAMRecord read) {
+        final GenomeLoc readLoc = genomeLocParser.createGenomeLoc( read );
+        return readLoc.overlapsP(extendedLoc);
+    }
+
+    /**
+     * Add all reads to this active region
+     * @param reads a collection of reads to add to this active region
+     */
+    public void addAll(final Collection<GATKSAMRecord> reads) {
+        if ( reads == null ) throw new IllegalArgumentException("reads cannot be null");
+        for ( final GATKSAMRecord read : reads )
+            add(read);
+    }
+
+    /**
+     * Clear all of the reads currently in this active region
+     */
+    @Ensures("size() == 0")
+    public void clearReads() {
+        spanIncludingReads = extendedLoc;
+        reads.clear();
+    }
+
+    /**
+     * Remove all of the reads in readsToRemove from this active region
+     * @param readsToRemove the set of reads we want to remove
+     */
+    public void removeAll( final Set<GATKSAMRecord> readsToRemove ) {
+        final Iterator<GATKSAMRecord> it = reads.iterator();
+        spanIncludingReads = extendedLoc;
+        while ( it.hasNext() ) {
+            final GATKSAMRecord read = it.next();
+            if ( readsToRemove.contains(read) )
+                it.remove();
+            else
+                spanIncludingReads = spanIncludingReads.union( genomeLocParser.createGenomeLoc(read) );
+        }
+    }
+
+    /**
+     * Is this region equal to other, excluding any reads in either region in the comparison
+     * @param other the other active region we want to test
+     * @return true if this region is equal, excluding any reads and derived values, to other
+     */
+    protected boolean equalExceptReads(final ActiveRegion other) {
+        if ( activeRegionLoc.compareTo(other.activeRegionLoc) != 0 ) return false;
+        if ( isActive() != other.isActive()) return false;
+        if ( genomeLocParser != other.genomeLocParser ) return false;
+        if ( extension != other.extension ) return false;
+        if ( extendedLoc.compareTo(other.extendedLoc) != 0 ) return false;
+        return true;
+    }
+
+    /**
+     * Does this region represent an active region (all isActiveProbs above threshold) or
+     * an inactive region (all isActiveProbs below threshold)?
+     */
+    public boolean isActive() {
+        return isActive;
+    }
+
+    /**
+     * Intersect this active region with the allowed intervals, returning a list of active regions
+     * that only contain locations present in intervals
+     *
+     * Note that the returned list may be empty, if this active region doesn't overlap the set at all
+     *
+     * Note that the resulting regions are all empty, regardless of whether the current active region has reads
+     *
+     * @param intervals a non-null set of intervals that are allowed
+     * @return an ordered list of active region where each interval is contained within intervals
+     */
+    @Ensures("result != null")
+    protected List<ActiveRegion> splitAndTrimToIntervals(final GenomeLocSortedSet intervals) {
+        final List<GenomeLoc> allOverlapping = intervals.getOverlapping(getLocation());
+        final List<ActiveRegion> clippedRegions = new LinkedList<ActiveRegion>();
+
+        for ( final GenomeLoc overlapping : allOverlapping ) {
+            clippedRegions.add(trim(overlapping, extension));
+        }
+
+        return clippedRegions;
+    }
+
+    /**
+     * Trim this active to just the span, producing a new active region without any reads that has only
+     * the extent of newExtend intersected with the current extent
+     * @param span the new extend of the active region we want
+     * @param extension the extension size we want for the newly trimmed active region
+     * @return a non-null, empty active region
+     */
+    public ActiveRegion trim(final GenomeLoc span, final int extension) {
+        if ( span == null ) throw new IllegalArgumentException("Active region extent cannot be null");
+        if ( extension < 0) throw new IllegalArgumentException("the extension size must be 0 or greater");
+        final int extendStart = Math.max(1,span.getStart() - extension);
+        final int maxStop = genomeLocParser.getContigs().getSequence(span.getContigIndex()).getSequenceLength();
+        final int extendStop = Math.min(span.getStop() + extension, maxStop);
+        final GenomeLoc extendedSpan = genomeLocParser.createGenomeLoc(span.getContig(), extendStart, extendStop);
+        return trim(span, extendedSpan);
+
+//TODO - Inconsiste support of substates trimming. Check lack of consistency!!!!
+//        final GenomeLoc subLoc = getLocation().intersect(span);
+//        final int subStart = subLoc.getStart() - getLocation().getStart();
+//        final int subEnd = subStart + subLoc.size();
+//        final List<ActivityProfileState> subStates = supportingStates.isEmpty() ? supportingStates : supportingStates.subList(subStart, subEnd);
+//        return new ActiveRegion( subLoc, subStates, isActive, genomeLocParser, extension );
+
+    }
+
+    public ActiveRegion trim(final GenomeLoc span) {
+        return trim(span,span);
+    }
+
+    /**
+     * Trim this active to no more than the span, producing a new active region with properly trimmed reads that
+     * attempts to provide the best possible representation of this active region covering the span.
+     *
+     * The challenge here is that span may (1) be larger than can be represented by this active region
+     * + its original extension and (2) the extension must be symmetric on both sides.  This algorithm
+     * therefore determines how best to represent span as a subset of the span of this
+     * region with a padding value that captures as much of the span as possible.
+     *
+     * For example, suppose this active region is
+     *
+     * Active:    100-200 with extension of 50, so that the true span is 50-250
+     * NewExtent: 150-225 saying that we'd ideally like to just have bases 150-225
+     *
+     * Here we represent the active region as a active region from 150-200 with 25 bp of padding.
+     *
+     * The overall constraint is that the active region can never exceed the original active region, and
+     * the extension is chosen to maximize overlap with the desired region
+     *
+     * @param span the new extend of the active region we want
+     * @return a non-null, empty active region
+     */
+    public ActiveRegion trim(final GenomeLoc span, final GenomeLoc extendedSpan) {
+        if ( span == null ) throw new IllegalArgumentException("Active region extent cannot be null");
+        if ( extendedSpan == null ) throw new IllegalArgumentException("Active region extended span cannot be null");
+        if ( ! extendedSpan.containsP(span))
+            throw new IllegalArgumentException("The requested extended must fully contain the requested span");
+
+        final GenomeLoc subActive = getLocation().intersect(span);
+        final int requiredOnRight = Math.max(extendedSpan.getStop() - subActive.getStop(), 0);
+        final int requiredOnLeft = Math.max(subActive.getStart() - extendedSpan.getStart(), 0);
+        final int requiredExtension = Math.min(Math.max(requiredOnLeft, requiredOnRight), getExtension());
+
+        final ActiveRegion result = new ActiveRegion( subActive, Collections.<ActivityProfileState>emptyList(), isActive, genomeLocParser, requiredExtension );
+
+        final List<GATKSAMRecord> myReads = getReads();
+        final GenomeLoc resultExtendedLoc = result.getExtendedLoc();
+        final int resultExtendedLocStart = resultExtendedLoc.getStart();
+        final int resultExtendedLocStop = resultExtendedLoc.getStop();
+
+        final List<GATKSAMRecord> trimmedReads = new ArrayList<>(myReads.size());
+        for( final GATKSAMRecord read : myReads ) {
+            final GATKSAMRecord clippedRead = ReadClipper.hardClipToRegion(read,
+                    resultExtendedLocStart, resultExtendedLocStop);
+            if( result.readOverlapsRegion(clippedRead) && clippedRead.getReadLength() > 0 )
+                trimmedReads.add(clippedRead);
+        }
+        result.clearReads();
+        result.addAll(ReadUtils.sortReadsByCoordinate(trimmedReads));
+        return result;
+    }
+
+    public void setFinalized(final boolean value) {
+        hasBeenFinalized = value;
+    }
+
+    public boolean isFinalized() {
+        return hasBeenFinalized;
+    }
+
+}
\ No newline at end of file
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/activeregion/ActiveRegionReadState.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/activeregion/ActiveRegionReadState.java
new file mode 100644
index 0000000..76b4eb6
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/activeregion/ActiveRegionReadState.java
@@ -0,0 +1,40 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.utils.activeregion;
+
+/**
+ * Describes how a read relates to an assigned ActiveRegion
+ *
+ * User: thibault
+ * Date: 11/26/12
+ * Time: 2:35 PM
+ */
+public enum ActiveRegionReadState {
+    PRIMARY,        // This is the read's primary region
+    NONPRIMARY,     // This region overlaps the read, but it is not primary
+    EXTENDED,       // This region would overlap the read if it were extended
+    UNMAPPED        // This read is not mapped
+}
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/activeregion/ActivityProfile.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/activeregion/ActivityProfile.java
new file mode 100644
index 0000000..2d97f69
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/activeregion/ActivityProfile.java
@@ -0,0 +1,520 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.utils.activeregion;
+
+import com.google.java.contract.Ensures;
+import com.google.java.contract.Requires;
+import org.broadinstitute.gatk.utils.GenomeLoc;
+import org.broadinstitute.gatk.utils.GenomeLocParser;
+import org.broadinstitute.gatk.utils.GenomeLocSortedSet;
+
+import java.util.*;
+
+/**
+ * Class holding information about per-base activity scores for the
+ * active region traversal
+ *
+ * @author Mark DePristo
+ * @since Date created
+ */
+public class ActivityProfile {
+    protected final List<ActivityProfileState> stateList;
+    protected final GenomeLocParser parser;
+    protected final GenomeLocSortedSet restrictToIntervals;
+
+    protected final int maxProbPropagationDistance;
+    protected final double activeProbThreshold;
+
+    protected GenomeLoc regionStartLoc = null;
+    protected GenomeLoc regionStopLoc = null;
+
+    /**
+     * A cached value of the regionStartLoc contig length, to make calls to
+     * getCurrentContigLength efficient
+     */
+    protected int contigLength = -1;
+
+    /**
+     * Create a new empty ActivityProfile
+     * @param parser the parser we can use to create genome locs, cannot be null
+     * @param maxProbPropagationDistance region probability propagation distance beyond it's maximum size
+     * @param activeProbThreshold threshold for the probability of am active profile state being active
+     */
+    public ActivityProfile(final GenomeLocParser parser, final int maxProbPropagationDistance, final double activeProbThreshold) {
+        this(parser, maxProbPropagationDistance, activeProbThreshold, null);
+    }
+
+    /**
+     * Create a empty ActivityProfile, restricting output to profiles overlapping intervals, if not null
+     * @param parser the parser we can use to create genome locs, cannot be null
+     * @param maxProbPropagationDistance region probability propagation distance beyond it's maximum size
+     * @param activeProbThreshold threshold for the probability of a profile state being active
+     * @param intervals only include states that are within these intervals, if not null
+     */
+    public ActivityProfile(final GenomeLocParser parser, final int maxProbPropagationDistance, final double activeProbThreshold, final GenomeLocSortedSet intervals) {
+        if ( parser == null ) throw new IllegalArgumentException("parser cannot be null");
+
+        this.parser = parser;
+        this.stateList = new ArrayList<ActivityProfileState>();
+        this.restrictToIntervals = intervals;
+        this.maxProbPropagationDistance = maxProbPropagationDistance;
+        this.activeProbThreshold = activeProbThreshold;
+    }
+
+    @Override
+    public String toString() {
+        return "ActivityProfile{" +
+                "start=" + regionStartLoc +
+                ", stop=" + regionStopLoc +
+                '}';
+    }
+
+    /**
+     * How far away can probability mass be moved around in this profile?
+     *
+     * This distance puts an upper limit on how far, in bp, we will ever propagate probability max around
+     * when adding a new ActivityProfileState.  For example, if the value of this function is
+     * 10, and you are looking at a state at bp 5, and we know that no states beyond 5 + 10 will have
+     * their probability propagated back to that state.
+     *
+     * @return a positive integer distance in bp
+     */
+    @Ensures("result >= 0")
+    public int getMaxProbPropagationDistance() {
+        return maxProbPropagationDistance;
+    }
+
+    /**
+     * How many profile results are in this profile?
+     * @return the number of profile results
+     */
+    @Ensures("result >= 0")
+    public int size() {
+        return stateList.size();
+    }
+
+    /**
+     * Is this profile empty?
+     * @return true if the profile is empty
+     */
+    @Ensures("isEmpty() == (size() == 0)")
+    public boolean isEmpty() {
+        return stateList.isEmpty();
+    }
+
+    /**
+     * Get the span of this activity profile, which is from the start of the first state to the stop of the last
+     * @return a potentially null GenomeLoc.  Will be null if this profile is empty
+     */
+    public GenomeLoc getSpan() {
+        return isEmpty() ? null : regionStartLoc.endpointSpan(regionStopLoc);
+    }
+
+    @Requires("! isEmpty()")
+    public int getContigIndex() {
+        return regionStartLoc.getContigIndex();
+    }
+
+    @Requires("! isEmpty()")
+    public int getStop() {
+        return regionStopLoc.getStop();
+    }
+
+    /**
+     * Get the list of active profile results in this object
+     * @return a non-null, ordered list of active profile results
+     */
+    @Ensures("result != null")
+    protected List<ActivityProfileState> getStateList() {
+        return stateList;
+    }
+
+    /**
+     * Get the probabilities of the states as a single linear array of doubles
+     * @return a non-null array
+     */
+    @Ensures("result != null")
+    protected double[] getProbabilitiesAsArray() {
+        final double[] probs = new double[getStateList().size()];
+        int i = 0;
+        for ( final ActivityProfileState state : getStateList() )
+            probs[i++] = state.isActiveProb;
+        return probs;
+    }
+
+    /**
+     * Helper function that gets the genome loc for a site offset from relativeLoc, protecting ourselves from
+     * falling off the edge of the contig.
+     *
+     * @param relativeLoc the location offset is relative to
+     * @param offset the offset from relativeLoc where we'd like to create a GenomeLoc
+     * @return a genome loc with relativeLoc.start + offset, if this is on the contig, null otherwise
+     */
+    @Requires("relativeLoc != null")
+    protected GenomeLoc getLocForOffset(final GenomeLoc relativeLoc, final int offset) {
+        final int start = relativeLoc.getStart() + offset;
+        if ( start < 0 || start > getCurrentContigLength() ) {
+            return null;
+        } else {
+            return parser.createGenomeLoc(regionStartLoc.getContig(), regionStartLoc.getContigIndex(), start, start);
+        }
+    }
+
+    /**
+     * Get the length of the current contig
+     * @return the length in bp
+     */
+    @Requires("regionStartLoc != null")
+    @Ensures("result > 0")
+    private int getCurrentContigLength() {
+        return contigLength;
+    }
+
+    // --------------------------------------------------------------------------------
+    //
+    // routines to add states to a profile
+    //
+    // --------------------------------------------------------------------------------
+
+    /**
+     * Add the next ActivityProfileState to this profile.
+     *
+     * Must be contiguous with the previously added result, or an IllegalArgumentException will be thrown
+     *
+     * @param state a well-formed ActivityProfileState result to incorporate into this profile
+     */
+    @Requires("state != null")
+    public void add(final ActivityProfileState state) {
+        final GenomeLoc loc = state.getLoc();
+
+        if ( regionStartLoc == null ) {
+            regionStartLoc = loc;
+            regionStopLoc = loc;
+            contigLength = parser.getContigInfo(regionStartLoc.getContig()).getSequenceLength();
+        } else {
+            if ( regionStopLoc.getStart() != loc.getStart() - 1 )
+                throw new IllegalArgumentException("Bad add call to ActivityProfile: loc " + loc + " not immediately after last loc " + regionStopLoc );
+            regionStopLoc = loc;
+        }
+
+        final Collection<ActivityProfileState> processedStates = processState(state);
+        for ( final ActivityProfileState processedState : processedStates ) {
+            incorporateSingleState(processedState);
+        }
+    }
+
+    /**
+     * Incorporate a single activity profile state into the current list of states
+     *
+     * If state's position occurs immediately after the last position in this profile, then
+     * the state is appended to the state list.  If it's within the existing states list,
+     * the prob of stateToAdd is added to its corresponding state in the list.  If the
+     * position would be before the start of this profile, stateToAdd is simply ignored.
+     *
+     * @param stateToAdd the state we want to add to the states list
+     */
+    @Requires("stateToAdd != null")
+    private void incorporateSingleState(final ActivityProfileState stateToAdd) {
+        final int position = stateToAdd.getOffset(regionStartLoc);
+
+        if ( position > size() )
+            // should we allow this?  probably not
+            throw new IllegalArgumentException("Must add state contiguous to existing states: adding " + stateToAdd);
+
+        if ( position >= 0 ) {
+            // ignore states starting before this region's start
+            if ( position < size() ) {
+                stateList.get(position).isActiveProb += stateToAdd.isActiveProb;
+            } else {
+                if ( position != size() ) throw new IllegalStateException("position == size but it wasn't");
+                stateList.add(stateToAdd);
+            }
+        }
+    }
+
+    /**
+     * Process justAddedState, returning a collection of derived states that actually be added to the stateList
+     *
+     * The purpose of this function is to transform justAddedStates, if needed, into a series of atomic states
+     * that we actually want to track.  For example, if state is for soft clips, we transform that single
+     * state into a list of states that surround the state up to the distance of the soft clip.
+     *
+     * Can be overridden by subclasses to transform states in any way
+     *
+     * There's no particular contract for the output states, except that they can never refer to states
+     * beyond the current end of the stateList unless the explicitly include preceding states before
+     * the reference.  So for example if the current state list is [1, 2, 3] this function could return
+     * [1,2,3,4,5] but not [1,2,3,5].
+     *
+     * @param justAddedState the state our client provided to use to add to the list
+     * @return a list of derived states that should actually be added to this profile's state list
+     */
+    protected Collection<ActivityProfileState> processState(final ActivityProfileState justAddedState) {
+        if ( justAddedState.resultState.equals(ActivityProfileState.Type.HIGH_QUALITY_SOFT_CLIPS) ) {
+            // special code to deal with the problem that high quality soft clipped bases aren't added to pileups
+            final List<ActivityProfileState> states = new LinkedList<ActivityProfileState>();
+            // add no more than the max prob propagation distance num HQ clips
+            final int numHQClips = Math.min(justAddedState.resultValue.intValue(), getMaxProbPropagationDistance());
+            for( int jjj = - numHQClips; jjj <= numHQClips; jjj++ ) {
+                final GenomeLoc loc = getLocForOffset(justAddedState.getLoc(), jjj);
+                if ( loc != null )
+                    states.add(new ActivityProfileState(loc, justAddedState.isActiveProb));
+            }
+
+            return states;
+        } else {
+            return Collections.singletonList(justAddedState);
+        }
+    }
+
+    // --------------------------------------------------------------------------------
+    //
+    // routines to get active regions from the profile
+    //
+    // --------------------------------------------------------------------------------
+
+    /**
+     * Get the next completed active regions from this profile, and remove all states supporting them from this profile
+     *
+     * Takes the current profile and finds all of the active / inactive from the start of the profile that are
+     * ready.  By ready we mean unable to have their probability modified any longer by future additions to the
+     * profile.  The regions that are popped off the profile take their states with them, so the start of this
+     * profile will always be after the end of the last region returned here.
+     *
+     * The regions are returned sorted by genomic position.
+     *
+     * This function may not return anything in the list, if no regions are ready
+     *
+     * No returned region will be larger than maxRegionSize.
+     *
+     * @param activeRegionExtension the extension value to provide to the constructed regions
+     * @param minRegionSize the minimum region size, in the case where we have to cut up regions that are too large
+     * @param maxRegionSize the maximize size of the returned region
+     * @param forceConversion if true, we'll return a region whose end isn't sufficiently far from the end of the
+     *                        stateList.  Used to close out the active region when we've hit some kind of end (such
+     *                        as the end of the contig)
+     * @return a non-null list of active regions
+     */
+    @Ensures("result != null")
+    public List<ActiveRegion> popReadyActiveRegions(final int activeRegionExtension, final int minRegionSize, final int maxRegionSize, final boolean forceConversion) {
+        if ( activeRegionExtension < 0 ) throw new IllegalArgumentException("activeRegionExtension must be >= 0 but got " + activeRegionExtension);
+        if ( minRegionSize < 1 ) throw new IllegalArgumentException("minRegionSize must be >= 1 but got " + minRegionSize);
+        if ( maxRegionSize < 1 ) throw new IllegalArgumentException("maxRegionSize must be >= 1 but got " + maxRegionSize);
+
+        final LinkedList<ActiveRegion> regions = new LinkedList<ActiveRegion>();
+
+        while ( true ) {
+            final ActiveRegion nextRegion = popNextReadyActiveRegion(activeRegionExtension, minRegionSize, maxRegionSize, forceConversion);
+            if ( nextRegion == null )
+                return regions;
+            else {
+                if ( restrictToIntervals == null )
+                    regions.add(nextRegion);
+                else
+                    regions.addAll(nextRegion.splitAndTrimToIntervals(restrictToIntervals));
+            }
+        }
+    }
+
+    /**
+     * Helper function for popReadyActiveRegions that pops the first ready region off the front of this profile
+     *
+     * If a region is returned, modifies the state of this profile so that states used to make the region are
+     * no longer part of the profile.  Associated information (like the region start position) of this profile
+     * are also updated.
+     *
+     * @param activeRegionExtension the extension value to provide to the constructed regions
+     * @param minRegionSize the minimum region size, in the case where we have to cut up regions that are too large
+     * @param maxRegionSize the maximize size of the returned region
+     * @param forceConversion if true, we'll return a region whose end isn't sufficiently far from the end of the
+     *                        stateList.  Used to close out the active region when we've hit some kind of end (such
+     *                        as the end of the contig)
+     * @return a fully formed active region, or null if none can be made
+     */
+    private ActiveRegion popNextReadyActiveRegion(final int activeRegionExtension, final int minRegionSize, final int maxRegionSize, final boolean forceConversion) {
+        if ( stateList.isEmpty() )
+            return null;
+
+        // If we are flushing the activity profile we need to trim off the excess states so that we don't create regions outside of our current processing interval
+        if( forceConversion ) {
+            final List<ActivityProfileState> statesToTrimAway = new ArrayList<ActivityProfileState>(stateList.subList(getSpan().size(), stateList.size()));
+            stateList.removeAll(statesToTrimAway);
+        }
+
+        final ActivityProfileState first = stateList.get(0);
+        final boolean isActiveRegion = first.isActiveProb > activeProbThreshold;
+        final int offsetOfNextRegionEnd = findEndOfRegion(isActiveRegion, minRegionSize, maxRegionSize, forceConversion);
+        if ( offsetOfNextRegionEnd == -1 )
+            // couldn't find a valid ending offset, so we return null
+            return null;
+
+        // we need to create the active region, and clip out the states we're extracting from this profile
+        final List<ActivityProfileState> sub = stateList.subList(0, offsetOfNextRegionEnd + 1);
+        final List<ActivityProfileState> supportingStates = new ArrayList<ActivityProfileState>(sub);
+        sub.clear();
+
+        // update the start and stop locations as necessary
+        if ( stateList.isEmpty() ) {
+            regionStartLoc = regionStopLoc = null;
+        } else {
+            regionStartLoc = stateList.get(0).getLoc();
+        }
+        final GenomeLoc regionLoc = parser.createGenomeLoc(first.getLoc().getContig(), first.getLoc().getStart(), first.getLoc().getStart() + offsetOfNextRegionEnd);
+        return new ActiveRegion(regionLoc, supportingStates, isActiveRegion, parser, activeRegionExtension);
+    }
+
+    /**
+     * Find the end of the current region, returning the index into the element isActive element, or -1 if the region isn't done
+     *
+     * The current region is defined from the start of the stateList, looking for elements that have the same isActiveRegion
+     * flag (i.e., if isActiveRegion is true we are looking for states with isActiveProb > threshold, or alternatively
+     * for states < threshold).  The maximize size of the returned region is maxRegionSize.  If forceConversion is
+     * true, then we'll return the region end even if this isn't safely beyond the max prob propagation distance.
+     *
+     * Note that if isActiveRegion is true, and we can construct a active region > maxRegionSize in bp, we
+     * find the further local minimum within that max region, and cut the region there, under the constraint
+     * that the resulting region must be at least minRegionSize in bp.
+     *
+     * @param isActiveRegion is the region we're looking for an active region or inactive region?
+     * @param minRegionSize the minimum region size, in the case where we have to cut up regions that are too large
+     * @param maxRegionSize the maximize size of the returned region
+     * @param forceConversion if true, we'll return a region whose end isn't sufficiently far from the end of the
+     *                        stateList.  Used to close out the active region when we've hit some kind of end (such
+     *                        as the end of the contig)
+     * @return the index into stateList of the last element of this region, or -1 if it cannot be found
+     */
+    @Ensures({
+            "result >= -1",
+            "result == -1 || result < maxRegionSize",
+            "! (result == -1 && forceConversion)"})
+    private int findEndOfRegion(final boolean isActiveRegion, final int minRegionSize, final int maxRegionSize, final boolean forceConversion) {
+        if ( ! forceConversion && stateList.size() < maxRegionSize + getMaxProbPropagationDistance() ) {
+            // we really haven't finalized at the probability mass that might affect our decision, so keep
+            // waiting until we do before we try to make any decisions
+            return -1;
+        }
+
+        int endOfActiveRegion = findFirstActivityBoundary(isActiveRegion, maxRegionSize);
+
+        if ( isActiveRegion && endOfActiveRegion == maxRegionSize )
+            // we've run to the end of the region, let's find a good place to cut
+            endOfActiveRegion = findBestCutSite(endOfActiveRegion, minRegionSize);
+
+        // we're one past the end, so i must be decremented
+        return endOfActiveRegion - 1;
+    }
+
+    /**
+     * Find the the local minimum within 0 - endOfActiveRegion where we should divide region
+     *
+     * This algorithm finds the global minimum probability state within the region [minRegionSize, endOfActiveRegion)
+     * (exclusive of endOfActiveRegion), and returns the state index of that state.
+     * that it
+     *
+     * @param endOfActiveRegion the last state of the current active region (exclusive)
+     * @param minRegionSize the minimum of the left-most region, after cutting
+     * @return the index of state after the cut site (just like endOfActiveRegion)
+     */
+    @Requires({"endOfActiveRegion >= minRegionSize", "minRegionSize >= 0"})
+    @Ensures({"result >= minRegionSize", "result <= endOfActiveRegion"})
+    private int findBestCutSite(final int endOfActiveRegion, final int minRegionSize) {
+        int minI = endOfActiveRegion - 1;
+        double minP = Double.MAX_VALUE;
+
+        for ( int i = minI; i >= minRegionSize - 1; i-- ) {
+            double cur = getProb(i);
+            if ( cur < minP && isMinimum(i) ) {
+                minP = cur;
+                minI = i;
+            }
+        }
+
+        return minI + 1;
+    }
+
+    /**
+     * Find the first index into the state list where the state is considered ! isActiveRegion
+     *
+     * Note that each state has a probability of being active, and this function thresholds that
+     * value on activeProbThreshold, coloring each state as active or inactive.  Finds the
+     * largest contiguous stretch of states starting at the first state (index 0) with the same isActive
+     * state as isActiveRegion.  If the entire state list has the same isActive value, then returns
+     * maxRegionSize
+     *
+     * @param isActiveRegion are we looking for a stretch of active states, or inactive ones?
+     * @param maxRegionSize don't look for a boundary that would yield a region of size > maxRegionSize
+     * @return the index of the first state in the state list with isActive value != isActiveRegion, or maxRegionSize
+     *         if no such element exists
+     */
+    @Requires({"maxRegionSize > 0"})
+    @Ensures({"result >= 0", "result <= stateList.size()"})
+    private int findFirstActivityBoundary(final boolean isActiveRegion, final int maxRegionSize) {
+        final int nStates = stateList.size();
+        int endOfActiveRegion = 0;
+
+        while ( endOfActiveRegion < nStates && endOfActiveRegion < maxRegionSize ) {
+            if ( getProb(endOfActiveRegion) > activeProbThreshold != isActiveRegion ) {
+                break;
+            }
+            endOfActiveRegion++;
+        }
+
+        return endOfActiveRegion;
+    }
+
+    /**
+     * Helper function to get the probability of the state at offset index
+     * @param index a valid offset into the state list
+     * @return the isActiveProb of the state at index
+     */
+    @Requires({"index >= 0", "index < stateList.size()"})
+    private double getProb(final int index) {
+        return stateList.get(index).isActiveProb;
+    }
+
+    /**
+     * Is the probability at index in a local minimum?
+     *
+     * Checks that the probability at index is <= both the probabilities to either side.
+     * Returns false if index is at the end or the start of the state list.
+     *
+     * @param index the index of the state we want to test
+     * @return true if prob at state is a minimum, false otherwise
+     */
+    @Requires({"index >= 0", "index < stateList.size()"})
+    private boolean isMinimum(final int index) {
+        if ( index == stateList.size() - 1 )
+            // we cannot be at a minimum if the current position is the last in the state list
+            return false;
+        else if ( index < 1 )
+            // we cannot be at a minimum if the current position is the first or second
+            return false;
+        else {
+            final double indexP = getProb(index);
+            return indexP <= getProb(index+1) && indexP < getProb(index-1);
+        }
+    }
+}
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/activeregion/ActivityProfileState.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/activeregion/ActivityProfileState.java
new file mode 100644
index 0000000..915db61
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/activeregion/ActivityProfileState.java
@@ -0,0 +1,112 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.utils.activeregion;
+
+import com.google.java.contract.Ensures;
+import com.google.java.contract.Requires;
+import org.broadinstitute.gatk.utils.GenomeLoc;
+
+/**
+ * The state of an active region walker's isActive call at a specific locus in the genome
+ *
+ * User: rpoplin
+ * Date: 7/27/12
+ */
+public class ActivityProfileState {
+    final private GenomeLoc loc;
+    public double isActiveProb;
+    public Type resultState;
+    public Number resultValue;
+
+    public enum Type {
+        NONE,
+        HIGH_QUALITY_SOFT_CLIPS
+    }
+
+    /**
+     * Create a new ActivityProfileState at loc with probability of being active of isActiveProb
+     *
+     * @param loc the position of the result profile (for debugging purposes)
+     * @param isActiveProb the probability of being active (between 0 and 1)
+     */
+    @Requires({"loc != null", "isActiveProb >= 0.0 && isActiveProb <= 1.0"})
+    public ActivityProfileState(final GenomeLoc loc, final double isActiveProb) {
+        this(loc, isActiveProb, Type.NONE, null);
+    }
+
+    /**
+     * Create a new ActivityProfileState at loc with probability of being active of isActiveProb that maintains some
+     * information about the result state and value
+     *
+     * The only state value in use is HIGH_QUALITY_SOFT_CLIPS, and here the value is interpreted as the number
+     * of bp affected by the soft clips.
+     *
+     * @param loc the position of the result profile (for debugging purposes)
+     * @param isActiveProb the probability of being active (between 0 and 1)
+     */
+    @Requires({"loc != null", "isActiveProb >= 0.0 && isActiveProb <= 1.0"})
+    public ActivityProfileState(final GenomeLoc loc, final double isActiveProb, final Type resultState, final Number resultValue) {
+        // make sure the location of that activity profile is 1
+        if ( loc.size() != 1 )
+            throw new IllegalArgumentException("Location for an ActivityProfileState must have to size 1 bp but saw " + loc);
+        if ( resultValue != null && resultValue.doubleValue() < 0 )
+            throw new IllegalArgumentException("Result value isn't null and its < 0, which is illegal: " + resultValue);
+
+        this.loc = loc;
+        this.isActiveProb = isActiveProb;
+        this.resultState = resultState;
+        this.resultValue = resultValue;
+    }
+
+    /**
+     * The offset of state w.r.t. our current region's start location
+     * @param regionStartLoc the start of the region, as a genome loc
+     * @return the position of this profile relative to the start of this region
+     */
+    public int getOffset(final GenomeLoc regionStartLoc) {
+        return getLoc().getStart() - regionStartLoc.getStart();
+    }
+
+
+    /**
+     * Get the genome loc associated with the ActivityProfileState
+     * @return the location of this result
+     */
+    @Ensures("result != null")
+    public GenomeLoc getLoc() {
+        return loc;
+    }
+
+    @Override
+    public String toString() {
+        return "ActivityProfileState{" +
+                "loc=" + loc +
+                ", isActiveProb=" + isActiveProb +
+                ", resultState=" + resultState +
+                ", resultValue=" + resultValue +
+                '}';
+    }
+}
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/activeregion/BandPassActivityProfile.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/activeregion/BandPassActivityProfile.java
new file mode 100644
index 0000000..52437a8
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/activeregion/BandPassActivityProfile.java
@@ -0,0 +1,194 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.utils.activeregion;
+
+import com.google.java.contract.Ensures;
+import org.broadinstitute.gatk.utils.GenomeLoc;
+import org.broadinstitute.gatk.utils.GenomeLocParser;
+import org.broadinstitute.gatk.utils.GenomeLocSortedSet;
+import org.broadinstitute.gatk.utils.MathUtils;
+
+import java.util.Collection;
+import java.util.LinkedList;
+
+/**
+ * A band pass filtering version of the activity profile
+ *
+ * Applies a band pass filter with a Gaussian kernel to the input state probabilities to smooth
+ * them out of an interval
+ *
+ * @author Mark DePristo
+ * @since 2011
+ */
+public class BandPassActivityProfile extends ActivityProfile {
+    public static final int MAX_FILTER_SIZE = 50;
+    private final static double MIN_PROB_TO_KEEP_IN_FILTER = 1e-5;
+    public static final double DEFAULT_SIGMA = 17.0;
+
+    private final int filterSize;
+    private final double sigma;
+    private final double[] GaussianKernel;
+
+    /**
+     * Create a new BandPassActivityProfile with default sigma and filter sizes
+     *
+     * @see #BandPassActivityProfile(org.broadinstitute.gatk.utils.GenomeLocParser, org.broadinstitute.gatk.utils.GenomeLocSortedSet, int, double, int, double, boolean)
+     */
+    public BandPassActivityProfile(final GenomeLocParser parser, final GenomeLocSortedSet restrictToIntervals,
+                                   final int maxProbPropagationDistance, final double activeProbThreshold) {
+        this(parser, restrictToIntervals, maxProbPropagationDistance, activeProbThreshold, MAX_FILTER_SIZE, DEFAULT_SIGMA);
+    }
+
+    /**
+     * @see #BandPassActivityProfile(org.broadinstitute.gatk.utils.GenomeLocParser, org.broadinstitute.gatk.utils.GenomeLocSortedSet, int, double, int, double, boolean)
+     *
+     * sets adaptiveFilterSize to true
+     */
+    public BandPassActivityProfile(final GenomeLocParser parser, final GenomeLocSortedSet restrictToIntervals,
+                                   final int maxProbPropagationDistance, final double activeProbThreshold,
+                                   final int maxFilterSize, final double sigma) {
+        this(parser, restrictToIntervals, maxProbPropagationDistance, activeProbThreshold, maxFilterSize, sigma, true);
+    }
+
+    /**
+     * Create an activity profile that implements a band pass filter on the states
+     *
+     * @param parser our genome loc parser
+     * @param restrictToIntervals only include states that are within these intervals, if not null
+     * @param maxProbPropagationDistance region probability propagation distance beyond it's maximum size
+     * @param activeProbThreshold  threshold for the probability of a profile state being active
+     * @param maxFilterSize the maximum size of the band pass filter we are allowed to create, regardless of sigma
+     * @param sigma the variance of the Gaussian kernel for this band pass filter
+     * @param adaptiveFilterSize if true, use the kernel itself to determine the best filter size
+     */
+    public BandPassActivityProfile(final GenomeLocParser parser, final GenomeLocSortedSet restrictToIntervals, final int maxProbPropagationDistance,
+                                   final double activeProbThreshold, final int maxFilterSize, final double sigma, final boolean adaptiveFilterSize) {
+        super(parser, maxProbPropagationDistance, activeProbThreshold, restrictToIntervals);
+
+        if ( sigma < 0 ) throw new IllegalArgumentException("Sigma must be greater than or equal to 0 but got " + sigma);
+
+        // setup the Gaussian kernel for the band pass filter
+        this.sigma = sigma;
+        final double[] fullKernel = makeKernel(maxFilterSize, sigma);
+        this.filterSize = adaptiveFilterSize ? determineFilterSize(fullKernel, MIN_PROB_TO_KEEP_IN_FILTER) : maxFilterSize;
+        this.GaussianKernel = makeKernel(this.filterSize, sigma);
+    }
+
+    protected static int determineFilterSize(final double[] kernel, final double minProbToKeepInFilter) {
+        final int middle = (kernel.length - 1) / 2;
+        int filterEnd = middle;
+        while ( filterEnd > 0 ) {
+            if ( kernel[filterEnd - 1] < minProbToKeepInFilter ) {
+                break;
+            }
+            filterEnd--;
+        }
+        return middle - filterEnd;
+    }
+
+    protected static double[] makeKernel(final int filterSize, final double sigma) {
+        final int bandSize = 2 * filterSize + 1;
+        final double[] kernel = new double[bandSize];
+        for( int iii = 0; iii < bandSize; iii++ ) {
+            kernel[iii] = MathUtils.normalDistribution(filterSize, sigma, iii);
+        }
+        return MathUtils.normalizeFromRealSpace(kernel);
+    }
+
+    /**
+     * Our maximize propagation distance is whatever our parent's is, plus our filter size
+     *
+     * Stops the profile from interpreting sites that aren't yet fully determined due to
+     * propagation of the probabilities.
+     *
+     * @return the distance in bp we might move our probabilities around for some site i
+     */
+    @Override
+    public int getMaxProbPropagationDistance() {
+        return super.getMaxProbPropagationDistance() + filterSize;
+    }
+
+    /**
+     * Get the size (in bp) of the band pass filter
+     * @return a positive integer
+     */
+    @Ensures("result >= 1")
+    public int getBandSize() {
+        return 2 * filterSize + 1;
+    }
+
+    /**
+     * Get the filter size (which is the size of each wing of the band, minus the center point)
+     * @return a positive integer
+     */
+    @Ensures("result >= 0")
+    public int getFilteredSize() {
+        return filterSize;
+    }
+
+    /**
+     * Get the Gaussian kernel sigma value
+     * @return a positive double
+     */
+    @Ensures("result >= 0")
+    public double getSigma() {
+        return sigma;
+    }
+
+    /**
+     * Get the kernel of this band pass filter.  Do not modify returned result
+     * @return the kernel used in this band pass filter
+     */
+    @Ensures({"result != null", "result.length == getBandSize()"})
+    protected double[] getKernel() {
+        return GaussianKernel;
+    }
+
+    /**
+     * Band pass the probabilities in the ActivityProfile, producing a new profile that's band pass filtered
+     * @return a new double[] that's the band-pass filtered version of this profile
+     */
+    @Override
+    protected Collection<ActivityProfileState> processState(final ActivityProfileState justAddedState) {
+        final Collection<ActivityProfileState> states = new LinkedList<ActivityProfileState>();
+
+        for ( final ActivityProfileState superState : super.processState(justAddedState) ) {
+            if ( superState.isActiveProb > 0.0 ) {
+                for( int jjj = -filterSize; jjj <= filterSize; jjj++ ) {
+                    final GenomeLoc loc = getLocForOffset(justAddedState.getLoc(), jjj);
+                    if ( loc != null ) {
+                        final double newProb = superState.isActiveProb * GaussianKernel[jjj + filterSize];
+                        states.add(new ActivityProfileState(loc, newProb));
+                    }
+                }
+            } else {
+                states.add(justAddedState);
+            }
+        }
+
+        return states;
+    }
+}
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/analysis/AminoAcid.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/analysis/AminoAcid.java
new file mode 100644
index 0000000..0416609
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/analysis/AminoAcid.java
@@ -0,0 +1,114 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.utils.analysis;
+
+/*
+ * Copyright (c) 2010 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.
+ */
+
+/**
+ * @author chartl
+ * @since June 28, 2010
+ */
+
+public enum AminoAcid {
+    
+    Alanine("Alanine","Ala","A",new String[]{"GCA","GCC","GCG","GCT"}),
+    Arganine("Arganine","Arg","R",new String[]{"AGA","AGG","CGA","CGC","CGG","CGT"}),
+    Asparagine("Asparagine","Asn","N",new String[]{"AAC","AAT"}),
+    Aspartic_acid("Aspartic acid","Asp","D",new String[]{"GAT","GAC"}),
+    Cysteine("Cysteine","Cys","C",new String[]{"TGC","TGC"}),
+    Glutamic_acid("Glutamic acid","Glu","E",new String[]{"GAA","GAG"}),
+    Glutamine("Glutamine","Gln","Q",new String[]{"CAA","CAG"}),
+    Glycine("Glycine","Gly","G",new String[]{"GGA","GGC","GGG","GGT"}),
+    Histidine("Histidine","His","H",new String[]{"CAC","CAT"}),
+    Isoleucine("Isoleucine","Ile","I",new String[]{"ATA","ATC","ATT"}),
+    Leucine("Leucine","Leu","L",new String[]{"CTA","CTC","CTG","CTT","TTA","TTG"}),
+    Lysine("Lysine","Lys","K", new String[]{"AAA","AAG"}),
+    Methionine("Methionine","Met","M",new String[]{"ATG"}),
+    Phenylalanine("Phenylalanine","Phe","F",new String[]{"TTC","TTT"}),
+    Proline("Proline","Pro","P",new String[]{"CCA","CCC","CCG","CCT"}),
+    Serine("Serine","Ser","S",new String[]{"AGC","AGT","TCA","TCC","TCG","TCT"}),
+    Stop_codon("Stop codon","Stop","*",new String[]{"TAA","TAG","TGA"}),
+    Threonine("Threonine","Thr","T",new String[]{"ACA","ACC","ACG","ACT"}),
+    Tryptophan("Tryptophan","Trp","W",new String[]{"TGG"}),
+    Tyrosine("Tyrosine","Tyr","Y",new String[]{"TAC","TAT"}),
+    Valine("Valine","Val","V",new String[]{"GTA","GTC","GTG","GTT"});
+
+    String[] codons;
+    String fullName;
+    String code;
+    String letter;
+
+    AminoAcid(String name, String shortName, String abbrev, String[] myCodons) {
+        codons = myCodons;
+        fullName = name;
+        code = shortName;
+        letter = abbrev;
+    }
+
+    public String getName() {
+        return fullName;
+    }
+
+    public String getLetter() {
+        return letter;
+    }
+
+    public String getCode() {
+        return code;
+    }
+
+    public boolean isStop() {
+        return this == Stop_codon;
+    }
+
+    public String toString() {
+        return getName();
+    }
+    
+}
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/analysis/AminoAcidTable.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/analysis/AminoAcidTable.java
new file mode 100644
index 0000000..7cd8933
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/analysis/AminoAcidTable.java
@@ -0,0 +1,94 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.utils.analysis;
+
+import java.util.HashMap;
+
+/*
+ * Copyright (c) 2010 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.
+ */
+
+/**
+ * @author chartl
+ * @since June 28, 2010
+ */
+
+public class AminoAcidTable {
+    public HashMap<String,AminoAcid> tableByCodon = new HashMap<String,AminoAcid>(21);
+    public HashMap<String,AminoAcid> tableByCode = new HashMap<String,AminoAcid>(21);
+    public AminoAcidTable() {
+        for ( AminoAcid acid : AminoAcid.values() ) {
+            tableByCode.put(acid.getCode(),acid);
+            for ( String codon : acid.codons ) {
+                tableByCodon.put(codon,acid);
+            }
+        }
+    }
+
+    // todo -- these functions are for the genomic annotator and are named too generally -- they are
+    // todo -- actually accessors by codon; thus should be more specific.
+    public AminoAcid getEukaryoticAA(String codon) {
+        return tableByCodon.get(codon.toUpperCase());
+    }
+
+    public AminoAcid getMitochondrialAA(String codon, boolean isFirst) {
+        String upperCodon = codon.toUpperCase();
+        if ( isFirst && upperCodon.equals("ATT") || upperCodon.equals("ATA") ) {
+            return AminoAcid.Methionine;
+        } else if ( upperCodon.equals("AGA") || upperCodon.equals("AGG") ) {
+            return AminoAcid.Stop_codon;
+        } else if ( upperCodon.equals("TGA") ) {
+            return AminoAcid.Tryptophan;
+        } else {
+            return tableByCodon.get(upperCodon);
+        }
+    }
+
+    public AminoAcid getAminoAcidByCode(String code) {
+        return tableByCode.get(code);
+    }
+}
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/analysis/AminoAcidUtils.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/analysis/AminoAcidUtils.java
new file mode 100644
index 0000000..9213e82
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/analysis/AminoAcidUtils.java
@@ -0,0 +1,77 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.utils.analysis;
+
+/*
+ * Copyright (c) 2010 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.
+ */
+
+/**
+ * @author chartl
+ * @since June 28, 2010
+ */
+
+public class AminoAcidUtils {
+
+    public static String[] getAminoAcidNames() {
+        String[] names = new String[AminoAcid.values().length];
+        for ( AminoAcid acid : AminoAcid.values() ) {
+            names[acid.ordinal()] = acid.getName();
+        }
+
+        return names;
+    }
+
+    public static String[] getAminoAcidCodes() {
+        String[] codes = new String[AminoAcid.values().length];
+        for ( AminoAcid acid : AminoAcid.values() ) {
+            codes[acid.ordinal()] = acid.getCode();
+        }
+
+        return codes;
+    }
+}
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/baq/BAQ.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/baq/BAQ.java
new file mode 100644
index 0000000..da8d00e
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/baq/BAQ.java
@@ -0,0 +1,713 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.utils.baq;
+
+import htsjdk.samtools.reference.IndexedFastaSequenceFile;
+import htsjdk.samtools.reference.ReferenceSequence;
+import htsjdk.samtools.CigarElement;
+import htsjdk.samtools.CigarOperator;
+import htsjdk.samtools.SAMRecord;
+import htsjdk.samtools.SAMUtils;
+import org.apache.log4j.Logger;
+import org.broadinstitute.gatk.utils.collections.Pair;
+import org.broadinstitute.gatk.utils.exceptions.ReviewedGATKException;
+import org.broadinstitute.gatk.utils.exceptions.UserException;
+import org.broadinstitute.gatk.utils.sam.ReadUtils;
+
+/*
+  The topology of the profile HMM:
+
+           /\             /\        /\             /\
+           I[1]           I[k-1]    I[k]           I[L]
+            ^   \      \    ^    \   ^   \      \   ^
+            |    \      \   |     \  |    \      \  |
+    M[0]   M[1] -> ... -> M[k-1] -> M[k] -> ... -> M[L]   M[L+1]
+                \      \/        \/      \/      /
+                 \     /\        /\      /\     /
+                       -> D[k-1] -> D[k] ->
+
+   M[0] points to every {M,I}[k] and every {M,I}[k] points M[L+1].
+
+   On input, _ref is the reference sequence and _query is the query
+   sequence. Both are sequences of 0/1/2/3/4 where 4 stands for an
+   ambiguous residue. iqual is the base quality. c sets the gap open
+   probability, gap extension probability and band width.
+
+   On output, state and q are arrays of length l_query. The higher 30
+   bits give the reference position the query base is matched to and the
+   lower two bits can be 0 (an alignment match) or 1 (an
+   insertion). q[i] gives the phred scaled posterior probability of
+   state[i] being wrong.
+ */
+public class BAQ {
+    private final static Logger logger = Logger.getLogger(BAQ.class);
+    private final static boolean DEBUG = false;
+
+    public enum CalculationMode {
+        OFF,                        // don't apply BAQ at all, the default
+        CALCULATE_AS_NECESSARY,     // do HMM BAQ calculation on the fly, as necessary, if there's no tag
+        RECALCULATE                 // do HMM BAQ calculation on the fly, regardless of whether there's a tag present
+    }
+
+    /** these are features that only the walker can override */
+    public enum QualityMode {
+        ADD_TAG,                    // calculate the BAQ, but write it into the reads as the BAQ tag, leaving QUAL field alone
+        OVERWRITE_QUALS,            // overwrite the quality field directly
+        DONT_MODIFY                 // do the BAQ, but don't modify the quality scores themselves, just return them in the function.
+    }
+
+    public static final String BAQ_TAG = "BQ";
+
+    private static double[] qual2prob = new double[256];
+    static {
+        for (int i = 0; i < 256; ++i)
+            qual2prob[i] = Math.pow(10, -i/10.);
+    }
+
+    // Phred scaled now (changed 1/10/2011)
+    public static final double DEFAULT_GOP = 40;
+
+    /*  Takes a Phred Scale quality score and returns the error probability.
+     *
+     *  Quick conversion function to maintain internal structure of BAQ calculation on
+     *  probability scale, but take the user entered parameter in phred-scale.
+     *
+     *  @param x phred scaled score
+     *  @return probability of incorrect base call
+     */
+    private double convertFromPhredScale(double x) { return (Math.pow(10,(-x)/10.));}
+
+    public double cd = -1;      // gap open probability [1e-3]
+    private double ce = 0.1;    // gap extension probability [0.1]
+	private int cb = 7;         // band width [7]
+    private boolean includeClippedBases = false;
+
+    public byte getMinBaseQual() {
+        return minBaseQual;
+    }
+
+    /**
+     * Any bases with Q < MIN_BASE_QUAL are raised up to this base quality
+     */
+    private byte minBaseQual = 4;
+
+    public double getGapOpenProb() {
+        return cd;
+    }
+
+    public double getGapExtensionProb() {
+        return ce;
+    }
+
+    public int getBandWidth() {
+        return cb;
+    }
+
+    /**
+     * Use defaults for everything
+     */
+    public BAQ() {
+        this(DEFAULT_GOP);
+    }
+
+    /**
+     * Use defaults for everything
+     */
+    public BAQ(final double gapOpenPenalty) {
+        cd = convertFromPhredScale(gapOpenPenalty);
+        initializeCachedData();
+    }
+
+
+
+    /**
+     * Create a new HmmGlocal object with specified parameters
+     *
+     * @param d gap open prob (not phred scaled!).
+     * @param e gap extension prob.
+     * @param b band width
+     * @param minBaseQual All bases with Q < minBaseQual are up'd to this value
+     */
+	public BAQ(final double d, final double e, final int b, final byte minBaseQual, boolean includeClippedBases) {
+		cd = d; ce = e; cb = b;
+        this.minBaseQual = minBaseQual;
+        this.includeClippedBases = includeClippedBases;
+        initializeCachedData();
+	}
+
+    private final static double EM = 0.33333333333;
+    private final static double EI = 0.25;
+
+    private double[][][] EPSILONS = new double[256][256][SAMUtils.MAX_PHRED_SCORE+1];
+
+    private void initializeCachedData() {
+        for ( int i = 0; i < 256; i++ )
+            for ( int j = 0; j < 256; j++ )
+                for ( int q = 0; q <= SAMUtils.MAX_PHRED_SCORE; q++ ) {
+                    EPSILONS[i][j][q] = 1.0;
+                }
+
+        for ( char b1 : "ACGTacgt".toCharArray() ) {
+            for ( char b2 : "ACGTacgt".toCharArray() ) {
+                for ( int q = 0; q <= SAMUtils.MAX_PHRED_SCORE; q++ ) {
+                    double qual = qual2prob[q < minBaseQual ? minBaseQual : q];
+                    double e = Character.toLowerCase(b1) == Character.toLowerCase(b2) ? 1 - qual : qual * EM;
+                    EPSILONS[(byte)b1][(byte)b2][q] = e;
+                }
+            }
+        }
+    }
+
+    protected double calcEpsilon( byte ref, byte read, byte qualB ) {
+        return EPSILONS[ref][read][qualB];
+    }
+
+    // ####################################################################################################
+    //
+    // NOTE -- THIS CODE IS SYNCHRONIZED WITH CODE IN THE SAMTOOLS REPOSITORY.  CHANGES TO THIS CODE SHOULD BE
+    // NOTE -- PUSHED BACK TO HENG LI
+    //
+    // ####################################################################################################
+    public int hmm_glocal(final byte[] ref, final byte[] query, int qstart, int l_query, final byte[] _iqual, int[] state, byte[] q) {
+        if ( ref == null ) throw new ReviewedGATKException("BUG: ref sequence is null");
+        if ( query == null ) throw new ReviewedGATKException("BUG: query sequence is null");
+        if ( _iqual == null ) throw new ReviewedGATKException("BUG: query quality vector is null");
+        if ( query.length != _iqual.length ) throw new ReviewedGATKException("BUG: read sequence length != qual length");
+        if ( l_query < 1 ) throw new ReviewedGATKException("BUG: length of query sequence < 0: " + l_query);
+        if ( qstart < 0 ) throw new ReviewedGATKException("BUG: query sequence start < 0: " + qstart);
+
+        //if ( q != null && q.length != state.length ) throw new ReviewedGATKException("BUG: BAQ quality length != read sequence length");
+        //if ( state != null && state.length != l_query ) throw new ReviewedGATKException("BUG: state length != read sequence length");
+
+		int i, k;
+
+        /*** initialization ***/
+		// change coordinates
+		final int l_ref = ref.length;
+
+		// set band width
+		int bw2, bw = l_ref > l_query? l_ref : l_query;
+        if (cb < Math.abs(l_ref - l_query)) {
+            bw = Math.abs(l_ref - l_query) + 3;
+            //System.out.printf("SC  cb=%d, bw=%d%n", cb, bw);
+        }
+        if (bw > cb) bw = cb;
+		if (bw < Math.abs(l_ref - l_query)) {
+            //int bwOld = bw;
+            bw = Math.abs(l_ref - l_query);
+            //System.out.printf("old bw is %d, new is %d%n", bwOld, bw);
+        }
+        //System.out.printf("c->bw = %d, bw = %d, l_ref = %d, l_query = %d\n", cb, bw, l_ref, l_query);
+		bw2 = bw * 2 + 1;
+
+        // allocate the forward and backward matrices f[][] and b[][] and the scaling array s[]
+		double[][] f = new double[l_query+1][bw2*3 + 6];
+		double[][] b = new double[l_query+1][bw2*3 + 6];
+		double[] s = new double[l_query+2];
+
+		// initialize transition probabilities
+		double sM, sI, bM, bI;
+		sM = sI = 1. / (2 * l_query + 2);
+        bM = (1 - cd) / l_ref; bI = cd / l_ref; // (bM+bI)*l_ref==1
+
+		double[] m = new double[9];
+		m[0*3+0] = (1 - cd - cd) * (1 - sM); m[0*3+1] = m[0*3+2] = cd * (1 - sM);
+		m[1*3+0] = (1 - ce) * (1 - sI); m[1*3+1] = ce * (1 - sI); m[1*3+2] = 0.;
+		m[2*3+0] = 1 - ce; m[2*3+1] = 0.; m[2*3+2] = ce;
+
+
+		/*** forward ***/
+		// f[0]
+		f[0][set_u(bw, 0, 0)] = s[0] = 1.;
+		{ // f[1]
+			double[] fi = f[1];
+			double sum;
+			int beg = 1, end = l_ref < bw + 1? l_ref : bw + 1, _beg, _end;
+			for (k = beg, sum = 0.; k <= end; ++k) {
+				int u;
+                double e = calcEpsilon(ref[k-1], query[qstart], _iqual[qstart]);
+				u = set_u(bw, 1, k);
+				fi[u+0] = e * bM; fi[u+1] = EI * bI;
+				sum += fi[u] + fi[u+1];
+			}
+			// rescale
+			s[1] = sum;
+			_beg = set_u(bw, 1, beg); _end = set_u(bw, 1, end); _end += 2;
+			for (k = _beg; k <= _end; ++k) fi[k] /= sum;
+		}
+
+		// f[2..l_query]
+		for (i = 2; i <= l_query; ++i) {
+			double[] fi = f[i], fi1 = f[i-1];
+			double sum;
+			int beg = 1, end = l_ref, x, _beg, _end;
+			byte qyi = query[qstart+i-1];
+			x = i - bw; beg = beg > x? beg : x; // band start
+			x = i + bw; end = end < x? end : x; // band end
+			for (k = beg, sum = 0.; k <= end; ++k) {
+				int u, v11, v01, v10;
+                double e = calcEpsilon(ref[k-1], qyi, _iqual[qstart+i-1]);
+				u = set_u(bw, i, k); v11 = set_u(bw, i-1, k-1); v10 = set_u(bw, i-1, k); v01 = set_u(bw, i, k-1);
+				fi[u+0] = e * (m[0] * fi1[v11+0] + m[3] * fi1[v11+1] + m[6] * fi1[v11+2]);
+				fi[u+1] = EI * (m[1] * fi1[v10+0] + m[4] * fi1[v10+1]);
+				fi[u+2] = m[2] * fi[v01+0] + m[8] * fi[v01+2];
+				sum += fi[u] + fi[u+1] + fi[u+2];
+				//System.out.println("("+i+","+k+";"+u+"): "+fi[u]+","+fi[u+1]+","+fi[u+2]);
+			}
+			// rescale
+			s[i] = sum;
+			_beg = set_u(bw, i, beg); _end = set_u(bw, i, end); _end += 2;
+			for (k = _beg, sum = 1./sum; k <= _end; ++k) fi[k] *= sum;
+		}
+		{ // f[l_query+1]
+			double sum;
+			for (k = 1, sum = 0.; k <= l_ref; ++k) {
+				int u = set_u(bw, l_query, k);
+				if (u < 3 || u >= bw2*3+3) continue;
+				sum += f[l_query][u+0] * sM + f[l_query][u+1] * sI;
+			}
+			s[l_query+1] = sum; // the last scaling factor
+		}
+
+		/*** backward ***/
+		// b[l_query] (b[l_query+1][0]=1 and thus \tilde{b}[][]=1/s[l_query+1]; this is where s[l_query+1] comes from)
+		for (k = 1; k <= l_ref; ++k) {
+			int u = set_u(bw, l_query, k);
+			double[] bi = b[l_query];
+			if (u < 3 || u >= bw2*3+3) continue;
+			bi[u+0] = sM / s[l_query] / s[l_query+1]; bi[u+1] = sI / s[l_query] / s[l_query+1];
+		}
+		// b[l_query-1..1]
+		for (i = l_query - 1; i >= 1; --i) {
+			int beg = 1, end = l_ref, x, _beg, _end;
+			double[] bi = b[i], bi1 = b[i+1];
+			double y = (i > 1)? 1. : 0.;
+			byte qyi1 = query[qstart+i];
+			x = i - bw; beg = beg > x? beg : x;
+			x = i + bw; end = end < x? end : x;
+			for (k = end; k >= beg; --k) {
+				int u, v11, v01, v10;
+				u = set_u(bw, i, k); v11 = set_u(bw, i+1, k+1); v10 = set_u(bw, i+1, k); v01 = set_u(bw, i, k+1);
+                final double e = (k >= l_ref? 0 : calcEpsilon(ref[k], qyi1, _iqual[qstart+i])) * bi1[v11];
+                bi[u+0] = e * m[0] + EI * m[1] * bi1[v10+1] + m[2] * bi[v01+2]; // bi1[v11] has been folded into e.
+				bi[u+1] = e * m[3] + EI * m[4] * bi1[v10+1];
+				bi[u+2] = (e * m[6] + m[8] * bi[v01+2]) * y;
+			}
+			// rescale
+			_beg = set_u(bw, i, beg); _end = set_u(bw, i, end); _end += 2;
+			for (k = _beg, y = 1./s[i]; k <= _end; ++k) bi[k] *= y;
+		}
+
+ 		double pb;
+		{ // b[0]
+			int beg = 1, end = l_ref < bw + 1? l_ref : bw + 1;
+			double sum = 0.;
+			for (k = end; k >= beg; --k) {
+				int u = set_u(bw, 1, k);
+                double e = calcEpsilon(ref[k-1], query[qstart], _iqual[qstart]);
+                if (u < 3 || u >= bw2*3+3) continue;
+				sum += e * b[1][u+0] * bM + EI * b[1][u+1] * bI;
+			}
+			pb = b[0][set_u(bw, 0, 0)] = sum / s[0]; // if everything works as is expected, pb == 1.0
+		}
+
+        
+		/*** MAP ***/
+		for (i = 1; i <= l_query; ++i) {
+			double sum = 0., max = 0.;
+			final double[] fi = f[i], bi = b[i];
+			int beg = 1, end = l_ref, x, max_k = -1;
+			x = i - bw; beg = beg > x? beg : x;
+			x = i + bw; end = end < x? end : x;
+			for (k = beg; k <= end; ++k) {
+				final int u = set_u(bw, i, k);
+				double z;
+				sum += (z = fi[u+0] * bi[u+0]); if (z > max) { max = z; max_k = (k-1)<<2 | 0; }
+				sum += (z = fi[u+1] * bi[u+1]); if (z > max) { max = z; max_k = (k-1)<<2 | 1; }
+			}
+			max /= sum; sum *= s[i]; // if everything works as is expected, sum == 1.0
+			if (state != null) state[qstart+i-1] = max_k;
+			if (q != null) {
+				k = (int)(-4.343 * Math.log(1. - max) + .499); // = 10*log10(1-max)
+				q[qstart+i-1] = (byte)(k > 100? 99 : (k < minBaseQual ? minBaseQual : k));
+			}
+			//System.out.println("("+pb+","+sum+")"+" ("+(i-1)+","+(max_k>>2)+","+(max_k&3)+","+max+")");
+		}
+
+		return 0;
+	}
+
+    // ---------------------------------------------------------------------------------------------------------------
+    //
+    // Helper routines
+    //
+    // ---------------------------------------------------------------------------------------------------------------
+
+    /** decode the bit encoded state array values */
+    public static boolean stateIsIndel(int state) {
+        return (state & 3) != 0;
+    }
+
+    /** decode the bit encoded state array values */
+    public static int stateAlignedPosition(int state) {
+        return state >> 2;
+    }
+
+    /**
+     * helper routine for hmm_glocal
+     *
+     * @param b
+     * @param i
+     * @param k
+     * @return
+     */
+    private static int set_u(final int b, final int i, final int k) {
+		int x = i - b;
+		x = x > 0 ? x : 0;
+		return (k + 1 - x) * 3;
+	}
+
+    // ---------------------------------------------------------------------------------------------------------------
+    //
+    // Actually working with the BAQ tag now
+    //
+    // ---------------------------------------------------------------------------------------------------------------
+    
+    /**
+     * Get the BAQ attribute from the tag in read.  Returns null if no BAQ tag is present.
+     * @param read
+     * @return
+     */
+    public static byte[] getBAQTag(SAMRecord read) {
+        String s = read.getStringAttribute(BAQ_TAG);
+        return s != null ? s.getBytes() : null;
+    }
+
+    public static String encodeBQTag(SAMRecord read, byte[] baq) {
+        // Offset to base alignment quality (BAQ), of the same length as the read sequence.
+        // At the i-th read base, BAQi = Qi - (BQi - 64) where Qi is the i-th base quality.
+        // so BQi = Qi - BAQi + 64
+        byte[] bqTag = new byte[baq.length];
+        for ( int i = 0; i < bqTag.length; i++) {
+            final int bq = (int)read.getBaseQualities()[i] + 64;
+            final int baq_i = (int)baq[i];
+            final int tag = bq - baq_i;
+            // problem with the calculation of the correction factor; this is our problem
+            if ( tag < 0 )
+                throw new ReviewedGATKException("BAQ tag calculation error.  BAQ value above base quality at " + read);
+            // the original quality is too high, almost certainly due to using the wrong encoding in the BAM file
+            if ( tag > Byte.MAX_VALUE )
+                throw new UserException.MisencodedBAM(read, "we encountered an extremely high quality score (" + (int)read.getBaseQualities()[i] + ") with BAQ correction factor of " + baq_i);
+            bqTag[i] = (byte)tag;
+        }
+        return new String(bqTag);
+    }
+
+    public static void addBAQTag(SAMRecord read, byte[] baq) {
+        read.setAttribute(BAQ_TAG, encodeBQTag(read, baq));
+    }
+
+
+    /**
+      * Returns true if the read has a BAQ tag, or false otherwise
+      * @param read
+      * @return
+      */
+    public static boolean hasBAQTag(SAMRecord read) {
+        return read.getStringAttribute(BAQ_TAG) != null;
+    }
+
+    /**
+     * Returns a new qual array for read that includes the BAQ adjustment.  Does not support on-the-fly BAQ calculation
+     *
+     * @param read the SAMRecord to operate on
+     * @param overwriteOriginalQuals If true, we replace the original qualities scores in the read with their BAQ'd version
+     * @param useRawQualsIfNoBAQTag If useRawQualsIfNoBAQTag is true, then if there's no BAQ annotation we just use the raw quality scores.  Throws IllegalStateException is false and no BAQ tag is present
+     * @return
+     */
+    public static byte[] calcBAQFromTag(SAMRecord read, boolean overwriteOriginalQuals, boolean useRawQualsIfNoBAQTag) {
+        byte[] rawQuals = read.getBaseQualities();
+        byte[] newQuals = rawQuals;
+        byte[] baq = getBAQTag(read);
+
+        if ( baq != null ) {
+            // Offset to base alignment quality (BAQ), of the same length as the read sequence.
+            // At the i-th read base, BAQi = Qi - (BQi - 64) where Qi is the i-th base quality.
+            newQuals = overwriteOriginalQuals ? rawQuals : new byte[rawQuals.length];
+            for ( int i = 0; i < rawQuals.length; i++) {
+                int rawQual = (int)rawQuals[i];
+                int baq_delta = (int)baq[i] - 64;
+                int newval =  rawQual - baq_delta;
+                if ( newval < 0 )
+                    throw new UserException.MalformedBAM(read, "BAQ tag error: the BAQ value is larger than the base quality");
+                newQuals[i] = (byte)newval;
+            }
+        } else if ( ! useRawQualsIfNoBAQTag ) {
+            throw new IllegalStateException("Required BAQ tag to be present, but none was on read " + read.getReadName());
+        }
+
+        return newQuals;
+    }
+
+    /**
+     * Returns the BAQ adjusted quality score for this read at this offset.  Does not support on-the-fly BAQ calculation
+     *
+     * @param read the SAMRecord to operate on
+     * @param offset the offset of operate on
+     * @param useRawQualsIfNoBAQTag If useRawQualsIfNoBAQTag is true, then if there's no BAQ annotation we just use the raw quality scores.  Throws IllegalStateException is false and no BAQ tag is present
+     * @return
+     */
+    public static byte calcBAQFromTag(SAMRecord read, int offset, boolean useRawQualsIfNoBAQTag) {
+        byte rawQual = read.getBaseQualities()[offset];
+        byte newQual = rawQual;
+        byte[] baq = getBAQTag(read);
+
+        if ( baq != null ) {
+            // Offset to base alignment quality (BAQ), of the same length as the read sequence.
+            // At the i-th read base, BAQi = Qi - (BQi - 64) where Qi is the i-th base quality.
+            int baq_delta = (int)baq[offset] - 64;
+            int newval =  rawQual - baq_delta;
+            if ( newval < 0 )
+                throw new UserException.MalformedBAM(read, "BAQ tag error: the BAQ value is larger than the base quality");
+            newQual = (byte)newval;
+        
+        } else if ( ! useRawQualsIfNoBAQTag ) {
+            throw new IllegalStateException("Required BAQ tag to be present, but none was on read " + read.getReadName());
+        }
+
+        return newQual;
+    }
+
+    public static class BAQCalculationResult {
+        public byte[] refBases, rawQuals, readBases, bq;
+        public int[] state;
+
+        public BAQCalculationResult(SAMRecord read, byte[] ref) {
+            this(read.getBaseQualities(), read.getReadBases(), ref);
+        }
+
+        public BAQCalculationResult(byte[] bases, byte[] quals, byte[] ref) {
+            // prepares data for calculation
+            rawQuals = quals;
+            readBases = bases;
+
+            // now actually prepare the data structures, and fire up the hmm
+            bq = new byte[rawQuals.length];
+            state = new int[rawQuals.length];
+            this.refBases = ref;
+        }
+    }
+
+     public BAQCalculationResult calcBAQFromHMM(SAMRecord read, IndexedFastaSequenceFile refReader) {
+        // start is alignment start - band width / 2 - size of first I element, if there is one.  Stop is similar
+        int offset = getBandWidth() / 2;
+        long readStart = includeClippedBases ? read.getUnclippedStart() : read.getAlignmentStart();
+        long start = Math.max(readStart - offset - ReadUtils.getFirstInsertionOffset(read), 0);
+        long stop = (includeClippedBases ? read.getUnclippedEnd() : read.getAlignmentEnd()) + offset + ReadUtils.getLastInsertionOffset(read);
+
+        if ( stop > refReader.getSequenceDictionary().getSequence(read.getReferenceName()).getSequenceLength() ) {
+            return null;
+        } else {
+            // now that we have the start and stop, get the reference sequence covering it
+            ReferenceSequence refSeq = refReader.getSubsequenceAt(read.getReferenceName(), start, stop);
+            return calcBAQFromHMM(read, refSeq.getBases(), (int)(start - readStart));
+        }
+    }
+
+//    final SimpleTimer total = new SimpleTimer();
+//    final SimpleTimer local = new SimpleTimer();
+//    int n = 0;
+    public BAQCalculationResult calcBAQFromHMM(byte[] ref, byte[] query, byte[] quals, int queryStart, int queryEnd ) {
+//        total.restart();
+        if ( queryStart < 0 ) throw new ReviewedGATKException("BUG: queryStart < 0: " + queryStart);
+        if ( queryEnd < 0 ) throw new ReviewedGATKException("BUG: queryEnd < 0: " + queryEnd);
+        if ( queryEnd < queryStart ) throw new ReviewedGATKException("BUG: queryStart < queryEnd : " + queryStart + " end =" + queryEnd);
+
+        // note -- assumes ref is offset from the *CLIPPED* start
+        BAQCalculationResult baqResult = new BAQCalculationResult(query, quals, ref);
+        int queryLen = queryEnd - queryStart;
+//        local.restart();
+        hmm_glocal(baqResult.refBases, baqResult.readBases, queryStart, queryLen, baqResult.rawQuals, baqResult.state, baqResult.bq);
+//        local.stop();
+//        total.stop();
+//        if ( n++ % 100000 == 0 )
+//            logger.info("n = " + n + ": Total " + total.getElapsedTimeNano() + " local " + local.getElapsedTimeNano());
+        return baqResult;
+    }
+
+
+    /**
+     * Determine the appropriate start and stop offsets in the reads for the bases given the cigar string
+     * @param read
+     * @return
+     */
+    private final Pair<Integer,Integer> calculateQueryRange(SAMRecord read) {
+        int queryStart = -1, queryStop = -1;
+        int readI = 0;
+
+        // iterate over the cigar elements to determine the start and stop of the read bases for the BAQ calculation
+        for ( CigarElement elt : read.getCigar().getCigarElements() ) {
+            switch (elt.getOperator()) {
+                case N:  return null; // cannot handle these
+                case H : case P : case D: break; // ignore pads, hard clips, and deletions
+                case I : case S: case M: case EQ: case X:
+                    int prev = readI;
+                    readI += elt.getLength();
+                    if ( includeClippedBases || elt.getOperator() != CigarOperator.S) {
+                        if ( queryStart == -1 )
+                            queryStart = prev;
+                        queryStop = readI;
+                    }
+                    // in the else case we aren't including soft clipped bases, so we don't update
+                    // queryStart or queryStop
+                    break;
+                default: throw new ReviewedGATKException("BUG: Unexpected CIGAR element " + elt + " in read " + read.getReadName());
+            }
+        }
+
+        if ( queryStop == queryStart ) {
+            // this read is completely clipped away, and yet is present in the file for some reason
+            // usually they are flagged as non-PF, but it's possible to push them through the BAM
+            //System.err.printf("WARNING -- read is completely clipped away: " + read.format());
+            return null;
+        }
+
+        return new Pair<Integer, Integer>(queryStart, queryStop);
+    }
+
+    // we need to pad ref by at least the bandwidth / 2 on either side
+    public BAQCalculationResult calcBAQFromHMM(SAMRecord read, byte[] ref, int refOffset) {
+        // todo -- need to handle the case where the cigar sum of lengths doesn't cover the whole read
+        Pair<Integer, Integer> queryRange = calculateQueryRange(read);
+        if ( queryRange == null ) return null; // read has Ns, or is completely clipped away
+
+        int queryStart = queryRange.getFirst();
+        int queryEnd = queryRange.getSecond();
+
+        BAQCalculationResult baqResult = calcBAQFromHMM(ref, read.getReadBases(), read.getBaseQualities(), queryStart, queryEnd);
+
+        // cap quals
+        int readI = 0, refI = 0;
+        for ( CigarElement elt : read.getCigar().getCigarElements() ) {
+            int l = elt.getLength();
+            switch (elt.getOperator()) {
+                case N: // cannot handle these
+                    return null;
+                case H : case P : // ignore pads and hard clips
+                    break;
+                case S : refI += l; // move the reference too, in addition to I
+                case I :
+                    // todo -- is it really the case that we want to treat I and S the same?
+                    for ( int i = readI; i < readI + l; i++ ) baqResult.bq[i] = baqResult.rawQuals[i];
+                    readI += l;
+                    break;
+                case D : refI += l; break;
+                case M :
+                    for (int i = readI; i < readI + l; i++) {
+                        int expectedPos = refI - refOffset + (i - readI);
+                        baqResult.bq[i] = capBaseByBAQ( baqResult.rawQuals[i], baqResult.bq[i], baqResult.state[i], expectedPos );
+                    }
+                    readI += l; refI += l;
+                    break;
+                default:
+                    throw new ReviewedGATKException("BUG: Unexpected CIGAR element " + elt + " in read " + read.getReadName());
+            }
+        }
+        if ( readI != read.getReadLength() ) // odd cigar string
+            System.arraycopy(baqResult.rawQuals, 0, baqResult.bq, 0, baqResult.bq.length);
+
+        return baqResult;
+    }
+
+    public byte capBaseByBAQ( byte oq, byte bq, int state, int expectedPos ) {
+        byte b;
+        boolean isIndel = stateIsIndel(state);
+        int pos = stateAlignedPosition(state);
+        if ( isIndel || pos != expectedPos ) // we are an indel or we don't align to our best current position
+            b = minBaseQual; // just take b = minBaseQuality
+        else
+            b = bq < oq ? bq : oq;
+
+        return b;
+    }
+
+    /**
+     * Modifies read in place so that the base quality scores are capped by the BAQ calculation.  Uses the BAQ
+     * tag if present already and alwaysRecalculate is false, otherwise fires up the HMM and does the BAQ on the fly
+     * using the refReader to obtain the reference bases as needed.
+     * 
+     * @param read
+     * @param refReader
+     * @param calculationType
+     * @return BQ qualities for use, in case qmode is DONT_MODIFY
+     */
+    public byte[] baqRead(SAMRecord read, IndexedFastaSequenceFile refReader, CalculationMode calculationType, QualityMode qmode ) {
+        if ( DEBUG ) System.out.printf("BAQ %s read %s%n", calculationType, read.getReadName());
+
+        byte[] BAQQuals = read.getBaseQualities();      // in general we are overwriting quals, so just get a pointer to them
+        if ( calculationType == CalculationMode.OFF) { // we don't want to do anything
+            ; // just fall though
+        } else if ( excludeReadFromBAQ(read) ) {
+            ; // just fall through
+        } else {
+            final boolean readHasBAQTag = hasBAQTag(read);
+
+            if ( calculationType == CalculationMode.RECALCULATE || ! readHasBAQTag ) {
+                if ( DEBUG ) System.out.printf("  Calculating BAQ on the fly%n");
+                BAQCalculationResult hmmResult = calcBAQFromHMM(read, refReader);
+                if ( hmmResult != null ) {
+                    switch ( qmode ) {
+                        case ADD_TAG:         addBAQTag(read, hmmResult.bq); break;
+                        case OVERWRITE_QUALS: System.arraycopy(hmmResult.bq, 0, read.getBaseQualities(), 0, hmmResult.bq.length); break;
+                        case DONT_MODIFY:     BAQQuals = hmmResult.bq; break;
+                        default:              throw new ReviewedGATKException("BUG: unexpected qmode " + qmode);
+                    }
+                } else if ( readHasBAQTag ) {
+                    // remove the BAQ tag if it's there because we cannot trust it
+                    read.setAttribute(BAQ_TAG, null);
+                }
+            } else if ( qmode == QualityMode.OVERWRITE_QUALS ) { // only makes sense if we are overwriting quals
+                if ( DEBUG ) System.out.printf("  Taking BAQ from tag%n");
+                // this overwrites the original qualities
+                calcBAQFromTag(read, true, false);
+            }
+        }
+
+        return BAQQuals;
+    }
+
+    /**
+     * Returns true if we don't think this read is eligible for the BAQ calculation.  Examples include non-PF reads,
+     * duplicates, or unmapped reads.  Used by baqRead to determine if a read should fall through the calculation.
+     *
+     * @param read
+     * @return
+     */
+    public boolean excludeReadFromBAQ(SAMRecord read) {
+        // keeping mapped reads, regardless of pairing status, or primary alignment status.
+        return read.getReadUnmappedFlag() || read.getReadFailsVendorQualityCheckFlag() || read.getDuplicateReadFlag();
+    }
+}
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/baq/BAQReadTransformer.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/baq/BAQReadTransformer.java
new file mode 100644
index 0000000..c9192e1
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/baq/BAQReadTransformer.java
@@ -0,0 +1,74 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.utils.baq;
+
+import htsjdk.samtools.reference.IndexedFastaSequenceFile;
+import org.broadinstitute.gatk.engine.GenomeAnalysisEngine;
+import org.broadinstitute.gatk.engine.WalkerManager;
+import org.broadinstitute.gatk.engine.iterators.ReadTransformer;
+import org.broadinstitute.gatk.engine.walkers.BAQMode;
+import org.broadinstitute.gatk.engine.walkers.Walker;
+import org.broadinstitute.gatk.utils.exceptions.ReviewedGATKException;
+import org.broadinstitute.gatk.utils.exceptions.UserException;
+import org.broadinstitute.gatk.utils.sam.GATKSAMRecord;
+
+/**
+ * Applies Heng's BAQ calculation to a stream of incoming reads
+ */
+public class BAQReadTransformer extends ReadTransformer {
+    private BAQ baqHMM;
+    private IndexedFastaSequenceFile refReader;
+    private BAQ.CalculationMode cmode;
+    private BAQ.QualityMode qmode;
+
+    @Override
+    public ApplicationTime initializeSub(final GenomeAnalysisEngine engine, final Walker walker) {
+        final BAQMode mode = WalkerManager.getWalkerAnnotation(walker, BAQMode.class);
+        this.refReader = engine.getReferenceDataSource().getReference();
+        this.cmode = engine.getArguments().BAQMode;
+        this.qmode = mode.QualityMode();
+        baqHMM = new BAQ(engine.getArguments().BAQGOP);
+
+        if ( qmode == BAQ.QualityMode.DONT_MODIFY )
+            throw new ReviewedGATKException("BUG: shouldn't create BAQ transformer with quality mode DONT_MODIFY");
+
+        if ( mode.ApplicationTime() == ReadTransformer.ApplicationTime.FORBIDDEN && enabled() )
+            throw new UserException.BadArgumentValue("baq", "Walker cannot accept BAQ'd base qualities, and yet BAQ mode " + cmode + " was requested.");
+
+        return mode.ApplicationTime();
+    }
+
+    @Override
+    public boolean enabled() {
+        return cmode != BAQ.CalculationMode.OFF;
+    }
+
+    @Override
+    public GATKSAMRecord apply(final GATKSAMRecord read) {
+        baqHMM.baqRead(read, refReader, cmode, qmode);
+        return read;
+    }
+}
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/baq/ReadTransformingIterator.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/baq/ReadTransformingIterator.java
new file mode 100644
index 0000000..18ca02f
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/baq/ReadTransformingIterator.java
@@ -0,0 +1,69 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.utils.baq;
+
+import com.google.java.contract.Ensures;
+import com.google.java.contract.Requires;
+import htsjdk.samtools.SAMRecord;
+import org.broadinstitute.gatk.engine.iterators.ReadTransformer;
+import org.broadinstitute.gatk.engine.iterators.GATKSAMIterator;
+import org.broadinstitute.gatk.utils.sam.GATKSAMRecord;
+
+import java.util.Iterator;
+
+/**
+ * Iterator that applies a ReadTransformer to a stream of reads
+ */
+public class ReadTransformingIterator implements GATKSAMIterator {
+    private final GATKSAMIterator it;
+    private final ReadTransformer transformer;
+
+    /**
+     * Creates a new ReadTransforming iterator
+     */
+    @Requires({"it != null", "transformer != null", "transformer.isInitialized()"})
+    public ReadTransformingIterator(final GATKSAMIterator it, final ReadTransformer transformer) {
+        if ( ! transformer.isInitialized() )
+            throw new IllegalStateException("Creating a read transformer stream for an uninitialized read transformer: " + transformer);
+        if ( transformer.getApplicationTime() == ReadTransformer.ApplicationTime.FORBIDDEN )
+            throw new IllegalStateException("Creating a read transformer stream for a forbidden transformer " + transformer);
+
+        this.it = it;
+        this.transformer = transformer;
+    }
+
+    @Requires("hasNext()")
+    @Ensures("result != null")
+    public SAMRecord next()     {
+        final GATKSAMRecord read = (GATKSAMRecord)it.next();
+        return transformer.apply(read);
+    }
+
+    public boolean hasNext()    { return this.it.hasNext(); }
+    public void remove()        { throw new UnsupportedOperationException("Can not remove records from a SAM file via an iterator!"); }
+    public void close()         { it.close(); }
+    public Iterator<SAMRecord> iterator() { return this; }
+}
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/classloader/JVMUtils.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/classloader/JVMUtils.java
new file mode 100644
index 0000000..d695543
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/classloader/JVMUtils.java
@@ -0,0 +1,309 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.utils.classloader;
+
+import org.broadinstitute.gatk.utils.Utils;
+import org.broadinstitute.gatk.utils.exceptions.ReviewedGATKException;
+import org.broadinstitute.gatk.utils.exceptions.GATKException;
+import org.reflections.util.ClasspathHelper;
+
+import java.io.File;
+import java.io.IOException;
+import java.lang.reflect.*;
+import java.net.URL;
+import java.util.*;
+
+/**
+ * Created by IntelliJ IDEA.
+ * User: hanna
+ * Date: Mar 30, 2009
+ * Time: 5:38:05 PM
+ *
+ * A set of static utility methods for determining information about this runtime environment.
+ * Introspects classes, loads jars, etc.
+ */
+public class JVMUtils {
+    /**
+     * Constructor access disallowed...static utility methods only!
+     */
+    private JVMUtils() { }
+
+    /**
+     * Determines which location contains the specified class.
+     * @param clazz The specified class.
+     * @return Location (either jar file or directory) of path containing class.
+     * @throws IOException when the URI cannot be found.
+     */
+    public static File getLocationFor( Class clazz ) throws IOException {
+        try {
+            java.net.URI locationURI = clazz.getProtectionDomain().getCodeSource().getLocation().toURI();
+            return new File(locationURI);
+        }
+        catch (java.net.URISyntaxException ex) {
+            // a URISyntaxException here must be an IO error; wrap as such.
+            throw new IOException(ex);
+        }
+        catch ( NullPointerException ne ) {
+        	throw new IOException("Can not extract code source location for "+clazz.getName());
+        }
+    }    
+
+    /**
+     * Is the specified class a concrete implementation of baseClass?
+     * @param clazz Class to check.
+     * @return True if clazz is concrete.  False otherwise.
+     */
+    public static boolean isConcrete( Class clazz ) {
+        return !Modifier.isAbstract(clazz.getModifiers()) &&
+               !Modifier.isInterface(clazz.getModifiers());
+    }
+
+    /**
+     * Is the specified class anonymous?  The plugin manager (for one) generally requires that
+     * plugin classes be named so that they can easily be specified from the command line.
+     * @param clazz The class on which to perform the anonymous check.
+     * @return True if the class is anonymous; false otherwise.
+     */
+    public static boolean isAnonymous(Class clazz) {
+        return clazz.isAnonymousClass();
+    }
+
+    /**
+     * Retrieve all fields available in this object, regardless of where they are declared or
+     * whether they're accessible.
+     * @param type Type to inspect for fields.
+     * @return A list of all available fields.
+     */
+    public static List<Field> getAllFields(Class type) {
+        List<Field> allFields = new ArrayList<Field>();
+        while( type != null ) {
+            allFields.addAll(Arrays.asList(type.getDeclaredFields()));
+            type = type.getSuperclass();
+        }
+        return allFields;
+    }
+
+    /**
+     * Find the field with the given name in the class.  Will inspect all fields, independent
+     * of access level.
+     * @param type Class in which to search for the given field.
+     * @param fieldName Name of the field for which to search.
+     * @return The field, or null if no such field exists.
+     */
+    public static Field findField( Class type, String fieldName ) {
+        while( type != null ) {
+            Field[] fields = type.getDeclaredFields();
+            for( Field field: fields ) {
+                if( field.getName().equals(fieldName) )
+                    return field;
+            }
+            type = type.getSuperclass();
+        }
+        return null;
+    }
+
+    /**
+     * Sets the provided field in the given instance to the given value.  Circumvents access restrictions:
+     * a field can be private and still set successfully by this function.
+     * @param field Field to set in the given object.
+     * @param instance Instance in which to set the field.
+     * @param value The value to which to set the given field in the given instance.
+     */
+    public static void setFieldValue( Field field, Object instance, Object value ) {
+        try {
+            field.setAccessible(true);
+            field.set(instance, value);
+        }
+        catch( IllegalAccessException ex ) {
+            throw new ReviewedGATKException(String.format("Could not set %s in instance %s to %s",field.getName(),instance.getClass().getName(),value.toString()));
+        }
+    }
+
+    /**
+     * Gets the value stored in the provided field in the given instance.
+     * @param field Field to set in the given object.
+     * @param instance Instance in which to set the field.
+     * @return Value currently stored in the given field.
+     */
+    public static Object getFieldValue( Field field, Object instance ) {
+        try {
+            field.setAccessible(true);
+            return field.get(instance);
+        }
+        catch( IllegalAccessException ex ) {
+            throw new ReviewedGATKException(String.format("Could not retrieve %s in instance %s",field.getName(),instance.getClass().getName()));
+        }
+    }
+
+    /**
+     * Gets a single object in the list matching or type-compatible with the given type.  Exceptions out if multiple objects match. 
+     * @param objectsToFilter objects to filter.
+     * @param type The desired type.
+     * @param <T> The selected type.
+     * @return A collection of the given arguments with the specified type.
+     */
+    public static <T> T getObjectOfType(Collection<Object> objectsToFilter, Class<T> type) {
+        // TODO: Make JVM utils.
+        Collection<T> selectedObjects = getObjectsOfType(objectsToFilter,type);
+        if(selectedObjects.size() > 1)
+            throw new ReviewedGATKException("User asked for a single instance of the type, multiple were present");
+        if(selectedObjects.size() == 0)
+            throw new ReviewedGATKException("User asked for a single instance of the type, but none were present");
+        return selectedObjects.iterator().next();
+    }
+
+    /**
+     * Gets a collection of all objects in the list matching or type-compatible with the given type.
+     * @param objectsToFilter objects to filter.
+     * @param type The desired type.
+     * @param <T> Again, the desired type.  Used so that clients can ignore type safety.
+     * @return A collection of the given arguments with the specified type.
+     */
+    @SuppressWarnings("unchecked")
+    public static <T> Collection<T> getObjectsOfType(Collection<Object> objectsToFilter, Class<T> type) {
+        Collection<T> selectedObjects = new ArrayList<T>();
+        for(Object object: objectsToFilter) {
+            if(type.isAssignableFrom(object.getClass()))
+                selectedObjects.add((T)object);
+        }
+        return selectedObjects;
+    }
+
+    /**
+     * Returns the list of class path urls.
+     * @return the list of class path urls.
+     */
+    public static Set<URL> getClasspathURLs() {
+        return ClasspathHelper.forManifest();
+    }
+
+    /**
+     * Adds all the generic types from a class definition to the collection.
+     * Does not inspect the methods or fields, only the class.
+     * @param classes Set to collect the classes.
+     * @param type Type to inspect.
+     */
+    public static void addGenericTypes(Set<Class<?>> classes, Type type) {
+        if (type instanceof ParameterizedType) {
+            ParameterizedType parameterizedType = (ParameterizedType)type;
+            for (Type actualType: parameterizedType.getActualTypeArguments())
+                addGenericTypes(classes, actualType);
+        } else if (type instanceof GenericArrayType) {
+            addGenericTypes(classes, ((GenericArrayType)type).getGenericComponentType());
+        } else if (type instanceof WildcardType) {
+            WildcardType wildcardType = (WildcardType)type;
+            for (Type upperType: wildcardType.getUpperBounds())
+                addGenericTypes(classes, upperType);
+            for (Type lowerType: wildcardType.getLowerBounds())
+                addGenericTypes(classes, lowerType);
+        } else if (type instanceof Class<?>) {
+            classes.add((Class<?>) type);
+        } else {
+            throw new GATKException("Unknown type: " + type + " (" + type.getClass().getName() + ")");
+        }
+    }
+
+    public static Class getParameterizedTypeClass(Type t) {
+        if ( t instanceof ParameterizedType ) {
+            ParameterizedType parameterizedType = (ParameterizedType)t;
+            if ( parameterizedType.getActualTypeArguments().length != 1 )
+                throw new ReviewedGATKException("BUG: more than 1 generic type found on class" + t);
+            return (Class)parameterizedType.getActualTypeArguments()[0];
+        } else
+            throw new ReviewedGATKException("BUG: could not find generic type on class " + t);
+    }
+
+    /**
+     * Returns a comma-separated list of the names of the interfaces implemented by this class
+     *
+     * @param covClass class
+     * @return names of interfaces
+     */
+    public static String classInterfaces(final Class covClass) {
+        final List<String> interfaces = new ArrayList<String>();
+        for ( final Class interfaceClass : covClass.getInterfaces() )
+            interfaces.add(interfaceClass.getSimpleName());
+        return Utils.join(", ", interfaces);
+    }
+
+    /**
+     * Returns the Class that invoked the specified "callee" class by examining the runtime stack.
+     * The calling class is defined as the first class below the callee class on the stack.
+     *
+     * For example, given callee == MyClass and the following runtime stack:
+     *
+     * JVMUtils.getCallingClass(MyClass) <-- top
+     * MyClass.foo()
+     * MyClass.bar()
+     * OtherClass.foo()
+     * OtherClass.bar()
+     * etc.
+     *
+     * this method would return OtherClass, since its methods invoked the methods in MyClass.
+     *
+     * Considers only the occurrence of the callee class on the stack that is closest to the top
+     * (even if there are multiple, non-contiguous occurrences).
+     *
+     * @param callee Class object for the class whose calling class we want to locate
+     * @return Class object for the class that invoked the callee class, or null if
+     *         no calling class was found
+     * @throws IllegalArgumentException if the callee class is not found on the runtime stack
+     * @throws IllegalStateException if we get an error while trying to load the Class object for the calling
+     *                               class reported on the runtime stack
+     */
+    public static Class getCallingClass( final Class callee ) {
+        final StackTraceElement[] stackTrace = new Throwable().getStackTrace();
+        final String calleeClassName = callee.getName();
+
+        // Start examining the stack at the second-from-the-top position, to remove
+        // this method call (ie., the call to getCallingClass() itself) from consideration.
+        int stackTraceIndex = 1;
+
+        // Find the first occurrence of the callee on the runtime stack. Need to use String comparison
+        // unfortunately, due to limitations of the StackTraceElement class.
+        while ( stackTraceIndex < stackTrace.length && ! stackTrace[stackTraceIndex].getClassName().equals(calleeClassName) ) {
+            stackTraceIndex++;
+        }
+
+        // Make sure we actually found the callee class on the stack
+        if ( stackTraceIndex == stackTrace.length ) {
+            throw new IllegalArgumentException(String.format("Specified callee %s is not present on the call stack", callee.getSimpleName()));
+        }
+
+        // Now find the caller class, which will be the class below the callee on the stack
+        while ( stackTraceIndex < stackTrace.length && stackTrace[stackTraceIndex].getClassName().equals(calleeClassName) ) {
+            stackTraceIndex++;
+        }
+
+        try {
+            return stackTraceIndex < stackTrace.length ? Class.forName(stackTrace[stackTraceIndex].getClassName()) : null;
+        }
+        catch ( ClassNotFoundException e ) {
+            throw new IllegalStateException(String.format("Could not find caller class %s from the runtime stack in the classpath",
+                                                          stackTrace[stackTraceIndex].getClassName()));
+        }
+    }
+}
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/classloader/PluginManager.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/classloader/PluginManager.java
new file mode 100644
index 0000000..7313e19
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/classloader/PluginManager.java
@@ -0,0 +1,355 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.utils.classloader;
+
+import org.apache.log4j.Level;
+import org.apache.log4j.Logger;
+import org.broadinstitute.gatk.engine.WalkerManager;
+import org.broadinstitute.gatk.engine.filters.FilterManager;
+import org.broadinstitute.gatk.utils.exceptions.DynamicClassResolutionException;
+import org.broadinstitute.gatk.utils.exceptions.ReviewedGATKException;
+import org.broadinstitute.gatk.utils.exceptions.UserException;
+import org.reflections.Reflections;
+import org.reflections.scanners.SubTypesScanner;
+import org.reflections.util.ConfigurationBuilder;
+
+import java.io.File;
+import java.lang.reflect.Constructor;
+import java.lang.reflect.Method;
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.net.URLClassLoader;
+import java.util.*;
+
+/**
+ * Manage plugins and plugin configuration.
+ * @author mhanna
+ * @version 0.1
+ */
+public class PluginManager<PluginType> {
+    /**
+     * A reference into our introspection utility.
+     */
+    private static final Reflections defaultReflections;
+
+    static {
+        // turn off logging in the reflections library - they talk too much
+        Reflections.log = null;
+
+        Set<URL> classPathUrls = new LinkedHashSet<URL>();
+
+        URL cwd;
+        try {
+            cwd = new File(".").getAbsoluteFile().toURI().toURL();
+        } catch (MalformedURLException e) {
+            throw new RuntimeException(e);
+        }
+
+        // NOTE: Reflections also scans directories for classes.
+        // Meanwhile some of the jar MANIFEST.MF Bundle-ClassPath properties contain "."
+        // Do NOT let reflections scan the CWD where it often picks up test classes when
+        // they weren't explicitly in the classpath, for example the UninstantiableWalker
+        for (URL url: JVMUtils.getClasspathURLs())
+            if (!url.equals(cwd))
+                classPathUrls.add(url);
+
+        defaultReflections = new Reflections( new ConfigurationBuilder()
+            .setUrls(classPathUrls)
+            .setScanners(new SubTypesScanner()));
+    }
+
+    /**
+     * Defines the category of plugin defined by the subclass.
+     */
+    protected final String pluginCategory;
+
+    /**
+     * Define common strings to trim off the end of the name.
+     */
+    protected final String pluginSuffix;
+    
+    /**
+     * Plugins stored based on their name.
+     */
+    private final SortedMap<String, Class<? extends PluginType>> pluginsByName;
+
+    private final List<Class<? extends PluginType>> plugins;
+    private final List<Class<? extends PluginType>> interfaces;
+
+    /**
+     * Create a new plugin manager.
+     * @param pluginType Core type for a plugin.
+     */
+    public PluginManager(Class pluginType) {
+        this(pluginType, pluginType.getSimpleName().toLowerCase(), pluginType.getSimpleName(), null);
+    }
+
+    /**
+     * Create a new plugin manager.
+     * @param pluginType Core type for a plugin.
+     * @param classpath Custom class path to search for classes.
+     */
+    public PluginManager(Class pluginType, List<URL> classpath) {
+        this(pluginType, pluginType.getSimpleName().toLowerCase(), pluginType.getSimpleName(), classpath);
+    }
+
+    /**
+     * Create a new plugin manager.
+     * @param pluginType Core type for a plugin.
+     * @param pluginCategory Provides a category name to the plugin.  Must not be null.
+     * @param pluginSuffix Provides a suffix that will be trimmed off when converting to a plugin name.  Can be null.
+     */
+    public PluginManager(Class pluginType, String pluginCategory, String pluginSuffix) {
+        this(pluginType, pluginCategory, pluginSuffix, null);
+    }
+
+    /**
+     * Create a new plugin manager.
+     * @param pluginType Core type for a plugin.
+     * @param pluginCategory Provides a category name to the plugin.  Must not be null.
+     * @param pluginSuffix Provides a suffix that will be trimmed off when converting to a plugin name.  Can be null.
+     * @param classpath Custom class path to search for classes.
+     */
+    public PluginManager(Class pluginType, String pluginCategory, String pluginSuffix, List<URL> classpath) {
+        this.pluginCategory = pluginCategory;
+        this.pluginSuffix = pluginSuffix;
+
+        this.plugins = new ArrayList<Class<? extends PluginType>>();
+        this.interfaces = new ArrayList<Class<? extends PluginType>>();
+
+        Reflections reflections;
+        if (classpath == null) {
+            reflections = defaultReflections;
+        } else {
+            addClasspath(classpath);
+            reflections = new Reflections( new ConfigurationBuilder()
+                .setUrls(classpath)
+                .setScanners(new SubTypesScanner()));
+        }
+
+        // Load all classes types filtering them by concrete.
+        @SuppressWarnings("unchecked")
+        Set<Class<? extends PluginType>> allTypes = reflections.getSubTypesOf(pluginType);
+        for( Class<? extends PluginType> type: allTypes ) {
+            // The plugin manager does not support anonymous classes; to be a plugin, a class must have a name.
+            if(JVMUtils.isAnonymous(type))
+                continue;
+
+            if( JVMUtils.isConcrete(type) )
+                plugins.add(type);
+            else
+                interfaces.add(type);
+        }
+
+        pluginsByName = new TreeMap<String, Class<? extends PluginType>>();
+        for (Class<? extends PluginType> pluginClass : plugins) {
+            String pluginName = getName(pluginClass);
+            pluginsByName.put(pluginName, pluginClass);
+        }
+
+        // sort the plugins so the order of elements is deterministic
+        sortPlugins(plugins);
+        sortPlugins(interfaces);
+    }
+
+    /**
+     * Sorts, in place, the list of plugins according to getName() on each element
+     *
+     * @param unsortedPlugins unsorted plugins
+     */
+    private void sortPlugins(final List<Class<? extends PluginType>> unsortedPlugins) {
+        Collections.sort(unsortedPlugins, new ComparePluginsByName());
+    }
+
+    private final class ComparePluginsByName implements Comparator<Class<? extends PluginType>> {
+        @Override
+        public int compare(final Class<? extends PluginType> aClass, final Class<? extends PluginType> aClass1) {
+            String pluginName1 = getName(aClass);
+            String pluginName2 = getName(aClass1);
+            return pluginName1.compareTo(pluginName2);
+        }
+    }
+
+    /**
+     * Adds the URL to the system class loader classpath using reflection.
+     * HACK: Uses reflection to modify the class path, and assumes loader is a URLClassLoader.
+     * @param urls URLs to add to the system class loader classpath.
+     */
+    private static void addClasspath(List<URL> urls) {
+      Set<URL> existing = JVMUtils.getClasspathURLs();
+      for (URL url : urls) {
+          if (existing.contains(url))
+            continue;
+          try {
+              Method method = URLClassLoader.class.getDeclaredMethod("addURL", URL.class);
+              if (!method.isAccessible())
+                  method.setAccessible(true);
+              method.invoke(ClassLoader.getSystemClassLoader(), url);
+          } catch (Exception e) {
+              throw new ReviewedGATKException("Error adding url to the current classloader.", e);
+          }
+      }
+    }
+    
+    public Map<String, Class<? extends PluginType>> getPluginsByName() {
+        return Collections.unmodifiableMap(pluginsByName);
+    }
+
+    /**
+     * Does a plugin with the given name exist?
+     *
+     * @param pluginName Name of the plugin for which to search.
+     * @return True if the plugin exists, false otherwise.
+     */
+    public boolean exists(String pluginName) {
+        return pluginsByName.containsKey(pluginName);
+    }
+
+    /**
+     * Does a plugin with the given name exist?
+     *
+     * @param plugin Name of the plugin for which to search.
+     * @return True if the plugin exists, false otherwise.
+     */
+    public boolean exists(Class<? extends PluginType> plugin) {
+        return pluginsByName.containsValue(plugin);
+    }
+
+    /**
+     * Returns the plugin classes
+     * @return the plugin classes
+     */
+    public List<Class<? extends PluginType>> getPlugins() {
+        return plugins;
+    }
+
+    /**
+     * Returns the interface classes
+     * @return the interface classes
+     */
+    public List<Class<? extends PluginType>> getInterfaces() {
+        return interfaces;
+    }
+
+    /**
+     * Returns the plugin classes implementing interface or base clase
+     * @param type type of interface or base class
+     * @return the plugin classes implementing interface or base class
+     */
+    public List<Class<? extends PluginType>> getPluginsImplementing(Class<?> type) {
+        List<Class<? extends PluginType>> implementing = new ArrayList<Class<? extends PluginType>>();
+        for (Class<? extends PluginType> plugin: getPlugins())
+            if (type.isAssignableFrom(plugin))
+                implementing.add(plugin);
+        return implementing;
+    }
+
+
+
+    /**
+     * Gets a plugin with the given name
+     *
+     * @param pluginName Name of the plugin to retrieve.
+     * @return The plugin object if found; null otherwise.
+     */
+    public PluginType createByName(String pluginName) {
+        Class<? extends PluginType> plugin = pluginsByName.get(pluginName);
+        if( plugin == null ) {
+            String errorMessage = formatErrorMessage(pluginCategory,pluginName);
+            if ( this.getClass().isAssignableFrom(FilterManager.class) ) {
+                throw new UserException.MalformedReadFilterException(errorMessage);
+            } else if ( this.getClass().isAssignableFrom(WalkerManager.class) ) {
+                throw new UserException.MalformedWalkerArgumentsException(errorMessage);
+            } else {
+                throw new UserException.CommandLineException(errorMessage);
+            }
+        }
+        try {
+            return plugin.newInstance();
+        } catch (Exception e) {
+            throw new DynamicClassResolutionException(plugin, e);
+        }
+    }
+
+    /**
+     * create a plugin with the given type
+     *
+     * @param pluginType type of the plugin to create.
+     * @return The plugin object if created; null otherwise.
+     */
+    public PluginType createByType(Class<? extends PluginType> pluginType) {
+        Logger logger = Logger.getLogger(PluginManager.class);
+        logger.setLevel(Level.ERROR);
+        try {
+            Constructor<? extends PluginType> noArgsConstructor = pluginType.getDeclaredConstructor((Class[])null);
+            noArgsConstructor.setAccessible(true);
+            return noArgsConstructor.newInstance();
+        } catch (Exception e) {
+            logger.error("Couldn't initialize the plugin. Typically this is because of wrong global class variable initializations.");
+            throw new DynamicClassResolutionException(pluginType, e);
+        }
+    }
+
+    /**
+     * Returns concrete instances of the plugins
+     * @return concrete instances of the plugins
+     */
+    public List<PluginType> createAllTypes() {
+        List<PluginType> instances = new ArrayList<PluginType>();
+        for ( Class<? extends PluginType> c : getPlugins() ) {
+            instances.add(createByType(c));
+        }
+        return instances;
+    }
+
+    /**
+     * Create a name for this type of plugin.
+     *
+     * @param pluginType The type of plugin.
+     * @return A name for this type of plugin.
+     */
+    public String getName(Class pluginType) {
+        String pluginName = "";
+
+        if (pluginName.length() == 0) {
+            pluginName = pluginType.getSimpleName();
+            if (pluginSuffix != null && pluginName.endsWith(pluginSuffix))
+                pluginName = pluginName.substring(0, pluginName.lastIndexOf(pluginSuffix));
+        }
+
+        return pluginName;
+    }
+
+    /**
+     * Generate the error message for the plugin manager. The message is allowed to depend on the class.
+     * @param pluginCategory - string, the category of the plugin (e.g. read filter)
+     * @param pluginName - string, what we were trying to match (but failed to)
+     * @return error message text describing the error
+     */
+    protected String formatErrorMessage(String pluginCategory, String pluginName ) {
+        return String.format("Could not find %s with name: %s", pluginCategory,pluginName);
+    }
+}
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/classloader/ProtectedPackageSource.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/classloader/ProtectedPackageSource.java
new file mode 100644
index 0000000..7c7a776
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/classloader/ProtectedPackageSource.java
@@ -0,0 +1,28 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.utils.classloader;
+
+public interface ProtectedPackageSource {}
\ No newline at end of file
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/classloader/PublicPackageSource.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/classloader/PublicPackageSource.java
new file mode 100644
index 0000000..5321466
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/classloader/PublicPackageSource.java
@@ -0,0 +1,28 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.utils.classloader;
+
+public interface PublicPackageSource {}
\ No newline at end of file
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/clipping/ClippingOp.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/clipping/ClippingOp.java
new file mode 100644
index 0000000..f4ca70e
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/clipping/ClippingOp.java
@@ -0,0 +1,617 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.utils.clipping;
+
+import com.google.java.contract.Requires;
+import htsjdk.samtools.Cigar;
+import htsjdk.samtools.CigarElement;
+import htsjdk.samtools.CigarOperator;
+import org.broadinstitute.gatk.utils.recalibration.EventType;
+import org.broadinstitute.gatk.utils.exceptions.ReviewedGATKException;
+import org.broadinstitute.gatk.utils.exceptions.UserException;
+import org.broadinstitute.gatk.utils.sam.GATKSAMRecord;
+
+import java.util.Iterator;
+import java.util.List;
+import java.util.Stack;
+import java.util.Vector;
+
+/**
+ * Represents a clip on a read.  It has a type (see the enum) along with a start and stop in the bases
+ * of the read, plus an option extraInfo (useful for carrying info where needed).
+ * <p/>
+ * Also holds the critical apply function that actually execute the clipping operation on a provided read,
+ * according to the wishes of the supplied ClippingAlgorithm enum.
+ */
+public class ClippingOp {
+    public final int start, stop; // inclusive
+
+    public ClippingOp(int start, int stop) {
+        this.start = start;
+        this.stop = stop;
+    }
+
+
+    public int getLength() {
+        return stop - start + 1;
+    }
+
+    /**
+     * Clips the bases in read according to this operation's start and stop.  Uses the clipping
+     * representation used is the one provided by algorithm argument.
+     *
+     * @param algorithm    clipping algorithm to use
+     * @param originalRead the read to be clipped
+     */
+    public GATKSAMRecord apply(ClippingRepresentation algorithm, GATKSAMRecord originalRead) {
+        GATKSAMRecord read = (GATKSAMRecord) originalRead.clone();
+        byte[] quals = read.getBaseQualities();
+        byte[] bases = read.getReadBases();
+        byte[] newBases = new byte[bases.length];
+        byte[] newQuals = new byte[quals.length];
+
+        switch (algorithm) {
+            // important note:
+            //   it's not safe to call read.getReadBases()[i] = 'N' or read.getBaseQualities()[i] = 0
+            //   because you're not guaranteed to get a pointer to the actual array of bytes in the GATKSAMRecord
+            case WRITE_NS:
+                for (int i = 0; i < bases.length; i++) {
+                    if (i >= start && i <= stop) {
+                        newBases[i] = 'N';
+                    }
+                    else {
+                        newBases[i] = bases[i];
+                    }
+                }
+                read.setReadBases(newBases);
+                break;
+            case WRITE_Q0S:
+                for (int i = 0; i < quals.length; i++) {
+                    if (i >= start && i <= stop) {
+                        newQuals[i] = 0;
+                    }
+                    else {
+                        newQuals[i] = quals[i];
+                    }
+                }
+                read.setBaseQualities(newQuals);
+                break;
+            case WRITE_NS_Q0S:
+                for (int i = 0; i < bases.length; i++) {
+                    if (i >= start && i <= stop) {
+                        newQuals[i] = 0;
+                        newBases[i] = 'N';
+                    }
+                    else {
+                        newQuals[i] = quals[i];
+                        newBases[i] = bases[i];
+                    }
+                }
+                read.setBaseQualities(newBases);
+                read.setReadBases(newBases);
+                break;
+            case HARDCLIP_BASES:
+                read = hardClip(read, start, stop);
+                break;
+
+            case SOFTCLIP_BASES:
+                if (read.getReadUnmappedFlag()) {
+                    // we can't process unmapped reads
+                    throw new UserException("Read Clipper cannot soft clip unmapped reads");
+                }
+
+                //System.out.printf("%d %d %d%n", stop, start, read.getReadLength());
+                int myStop = stop;
+                if ((stop + 1 - start) == read.getReadLength()) {
+                    // BAM representation issue -- we can't SOFTCLIP away all bases in a read, just leave it alone
+                    //Walker.logger.info(String.format("Warning, read %s has all bases clip but this can't be represented with SOFTCLIP_BASES, just leaving it alone", read.getReadName()));
+                    //break;
+                    myStop--; // just decrement stop
+                }
+
+                if (start > 0 && myStop != read.getReadLength() - 1)
+                    throw new RuntimeException(String.format("Cannot apply soft clipping operator to the middle of a read: %s to be clipped at %d-%d", read.getReadName(), start, myStop));
+
+                Cigar oldCigar = read.getCigar();
+
+                int scLeft = 0, scRight = read.getReadLength();
+                if (start == 0)
+                    scLeft = myStop + 1;
+                else
+                    scRight = start;
+
+                Cigar newCigar = softClip(oldCigar, scLeft, scRight);
+                read.setCigar(newCigar);
+
+                int newClippedStart = getNewAlignmentStartOffset(newCigar, oldCigar);
+                int newStart = read.getAlignmentStart() + newClippedStart;
+                read.setAlignmentStart(newStart);
+
+                break;
+
+            case REVERT_SOFTCLIPPED_BASES:
+                read = revertSoftClippedBases(read);
+                break;
+
+            default:
+                throw new IllegalStateException("Unexpected Clipping operator type " + algorithm);
+        }
+
+        return read;
+    }
+
+    private GATKSAMRecord revertSoftClippedBases(GATKSAMRecord read) {
+        GATKSAMRecord unclipped = (GATKSAMRecord) read.clone();
+
+        Cigar unclippedCigar = new Cigar();
+        int matchesCount = 0;
+        for (CigarElement element : read.getCigar().getCigarElements()) {
+            if (element.getOperator() == CigarOperator.SOFT_CLIP || element.getOperator() == CigarOperator.MATCH_OR_MISMATCH)
+                matchesCount += element.getLength();
+            else if (matchesCount > 0) {
+                unclippedCigar.add(new CigarElement(matchesCount, CigarOperator.MATCH_OR_MISMATCH));
+                matchesCount = 0;
+                unclippedCigar.add(element);
+            } else
+                unclippedCigar.add(element);
+        }
+        if (matchesCount > 0)
+            unclippedCigar.add(new CigarElement(matchesCount, CigarOperator.MATCH_OR_MISMATCH));
+
+        unclipped.setCigar(unclippedCigar);
+        final int newStart = read.getAlignmentStart() + calculateAlignmentStartShift(read.getCigar(), unclippedCigar);
+        unclipped.setAlignmentStart(newStart);
+
+        if ( newStart <= 0 ) {
+            // if the start of the unclipped read occurs before the contig,
+            // we must hard clip away the bases since we cannot represent reads with
+            // negative or 0 alignment start values in the SAMRecord (e.g., 0 means unaligned)
+            return hardClip(unclipped, 0, - newStart);
+        } else {
+            return unclipped;
+        }
+    }
+
+    /**
+     * Given a cigar string, get the number of bases hard or soft clipped at the start
+     */
+    private int getNewAlignmentStartOffset(final Cigar __cigar, final Cigar __oldCigar) {
+        int num = 0;
+        for (CigarElement e : __cigar.getCigarElements()) {
+            if (!e.getOperator().consumesReferenceBases()) {
+                if (e.getOperator().consumesReadBases()) {
+                    num += e.getLength();
+                }
+            } else {
+                break;
+            }
+        }
+
+        int oldNum = 0;
+        int curReadCounter = 0;
+
+        for (CigarElement e : __oldCigar.getCigarElements()) {
+            int curRefLength = e.getLength();
+            int curReadLength = e.getLength();
+            if (!e.getOperator().consumesReadBases()) {
+                curReadLength = 0;
+            }
+
+            boolean truncated = false;
+            if (curReadCounter + curReadLength > num) {
+                curReadLength = num - curReadCounter;
+                curRefLength = num - curReadCounter;
+                truncated = true;
+            }
+
+            if (!e.getOperator().consumesReferenceBases()) {
+                curRefLength = 0;
+            }
+
+            curReadCounter += curReadLength;
+            oldNum += curRefLength;
+
+            if (curReadCounter > num || truncated) {
+                break;
+            }
+        }
+
+        return oldNum;
+    }
+
+    /**
+     * Given a cigar string, soft clip up to startClipEnd and soft clip starting at endClipBegin
+     */
+    private Cigar softClip(final Cigar __cigar, final int __startClipEnd, final int __endClipBegin) {
+        if (__endClipBegin <= __startClipEnd) {
+            //whole thing should be soft clipped
+            int cigarLength = 0;
+            for (CigarElement e : __cigar.getCigarElements()) {
+                cigarLength += e.getLength();
+            }
+
+            Cigar newCigar = new Cigar();
+            newCigar.add(new CigarElement(cigarLength, CigarOperator.SOFT_CLIP));
+            assert newCigar.isValid(null, -1) == null;
+            return newCigar;
+        }
+
+        int curLength = 0;
+        Vector<CigarElement> newElements = new Vector<CigarElement>();
+        for (CigarElement curElem : __cigar.getCigarElements()) {
+            if (!curElem.getOperator().consumesReadBases()) {
+                if (curElem.getOperator() == CigarOperator.HARD_CLIP || curLength > __startClipEnd && curLength < __endClipBegin) {
+                    newElements.add(new CigarElement(curElem.getLength(), curElem.getOperator()));
+                }
+                continue;
+            }
+
+            int s = curLength;
+            int e = curLength + curElem.getLength();
+            if (e <= __startClipEnd || s >= __endClipBegin) {
+                //must turn this entire thing into a clip
+                newElements.add(new CigarElement(curElem.getLength(), CigarOperator.SOFT_CLIP));
+            } else if (s >= __startClipEnd && e <= __endClipBegin) {
+                //same thing
+                newElements.add(new CigarElement(curElem.getLength(), curElem.getOperator()));
+            } else {
+                //we are clipping in the middle of this guy
+                CigarElement newStart = null;
+                CigarElement newMid = null;
+                CigarElement newEnd = null;
+
+                int midLength = curElem.getLength();
+                if (s < __startClipEnd) {
+                    newStart = new CigarElement(__startClipEnd - s, CigarOperator.SOFT_CLIP);
+                    midLength -= newStart.getLength();
+                }
+
+                if (e > __endClipBegin) {
+                    newEnd = new CigarElement(e - __endClipBegin, CigarOperator.SOFT_CLIP);
+                    midLength -= newEnd.getLength();
+                }
+                assert midLength >= 0;
+                if (midLength > 0) {
+                    newMid = new CigarElement(midLength, curElem.getOperator());
+                }
+                if (newStart != null) {
+                    newElements.add(newStart);
+                }
+                if (newMid != null) {
+                    newElements.add(newMid);
+                }
+                if (newEnd != null) {
+                    newElements.add(newEnd);
+                }
+            }
+            curLength += curElem.getLength();
+        }
+
+        Vector<CigarElement> finalNewElements = new Vector<CigarElement>();
+        CigarElement lastElement = null;
+        for (CigarElement elem : newElements) {
+            if (lastElement == null || lastElement.getOperator() != elem.getOperator()) {
+                if (lastElement != null) {
+                    finalNewElements.add(lastElement);
+                }
+                lastElement = elem;
+            } else {
+                lastElement = new CigarElement(lastElement.getLength() + elem.getLength(), lastElement.getOperator());
+            }
+        }
+        if (lastElement != null) {
+            finalNewElements.add(lastElement);
+        }
+
+        Cigar newCigar = new Cigar(finalNewElements);
+        assert newCigar.isValid(null, -1) == null;
+        return newCigar;
+    }
+
+    /**
+     * Hard clip bases from read, from start to stop in base coordinates
+     *
+     * If start == 0, then we will clip from the front of the read, otherwise we clip
+     * from the right.  If start == 0 and stop == 10, this would clip out the first
+     * 10 bases of the read.
+     *
+     * Note that this function works with reads with negative alignment starts, in order to
+     * allow us to hardClip reads that have had their soft clips reverted and so might have
+     * negative alignment starts
+     *
+     * Works properly with reduced reads and insertion/deletion base qualities
+     *
+     * @param read a non-null read
+     * @param start a start >= 0 and < read.length
+     * @param stop a stop >= 0 and < read.length.
+     * @return a cloned version of read that has been properly trimmed down
+     */
+    private GATKSAMRecord hardClip(GATKSAMRecord read, int start, int stop) {
+
+        // If the read is unmapped there is no Cigar string and neither should we create a new cigar string
+        final CigarShift cigarShift = (read.getReadUnmappedFlag()) ? new CigarShift(new Cigar(), 0, 0) : hardClipCigar(read.getCigar(), start, stop);
+
+        // the cigar may force a shift left or right (or both) in case we are left with insertions
+        // starting or ending the read after applying the hard clip on start/stop.
+        final int newLength = read.getReadLength() - (stop - start + 1) - cigarShift.shiftFromStart - cigarShift.shiftFromEnd;
+        final byte[] newBases = new byte[newLength];
+        final byte[] newQuals = new byte[newLength];
+        final int copyStart = (start == 0) ? stop + 1 + cigarShift.shiftFromStart : cigarShift.shiftFromStart;
+
+        System.arraycopy(read.getReadBases(), copyStart, newBases, 0, newLength);
+        System.arraycopy(read.getBaseQualities(), copyStart, newQuals, 0, newLength);
+
+        final GATKSAMRecord hardClippedRead = (GATKSAMRecord) read.clone();
+
+        hardClippedRead.resetSoftStartAndEnd();                                                                         // reset the cached soft start and end because they may have changed now that the read was hard clipped. No need to calculate them now. They'll be lazily calculated on the next call to getSoftStart()/End()
+        hardClippedRead.setBaseQualities(newQuals);
+        hardClippedRead.setReadBases(newBases);
+        hardClippedRead.setCigar(cigarShift.cigar);
+        if (start == 0)
+            hardClippedRead.setAlignmentStart(read.getAlignmentStart() + calculateAlignmentStartShift(read.getCigar(), cigarShift.cigar));
+
+        if (read.hasBaseIndelQualities()) {
+            final byte[] newBaseInsertionQuals = new byte[newLength];
+            final byte[] newBaseDeletionQuals = new byte[newLength];
+            System.arraycopy(read.getBaseInsertionQualities(), copyStart, newBaseInsertionQuals, 0, newLength);
+            System.arraycopy(read.getBaseDeletionQualities(), copyStart, newBaseDeletionQuals, 0, newLength);
+            hardClippedRead.setBaseQualities(newBaseInsertionQuals, EventType.BASE_INSERTION);
+            hardClippedRead.setBaseQualities(newBaseDeletionQuals, EventType.BASE_DELETION);
+        }
+
+        return hardClippedRead;
+
+    }
+
+    @Requires({"!cigar.isEmpty()"})
+    private CigarShift hardClipCigar(Cigar cigar, int start, int stop) {
+        Cigar newCigar = new Cigar();
+        int index = 0;
+        int totalHardClipCount = stop - start + 1;
+        int alignmentShift = 0; // caused by hard clipping deletions
+
+        // hard clip the beginning of the cigar string
+        if (start == 0) {
+            Iterator<CigarElement> cigarElementIterator = cigar.getCigarElements().iterator();
+            CigarElement cigarElement = cigarElementIterator.next();
+            // Skip all leading hard clips
+            while (cigarElement.getOperator() == CigarOperator.HARD_CLIP) {
+                totalHardClipCount += cigarElement.getLength();
+                if (cigarElementIterator.hasNext())
+                    cigarElement = cigarElementIterator.next();
+                else
+                    throw new ReviewedGATKException("Read is entirely hardclipped, shouldn't be trying to clip it's cigar string");
+            }
+            // keep clipping until we hit stop
+            while (index <= stop) {
+                int shift = 0;
+                if (cigarElement.getOperator().consumesReadBases())
+                    shift = cigarElement.getLength();
+
+                // we're still clipping or just finished perfectly
+                if (index + shift == stop + 1) {
+                    alignmentShift += calculateHardClippingAlignmentShift(cigarElement, cigarElement.getLength());
+                    newCigar.add(new CigarElement(totalHardClipCount + alignmentShift, CigarOperator.HARD_CLIP));
+                }
+                // element goes beyond what we need to clip
+                else if (index + shift > stop + 1) {
+                    int elementLengthAfterChopping = cigarElement.getLength() - (stop - index + 1);
+                    alignmentShift += calculateHardClippingAlignmentShift(cigarElement, stop - index + 1);
+                    newCigar.add(new CigarElement(totalHardClipCount + alignmentShift, CigarOperator.HARD_CLIP));
+                    newCigar.add(new CigarElement(elementLengthAfterChopping, cigarElement.getOperator()));
+                }
+                index += shift;
+                alignmentShift += calculateHardClippingAlignmentShift(cigarElement, shift);
+
+                if (index <= stop && cigarElementIterator.hasNext())
+                    cigarElement = cigarElementIterator.next();
+                else
+                    break;
+            }
+
+            // add the remaining cigar elements
+            while (cigarElementIterator.hasNext()) {
+                cigarElement = cigarElementIterator.next();
+                newCigar.add(new CigarElement(cigarElement.getLength(), cigarElement.getOperator()));
+            }
+        }
+
+        // hard clip the end of the cigar string
+        else {
+            Iterator<CigarElement> cigarElementIterator = cigar.getCigarElements().iterator();
+            CigarElement cigarElement = cigarElementIterator.next();
+
+            // Keep marching on until we find the start
+            while (index < start) {
+                int shift = 0;
+                if (cigarElement.getOperator().consumesReadBases())
+                    shift = cigarElement.getLength();
+
+                // we haven't gotten to the start yet, keep everything as is.
+                if (index + shift < start)
+                    newCigar.add(new CigarElement(cigarElement.getLength(), cigarElement.getOperator()));
+
+                    // element goes beyond our clip starting position
+                else {
+                    int elementLengthAfterChopping = start - index;
+                    alignmentShift += calculateHardClippingAlignmentShift(cigarElement, cigarElement.getLength() - (start - index));
+
+                    // if this last element is a HARD CLIP operator, just merge it with our hard clip operator to be added later
+                    if (cigarElement.getOperator() == CigarOperator.HARD_CLIP)
+                        totalHardClipCount += elementLengthAfterChopping;
+                        // otherwise, maintain what's left of this last operator
+                    else
+                        newCigar.add(new CigarElement(elementLengthAfterChopping, cigarElement.getOperator()));
+                }
+                index += shift;
+                if (index < start && cigarElementIterator.hasNext())
+                    cigarElement = cigarElementIterator.next();
+                else
+                    break;
+            }
+
+            // check if we are hard clipping indels
+            while (cigarElementIterator.hasNext()) {
+                cigarElement = cigarElementIterator.next();
+                alignmentShift += calculateHardClippingAlignmentShift(cigarElement, cigarElement.getLength());
+
+                // if the read had a HardClip operator in the end, combine it with the Hard Clip we are adding
+                if (cigarElement.getOperator() == CigarOperator.HARD_CLIP)
+                    totalHardClipCount += cigarElement.getLength();
+            }
+            newCigar.add(new CigarElement(totalHardClipCount + alignmentShift, CigarOperator.HARD_CLIP));
+        }
+        return cleanHardClippedCigar(newCigar);
+    }
+
+    /**
+     * Checks if a hard clipped cigar left a read starting or ending with deletions or gap (N)
+     * and cleans it up accordingly.
+     *
+     * @param cigar the original cigar
+     * @return an object with the shifts (see CigarShift class)
+     */
+    private CigarShift cleanHardClippedCigar(final Cigar cigar) {
+        final Cigar cleanCigar = new Cigar();
+        int shiftFromStart = 0;
+        int shiftFromEnd = 0;
+        Stack<CigarElement> cigarStack = new Stack<CigarElement>();
+        final Stack<CigarElement> inverseCigarStack = new Stack<CigarElement>();
+
+        for (final CigarElement cigarElement : cigar.getCigarElements())
+            cigarStack.push(cigarElement);
+
+        for (int i = 1; i <= 2; i++) {
+            int shift = 0;
+            int totalHardClip = 0;
+            boolean readHasStarted = false;
+            boolean addedHardClips = false;
+
+            while (!cigarStack.empty()) {
+                CigarElement cigarElement = cigarStack.pop();
+
+                if (!readHasStarted &&
+                        cigarElement.getOperator() != CigarOperator.DELETION &&
+                        cigarElement.getOperator() != CigarOperator.SKIPPED_REGION &&
+                        cigarElement.getOperator() != CigarOperator.HARD_CLIP)
+                    readHasStarted = true;
+
+                else if (!readHasStarted && cigarElement.getOperator() == CigarOperator.HARD_CLIP)
+                    totalHardClip += cigarElement.getLength();
+
+                else if (!readHasStarted && cigarElement.getOperator() == CigarOperator.DELETION)
+                    totalHardClip += cigarElement.getLength();
+
+                else if (!readHasStarted && cigarElement.getOperator() == CigarOperator.SKIPPED_REGION)
+                    totalHardClip += cigarElement.getLength();
+
+                if (readHasStarted) {
+                    if (i == 1) {
+                        if (!addedHardClips) {
+                            if (totalHardClip > 0)
+                                inverseCigarStack.push(new CigarElement(totalHardClip, CigarOperator.HARD_CLIP));
+                            addedHardClips = true;
+                        }
+                        inverseCigarStack.push(cigarElement);
+                    } else {
+                        if (!addedHardClips) {
+                            if (totalHardClip > 0)
+                                cleanCigar.add(new CigarElement(totalHardClip, CigarOperator.HARD_CLIP));
+                            addedHardClips = true;
+                        }
+                        cleanCigar.add(cigarElement);
+                    }
+                }
+            }
+            // first pass  (i=1) is from end to start of the cigar elements
+            if (i == 1) {
+                shiftFromEnd = shift;
+                cigarStack = inverseCigarStack;
+            }
+            // second pass (i=2) is from start to end with the end already cleaned
+            else {
+                shiftFromStart = shift;
+            }
+        }
+        return new CigarShift(cleanCigar, shiftFromStart, shiftFromEnd);
+    }
+
+    /**
+     * Compute the offset of the first "real" position in the cigar on the genome
+     *
+     * This is defined as a first position after a run of Hs followed by a run of Ss
+     *
+     * @param cigar A non-null cigar
+     * @return the offset (from 0) of the first on-genome base
+     */
+    private int calcHardSoftOffset(final Cigar cigar) {
+        final List<CigarElement> elements = cigar.getCigarElements();
+
+        int size = 0;
+        int i = 0;
+        while ( i < elements.size() && elements.get(i).getOperator() == CigarOperator.HARD_CLIP ) {
+            size += elements.get(i).getLength();
+            i++;
+        }
+        while ( i < elements.size() && elements.get(i).getOperator() == CigarOperator.SOFT_CLIP ) {
+            size += elements.get(i).getLength();
+            i++;
+        }
+
+        return size;
+    }
+
+    private int calculateAlignmentStartShift(Cigar oldCigar, Cigar newCigar) {
+        final int newShift = calcHardSoftOffset(newCigar);
+        final int oldShift = calcHardSoftOffset(oldCigar);
+        return newShift - oldShift;
+    }
+
+    private int calculateHardClippingAlignmentShift(CigarElement cigarElement, int clippedLength) {
+        // Insertions should be discounted from the total hard clip count
+        if (cigarElement.getOperator() == CigarOperator.INSERTION)
+            return -clippedLength;
+
+            // Deletions and Ns should be added to the total hard clip count (because we want to maintain the original alignment start)
+        else if (cigarElement.getOperator() == CigarOperator.DELETION || cigarElement.getOperator() == CigarOperator.SKIPPED_REGION)
+            return cigarElement.getLength();
+
+        // There is no shift if we are not clipping an indel
+        return 0;
+    }
+
+    private static class CigarShift {
+        private Cigar cigar;
+        private int shiftFromStart;
+        private int shiftFromEnd;
+
+        private CigarShift(Cigar cigar, int shiftFromStart, int shiftFromEnd) {
+            this.cigar = cigar;
+            this.shiftFromStart = shiftFromStart;
+            this.shiftFromEnd = shiftFromEnd;
+        }
+    }
+}
\ No newline at end of file
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/clipping/ClippingRepresentation.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/clipping/ClippingRepresentation.java
new file mode 100644
index 0000000..5d86e0b
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/clipping/ClippingRepresentation.java
@@ -0,0 +1,63 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.utils.clipping;
+
+/**
+ * How should we represent a clipped bases in a read?
+ */
+public enum ClippingRepresentation {
+    /** Clipped bases are changed to Ns */
+    WRITE_NS,
+
+    /** Clipped bases are changed to have Q0 quality score */
+    WRITE_Q0S,
+
+    /** Clipped bases are change to have both an N base and a Q0 quality score */
+    WRITE_NS_Q0S,
+
+    /**
+     * Change the read's cigar string to soft clip (S, see sam-spec) away the bases.
+     * Note that this can only be applied to cases where the clipped bases occur
+     * at the start or end of a read.
+     */
+    SOFTCLIP_BASES,
+
+    /**
+     * WARNING: THIS OPTION IS STILL UNDER DEVELOPMENT AND IS NOT SUPPORTED.
+     *
+     * Change the read's cigar string to hard clip (H, see sam-spec) away the bases.
+     * Hard clipping, unlike soft clipping, actually removes bases from the read,
+     * reducing the resulting file's size but introducing an irrevesible (i.e.,
+     * lossy) operation.  Note that this can only be applied to cases where the clipped
+     * bases occur at the start or end of a read.
+     */
+    HARDCLIP_BASES,
+
+    /**
+     * Turn all soft-clipped bases into matches
+     */
+    REVERT_SOFTCLIPPED_BASES,
+}
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/clipping/ReadClipper.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/clipping/ReadClipper.java
new file mode 100644
index 0000000..c31784f
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/clipping/ReadClipper.java
@@ -0,0 +1,568 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.utils.clipping;
+
+import com.google.java.contract.Requires;
+import htsjdk.samtools.CigarElement;
+import htsjdk.samtools.CigarOperator;
+import org.broadinstitute.gatk.utils.exceptions.ReviewedGATKException;
+import org.broadinstitute.gatk.utils.recalibration.EventType;
+import org.broadinstitute.gatk.utils.sam.CigarUtils;
+import org.broadinstitute.gatk.utils.sam.GATKSAMRecord;
+import org.broadinstitute.gatk.utils.sam.ReadUtils;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * A comprehensive clipping tool.
+ *
+ * General Contract:
+ *  - All clipping operations return a new read with the clipped bases requested, it never modifies the original read.
+ *  - If a read is fully clipped, return an empty GATKSAMRecord, never null.
+ *  - When hard clipping, add cigar operator H for every *reference base* removed (i.e. Matches, SoftClips and Deletions, but *not* insertions). See Hard Clipping notes for details.
+ *
+ *
+ * There are several types of clipping to use:
+ *
+ * Write N's:
+ *   Change the bases to N's in the desired region. This can be applied anywhere in the read.
+ *
+ * Write Q0's:
+ *   Change the quality of the bases in the desired region to Q0. This can be applied anywhere in the read.
+ *
+ * Write both N's and Q0's:
+ *   Same as the two independent operations, put together.
+ *
+ * Soft Clipping:
+ *   Do not change the read, just mark the reads as soft clipped in the Cigar String
+ *   and adjust the alignment start and end of the read.
+ *
+ * Hard Clipping:
+ *   Creates a new read without the hard clipped bases (and base qualities). The cigar string
+ *   will be updated with the cigar operator H for every reference base removed (i.e. Matches,
+ *   Soft clipped bases and deletions, but *not* insertions). This contract with the cigar
+ *   is necessary to allow read.getUnclippedStart() / End() to recover the original alignment
+ *   of the read (before clipping).
+ *
+ */
+public class ReadClipper {
+    final GATKSAMRecord read;
+    boolean wasClipped;
+    List<ClippingOp> ops = null;
+
+    /**
+     * Initializes a ReadClipper object.
+     *
+     * You can set up your clipping operations using the addOp method. When you're ready to
+     * generate a new read with all the clipping operations, use clipRead().
+     *
+     * Note: Use this if you want to set up multiple operations on the read using the ClippingOp
+     * class. If you just want to apply one of the typical modes of clipping, use the static
+     * clipping functions available in this class instead.
+     *
+     * @param read the read to clip
+     */
+    public ReadClipper(final GATKSAMRecord read) {
+        this.read = read;
+        this.wasClipped = false;
+    }
+
+    /**
+     * Add clipping operation to the read.
+     *
+     * You can add as many operations as necessary to this read before clipping. Beware that the
+     * order in which you add these operations matter. For example, if you hard clip the beginning
+     * of a read first then try to hard clip the end, the indices will have changed. Make sure you
+     * know what you're doing, otherwise just use the static functions below that take care of the
+     * ordering for you.
+     *
+     * Note: You only choose the clipping mode when you use clipRead()
+     *
+     * @param op a ClippingOp object describing the area you want to clip.
+     */
+    public void addOp(ClippingOp op) {
+        if (ops == null) ops = new ArrayList<ClippingOp>();
+        ops.add(op);
+    }
+
+    /**
+     * Check the list of operations set up for this read.
+     *
+     * @return a list of the operations set up for this read.
+     */
+    public List<ClippingOp> getOps() {
+        return ops;
+    }
+
+    /**
+     * Check whether or not this read has been clipped.
+     * @return true if this read has produced a clipped read, false otherwise.
+     */
+    public boolean wasClipped() {
+        return wasClipped;
+    }
+
+    /**
+     * The original read.
+     *
+     * @return  returns the read to be clipped (original)
+     */
+    public GATKSAMRecord getRead() {
+        return read;
+    }
+
+    /**
+     * Clips a read according to ops and the chosen algorithm.
+     *
+     * @param algorithm What mode of clipping do you want to apply for the stacked operations.
+     * @return the read with the clipping applied.
+     */
+    public GATKSAMRecord clipRead(ClippingRepresentation algorithm) {
+        if (ops == null)
+            return getRead();
+
+        GATKSAMRecord clippedRead = read;
+        for (ClippingOp op : getOps()) {
+            final int readLength = clippedRead.getReadLength();
+            //check if the clipped read can still be clipped in the range requested
+            if (op.start < readLength) {
+                ClippingOp fixedOperation = op;
+                if (op.stop >= readLength)
+                    fixedOperation = new ClippingOp(op.start, readLength - 1);
+
+                clippedRead = fixedOperation.apply(algorithm, clippedRead);
+            }
+        }
+        wasClipped = true;
+        ops.clear();
+        if ( clippedRead.isEmpty() )
+            return GATKSAMRecord.emptyRead(clippedRead);
+        return clippedRead;
+    }
+
+
+    /**
+     * Hard clips the left tail of a read up to (and including) refStop using reference
+     * coordinates.
+     *
+     * @param refStop the last base to be hard clipped in the left tail of the read.
+     * @return a new read, without the left tail.
+     */
+    @Requires("!read.getReadUnmappedFlag()")  // can't handle unmapped reads, as we're using reference coordinates to clip
+    private GATKSAMRecord hardClipByReferenceCoordinatesLeftTail(int refStop) {
+        return hardClipByReferenceCoordinates(-1, refStop);
+    }
+    public static GATKSAMRecord hardClipByReferenceCoordinatesLeftTail(GATKSAMRecord read, int refStop) {
+        return (new ReadClipper(read)).hardClipByReferenceCoordinates(-1, refStop);
+    }
+
+
+
+    /**
+     * Hard clips the right tail of a read starting at (and including) refStart using reference
+     * coordinates.
+     *
+     * @param refStart refStop the first base to be hard clipped in the right tail of the read.
+     * @return a new read, without the right tail.
+     */
+    @Requires("!read.getReadUnmappedFlag()")  // can't handle unmapped reads, as we're using reference coordinates to clip
+    private GATKSAMRecord hardClipByReferenceCoordinatesRightTail(int refStart) {
+        return hardClipByReferenceCoordinates(refStart, -1);
+    }
+    public static GATKSAMRecord hardClipByReferenceCoordinatesRightTail(GATKSAMRecord read, int refStart) {
+        return (new ReadClipper(read)).hardClipByReferenceCoordinates(refStart, -1);
+    }
+
+    /**
+     * Hard clips a read using read coordinates.
+     *
+     * @param start the first base to clip (inclusive)
+     * @param stop the last base to clip (inclusive)
+     * @return a new read, without the clipped bases
+     */
+    @Requires({"start >= 0 && stop <= read.getReadLength() - 1",   // start and stop have to be within the read
+               "start == 0 || stop == read.getReadLength() - 1"})  // cannot clip the middle of the read
+    private GATKSAMRecord hardClipByReadCoordinates(int start, int stop) {
+        if (read.isEmpty() || (start == 0 && stop == read.getReadLength() - 1))
+            return GATKSAMRecord.emptyRead(read);
+
+        this.addOp(new ClippingOp(start, stop));
+        return clipRead(ClippingRepresentation.HARDCLIP_BASES);
+    }
+    public static GATKSAMRecord hardClipByReadCoordinates(GATKSAMRecord read, int start, int stop) {
+        return (new ReadClipper(read)).hardClipByReadCoordinates(start, stop);
+    }
+
+
+    /**
+     * Hard clips both tails of a read.
+     *   Left tail goes from the beginning to the 'left' coordinate (inclusive)
+     *   Right tail goes from the 'right' coordinate (inclusive) until the end of the read
+     *
+     * @param left the coordinate of the last base to be clipped in the left tail (inclusive)
+     * @param right the coordinate of the first base to be clipped in the right tail (inclusive)
+     * @return a new read, without the clipped bases
+     */
+    @Requires({"left <= right",                    // tails cannot overlap
+               "left >= read.getAlignmentStart()", // coordinate has to be within the mapped read
+               "right <= read.getAlignmentEnd()"}) // coordinate has to be within the mapped read
+    private GATKSAMRecord hardClipBothEndsByReferenceCoordinates(int left, int right) {
+        if (read.isEmpty() || left == right)
+            return GATKSAMRecord.emptyRead(read);
+        GATKSAMRecord leftTailRead = hardClipByReferenceCoordinates(right, -1);
+
+        // after clipping one tail, it is possible that the consequent hard clipping of adjacent deletions
+        // make the left cut index no longer part of the read. In that case, clip the read entirely.
+        if (left > leftTailRead.getAlignmentEnd())
+            return GATKSAMRecord.emptyRead(read);
+
+        ReadClipper clipper = new ReadClipper(leftTailRead);
+        return clipper.hardClipByReferenceCoordinatesLeftTail(left);
+    }
+    public static GATKSAMRecord hardClipBothEndsByReferenceCoordinates(GATKSAMRecord read, int left, int right) {
+        return (new ReadClipper(read)).hardClipBothEndsByReferenceCoordinates(left, right);
+    }
+
+
+    /**
+     * Clips any contiguous tail (left, right or both) with base quality lower than lowQual using the desired algorithm.
+     *
+     * This function will look for low quality tails and hard clip them away. A low quality tail
+     * ends when a base has base quality greater than lowQual.
+     *
+     * @param algorithm the algorithm to use (HardClip, SoftClip, Write N's,...)
+     * @param lowQual every base quality lower than or equal to this in the tail of the read will be hard clipped
+     * @return a new read without low quality tails
+     */
+    private GATKSAMRecord clipLowQualEnds(ClippingRepresentation algorithm, byte lowQual) {
+        if (read.isEmpty())
+            return read;
+
+        final byte [] quals = read.getBaseQualities();
+        final int readLength = read.getReadLength();
+        int leftClipIndex = 0;
+        int rightClipIndex = readLength - 1;
+
+        // check how far we can clip both sides
+        while (rightClipIndex >= 0 && quals[rightClipIndex] <= lowQual) rightClipIndex--;
+        while (leftClipIndex < readLength && quals[leftClipIndex] <= lowQual) leftClipIndex++;
+
+        // if the entire read should be clipped, then return an empty read.
+        if (leftClipIndex > rightClipIndex)
+            return GATKSAMRecord.emptyRead(read);
+
+        if (rightClipIndex < readLength - 1) {
+            this.addOp(new ClippingOp(rightClipIndex + 1, readLength - 1));
+        }
+        if (leftClipIndex > 0 ) {
+            this.addOp(new ClippingOp(0, leftClipIndex - 1));
+        }
+        return this.clipRead(algorithm);
+    }
+
+    private GATKSAMRecord hardClipLowQualEnds(byte lowQual) {
+        return this.clipLowQualEnds(ClippingRepresentation.HARDCLIP_BASES, lowQual);
+    }
+    public static GATKSAMRecord hardClipLowQualEnds(GATKSAMRecord read, byte lowQual) {
+        return (new ReadClipper(read)).hardClipLowQualEnds(lowQual);
+    }
+    public static GATKSAMRecord clipLowQualEnds(GATKSAMRecord read, byte lowQual, ClippingRepresentation algorithm) {
+        return (new ReadClipper(read)).clipLowQualEnds(algorithm, lowQual);
+    }
+
+
+    /**
+     * Will hard clip every soft clipped bases in the read.
+     *
+     * @return a new read without the soft clipped bases
+     */
+    private GATKSAMRecord hardClipSoftClippedBases () {
+        if (read.isEmpty())
+            return read;
+
+        int readIndex = 0;
+        int cutLeft = -1;            // first position to hard clip (inclusive)
+        int cutRight = -1;           // first position to hard clip (inclusive)
+        boolean rightTail = false;   // trigger to stop clipping the left tail and start cutting the right tail
+
+        for (CigarElement cigarElement : read.getCigar().getCigarElements()) {
+            if (cigarElement.getOperator() == CigarOperator.SOFT_CLIP) {
+                if (rightTail) {
+                    cutRight = readIndex;
+                }
+                else {
+                    cutLeft = readIndex + cigarElement.getLength() - 1;
+                }
+            }
+            else if (cigarElement.getOperator() != CigarOperator.HARD_CLIP)
+                rightTail = true;
+
+            if (cigarElement.getOperator().consumesReadBases())
+                readIndex += cigarElement.getLength();
+        }
+
+        // It is extremely important that we cut the end first otherwise the read coordinates change.
+        if (cutRight >= 0)
+            this.addOp(new ClippingOp(cutRight, read.getReadLength() - 1));
+        if (cutLeft >= 0)
+            this.addOp(new ClippingOp(0, cutLeft));
+
+        return clipRead(ClippingRepresentation.HARDCLIP_BASES);
+    }
+    public static GATKSAMRecord hardClipSoftClippedBases (GATKSAMRecord read) {
+        return (new ReadClipper(read)).hardClipSoftClippedBases();
+    }
+
+
+    /**
+     * Hard clip the read to the variable region (from refStart to refStop)
+     *
+     * @param read     the read to be clipped
+     * @param refStart the beginning of the variant region (inclusive)
+     * @param refStop  the end of the variant region (inclusive)
+     * @return the read hard clipped to the variant region
+     */
+    public static GATKSAMRecord hardClipToRegion( final GATKSAMRecord read, final int refStart, final int refStop ) {
+        final int start = read.getAlignmentStart();
+        final int stop = read.getAlignmentEnd();
+        return hardClipToRegion(read, refStart, refStop,start,stop);
+    }
+
+    /**
+     * Hard clip the read to the variable region (from refStart to refStop) processing also the clipped bases
+     *
+     * @param read     the read to be clipped
+     * @param refStart the beginning of the variant region (inclusive)
+     * @param refStop  the end of the variant region (inclusive)
+     * @return the read hard clipped to the variant region
+     */
+    public static GATKSAMRecord hardClipToRegionIncludingClippedBases( final GATKSAMRecord read, final int refStart, final int refStop ) {
+        final int start = read.getOriginalAlignmentStart();
+        final int stop = start + CigarUtils.countRefBasesBasedOnCigar(read,0,read.getCigarLength()) - 1;
+        return hardClipToRegion(read, refStart, refStop,start,stop);
+    }
+
+    private static GATKSAMRecord hardClipToRegion( final GATKSAMRecord read, final int refStart, final int refStop, final int alignmentStart, final int alignmentStop){
+        // check if the read is contained in region
+        if (alignmentStart <= refStop && alignmentStop >= refStart) {
+            if (alignmentStart < refStart && alignmentStop > refStop)
+                return hardClipBothEndsByReferenceCoordinates(read, refStart - 1, refStop + 1);
+            else if (alignmentStart < refStart)
+                return hardClipByReferenceCoordinatesLeftTail(read, refStart - 1);
+            else if (alignmentStop > refStop)
+                return hardClipByReferenceCoordinatesRightTail(read, refStop + 1);
+            return read;
+        } else
+            return GATKSAMRecord.emptyRead(read);
+
+    }
+
+    public static List<GATKSAMRecord> hardClipToRegion( final List<GATKSAMRecord> reads, final int refStart, final int refStop ) {
+        final List<GATKSAMRecord> returnList = new ArrayList<GATKSAMRecord>( reads.size() );
+        for( final GATKSAMRecord read : reads ) {
+            final GATKSAMRecord clippedRead = hardClipToRegion( read, refStart, refStop );
+            if( !clippedRead.isEmpty() ) {
+                returnList.add( clippedRead );
+            }
+        }
+        return returnList;
+    }
+
+    /**
+     * Checks if a read contains adaptor sequences. If it does, hard clips them out.
+     *
+     * Note: To see how a read is checked for adaptor sequence see ReadUtils.getAdaptorBoundary()
+     *
+     * @return a new read without adaptor sequence
+     */
+    private GATKSAMRecord hardClipAdaptorSequence () {
+        final int adaptorBoundary = ReadUtils.getAdaptorBoundary(read);
+
+        if (adaptorBoundary == ReadUtils.CANNOT_COMPUTE_ADAPTOR_BOUNDARY || !ReadUtils.isInsideRead(read, adaptorBoundary))
+            return read;
+
+        return read.getReadNegativeStrandFlag() ? hardClipByReferenceCoordinatesLeftTail(adaptorBoundary) : hardClipByReferenceCoordinatesRightTail(adaptorBoundary);
+    }
+    public static GATKSAMRecord hardClipAdaptorSequence (GATKSAMRecord read) {
+        return (new ReadClipper(read)).hardClipAdaptorSequence();
+    }
+
+
+    /**
+     * Hard clips any leading insertions in the read. Only looks at the beginning of the read, not the end.
+     *
+     * @return a new read without leading insertions
+     */
+    private GATKSAMRecord hardClipLeadingInsertions() {
+        if (read.isEmpty())
+            return read;
+
+        for(CigarElement cigarElement : read.getCigar().getCigarElements()) {
+            if (cigarElement.getOperator() != CigarOperator.HARD_CLIP && cigarElement.getOperator() != CigarOperator.SOFT_CLIP &&
+                cigarElement.getOperator() != CigarOperator.INSERTION)
+                break;
+
+            else if (cigarElement.getOperator() == CigarOperator.INSERTION)
+                this.addOp(new ClippingOp(0, cigarElement.getLength() - 1));
+
+        }
+        return clipRead(ClippingRepresentation.HARDCLIP_BASES);
+    }
+    public static GATKSAMRecord hardClipLeadingInsertions(GATKSAMRecord read) {
+        return (new ReadClipper(read)).hardClipLeadingInsertions();
+    }
+
+
+    /**
+     * Turns soft clipped bases into matches
+     * @return a new read with every soft clip turned into a match
+     */
+    private GATKSAMRecord revertSoftClippedBases() {
+        if (read.isEmpty())
+            return read;
+
+        this.addOp(new ClippingOp(0, 0));
+        return this.clipRead(ClippingRepresentation.REVERT_SOFTCLIPPED_BASES);
+    }
+
+    /**
+     * Reverts ALL soft-clipped bases
+     *
+     * @param read the read
+     * @return the read with all soft-clipped bases turned into matches
+     */
+    public static GATKSAMRecord revertSoftClippedBases(GATKSAMRecord read) {
+        return (new ReadClipper(read)).revertSoftClippedBases();
+    }
+
+    /**
+     * Reverts only soft clipped bases with quality score greater than or equal to minQual
+     *
+     * todo -- Note: Will write a temporary field with the number of soft clips that were undone on each side (left: 'SL', right: 'SR') -- THIS HAS BEEN REMOVED TEMPORARILY SHOULD HAPPEN INSIDE THE CLIPPING ROUTINE!
+     *
+     * @param read    the read
+     * @param minQual the mininum base quality score to revert the base (inclusive)
+     * @return a new read with high quality soft clips reverted
+     */
+    public static GATKSAMRecord revertSoftClippedBases(GATKSAMRecord read, byte minQual) {
+        return revertSoftClippedBases(hardClipLowQualitySoftClips(read, minQual));
+    }
+
+    /**
+     * Hard clips away soft clipped bases that are below the given quality threshold
+     *
+     * @param read    the read
+     * @param minQual the mininum base quality score to revert the base (inclusive)
+     * @return a new read without low quality soft clipped bases
+     */
+    public static GATKSAMRecord hardClipLowQualitySoftClips(GATKSAMRecord read, byte minQual) {
+        int nLeadingSoftClips = read.getAlignmentStart() - read.getSoftStart();
+        if (read.isEmpty() || nLeadingSoftClips > read.getReadLength())
+            return GATKSAMRecord.emptyRead(read);
+
+        byte [] quals = read.getBaseQualities(EventType.BASE_SUBSTITUTION);
+        int left = -1;
+
+        if (nLeadingSoftClips > 0) {
+            for (int i = nLeadingSoftClips - 1; i >= 0; i--) {
+                if (quals[i] >= minQual)
+                    left = i;
+                else
+                    break;
+            }
+        }
+
+        int right = -1;
+        int nTailingSoftClips = read.getSoftEnd() - read.getAlignmentEnd();
+        if (nTailingSoftClips > 0) {
+            for (int i = read.getReadLength() - nTailingSoftClips; i < read.getReadLength() ; i++) {
+                if (quals[i] >= minQual)
+                    right = i;
+                else
+                    break;
+            }
+        }
+
+        GATKSAMRecord clippedRead = read;
+        if (right >= 0 && right + 1 < clippedRead.getReadLength())                                                      // only clip if there are softclipped bases (right >= 0) and the first high quality soft clip is not the last base (right+1 < readlength)
+                clippedRead = hardClipByReadCoordinates(clippedRead, right+1, clippedRead.getReadLength()-1);           // first we hard clip the low quality soft clips on the right tail
+        if (left >= 0 && left - 1 > 0)                                                                                  // only clip if there are softclipped bases (left >= 0) and the first high quality soft clip is not the last base (left-1 > 0)
+                clippedRead = hardClipByReadCoordinates(clippedRead, 0, left-1);                                        // then we hard clip the low quality soft clips on the left tail
+
+        return clippedRead;
+    }
+
+    /**
+     * Generic functionality to hard clip a read, used internally by hardClipByReferenceCoordinatesLeftTail
+     * and hardClipByReferenceCoordinatesRightTail. Should not be used directly.
+     *
+     * Note, it REQUIRES you to give the directionality of your hard clip (i.e. whether you're clipping the
+     * left of right tail) by specifying either refStart < 0 or refStop < 0.
+     *
+     * @param refStart  first base to clip (inclusive)
+     * @param refStop last base to clip (inclusive)
+     * @return a new read, without the clipped bases
+     */
+    @Requires({"!read.getReadUnmappedFlag()", "refStart < 0 || refStop < 0"})  // can't handle unmapped reads, as we're using reference coordinates to clip
+    protected GATKSAMRecord hardClipByReferenceCoordinates(int refStart, int refStop) {
+        if (read.isEmpty())
+            return read;
+
+        int start;
+        int stop;
+
+        // Determine the read coordinate to start and stop hard clipping
+        if (refStart < 0) {
+            if (refStop < 0)
+                throw new ReviewedGATKException("Only one of refStart or refStop must be < 0, not both (" + refStart + ", " + refStop + ")");
+            start = 0;
+            stop = ReadUtils.getReadCoordinateForReferenceCoordinate(read, refStop, ReadUtils.ClippingTail.LEFT_TAIL);
+        }
+        else {
+            if (refStop >= 0)
+                throw new ReviewedGATKException("Either refStart or refStop must be < 0 (" + refStart + ", " + refStop + ")");
+            start = ReadUtils.getReadCoordinateForReferenceCoordinate(read, refStart, ReadUtils.ClippingTail.RIGHT_TAIL);
+            stop = read.getReadLength() - 1;
+        }
+
+        if (start < 0 || stop > read.getReadLength() - 1)
+            throw new ReviewedGATKException("Trying to clip before the start or after the end of a read");
+
+        if ( start > stop )
+            throw new ReviewedGATKException(String.format("START (%d) > (%d) STOP -- this should never happen, please check read: %s (CIGAR: %s)", start, stop, read, read.getCigarString()));
+
+        if ( start > 0 && stop < read.getReadLength() - 1)
+            throw new ReviewedGATKException(String.format("Trying to clip the middle of the read: start %d, stop %d, cigar: %s", start, stop, read.getCigarString()));
+
+        this.addOp(new ClippingOp(start, stop));
+        GATKSAMRecord clippedRead = clipRead(ClippingRepresentation.HARDCLIP_BASES);
+        this.ops = null;
+        return clippedRead;
+    }
+
+
+}
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/codecs/beagle/BeagleCodec.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/codecs/beagle/BeagleCodec.java
new file mode 100644
index 0000000..9159003
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/codecs/beagle/BeagleCodec.java
@@ -0,0 +1,276 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.utils.codecs.beagle;
+/*
+ * Copyright (c) 2010 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.
+ */
+
+
+import htsjdk.tribble.AsciiFeatureCodec;
+import htsjdk.tribble.exception.CodecLineParsingException;
+import htsjdk.tribble.readers.LineIterator;
+import org.broadinstitute.gatk.engine.refdata.ReferenceDependentFeatureCodec;
+import org.broadinstitute.gatk.utils.GenomeLoc;
+import org.broadinstitute.gatk.utils.GenomeLocParser;
+
+import java.io.IOException;
+import java.util.*;
+import java.util.regex.Pattern;
+
+/**
+ * Codec for Beagle imputation engine
+ *
+ * <p>
+ * Reads in tabular files with site markers and genotype posteriors, genotypes and phasing that Beagle produced
+ * </p>
+ *
+ * <p>
+ * See also: @see <a href="http://faculty.washington.edu/browning/beagle/beagle.html">BEAGLE home page</a><br>
+ * </p>
+
+ * </p>
+ *
+ * <h2>File format example for phased genotypes file</h2>
+ * <pre>
+ *     dummy header
+ *      20:60251 T T T T T T
+ *      20:60321 G G G G G G
+ *      20:60467 G G G G G G
+ * </pre>
+ *
+ * <h2>File format example for genotype posteriors</h2>
+ * <pre>
+ *     marker alleleA alleleB NA07056 NA07056 NA07056
+ *     20:60251 T C 0.9962 0.0038 0 0.99245 0.00755 0 0.99245 0.00755 0
+ *     20:60321 G T 0.98747 0.01253 0 0.99922 0.00078 0 0.99368 0.00632 0
+ *     20:60467 G C 0.97475 0.02525 0 0.98718 0.01282 0 0.98718 0.01282 0
+ * </pre>
+ *
+ * <h2>File format example for r2 file
+ * <pre>
+ *      20:60251        0.747
+ *      20:60321        0.763
+ *      20:60467        0.524
+ * </pre>
+ * </h2>
+ * @author Mark DePristo
+ * @since 2010
+ */
+public class BeagleCodec extends AsciiFeatureCodec<BeagleFeature> implements ReferenceDependentFeatureCodec {
+    private String[] header;
+    public enum BeagleReaderType {PROBLIKELIHOOD, GENOTYPES, R2};
+    private BeagleReaderType readerType;
+    private int valuesPerSample;
+    private int initialSampleIndex;
+    private int markerPosition;
+    private ArrayList<String> sampleNames;
+    private int expectedTokensPerLine;
+    private final static Set<String> HEADER_IDs = new HashSet<String>(Arrays.asList("marker", "I"));
+
+    private static final String delimiterRegex = "\\s+";
+
+    /**
+     * The parser to use when resolving genome-wide locations.
+     */
+    private GenomeLocParser genomeLocParser;
+
+    public BeagleCodec() {
+        super(BeagleFeature.class);
+    }
+
+    /**
+     * Set the parser to use when resolving genetic data.
+     * @param genomeLocParser The supplied parser.
+     */
+    public void setGenomeLocParser(GenomeLocParser genomeLocParser) {
+        this.genomeLocParser =  genomeLocParser;
+    }
+
+    @Override
+    public Object readActualHeader(LineIterator reader) {
+        int[] lineCounter = new int[1];
+        try {
+            header = readHeader(reader, lineCounter);
+
+            Boolean getSamples = true;
+            markerPosition = 0; //default value for all readers
+
+            if (header[0].matches("I")) {
+                // Phased genotype Beagle files start with "I"
+                readerType = BeagleReaderType.GENOTYPES;
+                valuesPerSample = 2;
+                initialSampleIndex = 2;
+                markerPosition = 1;
+            }
+            else if (header[0].matches("marker")) {
+                readerType = BeagleReaderType.PROBLIKELIHOOD;
+                valuesPerSample = 3;
+                initialSampleIndex = 3;
+            }
+            else {
+                readerType = BeagleReaderType.R2;
+                getSamples = false;
+                // signal we don't have a header
+                lineCounter[0] = 0;
+                // not needed, but for consistency:
+                valuesPerSample = 0;
+                initialSampleIndex = 0;
+            }
+
+            sampleNames = new ArrayList<String>();
+
+            if (getSamples) {
+                for (int k = initialSampleIndex; k < header.length; k += valuesPerSample)
+                    sampleNames.add(header[k]);
+
+                expectedTokensPerLine = sampleNames.size()*valuesPerSample+initialSampleIndex;
+
+            } else {
+                expectedTokensPerLine = 2;
+            }
+
+
+        } catch(IOException e) {
+            throw new IllegalArgumentException("Unable to read from file.", e);
+        }
+        return header;
+    }
+
+    private static String[] readHeader(final LineIterator source, int[] lineCounter) throws IOException {
+
+        String[] header = null;
+        int numLines = 0;
+
+        //find the 1st line that's non-empty and not a comment
+        while(source.hasNext()) {
+            final String line = source.next();
+            numLines++;
+            if ( line.trim().isEmpty() ) {
+                continue;
+            }
+
+            //parse the header
+            header = line.split(delimiterRegex);
+            break;
+        }
+
+        // check that we found the header
+        if ( header == null ) {
+            throw new IllegalArgumentException("No header in " + source);
+        }
+
+        if(lineCounter != null) {
+            lineCounter[0] = numLines;
+        }
+
+        return header;
+    }
+
+    private static Pattern MARKER_PATTERN = Pattern.compile("(.+):([0-9]+)");
+
+    public BeagleFeature decode(String line) {
+        String[] tokens;
+
+        // split the line
+        tokens = line.split(delimiterRegex);
+        if (tokens.length != expectedTokensPerLine)
+            throw new CodecLineParsingException("Incorrect number of fields in Beagle input on line "+line);
+
+        if ( HEADER_IDs.contains(tokens[0]) )
+            return null;
+
+        BeagleFeature bglFeature = new BeagleFeature();
+
+        final GenomeLoc loc = genomeLocParser.parseGenomeLoc(tokens[markerPosition]); //GenomeLocParser.parseGenomeLoc(values.get(0)); - TODO switch to this
+
+        //parse the location: common to all readers
+        bglFeature.setChr(loc.getContig());
+        bglFeature.setStart((int) loc.getStart());
+        bglFeature.setEnd((int) loc.getStop());
+
+        // Parse R2 if needed
+        if (readerType == BeagleReaderType.R2) {
+            bglFeature.setR2value(Double.valueOf(tokens[1]));
+        }
+        else if (readerType == BeagleReaderType.GENOTYPES) {
+            // read phased Genotype pairs
+            HashMap<String, ArrayList<String>> sampleGenotypes = new HashMap<String, ArrayList<String>>();
+
+            for ( int i = 2; i < tokens.length; i+=2 ) {
+                String sampleName = sampleNames.get(i/2-1);
+                if ( ! sampleGenotypes.containsKey(sampleName) ) {
+                    sampleGenotypes.put(sampleName, new ArrayList<String>());
+                }
+
+                sampleGenotypes.get(sampleName).add(tokens[i]);
+                sampleGenotypes.get(sampleName).add(tokens[i+1]);
+            }
+
+            bglFeature.setGenotypes(sampleGenotypes);
+        }
+        else {
+            // read probabilities/likelihood trios and alleles
+            bglFeature.setAlleleA(tokens[1], true);
+            bglFeature.setAlleleB(tokens[2], false);
+            HashMap<String, ArrayList<String>> sampleProbLikelihoods = new HashMap<String, ArrayList<String>>();
+
+            for ( int i = 3; i < tokens.length; i+=3 ) {
+                String sampleName = sampleNames.get(i/3-1);
+                if ( ! sampleProbLikelihoods.containsKey(sampleName) ) {
+                    sampleProbLikelihoods.put(sampleName, new ArrayList<String>());
+                }
+
+                sampleProbLikelihoods.get(sampleName).add(tokens[i]);
+                sampleProbLikelihoods.get(sampleName).add(tokens[i+1]);
+                sampleProbLikelihoods.get(sampleName).add(tokens[i+2]);
+            }
+            bglFeature.setProbLikelihoods(sampleProbLikelihoods);
+        }
+
+        return bglFeature;
+    }
+}
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/codecs/beagle/BeagleFeature.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/codecs/beagle/BeagleFeature.java
new file mode 100644
index 0000000..bd9e4ef
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/codecs/beagle/BeagleFeature.java
@@ -0,0 +1,111 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.utils.codecs.beagle;
+
+import htsjdk.tribble.Feature;
+import htsjdk.variant.variantcontext.Allele;
+
+import java.util.ArrayList;
+import java.util.Map;
+
+public class BeagleFeature implements Feature {
+
+    private String chr;
+    private int start;
+    private int end;
+
+    Map<String, ArrayList<String>> sampleGenotypes;
+    private Double r2Value;
+    Map<String, ArrayList<String>> probLikelihoods;
+
+    Allele AlleleA;
+    Allele AlleleB;
+
+
+    public String getChr() {
+        return chr;
+    }
+
+    public int getStart() {
+        return start;
+    }
+
+    public int getEnd() {
+        return end;
+    }
+
+    public Double getR2value() {
+        return r2Value;
+    }
+
+    public Allele getAlleleA() {
+        return AlleleA;
+    }
+
+    public Allele getAlleleB() {
+        return AlleleB;
+    }
+
+    public Map<String, ArrayList<String>> getProbLikelihoods() {
+        return probLikelihoods;
+    }
+
+    public Map<String, ArrayList<String>> getGenotypes() {
+        return sampleGenotypes;        
+    }
+
+    protected void setChr(String chr) {
+       this.chr = chr;
+    }
+
+    protected void setStart(int start) {
+        this.start = start;
+    }
+
+    protected void setEnd(int end) {
+        this.end = end;
+    }
+
+    protected void setR2value(double r2) {
+        this.r2Value = r2;
+    }
+
+    protected void setAlleleA(String a, boolean isRef) {
+        this.AlleleA = Allele.create(a, isRef);
+    }
+
+    protected void setAlleleB(String a, boolean isRef) {
+        this.AlleleB = Allele.create(a, isRef);
+    }
+
+    protected void setProbLikelihoods(Map<String, ArrayList<String>> p) {
+        this.probLikelihoods = p;
+    }
+
+    protected void setGenotypes(Map<String, ArrayList<String>> p) {
+        this.sampleGenotypes = p;
+    }
+}
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/codecs/hapmap/RawHapMapCodec.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/codecs/hapmap/RawHapMapCodec.java
new file mode 100644
index 0000000..ac50853
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/codecs/hapmap/RawHapMapCodec.java
@@ -0,0 +1,125 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.utils.codecs.hapmap;
+
+import htsjdk.tribble.AsciiFeatureCodec;
+import htsjdk.tribble.FeatureCodecHeader;
+import htsjdk.tribble.annotation.Strand;
+import htsjdk.tribble.readers.LineIterator;
+
+import java.io.IOException;
+import java.util.Arrays;
+
+/**
+ * A codec for the file types produced by the HapMap consortium
+ *
+ * <p>
+ *     The format includes eleven standard fields, plus genotypes for each of the samples included
+ *     in the file:
+ *
+ * <pre>
+ *     Col1: refSNP rs# identifier at the time of release (NB might merge with another rs# in the future)
+ *     Col2: SNP alleles according to dbSNP
+ *     Col3: chromosome that SNP maps to
+ *     Col4: chromosome position of SNP, in basepairs on reference sequence
+ *     Col5: strand of reference sequence that SNP maps to
+ *     Col6: version of reference sequence assembly
+ *     Col7: HapMap genotype center that produced the genotypes
+ *     Col8: LSID for HapMap protocol used for genotyping
+ *     Col9: LSID for HapMap assay used for genotyping
+ *     Col10: LSID for panel of individuals genotyped
+ *     Col11: QC-code, currently 'QC+' for all entries (for future use)
+ *     Col12 and on: observed genotypes of samples, one per column, sample identifiers in column headers (Coriell catalog numbers, example: NA10847). Duplicate samples have .dup suffix.
+ * </pre>
+ * </p>
+ *
+ * <p>
+ *  See also: @See <a href="http://hapmap.ncbi.nlm.nih.gov/downloads/genotypes/">HapMap genotypes download</a>
+ * </p>
+ *
+ * <h2>File format example</h2>
+ * From <a href="http://hapmap.ncbi.nlm.nih.gov/downloads/genotypes/latest/forward/non-redundant/genotypes_chr1_ASW_r27_nr.b36_fwd.txt.gz">genotypes_chr1_ASW_r27_nr.b36_fwd.txt.gz</a>:
+ * <pre>
+ *     rs# alleles chrom pos strand assembly# center protLSID assayLSID panelLSID QCcode NA19625 NA19700 NA19701 NA19702 NA19703 NA19704 NA19705 NA19708 NA19712 NA19711 NA19818 NA19819 NA19828 NA19835 NA19834 NA19836 NA19902 NA19901 NA19900 NA19904 NA19919 NA19908 NA19909 NA19914 NA19915 NA19916 NA19917 NA19918 NA19921 NA20129 NA19713 NA19982 NA19983 NA19714 NA19985 NA20128 NA20126 NA20127 NA20277 NA20276 NA20279 NA20282 NA20281 NA20284 NA20287 NA20288 NA20290 NA20289 NA20291 NA20292 NA2 [...]
+ *     rs9629043 C/T chr1 554636 + ncbi_b36 broad urn:LSID:affymetrix.hapmap.org:Protocol:GenomeWideSNP_6.0:3 urn:LSID:broad.hapmap.org:Assay:SNP_A-8575115:3 urn:lsid:dcc.hapmap.org:Panel:US_African-30-trios:3 QC+ CC CC CC CC CC CC CC CC CC CC CC CC NN CC CC CC CT CT CC CC CC CC CC CC CC CC CC CC CC CC CC CC CC CC CC CC CC CC CC CC CC CC CC CC CC CC CC CC CC CC CC CC CC CC CT CC CC CC CC CC CC CC CC CC CC CC CC CC CC CC CC CC CC CC CC CC CC CC CC CC CC CC CC
+ *     rs28446478 G/T chr1 576058 + ncbi_b36 sanger urn:LSID:illumina.hapmap.org:Protocol:Human_1M_BeadChip:3 urn:LSID:sanger.hapmap.org:Assay:H1Mrs28446478:3 urn:lsid:dcc.hapmap.org:Panel:US_African-30-trios:3 QC+ GT TT GT TT TT TT TT GT GT TT TT TT TT GT GT GT GT TT GT TT GT GT TT GT GT TT TT TT GT GT TT TT TT GT TT GT TT GT GT GT GT GT TT GT TT TT GT GT TT TT TT TT TT TT GT GT GT GT TT TT TT TT GT TT GT TT TT GT TT TT TT GT TT TT TT GT GT TT GT TT GT TT TT
+ *     rs12565286 C/G chr1 711153 + ncbi_b36 broad urn:LSID:affymetrix.hapmap.org:Protocol:GenomeWideSNP_6.0:3 urn:LSID:broad.hapmap.org:Assay:SNP_A-8709646:3 urn:lsid:dcc.hapmap.org:Panel:US_African-30-trios:3 QC+ GG GG GG GG GG GG GG GG CG GG GG GG GG GG GG GG GG GG GG CG GG GG GG GG GG GG GG GG GG GG GG GG GG GG GG GG GG GG GG GG CG GG GG GG GG GG GG GG CG CG GG GG GG GG GG GG GG GG GG CG CG GG GG GG GG GG GG GG GG GG GG CG NN GG GG GG GG GG GG NN GG NN NN
+ * </pre>
+ *
+ * @author Mark DePristo
+ * @since 2010
+ */
+public class RawHapMapCodec extends AsciiFeatureCodec<RawHapMapFeature> {
+    // the minimum number of features in the HapMap file line
+    private static final int minimumFeatureCount = 11;
+
+    private String headerLine;
+
+    public RawHapMapCodec() {
+        super(RawHapMapFeature.class);
+    }
+
+    /**
+     * decode the hapmap record
+     * @param line the input line to decode
+     * @return a HapMapFeature, with the given fields 
+     */
+    public RawHapMapFeature decode(String line) {
+        String[] array = line.split("\\s+");
+
+        // make sure the split was successful - that we got an appropriate number of fields
+        if (array.length < minimumFeatureCount)
+            throw new IllegalArgumentException("Unable to parse line " + line + ", the length of split features is less than the minimum of " + minimumFeatureCount);
+
+        // create a new feature given the array
+        return new RawHapMapFeature(array[0],
+                array[1].split("/"),
+                array[2],
+                Long.valueOf(array[3]),
+                Strand.toStrand(array[4]),
+                array[5],
+                array[6],
+                array[7],
+                array[8],
+                array[9],
+                array[10],
+                Arrays.copyOfRange(array,11,array.length),
+                headerLine);
+    }
+
+    @Override
+    public Object readActualHeader(final LineIterator lineIterator) {
+        this.headerLine = lineIterator.next();
+        return headerLine;
+    }
+
+    @Override
+    public FeatureCodecHeader readHeader(final LineIterator lineIterator) throws IOException {
+        final String header = (String) readActualHeader(lineIterator);
+        // TODO: This approach may cause issues with files formatted with \r\n-style line-endings.
+        return new FeatureCodecHeader(header, header.length() + 1);
+    }
+}
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/codecs/hapmap/RawHapMapFeature.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/codecs/hapmap/RawHapMapFeature.java
new file mode 100644
index 0000000..a9b8788
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/codecs/hapmap/RawHapMapFeature.java
@@ -0,0 +1,196 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.utils.codecs.hapmap;
+
+import htsjdk.tribble.Feature;
+import htsjdk.tribble.annotation.Strand;
+import htsjdk.variant.variantcontext.Allele;
+
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * a feature returned by the HapMap Codec - it represents contig, position, name,
+ * alleles, other hapmap information, and genotypes for specified samples
+ */
+public class RawHapMapFeature implements Feature {
+
+    public static final String NULL_ALLELE_STRING = "-";
+    public static final String INSERTION = "I";
+    public static final String DELETION = "D";
+
+    // the variables we store internally in the class
+    private final String name;
+    private final String[] alleles;
+    private Map<String, Allele> actualAlleles = null;
+    private final String contig ;
+    private long position;
+    private final Strand strand;
+    private final String assembly;
+    private final String center;
+    private final String protLSID;
+    private final String assayLSID;
+    private final String panelLSID;
+    private final String qccode;
+    private final String[] genotypes;
+
+    // we store the header line, if they'd like to get the samples
+    private final String headerLine;
+
+    /**
+     * create a HapMap Feature, based on all the records available in the hapmap file
+     * @param contig the contig name
+     * @param position the position
+     * @param strand the strand enum
+     * @param assembly what assembly this feature is from
+     * @param center the center that provided this SNP
+     * @param protLSID ??
+     * @param assayLSID ??
+     * @param panelLSID ??
+     * @param qccode ??
+     * @param genotypes a list of strings, representing the genotypes for the list of samples
+     */
+    public RawHapMapFeature(String name,
+                            String[] alleles,
+                            String contig,
+                            Long position,
+                            Strand strand,
+                            String assembly,
+                            String center,
+                            String protLSID,
+                            String assayLSID,
+                            String panelLSID,
+                            String qccode,
+                            String[] genotypes,
+                            String headerLine) {
+        this.name = name;
+        this.alleles = alleles;
+        this.contig = contig;
+        this.position = position;
+        this.strand = strand;
+        this.assembly =  assembly;
+        this.center =  center;
+        this.protLSID = protLSID ;
+        this.assayLSID = assayLSID ;
+        this.panelLSID = panelLSID ;
+        this.qccode = qccode;
+        this.genotypes = genotypes;
+        this.headerLine = headerLine;
+    }
+
+    /**
+     * get the contig value
+     * @return a string representing the contig
+     */
+    public String getChr() {
+        return contig;
+    }
+
+    /**
+     * get the start position, as an integer
+     * @return an int, representing the start position
+     */
+    public int getStart() {
+        return (int)position;
+    }
+
+    /**
+     * get the end position
+     * @return get the end position as an int
+     */
+    public int getEnd() {
+        return (int)position;
+    }
+
+    /**
+     * Getter methods
+     */
+
+    public Strand getStrand() {
+        return strand;
+    }
+
+    public String getAssembly() {
+        return assembly;
+    }
+
+    public String getCenter() {
+        return center;
+    }
+
+    public String getProtLSID() {
+        return protLSID;
+    }
+
+    public String getAssayLSID() {
+        return assayLSID;
+    }
+
+    public String getPanelLSID() {
+        return panelLSID;
+    }
+
+    public String getQCCode() {
+        return qccode;
+    }
+
+    public String getName() {
+        return name;
+    }
+
+    public String[] getAlleles() {
+        return alleles;
+    }
+
+    public String[] getGenotypes() {
+        return genotypes;
+    }
+
+    // This is necessary because HapMap places insertions in the incorrect position
+    public void updatePosition(long position) {
+        this.position = position;
+    }
+
+    public void setActualAlleles(Map<String, Allele> alleleMap) {
+        actualAlleles = new HashMap<String, Allele>(alleleMap);
+    }
+
+    public Map<String, Allele> getActualAlleles() {
+        return actualAlleles;
+    }
+    
+    /**
+     * get a list of the samples from the header (in order)
+     * @return a string array of sample names
+     */
+    public String[] getSampleIDs() {
+		String[] header = headerLine.split("\\s+");
+		String[] sample_ids = new String[header.length-11];
+		for (int i = 11; i < header.length; i++)
+			sample_ids[i-11] = header[i];
+		return sample_ids;
+	}
+}
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/codecs/refseq/RefSeqCodec.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/codecs/refseq/RefSeqCodec.java
new file mode 100644
index 0000000..9d60076
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/codecs/refseq/RefSeqCodec.java
@@ -0,0 +1,171 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.utils.codecs.refseq;
+
+import htsjdk.tribble.AsciiFeatureCodec;
+import htsjdk.tribble.Feature;
+import htsjdk.tribble.TribbleException;
+import htsjdk.tribble.readers.LineIterator;
+import org.broadinstitute.gatk.engine.refdata.ReferenceDependentFeatureCodec;
+import org.broadinstitute.gatk.utils.GenomeLoc;
+import org.broadinstitute.gatk.utils.GenomeLocParser;
+import org.broadinstitute.gatk.utils.Utils;
+import org.broadinstitute.gatk.utils.exceptions.UserException;
+
+import java.util.ArrayList;
+
+/**
+ * Allows for reading in RefSeq information
+ *
+ * <p>
+ * Parses a sorted UCSC RefSeq file (see below) into relevant features: the gene name, the unique gene name (if multiple transcrips get separate entries), exons, gene start/stop, coding start/stop,
+ * strandedness of transcription. 
+ * </p>
+ *
+ * <p>
+ * Instructions for generating a RefSeq file for use with the RefSeq codec can be found on the documentation guide here
+ * <a href="http://www.broadinstitute.org/gatk/guide/article?id=1329">http://www.broadinstitute.org/gatk/guide/article?id=1329</a>
+ * </p>
+ * <h2> Usage </h2>
+ * The RefSeq Rod can be bound as any other rod, and is specified by REFSEQ, for example
+ * <pre>
+ * -refSeqBinding:REFSEQ /path/to/refSeq.txt
+ * </pre>
+ *
+ * You will need to consult individual walkers for the binding name ("refSeqBinding", above)
+ *
+ * <h2>File format example</h2>
+ * If you want to define your own file for use, the format is (tab delimited):
+ * bin, name, chrom, strand, transcription start, transcription end, coding start, coding end, num exons, exon starts, exon ends, id, alt. name, coding start status (complete/incomplete), coding end status (complete,incomplete)
+ * and exon frames, for example:
+ * <pre>
+ * 76 NM_001011874 1 - 3204562 3661579 3206102 3661429 3 3204562,3411782,3660632, 3207049,3411982,3661579, 0 Xkr4 cmpl cmpl 1,2,0,
+ * </pre>
+ * for more information see <a href="http://skip.ucsc.edu/cgi-bin/hgTables?hgsid=5651&hgta_doSchemaDb=mm8&hgta_doSchemaTable=refGene">here</a>
+ * <p>
+ *     
+ * </p>
+ *
+ * @author Mark DePristo
+ * @since 2010
+ */
+public class RefSeqCodec extends AsciiFeatureCodec<RefSeqFeature> implements ReferenceDependentFeatureCodec {
+
+    /**
+     * The parser to use when resolving genome-wide locations.
+     */
+    private GenomeLocParser genomeLocParser;
+    private boolean zero_coding_length_user_warned = false;
+
+    public RefSeqCodec() {
+        super(RefSeqFeature.class);
+    }
+
+    /**
+     * Set the parser to use when resolving genetic data.
+     * @param genomeLocParser The supplied parser.
+     */
+    @Override
+    public void setGenomeLocParser(GenomeLocParser genomeLocParser) {
+        this.genomeLocParser =  genomeLocParser;
+    }
+
+    @Override
+    public Feature decodeLoc(final LineIterator lineIterator) {
+        final String line = lineIterator.next();
+        if (line.startsWith("#")) return null;
+        String fields[] = line.split("\t");
+        if (fields.length < 3) throw new TribbleException("RefSeq (decodeLoc) : Unable to parse line -> " + line + ", we expected at least 3 columns, we saw " + fields.length);
+        String contig_name = fields[2];
+        try {
+            return new RefSeqFeature(genomeLocParser.createGenomeLoc(contig_name, Integer.parseInt(fields[4])+1, Integer.parseInt(fields[5])));
+        } catch ( UserException.MalformedGenomeLoc e ) {
+            Utils.warnUser("RefSeq file is potentially incorrect, as some transcripts or exons have a negative length ("+fields[2]+")");
+            return null;
+        } catch ( NumberFormatException e ) {
+            throw new UserException.MalformedFile("Could not parse location from line: " + line);
+        }
+    }
+
+    /** Fills this object from a text line in RefSeq (UCSC) text dump file */
+    @Override
+    public RefSeqFeature decode(String line) {
+        if (line.startsWith("#")) return null;
+        String fields[] = line.split("\t");
+
+        // we reference postion 15 in the split array below, make sure we have at least that many columns
+        if (fields.length < 16) throw new TribbleException("RefSeq (decode) : Unable to parse line -> " + line + ", we expected at least 16 columns, we saw " + fields.length);
+        String contig_name = fields[2];
+        RefSeqFeature feature = new RefSeqFeature(genomeLocParser.createGenomeLoc(contig_name, Integer.parseInt(fields[4])+1, Integer.parseInt(fields[5])));
+
+        feature.setTranscript_id(fields[1]);
+        if ( fields[3].length()==1 && fields[3].charAt(0)=='+') feature.setStrand(1);
+        else if ( fields[3].length()==1 && fields[3].charAt(0)=='-') feature.setStrand(-1);
+        else throw new UserException.MalformedFile("Expected strand symbol (+/-), found: "+fields[3] + " for line=" + line);
+
+        int coding_start = Integer.parseInt(fields[6])+1;
+        int coding_stop = Integer.parseInt(fields[7]);
+
+        if ( coding_start > coding_stop ) {
+            if ( ! zero_coding_length_user_warned ) {
+                Utils.warnUser("RefSeq file contains transcripts with zero coding length. "+
+                        "Such transcripts will be ignored (this warning is printed only once)");
+                zero_coding_length_user_warned = true;
+            }
+            return null;
+        }
+
+        feature.setTranscript_interval(genomeLocParser.createGenomeLoc(contig_name, Integer.parseInt(fields[4])+1, Integer.parseInt(fields[5])));
+        feature.setTranscript_coding_interval(genomeLocParser.createGenomeLoc(contig_name, coding_start, coding_stop));
+        feature.setGene_name(fields[12]);
+        String[] exon_starts = fields[9].split(",");
+        String[] exon_stops = fields[10].split(",");
+        String[] eframes = fields[15].split(",");
+
+        if ( exon_starts.length != exon_stops.length )
+            throw new UserException.MalformedFile("Data format error: numbers of exon start and stop positions differ for line=" + line);
+        if ( exon_starts.length != eframes.length )
+            throw new UserException.MalformedFile("Data format error: numbers of exons and exon frameshifts differ for line=" + line);
+
+        ArrayList<GenomeLoc> exons = new ArrayList<GenomeLoc>(exon_starts.length);
+        ArrayList<Integer> exon_frames = new ArrayList<Integer>(eframes.length);
+
+        for ( int i = 0 ; i < exon_starts.length  ; i++ ) {
+            exons.add(genomeLocParser.createGenomeLoc(contig_name, Integer.parseInt(exon_starts[i])+1, Integer.parseInt(exon_stops[i]) ) );
+            exon_frames.add(Integer.decode(eframes[i]));
+        }
+
+        feature.setExons(exons);
+        feature.setExon_frames(exon_frames);
+        return feature;
+    }
+
+    @Override
+    public Object readActualHeader(LineIterator lineIterator) {
+        // No header for this format
+        return null;
+    }
+}
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/codecs/refseq/RefSeqFeature.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/codecs/refseq/RefSeqFeature.java
new file mode 100644
index 0000000..226a353
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/codecs/refseq/RefSeqFeature.java
@@ -0,0 +1,323 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.utils.codecs.refseq;
+
+import htsjdk.tribble.Feature;
+import org.broadinstitute.gatk.engine.refdata.utils.GATKFeature;
+import org.broadinstitute.gatk.engine.refdata.utils.RODRecordList;
+import org.broadinstitute.gatk.utils.GenomeLoc;
+import org.broadinstitute.gatk.utils.exceptions.ReviewedGATKException;
+
+import java.util.*;
+
+/**
+ * the ref seq feature
+ */
+public class RefSeqFeature implements Transcript, Feature {
+
+    private String transcript_id;
+    private int strand;
+    private GenomeLoc transcript_interval;
+    private GenomeLoc transcript_coding_interval;
+    private List<GenomeLoc> exons;
+    private String gene_name;
+    private List<Integer> exon_frames;
+    private String name;
+
+    public RefSeqFeature(GenomeLoc genomeLoc) {
+        this.transcript_interval = genomeLoc;
+    }
+
+    /** Returns id of the transcript (RefSeq NM_* id) */
+    public String getTranscriptId() { return transcript_id; }
+
+    /** Returns coding strand of the transcript, 1 or -1 for positive or negative strand, respectively */
+    public int getStrand() { return strand; }
+
+    /** Returns transcript's full genomic interval (includes all exons with UTRs) */
+    public GenomeLoc getLocation() {
+        return transcript_interval;
+    }
+
+    /** Returns genomic interval of the coding sequence (does not include UTRs, but still includes introns, since it's a single interval on the DNA) */
+    public GenomeLoc getCodingLocation() { return transcript_coding_interval; }
+
+    /** Name of the gene this transcript corresponds to (NOT gene id such as Entrez etc) */
+    public String getGeneName() { return gene_name; }
+
+    /** Number of exons in this transcript */
+    public int getNumExons() { return exons.size(); }
+
+    /** Genomic location of the n-th exon; throws an exception if n is out of bounds */
+    public GenomeLoc getExonLocation(int n) {
+        if ( n >= exons.size() || n < 0 ) throw new ReviewedGATKException("Index out-of-bounds. Transcript has " + exons.size() +" exons; requested: "+n);
+        return exons.get(n);
+    }
+
+    /** Returns the list of all exons in this transcript, as genomic intervals */
+    public List<GenomeLoc> getExons() { return exons; }
+
+    /** Returns all exons falling ::entirely:: inside an interval **/
+    public List<GenomeLoc> getExonsInInterval( GenomeLoc interval ) {
+        List<GenomeLoc> relevantExons = new ArrayList<GenomeLoc>(exons.size());
+        for ( GenomeLoc exon : getExons() ) {
+            if ( interval.containsP(exon) ) {
+                relevantExons.add(exon);
+            }
+        }
+
+        return relevantExons;
+    }
+
+    /** convenience method; returns the numbers of the exons in the interval **/
+    public List<Integer> getExonNumbersInInterval( GenomeLoc interval ) {
+        List<Integer> numbers = new ArrayList<Integer>();
+        int iNo = 0;
+        for ( GenomeLoc exon : getExons() ) {
+            if ( interval.containsP(exon) ) {
+                numbers.add(iNo);
+            }
+            iNo++;
+        }
+
+        return numbers;
+    }
+
+    public String getTranscriptUniqueGeneName() {
+        return String.format("%s(%s)",getGeneName(),getTranscriptId());
+    }
+
+    public String getOverlapString(GenomeLoc position) {
+        boolean is_exon = false;
+        StringBuilder overlapString = new StringBuilder();
+        int exonNo = 1;
+
+        for ( GenomeLoc exon : exons ) {
+            if ( exon.containsP(position) ) {
+                overlapString.append(String.format("exon_%d",exonNo));
+                is_exon = true;
+                break;
+            }
+            exonNo ++;
+        }
+
+        if ( ! is_exon ) {
+            if ( overlapsCodingP(position) ) {
+                overlapString.append("Intron");
+            } else {
+                overlapString.append("UTR");
+            }
+        }
+
+        return overlapString.toString();
+    }
+
+    ArrayList<GenomeLoc> exonInRefOrderCache = null;
+
+    public Integer getSortedOverlapInteger(GenomeLoc position) {
+        int exonNo = -1;
+        ArrayList<GenomeLoc> exonsInReferenceOrder = exonInRefOrderCache != null ? exonInRefOrderCache : new ArrayList<GenomeLoc>(exons);
+        if ( exonInRefOrderCache == null ) {
+            Collections.sort(exonsInReferenceOrder);
+        }
+        exonInRefOrderCache = exonsInReferenceOrder;
+        for ( GenomeLoc exon : exonsInReferenceOrder ) {
+            if ( exon.overlapsP(position) ) {
+                return ++exonNo;
+            }
+            ++exonNo;
+        }
+
+        return -1;
+    }
+
+    public GenomeLoc getSortedExonLoc(int offset) {
+        ArrayList<GenomeLoc> exonsInReferenceOrder = exonInRefOrderCache != null ? exonInRefOrderCache : new ArrayList<GenomeLoc>(exons);
+        if ( exonInRefOrderCache == null ) {
+            Collections.sort(exonsInReferenceOrder);
+        }
+        exonInRefOrderCache = exonsInReferenceOrder;
+        return exonsInReferenceOrder.get(offset);
+    }
+
+    /** Returns true if the specified interval 'that' overlaps with the full genomic interval of this transcript */
+    public boolean overlapsP (GenomeLoc that) {
+        return getLocation().overlapsP(that);
+    }
+
+    /** Returns true if the specified interval 'that' overlaps with the coding genomic interval of this transcript.
+     * NOTE: since "coding interval" is still a single genomic interval, it will not contain UTRs of the outermost exons,
+     * but it will still contain introns and/or exons internal to this genomic locus that are not spliced into this transcript.
+     * @see #overlapsExonP
+     */
+    public boolean overlapsCodingP (GenomeLoc that) {
+        return transcript_coding_interval.overlapsP(that);
+    }
+
+    /** Returns true if the specified interval 'that' overlaps with any of the exons actually spliced into this transcript */
+    public boolean overlapsExonP (GenomeLoc that) {
+        for ( GenomeLoc e : exons ) {
+            if ( e.overlapsP(that) ) return true;
+        }
+        return false;
+    }
+    public String toString() {
+            StringBuilder b = new StringBuilder("000\t"); // first field is unused but required in th ecurrent format; just set to something
+            b.append(transcript_id);   // #1
+            b.append('\t');
+            b.append(getLocation().getContig()); // #2
+            b.append('\t');
+            b.append( (strand==1?'+':'-') ); // #3
+            b.append('\t');
+            b.append( (getLocation().getStart() - 1) ); // #4
+            b.append('\t');
+            b.append( getLocation().getStop());  // #5
+            b.append('\t');
+            b.append( (transcript_coding_interval.getStart() - 1) ); // #6
+            b.append('\t');
+            b.append( transcript_coding_interval.getStop());  // #7
+            b.append('\t');
+            b.append(exons.size()); // #8
+            b.append('\t');
+            for ( GenomeLoc loc : exons ) { b.append( (loc.getStart()-1) ); b.append(','); } // #9
+            b.append('\t');
+            for ( GenomeLoc loc : exons ) { b.append( loc.getStop() ); b.append(','); } // #10
+            b.append("\t0\t"); // # 11 - unused?
+            b.append(gene_name); // # 12
+            b.append("\tcmpl\tcmpl\t"); // #13, #14 - unused?
+            for ( Integer f : exon_frames ) { b.append( f ); b.append(','); } // #15
+
+
+            return b.toString();
+        }
+
+        /** Convenience method, which is packaged here for a lack of better place; it is indeed closely related to
+         * rodRefSeq though: takes list of rods (transcripts) overlapping with a given position and determines whether
+         * this position is fully whithin an exon of <i>any</i> of those transcripts. Passing null is safe (will return false).
+         * NOTE: position can be still within a UTR, see #isCoding
+         * @return true if it's an exon
+         */
+        public static boolean isExon(RODRecordList l) {
+
+            if ( l == null ) return false;
+
+            GenomeLoc loc = l.getLocation();
+
+            for ( GATKFeature t : l ) {
+                if ( ((RefSeqFeature)t.getUnderlyingObject()).overlapsExonP(loc) ) return true;
+            }
+            return false;
+
+        }
+
+        /** Convenience method, which is packaged here for a lack of better place; it is indeed closely related to
+         * rodRefSeq though: takes list of rods (transcripts) overlapping with a given position and determines whether
+         * this position is fully whithin a coding region of <i>any</i> of those transcripts.
+         * Passing null is safe (will return false).
+         * NOTE: "coding" interval is defined as a single genomic interval, so it
+         * does not include the UTRs of the outermost exons, but it includes introns between exons spliced into a
+         * transcript, or internal exons that are not spliced into a given transcript. To check that a position is
+         * indeed within an exon but not in UTR, use #isCodingExon().
+         * @return
+         */
+        public static boolean isCoding(RODRecordList l) {
+
+            if ( l == null ) return false;
+
+            GenomeLoc loc = l.getLocation();
+
+            for ( GATKFeature t : l ) {
+                if ( ((RefSeqFeature)t.getUnderlyingObject()).overlapsCodingP(loc) ) return true;
+            }
+            return false;
+
+        }
+
+        /** Convenience method, which is packaged here for a lack of better place; it is indeed closely related to
+         * rodRefSeq though: takes list of rods (transcripts) overlapping with a given position and determines whether
+         * this position is fully whithin a coding exon portion (i.e. true coding sequence) of <i>any</i> of those transcripts.
+         * Passing null is safe (will return false). In other words, this method returns true if the list contains a transcript,
+         * for which the current position is within an exon <i>and</i> within a coding interval simultaneously.
+         * @return
+         */
+        public static boolean isCodingExon(RODRecordList l) {
+
+            if ( l == null ) return false;
+
+            GenomeLoc loc = l.getLocation();
+
+            for ( GATKFeature t : l ) {
+                if ( ((RefSeqFeature)t.getUnderlyingObject()).overlapsCodingP(loc) && ((RefSeqFeature)t.getUnderlyingObject()).overlapsExonP(loc) ) return true;
+            }
+            return false;
+
+        }
+
+
+    public void setTranscript_id(String transcript_id) {
+        this.transcript_id = transcript_id;
+    }
+
+    public void setStrand(int strand) {
+        this.strand = strand;
+    }
+
+    public void setTranscript_interval(GenomeLoc transcript_interval) {
+        this.transcript_interval = transcript_interval;
+    }
+
+    public void setTranscript_coding_interval(GenomeLoc transcript_coding_interval) {
+        this.transcript_coding_interval = transcript_coding_interval;
+    }
+
+    public void setExons(List<GenomeLoc> exons) {
+        this.exons = exons;
+    }
+
+    public void setGene_name(String gene_name) {
+        this.gene_name = gene_name;
+    }
+
+    public void setExon_frames(List<Integer> exon_frames) {
+        this.exon_frames = exon_frames;
+    }
+
+    public void setName(String name) {
+        this.name = name;
+    }
+
+    public String getChr() {
+        return transcript_interval.getContig();
+    }
+
+    public int getStart() {
+        return transcript_interval.getStart();
+    }
+
+    public int getEnd() {
+        return transcript_interval.getStop();
+    }
+}
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/codecs/refseq/Transcript.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/codecs/refseq/Transcript.java
new file mode 100644
index 0000000..1671c79
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/codecs/refseq/Transcript.java
@@ -0,0 +1,78 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.utils.codecs.refseq;
+
+import org.broadinstitute.gatk.utils.GenomeLoc;
+import org.broadinstitute.gatk.utils.HasGenomeLocation;
+
+import java.util.List;
+
+/**
+ * Created by IntelliJ IDEA.
+ * User: asivache
+ * Date: Sep 22, 2009
+ * Time: 5:22:30 PM
+ * To change this template use File | Settings | File Templates.
+ */
+public interface Transcript extends HasGenomeLocation {
+
+    /** Returns id of the transcript (RefSeq NM_* id) */
+    public String getTranscriptId();
+    /** Returns coding strand of the transcript, 1 or -1 for positive or negative strand, respectively */
+    public int getStrand();
+    /** Returns transcript's full genomic interval (includes all exons with UTRs) */
+    public GenomeLoc getLocation();
+    /** Returns genomic interval of the coding sequence (does not include
+     * UTRs, but still includes introns, since it's a single interval on the DNA)
+     */
+    public GenomeLoc getCodingLocation();
+    /** Name of the gene this transcript corresponds to (typically NOT gene id such as Entrez etc,
+     * but the implementation can decide otherwise)
+     */
+    public String getGeneName();
+    /** Number of exons in this transcript */
+    public int getNumExons();
+    /** Genomic location of the n-th exon; expected to throw an exception (runtime) if n is out of bounds */
+    public GenomeLoc getExonLocation(int n);
+
+    /** Returns the list of all exons in this transcript, as genomic intervals */
+    public List<GenomeLoc> getExons();
+
+    /** Returns true if the specified interval 'that' overlaps with the full genomic interval of this transcript */
+    public boolean overlapsP (GenomeLoc that);
+
+    /** Returns true if the specified interval 'that' overlaps with the coding genomic interval of this transcript.
+      * NOTE: since "coding interval" is still a single genomic interval, it will not contain UTRs of the outermost exons,
+      * but it will still contain introns and/or exons internal to this genomic locus that are not spliced into this transcript.
+      * @see #overlapsExonP
+      */
+    public boolean overlapsCodingP (GenomeLoc that);
+
+    /** Returns true if the specified interval 'that' overlaps with any of the exons actually spliced into this transcript */
+    public boolean overlapsExonP (GenomeLoc that);
+
+
+}
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/codecs/sampileup/SAMPileupCodec.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/codecs/sampileup/SAMPileupCodec.java
new file mode 100644
index 0000000..8c43854
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/codecs/sampileup/SAMPileupCodec.java
@@ -0,0 +1,354 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.utils.codecs.sampileup;
+
+import htsjdk.tribble.AsciiFeatureCodec;
+import htsjdk.tribble.exception.CodecLineParsingException;
+import htsjdk.tribble.readers.LineIterator;
+import htsjdk.tribble.util.ParsingUtils;
+
+import java.util.ArrayList;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import static org.broadinstitute.gatk.utils.codecs.sampileup.SAMPileupFeature.VariantType;
+
+/**
+ * Decoder for SAM pileup data.
+ *
+ * <p>
+ *     From the <a href="http://samtools.sourceforge.net/">SAMTools project documentation</a>:
+ * </p>
+ * <p>The Pileup format was first used by Tony Cox and Zemin Ning at
+ *     the Sanger Institute. It describes the base-pair information at each chromosomal position. This format
+ *     facilitates SNP/indel calling and brief alignment viewing by eye. Note that the pileup program has been replaced
+ *     in Samtools by mpileup, which produces a slightly different output format by default.
+ * </p>
+
+ * <h3>Format</h3>
+ * <p>There are two versions of the original pileup format: the current 6-column format produced by Samtools, and the old
+ * 10/13-column "consensus" format which could be obtained by using the -c argument, now deprecated. </p>
+ * <h4>Simple pileup: 6-column format</h4>
+ * <p>
+ *     Each line consists of chromosome, 1-based coordinate, reference base, the
+ *     number of reads covering the site, read bases and base qualities. At the
+ *     read base column, a dot stands for a match to the reference base on the
+ *     forward strand, a comma for a match on the reverse strand, `ACGTN' for a mismatch
+ *     on the forward strand and `acgtn' for a mismatch on the reverse strand.
+ *     A pattern `\+[0-9]+[ACGTNacgtn]+' indicates there is an insertion between
+ *     this reference position and the next reference position. The length of the
+ *     insertion is given by the integer in the pattern, followed by the inserted sequence.
+ * </p>
+ * <pre>
+ *     seq1 272 T 24  ,.$.....,,.,.,...,,,.,..^+. <<<+;<<<<<<<<<<<=<;<;7<&
+ *     seq1 273 T 23  ,.....,,.,.,...,,,.,..A <<<;<<<<<<<<<3<=<<<;<<+
+ *     seq1 274 T 23  ,.$....,,.,.,...,,,.,...    7<7;<;<<<<<<<<<=<;<;<<6
+ *     seq1 275 A 23  ,$....,,.,.,...,,,.,...^l.  <+;9*<<<<<<<<<=<<:;<<<<
+ *     seq1 276 G 22  ...T,,.,.,...,,,.,....  33;+<<7=7<<7<&<<1;<<6<
+ *     seq1 277 T 22  ....,,.,.,.C.,,,.,..G.  +7<;<<<<<<<&<=<<:;<<&<
+ *     seq1 278 G 23  ....,,.,.,...,,,.,....^k.   %38*<<;<7<<7<=<<<;<<<<<
+ *     seq1 279 C 23  A..T,,.,.,...,,,.,..... ;75&<<<<<<<<<=<<<9<<:<<
+ * </pre>
+ * <p>
+ *     See the <a href="http://samtools.sourceforge.net/pileup.shtml">Pileup format documentation</a> for more details.
+ * </p>
+ *
+ * <h4>Consensus pileup: 10/13-column format</h4>
+ * <p>The "consensus" or extended pileup consists of the following:
+ *  <ul>
+ *      <li>original 6 columns as described above</li>
+ *      <li>4 extra columns representing consensus values (consensus base, consensus quality, variant quality and maximum mapping quality of the
+ * reads covering the sites) for all sites, inserted before the bases and quality strings</li>
+ *      <li>3 extra columns indicating counts of reads supporting indels (just for indel sites)</li>
+ *  </ul>
+ * </p>
+ * <h4>Example of consensus pileup for SNP or non-variant sites</h4>
+ * <pre>
+ *     seq1  60  T  T  66  0  99  13  ...........^~.^~.   9<<55<;<<<<<<
+ *     seq1  61  G  G  72  0  99  15  .............^~.^y. (;975&;<<<<<<<<
+ *     seq1  62  T  T  72  0  99  15  .$..............    <;;,55;<<<<<<<<
+ *     seq1  63  G  G  72  0  99  15  .$.............^~.  4;2;<7:+<<<<<<<
+ *     seq1  64  G  G  69  0  99  14  ..............  9+5<;;;<<<<<<<
+ *     seq1  65  A  A  69  0  99  14  .$............. <5-2<;;<<<<<<;
+ *     seq1  66  C  C  66  0  99  13  .............   &*<;;<<<<<<8<
+ *     seq1  67  C  C  69  0  99  14  .............^~.    ,75<.4<<<<<-<<
+ *     seq1  68  C  C  69  0  99  14  ..............  576<;7<<<<<8<< *
+ * </pre>
+ *
+ * <h4>Example of consensus pileup for indels</h4>
+ * <pre>
+ *     Escherichia_coli_K12	3995037	*	*\/*	430	0	37	144	*	+A	143	1	0
+ *     Escherichia_coli_K12	3995279	*	*\/*	202	0	36	68	*	+A	67	1	0
+ *     Escherichia_coli_K12	3995281	*	*\/*	239	0	36	67	*	-CG	66	1	0
+ * </pre>
+ * <p>
+ *     See <a href="http://samtools.sourceforge.net/cns0.shtml/">Consensus pileup format (deprecated)</a> for more details.
+ * </p>
+ *
+ * <h3>Caveat</h3>
+ * <p>Handling of indels is questionable at the moment. Proceed with care.</p>
+ *
+ *
+ * @author Matt Hanna, Geraldine VdAuwera
+ * @since 2014
+ */
+public class SAMPileupCodec extends AsciiFeatureCodec<SAMPileupFeature> {
+    // number of tokens expected (6 or 10 are valid, anything else is wrong)
+    private static final int basicTokenCount = 6;
+    private static final int consensusSNPTokenCount = 10;
+    private static final int consensusIndelTokenCount = 13;
+    private static final char fldDelim = '\t';
+    // allocate once and don't ever bother creating them again:
+    private static final String baseA = "A";
+    private static final String baseC = "C";
+    private static final String baseG = "G";
+    private static final String baseT = "T";
+    private static final String emptyStr = ""; // we will use this for "reference" allele in insertions
+
+    public SAMPileupCodec() {
+        super(SAMPileupFeature.class);
+    }
+
+    public SAMPileupFeature decode(String line) {
+        //+1 because we want to know if we have more than the max
+        String[] tokens = new String[consensusIndelTokenCount+1];
+
+        // split the line
+        final int count = ParsingUtils.split(line,tokens,fldDelim);
+
+        SAMPileupFeature feature = new SAMPileupFeature();
+
+        /**
+         * Tokens 0, 1, 2 are the same for both formats so they will be interpreted without differentiation.
+         * The 10/13-format has 4 tokens inserted after token 2 compared to the 6-format, plus 3 more tokens added at
+         * the end for indels. We are currently not making any use of the extra indel tokens.
+         *
+         * Any token count other than basicTokenCount, consensusSNPTokenCount or consensusIndelTokenCount is wrong.
+         */
+        final String observedString, bases, quals;
+
+        feature.setChr(tokens[0]);
+        feature.setStart(Integer.parseInt(tokens[1]));
+
+        if(tokens[2].length() != 1)  {
+            throw new CodecLineParsingException("The SAM pileup line had unexpected base " + tokens[2] + " on line = " + line);
+        }
+        feature.setRef(tokens[2].charAt(0));
+
+        switch (count) {
+            case basicTokenCount:
+                bases = tokens[4];
+                quals = tokens[5];
+                // parsing is pretty straightforward for 6-col format
+                if ( feature.getRef() == '*' ) {   // this indicates an indel -- but it shouldn't occur with vanilla 6-col format
+                    throw new CodecLineParsingException("Found an indel on line = " + line + " but it shouldn't happen in simple pileup format");
+                } else {
+                    parseBasesAndQuals(feature, bases, quals);
+                    feature.setRefBases(tokens[2].toUpperCase());
+                    feature.setEnd(feature.getStart());
+                }
+                break;
+            case consensusSNPTokenCount: // pileup called a SNP or a reference base
+                observedString = tokens[3].toUpperCase();
+                feature.setFWDAlleles(new ArrayList<String>(2));
+                feature.setConsensusConfidence(Double.parseDouble(tokens[4]));
+                feature.setVariantConfidence(Double.parseDouble(tokens[5]));
+                bases = tokens[8];
+                quals = tokens[9];
+                // confirm that we have a non-variant, not a mis-parsed indel
+                if ( feature.getRef() == '*' ) {
+                    throw new CodecLineParsingException("Line parsing of " + line + " says we have a SNP or non-variant but the ref base is '*', which indicates an indel");
+                }
+                // Parse the SNP or non-variant
+                parseBasesAndQuals(feature, bases, quals);
+                if ( observedString.length() != 1 ) {
+                    throw new CodecLineParsingException( "Line parsing of " + line + " says we have a SNP or non-variant but the genotype token is not a single letter: " + observedString);
+                }
+                feature.setRefBases(tokens[2].toUpperCase());
+                feature.setEnd(feature.getStart());
+
+                char ch = observedString.charAt(0);
+
+                switch ( ch ) {  // record alleles (decompose ambiguous base codes)
+                    case 'A': feature.getFWDAlleles().add(baseA); feature.getFWDAlleles().add(baseA); break;
+                    case 'C': feature.getFWDAlleles().add(baseC); feature.getFWDAlleles().add(baseC); break;
+                    case 'G': feature.getFWDAlleles().add(baseG); feature.getFWDAlleles().add(baseG); break;
+                    case 'T': feature.getFWDAlleles().add(baseT); feature.getFWDAlleles().add(baseT); break;
+                    case 'M': feature.getFWDAlleles().add(baseA); feature.getFWDAlleles().add(baseC); break;
+                    case 'R': feature.getFWDAlleles().add(baseA); feature.getFWDAlleles().add(baseG); break;
+                    case 'W': feature.getFWDAlleles().add(baseA); feature.getFWDAlleles().add(baseT); break;
+                    case 'S': feature.getFWDAlleles().add(baseC); feature.getFWDAlleles().add(baseG); break;
+                    case 'Y': feature.getFWDAlleles().add(baseC); feature.getFWDAlleles().add(baseT); break;
+                    case 'K': feature.getFWDAlleles().add(baseG); feature.getFWDAlleles().add(baseT); break;
+                }
+                if ( feature.getFWDAlleles().get(0).charAt(0) == feature.getRef() && feature.getFWDAlleles().get(1).charAt(0) == feature.getRef() ) feature.setVariantType(VariantType.NONE);
+                else {
+                    // 	we know that at least one allele is non-ref;
+                    // if one is ref and the other is non-ref, or if both are non ref but they are the same (i.e.
+                    // homozygous non-ref), we still have 2 allelic variants at the site (e.g. one ref and one nonref)
+                    feature.setVariantType(VariantType.SNP);
+                    if ( feature.getFWDAlleles().get(0).charAt(0) == feature.getRef() ||
+                            feature.getFWDAlleles().get(1).charAt(0) == feature.getRef() ||
+                            feature.getFWDAlleles().get(0).equals(feature.getFWDAlleles().get(1))
+                            ) feature.setNumNonRef(1);
+                    else feature.setNumNonRef(2); // if both observations differ from ref and they are not equal to one another, then we get multiallelic site...
+                }
+                break;
+            case consensusIndelTokenCount:
+                observedString = tokens[3].toUpperCase();
+                feature.setFWDAlleles(new ArrayList<String>(2));
+                feature.setConsensusConfidence(Double.parseDouble(tokens[4]));
+                feature.setVariantConfidence(Double.parseDouble(tokens[5]));
+                // confirm that we have an indel, not a mis-parsed SNP or non-variant
+                if ( feature.getRef() != '*' ) {
+                    throw new CodecLineParsingException("Line parsing of " + line + " says we have an indel but the ref base is not '*'");
+                }
+                // Parse the indel
+                parseIndels(observedString,feature) ;
+                if ( feature.isDeletion() ) feature.setEnd(feature.getStart()+feature.length()-1);
+                else feature.setEnd(feature.getStart()); // if it's not a deletion and we are biallelic, this has got to be an insertion; otherwise the state is inconsistent!!!!
+                break;
+            default:
+                throw new CodecLineParsingException("The SAM pileup line didn't have the expected number of tokens " +
+                    "(expected = " + basicTokenCount + " (basic pileup), " + consensusSNPTokenCount +
+                    " (consensus pileup for a SNP or non-variant site) or " + consensusIndelTokenCount +
+                    " (consensus pileup for an indel); saw = " + count + " on line = " + line + ")");
+        }
+        return feature;
+    }
+
+    @Override
+    public Object readActualHeader(LineIterator lineIterator) {
+        // No header for this format
+        return null;
+    }
+
+    private void parseIndels(String genotype,SAMPileupFeature feature) {
+        String [] obs = genotype.split("/"); // get observations, now need to tinker with them a bit
+
+        // if reference allele is among the observed alleles, we will need to take special care of it since we do not have direct access to the reference;
+        // if we have an insertion, the "reference" allele is going to be empty; if it it is a deletion, we will deduce the "reference allele" bases
+        // from what we have recorded for the deletion allele (e.g. "-CAC")
+        boolean hasRefAllele = false;
+
+        for ( int i = 0 ; i < obs.length ; i++ ) {
+            if ( obs[i].length() == 1 && obs[i].charAt(0) == '*'  ) {
+                hasRefAllele = true;
+                feature.getFWDAlleles().add(emptyStr);
+                continue;
+            }
+
+            String varBases = obs[i].toUpperCase();
+
+            switch ( obs[i].charAt(0) )  {
+                case '+':
+                    if (!feature.isReference() && !feature.isInsertion()) feature.setVariantType(VariantType.INDEL);
+                    else feature.setVariantType(VariantType.INSERTION);
+                    feature.setRefBases(emptyStr);
+                    break;
+                case '-' :
+                    if (!feature.isReference() && !feature.isDeletion()) feature.setVariantType(VariantType.INDEL);
+                    else feature.setVariantType(VariantType.DELETION);
+                    feature.setRefBases(varBases); // remember what was deleted, this will be saved as "reference allele"
+                    break;
+                default: throw new CodecLineParsingException("Can not interpret observed indel allele record: "+genotype);
+            }
+            feature.getFWDAlleles().add(varBases);
+            feature.setLength(obs[i].length()-1); // inconsistent for non-biallelic indels!!
+        }
+        if ( hasRefAllele ) {
+            // we got at least one ref. allele (out of two recorded)
+            if (feature.isReference()) { // both top theories are actually ref allele;
+                feature.setNumNonRef(0); // no observations of non-reference allele at all
+                feature.setRefBases(emptyStr);
+            } else {
+                feature.setNumNonRef(1); // hasRefAllele = true, so one allele was definitely ref, hence there is only one left
+            }
+        } else {
+            // we observe two non-ref alleles; they better be the same variant, otherwise the site is not bi-allelic and at the moment we
+            // fail to set data in a consistent way.
+            if ( feature.getFWDAlleles().get(0).equals(feature.getFWDAlleles().get(1))) feature.setNumNonRef(1);
+            else feature.setNumNonRef(2);
+        }
+        // DONE with indels
+
+    }
+
+    private void parseBasesAndQuals(SAMPileupFeature feature, final String bases, final String quals)
+    {
+        //System.out.printf("%s%n%s%n", bases, quals);
+
+        // needs to convert the base string with its . and , to the ref base
+        StringBuilder baseBuilder = new StringBuilder();
+        StringBuilder qualBuilder = new StringBuilder();
+        boolean done = false;
+        for ( int i = 0, j = 0; i < bases.length() && ! done; i++ ) {
+            //System.out.printf("%d %d%n", i, j);
+            char c = (char)bases.charAt(i);
+
+            switch ( c ) {
+                case '.':   // matches reference
+                case ',':   // matches reference
+                    baseBuilder.append(feature.getRef());
+                    qualBuilder.append(quals.charAt(j++));
+                    break;
+                case '$':   // end of read
+                    break;
+                case '*':   // end of indel?
+                    j++;
+                    break;
+                case '^':   // mapping quality
+                    i++;
+                    break;
+                case '+':   // start of indel
+                case '-':   // start of indel
+                    final Pattern regex = Pattern.compile("([0-9]+).*");             // matches case 1
+                    final String rest = bases.substring(i+1);
+                    //System.out.printf("sub is %s%n", rest);
+                    Matcher match = regex.matcher(rest);
+                    if ( ! match.matches() ) {
+                        if ( feature.getRef() != '*' )
+                            throw new CodecLineParsingException("Bad pileup format: " + bases + " at position " + i);
+                        done = true;
+                    }
+                    else {
+                        String g = match.group(1);
+                        //System.out.printf("group is %d, match is %s%n", match.groupCount(), g);
+                        int l = Integer.parseInt(g);
+                        i += l + g.length();    // length of number + that many bases + +/- at the start (included in the next i++)
+                        //System.out.printf("remaining is %d => %s%n", l, bases.substring(i+1));
+                    }
+                    break;
+                default:   // non reference base
+                    baseBuilder.append(c);
+                    qualBuilder.append(quals.charAt(j++));
+            }
+        }
+
+        feature.setPileupBases(baseBuilder.toString());
+        feature.setPileupQuals(qualBuilder.toString());
+    }
+}
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/codecs/sampileup/SAMPileupFeature.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/codecs/sampileup/SAMPileupFeature.java
new file mode 100644
index 0000000..89f168b
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/codecs/sampileup/SAMPileupFeature.java
@@ -0,0 +1,276 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.utils.codecs.sampileup;
+
+import htsjdk.samtools.util.StringUtil;
+import htsjdk.tribble.Feature;
+
+import java.util.List;
+
+/**
+ * A tribble feature representing a SAM pileup.
+ *
+ * Allows intake of both simple (6-column) or extended/consensus (10/13-column) pileups. Simple pileup features will
+ * contain only basic information, no observed alleles or variant/genotype inferences, and so shouldn't be used as
+ * input for analysis that requires that information.
+ *
+ * @author mhanna
+ * @version 0.1
+ */
+public class SAMPileupFeature implements Feature {
+    public enum VariantType { NONE, SNP, INSERTION, DELETION, INDEL }; 
+
+    private String contig;            // genomic location of this genotyped site
+    private int start;
+    private int stop;
+
+    private char refBaseChar; // what we have set for the reference base (is set to a '*' for indel!)
+    private String refBases;        // the reference base sequence according to NCBI; single base for point mutations, deleted bases for  deletions, empty string for insertions
+
+    private String pileupQuals;     // the read base qualities
+    private String pileupBases;     // the read bases themselves
+
+    private List<String> observedAlleles = null;    // The sequences of the observed alleles (e.g. {"A","C"} for point mutation or {"","+CC"} for het. insertion
+    private VariantType varType = VariantType.NONE;
+    private int nNonref = 0; // number of non-reference alleles observed
+    private int eventLength = 0; // number of inserted or deleted bases    
+
+    private double consensusScore = 0;
+    private double variantScore = 0;
+
+    /**
+     * create the pileup feature.  Default protection so that only other classes in this package can create it.
+     */
+    SAMPileupFeature() {}
+
+    public String getChr() {
+        return contig;
+    }
+
+    protected void setChr(String chr) {
+        this.contig = chr;
+    }
+
+    public int getStart() {
+        return start;
+    }
+
+    protected void setStart(int start) {
+        this.start = start;
+    }
+
+    public int getEnd() {
+        return stop;
+    }
+
+    protected void setEnd(int end) {
+        this.stop = end;
+    }
+
+    public String getQualsAsString()        { return pileupQuals; }
+
+    protected void setPileupQuals(String pileupQuals) {
+        this.pileupQuals = pileupQuals;
+    }
+
+    /** Returns reference base for point genotypes or '*' for indel genotypes, as a char.
+     *
+     */
+    public char getRef()            { return refBaseChar; }
+
+    protected void setRef(char ref) {
+        this.refBaseChar = ref;
+    }
+
+    public int size()               { return pileupQuals.length(); }
+
+    /** Returns pile of observed bases over the current genomic location.
+     *
+     */
+    public String getBasesAsString()        { return pileupBases; }
+
+    protected void setPileupBases(String pileupBases) {
+        this.pileupBases = pileupBases;
+    }
+
+    /** Returns formatted pileup string for the current genomic location as
+     * "location: reference_base observed_base_pile observed_qual_pile"
+     */
+    public String getPileupString()
+    {
+        if(start == stop)
+            return String.format("%s:%d: %s %s %s", getChr(), getStart(), getRef(), getBasesAsString(), getQualsAsString());
+        else
+            return String.format("%s:%d-%d: %s %s %s", getChr(), getStart(), getEnd(), getRef(), getBasesAsString(), getQualsAsString());
+    }
+
+    /**
+     * Gets the bases in byte array form.
+     * @return byte array of the available bases.
+     */
+    public byte[] getBases() {
+        return StringUtil.stringToBytes(getBasesAsString());
+    }
+
+    /**
+     * Gets the Phred base qualities without ASCII offset.
+     * @return Phred base qualities.
+     */
+    public byte[] getQuals() {
+        byte[] quals = StringUtil.stringToBytes(getQualsAsString());
+        for(int i = 0; i < quals.length; i++) quals[i] -= 33;
+        return quals;
+    }
+
+    /** Returns bases in the reference allele as a String. For point genotypes, the string consists of a single
+     * character (reference base). For indel genotypes, the string is empty for insertions into
+     * the reference, or consists of deleted bases for deletions.
+     *
+     * @return reference allele, forward strand
+     */
+    public String getFWDRefBases() {
+        return refBases;
+    }
+
+    protected void setRefBases(String refBases) {
+        this.refBases = refBases;
+    }
+
+    public List<String> getFWDAlleles()  {
+        return observedAlleles;
+    }
+
+    protected void setFWDAlleles(List<String> alleles) {
+        this.observedAlleles = alleles;
+    }
+
+    // ----------------------------------------------------------------------
+    //
+    // What kind of variant are we?
+    //
+    // ----------------------------------------------------------------------
+    public boolean isSNP() { return varType == VariantType.SNP; }
+    public boolean isInsertion() { return varType == VariantType.INSERTION; }
+    public boolean isDeletion() { return varType == VariantType.DELETION ; }
+    public boolean isIndel() { return isInsertion() || isDeletion() || varType == VariantType.INDEL; }
+    public boolean isReference()  { return varType == VariantType.NONE; }
+
+    protected void setVariantType(VariantType variantType) {
+        this.varType = variantType;
+    }
+
+    public boolean isHom() {
+    	// implementation-dependent: here we use the fact that for ref and snps we actually use fixed static strings to remember the genotype
+    	if ( ! isIndel() ) return ( observedAlleles.get(0).equals(observedAlleles.get(1)) );
+    	return ( isInsertion() || isDeletion() ) && observedAlleles.get(0).equals(observedAlleles.get(1) );
+    }
+
+    public boolean isHet() {
+    	// implementation-dependent: here we use the fact that for ref and snps we actually use fixed static strings to remember the genotype
+    	if ( ! isIndel() ) return ( !(observedAlleles.get(0).equals(observedAlleles.get(1))) );
+    	return isIndel() || ( ! observedAlleles.get(0).equals(observedAlleles.get(1) ) );
+    }
+
+    public double getVariantConfidence() {
+        return variantScore;
+    }
+
+    protected void setVariantConfidence(double variantScore) {
+        this.variantScore = variantScore;
+    }
+
+    public boolean isBiallelic() {
+        return nNonref  < 2;
+    }
+
+    protected void setNumNonRef(int nNonref) {
+        this.nNonref = nNonref;
+    }
+
+    public double getConsensusConfidence() {
+        return consensusScore;
+    }
+
+    protected void setConsensusConfidence(double consensusScore) {
+        this.consensusScore = consensusScore;
+    }
+
+    public int length() {
+        return eventLength;
+    }
+
+    protected void setLength(int eventLength) {
+        this.eventLength = eventLength;
+    }
+
+	public boolean isIndelGenotype() {
+		return refBaseChar == '*';
+	}
+
+
+	public boolean isPointGenotype() {
+		return ! isIndelGenotype();
+	}
+
+	/** Implements method required by GenotypeList interface. If this object represents
+	 * an indel genotype, then it returns itself through this method. If this object is a
+	 * point genotype, this method returns null.
+	 * @return
+	 */
+	public SAMPileupFeature getIndelGenotype() {
+		if ( isIndelGenotype() ) return this;
+		else return null;
+	}
+
+	/** Implements method required by GenotypeList interface. If this object represents
+	 * a point genotype, then it returns itself through this method. If this object is an
+	 * indel genotype, this method returns null.
+	 * @return
+	 */
+	public SAMPileupFeature getPointGenotype() {
+		if ( isPointGenotype() ) return this;
+		else return null;
+	}
+
+	/** Returns true if this object \em is an indel genotype (and thus
+	 * indel genotype is what it only has).
+	 * @return
+	 */
+	public boolean hasIndelGenotype() {
+		return isIndelGenotype();
+	}
+
+	/** Returns true if this object \em is a point genotype (and thus
+	 * point genotype is what it only has.
+	 * @return
+	 */
+	public boolean hasPointGenotype() {
+		return isPointGenotype();
+	}
+
+
+
+}
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/codecs/samread/SAMReadCodec.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/codecs/samread/SAMReadCodec.java
new file mode 100644
index 0000000..d83ce6d
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/codecs/samread/SAMReadCodec.java
@@ -0,0 +1,123 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.utils.codecs.samread;
+
+import htsjdk.samtools.Cigar;
+import htsjdk.samtools.TextCigarCodec;
+import htsjdk.samtools.util.StringUtil;
+import htsjdk.tribble.AsciiFeatureCodec;
+import htsjdk.tribble.exception.CodecLineParsingException;
+import htsjdk.tribble.readers.LineIterator;
+import htsjdk.tribble.util.ParsingUtils;
+
+/**
+ * Decodes a simple SAM text string.
+ *
+ * <p>
+ * Reads in the SAM text version of a BAM file as a ROD.  For testing only
+ * </p>
+ *
+ * <p>
+ * See also: @see <a href="http://samtools.sourceforge.net">SAMTools</a> for format specification
+ * </p>
+ *
+ * <h2>File format example</h2>
+ * <pre>
+ *     SL-XBC:1:10:628:923#0	16	Escherichia_coli_K12	1	37	76M	=	1	0	AGCTTTTCATTCTGACTGCAACGGGCAATATGTCTCTGTGTGGATTAAAAAAAGAGTGTCTGATAGCAGCTTCTGA	B@>87<;A@?@957:>>@AA at B>@A9AB at B>@A@@@@@A;=AAB at BBBBBCBBBB@>A>:ABB at BAABCB=CA at CB
+ * </pre>
+ *
+ * @author Matt Hanna
+ * @since 2009
+ */
+public class SAMReadCodec extends AsciiFeatureCodec<SAMReadFeature> {
+    /* SL-XBC:1:10:628:923#0	16	Escherichia_coli_K12	1	37	76M	=	1	0	AGCTTTTCATTCTGACTGCAACGGGCAATATGTCTCTGTGTGGATTAAAAAAAGAGTGTCTGATAGCAGCTTCTGA	B@>87<;A@?@957:>>@AA at B>@A9AB at B>@A@@@@@A;=AAB at BBBBBCBBBB@>A>:ABB at BAABCB=CA at CB */
+
+    // the number of tokens we expect to parse from a read line
+    private static final int expectedTokenCount = 11;
+
+    public SAMReadCodec() {
+        super(SAMReadFeature.class);
+    }
+
+    /**
+     * Decode a single line in a SAM text file.
+     * @param line line to decode.
+     * @return A SAMReadFeature modeling that line.
+     */
+    public SAMReadFeature decode(String line) {
+        // we may be asked to process a header line; ignore it
+        if (line.startsWith("@")) return null;        
+
+        String[] tokens = new String[expectedTokenCount];
+
+        // split the line
+        int count = ParsingUtils.splitWhitespace(line,tokens);
+
+        // check to see if we've parsed the string into the right number of tokens (expectedTokenCount)
+        if (count != expectedTokenCount)
+            throw new CodecLineParsingException("the SAM read line didn't have the expected number of tokens " +
+                                                "(expected = " + expectedTokenCount + ", saw = " + count + " on " +
+                                                "line = " + line + ")");
+
+        final String readName = tokens[0];
+        final int flags = Integer.parseInt(tokens[1]);
+        final String contigName = tokens[2];
+        final int alignmentStart = Integer.parseInt(tokens[3]);
+        final int mapQ = Integer.parseInt(tokens[4]);
+        final String cigarString = tokens[5];
+        final String mateContigName = tokens[6];
+        final int mateAlignmentStart = Integer.parseInt(tokens[7]);
+        final int inferredInsertSize = Integer.parseInt(tokens[8]);
+        final byte[] bases = StringUtil.stringToBytes(tokens[9]);
+        final byte[] qualities = StringUtil.stringToBytes(tokens[10]);
+
+        // Infer the alignment end.
+        Cigar cigar = TextCigarCodec.getSingleton().decode(cigarString);
+        int alignmentEnd = alignmentStart + cigar.getReferenceLength() - 1;
+
+        // Remove printable character conversion from the qualities.
+        for(byte quality: qualities) quality -= 33;
+
+        return new SAMReadFeature(readName,
+                                  flags,
+                                  contigName,
+                                  alignmentStart,
+                                  alignmentEnd,
+                                  mapQ,
+                                  cigarString,
+                                  mateContigName,
+                                  mateAlignmentStart,
+                                  inferredInsertSize,
+                                  bases,
+                                  qualities);
+    }
+
+    @Override
+    public Object readActualHeader(LineIterator lineIterator) {
+        // No header for this format
+        return null;
+    }
+}
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/codecs/samread/SAMReadFeature.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/codecs/samread/SAMReadFeature.java
new file mode 100644
index 0000000..129ae6e
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/codecs/samread/SAMReadFeature.java
@@ -0,0 +1,199 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.utils.codecs.samread;
+
+import htsjdk.tribble.Feature;
+
+/**
+ * Represents a SAM record read from a SAM text format file. 
+ *
+ * @author mhanna
+ * @version 0.1
+ */
+public class SAMReadFeature implements Feature {
+    /**
+     * Name of this read.
+     */
+    private final String readName;
+
+    /**
+     * Flags associated with this read.
+     */
+    private final int flags;
+
+    /**
+     * Contig to which this read is aligned.
+     */
+    private final String contig;
+
+    /**
+     * Position on contig to which this read is aligned.
+     */
+    private final int alignmentStart;
+
+    /**
+     * Position on contig at which this alignment ends.
+     */
+    private final int alignmentEnd;
+
+    /**
+     * Mapping quality for the read.
+     */
+    private final int mapQ;
+
+    /**
+     * Cigar string matching read to reference.
+     */
+    private final String cigarString;
+
+    /**
+     * Contig to which this read's pair is aligned.
+     */
+    private final String mateContig;
+
+    /**
+     * Position in contig to which this read's pair is aligned.
+     */
+    private final int mateAlignmentStart;
+
+    /**
+     * Size between pairs.
+     */
+    private final int insertSize;
+
+    /**
+     * Bases in this read.
+     */
+    private final byte[] bases;
+
+    /**
+     * Qualities constituting this read.
+     */
+    private final byte[] qualities;
+
+    // Tags are not currently supported.
+
+    /**
+     * create the read feature.  Default protection so that only other classes in this package can create it.
+     */
+    SAMReadFeature(final String readName,
+                   final int flags,
+                   final String contig,
+                   final int alignmentStart,
+                   final int alignmentEnd,
+                   final int mapQ,
+                   final String cigarString,
+                   final String mateContig,
+                   final int mateAlignmentStart,
+                   final int insertSize,
+                   final byte[] bases,
+                   final byte[] qualities) {
+        this.readName = readName;
+        this.flags = flags;
+        this.contig = contig;
+        this.alignmentStart = alignmentStart;
+        this.alignmentEnd = alignmentEnd;
+        this.mapQ = mapQ;
+        this.cigarString = cigarString;
+        this.mateContig = mateContig;
+        this.mateAlignmentStart = mateAlignmentStart;
+        this.insertSize = insertSize;
+        this.bases = bases;
+        this.qualities = qualities;
+    }
+
+    public String getReadName() {
+        return readName;
+    }
+
+    public int getFlags() {
+        return flags;
+    }
+
+    public String getReferenceName() {
+        return contig;
+    }
+
+    public int getAlignmentStart() {
+        return alignmentStart;
+    }
+
+    public int getAlignmentEnd() {
+        return alignmentEnd;
+    }
+
+    /**
+     * An alias for getReferenceName, required by Feature interface.
+     * @return Aligned contig name.
+     */
+    public String getChr() {
+        return getReferenceName();
+    }
+
+    /**
+     * An alias for getAlignmentEnd(), required by Feature interface.
+     * @return End of alignment, inclusive.
+     */
+    public int getStart() {
+        return getAlignmentStart();
+    }
+
+    /**
+     * An alias for getAlignmentStart(), required by Feature interface.
+     * @return Aligned position.  1-based.
+     */
+    public int getEnd() {
+        return getAlignmentEnd();
+    }    
+
+    public int getMappingQuality() {
+        return mapQ;
+    }
+
+    public String getCigarString() {
+        return cigarString;
+    }
+
+    public String getMateReferenceName() {
+        return mateContig;
+    }
+
+    public int getMateAlignmentStart() {
+        return mateAlignmentStart;
+    }
+
+    public int getInferredInsertSize() {
+        return insertSize;
+    }
+
+    public byte[] getReadBases() {
+        return bases;    
+    }
+
+    public byte[] getReadQualities() {
+        return qualities;
+    }
+}
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/codecs/table/BedTableCodec.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/codecs/table/BedTableCodec.java
new file mode 100644
index 0000000..9a0115f
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/codecs/table/BedTableCodec.java
@@ -0,0 +1,59 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.utils.codecs.table;
+
+import htsjdk.tribble.Feature;
+import org.broadinstitute.gatk.engine.refdata.ReferenceDependentFeatureCodec;
+
+import java.util.Arrays;
+
+/**
+ * The standard table codec that expects loci as contig start stop, not contig:start-stop
+ *
+ * <p>
+ * The standard table codec with a slightly different parsing convention
+ * (expects loci as contig start stop, not contig:start-stop)
+ * </p>
+ *
+ * <p>
+ * See also: TableCodec
+ * </p>
+ *
+ * @author Chris Hartl
+ * @since 2010
+ */
+public class BedTableCodec extends TableCodec implements ReferenceDependentFeatureCodec {
+
+    @Override
+    public TableFeature decode(String line) {
+        if (line.startsWith(headerDelimiter) || line.startsWith(commentDelimiter) || line.startsWith(igvHeaderDelimiter))
+            return null;
+        String[] split = line.split(delimiterRegex);
+        if (split.length < 1)
+            throw new IllegalArgumentException("TableCodec line = " + line + " doesn't appear to be a valid table format");
+        return new TableFeature(genomeLocParser.createGenomeLoc(split[0],Integer.parseInt(split[1])-1,Integer.parseInt(split[2])), Arrays.asList(split),header);
+    }
+}
\ No newline at end of file
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/codecs/table/TableCodec.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/codecs/table/TableCodec.java
new file mode 100644
index 0000000..1058d3e
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/codecs/table/TableCodec.java
@@ -0,0 +1,126 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.utils.codecs.table;
+
+import htsjdk.tribble.AsciiFeatureCodec;
+import htsjdk.tribble.readers.LineIterator;
+import org.broadinstitute.gatk.engine.refdata.ReferenceDependentFeatureCodec;
+import org.broadinstitute.gatk.utils.GenomeLocParser;
+import org.broadinstitute.gatk.utils.exceptions.UserException;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+
+/**
+ * Reads tab deliminated tabular text files
+ *
+ * <p>
+ *     <ul>
+ *     <li>Header: must begin with line HEADER or track (for IGV), followed by any number of column names,
+ *     separated by whitespace.</li>
+ *     <li>Comment lines starting with # are ignored</li>
+ *     <li>Each non-header and non-comment line is split into parts by whitespace,
+ *     and these parts are assigned as a map to their corresponding column name in the header.
+ *     Note that the first element (corresponding to the HEADER column) must be a valid genome loc
+ *     such as 1, 1:1 or 1:1-10, which is the position of the Table element on the genome.  TableCodec
+ *     requires that there be one value for each column in the header, and no more, on all lines.</li>
+ *     </ul>
+ * </p>
+ *
+ * </p>
+ *
+ * <h2>File format example</h2>
+ * <pre>
+ *     HEADER a b c
+ *     1:1  1   2   3
+ *     1:2  4   5   6
+ *     1:3  7   8   9
+ * </pre>
+ *
+ * @author Mark DePristo
+ * @since 2009
+ */
+public class TableCodec extends AsciiFeatureCodec<TableFeature> implements ReferenceDependentFeatureCodec {
+    final static protected String delimiterRegex = "\\s+";
+    final static protected String headerDelimiter = "HEADER";
+    final static protected String igvHeaderDelimiter = "track";
+    final static protected String commentDelimiter = "#";
+
+    protected ArrayList<String> header = new ArrayList<String>();
+
+    /**
+     * The parser to use when resolving genome-wide locations.
+     */
+    protected GenomeLocParser genomeLocParser;
+
+    public TableCodec() {
+        super(TableFeature.class);
+    }
+
+    /**
+     * Set the parser to use when resolving genetic data.
+     * @param genomeLocParser The supplied parser.
+     */
+    @Override
+    public void setGenomeLocParser(GenomeLocParser genomeLocParser) {
+        this.genomeLocParser =  genomeLocParser;
+    }
+
+    @Override
+    public TableFeature decode(String line) {
+        if (line.startsWith(headerDelimiter) || line.startsWith(commentDelimiter) || line.startsWith(igvHeaderDelimiter))
+            return null;
+        String[] split = line.split(delimiterRegex);
+        if (split.length < 1)
+            throw new IllegalArgumentException("TableCodec line = " + line + " doesn't appear to be a valid table format");
+        return new TableFeature(genomeLocParser.parseGenomeLoc(split[0]),Arrays.asList(split), header);
+    }
+
+    @Override
+    public Object readActualHeader(final LineIterator reader) {
+        boolean isFirst = true;
+        while (reader.hasNext()) {
+            final String line = reader.peek(); // Peek to avoid reading non-header data
+            if ( isFirst && ! line.startsWith(headerDelimiter) && ! line.startsWith(commentDelimiter)) {
+                throw new UserException.MalformedFile("TableCodec file does not have a header");
+            }
+            isFirst &= line.startsWith(commentDelimiter);
+            if (line.startsWith(headerDelimiter)) {
+                reader.next(); // "Commit" the peek
+                if (header.size() > 0) throw new IllegalStateException("Input table file seems to have two header lines.  The second is = " + line);
+                final String spl[] = line.split(delimiterRegex);
+                Collections.addAll(header, spl);
+                return header;
+            } else if (line.startsWith(commentDelimiter)) {
+                reader.next(); // "Commit" the peek
+            } else {
+                break;
+            }
+        }
+        return header;
+    }
+}
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/codecs/table/TableFeature.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/codecs/table/TableFeature.java
new file mode 100644
index 0000000..58b06c9
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/codecs/table/TableFeature.java
@@ -0,0 +1,99 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.utils.codecs.table;
+
+
+import htsjdk.tribble.Feature;
+import org.broadinstitute.gatk.utils.GenomeLoc;
+import org.broadinstitute.gatk.utils.Utils;
+
+import java.util.List;
+
+/**
+ * A feature representing a single row out of a text table
+ */
+public class TableFeature implements Feature {
+    // stores the values for the columns seperated out
+    private final List<String> values;
+
+    // if we have column names, we store them here
+    private final List<String> keys;
+
+    // our location
+    private final GenomeLoc position;
+
+    public TableFeature(GenomeLoc position, List<String> values, List<String> keys) {
+        this.values = values;
+        this.keys = keys;
+        this.position = position;
+    }
+
+    @Override
+    public String getChr() {
+        return position.getContig();
+    }
+
+    @Override
+    public int getStart() {
+        return (int)position.getStart();
+    }
+
+    @Override
+    public int getEnd() {
+        return (int)position.getStop();
+    }
+
+    public String getValue(int columnPosition) {
+        if (columnPosition >= values.size()) throw new IllegalArgumentException("We only have " + values.size() + "columns, the requested column = " + columnPosition);
+        return values.get(columnPosition);
+    }
+
+    public String toString() {
+        return String.format("%s\t%s",position.toString(), Utils.join("\t",values));
+    }
+
+    public String get(String columnName) {
+        int position = keys.indexOf(columnName);
+        if (position < 0) throw new IllegalArgumentException("We don't have a column named " + columnName);
+        return values.get(position);
+    }
+
+    public GenomeLoc getLocation() {
+        return this.position;
+    }
+
+    public List<String> getAllValues() {
+        return getValuesTo(values.size());
+    }
+
+    public List<String> getValuesTo(int columnPosition) {
+        return values.subList(0,columnPosition);
+    }
+
+    public List<String> getHeader() {
+        return keys;
+    }
+}
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/collections/DefaultHashMap.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/collections/DefaultHashMap.java
new file mode 100644
index 0000000..2c543dd
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/collections/DefaultHashMap.java
@@ -0,0 +1,56 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.utils.collections;
+
+import java.util.HashMap;
+
+/**
+ * Created with IntelliJ IDEA.
+ * User: farjoun
+ * Date: 10/30/12
+ * Time: 3:20 PM
+ * To change this template use File | Settings | File Templates.
+ */
+
+//lifted from http://stackoverflow.com/questions/7519339
+//could also use org.apache.commons.collections.map.DefaultedMap http://commons.apache.org/collections/apidocs/org/apache/commons/collections/map/DefaultedMap.html
+public class DefaultHashMap<K,V> extends HashMap<K,V> {
+
+    public void setDefaultValue(V defaultValue) {
+        this.defaultValue = defaultValue;
+    }
+    protected V defaultValue;
+    public DefaultHashMap(V defaultValue) {
+        this.defaultValue = defaultValue;
+    }
+    @Override
+    public V get(Object k) {
+        V v = super.get(k);
+        return ((v == null) && !this.containsKey(k)) ? this.defaultValue : v;
+    }
+
+}
+
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/collections/ExpandingArrayList.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/collections/ExpandingArrayList.java
new file mode 100644
index 0000000..b2b23d3
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/collections/ExpandingArrayList.java
@@ -0,0 +1,69 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.utils.collections;
+
+import java.util.ArrayList;
+import java.util.Collection;
+
+public class ExpandingArrayList<E> extends ArrayList<E> {
+    public ExpandingArrayList() { super(); }
+    public ExpandingArrayList(Collection<? extends E> c) { super(c); }
+    public ExpandingArrayList(int initialCapacity) { super(initialCapacity); }
+
+    /**
+     * Returns the element at the specified position in this list.  If index > size,
+     * returns null.  Otherwise tries to access the array
+     * @param index
+     * @return
+     * @throws IndexOutOfBoundsException in index < 0
+     */
+    public E get(int index) throws IndexOutOfBoundsException {
+        if ( index < size() )
+            return super.get(index);
+        else
+            return null;
+    }
+
+    public E expandingGet(int index, E default_value) throws IndexOutOfBoundsException {
+        maybeExpand(index, default_value);
+        return super.get(index);
+    }
+
+    private void maybeExpand(int index, E value) {
+        if ( index >= size() ) {
+            ensureCapacity(index+1); // make sure we have space to hold at least index + 1 elements
+            // We need to add null items until we can safely set index to element
+            for ( int i = size(); i <= index; i++ )
+                add(value);
+        }
+    }
+
+
+    public E set(int index, E element) {
+        maybeExpand(index, null);
+        return super.set(index, element);
+    }
+}
\ No newline at end of file
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/collections/IndexedSet.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/collections/IndexedSet.java
new file mode 100644
index 0000000..2bedb92
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/collections/IndexedSet.java
@@ -0,0 +1,342 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.utils.collections;
+
+import it.unimi.dsi.fastutil.objects.Object2IntMap;
+import it.unimi.dsi.fastutil.objects.Object2IntOpenHashMap;
+
+import java.util.*;
+
+/**
+* Set set where each element can be reference by a unique integer index that runs from
+*     0 to the size of the set - 1.
+*
+* @author Valentin Ruano-Rubio <valentin at broadinstitute.org>
+*/
+public class IndexedSet<E> extends AbstractSet<E> implements Set<E> {
+
+    /**
+     * Elements stored in an array-list by their index.
+     */
+    private final ArrayList<E> elements;
+
+    /**
+     * A unmodifiable view to the element list. Initially {@code null} it is thread-unsafe lazy instantiated
+     * when requested first time through {@link #asList}. Therefore typically it is shared by invoking code but
+     * there could be some extra copies (rare though) in multi-thread runs.
+     */
+    private transient List<E> unmodifiableElementsListView;
+
+    /**
+     * Quick element to index lookup map.
+     * <p>
+     *  Uses a primitive int value map for efficiency sake.
+     * </p>
+     */
+    private final Object2IntMap<E> indexByElement;
+
+    /**
+     * Creates an empty indexed set indicating the expected number of elements.
+     *
+     * @param initialCapacity the initial number of elements.
+     */
+    public IndexedSet(final int initialCapacity) {
+        elements = new ArrayList<>(initialCapacity);
+        indexByElement = new Object2IntOpenHashMap<>(initialCapacity);
+    }
+
+    /**
+     * Creates a new sample list from a existing collection of elements.
+     *
+     * <p>
+     *     Elements will be indexed as they appear in the input array. Repeats will be ignored.
+     * </p>
+     *
+     * @param values the original sample list.
+     *
+     * @throws IllegalArgumentException
+     * if {@code values} array is {@code null} itself, or it contains {@code null}.
+     */
+    @SuppressWarnings("unchecked")
+    public IndexedSet(final Collection<E> values) {
+        if (values == null)
+            throw new IllegalArgumentException("input values cannot be null");
+
+        final int initialCapacity = values.size();
+        elements = new ArrayList<>(initialCapacity);
+        indexByElement = new Object2IntOpenHashMap<>(initialCapacity);
+        int nextIndex = 0;
+        for (final E value : values) {
+            if (value == null)
+                throw new IllegalArgumentException("null element not allowed: index == " + nextIndex);
+            if (indexByElement.containsKey(value))
+                continue;
+            indexByElement.put(value, nextIndex++);
+            elements.add(value);
+        }
+    }
+
+    /**
+     * Creates a new sample list from a existing array of elements.
+     *
+     * <p>
+     *     Elements will be indexed as they appear in the collection. Repeats will be ignored.
+     * </p>
+     *
+     * @param values the original sample list.
+     *
+     * @throws IllegalArgumentException
+     * if {@code values} collection is {@code null} itself, or it contains {@code null}.
+     */
+    @SuppressWarnings("unchecked")
+    public IndexedSet(final E ... values) {
+        if (values == null)
+            throw new IllegalArgumentException("input values cannot be null");
+
+        final int initialCapacity = values.length;
+        elements = new ArrayList<>(initialCapacity);
+        indexByElement = new Object2IntOpenHashMap<>(initialCapacity);
+        int nextIndex = 0;
+        for (final E value : values) {
+            if (value == null)
+                throw new IllegalArgumentException("null element not allowed: index == " + nextIndex);
+            if (indexByElement.containsKey(value))
+                continue;
+            indexByElement.put(value, nextIndex++);
+            elements.add(value);
+        }
+    }
+
+    /**
+     * Returns a list view of the elements in the set.
+     *
+     * <p>
+     *     Elements are sorted by their index within the set.
+     * </p>
+     *
+     * <p>
+     *     This view changes as the indexed set changes but it cannot be used to update its contents.
+     *     In such case a {@link UnsupportedOperationException} exception will be thrown if the calling
+     *     code tries to tho just that.
+     * </p>
+     *
+     * @return never {@code null}.
+     */
+    public List<E> asList() {
+        if (unmodifiableElementsListView == null)
+            unmodifiableElementsListView = Collections.unmodifiableList(elements);
+        return unmodifiableElementsListView;
+    }
+
+    /**
+     * Throws an exception if an index is out of bounds.
+     *
+     * <p>
+     *     An element index is valid iff is within [0,{@link #size()}).
+     * </p>
+     *
+     * @param index the query index.
+     *
+     * @throws IllegalArgumentException {@code index} is out of bounds.
+     */
+    protected void checkIndex(final int index) {
+        if (index < 0)
+            throw new IllegalArgumentException("the index cannot be negative: " + index);
+        if (index >= size())
+            throw new IllegalArgumentException("the index is equal or larger than the list length: " + index + " >= " + size());
+    }
+
+    @Override
+    public Iterator<E> iterator() {
+        return asList().iterator();
+    }
+
+    /**
+     * Returns number of elements in the set.
+     * @return never {@code null}.
+     */
+    @Override
+    public int size() {
+        return elements.size();
+    }
+
+    /**
+     *
+     * @param o
+     * @return {@code true} iff {@code o} is in
+     */
+    @Override
+    @SuppressWarnings("all")
+    public boolean contains(final Object o) {
+        return o != null && indexByElement.containsKey(o);
+    }
+
+    /**
+     * Adds a new element to the set.
+     *
+     * <p>
+     *     If the element was already in th set nothing will happen and the method will return {@code false}. However,
+     *     if the element is new to this set, it will assigned the next index available (equal to the size before addition).
+     *     The method will return {@code true} in this case.
+     * </p>
+     *
+     * @param o the object to add.
+     *
+     * @throw IllegalArgumentException if {@code o} is {@code null}.
+     *
+     * @return {@code true} iff the set was modified by this operation.
+     */
+    @Override
+    public boolean add(final E o) {
+        if (o == null)
+            throw new IllegalArgumentException("the input argument cannot be null");
+        if (contains(o))
+            return false;
+        final int nextIndex = size();
+        elements.add(o);
+        indexByElement.put(o, nextIndex);
+        return true;
+    }
+
+    /**
+     * Removes an element from the set.
+     *
+     * <p>
+     *     If the element was not present in the set, nothing happens and the method return false. However,
+     *     if the element is new to this set, it will be assigned the next index available (equal to the size
+     *     before addition).
+     *     The method will return {@code true} in this case.
+     * </p>
+     *
+     * @param o the object to add.
+     *
+     * @throw IllegalArgumentException if {@code o} is {@code null}.
+     *
+     * @return {@code true} iff the set was modified by this operation.
+     */   @Override
+    public boolean remove(final Object o) {
+        final int index = indexByElement.removeInt(o);
+        if (index == -1)
+            return false;
+        elements.remove(index);
+        indexByElement.remove(o);
+        final ListIterator<E> it = elements.listIterator(index);
+        int nextIndex = index;
+        while (it.hasNext())
+            indexByElement.put(it.next(),nextIndex++);
+        return true;
+    }
+
+    /**
+     * Removes all elements in the set.
+     */
+    @Override
+    public void clear() {
+        elements.clear();
+        indexByElement.clear();
+    }
+
+    /**
+     * Compares this with another indexed set.
+     * @param o the other object to compare to.
+     * @return {@code false} unless {@code o} is a indexed-set that contains the same elements in the same order.
+     */
+    @Override
+    public boolean equals(final Object o) {
+        if (o == this)
+            return true;
+        if (o == null)
+            return false;
+        if (!(o instanceof IndexedSet<?>))
+            return false;
+
+        final IndexedSet<?> other = (IndexedSet<?>)o;
+
+        return equals(other);
+    }
+
+    /**
+     * Compare to another indexed set.
+     *
+     * @param other the target indexed set.
+     *
+     * @throws java.lang.IllegalArgumentException if {@code other} is {@code null}.
+     *
+     * @return {@code true} iff {@other} is not {@code null}, and contains exactly the same elements
+     * (as compared using {@link Object#equals} a this set with matching indices.
+     */
+    public boolean equals(final IndexedSet<?> other) {
+        if (other == null)
+            throw new IllegalArgumentException("other cannot be null");
+        final ArrayList<?> otherElements = other.elements;
+
+        final int elementCount = elements.size();
+        if (otherElements.size() != elementCount)
+            return false;
+        for (int i = 0; i < elementCount; i++)
+            if (!elements.get(i).equals(otherElements.get(i)))
+                return false;
+        return true;
+    }
+
+    @Override
+    public int hashCode() {
+        int result = 1;
+
+        for (final E element : elements)
+            result = 31 * result + (element == null ? 0 : element.hashCode());
+        return result;
+    }
+
+    /**
+     * Returns the element given its index within the set.
+     * @param index the target element's index.
+     *
+     * @throws IllegalArgumentException if {@code index} is not valid; in [0,{@link #size()}).
+     *
+     * @return never {@code null}; as null is not a valid element.
+     */
+    public E get(final int index) {
+        checkIndex(index);
+        return elements.get(index);
+    }
+
+    /**
+     * Returns the index of an object.
+     * @param o the object of interest.
+     *
+     * @throws IllegalArgumentException if {@code o} is {@code null}.
+     *
+     * @return {@code -1} if such an object is not an element of this set, otherwise is index in the set thus a
+     * values within [0,{@link #size()}).
+     */
+    public int indexOf(final E o) {
+        if (o == null)
+            throw new IllegalArgumentException("the query object cannot be null");
+        return indexByElement.containsKey(o) ? indexByElement.getInt(o) : -1;
+    }
+
+}
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/collections/LoggingNestedIntegerArray.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/collections/LoggingNestedIntegerArray.java
new file mode 100644
index 0000000..3117852
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/collections/LoggingNestedIntegerArray.java
@@ -0,0 +1,120 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.utils.collections;
+
+import org.broadinstitute.gatk.utils.exceptions.ReviewedGATKException;
+
+import java.io.PrintStream;
+
+/**
+ * Wrapper around the basic NestedIntegerArray class that logs all updates (ie., all calls to put())
+ * to the provided output stream. For testing/debugging purposes.
+ *
+ * Log entries are of the following form (fields are tab-separated):
+ * LABEL    OPERATION    VALUE   KEY1    KEY2    ...     KEY_N
+ *
+ * A header line is written before the log entries giving the dimensions of this NestedIntegerArray.
+ * It has the form:
+ *
+ * # LABEL    SIZE_OF_FIRST_DIMENSION    SIZE_OF_SECOND_DIMENSION    ...    SIZE_OF_NTH_DIMENSION
+ *
+ * @author David Roazen
+ */
+public class LoggingNestedIntegerArray<T> extends NestedIntegerArray<T> {
+
+    private PrintStream log;
+    private String logEntryLabel;
+
+    public static final String HEADER_LINE_PREFIX = "# ";
+    public enum NestedIntegerArrayOperation { GET, PUT };
+
+    /**
+     *
+     * @param log output stream to which to log update operations
+     * @param logEntryLabel String that should be prefixed to each log entry
+     * @param dimensions
+     */
+    public LoggingNestedIntegerArray( PrintStream log, String logEntryLabel, final int... dimensions ) {
+        super(dimensions);
+
+        if ( log == null ) {
+            throw new ReviewedGATKException("Log output stream must not be null");
+        }
+        this.log = log;
+        this.logEntryLabel = logEntryLabel != null ? logEntryLabel : "";
+
+        // Write the header line recording the dimensions of this NestedIntegerArray:
+        StringBuilder logHeaderLine = new StringBuilder();
+
+        logHeaderLine.append(HEADER_LINE_PREFIX);
+        logHeaderLine.append(this.logEntryLabel);
+        for ( int dimension : dimensions ) {
+            logHeaderLine.append("\t");
+            logHeaderLine.append(dimension);
+        }
+
+        this.log.println(logHeaderLine.toString());
+    }
+
+    @Override
+    public T get( final int... keys ) {
+        StringBuilder logEntry = new StringBuilder();
+
+        logEntry.append(logEntryLabel);
+        logEntry.append("\t");
+        logEntry.append(NestedIntegerArrayOperation.GET);
+        logEntry.append("\t");  // empty field for the datum value
+
+        for ( int key : keys ) {
+            logEntry.append("\t");
+            logEntry.append(key);
+        }
+
+        log.println(logEntry.toString());
+
+        return super.get(keys);
+    }
+
+    @Override
+    public boolean put( final T value, final int... keys ) {
+        StringBuilder logEntry = new StringBuilder();
+
+        logEntry.append(logEntryLabel);
+        logEntry.append("\t");
+        logEntry.append(NestedIntegerArrayOperation.PUT);
+        logEntry.append("\t");
+        logEntry.append(value);
+        for ( int key : keys ) {
+            logEntry.append("\t");
+            logEntry.append(key);
+        }
+
+        // PrintStream methods all use synchronized blocks internally, so our logging is thread-safe
+        log.println(logEntry.toString());
+
+        return super.put(value, keys);
+    }
+}
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/collections/NestedIntegerArray.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/collections/NestedIntegerArray.java
new file mode 100644
index 0000000..02dd15a
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/collections/NestedIntegerArray.java
@@ -0,0 +1,221 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.utils.collections;
+
+import org.apache.log4j.Logger;
+import org.broadinstitute.gatk.utils.exceptions.ReviewedGATKException;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+/**
+ * Created by IntelliJ IDEA.
+ * User: ebanks
+ * Date: July 1, 2012
+ */
+
+public class NestedIntegerArray<T> {
+
+    private static Logger logger = Logger.getLogger(NestedIntegerArray.class);
+
+    protected final Object[] data;
+
+    protected final int numDimensions;
+    protected final int[] dimensions;
+
+    // Preallocate the first two dimensions to limit contention during tree traversals in put()
+    private static final int NUM_DIMENSIONS_TO_PREALLOCATE = 2;
+
+    public NestedIntegerArray(final int... dimensions) {
+        numDimensions = dimensions.length;
+        if ( numDimensions == 0 )
+            throw new ReviewedGATKException("There must be at least one dimension to an NestedIntegerArray");
+        this.dimensions = dimensions.clone();
+
+        int dimensionsToPreallocate = Math.min(dimensions.length, NUM_DIMENSIONS_TO_PREALLOCATE);
+
+        if ( logger.isDebugEnabled() ) logger.debug(String.format("Creating NestedIntegerArray with dimensions %s", Arrays.toString(dimensions)));
+        if ( logger.isDebugEnabled() ) logger.debug(String.format("Pre-allocating first %d dimensions", dimensionsToPreallocate));
+
+        data = new Object[dimensions[0]];
+        preallocateArray(data, 0, dimensionsToPreallocate);
+
+        if ( logger.isDebugEnabled() ) logger.debug(String.format("Done pre-allocating first %d dimensions", dimensionsToPreallocate));
+    }
+
+    /**
+     * @return the dimensions of this nested integer array.  DO NOT MODIFY
+     */
+    public int[] getDimensions() {
+        return dimensions;
+    }
+
+    /**
+     * Recursively allocate the first dimensionsToPreallocate dimensions of the tree
+     *
+     * Pre-allocating the first few dimensions helps limit contention during tree traversals in put()
+     *
+     * @param subarray current node in the tree
+     * @param dimension current level in the tree
+     * @param dimensionsToPreallocate preallocate only this many dimensions (starting from the first)
+     */
+    private void preallocateArray( Object[] subarray, int dimension, int dimensionsToPreallocate ) {
+        if ( dimension >= dimensionsToPreallocate - 1 ) {
+            return;
+        }
+
+        for ( int i = 0; i < subarray.length; i++ ) {
+            subarray[i] = new Object[dimensions[dimension + 1]];
+            preallocateArray((Object[])subarray[i], dimension + 1, dimensionsToPreallocate);
+        }
+    }
+
+    public T get(final int... keys) {
+        final int numNestedDimensions = numDimensions - 1;
+        Object[] myData = data;
+
+        for( int i = 0; i < numNestedDimensions; i++ ) {
+            if ( keys[i] >= dimensions[i] )
+                return null;
+
+            myData = (Object[])myData[keys[i]];
+            if ( myData == null )
+                return null;
+        }
+
+        return (T)myData[keys[numNestedDimensions]];
+    }
+
+    /**
+     * Insert a value at the position specified by the given keys.
+     *
+     * This method is thread-safe, however the caller MUST check the
+     * return value to see if the put succeeded. This method RETURNS FALSE if
+     * the value could not be inserted because there already was a value present
+     * at the specified location. In this case the caller should do a get() to get
+     * the already-existing value and (potentially) update it.
+     *
+     * @param value value to insert
+     * @param keys keys specifying the location of the value in the tree
+     * @return true if the value was inserted, false if it could not be inserted because there was already
+     *         a value at the specified position
+     */
+    public boolean put(final T value, final int... keys) { // WARNING! value comes before the keys!
+        if ( keys.length != numDimensions )
+            throw new ReviewedGATKException("Exactly " + numDimensions + " keys should be passed to this NestedIntegerArray but " + keys.length + " were provided");
+
+        final int numNestedDimensions = numDimensions - 1;
+        Object[] myData = data;
+        for ( int i = 0; i < numNestedDimensions; i++ ) {
+            if ( keys[i] >= dimensions[i] )
+                throw new ReviewedGATKException("Key " + keys[i] + " is too large for dimension " + i + " (max is " + (dimensions[i]-1) + ")");
+
+            // If we're at or beyond the last dimension that was pre-allocated, we need to do a synchronized
+            // check to see if the next branch exists, and if it doesn't, create it
+            if ( i >= NUM_DIMENSIONS_TO_PREALLOCATE - 1 ) {
+                synchronized ( myData ) {
+                    if ( myData[keys[i]] == null ) {
+                        myData[keys[i]] = new Object[dimensions[i + 1]];
+                    }
+                }
+            }
+
+            myData = (Object[])myData[keys[i]];
+        }
+
+        synchronized ( myData ) {   // lock the bottom row while we examine and (potentially) update it
+
+            // Insert the new value only if there still isn't any existing value in this position
+            if ( myData[keys[numNestedDimensions]] == null ) {
+                myData[keys[numNestedDimensions]] = value;
+            }
+            else {
+                // Already have a value for this leaf (perhaps another thread came along and inserted one
+                // while we traversed the tree), so return false to notify the caller that we didn't put
+                // the item
+                return false;
+            }
+        }
+
+        return true;
+    }
+
+    public List<T> getAllValues() {
+        final List<T> result = new ArrayList<T>();
+        fillAllValues(data, result);
+        return result;
+    }
+
+    private void fillAllValues(final Object[] array, final List<T> result) {
+        for ( Object value : array ) {
+            if ( value == null )
+                continue;
+            if ( value instanceof Object[] )
+                fillAllValues((Object[])value, result);
+            else
+                result.add((T)value);
+        }
+    }
+
+    public static class Leaf<T> {
+        public final int[] keys;
+        public final T value;
+
+        public Leaf(final int[] keys, final T value) {
+            this.keys = keys;
+            this.value = value;
+        }
+    }
+
+    public List<Leaf<T>> getAllLeaves() {
+        final List<Leaf<T>> result = new ArrayList<Leaf<T>>();
+        fillAllLeaves(data, new int[0], result);
+        return result;
+    }
+
+    private void fillAllLeaves(final Object[] array, final int[] path, final List<Leaf<T>> result) {
+        for ( int key = 0; key < array.length; key++ ) {
+            final Object value = array[key];
+            if ( value == null )
+                continue;
+            final int[] newPath = appendToPath(path, key);
+            if ( value instanceof Object[] ) {
+                fillAllLeaves((Object[]) value, newPath, result);
+            } else {
+                result.add(new Leaf<T>(newPath, (T)value));
+            }
+        }
+    }
+
+    private int[] appendToPath(final int[] path, final int newKey) {
+        final int[] newPath = new int[path.length + 1];
+        for ( int i = 0; i < path.length; i++ )
+            newPath[i] = path[i];
+        newPath[path.length] = newKey;
+        return newPath;
+    }
+}
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/collections/Pair.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/collections/Pair.java
new file mode 100644
index 0000000..b09c9df
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/collections/Pair.java
@@ -0,0 +1,93 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.utils.collections;
+
+
+public class Pair<X,Y> {
+    // declare public, STL-style for easier and more efficient access:
+    public X first; 
+    public Y second;
+
+    public Pair(X x, Y y) { first = x; second = y; }
+
+    public void set(X x, Y y) { first = x; second = y; }
+
+    /** Java-style getter; note that we currently allow direct access to 
+        the member field.
+    */
+    public X getFirst() { return first; }
+
+    /** Java-style getter; note that we currently allow direct access to 
+        the member field.
+    */
+    public Y getSecond() { return second; }
+
+    /**
+     * Calculate whether this pair object is equal to another object.
+     * @param o The other object (hopefully a pair).
+     * @return True if the two are equal; false otherwise.
+     */
+    @Override
+    public boolean equals( Object o ) {
+        if( o == null )
+            return false;
+        if( !(o instanceof Pair) )
+            return false;
+
+        Pair other = (Pair)o;
+
+        // Check to see whether one is null but not the other.
+        if( this.first == null && other.first != null ) return false;
+        if( this.second == null && other.second != null ) return false;
+
+        // Check to see whether the values are equal.
+        //  If the param of equals is null, it should by contract return false.
+        if( this.first != null && !this.first.equals(other.first) ) return false;
+        if( this.second != null && !this.second.equals(other.second) ) return false;        
+
+        return true;
+    }
+
+    /**
+     * Basic hashcode function.  Assume hashcodes of first and second are
+     * randomly distributed and return the XOR of the two.
+     * @return Randomly distributed hashcode of the pair.
+     */
+    @Override
+    public int hashCode() {
+        if( second == null && first == null )
+            return 0;
+        if( second == null )
+            return first.hashCode();
+        if( first == null )
+            return second.hashCode();
+        return first.hashCode() ^ second.hashCode();
+    }
+
+    public String toString() {
+        return first+","+second;
+    }
+}
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/collections/Permutation.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/collections/Permutation.java
new file mode 100644
index 0000000..53eafe7
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/collections/Permutation.java
@@ -0,0 +1,103 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.utils.collections;
+
+import java.util.List;
+
+/**
+ * Represent a permutation of a ordered set or list of elements.
+ *
+ * @author Valentin Ruano-Rubio <valentin at broadinstitute.org>
+ */
+public interface Permutation<E> {
+
+    /**
+     * Checks whether this permutation is a partial one of the original list.
+     *
+     * <p>
+     *     A partial permutation is one in that no all original elements take part of.
+     * </p>
+     *
+     * @return {@code true} iff this is a partial permutation.
+     */
+    public boolean isPartial();
+
+    /**
+     * Checks whether this is a trivial permutation where the resulting element list is the same as original.
+     *
+     * @return {@code true} iff the resulting element list is the same as the original.
+     */
+    public boolean isNonPermuted();
+
+    /**
+     * Given an index on the original list, returns the position of tha element in the resulting list.
+     *
+     * @param fromIndex the query original element index.
+     *
+     * @throws IllegalArgumentException if {@code fromIndex} is not a valid index within the original list.
+     *
+     * @return -1 if that element is not part of the result (partial) permutation, otherwise some number between
+     *   0 and {@link #toSize()} - 1.
+     */
+    public int toIndex(final int fromIndex);
+
+    /**
+     * Given an index on the resulting list, it gives you the index of that element on the original list.
+     * @param toIndex the query resulting list index.
+     *
+     * @throws IllegalArgumentException if {@code toIndex} is not a valid index, i.e. in [0,{@link #toSize()}-1).
+     *
+     * @return a value between 0 and {@link #fromSize()} - 1.
+     */
+    public int fromIndex(final int toIndex);
+
+    /**
+     * Length of the original element list.
+     *
+     * @return 0 or greater.
+     */
+    public int fromSize();
+
+    /**
+     * Length of the resulting element list.
+     *
+     * @return 0 or greater.
+     */
+    public int toSize();
+
+    /**
+     * Returns an unmodifiable view to the original element list.
+     * @return never {@code null}.
+     */
+    public List<E> fromList();
+
+    /**
+     * Returns an unmodifiable view to the original element list.
+     *
+     * @return never {@code null}.
+     */
+    public List<E> toList();
+}
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/collections/PrimitivePair.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/collections/PrimitivePair.java
new file mode 100644
index 0000000..2b759ce
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/collections/PrimitivePair.java
@@ -0,0 +1,200 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.utils.collections;
+
+
+/** This class is used to group together multiple Pair classes for
+ *  primitive types (thanks to generics shortcomings, these implementations
+ *  are more efficient then generic ones). This class contains no methods and
+ *  no fields, but only declarations of inner classes.
+ */
+ 
+public class PrimitivePair {
+
+   /** Pair of two integers */
+  public static class Int {
+    // declare public, STL-style for easier and more efficient access:
+    public int first; 
+    public int second;
+
+    public Int(int x, int y) { first = x; second = y; }
+    public Int() { first = second = 0; }
+
+    public void set(int x, int y) { first = x; second = y; }
+
+    /** Java-style getter; note that we currently allow direct access to 
+        the member field.
+    */
+    public int getFirst() { return first; }
+
+    /** Java-style getter; note that we currently allow direct access to 
+        the member field.
+    */
+    public int getSecond() { return second; }
+
+       /** Increments the elements of this pair by the
+        * corresponding elements of the pair <code>p</code> and returns this
+        * pair (modified). This method does not allocate a new pair, but changes
+        * in place the values stored in the object the method is invoked from. The
+        * method is unsafe: if p is null, a runtime exception will be thrown.
+        * @param p
+        * @return
+        */
+    public PrimitivePair.Int add(PrimitivePair.Int p) {
+        first += p.first;
+        second += p.second;
+        return this;
+    }
+
+       /** Decrements the elements of this pair by the
+        * corresponding elements of the pair <code>p</code> and returns this
+        * pair (modified). This method does not allocate a new pair, but changes
+        * in place the values stored in the object the method is invoked from. The
+        * method is unsafe: if p is null, a runtime exception will be thrown.
+        * @param p
+        * @return
+        */
+    public PrimitivePair.Int subtract(PrimitivePair.Int p) {
+        first -= p.first;
+        second -= p.second;
+        return this;
+    }
+
+       /** Copies values from the argument <code>p</code> into the corresponding
+        * elements of this pair and returns this pair (modified).
+        * @param p
+        * @return
+        */
+    public PrimitivePair.Int assignFrom(PrimitivePair.Int p ) {
+        first = p.first;
+        second = p.second;
+        return this;
+    }
+
+
+  }
+
+    public static class Long {
+      // declare public, STL-style for easier and more efficient access:
+      public long first;
+      public long second;
+
+      public Long(long x, long y) { first = x; second = y; }
+      public Long() { first = second = 0; }
+
+      public void set(long x, long y) { first = x; second = y; }
+
+      /** Java-style getter; note that we currently allow direct access to
+          the member field.
+      */
+      public long getFirst() { return first; }
+
+      /** Java-style getter; note that we currently allow direct access to
+          the member field.
+      */
+      public long getSecond() { return second; }
+
+        /** Increments the elements of this pair by the
+         * corresponding elements of the pair <code>p</code> and returns this
+         * pair (modified). This method does not allocate a new pair, but changes
+         * in place the values stored in the object the method is invoked from. The
+         * method is unsafe: if p is null, a runtime exception will be thrown.
+         * @param p
+         * @return
+         */
+     public PrimitivePair.Long add(PrimitivePair.Int p) {
+         first += p.first;
+         second += p.second;
+         return this;
+     }
+
+        /** Increments the elements of this pair by the
+         * corresponding elements of the pair <code>p</code> and returns this
+         * pair (modified). This method does not allocate a new pair, but changes
+         * in place the values stored in the object the method is invoked from. The
+         * method is unsafe: if p is null, a runtime exception will be thrown.
+         * @param p
+         * @return
+         */
+     public PrimitivePair.Long add(PrimitivePair.Long p) {
+         first += p.first;
+         second += p.second;
+         return this;
+     }
+
+        /** Decrements the elements of this pair by the
+         * corresponding elements of the pair <code>p</code> and returns this
+         * pair (modified). This method does not allocate a new pair, but changes
+         * in place the values stored in the object the method is invoked from. The
+         * method is unsafe: if p is null, a runtime exception will be thrown.
+         * @param p
+         * @return
+         */
+     public PrimitivePair.Long subtract(PrimitivePair.Int p) {
+         first -= p.first;
+         second -= p.second;
+         return this;
+     }
+
+        /** Decrements the elements of this pair by the
+         * corresponding elements of the pair <code>p</code> and returns this
+         * pair (modified). This method does not allocate a new pair, but changes
+         * in place the values stored in the object the method is invoked from. The
+         * method is unsafe: if p is null, a runtime exception will be thrown.
+         * @param p
+         * @return
+         */
+     public PrimitivePair.Long subtract(PrimitivePair.Long p) {
+         first -= p.first;
+         second -= p.second;
+         return this;
+     }
+
+     /** Copies values from the argument <code>p</code> into the corresponding
+       * elements of this pair and returns this pair (modified).
+       * @param p
+       * @return
+     */
+     public PrimitivePair.Long assignFrom(PrimitivePair.Long p ) {
+         first = p.first;
+         second = p.second;
+         return this;
+     }
+
+     /** Copies values from the argument <code>p</code> into the corresponding
+       * elements of this pair and returns this pair (modified).
+       * @param p
+       * @return
+     */
+     public PrimitivePair.Long assignFrom(PrimitivePair.Int p ) {
+            first = p.first;
+            second = p.second;
+            return this;
+     }
+
+    }
+
+}
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/collections/RODMergingIterator.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/collections/RODMergingIterator.java
new file mode 100644
index 0000000..7af62bd
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/collections/RODMergingIterator.java
@@ -0,0 +1,160 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.utils.collections;
+
+import org.broadinstitute.gatk.engine.refdata.utils.LocationAwareSeekableRODIterator;
+import org.broadinstitute.gatk.engine.refdata.utils.RODRecordList;
+import org.broadinstitute.gatk.utils.GenomeLoc;
+import org.broadinstitute.gatk.utils.exceptions.ReviewedGATKException;
+
+import java.util.Collection;
+import java.util.Iterator;
+import java.util.LinkedList;
+import java.util.PriorityQueue;
+
+public class RODMergingIterator implements Iterator<RODRecordList>, Iterable<RODRecordList> {
+    PriorityQueue<Element> queue = new PriorityQueue<Element>();
+
+    private class Element implements Comparable<Element> {
+        public LocationAwareSeekableRODIterator it = null;
+        public GenomeLoc nextLoc = null;
+
+        public Element(Iterator<RODRecordList> it) {
+            if ( it instanceof LocationAwareSeekableRODIterator) {
+                this.it = (LocationAwareSeekableRODIterator)it;
+                if ( ! it.hasNext() ) throw new ReviewedGATKException("Iterator is empty");
+                update();
+            } else {
+                throw new ReviewedGATKException("Iterator passed to RODMergingIterator is not LocationAwareSeekableRODIterator");
+            }
+        }
+
+        public Element update() {
+ //           E prev = value;
+            nextLoc = it.peekNextLocation(); // will return null if there is no next location
+            return this;
+        }
+
+        public int compareTo(Element other) {
+            if ( nextLoc == null ) {
+                if ( other.nextLoc != null ) return 1; // null means no more data available, so its after any non-null position
+                return 0;
+            }
+            if ( other.nextLoc == null ) return -1; // we can get to this point only if this.nextLoc != null
+
+            return nextLoc.compareTo(other.nextLoc);
+        }
+
+        public RODRecordList next() {
+            RODRecordList value = it.next();
+            update();
+            return value;
+        }
+    }
+
+    public Iterator<RODRecordList> iterator() {
+        return this;
+    }
+
+    public RODMergingIterator() {
+        ;
+    }
+
+    public RODMergingIterator(Iterator<RODRecordList> it) {
+         add(it);
+    }
+
+    public RODMergingIterator(Collection<Iterator<RODRecordList>> its) {
+        for ( Iterator<RODRecordList> it : its ) {
+            add(it);
+        }
+    }
+
+    /** If the iterator is non-empty (hasNext() is true), put it into the queue. The next location the iterator
+     * will be after a call to next() is peeked into and cached as queue's priority value.
+     * @param it
+     */
+    public void add(Iterator<RODRecordList> it) {
+        if ( it.hasNext() )
+            queue.add(new Element(it));
+    }
+
+    public boolean hasNext() {
+        return ! queue.isEmpty();
+    }
+
+    public RODRecordList next() {
+        Element e = queue.poll();
+        RODRecordList value = e.next(); // next() will also update next location cached by the Element
+
+        if ( e.nextLoc != null ) // we have more data in the track
+            queue.add(e); // add the element back to queue (note: its next location, on which priority is based, was updated
+
+        //System.out.printf("Element is %s%n", e.value);
+        return value;
+    }
+
+    /** Peeks into the genomic location of the record this iterator will return next.
+     *
+     * @return
+     */
+    public GenomeLoc peekLocation() {
+        return queue.peek().nextLoc;
+    }
+
+    public Collection<RODRecordList> allElementsLTE(RODRecordList elt) {
+        return allElementsLTE(elt, true);
+    }
+
+    public Collection<RODRecordList> allElementsLTE(RODRecordList elt, boolean includeElt) {
+        LinkedList<RODRecordList> all = new LinkedList<RODRecordList>();
+
+        if ( includeElt ) all.add(elt);
+        
+        while ( hasNext() ) {
+            Element x = queue.peek();
+            //System.out.printf("elt.compareTo(x) == %d%n", elt.compareTo(x));
+            //System.out.printf("In allElementLTE%n");
+            int cmp = elt.getLocation().compareTo(x.nextLoc);
+            //System.out.printf("x=%s%n  elt=%s%n  => elt.compareTo(x) == %d%n", x, elt, cmp);
+            if ( cmp >= 0 ) {
+                //System.out.printf("  Adding element x=%s, size = %d%n", x, all.size());
+                all.add(next());
+                //System.out.printf("  Added size = %d%n", all.size());
+            }
+            else {
+                //System.out.printf("breaking...%n");
+                break;
+            }
+        }
+
+        return all;
+    }
+
+    public void remove() {
+        throw new UnsupportedOperationException();
+    }
+}
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/commandline/Advanced.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/commandline/Advanced.java
new file mode 100644
index 0000000..3995ff7
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/commandline/Advanced.java
@@ -0,0 +1,41 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.utils.commandline;
+
+import java.lang.annotation.*;
+
+/**
+ * Indicates that a walker argument should is considered an advanced option.
+ *
+ * @author Mark DePristo
+ * @version 0.1
+ */
+ at Documented
+ at Inherited
+ at Retention(RetentionPolicy.RUNTIME)
+ at Target({ElementType.TYPE,ElementType.FIELD})
+public @interface Advanced {
+}
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/commandline/Argument.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/commandline/Argument.java
new file mode 100644
index 0000000..66c5629
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/commandline/Argument.java
@@ -0,0 +1,125 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.utils.commandline;
+
+import java.lang.annotation.*;
+
+/**
+ * Created by IntelliJ IDEA.
+ * User: hanna
+ * Date: Mar 24, 2009
+ * Time: 11:11:36 AM
+ */
+/**
+ * Annotates fields in objects that should be used as command-line arguments.
+ * Any field annotated with @Argument can appear as a command-line parameter. 
+ */
+ at Documented
+ at Inherited
+ at Retention(RetentionPolicy.RUNTIME)
+ at Target(ElementType.FIELD)
+public @interface Argument {
+    /**
+     * The full name of the command-line argument.  Full names should be
+     * prefixed on the command-line with a double dash (--).
+     * @return Selected full name, or "" to use the default.
+     */
+    String fullName() default "";
+
+    /**
+     * Specified short name of the command.  Short names should be prefixed
+     * with a single dash.  Argument values can directly abut single-char
+     * short names or be separated from them by a space.
+     * @return Selected short name, or "" for none.
+     */
+    String shortName() default "";
+
+    /**
+     * Documentation for the command-line argument.  Should appear when the
+     * --help argument is specified. 
+     * @return Doc string associated with this command-line argument.
+     */
+    String doc() default "Undocumented option";
+
+    /**
+     * Is this argument required.  If true, the command-line argument system will
+     * make a best guess for populating this argument based on the type descriptor,
+     * and will fail if the type can't be populated.
+     * @return True if the argument is required.  False otherwise.
+     */
+    boolean required() default true;
+
+    /**
+     * Should this command-line argument be exclusive of others.  Should be
+     * a comma-separated list of names of arguments of which this should be
+     * independent.
+     * @return A comma-separated string listing other arguments of which this
+     *         argument should be independent.
+     */
+    String exclusiveOf() default "";
+
+    /**
+     * Provide a regexp-based validation string.
+     * @return Non-empty regexp for validation, blank otherwise. 
+     */
+    String validation() default "";
+
+    /**
+     * Hard lower bound on the allowed value for the annotated argument -- generates an exception if violated.
+     * Enforced only for numeric types whose values are explicitly specified on the command line.
+     *
+     * @return Hard lower bound on the allowed value for the annotated argument, or Double.NEGATIVE_INFINITY
+     *         if there is none.
+     */
+    double minValue() default Double.NEGATIVE_INFINITY;
+
+    /**
+     * Hard upper bound on the allowed value for the annotated argument -- generates an exception if violated.
+     * Enforced only for numeric types whose values are explicitly specified on the command line.
+     *
+     * @return Hard upper bound on the allowed value for the annotated argument, or Double.POSITIVE_INFINITY
+     *         if there is none.
+     */
+    double maxValue() default Double.POSITIVE_INFINITY;
+
+    /**
+     * Soft lower bound on the allowed value for the annotated argument -- generates a warning if violated.
+     * Enforced only for numeric types whose values are explicitly specified on the command line.
+     *
+     * @return Soft lower bound on the allowed value for the annotated argument, or Double.NEGATIVE_INFINITY
+     *         if there is none.
+     */
+    double minRecommendedValue() default Double.NEGATIVE_INFINITY;
+
+    /**
+     * Soft upper bound on the allowed value for the annotated argument -- generates a warning if violated.
+     * Enforced only for numeric types whose values are explicitly specified on the command line.
+     *
+     * @return Soft upper bound on the allowed value for the annotated argument, or Double.POSITIVE_INFINITY
+     *         if there is none.
+     */
+    double maxRecommendedValue() default Double.POSITIVE_INFINITY;
+}
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/commandline/ArgumentCollection.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/commandline/ArgumentCollection.java
new file mode 100644
index 0000000..c142f06
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/commandline/ArgumentCollection.java
@@ -0,0 +1,45 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.utils.commandline;
+
+import java.lang.annotation.*;
+
+/**
+ * @author aaron
+ * @version 1.0
+ * @date May 8, 2009
+ * <p/>
+ * @interface ArgumentCollection
+ * <p/>
+ * This object represents an class, that is a collection of arguments.
+ */
+ at Documented
+ at Inherited
+ at Retention(RetentionPolicy.RUNTIME)
+ at Target({ElementType.FIELD})
+public @interface ArgumentCollection {
+
+}
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/commandline/ArgumentDefinition.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/commandline/ArgumentDefinition.java
new file mode 100644
index 0000000..f2e7e6e
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/commandline/ArgumentDefinition.java
@@ -0,0 +1,297 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.utils.commandline;
+
+import org.broadinstitute.gatk.utils.Utils;
+import org.broadinstitute.gatk.utils.exceptions.ReviewedGATKException;
+
+import java.lang.annotation.Annotation;
+import java.util.List;
+
+/**
+ * A specific argument definition.  Maps one-to-one with a field in some class.
+ */
+public class ArgumentDefinition {
+    /**
+     * Whether an argument is an input or an output.
+     */
+    public final ArgumentIOType ioType;
+
+    /**
+     * The class of the argument.
+     */
+    public final Class argumentType;
+
+    /**
+     * Full name of the argument.  Must have a value.
+     */
+    public final String fullName;
+
+    /**
+     * Short name of the argument.  Can be null.
+     */
+    public final String shortName;
+
+    /**
+     * Doc string for the argument.  Displayed in help.
+     */
+    public final String doc;
+
+    /**
+     * Must this argument be specified on the command-line?  Note that there's a
+     * critical difference between the meaning of a required argument from the
+     * perspective of the argument source and the perspective of the argument
+     * definition: the argument source's required field indicates that the field
+     * should somehow be populated by the GATK (and fail if there's an error).
+     * The ArgumentDefinition required element means that the required element
+     * must be specified on the command-line.
+     */
+    public final boolean required;
+
+    /**
+     * Is this argument a flag?  Users can't specify a value for a flag.
+     */
+    public final boolean isFlag;
+
+    /**
+     * Does this argument support multiple values (repeated "-arg value1 -arg value2"-style structures).
+     */
+    public final boolean isMultiValued;
+
+    /**
+     * The class of the componentType.  Not used for scalars.
+     */
+    public final Class componentType;
+
+    /**
+     * Is this argument hidden from the help system?
+     */
+    public final boolean isHidden;
+
+    /**
+     * Is this argument exclusive of other arguments?
+     */
+    public final String exclusiveOf;
+
+    /**
+     * Can we validate this regular expression?
+     */
+    public final String validation;
+
+    /**
+     * A list of valid options for this argument, if there is a compelling subset.
+     */
+    public final List<String> validOptions;
+
+    /**
+     * Creates a new argument definition.
+     * @param ioType Whether the argument is an input or an output.
+     * @param argumentType The class of the field.
+     * @param fullName Full name for this argument definition.
+     * @param shortName Short name for this argument definition.
+     * @param doc Doc string for this argument.
+     * @param required Whether or not this argument is required.
+     * @param isFlag Whether or not this argument should be treated as a flag.
+     * @param isMultiValued Whether or not this argument supports multiple values.
+     * @param isHidden Whether or not this argument should be hidden from the command-line argument system.
+     * @param componentType For multivalued arguments the type of the components.
+     * @param exclusiveOf Whether this command line argument is mutually exclusive of other arguments.
+     * @param validation A regular expression for command-line argument validation.
+     * @param validOptions is there a particular list of options that's valid for this argument definition?  List them if so, otherwise set this to null. 
+     */
+    public ArgumentDefinition( ArgumentIOType ioType,
+                               Class argumentType,
+                               String fullName,
+                               String shortName,
+                               String doc,
+                               boolean required,
+                               boolean isFlag,
+                               boolean isMultiValued,
+                               boolean isHidden,
+                               Class componentType,
+                               String exclusiveOf,
+                               String validation,
+                               List<String> validOptions) {
+        this.ioType = ioType;
+        this.argumentType = argumentType;
+        this.fullName = fullName;
+        this.shortName = shortName;
+        this.doc = doc;
+        this.required = required;
+        this.isFlag = isFlag;
+        this.isMultiValued = isMultiValued;
+        this.isHidden = isHidden;
+        this.componentType = componentType;
+        this.exclusiveOf = exclusiveOf;
+        this.validation = validation;
+        this.validOptions = validOptions;
+
+        validateName(shortName);
+        validateName(fullName);
+    }
+
+    /**
+     * Creates a new argument definition.
+     * @param annotation The annotation on the field.
+     * @param argumentType The class of the field.
+     * @param defaultFullName Default full name for this argument definition.
+     * @param defaultShortName Default short name for this argument definition.
+     * @param isFlag Whether or not this argument should be treated as a flag.
+     * @param isMultiValued Whether or not this argument supports multiple values.
+     * @param componentType For multivalued arguments the type of the components.
+     * @param isHidden Whether or not this argument should be hidden from the command-line argument system.
+     * @param validOptions is there a particular list of options that's valid for this argument definition?  List them if so, otherwise set this to null.
+     */
+    public ArgumentDefinition( Annotation annotation,
+                               ArgumentIOType ioType,
+                               Class argumentType,
+                               String defaultFullName,
+                               String defaultShortName,
+                               String doc,
+                               boolean isRequired,
+                               boolean isFlag,
+                               boolean isMultiValued,
+                               boolean isHidden,
+                               Class componentType,
+                               String exclusiveOf,
+                               String validation,
+                               List<String> validOptions) {
+
+        String fullName = (String)CommandLineUtils.getValue(annotation, "fullName");
+        String shortName = (String)CommandLineUtils.getValue(annotation, "shortName");
+        boolean isFullNameProvided = fullName.trim().length() > 0;
+        boolean isShortNameProvided = shortName.trim().length() > 0;
+
+        fullName = isFullNameProvided ? fullName.trim() : defaultFullName;
+
+        // If the short name is provided, use that.  If the user hasn't provided any names at all, use
+        // the default.  If somewhere in the middle, leave the short name blank.
+        if( isShortNameProvided )
+            shortName = shortName.trim();
+        else if( !isFullNameProvided )
+            shortName = defaultShortName;
+        else
+            shortName = null;
+
+        validateName(shortName);
+        validateName(fullName);
+
+        this.ioType = ioType;
+        this.argumentType = argumentType;
+        this.fullName = fullName;
+        this.shortName = shortName;
+        this.doc = doc;
+        this.required = isRequired;
+        this.isFlag = isFlag;
+        this.isMultiValued = isMultiValued;
+        this.isHidden = isHidden;
+        this.componentType = componentType;
+        this.exclusiveOf = exclusiveOf;
+        this.validation = validation;
+        this.validOptions = validOptions;
+    }
+    
+    @Override
+    public int hashCode() {
+        int hashCode = fullName.hashCode();
+        if(shortName != null) hashCode ^= shortName.hashCode();
+        return hashCode;
+    }
+
+    public boolean equals( Object o ) {
+        if( o == null )
+            return false;
+        if( !(o instanceof ArgumentDefinition) )
+            return false;
+
+        ArgumentDefinition other = (ArgumentDefinition)o;
+
+        return Utils.equals(fullName,other.fullName) &&
+               Utils.equals(shortName,other.shortName);
+    }
+
+    /**
+     * Retrieves the full name of the argument, specifiable with the '--' prefix.  The full name can be
+     * either specified explicitly with the fullName annotation parameter or implied by the field name.
+     * @param annotation Original field annotation.
+     * @param fieldName Original field name.
+     * @return full name of the argument.  Never null.
+     */
+    public static String getFullName( Annotation annotation, String fieldName ) {
+        String fullName = (String)CommandLineUtils.getValue(annotation, "fullName");
+        return fullName.trim().length() > 0 ? fullName.trim() : fieldName.toLowerCase();
+    }
+
+    /**
+     * Retrieves the short name of the argument, specifiable with the '-' prefix.  The short name can
+     * be specified or not; if left unspecified, no short name will be present.
+     * @param annotation Original field annotation.
+     * @return short name of the argument.  Null if no short name exists.
+     */
+    public static String getShortName( Annotation annotation ) {
+        String shortName = (String)CommandLineUtils.getValue(annotation, "shortName");
+        return shortName.trim().length() > 0 ? shortName.trim() : null;
+    }
+
+    /**
+     * Documentation for this argument.  Mandatory field.
+     * @param annotation Original field annotation.
+     * @return Documentation for this argument.
+     */
+    public static String getDoc( Annotation annotation ) {
+        return (String)CommandLineUtils.getValue(annotation, "doc");
+    }
+
+    /**
+     * Specifies other arguments which cannot be used in conjunction with this argument.  Comma-separated list.
+     * @param annotation Original field annotation.
+     * @return A comma-separated list of exclusive arguments, or null if none are present.
+     */
+    public static String getExclusiveOf( Annotation annotation ) {
+        String exclusiveOf = (String)CommandLineUtils.getValue(annotation, "exclusiveOf");
+        return exclusiveOf.trim().length() > 0 ? exclusiveOf.trim() : null;
+    }
+
+    /**
+     * A regular expression which can be used for validation.
+     * @param annotation Original field annotation.
+     * @return a JVM regex-compatible regular expression, or null to permit any possible value.
+     */
+    public static String getValidationRegex( Annotation annotation ) {
+        String validation = (String)CommandLineUtils.getValue(annotation, "validation");
+        return validation.trim().length() > 0 ? validation.trim() : null;
+    }
+
+    /**
+     * Make sure the argument's name is valid
+     *
+     * @param name
+     */
+    private void validateName(final String name) {
+        if ( name != null && name.startsWith("-") )
+            throw new ReviewedGATKException("Invalid argument definition: " + name + " begins with a -");
+    }
+}
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/commandline/ArgumentDefinitionGroup.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/commandline/ArgumentDefinitionGroup.java
new file mode 100644
index 0000000..b6bb16c
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/commandline/ArgumentDefinitionGroup.java
@@ -0,0 +1,99 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.utils.commandline;
+
+import org.broadinstitute.gatk.utils.exceptions.ReviewedGATKException;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Iterator;
+import java.util.List;
+
+/**
+ * A group of argument definitions.
+ */
+public class ArgumentDefinitionGroup implements Iterable<ArgumentDefinition> {
+    /**
+     * Name of this group.
+     */
+    public final String groupName;
+
+    /**
+     * The argument definitions associated with this group.
+     */
+    public final List<ArgumentDefinition> argumentDefinitions;
+
+    public ArgumentDefinitionGroup( String groupName, List<ArgumentDefinition> argumentDefinitions ) {
+        this.groupName = groupName;
+        this.argumentDefinitions = Collections.unmodifiableList( argumentDefinitions );
+    }
+
+    /**
+     * Does the name of this argument group match the name of another?
+     */
+    public boolean groupNameMatches( ArgumentDefinitionGroup other ) {
+        if( this.groupName == null )
+            return other.groupName == null;
+        return this.groupName.equals(other.groupName);
+    }
+
+    /**
+     * Merges another argument group into this argument group.  Return a new
+     * group since argument groups are supposed to be immutable. Asserts that
+     * both argument groups have the same name.
+     */
+    public ArgumentDefinitionGroup merge( ArgumentDefinitionGroup other ) {
+        if( !groupNameMatches(other) )
+            throw new ReviewedGATKException("Unable to merge two argument groups with differing names.");
+
+        // Create a merged definition group.
+        List<ArgumentDefinition> mergedDefinitions = new ArrayList<ArgumentDefinition>();
+        mergedDefinitions.addAll(this.argumentDefinitions);
+        mergedDefinitions.addAll(other.argumentDefinitions);
+
+        return new ArgumentDefinitionGroup(groupName,mergedDefinitions);
+    }
+
+    /**
+     * Iterate over the arguments in an argument definition group.
+     * @return
+     */
+    public Iterator<ArgumentDefinition> iterator() {
+        return argumentDefinitions.iterator();
+    }
+
+    /**
+     * Reports whether all the arguments in this group are hidden.
+     * @return True if all are hidden, false if some or none are hidden.
+     */
+    public boolean allHidden() {
+        for(ArgumentDefinition argumentDefinition: argumentDefinitions) {
+            if(!argumentDefinition.isHidden)
+                return false;
+        }
+        return true;
+    }
+}
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/commandline/ArgumentDefinitions.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/commandline/ArgumentDefinitions.java
new file mode 100644
index 0000000..8bc17d7
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/commandline/ArgumentDefinitions.java
@@ -0,0 +1,195 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.utils.commandline;
+
+import org.broadinstitute.gatk.utils.exceptions.ReviewedGATKException;
+
+import java.util.Collection;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.Set;
+
+/**
+ * A collection of argument definitions.
+ */
+public class ArgumentDefinitions implements Iterable<ArgumentDefinition> {
+    /**
+     * Backing data set of argument stored by short name and long name.
+     */
+    private Set<ArgumentDefinition> argumentDefinitions = new HashSet<ArgumentDefinition>();
+
+    /**
+     * The groupings of argument definitions.  Used mainly for help output.
+     */
+    private Set<ArgumentDefinitionGroup> argumentDefinitionGroups = new HashSet<ArgumentDefinitionGroup>();
+
+    /**
+     * Adds an argument to the this argument definition list.
+     * @param argumentDefinitionGroup The group of arguments to add.
+     */
+    public void add( ArgumentDefinitionGroup argumentDefinitionGroup ) {
+        for( ArgumentDefinition definition: argumentDefinitionGroup ) {
+            // Do some basic validation before adding the definition. 
+            if( definition.fullName.length() == 0 )
+                throw new IllegalArgumentException( "Argument cannot have 0-length fullname." );
+            if( hasArgumentDefinition( definition.fullName, FullNameDefinitionMatcher ) )
+                throw new ReviewedGATKException("Duplicate definition of argument with full name: " + definition.fullName);
+            if( definition.shortName != null && hasArgumentDefinition( definition.shortName, ShortNameDefinitionMatcher ) )
+                throw new ReviewedGATKException("Duplicate definition of argument with short name: " + definition.shortName);
+
+            argumentDefinitions.add( definition );
+        }
+
+        // Find an existing argument definition group with this name.
+        // If one exists, merge this group into the other.
+        Iterator<ArgumentDefinitionGroup> definitionGroupIterator = argumentDefinitionGroups.iterator();
+        while( definitionGroupIterator.hasNext() ) {
+            ArgumentDefinitionGroup candidate = definitionGroupIterator.next();            
+            if( candidate.groupNameMatches(argumentDefinitionGroup) ) {
+                argumentDefinitionGroup = candidate.merge(argumentDefinitionGroup);
+                definitionGroupIterator.remove();
+            }
+        }
+
+        // Otherwise, add the new group.
+        argumentDefinitionGroups.add( argumentDefinitionGroup );
+    }
+
+    /**
+     * Are there any argument definitions matching the given property?
+     * @param property Property to find.
+     * @param matcher Method of matching a given property.
+     * @return True if one or multiple argument definitions match; false otherwise.
+     */
+    public boolean hasArgumentDefinition( Object property, DefinitionMatcher matcher ) {
+        return findArgumentDefinitions( property, matcher ).size() > 0;
+    }
+
+    /**
+     * Find the given definition matching this property.
+     * @param property Property to find.
+     * @param matcher Method of matching a given property.
+     * @return The ArgumentDefinition matching the given property.  Null if none matches.
+     * @throws IllegalArgumentException if multiple arguments match this definition.
+     */
+    public ArgumentDefinition findArgumentDefinition( Object property, DefinitionMatcher matcher ) {
+        Collection<ArgumentDefinition> selectedDefinitions = findArgumentDefinitions( property, matcher );
+        if( selectedDefinitions.size() > 1 )
+            throw new IllegalArgumentException("Multiple argument definitions match the selected property: " + property);
+
+        if( selectedDefinitions.size() == 0 )
+            return null;
+
+        return selectedDefinitions.iterator().next();
+    }
+
+    /**
+     * Find all argument definitions matching a certain category.
+     * @param property Property to inspect.
+     * @param matcher Test to see whether property matches.
+     * @return All argument definitions matching a certain object.
+     */
+    public Collection<ArgumentDefinition> findArgumentDefinitions( Object property, DefinitionMatcher matcher ) {
+        Set<ArgumentDefinition> selectedArgumentDefinitions = new HashSet<ArgumentDefinition>();
+        for( ArgumentDefinition argumentDefinition: argumentDefinitions ) {
+            if( matcher.matches( argumentDefinition, property ) )
+                selectedArgumentDefinitions.add( argumentDefinition );
+        }
+        return selectedArgumentDefinitions;
+    }
+
+    /**
+     * Return a list of the available argument groups.
+     * @return All the argument groups that have been added.
+     */
+    public Collection<ArgumentDefinitionGroup> getArgumentDefinitionGroups() {
+        return argumentDefinitionGroups;
+    }
+
+    /**
+     * Iterates through all command-line arguments.
+     * @return an iterator over command-line arguments.
+     */
+    public Iterator<ArgumentDefinition> iterator() {
+        return argumentDefinitions.iterator();
+    }
+
+    /**
+     * Match the full name of a definition.
+     */
+    static DefinitionMatcher FullNameDefinitionMatcher = new DefinitionMatcher() {
+        public boolean matches( ArgumentDefinition definition, Object key ) {
+            if( definition.fullName == null )
+                return key == null;
+            else
+                return definition.fullName.equals( key );
+        }        
+    };
+
+    /**
+     * Match the short name of a definition.
+     */
+    static DefinitionMatcher ShortNameDefinitionMatcher = new DefinitionMatcher() {
+        public boolean matches( ArgumentDefinition definition, Object key ) {
+            if( definition.shortName == null )
+                return key == null;
+            else
+                return definition.shortName.equals( key );
+        }
+    };
+
+    /**
+     * Find all required definitions.
+     */
+    static DefinitionMatcher RequiredDefinitionMatcher = new DefinitionMatcher() {
+        public boolean matches( ArgumentDefinition definition, Object key ) {
+            if( !(key instanceof Boolean) )
+                throw new IllegalArgumentException("RequiredDefinitionMatcher requires boolean key");
+            return definition.required == (Boolean)key;
+        }
+    };
+
+    static DefinitionMatcher VerifiableDefinitionMatcher = new DefinitionMatcher() {
+        public boolean matches( ArgumentDefinition definition, Object key ) {
+            // We can perform some sort of validation for anything that isn't a flag or enum.
+            // Because enums can have a default value, it might be valid to specify an enum argument with no value
+            return !definition.isFlag  && !definition.argumentType.isEnum();
+        }        
+    };
+}
+
+/**
+ * A Comparator-esque interface for finding argument definitions within a collection.
+ */
+interface DefinitionMatcher {
+    /**
+     * Does the given definition match the provided key?
+     * @param definition The definition to inspect.
+     * @param key The value to match.
+     * @return True if the key matches the definition, false otherwise.
+     */
+    boolean matches( ArgumentDefinition definition, Object key );
+}
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/commandline/ArgumentException.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/commandline/ArgumentException.java
new file mode 100644
index 0000000..a55da89
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/commandline/ArgumentException.java
@@ -0,0 +1,38 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.utils.commandline;
+
+import org.broadinstitute.gatk.utils.exceptions.UserException;
+
+/**
+ * Generic class for handling misc parsing exceptions.
+ */
+public class ArgumentException extends UserException {
+    public ArgumentException( String message ) {
+        super( message );
+    }
+}
+
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/commandline/ArgumentIOType.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/commandline/ArgumentIOType.java
new file mode 100644
index 0000000..27b8163
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/commandline/ArgumentIOType.java
@@ -0,0 +1,52 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.utils.commandline;
+
+import org.broadinstitute.gatk.utils.exceptions.ReviewedGATKException;
+
+import java.lang.annotation.Annotation;
+
+public enum ArgumentIOType {
+    INPUT(Input.class), OUTPUT(Output.class), ARGUMENT(Argument.class);
+
+    public final Class<? extends Annotation> annotationClass;
+
+    ArgumentIOType(Class<? extends Annotation> annotationClass) {
+        this.annotationClass = annotationClass;
+    }
+
+    /**
+     * Returns the ArgumentIOType for the annotation.
+     * @param annotation @Input or @Output
+     * @return ArgumentIOType.Input, Output, or Unknown
+     */
+    public static ArgumentIOType getIOType(Annotation annotation) {
+        for (ArgumentIOType ioType: ArgumentIOType.values())
+            if (ioType.annotationClass.isAssignableFrom(annotation.getClass()))
+                return ioType;
+        throw new ReviewedGATKException("Unknown annotation type: " + annotation);
+    }
+}
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/commandline/ArgumentMatch.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/commandline/ArgumentMatch.java
new file mode 100644
index 0000000..885e02d
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/commandline/ArgumentMatch.java
@@ -0,0 +1,294 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.utils.commandline;
+
+import org.broadinstitute.gatk.engine.walkers.Multiplexer;
+
+import java.util.*;
+
+/**
+ * A mapping of all the sites where an argument definition maps to a site on the command line.
+ */
+public class ArgumentMatch implements Iterable<ArgumentMatch> {
+    /**
+     * The argument definition that's been matched.
+     */
+    public final ArgumentDefinition definition;
+
+    /**
+     * The text that's been matched, as it appears in the command line arguments.
+     */
+    public final String label;
+
+    /**
+     * Maps indices of command line arguments to values paired with that argument.
+     */
+    public final SortedMap<ArgumentMatchSite,List<ArgumentMatchValue>> sites = new TreeMap<ArgumentMatchSite,List<ArgumentMatchValue>>();
+
+    /**
+     * An ordered, freeform collection of tags.
+     */
+    public final Tags tags;
+
+    /**
+     * Create a new argument match, defining its properties later.  Used to create invalid arguments.
+     */
+    public ArgumentMatch() {
+        this(null,null);
+    }
+
+    /**
+     * Minimal constructor for transform function.
+     * @param label Label of the argument match.  Must not be null.
+     * @param definition The associated definition, if one exists.  May be null.
+     */
+    private ArgumentMatch(final String label, final ArgumentDefinition definition) {
+        this.label = label;
+        this.definition = definition;
+        this.tags = new Tags();
+    }
+
+    /**
+     * A simple way of indicating that an argument with the given label and definition exists at this site.
+     * @param label Label of the argument match.  Must not be null.
+     * @param definition The associated definition, if one exists.  May be null.
+     * @param site Position of the argument.  Must not be null.
+     * @param tags ordered freeform text tags associated with this argument.
+     */
+    public ArgumentMatch(final String label, final ArgumentDefinition definition, final ArgumentMatchSite site, final Tags tags) {
+        this( label, definition, site, null, tags );
+    }
+
+    /**
+     * A simple way of indicating that an argument with the given label and definition exists at this site.
+     * @param label Label of the argument match.  Must not be null.
+     * @param definition The associated definition, if one exists.  May be null.
+     * @param site Position of the argument.  Must not be null.
+     * @param value Value for the argument at this position.
+     * @param tags ordered freeform text tags associated with this argument.
+     */
+    private ArgumentMatch(final String label, final ArgumentDefinition definition, final ArgumentMatchSite site, final ArgumentMatchValue value, final Tags tags) {
+        this.label = label;
+        this.definition = definition;
+
+        ArrayList<ArgumentMatchValue> values = new ArrayList<ArgumentMatchValue>();
+        if( value != null )
+            values.add(value);
+        sites.put(site,values );
+
+        this.tags = tags;
+    }
+
+    /**
+     * Check to see whether two ArgumentMatch objects are equal.
+     * @param other Object to which this should be compared.
+     * @return True if objects are equal, false if objects are not equal or incomparable.
+     */
+    @Override
+    public boolean equals(Object other) {
+        // this clearly isn't null, since this.equals() when this == null would result in an NPE.
+        if(other == null)
+            return false;
+        if(!(other instanceof ArgumentMatch))
+            return false;
+        ArgumentMatch otherArgumentMatch = (ArgumentMatch)other;
+        return this.definition.equals(otherArgumentMatch.definition) &&
+                this.label.equals(otherArgumentMatch.label) &&
+                this.sites.equals(otherArgumentMatch.sites) &&
+                this.tags.equals(otherArgumentMatch.tags);
+    }
+
+
+    /**
+     * Reformat the given entries with the given multiplexer and key.
+     * TODO: Generify this.
+     * @param multiplexer Multiplexer that controls the transformation process.
+     * @param key Key which specifies the transform.
+     * @return A variant of this ArgumentMatch with all keys transformed.
+     */
+    @SuppressWarnings("unchecked")
+    ArgumentMatch transform(Multiplexer multiplexer, Object key) {
+        SortedMap<ArgumentMatchSite,List<ArgumentMatchValue>> newIndices = new TreeMap<ArgumentMatchSite,List<ArgumentMatchValue>>();
+        for(Map.Entry<ArgumentMatchSite,List<ArgumentMatchValue>> site: sites.entrySet()) {
+            List<ArgumentMatchValue> newEntries = new ArrayList<ArgumentMatchValue>();
+            for(ArgumentMatchValue entry: site.getValue())
+                newEntries.add(new ArgumentMatchStringValue(multiplexer.transformArgument(key,entry.asString())));
+            newIndices.put(site.getKey(),newEntries);
+        }
+        ArgumentMatch newArgumentMatch = new ArgumentMatch(label,definition);
+        newArgumentMatch.sites.putAll(newIndices);
+        return newArgumentMatch;
+    }
+
+    /**
+     * Return a string representation of the given argument match, for debugging purposes.
+     * @return String representation of the match.
+     */
+    public String toString() {
+        return label;
+    }
+
+    /**
+     * Creates an iterator that walks over each individual match at each position of a given argument.
+     * @return An iterator over the individual matches in this argument.  Will not be null.
+     */
+    public Iterator<ArgumentMatch> iterator() {
+        return new Iterator<ArgumentMatch>() {
+            /**
+             * Iterate over each the available site.
+             */
+            private Iterator<ArgumentMatchSite> siteIterator = null;
+
+            /**
+             * Iterate over each available token.
+             */
+            private Iterator<ArgumentMatchValue> tokenIterator = null;
+
+            /**
+             * The next site to return.  Null if none remain.
+             */
+            ArgumentMatchSite nextSite = null;
+
+            /**
+             * The next token to return.  Null if none remain.
+             */
+            ArgumentMatchValue nextToken = null;
+
+            {
+                siteIterator = sites.keySet().iterator();
+                prepareNext();
+            }
+
+            /**
+             * Is there a nextToken available to return?
+             * @return True if there's another token waiting in the wings.  False otherwise.
+             */
+            public boolean hasNext() {
+                return nextSite != null;
+            }
+
+            /**
+             * Get the next token, if one exists.  If not, throw an IllegalStateException.
+             * @return The next ArgumentMatch in the series.  Should never be null.
+             */
+            public ArgumentMatch next() {
+                if( nextSite == null )
+                    throw new IllegalStateException( "No more ArgumentMatches are available" );
+
+                ArgumentMatch match = new ArgumentMatch( label, definition, nextSite, nextToken, tags );
+                prepareNext();
+                return match;
+            }
+
+            /**
+             * Initialize the next ArgumentMatch to return.  If no ArgumentMatches are available,
+             * initialize nextSite / nextToken to null.
+             */
+            private void prepareNext() {
+                if( tokenIterator != null && tokenIterator.hasNext() ) {
+                    nextToken = tokenIterator.next();
+                }
+                else {
+                    nextSite = null;
+                    nextToken = null;
+
+                    // Do a nested loop.  While more data is present in the inner loop, grab that data.
+                    // Otherwise, troll the outer iterator looking for more data.
+                    while( siteIterator.hasNext() ) {
+                        nextSite = siteIterator.next();
+                        if( sites.get(nextSite) != null ) {
+                            tokenIterator = sites.get(nextSite).iterator();
+                            nextToken = tokenIterator.hasNext() ? tokenIterator.next() : null;
+                            break;
+                        }
+                    }
+                }
+
+            }
+
+            /**
+             * Remove is unsupported in this context.
+             */
+            public void remove() {
+                throw new UnsupportedOperationException("Cannot remove an argument match from the collection while iterating.");
+            }
+        };
+    }
+
+    /**
+     * Merge two ArgumentMatches, so that the values for all arguments go into the
+     * same data structure.
+     * @param other The other match to merge into.
+     */
+    public void mergeInto( ArgumentMatch other ) {
+        sites.putAll(other.sites);
+    }
+
+    /**
+     * Associate a value with this merge maapping.
+     * @param site site of the command-line argument to which this value is mated.
+     * @param value Text representation of value to add.
+     */
+    public void addValue( ArgumentMatchSite site, ArgumentMatchValue value ) {
+        if( !sites.containsKey(site) || sites.get(site) == null )
+            sites.put(site, new ArrayList<ArgumentMatchValue>() );
+        sites.get(site).add(value);
+    }
+
+    /**
+     * Does this argument already have a value at the given site?
+     * Arguments are only allowed to be single-valued per site, and
+     * flags aren't allowed a value at all.
+     * @param site Site at which to check for values.
+     * @return True if the argument has a value at the given site.  False otherwise.
+     */
+    public boolean hasValueAtSite( ArgumentMatchSite site ) {
+        return (sites.get(site) != null && sites.get(site).size() >= 1) || isArgumentFlag();
+    }
+
+    /**
+     * Return the values associated with this argument match.
+     * @return A collection of the string representation of these value.
+     */
+    public List<ArgumentMatchValue> values() {
+        final List<ArgumentMatchValue> values = new ArrayList<ArgumentMatchValue>();
+        for ( final List<ArgumentMatchValue> siteValue : sites.values() ) {
+            if ( siteValue != null )
+                values.addAll(siteValue);
+            else
+                values.add(null);
+        }
+        return values;
+    }
+
+    /**
+     * Convenience method returning true if the definition is a flag.
+     * @return True if definition is known to be a flag; false if not known to be a flag.
+     */
+    private boolean isArgumentFlag() {
+        return definition != null && definition.isFlag;
+    }
+}
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/commandline/ArgumentMatchFileValue.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/commandline/ArgumentMatchFileValue.java
new file mode 100644
index 0000000..3b9c8d3
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/commandline/ArgumentMatchFileValue.java
@@ -0,0 +1,52 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.utils.commandline;
+
+import java.io.File;
+
+/**
+ * Holds a reference to a file as an argument match value.
+ *
+ * This is useful when the type of the stored file may be a subclass of java.io.File,
+ * for example a Queue RemoteFile.
+ */
+public class ArgumentMatchFileValue extends ArgumentMatchValue {
+    private final File file;
+
+    public ArgumentMatchFileValue(File file) {
+        this.file = file;
+    }
+
+    @Override
+    public String asString() {
+        return file == null ? null : file.getAbsolutePath();
+    }
+
+    @Override
+    public File asFile() {
+        return file;
+    }
+}
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/commandline/ArgumentMatchSite.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/commandline/ArgumentMatchSite.java
new file mode 100644
index 0000000..967d4c6
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/commandline/ArgumentMatchSite.java
@@ -0,0 +1,77 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.utils.commandline;
+
+/**
+ * Which source and the index within the source where an argument match was found.
+ */
+public class ArgumentMatchSite implements Comparable<ArgumentMatchSite> {
+    private final ArgumentMatchSource source;
+    private final int index;
+
+    public ArgumentMatchSite(ArgumentMatchSource source, int index) {
+        this.source = source;
+        this.index = index;
+    }
+
+    public ArgumentMatchSource getSource() {
+        return source;
+    }
+
+    public int getIndex() {
+        return index;
+    }
+
+    @Override
+    public boolean equals(Object o) {
+        if (this == o) return true;
+        if (o == null || getClass() != o.getClass()) return false;
+
+        ArgumentMatchSite that = (ArgumentMatchSite) o;
+
+        return (index == that.index) && (source == null ? that.source == null : source.equals(that.source));
+    }
+
+    @Override
+    public int hashCode() {
+        int result = source != null ? source.hashCode() : 0;
+        // Generated by intellij. No other special reason to this implementation. -ks
+        result = 31 * result + index;
+        return result;
+    }
+
+    @Override
+    public int compareTo(ArgumentMatchSite that) {
+        int comp = this.source.compareTo(that.source);
+        if (comp != 0)
+            return comp;
+
+        // Both files are the same.
+        if (this.index == that.index)
+            return 0;
+        return this.index < that.index ? -1 : 1;
+    }
+}
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/commandline/ArgumentMatchSource.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/commandline/ArgumentMatchSource.java
new file mode 100644
index 0000000..a7ce7ba
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/commandline/ArgumentMatchSource.java
@@ -0,0 +1,97 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.utils.commandline;
+
+/**
+ * Where an argument match originated, via the commandline or a custom provider.
+ */
+public class ArgumentMatchSource implements Comparable<ArgumentMatchSource> {
+    public static final ArgumentMatchSource COMMAND_LINE = new ArgumentMatchSource(ArgumentMatchSourceType.CommandLine, null);
+
+    private final ArgumentMatchSourceType type;
+    private final String description;
+
+    /**
+     * Creates an argument match source from the specified file.
+     * @param description Where the arguments originated.
+     */
+    public ArgumentMatchSource(String description) {
+        this(ArgumentMatchSourceType.Provider, description);
+    }
+
+    private ArgumentMatchSource(ArgumentMatchSourceType type, String description) {
+        if (type == ArgumentMatchSourceType.Provider && description == null)
+            throw new IllegalArgumentException("An argument match source provider cannot have a null description.");
+        this.type = type;
+        this.description = description;
+    }
+
+    public ArgumentMatchSourceType getType() {
+        return type;
+    }
+
+    public String getDescription() {
+        return description;
+    }
+
+    @Override
+    public boolean equals(Object o) {
+        if (this == o) return true;
+        if (o == null || getClass() != o.getClass()) return false;
+
+        ArgumentMatchSource that = (ArgumentMatchSource) o;
+
+        return (type == that.type) && (description == null ? that.description == null : description.equals(that.description));
+    }
+
+    @Override
+    public int hashCode() {
+        int result = type != null ? type.hashCode() : 0;
+        result = 31 * result + (description != null ? description.hashCode() : 0);
+        return result;
+    }
+
+    /**
+     * Compares two sources, putting the command line first, then files.
+     */
+    @Override
+    public int compareTo(ArgumentMatchSource that) {
+        int comp = this.type.compareTo(that.type);
+        if (comp != 0)
+            return comp;
+
+        String d1 = this.description;
+        String d2 = that.description;
+
+        if ((d1 == null) ^ (d2 == null)) {
+            // If one of the descriptions is null and the other is not
+            // put the null description first
+            return d1 == null ? -1 : 1;
+        }
+
+        return d1 == null ? 0 : d1.compareTo(d2);
+    }
+}
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/commandline/ArgumentMatchSourceType.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/commandline/ArgumentMatchSourceType.java
new file mode 100644
index 0000000..9dee5be
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/commandline/ArgumentMatchSourceType.java
@@ -0,0 +1,33 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.utils.commandline;
+
+/**
+ * Type of where an argument match originated, via the commandline or a some other provider.
+ */
+public enum ArgumentMatchSourceType {
+    CommandLine, Provider
+}
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/commandline/ArgumentMatchStringValue.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/commandline/ArgumentMatchStringValue.java
new file mode 100644
index 0000000..9f772bc
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/commandline/ArgumentMatchStringValue.java
@@ -0,0 +1,49 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.utils.commandline;
+
+import java.io.File;
+
+/**
+ * Argument values that originated from a string.
+ */
+public class ArgumentMatchStringValue extends ArgumentMatchValue {
+    private final String value;
+
+    public ArgumentMatchStringValue(String value) {
+        this.value = value;
+    }
+
+    @Override
+    public String asString() {
+        return value;
+    }
+
+    @Override
+    public File asFile() {
+        return value == null ? null : new File(value);
+    }
+}
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/commandline/ArgumentMatchValue.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/commandline/ArgumentMatchValue.java
new file mode 100644
index 0000000..f37d538
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/commandline/ArgumentMatchValue.java
@@ -0,0 +1,43 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.utils.commandline;
+
+import java.io.File;
+
+/**
+ * Returns argument values as either strings or values.
+ */
+public abstract class ArgumentMatchValue {
+    /**
+     * @return the value of this argument as a String object.
+     */
+    public abstract String asString();
+
+    /**
+     * @return the value of this argument as a File object.
+     */
+    public abstract File asFile();
+}
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/commandline/ArgumentMatches.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/commandline/ArgumentMatches.java
new file mode 100644
index 0000000..2d81cfc
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/commandline/ArgumentMatches.java
@@ -0,0 +1,211 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.utils.commandline;
+
+import org.broadinstitute.gatk.engine.walkers.Multiplexer;
+
+import java.util.*;
+/**
+ * Represents a list of potential matches between the arguments defined
+ * by the argument sources and the arguments passed in via the command line.
+ */
+public class ArgumentMatches implements Iterable<ArgumentMatch> {
+    /**
+     * Collection matches from argument definition to argument value.
+     * Package protected access is deliberate.
+     */
+    Map<ArgumentMatchSite,ArgumentMatch> argumentMatches = new TreeMap<ArgumentMatchSite,ArgumentMatch>();
+
+    /**
+     * Provide a place to put command-line argument values that don't seem to belong to
+     * any particular command-line option.
+     */
+    ArgumentMatch MissingArgument = new ArgumentMatch();
+
+    /**
+     * Get an iterator cycling through *unique* command-line argument <-> definition matches.
+     * @return Iterator over all argument matches.
+     */
+    public Iterator<ArgumentMatch> iterator() {
+        return getUniqueMatches().iterator();
+    }
+
+    /**
+     * Create an empty ArgumentMatches object.
+     */
+    public ArgumentMatches() {
+    }
+
+    /**
+     * Create a singleton ArgumentMatches object.
+     * @param match Match to incorporate.
+     */
+    public ArgumentMatches( ArgumentMatch match ) {
+        mergeInto( match );
+    }
+
+    /**
+     * Returns the number of matches in this structure.
+     * @return Count of the matches in this structure.
+     */
+    public int size() {
+        return argumentMatches.size();
+    }
+
+    /**
+     * Indicates whether the site contains a matched argument.
+     * @param site Site at which to check.
+     * @return True if the site has a match.  False otherwise.
+     */
+    boolean hasMatch( ArgumentMatchSite site ) {
+        return argumentMatches.containsKey( site );
+    }
+
+    /**
+     * Gets the match at a given site.
+     * @param site Site at which to look for a match.
+     * @return The match present at the given site.
+     * @throws IllegalArgumentException if site does not contain a match.
+     */
+    ArgumentMatch getMatch( ArgumentMatchSite site ) {
+        if( !argumentMatches.containsKey(site) )
+            throw new IllegalArgumentException( "Site does not contain an argument: " + site );
+        return argumentMatches.get(site);
+    }
+
+    /**
+     * Does the match collection have a match for this argument definition.
+     * @param definition Definition to match.
+     * @return True if a match exists; false otherwise.
+     */
+    boolean hasMatch( ArgumentDefinition definition ) {
+        return findMatches( definition ).size() > 0;
+    }
+
+    /**
+     * Return all argument matches of this source.
+     * @param parsingEngine Parsing engine.
+     * @param argumentSource Argument source to match.
+     * @return List of all matches.
+     */
+
+    ArgumentMatches findMatches(ParsingEngine parsingEngine, ArgumentSource argumentSource) {
+        List<ArgumentDefinition> sourceDefinitions = parsingEngine.selectBestTypeDescriptor(argumentSource.field.getType()).createArgumentDefinitions(argumentSource);
+
+        ArgumentMatches matches = new ArgumentMatches();
+        for( ArgumentMatch argumentMatch: getUniqueMatches() ) {
+            if( sourceDefinitions.contains(argumentMatch.definition) )
+                matches.mergeInto( argumentMatch );
+        }
+        return matches;
+    }
+
+    /**
+     * Return all argument matches of this definition.
+     * @param definition Argument definition to match.
+     * @return List of all matches.
+     */
+    ArgumentMatches findMatches( ArgumentDefinition definition ) {
+        ArgumentMatches matches = new ArgumentMatches();
+        for( ArgumentMatch argumentMatch: argumentMatches.values() ) {
+            if( argumentMatch.definition == definition )
+                matches.mergeInto( argumentMatch );
+        }
+        return matches;
+    }
+
+    /**
+     * Find all successful matches (a 'successful' match is one paired with a definition).
+     * @return All successful matches.
+     */
+    ArgumentMatches findSuccessfulMatches() {
+        ArgumentMatches matches = new ArgumentMatches();
+        for( ArgumentMatch argumentMatch: argumentMatches.values() ) {
+            if( argumentMatch.definition != null )
+                matches.mergeInto( argumentMatch );
+        }
+        return matches;
+    }
+
+    /**
+     * Find arguments that are unmatched to any definition.
+     * @return Set of matches that have no associated definition.
+     */
+    ArgumentMatches findUnmatched() {
+        ArgumentMatches matches = new ArgumentMatches();
+        for( ArgumentMatch argumentMatch: argumentMatches.values() ) {
+            if( argumentMatch.definition == null )
+                matches.mergeInto( argumentMatch );
+        }
+        return matches;
+    }
+
+    /**
+     * Reformat the given entries with the given multiplexer and key.
+     * TODO: Generify this.
+     * @param multiplexer Multiplexer that controls the transformation process.
+     * @param key Key which specifies the transform.
+     * @return new argument matches.
+     */
+    ArgumentMatches transform(Multiplexer multiplexer, Object key) {
+        ArgumentMatches newArgumentMatches = new ArgumentMatches();
+        for(ArgumentMatch match: argumentMatches.values())
+            newArgumentMatches.mergeInto(match.transform(multiplexer,key));
+        return newArgumentMatches;
+    }
+
+    /**
+     * Merges the given argument match into the set of existing argument matches.
+     * If multiple arguments are present, those arguments will end up grouped.
+     * @param match The match to merge into.
+     */
+    void mergeInto( ArgumentMatch match ) {
+        boolean definitionExists = false;
+
+        // Clone the list of argument matches to avoid ConcurrentModificationExceptions.
+        for( ArgumentMatch argumentMatch: getUniqueMatches() ) {
+            if( argumentMatch.definition == match.definition && argumentMatch.tags.equals(match.tags) ) {
+                argumentMatch.mergeInto( match );
+                for( ArgumentMatchSite site: match.sites.keySet() )
+                    argumentMatches.put( site, argumentMatch );
+                definitionExists = true;
+            }
+        }
+
+        if( !definitionExists ) {
+            for( ArgumentMatchSite site: match.sites.keySet() )
+                argumentMatches.put( site, match );
+        }
+    }    
+
+    /**
+     * Determines, of the argument matches by position, which are unique and returns that list.
+     * @return A unique set of matches.
+     */
+    private Set<ArgumentMatch> getUniqueMatches() {
+        return new LinkedHashSet<ArgumentMatch>( argumentMatches.values() );
+    }    
+}
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/commandline/ArgumentSource.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/commandline/ArgumentSource.java
new file mode 100644
index 0000000..79e07a6
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/commandline/ArgumentSource.java
@@ -0,0 +1,243 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.utils.commandline;
+
+import org.broadinstitute.gatk.utils.exceptions.ReviewedGATKException;
+
+import java.lang.reflect.Field;
+import java.util.Arrays;
+import java.util.List;
+
+/**
+ * Describes the source field which defines a command-line argument.
+ * A parsed-object version of the command-line argument will be
+ * injected into an object containing this field.
+ *
+ * @author mhanna
+ * @version 0.1
+ */
+public class ArgumentSource {
+    /**
+     * Field into which to inject command-line arguments.
+     */
+    public final Field[] parentFields;
+
+    /**
+     * Field into which to inject command-line arguments.
+     */
+    public final Field field;
+
+    /**
+     * Type descriptor to use when parsing new argument types.
+     */
+    private final ArgumentTypeDescriptor typeDescriptor;
+
+    /**
+     * Create a new command-line argument target.
+     * @param parentFields Parent fields containing the the field.  Field must be annotated with 'ArgumentCollection'.
+     * @param field Field containing the argument.  Field must be annotated with 'Input' or 'Output'.
+     * @param typeDescriptor custom type descriptor to use when parsing.
+     */
+    protected ArgumentSource( Field[] parentFields, Field field, ArgumentTypeDescriptor typeDescriptor) {
+        this.parentFields = parentFields;
+        this.field = field;
+        this.typeDescriptor = typeDescriptor;
+    }
+
+    /**
+     * Somewhat hackish copy constructor to track fields with a custom type descriptor.
+     * TODO: Separate type descriptor from ArgumentSource in general usage.
+     * @param typeDescriptor New type descriptor for the object.
+     */
+    public ArgumentSource copyWithCustomTypeDescriptor(final ArgumentTypeDescriptor typeDescriptor) {
+        return new ArgumentSource(parentFields,field,typeDescriptor);
+    }
+
+    /**
+     * True if this argument source equals other.
+     * @param other Another object, possibly an argument source, to test for equality.  Any object can
+     *              be tested, but only instances of ArgumentSource will result in equals returning true.
+     * @return True if this argument source matches other.  False otherwise.
+     */
+    @Override
+    public boolean equals( Object other ) {
+        if( other == null )
+            return false;
+        if( !(other instanceof ArgumentSource) )
+            return false;
+
+        ArgumentSource otherArgumentSource = (ArgumentSource)other;
+        return this.field == otherArgumentSource.field && Arrays.equals(this.parentFields, otherArgumentSource.parentFields);
+    }
+
+    /**
+     * Returns an appropriate hash code for this argument source.
+     * @return A uniformly distributed hashcode representing this argument source.
+     */
+    @Override
+    public int hashCode() {
+        return field.hashCode();
+    }
+
+    /**
+     * Generate a list of all argument definitions to which this argument source maps.
+     * @return A non-null, non-empty list of argument definitions.
+     */
+    public List<ArgumentDefinition> createArgumentDefinitions() {
+        return typeDescriptor.createArgumentDefinitions( this );
+    }
+
+    /**
+     * Parses the specified value based on the specified type.
+     * @param values String representation of all values passed.
+     * @return the parsed value of the object.
+     */
+    public Object parse( ParsingEngine parsingEngine, ArgumentMatches values ) {
+        return typeDescriptor.parse( parsingEngine, this, values );
+    }
+
+    /**
+     * Returns whether this field is required.  Note that flag fields are always forced to 'not required'.
+     * @return True if the field is mandatory and not a boolean flag.  False otherwise.
+     */
+    public boolean isRequired() {
+        return (Boolean)CommandLineUtils.getValue(ArgumentTypeDescriptor.getArgumentAnnotation(this),"required");
+    }
+
+    /**
+     * Returns true if the argument is a flag (a 0-valued argument).
+     * @return True if argument is a flag; false otherwise.
+     */
+    public boolean isFlag() {
+        return (field.getType() == Boolean.class) || (field.getType() == Boolean.TYPE);
+    }
+
+    /**
+     * Can this argument support multiple values, or just one?
+     * @return True if the argument supports multiple values.
+     */
+    public boolean isMultiValued() {
+        return typeDescriptor.isMultiValued( this );
+    }
+
+    /**
+     * Should the given class be hidden from the command-line argument system.
+     * @return True if so.  False otherwise.
+     */
+    public boolean isHidden() {
+        return field.isAnnotationPresent(Hidden.class) || field.isAnnotationPresent(Deprecated.class);
+    }
+
+    /**
+     * Is the given argument considered an advanced option when displaying on the command-line argument system.
+     * @return True if so.  False otherwise.
+     */
+    public boolean isAdvanced() {
+        return field.isAnnotationPresent(Advanced.class);
+    }
+
+    /**
+     * Is the given argument an output.
+     * @return True if so. False otherwise.
+     */
+    public boolean isOutput() {
+        return field.isAnnotationPresent(Output.class);
+    }
+
+    /**
+     * Is the given argument an input.
+     * @return True if so. False otherwise.
+     */
+    public boolean isInput() {
+        return field.isAnnotationPresent(Input.class);
+    }
+
+    /**
+     * Is this command-line argument dependent on some primitive argument types?
+     * @return True if this command-line argument depends on other arguments; false otherwise.
+     */
+    public boolean isDependent() {
+        return typeDescriptor instanceof MultiplexArgumentTypeDescriptor;
+    }
+
+    /**
+     * Returns whether the field has been deprecated and should no longer be used.
+     * @return True if field has been deprecated.
+     */
+    public boolean isDeprecated() {
+        return field.isAnnotationPresent(Deprecated.class);
+    }
+
+    /**
+     * Returns whether the field should default to stdout if not provided explicitly on the command-line.
+     * @return True if field should default to stdout.
+     */
+    public boolean defaultsToStdout() {
+        return field.isAnnotationPresent(Output.class) && (Boolean)CommandLineUtils.getValue(ArgumentTypeDescriptor.getArgumentAnnotation(this),"defaultToStdout");
+    }
+
+    /**
+     * Returns false if a type-specific default can be employed.
+     * @return True to throw in a type specific default.  False otherwise.
+     */
+    public boolean createsTypeDefault() {
+        return typeDescriptor.createsTypeDefault(this);
+    }
+
+    public String typeDefaultDocString() {
+        return typeDescriptor.typeDefaultDocString(this);
+    }
+
+    /**
+     * Generates a default for the given type.
+     * @param parsingEngine the parsing engine used to validate this argument type descriptor.
+     * @return A default value for the given type.
+     */
+    public Object createTypeDefault(ParsingEngine parsingEngine) {
+        return typeDescriptor.createTypeDefault(parsingEngine,this,field.getGenericType());
+    }
+
+    /**
+     * Builds out a new type descriptor for the given dependent argument as a function
+     * of the containing object.
+     * @param parsingEngine the parsing engine to use when building out this custom type descriptor.
+     * @param containingObject The containing object.
+     * @return An argument type descriptor for the custom derivative field.
+     */
+    public MultiplexArgumentTypeDescriptor createDependentTypeDescriptor(ParsingEngine parsingEngine,Object containingObject) {
+        if(!isDependent())
+            throw new ReviewedGATKException("Field " + field.getName() + " is independent; no dependent type descriptor can be derived.");
+        return ((MultiplexArgumentTypeDescriptor)typeDescriptor).createCustomTypeDescriptor(parsingEngine,this,containingObject);
+    }
+
+    /**
+     * Gets a string representation of the argument source for debugging.
+     * @return String representation of the argument source.
+     */
+    public String toString() {
+        return field.getDeclaringClass().getSimpleName() + ": " + field.getName();
+    }
+}
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/commandline/ArgumentTypeDescriptor.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/commandline/ArgumentTypeDescriptor.java
new file mode 100644
index 0000000..5bfc516
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/commandline/ArgumentTypeDescriptor.java
@@ -0,0 +1,1030 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.utils.commandline;
+
+import org.apache.log4j.Logger;
+import htsjdk.tribble.Feature;
+import org.broadinstitute.gatk.engine.refdata.tracks.FeatureManager;
+import org.broadinstitute.gatk.engine.walkers.Multiplex;
+import org.broadinstitute.gatk.engine.walkers.Multiplexer;
+import org.broadinstitute.gatk.utils.classloader.JVMUtils;
+import org.broadinstitute.gatk.utils.exceptions.DynamicClassResolutionException;
+import org.broadinstitute.gatk.utils.exceptions.ReviewedGATKException;
+import org.broadinstitute.gatk.utils.exceptions.UserException;
+import org.broadinstitute.gatk.utils.text.XReadLines;
+
+import java.io.File;
+import java.io.IOException;
+import java.lang.annotation.Annotation;
+import java.lang.reflect.*;
+import java.util.*;
+
+/**
+ * An descriptor capable of providing parsers that can parse any type
+ * of supported command-line argument.
+ *
+ * @author mhanna
+ * @version 0.1
+ */
+public abstract class ArgumentTypeDescriptor {
+    private static Class[] ARGUMENT_ANNOTATIONS = {Input.class, Output.class, Argument.class};
+
+    /**
+     * our log, which we want to capture anything from org.broadinstitute.gatk
+     */
+    protected static final Logger logger = Logger.getLogger(ArgumentTypeDescriptor.class);
+
+    /**
+     * Fetch the given descriptor from the descriptor repository.
+     * @param descriptors the descriptors from which to select a good match.
+     * @param type Class for which to specify a descriptor.
+     * @return descriptor for the given type.
+     */
+    public static ArgumentTypeDescriptor selectBest( Collection<ArgumentTypeDescriptor> descriptors, Class type ) {
+        for( ArgumentTypeDescriptor descriptor: descriptors ) {
+            if( descriptor.supports(type) )
+                return descriptor;
+        }
+        throw new ReviewedGATKException("Can't process command-line arguments of type: " + type.getName());
+    }
+
+    /**
+     * Does this descriptor support classes of the given type?
+     * @param type The type to check.
+     * @return true if this descriptor supports the given type, false otherwise.
+     */
+    public abstract boolean supports( Class type );
+
+    /**
+     * Returns false if a type-specific default can be employed.
+     * @param source Source of the command-line argument.
+     * @return True to throw in a type specific default.  False otherwise.
+     */
+    public boolean createsTypeDefault(ArgumentSource source) { return false; }
+
+    /**
+     * Returns a documentation-friendly value for the default of a type descriptor.
+     * Must be overridden if createsTypeDefault return true.  cannot be called otherwise
+     * @param source Source of the command-line argument.
+     * @return Friendly string of the default value, for documentation.  If doesn't create a default, throws
+     * and UnsupportedOperationException
+     */
+    public String typeDefaultDocString(ArgumentSource source) {
+        throw new UnsupportedOperationException();
+    }
+
+    /**
+     * Generates a default for the given type.
+     *
+     * @param parsingEngine the parsing engine used to validate this argument type descriptor.
+     * @param source Source of the command-line argument.
+     * @param type Type of value to create, in case the command-line argument system wants influence.
+     * @return A default value for the given type.
+     */
+    public Object createTypeDefault(ParsingEngine parsingEngine,ArgumentSource source, Type type) { throw new UnsupportedOperationException("Unable to create default for type " + getClass()); }
+
+    /**
+     * Given the given argument source and attributes, synthesize argument definitions for command-line arguments.
+     * @param source Source class and field for the given argument.
+     * @return A list of command-line argument definitions supporting this field.
+     */
+    public List<ArgumentDefinition> createArgumentDefinitions( ArgumentSource source ) {
+        return Collections.singletonList(createDefaultArgumentDefinition(source));
+    }
+
+    /**
+     * Parses an argument source to an object.
+     * WARNING!  Mandatory side effect of parsing!  Each parse routine should register the tags it finds with the proper CommandLineProgram.
+     * TODO: Fix this, perhaps with an event model indicating that a new argument has been created.
+     *
+     * @param parsingEngine The engine responsible for parsing.
+     * @param source The source used to find the matches.
+     * @param matches The matches for the source.
+     * @return The parsed object.
+     */
+    public Object parse(ParsingEngine parsingEngine, ArgumentSource source, ArgumentMatches matches) {
+        return parse(parsingEngine, source, source.field.getGenericType(), matches);
+    }
+
+    /**
+     * Returns true if the field is a collection or an array.
+     * @param source The argument source to check.
+     * @return true if the field is a collection or an array.
+     */
+    public boolean isMultiValued( ArgumentSource source ) {
+        Class argumentType = source.field.getType();
+        return Collection.class.isAssignableFrom(argumentType) || argumentType.isArray();
+    }
+
+    /**
+     * By default, argument sources create argument definitions with a set of default values.
+     * Use this method to create the one simple argument definition.
+     * @param source argument source for which to create a default definition.
+     * @return The default definition for this argument source.
+     */
+    protected ArgumentDefinition createDefaultArgumentDefinition( ArgumentSource source ) {
+        Annotation argumentAnnotation = getArgumentAnnotation(source);
+        return new ArgumentDefinition( ArgumentIOType.getIOType(argumentAnnotation),
+                source.field.getType(),
+                ArgumentDefinition.getFullName(argumentAnnotation, source.field.getName()),
+                ArgumentDefinition.getShortName(argumentAnnotation),
+                ArgumentDefinition.getDoc(argumentAnnotation),
+                source.isRequired() && !createsTypeDefault(source) && !source.isFlag() && !source.isDeprecated(),
+                source.isFlag(),
+                source.isMultiValued(),
+                source.isHidden(),
+                makeRawTypeIfNecessary(getCollectionComponentType(source.field)),
+                ArgumentDefinition.getExclusiveOf(argumentAnnotation),
+                ArgumentDefinition.getValidationRegex(argumentAnnotation),
+                getValidOptions(source) );
+    }
+
+    /**
+     * Return the component type of a field, or String.class if the type cannot be found.
+     * @param field The reflected field to inspect.
+     * @return The parameterized component type, or String.class if the parameterized type could not be found.
+     * @throws IllegalArgumentException If more than one parameterized type is found on the field.
+     */
+    protected Type getCollectionComponentType( Field field ) {
+        return null;
+    }
+
+    /**
+     * Parses the argument matches for a class type into an object.
+     * @param source The original argument source used to find the matches.
+     * @param type The current class type being inspected.  May not match the argument source.field.getType() if this as a collection for example.
+     * @param matches The argument matches for the argument source, or the individual argument match for a scalar if this is being called to help parse a collection.
+     * @return The individual parsed object matching the argument match with Class type.
+     */
+    public abstract Object parse( ParsingEngine parsingEngine, ArgumentSource source, Type type, ArgumentMatches matches );
+
+    /**
+     * If the argument source only accepts a small set of options, populate the returned list with
+     * those options.  Otherwise, leave the list empty.
+     * @param source Original field specifying command-line arguments.
+     * @return A list of valid options.
+     */
+    protected List<String> getValidOptions( ArgumentSource source ) {
+        if(!source.field.getType().isEnum())
+            return null;
+        List<String> validOptions = new ArrayList<String>();
+        for(Object constant: source.field.getType().getEnumConstants())
+            validOptions.add(constant.toString());
+        return validOptions;
+    }
+
+    /**
+     * Returns true if the argument with the given full name exists in the collection of ArgumentMatches.
+     * @param definition Definition of the argument for which to find matches.
+     * @param matches The matches for the given argument.
+     * @return true if the argument is present, or false if not present.
+     */
+    protected boolean argumentIsPresent( ArgumentDefinition definition, ArgumentMatches matches ) {
+        for( ArgumentMatch match: matches ) {
+            if( match.definition.equals(definition) )
+                return true;
+        }
+        return false;
+    }
+
+    /**
+     * Gets the value of an argument with the given full name, from the collection of ArgumentMatches.
+     * If the argument matches multiple values, an exception will be thrown.
+     * @param definition Definition of the argument for which to find matches.
+     * @param matches The matches for the given argument.
+     * @return The value of the argument if available, or null if not present.
+     */
+    protected ArgumentMatchValue getArgumentValue( ArgumentDefinition definition, ArgumentMatches matches ) {
+        Collection<ArgumentMatchValue> argumentValues = getArgumentValues( definition, matches );
+        if( argumentValues.size() > 1 )
+            throw new UserException.CommandLineException("Multiple values associated with given definition, but this argument expects only one: " + definition.fullName);
+        return argumentValues.size() > 0 ? argumentValues.iterator().next() : null;
+    }
+
+    /**
+     * Gets the tags associated with a given command-line argument.
+     * If the argument matches multiple values, an exception will be thrown.
+     * @param matches The matches for the given argument.
+     * @return The value of the argument if available, or null if not present.
+     */
+    protected Tags getArgumentTags(ArgumentMatches matches) {
+        Tags tags = new Tags();
+        for(ArgumentMatch match: matches) {
+            if(!tags.isEmpty() && !match.tags.isEmpty())
+                throw new ReviewedGATKException("BUG: multiple conflicting sets of tags are available, and the type descriptor specifies no way of resolving the conflict.");
+            tags = match.tags;
+        }
+        return tags;
+    }
+
+    /**
+     * Gets the values of an argument with the given full name, from the collection of ArgumentMatches.
+     * @param definition Definition of the argument for which to find matches.
+     * @param matches The matches for the given argument.
+     * @return The value of the argument if available, or an empty collection if not present.
+     */
+    protected Collection<ArgumentMatchValue> getArgumentValues( ArgumentDefinition definition, ArgumentMatches matches ) {
+        Collection<ArgumentMatchValue> values = new ArrayList<ArgumentMatchValue>();
+        for( ArgumentMatch match: matches ) {
+            if( match.definition.equals(definition) )
+                values.addAll(match.values());
+        }
+        return values;
+    }
+
+    /**
+     * Retrieves the argument description from the given argument source.  Will throw an exception if
+     * the given ArgumentSource
+     * @param source source of the argument.
+     * @return Argument description annotation associated with the given field.
+     */
+    @SuppressWarnings("unchecked")
+    protected static Annotation getArgumentAnnotation( ArgumentSource source ) {
+        for (Class annotation: ARGUMENT_ANNOTATIONS)
+            if (source.field.isAnnotationPresent(annotation))
+                return source.field.getAnnotation(annotation);
+        throw new ReviewedGATKException("ArgumentAnnotation is not present for the argument field: " + source.field.getName());
+    }
+
+    /**
+     * Returns true if an argument annotation is present
+     * @param field The field to check for an annotation.
+     * @return True if an argument annotation is present on the field.
+     */
+    @SuppressWarnings("unchecked")
+    public static boolean isArgumentAnnotationPresent(Field field) {
+        for (Class annotation: ARGUMENT_ANNOTATIONS)
+            if (field.isAnnotationPresent(annotation))
+                return true;
+        return false;
+    }
+
+    /**
+     * Returns true if the given annotation is hidden from the help system.
+     * @param field Field to test.
+     * @return True if argument should be hidden.  False otherwise.
+     */
+    public static boolean isArgumentHidden(Field field) {
+        return field.isAnnotationPresent(Hidden.class);
+    }
+
+    public static Class makeRawTypeIfNecessary(Type t) {
+        if ( t == null )
+            return null;
+        else if ( t instanceof ParameterizedType )
+            return (Class)((ParameterizedType) t).getRawType();
+        else if ( t instanceof Class ) {
+            return (Class)t;
+        } else {
+            throw new IllegalArgumentException("Unable to determine Class-derived component type of field: " + t);
+        }
+    }
+
+    /**
+     * The actual argument parsing method.
+     * @param source             source
+     * @param type               type to check
+     * @param matches            matches
+     * @param tags               argument tags
+     * @return the RodBinding/IntervalBinding object depending on the value of createIntervalBinding.
+     */
+    protected Object parseBinding(ArgumentSource source, Type type, ArgumentMatches matches, Tags tags) {
+        ArgumentDefinition defaultDefinition = createDefaultArgumentDefinition(source);
+        ArgumentMatchValue value = getArgumentValue(defaultDefinition, matches);
+        @SuppressWarnings("unchecked")
+        Class<? extends Feature> parameterType = JVMUtils.getParameterizedTypeClass(type);
+        String name = defaultDefinition.fullName;
+
+        return parseBinding(value, parameterType, type, name, tags, source.field.getName());
+    }
+
+    /**
+     *
+     * @param value The source of the binding
+     * @param parameterType The Tribble Feature parameter type
+     * @param bindingClass The class type for the binding (ex: RodBinding, IntervalBinding, etc.) Must have the correct constructor for creating the binding.
+     * @param bindingName The name of the binding passed to the constructor.
+     * @param tags Tags for the binding used for parsing and passed to the constructor.
+     * @param fieldName The name of the field that was parsed. Used for error reporting.
+     * @return The newly created binding object of type bindingClass.
+     */
+    public static Object parseBinding(ArgumentMatchValue value, Class<? extends Feature> parameterType, Type bindingClass,
+                                      String bindingName, Tags tags, String fieldName) {
+        try {
+            String tribbleType = null;
+            // must have one or two tag values here
+            if ( tags.getPositionalTags().size() > 2 ) {
+                throw new UserException.CommandLineException(
+                        String.format("Unexpected number of positional tags for argument %s : %s. " +
+                                "Rod bindings only support -X:type and -X:name,type argument styles",
+                                value.asString(), fieldName));
+            } else if ( tags.getPositionalTags().size() == 2 ) {
+                // -X:name,type style
+                bindingName = tags.getPositionalTags().get(0);
+                tribbleType = tags.getPositionalTags().get(1);
+
+                FeatureManager manager = new FeatureManager();
+                if ( manager.getByName(tribbleType) == null )
+                    throw new UserException.UnknownTribbleType(
+                            tribbleType,
+                            String.format("Unable to find tribble type '%s' provided on the command line. " +
+                                    "Please select a correct type from among the supported types:%n%s",
+                                    tribbleType, manager.userFriendlyListOfAvailableFeatures(parameterType)));
+
+            } else {
+                // case with 0 or 1 positional tags
+                FeatureManager manager = new FeatureManager();
+
+                // -X:type style is a type when we cannot determine the type dynamically
+                String tag1 = tags.getPositionalTags().size() == 1 ? tags.getPositionalTags().get(0) : null;
+                if ( tag1 != null ) {
+                    if ( manager.getByName(tag1) != null ) // this a type
+                        tribbleType = tag1;
+                    else
+                        bindingName = tag1;
+                }
+
+                if ( tribbleType == null ) {
+                    // try to determine the file type dynamically
+                    File file = value.asFile();
+                    if ( file.canRead() && file.isFile() ) {
+                        FeatureManager.FeatureDescriptor featureDescriptor = manager.getByFiletype(file);
+                        if ( featureDescriptor != null ) {
+                            tribbleType = featureDescriptor.getName();
+                            logger.debug("Dynamically determined type of " + file + " to be " + tribbleType);
+                        }
+                    }
+
+                    if ( tribbleType == null ) {
+                        // IntervalBinding can be created from a normal String
+                        Class rawType = (makeRawTypeIfNecessary(bindingClass));
+                        try {
+                            return rawType.getConstructor(String.class).newInstance(value.asString());
+                        } catch (NoSuchMethodException e) {
+                            /* ignore */
+                        }
+
+                        if ( ! file.exists() ) {
+                            throw new UserException.CouldNotReadInputFile(file, "file does not exist");
+                        } else if ( ! file.canRead() || ! file.isFile() ) {
+                            throw new UserException.CouldNotReadInputFile(file, "file could not be read");
+                        } else {
+                            throw new UserException.CommandLineException(
+                                    String.format("No tribble type was provided on the command line and the type of the file could not be determined dynamically. " +
+                                            "Please add an explicit type tag :NAME listing the correct type from among the supported types:%n%s",
+                                            manager.userFriendlyListOfAvailableFeatures(parameterType)));
+                        }
+                    }
+                }
+            }
+
+            Constructor ctor = (makeRawTypeIfNecessary(bindingClass)).getConstructor(Class.class, String.class, String.class, String.class, Tags.class);
+            return ctor.newInstance(parameterType, bindingName, value.asString(), tribbleType, tags);
+        } catch (Exception e) {
+            if ( e instanceof UserException )
+                throw ((UserException)e);
+            else
+                throw new UserException.CommandLineException(
+                        String.format("Failed to parse value %s for argument %s. Message: %s",
+                                value, fieldName, e.getMessage()));
+        }
+    }
+
+    /**
+     * Parse the source of a RodBindingCollection, which can be either a file of RodBindings or an actual RodBinding.
+     *
+     * @param parsingEngine the parsing engine used to validate this argument type descriptor
+     * @param source             source
+     * @param type               type
+     * @param matches            matches
+     * @param tags               argument tags
+     * @return the newly created binding object
+     */
+    public Object parseRodBindingCollectionSource(final ParsingEngine parsingEngine,
+                                                  final ArgumentSource source,
+                                                  final Type type,
+                                                  final ArgumentMatches matches,
+                                                  final Tags tags) {
+
+        final ArgumentDefinition defaultDefinition = createDefaultArgumentDefinition(source);
+        final ArgumentMatchValue value = getArgumentValue(defaultDefinition, matches);
+        @SuppressWarnings("unchecked")
+        Class<? extends Feature> parameterType = JVMUtils.getParameterizedTypeClass(type);
+        String name = defaultDefinition.fullName;
+
+        // if this a list of files, get those bindings
+        final File file = value.asFile();
+        try {
+            if (file.getAbsolutePath().endsWith(".list")) {
+                return getRodBindingsCollection(file, parsingEngine, parameterType, name, tags, source.field.getName());
+            }
+        } catch (IOException e) {
+            throw new UserException.CouldNotReadInputFile(file, e);
+        }
+
+        // otherwise, treat this as an individual binding
+        final RodBinding binding = (RodBinding)parseBinding(value, parameterType, RodBinding.class, name, tags, source.field.getName());
+        parsingEngine.addTags(binding, tags);
+        parsingEngine.addRodBinding(binding);
+        return RodBindingCollection.createRodBindingCollectionOfType(parameterType, Arrays.asList(binding));
+    }
+
+    /**
+     * Retrieve and parse a collection of RodBindings from the given file.
+     *
+     * If the file contains duplicate entries or is empty, an exception will be thrown.
+     *
+     * @param file             the source file
+     * @param parsingEngine    the engine responsible for parsing
+     * @param parameterType    the Tribble Feature parameter type
+     * @param bindingName      the name of the binding passed to the constructor.
+     * @param defaultTags      general tags for the binding used for parsing and passed to the constructor.
+     * @param fieldName        the name of the field that was parsed. Used for error reporting.
+     * @return the newly created collection of binding objects.
+     */
+    public static Object getRodBindingsCollection(final File file,
+                                                  final ParsingEngine parsingEngine,
+                                                  final Class<? extends Feature> parameterType,
+                                                  final String bindingName,
+                                                  final Tags defaultTags,
+                                                  final String fieldName) throws IOException {
+        final List<RodBinding> bindings = new ArrayList<>();
+
+        // Keep track of the files in this list so that we can check for duplicates and empty files
+        final Set<String> fileValues = new HashSet<>();
+
+        // parse each line separately using the given Tags if none are provided on each line
+        for ( final String line: new XReadLines(file) ) {
+            final String[] tokens = line.split("\\s+");
+            final RodBinding binding;
+
+            if ( tokens.length == 0 ) {
+                continue; // empty line, so do nothing
+            }
+            // use the default tags if none are provided for this binding
+            else if ( tokens.length == 1 ) {
+                final ArgumentMatchValue value = parseAndValidateArgumentMatchValue(tokens[0], fileValues, fieldName, file.getName());
+                binding = (RodBinding)parseBinding(value, parameterType, RodBinding.class, bindingName, defaultTags, fieldName);
+                parsingEngine.addTags(binding, defaultTags);
+
+            }
+            // use the new tags if provided
+            else if ( tokens.length == 2 ) {
+                final Tags tags = ParsingMethod.parseTags(fieldName, tokens[0]);
+                final ArgumentMatchValue value = parseAndValidateArgumentMatchValue(tokens[1], fileValues, fieldName, file.getName());
+                binding = (RodBinding)parseBinding(value, parameterType, RodBinding.class, bindingName, tags, fieldName);
+                parsingEngine.addTags(binding, tags);
+            } else {
+                throw new UserException.BadArgumentValue(fieldName, "data lines should consist of an optional set of tags along with a path to a file; too many tokens are present for line: " + line);
+            }
+
+            bindings.add(binding);
+            parsingEngine.addRodBinding(binding);
+        }
+
+        if (fileValues.isEmpty()) {
+            throw new UserException.BadArgumentValue(fieldName, "The input list " + file.getName() + " is empty.");
+        }
+
+        return RodBindingCollection.createRodBindingCollectionOfType(parameterType, bindings);
+    }
+
+    /**
+     * Validates the resource file name and constructs an ArgumentMatchValue from it.
+     *
+     * If the list name has already been processed in the current list, throws a UserException, otherwise
+     * creates an ArgumentMatchValue to represent the list.
+     *
+     * @param token Name of the ROD resource file.
+     * @param fileValues Set of names of ROD files that have already been processed.
+     * @param fieldName Name of the argument field being populated.
+     * @param listFileName Name of the list file being processed.
+     * @return
+     */
+    private static ArgumentMatchValue parseAndValidateArgumentMatchValue(final String token, final Set<String> fileValues, final String fieldName,
+                                                                         final String listFileName) {
+        checkForDuplicateFileName(token, fileValues, fieldName, listFileName);
+        return new ArgumentMatchStringValue(token);
+    }
+
+    /**
+     * Checks to make sure that the current file name to be processed has not already been processed.
+     *
+     * Checks the name of the current file against the names that have already been processed, throwing
+     * an informative BadArgumentValue exception if it has already been seen. As a side effect adds the
+     * current file name to the set of filenames that have already been processed.
+     *
+     * @param currentFile Name of the current file to process
+     * @param processedFiles Set of file names that have already been processed
+     * @param fieldName Name of the argument that is being populated
+     * @param listName Filename of the list that is being processed
+     */
+    protected static void checkForDuplicateFileName(final String currentFile, final Set<String> processedFiles,
+                                                    final String fieldName, final String listName) {
+        if (processedFiles.contains(currentFile)) {
+            throw new UserException.BadArgumentValue(fieldName, "The input list " + listName + " contains file " + currentFile +
+                                                     " multiple times, which isn't allowed. If you are intentionally trying to " +
+                                                     "include the same file more than once, you will need to specify it in separate file lists.");
+        }
+        processedFiles.add(currentFile);
+    }
+}
+
+/**
+ * Parser for RodBinding objects
+ */
+class RodBindingArgumentTypeDescriptor extends ArgumentTypeDescriptor {
+    /**
+     * We only want RodBinding class objects
+     * @param type The type to check.
+     * @return true if the provided class is a RodBinding.class
+     */
+    @Override
+    public boolean supports( Class type ) {
+        return isRodBinding(type);
+    }
+
+    public static boolean isRodBinding( Class type ) {
+        return RodBinding.class.isAssignableFrom(type);
+    }
+
+    @Override
+    public boolean createsTypeDefault(ArgumentSource source) { return ! source.isRequired(); }
+
+    @Override
+    @SuppressWarnings("unchecked")
+    public Object createTypeDefault(ParsingEngine parsingEngine, ArgumentSource source, Type type) {
+        Class parameterType = JVMUtils.getParameterizedTypeClass(type);
+        return RodBinding.makeUnbound((Class<? extends Feature>)parameterType);
+    }
+
+    @Override
+    public String typeDefaultDocString(ArgumentSource source) {
+        return "none";
+    }
+
+    @Override
+    public Object parse(ParsingEngine parsingEngine, ArgumentSource source, Type type, ArgumentMatches matches) {
+        Tags tags = getArgumentTags(matches);
+        RodBinding rbind = (RodBinding)parseBinding(source, type, matches, tags);
+        parsingEngine.addTags(rbind, tags);
+        parsingEngine.addRodBinding(rbind);
+        return rbind;
+    }
+}
+
+/**
+ * Parser for IntervalBinding objects
+ */
+class IntervalBindingArgumentTypeDescriptor extends ArgumentTypeDescriptor {
+    /**
+     * We only want IntervalBinding class objects
+     * @param type The type to check.
+     * @return true if the provided class is an IntervalBinding.class
+     */
+    @Override
+    public boolean supports( Class type ) {
+        return isIntervalBinding(type);
+    }
+
+    public static boolean isIntervalBinding( Class type ) {
+        return IntervalBinding.class.isAssignableFrom(type);
+    }
+
+    /**
+     * See note from RodBindingArgumentTypeDescriptor.parse().
+     *
+     * @param parsingEngine      parsing engine
+     * @param source             source
+     * @param type               type to check
+     * @param matches            matches
+     * @return the IntervalBinding object.
+     */
+    @Override
+    public Object parse(ParsingEngine parsingEngine, ArgumentSource source, Type type, ArgumentMatches matches) {
+        return parseBinding(source, type, matches, getArgumentTags(matches));
+    }
+}
+
+/**
+ * Parser for RodBindingCollection objects
+ */
+class RodBindingCollectionArgumentTypeDescriptor extends ArgumentTypeDescriptor {
+    /**
+     * We only want RodBindingCollection class objects
+     * @param type The type to check.
+     * @return true if the provided class is an RodBindingCollection.class
+     */
+    @Override
+    public boolean supports( final Class type ) {
+        return isRodBindingCollection(type);
+    }
+
+    public static boolean isRodBindingCollection( final Class type ) {
+        return RodBindingCollection.class.isAssignableFrom(type);
+    }
+
+    /**
+     * See note from RodBindingArgumentTypeDescriptor.parse().
+     *
+     * @param parsingEngine      parsing engine
+     * @param source             source
+     * @param type               type to check
+     * @param matches            matches
+     * @return the IntervalBinding object.
+     */
+    @Override
+    public Object parse(final ParsingEngine parsingEngine, final ArgumentSource source, final Type type, final ArgumentMatches matches) {
+        final Tags tags = getArgumentTags(matches);
+        return parseRodBindingCollectionSource(parsingEngine, source, type, matches, tags);
+    }
+}
+
+/**
+ * Parse simple argument types: java primitives, wrapper classes, and anything that has
+ * a simple String constructor.
+ */
+class SimpleArgumentTypeDescriptor extends ArgumentTypeDescriptor {
+
+    /**
+     * @param type  the class type
+     * @return true if this class is a binding type, false otherwise
+     */
+    private boolean isBinding(final Class type) {
+        return RodBindingArgumentTypeDescriptor.isRodBinding(type) ||
+                IntervalBindingArgumentTypeDescriptor.isIntervalBinding(type) ||
+                RodBindingCollectionArgumentTypeDescriptor.isRodBindingCollection(type);
+    }
+
+
+    @Override
+    public boolean supports( Class type ) {
+        if ( isBinding(type) ) return false;
+        if ( type.isPrimitive() ) return true;
+        if ( type.isEnum() ) return true;
+        if ( primitiveToWrapperMap.containsValue(type) ) return true;
+
+        try {
+            type.getConstructor(String.class);
+            return true;
+        }
+        catch( Exception ex ) {
+            // An exception thrown above means that the String constructor either doesn't
+            // exist or can't be accessed.  In either case, this descriptor doesn't support this type.
+            return false;
+        }
+    }
+
+    @Override
+    public Object parse(ParsingEngine parsingEngine, ArgumentSource source, Type fulltype, ArgumentMatches matches) {
+        Class type = makeRawTypeIfNecessary(fulltype);
+        if (source.isFlag())
+            return true;
+
+        ArgumentDefinition defaultDefinition = createDefaultArgumentDefinition(source);
+        ArgumentMatchValue value = getArgumentValue(defaultDefinition, matches);
+        Object result;
+        Tags tags = getArgumentTags(matches);
+
+        // lets go through the types we support
+        try {
+            if (type.isPrimitive()) {
+                Method valueOf = primitiveToWrapperMap.get(type).getMethod("valueOf",String.class);
+                if(value == null)
+                    throw new MissingArgumentValueException(createDefaultArgumentDefinition(source));
+                result = valueOf.invoke(null,value.asString().trim());
+            } else if (type.isEnum()) {
+                Object[] vals = type.getEnumConstants();
+                Object defaultEnumeration = null;  // as we look at options, record the default option if it exists
+                for (Object val : vals) {
+                    if (String.valueOf(val).equalsIgnoreCase(value == null ? null : value.asString())) return val;
+                    try { if (type.getField(val.toString()).isAnnotationPresent(EnumerationArgumentDefault.class)) defaultEnumeration = val; }
+                    catch (NoSuchFieldException e) { throw new ReviewedGATKException("parsing " + type.toString() + "doesn't contain the field " + val.toString()); }
+                }
+                // if their argument has no value (null), and there's a default, return that default for the enum value
+                if (defaultEnumeration != null && value == null)
+                    result = defaultEnumeration;
+                    // if their argument has no value and there's no default, throw a missing argument value exception.
+                    // TODO: Clean this up so that null values never make it to this point.  To fix this, we'll have to clean up the implementation of -U.
+                else if (value == null)
+                    throw new MissingArgumentValueException(createDefaultArgumentDefinition(source));
+                else
+                    throw new UnknownEnumeratedValueException(createDefaultArgumentDefinition(source),value.asString());
+            } else if (type.equals(File.class)) {
+                result = value == null ? null : value.asFile();
+            } else {
+                if (value == null)
+                    throw new MissingArgumentValueException(createDefaultArgumentDefinition(source));
+                Constructor ctor = type.getConstructor(String.class);
+                result = ctor.newInstance(value.asString());
+            }
+        } catch (UserException e) {
+            throw e;
+        } catch (InvocationTargetException e) {
+            throw new UserException.CommandLineException(String.format("Failed to parse value %s for argument %s.  This is most commonly caused by providing an incorrect data type (e.g. a double when an int is required)",
+                    value, source.field.getName()));
+        } catch (Exception e) {
+            throw new DynamicClassResolutionException(String.class, e);
+        }
+
+        // TODO FIXME!
+
+        // WARNING: Side effect!
+        parsingEngine.addTags(result,tags);
+
+        return result;
+    }
+
+
+    /**
+     * A mapping of the primitive types to their associated wrapper classes.  Is there really no way to infer
+     * this association available in the JRE?
+     */
+    private static Map<Class,Class> primitiveToWrapperMap = new HashMap<Class,Class>() {
+        {
+            put( Boolean.TYPE, Boolean.class );
+            put( Character.TYPE, Character.class );
+            put( Byte.TYPE, Byte.class );
+            put( Short.TYPE, Short.class );
+            put( Integer.TYPE, Integer.class );
+            put( Long.TYPE, Long.class );
+            put( Float.TYPE, Float.class );
+            put( Double.TYPE, Double.class );
+        }
+    };
+}
+
+/**
+ * Process compound argument types: arrays, and typed and untyped collections.
+ */
+class CompoundArgumentTypeDescriptor extends ArgumentTypeDescriptor {
+    @Override
+    public boolean supports( Class type ) {
+        return ( Collection.class.isAssignableFrom(type) || type.isArray() );
+    }
+
+    @Override
+    @SuppressWarnings("unchecked")
+    public Object parse(ParsingEngine parsingEngine,ArgumentSource source, Type fulltype, ArgumentMatches matches) {
+        Class type = makeRawTypeIfNecessary(fulltype);
+        Type componentType;
+        Object result;
+
+        if( Collection.class.isAssignableFrom(type) ) {
+
+            // If this is a generic interface, pick a concrete implementation to create and pass back.
+            // Because of type erasure, don't worry about creating one of exactly the correct type.
+            if( Modifier.isInterface(type.getModifiers()) || Modifier.isAbstract(type.getModifiers()) )
+            {
+                if( java.util.List.class.isAssignableFrom(type) ) type = ArrayList.class;
+                else if( java.util.Queue.class.isAssignableFrom(type) ) type = java.util.ArrayDeque.class;
+                else if( java.util.Set.class.isAssignableFrom(type) ) type = java.util.TreeSet.class;
+            }
+
+            componentType = getCollectionComponentType( source.field );
+            ArgumentTypeDescriptor componentArgumentParser = parsingEngine.selectBestTypeDescriptor(makeRawTypeIfNecessary(componentType));
+
+            Collection collection;
+            try {
+                collection = (Collection)type.newInstance();
+            }
+            catch (InstantiationException e) {
+                logger.fatal("ArgumentParser: InstantiationException: cannot convert field " + source.field.getName());
+                throw new ReviewedGATKException("constructFromString:InstantiationException: Failed conversion " + e.getMessage());
+            }
+            catch (IllegalAccessException e) {
+                logger.fatal("ArgumentParser: IllegalAccessException: cannot convert field " + source.field.getName());
+                throw new ReviewedGATKException("constructFromString:IllegalAccessException: Failed conversion " + e.getMessage());
+            }
+
+            for( ArgumentMatch match: matches ) {
+                for( ArgumentMatch value: match ) {
+                    Object object = componentArgumentParser.parse(parsingEngine,source,componentType,new ArgumentMatches(value));
+                    collection.add( object );
+                    // WARNING: Side effect!
+                    parsingEngine.addTags(object,value.tags);
+                }
+            }
+
+            result = collection;
+
+        }
+        else if( type.isArray() ) {
+            componentType = type.getComponentType();
+            ArgumentTypeDescriptor componentArgumentParser = parsingEngine.selectBestTypeDescriptor(makeRawTypeIfNecessary(componentType));
+
+            // Assemble a collection of individual values used in this computation.
+            Collection<ArgumentMatch> values = new ArrayList<ArgumentMatch>();
+            for( ArgumentMatch match: matches )
+                for( ArgumentMatch value: match )
+                    values.add(value);
+
+            result = Array.newInstance(makeRawTypeIfNecessary(componentType),values.size());
+
+            int i = 0;
+            for( ArgumentMatch value: values ) {
+                Object object = componentArgumentParser.parse(parsingEngine,source,componentType,new ArgumentMatches(value));
+                Array.set(result,i++,object);
+                // WARNING: Side effect!
+                parsingEngine.addTags(object,value.tags);
+            }
+        }
+        else
+            throw new ReviewedGATKException("Unsupported compound argument type: " + type);
+
+        return result;
+    }
+
+    /**
+     * Return the component type of a field, or String.class if the type cannot be found.
+     * @param field The reflected field to inspect.
+     * @return The parameterized component type, or String.class if the parameterized type could not be found.
+     * @throws IllegalArgumentException If more than one parameterized type is found on the field.
+     */
+    @Override
+    protected Type getCollectionComponentType( Field field ) {
+        // If this is a parameterized collection, find the contained type.  If blow up if more than one type exists.
+        if( field.getGenericType() instanceof ParameterizedType) {
+            ParameterizedType parameterizedType = (ParameterizedType)field.getGenericType();
+            if( parameterizedType.getActualTypeArguments().length > 1 )
+                throw new IllegalArgumentException("Unable to determine collection type of field: " + field.toString());
+            return parameterizedType.getActualTypeArguments()[0];
+        }
+        else
+            return String.class;
+    }
+}
+
+class MultiplexArgumentTypeDescriptor extends ArgumentTypeDescriptor {
+    /**
+     * The multiplexer controlling how data is split.
+     */
+    private final Multiplexer multiplexer;
+
+    /**
+     * The set of identifiers for the multiplexed entries.
+     */
+    private final Collection<?> multiplexedIds;
+
+    public MultiplexArgumentTypeDescriptor() {
+        this.multiplexer = null;
+        this.multiplexedIds = null;
+    }
+
+    /**
+     * Private constructor to use in creating a closure of the MultiplexArgumentTypeDescriptor specific to the
+     * given set of multiplexed ids.
+     * @param multiplexedIds The collection of multiplexed entries
+     */
+    private MultiplexArgumentTypeDescriptor(final Multiplexer multiplexer, final Collection<?> multiplexedIds) {
+        this.multiplexer = multiplexer;
+        this.multiplexedIds = multiplexedIds;
+    }
+
+    @Override
+    public boolean supports( Class type ) {
+        return ( Map.class.isAssignableFrom(type) );
+    }
+
+    @Override
+    public boolean createsTypeDefault(ArgumentSource source) {
+        // Multiplexing always creates a type default.
+        return true;
+    }
+
+    @Override
+    public Object createTypeDefault(ParsingEngine parsingEngine,ArgumentSource source, Type type) {
+        if(multiplexer == null || multiplexedIds == null)
+            throw new ReviewedGATKException("No multiplexed ids available");
+
+        Map<Object,Object> multiplexedMapping = new HashMap<Object,Object>();
+        Class componentType = makeRawTypeIfNecessary(getCollectionComponentType(source.field));
+        ArgumentTypeDescriptor componentTypeDescriptor = parsingEngine.selectBestTypeDescriptor(componentType);
+
+        for(Object id: multiplexedIds) {
+            Object value = null;
+            if(componentTypeDescriptor.createsTypeDefault(source))
+                value = componentTypeDescriptor.createTypeDefault(parsingEngine,source,componentType);
+            multiplexedMapping.put(id,value);
+        }
+        return multiplexedMapping;
+    }
+
+    @Override
+    public String typeDefaultDocString(ArgumentSource source) {
+        return "None";
+    }
+
+    @Override
+    public Object parse(ParsingEngine parsingEngine, ArgumentSource source, Type type, ArgumentMatches matches) {
+        if(multiplexedIds == null)
+            throw new ReviewedGATKException("Cannot directly parse a MultiplexArgumentTypeDescriptor; must create a derivative type descriptor first.");
+
+        Map<Object,Object> multiplexedMapping = new HashMap<Object,Object>();
+
+        Class componentType = makeRawTypeIfNecessary(getCollectionComponentType(source.field));
+
+
+        for(Object id: multiplexedIds) {
+            Object value = parsingEngine.selectBestTypeDescriptor(componentType).parse(parsingEngine,source,componentType,matches.transform(multiplexer,id));
+            multiplexedMapping.put(id,value);
+        }
+
+        parsingEngine.addTags(multiplexedMapping,getArgumentTags(matches));
+
+        return multiplexedMapping;
+    }
+
+    public MultiplexArgumentTypeDescriptor createCustomTypeDescriptor(ParsingEngine parsingEngine,ArgumentSource dependentArgument,Object containingObject) {
+        String[] sourceFields = dependentArgument.field.getAnnotation(Multiplex.class).arguments();
+
+        List<ArgumentSource> allSources = parsingEngine.extractArgumentSources(containingObject.getClass());
+        Class[] sourceTypes = new Class[sourceFields.length];
+        Object[] sourceValues = new Object[sourceFields.length];
+        int currentField = 0;
+
+        for(String sourceField: sourceFields) {
+            boolean fieldFound = false;
+            for(ArgumentSource source: allSources) {
+                if(!source.field.getName().equals(sourceField))
+                    continue;
+                if(source.field.isAnnotationPresent(Multiplex.class))
+                    throw new ReviewedGATKException("Command-line arguments can only depend on independent fields");
+                sourceTypes[currentField] = source.field.getType();
+                sourceValues[currentField] = JVMUtils.getFieldValue(source.field,containingObject);
+                currentField++;
+                fieldFound = true;
+            }
+            if(!fieldFound)
+                throw new ReviewedGATKException(String.format("Unable to find source field %s, referred to by dependent field %s",sourceField,dependentArgument.field.getName()));
+        }
+
+        Class<? extends Multiplexer> multiplexerType = dependentArgument.field.getAnnotation(Multiplex.class).value();
+        Constructor<? extends Multiplexer> multiplexerConstructor;
+        try {
+            multiplexerConstructor = multiplexerType.getConstructor(sourceTypes);
+            multiplexerConstructor.setAccessible(true);
+        }
+        catch(NoSuchMethodException ex) {
+            throw new ReviewedGATKException(String.format("Unable to find constructor for class %s with parameters %s",multiplexerType.getName(),Arrays.deepToString(sourceFields)),ex);
+        }
+
+        Multiplexer multiplexer;
+        try {
+            multiplexer = multiplexerConstructor.newInstance(sourceValues);
+        }
+        catch(IllegalAccessException ex) {
+            throw new ReviewedGATKException(String.format("Constructor for class %s with parameters %s is inaccessible",multiplexerType.getName(),Arrays.deepToString(sourceFields)),ex);
+        }
+        catch(InstantiationException ex) {
+            throw new ReviewedGATKException(String.format("Can't create class %s with parameters %s",multiplexerType.getName(),Arrays.deepToString(sourceFields)),ex);
+        }
+        catch(InvocationTargetException ex) {
+            throw new ReviewedGATKException(String.format("Can't invoke constructor of class %s with parameters %s",multiplexerType.getName(),Arrays.deepToString(sourceFields)),ex);
+        }
+
+        return new MultiplexArgumentTypeDescriptor(multiplexer,multiplexer.multiplex());
+    }
+
+    /**
+     * Return the component type of a field, or String.class if the type cannot be found.
+     * @param field The reflected field to inspect.
+     * @return The parameterized component type, or String.class if the parameterized type could not be found.
+     * @throws IllegalArgumentException If more than one parameterized type is found on the field.
+     */
+    @Override
+    protected Type getCollectionComponentType( Field field ) {
+        // Multiplex arguments must resolve to maps from which the clp should extract the second type.
+        if( field.getGenericType() instanceof ParameterizedType) {
+            ParameterizedType parameterizedType = (ParameterizedType)field.getGenericType();
+            if( parameterizedType.getActualTypeArguments().length != 2 )
+                throw new IllegalArgumentException("Unable to determine collection type of field: " + field.toString());
+            return (Class)parameterizedType.getActualTypeArguments()[1];
+        }
+        else
+            return String.class;
+    }
+}
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/commandline/ClassType.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/commandline/ClassType.java
new file mode 100644
index 0000000..d57d326
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/commandline/ClassType.java
@@ -0,0 +1,40 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.utils.commandline;
+
+import java.lang.annotation.*;
+
+/**
+ * Annotates generic fields where the parameterized type is not specified or erased.
+ * Primarily used for Queue traits.  Defined in java since scala does not support RetentionPolicy.RUNTIME.
+ */
+ at Documented
+ at Inherited
+ at Retention(RetentionPolicy.RUNTIME)
+ at Target({ElementType.FIELD})
+public @interface ClassType {
+    Class value();
+}
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/commandline/CommandLineProgram.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/commandline/CommandLineProgram.java
new file mode 100644
index 0000000..80ebe2c
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/commandline/CommandLineProgram.java
@@ -0,0 +1,447 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.utils.commandline;
+
+import org.apache.log4j.FileAppender;
+import org.apache.log4j.Level;
+import org.apache.log4j.Logger;
+import org.apache.log4j.PatternLayout;
+import org.broadinstitute.gatk.engine.CommandLineGATK;
+import org.broadinstitute.gatk.utils.exceptions.ReviewedGATKException;
+import org.broadinstitute.gatk.utils.help.ApplicationDetails;
+import org.broadinstitute.gatk.utils.help.HelpConstants;
+import org.broadinstitute.gatk.utils.help.HelpFormatter;
+
+import java.io.IOException;
+import java.util.*;
+
+public abstract class CommandLineProgram {
+
+    /** The command-line program and the arguments it returned. */
+    public ParsingEngine parser = null;
+
+    /**
+     * Setting INFO gets you INFO up to FATAL, setting ERROR gets you ERROR and FATAL level logging, and so on.
+     */
+    @Argument(fullName = "logging_level", shortName = "l", doc = "Set the minimum level of logging", required = false)
+    protected String logging_level = "INFO";
+
+    /**
+     * File to save the logging output.
+     */
+    @Output(fullName = "log_to_file", shortName = "log", doc = "Set the logging location", required = false)
+    protected String toFile = null;
+
+    /**
+     * This will produce a help message in the terminal with general usage information, listing available arguments
+     * as well as tool-specific information if applicable.
+     */
+    @Argument(fullName = "help", shortName = "h", doc = "Generate the help message", required = false)
+    public Boolean help = false;
+
+    /**
+     * Use this to check the version number of the GATK executable you are invoking. Note that the version number is
+     * always included in the output at the start of every run as well as any error message.
+     */
+    @Argument(fullName = "version", shortName = "version", doc ="Output version information", required = false)
+    public Boolean version = false;
+
+
+    /** our logging output patterns */
+    private static final String patternString = "%-5p %d{HH:mm:ss,SSS} %C{1} - %m %n";
+
+    static {
+        /**
+         * The very first thing that any GATK application does is forces the JVM locale into US English, so that we don't have
+         * to think about number formatting issues.
+         */
+        forceJVMLocaleToUSEnglish();
+        // setup a basic log configuration
+        CommandLineUtils.configureConsoleLogging();
+    }
+
+
+    /**
+     * Allows a given application to return a brief description of itself.
+     *
+     * @return An ApplicationDetails object describing the current application.  Should not be null.
+     */
+    protected ApplicationDetails getApplicationDetails() {
+        return new ApplicationDetails(ApplicationDetails.createDefaultHeader(getClass()),
+                                      Collections.<String>emptyList(),
+                                      ApplicationDetails.createDefaultRunningInstructions(getClass()),
+                                      null);
+    }
+
+    /**
+     * Subclasses of CommandLinePrograms can provide their own types of command-line arguments.
+     * @return A collection of type descriptors generating implementation-dependent placeholders.
+     */
+    protected Collection<ArgumentTypeDescriptor> getArgumentTypeDescriptors() {
+        return Collections.emptyList();
+    }
+
+    /**
+     * Will this application want to vary its argument list dynamically?
+     * If so, parse the command-line options and then prompt the subclass to return
+     * a list of argument providers.
+     *
+     * @return Whether the application should vary command-line arguments dynamically.
+     */
+    protected boolean canAddArgumentsDynamically() { return false; }
+
+    /**
+     * Provide a list of object to inspect, looking for additional command-line arguments.
+     *
+     * @return A list of objects to inspect.
+     */
+    protected Class[] getArgumentSources() {
+        return new Class[]{};
+    }
+
+    /**
+     * Name this argument source.  Provides the (full) class name as a default.
+     *
+     * @param source The argument source.
+     *
+     * @return a name for the argument source.
+     */
+    protected String getArgumentSourceName( Class source ) { return source.toString(); }
+
+    /**
+     * Sets the command-line parsing engine. Necessary for unit testing purposes.
+     * @param parser the new command-line parsing engine
+     */
+    public void setParser( ParsingEngine parser ) {
+        this.parser = parser;
+    }
+
+    /**
+     * this is the function that the inheriting class can expect to have called
+     * when all the argument processing is done
+     *
+     * @return the return code to exit the program with
+     * @throws Exception when an exception occurs
+     */
+    protected abstract int execute() throws Exception;
+
+    public static int result = -1;
+
+    @SuppressWarnings("unchecked")
+    public static void start(CommandLineProgram clp, String[] args) throws Exception {
+        start(clp, args, false);
+    }
+
+    /**
+     * This function is called to start processing the command line, and kick
+     * off the execute message of the program.
+     *
+     * @param clp  the command line program to execute
+     * @param args the command line arguments passed in
+     * @param dryRun dry run
+     * @throws Exception when an exception occurs
+     */
+    @SuppressWarnings("unchecked")
+    public static void start(CommandLineProgram clp, String[] args, boolean dryRun) throws Exception {
+
+        try {
+            // setup our log layout
+            PatternLayout layout = new PatternLayout();
+
+            Logger logger = CommandLineUtils.getStingLogger();
+
+            // now set the layout of all the loggers to our layout
+            CommandLineUtils.setLayout(logger, layout);
+
+            // Initialize the logger using the defaults.
+            clp.setupLoggerLevel(layout);
+
+            // setup the parser
+            ParsingEngine parser = clp.parser = new ParsingEngine(clp);
+            parser.addArgumentSource(clp.getClass());
+
+            Map<ArgumentMatchSource, ParsedArgs> parsedArgs;
+
+            // process the args
+            if (clp.canAddArgumentsDynamically()) {
+                // if the command-line program can toss in extra args, fetch them and reparse the arguments.
+                parser.parse(args);
+
+                // Allow invalid and missing required arguments to pass this validation step.
+                //   - InvalidArgument in case these arguments are specified by plugins.
+                //   - MissingRequiredArgument in case the user requested help.  Handle that later, once we've
+                //                             determined the full complement of arguments.
+                if ( ! dryRun )
+                    parser.validate(EnumSet.of(ParsingEngine.ValidationType.MissingRequiredArgument,
+                            ParsingEngine.ValidationType.InvalidArgument));
+                parser.loadArgumentsIntoObject(clp);
+
+                // Initialize the logger using the loaded command line.
+                clp.setupLoggerLevel(layout);
+
+                Class[] argumentSources = clp.getArgumentSources();
+                    for (Class argumentSource : argumentSources)
+                    parser.addArgumentSource(clp.getArgumentSourceName(argumentSource), argumentSource);
+                parsedArgs = parser.parse(args);
+
+                if (isVersionPresent(parser))
+                    printVersionAndExit();
+
+                if (isHelpPresent(parser))
+                    printHelpAndExit(clp, parser);
+
+                if ( ! dryRun ) parser.validate();
+            } else {
+                parsedArgs = parser.parse(args);
+
+                if ( ! dryRun ) {
+                    if (isHelpPresent(parser))
+                        printHelpAndExit(clp, parser);
+
+                    parser.validate();
+                }
+                parser.loadArgumentsIntoObject(clp);
+
+                // Initialize the logger using the loaded command line.
+                clp.setupLoggerLevel(layout);
+            }
+
+            if ( ! dryRun ) {
+                // if they specify a log location, output our data there
+                if (clp.toFile != null) {
+                    FileAppender appender;
+                    try {
+                        appender = new FileAppender(layout, clp.toFile, false);
+                        logger.addAppender(appender);
+                    } catch (IOException e) {
+                        throw new RuntimeException("Unable to re-route log output to " + clp.toFile + " make sure the destination exists");
+                    }
+                }
+
+                // regardless of what happens next, generate the header information
+                HelpFormatter.generateHeaderInformation(clp.getApplicationDetails(), parsedArgs);
+
+                // call the execute
+                CommandLineProgram.result = clp.execute();
+            }
+        }
+        catch (ArgumentException e) {
+            //clp.parser.printHelp(clp.getApplicationDetails());
+            // Rethrow the exception to exit with an error.
+            throw e;
+        }
+    }
+
+    /**
+     * Find fields in the object obj that look like command-line arguments, and put command-line
+     * arguments into them.
+     *
+     * @param obj Object to inspect for command line arguments.
+     */
+    public void loadArgumentsIntoObject(Object obj) {
+        parser.loadArgumentsIntoObject(obj);
+    }
+
+    /**
+     * this function checks the logger level passed in on the command line, taking the lowest
+     * level that was provided.
+     * @param layout Pattern layout to format based on the logger level.
+     */
+    private void setupLoggerLevel(PatternLayout layout) {
+        layout.setConversionPattern(patternString);
+
+        // set the default logger level
+        Level par;
+        if (logging_level.toUpperCase().equals("DEBUG")) {
+            par = Level.DEBUG;
+        } else if (logging_level.toUpperCase().equals("INFO")) {
+            par = Level.INFO;
+        } else if (logging_level.toUpperCase().equals("WARN")) {
+            par = Level.WARN;
+        } else if (logging_level.toUpperCase().equals("ERROR")) {
+            par = Level.ERROR;
+        } else if (logging_level.toUpperCase().equals("FATAL")) {
+            par = Level.FATAL;
+        } else if (logging_level.toUpperCase().equals("OFF")) {
+            par = Level.OFF;
+        } else {
+            // we don't understand the logging level, let's get out of here
+            throw new ArgumentException("Unable to match: " + logging_level + " to a logging level, make sure it's a valid level (DEBUG, INFO, WARN, ERROR, FATAL, OFF)");
+        }
+
+        Logger.getRootLogger().setLevel(par);
+    }
+
+    /**
+     * a function used to indicate an error occurred in the command line tool
+     */
+    private static void printDocumentationReference() {
+        errorPrintf("Visit our website and forum for extensive documentation and answers to %n");
+        errorPrintf("commonly asked questions " + HelpConstants.BASE_GATK_URL + "%n");
+    }
+
+
+    /**
+     * Do a cursory search for the given argument.
+     *
+     * @param parser Parser
+     *
+     * @return True if help is present; false otherwise.
+     */
+    private static boolean isHelpPresent(ParsingEngine parser) {
+        return parser.isArgumentPresent("help");
+    }
+
+    /**
+     * Print help and exit.
+     *
+     * @param clp    Instance of the command-line program.
+     * @param parser True if help is present; false otherwise.
+     */
+    private static void printHelpAndExit(CommandLineProgram clp, ParsingEngine parser) {
+        parser.printHelp(clp.getApplicationDetails());
+        System.exit(0);
+    }
+
+    /**
+     * Do a cursory search for the argument "version".
+     *
+     * @param parser Parser
+     *
+     * @return True if version is present; false otherwise.
+     */
+    private static boolean isVersionPresent(ParsingEngine parser) {
+        return parser.isArgumentPresent("version");
+    }
+
+    /**
+     * Print help and exit.
+     */
+    private static void printVersionAndExit() {
+        System.out.println(CommandLineGATK.getVersionNumber().toString());
+        System.exit(0);
+    }
+
+
+    private static void errorPrintf(String format, Object... s) {
+        String formatted = String.format(format, s);
+
+        if ( formatted.trim().equals("") )
+            System.err.println("##### ERROR");
+        else {
+            for ( String part : formatted.split("\n") ) {
+                System.err.println("##### ERROR " + part);
+            }
+        }
+    }
+
+
+    /**
+     * used to indicate an error occured
+     *
+     * @param msg the message
+     * @param t   the error
+     */
+    public static void exitSystemWithError(String msg, final Throwable t) {
+        errorPrintf("------------------------------------------------------------------------------------------%n");
+        errorPrintf("stack trace %n");
+        t.printStackTrace();
+
+        errorPrintf("------------------------------------------------------------------------------------------%n");
+        errorPrintf("A GATK RUNTIME ERROR has occurred (version %s):%n", CommandLineGATK.getVersionNumber());
+        errorPrintf("%n");
+        errorPrintf("This might be a bug. Please check the documentation guide to see if this is a known problem.%n");
+        errorPrintf("If not, please post the error message, with stack trace, to the GATK forum.%n");
+        printDocumentationReference();
+        if ( msg == null ) // some exceptions don't have detailed messages
+            msg = "Code exception (see stack trace for error itself)";
+        errorPrintf("%n");
+        errorPrintf("MESSAGE: %s%n", msg.trim());
+        errorPrintf("------------------------------------------------------------------------------------------%n");
+        System.exit(1);
+    }
+
+    public static void exitSystemWithUserError(final Exception e) {
+        if ( e.getMessage() == null )
+            throw new ReviewedGATKException("UserException found with no message!", e);
+
+        errorPrintf("------------------------------------------------------------------------------------------%n");
+        errorPrintf("A USER ERROR has occurred (version %s): %n", CommandLineGATK.getVersionNumber());
+        errorPrintf("%n");
+        errorPrintf("This means that one or more arguments or inputs in your command are incorrect.%n");
+        errorPrintf("The error message below tells you what is the problem.%n");
+        errorPrintf("%n");
+        errorPrintf("If the problem is an invalid argument, please check the online documentation guide%n");
+        errorPrintf("(or rerun your command with --help) to view allowable command-line arguments for this tool.%n");
+        errorPrintf("%n");
+        printDocumentationReference();
+        errorPrintf("%n");
+        errorPrintf("Please do NOT post this error to the GATK forum unless you have really tried to fix it yourself.%n");
+        errorPrintf("%n");
+        errorPrintf("MESSAGE: %s%n", e.getMessage().trim());
+        errorPrintf("------------------------------------------------------------------------------------------%n");
+        System.exit(1);
+    }
+
+    public static void exitSystemWithSamError(final Throwable t) {
+        if ( t.getMessage() == null )
+            throw new ReviewedGATKException("SamException found with no message!", t);
+
+        errorPrintf("------------------------------------------------------------------------------------------%n");
+        errorPrintf("A BAM ERROR has occurred (version %s): %n", CommandLineGATK.getVersionNumber());
+        errorPrintf("%n");
+        errorPrintf("This means that there is something wrong with the BAM file(s) you provided.%n");
+        errorPrintf("The error message below tells you what is the problem.%n");
+        errorPrintf("%n");
+        printDocumentationReference();
+        errorPrintf("%n");
+        errorPrintf("Please do NOT post this error to the GATK forum until you have followed these instructions:%n");
+        errorPrintf("- Make sure that your BAM file is well-formed by running Picard's validator on it%n");
+        errorPrintf("(see http://picard.sourceforge.net/command-line-overview.shtml#ValidateSamFile for details)%n");
+        errorPrintf("- Ensure that your BAM index is not corrupted: delete the current one and regenerate it with 'samtools index'%n");
+        errorPrintf("%n");
+        errorPrintf("MESSAGE: %s%n", t.getMessage().trim());
+        errorPrintf("------------------------------------------------------------------------------------------%n");
+        System.exit(1);
+    }
+
+
+    /**
+     * used to indicate an error occured
+     *
+     * @param t the exception that occurred
+     */
+    public static void exitSystemWithError(Throwable t) {
+        exitSystemWithError(t.getMessage(), t);
+    }
+
+    /**
+     * A hack to ensure that numbers are always formatted in the US style.
+     */
+    protected static void forceJVMLocaleToUSEnglish() {
+        Locale.setDefault(Locale.US);
+    }
+}
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/commandline/CommandLineUtils.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/commandline/CommandLineUtils.java
new file mode 100644
index 0000000..70f5532
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/commandline/CommandLineUtils.java
@@ -0,0 +1,192 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.utils.commandline;
+
+import org.apache.log4j.Appender;
+import org.apache.log4j.ConsoleAppender;
+import org.apache.log4j.Logger;
+import org.apache.log4j.PatternLayout;
+import org.broadinstitute.gatk.utils.exceptions.ReviewedGATKException;
+
+import java.lang.annotation.Annotation;
+import java.util.Collections;
+import java.util.Enumeration;
+import java.util.LinkedHashMap;
+import java.util.Map;
+
+/**
+ * Static utility methods for working with command-line arguments.
+ *
+ * @author mhanna
+ * @version 0.1
+ */
+public class CommandLineUtils {
+
+    /**
+     * Returns a key-value mapping of the command-line arguments passed into the GATK.
+     * Will be approximate; this class doesn't have all the required data to completely
+     * reconstruct the list of command-line arguments from the given objects.
+     *
+     * @param parsingEngine      The parsing engine
+     * @param argumentProviders  The providers of command-line arguments.
+     * @return A key-value mapping of argument full names to argument values.  Produces best string representation
+     *         possible given the information available.
+     */
+    public static Map<String,String> getApproximateCommandLineArguments(ParsingEngine parsingEngine, Object... argumentProviders) {
+        return getApproximateCommandLineArguments(parsingEngine, false, argumentProviders);
+    }
+
+    /**
+     * Returns a key-value mapping of the command-line arguments passed into the GATK.
+     * Will be approximate; this class doesn't have all the required data to completely
+     * reconstruct the list of command-line arguments from the given objects.
+     * 
+     * @param parsingEngine      The parsing engine
+     * @param skipObjectPointers Should we skip arguments whose values are pointers (and don't print nicely)?
+     * @param argumentProviders  The providers of command-line arguments.
+     * @return A key-value mapping of argument full names to argument values.  Produces best string representation
+     *         possible given the information available.
+     */
+    public static Map<String,String> getApproximateCommandLineArguments(ParsingEngine parsingEngine, boolean skipObjectPointers, Object... argumentProviders) {
+        Map<String,String> commandLineArguments = new LinkedHashMap<String,String>();
+
+        for(Object argumentProvider: argumentProviders) {
+            Map<ArgumentSource, Object> argBindings = parsingEngine.extractArgumentBindings(argumentProvider);
+            for(Map.Entry<ArgumentSource, Object> elt: argBindings.entrySet()) {
+                Object argumentValue = elt.getValue();
+
+                String argumentValueString = argumentValue != null ? argumentValue.toString() : null;
+                if ( skipObjectPointers && isObjectPointer(argumentValueString) )
+                    continue;
+
+                for(ArgumentDefinition definition: elt.getKey().createArgumentDefinitions()) {
+                    String argumentName = definition.fullName;
+                    commandLineArguments.put(argumentName,argumentValueString);
+                }
+            }
+        }
+
+        return commandLineArguments;
+    }
+
+    /**
+     * Create an approximate list of command-line arguments based on the given argument providers.
+     * @param parsingEngine      The parsing engine
+     * @param argumentProviders  Argument providers to inspect.
+     * @return A string representing the given command-line arguments.
+     */
+    public static String createApproximateCommandLineArgumentString(ParsingEngine parsingEngine, Object... argumentProviders) {
+        return createApproximateCommandLineArgumentString(parsingEngine, true, argumentProviders);
+    }
+
+    /**
+     * Create an approximate list of command-line arguments based on the given argument providers.
+     * @param parsingEngine      The parsing engine
+     * @param skipObjectPointers Should we skip arguments whose values are pointers (and don't print nicely)?
+     * @param argumentProviders  Argument providers to inspect.
+     * @return A string representing the given command-line arguments.
+     */
+    public static String createApproximateCommandLineArgumentString(ParsingEngine parsingEngine, boolean skipObjectPointers, Object... argumentProviders) {
+        Map<String,String> commandLineArgs = getApproximateCommandLineArguments(parsingEngine, skipObjectPointers, argumentProviders);
+        StringBuffer sb = new StringBuffer();
+
+        boolean first = true;
+        for ( Map.Entry<String, String> commandLineArg : commandLineArgs.entrySet() ) {
+            if ( !first )
+                sb.append(" ");
+            sb.append(commandLineArg.getKey());
+            sb.append("=");
+            sb.append(commandLineArg.getValue());
+            first = false;
+        }
+
+        return sb.toString();
+    }
+
+    /**
+     * A hack to get around the fact that Java doesn't like inheritance in Annotations.
+     * @param annotation to run the method on
+     * @param method the method to invoke
+     * @return the return value of the method
+     */
+    public static Object getValue(Annotation annotation, String method) {
+        try {
+            return annotation.getClass().getMethod(method).invoke(annotation);
+        } catch (Exception e) {
+            throw new ReviewedGATKException("Unable to access method " + method + " on annotation " + annotation.getClass(), e);
+        }
+    }
+
+    // The problem here is that some of the fields being output are Objects - and those
+    //  Objects don't overload toString() so that the output is just the memory pointer
+    //  to the Object.  Because those values are non-deterministic, they don't merge well
+    //  into BAM/VCF headers (plus, it's just damn ugly).  Perhaps there's a better way to
+    //  do this, but at least this one works for the moment.
+    private static final String pointerRegexp = ".+@[0-9a-fA-F]+$";
+    private static boolean isObjectPointer(String s) {
+        return s != null && s.matches(pointerRegexp);
+    }
+
+    /**
+     * Returns the root logger for all GATK code.
+     * @return the root logger for all GATK  code.
+     */
+    public static Logger getStingLogger() {
+        return Logger.getLogger("org.broadinstitute.gatk");
+    }
+
+    /**
+     * Enables console logging.
+     */
+    @SuppressWarnings("unchecked")
+    public static void configureConsoleLogging() {
+        // Check to see if a console logger has already been enabled.
+        for (Logger logger = getStingLogger(); logger != null; logger = (Logger)logger.getParent()) {
+            Enumeration<Appender> e = (Enumeration<Appender>) logger.getAllAppenders();
+            for (Appender appender: Collections.list(e)) {
+                if (appender instanceof ConsoleAppender)
+                    return;
+            }
+        }
+        // Extracted from BasicConfigurator.configure(), but only applied to the GATK logger.
+        Logger.getRootLogger().addAppender(new ConsoleAppender(
+                    new PatternLayout(PatternLayout.TTCC_CONVERSION_PATTERN), ConsoleAppender.SYSTEM_ERR));
+    }
+
+    /**
+     * Sets the layout of the logger.
+     * @param logger The logger.
+     * @param layout The layout.
+     */
+    @SuppressWarnings("unchecked")
+    public static void setLayout(Logger logger, PatternLayout layout) {
+        for (; logger != null; logger = (Logger)logger.getParent()) {
+            Enumeration<Appender> e = (Enumeration<Appender>) logger.getAllAppenders();
+            for (Appender appender: Collections.list(e))
+                appender.setLayout(layout);
+        }
+    }
+}
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/commandline/EnumerationArgumentDefault.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/commandline/EnumerationArgumentDefault.java
new file mode 100644
index 0000000..3bbdedb
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/commandline/EnumerationArgumentDefault.java
@@ -0,0 +1,65 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.utils.commandline;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * @author aaron
+ * <p/>
+ * Annotation EnumerationArgumentDefault
+ * <p/>
+ * Allows the default argument value to be set for an enum; this allows us to treat enums as
+ * booleans on the command line. I.e.
+ *
+ * if we're using an enum Shape,
+ *
+ * enum shape {
+ *  SQUARE,
+ *  CIRCLE,
+ *  @EnumerationArgumentDefault
+ *  TRIANGLE
+ * }
+ *
+ * and a command line option -shape, the EnumerationArgumentDefault would allow you to say:
+ * -shape
+ * or
+ * -shape TRIANGLE
+ *
+ * would get -shape set to TRIANGLE, where:
+ *
+ * -shape SQUARE
+ *
+ * would set shape to SQUARE
+ *
+ */
+ at Retention(RetentionPolicy.RUNTIME)
+ at Target(ElementType.FIELD)
+public @interface EnumerationArgumentDefault {
+}
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/commandline/Gather.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/commandline/Gather.java
new file mode 100644
index 0000000..b291663
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/commandline/Gather.java
@@ -0,0 +1,41 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.utils.commandline;
+
+import java.lang.annotation.*;
+
+/**
+ * Specifies the class type to gather an @Output
+ */
+ at Documented
+ at Inherited
+ at Retention(RetentionPolicy.RUNTIME)
+ at Target({ElementType.FIELD})
+public @interface Gather {
+    Class value() default Gather.class;
+    String className() default "";
+    boolean enabled() default true;
+}
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/commandline/Gatherer.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/commandline/Gatherer.java
new file mode 100644
index 0000000..761611f
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/commandline/Gatherer.java
@@ -0,0 +1,47 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.utils.commandline;
+
+import java.io.File;
+import java.util.List;
+
+/**
+ * Combines a list of files into a single output.
+ */
+public abstract class Gatherer {
+    /**
+     * Gathers a list of files into a single output.
+     * @param inputs Files to combine.
+     * @param output Path to output file.
+     */
+    public abstract void gather(List<File> inputs, File output);
+
+    /**
+     * Returns true if the caller should wait for the input files to propagate over NFS before running gather().
+     * @return true if the caller should wait for the input files to propagate over NFS before running gather().
+     */
+    public boolean waitForInputs() { return true; }
+}
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/commandline/Hidden.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/commandline/Hidden.java
new file mode 100644
index 0000000..02325a7
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/commandline/Hidden.java
@@ -0,0 +1,41 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.utils.commandline;
+
+import java.lang.annotation.*;
+
+/**
+ * Indicates that a walker or walker argument should not be presented in the help system.
+ *
+ * @author mhanna
+ * @version 0.1
+ */
+ at Documented
+ at Inherited
+ at Retention(RetentionPolicy.RUNTIME)
+ at Target({ElementType.TYPE,ElementType.FIELD})
+public @interface Hidden {
+}
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/commandline/Input.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/commandline/Input.java
new file mode 100644
index 0000000..8ec0483
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/commandline/Input.java
@@ -0,0 +1,83 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.utils.commandline;
+
+import java.lang.annotation.*;
+
+/**
+ * Annotates fields in objects that should be used as command-line arguments.
+ * Any field annotated with @Input can appear as a command-line parameter.
+ */
+ at Documented
+ at Inherited
+ at Retention(RetentionPolicy.RUNTIME)
+ at Target(ElementType.FIELD)
+public @interface Input {
+    /**
+     * The full name of the command-line argument.  Full names should be
+     * prefixed on the command-line with a double dash (--).
+     * @return Selected full name, or "" to use the default.
+     */
+    String fullName() default "";
+
+    /**
+     * Specified short name of the command.  Short names should be prefixed
+     * with a single dash.  Argument values can directly abut single-char
+     * short names or be separated from them by a space.
+     * @return Selected short name, or "" for none.
+     */
+    String shortName() default "";
+
+    /**
+     * Documentation for the command-line argument.  Should appear when the
+     * --help argument is specified.
+     * @return Doc string associated with this command-line argument.
+     */
+    String doc() default "Undocumented option";
+
+    /**
+     * Is this argument required.  If true, the command-line argument system will
+     * make a best guess for populating this argument based on the type descriptor,
+     * and will fail if the type can't be populated.
+     * @return True if the argument is required.  False otherwise.
+     */
+    boolean required() default true;
+
+    /**
+     * Should this command-line argument be exclusive of others.  Should be
+     * a comma-separated list of names of arguments of which this should be
+     * independent.
+     * @return A comma-separated string listing other arguments of which this
+     *         argument should be independent.
+     */
+    String exclusiveOf() default "";
+
+    /**
+     * Provide a regexp-based validation string.
+     * @return Non-empty regexp for validation, blank otherwise.
+     */
+    String validation() default "";
+}
\ No newline at end of file
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/commandline/IntervalArgumentCollection.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/commandline/IntervalArgumentCollection.java
new file mode 100644
index 0000000..717a077
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/commandline/IntervalArgumentCollection.java
@@ -0,0 +1,88 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.utils.commandline;
+
+import htsjdk.tribble.Feature;
+import org.broadinstitute.gatk.utils.interval.IntervalMergingRule;
+import org.broadinstitute.gatk.utils.interval.IntervalSetRule;
+
+import java.util.List;
+
+public class IntervalArgumentCollection {
+    /**
+     * Use this option to perform the analysis over only part of the genome. This argument can be specified multiple times.
+     * You can use samtools-style intervals either explicitly on the command line (e.g. -L chr1 or -L chr1:100-200) or
+     * by loading in a file containing a list of intervals (e.g. -L myFile.intervals).
+     *
+     * Additionally, you can also specify a ROD file (such as a VCF file) in order to perform the analysis at specific
+     * positions based on the records present in the file (e.g. -L file.vcf).
+     *
+     * Finally, you can also use this to perform the analysis on the reads that are completely unmapped in the BAM file
+     * (i.e. those without a reference contig) by specifying -L unmapped.
+     */
+    @Input(fullName = "intervals", shortName = "L", doc = "One or more genomic intervals over which to operate", required = false)
+    public List<IntervalBinding<Feature>> intervals = null;
+
+    /**
+     * Use this option to exclude certain parts of the genome from the analysis (like -L, but the opposite).
+     * This argument can be specified multiple times. You can use samtools-style intervals either explicitly on the
+     * command line (e.g. -XL chr1 or -XL chr1:100-200) or by loading in a file containing a list of intervals
+     * (e.g. -XL myFile.intervals).
+     *
+     * Additionally, you can also specify a ROD file (such as a VCF file) in order to exclude specific
+     * positions from the analysis based on the records present in the file (e.g. -XL file.vcf).
+     * */
+    @Input(fullName = "excludeIntervals", shortName = "XL", doc = "One or more genomic intervals to exclude from processing", required = false)
+    public List<IntervalBinding<Feature>> excludeIntervals = null;
+
+    /**
+     * By default, the program will take the UNION of all intervals specified using -L and/or -XL. However, you can
+     * change this setting for -L, for example if you want to take the INTERSECTION of the sets instead. E.g. to perform the
+     * analysis on positions for which there is a record in a VCF, but restrict this to just those on chromosome 20,
+     * you would do -L chr20 -L file.vcf -isr INTERSECTION. However, it is not possible to modify the merging approach
+     * for intervals passed using -XL (they will always be merged using UNION).
+     *
+     * Note that if you specify both -L and -XL, the -XL interval set will be subtracted from the -L interval set.
+     */
+    @Argument(fullName = "interval_set_rule", shortName = "isr", doc = "Set merging approach to use for combining interval inputs", required = false)
+    public IntervalSetRule intervalSetRule = IntervalSetRule.UNION;
+
+    /**
+     * By default, the program merges abutting intervals (i.e. intervals that are directly side-by-side but do not
+     * actually overlap) into a single continuous interval. However you can change this behavior if you want them to be
+     * treated as separate intervals instead.
+     */
+    @Argument(fullName = "interval_merging", shortName = "im", doc = "Interval merging rule for abutting intervals", required = false)
+    public IntervalMergingRule intervalMerging = IntervalMergingRule.ALL;
+
+    /**
+     * Use this to add padding to the intervals specified using -L and/or -XL. For example, '-L chr1:100' with a
+     * padding value of 20 would turn into '-L chr1:80-120'. This is typically used to add padding around exons when
+     * analyzing exomes. The general Broad exome calling pipeline uses 100 bp padding by default.
+     */
+    @Argument(fullName = "interval_padding", shortName = "ip", doc = "Amount of padding (in bp) to add to each interval", required = false, minValue = 0)
+    public int intervalPadding = 0;
+}
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/commandline/IntervalBinding.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/commandline/IntervalBinding.java
new file mode 100644
index 0000000..59048a9
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/commandline/IntervalBinding.java
@@ -0,0 +1,106 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.utils.commandline;
+
+import com.google.java.contract.Requires;
+import htsjdk.tribble.AbstractFeatureReader;
+import htsjdk.tribble.Feature;
+import htsjdk.tribble.FeatureCodec;
+import htsjdk.tribble.FeatureReader;
+import org.broadinstitute.gatk.engine.GenomeAnalysisEngine;
+import org.broadinstitute.gatk.engine.refdata.ReferenceDependentFeatureCodec;
+import org.broadinstitute.gatk.engine.refdata.tracks.FeatureManager;
+import org.broadinstitute.gatk.utils.GenomeLoc;
+import org.broadinstitute.gatk.utils.GenomeLocParser;
+import org.broadinstitute.gatk.utils.exceptions.UserException;
+import org.broadinstitute.gatk.utils.interval.IntervalUtils;
+
+import java.util.*;
+
+/**
+ * An IntervalBinding representing a walker argument that gets bound to either a ROD track or interval string.
+ *
+ * The IntervalBinding<T> is a formal GATK argument that bridges between a walker and
+ * the engine to construct intervals for traversal at runtime.  The IntervalBinding can
+ * either be a RodBinding<T>, a string of one interval, or a file with interval strings.
+ * The GATK Engine takes care of initializing the binding when appropriate and determining intervals from it.
+ *
+ * Note that this class is immutable.
+ */
+public final class IntervalBinding<T extends Feature> {
+
+    private RodBinding<T> featureIntervals;
+    private String stringIntervals;
+
+    @Requires({"type != null", "rawName != null", "source != null", "tribbleType != null", "tags != null"})
+    public IntervalBinding(Class<T> type, final String rawName, final String source, final String tribbleType, final Tags tags) {
+        featureIntervals = new RodBinding<>(type, rawName, source, tribbleType, tags);
+    }
+
+    @Requires({"intervalArgument != null"})
+    public IntervalBinding(String intervalArgument) {
+        stringIntervals = intervalArgument;
+    }
+
+    public String getSource() {
+        return ( featureIntervals != null ? featureIntervals.getSource() : stringIntervals );
+    }
+
+    public List<GenomeLoc> getIntervals(final GenomeAnalysisEngine toolkit) {
+        return getIntervals(toolkit.getGenomeLocParser());
+    }
+
+    public List<GenomeLoc> getIntervals(final GenomeLocParser genomeLocParser) {
+        List<GenomeLoc> intervals;
+
+        if ( featureIntervals != null ) {
+            intervals = new ArrayList<>();
+
+            // TODO -- after ROD system cleanup, go through the ROD system so that we can handle things like gzipped files
+
+            final FeatureCodec codec = new FeatureManager().getByName(featureIntervals.getTribbleType()).getCodec();
+            if ( codec instanceof ReferenceDependentFeatureCodec )
+                ((ReferenceDependentFeatureCodec)codec).setGenomeLocParser(genomeLocParser);
+            try {
+                FeatureReader<Feature> reader = AbstractFeatureReader.getFeatureReader(featureIntervals.getSource(), codec, false);
+                for ( Feature feature : reader.iterator() )
+                    intervals.add(genomeLocParser.createGenomeLoc(feature));
+            } catch (Exception e) {
+                throw new UserException.MalformedFile(featureIntervals.getSource(), "Problem reading the interval file", e);
+            }
+
+        } else {
+            intervals = IntervalUtils.parseIntervalArguments(genomeLocParser, stringIntervals);
+        }
+
+        Collections.sort(intervals);
+        return intervals;
+    }
+
+    public String toString() {
+        return getSource();
+    }
+}
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/commandline/MissingArgumentValueException.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/commandline/MissingArgumentValueException.java
new file mode 100644
index 0000000..f8f3895
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/commandline/MissingArgumentValueException.java
@@ -0,0 +1,50 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.utils.commandline;
+
+import org.broadinstitute.gatk.utils.Utils;
+
+/**
+ * Specifies that a value was missing when attempting to populate an argument.
+ */
+public class MissingArgumentValueException extends ArgumentException {
+    public MissingArgumentValueException( ArgumentDefinition... missingArguments ) {
+        super( formatArguments(missingArguments) );
+    }
+
+    private static String formatArguments( ArgumentDefinition... missingArguments ) {
+        StringBuilder sb = new StringBuilder();
+        for( ArgumentDefinition missingArgument: missingArguments ) {
+            if( missingArgument.shortName != null )
+                sb.append( String.format("%nValue for argument with name '--%s' (-%s) is missing.", missingArgument.fullName, missingArgument.shortName) );
+            else
+                sb.append( String.format("%nValue for argument with name '--%s' is missing.", missingArgument.fullName) );
+            if(missingArgument.validOptions != null)
+                sb.append( String.format("  Valid options are (%s).", Utils.join(",",missingArgument.validOptions)));
+        }
+        return sb.toString();
+    }
+}
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/commandline/Output.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/commandline/Output.java
new file mode 100644
index 0000000..88057a2
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/commandline/Output.java
@@ -0,0 +1,90 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.utils.commandline;
+
+import java.lang.annotation.*;
+
+/**
+ * Annotates fields in objects that should be used as command-line arguments.
+ * Any field annotated with @Argument can appear as a command-line parameter.
+ */
+ at Documented
+ at Inherited
+ at Retention(RetentionPolicy.RUNTIME)
+ at Target(ElementType.FIELD)
+public @interface Output {
+    /**
+     * The full name of the command-line argument.  Full names should be
+     * prefixed on the command-line with a double dash (--).
+     * @return Selected full name, or "" to use the default.
+     */
+    String fullName() default "out";
+
+    /**
+     * Specified short name of the command.  Short names should be prefixed
+     * with a single dash.  Argument values can directly abut single-char
+     * short names or be separated from them by a space.
+     * @return Selected short name, or "" for none.
+     */
+    String shortName() default "o";
+
+    /**
+     * Documentation for the command-line argument.  Should appear when the
+     * --help argument is specified.
+     * @return Doc string associated with this command-line argument.
+     */
+    String doc() default "An output file created by the walker.  Will overwrite contents if file exists";
+
+    /**
+     * Is this argument required.  If true, the command-line argument system will
+     * make a best guess for populating this argument based on the type, and will
+     * fail if the type can't be populated.
+     * @return True if the argument is required.  False otherwise.
+     */
+    boolean required() default false;
+
+    /**
+     * If this argument is not required, should it default to use stdout if no
+     * output file is explicitly provided on the command-line?
+     * @return True if the argument should default to stdout.  False otherwise.
+     */
+    boolean defaultToStdout() default true;
+
+    /**
+     * Should this command-line argument be exclusive of others.  Should be
+     * a comma-separated list of names of arguments of which this should be
+     * independent.
+     * @return A comma-separated string listing other arguments of which this
+     *         argument should be independent.
+     */
+    String exclusiveOf() default "";
+
+    /**
+     * Provide a regexp-based validation string.
+     * @return Non-empty regexp for validation, blank otherwise.
+     */
+    String validation() default "";
+}
\ No newline at end of file
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/commandline/ParsedArgs.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/commandline/ParsedArgs.java
new file mode 100644
index 0000000..45cc055
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/commandline/ParsedArgs.java
@@ -0,0 +1,38 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.utils.commandline;
+
+/**
+ * Represents a collection of parsed arguments for an argument source.
+ *
+ * Useful for printing out help documents.
+ */
+public abstract class ParsedArgs {
+    /**
+     * @return A compact description of the arguments from an provider/source.
+     */
+    public abstract String getDescription();
+}
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/commandline/ParsedListArgs.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/commandline/ParsedListArgs.java
new file mode 100644
index 0000000..aa9e186
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/commandline/ParsedListArgs.java
@@ -0,0 +1,55 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.utils.commandline;
+
+import org.apache.commons.lang.StringUtils;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+/**
+ * A list of string arguments, usually from the command line or an args list file.
+ */
+public class ParsedListArgs extends ParsedArgs {
+    private final List<String> args = new ArrayList<String>();
+
+    public ParsedListArgs() {
+    }
+
+    public ParsedListArgs(List<String> args) {
+        this.args.addAll(args);
+    }
+
+    public void add(String... args) {
+        this.args.addAll(Arrays.asList(args));
+    }
+
+    @Override
+    public String getDescription() {
+        return StringUtils.join(this.args, " ");
+    }
+}
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/commandline/ParsingEngine.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/commandline/ParsingEngine.java
new file mode 100644
index 0000000..6244b86
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/commandline/ParsingEngine.java
@@ -0,0 +1,829 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.utils.commandline;
+
+import com.google.java.contract.Requires;
+import org.apache.commons.io.FileUtils;
+import org.apache.log4j.Logger;
+import org.broadinstitute.gatk.utils.Utils;
+import org.broadinstitute.gatk.utils.classloader.JVMUtils;
+import org.broadinstitute.gatk.utils.classloader.PluginManager;
+import org.broadinstitute.gatk.utils.collections.Pair;
+import org.broadinstitute.gatk.utils.exceptions.ReviewedGATKException;
+import org.broadinstitute.gatk.utils.exceptions.UserException;
+import org.broadinstitute.gatk.utils.help.ApplicationDetails;
+import org.broadinstitute.gatk.utils.help.HelpFormatter;
+
+import java.io.File;
+import java.io.IOException;
+import java.lang.annotation.Annotation;
+import java.lang.reflect.Field;
+import java.util.*;
+
+/**
+ * A parser for command-line arguments.
+ */
+public class ParsingEngine {
+
+    /**
+     * The loaded argument sources along with their back definitions.
+     */
+    private Map<ArgumentDefinition,ArgumentSource> argumentSourcesByDefinition = new HashMap<ArgumentDefinition,ArgumentSource>();
+
+    /**
+     * A list of defined arguments against which command lines are matched.
+     * Package protected for testing access.
+     */
+    public ArgumentDefinitions argumentDefinitions = new ArgumentDefinitions();
+
+    /**
+     * A list of matches from defined arguments to command-line text.
+     * Indicates as best as possible where command-line text remains unmatched
+     * to existing arguments.
+     */
+    private ArgumentMatches argumentMatches = null;
+
+    /**
+     * Techniques for parsing and for argument lookup.
+     */
+    private List<ParsingMethod> parsingMethods = new ArrayList<ParsingMethod>();
+
+    /**
+     * All of the RodBinding objects we've seen while parsing
+     */
+    private List<RodBinding> rodBindings = new ArrayList<RodBinding>();
+
+    /**
+     * Class reference to the different types of descriptors that the create method can create.
+     * The type of set used must be ordered (but not necessarily sorted).
+     */
+    private static final Set<ArgumentTypeDescriptor> STANDARD_ARGUMENT_TYPE_DESCRIPTORS = new LinkedHashSet<ArgumentTypeDescriptor>( Arrays.asList(new SimpleArgumentTypeDescriptor(),
+            new IntervalBindingArgumentTypeDescriptor(),
+            new RodBindingArgumentTypeDescriptor(),
+            new RodBindingCollectionArgumentTypeDescriptor(),
+            new CompoundArgumentTypeDescriptor(),
+            new MultiplexArgumentTypeDescriptor()) );
+
+    private Set<ArgumentTypeDescriptor> argumentTypeDescriptors = new LinkedHashSet<ArgumentTypeDescriptor>();
+
+    /**
+     * List of tags associated with the given instantiation of the command-line argument.
+     */
+    private final Map<Object,Tags> tags = new IdentityHashMap<Object,Tags>();
+
+    private PluginManager<ParsingEngineArgumentProvider> argumentProviderPluginManager =
+            new PluginManager<ParsingEngineArgumentProvider>(ParsingEngineArgumentProvider.class);
+
+    /**
+     * our log, which we want to capture anything from org.broadinstitute.gatk
+     */
+    protected static Logger logger = Logger.getLogger(ParsingEngine.class);
+
+    public ParsingEngine( CommandLineProgram clp ) {
+        RodBinding.resetNameCounter();
+        parsingMethods.add( ParsingMethod.FullNameParsingMethod );
+        parsingMethods.add( ParsingMethod.ShortNameParsingMethod );
+
+        // Order matters here!  Make sure the clp's new type descriptors go in before the original type descriptors.
+        if(clp != null)
+            argumentTypeDescriptors.addAll(clp.getArgumentTypeDescriptors());
+        argumentTypeDescriptors.addAll(STANDARD_ARGUMENT_TYPE_DESCRIPTORS);
+
+        List<Class<? extends ParsingEngineArgumentProvider>> providers = argumentProviderPluginManager.getPlugins();
+        for (Class<? extends ParsingEngineArgumentProvider> provider: providers) {
+            addArgumentSource(provider);
+        }
+    }
+
+    /**
+     * Add a main argument source.  Argument sources are expected to have
+     * any number of fields with an @Argument annotation attached.
+     * @param source     An argument source from which to extract command-line arguments.
+     */
+    public void addArgumentSource( Class source ) {
+        addArgumentSource(null, source);
+    }
+
+    public ArgumentMatches getArgumentMatches() {
+        return argumentMatches;
+    }
+
+    /**
+     * Add an argument source.  Argument sources are expected to have
+     * any number of fields with an @Argument annotation attached.
+     * @param sourceName name for this argument source.  'Null' indicates that this source should be treated
+     *                   as the main module.
+     * @param sourceClass A class containing argument sources from which to extract command-line arguments.
+     */
+    public void addArgumentSource( String sourceName, Class sourceClass ) {
+        List<ArgumentDefinition> argumentsFromSource = new ArrayList<ArgumentDefinition>();
+        for( ArgumentSource argumentSource: extractArgumentSources(sourceClass) ) {
+            List<ArgumentDefinition> argumentDefinitions = argumentSource.createArgumentDefinitions();
+            for(ArgumentDefinition argumentDefinition: argumentDefinitions) {
+                argumentSourcesByDefinition.put(argumentDefinition,argumentSource);
+                argumentsFromSource.add( argumentDefinition );
+            }
+        }
+        argumentDefinitions.add( new ArgumentDefinitionGroup(sourceName, argumentsFromSource) );
+    }
+
+    /**
+     * Do a cursory search to see if an argument with the given name is present.
+     * @param argumentFullName full name of the argument.
+     * @return True if the argument is present.  False otherwise.
+     */
+    public boolean isArgumentPresent( String argumentFullName ) {
+        ArgumentDefinition definition =
+                argumentDefinitions.findArgumentDefinition(argumentFullName,ArgumentDefinitions.FullNameDefinitionMatcher);
+        return argumentMatches.hasMatch(definition);
+
+    }
+
+    /**
+     * Parse the given set of command-line arguments, returning
+     * an ArgumentMatches object describing the best fit of these
+     * command-line arguments to the arguments that are actually
+     * required.
+     * @param tokens Tokens passed on the command line.
+     * @return The parsed arguments by file.
+     */
+    public SortedMap<ArgumentMatchSource, ParsedArgs> parse( String[] tokens ) {
+        argumentMatches = new ArgumentMatches();
+        SortedMap<ArgumentMatchSource, ParsedArgs> parsedArgs = new TreeMap<ArgumentMatchSource, ParsedArgs>();
+
+        List<String> cmdLineTokens = Arrays.asList(tokens);
+        parse(ArgumentMatchSource.COMMAND_LINE, cmdLineTokens, argumentMatches, parsedArgs);
+
+        List<ParsingEngineArgumentProvider> providers = argumentProviderPluginManager.createAllTypes();
+
+        for (ParsingEngineArgumentProvider provider: providers) {
+            // Load the arguments ONLY into the provider.
+            // Validation may optionally run on the rest of the arguments.
+            loadArgumentsIntoObject(provider);
+        }
+
+        for (ParsingEngineArgumentProvider provider: providers) {
+            provider.parse(this, parsedArgs);
+        }
+
+        return parsedArgs;
+    }
+
+    public void parse(ArgumentMatchSource matchSource, List<String> tokens,
+                         ArgumentMatches argumentMatches, SortedMap<ArgumentMatchSource, ParsedArgs> parsedArgs) {
+        ArgumentMatchSite lastArgumentMatchSite = new ArgumentMatchSite(matchSource, -1);
+
+        int i = 0;
+        for (String token: tokens) {
+            // If the token is of argument form, parse it into its own argument match.
+            // Otherwise, pair it with the most recently used argument discovered.
+            ArgumentMatchSite site = new ArgumentMatchSite(matchSource, i);
+            if( isArgumentForm(token) ) {
+                ArgumentMatch argumentMatch = parseArgument( token, site );
+                if( argumentMatch != null ) {
+                    argumentMatches.mergeInto( argumentMatch );
+                    lastArgumentMatchSite = site;
+                }
+            }
+            else {
+                if( argumentMatches.hasMatch(lastArgumentMatchSite) &&
+                        !argumentMatches.getMatch(lastArgumentMatchSite).hasValueAtSite(lastArgumentMatchSite))
+                    argumentMatches.getMatch(lastArgumentMatchSite).addValue( lastArgumentMatchSite, new ArgumentMatchStringValue(token) );
+                else
+                    argumentMatches.MissingArgument.addValue( site, new ArgumentMatchStringValue(token) );
+
+            }
+            i++;
+        }
+
+        parsedArgs.put(matchSource, new ParsedListArgs(tokens));
+    }
+
+    public void parsePairs(ArgumentMatchSource matchSource, List<Pair<String, ArgumentMatchValue>> tokens,
+                         ArgumentMatches argumentMatches, ParsedArgs matchSourceArgs,
+                         SortedMap<ArgumentMatchSource, ParsedArgs> parsedArgs) {
+        int i = 0;
+        for (Pair<String, ArgumentMatchValue> pair: tokens) {
+
+            ArgumentMatchSite site = new ArgumentMatchSite(matchSource, i);
+            List<DefinitionMatcher> matchers = Arrays.asList(ArgumentDefinitions.FullNameDefinitionMatcher, ArgumentDefinitions.ShortNameDefinitionMatcher);
+            ArgumentDefinition definition = null;
+            for (DefinitionMatcher matcher: matchers) {
+                definition = argumentDefinitions.findArgumentDefinition( pair.getFirst(), matcher );
+                if (definition != null)
+                    break;
+            }
+            if (definition == null)
+                continue;
+            ArgumentMatch argumentMatch = new ArgumentMatch(pair.getFirst(), definition, site, new Tags());
+            argumentMatches.mergeInto(argumentMatch);
+            argumentMatch.addValue(site, pair.getSecond());
+            i++;
+        }
+
+        parsedArgs.put(matchSource, matchSourceArgs);
+    }
+
+    protected List<String> getArguments(File file) {
+        try {
+            if (file.getAbsolutePath().endsWith(".list")) {
+                return getListArguments(file);
+            }
+        } catch (IOException e) {
+            throw new UserException.CouldNotReadInputFile(file, e);
+        }
+        throw new UserException.CouldNotReadInputFile(file, "file extension is not .list");
+    }
+
+    private List<String> getListArguments(File file) throws IOException {
+        ArrayList<String> argsList = new ArrayList<String>();
+        for (String line: FileUtils.readLines(file))
+            argsList.addAll(Arrays.asList(Utils.escapeExpressions(line)));
+        return argsList;
+    }
+
+    public enum ValidationType { MissingRequiredArgument,
+                                 InvalidArgument,
+                                 InvalidArgumentValue,
+                                 ValueMissingArgument,
+                                 TooManyValuesForArgument,
+                                 MutuallyExclusive }
+
+    /**
+     * Validates the list of command-line argument matches.
+     */
+    public void validate() {
+        validate( EnumSet.noneOf(ValidationType.class) );
+    }
+
+    /**
+     * Validates the list of command-line argument matches.  On failure throws an exception with detailed info about the
+     * particular failures.  Takes an EnumSet indicating which validation checks to skip.
+     * @param skipValidationOf List of validation checks to skip.
+     */
+    public void validate( EnumSet<ValidationType> skipValidationOf ) {
+        // Find missing required arguments.
+        if( !skipValidationOf.contains(ValidationType.MissingRequiredArgument) ) {
+            Collection<ArgumentDefinition> requiredArguments =
+                    argumentDefinitions.findArgumentDefinitions( true, ArgumentDefinitions.RequiredDefinitionMatcher );
+            Collection<ArgumentDefinition> missingArguments = new ArrayList<ArgumentDefinition>();
+            for( ArgumentDefinition requiredArgument: requiredArguments ) {
+                if( !argumentMatches.hasMatch(requiredArgument) )
+                    missingArguments.add( requiredArgument );
+            }
+
+            if( missingArguments.size() > 0 )
+                throw new MissingArgumentException( missingArguments );
+        }
+
+        // Find invalid arguments.  Invalid arguments will have a null argument definition.
+        if( !skipValidationOf.contains(ValidationType.InvalidArgument) ) {
+            ArgumentMatches invalidArguments = argumentMatches.findUnmatched();
+            if( invalidArguments.size() > 0 )
+                throw new InvalidArgumentException( invalidArguments );
+        }
+
+        // Find invalid argument values -- invalid arguments are either completely missing or fail the specified 'validation' regular expression.
+        if( !skipValidationOf.contains(ValidationType.InvalidArgumentValue) ) {
+            Collection<ArgumentDefinition> verifiableArguments = 
+                    argumentDefinitions.findArgumentDefinitions( null, ArgumentDefinitions.VerifiableDefinitionMatcher );
+            Collection<Pair<ArgumentDefinition,String>> invalidValues = new ArrayList<Pair<ArgumentDefinition,String>>();
+            for( ArgumentDefinition verifiableArgument: verifiableArguments ) {
+                ArgumentMatches verifiableMatches = argumentMatches.findMatches( verifiableArgument );
+                // Check to see whether an argument value was specified.  Argument values must be provided
+                // when the argument name is specified and the argument is not a flag type.
+                for(ArgumentMatch verifiableMatch: verifiableMatches) {
+                    ArgumentSource argumentSource = argumentSourcesByDefinition.get(verifiableArgument);
+                    if(verifiableMatch.values().size() == 0 && !verifiableArgument.isFlag && !argumentSource.createsTypeDefault())
+                        invalidValues.add(new Pair<ArgumentDefinition,String>(verifiableArgument,null));
+                }
+
+                // Ensure that the field contents meet the validation criteria specified by the regular expression.
+                for( ArgumentMatch verifiableMatch: verifiableMatches ) {
+                    for( ArgumentMatchValue value: verifiableMatch.values() ) {
+                        if( verifiableArgument.validation != null && !value.asString().matches(verifiableArgument.validation) )
+                            invalidValues.add( new Pair<ArgumentDefinition,String>(verifiableArgument, value.asString()) );
+                    }
+                }
+            }
+
+            if( invalidValues.size() > 0 )
+                throw new InvalidArgumentValueException( invalidValues );
+        }
+
+        // Find values without an associated mate.
+        if( !skipValidationOf.contains(ValidationType.ValueMissingArgument) ) {
+            if( argumentMatches.MissingArgument.values().size() > 0 )
+                throw new UnmatchedArgumentException( argumentMatches.MissingArgument );
+        }
+
+        // Find arguments with too many values.
+        if( !skipValidationOf.contains(ValidationType.TooManyValuesForArgument)) {
+            Collection<ArgumentMatch> overvaluedArguments = new ArrayList<ArgumentMatch>();
+            for( ArgumentMatch argumentMatch: argumentMatches.findSuccessfulMatches() ) {
+                // Warning: assumes that definition is not null (asserted by checks above).
+                if( !argumentMatch.definition.isMultiValued && argumentMatch.values().size() > 1 )
+                    overvaluedArguments.add(argumentMatch);
+            }
+
+            if( !overvaluedArguments.isEmpty() )
+                throw new TooManyValuesForArgumentException(overvaluedArguments);
+        }
+
+        // Find sets of options that are supposed to be mutually exclusive.
+        if( !skipValidationOf.contains(ValidationType.MutuallyExclusive)) {
+            Collection<Pair<ArgumentMatch,ArgumentMatch>> invalidPairs = new ArrayList<Pair<ArgumentMatch,ArgumentMatch>>();
+            for( ArgumentMatch argumentMatch: argumentMatches.findSuccessfulMatches() ) {
+                if( argumentMatch.definition.exclusiveOf != null ) {
+                    for( ArgumentMatch conflictingMatch: argumentMatches.findSuccessfulMatches() ) {
+                        // Skip over the current element.
+                        if( argumentMatch == conflictingMatch )
+                            continue;
+                        if( argumentMatch.definition.exclusiveOf.equals(conflictingMatch.definition.fullName) ||
+                            argumentMatch.definition.exclusiveOf.equals(conflictingMatch.definition.shortName))
+                            invalidPairs.add( new Pair<ArgumentMatch,ArgumentMatch>(argumentMatch, conflictingMatch) );
+                    }
+                }
+            }
+
+            if( !invalidPairs.isEmpty() )
+                throw new ArgumentsAreMutuallyExclusiveException( invalidPairs );
+        }
+    }
+
+    /**
+     * Loads a set of matched command-line arguments into the given object.
+     * @param object Object into which to add arguments.
+     */
+    public void loadArgumentsIntoObject( Object object ) {
+        loadArgumentsIntoObject(object, true);
+    }
+
+    /**
+     * Loads a set of matched command-line arguments into the given object.
+     * @param object Object into which to add arguments.
+     * @param enforceArgumentRanges If true, check that the argument value is within the range specified
+     *                              in the corresponding Argument annotation by min/max value attributes. This
+     *                              check is only performed for numeric types, and only when a min and/or
+     *                              max value is actually defined in the annotation. It is also only performed
+     *                              for values actually specified on the command line, and not for default values.
+     */
+    public void loadArgumentsIntoObject( Object object, boolean enforceArgumentRanges ) {
+        List<ArgumentSource> argumentSources = extractArgumentSources(object.getClass());
+
+        List<ArgumentSource> dependentArguments = new ArrayList<ArgumentSource>();
+
+        for( ArgumentSource argumentSource: argumentSources ) {
+            if(argumentSource.isDeprecated() && argumentMatches.findMatches(this,argumentSource).size() > 0)
+                notifyDeprecatedCommandLineArgument(argumentSource);
+
+            // If this argument source depends on other command-line arguments, skip it and make a note to process it later.
+            if(argumentSource.isDependent()) {
+                dependentArguments.add(argumentSource);
+                continue;
+            }
+            loadValueIntoObject(argumentSource, object, argumentMatches.findMatches(this,argumentSource), enforceArgumentRanges);
+        }
+
+        for(ArgumentSource dependentArgument: dependentArguments) {
+            MultiplexArgumentTypeDescriptor dependentDescriptor = dependentArgument.createDependentTypeDescriptor(this,object);
+            ArgumentSource dependentSource = dependentArgument.copyWithCustomTypeDescriptor(dependentDescriptor);
+            loadValueIntoObject(dependentSource,object,argumentMatches.findMatches(this,dependentSource), enforceArgumentRanges);
+        }
+    }
+
+    /**
+     * Notify the user that tags have been created.
+     * @param key The key created.
+     * @param tags List of tags, or empty list if no tags are present.
+     */
+    public void addTags(Object key, final Tags tags) {
+        this.tags.put(key,tags);        
+    }
+
+    /**
+     * Gets the tags associated with a given object.
+     * @param key Key for which to find a tag.
+     * @return List of tags associated with this key.
+     */
+    public Tags getTags(Object key)  {
+        if(!tags.containsKey(key))
+            return new Tags();
+        return tags.get(key);
+    }
+
+    /**
+     * Add a RodBinding type argument to this parser.  Called during parsing to allow
+     * us to track all of the RodBindings discovered in the command line.
+     * @param rodBinding the rodbinding to add.  Must not be added twice
+     */
+    @Requires("rodBinding != null")
+    public void addRodBinding(final RodBinding rodBinding) {
+        rodBindings.add(rodBinding);
+    }
+
+    /**
+     * Notify the user that a deprecated command-line argument has been used.
+     * @param argumentSource Deprecated argument source specified by user.
+     */
+    private void notifyDeprecatedCommandLineArgument(ArgumentSource argumentSource) {
+        // Grab the first argument definition and report that one as the failure.  Theoretically, we should notify of all failures.
+        List<ArgumentDefinition> definitions = argumentSource.createArgumentDefinitions();
+        if(definitions.size() < 1)
+            throw new ReviewedGATKException("Internal error.  Argument source creates no definitions.");
+        ArgumentDefinition definition = definitions.get(0);
+        throw new UserException.DeprecatedArgument(definition.fullName,definition.doc);
+    }
+
+    /**
+     * Loads a single argument into the object and that objects children.
+     * @param argumentMatches Argument matches to load into the object.
+     * @param source Argument source to load into the object.
+     * @param instance Object into which to inject the value.  The target might be in a container within the instance.
+     * @param enforceArgumentRanges If true, check that the argument value is within the range specified
+     *                              in the corresponding Argument annotation by min/max value attributes. This
+     *                              check is only performed for numeric types, and only when a min and/or
+     *                              max value is actually defined in the annotation. It is also only performed
+     *                              for values actually specified on the command line, and not for default values.
+     */
+    private void loadValueIntoObject( ArgumentSource source, Object instance, ArgumentMatches argumentMatches, boolean enforceArgumentRanges ) {
+        // Nothing to load
+        if( argumentMatches.size() == 0 && ! source.createsTypeDefault() )
+            return;
+
+        // Target instance into which to inject the value.
+        Collection<Object> targets = findTargets( source, instance );
+
+        // Abort if no home is found for the object.
+        if( targets.size() == 0 )
+            throw new ReviewedGATKException("Internal command-line parser error: unable to find a home for argument matches " + argumentMatches);
+
+        for( Object target: targets ) {
+            Object value;
+            boolean usedTypeDefault = false;
+            if ( argumentMatches.size() != 0 ) {
+                value = source.parse(this,argumentMatches);
+            }
+            else {
+                value = source.createTypeDefault(this);
+                usedTypeDefault = true;
+            }
+
+            // Only check argument ranges if a check was requested AND we used a value from the command line rather
+            // than the type default
+            if ( enforceArgumentRanges && ! usedTypeDefault ) {
+                checkArgumentRange(source, value);
+            }
+
+            JVMUtils.setFieldValue(source.field,target,value);
+        }
+    }
+
+    /**
+     * Check the provided value against any range constraints specified in the Argument annotation
+     * for the corresponding field. Throw an exception if hard limits are violated, or emit a warning
+     * if soft limits are violated.
+     *
+     * Only checks numeric types (int, double, etc.)
+     * Only checks fields with an actual @Argument annotation
+     * Only checks manually-specified constraints (there are no default constraints).
+     *
+     * @param argumentSource The source field for the command-line argument
+     * @param argumentValue The value we're considering putting in that source field
+     */
+    private void checkArgumentRange( final ArgumentSource argumentSource, final Object argumentValue ) {
+        // Only validate numeric types
+        if ( ! (argumentValue instanceof Number) ) {
+            return;
+        }
+        final double argumentDoubleValue = ((Number)argumentValue).doubleValue();
+
+        // Only validate fields with an @Argument annotation
+        final Annotation argumentAnnotation = argumentSource.field.getAnnotation(Argument.class);
+        if ( argumentAnnotation == null ) {
+            return;
+        }
+
+        final double minValue = (Double)CommandLineUtils.getValue(argumentAnnotation, "minValue");
+        final double maxValue = (Double)CommandLineUtils.getValue(argumentAnnotation, "maxValue");
+        final double minRecommendedValue = (Double)CommandLineUtils.getValue(argumentAnnotation, "minRecommendedValue");
+        final double maxRecommendedValue = (Double)CommandLineUtils.getValue(argumentAnnotation, "maxRecommendedValue");
+        final String argumentName = (String)CommandLineUtils.getValue(argumentAnnotation, "fullName");
+
+        // Check hard limits first, if specified
+        if ( minValue != Double.NEGATIVE_INFINITY && argumentDoubleValue < minValue ) {
+            throw new ArgumentValueOutOfRangeException(argumentName, argumentDoubleValue, minValue, "minimum");
+        }
+
+        if ( maxValue != Double.POSITIVE_INFINITY && argumentDoubleValue > maxValue ) {
+            throw new ArgumentValueOutOfRangeException(argumentName, argumentDoubleValue, maxValue, "maximum");
+        }
+
+        // Then check soft limits, if specified
+        if ( minRecommendedValue != Double.NEGATIVE_INFINITY && argumentDoubleValue < minRecommendedValue ) {
+            logger.warn(String.format("WARNING: argument --%s has value %.2f, but minimum recommended value is %.2f",
+                        argumentName, argumentDoubleValue, minRecommendedValue));
+        }
+
+        if ( maxRecommendedValue != Double.POSITIVE_INFINITY && argumentDoubleValue > maxRecommendedValue ) {
+            logger.warn(String.format("WARNING: argument --%s has value %.2f, but maximum recommended value is %.2f",
+                        argumentName, argumentDoubleValue, maxRecommendedValue));
+        }
+    }
+
+    public Collection<RodBinding> getRodBindings() {
+        return Collections.unmodifiableCollection(rodBindings);
+    }
+
+    /**
+     * Gets a collection of the container instances of the given type stored within the given target.
+     * @param source Argument source.
+     * @param instance Container.
+     * @return A collection of containers matching the given argument source.
+     */
+    private Collection<Object> findTargets(ArgumentSource source, Object instance) {
+        LinkedHashSet<Object> targets = new LinkedHashSet<Object>();
+        for( Class clazz = instance.getClass(); clazz != null; clazz = clazz.getSuperclass() ) {
+            for( Field field: clazz.getDeclaredFields() ) {
+                if( field.equals(source.field) ) {
+                    targets.add(instance);
+                } else if( field.isAnnotationPresent(ArgumentCollection.class) ) {
+                    targets.addAll(findTargets(source, JVMUtils.getFieldValue(field, instance)));
+                }
+            }
+        }
+        return targets;
+    }
+
+    /**
+     * Prints out the help associated with these command-line argument definitions.
+     * @param applicationDetails Details about the specific GATK-based application being run.
+     */
+    public void printHelp( ApplicationDetails applicationDetails ) {
+        new HelpFormatter().printHelp(applicationDetails,argumentDefinitions);
+    }
+
+    /**
+     * Extract all the argument sources from a given object.
+     * @param sourceClass class to act as sources for other arguments.
+     * @return A list of sources associated with this object and its aggregated objects.
+     */
+    public List<ArgumentSource> extractArgumentSources(Class sourceClass) {
+        return extractArgumentSources(sourceClass, new Field[0]);
+    }
+
+    /**
+     * Fetch the best command-line argument descriptor for the given class.
+     * @param type Class for which to specify a descriptor.
+     * @return descriptor for the given type.
+     */
+    public ArgumentTypeDescriptor selectBestTypeDescriptor(Class type) {
+        return ArgumentTypeDescriptor.selectBest(argumentTypeDescriptors,type);
+    }
+
+    private List<ArgumentSource> extractArgumentSources(Class sourceClass, Field[] parentFields) {
+        // now simply call into the truly general routine extract argument bindings but with a null
+        // object so bindings aren't computed
+        Map<ArgumentSource, Object> bindings = extractArgumentBindings(null, sourceClass, parentFields);
+        return new ArrayList<ArgumentSource>(bindings.keySet());
+    }
+
+    public Map<ArgumentSource, Object> extractArgumentBindings(Object obj) {
+        if ( obj == null ) throw new IllegalArgumentException("Incoming object cannot be null");
+        return extractArgumentBindings(obj, obj.getClass(), new Field[0]);
+    }
+
+    /**
+     * Extract all the argument sources from a given object, along with their bindings if obj != null .
+     * @param obj the object corresponding to the sourceClass
+     * @param sourceClass class to act as sources for other arguments.
+     * @param parentFields Parent Fields
+     * @return A map of sources associated with this object and its aggregated objects and bindings to their bindings values
+     */
+    private Map<ArgumentSource, Object> extractArgumentBindings(Object obj, Class sourceClass, Field[] parentFields) {
+        Map<ArgumentSource, Object> bindings = new LinkedHashMap<ArgumentSource, Object>();
+
+        while( sourceClass != null ) {
+            Field[] fields = sourceClass.getDeclaredFields();
+            for( Field field: fields ) {
+                if( ArgumentTypeDescriptor.isArgumentAnnotationPresent(field) ) {
+                    Object val = obj != null ? JVMUtils.getFieldValue(field, obj) : null;
+                    bindings.put( new ArgumentSource(parentFields, field, selectBestTypeDescriptor(field.getType())), val );
+                }
+                if( field.isAnnotationPresent(ArgumentCollection.class) ) {
+                    Object val = obj != null ? JVMUtils.getFieldValue(field, obj) : null;
+                    Field[] newParentFields = Arrays.copyOf(parentFields, parentFields.length + 1);
+                    newParentFields[parentFields.length] = field;
+                    bindings.putAll( extractArgumentBindings(val, field.getType(), newParentFields) );
+                }
+            }
+
+            sourceClass = sourceClass.getSuperclass();
+        }
+
+        return bindings;
+    }
+
+    /**
+     * Determines whether a token looks like the name of an argument.
+     * @param token Token to inspect.  Can be surrounded by whitespace.
+     * @return True if token is of short name form.
+     */
+    private boolean isArgumentForm( String token ) {
+        for( ParsingMethod parsingMethod: parsingMethods ) {
+            if( parsingMethod.matches(token) )
+                return true;
+        }
+
+        return false;
+    }
+
+    /**
+     * Parse a short name into an ArgumentMatch.
+     * @param token The token to parse.  The token should pass the isLongArgumentForm test.
+     * @param position The position of the token in question.
+     * @return ArgumentMatch associated with this token, or null if no match exists.
+     */    
+    private ArgumentMatch parseArgument( String token, ArgumentMatchSite position ) {
+        if( !isArgumentForm(token) )
+            throw new IllegalArgumentException( "Token is not recognizable as an argument: " + token );
+
+        for( ParsingMethod parsingMethod: parsingMethods ) {
+            if( parsingMethod.matches( token ) )
+                return parsingMethod.match( argumentDefinitions, token, position );
+        }
+
+        // No parse results found.
+        return null;
+    }
+}
+
+/**
+ * An exception indicating that some required arguments are missing.
+ */
+class MissingArgumentException extends ArgumentException {
+    public MissingArgumentException( Collection<ArgumentDefinition> missingArguments ) {
+        super( formatArguments(missingArguments) );
+    }
+
+    private static String formatArguments( Collection<ArgumentDefinition> missingArguments ) {
+        StringBuilder sb = new StringBuilder();
+        for( ArgumentDefinition missingArgument: missingArguments ) {
+            if( missingArgument.shortName != null )
+                sb.append( String.format("%nArgument with name '--%s' (-%s) is missing.", missingArgument.fullName, missingArgument.shortName) );
+            else
+                sb.append( String.format("%nArgument with name '--%s' is missing.", missingArgument.fullName) );
+        }
+        return sb.toString();
+    }
+}
+
+/**
+ * An exception for undefined arguments.
+ */
+class InvalidArgumentException extends ArgumentException {
+    public InvalidArgumentException( ArgumentMatches invalidArguments ) {
+        super( formatArguments(invalidArguments) );
+    }
+
+    private static String formatArguments( ArgumentMatches invalidArguments ) {
+        StringBuilder sb = new StringBuilder();
+        for( ArgumentMatch invalidArgument: invalidArguments )
+            sb.append( String.format("%nArgument with name '%s' isn't defined.", invalidArgument.label) );
+        return sb.toString();
+    }
+}
+
+/**
+ * An exception for values whose format is invalid.
+ */
+class InvalidArgumentValueException extends ArgumentException {
+    public InvalidArgumentValueException( Collection<Pair<ArgumentDefinition,String>> invalidArgumentValues ) {
+        super( formatArguments(invalidArgumentValues) );
+    }
+
+    private static String formatArguments( Collection<Pair<ArgumentDefinition,String>> invalidArgumentValues ) {
+        StringBuilder sb = new StringBuilder();
+        for( Pair<ArgumentDefinition,String> invalidValue: invalidArgumentValues ) {
+            if(invalidValue.getSecond() == null)
+                sb.append( String.format("%nArgument '--%s' requires a value but none was provided",
+                                         invalidValue.first.fullName) );
+            else
+                sb.append( String.format("%nArgument '--%s' has value of incorrect format: %s (should match %s)",
+                        invalidValue.first.fullName,
+                        invalidValue.second,
+                        invalidValue.first.validation) );
+        }
+        return sb.toString();
+    }
+}
+
+class ArgumentValueOutOfRangeException extends ArgumentException {
+    public ArgumentValueOutOfRangeException( final String argumentName, final double argumentActualValue,
+                                             final double argumentBoundaryValue, final String argumentBoundaryType ) {
+        super(String.format("Argument --%s has value %.2f, but %s allowed value is %.2f",
+                            argumentName, argumentActualValue, argumentBoundaryType, argumentBoundaryValue));
+    }
+}
+
+/**
+ * An exception for values that can't be mated with any argument.
+ */
+class UnmatchedArgumentException extends ArgumentException {
+    public UnmatchedArgumentException( ArgumentMatch invalidValues ) {
+        super( formatArguments(invalidValues) );
+    }
+
+    private static String formatArguments( ArgumentMatch invalidValues ) {
+        StringBuilder sb = new StringBuilder();
+        for( ArgumentMatchSite site: invalidValues.sites.keySet() )
+            for( ArgumentMatchValue value: invalidValues.sites.get(site) ) {
+                switch (site.getSource().getType()) {
+                    case CommandLine:
+                        sb.append( String.format("%nInvalid argument value '%s' at position %d.",
+                                value.asString(), site.getIndex()) );
+                        break;
+                    case Provider:
+                        sb.append( String.format("%nInvalid argument value '%s' in %s at position %d.",
+                                value.asString(), site.getSource().getDescription(), site.getIndex()) );
+                        break;
+                    default:
+                        throw new RuntimeException( String.format("Unexpected argument match source type: %s",
+                                site.getSource().getType()));
+                }
+                if(value.asString() != null && Utils.dupString(' ',value.asString().length()).equals(value.asString()))
+                    sb.append("  Please make sure any line continuation backslashes on your command line are not followed by whitespace.");
+            }
+        return sb.toString();
+    }
+}
+
+/**
+ * An exception indicating that too many values have been provided for the given argument.
+ */
+class TooManyValuesForArgumentException extends ArgumentException {
+    public TooManyValuesForArgumentException( Collection<ArgumentMatch> arguments ) {
+        super( formatArguments(arguments) );
+    }
+
+    private static String formatArguments( Collection<ArgumentMatch> arguments ) {
+        StringBuilder sb = new StringBuilder();
+        for( ArgumentMatch argument: arguments )
+            sb.append( String.format("%nArgument '%s' has too many values: %s.", argument.label, Arrays.deepToString(argument.values().toArray())) );
+        return sb.toString();
+    }
+}
+
+/**
+ * An exception indicating that mutually exclusive options have been passed in the same command line.
+ */
+class ArgumentsAreMutuallyExclusiveException extends ArgumentException {
+    public ArgumentsAreMutuallyExclusiveException( Collection<Pair<ArgumentMatch,ArgumentMatch>> arguments ) {
+        super( formatArguments(arguments) );
+    }
+
+    private static String formatArguments( Collection<Pair<ArgumentMatch,ArgumentMatch>> arguments ) {
+        StringBuilder sb = new StringBuilder();
+        for( Pair<ArgumentMatch,ArgumentMatch> argument: arguments )
+            sb.append( String.format("%nArguments '%s' and '%s' are mutually exclusive.", argument.first.definition.fullName, argument.second.definition.fullName ) );
+        return sb.toString();
+    }
+
+}
+
+
+/**
+ * An exception for when an argument doesn't match an of the enumerated options for that var type
+ */
+class UnknownEnumeratedValueException extends ArgumentException {
+    public UnknownEnumeratedValueException(ArgumentDefinition definition, String argumentPassed) {
+        super( formatArguments(definition,argumentPassed) );
+    }
+
+    private static String formatArguments(ArgumentDefinition definition, String argumentPassed) {
+        return String.format("Invalid value %s specified for argument %s; valid options are (%s).", argumentPassed, definition.fullName, Utils.join(",",definition.validOptions));
+    }
+}
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/commandline/ParsingEngineArgumentFiles.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/commandline/ParsingEngineArgumentFiles.java
new file mode 100644
index 0000000..0361c4c
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/commandline/ParsingEngineArgumentFiles.java
@@ -0,0 +1,55 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.utils.commandline;
+
+import java.io.File;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.SortedMap;
+
+/**
+ * Container class to store the list of argument files.
+ * The files will be parsed after the command line arguments.
+ */
+public class ParsingEngineArgumentFiles extends ParsingEngineArgumentProvider {
+    @Argument(fullName = "arg_file", shortName = "args", doc = "Reads arguments from the specified file", required = false)
+    public List<File> files = new ArrayList<File>();
+
+    @Override
+    public void parse(ParsingEngine parsingEngine, SortedMap<ArgumentMatchSource, ParsedArgs> parsedArgs) {
+        ArgumentMatches argumentMatches = parsingEngine.getArgumentMatches();
+        for (File file: this.files) {
+            List<String> fileTokens = parsingEngine.getArguments(file);
+            parsingEngine.parse(new ArgumentMatchFileSource(file), fileTokens, argumentMatches, parsedArgs);
+        }
+    }
+}
+
+class ArgumentMatchFileSource extends ArgumentMatchSource {
+    ArgumentMatchFileSource(File file) {
+        super("file " + file.getAbsolutePath());
+    }
+}
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/commandline/ParsingEngineArgumentProvider.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/commandline/ParsingEngineArgumentProvider.java
new file mode 100644
index 0000000..d53a36c
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/commandline/ParsingEngineArgumentProvider.java
@@ -0,0 +1,37 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.utils.commandline;
+
+import java.util.List;
+import java.util.SortedMap;
+
+/**
+ * A class that can parse arguments for the engine
+ */
+public abstract class ParsingEngineArgumentProvider {
+    public abstract void parse(ParsingEngine parsingEngine, SortedMap<ArgumentMatchSource, ParsedArgs> parsedArgs);
+}
+
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/commandline/ParsingMethod.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/commandline/ParsingMethod.java
new file mode 100644
index 0000000..a939742
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/commandline/ParsingMethod.java
@@ -0,0 +1,127 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.utils.commandline;
+
+import org.broadinstitute.gatk.utils.Utils;
+
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+/**
+ * Holds a pattern, along with how to get to the argument definitions that could match that pattern.
+ */
+public abstract class ParsingMethod {
+    private final Pattern pattern;
+    private final DefinitionMatcher definitionMatcher;
+
+    /**
+     * Create a new parsing method with the given identifying / validating pattern and definition matcher.
+     * @param pattern The pattern
+     * @param definitionMatcher The definition matcher.
+     */
+    private ParsingMethod( Pattern pattern, DefinitionMatcher definitionMatcher ) {
+        this.pattern = pattern;
+        this.definitionMatcher = definitionMatcher;
+    }
+
+    /**
+     * Can the given token be parsed by this parsing method?
+     * @param token Token to validate.
+     * @return True if the given token matches.
+     */
+    public boolean matches( String token ) {
+        Matcher matcher = pattern.matcher(token);
+        return matcher.matches();        
+    }
+
+    /**
+     * Find the best match for a given token at a given position from among the provided
+     * argument definitions.
+     * @param definitions List of argument definitions.
+     * @param token The token from the command line to match.  Should be validated using
+     *              ParsingMethod's matches() tester.
+     * @param position Position at which this command-line argument occurs.  Will be used
+     *                 for validation later.
+     * @return An argument match.  Definition field will be populated if a match was found or
+     *         empty if no appropriate definition could be found. 
+     */
+    public ArgumentMatch match( ArgumentDefinitions definitions, String token, ArgumentMatchSite position ) {
+        // If the argument is valid, parse out the argument.
+        Matcher matcher = pattern.matcher(token);
+
+        // Didn't match?  Must be bad input.
+        if( !matcher.matches() )
+            throw new IllegalArgumentException( String.format("Unable to parse token %s with pattern %s", token, pattern.pattern()) );
+
+        String argument = matcher.group(1).trim();
+
+        Tags tags = parseTags(argument, matcher.group(2));
+
+        // Find the most appropriate argument definition for the given argument.
+        ArgumentDefinition argumentDefinition = definitions.findArgumentDefinition( argument, definitionMatcher );
+
+        // Try to find a matching argument.  If found, label that as the match.  If not found, add the argument
+        // with a null definition.
+        return new ArgumentMatch(argument,argumentDefinition,position,tags);
+    }
+
+    public static Tags parseTags(String argument, String tagString) {
+        Tags tags = new Tags();
+        if (tagString != null) {
+            for(String tag: Utils.split(tagString, ",")) {
+                // Check for presence of an '=' sign, indicating a key-value pair in the tag line.
+                int equalDelimiterPos = tag.indexOf('=');
+                if(equalDelimiterPos >= 0) {
+                    // Sanity check; ensure that there aren't multiple '=' in this key-value pair.
+                    if(tag.indexOf('=',equalDelimiterPos+1) >= 0)
+                        throw new ArgumentException(String.format("Tag %s passed to argument %s is malformed.  Please ensure that " +
+                                "key-value tags are of the form <key>=<value>, and neither key " +
+                                "nor value contain the '=' character", tag, argument));
+                    tags.addKeyValueTag(tag.substring(0,equalDelimiterPos),tag.substring(equalDelimiterPos+1));
+                }
+                else
+                    tags.addPositionalTag(tag);
+
+            }
+        }
+        return tags;
+    }
+
+    /**
+     * A command-line argument always starts with an alphabetical character or underscore followed by any word character.
+     */
+    private static final String ARGUMENT_TEXT = "[A-Za-z_][\\w\\-\\.]*";
+
+    /**
+     * Tags, on the other hand, can start with any word character.
+     */
+    private static final String TAG_TEXT = "[\\w\\-\\.\\=]*";
+
+    public static final ParsingMethod FullNameParsingMethod = new ParsingMethod(Pattern.compile(String.format("\\s*--(%1$s)(?:\\:(%2$s(?:,%2$s)*))?\\s*",ARGUMENT_TEXT,TAG_TEXT)),
+                                                                          ArgumentDefinitions.FullNameDefinitionMatcher) {};
+    public static final ParsingMethod ShortNameParsingMethod = new ParsingMethod(Pattern.compile(String.format("\\s*-(%1$s)(?:\\:(%2$s(?:,%2$s)*))?\\s*",ARGUMENT_TEXT,TAG_TEXT)),
+                                                                           ArgumentDefinitions.ShortNameDefinitionMatcher) {};
+}
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/commandline/RodBinding.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/commandline/RodBinding.java
new file mode 100644
index 0000000..2c55787
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/commandline/RodBinding.java
@@ -0,0 +1,197 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.utils.commandline;
+
+import com.google.java.contract.Ensures;
+import com.google.java.contract.Requires;
+import htsjdk.tribble.Feature;
+
+import java.util.*;
+
+/**
+ * A RodBinding represents a walker argument that gets bound to a ROD track.
+ *
+ * The RodBinding<T> is a formal GATK argument that bridges between a walker and
+ * the RefMetaDataTracker to obtain data about this rod track at runtime.  The RodBinding
+ * is explicitly typed with type of the Tribble.Feature expected to be produced by this
+ * argument.  The GATK Engine takes care of initializing the binding and connecting it
+ * to the RMD system.
+ *
+ * It is recommended that optional RodBindings be initialized to the value returned
+ * by the static method makeUnbound().
+ *
+ * Note that this class is immutable.
+ */
+public final class RodBinding<T extends Feature> {
+    protected final static String UNBOUND_VARIABLE_NAME = "";
+    protected final static String UNBOUND_SOURCE = "UNBOUND";
+    protected final static String UNBOUND_TRIBBLE_TYPE = "";
+
+    /**
+     * Create an unbound Rodbinding of type.  This is the correct programming
+     * style for an optional RodBinding<T>
+     *
+     *     At Input()
+     *     RodBinding<T> x = RodBinding.makeUnbound(T.class)
+     *
+     * The unbound binding is guaranteed to never match any binding.  It uniquely
+     * returns false to isBound().
+     *
+     * @param type the Class type produced by this unbound object
+     * @param <T> any class extending Tribble Feature
+     * @return the UNBOUND RodBinding producing objects of type T
+     */
+    @Requires("type != null")
+    protected final static <T extends Feature> RodBinding<T> makeUnbound(Class<T> type) {
+        return new RodBinding<T>(type);
+    }
+
+    /** The name of this binding.  Often the name of the field itself, but can be overridden on cmdline */
+    final private String name;
+    /** where the data for this ROD is coming from.  A file or special value if coming from stdin */
+    final private String source;
+    /** the string name of the tribble type, such as vcf, bed, etc. */
+    final private String tribbleType;
+    /** The command line tags associated with this RodBinding */
+    final private Tags tags;
+    /** The Java class expected for this RodBinding.  Must correspond to the type emitted by Tribble */
+    final private Class<T> type;
+    /** True for all RodBindings except the special UNBOUND binding, which is the default for optional arguments */
+    final private boolean bound;
+
+    /**
+     * The name counter.  This is how we create unique names for collections of RodBindings
+     * on the command line.  If you have provide the GATK with -X file1 and -X file2 to a
+     * RodBinding argument as List<RodBinding<T>> then each binding will receive automatically
+     * the name of X and X2.
+     */
+    final private static Map<String, Integer> nameCounter = new HashMap<String, Integer>();
+
+    /** for UnitTests */
+    final public static void resetNameCounter() {
+        nameCounter.clear();
+    }
+
+    @Requires("rawName != null")
+    @Ensures("result != null")
+    final private static synchronized String countedVariableName(final String rawName) {
+        Integer count = nameCounter.get(rawName);
+        if ( count == null ) {
+            nameCounter.put(rawName, 1);
+            return rawName;
+        } else {
+            nameCounter.put(rawName, count + 1);
+            return rawName + (count + 1);
+        }
+    }
+
+    @Requires({"type != null", "rawName != null", "source != null", "tribbleType != null", "tags != null"})
+    public RodBinding(Class<T> type, final String rawName, final String source, final String tribbleType, final Tags tags) {
+        this.type = type;
+        this.name = countedVariableName(rawName);
+        this.source = source;
+        this.tribbleType = tribbleType;
+        this.tags = tags;
+        this.bound = true;
+    }
+
+    /**
+     * For testing purposes only.  Creates a RodBinding sufficient for looking up associations to rawName
+     * @param type
+     * @param rawName
+     */
+    public RodBinding(Class<T> type, final String rawName) {
+        this(type, rawName, "missing", type.getSimpleName(), new Tags());
+    }
+
+    /**
+     * Make an unbound RodBinding<T>.  Only available for creating the globally unique UNBOUND object
+     * @param type class this unbound RodBinding creates
+     */
+    @Requires({"type != null"})
+    private RodBinding(Class<T> type) {
+        this.type = type;
+        this.name = UNBOUND_VARIABLE_NAME;  // special value can never be found in RefMetaDataTracker
+        this.source = UNBOUND_SOURCE;
+        this.tribbleType = UNBOUND_TRIBBLE_TYPE;
+        this.tags = new Tags();
+        this.bound = false;
+    }
+
+
+   /**
+     * @return True for all RodBindings except the special UNBOUND binding, which is the default for optional arguments
+     */
+    final public boolean isBound() {
+        return bound;
+    }
+
+    /**
+     * @return The name of this binding.  Often the name of the field itself, but can be overridden on cmdline
+     */
+    @Ensures({"result != null"})
+    final public String getName() {
+        return name;
+    }
+
+    /**
+     * @return the string name of the tribble type, such as vcf, bed, etc.
+     */
+    @Ensures({"result != null"})
+    final public Class<T> getType() {
+        return type;
+    }
+
+    /**
+     * @return where the data for this ROD is coming from.  A file or special value if coming from stdin
+     */
+    @Ensures({"result != null"})
+    final public String getSource() {
+        return source;
+    }
+
+    /**
+     * @return The command line tags associated with this RodBinding.  Will include the tags used to
+     * determine the name and type of this RodBinding
+     */
+    @Ensures({"result != null"})
+    final public Tags getTags() {
+        return tags;
+    }
+
+    /**
+     * @return The Java class expected for this RodBinding.  Must correspond to the type emited by Tribble
+     */
+    @Ensures({"result != null"})
+    final public String getTribbleType() {
+        return tribbleType;
+    }
+
+    @Override
+    public String toString() {
+        return String.format("(RodBinding name=%s source=%s)", getName(), getSource());
+    }
+}
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/commandline/RodBindingCollection.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/commandline/RodBindingCollection.java
new file mode 100644
index 0000000..faf4565
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/commandline/RodBindingCollection.java
@@ -0,0 +1,89 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.utils.commandline;
+
+import com.google.java.contract.Ensures;
+import htsjdk.tribble.Feature;
+import org.broadinstitute.gatk.utils.exceptions.UserException;
+
+import java.lang.reflect.Constructor;
+import java.lang.reflect.InvocationTargetException;
+import java.util.*;
+
+/**
+ * A RodBindingCollection represents a collection of RodBindings.
+ *
+ * The RodBindingCollection<T> is a formal GATK argument that is used to specify a file of RodBindings.
+ *
+ */
+public final class RodBindingCollection<T extends Feature> {
+
+    /** The Java class expected for this RodBinding.  Must correspond to the type emitted by Tribble */
+    final private Class<T> type;
+
+    private Collection<RodBinding<T>> rodBindings;
+
+    public RodBindingCollection(final Class<T> type, final Collection<RodBinding<T>> rodBindings) {
+        this.type = type;
+        this.rodBindings = Collections.unmodifiableCollection(rodBindings);
+    }
+
+    /**
+     * @return the collection of RodBindings
+     */
+    final public Collection<RodBinding<T>> getRodBindings() {
+        return rodBindings;
+    }
+
+    /**
+     * @return the string name of the tribble type, such as vcf, bed, etc.
+     */
+    @Ensures({"result != null"})
+    final public Class<T> getType() {
+        return type;
+    }
+
+    @Override
+    public String toString() {
+        return String.format("(RodBindingCollection %s)", getRodBindings());
+    }
+
+    /**
+     * Utility method to help construct a RodBindingCollection of the given Feature type
+     *
+     * @param type         the Feature type
+     * @param rodBindings  the rod bindings to put into the collection
+     * @return a new RodBindingCollection object
+     */
+    public static Object createRodBindingCollectionOfType(final Class<? extends Feature> type, final Collection<RodBinding> rodBindings) {
+        try {
+            final Constructor ctor = RodBindingCollection.class.getConstructor(Class.class, Collection.class);
+            return ctor.newInstance(type, rodBindings);
+        } catch (final Exception e) {
+            throw new IllegalStateException("Failed to create a RodBindingCollection for type " + type);
+        }
+    }
+}
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/commandline/Tags.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/commandline/Tags.java
new file mode 100644
index 0000000..2b1c7f7
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/commandline/Tags.java
@@ -0,0 +1,112 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.utils.commandline;
+
+import java.util.*;
+
+/**
+ * Models the tags that can appear after command-line arguments
+ * in the GATK.
+ */
+public class Tags {
+    /**
+     * Storage for the ordered, unkeyed, positional tags.
+     */
+    private final List<String> positionalTags = new ArrayList<String>();
+
+    /**
+     * Storage for key-value tags of the form <key>=<value>
+     */
+    private Map<String,String> keyValueTags = new HashMap<String,String>();
+
+    /**
+     * Tests to see whether two tag sets are equal.
+     * @param other Other object to test for equality.
+     * @return True if objects are the same.  False if objects differ.
+     */
+    @Override
+    public boolean equals(Object other) {
+        if(other == null)
+            return false;
+
+        if(!(other instanceof Tags))
+            return false;
+
+        Tags otherTags = (Tags)other;
+        return this.positionalTags.equals(otherTags.positionalTags) && this.keyValueTags.equals(otherTags.keyValueTags);
+    }
+
+    /**
+     * Returns whether any tags are specified on the command-line for this operation.
+     * @return True if the tags are empty; false otherwise.
+     */
+    public boolean isEmpty() {
+        return positionalTags.isEmpty() && keyValueTags.isEmpty();
+    }
+
+    /**
+     * Retrieves the list of all positional tags associated with this argument.
+     * @return A list of positional tags.
+     */
+    public List<String> getPositionalTags() {
+        return Collections.unmodifiableList(positionalTags);
+    }
+
+    /**
+     * Gets the value associated with a given <key>=<value> argument tag.
+     * @param key The key for which to retrieve the value.
+     * @return The value paired with the given key, or null if no such element exists.
+     */
+    public String getValue(final String key) {
+        return keyValueTags.get(key);
+    }
+
+    /**
+     * Returns true if tags contains given key
+     * @param key The key for which to check existence.
+     * @return true if tags contains given key
+     */
+    public boolean containsKey(final String key) {
+        return keyValueTags.containsKey(key);
+    }
+
+    /**
+     * Adds positional tag(s) to the tag object.
+     * @param tags The tag strings to add.
+     */
+    protected void addPositionalTag(final String... tags) {
+        positionalTags.addAll(Arrays.asList(tags));
+    }
+
+    /**
+     * Adds a <key>-<value> tag to this tag library.
+     * @param key key tag to add.
+     * @param value value to associate with this key.
+     */
+    protected void addKeyValueTag(final String key, final String value) {
+        keyValueTags.put(key,value);
+    }
+}
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/commandline/package-info.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/commandline/package-info.java
new file mode 100644
index 0000000..f572d34
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/commandline/package-info.java
@@ -0,0 +1,26 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.utils.commandline;
\ No newline at end of file
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/crypt/CryptUtils.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/crypt/CryptUtils.java
new file mode 100644
index 0000000..d6ccd32
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/crypt/CryptUtils.java
@@ -0,0 +1,391 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.utils.crypt;
+
+import org.broadinstitute.gatk.utils.exceptions.ReviewedGATKException;
+import org.broadinstitute.gatk.utils.io.IOUtils;
+
+import javax.crypto.Cipher;
+import java.io.File;
+import java.io.InputStream;
+import java.security.*;
+import java.security.spec.InvalidKeySpecException;
+import java.security.spec.KeySpec;
+import java.security.spec.PKCS8EncodedKeySpec;
+import java.security.spec.X509EncodedKeySpec;
+import java.util.Arrays;
+
+/**
+ * A set of cryptographic utility methods and constants.
+ *
+ * Contains methods to:
+ *
+ * -Create a public/private key pair
+ * -Read and write public/private keys to/from files/streams
+ * -Load the GATK master private/public keys
+ * -Encrypt/decrypt data
+ *
+ * Also contains constants that control the cryptographic defaults
+ * throughout the GATK.
+ *
+ * @author David Roazen
+ */
+public class CryptUtils {
+
+    // ---------------------------------------------------------------------------------
+    // Constants (these control the default cryptographic settings throughout the GATK):
+    // ---------------------------------------------------------------------------------
+
+    /**
+     * Default key length in bits of newly-created keys. 2048 bits provides a good balance between
+     * security and speed.
+     */
+    public static final int DEFAULT_KEY_LENGTH = 2048;
+
+    /**
+     * Default encryption algorithm to use, when none is specified.
+     */
+    public static final String DEFAULT_ENCRYPTION_ALGORITHM = "RSA";
+
+    /**
+     * Default random-number generation algorithm to use, when none is specified.
+     */
+    public static final String DEFAULT_RANDOM_NUMBER_GENERATION_ALGORITHM = "SHA1PRNG";
+
+    /**
+     * Name of the public key file distributed with the GATK. This file is packaged
+     * into the GATK jar, and we use the system ClassLoader to find it.
+     */
+    public static final String GATK_DISTRIBUTED_PUBLIC_KEY_FILE_NAME = "GATK_public.key";
+
+    /**
+     * Location of the master copy of the GATK private key.
+     */
+    public static final String GATK_MASTER_PRIVATE_KEY_FILE = "/humgen/gsa-hpprojects/GATK/data/gatk_master_keys/GATK_private.key";
+
+    /**
+     * Location of the master copy of the GATK public key. This file should always be the same as
+     * the public key file distributed with the GATK (and there are automated tests to ensure that it is).
+     */
+    public static final String GATK_MASTER_PUBLIC_KEY_FILE =  "/humgen/gsa-hpprojects/GATK/data/gatk_master_keys/GATK_public.key";
+
+    /**
+     * Directory where generated GATK user keys are stored. See the GATKKey class for more information.
+     */
+    public static final String GATK_USER_KEY_DIRECTORY =      "/humgen/gsa-hpprojects/GATK/data/gatk_user_keys/";
+
+
+    // -----------------------
+    // Utility Methods:
+    // -----------------------
+
+    /**
+     * Generate a new public/private key pair using the default encryption settings defined above.
+     *
+     * @return A new public/private key pair created using the default settings
+     */
+    public static KeyPair generateKeyPair() {
+        return generateKeyPair(DEFAULT_KEY_LENGTH, DEFAULT_ENCRYPTION_ALGORITHM, DEFAULT_RANDOM_NUMBER_GENERATION_ALGORITHM);
+    }
+
+    /**
+     * Generate a new public/private key pair using custom encryption settings.
+     *
+     * @param keyLength Length of the key in bits
+     * @param encryptionAlgorithm Encryption algorithm to use
+     * @param randNumberAlgorithm Random-number generation algorithm to use
+     * @return A new public/private key pair, created according to the specified parameters
+     */
+    public static KeyPair generateKeyPair( int keyLength, String encryptionAlgorithm, String randNumberAlgorithm ) {
+        try {
+            KeyPairGenerator keyGen = KeyPairGenerator.getInstance(encryptionAlgorithm);
+            SecureRandom randomnessSource = createRandomnessSource(randNumberAlgorithm);
+
+            keyGen.initialize(keyLength, randomnessSource);
+            return keyGen.generateKeyPair();
+        }
+        catch ( NoSuchAlgorithmException e ) {
+            throw new ReviewedGATKException(String.format("Could not find an implementation of the requested encryption algorithm %s", encryptionAlgorithm), e);
+        }
+        catch ( Exception e ) {
+            throw new ReviewedGATKException("Error while generating key pair", e);
+        }
+    }
+
+    /**
+     * Create a source of randomness using the default random-number generation algorithm.
+     *
+     * @return A randomness source that uses the default algorithm
+     */
+    public static SecureRandom createRandomnessSource() {
+        return createRandomnessSource(DEFAULT_RANDOM_NUMBER_GENERATION_ALGORITHM);
+    }
+
+    /**
+     * Create a source of randomness using a custom random-number generation algorithm.
+     *
+     * @param randAlgorithm The random-number generation algorithm to use
+     * @return A randomness sources that uses the specified algorithm
+     */
+    public static SecureRandom createRandomnessSource ( String randAlgorithm ) {
+        try {
+            return SecureRandom.getInstance(randAlgorithm);
+        }
+        catch ( NoSuchAlgorithmException e ) {
+            throw new ReviewedGATKException(String.format("Could not find an implementation of the requested random-number generation algorithm %s", randAlgorithm), e);
+        }
+    }
+
+    /**
+     * Writes a public/private key pair to disk
+     *
+     * @param keyPair The key pair we're writing to disk
+     * @param privateKeyFile Location to write the private key
+     * @param publicKeyFile Location to write the public key
+     */
+    public static void writeKeyPair ( KeyPair keyPair, File privateKeyFile, File publicKeyFile ) {
+        writeKey(keyPair.getPrivate(), privateKeyFile);
+        writeKey(keyPair.getPublic(), publicKeyFile);
+    }
+
+    /**
+     * Writes an arbitrary key to disk
+     *
+     * @param key The key to write
+     * @param destination Location to write the key to
+     */
+    public static void writeKey ( Key key, File destination ) {
+        IOUtils.writeByteArrayToFile(key.getEncoded(), destination);
+    }
+
+    /**
+     * Reads in a public key created using the default encryption algorithm from a file.
+     *
+     * @param source File containing the public key
+     * @return The public key read
+     */
+    public static PublicKey readPublicKey ( File source ) {
+        return decodePublicKey(IOUtils.readFileIntoByteArray(source), DEFAULT_ENCRYPTION_ALGORITHM);
+    }
+
+    /**
+     * Reads in a public key created using the default encryption algorithm from a stream.
+     *
+     * @param source Stream attached to the public key
+     * @return The public key read
+     */
+    public static PublicKey readPublicKey ( InputStream source ) {
+        return decodePublicKey(IOUtils.readStreamIntoByteArray(source), DEFAULT_ENCRYPTION_ALGORITHM);
+    }
+
+    /**
+     * Decodes the raw bytes of a public key into a usable object.
+     *
+     * @param rawKey The encoded bytes of a public key as read from, eg., a file. The
+     *               key must be in the standard X.509 format for a public key.
+     * @param encryptionAlgorithm The encryption algorithm used to create the public key
+     * @return The public key as a usable object
+     */
+    public static PublicKey decodePublicKey ( byte[] rawKey, String encryptionAlgorithm ) {
+        try {
+            KeySpec keySpec = new X509EncodedKeySpec(rawKey);
+            KeyFactory keyFactory = KeyFactory.getInstance(encryptionAlgorithm);
+            return keyFactory.generatePublic(keySpec);
+        }
+        catch ( NoSuchAlgorithmException e ) {
+            throw new ReviewedGATKException(String.format("Could not find an implementation of the requested encryption algorithm %s", encryptionAlgorithm), e);
+        }
+        catch ( InvalidKeySpecException e ) {
+            throw new ReviewedGATKException("Unable to use X.509 key specification to decode the given key", e);
+        }
+    }
+
+    /**
+     * Reads in a private key created using the default encryption algorithm from a file.
+     *
+     * @param source File containing the private key
+     * @return The private key read
+     */
+    public static PrivateKey readPrivateKey ( File source ) {
+        return decodePrivateKey(IOUtils.readFileIntoByteArray(source), DEFAULT_ENCRYPTION_ALGORITHM);
+    }
+
+    /**
+     * Reads in a private key created using the default encryption algorithm from a stream.
+     *
+     * @param source Stream attached to the private key
+     * @return The private key read
+     */
+    public static PrivateKey readPrivateKey ( InputStream source ) {
+        return decodePrivateKey(IOUtils.readStreamIntoByteArray(source), DEFAULT_ENCRYPTION_ALGORITHM);
+    }
+
+    /**
+     * Decodes the raw bytes of a private key into a usable object.
+     *
+     * @param rawKey The encoded bytes of a private key as read from, eg., a file. The
+     *               key must be in the standard PKCS #8 format for a private key.
+     * @param encryptionAlgorithm The encryption algorithm used to create the private key
+     * @return The private key as a usable object
+     */
+    public static PrivateKey decodePrivateKey ( byte[] rawKey, String encryptionAlgorithm ) {
+        try {
+            KeySpec keySpec = new PKCS8EncodedKeySpec(rawKey);
+            KeyFactory keyFactory = KeyFactory.getInstance(encryptionAlgorithm);
+            return keyFactory.generatePrivate(keySpec);
+        }
+        catch ( NoSuchAlgorithmException e ) {
+            throw new ReviewedGATKException(String.format("Could not find an implementation of the requested encryption algorithm %s", encryptionAlgorithm), e);
+        }
+        catch ( InvalidKeySpecException e ) {
+            throw new ReviewedGATKException("Unable to use the PKCS #8 key specification to decode the given key", e);
+        }
+    }
+
+    /**
+     * Loads the copy of the GATK public key that is distributed with the GATK. Uses the system
+     * ClassLoader to locate the public key file, which should be stored at the root of the GATK
+     * jar file.
+     *
+     * @return The GATK public key as a usable object
+     */
+    public static PublicKey loadGATKDistributedPublicKey() {
+        InputStream publicKeyInputStream = ClassLoader.getSystemResourceAsStream(GATK_DISTRIBUTED_PUBLIC_KEY_FILE_NAME);
+
+        if ( publicKeyInputStream == null ) {
+            throw new ReviewedGATKException(String.format("Could not locate the GATK public key %s in the classpath",
+                                                           GATK_DISTRIBUTED_PUBLIC_KEY_FILE_NAME));
+        }
+
+        return readPublicKey(publicKeyInputStream);
+    }
+
+    /**
+     * Loads the master copy of the GATK private key. You must have the appropriate UNIX permissions
+     * to do this!
+     *
+     * @return The GATK master private key as a usable object
+     */
+    public static PrivateKey loadGATKMasterPrivateKey() {
+        return readPrivateKey(new File(GATK_MASTER_PRIVATE_KEY_FILE));
+    }
+
+    /**
+     * Loads the master copy of the GATK public key. This should always be the same as the
+     * public key distributed with the GATK returned by loadGATKDistributedPublicKey().
+     *
+     * @return The GATK master public key as a usable object
+     */
+    public static PublicKey loadGATKMasterPublicKey() {
+        return readPublicKey(new File(GATK_MASTER_PUBLIC_KEY_FILE));
+    }
+
+    /**
+     * Encrypts the given data using the key provided.
+     *
+     * @param data The data to encrypt, as a byte array
+     * @param encryptKey The key with which to encrypt the data
+     * @return The encrypted version of the provided data
+     */
+    public static byte[] encryptData ( byte[] data, Key encryptKey ) {
+        return transformDataUsingCipher(data, encryptKey, Cipher.ENCRYPT_MODE);
+    }
+
+    /**
+     * Decrypts the given data using the key provided.
+     *
+     * @param encryptedData Data to decrypt, as a byte array
+     * @param decryptKey The key with which to decrypt the data
+     * @return The decrypted version of the provided data
+     */
+    public static byte[] decryptData ( byte[] encryptedData, Key decryptKey ) {
+        return transformDataUsingCipher(encryptedData, decryptKey, Cipher.DECRYPT_MODE);
+    }
+
+    /**
+     * Helper method for encryption/decryption that takes data and processes it using
+     * the given key
+     *
+     * @param data Data to encrypt/decrypt
+     * @param key Key to use to encrypt/decrypt the data
+     * @param cipherMode Specifies whether we are encrypting or decrypting
+     * @return The encrypted/decrypted data
+     */
+    private static byte[] transformDataUsingCipher ( byte[] data, Key key, int cipherMode ) {
+        try {
+            Cipher cipher = Cipher.getInstance(key.getAlgorithm());
+            cipher.init(cipherMode, key);
+            return cipher.doFinal(data);
+        }
+        catch ( NoSuchAlgorithmException e ) {
+            throw new ReviewedGATKException(String.format("Could not find an implementation of the requested algorithm %s",
+                                             key.getAlgorithm()), e);
+        }
+        catch ( InvalidKeyException e ) {
+            throw new ReviewedGATKException("Key is invalid", e);
+        }
+        catch ( GeneralSecurityException e ) {
+            throw new ReviewedGATKException("Error during encryption", e);
+        }
+    }
+
+    /**
+     * Tests whether the public/private keys provided can each decrypt data encrypted by
+     * the other key -- ie., tests whether these two keys are part of the same public/private
+     * key pair.
+     *
+     * @param privateKey The private key to test
+     * @param publicKey The public key to test
+     * @return True if the keys are part of the same key pair and can decrypt each other's
+     *         encrypted data, otherwise false.
+     */
+    public static boolean keysDecryptEachOther ( PrivateKey privateKey, PublicKey publicKey ) {
+        byte[] plainText = "Test PlainText".getBytes();
+
+        byte[] dataEncryptedUsingPrivateKey = CryptUtils.encryptData(plainText, privateKey);
+        byte[] dataEncryptedUsingPublicKey = CryptUtils.encryptData(plainText, publicKey);
+
+        byte[] privateKeyDataDecryptedWithPublicKey = CryptUtils.decryptData(dataEncryptedUsingPrivateKey, publicKey);
+        byte[] publicKeyDataDecryptedWithPrivateKey = CryptUtils.decryptData(dataEncryptedUsingPublicKey, privateKey);
+
+        // Make sure we actually transformed the data during encryption:
+        if ( Arrays.equals(plainText, dataEncryptedUsingPrivateKey) ||
+             Arrays.equals(plainText, dataEncryptedUsingPublicKey) ||
+             Arrays.equals(dataEncryptedUsingPrivateKey, dataEncryptedUsingPublicKey) ) {
+            return false;
+        }
+
+        // Make sure that we were able to recreate the original plaintext using
+        // both the public key on the private-key-encrypted data and the private
+        // key on the public-key-encrypted data:
+        if ( ! Arrays.equals(plainText, privateKeyDataDecryptedWithPublicKey) ||
+             ! Arrays.equals(plainText, publicKeyDataDecryptedWithPrivateKey) ) {
+            return false;
+        }
+
+        return true;
+    }
+}
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/crypt/GATKKey.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/crypt/GATKKey.java
new file mode 100644
index 0000000..ab21a2a
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/crypt/GATKKey.java
@@ -0,0 +1,350 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.utils.crypt;
+
+import org.broadinstitute.gatk.utils.exceptions.ReviewedGATKException;
+import org.broadinstitute.gatk.utils.exceptions.UserException;
+import org.broadinstitute.gatk.utils.io.IOUtils;
+
+import java.io.*;
+import java.security.*;
+import java.util.zip.GZIPInputStream;
+import java.util.zip.GZIPOutputStream;
+
+/**
+ * Class to represent a GATK user key.
+ *
+ * A GATK user key contains an email address and a cryptographic signature.
+ * The signature is the SHA-1 hash of the email address encrypted using
+ * the GATK master private key. The GATK master public key (distributed
+ * with the GATK) is used to decrypt the signature and validate the key
+ * at the start of each GATK run that requires a key.
+ *
+ * Keys are cryptographically secure in that valid keys definitely come
+ * from us and cannot be fabricated, however nothing prevents keys from
+ * being shared between users.
+ *
+ * GATK user keys have the following on-disk format:
+ *
+ *     GZIP Container:
+ *         Email address
+ *         NUL byte (delimiter)
+ *         Cryptographic Signature (encrypted SHA-1 hash of email address)
+ *
+ * The key data is wrapped within a GZIP container to placate over-zealous
+ * email filters (since keys must often be emailed) and also to provide an
+ * additional integrity check via the built-in GZIP CRC.
+ *
+ * @author David Roazen
+ */
+public class GATKKey {
+
+    /**
+     * Private key used to sign the GATK key. Required only when creating a new
+     * key from scratch, not when loading an existing key from disk.
+     */
+    private PrivateKey privateKey;
+
+    /**
+     * Public key used to validate the GATK key.
+     */
+    private PublicKey publicKey;
+
+    /**
+     * The user's email address, stored within the key and signed.
+     */
+    private String emailAddress;
+
+    /**
+     * The cryptographic signature of the email address. By default, this is
+     * the SHA-1 hash of the email address encrypted using the RSA algorithm.
+     */
+    private byte[] signature;
+
+    /**
+     * The combination of hash/encryption algorithms to use to generate the signature.
+     * By default this is "SHA1withRSA"
+     */
+    private String signingAlgorithm;
+
+    /**
+     * Default hash/encryption algorithms to use to sign the key.
+     */
+    public static final String DEFAULT_SIGNING_ALGORITHM = "SHA1withRSA";
+
+    /**
+     * Byte value used to separate the email address from its signature in the key file.
+     */
+    public static final byte GATK_KEY_SECTIONAL_DELIMITER = 0;
+
+
+    // -----------------------
+    // Constructors:
+    // -----------------------
+
+    /**
+     * Constructor to create a new GATK key from scratch using an email address
+     * and public/private key pair. The private key is used for signing, and the
+     * public key is used to validate the newly-created key.
+     *
+     * @param privateKey Private key used to sign the new GATK key
+     * @param publicKey Public key used to validate the new GATK key
+     * @param emailAddress The user's email address, which we will store in the key and sign
+     */
+    public GATKKey ( PrivateKey privateKey, PublicKey publicKey, String emailAddress ) {
+        this(privateKey, publicKey, emailAddress, DEFAULT_SIGNING_ALGORITHM);
+    }
+
+    /**
+     * Constructor to create a new GATK key from scratch using an email address
+     * and public/private key pair, and additionally specify the signing algorithm
+     * to use. The private key is used for signing, and the public key is used to
+     * validate the newly-created key.
+     *
+     * @param privateKey Private key used to sign the new GATK key
+     * @param publicKey Public key used to validate the new GATK key
+     * @param emailAddress The user's email address, which we will store in the key and sign
+     * @param signingAlgorithm The combination of hash and encryption algorithms to use to sign the key
+     */
+    public GATKKey ( PrivateKey privateKey, PublicKey publicKey, String emailAddress, String signingAlgorithm ) {
+        if ( privateKey == null || publicKey == null || emailAddress == null || emailAddress.length() == 0 || signingAlgorithm == null ) {
+            throw new ReviewedGATKException("Cannot construct GATKKey using null/empty arguments");
+        }
+
+        this.privateKey = privateKey;
+        this.publicKey = publicKey;
+        this.emailAddress = emailAddress;
+        this.signingAlgorithm = signingAlgorithm;
+
+        validateEmailAddress();
+        generateSignature();
+
+        if ( ! isValid() ) {
+            throw new ReviewedGATKException("Newly-generated GATK key fails validation -- this should never happen!");
+        }
+    }
+
+    /**
+     * Constructor to load an existing GATK key from a file.
+     *
+     * During loading, the key file is checked for integrity, but not cryptographic
+     * validity (which must be done through a subsequent call to isValid()).
+     *
+     * @param publicKey Public key that will be used to validate the loaded GATK key
+     *                  in subsequent calls to isValid()
+     * @param keyFile File containing the GATK key to load
+     */
+    public GATKKey ( PublicKey publicKey, File keyFile ) {
+        this(publicKey, keyFile, DEFAULT_SIGNING_ALGORITHM);
+    }
+
+    /**
+     * Constructor to load an existing GATK key from a file, and additionally specify
+     * the signing algorithm used to sign the key being loaded.
+     *
+     * During loading, the key file is checked for integrity, but not cryptographic
+     * validity (which must be done through a subsequent call to isValid()).
+     *
+     * @param publicKey Public key that will be used to validate the loaded GATK key
+     *                  in subsequent calls to isValid()
+     * @param keyFile File containing the GATK key to load
+     * @param signingAlgorithm The combination of hash and encryption algorithms used to sign the key
+     */
+    public GATKKey ( PublicKey publicKey, File keyFile, String signingAlgorithm ) {
+        if ( publicKey == null || keyFile == null || signingAlgorithm == null ) {
+            throw new ReviewedGATKException("Cannot construct GATKKey using null arguments");
+        }
+
+        this.publicKey = publicKey;
+        this.signingAlgorithm = signingAlgorithm;
+
+        readKey(keyFile);
+    }
+
+    // -----------------------
+    // Public API Methods:
+    // -----------------------
+
+    /**
+     * Writes out this key to a file in the format described at the top of this class,
+     * encapsulating the key within a GZIP container.
+     *
+     * @param destination File to write the key to
+     */
+    public void writeKey ( File destination ) {
+        try {
+            byte[] keyBytes = marshalKeyData();
+            IOUtils.writeByteArrayToStream(keyBytes, new GZIPOutputStream(new FileOutputStream(destination)));
+        }
+        catch ( IOException e ) {
+            throw new UserException.CouldNotCreateOutputFile(destination, e);
+        }
+    }
+
+    /**
+     * Checks whether the signature of this key is cryptographically valid (ie., can be
+     * decrypted by the public key to produce a valid SHA-1 hash of the email address
+     * in the key).
+     *
+     * @return True if the key's signature passes validation, otherwise false
+     */
+    public boolean isValid() {
+        try {
+            Signature sig = Signature.getInstance(signingAlgorithm);
+            sig.initVerify(publicKey);
+            sig.update(emailAddress.getBytes());
+            return sig.verify(signature);
+        }
+        catch ( NoSuchAlgorithmException e ) {
+            throw new ReviewedGATKException(String.format("Signing algorithm %s not found", signingAlgorithm), e);
+        }
+        catch ( InvalidKeyException e ) {
+            // If the GATK public key is invalid, it's likely our problem, not the user's:
+            throw new ReviewedGATKException(String.format("Public key %s is invalid", publicKey), e);
+        }
+        catch ( SignatureException e ) {
+            throw new UserException.UnreadableKeyException("Signature is invalid or signing algorithm was unable to process the input data", e);
+        }
+    }
+
+    // -----------------------
+    // Private Helper Methods:
+    // -----------------------
+
+    /**
+     * Helper method that creates a signature for this key using the combination of
+     * hash/encryption algorithms specified at construction time.
+     */
+    private void generateSignature() {
+        try {
+            Signature sig = Signature.getInstance(signingAlgorithm);
+            sig.initSign(privateKey, CryptUtils.createRandomnessSource());
+            sig.update(emailAddress.getBytes());
+            signature = sig.sign();
+        }
+        catch ( NoSuchAlgorithmException e ) {
+            throw new ReviewedGATKException(String.format("Signing algorithm %s not found", signingAlgorithm), e);
+        }
+        catch ( InvalidKeyException e ) {
+            throw new ReviewedGATKException(String.format("Private key %s is invalid", privateKey), e);
+        }
+        catch ( SignatureException e ) {
+            throw new ReviewedGATKException(String.format("Error creating signature for email address %s", emailAddress), e);
+        }
+    }
+
+    /**
+     * Helper method that reads in a GATK key from a file. Should not be called directly --
+     * use the appropriate constructor above.
+     *
+     * @param source File to read the key from
+     */
+    private void readKey ( File source ) {
+        try {
+            byte[] keyBytes = IOUtils.readStreamIntoByteArray(new GZIPInputStream(new FileInputStream(source)));
+
+            // As a sanity check, compare the number of bytes read to the uncompressed file size
+            // stored in the GZIP ISIZE field. If they don't match, the key must be corrupt:
+            if ( keyBytes.length != IOUtils.getGZIPFileUncompressedSize(source) ) {
+                throw new UserException.UnreadableKeyException("Number of bytes read does not match the uncompressed size specified in the GZIP ISIZE field");
+            }
+
+            unmarshalKeyData(keyBytes);
+        }
+        catch ( FileNotFoundException e ) {
+            throw new UserException.CouldNotReadInputFile(source, e);
+        }
+        catch ( IOException e ) {
+            throw new UserException.UnreadableKeyException(source, e);
+        }
+        catch ( UserException.CouldNotReadInputFile e ) {
+            throw new UserException.UnreadableKeyException(source, e);
+        }
+    }
+
+    /**
+     * Helper method that assembles the email address and signature into a format
+     * suitable for writing to disk.
+     *
+     * @return The aggregated key data, ready to be written to disk
+     */
+    private byte[] marshalKeyData() {
+        byte[] emailAddressBytes = emailAddress.getBytes();
+        byte[] assembledKey = new byte[emailAddressBytes.length + 1 + signature.length];
+
+        System.arraycopy(emailAddressBytes, 0, assembledKey, 0, emailAddressBytes.length);
+        assembledKey[emailAddressBytes.length] = GATK_KEY_SECTIONAL_DELIMITER;
+        System.arraycopy(signature, 0, assembledKey, emailAddressBytes.length + 1, signature.length);
+
+        return assembledKey;
+    }
+
+    /**
+     * Helper method that parses the raw key data from disk into its component
+     * email address and signature. Performs some basic validation in the process.
+     *
+     * @param keyBytes The raw, uncompressed key data read from disk
+     */
+    private void unmarshalKeyData ( byte[] keyBytes ) {
+        int delimiterPosition = -1;
+
+        for ( int i = 0; i < keyBytes.length; i++ ) {
+            if ( keyBytes[i] == GATK_KEY_SECTIONAL_DELIMITER ) {
+                delimiterPosition = i;
+                break;
+            }
+        }
+
+        if ( delimiterPosition == -1 ) {
+            throw new UserException.UnreadableKeyException("Malformed GATK key contains no sectional delimiter");
+        }
+        else if ( delimiterPosition == 0 ) {
+            throw new UserException.UnreadableKeyException("Malformed GATK key contains no email address");
+        }
+        else if ( delimiterPosition == keyBytes.length - 1 ) {
+            throw new UserException.UnreadableKeyException("Malformed GATK key contains no signature");
+        }
+
+        byte[] emailAddressBytes = new byte[delimiterPosition];
+        System.arraycopy(keyBytes, 0, emailAddressBytes, 0, delimiterPosition);
+        emailAddress = new String(emailAddressBytes);
+
+        signature = new byte[keyBytes.length - delimiterPosition - 1];
+        System.arraycopy(keyBytes, delimiterPosition + 1, signature, 0, keyBytes.length - delimiterPosition - 1);
+    }
+
+    /**
+     * Helper method that ensures that the user's email address does not contain the NUL byte, which we
+     * reserve as a delimiter within each key file.
+     */
+    private void validateEmailAddress() {
+        for ( byte b : emailAddress.getBytes() ) {
+            if ( b == GATK_KEY_SECTIONAL_DELIMITER ) {
+                throw new UserException(String.format("Email address must not contain a byte with value %d", GATK_KEY_SECTIONAL_DELIMITER));
+            }
+        }
+    }
+}
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/duplicates/DupUtils.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/duplicates/DupUtils.java
new file mode 100644
index 0000000..3d27407
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/duplicates/DupUtils.java
@@ -0,0 +1,142 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.utils.duplicates;
+
+import org.broadinstitute.gatk.utils.BaseUtils;
+import org.broadinstitute.gatk.utils.GenomeLoc;
+import org.broadinstitute.gatk.utils.GenomeLocParser;
+import org.broadinstitute.gatk.utils.QualityUtils;
+import org.broadinstitute.gatk.utils.collections.Pair;
+import org.broadinstitute.gatk.utils.exceptions.ReviewedGATKException;
+import org.broadinstitute.gatk.utils.pileup.PileupElement;
+import org.broadinstitute.gatk.utils.pileup.ReadBackedPileup;
+import org.broadinstitute.gatk.utils.pileup.ReadBackedPileupImpl;
+import org.broadinstitute.gatk.utils.sam.GATKSAMRecord;
+
+import java.util.Arrays;
+import java.util.List;
+
+public class DupUtils {
+    private static GATKSAMRecord tmpCopyRead(GATKSAMRecord read) {
+        return (GATKSAMRecord)read.clone();
+    }
+
+    public static GATKSAMRecord combineDuplicates(GenomeLocParser genomeLocParser,List<GATKSAMRecord> duplicates, int maxQScore) {
+        if ( duplicates.size() == 0 )
+            return null;
+
+        // make the combined read by copying the first read and setting the
+        // bases and quals to new arrays
+        GATKSAMRecord comb = tmpCopyRead(duplicates.get(0));
+        //GATKSAMRecord comb = tmpCopyRead(duplicates.get(0));
+        comb.setDuplicateReadFlag(false);
+        int readLen = comb.getReadBases().length;
+        byte[] bases = new byte[readLen];
+        byte[] quals = new byte[readLen];
+
+        for ( int i = 0; i < readLen; i++ ) {
+            //System.out.printf("I is %d%n", i);
+            //for ( GATKSAMRecord read : duplicates ) {
+            //    System.out.printf("dup base %c %d%n", (char)read.getReadBases()[i], read.getBaseQualities()[i]);
+            //}
+            Pair<Byte, Byte> baseAndQual = combineBaseProbs(genomeLocParser,duplicates, i, maxQScore);
+            bases[i] = baseAndQual.getFirst();
+            quals[i] = baseAndQual.getSecond();            
+        }
+
+
+        comb.setBaseQualities(quals);
+        comb.setReadBases(bases);
+
+        return comb;
+    }
+
+    private static Pair<Byte, Byte> baseProbs2BaseAndQual(double[] probs, int maxQScore) {
+        byte bestBase = 0;
+        double bestProb = Double.NEGATIVE_INFINITY;
+        double sumProbs = 0;
+
+        for ( int i = 0; i < 4; i++ ) {
+            sumProbs += Math.pow(10, probs[i]);
+            //System.out.printf("Bestprob is %f > %f%n", bestProb, probs[i]);
+            if ( probs[i] > bestProb ) {
+                bestBase = BaseUtils.baseIndexToSimpleBase(i);
+                bestProb = probs[i];
+            }
+        }
+
+        Arrays.sort(probs);
+        double normalizedP = Math.pow(10, bestProb) / sumProbs;
+        byte qual = QualityUtils.trueProbToQual(normalizedP, maxQScore);
+//        if ( false ) {
+//            System.out.printf("Best base is %s %.8f%n", bestBase, bestProb);
+//            System.out.printf("2nd  base is %.8f%n", probs[1]);
+//            System.out.printf("normalized P %.8f%n", normalizedP);
+//            System.out.printf("normalized Q %.8f%n", 1 - normalizedP);
+//            System.out.printf("max Q        %2d%n", maxQScore);
+//            System.out.printf("eps          %.8f%n", eps);
+//            System.out.printf("encoded    Q %2d%n", qual);
+//        }
+
+        return new Pair<Byte, Byte>(bestBase, qual);
+    }
+
+    private static void print4BaseQuals(String header, double[] probs) {
+        System.out.printf("%s log10(P(b)) is ", header);
+        for ( int i = 0; i < 4; i++ ) {
+            System.out.printf("%c=%+.8f ", (char)BaseUtils.baseIndexToSimpleBase(i), probs[i]);
+        }
+        System.out.printf("%n");
+    }
+
+    private static Pair<Byte, Byte> combineBaseProbs(GenomeLocParser genomeLocParser,List<GATKSAMRecord> duplicates, int readOffset, int maxQScore) {
+        GenomeLoc loc = genomeLocParser.createGenomeLoc(duplicates.get(0));
+        ReadBackedPileup pileup = new ReadBackedPileupImpl(loc, duplicates, readOffset);
+
+        final boolean debug = false;
+
+        // calculate base probs
+        double[] qualSums = {0.0, 0.0, 0.0, 0.0};
+        if ( debug ) print4BaseQuals("start", qualSums);
+
+        for (PileupElement e : pileup ) {
+            int baseIndex = e.getBaseIndex();
+            byte qual = e.getQual();
+            double pqual = QualityUtils.qualToProb(qual);
+            for ( int j = 0; j < 4; j++) {
+                qualSums[j] += Math.log10(j == baseIndex ?  pqual : (1 - pqual)/3);
+            }
+
+            if ( debug ) print4BaseQuals(String.format("%c Q%2d", e.getBase(), qual), qualSums);
+        }
+        if ( debug ) print4BaseQuals("final", qualSums);
+
+        Pair<Byte, Byte> combined = baseProbs2BaseAndQual(qualSums, maxQScore);
+        if ( debug ) System.out.printf("%s => %c Q%s%n", pileup.getPileupString('N'), (char)(byte)combined.getFirst(), combined.getSecond());
+
+        return combined;
+    }
+}
\ No newline at end of file
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/duplicates/DuplicateComp.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/duplicates/DuplicateComp.java
new file mode 100644
index 0000000..9213a3e
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/duplicates/DuplicateComp.java
@@ -0,0 +1,66 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.utils.duplicates;
+
+public class DuplicateComp {
+    public int getQLarger() {
+        return qLarger;
+    }
+
+    public void setQLarger(int qLarger) {
+        this.qLarger = qLarger;
+    }
+
+    public int getQSmaller() {
+        return qSmaller;
+    }
+
+    public void setQSmaller(int qSmaller) {
+        this.qSmaller = qSmaller;
+    }
+
+    public boolean isMismatchP() {
+        return mismatchP;
+    }
+
+    public void setMismatchP(boolean mismatchP) {
+        this.mismatchP = mismatchP;
+    }
+
+    private int qLarger;
+    private int qSmaller;
+    private boolean mismatchP;
+
+    public DuplicateComp(int qLarger, int qSmaller, boolean misMatchP) {
+        this.qLarger = qLarger;
+        this.qSmaller = qSmaller;
+        this.mismatchP = misMatchP;
+    }
+
+    public String toString() {
+        return String.format("%d %d %b", qLarger, qSmaller, mismatchP);
+    }
+}
\ No newline at end of file
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/exceptions/DynamicClassResolutionException.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/exceptions/DynamicClassResolutionException.java
new file mode 100644
index 0000000..1c53420
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/exceptions/DynamicClassResolutionException.java
@@ -0,0 +1,54 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.utils.exceptions;
+
+import java.lang.reflect.InvocationTargetException;
+
+/**
+ * Class for handling common failures of dynamic class resolution
+ */
+public class DynamicClassResolutionException extends UserException {
+    public DynamicClassResolutionException(Class c, Exception ex) {
+        super(String.format("Could not create module %s because %s caused by exception %s",
+                c.getSimpleName(), moreInfo(ex), ex.getMessage()));
+    }
+
+    private static String moreInfo(Exception ex) {
+        try {
+            throw ex;
+        } catch (InstantiationException e) {
+            return "BUG: cannot instantiate class: must be concrete class";
+        } catch (NoSuchMethodException e) {
+            return "BUG: Cannot find expected constructor for class";
+        } catch (IllegalAccessException e) {
+            return "Cannot instantiate class (Illegal Access)";
+        } catch (InvocationTargetException e) {
+            return "Cannot instantiate class (Invocation failure)";
+        } catch ( Exception e ) {
+            return String.format("an exception of type %s occurred",e.getClass().getSimpleName());
+        }
+    }
+}
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/exceptions/UserException.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/exceptions/UserException.java
new file mode 100644
index 0000000..07db4fc
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/exceptions/UserException.java
@@ -0,0 +1,485 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.utils.exceptions;
+
+import htsjdk.samtools.CigarOperator;
+import htsjdk.samtools.SAMFileHeader;
+import htsjdk.samtools.SAMRecord;
+import htsjdk.samtools.SAMSequenceDictionary;
+import org.broadinstitute.gatk.utils.GenomeLoc;
+import org.broadinstitute.gatk.utils.help.DocumentedGATKFeature;
+import org.broadinstitute.gatk.utils.help.HelpConstants;
+import org.broadinstitute.gatk.utils.sam.ReadUtils;
+import org.broadinstitute.gatk.utils.variant.GATKVCFIndexType;
+import htsjdk.variant.variantcontext.VariantContext;
+
+import java.io.File;
+
+/**
+ * Represents the common user errors detected by GATK
+ *
+ * Root class for all GATK user errors, as well as the container for errors themselves
+ */
+ at DocumentedGATKFeature(
+        groupName = HelpConstants.DOCS_CAT_USRERR,
+        summary = "Errors caused by incorrect user behavior, such as bad files, bad arguments, etc." )
+public class UserException extends ReviewedGATKException {
+    /**
+     * The URL where people can get help messages.  Printed when an error occurs
+     */
+    public static final String PHONE_HOME_DOCS_URL = "http://gatkforums.broadinstitute.org/discussion/1250/what-is-phone-home-and-how-does-it-affect-me#latest";
+
+    public UserException(String msg) { super(msg); }
+    public UserException(String msg, Throwable e) { super(msg, e); }
+    private UserException(Throwable e) { super("", e); } // cannot be called, private access
+
+    protected static String getMessage(Throwable t) {
+        String message = t.getMessage();
+        return message != null ? message : t.getClass().getName();
+    }
+
+    public static class CommandLineException extends UserException {
+        public CommandLineException(String message) {
+            super(String.format("Invalid command line: %s", message));
+        }
+    }
+
+    public static class MalformedReadFilterException extends CommandLineException {
+        public MalformedReadFilterException(String message) {
+            super(String.format("Malformed read filter: %s",message));
+        }
+    }
+
+    public static class IncompatibleReadFiltersException extends CommandLineException {
+        public IncompatibleReadFiltersException(final String filter1, final String filter2) {
+            super(String.format("Two read filters are enabled that are incompatible and cannot be used simultaneously: %s and %s", filter1, filter2));
+        }
+    }
+
+    public static class MalformedWalkerArgumentsException extends CommandLineException {
+        public MalformedWalkerArgumentsException(String message) {
+            super(String.format("Malformed walker argument: %s",message));
+        }
+    }
+
+    public static class UnsupportedCigarOperatorException extends UserException {
+        public UnsupportedCigarOperatorException(final CigarOperator co, final SAMRecord read, final String message) {
+            super(String.format(
+                "Unsupported CIGAR operator %s in read %s at %s:%d. %s",
+                co,
+                read.getReadName(),
+                read.getReferenceName(),
+                read.getAlignmentStart(),
+                message));
+        }
+    }
+
+
+    public static class MalformedGenomeLoc extends UserException {
+        public MalformedGenomeLoc(String message, GenomeLoc loc) {
+            super(String.format("Badly formed genome loc: %s: %s", message, loc));
+        }
+
+        public MalformedGenomeLoc(String message) {
+            super(String.format("Badly formed genome loc: %s", message));
+        }
+    }
+
+    public static class BadInput extends UserException {
+        public BadInput(String message) {
+            super(String.format("Bad input: %s", message));
+        }
+    }
+
+    // todo -- fix up exception cause passing
+    public static class MissingArgument extends CommandLineException {
+        public MissingArgument(String arg, String message) {
+            super(String.format("Argument %s was missing: %s", arg, message));
+        }
+    }
+
+    public static class BadArgumentValue extends CommandLineException {
+        public BadArgumentValue(String arg, String message) {
+            super(String.format("Argument %s has a bad value: %s", arg, message));
+        }
+    }
+
+    public static class UnknownTribbleType extends CommandLineException {
+        public UnknownTribbleType(String type, String message) {
+            super(String.format("Unknown tribble type %s: %s", type, message));
+        }
+    }
+
+
+    public static class BadTmpDir extends UserException {
+        public BadTmpDir(String message) {
+            super(String.format("Failure working with the tmp directory %s. Override with -Djava.io.tmpdir=X on the command line to a bigger/better file system.  Exact error was %s", System.getProperties().get("java.io.tmpdir"), message));
+        }
+    }
+
+    public static class TooManyOpenFiles extends UserException {
+        public TooManyOpenFiles() {
+            super(String.format("There was a failure because there are too many files open concurrently; your system's open file handle limit is too small.  See the unix ulimit command to adjust this limit"));
+        }
+    }
+
+    public static class LocalParallelizationProblem extends UserException {
+        public LocalParallelizationProblem(final File file) {
+            super(String.format("There was a failure because temporary file %s could not be found while running the GATK with more than one thread.  Possible causes for this problem include: your system's open file handle limit is too small, your output or temp directories do not have sufficient space, or just an isolated file system blip", file.getAbsolutePath()));
+        }
+    }
+
+    public static class NotEnoughMemory extends UserException {
+        public NotEnoughMemory() {
+            super(String.format("There was a failure because you did not provide enough memory to run this program.  See the -Xmx JVM argument to adjust the maximum heap size provided to Java"));
+        }
+    }
+
+    public static class ErrorWritingBamFile extends UserException {
+        public ErrorWritingBamFile(String message) {
+            super(String.format("An error occurred when trying to write the BAM file.  Usually this happens when there is not enough space in the directory to which the data is being written (generally the temp directory) or when your system's open file handle limit is too small.  To tell Java to use a bigger/better file system use -Djava.io.tmpdir=X on the command line.  The exact error was %s", message));
+        }
+    }
+
+    public static class NoSpaceOnDevice extends UserException {
+        public NoSpaceOnDevice() {
+            super("There is no space left on the device, so writing failed");
+        }
+    }
+
+    public static class CouldNotReadInputFile extends UserException {
+        public CouldNotReadInputFile(String message, Exception e) {
+            super(String.format("Couldn't read file because %s caused by %s", message, getMessage(e)));
+        }
+
+        public CouldNotReadInputFile(File file) {
+            super(String.format("Couldn't read file %s", file.getAbsolutePath()));
+        }
+
+        public CouldNotReadInputFile(File file, String message) {
+            super(String.format("Couldn't read file %s because %s", file.getAbsolutePath(), message));
+        }
+
+        public CouldNotReadInputFile(String file, String message) {
+            super(String.format("Couldn't read file %s because %s", file, message));
+        }
+
+        public CouldNotReadInputFile(File file, String message, Exception e) {
+            super(String.format("Couldn't read file %s because %s with exception %s", file.getAbsolutePath(), message, getMessage(e)));
+        }
+
+        public CouldNotReadInputFile(File file, Exception e) {
+            this(file, getMessage(e));
+        }
+
+        public CouldNotReadInputFile(String message) {
+            super(message);
+        }
+    }
+
+
+    public static class CouldNotCreateOutputFile extends UserException {
+        public CouldNotCreateOutputFile(File file, String message, Exception e) {
+            super(String.format("Couldn't write file %s because %s with exception %s", file.getAbsolutePath(), message, getMessage(e)));
+        }
+
+        public CouldNotCreateOutputFile(File file, String message) {
+            super(String.format("Couldn't write file %s because %s", file.getAbsolutePath(), message));
+        }
+
+        public CouldNotCreateOutputFile(String filename, String message, Exception e) {
+            super(String.format("Couldn't write file %s because %s with exception %s", filename, message, getMessage(e)));
+        }
+
+        public CouldNotCreateOutputFile(File file, Exception e) {
+            super(String.format("Couldn't write file %s because exception %s", file.getAbsolutePath(), getMessage(e)));
+        }
+
+        public CouldNotCreateOutputFile(String message, Exception e) {
+            super(message, e);
+        }
+    }
+
+    public static class MissortedBAM extends UserException {
+        public MissortedBAM(SAMFileHeader.SortOrder order, File file, SAMFileHeader header) {
+            super(String.format("Missorted Input SAM/BAM files: %s is must be sorted in %s order but order was: %s", file, order, header.getSortOrder()));
+        }
+
+        public MissortedBAM(SAMFileHeader.SortOrder order, String message) {
+            super(String.format("Missorted Input SAM/BAM files: files are not sorted in %s order; %s", order, message));
+        }
+
+        public MissortedBAM(SAMFileHeader.SortOrder order, SAMRecord read, String message) {
+            super(String.format("Missorted Input SAM/BAM file %s: file sorted in %s order but %s is required; %s",
+                    read.getFileSource().getReader(), read.getHeader().getSortOrder(), order, message));
+        }
+
+        public MissortedBAM(String message) {
+            super(String.format("Missorted Input SAM/BAM files: %s", message));
+        }
+    }
+
+    public static class MalformedBAM extends UserException {
+        public MalformedBAM(SAMRecord read, String message) {
+            this(read.getFileSource() != null ? read.getFileSource().getReader().toString() : "(none)", message);
+        }
+
+        public MalformedBAM(File file, String message) {
+            this(file.toString(), message);
+        }
+
+        public MalformedBAM(String source, String message) {
+            super(String.format("SAM/BAM file %s is malformed: %s", source, message));
+        }
+    }
+
+    public static class MisencodedBAM extends UserException {
+        public MisencodedBAM(SAMRecord read, String message) {
+            this(read.getFileSource() != null ? read.getFileSource().getReader().toString() : "(none)", message);
+        }
+
+        public MisencodedBAM(String source, String message) {
+            super(String.format("SAM/BAM file %s appears to be using the wrong encoding for quality scores: %s; please see the GATK --help documentation for options related to this error", source, message));
+        }
+    }
+
+    public static class MalformedVCF extends UserException {
+        public MalformedVCF(String message, String line) {
+            super(String.format("The provided VCF file is malformed at line %s: %s", line, message));
+        }
+
+        public MalformedVCF(String message) {
+            super(String.format("The provided VCF file is malformed: %s", message));
+        }
+
+        public MalformedVCF(String message, int lineNo) {
+            super(String.format("The provided VCF file is malformed at approximately line number %d: %s", lineNo, message));
+        }
+    }
+
+    public static class MalformedBCF2 extends UserException {
+        public MalformedBCF2( String message ) {
+            super(String.format("Malformed BCF2 file: %s", message));
+        }
+    }
+
+    public static class MalformedVCFHeader extends UserException {
+        public MalformedVCFHeader(String message) {
+            super(String.format("The provided VCF file has a malformed header: %s", message));
+        }
+    }
+
+    public static class ReadMissingReadGroup extends MalformedBAM {
+        public ReadMissingReadGroup(final SAMRecord read) {
+            super(read, String.format("Read %s is missing the read group (RG) tag, which is required by the GATK.  Please use " + HelpConstants.forumPost("discussion/59/companion-utilities-replacereadgroups to fix this problem"), read.getReadName()));
+        }
+    }
+
+    public static class ReadHasUndefinedReadGroup extends MalformedBAM {
+        public ReadHasUndefinedReadGroup(final SAMRecord read, final String rgID) {
+            super(read, String.format("Read %s uses a read group (%s) that is not defined in the BAM header, which is not valid.  Please use " + HelpConstants.forumPost("discussion/59/companion-utilities-replacereadgroups to fix this problem"), read.getReadName(), rgID));
+        }
+    }
+
+    public static class VariantContextMissingRequiredField extends UserException {
+        public VariantContextMissingRequiredField(String field, VariantContext vc) {
+            super(String.format("Variant at %s:%d is is missing the required field %s", vc.getChr(), vc.getStart(), field));
+        }
+    }
+
+    public static class MissortedFile extends UserException {
+        public MissortedFile(File file, String message, Exception e) {
+            super(String.format("Missorted Input file: %s is must be sorted in coordinate order. %s and got error %s", file, message, getMessage(e)));
+        }
+    }
+
+    public static class FailsStrictValidation extends UserException {
+        public FailsStrictValidation(File f, String message) {
+            super(String.format("File %s fails strict validation: %s", f.getAbsolutePath(), message));
+        }
+    }
+
+    public static class MalformedFile extends UserException {
+        public MalformedFile(String message) {
+            super(String.format("Unknown file is malformed: %s", message));
+        }
+
+        public MalformedFile(String message, Exception e) {
+            super(String.format("Unknown file is malformed: %s caused by %s", message, getMessage(e)));
+        }
+
+        public MalformedFile(File f, String message) {
+            super(String.format("File %s is malformed: %s", f.getAbsolutePath(), message));
+        }
+
+        public MalformedFile(File f, String message, Exception e) {
+            super(String.format("File %s is malformed: %s caused by %s", f.getAbsolutePath(), message, getMessage(e)));
+        }
+
+        public MalformedFile(String name, String message) {
+            super(String.format("File associated with name %s is malformed: %s", name, message));
+        }
+
+        public MalformedFile(String name, String message, Exception e) {
+            super(String.format("File associated with name %s is malformed: %s caused by %s", name, message, getMessage(e)));
+        }
+     }
+
+    public static class CannotExecuteRScript extends UserException {
+        public CannotExecuteRScript(String message) {
+            super(String.format("Unable to execute RScript command: " + message));
+        }
+        public CannotExecuteRScript(String message, Exception e) {
+            super(String.format("Unable to execute RScript command: " + message), e);
+        }
+    }
+
+    public static class DeprecatedArgument extends CommandLineException {
+        public DeprecatedArgument(String param, String doc) {
+            super(String.format("The parameter %s is deprecated.  %s",param,doc));
+        }
+    }
+
+
+    public static class IncompatibleSequenceDictionaries extends UserException {
+        public IncompatibleSequenceDictionaries(String message, String name1, SAMSequenceDictionary dict1, String name2, SAMSequenceDictionary dict2) {
+            super(String.format("Input files %s and %s have incompatible contigs: %s.\n  %s contigs = %s\n  %s contigs = %s",
+                    name1, name2, message, name1, ReadUtils.prettyPrintSequenceRecords(dict1), name2, ReadUtils.prettyPrintSequenceRecords(dict2)));
+        }
+    }
+
+    public static class LexicographicallySortedSequenceDictionary extends UserException {
+        public LexicographicallySortedSequenceDictionary(String name, SAMSequenceDictionary dict) {
+            super(String.format("Lexicographically sorted human genome sequence detected in %s."
+                    + "\nFor safety's sake the GATK requires human contigs in karyotypic order: 1, 2, ..., 10, 11, ..., 20, 21, 22, X, Y with M either leading or trailing these contigs."
+                    + "\nThis is because all distributed GATK resources are sorted in karyotypic order, and your processing will fail when you need to use these files."
+                    + "\nYou can use the ReorderSam utility to fix this problem: " + HelpConstants.forumPost("discussion/58/companion-utilities-reordersam")
+                    + "\n  %s contigs = %s",
+                    name, name, ReadUtils.prettyPrintSequenceRecords(dict)));
+        }
+    }
+
+    public static class DeprecatedWalker extends UserException {
+        public DeprecatedWalker(String walkerName, String version) {
+            super(String.format("Walker %s is no longer available in the GATK; it has been deprecated since version %s", walkerName, version));
+        }
+    }
+
+    public static class DeprecatedAnnotation extends UserException {
+        public DeprecatedAnnotation(String annotationName, String version) {
+            super(String.format("Annotation %s is no longer available in the GATK; it has been deprecated since version %s", annotationName, version));
+        }
+    }
+
+    public static class CannotExecuteQScript extends UserException {
+        public CannotExecuteQScript(String message) {
+            super(String.format("Unable to execute QScript: " + message));
+        }
+        public CannotExecuteQScript(String message, Exception e) {
+            super(String.format("Unable to execute QScript: " + message), e);
+        }
+    }
+
+    public static class CannotHandleGzippedRef extends UserException {
+        public CannotHandleGzippedRef() {
+            super("The GATK cannot process compressed (.gz) reference sequences. Please unzip the file and try again.  Sorry for the inconvenience.");
+        }
+    }
+
+    public static class MissingReferenceFaiFile extends UserException {
+        public MissingReferenceFaiFile( final File indexFile, final File fastaFile ) {
+            super(String.format("Fasta index file %s for reference %s does not exist. Please see %s for help creating it.",
+                                indexFile.getAbsolutePath(), fastaFile.getAbsolutePath(),
+                                HelpConstants.forumPost("discussion/1601/how-can-i-prepare-a-fasta-file-to-use-as-reference")));
+        }
+    }
+
+    public static class MissingReferenceDictFile extends UserException {
+        public MissingReferenceDictFile( final File dictFile, final File fastaFile ) {
+            super(String.format("Fasta dict file %s for reference %s does not exist. Please see %s for help creating it.",
+                                dictFile.getAbsolutePath(), fastaFile.getAbsolutePath(),
+                                HelpConstants.forumPost("discussion/1601/how-can-i-prepare-a-fasta-file-to-use-as-reference")));
+        }
+    }
+
+    public static class UnreadableKeyException extends UserException {
+        public UnreadableKeyException ( File f, Exception e ) {
+            super(String.format("Key file %s cannot be read (possibly the key file is corrupt?). Error was: %s. " +
+                                "Please see %s for help.",
+                                f.getAbsolutePath(), getMessage(e), PHONE_HOME_DOCS_URL));
+        }
+
+        public UnreadableKeyException ( String message, Exception e ) {
+            this(String.format("%s. Error was: %s", message, getMessage(e)));
+        }
+
+        public UnreadableKeyException ( String message ) {
+            super(String.format("Key file cannot be read (possibly the key file is corrupt?): %s. " +
+                                "Please see %s for help.",
+                                message, PHONE_HOME_DOCS_URL));
+        }
+    }
+
+    public static class KeySignatureVerificationException extends UserException {
+        public KeySignatureVerificationException ( File f ) {
+            super(String.format("The signature in key file %s failed cryptographic verification. " +
+                                "If this key was valid in the past, it's likely been revoked. " +
+                                "Please see %s for help.",
+                                f.getAbsolutePath(), PHONE_HOME_DOCS_URL));
+        }
+    }
+
+    public static class GVCFIndexException extends UserException {
+        public GVCFIndexException (GATKVCFIndexType indexType, int indexParameter) {
+            super(String.format("GVCF output requires a specific indexing strategy.  Please re-run including the arguments " +
+                    "-variant_index_type %s -variant_index_parameter %d.",
+                    indexType, indexParameter));
+        }
+    }
+
+    /**
+     * A special exception that happens only in the case where
+     * the filesystem, by design or configuration, is completely unable
+     * to handle locking.  This exception will specifically NOT be thrown
+     * in the case where the filesystem handles locking but is unable to
+     * acquire a lock due to concurrency.
+     */
+    public static class FileSystemInabilityToLockException extends UserException {
+        public FileSystemInabilityToLockException( String message ) {
+            super(message);
+        }
+
+        public FileSystemInabilityToLockException( String message, Exception innerException ) {
+            super(message,innerException);
+        }
+    }
+
+    public static class IncompatibleRecalibrationTableParameters extends UserException {
+        public IncompatibleRecalibrationTableParameters(String s) {
+            super(s);
+        }
+    }
+}
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/fasta/ArtificialFastaUtils.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/fasta/ArtificialFastaUtils.java
new file mode 100644
index 0000000..bf03ec6
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/fasta/ArtificialFastaUtils.java
@@ -0,0 +1,154 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.utils.fasta;
+
+import org.broadinstitute.gatk.utils.exceptions.ReviewedGATKException;
+
+import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
+import java.io.PrintStream;
+import java.util.List;
+
+
+/**
+ * @author aaron
+ *         <p/>
+ *         Class ArtificialFastaUtils
+ *         <p/>
+ *         artificial fasta utility class, for generating fake fastas.
+ */
+public class ArtificialFastaUtils {
+    public enum BASE_PATTERN {
+        RANDOM, ALL_A, ALL_T, ALL_C, ALL_G;
+    }
+
+    // what bases we support
+    public enum BASES {
+        A, T, C, G;
+    }
+
+    // create an artificial fasta file
+    public static void createArtificialFasta(String fileName,
+                                             List<String> contigNames,
+                                             List<Integer> contigSizes,
+                                             BASE_PATTERN pattern) {
+        PrintStream s;
+        try {
+            s = new PrintStream(new FileOutputStream(fileName));
+        } catch (FileNotFoundException e) {
+            throw new ReviewedGATKException("Filename " + fileName + " passed to the ArtificialFastaUtils generated a FileNotFound exception", e);
+        }
+        generateFakeFasta(contigNames, contigSizes, pattern, s);
+    }
+
+    // create an artificial fasta file
+    public static void createArtificialFasta(PrintStream stream,
+                                             List<String> contigNames,
+                                             List<Integer> contigSizes,
+                                             BASE_PATTERN pattern) {
+
+        generateFakeFasta(contigNames, contigSizes, pattern, stream);
+    }
+
+    /**
+     * create a fake fasta file
+     *
+     * @param contigNames the pile of contig names
+     * @param contigSizes the pile of contig sizes
+     * @param pattern     the pattern to use for the base distrobution
+     * @param s           the print stream to write to
+     */
+    private static void generateFakeFasta(List<String> contigNames, List<Integer> contigSizes, BASE_PATTERN pattern, PrintStream s) {
+        if (contigNames.size() != contigSizes.size()) {
+            throw new ReviewedGATKException("ArtificialContig name and size arrays are not equal sizes");
+        }
+        for (int x = 0; x < contigNames.size(); x++) {
+            ArtificialContig tig = new ArtificialContig(contigNames.get(x), contigSizes.get(x), pattern);
+            tig.write(s);
+        }
+        s.close();
+    }
+
+}
+
+
+/** the fake contig class, a fasta is made up of these */
+class ArtificialContig {
+    public static final int COLUMN_WIDTH = 80;
+
+    final protected String mName;
+    final protected int mSize;
+    final protected ArtificialFastaUtils.BASE_PATTERN mPattern;
+
+    public ArtificialContig(String name, int size, ArtificialFastaUtils.BASE_PATTERN pat) {
+        this.mName = name;
+        this.mSize = size;
+        this.mPattern = pat;
+    }
+
+    /**
+     * write out the contig to a stream
+     *
+     * @param stream
+     */
+    public void write(PrintStream stream) {
+        stream.println(">" + mName);
+        int count = 0;
+        while (count < mSize) {
+            for (int x = 0; x < COLUMN_WIDTH; x++) {
+                stream.print(generateAppropriateBase());
+                count++;
+                if (count >= mSize) {
+                    break;
+                }
+            }
+            stream.println();
+        }
+    }
+
+    /**
+     * generate the appropriate base, given the BASE_PATTERN
+     *
+     * @return a base, as a string
+     */
+    public String generateAppropriateBase() {
+        switch (mPattern) {
+            case RANDOM:
+                return (ArtificialFastaUtils.BASES.values()[(int) Math.round(Math.random() * 4)]).toString();
+            case ALL_A:
+                return "A";
+            case ALL_T:
+                return "T";
+            case ALL_C:
+                return "C";
+            case ALL_G:
+                return "G";
+            default:
+                throw new ReviewedGATKException("Unknown base pattern");
+        }
+    }
+
+}
\ No newline at end of file
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/fasta/CachingIndexedFastaSequenceFile.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/fasta/CachingIndexedFastaSequenceFile.java
new file mode 100644
index 0000000..05f2ccf
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/fasta/CachingIndexedFastaSequenceFile.java
@@ -0,0 +1,311 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.utils.fasta;
+
+import picard.PicardException;
+import htsjdk.samtools.reference.FastaSequenceIndex;
+import htsjdk.samtools.reference.IndexedFastaSequenceFile;
+import htsjdk.samtools.reference.ReferenceSequence;
+import htsjdk.samtools.SAMSequenceRecord;
+import htsjdk.samtools.util.StringUtil;
+import org.apache.log4j.Priority;
+import org.broadinstitute.gatk.utils.exceptions.ReviewedGATKException;
+import org.broadinstitute.gatk.utils.BaseUtils;
+
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.util.Arrays;
+
+/**
+ * A caching version of the IndexedFastaSequenceFile that avoids going to disk as often as the raw indexer.
+ *
+ * Thread-safe!  Uses a thread-local cache.
+ *
+ * Automatically upper-cases the bases coming in, unless the flag preserveCase is explicitly set.
+ * Automatically converts IUPAC bases to Ns, unless the flag preserveIUPAC is explicitly set.
+ */
+public class CachingIndexedFastaSequenceFile extends IndexedFastaSequenceFile {
+    protected static final org.apache.log4j.Logger logger = org.apache.log4j.Logger.getLogger(CachingIndexedFastaSequenceFile.class);
+
+    /** do we want to print debugging information about cache efficiency? */
+    private static final boolean PRINT_EFFICIENCY = false;
+
+    /** If we are printing efficiency info, what frequency should we do it at? */
+    private static final int PRINT_FREQUENCY = 10000;
+
+    /** The default cache size in bp */
+    public static final long DEFAULT_CACHE_SIZE = 1000000;
+
+    /** The cache size of this CachingIndexedFastaSequenceFile */
+    private final long cacheSize;
+
+    /** When we have a cache miss at position X, we load sequence from X - cacheMissBackup */
+    private final long cacheMissBackup;
+
+    /**
+     * If true, we will preserve the case of the original base in the genome
+     */
+    private final boolean preserveCase;
+
+    /**
+     * If true, we will preserve the IUPAC bases in the genome
+     */
+    private final boolean preserveIUPAC;
+
+    // information about checking efficiency
+    long cacheHits = 0;
+    long cacheMisses = 0;
+
+    /** Represents a specific cached sequence, with a specific start and stop, as well as the bases */
+    private static class Cache {
+        long start = -1, stop = -1;
+        ReferenceSequence seq = null;
+    }
+
+    /**
+     * Thread local cache to allow multi-threaded use of this class
+     */
+    private ThreadLocal<Cache> cache;
+    {
+        cache = new ThreadLocal<Cache> () {
+            @Override protected Cache initialValue() {
+                return new Cache();
+            }
+        };
+    }
+
+    /**
+     * Same as general constructor but allows one to override the default cacheSize
+     *
+     * @param fasta the file we will read our FASTA sequence from.
+     * @param index the index of the fasta file, used for efficient random access
+     * @param cacheSize the size in bp of the cache we will use for this reader
+     * @param preserveCase If true, we will keep the case of the underlying bases in the FASTA, otherwise everything is converted to upper case
+     * @param preserveIUPAC If true, we will keep the IUPAC bases in the FASTA, otherwise they are converted to Ns
+     */
+    public CachingIndexedFastaSequenceFile(final File fasta, final FastaSequenceIndex index, final long cacheSize, final boolean preserveCase, final boolean preserveIUPAC) {
+        super(fasta, index);
+        if ( cacheSize < 0 ) throw new IllegalArgumentException("cacheSize must be > 0");
+        this.cacheSize = cacheSize;
+        this.cacheMissBackup = Math.max(cacheSize / 1000, 1);
+        this.preserveCase = preserveCase;
+        this.preserveIUPAC = preserveIUPAC;
+    }
+
+    /**
+     * Open the given indexed fasta sequence file.  Throw an exception if the file cannot be opened.
+     *
+     * Looks for a index file for fasta on disk
+     * Uses provided cacheSize instead of the default
+     *
+     * @param fasta The file to open.
+     * @param cacheSize the size of the cache to use in this CachingIndexedFastaReader, must be >= 0
+     * @param preserveCase If true, we will keep the case of the underlying bases in the FASTA, otherwise everything is converted to upper case
+     */
+    public CachingIndexedFastaSequenceFile(final File fasta, final long cacheSize, final boolean preserveCase, final boolean  preserveIUPAC) throws FileNotFoundException {
+        super(fasta);
+        if ( cacheSize < 0 ) throw new IllegalArgumentException("cacheSize must be > 0");
+        this.cacheSize = cacheSize;
+        this.cacheMissBackup = Math.max(cacheSize / 1000, 1);
+        this.preserveCase = preserveCase;
+        this.preserveIUPAC = preserveIUPAC;
+    }
+
+    /**
+     * Same as general constructor but allows one to override the default cacheSize
+     *
+     * By default, this CachingIndexedFastaReader converts all incoming bases to upper case
+     *
+     * @param fasta the file we will read our FASTA sequence from.
+     * @param index the index of the fasta file, used for efficient random access
+     * @param cacheSize the size in bp of the cache we will use for this reader
+     */
+    public CachingIndexedFastaSequenceFile(final File fasta, final FastaSequenceIndex index, final long cacheSize) {
+        this(fasta, index, cacheSize, false, false);
+    }
+
+    /**
+     * Open the given indexed fasta sequence file.  Throw an exception if the file cannot be opened.
+     *
+     * Looks for a index file for fasta on disk.
+     * This CachingIndexedFastaReader will convert all FASTA bases to upper cases under the hood
+     *
+     * @param fasta The file to open.
+     */
+    public CachingIndexedFastaSequenceFile(final File fasta) throws FileNotFoundException {
+        this(fasta, false);
+    }
+
+    /**
+     * Open the given indexed fasta sequence file.  Throw an exception if the file cannot be opened.
+     *
+     * Looks for a index file for fasta on disk
+     *
+     * @param fasta The file to open.
+     * @param preserveCase If true, we will keep the case of the underlying bases in the FASTA, otherwise everything is converted to upper case
+     */
+    public CachingIndexedFastaSequenceFile(final File fasta, final boolean preserveCase) throws FileNotFoundException {
+        this(fasta, DEFAULT_CACHE_SIZE, preserveCase, false);
+    }
+
+    /**
+     * Open the given indexed fasta sequence file.  Throw an exception if the file cannot be opened.
+     *
+     * Looks for a index file for fasta on disk
+     * Uses provided cacheSize instead of the default
+     *
+     * @param fasta The file to open.
+     * @param cacheSize the size of the cache to use in this CachingIndexedFastaReader, must be >= 0
+     */
+    public CachingIndexedFastaSequenceFile(final File fasta, final long cacheSize ) throws FileNotFoundException {
+        this(fasta, cacheSize, false, false);
+    }
+
+    /**
+     * Print the efficiency (hits / queries) to logger with priority
+     */
+    public void printEfficiency(final Priority priority) {
+        logger.log(priority, String.format("### CachingIndexedFastaReader: hits=%d misses=%d efficiency %.6f%%", cacheHits, cacheMisses, calcEfficiency()));
+    }
+
+    /**
+     * Returns the efficiency (% of hits of all queries) of this object
+     * @return
+     */
+    public double calcEfficiency() {
+        return 100.0 * cacheHits / (cacheMisses + cacheHits * 1.0);
+    }
+
+    /**
+     * @return the number of cache hits that have occurred
+     */
+    public long getCacheHits() {
+        return cacheHits;
+    }
+
+    /**
+     * @return the number of cache misses that have occurred
+     */
+    public long getCacheMisses() {
+        return cacheMisses;
+    }
+
+    /**
+     * @return the size of the cache we are using
+     */
+    public long getCacheSize() {
+        return cacheSize;
+    }
+
+    /**
+     * Is this CachingIndexedFastaReader keeping the original case of bases in the fasta, or is
+     * everything being made upper case?
+     *
+     * @return true if the bases coming from this reader are in the original case in the fasta, false if they are all upper cased
+     */
+    public boolean isPreservingCase() {
+        return preserveCase;
+    }
+
+    /**
+     * Is uppercasing bases?
+     *
+     * @return true if bases coming from this CachingIndexedFastaSequenceFile are all upper cased, false if this reader are in the original case in the fasta
+     */
+    public boolean isUppercasingBases() {
+        return ! isPreservingCase();
+    }
+
+    /**
+     * Is this CachingIndexedFastaReader keeping the IUPAC bases in the fasta, or is it turning them into Ns?
+     *
+     * @return true if the IUPAC bases coming from this reader are not modified
+     */
+    public boolean isPreservingIUPAC() {
+        return preserveIUPAC;
+    }
+
+    /**
+     * Gets the subsequence of the contig in the range [start,stop]
+     *
+     * Uses the sequence cache if possible, or updates the cache to handle the request.  If the range
+     * is larger than the cache itself, just loads the sequence directly, not changing the cache at all
+     *
+     * @param contig Contig whose subsequence to retrieve.
+     * @param start inclusive, 1-based start of region.
+     * @param stop inclusive, 1-based stop of region.
+     * @return The partial reference sequence associated with this range.  If preserveCase is false, then
+     *         all of the bases in the ReferenceSequence returned by this method will be upper cased.
+     */
+    @Override
+    public ReferenceSequence getSubsequenceAt( final String contig, long start, final long stop ) {
+        final ReferenceSequence result;
+        final Cache myCache = cache.get();
+
+        if ( (stop - start) >= cacheSize ) {
+            cacheMisses++;
+            result = super.getSubsequenceAt(contig, start, stop);
+            if ( ! preserveCase ) StringUtil.toUpperCase(result.getBases());
+            if ( ! preserveIUPAC ) BaseUtils.convertIUPACtoN(result.getBases(), true, start < 1);
+        } else {
+            // todo -- potential optimization is to check if contig.name == contig, as this in general will be true
+            SAMSequenceRecord contigInfo = super.getSequenceDictionary().getSequence(contig);
+
+            if (stop > contigInfo.getSequenceLength())
+                throw new PicardException("Query asks for data past end of contig");
+
+            if ( start < myCache.start || stop > myCache.stop || myCache.seq == null || myCache.seq.getContigIndex() != contigInfo.getSequenceIndex() ) {
+                cacheMisses++;
+                myCache.start = Math.max(start - cacheMissBackup, 0);
+                myCache.stop  = Math.min(start + cacheSize + cacheMissBackup, contigInfo.getSequenceLength());
+                myCache.seq   = super.getSubsequenceAt(contig, myCache.start, myCache.stop);
+
+                // convert all of the bases in the sequence to upper case if we aren't preserving cases
+                if ( ! preserveCase ) StringUtil.toUpperCase(myCache.seq.getBases());
+                if ( ! preserveIUPAC ) BaseUtils.convertIUPACtoN(myCache.seq.getBases(), true, myCache.start == 0);
+            } else {
+                cacheHits++;
+            }
+
+            // at this point we determine where in the cache we want to extract the requested subsequence
+            final int cacheOffsetStart = (int)(start - myCache.start);
+            final int cacheOffsetStop = (int)(stop - start + cacheOffsetStart + 1);
+
+            try {
+                result = new ReferenceSequence(myCache.seq.getName(), myCache.seq.getContigIndex(), Arrays.copyOfRange(myCache.seq.getBases(), cacheOffsetStart, cacheOffsetStop));
+            } catch ( ArrayIndexOutOfBoundsException e ) {
+                throw new ReviewedGATKException(String.format("BUG: bad array indexing.  Cache start %d and end %d, request start %d end %d, offset start %d and end %d, base size %d",
+                        myCache.start, myCache.stop, start, stop, cacheOffsetStart, cacheOffsetStop, myCache.seq.getBases().length), e);
+            }
+        }
+
+        // for debugging -- print out our efficiency if requested
+        if ( PRINT_EFFICIENCY && (getCacheHits() + getCacheMisses()) % PRINT_FREQUENCY == 0 )
+            printEfficiency(Priority.INFO);
+
+        return result;
+    }
+}
\ No newline at end of file
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/fasta/package-info.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/fasta/package-info.java
new file mode 100644
index 0000000..ec94dac
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/fasta/package-info.java
@@ -0,0 +1,26 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.utils.fasta;
\ No newline at end of file
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/file/FSLockWithShared.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/file/FSLockWithShared.java
new file mode 100644
index 0000000..934a022
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/file/FSLockWithShared.java
@@ -0,0 +1,293 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.utils.file;
+
+import org.apache.log4j.Logger;
+import org.broadinstitute.gatk.utils.exceptions.UserException;
+
+import java.io.File;
+import java.io.IOException;
+import java.io.RandomAccessFile;
+import java.nio.channels.*;
+import java.util.concurrent.*;
+
+/**
+ * a quick implementation of a file based lock, using the Java NIO classes
+ */
+public class FSLockWithShared {
+    // connect to the logger
+    private final static Logger logger = Logger.getLogger(FSLockWithShared.class);
+
+    // the file we're attempting to lock
+    private final File file;
+
+    // the file lock
+    private FileLock lock = null;
+
+    // the file channel we open
+    private FileChannel channel = null;
+
+    // Timeout (in milliseconds) before we give up during non-blocking lock-acquisition calls.
+    // Necessary because these "non-blocking" calls can hang if there's a problem with the
+    // OS file locking support.
+    private int lockAcquisitionTimeout;
+
+    // Default value for lockAcquisitionTimeout when none is explicitly provided
+    public static final int DEFAULT_LOCK_ACQUISITION_TIMEOUT_IN_MILLISECONDS = 30 * 1000;
+
+    // Amount of time to wait when trying to shut down the lock-acquisition thread before giving up
+    public static final int THREAD_TERMINATION_TIMEOUT_IN_MILLISECONDS = 30 * 1000;
+
+    /**
+     * Create a lock associated with the specified File. Use the default lock
+     * acquisition timeout of 30 seconds.
+     *
+     * @param file file to lock
+     */
+    public FSLockWithShared( final File file ) {
+        this.file = file;
+        lockAcquisitionTimeout = DEFAULT_LOCK_ACQUISITION_TIMEOUT_IN_MILLISECONDS;
+    }
+
+    /**
+     * Create a lock associated with the specified File, and set a custom lock
+     * acquisition timeout.
+     *
+     * @param file file to lock
+     * @param lockAcquisitionTimeout maximum number of milliseconds to wait during non-blocking
+     *                               lock acquisition calls before concluding that there's a
+     *                               problem with the OS file locking support and throwing an error.
+     */
+    public FSLockWithShared( final File file, final int lockAcquisitionTimeout ) {
+        this.file = file;
+        this.lockAcquisitionTimeout = lockAcquisitionTimeout;
+    }
+
+    /**
+     * Get a shared (read) lock on a file. Does not block, and returns immediately
+     * under normal conditions with the result of the lock acquisition attempt. Will
+     * throw an exception if there's a problem with the OS file locking support.
+     *
+     * @return boolean true if we obtained a lock, false if we failed to obtain one
+     */
+    public boolean sharedLock() {
+        return acquireLockWithTimeout(true);
+    }
+
+    /**
+     * Get an exclusive (read-write) lock on a file. Does not block, and returns immediately
+     * under normal conditions with the result of the lock acquisition attempt. Will
+     * throw an exception if there's a problem with the OS file locking support.
+     *
+     * @return boolean true if we obtained a lock, false if we failed to obtain one
+     */
+    public boolean exclusiveLock() {
+        return acquireLockWithTimeout(false);
+    }
+
+    /**
+     * Attempt to acquire a lock of the specified type on the file in a background thread.
+     * Uses non-blocking lock-acquisition calls that should return immediately, but may
+     * get stuck if there's a problem with the OS file locking support. If the call gets
+     * stuck and the timeout elapses, throws a UserException, since it's not safe to
+     * proceed with a stuck lock acquisition thread (and there's no way to reliably
+     * interrupt it once the underlying system call hangs).
+     *
+     * @param acquireSharedLock if true, request a shared lock rather than an exclusive lock
+     * @return true if a lock was acquired, false if we failed
+     */
+    private boolean acquireLockWithTimeout( final boolean acquireSharedLock ) {
+        // Use daemon threads so that hopelessly stuck lock acquisition threads won't prevent the JVM from exiting
+        final ExecutorService executor = Executors.newSingleThreadExecutor(new ThreadFactory() {
+                                                                               public Thread newThread( Runnable r ) {
+                                                                                   Thread lockAcquisitionThread = new Thread(r);
+                                                                                   lockAcquisitionThread.setDaemon(true);
+                                                                                   return lockAcquisitionThread;
+                                                                               }
+                                                                           });
+        final FutureTask<Boolean> lockAcquisitionTask = new FutureTask<Boolean>(new LockAcquisitionTask(acquireSharedLock));
+        boolean lockAcquired = false;
+
+        try {
+            executor.execute(lockAcquisitionTask);
+
+            // Wait at most lockAcquisitionTimeout milliseconds for the lock acquisition task to finish.
+            lockAcquired = lockAcquisitionTask.get(lockAcquisitionTimeout, TimeUnit.MILLISECONDS);
+        }
+        // Lock acquisition timeout elapsed. Since we're using NON-BLOCKING lock-acquisition calls,
+        // this implies that there's a problem with the OS locking daemon, or locks are not supported.
+        // Since it's not safe to proceed with a potentially stuck lock acquisition thread, we need to
+        // shut down the JVM in order to kill it.
+        catch ( TimeoutException e ) {
+            throw new UserException.FileSystemInabilityToLockException(
+                    String.format("Timeout of %d milliseconds was reached while trying to acquire a lock on file %s. " +
+                                  "Since the GATK uses non-blocking lock acquisition calls that are not supposed to wait, " +
+                                  "this implies a problem with the file locking support in your operating system.",
+                                  lockAcquisitionTimeout, file.getAbsolutePath()));
+        }
+        // Lock acquisition thread threw an exception. Need to unpack it via e.getCause()
+        catch ( ExecutionException e ) {
+            logger.warn(String.format("WARNING: Unable to lock file %s because exception %s occurred with error message %s",
+                                      file.getAbsolutePath(),
+                                      e.getCause() != null ? e.getCause().getClass().getSimpleName() : "unknown",
+                                      e.getCause() != null ? e.getCause().getMessage() : "none"));
+            lockAcquired = false;
+        }
+        // Interrupted while waiting for the lock acquisition thread -- not likely to happen
+        catch ( InterruptedException e ) {
+            logger.warn(String.format("WARNING: interrupted while attempting to acquire a lock for file %s", file.getAbsolutePath()));
+            lockAcquired = false;
+        }
+        catch ( Exception e ) {
+            logger.warn(String.format("WARNING: error while attempting to acquire a lock for file %s. Error message: %s",
+                                      file.getAbsolutePath(), e.getMessage()));
+            lockAcquired = false;
+        }
+
+        shutdownLockAcquisitionTask(executor);
+
+        // Upon failure to acquire a lock, we always call unlock() to close the FileChannel if it was opened
+        // and to deal with very hypothetical edge cases where a lock might actually have been acquired despite the
+        // lock acquisition thread returning false.
+        if ( ! lockAcquired ) {
+            unlock();
+        }
+
+        return lockAcquired;
+    }
+
+    /**
+     * Ensures that the lock acquisition task running in the provided executor has cleanly terminated.
+     * Throws a UserException if unable to shut it down within the period defined by the THREAD_TERMINATION_TIMEOUT.
+     *
+     * @param executor ExecutorService executing the lock-acquisition thread
+     */
+    private void shutdownLockAcquisitionTask( final ExecutorService executor ) {
+        boolean shutdownAttemptSucceeded;
+
+        try {
+            executor.shutdownNow();
+            shutdownAttemptSucceeded = executor.awaitTermination(THREAD_TERMINATION_TIMEOUT_IN_MILLISECONDS, TimeUnit.MILLISECONDS);
+        }
+        catch ( InterruptedException e ) {
+            shutdownAttemptSucceeded = false;
+        }
+
+        if ( ! shutdownAttemptSucceeded ) {
+            throw new UserException(String.format("Failed to terminate lock acquisition thread while trying to lock file %s. " +
+                                                  "Exiting because it's not safe to proceed with this run of the GATK.",
+                                                  file.getAbsolutePath()));
+        }
+    }
+
+    /**
+     * Background task that attempts to acquire a lock of the specified type, and returns a boolean
+     * indicating success/failure. Uses a non-blocking tryLock() call that should return immediately
+     * (but may get stuck if there's a problem with the OS locking daemon).
+     */
+    private class LockAcquisitionTask implements Callable<Boolean> {
+        private final boolean acquireSharedLock;
+
+        public LockAcquisitionTask( final boolean acquireSharedLock ) {
+            this.acquireSharedLock = acquireSharedLock;
+        }
+
+        public Boolean call() {
+            // Get a read-only or read-write file channel, depending on the type of lock
+            try {
+                channel = new RandomAccessFile(file, acquireSharedLock ? "r" : "rw").getChannel();
+            }
+            catch ( IOException e ) {
+                logger.warn(String.format("WARNING: Unable to lock file %s because we could not open a file channel", file.getAbsolutePath()));
+                return false;
+            }
+
+            boolean lockAcquired = false;
+
+            try {
+                // Non-blocking lock-acquisition call, should return right away. If it doesn't return immediately
+                // due to problems with the OS locking daemon, it will potentially be timed-out and interrupted.
+                lock = channel.tryLock(0, Long.MAX_VALUE, acquireSharedLock);
+                lockAcquired = lock != null;
+            }
+            catch ( AsynchronousCloseException e ) {
+                logger.warn(String.format("WARNING: Unable to lock file %s because the file channel was closed by another thread", file.getAbsolutePath()));
+                lockAcquired = false;
+            }
+            catch ( ClosedChannelException e ) {
+                logger.warn(String.format("WARNING: Unable to lock file %s because the file channel is closed.", file.getAbsolutePath()));
+                lockAcquired = false;
+            }
+            catch ( OverlappingFileLockException e ) {
+                logger.warn(String.format("WARNING: Unable to lock file %s because you already have a lock on this file.", file.getAbsolutePath()));
+                lockAcquired = false;
+            }
+            catch ( FileLockInterruptionException e ) {
+                logger.warn(String.format("WARNING: Interrupted while attempting to lock file %s", file.getAbsolutePath()));
+                lockAcquired = false;
+            }
+            catch ( IOException e ) {
+                logger.warn(String.format("WARNING: Unable to lock file %s because an IOException occurred with message: %s.", file.getAbsolutePath(), e.getMessage()));
+                lockAcquired = false;
+            }
+
+            return lockAcquired;
+        }
+    }
+
+    /**
+     * Unlock the file
+     *
+     * note: this allows unlocking a file that failed to lock (no required user checks on null locks).
+     */
+    public void unlock() {
+        releaseLock();
+        closeChannel();
+    }
+
+    private void releaseLock() {
+        try {
+            if ( lock != null )
+                lock.release();
+        }
+        catch ( ClosedChannelException e ) {
+            // if the channel was already closed we don't have to worry
+        }
+        catch ( IOException e ) {
+            throw new UserException(String.format("An error occurred while releasing the lock for file %s", file.getAbsolutePath()), e);
+        }
+    }
+
+    private void closeChannel() {
+        try {
+            if ( channel != null )
+                channel.close();
+        }
+        catch ( IOException e ) {
+            throw new UserException(String.format("An error occurred while closing channel for file %s", file.getAbsolutePath()), e);
+        }
+    }
+}
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/fragments/FragmentCollection.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/fragments/FragmentCollection.java
new file mode 100644
index 0000000..67d55ff
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/fragments/FragmentCollection.java
@@ -0,0 +1,67 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.utils.fragments;
+
+import java.util.Collection;
+import java.util.Collections;
+import java.util.List;
+
+/**
+ * Useful helper class to represent the results of the reads -> fragment calculation.
+ *
+ * Contains singleton -- objects whose underlying reads do not overlap their mate pair
+ * Contains overlappingPairs -- objects whose underlying reads do overlap their mate pair
+ *
+ * User: ebanks, depristo
+ * Date: Jan 10, 2011
+ */
+public class FragmentCollection<T> {
+    Collection<T> singletons;
+    Collection<List<T>> overlappingPairs;
+
+    public FragmentCollection(final Collection<T> singletons, final Collection<List<T>> overlappingPairs) {
+        this.singletons = singletons == null ? Collections.<T>emptyList() : singletons;
+        this.overlappingPairs = overlappingPairs == null ? Collections.<List<T>>emptyList() : overlappingPairs;
+    }
+
+    /**
+     * Gets the T elements not containing overlapping elements, in no particular order
+     *
+     * @return
+     */
+    public Collection<T> getSingletonReads() {
+        return singletons;
+    }
+
+    /**
+     * Gets the T elements containing overlapping elements, in no particular order
+     *
+     * @return
+     */
+    public Collection<List<T>> getOverlappingPairs() {
+        return overlappingPairs;
+    }
+}
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/fragments/FragmentUtils.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/fragments/FragmentUtils.java
new file mode 100644
index 0000000..689fdf6
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/fragments/FragmentUtils.java
@@ -0,0 +1,377 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.utils.fragments;
+
+import com.google.java.contract.Ensures;
+import com.google.java.contract.Requires;
+import htsjdk.samtools.util.QualityUtil;
+import htsjdk.samtools.Cigar;
+import htsjdk.samtools.CigarElement;
+import htsjdk.samtools.CigarOperator;
+import htsjdk.samtools.SAMRecord;
+import org.broadinstitute.gatk.utils.clipping.ReadClipper;
+import org.broadinstitute.gatk.utils.recalibration.EventType;
+import org.broadinstitute.gatk.utils.collections.Pair;
+import org.broadinstitute.gatk.utils.exceptions.ReviewedGATKException;
+import org.broadinstitute.gatk.utils.pileup.PileupElement;
+import org.broadinstitute.gatk.utils.pileup.ReadBackedPileup;
+import org.broadinstitute.gatk.utils.sam.GATKSAMRecord;
+import org.broadinstitute.gatk.utils.sam.ReadUtils;
+
+import java.util.*;
+
+/**
+ * An easy to access fragment-based pileup, which contains two separate pileups.  The first
+ * is a regular collection of PileupElements containing all of the reads in the original RBP
+ * that uniquely info about a fragment.  The second are TwoReadPileupElements that, as the
+ * name suggests, contain two reads that are sequenced from the same underlying fragment.
+ *
+ * Based on the original code by E. Banks
+ *
+ * Oct 21: note that the order of the oneReadPileup and twoReadPileups are not
+ * defined.  The algorithms that produce these lists are in fact producing
+ * lists of Pileup elements *NOT* sorted by alignment start position of the underlying
+ * reads.
+ *
+ * User: depristo
+ * Date: 3/26/11
+ * Time: 10:09 PM
+ */
+public final class FragmentUtils {
+
+    public final static double DEFAULT_PCR_ERROR_RATE = 1e-4;
+    public final static int DEFAULT_PCR_ERROR_QUAL = QualityUtil.getPhredScoreFromErrorProbability(DEFAULT_PCR_ERROR_RATE);
+    public final static int HALF_OF_DEFAULT_PCR_ERROR_QUAL = DEFAULT_PCR_ERROR_QUAL / 2;
+
+    protected final static byte MIN_QUAL_BAD_OVERLAP = 16;
+    private FragmentUtils() {} // private constructor
+
+    /**
+     * A getter function that takes an Object of type T and returns its associated SAMRecord.
+     *
+     * Allows us to write a generic T -> Fragment algorithm that works with any object containing
+     * a read.
+     *
+     * @param <T> The type of the object that contains a GATKSAMRecord
+     */
+    public interface ReadGetter<T> {
+        /**
+         * Get the GATKSAMRecord associated with object
+         *
+         * @param object the thing that contains the read
+         * @return a non-null GATKSAMRecord read
+         */
+        public GATKSAMRecord get(T object);
+    }
+
+    /**
+     * Identify getter for SAMRecords themselves
+     */
+    private final static ReadGetter<GATKSAMRecord> SamRecordGetter = new ReadGetter<GATKSAMRecord>() {
+        @Override public GATKSAMRecord get(final GATKSAMRecord object) { return object; }
+    };
+
+    /**
+     * Gets the SAMRecord in a PileupElement
+     */
+    private final static ReadGetter<PileupElement> PileupElementGetter = new ReadGetter<PileupElement>() {
+        @Override public GATKSAMRecord get(final PileupElement object) { return object.getRead(); }
+    };
+
+
+    /**
+     * Generic algorithm that takes an iterable over T objects, a getter routine to extract the reads in T,
+     * and returns a FragmentCollection that contains the T objects whose underlying reads either overlap (or
+     * not) with their mate pairs.
+     *
+     * @param readContainingObjects An iterator of objects that contain GATKSAMRecords
+     * @param nElements the number of elements to be provided by the iterator, which is usually known upfront and
+     *                  greatly improves the efficiency of the fragment calculation
+     * @param getter a helper function that takes an object of type T and returns is associated GATKSAMRecord
+     * @param <T>
+     * @return a fragment collection
+     */
+    @Requires({
+            "readContainingObjects != null",
+            "nElements >= 0",
+            "getter != null"
+    })
+    @Ensures("result != null")
+    private static <T> FragmentCollection<T> create(final Iterable<T> readContainingObjects, final int nElements, final ReadGetter<T> getter) {
+        Collection<T> singletons = null;
+        Collection<List<T>> overlapping = null;
+        Map<String, T> nameMap = null;
+
+        int lastStart = -1;
+
+        // build an initial map, grabbing all of the multi-read fragments
+        for ( final T p : readContainingObjects ) {
+            final SAMRecord read = getter.get(p);
+
+            if ( read.getAlignmentStart() < lastStart ) {
+                throw new IllegalArgumentException(String.format(
+                        "FragmentUtils.create assumes that the incoming objects are ordered by " +
+                                "SAMRecord alignment start, but saw a read %s with alignment start " +
+                                "%d before the previous start %d", read.getSAMString(), read.getAlignmentStart(), lastStart));
+            }
+            lastStart = read.getAlignmentStart();
+
+            final int mateStart = read.getMateAlignmentStart();
+            if ( mateStart == 0 || mateStart > read.getAlignmentEnd() ) {
+                // if we know that this read won't overlap its mate, or doesn't have one, jump out early
+                if ( singletons == null ) singletons = new ArrayList<T>(nElements); // lazy init
+                singletons.add(p);
+            } else {
+                // the read might overlap it's mate, or is the rightmost read of a pair
+                final String readName = read.getReadName();
+                final T pe1 = nameMap == null ? null : nameMap.get(readName);
+                if ( pe1 != null ) {
+                    // assumes we have at most 2 reads per fragment
+                    if ( overlapping == null ) overlapping = new ArrayList<List<T>>(); // lazy init
+                    overlapping.add(Arrays.asList(pe1, p));
+                    nameMap.remove(readName);
+                } else {
+                    if ( nameMap == null ) nameMap = new HashMap<String, T>(nElements); // lazy init
+                    nameMap.put(readName, p);
+                }
+            }
+        }
+
+        // add all of the reads that are potentially overlapping but whose mate never showed
+        // up to the oneReadPile
+        if ( nameMap != null && ! nameMap.isEmpty() ) {
+            if ( singletons == null )
+                singletons = nameMap.values();
+            else
+                singletons.addAll(nameMap.values());
+        }
+
+        return new FragmentCollection<T>(singletons, overlapping);
+    }
+
+    /**
+     * Create a FragmentCollection containing PileupElements from the ReadBackedPileup rbp
+     * @param rbp a non-null read-backed pileup.  The elements in this ReadBackedPileup must be ordered
+     * @return a non-null FragmentCollection
+     */
+    @Ensures("result != null")
+    public static FragmentCollection<PileupElement> create(final ReadBackedPileup rbp) {
+        if ( rbp == null ) throw new IllegalArgumentException("Pileup cannot be null");
+        return create(rbp, rbp.getNumberOfElements(), PileupElementGetter);
+    }
+
+    /**
+     * Create a FragmentCollection containing GATKSAMRecords from a list of reads
+     *
+     * @param reads a non-null list of reads, ordered by their start location
+     * @return a non-null FragmentCollection
+     */
+    @Ensures("result != null")
+    public static FragmentCollection<GATKSAMRecord> create(final List<GATKSAMRecord> reads) {
+        if ( reads == null ) throw new IllegalArgumentException("Pileup cannot be null");
+        return create(reads, reads.size(), SamRecordGetter);
+    }
+
+    public static void adjustQualsOfOverlappingPairedFragments( final List<GATKSAMRecord> overlappingPair ) {
+        if( overlappingPair.size() != 2 ) { throw new ReviewedGATKException("Found overlapping pair with " + overlappingPair.size() + " reads, but expecting exactly 2."); }
+
+        final GATKSAMRecord firstRead = overlappingPair.get(0);
+        final GATKSAMRecord secondRead = overlappingPair.get(1);
+
+        if ( secondRead.getSoftStart() < firstRead.getSoftStart() ) {
+            adjustQualsOfOverlappingPairedFragments(secondRead, firstRead);
+        } else {
+            adjustQualsOfOverlappingPairedFragments(firstRead, secondRead);
+        }
+    }
+
+    /**
+     * Fix two overlapping reads from the same fragment by adjusting base qualities, if possible
+     *
+     * firstRead and secondRead must be part of the same fragment (though this isn't checked).  Looks
+     * at the bases and alignment, and tries its best to create adjusted base qualities so that the observations
+     * are not treated independently.
+     *
+     * Assumes that firstRead starts before secondRead (according to their soft clipped starts)
+     *
+     * @param clippedFirstRead the left most read
+     * @param clippedSecondRead the right most read
+     *
+     * @return a strandless merged read of first and second, or null if the algorithm cannot create a meaningful one
+     */
+    public static void adjustQualsOfOverlappingPairedFragments(final GATKSAMRecord clippedFirstRead, final GATKSAMRecord clippedSecondRead) {
+        if ( clippedFirstRead == null ) throw new IllegalArgumentException("clippedFirstRead cannot be null");
+        if ( clippedSecondRead == null ) throw new IllegalArgumentException("clippedSecondRead cannot be null");
+        if ( ! clippedFirstRead.getReadName().equals(clippedSecondRead.getReadName()) ) throw new IllegalArgumentException("attempting to merge two reads with different names " + clippedFirstRead + " and " + clippedSecondRead);
+
+        // don't adjust fragments that do not overlap
+        if ( clippedFirstRead.getAlignmentEnd() < clippedSecondRead.getAlignmentStart() || !clippedFirstRead.getReferenceIndex().equals(clippedSecondRead.getReferenceIndex()) )
+            return;
+
+        final Pair<Integer, Boolean> pair = ReadUtils.getReadCoordinateForReferenceCoordinate(clippedFirstRead, clippedSecondRead.getAlignmentStart());
+        final int firstReadStop = ( pair.getSecond() ? pair.getFirst() + 1 : pair.getFirst() );
+        final int numOverlappingBases = Math.min(clippedFirstRead.getReadLength() - firstReadStop, clippedSecondRead.getReadLength());
+
+        final byte[] firstReadBases = clippedFirstRead.getReadBases();
+        final byte[] firstReadQuals = clippedFirstRead.getBaseQualities();
+        final byte[] secondReadBases = clippedSecondRead.getReadBases();
+        final byte[] secondReadQuals = clippedSecondRead.getBaseQualities();
+
+        for ( int i = 0; i < numOverlappingBases; i++ ) {
+            final int firstReadIndex = firstReadStop + i;
+            final byte firstReadBase = firstReadBases[firstReadIndex];
+            final byte secondReadBase = secondReadBases[i];
+
+            if ( firstReadBase == secondReadBase ) {
+                firstReadQuals[firstReadIndex] = (byte) Math.min(firstReadQuals[firstReadIndex], HALF_OF_DEFAULT_PCR_ERROR_QUAL);
+                secondReadQuals[i] = (byte) Math.min(secondReadQuals[i], HALF_OF_DEFAULT_PCR_ERROR_QUAL);
+            } else {
+                // TODO -- use the proper statistical treatment of the quals from DiploidSNPGenotypeLikelihoods.java
+                firstReadQuals[firstReadIndex] = 0;
+                secondReadQuals[i] = 0;
+            }
+        }
+
+        clippedFirstRead.setBaseQualities(firstReadQuals);
+        clippedSecondRead.setBaseQualities(secondReadQuals);
+    }
+
+    public static List<GATKSAMRecord> mergeOverlappingPairedFragments( final List<GATKSAMRecord> overlappingPair ) {
+        if( overlappingPair.size() != 2 ) { throw new ReviewedGATKException("Found overlapping pair with " + overlappingPair.size() + " reads, but expecting exactly 2."); }
+
+        final GATKSAMRecord firstRead = overlappingPair.get(0);
+        final GATKSAMRecord secondRead = overlappingPair.get(1);
+
+        final GATKSAMRecord merged;
+        if( !(secondRead.getSoftStart() <= firstRead.getSoftEnd() && secondRead.getSoftStart() >= firstRead.getSoftStart() && secondRead.getSoftEnd() >= firstRead.getSoftEnd()) ) {
+            merged = mergeOverlappingPairedFragments(secondRead, firstRead);
+        } else {
+            merged = mergeOverlappingPairedFragments(firstRead, secondRead);
+        }
+
+        return merged == null ? overlappingPair : Collections.singletonList(merged);
+    }
+
+    /**
+     * Merge two overlapping reads from the same fragment into a single super read, if possible
+     *
+     * firstRead and secondRead must be part of the same fragment (though this isn't checked).  Looks
+     * at the bases and alignment, and tries its best to create a meaningful synthetic single super read
+     * that represents the entire sequenced fragment.
+     *
+     * Assumes that firstRead starts before secondRead (according to their soft clipped starts)
+     *
+     * @param unclippedFirstRead the left most read
+     * @param unclippedSecondRead the right most read
+     *
+     * @return a strandless merged read of first and second, or null if the algorithm cannot create a meaningful one
+     */
+    public static GATKSAMRecord mergeOverlappingPairedFragments(final GATKSAMRecord unclippedFirstRead, final GATKSAMRecord unclippedSecondRead) {
+        if ( unclippedFirstRead == null ) throw new IllegalArgumentException("unclippedFirstRead cannot be null");
+        if ( unclippedSecondRead == null ) throw new IllegalArgumentException("unclippedSecondRead cannot be null");
+        if ( ! unclippedFirstRead.getReadName().equals(unclippedSecondRead.getReadName()) ) throw new IllegalArgumentException("attempting to merge two reads with different names " + unclippedFirstRead + " and " + unclippedSecondRead);
+
+        if( unclippedFirstRead.getCigarString().contains("I") || unclippedFirstRead.getCigarString().contains("D") || unclippedSecondRead.getCigarString().contains("I") || unclippedSecondRead.getCigarString().contains("D") ) {
+            return null; // fragments contain indels so don't merge them
+        }
+
+        final GATKSAMRecord firstRead = ReadClipper.hardClipAdaptorSequence(ReadClipper.revertSoftClippedBases(unclippedFirstRead));
+        final GATKSAMRecord secondRead = ReadClipper.hardClipAdaptorSequence(ReadClipper.revertSoftClippedBases(unclippedSecondRead));
+
+        if( !(secondRead.getSoftStart() <= firstRead.getSoftEnd() && secondRead.getSoftStart() >= firstRead.getSoftStart() && secondRead.getSoftEnd() >= firstRead.getSoftEnd()) ) {
+            return null; // can't merge them, yet:  AAAAAAAAAAA-BBBBBBBBBBB-AAAAAAAAAAAAAA, B is contained entirely inside A
+        }
+
+        final Pair<Integer, Boolean> pair = ReadUtils.getReadCoordinateForReferenceCoordinate(firstRead, secondRead.getAlignmentStart());
+
+        final int firstReadStop = ( pair.getSecond() ? pair.getFirst() + 1 : pair.getFirst() );
+        final int numBases = firstReadStop + secondRead.getReadLength();
+        final byte[] bases = new byte[numBases];
+        final byte[] quals = new byte[numBases];
+        final byte[] insertionQuals = new byte[numBases];
+        final byte[] deletionQuals = new byte[numBases];
+        final byte[] firstReadBases = firstRead.getReadBases();
+        final byte[] firstReadQuals = firstRead.getBaseQualities();
+        final byte[] secondReadBases = secondRead.getReadBases();
+        final byte[] secondReadQuals = secondRead.getBaseQualities();
+
+        for(int iii = 0; iii < firstReadStop; iii++) {
+            bases[iii] = firstReadBases[iii];
+            quals[iii] = firstReadQuals[iii];
+        }
+        for(int iii = firstReadStop; iii < firstRead.getReadLength(); iii++) {
+            if( firstReadQuals[iii] > MIN_QUAL_BAD_OVERLAP && secondReadQuals[iii-firstReadStop] > MIN_QUAL_BAD_OVERLAP && firstReadBases[iii] != secondReadBases[iii-firstReadStop] ) {
+                return null; // high qual bases don't match exactly, probably indel in only one of the fragments, so don't merge them
+            }
+            if( firstReadQuals[iii] < MIN_QUAL_BAD_OVERLAP && secondReadQuals[iii-firstReadStop] < MIN_QUAL_BAD_OVERLAP ) {
+                return null; // both reads have low qual bases in the overlap region so don't merge them because don't know what is going on
+            }
+            bases[iii] = ( firstReadQuals[iii] > secondReadQuals[iii-firstReadStop] ? firstReadBases[iii] : secondReadBases[iii-firstReadStop] );
+            quals[iii] = ( firstReadQuals[iii] > secondReadQuals[iii-firstReadStop] ? firstReadQuals[iii] : secondReadQuals[iii-firstReadStop] );
+        }
+        for(int iii = firstRead.getReadLength(); iii < numBases; iii++) {
+            bases[iii] = secondReadBases[iii-firstReadStop];
+            quals[iii] = secondReadQuals[iii-firstReadStop];
+        }
+
+        final GATKSAMRecord returnRead = new GATKSAMRecord( firstRead.getHeader() );
+        returnRead.setIsStrandless(true);
+        returnRead.setAlignmentStart( firstRead.getAlignmentStart() );
+        returnRead.setReadBases( bases );
+        returnRead.setBaseQualities( quals );
+        returnRead.setReadGroup( firstRead.getReadGroup() );
+        returnRead.setReferenceName( firstRead.getReferenceName() );
+        returnRead.setReadName( firstRead.getReadName() );
+        final CigarElement c = new CigarElement(bases.length, CigarOperator.M);
+        final ArrayList<CigarElement> cList = new ArrayList<CigarElement>();
+        cList.add(c);
+        returnRead.setCigar( new Cigar( cList ));
+        returnRead.setMappingQuality( firstRead.getMappingQuality() );
+
+        if( firstRead.hasBaseIndelQualities() || secondRead.hasBaseIndelQualities() ) {
+            final byte[] firstReadInsertionQuals = firstRead.getBaseInsertionQualities();
+            final byte[] firstReadDeletionQuals = firstRead.getBaseDeletionQualities();
+            final byte[] secondReadInsertionQuals = secondRead.getBaseInsertionQualities();
+            final byte[] secondReadDeletionQuals = secondRead.getBaseDeletionQualities();
+            for(int iii = 0; iii < firstReadStop; iii++) {
+                insertionQuals[iii] = firstReadInsertionQuals[iii];
+                deletionQuals[iii] = firstReadDeletionQuals[iii];
+            }
+            for(int iii = firstReadStop; iii < firstRead.getReadLength(); iii++) {
+                insertionQuals[iii] = ( firstReadQuals[iii] > secondReadQuals[iii-firstReadStop] ? firstReadInsertionQuals[iii] : secondReadInsertionQuals[iii-firstReadStop] ); // Purposefully checking the highest *base* quality score
+                deletionQuals[iii] = ( firstReadQuals[iii] > secondReadQuals[iii-firstReadStop] ? firstReadDeletionQuals[iii] : secondReadDeletionQuals[iii-firstReadStop] ); // Purposefully checking the highest *base* quality score
+            }
+            for(int iii = firstRead.getReadLength(); iii < numBases; iii++) {
+                insertionQuals[iii] = secondReadInsertionQuals[iii-firstReadStop];
+                deletionQuals[iii] = secondReadDeletionQuals[iii-firstReadStop];
+            }
+            returnRead.setBaseQualities( insertionQuals, EventType.BASE_INSERTION );
+            returnRead.setBaseQualities( deletionQuals, EventType.BASE_DELETION );
+        }
+
+        return returnRead;
+    }
+}
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/genotyper/DiploidGenotype.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/genotyper/DiploidGenotype.java
new file mode 100644
index 0000000..f836f44
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/genotyper/DiploidGenotype.java
@@ -0,0 +1,125 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.utils.genotyper;
+
+import org.broadinstitute.gatk.utils.BaseUtils;
+
+public enum DiploidGenotype {
+    AA ('A', 'A'),
+    AC ('A', 'C'),
+    CC ('C', 'C'),
+    AG ('A', 'G'),
+    CG ('C', 'G'),
+    GG ('G', 'G'),
+    AT ('A', 'T'),
+    CT ('C', 'T'),
+    GT ('G', 'T'),
+    TT ('T', 'T');
+
+    public byte base1, base2;
+
+    @Deprecated
+    private DiploidGenotype(char base1, char base2) {
+        this((byte)base1, (byte)base2);
+    }
+
+    private DiploidGenotype(byte base1, byte base2) {
+        this.base1 = base1;
+        this.base2 = base2;
+    }
+
+    public boolean isHomRef(byte r) {
+        return isHom() && r == base1;
+    }
+
+    public boolean isHomVar(byte r) {
+        return isHom() && r != base1;
+    }
+
+    public boolean isHetRef(byte r) {
+        if ( base1 == r )
+            return r != base2;
+        else
+            return base2 == r;
+    }
+
+    public boolean isHom() {
+        return ! isHet();
+    }
+
+    public boolean isHet() {
+        return base1 != base2;
+    }
+
+    /**
+     * create a diploid genotype, given a character to make into a hom genotype
+     * @param hom the character to turn into a hom genotype, i.e. if it is A, then returned will be AA
+     * @return the diploid genotype
+     */
+    public static DiploidGenotype createHomGenotype(byte hom) {
+        int index = BaseUtils.simpleBaseToBaseIndex(hom);
+        if ( index == -1 )
+            throw new IllegalArgumentException(hom + " is not a valid base character");
+        return conversionMatrix[index][index];
+    }
+
+    /**
+     * create a diploid genotype, given 2 chars which may not necessarily be ordered correctly
+     * @param base1 base1
+     * @param base2 base2
+     * @return the diploid genotype
+     */
+    public static DiploidGenotype createDiploidGenotype(byte base1, byte base2) {
+        int index1 = BaseUtils.simpleBaseToBaseIndex(base1);
+        if ( index1 == -1 )
+            throw new IllegalArgumentException(base1 + " is not a valid base character");
+        int index2 = BaseUtils.simpleBaseToBaseIndex(base2);
+        if ( index2 == -1 )
+            throw new IllegalArgumentException(base2 + " is not a valid base character");
+        return conversionMatrix[index1][index2];
+    }
+
+    /**
+     * create a diploid genotype, given 2 base indexes which may not necessarily be ordered correctly
+     * @param baseIndex1 base1
+     * @param baseIndex2 base2
+     * @return the diploid genotype
+     */
+    public static DiploidGenotype createDiploidGenotype(int baseIndex1, int baseIndex2) {
+        if ( baseIndex1 == -1 )
+            throw new IllegalArgumentException(baseIndex1 + " does not represent a valid base character");
+        if ( baseIndex2 == -1 )
+            throw new IllegalArgumentException(baseIndex2 + " does not represent a valid base character");
+        return conversionMatrix[baseIndex1][baseIndex2];
+    }
+
+    private static final DiploidGenotype[][] conversionMatrix = {
+            { DiploidGenotype.AA, DiploidGenotype.AC, DiploidGenotype.AG, DiploidGenotype.AT },
+            { DiploidGenotype.AC, DiploidGenotype.CC, DiploidGenotype.CG, DiploidGenotype.CT },
+            { DiploidGenotype.AG, DiploidGenotype.CG, DiploidGenotype.GG, DiploidGenotype.GT },
+            { DiploidGenotype.AT, DiploidGenotype.CT, DiploidGenotype.GT, DiploidGenotype.TT }
+    };
+}
\ No newline at end of file
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/genotyper/MostLikelyAllele.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/genotyper/MostLikelyAllele.java
new file mode 100644
index 0000000..65c1fd0
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/genotyper/MostLikelyAllele.java
@@ -0,0 +1,134 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.utils.genotyper;
+
+import org.broadinstitute.gatk.utils.MathUtils;
+import htsjdk.variant.variantcontext.Allele;
+
+/**
+ * Stores the most likely and second most likely alleles, along with a threshold
+ * for assuming computing that a read is informative.
+ *
+ * If the difference between the most-likely allele and the next-most-likely allele is < INFORMATIVE_LIKELIHOOD_THRESHOLD
+ * then the most likely allele is set to "no call", and isInformative will return false.  This constant can be
+ * overridden simply by using one of the version of these calls that accepts informative threshold as an argument.
+ *
+ * For convenience, there are functions called getAlleleIfInformative that return either the most likely allele, or
+ * NO_CALL if two or more alleles have likelihoods within INFORMATIVE_LIKELIHOOD_THRESHOLD of one another.
+ *
+ * By default empty allele maps will return NO_CALL, and allele maps with a single entry will return the
+ * corresponding key
+ *
+ * User: depristo
+ * Date: 3/24/13
+ * Time: 1:39 PM
+ */
+public final class MostLikelyAllele {
+    public static final double INFORMATIVE_LIKELIHOOD_THRESHOLD = 0.2;
+
+    final Allele mostLikely;
+    final Allele secondLikely;
+    final double log10LikelihoodOfMostLikely;
+    final double log10LikelihoodOfSecondBest;
+
+    /**
+     * Create a new MostLikelyAllele
+     *
+     * If there's a meaningful most likely allele, allele should be a real allele.  If none can be determined,
+     * mostLikely should be a NO_CALL allele.
+     *
+     * @param mostLikely the most likely allele
+     * @param secondMostLikely the most likely allele after mostLikely
+     * @param log10LikelihoodOfMostLikely the log10 likelihood of the most likely allele
+     * @param log10LikelihoodOfSecondBest the log10 likelihood of the next most likely allele (should be NEGATIVE_INFINITY if none is available)
+     */
+    public MostLikelyAllele(final Allele mostLikely, final Allele secondMostLikely, double log10LikelihoodOfMostLikely, double log10LikelihoodOfSecondBest) {
+        if ( mostLikely == null ) throw new IllegalArgumentException("mostLikely allele cannot be null");
+        if ( log10LikelihoodOfMostLikely != Double.NEGATIVE_INFINITY && ! MathUtils.goodLog10Probability(log10LikelihoodOfMostLikely) )
+            throw new IllegalArgumentException("log10LikelihoodOfMostLikely must be either -Infinity or a good log10 prob but got " + log10LikelihoodOfMostLikely);
+        if ( log10LikelihoodOfSecondBest != Double.NEGATIVE_INFINITY && ! MathUtils.goodLog10Probability(log10LikelihoodOfSecondBest) )
+            throw new IllegalArgumentException("log10LikelihoodOfSecondBest must be either -Infinity or a good log10 prob but got " + log10LikelihoodOfSecondBest);
+        if ( log10LikelihoodOfMostLikely < log10LikelihoodOfSecondBest )
+            throw new IllegalArgumentException("log10LikelihoodOfMostLikely must be <= log10LikelihoodOfSecondBest but got " + log10LikelihoodOfMostLikely + " vs 2nd " + log10LikelihoodOfSecondBest);
+
+        this.mostLikely = mostLikely;
+        this.secondLikely = secondMostLikely;
+        this.log10LikelihoodOfMostLikely = log10LikelihoodOfMostLikely;
+        this.log10LikelihoodOfSecondBest = log10LikelihoodOfSecondBest;
+    }
+
+    public Allele getMostLikelyAllele() {
+        return mostLikely;
+    }
+
+    public Allele getSecondMostLikelyAllele() {
+        return secondLikely;
+    }
+
+    public double getLog10LikelihoodOfMostLikely() {
+        return log10LikelihoodOfMostLikely;
+    }
+
+    public double getLog10LikelihoodOfSecondBest() {
+        return log10LikelihoodOfSecondBest;
+    }
+
+    /**
+     * @see #isInformative(double) with threshold of INFORMATIVE_LIKELIHOOD_THRESHOLD
+     */
+    public boolean isInformative() {
+        return isInformative(INFORMATIVE_LIKELIHOOD_THRESHOLD);
+    }
+
+    /**
+     * Was this allele selected from an object that was specifically informative about the allele?
+     *
+     * The calculation that implements this is whether the likelihood of the most likely allele is larger
+     * than the second most likely by at least the log10ThresholdForInformative
+     *
+     * @return true if so, false if not
+     */
+    public boolean isInformative(final double log10ThresholdForInformative) {
+        return getLog10LikelihoodOfMostLikely() - getLog10LikelihoodOfSecondBest() > log10ThresholdForInformative;
+    }
+
+    /**
+     * @see #getAlleleIfInformative(double) with threshold of INFORMATIVE_LIKELIHOOD_THRESHOLD
+     */
+    public Allele getAlleleIfInformative() {
+        return getAlleleIfInformative(INFORMATIVE_LIKELIHOOD_THRESHOLD);
+    }
+
+    /**
+     * Get the most likely allele if isInformative(log10ThresholdForInformative) is true, or NO_CALL otherwise
+     *
+     * @param log10ThresholdForInformative a log10 threshold to determine if the most likely allele was informative
+     * @return a non-null allele
+     */
+    public Allele getAlleleIfInformative(final double log10ThresholdForInformative) {
+        return isInformative(log10ThresholdForInformative) ? getMostLikelyAllele() : Allele.NO_CALL;
+    }
+}
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/genotyper/PerReadAlleleLikelihoodMap.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/genotyper/PerReadAlleleLikelihoodMap.java
new file mode 100644
index 0000000..1dd8a8a
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/genotyper/PerReadAlleleLikelihoodMap.java
@@ -0,0 +1,413 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.utils.genotyper;
+
+
+import com.google.java.contract.Ensures;
+import org.broadinstitute.gatk.engine.downsampling.AlleleBiasedDownsamplingUtils;
+import org.broadinstitute.gatk.utils.GenomeLoc;
+import org.broadinstitute.gatk.utils.MathUtils;
+import org.broadinstitute.gatk.utils.haplotype.Haplotype;
+import org.broadinstitute.gatk.utils.pileup.PileupElement;
+import org.broadinstitute.gatk.utils.pileup.ReadBackedPileup;
+import org.broadinstitute.gatk.utils.sam.AlignmentUtils;
+import org.broadinstitute.gatk.utils.sam.GATKSAMRecord;
+import htsjdk.variant.variantcontext.Allele;
+
+import java.util.*;
+
+/**
+ *   Wrapper class that holds a set of maps of the form (Read -> Map(Allele->Double))
+ *   For each read, this holds underlying alleles represented by an aligned read, and corresponding relative likelihood.
+ */
+public class PerReadAlleleLikelihoodMap {
+    /** A set of all of the allele, so we can efficiently determine if an allele is already present */
+    private final Map<Allele,Integer> allelesSet = new HashMap<>();
+    /** A list of the unique allele, as an ArrayList so we can call get(i) efficiently */
+    protected final List<Allele> alleles = new ArrayList<>();
+
+
+
+    protected final Map<GATKSAMRecord, Map<Allele, Double>> likelihoodReadMap = new LinkedHashMap<>();
+
+    public PerReadAlleleLikelihoodMap() { }
+
+    /**
+     * Add a new entry into the Read -> ( Allele -> Likelihood ) map of maps.
+     * @param read - the GATKSAMRecord that was evaluated
+     * @param a - the Allele against which the GATKSAMRecord was evaluated
+     * @param likelihood - the likelihood score resulting from the evaluation of "read" against "a"
+     */
+    public void add(final GATKSAMRecord read, final Allele a, final Double likelihood) {
+        if ( read == null ) throw new IllegalArgumentException("Cannot add a null read to the allele likelihood map");
+        if ( a == null ) throw new IllegalArgumentException("Cannot add a null allele to the allele likelihood map");
+        if ( likelihood == null ) throw new IllegalArgumentException("Likelihood cannot be null");
+        if ( likelihood > 0.0 ) throw new IllegalArgumentException("Likelihood must be negative (L = log(p))");
+
+        if (!allelesSet.containsKey(a)) {
+            allelesSet.put(a,alleles.size());
+            alleles.add(a);
+        }
+        Map<Allele,Double> likelihoodMap = likelihoodReadMap.get(read);
+        if (likelihoodMap == null){
+            // LinkedHashMap will ensure iterating through alleles will be in consistent order
+            likelihoodMap = new LinkedHashMap<>();
+            likelihoodReadMap.put(read,likelihoodMap);
+        }
+
+        likelihoodMap.put(a,likelihood);
+
+
+    }
+
+    public ReadBackedPileup createPerAlleleDownsampledBasePileup(final ReadBackedPileup pileup, final double downsamplingFraction) {
+        return AlleleBiasedDownsamplingUtils.createAlleleBiasedBasePileup(pileup, downsamplingFraction);
+    }
+
+    /**
+     * For each allele "a" , identify those reads whose most likely allele is "a", and remove a "downsamplingFraction" proportion
+     * of those reads from the "likelihoodReadMap". This is used for e.g. sample contamination
+     * @param downsamplingFraction - the fraction of supporting reads to remove from each allele. If <=0 all reads kept, if >=1 all reads tossed.
+     */
+    public void performPerAlleleDownsampling(final double downsamplingFraction) {
+        // special case removal of all or no reads
+        if ( downsamplingFraction <= 0.0 )
+            return;
+        if ( downsamplingFraction >= 1.0 ) {
+            likelihoodReadMap.clear();
+            return;
+        }
+
+        // start by stratifying the reads by the alleles they represent at this position
+        final Map<Allele, List<GATKSAMRecord>> alleleReadMap = getAlleleStratifiedReadMap();
+
+        // compute the reads to remove and actually remove them
+        final List<GATKSAMRecord> readsToRemove = AlleleBiasedDownsamplingUtils.selectAlleleBiasedReads(alleleReadMap, downsamplingFraction);
+        for ( final GATKSAMRecord read : readsToRemove )
+            likelihoodReadMap.remove(read);
+    }
+
+    /**
+     * Convert the @likelihoodReadMap to a map of alleles to reads, where each read is mapped uniquely to the allele
+     * for which it has the greatest associated likelihood
+     * @return a map from each allele to a list of reads that 'support' the allele
+     */
+    protected Map<Allele,List<GATKSAMRecord>> getAlleleStratifiedReadMap() {
+        final Map<Allele, List<GATKSAMRecord>> alleleReadMap = new HashMap<>(alleles.size());
+        for ( final Allele allele : alleles )
+            alleleReadMap.put(allele, new ArrayList<GATKSAMRecord>());
+
+        for ( final Map.Entry<GATKSAMRecord, Map<Allele, Double>> entry : likelihoodReadMap.entrySet() ) {
+            final MostLikelyAllele bestAllele = getMostLikelyAllele(entry.getValue());
+            if ( bestAllele.isInformative() )
+                alleleReadMap.get(bestAllele.getMostLikelyAllele()).add(entry.getKey());
+        }
+
+        return alleleReadMap;
+    }
+
+    @Ensures("result >=0")
+    public int size() {
+        return likelihoodReadMap.size();
+    }
+
+    /**
+     * Helper function to add the read underneath a pileup element to the map
+     * @param p                              Pileup element
+     * @param a                              Corresponding allele
+     * @param likelihood                     Allele likelihood
+     */
+    public void add(PileupElement p, Allele a, Double likelihood) {
+        if (p==null)
+            throw new IllegalArgumentException("Pileup element cannot be null");
+        if ( p.getRead()==null )
+           throw new IllegalArgumentException("Read underlying pileup element cannot be null");
+        if ( a == null )
+           throw new IllegalArgumentException("Allele for add() cannot be null");
+
+        add(p.getRead(), a, likelihood);
+    }
+
+     /**
+     * Does the current map contain the key associated with a particular SAM record in pileup?
+     * @param p                 Pileup element
+     * @return true if the map contains pileup element, else false
+     */
+    public boolean containsPileupElement(final PileupElement p) {
+        return likelihoodReadMap.containsKey(p.getRead());
+    }
+
+    public boolean isEmpty() {
+        return likelihoodReadMap.isEmpty();
+    }
+
+    public Map<GATKSAMRecord,Map<Allele,Double>> getLikelihoodReadMap() {
+        return likelihoodReadMap;
+    }
+
+    public void clear() {
+        allelesSet.clear();
+        alleles.clear();
+        likelihoodReadMap.clear();
+    }
+
+    public Set<GATKSAMRecord> getStoredElements() {
+        return likelihoodReadMap.keySet();
+    }
+
+//    public Collection<Map<Allele,Double>> getLikelihoodMapValues() {
+//        return likelihoodReadMap.values();
+//    }
+
+    public int getNumberOfStoredElements() {
+        return likelihoodReadMap.size();
+    }
+
+    public Map<Allele,Double> getLikelihoodsAssociatedWithPileupElement(final PileupElement p) {
+        if (!likelihoodReadMap.containsKey(p.getRead()))
+            return null;
+
+        return likelihoodReadMap.get(p.getRead());
+    }
+
+
+    /**
+     * Get the log10 likelihood associated with an individual read/allele
+     *
+     * @param read the read whose likelihood we want
+     * @param allele the allele whose likelihood we want
+     * @return the log10 likelihood that this read matches this allele
+     */
+    public double getLikelihoodAssociatedWithReadAndAllele(final GATKSAMRecord read, final Allele allele){
+        if (!allelesSet.containsKey(allele) || !likelihoodReadMap.containsKey(read))
+            return 0.0;
+
+        return likelihoodReadMap.get(read).get(allele);
+    }
+
+    /**
+     * Get the most likely alleles estimated across all reads in this object
+     *
+     * Takes the most likely two alleles according to their diploid genotype likelihoods.  That is, for
+     * each allele i and j we compute p(D | i,j) where D is the read likelihoods.  We track the maximum
+     * i,j likelihood and return an object that contains the alleles i and j as well as the max likelihood.
+     *
+     * Note that the second most likely diploid genotype is not tracked so the resulting MostLikelyAllele
+     * doesn't have a meaningful get best likelihood.
+     *
+     * @return a MostLikelyAllele object, or null if this map is empty
+     */
+    public MostLikelyAllele getMostLikelyDiploidAlleles() {
+        if ( isEmpty() ) return null;
+
+        int hap1 = 0;
+        int hap2 = 0;
+        double maxElement = Double.NEGATIVE_INFINITY;
+        for( int iii = 0; iii < alleles.size(); iii++ ) {
+            final Allele iii_allele = alleles.get(iii);
+            for( int jjj = 0; jjj <= iii; jjj++ ) {
+                final Allele jjj_allele = alleles.get(jjj);
+
+                double haplotypeLikelihood = 0.0;
+                for( final Map.Entry<GATKSAMRecord, Map<Allele,Double>> entry : likelihoodReadMap.entrySet() ) {
+                    // Compute log10(10^x1/2 + 10^x2/2) = log10(10^x1+10^x2)-log10(2)
+                    final double likelihood_iii = entry.getValue().get(iii_allele);
+                    final double likelihood_jjj = entry.getValue().get(jjj_allele);
+                    haplotypeLikelihood += MathUtils.approximateLog10SumLog10(likelihood_iii, likelihood_jjj) + MathUtils.LOG_ONE_HALF;
+
+                    // fast exit.  If this diploid pair is already worse than the max, just stop and look at the next pair
+                    if ( haplotypeLikelihood < maxElement ) break;
+                }
+
+                // keep track of the max element and associated indices
+                if ( haplotypeLikelihood > maxElement ) {
+                    hap1 = iii;
+                    hap2 = jjj;
+                    maxElement = haplotypeLikelihood;
+                }
+            }
+        }
+
+        if ( maxElement == Double.NEGATIVE_INFINITY )
+            throw new IllegalStateException("max likelihood is " + maxElement + " indicating something has gone wrong");
+
+        return new MostLikelyAllele(alleles.get(hap1), alleles.get(hap2), maxElement, maxElement);
+    }
+
+    /**
+     * Given a map from alleles to likelihoods, find the allele with the largest likelihood.
+     *
+     * @param alleleMap - a map from alleles to likelihoods
+     * @return - a MostLikelyAllele object
+     */
+    @Ensures("result != null")
+    public static MostLikelyAllele getMostLikelyAllele( final Map<Allele,Double> alleleMap ) {
+        return getMostLikelyAllele(alleleMap, null);
+    }
+
+    /**
+     * Given a map from alleles to likelihoods, find the allele with the largest likelihood.
+     *
+     * @param alleleMap - a map from alleles to likelihoods
+     * @param onlyConsiderTheseAlleles if not null, we will only consider alleles in this set for being one of the best.
+     *                                 this is useful for the case where you've selected a subset of the alleles that
+     *                                 the reads have been computed for further analysis.  If null totally ignored
+     * @return - a MostLikelyAllele object
+     */
+    public static MostLikelyAllele getMostLikelyAllele( final Map<Allele,Double> alleleMap, final Set<Allele> onlyConsiderTheseAlleles ) {
+        if ( alleleMap == null ) throw new IllegalArgumentException("The allele to likelihood map cannot be null");
+        double maxLike = Double.NEGATIVE_INFINITY;
+        double prevMaxLike = Double.NEGATIVE_INFINITY;
+        Allele mostLikelyAllele = Allele.NO_CALL;
+        Allele secondMostLikely = null;
+
+        for (final Map.Entry<Allele,Double> el : alleleMap.entrySet()) {
+            if ( onlyConsiderTheseAlleles != null && ! onlyConsiderTheseAlleles.contains(el.getKey()) )
+                continue;
+
+            if (el.getValue() > maxLike) {
+                prevMaxLike = maxLike;
+                maxLike = el.getValue();
+                secondMostLikely = mostLikelyAllele;
+                mostLikelyAllele = el.getKey();
+            } else if( el.getValue() > prevMaxLike ) {
+                secondMostLikely = el.getKey();
+                prevMaxLike = el.getValue();
+            }
+        }
+
+        return new MostLikelyAllele(mostLikelyAllele, secondMostLikely, maxLike, prevMaxLike);
+    }
+
+    /**
+     * Debug method to dump contents of object into string for display
+     */
+    public String toString() {
+        final StringBuilder sb = new StringBuilder();
+
+        sb.append("Alelles in map:");
+        for (final Allele a:alleles) {
+            sb.append(a.getDisplayString()+",");
+        }
+        sb.append("\n");
+        for (final Map.Entry <GATKSAMRecord, Map<Allele, Double>> el : getLikelihoodReadMap().entrySet() ) {
+            for (final Map.Entry<Allele,Double> eli : el.getValue().entrySet()) {
+                sb.append("Read "+el.getKey().getReadName()+". Allele:"+eli.getKey().getDisplayString()+" has likelihood="+Double.toString(eli.getValue())+"\n");
+            }
+
+        }
+        return sb.toString();
+    }
+
+    /**
+     * Remove reads from this map that are poorly modelled w.r.t. their per allele likelihoods
+     *
+     * Goes through each read in this map, and if it is poorly modelled removes it from the map.
+     *
+     * @see #readIsPoorlyModelled(org.broadinstitute.gatk.utils.sam.GATKSAMRecord, java.util.Collection, double)
+     * for more information about the poorly modelled test.
+     *
+     * @param maxErrorRatePerBase see equivalent parameter in #readIsPoorlyModelled
+     * @return the list of reads removed from this map because they are poorly modelled
+     */
+    public List<GATKSAMRecord> filterPoorlyModelledReads(final double maxErrorRatePerBase) {
+        final List<GATKSAMRecord> removedReads = new LinkedList<>();
+        final Iterator<Map.Entry<GATKSAMRecord, Map<Allele, Double>>> it = likelihoodReadMap.entrySet().iterator();
+        while ( it.hasNext() ) {
+            final Map.Entry<GATKSAMRecord, Map<Allele, Double>> record = it.next();
+            if ( readIsPoorlyModelled(record.getKey(), record.getValue().values(), maxErrorRatePerBase) ) {
+                it.remove();
+                removedReads.add(record.getKey());
+            }
+        }
+
+        return removedReads;
+    }
+
+    /**
+     * Is this read poorly modelled by all of the alleles in this map?
+     *
+     * A read is poorly modeled when it's likelihood is below what would be expected for a read
+     * originating from one of the alleles given the maxErrorRatePerBase of the reads in general.
+     *
+     * This function makes a number of key assumptions.  First, that the likelihoods reflect the total likelihood
+     * of the read.  In other words, that the read would be fully explained by one of the alleles.  This means
+     * that the allele should be something like the full haplotype from which the read might originate.
+     *
+     * It further assumes that each error in the read occurs with likelihood of -3 (Q30 confidence per base).  So
+     * a read with a 10% error rate with Q30 bases that's 100 bp long we'd expect to see 10 real Q30 errors
+     * even against the true haplotype.  So for this read to be well modelled by at least one allele we'd expect
+     * a likelihood to be >= 10 * -3.
+     *
+     * @param read the read we want to evaluate
+     * @param log10Likelihoods a list of the log10 likelihoods of the read against a set of haplotypes.
+     * @param maxErrorRatePerBase the maximum error rate we'd expect for this read per base, in real space.  So
+     *                            0.01 means a 1% error rate
+     * @return true if none of the log10 likelihoods imply that the read truly originated from one of the haplotypes
+     */
+    protected boolean readIsPoorlyModelled(final GATKSAMRecord read, final Collection<Double> log10Likelihoods, final double maxErrorRatePerBase) {
+        final double maxErrorsForRead = Math.min(2.0, Math.ceil(read.getReadLength() * maxErrorRatePerBase));
+        final double log10QualPerBase = -4.0;
+        final double log10MaxLikelihoodForTrueAllele = maxErrorsForRead * log10QualPerBase;
+
+        for ( final double log10Likelihood : log10Likelihoods )
+            if ( log10Likelihood >= log10MaxLikelihoodForTrueAllele )
+                return false;
+
+        return true;
+    }
+
+    /**
+     * Get an unmodifiable set of the unique alleles in this PerReadAlleleLikelihoodMap
+     * @return a non-null unmodifiable map
+     */
+    public Set<Allele> getAllelesSet() {
+        return Collections.unmodifiableSet(allelesSet.keySet());
+    }
+
+    /**
+     * Loop over all of the reads in this likelihood map and realign them to its most likely haplotype
+     * @param haplotypes            the collection of haplotypes
+     * @param paddedReferenceLoc    the active region
+     */
+    public void realignReadsToMostLikelyHaplotype(final Collection<Haplotype> haplotypes, final GenomeLoc paddedReferenceLoc) {
+
+        // we need to remap the Alleles back to the Haplotypes; inefficient but unfortunately this is a requirement currently
+        final Map<Allele, Haplotype> alleleToHaplotypeMap = new HashMap<>(haplotypes.size());
+        for ( final Haplotype haplotype : haplotypes )
+            alleleToHaplotypeMap.put(Allele.create(haplotype.getBases()), haplotype);
+
+        final Map<GATKSAMRecord, Map<Allele, Double>> newLikelihoodReadMap = new LinkedHashMap<>(likelihoodReadMap.size());
+        for( final Map.Entry<GATKSAMRecord, Map<Allele, Double>> entry : likelihoodReadMap.entrySet() ) {
+            final MostLikelyAllele bestAllele = PerReadAlleleLikelihoodMap.getMostLikelyAllele(entry.getValue());
+            final GATKSAMRecord alignedToRef = AlignmentUtils.createReadAlignedToRef(entry.getKey(), alleleToHaplotypeMap.get(bestAllele.getMostLikelyAllele()), paddedReferenceLoc.getStart(), bestAllele.isInformative());
+            newLikelihoodReadMap.put(alignedToRef, entry.getValue());
+        }
+
+        likelihoodReadMap.clear();
+        likelihoodReadMap.putAll(newLikelihoodReadMap);
+    }
+}
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/genotyper/ReadLikelihoods.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/genotyper/ReadLikelihoods.java
new file mode 100644
index 0000000..fa9fc30
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/genotyper/ReadLikelihoods.java
@@ -0,0 +1,1587 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.utils.genotyper;
+
+import htsjdk.variant.variantcontext.Allele;
+import it.unimi.dsi.fastutil.ints.IntArrayList;
+import it.unimi.dsi.fastutil.objects.Object2IntMap;
+import it.unimi.dsi.fastutil.objects.Object2IntOpenHashMap;
+import org.broadinstitute.gatk.engine.downsampling.AlleleBiasedDownsamplingUtils;
+import org.broadinstitute.gatk.tools.walkers.genotyper.*;
+import org.broadinstitute.gatk.utils.GenomeLoc;
+import org.broadinstitute.gatk.utils.Utils;
+import org.broadinstitute.gatk.utils.sam.GATKSAMRecord;
+import org.broadinstitute.gatk.utils.variant.GATKVariantContextUtils;
+
+import java.util.*;
+
+/**
+ * Read-likelihoods container implementation based on integer indexed arrays.
+ *
+ * @param <A> the type of the allele the likelihood makes reference to.
+ *
+ * @author Valentin Ruano-Rubio <valentin at broadinstitute.org>
+ */
+public class ReadLikelihoods<A extends Allele> implements SampleList, AlleleList<A>, Cloneable {
+
+    /**
+     * Reads by sample index. Each sub array contains reference to the reads of the ith sample.
+     */
+    private GATKSAMRecord[][] readsBySampleIndex;
+
+    /**
+     * Indexed per sample, allele and finally read (within sample).
+     * <p>
+     *     valuesBySampleIndex[s][a][r] == lnLk(R_r | A_a) where R_r comes from Sample s.
+     * </p>
+     */
+    private double[][][] valuesBySampleIndex;
+
+    /**
+     * Sample list
+     */
+    private final SampleList samples;
+
+    /**
+     * Allele list
+     */
+    private AlleleList<A> alleles;
+
+    /**
+     * Cached allele list.
+     */
+    private List<A> alleleList;
+
+    /**
+     * Cached sample list.
+     */
+    private List<String> sampleList;
+
+    /**
+     * Maps from each read to its index within the sample.
+     *
+     * <p>In order to save CPU time the indices contained in this array (not the array itself) is
+     * lazily initialized by invoking {@link #readIndexBySampleIndex(int)}.</p>
+     */
+    private final Object2IntMap<GATKSAMRecord>[] readIndexBySampleIndex;
+
+    /**
+     * Index of the reference allele if any, otherwise -1
+     */
+    private int referenceAlleleIndex = -1;
+
+    /**
+     * Caches the read-list per sample list returned by {@link #sampleReads}
+     */
+    private final List<GATKSAMRecord>[] readListBySampleIndex;
+
+    /**
+     * Sample matrices lazily initialized (the elements not the array) by invoking {@link #sampleMatrix(int)}.
+     */
+    private final Matrix<A>[] sampleMatrices;
+
+    /**
+     * Constructs a new read-likelihood collection.
+     *
+     * <p>
+     *     The initial likelihoods for all allele-read combinations are
+     *     0.
+     * </p>
+     *
+     * @param samples all supported samples in the collection.
+     * @param alleles all supported alleles in the collection.
+     * @param reads reads stratified per sample.
+     *
+     * @throws IllegalArgumentException if any of {@code allele}, {@code samples}
+     * or {@code reads} is {@code null},
+     *  or if they contain null values.
+     */
+    @SuppressWarnings("unchecked")
+    public ReadLikelihoods(final SampleList samples, final AlleleList<A> alleles,
+                           final Map<String, List<GATKSAMRecord>> reads) {
+        if (alleles == null)
+            throw new IllegalArgumentException("allele list cannot be null");
+        if (samples == null)
+            throw new IllegalArgumentException("sample list cannot be null");
+        if (reads == null)
+            throw new IllegalArgumentException("read map cannot be null");
+
+        this.samples = samples;
+        this.alleles = alleles;
+
+        final int sampleCount = samples.sampleCount();
+        final int alleleCount = alleles.alleleCount();
+
+        readsBySampleIndex = new GATKSAMRecord[sampleCount][];
+        readListBySampleIndex = new List[sampleCount];
+        valuesBySampleIndex = new double[sampleCount][][];
+        referenceAlleleIndex = findReferenceAllele(alleles);
+
+        readIndexBySampleIndex = new Object2IntMap[sampleCount];
+
+        setupIndexes(reads, sampleCount, alleleCount);
+
+        sampleMatrices = (Matrix<A>[]) new Matrix[sampleCount];
+    }
+
+    // Add all the indices to alleles, sample and reads in the look-up maps.
+    private void setupIndexes(final Map<String, List<GATKSAMRecord>> reads, final int sampleCount, final int alleleCount) {
+        for (int i = 0; i < sampleCount; i++)
+            setupSampleData(i, reads, alleleCount);
+    }
+
+    // Assumes that {@link #samples} has been initialized with the sample names.
+    private void setupSampleData(final int sampleIndex, final Map<String, List<GATKSAMRecord>> readsBySample,
+                                 final int alleleCount) {
+        final String sample = samples.sampleAt(sampleIndex);
+
+        final List<GATKSAMRecord> reads = readsBySample.get(sample);
+        readsBySampleIndex[sampleIndex] = reads == null
+                ? new GATKSAMRecord[0]
+                : reads.toArray(new GATKSAMRecord[reads.size()]);
+        final int sampleReadCount = readsBySampleIndex[sampleIndex].length;
+
+        final double[][] sampleValues = new double[alleleCount][sampleReadCount];
+        valuesBySampleIndex[sampleIndex] = sampleValues;
+    }
+
+    /**
+     * Create an independent copy of this read-likelihoods collection
+     */
+    public ReadLikelihoods<A> clone() {
+
+        final int sampleCount = samples.sampleCount();
+        final int alleleCount = alleles.alleleCount();
+
+        final double[][][] newLikelihoodValues = new double[sampleCount][alleleCount][];
+
+        @SuppressWarnings("unchecked")
+        final Object2IntMap<GATKSAMRecord>[] newReadIndexBySampleIndex = new Object2IntMap[sampleCount];
+        final GATKSAMRecord[][] newReadsBySampleIndex = new GATKSAMRecord[sampleCount][];
+
+        for (int s = 0; s < sampleCount; s++) {
+            newReadsBySampleIndex[s] = readsBySampleIndex[s].clone();
+            for (int a = 0; a < alleleCount; a++)
+                newLikelihoodValues[s][a] = valuesBySampleIndex[s][a].clone();
+        }
+
+        // Finally we create the new read-likelihood
+        return new ReadLikelihoods<>(alleles, samples,
+                newReadsBySampleIndex,
+                newReadIndexBySampleIndex, newLikelihoodValues);
+    }
+
+    // Internally used constructor.
+    @SuppressWarnings("unchecked")
+    private ReadLikelihoods(final AlleleList alleles, final SampleList samples,
+                            final GATKSAMRecord[][] readsBySampleIndex, final Object2IntMap<GATKSAMRecord>[] readIndex,
+                            final double[][][] values) {
+        this.samples = samples;
+        this.alleles = alleles;
+        this.readsBySampleIndex = readsBySampleIndex;
+        this.valuesBySampleIndex = values;
+        this.readIndexBySampleIndex = readIndex;
+        final int sampleCount = samples.sampleCount();
+        this.readListBySampleIndex = new List[sampleCount];
+
+        referenceAlleleIndex = findReferenceAllele(alleles);
+        sampleMatrices = (Matrix<A>[]) new Matrix[sampleCount];
+    }
+
+    // Search for the reference allele, if not found the index is -1.
+    private int findReferenceAllele(final AlleleList<A> alleles) {
+        final int alleleCount = alleles.alleleCount();
+        for (int i = 0; i < alleleCount; i++)
+            if (alleles.alleleAt(i).isReference())
+                return i;
+        return -1;
+    }
+
+    /**
+     * Returns the index of a sample within the likelihood collection.
+     *
+     * @param sample the query sample.
+     *
+     * @throws IllegalArgumentException if {@code sample} is {@code null}.
+     * @return -1 if the allele is not included, 0 or greater otherwise.
+     */
+    public int sampleIndex(final String sample) {
+        return samples.sampleIndex(sample);
+    }
+
+    /**
+     * Number of samples included in the likelihood collection.
+     * @return 0 or greater.
+     */
+    public int sampleCount() {
+        return samples.sampleCount();
+    }
+
+    /**
+     * Returns sample name given its index.
+     *
+     * @param sampleIndex query index.
+     *
+     * @throws IllegalArgumentException if {@code sampleIndex} is negative.
+     *
+     * @return never {@code null}.
+     */
+    public String sampleAt(final int sampleIndex) {
+        return samples.sampleAt(sampleIndex);
+    }
+
+    /**
+     * Returns the index of an allele within the likelihood collection.
+     *
+     * @param allele the query allele.
+     *
+     * @throws IllegalArgumentException if {@code allele} is {@code null}.
+     *
+     * @return -1 if the allele is not included, 0 or greater otherwise.
+     */
+    public int alleleIndex(final A allele) {
+        return alleles.alleleIndex(allele);
+    }
+
+    /**
+     * Returns number of alleles in the collection.
+     * @return 0 or greater.
+     */
+    @SuppressWarnings("unused")
+    public int alleleCount() {
+        return alleles.alleleCount();
+    }
+
+    /**
+     * Returns the allele given its index.
+     *
+     * @param alleleIndex the allele index.
+     *
+     * @throws IllegalArgumentException the allele index is {@code null}.
+     *
+     * @return never {@code null}.
+     */
+    public A alleleAt(final int alleleIndex) {
+        return alleles.alleleAt(alleleIndex);
+    }
+
+    /**
+     * Returns the reads that belong to a sample sorted by their index (within that sample).
+     *
+     * @param sampleIndex the requested sample.
+     * @return never {@code null} but perhaps a zero-length array if there is no reads in sample. No element in
+     *   the array will be null.
+     */
+    public List<GATKSAMRecord> sampleReads(final int sampleIndex) {
+        checkSampleIndex(sampleIndex);
+        final List<GATKSAMRecord> extantList = readListBySampleIndex[sampleIndex];
+        if (extantList == null)
+            return readListBySampleIndex[sampleIndex] = Collections.unmodifiableList(Arrays.asList(readsBySampleIndex[sampleIndex]));
+        else
+            return extantList;
+    }
+
+    /**
+     * Returns a read vs allele likelihood matrix corresponding to a sample.
+     *
+     * @param sampleIndex target sample.
+     *
+     * @throws IllegalArgumentException if {@code sampleIndex} is not null.
+     *
+     * @return never {@code null}
+     */
+    public Matrix<A> sampleMatrix(final int sampleIndex) {
+        checkSampleIndex(sampleIndex);
+        final Matrix<A> extantResult = sampleMatrices[sampleIndex];
+        if (extantResult != null)
+            return extantResult;
+        else
+            return sampleMatrices[sampleIndex] = new SampleMatrix(sampleIndex);
+    }
+
+    /**
+     * Adjusts likelihoods so that for each read, the best allele likelihood is 0 and caps the minimum likelihood
+     * of any allele for each read based on the maximum alternative allele likelihood.
+     *
+     * @param bestToZero set the best likelihood to 0, others will be subtracted the same amount.
+     * @param maximumLikelihoodDifferenceCap maximum difference between the best alternative allele likelihood
+     *                                           and any other likelihood.
+     *
+     * @throws IllegalArgumentException if {@code maximumDifferenceWithBestAlternative} is not 0 or less.
+     */
+    public void normalizeLikelihoods(final boolean bestToZero, final double maximumLikelihoodDifferenceCap) {
+        if (maximumLikelihoodDifferenceCap >= 0.0 || Double.isNaN(maximumLikelihoodDifferenceCap))
+            throw new IllegalArgumentException("the minimum reference likelihood fall cannot be positive");
+
+        if (maximumLikelihoodDifferenceCap == Double.NEGATIVE_INFINITY && !bestToZero)
+            return;
+
+        final int alleleCount = alleles.alleleCount();
+        if (alleleCount == 0) // trivial case there is no alleles.
+            return;
+        else if (alleleCount == 1 && !bestToZero)
+            return;
+
+        for (int s = 0; s < valuesBySampleIndex.length; s++) {
+            final double[][] sampleValues = valuesBySampleIndex[s];
+            final int readCount = readsBySampleIndex[s].length;
+            for (int r = 0; r < readCount; r++)
+                normalizeLikelihoodsPerRead(bestToZero, maximumLikelihoodDifferenceCap, sampleValues, s, r);
+        }
+    }
+
+    // Does the normalizeLikelihoods job for each read.
+    private void normalizeLikelihoodsPerRead(final boolean bestToZero, final double maximumBestAltLikelihoodDifference,
+                                             final double[][] sampleValues, final int sampleIndex, final int readIndex) {
+
+        final BestAllele bestAlternativeAllele = searchBestAllele(sampleIndex,readIndex,false);
+
+        final double worstLikelihoodCap = bestAlternativeAllele.likelihood + maximumBestAltLikelihoodDifference;
+
+        final double referenceLikelihood = referenceAlleleIndex == -1 ? Double.NEGATIVE_INFINITY :
+                sampleValues[referenceAlleleIndex][readIndex];
+
+
+        final double bestAbsoluteLikelihood = Math.max(bestAlternativeAllele.likelihood,referenceLikelihood);
+
+        final int alleleCount = alleles.alleleCount();
+        if (bestToZero) {
+            if (bestAbsoluteLikelihood == Double.NEGATIVE_INFINITY)
+                for (int a = 0; a < alleleCount; a++)
+                    sampleValues[a][readIndex] = 0;
+            else if (worstLikelihoodCap != Double.NEGATIVE_INFINITY)
+                for (int a = 0; a < alleleCount; a++)
+                    sampleValues[a][readIndex] = (sampleValues[a][readIndex] < worstLikelihoodCap ? worstLikelihoodCap : sampleValues[a][readIndex]) - bestAbsoluteLikelihood;
+            else
+                for (int a = 0; a < alleleCount; a++)
+                    sampleValues[a][readIndex] -= bestAbsoluteLikelihood;
+        } else  // else if (maximumReferenceLikelihoodFall != Double.NEGATIVE_INFINITY ) { //
+            // Guarantee to be the case by enclosing code.
+            for (int a = 0; a < alleleCount; a++)
+                if (sampleValues[a][readIndex] < worstLikelihoodCap)
+                    sampleValues[a][readIndex] = worstLikelihoodCap;
+    }
+
+    /**
+     * Returns the samples in this read-likelihood collection.
+     * <p>
+     *     Samples are sorted by their index in the collection.
+     * </p>
+     *
+     * <p>
+     *     The returned list is an unmodifiable view on the read-likelihoods sample list.
+     * </p>
+     *
+     * @return never {@code null}.
+     */
+    public List<String> samples() {
+        return sampleList == null ? sampleList = SampleListUtils.asList(samples) : sampleList;
+
+    }
+
+    /**
+     * Returns the samples in this read-likelihood collection.
+     * <p>
+     *     Samples are sorted by their index in the collection.
+     * </p>
+     *
+     * <p>
+     *     The returned list is an unmodifiable. It will not be updated if the collection
+     *     allele list changes.
+     * </p>
+     *
+     * @return never {@code null}.
+     */
+    public List<A> alleles() {
+        return alleleList == null ? alleleList = AlleleListUtils.asList(alleles) : alleleList;
+    }
+
+
+    /**
+     * Search the best allele for a read.
+     *
+     * @param sampleIndex including sample index.
+     * @param readIndex  target read index.
+     *
+     * @return never {@code null}, but with {@link BestAllele#allele allele} == {@code null}
+     * if non-could be found.
+     */
+    private BestAllele searchBestAllele(final int sampleIndex, final int readIndex, final boolean canBeReference) {
+        final int alleleCount = alleles.alleleCount();
+        if (alleleCount == 0 || (alleleCount == 1 && referenceAlleleIndex == 0 && !canBeReference))
+            return new BestAllele(sampleIndex,readIndex,-1,Double.NEGATIVE_INFINITY,Double.NEGATIVE_INFINITY);
+
+        final double[][] sampleValues = valuesBySampleIndex[sampleIndex];
+        int bestAlleleIndex = canBeReference || referenceAlleleIndex != 0 ? 0 : 1;
+
+        double bestLikelihood = sampleValues[bestAlleleIndex][readIndex];
+        double secondBestLikelihood = Double.NEGATIVE_INFINITY;
+        for (int a = bestAlleleIndex + 1; a < alleleCount; a++) {
+            if (!canBeReference && referenceAlleleIndex == a)
+                continue;
+            final double candidateLikelihood = sampleValues[a][readIndex];
+            if (candidateLikelihood > bestLikelihood) {
+                bestAlleleIndex = a;
+                secondBestLikelihood = bestLikelihood;
+                bestLikelihood = candidateLikelihood;
+            } else if (candidateLikelihood > secondBestLikelihood) {
+                secondBestLikelihood = candidateLikelihood;
+            }
+        }
+        return new BestAllele(sampleIndex,readIndex,bestAlleleIndex,bestLikelihood,secondBestLikelihood);
+    }
+
+    public void changeReads(final Map<GATKSAMRecord, GATKSAMRecord> readRealignments) {
+        final int sampleCount = samples.sampleCount();
+        for (int s = 0; s < sampleCount; s++) {
+            final GATKSAMRecord[] sampleReads = readsBySampleIndex[s];
+            final Object2IntMap<GATKSAMRecord> readIndex = readIndexBySampleIndex[s];
+            final int sampleReadCount = sampleReads.length;
+            for (int r = 0; r < sampleReadCount; r++) {
+                final GATKSAMRecord read = sampleReads[r];
+                final GATKSAMRecord replacement = readRealignments.get(read);
+                if (replacement == null)
+                    continue;
+                sampleReads[r] = replacement;
+                if (readIndex != null) {
+                    readIndex.remove(read);
+                    readIndex.put(replacement, r);
+                }
+            }
+        }
+    }
+
+    /**
+     * Add alleles that are missing in the read-likelihoods collection giving all reads a default
+     * likelihood value.
+     * @param candidateAlleles the potentially missing alleles.
+     * @param defaultLikelihood the default read likelihood value for that allele.
+     *
+     * @throws IllegalArgumentException if {@code candidateAlleles} is {@code null} or there is more than
+     * one missing allele that is a reference or there is one but the collection already has
+     * a reference allele.
+     */
+    public void addMissingAlleles(final Collection<A> candidateAlleles, final double defaultLikelihood) {
+        if (candidateAlleles == null)
+            throw new IllegalArgumentException("the candidateAlleles list cannot be null");
+        if (candidateAlleles.isEmpty())
+            return;
+        final List<A> allelesToAdd = new ArrayList<>(candidateAlleles.size());
+        for (final A allele : candidateAlleles)
+            if (alleles.alleleIndex(allele) == -1)
+                allelesToAdd.add(allele);
+
+        if (allelesToAdd.isEmpty())
+            return;
+
+        final int oldAlleleCount = alleles.alleleCount();
+        final int newAlleleCount = alleles.alleleCount() + allelesToAdd.size();
+
+        alleleList = null;
+        int referenceIndex = this.referenceAlleleIndex;
+        @SuppressWarnings("unchecked")
+        final A[] newAlleles = (A[]) new Allele[newAlleleCount];
+        for (int a = 0; a < oldAlleleCount; a++)
+            newAlleles[a] = this.alleleAt(a);
+        int newIndex = oldAlleleCount;
+        for (final A allele : allelesToAdd) {
+            if (allele.isReference()) {
+                if (referenceIndex != -1)
+                    throw new IllegalArgumentException("there cannot be more than one reference allele");
+                referenceIndex = newIndex;
+            }
+            newAlleles[newIndex++] = allele;
+        }
+
+        alleles = new IndexedAlleleList<>(newAlleles);
+
+        if (referenceIndex != -1)
+            referenceAlleleIndex = referenceIndex;
+
+        final int sampleCount = samples.sampleCount();
+        for (int s = 0; s < sampleCount; s++) {
+            final int sampleReadCount = readsBySampleIndex[s].length;
+            final double[][] newValuesBySampleIndex = Arrays.copyOf(valuesBySampleIndex[s],newAlleleCount);
+            for (int a = oldAlleleCount; a < newAlleleCount; a++) {
+                newValuesBySampleIndex[a] = new double[sampleReadCount];
+                if (defaultLikelihood != 0.0)
+                    Arrays.fill(newValuesBySampleIndex[a],defaultLikelihood);
+            }
+            valuesBySampleIndex[s] = newValuesBySampleIndex;
+        }
+    }
+
+    /**
+     * Likelihood matrix between a set of alleles and reads.
+     * @param <A> the allele-type.
+     */
+    public interface Matrix<A extends Allele> extends AlleleList<A> {
+
+        /**
+         * List of reads in the matrix sorted by their index therein.
+         * @return never {@code null}.
+         */
+        public List<GATKSAMRecord> reads();
+
+        /**
+         * List of alleles in the matrix sorted by their index in the collection.
+         * @return never {@code null}.
+         */
+        public List<A> alleles();
+
+        /**
+         * Set the likelihood of a read given an allele through their indices.
+         *
+         * @param alleleIndex the target allele index.
+         * @param readIndex the target read index.
+         * @param value new likelihood value for the target read give the target allele.
+         *
+         * @throws IllegalArgumentException if {@code alleleIndex} or {@code readIndex}
+         *  are not valid allele and read indices respectively.
+         */
+        public void set(final int alleleIndex, final int readIndex, final double value);
+
+        /**
+         * Returns the likelihood of a read given a haplotype.
+         *
+         * @param alleleIndex the index of the given haplotype.
+         * @param readIndex the index of the target read.
+         *
+         * @throws IllegalArgumentException if {@code alleleIndex} or {@code readIndex} is not a
+         * valid allele or read index respectively.
+         *
+         * @return the requested likelihood, whatever value was provided using {@link #set(int,int,double) set}
+         *    or 0.0 if none was set.
+         */
+        public double get(final int alleleIndex, final int readIndex);
+
+        /**
+         * Queries the index of an allele in the matrix.
+         *
+         * @param allele the target allele.
+         *
+         * @throws IllegalArgumentException if {@code allele} is {@code null}.
+         * @return -1 if such allele does not exist, otherwise its index which 0 or greater.
+         */
+        @SuppressWarnings("unused")
+        public int alleleIndex(final A allele);
+
+        /**
+         * Queries the index of a read in the matrix.
+         *
+         * @param read the target read.
+         *
+         * @throws IllegalArgumentException if {@code read} is {@code null}.
+         *
+         * @return -1 if there is not such a read in the matrix, otherwise its index
+         *    which is 0 or greater.
+         */
+        @SuppressWarnings("unused")
+        public int readIndex(final GATKSAMRecord read);
+
+        /**
+         * Number of allele in the matrix.
+         * @return never negative.
+         */
+        public int alleleCount();
+
+        /**
+         * Number of reads in the matrix.
+         * @return never negative.
+         */
+        public int readCount();
+
+        /**
+         * Returns the allele given its index.
+         *
+         * @param alleleIndex the target allele index.
+         *
+         * @throws IllegalArgumentException if {@code alleleIndex} is not a valid allele index.
+         * @return never {@code null}.
+         */
+        public A alleleAt(final int alleleIndex);
+
+        /**
+         * Returns the allele given its index.
+         *
+         * @param readIndex the target allele index.
+         *
+         * @throws IllegalArgumentException if {@code readIndex} is not a valid read index.
+         * @return never {@code null}.
+         */
+        public GATKSAMRecord readAt(final int readIndex);
+
+
+        /**
+         * Copies the likelihood of all the reads for a given allele into an array from a particular offset.
+         * @param alleleIndex the targeted allele
+         * @param dest the destination array.
+         * @param offset the copy offset within the destination allele
+         */
+        public void copyAlleleLikelihoods(final int alleleIndex, final double[] dest, final int offset);
+    }
+
+    /**
+     * Perform marginalization from an allele set to another (smaller one) taking the maximum value
+     * for each read in the original allele subset.
+     *
+     * @param newToOldAlleleMap map where the keys are the new alleles and the value list the original
+     *                          alleles that correspond to the new one.
+     * @return never {@code null}. The result will have the requested set of new alleles (keys in {@code newToOldAlleleMap}, and
+     * the same set of samples and reads as the original.
+     *
+     * @throws IllegalArgumentException is {@code newToOldAlleleMap} is {@code null} or contains {@code null} values,
+     *  or its values contain reference to non-existing alleles in this read-likelihood collection. Also no new allele
+     *  can have zero old alleles mapping nor two new alleles can make reference to the same old allele.
+     */
+    public <B extends Allele> ReadLikelihoods<B> marginalize(final Map<B, List<A>> newToOldAlleleMap) {
+
+        if (newToOldAlleleMap == null)
+            throw new IllegalArgumentException("the input allele mapping cannot be null");
+
+        @SuppressWarnings("unchecked")
+        final B[] newAlleles = newToOldAlleleMap.keySet().toArray((B[]) new Allele[newToOldAlleleMap.size()]);
+        final int oldAlleleCount = alleles.alleleCount();
+        final int newAlleleCount = newAlleles.length;
+
+        // we get the index correspondence between new old -> new allele, -1 entries mean that the old
+        // allele does not map to any new; supported but typically not the case.
+        final int[] oldToNewAlleleIndexMap = oldToNewAlleleIndexMap(newToOldAlleleMap, newAlleles, oldAlleleCount, newAlleleCount);
+
+        // We calculate the marginal likelihoods.
+
+        final double[][][] newLikelihoodValues = marginalLikelihoods(oldAlleleCount, newAlleleCount, oldToNewAlleleIndexMap, null);
+
+        final int sampleCount = samples.sampleCount();
+
+        @SuppressWarnings("unchecked")
+        final Object2IntMap<GATKSAMRecord>[] newReadIndexBySampleIndex = new Object2IntMap[sampleCount];
+        final GATKSAMRecord[][] newReadsBySampleIndex = new GATKSAMRecord[sampleCount][];
+
+        for (int s = 0; s < sampleCount; s++) {
+            newReadsBySampleIndex[s] = readsBySampleIndex[s].clone();
+        }
+
+        // Finally we create the new read-likelihood
+        return new ReadLikelihoods<>(new IndexedAlleleList(newAlleles), samples,
+                newReadsBySampleIndex,
+                newReadIndexBySampleIndex, newLikelihoodValues);
+    }
+
+
+    /**
+     * Perform marginalization from an allele set to another (smaller one) taking the maximum value
+     * for each read in the original allele subset.
+     *
+     * @param newToOldAlleleMap map where the keys are the new alleles and the value list the original
+     *                          alleles that correspond to the new one.
+     * @return never {@code null}. The result will have the requested set of new alleles (keys in {@code newToOldAlleleMap}, and
+     * the same set of samples and reads as the original.
+     *
+     * @param overlap if not {@code null}, only reads that overlap the location (with unclipping) will be present in
+     *                        the output read-collection.
+     *
+     * @throws IllegalArgumentException is {@code newToOldAlleleMap} is {@code null} or contains {@code null} values,
+     *  or its values contain reference to non-existing alleles in this read-likelihood collection. Also no new allele
+     *  can have zero old alleles mapping nor two new alleles can make reference to the same old allele.
+     */
+    public <B extends Allele> ReadLikelihoods<B> marginalize(final Map<B, List<A>> newToOldAlleleMap, final GenomeLoc overlap) {
+
+        if (overlap == null)
+            return marginalize(newToOldAlleleMap);
+
+        if (newToOldAlleleMap == null)
+            throw new IllegalArgumentException("the input allele mapping cannot be null");
+
+        @SuppressWarnings("unchecked")
+        final B[] newAlleles = newToOldAlleleMap.keySet().toArray((B[]) new Allele[newToOldAlleleMap.size()]);
+        final int oldAlleleCount = alleles.alleleCount();
+        final int newAlleleCount = newAlleles.length;
+
+        // we get the index correspondence between new old -> new allele, -1 entries mean that the old
+        // allele does not map to any new; supported but typically not the case.
+        final int[] oldToNewAlleleIndexMap = oldToNewAlleleIndexMap(newToOldAlleleMap, newAlleles, oldAlleleCount, newAlleleCount);
+
+        final int[][] readsToKeep = overlappingReadIndicesBySampleIndex(overlap);
+        // We calculate the marginal likelihoods.
+
+        final double[][][] newLikelihoodValues = marginalLikelihoods(oldAlleleCount, newAlleleCount, oldToNewAlleleIndexMap, readsToKeep);
+
+        final int sampleCount = samples.sampleCount();
+
+        @SuppressWarnings("unchecked")
+        final Object2IntMap<GATKSAMRecord>[] newReadIndexBySampleIndex = new Object2IntMap[sampleCount];
+        final GATKSAMRecord[][] newReadsBySampleIndex = new GATKSAMRecord[sampleCount][];
+
+        for (int s = 0; s < sampleCount; s++) {
+            final int[] sampleReadsToKeep = readsToKeep[s];
+            final GATKSAMRecord[] oldSampleReads = readsBySampleIndex[s];
+            final int oldSampleReadCount = oldSampleReads.length;
+            final int newSampleReadCount = sampleReadsToKeep.length;
+            if (newSampleReadCount == oldSampleReadCount) {
+                newReadsBySampleIndex[s] = oldSampleReads.clone();
+            } else {
+                newReadsBySampleIndex[s] = new GATKSAMRecord[newSampleReadCount];
+                for (int i = 0; i < newSampleReadCount; i++)
+                    newReadsBySampleIndex[s][i] = oldSampleReads[sampleReadsToKeep[i]];
+            }
+        }
+
+        // Finally we create the new read-likelihood
+        return new ReadLikelihoods<>(new IndexedAlleleList(newAlleles), samples,
+                newReadsBySampleIndex,
+                newReadIndexBySampleIndex, newLikelihoodValues);
+    }
+
+    private int[][] overlappingReadIndicesBySampleIndex(final GenomeLoc overlap) {
+        if (overlap == null)
+            return null;
+        final int sampleCount = samples.sampleCount();
+        final int[][] result = new int[sampleCount][];
+        final IntArrayList buffer = new IntArrayList(200);
+        final int referenceIndex = overlap.getContigIndex();
+        final int overlapStart = overlap.getStart();
+        final int overlapEnd = overlap.getStop();
+        for (int s = 0; s < sampleCount; s++) {
+            buffer.clear();
+            final GATKSAMRecord[] sampleReads = readsBySampleIndex[s];
+            final int sampleReadCount = sampleReads.length;
+            buffer.ensureCapacity(sampleReadCount);
+            for (int r = 0; r < sampleReadCount; r++)
+                if (unclippedReadOverlapsRegion(sampleReads[r], referenceIndex, overlapStart, overlapEnd))
+                    buffer.add(r);
+            result[s] = buffer.toIntArray();
+        }
+        return result;
+    }
+
+    public static boolean unclippedReadOverlapsRegion(final GATKSAMRecord read, final GenomeLoc region) {
+        return unclippedReadOverlapsRegion(read, region.getContigIndex(), region.getStart(), region.getStop());
+    }
+
+    private static boolean unclippedReadOverlapsRegion(final GATKSAMRecord sampleRead, final int referenceIndex, final int start, final int end) {
+        final int readReference = sampleRead.getReferenceIndex();
+       if (readReference != referenceIndex)
+            return false;
+
+        final int readStart = sampleRead.getUnclippedStart();
+        if (readStart > end)
+            return false;
+
+        final int readEnd = sampleRead.getReadUnmappedFlag() ? sampleRead.getUnclippedEnd()
+                : Math.max(sampleRead.getUnclippedEnd(), sampleRead.getUnclippedStart());
+        return readEnd >= start;
+    }
+
+    // Calculate the marginal likelihoods considering the old -> new allele index mapping.
+    private double[][][] marginalLikelihoods(final int oldAlleleCount, final int newAlleleCount, final int[] oldToNewAlleleIndexMap, final int[][] readsToKeep) {
+
+        final int sampleCount = samples.sampleCount();
+        final double[][][] result = new double[sampleCount][][];
+
+        for (int s = 0; s < sampleCount; s++) {
+            final int sampleReadCount = readsBySampleIndex[s].length;
+            final double[][] oldSampleValues = valuesBySampleIndex[s];
+            final int[] sampleReadToKeep = readsToKeep == null || readsToKeep[s].length == sampleReadCount ? null : readsToKeep[s];
+            final int newSampleReadCount = sampleReadToKeep == null ? sampleReadCount : sampleReadToKeep.length;
+            final double[][] newSampleValues = result[s] = new double[newAlleleCount][newSampleReadCount];
+            // We initiate all likelihoods to -Inf.
+            for (int a = 0; a < newAlleleCount; a++)
+                Arrays.fill(newSampleValues[a], Double.NEGATIVE_INFINITY);
+            // For each old allele and read we update the new table keeping the maximum likelihood.
+            for (int r = 0; r < newSampleReadCount; r++) {
+                for (int a = 0; a < oldAlleleCount; a++) {
+                    final int oldReadIndex = newSampleReadCount == sampleReadCount ? r : sampleReadToKeep[r];
+                    final int newAlleleIndex = oldToNewAlleleIndexMap[a];
+                    if (newAlleleIndex == -1)
+                        continue;
+                    final double likelihood = oldSampleValues[a][oldReadIndex];
+                    if (likelihood > newSampleValues[newAlleleIndex][r])
+                        newSampleValues[newAlleleIndex][r] = likelihood;
+                }
+            }
+        }
+        return result;
+    }
+
+    /**
+     * Given a collection of likelihood in the old map format, it creates the corresponding read-likelihoods collection.
+     *
+     * @param map the likelihoods to transform.
+     *
+     * @throws IllegalArgumentException if {@code map} is {@code null}.
+     *
+     * @return never {@code null}.
+     */
+    public static ReadLikelihoods<Allele> fromPerAlleleReadLikelihoodsMap(final Map<String,PerReadAlleleLikelihoodMap> map) {
+
+        // First we need to create the read-likelihood collection with all required alleles, samples and reads.
+        final SampleList sampleList = new IndexedSampleList(map.keySet());
+        final Set<Allele> alleles = new LinkedHashSet<>(10);
+        final Map<String,List<GATKSAMRecord>> sampleToReads = new HashMap<>(sampleList.sampleCount());
+        for (final Map.Entry<String,PerReadAlleleLikelihoodMap> entry : map.entrySet()) {
+            final String sample = entry.getKey();
+            final PerReadAlleleLikelihoodMap sampleLikelihoods = entry.getValue();
+            alleles.addAll(sampleLikelihoods.getAllelesSet());
+            sampleToReads.put(sample,new ArrayList<>(sampleLikelihoods.getLikelihoodReadMap().keySet()));
+        }
+
+        final AlleleList<Allele> alleleList = new IndexedAlleleList<>(alleles);
+        final ReadLikelihoods<Allele> result = new ReadLikelihoods<>(sampleList,alleleList,sampleToReads);
+
+        // Now set the likelihoods.
+        for (final Map.Entry<String,PerReadAlleleLikelihoodMap> sampleEntry : map.entrySet()) {
+            final ReadLikelihoods.Matrix<Allele> sampleMatrix = result.sampleMatrix(result.sampleIndex(sampleEntry.getKey()));
+            for (final Map.Entry<GATKSAMRecord,Map<Allele,Double>> readEntry : sampleEntry.getValue().getLikelihoodReadMap().entrySet()) {
+                final GATKSAMRecord read = readEntry.getKey();
+                final int readIndex = sampleMatrix.readIndex(read);
+                for (final Map.Entry<Allele,Double> alleleEntry : readEntry.getValue().entrySet()) {
+                    final int alleleIndex = result.alleleIndex(alleleEntry.getKey());
+                    sampleMatrix.set(alleleIndex,readIndex,alleleEntry.getValue());
+                }
+            }
+        }
+        return result;
+    }
+
+    // calculates an old to new allele index map array.
+    private <B extends Allele> int[] oldToNewAlleleIndexMap(final Map<B, List<A>> newToOldAlleleMap, final B[] newAlleles,
+                                                            final int oldAlleleCount, final int newAlleleCount) {
+
+        final int[] oldToNewAlleleIndexMap = new int[oldAlleleCount];
+        Arrays.fill(oldToNewAlleleIndexMap, -1);  // -1 indicate that there is no new allele that make reference to that old one.
+
+        for (int i = 0; i < newAlleleCount; i++) {
+            final B newAllele = newAlleles[i];
+            if (newAllele == null)
+                throw new IllegalArgumentException("input alleles cannot be null");
+            final List<A> oldAlleles = newToOldAlleleMap.get(newAllele);
+            if (oldAlleles == null)
+                throw new IllegalArgumentException("no new allele list can be null");
+            for (final A oldAllele : oldAlleles) {
+                if (oldAllele == null)
+                    throw new IllegalArgumentException("old alleles cannot be null");
+                final int oldAlleleIndex = alleleIndex(oldAllele);
+                if (oldAlleleIndex == -1)
+                    throw new IllegalArgumentException("missing old allele " + oldAllele + " in likelihood collection ");
+                if (oldToNewAlleleIndexMap[oldAlleleIndex] != -1)
+                    throw new IllegalArgumentException("collision: two new alleles make reference to the same old allele");
+                oldToNewAlleleIndexMap[oldAlleleIndex] = i;
+            }
+        }
+        return oldToNewAlleleIndexMap;
+    }
+
+    /**
+     * Remove those reads that do not overlap certain genomic location.
+     *
+     * <p>
+     *     This method modifies the current read-likelihoods collection.
+     * </p>
+     *
+     * @param location the target location.
+     *
+     * @throws IllegalArgumentException the location cannot be {@code null} nor unmapped.
+     */
+    @SuppressWarnings("unused")
+    public void filterToOnlyOverlappingUnclippedReads(final GenomeLoc location) {
+        if (location == null)
+            throw new IllegalArgumentException("the location cannot be null");
+        if (location.isUnmapped())
+            throw new IllegalArgumentException("the location cannot be unmapped");
+
+        final int sampleCount = samples.sampleCount();
+
+        final int locContig = location.getContigIndex();
+        final int locStart = location.getStart();
+        final int locEnd = location.getStop();
+
+        final int alleleCount = alleles.alleleCount();
+        final IntArrayList removeIndices = new IntArrayList(10);
+        for (int s = 0; s < sampleCount; s++) {
+            int readRemoveCount = 0;
+            final GATKSAMRecord[] sampleReads = readsBySampleIndex[s];
+            final int sampleReadCount = sampleReads.length;
+            for (int r = 0; r < sampleReadCount; r++)
+                if (!unclippedReadOverlapsRegion(sampleReads[r], locContig, locStart, locEnd))
+                    removeIndices.add(r);
+            removeSampleReads(s,removeIndices,alleleCount);
+            removeIndices.clear();
+        }
+    }
+
+    // Compare the read coordinates to the location of interest.
+    private boolean readOverlapsLocation(final String contig, final int locStart,
+                                         final int locEnd, final GATKSAMRecord read) {
+        final boolean overlaps;
+
+        if (read.getReadUnmappedFlag())
+            overlaps = false;
+        else if (!read.getReferenceName().equals(contig))
+            overlaps = false;
+        else {
+            int alnStart = read.getAlignmentStart();
+            int alnStop = read.getAlignmentEnd();
+            if (alnStart > alnStop) { // Paranoia? based on GLP.createGenomeLoc(Read) this can happen?.
+                final int end = alnStart;
+                alnStart = alnStop;
+                alnStop = end;
+            }
+            overlaps = !(alnStop < locStart || alnStart > locEnd);
+        }
+        return overlaps;
+    }
+
+    /**
+     * Removes those read that the best possible likelihood given any allele is just too low.
+     *
+     * <p>
+     *     This is determined by a maximum error per read-base against the best likelihood possible.
+     * </p>
+     *
+     * @param maximumErrorPerBase the minimum acceptable error rate per read base, must be
+     *                            a positive number.
+     *
+     * @throws IllegalStateException is not supported for read-likelihood that do not contain alleles.
+     *
+     * @throws IllegalArgumentException if {@code maximumErrorPerBase} is negative.
+     */
+    public void filterPoorlyModeledReads(final double maximumErrorPerBase) {
+        if (alleles.alleleCount() == 0)
+            throw new IllegalStateException("unsupported for read-likelihood collections with no alleles");
+        if (Double.isNaN(maximumErrorPerBase) || maximumErrorPerBase <= 0.0)
+            throw new IllegalArgumentException("the maximum error per base must be a positive number");
+        final int sampleCount = samples.sampleCount();
+
+        final int alleleCount = alleles.alleleCount();
+        final IntArrayList removeIndices = new IntArrayList(10);
+        for (int s = 0; s < sampleCount; s++) {
+            final GATKSAMRecord[] sampleReads = readsBySampleIndex[s];
+            final int sampleReadCount = sampleReads.length;
+            for (int r = 0; r < sampleReadCount; r++) {
+                final GATKSAMRecord read = sampleReads[r];
+                if (readIsPoorlyModelled(s,r,read, maximumErrorPerBase))
+                    removeIndices.add(r);
+            }
+            removeSampleReads(s, removeIndices, alleleCount);
+            removeIndices.clear();
+        }
+    }
+
+    // Check whether the read is poorly modelled.
+    protected boolean readIsPoorlyModelled(final int sampleIndex, final int readIndex, final GATKSAMRecord read, final double maxErrorRatePerBase) {
+        final double maxErrorsForRead = Math.min(2.0, Math.ceil(read.getReadLength() * maxErrorRatePerBase));
+        final double log10QualPerBase = -4.0;
+        final double log10MaxLikelihoodForTrueAllele = maxErrorsForRead * log10QualPerBase;
+
+        final int alleleCount = alleles.alleleCount();
+        final double[][] sampleValues = valuesBySampleIndex[sampleIndex];
+        for (int a = 0; a < alleleCount; a++)
+            if (sampleValues[a][readIndex] >= log10MaxLikelihoodForTrueAllele)
+                return false;
+        return true;
+    }
+
+
+    /**
+     * Add more reads to the collection.
+     *
+     * @param readsBySample reads to add.
+     * @param initialLikelihood the likelihood for the new entries.
+     *
+     * @throws IllegalArgumentException if {@code readsBySample} is {@code null} or {@code readsBySample} contains
+     *  {@code null} reads, or {@code readsBySample} contains read that are already present in the read-likelihood
+     *  collection.
+     */
+    public void addReads(final Map<String,List<GATKSAMRecord>> readsBySample, final double initialLikelihood) {
+
+        for (final Map.Entry<String,List<GATKSAMRecord>> entry : readsBySample.entrySet()) {
+
+            final String sample = entry.getKey();
+            final List<GATKSAMRecord> newSampleReads = entry.getValue();
+            final int sampleIndex = samples.sampleIndex(sample);
+
+            if (sampleIndex == -1)
+                throw new IllegalArgumentException("input sample " + sample +
+                        " is not part of the read-likelihoods collection");
+
+            if (newSampleReads == null || newSampleReads.size() == 0)
+                continue;
+
+            final int sampleReadCount = readsBySampleIndex[sampleIndex].length;
+            final int newSampleReadCount = sampleReadCount + newSampleReads.size();
+
+            appendReads(newSampleReads, sampleIndex, sampleReadCount, newSampleReadCount);
+            extendsLikelihoodArrays(initialLikelihood, sampleIndex, sampleReadCount, newSampleReadCount);
+        }
+    }
+
+    // Extends the likelihood arrays-matrices.
+    private void extendsLikelihoodArrays(double initialLikelihood, int sampleIndex, int sampleReadCount, int newSampleReadCount) {
+        final double[][] sampleValues = valuesBySampleIndex[sampleIndex];
+        final int alleleCount = alleles.alleleCount();
+        for (int a = 0; a < alleleCount; a++)
+            sampleValues[a] = Arrays.copyOf(sampleValues[a], newSampleReadCount);
+        if (initialLikelihood != 0.0) // the default array new value.
+            for (int a = 0; a < alleleCount; a++)
+                Arrays.fill(sampleValues[a],sampleReadCount,newSampleReadCount,initialLikelihood);
+    }
+
+    // Append the new read reference into the structure per-sample.
+    private void appendReads(final List<GATKSAMRecord> newSampleReads, final int sampleIndex,
+                             final int sampleReadCount, final int newSampleReadCount) {
+        final GATKSAMRecord[] sampleReads = readsBySampleIndex[sampleIndex] =
+                Arrays.copyOf(readsBySampleIndex[sampleIndex], newSampleReadCount);
+
+        int nextReadIndex = sampleReadCount;
+        final Object2IntMap<GATKSAMRecord> sampleReadIndex = readIndexBySampleIndex[sampleIndex];
+        for (final GATKSAMRecord newRead : newSampleReads) {
+        //    if (sampleReadIndex.containsKey(newRead)) // might be worth handle this without exception (ignore the read?) but in practice should never be the case.
+        //        throw new IllegalArgumentException("you cannot add reads that are already in read-likelihood collection");
+            if (sampleReadIndex != null ) sampleReadIndex.put(newRead,nextReadIndex);
+            sampleReads[nextReadIndex++] = newRead;
+        }
+    }
+
+    /**
+     * Adds the non-reference allele to the read-likelihood collection setting each read likelihood to the second
+     * best found (or best one if only one allele has likelihood).
+     *
+     * <p>Nothing will happen if the read-likelihoods collection already includes the non-ref allele</p>
+     *
+     * <p>
+     *     <i>Implementation note: even when strictly speaking we do not need to demand the calling code to pass
+     *     the reference the non-ref allele, we still demand it in order to lead the
+     *     the calling code to use the right generic type for this likelihoods
+     *     collection {@link Allele}.</i>
+     * </p>
+     *
+     * @param nonRefAllele the non-ref allele.
+     *
+     * @throws IllegalArgumentException if {@code nonRefAllele} is anything but the designated <NON_REF>
+     * symbolic allele {@link GATKVariantContextUtils#NON_REF_SYMBOLIC_ALLELE}.
+     */
+    public void addNonReferenceAllele(final A nonRefAllele) {
+
+        if (nonRefAllele == null)
+            throw new IllegalArgumentException("non-ref allele cannot be null");
+        if (!nonRefAllele.equals(GATKVariantContextUtils.NON_REF_SYMBOLIC_ALLELE))
+            throw new IllegalArgumentException("the non-ref allele is not valid");
+        // Already present?
+        if (alleles.alleleIndex(nonRefAllele) != -1)
+            return;
+
+        final int oldAlleleCount = alleles.alleleCount();
+        final int newAlleleCount = oldAlleleCount + 1;
+        @SuppressWarnings("unchecked")
+        final A[] newAlleles = (A[]) new Allele[newAlleleCount];
+        for (int a = 0; a < oldAlleleCount; a++)
+            newAlleles[a] = alleles.alleleAt(a);
+        newAlleles[oldAlleleCount] = nonRefAllele;
+        alleles = new IndexedAlleleList<>(newAlleles);
+        alleleList = null; // remove the cached alleleList.
+
+        final int sampleCount = samples.sampleCount();
+        for (int s = 0; s < sampleCount; s++)
+            addNonReferenceAlleleLikelihoodsPerSample(oldAlleleCount, newAlleleCount, s);
+    }
+
+    // Updates per-sample structures according to the addition of the NON_REF allele.
+    private void addNonReferenceAlleleLikelihoodsPerSample(final int alleleCount, final int newAlleleCount, final int sampleIndex) {
+        final double[][] sampleValues = valuesBySampleIndex[sampleIndex] = Arrays.copyOf(valuesBySampleIndex[sampleIndex], newAlleleCount);
+        final int sampleReadCount = readsBySampleIndex[sampleIndex].length;
+
+        final double[] nonRefAlleleLikelihoods = sampleValues[alleleCount] = new double [sampleReadCount];
+        Arrays.fill(nonRefAlleleLikelihoods,Double.NEGATIVE_INFINITY);
+        for (int r = 0; r < sampleReadCount; r++) {
+            final BestAllele bestAllele = searchBestAllele(sampleIndex,r,true);
+            final double secondBestLikelihood = Double.isInfinite(bestAllele.confidence) ? bestAllele.likelihood
+                    : bestAllele.likelihood - bestAllele.confidence;
+            nonRefAlleleLikelihoods[r] = secondBestLikelihood;
+        }
+    }
+
+    /**
+     * Downsamples reads based on contamination fractions making sure that all alleles are affected proportionally.
+     *
+     * @param perSampleDownsamplingFraction contamination sample map where the sample name are the keys and the
+     *                                       fractions are the values.
+     *
+     * @throws IllegalArgumentException if {@code perSampleDownsamplingFraction} is {@code null}.
+     */
+    public void contaminationDownsampling(final Map<String, Double> perSampleDownsamplingFraction) {
+
+        final int sampleCount = samples.sampleCount();
+        final IntArrayList readsToRemove = new IntArrayList(10); // blind estimate, can be improved?
+        final int alleleCount = alleles.alleleCount();
+        for (int s = 0; s < sampleCount; s++) {
+            final String sample = samples.sampleAt(s);
+            final Double fractionDouble = perSampleDownsamplingFraction.get(sample);
+            if (fractionDouble == null)
+                continue;
+            final double fraction = fractionDouble;
+            if (Double.isNaN(fraction) || fraction <= 0.0)
+                continue;
+            if (fraction >= 1.0) {
+                final int sampleReadCount = readsBySampleIndex[s].length;
+                readsToRemove.ensureCapacity(sampleReadCount);
+                for (int r = 0; r < sampleReadCount; r++)
+                    readsToRemove.add(r);
+                removeSampleReads(s,readsToRemove,alleleCount);
+                readsToRemove.clear();
+            }
+            else {
+                final Map<A,List<GATKSAMRecord>> readsByBestAllelesMap = readsByBestAlleleMap(s);
+                removeSampleReads(s,AlleleBiasedDownsamplingUtils.selectAlleleBiasedReads(readsByBestAllelesMap, fraction),alleleCount);
+            }
+        }
+    }
+
+    /**
+     * Given a collection of likelihood in the old map format, it creates the corresponding read-likelihoods collection.
+     *
+     * @param alleleList the target list of alleles.
+     * @param map the likelihoods to transform.
+     *
+     *
+     * @throws IllegalArgumentException if {@code map} is {@code null}, or {@code map} does not contain likelihoods for all read vs allele combinations.
+     *
+     * @return never {@code null}.
+     */
+    public static ReadLikelihoods<Allele> fromPerAlleleReadLikelihoodsMap(final AlleleList<Allele> alleleList, final Map<String,PerReadAlleleLikelihoodMap> map) {
+
+        //TODO add test code for this method.
+        // First we need to create the read-likelihood collection with all required alleles, samples and reads.
+        final SampleList sampleList = new IndexedSampleList(map.keySet());
+        final int alleleCount = alleleList.alleleCount();
+        final Map<String,List<GATKSAMRecord>> sampleToReads = new HashMap<>(sampleList.sampleCount());
+        for (final Map.Entry<String,PerReadAlleleLikelihoodMap> entry : map.entrySet()) {
+            final String sample = entry.getKey();
+            final PerReadAlleleLikelihoodMap sampleLikelihoods = entry.getValue();
+            sampleToReads.put(sample,new ArrayList<>(sampleLikelihoods.getLikelihoodReadMap().keySet()));
+        }
+
+        final ReadLikelihoods<Allele> result = new ReadLikelihoods<>(sampleList,alleleList,sampleToReads);
+
+        // Now set the likelihoods.
+        for (final Map.Entry<String,PerReadAlleleLikelihoodMap> sampleEntry : map.entrySet()) {
+            final ReadLikelihoods.Matrix<Allele> sampleMatrix = result.sampleMatrix(result.sampleIndex(sampleEntry.getKey()));
+            for (final Map.Entry<GATKSAMRecord,Map<Allele,Double>> readEntry : sampleEntry.getValue().getLikelihoodReadMap().entrySet()) {
+                final GATKSAMRecord read = readEntry.getKey();
+                final int readIndex = sampleMatrix.readIndex(read);
+                final Map<Allele,Double> alleleToLikelihoodMap = readEntry.getValue();
+                for (int a = 0; a < alleleCount; a++) {
+                    final Allele allele = alleleList.alleleAt(a);
+                    final Double likelihood = alleleToLikelihoodMap.get(allele);
+                    if (likelihood == null)
+                        throw new IllegalArgumentException("there is no likelihood for allele " + allele + " and read " + read);
+                    sampleMatrix.set(a,readIndex,likelihood);
+                }
+            }
+        }
+        return result;
+    }
+
+    /**
+     * Returns the collection of best allele estimates for the reads based on the read-likelihoods.
+     *
+     * @throws IllegalStateException if there is no alleles.
+     *
+     * @return never {@code null}, one element per read in the read-likelihoods collection.
+     */
+    public Collection<BestAllele> bestAlleles() {
+        final List<BestAllele> result = new ArrayList<>(100); // blind estimate.
+        final int sampleCount = samples.sampleCount();
+        for (int s = 0; s < sampleCount; s++) {
+            final GATKSAMRecord[] sampleReads = readsBySampleIndex[s];
+            final int readCount = sampleReads.length;
+            for (int r = 0; r < readCount; r++)
+                result.add(searchBestAllele(s,r,true));
+        }
+        return result;
+    }
+
+    /**
+     * Returns reads stratified by their best allele.
+     * @param sampleIndex the target sample.
+     * @return never {@code null}, perhaps empty.
+     */
+    public Map<A,List<GATKSAMRecord>> readsByBestAlleleMap(final int sampleIndex) {
+        checkSampleIndex(sampleIndex);
+        final int alleleCount = alleles.alleleCount();
+        final int sampleReadCount = readsBySampleIndex[sampleIndex].length;
+        final Map<A,List<GATKSAMRecord>> result = new HashMap<>(alleleCount);
+        for (int a = 0; a < alleleCount; a++)
+            result.put(alleles.alleleAt(a),new ArrayList<GATKSAMRecord>(sampleReadCount));
+        readsByBestAlleleMap(sampleIndex,result);
+        return result;
+    }
+
+    /**
+     * Returns reads stratified by their best allele.
+     * @return never {@code null}, perhaps empty.
+     */
+    @SuppressWarnings("unused")
+    public Map<A,List<GATKSAMRecord>> readsByBestAlleleMap() {
+        final int alleleCount = alleles.alleleCount();
+        final Map<A,List<GATKSAMRecord>> result = new HashMap<>(alleleCount);
+        final int totalReadCount = readCount();
+        for (int a = 0; a < alleleCount; a++)
+            result.put(alleles.alleleAt(a),new ArrayList<GATKSAMRecord>(totalReadCount));
+        final int sampleCount = samples.sampleCount();
+        for (int s = 0; s < sampleCount; s++)
+            readsByBestAlleleMap(s,result);
+        return result;
+    }
+
+    private void readsByBestAlleleMap(final int sampleIndex, final Map<A,List<GATKSAMRecord>> result) {
+        final GATKSAMRecord[] reads = readsBySampleIndex[sampleIndex];
+        final int readCount = reads.length;
+
+        for (int r = 0; r < readCount; r++) {
+            final BestAllele bestAllele = searchBestAllele(sampleIndex,r,true);
+            if (!bestAllele.isInformative())
+                continue;
+            result.get(bestAllele.allele).add(bestAllele.read);
+        }
+    }
+
+    /**
+     * Returns the index of a read within a sample read-likelihood sub collection.
+     * @param sampleIndex the sample index.
+     * @param read the query read.
+     * @return -1 if there is no such read in that sample, 0 or greater otherwise.
+     */
+    @SuppressWarnings("unused")
+    public int readIndex(final int sampleIndex, final GATKSAMRecord read) {
+        final Object2IntMap<GATKSAMRecord> readIndex = readIndexBySampleIndex(sampleIndex);
+        if (readIndex.containsKey(read))
+            return readIndexBySampleIndex(sampleIndex).getInt(read);
+        else
+            return -1;
+    }
+
+    /**
+     * Returns the total number of reads in the read-likelihood collection.
+     *
+     * @return never {@code null}
+     */
+    public int readCount() {
+        int sum = 0;
+        final int sampleCount = samples.sampleCount();
+        for (int i = 0; i < sampleCount; i++)
+            sum += readsBySampleIndex[i].length;
+        return sum;
+    }
+
+    /**
+     * Returns the number of reads that belong to a sample in the read-likelihood collection.
+     * @param sampleIndex the query sample index.
+     *
+     * @throws IllegalArgumentException if {@code sampleIndex} is not a valid sample index.
+     * @return 0 or greater.
+     */
+    public int sampleReadCount(int sampleIndex) {
+        checkSampleIndex(sampleIndex);
+        return readsBySampleIndex[sampleIndex].length;
+    }
+
+    /**
+     * Contains information about the best allele for a read search result.
+     */
+    public class BestAllele {
+        public static final double INFORMATIVE_THRESHOLD = 0.2;
+
+        /**
+         * Null if there is no possible match (no allele?).
+         */
+        public final A allele;
+
+        /**
+         * The containing sample.
+         */
+        public final String sample;
+
+        /**
+         * The query read.
+         */
+        public final GATKSAMRecord read;
+
+        /**
+         * If allele != null, the indicates the likelihood of the read.
+         */
+        public final double likelihood;
+
+        /**
+         * Confidence that the read actually was generated under that likelihood.
+         * This is equal to the difference between this and the second best allele match.
+         */
+        public final double confidence;
+
+        private BestAllele(final int sampleIndex, final int readIndex, final int bestAlleleIndex,
+                           final double likelihood, final double secondBestLikelihood) {
+            allele = bestAlleleIndex == -1 ? null : alleles.alleleAt(bestAlleleIndex);
+            this.likelihood = likelihood;
+            sample = samples.sampleAt(sampleIndex);
+            read = readsBySampleIndex[sampleIndex][readIndex];
+            confidence = likelihood == secondBestLikelihood ? 0 : likelihood - secondBestLikelihood;
+        }
+
+        public boolean isInformative() {
+            return confidence > INFORMATIVE_THRESHOLD;
+        }
+    }
+
+    private void removeSampleReads(final int sampleIndex, final IntArrayList indexToRemove, final int alleleCount) {
+        final int removeCount = indexToRemove.size();
+        if (removeCount == 0)
+            return;
+
+        final GATKSAMRecord[] sampleReads = readsBySampleIndex[sampleIndex];
+        final int sampleReadCount = sampleReads.length;
+
+        final Object2IntMap<GATKSAMRecord> indexByRead = readIndexBySampleIndex[sampleIndex];
+        if (indexByRead != null)
+            for (int i = 0; i < removeCount; i++)
+                indexByRead.remove(sampleReads[indexToRemove.getInt(i)]);
+        final boolean[] removeIndex = new boolean[sampleReadCount];
+        int firstDeleted = indexToRemove.get(0);
+        for (int i = 0; i < removeCount; i++)
+            removeIndex[indexToRemove.get(i)] = true;
+
+        final int newSampleReadCount = sampleReadCount - removeCount;
+
+        // Now we skim out the removed reads from the read array.
+        final GATKSAMRecord[] oldSampleReads = readsBySampleIndex[sampleIndex];
+        final GATKSAMRecord[] newSampleReads = new GATKSAMRecord[newSampleReadCount];
+
+        System.arraycopy(oldSampleReads,0,newSampleReads,0,firstDeleted);
+        Utils.skimArray(oldSampleReads,firstDeleted, newSampleReads, firstDeleted, removeIndex, firstDeleted);
+
+        // Then we skim out the likelihoods of the removed reads.
+        final double[][] oldSampleValues = valuesBySampleIndex[sampleIndex];
+        final double[][] newSampleValues = new double[alleleCount][newSampleReadCount];
+        for (int a = 0; a < alleleCount; a++) {
+            System.arraycopy(oldSampleValues[a],0,newSampleValues[a],0,firstDeleted);
+            Utils.skimArray(oldSampleValues[a], firstDeleted, newSampleValues[a], firstDeleted, removeIndex, firstDeleted);
+        }
+        valuesBySampleIndex[sampleIndex] = newSampleValues;
+        readsBySampleIndex[sampleIndex] = newSampleReads;
+        readListBySampleIndex[sampleIndex] = null; // reset the unmodifiable list.
+    }
+
+
+    // Requires that the collection passed iterator can remove elements, and it can be modified.
+    private void removeSampleReads(final int sampleIndex, final Collection<GATKSAMRecord> readsToRemove, final int alleleCount) {
+        final GATKSAMRecord[] sampleReads = readsBySampleIndex[sampleIndex];
+        final int sampleReadCount = sampleReads.length;
+
+        final Object2IntMap<GATKSAMRecord> indexByRead = readIndexBySampleIndex(sampleIndex);
+        // Count how many we are going to remove, which ones (indexes) and remove entry from the read-index map.
+        final boolean[] removeIndex = new boolean[sampleReadCount];
+        int removeCount = 0; // captures the number of deletions.
+        int firstDeleted = sampleReadCount;    // captures the first position that was deleted.
+
+        final Iterator<GATKSAMRecord> readsToRemoveIterator = readsToRemove.iterator();
+        while (readsToRemoveIterator.hasNext()) {
+            final GATKSAMRecord read = readsToRemoveIterator.next();
+            if (indexByRead.containsKey(read)) {
+                final int index = indexByRead.getInt(read);
+                if (firstDeleted > index)
+                    firstDeleted = index;
+                removeCount++;
+                removeIndex[index] = true;
+                readsToRemoveIterator.remove();
+                indexByRead.remove(read);
+            }
+        }
+
+        // Nothing to remove we just finish here.
+        if (removeCount == 0)
+            return;
+
+        final int newSampleReadCount = sampleReadCount - removeCount;
+
+        // Now we skim out the removed reads from the read array.
+        final GATKSAMRecord[] oldSampleReads = readsBySampleIndex[sampleIndex];
+        final GATKSAMRecord[] newSampleReads = new GATKSAMRecord[newSampleReadCount];
+
+        System.arraycopy(oldSampleReads,0,newSampleReads,0,firstDeleted);
+        Utils.skimArray(oldSampleReads,firstDeleted, newSampleReads, firstDeleted, removeIndex, firstDeleted);
+
+        // Update the indices for the extant reads from the first deletion onwards.
+        for (int r = firstDeleted; r < newSampleReadCount; r++) {
+            indexByRead.put(newSampleReads[r], r);
+        }
+
+        // Then we skim out the likelihoods of the removed reads.
+        final double[][] oldSampleValues = valuesBySampleIndex[sampleIndex];
+        final double[][] newSampleValues = new double[alleleCount][newSampleReadCount];
+        for (int a = 0; a < alleleCount; a++) {
+            System.arraycopy(oldSampleValues[a],0,newSampleValues[a],0,firstDeleted);
+            Utils.skimArray(oldSampleValues[a], firstDeleted, newSampleValues[a], firstDeleted, removeIndex, firstDeleted);
+        }
+        valuesBySampleIndex[sampleIndex] = newSampleValues;
+        readsBySampleIndex[sampleIndex] = newSampleReads;
+        readListBySampleIndex[sampleIndex] = null; // reset the unmodifiable list.
+    }
+
+    private Object2IntMap<GATKSAMRecord> readIndexBySampleIndex(final int sampleIndex) {
+        if (readIndexBySampleIndex[sampleIndex] == null) {
+            final GATKSAMRecord[] sampleReads = readsBySampleIndex[sampleIndex];
+            final int sampleReadCount = sampleReads.length;
+            readIndexBySampleIndex[sampleIndex] = new Object2IntOpenHashMap<>(sampleReadCount);
+            for (int r = 0; r < sampleReadCount; r++)
+                readIndexBySampleIndex[sampleIndex].put(sampleReads[r],r);
+        }
+        return readIndexBySampleIndex[sampleIndex];
+    }
+
+    /**
+     * Transform into a multi-sample HashMap backed {@link PerReadAlleleLikelihoodMap} type.
+     * @return never {@code null}.
+     *
+     * @deprecated
+     *
+     * This method should eventually disappear once we have removed PerReadAlleleLikelihoodMap class completelly.
+     */
+    @Deprecated
+    @SuppressWarnings("all")
+    public Map<String, PerReadAlleleLikelihoodMap> toPerReadAlleleLikelihoodMap() {
+        final int sampleCount = samples.sampleCount();
+        final Map<String, PerReadAlleleLikelihoodMap> result = new HashMap<>(sampleCount);
+        for (int s = 0; s < sampleCount; s++)
+            result.put(samples.sampleAt(s),toPerReadAlleleLikelihoodMap(s));
+        return result;
+    }
+
+    /**
+     * Transform into a single-sample HashMap backed {@link PerReadAlleleLikelihoodMap} type.
+     *
+     * @return never {@code null}.
+     */
+    @Deprecated
+    public PerReadAlleleLikelihoodMap toPerReadAlleleLikelihoodMap(final int sampleIndex) {
+        checkSampleIndex(sampleIndex);
+        final PerReadAlleleLikelihoodMap result = new PerReadAlleleLikelihoodMap();
+        final int alleleCount = alleles.alleleCount();
+        final GATKSAMRecord[] sampleReads = readsBySampleIndex[sampleIndex];
+        final int sampleReadCount = sampleReads.length;
+        for (int a = 0; a < alleleCount; a++) {
+            final A allele = alleles.alleleAt(a);
+            final double[] readLikelihoods = valuesBySampleIndex[sampleIndex][a];
+            for (int r = 0; r < sampleReadCount; r++)
+                result.add(sampleReads[r], allele, readLikelihoods[r]);
+        }
+        return result;
+    }
+
+    /**
+     * Implements a likelihood matrix per sample given its index.
+     */
+    private class SampleMatrix implements Matrix<A> {
+
+        private final int sampleIndex;
+
+        private SampleMatrix(final int sampleIndex) {
+            this.sampleIndex = sampleIndex;
+        }
+
+        @Override
+        public List<GATKSAMRecord> reads() {
+            return sampleReads(sampleIndex);
+        }
+
+        @Override
+        public List<A> alleles() {
+            return ReadLikelihoods.this.alleles();
+        }
+
+        @Override
+        public void set(final int alleleIndex, final int readIndex, final double value) {
+            valuesBySampleIndex[sampleIndex][alleleIndex][readIndex] = value;
+        }
+
+        @Override
+        public double get(final int alleleIndex, final int readIndex) {
+            return valuesBySampleIndex[sampleIndex][alleleIndex][readIndex];
+        }
+
+        @Override
+        public int alleleIndex(final A allele) {
+            return ReadLikelihoods.this.alleleIndex(allele);
+        }
+
+        @Override
+        public int readIndex(final GATKSAMRecord read) {
+            return ReadLikelihoods.this.readIndex(sampleIndex, read);
+        }
+
+        @Override
+        public int alleleCount() {
+            return alleles.alleleCount();
+        }
+
+        @Override
+        public int readCount() {
+            return readsBySampleIndex[sampleIndex].length;
+        }
+
+        @Override
+        public A alleleAt(int alleleIndex) {
+            return ReadLikelihoods.this.alleleAt(alleleIndex);
+        }
+
+        @Override
+        public GATKSAMRecord readAt(final int readIndex) {
+            if (readIndex < 0)
+                throw new IllegalArgumentException("the read-index cannot be negative");
+            final GATKSAMRecord[] sampleReads = readsBySampleIndex[sampleIndex];
+            if (readIndex >= sampleReads.length)
+                throw new IllegalArgumentException("the read-index is beyond the read count of the sample");
+            return sampleReads[readIndex];
+        }
+
+        @Override
+        public void copyAlleleLikelihoods(final int alleleIndex, final double[] dest, final int offset) {
+            System.arraycopy(valuesBySampleIndex[sampleIndex][alleleIndex],0,dest,offset,readCount());
+        }
+    }
+
+    /**
+     * Checks whether the provide sample index is valid.
+     * <p>
+     *     If not, it throws an exception.
+     * </p>
+     * @param sampleIndex the target sample index.
+     *
+     * @throws IllegalArgumentException if {@code sampleIndex} is invalid, i.e. outside the range [0,{@link #sampleCount}).
+     */
+    private void checkSampleIndex(final int sampleIndex) {
+        if (sampleIndex < 0 || sampleIndex >= samples.sampleCount())
+            throw new IllegalArgumentException("invalid sample index: " + sampleIndex);
+    }
+}
\ No newline at end of file
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/haplotype/EventMap.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/haplotype/EventMap.java
new file mode 100644
index 0000000..e5eee12
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/haplotype/EventMap.java
@@ -0,0 +1,423 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.utils.haplotype;
+
+import com.google.java.contract.Ensures;
+import com.google.java.contract.Requires;
+import htsjdk.samtools.Cigar;
+import htsjdk.samtools.CigarElement;
+import org.apache.commons.lang.ArrayUtils;
+import org.apache.log4j.Logger;
+import org.broadinstitute.gatk.utils.BaseUtils;
+import org.broadinstitute.gatk.utils.GenomeLoc;
+import org.broadinstitute.gatk.utils.exceptions.ReviewedGATKException;
+import org.broadinstitute.gatk.utils.sam.AlignmentUtils;
+import htsjdk.variant.variantcontext.Allele;
+import htsjdk.variant.variantcontext.VariantContext;
+import htsjdk.variant.variantcontext.VariantContextBuilder;
+
+import java.util.*;
+
+/**
+ * Extract simple VariantContext events from a single haplotype
+ *
+ * User: depristo
+ * Date: 3/27/13
+ * Time: 8:35 AM
+ */
+public class EventMap extends TreeMap<Integer, VariantContext> {
+    private final static Logger logger = Logger.getLogger(EventMap.class);
+    protected final static int MIN_NUMBER_OF_EVENTS_TO_COMBINE_INTO_BLOCK_SUBSTITUTION = 3;
+    private static final int MAX_EVENTS_PER_HAPLOTYPE = 3;
+    private static final int MAX_INDELS_PER_HAPLOTYPE = 2;
+    public final static Allele SYMBOLIC_UNASSEMBLED_EVENT_ALLELE = Allele.create("<UNASSEMBLED_EVENT>", false);
+
+    private final Haplotype haplotype;
+    private final byte[] ref;
+    private final GenomeLoc refLoc;
+    private final String sourceNameToAdd;
+
+    public EventMap(final Haplotype haplotype, final byte[] ref, final GenomeLoc refLoc, final String sourceNameToAdd) {
+        super();
+        this.haplotype = haplotype;
+        this.ref = ref;
+        this.refLoc = refLoc;
+        this.sourceNameToAdd = sourceNameToAdd;
+
+        processCigarForInitialEvents();
+    }
+
+    /**
+     * For testing.  Let's you set up a explicit configuration without having to process a haplotype and reference
+     * @param stateForTesting
+     */
+    public EventMap(final Collection<VariantContext> stateForTesting) {
+        haplotype = null;
+        ref = null;
+        refLoc = null;
+        sourceNameToAdd = null;
+        for ( final VariantContext vc : stateForTesting )
+            addVC(vc);
+    }
+
+    protected void processCigarForInitialEvents() {
+        final Cigar cigar = haplotype.getCigar();
+        final byte[] alignment = haplotype.getBases();
+
+        int refPos = haplotype.getAlignmentStartHapwrtRef();
+        if( refPos < 0 ) {
+            return;
+        } // Protection against SW failures
+
+        final List<VariantContext> proposedEvents = new ArrayList<>();
+
+        int alignmentPos = 0;
+
+        for( int cigarIndex = 0; cigarIndex < cigar.numCigarElements(); cigarIndex++ ) {
+            final CigarElement ce = cigar.getCigarElement(cigarIndex);
+            final int elementLength = ce.getLength();
+            switch( ce.getOperator() ) {
+                case I:
+                {
+                    if( refPos > 0 ) { // protect against trying to create insertions/deletions at the beginning of a contig
+                        final List<Allele> insertionAlleles = new ArrayList<Allele>();
+                        final int insertionStart = refLoc.getStart() + refPos - 1;
+                        final byte refByte = ref[refPos-1];
+                        if( BaseUtils.isRegularBase(refByte) ) {
+                            insertionAlleles.add( Allele.create(refByte, true) );
+                        }
+                        if( cigarIndex == 0 || cigarIndex == cigar.getCigarElements().size() - 1 ) {
+                            // if the insertion isn't completely resolved in the haplotype, skip it
+                            // note this used to emit SYMBOLIC_UNASSEMBLED_EVENT_ALLELE but that seems dangerous
+                        } else {
+                            byte[] insertionBases = new byte[]{};
+                            insertionBases = ArrayUtils.add(insertionBases, ref[refPos - 1]); // add the padding base
+                            insertionBases = ArrayUtils.addAll(insertionBases, Arrays.copyOfRange(alignment, alignmentPos, alignmentPos + elementLength));
+                            if( BaseUtils.isAllRegularBases(insertionBases) ) {
+                                insertionAlleles.add( Allele.create(insertionBases, false) );
+                            }
+                        }
+                        if( insertionAlleles.size() == 2 ) { // found a proper ref and alt allele
+                            proposedEvents.add(new VariantContextBuilder(sourceNameToAdd, refLoc.getContig(), insertionStart, insertionStart, insertionAlleles).make());
+                        }
+                    }
+                    alignmentPos += elementLength;
+                    break;
+                }
+                case S:
+                {
+                    alignmentPos += elementLength;
+                    break;
+                }
+                case D:
+                {
+                    if( refPos > 0 ) { // protect against trying to create insertions/deletions at the beginning of a contig
+                        final byte[] deletionBases = Arrays.copyOfRange( ref, refPos - 1, refPos + elementLength );  // add padding base
+                        final List<Allele> deletionAlleles = new ArrayList<Allele>();
+                        final int deletionStart = refLoc.getStart() + refPos - 1;
+                        final byte refByte = ref[refPos-1];
+                        if( BaseUtils.isRegularBase(refByte) && BaseUtils.isAllRegularBases(deletionBases) ) {
+                            deletionAlleles.add( Allele.create(deletionBases, true) );
+                            deletionAlleles.add( Allele.create(refByte, false) );
+                            proposedEvents.add(new VariantContextBuilder(sourceNameToAdd, refLoc.getContig(), deletionStart, deletionStart + elementLength, deletionAlleles).make());
+                        }
+                    }
+                    refPos += elementLength;
+                    break;
+                }
+                case M:
+                case EQ:
+                case X:
+                {
+                    for( int iii = 0; iii < elementLength; iii++ ) {
+                        final byte refByte = ref[refPos];
+                        final byte altByte = alignment[alignmentPos];
+                        if( refByte != altByte ) { // SNP!
+                            if( BaseUtils.isRegularBase(refByte) && BaseUtils.isRegularBase(altByte) ) {
+                                final List<Allele> snpAlleles = new ArrayList<Allele>();
+                                snpAlleles.add( Allele.create( refByte, true ) );
+                                snpAlleles.add( Allele.create( altByte, false ) );
+                                proposedEvents.add(new VariantContextBuilder(sourceNameToAdd, refLoc.getContig(), refLoc.getStart() + refPos, refLoc.getStart() + refPos, snpAlleles).make());
+                            }
+                        }
+                        refPos++;
+                        alignmentPos++;
+                    }
+                    break;
+                }
+                case N:
+                case H:
+                case P:
+                default:
+                    throw new ReviewedGATKException( "Unsupported cigar operator created during SW alignment: " + ce.getOperator() );
+            }
+        }
+
+        for ( final VariantContext proposedEvent : proposedEvents )
+            addVC(proposedEvent, true);
+    }
+
+    /**
+     * Add VariantContext vc to this map, merging events with the same start sites if necessary
+     * @param vc the variant context to add
+     */
+    protected void addVC(final VariantContext vc) {
+        addVC(vc, true);
+    }
+
+    /**
+     * Add VariantContext vc to this map
+     * @param vc the variant context to add
+     * @param merge should we attempt to merge it with an already existing element, or should we throw an error in that case?
+     */
+    protected void addVC(final VariantContext vc, final boolean merge) {
+        if ( vc == null ) throw new IllegalArgumentException("vc cannot be null");
+
+        if ( containsKey(vc.getStart()) ) {
+            if ( merge ) {
+                final VariantContext prev = get(vc.getStart());
+                put(vc.getStart(), makeBlock(prev, vc));
+            } else {
+                throw new IllegalStateException("Will not merge previously bound variant contexts as merge is false at " + vc);
+            }
+        } else
+            put(vc.getStart(), vc);
+    }
+
+    /**
+     * Create a block substitution out of two variant contexts that start at the same position
+     *
+     * vc1 can be SNP, and vc2 can then be either a insertion or deletion.
+     * If vc1 is an indel, then vc2 must be the opposite type (vc1 deletion => vc2 must be an insertion)
+     *
+     * @param vc1 the first variant context we want to merge
+     * @param vc2 the second
+     * @return a block substitution that represents the composite substitution implied by vc1 and vc2
+     */
+    protected VariantContext makeBlock(final VariantContext vc1, final VariantContext vc2) {
+        if ( vc1.getStart() != vc2.getStart() )  throw new IllegalArgumentException("vc1 and 2 must have the same start but got " + vc1 + " and " + vc2);
+        if ( ! vc1.isBiallelic() ) throw new IllegalArgumentException("vc1 must be biallelic");
+        if ( ! vc1.isSNP() ) {
+            if ( ! ((vc1.isSimpleDeletion() && vc2.isSimpleInsertion()) || (vc1.isSimpleInsertion() && vc2.isSimpleDeletion())))
+                throw new IllegalArgumentException("Can only merge single insertion with deletion (or vice versa) but got " + vc1 + " merging with " + vc2);
+        } else if ( vc2.isSNP() ) {
+            throw new IllegalArgumentException("vc1 is " + vc1 + " but vc2 is a SNP, which implies there's been some terrible bug in the cigar " + vc2);
+        }
+
+        final Allele ref, alt;
+        final VariantContextBuilder b = new VariantContextBuilder(vc1);
+        if ( vc1.isSNP() ) {
+            // we have to repair the first base, so SNP case is special cased
+            if ( vc1.getReference().equals(vc2.getReference()) ) {
+                // we've got an insertion, so we just update the alt to have the prev alt
+                ref = vc1.getReference();
+                alt = Allele.create(vc1.getAlternateAllele(0).getDisplayString() + vc2.getAlternateAllele(0).getDisplayString().substring(1), false);
+            } else {
+                // we're dealing with a deletion, so we patch the ref
+                ref = vc2.getReference();
+                alt = vc1.getAlternateAllele(0);
+                b.stop(vc2.getEnd());
+            }
+        } else {
+            final VariantContext insertion = vc1.isSimpleInsertion() ? vc1 : vc2;
+            final VariantContext deletion  = vc1.isSimpleInsertion() ? vc2 : vc1;
+            ref = deletion.getReference();
+            alt = insertion.getAlternateAllele(0);
+            b.stop(deletion.getEnd());
+        }
+
+        return b.alleles(Arrays.asList(ref, alt)).make();
+    }
+
+    // TODO -- warning this is an O(N^3) algorithm because I'm just lazy.  If it's valuable we need to reengineer it
+    @Requires("getNumberOfEvents() > 0")
+    protected void replaceClumpedEventsWithBlockSubstitutions() {
+        if ( getNumberOfEvents() >= MIN_NUMBER_OF_EVENTS_TO_COMBINE_INTO_BLOCK_SUBSTITUTION) {
+            int lastStart = -1;
+            for ( boolean foundOne = true; foundOne; ) {
+                foundOne = false;
+                for ( final VariantContext vc : getVariantContexts() ) {
+                    if ( vc.getStart() > lastStart ) {
+                        lastStart = vc.getStart();
+                        final List<VariantContext> neighborhood = getNeighborhood(vc, 10);
+                        if ( updateToBlockSubstitutionIfBetter(neighborhood) ) {
+                            foundOne = true;
+                            break;
+                        }
+                    }
+                }
+            }
+        }
+    }
+
+    protected boolean updateToBlockSubstitutionIfBetter(final List<VariantContext> neighbors) {
+        if (neighbors.size() < MIN_NUMBER_OF_EVENTS_TO_COMBINE_INTO_BLOCK_SUBSTITUTION)
+            return false;
+        // TODO -- need more tests to decide if this is really so good
+
+        final VariantContext first = neighbors.get(0);
+        final int refStartOffset = first.getStart() - refLoc.getStart();
+        final int refEndOffset = neighbors.get(neighbors.size() - 1).getEnd() - refLoc.getStart();
+
+        final byte[] refBases = Arrays.copyOfRange(ref, refStartOffset, refEndOffset + 1);
+        final byte[] hapBases = AlignmentUtils.getBasesCoveringRefInterval(refStartOffset, refEndOffset, haplotype.getBases(), haplotype.getAlignmentStartHapwrtRef(), haplotype.getCigar());
+
+        final VariantContextBuilder builder = new VariantContextBuilder(first);
+        builder.stop(first.getStart() + refBases.length - 1);
+        builder.alleles(Arrays.asList(Allele.create(refBases, true), Allele.create(hapBases)));
+        final VariantContext block = builder.make();
+
+        // remove all merged events
+        for ( final VariantContext merged : neighbors ) {
+            if ( remove(merged.getStart()) == null )
+                throw new IllegalArgumentException("Expected to remove variant context from the event map but remove said there wasn't any element there: " + merged);
+        }
+
+        // note must be after we remove the previous events as the treeset only allows one key per start
+        logger.info("Transforming into block substitution at " + block);
+        addVC(block, false);
+
+        return true;
+    }
+
+    /**
+     * Get all of the variant contexts starting at leftMost that are within maxBP of each other
+     *
+     * @param leftMost the left most (smallest position) variant context that will start the neighborhood
+     * @param maxBPBetweenEvents the maximum distance in BP between the end of one event the start of the next
+     *                           to be included the the resulting list
+     * @return a list that contains at least one element (leftMost)
+     */
+    @Requires({"leftMost != null", "maxBPBetweenEvents >= 0"})
+    @Ensures({"result != null", "! result.isEmpty()"})
+    protected List<VariantContext> getNeighborhood(final VariantContext leftMost, final int maxBPBetweenEvents) {
+        final List<VariantContext> neighbors = new LinkedList<VariantContext>();
+
+        VariantContext left = leftMost;
+        for ( final VariantContext vc : getVariantContexts() ) {
+            if ( vc.getStart() < leftMost.getStart() )
+                continue;
+
+            if ( vc.getStart() - left.getEnd() < maxBPBetweenEvents ) {
+                // this vc is within max distance to the end of the left event, so accumulate it
+                neighbors.add(vc);
+                left = vc;
+            }
+        }
+
+        return neighbors;
+    }
+
+    /**
+     * Get the starting positions of events in this event map
+     * @return
+     */
+    public Set<Integer> getStartPositions() {
+        return keySet();
+    }
+
+    /**
+     * Get the variant contexts in order of start position in this event map
+     * @return
+     */
+    public Collection<VariantContext> getVariantContexts() {
+        return values();
+    }
+
+    /**
+     * How many events do we have?
+     * @return
+     */
+    public int getNumberOfEvents() {
+        return size();
+    }
+
+    @Override
+    public String toString() {
+        final StringBuilder b = new StringBuilder("EventMap{");
+        for ( final VariantContext vc : getVariantContexts() )
+            b.append(String.format("%s:%d-%d %s,", vc.getChr(), vc.getStart(), vc.getEnd(), vc.getAlleles()));
+        b.append("}");
+        return b.toString();
+    }
+
+    /**
+     * Build event maps for each haplotype, returning the sorted set of all of the starting positions of all
+     * events across all haplotypes
+     *
+     * @param haplotypes a list of haplotypes
+     * @param ref the reference bases
+     * @param refLoc the span of the reference bases
+     * @param debug if true, we'll emit debugging information during this operation
+     * @return a sorted set of start positions of all events among all haplotypes
+     */
+    public static TreeSet<Integer> buildEventMapsForHaplotypes( final List<Haplotype> haplotypes,
+                                                                final byte[] ref,
+                                                                final GenomeLoc refLoc,
+                                                                final boolean debug) {
+        // Using the cigar from each called haplotype figure out what events need to be written out in a VCF file
+        final TreeSet<Integer> startPosKeySet = new TreeSet<Integer>();
+        int hapNumber = 0;
+
+        if( debug ) logger.info("=== Best Haplotypes ===");
+        for( final Haplotype h : haplotypes ) {
+            // Walk along the alignment and turn any difference from the reference into an event
+            h.setEventMap( new EventMap( h, ref, refLoc, "HC" + hapNumber++ ) );
+            startPosKeySet.addAll(h.getEventMap().getStartPositions());
+
+            if( debug ) {
+                logger.info(h.toString());
+                logger.info("> Cigar = " + h.getCigar());
+                logger.info(">> Events = " + h.getEventMap());
+            }
+        }
+
+        return startPosKeySet;
+    }
+
+    private static class VariantContextComparator implements Comparator<VariantContext> {
+        @Override
+        public int compare(VariantContext vc1, VariantContext vc2) {
+            return vc1.getStart() - vc2.getStart();
+        }
+    }
+
+    /**
+     * Get all of the VariantContexts in the event maps for all haplotypes, sorted by their start position
+     * @param haplotypes the set of haplotypes to grab the VCs from
+     * @return a sorted set of variant contexts
+     */
+    public static TreeSet<VariantContext> getAllVariantContexts( final List<Haplotype> haplotypes ) {
+        // Using the cigar from each called haplotype figure out what events need to be written out in a VCF file
+        final TreeSet<VariantContext> vcs = new TreeSet<VariantContext>(new VariantContextComparator());
+
+        for( final Haplotype h : haplotypes ) {
+            vcs.addAll(h.getEventMap().getVariantContexts());
+        }
+
+        return vcs;
+    }
+}
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/haplotype/Haplotype.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/haplotype/Haplotype.java
new file mode 100644
index 0000000..7b31b2a
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/haplotype/Haplotype.java
@@ -0,0 +1,343 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.utils.haplotype;
+
+import com.google.java.contract.Requires;
+import htsjdk.samtools.Cigar;
+import htsjdk.samtools.CigarElement;
+import htsjdk.samtools.CigarOperator;
+import org.apache.commons.lang.ArrayUtils;
+import org.broadinstitute.gatk.engine.contexts.ReferenceContext;
+import org.broadinstitute.gatk.utils.GenomeLoc;
+import org.broadinstitute.gatk.utils.exceptions.ReviewedGATKException;
+import org.broadinstitute.gatk.utils.sam.AlignmentUtils;
+import org.broadinstitute.gatk.utils.sam.ReadUtils;
+import htsjdk.variant.variantcontext.Allele;
+
+import java.util.Arrays;
+import java.util.Comparator;
+import java.util.LinkedHashMap;
+import java.util.List;
+
+public class Haplotype extends Allele {
+
+
+    private GenomeLoc genomeLocation = null;
+    private EventMap eventMap = null;
+    private Cigar cigar;
+    private int alignmentStartHapwrtRef;
+    private double score = Double.NaN;
+
+    /**
+     * Main constructor
+     *
+     * @param bases a non-null array of bases
+     * @param isRef is this the reference haplotype?
+     */
+    public Haplotype( final byte[] bases, final boolean isRef ) {
+        super(bases.clone(), isRef);
+    }
+
+    /**
+     * Create a new non-ref haplotype
+     *
+     * @param bases a non-null array of bases
+     */
+    public Haplotype( final byte[] bases ) {
+        this(bases, false);
+    }
+
+    /**
+     * Create a new haplotype with bases
+     *
+     * Requires bases.length == cigar.getReadLength()
+     *
+     * @param bases a non-null array of bases
+     * @param isRef is this the reference haplotype?
+     * @param alignmentStartHapwrtRef offset of this haplotype w.r.t. the reference
+     * @param cigar the cigar that maps this haplotype to the reference sequence
+     */
+    public Haplotype( final byte[] bases, final boolean isRef, final int alignmentStartHapwrtRef, final Cigar cigar) {
+        this(bases, isRef);
+        this.alignmentStartHapwrtRef = alignmentStartHapwrtRef;
+        setCigar(cigar);
+    }
+
+    /**
+     * Copy constructor.  Note the ref state of the provided allele is ignored!
+     *
+     * @param allele allele to copy
+     */
+    public Haplotype( final Allele allele ) {
+        super(allele, true);
+    }
+
+    public Haplotype( final byte[] bases, final GenomeLoc loc ) {
+        this(bases, false);
+        this.genomeLocation = loc;
+    }
+
+    /**
+     * Create a new Haplotype derived from this one that exactly spans the provided location
+     *
+     * Note that this haplotype must have a contain a genome loc for this operation to be successful.  If no
+     * GenomeLoc is contained than @throws an IllegalStateException
+     *
+     * Also loc must be fully contained within this Haplotype's genomeLoc.  If not an IllegalArgumentException is
+     * thrown.
+     *
+     * @param loc a location completely contained within this Haplotype's location
+     * @return a new Haplotype within only the bases spanning the provided location, or null for some reason the haplotype would be malformed if
+     */
+    public Haplotype trim(final GenomeLoc loc) {
+        if ( loc == null ) throw new IllegalArgumentException("Loc cannot be null");
+        if ( genomeLocation == null ) throw new IllegalStateException("Cannot trim a Haplotype without containing GenomeLoc");
+        if ( ! genomeLocation.containsP(loc) ) throw new IllegalArgumentException("Can only trim a Haplotype to a containing span.  My loc is " + genomeLocation + " but wanted trim to " + loc);
+        if ( getCigar() == null ) throw new IllegalArgumentException("Cannot trim haplotype without a cigar " + this);
+
+        final int newStart = loc.getStart() - this.genomeLocation.getStart();
+        final int newStop = newStart + loc.size() - 1;
+        final byte[] newBases = AlignmentUtils.getBasesCoveringRefInterval(newStart, newStop, getBases(), 0, getCigar());
+        final Cigar newCigar = AlignmentUtils.trimCigarByReference(getCigar(), newStart, newStop);
+
+        if ( newBases == null || AlignmentUtils.startsOrEndsWithInsertionOrDeletion(newCigar) )
+            // we cannot meaningfully chop down the haplotype, so return null
+            return null;
+
+        final Haplotype ret = new Haplotype(newBases, isReference());
+        ret.setCigar(newCigar);
+        ret.setGenomeLocation(loc);
+        ret.setAlignmentStartHapwrtRef(newStart + getAlignmentStartHapwrtRef());
+        return ret;
+    }
+
+    @Override
+    public boolean equals( Object h ) {
+        return h instanceof Haplotype && Arrays.equals(getBases(), ((Haplotype) h).getBases());
+    }
+
+    @Override
+    public int hashCode() {
+        return Arrays.hashCode(getBases());
+    }
+
+    public EventMap getEventMap() {
+        return eventMap;
+    }
+
+    public void setEventMap( final EventMap eventMap ) {
+        this.eventMap = eventMap;
+    }
+
+    @Override
+    public String toString() {
+        return getDisplayString();
+    }
+
+    /**
+     * Get the span of this haplotype (may be null)
+     * @return a potentially null genome loc
+     */
+    public GenomeLoc getGenomeLocation() {
+        return genomeLocation;
+    }
+
+    public void setGenomeLocation(GenomeLoc genomeLocation) {
+        this.genomeLocation = genomeLocation;
+    }
+
+    public long getStartPosition() {
+        return genomeLocation.getStart();
+    }
+
+    public long getStopPosition() {
+        return genomeLocation.getStop();
+    }
+
+    public int getAlignmentStartHapwrtRef() {
+        return alignmentStartHapwrtRef;
+    }
+
+    public void setAlignmentStartHapwrtRef( final int alignmentStartHapwrtRef ) {
+        this.alignmentStartHapwrtRef = alignmentStartHapwrtRef;
+    }
+
+    /**
+     * Get the cigar for this haplotype.  Note that the cigar is guaranteed to be consolidated
+     * in that multiple adjacent equal operates will have been merged
+     * @return the cigar of this haplotype
+     */
+    public Cigar getCigar() {
+        return cigar;
+    }
+
+    /**
+     * Get the haplotype cigar extended by padSize M at the tail, consolidated into a clean cigar
+     *
+     * @param padSize how many additional Ms should be appended to the end of this cigar.  Must be >= 0
+     * @return a newly allocated Cigar that consolidate(getCigar + padSize + M)
+     */
+    public Cigar getConsolidatedPaddedCigar(final int padSize) {
+        if ( padSize < 0 ) throw new IllegalArgumentException("padSize must be >= 0 but got " + padSize);
+        final Cigar extendedHaplotypeCigar = new Cigar(getCigar().getCigarElements());
+        if ( padSize > 0 ) extendedHaplotypeCigar.add(new CigarElement(padSize, CigarOperator.M));
+        return AlignmentUtils.consolidateCigar(extendedHaplotypeCigar);
+    }
+
+    /**
+     * Set the cigar of this haplotype to cigar.
+     *
+     * Note that this function consolidates the cigar, so that 1M1M1I1M1M => 2M1I2M
+     *
+     * @param cigar a cigar whose readLength == length()
+     */
+    public void setCigar( final Cigar cigar ) {
+        this.cigar = AlignmentUtils.consolidateCigar(cigar);
+        if ( this.cigar.getReadLength() != length() )
+            throw new IllegalArgumentException("Read length " + length() + " not equal to the read length of the cigar " + cigar.getReadLength() + " " + this.cigar);
+    }
+
+    @Requires({"refInsertLocation >= 0"})
+    public Haplotype insertAllele( final Allele refAllele, final Allele altAllele, final int refInsertLocation, final int genomicInsertLocation ) {
+        // refInsertLocation is in ref haplotype offset coordinates NOT genomic coordinates
+        final int haplotypeInsertLocation = ReadUtils.getReadCoordinateForReferenceCoordinate(alignmentStartHapwrtRef, cigar, refInsertLocation, ReadUtils.ClippingTail.RIGHT_TAIL, true);
+        final byte[] myBases = this.getBases();
+        if( haplotypeInsertLocation == -1 || haplotypeInsertLocation + refAllele.length() >= myBases.length ) { // desired change falls inside deletion so don't bother creating a new haplotype
+            return null;
+        }
+
+        byte[] newHaplotypeBases = new byte[]{};
+        newHaplotypeBases = ArrayUtils.addAll(newHaplotypeBases, ArrayUtils.subarray(myBases, 0, haplotypeInsertLocation)); // bases before the variant
+        newHaplotypeBases = ArrayUtils.addAll(newHaplotypeBases, altAllele.getBases()); // the alt allele of the variant
+        newHaplotypeBases = ArrayUtils.addAll(newHaplotypeBases, ArrayUtils.subarray(myBases, haplotypeInsertLocation + refAllele.length(), myBases.length)); // bases after the variant
+        return new Haplotype(newHaplotypeBases);
+    }
+
+    public static LinkedHashMap<Allele,Haplotype> makeHaplotypeListFromAlleles(final List<Allele> alleleList,
+                                                                               final int startPos,
+                                                                               final ReferenceContext ref,
+                                                                               final int haplotypeSize,
+                                                                               final int numPrefBases) {
+
+        LinkedHashMap<Allele,Haplotype> haplotypeMap = new LinkedHashMap<Allele,Haplotype>();
+
+        Allele refAllele = null;
+
+        for (Allele a:alleleList) {
+            if (a.isReference()) {
+                refAllele = a;
+                break;
+            }
+        }
+
+        if (refAllele == null)
+            throw new ReviewedGATKException("BUG: no ref alleles in input to makeHaplotypeListfrom Alleles at loc: "+ startPos);
+
+        final byte[] refBases = ref.getBases();
+
+        final int startIdxInReference = 1 + startPos - numPrefBases - ref.getWindow().getStart();
+        final String basesBeforeVariant = new String(Arrays.copyOfRange(refBases, startIdxInReference, startIdxInReference + numPrefBases));
+
+        // protect against long events that overrun available reference context
+        final int startAfter = Math.min(startIdxInReference + numPrefBases + refAllele.getBases().length - 1, refBases.length);
+        final String basesAfterVariant = new String(Arrays.copyOfRange(refBases, startAfter, refBases.length));
+
+        // Create location for all haplotypes
+        final int startLoc = ref.getWindow().getStart() + startIdxInReference;
+        final int stopLoc = startLoc + haplotypeSize-1;
+
+        final GenomeLoc locus = ref.getGenomeLocParser().createGenomeLoc(ref.getLocus().getContig(),startLoc,stopLoc);
+
+        for (final Allele a : alleleList) {
+
+            final byte[] alleleBases = a.getBases();
+            // use string concatenation
+            String haplotypeString = basesBeforeVariant + new String(Arrays.copyOfRange(alleleBases, 1, alleleBases.length)) + basesAfterVariant;
+            haplotypeString = haplotypeString.substring(0,haplotypeSize);
+
+            haplotypeMap.put(a,new Haplotype(haplotypeString.getBytes(), locus));
+        }
+
+        return haplotypeMap;
+    }
+
+    private static class Event {
+        public Allele ref;
+        public Allele alt;
+        public int pos;
+
+        public Event( final Allele ref, final Allele alt, final int pos ) {
+            this.ref = ref;
+            this.alt = alt;
+            this.pos = pos;
+        }
+    }
+
+    /**
+     * Get the score (an estimate of the support) of this haplotype
+     * @return a double, where higher values are better
+     */
+    public double getScore() {
+        return score;
+    }
+
+    /**
+     * Set the score (an estimate of the support) of this haplotype.
+     *
+     * Note that if this is the reference haplotype it is always given Double.MAX_VALUE score
+     *
+     * @param score a double, where higher values are better
+     */
+    public void setScore(double score) {
+        this.score = score;
+    }
+
+    /**
+     * Comparator used to sort haplotypes, alphanumerically.
+     *
+     * <p>
+     *     If one haplotype is the prefix of the other, the shorter one comes first.
+     * </p>
+     */
+    public static final Comparator<Haplotype> ALPHANUMERICAL_COMPARATOR = new Comparator<Haplotype>() {
+
+        @Override
+        public int compare(final Haplotype o1, final Haplotype o2) {
+            if (o1 == o2)
+                return 0;
+            final byte[] bases1 = o1.getBases();
+            final byte[] bases2 = o2.getBases();
+            final int iLimit = Math.min(bases1.length, bases2.length);
+            for (int i = 0; i < iLimit; i++) {
+                final int cmp = Byte.compare(bases1[i], bases2[i]);
+                if (cmp != 0) return cmp;
+            }
+            if (bases1.length == bases2.length) return 0;
+            return (bases1.length > bases2.length) ? -1 : 1; // is a bit better to get the longest haplotypes first.
+        }
+    };
+
+}
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/haplotype/HaplotypeBaseComparator.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/haplotype/HaplotypeBaseComparator.java
new file mode 100644
index 0000000..8d1dfff
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/haplotype/HaplotypeBaseComparator.java
@@ -0,0 +1,42 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.utils.haplotype;
+
+import java.util.Comparator;
+
+/**
+ * Compares two haplotypes in the lexicographic order of their bases
+ *
+ * User: depristo
+ * Date: 3/29/13
+ * Time: 11:09 AM
+ */
+public class HaplotypeBaseComparator implements Comparator<Haplotype> {
+    @Override
+    public int compare( final Haplotype hap1, final Haplotype hap2 ) {
+        return hap1.getBaseString().compareTo(hap2.getBaseString());
+    }
+}
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/haplotype/HaplotypeScoreComparator.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/haplotype/HaplotypeScoreComparator.java
new file mode 100644
index 0000000..7818d3e
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/haplotype/HaplotypeScoreComparator.java
@@ -0,0 +1,39 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.utils.haplotype;
+
+import java.util.Comparator;
+
+/**
+ * A comparator that sorts haplotypes in decreasing order of score, so that the best supported
+ * haplotypes are at the top
+ */
+public class HaplotypeScoreComparator implements Comparator<Haplotype> {
+    @Override
+    public int compare(Haplotype o1, Haplotype o2) {
+        return -1 * Double.valueOf(o1.getScore()).compareTo(o2.getScore());
+    }
+}
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/haplotype/HaplotypeSizeAndBaseComparator.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/haplotype/HaplotypeSizeAndBaseComparator.java
new file mode 100644
index 0000000..4818068
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/haplotype/HaplotypeSizeAndBaseComparator.java
@@ -0,0 +1,47 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.utils.haplotype;
+
+import java.util.Comparator;
+
+/**
+ * Compares two haplotypes first by their lengths and then by lexicographic order of their bases.
+ *
+ * User: btaylor
+ * Date: 8/1/13
+ * Time: 11:09 AM
+ */
+public class HaplotypeSizeAndBaseComparator implements Comparator<Haplotype> {
+    @Override
+    public int compare( final Haplotype hap1, final Haplotype hap2 ) {
+        if (hap1.getBases().length < hap2.getBases().length)
+            return -1;
+        else if (hap1.getBases().length > hap2.getBases().length)
+            return 1;
+        else
+            return hap1.getBaseString().compareTo(hap2.getBaseString());
+    }
+}
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/help/ApplicationDetails.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/help/ApplicationDetails.java
new file mode 100644
index 0000000..a0c7afb
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/help/ApplicationDetails.java
@@ -0,0 +1,95 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.utils.help;
+
+import org.broadinstitute.gatk.utils.commandline.CommandLineProgram;
+import org.broadinstitute.gatk.utils.classloader.JVMUtils;
+import org.broadinstitute.gatk.utils.exceptions.ReviewedGATKException;
+
+import java.io.IOException;
+import java.util.Collections;
+import java.util.List;
+
+/**
+ * Contains details additional details that the program can
+ * supply about itself.
+ *
+ * @author hanna
+ * @version 0.1
+ */
+
+public class ApplicationDetails {
+    /**
+     * Retrieve key information about the application (name, who to contact for support, etc.).
+     */
+    final List<String> applicationHeader;
+
+    /**
+     * Stores additional attribution for a given walker.
+     */
+    final List<String> attribution;
+
+    /**
+     * Extract details covering exactly how to run this executable.
+     */
+    final String runningInstructions;
+
+    /**
+     * Additional help particular to this command-line application.
+     */
+    final String additionalHelp;
+
+    public ApplicationDetails( List<String> applicationHeader, List<String> attribution, String runningInstructions, String additionalHelp ) {
+        this.applicationHeader = applicationHeader;
+        this.attribution = attribution;
+        this.runningInstructions = runningInstructions;
+        this.additionalHelp = additionalHelp;
+    }
+
+    public static List<String> createDefaultHeader(Class<? extends CommandLineProgram> application) {
+        return Collections.singletonList("Program Name: " + application.getName());
+    }
+
+    public static String createDefaultRunningInstructions(Class<? extends CommandLineProgram> application) {
+        // Default implementation to find a command line that makes sense.
+        // If the user is running from a jar, return '-jar <jarname>'; otherwise
+        // return the full class name.
+        String runningInstructions = null;
+        try {
+            runningInstructions = JVMUtils.getLocationFor( application ).getName();
+        }
+        catch( IOException ex ) {
+            throw new ReviewedGATKException("Unable to determine running instructions", ex);
+        }
+
+        if( runningInstructions.endsWith(".jar") )
+            runningInstructions = String.format("-jar %s", runningInstructions);
+        else
+            runningInstructions = application.getName();
+
+        return runningInstructions;
+    }
+}
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/help/DocletUtils.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/help/DocletUtils.java
new file mode 100644
index 0000000..324fcfc
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/help/DocletUtils.java
@@ -0,0 +1,76 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.utils.help;
+
+import com.sun.javadoc.FieldDoc;
+import com.sun.javadoc.PackageDoc;
+import com.sun.javadoc.ProgramElementDoc;
+import org.broadinstitute.gatk.utils.classloader.JVMUtils;
+
+import java.lang.reflect.Field;
+
+/**
+ * Methods in the class must ONLY be used by doclets, since the com.sun.javadoc.* classes are not
+ * available on all systems, and we don't want the GATK proper to depend on them.
+ */
+public class DocletUtils {
+
+    protected static boolean assignableToClass(ProgramElementDoc classDoc, Class lhsClass, boolean requireConcrete) {
+        try {
+            Class type = getClassForDoc(classDoc);
+            return lhsClass.isAssignableFrom(type) && (!requireConcrete || JVMUtils.isConcrete(type));
+        } catch (Throwable t) {
+            // Ignore errors.
+            return false;
+        }
+    }
+
+    protected static Class getClassForDoc(ProgramElementDoc doc) throws ClassNotFoundException {
+        return Class.forName(getClassName(doc));
+    }
+
+    protected static Field getFieldForFieldDoc(FieldDoc fieldDoc) {
+        try {
+            Class clazz = getClassForDoc(fieldDoc.containingClass());
+            return JVMUtils.findField(clazz, fieldDoc.name());
+        } catch (ClassNotFoundException e) {
+            throw new RuntimeException(e);
+        }
+    }
+
+    /**
+     * Reconstitute the class name from the given class JavaDoc object.
+     *
+     * @param doc the Javadoc model for the given class.
+     * @return The (string) class name of the given class.
+     */
+    protected static String getClassName(ProgramElementDoc doc) {
+        PackageDoc containingPackage = doc.containingPackage();
+        return containingPackage.name().length() > 0 ?
+                String.format("%s.%s", containingPackage.name(), doc.name()) :
+                String.format("%s", doc.name());
+    }
+}
\ No newline at end of file
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/help/DocumentedGATKFeature.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/help/DocumentedGATKFeature.java
new file mode 100644
index 0000000..eed95b4
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/help/DocumentedGATKFeature.java
@@ -0,0 +1,50 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.utils.help;
+
+import java.lang.annotation.*;
+
+/**
+ * An annotation to identify a class as a GATK capability for documentation
+ *
+ * @author depristo
+ */
+ at Documented
+ at Inherited
+ at Retention(RetentionPolicy.RUNTIME)
+ at Target(ElementType.TYPE)
+public @interface DocumentedGATKFeature {
+    /** Should we actually document this feature, even though it's annotated? */
+    public boolean enable() default true;
+    /** The overall group name (walkers, readfilters) this feature is associated with */
+    public String groupName();
+    /** A human readable summary of the purpose of this group of features */
+    public String summary() default "";
+    /** Are there links to other docs that we should include?  CommandLineGATK.class for walkers, for example? */
+    public Class[] extraDocs() default {};
+    /** Who is the go-to developer for operation/documentation issues? */
+    public String gotoDev() default "NA";
+}
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/help/DocumentedGATKFeatureHandler.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/help/DocumentedGATKFeatureHandler.java
new file mode 100644
index 0000000..e81ab21
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/help/DocumentedGATKFeatureHandler.java
@@ -0,0 +1,99 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.utils.help;
+
+import com.sun.javadoc.ClassDoc;
+import com.sun.javadoc.RootDoc;
+
+import java.io.*;
+import java.util.Set;
+
+/**
+ * Extend this class to provide a documentation handler for GATKdocs
+ */
+public abstract class DocumentedGATKFeatureHandler {
+    private GATKDoclet doclet;
+
+    /**
+     * @return the javadoc RootDoc of this javadoc run
+     */
+    protected RootDoc getRootDoc() {
+        return this.doclet.rootDoc;
+    }
+
+    /** Set the master doclet driving this handler */
+    public void setDoclet(GATKDoclet doclet) {
+        this.doclet = doclet;
+    }
+
+    /**
+     * @return the GATKDoclet driving this documentation run
+     */
+    public GATKDoclet getDoclet() {
+        return doclet;
+    }
+
+    /**
+     * Should return false iff this handler wants GATKDoclet to skip documenting
+     * this ClassDoc.
+     * @param doc that is being considered for inclusion in the docs
+     * @return true if the doclet should document ClassDoc doc
+     */
+    public boolean includeInDocs(ClassDoc doc) { return true; }
+
+    /**
+     * Return the flat filename (no paths) that the handler would like the Doclet to
+     * write out the documentation for ClassDoc doc and its associated Class clazz
+     * @param doc
+     * @param clazz
+     * @return
+     */
+    public String getDestinationFilename(ClassDoc doc, Class clazz) {
+        return GATKDocUtils.phpFilenameForClass(clazz);
+    }
+
+    /**
+     * Return the name of the FreeMarker template we will use to process ClassDoc doc.
+     *
+     * Note this is a flat filename relative to settings/helpTemplates in the GATK source tree
+     * @param doc
+     * @return
+     * @throws IOException
+     */
+    public abstract String getTemplateName(ClassDoc doc) throws IOException;
+
+    /**
+     * Actually generate the documentation map associated with toProcess
+     *
+     * Can use all to provide references and rootDoc for additional information, if necessary.
+     * Implementing methods should end with a call to setHandlerContext on toProcess, as in:
+     *
+     * toProcess.setHandlerContent(summary, rootMap);
+     *
+     * @param toProcess
+     */
+    public abstract void processOne(GATKDocWorkUnit toProcess);
+}
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/help/DocumentedGATKFeatureObject.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/help/DocumentedGATKFeatureObject.java
new file mode 100644
index 0000000..45f0c14
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/help/DocumentedGATKFeatureObject.java
@@ -0,0 +1,61 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.utils.help;
+
+/**
+ * Documentation unit.  Effectively a class version of the DocumentedGATKFeature.
+ * Immutable data structure.
+ *
+ * @author depristo
+ */
+class DocumentedGATKFeatureObject {
+    /** Which class are we documenting.  Specific to each class being documented */
+    private final Class classToDoc;
+    /** Are we enabled? */
+    private final boolean enable;
+    private final String groupName, summary, gotoDev;
+    private final Class[] extraDocs;
+
+    public DocumentedGATKFeatureObject(Class classToDoc, final boolean enable, final String groupName, final String summary, final Class[] extraDocs, final String gotoDev) {
+        this.classToDoc = classToDoc;
+        this.enable = enable;
+        this.groupName = groupName;
+        this.summary = summary;
+        this.extraDocs = extraDocs;
+        this.gotoDev = gotoDev;
+    }
+
+    public DocumentedGATKFeatureObject(Class classToDoc, final String groupName, final String summary, final String gotoDev) {
+        this(classToDoc, true, groupName, summary, new Class[]{}, gotoDev);
+    }
+
+    public Class getClassToDoc() { return classToDoc; }
+    public boolean enable() { return enable; }
+    public String groupName() { return groupName; }
+    public String summary() { return summary; }
+    public Class[] extraDocs() { return extraDocs; }
+    public String gotoDev() { return gotoDev; }
+}
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/help/ForumAPIUtils.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/help/ForumAPIUtils.java
new file mode 100644
index 0000000..fbf6528
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/help/ForumAPIUtils.java
@@ -0,0 +1,173 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.utils.help;
+
+import com.google.gson.Gson;
+import org.apache.commons.io.IOUtils;
+import org.apache.http.HttpResponse;
+import org.apache.http.client.ClientProtocolException;
+import org.apache.http.client.methods.HttpGet;
+import org.apache.http.client.methods.HttpPost;
+import org.apache.http.entity.StringEntity;
+import org.apache.http.impl.client.DefaultHttpClient;
+
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.net.MalformedURLException;
+import java.util.ArrayList;
+import java.util.List;
+
+public class ForumAPIUtils {
+    /**
+     * How we post to the forum
+     */
+    final private static String ACCESS_TOKEN = "access_token=";
+
+    public static List<String> getPostedTools(String forumKey) {
+        Gson gson = new Gson();
+        List<String> output = new ArrayList<String>();
+
+        String text = httpGet(HelpConstants.GATK_FORUM_API_URL + "categories.json?CategoryIdentifier=tool-bulletin&page=1-100000&" + ACCESS_TOKEN + forumKey);
+
+        APIQuery details = gson.fromJson(text, APIQuery.class);
+        ForumDiscussion[] discussions = details.Discussions;
+
+        for (ForumDiscussion post : discussions) {
+            output.add(post.Name);
+        }
+
+        /*
+        System.out.println(details.isJsonArray());
+        System.out.println(details.isJsonNull());
+        System.out.println(details.isJsonObject());
+        System.out.println(details.isJsonPrimitive());
+
+        JsonArray posted = details.getAsJsonPrimitive().get("Discussions").getAsJsonArray();
+
+        for ( JsonElement post : posted ) {
+            output.add( post.getAsJsonObject().get("Name").getAsString());
+        }
+        */
+        return output;
+    }
+
+
+    private static String httpGet(String urlStr) {
+        String output = "";
+
+        try {
+
+            DefaultHttpClient httpClient = new DefaultHttpClient();
+            HttpGet getRequest = new HttpGet(urlStr);
+            getRequest.addHeader("accept", "application/json");
+
+            HttpResponse response = httpClient.execute(getRequest);
+
+            if (response.getStatusLine().getStatusCode() != 200) {
+                throw new RuntimeException("Failed : HTTP error code : "
+                        + response.getStatusLine().getStatusCode());
+            }
+
+            output = IOUtils.toString(response.getEntity().getContent());
+
+            httpClient.getConnectionManager().shutdown();
+
+        } catch (ClientProtocolException e) {
+
+            e.printStackTrace();
+
+        } catch (IOException e) {
+
+            e.printStackTrace();
+        }
+        return output;
+    }
+
+    private static String httpPost(String data, String URL) {
+        try {
+
+            DefaultHttpClient httpClient = new DefaultHttpClient();
+            HttpPost postRequest = new HttpPost(URL);
+
+            StringEntity input = new StringEntity(data);
+            input.setContentType("application/json");
+            postRequest.setEntity(input);
+
+            HttpResponse response = httpClient.execute(postRequest);
+
+            if (response.getStatusLine().getStatusCode() != 200) {
+                throw new RuntimeException("Failed : HTTP error code : "
+                        + response.getStatusLine().getStatusCode());
+            }
+
+            BufferedReader br = new BufferedReader(
+                    new InputStreamReader((response.getEntity().getContent())));
+
+            String output = "";
+            String line;
+            System.out.println("Output from Server .... \n");
+            while ((line = br.readLine()) != null) {
+                output += (line + '\n');
+                System.out.println(line);
+            }
+
+            br.close();
+            httpClient.getConnectionManager().shutdown();
+            return output;
+
+        } catch (MalformedURLException e) {
+
+            e.printStackTrace();
+
+        } catch (IOException e) {
+
+            e.printStackTrace();
+
+        }
+        return null;
+    }
+
+    public static void postToForum(GATKDocWorkUnit tool, final String forumKey) {
+
+
+        ForumDiscussion post = new ForumDiscussion(tool);
+
+        Gson gson = new Gson();
+
+        String data = gson.toJson(post.getPostData());
+        httpPost(data, HelpConstants.GATK_FORUM_API_URL + "post/discussion.json?" + ACCESS_TOKEN + forumKey);
+
+
+    }
+
+    class APIQuery {
+        ForumDiscussion[] Discussions;
+
+        public APIQuery() {}
+    }
+
+}
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/help/ForumDiscussion.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/help/ForumDiscussion.java
new file mode 100644
index 0000000..7b95b50
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/help/ForumDiscussion.java
@@ -0,0 +1,84 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.utils.help;
+
+import java.util.HashMap;
+import java.util.Map;
+
+class ForumDiscussion {
+
+    final private static String POST_TEMPLATE = "<p>A new tool has been released!</p><p>Check out the documentation at <a href='%s'>%s</a>.</p>";
+
+    final int Announce;
+    final String Body;
+    final String Category;
+    final int Closed;
+    final String Format;
+    final String Name;
+    final int Sink;
+    final String Tags;
+    final String Type;
+
+    public ForumDiscussion(String name, String body, String format, String category,
+                           String tagsCSV, String type, int closed, int announce, int sink) {
+        this.Name = name;
+        this.Body = body;
+        this.Format = format;
+        this.Category = category;
+        this.Tags = tagsCSV;
+        this.Type = type;
+        this.Closed = closed;
+        this.Announce = announce;
+        this.Sink = sink;
+    }
+
+    public ForumDiscussion(GATKDocWorkUnit tool) {
+        this(tool.name,
+                String.format(POST_TEMPLATE, GATKDocUtils.URL_ROOT_FOR_RELEASE_GATKDOCS + tool.filename, tool.name),
+                "Html", "tool-bulletin", tool.name + "," + tool.group + ",gatkdocs", "Discussion", 0, -1, -1);
+    }
+
+    public Map<String, String> getPostData() {
+        Map<String, String> output = new HashMap<String, String>();
+
+        output.put("Name", Name);
+        output.put("Body", Body);
+        output.put("Format", Format);
+        output.put("Category", Category);
+        if (Tags != null)
+            output.put("Tags", Tags);
+        if (Type != null)
+            output.put("Type", Type);
+        if (Closed != -1)
+            output.put("Closed", Closed == 1 ? "1" : "0");
+        if (Announce != -1)
+            output.put("Announce", Announce == 1 ? "1" : "0");
+        if (Sink != -1)
+            output.put("Sink", Sink == 1 ? "1" : "0");
+
+        return output;
+    }
+}
\ No newline at end of file
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/help/GATKDocUtils.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/help/GATKDocUtils.java
new file mode 100644
index 0000000..72aba4d
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/help/GATKDocUtils.java
@@ -0,0 +1,71 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.utils.help;
+
+public class GATKDocUtils {
+    /**
+     * The URL root for RELEASED GATKDOC units
+     */
+    public final static String URL_ROOT_FOR_RELEASE_GATKDOCS = HelpConstants.GATK_DOCS_URL;
+    /**
+     * The URL root for STABLE GATKDOC units             //TODO: do sthing with this or remove -- URL goes nowhere
+     */
+    public final static String URL_ROOT_FOR_STABLE_GATKDOCS = "http://iwww.broadinstitute.org/gsa/gatkdocs/stable/";
+    /**
+     * The URL root for UNSTABLE GATKDOC units           //TODO: do sthing with this or remove -- URL goes nowhere
+     */
+    public final static String URL_ROOT_FOR_UNSTABLE_GATKDOCS = "http://iwww.broadinstitute.org/gsa/gatkdocs/unstable/";
+
+    /**
+     * Return the filename of the GATKDoc PHP that would be generated for Class.  This
+     * does not guarantee that the docs exist, or that docs would actually be generated
+     * for class (might not be annotated for documentation, for example).  But if
+     * this class is documented, GATKDocs will write the docs to a file named as returned
+     * by this function.
+     *
+     * @param c
+     * @return
+     */
+    public static String phpFilenameForClass(Class c) {
+        return c.getName().replace(".", "_") + ".php";
+    }
+
+    /**
+     * Returns a full URL http://etc/ linking to the documentation for class (assuming it
+     * exists).  Currently points to the RELEASE doc path only.     //TODO: do sthing with other paths or remove ?
+     *
+     * @param c
+     * @return
+     */
+    public static String helpLinksToGATKDocs(Class c) {
+        String classPath = phpFilenameForClass(c);
+        StringBuilder b = new StringBuilder();
+        b.append(URL_ROOT_FOR_RELEASE_GATKDOCS).append(classPath);
+        //b.append("stable   version: ").append(URL_ROOT_FOR_STABLE_GATKDOCS).append(classPath).append("\n");
+        //b.append("unstable version: ").append(URL_ROOT_FOR_UNSTABLE_GATKDOCS).append(classPath).append("\n");
+        return b.toString();
+    }
+}
\ No newline at end of file
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/help/GATKDocWorkUnit.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/help/GATKDocWorkUnit.java
new file mode 100644
index 0000000..005d900
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/help/GATKDocWorkUnit.java
@@ -0,0 +1,127 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.utils.help;
+
+import com.sun.javadoc.ClassDoc;
+
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * Simple collection of all relevant information about something the GATKDoclet can document
+ * <p/>
+ * Created by IntelliJ IDEA.
+ * User: depristo
+ * Date: 7/24/11
+ * Time: 7:59 PM
+ */
+class GATKDocWorkUnit implements Comparable<GATKDocWorkUnit> {
+    /**
+     * The class that's being documented
+     */
+    final Class clazz;
+    /**
+     * The name of the thing we are documenting
+     */
+    final String name;
+    /**
+     * the filename where we will be writing the docs for this class
+     */
+    final String filename;
+    /**
+     * The name of the documentation group (e.g., walkers, read filters) class belongs to
+     */
+    final String group;
+    /**
+     * The documentation handler for this class
+     */
+    final DocumentedGATKFeatureHandler handler;
+    /**
+     * The javadoc documentation for clazz
+     */
+    final ClassDoc classDoc;
+    /**
+     * The annotation that lead to this Class being in GATKDoc
+     */
+    final DocumentedGATKFeatureObject annotation;
+    /**
+     * When was this walker built, and what's the absolute version number
+     */
+    final String buildTimestamp, absoluteVersion;
+
+    // set by the handler
+    String summary;
+    Map<String, Object> forTemplate; // this is where the actual doc content gets stored
+
+    public GATKDocWorkUnit(String name, String filename, String group, DocumentedGATKFeatureObject annotation,
+                           DocumentedGATKFeatureHandler handler, ClassDoc classDoc, Class clazz,
+                           String buildTimestamp, String absoluteVersion) {
+        this.annotation = annotation;
+        this.name = name;
+        this.filename = filename;
+        this.group = group;
+        this.handler = handler;
+        this.classDoc = classDoc;
+        this.clazz = clazz;
+        this.buildTimestamp = buildTimestamp;
+        this.absoluteVersion = absoluteVersion;
+    }
+
+    /**
+     * Called by the GATKDoclet to set handler provided context for this work unit
+     *
+     * @param summary
+     * @param forTemplate
+     */
+    public void setHandlerContent(String summary, Map<String, Object> forTemplate) {
+        this.summary = summary;
+        this.forTemplate = forTemplate;
+    }
+
+    /**
+     * Return a String -> String map suitable for FreeMarker to create an index to this WorkUnit
+     *
+     * @return
+     */
+    public Map<String, String> indexDataMap() {
+        Map<String, String> data = new HashMap<String, String>();
+        data.put("name", name);
+        data.put("summary", summary);
+        data.put("filename", filename);
+        data.put("group", group);
+        return data;
+    }
+
+    /**
+     * Sort in order of the name of this WorkUnit
+     *
+     * @param other
+     * @return
+     */
+    public int compareTo(GATKDocWorkUnit other) {
+        return this.name.compareTo(other.name);
+    }
+}
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/help/GATKDoclet.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/help/GATKDoclet.java
new file mode 100644
index 0000000..bd03add
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/help/GATKDoclet.java
@@ -0,0 +1,576 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.utils.help;
+
+import com.google.gson.ExclusionStrategy;
+import com.google.gson.FieldAttributes;
+import com.google.gson.Gson;
+import com.google.gson.GsonBuilder;
+import com.google.gson.annotations.Expose;
+import com.google.gson.stream.JsonWriter;
+import com.sun.javadoc.ClassDoc;
+import com.sun.javadoc.RootDoc;
+import freemarker.template.Configuration;
+import freemarker.template.DefaultObjectWrapper;
+import freemarker.template.Template;
+import freemarker.template.TemplateException;
+import org.apache.commons.io.FileUtils;
+import org.apache.log4j.Level;
+import org.apache.log4j.Logger;
+import htsjdk.tribble.FeatureCodec;
+import org.broadinstitute.gatk.engine.CommandLineGATK;
+import org.broadinstitute.gatk.tools.walkers.qc.DocumentationTest;
+import org.broadinstitute.gatk.utils.exceptions.ReviewedGATKException;
+import org.broadinstitute.gatk.utils.exceptions.UserException;
+import org.broadinstitute.gatk.utils.text.XReadLines;
+
+import java.io.*;
+import java.util.*;
+
+/**
+ * Javadoc Doclet that combines javadoc, GATK ParsingEngine annotations, and FreeMarker
+ * templates to produce PHP formatted GATKDocs for walkers
+ * and other classes.
+ * <p/>
+ * This document has the following workflow:
+ * <p/>
+ * 1 -- walk the javadoc hierarchy, looking for class that have the
+ * DocumentedGATKFeature annotation or are in the type hierarchy in the
+ * static list of things to document, and are to be documented
+ * 2 -- construct for each a GATKDocWorkUnit, resulting in the complete
+ * set of things to document
+ * 3 -- for each unit, actually generate a PHP page documenting it
+ * as well as links to related features via their units.  Writing
+ * of a specific class PHP is accomplished by a generate DocumentationHandler
+ * 4 -- write out an index of all units, organized by group
+ * 5 -- emit JSON version of GATKDocs using Google GSON (currently incomplete but workable)
+ * <p/>
+ * The documented classes are restricted to only those with @DocumentedGATKFeature
+ * annotation or are in the STATIC_DOCS class.
+ */
+public class GATKDoclet {
+    final protected static Logger logger = Logger.getLogger(GATKDoclet.class);
+
+    /**
+     * Where we find the help FreeMarker templates
+     */
+    final protected static File SETTINGS_DIR = new File("settings/helpTemplates");
+
+    /**
+     * Where we write the GATKDoc PHP directory
+     */
+    final protected static File DESTINATION_DIR = new File("gatkdocs");
+
+    final private static String FORUM_KEY_PATH = "/local/gsa-engineering/gatkdocs_publisher/forum.key";
+    // ----------------------------------------------------------------------
+    //
+    // Global variables that are set on the command line by javadoc
+    //
+    // ----------------------------------------------------------------------
+    protected static File settingsDir = SETTINGS_DIR;
+    protected static File destinationDir = DESTINATION_DIR;
+    protected static String forumKeyPath = FORUM_KEY_PATH;
+    protected static String buildTimestamp = null, absoluteVersion = null;
+    protected static boolean showHiddenFeatures = false;
+
+    protected static boolean testOnly = false;
+
+    /**
+     * Any class that's in this list will be included in the documentation
+     * when the -test argument is provided.  Useful for debugging.
+     */
+    private static final List<Class<?>> testOnlyKeepers = Arrays.asList(
+            DocumentationTest.class, CommandLineGATK.class, UserException.class);
+
+    /**
+     * The javadoc root doc
+     */
+    RootDoc rootDoc;
+
+    /**
+     * The set of all things we are going to document
+     */
+    Set<GATKDocWorkUnit> myWorkUnits;
+
+    /**
+     * A static list of DocumentedGATKFeatureObjects.  Any class that is as or extends
+     * one of the DocumentedGATKFeatureObjects.clazz of this collection will also
+     * be documented, even if it doesn't have the @DocumentedGATKFeature annotation.  Useful
+     * when you want to document things that implement an interface (annotations on java
+     * interfaces aren't inherited) or whose base class isn't under your control (tribble
+     * codecs).
+     */
+    final static Collection<DocumentedGATKFeatureObject> STATIC_DOCS = new ArrayList<DocumentedGATKFeatureObject>();
+
+    static {
+        STATIC_DOCS.add(new DocumentedGATKFeatureObject(FeatureCodec.class,
+                HelpConstants.DOCS_CAT_RODCODECS,
+                "Tribble codecs for reading reference ordered data (ROD) files such as VCF or BED",
+                "NA"));
+    }
+
+    /**
+     * Extracts the contents of certain types of javadoc and adds them to an XML file.
+     *
+     * @param rootDoc The documentation root.
+     * @return Whether the JavaDoc run succeeded.
+     * @throws java.io.IOException if output can't be written.
+     */
+    public static boolean start(RootDoc rootDoc) throws IOException {
+        logger.setLevel(Level.INFO);
+
+        // load arguments
+        for (String[] options : rootDoc.options()) {
+            if (options[0].equals("-settings-dir"))
+                settingsDir = new File(options[1]);
+            if (options[0].equals("-destination-dir"))
+                destinationDir = new File(options[1]);
+            if (options[0].equals("-forum-key-path"))
+                forumKeyPath = options[1];
+            if (options[0].equals("-build-timestamp"))
+                buildTimestamp = options[1];
+            if (options[0].equals("-absolute-version"))
+                absoluteVersion = options[1];
+            if (options[0].equals("-include-hidden"))
+                showHiddenFeatures = true;
+            if (options[0].equals("-test"))
+                testOnly = true;
+        }
+
+        if (!settingsDir.exists())
+            throw new RuntimeException("-settings-dir " + settingsDir.getPath() + " does not exist");
+        else if (!settingsDir.isDirectory())
+            throw new RuntimeException("-settings-dir " + settingsDir.getPath() + " is not a directory");
+
+        // process the docs
+        new GATKDoclet().processDocs(rootDoc);
+
+        return true;
+    }
+
+    /**
+     * Validate the given options against options supported by this doclet.
+     *
+     * @param option Option to validate.
+     * @return Number of potential parameters; 0 if not supported.
+     */
+    public static int optionLength(String option) {
+        if (option.equals("-settings-dir") ||
+                option.equals("-destination-dir") ||
+                option.equals("-forum-key-path") ||
+                option.equals("-build-timestamp") ||
+                option.equals("-absolute-version") ||
+                option.equals("-include-hidden")) {
+            return 2;
+        } else if (option.equals("-test"))
+            return 1;
+        else
+            return 0;
+    }
+
+    /**
+     * Are we supposed to include @Hidden annotations in our documented output?
+     *
+     * @return
+     */
+    public boolean showHiddenFeatures() {
+        return showHiddenFeatures;
+    }
+
+    /**
+     * @param rootDoc
+     */
+    private void processDocs(RootDoc rootDoc) {
+        // setup the global access to the root
+        this.rootDoc = rootDoc;
+
+        try {
+            // print the Version number
+            FileUtils.writeByteArrayToFile(new File(destinationDir + "/current.version.txt"), getSimpleVersion(absoluteVersion).getBytes());
+
+            /* ------------------------------------------------------------------- */
+            /* You should do this ONLY ONCE in the whole application life-cycle:   */
+
+            Configuration cfg = new Configuration();
+            // Specify the data source where the template files come from.
+            cfg.setDirectoryForTemplateLoading(settingsDir);
+            // Specify how templates will see the data-model. This is an advanced topic...
+            cfg.setObjectWrapper(new DefaultObjectWrapper());
+
+            myWorkUnits = computeWorkUnits();
+
+            List<Map<String, String>> groups = new ArrayList<Map<String, String>>();
+            Set<String> seenDocumentationFeatures = new HashSet<String>();
+            List<Map<String, String>> data = new ArrayList<Map<String, String>>();
+            for (GATKDocWorkUnit workUnit : myWorkUnits) {
+                data.add(workUnit.indexDataMap());
+                if (!seenDocumentationFeatures.contains(workUnit.annotation.groupName())) {
+                    groups.add(toMap(workUnit.annotation));
+                    seenDocumentationFeatures.add(workUnit.annotation.groupName());
+                }
+            }
+
+            for (GATKDocWorkUnit workUnit : myWorkUnits) {
+                processDocWorkUnit(cfg, workUnit, groups, data);
+            }
+
+            processIndex(cfg, new ArrayList<GATKDocWorkUnit>(myWorkUnits));
+
+            File forumKeyFile = new File(forumKeyPath);
+            if (forumKeyFile.exists()) {
+                String forumKey = null;
+                // Read in a one-line file so we can do a for loop
+                for (String line : new XReadLines(forumKeyFile))
+                    forumKey = line;
+                updateForum(myWorkUnits, forumKey);
+            }
+        } catch (FileNotFoundException e) {
+            throw new RuntimeException(e);
+        } catch (IOException e) {
+            throw new RuntimeException(e);
+        }
+    }
+
+    private void updateForum(Set<GATKDocWorkUnit> docWorkUnits, String forumKey) {
+        //first get list of posts that need to be added
+        List<String> old = ForumAPIUtils.getPostedTools(forumKey);
+
+        for (String s : old)
+            System.out.println(s);
+
+        System.out.printf("Forum has %d items%n", old.size());
+        System.out.printf("Docs have %d items%n", docWorkUnits.size());
+
+        List<GATKDocWorkUnit> toAdd = new ArrayList<GATKDocWorkUnit>();
+        for (GATKDocWorkUnit tool : docWorkUnits) {
+            if (!old.contains(tool.name)) {
+                System.out.println("WILL POST: " + tool.name + " TO FORUM");
+                toAdd.add(tool);
+            }
+        }
+
+        //update using list
+        for (GATKDocWorkUnit tool : toAdd) {
+            //if ( tool.name.equals("ApplyRecalibration") )
+            ForumAPIUtils.postToForum(tool, forumKey);
+        }
+    }
+
+    /**
+     * Returns the set of all GATKDocWorkUnits that we are going to generate docs for.
+     *
+     * @return
+     */
+    private Set<GATKDocWorkUnit> computeWorkUnits() {
+        TreeSet<GATKDocWorkUnit> m = new TreeSet<GATKDocWorkUnit>();
+
+        for (ClassDoc doc : rootDoc.classes()) {
+            //logger.debug("Considering " + doc);
+            Class clazz = getClassForClassDoc(doc);
+
+            // don't add anything that's not DocumentationTest if we are in test mode
+            if (clazz != null && testOnly && !testOnlyKeepers.contains(clazz))
+                continue;
+
+            //if ( clazz != null && clazz.getName().equals("org.broadinstitute.gatk.tools.walkers.annotator.AlleleBalance"))
+            //    logger.debug("foo");
+
+            DocumentedGATKFeatureObject feature = getFeatureForClassDoc(doc);
+            DocumentedGATKFeatureHandler handler = createHandler(doc, feature);
+            if (handler != null && handler.includeInDocs(doc)) {
+                //logger.info("Generating documentation for class " + doc);
+                String filename = handler.getDestinationFilename(doc, clazz);
+                GATKDocWorkUnit unit = new GATKDocWorkUnit(doc.name(),
+                        filename, feature.groupName(), feature, handler, doc, clazz,
+                        buildTimestamp, absoluteVersion);
+                m.add(unit);
+            }
+        }
+
+        return m;
+    }
+
+    /**
+     * Create a handler capable of documenting the class doc according to feature.  Returns
+     * null if no appropriate handler is found or doc shouldn't be documented at all.
+     *
+     * @param doc
+     * @param feature
+     * @return
+     */
+    private DocumentedGATKFeatureHandler createHandler(ClassDoc doc, DocumentedGATKFeatureObject feature) {
+        if (feature != null) {
+            if (feature.enable()) {
+                DocumentedGATKFeatureHandler handler = new GenericDocumentationHandler();
+                handler.setDoclet(this);
+                return handler;
+            } else {
+                logger.info("Skipping disabled Documentation for " + doc);
+            }
+        }
+
+        return null;
+    }
+
+    /**
+     * Returns the instantiated DocumentedGATKFeatureObject that describes the GATKDoc
+     * structure we will apply to Doc.
+     *
+     * @param doc
+     * @return null if this proves inappropriate or doc shouldn't be documented
+     */
+    private DocumentedGATKFeatureObject getFeatureForClassDoc(ClassDoc doc) {
+        Class<? extends Object> docClass = getClassForClassDoc(doc);
+
+        if (docClass == null)
+            return null; // not annotated so it shouldn't be documented
+
+        if (docClass.isAnnotationPresent(DocumentedGATKFeature.class)) {
+            DocumentedGATKFeature f = docClass.getAnnotation(DocumentedGATKFeature.class);
+            return new DocumentedGATKFeatureObject(docClass, f.enable(), f.groupName(), f.summary(), f.extraDocs(), f.gotoDev());
+        } else {
+            for (DocumentedGATKFeatureObject staticDocs : STATIC_DOCS) {
+                if (staticDocs.getClassToDoc().isAssignableFrom(docClass)) {
+                    return new DocumentedGATKFeatureObject(docClass, staticDocs.enable(), staticDocs.groupName(), staticDocs.summary(), staticDocs.extraDocs(), staticDocs.gotoDev());
+                }
+            }
+            return null;
+        }
+    }
+
+    /**
+     * Return the Java class described by the ClassDoc doc
+     *
+     * @param doc
+     * @return
+     */
+    private Class<? extends Object> getClassForClassDoc(ClassDoc doc) {
+        try {
+            // todo -- what do I need the ? extends Object to pass the compiler?
+            return (Class<? extends Object>) DocletUtils.getClassForDoc(doc);
+        } catch (ClassNotFoundException e) {
+            //logger.warn("Couldn't find class for ClassDoc " + doc);
+            // we got a classdoc for a class we can't find.  Maybe in a library or something
+            return null;
+        } catch (NoClassDefFoundError e) {
+            return null;
+        } catch (UnsatisfiedLinkError e) {
+            return null; // naughty BWA bindings
+        }
+    }
+
+    /**
+     * Create the php index listing all of the GATKDocs features
+     *
+     * @param cfg
+     * @param indexData
+     * @throws IOException
+     */
+    private void processIndex(Configuration cfg, List<GATKDocWorkUnit> indexData) throws IOException {
+        /* Get or create a template */
+        Template temp = cfg.getTemplate("generic.index.template.html");
+
+        /* Merge data-model with template */
+        Writer out = new OutputStreamWriter(new FileOutputStream(new File(destinationDir + "/index.php")));
+        try {
+            temp.process(groupIndexData(indexData), out);
+            out.flush();
+        } catch (TemplateException e) {
+            throw new ReviewedGATKException("Failed to create GATK documentation", e);
+        }
+    }
+
+    /**
+     * Helpful function to create the php index.  Given all of the already run GATKDocWorkUnits,
+     * create the high-level grouping data listing individual features by group.
+     *
+     * @param indexData
+     * @return
+     */
+    private Map<String, Object> groupIndexData(List<GATKDocWorkUnit> indexData) {
+        //
+        // root -> data -> { summary -> y, filename -> z }, etc
+        //      -> groups -> group1, group2, etc.
+        Map<String, Object> root = new HashMap<String, Object>();
+
+
+        Collections.sort(indexData);
+
+        List<Map<String, String>> groups = new ArrayList<Map<String, String>>();
+        Set<String> seenDocumentationFeatures = new HashSet<String>();
+        List<Map<String, String>> data = new ArrayList<Map<String, String>>();
+        for (GATKDocWorkUnit workUnit : indexData) {
+            data.add(workUnit.indexDataMap());
+            if (!seenDocumentationFeatures.contains(workUnit.annotation.groupName())) {
+                groups.add(toMap(workUnit.annotation));
+                seenDocumentationFeatures.add(workUnit.annotation.groupName());
+            }
+        }
+
+        //System.out.printf(groups.toString());
+
+        root.put("data", data);
+        root.put("groups", groups);
+        root.put("timestamp", buildTimestamp);
+        root.put("version", absoluteVersion);
+
+        return root;
+    }
+
+    /**
+     * Trivial helper routine that returns the map of name and summary given the annotation
+     * AND adds a super-category so that we can custom-order the categories in the index
+     *
+     * @param annotation
+     * @return
+     */
+    private static final Map<String, String> toMap(DocumentedGATKFeatureObject annotation) {
+        Map<String, String> root = new HashMap<String, String>();
+        root.put("id", annotation.groupName().replaceAll("\\W", ""));
+        root.put("name", annotation.groupName());
+        root.put("summary", annotation.summary());
+
+        /**
+         * Add-on super-category definitions. The assignments depend on parsing the names
+         * defined in HelpConstants.java so be careful of changing anything.
+         * Also, the super-category value strings need to be the same as used in the
+         * Freemarker template. This is all fairly clunky but the best I could do without
+         * making major changes to the DocumentedGATKFeatureObject. Doesn't help that
+         * Freemarker makes any scripting horribly awkward.
+         */
+        final String supercatValue;
+        if (annotation.groupName().endsWith(" Tools")) supercatValue = "tools";
+        else if (annotation.groupName().endsWith(" Utilities")) supercatValue = "utilities";
+        else if (annotation.groupName().startsWith("Engine ")) supercatValue = "engine";
+        else if (annotation.groupName().endsWith(" (DevZone)")) supercatValue = "dev";
+        else supercatValue = "other";
+
+        root.put("supercat", supercatValue);
+
+        return root;
+    }
+
+    /**
+     * Helper function that finding the GATKDocWorkUnit associated with class from among all of the work units
+     *
+     * @param c the class we are looking for
+     * @return the GATKDocWorkUnit whose .clazz.equals(c), or null if none could be found
+     */
+    public final GATKDocWorkUnit findWorkUnitForClass(Class c) {
+        for (final GATKDocWorkUnit unit : this.myWorkUnits)
+            if (unit.clazz.equals(c))
+                return unit;
+        return null;
+    }
+
+    /**
+     * Return the ClassDoc associated with clazz
+     *
+     * @param clazz
+     * @return
+     */
+    public ClassDoc getClassDocForClass(Class clazz) {
+        return rootDoc.classNamed(clazz.getName());
+    }
+
+    /**
+     * High-level function that processes a single DocWorkUnit unit using its handler
+     *
+     * @param cfg
+     * @param unit
+     * @param data
+     * @throws IOException
+     */
+    private void processDocWorkUnit(Configuration cfg, GATKDocWorkUnit unit, List<Map<String, String>> groups, List<Map<String, String>> data)
+            throws IOException {
+        //System.out.printf("Processing documentation for class %s%n", unit.classDoc);
+        unit.handler.processOne(unit);
+        unit.forTemplate.put("groups", groups);
+        unit.forTemplate.put("data", data);
+        // Get or create a template
+        Template temp = cfg.getTemplate(unit.handler.getTemplateName(unit.classDoc));
+
+        // Merge data-model with template
+        File outputPath = new File(destinationDir + "/" + unit.filename);
+        try {
+            Writer out = new OutputStreamWriter(new FileOutputStream(outputPath));
+            temp.process(unit.forTemplate, out);
+            out.flush();
+        } catch (TemplateException e) {
+            throw new ReviewedGATKException("Failed to create GATK documentation", e);
+        }
+
+        // Create GSON-friendly object from unit.forTemplate
+        GSONWorkUnit gsonworkunit = new GSONWorkUnit();
+        gsonworkunit.populate(  unit.forTemplate.get("summary").toString(),
+                                unit.forTemplate.get("parallel"),
+                                unit.forTemplate.get("activeregion"),
+                                unit.forTemplate.get("partitiontype").toString(),
+                                unit.forTemplate.get("walkertype").toString(),
+                                unit.forTemplate.get("gson-arguments"),
+                                unit.forTemplate.get("refwindow"),
+                                unit.forTemplate.get("description").toString(),
+                                unit.forTemplate.get("name").toString(),
+                                unit.forTemplate.get("annotinfo").toString(),
+                                unit.forTemplate.get("readfilters"),
+                                unit.forTemplate.get("downsampling"),
+                                unit.forTemplate.get("group").toString(),
+                                unit.forTemplate.get("annotfield").toString(),
+                                unit.forTemplate.get("annotdescript")
+        );
+
+        // Prepare to write JSON entry to file
+        File outputPathForJSON = new File(destinationDir + "/" + unit.filename + ".json");
+
+        try {
+            BufferedWriter outJSON = new BufferedWriter(new FileWriter(outputPathForJSON));
+            // Convert object to JSON
+            Gson gson = new GsonBuilder()
+                .serializeSpecialFloatingPointValues()
+                .setPrettyPrinting()
+                .create();
+            String json = gson.toJson(gsonworkunit); // was run on unit.forTemplate
+            outJSON.write(json);
+            outJSON.close();
+
+        } catch (Exception e) {
+            throw new ReviewedGATKException("Failed to create JSON entry", e);
+        }
+    }
+
+    private static String getSimpleVersion(String absoluteVersion) {
+        String[] parts = absoluteVersion.split("-");
+
+        // by skipping i=0, there is no trailing separator
+        for (int i = 1; i < 2; i++) {
+            parts[0] = parts[0].concat("-");
+            parts[0] = parts[0].concat(parts[i]);
+        }
+
+        return parts[0];
+    }
+
+}
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/help/GSONArgument.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/help/GSONArgument.java
new file mode 100644
index 0000000..db214b9
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/help/GSONArgument.java
@@ -0,0 +1,83 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.utils.help;
+
+import java.util.List;
+import java.util.Map;
+
+/**
+ * GSON-friendly version of the argument bindings
+ */
+public class GSONArgument {
+
+    String summary;
+    String name;
+    String synonyms;
+    String type;
+    String required;
+    String fulltext;
+    String defaultValue;
+    String minValue;
+    String maxValue;
+    String minRecValue;
+    String maxRecValue;
+    String rodTypes;
+    String kind;
+    List<Map<String, Object>> options;
+
+    public void populate(   String summary,
+                            String name,
+                            String synonyms,
+                            String type,
+                            String required,
+                            String fulltext,
+                            String defaultValue,
+                            String minValue,
+                            String maxValue,
+                            String minRecValue,
+                            String maxRecValue,
+                            String rodTypes,
+                            String kind,
+                            List<Map<String, Object>> options
+    ) {
+        this.summary = summary;
+        this.name = name;
+        this.synonyms = synonyms;
+        this.type = type;
+        this.required = required;
+        this.fulltext = fulltext;
+        this.defaultValue = defaultValue;
+        this.minValue = minValue;
+        this.maxValue = maxValue;
+        this.minRecValue = minRecValue;
+        this.maxRecValue = maxRecValue;
+        this.rodTypes = rodTypes;
+        this.kind = kind;
+        this.options = options;
+    }
+
+
+}
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/help/GSONWorkUnit.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/help/GSONWorkUnit.java
new file mode 100644
index 0000000..c4481c0
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/help/GSONWorkUnit.java
@@ -0,0 +1,86 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.utils.help;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+
+/**
+ * GSON-friendly version of the GATKDocWorkUnit
+ */
+public class GSONWorkUnit {
+
+    String summary;
+    Object parallel;
+    Object activeregion;
+    String partitiontype;
+    String walkertype;
+    Object arguments;
+    Object refwindow;
+    String description;
+    String name;
+    String annotinfo;
+    Object readfilters;
+    Object downsampling;
+    String group;
+    String annotfield;
+    Object annotdescript;
+
+    public void populate(String summary,
+                         Object parallel,
+                         Object activeregion,
+                         String partitiontype,
+                         String walkertype,
+                         Object arguments,
+                         Object refwindow,
+                         String description,
+                         String name,
+                         String annotinfo,
+                         Object readfilters,
+                         Object downsampling,
+                         String group,
+                         String annotfield,
+                         Object annotdescript
+    ) {
+        this.summary = summary;
+        this.parallel = parallel;
+        this.activeregion = activeregion;
+        this.partitiontype = partitiontype;
+        this.walkertype = walkertype;
+        this.arguments = arguments;
+        this.refwindow = refwindow;
+        this.description = description;
+        this.name = name;
+        this.annotinfo = annotinfo;
+        this.readfilters = readfilters;
+        this.downsampling = downsampling;
+        this.group = group;
+        this.annotfield = annotfield;
+        this.annotdescript = annotdescript;
+    }
+
+}
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/help/GenericDocumentationHandler.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/help/GenericDocumentationHandler.java
new file mode 100644
index 0000000..fea1496
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/help/GenericDocumentationHandler.java
@@ -0,0 +1,1008 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.utils.help;
+
+import com.google.java.contract.Ensures;
+import com.google.java.contract.Requires;
+import com.sun.javadoc.ClassDoc;
+import com.sun.javadoc.FieldDoc;
+import com.sun.javadoc.Tag;
+import org.apache.commons.lang.StringUtils;
+import org.apache.log4j.Logger;
+import htsjdk.tribble.Feature;
+import org.broadinstitute.gatk.engine.walkers.*;
+import org.broadinstitute.gatk.utils.commandline.*;
+import org.broadinstitute.gatk.engine.CommandLineGATK;
+import org.broadinstitute.gatk.engine.refdata.tracks.FeatureManager;
+import org.broadinstitute.gatk.tools.walkers.annotator.interfaces.GenotypeAnnotation;
+import org.broadinstitute.gatk.tools.walkers.annotator.interfaces.InfoFieldAnnotation;
+import org.broadinstitute.gatk.utils.Utils;
+import org.broadinstitute.gatk.utils.classloader.JVMUtils;
+import org.broadinstitute.gatk.utils.collections.Pair;
+import org.broadinstitute.gatk.utils.exceptions.ReviewedGATKException;
+import org.broadinstitute.gatk.utils.exceptions.GATKException;
+
+import java.io.IOException;
+import java.lang.annotation.Annotation;
+import java.lang.reflect.*;
+import java.util.*;
+
+/**
+ *
+ */
+public class GenericDocumentationHandler extends DocumentedGATKFeatureHandler {
+    private static Logger logger = Logger.getLogger(GenericDocumentationHandler.class);
+
+    /**
+     * The max. length of the longest of --fullName -shortName argument name
+     * before we prefer the shorter option.
+     */
+    private static final int MAX_DISPLAY_NAME = 30;
+
+    /**
+     * The Class we are documenting
+     */
+    private GATKDocWorkUnit toProcess;
+
+    @Override
+    public boolean includeInDocs(ClassDoc doc) {
+        try {
+            Class type = DocletUtils.getClassForDoc(doc);
+            boolean hidden = !getDoclet().showHiddenFeatures() && type.isAnnotationPresent(Hidden.class);
+            return !hidden && JVMUtils.isConcrete(type);
+        } catch (ClassNotFoundException e) {
+            return false;
+        }
+    }
+
+
+    @Override
+    public String getTemplateName(ClassDoc doc) throws IOException {
+        return "generic.template.html";
+    }
+
+    @Override
+    public void processOne(GATKDocWorkUnit toProcessArg) {
+        this.toProcess = toProcessArg;
+
+        //System.out.printf("%s class %s%n", toProcess.group, toProcess.classDoc);
+        Map<String, Object> root = new HashMap<String, Object>();
+
+        addHighLevelBindings(root);
+        addArgumentBindings(root);
+        addRelatedBindings(root);
+        root.put("group", toProcess.group);
+
+        // Adding in retrieval of peripheral info (rf annotations etc)
+        getClazzAnnotations(toProcess.clazz, root);
+
+        toProcess.setHandlerContent((String) root.get("summary"), root);
+    }
+
+    /**
+     * Add high-level summary information about toProcess to root, such as its
+     * name, summary, description, version, etc.
+     *
+     * @param root
+     */
+    protected void addHighLevelBindings(Map<String, Object> root) {
+        root.put("name", toProcess.classDoc.name());
+
+        // Extract overrides from the doc tags.
+        StringBuilder summaryBuilder = new StringBuilder();
+        for (Tag tag : toProcess.classDoc.firstSentenceTags())
+            summaryBuilder.append(tag.text());
+        root.put("summary", summaryBuilder.toString());
+        root.put("description", toProcess.classDoc.commentText().substring(summaryBuilder.toString().length()));
+        root.put("timestamp", toProcess.buildTimestamp);
+        root.put("version", toProcess.absoluteVersion);
+
+        for (Tag tag : toProcess.classDoc.tags()) {
+            root.put(tag.name(), tag.text());
+        }
+
+        root.put("gotoDev", toProcess.annotation.gotoDev());
+    }
+
+    /**
+     * Add bindings describing related GATK capabilites to toProcess
+     *
+     * @param root
+     */
+    protected void addRelatedBindings(Map<String, Object> root) {
+        List<Map<String, Object>> extraDocsData = new ArrayList<Map<String, Object>>();
+
+        // add in all of the explicitly related items
+        for (final Class extraDocClass : toProcess.annotation.extraDocs()) {
+            final GATKDocWorkUnit otherUnit = getDoclet().findWorkUnitForClass(extraDocClass);
+            if (otherUnit == null)
+                throw new ReviewedGATKException("Requested extraDocs for class without any documentation: " + extraDocClass);
+            extraDocsData.add(
+                    new HashMap<String, Object>() {{
+                        put("filename", otherUnit.filename);
+                        put("name", otherUnit.name);
+                    }});
+        }
+        root.put("extradocs", extraDocsData);
+    }
+
+    /**
+     * Add information about all of the arguments available to toProcess to root
+     *
+     * @param root
+     */
+    protected void addArgumentBindings(Map<String, Object> root) {
+        ParsingEngine parsingEngine = createStandardGATKParsingEngine();
+
+        Map<String, List<Map<String, Object>>> args = createArgumentMap();
+        root.put("arguments", args);
+        try {
+            // loop over all of the arguments according to the parsing engine
+            for (final ArgumentSource argumentSource : parsingEngine.extractArgumentSources(DocletUtils.getClassForDoc(toProcess.classDoc))) {
+                ArgumentDefinition argDef = argumentSource.createArgumentDefinitions().get(0);
+                FieldDoc fieldDoc = getFieldDoc(toProcess.classDoc, argumentSource.field.getName());
+                Map<String, Object> argBindings = docForArgument(fieldDoc, argumentSource, argDef);
+                if (!argumentSource.isHidden() || getDoclet().showHiddenFeatures()) {
+                    final String kind = docKindOfArg(argumentSource);
+                    argBindings.put("kind", kind);
+                    // Retrieve default value
+                    final Object value = argumentValue(toProcess.clazz, argumentSource);
+                    if (value != null) {
+                        argBindings.put("defaultValue", prettyPrintValueString(value));
+                    } else {
+                        argBindings.put("defaultValue", "NA");
+                    }
+                    // Retrieve min and max / hard and soft value thresholds for numeric args
+                    if (value instanceof Number) {
+                        if (argumentSource.field.isAnnotationPresent(Argument.class))   {
+                            argBindings.put("minValue", argumentSource.field.getAnnotation(Argument.class).minValue());
+                            argBindings.put("maxValue", argumentSource.field.getAnnotation(Argument.class).maxValue());
+                            if (argumentSource.field.getAnnotation(Argument.class).minRecommendedValue() != Double.NEGATIVE_INFINITY) {
+                                argBindings.put("minRecValue", argumentSource.field.getAnnotation(Argument.class).minRecommendedValue());
+                            } else {
+                                argBindings.put("minRecValue", "NA");
+                            }
+                            if (argumentSource.field.getAnnotation(Argument.class).maxRecommendedValue() != Double.POSITIVE_INFINITY) {
+                                argBindings.put("maxRecValue", argumentSource.field.getAnnotation(Argument.class).maxRecommendedValue());
+                            } else {
+                                argBindings.put("maxRecValue", "NA");
+                            }
+                        }
+                    } else {
+                        argBindings.put("minValue", "NA");
+                        argBindings.put("maxValue", "NA");
+                        argBindings.put("minRecValue", "NA");
+                        argBindings.put("maxRecValue", "NA");
+                        argBindings.put("defaultValue", "NA");
+                    }
+                    // Finalize argument bindings
+                    args.get(kind).add(argBindings);
+                    args.get("all").add(argBindings);
+                }
+            }
+
+            // sort the arguments
+            for (Map.Entry<String, List<Map<String, Object>>> entry : args.entrySet()) {
+                entry.setValue(sortArguments(entry.getValue()));
+            }
+            // make a GSON-friendly map of arguments -- uses some hacky casting
+            List<GSONArgument> allGSONArgs = new ArrayList<GSONArgument>();
+            for ( Map<String, Object> item : args.get("all")) {
+                GSONArgument itemGSONArg = new GSONArgument();
+
+                itemGSONArg.populate(item.get("summary").toString(),
+                        item.get("name").toString(),
+                        item.get("synonyms").toString(),
+                        item.get("type").toString(),
+                        item.get("required").toString(),
+                        item.get("fulltext").toString(),
+                        item.get("defaultValue").toString(),
+                        item.get("minValue").toString(),
+                        item.get("maxValue").toString(),
+                        item.get("minRecValue").toString(),
+                        item.get("maxRecValue").toString(),
+                        item.get("rodTypes").toString(),
+                        item.get("kind").toString(),
+                        (List<Map<String, Object>>)item.get("options")
+                );
+                allGSONArgs.add(itemGSONArg);
+            }
+            root.put("gson-arguments", allGSONArgs);
+
+        } catch (ClassNotFoundException e) {
+            throw new RuntimeException(e);
+        }
+    }
+
+    /**
+     * Return the argument kind (required, advanced, hidden, etc) of this argumentSource
+     *
+     * @param argumentSource
+     * @return
+     */
+    @Requires("argumentSource != null")
+    @Ensures("result != null")
+    private String docKindOfArg(ArgumentSource argumentSource) {
+        if (argumentSource.isRequired()) {
+            if (argumentSource.isInput()) return "required_in";
+            else if (argumentSource.isOutput()) return "required_out";
+            else if (argumentSource.isFlag()) return "required_flag";
+            else return "required_param";
+            }
+        else if (argumentSource.isAdvanced()) {
+            if (argumentSource.isInput()) return "advanced_in";
+            else if (argumentSource.isOutput()) return "advanced_out";
+            else if (argumentSource.isFlag()) return "advanced_flag";
+            else return "advanced_param";
+        }
+        else if (argumentSource.isHidden()) return "hidden";
+        else if (argumentSource.isDeprecated()) return "deprecated";
+        else {
+            if (argumentSource.isInput()) return "optional_in";
+            else if (argumentSource.isOutput()) return "optional_out";
+            else if (argumentSource.isFlag()) return "optional_flag";
+            else return "optional_param";
+        }
+    }
+
+    /**
+     * Attempts to determine the value of argumentSource in an instantiated version of c
+     *
+     * @param c
+     * @param argumentSource
+     * @return value of argumentSource, or null if this isn't possible
+     */
+    @Requires({"c != null", "argumentSource != null"})
+    private Object argumentValue(Class c, ArgumentSource argumentSource) {
+        // get the value of the field
+        // attempt to instantiate the class
+        final Object instance = makeInstanceIfPossible(toProcess.clazz);
+        if (instance != null) {
+            final Object value = getFieldValue(instance, argumentSource.field.getName());
+            if (value != null)
+                return value;
+
+            if (argumentSource.createsTypeDefault()) {
+                try { // handle the case where there's an implicit default
+                    return argumentSource.typeDefaultDocString();
+                } catch (ReviewedGATKException e) {
+                    ; // failed to create type default, don't worry about it
+                }
+            }
+        }
+
+        return null;
+    }
+
+    /**
+     * Create the argument map for holding class arguments
+     *
+     * @return
+     */
+    private Map<String, List<Map<String, Object>>> createArgumentMap() {
+        Map<String, List<Map<String, Object>>> args = new HashMap<String, List<Map<String, Object>>>();
+        args.put("all", new ArrayList<Map<String, Object>>());
+        args.put("required_in", new ArrayList<Map<String, Object>>());
+        args.put("required_out", new ArrayList<Map<String, Object>>());
+        args.put("required_param", new ArrayList<Map<String, Object>>());
+        args.put("required_flag", new ArrayList<Map<String, Object>>());
+        args.put("optional_in", new ArrayList<Map<String, Object>>());
+        args.put("optional_out", new ArrayList<Map<String, Object>>());
+        args.put("optional_param", new ArrayList<Map<String, Object>>());
+        args.put("optional_flag", new ArrayList<Map<String, Object>>());
+        args.put("advanced_in", new ArrayList<Map<String, Object>>());
+        args.put("advanced_out", new ArrayList<Map<String, Object>>());
+        args.put("advanced_param", new ArrayList<Map<String, Object>>());
+        args.put("advanced_flag", new ArrayList<Map<String, Object>>());
+        args.put("hidden", new ArrayList<Map<String, Object>>());
+        args.put("deprecated", new ArrayList<Map<String, Object>>());
+        return args;
+    }
+
+
+    /**
+     * Sorts the individual argument list in unsorted according to CompareArgumentsByName
+     *
+     * @param unsorted
+     * @return
+     */
+    private List<Map<String, Object>> sortArguments(List<Map<String, Object>> unsorted) {
+        Collections.sort(unsorted, new CompareArgumentsByName());
+        return unsorted;
+    }
+
+    /**
+     * Sort arguments by case-insensitive comparison ignoring the -- and - prefixes
+     */
+    private class CompareArgumentsByName implements Comparator<Map<String, Object>> {
+        public int compare(Map<String, Object> x, Map<String, Object> y) {
+            return elt(x).compareTo(elt(y));
+        }
+
+        private String elt(Map<String, Object> m) {
+            String v = m.get("name").toString().toLowerCase();
+            if (v.startsWith("--"))
+                return v.substring(2);
+            else if (v.startsWith("-"))
+                return v.substring(1);
+            else
+                throw new RuntimeException("Expect to see arguments beginning with at least one -, but found " + v);
+        }
+    }
+
+    /**
+     * Umbrella function that groups the collection of values for specific annotations applied to an
+     * instance of class c. Lists of collected values are added directly to the "toProcess" object.
+     * Requires being able to instantiate the class.
+     *
+     * @param classToProcess the object to instantiate and query for the annotation
+     * @param root the root of the document handler, to which we'll store collected annotations
+     */
+    private void getClazzAnnotations(Class classToProcess, Map<String, Object> root) {
+        //
+        // attempt to instantiate the class
+        final Object instance = makeInstanceIfPossible(classToProcess);
+        if (instance != null) {
+            final Class myClass = instance.getClass();
+            // Get parallelism options
+            final HashSet<HashMap<String, Object>> parallelOptions = getParallelism(myClass, new HashSet<HashMap<String, Object>>());
+            root.put("parallel", parallelOptions);
+            // Get annotation info (what type of annotation, standard etc.)
+            final HashSet<String> annotInfo = getAnnotInfo(myClass, new HashSet<String>());
+            root.put("annotinfo", StringUtils.join(annotInfo, ", "));
+            // Get annotation field (whether it goes in INFO or FORMAT)
+            root.put("annotfield", getAnnotField(myClass));
+            // Get walker type if applicable
+            root.put("walkertype", getWalkerType(myClass));
+            // Get partition type if applicable
+            root.put("partitiontype", getPartitionType(myClass));
+            // Get read filter annotations (ReadFilters) if applicable
+            final HashSet<HashMap<String, Object>> bucket= getReadFilters(myClass, new HashSet<HashMap<String, Object>>());
+            root.put("readfilters", bucket);
+            // Get default downsampling settings
+            final HashMap<String, Object> dsSettings = getDownSamplingSettings(myClass, new HashMap<String, Object>());
+            root.put("downsampling", dsSettings);
+            // Get reference window size settings
+            final HashMap<String, Object> refwindow = getRefWindow(myClass, new HashMap<String, Object>());
+            root.put("refwindow", refwindow);
+            // Get ActiveRegion size settings
+            final HashMap<String, Object> activeRegion = getActiveRegion(myClass, new HashMap<String, Object>());
+            root.put("activeregion", activeRegion);
+            // Get annotation header line description if applicable
+            final Object annotDescriptLines = getAnnotDescript(instance, myClass);
+            root.put("annotdescript", annotDescriptLines);
+
+            // anything else?
+        } else {
+            // put empty items to avoid blowups
+            root.put("parallel", new HashSet<String>());
+            root.put("annotinfo", "");
+            root.put("annotfield", "");
+            root.put("walkertype", "");
+            root.put("partitiontype", "");
+            root.put("readfilters", new HashSet<HashMap<String, Object>>());
+            root.put("downsampling", new HashMap<String, Object>());
+            root.put("refwindow", new HashMap<String, Object>());
+            root.put("activeregion", new HashMap<String, Object>());
+            root.put("annotdescript", new ArrayList<HashMap<String, Object>>());
+        }
+    }
+
+    /**
+     * Utility function that looks up annotation descriptions if applicable.
+     *
+     * @param myClass the class to query
+     * @return a hash map of descriptions, otherwise an empty map
+     */
+    private Object getAnnotDescript(Object instance, Class myClass) {
+        //
+        // Check if the class has the method we want
+        for (Method classMethod : myClass.getMethods()) {
+            if (classMethod.toString().contains("getDescriptions") && classMethod.toString().contains("annotator")) {
+                try {
+                    return classMethod.invoke(instance);
+                } catch (IllegalArgumentException e) {
+                } catch (IllegalAccessException e) {
+                } catch (InvocationTargetException e) {
+                }
+            }
+        }
+        return null;
+    }
+
+    /**
+     * Utility function that checks which parallelism options are available for an instance of class c.
+     *
+     * @param myClass the class to query for the interfaces
+     * @param parallelOptions an empty HashSet in which to collect the info
+     * @return a hash set of parallelism options, otherwise an empty set
+     */
+    private HashSet<HashMap<String, Object>> getParallelism(Class myClass, HashSet<HashMap<String, Object>> parallelOptions) {
+        //
+        // Retrieve interfaces
+        Class[] implementedInterfaces = myClass.getInterfaces();
+        for (Class intfClass : implementedInterfaces) {
+            final HashMap<String, Object> nugget = new HashMap<String, Object>();
+            if (intfClass.getSimpleName().equals("TreeReducible")) {
+                nugget.put("name", intfClass.getSimpleName());
+                nugget.put("arg", HelpConstants.ARG_TREEREDUCIBLE);
+                nugget.put("link", HelpConstants.CMDLINE_GATK_URL + "#" + HelpConstants.ARG_TREEREDUCIBLE);
+            } else if (intfClass.getSimpleName().equals("NanoSchedulable")) {
+                nugget.put("name", intfClass.getSimpleName());
+                nugget.put("arg", HelpConstants.ARG_NANOSCHEDULABLE);
+                nugget.put("link", HelpConstants.CMDLINE_GATK_URL + "#" + HelpConstants.ARG_NANOSCHEDULABLE);
+            } else {
+                continue;
+            }
+            parallelOptions.add(nugget);
+        }
+        // Look up superclasses recursively
+        final Class mySuperClass = myClass.getSuperclass();
+        if (mySuperClass.getSimpleName().equals("Object")) {
+            return parallelOptions;
+        }
+        return getParallelism(mySuperClass, parallelOptions);
+    }
+
+    /**
+     * Utility function that looks up whether the annotation goes in INFO or FORMAT field.
+     *
+     * @param myClass the class to query for the interfaces
+     * @return a String specifying the annotation field
+     */
+    private final String getAnnotField(Class myClass) {
+        //
+        // Look up superclasses recursively until we find either
+        // GenotypeAnnotation or InfoFieldAnnotation
+        final Class mySuperClass = myClass.getSuperclass();
+        if (mySuperClass == InfoFieldAnnotation.class) {
+            return "INFO (variant-level)";
+        } else if (mySuperClass == GenotypeAnnotation.class) {
+            return "FORMAT (sample genotype-level)";
+        } else if (mySuperClass.getSimpleName().equals("Object")) {
+            return "";
+        }
+        return getAnnotField(mySuperClass);
+    }
+
+    /**
+     * Utility function that determines the annotation type for an instance of class c.
+     *
+     * @param myClass the class to query for the interfaces
+     * @param annotInfo an empty HashSet in which to collect the info
+     * @return a hash set of the annotation types, otherwise an empty set
+     */
+    private HashSet<String> getAnnotInfo(Class myClass, HashSet<String> annotInfo) {
+        //
+        // Retrieve interfaces
+        Class[] implementedInterfaces = myClass.getInterfaces();
+        for (Class intfClass : implementedInterfaces) {
+            if (intfClass.getName().contains("Annotation")) {
+                annotInfo.add(intfClass.getSimpleName());
+            }
+        }
+        // Look up superclasses recursively
+        final Class mySuperClass = myClass.getSuperclass();
+        if (mySuperClass.getSimpleName().equals("Object")) {
+            return annotInfo;
+        }
+        return getAnnotInfo(mySuperClass, annotInfo);
+    }
+
+    /**
+     * Utility function that determines the default downsampling settings for an instance of class c.
+     *
+     * @param myClass the class to query for the settings
+     * @param dsSettings an empty HashMap in which to collect the info
+     * @return a hash set of the downsampling settings, otherwise an empty set
+     */
+    private HashMap<String, Object> getDownSamplingSettings(Class myClass, HashMap<String, Object> dsSettings) {
+        //
+        // Retrieve annotation
+        if (myClass.isAnnotationPresent(Downsample.class)) {
+            final Annotation thisAnnotation = myClass.getAnnotation(Downsample.class);
+            if(thisAnnotation instanceof Downsample) {
+                final Downsample dsAnnotation = (Downsample) thisAnnotation;
+                dsSettings.put("by", dsAnnotation.by().toString());
+                dsSettings.put("to_cov", dsAnnotation.toCoverage());
+            }
+        }
+        return dsSettings;
+    }
+
+    /**
+     * Utility function that determines the reference window size for an instance of class c.
+     *
+     * @param myClass the class to query for the settings
+     * @param refWindow an empty HashMap in which to collect the info
+     * @return a HashMap of the window start and stop, otherwise an empty HashMap
+     */
+    private HashMap<String, Object> getRefWindow(Class myClass, HashMap<String, Object> refWindow) {
+        //
+        // Retrieve annotation
+        if (myClass.isAnnotationPresent(Reference.class)) {
+            final Annotation thisAnnotation = myClass.getAnnotation(Reference.class);
+            if(thisAnnotation instanceof Reference) {
+                final Reference refAnnotation = (Reference) thisAnnotation;
+                refWindow.put("start", refAnnotation.window().start());
+                refWindow.put("stop", refAnnotation.window().stop());
+            }
+        }
+        return refWindow;
+    }
+
+    /**
+     * Utility function that determines the ActiveRegion settings for an instance of class c.
+     *
+     * @param myClass the class to query for the settings
+     * @param activeRegion an empty HashMap in which to collect the info
+     * @return a HashMap of the ActiveRegion parameters, otherwise an empty HashMap
+     */
+    private HashMap<String, Object> getActiveRegion(Class myClass, HashMap<String, Object> activeRegion) {
+        //
+        // Retrieve annotation
+        if (myClass.isAnnotationPresent(ActiveRegionTraversalParameters.class)) {
+            final Annotation thisAnnotation = myClass.getAnnotation(ActiveRegionTraversalParameters.class);
+            if(thisAnnotation instanceof ActiveRegionTraversalParameters) {
+                final ActiveRegionTraversalParameters arAnnotation = (ActiveRegionTraversalParameters) thisAnnotation;
+                activeRegion.put("ext", arAnnotation.extension());
+                activeRegion.put("max", arAnnotation.maxRegion());
+                activeRegion.put("min", arAnnotation.minRegion());
+            }
+        }
+        return activeRegion;
+    }
+
+    /**
+     * Utility function that determines the partition type of an instance of class c.
+     *
+     * @param myClass the class to query for the annotation
+     * @return the partition type if applicable, otherwise an empty string
+     */
+    private String getPartitionType(Class myClass) {
+        //
+        // Retrieve annotation
+        if (myClass.isAnnotationPresent(PartitionBy.class)) {
+            final Annotation thisAnnotation = myClass.getAnnotation(PartitionBy.class);
+            if(thisAnnotation instanceof PartitionBy) {
+                final PartitionBy partAnnotation = (PartitionBy) thisAnnotation;
+                return partAnnotation.value().toString();
+            }
+        }
+        return "";
+    }
+
+    /**
+     * Utility function that determines the type of walker subclassed by an instance of class c.
+     *
+     * @param myClass the class to query for the annotation
+     * @return the type of walker if applicable, otherwise an empty string
+     */
+    private String getWalkerType(Class myClass) {
+        //
+        // Look up superclasses recursively until we find either Walker or Object
+        final Class mySuperClass = myClass.getSuperclass();
+        if (mySuperClass.getSimpleName().equals("Walker")) {
+            return myClass.getSimpleName();
+        } else if (mySuperClass.getSimpleName().equals("Object")) {
+            return "";
+        }
+        return getWalkerType(mySuperClass);
+    }
+
+    /**
+     * Utility function that finds the values of ReadFilters annotation applied to an instance of class c.
+     *
+     * @param myClass the class to query for the annotation
+     * @param bucket a container in which we store the annotations collected
+     * @return a hash set of values, otherwise an empty set
+     */
+    private HashSet<HashMap<String, Object>> getReadFilters(Class myClass, HashSet<HashMap<String, Object>> bucket) {
+        //
+        // Retrieve annotation
+        if (myClass.isAnnotationPresent(ReadFilters.class)) {
+            final Annotation thisAnnotation = myClass.getAnnotation(ReadFilters.class);
+            if(thisAnnotation instanceof ReadFilters) {
+                final ReadFilters rfAnnotation = (ReadFilters) thisAnnotation;
+                for (Class<?> filter : rfAnnotation.value()) {
+                    // make hashmap of simplename and url
+                    final HashMap<String, Object> nugget = new HashMap<String, Object>();
+                    nugget.put("name", filter.getSimpleName());
+                    nugget.put("filename", GATKDocUtils.phpFilenameForClass(filter));
+                    bucket.add(nugget);
+                }
+            }
+        }
+        // Look up superclasses recursively
+        final Class mySuperClass = myClass.getSuperclass();
+        if (mySuperClass.getSimpleName().equals("Object")) {
+            return bucket;
+        }
+        return getReadFilters(mySuperClass, bucket);
+    }
+
+
+    /**
+     * Utility function that finds the value of fieldName in any fields of ArgumentCollection fields in
+     * instance of class c.
+     *
+     * @param instance  the object to query for the field value
+     * @param fieldName the name of the field we are looking for in instance
+     * @return The value assigned to field in the ArgumentCollection, otherwise null
+     */
+    private Object getFieldValue(Object instance, String fieldName) {
+        //
+        // subtle note.  If you have a field named X that is an ArgumentCollection that
+        // contains a field X as well, you need only consider fields in the argumentCollection, not
+        // matching the argument itself.
+        //
+        // @ArgumentCollection
+        // protected DbsnpArgumentCollection dbsnp = new DbsnpArgumentCollection();
+        //
+
+        for (Field field : JVMUtils.getAllFields(instance.getClass())) {
+            if (field.isAnnotationPresent(ArgumentCollection.class)) {
+                //System.out.printf("Searching for %s in argument collection field %s%n", fieldName, field);
+                Object fieldValue = JVMUtils.getFieldValue(field, instance);
+                Object value = getFieldValue(fieldValue, fieldName);
+                if (value != null)
+                    return value;
+            } else if (field.getName().equals(fieldName)) {
+                return JVMUtils.getFieldValue(field, instance);
+            }
+        }
+
+        return null;
+    }
+
+    /**
+     * Pretty prints value
+     * <p/>
+     * Assumes value != null
+     *
+     * @param value
+     * @return
+     */
+    private Object prettyPrintValueString(Object value) {
+        if (value.getClass().isArray()) {
+            Class type = value.getClass().getComponentType();
+            if (boolean.class.isAssignableFrom(type))
+                return Arrays.toString((boolean[]) value);
+            if (byte.class.isAssignableFrom(type))
+                return Arrays.toString((byte[]) value);
+            if (char.class.isAssignableFrom(type))
+                return Arrays.toString((char[]) value);
+            if (double.class.isAssignableFrom(type))
+                return Arrays.toString((double[]) value);
+            if (float.class.isAssignableFrom(type))
+                return Arrays.toString((float[]) value);
+            if (int.class.isAssignableFrom(type))
+                return Arrays.toString((int[]) value);
+            if (long.class.isAssignableFrom(type))
+                return Arrays.toString((long[]) value);
+            if (short.class.isAssignableFrom(type))
+                return Arrays.toString((short[]) value);
+            if (Object.class.isAssignableFrom(type))
+                return Arrays.toString((Object[]) value);
+            else
+                throw new RuntimeException("Unexpected array type in prettyPrintValue.  Value was " + value + " type is " + type);
+        } else if (RodBinding.class.isAssignableFrom(value.getClass())) {
+            // annoying special case to handle the UnBound() constructor
+            return "none";
+        } else if (value instanceof String) {
+            return value.equals("") ? "\"\"" : value;
+        } else {
+            return value.toString();
+        }
+    }
+
+    /**
+     * Attempt to instantiate class c, if possible.  Returns null if this proves impossible.
+     *
+     * @param c
+     * @return
+     */
+    private Object makeInstanceIfPossible(Class c) {
+        Object instance = null;
+        try {
+            // don't try to make something where we will obviously fail
+            if (!c.isEnum() && !c.isAnnotation() && !c.isAnonymousClass() &&
+                    !c.isArray() && !c.isPrimitive() & JVMUtils.isConcrete(c)) {
+                instance = c.newInstance();
+                //System.out.printf("Created object of class %s => %s%n", c, instance);
+                return instance;
+            } else
+                return null;
+        } catch (IllegalAccessException e) {
+        } catch (InstantiationException e) {
+        } catch (ExceptionInInitializerError e) {
+        } catch (SecurityException e) {
+        }
+        // this last one is super dangerous, but some of these methods catch ClassNotFoundExceptions
+        // and rethrow then as RuntimeExceptions
+        catch (RuntimeException e) {
+        }
+
+        return instance;
+    }
+
+
+    /**
+     * Create an instance of the GATK parsing engine, for argument processing with GATKDoclet
+     *
+     * @return
+     */
+    private ParsingEngine createStandardGATKParsingEngine() {
+        CommandLineProgram clp = new CommandLineGATK();
+        try {
+            CommandLineProgram.start(clp, new String[]{}, true);
+            return clp.parser;
+        } catch (Exception e) {
+            throw new RuntimeException(e);
+        }
+    }
+
+    /**
+     * Gets the javadocs associated with field name in classDoc.  Throws a
+     * runtime exception if this proves impossible.
+     *
+     * @param classDoc
+     * @param name
+     * @return
+     */
+    private FieldDoc getFieldDoc(ClassDoc classDoc, String name) {
+        return getFieldDoc(classDoc, name, true);
+    }
+
+    /**
+     * Recursive helper routine to getFieldDoc()
+     *
+     * @param classDoc
+     * @param name
+     * @param primary
+     * @return
+     */
+    private FieldDoc getFieldDoc(ClassDoc classDoc, String name, boolean primary) {
+        //System.out.printf("Looking for %s in %s%n", name, classDoc.name());
+        for (FieldDoc fieldDoc : classDoc.fields(false)) {
+            //System.out.printf("fieldDoc " + fieldDoc + " name " + fieldDoc.name());
+            if (fieldDoc.name().equals(name))
+                return fieldDoc;
+
+            Field field = DocletUtils.getFieldForFieldDoc(fieldDoc);
+            if (field == null)
+                throw new RuntimeException("Could not find the field corresponding to " + fieldDoc + ", presumably because the field is inaccessible");
+            if (field.isAnnotationPresent(ArgumentCollection.class)) {
+                ClassDoc typeDoc = getRootDoc().classNamed(fieldDoc.type().qualifiedTypeName());
+                if (typeDoc == null)
+                    throw new ReviewedGATKException("Tried to get javadocs for ArgumentCollection field " + fieldDoc + " but could't find the class in the RootDoc");
+                else {
+                    FieldDoc result = getFieldDoc(typeDoc, name, false);
+                    if (result != null)
+                        return result;
+                    // else keep searching
+                }
+            }
+        }
+
+        // if we didn't find it here, wander up to the superclass to find the field
+        if (classDoc.superclass() != null) {
+            return getFieldDoc(classDoc.superclass(), name, false);
+        }
+
+        if (primary)
+            throw new RuntimeException("No field found for expected field " + name);
+        else
+            return null;
+    }
+
+    /**
+     * Returns a Pair of (main, synonym) names for argument with fullName s1 and
+     * shortName s2.
+     *
+     * Previously we had it so the main name was selected to be the longest of the two, provided
+     * it didn't exceed MAX_DISPLAY_NAME, in which case the shorter was taken. But we now disable
+     * the length-based name rearrangement in order to maintain consistency in the GATKDocs table.
+     *
+     * This may cause messed up spacing in the CLI-help display but we don't care as much about that
+     * since more users use the online GATKDocs for looking up arguments.
+     *
+     * @param s1 the short argument name without -, or null if not provided
+     * @param s2 the long argument name without --, or null if not provided
+     * @return A pair of fully qualified names (with - or --) for the argument.  The first
+     *         element is the primary display name while the second (potentially null) is a
+     *         synonymous name.
+     */
+    Pair<String, String> displayNames(String s1, String s2) {
+        s1 = s1 == null ? null : "-" + s1;
+        s2 = s2 == null ? null : "--" + s2;
+
+        if (s1 == null) return new Pair<String, String>(s2, null);
+        if (s2 == null) return new Pair<String, String>(s1, null);
+
+        return new Pair<String, String>(s2, s1);
+    }
+
+    /**
+     * Returns a human readable string that describes the Type type of a GATK argument.
+     * <p/>
+     * This will include parameterized types, so that Set{T} shows up as Set(T) and not
+     * just Set in the docs.
+     *
+     * @param type
+     * @return
+     */
+    protected String argumentTypeString(Type type) {
+        if (type instanceof ParameterizedType) {
+            ParameterizedType parameterizedType = (ParameterizedType) type;
+            List<String> subs = new ArrayList<String>();
+            for (Type actualType : parameterizedType.getActualTypeArguments())
+                subs.add(argumentTypeString(actualType));
+            return argumentTypeString(((ParameterizedType) type).getRawType()) + "[" + Utils.join(",", subs) + "]";
+        } else if (type instanceof GenericArrayType) {
+            return argumentTypeString(((GenericArrayType) type).getGenericComponentType()) + "[]";
+        } else if (type instanceof WildcardType) {
+            throw new RuntimeException("We don't support wildcards in arguments: " + type);
+        } else if (type instanceof Class<?>) {
+            return ((Class) type).getSimpleName();
+        } else {
+            throw new GATKException("Unknown type: " + type);
+        }
+    }
+
+    /**
+     * Helper routine that returns the Feature.class required by a RodBinding,
+     * either T for RodBinding{T} or List{RodBinding{T}}.  Returns null if
+     * the Type doesn't fit either model.
+     *
+     * @param type
+     * @return
+     */
+    protected Class<? extends Feature> getFeatureTypeIfPossible(Type type) {
+        if (type instanceof ParameterizedType) {
+            ParameterizedType paramType = (ParameterizedType) type;
+            if (RodBinding.class.isAssignableFrom((Class<?>) paramType.getRawType())) {
+                return (Class<? extends Feature>) JVMUtils.getParameterizedTypeClass(type);
+            } else {
+                for (Type paramtype : paramType.getActualTypeArguments()) {
+                    Class<? extends Feature> x = getFeatureTypeIfPossible(paramtype);
+                    if (x != null)
+                        return x;
+                }
+            }
+        }
+
+        return null;
+    }
+
+    /**
+     * High-level entry point for creating a FreeMarker map describing the GATK argument
+     * source with definition def, with associated javadoc fieldDoc.
+     *
+     * @param fieldDoc
+     * @param source
+     * @param def
+     * @return a non-null Map binding argument keys with their values
+     */
+    protected Map<String, Object> docForArgument(FieldDoc fieldDoc, ArgumentSource source, ArgumentDefinition def) {
+        Map<String, Object> root = new HashMap<String, Object>();
+        Pair<String, String> names = displayNames(def.shortName, def.fullName);
+
+        root.put("name", names.getFirst());
+
+        if (names.getSecond() != null) {
+            root.put("synonyms", names.getSecond());
+        } else {
+            root.put("synonyms", "NA");
+        }
+
+        root.put("required", def.required ? "yes" : "no");
+
+        // type of the field
+        root.put("type", argumentTypeString(source.field.getGenericType()));
+
+        Class<? extends Feature> featureClass = getFeatureTypeIfPossible(source.field.getGenericType());
+        if (featureClass != null) {
+            // deal with the allowable types
+            FeatureManager manager = new FeatureManager();
+            List<String> rodTypes = new ArrayList<String>();
+            for (FeatureManager.FeatureDescriptor descriptor : manager.getByFeature(featureClass)) {
+                rodTypes.add(String.format("<a href=%s>%s</a>",
+                        GATKDocUtils.phpFilenameForClass(descriptor.getCodecClass()),
+                        descriptor.getName()));
+            }
+
+            root.put("rodTypes", Utils.join(", ", rodTypes));
+        } else {
+            root.put("rodTypes", "NA");
+        }
+
+        // summary and fulltext
+        root.put("summary", def.doc != null ? def.doc : "");
+        root.put("fulltext", fieldDoc.commentText());
+
+        // What are our enum options?
+        if (def.validOptions != null) {
+            root.put("options", docForEnumArgument(source.field.getType()));
+        } else {
+            root.put("options", new ArrayList());
+        }
+        // general attributes
+        List<String> attributes = new ArrayList<String>();
+        if (def.required) attributes.add("required");
+        if (source.isDeprecated()) attributes.add("deprecated");
+        if (attributes.size() > 0) {
+            root.put("attributes", Utils.join(", ", attributes));
+        } else {
+            root.put("attributes", "NA");
+        }
+        return root;
+    }
+
+    /**
+     * Helper routine that provides a FreeMarker map for an enumClass, grabbing the
+     * values of the enum and their associated javadoc documentation.
+     *
+     * @param enumClass
+     * @return
+     */
+    @Requires("enumClass.isEnum()")
+    private List<Map<String, Object>> docForEnumArgument(final Class enumClass) {
+        final ClassDoc doc = this.getDoclet().getClassDocForClass(enumClass);
+        if ( doc == null )
+            throw new RuntimeException("Tried to get docs for enum " + enumClass + " but got null instead");
+
+        final Set<String> enumConstantFieldNames = enumConstantsNames(enumClass);
+
+        final List<Map<String, Object>> bindings = new ArrayList<Map<String, Object>>();
+        for (final FieldDoc fieldDoc : doc.fields(false)) {
+            if (enumConstantFieldNames.contains(fieldDoc.name()) )
+                bindings.add(
+                        new HashMap<String, Object>() {{
+                            put("name", fieldDoc.name());
+                            put("summary", fieldDoc.commentText());
+                        }});
+        }
+
+        return bindings;
+    }
+
+    /**
+     * Returns the name of the fields that are enum constants according to reflection
+     *
+     * @return a non-null set of fields that are enum constants
+     */
+    private Set<String> enumConstantsNames(final Class enumClass) {
+        final Set<String> enumConstantFieldNames = new HashSet<String>();
+
+        for ( final Field field : enumClass.getFields() ) {
+            if ( field.isEnumConstant() )
+                enumConstantFieldNames.add(field.getName());
+        }
+
+        return enumConstantFieldNames;
+    }
+}
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/help/HelpConstants.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/help/HelpConstants.java
new file mode 100644
index 0000000..16257c6
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/help/HelpConstants.java
@@ -0,0 +1,83 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.utils.help;
+
+public class HelpConstants {
+
+    public final static String BASE_GATK_URL = "http://www.broadinstitute.org/gatk";
+    public final static String GATK_DOCS_URL = BASE_GATK_URL + "/tooldocs/";
+    public final static String GATK_FORUM_URL = "http://gatkforums.broadinstitute.org/";
+    public final static String GATK_FORUM_API_URL = "https://gatkforums.broadinstitute.org/api/v1/";
+
+    /**
+     * Arguments for parallelism options
+     */
+    public final static String ARG_TREEREDUCIBLE = "-nt";
+    public final static String ARG_NANOSCHEDULABLE = "-nct";
+    public final static String CMDLINE_GATK_URL = GATK_DOCS_URL + "org_broadinstitute_gatk_engine_CommandLineGATK.php";
+
+    /**
+     * Definition of the group names / categories of tools.
+     * The names get parsed to make supercategories in the doc index,
+     * so be careful when making big changes -- see GATKDoclet.java toMap()
+     */
+    public final static String DOCS_CAT_DATA = "Sequence Data Processing Tools";
+    public final static String DOCS_CAT_QC = "Diagnostics and Quality Control Tools";
+    public final static String DOCS_CAT_ENGINE = "Engine Parameters (available to all tools)";
+    public final static String DOCS_CAT_RF = "Read Filters";
+    public final static String DOCS_CAT_REFUTILS = "Reference Utilities";
+    public final static String DOCS_CAT_RODCODECS = "ROD Codecs";
+    public final static String DOCS_CAT_USRERR = "User Exceptions (DevZone)";
+    public final static String DOCS_CAT_VALIDATION = "Validation Utilities";
+    public final static String DOCS_CAT_ANNOT = "Variant Annotations";
+    public final static String DOCS_CAT_VARDISC = "Variant Discovery Tools";
+    public final static String DOCS_CAT_VARMANIP = "Variant Evaluation and Manipulation Tools";
+    public final static String DOCS_CAT_TOY = "Toy Walkers (DevZone)";
+    public final static String DOCS_CAT_HELPUTILS = "Help Utilities";
+
+    public static String forumPost(String post) {
+    	return GATK_FORUM_URL + post;
+    }
+
+    /**
+     * Go-to developer name codes for tracking and display purposes. Only current team members should be in this list.
+     * When someone leaves, their charges should be redistributed. The actual string should be closest to the dev's
+     * abbreviated name or two/three-letter nickname as possible. The code can be something else if necessary to
+     * disambiguate from other variable.
+     */
+    public final static String MC = "MC"; // Mauricio Carneiro
+    public final static String EB = "EB"; // Eric Banks
+    public final static String RP = "RP"; // Ryan Poplin
+    public final static String GVDA = "GG"; // Geraldine Van der Auwera
+    public final static String VRR = "VRR"; // Valentin Ruano-Rubio
+    public final static String ALM = "ALM"; // Ami Levy-Moonshine
+    public final static String BH = "BH"; // Bertrand Haas
+    public final static String JoT = "JT"; // Joel Thibault
+    public final static String DR = "DR"; // David Roazen
+    public final static String KS = "KS"; // Khalid Shakir
+
+
+}
\ No newline at end of file
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/help/HelpFormatter.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/help/HelpFormatter.java
new file mode 100644
index 0000000..a8d4693
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/help/HelpFormatter.java
@@ -0,0 +1,336 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.utils.help;
+
+import org.apache.log4j.Logger;
+import org.broadinstitute.gatk.utils.commandline.*;
+import org.broadinstitute.gatk.utils.Utils;
+import org.broadinstitute.gatk.utils.text.TextFormattingUtils;
+
+import java.net.InetAddress;
+import java.text.DateFormat;
+import java.text.SimpleDateFormat;
+import java.util.*;
+/**
+ * Print out help for GATK command-line applications.
+ */
+
+public class HelpFormatter {
+    /** our log, which we want to capture anything from org.broadinstitute.gatk */
+    private static Logger logger = Logger.getLogger(HelpFormatter.class);
+
+    public static final int FIELD_SEPARATION_WIDTH = 3;
+
+    /**
+     * Prints the help, given a collection of argument definitions.
+     * @param applicationDetails Application details
+     * @param argumentDefinitions Argument definitions for which help should be printed.
+     */
+    public void printHelp( ApplicationDetails applicationDetails, ArgumentDefinitions argumentDefinitions ) {
+        List<ArgumentDefinitionGroup> argumentGroups = prepareArgumentGroups( argumentDefinitions );
+
+        List<String> header = applicationDetails.applicationHeader;
+        String barrier = createBarrier(header);
+
+        System.out.printf("%s%n",barrier);
+        for(String headerLine: header)
+            System.out.printf("%s%n",headerLine);
+        System.out.printf("%s%n",barrier);
+        for(String attributionLine: applicationDetails.attribution)
+            System.out.printf("%s%n",attributionLine);
+        System.out.printf("%s%n",barrier);
+
+        String synopsis = getSynopsis(applicationDetails.runningInstructions,argumentGroups);
+        String additionalDetails = applicationDetails.additionalHelp != null ? applicationDetails.additionalHelp : "";
+        String detailedDescription = getDetailed(argumentGroups);
+
+        System.out.printf("%s%n%s%n%s%n",synopsis,detailedDescription,additionalDetails );
+    }
+
+    /**
+     * Gets the synopsis: the actual command to run.
+     * @param runningInstructions Instructions on how to run hte application.
+     * @param argumentGroups Program arguments sorted in order of definition group displays.
+     * @return A synopsis line.
+     */
+    private String getSynopsis( String runningInstructions,
+                                List<ArgumentDefinitionGroup> argumentGroups ) {
+        // Build out the synopsis all as one long line.        
+        StringBuilder lineBuilder = new StringBuilder();
+        Formatter lineFormatter = new Formatter( lineBuilder );
+
+        lineFormatter.format("java %s", runningInstructions);
+
+        for( ArgumentDefinitionGroup argumentGroup: argumentGroups ) {
+            for( ArgumentDefinition argumentDefinition: argumentGroup.argumentDefinitions ) {
+                if(argumentDefinition.isHidden)
+                    continue;
+                lineFormatter.format(" ");
+                if( !argumentDefinition.required ) lineFormatter.format("[");
+                if( argumentDefinition.shortName != null )
+                    lineFormatter.format("-%s", argumentDefinition.shortName);
+                else
+                    lineFormatter.format("--%s", argumentDefinition.fullName);
+                if( !argumentDefinition.isFlag )
+                    lineFormatter.format(" <%s>", argumentDefinition.fullName);                
+                if( !argumentDefinition.required ) lineFormatter.format("]");
+            }
+        }
+
+        // Word wrap the synopsis.
+        List<String> wrappedSynopsis = TextFormattingUtils.wordWrap( lineBuilder.toString(), TextFormattingUtils.DEFAULT_LINE_WIDTH );
+
+        String header = "usage: ";
+        int headerLength = header.length();
+
+        StringBuilder synopsisBuilder = new StringBuilder();
+        Formatter synopsisFormatter = new Formatter(synopsisBuilder);
+        for( String synopsisLine: wrappedSynopsis ) {
+            synopsisFormatter.format("%" + headerLength + "s%s%n", header, synopsisLine);
+            header = "";
+        }
+
+        return synopsisBuilder.toString();
+    }
+
+    /**
+     * Gets detailed output about each argument type.
+     * @param argumentGroups Collection of program arguments sorted according to how they should be shown. 
+     * @return Detailed text about all arguments.
+     */
+    private String getDetailed( List<ArgumentDefinitionGroup> argumentGroups ) {
+        StringBuilder builder = new StringBuilder();
+
+        for( ArgumentDefinitionGroup argumentGroup: argumentGroups )
+            builder.append( getDetailForGroup( argumentGroup ) );
+
+        return builder.toString();
+    }
+
+    /**
+     * Gets a detailed description for a given argument group.
+     * @param argumentDefinitionGroup The group of argument definitions to render.
+     * @return A string giving detailed info about the contents of this group.
+     */
+    private String getDetailForGroup( ArgumentDefinitionGroup argumentDefinitionGroup ) {
+        if(argumentDefinitionGroup.allHidden())
+            return "";
+
+        StringBuilder builder = new StringBuilder();
+        Formatter formatter = new Formatter( builder );
+
+        if( argumentDefinitionGroup.groupName != null && argumentDefinitionGroup.argumentDefinitions.size() != 0 )
+            builder.append( String.format("%nArguments for %s:%n", argumentDefinitionGroup.groupName ) );
+
+        List<ArgumentDefinition> argumentDefinitions = new ArrayList<ArgumentDefinition>();
+        for(ArgumentDefinition argumentDefinition: argumentDefinitionGroup.argumentDefinitions) {
+            if(!argumentDefinition.isHidden)
+                argumentDefinitions.add(argumentDefinition);
+        }
+
+        // Try to fit the entire argument definition across the screen, but impose an arbitrary cap of 3/4 *
+        // LINE_WIDTH in case the length of the arguments gets out of control.
+        int argWidth = Math.min( findLongestArgumentCallingInfo(argumentDefinitions), (TextFormattingUtils.DEFAULT_LINE_WIDTH*3)/4 - FIELD_SEPARATION_WIDTH );
+        int docWidth = TextFormattingUtils.DEFAULT_LINE_WIDTH - argWidth - FIELD_SEPARATION_WIDTH;
+
+        for( ArgumentDefinition argumentDefinition: argumentDefinitions ) {
+            Iterator<String> wordWrappedArgs = TextFormattingUtils.wordWrap( getArgumentCallingInfo(argumentDefinition), argWidth ).iterator();
+            Iterator<String> wordWrappedDoc  = TextFormattingUtils.wordWrap( getArgumentDoc(argumentDefinition), docWidth ).iterator();
+
+            while( wordWrappedArgs.hasNext() || wordWrappedDoc.hasNext() ) {
+                String arg = wordWrappedArgs.hasNext() ? wordWrappedArgs.next() : "";
+                String doc = wordWrappedDoc.hasNext() ? wordWrappedDoc.next() : "";
+
+                String formatString = "%-" + argWidth + "s%" + FIELD_SEPARATION_WIDTH + "s%s%n";
+                formatter.format( formatString, arg, "", doc );
+            }
+        }
+
+        return builder.toString();
+    }
+
+    /**
+     * Gets a string indicating how this argument should be passed to the application.
+     * @param argumentDefinition Argument definition for which help should be printed.
+     * @return Calling information for this argument.
+     */
+    private String getArgumentCallingInfo( ArgumentDefinition argumentDefinition ) {
+        StringBuilder builder = new StringBuilder();
+        Formatter formatter = new Formatter( builder );
+
+        formatter.format(" ");
+        if( argumentDefinition.shortName != null )
+            formatter.format("-%s,", argumentDefinition.shortName);
+        formatter.format("--%s", argumentDefinition.fullName);
+        if( !argumentDefinition.isFlag )
+            formatter.format(" <%s>", argumentDefinition.fullName);
+
+        return builder.toString();
+    }
+
+    /**
+     * Gets a string of argument documentation.
+     * @param argumentDefinition Argument definition for which help should be printed.
+     * @return Brief description for this argument.
+     */
+    private String getArgumentDoc( ArgumentDefinition argumentDefinition ) {
+        StringBuilder builder = new StringBuilder();
+        builder.append(argumentDefinition.doc);
+        if( argumentDefinition.validOptions != null ) {
+            builder.append(" (");
+            builder.append(Utils.join("|",argumentDefinition.validOptions));
+            builder.append(")");
+        }
+        return builder.toString();
+    }
+
+    /**
+     * Crude implementation which finds the longest argument portion
+     * given a set of arguments.
+     * @param argumentDefinitions argument definitions to inspect.
+     * @return longest argument length.
+     */
+    private int findLongestArgumentCallingInfo( Collection<ArgumentDefinition> argumentDefinitions ) {
+        int longest = 0;
+        for( ArgumentDefinition argumentDefinition: argumentDefinitions ) {
+            String argumentText = getArgumentCallingInfo( argumentDefinition );
+            if( longest < argumentText.length() )
+                longest = argumentText.length();
+        }
+        return longest;
+    }
+
+    /**
+     * Extract the argument definition groups from the argument definitions and arrange them appropriately.
+     * For help, we want the arguments sorted as they are declared in the class.  However, required arguments
+     * should appear before optional arguments.
+     * @param argumentDefinitions Argument definitions from which to extract argument groups.
+     * @return A list of argument groups sorted in display order.
+     */
+    private List<ArgumentDefinitionGroup> prepareArgumentGroups( ArgumentDefinitions argumentDefinitions ) {
+        // Sort the list of argument definitions according to how they should be shown.
+        // Put the sorted results into a new cloned data structure.
+        Comparator<ArgumentDefinition> definitionComparator = new Comparator<ArgumentDefinition>() {
+            public int compare( ArgumentDefinition lhs, ArgumentDefinition rhs ) {
+                if( lhs.required && rhs.required ) return 0;
+                if( lhs.required ) return -1;
+                if( rhs.required ) return 1;
+                return 0;
+            }
+        };
+
+        List<ArgumentDefinitionGroup> argumentGroups = new ArrayList<ArgumentDefinitionGroup>();
+        for( ArgumentDefinitionGroup argumentGroup: argumentDefinitions.getArgumentDefinitionGroups() ) {
+            List<ArgumentDefinition> sortedDefinitions = new ArrayList<ArgumentDefinition>( argumentGroup.argumentDefinitions );
+            Collections.sort( sortedDefinitions, definitionComparator );
+            argumentGroups.add( new ArgumentDefinitionGroup(argumentGroup.groupName,sortedDefinitions) );
+        }
+
+        // Sort the argument groups themselves with main arguments first, followed by plugins sorted in name order.
+        Comparator<ArgumentDefinitionGroup> groupComparator = new Comparator<ArgumentDefinitionGroup>() {
+            public int compare( ArgumentDefinitionGroup lhs, ArgumentDefinitionGroup rhs ) {
+                if( lhs.groupName == null && rhs.groupName == null ) return 0;
+                if( lhs.groupName == null ) return -1;
+                if( rhs.groupName == null ) return 1;
+                return lhs.groupName.compareTo(rhs.groupName);
+            }
+        };
+        Collections.sort( argumentGroups, groupComparator );
+
+
+        return argumentGroups;
+    }
+
+    /**
+     * generateHeaderInformation
+     * <p/>
+     * <p/>
+     * Generate a standard header for the logger
+     *
+     * @param applicationDetails details of the application to run.
+     * @param parsedArgs the arguments passed in
+     */
+    public static void generateHeaderInformation(ApplicationDetails applicationDetails, Map<ArgumentMatchSource, ParsedArgs> parsedArgs) {
+
+        DateFormat dateFormat = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss");
+        java.util.Date date = new java.util.Date();
+
+        String barrier = createBarrier(applicationDetails.applicationHeader);
+
+        logger.info(barrier);
+        for (String headerLine : applicationDetails.applicationHeader)
+            logger.info(headerLine);
+        logger.debug("Current directory: " + System.getProperty("user.dir"));
+        for (Map.Entry<ArgumentMatchSource, ParsedArgs> entry: parsedArgs.entrySet()) {
+            ArgumentMatchSource matchSource = entry.getKey();
+            final String sourceName;
+            switch (matchSource.getType()) {
+                case CommandLine: sourceName = "Program"; break;
+                case Provider: sourceName = matchSource.getDescription(); break;
+                default: throw new RuntimeException("Unexpected argument match source type: " + matchSource.getType());
+            }
+
+            String output = sourceName + " Args: " + entry.getValue().getDescription();
+            logger.info(output);
+        }
+        logger.info(generateUserHelpData());
+        logger.info("Date/Time: " + dateFormat.format(date));
+        logger.info(barrier);
+
+        for(String attribution: applicationDetails.attribution)
+            logger.info(attribution);
+        logger.info(barrier);
+    }
+
+    /**
+     * Create the user-related help information.
+     * @return a non-null, non-empty String with the relevant information.
+     */
+    private static String generateUserHelpData() {
+	try {
+	    return "Executing as " +
+		System.getProperty("user.name") + "@" + InetAddress.getLocalHost().getHostName() +
+		" on " + System.getProperty("os.name") + " " + System.getProperty("os.version") +
+		" " + System.getProperty("os.arch") + "; " + System.getProperty("java.vm.name") +
+		" " + System.getProperty("java.runtime.version") + ".";
+	} catch (Exception e) {
+	    // don't fail
+	    return "";
+	}
+    }
+
+    /**
+     * Create a barrier to use to distinguish the header from the rest of the output.
+     * @param text A collection of lines to output as part of a header.
+     * @return A barrier consisting of the '-' character.
+     */
+    private static String createBarrier(List<String> text) {
+        int barrierWidth = 0;
+        for(String headerLine: text)
+            barrierWidth = Math.max(headerLine.length(),barrierWidth);
+        return String.format("%0" + barrierWidth + "d",0).replace('0','-');
+    }
+}
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/help/HelpUtils.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/help/HelpUtils.java
new file mode 100644
index 0000000..1011a49
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/help/HelpUtils.java
@@ -0,0 +1,64 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.utils.help;
+
+import org.broadinstitute.gatk.tools.walkers.annotator.interfaces.AnnotationType;
+import org.broadinstitute.gatk.tools.walkers.annotator.interfaces.GenotypeAnnotation;
+import org.broadinstitute.gatk.tools.walkers.annotator.interfaces.InfoFieldAnnotation;
+import org.broadinstitute.gatk.tools.walkers.annotator.interfaces.StandardAnnotation;
+import org.broadinstitute.gatk.utils.classloader.PluginManager;
+
+import java.util.List;
+
+/**
+ * NON-javadoc/doclet help-related utility methods should go here. Anything with a com.sun.javadoc.* dependency
+ * should go into DocletUtils for use only by doclets.
+ */
+public class HelpUtils {
+
+    /**
+     * Simple method to print a list of available annotations.
+     */
+    public static void listAnnotations() {
+        System.out.println("\nThis is a list of available Variant Annotations for use with tools such as UnifiedGenotyper, HaplotypeCaller and VariantAnnotator. Please see the Technical Documentation for more details about these annotations:");
+        System.out.println("http://www.broadinstitute.org/gatk/tooldocs/");
+        System.out.println("\nStandard annotations in the list below are marked with a '*'.");
+        List<Class<? extends InfoFieldAnnotation>> infoAnnotationClasses = new PluginManager<InfoFieldAnnotation>(InfoFieldAnnotation.class).getPlugins();
+        System.out.println("\nAvailable annotations for the VCF INFO field:");
+        for (int i = 0; i < infoAnnotationClasses.size(); i++)
+            System.out.println("\t" + (StandardAnnotation.class.isAssignableFrom(infoAnnotationClasses.get(i)) ? "*" : "") + infoAnnotationClasses.get(i).getSimpleName());
+        System.out.println();
+        List<Class<? extends GenotypeAnnotation>> genotypeAnnotationClasses = new PluginManager<GenotypeAnnotation>(GenotypeAnnotation.class).getPlugins();
+        System.out.println("\nAvailable annotations for the VCF FORMAT field:");
+        for (int i = 0; i < genotypeAnnotationClasses.size(); i++)
+            System.out.println("\t" + (StandardAnnotation.class.isAssignableFrom(genotypeAnnotationClasses.get(i)) ? "*" : "") + genotypeAnnotationClasses.get(i).getSimpleName());
+        System.out.println();
+        System.out.println("\nAvailable classes/groups of annotations:");
+        for ( Class c : new PluginManager<AnnotationType>(AnnotationType.class).getInterfaces() )
+            System.out.println("\t" + c.getSimpleName());
+        System.out.println();
+    }
+}
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/help/ResourceBundleExtractorDoclet.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/help/ResourceBundleExtractorDoclet.java
new file mode 100644
index 0000000..f28130b
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/help/ResourceBundleExtractorDoclet.java
@@ -0,0 +1,228 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.utils.help;
+
+import com.sun.javadoc.*;
+import org.broadinstitute.gatk.engine.walkers.Walker;
+import org.broadinstitute.gatk.utils.Utils;
+
+import java.io.*;
+import java.util.*;
+
+/**
+ * Extracts certain types of javadoc (specifically package and class descriptions) and makes them available
+ * to applications at runtime.
+ *
+ * @author mhanna
+ * @version 0.1
+ */
+public class ResourceBundleExtractorDoclet {
+    /**
+     * Taglet for the particular version number.
+     */
+    public static final String VERSION_TAGLET_NAME = "version";
+    public static final String SUMMARY_TAGLET_NAME = "help.summary";
+    public static final String DESCRIPTION_TAGLET_NAME = "help.description";
+
+    /**
+     * Maintains a collection of resources in memory as they're accumulated.
+     */
+    protected final Properties resourceText = new Properties();
+
+    /**
+     * Maintains a collection of classes that should really be documented.
+     */
+    protected final Set<String> undocumentedWalkers = new HashSet<String>();
+
+    protected String buildTimestamp = null, absoluteVersion = null;
+
+    /**
+     * Extracts the contents of certain types of javadoc and adds them to an XML file.
+     * @param rootDoc The documentation root.
+     * @return Whether the JavaDoc run succeeded.
+     * @throws IOException if output can't be written.
+     */
+    public static boolean start(RootDoc rootDoc) throws IOException {
+        ResourceBundleExtractorDoclet doclet = new ResourceBundleExtractorDoclet();
+        PrintStream out = doclet.loadData(rootDoc, true);
+        doclet.processDocs(rootDoc, out);
+        return true;
+    }
+
+    protected PrintStream loadData(RootDoc rootDoc, boolean overwriteResourcesFile) {
+        PrintStream out = System.out;
+
+        for(String[] options: rootDoc.options()) {
+            if(options[0].equals("-out")) {
+                try {
+                    loadExistingResourceFile(options[1], rootDoc);
+                    if ( overwriteResourcesFile )
+                        out = new PrintStream(options[1]);
+                } catch ( FileNotFoundException e ) {
+                    throw new RuntimeException(e);
+                } catch ( IOException e ) {
+                    throw new RuntimeException(e);
+                }
+            }
+            if(options[0].equals("-build-timestamp"))
+                buildTimestamp = options[1];
+            if (options[0].equals("-absolute-version"))
+                absoluteVersion = options[1];
+        }
+
+        resourceText.setProperty("build.timestamp",buildTimestamp);
+        return out;
+    }
+
+    protected void processDocs(RootDoc rootDoc, PrintStream out) {
+        // Cache packages as we see them, since there's no direct way to iterate over packages.
+        Set<PackageDoc> packages = new HashSet<PackageDoc>();
+
+        for(ClassDoc currentClass: rootDoc.classes()) {
+            PackageDoc containingPackage = currentClass.containingPackage();
+            packages.add(containingPackage);
+
+            if(isRequiredJavadocMissing(currentClass) && isWalker(currentClass))
+                undocumentedWalkers.add(currentClass.name());
+
+            renderHelpText(DocletUtils.getClassName(currentClass),currentClass);
+        }
+
+        for(PackageDoc currentPackage: packages)
+            renderHelpText(currentPackage.name(),currentPackage);
+
+        try {
+            resourceText.store(out,"Strings displayed by the GATK help system");
+        } catch ( FileNotFoundException e ) {
+            throw new RuntimeException(e);
+        } catch ( IOException e ) {
+            throw new RuntimeException(e);
+        }
+
+        // ASCII codes for making text blink
+        final String blink = "\u001B\u005B\u0035\u006D";
+        final String reset = "\u001B\u005B\u006D";
+
+        if(undocumentedWalkers.size() > 0)
+            Utils.warnUser(String.format("The following walkers are currently undocumented: %s%s%s", blink, Utils.join(" ",undocumentedWalkers), reset));
+    }
+
+    /**
+     * Validate the given options against options supported by this doclet.
+     * @param option Option to validate.
+     * @return Number of potential parameters; 0 if not supported.
+     */
+    public static int optionLength(String option) {
+        if(option.equals("-build-timestamp") || option.equals("-out") || option.equals("-absolute-version") ) {
+            return 2;
+        }
+        return 0;
+    }
+
+    /**
+     * Attempts to load the contents of the resource file named by resourceFileName into
+     * our in-memory resource collection resourceText. If the resource file doesn't exist,
+     * prints a notice to the user but does not throw an exception back to the calling method,
+     * since we'll just create a new resource file from scratch in that case.
+     * @param  resourceFileName  name of the resource file to attempt to load.
+     * @param  rootDoc           the documentation root.
+     * @throws IOException       if there is an I/O-related error other than FileNotFoundException
+     *                           while attempting to read the resource file.
+     */
+    private void loadExistingResourceFile( String resourceFileName, RootDoc rootDoc ) throws IOException {
+        try {
+            BufferedReader resourceFile = new BufferedReader(new FileReader(resourceFileName));
+            try {
+                resourceText.load(resourceFile);
+            }
+            finally {
+                resourceFile.close();
+            }
+        }
+        catch ( FileNotFoundException e ) {
+            rootDoc.printNotice("Resource file not found -- generating a new one from scratch.");
+        }
+    }
+
+    /**
+     * Determine whether a given class is a walker.
+     * @param classDoc the type of the given class.
+     * @return True if the class of the given name is a walker.  False otherwise.
+     */
+    protected static boolean isWalker(ClassDoc classDoc) {
+        return DocletUtils.assignableToClass(classDoc, Walker.class, true);
+    }
+
+    /**
+     * Is the javadoc for the given class missing?
+     * @param classDoc Class for which to inspect the JavaDoc.
+     * @return True if the JavaDoc is missing.  False otherwise.
+     */
+    private static boolean isRequiredJavadocMissing(ClassDoc classDoc) {
+        return classDoc.commentText().length() == 0 || classDoc.commentText().contains("Created by IntelliJ");
+    }
+
+    /**
+     * Renders all the help text required for a given name.
+     * @param elementName element name to use as the key
+     * @param element Doc element to process.
+     */
+    private void renderHelpText(String elementName, Doc element) {
+        StringBuilder summaryBuilder = new StringBuilder();
+        for(Tag tag: element.firstSentenceTags())
+             summaryBuilder.append(tag.text());
+        String summary = summaryBuilder.toString();
+        String description = element.commentText();
+
+        // this might seem unnecessary, but the GATK command line program uses this tag to determine the version when running
+        if(absoluteVersion != null)
+            resourceText.setProperty(String.format("%s.%s",elementName,VERSION_TAGLET_NAME),absoluteVersion);
+
+        // Write out an alternate element summary, if exists.
+        resourceText.setProperty(String.format("%s.%s",elementName,SUMMARY_TAGLET_NAME),formatText(summary));
+
+        // Write out an alternate description, if present.
+        resourceText.setProperty(String.format("%s.%s",elementName,DESCRIPTION_TAGLET_NAME),formatText(description));
+    }
+
+    /**
+     * Format text for consumption by the properties file.
+     * @param text Text to format.
+     * @return Formatted text; string trimmed, newlines removed.
+     */
+    private static String formatText(String text) {
+        Scanner scanner = new Scanner(text);
+        StringBuilder output = new StringBuilder();
+
+        while(scanner.hasNextLine()) {
+            if(output.length() > 0)
+                output.append(' ');
+            output.append(scanner.nextLine().trim());
+        }
+
+        return output.toString();    
+    }
+}
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/instrumentation/Sizeof.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/instrumentation/Sizeof.java
new file mode 100644
index 0000000..a31c498
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/instrumentation/Sizeof.java
@@ -0,0 +1,146 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.utils.instrumentation;
+
+import org.broadinstitute.gatk.utils.exceptions.ReviewedGATKException;
+
+import java.lang.instrument.Instrumentation;
+import java.lang.reflect.Array;
+import java.lang.reflect.Field;
+import java.lang.reflect.Modifier;
+import java.util.IdentityHashMap;
+
+/**
+ * A sizeof implementation for Java.  Relies on the Java instrumentation API, so
+ * it must be added as an agent to function properly.
+ *
+ * To run, add -javaagent:$STING_HOME/dist/StingUtils.jar as a command-line
+ * JVM argument.
+ *
+ * @author mhanna
+ * @version 0.1
+ */
+public class Sizeof {
+    /**
+     * Instrumentation object.  Registered by the JVM via the premain() method.
+     */
+    private static Instrumentation instrumentation;
+
+    /**
+     * Called by the JVM before the agent is started.
+     * @param args Arguments?
+     * @param inst Instrumentation object, used to perform instrumentation in the JVM.
+     */
+    public static void premain(String args, Instrumentation inst) {
+        instrumentation = inst;
+    }
+
+    /**
+     * Is this Sizeof operator enabled?  To enable, add the -javaagent directive listed in the class-level javadoc.
+     * @return True if sizeof() is enabled.  If false, any calls to utility methods of this class will throw an exception.
+     */
+    public static boolean isEnabled() {
+        return instrumentation != null;
+    }
+
+    /**
+     * Gets the size of the given object.  Retrieves the size for only this object; any reference fields in the object will only be
+     * counted as single pointers.
+     * @param o The object to sizeof().
+     * @return Gets the best possible approximation we can get of the size of the object in memory.  On Sun JVM, includes some object padding.
+     */
+    public static long getObjectSize(Object o) {
+        if(!isEnabled())
+            throw new ReviewedGATKException("Sizeof operator is currently disabled!  To enable, review the documentation in Sizeof.java");
+        return instrumentation.getObjectSize(o);
+    }
+
+    /**
+     * Gets the size of the given object, including the size of the objects to which this object refers.
+     * @param o The object to sizeof().
+     * @return Gets the best possible approximation we can get of the size of the object in memory, including all references within each object.
+     */
+    public static long getObjectGraphSize(Object o) {
+        if(!isEnabled())
+            throw new ReviewedGATKException("Sizeof operator is currently disabled!  To enable, review the documentation in Sizeof.java");
+        IdentityHashMap<Object,Object> objectsSeen = new IdentityHashMap<Object,Object>();
+        return getObjectGraphSize(o,objectsSeen);
+    }
+
+    /**
+     * The engine for walking the graph of all objects and their children.
+     * @param o The object to traverse.
+     * @param objectsSeen A list of all objects already seen.
+     * @return Gets the best possible approximation we can get of the size of the object in memory, including all references within each object.
+     */
+    private static long getObjectGraphSize(Object o,IdentityHashMap<Object,Object> objectsSeen) {
+        // Size of a null object itself (as opposed to the reference to the null object) is 0.
+        if(o == null)
+            return 0;
+        
+        // Don't allow repeated traversals of the same object.
+        if(objectsSeen.containsKey(o))
+            return 0;
+        objectsSeen.put(o,o);
+
+        // Get the size of the object itself, plus all contained primitives.
+        long totalSize = instrumentation.getObjectSize(o);
+
+        // Get the size of (non-primitive) array elements.
+        Class<?> classToInspect = o.getClass();
+        if(classToInspect.isArray()) {
+            if(!classToInspect.getComponentType().isPrimitive()) {
+                for(int i = 0; i < Array.getLength(o); i++)
+                    totalSize += getObjectGraphSize(Array.get(o,i),objectsSeen);
+            }
+        }
+
+        // Walk the descendents of each field of this class.  Be sure to avoid synthetic fields like this$0 -- these
+        // are back references to the parent of the object contained in the inner class.
+        // Potential BUG: Are there other types of synthetic fields we should be tracking?
+        while(classToInspect != null) {
+            for(Field field: classToInspect.getDeclaredFields()) {
+                if(field.getType().isPrimitive())
+                    continue;
+                if(Modifier.isStatic(field.getModifiers()))
+                    continue;
+                if(field.isSynthetic())
+                    continue;
+                field.setAccessible(true);
+                Object fieldValue;
+                try {
+                    fieldValue = field.get(o);
+                }
+                catch(IllegalAccessException ex) {
+                    throw new ReviewedGATKException("Unable to access field " + field.getName(),ex);
+                }
+                totalSize += getObjectGraphSize(fieldValue,objectsSeen);
+            }
+            classToInspect = classToInspect.getSuperclass();
+        }
+        return totalSize;
+    }
+}
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/interval/IntervalMergingRule.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/interval/IntervalMergingRule.java
new file mode 100644
index 0000000..3e5eb45
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/interval/IntervalMergingRule.java
@@ -0,0 +1,35 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.utils.interval;
+
+
+/**
+ * a class we use to determine the merging rules for intervals passed to the GATK
+ */
+public enum IntervalMergingRule {
+    ALL, // we merge both overlapping intervals and abutting intervals
+    OVERLAPPING_ONLY // We merge intervals that are overlapping, but NOT ones that only abut each other
+}
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/interval/IntervalSetRule.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/interval/IntervalSetRule.java
new file mode 100644
index 0000000..e9d20ee
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/interval/IntervalSetRule.java
@@ -0,0 +1,36 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.utils.interval;
+
+/**
+ * set operators for combining lists of intervals
+ */
+public enum IntervalSetRule {
+    /** Take the union of all intervals */
+    UNION,
+    /** Take the intersection of intervals (the subset that overlaps all intervals specified) */
+    INTERSECTION;
+}
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/interval/IntervalUtils.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/interval/IntervalUtils.java
new file mode 100644
index 0000000..7fffb12
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/interval/IntervalUtils.java
@@ -0,0 +1,890 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.utils.interval;
+
+import com.google.java.contract.Ensures;
+import com.google.java.contract.Requires;
+import htsjdk.samtools.util.Interval;
+import htsjdk.samtools.util.IntervalList;
+import htsjdk.samtools.SAMFileHeader;
+import org.apache.log4j.Logger;
+import htsjdk.tribble.Feature;
+import org.broadinstitute.gatk.utils.commandline.IntervalArgumentCollection;
+import org.broadinstitute.gatk.utils.commandline.IntervalBinding;
+import org.broadinstitute.gatk.engine.datasources.reference.ReferenceDataSource;
+import org.broadinstitute.gatk.utils.GenomeLoc;
+import org.broadinstitute.gatk.utils.GenomeLocParser;
+import org.broadinstitute.gatk.utils.GenomeLocSortedSet;
+import org.broadinstitute.gatk.utils.Utils;
+import org.broadinstitute.gatk.utils.collections.Pair;
+import org.broadinstitute.gatk.utils.exceptions.ReviewedGATKException;
+import org.broadinstitute.gatk.utils.exceptions.UserException;
+import org.broadinstitute.gatk.utils.text.XReadLines;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.*;
+
+/**
+ * Parse text representations of interval strings that
+ * can appear in GATK-based applications.
+ *
+ * @author mhanna
+ * @version 0.1
+ */
+public class IntervalUtils {
+    private static Logger logger = Logger.getLogger(IntervalUtils.class);
+
+    /**
+     * Turns a set of strings describing intervals into a parsed set of intervals.  Valid string elements can be files,
+     * intervals in samtools notation (chrA:B-C), or some combination of the above separated by semicolons.  Additionally,
+     * 'all' can be supplied to indicate all possible intervals, but 'all' must be exclusive of all other interval
+     * specifications.
+     *
+     * @param parser Genome loc parser.
+     * @param argList A list of strings containing interval data.
+     * @return an unsorted, unmerged representation of the given intervals.  Null is used to indicate that all intervals should be used.
+     */
+    public static List<GenomeLoc> parseIntervalArguments(GenomeLocParser parser, List<String> argList) {
+        List<GenomeLoc> rawIntervals = new ArrayList<GenomeLoc>();    // running list of raw GenomeLocs
+
+        if (argList != null) { // now that we can be in this function if only the ROD-to-Intervals was provided, we need to
+                               // ensure that the arg list isn't null before looping.
+            for (String argument : argList) {
+                rawIntervals.addAll(parseIntervalArguments(parser, argument));
+            }
+        }
+
+        return rawIntervals;
+    }
+
+    public static List<GenomeLoc> parseIntervalArguments(GenomeLocParser parser, String arg) {
+        List<GenomeLoc> rawIntervals = new ArrayList<GenomeLoc>();    // running list of raw GenomeLocs
+
+        if ( arg.indexOf(';') != -1 ) {
+            throw new UserException.BadArgumentValue("-L " + arg, "The legacy -L \"interval1;interval2\" syntax " +
+                                                     "is no longer supported. Please use one -L argument for each " +
+                                                     "interval or an interval file instead.");
+        }
+
+        // if any argument is 'unmapped', "parse" it to a null entry.  A null in this case means 'all the intervals with no alignment data'.
+        if (isUnmapped(arg))
+            rawIntervals.add(GenomeLoc.UNMAPPED);
+        // if it's a file, add items to raw interval list
+        else if (isIntervalFile(arg)) {
+            try {
+                rawIntervals.addAll(intervalFileToList(parser, arg));
+            }
+            catch ( UserException.MalformedGenomeLoc e ) {
+                throw e;
+            }
+            catch ( Exception e ) {
+                throw new UserException.MalformedFile(arg, "Interval file could not be parsed in any supported format.", e);
+            }
+        }
+        // otherwise treat as an interval -> parse and add to raw interval list
+        else {
+            rawIntervals.add(parser.parseGenomeLoc(arg));
+        }
+
+        return rawIntervals;
+    }
+
+    /**
+     * Read a file of genome locations to process. The file may be in BED, Picard,
+     * or GATK interval format.
+     *
+     * @param glParser   GenomeLocParser
+     * @param file_name  interval file
+     * @return List<GenomeLoc> List of Genome Locs that have been parsed from file
+     */
+    public static List<GenomeLoc> intervalFileToList(final GenomeLocParser glParser, final String file_name) {
+        // try to open file
+        File inputFile = new File(file_name);
+        List<GenomeLoc> ret = new ArrayList<GenomeLoc>();
+
+        // case: BED file
+        if ( file_name.toUpperCase().endsWith(".BED") ) {
+            // this is now supported in Tribble
+            throw new ReviewedGATKException("BED files must be parsed through Tribble; parsing them as intervals through the GATK engine is no longer supported");
+        }
+        else {
+            /**
+             * IF not a BED file:
+             * first try to read it as a Picard interval file since that's well structured
+             * we'll fail quickly if it's not a valid file.
+             */
+            boolean isPicardInterval = false;
+            try {
+                // Note: Picard will skip over intervals with contigs not in the sequence dictionary
+                IntervalList il = IntervalList.fromFile(inputFile);
+                isPicardInterval = true;
+
+                int nInvalidIntervals = 0;
+                for (Interval interval : il.getIntervals()) {
+                    if ( glParser.isValidGenomeLoc(interval.getSequence(), interval.getStart(), interval.getEnd(), true))
+                        ret.add(glParser.createGenomeLoc(interval.getSequence(), interval.getStart(), interval.getEnd(), true));
+                    else {
+                        nInvalidIntervals++;
+                    }
+                }
+                if ( nInvalidIntervals > 0 )
+                    logger.warn("Ignoring " + nInvalidIntervals + " invalid intervals from " + inputFile);
+            }
+
+            // if that didn't work, try parsing file as a GATK interval file
+            catch (Exception e) {
+                if ( isPicardInterval ) // definitely a picard file, but we failed to parse
+                    throw new UserException.CouldNotReadInputFile(inputFile, e);
+                else {
+                    try {
+                        XReadLines reader = new XReadLines(new File(file_name));
+                        for(String line: reader) {
+                            if ( line.trim().length() > 0 ) {
+                                ret.add(glParser.parseGenomeLoc(line));
+                            }
+                        }
+                        reader.close();
+                    }
+                    catch (IOException e2) {
+                        throw new UserException.CouldNotReadInputFile(inputFile, e2);
+                    }
+                }
+            }
+        }
+
+        return ret;
+    }
+
+    /**
+     * Returns true if the interval string is the "unmapped" interval
+     * @param interval Interval to check
+     * @return true if the interval string is the "unmapped" interval
+     */
+    public static boolean isUnmapped(String interval) {
+        return (interval != null && interval.trim().toLowerCase().equals("unmapped"));
+    }
+
+    /**
+     * merge two interval lists, using an interval set rule
+     * @param setOne a list of genomeLocs, in order (cannot be NULL)
+     * @param setTwo a list of genomeLocs, also in order (cannot be NULL)
+     * @param rule the rule to use for merging, i.e. union, intersection, etc
+     * @return a list, correctly merged using the specified rule
+     */
+    public static List<GenomeLoc> mergeListsBySetOperator(List<GenomeLoc> setOne, List<GenomeLoc> setTwo, IntervalSetRule rule) {
+        // shortcut, if either set is zero, return the other set
+        if (setOne == null || setOne.size() == 0 || setTwo == null || setTwo.size() == 0)
+            return Collections.unmodifiableList((setOne == null || setOne.size() == 0) ? setTwo : setOne);
+
+        // our master list, since we can't guarantee removal time in a generic list
+        LinkedList<GenomeLoc> retList = new LinkedList<GenomeLoc>();
+
+        // if we're set to UNION, just add them all
+        if (rule == null || rule == IntervalSetRule.UNION) {
+            retList.addAll(setOne);
+            retList.addAll(setTwo);
+            return Collections.unmodifiableList(retList);
+        }
+
+        // else we're INTERSECTION, create two indexes into the lists
+        int iOne = 0;
+        int iTwo = 0;
+
+        // merge the second into the first using the rule
+        while (iTwo < setTwo.size() && iOne < setOne.size())
+            // if the first list is ahead, drop items off the second until we overlap
+            if (setTwo.get(iTwo).isBefore(setOne.get(iOne)))
+                iTwo++;
+            // if the second is ahead, drop intervals off the first until we overlap
+            else if (setOne.get(iOne).isBefore(setTwo.get(iTwo)))
+                iOne++;
+            // we overlap, intersect the two intervals and add the result.  Then remove the interval that ends first.
+            else {
+                retList.add(setOne.get(iOne).intersect(setTwo.get(iTwo)));
+                if (setOne.get(iOne).getStop() < setTwo.get(iTwo).getStop()) iOne++;
+                else iTwo++;
+            }
+
+        //if we have an empty list, throw an exception.  If they specified intersection and there are no items, this is bad.
+        if (retList.size() == 0)
+                throw new UserException.BadInput("The INTERSECTION of your -L options produced no intervals.");
+
+        // we don't need to add the rest of remaining locations, since we know they don't overlap. return what we have
+        return Collections.unmodifiableList(retList);
+    }
+
+    /**
+     * Sorts and merges an interval list.  Multiple techniques are available for merging: ALL, which combines
+     * all overlapping and abutting intervals into an interval that spans the union of all covered bases, and
+     * OVERLAPPING_ONLY, which unions overlapping intervals but keeps abutting intervals separate.
+     *
+     * @param parser Genome loc parser for the intervals.
+     * @param intervals A collection of intervals to merge.
+     * @param mergingRule A descriptor for the type of merging to perform.
+     * @return A sorted, merged version of the intervals passed in.
+     */
+    public static GenomeLocSortedSet sortAndMergeIntervals(GenomeLocParser parser, List<GenomeLoc> intervals, IntervalMergingRule mergingRule) {
+        // Make a copy of the (potentially unmodifiable) list to be sorted
+        intervals = new ArrayList<GenomeLoc>(intervals);
+        // sort raw interval list
+        Collections.sort(intervals);
+        // now merge raw interval list
+        intervals = mergeIntervalLocations(intervals, mergingRule);
+
+        return GenomeLocSortedSet.createSetFromList(parser,intervals);
+    }
+
+    /**
+     * computes whether the test interval list is equivalent to master.  To be equivalent, test must
+     * contain GenomeLocs covering every base in master, exactly once.  Note that this algorithm
+     * assumes that master genomelocs are all discontiguous (i.e., we don't have locs like 1-3 and 4-6 but
+     * rather just 1-6).  In order to use this algorithm with contiguous genomelocs first merge them.  The algorithm
+     * doesn't assume that test has discontinuous genomelocs.
+     *
+     * Returns a null string if there are no differences, otherwise returns a string describing the difference
+     * (useful for UnitTests).  Assumes both lists are sorted
+     *
+     * @param masterArg sorted master genome locs
+     * @param testArg sorted test genome locs
+     * @return null string if there are no difference, otherwise a string describing the difference
+     */
+    public static String equateIntervals(List<GenomeLoc> masterArg, List<GenomeLoc> testArg) {
+        LinkedList<GenomeLoc> master = new LinkedList<GenomeLoc>(masterArg);
+        LinkedList<GenomeLoc> test = new LinkedList<GenomeLoc>(testArg);
+
+        while ( ! master.isEmpty() ) { // there's still unchecked bases in master
+            final GenomeLoc masterHead = master.pop();
+            final GenomeLoc testHead = test.pop();
+
+            if ( testHead.overlapsP(masterHead) ) {
+                // remove the parts of test that overlap master, and push the remaining
+                // parts onto master for further comparison.
+                for ( final GenomeLoc masterPart : Utils.reverse(masterHead.subtract(testHead)) ) {
+                    master.push(masterPart);
+                }
+            } else {
+                // testHead is incompatible with masterHead, so we must have extra bases in testHead
+                // that aren't in master
+                return "Incompatible locs detected masterHead=" + masterHead + ", testHead=" + testHead;
+            }
+        }
+
+        if ( test.isEmpty() ) // everything is equal
+            return null; // no differences
+        else
+            return "Remaining elements found in test: first=" + test.peek();
+    }
+
+
+    /**
+     * Check if string argument was intented as a file
+     * Accepted file extensions: .bed .list, .picard, .interval_list, .intervals.
+     * @param str token to identify as a filename.
+     * @return true if the token looks like a filename, or false otherwise.
+     */
+    public static boolean isIntervalFile(String str) {
+        return isIntervalFile(str, true);
+    }
+
+    /**
+     * Check if string argument was intented as a file
+     * Accepted file extensions: .bed .list, .picard, .interval_list, .intervals.
+     * @param str token to identify as a filename.
+     * @param checkExists if true throws an exception if the file doesn't exist.
+     * @return true if the token looks like a filename, or false otherwise.
+     */
+    public static boolean isIntervalFile(String str, boolean checkExists) {
+        // should we define list of file extensions as a public array somewhere?
+        // is regex or endsiwth better?
+        File file = new File(str);
+        if (str.toUpperCase().endsWith(".BED") || str.toUpperCase().endsWith(".LIST") ||
+                str.toUpperCase().endsWith(".PICARD") || str.toUpperCase().endsWith(".INTERVAL_LIST")
+                || str.toUpperCase().endsWith(".INTERVALS")) {
+            if (!checkExists)
+                return true;
+            else if (file.exists())
+                return true;
+            else
+                throw new UserException.CouldNotReadInputFile(file, "The interval file does not exist.");
+        }
+
+        if(file.exists())
+            throw new UserException.CouldNotReadInputFile(file, String.format("The interval file %s does not have one of " +
+                    "the supported extensions (.bed, .list, .picard, .interval_list, or .intervals). " +
+                    "Please rename your file with the appropriate extension. If %s is NOT supposed to be a file, " +
+                    "please move or rename the file at location %s", str, str, file.getAbsolutePath()));
+
+        else return false;
+    }
+
+    /**
+     * Returns a map of contig names with their sizes.
+     * @param reference The reference for the intervals.
+     * @return A map of contig names with their sizes.
+     */
+    public static Map<String, Integer> getContigSizes(File reference) {
+        ReferenceDataSource referenceSource = new ReferenceDataSource(reference);
+        List<GenomeLoc> locs = GenomeLocSortedSet.createSetFromSequenceDictionary(referenceSource.getReference().getSequenceDictionary()).toList();
+        Map<String, Integer> lengths = new LinkedHashMap<String, Integer>();
+        for (GenomeLoc loc: locs)
+            lengths.put(loc.getContig(), loc.size());
+        return lengths;
+    }
+
+    /**
+     * Splits an interval list into multiple files.
+     * @param fileHeader The sam file header.
+     * @param locs The genome locs to split.
+     * @param scatterParts The output interval lists to write to.
+     */
+    public static void scatterContigIntervals(SAMFileHeader fileHeader, List<GenomeLoc> locs, List<File> scatterParts) {
+
+	// Contract: must divide locs up so that each of scatterParts gets a sublist such that:
+	// (a) all locs concerning a particular contig go to the same part
+	// (b) locs are not split or combined, and remain in the same order (so scatterParts[0] + ... + scatterParts[n] == locs)
+
+	// Locs are already sorted.
+
+	long totalBases = 0;
+	for(GenomeLoc loc : locs)
+	    totalBases += loc.size();
+
+	long idealBasesPerPart = totalBases / scatterParts.size();
+	if(idealBasesPerPart == 0)
+	    throw new UserException.BadInput(String.format("Genome region is too short (%d bases) to split into %d parts", totalBases, scatterParts.size()));
+
+	// Find the indices in locs where we switch from one contig to the next.
+	ArrayList<Integer> contigStartLocs = new ArrayList<Integer>();
+	String prevContig = null;
+
+	for(int i = 0; i < locs.size(); ++i) {
+
+	    GenomeLoc loc = locs.get(i);
+	    if(prevContig == null || !loc.getContig().equals(prevContig))
+		contigStartLocs.add(i);
+	    prevContig = loc.getContig();
+
+	}
+
+	if(contigStartLocs.size() < scatterParts.size())
+	    throw new UserException.BadInput(String.format("Input genome region has too few contigs (%d) to split into %d parts", contigStartLocs.size(), scatterParts.size()));
+
+	long thisPartBases = 0;
+	int partIdx = 0;
+	IntervalList outList = new IntervalList(fileHeader);
+
+	for(int i = 0; i < locs.size(); ++i) {
+
+	    GenomeLoc loc = locs.get(i);
+	    thisPartBases += loc.getStop() - loc.getStart();
+
+	    outList.add(toInterval(loc, i));
+
+	    boolean partMustStop = false;
+
+	    if(partIdx < (scatterParts.size() - 1)) {
+
+		// If there are n contigs and n parts remaining then we must split here,
+		// otherwise we will run out of contigs.
+
+		int nextPart = partIdx + 1;
+		int nextPartMustStartBy = contigStartLocs.get(nextPart + (contigStartLocs.size() - scatterParts.size()));
+		if(i + 1 == nextPartMustStartBy)
+		    partMustStop = true;
+		
+	    }
+	    else if(i == locs.size() - 1) {
+
+		// We're done! Write the last scatter file.
+		partMustStop = true;
+
+	    }
+	    
+	    if(partMustStop || thisPartBases > idealBasesPerPart) {
+
+		// Ideally we would split here. However, we must make sure to do so
+		// on a contig boundary. Test always passes with partMustStop == true
+		// since that indicates we're at a contig boundary.
+
+		GenomeLoc nextLoc = null;
+		if((i + 1) < locs.size())
+		    nextLoc = locs.get(i+1);
+
+		if(nextLoc == null || !nextLoc.getContig().equals(loc.getContig())) {
+
+		    // Write out this part:
+		    outList.write(scatterParts.get(partIdx));
+
+		    // Reset. If this part ran long, leave the excess in thisPartBases
+		    // and the next will be a little shorter to compensate.
+		    outList = new IntervalList(fileHeader);
+		    thisPartBases -= idealBasesPerPart;
+		    ++partIdx;
+		    
+		}
+
+	    }
+
+	}
+
+    }
+
+    /**
+     * Splits an interval list into multiple sublists.
+     * @param locs The genome locs to split.
+     * @param splits The stop points for the genome locs returned by splitFixedIntervals.
+     * @return A list of lists of genome locs, split according to splits
+     */
+    public static List<List<GenomeLoc>> splitIntervalsToSubLists(List<GenomeLoc> locs, List<Integer> splits) {
+        int start = 0;
+        List<List<GenomeLoc>> sublists = new ArrayList<List<GenomeLoc>>(splits.size());
+        for (Integer stop: splits) {
+            List<GenomeLoc> curList = new ArrayList<GenomeLoc>();
+            for (int i = start; i < stop; i++)
+                curList.add(locs.get(i));
+            start = stop;
+            sublists.add(curList);
+        }
+
+        return sublists;
+    }
+
+
+    /**
+     * Splits an interval list into multiple files.
+     * @param fileHeader The sam file header.
+     * @param splits Pre-divided genome locs returned by splitFixedIntervals.
+     * @param scatterParts The output interval lists to write to.
+     */
+    public static void scatterFixedIntervals(SAMFileHeader fileHeader, List<List<GenomeLoc>> splits, List<File> scatterParts) {
+        if (splits.size() != scatterParts.size())
+            throw new UserException.BadArgumentValue("splits", String.format("Split points %d does not equal the number of scatter parts %d.", splits.size(), scatterParts.size()));
+
+        int fileIndex = 0;
+        int locIndex = 1;
+        for (final List<GenomeLoc> split : splits) {
+            IntervalList intervalList = new IntervalList(fileHeader);
+            for (final GenomeLoc loc : split)
+                intervalList.add(toInterval(loc, locIndex++));
+            intervalList.write(scatterParts.get(fileIndex++));
+        }
+    }
+
+    /**
+     * Splits the genome locs up by size.
+     * @param locs Genome locs to split.
+     * @param numParts Number of parts to split the locs into.
+     * @return The stop points to split the genome locs.
+     */
+    public static List<List<GenomeLoc>> splitFixedIntervals(List<GenomeLoc> locs, int numParts) {
+        if (locs.size() < numParts)
+            throw new UserException.BadArgumentValue("scatterParts", String.format("Cannot scatter %d locs into %d parts.", locs.size(), numParts));
+        final long locsSize = intervalSize(locs);
+        final List<Integer> splitPoints = new ArrayList<Integer>();
+        addFixedSplit(splitPoints, locs, locsSize, 0, locs.size(), numParts);
+        Collections.sort(splitPoints);
+        splitPoints.add(locs.size());
+        return splitIntervalsToSubLists(locs, splitPoints);
+    }
+
+    @Requires({"locs != null", "numParts > 0"})
+    @Ensures("result != null")
+    public static List<List<GenomeLoc>> splitLocusIntervals(List<GenomeLoc> locs, int numParts) {
+        // the ideal size of each split
+        final long bp = IntervalUtils.intervalSize(locs);
+        final long idealSplitSize = Math.max((long)Math.floor(bp / (1.0*numParts)), 1);
+
+        // algorithm:
+        // split = ()
+        // set size = 0
+        // pop the head H off locs.
+        // If size + size(H) < splitSize:
+        //      add H to split, continue
+        // If size + size(H) == splitSize:
+        //      done with split, put in splits, restart
+        // if size + size(H) > splitSize:
+        //      cut H into two pieces, first of which has splitSize - size bp
+        //      push both pieces onto locs, continue
+        // The last split is special -- when you have only one split left, it gets all of the remaining locs
+        // to deal with rounding issues
+        final List<List<GenomeLoc>> splits = new ArrayList<List<GenomeLoc>>(numParts);
+
+        LinkedList<GenomeLoc> locsLinkedList = new LinkedList<GenomeLoc>(locs);
+        while ( ! locsLinkedList.isEmpty() ) {
+            if ( splits.size() + 1 == numParts ) {
+                // the last one gets all of the remaining parts
+                splits.add(new ArrayList<GenomeLoc>(locsLinkedList));
+                locsLinkedList.clear();
+            } else {
+                final SplitLocusRecursive one = splitLocusIntervals1(locsLinkedList, idealSplitSize);
+                splits.add(one.split);
+                locsLinkedList = one.remaining;
+            }
+        }
+
+        return splits;
+    }
+
+    @Requires({"remaining != null", "!remaining.isEmpty()", "idealSplitSize > 0"})
+    @Ensures({"result != null"})
+    static SplitLocusRecursive splitLocusIntervals1(LinkedList<GenomeLoc> remaining, long idealSplitSize) {
+        final List<GenomeLoc> split = new ArrayList<GenomeLoc>();
+        long size = 0;
+
+        while ( ! remaining.isEmpty() ) {
+            GenomeLoc head = remaining.pop();
+            final long newSize = size + head.size();
+
+            if ( newSize == idealSplitSize ) {
+                split.add(head);
+                break; // we are done
+            } else if ( newSize > idealSplitSize ) {
+                final long remainingBp = idealSplitSize - size;
+                final long cutPoint = head.getStart() + remainingBp;
+                GenomeLoc[] parts = head.split((int)cutPoint);
+                remaining.push(parts[1]);
+                remaining.push(parts[0]);
+                // when we go around, head.size' = idealSplitSize - size
+                // so newSize' = splitSize + head.size' = size + (idealSplitSize - size) = idealSplitSize
+            } else {
+                split.add(head);
+                size = newSize;
+            }
+        }
+
+        return new SplitLocusRecursive(split, remaining);
+    }
+
+    /**
+     * Setup the intervals to be processed
+     */
+    public static GenomeLocSortedSet parseIntervalBindings(
+            final ReferenceDataSource referenceDataSource,
+            final List<IntervalBinding<Feature>> intervals,
+            final IntervalSetRule intervalSetRule, final IntervalMergingRule intervalMergingRule, final int intervalPadding,
+            final List<IntervalBinding<Feature>> excludeIntervals) {
+
+        Pair<GenomeLocSortedSet, GenomeLocSortedSet> includeExcludePair = parseIntervalBindingsPair(
+                referenceDataSource, intervals, intervalSetRule, intervalMergingRule, intervalPadding, excludeIntervals);
+
+        GenomeLocSortedSet includeSortedSet = includeExcludePair.getFirst();
+        GenomeLocSortedSet excludeSortedSet = includeExcludePair.getSecond();
+
+        if (excludeSortedSet != null) {
+            return includeSortedSet.subtractRegions(excludeSortedSet);
+        } else {
+            return includeSortedSet;
+        }
+    }
+
+    public static GenomeLocSortedSet parseIntervalArguments(final ReferenceDataSource referenceDataSource, IntervalArgumentCollection argCollection) {
+        GenomeLocSortedSet intervals = null;
+
+        // return if no interval arguments at all
+        if ( argCollection.intervals == null && argCollection.excludeIntervals == null )
+            return intervals;
+
+        // Note that the use of '-L all' is no longer supported.
+
+        // if include argument isn't given, create new set of all possible intervals
+
+        final Pair<GenomeLocSortedSet, GenomeLocSortedSet> includeExcludePair = IntervalUtils.parseIntervalBindingsPair(
+                referenceDataSource,
+                argCollection.intervals,
+                argCollection.intervalSetRule, argCollection.intervalMerging, argCollection.intervalPadding,
+                argCollection.excludeIntervals);
+
+        final GenomeLocSortedSet includeSortedSet = includeExcludePair.getFirst();
+        final GenomeLocSortedSet excludeSortedSet = includeExcludePair.getSecond();
+
+        // if no exclude arguments, can return parseIntervalArguments directly
+        if ( excludeSortedSet == null )
+            intervals = includeSortedSet;
+
+            // otherwise there are exclude arguments => must merge include and exclude GenomeLocSortedSets
+        else {
+            intervals = includeSortedSet.subtractRegions(excludeSortedSet);
+
+            // logging messages only printed when exclude (-XL) arguments are given
+            final long toPruneSize = includeSortedSet.coveredSize();
+            final long toExcludeSize = excludeSortedSet.coveredSize();
+            final long intervalSize = intervals.coveredSize();
+            logger.info(String.format("Initial include intervals span %d loci; exclude intervals span %d loci", toPruneSize, toExcludeSize));
+            logger.info(String.format("Excluding %d loci from original intervals (%.2f%% reduction)",
+                    toPruneSize - intervalSize, (toPruneSize - intervalSize) / (0.01 * toPruneSize)));
+        }
+
+        logger.info(String.format("Processing %d bp from intervals", intervals.coveredSize()));
+        return intervals;
+    }
+
+    public static Pair<GenomeLocSortedSet, GenomeLocSortedSet> parseIntervalBindingsPair(
+            final ReferenceDataSource referenceDataSource,
+            final List<IntervalBinding<Feature>> intervals,
+            final IntervalSetRule intervalSetRule, final IntervalMergingRule intervalMergingRule, final int intervalPadding,
+            final List<IntervalBinding<Feature>> excludeIntervals) {
+        GenomeLocParser genomeLocParser = new GenomeLocParser(referenceDataSource.getReference());
+
+        // if include argument isn't given, create new set of all possible intervals
+        GenomeLocSortedSet includeSortedSet = ((intervals == null || intervals.size() == 0) ?
+                GenomeLocSortedSet.createSetFromSequenceDictionary(referenceDataSource.getReference().getSequenceDictionary()) :
+                loadIntervals(intervals, intervalSetRule, intervalMergingRule, intervalPadding, genomeLocParser));
+
+        GenomeLocSortedSet excludeSortedSet = null;
+        if (excludeIntervals != null && excludeIntervals.size() > 0) {
+            excludeSortedSet = loadIntervals(excludeIntervals, IntervalSetRule.UNION, intervalMergingRule, 0, genomeLocParser);
+        }
+        return new Pair<GenomeLocSortedSet, GenomeLocSortedSet>(includeSortedSet, excludeSortedSet);
+    }
+
+    public static GenomeLocSortedSet loadIntervals(
+            final List<IntervalBinding<Feature>> intervalBindings,
+            final IntervalSetRule rule, final IntervalMergingRule intervalMergingRule, final int padding,
+            final GenomeLocParser genomeLocParser) {
+        List<GenomeLoc> allIntervals = new ArrayList<GenomeLoc>();
+        for ( IntervalBinding intervalBinding : intervalBindings) {
+            @SuppressWarnings("unchecked")
+            List<GenomeLoc> intervals = intervalBinding.getIntervals(genomeLocParser);
+
+            if ( intervals.isEmpty() ) {
+                logger.warn("The interval file " + intervalBinding.getSource() + " contains no intervals that could be parsed.");
+            }
+
+            if ( padding > 0 ) {
+                intervals = getIntervalsWithFlanks(genomeLocParser, intervals, padding);
+            }
+
+            allIntervals = mergeListsBySetOperator(intervals, allIntervals, rule);
+        }
+
+        return sortAndMergeIntervals(genomeLocParser, allIntervals, intervalMergingRule);
+    }
+
+    private final static class SplitLocusRecursive {
+        final List<GenomeLoc> split;
+        final LinkedList<GenomeLoc> remaining;
+
+        @Requires({"split != null", "remaining != null"})
+        private SplitLocusRecursive(final List<GenomeLoc> split, final LinkedList<GenomeLoc> remaining) {
+            this.split = split;
+            this.remaining = remaining;
+        }
+    }
+
+    public static List<GenomeLoc> flattenSplitIntervals(List<List<GenomeLoc>> splits) {
+        final List<GenomeLoc> locs = new ArrayList<GenomeLoc>();
+        for ( final List<GenomeLoc> split : splits )
+            locs.addAll(split);
+        return locs;
+    }
+
+    private static void addFixedSplit(List<Integer> splitPoints, List<GenomeLoc> locs, long locsSize, int startIndex, int stopIndex, int numParts) {
+        if (numParts < 2)
+            return;
+        int halfParts = (numParts + 1) / 2;
+        Pair<Integer, Long> splitPoint = getFixedSplit(locs, locsSize, startIndex, stopIndex, halfParts, numParts - halfParts);
+        int splitIndex = splitPoint.first;
+        long splitSize = splitPoint.second;
+        splitPoints.add(splitIndex);
+        addFixedSplit(splitPoints, locs, splitSize, startIndex, splitIndex, halfParts);
+        addFixedSplit(splitPoints, locs, locsSize - splitSize, splitIndex, stopIndex, numParts - halfParts);
+    }
+
+    private static Pair<Integer, Long> getFixedSplit(List<GenomeLoc> locs, long locsSize, int startIndex, int stopIndex, int minLocs, int maxLocs) {
+        int splitIndex = startIndex;
+        long splitSize = 0;
+        for (int i = 0; i < minLocs; i++) {
+            splitSize += locs.get(splitIndex).size();
+            splitIndex++;
+        }
+        long halfSize = locsSize / 2;
+        while (splitIndex < (stopIndex - maxLocs) && splitSize < halfSize) {
+            splitSize += locs.get(splitIndex).size();
+            splitIndex++;
+        }
+        return new Pair<Integer, Long>(splitIndex, splitSize);
+    }
+
+    /**
+     * Converts a GenomeLoc to a picard interval.
+     * @param loc The GenomeLoc.
+     * @param locIndex The loc index for use in the file.
+     * @return The picard interval.
+     */
+    private static htsjdk.samtools.util.Interval toInterval(GenomeLoc loc, int locIndex) {
+        return new htsjdk.samtools.util.Interval(loc.getContig(), loc.getStart(), loc.getStop(), false, "interval_" + locIndex);
+    }
+
+    /**
+     * merge a list of genome locs that may be overlapping, returning the list of unique genomic locations
+     *
+     * @param raw the unchecked genome loc list
+     * @param rule the merging rule we're using
+     *
+     * @return the list of merged locations
+     */
+    public static List<GenomeLoc> mergeIntervalLocations(final List<GenomeLoc> raw, IntervalMergingRule rule) {
+        if (raw.size() <= 1)
+            return Collections.unmodifiableList(raw);
+        else {
+            ArrayList<GenomeLoc> merged = new ArrayList<GenomeLoc>();
+            Iterator<GenomeLoc> it = raw.iterator();
+            GenomeLoc prev = it.next();
+            while (it.hasNext()) {
+                GenomeLoc curr = it.next();
+                if (prev.overlapsP(curr)) {
+                    prev = prev.merge(curr);
+                } else if (prev.contiguousP(curr) && (rule == null || rule == IntervalMergingRule.ALL)) {
+                    prev = prev.merge(curr);
+                } else {
+                    merged.add(prev);
+                    prev = curr;
+                }
+            }
+            merged.add(prev);
+            return Collections.unmodifiableList(merged);
+        }
+    }
+
+    public static long intervalSize(final List<GenomeLoc> locs) {
+        long size = 0;
+        for ( final GenomeLoc loc : locs )
+            size += loc.size();
+        return size;
+    }
+
+    public static void writeFlankingIntervals(File reference, File inputIntervals, File flankingIntervals, int basePairs) {
+        ReferenceDataSource referenceDataSource = new ReferenceDataSource(reference);
+        GenomeLocParser parser = new GenomeLocParser(referenceDataSource.getReference());
+        List<GenomeLoc> originalList = intervalFileToList(parser, inputIntervals.getAbsolutePath());
+
+        if (originalList.isEmpty())
+            throw new UserException.MalformedFile(inputIntervals, "File contains no intervals");
+
+        List<GenomeLoc> flankingList = getFlankingIntervals(parser, originalList, basePairs);
+
+        if (flankingList.isEmpty())
+            throw new UserException.MalformedFile(inputIntervals, "Unable to produce any flanks for the intervals");
+
+        SAMFileHeader samFileHeader = new SAMFileHeader();
+        samFileHeader.setSequenceDictionary(referenceDataSource.getReference().getSequenceDictionary());
+        IntervalList intervalList = new IntervalList(samFileHeader);
+        int i = 0;
+        for (GenomeLoc loc: flankingList)
+            intervalList.add(toInterval(loc, ++i));
+        intervalList.write(flankingIntervals);
+    }
+
+    /**
+     * Returns a list of intervals between the passed int locs. Does not extend UNMAPPED locs.
+     * @param parser A genome loc parser for creating the new intervals
+     * @param locs Original genome locs
+     * @param basePairs Number of base pairs on each side of loc
+     * @return The list of intervals between the locs
+     */
+    public static List<GenomeLoc> getFlankingIntervals(final GenomeLocParser parser, final List<GenomeLoc> locs, final int basePairs) {
+        List<GenomeLoc> sorted = sortAndMergeIntervals(parser, locs, IntervalMergingRule.ALL).toList();
+
+        if (sorted.size() == 0)
+            return Collections.emptyList();
+
+        LinkedHashMap<String, List<GenomeLoc>> locsByContig = splitByContig(sorted);
+        List<GenomeLoc> expanded = new ArrayList<GenomeLoc>();
+        for (Map.Entry<String, List<GenomeLoc>> contig: locsByContig.entrySet()) {
+            List<GenomeLoc> contigLocs = contig.getValue();
+            int contigLocsSize = contigLocs.size();
+
+            GenomeLoc startLoc, stopLoc;
+
+            // Create loc at start of the list
+            startLoc = parser.createGenomeLocAtStart(contigLocs.get(0), basePairs);
+            if (startLoc != null)
+                expanded.add(startLoc);
+
+            // Create locs between each loc[i] and loc[i+1]
+            for (int i = 0; i < contigLocsSize - 1; i++) {
+                stopLoc = parser.createGenomeLocAtStop(contigLocs.get(i), basePairs);
+                startLoc = parser.createGenomeLocAtStart(contigLocs.get(i + 1), basePairs);
+                if (stopLoc.getStop() + 1 >= startLoc.getStart()) {
+                    // NOTE: This is different than GenomeLoc.merge()
+                    // merge() returns a loc which covers the entire range of stop and start,
+                    // possibly returning positions inside loc(i) or loc(i+1)
+                    // We want to make sure that the start of the stopLoc is used, and the stop of the startLoc
+                    GenomeLoc merged = parser.createGenomeLoc(
+                            stopLoc.getContig(), stopLoc.getStart(), startLoc.getStop());
+                    expanded.add(merged);
+                } else {
+                    expanded.add(stopLoc);
+                    expanded.add(startLoc);
+                }
+            }
+
+            // Create loc at the end of the list
+            stopLoc = parser.createGenomeLocAtStop(contigLocs.get(contigLocsSize - 1), basePairs);
+            if (stopLoc != null)
+                expanded.add(stopLoc);
+        }
+        return expanded;
+    }
+
+    /**
+     * Returns a list of intervals between the passed int locs. Does not extend UNMAPPED locs.
+     * @param parser A genome loc parser for creating the new intervals
+     * @param locs Original genome locs
+     * @param basePairs Number of base pairs on each side of loc
+     * @return The list of intervals between the locs
+     */
+    public static List<GenomeLoc> getIntervalsWithFlanks(final GenomeLocParser parser, final List<GenomeLoc> locs, final int basePairs) {
+
+        if (locs.size() == 0)
+            return Collections.emptyList();
+
+        final List<GenomeLoc> expanded = new ArrayList<GenomeLoc>();
+        for ( final GenomeLoc loc : locs ) {
+            expanded.add(parser.createPaddedGenomeLoc(loc, basePairs));
+        }
+
+        return sortAndMergeIntervals(parser, expanded, IntervalMergingRule.ALL).toList();
+    }
+
+    private static LinkedHashMap<String, List<GenomeLoc>> splitByContig(List<GenomeLoc> sorted) {
+        LinkedHashMap<String, List<GenomeLoc>> splits = new LinkedHashMap<String, List<GenomeLoc>>();
+        GenomeLoc last = null;
+        List<GenomeLoc> contigLocs = null;
+        for (GenomeLoc loc: sorted) {
+            if (GenomeLoc.isUnmapped(loc))
+                continue;
+            if (last == null || !last.onSameContig(loc)) {
+                contigLocs = new ArrayList<GenomeLoc>();
+                splits.put(loc.getContig(), contigLocs);
+            }
+            contigLocs.add(loc);
+            last = loc;
+        }
+        return splits;
+    }
+}
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/io/FileExtension.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/io/FileExtension.java
new file mode 100644
index 0000000..e099a45
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/io/FileExtension.java
@@ -0,0 +1,37 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.utils.io;
+
+import java.io.File;
+
+public interface FileExtension {
+    /**
+     * Returns a clone of the FileExtension with a new path.
+     * @param path New path.
+     * @return New FileExtension
+     */
+    public File withPath(String path);
+}
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/io/HardThresholdingOutputStream.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/io/HardThresholdingOutputStream.java
new file mode 100644
index 0000000..1d041b6
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/io/HardThresholdingOutputStream.java
@@ -0,0 +1,56 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.utils.io;
+
+import org.apache.commons.io.output.ThresholdingOutputStream;
+
+import java.io.IOException;
+
+/**
+ * An output stream which stops at the threshold
+ * instead of potentially triggering early.
+ */
+public abstract class HardThresholdingOutputStream extends ThresholdingOutputStream {
+    protected HardThresholdingOutputStream(int threshold) {
+        super(threshold);
+    }
+
+    @Override
+    public void write(byte[] b) throws IOException {
+        write(b, 0, b.length);
+    }
+
+    @Override
+    public void write(byte[] b, int off, int len) throws IOException {
+        int remaining = this.getThreshold() - (int)this.getByteCount();
+        if (!isThresholdExceeded() && len > remaining) {
+            super.write(b, off, remaining);
+            super.write(b, off + remaining, len - remaining);
+        } else {
+            super.write(b, off, len);
+        }
+    }
+}
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/io/IOUtils.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/io/IOUtils.java
new file mode 100644
index 0000000..7defcea
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/io/IOUtils.java
@@ -0,0 +1,575 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.utils.io;
+
+import org.apache.commons.io.FileUtils;
+import org.apache.commons.io.FilenameUtils;
+import org.apache.commons.io.LineIterator;
+import org.apache.commons.lang.StringUtils;
+import org.apache.log4j.Logger;
+import org.broadinstitute.gatk.utils.exceptions.ReviewedGATKException;
+import org.broadinstitute.gatk.utils.exceptions.GATKException;
+import org.broadinstitute.gatk.utils.exceptions.UserException;
+
+import java.io.*;
+import java.nio.ByteBuffer;
+import java.nio.ByteOrder;
+import java.util.*;
+
+public class IOUtils {
+    private static Logger logger = Logger.getLogger(IOUtils.class);
+    private static final File DEV_DIR = new File("/dev");
+
+    /**
+     * Checks if the temp directory has been setup and throws an exception if they user hasn't set it correctly.
+     *
+     * @param tempDir Temporary directory.
+     */
+    public static void checkTempDir(File tempDir) {
+        if (isDefaultTempDir(tempDir))
+            throw new UserException.BadTmpDir("java.io.tmpdir must be explicitly set");
+        if (!tempDir.exists() && !tempDir.mkdirs())
+            throw new UserException.BadTmpDir("Could not create directory: " + tempDir.getAbsolutePath());
+    }
+
+    /**
+     * Returns true if the directory is a default temporary directory.
+     * @param tempDir the directory to check.
+     * @return true if the directory is a default temporary directory.
+     */
+    public static boolean isDefaultTempDir(File tempDir) {
+        String tempDirPath = tempDir.getAbsolutePath();
+        // Keeps the user from leaving the temp directory as the default, and on Macs from having pluses
+        // in the path which can cause problems with the Google Reflections library.
+        // see also: http://benjchristensen.com/2009/09/22/mac-osx-10-6-java-java-io-tmpdir/
+        return (tempDirPath.startsWith("/var/folders/") || (tempDirPath.equals("/tmp")) || (tempDirPath.equals("/tmp/")));
+    }
+
+    /**
+     * Creates a temp directory with the prefix and optional suffix.
+     *
+     * @param prefix       Prefix for the directory name.
+     * @param suffix       Optional suffix for the directory name.
+     * @return The created temporary directory.
+     */
+    public static File tempDir(String prefix, String suffix) {
+        return tempDir(prefix, suffix, null);
+    }
+
+    /**
+     * Creates a temp directory with the prefix and optional suffix.
+     *
+     * @param prefix        Prefix for the directory name.
+     * @param suffix        Optional suffix for the directory name.
+     * @param tempDirParent Parent directory for the temp directory.
+     * @return The created temporary directory.
+     */
+    public static File tempDir(String prefix, String suffix, File tempDirParent) {
+        try {
+            if (tempDirParent == null)
+                tempDirParent = FileUtils.getTempDirectory();
+            if (!tempDirParent.exists() && !tempDirParent.mkdirs())
+                throw new UserException.BadTmpDir("Could not create temp directory: " + tempDirParent);
+            File temp = File.createTempFile(prefix, suffix, tempDirParent);
+            if (!temp.delete())
+                throw new UserException.BadTmpDir("Could not delete sub file: " + temp.getAbsolutePath());
+            if (!temp.mkdir())
+                throw new UserException.BadTmpDir("Could not create sub directory: " + temp.getAbsolutePath());
+            return absolute(temp);
+        } catch (IOException e) {
+            throw new UserException.BadTmpDir(e.getMessage());
+        }
+    }
+
+    /**
+     * Writes content to a temp file and returns the path to the temporary file.
+     *
+     * @param content   to write.
+     * @param prefix    Prefix for the temp file.
+     * @param suffix    Suffix for the temp file.
+     * @return the path to the temp file.
+     */
+    public static File writeTempFile(String content, String prefix, String suffix) {
+        return writeTempFile(content, prefix, suffix, null);
+    }
+
+    /**
+     * Writes content to a temp file and returns the path to the temporary file.
+     *
+     * @param content   to write.
+     * @param prefix    Prefix for the temp file.
+     * @param suffix    Suffix for the temp file.
+     * @param directory Directory for the temp file.
+     * @return the path to the temp file.
+     */
+    public static File writeTempFile(String content, String prefix, String suffix, File directory) {
+        try {
+            File tempFile = absolute(File.createTempFile(prefix, suffix, directory));
+            FileUtils.writeStringToFile(tempFile, content);
+            return tempFile;
+        } catch (IOException e) {
+            throw new UserException.BadTmpDir(e.getMessage());
+        }
+    }
+
+    /**
+     * Waits for NFS to propagate a file creation, imposing a timeout.
+     *
+     * Based on Apache Commons IO FileUtils.waitFor()
+     *
+     * @param file    The file to wait for.
+     * @param seconds The maximum time in seconds to wait.
+     * @return true if the file exists
+     */
+    public static boolean waitFor(File file, int seconds) {
+        return waitFor(Collections.singletonList(file), seconds).isEmpty();
+    }
+
+    /**
+     * Waits for NFS to propagate a file creation, imposing a timeout.
+     *
+     * Based on Apache Commons IO FileUtils.waitFor()
+     *
+     * @param files   The list of files to wait for.
+     * @param seconds The maximum time in seconds to wait.
+     * @return Files that still do not exists at the end of the timeout, or a empty list if all files exists.
+     */
+    public static List<File> waitFor(Collection<File> files, int seconds) {
+        long timeout = 0;
+        long tick = 0;
+        List<File> missingFiles = new ArrayList<File>();
+        for (File file : files)
+            if (!file.exists())
+                missingFiles.add(file);
+
+        while (!missingFiles.isEmpty() && timeout <= seconds) {
+            if (tick >= 10) {
+                tick = 0;
+                timeout++;
+            }
+            tick++;
+            try {
+                Thread.sleep(100);
+            } catch (InterruptedException ignore) {
+            }
+            List<File> newMissingFiles = new ArrayList<File>();
+            for (File file : missingFiles)
+                if (!file.exists())
+                    newMissingFiles.add(file);
+            missingFiles = newMissingFiles;
+        }
+        return missingFiles;
+    }
+
+    /**
+     * Returns the directory at the number of levels deep.
+     * For example 2 levels of /path/to/dir will return /path/to
+     *
+     * @param dir   Directory path.
+     * @param level how many levels deep from the root.
+     * @return The path to the parent directory that is level-levels deep.
+     */
+    public static File dirLevel(File dir, int level) {
+        List<File> directories = new ArrayList<File>();
+        File parentDir = absolute(dir);
+        while (parentDir != null) {
+            directories.add(0, parentDir);
+            parentDir = parentDir.getParentFile();
+        }
+        if (directories.size() <= level)
+            return directories.get(directories.size() - 1);
+        else
+            return directories.get(level);
+    }
+
+    /**
+     * Returns the sub path rooted at the parent.
+     *
+     * @param parent The parent directory.
+     * @param path   The sub path to append to the parent, if the path is not absolute.
+     * @return The absolute path to the file in the parent dir if the path was not absolute, otherwise the original path.
+     */
+    public static File absolute(File parent, String path) {
+        return absolute(parent, new File(path));
+    }
+
+    /**
+     * Returns the sub path rooted at the parent.
+     *
+     * @param parent The parent directory.
+     * @param file   The sub path to append to the parent, if the path is not absolute.
+     * @return The absolute path to the file in the parent dir if the path was not absolute, otherwise the original path.
+     */
+    public static File absolute(File parent, File file) {
+        String newPath;
+        if (file.isAbsolute())
+            newPath = absolutePath(file);
+        else
+            newPath = absolutePath(new File(parent, file.getPath()));
+        return replacePath(file, newPath);
+    }
+
+    /**
+     * A mix of getCanonicalFile and getAbsoluteFile that returns the
+     * absolute path to the file without deferencing symbolic links.
+     *
+     * @param file the file.
+     * @return the absolute path to the file.
+     */
+    public static File absolute(File file) {
+        return replacePath(file, absolutePath(file));
+    }
+
+    private static String absolutePath(File file) {
+        File fileAbs = file.getAbsoluteFile();
+        LinkedList<String> names = new LinkedList<String>();
+        while (fileAbs != null) {
+            String name = fileAbs.getName();
+            fileAbs = fileAbs.getParentFile();
+
+            if (".".equals(name)) {
+                /* skip */
+
+                /* TODO: What do we do for ".."?
+              } else if (name == "..") {
+
+                CentOS tcsh says use getCanonicalFile:
+                ~ $ mkdir -p test1/test2
+                ~ $ ln -s test1/test2 test3
+                ~ $ cd test3/..
+                ~/test1 $
+
+                Mac bash says keep going with getAbsoluteFile:
+                ~ $ mkdir -p test1/test2
+                ~ $ ln -s test1/test2 test3
+                ~ $ cd test3/..
+                ~ $
+
+                For now, leave it and let the shell figure it out.
+                */
+            } else {
+                names.add(0, name);
+            }
+        }
+
+        return ("/" + StringUtils.join(names, "/"));
+    }
+
+    private static File replacePath(File file, String path) {
+        if (file instanceof FileExtension)
+            return ((FileExtension)file).withPath(path);
+        if (!File.class.equals(file.getClass()))
+            throw new GATKException("Sub classes of java.io.File must also implement FileExtension");
+        return new File(path);
+    }
+
+    /**
+     * Returns the last lines of the file.
+     * NOTE: This is only safe to run on smaller files!
+     *
+     * @param file  File to read.
+     * @param count Maximum number of lines to return.
+     * @return The last count lines from file.
+     * @throws IOException When unable to read the file.
+     */
+    public static List<String> tail(File file, int count) throws IOException {
+        LinkedList<String> tailLines = new LinkedList<String>();
+        FileReader reader = new FileReader(file);
+        try {
+            LineIterator iterator = org.apache.commons.io.IOUtils.lineIterator(reader);
+            int lineCount = 0;
+            while (iterator.hasNext()) {
+                String line = iterator.nextLine();
+                lineCount++;
+                if (lineCount > count)
+                    tailLines.removeFirst();
+                tailLines.offer(line);
+            }
+        } finally {
+            org.apache.commons.io.IOUtils.closeQuietly(reader);
+        }
+        return tailLines;
+    }
+
+    /**
+     * Tries to delete a file. Emits a warning if the file
+     * is not a special file and was unable to be deleted.
+     *
+     * @param file File to delete.
+     * @return true if the file was deleted.
+     */
+    public static boolean tryDelete(File file) {
+        if (isSpecialFile(file)) {
+            logger.debug("Not trying to delete " + file);
+            return false;
+        }
+        boolean deleted = FileUtils.deleteQuietly(file);
+        if (deleted)
+            logger.debug("Deleted " + file);
+        else if (file.exists())
+            logger.warn("Unable to delete " + file);
+        return deleted;
+    }
+
+    /**
+     * Writes the an embedded resource to a temp file.
+     * File is not scheduled for deletion and must be cleaned up by the caller.
+     * @param resource Embedded resource.
+     * @return Path to the temp file with the contents of the resource.
+     */
+    public static File writeTempResource(Resource resource) {
+        File temp;
+        try {
+            temp = File.createTempFile(FilenameUtils.getBaseName(resource.getPath()) + ".", "." + FilenameUtils.getExtension(resource.getPath()));
+        } catch (IOException e) {
+            throw new UserException.BadTmpDir(e.getMessage());
+        }
+        writeResource(resource, temp);
+        return temp;
+    }
+
+    /**
+     * Writes the an embedded resource to a file.
+     * File is not scheduled for deletion and must be cleaned up by the caller.
+     * @param resource Embedded resource.
+     * @param file File path to write.
+     */
+    public static void writeResource(Resource resource, File file) {
+        String path = resource.getPath();
+        InputStream inputStream = resource.getResourceContentsAsStream();
+        OutputStream outputStream = null;
+        try {
+            outputStream = FileUtils.openOutputStream(file);
+            org.apache.commons.io.IOUtils.copy(inputStream, outputStream);
+        } catch (IOException e) {
+            throw new GATKException(String.format("Unable to copy resource '%s' to '%s'", path, file), e);
+        } finally {
+            org.apache.commons.io.IOUtils.closeQuietly(inputStream);
+            org.apache.commons.io.IOUtils.closeQuietly(outputStream);
+        }
+    }
+
+    /**
+     * Returns a file throwing a UserException if the file cannot be read.
+     * @param path File path
+     * @return LineIterator
+     */
+    public static LineIterator lineIterator(String path) {
+        return lineIterator(new File(path));
+    }
+
+    /**
+     * Returns a file throwing a UserException if the file cannot be read.
+     * @param file File
+     * @return LineIterator
+     */
+    public static LineIterator lineIterator(File file) {
+        try {
+            return FileUtils.lineIterator(file);
+        } catch (IOException e) {
+            throw new UserException.CouldNotReadInputFile(file, e);
+        }
+
+    }
+
+    /**
+     * Returns true if the file is a special file.
+     * @param file File path to check.
+     * @return true if the file is a special file.
+     */
+    public static boolean isSpecialFile(File file) {
+        return file != null && (file.getAbsolutePath().startsWith("/dev/") || file.equals(DEV_DIR));
+    }
+
+    /**
+     * Reads the entirety of the given file into a byte array. Uses a read buffer size of 4096 bytes.
+     *
+     * @param source File to read
+     * @return The contents of the file as a byte array
+     */
+    public static byte[] readFileIntoByteArray ( File source ) {
+        return readFileIntoByteArray(source, 4096);
+    }
+
+    /**
+     * Reads the entirety of the given file into a byte array using the requested read buffer size.
+     *
+     * @param source File to read
+     * @param readBufferSize Number of bytes to read in at one time
+     * @return The contents of the file as a byte array
+     */
+    public static byte[] readFileIntoByteArray ( File source, int readBufferSize ) {
+        if ( source == null ) {
+            throw new ReviewedGATKException("Source file was null");
+        }
+
+        byte[] fileContents;
+
+        try {
+            fileContents = readStreamIntoByteArray(new FileInputStream(source), readBufferSize);
+        }
+        catch ( FileNotFoundException e ) {
+            throw new UserException.CouldNotReadInputFile(source, e);
+        }
+
+        if ( fileContents.length != source.length() ) {
+            throw new UserException.CouldNotReadInputFile(String.format("Unable to completely read file %s: read only %d/%d bytes",
+                                                          source.getAbsolutePath(), fileContents.length, source.length()));
+        }
+
+        return fileContents;
+    }
+
+    /**
+     * Reads all data from the given stream into a byte array. Uses a read buffer size of 4096 bytes.
+     *
+     * @param in Stream to read data from
+     * @return The contents of the stream as a byte array
+     */
+    public static byte[] readStreamIntoByteArray ( InputStream in ) {
+        return readStreamIntoByteArray(in, 4096);
+    }
+
+    /**
+     * Reads all data from the given stream into a byte array using the requested read buffer size.
+     *
+     * @param in Stream to read data from
+     * @param readBufferSize Number of bytes to read in at one time
+     * @return The contents of the stream as a byte array
+     */
+    public static byte[] readStreamIntoByteArray ( InputStream in, int readBufferSize ) {
+        if ( in == null ) {
+            throw new ReviewedGATKException("Input stream was null");
+        }
+        else if ( readBufferSize <= 0 ) {
+            throw new ReviewedGATKException("Read buffer size must be > 0");
+        }
+
+        // Use a fixed-size buffer for each read, but a dynamically-growing buffer
+        // to hold the accumulated contents of the file/stream:
+        byte[] readBuffer = new byte[readBufferSize];
+        ByteArrayOutputStream fileBuffer = new ByteArrayOutputStream(readBufferSize * 4);
+
+        try {
+            try {
+                int currentBytesRead;
+
+                while ( (currentBytesRead = in.read(readBuffer, 0, readBuffer.length)) >= 0 ) {
+                    fileBuffer.write(readBuffer, 0, currentBytesRead);
+                }
+            }
+            finally {
+                in.close();
+            }
+        }
+        catch ( IOException e ) {
+            throw new UserException.CouldNotReadInputFile("I/O error reading from input stream", e);
+        }
+
+        return fileBuffer.toByteArray();
+    }
+
+    /**
+     * Writes the given array of bytes to a file
+     *
+     * @param bytes Data to write
+     * @param destination File to write the data to
+     */
+    public static void writeByteArrayToFile ( byte[] bytes, File destination ) {
+        if ( destination == null ) {
+            throw new ReviewedGATKException("Destination file was null");
+        }
+
+        try {
+            writeByteArrayToStream(bytes, new FileOutputStream(destination));
+        }
+        catch ( FileNotFoundException e ) {
+            throw new UserException.CouldNotCreateOutputFile(destination, e);
+        }
+    }
+
+    /**
+     * Writes the given array of bytes to a stream
+     *
+     * @param bytes Data to write
+     * @param out Stream to write the data to
+     */
+    public static void writeByteArrayToStream ( byte[] bytes, OutputStream out ) {
+        if ( bytes == null || out == null ) {
+            throw new ReviewedGATKException("Data to write or output stream was null");
+        }
+
+        try {
+            try {
+                out.write(bytes);
+            }
+            finally {
+                out.close();
+            }
+        }
+        catch ( IOException e ) {
+            throw new UserException.CouldNotCreateOutputFile("I/O error writing to output stream", e);
+        }
+    }
+
+    /**
+     * Determines the uncompressed size of a GZIP file. Uses the GZIP ISIZE field in the last
+     * 4 bytes of the file to get this information.
+     *
+     * @param gzipFile GZIP-format file whose uncompressed size to determine
+     * @return The uncompressed size (in bytes) of the GZIP file
+     */
+    public static int getGZIPFileUncompressedSize ( File gzipFile ) {
+        if ( gzipFile == null ) {
+            throw new ReviewedGATKException("GZIP file to examine was null");
+        }
+
+        try {
+            // The GZIP ISIZE field holds the uncompressed size of the compressed data.
+            // It occupies the last 4 bytes of any GZIP file:
+            RandomAccessFile in = new RandomAccessFile(gzipFile, "r");
+            in.seek(gzipFile.length() - 4);
+            byte[] sizeBytes = new byte[4];
+            in.read(sizeBytes, 0, 4);
+
+            ByteBuffer byteBuf = ByteBuffer.wrap(sizeBytes);
+            byteBuf.order(ByteOrder.LITTLE_ENDIAN);   // The GZIP spec mandates little-endian byte order
+            int uncompressedSize = byteBuf.getInt();
+
+            // If the size read in is negative, we've overflowed our signed integer:
+            if ( uncompressedSize < 0 ) {
+                throw new UserException.CouldNotReadInputFile(String.format("Cannot accurately determine the uncompressed size of file %s " +
+                                                               "because it's either larger than %d bytes or the GZIP ISIZE field is corrupt",
+                                                               gzipFile.getAbsolutePath(), Integer.MAX_VALUE));
+            }
+
+            return uncompressedSize;
+        }
+        catch ( IOException e ) {
+            throw new UserException.CouldNotReadInputFile(gzipFile, e);
+        }
+    }
+}
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/io/Resource.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/io/Resource.java
new file mode 100644
index 0000000..abebe52
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/io/Resource.java
@@ -0,0 +1,91 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.utils.io;
+
+import java.io.File;
+import java.io.InputStream;
+
+/**
+ * Stores a resource by path and a relative class.
+ */
+public class Resource {
+    private final String path;
+    private final Class<?> relativeClass;
+
+    /**
+     * Create a resource with a path and a relative class.
+     * @param path Relative or absolute path to the class.
+     * @param relativeClass Relative class to use as a class loader and for a relative package.
+     *
+     * If the relative class is null then the system classloader will be used and the path must be absolute.
+     */
+    public Resource(String path, Class<?> relativeClass) {
+        this.path = path;
+        this.relativeClass = relativeClass;
+    }
+
+    public Class<?> getRelativeClass() {
+        return relativeClass;
+    }
+
+    public String getPath() {
+        return path;
+    }
+
+    public String getFullPath() {
+        if (relativeClass == null)
+            return path;
+        if (new File(path).isAbsolute())
+            return path;
+        return String.format("%s%s%s",
+                relativeClass.getPackage().getName().replace('.', File.separatorChar),
+                File.separator,
+                path);
+    }
+
+    /**
+     * Get the contents of this resource as an InputStream
+     * @throws IllegalArgumentException if resource cannot be read
+     * @return an input stream that will read the contents of this resource
+     */
+    public InputStream getResourceContentsAsStream() {
+        final Class<?> clazz = getRelativeClass();
+
+        final InputStream inputStream;
+        if (clazz == null) {
+            inputStream = ClassLoader.getSystemResourceAsStream(path);
+            if (inputStream == null)
+                throw new IllegalArgumentException("Resource not found: " + path);
+        } else {
+            inputStream = clazz.getResourceAsStream(path);
+            if (inputStream == null)
+                throw new IllegalArgumentException("Resource not found relative to " + clazz + ": " + path);
+
+        }
+
+        return inputStream;
+    }
+}
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/jna/clibrary/JNAUtils.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/jna/clibrary/JNAUtils.java
new file mode 100644
index 0000000..0c14ffa
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/jna/clibrary/JNAUtils.java
@@ -0,0 +1,59 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.utils.jna.clibrary;
+
+import com.sun.jna.Platform;
+
+/**
+ * Collection of functions that are in the standard CLibrary but are associated with different headers on different platforms.
+ */
+public class JNAUtils {
+    /**
+     * Defined in different places on different systems, this is currently 256 on mac and 64 everywhere else.
+     */
+    public static final int MAXHOSTNAMELEN;
+
+    /**
+     * Maximum path length.
+     */
+    public static final int MAXPATHLEN = 1024;
+
+    static {
+      int maxhostnamelen = 64;
+      if (Platform.isMac())
+         maxhostnamelen = 256;
+      MAXHOSTNAMELEN = maxhostnamelen;
+    }
+
+    /**
+     * Converts a non-zero int to true, otherwise false.
+     * @param val int to check.
+     * @return true if val is non-zero.
+     */
+    public static boolean toBoolean(int val) {
+        return val != 0;
+    }
+}
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/jna/clibrary/LibC.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/jna/clibrary/LibC.java
new file mode 100644
index 0000000..dd2d7e7
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/jna/clibrary/LibC.java
@@ -0,0 +1,200 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.utils.jna.clibrary;
+
+import com.sun.jna.LastErrorException;
+import com.sun.jna.Native;
+import com.sun.jna.NativeLong;
+import com.sun.jna.Structure;
+import com.sun.jna.ptr.NativeLongByReference;
+
+/**
+ * Sparse port of the Standard C Library libc -lc.
+ */
+ at SuppressWarnings("unused")
+public class LibC {
+
+    static {
+        Native.register("c");
+    }
+
+    /** Operation not permitted */
+    public static final int EPERM = 1;
+
+    /** No such file or directory */
+    public static final int ENOENT = 2;
+
+    /** No such process */
+    public static final int ESRCH = 3;
+
+    /** Interrupted system call */
+    public static final int EINTR = 4;
+
+    /** I/O error */
+    public static final int EIO = 5;
+
+    /** No such device or address */
+    public static final int ENXIO = 6;
+
+    /** Argument list too long */
+    public static final int E2BIG = 7;
+
+    /** Exec format error */
+    public static final int ENOEXEC = 8;
+
+    /** Bad file number */
+    public static final int EBADF = 9;
+
+    /** No child processes */
+    public static final int ECHILD = 10;
+
+    /** Try again */
+    public static final int EAGAIN = 11;
+
+    /** Out of memory */
+    public static final int ENOMEM = 12;
+
+    /** Permission denied */
+    public static final int EACCES = 13;
+
+    /** Bad address */
+    public static final int EFAULT = 14;
+
+    /** Block device required */
+    public static final int ENOTBLK = 15;
+
+    /** Device or resource busy */
+    public static final int EBUSY = 16;
+
+    /** File exists */
+    public static final int EEXIST = 17;
+
+    /** Cross-device link */
+    public static final int EXDEV = 18;
+
+    /** No such device */
+    public static final int ENODEV = 19;
+
+    /** Not a directory */
+    public static final int ENOTDIR = 20;
+
+    /** Is a directory */
+    public static final int EISDIR = 21;
+
+    /** Invalid argument */
+    public static final int EINVAL = 22;
+
+    /** File table overflow */
+    public static final int ENFILE = 23;
+
+    /** Too many open files */
+    public static final int EMFILE = 24;
+
+    /** Not a typewriter */
+    public static final int ENOTTY = 25;
+
+    /** Text file busy */
+    public static final int ETXTBSY = 26;
+
+    /** File too large */
+    public static final int EFBIG = 27;
+
+    /** No space left on device */
+    public static final int ENOSPC = 28;
+
+    /** Illegal seek */
+    public static final int ESPIPE = 29;
+
+    /** Read-only file system */
+    public static final int EROFS = 30;
+
+    /** Too many links */
+    public static final int EMLINK = 31;
+
+    /** Broken pipe */
+    public static final int EPIPE = 32;
+
+    /** Math argument out of domain of func */
+    public static final int EDOM = 33;
+
+    /** Math result not representable */
+    public static final int ERANGE = 34;
+
+    /**
+     * Inserts or resets the environment variable name in the current environment list.  If the variable name does not exist
+     * in the list, it is inserted with the given value.  If the variable does exist, the argument overwrite is tested; if overwrite is zero, the
+     * variable is not reset, otherwise it is reset to the given value.
+     * @param name the environment variable name
+     * @param value the given value
+     * @param overwrite if overwrite is zero, the variable is not reset, otherwise it is reset to the given value
+     * @return the value 0 if successful; otherwise the value -1 is returned and the global variable errno is set to indicate the error.
+     * @throws LastErrorException [ENOMEM] The function failed because it was unable to allocate memory for the environment.
+     */
+    public static native int setenv(String name, String value, int overwrite) throws LastErrorException;
+
+    /**
+     * Obtains the current value of the environment variable, name.
+     * @param name the environment variable name
+     * @return the value of the environment variable as a NUL-terminated string.  If the variable name is not in the current environment, NULL is returned.
+     */
+    public static native String getenv(String name);
+
+    /**
+     * The unsetenv() function deletes all instances of the variable name pointed to by name from the list.  Note that only the variable name
+     * (e.g., "NAME") should be given; "NAME=value" will not work.
+     * @param name the environment variable name
+     * @return the value 0 if successful; otherwise the value -1 is returned and the global variable errno is set to indicate the error.
+     * @throws LastErrorException The function failed.
+     */
+    public static native int unsetenv(String name) throws LastErrorException;
+
+    public static class timeval extends Structure {
+        public static class ByReference extends timeval implements Structure.ByReference {
+        }
+
+        public static class ByValue extends timeval implements Structure.ByValue {
+        }
+
+        public NativeLong tv_sec;
+        public NativeLong tv_usec;
+    }
+
+    /**
+     * The time() function returns the value of time in seconds since 0 hours, 0 minutes, 0 seconds, January 1, 1970, Coordinated Universal Time, without including leap seconds.  If an error occurs, time() returns the value (time_t)-1.
+     * The return value is also stored in *tloc, provided that t is non-null.
+     * @param t the value of time in seconds,  provided that t is non-null.
+     * @return the value of time in seconds
+     */
+    public static native NativeLong time(NativeLongByReference t);
+
+    /**
+     * Returns the difference between two calendar times, (time1 - time0), expressed in seconds.
+     * @param time1 Time 1
+     * @param time0 Time 0
+     * @return the difference between two calendar times, (time1 - time0), expressed in seconds.
+     */
+    public static native double difftime(NativeLong time1, NativeLong time0);
+}
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/jna/drmaa/v1_0/JnaJobInfo.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/jna/drmaa/v1_0/JnaJobInfo.java
new file mode 100644
index 0000000..1a99bfa
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/jna/drmaa/v1_0/JnaJobInfo.java
@@ -0,0 +1,101 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.utils.jna.drmaa.v1_0;
+
+import org.ggf.drmaa.DrmaaException;
+import org.ggf.drmaa.JobInfo;
+
+import java.util.Map;
+
+/**
+ * JNA mapping from Java to C DRMAA binding.
+ */
+public class JnaJobInfo implements JobInfo {
+
+    private final String jobId;
+    private final Map<String, String> rusage;
+    private final boolean hasExited;
+    private final int exitStatus;
+    private final boolean hasSignaled;
+    private final String terminatingSignal;
+    private final boolean hasCoreDump;
+    private final boolean wasAborted;
+            
+    public JnaJobInfo(String jobId, Map<String, String> rusage, boolean hasExited, int exitStatus, boolean hasSignaled, String terminatingSignal, boolean hasCoreDump, boolean wasAborted) {
+        this.jobId = jobId;
+        this.rusage = rusage;
+        this.hasExited = hasExited;
+        this.exitStatus = exitStatus;
+        this.hasSignaled = hasSignaled;
+        this.terminatingSignal = terminatingSignal;
+        this.hasCoreDump = hasCoreDump;
+        this.wasAborted = wasAborted;
+    }
+
+    @Override
+    public String getJobId() throws DrmaaException {
+        return this.jobId;
+    }
+
+    @Override
+    public Map getResourceUsage() throws DrmaaException {
+        return rusage;
+    }
+
+    @Override
+    public boolean hasExited() throws DrmaaException {
+        return hasExited;
+    }
+
+    @Override
+    public int getExitStatus() throws DrmaaException {
+        if (!hasExited)
+            throw new IllegalStateException("job has not exited");
+        return exitStatus;
+    }
+
+    @Override
+    public boolean hasSignaled() throws DrmaaException {
+        return hasSignaled;
+    }
+
+    @Override
+    public String getTerminatingSignal() throws DrmaaException {
+        if (!hasSignaled)
+            throw new IllegalStateException("job has not signaled");
+        return terminatingSignal;
+    }
+
+    @Override
+    public boolean hasCoreDump() throws DrmaaException {
+        return hasCoreDump;
+    }
+
+    @Override
+    public boolean wasAborted() throws DrmaaException {
+        return wasAborted;
+    }
+}
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/jna/drmaa/v1_0/JnaJobTemplate.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/jna/drmaa/v1_0/JnaJobTemplate.java
new file mode 100644
index 0000000..b8add99
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/jna/drmaa/v1_0/JnaJobTemplate.java
@@ -0,0 +1,316 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.utils.jna.drmaa.v1_0;
+
+import com.sun.jna.Pointer;
+import org.ggf.drmaa.*;
+
+import java.util.*;
+
+/**
+ * JNA mapping from Java to C DRMAA binding.
+ */
+public class JnaJobTemplate implements JobTemplate {
+    private final JnaSession session;
+    private final Pointer jt;
+
+    public JnaJobTemplate(JnaSession session, Pointer jt) {
+        this.session = session;
+        this.jt = jt;
+    }
+
+    public Pointer getPointer() {
+        return jt;
+    }
+
+    @Override
+    public void setRemoteCommand(String s) throws DrmaaException {
+        JnaSession.setAttribute(jt, LibDrmaa.DRMAA_REMOTE_COMMAND, s);
+    }
+
+    @Override
+    public String getRemoteCommand() throws DrmaaException {
+        return JnaSession.getAttribute(jt, LibDrmaa.DRMAA_REMOTE_COMMAND);
+    }
+
+    @SuppressWarnings("unchecked")
+    @Override
+    public void setArgs(List list) throws DrmaaException {
+        JnaSession.setVectorAttribute(jt, LibDrmaa.DRMAA_V_ARGV, list);
+    }
+
+    @Override
+    public List getArgs() throws DrmaaException {
+        return JnaSession.getVectorAttribute(jt, LibDrmaa.DRMAA_V_ARGV);
+    }
+
+    @Override
+    public void setJobSubmissionState(int state) throws DrmaaException {
+        String stateString;
+        if (state == JobTemplate.HOLD_STATE)
+            stateString = LibDrmaa.DRMAA_SUBMISSION_STATE_HOLD;
+        else if (state == JobTemplate.ACTIVE_STATE)
+            stateString = LibDrmaa.DRMAA_SUBMISSION_STATE_ACTIVE;
+        else
+            throw new InvalidAttributeValueException("jobSubmissionState attribute is invalid");
+        JnaSession.setAttribute(jt, LibDrmaa.DRMAA_JS_STATE, stateString);
+    }
+
+    @Override
+    public int getJobSubmissionState() throws DrmaaException {
+        int state;
+        String stateString = JnaSession.getAttribute(jt, LibDrmaa.DRMAA_JS_STATE);
+        if (LibDrmaa.DRMAA_SUBMISSION_STATE_HOLD.equals(stateString))
+            state = JobTemplate.HOLD_STATE;
+        else if (LibDrmaa.DRMAA_SUBMISSION_STATE_ACTIVE.equals(stateString))
+            state = JobTemplate.ACTIVE_STATE;
+        else
+            throw new InvalidAttributeValueException("jobSubmissionState attribute is invalid");
+        return state;
+    }
+
+    @SuppressWarnings("unchecked")
+    @Override
+    public void setJobEnvironment(Map env) throws DrmaaException {
+        JnaSession.setVectorAttribute(jt, LibDrmaa.DRMAA_V_ENV, JnaSession.mapToCollection(env));
+    }
+
+    @SuppressWarnings("unchecked")
+    @Override
+    public Map getJobEnvironment() throws DrmaaException {
+        return JnaSession.collectionToMap(JnaSession.getVectorAttribute(jt, LibDrmaa.DRMAA_V_ENV));
+    }
+
+    @Override
+    public void setWorkingDirectory(String s) throws DrmaaException {
+        JnaSession.setAttribute(jt, LibDrmaa.DRMAA_WD, s);
+    }
+
+    @Override
+    public String getWorkingDirectory() throws DrmaaException {
+        return JnaSession.getAttribute(jt, LibDrmaa.DRMAA_WD);
+    }
+
+    @Override
+    public void setJobCategory(String s) throws DrmaaException {
+        JnaSession.setAttribute(jt, LibDrmaa.DRMAA_JOB_CATEGORY, s);
+    }
+
+    @Override
+    public String getJobCategory() throws DrmaaException {
+        return JnaSession.getAttribute(jt, LibDrmaa.DRMAA_JOB_CATEGORY);
+    }
+
+    @Override
+    public void setNativeSpecification(String s) throws DrmaaException {
+        JnaSession.setAttribute(jt, LibDrmaa.DRMAA_NATIVE_SPECIFICATION, s);
+    }
+
+    @Override
+    public String getNativeSpecification() throws DrmaaException {
+        return JnaSession.getAttribute(jt, LibDrmaa.DRMAA_NATIVE_SPECIFICATION);
+    }
+
+    @SuppressWarnings("unchecked")
+    @Override
+    public void setEmail(Set set) throws DrmaaException {
+        JnaSession.setVectorAttribute(jt, LibDrmaa.DRMAA_V_EMAIL, set);
+    }
+
+    @SuppressWarnings("unchecked")
+    @Override
+    public Set getEmail() throws DrmaaException {
+        return new LinkedHashSet<String>(JnaSession.getVectorAttribute(jt, LibDrmaa.DRMAA_V_EMAIL));
+    }
+
+    @Override
+    public void setBlockEmail(boolean b) throws DrmaaException {
+        JnaSession.setAttribute(jt, LibDrmaa.DRMAA_BLOCK_EMAIL, b ? "1" : "0");
+    }
+
+    @Override
+    public boolean getBlockEmail() throws DrmaaException {
+        return "1".equals(JnaSession.getAttribute(jt, LibDrmaa.DRMAA_BLOCK_EMAIL));
+    }
+
+    @Override
+    public void setStartTime(PartialTimestamp partialTimestamp) throws DrmaaException {
+        JnaSession.setPartialTime(jt, LibDrmaa.DRMAA_START_TIME, partialTimestamp);
+    }
+
+    @Override
+    public PartialTimestamp getStartTime() throws DrmaaException {
+        return JnaSession.getPartialTime(jt, LibDrmaa.DRMAA_START_TIME);
+    }
+
+    @Override
+    public void setJobName(String s) throws DrmaaException {
+        JnaSession.setAttribute(jt, LibDrmaa.DRMAA_JOB_NAME, s);
+    }
+
+    @Override
+    public String getJobName() throws DrmaaException {
+        return JnaSession.getAttribute(jt, LibDrmaa.DRMAA_JOB_NAME);
+    }
+
+    @Override
+    public void setInputPath(String s) throws DrmaaException {
+        JnaSession.setAttribute(jt, LibDrmaa.DRMAA_INPUT_PATH, s);
+    }
+
+    @Override
+    public String getInputPath() throws DrmaaException {
+        return JnaSession.getAttribute(jt, LibDrmaa.DRMAA_INPUT_PATH);
+    }
+
+    @Override
+    public void setOutputPath(String s) throws DrmaaException {
+        JnaSession.setAttribute(jt, LibDrmaa.DRMAA_OUTPUT_PATH, s);
+    }
+
+    @Override
+    public String getOutputPath() throws DrmaaException {
+        return JnaSession.getAttribute(jt, LibDrmaa.DRMAA_OUTPUT_PATH);
+    }
+
+    @Override
+    public void setErrorPath(String s) throws DrmaaException {
+        JnaSession.setAttribute(jt, LibDrmaa.DRMAA_ERROR_PATH, s);
+    }
+
+    @Override
+    public String getErrorPath() throws DrmaaException {
+        return JnaSession.getAttribute(jt, LibDrmaa.DRMAA_ERROR_PATH);
+    }
+
+    @Override
+    public void setJoinFiles(boolean b) throws DrmaaException {
+        JnaSession.setAttribute(jt, LibDrmaa.DRMAA_JOIN_FILES, b ? "y" : "n");
+    }
+
+    @Override
+    public boolean getJoinFiles() throws DrmaaException {
+        return "y".equals(JnaSession.getAttribute(jt, LibDrmaa.DRMAA_JOIN_FILES));
+    }
+
+    @Override
+    public void setTransferFiles(FileTransferMode fileTransferMode) throws DrmaaException {
+        StringBuilder buf = new StringBuilder();
+
+        if (fileTransferMode.getInputStream())
+            buf.append('i');
+
+        if (fileTransferMode.getOutputStream())
+            buf.append('o');
+
+        if (fileTransferMode.getErrorStream())
+            buf.append('e');
+
+        JnaSession.setAttribute(jt, LibDrmaa.DRMAA_TRANSFER_FILES, buf.toString());
+    }
+
+    @Override
+    public FileTransferMode getTransferFiles() throws DrmaaException {
+        String mode = JnaSession.getAttribute(jt, LibDrmaa.DRMAA_TRANSFER_FILES);
+
+        if (mode == null)
+            return null;
+
+        FileTransferMode fileTransferMode = new FileTransferMode();
+        fileTransferMode.setInputStream(mode.indexOf('i') >= 0);
+        fileTransferMode.setOutputStream(mode.indexOf('o') >= 0);
+        fileTransferMode.setErrorStream(mode.indexOf('e') >= 0);
+        return fileTransferMode;
+    }
+
+    @Override
+    public void setDeadlineTime(PartialTimestamp partialTimestamp) throws DrmaaException {
+        JnaSession.setPartialTime(jt, LibDrmaa.DRMAA_DEADLINE_TIME, partialTimestamp);
+    }
+
+    @Override
+    public PartialTimestamp getDeadlineTime() throws DrmaaException {
+        return JnaSession.getPartialTime(jt, LibDrmaa.DRMAA_DEADLINE_TIME);
+    }
+
+    @Override
+    public void setHardWallclockTimeLimit(long l) throws DrmaaException {
+        JnaSession.setAttribute(jt, LibDrmaa.DRMAA_WCT_HLIMIT, JnaSession.formatLimit(l));
+    }
+
+    @Override
+    public long getHardWallclockTimeLimit() throws DrmaaException {
+        return JnaSession.parseLimit(JnaSession.getAttribute(jt, LibDrmaa.DRMAA_WCT_HLIMIT));
+    }
+
+    @Override
+    public void setSoftWallclockTimeLimit(long l) throws DrmaaException {
+        JnaSession.setAttribute(jt, LibDrmaa.DRMAA_WCT_SLIMIT, JnaSession.formatLimit(l));
+    }
+
+    @Override
+    public long getSoftWallclockTimeLimit() throws DrmaaException {
+        return JnaSession.parseLimit(JnaSession.getAttribute(jt, LibDrmaa.DRMAA_WCT_SLIMIT));
+    }
+
+    @Override
+    public void setHardRunDurationLimit(long l) throws DrmaaException {
+        JnaSession.setAttribute(jt, LibDrmaa.DRMAA_DURATION_HLIMIT, JnaSession.formatLimit(l));
+    }
+
+    @Override
+    public long getHardRunDurationLimit() throws DrmaaException {
+        return JnaSession.parseLimit(JnaSession.getAttribute(jt, LibDrmaa.DRMAA_DURATION_HLIMIT));
+    }
+
+    @Override
+    public void setSoftRunDurationLimit(long l) throws DrmaaException {
+        JnaSession.setAttribute(jt, LibDrmaa.DRMAA_DURATION_SLIMIT, JnaSession.formatLimit(l));
+    }
+
+    @Override
+    public long getSoftRunDurationLimit() throws DrmaaException {
+        return JnaSession.parseLimit(JnaSession.getAttribute(jt, LibDrmaa.DRMAA_DURATION_SLIMIT));
+    }
+
+    @Override
+    public Set getAttributeNames() throws DrmaaException {
+        return JnaSession.getAttrNames();
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        if (!(obj instanceof JnaJobTemplate))
+            return false;
+        JnaJobTemplate other = (JnaJobTemplate) obj;
+        return this.jt.equals(other.jt) && this.session.equals(other.session);
+    }
+
+    @Override
+    public int hashCode() {
+        return jt.hashCode();
+    }
+}
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/jna/drmaa/v1_0/JnaSession.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/jna/drmaa/v1_0/JnaSession.java
new file mode 100644
index 0000000..67eaad7
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/jna/drmaa/v1_0/JnaSession.java
@@ -0,0 +1,461 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.utils.jna.drmaa.v1_0;
+
+import com.sun.jna.Memory;
+import com.sun.jna.NativeLong;
+import com.sun.jna.Pointer;
+import com.sun.jna.StringArray;
+import com.sun.jna.ptr.IntByReference;
+import com.sun.jna.ptr.PointerByReference;
+import org.ggf.drmaa.*;
+
+import java.text.ParseException;
+import java.util.*;
+
+/**
+ * JNA mapping from Java to C DRMAA binding.
+ * See: Java and C Binding Documents on http://drmaa.org
+ */
+public class JnaSession implements Session {
+    private static final PartialTimestampFormat PARTIAL_TIMESTAMP_FORMAT = new PartialTimestampFormat();
+    private static final ThreadLocal<Memory> threadError = new ThreadLocal<Memory>() {
+        @Override
+        protected Memory initialValue() {
+            return new Memory(LibDrmaa.DRMAA_ERROR_STRING_BUFFER);
+        }
+    };
+
+    @Override
+    public void init(String contact) throws DrmaaException {
+        checkError(LibDrmaa.drmaa_init(contact, getError(), LibDrmaa.DRMAA_ERROR_STRING_BUFFER_LEN));
+    }
+
+    @Override
+    public void exit() throws DrmaaException {
+        checkError(LibDrmaa.drmaa_exit(getError(), LibDrmaa.DRMAA_ERROR_STRING_BUFFER_LEN));
+    }
+
+    @Override
+    public JobTemplate createJobTemplate() throws DrmaaException {
+        PointerByReference jtRef = new PointerByReference();
+        checkError(LibDrmaa.drmaa_allocate_job_template(jtRef, getError(), LibDrmaa.DRMAA_ERROR_STRING_BUFFER_LEN));
+        return new JnaJobTemplate(this, jtRef.getValue());
+    }
+
+    @Override
+    public void deleteJobTemplate(JobTemplate jobTemplate) throws DrmaaException {
+        JnaJobTemplate jnaJobTemplate = (JnaJobTemplate) jobTemplate;
+        checkError(LibDrmaa.drmaa_delete_job_template(jnaJobTemplate.getPointer(), getError(), LibDrmaa.DRMAA_ERROR_STRING_BUFFER_LEN));
+    }
+
+    @Override
+    public String runJob(JobTemplate jobTemplate) throws DrmaaException {
+        Memory jobId = new Memory(LibDrmaa.DRMAA_JOBNAME_BUFFER);
+        JnaJobTemplate jnaJobTemplate = (JnaJobTemplate) jobTemplate;
+        checkError(LibDrmaa.drmaa_run_job(jobId, LibDrmaa.DRMAA_JOBNAME_BUFFER_LEN, jnaJobTemplate.getPointer(), getError(), LibDrmaa.DRMAA_ERROR_STRING_BUFFER_LEN));
+        return jobId.getString(0);
+    }
+
+    @Override
+    public List runBulkJobs(JobTemplate jobTemplate, int start, int end, int incr) throws DrmaaException {
+        PointerByReference jobIds = new PointerByReference();
+        JnaJobTemplate jnaJobTemplate = (JnaJobTemplate) jobTemplate;
+        checkError(LibDrmaa.drmaa_run_bulk_jobs(jobIds, jnaJobTemplate.getPointer(), start, end, incr, getError(), LibDrmaa.DRMAA_ERROR_STRING_BUFFER_LEN));
+        try {
+            return getJobIds(jobIds);
+        } finally {
+            releaseJobIds(jobIds);
+        }
+    }
+
+    @Override
+    public void control(String jobId, int action) throws DrmaaException {
+        checkError(LibDrmaa.drmaa_control(jobId, action, getError(), LibDrmaa.DRMAA_ERROR_STRING_BUFFER_LEN));
+    }
+
+    @SuppressWarnings("unchecked")
+    @Override
+    public void synchronize(List list, long timeout, boolean dispose) throws DrmaaException {
+        StringArray jobIds = new StringArray((String[]) list.toArray(new String[list.size()]));
+        checkError(LibDrmaa.drmaa_synchronize(jobIds, new NativeLong(timeout), dispose ? 1 : 0, getError(), LibDrmaa.DRMAA_ERROR_STRING_BUFFER_LEN));
+    }
+
+    @Override
+    public JobInfo wait(String jobId, long timeout) throws DrmaaException {
+        Memory jobIdOut = new Memory(LibDrmaa.DRMAA_JOBNAME_BUFFER);
+        IntByReference stat = new IntByReference();
+        PointerByReference rusage = new PointerByReference();
+        IntByReference exited = new IntByReference();
+        IntByReference exitStatus = new IntByReference();
+        IntByReference signaled = new IntByReference();
+        Memory signal = new Memory(LibDrmaa.DRMAA_SIGNAL_BUFFER);
+        IntByReference coreDumped = new IntByReference();
+        IntByReference aborted = new IntByReference();
+
+        int errnum;
+
+        errnum = LibDrmaa.drmaa_wait(jobId, jobIdOut, LibDrmaa.DRMAA_JOBNAME_BUFFER_LEN, stat, new NativeLong(timeout), rusage, getError(), LibDrmaa.DRMAA_ERROR_STRING_BUFFER_LEN);
+
+        Map<String, String> rusageMap;
+        if (errnum == LibDrmaa.DRMAA_ERRNO.DRMAA_ERRNO_NO_RUSAGE) {
+            rusageMap = null;
+        } else {
+            try {
+                rusageMap = collectionToMap(getAttrValues(rusage));
+            } finally {
+                releaseAttrValues(rusage);
+            }
+        }
+
+        checkError(LibDrmaa.drmaa_wifexited(exited, stat.getValue(), getError(), LibDrmaa.DRMAA_ERROR_STRING_BUFFER_LEN));
+
+        if (exited.getValue() != 0) {
+            checkError(LibDrmaa.drmaa_wexitstatus(exitStatus, stat.getValue(), getError(), LibDrmaa.DRMAA_ERROR_STRING_BUFFER_LEN));
+        }
+
+        checkError(LibDrmaa.drmaa_wifsignaled(signaled, stat.getValue(), getError(), LibDrmaa.DRMAA_ERROR_STRING_BUFFER_LEN));
+
+        if (signaled.getValue() != 0) {
+            checkError(LibDrmaa.drmaa_wtermsig(signal, LibDrmaa.DRMAA_SIGNAL_BUFFER_LEN, stat.getValue(), getError(), LibDrmaa.DRMAA_ERROR_STRING_BUFFER_LEN));
+            checkError(LibDrmaa.drmaa_wcoredump(coreDumped, stat.getValue(), getError(), LibDrmaa.DRMAA_ERROR_STRING_BUFFER_LEN));
+        }
+
+        checkError(LibDrmaa.drmaa_wifaborted(aborted, stat.getValue(), getError(), LibDrmaa.DRMAA_ERROR_STRING_BUFFER_LEN));
+
+        return new JnaJobInfo(jobIdOut.getString(0), rusageMap, exited.getValue() != 0, exitStatus.getValue(),
+                signaled.getValue() != 0, signal.getString(0), coreDumped.getValue() != 0, aborted.getValue() != 0);
+    }
+
+    @Override
+    public int getJobProgramStatus(String jobId) throws DrmaaException {
+        IntByReference remotePs = new IntByReference();
+        checkError(LibDrmaa.drmaa_job_ps(jobId, remotePs, getError(), LibDrmaa.DRMAA_ERROR_STRING_BUFFER_LEN));
+        return remotePs.getValue();
+    }
+
+    @Override
+    public String getContact() {
+        Memory contact = new Memory(LibDrmaa.DRMAA_CONTACT_BUFFER);
+        try {
+            checkError(LibDrmaa.drmaa_get_contact(contact, LibDrmaa.DRMAA_CONTACT_BUFFER_LEN, getError(), LibDrmaa.DRMAA_ERROR_STRING_BUFFER_LEN));
+        } catch (DrmaaException e) {
+            // DRMAA spec says this method should throw DrmaaException.
+            // Why doesn't interface implement this?
+            throw new RuntimeException(e);
+        }
+        return contact.getString(0);
+    }
+
+    @Override
+    public Version getVersion() {
+        IntByReference major = new IntByReference();
+        IntByReference minor = new IntByReference();
+        try {
+            checkError(LibDrmaa.drmaa_version(major, minor, getError(), LibDrmaa.DRMAA_ERROR_STRING_BUFFER_LEN));
+        } catch (DrmaaException e) {
+            // DRMAA spec says this method should throw DrmaaException.
+            // Why doesn't interface implement this?
+            throw new RuntimeException(e);
+        }
+        return new Version(major.getValue(), minor.getValue());
+    }
+
+    @Override
+    public String getDrmSystem() {
+        Memory drmSystem = new Memory(LibDrmaa.DRMAA_DRM_SYSTEM_BUFFER);
+        try {
+            checkError(LibDrmaa.drmaa_get_DRM_system(drmSystem, LibDrmaa.DRMAA_DRM_SYSTEM_BUFFER_LEN, getError(), LibDrmaa.DRMAA_ERROR_STRING_BUFFER_LEN));
+        } catch (DrmaaException e) {
+            // DRMAA spec says this method should throw DrmaaException.
+            // Why doesn't interface implement this?
+            throw new RuntimeException(e);
+        }
+        return drmSystem.getString(0);
+    }
+
+    @Override
+    public String getDrmaaImplementation() {
+        Memory drmaaImplementation = new Memory(LibDrmaa.DRMAA_DRMAA_IMPLEMENTATION_BUFFER);
+        try {
+            checkError(LibDrmaa.drmaa_get_DRMAA_implementation(drmaaImplementation, LibDrmaa.DRMAA_DRMAA_IMPLEMENTATION_BUFFER_LEN, getError(), LibDrmaa.DRMAA_ERROR_STRING_BUFFER_LEN));
+        } catch (DrmaaException e) {
+            // DRMAA spec says this method should throw DrmaaException.
+            // Why doesn't interface implement this?
+            throw new RuntimeException(e);
+        }
+        return drmaaImplementation.getString(0);
+    }
+
+    public static void setAttribute(Pointer jt, String name, String value) throws DrmaaException {
+        if (getAttrNames().contains(name)) {
+            checkError(LibDrmaa.drmaa_set_attribute(jt, name, value, getError(), LibDrmaa.DRMAA_ERROR_STRING_BUFFER_LEN));
+        }
+        else {
+            throw new InvalidAttributeValueException("Attribute " + name + " is not supported by this implementation of DRMAA");
+        }
+    }
+
+    public static String getAttribute(Pointer jt, String name) throws DrmaaException {
+        if (getAttrNames().contains(name)) {
+            Memory attrBuffer = new Memory(LibDrmaa.DRMAA_ATTR_BUFFER);
+            checkError(LibDrmaa.drmaa_get_attribute(jt, name, attrBuffer, LibDrmaa.DRMAA_ATTR_BUFFER_LEN, getError(), LibDrmaa.DRMAA_ERROR_STRING_BUFFER_LEN));
+            return attrBuffer.getString(0);
+        }
+        else {
+            throw new InvalidAttributeValueException("Attribute " + name + " is not supported by this implementation of DRMAA");
+        }
+    }
+
+    public static void setVectorAttribute(Pointer jt, String name, Collection<String> values) throws DrmaaException {
+        StringArray valuesArray = new StringArray(values.toArray(new String[values.size()]));
+        checkError(LibDrmaa.drmaa_set_vector_attribute(jt, name, valuesArray, getError(), LibDrmaa.DRMAA_ERROR_STRING_BUFFER_LEN));
+    }
+
+    public static List<String> getVectorAttribute(Pointer jt, String name) throws DrmaaException {
+        PointerByReference values = new PointerByReference();
+        checkError(LibDrmaa.drmaa_get_vector_attribute(jt, name, values, getError(), LibDrmaa.DRMAA_ERROR_STRING_BUFFER_LEN));
+        try {
+            return getAttrValues(values);
+        } finally {
+            releaseAttrValues(values);
+        }
+    }
+
+    public static void setPartialTime(Pointer jt, String name, PartialTimestamp partialTimestamp) throws DrmaaException {
+        setAttribute(jt, name, PARTIAL_TIMESTAMP_FORMAT.format(partialTimestamp));
+    }
+
+    public static PartialTimestamp getPartialTime(Pointer jt, String name) throws DrmaaException {
+        String time = getAttribute(jt, name);
+        if (time == null)
+            return null;
+        try {
+            return PARTIAL_TIMESTAMP_FORMAT.parse(time);
+        } catch (ParseException e) {
+            throw new InternalException(name + " property is unparsable");
+        }
+    }
+
+    public static Set<String> getAttrNames() throws DrmaaException {
+        PointerByReference values = new PointerByReference();
+        checkError(LibDrmaa.drmaa_get_attribute_names(values, getError(), LibDrmaa.DRMAA_ERROR_STRING_BUFFER_LEN));
+        try {
+            return new LinkedHashSet<String>(getAttrNames(values));
+        } finally {
+            releaseAttrNames(values);
+        }
+    }
+
+    public static Collection<String> mapToCollection(Map<String, String> map) {
+        Collection<String> collection = new LinkedHashSet<String>();
+        for (Map.Entry<String, String> entry: map.entrySet())
+            collection.add(entry.getKey() + "=" + entry.getValue());
+        return collection;
+    }
+
+    public static Map<String, String> collectionToMap(Collection<String> list) {
+        Map<String, String> map = new LinkedHashMap<String, String>();
+        for (String entry: list) {
+            if (entry == null)
+                continue;
+            int equals = entry.indexOf('=');
+            if (equals < 0)
+                continue;
+            map.put(entry.substring(0, equals), entry.substring(equals + 1));
+        }
+        return map;
+    }
+
+    public static String formatLimit(long secs) {
+        long seconds = (secs % 60);
+        long minutes = (secs / 60) % 60;
+        long hours = (secs / 3600);
+        return String.format("%d:%02d:%02d", hours, minutes, seconds);
+    }
+
+    public static long parseLimit(String limit) {
+        long seconds = 0;
+        if (limit != null) {
+            for (String token: limit.split(":")) {
+                seconds *= 60;
+                seconds += Long.parseLong(token);
+            }
+        }
+        return seconds;
+    }
+
+    private static List<String> getAttrNames(PointerByReference names) throws DrmaaException {
+        List<String> namesList = new ArrayList<String>();
+        IntByReference size = new IntByReference();
+        int errnum;
+
+        errnum = LibDrmaa.drmaa_get_num_attr_names(names.getValue(), size);
+        checkError(errnum, "unable to get attribute names");
+        int num = size.getValue();
+
+        Memory value = new Memory(LibDrmaa.DRMAA_ATTR_BUFFER);
+        for (int i = 1; i <= num; i++) {
+            errnum = LibDrmaa.drmaa_get_next_attr_name(names.getValue(), value, LibDrmaa.DRMAA_ATTR_BUFFER_LEN);
+            checkError(errnum, "unable to get attribute name " + i);
+            if (errnum == LibDrmaa.DRMAA_ERRNO.DRMAA_ERRNO_NO_MORE_ELEMENTS)
+                break;
+            namesList.add(value.getString(0));
+        }
+
+        return namesList;
+    }
+
+    private static List<String> getAttrValues(PointerByReference values) throws DrmaaException {
+        List<String> valuesList = new ArrayList<String>();
+        IntByReference size = new IntByReference();
+        int errnum;
+
+        errnum = LibDrmaa.drmaa_get_num_attr_values(values.getValue(), size);
+        checkError(errnum, "unable to get attribute values");
+        int num = size.getValue();
+
+        Memory value = new Memory(LibDrmaa.DRMAA_ATTR_BUFFER);
+        for (int i = 1; i <= num; i++) {
+            errnum = LibDrmaa.drmaa_get_next_attr_value(values.getValue(), value, LibDrmaa.DRMAA_ATTR_BUFFER_LEN);
+            checkError(errnum, "unable to get attribute value " + i);
+            if (errnum == LibDrmaa.DRMAA_ERRNO.DRMAA_ERRNO_NO_MORE_ELEMENTS)
+                break;
+            valuesList.add(value.getString(0));
+        }
+
+        return valuesList;
+    }
+
+    private static List<String> getJobIds(PointerByReference jobIds) throws DrmaaException {
+        List<String> jobIdsList = new ArrayList<String>();
+        IntByReference size = new IntByReference();
+        int errnum;
+
+        errnum = LibDrmaa.drmaa_get_num_job_ids(jobIds.getValue(), size);
+        checkError(errnum, "unable to get jobIds");
+        int num = size.getValue();
+
+        Memory value = new Memory(LibDrmaa.DRMAA_JOBNAME_BUFFER);
+        for (int i = 1; i <= num; i++) {
+            errnum = LibDrmaa.drmaa_get_next_job_id(jobIds.getValue(), value, LibDrmaa.DRMAA_JOBNAME_BUFFER_LEN);
+            checkError(errnum, "unable to get jobId " + i);
+            if (errnum == LibDrmaa.DRMAA_ERRNO.DRMAA_ERRNO_NO_MORE_ELEMENTS)
+                break;
+            jobIdsList.add(value.getString(0));
+        }
+
+        return jobIdsList;
+    }
+
+    private static void releaseAttrNames(PointerByReference names) throws DrmaaException {
+        LibDrmaa.drmaa_release_attr_names(names.getValue());
+    }
+
+    private static void releaseAttrValues(PointerByReference values) throws DrmaaException {
+        LibDrmaa.drmaa_release_attr_values(values.getValue());
+    }
+
+    private static void releaseJobIds(PointerByReference jobIds) throws DrmaaException {
+        LibDrmaa.drmaa_release_job_ids(jobIds.getValue());
+    }
+
+    private static Memory getError() {
+        return threadError.get();
+    }
+
+    private static void checkError(int errnum) throws DrmaaException {
+        if (errnum != LibDrmaa.DRMAA_ERRNO.DRMAA_ERRNO_SUCCESS)
+            checkError(errnum, getError().getString(0));
+    }
+
+    private static void checkError(int errnum, String error) throws DrmaaException {
+        switch (errnum) {
+            case LibDrmaa.DRMAA_ERRNO.DRMAA_ERRNO_SUCCESS:
+                break;
+            case LibDrmaa.DRMAA_ERRNO.DRMAA_ERRNO_INTERNAL_ERROR:
+                throw new InternalException(error);
+            case LibDrmaa.DRMAA_ERRNO.DRMAA_ERRNO_DRM_COMMUNICATION_FAILURE:
+                throw new DrmCommunicationException(error);
+            case LibDrmaa.DRMAA_ERRNO.DRMAA_ERRNO_AUTH_FAILURE:
+                throw new AuthorizationException(error);
+            case LibDrmaa.DRMAA_ERRNO.DRMAA_ERRNO_INVALID_ARGUMENT:
+                throw new IllegalArgumentException(error);
+            case LibDrmaa.DRMAA_ERRNO.DRMAA_ERRNO_NO_ACTIVE_SESSION:
+                throw new NoActiveSessionException(error);
+            case LibDrmaa.DRMAA_ERRNO.DRMAA_ERRNO_NO_MEMORY:
+                throw new OutOfMemoryError(error);
+
+                /* -------------- init and exit specific --------------- */
+            case LibDrmaa.DRMAA_ERRNO.DRMAA_ERRNO_INVALID_CONTACT_STRING:
+                throw new InvalidContactStringException(error);
+            case LibDrmaa.DRMAA_ERRNO.DRMAA_ERRNO_DEFAULT_CONTACT_STRING_ERROR:
+                throw new DefaultContactStringException(error);
+            case LibDrmaa.DRMAA_ERRNO.DRMAA_ERRNO_NO_DEFAULT_CONTACT_STRING_SELECTED:
+                throw new NoDefaultContactStringException(error);
+            case LibDrmaa.DRMAA_ERRNO.DRMAA_ERRNO_DRMS_INIT_FAILED:
+                throw new DrmsInitException(error);
+            case LibDrmaa.DRMAA_ERRNO.DRMAA_ERRNO_ALREADY_ACTIVE_SESSION:
+                throw new AlreadyActiveSessionException(error);
+            case LibDrmaa.DRMAA_ERRNO.DRMAA_ERRNO_DRMS_EXIT_ERROR:
+                throw new DrmsExitException(error);
+
+                /* ---------------- job attributes specific -------------- */
+            case LibDrmaa.DRMAA_ERRNO.DRMAA_ERRNO_INVALID_ATTRIBUTE_FORMAT:
+                throw new InvalidAttributeFormatException(error);
+            case LibDrmaa.DRMAA_ERRNO.DRMAA_ERRNO_INVALID_ATTRIBUTE_VALUE:
+                throw new InvalidAttributeValueException(error);
+            case LibDrmaa.DRMAA_ERRNO.DRMAA_ERRNO_CONFLICTING_ATTRIBUTE_VALUES:
+                throw new ConflictingAttributeValuesException(error);
+
+                /* --------------------- job submission specific -------------- */
+            case LibDrmaa.DRMAA_ERRNO.DRMAA_ERRNO_TRY_LATER:
+                throw new TryLaterException(error);
+            case LibDrmaa.DRMAA_ERRNO.DRMAA_ERRNO_DENIED_BY_DRM:
+                throw new DeniedByDrmException(error);
+
+                /* ------------------------------- job control specific ---------------- */
+            case LibDrmaa.DRMAA_ERRNO.DRMAA_ERRNO_INVALID_JOB:
+                throw new InvalidJobException(error);
+            case LibDrmaa.DRMAA_ERRNO.DRMAA_ERRNO_RESUME_INCONSISTENT_STATE:
+                throw new ResumeInconsistentStateException(error);
+            case LibDrmaa.DRMAA_ERRNO.DRMAA_ERRNO_SUSPEND_INCONSISTENT_STATE:
+                throw new SuspendInconsistentStateException(error);
+            case LibDrmaa.DRMAA_ERRNO.DRMAA_ERRNO_HOLD_INCONSISTENT_STATE:
+                throw new HoldInconsistentStateException(error);
+            case LibDrmaa.DRMAA_ERRNO.DRMAA_ERRNO_RELEASE_INCONSISTENT_STATE:
+                throw new ReleaseInconsistentStateException(error);
+            case LibDrmaa.DRMAA_ERRNO.DRMAA_ERRNO_EXIT_TIMEOUT:
+                throw new ExitTimeoutException(error);
+            case LibDrmaa.DRMAA_ERRNO.DRMAA_ERRNO_NO_RUSAGE:
+                break;
+            case LibDrmaa.DRMAA_ERRNO.DRMAA_ERRNO_NO_MORE_ELEMENTS:
+                break;
+            default:
+                throw new IllegalArgumentException(String.format("Unknown error code %d: %s", errnum, error));
+        }
+    }
+}
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/jna/drmaa/v1_0/JnaSessionFactory.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/jna/drmaa/v1_0/JnaSessionFactory.java
new file mode 100644
index 0000000..f4dbc98
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/jna/drmaa/v1_0/JnaSessionFactory.java
@@ -0,0 +1,40 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.utils.jna.drmaa.v1_0;
+
+import org.ggf.drmaa.Session;
+import org.ggf.drmaa.SessionFactory;
+
+/**
+ * JNA mapping from Java to C DRMAA binding.
+ */
+ at SuppressWarnings("unused")
+public class JnaSessionFactory extends SessionFactory {
+    @Override
+    public Session getSession() {
+        return new JnaSession();
+    }
+}
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/jna/drmaa/v1_0/LibDrmaa.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/jna/drmaa/v1_0/LibDrmaa.java
new file mode 100644
index 0000000..3e5c4e4
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/jna/drmaa/v1_0/LibDrmaa.java
@@ -0,0 +1,723 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.utils.jna.drmaa.v1_0;
+
+import com.sun.jna.*;
+import com.sun.jna.ptr.IntByReference;
+import com.sun.jna.ptr.PointerByReference;
+
+ at SuppressWarnings("unused")
+public class LibDrmaa {
+    static {
+        Native.register("drmaa");
+    }
+
+/* see www.drmaa.org for more details on the DRMAA specification */
+/****** DRMAA/-DRMAA_Interface *************************************************
+*  NAME
+*     DRMAA_Interface -- DRMAA interface
+*
+*  FUNCTION
+*     The enlisted functions specify the C/C++ binding of the DRMAA interface
+*     specification.
+*
+*  SEE ALSO
+*     DRMAA/drmaa_get_next_attr_name()
+*     DRMAA/drmaa_get_next_attr_value()
+*     DRMAA/drmaa_get_next_job_id()
+*     DRMAA/drmaa_release_attr_names()
+*     DRMAA/drmaa_release_attr_values()
+*     DRMAA/drmaa_release_job_ids()
+*     DRMAA/drmaa_init()
+*     DRMAA/drmaa_exit()
+*     DRMAA/drmaa_allocate_job_template()
+*     DRMAA/drmaa_delete_job_template()
+*     DRMAA/drmaa_set_attribute()
+*     DRMAA/drmaa_get_attribute()
+*     DRMAA/drmaa_set_vector_attribute()
+*     DRMAA/drmaa_get_vector_attribute()
+*     DRMAA/drmaa_get_attribute_names()
+*     DRMAA/drmaa_get_vector_attribute_names()
+*     DRMAA/drmaa_run_job()
+*     DRMAA/drmaa_run_bulk_jobs()
+*     DRMAA/drmaa_control()
+*     DRMAA/drmaa_synchronize()
+*     DRMAA/drmaa_wait()
+*     DRMAA/drmaa_wifexited()
+*     DRMAA/drmaa_wexitstatus()
+*     DRMAA/drmaa_wifsignaled()
+*     DRMAA/drmaa_wtermsig()
+*     DRMAA/drmaa_wcoredump()
+*     DRMAA/drmaa_wifaborted()
+*     DRMAA/drmaa_job_ps()
+*     DRMAA/drmaa_strerror()
+*     DRMAA/drmaa_get_contact()
+*     DRMAA/drmaa_version()
+*     DRMAA/drmaa_get_DRM_system()
+*******************************************************************************/
+
+/* ------------------- Constants ------------------- */
+/*
+ * some not yet agreed buffer length constants
+ * these are recommended minimum values
+ */
+
+/* drmaa_get_attribute() */
+public static final long DRMAA_ATTR_BUFFER = 1024;
+public static final NativeLong DRMAA_ATTR_BUFFER_LEN = new NativeLong(DRMAA_ATTR_BUFFER - 1);
+
+/* drmaa_get_contact() */
+public static final long DRMAA_CONTACT_BUFFER = 1024;
+public static final NativeLong DRMAA_CONTACT_BUFFER_LEN = new NativeLong(DRMAA_CONTACT_BUFFER - 1);
+
+/* drmaa_get_DRM_system() */
+public static final long DRMAA_DRM_SYSTEM_BUFFER = 1024;
+public static final NativeLong DRMAA_DRM_SYSTEM_BUFFER_LEN = new NativeLong(DRMAA_DRM_SYSTEM_BUFFER - 1);
+
+/* drmaa_get_DRM_system() */
+public static final long DRMAA_DRMAA_IMPLEMENTATION_BUFFER = 1024;
+public static final NativeLong DRMAA_DRMAA_IMPLEMENTATION_BUFFER_LEN = new NativeLong(DRMAA_DRMAA_IMPLEMENTATION_BUFFER - 1);
+
+/*
+ * Agreed buffer length constants
+ * these are recommended minimum values
+ */
+public static final long DRMAA_ERROR_STRING_BUFFER = 1024;
+public static final long DRMAA_JOBNAME_BUFFER = 1024;
+public static final long DRMAA_SIGNAL_BUFFER = 32;
+
+public static final NativeLong DRMAA_ERROR_STRING_BUFFER_LEN = new NativeLong(DRMAA_ERROR_STRING_BUFFER - 1);
+public static final NativeLong DRMAA_JOBNAME_BUFFER_LEN = new NativeLong(DRMAA_JOBNAME_BUFFER - 1);
+public static final NativeLong DRMAA_SIGNAL_BUFFER_LEN = new NativeLong(DRMAA_SIGNAL_BUFFER - 1);
+
+/*
+ * Agreed constants
+ */
+public static final NativeLong DRMAA_TIMEOUT_WAIT_FOREVER = new NativeLong(-1);
+public static final NativeLong DRMAA_TIMEOUT_NO_WAIT = new NativeLong(0);
+
+public static final String DRMAA_JOB_IDS_SESSION_ANY = "DRMAA_JOB_IDS_SESSION_ANY";
+public static final String DRMAA_JOB_IDS_SESSION_ALL = "DRMAA_JOB_IDS_SESSION_ALL";
+
+public static final String DRMAA_SUBMISSION_STATE_ACTIVE = "drmaa_active";
+public static final String DRMAA_SUBMISSION_STATE_HOLD = "drmaa_hold";
+
+/*
+ * Agreed placeholder names
+ */
+public static final String DRMAA_PLACEHOLDER_INCR = "$drmaa_incr_ph$";
+public static final String DRMAA_PLACEHOLDER_HD = "$drmaa_hd_ph$";
+public static final String DRMAA_PLACEHOLDER_WD = "$drmaa_wd_ph$";
+
+/*
+ * Agreed names of job template attributes
+ */
+public static final String DRMAA_REMOTE_COMMAND = "drmaa_remote_command";
+public static final String DRMAA_JS_STATE = "drmaa_js_state";
+public static final String DRMAA_WD = "drmaa_wd";
+public static final String DRMAA_JOB_CATEGORY = "drmaa_job_category";
+public static final String DRMAA_NATIVE_SPECIFICATION = "drmaa_native_specification";
+public static final String DRMAA_BLOCK_EMAIL = "drmaa_block_email";
+public static final String DRMAA_START_TIME = "drmaa_start_time";
+public static final String DRMAA_JOB_NAME = "drmaa_job_name";
+public static final String DRMAA_INPUT_PATH = "drmaa_input_path";
+public static final String DRMAA_OUTPUT_PATH = "drmaa_output_path";
+public static final String DRMAA_ERROR_PATH = "drmaa_error_path";
+public static final String DRMAA_JOIN_FILES = "drmaa_join_files";
+public static final String DRMAA_TRANSFER_FILES = "drmaa_transfer_files";
+public static final String DRMAA_DEADLINE_TIME = "drmaa_deadline_time";
+public static final String DRMAA_WCT_HLIMIT = "drmaa_wct_hlimit";
+public static final String DRMAA_WCT_SLIMIT = "drmaa_wct_slimit";
+public static final String DRMAA_DURATION_HLIMIT = "drmaa_duration_hlimit";
+public static final String DRMAA_DURATION_SLIMIT = "drmaa_duration_slimit";
+
+/* names of job template vector attributes */
+public static final String DRMAA_V_ARGV = "drmaa_v_argv";
+public static final String DRMAA_V_ENV = "drmaa_v_env";
+public static final String DRMAA_V_EMAIL = "drmaa_v_email";
+
+/*
+ * DRMAA errno values
+ *
+ * do not touch these values are agreed !!!
+ */
+public static interface DRMAA_ERRNO {
+   /* -------------- these are relevant to all sections ---------------- */
+   public static final int DRMAA_ERRNO_SUCCESS = 0; /* Routine returned normally with success. */
+   public static final int DRMAA_ERRNO_INTERNAL_ERROR = 1; /* Unexpected or internal DRMAA error like memory allocation, system call failure, etc. */
+   public static final int DRMAA_ERRNO_DRM_COMMUNICATION_FAILURE = 2; /* Could not contact DRM system for this request. */
+   public static final int DRMAA_ERRNO_AUTH_FAILURE = 3; /* The specified request is not processed successfully due to authorization failure. */
+   public static final int DRMAA_ERRNO_INVALID_ARGUMENT = 4; /* The input value for an argument is invalid. */
+   public static final int DRMAA_ERRNO_NO_ACTIVE_SESSION = 5; /* Exit routine failed because there is no active session */
+   public static final int DRMAA_ERRNO_NO_MEMORY = 6; /* failed allocating memory */
+
+   /* -------------- init and exit specific --------------- */
+   public static final int DRMAA_ERRNO_INVALID_CONTACT_STRING = 7; /* Initialization failed due to invalid contact string. */
+   public static final int DRMAA_ERRNO_DEFAULT_CONTACT_STRING_ERROR = 8; /* DRMAA could not use the default contact string to connect to DRM system. */
+   public static final int DRMAA_ERRNO_NO_DEFAULT_CONTACT_STRING_SELECTED = 9; /* No default contact string was provided or selected. DRMAA requires that the default contact string is selected when there is more than one default contact string due to multiple DRMAA implementation contained in the binary module. */
+   public static final int DRMAA_ERRNO_DRMS_INIT_FAILED = 10; /* Initialization failed due to failure to init DRM system. */
+   public static final int DRMAA_ERRNO_ALREADY_ACTIVE_SESSION = 11; /* Initialization failed due to existing DRMAA session. */
+   public static final int DRMAA_ERRNO_DRMS_EXIT_ERROR = 12; /* DRM system disengagement failed. */
+
+   /* ---------------- job attributes specific -------------- */
+   public static final int DRMAA_ERRNO_INVALID_ATTRIBUTE_FORMAT = 13; /* The format for the job attribute value is invalid. */
+   public static final int DRMAA_ERRNO_INVALID_ATTRIBUTE_VALUE = 14; /* The value for the job attribute is invalid. */
+   public static final int DRMAA_ERRNO_CONFLICTING_ATTRIBUTE_VALUES = 15; /* The value of this attribute is conflicting with a previously set attributes. */
+
+   /* --------------------- job submission specific -------------- */
+   public static final int DRMAA_ERRNO_TRY_LATER = 16; /* Could not pass job now to DRM system. A retry may succeed however (saturation). */
+   public static final int DRMAA_ERRNO_DENIED_BY_DRM = 17; /* The DRM system rejected the job. The job will never be accepted due to DRM configuration or job template settings. */
+
+   /* ------------------------------- job control specific ---------------- */
+   public static final int DRMAA_ERRNO_INVALID_JOB = 18; /* The job specified by the 'jobid' does not exist. */
+   public static final int DRMAA_ERRNO_RESUME_INCONSISTENT_STATE = 19; /* The job has not been suspended. The RESUME request will not be processed. */
+   public static final int DRMAA_ERRNO_SUSPEND_INCONSISTENT_STATE = 20; /* The job has not been running, and it cannot be suspended. */
+   public static final int DRMAA_ERRNO_HOLD_INCONSISTENT_STATE = 21; /* The job cannot be moved to a HOLD state. */
+   public static final int DRMAA_ERRNO_RELEASE_INCONSISTENT_STATE = 22; /* The job is not in a HOLD state. */
+   public static final int DRMAA_ERRNO_EXIT_TIMEOUT = 23; /* We have encountered a time-out condition for drmaa_synchronize or drmaa_wait. */
+   public static final int DRMAA_ERRNO_NO_RUSAGE = 24; /* This error code is returned by drmaa_wait() when a job has finished but no rusage and stat data could be provided. */
+   public static final int DRMAA_ERRNO_NO_MORE_ELEMENTS = 25; /* There are no more elements in the opaque string vector. */
+
+   public static final int DRMAA_NO_ERRNO = 26;
+}
+
+/*
+ * Agreed DRMAA job states as returned by drmaa_job_ps()
+ */
+public static interface DRMAA_PS {
+ public static final int DRMAA_PS_UNDETERMINED = 0x00; /* process status cannot be determined */
+ public static final int DRMAA_PS_QUEUED_ACTIVE = 0x10; /* job is queued and active */
+ public static final int DRMAA_PS_SYSTEM_ON_HOLD = 0x11; /* job is queued and in system hold */
+ public static final int DRMAA_PS_USER_ON_HOLD = 0x12; /* job is queued and in user hold */
+ public static final int DRMAA_PS_USER_SYSTEM_ON_HOLD = 0x13; /* job is queued and in user and system hold */
+ public static final int DRMAA_PS_RUNNING = 0x20; /* job is running */
+ public static final int DRMAA_PS_SYSTEM_SUSPENDED = 0x21; /* job is system suspended */
+ public static final int DRMAA_PS_USER_SUSPENDED = 0x22; /* job is user suspended */
+ public static final int DRMAA_PS_USER_SYSTEM_SUSPENDED = 0x23; /* job is user and system suspended */
+ public static final int DRMAA_PS_DONE = 0x30; /* job finished normally */
+ public static final int DRMAA_PS_FAILED = 0x40;  /* job finished, but failed */
+}
+
+/*
+ * Agreed DRMAA actions for drmaa_control()
+ */
+public static interface DRMAA_CONTROL {
+ public static final int DRMAA_CONTROL_SUSPEND = 0;
+ public static final int DRMAA_CONTROL_RESUME = 1;
+ public static final int DRMAA_CONTROL_HOLD = 2;
+ public static final int DRMAA_CONTROL_RELEASE = 3;
+ public static final int DRMAA_CONTROL_TERMINATE = 4;
+}
+
+/* ------------------- Data types ------------------- */
+/*
+ * Agreed opaque DRMAA job template
+ * struct drmaa_job_template_s is in japiP.h
+ */
+//typedef struct drmaa_job_template_s drmaa_job_template_t;
+
+/* ---------- C/C++ language binding specific interfaces -------- */
+
+//typedef struct drmaa_attr_names_s drmaa_attr_names_t;
+//typedef struct drmaa_attr_values_s drmaa_attr_values_t;
+//typedef struct drmaa_job_ids_s  drmaa_job_ids_t;
+
+/*
+ * get next string attribute from iterator
+ *
+ * returns DRMAA_ERRNO_SUCCESS or DRMAA_ERRNO_INVALID_ATTRIBUTE_VALUE
+ * if no such exists
+ */
+
+public static native int drmaa_get_next_attr_name(/* drmaa_attr_names_t* */ Pointer values, Pointer value,
+                             NativeLong value_len);
+public static native int drmaa_get_next_attr_value(/* drmaa_attr_names_t* */ Pointer values, Pointer value,
+                              NativeLong value_len);
+public static native int drmaa_get_next_job_id(/* drmaa_job_ids_t* */ Pointer values, Pointer value,
+                          NativeLong value_len);
+
+/*
+ * get element count of opaque string vector
+ *
+ * Gives the number of elements in the opaque string vector.  Useful for
+ * copying the contents into an array.
+ */
+public static native int drmaa_get_num_attr_names(/* drmaa_attr_names_t* */ Pointer values, IntByReference size);
+public static native int drmaa_get_num_attr_values(/* drmaa_attr_values_t* */ Pointer values, IntByReference size);
+public static native int drmaa_get_num_job_ids(/* drmaa_job_ids_t* */ Pointer values, IntByReference size);
+
+/*
+ * release opaque string vector
+ *
+ * Opaque string vectors can be used without any constraint
+ * until the release function has been called.
+ */
+public static native void drmaa_release_attr_names(/* drmaa_attr_names_t* */ Pointer values);
+public static native void drmaa_release_attr_values(/* drmaa_attr_values_t* */ Pointer values);
+public static native void drmaa_release_job_ids(/* drmaa_job_ids_t* */ Pointer values);
+
+/* ------------------- init/exit routines ------------------- */
+/*
+ * Initialize DRMAA API library and create a new DRMAA Session. 'Contact'
+ * is an implementation dependent string which MAY be used to specify
+ * which DRM system to use. This routine MUST be called before any
+ * other DRMAA calls, except for drmaa_version().
+ * If 'contact' is NULL, the default DRM system SHALL be used provided there is
+ * only one DRMAA implementation in the provided binary module.  When these is
+ * more than one DRMAA implementation in the binary module, drmaa_init() SHALL
+ * return the DRMAA_ERRNO_NO_DEFAULT_CONTACT_STRING_SELECTED error. drmaa_init()
+ * SHOULD be called by only one of the threads. The main thread is RECOMMENDED.
+ * A call by another thread SHALL return DRMAA_ERRNO_ALREADY_ACTIVE_SESSION.
+ * When 'contact' is a a semi-colon separated list of name=value strings, the
+ * strings will be parsed and interpreted.  The current list of accepted names
+ * is:
+ *    session -- the id of the session to which to reconnect
+#if 0
+ *    sge_root -- the SGE_ROOT to use
+ *    sge_cell -- the SGE_CELL to use
+#endif
+ *
+ * drmaa_init() SHALL return DRMAA_ERRNO_SUCCESS on success, otherwise:
+ *    DRMAA_ERRNO_INVALID_CONTACT_STRING,
+ *    DRMAA_ERRNO_NO_MEMORY,
+ *    DRMAA_ERRNO_ALREADY_ACTIVE_SESSION,
+ *    DRMAA_ERRNO_NO_DEFAULT_CONTACT_STRING_SELECTED, or
+ *    DRMAA_ERRNO_DEFAULT_CONTACT_STRING_ERROR.
+ */
+public static native int drmaa_init(String contact, Pointer error_diagnosis, NativeLong error_diag_len);
+
+
+/*
+ * Disengage from DRMAA library and allow the DRMAA library to perform
+ * any necessary internal clean up.
+ * This routine SHALL end the current DRMAA Session, but SHALL NOT effect any
+ * jobs (e.g., queued and running jobs SHALL remain queued and running).
+ * drmaa_exit() SHOULD be called by only one of the threads. Other thread calls
+ * to drmaa_exit() MAY fail since there is no active session.
+ *
+ * drmaa_exit() SHALL return DRMAA_ERRNO_SUCCESS on success, otherwise:
+ *    DRMAA_ERRNO_DRMS_EXIT_ERROR or
+ *    DRMAA_ERRNO_NO_ACTIVE_SESSION.
+ */
+public static native int drmaa_exit(Pointer error_diagnosis, NativeLong error_diag_len);
+
+/* ------------------- job template routines ------------------- */
+
+/*
+ * Allocate a new job template.
+ *
+ * drmaa_allocate_job_template() SHALL return DRMAA_ERRNO_SUCCESS on success,
+ * otherwise:
+ *    DRMAA_ERRNO_DRM_COMMUNICATION_FAILURE,
+ *    DRMAA_ERRNO_INTERNAL_ERROR or
+ *    DRMAA_ERRNO_NO_MEMORY.
+ */
+public static native int drmaa_allocate_job_template(/* drmaa_job_template_t** */ PointerByReference jt, Pointer error_diagnosis, NativeLong error_diag_len);
+
+/*
+ * Deallocate a job template. This routine has no effect on jobs.
+ *
+ * drmaa_delete_job_template() SHALL return DRMAA_ERRNO_SUCCESS on success,
+ * otherwise:
+ *    DRMAA_ERRNO_DRM_COMMUNICATION_FAILURE or
+ *    DRMAA_ERRNO_INTERNAL_ERROR.
+ */
+public static native int drmaa_delete_job_template(/* drmaa_job_template_t* */ Pointer jt, Pointer error_diagnosis,
+                              NativeLong error_diag_len);
+
+
+/*
+ * Adds ('name', 'value') pair to list of attributes in job template 'jt'.
+ * Only non-vector attributes SHALL be passed.
+ *
+ * drmaa_set_attribute() SHALL return DRMAA_ERRNO_SUCCESS on success, otherwise:
+ *    DRMAA_ERRNO_INVALID_ATTRIBUTE_FORMAT,
+ *    DRMAA_ERRNO_INVALID_ARGUMENT,
+ *    DRMAA_ERRNO_NO_MEMORY,
+ *    DRMAA_ERRNO_INVALID_ATTRIBUTE_VALUE or
+ *    DRMAA_ERRNO_CONFLICTING_ATTRIBUTE_VALUES.
+ */
+public static native int drmaa_set_attribute(/* drmaa_job_template_t* */ Pointer jt, String name,
+                        String value, Pointer error_diagnosis,
+                        NativeLong error_diag_len);
+
+
+/*
+ * If 'name' is an existing non-vector attribute name in the job
+ * template 'jt', then the value of 'name' SHALL be returned; otherwise,
+ * NULL is returned.
+ *
+ * drmaa_get_attribute() SHALL return DRMAA_ERRNO_SUCCESS on success, otherwise:
+ *    DRMAA_ERRNO_INVALID_ATTRIBUTE_VALUE.
+ */
+public static native int drmaa_get_attribute(/* drmaa_job_template_t* */ Pointer jt, String name, Pointer value,
+                        NativeLong value_len, Pointer error_diagnosis,
+                        NativeLong error_diag_len);
+
+/* Adds ('name', 'values') pair to list of vector attributes in job template
+ * 'jt'. Only vector attributes SHALL be passed.
+ * A 'value' string vector containing n elements must be n+1 elements long, with
+ * the nth value, i.e. value[n], being set to NULL as a delimitor.
+ *
+ * drmaa_set_vector_attribute() SHALL return DRMAA_ERRNO_SUCCESS on success,
+ * otherwise:
+ *    DRMAA_ERRNO_INVALID_ATTRIBUTE_FORMAT,
+ *    DRMAA_ERRNO_INVALID_ARGUMENT,
+ *    DRMAA_ERRNO_NO_MEMORY,
+ *    DRMAA_ERRNO_CONFLICTING_ATTRIBUTE_VALUES.
+ */
+public static native int drmaa_set_vector_attribute(/* drmaa_job_template_t* */ Pointer jt, String name,
+                               Pointer value, Pointer error_diagnosis,
+                               NativeLong error_diag_len);
+
+
+/*
+ * If 'name' is an existing vector attribute name in the job template 'jt',
+ * then the values of 'name' are returned; otherwise, NULL is returned.
+ *
+ * drmaa_get_vector_attribute() SHALL return DRMAA_ERRNO_SUCCESS on success,
+ * otherwise:
+ *    DRMAA_ERRNO_INVALID_ATTRIBUTE_VALUE.
+ */
+public static native int drmaa_get_vector_attribute(/* drmaa_job_template_t* */ Pointer jt, String name,
+                               /* drmaa_attr_values_t ** */ PointerByReference values,
+                               Pointer error_diagnosis, NativeLong error_diag_len);
+
+
+/*
+ * SHALL return the set of supported attribute names whose associated
+ * value type is String. This set SHALL include supported DRMAA reserved
+ * attribute names and native attribute names.
+ *
+ * drmaa_get_attribute_names() SHALL return DRMAA_ERRNO_SUCCESS on success,
+ * otherwise:
+ *    DRMAA_ERRNO_NO_MEMORY.
+ */
+public static native int drmaa_get_attribute_names(/* drmaa_attr_names_t ** */ PointerByReference values,
+                              Pointer error_diagnosis, NativeLong error_diag_len);
+
+/*
+ * SHALL return the set of supported attribute names whose associated
+ * value type is String Vector.  This set SHALL include supported DRMAA reserved
+ * attribute names and native attribute names.
+ *
+ * drmaa_get_vector_attribute_names() SHALL return DRMAA_ERRNO_SUCCESS on
+ * success, otherwise:
+ *    DRMAA_ERRNO_NO_MEMORY.
+ */
+public static native int drmaa_get_vector_attribute_names(/* drmaa_attr_names_t ** */ PointerByReference values,
+                                     Pointer error_diagnosis,
+                                     NativeLong error_diag_len);
+
+/* ------------------- job submission routines ------------------- */
+
+/*
+ * Submit a job with attributes defined in the job template 'jt'.
+ * The job identifier 'job_id' is a printable, NULL terminated string,
+ * identical to that returned by the underlying DRM system.
+ *
+ * drmaa_run_job() SHALL return DRMAA_ERRNO_SUCCESS on success, otherwise:
+ *    DRMAA_ERRNO_TRY_LATER,
+ *    DRMAA_ERRNO_DENIED_BY_DRM,
+ *    DRMAA_ERRNO_NO_MEMORY,
+ *    DRMAA_ERRNO_DRM_COMMUNICATION_FAILURE or
+ *    DRMAA_ERRNO_AUTH_FAILURE.
+ */
+public static native int drmaa_run_job(Pointer job_id, NativeLong job_id_len,
+                  /* drmaa_job_template_t * */ Pointer jt, Pointer error_diagnosis,
+                  NativeLong error_diag_len);
+
+/*
+ * Submit a set of parametric jobs, dependent on the implied loop index, each
+ * with attributes defined in the job template 'jt'.
+ * The job identifiers 'job_ids' SHALL all be printable,
+ * NULL terminated strings, identical to those returned by the underlying
+ * DRM system. Nonnegative loop bounds SHALL NOT use file names
+ * that start with minus sign like command line options.
+ * DRMAA defines a special index placeholder, drmaa_incr_ph, (which has the
+ * value "$incr_pl$") that is used to construct parametric job templates.
+ * For example:
+ * //C++ string syntax used
+ * drmaa_set_attribute(pjt, "stderr", drmaa_incr_ph + ".err" );
+ *
+ * drmaa_run_bulk_jobs() SHALL return DRMAA_ERRNO_SUCCESS on success, otherwise:
+ *    DRMAA_ERRNO_TRY_LATER,
+ *    DRMAA_ERRNO_DENIED_BY_DRM,
+ *    DRMAA_ERRNO_NO_MEMORY,
+ *    DRMAA_ERRNO_DRM_COMMUNICATION_FAILURE or
+ *    DRMAA_ERRNO_AUTH_FAILURE.
+ */
+public static native int drmaa_run_bulk_jobs(/* drmaa_job_ids_t ** */ PointerByReference jobids,
+                        /* drmaa_job_template_t * */ Pointer jt, int start, int end,
+                        int incr, Pointer error_diagnosis, NativeLong error_diag_len);
+
+/* ------------------- job control routines ------------------- */
+
+/*
+ * Start, stop, restart, or kill the job identified by 'job_id'.
+ * If 'job_id' is DRMAA_JOB_IDS_SESSION_ALL then this routine
+ * acts on all jobs *submitted* during this DRMAA session.
+ * The legal values for 'action' and their meanings SHALL be:
+ * DRMAA_CONTROL_SUSPEND:     stop the job,
+ * DRMAA_CONTROL_RESUME:      (re)start the job,
+ * DRMAA_CONTROL_HOLD:        put the job on-hold,
+ * DRMAA_CONTROL_RELEASE:     release the hold on the job, and
+ * DRMAA_CONTROL_TERMINATE:   kill the job.
+ *
+ * This routine SHALL return once the action has been acknowledged by
+ * the DRM system, but does not necessarily wait until the action
+ * has been completed.
+ *
+ * drmaa_control() SHALL return DRMAA_ERRNO_SUCCESS on success, otherwise:
+ *    DRMAA_ERRNO_DRM_COMMUNICATION_FAILURE,
+ *    DRMAA_ERRNO_AUTH_FAILURE,
+ *    DRMAA_ERRNO_NO_MEMORY,
+ *    DRMAA_ERRNO_RESUME_INCONSISTENT_STATE,
+ *    DRMAA_ERRNO_SUSPEND_INCONSISTENT_STATE,
+ *    DRMAA_ERRNO_HOLD_INCONSISTENT_STATE,
+ *    DRMAA_ERRNO_RELEASE_INCONSISTENT_STATE or
+ *    DRMAA_ERRNO_INVALID_JOB.
+ */
+public static native int drmaa_control(String jobid, int action, Pointer error_diagnosis,
+                  NativeLong error_diag_len);
+
+
+/*
+ * Wait until all jobs specified by 'job_ids' have finished
+ * execution. If 'job_ids' is DRMAA_JOB_IDS_SESSION_ALL then this routine
+ * waits for all jobs *submitted* during this DRMAA session. The timeout value
+ * is used to specify the number of seconds to wait for the job to fail finish
+ * before returning if a result is not immediately available.  The value
+ * DRMAA_TIMEOUT_WAIT_FOREVER can be used to specify that routine should wait
+ * indefinitely for a result. The value DRMAA_TIMEOUT_NO_WAIT can be used to
+ * specify that the routine should return immediately if no result is available.
+ * If the call exits before timeout, all the jobs have
+ * been waited on or there was an interrupt.
+ * If the invocation exits on timeout, the return code is
+ * DRMAA_ERRNO_EXIT_TIMEOUT. The caller SHOULD check system time before and
+ * after this call in order to check how much time has passed.
+ *
+ * The dispose parameter specifies how to treat reaping information:
+ * True=1      "fake reap", i.e. dispose of the rusage data
+ * False=0     do not reap
+ *
+ * A 'job_ids' string vector containing n elements must be n+1 elements long,
+ * with the nth value, i.e. job_ids[n], being set to NULL as a delimitor.
+ *
+ * drmaa_synchronize() SHALL return DRMAA_ERRNO_SUCCESS on success, otherwise:
+ *    DRMAA_ERRNO_DRM_COMMUNICATION_FAILURE,
+ *    DRMAA_ERRNO_AUTH_FAILURE,
+ *    DRMAA_ERRNO_NO_MEMORY,
+ *    DRMAA_ERRNO_EXIT_TIMEOUT or
+ *    DRMAA_ERRNO_INVALID_JOB.
+ */
+public static native int drmaa_synchronize(Pointer job_ids, NativeLong timeout, int dispose,
+                      Pointer error_diagnosis, NativeLong error_diag_len);
+
+
+/*
+ * This routine SHALL wait for a job with job_id to fail or finish execution. If
+ * the special string, DRMAA_JOB_IDS_SESSION_ANY is provided as the job_id,
+ * this routine SHALL wait for any job from the session. This routine is modeled
+ * on the wait3 POSIX routine. The timeout value is used to specify the number
+ * of seconds to wait for the job to fail finish before returning if a result is
+ * not immediately available.  The value DRMAA_TIMEOUT_WAIT_FOREVER can be
+ * used to specify that routine should wait indefinitely for a result. The value
+ * DRMAA_TIMEOUT_NO_WAIT may be specified that the routine should return
+ * immediately if no result is available.
+ * If the call exits before timeout ,the job has been waited on
+ * successfully or there was an interrupt.
+ * If the invocation exits on timeout, the return code is
+ * DRMAA_ERRNO_EXIT_TIMEOUT. The caller SHOULD check system time before and
+ * after this call in order to check how much time has passed.
+ * The routine reaps jobs on a successful call, so any subsequent calls
+ * to drmaa_wait SHOULD fail returning an error DRMAA_ERRNO_INVALID_JOB meaning
+ * that the job has been already reaped. This error is the same as if the job
+ * was unknown. Failing due to an elapsed timeout has an effect that it is
+ * possible to issue drmaa_wait multiple times for the same job_id.  When
+ * successful, the rusage information SHALL be provided as an array of strings,
+ * where each string complies with the format <name>=<value>. The string portion
+ * <value> contains the amount of resources consumed by the job and is opaque.
+ * The 'stat' drmaa_wait parameter is used in the drmaa_w* functions for
+ * providing more detailed information about job termination if available. An
+ * analogous set of macros is defined in POSIX for analyzing the wait3(2) OUT
+ * parameter 'stat'.
+ *
+ * drmaa_wait() SHALL return DRMAA_ERRNO_SUCCESS on success, otherwise:
+ *    DRMAA_ERRNO_DRM_COMMUNICATION_FAILURE,
+ *    DRMAA_ERRNO_AUTH_FAILURE,
+ *    DRMAA_ERRNO_NO_RUSAGE,
+ *    DRMAA_ERRNO_NO_MEMORY,
+ *    DRMAA_ERRNO_EXIT_TIMEOUT or
+ *    DRMAA_ERRNO_INVALID_JOB.
+ */
+public static native int drmaa_wait(String job_id, Pointer job_id_out, NativeLong job_id_out_len,
+               IntByReference stat, NativeLong timeout, /* drmaa_attr_values_t ** */ PointerByReference rusage,
+               Pointer error_diagnosis, NativeLong error_diag_len);
+
+/*
+ * Evaluates into 'exited' a non-zero value if stat was returned for a
+ * job that terminated normally. A zero value can also indicate that
+ * altough the job has terminated normally an exit status is not available
+ * or that it is not known whether the job terminated normally. In both
+ * cases drmaa_wexitstatus() SHALL NOT provide exit status information.
+ * A non-zero 'exited' value indicates more detailed diagnosis can be provided
+ * by means of drmaa_wifsignaled(), drmaa_wtermsig() and drmaa_wcoredump().
+ */
+public static native int drmaa_wifexited(IntByReference exited, int stat, Pointer error_diagnosis,
+                    NativeLong error_diag_len);
+
+/*
+ * If the OUT parameter 'exited' of drmaa_wifexited() is non-zero,
+ * this function evaluates into 'exit_code' the exit code that the
+ * job passed to _exit() (see exit(2)) or exit(3C), or the value that
+ * the child process returned from main.
+ */
+public static native int drmaa_wexitstatus(IntByReference exit_status, int stat, Pointer error_diagnosis,
+                      NativeLong error_diag_len);
+
+/*
+ * Evaluates into 'signaled' a non-zero value if status was returned
+ * for a job that terminated due to the receipt of a signal. A zero value
+ * can also indicate that altough the job has terminated due to the receipt
+ * of a signal the signal is not available or that it is not known whether
+ * the job terminated due to the receipt of a signal. In both cases
+ * drmaa_wtermsig() SHALL NOT provide signal information.
+ */
+public static native int drmaa_wifsignaled(IntByReference signaled, int stat, Pointer error_diagnosis,
+                      NativeLong error_diag_len);
+
+/*
+ * If the OUT parameter 'signaled' of drmaa_wifsignaled(stat) is
+ * non-zero, this function evaluates into signal a string representation of the
+ * signal that caused the termination of the job. For signals declared by POSIX,
+ * the symbolic names SHALL be returned (e.g., SIGABRT, SIGALRM).
+ * For signals not declared by POSIX, any other string MAY be returned.
+ */
+public static native int drmaa_wtermsig(Pointer signal, NativeLong signal_len, int stat,
+                   Pointer error_diagnosis, NativeLong error_diag_len);
+
+/*
+ * If the OUT parameter 'signaled' of drmaa_wifsignaled(stat) is
+ * non-zero, this function evaluates into 'core_dumped' a non-zero value
+ * if a core image of the terminated job was created.
+ */
+public static native int drmaa_wcoredump(IntByReference core_dumped, int stat, Pointer error_diagnosis,
+                    NativeLong error_diag_len);
+
+/*
+ * Evaluates into 'aborted' a non-zero value if 'stat'
+ * was returned for a job that ended before entering the running state.
+ */
+public static native int drmaa_wifaborted(IntByReference aborted, int stat, Pointer error_diagnosis,
+                     NativeLong error_diag_len);
+
+
+
+/*
+ * Get the program status of the job identified by 'job_id'.
+ * The possible values returned in 'remote_ps' and their meanings SHALL be:
+ *
+ * DRMAA_PS_UNDETERMINED          = 0x00: process status cannot be determined
+ * DRMAA_PS_QUEUED_ACTIVE         = 0x10: job is queued and active
+ * DRMAA_PS_SYSTEM_ON_HOLD        = 0x11: job is queued and in system hold
+ * DRMAA_PS_USER_ON_HOLD          = 0x12: job is queued and in user hold
+ * DRMAA_PS_USER_SYSTEM_ON_HOLD   = 0x13: job is queued and in user and system
+ *                                        hold
+ * DRMAA_PS_RUNNING               = 0x20: job is running
+ * DRMAA_PS_SYSTEM_SUSPENDED      = 0x21: job is system suspended
+ * DRMAA_PS_USER_SUSPENDED        = 0x22: job is user suspended
+ * DRMAA_PS_USER_SYSTEM_SUSPENDED = 0x23: job is user and system suspended
+ * DRMAA_PS_DONE                  = 0x30: job finished normally
+ * DRMAA_PS_FAILED                = 0x40: job finished, but failed
+ *
+ * DRMAA SHOULD always get the status of job_id from DRM system, unless the
+ * previous status has been DRMAA_PS_FAILED or DRMAA_PS_DONE and the status has
+ * been successfully cached. Terminated jobs get DRMAA_PS_FAILED status.
+ *
+ * drmaa_synchronize() SHALL return DRMAA_ERRNO_SUCCESS on success, otherwise:
+ *    DRMAA_ERRNO_DRM_COMMUNICATION_FAILURE,
+ *    DRMAA_ERRNO_AUTH_FAILURE,
+ *    DRMAA_ERRNO_NO_MEMORY or
+ *    DRMAA_ERRNO_INVALID_JOB.
+ */
+public static native int drmaa_job_ps(String job_id, IntByReference remote_ps, Pointer error_diagnosis,
+                 NativeLong error_diag_len);
+
+/* ------------------- auxiliary routines ------------------- */
+
+/*
+ * SHALL return the error message text associated with the errno number. The
+ * routine SHALL return null string if called with invalid ERRNO number.
+ */
+public static native String drmaa_strerror(int drmaa_errno);
+
+/*
+ * If called before drmaa_init(), it SHALL return a comma delimited default
+ * DRMAA implementation contacts string, one per each DRM system provided
+ * implementation. If called after drmaa_init(), it SHALL return the selected
+ * contact string. The output string is Implementation dependent.
+ * drmaa_get_contact() SHALL return DRMAA_ERRNO_SUCCESS on success, otherwise:
+ *    DRMAA_ERRNO_INTERNAL_ERROR.
+ */
+public static native int drmaa_get_contact(Pointer contact, NativeLong contact_len,
+         Pointer error_diagnosis, NativeLong error_diag_len);
+
+/*
+ * OUT major - major version number (non-negative integer)
+ * OUT minor - minor version number (non-negative integer)
+ * SHALL return the major and minor version numbers of the DRMAA library;
+ * for DRMAA 1.0, 'major' is 1 and 'minor' is 0.
+ */
+public static native int drmaa_version(IntByReference major, IntByReference minor,
+         Pointer error_diagnosis, NativeLong error_diag_len);
+
+
+/*
+ * If called before drmaa_init(), it SHALL return a comma delimited DRM systems
+ * string, one per each DRM system provided implementation. If called after
+ * drmaa_init(), it SHALL return the selected DRM system. The output string is
+ * implementation dependent.
+ *
+ * drmaa_get_DRM_system() SHALL return DRMAA_ERRNO_SUCCESS on success,
+ * otherwise:
+ *    DRMAA_ERRNO_INTERNAL_ERROR.
+ */
+public static native int drmaa_get_DRM_system(Pointer drm_system, NativeLong drm_system_len,
+         Pointer error_diagnosis, NativeLong error_diag_len);
+
+
+/*
+ * If called before drmaa_init(), it SHALL return a comma delimited DRMAA
+ * implementations string, one per each DRM system provided implementation. If
+ * called after drmaa_init(), it SHALL return the selected DRMAA implementation.
+ * The output (string) is implementation dependent. drmaa_get_DRM_implementation
+ * routine SHALL return DRMAA_ERRNO_SUCCESS on success, otherwise:
+ *    DRMAA_ERRNO_INTERNAL_ERROR.
+ */
+public static native int drmaa_get_DRMAA_implementation(Pointer drmaa_impl, NativeLong drmaa_impl_len,
+         Pointer error_diagnosis, NativeLong error_diag_len);
+}
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/jna/lsf/v7_0_6/LibBat.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/jna/lsf/v7_0_6/LibBat.java
new file mode 100644
index 0000000..e66a40d
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/jna/lsf/v7_0_6/LibBat.java
@@ -0,0 +1,20014 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.utils.jna.lsf.v7_0_6;
+
+import com.sun.jna.*;
+import com.sun.jna.ptr.*;
+import org.broadinstitute.gatk.utils.jna.clibrary.JNAUtils;
+import org.broadinstitute.gatk.utils.jna.clibrary.LibC;
+
+/*
+  NOTE: This library uses Pointer for some Struct.ByReference members going
+  against the JNA recommendations at http://jna.java.net/#structure_use
+  Instead stuct arrays are Pointers and each structure contains a
+  constructor that can accept the Pointer iff the size of the array is
+  known to be greater than zero.
+
+  This was especially problematic in jobInfoEnt->items->resName. When
+  jobInfo->reserveCnt was zero jobInfoItems->items was not necessarily null.
+
+  LSF will often reuse memory for structure arrays but will set the
+  array size / count (reserveCnt above) to zero when the array should
+  not be accessed. When LSF has reused memory and points to a non-null
+  structure pointer (items) the inner structure may contain further
+  garbage pointers (especially items->resName).
+
+  When JNA sees a non-null Structure.ByReference it will autoRead() the
+  member. When autoRead() eventually gets to the items->resName trying
+  to run strlen on the bad memory address causes a SIGSEGV.
+
+  By using a Pointer instead of the Structure.ByReference JNA will not
+  automatically autoRead(), and the API user will have to pass the
+  pointer to the Structure on their own.
+*/
+
+/**
+ * JNA wrappers for LSF's lsbatch.h and -lbat
+ *
+ * $Id: lsbatch.h,v 2.1043 2009/08/06 16:50:49 bxia Exp $
+ * -----------------------------------------------------------------
+ *
+ *  Lsbatch Distributed Batch Utility --
+ *
+ *  Header file for all lsbatch components: applications, lsblib,
+ *                                          mbatchd and sbatchd
+ *
+ * ------------------------------------------------------------------
+ */
+ at SuppressWarnings("unused")
+public class LibBat {
+
+    static {
+        // via Platform LSF Configuration Reference, by default quiet the BSUB output.
+        if ("Y".equals(System.getProperty("BSUB_QUIET", "Y")))
+            LibC.setenv("BSUB_QUIET", "Y", 1);
+        String lsfLibDir = System.getenv("LSF_LIBDIR");
+        if (lsfLibDir != null) {
+            NativeLibrary.addSearchPath("lsf", lsfLibDir);
+            NativeLibrary.addSearchPath("bat", lsfLibDir);
+        }
+        /*
+        LSF 7.0.6 on the mac is missing the unsatisfied exported symbol for environ which was removed on MacOS X 10.5+.
+        nm $LSF_LIBDIR/liblsf.dylib | grep environ
+        See "man environ" for more info, along with http://lists.apple.com/archives/java-dev/2007/Dec/msg00096.html
+        For now, we export environ ourselves using libenvironhack.dylib available in c/libenvironhack.
+        */
+        if (Platform.isMac())
+            NativeLibrary.getInstance("environhack");
+        NativeLibrary liblsf = NativeLibrary.getInstance("lsf");
+        Native.register("bat");
+        // HACK: Running into a weird error:
+        //   java.lang.UnsatisfiedLinkError: Unable to load library 'bat': <$LSF_LIBDIR>/libbat.so: undefined symbol: xdr_resourceInfoReq
+        // This function is very clearly unsatisfied by running 'nm $LSF_LIBDIR/libbat.so | grep xdr_resourceInfoReq' but is
+        // found in liblsf.so when running 'nm $LSF_LIBDIR/liblsf.so | grep xdr_resourceInfoReq'. For now holding on to a reference
+        // to the LSF lib just in case this is a problem with the NativeLibrary's internal WeakReferences and the library being unloaded?
+        liblsf.getFunction("xdr_resourceInfoReq").getName();
+    }
+
+    // Via support at platform.com:
+    //    For equivalent api of bsub -a "xxx aaa qqq", option -a is not in struct submit, we
+    //    have to use setOption_ to set it. setOption_ can be used in user program by including
+    //    cmd.h or opensource.h of LSF opensource. You can refer to cmd.sub.c in opensource.
+    //
+    //    Here is a demonstration on the api for bsub -a
+    //    =========================================================================
+    //    /*define external setOption_ function*/
+    //    extern int setOption_(int argc, char **argv, char *template,
+    //    struct submit *req, int mask, int mask2, char **errMsg);
+    //
+    //    int setEsub(char *esub, struct submit *req) {
+    //    int x;
+    //    char *template, *arg[3];
+    //    /*set esub with the following strings and set array length*/
+    //    arg[0] = "blah";
+    //    arg[1] = "-a";
+    //    arg[2] = test;
+    //    /* -a "test", You can add additional esubs in here.  Just make sure they're space delimited.  ie. "test mpich lammpi" */
+    //    x=3;
+    //    /*set template*/
+    //    template = "a:"
+    //    /*run setOption_()*/
+    //    if (setOption_(x, arg, template, req, ~0, ~0, ~0, NULL) == -1) {
+    //    return(-1);
+    //    }
+    //    else {
+    //    return(0);
+    //    }
+    //    }
+    //    =========================================================================
+
+    /**
+     * Used for setting esub and other options not in struct submit.
+     * Via support at platform.com
+     *
+     * @param argc number of args
+     * @param argv arguments including a first argument that will not be used
+     * @param template a colon delimited list of arguments in getopt format
+     * @param jobSubReq the lsf submit
+     * @param mask unknown
+     * @param mask2 unknown
+     * @param mask3 unknown
+     * @param errMsg unknown
+     * @return -1 if the option setting failed
+     */
+    public static native int setOption_(int argc, Pointer argv, String template, submit jobSubReq, int mask, int mask2, int mask3, Pointer errMsg);
+
+    /** Max job name length as defined by 'man bsub'. */
+    public static final int MAX_JOB_NAME_LEN = 4094;
+
+/* if only everyone had <paths.h> */
+    public static final String _PATH_NULL = "/dev/null";
+
+    //public static int SKIP_SPACES (int word)  { while (word[0] == ' ' )  word++; }
+
+    //public static void FREEUP_ARRAY(int num, Pointer vector) { FREE_STRING_VECTOR_ENTRIES(num, vector);  FREEUP(vector); }
+
+
+/* event log version:
+*  each new major release requires to add a new line
+ */
+    public static final float LSB_EVENT_VERSION3_0 = 3.0f;
+    public static final float LSB_EVENT_VERSION3_1 = 3.1f;
+    public static final float LSB_EVENT_VERSION3_2 = 3.2f;
+    public static final float LSB_EVENT_VERSION4_0 = 4.0f;
+    public static final float LSB_EVENT_VERSION4_1 = 4.1f;
+    public static final float LSB_EVENT_VERSION4_2 = 4.2f;
+    public static final float LSB_EVENT_VERSION5_0 = 5.0f;
+    public static final float LSB_EVENT_VERSION5_1 = 5.1f;
+    public static final float LSB_EVENT_VERSION6_0 = 6.0f;
+    public static final float LSB_EVENT_VERSION6_1 = 6.1f;
+    public static final float LSB_EVENT_VERSION6_2 = 6.2f;
+    public static final float LSB_EVENT_VERSION7_0 = 7.0f;
+    public static final float LSB_EVENT_VERSION7_0_1 = 7.01f;
+    public static final float LSB_EVENT_VERSION7_0_2 = 7.02f;
+    public static final float LSB_EVENT_VERSION7_0_3 = 7.03f;
+    public static final float LSB_EVENT_VERSION7_0_4 = 7.04f;
+    public static final float LSB_EVENT_VERSION7_0_5 = 7.05f;
+    public static final float LSB_EVENT_VERSION7_0_6 = 7.06f;
+
+/* current event version number of the mbatchd */
+    public static final String THIS_VERSION = "7.06";
+
+    public static final int MAX_VERSION_LEN = 12;
+
+/* num of users per host partition */
+    public static final int MAX_HPART_USERS = 100;
+
+/* max byte limit, OS independent */
+    public static final int MAX_CHARLEN = 20;
+
+/* the max length of name */
+    public static final int MAX_LSB_NAME_LEN = 60;
+
+/*the max length of user group*/
+    public static final int MAX_LSB_UG_NAME_LEN = 512;
+
+/*Maximum levels that a user group hierachy can have*/
+    public static final int MAX_LSB_UG_HIERDEPTH = 64;
+
+/* the max length of command */
+    public static final int MAX_CMD_DESC_LEN = 512;
+
+/* for the local cluster */
+    public static final int MAX_CALENDARS = 256;
+
+/* max num of user equivalent entries */
+    public static final int MAX_USER_EQUIVALENT = 128;
+
+/* max num of user mapping entries */
+    public static final int MAX_USER_MAPPING = 128;
+
+/* max external msg's description length */
+    public static final int MAXDESCLEN = 20 * 512;
+
+/* num of user or host group */
+    public static final int MAX_GROUPS = 1024;
+
+/*
+*  RFC #725
+ */
+
+/* max len. of a filename */
+    public static final int MAXFULLFILENAMELEN = 4096;
+    public static final int MAXFULLPATHNAMELEN = 2 * MAXFULLFILENAMELEN;
+    public static final int FILENAMEPADDING = 128;
+
+    public static final String DEFAULT_MSG_DESC = "no description";
+
+    public static final int MSGSIZE = 4096;
+
+/* RFC #725
+*  extend the MSG size to 4*max filename len
+ */
+    public static final int MAXFULLMSGSIZE = 4 * MAXFULLFILENAMELEN;
+
+/* host status (hStatus) bits */
+    /**
+     *  \addtogroup host_status host_status
+     *  The status of the host. It is the bitwise inclusive OR of some of the following:
+     */
+
+    /**
+     * < Ready to accept and run jobs
+     */
+    public static final int HOST_STAT_OK = 0x0;
+
+/* Load is not good enough */
+    public static final int HOST_STAT_BUSY = 0x01;
+    /**
+     * < The host load is greater than a scheduling threshold. In this status, no new job will be scheduled to run on this host.
+     */
+
+/* Run windows are closed */
+    public static final int HOST_STAT_WIND = 0x02;
+    /**
+     * < The host dispatch window is closed. In this status, no new job will be accepted.
+     */
+
+/* Disabled by admin */
+    public static final int HOST_STAT_DISABLED = 0x04;
+    /**
+     * < The host has been disabled by the LSF administrator and will not accept jobs. In this status, no new job will be scheduled to  run on this host.
+     */
+
+/* Lim locked by admin */
+    public static final int HOST_STAT_LOCKED = 0x08;
+    /**< The host is locked by a exclusive task. In this status, no new job will be scheduled to run on this host.*/
+
+    /**
+     * < Great than job limit
+     */
+    public static final int HOST_STAT_FULL = 0x10;
+    /**< The host has reached its job limit. In this status, no new job will be scheduled to run on this host.*/
+
+    /**
+     * < The sbatchd on this host is unreachable.
+     */
+    public static final int HOST_STAT_UNREACH = 0x20;
+
+    /**
+     * < The LIM and sbatchd on this host are unavailable.
+     */
+    public static final int HOST_STAT_UNAVAIL = 0x40;
+
+    /**
+     * < The host does not have an LSF license.
+     */
+    public static final int HOST_STAT_UNLICENSED = 0x80;
+
+    /**
+     * < The host is running an sbatchd but not a LIM.
+     */
+    public static final int HOST_STAT_NO_LIM = 0x100;
+
+    /**
+     * < Running exclusive job
+     */
+    public static final int HOST_STAT_EXCLUSIVE = 0x200;
+
+    /**
+     * < Lim locked by master LIM
+     */
+    public static final int HOST_STAT_LOCKED_MASTER = 0x400;
+
+    /**
+     * < Close a remote lease host. This flag is  used together with HOST_STAT_DISABLED.
+     */
+    public static final int HOST_STAT_REMOTE_DISABLED = 0x800;
+
+    /**
+     * < Close a remote lease host due to the  lease is renewing or terminating.
+     */
+    public static final int HOST_STAT_LEASE_INACTIVE = 0x1000;
+
+/* if LSF_HPC_EXTENTIONS="LSB_HCLOSE_BY_RES" is set in lsf.conf
+*  host will be closed if RES is unavailable.
+ */
+
+    /**
+     * < Host is disabled by RES
+     */
+    public static final int HOST_STAT_DISABLED_RES = 0x4000;
+
+/* Kite#29531 a bit set in hData->hStatus
+*  to show whether the host is closed by
+*  admin or closed because RMS is not available.
+ */
+
+    /**
+     * < Host is disabled by RMS
+     */
+    public static final int HOST_STAT_DISABLED_RMS = 0x8000;
+
+/* lsf70 project scheduling, a removed host from mbatchd move into
+*  a new status HOST_STAT_LOCKED_EGO
+ */
+
+    /**
+     * < The host is disabled by EGO
+     */
+    public static final int HOST_STAT_LOCKED_EGO = 0x10000;
+
+    /**
+     * < If none of the above hold, hStatus is set to HOST_STAT_OK to indicate that the host is ready to accept and run jobs.
+     */
+    public static final int HOST_CLOSED_BY_ADMIN = 0x20000;
+
+    /**
+     * < Running cu exclusive job
+     */
+    public static final int HOST_STAT_CU_EXCLUSIVE = 0x40000;
+
+/* host is ok */
+
+    public static boolean LSB_HOST_OK(int status) {
+        return (status == HOST_STAT_OK);
+    }
+
+/* host is busy */
+
+    public static boolean LSB_HOST_BUSY(int status) {
+        return ((status & HOST_STAT_BUSY) != 0);
+    }
+
+/* host is closed */
+
+    public static boolean LSB_HOST_CLOSED(int status) {
+        return ((status & (HOST_STAT_WIND | HOST_STAT_DISABLED | HOST_STAT_LOCKED | HOST_STAT_LOCKED_MASTER | HOST_STAT_FULL | HOST_STAT_CU_EXCLUSIVE | HOST_STAT_EXCLUSIVE | HOST_STAT_LEASE_INACTIVE | HOST_STAT_NO_LIM)) != 0);
+    }
+
+/* host is full */
+
+    public static boolean LSB_HOST_FULL(int status) {
+        return ((status & HOST_STAT_FULL) != 0);
+    }
+
+/* host is unlicensed */
+
+    public static boolean LSB_HOST_UNLICENSED(int status) {
+        return ((status & HOST_STAT_UNLICENSED) != 0);
+    }
+
+/* host is unreach */
+
+    public static boolean LSB_HOST_UNREACH(int status) {
+        return ((status & HOST_STAT_UNREACH) != 0);
+    }
+
+/* host is unavail */
+
+    public static boolean LSB_HOST_UNAVAIL(int status) {
+        return ((status & HOST_STAT_UNAVAIL) != 0);
+    }
+
+
+    /* host busy reason bits */
+    /**
+     *  \addtogroup host_load_BusyReason host_load_BusyReason
+     *  If hStatus is HOST_STAT_BUSY, these indicate the host loadSched or loadStop
+     *  busy reason. If none of the thresholds have been exceeded, the value is
+     *  HOST_BUSY_NOT. Otherwise the value is the bitwise inclusive OR of some of the
+     *  following:
+     */
+
+    /**
+     * < Host not busy
+     */
+    public static final int HOST_BUSY_NOT = 0x000;
+
+    /**
+     * < The 15 second average CPU run queue length is too high.
+     */
+    public static final int HOST_BUSY_R15S = 0x001;
+
+    /**
+     * < The 1 minute average CPU run queue length is too high.
+     */
+    public static final int HOST_BUSY_R1M = 0x002;
+
+    /**
+     * < The 15 minute average CPU run queue length is too high.
+     */
+    public static final int HOST_BUSY_R15M = 0x004;
+
+    /**
+     * < The CPU utilization is too high.
+     */
+    public static final int HOST_BUSY_UT = 0x008;
+
+    /**
+     * < The paging rate is too high.
+     */
+    public static final int HOST_BUSY_PG = 0x010;
+
+    /**
+     * < The I/O rate is too high.
+     */
+    public static final int HOST_BUSY_IO = 0x020;
+
+    /**
+     * < There are too many login sessions.
+     */
+    public static final int HOST_BUSY_LS = 0x040;
+
+    /**
+     * < Host has not been idle long enough.
+     */
+    public static final int HOST_BUSY_IT = 0x080;
+
+    /**
+     * < There is not enough free space in the file  system containing /tmp.
+     */
+    public static final int HOST_BUSY_TMP = 0x100;
+
+    /**
+     * < There is not enough free swap space.
+     */
+    public static final int HOST_BUSY_SWP = 0x200;
+
+    /**
+     * < There is not enough free memory.
+     */
+    public static final int HOST_BUSY_MEM = 0x400;
+
+/* host is busy */
+
+    public static boolean LSB_ISBUSYON(int[] status, int index) {
+        return (((status[(index) / LibLsf.INTEGER_BITS]) & (1 << (index) % LibLsf.INTEGER_BITS)) != 0);
+    }
+
+
+/* queue status (qStatus) bits */
+    /**
+     *  \addtogroup queue_status queue_status
+     *  queue status (qStatus) bits
+     */
+
+    /**
+     * < The queue is open to accept newly submitted jobs.
+     */
+    public static final int QUEUE_STAT_OPEN = 0x01;
+
+    /**
+     * < The queue is actively dispatching jobs. The queue can be inactivated and  reactivated by the LSF administrator using  \ref lsb_queuecontrol. The queue will also be inactivated when its run or dispatch window  is closed. In this case it cannot be reactivated manually; it will be reactivated by the LSF system when its run and dispatch windows reopen.
+     */
+    public static final int QUEUE_STAT_ACTIVE = 0x02;
+
+    /**
+     * < The queue run and dispatch windows are open. The initial state of a queue at LSF boot time is open and either active or inactive, depending on its run and dispatch windows.
+     */
+    public static final int QUEUE_STAT_RUN = 0x04;
+
+    /**
+     * < Remote queue rejecting jobs.
+     */
+    public static final int QUEUE_STAT_NOPERM = 0x08;
+
+    /**
+     * < Remote queue status is disconnected.
+     */
+    public static final int QUEUE_STAT_DISC = 0x10;
+
+    /**
+     * < Queue run windows are closed.
+     */
+    public static final int QUEUE_STAT_RUNWIN_CLOSE = 0x20;
+
+/* queue attribute (QAttrib) bits */
+    /**
+     *  \addtogroup queue_attribute queue_attribute
+     *  queue attribute (QAttrib) bits.
+     */
+
+    /**
+     * < This queue accepts jobs which request exclusive execution.
+     */
+    public static final int Q_ATTRIB_EXCLUSIVE = 0x01;
+
+    /**
+     * < This queue is a default LSF queue.
+     */
+    public static final int Q_ATTRIB_DEFAULT = 0x02;
+
+    /**
+     * < This queue uses the FAIRSHARE scheduling policy. The user shares  are given in userShares.
+     */
+    public static final int Q_ATTRIB_FAIRSHARE = 0x04;
+
+    /**
+     * < This queue uses the PREEMPTIVE scheduling policy.
+     */
+    public static final int Q_ATTRIB_PREEMPTIVE = 0x08;
+
+    /**
+     * < This is an NQS forward queue. The target NQS queues are given in nqsQueues. For NQS forward queues, the hostList, procJobLimit, windows, mig and windowsD fields are meaningless.
+     */
+    public static final int Q_ATTRIB_NQS = 0x10;
+
+    /**
+     * < This queue can receive jobs from other clusters
+     */
+    public static final int Q_ATTRIB_RECEIVE = 0x20;
+
+    /**
+     * < This queue uses a preemptable scheduling policy.
+     */
+    public static final int Q_ATTRIB_PREEMPTABLE = 0x40;
+
+    /**
+     * < This queue uses a backfilling policy.
+     */
+    public static final int Q_ATTRIB_BACKFILL = 0x80;
+
+    /**
+     * < This queue uses a host preference policy.
+     */
+    public static final int Q_ATTRIB_HOST_PREFER = 0x100;
+
+    /**
+     * < This queue can't preempt any other another queue.
+     */
+    public static final int Q_ATTRIB_NONPREEMPTIVE = 0x200;
+
+    /**
+     * < This queue can't be preempted from any queue.
+     */
+    public static final int Q_ATTRIB_NONPREEMPTABLE = 0x400;
+
+    /**
+     * < This queue does not accept batch interactive jobs.
+     */
+    public static final int Q_ATTRIB_NO_INTERACTIVE = 0x800;
+
+    /**
+     * < This queue only accepts batch interactive jobs.
+     */
+    public static final int Q_ATTRIB_ONLY_INTERACTIVE = 0x1000;
+
+    /**
+     * < No host type related resource name specified in resource requirement.
+     */
+    public static final int Q_ATTRIB_NO_HOST_TYPE = 0x2000;
+
+    /**
+     * < This queue disables deadline constrained resource scheduling.
+     */
+    public static final int Q_ATTRIB_IGNORE_DEADLINE = 0x4000;
+
+    /**
+     * < Jobs may run as chkpntable.
+     */
+    public static final int Q_ATTRIB_CHKPNT = 0x8000;
+
+    /**
+     * < Jobs may run as rerunnable.
+     */
+    public static final int Q_ATTRIB_RERUNNABLE = 0x10000;
+
+    /**
+     * < Excluding remote jobs when local jobs are present in the queue.
+     */
+    public static final int Q_ATTRIB_EXCL_RMTJOB = 0x20000;
+
+    /**
+     * < Turn on a multicluster fast scheduling policy.
+     */
+    public static final int Q_ATTRIB_MC_FAST_SCHEDULE = 0x40000;
+
+    /**
+     * < Push interactive jobs in front of other jobs in queue.
+     */
+    public static final int Q_ATTRIB_ENQUE_INTERACTIVE_AHEAD = 0x80000;
+
+/* Only one of the following four flags could be TRUE. By default, the queue
+*  is a local queue only(none of them is set.)
+*      0x100000 - 0xf00000 is used for MC attribute
+ */
+
+
+    /**
+     * < Flags used by MultiCluster.
+     */
+    public static final int Q_MC_FLAG = 0xf00000;
+
+    /**
+     * < Lease and local.
+     */
+    public static final int Q_ATTRIB_LEASE_LOCAL = 0x100000;
+
+    /**
+     * < Lease only; no local.
+     */
+    public static final int Q_ATTRIB_LEASE_ONLY = 0x200000;
+
+    /**
+     * < Remote batch and local.
+     */
+    public static final int Q_ATTRIB_RMT_BATCH_LOCAL = 0x300000;
+
+    /**
+     * < Remote batch only.
+     */
+    public static final int Q_ATTRIB_RMT_BATCH_ONLY = 0x400000;
+
+
+    /**
+     * < Memory reservation.
+     */
+    public static final int Q_ATTRIB_RESOURCE_RESERVE = 0x1000000;
+
+    /**
+     * < Cross-queue fairshare.
+     */
+    public static final int Q_ATTRIB_FS_DISPATCH_ORDER_QUEUE = 0x2000000;
+
+    /**
+     * < Batch queue/partition
+     */
+    public static final int Q_ATTRIB_BATCH = 0x4000000;
+
+    /**
+     * < Online partition
+     */
+    public static final int Q_ATTRIB_ONLINE = 0x8000000;
+
+    /**
+     * < Interruptible backfill
+     */
+    public static final int Q_ATTRIB_INTERRUPTIBLE_BACKFILL = 0x10000000;
+
+    /**
+     * < Absolute Priority scheduling (APS) value.
+     */
+    public static final int Q_ATTRIB_APS = 0x20000000;
+
+    /**
+     * < No queue with RESOURCE_RESERVE or SLOT_RESERVE has higher priority than this queue.
+     */
+    public static final int Q_ATTRIB_NO_HIGHER_RESERVE = 0x40000000;
+
+    /**
+     * < No host valid
+     */
+    public static final int Q_ATTRIB_NO_HOST_VALID = 0x80000000;
+
+
+/* macros to check queue near real time attributes */
+
+    public static int IS_ONLINE_QUEUE(queueInfoEnt Q) {
+        return (Q.qAttrib & Q_ATTRIB_ONLINE);
+    }
+
+    public static int IS_BATCH_QUEUE(queueInfoEnt Q) {
+        return (Q.qAttrib & Q_ATTRIB_BATCH);
+    }
+
+/* macros to check queue remote attributes */
+
+    public static boolean IS_LEASE_LOCAL_QUEUE(queueInfoEnt Q) {
+        return ((Q.qAttrib & Q_MC_FLAG) == Q_ATTRIB_LEASE_LOCAL);
+    }
+
+    public static boolean IS_LEASE_ONLY_QUEUE(queueInfoEnt Q) {
+        return ((Q.qAttrib & Q_MC_FLAG) == Q_ATTRIB_LEASE_ONLY);
+    }
+
+    public static boolean IS_RMT_BATCH_LOCAL_QUEUE(queueInfoEnt Q) {
+        return ((Q.qAttrib & Q_MC_FLAG) == Q_ATTRIB_RMT_BATCH_LOCAL);
+    }
+
+    public static boolean IS_RMT_BATCH_ONLY_QUEUE(queueInfoEnt Q) {
+        return ((Q.qAttrib & Q_MC_FLAG) == Q_ATTRIB_RMT_BATCH_ONLY);
+    }
+
+    public static boolean IS_LEASE_QUEUE(queueInfoEnt Q) {
+        return (IS_LEASE_LOCAL_QUEUE(Q) || IS_LEASE_ONLY_QUEUE(Q));
+    }
+
+    public static boolean IS_RMT_BATCH_QUEUE(queueInfoEnt Q) {
+        return (IS_RMT_BATCH_LOCAL_QUEUE(Q) || IS_RMT_BATCH_ONLY_QUEUE(Q));
+    }
+
+    public static boolean IS_MC_QUEUE(queueInfoEnt Q) {
+        return (IS_LEASE_QUEUE(Q) || IS_RMT_BATCH_QUEUE(Q));
+    }
+
+    public static int SET_LEASE_LOCAL_QUEUE(queueInfoEnt Q) {
+        return (Q.qAttrib |= Q_ATTRIB_LEASE_LOCAL);
+    }
+
+    public static int SET_LEASE_ONLY_QUEUE(queueInfoEnt Q) {
+        return (Q.qAttrib |= Q_ATTRIB_LEASE_ONLY);
+    }
+
+    public static int SET_RMT_BATCH_LOCAL_QUEUE(queueInfoEnt Q) {
+        return (Q.qAttrib |= Q_ATTRIB_RMT_BATCH_LOCAL);
+    }
+
+    public static int SET_RMT_BATCH_ONLY_QUEUE(queueInfoEnt Q) {
+        return (Q.qAttrib |= Q_ATTRIB_RMT_BATCH_ONLY);
+    }
+
+    public static int CLR_MC_QUEUE_FLAG(queueInfoEnt Q) {
+        return (Q.qAttrib &= ~Q_MC_FLAG);
+    }
+
+
+/* the bits 0x10000000 to 0x80000000 is reserved for internal use (daemons.h) */
+
+/* exit code for mbatchd */
+    public static final int MASTER_NULL = 200;
+    public static final int MASTER_RESIGN = 201;
+    public static final int MASTER_RECONFIG = 202;
+    public static final int MASTER_FATAL = 203;
+    public static final int MASTER_MEM = 204;
+    public static final int MASTER_CONF = 205;
+    public static final int MASTER_EVENT = 206;
+    public static final int MASTER_DISABLE = 207;
+
+/* sub type of mbatchd die */
+    public static final int MBD_USER_CMD = 1;
+    public static final int MBD_NON_USER_CMD = 2;
+
+    /**
+     *  \addtogroup job_states job_states
+     *  define job states
+     */
+
+    /**
+     * < State null
+     */
+    public static final int JOB_STAT_NULL = 0x00;
+
+    /**
+     * < The job is pending, i.e., it  has not been dispatched yet.
+     */
+    public static final int JOB_STAT_PEND = 0x01;
+
+    /**
+     * < The pending job was suspended by its owner or the LSF system administrator.
+     */
+    public static final int JOB_STAT_PSUSP = 0x02;
+
+    /**
+     * < The job is running.
+     */
+    public static final int JOB_STAT_RUN = 0x04;
+
+    /**
+     * < The running job was suspended  by the system because an execution  host was overloaded or the queue run  window closed. (see \ref lsb_queueinfo,  \ref lsb_hostinfo, and lsb.queues.)
+     */
+    public static final int JOB_STAT_SSUSP = 0x08;
+
+    /**
+     * < The running job was suspended by its owner or the LSF systemadministrator.
+     */
+    public static final int JOB_STAT_USUSP = 0x10;
+
+    /**
+     * < The job has terminated with a non-zero status - it may have been aborted due  to an error in its execution, or  killed by its owner or by the  LSF system administrator.
+     */
+    public static final int JOB_STAT_EXIT = 0x20;
+
+    /**
+     * < The job has terminated with status 0.
+     */
+    public static final int JOB_STAT_DONE = 0x40;
+
+    /**
+     * < Post job process done successfully
+     */
+    public static final int JOB_STAT_PDONE = (0x80);
+
+    /**
+     * < Post job process has error
+     */
+    public static final int JOB_STAT_PERR = (0x100);
+
+    /**
+     * < Chunk job waiting its turn to exec
+     */
+    public static final int JOB_STAT_WAIT = (0x200);
+
+    /**
+     * < The slave batch daemon (sbatchd) on  the host on which the job is processed  has lost contact with the master batch  daemon (mbatchd).
+     */
+    public static final int JOB_STAT_UNKWN = 0x10000;
+
+    /**
+     *  \addtogroup event_types event_types
+     *  define statements used by \ref lsb_geteventrec. Events logged in lsb.events file
+     */
+
+    /**
+     * < Submit a new job
+     */
+    public static final int EVENT_JOB_NEW = 1;
+
+    /**
+     * < mbatchd is trying to start a job
+     */
+    public static final int EVENT_JOB_START = 2;
+
+    /**
+     * < Job's status change event
+     */
+    public static final int EVENT_JOB_STATUS = 3;
+
+    /**
+     * < Job switched to another queue
+     */
+    public static final int EVENT_JOB_SWITCH = 4;
+
+    /**
+     * < Move a pending job's position within a queue
+     */
+    public static final int EVENT_JOB_MOVE = 5;
+
+    /**
+     * < Queue's status changed by Platform LSF  administrator (bhc operation)
+     */
+    public static final int EVENT_QUEUE_CTRL = 6;
+
+    /**
+     * < Host status changed by Platform LSF  administrator (bhc operation)
+     */
+    public static final int EVENT_HOST_CTRL = 7;
+
+    /**
+     * < Log parameters before mbatchd died
+     */
+    public static final int EVENT_MBD_DIE = 8;
+
+    /**
+     * < Action that was not taken because the  mbatchd was unable to contact the sbatchd on the job's execution host
+     */
+    public static final int EVENT_MBD_UNFULFILL = 9;
+
+    /**
+     * < Job finished (Logged in lsb.acct)
+     */
+    public static final int EVENT_JOB_FINISH = 10;
+
+    /**
+     * < The complete list of load indices, including external load indices
+     */
+    public static final int EVENT_LOAD_INDEX = 11;
+
+    /**
+     * < Job checkpointed.
+     */
+    public static final int EVENT_CHKPNT = 12;
+
+    /**
+     * < Job migrated
+     */
+    public static final int EVENT_MIG = 13;
+
+    /**
+     * < The pre-execution command started
+     */
+    public static final int EVENT_PRE_EXEC_START = 14;
+
+    /**
+     * < New mbatchd start event
+     */
+    public static final int EVENT_MBD_START = 15;
+
+    /**
+     * < The job has been routed to NQS
+     */
+    public static final int EVENT_JOB_ROUTE = 16;
+
+    /**
+     * < Job modification request
+     */
+    public static final int EVENT_JOB_MODIFY = 17;
+
+    /**
+     * < Signal/delete a job
+     */
+    public static final int EVENT_JOB_SIGNAL = 18;
+
+    /**
+     * < Add new calendar to the system
+     */
+    public static final int EVENT_CAL_NEW = 19;
+
+    /**
+     * < Calendar modified
+     */
+    public static final int EVENT_CAL_MODIFY = 20;
+
+    /**
+     * < Delete a calendar in the system
+     */
+    public static final int EVENT_CAL_DELETE = 21;
+
+    /**
+     * < Job forwarded to another cluster
+     */
+    public static final int EVENT_JOB_FORWARD = 22;
+
+    /**
+     * < Job from a remote cluster dispatched
+     */
+    public static final int EVENT_JOB_ACCEPT = 23;
+
+    /**
+     * < Job status successfully sent to  submission cluster
+     */
+    public static final int EVENT_STATUS_ACK = 24;
+
+    /**
+     * < Job started successfully on the  execution host
+     */
+    public static final int EVENT_JOB_EXECUTE = 25;
+
+    /**
+     * < Send a message to a job
+     */
+    public static final int EVENT_JOB_MSG = 26;
+
+    /**
+     * < The message has been delivered
+     */
+    public static final int EVENT_JOB_MSG_ACK = 27;
+
+    /**
+     * < Job is requeued
+     */
+    public static final int EVENT_JOB_REQUEUE = 28;
+
+    /**
+     * < Submission mbatchd logs this after sending  an occupy request to execution mbatchd
+     */
+    public static final int EVENT_JOB_OCCUPY_REQ = 29;
+
+    /**
+     * < Submission mbatchd logs this event after  all execution mbatchds have vacated the occupied hosts for the job
+     */
+    public static final int EVENT_JOB_VACATED = 30;
+
+    /**
+     * < A signal action on a job has been  initiated or finished
+     */
+    public static final int EVENT_JOB_SIGACT = 32;
+
+    /**
+     * < sbatchd's new job status
+     */
+    public static final int EVENT_SBD_JOB_STATUS = 34;
+
+    /**
+     * < sbatchd accepts job start
+     */
+    public static final int EVENT_JOB_START_ACCEPT = 35;
+
+    /**
+     * < Undelete a calendar in the system
+     */
+    public static final int EVENT_CAL_UNDELETE = 36;
+
+    /**
+     * < Job is cleaned out of the core
+     */
+    public static final int EVENT_JOB_CLEAN = 37;
+
+    /**
+     * < Job exception was detected
+     */
+    public static final int EVENT_JOB_EXCEPTION = 38;
+
+    /**
+     * < Adding a new job group
+     */
+    public static final int EVENT_JGRP_ADD = 39;
+
+    /**
+     * < Modifying a job group
+     */
+    public static final int EVENT_JGRP_MOD = 40;
+
+    /**
+     * < Controlling a job group
+     */
+    public static final int EVENT_JGRP_CTRL = 41;
+
+    /**
+     * < Forcing a job to start on specified  hosts (brun operation)
+     */
+    public static final int EVENT_JOB_FORCE = 42;
+
+    /**
+     * < Switching the event file lsb.events
+     */
+    public static final int EVENT_LOG_SWITCH = 43;
+
+    /**
+     * < Job modification request
+     */
+    public static final int EVENT_JOB_MODIFY2 = 44;
+
+    /**
+     * < Log job group status
+     */
+    public static final int EVENT_JGRP_STATUS = 45;
+
+    /**
+     * < Job attributes have been set
+     */
+    public static final int EVENT_JOB_ATTR_SET = 46;
+
+    /**
+     * < Send an external message to a job
+     */
+    public static final int EVENT_JOB_EXT_MSG = 47;
+
+    /**
+     * < Update data status of a message for a job
+     */
+    public static final int EVENT_JOB_ATTA_DATA = 48;
+
+    /**
+     * < Insert one job to a chunk
+     */
+    public static final int EVENT_JOB_CHUNK = 49;
+
+    /**
+     * < Save unreported sbatchd status
+     */
+    public static final int EVENT_SBD_UNREPORTED_STATUS = 50;
+
+    /**
+     * < Reservation finished
+     */
+    public static final int EVENT_ADRSV_FINISH = 51;
+
+    /**
+     * < Dynamic host group control
+     */
+    public static final int EVENT_HGHOST_CTRL = 52;
+
+    /**
+     * < Saved current CPU allocation on service partition
+     */
+    public static final int EVENT_CPUPROFILE_STATUS = 53;
+
+    /**
+     * < Write out data logging file
+     */
+    public static final int EVENT_DATA_LOGGING = 54;
+
+    /**
+     * < Write job rusage in lsb.stream
+     */
+    public static final int EVENT_JOB_RUN_RUSAGE = 55;
+
+    /**
+     * < Stream closed and new stream opened.
+     */
+    public static final int EVENT_END_OF_STREAM = 56;
+
+    /**
+     * < SLA goal is reavaluated
+     */
+    public static final int EVENT_SLA_RECOMPUTE = 57;
+
+    /**
+     * < Write performance metrics to lsb.stream
+     */
+    public static final int EVENT_METRIC_LOG = 58;
+
+    /**
+     * < Write task finish log to ssched.acct
+     */
+    public static final int EVENT_TASK_FINISH = 59;
+
+    /**
+     * < Resize allocation is made
+     */
+    public static final int EVENT_JOB_RESIZE_NOTIFY_START = 60;
+
+    /**
+     * < Resize notification action initialized
+     */
+    public static final int EVENT_JOB_RESIZE_NOTIFY_ACCEPT = 61;
+
+    /**
+     * < Resize notification action completed
+     */
+    public static final int EVENT_JOB_RESIZE_NOTIFY_DONE = 62;
+
+    /**
+     * < Job resize release request is received
+     */
+    public static final int EVENT_JOB_RESIZE_RELEASE = 63;
+
+    /**
+     * < Job resize cancel request is received
+     */
+    public static final int EVENT_JOB_RESIZE_CANCEL = 64;
+
+    /**
+     * < Job resize event for lsb.acct
+     */
+    public static final int EVENT_JOB_RESIZE = 65;
+
+    /**
+     * < Saved array element's resource consumption  for LSF simulator
+     */
+    public static final int EVENT_JOB_ARRAY_ELEMENT = 66;
+
+    /**
+     * < Saved LSF simulator status
+     */
+    public static final int EVENT_MBD_SIM_STATUS = 67;
+
+/* event kind
+ */
+
+    /**
+     * < it is a job related event
+     */
+    public static final int EVENT_JOB_RELATED = 1;
+
+    /**
+     * < it is a non job related event
+     */
+    public static final int EVENT_NON_JOB_RELATED = 0;
+
+    /*
+   *  EXCLUSIVE PENDING REASONS
+   *  a job must stay pending as long as ONE of the exclusive reasons exists
+    */
+
+/* Job Related Reasons (001 - 300)
+ */
+    /**
+     * \addtogroup pending_reasons pending_reasons
+     * \brief          Each entry in the table contains one of the following pending reasons
+     */
+
+    /**
+     * < Virtual code; not a reason
+     */
+    public static final int PEND_JOB_REASON = 0;
+
+    /**
+     * < A new job is waiting to be scheduled
+     */
+    public static final int PEND_JOB_NEW = 1;
+
+    /**
+     * < The job is held until its specified start time
+     */
+    public static final int PEND_JOB_START_TIME = 2;
+
+    /**
+     * < The job is waiting for its dependency condition(s) to be satisfied
+     */
+    public static final int PEND_JOB_DEPEND = 3;
+
+    /**
+     * < The dependency condition is invalid or never satisfied
+     */
+    public static final int PEND_JOB_DEP_INVALID = 4;
+
+    /**
+     * < The migrating job is waiting to be rescheduled
+     */
+    public static final int PEND_JOB_MIG = 5;
+
+    /**
+     * < The job's pre-exec command exited with non-zero status
+     */
+    public static final int PEND_JOB_PRE_EXEC = 6;
+
+    /**
+     * < Unable to access jobfile
+     */
+    public static final int PEND_JOB_NO_FILE = 7;
+
+    /**
+     * < Unable to set job's environment variables
+     */
+    public static final int PEND_JOB_ENV = 8;
+
+    /**
+     * < Unable to determine the job's home or working directories
+     */
+    public static final int PEND_JOB_PATHS = 9;
+
+    /**
+     * < Unable to open the job's input and output files
+     */
+    public static final int PEND_JOB_OPEN_FILES = 10;
+
+    /**
+     * < Job execution initialization failed
+     */
+    public static final int PEND_JOB_EXEC_INIT = 11;
+
+    /**
+     * < Unable to copy restarting job's checkpoint files
+     */
+    public static final int PEND_JOB_RESTART_FILE = 12;
+
+    /**
+     * < Scheduling of the job is delayed
+     */
+    public static final int PEND_JOB_DELAY_SCHED = 13;
+
+    /**
+     * < Waiting for the re-scheduling of the job after switching queues
+     */
+    public static final int PEND_JOB_SWITCH = 14;
+
+    /**
+     * < An event is rejected by eeventd due to a syntax error
+     */
+    public static final int PEND_JOB_DEP_REJECT = 15;
+
+    /**
+     * < A JobScheduler feature is not enabled
+     */
+    public static final int PEND_JOB_JS_DISABLED = 16;
+
+    /**
+     * < Failed to get user password
+     */
+    public static final int PEND_JOB_NO_PASSWD = 17;
+
+    /**
+     * < The job is pending due to logon failure
+     */
+    public static final int PEND_JOB_LOGON_FAIL = 18;
+
+    /**
+     * < The job is waiting to be re-scheduled after its parameters have been changed
+     */
+    public static final int PEND_JOB_MODIFY = 19;
+
+    /**
+     * < The job time event is invalid
+     */
+    public static final int PEND_JOB_TIME_INVALID = 20;
+
+    /**
+     * < The job time event has expired
+     */
+    public static final int PEND_TIME_EXPIRED = 21;
+
+    /**
+     * < The job has been requeued
+     */
+    public static final int PEND_JOB_REQUEUED = 23;
+
+    /**
+     * < Waiting for the next time event
+     */
+    public static final int PEND_WAIT_NEXT = 24;
+
+    /**
+     * < The parent group is held
+     */
+    public static final int PEND_JGRP_HOLD = 25;
+
+    /**
+     * < The parent group is inactive
+     */
+    public static final int PEND_JGRP_INACT = 26;
+
+    /**
+     * < The group is waiting for scheduling
+     */
+    public static final int PEND_JGRP_WAIT = 27;
+
+    /**
+     * < The remote cluster(s) are unreachable
+     */
+    public static final int PEND_JOB_RCLUS_UNREACH = 28;
+
+    /**
+     * < SNDJOBS_TO queue rejected by remote  clusters
+     */
+    public static final int PEND_JOB_QUE_REJECT = 29;
+
+    /**
+     * < Waiting for new remote scheduling  session
+     */
+    public static final int PEND_JOB_RSCHED_START = 30;
+
+    /**
+     * < Waiting for allocation reply from remote clusters
+     */
+    public static final int PEND_JOB_RSCHED_ALLOC = 31;
+
+    /**
+     * < The job is forwarded to a remote cluster
+     */
+    public static final int PEND_JOB_FORWARDED = 32;
+
+    /**
+     * < The job running remotely is in a zombie state
+     */
+    public static final int PEND_JOB_RMT_ZOMBIE = 33;
+
+    /**
+     * < Job's enforced user group share account not selected
+     */
+    public static final int PEND_JOB_ENFUGRP = 34;
+
+    /**
+     * < The system is unable to schedule the job
+     */
+    public static final int PEND_SYS_UNABLE = 35;
+
+    /**
+     * < The parent group has just been released
+     */
+    public static final int PEND_JGRP_RELEASE = 36;
+
+    /**
+     * < The job has run since group active
+     */
+    public static final int PEND_HAS_RUN = 37;
+
+    /**
+     * < The job has reached its running element limit
+     */
+    public static final int PEND_JOB_ARRAY_JLIMIT = 38;
+
+    /**
+     * < Checkpoint directory is invalid
+     */
+    public static final int PEND_CHKPNT_DIR = 39;
+
+    /**
+     * < The first job in the chunk failed  (all other jobs in the chunk are set to PEND)
+     */
+    public static final int PEND_CHUNK_FAIL = 40;
+
+    /**
+     * < Optimum number of running jobs for SLA has been reached
+     */
+    public static final int PEND_JOB_SLA_MET = 41;
+
+    /**
+     * < Specified application profile does not exist
+     */
+    public static final int PEND_JOB_APP_NOEXIST = 42;
+
+    /**
+     * < Job no longer satisfies application  PROCLIMIT configuration
+     */
+    public static final int PEND_APP_PROCLIMIT = 43;
+
+    /**
+     * < No hosts for the job from EGO
+     */
+    public static final int PEND_EGO_NO_HOSTS = 44;
+
+    /**
+     * < The specified job group has reached its job limit
+     */
+    public static final int PEND_JGRP_JLIMIT = 45;
+
+    /**
+     * < Job pre-exec retry limit
+     */
+    public static final int PEND_PREEXEC_LIMIT = 46;
+
+    /**
+     * < Job re-queue limit
+     */
+    public static final int PEND_REQUEUE_LIMIT = 47;
+
+    /**
+     * < Job has bad res req
+     */
+    public static final int PEND_BAD_RESREQ = 48;
+
+    /**
+     * < Job's reservation is inactive
+     */
+    public static final int PEND_RSV_INACTIVE = 49;
+
+    /**
+     * < Job was in PSUSP with bad res req, after successful bmod  waiting for the user to bresume
+     */
+    public static final int PEND_WAITING_RESUME = 50;
+
+    /**
+     * < Job slot request cannot satisfy compound  resource requirement
+     */
+    public static final int PEND_SLOT_COMPOUND = 51;
+
+/*
+*  Queue and System Related Reasons (301 - 599)
+ */
+
+    /**
+     * < The queue is inactivated by the administrator
+     */
+    public static final int PEND_QUE_INACT = 301;
+
+    /**
+     * < The queue is inactivated by its time windows
+     */
+    public static final int PEND_QUE_WINDOW = 302;
+
+    /**
+     * < The queue has reached its job slot limit
+     */
+    public static final int PEND_QUE_JOB_LIMIT = 303;
+
+    /**
+     * < The user has reached the per-user job slot limit of the queue
+     */
+    public static final int PEND_QUE_USR_JLIMIT = 304;
+
+    /**
+     * < Not enough per-user job slots of the queue for the parallel job
+     */
+    public static final int PEND_QUE_USR_PJLIMIT = 305;
+
+    /**
+     * < The queue's pre-exec command exited with non-zero status
+     */
+    public static final int PEND_QUE_PRE_FAIL = 306;
+
+    /**
+     * < The job was not accepted by the NQS host,  Attempt again later
+     */
+    public static final int PEND_NQS_RETRY = 307;
+
+    /**
+     * < Unable to send the job to an NQS host
+     */
+    public static final int PEND_NQS_REASONS = 308;
+
+    /**
+     * < Unable to contact NQS host
+     */
+    public static final int PEND_NQS_FUN_OFF = 309;
+
+    /**
+     * < The system is not ready for scheduling after reconfiguration
+     */
+    public static final int PEND_SYS_NOT_READY = 310;
+
+    /**
+     * < The requeued job is waiting for rescheduling
+     */
+    public static final int PEND_SBD_JOB_REQUEUE = 311;
+
+    /**
+     * < Not enough hosts to meet the job's spanning requirement
+     */
+    public static final int PEND_JOB_SPREAD_TASK = 312;
+
+    /**
+     * < Not enough hosts to meet the queue's spanning requirement
+     */
+    public static final int PEND_QUE_SPREAD_TASK = 313;
+
+    /**
+     * < The queue has not enough job slots for the parallel job
+     */
+    public static final int PEND_QUE_PJOB_LIMIT = 314;
+
+    /**
+     * < The job will not finish before queue's run window is closed
+     */
+    public static final int PEND_QUE_WINDOW_WILL_CLOSE = 315;
+
+    /**
+     * < Job no longer satisfies queue  PROCLIMIT configuration
+     */
+    public static final int PEND_QUE_PROCLIMIT = 316;
+
+    /**
+     * < Job requeued due to plug-in failure
+     */
+    public static final int PEND_SBD_PLUGIN = 317;
+
+    /**
+     * < Waiting for lease signing
+     */
+    public static final int PEND_WAIT_SIGN_LEASE = 318;
+
+/* waitint for scheduling for SLOT_SHARE*/
+    public static final int PEND_WAIT_SLOT_SHARE = 319;
+
+/*
+*  User Related Reasons (601 - 800)
+ */
+
+    /**
+     * < The job slot limit is reached
+     */
+    public static final int PEND_USER_JOB_LIMIT = 601;
+
+    /**
+     * < A user group has reached its job slot limit
+     */
+    public static final int PEND_UGRP_JOB_LIMIT = 602;
+
+    /**
+     * < The job slot limit for the parallel job is reached
+     */
+    public static final int PEND_USER_PJOB_LIMIT = 603;
+
+    /**
+     * < A user group has reached its job slot limit for the parallel job
+     */
+    public static final int PEND_UGRP_PJOB_LIMIT = 604;
+
+    /**
+     * < Waiting for scheduling after resumed by user
+     */
+    public static final int PEND_USER_RESUME = 605;
+
+    /**
+     * < The job was suspended by the user while pending
+     */
+    public static final int PEND_USER_STOP = 607;
+
+    /**
+     * < Unable to determine user account for execution
+     */
+    public static final int PEND_NO_MAPPING = 608;
+
+    /**
+     * < The user has no permission to run the job on remote host/cluster
+     */
+    public static final int PEND_RMT_PERMISSION = 609;
+
+    /**
+     * < The job was suspended by LSF admin or root while pending
+     */
+    public static final int PEND_ADMIN_STOP = 610;
+
+    /**
+     * < The requested label is not valid
+     */
+    public static final int PEND_MLS_INVALID = 611;
+
+    /**
+     * < The requested label is above user allowed range
+     */
+    public static final int PEND_MLS_CLEARANCE = 612;
+
+    /**
+     * < The requested label rejected by /etc/rhost.conf
+     */
+    public static final int PEND_MLS_RHOST = 613;
+
+    /**
+     * < The requested label does not dominate current label
+     */
+    public static final int PEND_MLS_DOMINATE = 614;
+
+    /**
+     * < The requested label problem
+     */
+    public static final int PEND_MLS_FATAL = 615;
+
+    /**
+     * < LSF internally bstoped a pending job
+     */
+    public static final int PEND_INTERNAL_STOP = 616;
+
+/*
+*  NON-EXCLUSIVE PENDING REASONS
+*  A job may still start even though non-exclusive reasons exist.
+ */
+
+/*
+*  Host(sbatchd)-Job Related Reasons (1001 - 1300)
+ */
+
+    /**
+     * < The job's resource requirements not satisfied
+     */
+    public static final int PEND_HOST_RES_REQ = 1001;
+
+    /**
+     * < The job's requirement for exclusive execution not satisfied
+     */
+    public static final int PEND_HOST_NONEXCLUSIVE = 1002;
+
+    /**
+     * < Higher or equal priority jobs already suspended by system
+     */
+    public static final int PEND_HOST_JOB_SSUSP = 1003;
+
+    /**
+     * < The job failed to compete with other jobs on host partition
+     */
+    public static final int PEND_HOST_PART_PRIO = 1004;
+
+    /**
+     * < Unable to get the PID of the restarting job
+     */
+    public static final int PEND_SBD_GETPID = 1005;
+
+    /**
+     * < Unable to lock the host for exclusively executing the job
+     */
+    public static final int PEND_SBD_LOCK = 1006;
+
+    /**
+     * < Cleaning up zombie job
+     */
+    public static final int PEND_SBD_ZOMBIE = 1007;
+
+    /**
+     * < Can't run jobs submitted by root.  The job is rejected by the sbatchd
+     */
+    public static final int PEND_SBD_ROOT = 1008;
+
+    /**
+     * < Job can't finish on the host before queue's run window is closed
+     */
+    public static final int PEND_HOST_WIN_WILL_CLOSE = 1009;
+
+    /**
+     * < Job can't finish on the host before job's termination deadline
+     */
+    public static final int PEND_HOST_MISS_DEADLINE = 1010;
+
+    /**
+     * < The specified first execution host is  not eligible for this job at this time
+     */
+    public static final int PEND_FIRST_HOST_INELIGIBLE = 1011;
+
+    /**
+     * < Exclusive job reserves slots on host
+     */
+    public static final int PEND_HOST_EXCLUSIVE_RESERVE = 1012;
+
+    /**
+     * < Resized shadow job  or non-first resReq of a compound resReq job try to reuse the first execution host
+     */
+    public static final int PEND_FIRST_HOST_REUSE = 1013;
+/*
+*  Host Related Reasons (1301 - 1600)
+ */
+
+    /**
+     * < The host is closed by the LSF administrator
+     */
+    public static final int PEND_HOST_DISABLED = 1301;
+
+    /**
+     * < The host is locked by the LSF administrator
+     */
+    public static final int PEND_HOST_LOCKED = 1302;
+
+    /**
+     * < Not enough job slots for the parallel job
+     */
+    public static final int PEND_HOST_LESS_SLOTS = 1303;
+
+    /**
+     * < Dispatch windows are closed
+     */
+    public static final int PEND_HOST_WINDOW = 1304;
+
+    /**
+     * < The job slot limit reached
+     */
+    public static final int PEND_HOST_JOB_LIMIT = 1305;
+
+    /**
+     * < The queue's per-CPU job slot limit is reached
+     */
+    public static final int PEND_QUE_PROC_JLIMIT = 1306;
+
+    /**
+     * < The queue's per-host job slot limit is reached
+     */
+    public static final int PEND_QUE_HOST_JLIMIT = 1307;
+
+    /**
+     * < The user's per-CPU job slot limit is reached
+     */
+    public static final int PEND_USER_PROC_JLIMIT = 1308;
+
+    /**
+     * < The host's per-user job slot limit is reached
+     */
+    public static final int PEND_HOST_USR_JLIMIT = 1309;
+
+    /**
+     * < Not a member of the queue
+     */
+    public static final int PEND_HOST_QUE_MEMB = 1310;
+
+    /**
+     * < Not a user-specified host
+     */
+    public static final int PEND_HOST_USR_SPEC = 1311;
+
+    /**
+     * < The user has no access to the host partition
+     */
+    public static final int PEND_HOST_PART_USER = 1312;
+
+    /**
+     * < There is no such user account
+     */
+    public static final int PEND_HOST_NO_USER = 1313;
+
+    /**
+     * < Just started a job recently
+     */
+    public static final int PEND_HOST_ACCPT_ONE = 1314;
+
+    /**
+     * < Load info unavailable
+     */
+    public static final int PEND_LOAD_UNAVAIL = 1315;
+
+    /**
+     * < The LIM is unreachable by the sbatchd
+     */
+    public static final int PEND_HOST_NO_LIM = 1316;
+
+    /**
+     * < The host does not have a valid LSF software license
+     */
+    public static final int PEND_HOST_UNLICENSED = 1317;
+
+    /**
+     * < The queue's resource requirements are not satisfied
+     */
+    public static final int PEND_HOST_QUE_RESREQ = 1318;
+
+    /**
+     * < The submission host type is not the same
+     */
+    public static final int PEND_HOST_SCHED_TYPE = 1319;
+
+    /**
+     * < There are not enough processors to meet the job's spanning requirement.  The job level locality is unsatisfied.
+     */
+    public static final int PEND_JOB_NO_SPAN = 1320;
+
+    /**
+     * < There are not enough processors to meet the queue's spanning requirement.  The queue level locality is unsatisfied.
+     */
+    public static final int PEND_QUE_NO_SPAN = 1321;
+
+    /**
+     * < An exclusive job is running
+     */
+    public static final int PEND_HOST_EXCLUSIVE = 1322;
+
+    /**
+     * < Job Scheduler is disabled on the host.  It is not licensed to accept repetitive jobs.
+     */
+    public static final int PEND_HOST_JS_DISABLED = 1323;
+
+    /**
+     * < The user group's per-CPU job slot limit is reached
+     */
+    public static final int PEND_UGRP_PROC_JLIMIT = 1324;
+
+    /**
+     * < Incorrect host, group or cluster name
+     */
+    public static final int PEND_BAD_HOST = 1325;
+
+    /**
+     * < Host is not used by the queue
+     */
+    public static final int PEND_QUEUE_HOST = 1326;
+
+    /**
+     * < Host is locked by master LIM
+     */
+    public static final int PEND_HOST_LOCKED_MASTER = 1327;
+
+    /**
+     * < Not enough reserved job slots at this time for specified reservation ID
+     */
+    public static final int PEND_HOST_LESS_RSVSLOTS = 1328;
+
+    /**
+     * < Not enough slots or resources for whole duration of the job
+     */
+    public static final int PEND_HOST_LESS_DURATION = 1329;
+
+    /**
+     * < Specified reservation has expired or has been deleted
+     */
+    public static final int PEND_HOST_NO_RSVID = 1330;
+
+    /**
+     * < The host is closed due to lease is inactive
+     */
+    public static final int PEND_HOST_LEASE_INACTIVE = 1331;
+
+    /**
+     * < Not enough job slot(s) while advance reservation is active
+     */
+    public static final int PEND_HOST_ADRSV_ACTIVE = 1332;
+
+    /**
+     * < This queue is not configured to send jobs to the cluster specified in the advance
+     */
+    public static final int PEND_QUE_RSVID_NOMATCH = 1333;
+
+    /**
+     * < Individual host based reasons
+     */
+    public static final int PEND_HOST_GENERAL = 1334;
+
+    /**
+     * < Host does not belong to the specified  advance reservation
+     */
+    public static final int PEND_HOST_RSV = 1335;
+
+    /**
+     * < Host does not belong to a compute unit  of the required type
+     */
+    public static final int PEND_HOST_NOT_CU = 1336;
+
+    /**
+     * < A compute unit containing the host is  used exclusively
+     */
+    public static final int PEND_HOST_CU_EXCL = 1337;
+
+    /**
+     * < CU-level excl. job cannot start since CU  is occupied
+     */
+    public static final int PEND_HOST_CU_OCCUPIED = 1338;
+
+    /**
+     * < Insufficiently many usable slots on the  host's compute unit
+     */
+    public static final int PEND_HOST_USABLE_CU = 1339;
+
+    /**
+     * < No first execution compute unit satisfies CU 'usablepercu' requirement.
+     */
+    public static final int PEND_JOB_FIRST_CU = 1340;
+
+    /**
+     * < A CU containing the host is reserved  exclusively
+     */
+    public static final int PEND_HOST_CU_EXCL_RSV = 1341;
+
+    /**
+     * < Maxcus cannot be satisfied
+     */
+    public static final int PEND_JOB_CU_MAXCUS = 1342;
+
+    /**
+     * < Balance cannot be satisfied
+     */
+    public static final int PEND_JOB_CU_BALANCE = 1343;
+
+    /**
+     * < Cu not supported on toplib integration hosts
+     */
+    public static final int PEND_CU_TOPLIB_HOST = 1344;
+
+/*
+*  sbatchd Related Reasons (1601 - 1900)
+ */
+
+    /**
+     * < Cannot reach sbatchd
+     */
+    public static final int PEND_SBD_UNREACH = 1601;
+
+    /**
+     * < Number of jobs exceed quota
+     */
+    public static final int PEND_SBD_JOB_QUOTA = 1602;
+
+    /**
+     * < The job failed in talking to the server to start the job
+     */
+    public static final int PEND_JOB_START_FAIL = 1603;
+
+    /**
+     * < Failed in receiving the reply from the server when starting the job
+     */
+    public static final int PEND_JOB_START_UNKNWN = 1604;
+
+    /**
+     * < Unable to allocate memory to run job.  There is no memory on the sbatchd.
+     */
+    public static final int PEND_SBD_NO_MEM = 1605;
+
+    /**
+     * < Unable to fork process to run the job.  There are no more processes on the sbatchd.
+     */
+    public static final int PEND_SBD_NO_PROCESS = 1606;
+
+    /**
+     * < Unable to communicate with the job process
+     */
+    public static final int PEND_SBD_SOCKETPAIR = 1607;
+
+    /**
+     * < The slave batch server failed to accept the job
+     */
+    public static final int PEND_SBD_JOB_ACCEPT = 1608;
+
+    /**
+     * < Lease job remote dispatch failed
+     */
+    public static final int PEND_LEASE_JOB_REMOTE_DISPATCH = 1609;
+
+    /**
+     * < Failed to restart job from last checkpoint
+     */
+    public static final int PEND_JOB_RESTART_FAIL = 1610;
+/*
+*  Load Related Reasons (2001 - 2300)
+ */
+
+    /**
+     * < The load threshold is reached
+     */
+    public static final int PEND_HOST_LOAD = 2001;
+
+/*
+*  Queue Resource Reservation Related Reasons (2301 - 2600)
+ */
+
+    /**
+     * < The queue's requirements for resource  reservation are not satisfied.
+     */
+    public static final int PEND_HOST_QUE_RUSAGE = 2301;
+
+/*
+*  Jobs Resource Reservation Related Reasons (2601 - 2900)
+ */
+
+    /**
+     * < The job's requirements for resource  reservation are not satisfied.
+     */
+    public static final int PEND_HOST_JOB_RUSAGE = 2601;
+
+/*
+*  Remote Forwarding Related Reasons (2901 - 3200)
+ */
+
+    /**
+     * < Remote job not recongized by remote cluster, waiting for rescheduling
+     */
+    public static final int PEND_RMT_JOB_FORGOTTEN = 2901;
+
+    /**
+     * < Remote import limit reached, waiting  for rescheduling
+     */
+    public static final int PEND_RMT_IMPT_JOBBKLG = 2902;
+
+    /**
+     * < Remote schedule time reached,  waiting for rescheduling
+     */
+    public static final int PEND_RMT_MAX_RSCHED_TIME = 2903;
+
+    /**
+     * < Remote pre-exec retry limit reached, waiting for rescheduling
+     */
+    public static final int PEND_RMT_MAX_PREEXEC_RETRY = 2904;
+
+    /**
+     * < Remote queue is closed
+     */
+    public static final int PEND_RMT_QUEUE_CLOSED = 2905;
+
+    /**
+     * < Remote queue is inactive
+     */
+    public static final int PEND_RMT_QUEUE_INACTIVE = 2906;
+
+    /**
+     * < Remote queue is congested
+     */
+    public static final int PEND_RMT_QUEUE_CONGESTED = 2907;
+
+    /**
+     * < Remote queue is disconnected
+     */
+    public static final int PEND_RMT_QUEUE_DISCONNECT = 2908;
+
+    /**
+     * < Remote queue is not configured to accept jobs from this cluster
+     */
+    public static final int PEND_RMT_QUEUE_NOPERMISSION = 2909;
+
+    /**
+     * < Job's termination time exceeds the job creation time on remote cluster
+     */
+    public static final int PEND_RMT_BAD_TIME = 2910;
+
+    /**
+     * < Permission denied on the execution cluster
+     */
+    public static final int PEND_RMT_PERMISSIONS = 2911;
+
+    /**
+     * < Job's required on number of processors cannot be satisfied on the remote cluster
+     */
+    public static final int PEND_RMT_PROC_NUM = 2912;
+
+    /**
+     * < User is not defined in the fairshare policy of the remote queue
+     */
+    public static final int PEND_RMT_QUEUE_USE = 2913;
+
+    /**
+     * < Remote queue is a non-interactive queue
+     */
+    public static final int PEND_RMT_NO_INTERACTIVE = 2914;
+
+    /**
+     * < Remote queue is an interactive-only queue
+     */
+    public static final int PEND_RMT_ONLY_INTERACTIVE = 2915;
+
+    /**
+     * < Job's required maximum number of  processors is less then the minimum number
+     */
+    public static final int PEND_RMT_PROC_LESS = 2916;
+
+    /**
+     * < Job's required resource limit exceeds that of the remote queue
+     */
+    public static final int PEND_RMT_OVER_LIMIT = 2917;
+
+    /**
+     * < Job's resource requirements do not match with those of the remote queue
+     */
+    public static final int PEND_RMT_BAD_RESREQ = 2918;
+
+    /**
+     * < Job failed to be created on the remote cluster
+     */
+    public static final int PEND_RMT_CREATE_JOB = 2919;
+
+    /**
+     * < Job is requeued for rerun on the execution cluster
+     */
+    public static final int PEND_RMT_RERUN = 2920;
+
+    /**
+     * < Job is requeued on the execution cluster due to exit value
+     */
+    public static final int PEND_RMT_EXIT_REQUEUE = 2921;
+
+    /**
+     * < Job was killed and requeued on the execution cluster
+     */
+    public static final int PEND_RMT_REQUEUE = 2922;
+
+    /**
+     * < Job was forwarded to remote cluster
+     */
+    public static final int PEND_RMT_JOB_FORWARDING = 2923;
+
+    /**
+     * < Remote import queue defined for the job in lsb.queues is either not ready or not valid
+     */
+    public static final int PEND_RMT_QUEUE_INVALID = 2924;
+
+    /**
+     * < Remote queue is a non-exclusive queue
+     */
+    public static final int PEND_RMT_QUEUE_NO_EXCLUSIVE = 2925;
+
+    /**
+     * < Job was rejected; submitter does not belong to the specified User Group in the remote cluster or the user group does not exist in the remote cluster
+     */
+    public static final int PEND_RMT_UGROUP_MEMBER = 2926;
+
+    /**
+     * < Remote queue is rerunnable: can not accept interactive jobs
+     */
+    public static final int PEND_RMT_INTERACTIVE_RERUN = 2927;
+
+    /**
+     * < Remote cluster failed in talking to server to start the job
+     */
+    public static final int PEND_RMT_JOB_START_FAIL = 2928;
+
+    /**
+     * < Job was rejected; submitter does not belong to the specified User Group in the remote cluster or the user group does not exist in the remote cluster
+     */
+    public static final int PEND_RMT_FORWARD_FAIL_UGROUP_MEMBER = 2930;
+
+    /**
+     * < Specified remote reservation has expired or has been deleted
+     */
+    public static final int PEND_RMT_HOST_NO_RSVID = 2931;
+
+    /**
+     * < Application profile could not be found in the remote cluster.
+     */
+    public static final int PEND_RMT_APP_NULL = 2932;
+
+    /**
+     * < Job's required RUNLIMIT exceeds  RUNTIME*  JOB_RUNLIMIT_RATIO of the remote cluster.
+     */
+    public static final int PEND_RMT_BAD_RUNLIMIT = 2933;
+
+    /**
+     * < Job's required RUNTIME exceeds the hard runtime limit in the remote queue.
+     */
+    public static final int PEND_RMT_OVER_QUEUE_LIMIT = 2934;
+
+    /**
+     * < Job will be pend when no slots available among remote queues.
+     */
+    public static final int PEND_RMT_WHEN_NO_SLOTS = 2935;
+/* SUSPENDING REASONS */
+
+/*
+*  General Resource Limits Related Reasons ( 3201 - 4800)
+ */
+
+    /**
+     * < Resource limit defined on user  or user group has been reached.
+     */
+    public static final int PEND_GENERAL_LIMIT_USER = 3201;
+
+    /**
+     * < Resource (%s) limit defined on queue has been reached.
+     */
+    public static final int PEND_GENERAL_LIMIT_QUEUE = 3501;
+
+    /**
+     * < Resource limit defined on project has been reached.
+     */
+    public static final int PEND_GENERAL_LIMIT_PROJECT = 3801;
+
+    /**
+     * < Resource (%s) limit defined cluster wide has been reached.
+     */
+    public static final int PEND_GENERAL_LIMIT_CLUSTER = 4101;
+
+    /**
+     * < Resource (%s) limit defined on host and/or host group has  been reached.
+     */
+    public static final int PEND_GENERAL_LIMIT_HOST = 4401;
+
+    /**
+     * < JOBS limit defined for the user or user group has been reached.
+     */
+    public static final int PEND_GENERAL_LIMIT_JOBS_USER = 4701;
+
+    /**
+     * < JOBS limit defined for the queue has been reached.
+     */
+    public static final int PEND_GENERAL_LIMIT_JOBS_QUEUE = 4702;
+
+    /**
+     * < JOBS limit defined for the project has been reached.
+     */
+    public static final int PEND_GENERAL_LIMIT_JOBS_PROJECT = 4703;
+
+    /**
+     * < JOBS limit defined cluster-wide has been reached.
+     */
+    public static final int PEND_GENERAL_LIMIT_JOBS_CLUSTER = 4704;
+
+    /**
+     * < JOBS limit defined on host or host group has been reached.
+     */
+    public static final int PEND_GENERAL_LIMIT_JOBS_HOST = 4705;
+
+/* LSF2 Presto RLA-related reasons    (4900 - 4989) */
+
+    /**
+     * < RMS scheduler plugin  internal error.
+     */
+    public static final int PEND_RMS_PLUGIN_INTERNAL = 4900;
+
+    /**
+     * < RLA communication failure.
+     */
+    public static final int PEND_RMS_PLUGIN_RLA_COMM = 4901;
+
+    /**
+     * < RMS is not available.
+     */
+    public static final int PEND_RMS_NOT_AVAILABLE = 4902;
+
+    /**
+     * < Cannot satisfy the topology  requirement.
+     */
+    public static final int PEND_RMS_FAIL_TOPOLOGY = 4903;
+
+    /**
+     * < Cannot allocate an RMS resource.
+     */
+    public static final int PEND_RMS_FAIL_ALLOC = 4904;
+
+    /**
+     * < RMS job with special topology requirements cannot be preemptive or backfill job.
+     */
+    public static final int PEND_RMS_SPECIAL_NO_PREEMPT_BACKFILL = 4905;
+
+    /**
+     * < RMS job with special topology requirements cannot reserve slots.
+     */
+    public static final int PEND_RMS_SPECIAL_NO_RESERVE = 4906;
+
+    /**
+     * < RLA internal error.
+     */
+    public static final int PEND_RMS_RLA_INTERNAL = 4907;
+
+    /**
+     * < Not enough slots for job.  Job with RMS topology requirements cannot reserve slots, be preemptive, or be a backfill job.
+     */
+    public static final int PEND_RMS_NO_SLOTS_SPECIAL = 4908;
+
+    /**
+     * < User account does not exist on the execution host.
+     */
+    public static final int PEND_RMS_RLA_NO_SUCH_USER = 4909;
+
+    /**
+     * < Unknown host and/or partition unavailable.
+     */
+    public static final int PEND_RMS_RLA_NO_SUCH_HOST = 4910;
+
+    /**
+     * < Cannot schedule chunk jobs to RMS hosts.
+     */
+    public static final int PEND_RMS_CHUNKJOB = 4911;
+
+    /**
+     * < RLA protocol mismatch.
+     */
+    public static final int PEND_RLA_PROTOMISMATCH = 4912;
+
+    /**
+     * < Contradictory topology requirements specified.
+     */
+    public static final int PEND_RMS_BAD_TOPOLOGY = 4913;
+
+    /**
+     * < Not enough slots to satisfy manditory contiguous requirement.
+     */
+    public static final int PEND_RMS_RESREQ_MCONT = 4914;
+
+    /**
+     * < Not enough slots to satisfy RMS ptile requirement.
+     */
+    public static final int PEND_RMS_RESREQ_PTILE = 4915;
+
+    /**
+     * < Not enough slots to satisfy RMS nodes requirement.
+     */
+    public static final int PEND_RMS_RESREQ_NODES = 4916;
+
+    /**
+     * < Cannot satisfy RMS base node requirement.
+     */
+    public static final int PEND_RMS_RESREQ_BASE = 4917;
+
+    /**
+     * < Cannot satisfy RMS rails requirement.
+     */
+    public static final int PEND_RMS_RESREQ_RAILS = 4918;
+
+    /**
+     * < Cannot satisfy RMS railmask requirement.
+     */
+    public static final int PEND_RMS_RESREQ_RAILMASK = 4919;
+
+
+/*
+*  Maui Integration Related Reasons ( 5000 - 5100)
+ */
+
+    /**
+     * < Unable to communicate with external Maui scheduler.
+     */
+    public static final int PEND_MAUI_UNREACH = 5000;
+
+    /**
+     * < Job is pending at external Maui scheduler.
+     */
+    public static final int PEND_MAUI_FORWARD = 5001;
+
+    /**
+     * < External Maui scheduler sets detail reason.
+     */
+    public static final int PEND_MAUI_REASON = 5030;
+
+/*
+*  SGI CPUSET Integration Related Reasons ( 5200 - 5299)
+ */
+
+    /**
+     * < CPUSET attach failed.  Job requeued
+     */
+    public static final int PEND_CPUSET_ATTACH = 5200;
+
+    /**
+     * < Not a cpuset host
+     */
+    public static final int PEND_CPUSET_NOT_CPUSETHOST = 5201;
+
+    /**
+     * < Topd initialization failed
+     */
+    public static final int PEND_CPUSET_TOPD_INIT = 5202;
+
+    /**
+     * < Topd communication timeout
+     */
+    public static final int PEND_CPUSET_TOPD_TIME_OUT = 5203;
+
+    /**
+     * < Cannot satisfy the cpuset  allocation requirement
+     */
+    public static final int PEND_CPUSET_TOPD_FAIL_ALLOC = 5204;
+
+    /**
+     * < Bad cpuset allocation request
+     */
+    public static final int PEND_CPUSET_TOPD_BAD_REQUEST = 5205;
+
+    /**
+     * < Topd internal error
+     */
+    public static final int PEND_CPUSET_TOPD_INTERNAL = 5206;
+
+    /**
+     * < Cpuset system API failure
+     */
+    public static final int PEND_CPUSET_TOPD_SYSAPI_ERR = 5207;
+
+    /**
+     * < Specified static cpuset does  not exist on the host
+     */
+    public static final int PEND_CPUSET_TOPD_NOSUCH_NAME = 5208;
+
+    /**
+     * < Cpuset is already allocated   for this job
+     */
+    public static final int PEND_CPUSET_TOPD_JOB_EXIST = 5209;
+
+    /**
+     * < Topd malloc failure
+     */
+    public static final int PEND_CPUSET_TOPD_NO_MEMORY = 5210;
+
+    /**
+     * < User account does not exist   on the cpuset host
+     */
+    public static final int PEND_CPUSET_TOPD_INVALID_USER = 5211;
+
+    /**
+     * < User does not have permission   to run job within cpuset
+     */
+    public static final int PEND_CPUSET_TOPD_PERM_DENY = 5212;
+
+    /**
+     * < Topd is not available
+     */
+    public static final int PEND_CPUSET_TOPD_UNREACH = 5213;
+
+    /**
+     * < Topd communication failure
+     */
+    public static final int PEND_CPUSET_TOPD_COMM_ERR = 5214;
+
+
+    /**
+     * < CPUSET scheduler plugin internal error
+     */
+    public static final int PEND_CPUSET_PLUGIN_INTERNAL = 5215;
+
+    /**
+     * < Cannot schedule chunk jobs to cpuset hosts
+     */
+    public static final int PEND_CPUSET_CHUNKJOB = 5216;
+
+    /**
+     * < Can't satisfy CPU_LIST   requirement
+     */
+    public static final int PEND_CPUSET_CPULIST = 5217;
+
+    /**
+     * < Cannot satisfy CPUSET MAX_RADIUS requirement
+     */
+    public static final int PEND_CPUSET_MAXRADIUS = 5218;
+
+/* Bproc integration related reasons (5300 - 5320)
+ */
+
+    /**
+     * < Node allocation failed
+     */
+    public static final int PEND_NODE_ALLOC_FAIL = 5300;
+
+/* Eagle pending reasons  (5400 - 5449) */
+
+    /**
+     * < RMS resource is not available
+     */
+    public static final int PEND_RMSRID_UNAVAIL = 5400;
+
+
+    /**
+     * < Not enough free cpus to satisfy job requirements
+     */
+    public static final int PEND_NO_FREE_CPUS = 5450;
+
+    /**
+     * < Topology unknown or recently changed
+     */
+    public static final int PEND_TOPOLOGY_UNKNOWN = 5451;
+
+    /**
+     * < Contradictory topology requirement specified
+     */
+    public static final int PEND_BAD_TOPOLOGY = 5452;
+
+    /**
+     * < RLA communications failure
+     */
+    public static final int PEND_RLA_COMM = 5453;
+
+    /**
+     * < User account does not exist on execution host
+     */
+    public static final int PEND_RLA_NO_SUCH_USER = 5454;
+
+    /**
+     * < RLA internal error
+     */
+    public static final int PEND_RLA_INTERNAL = 5455;
+
+    /**
+     * < Unknown host and/or partition unavailable
+     */
+    public static final int PEND_RLA_NO_SUCH_HOST = 5456;
+
+    /**
+     * < Too few slots for specified topology requirement
+     */
+    public static final int PEND_RESREQ_TOOFEWSLOTS = 5457;
+
+/* PSET pending reasons (5500 - 5549) */
+
+    /**
+     * < PSET scheduler plugin internal error
+     */
+    public static final int PEND_PSET_PLUGIN_INTERNAL = 5500;
+
+    /**
+     * < Cannot satisfy PSET ptile requirement
+     */
+    public static final int PEND_PSET_RESREQ_PTILE = 5501;
+
+    /**
+     * < Cannot satisfy PSET cells requirement
+     */
+    public static final int PEND_PSET_RESREQ_CELLS = 5502;
+
+    /**
+     * < Cannot schedule chunk jobs to PSET hosts
+     */
+    public static final int PEND_PSET_CHUNKJOB = 5503;
+
+    /**
+     * < Host does not support processor set functionality
+     */
+    public static final int PEND_PSET_NOTSUPPORT = 5504;
+
+    /**
+     * < PSET bind failed. Job requeued
+     */
+    public static final int PEND_PSET_BIND_FAIL = 5505;
+
+    /**
+     * < Cannot satisfy PSET CELL_LIST  requirement
+     */
+    public static final int PEND_PSET_RESREQ_CELLLIST = 5506;
+
+
+/* SLURM pending reasons (5550 - 5599) */
+
+    /**
+     * < SLURM scheduler plugin internal error
+     */
+    public static final int PEND_SLURM_PLUGIN_INTERNAL = 5550;
+
+    /**
+     * < Not enough resource to satisfy  SLURM nodes requirment
+     */
+    public static final int PEND_SLURM_RESREQ_NODES = 5551;
+
+    /**
+     * < Not enough resource to satisfy  SLURM node attributes requirment.
+     */
+    public static final int PEND_SLURM_RESREQ_NODE_ATTR = 5552;
+
+    /**
+     * < Not enough resource to satisfy SLURM exclude requirment.
+     */
+    public static final int PEND_SLURM_RESREQ_EXCLUDE = 5553;
+
+    /**
+     * < Not enough resource to satisfy SLURM nodelist requirment.
+     */
+    public static final int PEND_SLURM_RESREQ_NODELIST = 5554;
+
+    /**
+     * < Not enough resource to satisfy SLURM contiguous requirment.
+     */
+    public static final int PEND_SLURM_RESREQ_CONTIGUOUS = 5555;
+
+    /**
+     * < SLURM allocation is not available. Job requeued.
+     */
+    public static final int PEND_SLURM_ALLOC_UNAVAIL = 5556;
+
+    /**
+     * < Invalid grammar in SLURM constraints option, job will never run.
+     */
+    public static final int PEND_SLURM_RESREQ_BAD_CONSTRAINT = 5557;
+
+/* Cray X1 pending reasons (5600 - 5649) */
+
+    /**
+     * < Not enough SSPs for job
+     */
+    public static final int PEND_CRAYX1_SSP = 5600;
+
+    /**
+     * < Not enough MSPs for job
+     */
+    public static final int PEND_CRAYX1_MSP = 5601;
+
+    /**
+     * < Unable to pass limit information to psched.
+     */
+    public static final int PEND_CRAYX1_PASS_LIMIT = 5602;
+
+/* Cray XT3 pending reasons (5650 - 5699) */
+
+    /**
+     * < Unable to create or assign a  partition by CPA
+     */
+    public static final int PEND_CRAYXT3_ASSIGN_FAIL = 5650;
+
+/* BlueGene pending reasons (5700 - 5749) */
+
+    /**
+     * < BG/L: Scheduler plug-in internal error.
+     */
+    public static final int PEND_BLUEGENE_PLUGIN_INTERNAL = 5700;
+
+    /**
+     * < BG/L: Allocation is not available. Job requeued.
+     */
+    public static final int PEND_BLUEGENE_ALLOC_UNAVAIL = 5701;
+
+    /**
+     * < BG/L: No free base partitions available for a full block allocation.
+     */
+    public static final int PEND_BLUEGENE_NOFREEMIDPLANES = 5702;
+
+    /**
+     * < BG/L: No free quarters available for a small block allocation.
+     */
+    public static final int PEND_BLUEGENE_NOFREEQUARTERS = 5703;
+
+    /**
+     * < BG/L: No free node cards available for a small block allocation.
+     */
+    public static final int PEND_BLUEGENE_NOFREENODECARDS = 5704;
+
+/* resize enhancement releated pending reasons */
+
+    /**
+     * < First execution host unavailable
+     */
+    public static final int PEND_RESIZE_FIRSTHOSTUNAVAIL = 5705;
+
+    /**
+     * < Master is not in the RUN state
+     */
+    public static final int PEND_RESIZE_MASTERSUSP = 5706;
+
+    /**
+     * < Host is not same as for master
+     */
+    public static final int PEND_RESIZE_MASTER_SAME = 5707;
+
+    /**
+     * < Host already used by master
+     */
+    public static final int PEND_RESIZE_SPAN_PTILE = 5708;
+
+    /**
+     * < The job can only use first host
+     */
+    public static final int PEND_RESIZE_SPAN_HOSTS = 5709;
+
+    /**
+     * < The job cannot get slots on remote hosts
+     */
+    public static final int PEND_RESIZE_LEASE_HOST = 5710;
+
+/* compound resreq related pending reasons (5800 - ??) */
+
+    /**
+     * < The job cannot get slots on  pre-7Update5 remote hosts
+     */
+    public static final int PEND_COMPOUND_RESREQ_OLD_LEASE_HOST = 5800;
+
+    /**
+     * < Hosts using LSF HPC system  integrations do not support compound resource requirements.
+     */
+    public static final int PEND_COMPOUND_RESREQ_TOPLIB_HOST = 5801;
+/* multi-phase resreq related pending reasons (5900 - ??) */
+
+    /**
+     * < The job cannot get slots on  pre-7Update6 remote hosts
+     */
+    public static final int PEND_MULTIPHASE_RESREQ_OLD_LEASE_HOST = 5900;
+
+/* EGO-Enabled SLA pending reasons (5750 - 5799) */
+
+    /**
+     * < Host does not have enough slots for this SLA job.
+     */
+    public static final int PEND_PS_PLUGIN_INTERNAL = 5750;
+
+    /**
+     * < EGO SLA: Failed to synchronize resource with MBD.
+     */
+    public static final int PEND_PS_MBD_SYNC = 5751;
+
+
+/* PLATFORM reserves pending reason number from 1 - 20000.
+*  External plugin is suggested to use platform's reserved pending reason
+*  number. However, they can use pending reason number between 20001 - 25000
+*  as customer specific pending reasons. In this case, bjobs -p will only show
+*  the reason number without detailed message
+ */
+
+    /**
+     * < Customized pending reason number between min and max.
+     */
+    public static final int PEND_CUSTOMER_MIN = 20001;
+
+    /**
+     * < Customized pending reason number between min and max.
+     */
+    public static final int PEND_CUSTOMER_MAX = 25000;
+
+
+    /**
+     * < The maximum number of reasons
+     */
+    public static final int PEND_MAX_REASONS = 25001;
+
+    /**
+     * \addtogroup suspending_reasons  suspending_reasons
+     * suspending_reasons is part of pending_reasons
+     */
+/* SUSPENDING REASONS */
+
+/* User related reasons */
+
+    /**
+     * < Virtual code. Not a reason
+     */
+    public static final int SUSP_USER_REASON = 0x00000000;
+
+    /**
+     * < The job is waiting to be re-scheduled after being resumed by the user.
+     */
+    public static final int SUSP_USER_RESUME = 0x00000001;
+
+    /**
+     * < The user suspended the job.
+     */
+    public static final int SUSP_USER_STOP = 0x00000002;
+
+/* Queue and system related reasons */
+
+    /**
+     * < Virtual code. Not a reason
+     */
+    public static final int SUSP_QUEUE_REASON = 0x00000004;
+
+    /**
+     * < The run window of the queue is closed.
+     */
+    public static final int SUSP_QUEUE_WINDOW = 0x00000008;
+
+    /**
+     * < Suspended after preemption. The system needs to re-allocate CPU utilization by job priority.
+     */
+    public static final int SUSP_RESCHED_PREEMPT = 0x00000010;
+
+    /**
+     * < The LSF administrator has locked the execution host.
+     */
+    public static final int SUSP_HOST_LOCK = 0x00000020;
+
+    /**
+     * < A load index exceeds its threshold. The subreasons field indicates which indices.
+     */
+    public static final int SUSP_LOAD_REASON = 0x00000040;
+
+    /**
+     * < The job was preempted by mbatchd because of a higher priorty job.
+     */
+    public static final int SUSP_MBD_PREEMPT = 0x00000080;
+
+    /**
+     * < Preempted by sbatchd. The job limit of the host/user has been reached.
+     */
+    public static final int SUSP_SBD_PREEMPT = 0x00000100;
+
+    /**
+     * < The suspend conditions of the queue,  as specified by the STOP_COND parameter in lsb.queues, are true.
+     */
+    public static final int SUSP_QUE_STOP_COND = 0x00000200;
+
+    /**
+     * < The resume conditions of the queue, as specified by the RESUME_COND parameter in lsb.queues, are false.
+     */
+    public static final int SUSP_QUE_RESUME_COND = 0x00000400;
+
+    /**
+     * < The job was suspended due to the paging rate and the host is not idle yet.
+     */
+    public static final int SUSP_PG_IT = 0x00000800;
+
+    /**
+     * < Resets the previous reason.
+     */
+    public static final int SUSP_REASON_RESET = 0x00001000;
+
+    /**
+     * < Load information on the execution hosts is unavailable.
+     */
+    public static final int SUSP_LOAD_UNAVAIL = 0x00002000;
+
+    /**
+     * < The job was suspened by root or the LSF administrator.
+     */
+    public static final int SUSP_ADMIN_STOP = 0x00004000;
+
+    /**
+     * < The job is terminated due to resource limit.
+     */
+    public static final int SUSP_RES_RESERVE = 0x00008000;
+
+    /**
+     * < The job is locked by the mbatchd.
+     */
+    public static final int SUSP_MBD_LOCK = 0x00010000;
+
+    /**
+     * < The job's requirements for resource  reservation are not satisfied.
+     */
+    public static final int SUSP_RES_LIMIT = 0x00020000;
+
+    /**
+     * < The job is suspended while the sbatchd is restarting.
+     */
+    public static final int SUSP_SBD_STARTUP = 0x00040000;
+
+    /**
+     * < The execution host is locked by the master LIM.
+     */
+    public static final int SUSP_HOST_LOCK_MASTER = 0x00080000;
+
+    /**
+     * < An advance reservation using the  host is active
+     */
+    public static final int SUSP_HOST_RSVACTIVE = 0x00100000;
+
+    /**
+     * < There is a detailed reason in the subreason field
+     */
+    public static final int SUSP_DETAILED_SUBREASON = 0x00200000;
+    /* GLB suspending reason */
+
+    /**
+     * < The job is preempted by glb
+     */
+    public static final int SUSP_GLB_LICENSE_PREEMPT = 0x00400000;
+
+    /* Cray X1 suspend reasons */
+
+    /**
+     * < Job not placed by Cray X1  psched
+     */
+    public static final int SUSP_CRAYX1_POSTED = 0x00800000;
+
+    /**
+     * < Job suspended when its advance  reservation expired
+     */
+    public static final int SUSP_ADVRSV_EXPIRED = 0x01000000;
+
+    /**
+     * \addtogroup suspending_subreasons  suspending_subreasons
+     * suspending_subreasons has the following options:
+     */
+
+    /**
+     * < Sub reason of SUSP_RES_LIMIT: RUNLIMIT is reached.
+     */
+    public static final int SUB_REASON_RUNLIMIT = 0x00000001;
+
+    /**
+     * < Sub reason of SUSP_RES_LIMIT: DEADLINE is reached.
+     */
+    public static final int SUB_REASON_DEADLINE = 0x00000002;
+
+    /**
+     * < Sub reason of SUSP_RES_LIMIT: PROCESSLIMIT is reached.
+     */
+    public static final int SUB_REASON_PROCESSLIMIT = 0x00000004;
+
+    /**
+     * < Sub reason of SUSP_RES_LIMIT: CPULIMIT is reached.
+     */
+    public static final int SUB_REASON_CPULIMIT = 0x00000008;
+
+    /**
+     * < Sub reason of SUSP_RES_LIMIT: MEMLIMIT is reached.
+     */
+    public static final int SUB_REASON_MEMLIMIT = 0x00000010;
+
+    /**
+     * < Sub reason of SUSP_RES_LIMIT: THREADLIMIT is reached.
+     */
+    public static final int SUB_REASON_THREADLIMIT = 0x00000020;
+
+    /**
+     * < Sub reason of SUSP_RES_LIMIT: SWAPLIMIT is reached.
+     */
+    public static final int SUB_REASON_SWAPLIMIT = 0x00000040;
+
+    /**
+     * < Account ID does not match those allowed by the gate
+     */
+    public static final int SUB_REASON_CRAYX1_ACCOUNTID = 0x00000001;
+
+    /**
+     * < Attribute does not match  those allowed by the gate
+     */
+    public static final int SUB_REASON_CRAYX1_ATTRIBUTE = 0x00000002;
+
+    /**
+     * < Blocked by one or more gates
+     */
+    public static final int SUB_REASON_CRAYX1_BLOCKED = 0x00000004;
+
+    /**
+     * < Application is in the process of being restarted  and it is under the control  of CPR
+     */
+    public static final int SUB_REASON_CRAYX1_RESTART = 0x00000008;
+
+    /**
+     * < Depth does not match those  allowed by the gate
+     */
+    public static final int SUB_REASON_CRAYX1_DEPTH = 0x00000010;
+
+    /**
+     * < GID does not match those  allowed by the gate
+     */
+    public static final int SUB_REASON_CRAYX1_GID = 0x00000020;
+
+    /**
+     * < No GASID is available
+     */
+    public static final int SUB_REASON_CRAYX1_GASID = 0x00000040;
+
+    /**
+     * < Hard label does not match  those allowed by the gate
+     */
+    public static final int SUB_REASON_CRAYX1_HARDLABEL = 0x00000080;
+
+    /**
+     * < Limit exceeded in regions   or domains
+     */
+    public static final int SUB_REASON_CRAYX1_LIMIT = 0x00000100;
+
+    /**
+     * < Memory size does not match  those allowed by the gate
+     */
+    public static final int SUB_REASON_CRAYX1_MEMORY = 0x00000200;
+
+    /**
+     * < Soft label does not match   those allowed by the gate
+     */
+    public static final int SUB_REASON_CRAYX1_SOFTLABEL = 0x00000400;
+
+    /**
+     * < Size gate (width times  depth larger than gate  allows)
+     */
+    public static final int SUB_REASON_CRAYX1_SIZE = 0x00000800;
+
+    /**
+     * < Time limit does not match those allowed by the gate
+     */
+    public static final int SUB_REASON_CRAYX1_TIME = 0x00001000;
+
+    /**
+     * < UID does not match those  allowed by the gate
+     */
+    public static final int SUB_REASON_CRAYX1_UID = 0x00002000;
+
+    /**
+     * < Width does not match those allowed by the gate
+     */
+    public static final int SUB_REASON_CRAYX1_WIDTH = 0x00004000;
+/*
+*  EXITING REASONS: currently only to indicate exited due to
+*  1) rerunnable job being restart from last chkpnt;
+*  2) being killed while execution host is unavailable
+ */
+
+    /** Job finished normally */
+    public static final int EXIT_NORMAL = 0x00000000;
+
+    /** Rerunnable job to be restarted */
+    public static final int EXIT_RESTART = 0x00000001;
+
+    /** Job killed while host unavailable */
+    public static final int EXIT_ZOMBIE = 0x00000002;
+
+    /** Job is finished and put into pend list */
+    public static final int FINISH_PEND = 0x00000004;
+
+    /** The job is killed while the execution host is unreach */
+    public static final int EXIT_KILL_ZOMBIE = 0x00000008;
+
+    /** The job in ZOMBIE is removed */
+    public static final int EXIT_ZOMBIE_JOB = 0x00000010;
+
+    /** Rerun a job without creating a ZOMBIE job */
+    public static final int EXIT_RERUN = 0x00000020;
+
+    /** Remote job has no mapping user name here */
+    public static final int EXIT_NO_MAPPING = 0x00000040;
+
+    /** Remote job has no permission running here */
+    public static final int EXIT_REMOTE_PERMISSION = 0x00000080;
+
+    /** Remote job cannot run locally because of environment problem */
+    public static final int EXIT_INIT_ENVIRON = 0x00000100;
+
+    /** Remote job failed in pre_exec command */
+    public static final int EXIT_PRE_EXEC = 0x00000200;
+
+    /** The job is killed and will be later requeued */
+    public static final int EXIT_REQUEUE = 0x00000400;
+
+    /** Job could not be killed but was removed from system */
+    public static final int EXIT_REMOVE = 0x00000800;
+
+    /** Requeue by exit value */
+    public static final int EXIT_VALUE_REQUEUE = 0x00001000;
+
+    /** Cancel request received from remote cluster. */
+    public static final int EXIT_CANCEL = 0x00002000;
+
+    /** MED killed job on web server */
+    public static final int EXIT_MED_KILLED = 0x00004000;
+
+    /** Remote lease job exit on execution, side, return to pend on submission */
+    public static final int EXIT_REMOTE_LEASE_JOB = 0x00008000;
+
+    /** Exit when cwd does not exist*/
+    public static final int EXIT_CWD_NOTEXIST = 0x00010000;
+
+
+    /** Mode indicating running in batch, js, or batch-js mode */
+    public static final int LSB_MODE_BATCH = 0x1;
+    public static final int LSB_MODE_JS = 0x2;
+    public static final int LSB_MODE_BATCH_RD = 0x4;
+
+    public static final int RLIMIT_CPU = 0;
+    public static final int RLIMIT_FSIZE = 1;
+    public static final int RLIMIT_DATA = 2;
+    public static final int RLIMIT_STACK = 3;
+    public static final int RLIMIT_CORE = 4;
+    public static final int RLIMIT_RSS = 5;
+    public static final int RLIM_INFINITY = 0x7fffffff;
+
+/*
+*  Error codes for lsblib calls
+*  Each error code has its corresponding error message defined in lsb.err.c
+*  The code number is just the position number of its message.
+*  Adding a new code here must add its message there in the corresponding
+*  position.  Changing any code number here must change the position there.
+ */
+/* Error codes related to job */
+
+    /** No error at all */
+    public static final int LSBE_NO_ERROR = 0;
+
+    /** No matching job found */
+    public static final int LSBE_NO_JOB = 1;
+
+    /** Job not started yet */
+    public static final int LSBE_NOT_STARTED = 2;
+
+    /** Job already started */
+    public static final int LSBE_JOB_STARTED = 3;
+
+    /** Job already finished */
+    public static final int LSBE_JOB_FINISH = 4;
+
+    /** Ask sbatchd to stop the wrong job */
+    public static final int LSBE_STOP_JOB = 5;
+
+    /** Depend_cond syntax error */
+    public static final int LSBE_DEPEND_SYNTAX = 6;
+
+    /** Queue doesn't accept EXCLUSIVE job */
+    public static final int LSBE_EXCLUSIVE = 7;
+
+    /** Root is not allowed to submit jobs */
+    public static final int LSBE_ROOT = 8;
+
+    /** Job is already being migrated */
+    public static final int LSBE_MIGRATION = 9;
+
+    /** Job is not chkpntable */
+    public static final int LSBE_J_UNCHKPNTABLE = 10;
+
+    /** Job has no output so far */
+    public static final int LSBE_NO_OUTPUT = 11;
+
+    /** No jobId can be used now */
+    public static final int LSBE_NO_JOBID = 12;
+
+    /** Queue only accepts bsub -I job */
+    public static final int LSBE_ONLY_INTERACTIVE = 13;
+
+    /** Queue doesn't accept bsub -I job */
+    public static final int LSBE_NO_INTERACTIVE = 14;
+
+/** Error codes related to user, queue and host */
+
+    /** No user defined in lsb.users file */
+    public static final int LSBE_NO_USER = 15;
+
+    /** Bad user name */
+    public static final int LSBE_BAD_USER = 16;
+
+    /** User permission denied */
+    public static final int LSBE_PERMISSION = 17;
+
+    /** No such queue in the system */
+    public static final int LSBE_BAD_QUEUE = 18;
+
+    /** Queue name should be given */
+    public static final int LSBE_QUEUE_NAME = 19;
+
+    /** Queue has been closed */
+    public static final int LSBE_QUEUE_CLOSED = 20;
+
+    /** Queue windows are closed */
+    public static final int LSBE_QUEUE_WINDOW = 21;
+
+    /** User cannot use the queue */
+    public static final int LSBE_QUEUE_USE = 22;
+
+    /** Bad host name or host group name" */
+    public static final int LSBE_BAD_HOST = 23;
+
+    /** Too many processors requested */
+    public static final int LSBE_PROC_NUM = 24;
+
+    /** No host partition in the system */
+    public static final int LSBE_NO_HPART = 25;
+
+    /** Bad host partition name */
+    public static final int LSBE_BAD_HPART = 26;
+
+    /** No group defined in the system */
+    public static final int LSBE_NO_GROUP = 27;
+
+    /** Bad host/user group name */
+    public static final int LSBE_BAD_GROUP = 28;
+
+    /** Host is not used by the queue */
+    public static final int LSBE_QUEUE_HOST = 29;
+
+    /** User reach UJOB_LIMIT of the queue */
+    public static final int LSBE_UJOB_LIMIT = 30;
+
+    /** No host available for migration */
+    public static final int LSBE_NO_HOST = 31;
+
+
+    /** chklog is corrupted */
+    public static final int LSBE_BAD_CHKLOG = 32;
+
+    /** User reach PJOB_LIMIT of the queue */
+    public static final int LSBE_PJOB_LIMIT = 33;
+
+    /** request from non LSF host rejected*/
+    public static final int LSBE_NOLSF_HOST = 34;
+
+/** Error codes related to input arguments of lsblib call */
+
+    /** Bad argument for lsblib call */
+    public static final int LSBE_BAD_ARG = 35;
+
+    /** Bad time spec for lsblib call */
+    public static final int LSBE_BAD_TIME = 36;
+
+    /** Start time is later than end time */
+    public static final int LSBE_START_TIME = 37;
+
+    /** Bad CPU limit specification */
+    public static final int LSBE_BAD_LIMIT = 38;
+
+    /** Over hard limit of queue */
+    public static final int LSBE_OVER_LIMIT = 39;
+
+    /** Empty job (command) */
+    public static final int LSBE_BAD_CMD = 40;
+
+    /** Bad signal value; not supported */
+    public static final int LSBE_BAD_SIGNAL = 41;
+
+    /** Bad job name */
+    public static final int LSBE_BAD_JOB = 42;
+
+    /** Queue reach QJOB_LIMIT of the queue */
+    public static final int LSBE_QJOB_LIMIT = 43;
+
+    /** Expired job terminate time*/
+    public static final int LSBE_BAD_TERM = 44;
+/** 44 is reserved for future use */
+
+/** Error codes related to lsb.events file */
+
+    /** Unknown event in event log file */
+    public static final int LSBE_UNKNOWN_EVENT = 45;
+
+    /** bad event format in event log file */
+    public static final int LSBE_EVENT_FORMAT = 46;
+
+    /** End of file */
+    public static final int LSBE_EOF = 47;
+/** 48-49 are reserved for future use */
+
+/** Error codes related to system failure */
+
+    /** mbatchd internal error */
+    public static final int LSBE_MBATCHD = 50;
+
+    /** sbatchd internal error */
+    public static final int LSBE_SBATCHD = 51;
+
+    /** lsbatch lib internal error */
+    public static final int LSBE_LSBLIB = 52;
+
+    /** LSLIB call fails */
+    public static final int LSBE_LSLIB = 53;
+
+    /** System call fails */
+    public static final int LSBE_SYS_CALL = 54;
+
+    /** Cannot alloc memory */
+    public static final int LSBE_NO_MEM = 55;
+
+    /** Lsbatch service not registered */
+    public static final int LSBE_SERVICE = 56;
+
+    /** LSB_SHAREDIR not defined */
+    public static final int LSBE_NO_ENV = 57;
+
+    /** chkpnt system call fail */
+    public static final int LSBE_CHKPNT_CALL = 58;
+
+    /** mbatchd cannot fork */
+    public static final int LSBE_NO_FORK = 59;
+
+/** Error codes related to communication between mbatchd/lsblib/sbatchd */
+
+    /** LSBATCH protocol error */
+    public static final int LSBE_PROTOCOL = 60;
+
+    /** XDR en/decode error */
+    public static final int LSBE_XDR = 61;
+
+    /** No appropriate port can be bound */
+    public static final int LSBE_PORT = 62;
+
+    /** Timeout in contacting mbatchd */
+    public static final int LSBE_TIME_OUT = 63;
+
+    /** Timeout on connect() call */
+    public static final int LSBE_CONN_TIMEOUT = 64;
+
+    /** Connection refused by server */
+    public static final int LSBE_CONN_REFUSED = 65;
+
+    /** server connection already exists */
+    public static final int LSBE_CONN_EXIST = 66;
+
+    /** server is not connected */
+    public static final int LSBE_CONN_NONEXIST = 67;
+
+    /** sbatchd cannot be reached */
+    public static final int LSBE_SBD_UNREACH = 68;
+
+    // Search for any ; \s+ /** and fix the comments
+    /** Operation cannot be performed right now, op. will be retried. */
+    public static final int LSBE_OP_RETRY = 69;
+
+    /** user has no enough job slots */
+    public static final int LSBE_USER_JLIMIT = 70;
+/** 71 is reserved for future use */
+
+/** Error codes related to NQS */
+
+    /** Bad specification for a NQS job */
+    public static final int LSBE_NQS_BAD_PAR = 72;
+
+
+    /** Client host has no license */
+    public static final int LSBE_NO_LICENSE = 73;
+
+/** Error codes related to calendar */
+
+    /** Bad calendar name */
+    public static final int LSBE_BAD_CALENDAR = 74;
+
+    /** No calendar found */
+    public static final int LSBE_NOMATCH_CALENDAR = 75;
+
+    /** No calendar in system */
+    public static final int LSBE_NO_CALENDAR = 76;
+
+    /** Bad calendar time events */
+    public static final int LSBE_BAD_TIMEEVENT = 77;
+
+    /** Calendar exist already */
+    public static final int LSBE_CAL_EXIST = 78;
+
+    /** Calendar function is not enabled*/
+    public static final int LSBE_CAL_DISABLED = 79;
+
+/** Error codes related to modify job's parameters */
+
+    /** the job's params cannot be changed */
+    public static final int LSBE_JOB_MODIFY = 80;
+    /** the changed once parameters are not used */
+    public static final int LSBE_JOB_MODIFY_ONCE = 81;
+
+
+    /** the job is not a repetitive job */
+    public static final int LSBE_J_UNREPETITIVE = 82;
+
+    /** bad cluster name */
+    public static final int LSBE_BAD_CLUSTER = 83;
+
+/** Error codes related jobs driven by calendar */
+
+    /** Job can not be killed in pending */
+    public static final int LSBE_PEND_CAL_JOB = 84;
+    /** This Running turn is being terminated */
+    public static final int LSBE_RUN_CAL_JOB = 85;
+
+
+    /** Modified parameters are being used */
+    public static final int LSBE_JOB_MODIFY_USED = 86;
+
+    /** Can not get user's token */
+    public static final int LSBE_AFS_TOKENS = 87;
+
+/** Error codes related to event */
+
+    /** Bad event name */
+    public static final int LSBE_BAD_EVENT = 88;
+
+    /** No event found */
+    public static final int LSBE_NOMATCH_EVENT = 89;
+
+    /** No event in system */
+    public static final int LSBE_NO_EVENT = 90;
+
+/** Error codes related to user, queue and host */
+
+    /** User reach HJOB_LIMIT of the queue */
+    public static final int LSBE_HJOB_LIMIT = 91;
+
+/** Error codes related to bmsg */
+
+    /** Message delivered */
+    public static final int LSBE_MSG_DELIVERED = 92;
+    /** MBD could not find the message that SBD mentions about */
+    public static final int LSBE_NO_JOBMSG = 93;
+
+    /** x */
+    public static final int LSBE_MSG_RETRY = 94;
+
+/** Error codes related to resource requirement */
+
+    /** Bad resource requirement */
+    public static final int LSBE_BAD_RESREQ = 95;
+
+
+    /** No enough hosts */
+    public static final int LSBE_NO_ENOUGH_HOST = 96;
+
+/** Error codes related to configuration lsblib call */
+
+    /** Fatal error in reading conf files */
+    public static final int LSBE_CONF_FATAL = 97;
+
+    /** Warning error in reading conf files */
+    public static final int LSBE_CONF_WARNING = 98;
+
+
+    /** CONF used calendar cannot be modified */
+    public static final int LSBE_CAL_MODIFY = 99;
+
+    /** Job created calendar cannot be modified */
+    public static final int LSBE_JOB_CAL_MODIFY = 100;
+    /** FAIRSHARE queue or HPART defined */
+    public static final int LSBE_HP_FAIRSHARE_DEF = 101;
+
+    /** No resource specified */
+    public static final int LSBE_NO_RESOURCE = 102;
+
+    /** Bad resource name */
+    public static final int LSBE_BAD_RESOURCE = 103;
+    /** Calendar not allowed for interactive job */
+    public static final int LSBE_INTERACTIVE_CAL = 104;
+    /** Interactive job cannot be rerunnable */
+    public static final int LSBE_INTERACTIVE_RERUN = 105;
+
+    /** PTY and infile specified */
+    public static final int LSBE_PTY_INFILE = 106;
+
+    /** JobScheduler is disabled */
+    public static final int LSBE_JS_DISABLED = 107;
+
+    /** Submission host and its host type can not be found any more */
+    public static final int LSBE_BAD_SUBMISSION_HOST = 108;
+    /** Lock the job so that it cann't be resume by sbatchd */
+    public static final int LSBE_LOCK_JOB = 109;
+
+    /** user not in the user group */
+    public static final int LSBE_UGROUP_MEMBER = 110;
+    /** Operation not supported for a Multicluster job */
+    public static final int LSBE_UNSUPPORTED_MC = 111;
+    /** Operation permission denied for a Multicluster job */
+    public static final int LSBE_PERMISSION_MC = 112;
+
+    /** System Calendar exist already */
+    public static final int LSBE_SYSCAL_EXIST = 113;
+
+    /** exceed q's resource reservation */
+    public static final int LSBE_OVER_RUSAGE = 114;
+
+    /** bad host spec of run/cpu limits */
+    public static final int LSBE_BAD_HOST_SPEC = 115;
+
+    /** calendar syntax error */
+    public static final int LSBE_SYNTAX_CALENDAR = 116;
+
+    /** delete a used calendar */
+    public static final int LSBE_CAL_USED = 117;
+
+    /** cyclic calednar dependence */
+    public static final int LSBE_CAL_CYC = 118;
+
+    /** bad user group name */
+    public static final int LSBE_BAD_UGROUP = 119;
+
+    /** esub aborted request */
+    public static final int LSBE_ESUB_ABORT = 120;
+
+    /** Bad exception handler syntax */
+    public static final int LSBE_EXCEPT_SYNTAX = 121;
+    /** Bad exception condition specification */
+    public static final int LSBE_EXCEPT_COND = 122;
+    /** Bad or invalid action specification */
+    public static final int LSBE_EXCEPT_ACTION = 123;
+
+    /** job dependence, not deleted immed */
+    public static final int LSBE_JOB_DEP = 124;
+/** error codes for job group */
+
+    /** the job group exists */
+    public static final int LSBE_JGRP_EXIST = 125;
+
+    /** the job group doesn't exist */
+    public static final int LSBE_JGRP_NULL = 126;
+
+    /** the group contains jobs */
+    public static final int LSBE_JGRP_HASJOB = 127;
+
+    /** the unknown group control signal */
+    public static final int LSBE_JGRP_CTRL_UNKWN = 128;
+
+    /** Bad Job Group name */
+    public static final int LSBE_JGRP_BAD = 129;
+
+    /** Job Array */
+    public static final int LSBE_JOB_ARRAY = 130;
+
+    /** Suspended job not supported */
+    public static final int LSBE_JOB_SUSP = 131;
+
+    /** Forwarded job not suported */
+    public static final int LSBE_JOB_FORW = 132;
+
+    /** parent group is held */
+    public static final int LSBE_JGRP_HOLD = 133;
+
+    /** bad index */
+    public static final int LSBE_BAD_IDX = 134;
+
+    /** index too big */
+    public static final int LSBE_BIG_IDX = 135;
+
+    /** job array not exist*/
+    public static final int LSBE_ARRAY_NULL = 136;
+
+    /** Void calendar */
+    public static final int LSBE_CAL_VOID = 137;
+
+    /** the job exists */
+    public static final int LSBE_JOB_EXIST = 138;
+
+    /** Job Element fail */
+    public static final int LSBE_JOB_ELEMENT = 139;
+
+    /** Bad jobId */
+    public static final int LSBE_BAD_JOBID = 140;
+
+    /** cannot change job name */
+    public static final int LSBE_MOD_JOB_NAME = 141;
+
+/** error codes for frame job */
+
+    /** Bad frame expression */
+    public static final int LSBE_BAD_FRAME = 142;
+
+    /** Frame index too long */
+    public static final int LSBE_FRAME_BIG_IDX = 143;
+
+    /** Frame index syntax error */
+    public static final int LSBE_FRAME_BAD_IDX = 144;
+
+
+    /** child process died */
+    public static final int LSBE_PREMATURE = 145;
+
+/** error code for user not in project group */
+
+    /** Invoker is not in project group */
+    public static final int LSBE_BAD_PROJECT_GROUP = 146;
+
+/** error code for user group / host group */
+
+    /** No host group defined in the system */
+    public static final int LSBE_NO_HOST_GROUP = 147;
+
+    /** No user group defined in the system */
+    public static final int LSBE_NO_USER_GROUP = 148;
+
+    /** Bad jobid index file format */
+    public static final int LSBE_INDEX_FORMAT = 149;
+
+/** error codes for IO_SPOOL facility */
+
+    /** source file does not exist */
+    public static final int LSBE_SP_SRC_NOT_SEEN = 150;
+
+    /** Number of failed spool hosts reached max */
+    public static final int LSBE_SP_FAILED_HOSTS_LIM = 151;
+
+    /** spool copy failed for this host*/
+    public static final int LSBE_SP_COPY_FAILED = 152;
+
+    /** fork failed */
+    public static final int LSBE_SP_FORK_FAILED = 153;
+
+    /** status of child is not available */
+    public static final int LSBE_SP_CHILD_DIES = 154;
+
+    /** child terminated with failure */
+    public static final int LSBE_SP_CHILD_FAILED = 155;
+
+    /** Unable to find a host for spooling */
+    public static final int LSBE_SP_FIND_HOST_FAILED = 156;
+
+    /** Cannot get $JOB_SPOOLDIR for this host */
+    public static final int LSBE_SP_SPOOLDIR_FAILED = 157;
+
+    /** Cannot delete spool file for this host */
+    public static final int LSBE_SP_DELETE_FAILED = 158;
+
+
+    /** Bad user priority */
+    public static final int LSBE_BAD_USER_PRIORITY = 159;
+
+    /** Job priority control undefined */
+    public static final int LSBE_NO_JOB_PRIORITY = 160;
+
+    /** Job has been killed & requeued */
+    public static final int LSBE_JOB_REQUEUED = 161;
+
+    /** Remote job cannot kill-requeued */
+    public static final int LSBE_JOB_REQUEUE_REMOTE = 162;
+
+    /** Cannot submit job array to a NQS queue */
+    public static final int LSBE_NQS_NO_ARRJOB = 163;
+
+/** error codes for EXT_JOB_STATUS */
+
+    /** No message available */
+    public static final int LSBE_BAD_EXT_MSGID = 164;
+
+    /** Not a regular file */
+    public static final int LSBE_NO_IFREG = 165;
+
+    /** MBD fail to create files in the directory*/
+    public static final int LSBE_BAD_ATTA_DIR = 166;
+
+    /** Fail to transfer data */
+    public static final int LSBE_COPY_DATA = 167;
+
+    /** exceed the limit on data transferring of a msg*/
+    public static final int LSBE_JOB_ATTA_LIMIT = 168;
+
+    /** cannot resize a chunk job, cannot bswitch a run/wait job */
+    public static final int LSBE_CHUNK_JOB = 169;
+
+/** Error code used in communications with dlogd */
+
+
+    /** dlogd is already connected */
+    public static final int LSBE_DLOGD_ISCONN = 170;
+
+/** Error code for LANL3_1ST_HOST */
+
+    /** Multiple first execution host */
+    public static final int LSBE_MULTI_FIRST_HOST = 171;
+
+    /** Host group as first execution host */
+    public static final int LSBE_HG_FIRST_HOST = 172;
+
+    /** Host partition as first execution host */
+    public static final int LSBE_HP_FIRST_HOST = 173;
+
+    /** "others" as first execution host */
+    public static final int LSBE_OTHERS_FIRST_HOST = 174;
+
+/** error code for multi-cluster: remote only queue */
+
+    /** cannot specify exec host */
+    public static final int LSBE_MC_HOST = 175;
+
+    /** cannot specify repetitive job */
+    public static final int LSBE_MC_REPETITIVE = 176;
+
+    /** cannot be a chkpnt job */
+    public static final int LSBE_MC_CHKPNT = 177;
+
+    /** cannot specify exception */
+    public static final int LSBE_MC_EXCEPTION = 178;
+
+    /** cannot specify time event */
+    public static final int LSBE_MC_TIMEEVENT = 179;
+
+    /** Too few processors requested */
+    public static final int LSBE_PROC_LESS = 180;
+    /** bmod pending options and running options together towards running job */
+    public static final int LSBE_MOD_MIX_OPTS = 181;
+
+    /** cannot bmod remote running job */
+    public static final int LSBE_MOD_REMOTE = 182;
+    /** cannot bmod cpulimit without LSB_JOB_CPULIMIT defined */
+    public static final int LSBE_MOD_CPULIMIT = 183;
+    /** cannot bmod memlimit without LSB_JOB_MEMLIMIT defined */
+    public static final int LSBE_MOD_MEMLIMIT = 184;
+
+    /** cannot bmod err file name */
+    public static final int LSBE_MOD_ERRFILE = 185;
+
+    /** host is locked by master LIM*/
+    public static final int LSBE_LOCKED_MASTER = 186;
+    /** warning time period is invalid */
+    public static final int LSBE_WARNING_INVALID_TIME_PERIOD = 187;
+    /** either warning time period or warning action is not specified */
+    public static final int LSBE_WARNING_MISSING = 188;
+    /** The job arrays involved in  one to one dependency do not  have the same size. */
+    public static final int LSBE_DEP_ARRAY_SIZE = 189;
+
+    /** Not enough processors to be reserved (lsb_addreservation()) */
+    public static final int LSBE_FEWER_PROCS = 190;
+
+    /** Bad reservation ID */
+    public static final int LSBE_BAD_RSVID = 191;
+
+    /** No more reservation IDs can be used now */
+    public static final int LSBE_NO_RSVID = 192;
+
+    /** No hosts are exported */
+    public static final int LSBE_NO_EXPORT_HOST = 193;
+
+    /** Trying to control remote hosts*/
+    public static final int LSBE_REMOTE_HOST_CONTROL = 194;
+
+/*Can't open a remote host closed by the remote cluster admin */
+    public static final int LSBE_REMOTE_CLOSED = 195;
+
+    /** User suspended job */
+    public static final int LSBE_USER_SUSPENDED = 196;
+
+    /** Admin suspended job */
+    public static final int LSBE_ADMIN_SUSPENDED = 197;
+
+    /** Not a local host name in  bhost -e command */
+    public static final int LSBE_NOT_LOCAL_HOST = 198;
+
+    /** The host's lease is not active. */
+    public static final int LSBE_LEASE_INACTIVE = 199;
+
+    /** The advance reserved host is not on queue. */
+    public static final int LSBE_QUEUE_ADRSV = 200;
+
+    /** The specified host(s) is not exported. */
+    public static final int LSBE_HOST_NOT_EXPORTED = 201;
+
+    /** The user specified host is not inn advance reservation */
+    public static final int LSBE_HOST_ADRSV = 202;
+
+    /** The remote cluster is not connected */
+    public static final int LSBE_MC_CONN_NONEXIST = 203;
+
+    /** The general resource limit broken */
+    public static final int LSBE_RL_BREAK = 204;
+
+/** ---- The following RMS errors are obsoleted in Eagle */
+
+    /** cannot submit a job with special topology requirement to a preemptive queue*/
+    public static final int LSBE_LSF2TP_PREEMPT = 205;
+
+    /** cannot submit a job with special topology requirement to a queue with slot reservation*/
+    public static final int LSBE_LSF2TP_RESERVE = 206;
+    /** cannot submit a job with special topology requirement to a queue with backill */
+    public static final int LSBE_LSF2TP_BACKFILL = 207;
+    /** ---- The above RMS errors are obsoleted in Eagle */
+
+    /** none existed policy name */
+    public static final int LSBE_RSV_POLICY_NAME_BAD = 208;
+
+    /** All normal user has no privilege */
+    public static final int LSBE_RSV_POLICY_PERMISSION_DENIED = 209;
+
+    /** user has no privilege */
+    public static final int LSBE_RSV_POLICY_USER = 210;
+
+    /** user has no privilege to create reservation on host */
+    public static final int LSBE_RSV_POLICY_HOST = 211;
+
+    /** time window is not allowed by policy */
+    public static final int LSBE_RSV_POLICY_TIMEWINDOW = 212;
+
+    /** the feature is disabled */
+    public static final int LSBE_RSV_POLICY_DISABLED = 213;
+    /** the general limit related errors */
+
+    /** There are no general limit defined */
+    public static final int LSBE_LIM_NO_GENERAL_LIMIT = 214;
+
+    /** There are no resource usage */
+    public static final int LSBE_LIM_NO_RSRC_USAGE = 215;
+
+    /** Convert data error */
+    public static final int LSBE_LIM_CONVERT_ERROR = 216;
+
+    /** There are no qualified host found in cluster*/
+    public static final int LSBE_RSV_NO_HOST = 217;
+
+    /** Cannot modify job group on element of job array */
+    public static final int LSBE_MOD_JGRP_ARRAY = 218;
+
+    /** Cannot combine modify job group or service class option with others */
+    public static final int LSBE_MOD_MIX = 219;
+
+    /** the service class doesn't exist */
+    public static final int LSBE_SLA_NULL = 220;
+
+    /** Modify job group for job in service class is not supported*/
+    public static final int LSBE_MOD_JGRP_SLA = 221;
+
+    /** User or user group is not a member of the specified service class */
+    public static final int LSBE_SLA_MEMBER = 222;
+
+    /** There is no exceptional host found */
+    public static final int LSBE_NO_EXCEPTIONAL_HOST = 223;
+
+    /** warning action (signal) is invalid */
+    public static final int LSBE_WARNING_INVALID_ACTION = 224;
+
+
+    /** Extsched option syntax error */
+    public static final int LSBE_EXTSCHED_SYNTAX = 225;
+
+    /** SLA doesn't work with remote only queues */
+    public static final int LSBE_SLA_RMT_ONLY_QUEUE = 226;
+
+    /** Cannot modify service class on element of job array */
+    public static final int LSBE_MOD_SLA_ARRAY = 227;
+
+    /** Modify service class for job in job group is not supported*/
+    public static final int LSBE_MOD_SLA_JGRP = 228;
+
+    /** Max. Pending job error */
+    public static final int LSBE_MAX_PEND = 229;
+
+    /** System concurrent query exceeded */
+    public static final int LSBE_CONCURRENT = 230;
+
+    /** Requested feature not enabled */
+    public static final int LSBE_FEATURE_NULL = 231;
+
+
+    /** Host is already member of group */
+    public static final int LSBE_DYNGRP_MEMBER = 232;
+
+    /** Host is not a dynamic host */
+    public static final int LSBE_BAD_DYN_HOST = 233;
+
+    /** Host was not added with badmin hghostadd */
+    public static final int LSBE_NO_GRP_MEMBER = 234;
+
+    /** Cannot create job info file */
+    public static final int LSBE_JOB_INFO_FILE = 235;
+
+    /** Cannot modify rusage to a new || (or) expression after the job is dispatched */
+    public static final int LSBE_MOD_OR_RUSAGE = 236;
+
+    /** Bad host group name */
+    public static final int LSBE_BAD_GROUP_NAME = 237;
+
+    /** Bad host name */
+    public static final int LSBE_BAD_HOST_NAME = 238;
+
+    /** Bsub is not permitted on DT cluster */
+    public static final int LSBE_DT_BSUB = 239;
+
+
+    /** The parent symphony job/group was  gone when submitting jobs*/
+    public static final int LSBE_PARENT_SYM_JOB = 240;
+
+    /** The partition has no cpu alllocated */
+    public static final int LSBE_PARTITION_NO_CPU = 241;
+
+    /** batch partition does not accept online jobs: obsolete */
+    public static final int LSBE_PARTITION_BATCH = 242;
+
+    /** online partition does not accept batch jobs */
+    public static final int LSBE_PARTITION_ONLINE = 243;
+
+    /** no batch licenses */
+    public static final int LSBE_NOLICENSE_BATCH = 244;
+
+    /** no online licenses */
+    public static final int LSBE_NOLICENSE_ONLINE = 245;
+
+    /** signal is not supported for service job */
+    public static final int LSBE_SIGNAL_SRVJOB = 246;
+
+    /** the begin time is not later than current time. */
+    public static final int LSBE_BEGIN_TIME_INVALID = 247;
+
+    /** the end time is not later than current time. */
+    public static final int LSBE_END_TIME_INVALID = 248;
+
+    /** Bad regular expression */
+    public static final int LSBE_BAD_REG_EXPR = 249;
+
+
+    /** Host group has regular expression */
+    public static final int LSBE_GRP_REG_EXPR = 250;
+
+    /** Host group have no member */
+    public static final int LSBE_GRP_HAVE_NO_MEMB = 251;
+
+    /** the application doesn't exist */
+    public static final int LSBE_APP_NULL = 252;
+
+    /** job's proclimit rejected by App */
+    public static final int LSBE_PROC_JOB_APP = 253;
+
+    /** app's proclimit rejected by Queue */
+    public static final int LSBE_PROC_APP_QUE = 254;
+
+    /** application name is too long */
+    public static final int LSBE_BAD_APPNAME = 255;
+
+    /** Over hard limit of queue */
+    public static final int LSBE_APP_OVER_LIMIT = 256;
+
+    /** Cannot remove default application */
+    public static final int LSBE_REMOVE_DEF_APP = 257;
+
+    /** Host is disabled by EGO */
+    public static final int LSBE_EGO_DISABLED = 258;
+
+    /** Host is a remote host. Remote hosts cannot be added to a local host group. */
+    public static final int LSBE_REMOTE_HOST = 259;
+
+    /** SLA is exclusive, only accept exclusive job. */
+    public static final int LSBE_SLA_EXCLUSIVE = 260;
+
+    /** SLA is non-exclusive, only accept non-exclusive job */
+    public static final int LSBE_SLA_NONEXCLUSIVE = 261;
+
+    /** The feature has already been started */
+    public static final int LSBE_PERFMON_STARTED = 262;
+
+    /** The Featurn has already been turn down */
+    public static final int LSBE_PERFMON_STOPED = 263;
+
+    /** Current sampling period is already set to %%s,seconds. Ignored*/
+    public static final int LSBE_PERFMON_PERIOD_SET = 264;
+
+    /** Default spool dir is disabled */
+    public static final int LSBE_DEFAULT_SPOOL_DIR_DISABLED = 265;
+
+    /** job belongs to an APS queue and cannot be moved */
+    public static final int LSBE_APS_QUEUE_JOB = 266;
+
+    /** job is not in an absolute priority enabled queue */
+    public static final int LSBE_BAD_APS_JOB = 267;
+
+    /** Wrong aps admin value */
+    public static final int LSBE_BAD_APS_VAL = 268;
+
+    /** Trying to delete a non-existent APS string */
+    public static final int LSBE_APS_STRING_UNDEF = 269;
+
+    /** A job cannot be assigned an SLA and an APS queue with factor FS */
+    public static final int LSBE_SLA_JOB_APS_QUEUE = 270;
+
+    /** bmod -aps | -apsn option cannot be mixed with other option */
+    public static final int LSBE_MOD_MIX_APS = 271;
+
+    /** specified ADMIN factor/system APS value out of range */
+    public static final int LSBE_APS_RANGE = 272;
+
+    /** specified ADMIN factor/system APS value is zero */
+    public static final int LSBE_APS_ZERO = 273;
+
+
+    /** res port is unknown */
+    public static final int LSBE_DJOB_RES_PORT_UNKNOWN = 274;
+
+    /** timeout on res communication */
+    public static final int LSBE_DJOB_RES_TIMEOUT = 275;
+
+    /** I/O error on remote stream */
+    public static final int LSBE_DJOB_RES_IOERR = 276;
+
+    /** res internal failure */
+    public static final int LSBE_DJOB_RES_INTERNAL_FAILURE = 277;
+
+
+    /** can not run outside LSF */
+    public static final int LSBE_DJOB_CAN_NOT_RUN = 278;
+
+    /** distributed job's validation failed due to incorrect job ID or index */
+    public static final int LSBE_DJOB_VALIDATION_BAD_JOBID = 279;
+
+    /** distributed job's validation failed due to incorrect host selection */
+    public static final int LSBE_DJOB_VALIDATION_BAD_HOST = 280;
+
+    /** distributed job's validation failed due to incorrect user */
+    public static final int LSBE_DJOB_VALIDATION_BAD_USER = 281;
+
+    /** failed while executing tasks */
+    public static final int LSBE_DJOB_EXECUTE_TASK = 282;
+
+    /** failed while waiting for tasks to finish*/
+    public static final int LSBE_DJOB_WAIT_TASK = 283;
+
+
+    /** HPC License not exist */
+    public static final int LSBE_APS_HPC = 284;
+
+    /** Integrity check of bsub command failed */
+    public static final int LSBE_DIGEST_CHECK_BSUB = 285;
+
+    /** Distributed Application Framework disabled */
+    public static final int LSBE_DJOB_DISABLED = 286;
+
+/** Error codes related to runtime estimation and cwd */
+
+    /** Bad runtime specification */
+    public static final int LSBE_BAD_RUNTIME = 287;
+
+    /** RUNLIMIT: Cannot exceed RUNTIME*JOB_RUNLIMIT_RATIO */
+    public static final int LSBE_BAD_RUNLIMIT = 288;
+
+    /** RUNTIME: Cannot exceed the hard runtime limit in the queue */
+    public static final int LSBE_OVER_QUEUE_LIMIT = 289;
+
+    /** RUNLIMIT: Is not set by command line */
+    public static final int LSBE_SET_BY_RATIO = 290;
+
+    /** current working directory name too long */
+    public static final int LSBE_BAD_CWD = 291;
+
+
+    /** Job group limit is greater than its parent group */
+    public static final int LSBE_JGRP_LIMIT_GRTR_THAN_PARENT = 292;
+
+    /** Job group limit is less than its children groups */
+    public static final int LSBE_JGRP_LIMIT_LESS_THAN_CHILDREN = 293;
+
+    /** Job Array end index should be specified explicitly */
+    public static final int LSBE_NO_ARRAY_END_INDEX = 294;
+
+    /** cannot bmod runtime without LSB_MOD_ALL_JOBS=y defined */
+    public static final int LSBE_MOD_RUNTIME = 295;
+
+    /** EP3 */
+    public static final int LSBE_BAD_SUCCESS_EXIT_VALUES = 296;
+    public static final int LSBE_DUP_SUCCESS_EXIT_VALUES = 297;
+    public static final int LSBE_NO_SUCCESS_EXIT_VALUES = 298;
+
+    public static final int LSBE_JOB_REQUEUE_BADARG = 299;
+    public static final int LSBE_JOB_REQUEUE_DUPLICATED = 300;
+
+    /** "all" with number */
+    public static final int LSBE_JOB_REQUEUE_INVALID_DIGIT = 301;
+
+    /** ~digit without "all" */
+    public static final int LSBE_JOB_REQUEUE_INVALID_TILDE = 302;
+    public static final int LSBE_JOB_REQUEUE_NOVALID = 303;
+
+
+    /** No matching job group found */
+    public static final int LSBE_NO_JGRP = 304;
+    public static final int LSBE_NOT_CONSUMABLE = 305;
+
+/** AR pre/post */
+
+    /** Cannot parse an Advance Reservation -exec string */
+    public static final int LSBE_RSV_BAD_EXEC = 306;
+
+    /** Unknown AR event type */
+    public static final int LSBE_RSV_EVENTTYPE = 307;
+
+    /** pre/post cannot have postive offset */
+    public static final int LSBE_RSV_SHIFT = 308;
+
+    /** pre-AR command cannot have offset < 0 in user-created AR */
+    public static final int LSBE_RSV_USHIFT = 309;
+
+    /** only one pre- and one post- cmd permitted per AR */
+    public static final int LSBE_RSV_NUMEVENTS = 310;
+
+/*Error codes related to AR Modification*/
+
+    /** ID does not correspond to a known AR. */
+    public static final int LSBE_ADRSV_ID_VALID = 311;
+
+    /** disable non-recurrent AR. */
+    public static final int LSBE_ADRSV_DISABLE_NONRECUR = 312;
+
+    /** modification is rejected because AR is activated. */
+    public static final int LSBE_ADRSV_MOD_ACTINSTANCE = 313;
+
+    /** modification is rejected because host slots is not available. */
+    public static final int LSBE_ADRSV_HOST_NOTAVAIL = 314;
+
+    /** the  time of the AR cannot be modified since resource is not available. */
+    public static final int LSBE_ADRSV_TIME_MOD_FAIL = 315;
+
+    /** resource requirement (-R) must be followed a slot requirment (-n) */
+    public static final int LSBE_ADRSV_R_AND_N = 316;
+
+/*modification is rejected because trying to empty the AR. */
+    public static final int LSBE_ADRSV_EMPTY = 317;
+
+/*modification is rejected because switching AR type. */
+    public static final int LSBE_ADRSV_SWITCHTYPE = 318;
+
+/*modification is rejected because specifying -n for system AR. */
+    public static final int LSBE_ADRSV_SYS_N = 319;
+
+    /** disable string is not valid. */
+    public static final int LSBE_ADRSV_DISABLE = 320;
+
+    /** Unique AR ID required */
+    public static final int LSBE_ADRSV_ID_UNIQUE = 321;
+
+    /** Bad reservation name */
+    public static final int LSBE_BAD_RSVNAME = 322;
+
+    /** Cannot change the start time of an active reservation. */
+    public static final int LSBE_ADVRSV_ACTIVESTART = 323;
+
+    /** AR ID is refernced by a job */
+    public static final int LSBE_ADRSV_ID_USED = 324;
+
+    /** the disable period has already been disabled */
+    public static final int LSBE_ADRSV_PREVDISABLED = 325;
+
+    /** an active period of a recurring reservation cannot be disabled */
+    public static final int LSBE_ADRSV_DISABLECURR = 326;
+
+    /** modification is rejected because specified hosts or host groups do not belong to the reservation */
+    public static final int LSBE_ADRSV_NOT_RSV_HOST = 327;
+
+/*new parser */
+
+/*checking resreq return ok */
+    public static final int LSBE_RESREQ_OK = 328;
+
+/*checking resreq return error */
+    public static final int LSBE_RESREQ_ERR = 329;
+
+
+    /** modification is rejected because reservation has running jobs on the specified hosts or host groups */
+    public static final int LSBE_ADRSV_HOST_USED = 330;
+
+
+    /** The checkpoint directory is too long */
+    public static final int LSBE_BAD_CHKPNTDIR = 331;
+
+    /** trying to modify in a remote cluster */
+    public static final int LSBE_ADRSV_MOD_REMOTE = 332;
+    public static final int LSBE_JOB_REQUEUE_BADEXCLUDE = 333;
+
+    /** trying to disable for a date in the past */
+    public static final int LSBE_ADRSV_DISABLE_DATE = 334;
+
+    /** cannot mix the -Un option with others for started jobs */
+    public static final int LSBE_ADRSV_DETACH_MIX = 335;
+
+    /** cannot detach a started job when the reservation is active */
+    public static final int LSBE_ADRSV_DETACH_ACTIVE = 336;
+
+    /** invalid time expression: must specify day for both start and end time */
+    public static final int LSBE_MISSING_START_END_TIME = 337;
+
+    /** Queue level limitation */
+    public static final int LSBE_JOB_RUSAGE_EXCEED_LIMIT = 338;
+
+    /** Queue level limitation */
+    public static final int LSBE_APP_RUSAGE_EXCEED_LIMIT = 339;
+
+    /** Hosts and host groups specified by -m are not used by the queue */
+    public static final int LSBE_CANDIDATE_HOST_EMPTY = 340;
+
+    /** An int must follow an open bracket */
+    public static final int LSBE_HS_BAD_AFTER_BRACKT = 341;
+
+    /** An end index must follow a dash */
+    public static final int LSBE_HS_NO_END_INDEX = 342;
+
+    /** Integers must come before and after the comma */
+    public static final int LSBE_HS_BAD_COMMA = 343;
+
+    /** Incorrect condensed host specification */
+    public static final int LSBE_HS_BAD_FORMAT = 344;
+
+    /** The start index must be less than end index */
+    public static final int LSBE_HS_BAD_ORDER = 345;
+
+    /** The end index must be less than 10 digits */
+    public static final int LSBE_HS_BAD_MANY_DIGITS = 346;
+
+    /** Number of digits in the start index must be less than that of end index */
+    public static final int LSBE_HS_BAD_NUM_DIGITS = 347;
+
+    /** The end index cannot start with zero (0) */
+    public static final int LSBE_HS_BAD_END_INDEX = 348;
+
+    /** Index must be an integer or a range */
+    public static final int LSBE_HS_BAD_INDEX = 349;
+
+/** host group admin*/
+
+    /** When a Host Group Admin (badmin hclose or hopen) closes or opens a host,  the usage of the -C "message" option must be compulsory, as is the logging  of the name of the person performing the action. */
+    public static final int LSBE_COMMENTS = 350;
+
+
+    /** First hosts specified by -m are not used by the queue */
+    public static final int LSBE_FIRST_HOSTS_NOT_IN_QUEUE = 351;
+
+
+    /** The job is not started */
+    public static final int LSBE_JOB_NOTSTART = 352;
+
+    /** Accumulated runtime of the job is not available */
+    public static final int LSBE_RUNTIME_INVAL = 353;
+
+    /** SSH feature can only be used for interactive job */
+    public static final int LSBE_SSH_NOT_INTERACTIVE = 354;
+
+    /** Run time specification is less than the accumulated run time */
+    public static final int LSBE_LESS_RUNTIME = 355;
+
+    /** Resize job notification command */
+    public static final int LSBE_RESIZE_NOTIFY_CMD_LEN = 356;
+
+    /** Job is not resizable */
+    public static final int LSBE_JOB_RESIZABLE = 357;
+
+    /** Bad bresize release host spec */
+    public static final int LSBE_RESIZE_RELEASE_HOSTSPEC = 358;
+
+    /** no resize notify matches in mbatchd*/
+    public static final int LSBE_NO_RESIZE_NOTIFY = 359;
+
+    /** Can't release first exec host */
+    public static final int LSBE_RESIZE_RELEASE_FRISTHOST = 360;
+
+    /** resize event in progress */
+    public static final int LSBE_RESIZE_EVENT_INPROGRESS = 361;
+
+    /** too few or too many slots */
+    public static final int LSBE_RESIZE_BAD_SLOTS = 362;
+
+    /** No active resize request */
+    public static final int LSBE_RESIZE_NO_ACTIVE_REQUEST = 363;
+
+    /** specified host not part of the job's allocation*/
+    public static final int LSBE_HOST_NOT_IN_ALLOC = 364;
+
+    /** nothing released */
+    public static final int LSBE_RESIZE_RELEASE_NOOP = 365;
+
+    /** Can't resize a brun job */
+    public static final int LSBE_RESIZE_URGENT_JOB = 366;
+    public static final int LSBE_RESIZE_EGO_SLA_COEXIST = 367;
+
+    /** hpc jobs can't be resized */
+    public static final int LSBE_HOST_NOT_SUPPORT_RESIZE = 368;
+
+    /** Application doesn't allow resizable */
+    public static final int LSBE_APP_RESIZABLE = 369;
+
+    /** can't operate on lost & found hosts*/
+    public static final int LSBE_RESIZE_LOST_AND_FOUND = 370;
+
+    /** can't resize while the first host is lost & found*/
+    public static final int LSBE_RESIZE_FIRSTHOST_LOST_AND_FOUND = 371;
+
+    /** bad host name (for resize) */
+    public static final int LSBE_RESIZE_BAD_HOST = 372;
+
+    /** proper app is required by an auto-resizable job */
+    public static final int LSBE_AUTORESIZE_APP = 373;
+
+    /** cannot resize job because there is a pedning resize request */
+    public static final int LSBE_RESIZE_PENDING_REQUEST = 374;
+
+    /** number of hosts specified by -m exceeding configuration */
+    public static final int LSBE_ASKED_HOSTS_NUMBER = 375;
+
+    /** All hosts reserved by advanced reservation are invalid in intersected hosts */
+    public static final int LSBE_AR_HOST_EMPTY = 376;
+
+    /** First hosts specified by -m are not used by advanced reservation */
+    public static final int LSBE_AR_FIRST_HOST_EMPTY = 377;
+
+    /** Internal jobbroker error */
+    public static final int LSBE_JB = 378;
+
+    /** Internal jobbroker database library error */
+    public static final int LSBE_JB_DBLIB = 379;
+
+    /** Jobbroker cannot reach database */
+    public static final int LSBE_JB_DB_UNREACH = 380;
+
+    /** Jobbroker cannot reach mbatchd */
+    public static final int LSBE_JB_MBD_UNREACH = 381;
+
+    /** BES server returned an error */
+    public static final int LSBE_JB_BES = 382;
+
+    /** Unsupported BES operation */
+    public static final int LSBE_JB_BES_UNSUPPORTED_OP = 383;
+
+    /** invalid LS project name*/
+    public static final int LSBE_LS_PROJECT_NAME = 384;
+
+    /** the end time is not later than start  time. */
+    public static final int LSBE_END_TIME_INVALID_COMPARE_START = 385;
+
+    /** one host cannot be defined in more than one host partition.*/
+    public static final int LSBE_HP_REDUNDANT_HOST = 386;
+
+    /** The application level compound resreq causes slots requirements conflict */
+    public static final int LSBE_COMPOUND_APP_SLOTS = 387;
+
+    /** The queue level compound resreq causes slots requirements conflict */
+    public static final int LSBE_COMPOUND_QUEUE_SLOTS = 388;
+
+    /** Resizable job cannot work with compound resreq */
+    public static final int LSBE_COMPOUND_RESIZE = 389;
+/** compute unit support */
+
+    /** Compute units cannot have overlapping hosts */
+    public static final int LSBE_CU_OVERLAPPING_HOST = 390;
+
+    /** The compute unit cannot contain other compute units */
+    public static final int LSBE_CU_BAD_HOST = 391;
+
+    /** The compute unit cannot contain host or host group as a member */
+    public static final int LSBE_CU_HOST_NOT_ALLOWED = 392;
+
+    /** Only lowest level compute units are allowed to add hosts as a member */
+    public static final int LSBE_CU_NOT_LOWEST_LEVEL = 393;
+
+    /** You cannot modify a compute unit resource requirement when a job is already running */
+    public static final int LSBE_CU_MOD_RESREQ = 394;
+
+    /** A compute unit resource requirement cannot be specified for auto resizable jobs */
+    public static final int LSBE_CU_AUTORESIZE = 395;
+
+    /** No COMPUTE_UNIT_TYPES are specified in lsb.params */
+    public static final int LSBE_NO_COMPUTE_UNIT_TYPES = 396;
+
+    /** No compute unit defined in the system */
+    public static final int LSBE_NO_COMPUTE_UNIT = 397;
+
+    /** No such compute unit defined in the system */
+    public static final int LSBE_BAD_COMPUTE_UNIT = 398;
+
+    /** The queue is not configured to accept exclusive compute unit jobs */
+    public static final int LSBE_CU_EXCLUSIVE = 399;
+
+    /** The queue is not configured to accept higher level of exclusive compute unit jobs */
+    public static final int LSBE_CU_EXCLUSIVE_LEVEL = 400;
+
+    /** Job cannot be switched due to the exclusive compute unit reqirement */
+    public static final int LSBE_CU_SWITCH = 401;
+
+    /** Job level compound resreq causes slots requirements conflict */
+    public static final int LSBE_COMPOUND_JOB_SLOTS = 402;
+
+    /** "||" used in rusage[] of queue resource requirement. It's conflict with job level compound resource requirement */
+    public static final int LSBE_COMPOUND_QUEUE_RUSAGE_OR = 403;
+
+    /** balance and usablecuslots cannot both be used in a compute unit resource requirement */
+    public static final int LSBE_CU_BALANCE_USABLECUSLOTS = 404;
+
+    /** TS jobs cannot use compound resource requirement (application level) */
+    public static final int LSBE_COMPOUND_TSJOB_APP = 405;
+
+    /** TS jobs cannot use compound resource requirement (queue level) */
+    public static final int LSBE_COMPOUND_TSJOB_QUEUE = 406;
+    /** Job dependency conditions using a job name or job name wild-card exceed limitation set by MAX_JOB_NAME_DEP in lsb.params */
+    public static final int LSBE_EXCEED_MAX_JOB_NAME_DEP = 407;
+
+    /** "is waiting for the remote cluster to synchronize." */
+    public static final int LSBE_WAIT_FOR_MC_SYNC = 408;
+
+    /** Job cannot exceed queue level RESRSV_LIMIT limitation */
+    public static final int LSBE_RUSAGE_EXCEED_RESRSV_LIMIT = 409;
+
+    /** job description too long */
+    public static final int LSBE_JOB_DESCRIPTION_LEN = 410;
+
+    /** Cannot use simulation options */
+    public static final int LSBE_NOT_IN_SIMMODE = 411;
+
+    /** Value of runtime simulation is incorrect */
+    public static final int LSBE_SIM_OPT_RUNTIME = 412;
+
+    /** Value of cputime simulation is incorrect */
+    public static final int LSBE_SIM_OPT_CPUTIME = 413;
+
+    /** Incorrect maxmem simulation opt */
+    public static final int LSBE_SIM_OPT_MAXMEM = 414;
+
+    /** Incorrect job exitstatus simulation opt */
+    public static final int LSBE_SIM_OPT_EXITSTATUS = 415;
+
+    /** Incorrect job simulation option syntax */
+    public static final int LSBE_SIM_OPT_SYNTAX = 416;
+
+    /** Number of the above error codes */
+    public static final int LSBE_NUM_ERR = 417;
+
+    /**
+     * *****************************************************
+     */
+
+/* op codes for hand shake protocol between client/server */
+    public static final int PREPARE_FOR_OP = 1024;
+    public static final int READY_FOR_OP = 1023;
+
+/*
+*  Data structures for lsblib interface
+ */
+
+
+    /**
+     * \addtogroup lsb_submit_options lsb_submit_options
+     * define statements used by lsb_submit.
+     */
+
+/* lsb_submit() options */
+    /**
+     * < Flag to indicate jobName parameter has data. Equivalent to bsub -J command line option existence.
+     */
+    public static final int SUB_JOB_NAME = 0x01;
+    /**
+     * < Flag to indicate queue parameter has data. Equivalent to bsub -q command line option existence.
+     */
+    public static final int SUB_QUEUE = 0x02;
+    /**
+     * < Flat to indicate numAskedHosts parameter has data. Equivalent to bsub -m command line option existence.
+     */
+    public static final int SUB_HOST = 0x04;
+    /**
+     * < Flag to indicate inFile parameter has data. Equivalent to bsub -i command line option existence.
+     */
+    public static final int SUB_IN_FILE = 0x08;
+    /**
+     * < Flag to indicate outFile parameter has data. Equivalent to bsub -o command line option existence.
+     */
+    public static final int SUB_OUT_FILE = 0x10;
+    /**
+     * < Flag to indicate errFile parameter has data. Equivalent to bsub -e command line option existence.
+     */
+    public static final int SUB_ERR_FILE = 0x20;
+    /**
+     * < Flag to indicate execution of a job on a host by itself requested. Equivalent to bsub -x command line option existence.
+     */
+    public static final int SUB_EXCLUSIVE = 0x40;
+    /**
+     * < Flag to indicate whether to send mail to the user when the job finishes. Equivalent to bsub -N command line option existence.
+     */
+    public static final int SUB_NOTIFY_END = 0x80;
+    /**
+     * < Flag to indicate whether to send mail to the user when the job is dispatched. Equivalent to bsub -B command line option existence.
+     */
+    public static final int SUB_NOTIFY_BEGIN = 0x100;
+    /**
+     * < Flag to indicate userGroup name parameter has data. Equivalent to bsub -G command line option existence.
+     */
+    public static final int SUB_USER_GROUP = 0x200;
+    /**
+     * < Flag to indicatechkpntPeriod parameter has data . Equivalent to bsub -k command line option existence.
+     */
+    public static final int SUB_CHKPNT_PERIOD = 0x400;
+    /**
+     * < Flag to indicate chkpntDir parameter has data. Equivalent to bsub -k command line option existence.
+     */
+    public static final int SUB_CHKPNT_DIR = 0x800;
+    /**
+     * < Indicates the job is checkpointable. Equivalent to bsub -k command line option.
+     */
+    public static final int SUB_CHKPNTABLE = SUB_CHKPNT_DIR;
+    /**
+     * < Flag to indicate whether to force the job to restart even if non-restartable conditions exist. These conditions are operating system specific. Equivalent to brestart() -f command line option existence.
+     */
+    public static final int SUB_RESTART_FORCE = 0x1000;
+    /**
+     * < Flag to indicate restart of a
+     * checkpointed job. Only jobs that have been successfully checkpointed
+     * can be restarted. Jobs are re-submitted and assigned a new job ID.
+     * By default, jobs are restarted with the same output file, file
+     * transfer specifications, job name, window signal value, checkpoint
+     * directory and period, and rerun options as the original job. To
+     * restart a job on another host, both hosts must be binary compatible,
+     * run the same OS version, have access to the executable, have access
+     * to all open files (LSF must locate them with an absolute path name),
+     * and have access to the checkpoint directory. Equivalent to bsub -k
+     * command line option existence.
+     */
+    public static final int SUB_RESTART = 0x2000;
+    /**
+     * < Indicates the job is re-runnable.
+     * If the execution host of the job is considered down, the batch
+     * system will re-queue this job in the same job queue, and re-run
+     * it from the beginning when a suitable host is found. Everything
+     * will be as if it were submitted as a new job, and a new job ID will
+     * be assigned. The user who submitted the failed job will receive a
+     * mail notice of the job failure, requeueing of the job, and the
+     * new job ID.
+     * <p/>
+     * For a job that was checkpointed before the execution host went down,
+     * the job will be restarted from the last checkpoint. Equivalent to
+     * bsub -r command line option existence.
+     */
+    public static final int SUB_RERUNNABLE = 0x4000;
+    /**
+     * < Flag to indicate sigValue parameter
+     * has data. Sends a signal as the queue window closes.
+     */
+    public static final int SUB_WINDOW_SIG = 0x8000;
+    /**
+     * < Flag to indicate hostSpec parameter
+     * has data.
+     */
+    public static final int SUB_HOST_SPEC = 0x10000;
+    /**
+     * < Flag to indicate dependCond parameter
+     * has data. Equivalent to bsub -w command line option existence.
+     */
+    public static final int SUB_DEPEND_COND = 0x20000;
+    /**
+     * < Flag to indicate resReq parameter
+     * has data. Equivalent to bsub -R command line option existence.
+     */
+    public static final int SUB_RES_REQ = 0x40000;
+    /**
+     * < Flag to indicate nxf parameter and structure xf have data.
+     */
+    public static final int SUB_OTHER_FILES = 0x80000;
+    /**
+     * < Flag to indicate preExecCmd
+     * parameter has data. Equivalent to bsub -E command line option
+     * existence.
+     */
+    public static final int SUB_PRE_EXEC = 0x100000;
+    /**
+     * < Equivalent to bsub -L command line option existence.
+     */
+    public static final int SUB_LOGIN_SHELL = 0x200000;
+    /**
+     * < Flag to indicate mailUser parameter has data.
+     */
+    public static final int SUB_MAIL_USER = 0x400000;
+    /**
+     * < Flag to indicate newCommand parameter has data. Equivalent to bmod bsub_options existence.
+     */
+    public static final int SUB_MODIFY = 0x800000;
+    /**
+     * < Flag to indicate modify option once.
+     */
+    public static final int SUB_MODIFY_ONCE = 0x1000000;
+    /**
+     * < Flag to indicate ProjectName
+     * parameter has data . Equivalent to bsub -P command line option
+     * existence.
+     */
+    public static final int SUB_PROJECT_NAME = 0x2000000;
+    /**
+     * < Indicates that the job is submitted
+     * as a batch interactive job. When this flag is given, \ref lsb_submit
+     * does not return unless an error occurs during the submission process.
+     * When the job is started, the user can interact with the job's
+     * standard input and output via the terminal. See the -I option
+     * in bsub for the description of a batch interactive job. Unless
+     * the SUB_PTY flag is specified, the job will run without a
+     * pseudo-terminal. Equivalent to bsub -I command line option.
+     */
+    public static final int SUB_INTERACTIVE = 0x4000000;
+    /**
+     * < Requests pseudo-terminal support
+     * for a job submitted with the SUB_INTERACTIVE flag. This flag is
+     * ignored if SUB_INTERACTIVE is not specified. A pseudo-terminal
+     * is required to run some applications (such as: vi). Equivalent to
+     * bsub -Ip command line option.
+     */
+    public static final int SUB_PTY = 0x8000000;
+    /**< Requests pseudo-terminal shell
+     *  mode support for a job submitted with the SUB_INTERACTIVE and
+     *  SUB_PTY flags. This flag is ignored if SUB_INTERACTIVE and SUB_PTY
+     *  are not specified. This flag should be specified for submitting
+     *  interactive shells, or applications which redefine the ctrl-C and
+     *  ctrl-Z keys (such as: jove). Equivalent to bsub -Is
+     *  command line option. */
+    public static final int SUB_PTY_SHELL = 0x10000000;
+
+    /**
+     * < Exception handler for job.
+     */
+    public static final int SUB_EXCEPT = 0x20000000;
+
+    /**
+     * < Specifies time_event.
+     */
+    public static final int SUB_TIME_EVENT = 0x40000000;
+/* the last bit 0x80000000 is reserved for internal use */
+
+    /**
+     * \addtogroup lsb_submit_options2 lsb_submit_options2
+     * define statements used by \ref lsb_submit.
+     */
+
+    /**< Hold the job after it is submitted. The job will be in PSUSP status. Equivalent to bsub -H command line option. */
+    public static final int SUB2_HOLD = 0x01;
+
+    /**
+     * < New cmd for bmod.
+     */
+    public static final int SUB2_MODIFY_CMD = 0x02;
+
+    /**//* Removed access to SUB2_BSUB_BLOCK since it exits the process (including the JVM) with the exit code of the submitted job. -kshakir December 14, 2010
+     * < Submit a job in a synchronous
+     * mode so that submission does not return until the job terminates.
+     * Note once this flag is set, the \ref lsb_submit will never return if
+     * the job is accepted by LSF. Programs that wishes to know the status
+     * of the submission needs to fork, with the child process invoking the
+     * API call in the blocking mode and the parent process wait on the
+     * child process (see wait() for details.
+     */
+    //public static final int SUB2_BSUB_BLOCK = 0x04;
+
+    /**
+     * < Submit from NT.
+     */
+    public static final int SUB2_HOST_NT = 0x08;
+
+    /**
+     * < Submit fom UNIX.
+     */
+    public static final int SUB2_HOST_UX = 0x10;
+
+    /**
+     * < Submit to a chkpntable queue.
+     */
+    public static final int SUB2_QUEUE_CHKPNT = 0x20;
+
+    /**
+     * < Submit to a rerunnable queue.
+     */
+    public static final int SUB2_QUEUE_RERUNNABLE = 0x40;
+
+    /**
+     * < Spool job command.
+     */
+    public static final int SUB2_IN_FILE_SPOOL = 0x80;
+
+    /**
+     * < Inputs the specified file with spooling
+     */
+    public static final int SUB2_JOB_CMD_SPOOL = 0x100;
+
+    /**
+     * < Submits job with priority.
+     */
+    public static final int SUB2_JOB_PRIORITY = 0x200;
+
+    /**
+     * < Job submitted without -n, use queue's default proclimit
+     */
+    public static final int SUB2_USE_DEF_PROCLIMIT = 0x400;
+
+    /**
+     * < bmod -c/-M/-W/-o/-e
+     */
+    public static final int SUB2_MODIFY_RUN_JOB = 0x800;
+
+    /**
+     * < bmod options only to pending jobs
+     */
+    public static final int SUB2_MODIFY_PEND_JOB = 0x1000;
+
+    /**
+     * < Job action warning time. Equivalent to bsub or bmod -wt.
+     */
+    public static final int SUB2_WARNING_TIME_PERIOD = 0x2000;
+
+    /**
+     * < Job action to be taken before a job control action occurs. Equivalent to bsub or bmod -wa.
+     */
+    public static final int SUB2_WARNING_ACTION = 0x4000;
+
+    /**
+     * < Use an advance reservation created with the brsvadd command. Equivalent to bsub -U.
+     */
+    public static final int SUB2_USE_RSV = 0x8000;
+
+    /**
+     * < Windows Terminal Services job
+     */
+    public static final int SUB2_TSJOB = 0x10000;
+
+/* SUB2_LSF2TP is obsolete in Eagle. We keep it here for backward
+*  compatibility */
+
+    /**
+     * < Parameter is deprecated
+     */
+    public static final int SUB2_LSF2TP = 0x20000;
+
+    /**
+     * < Submit into a job group
+     */
+    public static final int SUB2_JOB_GROUP = 0x40000;
+
+    /**
+     * < Submit into a service class
+     */
+    public static final int SUB2_SLA = 0x80000;
+
+    /**
+     * < Submit with -extsched options
+     */
+    public static final int SUB2_EXTSCHED = 0x100000;
+
+    /**
+     * < License Scheduler project
+     */
+    public static final int SUB2_LICENSE_PROJECT = 0x200000;
+
+    /**
+     * < Overwrite the standard output of the job. Equivalent to bsub -oo.
+     */
+    public static final int SUB2_OVERWRITE_OUT_FILE = 0x400000;
+
+    /**
+     * < Overwrites the standard error output of the job. Equivalent to bsub -eo.
+     */
+    public static final int SUB2_OVERWRITE_ERR_FILE = 0x800000;
+
+/* Following are for symphony submission definition.
+*  Note that SYM_GRP is an LSF job, which represents a symphony group.
+ */
+
+    /**
+     * < (symphony) session job
+     */
+    public static final int SUB2_SSM_JOB = 0x1000000;
+
+    /**
+     * < (symphony) symphony job
+     */
+    public static final int SUB2_SYM_JOB = 0x2000000;
+
+    /**
+     * < (symphony) service(LSF) job
+     */
+    public static final int SUB2_SRV_JOB = 0x4000000;
+
+    /**
+     * < (symphony) "group" job
+     */
+    public static final int SUB2_SYM_GRP = 0x8000000;
+
+    /**
+     * < (symphony) symphony job has child symphony job
+     */
+    public static final int SUB2_SYM_JOB_PARENT = 0x10000000;
+
+    /**
+     * < (symphony) symphony job has real time feature
+     */
+    public static final int SUB2_SYM_JOB_REALTIME = 0x20000000;
+
+    /**
+     * < (symphony) symphony job has dummy feature to hold all persistent service jobs.
+     */
+    public static final int SUB2_SYM_JOB_PERSIST_SRV = 0x40000000;
+
+    /**
+     * < Persistent session job
+     */
+    public static final int SUB2_SSM_JOB_PERSIST = 0x80000000;
+
+    /**
+     *  \addtogroup lsb_submit_options3 lsb_submit_options3
+     *  define statements used by \ref lsb_submit.
+     */
+
+    /**
+     * < Application profile name. Equivalent to bsub -app.
+     */
+    public static final int SUB3_APP = 0x01;
+
+    /**
+     * < Job rerunable because of application profile
+     */
+    public static final int SUB3_APP_RERUNNABLE = 0x02;
+
+    /**
+     * < Job modified with absolute priority. Equivalent to bmod -aps.
+     */
+    public static final int SUB3_ABSOLUTE_PRIORITY = 0x04;
+
+    /**
+     * < Submit into a default job group. Equivalent to bsub -g.
+     */
+    public static final int SUB3_DEFAULT_JOBGROUP = 0x08;
+
+    /**
+     * < Run the specified post-execution command on the execution host after the job finishes. Equivalent to bsub -Ep.
+     */
+    public static final int SUB3_POST_EXEC = 0x10;
+    /**
+     * < Pass user shell limits to execution host. Equivalent to bsub -ul.
+     */
+    public static final int SUB3_USER_SHELL_LIMITS = 0x20;
+    /**
+     * < Current working directory specified on the command line with bsub -cwd
+     */
+    public static final int SUB3_CWD = 0x40;
+    /**< Runtime estimate. Equivalent to bsub -We. Use in conjunction with SUB3_RUNTIME_ESTIMATION_ACC and SUB3_RUNTIME_ESTIMATION_PERC. */
+    public static final int SUB3_RUNTIME_ESTIMATION = 0x80;
+
+    /**
+     * < Job is not rerunnable. Equivalent to bsub -rn.
+     */
+    public static final int SUB3_NOT_RERUNNABLE = 0x100;
+
+    /**
+     * < Job level requeue exit values.
+     */
+    public static final int SUB3_JOB_REQUEUE = 0x200;
+    /**
+     * < Initial checkpoint period. Equivalent to bsub -k initial_checkpoint_period.
+     */
+    public static final int SUB3_INIT_CHKPNT_PERIOD = 0x400;
+    /**< Job migration threshold. Equivalent to bsub -mig migration_threshold. */
+    public static final int SUB3_MIG_THRESHOLD = 0x800;
+
+    /**
+     * < Checkpoint dir was set by application profile
+     */
+    public static final int SUB3_APP_CHKPNT_DIR = 0x1000;
+    /**
+     * < Value of BSUB_CHK_RESREQ environment variable, used for select section resource requirement string syntax checking with bsub -R. bsub only checks the resreq syntax.
+     */
+    public static final int SUB3_BSUB_CHK_RESREQ = 0x2000;
+    /**
+     * < Runtime estimate that is the accumulated run time plus the runtime estimate. Equivalent to bmod -We+. Use in conjunction with SUB3_RUNTIME_ESTIMATION.
+     */
+    public static final int SUB3_RUNTIME_ESTIMATION_ACC = 0x4000;
+    /**
+     * < Runtime estimate in percentage of completion. Equivalent to bmod -Wep. Two digits after the decimal point are suported. The highest eight bits of runtimeEstimation in the submit structure are used for the integer; the remaining bits are used for the fraction. Use in conjunction with SUB3_RUNTIME_ESTIMATION.
+     */
+    public static final int SUB3_RUNTIME_ESTIMATION_PERC = 0x8000;
+
+    /**
+     * < Protects the sessions of interactive jobs with SSH encryption. Equivalent to bsub -IS|-ISp|-ISs.
+     */
+    public static final int SUB3_INTERACTIVE_SSH = 0x10000;
+    /**< Protect the sessions of interactive x-window job with SSH encryption. Equivalent to bsub -IX.*/
+    public static final int SUB3_XJOB_SSH = 0x20000;
+
+    /**
+     * < If set the submitted job is auto-resizable
+     */
+    public static final int SUB3_AUTO_RESIZE = 0x40000;
+
+    /**
+     * < If set, the resize notify cmd specified
+     */
+    public static final int SUB3_RESIZE_NOTIFY_CMD = 0x80000;
+
+
+    /**
+     * < Job broker bulk submit
+     */
+    public static final int SUB3_BULK_SUBMIT = 0x100000;
+
+    /**
+     * < tty mode for interactive job
+     */
+    public static final int SUB3_INTERACTIVE_TTY = 0x200000;
+
+    /**
+     * < Job submitted from floating client
+     */
+    public static final int SUB3_FLOATING_CLIENT = 0x400000;
+
+    /**
+     * < ssh X11 forwarding (bsub -XF)
+     */
+    public static final int SUB3_XFJOB = 0x800000;
+
+    /**
+     * < ssh X11 forwarding (bsub -XF) without bsub -I...
+     */
+    public static final int SUB3_XFJOB_EXCLUSIVE = 0x1000000;
+
+    /**
+     * < Job description.
+     */
+    public static final int SUB3_JOB_DESCRIPTION = 0x2000000;
+
+    /**
+     * < Job submitted from floating client
+     */
+    public static final int SUB3_SIMULATION = 0x4000000;
+
+/* Check whether a job is symphony job. These macros should be used by all
+*  components, including ("submit" actually):
+*    - mbatchd: jData->submitReq
+*    - sbatchd: jobCard->jobSpecs
+*    - API: lsb_submit() and lsb_readjobinfo()
+ */
+
+    public static boolean IS_SSM_JOB(int option) {
+        return JNAUtils.toBoolean((option) & SUB2_SSM_JOB);
+    }
+
+    public static boolean IS_SSM_JOB_PERSIST(int option) {
+        return JNAUtils.toBoolean((option) & SUB2_SSM_JOB_PERSIST);
+    }
+
+    public static boolean IS_SYM_JOB(int option) {
+        return JNAUtils.toBoolean((option) & SUB2_SYM_JOB);
+    }
+
+    public static boolean IS_SYM_JOB_PARENT(int option) {
+        return JNAUtils.toBoolean((option) & SUB2_SYM_JOB_PARENT);
+    }
+
+    public static boolean IS_SYM_JOB_REALTIME(int option) {
+        return JNAUtils.toBoolean((option) & SUB2_SYM_JOB_REALTIME);
+    }
+
+    public static boolean IS_SYM_JOB_PERSIST_SRV(int option) {
+        return JNAUtils.toBoolean((option) & SUB2_SYM_JOB_PERSIST_SRV);
+    }
+
+    public static boolean IS_SRV_JOB(int option) {
+        return JNAUtils.toBoolean((option) & SUB2_SRV_JOB);
+    }
+
+    public static boolean IS_SYM_GRP(int option) {
+        return JNAUtils.toBoolean((option) & SUB2_SYM_GRP);
+    }
+
+    public static boolean IS_SYM_JOB_OR_SYM_GRP (int option)  { return (IS_SYM_JOB(option) || IS_SYM_GRP(option)); }
+/* symphony job for which resource usage should be collected */
+    public static boolean IS_REAL_SYM_JOB (int option)  { return (IS_SYM_JOB(option) && !IS_SYM_JOB_PERSIST_SRV(option)); }
+
+    public static boolean IS_WLM_JOB (int option)  { return (IS_SSM_JOB(option) || IS_SYM_JOB(option) || IS_SRV_JOB(option) || IS_SYM_GRP(option)); }
+    public static boolean IS_BATCH_JOB (int option)  { return (!IS_WLM_JOB(option)); }
+/* job for which resource usage should be collected */
+    public static boolean IS_JOB_FOR_ACCT (int option)  { return (IS_REAL_SYM_JOB(option) || IS_BATCH_JOB(option)); }
+
+    public static boolean IS_JOB_FOR_SYM (int option)  { return (IS_SYM_JOB(option) || IS_SRV_JOB(option) || IS_SYM_GRP(option)); }
+
+/* Don't send IS_SYM_JOB/IS_SYM_GRP jobs to scheduler;
+*  neither publish events nor brun the job allowed.
+ */
+    // NOTE: Don't know what this jp struct is.
+    //public static boolean IS_SYM_JOB_OR_GRP (int jp)   { return (   (jp) != null && (jp)->shared != null && (  IS_SYM_JOB((jp)->shared->jobBill.options2) ||IS_SYM_GRP((jp)->shared->jobBill.options2))); }
+
+/* name of the lost and find queue and host */
+    public static final String LOST_AND_FOUND = "lost_and_found";
+
+    public static final int DELETE_NUMBER = -2;
+    public static final int DEL_NUMPRO = LibLsf.INFINIT_INT;
+    public static final int DEFAULT_NUMPRO = LibLsf.INFINIT_INT - 1;
+    /**
+     *  \addtogroup calendar_command  calendar_command
+     *  options  for user calendar commands
+     */
+
+    /**
+     * < Add calenda
+     */
+    public static final int CALADD = 1;
+
+    /**
+     * < Modify calenda
+     */
+    public static final int CALMOD = 2;
+
+    /**
+     * < Delete calenda
+     */
+    public static final int CALDEL = 3;
+
+    /**
+     * < Undelete calenda
+     */
+    public static final int CALUNDEL = 4;
+
+    /**
+     * < Calenda occs
+     */
+    public static final int CALOCCS = 5;
+
+/* for user event commands */
+    public static final int EVEADD = 1;
+    public static final int EVEMOD = 2;
+    public static final int EVEDEL = 3;
+
+    public static final int PLUGIN_REQUEUE = 126;
+    public static final int PLUGIN_EXIT = 125;
+
+    /**
+     * \brief  xFile
+     */
+    public static class xFile extends Structure {
+        public static class ByReference extends xFile implements Structure.ByReference {}
+        public static class ByValue extends xFile implements Structure.ByValue {}
+        public xFile() {}
+        public xFile(Pointer p) { super(p); read(); }
+
+
+        /**
+         * < Pathname at submission host
+         */
+        public String subFn;
+
+        /**
+         * < Pathname at execution host
+         */
+        public String execFn;
+        /**
+         *  \addtogroup defs_lsb_XF_OP defs_lsb_XF_OP
+         *  options  xFile operation
+         */
+
+        /**
+         * < Transfer files from submit peer to  execution peer
+         */
+        public static final int XF_OP_SUB2EXEC = 0x1;
+
+        /**
+         * < Transfer files from execution peer to  submit peer
+         */
+        public static final int XF_OP_EXEC2SUB = 0x2;
+
+        /**
+         * < Transfer files from submit peer to  execution peer with appending mode
+         */
+        public static final int XF_OP_SUB2EXEC_APPEND = 0x4;
+
+        /**
+         * < Transfer files from execution peer to  submit peer with appending mode
+         */
+        public static final int XF_OP_EXEC2SUB_APPEND = 0x8;
+        public static final int XF_OP_URL_SOURCE = 0x10;
+
+        /**
+         * < Defined in \ref defs_lsb_XF_OP
+         */
+        public int options;
+    }
+
+
+
+    /* For NQS */
+    public static final int NQS_ROUTE = 0x1;
+    public static final int NQS_SIG = 0x2;
+    public static final int NQS_SERVER = 0x4;
+
+
+    public static final int MAXNFA = 1024;
+    public static final int MAXTAG = 10;
+
+    public static final int OKP = 1;
+    public static final int NOP = 0;
+
+    public static final int CHR = 1;
+    public static final int ANY = 2;
+    public static final int CCL = 3;
+    public static final int BOL = 4;
+    public static final int EOL = 5;
+    public static final int BOT = 6;
+    public static final int EOT = 7;
+    public static final int BOW = 8;
+    public static final int EOW = 9;
+    public static final int REF = 10;
+    public static final int CLO = 11;
+
+    public static final int END = 0;
+
+    /**
+     *  The following defines are not meant to be changeable.
+     *  They are for readability only.
+     */
+
+    public static final int MAXCHR = 128;
+    public static final int CHRBIT = 8;
+    public static final int BITBLK = MAXCHR / CHRBIT;
+    public static final int BLKIND = 0xAA;
+    public static final int BITIND = 0x7;
+
+    public static final int ASCIIB = 0x7F;
+
+    /**
+     *  byte classification table for word boundary operators BOW
+     *  and EOW. the reason for not using ctype macros is that we can
+     *  let the user add into our own table. see re_modw. This table
+     *  is not in the bitset form, since we may wish to extend it in the
+     *  future for other byte classifications.
+     *
+     *   TRUE for 0-9 A-Z a-z _
+     */
+
+    public static final byte[] chrtyp = {
+            0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+            0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+            0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+            0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+            0, 0, 0, 0, 0, 0, 0, 0, 1, 1,
+            1, 1, 1, 1, 1, 1, 1, 1, 0, 0,
+            0, 0, 0, 0, 0, 1, 1, 1, 1, 1,
+            1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+            1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+            1, 0, 0, 0, 0, 1, 0, 1, 1, 1,
+            1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+            1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+            1, 1, 1, 0, 0, 0, 0, 0
+    };
+
+    public static int inascii(int x) {
+        return (0x7F & (x));
+    }
+
+    public static int iswordc(int x) {
+        return chrtyp[inascii(x)];
+    }
+
+/*
+*  skip values for CLO XXX to skip past the closure
+ */
+
+
+/* [CLO] ANY END ... */
+    public static final int ANYSKIP = 2;
+
+/* [CLO] CHR chr END ... */
+    public static final int CHRSKIP = 3;
+
+/* [CLO] CCL 16bytes END ... */
+    public static final int CCLSKIP = 18;
+
+/*  In LSF7.0.6, we introduce submit_ext structure to support
+*   extended fields for furture added submit options.
+*   Each new options should have a unique key defined here.
+*   The new defined key should be bigger than 1000.
+*   Keys below 1000 are used for internal use.
+ */
+
+/* submit_ext test */
+    public static final int JDATA_EXT_TEST = 1001;
+
+/* LSF simulator: simReq */
+    public static final int JDATA_EXT_SIMREQ = 1002;
+
+/* structure for lsb_submit() call */
+
+    /**
+     * \extend submit data structure
+     */
+    public static class submit_ext extends Structure {
+        public static class ByReference extends submit_ext implements Structure.ByReference {}
+        public static class ByValue extends submit_ext implements Structure.ByValue {}
+        public submit_ext() {}
+        public submit_ext(Pointer p) { super(p); read(); }
+
+
+        /**
+         * < number of key value pairs.
+         */
+        public int num;
+
+        /**
+         * < Array of keys of the extended fields.
+         */
+        public Pointer keys;
+
+        /**
+         * < Array of values of the extended fields
+         */
+        public Pointer values;
+    }
+
+
+
+
+    /**
+     * \brief  submit request structure.
+     */
+    public static class submit extends Structure {
+        public static class ByReference extends submit implements Structure.ByReference {}
+        public static class ByValue extends submit implements Structure.ByValue {}
+        public submit() {}
+        public submit(Pointer p) { super(p); read(); }
+
+
+        /**
+         * <  <lsf/lsbatch.h> defines the flags in \ref lsb_submit_options constructed from bits. These flags correspond to some of the options of the bsub command line. Use the bitwise OR to set more than one flag.
+         */
+        public int options;
+
+
+        /**
+         * < Extended bitwise inclusive OR of some of the flags in \ref lsb_submit_options2.
+         */
+        public int options2;
+
+
+        /**
+         * < The job name. If jobName is null, command is used as the job name.
+         */
+        public String jobName;
+
+        /**
+         * < Submit the job to this queue. If queue is null, submit the job to a system default queue.
+         */
+        public String queue;
+
+        /**
+         * < The number of invoker specified candidate hosts for running the job. If numAskedHosts is 0, all qualified hosts will be considered.
+         */
+        public int numAskedHosts;
+
+        /**
+         * < The array of names of invoker specified candidate hosts.  The number of hosts is given by numAskedHosts.
+         */
+        public Pointer askedHosts;
+
+        /**
+         * < The resource requirements of the job. If resReq is null, the batch system will try to obtain resource requirements for command from the remote task lists (see \ref ls_task ). If the task does not appear in the remote task lists, then the default resource requirement is to run on host() of the same type.
+         */
+        public String resReq;
+
+        /**
+         * < Limits on the consumption of system resources by all processes belonging to this job. See getrlimit() for details. If an element of the array is -1, there is no limit for that resource. For the constants used to index the array, see \ref lsb_queueinfo .
+         */
+        public int[] rLimits = new int[LibLsf.LSF_RLIM_NLIMITS];
+
+        /**
+         * < Specify the host model to use for scaling rLimits[LSF_RLIMIT_CPU] and rLimits[LSF_RLIMIT_RUN]. (See \ref lsb_queueinfo). If hostSpec is null, the local host is assumed.
+         */
+        public String hostSpec;
+
+        /**
+         * <  The initial number of processors needed by a (parallel) job. The default is 1.
+         */
+        public int numProcessors;
+
+        /**
+         * < The job dependency condition.
+         */
+        public String dependCond;
+
+        /**
+         * <  Time event string
+         */
+        public String timeEvent;
+
+        /**
+         * <  Dispatch the job on or after beginTime, where beginTime is the number of seconds since 00:00:00 GMT, Jan. 1, 1970 (See time(), ctime()). If beginTime is 0, start the job as soon as possible.
+         */
+        public NativeLong beginTime;
+
+        /**
+         * <  The job termination deadline. If the job is still running at termTime, it will be sent a USR2 signal. If the job does not terminate within 10 minutes after being sent this signal, it will be ended. termTime has the same representation as beginTime. If termTime is 0, allow the job to run until it reaches a resource limit.
+         */
+        public NativeLong termTime;
+
+        /**
+         * < Applies to jobs submitted to a queue that has a run window (See \ref lsb_queueinfo). Send signal sigValue to the job 10 minutes before the run window is going to close. This allows the job to clean up or checkpoint itself, if desired. If the job does not terminate 10 minutes after being sent this signal, it will be suspended.
+         */
+        public int sigValue;
+
+        /**
+         * < The path name of the job's standard input file. If inFile is null, use /dev/null as the default.
+         */
+        public String inFile;
+
+        /**
+         * < The path name of the job's standard output file. If outFile is null, the job's output will be mailed to the submitter
+         */
+        public String outFile;
+
+        /**
+         * < The path name of the job's standard error output file. If errFile is null, the standard error output will be merged with the standard output of the job.
+         */
+        public String errFile;
+
+        /**
+         * < When submitting a job, the command line of the job.   When modifying a job, a mandatory parameter that  should be set to jobId in string format.
+         */
+        public String command;
+
+        /**
+         * < New command line for bmod.
+         */
+        public String newCommand;
+
+        /**
+         * < The job is checkpointable with a period of chkpntPeriod seconds. The value 0 disables periodic checkpointing.
+         */
+        public NativeLong chkpntPeriod;
+
+        /**
+         * < The directory where the chk directory for this job checkpoint files will be created. When a job is checkpointed, its checkpoint files are placed in chkpntDir/chk. chkpntDir can be a relative or absolute path name.
+         */
+        public String chkpntDir;
+
+        /**
+         * < The number of files to transfer.
+         */
+        public int nxf;
+
+        /**
+         * < The array of file transfer specifications. (The xFile structure is defined in <lsf/lsbatch.h>.)
+         */
+        public Pointer /* xFile.ByReference */ xf;
+
+        /**
+         * < The job pre-execution command.
+         */
+        public String preExecCmd;
+
+        /**
+         * < The user that results are mailed to.
+         */
+        public String mailUser;
+
+        /**
+         * < Delete options in options field.
+         */
+        public int delOptions;
+
+        /**
+         * < Extended delete options in options2 field.
+         */
+        public int delOptions2;
+
+        /**
+         * < The name of the project the job will be charged to.
+         */
+        public String projectName;
+
+        /**
+         * < Maximum number of processors required to run the job.
+         */
+        public int maxNumProcessors;
+
+        /**
+         * < Specified login shell used to initialize the execution environment for the job (see the -L option of bsub).
+         */
+        public String loginShell;
+
+        /**
+         * < The name of the LSF user group (see lsb.users) to which the job will belong. (see the -G option of bsub)
+         */
+        public String userGroup;
+
+        /**
+         * < Passes the exception handlers to mbatchd during a job. (see the -X option of bsub). Specifies execption handlers that tell the system how to respond to an exceptional condition for a job. An action is performed when any one of the following exceptions is detected: - \b missched - A job has not been scheduled within the time event specified in the -T option. - \b overrun - A job did not finish in its maximum time (maxtime). - \b underrun - A job finished before it reaches its [...]
+         */
+        public String exceptList;
+
+
+        /**
+         * < User priority for fairshare scheduling.
+         */
+        public int userPriority;
+
+        /**
+         * < Reservation ID for advance reservation.
+         */
+        public String rsvId;
+
+        /**
+         * < Job group under which the job runs.
+         */
+        public String jobGroup;
+
+        /**
+         * < SLA under which the job runs.
+         */
+        public String sla;
+
+        /**
+         * < External scheduler options.
+         */
+        public String extsched;
+
+        /**
+         * < Warning time period in seconds, -1 if unspecified.
+         */
+        public int warningTimePeriod;
+
+        /**
+         * < Warning action, SIGNAL | CHKPNT | command, null if unspecified.
+         */
+        public String warningAction;
+
+        /**
+         * < License Scheduler project name.
+         */
+        public String licenseProject;
+
+        /**
+         * < Extended bitwise inclusive OR of options flags in \ref lsb_submit_options3.
+         */
+        public int options3;
+
+        /**
+         * < Extended delete options in options3 field.
+         */
+        public int delOptions3;
+
+        /**
+         * < Application profile under which the job runs.
+         */
+        public String app;
+
+        /**
+         * < -1 if no -jsdl and -jsdl_strict options. - 0 -jsdl_strict option - 1 -jsdl option
+         */
+        public int jsdlFlag;
+
+        /**
+         * < JSDL filename
+         */
+        public String jsdlDoc;
+
+        /**
+         * < ARM correlator
+         */
+        public Pointer correlator;
+
+        /**
+         * <  Absolute priority scheduling string set by administrators to denote static system APS value or ADMIN factor APS value. This field is ignored by \ref lsb_submit.
+         */
+        public String apsString;
+
+        /**
+         * < Post-execution commands specified by -Ep option of bsub and bmod.
+         */
+        public String postExecCmd;
+
+        /**
+         * < Current working directory specified by -cwd option of bsub and bmod.
+         */
+        public String cwd;
+
+        /**
+         * < Runtime estimate specified by -We option of bsub and bmod.
+         */
+        public int runtimeEstimation;
+
+        /**
+         * < Job-level requeue exit values specified by -Q option of bsub and bmod.
+         */
+        public String requeueEValues;
+
+        /**
+         * < Initial checkpoint period specified by -k option of bsub and bmod.
+         */
+        public int initChkpntPeriod;
+
+        /**
+         * < Job migration threshold specified by -mig option of bsub and bmod.
+         */
+        public int migThreshold;
+
+        /**
+         * < Job resize notification command to be invoked on the first execution host when a resize request has been satisfied.
+         */
+        public String notifyCmd;
+
+        /**
+         * < Job description.
+         */
+        public String jobDescription;
+/* #if defined(LSF_SIMULATOR)
+
+/**< simulation related options */
+        /*public String simReq;*/
+        /* #endif */
+
+        /**
+         * < For new options in future
+         */
+        public submit_ext.ByReference submitExt;
+    }
+
+
+
+
+    /**
+     * \brief submit reply.
+     */
+    public static class submitReply extends Structure {
+        public static class ByReference extends submitReply implements Structure.ByReference {}
+        public static class ByValue extends submitReply implements Structure.ByValue {}
+        public submitReply() {}
+        public submitReply(Pointer p) { super(p); read(); }
+
+
+        /**
+         * < The queue the job was submitted to.
+         */
+        public String queue;
+
+        /**
+         * < DependCond contained badJobId but badJobId does not exist in the system.
+         */
+        public long badJobId;
+
+        /**
+         * < DependCond contained badJobName but badJobName does not exist in the system. If the environment variable BSUB_CHK_RESREQ is set, the value of lsberrno is either LSBE_RESREQ_OK or LSBE_RESREQ_ERR, depending on the result of resource requirement string checking. The badJobName field contains the detailed error message.
+         */
+        public String badJobName;
+
+        /**< If lsberrno is LSBE_BAD_HOST,
+         *  (**askedHosts)[badReqIndx] is not a host known to the system.
+         *  If lsberrno is LSBE_QUEUE_HOST, (**askedHosts)[badReqIndx]
+         *  is not a host used by the specified queue. If lsberrno is
+         *  LSBE_OVER_LIMIT, (*rLimits)[badReqIndx] exceeds the queue's
+         *  limit for the resource. */
+        public int badReqIndx;
+    }
+
+
+
+    /**
+     * \brief  submit migration request.
+     */
+    public static class submig extends Structure {
+        public static class ByReference extends submig implements Structure.ByReference {}
+        public static class ByValue extends submig implements Structure.ByValue {}
+        public submig() {}
+        public submig(Pointer p) { super(p); read(); }
+
+
+        /**
+         * < The job ID of the job to be migrated.
+         */
+        public long jobId;
+
+        /**
+         * < Please refer to \ref lsb_submit_options.
+         */
+        public int options;
+
+        /**
+         * < The number of hosts supplied as candidates  for migration.
+         */
+        public int numAskedHosts;
+
+        /**
+         * < An array of pointers to the names of candidate hosts for migration.
+         */
+        public Pointer askedHosts;
+    }
+
+
+
+/* structure for lsb_addjgrp() call */
+
+    public static class jgrpAdd extends Structure {
+        public static class ByReference extends jgrpAdd implements Structure.ByReference {}
+        public static class ByValue extends jgrpAdd implements Structure.ByValue {}
+        public jgrpAdd() {}
+        public jgrpAdd(Pointer p) { super(p); read(); }
+
+        public String groupSpec;
+        public String timeEvent;
+        public String depCond;
+        public String sla;
+        public int maxJLimit;
+    }
+
+
+
+/* structure for lsb_modjgrp() call */
+
+    public static class jgrpMod extends Structure {
+        public static class ByReference extends jgrpMod implements Structure.ByReference {}
+        public static class ByValue extends jgrpMod implements Structure.ByValue {}
+        public jgrpMod() {}
+        public jgrpMod(Pointer p) { super(p); read(); }
+
+        public String destSpec;
+        public jgrpAdd jgrp;
+    }
+
+
+
+/* structure for lsb_addjgrp() and lsb_modjgrp() call reply */
+
+    public static class jgrpReply extends Structure {
+        public static class ByReference extends jgrpReply implements Structure.ByReference {}
+        public static class ByValue extends jgrpReply implements Structure.ByValue {}
+        public jgrpReply() {}
+        public jgrpReply(Pointer p) { super(p); read(); }
+
+        public String badJgrpName;
+        public int num;
+        public Pointer delJgrpList;
+    }
+
+
+
+    /**
+     * \brief Signal a group of jobs.
+     */
+    public static class signalBulkJobs extends Structure {
+        public static class ByReference extends signalBulkJobs implements Structure.ByReference {}
+        public static class ByValue extends signalBulkJobs implements Structure.ByValue {}
+        public signalBulkJobs() {}
+        public signalBulkJobs(Pointer p) { super(p); read(); }
+
+
+        /**
+         * < Signal type
+         */
+        public int signal;
+
+        /**
+         * < Number of jobs
+         */
+        public int njobs;
+
+        /**
+         * < Jobids list
+         */
+        public Pointer jobs;
+
+        /**
+         * < Flags
+         */
+        public int flags;
+    }
+
+
+
+/* structure for lsb_ctrljgrp() call */
+
+    public static class jgrpCtrl extends Structure {
+        public static class ByReference extends jgrpCtrl implements Structure.ByReference {}
+        public static class ByValue extends jgrpCtrl implements Structure.ByValue {}
+        public jgrpCtrl() {}
+        public jgrpCtrl(Pointer p) { super(p); read(); }
+
+        public String groupSpec;
+        public String userSpec;
+        public int options;
+
+/* JGRP_RELEASE, JGRP_HOLD, JGRP_DEL */
+        public int ctrlOp;
+    }
+
+
+
+
+/* Indicate no change in chkpnt period for lsb_chkpntjob() */
+    public static final int LSB_CHKPERIOD_NOCHNG = -1;
+
+    /**
+     *  \addtogroup chkpnt_job_option  chkpnt_job_option
+     *  checkpoint job options()
+     */
+
+    /**
+     * < Kill process if successfully chkpnted
+     */
+    public static final int LSB_CHKPNT_KILL = 0x1;
+
+    /**
+     * < Force chkpnt even if non-chkpntable conditions exist.
+     */
+    public static final int LSB_CHKPNT_FORCE = 0x2;
+
+    /**
+     * < Copy all regular files in use by the  checkpointed process to the checkpoint directory.
+     */
+    public static final int LSB_CHKPNT_COPY = 0x3;
+
+    /**
+     * < Chkpnt for the purpose of migration
+     */
+    public static final int LSB_CHKPNT_MIG = 0x4;
+
+    /**
+     * < Stop  process if successfully chkpnted
+     */
+    public static final int LSB_CHKPNT_STOP = 0x8;
+
+    /**
+     *  \addtogroup kill_requeue  kill_requeue
+     *  kill and requeue a job options()
+     */
+
+    /**
+     * < Kill then re-queue a job
+     */
+    public static final int LSB_KILL_REQUEUE = 0x10;
+
+/* options for lsb_openjobinfo() */
+    /**
+     *  \addtogroup defs_lsb_openjobinfo  defs_lsb_openjobinfo
+     *  Information options about job.
+     */
+
+    /**
+     * < Reserved user name
+     */
+    public static final String ALL_USERS = "all";
+    /**
+     * \defgroup defs_lsb_openjobinfo_a defs_lsb_openjobinfo_a
+     * defs_lsb_openjobinfo_a is part of defs_lsb_openjobinfo
+     */
+    public static final int ALL_JOB = 0x0001;
+    /**
+     * < Information about all jobs, including unfinished jobs (pending, running or suspended) and recently finished jobs. LSF remembers jobs finished within the preceding period. This period is set by the parameter CLEAN_PERIOD in the lsb.params file. The default is 3600 seconds (1 hour). (See lsb.params). The command line equivalent is bjobs -a./
+     * <p/>
+     * /**< Information about recently finished jobs.
+     */
+    public static final int DONE_JOB = 0x0002;
+
+    /**
+     * < Information about pending jobs.
+     */
+    public static final int PEND_JOB = 0x0004;
+
+    /**
+     * < Information about suspended jobs.
+     */
+    public static final int SUSP_JOB = 0x0008;
+
+    /**
+     * < Information about all unfinished jobs.
+     */
+    public static final int CUR_JOB = 0x0010;
+
+    /**
+     * < Information about the last submitted job.
+     */
+    public static final int LAST_JOB = 0x0020;
+
+    /**
+     * < Information about all running jobs
+     */
+    public static final int RUN_JOB = 0x0040;
+
+    /**
+     * < Information about JobId only.
+     */
+    public static final int JOBID_ONLY = 0x0080;
+
+    /**
+     * < Internal use only.
+     */
+    public static final int HOST_NAME = 0x0100;
+
+    /**
+     * < Exclude pending jobs.
+     */
+    public static final int NO_PEND_REASONS = 0x0200;
+
+    /**
+     * < Return group info structures
+     */
+    public static final int JGRP_INFO = 0x0400;
+
+    /**
+     * < Recursively search job group tree
+     */
+    public static final int JGRP_RECURSIVE = 0x0800;
+
+    /**
+     * < Return job array info structures
+     */
+    public static final int JGRP_ARRAY_INFO = 0x1000;
+
+    /**
+     * < All jobs in the core
+     */
+    public static final int JOBID_ONLY_ALL = 0x02000;
+
+    /**
+     * < All zombie jobs
+     */
+    public static final int ZOMBIE_JOB = 0x04000;
+
+    /**
+     * < Display remote jobs by their submission jobid.
+     */
+    public static final int TRANSPARENT_MC = 0x08000;
+
+    /**
+     * < Exceptional jobs
+     */
+    public static final int EXCEPT_JOB = 0x10000;
+
+    /**
+     * < Display for murex jobs
+     */
+    public static final int MUREX_JOB = 0x20000;
+
+
+    /**
+     * < To symphony UA
+     */
+    public static final int TO_SYM_UA = 0x40000;
+
+    /**
+     * < Only show top-level symphony job
+     */
+    public static final int SYM_TOP_LEVEL_ONLY = 0x80000;
+
+    /**
+     * < For internal use only
+     */
+    public static final int JGRP_NAME = 0x100000;
+
+    /**
+     * < Condensed host group
+     */
+    public static final int COND_HOSTNAME = 0x200000;
+
+    /**
+     * < Called from command, for internal use only
+     */
+    public static final int FROM_BJOBSCMD = 0x400000;
+
+    /**
+     * < -l in command parameter, for internal use only
+     */
+    public static final int WITH_LOPTION = 0x800000;
+
+    /**
+     * < Jobs submitted to aps queue
+     */
+    public static final int APS_JOB = 0x1000000;
+
+    /**
+     * < Information about user group.
+     */
+    public static final int UGRP_INFO = 0x2000000;
+    /** RFC#1531: -G option support*/
+
+    /**
+     * < -WL
+     */
+    public static final int TIME_LEFT = 0x4000000;
+    /**
+     * < Estimated time remaining based on the runtime estimate or runlimit.
+     */
+
+/* -WF*/
+    public static final int FINISH_TIME = 0x8000000;
+    /**
+     * < Estimated finish time based on the runtime estimate or runlimit.
+     */
+
+/* -WP*/
+    public static final int COM_PERCENTAGE = 0x10000000;
+    /**
+     * < Estimated completion percentage based on the runtime estimate or runlimit. If options is 0, default to CUR_JOB.
+     */
+
+/* -ss option */
+    public static final int SSCHED_JOB = 0x20000000;
+
+/* -G option */
+    public static final int KILL_JGRP_RECURSIVE = 0x40000000;
+
+    /**
+     *  \addtogroup group_nodetypes group_nodetypes
+     *  define statements group node types.
+     */
+
+    /**
+     * <  Job
+     */
+    public static final int JGRP_NODE_JOB = 1;
+
+    /**
+     * <  Group
+     */
+    public static final int JGRP_NODE_GROUP = 2;
+
+    /**
+     * <  Array
+     */
+    public static final int JGRP_NODE_ARRAY = 3;
+
+    /**
+     * <  SLA
+     */
+    public static final int JGRP_NODE_SLA = 4;
+
+/* jobId macros */
+    public static final long LSB_MAX_ARRAY_JOBID = 0x0FFFFFFFFL;
+    public static final long LSB_MAX_ARRAY_IDX = 0x07FFFFFFFL;
+    public static final int LSB_MAX_SEDJOB_RUNID = (0x0F);
+    public static long LSB_JOBID (int array_jobId, int array_idx)    { return (((long)array_idx << 32) | array_jobId); }
+    public static int LSB_ARRAY_IDX (long jobId)   { return (((jobId) == -1) ? (0) : (int)(((long)jobId >> 32)  & LSB_MAX_ARRAY_IDX)); }
+    public static int LSB_ARRAY_JOBID (long jobId)  { return (((jobId) == -1) ? (-1) : (int)(jobId)); }
+    //public static int LSB_ARRAY_JOBID (long jobId)  { return (((jobId) == -1) ? (-1) : (int)(jobId & LSB_MAX_ARRAY_JOBID)); }
+
+/* Status of a job group */
+
+    public static final int JGRP_INACTIVE = 0;
+    public static final int JGRP_ACTIVE = 1;
+    public static final int JGRP_UNDEFINED = -1;
+
+    /**
+     *  \addtogroup jobgroup_controltypes jobgroup_controltypes
+     *  define statements job group control types.
+     */
+
+
+    /**
+     * < bgrelease
+     */
+    public static final int JGRP_RELEASE = 1;
+
+    /**
+     * < bghold
+     */
+    public static final int JGRP_HOLD = 2;
+
+    /**
+     * < bgdel
+     */
+    public static final int JGRP_DEL = 3;
+
+    /**
+     *  \addtogroup jobgroup_counterIndex jobgroup_counterIndex
+     *   Following can be used to index  into 'counters' array.
+     */
+
+    /**
+     * < Total jobs in the array
+     */
+    public static final int JGRP_COUNT_NJOBS = 0;
+
+    /**
+     * < Number of pending jobs in the array
+     */
+    public static final int JGRP_COUNT_PEND = 1;
+
+    /**
+     * < Number of held jobs in the array
+     */
+    public static final int JGRP_COUNT_NPSUSP = 2;
+
+    /**
+     * < Number of running jobs in the array
+     */
+    public static final int JGRP_COUNT_NRUN = 3;
+
+    /**
+     * < Number of jobs suspended by the system in the array
+     */
+    public static final int JGRP_COUNT_NSSUSP = 4;
+
+    /**
+     * < Number of jobs suspended by the user in the array
+     */
+    public static final int JGRP_COUNT_NUSUSP = 5;
+
+    /**
+     * < Number of exited jobs in the array
+     */
+    public static final int JGRP_COUNT_NEXIT = 6;
+
+    /**
+     * < Number of successfully completed jobs
+     */
+    public static final int JGRP_COUNT_NDONE = 7;
+
+    /**
+     * < Total slots in the array
+     */
+    public static final int JGRP_COUNT_NJOBS_SLOTS = 8;
+
+    /**
+     * < Number of pending slots in the array
+     */
+    public static final int JGRP_COUNT_PEND_SLOTS = 9;
+
+    /**
+     * < Number of running slots in the array
+     */
+    public static final int JGRP_COUNT_RUN_SLOTS = 10;
+
+    /**
+     * < Number of slots suspended by the system in the array
+     */
+    public static final int JGRP_COUNT_SSUSP_SLOTS = 11;
+
+    /**
+     * < Number of slots suspended by the user in the array
+     */
+    public static final int JGRP_COUNT_USUSP_SLOTS = 12;
+
+    /**
+     * < Number of reserverd slots in the array
+     */
+    public static final int JGRP_COUNT_RESV_SLOTS = 13;
+
+/* job group modification types */
+    public static final int JGRP_MOD_LIMIT = 0x1;
+
+/*the number of counters of job group
+* based on job level
+*/
+    public static final int NUM_JGRP_JOB_COUNTERS = 8;
+/* the number of all counters of job group,
+* including job level and slot level
+*/
+/* {njobs, npend, npsusp, nrun, nssusp nususp, nexit, ndone} */
+    public static final int NUM_JGRP_COUNTERS = 14;
+
+/* job group is created explicitly */
+    public static final int JGRP_CREATE_EXP = 0x01;
+
+/* job group is created implicitly */
+    public static final int JGRP_CREATE_IMP = 0x02;
+/* The LSF job group.
+ */
+
+    public static class jgrp extends Structure {
+        public static class ByReference extends jgrp implements Structure.ByReference {}
+        public static class ByValue extends jgrp implements Structure.ByValue {}
+        public jgrp() {}
+        public jgrp(Pointer p) { super(p); read(); }
+
+        public String name;
+        public String path;
+        public String user;
+        public String sla;
+        public int[] counters = new int[NUM_JGRP_COUNTERS];
+        public int maxJLimit;
+    }
+
+
+
+/* Structure for lsb_setjobattr() call */
+
+    public static class jobAttrInfoEnt extends Structure {
+        public static class ByReference extends jobAttrInfoEnt implements Structure.ByReference {}
+        public static class ByValue extends jobAttrInfoEnt implements Structure.ByValue {}
+        public jobAttrInfoEnt() {}
+        public jobAttrInfoEnt(Pointer p) { super(p); read(); }
+
+
+/* id of the job */
+        public long jobId;
+
+/* port number of the job */
+        public short port;
+
+/* first executing host of the job */
+        public byte[] hostname = new byte[LibLsf.MAXHOSTNAMELEN];
+    }
+
+
+
+    /**
+     * \brief  job attribute setting log.
+     */
+    public static class jobAttrSetLog extends Structure {
+        public static class ByReference extends jobAttrSetLog implements Structure.ByReference {}
+        public static class ByValue extends jobAttrSetLog implements Structure.ByValue {}
+        public jobAttrSetLog() {}
+        public jobAttrSetLog(Pointer p) { super(p); read(); }
+
+
+        /**
+         * < The unique ID for the job
+         */
+        public int jobId;
+
+        /**
+         * < Job array index; must be 0 in JOB_NEW
+         */
+        public int idx;
+
+        /**
+         * < The user who requested the action
+         */
+        public int uid;
+
+        /**
+         * < Job attributes
+         */
+        public int port;
+
+        /**
+         * < Name of the host
+         */
+        public String hostname;
+    }
+
+
+
+    /**
+     * \brief  job information head.
+     */
+    public static class jobInfoHead extends Structure {
+        public static class ByReference extends jobInfoHead implements Structure.ByReference {}
+        public static class ByValue extends jobInfoHead implements Structure.ByValue {}
+        public jobInfoHead() {}
+        public jobInfoHead(Pointer p) { super(p); read(); }
+
+
+        /**
+         * < The number of jobs in the connection
+         */
+        public int numJobs;
+
+        /**
+         * < An array of job identification numbers in the conection
+         */
+        public NativeLongByReference jobIds;
+
+        /**
+         * < The number of hosts in the connection
+         */
+        public int numHosts;
+
+        /**
+         * < An array of host names in the connection
+         */
+        public Pointer hostNames;
+
+        /**
+         * < The number of clusters in the connection
+         */
+        public int numClusters;
+
+        /**
+         * < An array of cluster names in the connection
+         */
+        public Pointer clusterNames;
+
+        /**
+         * < The number of remoteHosts in the connection
+         */
+        public IntByReference numRemoteHosts;
+
+        /**
+         * < An array of remoteHost names in the connection
+         */
+        public PointerByReference remoteHosts;
+    }
+
+
+
+    /**
+     * \brief job Information head extent
+     */
+    public static class jobInfoHeadExt extends Structure {
+        public static class ByReference extends jobInfoHeadExt implements Structure.ByReference {}
+        public static class ByValue extends jobInfoHeadExt implements Structure.ByValue {}
+        public jobInfoHeadExt() {}
+        public jobInfoHeadExt(Pointer p) { super(p); read(); }
+
+
+        /**
+         * <  Job Information header
+         */
+        public jobInfoHead.ByReference jobInfoHead;
+
+        /**
+         * <  Group Information returned
+         */
+        public Pointer groupInfo;
+    }
+
+
+
+    /**
+     * \brief structure reserveItem
+     */
+    public static class reserveItem extends Structure {
+        public static class ByReference extends reserveItem implements Structure.ByReference {}
+        public static class ByValue extends reserveItem implements Structure.ByValue {}
+        public reserveItem() {}
+        public reserveItem(Pointer p) { super(p); read(); }
+
+
+        /**
+         * < Name of the resource to reserve.
+         */
+        public String resName;
+
+        /**
+         * < The number of hosts to reserve this resource.
+         */
+        public int nHost;
+
+        /**
+         * < Amount of reservation is made on each host. Some hosts may reserve 0.
+         */
+        public FloatByReference value;
+
+        /**
+         * < Flag of shared or host-base resource
+         */
+        public int shared;
+    }
+
+
+
+    /**
+     * \brief  job information entry.
+     */
+    public static class jobInfoEnt extends Structure {
+        public static class ByReference extends jobInfoEnt implements Structure.ByReference {}
+        public static class ByValue extends jobInfoEnt implements Structure.ByValue {}
+        public jobInfoEnt() {}
+        public jobInfoEnt(Pointer p) { super(p); read(); }
+
+
+        /**
+         * < The job ID that the LSF system assigned to the job.
+         */
+        public long jobId;
+
+        /**
+         * < The name of the user who submitted the job.
+         */
+        public String user;
+
+        /**
+         * < The current status of the job.Possible values areshown in job_states
+         */
+        public int status;
+
+        /**
+         * < Pending or suspending reasons of the job
+         */
+        public IntByReference reasonTb;
+
+        /**
+         * < Length of reasonTb[]
+         */
+        public int numReasons;
+
+        /**
+         * < The reason a job is pending or suspended.
+         */
+        public int reasons;
+
+        /**
+         * < The reason a job is pending or suspended. If status is JOB_STAT_PEND, the values of reasons and subreasons are explained by \ref lsb_pendreason. If status is JOB_STAT_PSUSP, the values of reasons and subreasons are explained by \ref lsb_suspreason.   When reasons is PEND_HOST_LOAD or SUSP_LOAD_REASON,  subreasons indicates the load indices that are out of bounds. If reasons is PEND_HOST_LOAD, subreasons is the same as busySched in the hostInfoEnt structure; if reasons is SUS [...]
+         */
+        public int subreasons;
+
+        /**
+         * < The job process ID.
+         */
+        public int jobPid;
+
+        /**
+         * < The time the job was submitted, in seconds since 00:00:00 GMT, Jan. 1, 1970.
+         */
+        public NativeLong submitTime;
+
+        /**
+         * < Time when job slots are reserved
+         */
+        public NativeLong reserveTime;
+
+        /**
+         * < The time that the job started running, if it has been dispatched.
+         */
+        public NativeLong startTime;
+
+        /**
+         * < Job's predicted start time
+         */
+        public NativeLong predictedStartTime;
+
+        /**
+         * < The termination time of the job, if it has completed.
+         */
+        public NativeLong endTime;
+
+        /**
+         * < Last time event
+         */
+        public NativeLong lastEvent;
+
+        /**
+         * < Next time event
+         */
+        public NativeLong nextEvent;
+
+        /**
+         * < Duration time (minutes)
+         */
+        public int duration;
+
+        /**
+         * < CPU time consumed by the job
+         */
+        public float cpuTime;
+
+        /**
+         * < The file creation mask when the job was submitted.
+         */
+        public int umask;
+
+        /**
+         * < The current working directory when the job was submitted.
+         */
+        public String cwd;
+
+        /**
+         * < Home directory on submission host.
+         */
+        public String subHomeDir;
+
+        /**
+         * < The name of the host from which the job was  submitted.
+         */
+        public String fromHost;
+
+        /**
+         * < The array of names of hosts on which the job executes.
+         */
+        public Pointer exHosts;
+
+        /**
+         * < The number of hosts on which the job executes.
+         */
+        public int numExHosts;
+
+        /**
+         * < The CPU factor for normalizing CPU and wall clock time limits.
+         */
+        public float cpuFactor;
+
+        /**
+         * < The number of load indices in the loadSched and loadStop arrays.
+         */
+        public int nIdx;
+
+        /**
+         * < The values in the loadSched array specify the thresholds for the corresponding load indices. Only if the current values of all specified load indices of a host are within (below or above,  depending on the meaning of the load index) their corresponding thresholds may the suspended job be resumed on this host.  For an explanation of the entries in the loadSched, see \ref lsb_hostinfo.
+         */
+        public FloatByReference loadSched;
+
+        /**
+         * < The values in the loadStop array specify the thresholds for job suspension; if any of the current load index values of the host crosses its threshold, the job will be suspended.  For an explanation of the entries in the loadStop, see \ref lsb_hostinfo.
+         */
+        public FloatByReference loadStop;
+
+        /**
+         * < Structure for \ref lsb_submit call.
+         */
+        public submit submit;
+
+        /**
+         * < Job exit status.
+         */
+        public int exitStatus;
+
+        /**
+         * < Mapped UNIX user ID on the execution host.
+         */
+        public int execUid;
+
+        /**
+         * < Home directory for the job on the execution host.
+         */
+        public String execHome;
+
+        /**
+         * < Current working directory for the job on the execution host.
+         */
+        public String execCwd;
+
+        /**
+         * < Mapped user name on the execution host.
+         */
+        public String execUsername;
+
+        /**
+         * < Time of the last job resource usage update.
+         */
+        public NativeLong jRusageUpdateTime;
+
+        /**
+         * < Contains resource usage information for the job.
+         */
+        public LibLsf.jRusage runRusage;
+
+        /**
+         * < Job type.N_JOB, N_GROUP, N_HEAD
+         */
+        public int jType;
+
+        /**
+         * < The parent job group of a job or job group.
+         */
+        public String parentGroup;
+
+        /**
+         * < If jType is JGRP_NODE_GROUP, then it is the job group name. Otherwise, it is thejob name.
+         */
+        public String jName;
+
+        /**
+         * < Index into the counter array, only used for job arrays. Possible index values are shown in \ref jobgroup_counterIndex
+         */
+        public int[] counter = new int[NUM_JGRP_COUNTERS];
+
+        /**
+         * < Service port of the job.
+         */
+        public short port;
+
+        /**
+         * < Job dynamic priority
+         */
+        public int jobPriority;
+
+        /**
+         * < The number of external messages in the job.
+         */
+        public int numExternalMsg;
+
+        /**
+         * < This structure contains the information required to define an external message reply.
+         */
+        public Pointer externalMsg;
+
+        /**
+         * < MultiCluster cluster ID. If clusterId is greater than or equal to 0, the job is a pending remote job, and \ref lsb_readjobinfo checks for host_name\@cluster_name. If host name is needed, it should be found in  jInfoH->remoteHosts. If the remote host name is not available, the constant string remoteHost is used.
+         */
+        public int clusterId;
+
+        /**
+         * <  Detail reason field
+         */
+        public String detailReason;
+
+        /**
+         * < Idle factor for job exception handling. If the job idle factor is less than the specified threshold, LSF invokes LSF_SERVERDIR/eadmin to trigger the action for a job idle exception.
+         */
+        public float idleFactor;
+
+        /**
+         * < Job exception handling mask
+         */
+        public int exceptMask;
+
+
+        /**
+         * < Placement information of LSF HPC jobs.Placement information of LSF HPC jobs.Arbitrary information of a job stored as a string currently used by rms_rid  and rms_alloc
+         */
+        public String additionalInfo;
+
+        /**
+         * < Job termination reason. See lsbatch.h.
+         */
+        public int exitInfo;
+
+        /**
+         * < Job warning time period in seconds; -1 if unspecified.
+         */
+        public int warningTimePeriod;
+
+        /**
+         * < Warning action, SIGNAL | CHKPNT |command, null if unspecified
+         */
+        public String warningAction;
+
+        /**
+         * < SAAP charged for job
+         */
+        public String chargedSAAP;
+
+        /**
+         * < The rusage satisfied at job runtime
+         */
+        public String execRusage;
+
+        /**
+         * < The time when advance reservation expired or was deleted.
+         */
+        public NativeLong rsvInActive;
+
+        /**
+         * < The number of licenses reported from License Scheduler.
+         */
+        public int numLicense;
+
+        /**
+         * < License Scheduler license names.
+         */
+        public Pointer licenseNames;
+
+        /**
+         * < Absolute priority scheduling (APS) priority value.
+         */
+        public float aps;
+
+        /**
+         * < Absolute priority scheduling (APS) string set by administrators to denote static system APS value
+         */
+        public float adminAps;
+
+        /**
+         * < The real runtime on the execution host.
+         */
+        public int runTime;
+
+        /**
+         * < How many kinds of resource are reserved by this job
+         */
+        public int reserveCnt;
+
+        /**
+         * < Detail reservation information for each kind of resource
+         */
+        public Pointer /* reserveItem.ByReference */ items;
+
+        /**
+         * < Absolute priority scheduling (APS) string set by administrators to denote ADMIN factor APS value.
+         */
+        public float adminFactorVal;
+
+        /**
+         * < Pending resize min. 0, if no resize pending.
+         */
+        public int resizeMin;
+
+        /**
+         * < Pending resize max. 0, if no resize pending
+         */
+        public int resizeMax;
+
+        /**
+         * < Time when pending request was issued
+         */
+        public NativeLong resizeReqTime;
+
+        /**
+         * < Number of hosts when job starts
+         */
+        public int jStartNumExHosts;
+
+        /**
+         * < Host list when job starts
+         */
+        public Pointer jStartExHosts;
+
+        /**
+         * < Last time when job allocation changed
+         */
+        public NativeLong lastResizeTime;
+    }
+
+
+/* the bit set for jobInfoEnt->exceptMask */
+    public static final int J_EXCEPT_OVERRUN = 0x02;
+    public static final int J_EXCEPT_UNDERUN = 0x04;
+    public static final int J_EXCEPT_IDLE = 0x80;
+    public static final int J_EXCEPT_RUNTIME_EST_EXCEEDED = 0x100;
+
+/* exception showed by bjobs -l and bacct -l*/
+    public static final String OVERRUN = "overrun";
+    public static final String UNDERRUN = "underrun";
+    public static final String IDLE = "idle";
+    public static final String SPACE = "  ";
+    public static final String RUNTIME_EST_EXCEEDED = "runtime_est_exceeded";
+
+/* LSF7.0 moved jobInfoReq structure definition from
+*  daemonout.h to lsbatch.h. This structure will work
+*  with new API \ref lsb_openjobinfo_req
+ */
+
+    /**
+     * \brief  job Information Request
+     */
+    public static class jobInfoReq extends Structure {
+        public static class ByReference extends jobInfoReq implements Structure.ByReference {}
+        public static class ByValue extends jobInfoReq implements Structure.ByValue {}
+        public jobInfoReq() {}
+        public jobInfoReq(Pointer p) { super(p); read(); }
+
+
+        /**
+         * < Options defined in \ref defs_lsb_openjobinfo
+         */
+        public int options;
+
+        /**
+         * < Name of user whose jobs to be checked
+         */
+        public String userName;
+
+        /**
+         * < Job id, 0 means all jobs
+         */
+        public long jobId;
+
+        /**
+         * < Job name
+         */
+        public String jobName;
+
+        /**
+         * < Queue name
+         */
+        public String queue;
+
+        /**
+         * < Check jobs running on this host
+         */
+        public String host;
+
+        /**
+         * < Job application
+         */
+        public String app;
+
+        /**
+         * < Job description
+         */
+        public String jobDescription;
+
+        /**
+         * < For new options in future
+         */
+        public submit_ext.ByReference submitExt;
+    }
+
+
+
+    /**
+     * \brief  user information entry.
+     */
+    public static class userInfoEnt extends Structure {
+        public static class ByReference extends userInfoEnt implements Structure.ByReference {}
+        public static class ByValue extends userInfoEnt implements Structure.ByValue {}
+        public userInfoEnt() {}
+        public userInfoEnt(Pointer p) { super(p); read(); }
+
+
+        /**
+         * < Name of the user or user group
+         */
+        public String user;
+
+        /**
+         * < The maximum number of job slots the user or user group can use on each processor. The job slots can be used by started jobs or reserved for PEND jobs.
+         */
+        public float procJobLimit;
+
+        /**
+         * < The maximum number of job slots that the user or user group can use simultaneously in the local LSF cluster. The job slots can be used by started jobs or reserved for PEND jobs.
+         */
+        public int maxJobs;
+
+        /**
+         * < The current number of job slots used by running and suspended jobs belonging to the user or user group.
+         */
+        public int numStartJobs;
+
+        /**
+         * < The total number of job slots in the LSF cluster for the jobs submitted by the user or user group.
+         */
+        public int numJobs;
+
+        /**
+         * < The number of job slots the user or user group has for pending jobs.
+         */
+        public int numPEND;
+
+        /**
+         * < The number of job slots the user or user group has for running jobs.
+         */
+        public int numRUN;
+
+        /**
+         * < The number of job slots for the jobs belonging to the user or user group that have been suspended by the system.
+         */
+        public int numSSUSP;
+
+        /**
+         * < The number of job slots for the jobs belonging to the user or user group that have been suspended by the user or the LSF system administrator.
+         */
+        public int numUSUSP;
+
+        /**
+         * < The number of job slots reserved for the pending jobs belonging to the user or user group.
+         */
+        public int numRESERVE;
+
+        /**
+         * < The maximum number of pending jobs allowed.
+         */
+        public int maxPendJobs;
+    }
+
+
+
+/* UserEquivalent info */
+
+    public static class userEquivalentInfoEnt extends Structure {
+        public static class ByReference extends userEquivalentInfoEnt implements Structure.ByReference {}
+        public static class ByValue extends userEquivalentInfoEnt implements Structure.ByValue {}
+        public userEquivalentInfoEnt() {}
+        public userEquivalentInfoEnt(Pointer p) { super(p); read(); }
+
+        public String equivalentUsers;
+    }
+
+
+
+/* UserMapping info */
+
+    public static class userMappingInfoEnt extends Structure {
+        public static class ByReference extends userMappingInfoEnt implements Structure.ByReference {}
+        public static class ByValue extends userMappingInfoEnt implements Structure.ByValue {}
+        public userMappingInfoEnt() {}
+        public userMappingInfoEnt(Pointer p) { super(p); read(); }
+
+
+/* Users in the local cluster */
+        public String localUsers;
+
+/* Users in remote clusters */
+        public String remoteUsers;
+
+/* "export" or "import" */
+        public String direction;
+    }
+
+
+
+
+/* APS structures used for mapping between factors */
+
+    /**
+     * \brief  APS structures used for mapping between factors
+     */
+    public static class apsFactorMap extends Structure {
+        public static class ByReference extends apsFactorMap implements Structure.ByReference {}
+        public static class ByValue extends apsFactorMap implements Structure.ByValue {}
+        public apsFactorMap() {}
+        public apsFactorMap(Pointer p) { super(p); read(); }
+
+
+        /**
+         * < Name of factor.
+         */
+        public String factorName;
+
+        /**
+         * < SubFactor names.
+         */
+        public String subFactorNames;
+    }
+
+
+
+    /**
+     * \brief  APS structures used for mapping between factors
+     */
+    public static class apsLongNameMap extends Structure {
+        public static class ByReference extends apsLongNameMap implements Structure.ByReference {}
+        public static class ByValue extends apsLongNameMap implements Structure.ByValue {}
+        public apsLongNameMap() {}
+        public apsLongNameMap(Pointer p) { super(p); read(); }
+
+
+        /**
+         * < Short name
+         */
+        public String shortName;
+
+        /**
+         * < Long name
+         */
+        public String longName;
+    }
+
+
+
+
+/* options for lsb_queueinfo() , some values should not
+*  conflict with the option values for lsb_usergrpinfo() and lsb_hostinfo_ex()
+*  since they share the same xdr_infoReq()
+*/
+
+/* for compatibility for 2.0 */
+    public static final int ALL_QUEUE = 0x01;
+
+/* for compatibility for 2.0 */
+    public static final int DFT_QUEUE = 0x02;
+    public static final int CHECK_HOST = 0x80;
+    public static final int CHECK_USER = 0x100;
+    public static final int SORT_HOST = 0x200;
+
+/* not bqueues -l or -r */
+    public static final int QUEUE_SHORT_FORMAT = 0x400;
+/* expand hostname into official hostname in lsb_queueinfo */
+    public static final int EXPAND_HOSTNAME = 0x800;
+
+/* only retrieve batch partitions */
+    public static final int RETRIEVE_BATCH = 0x1000;
+
+/* Signal number in each version LSB_SIG_NUM must be equal to
+*  signal number in the latest version.
+ */
+    public static final int LSB_SIG_NUM_40 = 25;
+    public static final int LSB_SIG_NUM_41 = 26;
+
+/* Solutions #38347 */
+    public static final int LSB_SIG_NUM_51 = 30;
+    public static final int LSB_SIG_NUM_60 = 30;
+    public static final int LSB_SIG_NUM = 30;
+
+/* Dynamic CPU provision
+*  to indicate whether a SP can lend or borrow hosts
+ */
+    public static final int DCP_LEND_HOSTS = 0x0001;
+    public static final int DCP_BORROW_HOSTS = 0x0002;
+
+/* status to indicate the current situation of Dynamic CPU provision
+*  DCP_UNDER_ALLOC_AND_STARVING means a partition is under allocation
+*  of dynamic cpu and its pending jobs are starving for more cpus.
+ */
+    public static final int DCP_ALLOC_CPU_OK = 0x0;
+    public static final int DCP_UNDER_ALLOC_CPU = 0x0001;
+    public static final int DCP_JOB_WAIT_FOR_CPU = 0x0002;
+    public static final int DCP_ALLOC_CPU_BUSY = 0x0004;
+
+/* Structure for lsb_queueinfo() call */
+/* !!! IMPORTANT !!!
+*  If you change queueInfoEnt, you have to change Intlib/ade.lsbatch.h too!
+ */
+
+    /**
+     * queueInfoEnt  queue information entry.
+     */
+    public static class queueInfoEnt extends Structure {
+        public static class ByReference extends queueInfoEnt implements Structure.ByReference {}
+        public static class ByValue extends queueInfoEnt implements Structure.ByValue {}
+        public queueInfoEnt() {}
+        public queueInfoEnt(Pointer p) { super(p); read(); }
+
+
+        /**
+         * < The name of the queue.
+         */
+        public String queue;
+
+        /**
+         * < Describes the typical use of the queue.
+         */
+        public String description;
+
+        /**
+         * < Defines the priority of the queue. This determines the order in which the job queues are searched at job dispatch time: queues with higher priority values are searched first. (This is contrary to UNIX process priority ordering.)
+         */
+        public int priority;
+
+        /**
+         * < Defines the nice value at which jobs in this queue will be run.
+         */
+        public short nice;
+
+        /**
+         * < A blank-separated list of names of users allowed to submit jobs to this queue.
+         */
+        public String userList;
+
+        /**
+         * < A blank-separated list of names of hosts to which jobs in this queue may be dispatched.
+         */
+        public String hostList;
+
+        /**
+         * < Original HOSTS string in case "-" is used.
+         */
+        public String hostStr;
+
+        /**
+         * < The number of load indices in the loadSched and loadStop arrays.
+         */
+        public int nIdx;
+
+        /**
+         * < The queue and host loadSched and loadStop arrays control batch job dispatch, suspension, and resumption. The values in the loadSched array specify thresholds for the corresponding load indices. Only if the current values of all specified load indices of a host are within (below or above, depending on the meaning of the load index) the corresponding thresholds of this queue, will jobs in this queue be dispatched to the host. The same conditions are used to resume jobs dispatc [...]
+         */
+        public FloatByReference loadSched;
+
+        /**
+         * < The values in the loadStop array specify the thresholds for job suspension. If any of the current load index values of a host goes beyond a queue's threshold, jobs from the queue will be suspended. For an explanation of the fields in the loadSched and loadStop arrays, see \ref lsb_hostinfo.
+         */
+        public FloatByReference loadStop;
+
+        /**
+         * < Per-user limit on the number of jobs that can be dispatched from this queue and executed concurrently.
+         */
+        public int userJobLimit;
+
+        /**
+         * < Per-processor limit on the number of jobs that can be dispatched from this queue and executed concurrently.
+         */
+        public float procJobLimit;
+
+        /**
+         * < A blank-separated list of time windows describing the run window of the queue. When a queue's run window is closed, no job from this queue will be dispatched. When the run window closes, any running jobs from this queue will be suspended until the run window reopens, when they will be resumed. The default is no restriction, or always open (i.e., 24 hours a day, seven days a week). A time window has the format begin_time-end_time. Time is specified in the format [day:]hour[:m [...]
+         */
+        public String windows;
+
+        /**
+         * < The per-process UNIX hard resource limits for all jobs submitted to this queue (see getrlimit() and lsb.queues). The default values for the resource limits are unlimited, indicated by -1. The constants used to index the rLimits array and the corresponding resource limits are listed below. <br> LSF_RLIMIT_CPU (CPULIMIT) <br> LSF_RLIMIT_FSIZE (FILELIMIT) <br> LSF_RLIMIT_DATA (DATALIMIT) <br> LSF_RLIMIT_STACK    (STACKLIMIT) <br> LSF_RLIMIT_CORE     (CORELIMIT) <br> LSF_RLIMIT_ [...]
+         */
+        public int[] rLimits = new int[LibLsf.LSF_RLIM_NLIMITS];
+
+        /**
+         * < A host name or host model name. If the queue CPULIMIT or RUNLIMIT gives a host specification, hostSpec will be that specification. Otherwise, if defaultHostSpec (see below) is not null, hostSpec will be defaultHostSpec. Otherwise, if DEFAULT_HOST_SPEC is defined in the lsb.params file, (see lsb.params), hostSpec will be this value. Otherwise, hostSpec will be the name of the host with the largest CPU factor in the cluster.
+         */
+        public String hostSpec;
+
+        /**
+         * < The attributes of the queue.
+         */
+        public int qAttrib;
+
+        /**
+         * < The status of the queue.
+         */
+        public int qStatus;
+
+        /**
+         * < The maximum number of jobs dispatched by the queue and not yet finished.
+         */
+        public int maxJobs;
+
+        /**
+         * < Number of jobs in the queue, including pending, running, and suspended jobs.
+         */
+        public int numJobs;
+
+        /**
+         * < Number of pending jobs in the queue.
+         */
+        public int numPEND;
+
+        /**
+         * < Number of running jobs in the queue.
+         */
+        public int numRUN;
+
+        /**
+         * < Number of system suspended jobs in the queue.
+         */
+        public int numSSUSP;
+
+        /**
+         * < Number of user suspended jobs in the queue.
+         */
+        public int numUSUSP;
+
+        /**
+         * < The queue migration threshold in minutes.
+         */
+        public int mig;
+
+        /**
+         * < The number of seconds that a new job waits, before being scheduled. A value of zero (0) means the job is scheduled without any delay.
+         */
+        public int schedDelay;
+
+        /**
+         * < The number of seconds for a host to wait after dispatching a job to a host, before accepting a second job to dispatch to the same host.
+         */
+        public int acceptIntvl;
+
+        /**
+         * < A blank-separated list of time windows describing the dispatch window of the queue. When a queue's dispatch window is closed, no job from this queue will be dispatched.The default is no restriction, or always open (i.e., 24 hours a day, seven days a week). For the time window format, see windows (above).
+         */
+        public String windowsD;
+
+        /**
+         * < A blank-separated list of queue specifiers. Each queue specifier is of the form queue\@host where host is an NQS host name and queue is the name of a queue on that host.
+         */
+        public String nqsQueues;
+
+        /**
+         * < A blank-separated list of user shares. Each share is of the form [user, share] where user is a user name, a user group name, the reserved word default or the reserved word others, and share is the number of shares the user gets.
+         */
+        public String userShares;
+
+        /**
+         * < The value of DEFAULT_HOST_SPEC in the Queue section for this queue in the lsb.queues file.
+         */
+        public String defaultHostSpec;
+
+        /**
+         * < An LSF resource limit used to limit the number of job slots (processors) a (parallel) job in the queue will use. A job submitted to this queue must specify a number of processors not greater than this limit.
+         */
+        public int procLimit;
+
+        /**
+         * < A list of administrators of the queue. The users whose names are here are allowed to operate on the jobs in the queue and on the queue itself.
+         */
+        public String admins;
+
+        /**
+         * < Queue's pre-exec command. The command is executed before the real batch job is run on the execution host (or on the first host selected for a parallel batch job).
+         */
+        public String preCmd;
+
+        /**
+         * < Queue's post-exec command. The command is run when a job terminates.
+         */
+        public String postCmd;
+
+        /**
+         * < Jobs that exit with these values are automatically requeued.
+         */
+        public String requeueEValues;
+
+        /**
+         * < The maximum number of job slots a host can process from this queue, including job slots of dispatched jobs which have not finished yet and reserved slots for some PEND jobs. This limit controls the number of jobs sent to each host, regardless of a uniprocessor host or multiprocessor host. Default value for this limit is infinity.
+         */
+        public int hostJobLimit;
+
+        /**
+         * < Resource requirement string used to determine eligible hosts for a job.
+         */
+        public String resReq;
+
+        /**
+         * < Number of reserved job slots for pending jobs.
+         */
+        public int numRESERVE;
+
+        /**
+         * < The time used to hold the reserved job slots for a PEND job in this queue.
+         */
+        public int slotHoldTime;
+
+        /**
+         * < Remote MultiCluster send-jobs queues to forward jobs to.
+         */
+        public String sndJobsTo;
+
+        /**
+         * < Remote MultiCluster receive-jobs queues that can forward to this queue.
+         */
+        public String rcvJobsFrom;
+
+        /**
+         * < Resume threshold conditions for a suspended job in this queue.
+         */
+        public String resumeCond;
+
+        /**
+         * < Stop threshold conditions for a running job in this queue.
+         */
+        public String stopCond;
+
+        /**
+         * < Job starter command for a running job in this queue
+         */
+        public String jobStarter;
+
+        /**
+         * < Command configured for the SUSPEND action.
+         */
+        public String suspendActCmd;
+
+        /**
+         * < Command configured for the RESUME action.
+         */
+        public String resumeActCmd;
+
+        /**
+         * < Command configured for the TERMINATE action.
+         */
+        public String terminateActCmd;
+
+        /**
+         * < Configurable signal mapping
+         */
+        public int[] sigMap = new int[LSB_SIG_NUM];
+
+        /**
+         * < Preemptive scheduling and preemption policy specified for the queue.
+         */
+        public String preemption;
+
+        /**
+         * < Time period for a remote cluster to schedule a job. MultiCluster job forwarding model only. Determines how long a MultiCluster job stays pending in the execution cluster before returning to the submission cluster. The remote timeout limit in seconds is: \li MAX_RSCHED_TIME.ByReference  MBD_SLEEP_TIME=timeout
+         */
+        public int maxRschedTime;
+
+
+        /**
+         * < Number of share accounts in the queue.
+         */
+        public int numOfSAccts;
+
+        /**
+         * < (Only used for queues with fairshare policy) a share account vector capturing the fairshare information of the users using the queue. The storage for the array of queueInfoEnt structures will be reused by the next call.
+         */
+        public Pointer /* shareAcctInfoEnt.ByReference */ shareAccts;
+
+        /**
+         * < The directory where the checkpoint files are created.
+         */
+        public String chkpntDir;
+
+        /**
+         * < The checkpoint period in minutes.
+         */
+        public int chkpntPeriod;
+
+        /**
+         * < MultiCluster job forwarding model only. Specifies the MultiCluster pending job limit for a receive-jobs queue. This represents the maximum number of MultiCluster import jobs that can be pending in the queue; once the limit has been reached, the queue stops accepting jobs from remote clusters.
+         */
+        public int imptJobBklg;
+
+        /**
+         * < The default (soft) resource limits for all jobs submitted to this queue (see getrlimit() and lsb.queues).
+         */
+        public int[] defLimits = new int[LibLsf.LSF_RLIM_NLIMITS];
+
+        /**
+         * < The maximum number of jobs allowed to be dispatched together in one job chunk. Must be a positive integer greater than 1.
+         */
+        public int chunkJobSize;
+
+        /**
+         * < The minimum number of job slots (processors) that a job in the queue will use.
+         */
+        public int minProcLimit;
+
+        /**
+         * < The default (soft) limit on the number of job slots (processors) that a job in the queue will use.
+         */
+        public int defProcLimit;
+
+        /**
+         * < The list of queues for cross-queue fairshare.
+         */
+        public String fairshareQueues;
+
+        /**
+         * < Default external scheduling for the queue.
+         */
+        public String defExtSched;
+
+        /**
+         * < Mandatory external scheduling options for the queue.
+         */
+        public String mandExtSched;
+
+        /**
+         * < Share of job slots for queue-based fairshare. Represents the percentage of running jobs (job slots) in use from the queue. SLOT_SHARE must be greater than zero (0) and less than or equal to 100. The sum of SLOT_SHARE for all queues in the pool does not need to be 100%. It can be more or less, depending on your needs.
+         */
+        public int slotShare;
+
+        /**
+         * < Name of the pool of job slots the queue belongs to for queue-based fairshare. A queue can only belong to one pool. All queues in the pool must share the same set of hosts. Specify any ASCII string up to 60 chars long. You can use letters, digits, underscores (_) or dashes (-). You cannot use blank spaces.
+         */
+        public String slotPool;
+
+        /**
+         * < Specifies a threshold for job underrun exception handling. If a job exits before the specified number of minutes, LSF invokes LSF_SERVERDIR/eadmin to trigger the action for a job underrun exception.
+         */
+        public int underRCond;
+
+        /**
+         * < Specifies a threshold for job overrun exception handling. If a job runs longer than the specified run time, LSF invokes LSF_SERVERDIR/eadmin to trigger the action for a job overrun exception.
+         */
+        public int overRCond;
+
+        /**
+         * < Specifies a threshold for idle job exception handling. The value should be a number between 0.0 and 1.0 representing CPU time/runtime. If the job idle factor is less than the specified threshold, LSF invokes LSF_SERVERDIR/eadmin to trigger the action for a job idle exception.
+         */
+        public float idleCond;
+
+        /**
+         * < The number of underrun jobs in the queue.
+         */
+        public int underRJobs;
+
+        /**
+         * < The number of overrun jobs in the queue.
+         */
+        public int overRJobs;
+
+        /**
+         * < The number of idle jobs in the queue.
+         */
+        public int idleJobs;
+
+        /**
+         * < Specifies the amount of time before a job control action occurs that a job warning action is to be taken. For example, 2 minutes before the job reaches run time limit or termination deadline, or the queue's run window is closed, an URG signal is sent to the job. Job action warning time is not normalized. A job action warning time must be specified with a job warning action in order for job warning to take effect.
+         */
+        public int warningTimePeriod;
+
+        /**
+         * < Specifies the job action to be taken before a job control action occurs. For example, 2 minutes before the job reaches run time limit or termination deadline, or the queue's run window is closed, an URG signal is sent to the job. A job warning action must be specified with a job action warning time in order for job warning to take effect. If specified, LSF sends the warning action to the job before the actual control action is taken. This allows the job time to save its resu [...]
+         */
+        public String warningAction;
+
+        /**
+         * < AdminAction - queue control message
+         */
+        public String qCtrlMsg;
+
+        /**
+         * < Acept resource request.
+         */
+        public String acResReq;
+
+        /**
+         * < Limit of running session scheduler jobs.
+         */
+        public int symJobLimit;
+
+        /**
+         * < cpu_req for service partition of session scheduler
+         */
+        public String cpuReq;
+
+        /**
+         * < Indicate whether it would be willing to donate/borrow.
+         */
+        public int proAttr;
+
+        /**
+         * < The maximum number of hosts to lend.
+         */
+        public int lendLimit;
+
+        /**
+         * < The grace period to lend/return idle hosts.
+         */
+        public int hostReallocInterval;
+
+        /**
+         * < Number of CPUs required by CPU provision.
+         */
+        public int numCPURequired;
+
+        /**
+         * < Number of CPUs actually allocated.
+         */
+        public int numCPUAllocated;
+
+        /**
+         * < Number of CPUs borrowed.
+         */
+        public int numCPUBorrowed;
+
+        /**
+         * < Number of CPUs lent.
+         */
+        public int numCPULent;
+        /* the number of reserved cpu(numCPUReserved) = numCPUAllocated - numCPUBorrowed + numCPULent */
+
+
+        /* the following fields are for real-time app(ex. murex) of symphony */
+
+        /**
+         * < Scheduling granularity. in milliseconds.
+         */
+        public int schGranularity;
+
+        /**
+         * < The grace period for stopping session scheduler tasks.
+         */
+        public int symTaskGracePeriod;
+
+        /**
+         * < Minimum number of SSMs.
+         */
+        public int minOfSsm;
+
+        /**
+         * < Maximum number of SSMs.
+         */
+        public int maxOfSsm;
+
+        /**
+         * < Number of allocated slots.
+         */
+        public int numOfAllocSlots;
+
+        /**
+         * < Service preemptin policy.
+         */
+        public String servicePreemption;
+
+
+        /**
+         * < Dynamic cpu provision status.
+         */
+        public int provisionStatus;
+
+        /**
+         * < The minimum time for preemption and backfill, in seconds.
+         */
+        public int minTimeSlice;
+
+        /**
+         * < List of queues defined in a queue group for absolute priority scheduling (APS) across multiple queues.
+         */
+        public String queueGroup;
+
+        /**
+         * < The number of calculation factors for absolute priority scheduling (APS).
+         */
+        public int numApsFactors;
+
+        /**
+         * < List of calculation factors for absolute priority scheduling (APS)
+         */
+        public Pointer /* apsFactorInfo.ByReference */ apsFactorInfoList;
+
+        /**
+         * < The mapping of factors to subfactors for absolute priority scheduling (APS).
+         */
+        public Pointer /* apsFactorMap.ByReference */ apsFactorMaps;
+
+        /**
+         * < The mapping of factors to their long names for absolute priority scheduling (APS).
+         */
+        public Pointer /* apsLongNameMap.ByReference */ apsLongNames;
+
+        /**
+         * < Maximum number of job preempted times.
+         */
+        public int maxJobPreempt;
+
+        /**
+         * < Maximum number of pre-exec retry times.
+         */
+        public int maxPreExecRetry;
+
+        /**
+         * < Maximum number of pre-exec retry times for local cluster
+         */
+        public int localMaxPreExecRetry;
+
+        /**
+         * < Maximum number of job re-queue times.
+         */
+        public int maxJobRequeue;
+
+        /**
+         * < Use Linux-PAM
+         */
+        public int usePam;
+        /* compute unit exclusive */
+
+        /**
+         * < Compute unit type
+         */
+        public int cu_type_exclusive;
+
+        /**
+         * < A string specified in EXCLUSIVE=CU[\<string>]
+         */
+        public String cu_str_exclusive;
+
+        /**
+         * < Resource reservation limit
+         */
+        public String resRsvLimit;
+
+    }
+
+
+
+    /**
+     *  \addtogroup signal_action signal_action
+     *  define status for signal action
+     */
+
+    /**
+     * <  No action
+     */
+    public static final int ACT_NO = 0;
+
+    /**
+     * <  Start
+     */
+    public static final int ACT_START = 1;
+
+    /**
+     * <  Preempt
+     */
+    public static final int ACT_PREEMPT = 2;
+
+    /**
+     * <  Done
+     */
+    public static final int ACT_DONE = 3;
+
+    /**
+     * <  Fail
+     */
+    public static final int ACT_FAIL = 4;
+
+    /**
+     * \brief  host information entry.
+     */
+    public static class hostInfoEnt extends Structure {
+        public static class ByReference extends hostInfoEnt implements Structure.ByReference {}
+        public static class ByValue extends hostInfoEnt implements Structure.ByValue {}
+        public hostInfoEnt() {}
+        public hostInfoEnt(Pointer p) { super(p); read(); }
+
+
+        /**
+         * < The name of the host.
+         */
+        public String host;
+
+        /**
+         * < The status of the host. It is the bitwise  inclusive OR.  see \ref host_status
+         */
+        public int hStatus;
+
+        /**
+         * < Indicate host loadSched busy reason
+         */
+        public IntByReference busySched;
+
+        /**
+         * < Indicate host loadStop  busy reason.
+         */
+        public IntByReference busyStop;
+
+        /**
+         * < The host CPU factor used to scale CPU load values to account for differences in CPU speeds. The faster the CPU, the larger the CPU factor.
+         */
+        public float cpuFactor;
+
+        /**
+         * < The number of load indices in the load, loadSched and loadStop arrays.
+         */
+        public int nIdx;
+
+        /**
+         * < Load information array on a host. This array gives the load information that is used for  scheduling batch jobs. This load information  is the effective load information from \ref ls_loadofhosts (see \ref ls_loadofhosts) plus the load reserved for running jobs (see lsb.queues for details on resource reservation). The load array is indexed the same as loadSched and loadStop  (see loadSched and loadStop below).
+         */
+        public FloatByReference load;
+
+        /**
+         * < Stop scheduling new jobs if over
+         */
+        public FloatByReference loadSched;
+
+        /**
+         * < Stop jobs if over this load. The loadSched and loadStop arrays control batch job scheduling, suspension, and resumption. The values in the loadSched array specify the scheduling thresholds for the corresponding load indices. Only if the current values of all specified load indices of this host are within (below or above, depending on the meaning of the load index) the corresponding thresholds of this host, will jobs be scheduled to run on this host. Similarly, the values in  [...]
+         */
+        public FloatByReference loadStop;
+
+        /**
+         * < ASCII desp of run windows.One or more time windows in a week during which batch jobs may be dispatched to run on this host . The default is no restriction, or always open (i.e., 24 hours a day seven days a week). These windows are similar to the dispatch windows of batch job queues. See \ref lsb_queueinfo.
+         */
+        public String windows;
+
+        /**
+         * < The maximum number of job slots any user is allowed to use on this host.
+         */
+        public int userJobLimit;
+
+        /**
+         * < The maximum number of job slots that the host can process concurrently.
+         */
+        public int maxJobs;
+
+        /**
+         * < The number of job slots running or suspended on the host.
+         */
+        public int numJobs;
+
+        /**
+         * < The number of job slots running on the host.
+         */
+        public int numRUN;
+
+        /**
+         * < The number of job slots suspended by the batch daemon on the host.
+         */
+        public int numSSUSP;
+
+        /**
+         * < The number of job slots suspended by the job submitter or the LSF system administrator.
+         */
+        public int numUSUSP;
+
+        /**
+         * < The migration threshold in minutes after which a suspended job will be considered for migration.
+         */
+        public int mig;
+
+
+        /**
+         * < The host attributes; the bitwise inclusive OR of some of \ref host_attributes
+         */
+        public int attr;
+        /**
+         *  \addtogroup host_attributes host_attributes
+         *  The host attributes
+         */
+
+        /**
+         * < This host can checkpoint jobs
+         */
+        public static final int H_ATTR_CHKPNTABLE = 0x1;
+
+        /**
+         * < This host provides kernel support for checkpoint copy.
+         */
+        public static final int H_ATTR_CHKPNT_COPY = 0x2;
+
+        /**
+         * < The effective load of the host.
+         */
+        public FloatByReference realLoad;
+
+        /**
+         * < The number of job slots reserved by LSF for the PEND jobs.
+         */
+        public int numRESERVE;
+
+        /**
+         * < If attr has an H_ATTR_CHKPNT_COPY attribute, chkSig is set to the signal which triggers  checkpoint and copy operation. Otherwise,  chkSig is set to the signal which triggers  checkpoint operation on the host
+         */
+        public int chkSig;
+
+
+        /**
+         * < Num of resource used by the consumer
+         */
+        public float cnsmrUsage;
+
+        /**
+         * < Num of resource used by the provider
+         */
+        public float prvdrUsage;
+
+        /**
+         * < Num of resource available for the consumer to use
+         */
+        public float cnsmrAvail;
+
+        /**
+         * < Num of resource available for the provider to use
+         */
+        public float prvdrAvail;
+
+        /**
+         * < Num maximum of resource available in total
+         */
+        public float maxAvail;
+
+        /**
+         * < The job exit rate threshold on the host
+         */
+        public float maxExitRate;
+
+        /**
+         * < Number of job exit rate on the host
+         */
+        public float numExitRate;
+
+        /**
+         * < AdminAction - host control message
+         */
+        public String hCtrlMsg;
+
+    }
+
+
+
+    /**
+     * \brief  Host information condition entry.
+     */
+    public static class condHostInfoEnt extends Structure {
+        public static class ByReference extends condHostInfoEnt implements Structure.ByReference {}
+        public static class ByValue extends condHostInfoEnt implements Structure.ByValue {}
+        public condHostInfoEnt() {}
+        public condHostInfoEnt(Pointer p) { super(p); read(); }
+
+
+        /**
+         * < Host name
+         */
+        public String name;
+
+
+        /**
+         * < How many hosts are in the ok status
+         */
+        public int howManyOk;
+
+        /**
+         * < How many hosts are in the busy status
+         */
+        public int howManyBusy;
+
+        /**
+         * < How many hosts are in the closed status
+         */
+        public int howManyClosed;
+
+        /**
+         * < How many hosts are in the full status
+         */
+        public int howManyFull;
+
+        /**
+         * < How many hosts are in the unreach status
+         */
+        public int howManyUnreach;
+
+        /**
+         * < How many hosts are in the unavail status
+         */
+        public int howManyUnavail;
+
+
+        /**
+         * < The status of each host in the host group
+         */
+        public Pointer /* hostInfoEnt.ByReference */ hostInfo;
+
+    }
+
+
+
+    public static class adjustParam extends Structure {
+        public static class ByReference extends adjustParam implements Structure.ByReference {}
+        public static class ByValue extends adjustParam implements Structure.ByValue {}
+        public adjustParam() {}
+        public adjustParam(Pointer p) { super(p); read(); }
+
+
+/* key name of share adjustment */
+        public String key;
+
+/* value of the key */
+        public float value;
+    }
+
+
+
+
+/* cpu time factor */
+    public static final int FAIR_ADJUST_CPU_TIME_FACTOR = 0;
+
+/* run time factor */
+    public static final int FAIR_ADJUST_RUN_TIME_FACTOR = 1;
+
+/* run job factor */
+    public static final int FAIR_ADJUST_RUN_JOB_FACTOR = 2;
+
+/* committed run time factor */
+    public static final int FAIR_ADJUST_COMMITTED_RUN_TIME_FACTOR = 3;
+
+/* enable hist run time */
+    public static final int FAIR_ADJUST_ENABLE_HIST_RUN_TIME = 4;
+
+/* cpu time of finished jobs with decay */
+    public static final int FAIR_ADJUST_HIST_CPU_TIME = 5;
+
+/* cpu time of finished jobs within decay */
+    public static final int FAIR_ADJUST_NEW_USED_CPU_TIME = 6;
+
+/* total time that job spend in RUN state */
+    public static final int FAIR_ADJUST_RUN_TIME = 7;
+
+/* historical run time of finished jobs */
+    public static final int FAIR_ADJUST_HIST_RUN_TIME = 8;
+
+/* committed run time of started jobs */
+    public static final int FAIR_ADJUST_COMMITTED_RUN_TIME = 9;
+
+/* number of job slots used by started jobs */
+    public static final int FAIR_ADJUST_NUM_START_JOBS = 10;
+
+/* number of reserved slots used by pending jobs */
+    public static final int FAIR_ADJUST_NUM_RESERVE_JOBS = 11;
+
+/* total amount of memory used by started jobs */
+    public static final int FAIR_ADJUST_MEM_USED = 12;
+
+/* average memory allocated per slot */
+    public static final int FAIR_ADJUST_MEM_ALLOCATED = 13;
+
+/* total number of fairshare adjustment key value pairs */
+    public static final int FAIR_ADJUST_KVPS_SUM = 14;
+
+    //public String[] FairAdjustPairArrayName = new String[FAIR_ADJUST_KVPS_SUM];
+
+    public static class shareAdjustPair extends Structure {
+        public static class ByReference extends shareAdjustPair implements Structure.ByReference {}
+        public static class ByValue extends shareAdjustPair implements Structure.ByValue {}
+        public shareAdjustPair() {}
+        public shareAdjustPair(Pointer p) { super(p); read(); }
+
+
+/* queue share account */
+        public static int SHAREACCTTYPEQUEUE = 0x01;
+
+/* host partition share account */
+        public static final int SHAREACCTTYPEHP = 0x02;
+
+/* SLA share account */
+        public static final int SHAREACCTTYPESLA = 0x04;
+
+/* type of share account*/
+        public int shareAcctType;
+
+/* name of the share holder that use the share */
+        public String holderName;
+
+/* name of the provider policy name(name of queue, host partition or SLA) */
+        public String providerName;
+
+/* number of share adjustment key value pair */
+        public int numPair;
+
+/* share adjustment key value pair */
+        public Pointer /* adjustParam.ByReference */ adjustParam;
+    }
+
+
+
+    // NOTE: Not in libbat
+    //public static native float fairshare_adjustment(shareAdjustPair shareAdjustPair1);
+
+/* For lsb_hostpartinfo() call */
+
+    /**
+     * \brief   gets user information about host partitions.
+     */
+    public static class hostPartUserInfo extends Structure {
+        public static class ByReference extends hostPartUserInfo implements Structure.ByReference {}
+        public static class ByValue extends hostPartUserInfo implements Structure.ByValue {}
+        public hostPartUserInfo() {}
+        public hostPartUserInfo(Pointer p) { super(p); read(); }
+
+
+        /**
+         * < The user name or user group name.  See \ref lsb_userinfo  and \ref lsb_usergrpinfo
+         */
+        public String user;
+
+        /**
+         * < The number of shares assigned to the user or user group, as configured in the file lsb.hosts. (See lsb.hosts.)
+         */
+        public int shares;
+
+        /**
+         * < The priority of the user or user group to use the host partition. Bigger values represent higher priorities. Jobs belonging to the user or user group with the highest priority are considered first for dispatch when resources in the host partition are being contended for. In general, a user or user group with more shares, fewer numStartJobs and less histCpuTime has higher priority. The storage for the array of hostPartInfoEnt structures will be reused by the next call.
+         */
+        public float priority;
+
+        /**
+         * < The number of job slots belonging to the user or user group that are running or suspended in the host partition.
+         */
+        public int numStartJobs;
+
+        /**
+         * < The normalized CPU time accumulated in the host partition during the recent period by finished jobs belonging to the user or user group. The period may be configured in the file lsb.params (see lsb.params), with a default value of five (5) hours.
+         */
+        public float histCpuTime;
+
+        /**
+         * < The number of job slots that are reserved for the PEND jobs belonging to the user or user group in the host partition.
+         */
+        public int numReserveJobs;
+
+        /**
+         * < The time unfinished jobs spend  in RUN state
+         */
+        public int runTime;
+
+        /**
+         * < The fairshare adjustment value from the fairshare plugin  (libfairshareadjust.ByReference ). The adjustment is enabled and weighted by setting the value of FAIRSHARE_ADJUSTMENT_FACTOR in lsb.params.
+         */
+        public float shareAdjustment;
+    }
+
+
+
+/* For lsb_hostpartinfo() call */
+
+    /**
+     * \brief  gets information entry about host partitions.
+     */
+    public static class hostPartInfoEnt extends Structure {
+        public static class ByReference extends hostPartInfoEnt implements Structure.ByReference {}
+        public static class ByValue extends hostPartInfoEnt implements Structure.ByValue {}
+        public hostPartInfoEnt() {}
+        public hostPartInfoEnt(Pointer p) { super(p); read(); }
+
+
+        /**
+         * < The name of the host partition
+         */
+        public byte[] hostPart = new byte[MAX_LSB_NAME_LEN];
+
+        /**
+         * < A blank-separated list of names of hosts and host groups which are members of the host partition. The name of a host group has a '/' appended. see \ref lsb_hostgrpinfo.
+         */
+        public String hostList;
+
+        /**
+         * < The number of users in this host partition. i.e., the number of hostPartUserInfo structures.
+         */
+        public int numUsers;
+
+        /**
+         * < An array of hostPartUserInfo structures which hold information on users in this host partition.
+         */
+        public Pointer /* hostPartUserInfo.ByReference */ users;
+    }
+
+
+
+/* Library rappresentation of the share account */
+
+    /**
+     * \brief Library rappresentation of the share account
+     */
+    public static class shareAcctInfoEnt extends Structure {
+        public static class ByReference extends shareAcctInfoEnt implements Structure.ByReference {}
+        public static class ByValue extends shareAcctInfoEnt implements Structure.ByValue {}
+        public shareAcctInfoEnt() {}
+        public shareAcctInfoEnt(Pointer p) { super(p); read(); }
+
+
+        /**
+         * < The user name or user group name. (See \ref lsb_userinfo and \ref lsb_usergrpinfo.)
+         */
+        public String shareAcctPath;
+
+        /**
+         * < The number of shares assigned to  the user or user group, as configured in the file lsb.queues.
+         */
+        public int shares;
+
+        /**
+         * < The priority of the user or user group in the fairshare queue. Larger values represent higher priorities. Job belonging to the user or user group with the highest priority are considered first for dispatch in the fairshare queue. In general, a user or user group with more shares, fewer numStartJobs and less histCpuTime has higher priority.
+         */
+        public float priority;
+
+        /**
+         * < The number of job slots (belonging to the user or user group) that are running or suspended in the fairshare queue.
+         */
+        public int numStartJobs;
+
+        /**
+         * < The normalized CPU time accumulated in the fairshare queue by jobs belonging to the user or user group, over the time period configured in the file lsb.params. The default time period is 5 hours.
+         */
+        public float histCpuTime;
+
+        /**
+         * < The number of job slots that are reserved for the PEND jobs belonging to the user or user group in the host partition.
+         */
+        public int numReserveJobs;
+
+        /**
+         * < The time unfinished jobs spend in the RUN state.
+         */
+        public int runTime;
+
+        /**
+         * < The fairshare adjustment value from the fairshare plugin  (libfairshareadjust.SOEXT). The adjustment is enabled and weighted  by setting the value of FAIRSHARE_ADJUSTMENT_FACTOR in lsb.params.
+         */
+        public float shareAdjustment;
+    }
+
+
+
+/* boundaries and default value used by mbatchd for the maxJobId */
+    public static final int DEF_MAX_JOBID = 999999;
+    public static final int MAX_JOBID_LOW = 999999;
+    public static final int MAX_JOBID_HIGH = (LibLsf.INFINIT_INT - 1);
+
+
+/* default preemption wait time */
+    public static final int DEF_PREEMPTION_WAIT_TIME = 300;
+
+/* default number of hosts specified by -m */
+    public static final int DEF_MAX_ASKED_HOSTS = 512;
+
+/* For lsb_parameterinfo() call */
+
+    /**
+     * \brief The parameterInfo structure contains the following fields:
+     */
+    public static class parameterInfo extends Structure {
+        public static class ByReference extends parameterInfo implements Structure.ByReference {}
+        public static class ByValue extends parameterInfo implements Structure.ByValue {}
+        public parameterInfo() {}
+        public parameterInfo(Pointer p) { super(p); read(); }
+
+
+        /**
+         * < DEFAULT_QUEUE: A blank_separated list of queue names for automatic queue selection.
+         */
+        public String defaultQueues;
+
+        /**
+         * < DEFAULT_HOST_SPEC: The host name or host model name used as the system default for scaling CPULIMIT and RUNLIMIT.
+         */
+        public String defaultHostSpec;
+
+        /**
+         * < MBD_SLEEP_TIME: The interval in seconds at which the mbatchd dispatches jobs.
+         */
+        public int mbatchdInterval;
+
+        /**
+         * < SBD_SLEEP_TIME: The interval in seconds at which the sbatchd suspends or resumes jobs.
+         */
+        public int sbatchdInterval;
+
+        /**
+         * < JOB_ACCEPT_INTERVAL: The interval at which  a host accepts two successive jobs. (In units of SBD_SLEEP_TIME.)
+         */
+        public int jobAcceptInterval;
+
+        /**
+         * < MAX_RETRY: The maximum number of retries for dispatching a job.
+         */
+        public int maxDispRetries;
+
+        /**
+         * < MAX_SBD_FAIL: The maximum number of retries for reaching an sbatchd.
+         */
+        public int maxSbdRetries;
+
+        /**
+         * < PREEM_PERIOD: The interval in seconds for preempting jobs running on the same host.
+         */
+        public int preemptPeriod;
+
+        /**
+         * < CLEAN_PERIOD: The interval in seconds during which finished jobs are kept in core.
+         */
+        public int cleanPeriod;
+
+        /**
+         * < MAX_JOB_NUM: The maximum number of finished jobs that are logged in the current event file.
+         */
+        public int maxNumJobs;
+
+        /**
+         * < HIST_HOURS: The number of hours of resource consumption history used for fair share scheduling and scheduling within a host partition.
+         */
+        public float historyHours;
+
+        /**
+         * < PG_SUSP_IT: The interval a host must be idle before resuming a job suspended for excessive paging.
+         */
+        public int pgSuspendIt;
+
+        /**
+         * < The default project assigned to jobs.
+         */
+        public String defaultProject;
+
+        /**
+         * < Job submission retry interval
+         */
+        public int retryIntvl;
+
+        /**
+         * < For Cray NQS compatiblilty only. Used by LSF to get the NQS queue information
+         */
+        public int nqsQueuesFlags;
+
+        /**
+         * < nqsRequestsFlags
+         */
+        public int nqsRequestsFlags;
+
+        /**
+         * < The maximum number of times to attempt the preexecution command of a job from a remote cluster ( MultiCluster only)
+         */
+        public int maxPreExecRetry;
+
+        /**
+         * < Maximum number of pre-exec retry times for local cluster
+         */
+        public int localMaxPreExecRetry;
+
+        /**
+         * < Event watching Interval in seconds
+         */
+        public int eventWatchTime;
+
+        /**
+         * < Run time weighting factor for fairshare scheduling
+         */
+        public float runTimeFactor;
+
+        /**
+         * < Used for calcultion of the fairshare scheduling formula
+         */
+        public float waitTimeFactor;
+
+        /**
+         * < Job slots weighting factor for fairshare scheduling
+         */
+        public float runJobFactor;
+
+        /**
+         * < Default check interval
+         */
+        public int eEventCheckIntvl;
+
+        /**
+         * < sbatchd report every sbd_sleep_time
+         */
+        public int rusageUpdateRate;
+
+        /**
+         * < sbatchd updates jobs jRusage in mbatchd if more than 10% changes
+         */
+        public int rusageUpdatePercent;
+
+        /**
+         * < Time period to check for reconfig
+         */
+        public int condCheckTime;
+
+        /**
+         * < The maximum number of connections between master and slave batch daemons
+         */
+        public int maxSbdConnections;
+
+        /**
+         * < The interval for rescheduling jobs
+         */
+        public int rschedInterval;
+
+        /**
+         * < Max time mbatchd stays in scheduling routine, after which take a breather
+         */
+        public int maxSchedStay;
+
+        /**
+         * < During which load remains fresh
+         */
+        public int freshPeriod;
+
+        /**
+         * < The preemption behavior, GROUP_MAX, GROUP_JLP, USER_JLP, HOST_JLU,MINI_JOB, LEAST_RUN_TIME
+         */
+        public int preemptFor;
+
+        /**
+         * < Flags whether users can resume their jobs when suspended by the LSF administrator
+         */
+        public int adminSuspend;
+
+        /**
+         * < Flags to enable/disable normal user to create advance reservation
+         */
+        public int userReservation;
+
+        /**
+         * < CPU time weighting factor for fairshare scheduling
+         */
+        public float cpuTimeFactor;
+
+        /**
+         * < The starting month for a fiscal year
+         */
+        public int fyStart;
+
+        /**
+         * < The maximum number of jobs in a job array
+         */
+        public int maxJobArraySize;
+
+        /**
+         * < Replay period for exceptions, in seconds
+         */
+        public NativeLong exceptReplayPeriod;
+
+        /**
+         * < The interval to terminate a job
+         */
+        public int jobTerminateInterval;
+
+        /**
+         * <  User level account mapping for remote jobs is disabled
+         */
+        public int disableUAcctMap;
+
+        /**
+         * < If set to TRUE, Project name for a job will be considerred when doing fairshare scheduling, i.e., as if user has submitted jobs using -G
+         */
+        public int enforceFSProj;
+
+        /**
+         * < Enforces the check to see if the invoker of bsub is in the specifed group when the -P option is used
+         */
+        public int enforceProjCheck;
+
+        /**
+         * < Run time for a job
+         */
+        public int jobRunTimes;
+
+        /**
+         * < Event table Job default interval
+         */
+        public int dbDefaultIntval;
+
+        /**
+         * < Event table Job Host Count
+         */
+        public int dbHjobCountIntval;
+
+        /**
+         * < Event table Job Queue Count
+         */
+        public int dbQjobCountIntval;
+
+        /**
+         * < Event table Job User Count
+         */
+        public int dbUjobCountIntval;
+
+        /**
+         * < Event table Job Resource Interval
+         */
+        public int dbJobResUsageIntval;
+
+        /**
+         * < Event table Resource Load Interval
+         */
+        public int dbLoadIntval;
+
+        /**
+         * < Event table Job Info
+         */
+        public int dbJobInfoIntval;
+
+        /**
+         * < Used with job dependency scheduling
+         */
+        public int jobDepLastSub;
+
+        /**
+         * < Used with job dependency scheduling,  deprecated
+         */
+        public int maxJobNameDep;
+
+        /**
+         * < Select resources to be logged
+         */
+        public String dbSelectLoad;
+
+        /**
+         * < Job synchronizes its group status
+         */
+        public int jobSynJgrp;
+
+        /**
+         * < The batch jobs' temporary output directory
+         */
+        public String pjobSpoolDir;
+
+
+        /**
+         * < Maximal job priority defined for all users
+         */
+        public int maxUserPriority;
+
+        /**
+         * < Job priority is increased by the system dynamically based on waiting time
+         */
+        public int jobPriorityValue;
+
+        /**
+         * < Waiting time to increase Job priority by the system dynamically
+         */
+        public int jobPriorityTime;
+
+        /**
+         * < Enable internal statistical adjustment
+         */
+        public int enableAutoAdjust;
+
+        /**
+         * < Start to autoadjust when the user has  this number of pending jobs
+         */
+        public int autoAdjustAtNumPend;
+
+        /**
+         * < If this number of jobs has been visited skip the user
+         */
+        public float autoAdjustAtPercent;
+
+        /**
+         * <  Static shared resource update interval for the cluster actor
+         */
+        public int sharedResourceUpdFactor;
+
+        /**
+         * < Schedule job based on raw load info
+         */
+        public int scheRawLoad;
+
+        /**
+         * <  The batch jobs' external storage for attached data
+         */
+        public String jobAttaDir;
+
+        /**
+         * < Maximum message number for each job
+         */
+        public int maxJobMsgNum;
+
+        /**
+         * < Maximum attached data size to be transferred for each message
+         */
+        public int maxJobAttaSize;
+
+        /**
+         * < The life time of a child MBD to serve queries in the MT way
+         */
+        public int mbdRefreshTime;
+
+        /**
+         * < The interval of the execution cluster updating the job's resource usage
+         */
+        public int updJobRusageInterval;
+
+        /**
+         * < The account to which all windows workgroup users are to be mapped
+         */
+        public String sysMapAcct;
+
+        /**
+         * < Dispatch delay internal
+         */
+        public int preExecDelay;
+
+        /**
+         * < Update duplicate event interval
+         */
+        public int updEventUpdateInterval;
+
+        /**
+         * < Resources are reserved for parallel jobs on a per-slot basis
+         */
+        public int resourceReservePerSlot;
+
+        /**
+         * < Maximum job id --- read from the lsb.params
+         */
+        public int maxJobId;
+
+        /**
+         * < Define a list of preemptable resource  names
+         */
+        public String preemptResourceList;
+
+        /**
+         * < The preemption wait time
+         */
+        public int preemptionWaitTime;
+
+        /**
+         * < Maximum number of rollover lsb.acct files kept by mbatchd.
+         */
+        public int maxAcctArchiveNum;
+
+        /**
+         * < mbatchd Archive Interval
+         */
+        public int acctArchiveInDays;
+
+        /**
+         * < mbatchd Archive threshold
+         */
+        public int acctArchiveInSize;
+
+        /**
+         * < Committed run time weighting factor
+         */
+        public float committedRunTimeFactor;
+
+        /**
+         * < Enable the use of historical run time in the calculation of fairshare scheduling priority, Disable the use of historical run time in the calculation of fairshare scheduling priority
+         */
+        public int enableHistRunTime;
+
+/*#ifdef PS_SXNQS */
+/**< NQS resource usage update interval */
+/*    public int   nqsUpdateInterval;*/
+/*#endif */
+
+        /**
+         * < Open lease reclaim time
+         */
+        public int mcbOlmReclaimTimeDelay;
+
+        /**
+         * < Enable chunk job dispatch for jobs with CPU limit or run limits
+         */
+        public int chunkJobDuration;
+
+        /**
+         * < The interval for scheduling jobs by scheduler daemon
+         */
+        public int sessionInterval;
+
+        /**
+         * < The number of jobs per user per queue whose pending reason is published at the PEND_REASON_UPDATE_INTERVAL interval
+         */
+        public int publishReasonJobNum;
+
+        /**
+         * < The interval for publishing job pending reason by scheduler daemon
+         */
+        public int publishReasonInterval;
+
+        /**
+         * < Interval(in seconds) of pending reason  publish for all jobs
+         */
+        public int publishReason4AllJobInterval;
+
+        /**
+         * < MC pending reason update interval (0 means no updates)
+         */
+        public int mcUpdPendingReasonInterval;
+
+        /**
+         * < MC pending reason update package size (0 means no limit)
+         */
+        public int mcUpdPendingReasonPkgSize;
+
+        /**
+         * < No preemption if the run time is greater  than the value defined in here
+         */
+        public int noPreemptRunTime;
+
+        /**
+         * < No preemption if the finish time is less than the value defined in here
+         */
+        public int noPreemptFinishTime;
+
+        /**
+         * < mbatchd Archive Time
+         */
+        public String acctArchiveAt;
+
+        /**
+         * < Absolute run limit for job
+         */
+        public int absoluteRunLimit;
+
+        /**
+         * < The job exit rate duration
+         */
+        public int lsbExitRateDuration;
+
+        /**
+         * <  The duration to trigger eadmin
+         */
+        public int lsbTriggerDuration;
+
+        /**
+         * < Maximum time for job information query commands (for example,with bjobs) to wait
+         */
+        public int maxJobinfoQueryPeriod;
+
+        /**
+         * < Job submission retrial interval for client
+         */
+        public int jobSubRetryInterval;
+
+        /**
+         * < System wide max pending jobs
+         */
+        public int pendingJobThreshold;
+
+
+        /**
+         * < Max number of concurrent query
+         */
+        public int maxConcurrentJobQuery;
+
+        /**
+         * < Min event switch time period
+         */
+        public int minSwitchPeriod;
+
+
+        /**
+         * < Condense pending reasons enabled
+         */
+        public int condensePendingReasons;
+
+        /**
+         * < Schedule Parallel jobs based on slots instead of CPUs
+         */
+        public int slotBasedParallelSched;
+
+        /**
+         * < Disable user job movement operations, like btop/bbot.
+         */
+        public int disableUserJobMovement;
+
+        /**
+         * < Detect and report idle jobs only after specified minutes.
+         */
+        public int detectIdleJobAfter;
+        public int useSymbolPriority;
+        /**
+         * < Use symbolic when specifing priority of symphony jobs/
+         * <p/>
+         * /**< Priority rounding for symphony jobs
+         */
+        public int JobPriorityRound;
+
+        /**
+         * < The mapping of the symbolic priority  for symphony jobs
+         */
+        public String priorityMapping;
+
+        /**
+         * < Maximum number of subdirectories under LSB_SHAREDIR/cluster/logdir/info
+         */
+        public int maxInfoDirs;
+
+        /**
+         * < The minimum period of a child MBD to serve queries in the MT way
+         */
+        public int minMbdRefreshTime;
+
+        /**
+         * < Stop asking license to LS not due to lack license
+         */
+        public int enableStopAskingLicenses2LS;
+
+        /**
+         * < Expire time for finished job which will not taken into account when calculating queue fairshare priority
+         */
+        public int expiredTime;
+
+        /**
+         * < MBD child query processes will only run on the following CPUs
+         */
+        public String mbdQueryCPUs;
+
+        /**
+         * < The default application profile assigned to jobs
+         */
+        public String defaultApp;
+
+        /**
+         * < Enable or disable data streaming
+         */
+        public int enableStream;
+
+        /**
+         * < File to which lsbatch data is streamed
+         */
+        public String streamFile;
+
+        /**
+         * < File size in MB to which lsbatch data is streamed
+         */
+        public int streamSize;
+
+        /**
+         * < Sync up host status with master LIM is enabled
+         */
+        public int syncUpHostStatusWithLIM;
+
+        /**
+         * < Project schedulign default SLA
+         */
+        public String defaultSLA;
+
+        /**
+         * < EGO Enabled SLA scheduling timer period
+         */
+        public int slaTimer;
+
+        /**
+         * < EGO Enabled SLA scheduling time to live
+         */
+        public int mbdEgoTtl;
+
+        /**
+         * < EGO Enabled SLA scheduling connection timeout
+         */
+        public int mbdEgoConnTimeout;
+
+        /**
+         * < EGO Enabled SLA scheduling read timeout
+         */
+        public int mbdEgoReadTimeout;
+
+        /**
+         * < EGO Enabled SLA scheduling use MXJ flag
+         */
+        public int mbdUseEgoMXJ;
+
+        /**
+         * < EGO Enabled SLA scheduling reclaim by queue
+         */
+        public int mbdEgoReclaimByQueue;
+
+        /**
+         * < EGO Enabled SLA scheduling default velocity
+         */
+        public int defaultSLAvelocity;
+
+        /**
+         * < Type of host exit rate exception handling types: EXIT_RATE_TYPE
+         */
+        public String exitRateTypes;
+
+        /**
+         * < Type of host exit rate exception handling types: GLOBAL_EXIT_RATE
+         */
+        public float globalJobExitRate;
+
+        /**
+         * < Type of host exit rate exception handling types ENABLE_EXIT_RATE_PER_SLOT
+         */
+        public int enableJobExitRatePerSlot;
+
+        /**
+         * < Performance metrics monitor is enabled  flag
+         */
+        public int enableMetric;
+
+        /**
+         * < Performance metrics monitor sample period flag
+         */
+        public int schMetricsSample;
+
+        /**
+         * < Used to bound: (1) factors, (2) weights, and (3) APS values
+         */
+        public float maxApsValue;
+
+        /**
+         * < Child mbatchd gets updated information about new jobs from the parent mbatchd
+         */
+        public int newjobRefresh;
+
+        /**
+         * < Job type to preempt, PREEMPT_JOBTYPE_BACKFILL, PREEMPT_JOBTYPE_EXCLUSIVE
+         */
+        public int preemptJobType;
+
+        /**
+         * < The default job group assigned to jobs
+         */
+        public String defaultJgrp;
+
+        /**
+         * < Max ratio between run limit and runtime estimation
+         */
+        public int jobRunlimitRatio;
+
+        /**
+         * < Enable the post-execution processing of the job to be included as part of the job flag
+         */
+        public int jobIncludePostproc;
+
+        /**
+         * < Timeout of post-execution processing
+         */
+        public int jobPostprocTimeout;
+
+        /**
+         * < The interval, in seconds, for updating the session scheduler status summary
+         */
+        public int sschedUpdateSummaryInterval;
+
+        /**
+         * < The number of completed tasks for updating the session scheduler status summary
+         */
+        public int sschedUpdateSummaryByTask;
+
+        /**
+         * < The maximum number of times a task can be requeued via requeue exit values
+         */
+        public int sschedRequeueLimit;
+
+        /**
+         * < The maximum number of times a task can be retried after a dispatch error
+         */
+        public int sschedRetryLimit;
+
+        /**
+         * < The maximum number of tasks that can be submitted in one session
+         */
+        public int sschedMaxTasks;
+
+        /**
+         * < The maximum run time of a single task
+         */
+        public int sschedMaxRuntime;
+
+        /**
+         * < The output directory for task accounting files
+         */
+        public String sschedAcctDir;
+
+        /**
+         * < If TRUE enable the job group automatic deletion functionality (default is FALSE).
+         */
+        public int jgrpAutoDel;
+
+        /**
+         * < Maximum number of job preempted times
+         */
+        public int maxJobPreempt;
+
+        /**
+         * < Maximum number of job re-queue times
+         */
+        public int maxJobRequeue;
+
+        /**
+         * < No preempt run time percent
+         */
+        public int noPreemptRunTimePercent;
+
+        /**
+         * < No preempt finish time percent
+         */
+        public int noPreemptFinishTimePercent;
+
+
+        /**
+         * < The reservation request being within JL/U.
+         */
+        public int slotReserveQueueLimit;
+
+        /**
+         * < Job accept limit percentage.
+         */
+        public int maxJobPercentagePerSession;
+
+        /**
+         * < The low priority job will use the slots freed by preempted jobs.
+         */
+        public int useSuspSlots;
+
+
+        /**
+         * < Maximum number of the backup stream.utc files
+         */
+        public int maxStreamFileNum;
+
+        /**
+         * < If enforced only admin can use bkill -r option
+         */
+        public int privilegedUserForceBkill;
+
+        /**
+         * < It controls the remote queue selection flow.
+         */
+        public int mcSchedulingEnhance;
+
+        /**
+         * < It controls update interval of the counters  and other original data in MC implementation
+         */
+        public int mcUpdateInterval;
+
+        /**
+         * < Jobs run on only on hosts belonging to the intersection of the queue the job was submitted to, advance reservation hosts, and any hosts specified by bsub -m at the time of submission.
+         */
+        public int intersectCandidateHosts;
+
+        /**
+         * < Enforces the limitations of a single specified user group.
+         */
+        public int enforceOneUGLimit;
+
+        /**
+         * < Enable or disable logging runtime estimation exceeded event
+         */
+        public int logRuntimeESTExceeded;
+
+        /**
+         * < Compute unit types.
+         */
+        public String computeUnitTypes;
+
+        /**
+         * < Fairshare adjustment weighting factor
+         */
+        public float fairAdjustFactor;
+
+        /**
+         * < abs runtime and cputime for LSF simulator
+         */
+        public int simAbsoluteTime;
+
+        /**
+         * < switch for job exception enhancement
+         */
+        public int extendJobException;
+    }
+
+    /* parameterInfo */
+
+
+/* Bits for preemptFor parameter */
+    public static final int GROUP_MAX = 0x0001;
+    public static final int GROUP_JLP = 0x0002;
+    public static final int USER_JLP = 0x0004;
+    public static final int HOST_JLU = 0x0008;
+
+/* minimum of job */
+    public static final int MINI_JOB = 0x0010;
+
+/* least run time */
+    public static final int LEAST_RUN_TIME = 0x0020;
+
+/* optimal mini job */
+    public static final int OPTIMAL_MINI_JOB = 0x0040;
+
+/* Bits for mcSchedulingEnhance parameter */
+    public static final int RESOURCE_ONLY = 0x0001;
+    public static final int COUNT_PREEMPTABLE = 0x0002;
+    public static final int HIGH_QUEUE_PRIORITY = 0x0004;
+    public static final int PREEMPTABLE_QUEUE_PRIORITY = 0x0008;
+    public static final int PENDING_WHEN_NOSLOTS = 0x0010;
+
+/* options for bcaladd, bcalmod, bcaldel */
+    public static final int CAL_FORCE = 0x0001;
+
+/* Bits for preemptJobType parameter,
+*  used to enable backfill and exclusive
+*  preemption */
+    public static final int PREEMPT_JOBTYPE_EXCLUSIVE = 0x0001;
+    public static final int PREEMPT_JOBTYPE_BACKFILL = 0x0002;
+
+/* For lsb_calendarinfo() call */
+
+    /**
+     * \brief  calendar Information Entry.
+     */
+    public static class calendarInfoEnt extends Structure {
+        public static class ByReference extends calendarInfoEnt implements Structure.ByReference {}
+        public static class ByValue extends calendarInfoEnt implements Structure.ByValue {}
+        public calendarInfoEnt() {}
+        public calendarInfoEnt(Pointer p) { super(p); read(); }
+
+
+        /**
+         * < A pointer to the name of the calendar.
+         */
+        public String name;
+
+        /**
+         * < A description string associated with the calendar.
+         */
+        public String desc;
+
+        /**
+         * < Calendar Expression
+         */
+        public String calExpr;
+
+        /**
+         * < User name
+         */
+        public String userName;
+
+        /**
+         * < Calendar status
+         */
+        public int status;
+
+        /**
+         * < For future use
+         */
+        public int options;
+
+        /**
+         * < Last time event of the calendar
+         */
+        public int lastDay;
+
+        /**
+         * < Next time event of the calendar
+         */
+        public int nextDay;
+
+        /**
+         * < Create Time
+         */
+        public NativeLong creatTime;
+
+        /**
+         * < Last Modify Time
+         */
+        public NativeLong lastModifyTime;
+
+        /**
+         * < Type of calendar, etc.
+         */
+        public int flags;
+    }
+
+
+
+    public static final int ALL_CALENDARS = 0x1;
+
+    public static final int EVE_HIST = 0x1;
+    public static final int EVENT_ACTIVE = 1;
+    public static final int EVENT_INACTIVE = 2;
+    public static final int EVENT_REJECT = 3;
+
+    public static final int EVENT_TYPE_UNKNOWN = 0;
+    public static final int EVENT_TYPE_LATCHED = 1;
+    public static final int EVENT_TYPE_PULSEALL = 2;
+    public static final int EVENT_TYPE_PULSE = 3;
+    public static final int EVENT_TYPE_EXCLUSIVE = 4;
+
+/* define event types */
+    public static final int EV_UNDEF = 0;
+    public static final int EV_FILE = 1;
+    public static final int EV_EXCEPT = 2;
+    public static final int EV_USER = 3;
+
+    public static class loadInfoEnt extends Structure {
+        public static class ByReference extends loadInfoEnt implements Structure.ByReference {}
+        public static class ByValue extends loadInfoEnt implements Structure.ByValue {}
+        public loadInfoEnt() {}
+        public loadInfoEnt(Pointer p) { super(p); read(); }
+
+        public String hostName;
+        public int status;
+        public FloatByReference load;
+    }
+
+
+
+    public static class queuePairEnt extends Structure {
+        public static class ByReference extends queuePairEnt implements Structure.ByReference {}
+        public static class ByValue extends queuePairEnt implements Structure.ByValue {}
+        public queuePairEnt() {}
+        public queuePairEnt(Pointer p) { super(p); read(); }
+
+        public String local;
+        public String remote;
+        public int send;
+        public int status;
+    }
+
+
+
+    public static class rmbCluAppEnt extends Structure {
+        public static class ByReference extends rmbCluAppEnt implements Structure.ByReference {}
+        public static class ByValue extends rmbCluAppEnt implements Structure.ByValue {}
+        public rmbCluAppEnt() {}
+        public rmbCluAppEnt(Pointer p) { super(p); read(); }
+
+        public String name;
+        public String description;
+    }
+
+
+
+/* define 'cluster status' in lease model
+*  for bclusters command
+ */
+
+
+/* disconnection */
+    public static final int LEASE_CLU_STAT_DISC = 1;
+
+/* policy is exchanged but no lease is signed */
+    public static final int LEASE_CLU_STAT_CONN = 2;
+
+/* there are leases signed between two clusters */
+    public static final int LEASE_CLU_STAT_OK = 3;
+    public static final int LEASE_CLU_STAT_NUMBER = 3;
+/* consumer cluster status in lease model */
+
+    public static class consumerCluEnt extends Structure {
+        public static class ByReference extends consumerCluEnt implements Structure.ByReference {}
+        public static class ByValue extends consumerCluEnt implements Structure.ByValue {}
+        public consumerCluEnt() {}
+        public consumerCluEnt(Pointer p) { super(p); read(); }
+
+
+/* consumer cluster name */
+        public String cluName;
+
+/* cluster status, Ref- 'cluster status' definitions */
+        public int status;
+    }
+
+
+/* provider cluster status in lease model */
+
+    public static class providerCluEnt extends Structure {
+        public static class ByReference extends providerCluEnt implements Structure.ByReference {}
+        public static class ByValue extends providerCluEnt implements Structure.ByValue {}
+        public providerCluEnt() {}
+        public providerCluEnt(Pointer p) { super(p); read(); }
+
+
+/* provider cluster name */
+        public String cluName;
+
+/* cluster status, Ref- 'cluster status' definitions */
+        public int status;
+    }
+
+
+/* for remote batch model, its definition is same as  clusterInfoEnt*/
+
+    public static class rmbCluInfoEnt extends Structure {
+        public static class ByReference extends rmbCluInfoEnt implements Structure.ByReference {}
+        public static class ByValue extends rmbCluInfoEnt implements Structure.ByValue {}
+        public rmbCluInfoEnt() {}
+        public rmbCluInfoEnt(Pointer p) { super(p); read(); }
+
+        public String cluster;
+        public int numPairs;
+        public Pointer /* queuePairEnt.ByReference */ queues;
+        public int numApps;
+        public Pointer /* rmbCluAppEnt.ByReference */ apps;
+    }
+
+
+
+/* for leasing model */
+
+    public static class leaseCluInfoEnt extends Structure {
+        public static class ByReference extends leaseCluInfoEnt implements Structure.ByReference {}
+        public static class ByValue extends leaseCluInfoEnt implements Structure.ByValue {}
+        public leaseCluInfoEnt() {}
+        public leaseCluInfoEnt(Pointer p) { super(p); read(); }
+
+
+/* 1, import from all if "allremote" defined in lease queue*/
+        public int flags;
+
+/* the array size of consumer cluster array */
+        public int numConsumer;
+
+/* the consumer cluster array */
+        public Pointer /* consumerCluEnt.ByReference */ consumerClus;
+
+/* the array size of provider cluster array */
+        public int numProvider;
+
+/* the provider cluster array */
+        public Pointer /* providerCluEnt.ByReference */ providerClus;
+    }
+
+
+
+/* This is the old data structure, we
+*  leave it here to keep backward compatibility.
+*  It's definition is same as structure rmbCluInfoEnt.
+*  It is to transfer cluster status between mbatchd with
+*  old(4.x) bclusters command and old API-lsb_clusterinfo()
+ */
+
+    public static class clusterInfoEnt extends Structure {
+        public static class ByReference extends clusterInfoEnt implements Structure.ByReference {}
+        public static class ByValue extends clusterInfoEnt implements Structure.ByValue {}
+        public clusterInfoEnt() {}
+        public clusterInfoEnt(Pointer p) { super(p); read(); }
+
+        public String cluster;
+        public int numPairs;
+        public Pointer /* queuePairEnt.ByReference */ queues;
+        public int numApps;
+        public Pointer /* rmbCluAppEnt.ByReference */ apps;
+    }
+
+
+/* the new data structure to transfer cluster status between mbatchd with
+*  new(5.0) bclusters command and new API-lsb_clusterinfoEx()
+ */
+
+    public static class clusterInfoEntEx extends Structure {
+        public static class ByReference extends clusterInfoEntEx implements Structure.ByReference {}
+        public static class ByValue extends clusterInfoEntEx implements Structure.ByValue {}
+        public clusterInfoEntEx() {}
+        public clusterInfoEntEx(Pointer p) { super(p); read(); }
+
+
+/* cluster status related to remote batch*/
+        public rmbCluInfoEnt.ByReference rmbCluInfo;
+
+/* cluster status related to resource lease*/
+        public leaseCluInfoEnt leaseCluInfo;
+    }
+
+
+
+    public static class eventInfoEnt extends Structure {
+        public static class ByReference extends eventInfoEnt implements Structure.ByReference {}
+        public static class ByValue extends eventInfoEnt implements Structure.ByValue {}
+        public eventInfoEnt() {}
+        public eventInfoEnt(Pointer p) { super(p); read(); }
+
+
+/* name of event */
+        public String name;
+
+/* one of ACTIVE or INACTIVE */
+        public int status;
+
+/* one of LATCHED, PULSE and EXCLUSIVE */
+        public int type;
+
+/* one of FILE, ALARM, USER */
+        public int eType;
+
+/* user who created the event */
+        public String userName;
+
+/* event's attributes sent back from eeventd */
+        public String attributes;
+
+/* number of expression dependent on the event */
+        public int numDependents;
+
+/* last time when eeventd sent back message */
+        public NativeLong updateTime;
+
+/* last dispatched job dependent on the event */
+        public long lastDisJob;
+
+/* the time when the last job was dispatched */
+        public NativeLong lastDisTime;
+    }
+
+
+    public static final int ALL_EVENTS = 0x01;
+
+    /**
+     *  \addtogroup groupinfo_define groupinfo_define
+     *  define options for \ref lsb_usergrpinfo and \ref lsb_hostgrpinfo calls
+     */
+
+    /**
+     * < User group
+     */
+    public static final int USER_GRP = 0x1;
+
+    /**
+     * < Host group
+     */
+    public static final int HOST_GRP = 0x2;
+
+    /**
+     * < Host part group
+     */
+    public static final int HPART_HGRP = 0x4;
+    /**
+     *  \defgroup group_membership_option group_membership_option
+     *  \ingroup groupinfo_define
+     *  group membership options
+     */
+
+    /**
+     * < Expand the group membership recursively. That is, if a member of a group is itself a group, give the names of its members recursively, rather than its name, which is the default.
+     */
+    public static final int GRP_RECURSIVE = 0x8;
+
+    /**
+     * < Get membership of all groups.
+     */
+    public static final int GRP_ALL = 0x10;
+
+    /**
+     * < NQSQ_GRP
+     */
+    public static final int NQSQ_GRP = 0x20;
+
+    /**
+     * < Group shares
+     */
+    public static final int GRP_SHARES = 0x40;
+
+    /**
+     * < Dynamic group
+     */
+    public static final int DYNAMIC_GRP = 0x800;
+
+    /**
+     * < Group cu
+     */
+    public static final int GRP_CU = 0x1000;
+
+    /**
+     * \brief Structure for representing the shares assigned to a user group.
+     */
+    public static class userShares extends Structure {
+        public static class ByReference extends userShares implements Structure.ByReference {}
+        public static class ByValue extends userShares implements Structure.ByValue {}
+        public userShares() {}
+        public userShares(Pointer p) { super(p); read(); }
+
+
+        /**
+         * < This can be a user or a keyword "default" or others
+         */
+        public String user;
+
+        /**
+         * < The number of shares assigned to the user
+         */
+        public int shares;
+    }
+
+
+
+
+    /**
+     * \brief  group information entry.
+     */
+    public static class groupInfoEnt extends Structure {
+        public static class ByReference extends groupInfoEnt implements Structure.ByReference {}
+        public static class ByValue extends groupInfoEnt implements Structure.ByValue {}
+        public groupInfoEnt() {}
+        public groupInfoEnt(Pointer p) { super(p); read(); }
+
+
+        /**
+         * < Group name
+         */
+        public String group;
+
+        /**
+         * < ASCII list of member names
+         */
+        public String memberList;
+
+        /**
+         * < ASCII list of admin member names
+         */
+        public String adminMemberList;
+
+        /**
+         * < The number of users with shares
+         */
+        public int numUserShares;
+
+        /**
+         * < The user shares rappresentation
+         */
+        public Pointer /* userShares.ByReference */ userShares;
+
+        /**
+         *  \addtogroup group_define group_define
+         *   group define statements
+         */
+
+        /**
+         * < Group output is in regular (uncondensed) format.
+         */
+        public static final int GRP_NO_CONDENSE_OUTPUT = 0x01;
+
+        /**
+         * < Group output is in condensed format.
+         */
+        public static final int GRP_CONDENSE_OUTPUT = 0x02;
+
+        /**
+         * < Group have regular expresion
+         */
+        public static final int GRP_HAVE_REG_EXP = 0x04;
+
+        /**
+         * < Group is a service class.
+         */
+        public static final int GRP_SERVICE_CLASS = 0x08;
+
+        /**
+         * < Group is a compute unit.
+         */
+        public static final int GRP_IS_CU = 0x10;
+
+        /**
+         * < Options.see \ref group_define
+         */
+        public int options;
+
+        /**
+         * < Host membership pattern
+         */
+        public String pattern;
+
+        /**
+         * < Negation membership pattern
+         */
+        public String neg_pattern;
+
+        /**
+         * < Compute unit type
+         */
+        public int cu_type;
+    }
+
+
+
+    /**
+     * \brief  run job request.
+     */
+    public static class runJobRequest extends Structure {
+        public static class ByReference extends runJobRequest implements Structure.ByReference {}
+        public static class ByValue extends runJobRequest implements Structure.ByValue {}
+        public runJobRequest() {}
+        public runJobRequest(Pointer p) { super(p); read(); }
+
+
+        /**
+         * < Jobid of the requested job
+         */
+        public long jobId;
+
+        /**
+         * < The number of hosts
+         */
+        public int numHosts;
+
+        /**
+         * < Vector of hostnames
+         */
+        public Pointer hostname;
+        /**
+         *  \addtogroup runjob_option runjob_option
+         *  Options used for lsb_runjob:
+         */
+
+
+        /**
+         * < Normal jobs
+         */
+        public static final int RUNJOB_OPT_NORMAL = 0x01;
+
+        /**
+         * < Nostop jobs
+         */
+        public static final int RUNJOB_OPT_NOSTOP = 0x02;
+
+        /**
+         * < Pending jobs only, no finished jobs
+         */
+        public static final int RUNJOB_OPT_PENDONLY = 0x04;
+
+        /**
+         * < Check point job only, from beginning
+         */
+        public static final int RUNJOB_OPT_FROM_BEGIN = 0x08;
+
+        /**
+         * < brun to use free CPUs only
+         */
+        public static final int RUNJOB_OPT_FREE = 0x10;
+
+        /**
+         * < brun ignoring rusage
+         */
+        public static final int RUNJOB_OPT_IGNORE_RUSAGE = 0x20;
+
+        /**
+         * < Run job request options, see \ref runjob_option
+         */
+        public int options;
+
+        /**
+         * < Vector of number of slots per host
+         */
+        public IntByReference slots;
+    }
+
+
+
+    /**
+     *  \addtogroup external_msg_processing external_msg_processing
+     *  options for \ref lsb_readjobmsg call
+     */
+
+    /**
+     *  \defgroup external_msg_post external_msg_post
+     *  options specifying if the message has an attachment to be posted
+     */
+
+    /**
+     * < Post the external job message. There  is no attached data file.
+     */
+    public static final int EXT_MSG_POST = 0x01;
+
+    /**
+     * < Post the external job message and data file posted to the job.
+     */
+    public static final int EXT_ATTA_POST = 0x02;
+
+    /**
+     * <Read the external job message. There is no attached data file.
+     */
+    public static final int EXT_MSG_READ = 0x04;
+
+    /**
+     * < Read the external job message and data file posted to the job.If there is no data file attached, the error message "The attached data of the message is not available" is displayed, and the external job message is displayed.
+     */
+    public static final int EXT_ATTA_READ = 0x08;
+
+    /**
+     * < Replay the external message
+     */
+    public static final int EXT_MSG_REPLAY = 0x10;
+
+    /**
+     * < Post the external job noevent message
+     */
+    public static final int EXT_MSG_POST_NOEVENT = 0x20;
+
+
+    /**
+     * \brief structure jobExternalMsgReq contains the information required to
+     * define an external message of a job.
+     */
+    public static class jobExternalMsgReq extends Structure {
+        public static class ByReference extends jobExternalMsgReq implements Structure.ByReference {}
+        public static class ByValue extends jobExternalMsgReq implements Structure.ByValue {}
+        public jobExternalMsgReq() {}
+        public jobExternalMsgReq(Pointer p) { super(p); read(); }
+
+
+        /**
+         * < Specifies if the message has an attachment to be read.<lsf/lsbatch.h> defines the following flags constructed from bits. These flags correspond to options.\n EXT_MSG_READ\n Read the external job message. There is no attached data file.\n EXT_ATTA_READ\n Read the external job message and data file posted to the job.\n If there is no data file attached, the error message "The attached data of the message is not available" is displayed, and the external job  message is displayed.
+         */
+        public int options;
+
+        /**
+         * < The system generated job Id of the job.
+         */
+        public long jobId;
+
+        /**
+         * < The name of the job if jobId is undefined (<=0)
+         */
+        public String jobName;
+
+        /**
+         * < The message index. A job can have more than one message. Use msgIdx in an array to index messages.
+         */
+        public int msgIdx;
+
+        /**
+         * < Text description of the msg
+         */
+        public String desc;
+
+        /**
+         * < The userId of the author of the message.
+         */
+        public int userId;
+
+        /**
+         * < The size of the data file. If no data file is attached, the size is 0.
+         */
+        public NativeLong dataSize;
+
+        /**
+         * < The time the author posted the message.
+         */
+        public NativeLong postTime;
+
+        /**
+         * < The author of the message.
+         */
+        public String userName;
+    }
+
+
+
+    /**
+     *  \addtogroup ext_data_status ext_data_status
+     */
+
+    /**
+     * < Transferring the message's data file.
+     */
+    public static final int EXT_DATA_UNKNOWN = 0;
+
+    /**
+     * < The message does not have an attached  data file.
+     */
+    public static final int EXT_DATA_NOEXIST = 1;
+
+    /**
+     * < The message's data file is available.
+     */
+    public static final int EXT_DATA_AVAIL = 2;
+
+    /**
+     * < The message's data file is corrupt.
+     */
+    public static final int EXT_DATA_UNAVAIL = 3;
+
+    /**
+     * \brief structure jobExternalMsgReply contains the information required to
+     * define an external message reply.
+     */
+    public static class jobExternalMsgReply extends Structure {
+        public static class ByReference extends jobExternalMsgReply implements Structure.ByReference {}
+        public static class ByValue extends jobExternalMsgReply implements Structure.ByValue {}
+        public jobExternalMsgReply() {}
+        public jobExternalMsgReply(Pointer p) { super(p); read(); }
+
+
+        /**
+         * < The system generated job Id of the job associated with the message.
+         */
+        public long jobId;
+
+        /**
+         * < The message index. A job can have more than one message. Use msgIdx in an array to index messages.
+         */
+        public int msgIdx;
+
+        /**
+         * < The message you want to read.
+         */
+        public String desc;
+
+        /**
+         * < The user Id of the author of the message.
+         */
+        public int userId;
+
+        /**
+         * < The size of the data file attached. If no data file is attached, the size is 0.
+         */
+        public NativeLong dataSize;
+
+        /**
+         * < The time the message was posted.
+         */
+        public NativeLong postTime;
+
+        /**
+         * < The status of the attached data file.  The status of the data file can be one of the following:\n EXT_DATA_UNKNOWN\n Transferring the message's data file.\n EXT_DATA_NOEXIST\n The message does not have an attached data file.\n EXT_DATA_AVAIL\n The message's data file is available. \n EXT_DATA_UNAVAIL\n The message's data file is corrupt.
+         */
+        public int dataStatus;
+
+        /**
+         * < The author of the msg
+         */
+        public String userName;
+    }
+
+
+
+
+    /**
+     * Data structures representing the symphony job status update request.
+     */
+    public static class symJobInfo extends Structure {
+        public static class ByReference extends symJobInfo implements Structure.ByReference {}
+        public static class ByValue extends symJobInfo implements Structure.ByValue {}
+        public symJobInfo() {}
+        public symJobInfo(Pointer p) { super(p); read(); }
+
+
+/* the service parititon that SSM works for */
+        public String partition;
+
+/* the priority of the symphony job */
+        public int priority;
+
+/* the full name that indicates the job relationship */
+        public String jobFullName;
+
+/* the auxiliary description to help updating command info */
+        public String auxCmdDesc;
+
+/* the auxiliary description to help updating job description info */
+        public String auxJobDesc;
+    }
+
+
+
+    public static class symJobStatus extends Structure {
+        public static class ByReference extends symJobStatus implements Structure.ByReference {}
+        public static class ByValue extends symJobStatus implements Structure.ByValue {}
+        public symJobStatus() {}
+        public symJobStatus(Pointer p) { super(p); read(); }
+
+
+/* text description of the symphony job status */
+        public String desc;
+    }
+
+
+
+    public static class symJobProgress extends Structure {
+        public static class ByReference extends symJobProgress implements Structure.ByReference {}
+        public static class ByValue extends symJobProgress implements Structure.ByValue {}
+        public symJobProgress() {}
+        public symJobProgress(Pointer p) { super(p); read(); }
+
+
+/* text description of the symphony job progress */
+        public String desc;
+    }
+
+
+
+
+    public static class symJobStatusUpdateReq extends Structure {
+        public static class ByReference extends symJobStatusUpdateReq implements Structure.ByReference {}
+        public static class ByValue extends symJobStatusUpdateReq implements Structure.ByValue {}
+        public symJobStatusUpdateReq() {}
+        public symJobStatusUpdateReq(Pointer p) { super(p); read(); }
+
+
+/* the job to be update info into MBD */
+        public long jobId;
+
+        public static final int SYM_JOB_UPDATE_NONE = 0x0;
+        public static final int SYM_JOB_UPDATE_INFO = 0x1;
+        public static final int SYM_JOB_UPDATE_STATUS = 0x2;
+        public static final int SYM_JOB_UPDATE_PROGRESS = 0x4;
+
+/* the option to update the info */
+        public int bitOption;
+        public symJobInfo info;
+        public int numOfJobStatus;
+        public Pointer /* symJobStatus.ByReference */ status;
+        public symJobProgress progress;
+    }
+
+
+
+    public static class symJobStatusUpdateReqArray extends Structure {
+        public static class ByReference extends symJobStatusUpdateReqArray implements Structure.ByReference {}
+        public static class ByValue extends symJobStatusUpdateReqArray implements Structure.ByValue {}
+        public symJobStatusUpdateReqArray() {}
+        public symJobStatusUpdateReqArray(Pointer p) { super(p); read(); }
+
+        public int numOfJobReq;
+        public Pointer /* symJobStatusUpdateReq.ByReference */ symJobReqs;
+    }
+
+
+
+
+    /**
+     * Data structures representing the symphony job status update reply.
+     */
+
+    public static class symJobUpdateAck extends Structure {
+        public static class ByReference extends symJobUpdateAck implements Structure.ByReference {}
+        public static class ByValue extends symJobUpdateAck implements Structure.ByValue {}
+        public symJobUpdateAck() {}
+        public symJobUpdateAck(Pointer p) { super(p); read(); }
+
+        public static int SYM_UPDATE_ACK_OK = 0;
+        public static final int SYM_UPDATE_ACK_ERR = 1;
+        public int ackCode;
+
+/* text description of job info update acknowledgement */
+        public String desc;
+    }
+
+
+
+    public static class symJobStatusUpdateReply extends Structure {
+        public static class ByReference extends symJobStatusUpdateReply implements Structure.ByReference {}
+        public static class ByValue extends symJobStatusUpdateReply implements Structure.ByValue {}
+        public symJobStatusUpdateReply() {}
+        public symJobStatusUpdateReply(Pointer p) { super(p); read(); }
+
+
+/* the job to be update info into MBD */
+        public long jobId;
+        public static final int SYM_UPDATE_INFO_IDX = 0;
+        public static final int SYM_UPDATE_STATUS_IDX = 1;
+        public static final int SYM_UPDATE_PROGRESS_IDX = 2;
+        public static final int NUM_SYM_UPDATE_ACK = 3;
+        public symJobUpdateAck[] acks = new symJobUpdateAck[NUM_SYM_UPDATE_ACK];
+    }
+
+
+
+    public static class symJobStatusUpdateReplyArray extends Structure {
+        public static class ByReference extends symJobStatusUpdateReplyArray implements Structure.ByReference {}
+        public static class ByValue extends symJobStatusUpdateReplyArray implements Structure.ByValue {}
+        public symJobStatusUpdateReplyArray() {}
+        public symJobStatusUpdateReplyArray(Pointer p) { super(p); read(); }
+
+        public int numOfJobReply;
+        public Pointer /* symJobStatusUpdateReply.ByReference */ symJobReplys;
+    }
+
+
+
+
+/* Data structure representing the job array requeue operation.
+*  o jobId is the Lsbatch id of the job array to be requeued
+*  o status is the desired requeue status of the job, by default
+*    it is JOB_STAT_PEND, or user specified JOB_STAT_PSUSP
+*  o options specifies the status of the array elements that have
+*    to be requeued.
+*
+*  The function that operates on the data is lsb_requeuejob()
+ */
+
+    /**
+     *  \addtogroup requeuejob_options requeuejob_options
+     *  define statements used by \ref lsb_requeuejob.
+     */
+
+    /**
+     * < Requeues jobs that have finished running. Jobs that have exited are not re-run. Equivalent to brequeue -d command line option.
+     */
+    public static final int REQUEUE_DONE = 0x1;
+
+    /**
+     * < Requeues jobs that have exited. Finished jobs are not re-run. Equivalent to brequeue -e command line option.
+     */
+    public static final int REQUEUE_EXIT = 0x2;
+
+    /**
+     * < Requeues running jobs and puts them in PEND state. Equivalent to brequeue -r command line option.
+     */
+    public static final int REQUEUE_RUN = 0x4;
+
+    /**
+     * \brief  requeued job
+     */
+    public static class jobrequeue extends Structure {
+        public static class ByReference extends jobrequeue implements Structure.ByReference {}
+        public static class ByValue extends jobrequeue implements Structure.ByValue {}
+        public jobrequeue() {}
+        public jobrequeue(Pointer p) { super(p); read(); }
+
+
+        /**
+         * < Specifies the jobid of a single job or an array of jobs.
+         */
+        public long jobId;
+
+        /**
+         * < Specifies the lsbatch status of the requeued job after it has been requeued. The job status can be JOB_STAT_PEND or JOB_STATE_PSUSP. The default status is JOB_STAT_PEND.
+         */
+        public int status;
+
+        /**
+         * < Specifies the array elements to be requeued.  see \ref requeuejob_options
+         */
+        public int options;
+    }
+
+
+
+    public static class requeueEStruct extends Structure {
+        public static class ByReference extends requeueEStruct implements Structure.ByReference {}
+        public static class ByValue extends requeueEStruct implements Structure.ByValue {}
+        public requeueEStruct() {}
+        public requeueEStruct(Pointer p) { super(p); read(); }
+
+
+/* requeue type: normal, exclude, other, prefer_other, etc. */
+        public int type;
+
+/* requeue type: normal - as in 2.2 */
+        public static final int RQE_NORMAL = 0;
+
+/* requeue type: exclude */
+        public static final int RQE_EXCLUDE = 1;
+
+/* indicate the end of the list */
+        public static final int RQE_END = 255;
+
+/* requeue exit value */
+        public int value;
+
+/* requeue interval */
+        public int interval;
+    }
+
+
+
+    public static class requeue extends Structure {
+        public static class ByReference extends requeue implements Structure.ByReference {}
+        public static class ByValue extends requeue implements Structure.ByValue {}
+        public requeue() {}
+        public requeue(Pointer p) { super(p); read(); }
+
+        public int numReqValues;
+        public Pointer /* requeueEStruct.ByReference */ reqValues;
+    }
+
+
+
+/* The Service Level Agreement in LSF
+ */
+
+
+/* This is the library representation of the
+*  service class.
+ */
+
+    public static class serviceClass extends Structure {
+        public static class ByReference extends serviceClass implements Structure.ByReference {}
+        public static class ByValue extends serviceClass implements Structure.ByValue {}
+        public serviceClass() {}
+        public serviceClass(Pointer p) { super(p); read(); }
+
+
+/* SLA name */
+        public String name;
+
+/* SLA priority */
+        public float priority;
+
+/* The number of goals */
+        public int ngoals;
+
+/* The array of goals */
+        public Pointer /* objective.ByReference */ goals;
+
+/* Users allowed to use the SLA */
+        public String userGroups;
+
+/* SLA description */
+        public String description;
+
+/* SLA control action */
+        public String controlAction;
+
+/* Finished jobs per CLEAN_PERIOD */
+        public float throughput;
+
+/* Job counters */
+        public int[] counters = new int[NUM_JGRP_COUNTERS + 1];
+
+/* project scheduling enabled sla */
+        public String consumer;
+
+/* SLA EGO control parameters */
+        public slaControl.ByReference ctrl;
+
+/* SLA EGO control parameters */
+        public slaControlExt.ByReference ctrlExt;
+    }
+
+
+
+/* This is the library representation of the
+*  Service Level Objective.
+ */
+
+    public static final int GOAL_WINDOW_OPEN = 0x1;
+    public static final int GOAL_WINDOW_CLOSED = 0x2;
+    public static final int GOAL_ONTIME = 0x4;
+    public static final int GOAL_DELAYED = 0x8;
+    public static final int GOAL_DISABLED = 0x10;
+
+/* Enumerate all the possible performance goals
+*  for a service class.
+ */
+
+    public static interface objectives {
+        public static int GOAL_DEADLINE = 0;
+        public static int GOAL_VELOCITY = 1;
+        public static int GOAL_THROUGHPUT = 2;
+    }
+
+
+
+/* The objective of a goal, also called SLO, is represented
+*  by this data structure.
+ */
+
+    public static class objective extends Structure {
+        public static class ByReference extends objective implements Structure.ByReference {}
+        public static class ByValue extends objective implements Structure.ByValue {}
+        public objective() {}
+        public objective(Pointer p) { super(p); read(); }
+
+
+/* goal specs from lsb.serviceclasses */
+        public String spec;
+
+/* goal type */
+        public int type;
+
+/* the state of the goal OnTime || Delayed */
+        public int state;
+
+/* the configured value */
+        public int goal;
+
+/* the actual value */
+        public int actual;
+
+/* the optimum value */
+        public int optimum;
+
+/* the minimum value */
+        public int minimum;
+    }
+
+
+
+/* Control parameters for SLA management of hosts belonging
+*  to the EGO cluster. The control parameters are for each
+*  SLA that gets its hosts from EGO.
+ */
+
+    public static class slaControl extends Structure {
+        public static class ByReference extends slaControl implements Structure.ByReference {}
+        public static class ByValue extends slaControl implements Structure.ByValue {}
+        public slaControl() {}
+        public slaControl(Pointer p) { super(p); read(); }
+
+
+/* sla name */
+        public String sla;
+
+/* EGO consumer the sla is mapped to */
+        public String consumer;
+
+/* timeout for returning hosts to EGO */
+        public int maxHostIdleTime;
+
+/* timeout left before EGO forcefully reclaims */
+        public int recallTimeout;
+
+/* number of hosts beign recalled */
+        public int numHostRecalled;
+
+/* EGO resource requirement */
+        public String egoResReq;
+    }
+
+
+
+    public static class slaControlExt extends Structure {
+        public static class ByReference extends slaControlExt implements Structure.ByReference {}
+        public static class ByValue extends slaControlExt implements Structure.ByValue {}
+        public slaControlExt() {}
+        public slaControlExt(Pointer p) { super(p); read(); }
+
+
+/* whether exclusive allocation */
+        public int allocflags;
+
+/* tile parameter */
+        public int tile;
+    }
+
+
+
+/* Application Encapsulation in LSF
+*
+*  This is the library representation of the
+*  application.
+ */
+
+    public static class appInfoEnt extends Structure {
+        public static class ByReference extends appInfoEnt implements Structure.ByReference {}
+        public static class ByValue extends appInfoEnt implements Structure.ByValue {}
+        public appInfoEnt() {}
+        public appInfoEnt(Pointer p) { super(p); read(); }
+
+
+/* app name */
+        public String name;
+
+/* app description */
+        public String description;
+
+/* num of total jobs */
+        public int numJobs;
+
+/* num of pending slots */
+        public int numPEND;
+
+/* num of running slots */
+        public int numRUN;
+
+/* num of suspend slots */
+        public int numSSUSP;
+
+/* num of ususp slots */
+        public int numUSUSP;
+
+/* reserved job slots */
+        public int numRESERVE;
+
+/* app attributes */
+        public int aAttrib;
+
+/* number of jobs in one chunk */
+        public int chunkJobSize;
+
+/* requeue exit values */
+        public String requeueEValues;
+
+/* success exit values */
+        public String successEValues;
+
+/* app pre execution */
+        public String preCmd;
+
+/* app post execution */
+        public String postCmd;
+
+/* Job starter command(s) */
+        public String jobStarter;
+
+/* suspend action command */
+        public String suspendActCmd;
+
+/* resume action command */
+        public String resumeActCmd;
+
+/* terimate action command */
+        public String terminateActCmd;
+
+/*memory limit level type */
+        public int memLimitType;
+
+/* LSF resource limits (soft)*/
+        public int[] defLimits = new int[LibLsf.LSF_RLIM_NLIMITS];
+
+/* host spec from CPULIMIT or  RUNLIMIT */
+        public String hostSpec;
+
+/* resource requirement string */
+        public String resReq;
+
+/* maximal processor limit */
+        public int maxProcLimit;
+
+/* default processor limit */
+        public int defProcLimit;
+
+/* minimal processor limit */
+        public int minProcLimit;
+
+/* estimated run time */
+        public int runTime;
+
+/* include postproc as part of job */
+        public int jobIncludePostProc;
+
+/* time window for postproc */
+        public int jobPostProcTimeOut;
+
+/* remote task gone action */
+        public String rTaskGoneAction;
+
+/* pathname of pjob env script */
+        public String djobEnvScript;
+
+/* DJOB rusage interval */
+        public int djobRuInterval;
+
+/* DJOB heartbeat interval */
+        public int djobHbInterval;
+
+/* DJOB communication fail action */
+        public String djobCommfailAction;
+
+/* disable Distributed Application Framework */
+        public int djobDisabled;
+
+/* grace period (in seconds) before terminating tasks when a job shrinks*/
+        public int djobResizeGracePeriod;
+
+/* chkpnt directory */
+        public String chkpntDir;
+
+/* chlpnt method */
+        public String chkpntMethod;
+
+/* chkpnt period */
+        public int chkpntPeriod;
+
+/* initial chkpnt period */
+        public int initChkpntPeriod;
+
+/* migration  threshold */
+        public int migThreshold;
+
+/* maximum number of job preempted times */
+        public int maxJobPreempt;
+
+/* maximum number of pre-exec retry times */
+        public int maxPreExecRetry;
+
+/* maximum number of pre-exec retry times for local cluster */
+        public int localMaxPreExecRetry;
+
+/* maximum number of job re-queue times */
+        public int maxJobRequeue;
+
+/* no preempt run time */
+        public int noPreemptRunTime;
+
+/* no preempt finish time */
+        public int noPreemptFinishTime;
+
+/* no preempt run time percent */
+        public int noPreemptRunTimePercent;
+
+/* no preempt finish time percent */
+        public int noPreemptFinishTimePercent;
+
+/* use Linux-PAM */
+        public int usePam;
+
+/* processor binding options */
+        public int bindingOption;
+
+/* persistent same hosts and same order */
+        public int persistHostOrder;
+
+/* job resize notification cmd */
+        public String resizeNotifyCmd;
+    }
+
+
+
+/* application attributes
+ */
+
+/* rerunnable application */
+    public static final int A_ATTRIB_RERUNNABLE = 0x01;
+
+/* non rerunnable application */
+    public static final int A_ATTRIB_NONRERUNNABLE = 0x02;
+
+/* default application */
+    public static final int A_ATTRIB_DEFAULT = 0x04;
+
+/* runtime is absolute */
+    public static final int A_ATTRIB_ABS_RUNLIMIT = 0x08;
+
+/* process binding application */
+    public static final int A_ATTRIB_JOBBINDING = 0x10;
+
+/* process binding application */
+    public static final int A_ATTRIB_NONJOBBINDING = 0x20;
+
+/* checkpointable application */
+    public static final int A_ATTRIB_CHKPNT = 0x40;
+
+/* Job can be resizable manually */
+    public static final int A_ATTRIB_RESIZABLE = 0x80;
+
+/* Job can be resized automatically */
+    public static final int A_ATTRIB_AUTO_RESIZABLE = 0x100;
+
+
+/* processor binding options */
+    public static final int BINDING_OPTION_BALANCE = 0x1;
+    public static final int BINDING_OPTION_PACK = 0x2;
+    public static final int BINDING_OPTION_ANY = 0x4;
+    public static final int BINDING_OPTION_USER = 0x8;
+    public static final int BINDING_OPTION_USER_CPU_LIST = 0x10;
+    public static final int BINDING_OPTION_NONE = 0x20;
+
+    /**
+     *  \addtogroup movejob_options movejob_options
+     *  options for \ref lsb_movejob call
+     */
+
+    /**
+     * <  To top
+     */
+    public static final int TO_TOP = 1;
+
+    /**
+     * <  To bottom
+     */
+    public static final int TO_BOTTOM = 2;
+
+    /**
+     *  \addtogroup queue_ctrl_option queue_ctrl_option
+     *  options for \ref lsb_queuecontrol call
+     */
+
+    /**
+     * < Open the queue to accept jobs.
+     */
+    public static final int QUEUE_OPEN = 1;
+
+    /**
+     * < Close the queue so it will not accept jobs.
+     */
+    public static final int QUEUE_CLOSED = 2;
+
+    /**
+     * < Activate the queue to dispatch jobs.
+     */
+    public static final int QUEUE_ACTIVATE = 3;
+
+    /**
+     * < Inactivate the queue so it will not dispatch jobs.
+     */
+    public static final int QUEUE_INACTIVATE = 4;
+
+    /**
+     * < Clean the queue
+     */
+    public static final int QUEUE_CLEAN = 5;
+
+    /**
+     * \brief The structure of queueCtrlReq
+     */
+    public static class queueCtrlReq extends Structure {
+        public static class ByReference extends queueCtrlReq implements Structure.ByReference {}
+        public static class ByValue extends queueCtrlReq implements Structure.ByValue {}
+        public queueCtrlReq() {}
+        public queueCtrlReq(Pointer p) { super(p); read(); }
+
+
+        /**
+         * < The name of the queue to be controlled.
+         */
+        public String queue;
+
+        /**
+         * < Operations to be applied, for example, QUEUE_OPEN. You can refer to \ref queue_ctrl_option for more options.
+         */
+        public int opCode;
+
+        /**
+         * < The message attached by the admin
+         */
+        public String message;
+    }
+
+
+
+/* options for lsb_hostcontrol() call */
+    /**
+     *  \addtogroup host_ctrl_option host_ctrl_option
+     *  options operations to be applied
+     */
+
+    /**
+     * < Opens the host to accept jobs.
+     */
+    public static final int HOST_OPEN = 1;
+
+    /**
+     * < Closes the host so that no jobs can be dispatched to it.
+     */
+    public static final int HOST_CLOSE = 2;
+
+    /**
+     * < Restarts sbatchd on the host. sbatchd will receive a request from mbatchd and re-execute. This permits the sbatchd binary to be updated. This operation fails if no sbatchd is running on the specified host.
+     */
+    public static final int HOST_REBOOT = 3;
+
+    /**
+     * < The sbatchd on the host will exit.
+     */
+    public static final int HOST_SHUTDOWN = 4;
+
+    /**
+     * < Used for closing leased host on the submission cluster
+     */
+    public static final int HOST_CLOSE_REMOTE = 5;
+
+    /**
+     * \brief  Host control request.
+     */
+    public static class hostCtrlReq extends Structure {
+        public static class ByReference extends hostCtrlReq implements Structure.ByReference {}
+        public static class ByValue extends hostCtrlReq implements Structure.ByValue {}
+        public hostCtrlReq() {}
+        public hostCtrlReq(Pointer p) { super(p); read(); }
+
+
+        /**
+         * < The host to be controlled. If host is null, the local host is assumed.
+         */
+        public String host;
+
+        /**
+         * < Operations to be applied in \ref host_ctrl_option.
+         */
+        public int opCode;
+
+        /**
+         * < Message attached by the administrator.
+         */
+        public String message;
+    }
+
+
+
+/* options for lsb_hgcontrol() call */
+    public static final int HGHOST_ADD = 1;
+    public static final int HGHOST_DEL = 2;
+
+    public static class hgCtrlReq extends Structure {
+        public static class ByReference extends hgCtrlReq implements Structure.ByReference {}
+        public static class ByValue extends hgCtrlReq implements Structure.ByValue {}
+        public hgCtrlReq() {}
+        public hgCtrlReq(Pointer p) { super(p); read(); }
+
+        public int opCode;
+        public String grpname;
+        public int numhosts;
+        public Pointer hosts;
+        public String message;
+    }
+
+
+
+    public static class hgCtrlReply extends Structure {
+        public static class ByReference extends hgCtrlReply implements Structure.ByReference {}
+        public static class ByValue extends hgCtrlReply implements Structure.ByValue {}
+        public hgCtrlReply() {}
+        public hgCtrlReply(Pointer p) { super(p); read(); }
+
+        public int numsucc;
+        public int numfail;
+        public Pointer succHosts;
+        public Pointer failHosts;
+        public IntByReference failReasons;
+    }
+
+
+
+/* options for lsb_reconfig() call */
+    /**
+     *  \addtogroup mbd_operation mbd_operation
+     *   options for \ref lsb_reconfig call
+     */
+
+    /**
+     * < mbatchd restart
+     */
+    public static final int MBD_RESTART = 0;
+
+    /**
+     * < mbatchd reread configuration files
+     */
+    public static final int MBD_RECONFIG = 1;
+
+    /**
+     * < mbatchd check validity of configuration files
+     */
+    public static final int MBD_CKCONFIG = 2;
+
+    /**
+     * \brief  mbatchd control request.
+     */
+    public static class mbdCtrlReq extends Structure {
+        public static class ByReference extends mbdCtrlReq implements Structure.ByReference {}
+        public static class ByValue extends mbdCtrlReq implements Structure.ByValue {}
+        public mbdCtrlReq() {}
+        public mbdCtrlReq(Pointer p) { super(p); read(); }
+
+
+        /**
+         * < Operation applied, defined in \ref mbd_operation
+         */
+        public int opCode;
+
+        /**
+         * < Not used so far
+         */
+        public String name;
+
+        /**
+         * < The message attached by the admin
+         */
+        public String message;
+    }
+
+
+
+/* opcode for turn on or off the perfmon monitor */
+    public static final int PERFMON_START = 1;
+    public static final int PERFMON_STOP = 2;
+    public static final int PERFMON_SET_PERIOD = 3;
+
+
+/* defualt sample period 60 */
+    public static final int DEF_PERFMON_PERIOD = 60;
+
+
+    public static class perfmonMetricsEnt extends Structure {
+        public static class ByReference extends perfmonMetricsEnt implements Structure.ByReference {}
+        public static class ByValue extends perfmonMetricsEnt implements Structure.ByValue {}
+        public perfmonMetricsEnt() {}
+        public perfmonMetricsEnt(Pointer p) { super(p); read(); }
+
+/* metrice name */
+        public String name;
+
+/* last period counters */
+        public NativeLong current;
+
+/* max of (counter/interval)*sample period for one period */
+        public NativeLong max;
+
+/* min of (counter/interval)*sample period for one period */
+        public NativeLong min;
+
+/* avg of (total/interval)*sample period for one period */
+        public NativeLong avg;
+
+/* total counters from performance monitor turn on */
+        public String total;
+    }
+
+
+
+/*performance monitor info*/
+
+    public static class perfmonInfo extends Structure {
+        public static class ByReference extends perfmonInfo implements Structure.ByReference {}
+        public static class ByValue extends perfmonInfo implements Structure.ByValue {}
+        public perfmonInfo() {}
+        public perfmonInfo(Pointer p) { super(p); read(); }
+
+/* number of metrics*/
+        public int num;
+
+/* array of metrics counter */
+        public Pointer /* perfmonMetricsEnt.ByReference */ record;
+
+/* sample period */
+        public int period;
+
+/* time when the performance moniter turn on */
+        public NativeLong start;
+
+/* time when the performance moniter turn off */
+        public NativeLong end;
+    }
+
+
+
+/* options for lsb_reljgrp() call */
+    public static final int JGRP_RELEASE_PARENTONLY = 0x01;
+
+
+    /**
+     * \brief Records of logged events
+     */
+    public static class logSwitchLog extends Structure {
+        public static class ByReference extends logSwitchLog implements Structure.ByReference {}
+        public static class ByValue extends logSwitchLog implements Structure.ByValue {}
+        public logSwitchLog() {}
+        public logSwitchLog(Pointer p) { super(p); read(); }
+
+
+        /**
+         * < The last jobId so far
+         */
+        public int lastJobId;
+/*#if defined(LSF_SIMULATOR)*/
+
+/**< last trace record time */
+/*    public NativeLong lastTraceTime;*/
+
+        /**< last trace record type */
+/*public int    lastTraceType;*
+
+    /**< last trace record info */
+/*public String lastTraceInfo;*/
+        /*#endif*/
+    }
+
+
+
+    /**
+     * \brief Records of job CPU data logged event
+     */
+    public static class dataLoggingLog extends Structure {
+        public static class ByReference extends dataLoggingLog implements Structure.ByReference {}
+        public static class ByValue extends dataLoggingLog implements Structure.ByValue {}
+        public dataLoggingLog() {}
+        public dataLoggingLog(Pointer p) { super(p); read(); }
+
+
+        /**
+         * < The time of last job cpu data logging
+         */
+        public NativeLong loggingTime;
+    }
+
+
+
+    /**
+     * \brief  new job group log.
+     */
+    public static class jgrpNewLog extends Structure {
+        public static class ByReference extends jgrpNewLog implements Structure.ByReference {}
+        public static class ByValue extends jgrpNewLog implements Structure.ByValue {}
+        public jgrpNewLog() {}
+        public jgrpNewLog(Pointer p) { super(p); read(); }
+
+
+        /**
+         * < The user ID of the submitter
+         */
+        public int userId;
+
+        /**
+         * < The job submission time
+         */
+        public NativeLong submitTime;
+
+        /**
+         * < The name of the submitter
+         */
+        public byte[] userName = new byte[MAX_LSB_NAME_LEN];
+
+        /**
+         * < The job dependency condition
+         */
+        public String depCond;
+
+        /**
+         * < Time event string
+         */
+        public String timeEvent;
+
+        /**
+         * < Job group name
+         */
+        public String groupSpec;
+
+        /**
+         * < New job group name
+         */
+        public String destSpec;
+
+        /**
+         * < Delete options in options field
+         */
+        public int delOptions;
+
+        /**
+         * < Extended Delete options in options2 field
+         */
+        public int delOptions2;
+
+        /**
+         * < Platform type: such as Unix, Windows
+         */
+        public int fromPlatform;
+
+        /**
+         * < SLA service class name under which the job runs
+         */
+        public String sla;
+
+        /**
+         * < Max job group slots limit
+         */
+        public int maxJLimit;
+
+        /**
+         * < Job group creation method: implicit or explicit
+         */
+        public int options;
+    }
+
+
+
+    /**
+     * \brief  job group control log.
+     */
+    public static class jgrpCtrlLog extends Structure {
+        public static class ByReference extends jgrpCtrlLog implements Structure.ByReference {}
+        public static class ByValue extends jgrpCtrlLog implements Structure.ByValue {}
+        public jgrpCtrlLog() {}
+        public jgrpCtrlLog(Pointer p) { super(p); read(); }
+
+
+        /**
+         * < The user ID of the submitter
+         */
+        public int userId;
+
+        /**
+         * < The name of the submitter
+         */
+        public byte[] userName = new byte[MAX_LSB_NAME_LEN];
+
+        /**
+         * < Job group name
+         */
+        public String groupSpec;
+
+        /**
+         * < Options
+         */
+        public int options;
+
+        /**
+         * < Job control JGRP_RELEASE, JGRP_HOLD, JGRP_DEL
+         */
+        public int ctrlOp;
+    }
+
+
+
+    /**
+     * \brief  job group status log.
+     */
+    public static class jgrpStatusLog extends Structure {
+        public static class ByReference extends jgrpStatusLog implements Structure.ByReference {}
+        public static class ByValue extends jgrpStatusLog implements Structure.ByValue {}
+        public jgrpStatusLog() {}
+        public jgrpStatusLog(Pointer p) { super(p); read(); }
+
+
+        /**
+         * < The full group path name for the job group
+         */
+        public String groupSpec;
+
+        /**
+         * < Job group status
+         */
+        public int status;
+
+        /**
+         * < Prior status
+         */
+        public int oldStatus;
+    }
+
+
+
+    /**
+     * \brief jobNewLog logged in lsb.events when a job is submitted.
+     */
+    public static class jobNewLog extends Structure {
+        public static class ByReference extends jobNewLog implements Structure.ByReference {}
+        public static class ByValue extends jobNewLog implements Structure.ByValue {}
+        public jobNewLog() {}
+        public jobNewLog(Pointer p) { super(p); read(); }
+
+
+        /**
+         * < The job ID that the LSF assigned to the job
+         */
+        public int jobId;
+
+        /**
+         * < The user ID of the submitter
+         */
+        public int userId;
+
+        /**
+         * < The name of the submitter
+         */
+        public byte[] userName = new byte[MAX_LSB_NAME_LEN];
+
+        /**
+         * < Job submission options. see \ref lsb_submit.
+         */
+        public int options;
+
+        /**
+         * < Job submission options. see \ref lsb_submit.
+         */
+        public int options2;
+
+        /**
+         * < The number of processors requested for execution
+         */
+        public int numProcessors;
+
+        /**
+         * < The job submission time
+         */
+        public NativeLong submitTime;
+
+        /**
+         * < The job should be started on or after this time
+         */
+        public NativeLong beginTime;
+
+        /**
+         * < If the job has not finished by this time, it will be killed
+         */
+        public NativeLong termTime;
+
+        /**
+         * < The signal value sent to the job 10 minutes before its run window closes
+         */
+        public int sigValue;
+
+        /**
+         * < The checkpointing period
+         */
+        public int chkpntPeriod;
+
+        /**
+         * < The process ID assigned to the job when it was restarted
+         */
+        public int restartPid;
+
+        /**
+         * < The user's resource limits
+         */
+        public int[] rLimits = new int[LibLsf.LSF_RLIM_NLIMITS];
+
+        /**
+         * < The model, host name or host type for scaling CPULIMIT and RUNLIMIT
+         */
+        public byte[] hostSpec = new byte[LibLsf.MAXHOSTNAMELEN];
+
+        /**
+         * < The CPU factor for the above model, host name or host type
+         */
+        public float hostFactor;
+
+        /**
+         * < The file creation mask for this job
+         */
+        public int umask;
+
+        /**
+         * < The name of the queue to which this job was submitted
+         */
+        public byte[] queue = new byte[MAX_LSB_NAME_LEN];
+
+        /**
+         * < The resource requirements of the job
+         */
+        public String resReq;
+
+        /**
+         * < The submission host name
+         */
+        public byte[] fromHost = new byte[LibLsf.MAXHOSTNAMELEN];
+
+        /**
+         * < The current working directory
+         */
+        public String cwd;
+
+        /**
+         * < The checkpoint directory
+         */
+        public String chkpntDir;
+
+        /**
+         * < The input file name
+         */
+        public String inFile;
+
+        /**
+         * < The output file name
+         */
+        public String outFile;
+
+        /**
+         * < The error output file name
+         */
+        public String errFile;
+
+        /**
+         * < Job spool input file
+         */
+        public String inFileSpool;
+
+        /**
+         * < Job spool command file
+         */
+        public String commandSpool;
+
+        /**
+         * < Job spool directory
+         */
+        public String jobSpoolDir;
+
+        /**
+         * < The home directory of the submitter
+         */
+        public String subHomeDir;
+
+        /**
+         * < The job file name
+         */
+        public String jobFile;
+
+        /**
+         * < The number of hosts considered for dispatching this job
+         */
+        public int numAskedHosts;
+
+        /**
+         * < The array of names of hosts considered for dispatching this job
+         */
+        public Pointer askedHosts;
+
+        /**
+         * < The job dependency condition
+         */
+        public String dependCond;
+
+        /**
+         * < Time event string
+         */
+        public String timeEvent;
+
+        /**
+         * < The job name
+         */
+        public String jobName;
+
+        /**
+         * < The job command
+         */
+        public String command;
+
+        /**
+         * < The number of files to transfer
+         */
+        public int nxf;
+
+        /**
+         * < The array of file transfer specifications. (The xFile structure is defined in <lsf/lsbatch.h>)
+         */
+        public Pointer /* xFile.ByReference */ xf;
+
+        /**
+         * < The command string to be pre_executed
+         */
+        public String preExecCmd;
+
+        /**
+         * < User option mail string
+         */
+        public String mailUser;
+
+        /**
+         * < The project name for this job, used for accounting purposes
+         */
+        public String projectName;
+
+        /**
+         * < Port to be used for interactive jobs
+         */
+        public int niosPort;
+
+        /**
+         * < Maximum number of processors
+         */
+        public int maxNumProcessors;
+
+        /**
+         * < Execution host type
+         */
+        public String schedHostType;
+
+        /**
+         * < Login shell specified by user
+         */
+        public String loginShell;
+
+        /**
+         * < The user group name for this job
+         */
+        public String userGroup;
+
+        /**
+         * < List of alarm conditions for job
+         */
+        public String exceptList;
+
+        /**
+         * < Array idx, must be 0 in JOB_NEW
+         */
+        public int idx;
+
+        /**
+         * < User priority
+         */
+        public int userPriority;
+
+        /**
+         * < Advance reservation ID
+         */
+        public String rsvId;
+
+        /**
+         * < The job group under which the job runs.
+         */
+        public String jobGroup;
+
+        /**
+         * < External scheduling options
+         */
+        public String extsched;
+
+        /**
+         * < Warning time period in seconds, -1 if unspecified
+         */
+        public int warningTimePeriod;
+
+        /**
+         * < Warning action, SIGNAL | CHKPNT | command, null if unspecified
+         */
+        public String warningAction;
+
+        /**
+         * < The service class under which the job runs.
+         */
+        public String sla;
+
+        /**
+         * < The absolute run limit of the job
+         */
+        public int SLArunLimit;
+
+        /**
+         * < License Project
+         */
+        public String licenseProject;
+
+        /**
+         * < Extended bitwise inclusive OR of options flags. See \ref lsb_submit.
+         */
+        public int options3;
+
+        /**
+         * < Application profile under which the job runs.
+         */
+        public String app;
+
+        /**
+         * < Post-execution commands.
+         */
+        public String postExecCmd;
+
+        /**
+         * < Runtime estimate specified.
+         */
+        public int runtimeEstimation;
+
+        /**
+         * < Job-level requeue exit values.
+         */
+        public String requeueEValues;
+
+        /**
+         * < Initial checkpoint period
+         */
+        public int initChkpntPeriod;
+
+        /**
+         * < Job migration threshold.
+         */
+        public int migThreshold;
+
+        /**
+         * < Resize notify command
+         */
+        public String notifyCmd;
+
+        /**
+         * < Job description.
+         */
+        public String jobDescription;
+
+        /**
+         * < For new options in future
+         */
+        public submit_ext.ByReference submitExt;
+
+/*#if defined(LSF_SIMULATOR)*/
+
+/**< maximum memory */
+        /*public int    maxmem;*/
+
+        /**< exit status */
+        /*public int    exitstatus;*/
+
+        /**< job run time */
+        /*public int    runtime;*/
+
+        /**< system cpu time */
+        /*public int    cputime;*/
+
+        /**< allocated slots */
+        /*public int    slots;*/
+
+        /**< cpu factor */
+        /*public float  cpufactor;*/
+
+        /*#endif*/
+    }
+
+
+
+/*
+#if defined(LSF_SIMULATOR)
+public static class jobArrayElementLog extends Structure {
+public static class ByReference extends jobArrayElementLog implements Structure.ByReference {}
+public static class ByValue extends jobArrayElementLog implements Structure.ByValue {}
+
+    public int jobId;
+*/
+/* Copy LSF simulator related fields from jobNewLog */
+/*
+    public int idx;
+        public int maxmem;
+        public int exitstatus;
+        public int runtime;
+        public int cputime;
+        public int slots;
+        public float cpufactor;
+    };
+    #endif
+    */
+
+    /**
+     * \brief  job modified log.
+     */
+    public static class jobModLog extends Structure {
+        public static class ByReference extends jobModLog implements Structure.ByReference {}
+        public static class ByValue extends jobModLog implements Structure.ByValue {}
+        public jobModLog() {}
+        public jobModLog(Pointer p) { super(p); read(); }
+
+
+        /**
+         * < JobId or jobName in String/
+         * public String jobIdStr;
+         * <p/>
+         * /**< Job submission options(See \ref lsb_submit)
+         */
+        public int options;
+
+        /**
+         * < Job submission options(See \ref lsb_submit)
+         */
+        public int options2;
+
+        /**
+         * < Delete options in options field
+         */
+        public int delOptions;
+
+        /**
+         * < Extended delete options in options2 field .
+         */
+        public int delOptions2;
+
+        /**
+         * < The user ID of the submitter
+         */
+        public int userId;
+
+        /**
+         * < The name of the submitter
+         */
+        public String userName;
+
+        /**
+         * < The job submission time
+         */
+        public int submitTime;
+
+        /**
+         * < The file creation mask for this job
+         */
+        public int umask;
+
+        /**
+         * < The number of processors requested for execution
+         */
+        public int numProcessors;
+
+        /**
+         * < The job should be started on or after this time
+         */
+        public NativeLong beginTime;
+
+        /**
+         * < If the job has not finished by this time,  it will be killed
+         */
+        public NativeLong termTime;
+
+        /**
+         * < The signal value sent to the job 10 minutes before its run window closes
+         */
+        public int sigValue;
+
+        /**
+         * < The process ID assigned to the job when it was restarted
+         */
+        public int restartPid;
+
+
+        /**
+         * < The job name
+         */
+        public String jobName;
+
+        /**
+         * < The name of the queue to which this job was submitted
+         */
+        public String queue;
+
+
+        /**
+         * < The number of hosts considered for dispatching this job
+         */
+        public int numAskedHosts;
+
+        /**
+         * < List of asked hosts
+         */
+        public Pointer askedHosts;
+
+
+        /**
+         * < The resource requirements of the job
+         */
+        public String resReq;
+
+        /**
+         * < User's resource limits (soft)
+         */
+        public int[] rLimits = new int[LibLsf.LSF_RLIM_NLIMITS];
+
+        /**
+         * < The model, host name or host type for scaling CPULIMIT and RUNLIMIT
+         */
+        public String hostSpec;
+
+
+        /**
+         * < The job dependency condition
+         */
+        public String dependCond;
+
+        /**
+         * < Time event string.
+         */
+        public String timeEvent;
+
+
+        /**
+         * < The home directory of the submitter
+         */
+        public String subHomeDir;
+
+        /**
+         * < The input file name
+         */
+        public String inFile;
+
+        /**
+         * < The output file name
+         */
+        public String outFile;
+
+        /**
+         * < The error output file name
+         */
+        public String errFile;
+
+        /**
+         * < Command description - this is really a job description field
+         */
+        public String command;
+
+        /**
+         * < Job spool input file
+         */
+        public String inFileSpool;
+
+        /**
+         * < Job spool command file
+         */
+        public String commandSpool;
+
+        /**
+         * < The checkpointing period
+         */
+        public int chkpntPeriod;
+
+        /**
+         * < The checkpoint directory
+         */
+        public String chkpntDir;
+
+        /**
+         * < The number of files to transfer
+         */
+        public int nxf;
+
+        /**
+         * < The array of file transfer specifications.  (The xFile structure is defined in <lsf/lsbatch.h>)
+         */
+        public Pointer /* xFile.ByReference */ xf;
+
+
+        /**
+         * < The job file name: If == '\\0', indicate let mbatchd make up name, otherwise, mbatchd will use given name.  It is '\\0' if it is a regular job,non-nil means it is a restart job.
+         */
+        public String jobFile;
+
+        /**
+         * < The submission host name
+         */
+        public String fromHost;
+
+        /**
+         * < The current working directory
+         */
+        public String cwd;
+
+
+        /**
+         * < The pre-execution command
+         */
+        public String preExecCmd;
+
+        /**
+         * < User option mail string
+         */
+        public String mailUser;
+
+        /**
+         * < Project name for the job; used for accounting purposes
+         */
+        public String projectName;
+
+
+        /**
+         * < NIOS callback port to be used for interactive jobs
+         */
+        public int niosPort;
+
+        /**
+         * < Maximum number of processors
+         */
+        public int maxNumProcessors;
+
+
+        /**
+         * < The login shell specified by user
+         */
+        public String loginShell;
+
+        /**
+         * < Restart job's submission host type
+         */
+        public String schedHostType;
+
+        /**
+         * < The user group name for this job
+         */
+        public String userGroup;
+
+        /**
+         * < List of job exception conditions
+         */
+        public String exceptList;
+
+        /**
+         * < User priority
+         */
+        public int userPriority;
+
+        /**
+         * < Advance reservation ID
+         */
+        public String rsvId;
+
+        /**
+         * < External scheduling options
+         */
+        public String extsched;
+
+        /**
+         * < Job warning time period in seconds; -1 if unspecified
+         */
+        public int warningTimePeriod;
+
+        /**
+         * < Job warning action: SIGNAL | CHKPNT | command; null if unspecified
+         */
+        public String warningAction;
+
+        /**
+         * < The job group under which the job runs
+         */
+        public String jobGroup;
+
+        /**
+         * < SLA service class name under which the job runs
+         */
+        public String sla;
+
+        /**
+         * < LSF License Scheduler project name
+         */
+        public String licenseProject;
+
+        /**
+         * < Extended bitwise inclusive OR of options flags. see \ref lsb_submit.
+         */
+        public int options3;
+
+        /**
+         * < Extended delete options in options3 field.
+         */
+        public int delOptions3;
+
+        /**
+         * < Application profile under which the job runs.
+         */
+        public String app;
+
+        /**
+         * < Absolute priority scheduling string set by administrators to denote static  system APS value or ADMIN factor APS value.
+         */
+        public String apsString;
+
+        /**
+         * < Post-execution commands.
+         */
+        public String postExecCmd;
+
+        /**
+         * < Runtime estimate.
+         */
+        public int runtimeEstimation;
+
+        /**
+         * < Job-level requeue exit values.
+         */
+        public String requeueEValues;
+
+        /**
+         * < Initial checkpoint period
+         */
+        public int initChkpntPeriod;
+
+        /**
+         * < Job migration threshold.
+         */
+        public int migThreshold;
+
+        /**
+         * < Resize notify command
+         */
+        public String notifyCmd;
+
+        /**
+         * < Job description.
+         */
+        public String jobDescription;
+
+        /**
+         * < For new options in future
+         */
+        public submit_ext.ByReference submitExt;
+    }
+
+
+
+    /**
+     * \brief  logged in lsb.events when a job is started.
+     */
+    public static class jobStartLog extends Structure {
+        public static class ByReference extends jobStartLog implements Structure.ByReference {}
+        public static class ByValue extends jobStartLog implements Structure.ByValue {}
+        public jobStartLog() {}
+        public jobStartLog(Pointer p) { super(p); read(); }
+
+
+        /**
+         * < The unique ID for the job
+         */
+        public int jobId;
+
+        /**
+         * < The status of the job (see  \ref lsb_readjobinfo )
+         */
+        public int jStatus;
+
+        /**
+         * < The job process ID
+         */
+        public int jobPid;
+
+        /**
+         * < The job process group ID
+         */
+        public int jobPGid;
+
+        /**
+         * < The CPU factor of the first execution host
+         */
+        public float hostFactor;
+
+        /**
+         * < The number of processors used for execution
+         */
+        public int numExHosts;
+
+        /**
+         * < The array of execution host names
+         */
+        public Pointer execHosts;
+
+        /**
+         * < Pre-execution command defined in the queue
+         */
+        public String queuePreCmd;
+
+        /**
+         * < Post-execution command defined in the queue
+         */
+        public String queuePostCmd;
+
+        /**
+         * < Job processing flags
+         */
+        public int jFlags;
+
+        /**
+         * < The user group name for this job
+         */
+        public String userGroup;
+
+        /**
+         * < Job array index; must be 0 in JOB_NEW
+         */
+        public int idx;
+
+        /**
+         * < Placement information of LSF HPC jobs
+         */
+        public String additionalInfo;
+
+        /**
+         * < How long a backfilled job can run; used for preemption backfill jobs
+         */
+        public int duration4PreemptBackfill;
+
+        /**
+         * <  Job Flags2
+         */
+        public int jFlags2;
+    }
+
+
+
+    /**
+     * \brief logged in lsb.events when a job start request is accepted.
+     */
+    public static class jobStartAcceptLog extends Structure {
+        public static class ByReference extends jobStartAcceptLog implements Structure.ByReference {}
+        public static class ByValue extends jobStartAcceptLog implements Structure.ByValue {}
+        public jobStartAcceptLog() {}
+        public jobStartAcceptLog(Pointer p) { super(p); read(); }
+
+
+        /**
+         * < The unique ID for the job
+         */
+        public int jobId;
+
+        /**
+         * < The job process ID
+         */
+        public int jobPid;
+
+        /**
+         * < The job process group ID
+         */
+        public int jobPGid;
+
+        /**
+         * < Job array index; must be 0 in JOB_NEW
+         */
+        public int idx;
+    }
+
+
+
+    /**
+     * \brief logged in lsb.events when a job is executed.
+     */
+    public static class jobExecuteLog extends Structure {
+        public static class ByReference extends jobExecuteLog implements Structure.ByReference {}
+        public static class ByValue extends jobExecuteLog implements Structure.ByValue {}
+        public jobExecuteLog() {}
+        public jobExecuteLog(Pointer p) { super(p); read(); }
+
+        /* logged in lsb.events when a job is executed */
+
+        /**
+         * < The unique ID for the job
+         */
+        public int jobId;
+
+        /**
+         * < User ID under which the job is running
+         */
+        public int execUid;
+
+        /**
+         * < Home directory of the user denoted by execUid
+         */
+        public String execHome;
+
+        /**
+         * < Current working directory where job is running
+         */
+        public String execCwd;
+
+        /**
+         * < The job process group ID
+         */
+        public int jobPGid;
+
+        /**
+         * < User name under which the job is running
+         */
+        public String execUsername;
+
+        /**
+         * < The job process ID
+         */
+        public int jobPid;
+
+        /**
+         * < Job array index; must be 0 in JOB_NEW
+         */
+        public int idx;
+
+        /**
+         * < Placement information of LSF HPC jobs
+         */
+        public String additionalInfo;
+
+        /**
+         * < The run limit scaled by the exec host
+         */
+        public int SLAscaledRunLimit;
+
+        /**
+         * < The position of the job
+         */
+        public int position;
+
+        /**
+         * < The rusage satisfied at job runtime
+         */
+        public String execRusage;
+
+        /**
+         * < The duration for preemptive backfill class in seconds
+         */
+        public int duration4PreemptBackfill;
+    }
+
+
+
+
+    /**
+     * \brief logged when a job's status is changed.
+     */
+    public static class jobStatusLog extends Structure {
+        public static class ByReference extends jobStatusLog implements Structure.ByReference {}
+        public static class ByValue extends jobStatusLog implements Structure.ByValue {}
+        public jobStatusLog() {}
+        public jobStatusLog(Pointer p) { super(p); read(); }
+
+
+        /**
+         * < The unique ID for the job
+         */
+        public int jobId;
+
+        /**
+         * < The job status (see \ref lsb_readjobinfo )
+         */
+        public int jStatus;
+
+        /**
+         * < The reason the job is pending or suspended  (see \ref lsb_pendreason and \ref lsb_suspreason )
+         */
+        public int reason;
+
+        /**
+         * < The load indices that have overloaded the host (see \ref lsb_pendreason  and \ref lsb_suspreason )
+         */
+        public int subreasons;
+
+        /**
+         * < The CPU time consumed before this event occurred
+         */
+        public float cpuTime;
+
+        /**
+         * < The job completion time
+         */
+        public NativeLong endTime;
+
+        /**
+         * < Boolean indicating lsfRusage is logged
+         */
+        public int ru;
+
+        /**
+         * < Resource usage statisticsThe lsfRusage structure is defined in <lsf/lsf.h>. Note that the availability of certain fields depends on the platform on which the sbatchd runs. The fields that do not make sense on the platform will be logged as -1.0.
+         */
+        public LibLsf.lsfRusage lsfRusage;
+
+        /**
+         * < Job exit status
+         */
+        public int jFlags;
+
+        /**
+         * < Job's exit status
+         */
+        public int exitStatus;
+
+        /**
+         * < Job array index; must be 0 in JOB_NEW
+         */
+        public int idx;
+
+        /**
+         * < Job termination reason, see <lsf/lsbatch.h>
+         */
+        public int exitInfo;
+    }
+
+
+
+
+    /**
+     * \brief logged when a job's status is changed
+     */
+    public static class sbdJobStatusLog extends Structure {
+        public static class ByReference extends sbdJobStatusLog implements Structure.ByReference {}
+        public static class ByValue extends sbdJobStatusLog implements Structure.ByValue {}
+        public sbdJobStatusLog() {}
+        public sbdJobStatusLog(Pointer p) { super(p); read(); }
+
+
+        /**
+         * < The unique ID for the job
+         */
+        public int jobId;
+
+        /**
+         * < The status of the job (see \ref lsb_readjobinfo)
+         */
+        public int jStatus;
+
+        /**
+         * < The reason the job is pending or suspended (See \ref lsb_pendreason and \ref lsb_suspreason)
+         */
+        public int reasons;
+
+        /**
+         * < The load indices that have overloaded the host (See \ref lsb_pendreason and \ref lsb_suspreason)
+         */
+        public int subreasons;
+
+        /**
+         * < Action process ID
+         */
+        public int actPid;
+
+        /**
+         * < Action Value SIG_CHKPNT | SIG_CHKPNT_COPY |  SIG_WARNING
+         */
+        public int actValue;
+
+        /**
+         * < Action period
+         */
+        public NativeLong actPeriod;
+
+        /**
+         * < Action flag
+         */
+        public int actFlags;
+
+        /**
+         * < Action logging status
+         */
+        public int actStatus;
+
+        /**
+         * < Action Reason SUSP_MBD_LOCK | SUSP_USER_STOP | SUSP_USER_RESUME | SUSP_SBD_STARTUP
+         */
+        public int actReasons;
+
+        /**
+         * < Sub Reason SUB_REASON_RUNLIMIT | SUB_REASON_DEADLINE |SUB_REASON_PROCESSLIMIT | SUB_REASON_MEMLIMIT |SUB_REASON_CPULIMIT
+         */
+        public int actSubReasons;
+
+        /**
+         * < Job array index; must be 0 in JOB_NEW
+         */
+        public int idx;
+
+        /**
+         * < The signal value
+         */
+        public int sigValue;
+
+        /**
+         * < The termination reason of a job
+         */
+        public int exitInfo;
+    }
+
+
+
+    /**
+     * \brief job status that we could send to MBD
+     */
+    public static class sbdUnreportedStatusLog extends Structure {
+        public static class ByReference extends sbdUnreportedStatusLog implements Structure.ByReference {}
+        public static class ByValue extends sbdUnreportedStatusLog implements Structure.ByValue {}
+        public sbdUnreportedStatusLog() {}
+        public sbdUnreportedStatusLog(Pointer p) { super(p); read(); }
+
+
+        /**
+         * < The unique ID for the job
+         */
+        public int jobId;
+
+        /**
+         * < Action process ID
+         */
+        public int actPid;
+
+        /**
+         * < The job process ID
+         */
+        public int jobPid;
+
+        /**
+         * < The job process group ID
+         */
+        public int jobPGid;
+
+        /**
+         * < New status of the job
+         */
+        public int newStatus;
+
+        /**
+         * < Pending or suspending reason code
+         */
+        public int reason;
+
+        /**
+         * < Pending or suspending subreason code
+         */
+        public int subreasons;
+
+        /**
+         * < Resource usage information for the job  (see jobFinishLog)
+         */
+        public LibLsf.lsfRusage lsfRusage;
+
+        /**
+         * < User ID under which the job is running
+         */
+        public int execUid;
+
+        /**
+         * < Job exit status
+         */
+        public int exitStatus;
+
+        /**
+         * < Current working directory where job is running
+         */
+        public String execCwd;
+
+        /**
+         * < Home directory of the user denoted by execUid
+         */
+        public String execHome;
+
+        /**
+         * < User name under which the job is running
+         */
+        public String execUsername;
+
+        /**
+         * < Message index
+         */
+        public int msgId;
+
+        /**
+         * < Job's resource usage
+         */
+        public LibLsf.jRusage runRusage;
+
+        /**
+         * < Signal value
+         */
+        public int sigValue;
+
+        /**
+         * < Action logging status
+         */
+        public int actStatus;
+
+        /**
+         * < Sequence status of the job
+         */
+        public int seq;
+
+        /**
+         * < Job array index
+         */
+        public int idx;
+
+        /**
+         * < The termination reason of a job
+         */
+        public int exitInfo;
+    }
+
+
+
+    /**
+     * \brief logged when a job is switched to another queue
+     */
+    public static class jobSwitchLog extends Structure {
+        public static class ByReference extends jobSwitchLog implements Structure.ByReference {}
+        public static class ByValue extends jobSwitchLog implements Structure.ByValue {}
+        public jobSwitchLog() {}
+        public jobSwitchLog(Pointer p) { super(p); read(); }
+
+
+        /**
+         * < The user ID of the submitter
+         */
+        public int userId;
+
+        /**
+         * < The unique ID of the job
+         */
+        public int jobId;
+
+        /**
+         * < The name of the queue the job has been switched to
+         */
+        public byte[] queue = new byte[MAX_LSB_NAME_LEN];
+
+        /**
+         * < Job array index; must be 0 in JOB_NEW
+         */
+        public int idx;
+
+        /**
+         * < The name of the submitter
+         */
+        public byte[] userName = new byte[MAX_LSB_NAME_LEN];
+    }
+
+
+
+    /**
+     * \brief logged when a job is moved to another position
+     */
+    public static class jobMoveLog extends Structure {
+        public static class ByReference extends jobMoveLog implements Structure.ByReference {}
+        public static class ByValue extends jobMoveLog implements Structure.ByValue {}
+        public jobMoveLog() {}
+        public jobMoveLog(Pointer p) { super(p); read(); }
+
+        /* logged when a job is moved to another position */
+
+        /**
+         * < The user ID of the submitter
+         */
+        public int userId;
+
+        /**
+         * < The unique ID of the job
+         */
+        public int jobId;
+
+        /**
+         * < The new position of the job
+         */
+        public int position;
+
+        /**
+         * < The operation code for the move (see  \ref lsb_movejob)
+         */
+        public int base;
+
+        /**
+         * < Job array index; must be 0 in JOB_NEW
+         */
+        public int idx;
+
+        /**
+         * < The name of the submitter
+         */
+        public byte[] userName = new byte[MAX_LSB_NAME_LEN];
+    }
+
+
+
+    /**
+     * \brief  check point log.
+     */
+    public static class chkpntLog extends Structure {
+        public static class ByReference extends chkpntLog implements Structure.ByReference {}
+        public static class ByValue extends chkpntLog implements Structure.ByValue {}
+        public chkpntLog() {}
+        public chkpntLog(Pointer p) { super(p); read(); }
+
+
+        /**
+         * < The unique ID of the job
+         */
+        public int jobId;
+
+        /**
+         * < The new checkpointing period
+         */
+        public NativeLong period;
+
+        /**
+         * < The process ID of the checkpointing process (a child sbatchd)
+         */
+        public int pid;
+
+        /**
+         * < 0: checkpoint started; 1: checkpoint succeeded
+         */
+        public int ok;
+
+        /**
+         * < One of the following: \n LSB_CHKPNT_KILL : Kill process if checkpoint successful \n LSB_CHKPNT_FORCE : Force checkpoint even if non-checkpointable conditions exist \n LSB_CHKPNT_MIG : Checkpoint for the purpose of migration
+         */
+        public int flags;
+
+        /**
+         * < Job array index; must be 0 in JOB_NEW
+         */
+        public int idx;
+    }
+
+
+
+    /**
+     * \brief  job requeue log.
+     */
+    public static class jobRequeueLog extends Structure {
+        public static class ByReference extends jobRequeueLog implements Structure.ByReference {}
+        public static class ByValue extends jobRequeueLog implements Structure.ByValue {}
+        public jobRequeueLog() {}
+        public jobRequeueLog(Pointer p) { super(p); read(); }
+
+
+        /**
+         * < The unique ID of the job
+         */
+        public int jobId;
+
+        /**
+         * < Job array index; must be 0 in JOB_NEW
+         */
+        public int idx;
+    }
+
+
+
+    /**
+     * \brief  job clean log.
+     */
+    public static class jobCleanLog extends Structure {
+        public static class ByReference extends jobCleanLog implements Structure.ByReference {}
+        public static class ByValue extends jobCleanLog implements Structure.ByValue {}
+        public jobCleanLog() {}
+        public jobCleanLog(Pointer p) { super(p); read(); }
+
+
+        /**
+         * < The unique ID for the job
+         */
+        public int jobId;
+
+        /**
+         * < Job array index; must be 0 in JOB_NEW
+         */
+        public int idx;
+    }
+
+
+
+    /**
+     * \brief  job exception log.
+     */
+    public static class jobExceptionLog extends Structure {
+        public static class ByReference extends jobExceptionLog implements Structure.ByReference {}
+        public static class ByValue extends jobExceptionLog implements Structure.ByValue {}
+        public jobExceptionLog() {}
+        public jobExceptionLog(Pointer p) { super(p); read(); }
+
+
+        /**
+         * < The unique ID for the job
+         */
+        public int jobId;
+
+        /**
+         * < Job exception handling mask
+         */
+        public int exceptMask;
+
+        /**
+         * < Action Id (kill | alarm | rerun | setexcept)
+         */
+        public int actMask;
+
+        /**
+         * < Time event string
+         */
+        public NativeLong timeEvent;
+
+        /**
+         * < Except Info, pending reason for missched or cantrun exception, the exit code of thejob for the abend exception, otherwise 0.
+         */
+        public int exceptInfo;
+
+        /**
+         * < Job array index; must be 0 in JOB_NEW
+         */
+        public int idx;
+    }
+
+
+
+    /**
+     * \brief  signal action log.
+     */
+    public static class sigactLog extends Structure {
+        public static class ByReference extends sigactLog implements Structure.ByReference {}
+        public static class ByValue extends sigactLog implements Structure.ByValue {}
+        public sigactLog() {}
+        public sigactLog(Pointer p) { super(p); read(); }
+
+
+        /**
+         * < The unique ID of the job
+         */
+        public int jobId;
+
+        /**
+         * < Action period
+         */
+        public NativeLong period;
+
+        /**
+         * < Action process ID
+         */
+        public int pid;
+
+        /**
+         * < Job status
+         */
+        public int jStatus;
+
+        /**
+         * < Pending reasons
+         */
+        public int reasons;
+
+        /**
+         * < Action flag
+         */
+        public int flags;
+
+        /**
+         * < Signal symbol from the set: DELETEJOB |  KILL | KILLREQUEUE |REQUEUE_DONE | REQUEUE_EXIT | REQUEUE_PEND |REQUEUE_PSUSP_ADMIN | REQUEUE_PSUSP_USER | SIG_CHKPNT |  SIG_CHKPNT_COPY
+         */
+        public String signalSymbol;
+
+        /**
+         * < Action logging status (ACT_NO | ACT_START | ACT_PREEMPT | ACT_DONE |  ACT_FAIL) .Shown in signal_action
+         */
+        public int actStatus;
+
+        /**
+         * < Job array index; must be 0 in JOB_NEW
+         */
+        public int idx;
+    }
+
+
+
+    /**
+     * \brief  migration log.
+     */
+    public static class migLog extends Structure {
+        public static class ByReference extends migLog implements Structure.ByReference {}
+        public static class ByValue extends migLog implements Structure.ByValue {}
+        public migLog() {}
+        public migLog(Pointer p) { super(p); read(); }
+
+
+        /**
+         * < The job to be migrated
+         */
+        public int jobId;
+
+        /**
+         * < The number of candidate hosts for migration
+         */
+        public int numAskedHosts;
+
+        /**
+         * < The array of candidate host names
+         */
+        public Pointer askedHosts;
+
+        /**
+         * < The user ID of the submitter
+         */
+        public int userId;
+
+        /**
+         * < Job array index; must be 0 in JOB_NEW
+         */
+        public int idx;
+
+        /**
+         * < The user name of the submitter
+         */
+        public byte[] userName = new byte[MAX_LSB_NAME_LEN];
+    }
+
+
+
+    /**
+     * \brief  signal log.
+     */
+    public static class signalLog extends Structure {
+        public static class ByReference extends signalLog implements Structure.ByReference {}
+        public static class ByValue extends signalLog implements Structure.ByValue {}
+        public signalLog() {}
+        public signalLog(Pointer p) { super(p); read(); }
+
+
+        /**
+         * < The user ID of the submitter
+         */
+        public int userId;
+
+        /**
+         * < The unique ID of the job
+         */
+        public int jobId;
+
+        /**
+         * < Signal symbol from the set: DELETEJOB | KILL | KILLREQUEUE |REQUEUE_DONE | REQUEUE_EXIT | REQUEUE_PEND |REQUEUE_PSUSP_ADMIN | REQUEUE_PSUSP_USER | SIG_CHKPNT | SIG_CHKPNT_COPY
+         */
+        public String signalSymbol;
+
+        /**
+         * < The number of running times
+         */
+        public int runCount;
+
+        /**
+         * < Job array index; must be 0 in JOB_NEW
+         */
+        public int idx;
+
+        /**
+         * < The name of the submitter
+         */
+        public byte[] userName = new byte[MAX_LSB_NAME_LEN];
+    }
+
+
+
+    /**
+     * \brief logged when bqc command is invoked.
+     */
+    public static class queueCtrlLog extends Structure {
+        public static class ByReference extends queueCtrlLog implements Structure.ByReference {}
+        public static class ByValue extends queueCtrlLog implements Structure.ByValue {}
+        public queueCtrlLog() {}
+        public queueCtrlLog(Pointer p) { super(p); read(); }
+
+
+        /**
+         * < The queue control operation (see \ref lsb_queuecontrol)
+         */
+        public int opCode;
+
+        /**
+         * < The name of the queue
+         */
+        public byte[] queue = new byte[MAX_LSB_NAME_LEN];
+
+        /**
+         * < The user ID of the submitter
+         */
+        public int userId;
+
+        /**
+         * < The name of the submitter
+         */
+        public byte[] userName = new byte[MAX_LSB_NAME_LEN];
+
+        /**
+         * < Queue control message
+         */
+        public byte[] message = new byte[LibLsf.MAXLINELEN];
+    }
+
+
+
+/*
+*  \brief  new debug log.
+ */
+
+    public static class newDebugLog extends Structure {
+        public static class ByReference extends newDebugLog implements Structure.ByReference {}
+        public static class ByValue extends newDebugLog implements Structure.ByValue {}
+        public newDebugLog() {}
+        public newDebugLog(Pointer p) { super(p); read(); }
+
+
+        /**
+         * < The queue control operation
+         */
+        public int opCode;
+
+        /**
+         * < Debug level
+         */
+        public int level;
+
+        /**
+         * < Class of log
+         */
+        public int _logclass;
+
+        /**
+         * < Log enabled, disabled
+         */
+        public int turnOff;
+
+        /**
+         * < Name of log file
+         */
+        public byte[] logFileName = new byte[LibLsf.MAXLSFNAMELEN];
+
+        /**
+         * < The user ID of the submitter
+         */
+        public int userId;
+    }
+
+
+
+    /**
+     * \brief log the host control information.
+     */
+    public static class hostCtrlLog extends Structure {
+        public static class ByReference extends hostCtrlLog implements Structure.ByReference {}
+        public static class ByValue extends hostCtrlLog implements Structure.ByValue {}
+        public hostCtrlLog() {}
+        public hostCtrlLog(Pointer p) { super(p); read(); }
+
+
+        /**
+         * < The host control operation (See  \ref lsb_hostcontrol)
+         */
+        public int opCode;
+
+        /**
+         * < The name of the host
+         */
+        public byte[] host = new byte[LibLsf.MAXHOSTNAMELEN];
+
+        /**
+         * < The user ID of the submitter
+         */
+        public int userId;
+
+        /**
+         * < The name of the submitter
+         */
+        public byte[] userName = new byte[MAX_LSB_NAME_LEN];
+
+        /**
+         * < Host control message
+         */
+        public byte[] message = new byte[LibLsf.MAXLINELEN];
+    }
+
+
+
+    /**
+     * \brief logged when dynamic hosts are added to group.
+     */
+    public static class hgCtrlLog extends Structure {
+        public static class ByReference extends hgCtrlLog implements Structure.ByReference {}
+        public static class ByValue extends hgCtrlLog implements Structure.ByValue {}
+        public hgCtrlLog() {}
+        public hgCtrlLog(Pointer p) { super(p); read(); }
+
+
+        /**
+         * < The host control operation  (see \ref lsb_hostcontrol)
+         */
+        public int opCode;
+
+        /**
+         * < The name of the host
+         */
+        public byte[] host = new byte[LibLsf.MAXHOSTNAMELEN];
+
+        /**
+         * < The name of the host group
+         */
+        public byte[] grpname = new byte[LibLsf.MAXHOSTNAMELEN];
+
+        /**
+         * < The user ID of the submitter
+         */
+        public int userId;
+
+        /**
+         * < The name of the submitter
+         */
+        public byte[] userName = new byte[MAX_LSB_NAME_LEN];
+
+        /**
+         * < Host group control message
+         */
+        public byte[] message = new byte[LibLsf.MAXLINELEN];
+    }
+
+
+
+
+/* simulator is ready to schedule jobs */
+    public static final int SIMU_STATUS_READYSCHEDULE = 0x01;
+
+    /**
+     * \brief  mbatchd start log.
+     */
+    public static class mbdStartLog extends Structure {
+        public static class ByReference extends mbdStartLog implements Structure.ByReference {}
+        public static class ByValue extends mbdStartLog implements Structure.ByValue {}
+        public mbdStartLog() {}
+        public mbdStartLog(Pointer p) { super(p); read(); }
+
+
+        /**
+         * < The master host name
+         */
+        public byte[] master = new byte[LibLsf.MAXHOSTNAMELEN];
+
+        /**
+         * < The cluster name
+         */
+        public byte[] cluster = new byte[LibLsf.MAXLSFNAMELEN];
+
+        /**
+         * < The number of hosts in the cluster
+         */
+        public int numHosts;
+
+        /**
+         * < The number of queues in the cluster
+         */
+        public int numQueues;
+/*
+    public int    simDiffTime;
+    public int    pendJobsThreshold;
+    public int    simStatus;
+*/
+    }
+
+
+
+    public static class mbdSimStatusLog extends Structure {
+        public static class ByReference extends mbdSimStatusLog implements Structure.ByReference {}
+        public static class ByValue extends mbdSimStatusLog implements Structure.ByValue {}
+        public mbdSimStatusLog() {}
+        public mbdSimStatusLog(Pointer p) { super(p); read(); }
+
+
+/* simulator status */
+        public int simStatus;
+    }
+
+
+
+    /**
+     * \brief  mbatchd die log.
+     */
+    public static class mbdDieLog extends Structure {
+        public static class ByReference extends mbdDieLog implements Structure.ByReference {}
+        public static class ByValue extends mbdDieLog implements Structure.ByValue {}
+        public mbdDieLog() {}
+        public mbdDieLog(Pointer p) { super(p); read(); }
+
+
+        /**
+         * < The master host name
+         */
+        public byte[] master = new byte[LibLsf.MAXHOSTNAMELEN];
+
+        /**
+         * < The number of finished jobs that have been removed from the system and logged in the current event file
+         */
+        public int numRemoveJobs;
+
+        /**
+         * < The exit code from the master batch daemon
+         */
+        public int exitCode;
+
+        /**
+         * < mbatchd administrator control message
+         */
+        public byte[] message = new byte[LibLsf.MAXLINELEN];
+    }
+
+
+
+    /**
+     * \brief logged before mbatchd dies.
+     */
+    public static class unfulfillLog extends Structure {
+        public static class ByReference extends unfulfillLog implements Structure.ByReference {}
+        public static class ByValue extends unfulfillLog implements Structure.ByValue {}
+        public unfulfillLog() {}
+        public unfulfillLog(Pointer p) { super(p); read(); }
+
+
+        /**
+         * < The job ID.
+         */
+        public int jobId;
+
+        /**
+         * < The mbatchd has switched the job to a new queue but the sbatchd has not been informed of the switch
+         */
+        public int notSwitched;
+
+        /**
+         * < This signal was not sent to the job
+         */
+        public int sig;
+
+        /**
+         * < The job was not signaled to checkpoint itself
+         */
+        public int sig1;
+
+        /**
+         * < Checkpoint flags. see the chkpntLog structure below.
+         */
+        public int sig1Flags;
+
+        /**
+         * < The new checkpoint period for the job
+         */
+        public NativeLong chkPeriod;
+
+        /**
+         * < Flag for bmod running job's parameters
+         */
+        public int notModified;
+
+        /**
+         * < Job array index
+         */
+        public int idx;
+
+        /**
+         * < Option flags for pending job signals
+         */
+        public int miscOpts4PendSig;
+    }
+
+
+
+    public static final int TERM_UNKNOWN = 0;
+    public static final int TERM_PREEMPT = 1;
+    public static final int TERM_WINDOW = 2;
+    public static final int TERM_LOAD = 3;
+    public static final int TERM_OTHER = 4;
+    public static final int TERM_RUNLIMIT = 5;
+    public static final int TERM_DEADLINE = 6;
+    public static final int TERM_PROCESSLIMIT = 7;
+    public static final int TERM_FORCE_OWNER = 8;
+    public static final int TERM_FORCE_ADMIN = 9;
+    public static final int TERM_REQUEUE_OWNER = 10;
+    public static final int TERM_REQUEUE_ADMIN = 11;
+    public static final int TERM_CPULIMIT = 12;
+    public static final int TERM_CHKPNT = 13;
+    public static final int TERM_OWNER = 14;
+    public static final int TERM_ADMIN = 15;
+    public static final int TERM_MEMLIMIT = 16;
+    public static final int TERM_EXTERNAL_SIGNAL = 17;
+    public static final int TERM_RMS = 18;
+    public static final int TERM_ZOMBIE = 19;
+    public static final int TERM_SWAP = 20;
+    public static final int TERM_THREADLIMIT = 21;
+    public static final int TERM_SLURM = 22;
+    public static final int TERM_BUCKET_KILL = 23;
+    public static final int TERM_CTRL_PID = 24;
+    public static final int TERM_CWD_NOTEXIST = 25;
+
+    /**
+     * \brief logged in lsb.acct when a job finished.
+     */
+    public static class jobFinishLog extends Structure {
+        public static class ByReference extends jobFinishLog implements Structure.ByReference {}
+        public static class ByValue extends jobFinishLog implements Structure.ByValue {}
+        public jobFinishLog() {}
+        public jobFinishLog(Pointer p) { super(p); read(); }
+
+
+        /**
+         * < The unique ID for the job
+         */
+        public int jobId;
+
+        /**
+         * < The user ID of the submitter
+         */
+        public int userId;
+
+        /**
+         * < The user name of the submitter
+         */
+        public byte[] userName = new byte[MAX_LSB_NAME_LEN];
+
+        /**
+         * < Job submission options (see  \ref lsb_submit)
+         */
+        public int options;
+
+        /**
+         * < The number of processors requested for execution
+         */
+        public int numProcessors;
+
+        /**
+         * < The status of the job (See \ref lsb_readjobinfo)
+         */
+        public int jStatus;
+
+        /**
+         * < Job submission time
+         */
+        public NativeLong submitTime;
+
+        /**
+         * < The job started at or after this time
+         */
+        public NativeLong beginTime;
+
+        /**
+         * < If the job was not finished by this time, it was killed
+         */
+        public NativeLong termTime;
+
+        /**
+         * < Job dispatch time
+         */
+        public NativeLong startTime;
+
+        /**
+         * < The time the job finished
+         */
+        public NativeLong endTime;
+
+        /**
+         * < The name of the queue to which this job was submitted
+         */
+        public byte[] queue = new byte[MAX_LSB_NAME_LEN];
+
+        /**
+         * < Resource requirements
+         */
+        public String resReq;
+
+        /**
+         * < Submission host name
+         */
+        public byte[] fromHost = new byte[LibLsf.MAXHOSTNAMELEN];
+
+        /**
+         * < Current working directory
+         */
+        public String cwd;
+
+        /**
+         * < Input file name
+         */
+        public String inFile;
+
+        /**
+         * < Output file name
+         */
+        public String outFile;
+
+        /**
+         * < Error output file name
+         */
+        public String errFile;
+
+        /**
+         * < Job spool input file
+         */
+        public String inFileSpool;
+
+        /**
+         * < Job spool command file
+         */
+        public String commandSpool;
+
+        /**
+         * < Job file name
+         */
+        public String jobFile;
+
+        /**
+         * < The number of hosts considered for dispatching this job
+         */
+        public int numAskedHosts;
+
+        /**
+         * < The array of names of hosts considered for dispatching this job
+         */
+        public Pointer askedHosts;
+
+        /**
+         * < The CPU factor of the first execution host
+         */
+        public float hostFactor;
+
+        /**
+         * < The number of processors used for execution
+         */
+        public int numExHosts;
+
+        /**
+         * < The array of names of execution hosts
+         */
+        public Pointer execHosts;
+
+        /**
+         * < The total CPU time consumed by the job
+         */
+        public float cpuTime;
+
+        /**
+         * < Job name
+         */
+        public String jobName;
+
+        /**
+         * < Job command
+         */
+        public String command;
+
+        /**
+         * < Resource usage statistics.The lsfRusage structure is defined in <lsf/lsf.h>. Note that the availability of certain fields depends on the platform on which the sbatchd runs. The fields that do not make sense on this platform will be logged as -1.0.
+         */
+        public LibLsf.lsfRusage lsfRusage;
+
+        /**
+         * < The job dependency condition
+         */
+        public String dependCond;
+
+        /**
+         * < Time event string
+         */
+        public String timeEvent;
+
+        /**
+         * < The pre-execution command
+         */
+        public String preExecCmd;
+
+        /**
+         * < Name of the user to whom job related mail was sent
+         */
+        public String mailUser;
+
+        /**
+         * < The project name, used for accounting purposes.
+         */
+        public String projectName;
+
+        /**
+         * < Job's exit status
+         */
+        public int exitStatus;
+
+        /**
+         * < Maximum number of processors specified for the job
+         */
+        public int maxNumProcessors;
+
+        /**
+         * < Login shell specified by user
+         */
+        public String loginShell;
+
+        /**
+         * < Job array index
+         */
+        public int idx;
+
+        /**
+         * < Maximum memory used by job
+         */
+        public int maxRMem;
+
+        /**
+         * < Maximum swap used by job
+         */
+        public int maxRSwap;
+
+        /**
+         * < Advanced reservation ID
+         */
+        public String rsvId;
+
+        /**
+         * < Service class of the job
+         */
+        public String sla;
+
+        /**
+         * < Job exception handling mask
+         */
+        public int exceptMask;
+
+        /**
+         * < Placement information of LSF HPC jobs
+         */
+        public String additionalInfo;
+
+        /**
+         * < Job termination reason, see <lsf/lsbatch.h>
+         */
+        public int exitInfo;
+
+        /**
+         * < Job warning time period in seconds; -1 if unspecified
+         */
+        public int warningTimePeriod;
+
+        /**
+         * < Warning action, SIGNAL | CHKPNT | command, null if unspecified
+         */
+        public String warningAction;
+
+        /**
+         * < SAAP charged for job
+         */
+        public String chargedSAAP;
+
+        /**
+         * < LSF License Scheduler project name
+         */
+        public String licenseProject;
+
+        /**
+         * < Application profile under which the job runs.
+         */
+        public String app;
+
+        /**
+         * < Post-execution commands.
+         */
+        public String postExecCmd;
+
+        /**
+         * < Runtime estimate specified.
+         */
+        public int runtimeEstimation;
+
+        /**
+         * < Job group name
+         */
+        public String jgroup;
+
+        /**
+         * < Option2
+         */
+        public int options2;
+
+        /**
+         * < Job requeue exit values
+         */
+        public String requeueEValues;
+
+        /**
+         * < Resize notify command
+         */
+        public String notifyCmd;
+
+        /**
+         * < Last resize start time
+         */
+        public NativeLong lastResizeTime;
+
+        /**
+         * < Job description.
+         */
+        public String jobDescription;
+
+        /**
+         * < For new options in future
+         */
+        public submit_ext.ByReference submitExt;
+    }
+
+
+
+
+    /**
+     * \brief  load index log.
+     */
+
+    public static class loadIndexLog extends Structure {
+        public static class ByReference extends loadIndexLog implements Structure.ByReference {}
+        public static class ByValue extends loadIndexLog implements Structure.ByValue {}
+        public loadIndexLog() {}
+        public loadIndexLog(Pointer p) { super(p); read(); }
+
+
+        /**
+         * < The number of load indices
+         */
+        public int nIdx;
+
+        /**
+         * < The array of load index names
+         */
+        public Pointer name;
+    }
+
+
+
+    /**
+     * \brief  calendar log.
+     */
+    public static class calendarLog extends Structure {
+        public static class ByReference extends calendarLog implements Structure.ByReference {}
+        public static class ByValue extends calendarLog implements Structure.ByValue {}
+        public calendarLog() {}
+        public calendarLog(Pointer p) { super(p); read(); }
+
+
+        /**
+         * < Reserved for future use
+         */
+        public int options;
+
+        /**
+         * < The user ID of the submitter
+         */
+        public int userId;
+
+        /**
+         * < The name of the calendar
+         */
+        public String name;
+
+        /**
+         * < Description
+         */
+        public String desc;
+
+        /**
+         * < Calendar expression
+         */
+        public String calExpr;
+    }
+
+
+
+    /**
+     * \brief  job forward log.
+     */
+    public static class jobForwardLog extends Structure {
+        public static class ByReference extends jobForwardLog implements Structure.ByReference {}
+        public static class ByValue extends jobForwardLog implements Structure.ByValue {}
+        public jobForwardLog() {}
+        public jobForwardLog(Pointer p) { super(p); read(); }
+
+
+        /**
+         * < The unique ID of the job
+         */
+        public int jobId;
+
+        /**
+         * < The cluster name
+         */
+        public String cluster;
+
+        /**
+         * < Number of Reserved Hosts
+         */
+        public int numReserHosts;
+
+        /**
+         * < Reserved Host Names
+         */
+        public Pointer reserHosts;
+
+        /**
+         * < Job array index; must be 0 in JOB_NEW
+         */
+        public int idx;
+
+        /**
+         * < Remote job attributes from: \n JOB_FORWARD Remote batch job on submission side \n JOB_LEASE Lease job on submission side \n JOB_REMOTE_BATCH Remote batch job on execution side \n JOB_REMOTE_LEASE Lease job on execution side \n JOB_LEASE_RESYNC Lease job resync during restart \n JOB_REMOTE_RERUNNABLE Remote batch job rerunnable on execution cluster
+         */
+        public int jobRmtAttr;
+    }
+
+
+
+    /**
+     * \brief  job accept log.
+     */
+    public static class jobAcceptLog extends Structure {
+        public static class ByReference extends jobAcceptLog implements Structure.ByReference {}
+        public static class ByValue extends jobAcceptLog implements Structure.ByValue {}
+        public jobAcceptLog() {}
+        public jobAcceptLog(Pointer p) { super(p); read(); }
+
+
+        /**
+         * < The unique ID of the job
+         */
+        public int jobId;
+
+        /**
+         * < The unique ID of the remote job
+         */
+        public long remoteJid;
+
+        /**
+         * < The cluster name
+         */
+        public String cluster;
+
+        /**
+         * < Job array index; must be 0 in JOB_NEW
+         */
+        public int idx;
+
+        /**
+         * < Remote job attributes from: \n JOB_FORWARD Remote batch job on submission side \n JOB_LEASE Lease job on submission side \n JOB_REMOTE_BATCH Remote batch job on execution side \n JOB_REMOTE_LEASE Lease job on execution side \n JOB_LEASE_RESYNC Lease job resync during restart \n JOB_REMOTE_RERUNNABLE Remote batch job rerunnable on execution cluster
+         */
+        public int jobRmtAttr;
+    }
+
+
+
+    /**
+     * \brief  status Ack log.
+     */
+    public static class statusAckLog extends Structure {
+        public static class ByReference extends statusAckLog implements Structure.ByReference {}
+        public static class ByValue extends statusAckLog implements Structure.ByValue {}
+        public statusAckLog() {}
+        public statusAckLog(Pointer p) { super(p); read(); }
+
+
+        /**
+         * < The unique ID of the job
+         */
+        public int jobId;
+
+        /**
+         * < Line number of Status
+         */
+        public int statusNum;
+
+        /**
+         * < Job array index; must be 0 in JOB_NEW
+         */
+        public int idx;
+    }
+
+
+
+    /**
+     * \brief  job message log.
+     */
+    public static class jobMsgLog extends Structure {
+        public static class ByReference extends jobMsgLog implements Structure.ByReference {}
+        public static class ByValue extends jobMsgLog implements Structure.ByValue {}
+        public jobMsgLog() {}
+        public jobMsgLog(Pointer p) { super(p); read(); }
+
+
+        /**
+         * < The user ID of the submitter
+         */
+        public int usrId;
+
+        /**
+         * < The unique ID for the job
+         */
+        public int jobId;
+
+        /**
+         * < Message index
+         */
+        public int msgId;
+
+        /**
+         * < Message type
+         */
+        public int type;
+
+        /**
+         * < Message source
+         */
+        public String src;
+
+        /**
+         * < Message destination
+         */
+        public String dest;
+
+        /**
+         * < Message
+         */
+        public String msg;
+
+        /**
+         * < Job array index; must be 0 in JOB_NEW
+         */
+        public int idx;
+    }
+
+
+
+    /**
+     * \brief  job message ack log.
+     */
+    public static class jobMsgAckLog extends Structure {
+        public static class ByReference extends jobMsgAckLog implements Structure.ByReference {}
+        public static class ByValue extends jobMsgAckLog implements Structure.ByValue {}
+        public jobMsgAckLog() {}
+        public jobMsgAckLog(Pointer p) { super(p); read(); }
+
+
+        /**
+         * < The user ID of the submitter
+         */
+        public int usrId;
+
+        /**
+         * < The unique ID for the job
+         */
+        public int jobId;
+
+        /**
+         * < Message index
+         */
+        public int msgId;
+
+        /**
+         * < Message type
+         */
+        public int type;
+
+        /**
+         * < Message source
+         */
+        public String src;
+
+        /**
+         * < Message destination
+         */
+        public String dest;
+
+        /**
+         * < Message
+         */
+        public String msg;
+
+        /**
+         * < Job array index; must be 0 in JOB_NEW
+         */
+        public int idx;
+    }
+
+
+
+    /**
+     * \brief  job occupy request log. jobOccupyReqLog is for future use.
+     */
+    public static class jobOccupyReqLog extends Structure {
+        public static class ByReference extends jobOccupyReqLog implements Structure.ByReference {}
+        public static class ByValue extends jobOccupyReqLog implements Structure.ByValue {}
+        public jobOccupyReqLog() {}
+        public jobOccupyReqLog(Pointer p) { super(p); read(); }
+
+
+        /**
+         * < The user ID of the submitter
+         */
+        public int userId;
+
+        /**
+         * < The unique ID for the job
+         */
+        public int jobId;
+
+        /**
+         * < Number of Jobs Slots desired
+         */
+        public int numOccupyRequests;
+
+        /**
+         * < List of slots occupied
+         */
+        public Pointer occupyReqList;
+
+        /**
+         * < Job array index; must be 0 in JOB_NEW
+         */
+        public int idx;
+
+        /**
+         * < The name of the submitter
+         */
+        public byte[] userName = new byte[MAX_LSB_NAME_LEN];
+    }
+
+
+
+    /**
+     * \brief  job vacate log.jobVacatedLog is for future use.
+     */
+    public static class jobVacatedLog extends Structure {
+        public static class ByReference extends jobVacatedLog implements Structure.ByReference {}
+        public static class ByValue extends jobVacatedLog implements Structure.ByValue {}
+        public jobVacatedLog() {}
+        public jobVacatedLog(Pointer p) { super(p); read(); }
+
+
+        /**
+         * < The user ID of the submitter
+         */
+        public int userId;
+
+        /**
+         * < The unique ID for the job
+         */
+        public int jobId;
+
+        /**
+         * < Job array index; must be 0 in JOB_NEW
+         */
+        public int idx;
+
+        /**
+         * < The name of the submitter
+         */
+        public byte[] userName = new byte[MAX_LSB_NAME_LEN];
+    }
+
+
+
+    /**
+     * \brief  job force request log.
+     */
+    public static class jobForceRequestLog extends Structure {
+        public static class ByReference extends jobForceRequestLog implements Structure.ByReference {}
+        public static class ByValue extends jobForceRequestLog implements Structure.ByValue {}
+        public jobForceRequestLog() {}
+        public jobForceRequestLog(Pointer p) { super(p); read(); }
+
+
+        /**
+         * < The user ID of the submitter
+         */
+        public int userId;
+
+        /**
+         * < >1 for local/lease jobs; 0 for remote batch model
+         */
+        public int numExecHosts;
+
+        /**
+         * < The array of execution host names
+         */
+        public Pointer execHosts;
+
+        /**
+         * < The unique ID for the job
+         */
+        public int jobId;
+
+        /**
+         * < Job array index; must be 0 in JOB_NEW
+         */
+        public int idx;
+
+        /**
+         * < Job run options (RUNJOB_OPT_NOSTOP | JFLAG_URGENT_NOSTOP |JFLAG_URGENT)
+         */
+        public int options;
+
+        /**
+         * < The name of the submitter
+         */
+        public byte[] userName = new byte[MAX_LSB_NAME_LEN];
+
+        /**
+         * < The name of the queue to which this job was submitted
+         */
+        public String queue;
+    }
+
+
+
+    /**
+     * \brief  job chunck log.
+     */
+    public static class jobChunkLog extends Structure {
+        public static class ByReference extends jobChunkLog implements Structure.ByReference {}
+        public static class ByValue extends jobChunkLog implements Structure.ByValue {}
+        public jobChunkLog() {}
+        public jobChunkLog(Pointer p) { super(p); read(); }
+
+
+        /**
+         * < Size of array membJobId
+         */
+        public NativeLong membSize;
+
+        /**
+         * < Job ids of jobs in the chunk
+         */
+        public LongByReference membJobId;
+
+        /**
+         * < The number of processors used for execution
+         */
+        public NativeLong numExHosts;
+
+        /**
+         * < The array of names of execution hosts
+         */
+        public Pointer execHosts;
+    }
+
+
+
+    /**
+     * \brief  job external message log.
+     */
+    public static class jobExternalMsgLog extends Structure {
+        public static class ByReference extends jobExternalMsgLog implements Structure.ByReference {}
+        public static class ByValue extends jobExternalMsgLog implements Structure.ByValue {}
+        public jobExternalMsgLog() {}
+        public jobExternalMsgLog(Pointer p) { super(p); read(); }
+
+
+        /**
+         * < The unique ID for the job
+         */
+        public int jobId;
+
+        /**
+         * < Job array index; must be 0 in JOB_NEW
+         */
+        public int idx;
+
+        /**
+         * < The message index
+         */
+        public int msgIdx;
+
+        /**
+         * < Message description
+         */
+        public String desc;
+
+        /**
+         * < The user ID of the submitter
+         */
+        public int userId;
+
+        /**
+         * < Size of the message
+         */
+        public NativeLong dataSize;
+
+        /**
+         * < The time the author posted the message.
+         */
+        public NativeLong postTime;
+
+        /**
+         * < The status of the message
+         */
+        public int dataStatus;
+
+        /**
+         * < Name of attached data file. If no file is attached, use null.
+         */
+        public String fileName;
+
+        /**
+         * < The author of the message
+         */
+        public byte[] userName = new byte[MAX_LSB_NAME_LEN];
+    }
+
+
+
+    /**
+     * \brief  reservation request.
+     */
+    public static class rsvRes extends Structure {
+        public static class ByReference extends rsvRes implements Structure.ByReference {}
+        public static class ByValue extends rsvRes implements Structure.ByValue {}
+        public rsvRes() {}
+        public rsvRes(Pointer p) { super(p); read(); }
+
+
+        /**
+         * < Name of the resource (currently: host)
+         */
+        public String resName;
+
+        /**
+         * < Reserved counter (currently: cpu number)
+         */
+        public int count;
+
+        /**
+         * < Used of the reserved counter (not used)
+         */
+        public int usedAmt;
+    }
+
+
+
+    /**
+     * \brief for advanced reservation.
+     */
+    public static class rsvFinishLog extends Structure {
+        public static class ByReference extends rsvFinishLog implements Structure.ByReference {}
+        public static class ByValue extends rsvFinishLog implements Structure.ByValue {}
+        public rsvFinishLog() {}
+        public rsvFinishLog(Pointer p) { super(p); read(); }
+
+
+        /**
+         * < Time when the reservation is required
+         */
+        public NativeLong rsvReqTime;
+
+        /**
+         * < Same as the options field in the addRsvRequest(lsbatch.h)
+         */
+        public int options;
+
+        /**
+         * < The user who creat the reservation
+         */
+        public int uid;
+
+        /**
+         * < Reservation ID
+         */
+        public String rsvId;
+
+        /**
+         * < Client of the reservation
+         */
+        public String name;
+
+        /**
+         * < Number of resources reserved
+         */
+        public int numReses;
+
+        /**
+         * < Allocation vector
+         */
+        public Pointer /* rsvRes.ByReference */ alloc;
+
+        /**
+         * < Time window within which the reservation is active \n Two forms: int1-int2 or [day1]:hour1:0-[day2]:hour2:0
+         */
+        public String timeWindow;
+
+        /**
+         * < Duration in seconds. duration = to - from : when the reservation expired
+         */
+        public NativeLong duration;
+
+        /**
+         * < Creator of the reservation
+         */
+        public String creator;
+    }
+
+
+
+    /**
+     * \brief  CPU Profile Log
+     */
+    public static class cpuProfileLog extends Structure {
+        public static class ByReference extends cpuProfileLog implements Structure.ByReference {}
+        public static class ByValue extends cpuProfileLog implements Structure.ByValue {}
+        public cpuProfileLog() {}
+        public cpuProfileLog(Pointer p) { super(p); read(); }
+
+
+        /**
+         * < Queue name
+         */
+        public byte[] servicePartition = new byte[MAX_LSB_NAME_LEN];
+
+        /**
+         * < The number of CPU required
+         */
+        public int slotsRequired;
+
+        /**
+         * < The number of CPU actually allocated
+         */
+        public int slotsAllocated;
+
+        /**
+         * < The number of CPU borrowed
+         */
+        public int slotsBorrowed;
+
+        /**
+         * < The number of CPU lent
+         */
+        public int slotsLent;
+        /** note:  the number of CPU reserved = slotsAllocated - slotsBorrowed + slotsLent */
+    }
+
+
+
+    /**
+     * \brief  job resize start notify log.
+     */
+    public static class jobResizeNotifyStartLog extends Structure {
+        public static class ByReference extends jobResizeNotifyStartLog implements Structure.ByReference {}
+        public static class ByValue extends jobResizeNotifyStartLog implements Structure.ByValue {}
+        public jobResizeNotifyStartLog() {}
+        public jobResizeNotifyStartLog(Pointer p) { super(p); read(); }
+
+
+        /**
+         * <  JobId
+         */
+        public int jobId;
+
+        /**
+         * <  Index
+         */
+        public int idx;
+
+        /**
+         * <  Notify Id
+         */
+        public int notifyId;
+
+        /**
+         * <  Number of resized hosts.
+         */
+        public int numResizeHosts;
+
+        /**
+         * <  Resize Hosts
+         */
+        public Pointer resizeHosts;
+    }
+
+
+
+    /**
+     * \brief  job resize accept notify log.
+     */
+    public static class jobResizeNotifyAcceptLog extends Structure {
+        public static class ByReference extends jobResizeNotifyAcceptLog implements Structure.ByReference {}
+        public static class ByValue extends jobResizeNotifyAcceptLog implements Structure.ByValue {}
+        public jobResizeNotifyAcceptLog() {}
+        public jobResizeNotifyAcceptLog(Pointer p) { super(p); read(); }
+
+
+        /**
+         * <  JobId
+         */
+        public int jobId;
+
+        /**
+         * <  Index
+         */
+        public int idx;
+
+        /**
+         * <  Notify Id
+         */
+        public int notifyId;
+
+        /**
+         * <  Resize Notify command pid
+         */
+        public int resizeNotifyCmdPid;
+
+        /**
+         * <  Resize Notify command pgid
+         */
+        public int resizeNotifyCmdPGid;
+
+        /**
+         * <  Status
+         */
+        public int status;
+    }
+
+
+
+    /**
+     * \brief  job resize done notify log.
+     */
+    public static class jobResizeNotifyDoneLog extends Structure {
+        public static class ByReference extends jobResizeNotifyDoneLog implements Structure.ByReference {}
+        public static class ByValue extends jobResizeNotifyDoneLog implements Structure.ByValue {}
+        public jobResizeNotifyDoneLog() {}
+        public jobResizeNotifyDoneLog(Pointer p) { super(p); read(); }
+
+
+        /**
+         * <  JobId
+         */
+        public int jobId;
+
+        /**
+         * <  Index
+         */
+        public int idx;
+
+        /**
+         * <  Notify Id
+         */
+        public int notifyId;
+
+        /**
+         * <  Status
+         */
+        public int status;
+    }
+
+
+
+    /**
+     * \brief  job resize release log.
+     */
+    public static class jobResizeReleaseLog extends Structure {
+        public static class ByReference extends jobResizeReleaseLog implements Structure.ByReference {}
+        public static class ByValue extends jobResizeReleaseLog implements Structure.ByValue {}
+        public jobResizeReleaseLog() {}
+        public jobResizeReleaseLog(Pointer p) { super(p); read(); }
+
+
+        /**
+         * <  JobId
+         */
+        public int jobId;
+
+        /**
+         * <  Index
+         */
+        public int idx;
+
+        /**
+         * <  Request Id
+         */
+        public int reqId;
+
+        /**
+         * <  Options
+         */
+        public int options;
+
+        /**
+         * <  User Id
+         */
+        public int userId;
+
+        /**
+         * <  User Name
+         */
+        public String userName;
+
+        /**
+         * <  Resize Notify command
+         */
+        public String resizeNotifyCmd;
+
+        /**
+         * <  Number of resized hosts
+         */
+        public int numResizeHosts;
+
+        /**
+         * <  Resized hosts
+         */
+        public Pointer resizeHosts;
+    }
+
+
+
+    /**
+     * \brief  job resize cancel log.
+     */
+    public static class jobResizeCancelLog extends Structure {
+        public static class ByReference extends jobResizeCancelLog implements Structure.ByReference {}
+        public static class ByValue extends jobResizeCancelLog implements Structure.ByValue {}
+        public jobResizeCancelLog() {}
+        public jobResizeCancelLog(Pointer p) { super(p); read(); }
+
+
+        /**
+         * <  JobId
+         */
+        public int jobId;
+
+        /**
+         * <  Index
+         */
+        public int idx;
+
+        /**
+         * <  User Id
+         */
+        public int userId;
+
+        /**
+         * <  User name
+         */
+        public String userName;
+    }
+
+
+
+    /**
+     * \brief log the running rusage of a job in the lsb.stream file
+     */
+    public static class jobRunRusageLog extends Structure {
+        public static class ByReference extends jobRunRusageLog implements Structure.ByReference {}
+        public static class ByValue extends jobRunRusageLog implements Structure.ByValue {}
+        public jobRunRusageLog() {}
+        public jobRunRusageLog(Pointer p) { super(p); read(); }
+
+
+        /**
+         * < The unique ID of the job
+         */
+        public int jobid;
+
+        /**
+         * < Job array index; must be 0 in JOB_NEW
+         */
+        public int idx;
+
+        /**
+         * < jrusage
+         */
+        public LibLsf.jRusage jrusage;
+    }
+
+
+
+    /**
+     * \brief  SLA event log.
+     */
+    public static class slaLog extends Structure {
+        public static class ByReference extends slaLog implements Structure.ByReference {}
+        public static class ByValue extends slaLog implements Structure.ByValue {}
+        public slaLog() {}
+        public slaLog(Pointer p) { super(p); read(); }
+
+
+        /**
+         * < Service class name
+         */
+        public String name;
+
+        /**
+         * < Consumer name associated with the service class
+         */
+        public String consumer;
+
+        /**
+         * < Objectives
+         */
+        public int goaltype;
+
+        /**
+         * < The service class state (ontime, delayed)
+         */
+        public int state;
+
+        /**
+         * < Optimum number of job slots (or concurrently running jobs) needed for the  service class to meet its service-level goals
+         */
+        public int optimum;
+
+        /**
+         * < Job counters for the service class
+         */
+        public int[] counters = new int[NUM_JGRP_COUNTERS];
+    }
+
+
+
+    /**
+     * \brief  a wrap of structure perfmonLog for performance metrics project
+     */
+    public static class perfmonLogInfo extends Structure {
+        public static class ByReference extends perfmonLogInfo implements Structure.ByReference {}
+        public static class ByValue extends perfmonLogInfo implements Structure.ByValue {}
+        public perfmonLogInfo() {}
+        public perfmonLogInfo(Pointer p) { super(p); read(); }
+
+
+        /**
+         * <  Sample period
+         */
+        public int samplePeriod;
+
+        /**
+         * <  Metrics
+         */
+        public IntByReference metrics;
+
+        /**
+         * <  Start time
+         */
+        public NativeLong startTime;
+
+        /**
+         * <  Log time
+         */
+        public NativeLong logTime;
+    }
+
+
+
+    /**
+     * \brief performance metrics log in lsb.stream
+     */
+    public static class perfmonLog extends Structure {
+        public static class ByReference extends perfmonLog implements Structure.ByReference {}
+        public static class ByValue extends perfmonLog implements Structure.ByValue {}
+        public perfmonLog() {}
+        public perfmonLog(Pointer p) { super(p); read(); }
+
+
+        /**
+         * < Sample rate
+         */
+        public int samplePeriod;
+
+        /**
+         * < Number of Queries
+         */
+        public int totalQueries;
+
+        /**
+         * < Number of Job Query
+         */
+        public int jobQuries;
+
+        /**
+         * < Number of Queue Query
+         */
+        public int queueQuries;
+
+        /**
+         * < Number of Host Query
+         */
+        public int hostQuries;
+
+        /**
+         * < Number of Submission Requests
+         */
+        public int submissionRequest;
+
+        /**
+         * < Number of Jobs Submitted
+         */
+        public int jobSubmitted;
+
+        /**
+         * < Number of Dispatched Jobs
+         */
+        public int dispatchedjobs;
+
+        /**
+         * < Number of Job Completed
+         */
+        public int jobcompleted;
+
+        /**
+         * < Number of MultiCluster Jobs Sent
+         */
+        public int jobMCSend;
+
+        /**
+         * < Number of MultiCluster Jobs Received
+         */
+        public int jobMCReceive;
+
+        /**
+         * < Start Time
+         */
+        public NativeLong startTime;
+    }
+
+
+
+    /**
+     * \brief task finish log.Task accounting record in ssched.acct
+     */
+    public static class taskFinishLog extends Structure {
+        public static class ByReference extends taskFinishLog implements Structure.ByReference {}
+        public static class ByValue extends taskFinishLog implements Structure.ByValue {}
+        public taskFinishLog() {}
+        public taskFinishLog(Pointer p) { super(p); read(); }
+
+
+        /**
+         * <  Job finish event
+         */
+        public jobFinishLog jobFinishLog;
+
+        /**
+         * < Task ID
+         */
+        public int taskId;
+
+        /**
+         * < Task index
+         */
+        public int taskIdx;
+
+        /**
+         * < Name of task
+         */
+        public String taskName;
+
+        /**
+         * < Bit mask of task options: \n TASK_IN_FILE (0x01)-specify input file \n TASK_OUT_FILE (0x02)-specify output file \n TASK_ERR_FILE (0x04)-specify error file \n TASK_PRE_EXEC (0x08)-specify pre-exec command \n TASK_POST_EXEC (0x10)-specify post-exec command \n TASK_NAME (0x20)-specify task name
+         */
+        public int taskOptions;
+
+        /**
+         * < Task Exit Reason \n TASK_EXIT_NORMAL = 0- normal exit \n TASK_EXIT_INIT = 1-generic task initialization failure \n TASK_EXIT_PATH = 2-failed to initialize path \n TASK_EXIT_NO_FILE = 3-failed to create task file \n TASK_EXIT_PRE_EXEC = 4- task pre-exec failed \n TASK_EXIT_NO_PROCESS = 5-fork failed \n TASK_EXIT_XDR = 6-xdr communication error \n TASK_EXIT_NOMEM = 7- no memory \n TASK_EXIT_SYS = 8-system call failed \n TASK_EXIT_TSCHILD_EXEC = 9-failed to run sschild \n TASK_ [...]
+         */
+        public int taskExitReason;
+    }
+
+
+
+    /**
+     * \brief End of stream event. The stream is moved to lsb.stream.0 and
+     * a new lsb.stream is opened. Readers of lsb.stream when encounter
+     * the event EVENT_END_OF_STREAM should close and reopen the
+     * lsb.stream file.
+     */
+    public static class eventEOSLog extends Structure {
+        public static class ByReference extends eventEOSLog implements Structure.ByReference {}
+        public static class ByValue extends eventEOSLog implements Structure.ByValue {}
+        public eventEOSLog() {}
+        public eventEOSLog(Pointer p) { super(p); read(); }
+
+
+        /**
+         * < Event end of stream
+         */
+        public int eos;
+    }
+
+
+
+    /**
+     * \brief job resize event: indicating a realized job allocation change
+     */
+    public static class jobResizeLog extends Structure {
+        public static class ByReference extends jobResizeLog implements Structure.ByReference {}
+        public static class ByValue extends jobResizeLog implements Structure.ByValue {}
+        public jobResizeLog() {}
+        public jobResizeLog(Pointer p) { super(p); read(); }
+
+
+        /**
+         * <  JobId
+         */
+        public int jobId;
+
+        /**
+         * <  Index
+         */
+        public int idx;
+
+        /**
+         * <  Start time
+         */
+        public NativeLong startTime;
+
+        /**
+         * <  User Id
+         */
+        public int userId;
+
+        /**
+         * <  User name
+         */
+        public byte[] userName = new byte[MAX_LSB_NAME_LEN];
+
+        /**
+         * < 0 grow, 1 shrink
+         */
+        public int resizeType;
+
+        /**
+         * < The start time of last allocation
+         */
+        public NativeLong lastResizeStartTime;
+
+        /**
+         * < The finish time of last allocation
+         */
+        public NativeLong lastResizeFinishTime;
+
+        /**
+         * < Allocation before the resize
+         */
+        public int numExecHosts;
+
+        /**
+         * <  Execute hosts
+         */
+        public Pointer execHosts;
+
+        /**
+         * < The delta of the allocation change
+         */
+        public int numResizeHosts;
+
+        /**
+         * <  Resize hosts
+         */
+        public Pointer resizeHosts;
+    }
+
+
+
+    /**
+     * \brief  Log event types.
+     */
+    public static class eventLog extends Union {
+        /**
+         * <  Job new event
+         */
+        public jobNewLog jobNewLog;
+
+        /**
+         * <  Job start event
+         */
+        public jobStartLog jobStartLog;
+
+        /**
+         * <  Job status event
+         */
+        public jobStatusLog jobStatusLog;
+
+        /**
+         * <  sbatchd job status event
+         */
+        public sbdJobStatusLog sbdJobStatusLog;
+
+        /**
+         * <  Job switch event
+         */
+        public jobSwitchLog jobSwitchLog;
+
+        /**
+         * <  Job move event
+         */
+        public jobMoveLog jobMoveLog;
+
+        /**
+         * <  Queue control event
+         */
+        public queueCtrlLog queueCtrlLog;
+
+/* New debug event*/
+        public newDebugLog newDebugLog;
+
+        /**
+         * <  Host control event
+         */
+        public hostCtrlLog hostCtrlLog;
+
+        /**
+         * <  mbatchd start event
+         */
+        public mbdStartLog mbdStartLog;
+
+        /**
+         * <  mbatchd die event
+         */
+        public mbdDieLog mbdDieLog;
+
+        /**
+         * <  Unfulfill event
+         */
+        public unfulfillLog unfulfillLog;
+
+        /**
+         * <  Job finish event
+         */
+        public jobFinishLog jobFinishLog;
+
+        /**
+         * <  Load index event
+         */
+        public loadIndexLog loadIndexLog;
+
+        /**
+         * <  Migration initiated event
+         */
+        public migLog migLog;
+
+        /**
+         * <  Calendar event
+         */
+        public calendarLog calendarLog;
+
+        /**
+         * <  Job forward event
+         */
+        public jobForwardLog jobForwardLog;
+
+        /**
+         * <  Job accept event
+         */
+        public jobAcceptLog jobAcceptLog;
+
+        /**
+         * <  Job accepted from another  cluster event
+         */
+        public statusAckLog statusAckLog;
+
+        /**
+         * <  Job signal event
+         */
+        public signalLog signalLog;
+
+        /**
+         * <  Job execution event
+         */
+        public jobExecuteLog jobExecuteLog;
+
+        /**
+         * <  Job message event
+         */
+        public jobMsgLog jobMsgLog;
+
+        /**
+         * <  Job message ackknowledge event
+         */
+        public jobMsgAckLog jobMsgAckLog;
+
+        /**
+         * <  Job requeue event
+         */
+        public jobRequeueLog jobRequeueLog;
+
+        /**
+         * <  Checkpoint event
+         */
+        public chkpntLog chkpntLog;
+
+        /**
+         * <  Signal with action event
+         */
+        public sigactLog sigactLog;
+
+        /**
+         * <  Job occupy request event
+         */
+        public jobOccupyReqLog jobOccupyReqLog;
+
+        /**
+         * <  Job vacate event
+         */
+        public jobVacatedLog jobVacatedLog;
+
+        /**
+         * <  Job start accept event
+         */
+        public jobStartAcceptLog jobStartAcceptLog;
+
+        /**
+         * <  Job clean event
+         */
+        public jobCleanLog jobCleanLog;
+
+        /**
+         * <  Job exception event
+         */
+        public jobExceptionLog jobExceptionLog;
+
+        /**
+         * <  Job group new event
+         */
+        public jgrpNewLog jgrpNewLog;
+
+        /**
+         * <  Job group Ctrl event
+         */
+        public jgrpCtrlLog jgrpCtrlLog;
+
+        /**
+         * <  Job Force Request event
+         */
+        public jobForceRequestLog jobForceRequestLog;
+
+        /**
+         * <  Event switch event
+         */
+        public logSwitchLog logSwitchLog;
+
+        /**
+         * <  Job modify event
+         */
+        public jobModLog jobModLog;
+
+        /**
+         * <  Job group stratus event
+         */
+        public jgrpStatusLog jgrpStatusLog;
+
+        /**
+         * <  Job attribute setting event
+         */
+        public jobAttrSetLog jobAttrSetLog;
+
+        /**
+         * <  Job external message event
+         */
+        public jobExternalMsgLog jobExternalMsgLog;
+
+        /**
+         * <  Job chunk event
+         */
+        public jobChunkLog jobChunkLog;
+
+        /**
+         * < sbatchd  unreported status event
+         */
+        public sbdUnreportedStatusLog sbdUnreportedStatusLog;
+
+        /**
+         * <  Reservation finish event
+         */
+        public rsvFinishLog rsvFinishLog;
+
+        /**
+         * <  Host group control Log
+         */
+        public hgCtrlLog hgCtrlLog;
+
+        /**
+         * <  cpu profile event
+         */
+        public cpuProfileLog cpuProfileLog;
+
+        /**
+         * <  Data logging event
+         */
+        public dataLoggingLog dataLoggingLog;
+
+        /**
+         * <  Job run rusage event
+         */
+        public jobRunRusageLog jobRunRusageLog;
+
+        /**
+         * <  Event EOS event
+         */
+        public eventEOSLog eventEOSLog;
+
+        /**
+         * <  SLA event
+         */
+        public slaLog slaLog;
+
+        /**
+         * <  Performance event
+         */
+        public perfmonLog perfmonLog;
+
+        /**
+         * <  Task finish event
+         */
+        public taskFinishLog taskFinishLog;
+
+        /**
+         * <  Job resize notify start event
+         */
+        public jobResizeNotifyStartLog jobResizeNotifyStartLog;
+
+        /**
+         * <  Job resize notify accept event
+         */
+        public jobResizeNotifyAcceptLog jobResizeNotifyAcceptLog;
+
+        /**
+         * <  Job resize notify done event
+         */
+        public jobResizeNotifyDoneLog jobResizeNotifyDoneLog;
+
+        /**
+         * <  Job resize release event
+         */
+        public jobResizeReleaseLog jobResizeReleaseLog;
+
+        /**
+         * <  Job resize cancel event
+         */
+        public jobResizeCancelLog jobResizeCancelLog;
+
+        /**
+         * <  Job resize event
+         */
+        public jobResizeLog jobResizeLog;
+
+/*#if defined(LSF_SIMULATOR)*/
+/**< Job array element event */
+        /*public jobArrayElementLog jobArrayElementLog;*/
+
+        /**< LSF simulator status event */
+        /*public mbdSimStatusLog   mbdSimStatusLog;*/
+        /*#endif*/
+    }
+
+
+
+
+    /**
+     * \brief  event records.
+     */
+    public static class eventRec extends Structure {
+        public static class ByReference extends eventRec implements Structure.ByReference {}
+        public static class ByValue extends eventRec implements Structure.ByValue {}
+        public eventRec() {}
+        public eventRec(Pointer p) { super(p); read(); }
+
+
+        /**
+         * < The mbatchd version number
+         */
+        public byte[] version = new byte[MAX_VERSION_LEN];
+
+        /**
+         * < Event type in \ref event_types
+         */
+        public int type;
+
+        /**
+         * < The time the event occurred
+         */
+        public NativeLong eventTime;
+
+        /**
+         * < The information for this type of event, contained in a structure  corresponding to type
+         */
+        public eventLog eventLog;
+    }
+
+
+
+    public static class eventLogFile extends Structure {
+        public static class ByReference extends eventLogFile implements Structure.ByReference {}
+        public static class ByValue extends eventLogFile implements Structure.ByValue {}
+        public eventLogFile() {}
+        public eventLogFile(Pointer p) { super(p); read(); }
+
+
+/* event file directory */
+        public byte[] eventDir = new byte[LibLsf.MAXFILENAMELEN];
+
+/* start and end event time */
+        public NativeLong beginTime, endTime;
+    }
+
+
+
+    public static class eventLogHandle extends Structure {
+        public static class ByReference extends eventLogHandle implements Structure.ByReference {}
+        public static class ByValue extends eventLogHandle implements Structure.ByValue {}
+        public eventLogHandle() {}
+        public eventLogHandle(Pointer p) { super(p); read(); }
+
+
+/* open event file pointer */
+        public Pointer fp;
+
+/* current open events file name */
+        public byte[] openEventFile = new byte[LibLsf.MAXFILENAMELEN];
+
+/* current open event file number */
+        public int curOpenFile;
+        public int lastOpenFile;                   /* last open event file number, 0
+                  means lsb.events */
+    }
+
+
+
+
+    public static final String LSF_JOBIDINDEX_FILENAME = "lsb.events.index";
+    public static final String LSF_JOBIDINDEX_FILETAG = "#LSF_JOBID_INDEX_FILE";
+
+/* structures used to handle jobId index file */
+
+    public static class jobIdIndexS extends Structure {
+        public static class ByReference extends jobIdIndexS implements Structure.ByReference {}
+        public static class ByValue extends jobIdIndexS implements Structure.ByValue {}
+        public jobIdIndexS() {}
+        public jobIdIndexS(Pointer p) { super(p); read(); }
+
+
+/* the index file name */
+        public byte[] fileName = new byte[LibLsf.MAXFILENAMELEN];
+
+/* open index file pointer */
+        public Pointer fp;
+
+/* version number for future use */
+        public float version;
+
+/* total number of rows(files) indices */
+        public int totalRows;
+
+/* last update time */
+        public NativeLong lastUpdate;
+
+/* current rows */
+        public int curRow;
+        /* the event file currently handled is */
+        /* (totalRows - curRow + 1) */
+
+/* time stamp of current row */
+        public NativeLong timeStamp;
+
+/* min jobId in that row */
+        public long minJobId;
+
+/* max jobId in that row */
+        public long maxJobId;
+
+/* total number of jobIds */
+        public int totalJobIds;
+
+/* jobId array of current row */
+        public IntByReference jobIds;
+    }
+
+
+
+/* structures used to hold one element of sorted int list */
+
+    public static class sortIntList extends Structure {
+        public static class ByReference extends sortIntList implements Structure.ByReference {}
+        public static class ByValue extends sortIntList implements Structure.ByValue {}
+        public sortIntList() {}
+        public sortIntList(Pointer p) { super(p); read(); }
+
+        public int value;
+
+/* points to next element */
+        public sortIntList.ByReference forw;
+
+/* points to prior element */
+        public sortIntList.ByReference back;
+    }
+
+
+
+    public static class nqsStatusReq extends Structure {
+        public static class ByReference extends nqsStatusReq implements Structure.ByReference {}
+        public static class ByValue extends nqsStatusReq implements Structure.ByValue {}
+        public nqsStatusReq() {}
+        public nqsStatusReq(Pointer p) { super(p); read(); }
+
+        public long jobId;
+        public int opCode;
+        public int reportCode;
+        public String nqsQueue;
+        public int fromUid;
+        public String fromUserName;
+        public String fromHostName;
+        public int idx;
+    }
+
+
+
+    public static class nqsStatusReply extends Structure {
+        public static class ByReference extends nqsStatusReply implements Structure.ByReference {}
+        public static class ByValue extends nqsStatusReply implements Structure.ByValue {}
+        public nqsStatusReply() {}
+        public nqsStatusReply(Pointer p) { super(p); read(); }
+
+        public String orgHost;
+        public String orgUser;
+        public NativeLong startTime;
+        public String jobName;
+        public String nqsQueue;
+        public String lsbManager;
+        public int options;
+        public String outFile;
+        public String errFile;
+    }
+
+
+
+/*
+*  SBD uses the following data structure to communicate with
+*  the resource manager.
+*
+ */
+    public static final int LSB_MAX_SD_LENGTH = 128;
+
+    public static class lsbMsgHdr extends Structure {
+        public static class ByReference extends lsbMsgHdr implements Structure.ByReference {}
+        public static class ByValue extends lsbMsgHdr implements Structure.ByValue {}
+        public lsbMsgHdr() {}
+        public lsbMsgHdr(Pointer p) { super(p); read(); }
+
+        public int usrId;
+        public long jobId;
+        public int msgId;
+        public int type;
+        public String src;
+        public String dest;
+    }
+
+
+
+    public static class lsbMsg extends Structure {
+        public static class ByReference extends lsbMsg implements Structure.ByReference {}
+        public static class ByValue extends lsbMsg implements Structure.ByValue {}
+        public lsbMsg() {}
+        public lsbMsg(Pointer p) { super(p); read(); }
+
+        public lsbMsgHdr.ByReference header;
+        public String msg;
+    }
+
+
+
+/* data structures related to API_CONF */
+
+    public static final int CONF_NO_CHECK = 0x00;
+    public static final int CONF_CHECK = 0x01;
+    public static final int CONF_EXPAND = 0X02;
+    public static final int CONF_RETURN_HOSTSPEC = 0X04;
+    public static final int CONF_NO_EXPAND = 0X08;
+    public static final int CONF_HAS_CU = 0X10;
+
+    public static class paramConf extends Structure {
+        public static class ByReference extends paramConf implements Structure.ByReference {}
+        public static class ByValue extends paramConf implements Structure.ByValue {}
+        public paramConf() {}
+        public paramConf(Pointer p) { super(p); read(); }
+
+        public parameterInfo.ByReference param;
+    }
+
+
+
+    public static class userConf extends Structure {
+        public static class ByReference extends userConf implements Structure.ByReference {}
+        public static class ByValue extends userConf implements Structure.ByValue {}
+        public userConf() {}
+        public userConf(Pointer p) { super(p); read(); }
+
+        public int numUgroups;
+        public Pointer /* groupInfoEnt.ByReference */ ugroups;
+        public int numUsers;
+        public Pointer /* userInfoEnt.ByReference */ users;
+        public int numUserEquivalent;
+        public Pointer /* userEquivalentInfoEnt.ByReference */ userEquivalent;
+        public int numUserMapping;
+        public Pointer /* userMappingInfoEnt.ByReference */ userMapping;
+    }
+
+
+
+    public static class hostConf extends Structure {
+        public static class ByReference extends hostConf implements Structure.ByReference {}
+        public static class ByValue extends hostConf implements Structure.ByValue {}
+        public hostConf() {}
+        public hostConf(Pointer p) { super(p); read(); }
+
+        public int numHosts;
+        public Pointer /* hostInfoEnt.ByReference */ hosts;
+        public int numHparts;
+        public Pointer /* hostPartInfoEnt.ByReference */ hparts;
+        public int numHgroups;
+        public Pointer /* groupInfoEnt.ByReference */ hgroups;
+    }
+
+
+
+    /**
+     * \brief  lsb shared resource Instance.
+     */
+    public static class lsbSharedResourceInstance extends Structure {
+        public static class ByReference extends lsbSharedResourceInstance implements Structure.ByReference {}
+        public static class ByValue extends lsbSharedResourceInstance implements Structure.ByValue {}
+        public lsbSharedResourceInstance() {}
+        public lsbSharedResourceInstance(Pointer p) { super(p); read(); }
+
+
+        /**
+         * < Value used by mbatchd
+         */
+        public String totalValue;
+
+        /**
+         * < Reserved value
+         */
+        public String rsvValue;
+
+        /**
+         * < Number of Hosts associated with the resource.
+         */
+        public int nHosts;
+
+        /**
+         * < Hosts list
+         */
+        public Pointer hostList;
+    }
+
+
+
+    /**
+     * \brief lsb shared resource information.
+     */
+    public static class lsbSharedResourceInfo extends Structure {
+        public static class ByReference extends lsbSharedResourceInfo implements Structure.ByReference {}
+        public static class ByValue extends lsbSharedResourceInfo implements Structure.ByValue {}
+        public lsbSharedResourceInfo() {}
+        public lsbSharedResourceInfo(Pointer p) { super(p); read(); }
+
+
+        /**
+         * < Resource name
+         */
+        public String resourceName;
+
+        /**
+         * < Number of instances
+         */
+        public int nInstances;
+
+        /**
+         * < List of instances
+         */
+        public Pointer /* lsbSharedResourceInstance.ByReference */ instances;
+    }
+
+
+
+    public static class queueConf extends Structure {
+        public static class ByReference extends queueConf implements Structure.ByReference {}
+        public static class ByValue extends queueConf implements Structure.ByValue {}
+        public queueConf() {}
+        public queueConf(Pointer p) { super(p); read(); }
+
+        public int numQueues;
+        public Pointer /* queueInfoEnt.ByReference */ queues;
+    }
+
+
+
+    /**
+     * \brief  frame element information.
+     */
+    public static class frameElementInfo extends Structure {
+        public static class ByReference extends frameElementInfo implements Structure.ByReference {}
+        public static class ByValue extends frameElementInfo implements Structure.ByValue {}
+        public frameElementInfo() {}
+        public frameElementInfo(Pointer p) { super(p); read(); }
+
+
+        /**
+         * <  The job index in the frame job array.
+         */
+        public int jobindex;
+
+        /**
+         * <  The job status.
+         */
+        public int jobState;
+
+        /**
+         * <  The start frame of this frame job.
+         */
+        public int start;
+
+        /**
+         * <  The end frame of this frame job.
+         */
+        public int end;
+
+        /**
+         * <  The step of this frame job.
+         */
+        public int step;
+
+        /**
+         * <  The chunk size of this frame job.
+         */
+        public int chunk;
+    }
+
+
+
+    /**
+     * \brief  frame job Infomation.
+     */
+    public static class frameJobInfo extends Structure {
+        public static class ByReference extends frameJobInfo implements Structure.ByReference {}
+        public static class ByValue extends frameJobInfo implements Structure.ByValue {}
+        public frameJobInfo() {}
+        public frameJobInfo(Pointer p) { super(p); read(); }
+
+
+        /**
+         * < The job ID that the LSF system assigned to the frame job array.
+         */
+        public long jobGid;
+
+        /**
+         * < The max job number in one frame job array.
+         */
+        public int maxJob;
+
+        /**
+         * < The user submitted the frame job array.
+         */
+        public byte[] userName = new byte[MAX_LSB_NAME_LEN];
+
+        /**
+         * < Full job name
+         */
+        public byte[] jobName = new byte[LibLsf.MAXLINELEN];
+
+        /**
+         * < The full job name of the frame job array.  frameElementPtr The pointer to frame ob array table.
+         */
+        public frameElementInfo.ByReference frameElementPtr;
+    }
+
+
+
+    public static class nqsRusageReq extends Structure {
+        public static class ByReference extends nqsRusageReq implements Structure.ByReference {}
+        public static class ByValue extends nqsRusageReq implements Structure.ByValue {}
+        public nqsRusageReq() {}
+        public nqsRusageReq(Pointer p) { super(p); read(); }
+
+        public long jobId;
+        public int mem;
+        public float cpuTime;
+    }
+
+
+
+    public static class nqsRusageReply extends Structure {
+        public static class ByReference extends nqsRusageReply implements Structure.ByReference {}
+        public static class ByValue extends nqsRusageReply implements Structure.ByValue {}
+        public nqsRusageReply() {}
+        public nqsRusageReply(Pointer p) { super(p); read(); }
+
+        public int status;
+    }
+
+
+
+/* end of data structures related to API_CONF */
+
+/*
+*  Structure used for the Advance Reservation API
+*
+*  MBD allows the LSF administration to make advance reservation on
+*  behalf of a user, group or or for system maintenance purposes.
+*  Clients can add a reservation, remove a reservation and show
+*  reservation statuses.  The following data structures are used to
+*  encapsulate these requests
+*
+*     addRsvRequest: to add a reservation
+*     rmRsvRequest:  to remove a reservation
+*     rsvInfoEnt:    to display reservation information
+*
+ */
+
+    public static class _rsvEventInfo_prePost_t extends Structure {
+        public static class ByReference extends _rsvEventInfo_prePost_t implements Structure.ByReference {}
+        public static class ByValue extends _rsvEventInfo_prePost_t implements Structure.ByValue {}
+        public _rsvEventInfo_prePost_t() {}
+        public _rsvEventInfo_prePost_t(Pointer p) { super(p); read(); }
+
+        public int shift;
+    }
+
+
+
+    public static final int RSV_EXECEVENTTYPE_PRE = 1;
+    public static final int RSV_EXECEVENTTYPE_POST = 2;
+
+    public static final String RSV_EXECEVENTNAME_PRE = "pre";
+    public static final String RSV_EXECEVENTNAME_POST = "post";
+
+    /**
+     * \brief  reservation excution event
+     */
+    public static class _rsvExecEvent_t extends Structure {
+        public static class ByReference extends _rsvExecEvent_t implements Structure.ByReference {}
+        public static class ByValue extends _rsvExecEvent_t implements Structure.ByValue {}
+        public _rsvExecEvent_t() {}
+        public _rsvExecEvent_t(Pointer p) { super(p); read(); }
+
+
+        /**
+         * < Event type
+         */
+        public int type;
+
+        /**
+         * < Boolean: is there additional info?
+         */
+        public int infoAttached;
+
+        /**
+         * < Info pertaining to event, such as offset
+         */
+        public Pointer info;
+    }
+
+
+
+    /**
+     * \brief  reservation excution command
+     */
+    public static class _rsvExecCmd_t extends Structure {
+        public static class ByReference extends _rsvExecCmd_t implements Structure.ByReference {}
+        public static class ByValue extends _rsvExecCmd_t implements Structure.ByValue {}
+        public _rsvExecCmd_t() {}
+        public _rsvExecCmd_t(Pointer p) { super(p); read(); }
+
+
+        /**
+         * < Full path to the command name
+         */
+        public String path;
+
+        /**
+         * < Size of events array
+         */
+        public int numEvents;
+
+        /**
+         * < Array of events that trigger -exec command
+         */
+        public Pointer /* _rsvExecEvent_t.ByReference */ events;
+    }
+
+
+
+    /**
+     *  \addtogroup reservation_option reservation_option
+     *    definitions of reservation options.
+     */
+
+    /**
+     * <  User
+     */
+    public static final int RSV_OPTION_USER = 0x0001;
+
+    /**
+     * <  Group
+     */
+    public static final int RSV_OPTION_GROUP = 0x0002;
+
+    /**
+     * <  System
+     */
+    public static final int RSV_OPTION_SYSTEM = 0x0004;
+
+    /**
+     * <  Recur
+     */
+    public static final int RSV_OPTION_RECUR = 0x0008;
+
+    /**
+     * <  Resource requirement
+     */
+    public static final int RSV_OPTION_RESREQ = 0x0010;
+
+    /**
+     * <  Host
+     */
+    public static final int RSV_OPTION_HOST = 0x0020;
+
+    /**
+     * <  Open
+     */
+    public static final int RSV_OPTION_OPEN = 0x0040;
+
+    /**
+     * <  Delete
+     */
+    public static final int RSV_OPTION_DELETE = 0x0080;
+
+    /**
+     * <  Close
+     */
+    public static final int RSV_OPTION_CLOSED = 0x0100;
+
+    /**
+     * <  Execute
+     */
+    public static final int RSV_OPTION_EXEC = 0x0200;
+
+    /**
+     * <  Remote execute
+     */
+    public static final int RSV_OPTION_RMEXEC = 0x0400;
+
+    /**
+     * <  Next instance
+     */
+    public static final int RSV_OPTION_NEXTINSTANCE = 0x0800;
+
+    /**
+     * <  Disable
+     */
+    public static final int RSV_OPTION_DISABLE = 0x1000;
+
+    /**
+     * <  Add host
+     */
+    public static final int RSV_OPTION_ADDHOST = 0x2000;
+
+    /**
+     * <  Remote host
+     */
+    public static final int RSV_OPTION_RMHOST = 0x4000;
+
+    /**
+     * <  Description
+     */
+    public static final int RSV_OPTION_DESCRIPTION = 0x8000;
+
+    /**
+     * <  Timewindow mode
+     */
+    public static final int RSV_OPTION_TWMOD = 0x10000;
+
+    /**
+     * <  Switch open/close
+     */
+    public static final int RSV_OPTION_SWITCHOPENCLOSE = 0x20000;
+
+    /**
+     * <  User mode
+     */
+    public static final int RSV_OPTION_USERMOD = 0x40000;
+
+    /**
+     * <  Reservation name
+     */
+    public static final int RSV_OPTION_RSVNAME = 0x80000;
+
+    /**
+     * <  Expired
+     */
+    public static final int RSV_OPTION_EXPIRED = 0x100000;
+
+    /**
+     * \brief add reservation request.
+     */
+    public static class addRsvRequest extends Structure {
+        public static class ByReference extends addRsvRequest implements Structure.ByReference {}
+        public static class ByValue extends addRsvRequest implements Structure.ByValue {}
+        public addRsvRequest() {}
+        public addRsvRequest(Pointer p) { super(p); read(); }
+
+
+        /**
+         * <Reservation options \ref reservation_option
+         */
+        public int options;
+
+        /**
+         * < User or group for which the reservation is made
+         */
+        public String name;
+
+        /**
+         * < Minimum number of processors the required to run the job. See the -g option of brsvadd.
+         */
+        public int minNumProcs;
+
+        /**
+         * < Maximum number of processors the required to run the job.
+         */
+        public int maxNumProcs;
+
+        /**< Range of number of processors */
+        //struct procRange;
+
+        /**
+         * < The number of invoker specified hosts for the reservation. If numAskedHosts is 0, all qualified hosts will be considered.
+         */
+        public int numAskedHosts;
+
+        /**
+         * < The array of names of invoker specified hosts hosts for the reservation. The number of hosts is given by numAskedHosts. See the -m option of brsvadd.
+         */
+        public Pointer askedHosts;
+
+        /**
+         * < The resource requirements of the reservation. See the -R option of brsvadd.
+         */
+        public String resReq;
+
+        /**
+         * < Active time window for a recurring reservation. See the -t option of brsvadd.
+         */
+        public String timeWindow;
+
+        /**
+         * < Info for the -exec option.
+         */
+        public _rsvExecCmd_t.ByReference execCmd;
+
+        /**
+         * < Description for the reservation to be created. The description must be provided as a double quoted text string. The maximum length  is 512 chars.  Equivalent to the value of brsvadd -d.
+         */
+        public String desc;
+
+        /**
+         * < User-defined advance reservation name unique in an LSF cluster. The name is a string of letters, numeric chars, underscores, and dashes beginning with a letter. The maximum length of the name is 39 chars. Equivalent to the value of brsvadd -N.
+         */
+        public String rsvName;
+    }
+
+
+
+    /**
+     * \brief  remove reservation request.
+     */
+    public static class rmRsvRequest extends Structure {
+        public static class ByReference extends rmRsvRequest implements Structure.ByReference {}
+        public static class ByValue extends rmRsvRequest implements Structure.ByValue {}
+        public rmRsvRequest() {}
+        public rmRsvRequest(Pointer p) { super(p); read(); }
+
+
+        /**
+         * < Reservation ID of the reservation that you wish to remove.
+         */
+        public String rsvId;
+    }
+
+
+
+    /**
+     * \brief  modifiy reservation request
+     */
+    public static class modRsvRequest extends Structure {
+        public static class ByReference extends modRsvRequest implements Structure.ByReference {}
+        public static class ByValue extends modRsvRequest implements Structure.ByValue {}
+        public modRsvRequest() {}
+        public modRsvRequest(Pointer p) { super(p); read(); }
+
+
+        /**
+         * < Reservation ID of the reservation that you  wish to modify.
+         */
+        public String rsvId;
+
+        /**
+         * < LSF user name for the reservation.  See the -g option of brsvadd. .
+         */
+        public addRsvRequest fieldsFromAddReq;
+
+        /**
+         * < Disabled time duration
+         */
+        public String disabledDuration;
+    }
+
+
+
+    /**
+     * \brief  host reservation infromation entry.
+     */
+    public static class hostRsvInfoEnt extends Structure {
+        public static class ByReference extends hostRsvInfoEnt implements Structure.ByReference {}
+        public static class ByValue extends hostRsvInfoEnt implements Structure.ByValue {}
+        public hostRsvInfoEnt() {}
+        public hostRsvInfoEnt(Pointer p) { super(p); read(); }
+
+
+        /**
+         * < Host name.
+         */
+        public String host;
+
+        /**
+         * < Number of CPUs reserved on the host.
+         */
+        public int numCPUs;
+
+        /**
+         * < Number of job slots reserved on the host.
+         */
+        public int numSlots;
+
+        /**
+         * < Number of processors reserved on the host.
+         */
+        public int numRsvProcs;
+
+        /**
+         * < Count for used + suspended from reserved slots
+         */
+        public int numusedRsvProcs;
+
+        /**
+         * < Number of processors in use on the host.
+         */
+        public int numUsedProcs;
+    }
+
+
+
+    /**
+     * \brief  reservation information entry.
+     */
+    public static class rsvInfoEnt extends Structure {
+        public static class ByReference extends rsvInfoEnt implements Structure.ByReference {}
+        public static class ByValue extends rsvInfoEnt implements Structure.ByValue {}
+        public rsvInfoEnt() {}
+        public rsvInfoEnt(Pointer p) { super(p); read(); }
+
+
+        /**
+         * < Reservation options, see \ref reservation_option
+         */
+        public int options;
+
+        /**
+         * < Reservation ID returned from mbatchd. If the reservation fails, this is null. The memory for rsvid is allocated by the caller.
+         */
+        public String rsvId;
+
+        /**
+         * <  LSF user group name for the reservation. See the -g option of brsvadd.
+         */
+        public String name;
+
+        /**
+         * <  Number of hosts reserved
+         */
+        public int numRsvHosts;
+
+        /**
+         * <  Info about the reserved hosts
+         */
+        public Pointer /* hostRsvInfoEnt.ByReference */ rsvHosts;
+
+        /**
+         * < Active time window for a recurring reservation. See the -t option of  brsvadd.
+         */
+        public String timeWindow;
+
+        /**
+         * < Number of jobs running in the reservation.
+         */
+        public int numRsvJobs;
+
+        /**
+         * < Job IDs of jobs running in the reservation.
+         */
+        public LongByReference jobIds;
+
+        /**
+         * < Status of jobs running in the reservation.
+         */
+        public IntByReference jobStatus;
+
+        /**
+         * <  Description for the reservation to be created. The description must be provided as a double quoted text string. The maximum length is 512 chars. Equivalent to thevalue of brsvadd -d.
+         */
+        public String desc;
+
+        /**
+         * <  Null-terminated list of disabled durations
+         */
+        public Pointer disabledDurations;
+
+        /**
+         * <  The current state of the reservation - active or inactive.
+         */
+        public int state;
+
+        /**
+         * <  The time of the next instance of a recurring reservation.
+         */
+        public String nextInstance;
+
+        /**
+         * <  Creator of the reservation.
+         */
+        public String creator;
+    }
+
+
+
+/* backfill window related data structures and functions */
+
+    public static class slotInfoRequest extends Structure {
+        public static class ByReference extends slotInfoRequest implements Structure.ByReference {}
+        public static class ByValue extends slotInfoRequest implements Structure.ByValue {}
+        public slotInfoRequest() {}
+        public slotInfoRequest(Pointer p) { super(p); read(); }
+
+        /* options mask */
+
+/* Option -R */
+        public static int SLOT_OPTION_RESREQ = 0X001;
+
+        public int options;
+
+/* Resource requirement string */
+        public String resReq;
+    }
+
+
+
+/*copy from SRInfo*/
+
+    public static class SRInfoEnt extends Structure {
+        public static class ByReference extends SRInfoEnt implements Structure.ByReference {}
+        public static class ByValue extends SRInfoEnt implements Structure.ByValue {}
+        public SRInfoEnt() {}
+        public SRInfoEnt(Pointer p) { super(p); read(); }
+
+
+/*number of reserved slots*/
+        public int numReserved;
+
+/* job's predicted start time */
+        public NativeLong predictedStartTime;
+    }
+
+
+
+    public static class hostSRInfoEnt extends Structure {
+        public static class ByReference extends hostSRInfoEnt implements Structure.ByReference {}
+        public static class ByValue extends hostSRInfoEnt implements Structure.ByValue {}
+        public hostSRInfoEnt() {}
+        public hostSRInfoEnt(Pointer p) { super(p); read(); }
+
+        public String host;
+        public int hStatus;
+        public int userJobLimit;
+        public int maxJobs;
+        public int numJobs;
+        public int numRUN;
+        public int numSSUSP;
+        public int numUSUSP;
+        public int numRESERVE;
+        public int numSR;
+        public Pointer /* SRInfoEnt.ByReference */ SRInfo;
+    }
+
+
+
+    public static class slotInfoReply extends Structure {
+        public static class ByReference extends slotInfoReply implements Structure.ByReference {}
+        public static class ByValue extends slotInfoReply implements Structure.ByValue {}
+        public slotInfoReply() {}
+        public slotInfoReply(Pointer p) { super(p); read(); }
+
+
+/* to store the time of Master host */
+        public NativeLong masterTime;
+        public int numHosts;
+        public Pointer /* hostSRInfoEnt.ByReference */ hostInfo;
+        public int numAR;
+        public Pointer /* rsvInfoEnt.ByReference */ ARInfo;
+    }
+
+
+
+
+/* the general limit related data structures and functions */
+
+
+    public static final int LSB_RSRC_LIMIT_TYPE_SLOTS = 0;
+    public static final int LSB_RSRC_LIMIT_TYPE_SLOT_PERPSR = 1;
+    public static final int LSB_RSRC_LIMIT_TYPE_MEM = 2;
+    public static final int LSB_RSRC_LIMIT_TYPE_MEM_PERCENT = 3;
+    public static final int LSB_RSRC_LIMIT_TYPE_SWP = 4;
+    public static final int LSB_RSRC_LIMIT_TYPE_SWP_PERCENT = 5;
+    public static final int LSB_RSRC_LIMIT_TYPE_TMP = 6;
+    public static final int LSB_RSRC_LIMIT_TYPE_TMP_PERCENT = 7;
+    public static final int LSB_RSRC_LIMIT_TYPE_JOBS = 8;
+
+/* all external resources */
+    public static final int LSB_RSRC_LIMIT_TYPE_EXT_RSRC = 9;
+
+    /**
+     * \addtogroup _consumertype _consumertype
+     * consumer types
+     */
+    public static interface consumerType {
+        /**
+         * < Queues
+         */
+        public static final int LIMIT_QUEUES = 1;
+
+        /**
+         * < Per-queue
+         */
+        public static final int LIMIT_PER_QUEUE = 2;
+
+        /**
+         * < Users
+         */
+        public static final int LIMIT_USERS = 3;
+
+        /**
+         * < Per-users
+         */
+        public static final int LIMIT_PER_USER = 4;
+
+        /**
+         * < Hosts
+         */
+        public static final int LIMIT_HOSTS = 5;
+
+        /**
+         * < Per-host
+         */
+        public static final int LIMIT_PER_HOST = 6;
+
+        /**
+         * < Projects
+         */
+        public static final int LIMIT_PROJECTS = 7;
+
+        /**
+         * < Per-project
+         */
+        public static final int LIMIT_PER_PROJECT = 8;
+    }
+
+
+    /**< Type definitions */
+
+    /**
+     * \brief  limit consumer
+     */
+    public static class _limitConsumer extends Structure {
+        public static class ByReference extends _limitConsumer implements Structure.ByReference {}
+        public static class ByValue extends _limitConsumer implements Structure.ByValue {}
+        public _limitConsumer() {}
+        public _limitConsumer(Pointer p) { super(p); read(); }
+
+
+        /**
+         * < Consumer type ( _consumertype ):  -  Queues per-queue -  Users and per-user -  Hosts and per-host -  Projects and per-project
+         */
+        public int type;
+
+        /**
+         * < Consumer name
+         */
+        public String name;
+    }
+
+
+
+    /**
+     * \brief  limit resource.
+     */
+    public static class _limitResource extends Structure {
+        public static class ByReference extends _limitResource implements Structure.ByReference {}
+        public static class ByValue extends _limitResource implements Structure.ByValue {}
+        public _limitResource() {}
+        public _limitResource(Pointer p) { super(p); read(); }
+
+
+        /**
+         * < Resource name
+         */
+        public String name;
+
+        /**
+         * < Resource type
+         */
+        public int type;
+
+        /**
+         * < Resource val
+         */
+        public float val;
+    }
+
+
+
+    /**
+     * \brief   limit information request
+     */
+    public static class _limitInfoReq extends Structure {
+        public static class ByReference extends _limitInfoReq implements Structure.ByReference {}
+        public static class ByValue extends _limitInfoReq implements Structure.ByValue {}
+        public _limitInfoReq() {}
+        public _limitInfoReq(Pointer p) { super(p); read(); }
+
+
+        /**
+         * < Limit policy name given by the user.
+         */
+        public String name;
+
+        /**
+         * < Number of consumers
+         */
+        public int consumerC;
+
+        /**
+         * < Consumer name, queue/host/user/project
+         */
+        public Pointer /* _limitConsumer.ByReference */ consumerV;
+    }
+
+
+
+    /**
+     * \brief  limit item.
+     */
+    public static class _limitItem extends Structure {
+        public static class ByReference extends _limitItem implements Structure.ByReference {}
+        public static class ByValue extends _limitItem implements Structure.ByValue {}
+        public _limitItem() {}
+        public _limitItem(Pointer p) { super(p); read(); }
+
+
+        /**
+         * < Number of consumers
+         */
+        public int consumerC;
+
+        /**
+         * < Consumers, such as queue, host, user or project
+         */
+        public Pointer /* _limitConsumer.ByReference */ consumerV;
+
+        /**
+         * < Number of resources
+         */
+        public int resourceC;
+
+        /**
+         * < Resources list
+         */
+        public Pointer /* _limitResource.ByReference */ resourceV;
+    }
+
+
+
+    /**
+     * \brief  limit information entry .
+     */
+    public static class _limitInfoEnt extends Structure {
+        public static class ByReference extends _limitInfoEnt implements Structure.ByReference {}
+        public static class ByValue extends _limitInfoEnt implements Structure.ByValue {}
+        public _limitInfoEnt() {}
+        public _limitInfoEnt(Pointer p) { super(p); read(); }
+
+
+        /**
+         * < Limit policy name given by the user
+         */
+        public String name;
+
+        /**
+         * < Limit configuration
+         */
+        public _limitItem confInfo;
+
+        /**
+         * < Size of limit dynamic usage info array
+         */
+        public int usageC;
+
+        /**
+         * < Limit dynamic usage info array
+         */
+        public Pointer /* _limitItem.ByReference */ usageInfo;
+
+    }
+
+
+
+/* action code for threshold based on type/model, is used for
+*  predefinedThresholdTypeModel().
+ */
+
+    public static final int ADD_THRESHOLD = 1;
+    public static final int GET_THRESHOLD = 2;
+    public static final int DEL_THRESHOLD = 3;
+
+/* Structure to hold thresholds defined based on host's type/model */
+
+    public static class thresholdEntry extends Structure {
+        public static class ByReference extends thresholdEntry implements Structure.ByReference {}
+        public static class ByValue extends thresholdEntry implements Structure.ByValue {}
+        public thresholdEntry() {}
+        public thresholdEntry(Pointer p) { super(p); read(); }
+
+
+/* Name of type or model */
+        public String attr;
+
+/* Pointer to hostInfo */
+        public hostInfoEnt.ByReference hostEntryPtr;
+    }
+
+
+
+    /**
+     * \page lsb_limitInfo lsb_limitInfo
+     * \brief gets resource allocation limit configuration and dynamic usage
+     * information.
+     * <p/>
+     * Displays current usage of resource allocation limits configured in Limit
+     * sections in lsb.resources:
+     * \li    Configured limit policy name
+     * \li    Users
+     * \li    Queues
+     * \li    Hosts
+     * \li    Project names
+     * <p/>
+     * <b>\#include <lsf/lsbatch.h>
+     * <p/>
+     * int lsb_limitInfo( limitInfoReq.ByReference req,  limitInfoEnt.ByReference[] limitItemRef,
+     * IntByReference size, lsInfo.ByReference lsInfo)</b>
+     *
+     * @return int:-1
+     *         \n Function failed.
+     *         <p/>
+     *         \b Errors:
+     *         \par
+     *         On failure, lsberrno is set to indicate the error.
+     *         <p/>
+     *         <b>Equivalent line command:</b>
+     *         \par
+     *         blimits
+     *         <p/>
+     *         \b Files
+     *         \par
+     *         $LSB_CONFDIR/cluster_name/configdir/lsb.queues \n
+     *         $LSB_CONFDIR/cluster_name/configdir/lsb.users \n
+     *         $LSB_CONFDIR/cluster_name/configdir/lsb.hosts \n
+     *         $LSB_CONFDIR/cluster_name/configdir/lsb.resources
+     * @param req input, the user request for limit information
+     * @param limitItemRef output, the limit information array
+     * @param size output, the size of the limit information array
+     * @param lsInfo Please refer to the \ref lsInfo structure.
+     * <p/>
+     * <b>Data Structures:</b>
+     * \par
+     * _limitInfoReq
+     * \n _limitConsumer
+     * \n _limitInfoEnt
+     * \n _limitItem
+     * \n _limitResource
+     * <p/>
+     * <b>Define Statements:</b>
+     * \par
+     * \ref _consumertype
+     * #see \ref lsb_freeLimitInfoEnt
+     */
+    public static native int lsb_limitInfo(_limitInfoReq req, Pointer limitItemRef, IntByReference size, LibLsf.lsInfo lsInfo);
+
+    /**
+     * \page lsb_freeLimitInfoEnt lsb_freeLimitInfoEnt
+     * \brief Frees the memory allocated by \ref lsb_limitInfo.
+     * <p/>
+     * <b>\#include <lsf/lsbatch.h>
+     * <p/>
+     * void lsb_freeLimitInfoEnt(limitInfoEnt.ByReference  ent, int size)</b>
+     *
+     * @param size input, the size of the limit information array
+     *             <p/>
+     *             <b>Data Structures:</b>
+     *             \par
+     *             _limitInfoEnt
+     *             \n _limitItem
+     *             \n _limitConsumer
+     *             \n _limitResource
+     *             <p/>
+     *             <b>Define Statements:</b>
+     *             \par
+     *             \ref _consumertype
+     * return void
+     *         \n There's no return value.
+     *         <p/>
+     *         \b Errors:
+     *         \par
+     *         On failure, lsberrno is set to indicate the error.
+     *         <p/>
+     *         <b>Equivalent line commands:</b>
+     *         \par
+     *         blimits
+     *         <p/>
+     *         <b>Files:</b>
+     *         \par
+     *         $LSB_CONFDIR/cluster_name/configdir/lsb.queues \n
+     *         $LSB_CONFDIR/cluster_name/configdir/lsb.users \n
+     *         $LSB_CONFDIR/cluster_name/configdir/lsb.hosts \n
+     *         $LSB_CONFDIR/cluster_name/configdir/lsb.resources
+     * @param ent input, the array of limit information
+     * #see \ref lsb_limitInfo
+     */
+
+    public static native void lsb_freeLimitInfoEnt(_limitInfoEnt ent, int size);
+
+    /**
+     *  \addtogroup resizablejob_related resizablejob_related
+     *  Resizable job related definitions.
+     */
+
+    /**
+     * < Means release no slots
+     */
+    public static final int LSB_RESIZE_REL_NONE = 0x0;
+
+    /**
+     * < Means release all slots-In this case, nHosts, hosts and slots  indicate the slots that are not released
+     */
+    public static final int LSB_RESIZE_REL_ALL = 0x01;
+
+    /**
+     * < Means cancel any pending resize request
+     */
+    public static final int LSB_RESIZE_REL_CANCEL = 0x02;
+
+    /**
+     * < Means execute no resize notification command
+     */
+    public static final int LSB_RESIZE_REL_NO_NOTIFY = 0x04;
+
+    /**
+     * \brief  job resize release.
+     */
+    public static class job_resize_release extends Structure {
+        public static class ByReference extends job_resize_release implements Structure.ByReference {}
+        public static class ByValue extends job_resize_release implements Structure.ByValue {}
+        public job_resize_release() {}
+        public job_resize_release(Pointer p) { super(p); read(); }
+
+
+        /**
+         * < LSF job ID
+         */
+        public long jobId;
+
+        /**
+         * < Options is constructed from the bitwise inclusive OR of zero or more of the flags, as defined in \ref resizablejob_related .
+         */
+        public int options;
+
+        /**
+         * < Number of hosts in the hosts list, if no hosts are to be specified this should be zero
+         */
+        public int nHosts;
+
+        /**
+         * < Specified hosts list, nHosts number of elements
+         */
+        public Pointer hosts;
+
+        /**
+         * < Slots list, each element specifies the number of slots per corresponding host (0 implies all), nHosts number of elements
+         */
+        public IntByReference slots;
+
+        /**
+         * < Name and location of notification command
+         */
+        public String notifyCmd;
+    }
+
+
+
+    public static class job_resize_request extends Structure {
+        public static class ByReference extends job_resize_request implements Structure.ByReference {}
+        public static class ByValue extends job_resize_request implements Structure.ByValue {}
+        public job_resize_request() {}
+        public job_resize_request(Pointer p) { super(p); read(); }
+
+        public long jobId;
+        public int options;
+
+/* array size */
+        public int nHosts;
+
+/* array of hosts */
+        public Pointer hosts;
+
+/* notifocation command */
+        public String notifyCmd;
+    }
+
+
+
+/*
+*  End of resizable job related definitions
+ */
+
+/* Job Dependency Display */
+
+
+/* Job Dependency Display */
+/* for options */
+    /**
+     *  \addtogroup query_depend query_depend
+     *  Job Dependency Display for options
+     */
+
+    /**
+     * <  Recursively
+     */
+    public static final int QUERY_DEPEND_RECURSIVELY = 0x1;
+
+    /**
+     * <  Detail
+     */
+    public static final int QUERY_DEPEND_DETAIL = 0x2;
+
+    /**
+     * <  Unsatisfied
+     */
+    public static final int QUERY_DEPEND_UNSATISFIED = 0x4;
+
+    /**
+     * <  Child
+     */
+    public static final int QUERY_DEPEND_CHILD = 0x8;
+
+    /**
+     * \brief  job dependent request.
+     */
+
+    public static class jobDepRequest extends Structure {
+        public static class ByReference extends jobDepRequest implements Structure.ByReference {}
+        public static class ByValue extends jobDepRequest implements Structure.ByValue {}
+        public jobDepRequest() {}
+        public jobDepRequest(Pointer p) { super(p); read(); }
+
+        /**
+         * < Job ID of the queried job or job array.
+         */
+        public long jobId;
+
+        /**
+         * < You can set the following bits into this field:\n QUERY_DEPEND_RECURSIVELY\n Query the dependency information recursively.\n QUERY_DEPEND_DETAIL\n Query the detailed dependency information.\n QUERY_DEPEND_UNSATISFIED\n Query the jobs that cause this job pend.\n QUERY_DEPEND_CHILD\n Query child jobs.
+         */
+        public int options;
+
+        /**
+         * < The level when you set QUERY_DEPEND_RECURSIVELY.
+         */
+        public int level;
+    }
+
+
+
+
+    /**
+     * \brief  queried jobs.
+     */
+    public static class queriedJobs extends Structure {
+        public static class ByReference extends queriedJobs implements Structure.ByReference {}
+        public static class ByValue extends queriedJobs implements Structure.ByValue {}
+        public queriedJobs() {}
+        public queriedJobs(Pointer p) { super(p); read(); }
+
+
+        /**
+         * < Job ID of the queried job or job array.
+         */
+        public long jobId;
+
+        /**
+         * < The whole dependency condition of the job.
+         */
+        public String dependcondition;
+
+        /**
+         * < Whether the condition is satisfied.
+         */
+        public int satisfied;
+    }
+
+
+
+/* for hasDependency */
+    /**
+     *  \addtogroup job_has_depend job_has_depend
+     *  options for hasDependency
+     */
+
+    /**
+     * <  Job has dependency
+     */
+    public static final int JOB_HAS_DEPENDENCY = 0x1;
+
+    /**
+     * <  Job has individual  condition.
+     */
+    public static final int JOB_HAS_INDIVIDUAL_CONDITION = 0x2;
+
+    /**
+     * \brief  dependency jobs.
+     */
+
+    public static class dependJobs extends Structure {
+        public static class ByReference extends dependJobs implements Structure.ByReference {}
+        public static class ByValue extends dependJobs implements Structure.ByValue {}
+        public dependJobs() {}
+        public dependJobs(Pointer p) { super(p); read(); }
+
+        /**
+         * < Job ID. By default, it is the parent job of the queried job. Modify to child job by setting QUERY_DEPEND_CHILD in options of JobDepRequest.
+         */
+        public long jobId;
+
+        /**
+         * < The job name associated with the job ID.
+         */
+        public String jobname;
+
+        /**
+         * < The number of degrees of separation from the original job.
+         */
+        public int level;
+
+        /**
+         * < Job status of the job.
+         */
+        public int jobstatus;
+
+        /**
+         * < Whether the job ID has a dependency or not. When you set QUERY_DEPEND_RECURSIVELY in options of JobDepRequest, 0 indicates job ID does not have a dependency. Otherwise, one or more of the following bits displays:-  JOB_HAS_DEPENDENCY: Job has a dependency.-  JOB_HAS_INDIVIDUAL_CONDITION: Job has an individual dependency condition when it is an element of job array.
+         */
+        public int hasDependency;
+
+        /**
+         * < When you set "QUERY_DEPEND_DETAIL" into options, it is dependency condition of jobId. It is "" when you do not set "QUERY_DEPEND_DETAIL".
+         */
+        public String condition;
+
+        /**
+         * < Whether the condition is satisfied.
+         */
+        public int satisfied;
+
+        /**
+         * < Job ID. By default, it is the child job. Modify to parent job by setting QUERY_DEPEND_CHILD in options of JobDepRequest
+         */
+        public long depJobId;
+    }
+
+
+
+    /**
+     * \brief  job dependent information.
+     */
+
+    public static class jobDependInfo extends Structure {
+        public static class ByReference extends jobDependInfo implements Structure.ByReference {}
+        public static class ByValue extends jobDependInfo implements Structure.ByValue {}
+        public jobDependInfo() {}
+        public jobDependInfo(Pointer p) { super(p); read(); }
+
+
+        /**
+         * < You can set the following bits into this field:\n QUERY_DEPEND_RECURSIVELY\n Query the dependency information recursively.\n QUERY_DEPEND_DETAIL\n Query the detailed dependency information.\n QUERY_DEPEND_UNSATISFIED\n Query the jobs that cause this job pend.\n QUERY_DEPEND_CHILD\n Query child jobs.
+         */
+        public int options;
+
+        /**
+         * < The number of jobs you queried. By default, the value is 1. However, when you set QUERY_DEPEND_DETAIL in the options and you query a job array where some elements have a dependency condition that has changed, the value is the number of the changed element + 1.
+         */
+        public int numQueriedJobs;
+
+        /**
+         * < The jobs you queried.
+         */
+        public Pointer /* queriedJobs.ByReference */ queriedJobs;
+
+        /**
+         * < The number of levels returned.
+         */
+        public int level;
+
+        /**
+         * < The number of jobs returned.
+         */
+        public int numJobs;
+
+        /**
+         * < The returned dependency jobs.
+         */
+        public Pointer /* dependJobs.ByReference */ depJobs;
+    }
+
+
+
+
+/*
+*  Functional prototypes of the Advance Reservation API
+ */
+
+
+/* Macros */
+
+    public static boolean IS_PEND(int s) {
+        return (JNAUtils.toBoolean((s) & JOB_STAT_PEND) || JNAUtils.toBoolean((s) & JOB_STAT_PSUSP));
+    }
+
+/* Do not test JOB_STAT_UNKWN in IS_START() */
+
+    public static boolean IS_START(int s) {
+        return (JNAUtils.toBoolean((s) & JOB_STAT_RUN) || JNAUtils.toBoolean((s) & JOB_STAT_SSUSP) || JNAUtils.toBoolean((s) & JOB_STAT_USUSP));
+    }
+
+    public static boolean IS_FINISH(int s) {
+        return (JNAUtils.toBoolean((s) & JOB_STAT_DONE) || JNAUtils.toBoolean((s) & JOB_STAT_EXIT));
+    }
+
+    public static boolean IS_SUSP(int s) {
+        return (JNAUtils.toBoolean((s) & JOB_STAT_PSUSP) || JNAUtils.toBoolean((s) & JOB_STAT_SSUSP) || JNAUtils.toBoolean((s) & JOB_STAT_USUSP));
+    }
+
+/* Macro for checking post job process. (IO_SPOOL) */
+
+    public static boolean IS_POST_DONE(int s) {
+        return (((s) & JOB_STAT_PDONE) == JOB_STAT_PDONE);
+    }
+
+    public static boolean IS_POST_ERR(int s) {
+        return (((s) & JOB_STAT_PERR) == JOB_STAT_PERR);
+    }
+
+    public static boolean IS_POST_FINISH(int s) {
+        return (IS_POST_DONE(s) || IS_POST_ERR(s));
+    }
+
+/*On windows ,for dll library ,need to use _declspec(dllexport) to export
+*a symbol .but if do so ,static library will can not work .so we are going
+*to change lsberrno to a function.
+*/
+
+    public static int lsberrno() {
+        return lsb_errno().getValue();
+    }
+
+
+
+
+/*
+*  Version of the mbatchd that was last contacted.
+*  -1 indicates the mbatchd has not been contacted.
+ */
+    //public int lsb_mbd_version;
+
+/*
+*  The data definition for host name list operations
+ */
+    public static final int PRINT_SHORT_NAMELIST = 0x01;
+    public static final int PRINT_LONG_NAMELIST = 0x02;
+    public static final int PRINT_MCPU_HOSTS = 0x04;
+
+    public static class nameList extends Structure {
+        public static class ByReference extends nameList implements Structure.ByReference {}
+        public static class ByValue extends nameList implements Structure.ByValue {}
+        public nameList() {}
+        public nameList(Pointer p) { super(p); read(); }
+
+
+/* number of names */
+        public int listSize;
+
+/* a group of names */
+        public Pointer names;
+
+/* the ocurrent of corresponding name */
+        public IntByReference counter;
+    }
+
+
+
+    public static native nameList.ByReference lsb_parseShortStr(String string1, int int1);
+
+    public static native nameList.ByReference lsb_parseLongStr(String string1);
+
+    public static native String lsb_printNameList(nameList namelist1, int int1);
+
+    public static native nameList.ByReference lsb_compressStrList(Pointer stringArray1, int int1);
+
+    public static native String lsb_splitName(String string1, IntByReference int1);
+
+    public static native IntByReference lsb_errno();
+
+
+/* external routines related to API_CONF */
+
+    public static native paramConf.ByReference lsb_readparam(LibLsf.lsConf lsConf1);
+
+    public static native userConf.ByReference lsb_readuser(LibLsf.lsConf lsConf1, int int1, LibLsf.clusterConf clusterConf1);
+
+    public static native userConf.ByReference lsb_readuser_ex(LibLsf.lsConf lsConf1, int int1, LibLsf.clusterConf clusterConf1, LibLsf.sharedConf sharedConf1);
+
+    public static native hostConf.ByReference lsb_readhost(LibLsf.lsConf lsConf1, LibLsf.lsInfo lsInfo1, int int1, LibLsf.clusterConf clusterConf1);
+
+    public static native queueConf.ByReference lsb_readqueue(LibLsf.lsConf lsConf1, LibLsf.lsInfo lsInfo1, int int1, LibLsf.sharedConf sharedConf1, LibLsf.clusterConf clusterConf1);
+
+    public static native void updateClusterConf(LibLsf.clusterConf clusterConf1);
+
+/* end of external routines related to API_CONF */
+
+    /**
+     * \page lsb_hostpartinfo lsb_hostpartinfo
+     * Returns informaton about host partitions.
+     * <p/>
+     * <b>\#include <lsf/lsbatch.h>
+     * <p/>
+     * hostPartInfoEnt.ByReference lsb_hostpartinfo (String[] hostParts,
+     * IntByReference numHostParts)</b> @param hostParts An array of host partition names.
+     *
+     * @return null
+     *         \n Function failed.
+     *         <p/>
+     *         <b>Errors:</b>
+     *         \par
+     *         If the function fails, lsberrno is set to indicate the error. If lsberrno is
+     *         LSBE_BAD_HPART, (*hostParts)[*numHostParts] is not a host partition known
+     *         to the LSF system. Otherwise, if.ByReference numHostParts is less than its original value,
+     *         * numHostParts is the actual number of host partitions found.
+     *         <p/>
+     *         <b>Equivalent line commands:</b>
+     *         \par
+     *         none
+     *         <p/>
+     *         <b>Files:</b>
+     *         \par
+     *         $LSB_CONFDIR/cluster_name/configdir/lsb.hosts
+     * @param numHostHosts The number of host partition names.
+     * To get information on all host partitions, set hostParts to null;* numHostParts
+     * will be the actual number of host partitions when this call returns.
+     * <p/>
+     * <b>Data Structures:</b>
+     * \par
+     * hostPartInfoEnt
+     * \n hostPartUserInfo
+     * <p/>
+     * <b>Define Statements:</b>
+     * \par
+     * none
+     * #see \ref lsb_usergrpinfo
+     * #see \ref lsb_hostgrpinfo
+     * @param stringArray1 stringArray1
+     */
+    public static native hostPartInfoEnt.ByReference lsb_hostpartinfo(Pointer stringArray1, IntByReference numHostHosts);
+
+    /**
+     * \page lsb_init lsb_init
+     * \brief Initializes the LSF batch library (LSBLIB), and gets the
+     * configuration environment.
+     * <p/>
+     * You must use \ref lsb_init before any other LSBLIB library routine in your
+     * application.
+     * <p/>
+     * <b>\#include <lsf/lsbatch.h>
+     * <p/>
+     * int lsb_init(String appname)</b>
+     *
+     * @return int:-1 \n
+     *         The function failed.
+     *         <p/>
+     *         <b>Errors:</b>
+     *         \par
+     *         If the function fails, lsberrno is set to indicate the error.
+     *         <p/>
+     *         <b>Equivalent line commands:</b>
+     *         \par
+     *         none
+     *         <p/>
+     *         <b>Files:</b>
+     *         \par
+     *         none
+     * @param appName The name of your application.
+     * If appName holds the name of your application, a logfile with the same
+     * name as
+     * your application receives LSBLIB transaction information.
+     * If appName is null, the logfile $LSF_LOGDIR/bcmd receives LSBLIB
+     * transaction information.
+     * <p/>
+     * <b>Data Structures:</b>
+     * \par
+     * none
+     * <p/>
+     * <b>Define Statements:</b>
+     * \par
+     * none
+     * see none
+     */
+    public static native int lsb_init(String appName);
+
+    public static native int sch_lsb_init();
+
+    /**
+     * \page lsb_openjobinfo lsb_openjobinfo
+     * \brief Returns the number of jobs in the master batch daemon.
+     * <p/>
+     * \ref lsb_openjobinfo accesses information about pending, running and
+     * suspended jobs in the master batch daemon. Use \ref lsb_openjobinfo to
+     * create a connection to the master batch daemon. Next, use \ref lsb_readjobinfo
+     * to read job records.Close the connection using \ref lsb_closejobinfo.
+     * <p/>
+     * \ref lsb_openjobinfo opens a connection with mbatchd and returns the total
+     * number of records in the connection on success.
+     * <p/>
+     * <b>\#include <lsf/lsbatch.h>
+     * <p/>
+     * int lsb_openjobinfo(long jobId, String jobName,
+     * String userName, String queueName, String hostName,
+     * int options)</b>
+     *
+     * @param jobId   Passes information about jobs with the given job ID.
+     *                If jobId is 0, \ref lsb_openjobinfo looks to another parameter to return
+     *                information about jobs.If a member of a job array is to be passed, use
+     *                the array form jobID[ i ] where jobID is the job array name, and i is
+     *                the index value.
+     * @param options <lsf/lsbatch.h> defines the flags shown in
+     *                \ref defs_lsb_openjobinfo constructed from bits. Use the bitwise OR to set more
+     *                than one flag.
+     *                <p/>
+     *                <b>Data Structures:</b>
+     *                \par
+     *                none
+     *                <p/>
+     *                <b>Define Statements:</b>
+     *                \par
+     *                \ref defs_lsb_openjobinfo_a
+     *                \n \ref defs_lsb_openjobinfo
+     * @return int:-1 \n
+     *         The function failed.
+     *         <p/>
+     *         \b Errors:
+     *         \par
+     *         If the function fails, lsberrno is set to indicate the error.
+     *         <p/>
+     *         <b>Equivalent line command:</b>
+     *         \par
+     *         bjobs
+     *         <p/>
+     *         \b Files:
+     *         \par
+     *         ${LSF_ENVDIR:-/etc}/lsf.conf
+     * @param jobName Passes information about jobs with the given job name.
+     * If jobName is null, \ref lsb_openjobinfo looks to another parameter to return
+     * information about jobs.
+     * @param userName Passes information about jobs submitted by the named user
+     * or user group, or by all users if user is all. If user is null,
+     * \ref lsb_openjobinfo assumes the user is invoking this call.
+     * @param queueName Passes information about jobs belonging to the named
+     * queue. If queue is null,jobs in all the queues of the batch system are counted.
+     * @param hostName Passes information about jobs on the named host, host
+     * group or cluster name. If host is null, jobs on all hosts of the batch
+     * system will be considered.
+     * #see \ref               lsb_openjobinfo_a
+     * #see \ref               lsb_openjobinfo_a_ext
+     * #see \ref               lsb_openjobinfo_req
+     * #see \ref               lsb_closejobinfo
+     * #see \ref               lsb_readjobinfo
+     * #see \ref               lsb_readframejob
+     */
+    public static native int lsb_openjobinfo(long jobId, String jobName, String userName, String queueName, String hostName, int options);
+
+    /**
+     * \page lsb_openjobinfo_a lsb_openjobinfo_a
+     * \brief Provides the name and number of jobs and hosts in the master batch
+     * daemon.
+     * <p/>
+     * \ref lsb_openjobinfo_a provides more information on pending, running and
+     * suspended jobs than \ref lsb_openjobinfo. Use \ref lsb_openjobinfo_a to create a
+     * connection to the master batch daemon. Next, use \ref lsb_readjobinfo to read
+     * job records. Close the connection using \ref lsb_closejobinfo.
+     * <p/>
+     * \ref lsb_openjobinfo_a passes information about jobs based on the value of
+     * jobId,jobName, userName, queueName, or hostName. Only one parameter can be
+     * chosen. The other parameters must be null or 0.
+     * <p/>
+     * <b>\#include <lsf/lsbatch.h>
+     * <p/>
+     * jobInfoHead.ByReference lsb_openjobinfo_a(long jobId,
+     * String jobName,
+     * String userName,
+     * String queueName,
+     * String hostName,
+     * int options)</b>
+     *
+     * @param jobId   Passes information about jobs with the given job ID. If jobId
+     *                is 0, \ref lsb_openjobinfo looks to another parameter to return information
+     *                about jobs.
+     *                If information about a member of a job array is to be passed, use the array
+     *                form jobID[ i ] where jobID is the job array name, and i is the index value.
+     * @param options <lsf/lsbatch.h> defines the flags shown in def_lsb_openjobinfo_a
+     *                constructed from bits. Use the bitwise OR to set more than one flag.
+     *                <p/>
+     *                <b>Data Structures:</b>
+     *                \par
+     *                jobInfoHead
+     *                <p/>
+     *                <b>Define Statements:</b>
+     *                \par
+     *                \ref defs_lsb_openjobinfo_a
+     * @return null \n
+     *         The function failed.
+     *         <p/>
+     *         \b Errors:
+     *         \par
+     *         If the function fails, lsberrno is set to indicate the error.
+     *         <p/>
+     *         <b>Equivalent line command:</b>
+     *         \par
+     *         bjobs
+     *         <p/>
+     *         <b>Files:</b>
+     *         \par
+     *         ${LSF_ENVDIR:-/etc}/lsf.conf \n
+     *         $LSB_CONFDIR/cluster_name/configdir/lsb.params
+     * @param jobName Passes information about jobs with the given job name. If
+     * jobName is null, \ref lsb_openjobinfo looks to another parameter to return
+     * information about jobs.
+     * @param userName Passes information about jobs submitted by the named user
+     * or user group, or by all users if userName is all. If userName is null,
+     * \ref lsb_openjobinfo_a assumes the user is invoking this call.
+     * @param queueName Passes information about jobs belonging to the named queue.
+     * If queueName is null, jobs in all queues of the batch system will be
+     * considered.
+     * @param hostName Passes information about jobs on the named host, host group
+     * or cluster name. If hostName is null, jobs on all hosts of the batch system
+     * will be considered.
+     * #see \ref lsb_openjobinfo
+     * #see \ref lsb_closejobinfo
+     * #see \ref lsb_readjobinfo
+     * #see \ref lsb_readframejob
+     */
+    public static native jobInfoHead.ByReference lsb_openjobinfo_a(long jobId, String jobName, String userName, String queueName, String hostName, int options);
+
+    /**
+     * \page lsb_openjobinfo_a_ext lsb_openjobinfo_a_ext
+     * \brief  Returns the name and number of jobs and hosts in the master batch
+     * daemon with additional host group information.
+     * <p/>
+     * \ref lsb_openjobinfo_a_ext is run from \ref lsb_openjobinfo_a using the same
+     * parameters and provides the same information as \ref lsb_openjobinfo_a, but with
+     * additional host group information.
+     * <p/>
+     * \ref lsb_openjobinfo_a_ext passes information about jobs based on the value of
+     * jobId, jobName, userName, queueName, or hostName. Only one parameter can be
+     * chosen. The other parameters must be null or 0.
+     * <p/>
+     * <b>\#include <lsf/lsbatch.h>
+     * <p/>
+     * jobInfoHeadExt.ByReference
+     * lsb_openjobinfo_a_ext (long jobId, String jobName,
+     * String userName, String queueName,
+     * String hostName, int options)</b>
+     *
+     * @param jobId   Passes information about jobs with the given job ID. If jobId
+     *                is 0, \ref lsb_openjobinfo_a_ext looks to another parameter to return information
+     *                about jobs. If information about a member of a job array is to be passed, use
+     *                the array form jobID[ i ] where jobID is the job array name, and i is the
+     *                index value.
+     * @param options <lsf/lsbatch.h> defines the flags shown in
+     *                def_lsb_openjobinfo_a constructed from bits. Use the bitwise OR to set more
+     *                than one flag.
+     *                <p/>
+     *                <b>Data Structures:</b>
+     *                \par
+     *                jobInfoHeadExt
+     *                <p/>
+     *                <b>Define Statements:</b>
+     *                \par
+     *                \ref defs_lsb_openjobinfo_a
+     * @return null \n
+     *         The function failed.
+     *         <p/>
+     *         \b Errors:
+     *         \par
+     *         If the function fails, lsberrno is set to indicate the error.
+     *         <p/>
+     *         <b>Equivalent line command:</b>
+     *         \par
+     *         bjobs
+     *         <p/>
+     *         <b>Files:</b>
+     *         \par
+     *         ${LSF_ENVDIR:-/etc}/lsf.conf \n
+     *         $LSB_CONFDIR/cluster_name/configdir/lsb.params
+     * @param jobName Passes information about jobs with the given job name. If
+     * jobName is null, \ref lsb_openjobinfo_a_ext looks to another parameter to return
+     * information about jobs.
+     * @param userName Passes information about jobs submitted by the named user
+     * or user group, or by all users if userName is all. If userName is null,
+     * \ref lsb_openjobinfo_a_ext assumes the user is invoking this call.
+     * @param queueName Passes information about jobs belonging to the named queue.
+     * If queueName is null, jobs in all queues of the batch system will be considered.
+     * @param hostName Passes information about jobs on the named host, host group
+     * or cluster name. If hostName is null, jobs on all hosts of the batch system
+     * will be considered.
+     * #see \ref lsb_openjobinfo
+     * #see \ref lsb_closejobinfo
+     * #see \ref lsb_readjobinfo
+     * #see \ref lsb_readframejob
+     */
+    public static native jobInfoHeadExt.ByReference lsb_openjobinfo_a_ext(long jobId, String jobName, String userName, String queueName, String hostName, int options);
+
+    /**
+     * \page lsb_openjobinfo_req lsb_openjobinfo_req
+     * \brief  Extensible API.
+     * <p/>
+     * Instead of submitting individual requests this API defines
+     * all job info requests as objects, and can easily be enhanced to include
+     * additinal requests.
+     * <p/>
+     * <b>\#include <lsf/lsbatch.h>
+     * <p/>
+     * jobInfoHeadExt.ByReference lsb_openjobinfo_req (jobInfoReq.ByReference req)</b>
+     *
+     * @return null
+     *         \n Function failed.
+     *         <p/>
+     *         \b Errors:
+     *         \par
+     *         If the function fails, lsberrno is set to indicate the error.
+     *         <p/>
+     *         <b>Equivalent line command:</b>
+     *         \par
+     *         none
+     *         <p/>
+     *         \b Files:
+     *         \par
+     *         ${LSF_ENVDIR:-/etc}/lsf.conf
+     * @param req  job information request.
+     * <p/>
+     * <b>Data Structures:</b>
+     * \par
+     * jobInfoReq
+     * \n \ref jobInfoHeadExt
+     * <p/>
+     * <b>Define Statements:</b>
+     * \par
+     * \ref defs_lsb_openjobinfo_a
+     * \n \ref defs_lsb_openjobinfo
+     * #see \ref               lsb_openjobinfo_a
+     * #see \ref               lsb_openjobinfo_a_ext
+     * #see \ref               lsb_closejobinfo
+     * #see \ref               lsb_readjobinfo
+     * #see \ref               lsb_readframejob
+     */
+    public static native jobInfoHeadExt.ByReference lsb_openjobinfo_req(jobInfoReq req);
+
+    public static native int lsb_queryjobinfo(int int1, NativeLongByReference long1, String string1);
+
+    public static native jobInfoEnt.ByReference lsb_fetchjobinfo(IntByReference int1, int int2, NativeLongByReference long1, String string1);
+
+    public static native jobInfoEnt.ByReference lsb_fetchjobinfo_ext(IntByReference int1, int int2, NativeLongByReference long1, String string1, jobInfoHeadExt jobInfoHeadExt);
+
+    /**
+     * \page lsb_readjobinfo lsb_readjobinfo
+     * \brief Returns the next job information record in mbatchd.
+     * <p/>
+     * \ref lsb_readjobinfo reads the number of records defined by the more parameter.
+     * The more parameter receives its value from either \ref lsb_openjobinfo or
+     * \ref lsb_openjobinfo_a. Each time \ref lsb_readjobinfo is called, it returns one
+     * record from mbatchd. Use \ref lsb_readjobinfo in a loop and use more to
+     * determine how many times to repeat the loop to retrieve job information records.
+     * <p/>
+     * <b>\#include <lsf/lsbatch.h>
+     * \n \#include <time.h>
+     * \n \#include <lsf/lsf.h>
+     * <p/>
+     * jobInfoEnt.ByReference lsb_readjobinfo(IntByReference more)</b>
+     *
+     * @return null
+     *         \n Function failed.
+     *         <p/>
+     *         \b Errors:
+     *         \par
+     *         If there are no more records, then lsberrno is set to LSBE_EOF.
+     *         <p/>
+     *         <b>Equivalent line commands:</b>
+     *         \par
+     *         none
+     *         <p/>
+     *         <b>Files:</b>
+     *         \par
+     *         $LSB_CONFDIR/cluster_name/configdir/lsb.queues
+     * @param more Number of job records in the master batch daemon.
+     * <p/>
+     * <b>Data Structures:</b>
+     * \par
+     * jobInfoEnt
+     * \n jobExternalMsgReply
+     * \n jRusage
+     * \n pidInfo
+     * \n reserveItem
+     * \n submit
+     * <p/>
+     * <b>Define Statements:</b>
+     * \par
+     * \ref job_states
+     * \n \ref jobgroup_counterIndex
+     * \n \ref group_nodetypes
+     * #see \ref lsb_openjobinfo
+     * #see \ref lsb_openjobinfo_a
+     * #see \ref lsb_closejobinfo
+     * #see \ref lsb_hostinfo
+     * #see \ref lsb_pendreason
+     * #see \ref lsb_queueinfo
+     * #see \ref lsb_suspreason
+     */
+    public static native jobInfoEnt.ByReference lsb_readjobinfo(IntByReference more);
+
+    /**
+     * \page  lsb_submit lsb_submit
+     * Submits or restarts a job in the batch system.
+     * <p/>
+     * \ref lsb_submit submits or restarts a job in the batch system according to the
+     * jobSubReq specification.
+     * <p/>
+     * <b>\#include <lsf/lsbatch.h>
+     * <p/>
+     * long lsb_submit (submit.ByReference jobSubReq,
+     * submitReply.ByReference jobSubReply)</b>
+     *
+     * @return long:-1 \n
+     *         Function failed.
+     *         <p/>
+     *         \b Errors:
+     *         \par
+     *         If the function fails, lsberrno is set to indicate the error.
+     *         If the environment variable BSUB_CHK_RESREQ is set, the value of lsberrno is
+     *         either LSBE_RESREQ_OK or LSBE_RESREQ_ERR, depending on the result of
+     *         resource requirement string checking. The badJobName field in the submitReply
+     *         structure contains the detailed error message.
+     *         <p/>
+     *         <b>Equivalent line commands:</b>
+     *         \par
+     *         bsub
+     *         \n brestart
+     *         <p/>
+     *         \b Files:
+     *         \par
+     *         ${LSF_ENVDIR:-/etc}/lsf.conf
+     * @param jobSubReq
+     * Describes the requirements for job submission to the batch system.
+     * A job that does not meet these requirements is not submitted to the
+     * batch system and an error is returned.
+     * @param jobSubReply
+     * Describes the results of the job submission to the batch system.
+     * <p/>
+     * <b>Data Structures:</b>
+     * \par
+     * submit
+     * \n submitReply
+     * <p/>
+     * <b>Define Statements:</b>
+     * \par
+     * \ref lsb_submit_options
+     * \n \ref lsb_submit_options2
+     * \n \ref lsb_submit_options3
+     * #see \ref lsb_modify
+     * #see \ref ls_info
+     * #see \ref lsb_queueinfo
+     */
+    public static native long lsb_submit(submit jobSubReq, submitReply jobSubReply);
+
+    /**
+     * \page lsb_readjobinfo_cond lsb_readjobinfo_cond
+     * \brief Returns the next job information record for condensed host groups
+     * in mbatchd.
+     * <p/>
+     * \ref lsb_readjobinfo_cond reads the number of records defined by the more
+     * parameter. The more parameter receives its value from either \ref lsb_openjobinfo
+     * or \ref lsb_openjobinfo_a. Each time \ref lsb_readjobinfo_cond is called, it
+     * returns one record from mbatchd. Use \ref lsb_readjobinfo_cond in a loop and use
+     * more to determine how many times to repeat the loop to retrieve job information
+     * records.
+     * <p/>
+     * \ref lsb_readjobinfo_cond differs from \ref lsb_readjobinfo in that if jInfoHExt
+     * is not null, \ref lsb_readjobinfo_cond substitutes hostGroup (if it is a condensed
+     * host group) for job execution hosts.
+     * <p/>
+     * <b>\#include <lsf/lsbatch.h>
+     * \n \#include <time.h>
+     * \n \#include <lsf/lsf.h>
+     * <p/>
+     * jobInfoEnt.ByReference lsb_readjobinfo_cond(IntByReference more,
+     * jobInfoHeadExt.ByReference jInfoHExt);</b>
+     *
+     * @return null
+     *         \n Function failed.
+     *         <p/>
+     *         \b Errors:
+     *         \par
+     *         If there are no more records, then lsberrno is set to LSBE_EOF.
+     *         <p/>
+     *         <b>Equivalent line commands:</b>
+     *         \par
+     *         none
+     *         <p/>
+     *         <b>Files:</b>
+     *         \par
+     *         $LSB_CONFDIR/cluster_name/configdir/lsb.queues
+     * @param more Number of job records in the master batch daemon.
+     * @param jInfoHExt Job information header info for the condensed host group.
+     * <p/>
+     * <b>Data Structures:</b>
+     * \par
+     * jobInfoEnt
+     * \n jobExternalMsgReply
+     * \n jRusage
+     * \n pidInfo
+     * \n reserveItem
+     * \n submit
+     * <p/>
+     * <b>Define Statements:</b>
+     * \par
+     * \ref external_msg_processing
+     * \n \ref group_nodetypes
+     * #see \ref lsb_openjobinfo
+     * #see \ref lsb_openjobinfo_a
+     * #see \ref lsb_closejobinfo
+     * #see \ref lsb_hostinfo
+     * #see \ref lsb_pendreason
+     * #see \ref lsb_queueinfo
+     * #see \ref lsb_readjobinfo
+     * #see \ref lsb_suspreason
+     */
+    public static native jobInfoEnt.ByReference lsb_readjobinfo_cond(IntByReference more, jobInfoHeadExt jInfoHExt);
+
+    /**
+     * \page lsb_readframejob lsb_readframejob
+     * \brief Returns all frame jobs information which matchs the specified
+     * parameters and fills related information into the frame job information table.
+     * <p/>
+     * \ref lsb_readframejob gets all frame jobs information that matches the specified
+     * parameters and fills related information into the frame job information table.
+     * \ref lsb_readframejob is a wrapper of \ref lsb_openjobinfo, \ref lsb_readjobinfo, and
+     * \ref lsb_closejobinfo. Memory allocated in frameJobInfoTbl will be freed by
+     * user.
+     * <p/>
+     * <b>\#include <lsf/lsbatch.h>
+     * <p/>
+     * int lsb_readframejob(long jobId, String frameName,
+     * String user, String queue, String host, int options,
+     * frameJobInfo.ByReference[] frameJobInfoTbl)</b>
+     *
+     * @param jobId   Get information about the frame jobs with the given job ID.
+     *                If jobID is 0, get information about frame jobs which satisfy the other
+     *                specifications. If a job in a job array is to be modified, use the array
+     *                form jobID[i] where jobID is the job array name, and i is the index value.
+     * @param options <lsf/lsbatch.h> defines the following flags \ref defs_lsb_openjobinfo_a
+     *                constructed from bits. Use the bitwise OR to set more than one flag.
+     * @return int:-1
+     *         \n Function failed.
+     *         <p/>
+     *         \b Errors:
+     *         \par
+     *         If the function fails, lsberrno is set to indicate the error.
+     *         <p/>
+     *         <b>Equivalent line commands:</b>
+     *         \par
+     *         none
+     *         <p/>
+     *         <b>Files:</b>
+     *         \par
+     *         none
+     * @param frameName Get information about frame jobs with the given frame name.
+     * @param user Get information about frame jobs submitted by the named user
+     * or user group, or by all users if user is all. If user is null, the user
+     * invoking this routine is assumed.
+     * @param queue Get information about frame jobs belonging to the named queue.
+     * If queue is null,jobs in all queues of the batch system will be considered.
+     * @param host Get information about frame jobs on the named host, host
+     * group or cluster name.If host is null, jobs on all hosts of the batch
+     * system will be considered.
+     * @param frameJobInfoTbl The result of all frame jobs information.
+     * <p/>
+     * <b>Data Structures:</b>
+     * \par
+     * \n frameJobInfo
+     * \n frameElementInfo
+     * <p/>
+     * <b>Define Statements:</b>
+     * \par
+     * none
+     * #see \ref lsb_openjobinfo
+     * #see \ref lsb_readjobinfo
+     * #see \ref lsb_closejobinfo
+     */
+
+    public static native int lsb_readframejob(long jobId, String frameName, String user, String queue, String host, int options, Pointer frameJobInfoTbl);
+
+    /**
+     * \page lsb_closejobinfo lsb_closejobinfo
+     * \brief Closes job information connection with the master batch daemon.
+     * <p/>
+     * Use \ref lsb_closejobinfo to close the connection to the master batch daemon
+     * after opening a job information connection with \ref lsb_openjobinfo and reading
+     * job records with \ref lsb_readjobinfo.
+     * <p/>
+     * <b>\#include <lsf/lsbatch.h>
+     * <p/>
+     * void lsb_closejobinfo()</b>
+     *
+     * param void \n
+     *             <p/>
+     *             <b>Data Structures:</b>
+     *             \par
+     *             none
+     *             <p/>
+     *             <b>Define Statements:</b>
+     *             \par
+     *             none
+     * return void
+     *         \n There's no returns value.
+     *         <p/>
+     *         <p/>
+     *         \b Errors:
+     *         \par
+     *         On failure, lsberrno is set to indicate the error.
+     *         <p/>
+     *         <b>Equivalent line commands:</b>
+     *         \par
+     *         none
+     *         <p/>
+     *         <b>Files:</b>
+     *         \par
+     *         ${LSF_ENVDIR:-/etc}/lsf.conf
+     * #see \ref lsb_openjobinfo
+     * #see \ref lsb_openjobinfo_a
+     * #see \ref lsb_readjobinfo
+     */
+
+    public static native void lsb_closejobinfo();
+
+    /**
+     * \page  lsb_hostcontrol lsb_hostcontrol
+     * Opens or closes a host, or restarts or shuts down its slave batch daemon.
+     * <p/>
+     * \ref lsb_hostcontrol opens or closes a host, or restarts or shuts down its
+     * slave batch daemon. Any program using this API must be setuid to root if
+     * LSF_AUTH is not defined in the lsf.conf file.
+     * <p/>
+     * To restart the master batch daemon, mbatchd, in order to use updated
+     * batch LSF configuration files, use \ref lsb_reconfig.
+     * <p/>
+     * <b>\#include <lsf/lsbatch.h>
+     * <p/>
+     * int lsb_hostcontrol (hostCtrlReq.ByReference req)</b>
+     *
+     * @return int:-1 \n
+     *         Function failed.
+     *         <p/>
+     *         <b>Errors:</b>
+     *         \par
+     *         If the function fails, lsberrno is set to indicate the error.
+     *         <p/>
+     *         <b>Equivalent line commands:</b>
+     *         \par
+     *         none
+     *         <p/>
+     *         <b>Files:</b>
+     *         \par
+     *         ${LSF_ENVDIR:-/etc}/lsf.conf
+     * @param req The host control request.
+     * <p/>
+     * <b>Data Structures:</b>
+     * \par
+     * hostCtrlReq
+     * <p/>
+     * <b>Define Statements:</b>
+     * \par
+     * \ref host_ctrl_option
+     * #see \ref lsb_reconfig
+     */
+    public static native int lsb_hostcontrol(hostCtrlReq req);
+
+    public static native int lsb_hghostcontrol(hgCtrlReq hostCtrlReq1, hgCtrlReply reply);
+
+    /**
+     * \page lsb_queueinfo lsb_queueinfo
+     * \brief Returns information about batch queues.
+     * <p/>
+     * \ref lsb_queueinfo gets information about batch queues. See lsb.queues for more
+     * information about queue parameters.
+     * <p/>
+     * <b>\#include <lsf/lsbatch.h>
+     * <p/>
+     * queueInfoEnt.ByReference lsb_queueinfo(String[] queues,
+     * IntByReference numQueues, String hosts, String users,
+     * int options)</b>
+     *
+     * @param options Reserved for future use; supply 0.
+     *                <p/>
+     *                <b>Data Structures:</b>
+     *                \par
+     *                queueInfoEnt
+     *                \n shareAcctInfoEnt
+     *                \n apsFactorInfo
+     *                \n apsFactorMap
+     *                \n apsLongNameMap
+     *                <p/>
+     *                <b>Define Statements:</b>
+     *                \par
+     *                \ref queue_status
+     *                \n \ref queue_attribute
+     * @return null
+     *         \n Function Failed.
+     *         <p/>
+     *         \b Errors:
+     *         \par
+     *         If the function fails, lsberrno is set to indicate the error.
+     *         If lsberrno is LSBE_BAD_QUEUE, (*queues)[*numQueues] is not a queue known
+     *         to the LSF system. Otherwise, if.ByReference numQueues is less than its original value,
+     *         * numQueues is the actual number of queues found.
+     *         <p/>
+     *         <b>Equivalent line commands:</b>
+     *         \par
+     *         bqueues
+     *         <p/>
+     *         \b Files:
+     *         \par
+     *         $LSB_CONFDIR/cluster_name/configdir/lsb.queues
+     * @param queues An array of names of queues of interest.
+     * @param numQueues The number of queue names. To get information on all queues,
+     * set.ByReference numQueues to 0;* numQueues will be updated to the actual number of
+     * queues when this call returns.If.ByReference numQueues is 1 and queues is null,
+     * information on the system default queue is returned.
+     * @param hosts The host or cluster names. If hosts is not null, then only
+     * the queues that are enabled for the hosts are of interest.
+     * @param user The name of user. If user is not null, then only the queues
+     * that are enabled for the user are of interest.
+     * #see \ref lsb_hostinfo
+     * #see \ref lsb_userinfo
+     * #see \ref lsb_usergrpinfo
+     */
+    public static native queueInfoEnt.ByReference lsb_queueinfo(Pointer queues, IntByReference numQueues, String hosts, String user, int options);
+
+    /**
+     * \page lsb_reconfig lsb_reconfig
+     * \brief Dynamically reconfigures an LSF batch system.
+     * <p/>
+     * \ref lsb_reconfig dynamically reconfigures an LSF batch system to pick up new
+     * configuration parameters and changes to the job queue setup since system
+     * startup or the last reconfiguration (see lsb.queues).
+     * <p/>
+     * To restart a slave batch daemon, use \ref lsb_hostcontrol. This call is
+     * successfully invoked only by root or by the LSF administrator.
+     * <p/>
+     * Any program using this API must be setuid to root if LSF_AUTH is not
+     * defined in the lsf.conf file.
+     * <p/>
+     * <b>\#include <lsf/lsbatch.h>
+     * <p/>
+     * int lsb_reconfig (mbdCtrlReq.ByReference req)</b>
+     *
+     * @return int:-1 \n
+     *         The function failed.
+     *         <p/>
+     *         \b Errors:
+     *         \par
+     *         On failure, lsberrno is set to indicate the error.
+     *         <p/>
+     *         <b>Equivalent line commands:</b>
+     *         \par
+     *         badmin reconfig
+     *         <p/>
+     *         <b>Files:</b>
+     *         \par
+     *         ${LSF_ENVDIR:-/etc}/lsf.conf
+     * @param req mbatchd control request.
+     * <p/>
+     * <b>Data Structures:</b>
+     * \par
+     * mbdCtrlReq
+     * <p/>
+     * <b>Define Statements:</b>
+     * \par
+     * \ref mbd_operation
+     * #see \ref lsb_openjobinfo
+     */
+    public static native int lsb_reconfig(mbdCtrlReq req);
+
+    /**
+     * \page lsb_signaljob lsb_signaljob
+     * \brief Sends a signal to a job.
+     * <p/>
+     * Use \ref lsb_signaljob when migrating a job from one host to another. Use
+     * \ref lsb_signaljob to stop or kill a job on a host before using \ref lsb_mig to
+     * migrate the job. Next, use \ref lsb_signaljob to continue the stopped job at
+     * the specified host.
+     * <p/>
+     * Generally, use \ref lsb_signaljob to apply any UNIX signal to a job or process.
+     * <p/>
+     * Any program using this API must be setuid to root if LSF_AUTH is not defined
+     * in the lsf.conf file.
+     * <p/>
+     * <b>\#include <lsf/lsbatch.h>
+     * <p/>
+     * int lsb_signaljob (long jobId, int sigValue)</b>
+     *
+     * @param jobId    The job to be signaled. If a job in a job array is to be
+     *                 signaled, use the array form jobID[ i ] where jobID is the job array name,
+     *                 and i is the index value.
+     * @param sigValue SIGSTOP, SIGCONT, SIGKILL or some other UNIX signal.
+     *                 <p/>
+     *                 <b>Data Structures:</b>
+     *                 \par
+     *                 none
+     *                 <p/>
+     *                 <b>Define Statements:</b>
+     *                 \par
+     *                 none
+     * @return int:-1 \n
+     *         The function failed.
+     *         <p/>
+     *         \b Errors:
+     *         \par
+     *         If the function fails, lsberrno is set to indicate the error.
+     *         <p/>
+     *         <b>Equivalent line commands:</b>
+     *         \par
+     *         bkill \n
+     *         bstop \n
+     *         bresume
+     *         <p/>
+     *         <b>Files:</b>
+     *         \par
+     *         ${LSF_ENVDIR:-/etc}/lsf.conf
+     * #see \ref lsb_chkpntjob
+     * #see \ref lsb_forcekilljob
+     * #see \ref lsb_mig
+     */
+
+    public static native int lsb_signaljob(long jobId, int sigValue);
+
+    /**
+     * \page lsb_killbulkjobs lsb_killbulkjobs
+     * \brief Kills bulk jobs as soon as possible.
+     * <p/>
+     * Use \ref lsb_killbulkjobs to kill bulk jobs on a local host immediately, or
+     * to kill other jobs as soon as possible. If mbatchd rejects the request, it
+     * issues null as the reservation ID.
+     * <p/>
+     * <b>\#include <lsf/lsbatch.h>
+     * <p/>
+     * int lsb_killbulkjobs(signalBulkJobs.ByReference s)</b>
+     *
+     * @return int:-1 \n
+     *         The bulk jobs were not killed.
+     *         <p/>
+     *         \b Error:
+     *         \par
+     *         On failure, lsberrno is set to indicate the error.
+     *         <p/>
+     *         <b>Equivalent line command:</b>
+     *         \par
+     *         bkill -b
+     *         <p/>
+     *         <b>Files:</b>
+     *         \par
+     *         none
+     * @param s The signal to a group of jobs.
+     * <p/>
+     * <b>Data Structures:</b>
+     * \par
+     * signalBulkJobs
+     * <p/>
+     * <b>Define Statements:</b>
+     * \par
+     * none
+     * see none
+     */
+
+    public static native int lsb_killbulkjobs(signalBulkJobs s);
+
+    public static native int lsb_msgjob(long long1, String s);
+
+    /**
+     * \page lsb_chkpntjob lsb_chkpntjob
+     * \brief Checkpoints a job.
+     * <p/>
+     * Checkpoints a job.
+     * <p/>
+     * <b>\#include <lsf/lsbatch.h>
+     * <p/>
+     * int lsb_chkpntjob(long jobId, int period, int options)</b>
+     *
+     * @param jobId   The job to be checkpointed.
+     * @param period  The checkpoint period in seconds. The value 0
+     *                disables periodic checkpointing.
+     * @param options The bitwise inclusive OR of some of the following:
+     *                \n LSB_CHKPNT_KILL
+     *                Checkpoint and kill the job as an atomic action.
+     *                \n LSB_CHKPNT_FORCE
+     *                Checkpoint the job even if non-checkpointable conditions exist.
+     *                <p/>
+     *                <b>Data Structures:</b>
+     *                \par
+     *                none
+     *                <p/>
+     *                <b>Define Statements:</b>
+     *                \par
+     *                \ref chkpnt_job_option
+     * @return int:-1 \n
+     *         The function failed.
+     *         <p/>
+     *         \note Any program using this API must be setuid to root if LSF_AUTH
+     *         is not defined in the lsf.conf file.
+     *         <p/>
+     *         \b Errors:
+     *         \par
+     *         On failure, lsberrno is set to indicate the error.
+     *         <p/>
+     *         <b>Equivalent line commands:</b>
+     *         \par
+     *         bchkpnt
+     *         <p/>
+     *         <b>Files:</b>
+     *         \par
+     *         ${LSF_ENVDIR:-/etc}/lsf.conf
+     * see none
+     */
+    public static native int lsb_chkpntjob(long jobId, NativeLong period, int options);
+
+    /**
+     * \page lsb_deletejob lsb_deletejob
+     * \brief Kills a job in a queue
+     * <p/>
+     * Use \ref lsb_deletejob to send a signal to kill a running, user-suspended,
+     * or system-suspended job. The job can be requeued or deleted from the batch
+     * system.If the job is requeued, it retains its submit time but it is dispatched
+     * according to its requeue time. When the job is requeued, it is assigned the
+     * PEND status and re-run.If the job is deleted from the batch system, it is
+     * no longer available to be requeued.
+     * <p/>
+     * <b>\#include <lsf/lsbatch.h>
+     * <p/>
+     * int lsb_deletejob (long jobId, int times, int options)</b>
+     *
+     * @param jobId   The job to be killed. If an element of a job array is to be
+     *                killed, use the array form jobID[i] where jobID is the job array name,
+     *                and i is the index value.
+     * @param times   Original job submit time.
+     * @param options If the preprocessor macro LSB_KILL_REQUEUE in lsbatch.h is
+     *                compared with options and found true, then requeue the job using the same job ID.
+     *                If the preprocessor macro LSB_KILL_REQUEUE in lsbatch.h is compared with
+     *                options and found false, then the job is deleted from the batch system.
+     *                <p/>
+     *                <b>Data Structures:</b>
+     *                \par
+     *                none
+     *                <p/>
+     *                <b>Define Statements:</b>
+     *                \par
+     *                \ref kill_requeue
+     * @return int:-1 \n
+     *         The function failed.
+     *         <p/>
+     *         \note Any program using this API must be setuid to root if LSF_AUTH is not defined in the
+     *         \n lsf.conf file.
+     *         <p/>
+     *         \b Errors:
+     *         \par
+     *         On failure, lsberrno is set to indicate the error.
+     *         <p/>
+     *         <b>Equivalent line commands:</b>
+     *         \par
+     *         bkill
+     *         \n brequeue -J
+     *         <p/>
+     *         <b>Files:</b>
+     *         \par
+     *         ${LSF_ENVDIR:-/etc}/lsf.conf
+     * #see \ref lsb_signaljob
+     * #see \ref lsb_chkpntjob
+     */
+    public static native int lsb_deletejob(long jobId, int times, int options);
+
+    /**
+     * \page lsb_forcekilljob lsb_forcekilljob
+     * \brief This function is used to send special force kill signal.
+     * <p/>
+     * <b>\#include <lsf/lsbatch.h>
+     * <p/>
+     * int lsb_forcekilljob(long jobId)</b>
+     *
+     * @param jobId which job is to be killed.
+     *              <p/>
+     *              <b>Data Structures:</b>
+     *              \par
+     *              none
+     *              <p/>
+     *              <b>Define Statements:</b>
+     *              \par
+     *              none
+     * @return int:-1
+     *         \n Function failed.
+     *         <p/>
+     *         \b Errors:
+     *         \par
+     *         On failure, lsberrno is set to indicate the error.
+     *         <p/>
+     *         <b>Equivalent line commands:</b>
+     *         \par
+     *         none
+     *         <p/>
+     *         <b>Files:</b>
+     *         \par
+     *         none
+     * #see \ref lsb_signaljob
+     */
+    public static native int lsb_forcekilljob(long jobId);
+
+    /**
+     * \page lsb_submitframe lsb_submitframe
+     * \brief Submits a frame job to the batch system.
+     * <p/>
+     * \ref lsb_submitframe submits a frame job to the batch system according to the
+     * jobSubReq specification and frameExp.
+     * <p/>
+     * Any program using this API must be setuid to root if LSF_AUTH is not defined
+     * in the lsf.conf file.
+     * <p/>
+     * <b>\#include <lsf/lsbatch.h>
+     * <p/>
+     * int lsb_submitframe (submit.ByReference jobSubReq, String frameExp,
+     * submitReply.ByReference jobSubReply)</b>
+     *
+     * @return int:-1 \n
+     *         Function failed.
+     *         <p/>
+     *         \b Errors:
+     *         \par
+     *         If the function fails, lsberrno is set to indicate the error and jobSubReply gives
+     *         additional information about the error.
+     *         <p/>
+     *         <b>Equivalent line commands:</b>
+     *         \par
+     *         none
+     *         <p/>
+     *         <b>Files:</b>
+     *         \par
+     *         ${LSF_ENVDIR:-/etc}/lsf.conf
+     * @param jobSubReq Describes the requirements for job submission to the
+     * batch system. A job that does not meet these requirements is not submitted
+     * to the batch system and an error is returned. \n
+     * See \ref lsb_submit for descriptions of the submit structure fields.
+     * @param frameExp The syntax of frameExp is: \n
+     * <b>frame_name[indexlist]</b> \n
+     * frame_name is any name consisting of alphanumerics, periods, forward slashes,
+     * dashes or underscores. indexlist is a list of one or more frame indexes,
+     * separated by commas. These indexes can each be either a single integer or
+     * a range, specified in the following format: \n
+     * <b>start-end[xstep[:chunk]]</b> \n
+     * start, end, step, and chunk are integers, but chunk must be positive.
+     * If step and
+     * chunk are ommitted, the default value is 1.\n
+     * An example of a valid expression for frameExp is:\n
+     * <b>Frame_job_1[5,10-15,20-30x2:3]</b>
+     * @param jobSubReply Describes the results of the job submission to the
+     * batch system. \n
+     * See \ref lsb_submit for descriptions of the submitReply structure
+     * fields.
+     * <p/>
+     * <b>Data Structures:</b>
+     * \par
+     * submit
+     * \n submitReply
+     * <p/>
+     * <b>Define Statements:</b>
+     * \par
+     * \ref lsb_submit_options
+     * \n \ref lsb_submit_options2
+     * \n \ref lsb_submit_options3
+     * see none
+     */
+    public static native int lsb_submitframe(submit jobSubReq, String frameExp, submitReply jobSubReply);
+
+    /**
+     * \page lsb_requeuejob lsb_requeuejob
+     * \brief Requeues job arrays, jobs in job arrays, and individual jobs.
+     * <p/>
+     * Use \ref lsb_requeuejob to requeue job arrays, jobs in job arrays, and individual
+     * jobs that are running, pending, done, or exited. In a job array, you can
+     * requeue all the jobs or requeue individual jobs of the array.
+     * <p/>
+     * \ref lsb_requeuejob requeues jobs as if the jobs were in an array. A job not in an
+     * array is considered to be a job array composed of one job.
+     * <p/>
+     * Jobs in a job array can be requeued independently of each other regardless of
+     * any job's status (running, pending, exited, done). A requeued job is requeued
+     * to the same queue it was originally submitted from or switched to. The job
+     * submission time does not change so a requeued job is placed at the top of the
+     * queue. Use \ref lsb_movejob to place a job at the bottom or any other position
+     * in a queue.
+     * <p/>
+     * If a clean period is reached before \ref lsb_requeuejob is called, the cleaned
+     * jobs cannot be requeued. Set the variable CLEAN_PERIOD in your lsb.params file
+     * to determine the amount of time that job records are kept in MBD core memory
+     * after jobs have finished or terminated.
+     * <p/>
+     * To requeue a job assign values to the data members of the jobrequeue data
+     * structure, process command line options in case the user has specified a
+     * different job, and call \ref lsb_requeuejob to requeue the job array.
+     * <p/>
+     * Assign values to the jobID, status, and options data members of the jobrequeue
+     * data structure. Assign the job identification number to jobID. Assign
+     * JOB_STAT_PEND or JOB_STAT_PSUSP to status. Assign REQUEUE_DONE, REQUEUE_EXIT,
+     * and or REQUEUE_RUN to requeue running jobs.
+     * <p/>
+     * <b>\#include <lsf/lsbatch.h>
+     * <p/>
+     * int lsb_requeuejob(jobrequeue.ByReference  reqPtr)</b>
+     *
+     * @return int:-1 \n
+     *         The function failed.
+     *         <p/>
+     *         \b Errors:
+     *         \par
+     *         On failure, lsberrno is set to indicate the error.
+     *         <p/>
+     *         <b>Equivalent line commands:</b>
+     *         \par
+     *         brequeue -d
+     *         \n brequeue -e
+     *         \n brequeue -a
+     *         \n brequeue -r
+     *         \n brequeue -H
+     *         <p/>
+     *         <b>Files:</b>
+     *         \par
+     *         $LSB_CONFDIR/cluster_name/configdir/lsb.params
+     *         \n $LSB_SHAREDIR
+     * @param reqPtr This structure contains the information required to requeue a job.
+     * <p/>
+     * <b>Data Structures:</b>
+     * \par
+     * jobrequeue
+     * <p/>
+     * <b>Define Statements:</b>
+     * \par
+     * \ref requeuejob_options
+     * #see \ref lsb_movejob
+     * #see \ref lsb_pendreason
+     */
+    public static native int lsb_requeuejob(jobrequeue reqPtr);
+
+    /**
+     * \page lsb_sysmsg lsb_sysmsg
+     * \brief Returns a pointer to static data.
+     * <p/>
+     * \ref lsb_sysmsg returns a pointer to static data which stores the batch error
+     * message corresponding to lsberrno. The global variable lsberrno maintained
+     * by LSBLIB holds the error number from the most recent LSBLIB call that caused
+     * an error. If lsberrno == LSBE_SYS_CALL, then the system error message defined
+     * by errno is also returned. If lsberrno == LSBE_LSLIB, then the error message
+     * returned by \ref ls_sysmsg is returned.
+     * <p/>
+     * <b>\#include <lsf/lsbatch.h>
+     * <p/>
+     * String lsb_sysmsg ()</b>
+     *
+     * param void \n
+     *             <p/>
+     *             <b>Data Structures:</b>
+     *             \par
+     *             none
+     *             <p/>
+     *             <b>Define Statements:</b>
+     *             \par
+     *             none
+     * @return null
+     *         \n Function failed.
+     *         <p/>
+     *         \b Errors:
+     *         \par
+     *         If the function fails, lsberrno is set to indicate the error.
+     *         <p/>
+     *         <b>Equivalent line commands:</b>
+     *         \par
+     *         none
+     *         <p/>
+     *         <b>Files:</b>
+     *         \par
+     *         none
+     * #see \ref ls_perror
+     * #see \ref ls_sysmsg
+     */
+    public static native String lsb_sysmsg();
+
+    /**
+     * \page lsb_perror lsb_perror
+     * \brief Prints a batch LSF error message on stderr.
+     * <p/>
+     * \ref lsb_perror prints a batch LSF error message on stderr. The usrMsg is
+     * printed out first, followed by a ":" and the batch error message corresponding
+     * to lsberrno.
+     * <p/>
+     * \ref lsb_perror - Print LSBATCH error message on stderr. In addition
+     * to the error message defined by lsberrno, user supplied message usrMsg1
+     * is printed out first and a ':' is added to separate.ByReference  usrMsg1 and LSBATCH
+     * error message.
+     * <p/>
+     * <b>\#include <lsf/lsbatch.h>
+     * <p/>
+     * void lsb_perror (String usrMsg)</b>
+     *
+     * return void \n
+     *         Prints out the user supplied error message.
+     *         <p/>
+     *         \b Errors:
+     *         \par
+     *         If the function fails, lsberrno is set to indicate the error.
+     *         <p/>
+     *         <b>Equivalent line command:</b>
+     *         \par
+     *         none
+     *         <p/>
+     *         \b Files:
+     *         \par
+     *         none
+     * @param usrMsg A user supplied error message.
+     * <p/>
+     * <b>Data Structures:</b>
+     * \par
+     * none
+     * <p/>
+     * <b>Define Statements:</b>
+     * \par
+     * none
+     * see none
+     */
+    public static native void lsb_perror(String usrMsg);
+
+    public static native void lsb_errorByCmd(String string1, String string2, int int1);
+
+    public static native String lsb_sperror(String string1);
+
+    /**
+     * \page lsb_peekjob lsb_peekjob
+     * \brief Returns the base name of the file related to the job ID
+     * <p/>
+     * \ref lsb_peekjob retrieves the name of a job file.
+     * <p/>
+     * Only the submitter can peek at job output.
+     * <p/>
+     * The storage for the file name will be reused by the next call.
+     * <p/>
+     * Any program using this API must be setuid to root if LSF_AUTH
+     * is not defined in the lsf.conf file.
+     * <p/>
+     * <b>\#include <lsf/lsbatch.h>
+     * <p/>
+     * String  lsb_peekjob (long jobId)</b>
+     *
+     * @param jobId The job ID that the LSF system assigned to the job. If a job
+     *              in a job array is to be returned, use the array form jobID[i] where jobID
+     *              is the job array name, and i is the index value.
+     *              <p/>
+     *              <b>Data Structures:</b>
+     *              \par
+     *              none
+     *              <p/>
+     *              <b>Define Statements:</b>
+     *              \par
+     *              none
+     * @return null
+     *         \n Function failed.
+     *         <p/>
+     *         \b Errors:
+     *         \par
+     *         If the function fails, lsberrno is set to indicate the error.
+     *         <p/>
+     *         <b>Equivalent line command:</b>
+     *         \par
+     *         bpeek
+     *         <p/>
+     *         \b Files:
+     *         \par
+     *         ${LSF_ENVDIR:-/etc}/lsf.conf
+     * see none
+     */
+    public static native String lsb_peekjob(long jobId);
+
+    /**
+     * \page lsb_mig lsb_mig
+     * \brief Migrates a job from one host to another.
+     * <p/>
+     * \ref lsb_mig migrates a job from one host to another. Any program using
+     * this API must be setuid to root if LSF_AUTH is not defined
+     * in the lsf.conf file.
+     * <p/>
+     * <b>\#include <lsf/lsbatch.h>
+     * <p/>
+     * int lsb_mig(submig.ByReference mig, IntByReference badHostIdx)</b>
+     *
+     * @return int:-1 \n
+     *         Function failed.
+     *         <p/>
+     *         \b Errors:
+     *         \par
+     *         If the function fails, lsberrno is set to indicate the error and badHostIdx indicates
+     *         which askedHost is not acceptable.
+     *         <p/>
+     *         <b>Equivalent line command:</b>
+     *         \par
+     *         none
+     *         <p/>
+     *         \b Files:
+     *         \par
+     *         ${LSF_ENVDIR:-/etc}/lsf.conf
+     * @param mig The job to be migrated.
+     * @param badHostIdx If the call fails, (**askedHosts)[*badHostIdx] is not a
+     * host known to the LSF system.
+     * <p/>
+     * <b>Data Structures:</b>
+     * \par
+     * submig
+     * <p/>
+     * <b>Define Statements:</b>
+     * \par
+     * none
+     * #see \ref lsb_submit
+     */
+    public static native int lsb_mig(submig mig, IntByReference badHostIdx);
+
+    public static native clusterInfoEnt.ByReference lsb_clusterinfo(IntByReference int1, Pointer stringArray1, int int2);
+
+    public static native clusterInfoEntEx.ByReference lsb_clusterinfoEx(IntByReference int1, Pointer stringArray1, int int2);
+
+    /**
+     * \page lsb_hostinfo lsb_hostinfo
+     * Returns information about job server hosts.
+     * <p/>
+     * <b>\#include <lsf/lsbatch.h>
+     * <p/>
+     * hostInfoEnt.ByReference lsb_hostinfo(String[] hosts, IntByReference numHosts)</b>
+     *
+     * @return hostInfoEnt.ByReference :null
+     *         \n Function failed.
+     *         <p/>
+     *         <b>Errors:</b>
+     *         \par
+     *         If the function fails, lsberrno is set to indicate the error. If lsberrno is
+     *         LSBE_BAD_HOST, (*hosts)[*numHosts] is not a host known to the batch system.
+     *         Otherwise, if.ByReference numHosts is less than its original value,* numHosts is the actual
+     *         number of hosts found.
+     *         <p/>
+     *         <b>Equivalent line commands:</b>
+     *         \par
+     *         bhosts
+     *         <p/>
+     *         <b>Files:</b>
+     *         \par
+     *         $LSB_CONFDIR/cluster_name/configdir/lsb.hosts
+     * @param hosts
+     * An array of host or cluster names.
+     * @param numHosts
+     * The number of host names.
+     * To get information on all hosts, set.ByReference numHosts to 0;* numHosts will be set to the
+     * actual number of hostInfoEnt structures when this call returns.
+     * If.ByReference numHosts is 1 and hosts is null, information on the local host is returned.
+     * <p/>
+     * <b>Data Structures:</b>
+     * \par
+     * hostInfoEnt
+     * <p/>
+     * <b>Define Statements:</b>
+     * \par
+     * \ref host_status
+     * \n \ref host_load_BusyReason
+     * \n \ref host_attributes
+     * #see \ref lsb_hostinfo_ex
+     * #see \ref ls_info
+     * #see \ref ls_loadofhosts
+     * #see \ref lsb_queueinfo
+     * #see \ref lsb_userinfo
+     */
+    public static native hostInfoEnt.ByReference lsb_hostinfo(Pointer hosts, IntByReference numHosts);
+
+    /**
+     * \page lsb_hostinfo_ex lsb_hostinfo_ex
+     * Returns informaton about job server hosts that satisfy specified resource
+     * requirements. \ref lsb_hostinfo_ex returns information about job server hosts
+     * that satisfy the specified resource requirements.
+     * <p/>
+     * <b>\#include <lsf/lsbatch.h>
+     * <p/>
+     * hostInfoEnt.ByReference lsb_hostinfo_ex(String[] hosts,
+     * IntByReference numHosts, String resReq, int options)</b> @param hosts An array of host or cluster names.
+     *
+     * @param options Options is reserved for the future use.
+     *                <p/>
+     *                <b>Data Structures:</b>
+     *                \par
+     *                hostInfoEnt
+     *                <p/>
+     *                <b>Define Statements:</b>
+     *                \par
+     *                \ref host_status
+     *                \n \ref host_load_BusyReason
+     *                \n \ref host_attributes
+     * @return null
+     *         \n Function failed.
+     *         <p/>
+     *         <b>Errors:</b>
+     *         \par
+     *         If the function fails, lsberrno is set to indicate the error. If lsberrno is
+     *         LSBE_BAD_HOST, (*hosts)[*numHosts] is not a host known to the batch system.
+     *         Otherwise, if.ByReference numHosts is less than its original value,* numHosts is the actual
+     *         number of hosts found.
+     *         <p/>
+     *         <b>Equivalent line commands:</b>
+     *         \par
+     *         none
+     *         <p/>
+     *         <b>Files:</b>
+     *         \par
+     *         $LSB_CONFDIR/cluster_name/configdir/lsb.hosts
+     * @param numHosts The number of host names.
+     * To get information on all hosts, set.ByReference numHosts to 0;* numHosts will be set
+     * to the actual number of hostInfoEnt structures when this call returns.
+     * If.ByReference numHosts is 1 and hosts is null, information on the local host is returned.
+     * @param resReq Resource requirements.
+     * If this option is specified, then only host information for those hosts
+     * that satisfy the resource requirements is returned. Returned hosts are
+     * sorted according to the load on the resource() given in resReq, or by
+     * default according to CPU and paging load.
+     * #see \ref ls_info
+     * #see \ref ls_loadofhosts
+     * #see \ref lsb_hostinfo
+     * #see \ref lsb_queueinfo
+     * #see \ref lsb_userinfo
+     * @param string1 string1
+     */
+
+    public static native hostInfoEnt.ByReference lsb_hostinfo_ex(Pointer resReq, IntByReference numHosts, String string1, int options);
+
+    /**
+     * \page lsb_hostinfo_cond lsb_hostinfo_cond
+     * Returns condensed information about job server hosts.
+     * <p/>
+     * \ref lsb_hostinfo_cond returns condensed information about job server hosts.
+     * While \ref lsb_hostinfo returns specific information about individual hosts,
+     * \ref lsb_hostinfo_cond returns the number of jobs in each state within the
+     * entire host group. The condHostInfoEnt structure contains counters that
+     * indicate how many hosts are in the ok, busy, closed, full, unreach, and
+     * unavail states and an array of hostInfoEnt structures that indicate the
+     * status of each host in the host
+     * group.
+     * <p/>
+     * <b>\#include <lsf/lsbatch.h>
+     * <p/>
+     * condHostInfoEnt.ByReference  lsb_hostinfo_cond
+     * (String[] hosts, IntByReference numHosts,
+     * String resReq, int options)</b>
+     *
+     * @param options Any options called with the function.
+     *                <p/>
+     *                <b>Data Structures</b>
+     *                \par
+     *                condHostInfoEnt
+     *                \n hostInfoEnt
+     *                <p/>
+     *                <b>Define Statements:</b>
+     *                \par
+     *                none
+     * @return null
+     *         \n Function failed.
+     *         <p/>
+     *         <b Errors:</b>
+     *         \par
+     *         If the function fails, lsberrno is set to indicate the error.
+     *         <p/>
+     *         <b>Equivalent line commands:</b>
+     *         \par
+     *         none
+     *         <p/>
+     *         <b>Files:</b>
+     *         \par
+     *         none
+     * @param hosts An array of host names belonging to the host group.
+     * @param numHosts The number of host names in the host group.
+     * To get information on all hosts in the host group, set.ByReference numHosts to 0;
+     * * numHosts will be set to the actual number of hostInfoEnt structures in
+     * the host group when this call returns.
+     * @param resReq Any resource requirements called with the function.
+     * #see \ref lsb_hostinfo
+     */
+    public static native condHostInfoEnt.ByReference lsb_hostinfo_cond(Pointer hosts, IntByReference numHosts, String resReq, int options);
+
+    /**
+     * \page lsb_movejob lsb_movejob
+     * \brief Changes the position of a pending job in a queue.
+     * <p/>
+     * Use \ref lsb_movejob to move a pending job to a new position that you specify
+     * in a queue. Position the job in a queue by first specifying the job ID.
+     * Next, count, beginning at 1, from either the top or the bottom of the queue,
+     * to the position you want to place the job.
+     * <p/>
+     * To position a job at the top of a queue, choose the top of a queue parameter
+     * and a postion of 1.To position a job at the bottom of a queue, choose the
+     * bottom of the queue parameter and a position of 1.
+     * <p/>
+     * By default, LSF dispatches
+     * jobs in a queue in order of their arrival (such as first-come-first-served),
+     * subject to the availability of suitable server hosts.
+     * <p/>
+     * <b>\#include <lsf/lsbatch.h>
+     * <p/>
+     * int lsb_movejob (long jobId, IntByReference position, int opCode)</b>
+     *
+     * @param jobId  The job ID that the LSF system assigns to the job. If a job
+     *               in a job array is to be moved, use the array form jobID[ i ] where jobID is
+     *               the job array name, and i is the index value.
+     * @param opCode The top or bottom position of a queue.
+     *               \n \b TO_TOP
+     *               \n The top position of a queue.
+     *               \n \b TO_BOTTOM
+     *               \n The bottom position of a queue.
+     *               \n If an opCode is not specified for the top or bottom position, the
+     *               function fails.
+     *               <p/>
+     *               <b>Data Structures:</b>
+     *               \par
+     *               none
+     *               <p/>
+     *               <b>Define Statements:</b>
+     *               \par
+     *               \ref movejob_options
+     * @return int:-1 \n
+     *         The function failed.
+     *         <p/>
+     *         \b Errors:
+     *         \par
+     *         If the function fails, lsberrno is set to indicate the error.
+     *         <p/>
+     *         <b>Equivalent line command:</b>
+     *         \par
+     *         btop
+     *         \n bbot
+     *         \n bjobs -q
+     *         <p/>
+     *         \b Files:
+     *         \par
+     *         ${LSF_ENVDIR:-/etc}/lsf.conf
+     * @param position The new position of the job in a queue. position must be
+     * a value of 1 or more.
+     * #see \ref lsb_pendreason
+     */
+
+    public static native int lsb_movejob(long jobId, IntByReference opCode, int position);
+
+    /**
+     * \page lsb_switchjob lsb_switchjob
+     * \brief Switches an unfinished job to another queue.
+     * <p/>
+     * \ref lsb_switchjob switches an unfinished job to another queue. Effectively,
+     * the job is removed from its current queue and re-queued in the new queue.
+     * <p/>
+     * The switch operation can be performed only when the job is acceptable to
+     * the new queue. If the switch operation is unsuccessful, the job will stay
+     * where it is.A user can only switch his/her own unfinished jobs, but root
+     * and the LSF administrator can switch any unfinished job.
+     * <p/>
+     * Any program using this API must be setuid to root if LSF_AUTH is not defined
+     * in the lsf.conf file.
+     * <p/>
+     * <b>\#include <lsf/lsbatch.h>
+     * <p/>
+     * int lsb_switchjob (long jobId, String queue)</b>
+     *
+     * @param jobId The job to be switched. If an element of a job array is to
+     *              be switched, use the array form jobID[i] where jobID is the job array name,
+     *              and i is the index value.
+     * @return int:-1 \n
+     *         Function failed.
+     *         <p/>
+     *         \b Errors:
+     *         \par
+     *         If the function fails, lsberrno is set to indicate the error.
+     *         <p/>
+     *         <b>Equivalent line commands:</b>
+     *         \par
+     *         bswitch
+     *         <p/>
+     *         <b>Files:</b>
+     *         \par
+     *         ${LSF_ENVDIR:-/etc}/lsf.conf
+     * @param queue The new queue for the job.
+     * <p/>
+     * <b>Data Structures:</b>
+     * \par
+     * none
+     * <p/>
+     * <b>Define Statements:</b>
+     * \par
+     * none
+     * see none
+     */
+    public static native int lsb_switchjob(long jobId, String queue);
+
+    /**
+     * \page lsb_queuecontrol lsb_queuecontrol
+     * \brief Changes the status of a queue.
+     * <p/>
+     * \ref lsb_queuecontrol changes the status of a queue.
+     * <p/>
+     * Any program using this API must be setuid to root if LSF_AUTH is not defined
+     * in the lsf.conf file.
+     * <p/>
+     * If a queue is inactivated by its dispatch window (see lsb.queues), then it
+     * cannot be re-activated by this call.
+     * <p/>
+     * <b>\#include <lsf/lsbatch.h>
+     * <p/>
+     * int lsb_queuecontrol (queueCtrlReq.ByReference req)</b>
+     *
+     * @return int:-1 \n
+     *         Function failed.
+     *         <p/>
+     *         \b Errors:
+     *         \par
+     *         If the function fails, lsberrno is set to indicate the error.
+     *         <p/>
+     *         <b>Equivalent line commands:</b>
+     *         \par
+     *         none
+     *         <p/>
+     *         \b Files:
+     *         \par
+     *         ${LSF_ENVDIR:-/etc}/lsf.conf
+     * @param req queue control request.
+     * <p/>
+     * <b>Data Structures:</b>
+     * \par
+     * queueCtrlReq
+     * <p/>
+     * <b>Define Statements:</b>
+     * \par
+     * \ref queue_ctrl_option
+     * #see \ref lsb_queueinfo
+     */
+    public static native int lsb_queuecontrol(queueCtrlReq req);
+
+    /**
+     * \page lsb_userinfo lsb_userinfo
+     * \brief Returns the maximum number of job slots that a user can use
+     * simultaneously on any host and in the whole local LSF cluster.
+     * <p/>
+     * \ref lsb_userinfo gets the maximum number of job slots that a user can use
+     * simultaneously on any host and in the whole local LSF cluster, as well as
+     * the current number of job slots used by running and suspended jobs or
+     * reserved for pending jobs. The maximum numbers of job slots are defined
+     * in the LSF configuration file lsb.users (see lsb.users). The reserved
+     * user name default, defined in the lsb.users configuration file, matches
+     * users not listed in the lsb.users file who have no jobs started in the
+     * system.
+     * <p/>
+     * The returned array will be overwritten by the next call.
+     * <p/>
+     * <b>\#include <lsf/lsbatch.h>
+     * <p/>
+     * userInfoEnt.ByReference lsb_userinfo(String[] users, IntByReference numUsers)</b>
+     *
+     * @return null \n
+     *         Function failed.
+     *         <p/>
+     *         \b Errors:
+     *         \par
+     *         If the function fails, lsberrno is set to indicate the error. If lsberrno is
+     *         LSBE_BAD_USER, (*users)[*numUsers] is not a user known to the LSF system.
+     *         Otherwise, if.ByReference numUsers is less than its original value,* numUsers is the actual
+     *         number of users found.
+     *         <p/>
+     *         <b>Equivalent line commands:</b>
+     *         \par
+     *         busers
+     *         <p/>
+     *         <b>Files:</b>
+     *         \par
+     *         $LSB_CONFDIR/cluster_name/configdir/lsb.users
+     * @param users An array of user names.
+     * @param numUsers The number of user names.
+     * To get information about all users, set.ByReference numUsers = 0;* numUsers will
+     * be updated to the actual number of users when this call returns. To get
+     * information on the invoker, set users = null,* numUsers = 1.
+     * <p/>
+     * <b>Data Structures:</b>
+     * \par
+     * userInfoEnt
+     * <p/>
+     * <b>Define Statements:</b>
+     * \par
+     * none
+     * #see \ref lsb_hostinfo
+     * #see \ref lsb_queueinfo
+     */
+    public static native userInfoEnt.ByReference lsb_userinfo(Pointer users, IntByReference numUsers);
+
+    /**
+     * \page lsb_hostgrpinfo lsb_hostgrpinfo
+     * Returns LSF host group membership.
+     * <p/>
+     * \ref lsb_hostgrpinfo gets LSF host group membership.
+     * <p/>
+     * LSF host group is defined in the configuration file lsb.hosts.
+     * <p/>
+     * The storage for the array of groupInfoEnt structures will be reused by
+     * the next call.
+     * <p/>
+     * <b>\#include <lsf/lsbatch.h>
+     * <p/>
+     * groupInfoEnt.ByReference lsb_hostgrpinfo (String[] groups,IntByReference numGroups,
+     * int options)</b>
+     *
+     * @param options The bitwise inclusive OR of some of the following flags:
+     *                \n GRP_RECURSIVE
+     *                \n Expand the group membership recursively. That is, if a member of a
+     *                group is itself a group, give the names of its members recursively, rather
+     *                than its name, which is the default.
+     *                \n GRP_ALL
+     *                \n Get membership of all groups.
+     *                <p/>
+     *                <b>Data Structures:</b>
+     *                \par
+     *                groupInfoEnt
+     *                \n userShares
+     *                <p/>
+     *                <b>Define Statements:</b>
+     *                \par
+     *                \ref group_membership_option
+     *                \n \ref group_define
+     * @return null \n
+     *         Function failed.
+     *         <p/>
+     *         <b>Errors:</b>
+     *         \par
+     *         On failure, returns null and sets lsberrno to indicate the error. If there
+     *         are invalid groups specified, the function returns the groups up to the
+     *         invalid ones and then sets lsberrno to LSBE_BAD_GROUP, which means that
+     *         the specified (*groups)[*numGroups] is not a group known to the LSF system.
+     *         If the first group specified is invalid, the function returns null.
+     *         <p/>
+     *         <b>Equivalent line commands:</b>
+     *         \par
+     *         none
+     *         <p/>
+     *         <b>Files:</b>
+     *         \par
+     *         $LSB_CONFDIR/cluster_name/configdir/lsb.hosts \n
+     *         $LSB_CONFDIR/cluster_name/configdir/lsb.users
+     * @param groups An array of group names.
+     * @param numGroups The number of group names.* numGroups will be updated
+     * to the actual number of groups when this call returns.
+     * #see \ref lsb_usergrpinfo
+     */
+    public static native groupInfoEnt.ByReference lsb_hostgrpinfo(Pointer groups, IntByReference numGroups, int options);
+
+    /**
+     * \page lsb_usergrpinfo lsb_usergrpinfo
+     * \brief Returns LSF user group membership.
+     * <p/>
+     * \ref lsb_usergrpinfo gets LSF user group membership.
+     * LSF user group is defined in the configuration file lsb.users.
+     * The storage for the array of groupInfoEnt structures will be reused by
+     * the next call.
+     * <p/>
+     * <b>\#include <lsf/lsbatch.h>
+     * <p/>
+     * groupInfoEnt.ByReference lsb_usergrpinfo (String[] groups,
+     * IntByReference numGroups, int options)</b>
+     *
+     * @param options The bitwise inclusive OR of some of flags in \ref group_membership_option
+     *                <p/>
+     *                <b>Data Structures:</b>
+     *                \par
+     *                groupInfoEnt
+     *                <p/>
+     *                <b>Define Statements:</b>
+     *                \par
+     *                \ref group_membership_option
+     *                \n \ref group_define
+     * @return null \n
+     *         Function failed.
+     *         <p/>
+     *         \b Errors:
+     *         \par
+     *         On failure, returns null and sets lsberrno to indicate the error. If there
+     *         are invalid groups specified, the function returns the groups up to the
+     *         invalid ones. It then set lsberrno to LSBE_BAD_GROUP, that is the specified
+     *         (*groups)[*numGroups] is not a group known to the LSF system. If the first
+     *         group is invalid, the function returns null.
+     *         <p/>
+     *         <b>Equivalent line commands:</b>
+     *         \par
+     *         none
+     *         <p/>
+     *         <b>Files:</b>
+     *         \par
+     *         $LSB_CONFDIR/cluster_name/configdir/lsb.hosts
+     *         \n $LSB_CONFDIR/cluster_name/configdir/lsb.users
+     * @param groups An array of group names.
+     * @param numGroups The number of group names.* numGroups will be updated
+     * to the actual number of groups when this call returns.
+     * #see \ref lsb_hostgrpinfo
+     */
+    public static native groupInfoEnt.ByReference lsb_usergrpinfo(Pointer groups, IntByReference numGroups, int options);
+
+    /**
+     * \page lsb_parameterinfo lsb_parameterinfo
+     * \brief Returns information about the LSF cluster.
+     * <p/>
+     * \ref lsb_parameterinfo gets information about the LSF cluster.
+     * <p/>
+     * The static storage for the parameterInfo structure is reused on the next call.
+     * <p/>
+     * <b>\#include <lsf/lsbatch.h>
+     * <p/>
+     * parameterInfo.ByReference lsb_parameterinfo(String[] names,
+     * IntByReference numUsers, int options)</b>
+     *
+     * @param options Reserved but not used; supply 0.
+     *                <p/>
+     *                <b>Data Structures:</b>
+     *                \par
+     *                \ref parameterInfo
+     *                <p/>
+     *                <b>Define Statements:</b>
+     *                \par
+     *                none
+     * @return null \n
+     *         Function failed.
+     *         <p/>
+     *         \b Errors:
+     *         \par
+     *         If the function fails, lsberrno is set to indicate the error.
+     *         <p/>
+     *         <b>Equivalent line command:</b>
+     *         \par
+     *         none
+     *         <p/>
+     *         \b Files:
+     *         \par
+     *         $LSB_CONFDIR/cluster_name/configdir/lsb.params
+     * @param names Reserved but not used; supply null.
+     * @param numUsers Reserved but not used; supply null.
+     * see none
+     */
+    public static native parameterInfo.ByReference lsb_parameterinfo(Pointer names, IntByReference numUsers, int options);
+
+    /**
+     * \page lsb_modify lsb_modify
+     * \brief  Modifies a submitted job's parameters.
+     * <p/>
+     * lsb_modify() allows for the modification of a submitted job's parameters.
+     * <p/>
+     * <b>\#include <lsf/lsbatch.h>
+     * <p/>
+     * long lsb_modify (submit.ByReference jobsubReq,
+     * submitReply.ByReference jobSubReply,
+     * long jobId)</b>
+     *
+     * @param jobId The job to be modified. If an element of a job array is to
+     *              be modified, use the array form jobID[i] where jobID is the job array name,
+     *              and i is the index value.
+     *              <p/>
+     *              <b>Data Structures:</b>
+     *              \par
+     *              \ref submit
+     *              \n \ref submitReply
+     *              <p/>
+     *              <b>Define Statements:</b>
+     *              \par
+     *              none
+     * @return long:-1 \n
+     *         Function failed.
+     *         <p/>
+     *         \b Errors:
+     *         \par
+     *         If the function fails, lsberrno is set to indicate the error.
+     *         <p/>
+     *         <b>Equivalent line command :</b>
+     *         \par
+     *         bmod
+     *         <p/>
+     *         \b Files:
+     *         \par
+     *         ${LSF_ENVDIR:-/etc}/lsf.conf
+     * @param jobSubReq Describes the requirements for job modification to the
+     * batch system. A job that does not meet these requirements is not submitted
+     * to the batch system and an error is returned.
+     * @param jobSubReply Describes the results of the job modification to the
+     * batch system.
+     * #see \ref lsb_submit
+     * #see \ref ls_info
+     * #see \ref ls_rtask
+     * #see \ref lsb_queueinfo
+     */
+    public static native long lsb_modify(submit jobSubReq, submitReply jobSubReply, long jobId);
+
+    public static native FloatByReference getCpuFactor(String string1, int int1);
+
+    /**
+     * \page lsb_suspreason lsb_suspreason
+     * \brief Explains why a job was suspended.
+     * <p/>
+     * Using the SBD, \ref lsb_suspreason explains why system-suspended and
+     * user-suspended jobs were suspended.
+     * <p/>
+     * <b>\#include <lsf/lsbatch.h>
+     * <p/>
+     * String lsb_suspreason(int reasons, int subreasons,
+     * loadIndexLog.ByReference ld)</b>
+     *
+     * @param reasons    Reasons a job suspends.
+     * @param subreasons If reasons is SUSP_LOAD_REASON, subreasons indicates
+     *                   the load indices that are out of bounds. The integer values for the load
+     *                   indices are found in lsf.h.If reasons is SUSP_RES_LIMIT, subreasons
+     *                   indicates the job's requirements for resource reservation are not satisfied.
+     *                   The integer values for the job's requirements for resource reservation are
+     *                   found in lsbatch.h.
+     *                   \n Subreasons a job suspends if reasons is SUSP_LOAD_REASON:
+     *                   - \b  R15S
+     *                   \n 15 second CPU run queue length
+     *                   - \b  R1M
+     *                   \n 1 minute CPU run queue length
+     *                   - \b  R15M
+     *                   \n 15 minute CPU run queue length
+     *                   - \b  UT
+     *                   \n 1 minute CPU utilization
+     *                   - \b  PG
+     *                   \n Paging rate
+     *                   - \b  IO
+     *                   \n Disk IO rate
+     *                   - \b LS
+     *                   \n Number of log in sessions
+     *                   - \b IT
+     *                   \n Idle time
+     *                   - \b TMP
+     *                   \n Available temporary space
+     *                   - \b SWP
+     *                   \n Available swap space
+     *                   - \b MEM
+     *                   \n Available memory
+     *                   - \b USR1
+     *                   \n USR1 is used to describe unavailable or out of bounds user defined load
+     *                   information of an external dynamic load indice on execution hosts.
+     *                   - \b USR2
+     *                   \n USR2 is used to describe unavailable or out of bounds user defined load
+     *                   information of an external dynamic load indice on execution hosts.
+     * @return null \n
+     *         The function failed. The reason code is bad.
+     *         <p/>
+     *         \b Errors:
+     *         \par
+     *         No error handling
+     *         <p/>
+     *         <b>Equivalent line commands:</b>
+     *         \par
+     *         bjobs -s
+     *         <p/>
+     *         <b>Environment Variable:</b>
+     *         \par
+     *         LSB_SUSP_REASONS
+     *         <p/>
+     *         <b>Files:</b>
+     *         \par
+     *         $LSB_CONFDIR/cluster_name/configdir/lsb.queues \n
+     *         $LSB_SHAREDIR/cluster_name/logdir/lsb.events
+     * @param ld When reasons is SUSP_LOAD_REASON, ld is used to determine the
+     * name of any external load indices. ld uses the most recent load index log
+     * in the lsb.events file.
+     * <p/>
+     * <b>Data Structures:</b>
+     * \par
+     * loadIndexLog
+     * <p/>
+     * <b>Define Statements:</b>
+     * \par
+     * \ref suspending_reasons \n
+     * \ref suspending_subreasons
+     * #see \ref lsb_pendreason
+     */
+    public static native String lsb_suspreason(int reasons, int subreasons, loadIndexLog ld);
+
+    /**
+     * \page lsb_pendreason  lsb_pendreason
+     * \brief Explains why a job is pending.
+     * <p/>
+     * Use \ref lsb_pendreason to determine why a job is pending. Each pending reason is
+     * associated with one or more hosts.
+     * <p/>
+     * <b>\#include <lsf/lsbatch.h>
+     * <p/>
+     * String lsb_pendreason (int numReasons, IntByReference rsTb,
+     * jobInfoHead.ByReference jInfoH,
+     * loadIndexLog.ByReference ld, int clusterId)</b>
+     *
+     * @param numReasons The number of reasons in the rsTb reason table.
+     * @param clusterId  MultiCluster cluster ID. If clusterId is greater than or
+     *                   equal to 0, the job is a pending remote job, and \ref lsb_pendreason checks for
+     *                   host_name\@cluster_name. If host name is needed, it should be found in
+     *                   jInfoH->remoteHosts. If the remote host name is not available, the constant
+     *                   string remoteHost is used.
+     *                   <p/>
+     *                   <b>Data Structures:</b>
+     *                   \par
+     *                   \ref jobInfoHead
+     *                   \n \ref loadIndexLog
+     *                   <p/>
+     *                   <b>Define Statements:</b>
+     *                   \par
+     *                   \ref pending_reasons
+     *                   \n \ref suspending_reasons
+     *                   \n \ref suspending_subreasons
+     * @return null \n
+     *         The function fails. The reason code is bad.
+     *         <p/>
+     *         \b Errors:
+     *         \par
+     *         If no PEND reason is found, the function fails and lsberrno is set to indicate the error.
+     *         <p/>
+     *         <b>Equivalent line command:</b>
+     *         \par
+     *         bjobs -p
+     *         <p/>
+     *         \b Files:
+     *         \par
+     *         ${LSF_ENVDIR:-/etc}/lsf.conf
+     * @param rsTb The reason table. Each entry in the table contains one of \ref pending_reasons
+     * @param jInfoH jInfoH contains job information.
+     * @param ld From \ref lsb_suspreason, when reasons is SUSP_LOAD_REASON, ld is used to
+     * determine the name of any external load indices. ld uses the most recent load
+     * index log in the lsb.events file.
+     * #see \ref lsb_geteventrec
+     */
+    public static native String lsb_pendreason(int numReasons, IntByReference rsTb, jobInfoHead jInfoH, loadIndexLog ld, int clusterId);
+
+    /**
+     * \page lsb_calendarinfo lsb_calendarinfo
+     * \brief Gets information about calendars defined in the batch system.
+     * <p/>
+     * \ref lsb_calendarinfo gets information about calendars defined in the batch system.
+     * <p/>
+     * On success, this routine returns a pointer to an array of calendarInfoEnt
+     * structures which stores the information about the returned calendars and
+     * numCalendars gives number of calendars returned. On failure null is returned
+     * and lsberrno is set to indicate the error.
+     * <p/>
+     * <b>\#include <lsf/lsbatch.h>
+     * <p/>
+     * calendarInfoEnt.ByReference lsb_calendarinfo(String[] calendars,
+     * IntByReference numCalendars, String user)</b>
+     *
+     * @return null
+     *         \n Function failed.
+     *         <p/>
+     *         \b Errors:
+     *         \par
+     *         If the function fails, lsberrno is set to indicate the error.
+     *         <p/>
+     *         <b>Equivalent line commands:</b>
+     *         \par
+     *         none
+     *         <p/>
+     *         <b>Files:</b>
+     *         \par
+     *         none
+     * @param calendars calendars is a pointer to an array of calendar names.
+     * @param numCalendars numCalendars gives the number of calendar names. If
+     * * numCalendars is 0, then information about all calendars is returned.
+     * By default, only the invokers calendars are considered.
+     * @param user Setting the user parameter will cause the given users calendars
+     * to be considered.Use the reserved user name all to get calendars of all users.
+     * <p/>
+     * <b>Data Structures:</b>
+     * \par
+     * calendarInfoEnt
+     * <p/>
+     * <b>Define Statements:</b>
+     * \par
+     * none
+     * #see \ref lsb_calendarop
+     */
+    public static native calendarInfoEnt.ByReference lsb_calendarinfo(Pointer calendars, IntByReference numCalendars, String user);
+
+    public static native int lsb_calExprOccs(String string1, int int1, int int2, String string2, PointerByReference int3);
+
+    /**
+     * \page lsb_calendarop lsb_calendarop
+     * \brief Adds, modifies or deletes a calendar.
+     * <p/>
+     * \ref lsb_calendarop is used to add, modify or delete a calendar. The oper
+     * parameter is one of CALADD, CALMOD, or CALDEL. When the operation CALADD
+     * is specified, the first element of the names array is used as the name of
+     * the calendar to add. The desc and calExpr parameters should point to the
+     * description string and the time expression list, respectively. See bcaladd()
+     * for a description of time expressions.
+     * <p/>
+     * CALMOD permits the modification of the
+     * description or time expression list associated with an existing calendar. The
+     * first name in the names array indicates the calendar to be modified. The desc
+     * and calExpr parameters can be set to the updated value or to null to
+     * indicate that the existing value should be maintained.
+     * <p/>
+     * If the operation is
+     * CALDEL then the names parameter points to an array of calendar names to be
+     * deleted. numNames gives the number of names in the array. options is
+     * reserved for the future use.
+     * <p/>
+     * <b>\#include <lsf/lsbatch.h>
+     * <p/>
+     * IntByReference lsb_calendarop(int oper, int numNames, String[] names, byte
+     * * desc, String calExpr, int options, String[] badStr)</b>
+     *
+     * @param oper     One of CALADD, CALMOD, or CALDEL. Depending on which one is
+     *                 chosen, adds, modifies, or deletes a calendar.Defined in \ref calendar_command.
+     * @param numNames The number of names in the array.
+     * @param options  Currently unused.
+     * @return int:-1
+     *         \n Function failed.
+     *         <p/>
+     *         \b Errors:
+     *         \par
+     *         If the function fails, lsberrno is set to indicate the error. If error
+     *         is related to bad calendar name or time expression, the routine returns
+     *         the name or expression in badStr.
+     *         <p/>
+     *         <b>Equivalent line commands:</b>
+     *         \par
+     *         none
+     *         <p/>
+     *         <b>Files:</b>
+     *         \par
+     *         none
+     * @param names Depending on oper, it defines the name of the calendar is going
+     * to be added, modified or deleted.
+     * @param desc The calendar's description list.
+     * @param calExpr A calendar expression.
+     * @param badStr Return from mbatchd indicating bad name or event time of calendar.
+     * <p/>
+     * <b>Data Structures:</b>
+     * \par
+     * none
+     * <p/>
+     * <b>Define Statements:</b>
+     * \par
+     * \ref calendar_command
+     * #see \ref lsb_calendarinfo
+     */
+    public static native int lsb_calendarop(int oper, int numNames, Pointer names, String desc, String calExpr, int options, String badStr);
+
+    /**
+     * \page lsb_puteventrec lsb_puteventrec
+     * \brief Puts information of an eventRec structure pointed to by logPtr
+     * into a log file.
+     * <p/>
+     * \ref lsb_puteventrec puts information of an eventRec structure pointed to by
+     * logPtr into a log file. log_fp is a pointer pointing to the log file name
+     * that could be either event a log file or job log file.
+     * <p/>
+     * See \ref lsb_geteventrec for detailed information about parameters.
+     * <p/>
+     * <b>\#include <lsf/lsbatch.h>
+     * <p/>
+     * int lsb_puteventrec(Pointer log_fp, eventRec.ByReference logPtr)</b>
+     *
+     * @return int:-1 \n
+     *         Function failed.
+     *         <p/>
+     *         \b Errors:
+     *         \par
+     *         If the function fails, lsberrno is set to indicate the error.
+     *         <p/>
+     *         <b>Equivalent line commands:</b>
+     *         \par
+     *         none
+     *         <p/>
+     *         <b>Files:</b>
+     *         \par
+     *         $LSB_SHAREDIR/cluster_name/logdir/lsb.events
+     * @param logPtr The eventRec structure pointed to by logPtr into a log file.
+     * @param log_fp A pointer pointing to the log file name that could be either
+     * event a log file or job log file.
+     * <p/>
+     * <b>Data Structures:</b>
+     * \par
+     * eventRec
+     * \n eventLog
+     * \n xFile
+     * \n jobAttrSetLog
+     * \n logSwitchLog
+     * \n dataLoggingLog
+     * \n jgrpNewLog
+     * \n jgrpCtrlLog
+     * \n jgrpStatusLog
+     * \n jobNewLog
+     * \n jobModLog
+     * \n jobStartLog
+     * \n jobStartAcceptLog
+     * \n jobExecuteLog
+     * \n jobStatusLog
+     * \n sbdJobStatusLog
+     * \n sbdUnreportedStatusLog
+     * \n jobSwitchLog
+     * \n jobMoveLog
+     * \n chkpntLog
+     * \n jobRequeueLog
+     * \n jobCleanLog
+     * \n jobExceptionLog
+     * \n sigactLog
+     * \n migLog
+     * \n signalLog
+     * \n queueCtrlLog
+     * \n hostCtrlLog
+     * \n hgCtrlLog
+     * \n mbdStartLog
+     * \n mbdDieLog
+     * \n unfulfillLog
+     * \n jobFinishLog
+     * \n loadIndexLog
+     * \n calendarLog
+     * \n jobForwardLog
+     * \n jobAcceptLog
+     * \n statusAckLog
+     * \n jobMsgLog
+     * \n jobMsgAckLog
+     * \n jobOccupyReqLog
+     * \n jobVacatedLog
+     * \n jobForceRequestLog
+     * \n jobChunkLog
+     * \n jobExternalMsgLog
+     * \n rsvRes
+     * \n rsvFinishLog
+     * \n cpuProfileLog
+     * \n jobRunRusageLog
+     * \n slaLog
+     * \n perfmonLogInfo
+     * \n perfmonLog
+     * \n taskFinishLog
+     * \n eventEOSLog
+     * \n jobResizeNotifyStartLog
+     * \n jobResizeNotifyAcceptLog
+     * \n jobResizeNotifyDoneLog
+     * \n jobResizeReleaseLog
+     * \n jobResizeCancelLog
+     * \n jobResizeLog
+     * \n jRusage
+     * <p/>
+     * <b>Define Statements:</b>
+     * \par
+     * \ref event_types
+     * \n \ref defs_lsb_XF_OP
+     * \n \ref jobgroup_controltypes
+     * \n \ref signal_action
+     * #see \ref lsb_geteventrec
+     */
+    public static native int lsb_puteventrec(Pointer logPtr, eventRec log_fp);
+
+    public static native int lsb_puteventrecRaw(Pointer pointer1, eventRec eventRec1, String string1);
+
+    /**
+     * \page lsb_geteventrec lsb_geteventrec
+     * \brief Get an event record from a log file
+     * <p/>
+     * \ref lsb_geteventrec returns an eventRec from a log file.
+     * <p/>
+     * The storage for the eventRec structure returned by \ref lsb_geteventrec will be
+     * reused by the next call.
+     * <p/>
+     * <b>\#include <lsf/lsbatch.h>
+     * <p/>
+     * eventRec.ByReference lsb_geteventrec(Pointer  log_fp,IntByReference  lineNum)</b>
+     *
+     * @return null \n
+     *         Function failed.If there are no more records, returns null and sets
+     *         lsberrno to LSBE_EOF.
+     *         <p/>
+     *         \b Errors:
+     *         \par
+     *         On failure, lsberrno is set to indicate the error.
+     *         <p/>
+     *         <b>Equivalent line commands:</b>
+     *         \par
+     *         none
+     *         <p/>
+     *         <b>Files:</b>
+     *         \par
+     *         $LSB_SHAREDIR/cluster_name/logdir/lsb.acct
+     *         \n $LSB_SHAREDIR/cluster_name/logdir/lsb.events
+     *         \n $LSB_SHAREDIR/cluster_name/logdir/lsb.rsv.ids
+     *         \n $LSB_SHAREDIR/cluster_name/logdir/lsb.rsv.state
+     * @param log_fp Either an event log file or a job log file.
+     * @param lineNum The number of the event record.
+     * <p/>
+     * <b>Data Structures:</b>
+     * \par
+     * eventRec
+     * \n eventLog
+     * \n xFile
+     * \n jobAttrSetLog
+     * \n logSwitchLog
+     * \n dataLoggingLog
+     * \n jgrpNewLog
+     * \n jgrpCtrlLog
+     * \n jgrpStatusLog
+     * \n jobNewLog
+     * \n jobModLog
+     * \n jobStartLog
+     * \n jobStartAcceptLog
+     * \n jobExecuteLog
+     * \n jobStatusLog
+     * \n sbdJobStatusLog
+     * \n sbdUnreportedStatusLog
+     * \n jobSwitchLog
+     * \n jobMoveLog
+     * \n chkpntLog
+     * \n jobRequeueLog
+     * \n jobCleanLog
+     * \n jobExceptionLog
+     * \n sigactLog
+     * \n migLog
+     * \n signalLog
+     * \n queueCtrlLog
+     * \n hostCtrlLog
+     * \n hgCtrlLog
+     * \n mbdStartLog
+     * \n mbdDieLog
+     * \n unfulfillLog
+     * \n jobFinishLog
+     * \n loadIndexLog
+     * \n calendarLog
+     * \n jobForwardLog
+     * \n jobAcceptLog
+     * \n statusAckLog
+     * \n jobMsgLog
+     * \n jobMsgAckLog
+     * \n jobOccupyReqLog
+     * \n jobVacatedLog
+     * \n jobForceRequestLog
+     * \n jobChunkLog
+     * \n jobExternalMsgLog
+     * \n rsvRes
+     * \n rsvFinishLog
+     * \n cpuProfileLog
+     * \n jobRunRusageLog
+     * \n slaLog
+     * \n perfmonLogInfo
+     * \n perfmonLog
+     * \n taskFinishLog
+     * \n eventEOSLog
+     * \n jobResizeNotifyStartLog
+     * \n jobResizeNotifyAcceptLog
+     * \n jobResizeNotifyDoneLog
+     * \n jobResizeReleaseLog
+     * \n jobResizeCancelLog
+     * \n jobResizeLog
+     * \n jRusage
+     * <p/>
+     * <b>Define Statements:</b>
+     * \par
+     * \ref event_types
+     * \n \ref defs_lsb_XF_OP
+     * \n \ref jobgroup_controltypes
+     * \n \ref signal_action
+     * #see \ref lsb_hostcontrol
+     * #see \ref lsb_movejob
+     * #see \ref lsb_pendreason
+     * #see \ref lsb_puteventrec
+     * #see \ref lsb_queuecontrol
+     * #see \ref lsb_readjobinfo
+     * #see \ref lsb_submit
+     * #see \ref lsb_suspreason
+     */
+    public static native eventRec.ByReference lsb_geteventrec(Pointer log_fp, IntByReference lineNum);
+
+    public static native eventRec.ByReference lsb_geteventrec_decrypt(Pointer pointer1, IntByReference int1);
+
+    public static native eventRec.ByReference lsb_geteventrecord(Pointer pointer1, IntByReference int1);
+
+    public static native eventRec.ByReference lsb_geteventrecordEx(Pointer pointer1, IntByReference int1, Pointer stringArray1);
+
+    public static native eventRec.ByReference lsb_getnewjob_from_string(String string1);
+
+    public static native eventInfoEnt.ByReference lsb_eventinfo(Pointer stringArray1, IntByReference int1, String string1);
+
+    /**
+     * \page lsb_sharedresourceinfo lsb_sharedresourceinfo
+     * \brief Returns the requested shared resource information in dynamic values.
+     * <p/>
+     * \ref lsb_sharedresourceinfo returns the requested shared resource information in
+     * dynamic values. The result of this call is a chained data structure as
+     * defined in <lsf/lsbatch.h>, which contains requested information.
+     * <p/>
+     * <b>\#include <lsf/lsbatch.h>
+     * <p/>
+     * LSB_SHARED_RESOURCE_INFO_T.ByReference lsb_sharedresourceinfo(
+     * String[] resources,
+     * IntByReference numResources,
+     * String hostName, int options)</b>
+     *
+     * @param options options is reserved for future use. Currently, it should be set to 0.
+     *                <p/>
+     *                <b>Data Structures:</b>
+     *                \par
+     *                lsbSharedResourceInfo
+     *                \n lsbSharedResourceInstance
+     *                <p/>
+     *                <b>Define Statements:</b>
+     *                \par
+     *                none
+     * @return null \n
+     *         Function failed.
+     *         <p/>
+     *         \b Errors:
+     *         \par
+     *         If the function fails, lsberrno is set to indicate the error.
+     *         <p/>
+     *         <b>Equivalent line commands:</b>
+     *         \par
+     *         none
+     *         <p/>
+     *         <b>Files:</b>
+     *         \par
+     *         $LSF_CONFDIR/lsf.shared
+     *         \n $LSF_CONFDIR/lsf.cluster.cluster_name
+     * @param resources resources is an null terminated string array storing
+     * requesting resource names.Setting resources to point to null returns all
+     * shared resources.
+     * @param numResources numResources is an input/output parameter. On input
+     * it indicates how many resources are requested. Value 0 means requesting
+     * all shared resources. On return it contains qualified resource number.
+     * @param hostName hostName is a string containing a host name. Only shared resource
+     * available on the specified host will be returned. If hostName is a null,
+     * shared resource available on all hosts will be returned.
+     * #see \ref ls_sharedresourceinfo
+     */
+    public static native Pointer lsb_sharedresourceinfo(Pointer resources, IntByReference numResources, String hostName, int options);
+
+    /**
+     * \page lsb_geteventrecbyline lsb_geteventrecbyline
+     * Parse an event line and put the result in an event record structure.
+     * The \ref lsb_geteventrecbyline function parses an event line and puts the result
+     * in an event record structure.
+     * <p/>
+     * If the line to be parsed is a comment line, \ref lsb_geteventrecbyline sets errno to
+     * bad event format and logs an error.
+     * <p/>
+     * <b>\#include <lsf/lsbatch.h>
+     * <p/>
+     * int lsb_geteventrecbyline(String line, eventRec.ByReference logRec)</b>
+     *
+     * @return int:-1
+     *         \n Function failed and lserrno was set.
+     *         <p/>
+     *         \b Errors:
+     *         \par
+     *         none
+     *         <p/>
+     *         <b>Equivalent line commands:</b>
+     *         \par
+     *         none
+     *         <p/>
+     *         <b>Files:</b>
+     *         \par
+     *         none
+     * @param line
+     * Buffer containing a line of event text string
+     * @param logRec
+     * Pointer to an eventRec structure
+     * <p/>
+     * <b>Data Structures:</b>
+     * \par
+     * eventRec
+     * \n eventLog
+     * \n xFile
+     * \n jobAttrSetLog
+     * \n logSwitchLog
+     * \n dataLoggingLog
+     * \n jgrpNewLog
+     * \n jgrpCtrlLog
+     * \n jgrpStatusLog
+     * \n jobNewLog
+     * \n jobModLog
+     * \n jobStartLog
+     * \n jobStartAcceptLog
+     * \n jobExecuteLog
+     * \n jobStatusLog
+     * \n sbdJobStatusLog
+     * \n sbdUnreportedStatusLog
+     * \n jobSwitchLog
+     * \n jobMoveLog
+     * \n chkpntLog
+     * \n jobRequeueLog
+     * \n jobCleanLog
+     * \n jobExceptionLog
+     * \n sigactLog
+     * \n migLog
+     * \n signalLog
+     * \n queueCtrlLog
+     * \n hostCtrlLog
+     * \n hgCtrlLog
+     * \n mbdStartLog
+     * \n mbdDieLog
+     * \n unfulfillLog
+     * \n jobFinishLog
+     * \n loadIndexLog
+     * \n calendarLog
+     * \n jobForwardLog
+     * \n jobAcceptLog
+     * \n statusAckLog
+     * \n jobMsgLog
+     * \n jobMsgAckLog
+     * \n jobOccupyReqLog
+     * \n jobVacatedLog
+     * \n jobForceRequestLog
+     * \n jobChunkLog
+     * \n jobExternalMsgLog
+     * \n rsvRes
+     * \n rsvFinishLog
+     * \n cpuProfileLog
+     * \n jobRunRusageLog
+     * \n slaLog
+     * \n perfmonLogInfo
+     * \n perfmonLog
+     * \n taskFinishLog
+     * \n eventEOSLog
+     * \n jobResizeNotifyStartLog
+     * \n jobResizeNotifyAcceptLog
+     * \n jobResizeNotifyDoneLog
+     * \n jobResizeReleaseLog
+     * \n jobResizeCancelLog
+     * \n jobResizeLog
+     * \n jRusage
+     * <p/>
+     * <b>Define Statements:</b>
+     * \par
+     * none
+     * <p/>
+     * <b>Pre-Conditions:</b>
+     * \par
+     * The event record structure must have been initialized outside the
+     * \ref lsb_geteventrecbyline function.
+     * see none
+     */
+
+    public static native int lsb_geteventrecbyline(String line, eventRec logRec);
+/* Retain lsb_connect for now */
+
+    public static int lsb_connect(int a) {
+        return lsb_rcvconnect();
+    }
+
+    public static native int lsb_rcvconnect();
+
+    public static native int lsb_sndmsg(lsbMsgHdr lsbMsgHdr1, String string1, int int1);
+
+    public static native int lsb_rcvmsg(lsbMsgHdr lsbMsgHdr1, Pointer stringArray1, int int1);
+
+    /**
+     * \page  lsb_runjob lsb_runjob
+     * Starts a batch job immediately on a set of specified host().
+     * \ref lsb_runjob starts a batch job immediately on a set of specified host().
+     * The job must have been submitted and is in PEND or FINISHED status. Only
+     * the LSF administrator or the owner of the job can start the job. If the
+     * options is set to RUNJOB_OPT_NOSTOP, then the job will not be suspended by
+     * the queue's RUNWINDOW,loadStop and STOP_COND and the hosts' RUNWINDOW and
+     * loadStop conditions. By default, these conditions apply to the job as do
+     * to other normal jobs.
+     * <p/>
+     * Any program using this API must be setuid to root
+     * if LSF_AUTH is not defined in the lsf.conf file.
+     * <p/>
+     * <b>\#include <lsf/lsbatch.h>
+     * <p/>
+     * int lsb_runjob(runJobRequest.ByReference runJobRequest)</b>
+     *
+     * @param runJobRequest The job-starting request.
+     *                      <p/>
+     *                      <b>Data Structures:</b>
+     *                      \par
+     *                      runJobRequest
+     *                      <p/>
+     *                      <b>Define Statements:</b>
+     *                      \par
+     *                      \ref runjob_option
+     * @return int:-1 \n
+     *         Function failed.
+     *         <p/>
+     *         \b Errors:
+     *         \par
+     *         If the function fails, lsberrno is set to indicate the error.
+     *         <p/>
+     *         <b>Equivalent line commands:</b>
+     *         \par
+     *         brun
+     *         <p/>
+     *         \b Files:
+     *         \par
+     *         ${LSF_ENVDIR:-/etc}/lsf.conf
+     * see none
+     */
+    public static native int lsb_runjob(runJobRequest runJobRequest);
+
+/* API for job group */
+
+    public static native int lsb_addjgrp(jgrpAdd jgrpAdd1, Pointer jgrpReply1);
+
+    public static native int lsb_modjgrp(jgrpMod jgrpMod1, Pointer jgrpReply1);
+
+    public static native int lsb_holdjgrp(String string1, int int1, Pointer jgrpReply1);
+
+    public static native int lsb_reljgrp(String string1, int int1, Pointer jgrpReply1);
+
+    public static native int lsb_deljgrp(String string1, int int1, Pointer jgrpReply1);
+
+    public static native int lsb_deljgrp_ext(jgrpCtrl jgrpCtrl1, Pointer jgrpReply1);
+
+    public static native jgrp.ByReference lsb_listjgrp(IntByReference int1);
+
+    public static native serviceClass.ByReference lsb_serviceClassInfo(IntByReference int1);
+
+/* API for Application Encapsulation */
+
+    public static native appInfoEnt.ByReference lsb_appInfo(IntByReference int1);
+
+    public static native void lsb_freeAppInfoEnts(int int1, appInfoEnt appInfoEnt1);
+
+/* routine to convert the job id to string */
+
+    public static native String lsb_jobid2str(long long1);
+
+    public static native String lsb_jobid2str_r(long long1, byte[] byte1);
+
+    public static native String lsb_jobidinstr(long long1);
+/* routine to compose and decompose 64bit jobId */
+
+    public static native void jobId32To64(LongByReference long1, int int1, int int2);
+
+    public static native void jobId64To32(long long1, IntByReference int1, IntByReference int2);
+/* API for job attribute operations */
+
+    public static native int lsb_setjobattr(int int1, jobAttrInfoEnt jobAttrInfoEnt1);
+
+/* API for remote task execution */
+
+    public static native long lsb_rexecv(int int1, Pointer stringArray1, Pointer stringArray2, IntByReference int2, int int3);
+
+
+    public static interface lsb_catchCallback extends Callback {
+        int invoke(Pointer pointer);
+    }
+
+    public static native int lsb_catch(String string1, lsb_catchCallback callback);
+
+    public static native void lsb_throw(String string1, Pointer pointer1);
+
+/* API for job external message */
+
+    /**
+     *  \page lsb_postjobmsg lsb_postjobmsg
+     *  \brief Sends messages and data posted to a job.
+     *
+     *  Use \ref lsb_postjobmsg to post a message and data to a job, open a TCP
+     *  connection, and transfer attached message and data from the mbatchd. Use
+     *  \ref lsb_readjobmsg to display messages and copy data files posted by
+     *  \ref lsb_postjobmsg.
+     *
+     *  While you can post multiple messages and attached data files to a job,
+     *  you must call \ref lsb_postjobmsg for each message and attached data file
+     *  you want to post. By default, \ref lsb_postjobmsg posts a message to position
+     *  0 of the message index (msgId) (see PARAMETERS) of the specified job.
+     *  To post additional messages to a job, call \ref lsb_postjobmsg and increment
+     *  the message index.
+     *
+     *  \ref lsb_readjobmsg reads posted job messages by their
+     *  position in the message index.
+     *
+     *  If a data file is attached to a message and the flag EXT_ATTA_POST is set,
+     *  use the JOB_ATTA_DIR parameter in lsb.params(5) to specify the directory
+     *  where attachment data fies are saved. The directory must have at least 1MB
+     *  of free space.The mbatchd checks for available space in the job attachment
+     *  directory before transferring the file.
+     *
+     *  Use the MAX_JOB_ATTA_SIZE parameter in lsb.params(5) to set a maximum size
+     *  for job message attachments.
+     *
+     *  Users can only send messages and data from their own jobs. Root and LSF
+     *  administrators can also send messages of jobs submtted by other users, but
+     *  they cannot attach data files to jobs owned by other users.
+     *
+     *  You can post messages and data to a job until it is cleaned from the system.
+     *  You cannot send messages and data to finished or exited jobs.
+     *
+     *  <b>\#include <lsf/lsbatch.h> \n
+     *     \#include <time.h>
+     *
+     *  int lsb_postjobmsg(jobExternalMsgReq.ByReference jobExternalMsg,
+     *                    String filename)</b>
+     *
+     *  @param jobExternalMsg This structure contains the information required to
+     *  define an external message of a job.
+     *  @param filename Name of attached data file. If no file is attached, use null.
+     *
+     *  <b>Data Structures:</b>
+     *  \par
+     *  \ref jobExternalMsgReq
+     *
+     *  <b>Define Statements:</b>
+     *  \par
+     *  \ref external_msg_post
+     *
+     *  @return int:value \n
+     *  The successful function returns a socket number.
+     * return int:0 \n
+     *  The EXT_ATTA_POST bit of options is not set or there is no attached data.
+     *  return int:-1 \n
+     *  The function failed.
+     *
+     *  \b Errors:
+     *  \par
+     *  If the function fails, lserrno is set to indicate the error.
+     *
+     *  <b>Equivalent line command:</b>
+     *  \par
+     *  bpost
+     *
+     *  \b Files:
+     *  \par
+     *  $LSB_CONFDIR/cluster_name/configdir/lsb.params
+     *  \n $JOB_ATTA_DIR
+     *  \n $LSB_SHAREDIR/info
+     *
+     * #see \ref lsb_readjobmsg
+     *
+     */
+
+    public static native int lsb_postjobmsg(jobExternalMsgReq jobExternalMsg, String filename);
+    /**
+     *  \page lsb_readjobmsg lsb_readjobmsg
+     *  \brief Reads messages and data posted to a job.
+     *
+     *  Use \ref lsb_readjobmsg to open a TCP connection, receive attached messages and
+     *  data from the mbatchd, and display the messages posted by \ref lsb_postjobmsg.
+     *
+     *  By default, \ref lsb_readjobmsg displays the message "no description" or the
+     *  message at index position 0 of the specified job. To read other messages,
+     *  choose another index position. The index is populated by \ref lsb_postjobmsg.
+     *
+     *  If a data file is attached to a message and the flag EXT_ATTA_READ is set,
+     *  \ref lsb_readjobmsg gets the message and copies its data file to the default
+     *  directory JOB_ATTA_DIR, overwriting the specified file if it already exists.
+     *  If there is no file attached, the system reports an error.
+     *
+     *  Users can only read messages and data from their own jobs. Root and LSF
+     *  administrators can also read messages of jobs submtted by other users,
+     *  but they cannot read data files attached to jobs owned by other users.
+     *
+     *  You can read messages and data from a job until it is cleaned from the
+     *  system. You cannot read messages and data from done or exited jobs.
+     *
+     *  <b>\#include <lsf/lsbatch.h> \n
+     *  \#include <time.h> \n
+     *  int lsb_readjobmsg(jobExternalMsgReq.ByReference jobExternalMsg,
+     *          jobExternalMsgReply.ByReference jobExternalMsgReply)</b>
+     *
+     *  @param jobExternalMsg the information required to define an external
+     *  message of a job.
+     *  @param jobExternalMsgReply the information required to define an
+     *  external message reply.
+     *
+     *  <b>Data Structures:</b>
+     *  \par
+     *  jobExternalMsgReq
+     *  \n jobExternalMsgReply
+     *
+     *  <b>Define Statements:</b>
+     *  \par
+     *  \ref external_msg_processing
+     *  \n \ref ext_data_status
+     *
+     *  @return int:value \n
+     *  The successful function returns a socket number.
+     *  return int:0 \n
+     *  The EXT_ATTA_READ bit of options is not set or there is no
+     *  attached data.
+     *  return int:-1 \n
+     *  The function failed.
+     *
+     *  \b Errors:
+     *  \par
+     *  If the function fails, lserrno is set to indicate the error.
+     *
+     *  <b>Equivalent line commands:</b>
+     *  \par
+     *  bread
+     *
+     *  <b>Files:</b>
+     *  \par
+     *  $LSB_CONFDIR/cluster_name/configdir/lsb.params
+     *  \n $JOB_ATTA_DIR
+     *  \n $LSB_SHAREDIR/info
+     * #see \ref lsb_postjobmsg
+     */
+
+    public static native int lsb_readjobmsg(jobExternalMsgReq jobExternalMsg, jobExternalMsgReply jobExternalMsgReply);
+
+/* API for symphony job information update in bulk mode */
+
+    public static native int lsb_bulkJobInfoUpdate(symJobStatusUpdateReqArray symJobStatusUpdateReqArray1, symJobStatusUpdateReplyArray symJobStatusUpdateReplyArray1);
+
+/* API for advance reservation */
+
+    /**
+     * \page lsb_addreservation lsb_addreservation
+     * \brief Makes an advance reservation.
+     * <p/>
+     * Use \ref lsb_addreservation to send a reservation request to mbatchd. If
+     * mbatchd grants the reservation, it issues the reservation ID. If mbatchd
+     * rejects the request, it issues null as the reservation ID.
+     * <p/>
+     * <b>\#include <lsf/lsbatch.h>
+     * <p/>
+     * int lsb_addreservation (addRsvRequest.ByReference request, String rsvId)</b>
+     *
+     * @return int:-1 \n
+     *         The reservation failed.
+     *         <p/>
+     *         \b Errors:
+     *         \par
+     *         On failure, lsberrno is set to indicate the error.
+     *         <p/>
+     *         <b>Equivalent line commands:</b>
+     *         \par
+     *         brsvadd
+     *         <p/>
+     *         <b>Files:</b>
+     *         \par
+     *         none
+     * @param request The reservation request
+     * @param rsvId Reservation ID returned from mbatchd. If the reservation
+     * fails, this is null. The
+     * memory for rsvid is allocated by the caller.
+     * <p/>
+     * <b>Data Structures:</b>
+     * \par
+     * addRsvRequest
+     * \n _rsvExecCmd_t
+     * \n _rsvExecEvent_t
+     * <p/>
+     * <b>Define Statements:</b>
+     * \par
+     * \ref reservation_option
+     * #see \ref lsb_removereservation
+     * #see \ref lsb_modreservation
+     * #see \ref lsb_reservationinfo
+     */
+    public static native int lsb_addreservation(addRsvRequest request, String rsvId);
+
+    /**
+     * \page lsb_removereservation lsb_removereservation
+     * \brief Removes a reservation.
+     * <p/>
+     * Use \ref lsb_removereservation to remove a reservation. mbatchd removes the
+     * reservation with the specified reservation ID.
+     * <p/>
+     * <b>\#include <lsf/lsbatch.h>
+     * <p/>
+     * int lsb_removereservation(String rsvId)</b>
+     *
+     * @return int:-1 \n
+     *         The reservation removal failed.
+     *         <p/>
+     *         \b Errors:
+     *         \par
+     *         On failure, lsberrno is set to indicate the error.
+     *         <p/>
+     *         <b>Equivalent line commands:</b>
+     *         \par
+     *         brsvdel
+     *         <p/>
+     *         <b>Files:</b>
+     *         \par
+     *         none
+     * @param rsvId Reservation ID of the reservation that you wish to remove.
+     * <p/>
+     * <b>Data Structures:</b>
+     * \par
+     * none
+     * <p/>
+     * <b>Define Statements:</b>
+     * \par
+     * none
+     * #see \ref lsb_addreservation
+     * #see \ref lsb_modreservation
+     * #see \ref lsb_reservationinfo
+     */
+    public static native int lsb_removereservation(String rsvId);
+
+    /**
+     * \page lsb_reservationinfo lsb_reservationinfo
+     * \brief Retrieve reservation information to display active advance reservations.
+     * <p/>
+     * Use \ref lsb_reservationinfo to retrieve reservation information from mbatchd.
+     * This function allocates memory that the caller should free.
+     * <p/>
+     * If the \ref lsb_reservationinfo function succeeds, it returns the reservation
+     * records pertaining to a particular reservation ID (rsvId) as an array of
+     * rsvInfoEnt structs.
+     * <p/>
+     * If rsvId is null, all reservation information will be returned. If a
+     * particular rsvId  is specified:
+     * \li If found, the reservation record pertaining to a particular rsvId is
+     * returned
+     * \li If not found, the number of reservation records is set to zero and
+     * the lsberrno  is set appropiately
+     * <p/>
+     * <b>\#include <lsf/lsbatch.h>
+     * <p/>
+     * rsvInfoEnt.ByReference lsb_reservationinfo(String rsvId, IntByReference numEnts,
+     * int options)</b>
+     *
+     * @param options The parameter options is currently ignored.
+     *                <p/>
+     *                <b>Data Structures:</b>
+     *                \par
+     *                rsvInfoEnt
+     *                \n hostRsvInfoEnt
+     *                <p/>
+     *                <b>Define Statements:</b>
+     *                \par
+     *                none
+     * @return null
+     *         \n Function failed.
+     *         <p/>
+     *         \b Errors:
+     *         \par
+     *         On failure, lsberrno is set to indicate the error.
+     *         <p/>
+     *         <b>Equivalent line commands:</b>
+     *         \par
+     *         brsvs
+     *         <p/>
+     *         <b>Files:</b>
+     *         \par
+     *         none
+     * @param rsvId Reservation ID of the requested reservation.
+     * @param numEnts Number of reservation entries that mbatchd returns.
+     * #see \ref lsb_addreservation
+     * #see \ref lsb_modreservation
+     * #see \ref lsb_removereservation
+     */
+
+    public static native rsvInfoEnt.ByReference lsb_reservationinfo(String rsvId, IntByReference numEnts, int options);
+
+    public static native int lsb_freeRsvExecCmd(Pointer _rsvExecCmd_tArray1);
+
+    public static native _rsvExecCmd_t.ByReference lsb_dupRsvExecCmd(_rsvExecCmd_t _rsvExecCmd_t1);
+
+    public static native int lsb_parseRsvExecOption(String string1, Pointer _rsvExecCmd_tArray1);
+
+    /**
+     * \page lsb_modreservation lsb_modreservation
+     * \brief Modifies an advance reservation.
+     * <p/>
+     * Use \ref lsb_modreservation to modify an advance reservation. mbatchd receives
+     * the modification request and modifies the reservation with the specified
+     * reservation ID.
+     * <p/>
+     * <b>\#include <lsf/lsbatch.h>
+     * <p/>
+     * int lsb_modreservation(modRsvRequest.ByReference request)</b>
+     *
+     * @return int:-1 \n
+     *         The reservation modification failed.
+     *         <p/>
+     *         \b Errors:
+     *         \par
+     *         On failure, lsberrno is set to indicate the error.
+     *         <p/>
+     *         <b>Equivalent line command:</b>
+     *         \par
+     *         brsvmod
+     *         <p/>
+     *         \b Files:
+     *         \par
+     *         none
+     * @param request modify reservation request.
+     * <p/>
+     * <b>Data Structures:</b>
+     * \par
+     * modRsvRequest
+     * \n addRsvRequest
+     * \n _rsvExecCmd_t
+     * <p/>
+     * <b>Define Statements:</b>
+     * \par
+     * none
+     * #see \ref lsb_addreservation
+     * #see \ref lsb_removereservation
+     * #see \ref lsb_reservationinfo
+     */
+
+    public static native int lsb_modreservation(modRsvRequest request);
+
+/* routines for sorted integer list */
+    /*
+    sortIntList.ByReference  initSortIntList(int);
+    int insertSortIntList(sortIntList.ByReference , int);
+    sortIntList.ByReference  getNextSortIntList(sortIntList.ByReference , sortIntList.ByReference , IntByReference );
+    void freeSortIntList(sortIntList.ByReference );
+    int getMinSortIntList(sortIntList.ByReference , IntByReference );
+    int getMaxSortIntList(sortIntList.ByReference , IntByReference );
+    int getTotalSortIntList(sortIntList.ByReference );
+
+    int updateJobIdIndexFile (String string1, String string1, int);
+    */
+
+/* Structures and routine for obtaining subset of info about jobs
+*  This is being used by Maui integration.
+ */
+
+    public static class jobExtschInfoReq extends Structure {
+        public static class ByReference extends jobExtschInfoReq implements Structure.ByReference {}
+        public static class ByValue extends jobExtschInfoReq implements Structure.ByValue {}
+        public jobExtschInfoReq() {}
+        public jobExtschInfoReq(Pointer p) { super(p); read(); }
+
+        public int qCnt;
+        public Pointer queues;
+    }
+
+
+
+    public static class jobExtschInfo extends Structure {
+        public static class ByReference extends jobExtschInfo implements Structure.ByReference {}
+        public static class ByValue extends jobExtschInfo implements Structure.ByValue {}
+        public jobExtschInfo() {}
+        public jobExtschInfo(Pointer p) { super(p); read(); }
+
+        public long jobId;
+        public int status;
+        public NativeLong jRusageUpdateTime;
+        public LibLsf.jRusage runRusage;
+    }
+
+
+
+    public static class jobExtschInfoReply extends Structure {
+        public static class ByReference extends jobExtschInfoReply implements Structure.ByReference {}
+        public static class ByValue extends jobExtschInfoReply implements Structure.ByValue {}
+        public jobExtschInfoReply() {}
+        public jobExtschInfoReply(Pointer p) { super(p); read(); }
+
+        public int jobCnt;
+        public PointerByReference jobs;
+    }
+
+
+
+    public static native int getjobinfo4queues(jobExtschInfoReq jobExtschInfoReq1, jobExtschInfoReply jobExtschInfoReply1);
+
+    public static native void free_jobExtschInfoReply(jobExtschInfoReply jobExtschInfoReply1);
+
+    public static native void free_jobExtschInfoReq(jobExtschInfoReq jobExtschInfoReq1);
+
+/* For RFC 725 */
+
+    public static native String longer_strcpy(String dest, String src);
+
+/* Structures and API for job diagnostics.  These are applicable only if
+*  CONDENSE_PENDING_REASONS is enabled in lsb.params.
+ */
+
+    public static class diagnoseJobReq extends Structure {
+        public static class ByReference extends diagnoseJobReq implements Structure.ByReference {}
+        public static class ByValue extends diagnoseJobReq implements Structure.ByValue {}
+        public diagnoseJobReq() {}
+        public diagnoseJobReq(Pointer p) { super(p); read(); }
+
+        public int jobCnt;
+        public LongByReference jobId;
+    }
+
+
+
+    public static native int lsb_diagnosejob(diagnoseJobReq diagnoseJobReq1);
+
+    public static final int SIM_STATUS_RUN = 0x01;
+    public static final int SIM_STATUS_SUSPEND = 0x02;
+
+/* simulator status reply
+ */
+
+    public static class simStatusReply extends Structure {
+        public static class ByReference extends simStatusReply implements Structure.ByReference {}
+        public static class ByValue extends simStatusReply implements Structure.ByValue {}
+        public simStatusReply() {}
+        public simStatusReply(Pointer p) { super(p); read(); }
+
+        public int simStatus;
+        public NativeLong curTime;
+    }
+
+
+
+    public static native simStatusReply.ByReference lsb_simstatus();
+
+    public static native void free_simStatusReply(simStatusReply simStatusReply1);
+
+/* batch command options flag for lease */
+    public static final int LSB_HOST_OPTION_EXPORT = 0x1;
+/* bhosts -x option */
+    public static final int LSB_HOST_OPTION_EXCEPT = 0x2;
+/* retrieve hosts that belong to batch partition */
+    public static final int LSB_HOST_OPTION_BATCH = 0x4;
+
+
+/* Display condensed host output */
+    public static final int LSB_HOST_OPTION_CONDENSED = 0x08;
+
+/* error codes, structures and routines for syntax check of RMS external scheduler options */
+
+/*  non-rms option shown up in RMS[] */
+    public static final int RMS_NON_RMS_OPTIONS_ERR = (-1);
+
+/*  nodes and ptile co-exist */
+    public static final int RMS_NODE_PTILE_ERR = (-2);
+
+/*  rails and railmask co-exist */
+    public static final int RMS_RAIL_RAILMASK_ERR = (-3);
+
+/*  nodes is out of range 1..LSB_RMS_MAXNUMNODES */
+    public static final int RMS_NODES_OUT_BOUND_ERR = (-4);
+
+/*  ptile is out of range 1..LSB_RMS_MAXPTILE */
+    public static final int RMS_PTILE_OUT_BOUND_ERR = (-5);
+
+/*  rails is out of range 1..LSB_RMS_MAXNUMRAILS */
+    public static final int RMS_RAIL_OUT_BOUND_ERR = (-6);
+
+/*  railmask syntax error */
+    public static final int RMS_RAILMASK_OUT_BOUND_ERR = (-7);
+
+/*  nodes syntax error */
+    public static final int RMS_NODES_SYNTAX_ERR = (-8);
+
+/*  ptile syntax error */
+    public static final int RMS_PTILE_SYNTAX_ERR = (-9);
+
+/*  rails syntax error */
+    public static final int RMS_RAIL_SYNTAX_ERR = (-10);
+
+/*  railmask syntax error */
+    public static final int RMS_RAILMASK_SYNTAX_ERR = (-11);
+
+/*  base syntax error */
+    public static final int RMS_BASE_SYNTAX_ERR = (-12);
+
+/*  base string too NativeLong*/
+    public static final int RMS_BASE_TOO_LONG = (-13);
+
+/*  >=1 allocation types are specified */
+    public static final int RMS_TOO_MANY_ALLOCTYPE_ERR = (-14);
+
+/*  =1 allocation types are specified */
+    public static final int RMS_NO_LSF_EXTSCHED_Y_ERR = (-15);
+
+/*  error reading env from lsf.conf inside syntax check */
+    public static final int RMS_READ_ENV_ERR = (-20);
+
+/*  memory allocation problems inside syntax check function */
+    public static final int RMS_MEM_ALLOC_ERR = (-21);
+
+/*  [] mis-matched in RMS[] */
+    public static final int RMS_BRACKETS_MISMATCH_ERR = (-22);
+
+    public static interface rmsAllocType_t {
+          public static final int RMS_ALLOC_TYPE_UNKNOWN = 0;
+          public static final int RMS_ALLOC_TYPE_SLOAD = 1;
+          public static final int RMS_ALLOC_TYPE_SNODE = 2;
+          public static final int RMS_ALLOC_TYPE_MCONT = 3;
+    }
+
+
+
+    public static interface rmsTopology_t {
+          public static final int RMS_TOPOLOGY_UNKNOWN = 0;
+          public static final int RMS_TOPOLOGY_PTILE = 1;
+          public static final int RMS_TOPOLOGY_NODES = 2;
+    }
+
+
+
+    public static interface rmsFlags_t {
+          public static final int RMS_FLAGS_UNKNOWN = 0;
+          public static final int RMS_FLAGS_RAILS = 1;
+          public static final int RMS_FLAGS_RAILMASK = 2;
+    }
+
+
+
+    public static class rmsextschedoption extends Structure {
+        public static class ByReference extends rmsextschedoption implements Structure.ByReference {}
+        public static class ByValue extends rmsextschedoption implements Structure.ByValue {}
+        public rmsextschedoption() {}
+        public rmsextschedoption(Pointer p) { super(p); read(); }
+
+        public /*rmsAllocType_t*/ int alloc_type;
+        public /*rmsTopology_t*/ int topology;
+        public int topology_value;
+        public int set_base;
+        public byte[] base = new byte[LibLsf.MAXHOSTNAMELEN];
+        public /*rmsFlags_t*/ int flags;
+        public int flags_value;
+    }
+
+
+
+    public static native int parseRmsOptions(String string1, rmsextschedoption rmsextschedoption1, LibLsf.config_param config_param1);
+
+/* Stream interface.
+*  By default the stream lsb.stream is located in a subdirectory
+*  stream of the cluster working directory i.e.:
+*  work/<clustername>/logdir/stream and the size of
+*  lsb.stream is 1024MB
+ */
+    public static final int MBD_DEF_STREAM_SIZE = (1024 * 1024 * 1024);
+
+/* default maximum number of backup stream.utc file */
+    public static final int DEF_MAX_STREAM_FILE_NUMBER = 10;
+
+    /**
+     * \brief  Stream interface.
+     */
+    public static class lsbStream extends Structure {
+        public static class ByReference extends lsbStream implements Structure.ByReference {}
+        public static class ByValue extends lsbStream implements Structure.ByValue {}
+        public lsbStream() {}
+        public lsbStream(Pointer p) { super(p); read(); }
+
+        public static interface trsFunc extends Callback {
+            int invoke(String string1);
+        }
+
+        /**
+         * < Pointer to full path to the stream file
+         */
+        public String streamFile;
+
+        /**
+         * < Max size of the stream file
+         */
+        public int maxStreamSize;
+
+        /**
+         * < Max number of backup stream files
+         */
+        public int maxStreamFileNum;
+
+        /**
+         * < Set to 1 to enable trace of the stream
+         */
+        public int trace;
+
+        /**
+         * < Pointer to a function that the library invokes, passing a trace buffer.
+         */
+        public trsFunc trs;
+    }
+
+
+
+     /**//*
+     * \page lsb_openstream  lsb_openstream
+     * \brief Open and create an lsb_stream file.
+     * <p/>
+     * \ref lsb_openstream opens the streamFile .
+     * <p/>
+     * This API function is inside liblsbstream.so.
+     * <p/>
+     * <b>\#include <lsf/lsbatch.h>
+     * <p/>
+     * int lsb_openstream(lsbStream.ByReference params)</b>
+     *
+     * @return int:-1 or null \n
+     *         The function failed.
+     *         <p/>
+     *         \b Errors:
+     *         \par
+     *         If the function fails, lsberrno is set to indicate the error.
+     *         <p/>
+     *         <b>Equivalent line command:</b>
+     *         \par
+     *         none
+     *         <p/>
+     *         <b>Files:</b>
+     *         \par
+     *         $LSB_CONFDIR/cluster_name/configdir/lsb.params
+     * @param params Parameters.
+     * <p/>
+     * <b>Data Structures:</b>
+     * \par
+     * \ref lsbStream
+     * <p/>
+     * <b>Define Statements:</b>
+     * \par
+     * none
+     * #see \ref lsb_closestream
+     * #see \ref lsb_readstreamline
+     * #see \ref lsb_writestream
+     * #see \ref lsb_readstream
+     * #see \ref lsb_streamversion
+     */
+    // NOTE: Not in libbat
+    //public static native int lsb_openstream(lsbStream params);
+
+     /**//*
+     * \page lsb_closestream lsb_closestream
+     * \brief Close an lsb_stream file.
+     * <p/>
+     * \ref lsb_closestream closes the streamFile.
+     * <p/>
+     * This API function is inside liblsbstream.so.
+     * <p/>
+     * <b>\#include <lsf/lsbatch.h>
+     * <p/>
+     * int lsb_closestream(String config)</b>
+     *
+     * @return int:-1 \n
+     *         The function failed.
+     *         <p/>
+     *         \b Errors:
+     *         \par
+     *         If the function fails, lsberrno is set to indicate the error.
+     *         <p/>
+     *         <b>Equivalent line commands:</b>
+     *         \par
+     *         none
+     *         <p/>
+     *         <b>Files:</b>
+     *         \par
+     *         $LSB_CONFDIR/cluster_name/configdir/lsb.params
+     * @param config Pointer to the handle of the stream file.
+     * <p/>
+     * <b>Data Structures:</b>
+     * \par
+     * none
+     * <p/>
+     * <b>Define Statements:</b>
+     * \par
+     * none
+     * #see \ref lsb_openstream
+     * #see \ref lsb_readstreamline
+     * #see \ref lsb_writestream
+     * #see \ref lsb_readstream
+     * #see \ref lsb_streamversion
+     */
+    // NOTE: Not in libbat
+    //public static native int lsb_closestream(String config);
+
+     /**//*
+     * \page lsb_streamversion lsb_streamversion
+     * \brief Version of the current event type supported by mbatchd.
+     * <p/>
+     * \ref lsb_streamversion returns the event version number of mbatchd, which is the
+     * version of the events to be written to the stream file. This API function
+     * is inside liblsbstream.so.
+     * <p/>
+     * <b>\#include <lsf/lsbatch.h>
+     * <p/>
+     * String  lsb_streamversion()</b>
+     *
+     * param void \n
+     *             <p/>
+     *             <b>Data Structures:</b>
+     *             \par
+     *             none
+     *             <p/>
+     *             <b>Define Statements:</b>
+     *             \par
+     *             none
+     * @return null
+     *         \n Function failed.
+     *         <p/>
+     *         \b Errors:
+     *         \par
+     *         If the function fails, lsberrno is set to indicate the error.
+     *         <p/>
+     *         <b>Equivalent line commands:</b>
+     *         \par
+     *         none
+     *         <p/>
+     *         <b>Files:</b>
+     *         \par
+     *         $LSB_CONFDIR/cluster_name/configdir/lsb.params
+     * #see \ref lsb_closestream
+     * #see \ref lsb_geteventrec
+     * #see \ref lsb_openstream
+     * #see \ref lsb_puteventrec
+     * #see \ref lsb_readstreamline
+     * #see \ref lsb_writestream
+     * #see \ref lsb_readstream
+     */
+    // NOTE: Not in libbat
+    //public static native String lsb_streamversion();
+
+     /**//*
+     * \page lsb_writestream lsb_writestream
+     * \brief Writes a current version eventRec structure into the lsb_stream file.
+     * <p/>
+     * \ref lsb_writestream writes an eventrRec to the open streamFile.
+     * This API function is inside liblsbstream.so.
+     * <p/>
+     * <b>\#include <lsf/lsbatch.h>
+     * <p/>
+     * int lsb_writestream(eventRec.ByReference logPtr)</b>
+     *
+     * @return int:-1 \n
+     *         The function failed.
+     *         <p/>
+     *         \b Errors:
+     *         \par
+     *         If the function fails, lsberrno is set to indicate the error.
+     *         <p/>
+     *         <b>Equivalent line commands:</b>
+     *         \par
+     *         none
+     *         <p/>
+     *         <b>Files:</b>
+     *         \par
+     *         $LSB_CONFDIR/cluster_name/configdir/lsb.params
+     * @param logPtr Pointer to the eventRec structure.
+     * \n see \ref lsb_geteventrec for details on the eventRec structure.
+     * <p/>
+     * <b>Data Structures:</b>
+     * \par
+     * eventRec
+     * \n eventLog
+     * \n xFile
+     * \n jobAttrSetLog
+     * \n logSwitchLog
+     * \n dataLoggingLog
+     * \n jgrpNewLog
+     * \n jgrpCtrlLog
+     * \n jgrpStatusLog
+     * \n jobNewLog
+     * \n jobModLog
+     * \n jobStartLog
+     * \n jobStartAcceptLog
+     * \n jobExecuteLog
+     * \n jobStatusLog
+     * \n sbdJobStatusLog
+     * \n sbdUnreportedStatusLog
+     * \n jobSwitchLog
+     * \n jobMoveLog
+     * \n chkpntLog
+     * \n jobRequeueLog
+     * \n jobCleanLog
+     * \n jobExceptionLog
+     * \n sigactLog
+     * \n migLog
+     * \n signalLog
+     * \n queueCtrlLog
+     * \n hostCtrlLog
+     * \n hgCtrlLog
+     * \n mbdStartLog
+     * \n mbdDieLog
+     * \n unfulfillLog
+     * \n jobFinishLog
+     * \n loadIndexLog
+     * \n calendarLog
+     * \n jobForwardLog
+     * \n jobAcceptLog
+     * \n statusAckLog
+     * \n jobMsgLog
+     * \n jobMsgAckLog
+     * \n jobOccupyReqLog
+     * \n jobVacatedLog
+     * \n jobForceRequestLog
+     * \n jobChunkLog
+     * \n jobExternalMsgLog
+     * \n rsvRes
+     * \n rsvFinishLog
+     * \n cpuProfileLog
+     * \n jobRunRusageLog
+     * \n slaLog
+     * \n perfmonLogInfo
+     * \n perfmonLog
+     * \n taskFinishLog
+     * \n eventEOSLog
+     * \n jobResizeNotifyStartLog
+     * \n jobResizeNotifyAcceptLog
+     * \n jobResizeNotifyDoneLog
+     * \n jobResizeReleaseLog
+     * \n jobResizeCancelLog
+     * \n jobResizeLog
+     * \n jRusage
+     * <p/>
+     * <b>Define Statements:</b>
+     * \par
+     * \ref event_types
+     * \n \ref defs_lsb_XF_OP
+     * \n \ref jobgroup_controltypes
+     * \n \ref signal_action
+     * #see \ref lsb_closestream
+     * #see \ref lsb_geteventrec
+     * #see \ref lsb_openstream
+     * #see \ref lsb_puteventrec
+     * #see \ref lsb_readstreamline
+     * #see \ref lsb_streamversion
+     * #see \ref lsb_readstream
+     */
+    // NOTE: Not in libbat
+    //public static native int lsb_writestream(eventRec logPtr);
+
+     /**//*
+     * \page lsb_readstream lsb_readstream
+     * \brief Reads a current version eventRec structure from the lsb_stream file.
+     * <p/>
+     * \ref lsb_readstream reads an eventrRec from the open streamFile.
+     * <p/>
+     * <b>\#include <lsf/lsbatch.h>
+     * <p/>
+     * eventRec lsb_readstream(IntByReference nline)</b>
+     *
+     * @return int:-1 \n
+     *         The function failed.
+     *         <p/>
+     *         \b Errors:
+     *         \par
+     *         On failure, lsberrno is set to indicate the error.
+     *         <p/>
+     *         <b>Equivalent line commands:</b>
+     *         \par
+     *         none
+     *         <p/>
+     *         <b>Files:</b>
+     *         \par
+     *         $LSB_CONFDIR/cluster_name/configdir/lsb.params
+     * @param nline Line number in the stream file to be read.
+     * <p/>
+     * <b>Data Structures:</b>
+     * \par
+     * eventRec
+     * <p/>
+     * <b>Define Statements:</b>
+     * \par
+     * none
+     * #see \ref lsb_closestream
+     * #see \ref lsb_geteventrec
+     * #see \ref lsb_openstream
+     * #see \ref lsb_puteventrec
+     * #see \ref lsb_readstreamline
+     * #see \ref lsb_streamversion
+     * #see \ref lsb_writestream
+     */
+    // NOTE: Not in libbat
+    //public static native eventRec.ByReference lsb_readstream(IntByReference nline);
+
+     /**//*
+     * \page lsb_readstreamline lsb_readstreamline
+     * \brief Reads a current version eventRec structure from the lsb_stream file.
+     * <p/>
+     * \ref lsb_readstreamline reads an eventrRec from the open streamFile
+     * <p/>
+     * <b>\#include <lsf/lsbatch.h>
+     * <p/>
+     * eventRec.ByReference lsb_readstreamline(String line)</b>
+     *
+     * @return null \n
+     *         The function failed.
+     *         <p/>
+     *         \b Errors:
+     *         \par
+     *         On failure, lsberrno is set to indicate the error.
+     *         <p/>
+     *         <b>Equivalent line commands:</b>
+     *         \par
+     *         none
+     *         <p/>
+     *         <b>Files:</b>
+     *         \par
+     *         $LSB_CONFDIR/cluster_name/configdir/lsb.params
+     * @param line Line number in the stream file to be read.
+     * See \ref lsb_puteventrec and \ref lsb_geteventrec for details on the eventRec structure.
+     * Additionally, there are three additional event types supported.
+     * <p/>
+     * <b>Data Structures:</b>
+     * \par
+     * eventRec
+     * <p/>
+     * <b>Define Statements:</b>
+     * \par
+     * none
+     * #see \ref lsb_closestream
+     * #see \ref lsb_geteventrec
+     * #see \ref lsb_openstream
+     * #see \ref lsb_puteventrec
+     * #see \ref lsb_readstream
+     * #see \ref lsb_streamversion
+     * #see \ref lsb_writestream
+     */
+    // NOTE: Not in libbat
+    //public static native eventRec.ByReference lsb_readstreamline(String line);
+
+    public static final int NUM_EXITRATE_TYPES = 4;
+
+/* options for exit rate type */
+
+
+/* all exited jobs */
+    public static final int JOB_EXIT = 0x01;
+
+/* jobs failed to start due to initialization problem on execution host*/
+    public static final int JOB_INIT = 0x02;
+
+/* jobs failed to start due to HPC specific initialization problem on execution host*/
+    public static final int HPC_INIT = 0x04;
+
+/* jobs exited not related to reasons set by LSF */
+    public static final int JOB_EXIT_NONLSF = 0x08;
+
+    /**
+     * \brief  APS factor information
+     */
+    public static class apsFactorInfo extends Structure {
+        public static class ByReference extends apsFactorInfo implements Structure.ByReference {}
+        public static class ByValue extends apsFactorInfo implements Structure.ByValue {}
+        public apsFactorInfo() {}
+        public apsFactorInfo(Pointer p) { super(p); read(); }
+
+
+        /**
+         * <  Name
+         */
+        public String name;
+
+        /**
+         * <  Weight
+         */
+        public float weight;
+
+        /**
+         * <  Limit
+         */
+        public float limit;
+
+        /**
+         * <  Grace period
+         */
+        public int gracePeriod;
+    }
+
+
+
+/* options for job group delete */
+
+/* delete the specified user's all empty job groups*/
+    public static final int JGRP_DEL_USER_GROUPS = 0x01;
+
+/* delete one job group's all empty children groups including itself*/
+    public static final int JGRP_DEL_CHILD_GROUPS = 0x02;
+
+/* delete all empty job groups */
+    public static final int JGRP_DEL_ALL = 0x04;
+
+    /**
+     * ------------------------------------------------------------------------
+     * lsb_getallocFromHhostfile
+     * <p/>
+     * Read the specified hostfile and return the host list. If path is null
+     * then read the hostfile specified by LSB_DJOB_HOSTFILE. The hostfile
+     * is assumed to be in simple format of one host per line. A host
+     * can be repeated.
+     * <p/>
+     * This function will allocate the memory for hostlist.
+     * It is the responsibility of the caller to free the lists when no longer
+     * needed. On success hostlist will be a list of strings.
+     * Before freeing hostlist the individual
+     * elements must be freed.
+     * <p/>
+     * Parameters:
+     * @param hostlist  [OUT]
+     * @param path      [IN]    path to hostfile, if null check LSB_DJOB_HOSTFILE
+     * <p/>
+     * @return Value:
+     * >0    success, length of hostlist not including the null last element
+     * -1    failure, lsberrno is set
+     * -------------------------------------------------------------------------
+     */
+    public static native int lsb_getallocFromHostfile(Pointer hostlist, String path);
+
+
+    /**
+     *  \addtogroup defs_lsb_launch defs_lsb_launch
+     *  lsb_launch() Valid options are:
+     */
+
+    /**
+     * < Disable standard input and redirect input from the special  device /dev/null. This is equivalent to blaunch -n.
+     */
+    public static final int LSF_DJOB_DISABLE_STDIN = 0x01;
+
+    /**
+     * < Replace existing enviornment variable values with envp.
+     */
+    public static final int LSF_DJOB_REPLACE_ENV = 0x02;
+
+    /**
+     * < Non-blocking mode; the parallel job does not wait once all tasks start.  This forces \ref lsb_launch not to wait for its tasks to finish.
+     */
+    public static final int LSF_DJOB_NOWAIT = 0x04;
+
+    /**
+     * < Display standard error messages with a corresponding host name where the message was generated.Cannot be specified with LSF_DJOB_NOWAIT.
+     */
+    public static final int LSF_DJOB_STDERR_WITH_HOSTNAME = 0x08;
+
+    /**
+     * < Display standard output messages with a corresponding host name  where the message was generated. Cannot be specified with LSF_DJOB_NOWAIT.
+     */
+    public static final int LSF_DJOB_STDOUT_WITH_HOSTNAME = 0x10;
+
+    /**
+     * < Use user's login shell to  launch tasks
+     */
+    public static final int LSF_DJOB_USE_LOGIN_SHELL = 0x20;
+
+    /**
+     * < Use /bin/sh to launch tasks
+     */
+    public static final int LSF_DJOB_USE_BOURNE_SHELL = 0x40;
+
+    /**
+     * < Separate stderr from stdout
+     */
+    public static final int LSF_DJOB_STDERR = 0x80;
+
+/*
+* -------------------------------------------------------------------------
+*  lsb_launch (where, argv, options, envp)
+*
+*  DESCRIPTION:
+*
+*    The specified command (i.e., argv) will be launched on the remote
+*    nodes in parallel
+*
+*  ARGUMENTS:
+*    where [IN]:
+*        A null terminated list of hosts.
+*        If this parameter is null then the environment variable
+*        LSB_MCPU_HOSTS will be used.
+*        A task will be launched for each slot.
+*    options [IN]:
+*        options value obtained by ORing
+*    Envp [IN]:
+*        A Null terminated list of environment variables (in 'variable=value'
+*        format).
+*        The environment to set for each task.
+*        If this parameter is null then the same environment used to start
+*        the first task will be used.
+*        If non-null, it is appended to the environment used for the
+*        first task.
+*        If LSF_DJOB_REPLACE_ENV is specified, Envp entries will overwrite
+*        existing values except those LSF needs.
+*
+*  RETURN:
+*    < 0 on failure
+*    > 0 upon success (i.e., number of tasks issued)
+*
+ */
+
+    /**
+     * \page lsb_launch lsb_launch
+     * \brief  Launch commands on remote hosts in parallel.
+     * <p/>
+     * \ref lsb_launch is a synchronous API call to allow source level integration with
+     * vendor MPI implementations. This API will launch the specified command (argv)
+     * on the remote nodes in parallel.
+     * \n LSF must be installed before integrating your MPI implementation with
+     * \ref lsb_launch. The \ref lsb_launch API requires the full set of liblsf.so,
+     * libbat.so (or liblsf.a, libbat.a).
+     * <p/>
+     * <b>\#include <lsf/lsbatch.h>
+     * <p/>
+     * int lsb_launch (String[] where, String[] argv, int userOptions, String[] envp)</b>
+     *
+     * @param userOptions [IN] Options to modify the behavior of \ref lsb_launch
+     *                    Multiple option values can be specified. For example option values can be
+     *                    separated by OR (|):
+     *                    \n \ref lsb_launch (where, argv, LSF_DJOB_REPLACE_ENV | LSF_DJOB_DISABLE_STDIN, envp);
+     * @return < 0 \n
+     *         Function failed.
+     *         <p/>
+     *         \b Errors:
+     *         \par
+     *         If the function fails, lsberrno is set to indicate the error.
+     *         <p/>
+     *         <b>Equivalent line command:</b>
+     *         \par
+     *         blaunch
+     *         <p/>
+     *         <b>Files:</b>
+     *         \par
+     *         none
+     * @param where [IN] A null-terminated list of hosts. A task will be launched
+     * for each slot.If this parameter is null then the environment variable
+     * LSB_MCPU_HOSTS will be used.
+     * @param argv [IN] The command to be executed
+     * @param envp [IN] A null-terminated list of environment variables specifying
+     * the environment to set for each task.If envp is null, \ref lsb_launch uses the
+     * same environment used to start the first task on the first execution host.
+     * If non-null, envp values are appended to the environment used for the first
+     * task.If the LSF_DJOB_REPLACE_ENV option is specified, envp entries will
+     * overwrite all existing environment values except those needed by LSF.
+     * <p/>
+     * <b>Data Structures:</b>
+     * \par
+     * none
+     * <p/>
+     * <b>Define Statements:</b>
+     * \par
+     * \ref defs_lsb_launch
+     * see none
+     */
+    public static native int lsb_launch(Pointer where, Pointer argv, int userOptions, Pointer envp);
+
+/*
+* -------------------------------------------------------------------------
+*  lsb_getalloc
+*
+*  This function will allocate the memory for hostlist.
+*
+*  It is the responsibility of the caller to free the lists when no longer
+*  needed. On success hostlist will be a list of strings.
+*  Before freeing hostlist the individual
+*  elements must be freed.
+*
+*  Parameters:
+*     hostlist     [OUT]     null terminated list of hosts
+*
+*  Returns:
+*    >0    success, length of hostlist not including the null last element
+*    -1    failure, lsberrno is set
+*
+* -------------------------------------------------------------------------
+ */
+
+    /**
+     * \page lsb_getalloc lsb_getalloc
+     * \brief Allocates memory for a host list to be used for launching parallel
+     * tasks through blaunch and the \ref lsb_launch API.
+     * <p/>
+     * It is the responsibility of the caller to free the host list when it is
+     * no longer needed.On success, the host list will be a list of strings.
+     * Before freeing host list, the individual elements must be freed.
+     * <p/>
+     * An application using the \ref lsb_getalloc API is assumed to be part of an
+     * LSF job, and that LSB_MCPU_HOSTS is set in the environment.
+     * <p/>
+     * <b>\#include <lsf/lsbatch.h>
+     * <p/>
+     * int lsb_getalloc(String[][] hostlist)</b>
+     *
+     * @return < 0 \n
+     *         Function failed.
+     *         <p/>
+     *         \b Errors:
+     *         \par
+     *         If the function fails, lsberrno is set to indicate the error.
+     *         <p/>
+     *         <b>Equivalent line commands:</b>
+     *         \par
+     *         none
+     *         <p/>
+     *         <b>Files:</b>
+     *         \par
+     *         none
+     * @param hostlist [OUT] A null-terminated list of host names
+     * <p/>
+     * <b>Data Structures:</b>
+     * \par
+     * none
+     * <p/>
+     * <b>Define Statements:</b>
+     * \par
+     * none
+     * see none
+     */
+    public static native int lsb_getalloc(Pointer hostlist);
+
+    /**
+     * \page lsb_resize_cancel lsb_resize_cancel
+     * \brief Cancels a pending job resize allocation request.
+     * <p/>
+     * Use \ref lsb_resize_cancel to cancel a pending allocation request for a
+     * resizable job. A running job can only have one pending request at any
+     * particular time. If one request is still pending, additional requests
+     * are rejected with a proper error code.
+     * <p/>
+     * <b>\#include <lsf/lsbatch.h>
+     * <p/>
+     * int lsb_resize_cancel(long jobId);</b>
+     *
+     * @param jobId LSF job ID
+     *              <p/>
+     *              <b>Data Structures:</b>
+     *              \par
+     *              none
+     *              <p/>
+     *              <b>Define Statements:</b>
+     *              \par
+     *              none
+     * @return int:-1 \n
+     *         On failure, returns -1.
+     *         <p/>
+     *         \b Errors:
+     *         \par
+     *         lsberrno is set to indicate the error.
+     *         <p/>
+     *         <b>Equivalent line commands:</b>
+     *         \par
+     *         bresize cancel job_ID
+     *         <p/>
+     *         <b>Files:</b>
+     *         \par
+     *         none
+     * #see \ref lsb_resize_release
+     */
+
+    public static native int lsb_resize_cancel(long jobId);
+
+    /**
+     * \page lsb_resize_release lsb_resize_release
+     * \brief Releases part of the allocation of a running resizable job.
+     * <p/>
+     * Use \ref lsb_resize_release to release part of a running job allocation.
+     * A running job can only have one pending request at any particular time.
+     * If one request is still pending, additional requests are rejected with
+     * a proper error code.
+     * <p/>
+     * If a notification command is defined through job submission, application
+     * profile,or the \ref lsb_resize_release API, the notification command is invoked
+     * on the first execution host of the job allocation once allocation resize
+     * requests have been satisfied.
+     * <p/>
+     * <b>\#include <lsf/lsbatch.h>
+     * <p/>
+     * int lsb_resize_release(job_resize_release.ByReference req);</b>
+     *
+     * @return int:-1 \n
+     *         On failure, returns -1.
+     *         <p/>
+     *         \b Errors:
+     *         \par
+     *         lsberrno is set to indicate the error.
+     *         <p/>
+     *         <b>Equivalent line commands:</b>
+     *         \par
+     *         release [-c] [-rnc resize_notification_cmd | -rncn] released_host_specification job_ID
+     *         <p/>
+     *         <b>Files:</b>
+     *         \par
+     *         none
+     * @param req job resize release request.
+     * <p/>
+     * <b>Data Structures:</b>
+     * \par
+     * job_resize_release
+     * <p/>
+     * <b>Define Statements:</b>
+     * \par
+     * \ref resizablejob_related
+     * #see \ref lsb_resize_cancel
+     */
+    public static native int lsb_resize_release(job_resize_release req);
+
+    public static native int lsb_resize_request(job_resize_request job_resize_request1);
+
+    /**
+     * \page  lsb_getjobdepinfo lsb_getjobdepinfo
+     * Returns the job dependency information.
+     * <p/>
+     * \ref lsb_getjobdepinfo returns information about jobs (including job arrays) when
+     * a job has one or more dependencies on it.
+     * <p/>
+     * <b>\#include <lsf/lsbatch.h>
+     * <p/>
+     * jobDependInfo.ByReference
+     * lsb_getjobdepinfo(jobDepRequest.ByReference jobdepReq)</b>
+     *
+     * @return null
+     *         \n Function failed.
+     *         <p/>
+     *         \b Errors:
+     *         \par
+     *         none
+     *         <p/>
+     *         <b>Equivalent line commands:</b>
+     *         \par
+     *         none
+     *         <p/>
+     *         <b>Files:</b>
+     *         \par
+     *         none
+     * @param jobdepReq Job dependent Request.
+     * <p/>
+     * <b>Data Structures:</b>
+     * \par
+     * dependJobs
+     * \n queriedJobs
+     * \n jobDependInfo
+     * \n jobDepRequest
+     * <p/>
+     * <b>Define Statements:</b>
+     * \par
+     * \ref job_has_depend
+     * \n \ref query_depend
+     */
+    public static native jobDependInfo.ByReference lsb_getjobdepinfo(jobDepRequest jobdepReq);
+
+
+    /**
+     *  \page lsb_jsdl2submit lsb_jsdl2submit
+     *  \brief  Accepts a JSDL job submission file as input and converts the file
+     *   for use with LSF.
+     *
+     *  \ref lsb_jsdl2submit converts parameters specified in the JSDL file and merges
+     *  them with the other command line and job script options. The merged submit
+     *  request is then sent to mbatchd for processing.
+     *
+     *  Code must link to LSF_LIBDIR/libbat.jsdl.lib
+     *
+     *  <b>\#include <lsf/lsbatch.h>
+     *
+     *  int lsb_jsdl2submit(submit.ByReference req, String template);</b>
+     *
+     *  @param req Reads the specified JSDL options and maps them to the
+     *  submitReq structure. Code must specify either jsdl or jsdl_strict.
+     *  @param template The default template, which contains all of the bsub
+     *  submission options.
+     *
+     *  <b>Data Structures:</b>
+     *  \par
+     *  submit
+     *
+     *  <b>Define Statements:</b>
+     *  \par
+     *  none
+     *
+     *  @return int:0 \n
+     *  Function completed successfully.
+     *  @return int:-1 \n
+     *  Function failed.
+     *
+     *  <b>Errors:</b>
+     *  \par
+     *  On failure, sets lsberrno to indicate the error.
+     *
+     *  <b>Equivalent line command:</b>
+     *  \par
+     *   bsub with options
+     *
+     *  <b>Files:</b>
+     *  \par
+     *  $LSF_LIBDIR/jsdl.xsd
+     *  \n $LSF_LIBDIR/jsdl-posix.xsd
+     *  \n $LSF_LIBDIR/jsdl-lsf.xsd
+     *
+     *  @see \ref lsb_submit
+     *  @see \ref lsb_modify
+     */
+
+    /**
+     *  \page lsblib lsblib
+     *  \brief Application Programming Interface (API) library functions for batch jobs
+     *
+     *  LSBLIB functions allow application programs to get information about the hosts,
+     *  queues, users, jobs and configuration of the batch system. Application programs
+     *  can also submit jobs and control hosts, queues and jobs. Finally, application
+     *  programs can read batch log files and write batch error messages.
+     *
+     *  \note
+     *  \par
+     *  All LSBLIB APIs require that the batch header file <lsf/lsbatch.h> be included.
+     *  \par
+     *  Many LSBLIB APIs return a pointer to an array or structure. These data structures
+     *  are in static storage or on the heap. The next time the API is called, the storage
+     *  is overwritten or freed.
+     *  \par
+     *  Any program using LSBLIB APIs that change the state of the batch system (that
+     *  is, except for APIs that just get information about the system) must be setuid
+     *  to root if LSF_AUTH is not defined in the lsf.conf file.
+     *  \par
+     *  On systems which have both System V and BSD programming interfaces, LSBLIB
+     *  typically requires the BSD programming interface. On System V-based versions of
+     *  UNIX, for example SGI IRIX, it is normally necessary to link applications using
+     *  LSBLIB with the BSD compatibility library.
+     *  \par
+     *  On AFS systems, the following needs to be added to the end of your linkage
+     *  specifications when linking with LSBLIB (assuming your AFS library path is
+     *  /usr/afsws):
+     *  \par
+     *  For HP-UX and Solaris,
+     *  \par
+     *  -lc -L/usr/afsws/lib -L/usr/afsws/lib/afs -lsys -lrx -llwp /usr/afsws/lib/afs/util.a
+     *  \par
+     *  For other platforms,
+     *  \par
+     *  -lc -L/usr/afsws/lib -L/usr/afsws/lib/afs -lsys -lrx -llwp
+     *
+     *  \b Files:
+     *  \par
+     *  ${LSF_ENVDIR:-/etc}/lsf.conf
+     *  \n $LSF_CONFDIR/lsf.shared
+     *  \n $LSF_CONFDIR/lsf.cluster.cluster_name
+     *  \n $LSF_CONFDIR/lsf.task
+     *  \n $LSF_CONFDIR/lsf.task.cluster_name
+     *  \n $LSB_CONFDIR/cluster_name/configdir/lsb.hosts
+     *  \n $$LSB_CONFDIR/cluster_name/configdir/lsb.params
+     *  \n $LSB_CONFDIR/cluster_name/configdir/lsb.queues
+     *  \n $LSB_CONFDIR/cluster_name/configdir/lsb.users
+     *
+     *  @see lsblibapis
+     */
+}
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/jna/lsf/v7_0_6/LibLsf.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/jna/lsf/v7_0_6/LibLsf.java
new file mode 100644
index 0000000..cc4721d
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/jna/lsf/v7_0_6/LibLsf.java
@@ -0,0 +1,1780 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.utils.jna.lsf.v7_0_6;
+
+import com.sun.jna.*;
+import com.sun.jna.ptr.FloatByReference;
+import com.sun.jna.ptr.IntByReference;
+import com.sun.jna.ptr.PointerByReference;
+import org.broadinstitute.gatk.utils.jna.clibrary.JNAUtils;
+import org.broadinstitute.gatk.utils.jna.clibrary.LibC.timeval;
+
+/*
+  NOTE: This library uses Pointer for some Struct.ByReference members going
+  against the JNA recommendations at http://jna.java.net/#structure_use
+  Instead stuct arrays are Pointers and each structure contains a
+  constructor that can accept the Pointer iff the size of the array is
+  known to be greater than zero.
+
+  This was especially problematic in jobInfoEnt->items->resName. When
+  jobInfo->reserveCnt was zero jobInfoItems->items was not necessarily null.
+
+  LSF will often reuse memory for structure arrays but will set the
+  array size / count (reserveCnt above) to zero when the array should
+  not be accessed. When LSF has reused memory and points to a non-null
+  structure pointer (items) the inner structure may contain further
+  garbage pointers (especially items->resName).
+
+  When JNA sees a non-null Structure.ByReference it will autoRead() the
+  member. When autoRead() eventually gets to the items->resName trying
+  to run strlen on the bad memory address causes a SIGSEGV.
+
+  By using a Pointer instead of the Structure.ByReference JNA will not
+  automatically autoRead(), and the API user will have to pass the
+  pointer to the Structure on their own.
+*/
+
+/**
+ * JNA wrappers for LSF's lsf.h and -llsf
+ *
+ * $Id: base.h,v 1.25.6.12.2.5.2.11.2.15 2009/08/17 07:25:05 qlnie Exp $
+ ****************************************************************************
+ *
+ * Load Sharing Facility
+ *
+ * Header file for all components of load sharing facility.
+ *
+ ****************************************************************************/
+ at SuppressWarnings("unused")
+public class LibLsf {
+
+    static {
+        /*
+        LSF 7.0.6 on the mac is missing the unsatisfied exported symbol for environ which was removed on MacOS X 10.5+.
+        nm $LSF_LIBDIR/liblsf.dylib | grep environ
+        See "man environ" for more info, along with http://lists.apple.com/archives/java-dev/2007/Dec/msg00096.html
+        For now, we export environ ourselves using libenvironhack.dylib available in c/libenvironhack.
+        */
+        if (Platform.isMac())
+            NativeLibrary.getInstance("environhack");
+        String lsfLibDir = System.getenv("LSF_LIBDIR");
+        if (lsfLibDir != null) {
+            NativeLibrary.addSearchPath("lsf", lsfLibDir);
+        }
+        Native.register("lsf");
+    }
+
+    public static final String PASSWD_FILE_LS = "passwd.lsfuser";
+    public static final int PASSWORD_LEN = 64;
+    public static final int MAXHOSTNAMELEN = JNAUtils.MAXHOSTNAMELEN;
+    public static final int MAXPATHLEN = JNAUtils.MAXPATHLEN;
+
+
+    public static final int LOG_EMERG = 0;
+    public static final int LOG_ALERT = 1;
+    public static final int LOG_CRIT = 2;
+    public static final int LOG_ERR = 3;
+    public static final int LOG_WARNING = 4;
+    public static final int LOG_NOTICE = 5;
+    public static final int LOG_INFO = 6;
+    public static final int LOG_DEBUG = 7;
+
+    public static final int INVALID_SOCKET = -1;
+
+    public static boolean SOCK_INVALID(int c) {
+        return ((c) == INVALID_SOCKET);
+    }
+
+    public static class rlimit extends Structure {
+        public static class ByReference extends rlimit implements Structure.ByReference {}
+        public static class ByValue extends rlimit implements Structure.ByValue {}
+        public rlimit() {}
+        public rlimit(Pointer p) { super(p); read(); }
+
+        public NativeLong rlim_cur;
+        public NativeLong rlim_max;
+    }
+
+
+
+    public static class rusage extends Structure {
+        public static class ByReference extends rusage implements Structure.ByReference {}
+        public static class ByValue extends rusage implements Structure.ByValue {}
+        public rusage() {}
+        public rusage(Pointer p) { super(p); read(); }
+
+        public timeval ru_utime;
+        public timeval ru_stime;
+
+
+        public NativeLong ru_maxrss;
+        //public static final int ru_first = ru_ixrss;
+        public NativeLong ru_ixrss;
+        public NativeLong ru_idrss;
+        public NativeLong ru_isrss;
+        public NativeLong ru_minflt;
+        public NativeLong ru_majflt;
+        public NativeLong ru_nswap;
+        public NativeLong ru_inblock;
+        public NativeLong ru_oublock;
+        public NativeLong ru_msgsnd;
+        public NativeLong ru_msgrcv;
+        public NativeLong ru_nsignals;
+        public NativeLong ru_nvcsw;
+        public NativeLong ru_nivcsw;
+        //public static final int ru_last = ru_nivcsw;
+        // Listed in lsf.h but not present in structure.
+        //public NativeLong ru_ioch;
+    }
+
+
+
+
+    public static final String _VERSION_STR_ = "Platform LSF 7.0";
+    public static final String _WORKGROUP_STR_ = "";
+    public static final String _MINOR_STR_ = "";
+    public static final String _BUILD_STR_ = "";
+    public static final String _NOTE_STR_ = "";
+    public static final String _HOTFIX_STR_ = "";
+    public static final String _OS_STR_ = "";
+
+    public static final String _DATE_STR_ = "";
+    public static final String _BUILD_INFO_ = _MINOR_STR_ + "" + _BUILD_STR_ + "" + _WORKGROUP_STR_ + ", " + _DATE_STR_ + "\nCopyright 1992-2009 Platform Computing Corporation\n\n" + _OS_STR_ + _NOTE_STR_ + _HOTFIX_STR_;
+    public static final String _LS_VERSION_ = (_VERSION_STR_ + "" + _BUILD_INFO_);
+
+    //public static int XDR_SETPOS (int xdrs, int pos)  { (*(xdrs)->x_ops->x_setpostn)(xdrs, 0); return (*(xdrs)->x_ops->x_setpostn)(xdrs, pos); }
+    //public static int xdr_setpos (int xdrs, int pos)  { (*(xdrs)->x_ops->x_setpostn)(xdrs, 0); return (*(xdrs)->x_ops->x_setpostn)(xdrs, pos); }
+
+
+    public static final int LSF_XDR_VERSION2_0 = 1;
+    public static final int LSF_XDR_VERSION2_1 = 2;
+    public static final int LSF_XDR_VERSION2_2 = 3;
+    public static final int LSF_XDR_VERSION3_0 = 4;
+    public static final int LSF_XDR_VERSION3_1 = 5;
+    public static final int LSF_XDR_VERSION3_2 = 6;
+    public static final int LSF_XDR_VERSION3_2_2 = 7;
+    public static final int LSF_XDR_VERSION4_0 = 8;
+    public static final int LSF_XDR_VERSION4_1 = 9;
+    public static final int LSF_XDR_VERSION4_2 = 10;
+    public static final int LSF_XDR_VERSION5_0 = 11;
+    public static final int LSF_XDR_VERSION5_1 = 12;
+    public static final int LSF_XDR_VERSION6_0 = 13;
+    public static final int LSF_XDR_VERSION6_1 = 14;
+    public static final int LSF_XDR_VERSION6_2 = 15;
+    public static final int EGO_XDR_VERSION_1_1 = 16;
+    public static final int LSF_XDR_VERSION7_0 = 17;
+    public static final int EGO_XDR_VERSION_1_2 = LSF_XDR_VERSION7_0;
+    public static final int LSF_XDR_VERSION7_0_EP1 = 18;
+    public static final int LSF_XDR_VERSION7_0_EP2 = 19;
+    public static final int LSF_XDR_VERSION7_0_EP3 = 20;
+    public static final int LSF_XDR_VERSION7_0_EP4 = 21;
+    public static final int LSF_XDR_VERSION7_0_EP5 = 22;
+    public static final int LSF_XDR_VERSION7_0_EP6 = 23;
+    public static final int EGO_XDR_VERSION_1_2_2 = LSF_XDR_VERSION7_0_EP1;
+    public static final int EGO_XDR_VERSION_1_2_3 = LSF_XDR_VERSION7_0_EP2;
+
+    public static final int EGO_XDR_VERSION = LSF_XDR_VERSION7_0_EP2;
+
+    //public String LOG_VERSION;
+
+    public static final int LSF_DEFAULT_SOCKS = 15;
+    public static final int MAXLINELEN = 512;
+    public static final int MAXLSFNAMELEN = 40;
+    public static final int MAXLSFNAMELEN_70_EP1 = 128;
+
+    public static final int MAXSRES = 32;
+    public static final int MAXRESDESLEN = 256;
+    public static final int NBUILTINDEX = 11;
+    public static final int MAXTYPES = 128;
+    public static final int MAXMODELS = 1024 + 2;
+    public static final int MAXMODELS_70 = 128;
+    public static final int MAXTYPES_31 = 25;
+    public static final int MAXMODELS_31 = 30;
+    public static final int MAXFILENAMELEN = 256;
+    public static final int MAXEVARS = 30;
+
+    public static final int GENMALLOCPACE = 1024;
+
+
+    public static final int FIRST_RES_SOCK = 20;
+
+
+    public static final int R15S = 0;
+    public static final int R1M = 1;
+    public static final int R15M = 2;
+    public static final int UT = 3;
+    public static final int PG = 4;
+    public static final int IO = 5;
+    public static final int LS = 6;
+    public static final int IT = 7;
+    public static final int TMP = 8;
+    public static final int SWP = 9;
+    public static final int MEM = 10;
+    public static final int USR1 = 11;
+    public static final int USR2 = 12;
+
+
+    public static final float INFINIT_LOAD = (float) (0x7fffffff);
+    public static final float INFINIT_FLOAT = (float) (0x7fffffff);
+
+    public static final int INFINIT_INT = 0x7fffffff;
+    public static final long INFINIT_LONG_INT = 0x7fffffffffffffffL;
+    public static final short INFINIT_SHORT = 0x7fff;
+
+    public static final int DEFAULT_RLIMIT = -1;
+
+    public static final int LSF_RLIMIT_CPU = 0;
+    public static final int LSF_RLIMIT_FSIZE = 1;
+    public static final int LSF_RLIMIT_DATA = 2;
+    public static final int LSF_RLIMIT_STACK = 3;
+    public static final int LSF_RLIMIT_CORE = 4;
+    public static final int LSF_RLIMIT_RSS = 5;
+    public static final int LSF_RLIMIT_NOFILE = 6;
+    public static final int LSF_RLIMIT_OPEN_MAX = 7;
+    public static final int LSF_RLIMIT_VMEM = 8;
+    public static final int LSF_RLIMIT_SWAP = LSF_RLIMIT_VMEM;
+    public static final int LSF_RLIMIT_RUN = 9;
+    public static final int LSF_RLIMIT_PROCESS = 10;
+    public static final int LSF_RLIMIT_THREAD = 11;
+    public static final int LSF_RLIM_NLIMITS = 12;
+
+    public static final int LSF_RLIM_NLIMITS5_1 = 11;
+
+    //public static int seteuid (int x) { return setresuid(-1,x,-1); }
+    //public static int setegid (int x) { return setresgid(-1,x,-1); }
+
+    public static final int LSF_NULL_MODE = 0;
+    public static final int LSF_LOCAL_MODE = 1;
+    public static final int LSF_REMOTE_MODE = 2;
+
+
+    public static final int RF_MAXHOSTS = 5;
+
+
+    public static final int RF_CMD_MAXHOSTS = 0;
+
+
+    public static final int RF_CMD_RXFLAGS = 2;
+
+
+    public static final int STATUS_TIMEOUT = 125;
+    public static final int STATUS_IOERR = 124;
+    public static final int STATUS_EXCESS = 123;
+    public static final int STATUS_REX_NOMEM = 122;
+    public static final int STATUS_REX_FATAL = 121;
+    public static final int STATUS_REX_CWD = 120;
+    public static final int STATUS_REX_PTY = 119;
+    public static final int STATUS_REX_SP = 118;
+    public static final int STATUS_REX_FORK = 117;
+    public static final int STATUS_REX_AFS = 116;
+    public static final int STATUS_REX_UNKNOWN = 115;
+    public static final int STATUS_REX_NOVCL = 114;
+    public static final int STATUS_REX_NOSYM = 113;
+    public static final int STATUS_REX_VCL_INIT = 112;
+    public static final int STATUS_REX_VCL_SPAWN = 111;
+    public static final int STATUS_REX_EXEC = 110;
+    public static final int STATUS_REX_MLS_INVAL = 109;
+    public static final int STATUS_REX_MLS_CLEAR = 108;
+    public static final int STATUS_REX_MLS_RHOST = 107;
+    public static final int STATUS_REX_MLS_DOMIN = 106;
+    public static final int STATUS_DENIED = 105;
+
+
+    public static boolean REX_FATAL_ERROR(int s) {
+        return (((s) == STATUS_REX_NOVCL) || ((s) == STATUS_REX_NOSYM) || ((s) == STATUS_REX_NOMEM) || ((s) == STATUS_REX_FATAL) || ((s) == STATUS_REX_CWD) || ((s) == STATUS_REX_PTY) || ((s) == STATUS_REX_VCL_INIT) || ((s) == STATUS_REX_VCL_SPAWN) || ((s) == STATUS_REX_MLS_INVAL) || ((s) == STATUS_REX_MLS_CLEAR) || ((s) == STATUS_REX_MLS_RHOST) || ((s) == STATUS_REX_MLS_DOMIN));
+    }
+
+
+    public static final int REXF_USEPTY = 0x00000001;
+    public static final int REXF_CLNTDIR = 0x00000002;
+    public static final int REXF_TASKPORT = 0x00000004;
+    public static final int REXF_SHMODE = 0x00000008;
+    public static final int REXF_TASKINFO = 0x00000010;
+    public static final int REXF_REQVCL = 0x00000020;
+    public static final int REXF_SYNCNIOS = 0x00000040;
+    public static final int REXF_TTYASYNC = 0x00000080;
+    public static final int REXF_STDERR = 0x00000100;
+
+
+    public static final int EXACT = 0x01;
+    public static final int OK_ONLY = 0x02;
+    public static final int NORMALIZE = 0x04;
+    public static final int LOCALITY = 0x08;
+    public static final int IGNORE_RES = 0x10;
+    public static final int LOCAL_ONLY = 0x20;
+    public static final int DFT_FROMTYPE = 0x40;
+    public static final int ALL_CLUSTERS = 0x80;
+    public static final int EFFECTIVE = 0x100;
+
+
+    public static final int RECV_FROM_CLUSTERS = 0x200;
+    public static final int NEED_MY_CLUSTER_NAME = 0x400;
+
+
+    public static final int SEND_TO_CLUSTERS = 0x400;
+
+
+    public static final int NO_SORT = 0x800;
+
+
+    public static final int EXCLUSIVE_RESOURCE = 0x1000;
+
+    public static final int DT_CLUSTER_LOAD = 0x2000;
+
+
+    public static final int FROM_MASTER = 0x01;
+
+
+    public static final int KEEPUID = 0x01;
+
+
+    public static final int RES_CMD_REBOOT = 1;
+
+    public static final int RES_CMD_SHUTDOWN = 2;
+
+    public static final int RES_CMD_LOGON = 3;
+
+    public static final int RES_CMD_LOGOFF = 4;
+
+
+    public static final int LIM_CMD_REBOOT = 1;
+    public static final int LIM_CMD_SHUTDOWN = 2;
+    public static final int LIM_CMD_REMOVEHOST = 3;
+    public static final int LIM_CMD_ACTIVATE = 4;
+    public static final int LIM_CMD_DEACTIVATE = 5;
+    public static final int LIM_CMD_ELIM_ENV = 6;
+
+
+    public static class connectEnt extends Structure {
+        public static class ByReference extends connectEnt implements Structure.ByReference {}
+        public static class ByValue extends connectEnt implements Structure.ByValue {}
+        public connectEnt() {}
+        public connectEnt(Pointer p) { super(p); read(); }
+
+        public String hostname;
+        public int[] csock = new int[2];
+    }
+
+
+
+    public static final int INTEGER_BITS = 32;
+
+    public static int GET_INTNUM(int i) {
+        return ((i) / INTEGER_BITS + 1);
+    }
+
+
+    public static final int LIM_UNAVAIL = 0x00010000;
+    public static final int LIM_LOCKEDU = 0x00020000;
+    public static final int LIM_LOCKEDW = 0x00040000;
+    public static final int LIM_BUSY = 0x00080000;
+    public static final int LIM_RESDOWN = 0x00100000;
+    public static final int LIM_UNLICENSED = 0x00200000;
+    public static final int LIM_SBDDOWN = 0x00400000;
+    public static final int LIM_LOCKEDM = 0x00800000;
+
+    public static final int LIM_OK_MASK = 0x00bf0000;
+    public static final int LIM_PEMDOWN = 0x01000000;
+    public static final int LIM_LOCKEDU_RMS = 0x80000000;
+
+
+    public static boolean LS_ISUNAVAIL(int[] status) {
+        return (((status) != null) && (((status[0]) & LIM_UNAVAIL) != 0));
+    }
+
+
+    public static boolean LS_ISBUSYON(int[] status, int index) {
+        return (((status) != null) && (((status[1 + (index) / INTEGER_BITS]) & (1 << (index) % INTEGER_BITS)) != 0));
+    }
+
+    public static boolean LS_ISBUSY(int[] status) {
+        return (((status) != null) && (((status[0]) & LIM_BUSY) != 0));
+    }
+
+
+    public static boolean LS_ISRMSLOCK(int[] status) {
+        return (((status) != null) && (((status[0]) & LIM_LOCKEDU_RMS) != 0));
+    }
+
+
+    public static boolean LS_ISLOCKEDU(int[] status) {
+        return (((status) != null) && (((status[0]) & LIM_LOCKEDU) != 0));
+    }
+
+
+    public static boolean LS_ISLOCKEDW(int[] status) {
+        return (((status) != null) && (((status[0]) & LIM_LOCKEDW) != 0));
+    }
+
+
+    public static boolean LS_ISLOCKEDM(int[] status) {
+        return (((status) != null) && (((status[0]) & LIM_LOCKEDM) != 0));
+    }
+
+
+    public static boolean LS_ISLOCKED(int[] status) {
+        return (((status) != null) && (((status[0]) & (LIM_LOCKEDU | LIM_LOCKEDW | LIM_LOCKEDM)) != 0));
+    }
+
+
+    public static boolean LS_ISRESDOWN(int[] status) {
+        return (((status) != null) && (((status[0]) & LIM_RESDOWN) != 0));
+    }
+
+
+    public static boolean LS_ISSBDDOWN(int[] status) {
+        return (((status) != null) && (((status[0]) & LIM_SBDDOWN) != 0));
+    }
+
+    public static boolean LS_ISPEMDOWN(int[] status) {
+        return (((status[0]) & LIM_PEMDOWN) != 0);
+    }
+
+
+    public static boolean LS_ISUNLICENSED(int[] status) {
+        return (((status) != null) && (((status[0]) & LIM_UNLICENSED) != 0));
+    }
+
+
+    public static boolean LS_ISOK(int[] status) {
+        return (((status) != null) && ((status[0] & LIM_OK_MASK) == 0));
+    }
+
+
+    public static boolean LS_ISOKNRES(int[] status) {
+        return (((status) != null) && (((status[0] & ~(LIM_LOCKEDU_RMS)) & ~(LIM_RESDOWN | LIM_SBDDOWN | LIM_PEMDOWN)) == 0));
+    }
+
+
+    public static class placeInfo extends Structure {
+        public static class ByReference extends placeInfo implements Structure.ByReference {}
+        public static class ByValue extends placeInfo implements Structure.ByValue {}
+        public placeInfo() {}
+        public placeInfo(Pointer p) { super(p); read(); }
+
+        public byte[] hostName = new byte[MAXHOSTNAMELEN];
+        public int numtask;
+    }
+
+
+
+
+    public static class hostLoad extends Structure {
+        public static class ByReference extends hostLoad implements Structure.ByReference {}
+        public static class ByValue extends hostLoad implements Structure.ByValue {}
+        public hostLoad() {}
+        public hostLoad(Pointer p) { super(p); read(); }
+
+        public byte[] hostName = new byte[MAXHOSTNAMELEN];
+        public IntByReference status;
+        public FloatByReference li;
+    }
+
+
+
+
+    public static interface valueType {
+          public static final int LS_BOOLEAN = 0;
+          public static final int LS_NUMERIC = 1;
+          public static final int LS_STRING = 2;
+          public static final int LS_EXTERNAL = 3;
+    }
+
+
+
+    public static interface orderType {
+          public static final int INCR = 0;
+          public static final int DECR = 1;
+          public static final int NA = 2;
+    }
+
+
+
+
+    public static final int RESF_BUILTIN = 0x01;
+    public static final int RESF_DYNAMIC = 0x02;
+    public static final int RESF_GLOBAL = 0x04;
+    public static final int RESF_SHARED = 0x08;
+    public static final int RESF_LIC = 0x10;
+    public static final int RESF_EXTERNAL = 0x20;
+    public static final int RESF_RELEASE = 0x40;
+    public static final int RESF_DEFINED_IN_RESOURCEMAP = 0x80;
+
+    public static final int RESF_NON_CONSUMABLE = 0x100;
+    public static final int RESF_REDEFINABLE = 0x200;
+    public static final int RESF_ESRES = 0x400;
+
+
+    public static class resItem extends Structure {
+        public static class ByReference extends resItem implements Structure.ByReference {}
+        public static class ByValue extends resItem implements Structure.ByValue {}
+        public resItem() {}
+        public resItem(Pointer p) { super(p); read(); }
+
+        public byte[] name = new byte[MAXLSFNAMELEN];
+        public byte[] des = new byte[MAXRESDESLEN];
+        public /*valueType*/ int valueType;
+        public /*orderType*/ int orderType;
+        public int flags;
+        public int interval;
+    }
+
+
+
+
+    public static class lsInfo extends Structure {
+        public static class ByReference extends lsInfo implements Structure.ByReference {}
+        public static class ByValue extends lsInfo implements Structure.ByValue {}
+        public lsInfo() {}
+        public lsInfo(Pointer p) { super(p); read(); }
+
+        // The current version of JNA's Structure.getNativeAlignment passes a "null" to
+        // Native.getNativeSize() when accessing the contents of a 2D array.
+        // Although the method is marked as protected, there are also multiple "TO DO"
+        // comments so when we upgrade don't want to have specialized code floating around.
+
+        public int nRes;
+        public Pointer /* resItem.ByReference */ resTable;
+        public int nTypes;
+        public byte[] hostTypes = new byte[MAXTYPES * MAXLSFNAMELEN];
+        public int nModels;
+        public byte[] hostModels = new byte[MAXMODELS * MAXLSFNAMELEN];
+        public byte[] hostArchs = new byte[MAXMODELS * MAXLSFNAMELEN_70_EP1];
+        public int[] modelRefs = new int[MAXMODELS];
+        public float[] cpuFactor = new float[MAXMODELS];
+        public int numIndx;
+        public int numUsrIndx;
+    }
+
+
+
+
+    public static final int CLUST_STAT_OK = 0x01;
+    public static final int CLUST_STAT_UNAVAIL = 0x02;
+    public static final int CLUST_STAT_RECV_FROM = 0x04;
+    public static final int CLUST_STAT_SEND_TO = 0x08;
+
+
+    public static boolean IS_DEFAULT_AUTH(byte[] auth) {
+        return (auth == null || auth[0] == '\0');
+    }
+
+
+    public static class clusterInfo extends Structure {
+        public static class ByReference extends clusterInfo implements Structure.ByReference {}
+        public static class ByValue extends clusterInfo implements Structure.ByValue {}
+        public clusterInfo() {}
+        public clusterInfo(Pointer p) { super(p); read(); }
+
+        public byte[] clusterName = new byte[MAXLSFNAMELEN];
+        public int status;
+        public byte[] masterName = new byte[MAXHOSTNAMELEN];
+        public byte[] managerName = new byte[MAXLSFNAMELEN];
+        public int managerId;
+        public int numServers;
+        public int numClients;
+        public int nRes;
+        public Pointer resources;
+        public int nTypes;
+        public Pointer hostTypes;
+        public int nModels;
+        public Pointer hostModels;
+        public int nAdmins;
+        public IntByReference adminIds;
+        public Pointer admins;
+        public int analyzerLicFlag;
+        public int jsLicFlag;
+        public byte[] afterHoursWindow = new byte[MAXLINELEN];
+        public byte[] preferAuthName = new byte[MAXLSFNAMELEN];
+        public byte[] inUseAuthName = new byte[MAXLSFNAMELEN];
+    }
+
+
+    public static class hostInfo extends Structure {
+        public static class ByReference extends hostInfo implements Structure.ByReference {}
+        public static class ByValue extends hostInfo implements Structure.ByValue {}
+        public hostInfo() {}
+        public hostInfo(Pointer p) { super(p); read(); }
+
+        public byte[] hostName = new byte[MAXHOSTNAMELEN];
+        public String hostType;
+        public String hostModel;
+        public float cpuFactor;
+        public int maxCpus;
+        public int maxMem;
+        public int maxSwap;
+        public int maxTmp;
+        public int nDisks;
+        public int nRes;
+        public Pointer resources;
+        public int nDRes;
+        public Pointer DResources;
+        public String windows;
+        public int numIndx;
+        public FloatByReference busyThreshold;
+        public byte isServer;
+        public byte licensed;
+        public int rexPriority;
+        public int licFeaturesNeeded;
+
+
+        public static final int LSF_BASE_LIC = 0;
+        public static final int LSF_BATCH_LIC_OBSOLETE = 1;
+        public static final int LSF_JS_SCHEDULER_LIC = 2;
+        public static final int LSF_JS_LIC = 3;
+        public static final int LSF_CLIENT_LIC = 4;
+        public static final int LSF_MC_LIC = 5;
+        public static final int LSF_ANALYZER_SERVER_LIC = 6;
+        public static final int LSF_MAKE_LIC = 7;
+
+        public static final int LSF_PARALLEL_LIC = 8;
+        public static final int LSF_FLOAT_CLIENT_LIC = 9;
+        public static final int LSF_FTA_LIC = 10;
+        public static final int LSF_AFTER_HOURS_LIC = 11;
+        public static final int LSF_RESOURCE_PREEMPT_LIC = 12;
+        public static final int LSF_BACCT_LIC = 13;
+        public static final int LSF_SCHED_FAIRSHARE_LIC = 14;
+        public static final int LSF_SCHED_RESERVE_LIC = 15;
+        public static final int LSF_SCHED_PREEMPTION_LIC = 16;
+        public static final int LSF_SCHED_PARALLEL_LIC = 17;
+        public static final int LSF_SCHED_ADVRSV_LIC = 18;
+        public static final int LSF_API_CLIENT_LIC = 19;
+
+        public static final int CLUSTERWARE_MANAGER_LIC = 20;
+        public static final int LSF_MANAGER_LIC = 21;
+        public static final int LSF_PCC_HPC_LIC = 22;
+        public static final int sCLUSTERWARE_LIC = 23;
+        public static final int OTTAWA_MANAGER_LIC = 24;
+
+        public static final int SYMPHONY_MANAGER_ONLINE_LIC = 25;
+        public static final int SYMPHONY_MANAGER_BATCH_LIC = 26;
+        public static final int SYMPHONY_SCHED_JOB_PRIORITY_LIC = 27;
+        public static final int LSF_DUALCORE_X86_LIC = 28;
+        public static final int LSF_TSCHED_LIC = 29;
+        public static final int LSF_WORKGROUP_LIC = 30;
+        public static final int LSF_NUM_LIC_TYPE = 31;
+        public static final int LSF_WG_NUM_LIC_TYPE = 2;
+        public static final int LSF_NO_NEED_LIC = 32;
+
+        public int licClass;
+        public int cores;
+        public static final int INET6_ADDRSTRLEN = 46;
+        public byte[] hostAddr = new byte[INET6_ADDRSTRLEN];
+        public int pprocs;
+
+        public int cores_per_proc;
+        public int threads_per_core;
+    }
+
+    public static boolean HAS_BATCH_LICENSES(int featureEnabled) {
+        return (JNAUtils.toBoolean(featureEnabled & (1 << hostInfo.CLUSTERWARE_MANAGER_LIC)) || JNAUtils.toBoolean(featureEnabled & (1 << hostInfo.LSF_MANAGER_LIC)) || JNAUtils.toBoolean(featureEnabled & (1 << hostInfo.LSF_WORKGROUP_LIC)) || JNAUtils.toBoolean(featureEnabled & (1 << hostInfo.SYMPHONY_MANAGER_ONLINE_LIC)) || JNAUtils.toBoolean(featureEnabled & (1 << hostInfo.SYMPHONY_MANAGER_BATCH_LIC)));
+    }
+
+    public static boolean HAS_SYMPHONY_LICENSES(int featureEnabled) {
+        return (JNAUtils.toBoolean(featureEnabled & (1 << hostInfo.SYMPHONY_MANAGER_ONLINE_LIC)) || JNAUtils.toBoolean(featureEnabled & (1 << hostInfo.SYMPHONY_MANAGER_BATCH_LIC)));
+    }
+
+
+    public static class config_param extends Structure {
+        public static class ByReference extends config_param implements Structure.ByReference {}
+        public static class ByValue extends config_param implements Structure.ByValue {}
+        public config_param() {}
+        public config_param(Pointer p) { super(p); read(); }
+
+        public String paramName;
+        public String paramValue;
+    }
+
+
+
+    public static class lsfRusage extends Structure {
+        public static class ByReference extends lsfRusage implements Structure.ByReference {}
+        public static class ByValue extends lsfRusage implements Structure.ByValue {}
+        public lsfRusage() {}
+        public lsfRusage(Pointer p) { super(p); read(); }
+
+        public double ru_utime;
+        public double ru_stime;
+        public double ru_maxrss;
+        public double ru_ixrss;
+        public double ru_ismrss;
+        public double ru_idrss;
+        public double ru_isrss;
+        public double ru_minflt;
+        public double ru_majflt;
+        public double ru_nswap;
+        public double ru_inblock;
+        public double ru_oublock;
+        public double ru_ioch;
+        public double ru_msgsnd;
+        public double ru_msgrcv;
+        public double ru_nsignals;
+        public double ru_nvcsw;
+        public double ru_nivcsw;
+        public double ru_exutime;
+    }
+
+
+
+
+    public static class lsfAcctRec extends Structure {
+        public static class ByReference extends lsfAcctRec implements Structure.ByReference {}
+        public static class ByValue extends lsfAcctRec implements Structure.ByValue {}
+        public lsfAcctRec() {}
+        public lsfAcctRec(Pointer p) { super(p); read(); }
+
+        public int pid;
+        public String username;
+        public int exitStatus;
+        public NativeLong dispTime;
+        public NativeLong termTime;
+        public String fromHost;
+        public String execHost;
+        public String cwd;
+        public String cmdln;
+        public lsfRusage lsfRu;
+    }
+
+
+
+
+    public static class confNode extends Structure {
+        public static class ByReference extends confNode implements Structure.ByReference {}
+        public static class ByValue extends confNode implements Structure.ByValue {}
+        public confNode() {}
+        public confNode(Pointer p) { super(p); read(); }
+
+        public confNode.ByReference leftPtr;
+        public confNode.ByReference rightPtr;
+        public confNode.ByReference fwPtr;
+        public String cond;
+        public int beginLineNum;
+        public int numLines;
+        public Pointer lines;
+        public byte tag;
+    }
+
+
+
+    public static class pStack extends Structure {
+        public static class ByReference extends pStack implements Structure.ByReference {}
+        public static class ByValue extends pStack implements Structure.ByValue {}
+        public pStack() {}
+        public pStack(Pointer p) { super(p); read(); }
+
+        public int top;
+        public int size;
+        public PointerByReference nodes;
+    }
+
+
+
+    public static class confHandle extends Structure {
+        public static class ByReference extends confHandle implements Structure.ByReference {}
+        public static class ByValue extends confHandle implements Structure.ByValue {}
+        public confHandle() {}
+        public confHandle(Pointer p) { super(p); read(); }
+
+        public confNode.ByReference rootNode;
+        public String fname;
+        public confNode.ByReference curNode;
+        public int lineCount;
+        public pStack.ByReference ptrStack;
+    }
+
+
+
+    public static class lsConf extends Structure {
+        public static class ByReference extends lsConf implements Structure.ByReference {}
+        public static class ByValue extends lsConf implements Structure.ByValue {}
+        public lsConf() {}
+        public lsConf(Pointer p) { super(p); read(); }
+
+        public confHandle.ByReference confhandle;
+        public int numConds;
+        public Pointer conds;
+        public IntByReference values;
+    }
+
+
+
+    public static class sharedConf extends Structure {
+        public static class ByReference extends sharedConf implements Structure.ByReference {}
+        public static class ByValue extends sharedConf implements Structure.ByValue {}
+        public sharedConf() {}
+        public sharedConf(Pointer p) { super(p); read(); }
+
+        public lsInfo.ByReference lsinfo;
+        public int numCls;
+        public Pointer clusterNames;
+        public Pointer servers;
+    }
+
+
+
+
+    public static class lsSharedResourceInstance extends Structure {
+        public static class ByReference extends lsSharedResourceInstance implements Structure.ByReference {}
+        public static class ByValue extends lsSharedResourceInstance implements Structure.ByValue {}
+        public lsSharedResourceInstance() {}
+        public lsSharedResourceInstance(Pointer p) { super(p); read(); }
+
+        public String value;
+        public int nHosts;
+        public Pointer hostList;
+
+    }
+
+
+
+
+    public static class lsSharedResourceInfo extends Structure {
+        public static class ByReference extends lsSharedResourceInfo implements Structure.ByReference {}
+        public static class ByValue extends lsSharedResourceInfo implements Structure.ByValue {}
+        public lsSharedResourceInfo() {}
+        public lsSharedResourceInfo(Pointer p) { super(p); read(); }
+
+        public String resourceName;
+        public int nInstances;
+        public Pointer /* lsSharedResourceInstance.ByReference */ instances;
+    }
+
+
+
+    public static class clusterConf extends Structure {
+        public static class ByReference extends clusterConf implements Structure.ByReference {}
+        public static class ByValue extends clusterConf implements Structure.ByValue {}
+        public clusterConf() {}
+        public clusterConf(Pointer p) { super(p); read(); }
+
+        public clusterInfo.ByReference clinfo;
+        public int numHosts;
+        public Pointer /* hostInfo.ByReference */ hosts;
+        public int defaultFeatures;
+        public int numShareRes;
+        public Pointer /* lsSharedResourceInfo.ByReference */ shareRes;
+    }
+
+
+
+
+    public static class pidInfo extends Structure {
+        public static class ByReference extends pidInfo implements Structure.ByReference {}
+        public static class ByValue extends pidInfo implements Structure.ByValue {}
+        public pidInfo() {}
+        public pidInfo(Pointer p) { super(p); read(); }
+
+        public int pid;
+        public int ppid;
+        public int pgid;
+        public int jobid;
+    }
+
+
+
+
+    public static class jRusage extends Structure {
+        public static class ByReference extends jRusage implements Structure.ByReference {}
+        public static class ByValue extends jRusage implements Structure.ByValue {}
+        public jRusage() {}
+        public jRusage(Pointer p) { super(p); read(); }
+
+        public int mem;
+        public int swap;
+        public int utime;
+        public int stime;
+        public int npids;
+        public Pointer /* pidInfo.ByReference */ pidInfo;
+
+        public int npgids;
+        public IntByReference pgid;
+        public int nthreads;
+    }
+
+
+
+
+    public static final int NUM_SUBS = 2;
+    public static final int LEN_SUBS = 64;
+    public static final int NUM_CLASS_TYPE = 3;
+
+    public static class licUsage extends Structure {
+        public static class ByReference extends licUsage implements Structure.ByReference {}
+        public static class ByValue extends licUsage implements Structure.ByValue {}
+        public licUsage() {}
+        public licUsage(Pointer p) { super(p); read(); }
+
+        public int licDisplayMask;
+        public int usingDemoLicense;
+        public float[] total = new float[hostInfo.LSF_NUM_LIC_TYPE];
+        public float[] inUse = new float[hostInfo.LSF_NUM_LIC_TYPE];
+    }
+
+
+
+    public static class hostClassInfo extends Structure {
+        public static class ByReference extends hostClassInfo implements Structure.ByReference {}
+        public static class ByValue extends hostClassInfo implements Structure.ByValue {}
+        public hostClassInfo() {}
+        public hostClassInfo(Pointer p) { super(p); read(); }
+
+        public int numHosts;
+        public int numCpus;
+        public int numCores;
+    }
+
+
+
+    public static class lsfLicUsage extends Structure {
+        public static class ByReference extends lsfLicUsage implements Structure.ByReference {}
+        public static class ByValue extends lsfLicUsage implements Structure.ByValue {}
+        public lsfLicUsage() {}
+        public lsfLicUsage(Pointer p) { super(p); read(); }
+
+        public licUsage licUsage;
+        public hostClassInfo[] hostInfo = new hostClassInfo[NUM_CLASS_TYPE];
+        // The current version of JNA's Structure.getNativeAlignment passes a "null" to
+        // Native.getNativeSize() when accessing the contents of a 2D array.
+        // Although the method is marked as protected, there are also multiple "TO DO"
+        // comments so when we upgrade don't want to have specialized code floating around.
+        public byte[] substitution = new byte[NUM_SUBS * LEN_SUBS];
+        public byte[] cluster = new byte[MAXFILENAMELEN];
+    }
+
+
+    public static class param_entry extends Structure {
+        public static class ByReference extends param_entry implements Structure.ByReference {}
+        public static class ByValue extends param_entry implements Structure.ByValue {}
+        public param_entry() {}
+        public param_entry(Pointer p) { super(p); read(); }
+
+        public static int HAS_PARAM_VALUE = 0x001;
+        public static final int HAS_PARAM_DEFAULT = 0x002;
+
+        public int flags;
+        public String key;
+        public String value;
+        public String default_value;
+    }
+
+
+
+    public static class params_key_value_pair extends Structure {
+        public static class ByReference extends params_key_value_pair implements Structure.ByReference {}
+        public static class ByValue extends params_key_value_pair implements Structure.ByValue {}
+        public params_key_value_pair() {}
+        public params_key_value_pair(Pointer p) { super(p); read(); }
+
+        public int num_params;
+        public String daemon_time;
+        public Pointer /* param_entry.ByReference */ param;
+    }
+
+
+
+
+    public static final int LSE_NO_ERR = 0;
+    public static final int LSE_BAD_XDR = 1;
+    public static final int LSE_MSG_SYS = 2;
+    public static final int LSE_BAD_ARGS = 3;
+    public static final int LSE_MASTR_UNKNW = 4;
+    public static final int LSE_LIM_DOWN = 5;
+    public static final int LSE_PROTOC_LIM = 6;
+    public static final int LSE_SOCK_SYS = 7;
+    public static final int LSE_ACCEPT_SYS = 8;
+    public static final int LSE_BAD_TASKF = 9;
+    public static final int LSE_NO_HOST = 10;
+    public static final int LSE_NO_ELHOST = 11;
+    public static final int LSE_TIME_OUT = 12;
+    public static final int LSE_NIOS_DOWN = 13;
+    public static final int LSE_LIM_DENIED = 14;
+    public static final int LSE_LIM_IGNORE = 15;
+    public static final int LSE_LIM_BADHOST = 16;
+    public static final int LSE_LIM_ALOCKED = 17;
+    public static final int LSE_LIM_NLOCKED = 18;
+    public static final int LSE_LIM_BADMOD = 19;
+    public static final int LSE_SIG_SYS = 20;
+    public static final int LSE_BAD_EXP = 21;
+    public static final int LSE_NORCHILD = 22;
+    public static final int LSE_MALLOC = 23;
+    public static final int LSE_LSFCONF = 24;
+    public static final int LSE_BAD_ENV = 25;
+    public static final int LSE_LIM_NREG = 26;
+    public static final int LSE_RES_NREG = 27;
+    public static final int LSE_RES_NOMORECONN = 28;
+    public static final int LSE_BADUSER = 29;
+    public static final int LSE_RES_ROOTSECURE = 30;
+    public static final int LSE_RES_DENIED = 31;
+    public static final int LSE_BAD_OPCODE = 32;
+    public static final int LSE_PROTOC_RES = 33;
+    public static final int LSE_RES_CALLBACK = 34;
+    public static final int LSE_RES_NOMEM = 35;
+    public static final int LSE_RES_FATAL = 36;
+    public static final int LSE_RES_PTY = 37;
+    public static final int LSE_RES_SOCK = 38;
+    public static final int LSE_RES_FORK = 39;
+    public static final int LSE_NOMORE_SOCK = 40;
+    public static final int LSE_WDIR = 41;
+    public static final int LSE_LOSTCON = 42;
+    public static final int LSE_RES_INVCHILD = 43;
+    public static final int LSE_RES_KILL = 44;
+    public static final int LSE_PTYMODE = 45;
+    public static final int LSE_BAD_HOST = 46;
+    public static final int LSE_PROTOC_NIOS = 47;
+    public static final int LSE_WAIT_SYS = 48;
+    public static final int LSE_SETPARAM = 49;
+    public static final int LSE_RPIDLISTLEN = 50;
+    public static final int LSE_BAD_CLUSTER = 51;
+    public static final int LSE_RES_VERSION = 52;
+    public static final int LSE_EXECV_SYS = 53;
+    public static final int LSE_RES_DIR = 54;
+    public static final int LSE_RES_DIRW = 55;
+    public static final int LSE_BAD_SERVID = 56;
+    public static final int LSE_NLSF_HOST = 57;
+    public static final int LSE_UNKWN_RESNAME = 58;
+    public static final int LSE_UNKWN_RESVALUE = 59;
+    public static final int LSE_TASKEXIST = 60;
+    public static final int LSE_BAD_TID = 61;
+    public static final int LSE_TOOMANYTASK = 62;
+    public static final int LSE_LIMIT_SYS = 63;
+    public static final int LSE_BAD_NAMELIST = 64;
+    public static final int LSE_NO_LICENSE = 65;
+    public static final int LSE_LIM_NOMEM = 66;
+    public static final int LSE_NIO_INIT = 67;
+    public static final int LSE_CONF_SYNTAX = 68;
+    public static final int LSE_FILE_SYS = 69;
+    public static final int LSE_CONN_SYS = 70;
+    public static final int LSE_SELECT_SYS = 71;
+    public static final int LSE_EOF = 72;
+    public static final int LSE_ACCT_FORMAT = 73;
+    public static final int LSE_BAD_TIME = 74;
+    public static final int LSE_FORK = 75;
+    public static final int LSE_PIPE = 76;
+    public static final int LSE_ESUB = 77;
+    public static final int LSE_DCE_EXEC = 78;
+    public static final int LSE_EAUTH = 79;
+    public static final int LSE_NO_FILE = 80;
+    public static final int LSE_NO_CHAN = 81;
+    public static final int LSE_BAD_CHAN = 82;
+    public static final int LSE_INTERNAL = 83;
+    public static final int LSE_PROTOCOL = 84;
+    public static final int LSE_THRD_SYS = 85;
+    public static final int LSE_MISC_SYS = 86;
+    public static final int LSE_LOGON_FAIL = 87;
+    public static final int LSE_RES_RUSAGE = 88;
+    public static final int LSE_NO_RESOURCE = 89;
+    public static final int LSE_BAD_RESOURCE = 90;
+    public static final int LSE_RES_PARENT = 91;
+    public static final int LSE_NO_PASSWD = 92;
+    public static final int LSE_SUDOERS_CONF = 93;
+    public static final int LSE_SUDOERS_ROOT = 94;
+    public static final int LSE_I18N_SETLC = 95;
+    public static final int LSE_I18N_CATOPEN = 96;
+    public static final int LSE_I18N_NOMEM = 97;
+    public static final int LSE_NO_MEM = 98;
+    public static final int LSE_REGISTRY_SYS = 99;
+    public static final int LSE_FILE_CLOSE = 100;
+    public static final int LSE_LIMCONF_NOTREADY = 101;
+    public static final int LSE_MASTER_LIM_DOWN = 102;
+    public static final int LSE_MLS_INVALID = 103;
+    public static final int LSE_MLS_CLEARANCE = 104;
+    public static final int LSE_MLS_RHOST = 105;
+    public static final int LSE_MLS_DOMINATE = 106;
+    public static final int LSE_NO_CAL = 107;
+    public static final int LSE_NO_NETWORK = 108;
+    public static final int LSE_GETCONF_FAILED = 109;
+    public static final int LSE_TSSINIT = 110;
+    public static final int LSE_DYNM_DENIED = 111;
+    public static final int LSE_LIC_OVERUSE = 112;
+    public static final int LSE_EGOCONF = 113;
+    public static final int LSE_BAD_EGO_ENV = 114;
+    public static final int LSE_EGO_CONF_SYNTAX = 115;
+    public static final int LSE_EGO_GETCONF_FAILED = 116;
+    public static final int LSE_NS_LOOKUP = 117;
+    public static final int LSE_BAD_PASSWD = 118;
+
+    public static final int LSE_UNKWN_USER = 119;
+    public static final int LSE_NOT_WINHOST = 120;
+    public static final int LSE_NOT_MASTERCAND = 121;
+    public static final int LSE_HOST_UNAUTH = 122;
+    public static final int LSE_UNRESOLVALBE_HOST = 123;
+    public static final int LSE_RESOURCE_NOT_CONSUMABLE = 124;
+    public static final int LSE_SHUTDOWN = 125;
+    public static final int LSE_BAD_SYNTAX = 126;
+    public static final int LSE_NERR = 127;
+
+
+    public static boolean LSE_ISBAD_RESREQ(int s) {
+        return (((s) == LSE_BAD_EXP) || ((s) == LSE_UNKWN_RESNAME) || ((s) == LSE_UNKWN_RESVALUE));
+    }
+
+    public static boolean LSE_SYSCALL(int s) {
+        return (((s) == LSE_SELECT_SYS) || ((s) == LSE_CONN_SYS) || ((s) == LSE_FILE_SYS) || ((s) == LSE_MSG_SYS) || ((s) == LSE_SOCK_SYS) || ((s) == LSE_ACCEPT_SYS) || ((s) == LSE_SIG_SYS) || ((s) == LSE_WAIT_SYS) || ((s) == LSE_EXECV_SYS) || ((s) == LSE_LIMIT_SYS) || ((s) == LSE_PIPE) || ((s) == LSE_ESUB) || ((s) == LSE_REGISTRY_SYS) || ((s) == LSE_MISC_SYS));
+    }
+
+
+    /*
+    public static void TIMEVAL (int level, int func, int val)  {
+        if (timinglevel > level) {
+            timeval before, after;
+            timezone tz;
+            gettimeofday(&before, &tz);
+            func;
+            gettimeofday(&after, &tz);
+            val = (int)((after.tv_sec - before.tv_sec)*1000 +  (after.tv_usec-before.tv_usec)/1000);
+        } else {
+            func;
+            val = 0;
+        }
+    }
+    */
+
+    public static class ls_timeval extends Structure {
+        public static class ByReference extends ls_timeval implements Structure.ByReference {}
+        public static class ByValue extends ls_timeval implements Structure.ByValue {}
+        public ls_timeval() {}
+        public ls_timeval(Pointer p) { super(p); read(); }
+
+        public float rtime;
+        public float utime;
+        public float stime;
+    }
+
+
+
+    /*
+    public static void LS_TIMEVAL_ZERO(ls_timeval tv) {                            tv.rtime = 0.0;          tv.utime = 0.0;          tv.stime = 0.0;      }
+
+    public static int LS_TIMEVAL_INC (ls_timeval tv, int newtv) {                                  tv.rtime += newtv.rtime;       tv.utime += newtv.utime;       tv.stime += newtv.stime;      }
+
+    public static void LOG_TIME_MSG(int level, String name, ls_timeval tv, int count, String msg) { if (timinglevel > level) {  ls_syslog(LOG_INFO, "L%d %s rtime %.2f ms, utime %.2f ms, stime %.2f ms, count %d %s",  level, name, tv.rtime, tv.utime, tv.stime, count, msg);  } }; }
+
+    public static void TIMEIT (int level, String func, String name) {
+        if  (timinglevel > level && clockticks > 0) {
+            timeval _before, _after;
+            timezone _tz;
+            tms _buf, _buf2;
+            gettimeofday(&_before, &_tz);
+            times(&_buf);
+            func;
+            gettimeofday(&_after, &_tz);
+            times(&_buf2);
+            ls_syslog(LOG_INFO,"L%d %s rtime %.2f ms, utime %.2f ms, stime %.2f ms",  level,  name,  (_after.tv_sec - _before.tv_sec)*1000.0 +  (_after.tv_usec - _before.tv_usec)/1000.0,  1000.0*((_buf2.tms_utime - _buf.tms_utime)/clockticks),  1000.0*((_buf2.tms_stime - _buf.tms_stime)/clockticks));
+        } else {
+            func;
+        }
+    }
+
+    public static int TIMEVAL2 (int level, String func, ls_timeval tv) {
+        if (timinglevel > level && clockticks > 0) {
+            timeval _before, _after;
+            timezone _tz;
+            tms _buf, _buf2;
+            gettimeofday(&_before, &_tz);
+            times(&_buf);
+            func;
+            gettimeofday(&_after, &_tz);
+            times(&_buf2);
+            tv.rtime = (_after.tv_sec - _before.tv_sec)*1000.0 +  (_after.tv_usec - _before.tv_usec)/1000.0;
+            tv.utime = 1000.0*((_buf2.tms_utime - _buf.tms_utime)/clockticks);
+            tv.stime = 1000.0*((_buf2.tms_stime - _buf.tms_stime)/clockticks);
+        } else {
+            func;
+            tv.rtime = 0.0;
+            tv.utime = 0.0;
+            tv.stime = 0.0;
+        }
+    }
+
+    public static int TIMEIT_START_BLOCK (int level) {
+        tms _buf, _buf2;
+        timeval _before, _after;
+        timezone _tz;
+        if  (timinglevel > level) {
+            gettimeofday(&_before, &_tz);
+            times(&_buf);
+        }
+    }
+
+    public static int TIMEIT_END_BLOCK (int level, String name)  {
+        if  (timinglevel > level) {
+            float rt, ut, st;
+            gettimeofday(&_after, &_tz);
+            times(&_buf2);
+            rt = (_after.tv_sec - _before.tv_sec)*1000.0 +  (_after.tv_usec - _before.tv_usec)/1000.0;
+            ut = 1000.0*((_buf2.tms_utime - _buf.tms_utime)/clockticks);
+            st = 1000.0*((_buf2.tms_stime - _buf.tms_stime)/clockticks);
+            ls_syslog(LOG_INFO,"L%d %s rtime %.2f ms, utime %.2f ms, stime %.2f ms",  level, name, rt, ut, st);
+        }
+    }
+    */
+
+    public static final int LC_SCHED = 0x00000001;
+    public static final int LC_EXEC = 0x00000002;
+    public static final int LC_TRACE = 0x00000004;
+    public static final int LC_COMM = 0x00000008;
+    public static final int LC_XDR = 0x00000010;
+    public static final int LC_CHKPNT = 0x00000020;
+    public static final int LC_LICENCE = 0x00000040;
+    public static final int LC_LICENSE = 0x00000040;
+    public static final int LC_FILE = 0x00000080;
+    public static final int LC_AFS = 0x00000100;
+    public static final int LC_AUTH = 0x00000200;
+    public static final int LC_HANG = 0x00000400;
+    public static final int LC_MULTI = 0x00000800;
+    public static final int LC_SIGNAL = 0x00001000;
+    public static final int LC_DCE = 0x00002000;
+    public static final int LC_PIM = 0x00004000;
+    public static final int LC_MEMORY = 0x00004000;
+    public static final int LC_SYS = 0x00008000;
+    public static final int LC_JLIMIT = 0x00010000;
+    public static final int LC_FAIR = 0x00020000;
+    public static final int LC_PREEMPT = 0x00040000;
+    public static final int LC_PEND = 0x00080000;
+    public static final int LC_EEVENTD = 0x00100000;
+    public static final int LC_LOADINDX = 0x00200000;
+    public static final int LC_RESOURCE = 0x00200000;
+
+    public static final int LC_JGRP = 0x00400000;
+    public static final int LC_JARRAY = 0x00800000;
+    public static final int LC_MPI = 0x01000000;
+    public static final int LC_ELIM = 0x02000000;
+    public static final int LC_M_LOG = 0x04000000;
+    public static final int LC_PERFM = 0x08000000;
+    public static final int LC_DLOG = 0x10000000;
+    public static final int LC_HPC = 0x20000000;
+    public static final int LC_LICSCHED = 0x40000000;
+
+    public static final int LC_XDRVERSION = 0x80000000;
+    public static final int LC_FLEX = 0x80000000;
+
+    public static final int LC_ADVRSV = LC_DLOG;
+    public static final int LC_RESREQ = LC_M_LOG;
+
+
+    public static final int LOG_DEBUG1 = LOG_DEBUG + 1;
+    public static final int LOG_DEBUG2 = LOG_DEBUG + 2;
+    public static final int LOG_DEBUG3 = LOG_DEBUG + 3;
+
+
+    public static final int LSF_EVENT_LIM_DOWN = 1;
+    public static final int LSF_EVENT_RES_DOWN = 2;
+    public static final int LSF_EVENT_SBD_DOWN = 3;
+    public static final int LSF_EVENT_HOST_UNLIC = 4;
+    public static final int LSF_EVENT_MASTER_ELECT = 5;
+    public static final int LSF_EVENT_MASTER_RESIGN = 6;
+    public static final int LSF_EVENT_MBD_UP = 7;
+    public static final int LSF_EVENT_MBD_DOWN = 8;
+    public static final int LSF_EVENT_MBD_RECONFIG = 9;
+    public static final int LSF_EVENT_WORKDIR_FULL = 10;
+    public static final int LSF_EVENT_HOST_OPENED = 11;
+    public static final int LSF_EVENT_HOST_CLOSED = 12;
+    public static final int LSF_EVENT_QUEUE_OPENED = 13;
+    public static final int LSF_EVENT_QUEUE_CLOSED = 14;
+    public static final int LSF_EVENT_SCH_DOWN = 15;
+    public static final int LSF_EVENT_LIC_OVERUSE = 16;
+
+    public static final int LSF_NIOS_REQUEUE = 127;
+
+
+    /*
+    public int lserrno;
+    public int masterLimDown;
+    public int ls_nerr;
+    public String[] ls_errmsg;
+    public int logclass;
+    public int timinglevel;
+    public int clockticks;
+
+
+    public int lsf_lim_version;
+    */
+
+
+    public static native int ls_readconfenv(config_param config_param1, String string);
+
+
+    public static native Pointer ls_placereq(String resreq, IntByReference numhosts, int options, String fromhost);
+
+
+    public static native Pointer ls_placeofhosts(String resreq, IntByReference numhosts, int options, String fromhost, Pointer hostlist, int listsize);
+
+    // NOTE: Not in liblsf
+    //public static native Pointer ls_placeoftype(String resreq, IntByReference numhosts, int options, String fromhost, String hosttype);
+
+
+    public static native hostLoad.ByReference ls_load(String resreq, IntByReference numhosts, int options, String fromhost);
+
+
+    public static native hostLoad.ByReference ls_loadofhosts(String resreq, IntByReference numhosts, int options, String fromhost, Pointer hostlist, int listsize);
+
+    // NOTE: Not in liblsf
+    //public static native hostLoad.ByReference ls_loadoftype(String resreq, IntByReference numhosts, int options, String fromhost, String hosttype);
+
+
+    public static native hostLoad.ByReference ls_loadinfo(String resreq, IntByReference numhosts, int options, String fromhost, Pointer hostlist, int listsize, Pointer indxnamelist);
+
+
+    public static native int ls_loadadj(String resreq, placeInfo hostlist, int listsize);
+
+
+    public static native int ls_eligible(String task, String resreqstr, byte mode);
+
+
+    public static native String ls_resreq(String task);
+
+
+    public static native int ls_insertrtask(String task);
+
+
+    public static native int ls_insertltask(String task);
+
+
+    public static native int ls_deletertask(String task);
+
+
+    public static native int ls_deleteltask(String task);
+
+
+    public static native int ls_listrtask(Pointer taskList, int sortflag);
+
+
+    public static native int ls_listltask(Pointer taskList, int sortflag);
+
+
+    public static native Pointer ls_findmyconnections();
+
+
+    public static native int ls_isconnected(String hostName);
+
+    // NOTE: Not in liblsf
+    //public static native int ls_lostconnection();
+
+
+    public static native String ls_getclustername();
+
+
+    public static native clusterInfo.ByReference ls_clusterinfo(String string1, IntByReference int1, Pointer stringArray1, int int2, int int3);
+
+
+    public static native lsSharedResourceInfo.ByReference ls_sharedresourceinfo(Pointer stringArray1, IntByReference int1, String string1, int int2);
+
+
+    public static native String ls_getmastername();
+
+
+    public static native String ls_getmyhostname();
+
+
+    public static native String ls_getmyhostname2();
+
+
+    public static native hostInfo.ByReference ls_gethostinfo(String string1, IntByReference int1, Pointer stringArray1, int int2, int int3);
+
+    public static native String ls_getISVmode();
+
+    public static native int ls_isshutdown();
+
+    public static native int ls_isPartialLicensingEnabled();
+
+    /* NOTE: ls_getLicenseUsage() is not supported by LSF v8.x
+    *  Wei Xing, ICR
+    */
+//    public static native lsfLicUsage.ByReference ls_getLicenseUsage();
+
+    public static native lsInfo.ByReference ls_info();
+
+    public static native Pointer ls_indexnames(lsInfo lsInfo1);
+
+    public static native int ls_isclustername(String string);
+
+
+    public static native String ls_gethosttype(String hostname);
+
+
+    public static native FloatByReference ls_getmodelfactor(String modelname);
+
+
+    public static native FloatByReference ls_gethostfactor(String hostname);
+
+
+    public static native String ls_gethostmodel(String hostname);
+
+    // NOTE: Not in liblsf
+    //public static native IntByReference ls_gethostrespriority(String hostname);
+
+
+    public static native int ls_lockhost(NativeLong duration);
+
+
+    public static native int ls_unlockhost();
+
+
+    public static native int ls_limcontrol(String hostname, int opCode);
+
+    public static native void ls_remtty(int ind, int enableIntSus);
+
+    public static native void ls_loctty(int ind);
+
+
+    public static native String ls_sysmsg();
+
+
+    public static native void ls_perror(String usrMsg);
+
+
+    public static native lsConf.ByReference ls_getconf(String string);
+
+    public static native void ls_freeconf(lsConf lsConf1);
+
+    public static native sharedConf.ByReference ls_readshared(String string1);
+
+    public static native clusterConf.ByReference ls_readcluster(String string1, lsInfo lsInfo1);
+
+    public static native clusterConf.ByReference ls_readcluster_ex(String string1, lsInfo lsInfo1, int int1);
+
+
+    public static native int _ls_initdebug(String appName);
+
+    public static native void ls_syslog(int level, String fmt, Pointer args);
+
+    public static native void ls_errlog(Pointer fp, String fmt, Pointer args);
+
+    // NOTE: va_list is too compiler specific.  Skipping this function.
+    //public static native void  ls_verrlog (Pointer fp, String fmt, va_list ap);
+
+    public static native int ls_fdbusy(int fd);
+
+
+    public static native String ls_getmnthost(String fn);
+
+    public static native int ls_servavail(int int1, int int2);
+
+    public static native int ls_getpriority(IntByReference priority);
+
+    public static native int ls_setpriority(int newPriority);
+
+    public static native void ls_ruunix2lsf(rusage rusage, lsfRusage lsfRusage);
+
+    public static native void ls_rulsf2unix(lsfRusage lsfRusage, rusage rusage);
+
+    public static native void cleanLsfRusage(lsfRusage lsfRusage1);
+
+    public static native void cleanRusage(rusage rusage1);
+
+
+    // NOTE: Not in liblsf
+    //public static native int getBEtime(String string1, byte byte1, NativeLongByReference long1);
+
+
+    public static native int ls_postevent(int int1, String string1, Pointer stringArray1, int int2);
+
+    public static native int ls_postmultievent(int int1, String string1, Pointer stringArray1, int int2, int int3);
+
+    public static class extResInfo extends Structure {
+        public static class ByReference extends extResInfo implements Structure.ByReference {}
+        public static class ByValue extends extResInfo implements Structure.ByValue {}
+        public extResInfo() {}
+        public extResInfo(Pointer p) { super(p); read(); }
+
+        public String name;
+        public String type;
+        public String interval;
+        public String increasing;
+        public String des;
+    }
+
+
+
+
+    // NOTE: Not in liblsf
+    //public static native int lim_vcl_get_eres_version();
+
+    // NOTE: Not in liblsf
+    //public static native extResInfo.ByReference lim_vcl_get_eres_def(String string1);
+
+    // NOTE: Not in liblsf
+    //public static native String lim_vcl_get_eres_loc(String string1);
+
+    // NOTE: Not in liblsf
+    //public static native String lim_vcl_get_eres_val(String string1);
+
+
+    public static int isspace(byte c) {
+        return ((c == 0x20 || c == 0x09 || c == 0x0a || c == 0x0b || c == 0x0c || c == 0x0d) ? 8 : 0);
+    }
+
+    public static final int LSF_VERSION = LSF_XDR_VERSION7_0_EP6;
+    public static final String LSF_CURRENT_VERSION = "7.06";
+
+
+    public static final String LSF_PRODUCT_COPYRIGHT_STR = "Copyright 1992-2009 Platform Computing Corp.";
+
+
+    public static final String LSF_NAME_STR = "Platform LSF";
+    public static final String LSF_IDENTIFIER_STR = "";
+    public static final String LSF_PRODUCT_NAME_STR = LSF_NAME_STR + LSF_IDENTIFIER_STR;
+
+
+    public static final String LSF_PRODUCT_COMMENT_STR = "";
+
+
+    public static final String LSF_PRODUCT_BUILD_STR = "";
+
+
+    public static final String LSF_PRODUCT_BUILD_DATE_STR = "";
+
+
+    public static final int LSF_PRODUCT_MAJOR_VERSION = 7;
+    public static final int LSF_PRODUCT_MINOR_VERSION = 0;
+    public static final int LSF_PRODUCT_MAINTAIN_VERSION = 6;
+
+    public static final String LSF_PRODUCT_MAJOR_VERSION_STR = "7";
+    public static final String LSF_PRODUCT_MINOR_VERSION_STR = "0";
+    public static final String LSF_PRODUCT_MAINTAIN_VERSION_STR = "6";
+
+    public static final String LSF_PRODUCT_VERSION_STR = LSF_PRODUCT_MAJOR_VERSION_STR + "." + LSF_PRODUCT_MINOR_VERSION_STR + "." + LSF_PRODUCT_MAINTAIN_VERSION_STR;
+    public static final String LSF_FILE_VERSION_STR = LSF_PRODUCT_MAJOR_VERSION_STR + "." + LSF_PRODUCT_MINOR_VERSION_STR + "." + LSF_PRODUCT_MAINTAIN_VERSION_STR;
+
+
+    public static final String _VERSION_STR_LSID_ = "Platform LSF HPC 7";
+    public static final String _LSID_VERSION_ = (_VERSION_STR_LSID_ + " Update " + _MINOR_STR_ + ", " + _DATE_STR_ + "\nCopyright 1992-2009 Platform Computing Corporation\n");
+
+
+    /* Removing since the ls_nio functions which use fd_set, etc. are not in liblsf.
+
+    public static final int NIO_STDIN_ON = 0x01;
+    public static final int NIO_STDIN_OFF = 0x02;
+    public static final int NIO_TAGSTDOUT_ON = 0x03;
+    public static final int NIO_TAGSTDOUT_OFF = 0x04;
+
+    public static final int NIO_TASK_STDINON = 0x01;
+    public static final int NIO_TASK_STDINOFF = 0x02;
+    public static final int NIO_TASK_ALL = 0x03;
+    public static final int NIO_TASK_CONNECTED = 0x04;
+
+    public static interface nioType {
+          public static final int NIO_STATUS = 0;
+          public static final int NIO_STDOUT = 1;
+          public static final int NIO_EOF = 2;
+          public static final int NIO_IOERR = 3;
+          public static final int NIO_REQUEUE = 4;
+          public static final int NIO_STDERR = 5;
+    }
+
+
+
+    public static class nioEvent extends Structure {
+        public static class ByReference extends nioEvent implements Structure.ByReference {}
+        public static class ByValue extends nioEvent implements Structure.ByValue {}
+        public nioEvent() {}
+        public nioEvent(Pointer p) { super(p); read(); }
+
+        public int tid;
+        public *//*nioType*//* int type;
+        public int status;
+    }
+
+
+
+    public static class nioInfo extends Structure {
+        public static class ByReference extends nioInfo implements Structure.ByReference {}
+        public static class ByValue extends nioInfo implements Structure.ByValue {}
+        public nioInfo() {}
+        public nioInfo(Pointer p) { super(p); read(); }
+
+        public int num;
+        public Pointer / * nioEvent.ByReference * / ioTask;
+    }
+
+
+    public static final int FD_SETSIZE = 64;
+
+    public static class fd_set extends Structure {
+        public static class ByReference extends fd_set implements Structure.ByReference {}
+        public static class ByValue extends fd_set implements Structure.ByValue {}
+        public fd_set() {}
+        public fd_set(Pointer p) { super(p); read(); }
+
+        public int count;
+        public int[] fd = new int[FD_SETSIZE];
+    }
+    */
+
+    public static native int ls_initdebug(String appName);
+
+    // NOTE: Not in liblsf
+    //public static native int ls_nioinit(int sock);
+
+    // NOTE: Not in liblsf
+    //public static native int ls_nioselect(int int1, fd_set fd_set1, fd_set fd_set2, fd_set fd_set3, Pointer nioInfoArray1, timeval timeval1);
+
+    // NOTE: Not in liblsf
+    //public static native int ls_nioctl(int int1, int int2);
+
+    // NOTE: Not in liblsf
+    //public static native int ls_nionewtask(int int1, int int2);
+
+    // NOTE: Not in liblsf
+    //public static native int ls_nioremovetask(int int1);
+
+    // NOTE: Not in liblsf
+    //public static native int ls_niowrite(String string1, int int1);
+
+    // NOTE: Not in liblsf
+    //public static native int ls_nioclose();
+
+    // NOTE: Not in liblsf
+    //public static native int ls_nioread(int int1, String string1, int int2);
+
+    // NOTE: Not in liblsf
+    //public static native int ls_niotasks(int int1, IntByReference int2, int int3);
+
+    // NOTE: Not in liblsf
+    //public static native int ls_niostatus(int int1, IntByReference int2, rusage rusage1);
+
+    // NOTE: Not in liblsf
+    //public static native int ls_niokill(int int1);
+
+    // NOTE: Not in liblsf
+    //public static native int ls_niosetdebug(int int2);
+
+    // NOTE: Not in liblsf
+    //public static native int ls_niodump(int int1, int int2, int int3, String string1);
+
+
+    public int lsf_res_version;
+
+
+    public static native int ls_initrex(int a, int b);
+
+    public static int ls_init(int a, int b) {
+        return ls_initrex(a, b);
+    }
+
+
+    public static native int ls_donerex();
+
+    public static native int ls_niossync(int int1);
+
+
+    public static native int ls_setstdin(int on, IntByReference rpidlist, int len);
+
+
+    public static native int ls_getstdin(int on, IntByReference rpidlist, int maxlen);
+
+    public static native int ls_setstdout(int on, String format);
+
+
+    public static native int ls_stdinmode(int onoff);
+
+
+    public static native int ls_stoprex();
+
+
+    public static native int ls_chdir(String string1, String string2);
+
+
+    public static native int ls_connect(String string1);
+
+
+    public static native int ls_rkill(int int1, int int2);
+
+
+    public static native int ls_rsetenv(String host, Pointer env);
+
+    public static native int ls_rsetenv_async(String host, Pointer env);
+
+
+    public static native int ls_rescontrol(String host, int opcode, int options);
+
+
+    public static native lsfAcctRec.ByReference ls_getacctrec(Pointer pointer1, IntByReference int1);
+
+    public static native int ls_putacctrec(Pointer pointer1, lsfAcctRec lsfAcctRec1);
+
+
+    // NOTE: No idea what resLogRecord is.
+    //public static native resLogRecord.ByReference ls_readrexlog (Pointer );
+
+
+    public static native int ls_rexecv(String string1, Pointer string2, int int1);
+
+
+    public static native int ls_rexecve(String string1, Pointer stringArray1, int int1, Pointer stringArray2);
+
+    public static native int ls_rexecv2(String string1, Pointer stringArray1, int int1);
+
+    public static native int ls_startserver(String string1, Pointer stringArray1, int int1);
+
+
+    public static native int ls_rtask(String string1, Pointer stringArray1, int int1);
+
+
+    public static native int ls_rtaske(String string1, Pointer stringArray1, int int1, Pointer stringArray2);
+
+    public static native int ls_rtask2(String string1, Pointer stringArray1, int int1, Pointer stringArray2);
+
+
+    public static native int ls_rwait(IntByReference int1, int int2, rusage rusage1);
+
+
+    public static native int ls_rwaittid(int int1, IntByReference int2, int int3, rusage rusage1);
+
+
+    public static native int ls_conntaskport(int tid);
+
+
+    public static native int ls_ropen(String host, String fn, int flags, int mode);
+
+
+    public static native int ls_rclose(int rfd);
+
+
+    public static native int ls_rwrite(int rfd, String buf, int len);
+
+
+    public static native int ls_rread(int rfd, String buf, int len);
+
+
+    public static native NativeLong ls_rlseek(int rfd, NativeLong offset, int whence);
+
+
+    public static native int ls_runlink(String host, String fn);
+
+    public static native int ls_rfstat(int rfd, Pointer buf);
+
+    public static native int ls_rstat(String host, String fn, Pointer buf);
+
+
+    public static native String ls_rgetmnthost(String host, String fn);
+
+
+    public static native int ls_rfcontrol(int command, int arg);
+
+
+    public static native int ls_rfterminate(String host);
+}
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/locusiterator/AlignmentStateMachine.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/locusiterator/AlignmentStateMachine.java
new file mode 100644
index 0000000..f940386
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/locusiterator/AlignmentStateMachine.java
@@ -0,0 +1,370 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.utils.locusiterator;
+
+import com.google.java.contract.Ensures;
+import com.google.java.contract.Invariant;
+import com.google.java.contract.Requires;
+import htsjdk.samtools.Cigar;
+import htsjdk.samtools.CigarElement;
+import htsjdk.samtools.CigarOperator;
+import org.broadinstitute.gatk.utils.GenomeLoc;
+import org.broadinstitute.gatk.utils.GenomeLocParser;
+import org.broadinstitute.gatk.utils.exceptions.UserException;
+import org.broadinstitute.gatk.utils.pileup.PileupElement;
+import org.broadinstitute.gatk.utils.sam.GATKSAMRecord;
+
+/**
+ * Steps a single read along its alignment to the genome
+ *
+ * The logical model for generating extended events is as follows: the "record state"
+ * implements the traversal along the reference; thus stepForwardOnGenome() returns
+ * on every and only on actual reference bases. This can be a (mis)match or a deletion
+ * (in the latter case, we still return on every individual reference base the deletion spans).
+ *
+ * User: depristo
+ * Date: 1/5/13
+ * Time: 1:08 PM
+ */
+ at Invariant({
+        "nCigarElements >= 0",
+        "cigar != null",
+        "read != null",
+        "currentCigarElementOffset >= -1",
+        "currentCigarElementOffset <= nCigarElements"
+})
+public class AlignmentStateMachine {
+    /**
+     * Our read
+     */
+    private final GATKSAMRecord read;
+    private final Cigar cigar;
+    private final int nCigarElements;
+    private int currentCigarElementOffset = -1;
+
+    /**
+     * how far are we offset from the start of the read bases?
+     */
+    private int readOffset;
+
+    /**
+     * how far are we offset from the alignment start on the genome?
+     */
+    private int genomeOffset;
+
+    /**
+     * Our cigar element
+     */
+    private CigarElement currentElement;
+
+    /**
+     * how far are we into our cigarElement?
+     */
+    private int offsetIntoCurrentCigarElement;
+
+    @Requires({"read != null", "read.getAlignmentStart() != -1", "read.getCigar() != null"})
+    public AlignmentStateMachine(final GATKSAMRecord read) {
+        this.read = read;
+        this.cigar = read.getCigar();
+        this.nCigarElements = cigar.numCigarElements();
+        initializeAsLeftEdge();
+    }
+
+    /**
+     * Initialize the state variables to put this machine one bp before the
+     * start of the alignment, so that a call to stepForwardOnGenome() will advance
+     * us to the first proper location
+     */
+    @Ensures("isLeftEdge()")
+    private void initializeAsLeftEdge() {
+        readOffset = offsetIntoCurrentCigarElement = genomeOffset = -1;
+        currentElement = null;
+    }
+
+    /**
+     * Get the read we are aligning to the genome
+     * @return a non-null GATKSAMRecord
+     */
+    @Ensures("result != null")
+    public GATKSAMRecord getRead() {
+        return read;
+    }
+
+    /**
+     * Get the reference index of the underlying read
+     *
+     * @return the reference index of the read
+     */
+    @Ensures("result == getRead().getReferenceIndex()")
+    public int getReferenceIndex() {
+        return getRead().getReferenceIndex();
+    }
+
+    /**
+     * Is this the left edge state?  I.e., one that is before or after the current read?
+     * @return true if this state is an edge state, false otherwise
+     */
+    public boolean isLeftEdge() {
+        return readOffset == -1;
+    }
+
+    /**
+     * Are we on the right edge?  I.e., is the current state off the right of the alignment?
+     * @return true if off the right edge, false if otherwise
+     */
+    public boolean isRightEdge() {
+        return readOffset == read.getReadLength();
+    }
+
+    /**
+     * What is our current offset in the read's bases that aligns us with the reference genome?
+     *
+     * @return the current read offset position.  If an edge will be == -1
+     */
+    @Ensures("result >= -1")
+    public int getReadOffset() {
+        return readOffset;
+    }
+
+    /**
+     * What is the current offset w.r.t. the alignment state that aligns us to the readOffset?
+     *
+     * @return the current offset from the alignment start on the genome.  If this state is
+     * at the left edge the result will be -1;
+     */
+    @Ensures("result >= -1")
+    public int getGenomeOffset() {
+        return genomeOffset;
+    }
+
+    /**
+     * Get the position (1-based as standard) of the current alignment on the genome w.r.t. the read's alignment start
+     * @return the position on the genome of the current state in absolute coordinates
+     */
+    @Ensures("result > 0")
+    public int getGenomePosition() {
+        return read.getAlignmentStart() + getGenomeOffset();
+    }
+
+    /**
+     * Gets #getGenomePosition but as a 1 bp GenomeLoc
+     * @param genomeLocParser the parser to use to create the genome loc
+     * @return a non-null genome location with start position of getGenomePosition
+     */
+    @Requires("genomeLocParser != null")
+    @Ensures("result != null")
+    public GenomeLoc getLocation(final GenomeLocParser genomeLocParser) {
+        // TODO -- may return wonky results if on an edge (could be 0 or could be beyond genome location)
+        return genomeLocParser.createGenomeLoc(read.getReferenceName(), getGenomePosition());
+    }
+
+    /**
+     * Get the cigar element we're currently aligning with.
+     *
+     * For example, if the cigar string is 2M2D2M and we're in the second step of the
+     * first 2M, then this function returns the element 2M.  After calling stepForwardOnGenome
+     * this function would return 2D.
+     *
+     * @return the cigar element, or null if we're the left edge
+     */
+    @Ensures("result != null || isLeftEdge() || isRightEdge()")
+    public CigarElement getCurrentCigarElement() {
+        return currentElement;
+    }
+
+    /**
+     * Get the offset of the current cigar element among all cigar elements in the read
+     *
+     * Suppose our read's cigar is 1M2D3M, and we're at the first 1M.  This would
+     * return 0.  Stepping forward puts us in the 2D, so our offset is 1.  Another
+     * step forward would result in a 1 again (we're in the second position of the 2D).
+     * Finally, one more step forward brings us to 2 (for the 3M element)
+     *
+     * @return the offset of the current cigar element in the reads's cigar.  Will return -1 for
+     * when the state is on the left edge, and be == the number of cigar elements in the
+     * read when we're past the last position on the genome
+     */
+    @Ensures({"result >= -1", "result <= nCigarElements"})
+    public int getCurrentCigarElementOffset() {
+        return currentCigarElementOffset;
+    }
+
+    /**
+     * Get the offset of the current state into the current cigar element
+     *
+     * That is, suppose we have a read with cigar 2M3D4M, and we're right at
+     * the second M position.  offsetIntoCurrentCigarElement would be 1, as
+     * it's two elements into the 2M cigar.  Now stepping forward we'd be
+     * in cigar element 3D, and our offsetIntoCurrentCigarElement would be 0.
+     *
+     * @return the offset (from 0) of the current state in the current cigar element.
+     *  Will be 0 on the right edge, and -1 on the left.
+     */
+    @Ensures({"result >= 0 || (result == -1 && isLeftEdge())", "!isRightEdge() || result == 0"})
+    public int getOffsetIntoCurrentCigarElement() {
+        return offsetIntoCurrentCigarElement;
+    }
+
+    /**
+     * Convenience accessor of the CigarOperator of the current cigar element
+     *
+     * Robust to the case where we're on the edge, and currentElement is null, in which
+     * case this function returns null as well
+     *
+     * @return null if this is an edge state
+     */
+    @Ensures("result != null || isLeftEdge() || isRightEdge()")
+    public CigarOperator getCigarOperator() {
+        return currentElement == null ? null : currentElement.getOperator();
+    }
+
+    @Override
+    public String toString() {
+        return String.format("%s ro=%d go=%d cec=%d %s", read.getReadName(), readOffset, genomeOffset, offsetIntoCurrentCigarElement, currentElement);
+    }
+
+    // -----------------------------------------------------------------------------------------------
+    //
+    // Code for setting up prev / next states
+    //
+    // -----------------------------------------------------------------------------------------------
+
+    /**
+     * Step the state machine forward one unit
+     *
+     * Takes the current state of this machine, and advances the state until the next on-genome
+     * cigar element (M, X, =, D) is encountered, at which point this function returns with the
+     * cigar operator of the current element.
+     *
+     * Assumes that the AlignmentStateMachine is in the left edge state at the start, so that
+     * stepForwardOnGenome() can be called to move the machine to the first alignment position.  That
+     * is, the normal use of this code is:
+     *
+     * AlignmentStateMachine machine = new AlignmentStateMachine(read)
+     * machine.stepForwardOnGenome()
+     * // now the machine is at the first position on the genome
+     *
+     * When stepForwardOnGenome() advances off the right edge of the read, the state machine is
+     * left in a state such that isRightEdge() returns true and returns null, indicating the
+     * the machine cannot advance further.  The machine may explode, though this is not contracted,
+     * if stepForwardOnGenome() is called after a previous call returned null.
+     *
+     * @return the operator of the cigar element that machine stopped at, null if we advanced off the end of the read
+     */
+    @Ensures("result != null || isRightEdge()")
+    public CigarOperator stepForwardOnGenome() {
+        // loop until we either find a cigar element step that moves us one base on the genome, or we run
+        // out of cigar elements
+        while ( true ) {
+            // we enter this method with readOffset = index of the last processed base on the read
+            // (-1 if we did not process a single base yet); this can be last matching base,
+            // or last base of an insertion
+            if (currentElement == null || (offsetIntoCurrentCigarElement + 1) >= currentElement.getLength()) {
+                currentCigarElementOffset++;
+                if (currentCigarElementOffset < nCigarElements) {
+                    currentElement = cigar.getCigarElement(currentCigarElementOffset);
+                    offsetIntoCurrentCigarElement = -1;
+                    // next line: guards against cigar elements of length 0; when new cigar element is retrieved,
+                    // we reenter in order to re-check offsetIntoCurrentCigarElement against currentElement's length
+                    continue;
+                } else {
+                    if (currentElement != null && currentElement.getOperator() == CigarOperator.D)
+                        throw new UserException.MalformedBAM(read, "read ends with deletion. Cigar: " + read.getCigarString() + ". Although the SAM spec technically permits such reads, this is often indicative of malformed files. If you are sure you want to use this file, re-run your analysis with the extra option: -rf BadCigar");
+
+                    // we're done, so set the offset of the cigar to 0 for cleanliness, as well as the current element
+                    offsetIntoCurrentCigarElement = 0;
+                    readOffset = read.getReadLength();
+                    currentElement = null;
+
+                    // Reads that contain indels model the genomeOffset as the following base in the reference.  Because
+                    // we fall into this else block only when indels end the read, increment genomeOffset  such that the
+                    // current offset of this read is the next ref base after the end of the indel.  This position will
+                    // model a point on the reference somewhere after the end of the read.
+                    genomeOffset++; // extended events need that. Logically, it's legal to advance the genomic offset here:
+
+                    // we do step forward on the ref, and by returning null we also indicate that we are past the read end.
+                    return null;
+                }
+            }
+
+            offsetIntoCurrentCigarElement++;
+            boolean done = false;
+            switch (currentElement.getOperator()) {
+                case H: // ignore hard clips
+                case P: // ignore pads
+                    offsetIntoCurrentCigarElement = currentElement.getLength();
+                    break;
+                case I: // insertion w.r.t. the reference
+                case S: // soft clip
+                    offsetIntoCurrentCigarElement = currentElement.getLength();
+                    readOffset += currentElement.getLength();
+                    break;
+                case D: // deletion w.r.t. the reference
+                    if (readOffset < 0)             // we don't want reads starting with deletion, this is a malformed cigar string
+                        throw new UserException.MalformedBAM(read, "read starts with deletion. Cigar: " + read.getCigarString() + ". Although the SAM spec technically permits such reads, this is often indicative of malformed files. If you are sure you want to use this file, re-run your analysis with the extra option: -rf BadCigar");
+                    // should be the same as N case
+                    genomeOffset++;
+                    done = true;
+                    break;
+                case N: // reference skip (looks and gets processed just like a "deletion", just different logical meaning)
+                    genomeOffset++;
+                    done = true;
+                    break;
+                case M:
+                case EQ:
+                case X:
+                    readOffset++;
+                    genomeOffset++;
+                    done = true;
+                    break;
+                default:
+                    throw new IllegalStateException("Case statement didn't deal with cigar op: " + currentElement.getOperator());
+            }
+
+            if ( done )
+                return currentElement.getOperator();
+        }
+    }
+
+    /**
+     * Create a new PileupElement based on the current state of this element
+     *
+     * Must not be a left or right edge
+     *
+     * @return a pileup element
+     */
+    @Ensures("result != null")
+    public final PileupElement makePileupElement() {
+        if ( isLeftEdge() || isRightEdge() )
+            throw new IllegalStateException("Cannot make a pileup element from an edge alignment state");
+        return new PileupElement(read,
+                getReadOffset(),
+                getCurrentCigarElement(),
+                getCurrentCigarElementOffset(),
+                getOffsetIntoCurrentCigarElement());
+    }
+}
+
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/locusiterator/LIBSDownsamplingInfo.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/locusiterator/LIBSDownsamplingInfo.java
new file mode 100644
index 0000000..01bf17d
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/locusiterator/LIBSDownsamplingInfo.java
@@ -0,0 +1,51 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.utils.locusiterator;
+
+/**
+ * Simple wrapper about the information LIBS needs about downsampling
+ *
+ * User: depristo
+ * Date: 1/5/13
+ * Time: 1:26 PM
+ */
+class LIBSDownsamplingInfo {
+    final private boolean performDownsampling;
+    final private int toCoverage;
+
+    public LIBSDownsamplingInfo(boolean performDownsampling, int toCoverage) {
+        this.performDownsampling = performDownsampling;
+        this.toCoverage = toCoverage;
+    }
+
+    public boolean isPerformDownsampling() {
+        return performDownsampling;
+    }
+
+    public int getToCoverage() {
+        return toCoverage;
+    }
+}
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/locusiterator/LIBSPerformance.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/locusiterator/LIBSPerformance.java
new file mode 100644
index 0000000..d9b158f
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/locusiterator/LIBSPerformance.java
@@ -0,0 +1,198 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.utils.locusiterator;
+
+import htsjdk.samtools.reference.IndexedFastaSequenceFile;
+import htsjdk.samtools.SAMFileHeader;
+import htsjdk.samtools.SAMFileReader;
+import htsjdk.samtools.SAMReadGroupRecord;
+import htsjdk.samtools.SAMRecordIterator;
+import org.apache.log4j.Logger;
+import org.broadinstitute.gatk.utils.commandline.Argument;
+import org.broadinstitute.gatk.utils.commandline.CommandLineProgram;
+import org.broadinstitute.gatk.utils.commandline.Input;
+import org.broadinstitute.gatk.engine.ReadProperties;
+import org.broadinstitute.gatk.engine.contexts.AlignmentContext;
+import org.broadinstitute.gatk.engine.iterators.GATKSAMRecordIterator;
+import org.broadinstitute.gatk.utils.*;
+import org.broadinstitute.gatk.utils.fasta.CachingIndexedFastaSequenceFile;
+import org.broadinstitute.gatk.utils.sam.ArtificialSAMUtils;
+import org.broadinstitute.gatk.utils.sam.GATKSAMRecord;
+import org.broadinstitute.gatk.utils.sam.GATKSamRecordFactory;
+
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.util.*;
+
+/**
+ * Caliper microbenchmark of fragment pileup
+ */
+public class LIBSPerformance extends CommandLineProgram {
+    private static Logger logger = Logger.getLogger(LIBSPerformance.class);
+
+    @Input(fullName = "input_file", shortName = "I", doc = "SAM or BAM file(s)", required = true)
+    public File samFile = null;
+
+    @Input(fullName = "reference_sequence", shortName = "R", doc = "Reference sequence file", required = true)
+    public File referenceFile = null;
+
+    @Argument(fullName = "L", shortName = "L", doc = "Query location", required = false)
+    public String location = null;
+
+    @Argument(fullName = "dt", shortName = "dt", doc = "Enable downsampling", required = false)
+    public boolean downsample = false;
+
+    @Override
+    public int execute() throws IOException {
+        final IndexedFastaSequenceFile reference = new CachingIndexedFastaSequenceFile(referenceFile);
+        final GenomeLocParser genomeLocParser = new GenomeLocParser(reference);
+
+        final SAMFileReader reader = new SAMFileReader(samFile);
+        reader.setSAMRecordFactory(new GATKSamRecordFactory());
+
+        SAMRecordIterator rawIterator;
+        if ( location == null )
+            rawIterator = reader.iterator();
+        else {
+            final GenomeLoc loc = genomeLocParser.parseGenomeLoc(location);
+            rawIterator = reader.query(loc.getContig(), loc.getStart(), loc.getStop(), false);
+        }
+
+        final GATKSAMRecordIterator iterator = new GATKSAMRecordIterator(rawIterator);
+
+        final Set<String> samples = new HashSet<String>();
+        for ( final SAMReadGroupRecord rg : reader.getFileHeader().getReadGroups() )
+            samples.add(rg.getSample());
+
+        final LIBSDownsamplingInfo ds = new LIBSDownsamplingInfo(downsample, 250);
+
+        final LocusIteratorByState libs =
+                new LocusIteratorByState(
+                        iterator,
+                        ds,
+                        true,
+                        genomeLocParser,
+                        samples,
+                        false);
+
+        final SimpleTimer timer = new SimpleTimer().start();
+        int bp = 0;
+        double lastElapsed = 0;
+        while ( libs.hasNext() ) {
+            AlignmentContext context = libs.next();
+            bp++;
+            if ( timer.getElapsedTime() - lastElapsed > 10 ) {
+                logger.info(bp + " iterations at " + context.getLocation());
+                lastElapsed = timer.getElapsedTime();
+            }
+        }
+        logger.info(String.format("runtime in seconds: %.2f", timer.getElapsedTime()));
+
+        return 0;
+    }
+
+//    private void syntheticTests() {
+//        final int readLength = 101;
+//        final int nReads = 10000;
+//        final int locus = 1;
+//
+//        SAMFileHeader header = ArtificialSAMUtils.createArtificialSamHeader(1, 1, 1000);
+//        final GenomeLocParser genomeLocParser = new GenomeLocParser(header.getSequenceDictionary());
+//
+//        int nIterations = 0;
+//        for ( final String cigar : Arrays.asList("101M", "50M10I40M", "50M10D40M") ) {
+//            GATKSAMRecord read = ArtificialSAMUtils.createArtificialRead(header, "read", 0, locus, readLength);
+//            read.setReadBases(Utils.dupBytes((byte) 'A', readLength));
+//            final byte[] quals = new byte[readLength];
+//            for ( int i = 0; i < readLength; i++ )
+//                quals[i] = (byte)(i % QualityUtils.MAX_SAM_QUAL_SCORE);
+//            read.setBaseQualities(quals);
+//            read.setCigarString(cigar);
+//
+//            for ( int j = 0; j < nReads; j++ ) {
+//                for ( int i = 0; i < rep; i++ ) {
+//                    switch ( op ) {
+//                        case NEW_STATE:
+//                        {
+//                            final AlignmentStateMachine alignmentStateMachine = new AlignmentStateMachine(read);
+//                            while ( alignmentStateMachine.stepForwardOnGenome() != null ) {
+//                                nIterations++;
+//                            }
+//                        }
+//                        break;
+////                        case OLD_STATE:
+////                        {
+////                            final SAMRecordAlignmentState alignmentStateMachine = new SAMRecordAlignmentState(read);
+////                            while ( alignmentStateMachine.stepForwardOnGenome() != null ) {
+////                                alignmentStateMachine.getRead();
+////                                nIterations++;
+////                            }
+////                        }
+////                        break;
+//                        case NEW_LIBS:
+//                        {
+//                            final List<GATKSAMRecord> reads = Collections.nCopies(30, read);
+//                            final org.broadinstitute.gatk.utils.locusiterator.LocusIteratorByState libs =
+//                                    new org.broadinstitute.gatk.utils.locusiterator.LocusIteratorByState(
+//                                            new LocusIteratorByStateBaseTest.FakeCloseableIterator<GATKSAMRecord>(reads.iterator()),
+//                                            LocusIteratorByStateBaseTest.createTestReadProperties(),
+//                                            genomeLocParser,
+//                                            LocusIteratorByState.sampleListForSAMWithoutReadGroups());
+//
+//                            while ( libs.hasNext() ) {
+//                                AlignmentContext context = libs.next();
+//                            }
+//                        }
+//                    }
+//                }
+//            }
+//        }
+//
+//        System.out.printf("iterations %d%n", nIterations);
+//    }
+
+    /**
+     * Required main method implementation.
+     * @param argv Command-line argument text.
+     * @throws Exception on error.
+     */
+    public static void main(String[] argv) throws Exception {
+        int returnCode = 0;
+        try {
+            LIBSPerformance instance = new LIBSPerformance();
+            start(instance, argv);
+            returnCode = 0;
+        } catch(Exception ex) {
+            returnCode = 1;
+            ex.printStackTrace();
+            throw ex;
+        } finally {
+            System.exit(returnCode);
+        }
+    }
+
+}
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/locusiterator/LocusIterator.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/locusiterator/LocusIterator.java
new file mode 100644
index 0000000..72764e4
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/locusiterator/LocusIterator.java
@@ -0,0 +1,62 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.utils.locusiterator;
+
+import htsjdk.samtools.util.CloseableIterator;
+import org.broadinstitute.gatk.engine.contexts.AlignmentContext;
+
+import java.util.Iterator;
+
+/**
+ * Iterator that traverses a SAM File, accumulating information on a per-locus basis
+ */
+public abstract class LocusIterator implements Iterable<AlignmentContext>, CloseableIterator<AlignmentContext> {
+    public Iterator<AlignmentContext> iterator() {
+        return this;
+    }
+
+    public void close() {
+        //this.it.close();
+    }
+
+    public abstract boolean hasNext();
+    public abstract AlignmentContext next();
+
+    /**
+     * Get, if possible, the underlying LocusIteratorByState from this LocusIterator.
+     *
+     * @throws UnsupportedOperationException if we don't support this operation
+     *
+     * @return a non-null locus iterator by state
+     */
+    public LocusIteratorByState getLIBS() {
+        throw new UnsupportedOperationException("This locus iterator does not support getting the underlying LocusIteratorByState");
+    }
+
+    public void remove() {
+        throw new UnsupportedOperationException("Can not remove records from a SAM file via an iterator!");
+    }
+}
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/locusiterator/LocusIteratorByState.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/locusiterator/LocusIteratorByState.java
new file mode 100644
index 0000000..aaf6190
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/locusiterator/LocusIteratorByState.java
@@ -0,0 +1,454 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.utils.locusiterator;
+
+import com.google.java.contract.Ensures;
+import com.google.java.contract.Requires;
+import htsjdk.samtools.CigarOperator;
+import htsjdk.samtools.SAMFileReader;
+import htsjdk.samtools.SAMRecord;
+import htsjdk.samtools.util.CloseableIterator;
+import org.apache.log4j.Logger;
+import org.broadinstitute.gatk.engine.ReadProperties;
+import org.broadinstitute.gatk.engine.contexts.AlignmentContext;
+import org.broadinstitute.gatk.engine.downsampling.DownsampleType;
+import org.broadinstitute.gatk.engine.iterators.GATKSAMRecordIterator;
+import org.broadinstitute.gatk.utils.GenomeLoc;
+import org.broadinstitute.gatk.utils.GenomeLocParser;
+import org.broadinstitute.gatk.utils.SampleUtils;
+import org.broadinstitute.gatk.utils.pileup.PileupElement;
+import org.broadinstitute.gatk.utils.pileup.ReadBackedPileupImpl;
+import org.broadinstitute.gatk.utils.sam.GATKSAMRecord;
+import org.broadinstitute.gatk.utils.sam.ReadUtils;
+
+import java.util.*;
+
+/**
+ * Iterator that traverses a SAM File, accumulating information on a per-locus basis
+ *
+ * Produces AlignmentContext objects, that contain ReadBackedPileups of PileupElements.  This
+ * class has its core job of converting an iterator of ordered SAMRecords into those
+ * RBPs.
+ *
+ * There are a few constraints on required and ensured by LIBS:
+ *
+ * -- Requires the Iterator<GATKSAMRecord> to returns reads in coordinate sorted order, consistent with the ordering
+ * defined by the SAM file format.  That that for performance reasons this constraint isn't actually enforced.
+ * The behavior of LIBS is undefined in the case where the reads are badly ordered.
+ * -- The reads in the ReadBackedPileup are themselves in the order of appearance of the reads from the iterator.
+ * That is, the pileup is ordered in a way consistent with the SAM coordinate ordering
+ * -- Only aligned reads with at least one on-genomic cigar operator are passed on in the pileups.  That is,
+ * unmapped reads or reads that are all insertions (10I) or soft clipped (10S) are not passed on.
+ * -- LIBS can perform per-sample downsampling of a variety of kinds.
+ * -- Because of downsampling there's no guarantee that:
+ *   -- A read that could be aligned to a position will actually occur in the pileup (downsampled away)
+ *   -- A read that appears in a previous pileup that could align to a future position will actually occur
+ *      in that pileup.  That is, a read might show up at position i but be downsampled away in the pileup at j
+ * -- LIBS can optionally capture all of the reads that come off the iterator, before any leveling downsampling
+ * occurs, if requested.  This allows users of LIBS to see both a ReadBackedPileup view of the data as well as
+ * a stream of unique, sorted reads
+ */
+public final class LocusIteratorByState extends LocusIterator {
+    /** Indicates that we shouldn't do any downsampling */
+    public final static LIBSDownsamplingInfo NO_DOWNSAMPLING = new LIBSDownsamplingInfo(false, -1);
+
+    /**
+     * our log, which we want to capture anything from this class
+     */
+    private final static Logger logger = Logger.getLogger(LocusIteratorByState.class);
+
+    // -----------------------------------------------------------------------------------------------------------------
+    //
+    // member fields
+    //
+    // -----------------------------------------------------------------------------------------------------------------
+
+    /**
+     * Used to create new GenomeLocs as needed
+     */
+    private final GenomeLocParser genomeLocParser;
+
+    /**
+     * A complete list of all samples that may come out of the reads.  Must be
+     * comprehensive.
+     */
+    private final ArrayList<String> samples;
+
+    /**
+     * The system that maps incoming reads from the iterator to their pileup states
+     */
+    private final ReadStateManager readStates;
+
+    /**
+     * Should we include reads in the pileup which are aligned with a deletion operator to the reference?
+     */
+    private final boolean includeReadsWithDeletionAtLoci;
+
+    /**
+     * The next alignment context.  A non-null value means that a
+     * context is waiting from hasNext() for sending off to the next next() call.  A null
+     * value means that either hasNext() has not been called at all or that
+     * the underlying iterator is exhausted
+     */
+    private AlignmentContext nextAlignmentContext;
+
+    // -----------------------------------------------------------------------------------------------------------------
+    //
+    // constructors and other basic operations
+    //
+    // -----------------------------------------------------------------------------------------------------------------
+
+    /**
+     * Create a new LocusIteratorByState
+     *
+     * @param samIterator the iterator of reads to process into pileups.  Reads must be ordered
+     *                    according to standard coordinate-sorted BAM conventions
+     * @param readInformation meta-information about how to process the reads (i.e., should we do downsampling?)
+     * @param genomeLocParser used to create genome locs
+     * @param samples a complete list of samples present in the read groups for the reads coming from samIterator.
+     *                This is generally just the set of read group sample fields in the SAMFileHeader.  This
+     *                list of samples may contain a null element, and all reads without read groups will
+     *                be mapped to this null sample
+     */
+    public LocusIteratorByState(final Iterator<GATKSAMRecord> samIterator,
+                                final ReadProperties readInformation,
+                                final GenomeLocParser genomeLocParser,
+                                final Collection<String> samples) {
+        this(samIterator,
+                toDownsamplingInfo(readInformation),
+                readInformation.includeReadsWithDeletionAtLoci(),
+                genomeLocParser,
+                samples,
+                readInformation.keepUniqueReadListInLIBS());
+    }
+
+    /**
+     * Create a new LocusIteratorByState based on a SAMFileReader using reads in an iterator it
+     *
+     * Simple constructor that uses the samples in the reader, doesn't do any downsampling,
+     * and makes a new GenomeLocParser using the reader.  This constructor will be slow(ish)
+     * if you continually invoke this constructor, but it's easy to make.
+     *
+     * @param reader a non-null reader
+     * @param it an iterator from reader that has the reads we want to use to create ReadBackPileups
+     */
+    public LocusIteratorByState(final SAMFileReader reader, final CloseableIterator<SAMRecord> it) {
+        this(new GATKSAMRecordIterator(it),
+                new LIBSDownsamplingInfo(false, 0),
+                true,
+                new GenomeLocParser(reader.getFileHeader().getSequenceDictionary()),
+                SampleUtils.getSAMFileSamples(reader.getFileHeader()),
+                false);
+    }
+
+    /**
+     * Create a new LocusIteratorByState
+     *
+     * @param samIterator the iterator of reads to process into pileups.  Reads must be ordered
+     *                    according to standard coordinate-sorted BAM conventions
+     * @param downsamplingInfo meta-information about how to downsampling the reads
+     * @param genomeLocParser used to create genome locs
+     * @param samples a complete list of samples present in the read groups for the reads coming from samIterator.
+     *                This is generally just the set of read group sample fields in the SAMFileHeader.  This
+     *                list of samples may contain a null element, and all reads without read groups will
+     *                be mapped to this null sample
+     * @param maintainUniqueReadsList if true, we will keep the unique reads from off the samIterator and make them
+     *                                available via the transferReadsFromAllPreviousPileups interface
+     */
+    public LocusIteratorByState(final Iterator<GATKSAMRecord> samIterator,
+                                final LIBSDownsamplingInfo downsamplingInfo,
+                                final boolean includeReadsWithDeletionAtLoci,
+                                final GenomeLocParser genomeLocParser,
+                                final Collection<String> samples,
+                                final boolean maintainUniqueReadsList) {
+        if ( samIterator == null ) throw new IllegalArgumentException("samIterator cannot be null");
+        if ( downsamplingInfo == null ) throw new IllegalArgumentException("downsamplingInfo cannot be null");
+        if ( genomeLocParser == null ) throw new IllegalArgumentException("genomeLocParser cannot be null");
+        if ( samples == null ) throw new IllegalArgumentException("Samples cannot be null");
+
+        // currently the GATK expects this LocusIteratorByState to accept empty sample lists, when
+        // there's no read data.  So we need to throw this error only when samIterator.hasNext() is true
+        if (samples.isEmpty() && samIterator.hasNext()) {
+            throw new IllegalArgumentException("samples list must not be empty");
+        }
+
+        this.genomeLocParser = genomeLocParser;
+        this.includeReadsWithDeletionAtLoci = includeReadsWithDeletionAtLoci;
+        this.samples = new ArrayList<String>(samples);
+        this.readStates = new ReadStateManager(samIterator, this.samples, downsamplingInfo, maintainUniqueReadsList);
+    }
+
+    @Override
+    public Iterator<AlignmentContext> iterator() {
+        return this;
+    }
+
+    /**
+     * Get the current location (i.e., the bp of the center of the pileup) of the pileup, or null if not anywhere yet
+     *
+     * Assumes that read states is updated to reflect the current pileup position, but not advanced to the
+     * next location.
+     *
+     * @return the location of the current pileup, or null if we're after all reads
+     */
+    private GenomeLoc getLocation() {
+        return readStates.isEmpty() ? null : readStates.getFirst().getLocation(genomeLocParser);
+    }
+
+    // -----------------------------------------------------------------------------------------------------------------
+    //
+    // next() routine and associated collection operations
+    //
+    // -----------------------------------------------------------------------------------------------------------------
+
+    /**
+     * Is there another pileup available?
+     * @return
+     */
+    @Override
+    public boolean hasNext() {
+        lazyLoadNextAlignmentContext();
+        return nextAlignmentContext != null;
+    }
+
+    /**
+     * Get the next AlignmentContext available from the reads.
+     *
+     * @return a non-null AlignmentContext of the pileup after to the next genomic position covered by
+     * at least one read.
+     */
+    @Override
+    public AlignmentContext next() {
+        lazyLoadNextAlignmentContext();
+        if (!hasNext())
+            throw new NoSuchElementException("LocusIteratorByState: out of elements.");
+        AlignmentContext currentAlignmentContext = nextAlignmentContext;
+        nextAlignmentContext = null;
+        return currentAlignmentContext;
+    }
+
+    /**
+     * Move this LIBS until we are over position
+     *
+     * Will return null if cannot reach position (because we run out of data in the locus)
+     *
+     * @param position the start position of the AlignmentContext we want back
+     * @param stopAtFirstNonEmptySiteAfterPosition if true, we will stop as soon as we find a context with data with
+     *                                             position >= position, otherwise we will return a null value
+     *                                             and consume the data for the next position.  This means that without
+     *                                             specifying this value the LIBS will be in an indeterminate state
+     *                                             after calling this function, and should be reconstructed from scratch
+     *                                             for subsequent use
+     * @return a AlignmentContext at position, or null if this isn't possible
+     */
+    public AlignmentContext advanceToLocus(final int position, final boolean stopAtFirstNonEmptySiteAfterPosition) {
+        while ( hasNext() ) {
+            final AlignmentContext context = next();
+
+            if ( context == null )
+                // we ran out of data
+                return null;
+
+            if ( context.getPosition() == position )
+                return context;
+
+            if ( context.getPosition() > position)
+                return stopAtFirstNonEmptySiteAfterPosition ? context : null;
+        }
+
+        return null;
+    }
+
+    /**
+     * Creates the next alignment context from the given state.  Note that this is implemented as a
+     * lazy load method. nextAlignmentContext MUST BE null in order for this method to advance to the
+     * next entry.
+     */
+    private void lazyLoadNextAlignmentContext() {
+        while (nextAlignmentContext == null && readStates.hasNext()) {
+            readStates.collectPendingReads();
+
+            final GenomeLoc location = getLocation();
+            final Map<String, ReadBackedPileupImpl> fullPileup = new HashMap<String, ReadBackedPileupImpl>();
+
+            for (final Map.Entry<String, PerSampleReadStateManager> sampleStatePair : readStates ) {
+                final String sample = sampleStatePair.getKey();
+                final PerSampleReadStateManager readState = sampleStatePair.getValue();
+                final Iterator<AlignmentStateMachine> iterator = readState.iterator();
+                final List<PileupElement> pile = new ArrayList<PileupElement>(readState.size());
+
+                while (iterator.hasNext()) {
+                    // state object with the read/offset information
+                    final AlignmentStateMachine state = iterator.next();
+                    final GATKSAMRecord read = state.getRead();
+                    final CigarOperator op = state.getCigarOperator();
+
+                    if (op == CigarOperator.N) // N's are never added to any pileup
+                        continue;
+
+                    if (!dontIncludeReadInPileup(read, location.getStart())) {
+                        if ( ! includeReadsWithDeletionAtLoci && op == CigarOperator.D ) {
+                            continue;
+                        }
+
+                        pile.add(state.makePileupElement());
+                    }
+                }
+
+                if (! pile.isEmpty() ) // if this pileup added at least one base, add it to the full pileup
+                    fullPileup.put(sample, new ReadBackedPileupImpl(location, pile));
+            }
+
+            readStates.updateReadStates(); // critical - must be called after we get the current state offsets and location
+            if (!fullPileup.isEmpty()) // if we got reads with non-D/N over the current position, we are done
+                nextAlignmentContext = new AlignmentContext(location, new ReadBackedPileupImpl(location, fullPileup), false);
+        }
+    }
+
+    // -----------------------------------------------------------------------------------------------------------------
+    //
+    // getting the list of reads
+    //
+    // -----------------------------------------------------------------------------------------------------------------
+
+    /**
+     * Transfer current list of all unique reads that have ever been used in any pileup, clearing old list
+     *
+     * This list is guaranteed to only contain unique reads, even across calls to the this function.  It is
+     * literally the unique set of reads ever seen.
+     *
+     * The list occurs in the same order as they are encountered in the underlying iterator.
+     *
+     * Takes the maintained list of submitted reads, and transfers it to the caller of this
+     * function.  The old list of set to a new, cleanly allocated list so the caller officially
+     * owns the list returned by this call.  This is the only way to clear the tracking
+     * of submitted reads, if enabled.
+     *
+     * The purpose of this function is allow users of LIBS to keep track of all of the reads pulled off the
+     * underlying GATKSAMRecord iterator and that appeared at any point in the list of SAMRecordAlignmentState for
+     * any reads.  This function is intended to allow users to efficiently reconstruct the unique set of reads
+     * used across all pileups.  This is necessary for LIBS to handle because attempting to do
+     * so from the pileups coming out of LIBS is extremely expensive.
+     *
+     * This functionality is only available if LIBS was created with the argument to track the reads
+     *
+     * @throws UnsupportedOperationException if called when keepingSubmittedReads is false
+     *
+     * @return the current list
+     */
+    @Ensures("result != null")
+    public List<GATKSAMRecord> transferReadsFromAllPreviousPileups() {
+        return readStates.transferSubmittedReads();
+    }
+
+    /**
+     * Get the underlying list of tracked reads.  For testing only
+     * @return a non-null list
+     */
+    @Ensures("result != null")
+    protected List<GATKSAMRecord> getReadsFromAllPreviousPileups() {
+        return readStates.getSubmittedReads();
+    }
+
+    // -----------------------------------------------------------------------------------------------------------------
+    //
+    // utility functions
+    //
+    // -----------------------------------------------------------------------------------------------------------------
+
+    /**
+     * Should this read be excluded from the pileup?
+     *
+     * Generic place to put per-base filters appropriate to LocusIteratorByState
+     *
+     * @param rec the read to potentially exclude
+     * @param pos the genomic position of the current alignment
+     * @return true if the read should be excluded from the pileup, false otherwise
+     */
+    @Requires({"rec != null", "pos > 0"})
+    private boolean dontIncludeReadInPileup(final GATKSAMRecord rec, final long pos) {
+        return ReadUtils.isBaseInsideAdaptor(rec, pos);
+    }
+
+    /**
+     * Create a LIBSDownsamplingInfo object from the requested info in ReadProperties
+     *
+     * LIBS will invoke the Reservoir and Leveling downsamplers on the read stream if we're
+     * downsampling to coverage by sample. SAMDataSource will have refrained from applying
+     * any downsamplers to the read stream in this case, in the expectation that LIBS will
+     * manage the downsampling. The reason for this is twofold: performance (don't have to
+     * split/re-assemble the read stream in SAMDataSource), and to enable partial downsampling
+     * of reads (eg., using half of a read, and throwing the rest away).
+     *
+     * @param readInfo GATK engine information about what should be done to the reads
+     * @return a LIBS specific info holder about downsampling only
+     */
+    @Requires("readInfo != null")
+    @Ensures("result != null")
+    private static LIBSDownsamplingInfo toDownsamplingInfo(final ReadProperties readInfo) {
+        final boolean performDownsampling = readInfo.getDownsamplingMethod() != null &&
+                readInfo.getDownsamplingMethod().type == DownsampleType.BY_SAMPLE &&
+                readInfo.getDownsamplingMethod().toCoverage != null;
+        final int coverage = performDownsampling ? readInfo.getDownsamplingMethod().toCoverage : 0;
+
+        return new LIBSDownsamplingInfo(performDownsampling, coverage);
+    }
+
+    /**
+     * Create a pileup element for read at offset
+     *
+     * offset must correspond to a valid read offset given the read's cigar, or an IllegalStateException will be throw
+     *
+     * @param read a read
+     * @param offset the offset into the bases we'd like to use in the pileup
+     * @return a valid PileupElement with read and at offset
+     */
+    @Ensures("result != null")
+    public static PileupElement createPileupForReadAndOffset(final GATKSAMRecord read, final int offset) {
+        if ( read == null ) throw new IllegalArgumentException("read cannot be null");
+        if ( offset < 0 || offset >= read.getReadLength() ) throw new IllegalArgumentException("Invalid offset " + offset + " outside of bounds 0 and " + read.getReadLength());
+
+        final AlignmentStateMachine stateMachine = new AlignmentStateMachine(read);
+
+        while ( stateMachine.stepForwardOnGenome() != null ) {
+            if ( stateMachine.getReadOffset() == offset )
+                return stateMachine.makePileupElement();
+        }
+
+        throw new IllegalStateException("Tried to create a pileup for read " + read + " with offset " + offset +
+                " but we never saw such an offset in the alignment state machine");
+    }
+
+    /**
+     * For testing only.  Assumes that the incoming SAMRecords have no read groups, so creates a dummy sample list
+     * for the system.
+     */
+    public static List<String> sampleListForSAMWithoutReadGroups() {
+        List<String> samples = new ArrayList<String>();
+        samples.add(null);
+        return samples;
+    }
+}
\ No newline at end of file
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/locusiterator/PerSampleReadStateManager.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/locusiterator/PerSampleReadStateManager.java
new file mode 100644
index 0000000..e6d49c3
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/locusiterator/PerSampleReadStateManager.java
@@ -0,0 +1,261 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.utils.locusiterator;
+
+import com.google.java.contract.Ensures;
+import com.google.java.contract.Invariant;
+import com.google.java.contract.Requires;
+import htsjdk.samtools.CigarOperator;
+import org.apache.log4j.Logger;
+import org.broadinstitute.gatk.engine.downsampling.Downsampler;
+import org.broadinstitute.gatk.engine.downsampling.LevelingDownsampler;
+
+import java.util.Iterator;
+import java.util.LinkedList;
+import java.util.List;
+
+/**
+ * ReadStateManager for a single sample
+ *
+ * User: depristo
+ * Date: 1/13/13
+ * Time: 12:28 PM
+ */
+ at Invariant({
+        "readStartsAreWellOrdered()",
+        "! isDownsampling() || downsamplingTarget > 0",
+        "nSites >= 0",
+        "nSitesNeedingDownsampling >= 0",
+        "nSitesNeedingDownsampling <= nSites"
+})
+final class PerSampleReadStateManager implements Iterable<AlignmentStateMachine> {
+    private final static Logger logger = Logger.getLogger(ReadStateManager.class);
+    private final static boolean CAPTURE_DOWNSAMPLING_STATS = false;
+
+    /**
+     * A list (potentially empty) of alignment state machines.
+     *
+     * The state machines must be ordered by the alignment start of their underlying reads, with the
+     * lowest alignment starts on the left, and the largest on the right
+     */
+    private LinkedList<AlignmentStateMachine> readStatesByAlignmentStart = new LinkedList<AlignmentStateMachine>();
+
+    private final Downsampler<LinkedList<AlignmentStateMachine>> levelingDownsampler;
+    private final int downsamplingTarget;
+
+    /**
+     * The number of sites where downsampling has been invoked
+     */
+    private int nSitesNeedingDownsampling = 0;
+
+    /**
+     * The number of sites we've visited
+     */
+    private int nSites = 0;
+
+    /**
+     * Create a new PerSampleReadStateManager with downsampling parameters as requested by LIBSDownsamplingInfo
+     * @param LIBSDownsamplingInfo the downsampling params we want to use
+     */
+    public PerSampleReadStateManager(final LIBSDownsamplingInfo LIBSDownsamplingInfo) {
+        this.downsamplingTarget = LIBSDownsamplingInfo.isPerformDownsampling() ? LIBSDownsamplingInfo.getToCoverage() : -1;
+        this.levelingDownsampler = LIBSDownsamplingInfo.isPerformDownsampling()
+                ? new LevelingDownsampler<LinkedList<AlignmentStateMachine>, AlignmentStateMachine>(LIBSDownsamplingInfo.getToCoverage())
+                : null;
+    }
+
+    /**
+     * Group the underlying readStatesByAlignmentStart into a list of list of alignment state machines,
+     * where each list contains machines with a unique genome site.  The outer list is ordered
+     * by alignment start.
+     *
+     * For example, if the flat list has alignment starts [10, 10, 11, 12, 12, 13] then
+     * the resulting grouping will be [[10, 10], [11], [12, 12], [13]].
+     *
+     * @return a non-null list of lists
+     */
+    @Ensures("result != null")
+    private List<LinkedList<AlignmentStateMachine>> groupByAlignmentStart() {
+        final LinkedList<LinkedList<AlignmentStateMachine>> grouped = new LinkedList<LinkedList<AlignmentStateMachine>>();
+
+        AlignmentStateMachine last = null;
+        for ( final AlignmentStateMachine stateMachine : readStatesByAlignmentStart ) {
+            if ( last == null || stateMachine.getGenomeOffset() != last.getGenomeOffset() ) {
+                // we've advanced to a place where the state machine has a different state,
+                // so start a new list
+                grouped.add(new LinkedList<AlignmentStateMachine>());
+                last = stateMachine;
+            }
+            grouped.getLast().add(stateMachine);
+        }
+
+        return grouped;
+    }
+
+    /**
+     * Flattens the grouped list of list of alignment state machines into a single list in order
+     * @return a non-null list contains the state machines
+     */
+    @Ensures("result != null")
+    private LinkedList<AlignmentStateMachine> flattenByAlignmentStart(final List<LinkedList<AlignmentStateMachine>> grouped) {
+        final LinkedList<AlignmentStateMachine> flat = new LinkedList<AlignmentStateMachine>();
+        for ( final List<AlignmentStateMachine> l : grouped )
+            flat.addAll(l);
+        return flat;
+    }
+
+    /**
+     * Test that the reads are ordered by their alignment starts
+     * @return true if well ordered, false otherwise
+     */
+    private boolean readStartsAreWellOrdered() {
+        int lastStart = -1;
+        for ( final AlignmentStateMachine machine : readStatesByAlignmentStart ) {
+            if ( lastStart > machine.getRead().getAlignmentStart() )
+                return false;
+            lastStart = machine.getRead().getAlignmentStart();
+        }
+        return true;
+    }
+
+    /**
+     * Assumes it can just keep the states linked lists without making a copy
+     * @param states the new states to add to this manager
+     * @return The change in the number of states, after including states and potentially downsampling.  Note
+     * that this return result might be negative, if downsampling is enabled, as we might drop
+     * more sites than have been added by the downsampler
+     */
+    @Requires("states != null")
+    public int addStatesAtNextAlignmentStart(final LinkedList<AlignmentStateMachine> states) {
+        if ( states.isEmpty() ) {
+            return 0;
+        }
+
+        readStatesByAlignmentStart.addAll(states);
+        int nStatesAdded = states.size();
+
+        if ( isDownsampling() && readStatesByAlignmentStart.size() > downsamplingTarget ) {
+            // only go into the downsampling branch if we are downsampling and the coverage > the target
+            captureDownsamplingStats();
+            levelingDownsampler.submit(groupByAlignmentStart());
+            levelingDownsampler.signalEndOfInput();
+
+            nStatesAdded -= levelingDownsampler.getNumberOfDiscardedItems();
+
+            // use returned List directly rather than make a copy, for efficiency's sake
+            readStatesByAlignmentStart = flattenByAlignmentStart(levelingDownsampler.consumeFinalizedItems());
+            levelingDownsampler.resetStats();
+        }
+
+        return nStatesAdded;
+    }
+
+    /**
+     * Is downsampling enabled for this manager?
+     * @return true if we are downsampling, false otherwise
+     */
+    private boolean isDownsampling() {
+        return levelingDownsampler != null;
+    }
+
+    /**
+     * Get the leftmost alignment state machine, or null if the read states is empty
+     * @return a potentially null AlignmentStateMachine
+     */
+    public AlignmentStateMachine getFirst() {
+        return isEmpty() ? null : readStatesByAlignmentStart.getFirst();
+    }
+
+    /**
+     * Capture some statistics about the behavior of the downsampling, but only if CAPTURE_DOWNSAMPLING_STATS is true
+     */
+    @Requires("isDownsampling()")
+    private void captureDownsamplingStats() {
+        if ( CAPTURE_DOWNSAMPLING_STATS ) {
+            nSites++;
+            final int loc = getFirst().getGenomePosition();
+            String message = "Pass through";
+            final boolean downsampling = size() > downsamplingTarget;
+            if ( downsampling ) {
+                nSitesNeedingDownsampling++;
+                message = "Downsampling";
+            }
+
+            if ( downsampling || nSites % 10000 == 0 )
+                logger.info(String.format("%20s at %s: coverage=%d, max=%d, fraction of downsampled sites=%.2e",
+                        message, loc, size(), downsamplingTarget, (1.0 * nSitesNeedingDownsampling / nSites)));
+        }
+    }
+
+    /**
+     * Is there at least one alignment for this sample in this manager?
+     * @return true if there's at least one alignment, false otherwise
+     */
+    public boolean isEmpty() {
+        return readStatesByAlignmentStart.isEmpty();
+    }
+
+    /**
+     * Get the number of read states currently in this manager
+     * @return the number of read states
+     */
+    @Ensures("result >= 0")
+    public int size() {
+        return readStatesByAlignmentStart.size();
+    }
+
+    /**
+     * Advances all read states forward by one element, removing states that are
+     * no long aligned to the current position.
+     * @return the number of states we're removed after advancing
+     */
+    public int updateReadStates() {
+        int nRemoved = 0;
+        final Iterator<AlignmentStateMachine> it = iterator();
+        while (it.hasNext()) {
+            final AlignmentStateMachine state = it.next();
+            final CigarOperator op = state.stepForwardOnGenome();
+            if (op == null) {
+                // we discard the read only when we are past its end AND indel at the end of the read (if any) was
+                // already processed. Keeping the read state that returned null upon stepForwardOnGenome() is safe
+                // as the next call to stepForwardOnGenome() will return null again AND will clear hadIndel() flag.
+                it.remove();                                                // we've stepped off the end of the object
+                nRemoved++;
+            }
+        }
+
+        return nRemoved;
+    }
+
+    /**
+     * Iterate over the AlignmentStateMachine in this manager in alignment start order.
+     * @return a valid iterator
+     */
+    @Ensures("result != null")
+    public Iterator<AlignmentStateMachine> iterator() {
+        return readStatesByAlignmentStart.iterator();
+    }
+}
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/locusiterator/ReadStateManager.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/locusiterator/ReadStateManager.java
new file mode 100644
index 0000000..0014753
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/locusiterator/ReadStateManager.java
@@ -0,0 +1,289 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.utils.locusiterator;
+
+import com.google.java.contract.Ensures;
+import com.google.java.contract.Requires;
+import htsjdk.samtools.util.PeekableIterator;
+import org.broadinstitute.gatk.utils.sam.GATKSAMRecord;
+
+import java.util.*;
+
+/**
+ * Manages and updates mapping from sample -> List of SAMRecordAlignmentState
+ *
+ * Optionally can keep track of all of the reads pulled off the iterator and
+ * that appeared at any point in the list of SAMRecordAlignmentState for any reads.
+ * This functionaly is only possible at this stage, as this object does the popping of
+ * reads off the underlying source iterator, and presents only a pileup-like interface
+ * of samples -> SAMRecordAlignmentStates.  Reconstructing the unique set of reads
+ * used across all pileups is extremely expensive from that data structure.
+ *
+ * User: depristo
+ * Date: 1/5/13
+ * Time: 2:02 PM
+ */
+final class ReadStateManager implements Iterable<Map.Entry<String, PerSampleReadStateManager>> {
+    private final List<String> samples;
+    private final PeekableIterator<GATKSAMRecord> iterator;
+    private final SamplePartitioner<GATKSAMRecord> samplePartitioner;
+
+    /**
+     * A mapping from sample name -> the per sample read state manager that manages
+     *
+     * IT IS CRITICAL THAT THIS BE A LINKED HASH MAP, SO THAT THE ITERATION OF THE MAP OCCURS IN THE SAME
+     * ORDER AS THE ORIGINL SAMPLES
+     */
+    private final Map<String, PerSampleReadStateManager> readStatesBySample = new LinkedHashMap<String, PerSampleReadStateManager>();
+
+    private LinkedList<GATKSAMRecord> submittedReads;
+    private final boolean keepSubmittedReads;
+
+    private int totalReadStates = 0;
+
+    public ReadStateManager(final Iterator<GATKSAMRecord> source,
+                            final List<String> samples,
+                            final LIBSDownsamplingInfo LIBSDownsamplingInfo,
+                            final boolean keepSubmittedReads) {
+        this.samples = samples;
+        this.iterator = new PeekableIterator<GATKSAMRecord>(source);
+
+        this.keepSubmittedReads = keepSubmittedReads;
+        this.submittedReads = new LinkedList<GATKSAMRecord>();
+
+        for (final String sample : samples) {
+            // because this is a linked hash map the order of iteration will be in sample order
+            readStatesBySample.put(sample, new PerSampleReadStateManager(LIBSDownsamplingInfo));
+        }
+
+        samplePartitioner = new SamplePartitioner<GATKSAMRecord>(LIBSDownsamplingInfo, samples);
+    }
+
+    /**
+     * Returns a iterator over all the sample -> per-sample read state managers with each sample in this read state manager.
+     *
+     * The order of iteration is the same as the order of the samples provided upon construction to this
+     * ReadStateManager.
+     *
+     * @return Iterator over sample + per sample read state manager pairs for this read state manager.
+     */
+    @Override
+    public Iterator<Map.Entry<String, PerSampleReadStateManager>> iterator() {
+        return readStatesBySample.entrySet().iterator();
+    }
+
+    public boolean isEmpty() {
+        return totalReadStates == 0;
+    }
+
+    /**
+     * Retrieves the total number of reads in the manager across all samples.
+     *
+     * @return Total number of reads over all samples.
+     */
+    public int size() {
+        return totalReadStates;
+    }
+
+    /**
+     * Retrieves the total number of reads in the manager in the given sample.
+     *
+     * @param sample The sample.
+     * @return Total number of reads in the given sample.
+     */
+    public int size(final String sample) {
+        return readStatesBySample.get(sample).size();
+    }
+
+    public AlignmentStateMachine getFirst() {
+        for ( final PerSampleReadStateManager manager : readStatesBySample.values() ) {
+            if ( ! manager.isEmpty() )
+                return manager.getFirst();
+        }
+        return null;
+    }
+
+    public boolean hasNext() {
+        return totalReadStates > 0 || iterator.hasNext();
+    }
+
+    /**
+     * Advances all fo the read states by one bp.  After this call the read states are reflective
+     * of the next pileup.
+     */
+    public void updateReadStates() {
+        for (final PerSampleReadStateManager perSampleReadStateManager : readStatesBySample.values() ) {
+            totalReadStates -= perSampleReadStateManager.updateReadStates();
+        }
+    }
+
+    /**
+     * Does read start at the same position as described by currentContextIndex and currentAlignmentStart?
+     *
+     * @param read the read we want to test
+     * @param currentContigIndex the contig index (from the read's getReferenceIndex) of the reads in this state manager
+     * @param currentAlignmentStart the alignment start of the of the left-most position on the
+     *                           genome of the reads in this read state manager
+     * @return true if read has contig index and start equal to the current ones
+     */
+    private boolean readStartsAtCurrentPosition(final GATKSAMRecord read, final int currentContigIndex, final int currentAlignmentStart) {
+        return read.getAlignmentStart() == currentAlignmentStart && read.getReferenceIndex() == currentContigIndex;
+    }
+
+    /**
+     * Pull all of the reads off the iterator that overlap the left-most position among all
+     * reads this ReadStateManager
+     */
+    public void collectPendingReads() {
+        if (!iterator.hasNext())
+            return;
+
+        // determine the left-most boundary that determines which reads to keep in this new pileup
+        final int firstContigIndex;
+        final int firstAlignmentStart;
+        if ( isEmpty() ) {
+            // there are no reads here, so our next state is the next read in the stream
+            firstContigIndex = iterator.peek().getReferenceIndex();
+            firstAlignmentStart = iterator.peek().getAlignmentStart();
+        } else {
+            // there's a read in the system, so it's our targeted first read
+            final AlignmentStateMachine firstState = getFirst();
+            firstContigIndex = firstState.getReferenceIndex();
+            // note this isn't the alignment start of the read, but rather the alignment start position
+            firstAlignmentStart = firstState.getGenomePosition();
+        }
+
+        while ( iterator.hasNext() && readStartsAtCurrentPosition(iterator.peek(), firstContigIndex, firstAlignmentStart) ) {
+            submitRead(iterator.next());
+        }
+
+        samplePartitioner.doneSubmittingReads();
+
+        for (final String sample : samples) {
+            final Collection<GATKSAMRecord> newReads = samplePartitioner.getReadsForSample(sample);
+
+            // if we're keeping reads, take the (potentially downsampled) list of new reads for this sample
+            // and add to the list of reads.  Note this may reorder the list of reads someone (it groups them
+            // by sample, but it cannot change their absolute position on the genome as they all must
+            // start at the current location
+            if ( keepSubmittedReads )
+                submittedReads.addAll(newReads);
+
+            final PerSampleReadStateManager statesBySample = readStatesBySample.get(sample);
+            addReadsToSample(statesBySample, newReads);
+        }
+
+        samplePartitioner.reset();
+    }
+
+    /**
+     * Add a read to the sample partitioner, potentially adding it to all submitted reads, if appropriate
+     * @param read a non-null read
+     */
+    @Requires("read != null")
+    protected void submitRead(final GATKSAMRecord read) {
+        samplePartitioner.submitRead(read);
+    }
+
+    /**
+     * Transfer current list of submitted reads, clearing old list
+     *
+     * Takes the maintained list of submitted reads, and transfers it to the caller of this
+     * function.  The old list of set to a new, cleanly allocated list so the caller officially
+     * owns the list returned by this call.  This is the only way to clear the tracking
+     * of submitted reads, if enabled.
+     *
+     * How to use this function:
+     *
+     * while ( doing some work unit, such as creating pileup at some locus ):
+     *   interact with ReadStateManager in some way to make work unit
+     *   readsUsedInPileup = transferSubmittedReads)
+     *
+     * @throws UnsupportedOperationException if called when keepSubmittedReads is false
+     *
+     * @return the current list of submitted reads
+     */
+    @Ensures({
+            "result != null",
+            "result != submittedReads" // result and previous submitted reads are not == objects
+    })
+    public List<GATKSAMRecord> transferSubmittedReads() {
+        if ( ! keepSubmittedReads ) throw new UnsupportedOperationException("cannot transferSubmittedReads if you aren't keeping them");
+
+        final List<GATKSAMRecord> prevSubmittedReads = submittedReads;
+        this.submittedReads = new LinkedList<GATKSAMRecord>();
+
+        return prevSubmittedReads;
+    }
+
+    /**
+     * Are we keeping submitted reads, or not?
+     * @return true if we are keeping them, false otherwise
+     */
+    public boolean isKeepingSubmittedReads() {
+        return keepSubmittedReads;
+    }
+
+    /**
+     * Obtain a pointer to the list of submitted reads.
+     *
+     * This is not a copy of the list; it is shared with this ReadStateManager.  It should
+     * not be modified.  Updates to this ReadStateManager may change the contains of the
+     * list entirely.
+     *
+     * For testing purposes only.
+     *
+     * Will always be empty if we are are not keepSubmittedReads
+     *
+     * @return a non-null list of reads that have been submitted to this ReadStateManager
+     */
+    @Ensures({"result != null","keepSubmittedReads || result.isEmpty()"})
+    protected List<GATKSAMRecord> getSubmittedReads() {
+        return submittedReads;
+    }
+
+    /**
+     * Add reads with the given sample name to the given hanger entry.
+     *
+     * @param readStates The list of read states to add this collection of reads.
+     * @param reads      Reads to add.  Selected reads will be pulled from this source.
+     */
+    private void addReadsToSample(final PerSampleReadStateManager readStates, final Collection<GATKSAMRecord> reads) {
+        if (reads.isEmpty())
+            return;
+
+        final LinkedList<AlignmentStateMachine> newReadStates = new LinkedList<AlignmentStateMachine>();
+
+        for (final GATKSAMRecord read : reads) {
+            final AlignmentStateMachine state = new AlignmentStateMachine(read);
+            if ( state.stepForwardOnGenome() != null ) // todo -- should be an assertion not a skip
+                // explicitly filter out reads that are all insertions / soft clips
+                newReadStates.add(state);
+        }
+
+        totalReadStates += readStates.addStatesAtNextAlignmentStart(newReadStates);
+    }
+}
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/locusiterator/SamplePartitioner.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/locusiterator/SamplePartitioner.java
new file mode 100644
index 0000000..825cb35
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/locusiterator/SamplePartitioner.java
@@ -0,0 +1,172 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.utils.locusiterator;
+
+import com.google.java.contract.Ensures;
+import com.google.java.contract.Requires;
+import htsjdk.samtools.SAMRecord;
+import org.broadinstitute.gatk.engine.downsampling.Downsampler;
+import org.broadinstitute.gatk.engine.downsampling.PassThroughDownsampler;
+import org.broadinstitute.gatk.engine.downsampling.ReservoirDownsampler;
+
+import java.util.*;
+
+/**
+ * Divides reads by sample and (if requested) does a preliminary downsampling pass
+ * with a ReservoirDownsampler.
+ *
+ * Note: stores reads by sample ID string, not by sample object
+ */
+class SamplePartitioner<T extends SAMRecord> {
+    /**
+     * Map from sample name (as a string) to a downsampler of reads for that sample
+     */
+    final private Map<String, Downsampler<T>> readsBySample;
+
+    /**
+     * Are we in a state where we're done submitting reads and have semi-finalized the
+     * underlying per sample downsampler?
+     */
+    boolean doneSubmittingReads = false;
+
+    /**
+     * Create a new SamplePartitioner capable of splitting reads up into buckets of reads for
+     * each sample in samples, and perform a preliminary downsampling of these reads
+     * (separately for each sample) if downsampling is requested in LIBSDownsamplingInfo
+     *
+     * Note that samples must be comprehensive, in that all reads every submitted to this
+     * partitioner must come from one of the samples provided here.  If not, submitRead
+     * will throw an exception.  Duplicates in the list of samples will be ignored
+     *
+     * @param LIBSDownsamplingInfo do we want to downsample, and if so to what coverage?
+     * @param samples the complete list of samples we're going to partition reads into. Can be
+     *                empty, but in that case this code cannot function properly if you
+     *                attempt to add data to it.
+     */
+    @Ensures({
+            "readsBySample != null",
+            "readsBySample.size() == new HashSet(samples).size()"
+    })
+    public SamplePartitioner(final LIBSDownsamplingInfo LIBSDownsamplingInfo, final List<String> samples) {
+        if ( LIBSDownsamplingInfo == null ) throw new IllegalArgumentException("LIBSDownsamplingInfo cannot be null");
+        if ( samples == null ) throw new IllegalArgumentException("samples must be a non-null list");
+
+        readsBySample = new LinkedHashMap<String, Downsampler<T>>(samples.size());
+        for ( final String sample : samples ) {
+            readsBySample.put(sample, createDownsampler(LIBSDownsamplingInfo));
+        }
+    }
+
+    /**
+     * Create a new, ready to use downsampler based on the parameters in LIBSDownsamplingInfo
+     * @param LIBSDownsamplingInfo the parameters to use in creating the downsampler
+     * @return a downsampler appropriate for LIBSDownsamplingInfo.  If no downsampling is requested,
+     *   uses the PassThroughDownsampler, which does nothing at all.
+     */
+    @Requires("LIBSDownsamplingInfo != null")
+    @Ensures("result != null")
+    private Downsampler<T> createDownsampler(final LIBSDownsamplingInfo LIBSDownsamplingInfo) {
+        return LIBSDownsamplingInfo.isPerformDownsampling()
+                ? new ReservoirDownsampler<T>(LIBSDownsamplingInfo.getToCoverage(), true)
+                : new PassThroughDownsampler<T>();
+    }
+
+    /**
+     * Offer this read to the partitioner, putting it into the bucket of reads for the sample
+     * of read (obtained via the read's read group).
+     *
+     * If the read group is missing, uses the special "null" read group
+     *
+     * @throws IllegalStateException if the sample of read wasn't present in the original
+     *   set of samples provided to this SamplePartitioner at construction
+     *
+     * @param read the read to add to the sample's list of reads
+     */
+    @Requires("read != null")
+    @Ensures("doneSubmittingReads == false")
+    public void submitRead(final T read) {
+        final String sampleName = read.getReadGroup() != null ? read.getReadGroup().getSample() : null;
+        final Downsampler<T> downsampler = readsBySample.get(sampleName);
+        if ( downsampler == null )
+            throw new IllegalStateException("Offered read with sample name " + sampleName + " to SamplePartitioner " +
+                    "but this sample wasn't provided as one of possible samples at construction");
+
+        downsampler.submit(read);
+        doneSubmittingReads = false;
+    }
+
+    /**
+     * Tell this partitioner that all reads in this cycle have been submitted, so that we
+     * can finalize whatever downsampling is required by each sample.
+     *
+     * Note that we *must* call this function before getReadsForSample, or else that
+     * function will exception out.
+     */
+    @Ensures("doneSubmittingReads == true")
+    public void doneSubmittingReads() {
+        for ( final Downsampler<T> downsampler : readsBySample.values() ) {
+            downsampler.signalEndOfInput();
+        }
+        doneSubmittingReads = true;
+    }
+
+    /**
+     * Get the final collection of reads for this sample for this cycle
+     *
+     * The cycle is defined as all of the reads that occur between
+     * the first call to submitRead until doneSubmittingReads is called.  At that
+     * point additional downsampling may occur (depending on construction arguments)
+     * and that set of reads is returned here.
+     *
+     * Note that this function can only be called once per cycle, as underlying
+     * collection of reads is cleared.
+     *
+     * @param sampleName the sample we want reads for, must be present in the original samples
+     * @return a non-null collection of reads for sample in this cycle
+     */
+    @Ensures("result != null")
+    public Collection<T> getReadsForSample(final String sampleName) {
+        if ( ! doneSubmittingReads ) throw new IllegalStateException("getReadsForSample called before doneSubmittingReads was called");
+
+        final Downsampler<T> downsampler = readsBySample.get(sampleName);
+        if ( downsampler == null ) throw new NoSuchElementException("Sample name not found");
+
+        return downsampler.consumeFinalizedItems();
+    }
+
+    /**
+     * Resets this SamplePartitioner, indicating that we're starting a new
+     * cycle of adding reads to each underlying downsampler.
+     */
+    @Ensures("doneSubmittingReads == false")
+    public void reset() {
+        for ( final Downsampler<T> downsampler : readsBySample.values() ) {
+            downsampler.clearItems();
+            downsampler.resetStats();
+        }
+        doneSubmittingReads = false;
+    }
+}
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/nanoScheduler/EOFMarkedValue.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/nanoScheduler/EOFMarkedValue.java
new file mode 100644
index 0000000..c5255e4
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/nanoScheduler/EOFMarkedValue.java
@@ -0,0 +1,105 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.utils.nanoScheduler;
+
+/**
+ * Wrapper to hold data that distinguishing an special EOF marker from a real object
+ *
+ * The only way to tell in a consumer thread that a blocking queue has no more data ever
+ * coming down the pipe is to pass in a "poison" or EOF object.  This class provides
+ * a generic capacity for that...
+ *
+ * The use case looks like this:
+ *
+ * BlockingQueue q
+ * producer:
+ *   while ( x has items )
+ *      q.put(new EOFMarkedValue(x))
+ *   q.put(new EOFMarkedValue())
+ *
+ * Consumer:
+ *   while ( true )
+ *       value = q.take()
+ *       if ( value.isEOFMarker() )
+ *          break
+ *       else
+ *          do something useful with value
+ *
+ *
+ * User: depristo
+ * Date: 9/6/12
+ * Time: 3:08 PM
+ */
+//@Invariant("! isEOFMarker() || value == null")
+class EOFMarkedValue<T> {
+    /**
+     * True if this is the EOF marker object
+     */
+    final private boolean isLast;
+
+    /**
+     * Our value, if we aren't the EOF marker
+     */
+    final private T value;
+
+    /**
+     * Create a new EOFMarkedValue containing a real value, where last is false
+     * @param value
+     */
+    EOFMarkedValue(final T value) {
+        isLast = false;
+        this.value = value;
+    }
+
+    /**
+     * Create a new EOFMarkedValue that is the last item
+     */
+    EOFMarkedValue() {
+        isLast = true;
+        this.value = null;
+    }
+
+    /**
+     * Is this the EOF marker?
+     *
+     * @return true if so, else false
+     */
+    public boolean isEOFMarker() {
+        return isLast;
+    }
+
+    /**
+     * Get the value held by this EOFMarkedValue
+     *
+     * @return the value
+     * @throws IllegalStateException if this is the last item
+     */
+    public T getValue() {
+        if ( isEOFMarker() )
+            throw new IllegalStateException("Cannot get value for last object");
+        return value;
+    }
+}
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/nanoScheduler/InputProducer.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/nanoScheduler/InputProducer.java
new file mode 100644
index 0000000..3a67b43
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/nanoScheduler/InputProducer.java
@@ -0,0 +1,217 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.utils.nanoScheduler;
+
+import org.apache.log4j.Logger;
+
+import java.util.Iterator;
+import java.util.concurrent.CountDownLatch;
+
+/**
+ * Helper class that allows multiple threads to reads input values from
+ * an iterator, and track the number of items read from that iterator.
+ */
+class InputProducer<InputType> {
+    private final static Logger logger = Logger.getLogger(InputProducer.class);
+
+    /**
+     * The iterator we are using to get data from
+     */
+    final Iterator<InputType> inputReader;
+
+    /**
+     * Have we read the last value from inputReader?
+     *
+     * Must be a local variable, as inputReader.hasNext() can actually end up doing a lot
+     * of work, and the method getNumInputValues() is supposed to be called not in the
+     * thread executing the reading of values but in the thread enqueuing results
+     */
+    boolean readLastValue = false;
+
+    /**
+     * Once we've readLastValue, lastValue contains a continually
+     * updating InputValue where EOF is true.  It's not necessarily
+     * a single value, as each read updates lastValue with the
+     * next EOF marker
+     */
+    private InputValue lastValue = null;
+
+    int nRead = 0;
+    int inputID = -1;
+
+    public InputProducer(final Iterator<InputType> inputReader) {
+        if ( inputReader == null ) throw new IllegalArgumentException("inputReader cannot be null");
+        this.inputReader = inputReader;
+    }
+
+    /**
+     * Returns the number of elements in the input stream, AFTER we've read all of the values.
+     * If we haven't read them all yet, returns -1
+     *
+     * @return the total number of elements in input stream, or -1 if some are still to be read
+     */
+    public synchronized int getNumInputValues() {
+        return allInputsHaveBeenRead() ? nRead : -1;
+    }
+
+    /**
+     * Returns true if all of the elements have been read from the input stream
+     *
+     * @return true if all of the elements have been read from the input stream
+     */
+    public synchronized boolean allInputsHaveBeenRead() {
+        return readLastValue;
+    }
+
+    /**
+     * Read the next item from the input stream, if possible
+     *
+     * If the inputReader has values, returns them, otherwise return null.
+     *
+     * This method is synchronized, as it manipulates local state accessed across multiple threads.
+     *
+     * @return the next input stream value, or null if the stream contains no more elements
+     */
+    private synchronized InputType readNextItem() {
+        if ( ! inputReader.hasNext() ) {
+            // we are done, mark ourselves as such and return null
+            readLastValue = true;
+            return null;
+        } else {
+            // get the next value, and return it
+            final InputType input = inputReader.next();
+            if ( input == null )
+                throw new IllegalStateException("inputReader.next() returned a null value, breaking our contract");
+            nRead++;
+            return input;
+        }
+    }
+
+    /**
+     * Are there currently more values in the iterator?
+     *
+     * Note the word currently.  It's possible that some already submitted
+     * job will read a value from this InputProvider, so in some sense
+     * there are no more values and in the future there'll be no next
+     * value.  That said, once this returns false it means that all
+     * of the possible values have been read
+     *
+     * @return true if a future call to next might return a non-EOF value, false if
+     *         the underlying iterator is definitely empty
+     */
+    public synchronized boolean hasNext() {
+        return ! allInputsHaveBeenRead();
+    }
+
+    /**
+     * Get the next InputValue from this producer.  The next value is
+     * either (1) the next value from the iterator, in which case the
+     * the return value is an InputValue containing that value, or (2)
+     * an InputValue with the EOF marker, indicating that the underlying
+     * iterator has been exhausted.
+     *
+     * This function never fails -- it can be called endlessly and
+     * while the underlying iterator has values it returns them, and then
+     * it returns a succession of EOF marking input values.
+     *
+     * @return an InputValue containing the next value in the underlying
+     *         iterator, or one with EOF marker, if the iterator is exhausted
+     */
+    public synchronized InputValue next() {
+        if ( readLastValue ) {
+            // we read the last value, so our value is the next
+            // EOF marker based on the last value.  Make sure to
+            // update the last value so the markers keep incrementing
+            // their job ids
+            lastValue = lastValue.nextEOF();
+            return lastValue;
+        } else {
+            final InputType value = readNextItem();
+
+            if ( value == null ) {
+                if ( ! readLastValue )
+                    throw new IllegalStateException("value == null but readLastValue is false!");
+
+                // add the EOF object so our consumer knows we are done in all inputs
+                // note that we do not increase inputID here, so that variable indicates the ID
+                // of the last real value read from the queue
+                lastValue = new InputValue(inputID + 1);
+                return lastValue;
+            } else {
+                // add the actual value to the outputQueue
+                return new InputValue(++inputID, value);
+            }
+        }
+    }
+
+    /**
+     * Helper class that contains a read value suitable for EOF marking in a BlockingQueue
+     *
+     * This class also contains an ID, an integer incrementing from 0 to N, for N total
+     * values in the input stream.  This ID indicates which element in the element stream this
+     * InputValue corresponds to.  Necessary for tracking and ordering results by input position.
+     *
+     * Note that EOF markers have IDs > N, and ID values >> N can occur if many EOF markers
+     * are enqueued in the outputQueue.
+     */
+    class InputValue extends EOFMarkedValue<InputType> {
+        final int id;
+
+        private InputValue(final int id, InputType datum) {
+            super(datum);
+            if ( id < 0 ) throw new IllegalArgumentException("id must be >= 0");
+            this.id = id;
+        }
+        private InputValue(final int id) {
+            super();
+            if ( id < 0 ) throw new IllegalArgumentException("id must be >= 0");
+            this.id = id;
+        }
+
+        /**
+         * Returns the ID of this input marker
+         * @return id >= 0
+         */
+        public int getId() {
+            return id;
+        }
+
+        /**
+         * Create another EOF marker with ID + 1 to this one.
+         *
+         * Useful in the case where we need to enqueue another EOF marker for future jobs and we
+         * want them to have a meaningful ID, one greater than the last one.
+         *
+         * @return ID
+         */
+        //@Ensures({"result.isEOFMarker()", "result.getId() == getId() + 1"})
+        public InputValue nextEOF() {
+            if ( ! isEOFMarker() )
+                throw new IllegalArgumentException("Cannot request next EOF marker for non-EOF marker InputValue");
+            return new InputValue(getId() + 1);
+        }
+    }
+}
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/nanoScheduler/MapResult.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/nanoScheduler/MapResult.java
new file mode 100644
index 0000000..d6628a5
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/nanoScheduler/MapResult.java
@@ -0,0 +1,75 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.utils.nanoScheduler;
+
+/**
+ * Holds the results of a map job suitable for producer/consumer threading
+ * via a BlockingQueue
+ */
+class MapResult<MapType> extends EOFMarkedValue<MapType> implements Comparable<MapResult<MapType>> {
+    final int jobID;
+
+    /**
+     * Create a new MapResult with value datum and jod jobID ID
+     *
+     * @param datum the value produced by the map job
+     * @param jobID the id of the map job (for correctness testing)
+     */
+    MapResult(final MapType datum, final int jobID) {
+        super(datum);
+        this.jobID = jobID;
+        if ( jobID < 0 ) throw new IllegalArgumentException("JobID must be >= 0");
+    }
+
+    MapResult(final int jobID) {
+        super();
+        this.jobID = jobID;
+        if ( jobID < 0 ) throw new IllegalArgumentException("JobID must be >= 0");
+    }
+
+    /**
+     * @return the job ID of the map job that produced this MapResult
+     */
+    public int getJobID() {
+        return jobID;
+    }
+
+    /**
+     * Compare these MapResults in order of JobID.
+     *
+     * @param o
+     * @return
+     */
+    @Override
+    public int compareTo(MapResult<MapType> o) {
+        return Integer.valueOf(jobID).compareTo(o.getJobID());
+    }
+
+    @Override
+    public String toString() {
+        return "[MapResult id=" + jobID + "]";
+    }
+}
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/nanoScheduler/MapResultsQueue.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/nanoScheduler/MapResultsQueue.java
new file mode 100644
index 0000000..afeafb5
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/nanoScheduler/MapResultsQueue.java
@@ -0,0 +1,116 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.utils.nanoScheduler;
+
+import org.broadinstitute.gatk.utils.collections.ExpandingArrayList;
+
+/**
+ * Created with IntelliJ IDEA.
+ * User: depristo
+ * Date: 12/19/12
+ * Time: 3:53 PM
+ *
+ * This class makes some critical assumptions.  First is that the jobID of the first
+ * job is 0.  If this isn't true the MapResultsQueue will certainly fail.
+ */
+public class MapResultsQueue<MapType> {
+    //private final static boolean DEBUG = false;
+    //private final static Logger logger = Logger.getLogger(MapResultsQueue.class);
+
+    /**
+     * Although naturally stored as priority blocking queue, this is actually quite expensive
+     * due to the O(n log n) sorting calculation.  Since we know that the job ids start
+     * at 0 and increment by 1 in each successive job, we store an array instead.  The
+     * array is indexed by jobID, and contains the MapResult for that job id.  Because elements
+     * can be added to the queue in any order, we need to use an expanding array list to
+     * store the elements.
+     */
+    final ExpandingArrayList<MapResult<MapType>> queue = new ExpandingArrayList<MapResult<MapType>>(10000);
+
+    /**
+     * The jobID of the last job we've seen
+     */
+    int prevJobID = -1; // no jobs observed
+
+    /**
+     * Put mapResult into this MapResultsQueue, associated with its jobID
+     * @param mapResult a non-null map result
+     */
+    public synchronized void put(final MapResult<MapType> mapResult) {
+        if ( mapResult == null ) throw new IllegalArgumentException("mapResult cannot be null");
+
+        // make sure that nothing is at the job id for map
+        assert queue.size() < mapResult.getJobID() || queue.get(mapResult.getJobID()) == null;
+
+        queue.set(mapResult.getJobID(), mapResult);
+    }
+
+    /**
+     * Should we reduce the next value in the mapResultQueue?
+     *
+     * @return true if we should reduce
+     */
+    public synchronized boolean nextValueIsAvailable() {
+        final MapResult<MapType> nextMapResult = queue.get(nextJobID());
+
+        if ( nextMapResult == null ) {
+            // natural case -- the next job hasn't had a value added yet
+            return false;
+        } else if ( nextMapResult.getJobID() != nextJobID() ) {
+            // sanity check -- the job id at next isn't the one we expect
+            throw new IllegalStateException("Next job ID " + nextMapResult.getJobID() + " is not == previous job id " + prevJobID + " + 1");
+        } else {
+            // there's a value at the next job id, so return true
+            return true;
+        }
+    }
+
+    /**
+     * Get the next job ID'd be expect to see given our previous job id
+     * @return the next job id we'd fetch to reduce
+     */
+    private int nextJobID() {
+        return prevJobID + 1;
+    }
+
+    /**
+     * Can only be called when nextValueIsAvailable is true
+     * @return
+     * @throws InterruptedException
+     */
+    // TODO -- does this have to be synchronized? -- I think the answer is no
+    public synchronized MapResult<MapType> take() throws InterruptedException {
+        final MapResult<MapType> result = queue.get(nextJobID());
+
+        // make sure the value we've fetched has the right id
+        assert result.getJobID() == nextJobID();
+
+        prevJobID = result.getJobID();
+        queue.set(prevJobID, null);
+
+        return result;
+    }
+}
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/nanoScheduler/NSMapFunction.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/nanoScheduler/NSMapFunction.java
new file mode 100644
index 0000000..dbd58b4
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/nanoScheduler/NSMapFunction.java
@@ -0,0 +1,44 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.utils.nanoScheduler;
+
+/**
+ * A function that maps from InputType -> ResultType
+ *
+ * For use with the NanoScheduler
+ *
+ * User: depristo
+ * Date: 8/24/12
+ * Time: 9:49 AM
+ */
+public interface NSMapFunction<InputType, ResultType> {
+    /**
+     * Return function on input, returning a value of ResultType
+     * @param input
+     * @return
+     */
+    public ResultType apply(final InputType input);
+}
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/nanoScheduler/NSProgressFunction.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/nanoScheduler/NSProgressFunction.java
new file mode 100644
index 0000000..27d713e
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/nanoScheduler/NSProgressFunction.java
@@ -0,0 +1,37 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.utils.nanoScheduler;
+
+/**
+ * Created with IntelliJ IDEA.
+ * User: depristo
+ * Date: 9/4/12
+ * Time: 2:10 PM
+ * To change this template use File | Settings | File Templates.
+ */
+public interface NSProgressFunction<InputType> {
+    public void progress(final InputType lastMapInput);
+}
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/nanoScheduler/NSReduceFunction.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/nanoScheduler/NSReduceFunction.java
new file mode 100644
index 0000000..acb0a78
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/nanoScheduler/NSReduceFunction.java
@@ -0,0 +1,43 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.utils.nanoScheduler;
+
+/**
+ * A function that combines a value of MapType with an existing ReduceValue into a new ResultType
+ *
+ * User: depristo
+ * Date: 8/24/12
+ * Time: 9:49 AM
+ */
+public interface NSReduceFunction<MapType, ReduceType> {
+    /**
+     * Combine one with sum into a new ReduceType
+     * @param one the result of a map call on an input element
+     * @param sum the cumulative reduce result over all previous map calls
+     * @return
+     */
+    public ReduceType apply(MapType one, ReduceType sum);
+}
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/nanoScheduler/NanoScheduler.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/nanoScheduler/NanoScheduler.java
new file mode 100644
index 0000000..8b02721
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/nanoScheduler/NanoScheduler.java
@@ -0,0 +1,494 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.utils.nanoScheduler;
+
+import com.google.java.contract.Ensures;
+import com.google.java.contract.Requires;
+import org.apache.log4j.Logger;
+import org.broadinstitute.gatk.utils.MultiThreadedErrorTracker;
+import org.broadinstitute.gatk.utils.threading.NamedThreadFactory;
+
+import java.util.Iterator;
+import java.util.List;
+import java.util.concurrent.*;
+
+/**
+ * Framework for very fine grained MapReduce parallelism
+ *
+ * The overall framework works like this
+ *
+ * nano <- new Nanoschedule(bufferSize, numberOfMapElementsToProcessTogether, nThreads)
+ * List[Input] outerData : outerDataLoop )
+ *   result = nano.execute(outerData.iterator(), map, reduce)
+ *
+ * bufferSize determines how many elements from the input stream are read in one go by the
+ * nanoscheduler.  The scheduler may hold up to bufferSize in memory at one time, as well
+ * as up to bufferSize map results as well.
+ *
+ * numberOfMapElementsToProcessTogether determines how many input elements are processed
+ * together each thread cycle.  For example, if this value is 10, then the input data
+ * is grouped together in units of 10 elements each, and map called on each in term.  The more
+ * heavy-weight the map function is, in terms of CPU costs, the more it makes sense to
+ * have this number be small.  The lighter the CPU cost per element, though, the more this
+ * parameter introduces overhead due to need to context switch among threads to process
+ * each input element.  A value of -1 lets the nanoscheduler guess at a reasonable trade-off value.
+ *
+ * nThreads is a bit obvious yes?  Note though that the nanoscheduler assumes that it gets 1 thread
+ * from its client during the execute call, as this call blocks until all work is done.  The caller
+ * thread is put to work by execute to help with the processing of the data.  So in reality the
+ * nanoScheduler only spawn nThreads - 1 additional workers (if this is > 1).
+ *
+ * User: depristo
+ * Date: 8/24/12
+ * Time: 9:47 AM
+ */
+public class NanoScheduler<InputType, MapType, ReduceType> {
+    private final static Logger logger = Logger.getLogger(NanoScheduler.class);
+    private final static boolean ALLOW_SINGLE_THREAD_FASTPATH = true;
+    protected final static int UPDATE_PROGRESS_FREQ = 100;
+
+    /**
+     * Currently not used, but kept because it's conceptual reasonable to have a buffer
+     */
+    final int bufferSize;
+
+    /**
+     * The number of threads we're using to execute the map jobs in this nano scheduler
+     */
+    final int nThreads;
+
+    final ExecutorService masterExecutor;
+    final ExecutorService mapExecutor;
+    final MultiThreadedErrorTracker errorTracker = new MultiThreadedErrorTracker();
+
+    boolean shutdown = false;
+    boolean debug = false;
+    private NSProgressFunction<InputType> progressFunction = null;
+
+    /**
+     * Create a new nanoscheduler with the desire characteristics requested by the argument
+     *
+     * @param nThreads the number of threads to use to get work done, in addition to the
+     *                 thread calling execute
+     */
+    public NanoScheduler(final int nThreads) {
+        this(nThreads*100, nThreads);
+    }
+
+    protected NanoScheduler(final int bufferSize, final int nThreads) {
+        if ( bufferSize < 1 ) throw new IllegalArgumentException("bufferSize must be >= 1, got " + bufferSize);
+        if ( nThreads < 1 ) throw new IllegalArgumentException("nThreads must be >= 1, got " + nThreads);
+
+        this.bufferSize = bufferSize;
+        this.nThreads = nThreads;
+
+        if ( nThreads == 1 ) {
+            this.mapExecutor = this.masterExecutor = null;
+        } else {
+            this.masterExecutor = Executors.newSingleThreadExecutor(new NamedThreadFactory("NS-master-thread-%d"));
+            this.mapExecutor = Executors.newFixedThreadPool(nThreads, new NamedThreadFactory("NS-map-thread-%d"));
+        }
+    }
+
+    /**
+     * The number of parallel map threads in use with this NanoScheduler
+     * @return
+     */
+    @Ensures("result > 0")
+    public int getnThreads() {
+        return nThreads;
+    }
+
+    /**
+     * The input buffer size used by this NanoScheduler
+     * @return
+     */
+    @Ensures("result > 0")
+    public int getBufferSize() {
+        return this.bufferSize;
+    }
+
+    /**
+     * Tells this nanoScheduler to shutdown immediately, releasing all its resources.
+     *
+     * After this call, execute cannot be invoked without throwing an error
+     */
+    public void shutdown() {
+        if ( nThreads > 1 ) {
+            shutdownExecutor("mapExecutor", mapExecutor);
+            shutdownExecutor("masterExecutor", masterExecutor);
+        }
+
+        shutdown = true;
+    }
+
+    /**
+     * Helper function to cleanly shutdown an execution service, checking that the execution
+     * state is clean when it's done.
+     *
+     * @param name a string name for error messages for the executorService we are shutting down
+     * @param executorService the executorService to shut down
+     */
+    @Requires({"name != null", "executorService != null"})
+    @Ensures("executorService.isShutdown()")
+    private void shutdownExecutor(final String name, final ExecutorService executorService) {
+        if ( executorService.isShutdown() || executorService.isTerminated() )
+            throw new IllegalStateException("Executor service " + name + " is already shut down!");
+
+        final List<Runnable> remaining = executorService.shutdownNow();
+        if ( ! remaining.isEmpty() )
+            throw new IllegalStateException(remaining.size() + " remaining tasks found in an executor " + name + ", unexpected behavior!");
+    }
+
+    /**
+     * @return true if this nanoScheduler is shutdown, or false if its still open for business
+     */
+    public boolean isShutdown() {
+        return shutdown;
+    }
+
+    /**
+     * @return are we displaying verbose debugging information about the scheduling?
+     */
+    public boolean isDebug() {
+        return debug;
+    }
+
+    /**
+     * Helper function to display a String.formatted message if we are doing verbose debugging
+     *
+     * @param format the format argument suitable for String.format
+     * @param args the arguments for String.format
+     */
+    @Requires("format != null")
+    protected void debugPrint(final String format, Object ... args) {
+        if ( isDebug() )
+            logger.warn("Thread " + Thread.currentThread().getId() + ":" + String.format(format, args));
+    }
+
+    /**
+     * Turn on/off verbose debugging
+     *
+     * @param debug true if we want verbose debugging
+     */
+    public void setDebug(boolean debug) {
+        this.debug = debug;
+    }
+
+    /**
+     * Set the progress callback function to progressFunction
+     *
+     * The progress callback is invoked after each buffer size elements have been processed by map/reduce
+     *
+     * @param progressFunction a progress function to call, or null if you don't want any progress callback
+     */
+    public void setProgressFunction(final NSProgressFunction<InputType> progressFunction) {
+        this.progressFunction = progressFunction;
+    }
+
+    /**
+     * Execute a map/reduce job with this nanoScheduler
+     *
+     * Data comes from inputReader.  Will be read until hasNext() == false.
+     * map is called on each element provided by inputReader.  No order of operations is guarenteed
+     * reduce is called in order of the input data provided by inputReader on the result of map() applied
+     * to each element.
+     *
+     * Note that the caller thread is put to work with this function call.  The call doesn't return
+     * until all elements have been processes.
+     *
+     * It is safe to call this function repeatedly on a single nanoScheduler, at least until the
+     * shutdown method is called.
+     *
+     * Note that this function goes through a single threaded fast path if the number of threads
+     * is 1.
+     *
+     * @param inputReader an iterator providing us with the input data to nanoSchedule map/reduce over
+     * @param map the map function from input type -> map type, will be applied in parallel to each input
+     * @param reduce the reduce function from map type + reduce type -> reduce type to be applied in order to map results
+     * @return the last reduce value
+     */
+    public ReduceType execute(final Iterator<InputType> inputReader,
+                              final NSMapFunction<InputType, MapType> map,
+                              final ReduceType initialValue,
+                              final NSReduceFunction<MapType, ReduceType> reduce) {
+        if ( isShutdown() ) throw new IllegalStateException("execute called on already shutdown NanoScheduler");
+        if ( inputReader == null ) throw new IllegalArgumentException("inputReader cannot be null");
+        if ( map == null ) throw new IllegalArgumentException("map function cannot be null");
+        if ( reduce == null ) throw new IllegalArgumentException("reduce function cannot be null");
+
+        ReduceType result;
+        if ( ALLOW_SINGLE_THREAD_FASTPATH && getnThreads() == 1 ) {
+            result = executeSingleThreaded(inputReader, map, initialValue, reduce);
+        } else {
+            result = executeMultiThreaded(inputReader, map, initialValue, reduce);
+        }
+
+        return result;
+    }
+
+    /**
+     * Simple efficient reference implementation for single threaded execution.
+     *
+     * @return the reduce result of this map/reduce job
+     */
+    @Requires({"inputReader != null", "map != null", "reduce != null"})
+    private ReduceType executeSingleThreaded(final Iterator<InputType> inputReader,
+                                             final NSMapFunction<InputType, MapType> map,
+                                             final ReduceType initialValue,
+                                             final NSReduceFunction<MapType, ReduceType> reduce) {
+        ReduceType sum = initialValue;
+        int i = 0;
+
+        while ( true ) {
+            // start timer to ensure that both hasNext and next are caught by the timer
+            if ( ! inputReader.hasNext() ) {
+                break;
+            } else {
+                final InputType input = inputReader.next();
+
+                // map
+                final MapType mapValue = map.apply(input);
+
+                updateProgress(i++, input);
+
+                // reduce
+                sum = reduce.apply(mapValue, sum);
+            }
+        }
+
+        return sum;
+    }
+
+    /**
+     * Maybe update the progress meter (maybe because we don't want to do so so often that it costs cpu time)
+     * @param counter increasing counter to use to cut down on updates
+     * @param input the input we're currently at
+     */
+    private void updateProgress(final int counter, final InputType input) {
+        if ( progressFunction != null && counter % UPDATE_PROGRESS_FREQ == 0 )
+            progressFunction.progress(input);
+    }
+
+    /**
+     * Efficient parallel version of Map/Reduce
+     *
+     * @return the reduce result of this map/reduce job
+     */
+    @Requires({"inputReader != null", "map != null", "reduce != null"})
+    private ReduceType executeMultiThreaded(final Iterator<InputType> inputReader,
+                                            final NSMapFunction<InputType, MapType> map,
+                                            final ReduceType initialValue,
+                                            final NSReduceFunction<MapType, ReduceType> reduce) {
+        debugPrint("Executing nanoScheduler");
+
+        // start up the master job
+        final MasterJob masterJob = new MasterJob(inputReader, map, initialValue, reduce);
+        final Future<ReduceType> reduceResult = masterExecutor.submit(masterJob);
+
+        while ( true ) {
+            // check that no errors occurred while we were waiting
+            handleErrors();
+//            checkForDeadlocks();
+
+            try {
+                final ReduceType result = reduceResult.get(100, TimeUnit.MILLISECONDS);
+
+                // in case an error occurred in the reduce
+                handleErrors();
+
+                // return our final reduce result
+                return result;
+            } catch (final TimeoutException ex ) {
+                // a normal case -- we just aren't done
+            } catch (final InterruptedException ex) {
+                errorTracker.notifyOfError(ex);
+                // will handle error in the next round of the for loop
+            } catch (final ExecutionException ex) {
+                errorTracker.notifyOfError(ex);
+                // will handle error in the next round of the for loop
+            }
+        }
+    }
+
+//    private void checkForDeadlocks() {
+//        if ( deadLockCheckCounter++ % 100 == 0 ) {
+//            logger.info("Checking for deadlocks...");
+//            final ThreadMXBean bean = ManagementFactory.getThreadMXBean();
+//            final long[] threadIds = bean.findDeadlockedThreads(); // Returns null if no threads are deadlocked.
+//
+//            if (threadIds != null) {
+//                final ThreadInfo[] infos = bean.getThreadInfo(threadIds);
+//
+//                logger.error("!!! Deadlock detected !!!!");
+//                for (final ThreadInfo info : infos) {
+//                    logger.error("Thread " + info);
+//                    for ( final StackTraceElement elt : info.getStackTrace() ) {
+//                        logger.error("\t" + elt.toString());
+//                    }
+//                }
+//            }
+//        }
+//    }
+
+    private void handleErrors() {
+        if ( errorTracker.hasAnErrorOccurred() ) {
+            masterExecutor.shutdownNow();
+            mapExecutor.shutdownNow();
+            errorTracker.throwErrorIfPending();
+        }
+    }
+
+    /**
+     * MasterJob has the task to enqueue Map jobs and wait for the final reduce
+     *
+     * It must be run in a separate thread in order to properly handle errors that may occur
+     * in the input, map, or reduce jobs without deadlocking.
+     *
+     * The result of this callable is the final reduce value for the input / map / reduce jobs
+     */
+    private class MasterJob implements Callable<ReduceType> {
+        final Iterator<InputType> inputReader;
+        final NSMapFunction<InputType, MapType> map;
+        final ReduceType initialValue;
+        final NSReduceFunction<MapType, ReduceType> reduce;
+
+        private MasterJob(Iterator<InputType> inputReader, NSMapFunction<InputType, MapType> map, ReduceType initialValue, NSReduceFunction<MapType, ReduceType> reduce) {
+            this.inputReader = inputReader;
+            this.map = map;
+            this.initialValue = initialValue;
+            this.reduce = reduce;
+        }
+
+        @Override
+        public ReduceType call() {
+            // Create the input producer and start it running
+            final InputProducer<InputType> inputProducer = new InputProducer<InputType>(inputReader);
+
+            // create the MapResultsQueue to store results of map jobs.
+            final MapResultsQueue<MapType> mapResultQueue = new MapResultsQueue<MapType>();
+
+            // create the reducer we'll use for this nano scheduling run
+            final Reducer<MapType, ReduceType> reducer = new Reducer<MapType, ReduceType>(reduce, errorTracker, initialValue);
+
+            final CountDownLatch runningMapJobs = new CountDownLatch(nThreads);
+
+            try {
+                // create and submit the info needed by the read/map/reduce threads to do their work
+                for ( int i = 0; i < nThreads; i++ ) {
+                    mapExecutor.submit(new ReadMapReduceJob(inputProducer, mapResultQueue, runningMapJobs, map, reducer));
+                }
+
+                // wait for all of the input and map threads to finish
+                return waitForCompletion(mapResultQueue, runningMapJobs, reducer);
+            } catch (Throwable ex) {
+                errorTracker.notifyOfError(ex);
+                return initialValue;
+            }
+        }
+
+        /**
+         * Wait until the input thread and all map threads have completed running, and return the final reduce result
+         */
+        private ReduceType waitForCompletion(final MapResultsQueue<MapType> mapResultsQueue,
+                                             final CountDownLatch runningMapJobs,
+                                             final Reducer<MapType, ReduceType> reducer) throws InterruptedException {
+            // wait for all the map threads to finish by waiting on the runningMapJobs latch
+            runningMapJobs.await();
+
+            // do a final reduce here.  This is critically important because the InputMapReduce jobs
+            // no longer block on reducing, so it's possible for all the threads to end with a few
+            // reduce jobs on the queue still to do.  This call ensures that we reduce everything
+            reducer.reduceAsMuchAsPossible(mapResultsQueue, true);
+
+            // wait until we have a final reduce result
+            final ReduceType finalSum = reducer.getReduceResult();
+
+            // everything is finally shutdown, return the final reduce value
+            return finalSum;
+        }
+    }
+
+    private class ReadMapReduceJob implements Runnable {
+        final InputProducer<InputType> inputProducer;
+        final MapResultsQueue<MapType> mapResultQueue;
+        final NSMapFunction<InputType, MapType> map;
+        final Reducer<MapType, ReduceType> reducer;
+        final CountDownLatch runningMapJobs;
+
+        private ReadMapReduceJob(final InputProducer<InputType> inputProducer,
+                                 final MapResultsQueue<MapType> mapResultQueue,
+                                 final CountDownLatch runningMapJobs,
+                                 final NSMapFunction<InputType, MapType> map,
+                                 final Reducer<MapType, ReduceType> reducer) {
+            this.inputProducer = inputProducer;
+            this.mapResultQueue = mapResultQueue;
+            this.runningMapJobs = runningMapJobs;
+            this.map = map;
+            this.reducer = reducer;
+        }
+
+        @Override
+        public void run() {
+            try {
+                boolean done = false;
+                while ( ! done ) {
+                    // get the next item from the input producer
+                    final InputProducer<InputType>.InputValue inputWrapper = inputProducer.next();
+
+                    // depending on inputWrapper, actually do some work or not, putting result input result object
+                    final MapResult<MapType> result;
+                    if ( ! inputWrapper.isEOFMarker() ) {
+                        // just skip doing anything if we don't have work to do, which is possible
+                        // because we don't necessarily know how much input there is when we queue
+                        // up our jobs
+                        final InputType input = inputWrapper.getValue();
+
+                        // actually execute the map
+                        final MapType mapValue = map.apply(input);
+
+                        // enqueue the result into the mapResultQueue
+                        result = new MapResult<MapType>(mapValue, inputWrapper.getId());
+
+                        mapResultQueue.put(result);
+
+                        // reduce as much as possible, without blocking, if another thread is already doing reduces
+                        final int nReduced = reducer.reduceAsMuchAsPossible(mapResultQueue, false);
+
+                        updateProgress(inputWrapper.getId(), input);
+                    } else {
+                        done = true;
+                    }
+                }
+            } catch (Throwable ex) {
+                errorTracker.notifyOfError(ex);
+            } finally {
+                // we finished a map job, release the job queue semaphore
+                runningMapJobs.countDown();
+            }
+        }
+    }
+}
\ No newline at end of file
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/nanoScheduler/Reducer.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/nanoScheduler/Reducer.java
new file mode 100644
index 0000000..41b612f
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/nanoScheduler/Reducer.java
@@ -0,0 +1,169 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.utils.nanoScheduler;
+
+import com.google.java.contract.Ensures;
+import org.apache.log4j.Logger;
+import org.broadinstitute.gatk.utils.MultiThreadedErrorTracker;
+
+import java.util.concurrent.locks.Lock;
+import java.util.concurrent.locks.ReentrantLock;
+
+/**
+ * Reducer supporting multi-threaded reduce of the map/reduce.
+ *
+ * reduceAsMuchAsPossible is the key function.  Multiple threads can call into this, providing
+ * the map results queue, and this class accumulates the result of calling reduce
+ * on the maps objects.  reduceAsMuchAsPossible isn't directly synchronized, but manages multi-threading
+ * directly with a lock.  Threads can request either to block on the reduce call until it can be
+ * executed, or immediately exit if the lock isn't available.  That allows multi-threaded users
+ * to avoid piling up waiting to reduce while one thread is reducing.  They can instead immediately
+ * leave to go do something else productive
+ *
+ * @author depristo
+ * @since 2012
+ */
+class Reducer<MapType, ReduceType> {
+    private final static Logger logger = Logger.getLogger(Reducer.class);
+
+    /**
+     * The reduce function to execute
+     */
+    private final NSReduceFunction<MapType, ReduceType> reduce;
+
+    /**
+     * Used to communicate errors to the outer master thread
+     */
+    private final MultiThreadedErrorTracker errorTracker;
+
+    /**
+     * Lock used to protect the call reduceAsMuchAsPossible from race conditions
+     */
+    private final Lock reduceLock = new ReentrantLock();
+
+    /**
+     * The sum of the reduce function applied to all MapResults.  After this Reducer
+     * is done sum contains the final reduce result.
+     */
+    ReduceType sum;
+
+    /**
+     * Create a new Reducer that will apply the reduce function with initialSum value
+     * to values via reduceAsMuchAsPossible, timing the reduce function call costs with
+     * reduceTimer
+     *
+     * @param reduce the reduce function to apply
+     * @param initialSum the initial reduce sum
+     */
+    public Reducer(final NSReduceFunction<MapType, ReduceType> reduce,
+                   final MultiThreadedErrorTracker errorTracker,
+                   final ReduceType initialSum) {
+        if ( errorTracker == null ) throw new IllegalArgumentException("Error tracker cannot be null");
+        if ( reduce == null ) throw new IllegalArgumentException("Reduce function cannot be null");
+
+        this.errorTracker = errorTracker;
+        this.reduce = reduce;
+        this.sum = initialSum;
+    }
+
+    /**
+     * Reduce as much data as possible in mapResultQueue, returning the number of reduce calls completed
+     *
+     * As much as possible is defined as all of the MapResults in the queue are in order starting from the
+     * numSubmittedJobs we reduced previously, up to the either the queue being empty or where the next MapResult
+     * doesn't have JobID == prevJobID + 1.
+     *
+     * @param mapResultQueue a queue of MapResults in jobID order
+     * @return the number of reduces run, from 0 >
+     * @throws InterruptedException
+     */
+    @Ensures("result >= 0")
+    public int reduceAsMuchAsPossible(final MapResultsQueue<MapType> mapResultQueue, final boolean waitForLock) {
+        if ( mapResultQueue == null ) throw new IllegalArgumentException("mapResultQueue cannot be null");
+        int nReducesNow = 0;
+
+        final boolean haveLock = acquireReduceLock(waitForLock);
+        try {
+            if ( haveLock ) {
+                while ( mapResultQueue.nextValueIsAvailable() ) {
+                    final MapResult<MapType> result = mapResultQueue.take();
+
+                    if ( ! result.isEOFMarker() ) {
+                        nReducesNow++;
+
+                        // apply reduce, keeping track of sum
+                        sum = reduce.apply(result.getValue(), sum);
+                    }
+                }
+            }
+        } catch (Exception ex) {
+            errorTracker.notifyOfError(ex);
+        } finally {
+            if ( haveLock ) // if we acquired the lock, unlock it
+                releaseReduceLock();
+        }
+
+        return nReducesNow;
+    }
+
+    /**
+     * Acquire the reduce lock, either returning immediately if not possible or blocking until the lock is available
+     *
+     * @param blockUntilAvailable if true, we will block until the lock is available, otherwise we return immediately
+     *                            without acquiring the lock
+     * @return true if the lock has been acquired, false otherwise
+     */
+    protected boolean acquireReduceLock(final boolean blockUntilAvailable) {
+        if ( blockUntilAvailable ) {
+            reduceLock.lock();
+            return true;
+        } else {
+            return reduceLock.tryLock();
+        }
+    }
+
+    /**
+     * Free the reduce lock.
+     *
+     * Assumes that the invoking thread actually previously acquired the lock (it's a problem if not).
+     */
+    protected void releaseReduceLock() {
+        reduceLock.unlock();
+    }
+
+    /**
+     * Get the current reduce result resulting from applying reduce(...) to all MapResult elements.
+     *
+     * Note that this method cannot know if future reduce calls are coming in.  So it simply gets
+     * the current reduce result.  It is up to the caller to know whether the returned value is
+     * a partial result, or the full final value
+     *
+     * @return the total reduce result across all jobs
+     */
+    public ReduceType getReduceResult() {
+        return sum;
+    }
+}
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/pairhmm/BatchPairHMM.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/pairhmm/BatchPairHMM.java
new file mode 100644
index 0000000..2311564
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/pairhmm/BatchPairHMM.java
@@ -0,0 +1,41 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.utils.pairhmm;
+
+import org.broadinstitute.gatk.utils.haplotype.Haplotype;
+
+import java.util.List;
+
+public interface BatchPairHMM {
+    public void batchAdd(final List<Haplotype> haplotypes,
+                         final byte[] readBases,
+                         final byte[] readQuals,
+                         final byte[] insertionGOP,
+                         final byte[] deletionGOP,
+                         final byte[] overallGCP);
+
+    public double[] batchGetResult();
+}
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/pairhmm/Log10PairHMM.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/pairhmm/Log10PairHMM.java
new file mode 100644
index 0000000..4d84fc5
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/pairhmm/Log10PairHMM.java
@@ -0,0 +1,220 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.utils.pairhmm;
+
+import com.google.java.contract.Ensures;
+import com.google.java.contract.Requires;
+import org.broadinstitute.gatk.utils.MathUtils;
+import org.broadinstitute.gatk.utils.QualityUtils;
+
+import java.util.Arrays;
+
+import static java.lang.Math.log10;
+import static org.broadinstitute.gatk.utils.pairhmm.PairHMMModel.*;
+
+/**
+ * Util class for performing the pair HMM for local alignment. Figure 4.3 in Durbin 1998 book.
+ *
+ * User: rpoplin, carneiro
+ * Date: 3/1/12
+ */
+public class Log10PairHMM extends N2MemoryPairHMM {
+    /**
+     * Should we use exact log10 calculation (true), or an approximation (false)?
+     */
+    private final boolean doExactLog10;
+
+
+    // we divide e by 3 because the observed base could have come from any of the non-observed alleles
+    protected final static double log10_3 = log10(3.0);
+
+    /**
+     * Create an uninitialized PairHMM
+     *
+     * @param doExactLog10 should the log10 calculations be exact (slow) or approximate (faster)
+     */
+    public Log10PairHMM(final boolean doExactLog10) {
+        this.doExactLog10 = doExactLog10;
+    }
+
+    /**
+     * Is this HMM using exact log10 calculations?
+     * @return true if exact, false if approximate
+     */
+    public boolean isDoingExactLog10Calculations() {
+        return doExactLog10;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public void initialize(final int readMaxLength, final int haplotypeMaxLength ) {
+        super.initialize(readMaxLength, haplotypeMaxLength);
+
+        for( int iii=0; iii < paddedMaxReadLength; iii++ ) {
+            Arrays.fill(matchMatrix[iii], Double.NEGATIVE_INFINITY);
+            Arrays.fill(insertionMatrix[iii], Double.NEGATIVE_INFINITY);
+            Arrays.fill(deletionMatrix[iii], Double.NEGATIVE_INFINITY);
+        }
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public double subComputeReadLikelihoodGivenHaplotypeLog10( final byte[] haplotypeBases,
+                                                               final byte[] readBases,
+                                                               final byte[] readQuals,
+                                                               final byte[] insertionGOP,
+                                                               final byte[] deletionGOP,
+                                                               final byte[] overallGCP,
+                                                               final int hapStartIndex,
+                                                               final boolean recacheReadValues,
+                                                               final int nextHapStartIndex) {
+
+
+        if ( ! constantsAreInitialized || recacheReadValues )
+            initializeProbabilities(insertionGOP, deletionGOP, overallGCP);
+        initializePriors(haplotypeBases, readBases, readQuals, hapStartIndex);
+        if (previousHaplotypeBases == null || previousHaplotypeBases.length != haplotypeBases.length) {
+            // set the initial value (free deletions in the beginning) for the first row in the deletion matrix
+            initializeMatrixValues(haplotypeBases);
+        }
+
+        for (int i = 1; i < paddedReadLength; i++) {
+            // +1 here is because hapStartIndex is 0-based, but our matrices are 1 based
+            for (int j = hapStartIndex+1; j < paddedHaplotypeLength; j++) {
+                updateCell(i, j, prior[i][j], transition[i]);
+            }
+        }
+
+        // final probability is the log10 sum of the last element in the Match and Insertion state arrays
+        // this way we ignore all paths that ended in deletions! (huge)
+        // but we have to sum all the paths ending in the M and I matrices, because they're no longer extended.
+        return finalLikelihoodCalculation();
+    }
+
+    protected void initializeMatrixValues(final byte[] haplotypeBases) {
+        final double initialValue = Math.log10(1.0 / haplotypeBases.length);
+        for( int j = 0; j < paddedHaplotypeLength; j++ ) {
+            deletionMatrix[0][j] = initialValue;
+        }
+    }
+
+    protected double finalLikelihoodCalculation() {
+        final int endI = paddedReadLength - 1;
+        double finalSumProbabilities = myLog10SumLog10(new double[]{matchMatrix[endI][1], insertionMatrix[endI][1]});
+        for (int j = 2; j < paddedHaplotypeLength; j++)
+            finalSumProbabilities = myLog10SumLog10(new double[]{finalSumProbabilities, matchMatrix[endI][j], insertionMatrix[endI][j]});
+        return finalSumProbabilities;
+    }
+
+
+    /**
+     * Initializes the matrix that holds all the constants related to the editing
+     * distance between the read and the haplotype.
+     *
+     * @param haplotypeBases the bases of the haplotype
+     * @param readBases      the bases of the read
+     * @param readQuals      the base quality scores of the read
+     * @param startIndex     where to start updating the distanceMatrix (in case this read is similar to the previous read)
+     */
+    public void initializePriors(final byte[] haplotypeBases, final byte[] readBases, final byte[] readQuals, final int startIndex) {
+
+        // initialize the pBaseReadLog10 matrix for all combinations of read x haplotype bases
+        // Abusing the fact that java initializes arrays with 0.0, so no need to fill in rows and columns below 2.
+
+        for (int i = 0; i < readBases.length; i++) {
+            final byte x = readBases[i];
+            final byte qual = readQuals[i];
+            for (int j = startIndex; j < haplotypeBases.length; j++) {
+                final byte y = haplotypeBases[j];
+                prior[i+1][j+1] = ( x == y || x == (byte) 'N' || y == (byte) 'N' ?
+                        QualityUtils.qualToProbLog10(qual) : (QualityUtils.qualToErrorProbLog10(qual) - (doNotUseTristateCorrection ? 0.0 : log10_3)) );
+            }
+        }
+    }
+
+    /**
+     * Initializes the matrix that holds all the constants related to quality scores.
+     *
+     * @param insertionGOP   insertion quality scores of the read
+     * @param deletionGOP    deletion quality scores of the read
+     * @param overallGCP     overall gap continuation penalty
+     */
+    @Requires({
+            "insertionGOP != null",
+            "deletionGOP != null",
+            "overallGCP != null"
+    })
+    @Ensures("constantsAreInitialized")
+    protected void initializeProbabilities(final byte[] insertionGOP, final byte[] deletionGOP, final byte[] overallGCP) {
+        PairHMMModel.qualToTransProbsLog10(transition,insertionGOP,deletionGOP,overallGCP);
+        // note that we initialized the constants
+        constantsAreInitialized = true;
+    }
+
+
+    /**
+     * Compute the log10SumLog10 of the values
+     *
+     * NOTE NOTE NOTE
+     *
+     * Log10PairHMM depends critically on this function tolerating values that are all -Infinity
+     * and the sum returning -Infinity.  Note good.  Needs to be fixed.
+     *
+     * NOTE NOTE NOTE
+     *
+     * @param values an array of log10 probabilities that need to be summed
+     * @return the log10 of the sum of the probabilities
+     */
+    @Requires("values != null")
+    protected double myLog10SumLog10(final double[] values) {
+        return doExactLog10 ? MathUtils.log10sumLog10(values) : MathUtils.approximateLog10SumLog10(values);
+    }
+
+    /**
+     * Updates a cell in the HMM matrix
+     *
+     * The read and haplotype indices are offset by one because the state arrays have an extra column to hold the
+     * initial conditions
+
+     * @param indI             row index in the matrices to update
+     * @param indJ             column index in the matrices to update
+     * @param prior            the likelihood editing distance matrix for the read x haplotype
+     * @param transition        an array with the six transition relevant to this location
+     */
+    protected void updateCell( final int indI, final int indJ, final double prior, final double[] transition) {
+
+        matchMatrix[indI][indJ] = prior +
+                myLog10SumLog10(new double[]{matchMatrix[indI - 1][indJ - 1] + transition[matchToMatch],
+                                         insertionMatrix[indI - 1][indJ - 1] + transition[indelToMatch],
+                                          deletionMatrix[indI - 1][indJ - 1] + transition[indelToMatch]});
+        insertionMatrix[indI][indJ] = myLog10SumLog10(new double[] {matchMatrix[indI - 1][indJ] + transition[matchToInsertion], insertionMatrix[indI - 1][indJ] + transition[insertionToInsertion]});
+        deletionMatrix[indI][indJ]  = myLog10SumLog10(new double[] {matchMatrix[indI][indJ - 1] + transition[matchToDeletion],  deletionMatrix[indI][indJ - 1] + transition[deletionToDeletion]});
+    }
+}
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/pairhmm/N2MemoryPairHMM.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/pairhmm/N2MemoryPairHMM.java
new file mode 100644
index 0000000..0e0ffb5
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/pairhmm/N2MemoryPairHMM.java
@@ -0,0 +1,98 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.utils.pairhmm;
+
+import com.google.java.contract.Requires;
+
+/**
+ * Superclass for PairHMM that want to use a full read x haplotype matrix for their match, insertion, and deletion matrix
+ *
+ * User: rpoplin
+ * Date: 10/16/12
+ */
+abstract class N2MemoryPairHMM extends PairHMM {
+    protected double[][] transition = null; // The transition probabilities cache
+    protected double[][] prior = null;      // The prior probabilities cache
+    protected double[][] matchMatrix = null;
+    protected double[][] insertionMatrix = null;
+    protected double[][] deletionMatrix = null;
+
+    // only used for debugging purposes
+    protected boolean doNotUseTristateCorrection = false;
+
+    public void doNotUseTristateCorrection() {
+        doNotUseTristateCorrection = true;
+    }
+
+    /**
+     * Initialize this PairHMM, making it suitable to run against a read and haplotype with given lengths
+     *
+     * Note: Do not worry about padding, just provide the true max length of the read and haplotype. The HMM will take care of the padding.
+     *
+     * @param haplotypeMaxLength the max length of haplotypes we want to use with this PairHMM
+     * @param readMaxLength the max length of reads we want to use with this PairHMM
+     */
+    @Override
+    public void initialize( final int readMaxLength, final int haplotypeMaxLength ) {
+        super.initialize(readMaxLength, haplotypeMaxLength);
+
+        matchMatrix = new double[paddedMaxReadLength][paddedMaxHaplotypeLength];
+        insertionMatrix = new double[paddedMaxReadLength][paddedMaxHaplotypeLength];
+        deletionMatrix = new double[paddedMaxReadLength][paddedMaxHaplotypeLength];
+
+        transition = PairHMMModel.createTransitionMatrix(maxReadLength);
+        prior = new double[paddedMaxReadLength][paddedMaxHaplotypeLength];
+    }
+
+    /**
+     * Print out the core hmm matrices for debugging
+     */
+    protected void dumpMatrices() {
+        dumpMatrix("matchMetricArray", matchMatrix);
+        dumpMatrix("insertionMatrix", insertionMatrix);
+        dumpMatrix("deletionMatrix", deletionMatrix);
+    }
+
+    /**
+     * Print out in a human readable form the matrix for debugging
+     * @param name the name of this matrix
+     * @param matrix the matrix of values
+     */
+    @Requires({"name != null", "matrix != null"})
+    private void dumpMatrix(final String name, final double[][] matrix) {
+        System.out.printf("%s%n", name);
+        for ( int i = 0; i < matrix.length; i++) {
+            System.out.printf("\t%s[%d]", name, i);
+            for ( int j = 0; j < matrix[i].length; j++ ) {
+                if ( Double.isInfinite(matrix[i][j]) )
+                    System.out.printf(" %15s", String.format("%f", matrix[i][j]));
+                else
+                    System.out.printf(" % 15.5e", matrix[i][j]);
+            }
+            System.out.println();
+        }
+    }
+}
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/pairhmm/PairHMM.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/pairhmm/PairHMM.java
new file mode 100644
index 0000000..6c4460c
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/pairhmm/PairHMM.java
@@ -0,0 +1,357 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.utils.pairhmm;
+
+import com.google.java.contract.Requires;
+import htsjdk.variant.variantcontext.Allele;
+import org.apache.log4j.Logger;
+import org.broadinstitute.gatk.utils.MathUtils;
+import org.broadinstitute.gatk.utils.genotyper.ReadLikelihoods;
+import org.broadinstitute.gatk.utils.haplotype.Haplotype;
+import org.broadinstitute.gatk.utils.sam.GATKSAMRecord;
+
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.List;
+import java.util.Map;
+/**
+ * Util class for performing the pair HMM for local alignment. Figure 4.3 in Durbin 1998 book.
+ *
+ * User: rpoplin
+ * Date: 10/16/12
+ */
+public abstract class PairHMM {
+    protected final static Logger logger = Logger.getLogger(PairHMM.class);
+
+    protected boolean constantsAreInitialized = false;
+
+    protected byte[] previousHaplotypeBases;
+    protected int hapStartIndex;
+
+    public enum HMM_IMPLEMENTATION {
+        /* Very slow implementation which uses very accurate log10 sum functions. Only meant to be used as a reference test implementation */
+        EXACT,
+        /* PairHMM as implemented for the UnifiedGenotyper. Uses log10 sum functions accurate to only 1E-4 */
+        ORIGINAL,
+        /* Optimized version of the PairHMM which caches per-read computations and operations in real space to avoid costly sums of log10'ed likelihoods */
+        LOGLESS_CACHING,
+        /* Optimized AVX implementation of LOGLESS_CACHING called through JNI */
+        VECTOR_LOGLESS_CACHING,
+        /* Debugging for vector implementation of LOGLESS_CACHING */
+        DEBUG_VECTOR_LOGLESS_CACHING,
+        /* Logless caching PairHMM that stores computations in 1D arrays instead of matrices, and which proceeds diagonally over the (read x haplotype) intersection matrix */
+        ARRAY_LOGLESS
+    }
+
+    protected int maxHaplotypeLength, maxReadLength;
+    protected int paddedMaxReadLength, paddedMaxHaplotypeLength;
+    protected int paddedReadLength, paddedHaplotypeLength;
+    protected boolean initialized = false;
+
+    // only used for debugging purposes
+    protected boolean doNotUseTristateCorrection = false;
+    protected void doNotUseTristateCorrection() { doNotUseTristateCorrection = true; }
+
+    //debug array
+    protected double[] mLikelihoodArray;
+
+    //profiling information
+    protected static Boolean doProfiling = true;
+    protected static long pairHMMComputeTime = 0;
+    protected long threadLocalPairHMMComputeTimeDiff = 0;
+    protected long startTime = 0;
+
+    /**
+     * Initialize this PairHMM, making it suitable to run against a read and haplotype with given lengths
+     *
+     * Note: Do not worry about padding, just provide the true max length of the read and haplotype. The HMM will take care of the padding.
+     *
+     * @param haplotypeMaxLength the max length of haplotypes we want to use with this PairHMM
+     * @param readMaxLength the max length of reads we want to use with this PairHMM
+     */
+    public void initialize( final int readMaxLength, final int haplotypeMaxLength ) {
+        if ( readMaxLength <= 0 ) throw new IllegalArgumentException("READ_MAX_LENGTH must be > 0 but got " + readMaxLength);
+        if ( haplotypeMaxLength <= 0 ) throw new IllegalArgumentException("HAPLOTYPE_MAX_LENGTH must be > 0 but got " + haplotypeMaxLength);
+
+        maxHaplotypeLength = haplotypeMaxLength;
+        maxReadLength = readMaxLength;
+
+        // M, X, and Y arrays are of size read and haplotype + 1 because of an extra column for initial conditions and + 1 to consider the final base in a non-global alignment
+        paddedMaxReadLength = readMaxLength + 1;
+        paddedMaxHaplotypeLength = haplotypeMaxLength + 1;
+
+        previousHaplotypeBases = null;
+
+        constantsAreInitialized = false;
+        initialized = true;
+    }
+
+    /**
+     * Called at the end of PairHMM for a region - mostly used by the JNI implementations
+     */
+    public void finalizeRegion()
+    {
+        ;
+    }
+
+    /**
+     * Initialize this PairHMM, making it suitable to run against a read and haplotype with given lengths
+     * This function is used by the JNI implementations to transfer all data once to the native code
+     * @param haplotypes the list of haplotypes
+     * @param perSampleReadList map from sample name to list of reads
+     * @param haplotypeMaxLength the max length of haplotypes we want to use with this PairHMM
+     * @param readMaxLength the max length of reads we want to use with this PairHMM
+     */
+    public void initialize( final List<Haplotype> haplotypes, final Map<String, List<GATKSAMRecord>> perSampleReadList, final int readMaxLength, final int haplotypeMaxLength ) {
+        initialize(readMaxLength, haplotypeMaxLength);
+    }
+
+    private int findMaxReadLength(final GATKSAMRecord ... reads) {
+        int max = 0;
+        for (final GATKSAMRecord read : reads) {
+            final int readLength = read.getReadLength();
+            if (max < readLength)
+                max = readLength;
+        }
+        return max;
+    }
+
+    private int findMaxAlleleLength(final List<? extends Allele> alleles) {
+        int max = 0;
+        for (final Allele allele : alleles) {
+            final int alleleLength = allele.length();
+            if (max < alleleLength)
+                max = alleleLength;
+        }
+        return max;
+    }
+
+    protected int findMaxReadLength(final List<GATKSAMRecord> reads) {
+        int listMaxReadLength = 0;
+        for(GATKSAMRecord read : reads){
+            final int readLength = read.getReadLength();
+            if( readLength > listMaxReadLength ) { listMaxReadLength = readLength; }
+        }
+        return listMaxReadLength;
+    }
+
+    protected int findMaxHaplotypeLength(final Collection<Haplotype> haplotypes) {
+        int listMaxHaplotypeLength = 0;
+        for( final Haplotype h : haplotypes) {
+            final int haplotypeLength = h.getBases().length;
+            if( haplotypeLength > listMaxHaplotypeLength ) { listMaxHaplotypeLength = haplotypeLength; }
+        }
+        return listMaxHaplotypeLength;
+    }
+
+    /**
+     *  Given a list of reads and haplotypes, for every read compute the total probability of said read arising from
+     *  each haplotype given base substitution, insertion, and deletion probabilities.
+     *
+     * @param processedReads reads to analyze instead of the ones present in the destination read-likelihoods.
+     * @param likelihoods where to store the likelihoods where position [a][r] is reserved for the likelihood of {@code reads[r]}
+     *             conditional to {@code alleles[a]}.
+     * @param gcp penalty for gap continuations base array map for processed reads.
+     *
+     * @throws IllegalArgumentException
+     *
+     * @return never {@code null}.
+     */
+    public void computeLikelihoods(final ReadLikelihoods.Matrix<Haplotype> likelihoods,
+                                   final List<GATKSAMRecord> processedReads,
+                                   final Map<GATKSAMRecord,byte[]> gcp) {
+        if (processedReads.isEmpty())
+            return;
+        if(doProfiling)
+            startTime = System.nanoTime();
+        // (re)initialize the pairHMM only if necessary
+        final int readMaxLength = findMaxReadLength(processedReads);
+        final int haplotypeMaxLength = findMaxAlleleLength(likelihoods.alleles());
+        if (!initialized || readMaxLength > maxReadLength || haplotypeMaxLength > maxHaplotypeLength)
+            initialize(readMaxLength, haplotypeMaxLength);
+
+        final int readCount = processedReads.size();
+        final List<Haplotype> alleles = likelihoods.alleles();
+        final int alleleCount = alleles.size();
+        mLikelihoodArray = new double[readCount * alleleCount];
+        int idx = 0;
+        int readIndex = 0;
+        for(final GATKSAMRecord read : processedReads){
+            final byte[] readBases = read.getReadBases();
+            final byte[] readQuals = read.getBaseQualities();
+            final byte[] readInsQuals = read.getBaseInsertionQualities();
+            final byte[] readDelQuals = read.getBaseDeletionQualities();
+            final byte[] overallGCP = gcp.get(read);
+
+            // peak at the next haplotype in the list (necessary to get nextHaplotypeBases, which is required for caching in the array implementation)
+            final boolean isFirstHaplotype = true;
+            for (int a = 0; a < alleleCount; a++) {
+                final Allele allele = alleles.get(a);
+                final byte[] alleleBases = allele.getBases();
+                final byte[] nextAlleleBases = a == alleles.size() - 1 ? null : alleles.get(a + 1).getBases();
+                final double lk = computeReadLikelihoodGivenHaplotypeLog10(alleleBases,
+                        readBases, readQuals, readInsQuals, readDelQuals, overallGCP, isFirstHaplotype, nextAlleleBases);
+                likelihoods.set(a, readIndex, lk);
+                mLikelihoodArray[idx++] = lk;
+            }
+            readIndex++;
+        }
+        if(doProfiling) {
+            threadLocalPairHMMComputeTimeDiff = (System.nanoTime() - startTime);
+            //synchronized(doProfiling)
+            {
+                pairHMMComputeTime += threadLocalPairHMMComputeTimeDiff;
+            }
+        }
+    }
+
+    /**
+     * Compute the total probability of read arising from haplotypeBases given base substitution, insertion, and deletion
+     * probabilities.
+     *
+     * Note on using hapStartIndex.  This allows you to compute the exact true likelihood of a full haplotypes
+     * given a read, assuming that the previous calculation read over a full haplotype, recaching the read values,
+     * starting only at the place where the new haplotype bases and the previous haplotype bases different.  This
+     * index is 0-based, and can be computed with findFirstPositionWhereHaplotypesDiffer given the two haplotypes.
+     * Note that this assumes that the read and all associated quals values are the same.
+     *
+     * @param haplotypeBases the full sequence (in standard SAM encoding) of the haplotype, must be >= than read bases in length
+     * @param readBases the bases (in standard encoding) of the read, must be <= haplotype bases in length
+     * @param readQuals the phred-scaled per base substitution quality scores of read.  Must be the same length as readBases
+     * @param insertionGOP the phred-scaled per base insertion quality scores of read.  Must be the same length as readBases
+     * @param deletionGOP the phred-scaled per base deletion quality scores of read.  Must be the same length as readBases
+     * @param overallGCP the phred-scaled gap continuation penalties scores of read.  Must be the same length as readBases
+     * @param recacheReadValues if false, we don't recalculate any cached results, assuming that readBases and its associated
+     *                          parameters are the same, and only the haplotype bases are changing underneath us
+     * @return the log10 probability of read coming from the haplotype under the provided error model
+     */
+    protected final double computeReadLikelihoodGivenHaplotypeLog10( final byte[] haplotypeBases,
+                                                                  final byte[] readBases,
+                                                                  final byte[] readQuals,
+                                                                  final byte[] insertionGOP,
+                                                                  final byte[] deletionGOP,
+                                                                  final byte[] overallGCP,
+                                                                  final boolean recacheReadValues,
+                                                                  final byte[] nextHaploytpeBases) {
+
+        if ( ! initialized ) throw new IllegalStateException("Must call initialize before calling computeReadLikelihoodGivenHaplotypeLog10");
+        if ( haplotypeBases == null ) throw new IllegalArgumentException("haplotypeBases cannot be null");
+        if ( haplotypeBases.length > maxHaplotypeLength ) throw new IllegalArgumentException("Haplotype bases is too long, got " + haplotypeBases.length + " but max is " + maxHaplotypeLength);
+        if ( readBases == null ) throw new IllegalArgumentException("readBases cannot be null");
+        if ( readBases.length > maxReadLength ) throw new IllegalArgumentException("readBases is too long, got " + readBases.length + " but max is " + maxReadLength);
+        if ( readQuals.length != readBases.length ) throw new IllegalArgumentException("Read bases and read quals aren't the same size: " + readBases.length + " vs " + readQuals.length);
+        if ( insertionGOP.length != readBases.length ) throw new IllegalArgumentException("Read bases and read insertion quals aren't the same size: " + readBases.length + " vs " + insertionGOP.length);
+        if ( deletionGOP.length != readBases.length ) throw new IllegalArgumentException("Read bases and read deletion quals aren't the same size: " + readBases.length + " vs " + deletionGOP.length);
+        if ( overallGCP.length != readBases.length ) throw new IllegalArgumentException("Read bases and overall GCP aren't the same size: " + readBases.length + " vs " + overallGCP.length);
+
+        paddedReadLength = readBases.length + 1;
+        paddedHaplotypeLength = haplotypeBases.length + 1;
+
+        hapStartIndex =  (recacheReadValues) ? 0 : hapStartIndex;
+
+        // Pre-compute the difference between the current haplotype and the next one to be run
+        // Looking ahead is necessary for the ArrayLoglessPairHMM implementation
+        final int nextHapStartIndex =  (nextHaploytpeBases == null || haplotypeBases.length != nextHaploytpeBases.length) ? 0 : findFirstPositionWhereHaplotypesDiffer(haplotypeBases, nextHaploytpeBases);
+
+        double result = subComputeReadLikelihoodGivenHaplotypeLog10(haplotypeBases, readBases, readQuals, insertionGOP, deletionGOP, overallGCP, hapStartIndex, recacheReadValues, nextHapStartIndex);
+
+        if ( result > 0.0)
+            throw new IllegalStateException("PairHMM Log Probability cannot be greater than 0: " + String.format("haplotype: %s, read: %s, result: %f, PairHMM: %s", new String(haplotypeBases), new String(readBases), result, this.getClass().getSimpleName()));
+        else if (!MathUtils.goodLog10Probability(result))
+            throw new IllegalStateException("Invalid Log Probability: " + result);
+
+        // Warning: Careful if using the PairHMM in parallel! (this update has to be taken care of).
+        // Warning: This assumes no downstream modification of the haplotype bases (saves us from copying the array). It is okay for the haplotype caller and the Unified Genotyper.
+        previousHaplotypeBases = haplotypeBases;
+
+        // For the next iteration, the hapStartIndex for the next haploytpe becomes the index for the current haplotype
+        // The array implementation has to look ahead to the next haplotype to store caching info. It cannot do this if nextHapStart is before hapStart
+        hapStartIndex = (nextHapStartIndex < hapStartIndex) ? 0: nextHapStartIndex;
+
+        return result;
+    }
+
+    /**
+     * To be overloaded by subclasses to actually do calculation for #computeReadLikelihoodGivenHaplotypeLog10
+     */
+    @Requires({"readBases.length == readQuals.length", "readBases.length == insertionGOP.length", "readBases.length == deletionGOP.length",
+            "readBases.length == overallGCP.length", "matchMatrix!=null", "insertionMatrix!=null", "deletionMatrix!=null"})
+    protected abstract double subComputeReadLikelihoodGivenHaplotypeLog10( final byte[] haplotypeBases,
+                                                                           final byte[] readBases,
+                                                                           final byte[] readQuals,
+                                                                           final byte[] insertionGOP,
+                                                                           final byte[] deletionGOP,
+                                                                           final byte[] overallGCP,
+                                                                           final int hapStartIndex,
+                                                                           final boolean recacheReadValues,
+                                                                           final int nextHapStartIndex);
+
+    /**
+     * Compute the first position at which two haplotypes differ
+     *
+     * If the haplotypes are exact copies of each other, returns the min length of the two haplotypes.
+     *
+     * @param haplotype1 the first haplotype1
+     * @param haplotype2 the second haplotype1
+     * @return the index of the first position in haplotype1 and haplotype2 where the byte isn't the same
+     */
+    public static int findFirstPositionWhereHaplotypesDiffer(final byte[] haplotype1, final byte[] haplotype2) {
+        if ( haplotype1 == null || haplotype1.length == 0 ) throw new IllegalArgumentException("Haplotype1 is bad " + Arrays.toString(haplotype1));
+        if ( haplotype2 == null || haplotype2.length == 0 ) throw new IllegalArgumentException("Haplotype2 is bad " + Arrays.toString(haplotype2));
+
+        for( int iii = 0; iii < haplotype1.length && iii < haplotype2.length; iii++ ) {
+            if( haplotype1[iii] != haplotype2[iii] ) {
+                return iii;
+            }
+        }
+
+        return Math.min(haplotype1.length, haplotype2.length);
+    }
+
+    /**
+     * Use number of threads to set doProfiling flag - doProfiling iff numThreads == 1
+     * This function should be called only during initialization phase - single thread phase of HC
+     */
+    public static void setNumberOfThreads(final int numThreads)
+    {
+        doProfiling = (numThreads == 1);
+        if(numThreads > 1)
+            logger.info("Performance profiling for PairHMM is disabled because HaplotypeCaller is being run with multiple threads (-nct>1) option\nProfiling is enabled only when running in single thread mode\n");
+    }
+
+    /**
+     * Return the results of the computeLikelihoods function
+     */
+    public double[] getLikelihoodArray() { return mLikelihoodArray; }
+    /**
+     * Called at the end of the program to close files, print profiling information etc 
+     */
+    public void close()
+    {
+        if(doProfiling)
+            System.out.println("Total compute time in PairHMM computeLikelihoods() : "+(pairHMMComputeTime*1e-9));
+    }
+}
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/pairhmm/PairHMMModel.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/pairhmm/PairHMMModel.java
new file mode 100644
index 0000000..1cd8865
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/pairhmm/PairHMMModel.java
@@ -0,0 +1,435 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.utils.pairhmm;
+
+import org.broadinstitute.gatk.utils.MathUtils;
+import org.broadinstitute.gatk.utils.QualityUtils;
+
+/**
+ * Helper class that implement calculations required to implement the PairHMM Finite State Automation (FSA) model.
+ *
+ * @author Valentin Ruano-Rubio <valentin at broadinstitute.org>
+ */
+public class PairHMMModel {
+
+
+    /**
+     * Prevents instantiation of this class
+     */
+    private PairHMMModel() {
+
+    }
+
+    /**
+     * Length of the standard transition probability array.
+     */
+    public static final int TRANS_PROB_ARRAY_LENGTH = 6;
+
+    /**
+     * Position in the transition probability array for the Match-to-Match transition.
+     */
+    public static final int matchToMatch = 0;
+
+    /**
+     * Position in the transition probability array for the Indel-to-Match transition.
+     */
+    public static final int indelToMatch = 1;
+
+    /**
+     * Position in the transition probability array for the Match-to-Insertion transition.
+     */
+    public static final int matchToInsertion = 2;
+
+    /**
+     * Position in the transition probability array for the Insertion-to-Insertion transition.
+     */
+    public static final int insertionToInsertion = 3;
+
+    /**
+     * Position in the transition probability array for the Match-to-Deletion transition.
+     */
+    public static final int matchToDeletion = 4;
+
+    /**
+     * Position in the transition probability array for the Deletion-to-Deletion transition.
+     */
+    public static final int deletionToDeletion = 5;
+
+    /**
+     * Convenient ln10 constant.
+     */
+    private static double LN10 = Math.log(10);
+
+    /**
+     * Convenient (ln10)^-1 constant.
+     */
+    private static double INV_LN10 = 1.0 / LN10;
+
+    /**
+     * Holds pre-calculated the matchToMath probability values in linear scale.
+     *
+     * <p/>
+     * This is a triangular matrix stored in a unidimentional array like so:
+     * <p/>
+     * (0,0), (0,1), (1,1), (0,2), (1,2), (2,2), (0,3) ... ({@link QualityUtils#MAX_QUAL},{@link QualityUtils#MAX_QUAL})
+     */
+    private static double[] matchToMatchProb = new double[((QualityUtils.MAX_QUAL + 1) * (QualityUtils.MAX_QUAL + 2)) >> 1];
+
+    /**
+     * Holds pre-calculated the matchToMath probability values in log10 scale.
+     *
+     * <p/>
+     * This is a triangular matrix stored in a unidimentional array like so:
+     * <p/>
+     * (0,0), (0,1), (1,1), (0,2), (1,2), (2,2), (0,3) ... ({@link QualityUtils#MAX_QUAL},{@link QualityUtils#MAX_QUAL})
+     */
+    private static double[] matchToMatchLog10 = new double[((QualityUtils.MAX_QUAL + 1) * (QualityUtils.MAX_QUAL + 2)) >> 1];
+
+    /**
+     * Initialize matchToMatch cache tables {@link #matchToMatch} and {@link #matchToMatchLog10}
+     */
+    static {
+        for (int i = 0, offset = 0; i <= QualityUtils.MAX_QUAL; offset += ++i)
+            for (int j = 0; j <= i; j++) {
+                final double log10Sum = MathUtils.approximateLog10SumLog10(-0.1 * i,-0.1 * j);
+                matchToMatchLog10[offset + j] =
+                        Math.log1p( - Math.min(1,Math.pow(10,log10Sum))) * INV_LN10;
+                matchToMatchProb[offset + j] = Math.pow(10,matchToMatchLog10[offset + j]);
+            }
+    }
+
+    /**
+     * Fills a transition probability array given the different quality scores affecting a read site
+     *
+     * @param insQual the insertion quality score as a byte.
+     * @param delQual the deletion quality score as a byte.
+     * @param gcp the gap-continuation-penalty score as a byte.
+     *
+     * @throws NullPointerException if {@code dest} is {@code null}.
+     * @throws ArrayIndexOutOfBoundsException if {@code dest} is not large enough.
+     * @throws IllegalArgumentException if {@code insQual}, {@code delQual} or {@code gcp} is less than negative.
+     */
+    public static void qualToTransProbs(final double[] dest, final byte insQual, final byte delQual, final byte gcp) {
+        if (insQual < 0) throw new IllegalArgumentException("insert quality cannot less than 0: " + insQual);
+        if (delQual < 0) throw new IllegalArgumentException("deletion quality cannot be less than 0: " + delQual);
+        if (gcp < 0) throw new IllegalArgumentException("gcp cannot be less than 0: " + gcp);
+        dest[matchToMatch] = matchToMatchProb(insQual, delQual);
+        dest[matchToInsertion] = QualityUtils.qualToErrorProb(insQual);
+        dest[matchToDeletion] = QualityUtils.qualToErrorProb(delQual);
+        dest[indelToMatch] = QualityUtils.qualToProb(gcp);
+        dest[insertionToInsertion] = dest[deletionToDeletion] = QualityUtils.qualToErrorProb(gcp);
+    }
+
+    /**
+     * Returns a transition probability array given the different quality scores affecting a read site.
+     *
+     * @param insQual the insertion quality score as a byte.
+     * @param delQual the deletion quality score as a byte.
+     * @param gcp the gap-continuation-penalty score as a byte.
+     *
+     * @throws NullPointerException if {@code dest} is {@code null}.
+     * @throws ArrayIndexOutOfBoundsException if {@code dest} is not large enough.
+     * @throws IllegalArgumentException if {@code insQual}, {@code delQual} or {@code gcp} is less than negative.
+     *
+     * @return never {@code null}. An array of length {@link #TRANS_PROB_ARRAY_LENGTH}.
+     */
+    @SuppressWarnings("unused")
+    public static double[] qualToTransProbs(final byte insQual, final byte delQual, final byte gcp) {
+        final double[] dest = new double[TRANS_PROB_ARRAY_LENGTH];
+        qualToTransProbs(dest,insQual,delQual,gcp);
+        return dest;
+    }
+
+    /**
+     * Fills ax matrix with the transition probabilities for a number of bases.
+     *
+     * <p/>
+     * The first dimension of the matrix correspond to the different bases where the first one is stored in position 1.
+     * Thus the position 0 is left empty and the length of the resulting matrix is actually {@code insQual.length + 1}.
+     * <p/>
+     * Each entry is the transition probability array for that base with a length of {@link #TRANS_PROB_ARRAY_LENGTH}.
+     *
+     * @param dest the matrix to update
+     * @param insQuals insertion qualities.
+     * @param delQuals deletion qualities.
+     * @param gcps gap-continuation penalty qualities.
+     *
+     * @throws NullPointerException if any of the input arrays, matrices is {@code null} or any entry in {@code dest} is {@code null}.
+     * @throws IllegalArgumentException if {@code IllegalArgumentException}
+     *  if the input array don't have the same length.
+     * @throws ArrayIndexOutOfBoundsException if {@code dest} or any of its elements is not large enough to contain the
+     *  transition  matrix.
+     */
+    @SuppressWarnings("unused")
+    public static void qualToTransProbs(final double[][] dest, final byte[] insQuals, final byte[] delQuals, final byte[] gcps) {
+        final int readLength = insQuals.length;
+        if (delQuals.length != readLength) throw new IllegalArgumentException("deletion quality array length does not match insert quality array length: " + readLength + " != " + delQuals.length);
+        if (gcps.length != readLength) throw new IllegalArgumentException("deletion quality array length does not match insert quality array length: " + readLength + " != " + gcps.length);
+
+        if (dest.length < readLength + 1) throw new IllegalArgumentException("destination length is not enough for the read length: " + dest.length + " < " + readLength + " + 1");
+
+        for (int i = 0; i < readLength; i++)
+            qualToTransProbs(dest[i + 1], insQuals[i], delQuals[i], gcps[i]);
+    }
+
+    /**
+     * Returns a matrix with the transition probabilities for a number of bases.
+     *
+     * <p/>
+     * The first dimension of the matrix correspond to the different bases where the first one is stored in position 1.
+     * Thus the position 0 is left empty and the length of the resulting matrix is actually {@code insQual.length + 1}.
+     * <p/>
+     * Each entry is the transition probability array for that base with a length of {@link #TRANS_PROB_ARRAY_LENGTH}.
+     *
+     * @param insQuals insertion qualities.
+     * @param delQuals deletion qualities.
+     * @param gcps gap-continuation penalty qualities.
+     *
+     * @throws NullPointerException if any of the input arrays is {@code null}.
+     * @throws IllegalArgumentException if {@code IllegalArgumentException}
+     *  if the input array don't have the same length.
+     *
+     * @return never {@code null}, an matrix of the dimensions explained above.
+     */
+    @SuppressWarnings("unused")
+    public static double[][] qualToTransProbs(final byte[] insQuals, final byte[] delQuals, final byte[] gcps) {
+        final double[][] dest = createTransitionMatrix(insQuals.length);
+        qualToTransProbs(dest,insQuals,delQuals,gcps);
+        return dest;
+    }
+
+    /**
+     * Fills a transition log10 probability array given the different quality scores affecting a read site.
+     *
+     * @param insQual the insertion quality score as a byte.
+     * @param delQual the deletion quality score as a byte.
+     * @param gcp the gap-continuation-penalty score as a byte.
+     *
+     * @throws NullPointerException if {@code dest} is {@code null}.
+     * @throws ArrayIndexOutOfBoundsException if {@code dest} is not large enough.
+     * @throws IllegalArgumentException if {@code insQual}, {@code delQual} or {@code gcp} is less than negative.
+     */
+    public static void qualToTransProbsLog10(final double[] dest, final byte insQual, final byte delQual, final byte gcp) {
+        if (insQual < 0) throw new IllegalArgumentException("insert quality cannot less than 0: " + insQual);
+        if (delQual < 0) throw new IllegalArgumentException("deletion quality cannot be less than 0: " + delQual);
+        if (gcp < 0) throw new IllegalArgumentException("gcp cannot be less than 0: " + gcp);
+        dest[matchToMatch] = matchToMatchProbLog10(insQual, delQual);
+        dest[matchToInsertion] = QualityUtils.qualToErrorProbLog10(insQual);
+        dest[matchToDeletion] = QualityUtils.qualToErrorProbLog10(delQual);
+        dest[indelToMatch] = QualityUtils.qualToProbLog10(gcp);
+        dest[insertionToInsertion] = dest[deletionToDeletion] = QualityUtils.qualToErrorProbLog10(gcp);
+    }
+
+    /**
+     * Returns a transition log10 probability array given the different quality scores affecting a read site.
+     *
+     * @param insQual the insertion quality score as a byte.
+     * @param delQual the deletion quality score as a byte.
+     * @param gcp the gap-continuation-penalty score as a byte.
+     *
+     * @throws NullPointerException if {@code dest} is {@code null}.
+     * @throws ArrayIndexOutOfBoundsException if {@code dest} is not large enough.
+     * @throws IllegalArgumentException if {@code insQual}, {@code delQual} or {@code gcp} is less than negative.
+     *
+     * @return never {@code null}. An array of length {@link #TRANS_PROB_ARRAY_LENGTH}.
+     */
+    @SuppressWarnings("unused")
+    public static double[] qualToTransProbsLog10(final byte insQual, final byte delQual, final byte gcp) {
+        final double[] dest = new double[TRANS_PROB_ARRAY_LENGTH];
+        qualToTransProbsLog10(dest,insQual,delQual,gcp);
+        return dest;
+    }
+
+    /**
+     * Fills a matrix with the log10 transition probabilities for a number of bases.
+     *
+     * <p/>
+     * The first dimension of the matrix correspond to the different bases where the first one is stored in position 1.
+     * Thus the position 0 is left empty and the length of the resulting matrix is actually {@code insQual.length + 1}.
+     * <p/>
+     * Each entry is the transition probability array for that base with a length of {@link #TRANS_PROB_ARRAY_LENGTH}.
+     *
+     * @param insQuals insertion qualities.
+     * @param delQuals deletion qualities.
+     * @param gcps gap-continuation penalty qualities.
+     *
+     * @throws NullPointerException if any of the input arrays, matrices is {@code null} or any entry in {@code dest} is {@code null}.
+     * @throws IllegalArgumentException if {@code IllegalArgumentException}
+     *  if the input array don't have the same length.
+     * @throws ArrayIndexOutOfBoundsException if {@code dest} or any of its elements is not large enough to contain the
+     *  transition  matrix.
+     */
+    @SuppressWarnings("unused")
+    public static void qualToTransProbsLog10(final double[][] dest, final byte[] insQuals, final byte[] delQuals, final byte[] gcps) {
+        final int readLength = insQuals.length;
+        if (delQuals.length != readLength) throw new IllegalArgumentException("deletion quality array length does not match insert quality array length: " + readLength + " != " + delQuals.length);
+        if (gcps.length != readLength) throw new IllegalArgumentException("deletion quality array length does not match insert quality array length: " + readLength + " != " + gcps.length);
+        if (dest.length < readLength + 1) throw new IllegalArgumentException("destination length is not enough for the read length: " + dest.length + " < " + readLength + " + 1");
+
+        for (int i = 0; i < readLength; i++)
+            qualToTransProbsLog10(dest[i+1],insQuals[i],delQuals[i],gcps[i]);
+    }
+
+    /**
+     * Returns a matrix with the log10 transition probabilities for a number of bases.
+     *
+     * <p/>
+     * The first dimension of the matrix correspond to the different bases where the first one is stored in position 1.
+     * Thus the position 0 is left empty and the length of the resulting matrix is actually {@code insQual.length + 1}.
+     * <p/>
+     * Each entry is the transition probability array for that base with a length of {@link #TRANS_PROB_ARRAY_LENGTH}.
+     *
+     * @param insQuals insertion qualities.
+     * @param delQuals deletion qualities.
+     * @param gcps gap-continuation penalty qualities.
+     *
+     * @throws NullPointerException if any of the input arrays is {@code null}.
+     * @throws IllegalArgumentException if {@code IllegalArgumentException}
+     *  if the input array don't have the same length.
+     *
+     * @return never {@code null}, an matrix of the dimensions explained above.
+     */
+    @SuppressWarnings("unused")
+    public static double[][] qualToTransProbsLog10(final byte[] insQuals, final byte[] delQuals, final byte[] gcps) {
+        final double[][] dest = createTransitionMatrix(insQuals.length);
+        qualToTransProbsLog10(dest,insQuals,delQuals,gcps);
+        return dest;
+    }
+
+    /**
+     * Creates a transition probability matrix large enough to work with sequences of a particular length.
+     *
+     * @param maxReadLength the maximum read length for the transition matrix.
+     *
+     * @return never {@code null}. A matrix of {@code maxReadLength + 1} by {@link #TRANS_PROB_ARRAY_LENGTH} positions.
+     */
+    public static double[][] createTransitionMatrix(final int maxReadLength) {
+        return new double[maxReadLength + 1][TRANS_PROB_ARRAY_LENGTH];
+    }
+
+    /**
+     * Returns the probability that neither of two event takes place.
+     * <p/>
+     *
+     * We assume that both event never occur together and that delQual is the conditional probability
+     * (qual. encoded) of the second event, given the first event didn't took place. So that the
+     * probability of no event is: <br/>
+     *
+     * We assume that both event never occur together so that the probability of no event is: <br/>
+     *
+     * <code>1 - ProbErr(insQual) - ProbErr(delQual)</code> <br/>
+     *
+     * @param insQual PhRED scaled quality/probability of the first event.
+     * @param delQual PhRED scaled quality/probability of the second event.
+     *
+     * @return a value between 0 and 1.
+     */
+    public static double matchToMatchProb(final byte insQual, final byte delQual) {
+        return matchToMatchProb((insQual & 0xFF), (delQual & 0xFF));
+    }
+
+    /**
+     * Returns the probability (log 10 scaled) that neither of two event, insertion and deletion, takes place.
+     * <p/>
+     *
+     * We assume that both event never occur together so that the probability of no event is: <br/>
+     *
+     * <code>1 - ProbErr(insQual) - ProbErr(delQual)</code> <br/>
+     *
+     * @param insQual PhRED scaled quality/probability of an insertion.
+     * @param delQual PhRED scaled quality/probability of a deletion.
+     *
+     * @return a value between 0 and -Inf.
+     */
+    public static double matchToMatchProbLog10(final byte insQual, final byte delQual) {
+        return matchToMatchProbLog10((insQual & 0xFF), (delQual & 0xFF));
+    }
+
+    /**
+     * Returns the probability that neither of two events, insertion and deletion, takes place.
+     * <p/>
+     *
+     * We assume that both event never occur together and that delQual is the conditional probability
+     * (qual. encoded) of the second event, given the first event didn't took place. So that the
+     * probability of no event is: <br/>
+     *
+     * We assume that both event never occur together so that the probability of no event is: <br/>
+     *
+     * <code>1 - ProbErr(insQual) - ProbErr(delQual)</code> <br/>
+     *
+     * @param insQual PhRED scaled quality/probability of an insertion.
+     * @param delQual PhRED scaled quality/probability of a deletion.
+     * @return a value between 0 and 1.
+     */
+    public static double matchToMatchProb(final int insQual, final int delQual) {
+        final int minQual;
+        final int maxQual;
+        if (insQual <= delQual) {
+            minQual = insQual;
+            maxQual = delQual;
+        } else {
+            minQual = delQual;
+            maxQual = insQual;
+        }
+
+        if (minQual < 0) throw new IllegalArgumentException("quality cannot be negative: " + minQual + " and " + maxQual);
+
+        return (QualityUtils.MAX_QUAL < maxQual) ?  1.0 - Math.pow(10, MathUtils.approximateLog10SumLog10(-0.1 * minQual, -0.1 * maxQual)) :
+                matchToMatchProb[((maxQual * (maxQual + 1)) >> 1) + minQual];
+    }
+
+    /**
+     * Returns the probability (log 10 scaled) that neither of two event takes place.
+     * <p/>
+     *
+     * We assume that both event never occur together and that delQual is the conditional probability (qual. encoded)
+     * of the second event, given the first event didn't took place. So that the probability of no event is: <br/>
+     *
+     * We assume that both event never occur together so that the probability of no event is: <br/>
+     *
+     * <code>1 - ProbErr(insQual) - ProbErr(delQual)</code> <br/>
+     *
+     * @param insQual PhRED scaled quality/probability of an insertion.
+     * @param delQual PhRED scaled quality/probability of a deletion.
+     *
+     * @return a value between 0 and -Inf.
+     */
+    public static double matchToMatchProbLog10(final int insQual, final int delQual) {
+        final int minQual;
+        final int maxQual;
+        if (insQual <= delQual) {
+            minQual = insQual;
+            maxQual = delQual;
+        } else {
+            minQual = delQual;
+            maxQual = insQual;
+        }
+        return (QualityUtils.MAX_QUAL < maxQual) ? Math.log1p (
+                - Math.min(1,Math.pow(10,
+                        MathUtils.approximateLog10SumLog10(-.1 * minQual, -.1 * maxQual)))) * INV_LN10 :
+                matchToMatchLog10[((maxQual * (maxQual + 1)) >> 1) + minQual];
+    }
+}
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/pairhmm/PairHMMReadyHaplotypes.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/pairhmm/PairHMMReadyHaplotypes.java
new file mode 100644
index 0000000..2948404
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/pairhmm/PairHMMReadyHaplotypes.java
@@ -0,0 +1,182 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.utils.pairhmm;
+
+import java.util.*;
+
+/**
+ * Collection of haplotypes sorted in a conveniently way to be run efficiently by the PairHMM.
+ *
+ * TODO not yet in use but likely to be as part of making graph-base likelihood run faster.
+ * TODO this could be extended to the classical PairHMM implementation simplifyling the PairHMM API.
+ */
+public class PairHMMReadyHaplotypes implements Iterable<PairHMMReadyHaplotypes.Entry> {
+
+
+    public class Entry {
+
+        private final byte[] bases;
+
+        private double likelihood = Double.NaN;
+
+        protected Entry(final byte[] bases) {
+            this.bases = bases;
+        }
+
+        protected byte[] getBases() {
+            return bases;
+        }
+
+        public void setLikelihood(final double lk) {
+            likelihood = lk;
+        }
+
+        public double getLikelihood() {
+            return likelihood;
+        }
+
+    }
+
+    private Map<Entry,Map<Entry,Integer>> commonPrefixLength;
+
+    private SortedSet<Entry> entries;
+
+    private int capacity;
+
+    private final Comparator<Entry> comparator = new Comparator<Entry>() {
+        @Override
+        public int compare(final Entry o1, final Entry o2) {
+            final byte[] b1 = o1.bases;
+            final byte[] b2 = o2.bases;
+            Map<Entry,Integer> b1map = commonPrefixLength.get(o1);
+            if (b1map == null)
+                commonPrefixLength.put(o1, b1map = new HashMap<>(capacity));
+            Map<Entry,Integer> b2map = commonPrefixLength.get(o2);
+            if (b2map == null)
+                commonPrefixLength.put(o2, b2map = new HashMap<>(capacity));
+            final Integer previousI = b1map.get(o2) == null ? null : b1map.get(o2);
+            int i;
+            int result;
+            final int iLimit = Math.min(b1.length,b2.length);
+            if (previousI == null) {
+                for (i = 0; i < iLimit; i++)
+                    if (b1[i] != b2[i])
+                        break;
+                b1map.put(o2,i);
+                b2map.put(o1,i);
+            } else
+                i = previousI;
+
+            if (i < iLimit)
+                result = Byte.compare(b1[i],b2[i]);
+            else if (b1.length == b2.length)
+                result = 0;
+            else
+                result = b1.length < b2.length ? -1 : 1;
+            return result;
+        }
+    };
+
+    public PairHMMReadyHaplotypes(final int capacity) {
+        commonPrefixLength = new HashMap<>(capacity);
+        entries = new TreeSet<>(comparator);
+    }
+
+    public void add(final byte[] bases) {
+        final Entry entry = new Entry(bases);
+        entries.add(entry);
+    }
+
+    public int size() {
+        return entries.size();
+    }
+
+    @Override
+    public Iterator iterator() {
+        return new Iterator();
+    }
+
+    public class Iterator implements java.util.Iterator<Entry> {
+
+        private java.util.Iterator<Entry> actualIterator;
+        private Entry previousEntry;
+        private Entry currentEntry;
+        private int startIndex;
+        private int cmp;
+
+        private Iterator() {
+            actualIterator = entries.iterator();
+        }
+
+        public boolean hasNext() {
+            return actualIterator.hasNext();
+        }
+
+        public Entry next() {
+            previousEntry = currentEntry;
+            final Entry result = currentEntry = actualIterator.next();
+            startIndex = -1;
+            return result;
+        }
+
+        @Override
+        public void remove() {
+            throw new UnsupportedOperationException();
+        }
+
+        public byte[] bases() {
+            if (currentEntry == null)
+                throw new NoSuchElementException();
+            return currentEntry.bases;
+        }
+
+        public int startIndex() {
+            if (startIndex >= 0)
+                return startIndex;
+            else if (previousEntry == null)
+                return startIndex = 0;
+            else {
+                // The comparator will make sure the common-prefix-length is updated.
+                // The result in a field so that we avoid dead code elimination.
+                // perhaps I a bit paranohic but it does not harm to prevent.
+                cmp = comparator.compare(previousEntry,currentEntry);
+                return startIndex = commonPrefixLength.get(previousEntry).get(currentEntry);
+            }
+        }
+
+        @Override
+        public String toString() {
+            return super.toString() + " cmp = " + cmp;
+        }
+
+        public void setLikelihood(final double likelihood) {
+            if (currentEntry == null)
+                throw new NoSuchElementException();
+            currentEntry.setLikelihood(likelihood);
+        }
+    }
+
+}
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/pileup/MergingPileupElementIterator.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/pileup/MergingPileupElementIterator.java
new file mode 100644
index 0000000..d36d355
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/pileup/MergingPileupElementIterator.java
@@ -0,0 +1,76 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.utils.pileup;
+
+import htsjdk.samtools.util.PeekableIterator;
+
+import java.util.Comparator;
+import java.util.Iterator;
+import java.util.PriorityQueue;
+
+/**
+ * Merges multiple pileups broken down by sample.
+ *
+ * @author mhanna
+ * @version 0.1
+ */
+class MergingPileupElementIterator<PE extends PileupElement> implements Iterator<PE> {
+    private final PriorityQueue<PeekableIterator<PE>> perSampleIterators;
+
+    public MergingPileupElementIterator(PerSamplePileupElementTracker<PE> tracker) {
+        perSampleIterators = new PriorityQueue<PeekableIterator<PE>>(Math.max(1,tracker.getSamples().size()),new PileupElementIteratorComparator());
+        for(final String sample: tracker.getSamples()) {
+            PileupElementTracker<PE> trackerPerSample = tracker.getElements(sample);
+            if(trackerPerSample.size() != 0)
+                perSampleIterators.add(new PeekableIterator<PE>(trackerPerSample.iterator()));
+        }
+    }
+
+    public boolean hasNext() {
+        return !perSampleIterators.isEmpty();
+    }
+
+    public PE next() {
+        PeekableIterator<PE> currentIterator = perSampleIterators.remove();
+        PE current = currentIterator.next();
+        if(currentIterator.hasNext())
+            perSampleIterators.add(currentIterator);
+        return current;
+    }
+
+    public void remove() {
+        throw new UnsupportedOperationException("Cannot remove from a merging iterator.");
+    }
+
+    /**
+     * Compares two peekable iterators consisting of pileup elements.
+     */
+    private class PileupElementIteratorComparator implements Comparator<PeekableIterator<PE>> {
+        public int compare(PeekableIterator<PE> lhs, PeekableIterator<PE> rhs) {
+            return rhs.peek().getOffset() - lhs.peek().getOffset();
+        }
+    }
+}
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/pileup/PileupElement.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/pileup/PileupElement.java
new file mode 100644
index 0000000..4db0927
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/pileup/PileupElement.java
@@ -0,0 +1,539 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.utils.pileup;
+
+import com.google.java.contract.Ensures;
+import com.google.java.contract.Requires;
+import htsjdk.samtools.CigarElement;
+import htsjdk.samtools.CigarOperator;
+import org.broadinstitute.gatk.utils.BaseUtils;
+import org.broadinstitute.gatk.utils.sam.GATKSAMRecord;
+
+import java.util.Arrays;
+import java.util.EnumSet;
+import java.util.LinkedList;
+import java.util.List;
+
+/**
+ * Created by IntelliJ IDEA.
+ * User: depristo
+ * Date: Apr 14, 2009
+ * Time: 8:54:05 AM
+ */
+public class PileupElement implements Comparable<PileupElement> {
+    private final static LinkedList<CigarElement> EMPTY_LINKED_LIST = new LinkedList<>();
+
+    private final static EnumSet<CigarOperator> ON_GENOME_OPERATORS =
+            EnumSet.of(CigarOperator.M, CigarOperator.EQ, CigarOperator.X, CigarOperator.D);
+
+    public static final byte DELETION_BASE = BaseUtils.Base.D.base;
+    public static final byte DELETION_QUAL = (byte) 16;
+    public static final byte A_FOLLOWED_BY_INSERTION_BASE = (byte) 87;
+    public static final byte C_FOLLOWED_BY_INSERTION_BASE = (byte) 88;
+    public static final byte T_FOLLOWED_BY_INSERTION_BASE = (byte) 89;
+    public static final byte G_FOLLOWED_BY_INSERTION_BASE = (byte) 90;
+
+    protected final GATKSAMRecord read;         // the read this base belongs to
+    protected final int offset;                 // the offset in the bases array for this base
+
+    private final CigarElement currentCigarElement;
+    private final int currentCigarOffset;
+    private final int offsetInCurrentCigar;
+
+    /**
+     * Create a new pileup element
+     *
+     * @param read a non-null read to pileup
+     * @param baseOffset the offset into the read's base / qual vector aligned to this position on the genome. If the
+     *                   current cigar element is a deletion, offset should be the offset of the last M/=/X position.
+     * @param currentElement a non-null CigarElement that indicates the cigar element aligning the read to the genome
+     * @param currentCigarOffset the offset of currentElement in read.getCigar().getElement(currentCigarOffset) == currentElement)
+     * @param offsetInCurrentCigar how far into the currentElement are we in our alignment to the genome?
+     */
+    public PileupElement(final GATKSAMRecord read, final int baseOffset,
+                         final CigarElement currentElement, final int currentCigarOffset,
+                         final int offsetInCurrentCigar) {
+        assert currentElement != null;
+
+        this.read = read;
+        this.offset = baseOffset;
+        this.currentCigarElement = currentElement;
+        this.currentCigarOffset = currentCigarOffset;
+        this.offsetInCurrentCigar = offsetInCurrentCigar;
+
+        // for performance regions these are assertions
+        assert this.read != null;
+        assert this.offset >= 0 && this.offset < this.read.getReadLength();
+        assert this.currentCigarOffset >= 0;
+        assert this.currentCigarOffset < read.getCigarLength();
+        assert this.offsetInCurrentCigar >= 0;
+        assert this.offsetInCurrentCigar < currentElement.getLength();
+    }
+
+    /**
+     * Create a new PileupElement that's a copy of toCopy
+     * @param toCopy the element we want to copy
+     */
+    public PileupElement(final PileupElement toCopy) {
+        this(toCopy.read, toCopy.offset, toCopy.currentCigarElement, toCopy.currentCigarOffset, toCopy.offsetInCurrentCigar);
+    }
+
+    /**
+     * Is this element a deletion w.r.t. the reference genome?
+     *
+     * @return true if this is a deletion, false otherwise
+     */
+    public boolean isDeletion() {
+        return currentCigarElement.getOperator() == CigarOperator.D;
+    }
+
+    /**
+     * Is the current element immediately before a deletion, but itself not a deletion?
+     *
+     * Suppose we are aligning a read with cigar 3M2D1M.  This function is true
+     * if we are in the last cigar position of the 3M, but not if we are in the 2D itself.
+     *
+     * @return true if the next alignment position is a deletion w.r.t. the reference genome
+     */
+    public boolean isBeforeDeletionStart() {
+        return ! isDeletion() && atEndOfCurrentCigar() && hasOperator(getNextOnGenomeCigarElement(), CigarOperator.D);
+    }
+
+    /**
+     * Is the current element immediately after a deletion, but itself not a deletion?
+     *
+     * Suppose we are aligning a read with cigar 1M2D3M.  This function is true
+     * if we are in the first cigar position of the 3M, but not if we are in the 2D itself or
+     * in any but the first position of the 3M.
+     *
+     * @return true if the previous alignment position is a deletion w.r.t. the reference genome
+     */
+    public boolean isAfterDeletionEnd() {
+        return ! isDeletion() && atStartOfCurrentCigar() && hasOperator(getPreviousOnGenomeCigarElement(), CigarOperator.D);
+    }
+
+    /**
+     * Get the read for this pileup element
+     * @return a non-null GATKSAMRecord
+     */
+    @Ensures("result != null")
+    public GATKSAMRecord getRead() {
+        return read;
+    }
+
+    /**
+     * Get the offset of the this element into the read that aligns that read's base to this genomic position.
+     *
+     * If the current element is a deletion then offset is the offset of the last base containing offset.
+     *
+     * @return a valid offset into the read's bases
+     */
+    @Ensures({"result >= 0", "result <= read.getReadLength()"})
+    public int getOffset() {
+        return offset;
+    }
+
+    /**
+     * Get the base aligned to the genome at this location
+     *
+     * If the current element is a deletion returns DELETION_BASE
+     *
+     * @return a base encoded as a byte
+     */
+    @Ensures("result != DELETION_BASE || (isDeletion() && result == DELETION_BASE)")
+    public byte getBase() {
+        return isDeletion() ? DELETION_BASE : read.getReadBases()[offset];
+    }
+
+    @Deprecated
+    public int getBaseIndex() {
+        return BaseUtils.simpleBaseToBaseIndex(getBase());
+    }
+
+    /**
+     * Get the base quality score of the base at this aligned position on the genome
+     * @return a phred-scaled quality score as a byte
+     */
+    public byte getQual() {
+        return isDeletion() ? DELETION_QUAL : read.getBaseQualities()[offset];
+    }
+
+    /**
+     * Get the Base Insertion quality at this pileup position
+     * @return a phred-scaled quality score as a byte
+     */
+    public byte getBaseInsertionQual() {
+        return isDeletion() ? DELETION_QUAL : read.getBaseInsertionQualities()[offset];
+    }
+
+    /**
+     * Get the Base Deletion quality at this pileup position
+     * @return a phred-scaled quality score as a byte
+     */
+    public byte getBaseDeletionQual() {
+        return isDeletion() ? DELETION_QUAL : read.getBaseDeletionQualities()[offset];
+    }
+
+    /**
+     * Get the length of an immediately following insertion or deletion event, or 0 if no such event exists
+     *
+     * Only returns a positive value when this pileup element is immediately before an indel.  Being
+     * immediately before a deletion means that this pileup element isn't an deletion, and that the
+     * next genomic alignment for this read is a deletion.  For the insertion case, this means
+     * that an insertion cigar occurs immediately after this element, between this one and the
+     * next genomic position.
+     *
+     * Note this function may be expensive, so multiple uses should be cached by the caller
+     *
+     * @return length of the event (number of inserted or deleted bases), or 0
+     */
+    @Ensures("result >= 0")
+    public int getLengthOfImmediatelyFollowingIndel() {
+        final CigarElement element = getNextIndelCigarElement();
+        return element == null ? 0 : element.getLength();
+    }
+
+    /**
+     * Helpful function to get the immediately following cigar element, for an insertion or deletion
+     *
+     * if this state precedes a deletion (i.e., next position on genome) or insertion (immediately between
+     * this and the next position) returns the CigarElement corresponding to this event.  Otherwise returns
+     * null.
+     *
+     * @return a CigarElement, or null if the next alignment state ins't an insertion or deletion.
+     */
+    private CigarElement getNextIndelCigarElement() {
+        if ( isBeforeDeletionStart() ) {
+            final CigarElement element = getNextOnGenomeCigarElement();
+            if ( element == null || element.getOperator() != CigarOperator.D )
+                throw new IllegalStateException("Immediately before deletion but the next cigar element isn't a deletion " + element);
+            return element;
+        } else if ( isBeforeInsertion() ) {
+            final CigarElement element = getBetweenNextPosition().get(0);
+            if ( element.getOperator() != CigarOperator.I )
+                throw new IllegalStateException("Immediately before insertion but the next cigar element isn't an insertion " + element);
+            return element;
+        } else {
+            return null;
+        }
+    }
+
+    /**
+     * Get the bases for an insertion that immediately follows this alignment state, or null if none exists
+     *
+     * @see #getLengthOfImmediatelyFollowingIndel() for details on the meaning of immediately.
+     *
+     * If the immediately following state isn't an insertion, returns null
+     *
+     * @return actual sequence of inserted bases, or a null if the event is a deletion or if there is no event in the associated read.
+     */
+    @Ensures("result == null || result.length() == getLengthOfImmediatelyFollowingIndel()")
+    public String getBasesOfImmediatelyFollowingInsertion() {
+        final CigarElement element = getNextIndelCigarElement();
+        if ( element != null && element.getOperator() == CigarOperator.I ) {
+            final int getFrom = offset + 1;
+            final byte[] bases = Arrays.copyOfRange(read.getReadBases(), getFrom, getFrom + element.getLength());
+            return new String(bases);
+        } else
+            return null;
+    }
+
+    /**
+     * Get the mapping quality of the read of this element
+     * @return the mapping quality of the underlying SAM record
+     */
+    public int getMappingQual() {
+        return read.getMappingQuality();
+    }
+
+    @Ensures("result != null")
+    public String toString() {
+        return String.format("%s @ %d = %c Q%d", getRead().getReadName(), getOffset(), (char) getBase(), getQual());
+    }
+
+    @Override
+    public int compareTo(final PileupElement pileupElement) {
+        if (offset < pileupElement.offset)
+            return -1;
+        else if (offset > pileupElement.offset)
+            return 1;
+        else if (read.getAlignmentStart() < pileupElement.read.getAlignmentStart())
+            return -1;
+        else if (read.getAlignmentStart() > pileupElement.read.getAlignmentStart())
+            return 1;
+        else
+            return 0;
+    }
+
+    // --------------------------------------------------------------------------
+    //
+    // Reduced read accessors
+    //
+    // --------------------------------------------------------------------------
+
+    /**
+     * Get the cigar element aligning this element to the genome
+     * @return a non-null CigarElement
+     */
+    @Ensures("result != null")
+    public CigarElement getCurrentCigarElement() {
+        return currentCigarElement;
+    }
+
+    /**
+     * Get the offset of this cigar element in the Cigar of the current read (0-based)
+     *
+     * Suppose the cigar is 1M2D3I4D.  If we are in the 1M state this function returns
+     * 0.  If we are in 2D, the result is 1.  If we are in the 4D, the result is 3.
+     *
+     * @return an offset into the read.getCigar() that brings us to the current cigar element
+     */
+    public int getCurrentCigarOffset() {
+        return currentCigarOffset;
+    }
+
+    /**
+     * Get the offset into the *current* cigar element for this alignment position
+     *
+     * We can be anywhere from offset 0 (first position) to length - 1 of the current
+     * cigar element aligning us to this genomic position.
+     *
+     * @return a valid offset into the current cigar element
+     */
+    @Ensures({"result >= 0", "result < getCurrentCigarElement().getLength()"})
+    public int getOffsetInCurrentCigar() {
+        return offsetInCurrentCigar;
+    }
+
+    /**
+     * Get the cigar elements that occur before the current position but after the previous position on the genome
+     *
+     * For example, if we are in the 3M state of 1M2I3M state then 2I occurs before this position.
+     *
+     * Note that this function does not care where we are in the current cigar element.  In the previous
+     * example this list of elements contains the 2I state regardless of where you are in the 3M.
+     *
+     * Note this returns the list of all elements that occur between this and the prev site, so for
+     * example we might have 5S10I2M and this function would return [5S, 10I].
+     *
+     * @return a non-null list of CigarElements
+     */
+    @Ensures("result != null")
+    public LinkedList<CigarElement> getBetweenPrevPosition() {
+        return atStartOfCurrentCigar() ? getBetween(Direction.PREV) : EMPTY_LINKED_LIST;
+    }
+
+    /**
+     * Get the cigar elements that occur after the current position but before the next position on the genome
+     *
+     * @see #getBetweenPrevPosition() for more details
+     *
+     * @return a non-null list of CigarElements
+     */
+    @Ensures("result != null")
+    public LinkedList<CigarElement> getBetweenNextPosition() {
+        return atEndOfCurrentCigar() ? getBetween(Direction.NEXT) : EMPTY_LINKED_LIST;
+    }
+
+    /** for some helper functions */
+    private enum Direction { PREV, NEXT }
+
+    /**
+     * Helper function to get cigar elements between this and either the prev or next genomic position
+     *
+     * @param direction PREVIOUS if we want before, NEXT if we want after
+     * @return a non-null list of cigar elements between this and the neighboring position in direction
+     */
+    @Ensures("result != null")
+    private LinkedList<CigarElement> getBetween(final Direction direction) {
+        final int increment = direction == Direction.NEXT ? 1 : -1;
+        LinkedList<CigarElement> elements = null;
+        final int nCigarElements = read.getCigarLength();
+        for ( int i = currentCigarOffset + increment; i >= 0 && i < nCigarElements; i += increment) {
+            final CigarElement elt = read.getCigar().getCigarElement(i);
+            if ( ON_GENOME_OPERATORS.contains(elt.getOperator()) )
+                break;
+            else {
+                // optimization: don't allocate list if not necessary
+                if ( elements == null )
+                    elements = new LinkedList<CigarElement>();
+
+                if ( increment > 0 )
+                    // to keep the list in the right order, if we are incrementing positively add to the end
+                    elements.add(elt);
+                else
+                    // counting down => add to front
+                    elements.addFirst(elt);
+            }
+        }
+
+        // optimization: elements is null because nothing got added, just return the empty list
+        return elements == null ? EMPTY_LINKED_LIST : elements;
+    }
+
+    /**
+     * Get the cigar element of the previous genomic aligned position
+     *
+     * For example, we might have 1M2I3M, and be sitting at the someone in the 3M.  This
+     * function would return 1M, as the 2I isn't on the genome.  Note this function skips
+     * all of the positions that would occur in the current element.  So the result
+     * is always 1M regardless of whether we're in the first, second, or third position of the 3M
+     * cigar.
+     *
+     * @return a CigarElement, or null (indicating that no previous element exists)
+     */
+    @Ensures("result == null || ON_GENOME_OPERATORS.contains(result.getOperator())")
+    public CigarElement getPreviousOnGenomeCigarElement() {
+        return getNeighboringOnGenomeCigarElement(Direction.PREV);
+    }
+
+    /**
+     * Get the cigar element of the next genomic aligned position
+     *
+     * @see #getPreviousOnGenomeCigarElement() for more details
+     *
+     * @return a CigarElement, or null (indicating that no next element exists)
+     */
+    @Ensures("result == null || ON_GENOME_OPERATORS.contains(result.getOperator())")
+    public CigarElement getNextOnGenomeCigarElement() {
+        return getNeighboringOnGenomeCigarElement(Direction.NEXT);
+    }
+
+    /**
+     * Helper function to get the cigar element of the next or previous genomic position
+     * @param direction the direction to look in
+     * @return a CigarElement, or null if no such element exists
+     */
+    @Ensures("result == null || ON_GENOME_OPERATORS.contains(result.getOperator())")
+    private CigarElement getNeighboringOnGenomeCigarElement(final Direction direction) {
+        final int increment = direction == Direction.NEXT ? 1 : -1;
+        final int nCigarElements = read.getCigarLength();
+
+        for ( int i = currentCigarOffset + increment; i >= 0 && i < nCigarElements; i += increment) {
+            final CigarElement elt = read.getCigar().getCigarElement(i);
+            if ( ON_GENOME_OPERATORS.contains(elt.getOperator()) )
+                return elt;
+        }
+
+        // getting here means that you didn't find anything
+        return null;
+    }
+
+    /**
+     * Does the cigar element (which may be null) have operation toMatch?
+     *
+     * @param maybeCigarElement a CigarElement that might be null
+     * @param toMatch a CigarOperator we want to match against the one in maybeCigarElement
+     * @return true if maybeCigarElement isn't null and has operator toMatch
+     */
+    @Requires("toMatch != null")
+    private boolean hasOperator(final CigarElement maybeCigarElement, final CigarOperator toMatch) {
+        return maybeCigarElement != null && maybeCigarElement.getOperator() == toMatch;
+    }
+
+    /**
+     * Does an insertion occur immediately before the current position on the genome?
+     *
+     * @return true if yes, false if no
+     */
+    public boolean isAfterInsertion() { return isAfter(getBetweenPrevPosition(), CigarOperator.I); }
+
+    /**
+     * Does an insertion occur immediately after the current position on the genome?
+     *
+     * @return true if yes, false if no
+     */
+    public boolean isBeforeInsertion() { return isBefore(getBetweenNextPosition(), CigarOperator.I); }
+
+    /**
+     * Does a soft-clipping event occur immediately before the current position on the genome?
+     *
+     * @return true if yes, false if no
+     */
+    public boolean isAfterSoftClip() { return isAfter(getBetweenPrevPosition(), CigarOperator.S); }
+
+    /**
+     * Does a soft-clipping event occur immediately after the current position on the genome?
+     *
+     * @return true if yes, false if no
+     */
+    public boolean isBeforeSoftClip() { return isBefore(getBetweenNextPosition(), CigarOperator.S); }
+
+    /**
+     * Does a soft-clipping event occur immediately before or after the current position on the genome?
+     *
+     * @return true if yes, false if no
+     */
+    public boolean isNextToSoftClip() { return isAfterSoftClip() || isBeforeSoftClip(); }
+
+    /**
+     * Is the current position at the end of the current cigar?
+     *
+     * For example, if we are in element 3M, this function returns true if we are at offsetInCurrentCigar
+     * of 2, but not 0 or 1.
+     *
+     * @return true if we're at the end of the current cigar
+     */
+    public boolean atEndOfCurrentCigar() {
+        return offsetInCurrentCigar == currentCigarElement.getLength() - 1;
+    }
+
+    /**
+     * Is the current position at the start of the current cigar?
+     *
+     * For example, if we are in element 3M, this function returns true if we are at offsetInCurrentCigar
+     * of 0, but not 1 or 2.
+     *
+     * @return true if we're at the start of the current cigar
+     */
+    public boolean atStartOfCurrentCigar() {
+        return offsetInCurrentCigar == 0;
+    }
+
+    /**
+     * Is op the last element in the list of elements?
+     *
+     * @param elements the elements to examine
+     * @param op the op we want the last element's op to equal
+     * @return true if op == last(elements).op
+     */
+    @Requires({"elements != null", "op != null"})
+    private boolean isAfter(final LinkedList<CigarElement> elements, final CigarOperator op) {
+        return ! elements.isEmpty() && elements.peekLast().getOperator() == op;
+    }
+
+    /**
+     * Is op the first element in the list of elements?
+     *
+     * @param elements the elements to examine
+     * @param op the op we want the last element's op to equal
+     * @return true if op == first(elements).op
+     */
+    @Requires({"elements != null", "op != null"})
+    private boolean isBefore(final List<CigarElement> elements, final CigarOperator op) {
+        return ! elements.isEmpty() && elements.get(0).getOperator() == op;
+    }
+}
\ No newline at end of file
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/pileup/PileupElementFilter.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/pileup/PileupElementFilter.java
new file mode 100644
index 0000000..7f82709
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/pileup/PileupElementFilter.java
@@ -0,0 +1,36 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.utils.pileup;
+
+/**
+ * A filtering interface for pileup elements.
+ *
+ * @author mhanna
+ * @version 0.1
+ */
+public interface PileupElementFilter {
+    public boolean allow(final PileupElement pileupElement);
+}
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/pileup/PileupElementTracker.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/pileup/PileupElementTracker.java
new file mode 100644
index 0000000..7d49fcc
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/pileup/PileupElementTracker.java
@@ -0,0 +1,154 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.utils.pileup;
+
+import org.apache.commons.collections.iterators.IteratorChain;
+
+import java.util.*;
+
+/**
+ * Javadoc goes here.
+ *
+ * @author mhanna
+ * @version 0.1
+ */
+abstract class PileupElementTracker<PE extends PileupElement> implements Iterable<PE> {
+    public abstract int size();
+
+    /**
+     * Iterate through the PEs here, but in any order, which may improve performance
+     * if you don't care about the underlying order the reads are coming to you in.
+     * @return an iteratable over all pileup elements in this tracker
+     */
+    public abstract Iterable<PE> unorderedIterable();
+
+    /**
+     * Same as @see #unorderedIterable but the actual iterator itself
+     * @return
+     */
+    public Iterator<PE> unorderedIterator() { return unorderedIterable().iterator(); }
+
+    public abstract PileupElementTracker<PE> copy();
+}
+
+class UnifiedPileupElementTracker<PE extends PileupElement> extends PileupElementTracker<PE> {
+    private final List<PE> pileup;
+
+    @Override
+    public UnifiedPileupElementTracker<PE> copy() {
+        UnifiedPileupElementTracker<PE> result = new UnifiedPileupElementTracker<PE>();
+        for(PE element : pileup)
+            result.add(element);
+        return result;
+    }
+
+    public UnifiedPileupElementTracker() { pileup = new LinkedList<PE>(); }
+    public UnifiedPileupElementTracker(List<PE> pileup) { this.pileup = pileup; }
+
+    public void add(PE element) {
+        pileup.add(element);
+    }
+
+    public PE get(int index) {
+        return pileup.get(index);
+    }
+
+    public int size() {
+        return pileup.size();
+    }
+
+    public Iterator<PE> iterator() { return pileup.iterator(); }
+    public Iterable<PE> unorderedIterable() { return this; }
+}
+
+class PerSamplePileupElementTracker<PE extends PileupElement> extends PileupElementTracker<PE> {
+    private final Map<String,PileupElementTracker<PE>> pileup;
+    private int size = 0;
+
+    public PerSamplePileupElementTracker() {
+        pileup = new HashMap<String,PileupElementTracker<PE>>();
+    }
+
+    public PerSamplePileupElementTracker<PE> copy() {
+        PerSamplePileupElementTracker<PE> result = new PerSamplePileupElementTracker<PE>();
+        for (Map.Entry<String, PileupElementTracker<PE>> entry : pileup.entrySet())
+            result.addElements(entry.getKey(), entry.getValue());
+
+        return result;
+    }
+
+    /**
+     * Gets a list of all the samples stored in this pileup.
+     * @return List of samples in this pileup.
+     */
+    public Collection<String> getSamples() {
+        return pileup.keySet();
+    }
+
+    public PileupElementTracker<PE> getElements(final String sample) {
+        return pileup.get(sample);
+    }
+
+    public PileupElementTracker<PE> getElements(final Collection<String> selectSampleNames) {
+        PerSamplePileupElementTracker<PE> result = new PerSamplePileupElementTracker<PE>();
+        for (final String sample :  selectSampleNames) {
+            result.addElements(sample, pileup.get(sample));
+        }
+        return result;
+    }
+
+    public void addElements(final String sample, PileupElementTracker<PE> elements) {
+        pileup.put(sample,elements);
+        size += elements.size();
+    }
+
+    public Iterator<PE> iterator() { return new MergingPileupElementIterator<PE>(this); }
+
+    public int size() {
+        return size;
+    }
+
+
+    public Iterable<PE> unorderedIterable() {
+        return new Iterable<PE>() {
+            @Override
+            public Iterator<PE> iterator() {
+                return new Iterator<PE>() {
+                    final private IteratorChain chain = new IteratorChain();
+
+                    { // initialize the chain with the unordered iterators of the per sample pileups
+                        for ( PileupElementTracker<PE> pet : pileup.values() ) {
+                            chain.addIterator(pet.unorderedIterator());
+                        }
+                    }
+                    @Override public boolean hasNext() { return chain.hasNext(); }
+                    @Override public PE next() { return (PE)chain.next(); }
+                    @Override public void remove() { throw new UnsupportedOperationException("Cannot remove"); }
+                };
+            }
+        };
+    }
+}
\ No newline at end of file
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/pileup/ReadBackedPileup.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/pileup/ReadBackedPileup.java
new file mode 100644
index 0000000..e4394f1
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/pileup/ReadBackedPileup.java
@@ -0,0 +1,295 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.utils.pileup;
+
+import org.broadinstitute.gatk.utils.GenomeLoc;
+import org.broadinstitute.gatk.utils.HasGenomeLocation;
+import org.broadinstitute.gatk.utils.fragments.FragmentCollection;
+import org.broadinstitute.gatk.utils.sam.GATKSAMRecord;
+
+import java.util.Collection;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * A data retrieval interface for accessing parts of the pileup.
+ *
+ * @author mhanna
+ * @version 0.1
+ */
+public interface ReadBackedPileup extends Iterable<PileupElement>, HasGenomeLocation {
+    /**
+     * Returns a new ReadBackedPileup that is free of deletion spanning reads in this pileup.  Note that this
+     * does not copy the data, so both ReadBackedPileups should not be changed.  Doesn't make an unnecessary copy
+     * of the pileup (just returns this) if there are no deletions in the pileup.
+     *
+     * @return
+     */
+    public ReadBackedPileup getPileupWithoutDeletions();
+
+    /**
+     * Returns a new ReadBackedPileup where only one read from an overlapping read
+     * pair is retained.  If the two reads in question disagree to their basecall,
+     * neither read is retained.  If they agree on the base, the read with the higher
+     * quality observation is retained
+     *
+     * @return the newly filtered pileup
+     */
+    public ReadBackedPileup getOverlappingFragmentFilteredPileup();
+
+    /**
+     * Returns a new ReadBackedPileup where only one read from an overlapping read
+     * pair is retained.  If discardDiscordant and the two reads in question disagree to their basecall,
+     * neither read is retained.  Otherwise, the read with the higher
+     * quality (base or mapping, depending on baseQualNotMapQual) observation is retained
+     *
+     * @return the newly filtered pileup
+     */
+    public ReadBackedPileup getOverlappingFragmentFilteredPileup(boolean discardDiscordant, boolean baseQualNotMapQual);
+
+    /**
+     * Returns a new ReadBackedPileup that is free of mapping quality zero reads in this pileup.  Note that this
+     * does not copy the data, so both ReadBackedPileups should not be changed.  Doesn't make an unnecessary copy
+     * of the pileup (just returns this) if there are no MQ0 reads in the pileup.
+     *
+     * @return
+     */
+    public ReadBackedPileup getPileupWithoutMappingQualityZeroReads();
+
+    /**
+     * Gets the pileup consisting of only reads on the positive strand.
+     * @return A read-backed pileup consisting only of reads on the positive strand.
+     */
+    public ReadBackedPileup getPositiveStrandPileup();
+
+    /**
+     * Gets the pileup consisting of only reads on the negative strand.
+     * @return A read-backed pileup consisting only of reads on the negative strand.
+     */
+    public ReadBackedPileup getNegativeStrandPileup();
+
+    /**
+     * Gets a pileup consisting of all those elements passed by a given filter.
+     * @param filter Filter to use when testing for elements.
+     * @return a pileup without the given filtered elements.
+     */
+    public ReadBackedPileup getFilteredPileup(PileupElementFilter filter);
+
+    /** Returns subset of this pileup that contains only bases with quality >= minBaseQ, coming from
+     * reads with mapping qualities >= minMapQ. This method allocates and returns a new instance of ReadBackedPileup.
+     * @param minBaseQ
+     * @param minMapQ
+     * @return
+     */
+    public ReadBackedPileup getBaseAndMappingFilteredPileup( int minBaseQ, int minMapQ );
+
+    /** Returns subset of this pileup that contains only bases with quality >= minBaseQ.
+     * This method allocates and returns a new instance of ReadBackedPileup.
+     * @param minBaseQ
+     * @return
+     */
+    public ReadBackedPileup getBaseFilteredPileup( int minBaseQ );
+
+    /** Returns subset of this pileup that contains only bases coming from reads with mapping quality >= minMapQ.
+     * This method allocates and returns a new instance of ReadBackedPileup.
+     * @param minMapQ
+     * @return
+     */
+    public ReadBackedPileup getMappingFilteredPileup( int minMapQ );
+
+    /**
+     * Returns a pileup randomly downsampled to the desiredCoverage.
+     *
+     * @param desiredCoverage
+     * @return
+     */
+    public ReadBackedPileup getDownsampledPileup(int desiredCoverage);
+
+    /**
+     * Gets a collection of all the read groups represented in this pileup.
+     * @return A collection of all the read group ids represented in this pileup.
+     */
+    public Collection<String> getReadGroups();
+
+    /**
+     * Gets all the reads associated with a given read group.
+     * @param readGroupId Identifier for the read group.
+     * @return A pileup containing only the reads in the given read group.
+     */
+    public ReadBackedPileup getPileupForReadGroup(String readGroupId);
+
+    /**
+     * Gets all the reads associated with a given read groups.
+     * @param rgSet Set of identifiers for the read group.
+     * @return A pileup containing only the reads in the given read groups.
+     */
+    public ReadBackedPileup getPileupForReadGroups(final HashSet<String> rgSet);
+    
+    /**
+     * Gets all reads in a given lane id. (Lane ID is the read group
+     * id stripped of the last .XX sample identifier added by the GATK).
+     * @param laneID The read group ID without the sample identifier added by the GATK.
+     * @return A pileup containing the reads from all samples in the given lane.
+     */
+    public ReadBackedPileup getPileupForLane(String laneID);
+
+    /**
+     * Gets a collection of *names* of all the samples stored in this pileup.
+     * @return Collection of names
+     */
+    public Collection<String> getSamples();
+
+
+    /**
+     * Gets the particular subset of this pileup for all the given sample names.
+     * @param sampleNames Name of the sample to use.
+     * @return A subset of this pileup containing only reads with the given sample.
+     */
+    public ReadBackedPileup getPileupForSamples(Collection<String> sampleNames);
+
+    /**
+     * Gets the particular subset of this pileup for each given sample name.
+     *
+     * Same as calling getPileupForSample for all samples, but in O(n) instead of O(n^2).
+     *
+     * @param sampleNames Name of the sample to use.
+     * @return A subset of this pileup containing only reads with the given sample.
+     */
+    public Map<String, ReadBackedPileup> getPileupsForSamples(Collection<String> sampleNames);
+
+
+    /**
+     * Gets the particular subset of this pileup with the given sample name.
+     * @param sampleName Name of the sample to use.
+     * @return A subset of this pileup containing only reads with the given sample.
+     */
+    public ReadBackedPileup getPileupForSample(String sampleName);
+    
+    /**
+     * Simple useful routine to count the number of deletion bases in this pileup
+     *
+     * @return
+     */
+    public int getNumberOfDeletions();
+
+    /**
+     * Simple useful routine to count the number of deletion bases in at the next position this pileup
+     *
+     * @return
+     */
+    public int getNumberOfDeletionsAfterThisElement();
+
+    /**
+     * Simple useful routine to count the number of insertions right after this pileup
+     *
+     * @return
+     */
+    public int getNumberOfInsertionsAfterThisElement();
+
+    public int getNumberOfMappingQualityZeroReads();
+
+    /**
+     * @return the number of physical elements in this pileup (a reduced read is counted just once)
+     */
+    public int getNumberOfElements();
+
+    /**
+     * @return the number of abstract elements in this pileup (reduced reads are expanded to count all reads that they represent)
+     */
+    public int depthOfCoverage();
+
+    /**
+     * @return true if there are 0 elements in the pileup, false otherwise
+     */
+    public boolean isEmpty();
+
+    /**
+     * @return the location of this pileup
+     */
+    public GenomeLoc getLocation();
+
+    /**
+     * Get counts of A, C, G, T in order, which returns a int[4] vector with counts according
+     * to BaseUtils.simpleBaseToBaseIndex for each base.
+     *
+     * @return
+     */
+    public int[] getBaseCounts();
+
+    public String getPileupString(Character ref);
+
+    /**
+     * Returns a list of the reads in this pileup. Note this call costs O(n) and allocates fresh lists each time
+     * @return
+     */
+    public List<GATKSAMRecord> getReads();
+
+    /**
+     * Returns a list of the offsets in this pileup. Note this call costs O(n) and allocates fresh lists each time
+     * @return
+     */
+    public List<Integer> getOffsets();
+
+    /**
+     * Returns an array of the bases in this pileup. Note this call costs O(n) and allocates fresh array each time
+     * @return
+     */
+    public byte[] getBases();
+
+    /**
+    * Returns an array of the quals in this pileup. Note this call costs O(n) and allocates fresh array each time
+    * @return
+    */
+    public byte[] getQuals();
+
+    /**
+     * Get an array of the mapping qualities
+     * @return
+     */
+    public int[] getMappingQuals();
+
+    /**
+     * Returns a new ReadBackedPileup that is sorted by start coordinate of the reads.
+     *
+     * @return
+     */
+    public ReadBackedPileup getStartSortedPileup();
+
+    /**
+     * Converts this pileup into a FragmentCollection (see FragmentUtils for documentation)
+     * @return
+     */
+    public FragmentCollection<PileupElement> toFragments();
+
+    /**
+     * Creates a full copy (not shallow) of the ReadBacked Pileup
+     *
+     * @return
+     */
+    public ReadBackedPileup copy();
+
+}
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/pileup/ReadBackedPileupImpl.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/pileup/ReadBackedPileupImpl.java
new file mode 100644
index 0000000..840fbeb
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/pileup/ReadBackedPileupImpl.java
@@ -0,0 +1,1040 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.utils.pileup;
+
+import org.broadinstitute.gatk.engine.GenomeAnalysisEngine;
+import org.broadinstitute.gatk.utils.GenomeLoc;
+import org.broadinstitute.gatk.utils.exceptions.ReviewedGATKException;
+import org.broadinstitute.gatk.utils.fragments.FragmentCollection;
+import org.broadinstitute.gatk.utils.fragments.FragmentUtils;
+import org.broadinstitute.gatk.utils.locusiterator.LocusIteratorByState;
+import org.broadinstitute.gatk.utils.sam.GATKSAMRecord;
+import org.broadinstitute.gatk.utils.BaseUtils;
+
+import java.util.*;
+
+public class ReadBackedPileupImpl implements ReadBackedPileup {
+    protected final GenomeLoc loc;
+    protected final PileupElementTracker<PileupElement> pileupElementTracker;
+
+    private final static int UNINITIALIZED_CACHED_INT_VALUE = -1;
+
+    /**
+     * Different then number of elements due to reduced reads
+     */
+    private int depthOfCoverage = UNINITIALIZED_CACHED_INT_VALUE;
+    private int nDeletions = UNINITIALIZED_CACHED_INT_VALUE;            // cached value of the number of deletions
+    private int nMQ0Reads = UNINITIALIZED_CACHED_INT_VALUE;             // cached value of the number of MQ0 reads
+
+    /**
+     * Create a new version of a read backed pileup at loc, using the reads and their corresponding
+     * offsets.  This pileup will contain a list, in order of the reads, of the piled bases at
+     * reads[i] for all i in offsets.  Does not make a copy of the data, so it's not safe to
+     * go changing the reads.
+     *
+     * @param loc     The genome loc to associate reads wotj
+     * @param reads
+     * @param offsets
+     */
+    public ReadBackedPileupImpl(GenomeLoc loc, List<GATKSAMRecord> reads, List<Integer> offsets) {
+        this.loc = loc;
+        this.pileupElementTracker = readsOffsets2Pileup(reads, offsets);
+    }
+
+
+    /**
+     * Create a new version of a read backed pileup at loc without any aligned reads
+     */
+    public ReadBackedPileupImpl(GenomeLoc loc) {
+        this(loc, new UnifiedPileupElementTracker<PileupElement>());
+    }
+
+    /**
+     * Create a new version of a read backed pileup at loc, using the reads and their corresponding
+     * offsets.  This lower level constructure assumes pileup is well-formed and merely keeps a
+     * pointer to pileup.  Don't go changing the data in pileup.
+     */
+    public ReadBackedPileupImpl(GenomeLoc loc, List<PileupElement> pileup) {
+        if (loc == null) throw new ReviewedGATKException("Illegal null genomeloc in ReadBackedPileup");
+        if (pileup == null) throw new ReviewedGATKException("Illegal null pileup in ReadBackedPileup");
+
+        this.loc = loc;
+        this.pileupElementTracker = new UnifiedPileupElementTracker<PileupElement>(pileup);
+    }
+
+    /**
+     * Optimization of above constructor where all of the cached data is provided
+     *
+     * @param loc
+     * @param pileup
+     */
+    @Deprecated
+    public ReadBackedPileupImpl(GenomeLoc loc, List<PileupElement> pileup, int size, int nDeletions, int nMQ0Reads) {
+        this(loc, pileup);
+    }
+
+    protected ReadBackedPileupImpl(GenomeLoc loc, PileupElementTracker<PileupElement> tracker) {
+        this.loc = loc;
+        this.pileupElementTracker = tracker;
+    }
+
+    public ReadBackedPileupImpl(GenomeLoc loc, Map<String, ReadBackedPileupImpl> pileupsBySample) {
+        this.loc = loc;
+        PerSamplePileupElementTracker<PileupElement> tracker = new PerSamplePileupElementTracker<PileupElement>();
+        for (Map.Entry<String, ReadBackedPileupImpl> pileupEntry : pileupsBySample.entrySet()) {
+            tracker.addElements(pileupEntry.getKey(), pileupEntry.getValue().pileupElementTracker);
+        }
+        this.pileupElementTracker = tracker;
+    }
+
+    public ReadBackedPileupImpl(GenomeLoc loc, List<GATKSAMRecord> reads, int offset) {
+        this.loc = loc;
+        this.pileupElementTracker = readsOffsets2Pileup(reads, offset);
+    }
+
+    /**
+     * Helper routine for converting reads and offset lists to a PileupElement list.
+     *
+     * @param reads
+     * @param offsets
+     * @return
+     */
+    private PileupElementTracker<PileupElement> readsOffsets2Pileup(List<GATKSAMRecord> reads, List<Integer> offsets) {
+        if (reads == null) throw new ReviewedGATKException("Illegal null read list in UnifiedReadBackedPileup");
+        if (offsets == null) throw new ReviewedGATKException("Illegal null offsets list in UnifiedReadBackedPileup");
+        if (reads.size() != offsets.size())
+            throw new ReviewedGATKException("Reads and offset lists have different sizes!");
+
+        UnifiedPileupElementTracker<PileupElement> pileup = new UnifiedPileupElementTracker<PileupElement>();
+        for (int i = 0; i < reads.size(); i++) {
+            GATKSAMRecord read = reads.get(i);
+            int offset = offsets.get(i);
+            pileup.add(createNewPileupElement(read, offset)); // only used to create fake pileups for testing so ancillary information is not important
+        }
+
+        return pileup;
+    }
+
+    /**
+     * Helper routine for converting reads and a single offset to a PileupElement list.
+     *
+     * @param reads
+     * @param offset
+     * @return
+     */
+    private PileupElementTracker<PileupElement> readsOffsets2Pileup(List<GATKSAMRecord> reads, int offset) {
+        if (reads == null) throw new ReviewedGATKException("Illegal null read list in UnifiedReadBackedPileup");
+        if (offset < 0) throw new ReviewedGATKException("Illegal offset < 0 UnifiedReadBackedPileup");
+
+        UnifiedPileupElementTracker<PileupElement> pileup = new UnifiedPileupElementTracker<PileupElement>();
+        for (GATKSAMRecord read : reads) {
+            pileup.add(createNewPileupElement(read, offset)); // only used to create fake pileups for testing so ancillary information is not important
+        }
+
+        return pileup;
+    }
+
+    protected ReadBackedPileupImpl createNewPileup(GenomeLoc loc, PileupElementTracker<PileupElement> tracker) {
+        return new ReadBackedPileupImpl(loc, tracker);
+    }
+
+    protected PileupElement createNewPileupElement(GATKSAMRecord read, int offset) {
+        return LocusIteratorByState.createPileupForReadAndOffset(read, offset);
+    }    
+    
+    // --------------------------------------------------------
+    //
+    // Special 'constructors'
+    //
+    // --------------------------------------------------------
+
+    /**
+     * Returns a new ReadBackedPileup that is free of deletion spanning reads in this pileup.  Note that this
+     * does not copy the data, so both ReadBackedPileups should not be changed.  Doesn't make an unnecessary copy
+     * of the pileup (just returns this) if there are no deletions in the pileup.
+     *
+     * @return
+     */
+    @Override
+    public ReadBackedPileupImpl getPileupWithoutDeletions() {
+        if (getNumberOfDeletions() > 0) {
+            if (pileupElementTracker instanceof PerSamplePileupElementTracker) {
+                PerSamplePileupElementTracker<PileupElement> tracker = (PerSamplePileupElementTracker<PileupElement>) pileupElementTracker;
+                PerSamplePileupElementTracker<PileupElement> filteredTracker = new PerSamplePileupElementTracker<PileupElement>();
+
+                for (final String sample : tracker.getSamples()) {
+                    PileupElementTracker<PileupElement> perSampleElements = tracker.getElements(sample);
+                    ReadBackedPileupImpl pileup = createNewPileup(loc, perSampleElements).getPileupWithoutDeletions();
+                    filteredTracker.addElements(sample, pileup.pileupElementTracker);
+                }
+                return createNewPileup(loc, filteredTracker);
+
+            } else {
+                UnifiedPileupElementTracker<PileupElement> tracker = (UnifiedPileupElementTracker<PileupElement>) pileupElementTracker;
+                UnifiedPileupElementTracker<PileupElement> filteredTracker = new UnifiedPileupElementTracker<PileupElement>();
+
+                for (PileupElement p : tracker) {
+                    if (!p.isDeletion()) {
+                        filteredTracker.add(p);
+                    }
+                }
+                return createNewPileup(loc, filteredTracker);
+            }
+        } else {
+            return this;
+        }
+    }
+
+    /**
+     * Returns a new ReadBackedPileup where only one read from an overlapping read
+     * pair is retained.  If the two reads in question disagree to their basecall,
+     * neither read is retained.  If they agree on the base, the read with the higher
+     * base quality observation is retained
+     *
+     * @return the newly filtered pileup
+     */
+    @Override
+    public ReadBackedPileup getOverlappingFragmentFilteredPileup() {
+        return getOverlappingFragmentFilteredPileup(true, true);
+    }
+
+    /**
+     * Returns a new ReadBackedPileup where only one read from an overlapping read
+     * pair is retained.  If discardDiscordant and the two reads in question disagree to their basecall,
+     * neither read is retained.  Otherwise, the read with the higher
+     * quality (base or mapping, depending on baseQualNotMapQual) observation is retained
+     *
+     * @return the newly filtered pileup
+     */
+    @Override
+    public ReadBackedPileupImpl getOverlappingFragmentFilteredPileup(boolean discardDiscordant, boolean baseQualNotMapQual) {
+        if (pileupElementTracker instanceof PerSamplePileupElementTracker) {
+            PerSamplePileupElementTracker<PileupElement> tracker = (PerSamplePileupElementTracker<PileupElement>) pileupElementTracker;
+            PerSamplePileupElementTracker<PileupElement> filteredTracker = new PerSamplePileupElementTracker<PileupElement>();
+
+            for (final String sample : tracker.getSamples()) {
+                PileupElementTracker<PileupElement> perSampleElements = tracker.getElements(sample);
+                ReadBackedPileupImpl pileup = createNewPileup(loc, perSampleElements).getOverlappingFragmentFilteredPileup(discardDiscordant, baseQualNotMapQual);
+                filteredTracker.addElements(sample, pileup.pileupElementTracker);
+            }
+            return createNewPileup(loc, filteredTracker);
+        } else {
+            Map<String, PileupElement> filteredPileup = new HashMap<String, PileupElement>();
+
+            for (PileupElement p : pileupElementTracker) {
+                String readName = p.getRead().getReadName();
+
+                // if we've never seen this read before, life is good
+                if (!filteredPileup.containsKey(readName)) {
+                    filteredPileup.put(readName, p);
+                } else {
+                    PileupElement existing = filteredPileup.get(readName);
+
+                    // if the reads disagree at this position, throw them both out.  Otherwise
+                    // keep the element with the higher quality score
+                    if (discardDiscordant && existing.getBase() != p.getBase()) {
+                        filteredPileup.remove(readName);
+                    } else {
+                        if (baseQualNotMapQual) {
+                            if (existing.getQual() < p.getQual())
+                                filteredPileup.put(readName, p);
+                        }
+                        else {
+                            if (existing.getMappingQual() < p.getMappingQual())
+                                filteredPileup.put(readName, p);
+                        }
+                    }
+                }
+            }
+
+            UnifiedPileupElementTracker<PileupElement> filteredTracker = new UnifiedPileupElementTracker<PileupElement>();
+            for (PileupElement filteredElement : filteredPileup.values())
+                filteredTracker.add(filteredElement);
+
+            return createNewPileup(loc, filteredTracker);
+        }
+    }
+
+
+    /**
+     * Returns a new ReadBackedPileup that is free of mapping quality zero reads in this pileup.  Note that this
+     * does not copy the data, so both ReadBackedPileups should not be changed.  Doesn't make an unnecessary copy
+     * of the pileup (just returns this) if there are no MQ0 reads in the pileup.
+     *
+     * @return
+     */
+    @Override
+    public ReadBackedPileupImpl getPileupWithoutMappingQualityZeroReads() {
+        if (getNumberOfMappingQualityZeroReads() > 0) {
+            if (pileupElementTracker instanceof PerSamplePileupElementTracker) {
+                PerSamplePileupElementTracker<PileupElement> tracker = (PerSamplePileupElementTracker<PileupElement>) pileupElementTracker;
+                PerSamplePileupElementTracker<PileupElement> filteredTracker = new PerSamplePileupElementTracker<PileupElement>();
+
+                for (final String sample : tracker.getSamples()) {
+                    PileupElementTracker<PileupElement> perSampleElements = tracker.getElements(sample);
+                    ReadBackedPileupImpl pileup = createNewPileup(loc, perSampleElements).getPileupWithoutMappingQualityZeroReads();
+                    filteredTracker.addElements(sample, pileup.pileupElementTracker);
+                }
+                return createNewPileup(loc, filteredTracker);
+
+            } else {
+                UnifiedPileupElementTracker<PileupElement> tracker = (UnifiedPileupElementTracker<PileupElement>) pileupElementTracker;
+                UnifiedPileupElementTracker<PileupElement> filteredTracker = new UnifiedPileupElementTracker<PileupElement>();
+
+                for (PileupElement p : tracker) {
+                    if (p.getRead().getMappingQuality() > 0) {
+                        filteredTracker.add(p);
+                    }
+                }
+                return createNewPileup(loc, filteredTracker);
+            }
+        } else {
+            return this;
+        }
+    }
+
+    public ReadBackedPileupImpl getPositiveStrandPileup() {
+        if (pileupElementTracker instanceof PerSamplePileupElementTracker) {
+            PerSamplePileupElementTracker<PileupElement> tracker = (PerSamplePileupElementTracker<PileupElement>) pileupElementTracker;
+            PerSamplePileupElementTracker<PileupElement> filteredTracker = new PerSamplePileupElementTracker<PileupElement>();
+
+            for (final String sample : tracker.getSamples()) {
+                PileupElementTracker<PileupElement> perSampleElements = tracker.getElements(sample);
+                ReadBackedPileupImpl pileup = createNewPileup(loc, perSampleElements).getPositiveStrandPileup();
+                filteredTracker.addElements(sample, pileup.pileupElementTracker);
+            }
+            return createNewPileup(loc, filteredTracker);
+        } else {
+            UnifiedPileupElementTracker<PileupElement> tracker = (UnifiedPileupElementTracker<PileupElement>) pileupElementTracker;
+            UnifiedPileupElementTracker<PileupElement> filteredTracker = new UnifiedPileupElementTracker<PileupElement>();
+
+            for (PileupElement p : tracker) {
+                if (!p.getRead().getReadNegativeStrandFlag()) {
+                    filteredTracker.add(p);
+                }
+            }
+            return createNewPileup(loc, filteredTracker);
+        }
+    }
+
+    /**
+     * Gets the pileup consisting of only reads on the negative strand.
+     *
+     * @return A read-backed pileup consisting only of reads on the negative strand.
+     */
+    public ReadBackedPileupImpl getNegativeStrandPileup() {
+        if (pileupElementTracker instanceof PerSamplePileupElementTracker) {
+            PerSamplePileupElementTracker<PileupElement> tracker = (PerSamplePileupElementTracker<PileupElement>) pileupElementTracker;
+            PerSamplePileupElementTracker<PileupElement> filteredTracker = new PerSamplePileupElementTracker<PileupElement>();
+
+            for (final String sample : tracker.getSamples()) {
+                PileupElementTracker<PileupElement> perSampleElements = tracker.getElements(sample);
+                ReadBackedPileupImpl pileup = createNewPileup(loc, perSampleElements).getNegativeStrandPileup();
+                filteredTracker.addElements(sample, pileup.pileupElementTracker);
+            }
+            return createNewPileup(loc, filteredTracker);
+        } else {
+            UnifiedPileupElementTracker<PileupElement> tracker = (UnifiedPileupElementTracker<PileupElement>) pileupElementTracker;
+            UnifiedPileupElementTracker<PileupElement> filteredTracker = new UnifiedPileupElementTracker<PileupElement>();
+
+            for (PileupElement p : tracker) {
+                if (p.getRead().getReadNegativeStrandFlag()) {
+                    filteredTracker.add(p);
+                }
+            }
+            return createNewPileup(loc, filteredTracker);
+        }
+    }
+
+    /**
+     * Gets a pileup consisting of all those elements passed by a given filter.
+     *
+     * @param filter Filter to use when testing for elements.
+     * @return a pileup without the given filtered elements.
+     */
+    public ReadBackedPileupImpl getFilteredPileup(PileupElementFilter filter) {
+        if (pileupElementTracker instanceof PerSamplePileupElementTracker) {
+            PerSamplePileupElementTracker<PileupElement> tracker = (PerSamplePileupElementTracker<PileupElement>) pileupElementTracker;
+            PerSamplePileupElementTracker<PileupElement> filteredTracker = new PerSamplePileupElementTracker<PileupElement>();
+
+            for (final String sample : tracker.getSamples()) {
+                PileupElementTracker<PileupElement> perSampleElements = tracker.getElements(sample);
+                ReadBackedPileupImpl pileup = createNewPileup(loc, perSampleElements).getFilteredPileup(filter);
+                filteredTracker.addElements(sample, pileup.pileupElementTracker);
+            }
+
+            return createNewPileup(loc, filteredTracker);
+        } else {
+            UnifiedPileupElementTracker<PileupElement> filteredTracker = new UnifiedPileupElementTracker<PileupElement>();
+
+            for (PileupElement p : pileupElementTracker) {
+                if (filter.allow(p))
+                    filteredTracker.add(p);
+            }
+
+            return createNewPileup(loc, filteredTracker);
+        }
+    }
+
+    /**
+     * Returns subset of this pileup that contains only bases with quality >= minBaseQ, coming from
+     * reads with mapping qualities >= minMapQ. This method allocates and returns a new instance of ReadBackedPileup.
+     *
+     * @param minBaseQ
+     * @param minMapQ
+     * @return
+     */
+    @Override
+    public ReadBackedPileupImpl getBaseAndMappingFilteredPileup(int minBaseQ, int minMapQ) {
+        if (pileupElementTracker instanceof PerSamplePileupElementTracker) {
+            PerSamplePileupElementTracker<PileupElement> tracker = (PerSamplePileupElementTracker<PileupElement>) pileupElementTracker;
+            PerSamplePileupElementTracker<PileupElement> filteredTracker = new PerSamplePileupElementTracker<PileupElement>();
+
+            for (final String sample : tracker.getSamples()) {
+                PileupElementTracker<PileupElement> perSampleElements = tracker.getElements(sample);
+                ReadBackedPileupImpl pileup = createNewPileup(loc, perSampleElements).getBaseAndMappingFilteredPileup(minBaseQ, minMapQ);
+                filteredTracker.addElements(sample, pileup.pileupElementTracker);
+            }
+
+            return createNewPileup(loc, filteredTracker);
+        } else {
+            UnifiedPileupElementTracker<PileupElement> filteredTracker = new UnifiedPileupElementTracker<PileupElement>();
+
+            for (PileupElement p : pileupElementTracker) {
+                if (p.getRead().getMappingQuality() >= minMapQ && (p.isDeletion() || p.getQual() >= minBaseQ)) {
+                    filteredTracker.add(p);
+                }
+            }
+
+            return createNewPileup(loc, filteredTracker);
+        }
+    }
+
+    /**
+     * Returns subset of this pileup that contains only bases with quality >= minBaseQ.
+     * This method allocates and returns a new instance of ReadBackedPileup.
+     *
+     * @param minBaseQ
+     * @return
+     */
+    @Override
+    public ReadBackedPileup getBaseFilteredPileup(int minBaseQ) {
+        return getBaseAndMappingFilteredPileup(minBaseQ, -1);
+    }
+
+    /**
+     * Returns subset of this pileup that contains only bases coming from reads with mapping quality >= minMapQ.
+     * This method allocates and returns a new instance of ReadBackedPileup.
+     *
+     * @param minMapQ
+     * @return
+     */
+    @Override
+    public ReadBackedPileup getMappingFilteredPileup(int minMapQ) {
+        return getBaseAndMappingFilteredPileup(-1, minMapQ);
+    }
+
+    /**
+     * Gets a list of the read groups represented in this pileup.
+     *
+     * @return
+     */
+    @Override
+    public Collection<String> getReadGroups() {
+        Set<String> readGroups = new HashSet<String>();
+        for (PileupElement pileupElement : this)
+            readGroups.add(pileupElement.getRead().getReadGroup().getReadGroupId());
+        return readGroups;
+    }
+
+    /**
+     * Gets the pileup for a given read group.  Horrendously inefficient at this point.
+     *
+     * @param targetReadGroupId Identifier for the read group.
+     * @return A read-backed pileup containing only the reads in the given read group.
+     */
+    @Override
+    public ReadBackedPileupImpl getPileupForReadGroup(String targetReadGroupId) {
+        if (pileupElementTracker instanceof PerSamplePileupElementTracker) {
+            PerSamplePileupElementTracker<PileupElement> tracker = (PerSamplePileupElementTracker<PileupElement>) pileupElementTracker;
+            PerSamplePileupElementTracker<PileupElement> filteredTracker = new PerSamplePileupElementTracker<PileupElement>();
+
+            for (final String sample : tracker.getSamples()) {
+                PileupElementTracker<PileupElement> perSampleElements = tracker.getElements(sample);
+                ReadBackedPileupImpl pileup = createNewPileup(loc, perSampleElements).getPileupForReadGroup(targetReadGroupId);
+                if (pileup != null)
+                    filteredTracker.addElements(sample, pileup.pileupElementTracker);
+            }
+            return filteredTracker.size() > 0 ? createNewPileup(loc, filteredTracker) : null;
+        } else {
+            UnifiedPileupElementTracker<PileupElement> filteredTracker = new UnifiedPileupElementTracker<PileupElement>();
+            for (PileupElement p : pileupElementTracker) {
+                GATKSAMRecord read = p.getRead();
+                if (targetReadGroupId != null) {
+                    if (read.getReadGroup() != null && targetReadGroupId.equals(read.getReadGroup().getReadGroupId()))
+                        filteredTracker.add(p);
+                } else {
+                    if (read.getReadGroup() == null || read.getReadGroup().getReadGroupId() == null)
+                        filteredTracker.add(p);
+                }
+            }
+            return filteredTracker.size() > 0 ? createNewPileup(loc, filteredTracker) : null;
+        }
+    }
+
+    /**
+     * Gets the pileup for a set of read groups.  Horrendously inefficient at this point.
+     *
+     * @param rgSet List of identifiers for the read groups.
+     * @return A read-backed pileup containing only the reads in the given read groups.
+     */
+    @Override
+    public ReadBackedPileupImpl getPileupForReadGroups(final HashSet<String> rgSet) {
+        if (pileupElementTracker instanceof PerSamplePileupElementTracker) {
+            PerSamplePileupElementTracker<PileupElement> tracker = (PerSamplePileupElementTracker<PileupElement>) pileupElementTracker;
+            PerSamplePileupElementTracker<PileupElement> filteredTracker = new PerSamplePileupElementTracker<PileupElement>();
+
+            for (final String sample : tracker.getSamples()) {
+                PileupElementTracker<PileupElement> perSampleElements = tracker.getElements(sample);
+                ReadBackedPileupImpl pileup = createNewPileup(loc, perSampleElements).getPileupForReadGroups(rgSet);
+                if (pileup != null)
+                    filteredTracker.addElements(sample, pileup.pileupElementTracker);
+            }
+            return filteredTracker.size() > 0 ? createNewPileup(loc, filteredTracker) : null;
+        } else {
+            UnifiedPileupElementTracker<PileupElement> filteredTracker = new UnifiedPileupElementTracker<PileupElement>();
+            for (PileupElement p : pileupElementTracker) {
+                GATKSAMRecord read = p.getRead();
+                if (rgSet != null && !rgSet.isEmpty()) {
+                    if (read.getReadGroup() != null && rgSet.contains(read.getReadGroup().getReadGroupId()))
+                        filteredTracker.add(p);
+                } else {
+                    if (read.getReadGroup() == null || read.getReadGroup().getReadGroupId() == null)
+                        filteredTracker.add(p);
+                }
+            }
+            return filteredTracker.size() > 0 ? createNewPileup(loc, filteredTracker) : null;
+        }
+    }
+
+    @Override
+    public ReadBackedPileupImpl getPileupForLane(String laneID) {
+        if (pileupElementTracker instanceof PerSamplePileupElementTracker) {
+            PerSamplePileupElementTracker<PileupElement> tracker = (PerSamplePileupElementTracker<PileupElement>) pileupElementTracker;
+            PerSamplePileupElementTracker<PileupElement> filteredTracker = new PerSamplePileupElementTracker<PileupElement>();
+
+            for (final String sample : tracker.getSamples()) {
+                PileupElementTracker<PileupElement> perSampleElements = tracker.getElements(sample);
+                ReadBackedPileupImpl pileup = createNewPileup(loc, perSampleElements).getPileupForLane(laneID);
+                if (pileup != null)
+                    filteredTracker.addElements(sample, pileup.pileupElementTracker);
+            }
+            return filteredTracker.size() > 0 ? createNewPileup(loc, filteredTracker) : null;
+        } else {
+            UnifiedPileupElementTracker<PileupElement> filteredTracker = new UnifiedPileupElementTracker<PileupElement>();
+            for (PileupElement p : pileupElementTracker) {
+                GATKSAMRecord read = p.getRead();
+                if (laneID != null) {
+                    if (read.getReadGroup() != null &&
+                            (read.getReadGroup().getReadGroupId().startsWith(laneID + ".")) ||   // lane is the same, but sample identifier is different
+                            (read.getReadGroup().getReadGroupId().equals(laneID)))               // in case there is no sample identifier, they have to be exactly the same
+                        filteredTracker.add(p);
+                } else {
+                    if (read.getReadGroup() == null || read.getReadGroup().getReadGroupId() == null)
+                        filteredTracker.add(p);
+                }
+            }
+            return filteredTracker.size() > 0 ? createNewPileup(loc, filteredTracker) : null;
+        }
+    }
+
+    public Collection<String> getSamples() {
+        if (pileupElementTracker instanceof PerSamplePileupElementTracker) {
+            PerSamplePileupElementTracker<PileupElement> tracker = (PerSamplePileupElementTracker<PileupElement>) pileupElementTracker;
+            return new HashSet<String>(tracker.getSamples());
+        } else {
+            Collection<String> sampleNames = new HashSet<String>();
+            for (PileupElement p : this) {
+                GATKSAMRecord read = p.getRead();
+                String sampleName = read.getReadGroup() != null ? read.getReadGroup().getSample() : null;
+                sampleNames.add(sampleName);
+            }
+            return sampleNames;
+        }
+    }
+
+    /**
+     * Returns a pileup randomly downsampled to the desiredCoverage.
+     *
+     * TODO: delete this once the experimental downsampler stabilizes
+     *
+     * @param desiredCoverage
+     * @return
+     */
+    @Override
+    public ReadBackedPileup getDownsampledPileup(int desiredCoverage) {
+        if (getNumberOfElements() <= desiredCoverage)
+            return this;
+
+        // randomly choose numbers corresponding to positions in the reads list
+        TreeSet<Integer> positions = new TreeSet<Integer>();
+        for (int i = 0; i < desiredCoverage; /* no update */) {
+            if (positions.add(GenomeAnalysisEngine.getRandomGenerator().nextInt(getNumberOfElements())))
+                i++;
+        }
+
+        if (pileupElementTracker instanceof PerSamplePileupElementTracker) {
+            PerSamplePileupElementTracker<PileupElement> tracker = (PerSamplePileupElementTracker<PileupElement>) pileupElementTracker;
+            PerSamplePileupElementTracker<PileupElement> filteredTracker = new PerSamplePileupElementTracker<PileupElement>();
+
+
+            for (final String sample : tracker.getSamples()) {
+                PileupElementTracker<PileupElement> perSampleElements = tracker.getElements(sample);
+
+                int current = 0;
+                UnifiedPileupElementTracker<PileupElement> filteredPileup = new UnifiedPileupElementTracker<PileupElement>();
+                for (PileupElement p : perSampleElements) {
+                    if (positions.contains(current))
+                        filteredPileup.add(p);
+                    current++;
+
+                }
+                filteredTracker.addElements(sample, filteredPileup);
+            }
+
+            return createNewPileup(loc, filteredTracker);
+        } else {
+            UnifiedPileupElementTracker<PileupElement> tracker = (UnifiedPileupElementTracker<PileupElement>) pileupElementTracker;
+            UnifiedPileupElementTracker<PileupElement> filteredTracker = new UnifiedPileupElementTracker<PileupElement>();
+
+            Iterator positionIter = positions.iterator();
+
+            while (positionIter.hasNext()) {
+                int nextReadToKeep = (Integer) positionIter.next();
+                filteredTracker.add(tracker.get(nextReadToKeep));
+            }
+
+            return createNewPileup(getLocation(), filteredTracker);
+        }
+    }
+
+    @Override
+    public ReadBackedPileup getPileupForSamples(Collection<String> sampleNames) {
+        if (pileupElementTracker instanceof PerSamplePileupElementTracker) {
+            PerSamplePileupElementTracker<PileupElement> tracker = (PerSamplePileupElementTracker<PileupElement>) pileupElementTracker;
+            PileupElementTracker<PileupElement> filteredElements = tracker.getElements(sampleNames);
+            return filteredElements != null ? createNewPileup(loc, filteredElements) : null;
+        } else {
+            HashSet<String> hashSampleNames = new HashSet<String>(sampleNames);                                         // to speed up the "contains" access in the for loop
+            UnifiedPileupElementTracker<PileupElement> filteredTracker = new UnifiedPileupElementTracker<PileupElement>();
+            for (PileupElement p : pileupElementTracker) {
+                GATKSAMRecord read = p.getRead();
+                if (sampleNames != null) {                                                                              // still checking on sampleNames because hashSampleNames will never be null. And empty means something else.
+                    if (read.getReadGroup() != null && hashSampleNames.contains(read.getReadGroup().getSample()))
+                        filteredTracker.add(p);
+                } else {
+                    if (read.getReadGroup() == null || read.getReadGroup().getSample() == null)
+                        filteredTracker.add(p);
+                }
+            }
+            return filteredTracker.size() > 0 ? createNewPileup(loc, filteredTracker) : null;
+        }
+    }
+
+    @Override
+    public Map<String, ReadBackedPileup> getPileupsForSamples(Collection<String> sampleNames) {
+        Map<String, ReadBackedPileup> result = new HashMap<String, ReadBackedPileup>();
+        if (pileupElementTracker instanceof PerSamplePileupElementTracker) {
+            PerSamplePileupElementTracker<PileupElement> tracker = (PerSamplePileupElementTracker<PileupElement>) pileupElementTracker;
+            for (String sample : sampleNames) {
+                PileupElementTracker<PileupElement> filteredElements = tracker.getElements(sample);
+                if (filteredElements != null)
+                    result.put(sample, createNewPileup(loc, filteredElements));
+            }
+        } else {
+            Map<String, UnifiedPileupElementTracker<PileupElement>> trackerMap = new HashMap<String, UnifiedPileupElementTracker<PileupElement>>();
+
+            for (String sample : sampleNames) {                                                                         // initialize pileups for each sample
+                UnifiedPileupElementTracker<PileupElement> filteredTracker = new UnifiedPileupElementTracker<PileupElement>();
+                trackerMap.put(sample, filteredTracker);
+            }
+            for (PileupElement p : pileupElementTracker) {                                                                         // go through all pileup elements only once and add them to the respective sample's pileup
+                GATKSAMRecord read = p.getRead();
+                if (read.getReadGroup() != null) {
+                    String sample = read.getReadGroup().getSample();
+                    UnifiedPileupElementTracker<PileupElement> tracker = trackerMap.get(sample);
+                    if (tracker != null)                                                                                // we only add the pileup the requested samples. Completely ignore the rest
+                        tracker.add(p);
+                }
+            }
+            for (Map.Entry<String, UnifiedPileupElementTracker<PileupElement>> entry : trackerMap.entrySet())                      // create the ReadBackedPileup for each sample
+                result.put(entry.getKey(), createNewPileup(loc, entry.getValue()));
+        }
+        return result;
+    }
+
+
+    @Override
+    public ReadBackedPileup getPileupForSample(String sampleName) {
+        if (pileupElementTracker instanceof PerSamplePileupElementTracker) {
+            PerSamplePileupElementTracker<PileupElement> tracker = (PerSamplePileupElementTracker<PileupElement>) pileupElementTracker;
+            PileupElementTracker<PileupElement> filteredElements = tracker.getElements(sampleName);
+            return filteredElements != null ? createNewPileup(loc, filteredElements) : null;
+        } else {
+            UnifiedPileupElementTracker<PileupElement> filteredTracker = new UnifiedPileupElementTracker<PileupElement>();
+            for (PileupElement p : pileupElementTracker) {
+                GATKSAMRecord read = p.getRead();
+                if (sampleName != null) {
+                    if (read.getReadGroup() != null && sampleName.equals(read.getReadGroup().getSample()))
+                        filteredTracker.add(p);
+                } else {
+                    if (read.getReadGroup() == null || read.getReadGroup().getSample() == null)
+                        filteredTracker.add(p);
+                }
+            }
+            return filteredTracker.size() > 0 ? createNewPileup(loc, filteredTracker) : null;
+        }
+    }
+
+    // --------------------------------------------------------
+    //
+    // iterators
+    //
+    // --------------------------------------------------------
+
+    /**
+     * The best way to access PileupElements where you only care about the bases and quals in the pileup.
+     * <p/>
+     * for (PileupElement p : this) { doSomething(p); }
+     * <p/>
+     * Provides efficient iteration of the data.
+     *
+     * @return
+     */
+    @Override
+    public Iterator<PileupElement> iterator() {
+        return new Iterator<PileupElement>() {
+            private final Iterator<PileupElement> wrappedIterator = pileupElementTracker.iterator();
+
+            public boolean hasNext() {
+                return wrappedIterator.hasNext();
+            }
+
+            public PileupElement next() {
+                return wrappedIterator.next();
+            }
+
+            public void remove() {
+                throw new UnsupportedOperationException("Cannot remove from a pileup element iterator");
+            }
+        };
+    }
+
+    /**
+     * The best way to access PileupElements where you only care not only about bases and quals in the pileup
+     * but also need access to the index of the pileup element in the pile.
+     *
+     * for (ExtendedPileupElement p : this) { doSomething(p); }
+     *
+     * Provides efficient iteration of the data.
+     *
+     * @return
+     */
+
+    /**
+     * Simple useful routine to count the number of deletion bases in this pileup
+     *
+     * @return
+     */
+    @Override
+    public int getNumberOfDeletions() {
+        if ( nDeletions == UNINITIALIZED_CACHED_INT_VALUE ) {
+            nDeletions = 0;
+            for (PileupElement p : pileupElementTracker.unorderedIterable() ) {
+                if (p.isDeletion()) {
+                    nDeletions++;
+                }
+            }
+        }
+        return nDeletions;
+    }
+
+    @Override
+    public int getNumberOfMappingQualityZeroReads() {
+        if ( nMQ0Reads == UNINITIALIZED_CACHED_INT_VALUE ) {
+            nMQ0Reads = 0;
+
+            for (PileupElement p : pileupElementTracker.unorderedIterable()) {
+                if (p.getRead().getMappingQuality() == 0) {
+                    nMQ0Reads++;
+                }
+            }
+        }
+
+        return nMQ0Reads;
+    }
+
+    /**
+     * @return the number of physical elements in this pileup
+     */
+    @Override
+    public int getNumberOfElements() {
+        return pileupElementTracker.size();
+    }
+
+    /**
+     * @return the number of abstract elements in this pileup
+     */
+    @Override
+    public int depthOfCoverage() {
+        if (depthOfCoverage == UNINITIALIZED_CACHED_INT_VALUE) {
+            depthOfCoverage = pileupElementTracker.size();
+        }
+        return depthOfCoverage;
+    }
+
+    /**
+     * @return true if there are 0 elements in the pileup, false otherwise
+     */
+    @Override
+    public boolean isEmpty() {
+        return getNumberOfElements() == 0;
+    }
+
+
+    /**
+     * @return the location of this pileup
+     */
+    @Override
+    public GenomeLoc getLocation() {
+        return loc;
+    }
+
+    /**
+     * Get counts of A, C, G, T in order, which returns a int[4] vector with counts according
+     * to BaseUtils.simpleBaseToBaseIndex for each base.
+     *
+     * @return
+     */
+    @Override
+    public int[] getBaseCounts() {
+        int[] counts = new int[4];
+
+        // TODO -- can be optimized with .unorderedIterable()
+        if (pileupElementTracker instanceof PerSamplePileupElementTracker) {
+            PerSamplePileupElementTracker<PileupElement> tracker = (PerSamplePileupElementTracker<PileupElement>) pileupElementTracker;
+            for (final String sample : tracker.getSamples()) {
+                int[] countsBySample = createNewPileup(loc, tracker.getElements(sample)).getBaseCounts();
+                for (int i = 0; i < counts.length; i++)
+                    counts[i] += countsBySample[i];
+            }
+        } else {
+            for (PileupElement pile : this) {
+                // skip deletion sites
+                if (!pile.isDeletion()) {
+                    int index = BaseUtils.simpleBaseToBaseIndex((char) pile.getBase());
+                    if (index != -1)
+                        counts[index]++;
+                }
+            }
+        }
+
+        return counts;
+    }
+
+    @Override
+    public String getPileupString(Character ref) {
+        // In the pileup format, each line represents a genomic position, consisting of chromosome name,
+        // coordinate, reference base, read bases, read qualities and alignment mapping qualities.
+        return String.format("%s %s %c %s %s",
+                getLocation().getContig(), getLocation().getStart(),    // chromosome name and coordinate
+                ref,                                                     // reference base
+                new String(getBases()),
+                getQualsString());
+    }
+
+    // --------------------------------------------------------
+    //
+    // Convenience functions that may be slow
+    //
+    // --------------------------------------------------------
+
+    /**
+     * Returns a list of the reads in this pileup. Note this call costs O(n) and allocates fresh lists each time
+     *
+     * @return
+     */
+    @Override
+    public List<GATKSAMRecord> getReads() {
+        List<GATKSAMRecord> reads = new ArrayList<GATKSAMRecord>(getNumberOfElements());
+        for (PileupElement pile : this) {
+            reads.add(pile.getRead());
+        }
+        return reads;
+    }
+
+    @Override
+    public int getNumberOfDeletionsAfterThisElement() {
+        int count = 0;
+        for (PileupElement p : pileupElementTracker.unorderedIterable()) {
+            if (p.isBeforeDeletionStart())
+                count++;
+        }
+        return count;
+    }
+
+    @Override
+    public int getNumberOfInsertionsAfterThisElement() {
+        int count = 0;
+        for (PileupElement p : pileupElementTracker.unorderedIterable()) {
+            if (p.isBeforeInsertion())
+                count++;
+        }
+        return count;
+
+    }
+    /**
+     * Returns a list of the offsets in this pileup. Note this call costs O(n) and allocates fresh lists each time
+     *
+     * @return
+     */
+    @Override
+    public List<Integer> getOffsets() {
+        List<Integer> offsets = new ArrayList<Integer>(getNumberOfElements());
+        for (PileupElement pile : pileupElementTracker.unorderedIterable()) {
+            offsets.add(pile.getOffset());
+        }
+        return offsets;
+    }
+
+    /**
+     * Returns an array of the bases in this pileup. Note this call costs O(n) and allocates fresh array each time
+     *
+     * @return
+     */
+    @Override
+    public byte[] getBases() {
+        byte[] v = new byte[getNumberOfElements()];
+        int pos = 0;
+        for (PileupElement pile : pileupElementTracker) {
+            v[pos++] = pile.getBase();
+        }
+        return v;
+    }
+
+    /**
+     * Returns an array of the quals in this pileup. Note this call costs O(n) and allocates fresh array each time
+     *
+     * @return
+     */
+    @Override
+    public byte[] getQuals() {
+        byte[] v = new byte[getNumberOfElements()];
+        int pos = 0;
+        for (PileupElement pile : pileupElementTracker) {
+            v[pos++] = pile.getQual();
+        }
+        return v;
+    }
+
+    /**
+     * Get an array of the mapping qualities
+     *
+     * @return
+     */
+    @Override
+    public int[] getMappingQuals() {
+        final int[] v = new int[getNumberOfElements()];
+        int pos = 0;
+        for ( final PileupElement pile : pileupElementTracker ) {
+            v[pos++] = pile.getRead().getMappingQuality();
+        }
+        return v;
+    }
+
+    static String quals2String(byte[] quals) {
+        StringBuilder qualStr = new StringBuilder();
+        for (int qual : quals) {
+            qual = Math.min(qual, 63);              // todo: fixme, this isn't a good idea
+            char qualChar = (char) (33 + qual);     // todo: warning, this is illegal for qual > 63
+            qualStr.append(qualChar);
+        }
+
+        return qualStr.toString();
+    }
+
+    private String getQualsString() {
+        return quals2String(getQuals());
+    }
+
+    /**
+     * Returns a new ReadBackedPileup that is sorted by start coordinate of the reads.
+     *
+     * @return
+     */
+    @Override
+    public ReadBackedPileup getStartSortedPileup() {
+
+        final TreeSet<PileupElement> sortedElements = new TreeSet<PileupElement>(new Comparator<PileupElement>() {
+            @Override
+            public int compare(PileupElement element1, PileupElement element2) {
+                final int difference = element1.getRead().getAlignmentStart() - element2.getRead().getAlignmentStart();
+                return difference != 0 ? difference : element1.getRead().getReadName().compareTo(element2.getRead().getReadName());
+            }
+        });
+
+        if (pileupElementTracker instanceof PerSamplePileupElementTracker) {
+            PerSamplePileupElementTracker<PileupElement> tracker = (PerSamplePileupElementTracker<PileupElement>) pileupElementTracker;
+
+            for (final String sample : tracker.getSamples()) {
+                PileupElementTracker<PileupElement> perSampleElements = tracker.getElements(sample);
+                for (PileupElement pile : perSampleElements)
+                    sortedElements.add(pile);
+            }
+        }
+        else {
+            UnifiedPileupElementTracker<PileupElement> tracker = (UnifiedPileupElementTracker<PileupElement>) pileupElementTracker;
+            for (PileupElement pile : tracker)
+                sortedElements.add(pile);
+        }
+
+        UnifiedPileupElementTracker<PileupElement> sortedTracker = new UnifiedPileupElementTracker<PileupElement>();
+        for (PileupElement pile : sortedElements)
+            sortedTracker.add(pile);
+
+        return createNewPileup(loc, sortedTracker);
+    }
+
+    @Override
+    public FragmentCollection<PileupElement> toFragments() {
+        return FragmentUtils.create(this);
+    }
+
+    @Override
+    public ReadBackedPileup copy() {
+        return new ReadBackedPileupImpl(loc, pileupElementTracker.copy());
+    }
+}
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/pileup2/Notes b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/pileup2/Notes
new file mode 100644
index 0000000..0d989fa
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/pileup2/Notes
@@ -0,0 +1,34 @@
+Features needed:
+
+- intrinsic support for samples.  Pileups are tree based data structures whose leaves are actual
+pile ups of a single "sample" and whose nodes are collections of multiple sub pileups.  This will
+make join and split operations very cheap.
+
+- should be light-weight to create, and hold only minimal cached data to avoid unnecessary overhead.
+Things like the number of deletions, insertions, etc shouldn't be required information.  Size will
+continue to be a key cached value.  Could create a simple caching data structure that calculations lots of metrics about the pileup and was somehow
+cached internally, via a "CachedRBP" structure.  This will make it very cheap and easy to filter
+pileups on the fly, costing O(N) to create the filtered context.
+
+- immutable
+
+- support for holding neighboring reads to the left and right of the pileup itself
+
+- unified picture for "regular" and "extended" events.  ExtendedEvents are really a special
+call from the engine and have nothing to do with the data itself.
+
+- Where should algorithms operating on the pileups go?  Two options are in the interface itself,
+making it very heavy-weight but easy to access, vs. in an associated PileupOps static methods, a
+la Collections.
+
+- The Pileup2 should support in the fly filtering, so that read filters can be added at the top level
+and applied at all levels of the tree.  Basically a filtering pileup would just create a new
+mirrored tree with filtering applied to each node.   Very low overhead.
+
+- Sizes could be cached as needed, so that only one pass is ever needed over the size of any pileup
+
+- Fundamentally pileups are just collections of read-backed data.  The PileupElements contain
+all of the smarts -- regular, indel, fragment-based.  We need to be able to create pileups containing
+multiple subtype elements, which by necessity will need to declare their own static consensusType.  How is it
+best to do this in Java?  Have a single global ENUM that enumerates all of the possible types at
+compile time?  Perhaps something more dynamic?
\ No newline at end of file
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/progressmeter/ProgressMeter.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/progressmeter/ProgressMeter.java
new file mode 100644
index 0000000..f77ac04
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/progressmeter/ProgressMeter.java
@@ -0,0 +1,465 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.utils.progressmeter;
+
+import com.google.java.contract.Ensures;
+import com.google.java.contract.Invariant;
+import com.google.java.contract.Requires;
+import org.apache.log4j.Logger;
+import org.broadinstitute.gatk.utils.*;
+import org.broadinstitute.gatk.utils.exceptions.UserException;
+
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
+import java.io.PrintStream;
+import java.util.Arrays;
+import java.util.List;
+
+/**
+ * A meter measuring progress on a calculation through a set of genomic regions that can
+ * print a few key metrics to a logger and optionally to a file
+ *
+ * The key information for assessing progress is a set of genome locs describing the total
+ * set of regions we will process.  Whenever (at reasonable intervals) the processing unit
+ * can called notifyOfProgress and this logger may, depending on the metering delay, print
+ * a log message with the following metrics:
+ *
+ *      -- Number of processed X (X = processing units)
+ *      -- Runtime per.1M X
+ *      -- Percent of regions to be processed completed
+ *      -- The estimated total runtime based on previous performance
+ *      -- The estimated time remaining for the entire process
+ *
+ * The optional file log an expanded set of metrics in tabular format
+ * suitable for subsequent analysis in R.
+ *
+ * This class is -- and MUST BE -- thread-safe for use in the GATK.  Multiple independent
+ * threads executing processors will be calling notifyOfProgress() simultaneously and this
+ * class does (and MUST) properly sort out the timings of logs without interlacing outputs
+ * because of these threads.
+ *
+ * Consequently, the fundamental model for when to print the logs is time based.  We basically
+ * print a meter message every X seconds, minutes, hours, whatever is appropriate based on the
+ * estimated remaining runtime.
+ *
+ * @author depristo
+ * @since 2010 maybe, but written in 09/12 for clarity
+ */
+ at Invariant({
+        "targetSizeInBP >= 0",
+        "progressPrintFrequency > 0"
+})
+public class ProgressMeter {
+    protected static final Logger logger = Logger.getLogger(ProgressMeter.class);
+
+    // --------------------------------------------------------------------------------
+    // static constants controlling overall system behavior
+    // --------------------------------------------------------------------------------
+
+    /**
+     * Min. milliseconds after we start up the meter before we will print our first meter message
+     */
+    private final static long MIN_ELAPSED_TIME_BEFORE_FIRST_PROGRESS = 30 * 1000;
+
+    /**
+     * How often should we print performance logging information, when we are sending this
+     * information to a file?  Not dynamically updated as the logger meter is.
+     */
+    private final static long PERFORMANCE_LOG_PRINT_FREQUENCY = 10 * 1000;
+
+    private final static double TWO_HOURS_IN_SECONDS    =  2.0 * 60.0 * 60.0;
+    private final static double TWELVE_HOURS_IN_SECONDS = 12.0 * 60.0 * 60.0;
+
+    // --------------------------------------------------------------------------------
+    // Variables we updating during running
+    // --------------------------------------------------------------------------------
+
+    /**
+     * When was the last time we printed progress log?  In milleseconds
+     */
+    private long lastProgressPrintTime = -1;
+
+    /**
+     * How frequently should we be printing our meter messages?  Dynamically updated
+     * depending on how long we think the run has left.
+     */
+    private long progressPrintFrequency = 10 * 1000; // default value
+
+    /**
+     * When was the last time we printed to the performance log?  In millseconds
+     */
+    private long lastPerformanceLogPrintTime = -1;
+
+    // --------------------------------------------------------------------------------
+    // final variables fixed at object creation time
+    // --------------------------------------------------------------------------------
+
+    /**
+     * The set of genome locs describing the total region we are processing with
+     * this GATK run.  Used to determine how close we are to completing the run
+     */
+    private final GenomeLocSortedSet regionsBeingProcessed;
+
+    /**
+     * Size, in bp, of the area we are processing, derived from regionsBeingProcessed.
+     * Updated once in the system in initial for performance reasons
+     */
+    private final long targetSizeInBP;
+
+    /**
+     * A string describing the type of units being processes, so we can say things like
+     * "we are running at X processingUnitName per second"
+     */
+    private final String processingUnitName;
+
+    /**
+     * The space allocated to #processingUnitName in the output
+     */
+    private final int processingUnitWidth;
+
+    /**
+     * The format string used for progress lines
+     */
+    private final String progressFormatString;
+
+    /**
+     * A potentially null file where we print a supplementary, R readable performance log
+     * file.
+     */
+    private final PrintStream performanceLog;
+
+    /** We use the SimpleTimer to time our run */
+    private final SimpleTimer timer = new SimpleTimer();
+
+    private GenomeLoc maxGenomeLoc = null;
+    private Position position = new Position(PositionStatus.STARTING);
+    private long nTotalRecordsProcessed = 0;
+
+    /**
+     * The elapsed time in nanosecond, updated by the daemon thread, so that
+     * we don't pay any system call overhead to determine the the elapsed time.
+     */
+    private long elapsedTimeInNanosecondUpdatedByDaemon = 0;
+
+    final ProgressMeterDaemon progressMeterDaemon;
+
+    /**
+     * Create a new ProgressMeter
+     *
+     * Note that progress meter isn't started until the client calls start()
+     *
+     * @param performanceLogFile an optional performance log file where a table of performance logs will be written
+     * @param processingUnitName the name of the unit type being processed, suitable for saying X seconds per processingUnitName
+     * @param processingIntervals the intervals being processed
+     */
+    public ProgressMeter(final File performanceLogFile,
+                         final String processingUnitName,
+                         final GenomeLocSortedSet processingIntervals) {
+        this(performanceLogFile, processingUnitName, processingIntervals, ProgressMeterDaemon.DEFAULT_POLL_FREQUENCY_MILLISECONDS);
+    }
+
+    protected ProgressMeter(final File performanceLogFile,
+                            final String processingUnitName,
+                            final GenomeLocSortedSet processingIntervals,
+                            final long pollingFrequency) {
+        if ( processingUnitName == null ) throw new IllegalArgumentException("processingUnitName cannot be null");
+        if ( processingIntervals == null ) throw new IllegalArgumentException("Target intervals cannot be null");
+
+        this.processingUnitName = processingUnitName;
+        this.regionsBeingProcessed = processingIntervals;
+        this.processingUnitWidth = Math.max(processingUnitName.length(), "processed".length());
+        this.progressFormatString = String.format("%%15s   %%%1$ds   %%7s   %%%1$ds      %%5.1f%%%%   %%7s   %%9s", processingUnitWidth);
+
+        // setup the performance logger output, if requested
+        if ( performanceLogFile != null ) {
+            try {
+                this.performanceLog = new PrintStream(new FileOutputStream(performanceLogFile));
+                final List<String> pLogHeader = Arrays.asList("elapsed.time", "units.processed", "processing.speed",
+                        "bp.processed", "bp.speed", "genome.fraction.complete", "est.total.runtime", "est.time.remaining");
+                performanceLog.println(Utils.join("\t", pLogHeader));
+            } catch (FileNotFoundException e) {
+                throw new UserException.CouldNotCreateOutputFile(performanceLogFile, e);
+            }
+        } else {
+            performanceLog = null;
+        }
+
+        // cached for performance reasons
+        targetSizeInBP = processingIntervals.coveredSize();
+
+        // start up the timer
+        progressMeterDaemon = new ProgressMeterDaemon(this, pollingFrequency);
+    }
+
+    public ProgressMeterDaemon getProgressMeterDaemon() {
+        return progressMeterDaemon;
+    }
+
+    /**
+     * Start up the progress meter, printing initialization message and starting up the
+     * daemon thread for periodic printing.
+     */
+    @Requires("progressMeterDaemon != null")
+    public synchronized void start() {
+        timer.start();
+        lastProgressPrintTime = timer.currentTime();
+        final String formatString = String.format("%%15s | %%%1$ds | %%7s | %%%1$ds | %%9s | %%7s | %%9s", processingUnitWidth);
+
+        logger.info("[INITIALIZATION COMPLETE; STARTING PROCESSING]");
+        logger.info(String.format(formatString, "", "processed", "time", "per 1M", "", "total", "remaining"));
+        logger.info(String.format(formatString, "Location", processingUnitName, "elapsed", processingUnitName,
+                "completed", "runtime", "runtime"));
+
+        progressMeterDaemon.start();
+    }
+
+    /**
+     * @return the current runtime in nanoseconds
+     */
+    @Ensures("result >= 0")
+    public long getRuntimeInNanoseconds() {
+        return timer.getElapsedTimeNano();
+    }
+
+    /**
+     * This function is just like getRuntimeInNanoseconds but it doesn't actually query the
+     * system timer to determine the value, but rather uses a local variable in this meter
+     * that is updated by the daemon thread.  This means that the result is ridiculously imprecise
+     * for a nanosecond value (as it's only updated each pollingFrequency of the daemon) but
+     * it is free for clients to access, which can be critical when one wants to do tests like:
+     *
+     * for some work unit:
+     *   do unit if getRuntimeInNanosecondsUpdatedPeriodically < X
+     *
+     * and have this operation eventually timeout but don't want to pay the system call time to
+     * ensure that the loop exits as soon as the elapsed time exceeds X
+     *
+     * @return the current runtime in nanoseconds
+     */
+    @Ensures("result >= 0")
+    public long getRuntimeInNanosecondsUpdatedPeriodically() {
+        return elapsedTimeInNanosecondUpdatedByDaemon;
+    }
+
+    /**
+     * Update the period runtime variable to the current runtime in nanoseconds.  Should only
+     * be called by the daemon thread
+     */
+    protected void updateElapsedTimeInNanoseconds() {
+        elapsedTimeInNanosecondUpdatedByDaemon = getRuntimeInNanoseconds();
+    }
+
+
+
+    /**
+     * Utility routine that prints out process information (including timing) every N records or
+     * every M seconds, for N and M set in global variables.
+     *
+     * Synchronized to ensure that even with multiple threads calling notifyOfProgress we still
+     * get one clean stream of meter logs.
+     *
+     * Note this thread doesn't actually print progress, unless must print is true, but just registers
+     * the progress itself.  A separate printing daemon periodically polls the meter to print out
+     * progress
+     *
+     * @param loc Current location, can be null if you are at the end of the processing unit.  Must
+     *            have size == 1 (cannot be multiple bases in size).
+     * @param nTotalRecordsProcessed the total number of records we've processed
+     */
+    public synchronized void notifyOfProgress(final GenomeLoc loc, final long nTotalRecordsProcessed) {
+        if ( nTotalRecordsProcessed < 0 ) throw new IllegalArgumentException("nTotalRecordsProcessed must be >= 0");
+        if ( loc.size() != 1 ) throw new IllegalArgumentException("GenomeLoc must have size == 1 but got " + loc);
+
+        // weird comparison to ensure that loc == null (in unmapped reads) is keep before maxGenomeLoc == null (on startup)
+        this.maxGenomeLoc = loc == null ? loc : (maxGenomeLoc == null ? loc : loc.max(maxGenomeLoc));
+        this.nTotalRecordsProcessed = Math.max(this.nTotalRecordsProcessed, nTotalRecordsProcessed);
+
+        // a pretty name for our position
+        this.position = maxGenomeLoc == null ? new Position(PositionStatus.IN_UNMAPPED_READS) : new Position(maxGenomeLoc);
+    }
+
+    /**
+     * Describes the status of this position marker, such as starting up, done, in the unmapped reads,
+     * or somewhere on the genome
+     */
+    private enum PositionStatus {
+        STARTING("Starting"),
+        DONE("done"),
+        IN_UNMAPPED_READS("unmapped reads"),
+        ON_GENOME(null);
+
+        public final String message;
+
+        private PositionStatus(String message) {
+            this.message = message;
+        }
+    }
+
+    /**
+     * A pair of position status and the genome loc, if necessary.  Used to get a
+     * status update message as needed, without the computational cost of formatting
+     * the genome loc string every time a progress notification happens (which is almost
+     * always not printed)
+     */
+    private class Position {
+        final PositionStatus type;
+        final GenomeLoc maybeLoc;
+
+        /**
+         * Create a position object of any type != ON_GENOME
+         * @param type
+         */
+        @Requires({"type != null", "type != PositionStatus.ON_GENOME"})
+        private Position(PositionStatus type) {
+            this.type = type;
+            this.maybeLoc = null;
+        }
+
+        /**
+         * Create a position object of type ON_GENOME at genomeloc loc
+         * @param loc
+         */
+        @Requires("loc != null")
+        private Position(GenomeLoc loc) {
+            this.type = PositionStatus.ON_GENOME;
+            this.maybeLoc = loc;
+        }
+
+        /**
+         * @return a human-readable representation of this position
+         */
+        private String getMessage() {
+            if ( type == PositionStatus.ON_GENOME )
+                return maxGenomeLoc.getContig() + ":" + maxGenomeLoc.getStart();
+            else
+                return type.message;
+        }
+    }
+
+    /**
+     * Actually try to print out progress
+     *
+     * This function may print out if the progress print is due, but if not enough time has elapsed
+     * since the last print we will not print out information.
+     *
+     * @param mustPrint if true, progress will be printed regardless of the last time we printed progress
+     */
+    protected synchronized void printProgress(final boolean mustPrint) {
+        final long curTime = timer.currentTime();
+        final boolean printProgress = mustPrint || maxElapsedIntervalForPrinting(curTime, lastProgressPrintTime, progressPrintFrequency);
+        final boolean printLog = performanceLog != null && maxElapsedIntervalForPrinting(curTime, lastPerformanceLogPrintTime, PERFORMANCE_LOG_PRINT_FREQUENCY);
+
+        if ( printProgress || printLog ) {
+            final ProgressMeterData progressData = takeProgressSnapshot(maxGenomeLoc, nTotalRecordsProcessed);
+
+            final AutoFormattingTime elapsed = new AutoFormattingTime(progressData.getElapsedSeconds(), 5, 1);
+            final AutoFormattingTime bpRate = new AutoFormattingTime(progressData.secondsPerMillionBP());
+            final AutoFormattingTime unitRate = new AutoFormattingTime(progressData.secondsPerMillionElements());
+            final double fractionGenomeTargetCompleted = progressData.calculateFractionGenomeTargetCompleted(targetSizeInBP);
+            final AutoFormattingTime estTotalRuntime = new AutoFormattingTime(elapsed.getTimeInSeconds() / fractionGenomeTargetCompleted, 5, 1);
+            final AutoFormattingTime timeToCompletion = new AutoFormattingTime(estTotalRuntime.getTimeInSeconds() - elapsed.getTimeInSeconds());
+
+            if ( printProgress ) {
+                lastProgressPrintTime = curTime;
+                updateLoggerPrintFrequency(estTotalRuntime.getTimeInSeconds());
+
+                logger.info(String.format(progressFormatString,
+                        position.getMessage(), progressData.getUnitsProcessed()*1.0, elapsed, unitRate,
+                        100*fractionGenomeTargetCompleted, estTotalRuntime, timeToCompletion));
+
+            }
+
+            if ( printLog ) {
+                lastPerformanceLogPrintTime = curTime;
+                performanceLog.printf("%.2f\t%d\t%.2e\t%d\t%.2e\t%.2e\t%.2f\t%.2f%n",
+                        elapsed.getTimeInSeconds(), progressData.getUnitsProcessed(), unitRate.getTimeInSeconds(),
+                        progressData.getBpProcessed(), bpRate.getTimeInSeconds(),
+                        fractionGenomeTargetCompleted, estTotalRuntime.getTimeInSeconds(),
+                        timeToCompletion.getTimeInSeconds());
+            }
+        }
+    }
+
+    /**
+     * Determine, based on remaining runtime, how often to print the meter
+     *
+     * @param totalRuntimeSeconds kinda obvious, no?
+     */
+    private void updateLoggerPrintFrequency(final double totalRuntimeSeconds) {
+        // dynamically change the update rate so that short running jobs receive frequent updates while longer jobs receive fewer updates
+        if ( totalRuntimeSeconds > TWELVE_HOURS_IN_SECONDS )
+            progressPrintFrequency = 60 * 1000; // in milliseconds
+        else if ( totalRuntimeSeconds > TWO_HOURS_IN_SECONDS )
+            progressPrintFrequency = 30 * 1000; // in milliseconds
+        else
+            progressPrintFrequency = 10 * 1000; // in milliseconds
+    }
+
+    /**
+     * Creates a new ProgressData object recording a snapshot of our progress at this instant
+     *
+     * @param loc our current position.  If null, assumes we are done traversing
+     * @param nTotalRecordsProcessed the total number of records we've processed
+     * @return
+     */
+    private ProgressMeterData takeProgressSnapshot(final GenomeLoc loc, final long nTotalRecordsProcessed) {
+        // null -> end of processing
+        final long bpProcessed = loc == null ? targetSizeInBP : regionsBeingProcessed.sizeBeforeLoc(loc);
+        return new ProgressMeterData(timer.getElapsedTime(), nTotalRecordsProcessed, bpProcessed);
+    }
+
+    /**
+     * Should be called when processing is done
+     */
+    public void notifyDone(final long nTotalRecordsProcessed) {
+        // print out the progress meter
+        this.nTotalRecordsProcessed = nTotalRecordsProcessed;
+        this.position = new Position(PositionStatus.DONE);
+        printProgress(true);
+
+        logger.info(String.format("Total runtime %.2f secs, %.2f min, %.2f hours",
+                timer.getElapsedTime(), timer.getElapsedTime() / 60, timer.getElapsedTime() / 3600));
+
+        if ( performanceLog != null )
+            performanceLog.close();
+
+        // shutdown our daemon thread
+        progressMeterDaemon.done();
+    }
+
+    /**
+     * @param curTime (current runtime, in millisecs)
+     * @param lastPrintTime the last time we printed, in machine milliseconds
+     * @param printFreq maximum permitted difference between last print and current times
+     *
+     * @return true if the maximum interval (in millisecs) has passed since the last printing
+     */
+    private boolean maxElapsedIntervalForPrinting(final long curTime, long lastPrintTime, long printFreq) {
+        final long elapsed = curTime - lastPrintTime;
+        return elapsed > printFreq && elapsed > MIN_ELAPSED_TIME_BEFORE_FIRST_PROGRESS;
+    }
+}
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/progressmeter/ProgressMeterDaemon.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/progressmeter/ProgressMeterDaemon.java
new file mode 100644
index 0000000..f1f48e6
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/progressmeter/ProgressMeterDaemon.java
@@ -0,0 +1,111 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.utils.progressmeter;
+
+/**
+ * Daemon thread that periodically prints the progress of the progress meter
+ *
+ * User: depristo
+ * Date: 12/4/12
+ * Time: 9:16 PM
+ */
+public final class ProgressMeterDaemon extends Thread {
+    public final static long DEFAULT_POLL_FREQUENCY_MILLISECONDS = 10 * 1000;
+
+    /**
+     * How frequently should we poll and print progress?
+     */
+    private final long pollFrequencyMilliseconds;
+
+    /**
+     * How long are we waiting between print progress calls are issued?
+     * @return the time in milliseconds between progress meter calls
+     */
+    private long getPollFrequencyMilliseconds() {
+        return pollFrequencyMilliseconds;
+    }
+
+    /**
+     * Are we to continue periodically printing status, or should we shut down?
+     */
+    boolean done = false;
+
+    /**
+     * The meter we will call print on
+     */
+    final ProgressMeter meter;
+
+    /**
+     * Create a new ProgressMeterDaemon printing progress for meter
+     * @param meter the progress meter to print progress of
+     */
+    public ProgressMeterDaemon(final ProgressMeter meter, final long pollFrequencyMilliseconds) {
+        if ( meter == null ) throw new IllegalArgumentException("meter cannot be null");
+        if ( pollFrequencyMilliseconds <= 0 ) throw new IllegalArgumentException("pollFrequencyMilliseconds must be greater than 0 but got " + pollFrequencyMilliseconds);
+
+        this.meter = meter;
+        this.pollFrequencyMilliseconds = pollFrequencyMilliseconds;
+        setDaemon(true);
+        setName("ProgressMeterDaemon");
+    }
+
+    public ProgressMeterDaemon(final ProgressMeter meter) {
+        this(meter, DEFAULT_POLL_FREQUENCY_MILLISECONDS);
+    }
+
+    /**
+     * Tells this daemon thread to shutdown at the next opportunity, as the progress
+     * metering is complete.
+     */
+    public final void done() {
+        this.done = true;
+    }
+
+    /**
+     * Is this daemon thread done?
+     * @return true if done, false otherwise
+     */
+    public boolean isDone() {
+        return done;
+    }
+
+    /**
+     * Start up the ProgressMeterDaemon, polling every tens of seconds to print, if
+     * necessary, the provided progress meter.  Never exits until the JVM is complete,
+     * or done() is called, as the thread is a daemon thread
+     */
+    public void run() {
+        while (! done) {
+            meter.printProgress(false);
+            meter.updateElapsedTimeInNanoseconds();
+            try {
+                Thread.sleep(getPollFrequencyMilliseconds());
+            } catch (InterruptedException e) {
+                throw new RuntimeException(e);
+            }
+        }
+    }
+}
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/progressmeter/ProgressMeterData.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/progressmeter/ProgressMeterData.java
new file mode 100644
index 0000000..6804032
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/progressmeter/ProgressMeterData.java
@@ -0,0 +1,79 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.utils.progressmeter;
+
+import com.google.java.contract.Ensures;
+import com.google.java.contract.Requires;
+
+/**
+ * a snapshot of our performance, suitable for storage and later analysis
+ */
+class ProgressMeterData {
+    private final double elapsedSeconds;
+    private final long unitsProcessed;
+    private final long bpProcessed;
+
+    @Requires({"unitsProcessed >= 0", "bpProcessed >= 0", "elapsedSeconds >= 0"})
+    public ProgressMeterData(double elapsedSeconds, long unitsProcessed, long bpProcessed) {
+        this.elapsedSeconds = elapsedSeconds;
+        this.unitsProcessed = unitsProcessed;
+        this.bpProcessed = bpProcessed;
+    }
+
+    @Ensures("result >= 0.0")
+    public double getElapsedSeconds() {
+        return elapsedSeconds;
+    }
+
+    @Ensures("result >= 0")
+    public long getUnitsProcessed() {
+        return unitsProcessed;
+    }
+
+    @Ensures("result >= 0")
+    public long getBpProcessed() {
+        return bpProcessed;
+    }
+
+    /** How long in seconds to process 1M traversal units? */
+    @Ensures("result >= 0.0")
+    public double secondsPerMillionElements() {
+        return (elapsedSeconds * 1000000.0) / Math.max(unitsProcessed, 1);
+    }
+
+    /** How long in seconds to process 1M bp on the genome? */
+    @Ensures("result >= 0.0")
+    public double secondsPerMillionBP() {
+        return (elapsedSeconds * 1000000.0) / Math.max(bpProcessed, 1);
+    }
+
+    /** What fraction of the target intervals have we covered? */
+    @Requires("targetSize >= 0")
+    @Ensures({"result >= 0.0", "result <= 1.0"})
+    public double calculateFractionGenomeTargetCompleted(final long targetSize) {
+        return (1.0*bpProcessed) / Math.max(targetSize, 1);
+    }
+}
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/recalibration/BQSRArgumentSet.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/recalibration/BQSRArgumentSet.java
new file mode 100644
index 0000000..cc41bc5
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/recalibration/BQSRArgumentSet.java
@@ -0,0 +1,85 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.utils.recalibration;
+
+import org.broadinstitute.gatk.engine.arguments.GATKArgumentCollection;
+
+import java.io.File;
+
+public class BQSRArgumentSet {
+    // declare public, STL-style for easier and more efficient access:
+    private File BQSR_RECAL_FILE;
+    private int quantizationLevels;
+    private boolean disableIndelQuals;
+    private boolean emitOriginalQuals;
+    private int PRESERVE_QSCORES_LESS_THAN;
+    private double globalQScorePrior;
+
+    public BQSRArgumentSet(final GATKArgumentCollection args) {
+        this.BQSR_RECAL_FILE = args.BQSR_RECAL_FILE;
+        this.quantizationLevels = args.quantizationLevels;
+        this.disableIndelQuals = args.disableIndelQuals;
+        this.emitOriginalQuals = args.emitOriginalQuals;
+        this.PRESERVE_QSCORES_LESS_THAN = args.PRESERVE_QSCORES_LESS_THAN;
+        this.globalQScorePrior = args.globalQScorePrior;
+    }
+
+    public File getRecalFile() { return BQSR_RECAL_FILE; }
+
+    public int getQuantizationLevels() { return quantizationLevels; }
+
+    public boolean shouldDisableIndelQuals() { return disableIndelQuals; }
+
+    public boolean shouldEmitOriginalQuals() { return emitOriginalQuals; }
+
+    public int getPreserveQscoresLessThan() { return PRESERVE_QSCORES_LESS_THAN; }
+
+    public double getGlobalQScorePrior() { return globalQScorePrior; }
+
+    public void setRecalFile(final File BQSR_RECAL_FILE) {
+        this.BQSR_RECAL_FILE = BQSR_RECAL_FILE;
+    }
+
+    public void setQuantizationLevels(final int quantizationLevels) {
+        this.quantizationLevels = quantizationLevels;
+    }
+
+    public void setDisableIndelQuals(final boolean disableIndelQuals) {
+        this.disableIndelQuals = disableIndelQuals;
+    }
+
+    public void setEmitOriginalQuals(final boolean emitOriginalQuals) {
+        this.emitOriginalQuals = emitOriginalQuals;
+    }
+
+    public void setPreserveQscoresLessThan(final int PRESERVE_QSCORES_LESS_THAN) {
+        this.PRESERVE_QSCORES_LESS_THAN = PRESERVE_QSCORES_LESS_THAN;
+    }
+
+    public void setGlobalQScorePrior(final double globalQScorePrior) {
+        this.globalQScorePrior = globalQScorePrior;
+    }
+}
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/recalibration/BQSRMode.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/recalibration/BQSRMode.java
new file mode 100644
index 0000000..a742ed4
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/recalibration/BQSRMode.java
@@ -0,0 +1,55 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.utils.recalibration;
+
+import org.broadinstitute.gatk.engine.iterators.ReadTransformer;
+
+import java.lang.annotation.*;
+
+/**
+ * User: hanna
+ * Date: May 14, 2009
+ * Time: 1:51:22 PM
+ * BROAD INSTITUTE SOFTWARE COPYRIGHT NOTICE AND AGREEMENT
+ * Software and documentation are copyright 2005 by the Broad Institute.
+ * All rights are reserved.
+ *
+ * Users acknowledge that this software is supplied without any warranty or support.
+ * The Broad Institute is not responsible for its use, misuse, or
+ * functionality.
+ */
+
+/**
+ * Allows the walker to indicate what type of data it wants to consume.
+ */
+
+ at Documented
+ at Inherited
+ at Retention(RetentionPolicy.RUNTIME)
+ at Target(ElementType.TYPE)
+public @interface BQSRMode {
+    public abstract ReadTransformer.ApplicationTime ApplicationTime() default ReadTransformer.ApplicationTime.ON_INPUT;
+}
\ No newline at end of file
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/recalibration/EventType.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/recalibration/EventType.java
new file mode 100644
index 0000000..84ab785
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/recalibration/EventType.java
@@ -0,0 +1,72 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.utils.recalibration;
+
+public enum EventType {
+    BASE_SUBSTITUTION("M", "Base Substitution"),
+    BASE_INSERTION("I", "Base Insertion"),
+    BASE_DELETION("D", "Base Deletion");
+
+    private final String representation;
+    private final String longRepresentation;
+
+    private EventType(String representation, String longRepresentation) {
+        this.representation = representation;
+        this.longRepresentation = longRepresentation;
+    }
+
+    /**
+     * Get the EventType corresponding to its ordinal index
+     * @param index an ordinal index
+     * @return the event type corresponding to ordinal index
+     */
+    public static EventType eventFrom(int index) {
+        return EventType.values()[index];
+    }
+
+    /**
+     * Get the EventType with short string representation
+     * @throws IllegalArgumentException if representation doesn't correspond to one of EventType
+     * @param representation short string representation of the event
+     * @return an EventType
+     */
+    public static EventType eventFrom(String representation) {
+        for (EventType eventType : EventType.values())
+            if (eventType.representation.equals(representation))
+                return eventType;
+
+        throw new IllegalArgumentException(String.format("Event %s does not exist.", representation));
+    }
+
+    @Override
+    public String toString() {
+        return representation;
+    }
+
+    public String prettyPrint() {
+        return longRepresentation;
+    }
+}
\ No newline at end of file
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/runtime/CapturedStreamOutput.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/runtime/CapturedStreamOutput.java
new file mode 100644
index 0000000..0166e98
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/runtime/CapturedStreamOutput.java
@@ -0,0 +1,134 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.utils.runtime;
+
+import org.apache.commons.io.IOUtils;
+import org.apache.commons.io.output.NullOutputStream;
+import org.broadinstitute.gatk.utils.exceptions.ReviewedGATKException;
+import org.broadinstitute.gatk.utils.exceptions.UserException;
+import org.broadinstitute.gatk.utils.io.HardThresholdingOutputStream;
+
+import java.io.*;
+import java.util.EnumMap;
+
+/**
+ * Stream output captured from a stream.
+ */
+public class CapturedStreamOutput extends StreamOutput {
+    private final InputStream processStream;
+    private final EnumMap<StreamLocation, OutputStream> outputStreams = new EnumMap<StreamLocation, OutputStream>(StreamLocation.class);
+
+    /**
+     * The byte stream to capture content or null if no output string content was requested.
+     */
+    private final ByteArrayOutputStream bufferStream;
+
+    /**
+     * True if the buffer is truncated.
+     */
+    private boolean bufferTruncated = false;
+
+    /**
+     * @param settings       Settings that define what to capture.
+     * @param processStream  Stream to capture output.
+     * @param standardStream Stream to write debug output.
+     */
+    public CapturedStreamOutput(OutputStreamSettings settings, InputStream processStream, PrintStream standardStream) {
+        this.processStream = processStream;
+        int bufferSize = settings.getBufferSize();
+        this.bufferStream = (bufferSize < 0) ? new ByteArrayOutputStream() : new ByteArrayOutputStream(bufferSize);
+
+        for (StreamLocation location : settings.getStreamLocations()) {
+            OutputStream outputStream;
+            switch (location) {
+                case Buffer:
+                    if (bufferSize < 0) {
+                        outputStream = this.bufferStream;
+                    } else {
+                        outputStream = new HardThresholdingOutputStream(bufferSize) {
+                            @Override
+                            protected OutputStream getStream() throws IOException {
+                                return bufferTruncated ? NullOutputStream.NULL_OUTPUT_STREAM : bufferStream;
+                            }
+
+                            @Override
+                            protected void thresholdReached() throws IOException {
+                                bufferTruncated = true;
+                            }
+                        };
+                    }
+                    break;
+                case File:
+                    try {
+                        outputStream = new FileOutputStream(settings.getOutputFile(), settings.isAppendFile());
+                    } catch (IOException e) {
+                        throw new UserException.BadInput(e.getMessage());
+                    }
+                    break;
+                case Standard:
+                    outputStream = standardStream;
+                    break;
+                default:
+                    throw new ReviewedGATKException("Unexpected stream location: " + location);
+            }
+            this.outputStreams.put(location, outputStream);
+        }
+    }
+
+    @Override
+    public byte[] getBufferBytes() {
+        return bufferStream.toByteArray();
+    }
+
+    @Override
+    public boolean isBufferTruncated() {
+        return bufferTruncated;
+    }
+
+    /**
+     * Drain the input stream to keep the process from backing up until it's empty.
+     * File streams will be closed automatically when this method returns.
+     *
+     * @throws java.io.IOException When unable to read or write.
+     */
+    public void readAndClose() throws IOException {
+        try {
+            byte[] buf = new byte[4096];
+            int readCount;
+            while ((readCount = processStream.read(buf)) >= 0)
+                for (OutputStream outputStream : this.outputStreams.values()) {
+                    outputStream.write(buf, 0, readCount);
+                }
+        } finally {
+            for (StreamLocation location : this.outputStreams.keySet()) {
+                OutputStream outputStream = this.outputStreams.get(location);
+                outputStream.flush();
+                if (location != StreamLocation.Standard)
+                    IOUtils.closeQuietly(outputStream);
+            }
+        }
+    }
+}
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/runtime/InputStreamSettings.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/runtime/InputStreamSettings.java
new file mode 100644
index 0000000..56bfabd
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/runtime/InputStreamSettings.java
@@ -0,0 +1,116 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.utils.runtime;
+
+import java.io.File;
+import java.util.Collections;
+import java.util.EnumSet;
+import java.util.Set;
+
+/**
+ * Settings that define text to write to the process stdin.
+ */
+public class InputStreamSettings {
+    private final EnumSet<StreamLocation> streamLocations = EnumSet.noneOf(StreamLocation.class);
+    private byte[] inputBuffer;
+    private File inputFile;
+
+    public InputStreamSettings() {
+    }
+
+    /**
+     * @param inputBuffer String to write to stdin.
+     */
+    public InputStreamSettings(String inputBuffer) {
+        setInputBuffer(inputBuffer);
+    }
+
+    /**
+     * @param inputFile File to write to stdin.
+     */
+    public InputStreamSettings(File inputFile) {
+        setInputFile(inputFile);
+    }
+
+    /**
+     * @param inputBuffer String to write to stdin.
+     * @param inputFile   File to write to stdin.
+     */
+    public InputStreamSettings(byte[] inputBuffer, File inputFile) {
+        setInputBuffer(inputBuffer);
+        setInputFile(inputFile);
+    }
+
+    public Set<StreamLocation> getStreamLocations() {
+        return Collections.unmodifiableSet(streamLocations);
+    }
+
+    public byte[] getInputBuffer() {
+        return inputBuffer;
+    }
+
+    public void setInputBuffer(String inputBuffer) {
+        if (inputBuffer == null)
+            throw new IllegalArgumentException("inputBuffer cannot be null");
+        this.streamLocations.add(StreamLocation.Buffer);
+        this.inputBuffer = inputBuffer.getBytes();
+    }
+
+    public void setInputBuffer(byte[] inputBuffer) {
+        if (inputBuffer == null)
+            throw new IllegalArgumentException("inputBuffer cannot be null");
+        this.streamLocations.add(StreamLocation.Buffer);
+        this.inputBuffer = inputBuffer;
+    }
+
+    public void clearInputBuffer() {
+        this.streamLocations.remove(StreamLocation.Buffer);
+        this.inputBuffer = null;
+    }
+
+    public File getInputFile() {
+        return inputFile;
+    }
+
+    public void setInputFile(File inputFile) {
+        if (inputFile == null)
+            throw new IllegalArgumentException("inputFile cannot be null");
+        this.streamLocations.add(StreamLocation.File);
+        this.inputFile = inputFile;
+    }
+
+    public void clearInputFile() {
+        this.streamLocations.remove(StreamLocation.File);
+        this.inputFile = null;
+    }
+
+    public void setInputStandard(boolean inputStandard) {
+        if (inputStandard)
+            this.streamLocations.add(StreamLocation.Standard);
+        else
+            this.streamLocations.remove(StreamLocation.Standard);
+    }
+}
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/runtime/OutputStreamSettings.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/runtime/OutputStreamSettings.java
new file mode 100644
index 0000000..bc92291
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/runtime/OutputStreamSettings.java
@@ -0,0 +1,127 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.utils.runtime;
+
+import java.io.File;
+import java.util.Collections;
+import java.util.EnumSet;
+import java.util.Set;
+
+/**
+ * Settings that define text to capture from a process stream.
+ */
+public class OutputStreamSettings {
+    private final EnumSet<StreamLocation> streamLocations = EnumSet.noneOf(StreamLocation.class);
+    private int bufferSize;
+    private File outputFile;
+    private boolean appendFile;
+
+    public OutputStreamSettings() {
+    }
+
+    /**
+     * @param bufferSize The number of bytes to capture, or -1 for unlimited.
+     */
+    public OutputStreamSettings(int bufferSize) {
+        setBufferSize(bufferSize);
+    }
+
+    /**
+     * @param outputFile The file to write output to.
+     */
+    public OutputStreamSettings(File outputFile) {
+        setOutputFile(outputFile);
+    }
+
+    /**
+     * @param outputFile The file to write output to.
+     * @param append     true if the output file should be appended to.
+     */
+    public OutputStreamSettings(File outputFile, boolean append) {
+        setOutputFile(outputFile, append);
+    }
+
+    public OutputStreamSettings(int bufferSize, File outputFile, boolean appendFile) {
+        setBufferSize(bufferSize);
+        setOutputFile(outputFile, appendFile);
+    }
+
+    public Set<StreamLocation> getStreamLocations() {
+        return Collections.unmodifiableSet(streamLocations);
+    }
+
+    public int getBufferSize() {
+        return bufferSize;
+    }
+
+    public void setBufferSize(int bufferSize) {
+        this.streamLocations.add(StreamLocation.Buffer);
+        this.bufferSize = bufferSize;
+    }
+
+    public void clearBufferSize() {
+        this.streamLocations.remove(StreamLocation.Buffer);
+        this.bufferSize = 0;
+    }
+
+    public File getOutputFile() {
+        return outputFile;
+    }
+
+    public boolean isAppendFile() {
+        return appendFile;
+    }
+
+    /**
+     * Overwrites the outputFile with the process output.
+     *
+     * @param outputFile File to overwrite.
+     */
+    public void setOutputFile(File outputFile) {
+        setOutputFile(outputFile, false);
+    }
+
+    public void setOutputFile(File outputFile, boolean append) {
+        if (outputFile == null)
+            throw new IllegalArgumentException("outputFile cannot be null");
+        streamLocations.add(StreamLocation.File);
+        this.outputFile = outputFile;
+        this.appendFile = append;
+    }
+
+    public void clearOutputFile() {
+        streamLocations.remove(StreamLocation.File);
+        this.outputFile = null;
+        this.appendFile = false;
+    }
+
+    public void printStandard(boolean print) {
+        if (print)
+            this.streamLocations.add(StreamLocation.Standard);
+        else
+            this.streamLocations.remove(StreamLocation.Standard);
+    }
+}
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/runtime/ProcessController.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/runtime/ProcessController.java
new file mode 100644
index 0000000..3955817
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/runtime/ProcessController.java
@@ -0,0 +1,387 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.utils.runtime;
+
+import org.apache.commons.io.FileUtils;
+import org.apache.commons.io.IOUtils;
+import org.apache.commons.lang.StringUtils;
+import org.apache.log4j.Logger;
+import org.broadinstitute.gatk.utils.Utils;
+import org.broadinstitute.gatk.utils.exceptions.ReviewedGATKException;
+import org.broadinstitute.gatk.utils.exceptions.UserException;
+
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.util.*;
+
+/**
+ * Facade to Runtime.exec() and java.lang.Process.  Handles
+ * running a process to completion and returns stdout and stderr
+ * as strings.  Creates separate threads for reading stdout and stderr,
+ * then reuses those threads for each process most efficient use is
+ * to create one of these and use it repeatedly.  Instances are not
+ * thread-safe, however.
+ *
+ * TODO: java.io sometimes zombies the backround threads locking up on read().
+ * Supposedly NIO has better ways of interrupting a blocked stream but will
+ * require a little bit of refactoring.
+ *
+ * @author Michael Koehrsen
+ * @author Khalid Shakir
+ */
+public class ProcessController {
+    private static Logger logger = Logger.getLogger(ProcessController.class);
+
+    private static enum ProcessStream {Stdout, Stderr}
+
+    // Tracks running processes.
+    private static final Set<ProcessController> running = Collections.synchronizedSet(new HashSet<ProcessController>());
+
+    // Tracks this running process.
+    private Process process;
+
+    // Threads that capture stdout and stderr
+    private final OutputCapture stdoutCapture;
+    private final OutputCapture stderrCapture;
+
+    // When a caller destroyes a controller a new thread local version will be created
+    private boolean destroyed = false;
+
+    // Communication channels with output capture threads
+
+    // Holds the stdout and stderr sent to the background capture threads
+    private final Map<ProcessStream, CapturedStreamOutput> toCapture =
+            new EnumMap<ProcessStream, CapturedStreamOutput>(ProcessStream.class);
+
+    // Holds the results of the capture from the background capture threads.
+    // May be the content via toCapture or an StreamOutput.EMPTY if the capture was interrupted.
+    private final Map<ProcessStream, StreamOutput> fromCapture =
+            new EnumMap<ProcessStream, StreamOutput>(ProcessStream.class);
+
+    // Useful for debugging if background threads have shut down correctly
+    private static int nextControllerId = 0;
+    private final int controllerId;
+
+    public ProcessController() {
+        // Start the background threads for this controller.
+        synchronized (running) {
+            controllerId = nextControllerId++;
+        }
+        stdoutCapture = new OutputCapture(ProcessStream.Stdout, controllerId);
+        stderrCapture = new OutputCapture(ProcessStream.Stderr, controllerId);
+        stdoutCapture.start();
+        stderrCapture.start();
+    }
+
+    /**
+     * Returns a thread local ProcessController.
+     * Should NOT be closed when finished so it can be reused by the thread.
+     *
+     * @return a thread local ProcessController.
+     */
+    public static ProcessController getThreadLocal() {
+        // If the local controller was destroyed get a fresh instance.
+        if (threadProcessController.get().destroyed)
+            threadProcessController.remove();
+        return threadProcessController.get();
+    }
+
+    /**
+     * Thread local process controller container.
+     */
+    private static final ThreadLocal<ProcessController> threadProcessController =
+            new ThreadLocal<ProcessController>() {
+                @Override
+                protected ProcessController initialValue() {
+                    return new ProcessController();
+                }
+            };
+
+    /**
+     * Similar to Runtime.exec() but drains the output and error streams.
+     *
+     * @param command Command to run.
+     * @return The result code.
+     */
+    public static int exec(String[] command) {
+        ProcessController controller = ProcessController.getThreadLocal();
+        return controller.exec(new ProcessSettings(command)).getExitValue();
+    }
+
+    /**
+     * Executes a command line program with the settings and waits for it to return,
+     * processing the output on a background thread.
+     *
+     * @param settings Settings to be run.
+     * @return The output of the command.
+     */
+    public ProcessOutput exec(ProcessSettings settings) {
+        if (destroyed)
+            throw new IllegalStateException("This controller was destroyed");
+
+        ProcessBuilder builder = new ProcessBuilder(settings.getCommand());
+        builder.directory(settings.getDirectory());
+
+        Map<String, String> settingsEnvironment = settings.getEnvironment();
+        if (settingsEnvironment != null) {
+            Map<String, String> builderEnvironment = builder.environment();
+            builderEnvironment.clear();
+            builderEnvironment.putAll(settingsEnvironment);
+        }
+
+        builder.redirectErrorStream(settings.isRedirectErrorStream());
+
+        StreamOutput stdout = null;
+        StreamOutput stderr = null;
+
+        // Start the process running.
+
+        try {
+            synchronized (toCapture) {
+                process = builder.start();
+            }
+            running.add(this);
+        } catch (IOException e) {
+            String message = String.format("Unable to start command: %s\nReason: %s",
+                    StringUtils.join(builder.command(), " "),
+                    e.getMessage());
+            throw new ReviewedGATKException(message);
+        }
+
+        int exitCode;
+
+        try {
+            // Notify the background threads to start capturing.
+            synchronized (toCapture) {
+                toCapture.put(ProcessStream.Stdout,
+                        new CapturedStreamOutput(settings.getStdoutSettings(), process.getInputStream(), System.out));
+                toCapture.put(ProcessStream.Stderr,
+                        new CapturedStreamOutput(settings.getStderrSettings(), process.getErrorStream(), System.err));
+                toCapture.notifyAll();
+            }
+
+            // Write stdin content
+            InputStreamSettings stdinSettings = settings.getStdinSettings();
+            Set<StreamLocation> streamLocations = stdinSettings.getStreamLocations();
+            if (!streamLocations.isEmpty()) {
+                try {
+                    OutputStream stdinStream = process.getOutputStream();
+                    for (StreamLocation location : streamLocations) {
+                        InputStream inputStream;
+                        switch (location) {
+                            case Buffer:
+                                inputStream = new ByteArrayInputStream(stdinSettings.getInputBuffer());
+                                break;
+                            case File:
+                                try {
+                                    inputStream = FileUtils.openInputStream(stdinSettings.getInputFile());
+                                } catch (IOException e) {
+                                    throw new UserException.BadInput(e.getMessage());
+                                }
+                                break;
+                            case Standard:
+                                inputStream = System.in;
+                                break;
+                            default:
+                                throw new ReviewedGATKException("Unexpected stream location: " + location);
+                        }
+                        try {
+                            IOUtils.copy(inputStream, stdinStream);
+                        } finally {
+                            if (location != StreamLocation.Standard)
+                                IOUtils.closeQuietly(inputStream);
+                        }
+                    }
+                    stdinStream.flush();
+                } catch (IOException e) {
+                    throw new ReviewedGATKException("Error writing to stdin on command: " + StringUtils.join(builder.command(), " "), e);
+                }
+            }
+
+            // Wait for the process to complete.
+            try {
+                process.getOutputStream().close();
+                process.waitFor();
+            } catch (IOException e) {
+                throw new ReviewedGATKException("Unable to close stdin on command: " + StringUtils.join(builder.command(), " "), e);
+            } catch (InterruptedException e) {
+                throw new ReviewedGATKException("Process interrupted", e);
+            } finally {
+                while (!destroyed && stdout == null || stderr == null) {
+                    synchronized (fromCapture) {
+                        if (fromCapture.containsKey(ProcessStream.Stdout))
+                            stdout = fromCapture.remove(ProcessStream.Stdout);
+                        if (fromCapture.containsKey(ProcessStream.Stderr))
+                            stderr = fromCapture.remove(ProcessStream.Stderr);
+                        try {
+                            if (stdout == null || stderr == null)
+                                fromCapture.wait();
+                        } catch (InterruptedException e) {
+                            // Log the error, ignore the interrupt and wait patiently
+                            // for the OutputCaptures to (via finally) return their
+                            // stdout and stderr.
+                            logger.error(e);
+                        }
+                    }
+                }
+
+                if (destroyed) {
+                    if (stdout == null)
+                        stdout = StreamOutput.EMPTY;
+                    if (stderr == null)
+                        stderr = StreamOutput.EMPTY;
+                }
+            }
+        } finally {
+            synchronized (toCapture) {
+                exitCode = process.exitValue();
+                process = null;
+            }
+            running.remove(this);
+        }
+
+        return new ProcessOutput(exitCode, stdout, stderr);
+    }
+
+    /**
+     * Executes a command line program with the settings and waits for it to return,
+     * processing the output on a background thread.
+     *
+     * Throws an IOException if the ProcessOutput exit code is nonzero
+     *
+     * @param settings Settings to be run.
+     */
+    public ProcessOutput execAndCheck(ProcessSettings settings) throws IOException {
+        ProcessOutput po = exec(settings);
+        if (po.getExitValue() != 0) {
+            String message = String.format("Process exited with %d\nCommand Line: %s",
+                    po.getExitValue(),
+                    Utils.join(" ", settings.getCommand()));
+            throw new IOException(message);
+        }
+        return po;
+    }
+
+    /**
+     * @return The set of still running processes.
+     */
+    public static Set<ProcessController> getRunning() {
+        synchronized (running) {
+            return new HashSet<ProcessController>(running);
+        }
+    }
+
+    /**
+     * Stops the process from running and tries to ensure process is cleaned up properly.
+     * NOTE: sub-processes started by process may be zombied with their parents set to pid 1.
+     * NOTE: capture threads may block on read.
+     * TODO: Try to use NIO to interrupt streams.
+     */
+    public void tryDestroy() {
+        destroyed = true;
+        synchronized (toCapture) {
+            if (process != null) {
+                process.destroy();
+                IOUtils.closeQuietly(process.getInputStream());
+                IOUtils.closeQuietly(process.getErrorStream());
+            }
+            stdoutCapture.interrupt();
+            stderrCapture.interrupt();
+            toCapture.notifyAll();
+        }
+    }
+
+    @Override
+    protected void finalize() throws Throwable {
+        try {
+            tryDestroy();
+        } catch (Exception e) {
+            logger.error(e);
+        }
+        super.finalize();
+    }
+
+    private class OutputCapture extends Thread {
+        private final int controllerId;
+        private final ProcessStream key;
+
+        /**
+         * Reads in the output of a stream on a background thread to keep the output pipe from backing up and freezing the called process.
+         *
+         * @param key The stdout or stderr key for this output capture.
+         * @param controllerId Unique id of the controller.
+         */
+        public OutputCapture(ProcessStream key, int controllerId) {
+            super(String.format("OutputCapture-%d-%s-%s-%d", controllerId, key.name().toLowerCase(),
+                    Thread.currentThread().getName(), Thread.currentThread().getId()));
+            this.controllerId = controllerId;
+            this.key = key;
+            setDaemon(true);
+        }
+
+        /**
+         * Runs the capture.
+         */
+        @Override
+        public void run() {
+            while (!destroyed) {
+                StreamOutput processStream = StreamOutput.EMPTY;
+                try {
+                    // Wait for a new input stream to be passed from this process controller.
+                    CapturedStreamOutput capturedProcessStream = null;
+                    while (!destroyed && capturedProcessStream == null) {
+                        synchronized (toCapture) {
+                            if (toCapture.containsKey(key)) {
+                                capturedProcessStream = toCapture.remove(key);
+                            } else {
+                                toCapture.wait();
+                            }
+                        }
+                    }
+
+                    if (!destroyed) {
+                        // Read in the input stream
+                        processStream = capturedProcessStream;
+                        capturedProcessStream.readAndClose();
+                    }
+                } catch (InterruptedException e) {
+                    logger.info("OutputCapture interrupted, exiting");
+                    break;
+                } catch (IOException e) {
+                    logger.error("Error reading process output", e);
+                } finally {
+                    // Send the string back to the process controller.
+                    synchronized (fromCapture) {
+                        fromCapture.put(key, processStream);
+                        fromCapture.notify();
+                    }
+                }
+            }
+        }
+    }
+}
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/runtime/ProcessOutput.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/runtime/ProcessOutput.java
new file mode 100644
index 0000000..9276de7
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/runtime/ProcessOutput.java
@@ -0,0 +1,57 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.utils.runtime;
+
+public class ProcessOutput {
+    private final int exitValue;
+    private final StreamOutput stdout;
+    private final StreamOutput stderr;
+
+    /**
+     * The output of a process.
+     *
+     * @param exitValue The exit value.
+     * @param stdout    The capture of stdout as defined by the stdout OutputStreamSettings.
+     * @param stderr    The capture of stderr as defined by the stderr OutputStreamSettings.
+     */
+    public ProcessOutput(int exitValue, StreamOutput stdout, StreamOutput stderr) {
+        this.exitValue = exitValue;
+        this.stdout = stdout;
+        this.stderr = stderr;
+    }
+
+    public int getExitValue() {
+        return exitValue;
+    }
+
+    public StreamOutput getStdout() {
+        return stdout;
+    }
+
+    public StreamOutput getStderr() {
+        return stderr;
+    }
+}
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/runtime/ProcessSettings.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/runtime/ProcessSettings.java
new file mode 100644
index 0000000..7027b9d
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/runtime/ProcessSettings.java
@@ -0,0 +1,140 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.utils.runtime;
+
+
+import java.io.File;
+import java.util.Map;
+
+public class ProcessSettings {
+    private String[] command;
+    private Map<String, String> environment;
+    private File directory;
+    private boolean redirectErrorStream;
+    private InputStreamSettings stdinSettings;
+    private OutputStreamSettings stdoutSettings;
+    private OutputStreamSettings stderrSettings;
+
+    /**
+     * @param command Command line to run.
+     */
+    public ProcessSettings(String[] command) {
+        this(command, false, null, null, null, null, null);
+    }
+
+    /**
+     * @param command             Command line to run.
+     * @param redirectErrorStream true if stderr should be sent to stdout.
+     * @param environment         Environment settings to override System.getEnv, or null to use System.getEnv.
+     * @param directory           The directory to run the command in, or null to run in the current directory.
+     * @param stdinSettings       Settings for writing to the process stdin.
+     * @param stdoutSettings      Settings for capturing the process stdout.
+     * @param stderrSettings      Setting for capturing the process stderr.
+     */
+    public ProcessSettings(String[] command, boolean redirectErrorStream, File directory, Map<String, String> environment,
+                           InputStreamSettings stdinSettings, OutputStreamSettings stdoutSettings, OutputStreamSettings stderrSettings) {
+        this.command = checkCommand(command);
+        this.redirectErrorStream = redirectErrorStream;
+        this.directory = directory;
+        this.environment = environment;
+        this.stdinSettings = checkSettings(stdinSettings);
+        this.stdoutSettings = checkSettings(stdoutSettings);
+        this.stderrSettings = checkSettings(stderrSettings);
+    }
+
+    public String[] getCommand() {
+        return command;
+    }
+
+    public void setCommand(String[] command) {
+        this.command = checkCommand(command);
+    }
+
+    public boolean isRedirectErrorStream() {
+        return redirectErrorStream;
+    }
+
+    public void setRedirectErrorStream(boolean redirectErrorStream) {
+        this.redirectErrorStream = redirectErrorStream;
+    }
+
+    public File getDirectory() {
+        return directory;
+    }
+
+    public void setDirectory(File directory) {
+        this.directory = directory;
+    }
+
+    public Map<String, String> getEnvironment() {
+        return environment;
+    }
+
+    public void setEnvironment(Map<String, String> environment) {
+        this.environment = environment;
+    }
+
+    public InputStreamSettings getStdinSettings() {
+        return stdinSettings;
+    }
+
+    public void setStdinSettings(InputStreamSettings stdinSettings) {
+        this.stdinSettings = checkSettings(stdinSettings);
+    }
+
+    public OutputStreamSettings getStdoutSettings() {
+        return stdoutSettings;
+    }
+
+    public void setStdoutSettings(OutputStreamSettings stdoutSettings) {
+        this.stdoutSettings = checkSettings(stdoutSettings);
+    }
+
+    public OutputStreamSettings getStderrSettings() {
+        return stderrSettings;
+    }
+
+    public void setStderrSettings(OutputStreamSettings stderrSettings) {
+        this.stderrSettings = checkSettings(stderrSettings);
+    }
+
+    protected String[] checkCommand(String[] command) {
+        if (command == null)
+            throw new IllegalArgumentException("Command is not allowed to be null");
+        for (String s: command)
+            if (s == null)
+                throw new IllegalArgumentException("Command is not allowed to contain nulls");
+        return command;
+    }
+
+    protected InputStreamSettings checkSettings(InputStreamSettings settings) {
+        return settings == null ? new InputStreamSettings() : settings;
+    }
+
+    protected OutputStreamSettings checkSettings(OutputStreamSettings settings) {
+        return settings == null ? new OutputStreamSettings() : settings;
+    }
+}
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/runtime/RuntimeUtils.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/runtime/RuntimeUtils.java
new file mode 100644
index 0000000..7a982dd
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/runtime/RuntimeUtils.java
@@ -0,0 +1,77 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.utils.runtime;
+
+import org.apache.commons.lang.StringUtils;
+
+import java.io.File;
+import java.util.ArrayList;
+import java.util.List;
+
+public class RuntimeUtils {
+    public static final String[] PATHS;
+
+    static {
+        String path = System.getenv("PATH");
+        if (path == null)
+            path = System.getenv("path");
+        if (path == null) {
+            PATHS = new String[0];
+        } else {
+            PATHS = StringUtils.split(path, File.pathSeparatorChar);
+        }
+    }
+
+    /**
+     * Returns the path to an executable or null if it doesn't exist.
+     * @param executable Relative path
+     * @return The absolute file path.
+     */
+    public static File which(String executable) {
+        for (String path: PATHS) {
+            File file = new File(path, executable);
+            if (file.exists())
+                return file.getAbsoluteFile();
+        }
+        return null;
+    }
+
+    /**
+     * Return the current classpath as a list of absolute paths
+     * @return
+     */
+    public static List<String> getAbsoluteClassPaths() {
+        final String[] relativeClassPaths = System.getProperty("java.class.path").split(File.pathSeparator);
+        final List<String> absoluteClassPaths = new ArrayList<>(relativeClassPaths.length);
+        for (String classPath : relativeClassPaths) {
+            File cp = new File(classPath);
+            if (cp.exists())
+                absoluteClassPaths.add(cp.getAbsolutePath());
+        }
+
+        return absoluteClassPaths;
+    }
+}
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/runtime/StreamLocation.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/runtime/StreamLocation.java
new file mode 100644
index 0000000..37d66f0
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/runtime/StreamLocation.java
@@ -0,0 +1,33 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.utils.runtime;
+
+/**
+ * Where to read/write a stream
+ */
+public enum StreamLocation {
+    Buffer, File, Standard
+}
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/runtime/StreamOutput.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/runtime/StreamOutput.java
new file mode 100644
index 0000000..9ce039e
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/runtime/StreamOutput.java
@@ -0,0 +1,69 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.utils.runtime;
+
+/**
+ * The content of stdout or stderr.
+ */
+public abstract class StreamOutput {
+    /**
+     * Empty stream output when no output is captured due to an error.
+     */
+    public static final StreamOutput EMPTY = new StreamOutput() {
+        @Override
+        public byte[] getBufferBytes() {
+            return new byte[0];
+        }
+
+        @Override
+        public boolean isBufferTruncated() {
+            return false;
+        }
+    };
+
+    /**
+     * Returns the content as a string.
+     *
+     * @return The content as a string.
+     */
+    public String getBufferString() {
+        return new String(getBufferBytes());
+    }
+
+    /**
+     * Returns the content as a string.
+     *
+     * @return The content as a string.
+     */
+    public abstract byte[] getBufferBytes();
+
+    /**
+     * Returns true if the buffer was truncated.
+     *
+     * @return true if the buffer was truncated.
+     */
+    public abstract boolean isBufferTruncated();
+}
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/sam/AlignmentStartComparator.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/sam/AlignmentStartComparator.java
new file mode 100644
index 0000000..7e926d5
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/sam/AlignmentStartComparator.java
@@ -0,0 +1,50 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.utils.sam;
+
+import htsjdk.samtools.SAMRecord;
+
+import java.util.Comparator;
+
+/**
+ * Compares two SAMRecords only the basis on alignment start.  Note that
+ * comparisons are performed ONLY on the basis of alignment start; any
+ * two SAM records with the same alignment start will be considered equal.
+ *
+ * Unmapped alignments will all be considered equal.
+ *
+ * @author mhanna
+ * @version 0.1
+ */
+public class AlignmentStartComparator implements Comparator<SAMRecord> {
+    public int compare(SAMRecord lhs, SAMRecord rhs) {
+        if(!lhs.getReferenceIndex().equals(rhs.getReferenceIndex()))
+            return lhs.getReferenceIndex() - rhs.getReferenceIndex();
+
+        // Note: no integer overflow here because alignment starts are >= 0.
+        return lhs.getAlignmentStart() - rhs.getAlignmentStart();
+    }
+}
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/sam/AlignmentStartWithNoTiesComparator.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/sam/AlignmentStartWithNoTiesComparator.java
new file mode 100644
index 0000000..db3f458
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/sam/AlignmentStartWithNoTiesComparator.java
@@ -0,0 +1,73 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.utils.sam;
+
+import com.google.java.contract.Ensures;
+import com.google.java.contract.Requires;
+import htsjdk.samtools.SAMRecord;
+
+import java.util.Comparator;
+
+public class AlignmentStartWithNoTiesComparator implements Comparator<SAMRecord> {
+    @Requires("c1 >= 0 && c2 >= 0")
+    @Ensures("result == 0 || result == 1 || result == -1")
+    private int compareContigs(int c1, int c2) {
+        if (c1 == c2)
+            return 0;
+        else if (c1 > c2)
+            return 1;
+        return -1;
+    }
+
+    @Requires("r1 != null && r2 != null")
+    @Ensures("result == 0 || result == 1 || result == -1")
+    public int compare(SAMRecord r1, SAMRecord r2) {
+        int result;
+
+        if (r1 == r2)
+            result = 0;
+
+        else if (r1.getReadUnmappedFlag())
+            result = 1;
+        else if (r2.getReadUnmappedFlag())
+            result = -1;
+        else {
+            final int cmpContig = compareContigs(r1.getReferenceIndex(), r2.getReferenceIndex());
+
+            if (cmpContig != 0)
+                result = cmpContig;
+
+            else {
+                if (r1.getAlignmentStart() < r2.getAlignmentStart())
+                    result = -1;
+                else
+                    result = 1;
+            }
+        }
+
+        return result;
+    }
+}
\ No newline at end of file
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/sam/AlignmentUtils.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/sam/AlignmentUtils.java
new file mode 100644
index 0000000..4c9a444
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/sam/AlignmentUtils.java
@@ -0,0 +1,1337 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.utils.sam;
+
+import com.google.java.contract.Ensures;
+import com.google.java.contract.Requires;
+import htsjdk.samtools.Cigar;
+import htsjdk.samtools.CigarElement;
+import htsjdk.samtools.CigarOperator;
+import htsjdk.samtools.SAMRecord;
+import org.broadinstitute.gatk.utils.BaseUtils;
+import org.broadinstitute.gatk.utils.exceptions.ReviewedGATKException;
+import org.broadinstitute.gatk.utils.haplotype.Haplotype;
+import org.broadinstitute.gatk.utils.pileup.PileupElement;
+import org.broadinstitute.gatk.utils.recalibration.EventType;
+import org.broadinstitute.gatk.utils.smithwaterman.SWPairwiseAlignment;
+
+import java.util.*;
+
+
+public final class AlignmentUtils {
+    private final static EnumSet<CigarOperator> ALIGNED_TO_GENOME_OPERATORS = EnumSet.of(CigarOperator.M, CigarOperator.EQ, CigarOperator.X);
+    private final static EnumSet<CigarOperator> ALIGNED_TO_GENOME_PLUS_SOFTCLIPS = EnumSet.of(CigarOperator.M, CigarOperator.EQ, CigarOperator.X, CigarOperator.S);
+    public final static String HAPLOTYPE_TAG = "HC";
+
+    // cannot be instantiated
+    private AlignmentUtils() { }
+
+    /**
+     * Does cigar start or end with a deletion operation?
+     *
+     * @param cigar a non-null cigar to test
+     * @return true if the first or last operator of cigar is a D
+     */
+    public static boolean startsOrEndsWithInsertionOrDeletion(final Cigar cigar) {
+        if ( cigar == null ) throw new IllegalArgumentException("Cigar cannot be null");
+
+        if ( cigar.isEmpty() )
+            return false;
+
+        final CigarOperator first = cigar.getCigarElement(0).getOperator();
+        final CigarOperator last = cigar.getCigarElement(cigar.numCigarElements()-1).getOperator();
+        return first == CigarOperator.D || first == CigarOperator.I || last == CigarOperator.D || last == CigarOperator.I;
+    }
+
+    /**
+     * Aligns reads the haplotype, and then projects this alignment of read -> hap onto the reference
+     * via the alignment of haplotype (via its getCigar) method.
+     *
+     * @param originalRead the read we want to write aligned to the reference genome
+     * @param haplotype the haplotype that the read should be aligned to, before aligning to the reference
+     * @param referenceStart the start of the reference that haplotype is aligned to.  Provides global coordinate frame.
+     * @param isInformative true if the read is differentially informative for one of the haplotypes
+     *
+     * @throws IllegalArgumentException if {@code originalRead} is {@code null} or {@code haplotype} is {@code null} or it
+     *   does not have a Cigar or the {@code referenceStart} is invalid (less than 1).
+     *
+     * @return a GATKSAMRecord aligned to reference. Never {@code null}.
+     */
+    public static GATKSAMRecord createReadAlignedToRef(final GATKSAMRecord originalRead,
+                                                       final Haplotype haplotype,
+                                                       final int referenceStart,
+                                                       final boolean isInformative) {
+        if ( originalRead == null ) throw new IllegalArgumentException("originalRead cannot be null");
+        if ( haplotype == null ) throw new IllegalArgumentException("haplotype cannot be null");
+        if ( haplotype.getCigar() == null ) throw new IllegalArgumentException("Haplotype cigar not set " + haplotype);
+        if ( referenceStart < 1 ) throw new IllegalArgumentException("reference start much be >= 1 but got " + referenceStart);
+
+        // compute the smith-waterman alignment of read -> haplotype
+        final SWPairwiseAlignment swPairwiseAlignment = new SWPairwiseAlignment(haplotype.getBases(), originalRead.getReadBases(), CigarUtils.NEW_SW_PARAMETERS);
+        if ( swPairwiseAlignment.getAlignmentStart2wrt1() == -1 )
+            // sw can fail (reasons not clear) so if it happens just don't realign the read
+            return originalRead;
+        final Cigar swCigar = consolidateCigar(swPairwiseAlignment.getCigar());
+
+        // since we're modifying the read we need to clone it
+        final GATKSAMRecord read = (GATKSAMRecord)originalRead.clone();
+
+        // only informative reads are given the haplotype tag to enhance visualization
+        if ( isInformative )
+            read.setAttribute(HAPLOTYPE_TAG, haplotype.hashCode());
+
+        // compute here the read starts w.r.t. the reference from the SW result and the hap -> ref cigar
+        final Cigar extendedHaplotypeCigar = haplotype.getConsolidatedPaddedCigar(1000);
+        final int readStartOnHaplotype = calcFirstBaseMatchingReferenceInCigar(extendedHaplotypeCigar, swPairwiseAlignment.getAlignmentStart2wrt1());
+        final int readStartOnReference = referenceStart + haplotype.getAlignmentStartHapwrtRef() + readStartOnHaplotype;
+        read.setAlignmentStart(readStartOnReference);
+        read.resetSoftStartAndEnd();
+
+        // compute the read -> ref alignment by mapping read -> hap -> ref from the
+        // SW of read -> hap mapped through the given by hap -> ref
+        final Cigar haplotypeToRef = trimCigarByBases(extendedHaplotypeCigar, swPairwiseAlignment.getAlignmentStart2wrt1(), extendedHaplotypeCigar.getReadLength() - 1);
+        final Cigar readToRefCigarRaw = applyCigarToCigar(swCigar, haplotypeToRef);
+        final Cigar readToRefCigarClean = cleanUpCigar(readToRefCigarRaw);
+        final Cigar readToRefCigar = leftAlignIndel(readToRefCigarClean, haplotype.getBases(),
+                originalRead.getReadBases(), swPairwiseAlignment.getAlignmentStart2wrt1(), 0, true);
+
+        read.setCigar(readToRefCigar);
+
+        if ( readToRefCigar.getReadLength() != read.getReadLength() )
+            throw new IllegalStateException("Cigar " + readToRefCigar + " with read length " + readToRefCigar.getReadLength()
+                    + " != read length " + read.getReadLength() + " for read " + read.format() + "\nhapToRef " + haplotypeToRef + " length " + haplotypeToRef.getReadLength() + "/" + haplotypeToRef.getReferenceLength()
+                    + "\nreadToHap " + swCigar + " length " + swCigar.getReadLength() + "/" + swCigar.getReferenceLength());
+
+        return read;
+    }
+
+
+
+    /**
+     * Get the byte[] from bases that cover the reference interval refStart -> refEnd given the
+     * alignment of bases to the reference (basesToRefCigar) and the start offset of the bases on the reference
+     *
+     * refStart and refEnd are 0 based offsets that we want to obtain.  In the client code, if the reference
+     * bases start at position X and you want Y -> Z, refStart should be Y - X and refEnd should be Z - X.
+     *
+     * If refStart or refEnd would start or end the new bases within a deletion, this function will return null
+     *
+     * @param bases
+     * @param refStart
+     * @param refEnd
+     * @param basesStartOnRef where does the bases array start w.r.t. the reference start?  For example, bases[0] of
+     *                        could be at refStart == 0 if basesStartOnRef == 0, but it could just as easily be at
+     *                        10 (meaning bases doesn't fully span the reference), which would be indicated by basesStartOnRef == 10.
+     *                        It's not trivial to eliminate this parameter because it's tied up with the cigar
+     * @param basesToRefCigar the cigar that maps the bases to the reference genome
+     * @return a byte[] containing the bases covering this interval, or null if we would start or end within a deletion
+     */
+    public static byte[] getBasesCoveringRefInterval(final int refStart, final int refEnd, final byte[] bases, final int basesStartOnRef, final Cigar basesToRefCigar) {
+        if ( refStart < 0 || refEnd < refStart ) throw new IllegalArgumentException("Bad start " + refStart + " and/or stop " + refEnd);
+        if ( basesStartOnRef < 0 ) throw new IllegalArgumentException("BasesStartOnRef must be >= 0 but got " + basesStartOnRef);
+        if ( bases == null ) throw new IllegalArgumentException("Bases cannot be null");
+        if ( basesToRefCigar == null ) throw new IllegalArgumentException("basesToRefCigar cannot be null");
+        if ( bases.length != basesToRefCigar.getReadLength() ) throw new IllegalArgumentException("Mismatch in length between reference bases " + bases.length + " and cigar length " + basesToRefCigar);
+
+        int refPos = basesStartOnRef;
+        int basesPos = 0;
+        int basesStart = -1;
+        int basesStop = -1;
+        boolean done = false;
+
+        for ( int iii = 0; ! done && iii < basesToRefCigar.numCigarElements(); iii++ ) {
+            final CigarElement ce = basesToRefCigar.getCigarElement(iii);
+            switch ( ce.getOperator() ) {
+                case I:
+                    basesPos += ce.getLength();
+                    break;
+                case M: case X: case EQ:
+                    for ( int i = 0; i < ce.getLength(); i++ ) {
+                        if ( refPos == refStart )
+                            basesStart = basesPos;
+                        if ( refPos == refEnd ) {
+                            basesStop = basesPos;
+                            done = true;
+                            break;
+                        }
+                        refPos++;
+                        basesPos++;
+                    }
+                    break;
+                case D:
+                    for ( int i = 0; i < ce.getLength(); i++ ) {
+                        if ( refPos == refEnd || refPos == refStart ) {
+                            // if we ever reach a ref position that is either a start or an end, we fail
+                            return null;
+                        }
+                        refPos++;
+                    }
+                    break;
+                default:
+                    throw new IllegalStateException("Unsupported operator " + ce);
+            }
+        }
+
+        if ( basesStart == -1 || basesStop == -1 )
+            throw new IllegalStateException("Never found start " + basesStart + " or stop " + basesStop + " given cigar " + basesToRefCigar);
+
+        return Arrays.copyOfRange(bases, basesStart, basesStop + 1);
+    }
+
+    /**
+     * Get the number of bases at which refSeq and readSeq differ, given their alignment
+     *
+     * @param cigar the alignment of readSeq to refSeq
+     * @param refSeq the bases of the reference sequence
+     * @param readSeq the bases of the read sequence
+     * @return the number of bases that differ between refSeq and readSeq
+     */
+    public static int calcNumDifferentBases(final Cigar cigar, final byte[] refSeq, final byte[] readSeq) {
+        int refIndex = 0, readIdx = 0, delta = 0;
+
+        for (final CigarElement ce : cigar.getCigarElements()) {
+            final int elementLength = ce.getLength();
+            switch (ce.getOperator()) {
+                case X:case EQ:case M:
+                    for (int j = 0; j < elementLength; j++, refIndex++, readIdx++)
+                        delta += refSeq[refIndex] != readSeq[readIdx] ? 1 : 0;
+                    break;
+                case I:
+                    delta += elementLength;
+                case S:
+                    readIdx += elementLength;
+                    break;
+                case D:
+                    delta += elementLength;
+                case N:
+                    refIndex += elementLength;
+                    break;
+                case H:
+                case P:
+                    break;
+                default:
+                    throw new ReviewedGATKException("The " + ce.getOperator() + " cigar element is not currently supported");
+            }
+        }
+
+        return delta;
+    }
+
+    public static class MismatchCount {
+        public int numMismatches = 0;
+        public long mismatchQualities = 0;
+    }
+
+    public static long mismatchingQualities(GATKSAMRecord r, byte[] refSeq, int refIndex) {
+        return getMismatchCount(r, refSeq, refIndex).mismatchQualities;
+    }
+
+    /**
+     * @see #getMismatchCount(GATKSAMRecord, byte[], int, int, int) with startOnRead == 0 and nReadBases == read.getReadLength()
+     */
+    public static MismatchCount getMismatchCount(GATKSAMRecord r, byte[] refSeq, int refIndex) {
+        return getMismatchCount(r, refSeq, refIndex, 0, r.getReadLength());
+    }
+
+    // todo -- this code and mismatchesInRefWindow should be combined and optimized into a single
+    // todo -- high performance implementation.  We can do a lot better than this right now
+
+    /**
+     * Count how many bases mismatch the reference.  Indels are not considered mismatching.
+     *
+     * @param r                   the sam record to check against
+     * @param refSeq              the byte array representing the reference sequence
+     * @param refIndex            the index in the reference byte array of the read's first base (the reference index
+     *                            is matching the alignment start, there may be tons of soft-clipped bases before/after
+     *                            that so it's wrong to compare with getReadLength() here.).  Note that refIndex is
+     *                            zero based, not 1 based
+     * @param startOnRead         the index in the read's bases from which we start counting
+     * @param nReadBases          the number of bases after (but including) startOnRead that we check
+     * @return non-null object representing the mismatch count
+     */
+    @Ensures("result != null")
+    public static MismatchCount getMismatchCount(GATKSAMRecord r, byte[] refSeq, int refIndex, int startOnRead, int nReadBases) {
+        if ( r == null ) throw new IllegalArgumentException("attempting to calculate the mismatch count from a read that is null");
+        if ( refSeq == null ) throw new IllegalArgumentException("attempting to calculate the mismatch count with a reference sequence that is null");
+        if ( refIndex < 0 ) throw new IllegalArgumentException("attempting to calculate the mismatch count with a reference index that is negative");
+        if ( startOnRead < 0 ) throw new IllegalArgumentException("attempting to calculate the mismatch count with a read start that is negative");
+        if ( nReadBases < 0 ) throw new IllegalArgumentException("attempting to calculate the mismatch count for a negative number of read bases");
+        if ( refSeq.length - refIndex < (r.getAlignmentEnd() - r.getAlignmentStart()) )
+            throw new IllegalArgumentException("attempting to calculate the mismatch count against a reference string that is smaller than the read");
+
+        MismatchCount mc = new MismatchCount();
+
+        int readIdx = 0;
+        final int endOnRead = startOnRead + nReadBases - 1; // index of the last base on read we want to count (note we are including soft-clipped bases with this math)
+        final byte[] readSeq = r.getReadBases();
+        final Cigar c = r.getCigar();
+        final byte[] readQuals = r.getBaseQualities();
+        for (final CigarElement ce : c.getCigarElements()) {
+
+            if (readIdx > endOnRead)
+                break;
+
+            final int elementLength = ce.getLength();
+            switch (ce.getOperator()) {
+                case X:
+                    mc.numMismatches += elementLength;
+                    for (int j = 0; j < elementLength; j++)
+                        mc.mismatchQualities += readQuals[readIdx+j];
+                case EQ:
+                    refIndex += elementLength;
+                    readIdx += elementLength;
+                break;
+                case M:
+                    for (int j = 0; j < elementLength; j++, refIndex++, readIdx++) {
+                        if (refIndex >= refSeq.length)
+                            continue;                      // TODO : It should never happen, we should throw exception here
+                        if (readIdx < startOnRead) continue;
+                        if (readIdx > endOnRead) break;
+                        byte refChr = refSeq[refIndex];
+                        byte readChr = readSeq[readIdx];
+                        // Note: we need to count X/N's as mismatches because that's what SAM requires
+                        //if ( BaseUtils.simpleBaseToBaseIndex(readChr) == -1 ||
+                        //     BaseUtils.simpleBaseToBaseIndex(refChr)  == -1 )
+                        //    continue; // do not count Ns/Xs/etc ?
+                        if (readChr != refChr) {
+                            mc.numMismatches++;
+                            mc.mismatchQualities += readQuals[readIdx];
+                        }
+                    }
+                    break;
+                case I:
+                case S:
+                    readIdx += elementLength;
+                    break;
+                case D:
+                case N:
+                    refIndex += elementLength;
+                    break;
+                case H:
+                case P:
+                    break;
+                default:
+                    throw new ReviewedGATKException("The " + ce.getOperator() + " cigar element is not currently supported");
+            }
+
+        }
+        return mc;
+    }
+
+    /**
+     * Returns number of alignment blocks (continuous stretches of aligned bases) in the specified alignment.
+     * This method follows closely the SAMRecord::getAlignmentBlocks() implemented in samtools library, but
+     * it only counts blocks without actually allocating and filling the list of blocks themselves. Hence, this method is
+     * a much more efficient alternative to r.getAlignmentBlocks.size() in the situations when this number is all that is needed.
+     * Formally, this method simply returns the number of M elements in the cigar.
+     *
+     * @param r alignment
+     * @return number of continuous alignment blocks (i.e. 'M' elements of the cigar; all indel and clipping elements are ignored).
+     */
+    @Ensures("result >= 0")
+    public static int getNumAlignmentBlocks(final SAMRecord r) {
+        if ( r == null ) throw new IllegalArgumentException("read cannot be null");
+        final Cigar cigar = r.getCigar();
+        if (cigar == null) return 0;
+
+        int n = 0;
+        for (final CigarElement e : cigar.getCigarElements()) {
+            if (ALIGNED_TO_GENOME_OPERATORS.contains(e.getOperator()))
+                n++;
+        }
+
+        return n;
+    }
+
+
+    /**
+     * Get the number of bases aligned to the genome, including soft clips
+     *
+     * If read is not mapped (i.e., doesn't have a cigar) returns 0
+     *
+     * @param r a non-null GATKSAMRecord
+     * @return the number of bases aligned to the genome in R, including soft clipped bases
+     */
+    public static int getNumAlignedBasesCountingSoftClips(final GATKSAMRecord r) {
+        int n = 0;
+        final Cigar cigar = r.getCigar();
+        if (cigar == null) return 0;
+
+        for (final CigarElement e : cigar.getCigarElements())
+            if (ALIGNED_TO_GENOME_PLUS_SOFTCLIPS.contains(e.getOperator()))
+                n += e.getLength();
+
+        return n;
+    }
+
+    /**
+     * Count the number of bases hard clipped from read
+     *
+     * If read's cigar is null, return 0
+     *
+     * @param r a non-null read
+     * @return a positive integer
+     */
+    @Ensures("result >= 0")
+    public static int getNumHardClippedBases(final SAMRecord r) {
+        if ( r == null ) throw new IllegalArgumentException("Read cannot be null");
+
+        int n = 0;
+        final Cigar cigar = r.getCigar();
+        if (cigar == null) return 0;
+
+        for (final CigarElement e : cigar.getCigarElements())
+            if (e.getOperator() == CigarOperator.H)
+                n += e.getLength();
+
+        return n;
+    }
+
+    /**
+     * Calculate the number of bases that are soft clipped in read with quality score greater than threshold
+     *
+     * Handles the case where the cigar is null (i.e., the read is unmapped), returning 0
+     *
+     * @param read a non-null GATKSAMRecord.
+     * @param qualThreshold consider bases with quals > this value as high quality.  Must be >= 0
+     * @return positive integer
+     */
+    @Ensures("result >= 0")
+    public static int calcNumHighQualitySoftClips( final GATKSAMRecord read, final byte qualThreshold ) {
+        if ( read == null ) throw new IllegalArgumentException("Read cannot be null");
+        if ( qualThreshold < 0 ) throw new IllegalArgumentException("Expected qualThreshold to be a positive byte but saw " + qualThreshold);
+
+        if ( read.getCigar() == null ) // the read is unmapped
+            return 0;
+
+        final byte[] qual = read.getBaseQualities( EventType.BASE_SUBSTITUTION );
+
+        int numHQSoftClips = 0;
+        int alignPos = 0;
+        for ( final CigarElement ce : read.getCigar().getCigarElements() ) {
+            final int elementLength = ce.getLength();
+
+            switch( ce.getOperator() ) {
+                case S:
+                    for( int jjj = 0; jjj < elementLength; jjj++ ) {
+                        if( qual[alignPos++] > qualThreshold ) { numHQSoftClips++; }
+                    }
+                    break;
+                case M: case I: case EQ: case X:
+                    alignPos += elementLength;
+                    break;
+                case H: case P: case D: case N:
+                    break;
+                default:
+                    throw new IllegalStateException("Unsupported cigar operator: " + ce.getOperator());
+            }
+        }
+
+        return numHQSoftClips;
+    }
+
+    public static int calcAlignmentByteArrayOffset(final Cigar cigar, final PileupElement pileupElement, final int alignmentStart, final int refLocus) {
+        return calcAlignmentByteArrayOffset( cigar, pileupElement.getOffset(), pileupElement.isDeletion(), alignmentStart, refLocus );
+    }
+
+    /**
+     * Calculate the index into the read's bases of the beginning of the encompassing cigar element for a given cigar and offset
+     *
+     * @param cigar            the read's CIGAR -- cannot be null
+     * @param offset           the offset to use for the calculation or -1 if in the middle of a deletion
+     * @param isDeletion       are we in the middle of a deletion?
+     * @param alignmentStart   the alignment start of the read
+     * @param refLocus         the reference position of the offset
+     * @return a non-negative int index
+     */
+    @Ensures("result >= 0")
+    public static int calcAlignmentByteArrayOffset(final Cigar cigar, final int offset, final boolean isDeletion, final int alignmentStart, final int refLocus) {
+        if ( cigar == null ) throw new IllegalArgumentException("attempting to find the alignment position from a CIGAR that is null");
+        if ( offset < -1 ) throw new IllegalArgumentException("attempting to find the alignment position with an offset that is negative (and not -1)");
+        if ( alignmentStart < 0 ) throw new IllegalArgumentException("attempting to find the alignment position from an alignment start that is negative");
+        if ( refLocus < 0 ) throw new IllegalArgumentException("attempting to find the alignment position from a reference position that is negative");
+        if ( offset >= cigar.getReadLength() ) throw new IllegalArgumentException("attempting to find the alignment position of an offset than is larger than the read length");
+
+        int pileupOffset = offset;
+
+        // Reassign the offset if we are in the middle of a deletion because of the modified representation of the read bases
+        if (isDeletion) {
+            pileupOffset = refLocus - alignmentStart;
+            final CigarElement ce = cigar.getCigarElement(0);
+            if (ce.getOperator() == CigarOperator.S) {
+                pileupOffset += ce.getLength();
+            }
+        }
+
+        int pos = 0;
+        int alignmentPos = 0;
+
+        for (int iii = 0; iii < cigar.numCigarElements(); iii++) {
+            final CigarElement ce = cigar.getCigarElement(iii);
+            final int elementLength = ce.getLength();
+
+            switch (ce.getOperator()) {
+                case I:
+                case S: // TODO -- I don't think that soft clips should be treated the same as inserted bases here. Investigation needed.
+                    pos += elementLength;
+                    if (pos >= pileupOffset) {
+                        return alignmentPos;
+                    }
+                    break;
+                case D:
+                    if (!isDeletion) {
+                        alignmentPos += elementLength;
+                    } else {
+                        if (pos + elementLength - 1 >= pileupOffset) {
+                            return alignmentPos + (pileupOffset - pos);
+                        } else {
+                            pos += elementLength;
+                            alignmentPos += elementLength;
+                        }
+                    }
+                    break;
+                case M:
+                case EQ:
+                case X:
+                    if (pos + elementLength - 1 >= pileupOffset) {
+                        return alignmentPos + (pileupOffset - pos);
+                    } else {
+                        pos += elementLength;
+                        alignmentPos += elementLength;
+                    }
+                    break;
+                case H:
+                case P:
+                case N:
+                    break;
+                default:
+                    throw new ReviewedGATKException("Unsupported cigar operator: " + ce.getOperator());
+            }
+        }
+
+        return alignmentPos;
+    }
+
+    /**
+     * Generate an array of bases for just those that are aligned to the reference (i.e. no clips or insertions)
+     *
+     * @param cigar            the read's CIGAR -- cannot be null
+     * @param read             the read's base array
+     * @return a non-null array of bases (bytes)
+     */
+    @Ensures("result != null")
+    public static byte[] readToAlignmentByteArray(final Cigar cigar, final byte[] read) {
+        if ( cigar == null ) throw new IllegalArgumentException("attempting to generate an alignment from a CIGAR that is null");
+        if ( read == null ) throw new IllegalArgumentException("attempting to generate an alignment from a read sequence that is null");
+
+        final int alignmentLength = cigar.getReferenceLength();
+        final byte[] alignment = new byte[alignmentLength];
+        int alignPos = 0;
+        int readPos = 0;
+        for (int iii = 0; iii < cigar.numCigarElements(); iii++) {
+
+            final CigarElement ce = cigar.getCigarElement(iii);
+            final int elementLength = ce.getLength();
+
+            switch (ce.getOperator()) {
+                case I:
+                    if (alignPos > 0) {
+                        final int prevPos = alignPos - 1;
+                        if (alignment[prevPos] == BaseUtils.Base.A.base) {
+                            alignment[prevPos] = PileupElement.A_FOLLOWED_BY_INSERTION_BASE;
+                        } else if (alignment[prevPos] == BaseUtils.Base.C.base) {
+                            alignment[prevPos] = PileupElement.C_FOLLOWED_BY_INSERTION_BASE;
+                        } else if (alignment[prevPos] == BaseUtils.Base.T.base) {
+                            alignment[prevPos] = PileupElement.T_FOLLOWED_BY_INSERTION_BASE;
+                        } else if (alignment[prevPos] == BaseUtils.Base.G.base) {
+                            alignment[prevPos] = PileupElement.G_FOLLOWED_BY_INSERTION_BASE;
+                        }
+                    }
+                case S:
+                    readPos += elementLength;
+                    break;
+                case D:
+                case N:
+                    for (int jjj = 0; jjj < elementLength; jjj++) {
+                        alignment[alignPos++] = PileupElement.DELETION_BASE;
+                    }
+                    break;
+                case M:
+                case EQ:
+                case X:
+                    for (int jjj = 0; jjj < elementLength; jjj++) {
+                        alignment[alignPos++] = read[readPos++];
+                    }
+                    break;
+                case H:
+                case P:
+                    break;
+                default:
+                    throw new ReviewedGATKException("Unsupported cigar operator: " + ce.getOperator());
+            }
+        }
+        return alignment;
+    }
+
+    /**
+     * Returns true if the read does not belong to a contig, i.e. it's location is GenomeLoc.UNMAPPED.
+     * NOTE: A read can have a mapped GenomeLoc and still have an unmapped flag!
+     *
+     * @param r record
+     * @return true if read is unmapped to a genome loc
+     */
+    public static boolean isReadGenomeLocUnmapped(final SAMRecord r) {
+        return SAMRecord.NO_ALIGNMENT_REFERENCE_NAME.equals(r.getReferenceName());
+    }
+
+    /**
+     * Due to (unfortunate) multiple ways to indicate that read is unmapped allowed by SAM format
+     * specification, one may need this convenience shortcut. Checks both 'read unmapped' flag and
+     * alignment reference index/start.
+     *
+     * Our life would be so much easier if all sam files followed the specs. In reality,
+     * sam files (including those generated by maq or bwa) miss headers altogether. When
+     * reading such a SAM file, reference name is set, but since there is no sequence dictionary,
+     * null is always returned for referenceIndex. Let's be paranoid here, and make sure that
+     * we do not call the read "unmapped" when it has only reference name set with ref. index missing
+     * or vice versa.
+     *
+     * @param r a non-null record
+     * @return true if read is unmapped
+     */
+    public static boolean isReadUnmapped(final SAMRecord r) {
+        if ( r == null )
+            throw new IllegalArgumentException("Read cannot be null");
+
+        return r.getReadUnmappedFlag() ||
+               !((r.getReferenceIndex() != null && r.getReferenceIndex() != SAMRecord.NO_ALIGNMENT_REFERENCE_INDEX ||
+                  r.getReferenceName() != null && !r.getReferenceName().equals(SAMRecord.NO_ALIGNMENT_REFERENCE_NAME)) &&
+                 r.getAlignmentStart() != SAMRecord.NO_ALIGNMENT_START);
+
+    }
+
+    /**
+     * Need a well-formed, consolidated Cigar string so that the left aligning code works properly.
+     * For example, 1M1M1M1D2M1M --> 3M1D3M
+     * If the given cigar is empty then the returned cigar will also be empty
+     *
+     * Note that this routine collapses cigar elements of size 0, so 2M0M => 2M
+     *
+     * @param c the cigar to consolidate
+     * @return  a non-null cigar with consecutive matching operators merged into single operators.
+     */
+    @Ensures({"result != null"})
+    public static Cigar consolidateCigar( final Cigar c ) {
+        if ( c == null ) { throw new IllegalArgumentException("Cigar cannot be null"); }
+
+        // fast check to determine if there's anything worth doing before we create new Cigar and actually do some work
+        if ( ! needsConsolidation(c) )
+            return c;
+
+        final Cigar returnCigar = new Cigar();
+        int sumLength = 0;
+        CigarElement lastElement = null;
+
+        for( final CigarElement cur : c.getCigarElements() ) {
+            if ( cur.getLength() == 0 )
+                continue; // don't add elements of 0 length
+
+            if ( lastElement != null && lastElement.getOperator() != cur.getOperator() ) {
+                returnCigar.add(new CigarElement(sumLength, lastElement.getOperator()));
+                sumLength = 0;
+            }
+
+            sumLength += cur.getLength();
+            lastElement = cur;
+        }
+
+        if ( sumLength > 0 ) {
+            returnCigar.add(new CigarElement(sumLength, lastElement.getOperator()));
+        }
+
+        return returnCigar;
+    }
+
+    /**
+     * Does the cigar C need to be consolidated?
+     *
+     * @param c a non-null cigar
+     * @return true if so
+     */
+    private static boolean needsConsolidation(final Cigar c) {
+        if ( c.numCigarElements() <= 1 )
+            return false; // fast path for empty or single cigar
+
+        CigarOperator lastOp = null;
+        for( final CigarElement cur : c.getCigarElements() ) {
+            if ( cur.getLength() == 0 || lastOp == cur.getOperator() )
+                return true;
+            lastOp = cur.getOperator();
+        }
+
+        return false;
+    }
+
+    /**
+     * Takes the alignment of the read sequence <code>readSeq</code> to the reference sequence <code>refSeq</code>
+     * starting at 0-based position <code>refIndex</code> on the <code>refSeq</code> and specified by its <code>cigar</code>.
+     * The last argument <code>readIndex</code> specifies 0-based position on the read where the alignment described by the
+     * <code>cigar</code> starts. Usually cigars specify alignments of the whole read to the ref, so that readIndex is normally 0.
+     * Use non-zero readIndex only when the alignment cigar represents alignment of a part of the read. The refIndex in this case
+     * should be the position where the alignment of that part of the read starts at. In other words, both refIndex and readIndex are
+     * always the positions where the cigar starts on the ref and on the read, respectively.
+     * <p/>
+     * If the alignment has one or more indels, this method attempts to move them left across a stretch of repetitive bases.
+     * For instance, if the original cigar specifies that (any) one AT is deleted from a repeat sequence TATATATA, the output
+     * cigar will always mark the leftmost AT as deleted. If there is no indel in the original cigar or if the indel position
+     * is determined unambiguously (i.e. inserted/deleted sequence is not repeated), the original cigar is returned.
+     *
+     * Note that currently we do not actually support the case where there is more than one indel in the alignment.  We will throw
+     * an exception if there is -- unless the
+     *
+     * @param cigar     structure of the original alignment
+     * @param refSeq    reference sequence the read is aligned to
+     * @param readSeq   read sequence
+     * @param refIndex  0-based alignment start position on ref
+     * @param readIndex 0-based alignment start position on read
+     * @param doNotThrowExceptionForMultipleIndels  if true we will not throw an exception if we encounter multiple indels in the alignment will instead will return the original cigar
+     * @return a non-null cigar, in which the indels are guaranteed to be placed at the leftmost possible position across a repeat (if any)
+     */
+    @Ensures("result != null")
+    public static Cigar leftAlignIndel(Cigar cigar, final byte[] refSeq, final byte[] readSeq, final int refIndex, final int readIndex, final boolean doNotThrowExceptionForMultipleIndels) {
+        ensureLeftAlignmentHasGoodArguments(cigar, refSeq, readSeq, refIndex, readIndex);
+
+        final int numIndels = countIndelElements(cigar);
+        if ( numIndels == 0 )
+            return cigar;
+        if ( numIndels == 1 )
+            return leftAlignSingleIndel(cigar, refSeq, readSeq, refIndex, readIndex, true);
+
+        // if we got here then there is more than 1 indel in the alignment
+        if ( doNotThrowExceptionForMultipleIndels )
+            return cigar;
+
+        throw new UnsupportedOperationException("attempting to left align a CIGAR that has more than 1 indel in its alignment but this functionality has not been implemented yet");
+    }
+
+    private static void ensureLeftAlignmentHasGoodArguments(final Cigar cigar, final byte[] refSeq, final byte[] readSeq, final int refIndex, final int readIndex) {
+        if ( cigar == null ) throw new IllegalArgumentException("attempting to left align a CIGAR that is null");
+        if ( refSeq == null ) throw new IllegalArgumentException("attempting to left align a reference sequence that is null");
+        if ( readSeq == null ) throw new IllegalArgumentException("attempting to left align a read sequence that is null");
+        if ( refIndex < 0 ) throw new IllegalArgumentException("attempting to left align with a reference index less than 0");
+        if ( readIndex < 0 ) throw new IllegalArgumentException("attempting to left align with a read index less than 0");
+    }
+
+    /**
+     * Counts the number of I/D operators
+     *
+     * @param cigar   cigar to check -- cannot be null
+     * @return  non-negative count of indel operators
+     */
+    @Requires("cigar != null")
+    @Ensures("result >= 0")
+    private static int countIndelElements(final Cigar cigar) {
+        int indelCount = 0;
+        for ( CigarElement ce : cigar.getCigarElements() ) {
+            if ( ce.getOperator() == CigarOperator.D || ce.getOperator() == CigarOperator.I )
+                indelCount++;
+        }
+        return indelCount;
+    }
+
+    /**
+     * See the documentation for AlignmentUtils.leftAlignIndel() for more details.
+     *
+     * This flavor of the left alignment works if and only if the alignment has one - and only one - indel.
+     * An exception is thrown if there are no indels or more than 1 indel in the alignment.
+     *
+     * @param cigar     structure of the original alignment -- cannot be null
+     * @param refSeq    reference sequence the read is aligned to
+     * @param readSeq   read sequence
+     * @param refIndex  0-based alignment start position on ref
+     * @param readIndex 0-based alignment start position on read
+     * @param cleanupCigar if true, we'll cleanup the resulting cigar element, removing 0 length elements and deletions from the first cigar position
+     * @return a non-null cigar, in which the single indel is guaranteed to be placed at the leftmost possible position across a repeat (if any)
+     */
+    @Ensures("result != null")
+    public static Cigar leftAlignSingleIndel(Cigar cigar, final byte[] refSeq, final byte[] readSeq, final int refIndex, final int readIndex, final boolean cleanupCigar) {
+        ensureLeftAlignmentHasGoodArguments(cigar, refSeq, readSeq, refIndex, readIndex);
+
+        int indexOfIndel = -1;
+        for (int i = 0; i < cigar.numCigarElements(); i++) {
+            CigarElement ce = cigar.getCigarElement(i);
+            if (ce.getOperator() == CigarOperator.D || ce.getOperator() == CigarOperator.I) {
+                // if there is more than 1 indel, exception out
+                if (indexOfIndel != -1)
+                    throw new IllegalArgumentException("attempting to left align a CIGAR that has more than 1 indel in its alignment");
+                indexOfIndel = i;
+            }
+        }
+
+        // if there is no indel, exception out
+        if ( indexOfIndel == -1 )
+            throw new IllegalArgumentException("attempting to left align a CIGAR that has no indels in its alignment");
+        // if the alignment starts with an insertion (so that there is no place on the read to move that insertion further left), we are done
+        if ( indexOfIndel == 0 )
+            return cigar;
+
+        final int indelLength = cigar.getCigarElement(indexOfIndel).getLength();
+
+        byte[] altString = createIndelString(cigar, indexOfIndel, refSeq, readSeq, refIndex, readIndex);
+        if (altString == null)
+            return cigar;
+
+        Cigar newCigar = cigar;
+        for (int i = 0; i < indelLength; i++) {
+            newCigar = moveCigarLeft(newCigar, indexOfIndel);
+            byte[] newAltString = createIndelString(newCigar, indexOfIndel, refSeq, readSeq, refIndex, readIndex);
+
+            // check to make sure we haven't run off the end of the read
+            boolean reachedEndOfRead = cigarHasZeroSizeElement(newCigar);
+
+            if (Arrays.equals(altString, newAltString)) {
+                cigar = newCigar;
+                i = -1;
+                if (reachedEndOfRead)
+                    cigar = cleanupCigar ? cleanUpCigar(cigar) : cigar;
+            }
+
+            if (reachedEndOfRead)
+                break;
+        }
+
+        return cigar;
+    }
+
+    /**
+     * Does one of the elements in cigar have a 0 length?
+     *
+     * @param c a non-null cigar
+     * @return true if any element has 0 size
+     */
+    @Requires("c != null")
+    protected static boolean cigarHasZeroSizeElement(final Cigar c) {
+        for (final CigarElement ce : c.getCigarElements()) {
+            if (ce.getLength() == 0)
+                return true;
+        }
+        return false;
+    }
+
+    /**
+     * Clean up the incoming cigar
+     *
+     * Removes elements with zero size
+     * Clips away beginning deletion operators
+     *
+     * @param c the cigar string we want to clean up
+     * @return a newly allocated, cleaned up Cigar
+     */
+    @Requires("c != null")
+    @Ensures("result != null")
+    public static Cigar cleanUpCigar(final Cigar c) {
+        final List<CigarElement> elements = new ArrayList<CigarElement>(c.numCigarElements() - 1);
+
+        for (final CigarElement ce : c.getCigarElements()) {
+            if (ce.getLength() != 0 && (! elements.isEmpty() || ce.getOperator() != CigarOperator.D)) {
+                elements.add(ce);
+            }
+        }
+
+        return new Cigar(elements);
+    }
+
+    /**
+     * Removing a trailing deletion from the incoming cigar if present
+     *
+     * @param c the cigar we want to update
+     * @return a non-null Cigar
+     */
+    @Requires("c != null")
+    @Ensures("result != null")
+    public static Cigar removeTrailingDeletions(final Cigar c) {
+
+        final List<CigarElement> elements = c.getCigarElements();
+        if ( elements.get(elements.size() - 1).getOperator() != CigarOperator.D )
+            return c;
+
+        return new Cigar(elements.subList(0, elements.size() - 1));
+    }
+
+    /**
+     * Move the indel in a given cigar string one base to the left
+     *
+     * @param cigar          original cigar
+     * @param indexOfIndel   the index of the indel cigar element
+     * @return non-null cigar with indel moved one base to the left
+     */
+    @Requires("cigar != null && indexOfIndel >= 0 && indexOfIndel < cigar.numCigarElements()")
+    @Ensures("result != null")
+    private static Cigar moveCigarLeft(Cigar cigar, int indexOfIndel) {
+        // get the first few elements
+        ArrayList<CigarElement> elements = new ArrayList<CigarElement>(cigar.numCigarElements());
+        for (int i = 0; i < indexOfIndel - 1; i++)
+            elements.add(cigar.getCigarElement(i));
+
+        // get the indel element and move it left one base
+        CigarElement ce = cigar.getCigarElement(indexOfIndel - 1);
+        elements.add(new CigarElement(Math.max(ce.getLength() - 1, 0), ce.getOperator()));
+        elements.add(cigar.getCigarElement(indexOfIndel));
+        if (indexOfIndel + 1 < cigar.numCigarElements()) {
+            ce = cigar.getCigarElement(indexOfIndel + 1);
+            elements.add(new CigarElement(ce.getLength() + 1, ce.getOperator()));
+        } else {
+            elements.add(new CigarElement(1, CigarOperator.M));
+        }
+
+        // get the last few elements
+        for (int i = indexOfIndel + 2; i < cigar.numCigarElements(); i++)
+            elements.add(cigar.getCigarElement(i));
+        return new Cigar(elements);
+    }
+
+    /**
+     * Create the string (really a byte array) representation of an indel-containing cigar against the reference.
+     *
+     * @param cigar             the indel-containing cigar
+     * @param indexOfIndel      the index of the indel cigar element
+     * @param refSeq            the reference sequence
+     * @param readSeq           the read sequence for the cigar
+     * @param refIndex          the starting reference index into refSeq
+     * @param readIndex         the starting read index into readSeq
+     * @return non-null byte array which is the indel representation against the reference
+     */
+    @Requires("cigar != null && indexOfIndel >= 0 && indexOfIndel < cigar.numCigarElements() && refSeq != null && readSeq != null && refIndex >= 0 && readIndex >= 0")
+    @Ensures("result != null")
+    private static byte[] createIndelString(final Cigar cigar, final int indexOfIndel, final byte[] refSeq, final byte[] readSeq, int refIndex, int readIndex) {
+        CigarElement indel = cigar.getCigarElement(indexOfIndel);
+        int indelLength = indel.getLength();
+
+        int totalRefBases = 0;
+        for (int i = 0; i < indexOfIndel; i++) {
+            CigarElement ce = cigar.getCigarElement(i);
+            int length = ce.getLength();
+
+            switch (ce.getOperator()) {
+                case M:
+                case EQ:
+                case X:
+                    readIndex += length;
+                    refIndex += length;
+                    totalRefBases += length;
+                    break;
+                case S:
+                    readIndex += length;
+                    break;
+                case N:
+                    refIndex += length;
+                    totalRefBases += length;
+                    break;
+                default:
+                    break;
+            }
+        }
+
+        // sometimes, when there are very large known indels, we won't have enough reference sequence to cover them
+        if (totalRefBases + indelLength > refSeq.length)
+            indelLength -= (totalRefBases + indelLength - refSeq.length);
+
+        // the indel-based reference string
+        byte[] alt = new byte[refSeq.length + (indelLength * (indel.getOperator() == CigarOperator.D ? -1 : 1))];
+
+        // add the bases before the indel, making sure it's not aligned off the end of the reference
+        if (refIndex > alt.length || refIndex > refSeq.length)
+            return null;
+        System.arraycopy(refSeq, 0, alt, 0, refIndex);
+        int currentPos = refIndex;
+
+        // take care of the indel
+        if (indel.getOperator() == CigarOperator.D) {
+            refIndex += indelLength;
+        } else {
+            System.arraycopy(readSeq, readIndex, alt, currentPos, indelLength);
+            currentPos += indelLength;
+        }
+
+        // add the bases after the indel, making sure it's not aligned off the end of the reference
+        if (refSeq.length - refIndex > alt.length - currentPos)
+            return null;
+        System.arraycopy(refSeq, refIndex, alt, currentPos, refSeq.length - refIndex);
+
+        return alt;
+    }
+
+
+    /**
+     * Trim cigar down to one that starts at start reference on the left and extends to end on the reference
+     *
+     * @param cigar a non-null Cigar to trim down
+     * @param start Where should we start keeping bases on the reference?  The first position is 0
+     * @param end Where should we stop keeping bases on the reference?  The maximum value is cigar.getReferenceLength()
+     * @return a new Cigar with reference length == start - end + 1
+     */
+    public static Cigar trimCigarByReference(final Cigar cigar, final int start, final int end) {
+        if ( start < 0 ) throw new IllegalArgumentException("Start must be >= 0 but got " + start);
+        if ( end < start ) throw new IllegalArgumentException("End " + end + " is < start start " + start);
+        if ( end > cigar.getReferenceLength() ) throw new IllegalArgumentException("End is beyond the cigar's reference length " + end + " for cigar " + cigar );
+
+        final Cigar result = trimCigar(cigar, start, end, true);
+
+        if ( result.getReferenceLength() != end - start + 1)
+            throw new IllegalStateException("trimCigarByReference failure: start " + start + " end " + end + " for " + cigar + " resulted in cigar with wrong size " + result);
+        return result;
+    }
+
+    /**
+     * Trim cigar down to one that starts at start base in the cigar and extends to (inclusive) end base
+     *
+     * @param cigar a non-null Cigar to trim down
+     * @param start Where should we start keeping bases in the cigar?  The first position is 0
+     * @param end Where should we stop keeping bases in the cigar?  The maximum value is cigar.getReadLength()
+     * @return a new Cigar containing == start - end + 1 reads
+     */
+    public static Cigar trimCigarByBases(final Cigar cigar, final int start, final int end) {
+        if ( start < 0 ) throw new IllegalArgumentException("Start must be >= 0 but got " + start);
+        if ( end < start ) throw new IllegalArgumentException("End " + end + " is < start = " + start);
+        if ( end > cigar.getReadLength() ) throw new IllegalArgumentException("End is beyond the cigar's read length " + end + " for cigar " + cigar );
+
+        final Cigar result = trimCigar(cigar, start, end, false);
+
+        final int expectedSize = end - start + 1;
+        if ( result.getReadLength() != expectedSize)
+            throw new IllegalStateException("trimCigarByBases failure: start " + start + " end " + end + " for " + cigar + " resulted in cigar with wrong size " + result + " with size " + result.getReadLength() + " expected " + expectedSize + " for input cigar " + cigar);
+        return result;
+    }
+
+
+    /**
+     * Workhorse for trimCigarByBases and trimCigarByReference
+     *
+     * @param cigar a non-null Cigar to trim down
+     * @param start Where should we start keeping bases in the cigar?  The first position is 0
+     * @param end Where should we stop keeping bases in the cigar?  The maximum value is cigar.getReadLength()
+     * @param byReference should start and end be intrepreted as position in the reference or the read to trim to/from?
+     * @return a non-null cigar
+     */
+    @Requires({"cigar != null", "start >= 0", "start <= end"})
+    @Ensures("result != null")
+    private static Cigar trimCigar(final Cigar cigar, final int start, final int end, final boolean byReference) {
+        final List<CigarElement> newElements = new LinkedList<CigarElement>();
+
+        int pos = 0;
+        for ( final CigarElement elt : cigar.getCigarElements() ) {
+            if ( pos > end && (byReference || elt.getOperator() != CigarOperator.D) ) break;
+
+            switch ( elt.getOperator() ) {
+                case D:
+                    if ( ! byReference ) {
+                        if ( pos >= start )
+                            newElements.add(elt);
+                        break;
+                    }
+                    // otherwise fall through to the next case
+                case EQ: case M: case X:
+                    pos = addCigarElements(newElements, pos, start, end, elt);
+                    break;
+                case S: case I:
+                    if ( byReference ) {
+                        if ( pos >= start )
+                            newElements.add(elt);
+                    } else {
+                        pos = addCigarElements(newElements, pos, start, end, elt);
+                    }
+                    break;
+                default:
+                    throw new IllegalStateException("Cannot handle " + elt);
+            }
+        }
+
+        return AlignmentUtils.consolidateCigar(new Cigar(newElements));
+    }
+
+    /**
+     * Helper function for trimCigar that adds cigar elements (of total length X) of elt.op to dest for
+     * X bases that fall between start and end, where the last position of the base is pos.
+     *
+     * The primary use of this function is to create a new cigar element list that contains only
+     * elements that occur between start and end bases in an initial cigar.
+     *
+     * Note that this function may return multiple cigar elements (1M1M etc) that are best consolidated
+     * after the fact into a single simpler representation.
+     *
+     * @param dest we will append our cigar elements to this list
+     * @param pos the position (0 indexed) where elt started
+     * @param start only include bases that occur >= this position
+     * @param end only include bases that occur <= this position
+     * @param elt the element we are slicing down
+     * @return the position after we've traversed all elt.length bases of elt
+     */
+   protected static int addCigarElements(final List<CigarElement> dest, int pos, final int start, final int end, final CigarElement elt) {
+        final int length = Math.min(pos + elt.getLength() - 1, end) - Math.max(pos, start) + 1;
+        if ( length > 0 )
+            dest.add(new CigarElement(length, elt.getOperator()));
+        return pos + elt.getLength();
+    }
+
+    /**
+     * Get the offset (base 0) of the first reference aligned base in Cigar that occurs after readStartByBaseOfCigar base of the cigar
+     *
+     * The main purpose of this routine is to find a good start position for a read given it's cigar.  The real
+     * challenge is that the starting base might be inside an insertion, in which case the read actually starts
+     * at the next M/EQ/X operator.
+     *
+     * @param cigar a non-null cigar
+     * @param readStartByBaseOfCigar finds the first base after this (0 indexed) that aligns to the reference genome (M, EQ, X)
+     * @throws IllegalStateException if no such base can be found
+     * @return an offset into cigar
+     */
+    public static int calcFirstBaseMatchingReferenceInCigar(final Cigar cigar, int readStartByBaseOfCigar) {
+        if ( cigar == null ) throw new IllegalArgumentException("cigar cannot be null");
+        if ( readStartByBaseOfCigar >= cigar.getReadLength() ) throw new IllegalArgumentException("readStartByBaseOfCigar " + readStartByBaseOfCigar + " must be <= readLength " + cigar.getReadLength());
+
+        int hapOffset = 0, refOffset = 0;
+        for ( final CigarElement ce : cigar.getCigarElements() ) {
+            for ( int i = 0; i < ce.getLength(); i++ ) {
+                switch ( ce.getOperator() ) {
+                    case M:case EQ:case X:
+                        if ( hapOffset >= readStartByBaseOfCigar )
+                            return refOffset;
+                        hapOffset++;
+                        refOffset++;
+                        break;
+                    case I: case S:
+                        hapOffset++;
+                        break;
+                    case D:
+                        refOffset++;
+                        break;
+                    default:
+                        throw new IllegalStateException("calcFirstBaseMatchingReferenceInCigar does not support cigar " + ce.getOperator() + " in cigar " + cigar);
+                }
+            }
+        }
+
+        throw new IllegalStateException("Never found appropriate matching state for cigar " + cigar + " given start of " + readStartByBaseOfCigar);
+    }
+
+    /**
+     * Generate a new Cigar that maps the operations of the first cigar through those in a second
+     *
+     * For example, if first is 5M and the second is 2M1I2M then the result is 2M1I2M.
+     * However, if first is 1M2D3M and second is 2M1I3M this results in a cigar X
+     *
+     * ref   : AC-GTA
+     * hap   : ACxGTA  - 2M1I3M
+     * read  : A--GTA  - 1M2D3M
+     * result: A--GTA => 1M1D3M
+     *
+     * ref   : ACxG-TA
+     * hap   : AC-G-TA  - 2M1D3M
+     * read  : AC-GxTA  - 3M1I2M
+     * result: AC-GxTA => 2M1D1M1I2M
+     *
+     * ref   : ACGTA
+     * hap   : ACGTA  - 5M
+     * read  : A-GTA  - 1M1I3M
+     * result: A-GTA => 1M1I3M
+     *
+     * ref   : ACGTAC
+     * hap   : AC---C  - 2M3D1M
+     * read  : AC---C  - 3M
+     * result: AG---C => 2M3D
+     *
+     * The constraint here is that both cigars should imply that the result have the same number of
+     * reference bases (i.e.g, cigar.getReferenceLength() are equals).
+     *
+     * @param firstToSecond the cigar mapping hap1 -> hap2
+     * @param secondToThird the cigar mapping hap2 -> hap3
+     * @return A cigar mapping hap1 -> hap3
+     */
+    public static Cigar applyCigarToCigar(final Cigar firstToSecond, final Cigar secondToThird) {
+        final boolean DEBUG = false;
+
+        final List<CigarElement> newElements = new LinkedList<CigarElement>();
+        final int nElements12 = firstToSecond.getCigarElements().size();
+        final int nElements23 = secondToThird.getCigarElements().size();
+
+        int cigar12I = 0, cigar23I = 0;
+        int elt12I = 0, elt23I = 0;
+
+        while ( cigar12I < nElements12 && cigar23I < nElements23 ) {
+            final CigarElement elt12 = firstToSecond.getCigarElement(cigar12I);
+            final CigarElement elt23 = secondToThird.getCigarElement(cigar23I);
+
+            final CigarPairTransform transform = getTransformer(elt12.getOperator(), elt23.getOperator());
+
+            if ( DEBUG )
+                System.out.printf("Transform %s => %s with elt1 = %d %s @ %d elt2 = %d %s @ %d with transform %s%n",
+                        firstToSecond, secondToThird, cigar12I, elt12.getOperator(), elt12I, cigar23I, elt23.getOperator(), elt23I, transform);
+
+            if ( transform.op13 != null ) // skip no ops
+                newElements.add(new CigarElement(1, transform.op13));
+
+            elt12I += transform.advance12;
+            elt23I += transform.advance23;
+
+            // if have exhausted our current element, advance to the next one
+            if ( elt12I == elt12.getLength() ) { cigar12I++; elt12I = 0; }
+            if ( elt23I == elt23.getLength() ) { cigar23I++; elt23I = 0; }
+        }
+
+        return AlignmentUtils.consolidateCigar(new Cigar(newElements));
+    }
+
+    private static CigarPairTransform getTransformer(final CigarOperator op12, final CigarOperator op23) {
+        for ( final CigarPairTransform transform : cigarPairTransformers) {
+            if ( transform.op12.contains(op12) && transform.op23.contains(op23) )
+                return transform;
+        }
+
+        throw new IllegalStateException("No transformer for operators " + op12 + " and " + op23);
+    }
+
+    /**
+     * transformations that project one alignment state through another
+     *
+     * Think about this as a state machine, where we have:
+     *
+     * bases3 : xxx A zzz
+     * bases2 : xxx B zzz
+     * bases1 : xxx C zzz
+     *
+     * where A, B and C are alignment states of a three way alignment.  We want to capture
+     * the transition from operation mapping 1 -> 2 and an operation mapping 2 -> 3 and its
+     * associated mapping from 1 -> 3 and the advancement of the cigar states of 1->2 and 2->3.
+     *
+     * Imagine that A, B, and C are all equivalent (so that op12 = M and op23 = M).  This implies
+     * a mapping of 1->3 of M, and in this case the next states to consider in the 3 way alignment
+     * are the subsequent states in 1 and 2 (so that advance12 and advance23 are both 1).
+     *
+     * Obviously not all of the states and their associated transitions are so simple.  Suppose instead
+     * that op12 = I, and op23 = M.  What does this look like:
+     *
+     * bases3 : xxx - A zzz
+     * bases2 : xxx - B zzz
+     * bases1 : xxx I C zzz
+     *
+     * It means that op13 must be an insertion (as we have an extra base in 1 thats not present in 2 and
+     * so not present in 3).  We advance the cigar in 1 by 1 (as we've consumed one base in 1 for the I)
+     * but we haven't yet found the base corresponding to the M of op23.  So we don't advance23.
+     */
+    private static class CigarPairTransform {
+        private final EnumSet<CigarOperator> op12, op23;
+        private final CigarOperator op13;
+        private final int advance12, advance23;
+
+        private CigarPairTransform(CigarOperator op12, CigarOperator op23, CigarOperator op13, int advance12, int advance23) {
+            this.op12 = getCigarSet(op12);
+            this.op23 = getCigarSet(op23);
+            this.op13 = op13;
+            this.advance12 = advance12;
+            this.advance23 = advance23;
+        }
+
+        private static EnumSet<CigarOperator> getCigarSet(final CigarOperator masterOp) {
+            switch ( masterOp ) {
+                case M: return EnumSet.of(CigarOperator.M, CigarOperator.EQ, CigarOperator.X);
+                case I: return EnumSet.of(CigarOperator.I, CigarOperator.S);
+                case D: return EnumSet.of(CigarOperator.D);
+                default: throw new IllegalStateException("Unexpected state " + masterOp);
+            }
+        }
+
+        @Override
+        public String toString() {
+            return "CigarPairTransform{" +
+                    "op12=" + op12 +
+                    ", op23=" + op23 +
+                    ", op13=" + op13 +
+                    ", advance12=" + advance12 +
+                    ", advance23=" + advance23 +
+                    '}';
+        }
+    }
+
+
+    private final static List<CigarPairTransform> cigarPairTransformers = Arrays.asList(
+            //
+            // op12 is a match
+            //
+            // 3: xxx B yyy
+            // ^^^^^^^^^^^^
+            // 2: xxx M yyy
+            // 1: xxx M yyy
+            new CigarPairTransform(CigarOperator.M, CigarOperator.M, CigarOperator.M, 1, 1),
+            // 3: xxx I yyy
+            // ^^^^^^^^^^^^
+            // 2: xxx I yyy
+            // 1: xxx M yyy
+            new CigarPairTransform(CigarOperator.M, CigarOperator.I, CigarOperator.I, 1, 1),
+            // 3: xxx D yyy
+            // ^^^^^^^^^^^^
+            // 2: xxx D yyy
+            // 1: xxx M yyy
+            new CigarPairTransform(CigarOperator.M, CigarOperator.D, CigarOperator.D, 0, 1),
+
+            //
+            // op12 is a deletion
+            //
+            // 3: xxx D M yyy
+            // ^^^^^^^^^^^^
+            // 2: xxx M yyy
+            // 1: xxx D yyy
+            new CigarPairTransform(CigarOperator.D, CigarOperator.M, CigarOperator.D, 1, 1),
+            // 3: xxx D1 D2 yyy
+            // ^^^^^^^^^^^^
+            // 2: xxx D2 yyy
+            // 1: xxx D1 yyy
+            new CigarPairTransform(CigarOperator.D, CigarOperator.D, CigarOperator.D, 1, 0),
+            // 3: xxx X yyy => no-op, we skip emitting anything here
+            // ^^^^^^^^^^^^
+            // 2: xxx I yyy
+            // 1: xxx D yyy
+            new CigarPairTransform(CigarOperator.D, CigarOperator.I, null, 1, 1),
+
+            //
+            // op12 is a insertion
+            //
+            // 3: xxx I M yyy
+            // ^^^^^^^^^^^^
+            // 2: xxx M yyy
+            // 1: xxx I yyy
+            new CigarPairTransform(CigarOperator.I, CigarOperator.M, CigarOperator.I, 1, 0),
+            // 3: xxx I D yyy
+            // ^^^^^^^^^^^^
+            // 2: xxx D yyy
+            // 1: xxx I yyy
+            new CigarPairTransform(CigarOperator.I, CigarOperator.D, CigarOperator.I, 1, 0),
+            // 3: xxx I1 I2 yyy
+            // ^^^^^^^^^^^^
+            // 2: xxx I2 yyy
+            // 1: xxx I1 yyy
+            new CigarPairTransform(CigarOperator.I, CigarOperator.I, CigarOperator.I, 1, 0)
+            );
+}
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/sam/ArtificialBAMBuilder.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/sam/ArtificialBAMBuilder.java
new file mode 100644
index 0000000..8233252
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/sam/ArtificialBAMBuilder.java
@@ -0,0 +1,242 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.utils.sam;
+
+import htsjdk.samtools.reference.IndexedFastaSequenceFile;
+import htsjdk.samtools.*;
+import org.broadinstitute.gatk.utils.GenomeLocParser;
+import org.broadinstitute.gatk.utils.NGSPlatform;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.*;
+
+/**
+ * Easy to use creator of artificial BAM files for testing
+ *
+ * Allows us to make a stream of reads or an index BAM file with read having the following properties
+ *
+ * - coming from n samples
+ * - of fixed read length and aligned to the genome with M operator
+ * - having N reads per alignment start
+ * - skipping N bases between each alignment start
+ * - starting at a given alignment start
+ *
+ * User: depristo
+ * Date: 1/15/13
+ * Time: 9:22 AM
+ */
+public class ArtificialBAMBuilder {
+    public final static int BAM_SHARD_SIZE = 16384;
+
+    private final IndexedFastaSequenceFile reference;
+    private final GenomeLocParser parser;
+
+    final int nReadsPerLocus;
+    final int nLoci;
+
+    int skipNLoci = 0;
+    int alignmentStart = 1;
+    int readLength = 10;
+    private final ArrayList<String> samples = new ArrayList<String>();
+    private List<GATKSAMRecord> createdReads = null;
+
+    private LinkedList<GATKSAMRecord> additionalReads = new LinkedList<GATKSAMRecord>();
+
+    final SAMFileWriterFactory factory = new SAMFileWriterFactory();
+    {
+        factory.setCreateIndex(true);
+    }
+
+    SAMFileHeader header;
+
+    public ArtificialBAMBuilder(final IndexedFastaSequenceFile reference, int nReadsPerLocus, int nLoci) {
+        this.nReadsPerLocus = nReadsPerLocus;
+        this.nLoci = nLoci;
+
+        this.reference = reference;
+        this.parser = new GenomeLocParser(reference);
+        createAndSetHeader(1);
+    }
+
+    public ArtificialBAMBuilder(int nReadsPerLocus, int nLoci) {
+        this(ArtificialSAMUtils.createArtificialSamHeader(1, 1, 1000000).getSequenceDictionary(), nReadsPerLocus, nLoci);
+    }
+
+    public ArtificialBAMBuilder(final SAMSequenceDictionary dict, int nReadsPerLocus, int nLoci) {
+        this.nReadsPerLocus = nReadsPerLocus;
+        this.nLoci = nLoci;
+        this.reference = null;
+        this.parser = new GenomeLocParser(dict);
+        createAndSetHeader(1);
+    }
+
+    public IndexedFastaSequenceFile getReference() {
+        return reference;
+    }
+
+    public GenomeLocParser getGenomeLocParser() {
+        return parser;
+    }
+
+    public ArtificialBAMBuilder createAndSetHeader(final int nSamples) {
+        createdReads = null;
+        this.header = new SAMFileHeader();
+        header.setSortOrder(SAMFileHeader.SortOrder.coordinate);
+        header.setSequenceDictionary(parser.getContigs());
+        samples.clear();
+
+        for ( int i = 0; i < nSamples; i++ ) {
+            final GATKSAMReadGroupRecord rg = new GATKSAMReadGroupRecord("rg" + i);
+            final String sample = "sample" + i;
+            samples.add(sample);
+            rg.setSample(sample);
+            rg.setPlatform(NGSPlatform.ILLUMINA.getDefaultPlatform());
+            header.addReadGroup(rg);
+        }
+
+        return this;
+    }
+
+    public void addReads(final GATKSAMRecord readToAdd) {
+        createdReads = null;
+        additionalReads.add(readToAdd);
+    }
+
+    public void addReads(final Collection<GATKSAMRecord> readsToAdd) {
+        createdReads = null;
+        additionalReads.addAll(readsToAdd);
+    }
+
+    public List<String> getSamples() {
+        return samples;
+    }
+
+    /**
+     * Create a read stream based on the parameters.  The cigar string for each
+     * read will be *M, where * is the length of the read.
+     *
+     * Useful for testing things like LocusIteratorBystate
+     *
+     * @return a ordered list of reads
+     */
+    public List<GATKSAMRecord> makeReads() {
+        if ( createdReads == null ) {
+            final String baseName = "read";
+            final LinkedList<GATKSAMReadGroupRecord> readGroups = new LinkedList<GATKSAMReadGroupRecord>();
+            for ( final SAMReadGroupRecord rg : header.getReadGroups())
+                readGroups.add(new GATKSAMReadGroupRecord(rg));
+
+            List<GATKSAMRecord> reads = new ArrayList<GATKSAMRecord>(nReadsPerLocus*nLoci);
+            for ( int locusI = 0; locusI < nLoci; locusI++) {
+                final int locus = locusI * (skipNLoci + 1);
+                for ( int readI = 0; readI < nReadsPerLocus; readI++ ) {
+                    for ( final GATKSAMReadGroupRecord rg : readGroups ) {
+                        final String readName = String.format("%s.%d.%d.%s", baseName, locus, readI, rg.getId());
+                        final GATKSAMRecord read = ArtificialSAMUtils.createArtificialRead(header, readName, 0, alignmentStart + locus, readLength);
+                        read.setReadGroup(rg);
+                        reads.add(read);
+                    }
+                }
+            }
+
+            if ( ! additionalReads.isEmpty() ) {
+                reads.addAll(additionalReads);
+                Collections.sort(reads, new SAMRecordCoordinateComparator());
+            }
+
+            createdReads = new ArrayList<GATKSAMRecord>(reads);
+        }
+
+        return createdReads;
+    }
+
+    /**
+     * Make an indexed BAM file contains the reads in the builder, marking it for deleteOnExit()
+     * @return the BAM file
+     */
+    public File makeTemporarilyBAMFile() {
+        try {
+            final File file = File.createTempFile("tempBAM", ".bam");
+            file.deleteOnExit();
+
+            // Register the bam index file for deletion on exit as well:
+            new File(file.getAbsolutePath().replace(".bam", ".bai")).deleteOnExit();
+            new File(file.getAbsolutePath() + ".bai").deleteOnExit();
+
+            return makeBAMFile(file);
+        } catch ( IOException e ) {
+            throw new RuntimeException(e);
+        }
+    }
+
+    /**
+     * Write the reads from this builder to output, creating an index as well
+     * @param output the output BAM file we want to use
+     * @return
+     */
+    public File makeBAMFile(final File output) {
+        final SAMFileWriter writer = factory.makeBAMWriter(header, true, output, 0);
+        for ( final GATKSAMRecord read : makeReads() )
+            writer.addAlignment(read);
+        writer.close();
+        return output;
+    }
+
+    public int getnReadsPerLocus() { return nReadsPerLocus; }
+    public int getnLoci() { return nLoci; }
+    public int getSkipNLoci() { return skipNLoci; }
+    public ArtificialBAMBuilder setSkipNLoci(int skipNLoci) { this.skipNLoci = skipNLoci; createdReads = null; return this; }
+    public int getAlignmentStart() { return alignmentStart; }
+    public ArtificialBAMBuilder setAlignmentStart(int alignmentStart) { this.alignmentStart = alignmentStart; createdReads = null; return this; }
+    public int getReadLength() { return readLength; }
+    public ArtificialBAMBuilder setReadLength(int readLength) { this.readLength = readLength; createdReads = null; return this; }
+    public SAMFileHeader getHeader() { return header; }
+    public ArtificialBAMBuilder setHeader(SAMFileHeader header) { this.header = header; createdReads = null; return this; }
+
+    public int getAlignmentEnd() {
+        return alignmentStart + nLoci * (skipNLoci + 1) + readLength;
+    }
+
+
+    public int getNSamples() { return samples.size(); }
+
+    public int expectedNumberOfReads() {
+        return nLoci * nReadsPerLocus * header.getReadGroups().size();
+    }
+
+    @Override
+    public String toString() {
+        return "ArtificialBAMBuilder{" +
+                "samples=" + samples +
+                ", readLength=" + readLength +
+                ", alignmentStart=" + alignmentStart +
+                ", skipNLoci=" + skipNLoci +
+                ", nLoci=" + nLoci +
+                ", nReadsPerLocus=" + nReadsPerLocus +
+                '}';
+    }
+}
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/sam/ArtificialGATKSAMFileWriter.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/sam/ArtificialGATKSAMFileWriter.java
new file mode 100644
index 0000000..0821f46
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/sam/ArtificialGATKSAMFileWriter.java
@@ -0,0 +1,130 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.utils.sam;
+
+import htsjdk.samtools.SAMFileHeader;
+import htsjdk.samtools.SAMRecord;
+import htsjdk.samtools.util.ProgressLoggerInterface;
+import org.broadinstitute.gatk.engine.io.GATKSAMFileWriter;
+
+import java.util.ArrayList;
+import java.util.List;
+
+
+/*
+ * 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.
+ */
+
+/**
+ * @author aaron
+ *         <p/>
+ *         Class ArtificialGATKSAMFileWriter
+ *         <p/>
+ * generates a fake samwriter, that you can get the output reads
+ * from when you're done.  
+ */
+public class ArtificialGATKSAMFileWriter implements GATKSAMFileWriter {
+
+    // are we closed
+    private boolean closed = false;
+
+    // the SAMRecords we've added to this writer
+    List<SAMRecord> records = new ArrayList<SAMRecord>();
+
+    public void addAlignment( SAMRecord alignment ) {
+        records.add(alignment);
+    }
+
+    public SAMFileHeader getFileHeader() {
+        if (records.size() > 0) {
+            return records.get(0).getHeader();
+        }
+        return null;
+    }
+
+    /** not much to do when we're fake */
+    public void close() {
+        closed = true;
+    }
+
+    /**
+     * are we closed?
+     *
+     * @return true if we're closed
+     */
+    public boolean isClosed() {
+        return closed;
+    }
+
+    /**
+     * get the records we've seen
+     * @return
+     */
+    public List<SAMRecord> getRecords() {
+        return records;
+    }
+
+    @Override
+    public void writeHeader(SAMFileHeader header) {
+    }
+
+    @Override
+    public void setPresorted(boolean presorted) {
+    }
+
+    @Override
+    public void setMaxRecordsInRam(int maxRecordsInRam) {
+    }
+
+    /**
+     * @throws java.lang.UnsupportedOperationException No progress logging in this implementation.
+     */
+    @Override
+    public void setProgressLogger(final ProgressLoggerInterface logger) {
+        throw new UnsupportedOperationException("Progress logging not supported");
+    }
+}
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/sam/ArtificialMultiSampleReadStream.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/sam/ArtificialMultiSampleReadStream.java
new file mode 100644
index 0000000..84978c1
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/sam/ArtificialMultiSampleReadStream.java
@@ -0,0 +1,87 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.utils.sam;
+
+import htsjdk.samtools.MergingSamRecordIterator;
+import htsjdk.samtools.SamFileHeaderMerger;
+import htsjdk.samtools.SAMFileHeader;
+import htsjdk.samtools.SAMFileReader;
+import htsjdk.samtools.SAMRecord;
+import org.broadinstitute.gatk.engine.iterators.GATKSAMIterator;
+import org.broadinstitute.gatk.engine.iterators.GATKSAMIteratorAdapter;
+import org.broadinstitute.gatk.utils.exceptions.ReviewedGATKException;
+
+import java.util.*;
+
+/**
+ * Simple wrapper class that multiplexes multiple ArtificialSingleSampleReadStreams into a single stream of reads
+ *
+ * @author David Roazen
+ */
+public class ArtificialMultiSampleReadStream implements Iterable<SAMRecord> {
+
+    private Collection<ArtificialSingleSampleReadStream> perSampleArtificialReadStreams;
+    private MergingSamRecordIterator mergingIterator;
+
+    public ArtificialMultiSampleReadStream( Collection<ArtificialSingleSampleReadStream> perSampleArtificialReadStreams ) {
+        if ( perSampleArtificialReadStreams == null || perSampleArtificialReadStreams.isEmpty() ) {
+            throw new ReviewedGATKException("Can't create an ArtificialMultiSampleReadStream out of 0 ArtificialSingleSampleReadStreams");
+        }
+
+        this.perSampleArtificialReadStreams = perSampleArtificialReadStreams;
+    }
+
+    public Iterator<SAMRecord> iterator() {
+        // lazy initialization to prevent reads from being created until they're needed
+        initialize();
+
+        return mergingIterator;
+    }
+
+    public GATKSAMIterator getGATKSAMIterator() {
+        // lazy initialization to prevent reads from being created until they're needed
+        initialize();
+
+        return GATKSAMIteratorAdapter.adapt(mergingIterator);
+    }
+
+    private void initialize() {
+        Collection<SAMFileReader> perSampleSAMReaders = new ArrayList<SAMFileReader>(perSampleArtificialReadStreams.size());
+        Collection<SAMFileHeader> headers = new ArrayList<SAMFileHeader>(perSampleArtificialReadStreams.size());
+
+        for ( ArtificialSingleSampleReadStream readStream : perSampleArtificialReadStreams ) {
+            Collection<SAMRecord> thisStreamReads = readStream.makeReads();
+
+            SAMFileReader reader = new ArtificialSAMFileReader(readStream.getHeader(),
+                                                               thisStreamReads.toArray(new SAMRecord[thisStreamReads.size()]));
+            perSampleSAMReaders.add(reader);
+            headers.add(reader.getFileHeader());
+        }
+
+        SamFileHeaderMerger headerMerger = new SamFileHeaderMerger(SAMFileHeader.SortOrder.coordinate, headers, true);
+        mergingIterator = new MergingSamRecordIterator(headerMerger, perSampleSAMReaders, true);
+    }
+}
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/sam/ArtificialPatternedSAMIterator.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/sam/ArtificialPatternedSAMIterator.java
new file mode 100644
index 0000000..8434e15
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/sam/ArtificialPatternedSAMIterator.java
@@ -0,0 +1,172 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.utils.sam;
+
+import htsjdk.samtools.SAMFileHeader;
+import htsjdk.samtools.SAMRecord;
+
+
+/*
+ * 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.
+ */
+
+/**
+ * @author aaron
+ *
+ *  Class ArtificialPatternedSAMIterator
+ *
+ * This class allows you to pattern the artificial sam iterator, asking for reads
+ * in order or out of order.
+ */
+public class ArtificialPatternedSAMIterator extends ArtificialSAMIterator {
+
+    /** the pattern we're implementing */
+    public enum PATTERN {
+        RANDOM_READS, IN_ORDER_READS;
+    }
+
+    // our pattern
+    private final PATTERN mPattern;
+
+    /**
+     * this is pretty heavy (and it could be extremely heavy, given the amount of reads they request, but it
+     * allows us to give them each read once, reguardless of the order specified
+     */
+    private final int[] reads;
+    private final int readCount;
+
+    /**
+     * create the fake iterator, given the mapping of chromosomes and read counts.  If pattern
+     * is specified to be random, it will generate reads that are randomly placed on the current chromosome
+     *
+     * @param startingChr the starting chromosome
+     * @param endingChr   the ending chromosome
+     * @param readCount   the number of reads in each chromosome
+     * @param header      the associated header
+     * @param pattern     the pattern to implement
+     */
+    ArtificialPatternedSAMIterator( int startingChr, int endingChr, int readCount, int unmappedReadCount, SAMFileHeader header, PATTERN pattern ) {
+        super(startingChr, endingChr, readCount, unmappedReadCount, header);
+        mPattern = pattern;
+        this.readCount = readCount;
+        reads = new int[readCount];
+
+        for (int x = 0; x < readCount; x++) {
+            reads[x] = x+1;
+        }
+        if (pattern == PATTERN.RANDOM_READS) {
+            // scramble a bunch of the reads
+            for (int y = 0; y < readCount; y++) {
+                int ranOne = (int) Math.round(Math.random() * ( readCount - 1 ));
+                int ranTwo = (int) Math.round(Math.random() * ( readCount - 1 ));
+                int temp = reads[ranOne];
+                reads[ranOne] = reads[ranTwo];
+                reads[ranTwo] = temp;
+            }
+            /**
+             *  up to this point there's no garauntee that the random() has made the reads out of order (though it's
+             *  extremely extremely unlikely it's failed).  Let's make sure there at least out of order:
+             */
+            if (this.reads[0] < this.reads[reads.length - 1]) {
+                int temp = reads[0];
+                reads[0] = reads[reads.length - 1];
+                reads[reads.length - 1] = temp;
+            }
+
+        }
+
+    }
+
+    /**
+     * override the default ArtificialSAMIterator createNextRead method, which creates the next read
+     *
+     * @return
+     */
+    protected boolean createNextRead() {
+        if (currentRead > rCount) {
+            currentChromo++;
+            currentRead = 1;
+        }
+        // check for end condition, have we finished the chromosome listing, and have no unmapped reads
+        if (currentChromo >= eChromosomeCount) {
+            if (unmappedRemaining < 1) {
+                this.next = null;
+                return false;
+            } else {
+                ++totalReadCount;
+                this.next = ArtificialSAMUtils.createArtificialRead(this.header,
+                        String.valueOf(totalReadCount),
+                        SAMRecord.NO_ALIGNMENT_REFERENCE_INDEX,
+                        SAMRecord.NO_ALIGNMENT_START,
+                        50);
+                --unmappedRemaining;
+                return true;
+            }
+        }
+        ++totalReadCount;
+        this.next = getNextRecord(currentRead);
+
+        ++currentRead;
+        return true;
+    }
+
+
+    /**
+     * get the next read, given it's index in the chromosome
+     *
+     * @param read the read index in the chromosome
+     *
+     * @return a SAMRecord
+     */
+    private SAMRecord getNextRecord( int read ) {
+        if (read > this.readCount) {
+            return ArtificialSAMUtils.createArtificialRead(this.header, String.valueOf(reads[readCount - 1]), currentChromo, reads[readCount - 1], 50);
+        }
+        return ArtificialSAMUtils.createArtificialRead(this.header, String.valueOf(reads[read-1]), currentChromo, reads[read-1], 50);
+    }
+
+}
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/sam/ArtificialReadsTraversal.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/sam/ArtificialReadsTraversal.java
new file mode 100644
index 0000000..54c2b87
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/sam/ArtificialReadsTraversal.java
@@ -0,0 +1,140 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.utils.sam;
+
+import htsjdk.samtools.SAMFileHeader;
+import htsjdk.samtools.SAMRecord;
+import org.apache.log4j.Logger;
+import org.broadinstitute.gatk.engine.contexts.ReferenceContext;
+import org.broadinstitute.gatk.engine.datasources.providers.ShardDataProvider;
+import org.broadinstitute.gatk.engine.traversals.TraversalEngine;
+import org.broadinstitute.gatk.engine.walkers.ReadWalker;
+import org.broadinstitute.gatk.engine.walkers.Walker;
+
+
+/*
+ * 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.
+ */
+
+/**
+ * @author aaron
+ *
+ * this class acts as a fake reads traversal engine for testing out reads based traversals.
+ */
+public class ArtificialReadsTraversal<M,T> extends TraversalEngine<M,T,Walker<M,T>,ShardDataProvider> {
+
+    public int startingChr = 1;
+    public int endingChr = 5;
+    public int readsPerChr = 100;
+    public int unMappedReads = 1000;
+    private int DEFAULT_READ_LENGTH = ArtificialSAMUtils.DEFAULT_READ_LENGTH;
+    private ArtificialPatternedSAMIterator iter;
+    /** our log, which we want to capture anything from this class */
+    protected static Logger logger = Logger.getLogger(ArtificialReadsTraversal.class);
+
+    /** Creates a new, uninitialized ArtificialReadsTraversal */
+    public ArtificialReadsTraversal() {
+    }
+
+    // what read ordering are we using
+    private ArtificialPatternedSAMIterator.PATTERN readOrder = ArtificialPatternedSAMIterator.PATTERN.IN_ORDER_READS;
+
+
+    /**
+     * set the read ordering of the reads given to the walker
+     *
+     * @param readOrdering
+     */
+    public void setReadOrder( ArtificialPatternedSAMIterator.PATTERN readOrdering ) {
+        readOrder = readOrdering;
+    }
+
+    @Override
+    public String getTraversalUnits() {
+        return "reads";
+    }
+
+    /**
+     * Traverse by reads, given the data and the walker
+     *
+     * @param walker       the walker to traverse with
+     * @param dataProvider the provider of the reads data
+     * @param sum          the value of type T, specified by the walker, to feed to the walkers reduce function
+     *
+     * @return the reduce variable of the read walker
+     */
+    public T traverse( Walker<M, T> walker,
+                       ShardDataProvider dataProvider,
+                       T sum ) {
+
+        if (!( walker instanceof ReadWalker ))
+            throw new IllegalArgumentException("Walker isn't a read walker!");
+
+        ReadWalker<M, T> readWalker = (ReadWalker<M, T>) walker;
+        SAMFileHeader header = ArtificialSAMUtils.createArtificialSamHeader(( endingChr - startingChr ) + 1, startingChr, readsPerChr + DEFAULT_READ_LENGTH);
+        iter = new ArtificialPatternedSAMIterator(this.startingChr,
+                this.endingChr,
+                this.readsPerChr,
+                this.unMappedReads,
+                header,
+                this.readOrder);
+
+        // while we still have more reads
+        for (SAMRecord read : iter) {
+
+            // an array of characters that represent the reference
+            ReferenceContext refSeq = null;
+
+            final boolean keepMeP = readWalker.filter(refSeq, (GATKSAMRecord) read);
+            if (keepMeP) {
+                M x = readWalker.map(refSeq, (GATKSAMRecord) read, null);  // TODO: fix me at some point, it would be nice to fake out ROD data too
+                sum = readWalker.reduce(x, sum);
+            }
+        }
+        return sum;
+    }
+}
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/sam/ArtificialSAMFileReader.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/sam/ArtificialSAMFileReader.java
new file mode 100644
index 0000000..427b12e
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/sam/ArtificialSAMFileReader.java
@@ -0,0 +1,156 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.utils.sam;
+
+import htsjdk.samtools.*;
+import org.broadinstitute.gatk.utils.GenomeLoc;
+import org.broadinstitute.gatk.utils.GenomeLocParser;
+import org.broadinstitute.gatk.utils.exceptions.ReviewedGATKException;
+
+import java.io.ByteArrayInputStream;
+import java.io.InputStream;
+import java.io.UnsupportedEncodingException;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Iterator;
+import java.util.List;
+/**
+ * User: hanna
+ * Date: Jun 11, 2009
+ * Time: 9:35:31 AM
+ * BROAD INSTITUTE SOFTWARE COPYRIGHT NOTICE AND AGREEMENT
+ * Software and documentation are copyright 2005 by the Broad Institute.
+ * All rights are reserved.
+ *
+ * Users acknowledge that this software is supplied without any warranty or support.
+ * The Broad Institute is not responsible for its use, misuse, or
+ * functionality.
+ */
+
+/**
+ * Pass specified reads into the given walker.
+ */
+
+public class ArtificialSAMFileReader extends SAMFileReader {
+    /**
+     * The parser, for GenomeLocs.
+     */
+    private final GenomeLocParser genomeLocParser;
+
+    /**
+     * Backing data store of reads.
+     */
+    private final List<SAMRecord> reads;
+
+    private SAMFileHeader customHeader = null;
+
+    /**
+     * Construct an artificial SAM file reader.
+     * @param sequenceDictionary sequence dictionary used to initialize our GenomeLocParser
+     * @param reads Reads to use as backing data source.
+     */
+    public ArtificialSAMFileReader(SAMSequenceDictionary sequenceDictionary,SAMRecord... reads) {
+        super( createEmptyInputStream(),true );
+        this.genomeLocParser = new GenomeLocParser(sequenceDictionary);
+        this.reads = Arrays.asList(reads);
+    }
+
+    /**
+     * Construct an artificial SAM file reader with the given SAM file header
+     *
+     * @param customHeader Header that should be returned by calls to getFileHeader() on this reader
+     * @param reads Reads to use as backing data source.
+     */
+    public ArtificialSAMFileReader( SAMFileHeader customHeader, SAMRecord... reads ) {
+        super(createEmptyInputStream(),true);
+
+        this.customHeader = customHeader;
+        this.genomeLocParser = new GenomeLocParser(customHeader.getSequenceDictionary());
+        this.reads = Arrays.asList(reads);
+    }
+
+
+    @Override
+    public SAMFileHeader getFileHeader() {
+        if ( customHeader != null ) {
+            return customHeader;
+        }
+
+        return super.getFileHeader();
+    }
+
+    /**
+     * @{inheritDoc}
+     */
+    @Override
+    public SAMRecordIterator query(final String sequence, final int start, final int end, final boolean contained) {
+        GenomeLoc region = genomeLocParser.createGenomeLoc(sequence, start, end);
+        List<SAMRecord> coveredSubset = new ArrayList<SAMRecord>();
+
+        for( SAMRecord read: reads ) {
+            GenomeLoc readPosition = genomeLocParser.createGenomeLoc(read);
+            if( contained && region.containsP(readPosition) ) coveredSubset.add(read);
+            else if( !contained && readPosition.overlapsP(region) ) coveredSubset.add(read);
+        }
+
+        final Iterator<SAMRecord> iterator = coveredSubset.iterator();
+        return new SAMRecordIterator() {
+            public boolean hasNext() { return iterator.hasNext(); }
+            public SAMRecord next() { return iterator.next(); }
+            public void close() {}
+            public void remove() { iterator.remove(); }
+            public SAMRecordIterator assertSorted(SAMFileHeader.SortOrder sortOrder) { return this; }
+        };
+    }
+
+    @Override
+    public SAMRecordIterator iterator() {
+        return new SAMRecordIterator() {
+            private final Iterator<SAMRecord> iterator = reads.iterator();
+            public boolean hasNext() { return iterator.hasNext(); }
+            public SAMRecord next() { return iterator.next(); }
+            public void close() {}
+            public void remove() { iterator.remove(); }
+            public SAMRecordIterator assertSorted(SAMFileHeader.SortOrder sortOrder) { return this; }
+        };
+    }
+
+    /**
+     * Builds an empty input stream for faking out the sam file reader.
+     * Derive it from a string so that, in the future, it might be possible
+     * to fake the text of a sam file from samtools output, et.c
+     * @return Stream that returns no characters.
+     */
+    private static InputStream createEmptyInputStream() {
+        try {
+            byte[] byteArray = "".getBytes("ISO-8859-1");
+            return new ByteArrayInputStream(byteArray);
+        }
+        catch( UnsupportedEncodingException ex ) {
+            throw new ReviewedGATKException("Unable to build empty input stream",ex);
+        }
+    }
+}
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/sam/ArtificialSAMIterator.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/sam/ArtificialSAMIterator.java
new file mode 100644
index 0000000..b133e9c
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/sam/ArtificialSAMIterator.java
@@ -0,0 +1,212 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.utils.sam;
+
+import htsjdk.samtools.SAMFileHeader;
+import htsjdk.samtools.SAMRecord;
+import org.broadinstitute.gatk.engine.iterators.GATKSAMIterator;
+
+import java.util.Iterator;
+
+
+/*
+ * 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.
+ */
+
+/** this fake iterator allows us to look at how specific piles of reads are handled */
+public class ArtificialSAMIterator implements GATKSAMIterator {
+
+
+    protected int currentChromo = 0;
+    protected int currentRead = 1;
+    protected int totalReadCount = 0;
+    protected int unmappedRemaining = 0;
+    protected boolean done = false;
+    // the next record
+    protected SAMRecord next = null;
+    protected SAMFileHeader header = null;
+
+    // the passed in parameters
+    protected final int sChr;
+    protected final int eChromosomeCount;
+    protected final int rCount;
+    protected final int unmappedReadCount;
+
+    // let us know to make a read, we need this to help out the fake sam query iterator
+    private boolean initialized = false;
+
+    /**
+     * Is this iterator currently open or closed?  Closed iterators can be reused.
+     */    
+    protected boolean open = false;
+
+    /**
+     * create the fake iterator, given the mapping of chromosomes and read counts
+     *
+     * @param startingChr the starting chromosome
+     * @param endingChr   the ending chromosome
+     * @param readCount   the number of reads in each chromosome
+     * @param header      the associated header
+     */
+    ArtificialSAMIterator( int startingChr, int endingChr, int readCount, SAMFileHeader header ) {
+        sChr = startingChr;
+        eChromosomeCount = (endingChr - startingChr) + 1;
+        rCount = readCount;
+        this.header = header;
+        unmappedReadCount = 0;
+        reset();
+    }
+
+    protected void reset() {
+        this.currentChromo = 0;
+        this.currentRead = 1;
+        this.totalReadCount = 0;
+        this.done = false;
+        this.next = null;
+        this.initialized = false;
+        this.unmappedRemaining = unmappedReadCount;
+    }
+
+    /**
+     * create the fake iterator, given the mapping of chromosomes and read counts
+     *
+     * @param startingChr the starting chromosome
+     * @param endingChr   the ending chromosome
+     * @param readCount   the number of reads in each chromosome
+     * @param header      the associated header
+     */
+    ArtificialSAMIterator( int startingChr, int endingChr, int readCount, int unmappedReadCount, SAMFileHeader header ) {
+        sChr = startingChr;
+        eChromosomeCount = (endingChr - startingChr) + 1;
+        rCount = readCount;
+        this.header = header;
+        this.currentChromo = 0;
+        this.unmappedReadCount = unmappedReadCount;
+        reset();
+    }
+
+    public void close() {
+        open = false;
+    }
+
+    public boolean hasNext() {
+        open = true;
+
+        if (!initialized){
+            initialized = true;
+            createNextRead();
+        }
+        if (this.next != null) {
+            return true;
+        }
+        return false;
+    }
+
+    protected boolean createNextRead() {
+        if (currentRead > rCount) {
+            currentChromo++;
+            currentRead = 1;
+        }
+        // check for end condition, have we finished the chromosome listing, and have no unmapped reads
+        if (currentChromo >= eChromosomeCount) {
+            if (unmappedRemaining < 1) {
+                this.next = null;
+                return false;
+            } else {
+                ++totalReadCount;
+                this.next = ArtificialSAMUtils.createArtificialRead(this.header,
+                        String.valueOf(totalReadCount),
+                        SAMRecord.NO_ALIGNMENT_REFERENCE_INDEX,
+                        SAMRecord.NO_ALIGNMENT_START,
+                        50);
+                --unmappedRemaining;
+                return true;
+            }
+        }
+        ++totalReadCount;
+        this.next = ArtificialSAMUtils.createArtificialRead(this.header, String.valueOf(totalReadCount), currentChromo, currentRead, 50);
+        ++currentRead;
+        return true;
+    }
+
+
+    public SAMRecord next() {
+        open = true;        
+
+        SAMRecord ret = next;
+        createNextRead();
+        return ret;
+    }
+
+    public void remove() {
+        throw new UnsupportedOperationException("You've tried to remove on a GATKSAMIterator (unsupported), not to mention that this is a fake iterator.");
+    }
+
+    /**
+     * return this iterator, for the iterable interface
+     * @return
+     */
+    public Iterator<SAMRecord> iterator() {
+        return this;
+    }
+
+    /**
+     * some instrumentation methods
+     */
+    public int readsTaken() {
+        return totalReadCount;
+    }
+
+    /**
+     * peek at the next sam record
+     *
+     * @return
+     */
+    public SAMRecord peek() {
+        return this.next;
+    }
+}
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/sam/ArtificialSAMQueryIterator.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/sam/ArtificialSAMQueryIterator.java
new file mode 100644
index 0000000..fe7f7b0
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/sam/ArtificialSAMQueryIterator.java
@@ -0,0 +1,259 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.utils.sam;
+
+import htsjdk.samtools.SAMFileHeader;
+import htsjdk.samtools.SAMRecord;
+import htsjdk.samtools.SAMSequenceRecord;
+import org.broadinstitute.gatk.utils.exceptions.ReviewedGATKException;
+
+import java.util.List;
+
+
+/*
+ * 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.
+ */
+
+/**
+ * @author aaron
+ *
+ * allows query calls to the artificial sam iterator, which allows you
+ * to test out classes that use specific itervals.  The reads returned will
+ * all lie in order in the specified interval.
+ */
+public class ArtificialSAMQueryIterator extends ArtificialSAMIterator {
+
+    // get the next positon
+    protected int finalPos = 0;
+    protected int startPos = 0;
+    protected int contigIndex = -1;
+    protected boolean overlapping = false;
+    protected int startingChr = 0;
+    protected boolean seeked = false;
+
+    /**
+     * create the fake iterator, given the mapping of chromosomes and read counts
+     *
+     * @param startingChr the starting chromosome
+     * @param endingChr   the ending chromosome
+     * @param readCount   the number of reads in each chromosome
+     * @param header      the associated header
+     */
+    ArtificialSAMQueryIterator( int startingChr, int endingChr, int readCount, int unmappedReadCount, SAMFileHeader header ) {
+        super(startingChr, endingChr, readCount, unmappedReadCount, header);
+        this.startingChr = startingChr;
+    }
+
+    @Override
+    protected void reset() {
+        this.startPos = 0;
+        this.finalPos = 0;
+        this.contigIndex = -1;
+        // Doesn't make sense to reset the overlapping flag, because we rely on its state later on.
+        // TODO: Make this a bit more direct.
+        //overlapping = false;
+        this.startingChr = 0;
+        this.seeked = false;
+        super.reset();
+    }
+
+    /**
+     * query containing - get reads contained by the specified interval
+     *
+     * @param contig the contig index string
+     * @param start  the start position
+     * @param stop   the stop position
+     */
+    public void queryContained( String contig, int start, int stop ) {
+        this.overlapping = false;
+        initialize(contig, start, stop);
+    }
+
+    /**
+     * query containing - get reads contained by the specified interval
+     *
+     * @param contig the contig index string
+     * @param start  the start position
+     * @param stop   the stop position
+     */
+    public void queryOverlapping( String contig, int start, int stop ) {
+        this.overlapping = true;
+        initialize(contig, start, stop);
+    }
+
+    public void query( String contig, int start, int stop, boolean contained ) {
+        if (contained)
+            queryContained(contig, start, stop);
+        else
+            queryOverlapping(contig, start, stop);
+    }
+
+    public void queryUnmappedReads() {
+        initializeUnmapped();
+    }
+
+    /**
+     * initialize the iterator to an unmapped read position
+     */
+    public void initializeUnmapped() {
+        // throw away data from the previous invocation, if one exists.
+        ensureUntouched();
+        reset();
+
+        while (super.hasNext() && this.peek().getReferenceIndex() >= 0) {
+            super.next();
+        }
+        // sanity check that we have an actual matching read next
+        SAMRecord rec = this.peek();
+        if (rec == null) {
+            throw new ReviewedGATKException("The next read doesn't match");
+        }
+        // set the seeked variable to true
+        seeked = true;
+    }
+
+
+
+
+    /**
+     * initialize the query iterator
+     *
+     * @param contig the contig
+     * @param start  the start position
+     * @param stop   the stop postition
+     */
+    private void initialize( String contig, int start, int stop ) {
+        // throw away data from the previous invocation, if one exists.
+        ensureUntouched();
+        reset();
+
+        finalPos = stop;
+        startPos = start;
+        if (finalPos < 0) {
+            finalPos = Integer.MAX_VALUE;
+        }
+        // sanity check that we have the contig
+        contigIndex = -1;
+        List<SAMSequenceRecord> list = header.getSequenceDictionary().getSequences();
+        for (SAMSequenceRecord rec : list) {
+            if (rec.getSequenceName().equals(contig)) {
+                contigIndex = rec.getSequenceIndex();
+            }
+        }
+        if (contigIndex < 0) { throw new IllegalArgumentException("ArtificialContig" + contig + " doesn't exist"); }
+        while (super.hasNext() && this.peek().getReferenceIndex() < contigIndex) {
+            super.next();
+        }
+        if (!super.hasNext()) {
+            throw new ReviewedGATKException("Unable to find the target chromosome");
+        }
+        while (super.hasNext() && this.peek().getAlignmentStart() < start) {
+            super.next();
+        }
+        // sanity check that we have an actual matching read next
+        SAMRecord rec = this.peek();
+        if (!matches(rec)) {
+            throw new ReviewedGATKException("The next read doesn't match");
+        }
+        // set the seeked variable to true
+        seeked = true;
+    }
+
+    /**
+     * given a read and the query type, check if it matches our regions
+     *
+     * @param rec the read
+     *
+     * @return true if it belongs in our region
+     */
+    public boolean matches( SAMRecord rec ) {
+        if (rec.getReferenceIndex() != this.contigIndex) {
+            return false;
+        }
+        // if we have an unmapped read, matching the contig is good enough for us
+        if (rec.getReferenceIndex() < 0) {
+            return true;    
+        }
+
+        if (!overlapping) {
+            // if the start or the end are somewhere within our range
+            if (( rec.getAlignmentStart() >= startPos && rec.getAlignmentEnd() <= finalPos )) {
+                return true;
+            }
+        } else {
+            if (( rec.getAlignmentStart() <= finalPos && rec.getAlignmentStart() >= startPos ) ||
+                    ( rec.getAlignmentEnd() <= finalPos && rec.getAlignmentEnd() >= startPos )) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+
+    /**
+     * override the hasNext, to incorportate our limiting factor
+     *
+     * @return
+     */
+    public boolean hasNext() {
+        boolean res = super.hasNext();
+        if (!seeked) {
+            return res;
+        }
+        if (res && matches(this.next)) {
+            return true;
+        }
+        return false;
+    }
+
+    /** make sure we haven't been used as an iterator yet; this is to miror the MergingSamIterator2 action. */
+    public void ensureUntouched() {
+        if (open) {
+            throw new UnsupportedOperationException("We've already been used as an iterator; you can't query after that");
+        }
+    }
+}
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/sam/ArtificialSAMUtils.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/sam/ArtificialSAMUtils.java
new file mode 100644
index 0000000..7fb43ef
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/sam/ArtificialSAMUtils.java
@@ -0,0 +1,484 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.utils.sam;
+
+import htsjdk.samtools.*;
+import org.broadinstitute.gatk.engine.iterators.GATKSAMIterator;
+import org.broadinstitute.gatk.utils.GenomeLoc;
+import org.broadinstitute.gatk.utils.Utils;
+import org.broadinstitute.gatk.utils.exceptions.ReviewedGATKException;
+import org.broadinstitute.gatk.utils.locusiterator.LocusIteratorByState;
+import org.broadinstitute.gatk.utils.pileup.PileupElement;
+import org.broadinstitute.gatk.utils.pileup.ReadBackedPileup;
+import org.broadinstitute.gatk.utils.pileup.ReadBackedPileupImpl;
+
+import java.io.File;
+import java.util.*;
+
+/**
+ * @author aaron
+ * @version 1.0
+ */
+public class ArtificialSAMUtils {
+    public static final int DEFAULT_READ_LENGTH = 50;
+
+    /**
+     * create an artificial sam file
+     *
+     * @param filename            the filename to write to
+     * @param numberOfChromosomes the number of chromosomes
+     * @param startingChromosome  where to start counting
+     * @param chromosomeSize      how large each chromosome is
+     * @param readsPerChomosome   how many reads to make in each chromosome.  They'll be aligned from position 1 to x (which is the number of reads)
+     */
+    public static void createArtificialBamFile(String filename, int numberOfChromosomes, int startingChromosome, int chromosomeSize, int readsPerChomosome) {
+        SAMFileHeader header = createArtificialSamHeader(numberOfChromosomes, startingChromosome, chromosomeSize);
+        File outFile = new File(filename);
+
+        SAMFileWriter out = new SAMFileWriterFactory().makeBAMWriter(header, true, outFile);
+
+        for (int x = startingChromosome; x < startingChromosome + numberOfChromosomes; x++) {
+            for (int readNumber = 1; readNumber < readsPerChomosome; readNumber++) {
+                out.addAlignment(createArtificialRead(header, "Read_" + readNumber, x - startingChromosome, readNumber, DEFAULT_READ_LENGTH));
+            }
+        }
+
+        out.close();
+    }
+
+    /**
+     * create an artificial sam file
+     *
+     * @param filename            the filename to write to
+     * @param numberOfChromosomes the number of chromosomes
+     * @param startingChromosome  where to start counting
+     * @param chromosomeSize      how large each chromosome is
+     * @param readsPerChomosome   how many reads to make in each chromosome.  They'll be aligned from position 1 to x (which is the number of reads)
+     */
+    public static void createArtificialSamFile(String filename, int numberOfChromosomes, int startingChromosome, int chromosomeSize, int readsPerChomosome) {
+        SAMFileHeader header = createArtificialSamHeader(numberOfChromosomes, startingChromosome, chromosomeSize);
+        File outFile = new File(filename);
+
+        SAMFileWriter out = new SAMFileWriterFactory().makeSAMWriter(header, false, outFile);
+
+        for (int x = startingChromosome; x < startingChromosome + numberOfChromosomes; x++) {
+            for (int readNumber = 1; readNumber <= readsPerChomosome; readNumber++) {
+                out.addAlignment(createArtificialRead(header, "Read_" + readNumber, x - startingChromosome, readNumber, 100));
+            }
+        }
+
+        out.close();
+    }
+
+    /**
+     * Creates an artificial sam header, matching the parameters, chromosomes which will be labeled chr1, chr2, etc
+     *
+     * @param numberOfChromosomes the number of chromosomes to create
+     * @param startingChromosome  the starting number for the chromosome (most likely set to 1)
+     * @param chromosomeSize      the length of each chromosome
+     * @return
+     */
+    public static SAMFileHeader createArtificialSamHeader(int numberOfChromosomes, int startingChromosome, int chromosomeSize) {
+        SAMFileHeader header = new SAMFileHeader();
+        header.setSortOrder(htsjdk.samtools.SAMFileHeader.SortOrder.coordinate);
+        SAMSequenceDictionary dict = new SAMSequenceDictionary();
+        // make up some sequence records
+        for (int x = startingChromosome; x < startingChromosome + numberOfChromosomes; x++) {
+            SAMSequenceRecord rec = new SAMSequenceRecord("chr" + (x), chromosomeSize /* size */);
+            rec.setSequenceLength(chromosomeSize);
+            dict.addSequence(rec);
+        }
+        header.setSequenceDictionary(dict);
+        return header;
+    }
+
+    /**
+     * Creates an artificial sam header based on the sequence dictionary dict
+     *
+     * @return a new sam header
+     */
+    public static SAMFileHeader createArtificialSamHeader(final SAMSequenceDictionary dict) {
+        SAMFileHeader header = new SAMFileHeader();
+        header.setSortOrder(htsjdk.samtools.SAMFileHeader.SortOrder.coordinate);
+        header.setSequenceDictionary(dict);
+        return header;
+    }
+
+    /**
+     * Creates an artificial sam header with standard test parameters
+     *
+     * @return the sam header
+     */
+    public static SAMFileHeader createArtificialSamHeader() {
+        return createArtificialSamHeader(1, 1, 1000000);
+    }
+
+    /**
+     * setup a default read group for a SAMFileHeader
+     *
+     * @param header      the header to set
+     * @param readGroupID the read group ID tag
+     * @param sampleName  the sample name
+     * @return the adjusted SAMFileHeader
+     */
+    public static SAMFileHeader createDefaultReadGroup(SAMFileHeader header, String readGroupID, String sampleName) {
+        SAMReadGroupRecord rec = new SAMReadGroupRecord(readGroupID);
+        rec.setSample(sampleName);
+        List<SAMReadGroupRecord> readGroups = new ArrayList<SAMReadGroupRecord>();
+        readGroups.add(rec);
+        header.setReadGroups(readGroups);
+        return header;
+    }
+
+    /**
+     * setup read groups for the specified read groups and sample names
+     *
+     * @param header       the header to set
+     * @param readGroupIDs the read group ID tags
+     * @param sampleNames  the sample names
+     * @return the adjusted SAMFileHeader
+     */
+    public static SAMFileHeader createEnumeratedReadGroups(SAMFileHeader header, List<String> readGroupIDs, List<String> sampleNames) {
+        if (readGroupIDs.size() != sampleNames.size()) {
+            throw new ReviewedGATKException("read group count and sample name count must be the same");
+        }
+
+        List<SAMReadGroupRecord> readGroups = new ArrayList<SAMReadGroupRecord>();
+
+        int x = 0;
+        for (; x < readGroupIDs.size(); x++) {
+            SAMReadGroupRecord rec = new SAMReadGroupRecord(readGroupIDs.get(x));
+            rec.setSample(sampleNames.get(x));
+            readGroups.add(rec);
+        }
+        header.setReadGroups(readGroups);
+        return header;
+    }
+
+
+    /**
+     * Create an artificial read based on the parameters.  The cigar string will be *M, where * is the length of the read
+     *
+     * @param header         the SAM header to associate the read with
+     * @param name           the name of the read
+     * @param refIndex       the reference index, i.e. what chromosome to associate it with
+     * @param alignmentStart where to start the alignment
+     * @param length         the length of the read
+     * @return the artificial read
+     */
+    public static GATKSAMRecord createArtificialRead(SAMFileHeader header, String name, int refIndex, int alignmentStart, int length) {
+        if ((refIndex == SAMRecord.NO_ALIGNMENT_REFERENCE_INDEX && alignmentStart != SAMRecord.NO_ALIGNMENT_START) ||
+                (refIndex != SAMRecord.NO_ALIGNMENT_REFERENCE_INDEX && alignmentStart == SAMRecord.NO_ALIGNMENT_START))
+            throw new ReviewedGATKException("Invalid alignment start for artificial read, start = " + alignmentStart);
+        GATKSAMRecord record = new GATKSAMRecord(header);
+        record.setReadName(name);
+        record.setReferenceIndex(refIndex);
+        record.setAlignmentStart(alignmentStart);
+        List<CigarElement> elements = new ArrayList<CigarElement>();
+        elements.add(new CigarElement(length, CigarOperator.characterToEnum('M')));
+        record.setCigar(new Cigar(elements));
+        record.setProperPairFlag(false);
+
+        // our reads and quals are all 'A's by default
+        byte[] c = new byte[length];
+        byte[] q = new byte[length];
+        for (int x = 0; x < length; x++)
+            c[x] = q[x] = 'A';
+        record.setReadBases(c);
+        record.setBaseQualities(q);
+
+        if (refIndex == SAMRecord.NO_ALIGNMENT_REFERENCE_INDEX) {
+            record.setReadUnmappedFlag(true);
+        }
+
+        return record;
+    }
+
+    /**
+     * Create an artificial read based on the parameters.  The cigar string will be *M, where * is the length of the read
+     *
+     * @param header         the SAM header to associate the read with
+     * @param name           the name of the read
+     * @param refIndex       the reference index, i.e. what chromosome to associate it with
+     * @param alignmentStart where to start the alignment
+     * @param bases          the sequence of the read
+     * @param qual           the qualities of the read
+     * @return the artificial read
+     */
+    public static GATKSAMRecord createArtificialRead(SAMFileHeader header, String name, int refIndex, int alignmentStart, byte[] bases, byte[] qual) {
+        if (bases.length != qual.length) {
+            throw new ReviewedGATKException("Passed in read string is different length then the quality array");
+        }
+        GATKSAMRecord rec = createArtificialRead(header, name, refIndex, alignmentStart, bases.length);
+        rec.setReadBases(bases);
+        rec.setBaseQualities(qual);
+        rec.setReadGroup(new GATKSAMReadGroupRecord("x"));
+        if (refIndex == -1) {
+            rec.setReadUnmappedFlag(true);
+        }
+
+        return rec;
+    }
+
+    /**
+     * Create an artificial read based on the parameters
+     *
+     * @param header         the SAM header to associate the read with
+     * @param name           the name of the read
+     * @param refIndex       the reference index, i.e. what chromosome to associate it with
+     * @param alignmentStart where to start the alignment
+     * @param bases          the sequence of the read
+     * @param qual           the qualities of the read
+     * @param cigar          the cigar string of the read
+     * @return the artificial read
+     */
+    public static GATKSAMRecord createArtificialRead(SAMFileHeader header, String name, int refIndex, int alignmentStart, byte[] bases, byte[] qual, String cigar) {
+        GATKSAMRecord rec = createArtificialRead(header, name, refIndex, alignmentStart, bases, qual);
+        rec.setCigarString(cigar);
+        return rec;
+    }
+
+    /**
+     * Create an artificial read with the following default parameters :
+     * header:
+     * numberOfChromosomes = 1
+     * startingChromosome = 1
+     * chromosomeSize = 1000000
+     * read:
+     * name = "default_read"
+     * refIndex = 0
+     * alignmentStart = 1
+     *
+     * @param bases the sequence of the read
+     * @param qual  the qualities of the read
+     * @param cigar the cigar string of the read
+     * @return the artificial read
+     */
+    public static GATKSAMRecord createArtificialRead(byte[] bases, byte[] qual, String cigar) {
+        SAMFileHeader header = ArtificialSAMUtils.createArtificialSamHeader();
+        return ArtificialSAMUtils.createArtificialRead(header, "default_read", 0, 10000, bases, qual, cigar);
+    }
+
+    public static GATKSAMRecord createArtificialRead(Cigar cigar) {
+        int length = cigar.getReadLength();
+        byte [] base = {'A'};
+        byte [] qual = {30};
+        byte [] bases = Utils.arrayFromArrayWithLength(base, length);
+        byte [] quals = Utils.arrayFromArrayWithLength(qual, length);
+        SAMFileHeader header = ArtificialSAMUtils.createArtificialSamHeader();
+        return ArtificialSAMUtils.createArtificialRead(header, "default_read", 0, 10000, bases, quals, cigar.toString());
+    }
+
+    
+    public final static List<GATKSAMRecord> createPair(SAMFileHeader header, String name, int readLen, int leftStart, int rightStart, boolean leftIsFirst, boolean leftIsNegative) {
+        GATKSAMRecord left = ArtificialSAMUtils.createArtificialRead(header, name, 0, leftStart, readLen);
+        GATKSAMRecord right = ArtificialSAMUtils.createArtificialRead(header, name, 0, rightStart, readLen);
+
+        left.setReadPairedFlag(true);
+        right.setReadPairedFlag(true);
+
+        left.setProperPairFlag(true);
+        right.setProperPairFlag(true);
+
+        left.setFirstOfPairFlag(leftIsFirst);
+        right.setFirstOfPairFlag(!leftIsFirst);
+
+        left.setReadNegativeStrandFlag(leftIsNegative);
+        left.setMateNegativeStrandFlag(!leftIsNegative);
+        right.setReadNegativeStrandFlag(!leftIsNegative);
+        right.setMateNegativeStrandFlag(leftIsNegative);
+
+        left.setMateAlignmentStart(right.getAlignmentStart());
+        right.setMateAlignmentStart(left.getAlignmentStart());
+
+        left.setMateReferenceIndex(0);
+        right.setMateReferenceIndex(0);
+
+        int isize = rightStart + readLen - leftStart;
+        left.setInferredInsertSize(isize);
+        right.setInferredInsertSize(-isize);
+
+        return Arrays.asList(left, right);
+    }
+
+    /**
+     * Create a collection of identical artificial reads based on the parameters.  The cigar string for each
+     * read will be *M, where * is the length of the read.
+     *
+     * Useful for testing things like positional downsampling where you care only about the position and
+     * number of reads, and not the other attributes.
+     *
+     * @param stackSize      number of identical reads to create
+     * @param header         the SAM header to associate each read with
+     * @param name           name associated with each read
+     * @param refIndex       the reference index, i.e. what chromosome to associate them with
+     * @param alignmentStart where to start each alignment
+     * @param length         the length of each read
+     *
+     * @return a collection of stackSize reads all sharing the above properties
+     */
+    public static Collection<GATKSAMRecord> createStackOfIdenticalArtificialReads( int stackSize, SAMFileHeader header, String name, int refIndex, int alignmentStart, int length ) {
+        Collection<GATKSAMRecord> stack = new ArrayList<GATKSAMRecord>(stackSize);
+        for ( int i = 1; i <= stackSize; i++ ) {
+            stack.add(createArtificialRead(header, name, refIndex, alignmentStart, length));
+        }
+        return stack;
+    }
+
+    /**
+     * create an iterator containing the specified read piles
+     *
+     * @param startingChr the chromosome (reference ID) to start from
+     * @param endingChr   the id to end with
+     * @param readCount   the number of reads per chromosome
+     * @return GATKSAMIterator representing the specified amount of fake data
+     */
+    public static GATKSAMIterator mappedReadIterator(int startingChr, int endingChr, int readCount) {
+        SAMFileHeader header = createArtificialSamHeader((endingChr - startingChr) + 1, startingChr, readCount + DEFAULT_READ_LENGTH);
+
+        return new ArtificialSAMQueryIterator(startingChr, endingChr, readCount, 0, header);
+    }
+
+    /**
+     * create an iterator containing the specified read piles
+     *
+     * @param startingChr       the chromosome (reference ID) to start from
+     * @param endingChr         the id to end with
+     * @param readCount         the number of reads per chromosome
+     * @param unmappedReadCount the count of unmapped reads to place at the end of the iterator, like in a sorted bam file
+     * @return GATKSAMIterator representing the specified amount of fake data
+     */
+    public static GATKSAMIterator mappedAndUnmappedReadIterator(int startingChr, int endingChr, int readCount, int unmappedReadCount) {
+        SAMFileHeader header = createArtificialSamHeader((endingChr - startingChr) + 1, startingChr, readCount + DEFAULT_READ_LENGTH);
+
+        return new ArtificialSAMQueryIterator(startingChr, endingChr, readCount, unmappedReadCount, header);
+    }
+
+    /**
+     * create an ArtificialSAMQueryIterator containing the specified read piles
+     *
+     * @param startingChr the chromosome (reference ID) to start from
+     * @param endingChr   the id to end with
+     * @param readCount   the number of reads per chromosome
+     * @return GATKSAMIterator representing the specified amount of fake data
+     */
+    public static ArtificialSAMQueryIterator queryReadIterator(int startingChr, int endingChr, int readCount) {
+        SAMFileHeader header = createArtificialSamHeader((endingChr - startingChr) + 1, startingChr, readCount + DEFAULT_READ_LENGTH);
+
+        return new ArtificialSAMQueryIterator(startingChr, endingChr, readCount, 0, header);
+    }
+
+    /**
+     * create an ArtificialSAMQueryIterator containing the specified read piles
+     *
+     * @param startingChr       the chromosome (reference ID) to start from
+     * @param endingChr         the id to end with
+     * @param readCount         the number of reads per chromosome
+     * @param unmappedReadCount the count of unmapped reads to place at the end of the iterator, like in a sorted bam file
+     * @return GATKSAMIterator representing the specified amount of fake data
+     */
+    public static GATKSAMIterator queryReadIterator(int startingChr, int endingChr, int readCount, int unmappedReadCount) {
+        SAMFileHeader header = createArtificialSamHeader((endingChr - startingChr) + 1, startingChr, readCount + DEFAULT_READ_LENGTH);
+
+        return new ArtificialSAMQueryIterator(startingChr, endingChr, readCount, unmappedReadCount, header);
+    }
+
+    /**
+     * Create an iterator containing the specified reads
+     *
+     * @param reads the reads
+     * @return iterator for the reads
+     */
+    public static GATKSAMIterator createReadIterator(SAMRecord... reads) {
+        return createReadIterator(Arrays.asList(reads));
+    }
+
+    /**
+     * Create an iterator containing the specified reads
+     *
+     * @param reads the reads
+     * @return iterator for the reads
+     */
+    public static GATKSAMIterator createReadIterator(List<SAMRecord> reads) {
+        final Iterator<SAMRecord> iter = reads.iterator();
+        return new GATKSAMIterator() {
+            @Override public void close() {}
+            @Override public Iterator<SAMRecord> iterator() { return iter; }
+            @Override public boolean hasNext() { return iter.hasNext(); }
+            @Override public SAMRecord next() { return iter.next(); }
+            @Override public void remove() { iter.remove(); }
+        };
+    }
+
+    private final static int ranIntInclusive(Random ran, int start, int stop) {
+        final int range = stop - start;
+        return ran.nextInt(range) + start;
+    }
+
+    /**
+     * Creates a read backed pileup containing up to pileupSize reads at refID 0 from header at loc with
+     * reads created that have readLen bases.  Pairs are sampled from a gaussian distribution with mean insert
+     * size of insertSize and variation of insertSize / 10.  The first read will be in the pileup, and the second
+     * may be, depending on where this sampled insertSize puts it.
+     *
+     * @param header
+     * @param loc
+     * @param readLen
+     * @param insertSize
+     * @param pileupSize
+     * @return
+     */
+    public static ReadBackedPileup createReadBackedPileup(final SAMFileHeader header, final GenomeLoc loc, final int readLen, final int insertSize, final int pileupSize) {
+        final Random ran = new Random();
+        final boolean leftIsFirst = true;
+        final boolean leftIsNegative = false;
+        final int insertSizeVariation = insertSize / 10;
+        final int pos = loc.getStart();
+
+        final List<PileupElement> pileupElements = new ArrayList<PileupElement>();
+        for (int i = 0; i < pileupSize / 2; i++) {
+            final String readName = "read" + i;
+            final int leftStart = ranIntInclusive(ran, 1, pos);
+            final int fragmentSize = (int) (ran.nextGaussian() * insertSizeVariation + insertSize);
+            final int rightStart = leftStart + fragmentSize - readLen;
+
+            if (rightStart <= 0) continue;
+
+            List<GATKSAMRecord> pair = createPair(header, readName, readLen, leftStart, rightStart, leftIsFirst, leftIsNegative);
+            final GATKSAMRecord left = pair.get(0);
+            final GATKSAMRecord right = pair.get(1);
+
+            pileupElements.add(LocusIteratorByState.createPileupForReadAndOffset(left, pos - leftStart));
+
+            if (pos >= right.getAlignmentStart() && pos <= right.getAlignmentEnd()) {
+                pileupElements.add(LocusIteratorByState.createPileupForReadAndOffset(right, pos - rightStart));
+            }
+        }
+
+        Collections.sort(pileupElements);
+        return new ReadBackedPileupImpl(loc, pileupElements);
+    }
+}
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/sam/ArtificialSingleSampleReadStream.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/sam/ArtificialSingleSampleReadStream.java
new file mode 100644
index 0000000..27e25d3
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/sam/ArtificialSingleSampleReadStream.java
@@ -0,0 +1,213 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.utils.sam;
+
+import htsjdk.samtools.SAMFileHeader;
+import htsjdk.samtools.SAMRecord;
+import org.broadinstitute.gatk.engine.iterators.GATKSAMIterator;
+import org.broadinstitute.gatk.engine.iterators.GATKSAMIteratorAdapter;
+import org.broadinstitute.gatk.utils.MathUtils;
+import org.broadinstitute.gatk.utils.exceptions.ReviewedGATKException;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Iterator;
+
+/**
+ * An artificial stream of reads from a single read group/sample with configurable characteristics
+ * such as:
+ *
+ * -the number of contigs that the reads should be distributed across
+ * -number of "stacks" of reads sharing the same alignment start position per contig
+ * -the min/max number of reads in each stack (exact values chosen randomly from this range)
+ * -the min/max distance between stack start positions (exact values chosen randomly from this range)
+ * -the min/max length of each read (exact values chosen randomly from this range)
+ * -the number of unmapped reads
+ *
+ * The cigar string for all reads will be *M, where * is the length of the read.
+ *
+ * @author David Roazen
+ */
+public class ArtificialSingleSampleReadStream implements Iterable<SAMRecord> {
+    private SAMFileHeader header;
+    private String readGroupID;
+    private int numContigs;
+    private int numStacksPerContig;
+    private int minReadsPerStack;
+    private int maxReadsPerStack;
+    private int minDistanceBetweenStacks;
+    private int maxDistanceBetweenStacks;
+    private int minReadLength;
+    private int maxReadLength;
+    private int numUnmappedReads;
+
+    private static final String READ_GROUP_TAG = "RG";
+
+    public ArtificialSingleSampleReadStream( SAMFileHeader header,
+                                             String readGroupID,
+                                             int numContigs,
+                                             int numStacksPerContig,
+                                             int minReadsPerStack,
+                                             int maxReadsPerStack,
+                                             int minDistanceBetweenStacks,
+                                             int maxDistanceBetweenStacks,
+                                             int minReadLength,
+                                             int maxReadLength,
+                                             int numUnmappedReads ) {
+        this.header = header;
+        this.readGroupID = readGroupID;
+        this.numContigs = numContigs;
+        this.numStacksPerContig = numStacksPerContig;
+        this.minReadsPerStack = minReadsPerStack;
+        this.maxReadsPerStack = maxReadsPerStack;
+        this.minDistanceBetweenStacks = minDistanceBetweenStacks;
+        this.maxDistanceBetweenStacks = maxDistanceBetweenStacks;
+        this.minReadLength = minReadLength;
+        this.maxReadLength = maxReadLength;
+        this.numUnmappedReads = numUnmappedReads;
+
+        validateStreamParameters();
+    }
+
+    private void validateStreamParameters() {
+        if ( header == null || readGroupID == null ) {
+            throw new ReviewedGATKException("null SAMFileHeader or read group ID") ;
+        }
+
+        if ( header.getReadGroup(readGroupID) == null ) {
+            throw new ReviewedGATKException(String.format("Read group %s not found in SAMFileHeader", readGroupID));
+        }
+
+        if ( numContigs < 0 || numStacksPerContig < 0 || minReadsPerStack < 0 || maxReadsPerStack < 0 ||
+             minDistanceBetweenStacks < 0 || maxDistanceBetweenStacks < 0 || minReadLength < 0 || maxReadLength < 0 ||
+             numUnmappedReads < 0 ) {
+            throw new ReviewedGATKException("Read stream parameters must be >= 0");
+        }
+
+        if ( (numContigs == 0 && numStacksPerContig != 0) || (numContigs != 0 && numStacksPerContig == 0) ) {
+            throw new ReviewedGATKException("numContigs and numStacksPerContig must either both be > 0, or both be 0");
+        }
+
+        if ( minReadsPerStack > maxReadsPerStack ) {
+            throw new ReviewedGATKException("minReadsPerStack > maxReadsPerStack");
+        }
+
+        if ( minDistanceBetweenStacks > maxDistanceBetweenStacks ) {
+            throw new ReviewedGATKException("minDistanceBetweenStacks > maxDistanceBetweenStacks");
+        }
+
+        if ( minReadLength > maxReadLength ) {
+            throw new ReviewedGATKException("minReadLength > maxReadLength");
+        }
+    }
+
+    public Iterator<SAMRecord> iterator() {
+        return makeReads().iterator();
+    }
+
+    public GATKSAMIterator getGATKSAMIterator() {
+        return GATKSAMIteratorAdapter.adapt(iterator());
+    }
+
+    public Collection<SAMRecord> makeReads() {
+        Collection<SAMRecord> reads = new ArrayList<SAMRecord>(numContigs * numStacksPerContig * maxReadsPerStack);
+
+        for ( int contig = 0; contig < numContigs; contig++ ) {
+            int alignmentStart = 1;
+
+            for ( int stack = 0; stack < numStacksPerContig; stack++ ) {
+                reads.addAll(makeReadStack(contig, alignmentStart, MathUtils.randomIntegerInRange(minReadsPerStack, maxReadsPerStack)));
+                alignmentStart += MathUtils.randomIntegerInRange(minDistanceBetweenStacks, maxDistanceBetweenStacks);
+            }
+        }
+
+        if ( numUnmappedReads > 0 ) {
+            reads.addAll(makeReadStack(SAMRecord.NO_ALIGNMENT_REFERENCE_INDEX, SAMRecord.NO_ALIGNMENT_START, numUnmappedReads));
+        }
+
+        return reads;
+    }
+
+    private Collection<SAMRecord> makeReadStack( int contig, int alignmentStart, int stackSize ) {
+        Collection<SAMRecord> readStack = new ArrayList<SAMRecord>(stackSize);
+
+        for ( int i = 0; i < stackSize; i++ ) {
+            SAMRecord read = ArtificialSAMUtils.createArtificialRead(header,
+                                                                     "foo",
+                                                                     contig,
+                                                                     alignmentStart,
+                                                                     MathUtils.randomIntegerInRange(minReadLength, maxReadLength));
+            read.setAttribute(READ_GROUP_TAG, readGroupID);
+            readStack.add(read);
+        }
+
+        return readStack;
+    }
+
+    public SAMFileHeader getHeader() {
+        return header;
+    }
+
+    public String getReadGroupID() {
+        return readGroupID;
+    }
+
+    public int getNumContigs() {
+        return numContigs;
+    }
+
+    public int getNumStacksPerContig() {
+        return numStacksPerContig;
+    }
+
+    public int getMinReadsPerStack() {
+        return minReadsPerStack;
+    }
+
+    public int getMaxReadsPerStack() {
+        return maxReadsPerStack;
+    }
+
+    public int getMinDistanceBetweenStacks() {
+        return minDistanceBetweenStacks;
+    }
+
+    public int getMaxDistanceBetweenStacks() {
+        return maxDistanceBetweenStacks;
+    }
+
+    public int getMinReadLength() {
+        return minReadLength;
+    }
+
+    public int getMaxReadLength() {
+        return maxReadLength;
+    }
+
+    public int getNumUnmappedReads() {
+        return numUnmappedReads;
+    }
+}
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/sam/ArtificialSingleSampleReadStreamAnalyzer.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/sam/ArtificialSingleSampleReadStreamAnalyzer.java
new file mode 100644
index 0000000..196fa71
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/sam/ArtificialSingleSampleReadStreamAnalyzer.java
@@ -0,0 +1,282 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.utils.sam;
+
+import htsjdk.samtools.SAMRecord;
+import org.broadinstitute.gatk.utils.exceptions.ReviewedGATKException;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * A class for analyzing and validating the read stream produced by an ArtificialSingleSampleReadStream.
+ *
+ * Collects various statistics about the stream of reads it's fed, and validates the stream
+ * by checking whether the collected statistics match the nominal properties of the stream.
+ *
+ * Subclasses are expected to override the validate() method in order to check whether an artificial
+ * read stream has been *transformed* in some way (eg., by downsampling or some other process), rather
+ * than merely checking whether the stream matches its original properties.
+ *
+ * Usage is simple:
+ *
+ * ArtificialSingleSampleReadStreamAnalyzer analyzer = new ArtificialSingleSampleReadStreamAnalyzer(originalStream);
+ * analyzer.analyze(originalOrTransformedStream);
+ * analyzer.validate();  // override this method if you want to check whether the stream has been transformed
+ *                       // in a certain way relative to the original stream
+ *
+ * @author David Roazen
+ */
+public class ArtificialSingleSampleReadStreamAnalyzer {
+    protected ArtificialSingleSampleReadStream originalStream;
+    protected SAMRecord lastRead;
+    protected int totalReads;
+    protected boolean allSamplesMatch;
+    protected int numContigs;
+    protected List<Integer> stacksPerContig;
+    protected Integer minReadsPerStack;
+    protected Integer maxReadsPerStack;
+    protected Integer minDistanceBetweenStacks;
+    protected Integer maxDistanceBetweenStacks;
+    protected Integer minReadLength;
+    protected Integer maxReadLength;
+    protected int numUnmappedReads;
+
+    protected int currentContigNumStacks;
+    protected int currentStackNumReads;
+
+    /**
+     * Construct a new read stream analyzer, providing an ArtificialSingleSampleReadStream that will
+     * serve as the basis for comparison after the analysis is complete.
+     *
+     * @param originalStream the original ArtificialSingleSampleReadStream upon which the stream
+     *                       that will be fed to the analyzer is based
+     */
+    public ArtificialSingleSampleReadStreamAnalyzer( ArtificialSingleSampleReadStream originalStream ) {
+        this.originalStream = originalStream;
+        reset();
+    }
+
+    /**
+     * Reset all read stream statistics collected by this analyzer to prepare for a fresh run
+     */
+    public void reset() {
+        lastRead = null;
+        totalReads = 0;
+        allSamplesMatch = true;
+        numContigs = 0;
+        stacksPerContig = new ArrayList<Integer>();
+        minReadsPerStack = null;
+        maxReadsPerStack = null;
+        minDistanceBetweenStacks = null;
+        maxDistanceBetweenStacks = null;
+        minReadLength = null;
+        maxReadLength = null;
+        numUnmappedReads = 0;
+        currentContigNumStacks = 0;
+        currentStackNumReads = 0;
+    }
+
+    /**
+     * Collect statistics on the stream of reads passed in
+     *
+     * @param stream the stream of reads to analyze
+     */
+    public void analyze( Iterable<SAMRecord> stream ) {
+        for ( SAMRecord read : stream ) {
+            update(read);
+        }
+        finalizeStats();
+    }
+
+    /**
+     * Validate the stream by checking whether our collected statistics match the properties of the
+     * original stream. Throws a ReviewedGATKException if the stream is invalid.
+     *
+     * Override this method if you want to check whether the stream has been transformed in some
+     * way relative to the original stream.
+     */
+    public void validate() {
+        if ( (originalStream.getNumContigs() == 0 || originalStream.getNumStacksPerContig() == 0) && originalStream.getNumUnmappedReads() == 0 ) {
+            if ( totalReads != 0 ) {
+                throw new ReviewedGATKException("got reads from the stream, but the stream was configured to have 0 reads");
+            }
+            return;  // no further validation needed for the 0-reads case
+        }
+        else if ( totalReads == 0 ) {
+            throw new ReviewedGATKException("got no reads from the stream, but the stream was configured to have > 0 reads");
+        }
+
+        if ( ! allSamplesMatch ) {
+            throw new ReviewedGATKException("some reads had the wrong sample");
+        }
+
+        if ( numContigs != originalStream.getNumContigs() ) {
+            throw new ReviewedGATKException("number of contigs not correct");
+        }
+
+        if ( stacksPerContig.size() != originalStream.getNumContigs() ) {
+            throw new ReviewedGATKException(String.format("bug in analyzer code: calculated sizes for %d contigs even though there were only %d contigs",
+                                                           stacksPerContig.size(), originalStream.getNumContigs()));
+        }
+
+        for ( int contigStackCount : stacksPerContig ) {
+            if ( contigStackCount != originalStream.getNumStacksPerContig() ) {
+                throw new ReviewedGATKException("contig had incorrect number of stacks");
+            }
+        }
+
+        if ( originalStream.getNumStacksPerContig() > 0 ) {
+            if ( minReadsPerStack < originalStream.getMinReadsPerStack() ) {
+                throw new ReviewedGATKException("stack had fewer than the minimum number of reads");
+            }
+            if ( maxReadsPerStack > originalStream.getMaxReadsPerStack() ) {
+                throw new ReviewedGATKException("stack had more than the maximum number of reads");
+            }
+        }
+        else if ( minReadsPerStack != null || maxReadsPerStack != null ) {
+            throw new ReviewedGATKException("bug in analyzer code: reads per stack was calculated even though 0 stacks per contig was specified");
+        }
+
+        if ( originalStream.getNumStacksPerContig() > 1 ) {
+            if ( minDistanceBetweenStacks < originalStream.getMinDistanceBetweenStacks() ) {
+                throw new ReviewedGATKException("stacks were separated by less than the minimum distance");
+            }
+            if ( maxDistanceBetweenStacks > originalStream.getMaxDistanceBetweenStacks() ) {
+                throw new ReviewedGATKException("stacks were separated by more than the maximum distance");
+            }
+        }
+        else if ( minDistanceBetweenStacks != null || maxDistanceBetweenStacks != null ) {
+            throw new ReviewedGATKException("bug in analyzer code: distance between stacks was calculated even though numStacksPerContig was <= 1");
+        }
+
+        if ( minReadLength < originalStream.getMinReadLength() ) {
+            throw new ReviewedGATKException("read was shorter than the minimum allowed length");
+        }
+        if ( maxReadLength > originalStream.getMaxReadLength() ) {
+            throw new ReviewedGATKException("read was longer than the maximum allowed length");
+        }
+
+        if ( numUnmappedReads != originalStream.getNumUnmappedReads() ) {
+            throw new ReviewedGATKException(String.format("wrong number of unmapped reads: requested %d but saw %d",
+                                                           originalStream.getNumUnmappedReads(), numUnmappedReads));
+        }
+
+        if ( (originalStream.getNumContigs() == 0 || originalStream.getNumStacksPerContig() == 0) &&
+             numUnmappedReads != totalReads ) {
+            throw new ReviewedGATKException("stream should have consisted only of unmapped reads, but saw some mapped reads");
+        }
+    }
+
+    public void update( SAMRecord read ) {
+        if ( read.getReadUnmappedFlag() ) {
+            numUnmappedReads++;
+
+            if ( numUnmappedReads == 1 && lastRead != null ) {
+                processContigChange();
+                numContigs--;
+            }
+        }
+        else if ( lastRead == null ) {
+            numContigs = 1;
+            currentContigNumStacks = 1;
+            currentStackNumReads = 1;
+        }
+        else if ( ! read.getReferenceIndex().equals(lastRead.getReferenceIndex()) ) {
+            processContigChange();
+        }
+        else if ( read.getAlignmentStart() != lastRead.getAlignmentStart() ) {
+            processStackChangeWithinContig(read);
+        }
+        else {
+            currentStackNumReads++;
+        }
+
+        updateReadLength(read.getReadLength());
+        allSamplesMatch = allSamplesMatch && readHasCorrectSample(read);
+        totalReads++;
+
+        lastRead = read;
+    }
+
+
+    private void processContigChange() {
+        numContigs++;
+
+        stacksPerContig.add(currentContigNumStacks);
+        currentContigNumStacks = 1;
+
+        updateReadsPerStack(currentStackNumReads);
+        currentStackNumReads = 1;
+    }
+
+    private void processStackChangeWithinContig( SAMRecord read ) {
+        currentContigNumStacks++;
+
+        updateReadsPerStack(currentStackNumReads);
+        currentStackNumReads = 1;
+
+        updateDistanceBetweenStacks(read.getAlignmentStart() - lastRead.getAlignmentStart());
+    }
+
+    private void updateReadsPerStack( int stackReadCount ) {
+        if ( minReadsPerStack == null || stackReadCount < minReadsPerStack ) {
+            minReadsPerStack = stackReadCount;
+        }
+        if ( maxReadsPerStack == null || stackReadCount > maxReadsPerStack ) {
+            maxReadsPerStack = stackReadCount;
+        }
+    }
+
+    private void updateDistanceBetweenStacks( int stackDistance ) {
+        if ( minDistanceBetweenStacks == null || stackDistance < minDistanceBetweenStacks ) {
+            minDistanceBetweenStacks = stackDistance;
+        }
+        if ( maxDistanceBetweenStacks == null || stackDistance > maxDistanceBetweenStacks ) {
+            maxDistanceBetweenStacks = stackDistance;
+        }
+    }
+
+    private void updateReadLength( int readLength ) {
+        if ( minReadLength == null || readLength < minReadLength ) {
+            minReadLength = readLength;
+        }
+        if ( maxReadLength == null || readLength > maxReadLength ) {
+            maxReadLength = readLength;
+        }
+    }
+
+    private boolean readHasCorrectSample( SAMRecord read ) {
+        return originalStream.getReadGroupID().equals(read.getAttribute("RG"));
+    }
+
+    public void finalizeStats() {
+        if ( lastRead != null && ! lastRead.getReadUnmappedFlag() ) {
+            stacksPerContig.add(currentContigNumStacks);
+            updateReadsPerStack(currentStackNumReads);
+        }
+    }
+}
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/sam/BySampleSAMFileWriter.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/sam/BySampleSAMFileWriter.java
new file mode 100644
index 0000000..e212bd9
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/sam/BySampleSAMFileWriter.java
@@ -0,0 +1,70 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.utils.sam;
+
+import htsjdk.samtools.SAMFileHeader;
+import htsjdk.samtools.SAMProgramRecord;
+import htsjdk.samtools.SAMReadGroupRecord;
+import htsjdk.samtools.SAMRecord;
+import org.broadinstitute.gatk.engine.GenomeAnalysisEngine;
+import org.broadinstitute.gatk.engine.datasources.reads.SAMReaderID;
+import org.broadinstitute.gatk.utils.exceptions.ReviewedGATKException;
+
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * Created by IntelliJ IDEA.
+ * User: carneiro
+ * Date: Nov 13
+ */
+public class BySampleSAMFileWriter extends NWaySAMFileWriter{
+
+    private final Map<String, SAMReaderID> sampleToWriterMap;
+
+    public BySampleSAMFileWriter(GenomeAnalysisEngine toolkit, String ext, SAMFileHeader.SortOrder order, boolean presorted, boolean indexOnTheFly, boolean generateMD5, SAMProgramRecord pRecord, boolean keep_records) {
+        super(toolkit, ext, order, presorted, indexOnTheFly, generateMD5, pRecord, keep_records);
+
+        sampleToWriterMap = new HashMap<String, SAMReaderID>(toolkit.getSAMFileHeader().getReadGroups().size() * 2);
+
+        for (SAMReaderID readerID : toolkit.getReadsDataSource().getReaderIDs()) {
+            for (SAMReadGroupRecord rg : toolkit.getReadsDataSource().getHeader(readerID).getReadGroups()) {
+                String sample = rg.getSample();
+                if (sampleToWriterMap.containsKey(sample) && sampleToWriterMap.get(sample) != readerID) {
+                    throw new ReviewedGATKException("The same sample appears in multiple files, this input cannot be multiplexed using the BySampleSAMFileWriter, try NWaySAMFileWriter instead.");
+                }
+                else {
+                    sampleToWriterMap.put(sample, readerID);
+                }
+            }
+        }
+    }
+
+    @Override
+    public void addAlignment(SAMRecord samRecord) {
+        super.addAlignment(samRecord, sampleToWriterMap.get(samRecord.getReadGroup().getSample()));
+    }
+}
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/sam/CigarUtils.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/sam/CigarUtils.java
new file mode 100644
index 0000000..cd492fe
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/sam/CigarUtils.java
@@ -0,0 +1,273 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.utils.sam;
+
+import com.google.java.contract.Ensures;
+import htsjdk.samtools.Cigar;
+import htsjdk.samtools.CigarElement;
+import htsjdk.samtools.CigarOperator;
+import htsjdk.samtools.TextCigarCodec;
+import org.broadinstitute.gatk.utils.exceptions.ReviewedGATKException;
+import org.broadinstitute.gatk.utils.smithwaterman.Parameters;
+import org.broadinstitute.gatk.utils.smithwaterman.SWPairwiseAlignment;
+import org.broadinstitute.gatk.utils.smithwaterman.SmithWaterman;
+
+import java.util.Arrays;
+import java.util.Stack;
+
+/**
+ * Created with IntelliJ IDEA.
+ * User: ami
+ * Date: 11/26/13
+ * Time: 11:33 AM
+ * To change this template use File | Settings | File Templates.
+ */
+public class CigarUtils {
+
+    /**
+     * Combines equal adjacent elements of a Cigar object
+     *
+     * @param rawCigar the cigar object
+     * @return a combined cigar object
+     */
+    public static Cigar combineAdjacentCigarElements(Cigar rawCigar) {
+        Cigar combinedCigar = new Cigar();
+        CigarElement lastElement = null;
+        int lastElementLength = 0;
+        for (CigarElement cigarElement : rawCigar.getCigarElements()) {
+            if (lastElement != null &&
+                    ((lastElement.getOperator() == cigarElement.getOperator()) ||
+                            (lastElement.getOperator() == CigarOperator.I && cigarElement.getOperator() == CigarOperator.D) ||
+                            (lastElement.getOperator() == CigarOperator.D && cigarElement.getOperator() == CigarOperator.I)))
+                lastElementLength += cigarElement.getLength();
+            else
+            {
+                if (lastElement != null)
+                    combinedCigar.add(new CigarElement(lastElementLength, lastElement.getOperator()));
+
+                lastElement = cigarElement;
+                lastElementLength = cigarElement.getLength();
+            }
+        }
+        if (lastElement != null)
+            combinedCigar.add(new CigarElement(lastElementLength, lastElement.getOperator()));
+
+        return combinedCigar;
+    }
+
+    public static Cigar invertCigar (Cigar cigar) {
+        Stack<CigarElement> cigarStack = new Stack<CigarElement>();
+        for (CigarElement cigarElement : cigar.getCigarElements())
+            cigarStack.push(cigarElement);
+
+        Cigar invertedCigar = new Cigar();
+        while (!cigarStack.isEmpty())
+            invertedCigar.add(cigarStack.pop());
+
+        return invertedCigar;
+    }
+
+    /**
+     * Checks whether or not the read has any cigar element that is not H or S
+     *
+     * @param read the read
+     * @return true if it has any M, I or D, false otherwise
+     */
+    public static boolean readHasNonClippedBases(GATKSAMRecord read) {
+        for (CigarElement cigarElement : read.getCigar().getCigarElements())
+            if (cigarElement.getOperator() != CigarOperator.SOFT_CLIP && cigarElement.getOperator() != CigarOperator.HARD_CLIP)
+                return true;
+        return false;
+    }
+
+    public static Cigar cigarFromString(String cigarString) {
+        return TextCigarCodec.getSingleton().decode(cigarString);
+    }
+
+    /**
+    * A valid cigar object obeys the following rules:
+    *  - No Hard/Soft clips in the middle of the read
+    *  - No deletions in the beginning / end of the read
+    *  - No repeated adjacent element (e.g. 1M2M -> this should be 3M)
+    *  - No consecutive I/D elements
+    **/
+    public static boolean isCigarValid(Cigar cigar) {
+        if (cigar.isValid(null, -1) == null) {                                                                          // This should take care of most invalid Cigar Strings (picard's "exhaustive" implementation)
+
+            Stack<CigarElement> cigarElementStack = new Stack<CigarElement>();                                          // Stack to invert cigar string to find ending operator
+            CigarOperator startingOp = null;
+            CigarOperator endingOp = null;
+
+            // check if it doesn't start with deletions
+            boolean readHasStarted = false;                                                                             // search the list of elements for the starting operator
+            for (CigarElement cigarElement : cigar.getCigarElements()) {
+                if (!readHasStarted) {
+                    if (cigarElement.getOperator() != CigarOperator.SOFT_CLIP && cigarElement.getOperator() != CigarOperator.HARD_CLIP) {
+                        readHasStarted = true;
+                        startingOp = cigarElement.getOperator();
+                    }
+                }
+                cigarElementStack.push(cigarElement);
+            }
+
+            while (!cigarElementStack.empty()) {
+                CigarElement cigarElement = cigarElementStack.pop();
+                if (cigarElement.getOperator() != CigarOperator.SOFT_CLIP && cigarElement.getOperator() != CigarOperator.HARD_CLIP) {
+                    endingOp = cigarElement.getOperator();
+                    break;
+                }
+            }
+
+            if (startingOp != CigarOperator.DELETION && endingOp != CigarOperator.DELETION && startingOp != CigarOperator.SKIPPED_REGION && endingOp != CigarOperator.SKIPPED_REGION)
+                return true;                                                                                          // we don't accept reads starting or ending in deletions (add any other constraint here)
+        }
+
+        return false;
+    }
+
+    public static final int countRefBasesBasedOnCigar(final GATKSAMRecord read, final int cigarStartIndex, final int cigarEndIndex){
+        int result = 0;
+        for(int i = cigarStartIndex; i<cigarEndIndex;i++){
+            final CigarElement cigarElement = read.getCigar().getCigarElement(i);
+            switch (cigarElement.getOperator()) {
+                case M:
+                case S:
+                case D:
+                case N:
+                case H:
+                    result += cigarElement.getLength();
+                    break;
+                case I:
+                    break;
+                default:
+                    throw new ReviewedGATKException("Unsupported cigar operator: " + cigarElement.getOperator());
+            }
+        }
+        return result;
+    }
+
+    // used in the bubble state machine to apply Smith-Waterman to the bubble sequence
+    // these values were chosen via optimization against the NA12878 knowledge base
+    public static final Parameters NEW_SW_PARAMETERS = new Parameters(200, -150, -260, -11);
+
+    private final static String SW_PAD = "NNNNNNNNNN";
+
+    /**
+     * Calculate the cigar elements for this path against the reference sequence
+     *
+     * @param refSeq the reference sequence that all of the bases in this path should align to
+     * @return a Cigar mapping this path to refSeq, or null if no reasonable alignment could be found
+     */
+    public static Cigar calculateCigar(final byte[] refSeq, final byte[] altSeq) {
+        if ( altSeq.length == 0 ) {
+            // horrible edge case from the unit tests, where this path has no bases
+            return new Cigar(Arrays.asList(new CigarElement(refSeq.length, CigarOperator.D)));
+        }
+
+        final Cigar nonStandard;
+
+        final String paddedRef = SW_PAD + new String(refSeq) + SW_PAD;
+        final String paddedPath = SW_PAD + new String(altSeq) + SW_PAD;
+        final SmithWaterman alignment = new SWPairwiseAlignment( paddedRef.getBytes(), paddedPath.getBytes(), NEW_SW_PARAMETERS);
+
+        if ( isSWFailure(alignment) ) {
+            return null;
+        }
+
+
+        // cut off the padding bases
+        final int baseStart = SW_PAD.length();
+        final int baseEnd = paddedPath.length() - SW_PAD.length() - 1; // -1 because it's inclusive
+        nonStandard = AlignmentUtils.trimCigarByBases(alignment.getCigar(), baseStart, baseEnd);
+
+        if ( nonStandard.getReferenceLength() != refSeq.length ) {
+            nonStandard.add(new CigarElement(refSeq.length - nonStandard.getReferenceLength(), CigarOperator.D));
+        }
+
+        // finally, return the cigar with all indels left aligned
+        return leftAlignCigarSequentially(nonStandard, refSeq, altSeq, 0, 0);
+    }
+
+    /**
+     * Make sure that the SW didn't fail in some terrible way, and throw exception if it did
+     */
+    private static boolean isSWFailure(final SmithWaterman alignment) {
+        // check that the alignment starts at the first base, which it should given the padding
+        if ( alignment.getAlignmentStart2wrt1() > 0 ) {
+            return true;
+//          throw new IllegalStateException("SW failure ref " + paddedRef + " vs. " + paddedPath + " should always start at 0, but got " + alignment.getAlignmentStart2wrt1() + " with cigar " + alignment.getCigar());
+        }
+
+        // check that we aren't getting any S operators (which would be very bad downstream)
+        for ( final CigarElement ce : alignment.getCigar().getCigarElements() ) {
+            if ( ce.getOperator() == CigarOperator.S )
+                return true;
+            // soft clips at the end of the alignment are really insertions
+//                throw new IllegalStateException("SW failure ref " + paddedRef + " vs. " + paddedPath + " should never contain S operators but got cigar " + alignment.getCigar());
+        }
+
+        return false;
+    }
+
+    /**
+     * Left align the given cigar sequentially. This is needed because AlignmentUtils doesn't accept cigars with more than one indel in them.
+     * This is a target of future work to incorporate and generalize into AlignmentUtils for use by others.
+     * @param cigar     the cigar to left align
+     * @param refSeq    the reference byte array
+     * @param readSeq   the read byte array
+     * @param refIndex  0-based alignment start position on ref
+     * @param readIndex 0-based alignment start position on read
+     * @return          the left-aligned cigar
+     */
+    @Ensures({"cigar != null", "refSeq != null", "readSeq != null", "refIndex >= 0", "readIndex >= 0"})
+    public static Cigar leftAlignCigarSequentially(final Cigar cigar, final byte[] refSeq, final byte[] readSeq, int refIndex, int readIndex) {
+        final Cigar cigarToReturn = new Cigar();
+        Cigar cigarToAlign = new Cigar();
+        for (int i = 0; i < cigar.numCigarElements(); i++) {
+            final CigarElement ce = cigar.getCigarElement(i);
+            if (ce.getOperator() == CigarOperator.D || ce.getOperator() == CigarOperator.I) {
+                cigarToAlign.add(ce);
+                final Cigar leftAligned = AlignmentUtils.leftAlignSingleIndel(cigarToAlign, refSeq, readSeq, refIndex, readIndex, false);
+                for ( final CigarElement toAdd : leftAligned.getCigarElements() ) { cigarToReturn.add(toAdd); }
+                refIndex += cigarToAlign.getReferenceLength();
+                readIndex += cigarToAlign.getReadLength();
+                cigarToAlign = new Cigar();
+            } else {
+                cigarToAlign.add(ce);
+            }
+        }
+        if( !cigarToAlign.isEmpty() ) {
+            for( final CigarElement toAdd : cigarToAlign.getCigarElements() ) {
+                cigarToReturn.add(toAdd);
+            }
+        }
+
+        final Cigar result = AlignmentUtils.consolidateCigar(cigarToReturn);
+        if( result.getReferenceLength() != cigar.getReferenceLength() )
+            throw new IllegalStateException("leftAlignCigarSequentially failed to produce a valid CIGAR.  Reference lengths differ.  Initial cigar " + cigar + " left aligned into " + result);
+        return result;
+    }
+}
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/sam/GATKSAMReadGroupRecord.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/sam/GATKSAMReadGroupRecord.java
new file mode 100644
index 0000000..6af9059
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/sam/GATKSAMReadGroupRecord.java
@@ -0,0 +1,116 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.utils.sam;
+
+import htsjdk.samtools.SAMReadGroupRecord;
+import org.broadinstitute.gatk.utils.NGSPlatform;
+
+/**
+ * @author ebanks
+ * GATKSAMReadGroupRecord
+ *
+ * this class extends the samtools SAMReadGroupRecord class and caches important
+ * (and oft-accessed) data that's not already cached by the SAMReadGroupRecord class
+ *
+ */
+public class GATKSAMReadGroupRecord extends SAMReadGroupRecord {
+    // the SAMReadGroupRecord data we're caching
+    private String mSample = null;
+    private String mPlatform = null;
+    private NGSPlatform mNGSPlatform = null;
+
+    // because some values can be null, we don't want to duplicate effort
+    private boolean retrievedSample = false;
+    private boolean retrievedPlatform = false;
+    private boolean retrievedNGSPlatform = false;
+
+    public GATKSAMReadGroupRecord(final String id) {
+        super(id);
+    }
+
+    public GATKSAMReadGroupRecord(SAMReadGroupRecord record) {
+        super(record.getReadGroupId(), record);
+    }
+
+    /**
+     * Get the NGSPlatform enum telling us the platform of this read group
+     *
+     * This function call is caching, so subsequent calls to it are free, while
+     * the first time it's called there's a bit of work to resolve the enum
+     *
+     * @return an NGSPlatform enum value
+     */
+    public NGSPlatform getNGSPlatform() {
+        if ( ! retrievedNGSPlatform ) {
+            mNGSPlatform = NGSPlatform.fromReadGroupPL(getPlatform());
+            retrievedNGSPlatform = true;
+        }
+
+        return mNGSPlatform;
+    }
+
+    @Override
+    public String toString() {
+        return "GATKSAMReadGroupRecord @RG:" + getReadGroupId();
+    }
+
+    ///////////////////////////////////////////////////////////////////////////////
+    // *** The following methods are overloaded to cache the appropriate data ***//
+    ///////////////////////////////////////////////////////////////////////////////
+
+    @Override
+    public String getSample() {
+        if ( !retrievedSample ) {
+            mSample = super.getSample();
+            retrievedSample = true;
+        }
+        return mSample;
+    }
+
+    @Override
+    public void setSample(String s) {
+        super.setSample(s);
+        mSample = s;
+        retrievedSample = true;
+    }
+
+    @Override
+    public String getPlatform() {
+        if ( !retrievedPlatform ) {
+            mPlatform = super.getPlatform();
+            retrievedPlatform = true;
+        }
+        return mPlatform;
+    }
+
+    @Override
+    public void setPlatform(String s) {
+        super.setPlatform(s);
+        mPlatform = s;
+        retrievedPlatform = true;
+        retrievedNGSPlatform = false; // recalculate the NGSPlatform
+    }
+}
\ No newline at end of file
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/sam/GATKSAMRecord.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/sam/GATKSAMRecord.java
new file mode 100644
index 0000000..0080f01
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/sam/GATKSAMRecord.java
@@ -0,0 +1,631 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.utils.sam;
+
+import com.google.java.contract.Ensures;
+import htsjdk.samtools.*;
+import org.broadinstitute.gatk.utils.NGSPlatform;
+import org.broadinstitute.gatk.utils.exceptions.ReviewedGATKException;
+import org.broadinstitute.gatk.utils.recalibration.EventType;
+
+import java.util.*;
+
+/**
+ * @author ebanks, depristo
+ * GATKSAMRecord
+ *
+ * this class extends the samtools BAMRecord class (and SAMRecord) and caches important
+ * (and oft-accessed) data that's not already cached by the SAMRecord class
+ *
+ * IMPORTANT NOTE: Because ReadGroups are not set through the SAMRecord,
+ *   if they are ever modified externally then one must also invoke the
+ *   setReadGroup() method here to ensure that the cache is kept up-to-date.
+ *
+ * WARNING -- GATKSAMRecords cache several values (that are expensive to compute)
+ * that depending on the inferred insert size and alignment starts and stops of this read and its mate.
+ * Changing these values in any way will invalidate the cached value. However, we do not monitor those setter
+ * functions, so modifying a GATKSAMRecord in any way may result in stale cached values.
+ */
+public class GATKSAMRecord extends BAMRecord implements Cloneable {
+    // Base Quality Score Recalibrator specific attribute tags
+    public static final String BQSR_BASE_INSERTION_QUALITIES = "BI";                // base qualities for insertions
+    public static final String BQSR_BASE_DELETION_QUALITIES = "BD";                 // base qualities for deletions
+
+    /**
+     * The default quality score for an insertion or deletion, if
+     * none are provided for this read.
+     */
+    public static final byte DEFAULT_INSERTION_DELETION_QUAL = (byte)45;
+
+    // the SAMRecord data we're caching
+    private String mReadString = null;
+    private GATKSAMReadGroupRecord mReadGroup = null;
+    private final static int UNINITIALIZED = -1;
+    private int softStart = UNINITIALIZED;
+    private int softEnd = UNINITIALIZED;
+    private Integer adapterBoundary = null;
+
+    private boolean isStrandlessRead = false;
+
+    // because some values can be null, we don't want to duplicate effort
+    private boolean retrievedReadGroup = false;
+
+    // These temporary attributes were added here to make life easier for
+    // certain algorithms by providing a way to label or attach arbitrary data to
+    // individual GATKSAMRecords.
+    // These attributes exist in memory only, and are never written to disk.
+    private Map<Object, Object> temporaryAttributes;
+
+    /**
+     * HACK TO CREATE GATKSAMRECORD WITH ONLY A HEADER FOR TESTING PURPOSES ONLY
+     * @param header
+     */
+    public GATKSAMRecord(final SAMFileHeader header) {
+        this(new SAMRecord(header));
+    }
+
+    /**
+     * HACK TO CREATE GATKSAMRECORD BASED ONLY A SAMRECORD FOR TESTING PURPOSES ONLY
+     * @param read
+     */
+    public GATKSAMRecord(final SAMRecord read) {
+        super(read.getHeader(),
+                read.getReferenceIndex(),
+                read.getAlignmentStart(),
+                read.getReadName() != null ? (short)read.getReadNameLength() : 0,
+                (short)read.getMappingQuality(),
+                0,
+                read.getCigarLength(),
+                read.getFlags(),
+                read.getReadLength(),
+                read.getMateReferenceIndex(),
+                read.getMateAlignmentStart(),
+                read.getInferredInsertSize(),
+                null);
+        SAMReadGroupRecord samRG = read.getReadGroup();
+        clearAttributes();
+        if (samRG != null) {
+            GATKSAMReadGroupRecord rg = new GATKSAMReadGroupRecord(samRG);
+            setReadGroup(rg);
+        }
+    }
+
+    public GATKSAMRecord(final SAMFileHeader header,
+                         final int referenceSequenceIndex,
+                         final int alignmentStart,
+                         final short readNameLength,
+                         final short mappingQuality,
+                         final int indexingBin,
+                         final int cigarLen,
+                         final int flags,
+                         final int readLen,
+                         final int mateReferenceSequenceIndex,
+                         final int mateAlignmentStart,
+                         final int insertSize,
+                         final byte[] variableLengthBlock) {
+        super(header, referenceSequenceIndex, alignmentStart, readNameLength, mappingQuality, indexingBin, cigarLen,
+                flags, readLen, mateReferenceSequenceIndex, mateAlignmentStart, insertSize, variableLengthBlock);
+    }
+
+    public static GATKSAMRecord createRandomRead(int length) {
+        List<CigarElement> cigarElements = new LinkedList<>();
+        cigarElements.add(new CigarElement(length, CigarOperator.M));
+        Cigar cigar = new Cigar(cigarElements);
+        return ArtificialSAMUtils.createArtificialRead(cigar);
+    }
+
+    ///////////////////////////////////////////////////////////////////////////////
+    // *** support for reads without meaningful strand information            ***//
+    ///////////////////////////////////////////////////////////////////////////////
+
+    /**
+     * Does this read have a meaningful strandedness value?
+     *
+     * Some advanced types of reads, such as reads coming from merged fragments,
+     * don't have meaningful strandedness values, as they are composites of multiple
+     * other reads.  Strandless reads need to be handled specially by code that cares about
+     * stranded information, such as FS.
+     *
+     * @return true if this read doesn't have meaningful strand information
+     */
+    public boolean isStrandless() {
+        return isStrandlessRead;
+    }
+
+    /**
+     * Set the strandless state of this read to isStrandless
+     * @param isStrandless true if this read doesn't have a meaningful strandedness value
+     */
+    public void setIsStrandless(final boolean isStrandless) {
+        this.isStrandlessRead = isStrandless;
+    }
+
+    @Override
+    public boolean getReadNegativeStrandFlag() {
+        return ! isStrandless() && super.getReadNegativeStrandFlag();
+    }
+
+    @Override
+    public void setReadNegativeStrandFlag(final boolean flag) {
+        if ( isStrandless() )
+            throw new IllegalStateException("Cannot set the strand of a strandless read");
+        super.setReadNegativeStrandFlag(flag);
+    }
+
+
+    ///////////////////////////////////////////////////////////////////////////////
+    // *** The following methods are overloaded to cache the appropriate data ***//
+    ///////////////////////////////////////////////////////////////////////////////
+
+    @Override
+    public String getReadString() {
+        if ( mReadString == null )
+            mReadString = super.getReadString();
+        return mReadString;
+    }
+
+    @Override
+    public void setReadString(String s) {
+        super.setReadString(s);
+        mReadString = s;
+    }
+
+    /**
+     * Get the GATKSAMReadGroupRecord of this read
+     * @return a non-null GATKSAMReadGroupRecord
+     */
+    @Override
+    public GATKSAMReadGroupRecord getReadGroup() {
+        if ( ! retrievedReadGroup ) {
+            final SAMReadGroupRecord rg = super.getReadGroup();
+
+            // three cases: rg may be null (no rg, rg may already be a GATKSAMReadGroupRecord, or it may be
+            // a regular SAMReadGroupRecord in which case we have to make it a GATKSAMReadGroupRecord
+            if ( rg == null )
+                mReadGroup = null;
+            else if ( rg instanceof GATKSAMReadGroupRecord )
+                mReadGroup = (GATKSAMReadGroupRecord)rg;
+            else
+                mReadGroup = new GATKSAMReadGroupRecord(rg);
+
+            retrievedReadGroup = true;
+        }
+        return mReadGroup;
+    }
+
+    public void setReadGroup( final GATKSAMReadGroupRecord readGroup ) {
+        mReadGroup = readGroup;
+        retrievedReadGroup = true;
+        setAttribute("RG", mReadGroup.getId()); // todo -- this should be standardized, but we don't have access to SAMTagUtils!
+    }
+
+
+    @Override
+    public int hashCode() {
+        return super.hashCode();
+    }
+
+    @Override
+    public boolean equals(Object o) {
+        if (this == o) return true;
+
+        if (!(o instanceof GATKSAMRecord)) return false;
+
+        // note that we do not consider the GATKSAMRecord internal state at all
+        return super.equals(o);
+    }
+
+    /**
+     * Setters and Accessors for base insertion and base deletion quality scores
+     */
+    public void setBaseQualities( final byte[] quals, final EventType errorModel ) {
+        switch( errorModel ) {
+            case BASE_SUBSTITUTION:
+                setBaseQualities(quals);
+                break;
+            case BASE_INSERTION:
+                setAttribute( GATKSAMRecord.BQSR_BASE_INSERTION_QUALITIES, quals == null ? null : SAMUtils.phredToFastq(quals) );
+                break;
+            case BASE_DELETION:
+                setAttribute( GATKSAMRecord.BQSR_BASE_DELETION_QUALITIES, quals == null ? null : SAMUtils.phredToFastq(quals) );
+                break;
+            default:
+                throw new ReviewedGATKException("Unrecognized Base Recalibration type: " + errorModel );
+        }
+    }
+
+    public byte[] getBaseQualities( final EventType errorModel ) {
+        switch( errorModel ) {
+            case BASE_SUBSTITUTION:
+                return getBaseQualities();
+            case BASE_INSERTION:
+                return getBaseInsertionQualities();
+            case BASE_DELETION:
+                return getBaseDeletionQualities();
+            default:
+                throw new ReviewedGATKException("Unrecognized Base Recalibration type: " + errorModel );
+        }
+    }
+
+    /**
+     * @return whether or not this read has base insertion or deletion qualities (one of the two is sufficient to return true)
+     */
+    public boolean hasBaseIndelQualities() {
+        return getAttribute( BQSR_BASE_INSERTION_QUALITIES ) != null || getAttribute( BQSR_BASE_DELETION_QUALITIES ) != null;
+    }
+
+    /**
+     * @return the base deletion quality or null if read doesn't have one
+     */
+    public byte[] getExistingBaseInsertionQualities() {
+        return SAMUtils.fastqToPhred( getStringAttribute(BQSR_BASE_INSERTION_QUALITIES));
+    }
+
+    /**
+     * @return the base deletion quality or null if read doesn't have one
+     */
+    public byte[] getExistingBaseDeletionQualities() {
+        return SAMUtils.fastqToPhred( getStringAttribute(BQSR_BASE_DELETION_QUALITIES));
+    }
+
+    /**
+     * Default utility to query the base insertion quality of a read. If the read doesn't have one, it creates an array of default qualities (currently Q45)
+     * and assigns it to the read.
+     *
+     * @return the base insertion quality array
+     */
+    public byte[] getBaseInsertionQualities() {
+        byte [] quals = getExistingBaseInsertionQualities();
+        if( quals == null ) {
+            quals = new byte[getBaseQualities().length];
+            Arrays.fill(quals, DEFAULT_INSERTION_DELETION_QUAL); // Some day in the future when base insertion and base deletion quals exist the samtools API will
+                                           // be updated and the original quals will be pulled here, but for now we assume the original quality is a flat Q45
+        }
+        return quals;
+    }
+
+    /**
+     * Default utility to query the base deletion quality of a read. If the read doesn't have one, it creates an array of default qualities (currently Q45)
+     * and assigns it to the read.
+     *
+     * @return the base deletion quality array
+     */
+    public byte[] getBaseDeletionQualities() {
+        byte[] quals = getExistingBaseDeletionQualities();
+        if( quals == null ) {
+            quals = new byte[getBaseQualities().length];
+            Arrays.fill(quals, DEFAULT_INSERTION_DELETION_QUAL);  // Some day in the future when base insertion and base deletion quals exist the samtools API will
+                                            // be updated and the original quals will be pulled here, but for now we assume the original quality is a flat Q45
+        }
+        return quals;
+    }
+
+    /**
+     * Efficient caching accessor that returns the GATK NGSPlatform of this read
+     * @return
+     */
+    public NGSPlatform getNGSPlatform() {
+        return getReadGroup().getNGSPlatform();
+    }
+
+    ///////////////////////////////////////////////////////////////////////////////
+    // *** GATKSAMRecord specific methods                                     ***//
+    ///////////////////////////////////////////////////////////////////////////////
+
+    /**
+     * Checks whether an attribute has been set for the given key.
+     *
+     * Temporary attributes provide a way to label or attach arbitrary data to
+     * individual GATKSAMRecords. These attributes exist in memory only,
+     * and are never written to disk.
+     *
+     * @param key key
+     * @return True if an attribute has been set for this key.
+     */
+    public boolean containsTemporaryAttribute(Object key) {
+        return temporaryAttributes != null && temporaryAttributes.containsKey(key);
+    }
+
+    /**
+     * Sets the key to the given value, replacing any previous value. The previous
+     * value is returned.
+     *
+     * Temporary attributes provide a way to label or attach arbitrary data to
+     * individual GATKSAMRecords. These attributes exist in memory only,
+     * and are never written to disk.
+     *
+     * @param key    key
+     * @param value  value
+     * @return attribute
+     */
+    public Object setTemporaryAttribute(Object key, Object value) {
+        if(temporaryAttributes == null) {
+            temporaryAttributes = new HashMap<>();
+        }
+        return temporaryAttributes.put(key, value);
+    }
+
+    /**
+     * Looks up the value associated with the given key.
+     *
+     * Temporary attributes provide a way to label or attach arbitrary data to
+     * individual GATKSAMRecords. These attributes exist in memory only,
+     * and are never written to disk.
+     *
+     * @param key key
+     * @return The value, or null.
+     */
+    public Object getTemporaryAttribute(Object key) {
+        if(temporaryAttributes != null) {
+            return temporaryAttributes.get(key);
+        }
+        return null;
+    }
+
+    /**
+     * Checks whether if the read has any bases.
+     *
+     * Empty reads can be dangerous as it may have no cigar strings, no read names and
+     * other missing attributes.
+     *
+     * @return true if the read has no bases
+     */
+    public boolean isEmpty() {
+        return super.getReadBases() == null || super.getReadLength() == 0;
+    }
+
+    /**
+     * Clears all attributes except ReadGroup of the read.
+     */
+    public GATKSAMRecord simplify () {
+        GATKSAMReadGroupRecord rg = getReadGroup(); // save the read group information
+        byte[] insQuals = (this.getAttribute(BQSR_BASE_INSERTION_QUALITIES) == null) ? null : getBaseInsertionQualities();
+        byte[] delQuals = (this.getAttribute(BQSR_BASE_DELETION_QUALITIES)  == null) ? null : getBaseDeletionQualities();
+        this.clearAttributes(); // clear all attributes from the read
+        this.setReadGroup(rg); // restore read group
+        if (insQuals != null)
+           this.setBaseQualities(insQuals, EventType.BASE_INSERTION); // restore base insertion if we had any
+        if (delQuals != null)
+            this.setBaseQualities(delQuals, EventType.BASE_DELETION); // restore base deletion if we had any
+        return this;
+    }
+
+    /**
+     * Calculates the reference coordinate for the beginning of the read taking into account soft clips but not hard clips.
+     *
+     * Note: getUnclippedStart() adds soft and hard clips, this function only adds soft clips.
+     *
+     * @return the unclipped start of the read taking soft clips (but not hard clips) into account
+     */
+    public int getSoftStart() {
+        if ( softStart == UNINITIALIZED ) {
+            softStart = getAlignmentStart();
+            for (final CigarElement cig : getCigar().getCigarElements()) {
+                final CigarOperator op = cig.getOperator();
+
+                if (op == CigarOperator.SOFT_CLIP)
+                    softStart -= cig.getLength();
+                else if (op != CigarOperator.HARD_CLIP)
+                    break;
+            }
+        }
+        return softStart;
+    }
+
+    /**
+     * Calculates the reference coordinate for the end of the read taking into account soft clips but not hard clips.
+     *
+     * Note: getUnclippedEnd() adds soft and hard clips, this function only adds soft clips.
+     *
+     * @return the unclipped end of the read taking soft clips (but not hard clips) into account
+     */
+    public int getSoftEnd() {
+        if ( softEnd == UNINITIALIZED ) {
+            boolean foundAlignedBase = false;
+            softEnd = getAlignmentEnd();
+            final List<CigarElement> cigs = getCigar().getCigarElements();
+            for (int i = cigs.size() - 1; i >= 0; --i) {
+                final CigarElement cig = cigs.get(i);
+                final CigarOperator op = cig.getOperator();
+
+                if (op == CigarOperator.SOFT_CLIP) // assumes the soft clip that we found is at the end of the aligned read
+                    softEnd += cig.getLength();
+                else if (op != CigarOperator.HARD_CLIP) {
+                    foundAlignedBase = true;
+                    break;
+                }
+            }
+            if( !foundAlignedBase ) { // for example 64H14S, the soft end is actually the same as the alignment end
+                softEnd = getAlignmentEnd();
+            }
+        }
+
+        return softEnd;
+    }
+
+    /**
+     * If the read is hard clipped, the soft start and end will change. You can set manually or just reset the cache
+     * so that the next call to getSoftStart/End will recalculate it lazily.
+     */
+    public void resetSoftStartAndEnd() {
+        softStart = -1;
+        softEnd = -1;
+    }
+
+    /**
+     * If the read is hard clipped, the soft start and end will change. You can set manually or just reset the cache
+     * so that the next call to getSoftStart/End will recalculate it lazily.
+     */
+    public void resetSoftStartAndEnd(int softStart, int softEnd) {
+        this.softStart = softStart;
+        this.softEnd = softEnd;
+    }
+
+    /**
+     * Determines the original alignment start of a previously clipped read.
+     * 
+     * This is useful for reads that have been trimmed to a variant region and lost the information of it's original alignment end
+     * 
+     * @return the alignment start of a read before it was clipped
+     */
+    public int getOriginalAlignmentStart() {
+        return getUnclippedStart();
+    }
+
+    /**
+     * Determines the original alignment end of a previously clipped read.
+     *
+     * This is useful for reads that have been trimmed to a variant region and lost the information of it's original alignment end
+     * 
+     * @return the alignment end of a read before it was clipped
+     */
+    public int getOriginalAlignmentEnd() {
+        return getUnclippedEnd();
+    }
+
+    /**
+     * Creates an empty GATKSAMRecord with the read's header, read group and mate
+     * information, but empty (not-null) fields:
+     *  - Cigar String
+     *  - Read Bases
+     *  - Base Qualities
+     *
+     * Use this method if you want to create a new empty GATKSAMRecord based on
+     * another GATKSAMRecord
+     *
+     * @param read a read to copy the header from
+     * @return a read with no bases but safe for the GATK
+     */
+    public static GATKSAMRecord emptyRead(GATKSAMRecord read) {
+        GATKSAMRecord emptyRead = new GATKSAMRecord(read.getHeader(),
+                read.getReferenceIndex(),
+                0,
+                (short) 0,
+                (short) 0,
+                0,
+                0,
+                read.getFlags(),
+                0,
+                read.getMateReferenceIndex(),
+                read.getMateAlignmentStart(),
+                read.getInferredInsertSize(),
+                null);
+
+        emptyRead.setCigarString("");
+        emptyRead.setReadBases(new byte[0]);
+        emptyRead.setBaseQualities(new byte[0]);
+
+        SAMReadGroupRecord samRG = read.getReadGroup();
+        emptyRead.clearAttributes();
+        if (samRG != null) {
+            GATKSAMReadGroupRecord rg = new GATKSAMReadGroupRecord(samRG);
+            emptyRead.setReadGroup(rg);
+        }
+
+        return emptyRead;
+    }
+
+    /**
+     * Creates a new GATKSAMRecord with the source read's header, read group and mate
+     * information, but with the following fields set to user-supplied values:
+     *  - Read Bases
+     *  - Base Qualities
+     *  - Base Insertion Qualities
+     *  - Base Deletion Qualities
+     *
+     *  Cigar string is empty (not-null)
+     *
+     * Use this method if you want to create a new GATKSAMRecord based on
+     * another GATKSAMRecord, but with modified bases and qualities
+     *
+     * @param read a read to copy the header from
+     * @param readBases an array containing the new bases you wish use in place of the originals
+     * @param baseQualities an array containing the new base qualities you wish use in place of the originals
+     * @param baseInsertionQualities an array containing the new base insertion qaulities
+     * @param baseDeletionQualities an array containing the new base deletion qualities
+     * @return a read with modified bases and qualities, safe for the GATK
+     */
+    public static GATKSAMRecord createQualityModifiedRead(final GATKSAMRecord read,
+                                                          final byte[] readBases,
+                                                          final byte[] baseQualities,
+                                                          final byte[] baseInsertionQualities,
+                                                          final byte[] baseDeletionQualities) {
+        if ( baseQualities.length != readBases.length || baseInsertionQualities.length != readBases.length || baseDeletionQualities.length != readBases.length )
+            throw new IllegalArgumentException("Read bases and read quality arrays aren't the same size: Bases:" + readBases.length
+                                                + " vs Base Q's:" + baseQualities.length
+                                                + " vs Insert Q's:" + baseInsertionQualities.length
+                                                + " vs Delete Q's:" + baseDeletionQualities.length);
+
+        final GATKSAMRecord processedRead = GATKSAMRecord.emptyRead(read);
+        processedRead.setReadBases(readBases);
+        processedRead.setBaseQualities(baseQualities, EventType.BASE_SUBSTITUTION);
+        processedRead.setBaseQualities(baseInsertionQualities, EventType.BASE_INSERTION);
+        processedRead.setBaseQualities(baseDeletionQualities, EventType.BASE_DELETION);
+
+        return processedRead;
+    }
+
+    /**
+     * Shallow copy of everything, except for the attribute list and the temporary attributes. 
+     * A new list of the attributes is created for both, but the attributes themselves are copied by reference.  
+     * This should be safe because callers should never modify a mutable value returned by any of the get() methods anyway.
+     * 
+     * @return a shallow copy of the GATKSAMRecord
+     */
+    @Override
+    public Object clone() {
+        try {
+            final GATKSAMRecord clone = (GATKSAMRecord) super.clone();
+            if (temporaryAttributes != null) {
+                clone.temporaryAttributes = new HashMap<>();
+                for (Object attribute : temporaryAttributes.keySet())
+                    clone.setTemporaryAttribute(attribute, temporaryAttributes.get(attribute));
+            }
+            return clone;
+        } catch (final CloneNotSupportedException e) {
+            throw new RuntimeException( e );
+        }
+    }
+
+    /**
+     * A caching version of ReadUtils.getAdaptorBoundary()
+     *
+     * see #ReadUtils.getAdaptorBoundary(SAMRecord) for more information about the meaning of this function
+     *
+     * WARNING -- this function caches a value depending on the inferred insert size and alignment starts
+     * and stops of this read and its mate.  Changing these values in any way will invalidate the cached value.
+     * However, we do not monitor those setter functions, so modifying a GATKSAMRecord in any way may
+     * result in stale cached values.
+     *
+     * @return the result of calling ReadUtils.getAdaptorBoundary on this read
+     */
+    @Ensures("result == ReadUtils.getAdaptorBoundary(this)")
+    public int getAdaptorBoundary() {
+        if ( adapterBoundary == null )
+            adapterBoundary = ReadUtils.getAdaptorBoundary(this);
+        return adapterBoundary;
+    }
+}
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/sam/GATKSamRecordFactory.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/sam/GATKSamRecordFactory.java
new file mode 100644
index 0000000..1e5ad1e
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/sam/GATKSamRecordFactory.java
@@ -0,0 +1,75 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.utils.sam;
+
+import htsjdk.samtools.SAMFileHeader;
+import htsjdk.samtools.SAMRecord;
+import htsjdk.samtools.SAMRecordFactory;
+import htsjdk.samtools.BAMRecord;
+import org.broadinstitute.gatk.utils.exceptions.UserException;
+
+/**
+ * Factory interface implementation used to create GATKSamRecords
+ * from SAMFileReaders with SAM-JDK
+ *
+ * @author Mark DePristo
+ */
+public class GATKSamRecordFactory implements SAMRecordFactory {
+
+    /** Create a new SAMRecord to be filled in */
+    public SAMRecord createSAMRecord(SAMFileHeader header) {
+        throw new UserException.BadInput("The GATK now longer supports input SAM files");
+    }
+
+    /** Create a new BAM Record. */
+    public BAMRecord createBAMRecord(final SAMFileHeader header,
+                                     final int referenceSequenceIndex,
+                                     final int alignmentStart,
+                                     final short readNameLength,
+                                     final short mappingQuality,
+                                     final int indexingBin,
+                                     final int cigarLen,
+                                     final int flags,
+                                     final int readLen,
+                                     final int mateReferenceSequenceIndex,
+                                     final int mateAlignmentStart,
+                                     final int insertSize,
+                                     final byte[] variableLengthBlock) {
+        return new GATKSAMRecord(header,
+                referenceSequenceIndex,
+                alignmentStart,
+                readNameLength,
+                mappingQuality,
+                indexingBin,
+                cigarLen,
+                flags,
+                readLen,
+                mateReferenceSequenceIndex,
+                mateAlignmentStart,
+                insertSize,
+                variableLengthBlock);
+    }
+}
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/sam/MisencodedBaseQualityReadTransformer.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/sam/MisencodedBaseQualityReadTransformer.java
new file mode 100644
index 0000000..35146f0
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/sam/MisencodedBaseQualityReadTransformer.java
@@ -0,0 +1,94 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.utils.sam;
+
+import org.broadinstitute.gatk.engine.GenomeAnalysisEngine;
+import org.broadinstitute.gatk.engine.iterators.ReadTransformer;
+import org.broadinstitute.gatk.engine.walkers.Walker;
+import org.broadinstitute.gatk.utils.QualityUtils;
+import org.broadinstitute.gatk.utils.exceptions.UserException;
+
+/**
+ * Checks for and errors out (or fixes if requested) when it detects reads with base qualities that are not encoded with
+ * phred-scaled quality scores.  Q0 == ASCII 33 according to the SAM specification, whereas Illumina encoding starts at
+ * Q64.  The idea here is simple: if we are asked to fix the scores then we just subtract 31 from every quality score.
+ * Otherwise, we randomly sample reads (for efficiency) and error out if we encounter a qual that's too high.
+ */
+public class MisencodedBaseQualityReadTransformer extends ReadTransformer {
+
+    private static final int samplingFrequency = 1000;  // sample 1 read for every 1000 encountered
+    private static final int encodingFixValue = 31;  // Illumina_64 - PHRED_33
+
+    private boolean disabled;
+    private boolean fixQuals;
+    protected static int currentReadCounter = 0;
+
+    @Override
+    public ApplicationTime initializeSub(final GenomeAnalysisEngine engine, final Walker walker) {
+        fixQuals = engine.getArguments().FIX_MISENCODED_QUALS;
+        disabled = !fixQuals && engine.getArguments().ALLOW_POTENTIALLY_MISENCODED_QUALS;
+
+        return ReadTransformer.ApplicationTime.ON_INPUT;
+    }
+
+    @Override
+    public boolean enabled() {
+        return !disabled;
+    }
+
+    @Override
+    public GATKSAMRecord apply(final GATKSAMRecord read) {
+        if ( fixQuals )
+            return fixMisencodedQuals(read);
+
+        checkForMisencodedQuals(read);
+        return read;
+    }
+
+    protected static GATKSAMRecord fixMisencodedQuals(final GATKSAMRecord read) {
+        final byte[] quals = read.getBaseQualities();
+        for ( int i = 0; i < quals.length; i++ ) {
+            quals[i] -= encodingFixValue;
+            if ( quals[i] < 0 )
+                throw new UserException.BadInput("while fixing mis-encoded base qualities we encountered a read that was correctly encoded; we cannot handle such a mixture of reads so unfortunately the BAM must be fixed with some other tool");
+        }
+        read.setBaseQualities(quals);
+        return read;
+    }
+
+    protected static void checkForMisencodedQuals(final GATKSAMRecord read) {
+        // sample reads randomly for checking
+        if ( ++currentReadCounter >= samplingFrequency ) {
+            currentReadCounter = 0;
+
+            final byte[] quals = read.getBaseQualities();
+            for ( final byte qual : quals ) {
+                if ( qual > QualityUtils.MAX_REASONABLE_Q_SCORE )
+                    throw new UserException.MisencodedBAM(read, "we encountered an extremely high quality score of " + (int)qual);
+            }
+        }
+    }
+}
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/sam/NWaySAMFileWriter.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/sam/NWaySAMFileWriter.java
new file mode 100644
index 0000000..abf70d5
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/sam/NWaySAMFileWriter.java
@@ -0,0 +1,185 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.utils.sam;
+
+import htsjdk.samtools.*;
+import htsjdk.samtools.util.ProgressLoggerInterface;
+import org.broadinstitute.gatk.engine.GenomeAnalysisEngine;
+import org.broadinstitute.gatk.engine.datasources.reads.SAMReaderID;
+import org.broadinstitute.gatk.utils.Utils;
+import org.broadinstitute.gatk.utils.exceptions.GATKException;
+import org.broadinstitute.gatk.utils.exceptions.UserException;
+
+import java.io.File;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * Created by IntelliJ IDEA.
+ * User: asivache
+ * Date: May 31, 2011
+ * Time: 3:52:49 PM
+ * To change this template use File | Settings | File Templates.
+ */
+public class NWaySAMFileWriter implements SAMFileWriter {
+
+    private Map<SAMReaderID,SAMFileWriter> writerMap = null;
+    private boolean presorted ;
+    GenomeAnalysisEngine toolkit;
+    boolean KEEP_ALL_PG_RECORDS = false;
+
+    public NWaySAMFileWriter(GenomeAnalysisEngine toolkit, Map<String,String> in2out, SAMFileHeader.SortOrder order,
+                             boolean presorted, boolean indexOnTheFly, boolean generateMD5, SAMProgramRecord pRecord, boolean keep_records) {
+        this.presorted = presorted;
+        this.toolkit = toolkit;
+        this.KEEP_ALL_PG_RECORDS = keep_records;
+        writerMap = new HashMap<SAMReaderID,SAMFileWriter>();
+        setupByReader(toolkit,in2out,order, presorted, indexOnTheFly, generateMD5, pRecord);
+    }
+
+    public NWaySAMFileWriter(GenomeAnalysisEngine toolkit, String ext, SAMFileHeader.SortOrder order,
+                              boolean presorted, boolean indexOnTheFly , boolean generateMD5, SAMProgramRecord pRecord, boolean keep_records) {
+        this.presorted = presorted;
+        this.toolkit = toolkit;
+        this.KEEP_ALL_PG_RECORDS = keep_records;
+        writerMap = new HashMap<SAMReaderID,SAMFileWriter>();
+        setupByReader(toolkit,ext,order, presorted, indexOnTheFly, generateMD5, pRecord);
+    }
+
+    public NWaySAMFileWriter(GenomeAnalysisEngine toolkit, Map<String,String> in2out, SAMFileHeader.SortOrder order,
+                             boolean presorted, boolean indexOnTheFly, boolean generateMD5) {
+        this(toolkit, in2out, order, presorted, indexOnTheFly, generateMD5, null,false);
+    }
+
+    public NWaySAMFileWriter(GenomeAnalysisEngine toolkit, String ext, SAMFileHeader.SortOrder order,
+                              boolean presorted, boolean indexOnTheFly , boolean generateMD5) {
+        this(toolkit, ext, order, presorted, indexOnTheFly, generateMD5, null,false);
+    }
+
+    /**
+     * Instantiates multiple underlying SAM writes, one per input SAM reader registered with GATK engine (those will be retrieved
+     * from <code>toolkit</code>). The <code>in2out</code> map must contain an entry for each input filename and map it
+     * onto a unique output file name.
+     * @param toolkit
+     * @param in2out
+     */
+    public void setupByReader(GenomeAnalysisEngine toolkit, Map<String,String> in2out, SAMFileHeader.SortOrder order,
+                              boolean presorted, boolean indexOnTheFly, boolean generateMD5, SAMProgramRecord pRecord) {
+        if ( in2out==null ) throw new GATKException("input-output bam filename map for n-way-out writing is NULL");
+        for ( SAMReaderID rid : toolkit.getReadsDataSource().getReaderIDs() ) {
+
+            String fName = toolkit.getReadsDataSource().getSAMFile(rid).getName();
+
+            String outName;
+            if ( ! in2out.containsKey(fName) )
+                    throw new UserException.BadInput("Input-output bam filename map does not contain an entry for the input file "+fName);
+            outName = in2out.get(fName);
+
+            if ( writerMap.containsKey( rid ) )
+                throw new GATKException("nWayOut mode: Reader id for input sam file "+fName+" is already registered; "+
+                        "map file likely contains multiple entries for this input file");
+
+            addWriter(rid,outName, order, presorted, indexOnTheFly, generateMD5, pRecord);
+        }
+
+    }
+
+    /**
+     * Instantiates multiple underlying SAM writes, one per input SAM reader registered with GATK engine (those will be retrieved
+     * from <code>toolkit</code>). The output file names will be generated automatically by stripping ".sam" or ".bam" off the
+     * input file name and adding ext instead (e.g. ".cleaned.bam").
+     * onto a unique output file name.
+     * @param toolkit
+     * @param ext
+     */
+    public void setupByReader(GenomeAnalysisEngine toolkit, String ext, SAMFileHeader.SortOrder order,
+                              boolean presorted, boolean indexOnTheFly, boolean generateMD5, SAMProgramRecord pRecord) {
+        for ( SAMReaderID rid : toolkit.getReadsDataSource().getReaderIDs() ) {
+
+            String fName = toolkit.getReadsDataSource().getSAMFile(rid).getName();
+
+            String outName;
+            int pos ;
+            if ( fName.toUpperCase().endsWith(".BAM") ) pos = fName.toUpperCase().lastIndexOf(".BAM");
+            else {
+                if ( fName.toUpperCase().endsWith(".SAM") ) pos = fName.toUpperCase().lastIndexOf(".SAM");
+                else throw new UserException.BadInput("Input file name "+fName+" does not end with .sam or .bam");
+            }
+            String prefix = fName.substring(0,pos);
+            outName = prefix+ext;
+
+            if ( writerMap.containsKey( rid ) )
+                throw new GATKException("nWayOut mode: Reader id for input sam file "+fName+" is already registered");
+            addWriter(rid,outName, order, presorted, indexOnTheFly, generateMD5, pRecord);
+        }
+
+    }
+
+    private void addWriter(SAMReaderID id , String outName, SAMFileHeader.SortOrder order, boolean presorted,
+                           boolean indexOnTheFly, boolean generateMD5, SAMProgramRecord programRecord) {
+        File f = new File(outName);
+        SAMFileHeader header = Utils.setupWriter(toolkit.getSAMFileHeader(id), programRecord);
+        SAMFileWriterFactory factory = new SAMFileWriterFactory();
+        factory.setCreateIndex(indexOnTheFly);
+        factory.setCreateMd5File(generateMD5);
+        SAMFileWriter sw = factory.makeSAMOrBAMWriter(header, presorted, f);
+        writerMap.put(id,sw);
+    }
+
+    public Collection<SAMFileWriter> getWriters() {
+        return writerMap.values();
+    }
+
+    public void addAlignment(SAMRecord samRecord) {
+        final SAMReaderID id = toolkit.getReaderIDForRead(samRecord);
+        String rg = samRecord.getStringAttribute("RG");
+        if ( rg != null ) {
+            String rg_orig = toolkit.getReadsDataSource().getOriginalReadGroupId(rg);
+            samRecord.setAttribute("RG",rg_orig);
+        }
+        addAlignment(samRecord, id);
+    }
+
+    public void addAlignment(SAMRecord samRecord, SAMReaderID readerID) {
+        writerMap.get(readerID).addAlignment(samRecord);
+    }
+
+    public SAMFileHeader getFileHeader() {
+        return toolkit.getSAMFileHeader();
+    }
+
+    public void close() {
+        for ( SAMFileWriter w : writerMap.values() ) w.close();
+    }
+
+    @Override
+    public void setProgressLogger(final ProgressLoggerInterface logger) {
+        for (final SAMFileWriter writer: writerMap.values()) {
+            writer.setProgressLogger(logger);
+        }
+    }
+}
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/sam/ReadUnclippedStartWithNoTiesComparator.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/sam/ReadUnclippedStartWithNoTiesComparator.java
new file mode 100644
index 0000000..9d2a391
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/sam/ReadUnclippedStartWithNoTiesComparator.java
@@ -0,0 +1,73 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.utils.sam;
+
+import com.google.java.contract.Ensures;
+import com.google.java.contract.Requires;
+import htsjdk.samtools.SAMRecord;
+
+import java.util.Comparator;
+
+public class ReadUnclippedStartWithNoTiesComparator implements Comparator<SAMRecord> {
+    @Requires("c1 >= 0 && c2 >= 0")
+    @Ensures("result == 0 || result == 1 || result == -1")
+    private int compareContigs(int c1, int c2) {
+        if (c1 == c2)
+            return 0;
+        else if (c1 > c2)
+            return 1;
+        return -1;
+    }
+
+    @Requires("r1 != null && r2 != null")
+    @Ensures("result == 0 || result == 1 || result == -1")
+    public int compare(SAMRecord r1, SAMRecord r2) {
+        int result;
+
+        if (r1 == r2)
+            result = 0;
+
+        else if (r1.getReadUnmappedFlag())
+            result = 1;
+        else if (r2.getReadUnmappedFlag())
+            result = -1;
+        else {
+            final int cmpContig = compareContigs(r1.getReferenceIndex(), r2.getReferenceIndex());
+
+            if (cmpContig != 0)
+                result = cmpContig;
+
+            else {
+                if (r1.getUnclippedStart() < r2.getUnclippedStart())
+                    result = -1;
+                else
+                    result = 1;
+            }
+        }
+
+        return result;
+    }
+}
\ No newline at end of file
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/sam/ReadUtils.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/sam/ReadUtils.java
new file mode 100644
index 0000000..7fc1b40
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/sam/ReadUtils.java
@@ -0,0 +1,964 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.utils.sam;
+
+import com.google.java.contract.Ensures;
+import com.google.java.contract.Requires;
+import htsjdk.samtools.*;
+import org.apache.log4j.Logger;
+import org.broadinstitute.gatk.engine.GenomeAnalysisEngine;
+import org.broadinstitute.gatk.engine.io.stubs.SAMFileWriterStub;
+import org.broadinstitute.gatk.utils.*;
+import org.broadinstitute.gatk.utils.collections.Pair;
+import org.broadinstitute.gatk.utils.exceptions.ReviewedGATKException;
+
+import java.io.File;
+import java.util.*;
+
+/**
+ * A miscellaneous collection of utilities for working with SAM files, headers, etc.
+ * Static methods only, please.
+ *
+ * @author mhanna
+ * @version 0.1
+ */
+public class ReadUtils {
+    private final static Logger logger = Logger.getLogger(ReadUtils.class);
+    
+    private static final String OFFSET_OUT_OF_BOUNDS_EXCEPTION = "Offset cannot be greater than read length %d : %d";
+    private static final String OFFSET_NOT_ZERO_EXCEPTION = "We ran past the end of the read and never found the offset, something went wrong!";
+    
+    private ReadUtils() {
+    }
+
+    private static final int DEFAULT_ADAPTOR_SIZE = 100;
+    public static final int CLIPPING_GOAL_NOT_REACHED = -1;
+
+    /**
+     * A marker to tell which end of the read has been clipped
+     */
+    public enum ClippingTail {
+        LEFT_TAIL,
+        RIGHT_TAIL
+    }
+
+    /**
+     * A HashMap of the SAM spec read flag names
+     *
+     * Note: This is not being used right now, but can be useful in the future
+     */
+    private static final Map<Integer, String> readFlagNames = new HashMap<Integer, String>();
+
+    static {
+        readFlagNames.put(0x1, "Paired");
+        readFlagNames.put(0x2, "Proper");
+        readFlagNames.put(0x4, "Unmapped");
+        readFlagNames.put(0x8, "MateUnmapped");
+        readFlagNames.put(0x10, "Forward");
+        //readFlagNames.put(0x20, "MateForward");
+        readFlagNames.put(0x40, "FirstOfPair");
+        readFlagNames.put(0x80, "SecondOfPair");
+        readFlagNames.put(0x100, "NotPrimary");
+        readFlagNames.put(0x200, "NON-PF");
+        readFlagNames.put(0x400, "Duplicate");
+    }
+
+    /**
+     * This enum represents all the different ways in which a read can overlap an interval.
+     *
+     * NO_OVERLAP_CONTIG:
+     * read and interval are in different contigs.
+     *
+     * NO_OVERLAP_LEFT:
+     * the read does not overlap the interval.
+     *
+     *                        |----------------| (interval)
+     *   <---------------->                      (read)
+     *
+     * NO_OVERLAP_RIGHT:
+     * the read does not overlap the interval.
+     *
+     *   |----------------|                      (interval)
+     *                        <----------------> (read)
+     *
+     * OVERLAP_LEFT:
+     * the read starts before the beginning of the interval but ends inside of it
+     *
+     *          |----------------| (interval)
+     *   <---------------->        (read)
+     *
+     * OVERLAP_RIGHT:
+     * the read starts inside the interval but ends outside of it
+     *
+     *   |----------------|     (interval)
+     *       <----------------> (read)
+     *
+     * OVERLAP_LEFT_AND_RIGHT:
+     * the read starts before the interval and ends after the interval
+     *
+     *      |-----------|     (interval)
+     *  <-------------------> (read)
+     *
+     * OVERLAP_CONTAINED:
+     * the read starts and ends inside the interval
+     *
+     *  |----------------|     (interval)
+     *     <-------->          (read)
+     */
+    public enum ReadAndIntervalOverlap {NO_OVERLAP_CONTIG, NO_OVERLAP_LEFT, NO_OVERLAP_RIGHT, NO_OVERLAP_HARDCLIPPED_LEFT, NO_OVERLAP_HARDCLIPPED_RIGHT, OVERLAP_LEFT, OVERLAP_RIGHT, OVERLAP_LEFT_AND_RIGHT, OVERLAP_CONTAINED}
+
+    /**
+     * Creates a SAMFileWriter using all of the features currently set in the engine (command line arguments, ReadTransformers, etc)
+     * @param file the filename to write to
+     * @param engine the engine
+     * @return a SAMFileWriter with the correct options set
+     */
+    public static SAMFileWriter createSAMFileWriter(final String file, final GenomeAnalysisEngine engine) {
+        final SAMFileWriterStub output = new SAMFileWriterStub(engine, new File(file));
+        output.processArguments(engine.getArguments());
+        return output;
+    }
+
+    /**
+     *  As {@link #createSAMFileWriter(String, org.broadinstitute.gatk.engine.GenomeAnalysisEngine)}, but also sets the header
+     */
+    public static SAMFileWriter createSAMFileWriter(final String file, final GenomeAnalysisEngine engine, final SAMFileHeader header) {
+        final SAMFileWriterStub output = (SAMFileWriterStub) createSAMFileWriter(file, engine);
+        output.writeHeader(header);
+        return output;
+    }
+
+    /**
+     * is this base inside the adaptor of the read?
+     *
+     * There are two cases to treat here:
+     *
+     * 1) Read is in the negative strand => Adaptor boundary is on the left tail
+     * 2) Read is in the positive strand => Adaptor boundary is on the right tail
+     *
+     * Note: We return false to all reads that are UNMAPPED or have an weird big insert size (probably due to mismapping or bigger event)
+     *
+     * @param read the read to test
+     * @param basePos base position in REFERENCE coordinates (not read coordinates)
+     * @return whether or not the base is in the adaptor
+     */
+    public static boolean isBaseInsideAdaptor(final GATKSAMRecord read, long basePos) {
+        final int adaptorBoundary = read.getAdaptorBoundary();
+        if (adaptorBoundary == CANNOT_COMPUTE_ADAPTOR_BOUNDARY || read.getInferredInsertSize() > DEFAULT_ADAPTOR_SIZE)
+            return false;
+
+        return read.getReadNegativeStrandFlag() ? basePos <= adaptorBoundary : basePos >= adaptorBoundary;
+    }
+
+    /**
+     * Finds the adaptor boundary around the read and returns the first base inside the adaptor that is closest to
+     * the read boundary. If the read is in the positive strand, this is the first base after the end of the
+     * fragment (Picard calls it 'insert'), if the read is in the negative strand, this is the first base before the
+     * beginning of the fragment.
+     *
+     * There are two cases we need to treat here:
+     *
+     * 1) Our read is in the reverse strand :
+     *
+     *     <----------------------| *
+     *   |--------------------->
+     *
+     *   in these cases, the adaptor boundary is at the mate start (minus one)
+     *
+     * 2) Our read is in the forward strand :
+     *
+     *   |---------------------->   *
+     *     <----------------------|
+     *
+     *   in these cases the adaptor boundary is at the start of the read plus the inferred insert size (plus one)
+     *
+     * @param read the read being tested for the adaptor boundary
+     * @return the reference coordinate for the adaptor boundary (effectively the first base IN the adaptor, closest to the read.
+     * CANNOT_COMPUTE_ADAPTOR_BOUNDARY if the read is unmapped or the mate is mapped to another contig.
+     */
+    public static int getAdaptorBoundary(final SAMRecord read) {
+        if ( ! hasWellDefinedFragmentSize(read) ) {
+            return CANNOT_COMPUTE_ADAPTOR_BOUNDARY;
+        } else if ( read.getReadNegativeStrandFlag() ) {
+            return read.getMateAlignmentStart() - 1;           // case 1 (see header)
+        } else {
+            final int insertSize = Math.abs(read.getInferredInsertSize());    // the inferred insert size can be negative if the mate is mapped before the read (so we take the absolute value)
+            return read.getAlignmentStart() + insertSize + 1;  // case 2 (see header)
+        }
+    }
+
+    public static int CANNOT_COMPUTE_ADAPTOR_BOUNDARY = Integer.MIN_VALUE;
+
+    /**
+     * Can the adaptor sequence of read be reliably removed from the read based on the alignment of
+     * read and its mate?
+     *
+     * @param read the read to check
+     * @return true if it can, false otherwise
+     */
+    public static boolean hasWellDefinedFragmentSize(final SAMRecord read) {
+        if ( read.getInferredInsertSize() == 0 )
+            // no adaptors in reads with mates in another chromosome or unmapped pairs
+            return false;
+        if ( ! read.getReadPairedFlag() )
+            // only reads that are paired can be adaptor trimmed
+            return false;
+        if ( read.getReadUnmappedFlag() || read.getMateUnmappedFlag() )
+            // only reads when both reads are mapped can be trimmed
+            return false;
+//        if ( ! read.getProperPairFlag() )
+//            // note this flag isn't always set properly in BAMs, can will stop us from eliminating some proper pairs
+//            // reads that aren't part of a proper pair (i.e., have strange alignments) can't be trimmed
+//            return false;
+        if ( read.getReadNegativeStrandFlag() == read.getMateNegativeStrandFlag() )
+            // sanity check on getProperPairFlag to ensure that read1 and read2 aren't on the same strand
+            return false;
+
+        if ( read.getReadNegativeStrandFlag() ) {
+            // we're on the negative strand, so our read runs right to left
+            return read.getAlignmentEnd() > read.getMateAlignmentStart();
+        } else {
+            // we're on the positive strand, so our mate should be to our right (his start + insert size should be past our start)
+            return read.getAlignmentStart() <= read.getMateAlignmentStart() + read.getInferredInsertSize();
+        }
+    }
+
+    /**
+     * is the read a 454 read?
+     *
+     * @param read the read to test
+     * @return checks the read group tag PL for the default 454 tag
+     */
+    public static boolean is454Read(GATKSAMRecord read) {
+        return NGSPlatform.fromRead(read) == NGSPlatform.LS454;
+    }
+
+    /**
+     * is the read an IonTorrent read?
+     *
+     * @param read the read to test
+     * @return checks the read group tag PL for the default ion tag
+     */
+    public static boolean isIonRead(GATKSAMRecord read) {
+        return NGSPlatform.fromRead(read) == NGSPlatform.ION_TORRENT;
+    }
+
+    /**
+     * is the read a SOLiD read?
+     *
+     * @param read the read to test
+     * @return checks the read group tag PL for the default SOLiD tag
+     */
+    public static boolean isSOLiDRead(GATKSAMRecord read) {
+        return NGSPlatform.fromRead(read) == NGSPlatform.SOLID;
+    }
+
+    /**
+     * is the read a SLX read?
+     *
+     * @param read the read to test
+     * @return checks the read group tag PL for the default SLX tag
+     */
+    public static boolean isIlluminaRead(GATKSAMRecord read) {
+        return NGSPlatform.fromRead(read) == NGSPlatform.ILLUMINA;
+    }
+
+    /**
+     * checks if the read has a platform tag in the readgroup equal to 'name'.
+     * Assumes that 'name' is upper-cased.
+     *
+     * @param read the read to test
+     * @param name the upper-cased platform name to test
+     * @return whether or not name == PL tag in the read group of read
+     */
+    public static boolean isPlatformRead(GATKSAMRecord read, String name) {
+
+        SAMReadGroupRecord readGroup = read.getReadGroup();
+        if (readGroup != null) {
+            Object readPlatformAttr = readGroup.getAttribute("PL");
+            if (readPlatformAttr != null)
+                return readPlatformAttr.toString().toUpperCase().contains(name);
+        }
+        return false;
+    }
+
+
+    /**
+     * Returns the collections of reads sorted in coordinate order, according to the order defined
+     * in the reads themselves
+     *
+     * @param reads
+     * @return
+     */
+    public final static List<GATKSAMRecord> sortReadsByCoordinate(List<GATKSAMRecord> reads) {
+        final SAMRecordComparator comparer = new SAMRecordCoordinateComparator();
+        Collections.sort(reads, comparer);
+        return reads;
+    }
+
+    /**
+     * If a read starts in INSERTION, returns the first element length.
+     *
+     * Warning: If the read has Hard or Soft clips before the insertion this function will return 0.
+     *
+     * @param read
+     * @return the length of the first insertion, or 0 if there is none (see warning).
+     */
+    public final static int getFirstInsertionOffset(SAMRecord read) {
+        CigarElement e = read.getCigar().getCigarElement(0);
+        if ( e.getOperator() == CigarOperator.I )
+            return e.getLength();
+        else
+            return 0;
+    }
+
+    /**
+     * If a read ends in INSERTION, returns the last element length.
+     *
+     * Warning: If the read has Hard or Soft clips after the insertion this function will return 0.
+     *
+     * @param read
+     * @return the length of the last insertion, or 0 if there is none (see warning).
+     */
+    public final static int getLastInsertionOffset(SAMRecord read) {
+        CigarElement e = read.getCigar().getCigarElement(read.getCigarLength() - 1);
+        if ( e.getOperator() == CigarOperator.I )
+            return e.getLength();
+        else
+            return 0;
+    }
+
+    /**
+     * Determines what is the position of the read in relation to the interval.
+     * Note: This function uses the UNCLIPPED ENDS of the reads for the comparison.
+     * @param read the read
+     * @param interval the interval
+     * @return the overlap type as described by ReadAndIntervalOverlap enum (see above)
+     */
+    public static ReadAndIntervalOverlap getReadAndIntervalOverlapType(GATKSAMRecord read, GenomeLoc interval) {
+
+        int sStart = read.getSoftStart();
+        int sStop = read.getSoftEnd();
+        int uStart = read.getUnclippedStart();
+        int uStop = read.getUnclippedEnd();
+
+        if ( !read.getReferenceName().equals(interval.getContig()) )
+            return ReadAndIntervalOverlap.NO_OVERLAP_CONTIG;
+
+        else if ( uStop < interval.getStart() )
+            return ReadAndIntervalOverlap.NO_OVERLAP_LEFT;
+
+        else if ( uStart > interval.getStop() )
+            return ReadAndIntervalOverlap.NO_OVERLAP_RIGHT;
+
+        else if ( sStop < interval.getStart() )
+            return ReadAndIntervalOverlap.NO_OVERLAP_HARDCLIPPED_LEFT;
+
+        else if ( sStart > interval.getStop() )
+            return ReadAndIntervalOverlap.NO_OVERLAP_HARDCLIPPED_RIGHT;
+
+        else if ( (sStart >= interval.getStart()) &&
+                  (sStop <= interval.getStop()) )
+            return ReadAndIntervalOverlap.OVERLAP_CONTAINED;
+
+        else if ( (sStart < interval.getStart()) &&
+                  (sStop > interval.getStop()) )
+            return ReadAndIntervalOverlap.OVERLAP_LEFT_AND_RIGHT;
+
+        else if ( (sStart < interval.getStart()) )
+            return ReadAndIntervalOverlap.OVERLAP_LEFT;
+
+        else
+            return ReadAndIntervalOverlap.OVERLAP_RIGHT;
+    }
+
+    /**
+     * Pre-processes the results of getReadCoordinateForReferenceCoordinate(GATKSAMRecord, int) to take care of
+     * two corner cases:
+     * 
+     * 1. If clipping the right tail (end of the read) getReadCoordinateForReferenceCoordinate and fall inside
+     * a deletion return the base after the deletion. If clipping the left tail (beginning of the read) it
+     * doesn't matter because it already returns the previous base by default.
+     * 
+     * 2. If clipping the left tail (beginning of the read) getReadCoordinateForReferenceCoordinate and the
+     * read starts with an insertion, and you're requesting the first read based coordinate, it will skip
+     * the leading insertion (because it has the same reference coordinate as the following base).
+     *
+     * @param read
+     * @param refCoord
+     * @param tail
+     * @return the read coordinate corresponding to the requested reference coordinate for clipping.
+     */
+    @Requires({"refCoord >= read.getUnclippedStart()", "refCoord <= read.getUnclippedEnd() || (read.getUnclippedEnd() < read.getUnclippedStart())"})
+    @Ensures({"result >= 0", "result < read.getReadLength()"})
+    public static int getReadCoordinateForReferenceCoordinate(GATKSAMRecord read, int refCoord, ClippingTail tail) {
+        return getReadCoordinateForReferenceCoordinate(read.getSoftStart(), read.getCigar(), refCoord, tail, false);
+    }
+
+    public static int getReadCoordinateForReferenceCoordinateUpToEndOfRead(GATKSAMRecord read, int refCoord, ClippingTail tail) {
+        final int leftmostSafeVariantPosition = Math.max(read.getSoftStart(), refCoord);
+        return getReadCoordinateForReferenceCoordinate(read.getSoftStart(), read.getCigar(), leftmostSafeVariantPosition, tail, false);
+    }
+
+    public static int getReadCoordinateForReferenceCoordinate(final int alignmentStart, final Cigar cigar, final int refCoord, final ClippingTail tail, final boolean allowGoalNotReached) {
+        Pair<Integer, Boolean> result = getReadCoordinateForReferenceCoordinate(alignmentStart, cigar, refCoord, allowGoalNotReached);
+        int readCoord = result.getFirst();
+
+        // Corner case one: clipping the right tail and falls on deletion, move to the next
+        // read coordinate. It is not a problem for the left tail because the default answer
+        // from getReadCoordinateForReferenceCoordinate is to give the previous read coordinate.
+        if (result.getSecond() && tail == ClippingTail.RIGHT_TAIL)
+            readCoord++;
+
+        // clipping the left tail and first base is insertion, go to the next read coordinate
+        // with the same reference coordinate. Advance to the next cigar element, or to the
+        // end of the read if there is no next element.
+        final CigarElement firstElementIsInsertion = readStartsWithInsertion(cigar);
+        if (readCoord == 0 && tail == ClippingTail.LEFT_TAIL && firstElementIsInsertion != null)
+            readCoord = Math.min(firstElementIsInsertion.getLength(), cigar.getReadLength() - 1);
+
+        return readCoord;
+    }
+
+    /**
+     * Returns the read coordinate corresponding to the requested reference coordinate.
+     *
+     * WARNING: if the requested reference coordinate happens to fall inside or just before a deletion (or skipped region) in the read, this function
+     * will return the last read base before the deletion (or skipped region). This function returns a
+     * Pair(int readCoord, boolean fallsInsideOrJustBeforeDeletionOrSkippedRegion) so you can choose which readCoordinate to use when faced with
+     * a deletion (or skipped region).
+     *
+     * SUGGESTION: Use getReadCoordinateForReferenceCoordinate(GATKSAMRecord, int, ClippingTail) instead to get a
+     * pre-processed result according to normal clipping needs. Or you can use this function and tailor the
+     * behavior to your needs.
+     *
+     * @param read
+     * @param refCoord the requested reference coordinate
+     * @return the read coordinate corresponding to the requested reference coordinate. (see warning!)
+     */
+    @Requires({"refCoord >= read.getSoftStart()", "refCoord <= read.getSoftEnd()"})
+    @Ensures({"result.getFirst() >= 0", "result.getFirst() < read.getReadLength()"})
+    //TODO since we do not have contracts any more, should we check for the requirements in the method code?
+    public static Pair<Integer, Boolean> getReadCoordinateForReferenceCoordinate(GATKSAMRecord read, int refCoord) {
+        return getReadCoordinateForReferenceCoordinate(read.getSoftStart(), read.getCigar(), refCoord, false);
+    }
+
+    public static Pair<Integer, Boolean> getReadCoordinateForReferenceCoordinate(final int alignmentStart, final Cigar cigar, final int refCoord, final boolean allowGoalNotReached) {
+        int readBases = 0;
+        int refBases = 0;
+        boolean fallsInsideDeletionOrSkippedRegion = false;
+        boolean endJustBeforeDeletionOrSkippedRegion = false;
+        boolean fallsInsideOrJustBeforeDeletionOrSkippedRegion = false;
+
+        final int goal = refCoord - alignmentStart;  // The goal is to move this many reference bases
+        if (goal < 0) {
+            if (allowGoalNotReached) {
+                return new Pair<Integer, Boolean>(CLIPPING_GOAL_NOT_REACHED, false);
+            } else {
+                throw new ReviewedGATKException("Somehow the requested coordinate is not covered by the read. Too many deletions?");
+            }
+        }
+        boolean goalReached = refBases == goal;
+
+        Iterator<CigarElement> cigarElementIterator = cigar.getCigarElements().iterator();
+        while (!goalReached && cigarElementIterator.hasNext()) {
+            final CigarElement cigarElement = cigarElementIterator.next();
+            int shift = 0;
+
+            if (cigarElement.getOperator().consumesReferenceBases() || cigarElement.getOperator() == CigarOperator.SOFT_CLIP) {
+                if (refBases + cigarElement.getLength() < goal)
+                    shift = cigarElement.getLength();
+                else
+                    shift = goal - refBases;
+
+                refBases += shift;
+            }
+            goalReached = refBases == goal;
+
+            if (!goalReached && cigarElement.getOperator().consumesReadBases())
+                readBases += cigarElement.getLength();
+
+            if (goalReached) {
+                // Is this base's reference position within this cigar element? Or did we use it all?
+                final boolean endsWithinCigar = shift < cigarElement.getLength();
+
+                // If it isn't, we need to check the next one. There should *ALWAYS* be a next one
+                // since we checked if the goal coordinate is within the read length, so this is just a sanity check.
+                if (!endsWithinCigar && !cigarElementIterator.hasNext()) {
+                    if (allowGoalNotReached) {
+                        return new Pair<Integer, Boolean>(CLIPPING_GOAL_NOT_REACHED, false);
+                    } else {
+                        throw new ReviewedGATKException(String.format("Reference coordinate corresponds to a non-existent base in the read. This should never happen -- check read with alignment start: %s  and cigar: %s", alignmentStart, cigar));
+                    }
+                }
+
+                CigarElement nextCigarElement = null;
+
+                // if we end inside the current cigar element, we just have to check if it is a deletion (or skipped region)
+                if (endsWithinCigar)
+                    fallsInsideDeletionOrSkippedRegion = (cigarElement.getOperator() == CigarOperator.DELETION || cigarElement.getOperator() == CigarOperator.SKIPPED_REGION) ;
+
+                // if we end outside the current cigar element, we need to check if the next element is an insertion, deletion or skipped region.
+                else {
+                    nextCigarElement = cigarElementIterator.next();
+
+                    // if it's an insertion, we need to clip the whole insertion before looking at the next element
+                    if (nextCigarElement.getOperator() == CigarOperator.INSERTION) {
+                        readBases += nextCigarElement.getLength();
+                        if (!cigarElementIterator.hasNext()) {
+                            if (allowGoalNotReached) {
+                                return new Pair<Integer, Boolean>(CLIPPING_GOAL_NOT_REACHED, false);
+                            } else {
+                                throw new ReviewedGATKException(String.format("Reference coordinate corresponds to a non-existent base in the read. This should never happen -- check read with alignment start: %s  and cigar: %s", alignmentStart, cigar));
+                            }
+                        }
+
+                        nextCigarElement = cigarElementIterator.next();
+                    }
+
+                    // if it's a deletion (or skipped region), we will pass the information on to be handled downstream.
+                    endJustBeforeDeletionOrSkippedRegion = (nextCigarElement.getOperator() == CigarOperator.DELETION || nextCigarElement.getOperator() == CigarOperator.SKIPPED_REGION);
+                }
+
+                fallsInsideOrJustBeforeDeletionOrSkippedRegion = endJustBeforeDeletionOrSkippedRegion || fallsInsideDeletionOrSkippedRegion;
+
+                // If we reached our goal outside a deletion (or skipped region), add the shift
+                if (!fallsInsideOrJustBeforeDeletionOrSkippedRegion && cigarElement.getOperator().consumesReadBases())
+                    readBases += shift;
+
+                // If we reached our goal just before a deletion (or skipped region) we need
+                // to add the shift of the current cigar element but go back to it's last element to return the last
+                // base before the deletion (or skipped region) (see warning in function contracts)
+                else if (endJustBeforeDeletionOrSkippedRegion && cigarElement.getOperator().consumesReadBases())
+                    readBases += shift - 1;
+
+                // If we reached our goal inside a deletion (or skipped region), or just between a deletion and a skipped region,
+                // then we must backtrack to the last base before the deletion (or skipped region)
+                else if (fallsInsideDeletionOrSkippedRegion ||
+                        (endJustBeforeDeletionOrSkippedRegion && nextCigarElement.getOperator().equals(CigarOperator.N)) ||
+                        (endJustBeforeDeletionOrSkippedRegion && nextCigarElement.getOperator().equals(CigarOperator.D)))
+                    readBases--;
+            }
+        }
+
+        if (!goalReached) {
+            if (allowGoalNotReached) {
+                return new Pair<Integer, Boolean>(CLIPPING_GOAL_NOT_REACHED, false);
+            } else {
+                throw new ReviewedGATKException("Somehow the requested coordinate is not covered by the read. Alignment " + alignmentStart + " | " + cigar);
+            }
+        }
+
+        return new Pair<Integer, Boolean>(readBases, fallsInsideOrJustBeforeDeletionOrSkippedRegion);
+    }
+
+    /**
+     * Compares two SAMRecords only the basis on alignment start.  Note that
+     * comparisons are performed ONLY on the basis of alignment start; any
+     * two SAM records with the same alignment start will be considered equal.
+     *
+     * Unmapped alignments will all be considered equal.
+     */
+
+    @Requires({"read1 != null", "read2 != null"})
+    public static int compareSAMRecords(GATKSAMRecord read1, GATKSAMRecord read2) {
+        AlignmentStartComparator comp = new AlignmentStartComparator();
+        return comp.compare(read1, read2);
+    }
+
+    /**
+     * Is a base inside a read?
+     *
+     * @param read                the read to evaluate
+     * @param referenceCoordinate the reference coordinate of the base to test
+     * @return true if it is inside the read, false otherwise.
+     */
+    public static boolean isInsideRead(final GATKSAMRecord read, final int referenceCoordinate) {
+        return referenceCoordinate >= read.getAlignmentStart() && referenceCoordinate <= read.getAlignmentEnd();
+    }
+
+    /**
+     * Is this read all insertion?
+     *
+     * @param read
+     * @return whether or not the only element in the cigar string is an Insertion
+     */
+    public static boolean readIsEntirelyInsertion(GATKSAMRecord read) {
+        for (CigarElement cigarElement : read.getCigar().getCigarElements()) {
+            if (cigarElement.getOperator() != CigarOperator.INSERTION)
+                return false;
+        }
+        return true;
+    }
+
+    /**
+     * @see #readStartsWithInsertion(htsjdk.samtools.Cigar, boolean) with ignoreClipOps set to true
+     */
+    public static CigarElement readStartsWithInsertion(final Cigar cigarForRead) {
+        return readStartsWithInsertion(cigarForRead, true);
+    }
+
+    /**
+     * Checks if a read starts with an insertion.
+     *
+     * @param cigarForRead    the CIGAR to evaluate
+     * @param ignoreSoftClipOps   should we ignore S operators when evaluating whether an I operator is at the beginning?  Note that H operators are always ignored.
+     * @return the element if it's a leading insertion or null otherwise
+     */
+    public static CigarElement readStartsWithInsertion(final Cigar cigarForRead, final boolean ignoreSoftClipOps) {
+        for ( final CigarElement cigarElement : cigarForRead.getCigarElements() ) {
+            if ( cigarElement.getOperator() == CigarOperator.INSERTION )
+                return cigarElement;
+
+            else if ( cigarElement.getOperator() != CigarOperator.HARD_CLIP && ( !ignoreSoftClipOps || cigarElement.getOperator() != CigarOperator.SOFT_CLIP) )
+                break;
+        }
+        return null;
+    }
+
+    /**
+     * Returns the coverage distribution of a list of reads within the desired region.
+     *
+     * See getCoverageDistributionOfRead for information on how the coverage is calculated.
+     *
+     * @param list          the list of reads covering the region
+     * @param startLocation the first reference coordinate of the region (inclusive)
+     * @param stopLocation  the last reference coordinate of the region (inclusive)
+     * @return an array with the coverage of each position from startLocation to stopLocation
+     */
+    public static int [] getCoverageDistributionOfReads(List<GATKSAMRecord> list, int startLocation, int stopLocation) {
+        int [] totalCoverage = new int[stopLocation - startLocation + 1];
+
+        for (GATKSAMRecord read : list) {
+            int [] readCoverage = getCoverageDistributionOfRead(read, startLocation, stopLocation);
+            totalCoverage = MathUtils.addArrays(totalCoverage, readCoverage);
+        }
+
+        return totalCoverage;
+    }
+
+    /**
+     * Returns the coverage distribution of a single read within the desired region.
+     *
+     * Note: This function counts DELETIONS as coverage (since the main purpose is to downsample
+     * reads for variant regions, and deletions count as variants)
+     *
+     * @param read          the read to get the coverage distribution of
+     * @param startLocation the first reference coordinate of the region (inclusive)
+     * @param stopLocation  the last reference coordinate of the region (inclusive)
+     * @return an array with the coverage of each position from startLocation to stopLocation
+     */
+    public static int [] getCoverageDistributionOfRead(GATKSAMRecord read, int startLocation, int stopLocation) {
+        int [] coverage = new int[stopLocation - startLocation + 1];
+        int refLocation = read.getSoftStart();
+        for (CigarElement cigarElement : read.getCigar().getCigarElements()) {
+            switch (cigarElement.getOperator()) {
+                case S:
+                case M:
+                case EQ:
+                case N:
+                case X:
+                case D:
+                    for (int i = 0; i < cigarElement.getLength(); i++) {
+                        if (refLocation >= startLocation && refLocation <= stopLocation) {
+                            coverage[refLocation - startLocation]++;
+                        }
+                        refLocation++;
+                    }
+                    break;
+
+                case P:
+                case I:
+                case H:
+                    break;
+            }
+
+            if (refLocation > stopLocation)
+                break;
+        }
+        return coverage;
+    }
+
+    /**
+     * Makes association maps for the reads and loci coverage as described below :
+     *
+     *  - First: locusToReadMap -- a HashMap that describes for each locus, which reads contribute to its coverage.
+     *    Note: Locus is in reference coordinates.
+     *    Example: Locus => {read1, read2, ..., readN}
+     *
+     *  - Second: readToLocusMap -- a HashMap that describes for each read what loci it contributes to the coverage.
+     *    Note: Locus is a boolean array, indexed from 0 (= startLocation) to N (= stopLocation), with value==true meaning it contributes to the coverage.
+     *    Example: Read => {true, true, false, ... false}
+     *
+     * @param readList      the list of reads to generate the association mappings
+     * @param startLocation the first reference coordinate of the region (inclusive)
+     * @param stopLocation  the last reference coordinate of the region (inclusive)
+     * @return the two hashmaps described above
+     */
+    public static Pair<HashMap<Integer, HashSet<GATKSAMRecord>> , HashMap<GATKSAMRecord, Boolean[]>> getBothReadToLociMappings (List<GATKSAMRecord> readList, int startLocation, int stopLocation) {
+        int arraySize = stopLocation - startLocation + 1;
+
+        HashMap<Integer, HashSet<GATKSAMRecord>> locusToReadMap = new HashMap<Integer, HashSet<GATKSAMRecord>>(2*(stopLocation - startLocation + 1), 0.5f);
+        HashMap<GATKSAMRecord, Boolean[]> readToLocusMap = new HashMap<GATKSAMRecord, Boolean[]>(2*readList.size(), 0.5f);
+
+        for (int i = startLocation; i <= stopLocation; i++)
+            locusToReadMap.put(i, new HashSet<GATKSAMRecord>()); // Initialize the locusToRead map with empty lists
+
+        for (GATKSAMRecord read : readList) {
+            readToLocusMap.put(read, new Boolean[arraySize]);       // Initialize the readToLocus map with empty arrays
+
+            int [] readCoverage = getCoverageDistributionOfRead(read, startLocation, stopLocation);
+
+            for (int i = 0; i < readCoverage.length; i++) {
+                int refLocation = i + startLocation;
+                if (readCoverage[i] > 0) {
+                    // Update the hash for this locus
+                    HashSet<GATKSAMRecord> readSet = locusToReadMap.get(refLocation);
+                    readSet.add(read);
+
+                    // Add this locus to the read hash
+                    readToLocusMap.get(read)[refLocation - startLocation] = true;
+                }
+                else
+                    // Update the boolean array with a 'no coverage' from this read to this locus
+                    readToLocusMap.get(read)[refLocation-startLocation] = false;
+            }
+        }
+        return new Pair<HashMap<Integer, HashSet<GATKSAMRecord>>, HashMap<GATKSAMRecord, Boolean[]>>(locusToReadMap, readToLocusMap);
+    }
+
+    /**
+     * Create random read qualities
+     *
+     * @param length the length of the read
+     * @return an array with randomized base qualities between 0 and 50
+     */
+    public static byte[] createRandomReadQuals(int length) {
+        Random random = GenomeAnalysisEngine.getRandomGenerator();
+        byte[] quals = new byte[length];
+        for (int i = 0; i < length; i++)
+            quals[i] = (byte) random.nextInt(50);
+        return quals;
+    }
+
+    /**
+     * Create random read qualities
+     *
+     * @param length  the length of the read
+     * @param allowNs whether or not to allow N's in the read
+     * @return an array with randomized bases (A-N) with equal probability
+     */
+    public static byte[] createRandomReadBases(int length, boolean allowNs) {
+        Random random = GenomeAnalysisEngine.getRandomGenerator();
+        int numberOfBases = allowNs ? 5 : 4;
+        byte[] bases = new byte[length];
+        for (int i = 0; i < length; i++) {
+            switch (random.nextInt(numberOfBases)) {
+                case 0:
+                    bases[i] = 'A';
+                    break;
+                case 1:
+                    bases[i] = 'C';
+                    break;
+                case 2:
+                    bases[i] = 'G';
+                    break;
+                case 3:
+                    bases[i] = 'T';
+                    break;
+                case 4:
+                    bases[i] = 'N';
+                    break;
+                default:
+                    throw new ReviewedGATKException("Something went wrong, this is just impossible");
+            }
+        }
+        return bases;
+    }
+
+    public static GATKSAMRecord createRandomRead(int length) {
+        return createRandomRead(length, true);
+    }
+
+    public static GATKSAMRecord createRandomRead(int length, boolean allowNs) {
+        byte[] quals = ReadUtils.createRandomReadQuals(length);
+        byte[] bbases = ReadUtils.createRandomReadBases(length, allowNs);
+        return ArtificialSAMUtils.createArtificialRead(bbases, quals, bbases.length + "M");
+    }
+
+
+    public static String prettyPrintSequenceRecords ( SAMSequenceDictionary sequenceDictionary ) {
+        String[] sequenceRecordNames = new String[sequenceDictionary.size()];
+        int sequenceRecordIndex = 0;
+        for (SAMSequenceRecord sequenceRecord : sequenceDictionary.getSequences())
+            sequenceRecordNames[sequenceRecordIndex++] = sequenceRecord.getSequenceName();
+        return Arrays.deepToString(sequenceRecordNames);
+    }
+
+    /**
+     * Calculates the reference coordinate for a read coordinate
+     *
+     * @param read   the read
+     * @param offset the base in the read (coordinate in the read)
+     * @return the reference coordinate correspondent to this base
+     */
+    public static long getReferenceCoordinateForReadCoordinate(GATKSAMRecord read, int offset) {
+        if (offset > read.getReadLength()) 
+            throw new ReviewedGATKException(String.format(OFFSET_OUT_OF_BOUNDS_EXCEPTION, offset, read.getReadLength()));
+
+        long location = read.getAlignmentStart();
+        Iterator<CigarElement> cigarElementIterator = read.getCigar().getCigarElements().iterator();
+        while (offset > 0 && cigarElementIterator.hasNext()) {
+            CigarElement cigarElement = cigarElementIterator.next();
+            long move = 0;
+            if (cigarElement.getOperator().consumesReferenceBases())  
+                move = (long) Math.min(cigarElement.getLength(), offset);
+            location += move;
+            offset -= move;
+        }
+        if (offset > 0 && !cigarElementIterator.hasNext()) 
+            throw new ReviewedGATKException(OFFSET_NOT_ZERO_EXCEPTION);
+
+        return location;
+    }
+
+    /**
+     * Creates a map with each event in the read (cigar operator) and the read coordinate where it happened.
+     *
+     * Example:
+     *  D -> 2, 34, 75
+     *  I -> 55
+     *  S -> 0, 101
+     *  H -> 101
+     *
+     * @param read the read
+     * @return a map with the properties described above. See example
+     */
+    public static Map<CigarOperator, ArrayList<Integer>> getCigarOperatorForAllBases (GATKSAMRecord read) {
+        Map<CigarOperator, ArrayList<Integer>> events = new HashMap<CigarOperator, ArrayList<Integer>>();
+
+        int position = 0;
+        for (CigarElement cigarElement : read.getCigar().getCigarElements()) {
+            CigarOperator op = cigarElement.getOperator();
+            if (op.consumesReadBases()) {
+                ArrayList<Integer> list = events.get(op);
+                if (list == null) {
+                    list = new ArrayList<Integer>();
+                    events.put(op, list);
+                }
+                for (int i = position; i < cigarElement.getLength(); i++)
+                    list.add(position++);
+            }
+            else {
+                ArrayList<Integer> list = events.get(op);
+                if (list == null) {
+                    list = new ArrayList<Integer>();
+                    events.put(op, list);
+                }
+                list.add(position);
+            }
+        }
+        return events;
+    }
+
+    /**
+     * Given a read, outputs the read bases in a string format
+     *
+     * @param read the read
+     * @return a string representation of the read bases
+     */
+    public static String convertReadBasesToString(GATKSAMRecord read) {
+        String bases = "";
+        for (byte b : read.getReadBases()) {
+            bases += (char) b;
+        }
+        return bases.toUpperCase();
+    }
+
+    /**
+     * Given a read, outputs the base qualities in a string format
+     *
+     * @param quals the read qualities
+     * @return a string representation of the base qualities
+     */
+    public static String convertReadQualToString(byte[] quals) {
+        String result = "";
+        for (byte b : quals) {
+            result += (char) (33 + b);
+        }
+        return result;
+    }
+
+    /**
+     * Given a read, outputs the base qualities in a string format
+     *
+     * @param read the read
+     * @return a string representation of the base qualities
+     */
+    public static String convertReadQualToString(GATKSAMRecord read) {
+        return convertReadQualToString(read.getBaseQualities());
+    }
+
+    /**
+     * Returns the reverse complement of the read bases
+     *
+     * @param bases the read bases
+     * @return the reverse complement of the read bases
+     */
+    public static String getBasesReverseComplement(byte[] bases) {
+        String reverse = "";
+        for (int i = bases.length-1; i >=0; i--) {
+            reverse += (char) BaseUtils.getComplement(bases[i]);
+        }
+        return reverse;
+    }
+
+    /**
+     * Returns the reverse complement of the read bases
+     *
+     * @param read the read
+     * @return the reverse complement of the read bases
+     */
+    public static String getBasesReverseComplement(GATKSAMRecord read) {
+        return getBasesReverseComplement(read.getReadBases());
+    }
+
+    /**
+     * Calculate the maximum read length from the given list of reads.
+     * @param reads list of reads
+     * @return      non-negative integer
+     */
+    @Ensures({"result >= 0"})
+    public static int getMaxReadLength( final List<GATKSAMRecord> reads ) {
+        if( reads == null ) { throw new IllegalArgumentException("Attempting to check a null list of reads."); }
+
+        int maxReadLength = 0;
+        for( final GATKSAMRecord read : reads ) {
+            maxReadLength = Math.max(maxReadLength, read.getReadLength());
+        }
+        return maxReadLength;
+    }
+}
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/sam/SAMFileReaderBuilder.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/sam/SAMFileReaderBuilder.java
new file mode 100644
index 0000000..2c5ea5f
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/sam/SAMFileReaderBuilder.java
@@ -0,0 +1,84 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.utils.sam;
+
+import htsjdk.samtools.SAMFileReader;
+import htsjdk.samtools.ValidationStringency;
+import org.broadinstitute.gatk.utils.exceptions.ReviewedGATKException;
+
+import java.io.File;
+
+/**
+ * Allows the user to steadily accumulate information about what
+ * components go into a SAM file writer, ultimately using this
+ * information to create a SAM file writer on demand.
+ *
+ * @author mhanna
+ * @version 0.1
+ */
+public class SAMFileReaderBuilder {
+    /**
+     * To which file should output be written?
+     */
+    private File samFile = null;
+
+    /**
+     * What compression level should be used when building this file?
+     */
+    private ValidationStringency validationStringency = null;
+
+    /**
+     * Sets the handle of the sam file to which data should be written.
+     * @param samFile The SAM file into which data should flow.
+     */
+    public void setSAMFile( File samFile ) {
+        this.samFile = samFile;
+    }
+
+    /**
+     * Sets the validation stringency to apply when reading this sam file.
+     * @param validationStringency Stringency to apply.  Must not be null.
+     */
+    public void setValidationStringency( ValidationStringency validationStringency ) {
+        this.validationStringency = validationStringency;
+    }
+
+    /**
+     * Create the SAM writer, given the constituent parts accrued.
+     * @return Newly minted SAM file writer.
+     */
+    public SAMFileReader build() {
+        if( samFile == null )
+            throw new ReviewedGATKException( "Filename for output sam file must be supplied.");
+        if( validationStringency == null )
+            throw new ReviewedGATKException( "Header for output sam file must be supplied.");
+
+        SAMFileReader reader = new SAMFileReader( samFile );
+        reader.setValidationStringency( validationStringency );
+
+        return reader;
+    }
+}
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/sam/SimplifyingSAMFileWriter.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/sam/SimplifyingSAMFileWriter.java
new file mode 100644
index 0000000..4214619
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/sam/SimplifyingSAMFileWriter.java
@@ -0,0 +1,86 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.utils.sam;
+
+import htsjdk.samtools.SAMFileHeader;
+import htsjdk.samtools.SAMFileWriter;
+import htsjdk.samtools.SAMRecord;
+import htsjdk.samtools.util.ProgressLoggerInterface;
+
+/**
+ * XXX
+ */
+public class SimplifyingSAMFileWriter implements SAMFileWriter {
+    final SAMFileWriter dest;
+
+    public SimplifyingSAMFileWriter(final SAMFileWriter finalDestination) {
+        this.dest = finalDestination;
+    }
+
+    public void addAlignment( SAMRecord read ) {
+        if ( keepRead(read) ) {
+            dest.addAlignment(simplifyRead(read));
+
+        }
+    }
+
+    /**
+     * Retrieves the header to use when creating the new SAM file.
+     * @return header to use when creating the new SAM file.
+     */
+    public SAMFileHeader getFileHeader() {
+        return dest.getFileHeader();
+    }
+
+    /**
+     * @{inheritDoc}
+     */
+    public void close() {
+        dest.close();
+    }
+
+
+    public static final boolean keepRead(SAMRecord read) {
+        return ! excludeRead(read);
+    }
+
+    public static final boolean excludeRead(SAMRecord read) {
+        return read.getReadUnmappedFlag() || read.getReadFailsVendorQualityCheckFlag() || read.getDuplicateReadFlag() || read.getNotPrimaryAlignmentFlag();
+    }
+
+    public static final SAMRecord simplifyRead(SAMRecord read) {
+        // the only attribute we keep is the RG
+        Object rg = read.getAttribute("RG");
+        read.clearAttributes();
+        read.setAttribute("RG", rg);
+        return read;
+    }
+
+    @Override
+    public void setProgressLogger(final ProgressLoggerInterface logger) {
+        dest.setProgressLogger(logger);
+    }
+}
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/sam/package-info.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/sam/package-info.java
new file mode 100644
index 0000000..ee2bcec
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/sam/package-info.java
@@ -0,0 +1,26 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.utils.sam;
\ No newline at end of file
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/smithwaterman/GlobalEdgeGreedySWPairwiseAlignment.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/smithwaterman/GlobalEdgeGreedySWPairwiseAlignment.java
new file mode 100644
index 0000000..666ca8b
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/smithwaterman/GlobalEdgeGreedySWPairwiseAlignment.java
@@ -0,0 +1,208 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.utils.smithwaterman;
+
+import htsjdk.samtools.Cigar;
+import htsjdk.samtools.CigarElement;
+import org.broadinstitute.gatk.utils.Utils;
+import org.broadinstitute.gatk.utils.sam.AlignmentUtils;
+
+import java.util.*;
+
+/**
+ * Pairwise discrete Smith-Waterman alignment with an edge greedy implementation
+ *
+ * ************************************************************************
+ * ****                    IMPORTANT NOTE:                             ****
+ * ****  This class assumes that all bytes come from UPPERCASED chars! ****
+ * ************************************************************************
+ *
+ * User: ebanks
+ */
+public final class GlobalEdgeGreedySWPairwiseAlignment extends SWPairwiseAlignment {
+
+    private final static boolean DEBUG_MODE = false;
+
+    /**
+     * Create a new greedy SW pairwise aligner
+     *
+     * @param reference the reference sequence we want to align
+     * @param alternate the alternate sequence we want to align
+     * @param parameters the SW parameters to use
+     */
+    public GlobalEdgeGreedySWPairwiseAlignment(final byte[] reference, final byte[] alternate, final Parameters parameters) {
+        super(reference, alternate, parameters);
+    }
+
+    /**
+     * Create a new SW pairwise aligner
+     *
+     * After creating the object the two sequences are aligned with an internal call to align(seq1, seq2)
+     *
+     * @param reference the reference sequence we want to align
+     * @param alternate the alternate sequence we want to align
+     * @param namedParameters the named parameter set to get our parameters from
+     */
+    public GlobalEdgeGreedySWPairwiseAlignment(final byte[] reference, final byte[] alternate, final SWParameterSet namedParameters) {
+        this(reference, alternate, namedParameters.parameters);
+    }
+
+    /**
+     * @see #GlobalEdgeGreedySWPairwiseAlignment(byte[], byte[], SWParameterSet) with original default parameters
+     */
+    public GlobalEdgeGreedySWPairwiseAlignment(byte[] reference, byte[] alternate) {
+        this(reference, alternate, SWParameterSet.ORIGINAL_DEFAULT);
+    }
+
+    /**
+     * Aligns the alternate sequence to the reference sequence
+     *
+     * @param reference  ref sequence
+     * @param alternate  alt sequence
+     */
+    @Override
+    protected void align(final byte[] reference, final byte[] alternate) {
+        if ( reference == null || reference.length == 0 )
+            throw new IllegalArgumentException("Non-null, non-empty reference sequences are required for the Smith-Waterman calculation");
+        if ( alternate == null || alternate.length == 0 )
+            throw new IllegalArgumentException("Non-null, non-empty alternate sequences are required for the Smith-Waterman calculation");
+
+        final int forwardEdgeMatch = Utils.longestCommonPrefix(reference, alternate, Integer.MAX_VALUE);
+
+        // edge case: one sequence is a strict prefix of the other
+        if ( forwardEdgeMatch == reference.length || forwardEdgeMatch == alternate.length ) {
+            alignmentResult = new SWPairwiseAlignmentResult(makeCigarForStrictPrefixAndSuffix(reference, alternate, forwardEdgeMatch, 0), 0);
+            return;
+        }
+
+        int reverseEdgeMatch = Utils.longestCommonSuffix(reference, alternate, Integer.MAX_VALUE);
+
+        // edge case: one sequence is a strict suffix of the other
+        if ( reverseEdgeMatch == reference.length || reverseEdgeMatch == alternate.length ) {
+            alignmentResult = new SWPairwiseAlignmentResult(makeCigarForStrictPrefixAndSuffix(reference, alternate, 0, reverseEdgeMatch), 0);
+            return;
+        }
+
+        final int sizeOfRefToAlign = reference.length - forwardEdgeMatch - reverseEdgeMatch;
+        final int sizeOfAltToAlign = alternate.length - forwardEdgeMatch - reverseEdgeMatch;
+
+        // edge case: one sequence is a strict subset of the other accounting for both prefix and suffix
+        final int minSizeToAlign = Math.min(sizeOfRefToAlign, sizeOfAltToAlign);
+        if ( minSizeToAlign < 0 )
+            reverseEdgeMatch += minSizeToAlign;
+        if ( sizeOfRefToAlign <= 0 || sizeOfAltToAlign <= 0 ) {
+            alignmentResult = new SWPairwiseAlignmentResult(makeCigarForStrictPrefixAndSuffix(reference, alternate, forwardEdgeMatch, reverseEdgeMatch), 0);
+            return;
+        }
+
+        final byte[] refToAlign = Utils.trimArray(reference, forwardEdgeMatch, reverseEdgeMatch);
+        final byte[] altToAlign = Utils.trimArray(alternate, forwardEdgeMatch, reverseEdgeMatch);
+
+        final int[][] sw = new int[(sizeOfRefToAlign+1)][(sizeOfAltToAlign+1)];
+        if ( keepScoringMatrix ) SW = sw;
+        final int[][] btrack = new int[(sizeOfRefToAlign+1)][(sizeOfAltToAlign+1)];
+
+        calculateMatrix(refToAlign, altToAlign, sw, btrack, OVERHANG_STRATEGY.INDEL);
+
+        if ( DEBUG_MODE ) {
+            System.out.println(new String(refToAlign) + " vs. " + new String(altToAlign));
+            debugMatrix(sw);
+            System.out.println("----");
+            debugMatrix(btrack);
+            System.out.println();
+        }
+
+        alignmentResult = calculateCigar(forwardEdgeMatch, reverseEdgeMatch, sw, btrack);
+    }
+
+
+    private void debugMatrix(final int[][] matrix) {
+        for ( int i = 0; i < matrix.length; i++ ) {
+            int [] cur = matrix[i];
+            for ( int j = 0; j < cur.length; j++ )
+                System.out.print(cur[j] + " ");
+            System.out.println();
+        }
+    }
+
+    /**
+     * Creates a CIGAR for the case where the prefix/suffix match combination encompasses an entire sequence
+     *
+     * @param reference            the reference sequence
+     * @param alternate            the alternate sequence
+     * @param matchingPrefix       the prefix match size
+     * @param matchingSuffix       the suffix match size
+     * @return non-null CIGAR
+     */
+    private Cigar makeCigarForStrictPrefixAndSuffix(final byte[] reference, final byte[] alternate, final int matchingPrefix, final int matchingSuffix) {
+
+        final List<CigarElement> result = new ArrayList<CigarElement>();
+
+        // edge case: no D or I element
+        if ( reference.length == alternate.length ) {
+            result.add(makeElement(State.MATCH, matchingPrefix + matchingSuffix));
+        } else {
+            // add the first M element
+            if ( matchingPrefix > 0 )
+                result.add(makeElement(State.MATCH, matchingPrefix));
+
+            // add the D or I element
+            if ( alternate.length > reference.length )
+                result.add(makeElement(State.INSERTION, alternate.length - reference.length));
+            else // if ( reference.length > alternate.length )
+                result.add(makeElement(State.DELETION, reference.length - alternate.length));
+
+            // add the last M element
+            if ( matchingSuffix > 0 )
+                result.add(makeElement(State.MATCH, matchingSuffix));
+        }
+
+        return new Cigar(result);
+    }
+
+    /**
+     * Calculates the CIGAR for the alignment from the back track matrix
+     *
+     * @param matchingPrefix       the prefix match size
+     * @param matchingSuffix       the suffix match size
+     * @param sw                   the Smith-Waterman matrix to use
+     * @param btrack               the back track matrix to use
+     * @return non-null SWPairwiseAlignmentResult object
+     */
+    protected SWPairwiseAlignmentResult calculateCigar(final int matchingPrefix, final int matchingSuffix,
+                                                       final int[][] sw, final int[][] btrack) {
+
+        final SWPairwiseAlignmentResult SW_result = calculateCigar(sw, btrack, OVERHANG_STRATEGY.INDEL);
+
+        final LinkedList<CigarElement> lce = new LinkedList<CigarElement>(SW_result.cigar.getCigarElements());
+        if ( matchingPrefix > 0 )
+            lce.addFirst(makeElement(State.MATCH, matchingPrefix));
+        if ( matchingSuffix > 0 )
+            lce.addLast(makeElement(State.MATCH, matchingSuffix));
+
+        return new SWPairwiseAlignmentResult(AlignmentUtils.consolidateCigar(new Cigar(lce)), 0);
+    }
+}
\ No newline at end of file
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/smithwaterman/Parameters.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/smithwaterman/Parameters.java
new file mode 100644
index 0000000..46cb8be
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/smithwaterman/Parameters.java
@@ -0,0 +1,62 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.utils.smithwaterman;
+
+/**
+ * Holds the core Smith-Waterman alignment parameters of
+ *
+ * match value, and mismatch, gap open and gap extension penalties
+ *
+ * User: depristo
+ * Date: 4/11/13
+ * Time: 12:03 PM
+ */
+public final class Parameters {
+    public final int w_match;
+    public final int w_mismatch;
+    public final int w_open;
+    public final int w_extend;
+
+    /**
+     * Create a new set of SW parameters
+     * @param w_match the match score
+     * @param w_mismatch the mismatch penalty
+     * @param w_open the gap open penalty
+     * @param w_extend the gap extension penalty
+
+     */
+    public Parameters(final int w_match, final int w_mismatch, final int w_open, final int w_extend) {
+        if ( w_mismatch > 0 ) throw new IllegalArgumentException("w_mismatch must be <= 0 but got " + w_mismatch);
+        if ( w_open> 0 ) throw new IllegalArgumentException("w_open must be <= 0 but got " + w_open);
+        if ( w_extend> 0 ) throw new IllegalArgumentException("w_extend must be <= 0 but got " + w_extend);
+
+        this.w_match = w_match;
+        this.w_mismatch = w_mismatch;
+        this.w_open = w_open;
+        this.w_extend = w_extend;
+    }
+
+}
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/smithwaterman/SWPairwiseAlignment.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/smithwaterman/SWPairwiseAlignment.java
new file mode 100644
index 0000000..aa38c06
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/smithwaterman/SWPairwiseAlignment.java
@@ -0,0 +1,599 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.utils.smithwaterman;
+
+import htsjdk.samtools.Cigar;
+import htsjdk.samtools.CigarElement;
+import htsjdk.samtools.CigarOperator;
+import org.broadinstitute.gatk.utils.exceptions.GATKException;
+import org.broadinstitute.gatk.utils.sam.AlignmentUtils;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+
+/**
+ * Pairwise discrete smith-waterman alignment
+ *
+ * ************************************************************************
+ * ****                    IMPORTANT NOTE:                             ****
+ * ****  This class assumes that all bytes come from UPPERCASED chars! ****
+ * ************************************************************************
+ *
+ * User: asivache
+ * Date: Mar 23, 2009
+ * Time: 1:54:54 PM
+ */
+public class SWPairwiseAlignment implements SmithWaterman {
+
+    protected SWPairwiseAlignmentResult alignmentResult;
+
+    protected final Parameters parameters;
+
+    /**
+     * The state of a trace step through the matrix
+     */
+    protected enum State {
+        MATCH,
+        INSERTION,
+        DELETION,
+        CLIP
+    }
+
+    /**
+     * What strategy should we use when the best path does not start/end at the corners of the matrix?
+     */
+    public enum OVERHANG_STRATEGY {
+        /*
+         * Add softclips for the overhangs
+         */
+        SOFTCLIP,
+
+        /*
+         * Treat the overhangs as proper insertions/deletions
+         */
+        INDEL,
+
+        /*
+         * Treat the overhangs as proper insertions/deletions for leading (but not trailing) overhangs.
+         * This is useful e.g. when we want to merge dangling tails in an assembly graph: because we don't
+         * expect the dangling tail to reach the end of the reference path we are okay ignoring trailing
+         * deletions - but leading indels are still very much relevant.
+         */
+        LEADING_INDEL,
+
+        /*
+         * Just ignore the overhangs
+         */
+        IGNORE
+    }
+
+    protected static boolean cutoff = false;
+
+    protected OVERHANG_STRATEGY overhang_strategy = OVERHANG_STRATEGY.SOFTCLIP;
+
+    /**
+     * The SW scoring matrix, stored for debugging purposes if keepScoringMatrix is true
+     */
+    protected int[][] SW = null;
+
+    /**
+     * Only for testing purposes in the SWPairwiseAlignmentMain function
+     * set to true to keep SW scoring matrix after align call
+     */
+    protected static boolean keepScoringMatrix = false;
+
+    /**
+     * Create a new SW pairwise aligner.
+     *
+     * @deprecated in favor of constructors using the Parameter or ParameterSet class
+     */
+    @Deprecated
+    public SWPairwiseAlignment(byte[] seq1, byte[] seq2, int match, int mismatch, int open, int extend ) {
+        this(seq1, seq2, new Parameters(match, mismatch, open, extend));
+    }
+
+    /**
+     * Create a new SW pairwise aligner
+     *
+     * After creating the object the two sequences are aligned with an internal call to align(seq1, seq2)
+     *
+     * @param seq1 the first sequence we want to align
+     * @param seq2 the second sequence we want to align
+     * @param parameters the SW parameters to use
+     */
+    public SWPairwiseAlignment(byte[] seq1, byte[] seq2, Parameters parameters) {
+        this(parameters);
+        align(seq1,seq2);
+    }
+
+    /**
+     * Create a new SW pairwise aligner
+     *
+     * After creating the object the two sequences are aligned with an internal call to align(seq1, seq2)
+     *
+     * @param seq1 the first sequence we want to align
+     * @param seq2 the second sequence we want to align
+     * @param parameters the SW parameters to use
+     * @param strategy   the overhang strategy to use
+     */
+    public SWPairwiseAlignment(final byte[] seq1, final byte[] seq2, final SWParameterSet parameters, final OVERHANG_STRATEGY strategy) {
+        this(parameters.parameters);
+        overhang_strategy = strategy;
+        align(seq1, seq2);
+    }
+
+    /**
+     * Create a new SW pairwise aligner, without actually doing any alignment yet
+     *
+     * @param parameters the SW parameters to use
+     */
+    protected SWPairwiseAlignment(final Parameters parameters) {
+        this.parameters = parameters;
+    }
+
+    /**
+     * Create a new SW pairwise aligner
+     *
+     * After creating the object the two sequences are aligned with an internal call to align(seq1, seq2)
+     *
+     * @param seq1 the first sequence we want to align
+     * @param seq2 the second sequence we want to align
+     * @param namedParameters the named parameter set to get our parameters from
+     */
+    public SWPairwiseAlignment(byte[] seq1, byte[] seq2, SWParameterSet namedParameters) {
+        this(seq1, seq2, namedParameters.parameters);
+    }
+
+    public SWPairwiseAlignment(byte[] seq1, byte[] seq2) {
+        this(seq1,seq2,SWParameterSet.ORIGINAL_DEFAULT);
+    }
+
+    @Override
+    public Cigar getCigar() { return alignmentResult.cigar ; }
+
+    @Override
+    public int getAlignmentStart2wrt1() { return alignmentResult.alignment_offset; }
+
+    /**
+     * Aligns the alternate sequence to the reference sequence
+     *
+     * @param reference  ref sequence
+     * @param alternate  alt sequence
+     */
+    protected void align(final byte[] reference, final byte[] alternate) {
+        if ( reference == null || reference.length == 0 || alternate == null || alternate.length == 0 )
+            throw new IllegalArgumentException("Non-null, non-empty sequences are required for the Smith-Waterman calculation");
+
+        final int n = reference.length+1;
+        final int m = alternate.length+1;
+        int[][] sw = new int[n][m];
+        if ( keepScoringMatrix ) SW = sw;
+        int[][] btrack=new int[n][m];
+
+        calculateMatrix(reference, alternate, sw, btrack);
+        alignmentResult = calculateCigar(sw, btrack, overhang_strategy); // length of the segment (continuous matches, insertions or deletions)
+    }
+
+    /**
+     * Calculates the SW matrices for the given sequences
+     *
+     * @param reference  ref sequence
+     * @param alternate  alt sequence
+     * @param sw         the Smith-Waterman matrix to populate
+     * @param btrack     the back track matrix to populate
+     */
+    protected void calculateMatrix(final byte[] reference, final byte[] alternate, final int[][] sw, final int[][] btrack) {
+        calculateMatrix(reference, alternate, sw, btrack, overhang_strategy);
+    }
+
+    /**
+     * Calculates the SW matrices for the given sequences
+     *
+     * @param reference  ref sequence
+     * @param alternate  alt sequence
+     * @param sw         the Smith-Waterman matrix to populate
+     * @param btrack     the back track matrix to populate
+     * @param overhang_strategy    the strategy to use for dealing with overhangs
+     */
+    protected void calculateMatrix(final byte[] reference, final byte[] alternate, final int[][] sw, final int[][] btrack, final OVERHANG_STRATEGY overhang_strategy) {
+        if ( reference.length == 0 || alternate.length == 0 )
+            throw new IllegalArgumentException("Non-null, non-empty sequences are required for the Smith-Waterman calculation");
+
+        final int ncol = sw[0].length;//alternate.length+1; formerly m
+        final int nrow = sw.length;// reference.length+1; formerly n
+
+        final int MATRIX_MIN_CUTOFF;   // never let matrix elements drop below this cutoff
+        if ( cutoff ) MATRIX_MIN_CUTOFF = 0;
+        else MATRIX_MIN_CUTOFF = (int) -1e8;
+
+        int lowInitValue=Integer.MIN_VALUE/2;
+        final int[] best_gap_v = new int[ncol+1];
+        Arrays.fill(best_gap_v, lowInitValue);
+        final int[] gap_size_v = new int[ncol+1];
+        final int[] best_gap_h = new int[nrow+1];
+        Arrays.fill(best_gap_h,lowInitValue);
+        final int[] gap_size_h = new int[nrow+1];
+
+        // we need to initialize the SW matrix with gap penalties if we want to keep track of indels at the edges of alignments
+        if ( overhang_strategy == OVERHANG_STRATEGY.INDEL || overhang_strategy == OVERHANG_STRATEGY.LEADING_INDEL ) {
+            // initialize the first row
+            int[] topRow=sw[0];
+            topRow[1]=parameters.w_open;
+            int currentValue = parameters.w_open;
+            for ( int i = 2; i < topRow.length; i++ ) {
+                currentValue += parameters.w_extend;
+                topRow[i]=currentValue;
+            }
+            // initialize the first column
+            sw[1][0]=parameters.w_open;
+            currentValue = parameters.w_open;
+            for ( int i = 2; i < sw.length; i++ ) {
+                currentValue += parameters.w_extend;
+                sw[i][0]=currentValue;
+            }
+        }
+        // build smith-waterman matrix and keep backtrack info:
+        int[] curRow=sw[0];
+        for ( int i = 1; i <sw.length ; i++ ) {
+            final byte a_base = reference[i-1]; // letter in a at the current pos
+            final int[] lastRow=curRow;
+            curRow=sw[i];
+            final int[] curBackTrackRow=btrack[i];
+            for ( int j = 1; j < curRow.length; j++) {
+                final byte b_base = alternate[j-1]; // letter in b at the current pos
+                // in other words, step_diag = sw[i-1][j-1] + wd(a_base,b_base);
+                final int step_diag = lastRow[j-1] + wd(a_base,b_base);
+
+                // optimized "traversal" of all the matrix cells above the current one (i.e. traversing
+                // all 'step down' events that would end in the current cell. The optimized code
+                // does exactly the same thing as the commented out loop below. IMPORTANT:
+                // the optimization works ONLY for linear w(k)=wopen+(k-1)*wextend!!!!
+
+                // if a gap (length 1) was just opened above, this is the cost of arriving to the current cell:
+                int prev_gap = lastRow[j]+parameters.w_open;
+                best_gap_v[j] += parameters.w_extend; // for the gaps that were already opened earlier, extending them by 1 costs w_extend
+                 if (  prev_gap > best_gap_v[j]  ) {
+                    // opening a gap just before the current cell results in better score than extending by one
+                    // the best previously opened gap. This will hold for ALL cells below: since any gap
+                    // once opened always costs w_extend to extend by another base, we will always get a better score
+                    // by arriving to any cell below from the gap we just opened (prev_gap) rather than from the previous best gap
+                    best_gap_v[j] = prev_gap;
+                    gap_size_v[j] = 1; // remember that the best step-down gap from above has length 1 (we just opened it)
+                } else {
+                    // previous best gap is still the best, even after extension by another base, so we just record that extension:
+                    gap_size_v[j]++;
+                }
+
+                final int step_down = best_gap_v[j] ;
+                final int kd = gap_size_v[j];
+
+                // optimized "traversal" of all the matrix cells to the left of the current one (i.e. traversing
+                // all 'step right' events that would end in the current cell. The optimized code
+                // does exactly the same thing as the commented out loop below. IMPORTANT:
+                // the optimization works ONLY for linear w(k)=wopen+(k-1)*wextend!!!!
+
+                prev_gap =curRow[j-1]  + parameters.w_open; // what would it cost us to open length 1 gap just to the left from current cell
+                best_gap_h[i] += parameters.w_extend; // previous best gap would cost us that much if extended by another base
+                if ( prev_gap > best_gap_h[i] ) {
+                    // newly opened gap is better (score-wise) than any previous gap with the same row index i; since
+                    // gap penalty is linear with k, this new gap location is going to remain better than any previous ones
+                    best_gap_h[i] = prev_gap;
+                    gap_size_h[i] = 1;
+                } else {
+                    gap_size_h[i]++;
+                }
+
+                final int step_right = best_gap_h[i];
+                final int ki = gap_size_h[i];
+
+                //priority here will be step diagonal, step right, step down
+                final boolean diagHighestOrEqual = (step_diag >= step_down)
+                                                && (step_diag >= step_right);
+
+                if ( diagHighestOrEqual ) {
+                    curRow[j]=Math.max(MATRIX_MIN_CUTOFF,step_diag);
+                    curBackTrackRow[j]=0;
+                }
+                else if(step_right>=step_down) { //moving right is the highest
+                    curRow[j]=Math.max(MATRIX_MIN_CUTOFF,step_right);
+                    curBackTrackRow[j]=-ki; // negative = horizontal
+                }
+                else  {
+                    curRow[j]=Math.max(MATRIX_MIN_CUTOFF,step_down);
+                    curBackTrackRow[j]= kd; // positive=vertical
+                }
+            }
+        }
+    }
+
+    /*
+     * Class to store the result of calculating the CIGAR from the back track matrix
+     */
+    protected final class SWPairwiseAlignmentResult {
+        public final Cigar cigar;
+        public final int alignment_offset;
+        public SWPairwiseAlignmentResult(final Cigar cigar, final int alignment_offset) {
+            this.cigar = cigar;
+            this.alignment_offset = alignment_offset;
+        }
+    }
+
+    /**
+     * Calculates the CIGAR for the alignment from the back track matrix
+     *
+     * @param sw                   the Smith-Waterman matrix to use
+     * @param btrack               the back track matrix to use
+     * @param overhang_strategy    the strategy to use for dealing with overhangs
+     * @return non-null SWPairwiseAlignmentResult object
+     */
+    protected SWPairwiseAlignmentResult calculateCigar(final int[][] sw, final int[][] btrack, final OVERHANG_STRATEGY overhang_strategy) {
+        // p holds the position we start backtracking from; we will be assembling a cigar in the backwards order
+        int p1 = 0, p2 = 0;
+
+        int refLength = sw.length-1;
+        int altLength = sw[0].length-1;
+
+        int maxscore = Integer.MIN_VALUE; // sw scores are allowed to be negative
+        int segment_length = 0; // length of the segment (continuous matches, insertions or deletions)
+
+        // if we want to consider overhangs as legitimate operators, then just start from the corner of the matrix
+        if ( overhang_strategy == OVERHANG_STRATEGY.INDEL ) {
+            p1 = refLength;
+            p2 = altLength;
+        } else {
+            // look for the largest score on the rightmost column. we use >= combined with the traversal direction
+            // to ensure that if two scores are equal, the one closer to diagonal gets picked
+            //Note: this is not technically smith-waterman, as by only looking for max values on the right we are
+            //excluding high scoring local alignments
+            p2=altLength;
+
+            for(int i=1;i<sw.length;i++)  {
+               final int curScore = sw[i][altLength];
+               if (curScore >= maxscore ) {
+                    p1 = i;
+                    maxscore = curScore;
+               }
+            }
+            // now look for a larger score on the bottom-most row
+            if ( overhang_strategy != OVERHANG_STRATEGY.LEADING_INDEL ) {
+                final int[] bottomRow=sw[refLength];
+                for ( int j = 1 ; j < bottomRow.length; j++) {
+                    int curScore=bottomRow[j];
+                    // data_offset is the offset of [n][j]
+                    if ( curScore > maxscore ||
+                            (curScore == maxscore && Math.abs(refLength-j) < Math.abs(p1 - p2) ) ) {
+                        p1 = refLength;
+                        p2 = j ;
+                        maxscore = curScore;
+                        segment_length = altLength - j ; // end of sequence 2 is overhanging; we will just record it as 'M' segment
+                    }
+                }
+            }
+        }
+        final List<CigarElement> lce = new ArrayList<CigarElement>(5);
+        if ( segment_length > 0 && overhang_strategy == OVERHANG_STRATEGY.SOFTCLIP ) {
+            lce.add(makeElement(State.CLIP, segment_length));
+            segment_length = 0;
+        }
+
+        // we will be placing all insertions and deletions into sequence b, so the states are named w/regard
+        // to that sequence
+
+        State state = State.MATCH;
+        do {
+            int btr = btrack[p1][p2];
+            State new_state;
+            int step_length = 1;
+            if ( btr > 0 ) {
+                new_state = State.DELETION;
+                step_length = btr;
+            } else if ( btr < 0 ) {
+                new_state = State.INSERTION;
+                step_length = (-btr);
+            } else new_state = State.MATCH; // and step_length =1, already set above
+
+            // move to next best location in the sw matrix:
+            switch( new_state ) {
+                case MATCH:  p1--; p2--; break; // move back along the diag in the sw matrix
+                case INSERTION: p2 -= step_length; break; // move left
+                case DELETION:  p1 -= step_length; break; // move up
+            }
+
+            // now let's see if the state actually changed:
+            if ( new_state == state ) segment_length+=step_length;
+            else {
+                // state changed, lets emit previous segment, whatever it was (Insertion Deletion, or (Mis)Match).
+                lce.add(makeElement(state, segment_length));
+                segment_length = step_length;
+                state = new_state;
+            }
+        // next condition is equivalent to  while ( sw[p1][p2] != 0 ) (with modified p1 and/or p2:
+        } while ( p1 > 0 && p2 > 0 );
+
+        // post-process the last segment we are still keeping;
+        // NOTE: if reads "overhangs" the ref on the left (i.e. if p2>0) we are counting
+        // those extra bases sticking out of the ref into the first cigar element if DO_SOFTCLIP is false;
+        // otherwise they will be softclipped. For instance,
+        // if read length is 5 and alignment starts at offset -2 (i.e. read starts before the ref, and only
+        // last 3 bases of the read overlap with/align to the ref), the cigar will be still 5M if
+        // DO_SOFTCLIP is false or 2S3M if DO_SOFTCLIP is true.
+        // The consumers need to check for the alignment offset and deal with it properly.
+        final int alignment_offset;
+        if ( overhang_strategy == OVERHANG_STRATEGY.SOFTCLIP ) {
+            lce.add(makeElement(state, segment_length));
+            if ( p2 > 0 ) lce.add(makeElement(State.CLIP, p2));
+            alignment_offset = p1;
+        } else if ( overhang_strategy == OVERHANG_STRATEGY.IGNORE ) {
+            lce.add(makeElement(state, segment_length + p2));
+            alignment_offset = p1 - p2;
+        } else {  // overhang_strategy == OVERHANG_STRATEGY.INDEL || overhang_strategy == OVERHANG_STRATEGY.LEADING_INDEL
+
+            // take care of the actual alignment
+            lce.add(makeElement(state, segment_length));
+
+            // take care of overhangs at the beginning of the alignment
+            if ( p1 > 0 )
+                lce.add(makeElement(State.DELETION, p1));
+            else if ( p2 > 0 )
+                lce.add(makeElement(State.INSERTION, p2));
+
+            alignment_offset = 0;
+        }
+
+        Collections.reverse(lce);
+        return new SWPairwiseAlignmentResult(AlignmentUtils.consolidateCigar(new Cigar(lce)), alignment_offset);
+    }
+
+    protected CigarElement makeElement(final State state, final int length) {
+        CigarOperator op = null;
+        switch (state) {
+            case MATCH: op = CigarOperator.M; break;
+            case INSERTION: op = CigarOperator.I; break;
+            case DELETION: op = CigarOperator.D; break;
+            case CLIP: op = CigarOperator.S; break;
+        }
+        return new CigarElement(length, op);
+    }
+
+
+    private int wd(final byte x, final byte y) {
+        return (x == y ? parameters.w_match : parameters.w_mismatch);
+    }
+
+    public void printAlignment(byte[] ref, byte[] read) {
+        printAlignment(ref,read,100);
+    }
+    
+    public void printAlignment(byte[] ref, byte[] read, int width) {
+        StringBuilder bread = new StringBuilder();
+        StringBuilder bref = new StringBuilder();
+        StringBuilder match = new StringBuilder();
+
+        int i = 0;
+        int j = 0;
+
+        final int offset = getAlignmentStart2wrt1();
+
+        Cigar cigar = getCigar();
+
+        if ( overhang_strategy != OVERHANG_STRATEGY.SOFTCLIP ) {
+
+            // we need to go through all the hassle below only if we do not do softclipping;
+            // otherwise offset is never negative
+            if ( offset < 0 ) {
+                for (  ; j < (-offset) ; j++ ) {
+                    bread.append((char)read[j]);
+                    bref.append(' ');
+                    match.append(' ');
+                }
+                // at negative offsets, our cigar's first element carries overhanging bases
+                // that we have just printed above. Tweak the first element to
+                // exclude those bases. Here we create a new list of cigar elements, so the original
+                // list/original cigar are unchanged (they are unmodifiable anyway!)
+
+                List<CigarElement> tweaked = new ArrayList<CigarElement>();
+                tweaked.addAll(cigar.getCigarElements());
+                tweaked.set(0,new CigarElement(cigar.getCigarElement(0).getLength()+offset,
+                        cigar.getCigarElement(0).getOperator()));
+                cigar = new Cigar(tweaked);
+            }
+        }
+
+        if ( offset > 0 ) { // note: the way this implementation works, cigar will ever start from S *only* if read starts before the ref, i.e. offset = 0
+            for (  ; i < getAlignmentStart2wrt1() ; i++ ) {
+                bref.append((char)ref[i]);
+                bread.append(' ');
+                match.append(' ');
+            }
+        }
+        
+        for ( CigarElement e : cigar.getCigarElements() ) {
+            switch (e.getOperator()) {
+                case M :
+                    for ( int z = 0 ; z < e.getLength() ; z++, i++, j++  ) {
+                        bref.append((i<ref.length)?(char)ref[i]:' ');
+                        bread.append((j < read.length)?(char)read[j]:' ');
+                        match.append( ( i<ref.length && j < read.length ) ? (ref[i] == read[j] ? '.':'*' ) : ' ' );
+                    }
+                    break;
+                case I :
+                    for ( int z = 0 ; z < e.getLength(); z++, j++ ) {
+                        bref.append('-');
+                        bread.append((char)read[j]);
+                        match.append('I');
+                    }
+                    break;
+                case S :
+                    for ( int z = 0 ; z < e.getLength(); z++, j++ ) {
+                        bref.append(' ');
+                        bread.append((char)read[j]);
+                        match.append('S');
+                    }
+                    break;
+                case D:
+                    for ( int z = 0 ; z < e.getLength(); z++ , i++ ) {
+                        bref.append((char)ref[i]);
+                        bread.append('-');
+                        match.append('D');
+                    }
+                    break;
+                default:
+                    throw new GATKException("Unexpected Cigar element:" + e.getOperator());
+            }
+        }
+        for ( ; i < ref.length; i++ ) bref.append((char)ref[i]);
+        for ( ; j < read.length; j++ ) bread.append((char)read[j]);
+
+        int pos = 0 ;
+        int maxlength = Math.max(match.length(),Math.max(bread.length(),bref.length()));
+        while ( pos < maxlength ) {
+            print_cautiously(match,pos,width);
+            print_cautiously(bread,pos,width);
+            print_cautiously(bref,pos,width);
+            System.out.println();
+            pos += width;
+        }
+    }
+
+    /** String builder's substring is extremely stupid: instead of trimming and/or returning an empty
+     * string when one end/both ends of the interval are out of range, it crashes with an
+     * exception. This utility function simply prints the substring if the interval is within the index range
+     * or trims accordingly if it is not.
+     * @param s
+     * @param start
+     * @param width
+     */
+    private static void print_cautiously(StringBuilder s, int start, int width) {
+        if ( start >= s.length() ) {
+            System.out.println();
+            return;
+        }
+        int end = Math.min(start+width,s.length());
+        System.out.println(s.substring(start,end));
+    }
+}
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/smithwaterman/SWPairwiseAlignmentMain.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/smithwaterman/SWPairwiseAlignmentMain.java
new file mode 100644
index 0000000..3d2ddd1
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/smithwaterman/SWPairwiseAlignmentMain.java
@@ -0,0 +1,221 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.utils.smithwaterman;
+
+import org.broadinstitute.gatk.utils.Utils;
+import org.broadinstitute.gatk.utils.collections.Pair;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * Simple program to run SW performance test.
+ *
+ * // TODO -- should be replaced with Caliper before using again
+ *
+ * User: depristo
+ * Date: 2/28/13
+ * Time: 4:54 PM
+ * To change this template use File | Settings | File Templates.
+ */
+public class SWPairwiseAlignmentMain {
+    //    BELOW: main() method for testing; old implementations of the core methods are commented out below;
+//           uncomment everything through the end of the file if benchmarking of new vs old implementations is needed.
+
+    public static void main(String argv[]) {
+//        String ref="CACGAGCATATGTGTACATGAATTTGTATTGCACATGTGTTTAATGCGAACACGTGTCATGTGTATGTGTTCACATGCATGTGTGTCT";
+//        String read =   "GCATATGTTTACATGAATTTGTATTGCACATGTGTTTAATGCGAACACGTGTCATGTGTGTGTTCACATGCATGTG";
+
+        String ref = null;
+        String read = null;
+
+        Map<String,List<String>> args = processArgs(argv);
+
+        List<String> l = args.get("SEQ");
+        args.remove("SEQ");
+        if ( l == null ) {
+            System.err.println("SEQ argument is missing. Two input sequences must be provided");
+            System.exit(1);
+        }
+        if ( l.size() != 2 ) {
+            System.err.println("Two input sequences (SEQ arguments) must be provided. Found "+l.size()+" instead");
+            System.exit(1);
+        }
+
+        ref = l.get(0);
+        read = l.get(1);
+
+        Double m = extractSingleDoubleArg("MATCH",args);
+        Double mm = extractSingleDoubleArg("MISMATCH",args);
+        Double open = extractSingleDoubleArg("OPEN",args);
+        Double ext = extractSingleDoubleArg("EXTEND",args);
+
+        Boolean reverse = extractSingleBooleanArg("REVERSE",args);
+        if ( reverse != null && reverse.booleanValue() == true ) {
+            ref = Utils.reverse(ref);
+            read = Utils.reverse(read);
+        }
+
+        Boolean print_mat = extractSingleBooleanArg("PRINT_MATRIX",args);
+        Boolean cut = extractSingleBooleanArg("CUTOFF",args);
+        if ( cut != null ) SWPairwiseAlignment.cutoff = cut;
+
+        if ( args.size() != 0 ) {
+            System.err.println("Unknown argument on the command line: "+args.keySet().iterator().next());
+            System.exit(1);
+        }
+
+        final int w_match, w_mismatch, w_open, w_extend;
+
+        w_match = (m == null ? 30 : m.intValue());
+        w_mismatch = (mm == null ? -10 : mm.intValue());
+        w_open = (open == null ? -10 : open.intValue());
+        w_extend = (ext == null ? -2 : ext.intValue());
+
+
+        SWPairwiseAlignment.keepScoringMatrix = true;
+        SWPairwiseAlignment a = new SWPairwiseAlignment(ref.getBytes(),read.getBytes(),w_match,w_mismatch,w_open,w_extend);
+
+        System.out.println("start="+a.getAlignmentStart2wrt1()+", cigar="+a.getCigar()+
+                " length1="+ref.length()+" length2="+read.length());
+
+
+        System.out.println();
+        a.printAlignment(ref.getBytes(),read.getBytes());
+
+        System.out.println();
+        if ( print_mat != null && print_mat == true ) {
+            print(a.SW,ref.getBytes(),read.getBytes());
+        }
+    }
+
+    private static void print(final int[][] s, final byte[] a, final byte[] b) {
+        int n = a.length+1;
+        int m = b.length+1;
+        System.out.print("         ");
+        for ( int j = 1 ; j < m ; j++) System.out.printf(" %5c",(char)b[j-1]) ;
+        System.out.println();
+
+        for ( int i = 0 ; i < n ; i++) {
+            if ( i > 0 ) System.out.print((char)a[i-1]);
+            else System.out.print(' ');
+            System.out.print("  ");
+            for ( int j = 0; j < m ; j++ ) {
+                System.out.printf(" %5.1f",s[i][j]);
+            }
+            System.out.println();
+        }
+    }
+
+
+    static Pair<String,Integer> getArg(String prefix, String argv[], int i) {
+        String arg = null;
+        if ( argv[i].startsWith(prefix) ) {
+            arg = argv[i].substring(prefix.length());
+            if( arg.length() == 0 ) {
+                i++;
+                if ( i < argv.length ) arg = argv[i];
+                else {
+                    System.err.println("No value found after " + prefix + " argument tag");
+                    System.exit(1);
+                }
+            }
+            i++;
+        }
+        return new Pair<String,Integer>(arg,i);
+    }
+
+    static Map<String,List<String>> processArgs(String argv[]) {
+        Map<String,List<String>> args = new HashMap<String,List<String>>();
+
+        for ( int i = 0; i < argv.length ; i++ ) {
+            String arg = argv[i];
+            int pos = arg.indexOf('=');
+            if ( pos < 0 ) {
+                System.err.println("Argument "+arg+" is not of the form <ARG>=<VAL>");
+                System.exit(1);
+            }
+            String val = arg.substring(pos+1);
+            if ( val.length() == 0 ) {
+                // there was a space between '=' and the value
+                i++;
+                if ( i < argv.length ) val = argv[i];
+                else {
+                    System.err.println("No value found after " + arg + " argument tag");
+                    System.exit(1);
+                }
+            }
+            arg = arg.substring(0,pos);
+
+            List<String> l = args.get(arg);
+            if ( l == null ) {
+                l = new ArrayList<String>();
+                args.put(arg,l);
+            }
+            l.add(val);
+        }
+        return args;
+    }
+
+    static Double extractSingleDoubleArg(String argname, Map<String,List<String>> args) {
+        List<String> l = args.get(argname);
+        args.remove(argname);
+        if ( l == null ) return null;
+
+        if ( l.size() > 1 ) {
+            System.err.println("Only one "+argname+" argument is allowed");
+            System.exit(1);
+        }
+        double d=0;
+        try {
+            d = Double.parseDouble(l.get(0));
+        } catch ( NumberFormatException e) {
+            System.err.println("Can not parse value provided for "+argname+" argument ("+l.get(0)+")");
+            System.exit(1);
+        }
+        System.out.println("Argument "+argname+" set to "+d);
+        return new Double(d);
+    }
+
+
+    static Boolean extractSingleBooleanArg(String argname, Map<String,List<String>> args) {
+        List<String> l = args.get(argname);
+        args.remove(argname);
+        if ( l == null ) return null;
+
+        if ( l.size() > 1 ) {
+            System.err.println("Only one "+argname+" argument is allowed");
+            System.exit(1);
+        }
+        if ( l.get(0).equals("true") ) return Boolean.valueOf(true);
+        if ( l.get(0).equals("false") ) return Boolean.valueOf(false);
+        System.err.println("Can not parse value provided for "+argname+" argument ("+l.get(0)+"); true/false are allowed");
+        System.exit(1);
+        return Boolean.valueOf(false); // This value isn't used because it is preceded by System.exit(1)
+    }
+}
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/smithwaterman/SWParameterSet.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/smithwaterman/SWParameterSet.java
new file mode 100644
index 0000000..7226a98
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/smithwaterman/SWParameterSet.java
@@ -0,0 +1,51 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.utils.smithwaterman;
+
+/**
+ * Handy named collection of common Smith-waterman parameter sets
+ *
+ * User: depristo
+ * Date: 4/11/13
+ * Time: 12:02 PM
+ */
+public enum SWParameterSet {
+    // match=1, mismatch = -1/3, gap=-(1+k/3)
+    ORIGINAL_DEFAULT(new Parameters(3,-1,-4,-3)),
+
+    /**
+     * A standard set of values for NGS alignments
+     */
+    STANDARD_NGS(new Parameters(25, -50, -110, -6));
+
+    protected Parameters parameters;
+
+    SWParameterSet(final Parameters parameters) {
+        if ( parameters == null ) throw new IllegalArgumentException("parameters cannot be null");
+
+        this.parameters = parameters;
+    }
+}
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/smithwaterman/SmithWaterman.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/smithwaterman/SmithWaterman.java
new file mode 100644
index 0000000..c4184e1
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/smithwaterman/SmithWaterman.java
@@ -0,0 +1,57 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.utils.smithwaterman;
+
+import htsjdk.samtools.Cigar;
+
+/**
+ * Generic interface for SmithWaterman calculations
+ *
+ * This interface allows clients to use a generic SmithWaterman variable, without propagating the specific
+ * implementation of SmithWaterman throughout their code:
+ *
+ * SmithWaterman sw = new SpecificSmithWatermanImplementation(ref, read, params)
+ * sw.getCigar()
+ * sw.getAlignmentStart2wrt1()
+ *
+ * User: depristo
+ * Date: 4/26/13
+ * Time: 8:24 AM
+ */
+public interface SmithWaterman {
+
+    /**
+     * Get the cigar string for the alignment of this SmithWaterman class
+     * @return a non-null cigar
+     */
+    public Cigar getCigar();
+
+    /**
+     * Get the starting position of the read sequence in the reference sequence
+     * @return a positive integer >= 0
+     */
+    public int getAlignmentStart2wrt1();
+}
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/text/ListFileUtils.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/text/ListFileUtils.java
new file mode 100644
index 0000000..d6e1bcb
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/text/ListFileUtils.java
@@ -0,0 +1,344 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.utils.text;
+
+import org.broadinstitute.gatk.utils.commandline.ParsingEngine;
+import org.broadinstitute.gatk.utils.commandline.RodBinding;
+import org.broadinstitute.gatk.utils.commandline.Tags;
+import org.broadinstitute.gatk.engine.datasources.reads.SAMReaderID;
+import org.broadinstitute.gatk.engine.refdata.tracks.FeatureManager;
+import org.broadinstitute.gatk.engine.refdata.utils.RMDTriplet;
+import org.broadinstitute.gatk.utils.exceptions.UserException;
+
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.util.*;
+import java.util.regex.Pattern;
+
+/**
+ * A collection of convenience methods for working with list files.
+ */
+public class ListFileUtils {
+    /**
+     * Lines starting with this String in .list files are considered comments.
+     */
+    public static final String LIST_FILE_COMMENT_START = "#";        
+
+    /**
+     * Unpack the bam files to be processed, given a list of files.  That list of files can
+     * itself contain entries which are lists of other files to be read (note: you cannot have lists
+     * of lists of lists). Lines in .list files containing only whitespace or which begin with
+     * LIST_FILE_COMMENT_START are ignored.
+     *
+     * @param samFiles The sam files, in string format.
+     * @param parser Parser
+     * @return a flattened list of the bam files provided
+     */
+    public static List<SAMReaderID> unpackBAMFileList(final List<String> samFiles, final ParsingEngine parser) {
+        List<SAMReaderID> unpackedReads = new ArrayList<SAMReaderID>();
+        for( String inputFileName: samFiles ) {
+            Tags inputFileNameTags = parser.getTags(inputFileName);
+            inputFileName = expandFileName(inputFileName);
+            if (inputFileName.toLowerCase().endsWith(".list") ) {
+                try {
+                    for ( String fileName : new XReadLines(new File(inputFileName), true, LIST_FILE_COMMENT_START) ) {
+                        unpackedReads.add(new SAMReaderID(fileName,parser.getTags(inputFileName)));
+                    }
+                }
+                catch( FileNotFoundException ex ) {
+                    throw new UserException.CouldNotReadInputFile(new File(inputFileName), "Unable to find file while unpacking reads", ex);
+                }
+            }
+            else if(inputFileName.toLowerCase().endsWith(".bam")) {
+                unpackedReads.add(new SAMReaderID(inputFileName,inputFileNameTags));
+            }
+            else if(inputFileName.endsWith("stdin")) {
+                unpackedReads.add(new SAMReaderID(inputFileName,inputFileNameTags));
+            }
+            else {
+                throw new UserException.CommandLineException(String.format("The GATK reads argument (-I, --input_file) supports only BAM files with the .bam extension and lists of BAM files " +
+                        "with the .list extension, but the file %s has neither extension.  Please ensure that your BAM file or list " +
+                        "of BAM files is in the correct format, update the extension, and try again.",inputFileName));
+            }
+        }
+        return unpackedReads;
+    }
+
+    /**
+     * Convert command-line argument representation of ROD bindings to something more easily understandable by the engine.
+     * @param RODBindings a text equivale
+     * @param parser Parser
+     * @return a list of expanded, bound RODs.
+     */
+    @Deprecated
+    @SuppressWarnings("unused") // TODO: Who is still using this? External walkers?
+    public static Collection<RMDTriplet> unpackRODBindingsOldStyle(final Collection<String> RODBindings, final ParsingEngine parser) {
+        // todo -- this is a strange home for this code.  Move into ROD system
+        Collection<RMDTriplet> rodBindings = new ArrayList<RMDTriplet>();
+
+        for (String fileName: RODBindings) {
+            final Tags tags = parser.getTags(fileName);
+            fileName = expandFileName(fileName);
+
+            List<String> positionalTags = tags.getPositionalTags();
+            if(positionalTags.size() != 2)
+                throw new UserException("Invalid syntax for -B (reference-ordered data) input flag.  " +
+                        "Please use the following syntax when providing reference-ordered " +
+                        "data: -B:<name>,<type> <filename>.");
+            // Assume that if tags are present, those tags are name and type.
+            // Name is always first, followed by type.
+            String name = positionalTags.get(0);
+            String type = positionalTags.get(1);
+
+            RMDTriplet.RMDStorageType storageType;
+            if(tags.getValue("storage") != null)
+                storageType = Enum.valueOf(RMDTriplet.RMDStorageType.class,tags.getValue("storage"));
+            else if(fileName.toLowerCase().endsWith("stdin"))
+                storageType = RMDTriplet.RMDStorageType.STREAM;
+            else
+                storageType = RMDTriplet.RMDStorageType.FILE;
+
+            rodBindings.add(new RMDTriplet(name,type,fileName,storageType,tags));
+        }
+
+        return rodBindings;
+    }
+
+    /**
+     * Convert command-line argument representation of ROD bindings to something more easily understandable by the engine.
+     * @param RODBindings a text equivale
+     * @param parser Parser
+     * @return a list of expanded, bound RODs.
+     */
+    @SuppressWarnings("unchecked")
+    public static Collection<RMDTriplet> unpackRODBindings(final Collection<RodBinding> RODBindings, @SuppressWarnings("unused") final ParsingEngine parser) {
+        // todo -- this is a strange home for this code.  Move into ROD system
+        Collection<RMDTriplet> rodBindings = new ArrayList<RMDTriplet>();
+        FeatureManager builderForValidation = new FeatureManager();
+
+        for (RodBinding rodBinding: RODBindings) {
+            String argValue = rodBinding.getSource();
+            String fileName = expandFileName(argValue);
+            String name = rodBinding.getName();
+            String type = rodBinding.getTribbleType();
+
+            RMDTriplet.RMDStorageType storageType;
+            if(rodBinding.getTags().getValue("storage") != null)
+                storageType = Enum.valueOf(RMDTriplet.RMDStorageType.class,rodBinding.getTags().getValue("storage"));
+            else if(fileName.toLowerCase().endsWith("stdin"))
+                storageType = RMDTriplet.RMDStorageType.STREAM;
+            else
+                storageType = RMDTriplet.RMDStorageType.FILE;
+
+            RMDTriplet triplet = new RMDTriplet(name,type,fileName,storageType,rodBinding.getTags());
+
+            // validate triplet type
+            FeatureManager.FeatureDescriptor descriptor = builderForValidation.getByTriplet(triplet);
+            if ( descriptor == null )
+                throw new UserException.UnknownTribbleType(rodBinding.getTribbleType(),
+                        String.format("Field %s had provided type %s but there's no such Tribble type.  The compatible types are: %n%s",
+                                rodBinding.getName(), rodBinding.getTribbleType(), builderForValidation.userFriendlyListOfAvailableFeatures(rodBinding.getType())));
+            if ( ! rodBinding.getType().isAssignableFrom(descriptor.getFeatureClass()) )
+                throw new UserException.BadArgumentValue(rodBinding.getName(),
+                        String.format("Field %s expects Features of type %s, but the input file produces Features of type %s. The compatible types are: %n%s",
+                                rodBinding.getName(), rodBinding.getType().getSimpleName(), descriptor.getSimpleFeatureName(),
+                                builderForValidation.userFriendlyListOfAvailableFeatures(rodBinding.getType())));
+
+
+            rodBindings.add(triplet);
+        }
+
+        return rodBindings;
+    }
+
+    /**
+     * Expand any special characters that appear in the filename.  Right now, '-' is expanded to
+     * '/dev/stdin' only, but in the future, special characters like '~' and '*' that are passed
+     * directly to the command line in some circumstances could be expanded as well.  Be careful
+     * when adding UNIX-isms.
+     * @param argument the text appearing on the command-line.
+     * @return An expanded string suitable for opening by Java/UNIX file handling utilities.
+     */
+    private static String expandFileName(String argument) {
+        if(argument.trim().equals("-"))
+            return "/dev/stdin";
+        return argument;
+    }
+
+    /**
+     * Returns a new set of values, containing a final set of values expanded from values
+     * <p/>
+     * Each element E of values can either be a literal string or a file ending in .list.
+     * For each E ending in .list we try to read a file named E from disk, and if possible
+     * all lines from that file are expanded into unique values.
+     *
+     * @param values Original values
+     * @return entries from values or the files listed in values
+     */
+    public static Set<String> unpackSet(Collection<String> values) {
+        if (values == null)
+            throw new NullPointerException("values cannot be null");
+        Set<String> unpackedValues = new LinkedHashSet<String>();
+        // Let's first go through the list and see if we were given any files.
+        // We'll add every entry in the file to our set, and treat the entries as
+        // if they had been specified on the command line.
+        for (String value : values) {
+            File file = new File(value);
+            if (value.toLowerCase().endsWith(".list") && file.exists()) {
+                try {
+                    unpackedValues.addAll(new XReadLines(file, true, LIST_FILE_COMMENT_START).readLines());
+                } catch (IOException e) {
+                    throw new UserException.CouldNotReadInputFile(file, e);
+                }
+            } else {
+                unpackedValues.add(value);
+            }
+        }
+        return unpackedValues;
+    }
+
+    /**
+     * Returns a new set of values including only values listed by filters
+     * <p/>
+     * Each element E of values can either be a literal string or a file.  For each E,
+     * we try to read a file named E from disk, and if possible all lines from that file are expanded
+     * into unique names.
+     * <p/>
+     * Filters may also be a file of filters.
+     *
+     * @param values     Values or files with values
+     * @param filters    Filters or files with filters
+     * @param exactMatch If true match filters exactly, otherwise use as both exact and regular expressions
+     * @return entries from values or the files listed in values, filtered by filters
+     */
+    public static Set<String> includeMatching(Collection<String> values, Collection<String> filters, boolean exactMatch) {
+        return includeMatching(values, IDENTITY_STRING_CONVERTER, filters, exactMatch);
+    }
+
+    /**
+     * Converts a type T to a String representation.
+     *
+     * @param <T> Type to convert to a String.
+     */
+    public static interface StringConverter<T> {
+        String convert(T value);
+    }
+
+    /**
+     * Returns a new set of values including only values matching filters
+     * <p/>
+     * Filters may also be a file of filters.
+     * <p/>
+     * The converter should convert T to a unique String for each value in the set.
+     *
+     * @param values     Values or files with values
+     * @param converter  Converts values to strings
+     * @param filters    Filters or files with filters
+     * @param exactMatch If true match filters exactly, otherwise use as both exact and regular expressions
+     * @return entries from values including only values matching filters
+     */
+    public static <T> Set<T> includeMatching(Collection<T> values, StringConverter<T> converter, Collection<String> filters, boolean exactMatch) {
+        if (values == null)
+            throw new NullPointerException("values cannot be null");
+        if (converter == null)
+            throw new NullPointerException("converter cannot be null");
+        if (filters == null)
+            throw new NullPointerException("filters cannot be null");
+
+        Set<String> unpackedFilters = unpackSet(filters);
+        Set<T> filteredValues = new LinkedHashSet<T>();
+        Collection<Pattern> patterns = null;
+        if (!exactMatch)
+            patterns = compilePatterns(unpackedFilters);
+        for (T value : values) {
+            String converted = converter.convert(value);
+            if (unpackedFilters.contains(converted)) {
+                filteredValues.add(value);
+            } else if (!exactMatch) {
+                for (Pattern pattern : patterns)
+                    if (pattern.matcher(converted).find())
+                        filteredValues.add(value);
+            }
+        }
+        return filteredValues;
+    }
+    
+    /**
+     * Returns a new set of values excluding any values matching filters.
+     * <p/>
+     * Filters may also be a file of filters.
+     * <p/>
+     * The converter should convert T to a unique String for each value in the set.
+     *
+     * @param values     Values or files with values
+     * @param converter  Converts values to strings
+     * @param filters    Filters or files with filters
+     * @param exactMatch If true match filters exactly, otherwise use as both exact and regular expressions
+     * @return entries from values exluding any values matching filters
+     */
+    public static <T> Set<T> excludeMatching(Collection<T> values, StringConverter<T> converter, Collection<String> filters, boolean exactMatch) {
+        if (values == null)
+            throw new NullPointerException("values cannot be null");
+        if (converter == null)
+            throw new NullPointerException("converter cannot be null");
+        if (filters == null)
+            throw new NullPointerException("filters cannot be null");
+
+        Set<String> unpackedFilters = unpackSet(filters);
+        Set<T> filteredValues = new LinkedHashSet<T>();
+        filteredValues.addAll(values);
+        Collection<Pattern> patterns = null;
+        if (!exactMatch)
+            patterns = compilePatterns(unpackedFilters);
+        for (T value : values) {
+            String converted = converter.convert(value);
+            if (unpackedFilters.contains(converted)) {
+                filteredValues.remove(value);
+            } else if (!exactMatch) {
+                for (Pattern pattern : patterns)
+                    if (pattern.matcher(converted).find())
+                        filteredValues.remove(value);
+            }
+        }
+        return filteredValues;
+    }
+
+    private static Collection<Pattern> compilePatterns(Collection<String> filters) {
+        Collection<Pattern> patterns = new ArrayList<Pattern>();
+        for (String filter: filters) {
+            patterns.add(Pattern.compile(filter));
+        }
+        return patterns;
+    }
+
+    protected static final StringConverter<String> IDENTITY_STRING_CONVERTER = new StringConverter<String>() {
+        @Override
+        public String convert(String value) {
+            return value;
+        }
+    };
+}
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/text/TextFormattingUtils.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/text/TextFormattingUtils.java
new file mode 100644
index 0000000..65fb970
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/text/TextFormattingUtils.java
@@ -0,0 +1,172 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.utils.text;
+
+import org.apache.log4j.Logger;
+import org.broadinstitute.gatk.utils.exceptions.ReviewedGATKException;
+
+import java.io.IOException;
+import java.io.StringReader;
+import java.util.*;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+/**
+ * Common utilities for dealing with text formatting.
+ *
+ * @author mhanna
+ * @version 0.1
+ */
+public class TextFormattingUtils {
+    /**
+     * our log, which we want to capture anything from this class
+     */
+    private static Logger logger = Logger.getLogger(TextFormattingUtils.class);    
+
+    /**
+     * The default line width, for GATK output written to the screen.
+     */
+    public static final int DEFAULT_LINE_WIDTH = 120;
+
+    /**
+     * Simple implementation of word-wrap for a line of text.  Idea and
+     * regexp shamelessly stolen from http://joust.kano.net/weblog/archives/000060.html.
+     * Regexp can probably be simplified for our application.
+     * @param text Text to wrap.
+     * @param width Maximum line width.
+     * @return A list of word-wrapped lines.
+     */
+    public static List<String> wordWrap( String text, int width ) {
+        Pattern wrapper = Pattern.compile( String.format(".{0,%d}(?:\\S(?:[\\s|]|$)|$)", width-1) );
+        Matcher matcher = wrapper.matcher( text );
+
+        List<String> wrapped = new ArrayList<String>();
+        while( matcher.find() ) {
+            // Regular expression is supersensitive to whitespace.
+            // Assert that content is present before adding the line.
+            String line = matcher.group().trim();
+            if( line.length() > 0 )
+                wrapped.add( matcher.group() );
+        }
+        return wrapped;
+    }
+
+    /**
+     * Compares two strings independently of case sensitivity.
+     */
+    public static class CaseInsensitiveComparator implements Comparator<String> {
+        /**
+         * Compares the order of lhs to rhs, not taking case into account.
+         * @param lhs First object to compare.
+         * @param rhs Second object to compare.
+         * @return 0 if objects are identical; -1 if lhs is before rhs, 1 if rhs is before lhs.  Nulls are treated as after everything else.
+         */
+        public int compare(String lhs, String rhs) {
+            if(lhs == null && rhs == null) return 0;
+            if(lhs == null) return 1;
+            if(rhs == null) return -1;
+            return lhs.toLowerCase().compareTo(rhs.toLowerCase());
+        }
+    }
+
+    /**
+     * Load the contents of a resource bundle with the given name.  If no such resource exists, warn the user
+     * and create an empty bundle.
+     * @param bundleName The name of the bundle to load.
+     * @return The best resource bundle that can be found matching the given name.
+     */
+    public static ResourceBundle loadResourceBundle(String bundleName) {
+        ResourceBundle bundle;
+        try {
+            bundle = ResourceBundle.getBundle(bundleName);
+        }
+        catch(MissingResourceException ex) {
+            //logger.warn("Unable to load help text.  Help output will be sparse.");
+            // Generate an empty resource bundle.
+            try {
+                bundle = new PropertyResourceBundle(new StringReader(""));
+            }
+            catch(IOException ioe) {
+                throw new ReviewedGATKException("No resource bundle found, and unable to create an empty placeholder.",ioe);
+            }
+        }
+        return bundle;
+    }
+
+
+    /**
+     * Returns the word starting positions within line, excluding the first position 0.
+     * The returned list is compatible with splitFixedWidth.
+     * @param line Text to parse.
+     * @return the word starting positions within line, excluding the first position 0.
+     */
+    public static List<Integer> getWordStarts(String line) {
+        if (line == null)
+            throw new ReviewedGATKException("line is null");
+        List<Integer> starts = new ArrayList<Integer>();
+        int stop = line.length();
+        for (int i = 1; i < stop; i++)
+            if (Character.isWhitespace(line.charAt(i-1)))
+                if(!Character.isWhitespace(line.charAt(i)))
+                    starts.add(i);
+        return starts;
+    }
+
+    /**
+     * Parses a fixed width line of text.
+     * @param line Text to parse.
+     * @param columnStarts the column starting positions within line, excluding the first position 0.
+     * @return The parsed string array with each entry trimmed.
+     */
+    public static String[] splitFixedWidth(String line, List<Integer> columnStarts) {
+        if (line == null)
+            throw new ReviewedGATKException("line is null");
+        if (columnStarts == null)
+            throw new ReviewedGATKException("columnStarts is null");
+        int startCount = columnStarts.size();
+        String[] row = new String[startCount + 1];
+        if (startCount == 0) {
+            row[0] = line.trim();
+        } else {
+            row[0] = line.substring(0, columnStarts.get(0)).trim();
+            for (int i = 1; i < startCount; i++)
+                row[i] = line.substring(columnStarts.get(i - 1), columnStarts.get(i)).trim();
+            row[startCount] = line.substring(columnStarts.get(startCount - 1)).trim();
+        }
+        return row;
+    }
+
+    /**
+     * Parses a line of text by whitespace.
+     * @param line Text to parse.
+     * @return The parsed string array.
+     */
+    public static String[] splitWhiteSpace(String line) {
+        if (line == null)
+            throw new ReviewedGATKException("line is null");
+        return line.trim().split("\\s+");
+    }
+}
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/text/XReadLines.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/text/XReadLines.java
new file mode 100644
index 0000000..f410156
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/text/XReadLines.java
@@ -0,0 +1,208 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.utils.text;
+
+import java.io.*;
+import java.util.Iterator;
+import java.util.LinkedList;
+import java.util.List;
+
+/**
+ * Support for Python-like xreadlines() function as a class.  This is an iterator and iterable over
+ * Strings, each corresponding a line in the file (minus newline).  Enables the very simple accessing
+ * of lines in a file as:
+ *
+ * xReadLines reader = new xReadLines(new File(file_name));
+ * List<String> lines = reader.readLines();
+ * reader.close();
+ *
+ * or
+ *
+ * for ( String line : new xReadLines(new File(file_name)) {
+ *   doSomeWork(line);
+ * }
+ *
+ * For the love of god, please use this system for reading lines in a file.
+ */
+public class XReadLines implements Iterator<String>, Iterable<String> {
+    private final BufferedReader in;      // The stream we're reading from
+    private String nextLine = null;       // Return value of next call to next()
+    private final boolean trimWhitespace;
+    private final String commentPrefix;
+
+    public XReadLines(final File filename) throws FileNotFoundException {
+        this(new FileReader(filename), true, null);
+    }
+
+    public XReadLines(final File filename, final boolean trimWhitespace) throws FileNotFoundException {
+        this(new FileReader(filename), trimWhitespace, null);
+    }
+
+    /**
+     * Creates a new xReadLines object to read lines from filename
+     *
+     * @param filename file name
+     * @param trimWhitespace trim whitespace
+     * @param commentPrefix prefix for comments or null if no prefix is set
+     * @throws FileNotFoundException when the file is not found
+     */
+    public XReadLines(final File filename, final boolean trimWhitespace, final String commentPrefix) throws FileNotFoundException {
+        this(new FileReader(filename), trimWhitespace, commentPrefix);
+    }
+
+    public XReadLines(final InputStream inputStream) throws FileNotFoundException {
+        this(new InputStreamReader(inputStream), true, null);
+    }
+
+    public XReadLines(final InputStream inputStream, final boolean trimWhitespace) {
+        this(new InputStreamReader(inputStream), trimWhitespace, null);
+    }
+
+    /**
+     * Creates a new xReadLines object to read lines from an input stream
+     *
+     * @param inputStream input stream
+     * @param trimWhitespace trim whitespace
+     * @param commentPrefix prefix for comments or null if no prefix is set
+     */
+    public XReadLines(final InputStream inputStream, final boolean trimWhitespace, final String commentPrefix) {
+        this(new InputStreamReader(inputStream), trimWhitespace, commentPrefix);
+    }
+
+
+    /**
+     * Creates a new xReadLines object to read lines from a reader
+     *
+     * @param reader reader
+     */
+    public XReadLines(final Reader reader) {
+        this(reader, true, null);
+    }
+
+    /**
+     * Creates a new xReadLines object to read lines from an reader
+     *
+     * @param reader reader
+     * @param trimWhitespace trim whitespace
+     */
+    public XReadLines(final Reader reader, final boolean trimWhitespace) {
+        this(reader, trimWhitespace, null);
+    }
+
+    /**
+     * Creates a new xReadLines object to read lines from an bufferedReader
+     *
+     * @param reader file name
+     * @param trimWhitespace trim whitespace
+     * @param commentPrefix prefix for comments or null if no prefix is set
+     */
+    public XReadLines(final Reader reader, final boolean trimWhitespace, final String commentPrefix) {
+        this.in = (reader instanceof BufferedReader) ? (BufferedReader)reader : new BufferedReader(reader);
+        this.trimWhitespace = trimWhitespace;
+        this.commentPrefix = commentPrefix;
+        try {
+            this.nextLine = readNextLine();
+        } catch(IOException e) {
+            throw new IllegalArgumentException(e);
+        }
+    }
+
+    /**
+     * Reads all of the lines in the file, and returns them as a list of strings
+     *
+     * @return all of the lines in the file.
+     */
+    public List<String> readLines() {
+        List<String> lines = new LinkedList<String>();
+        for ( String line : this ) {
+            lines.add(line);
+        }
+        return lines;
+    }
+
+    /**
+     * I'm an iterator too...
+     * @return an iterator
+     */
+    public Iterator<String> iterator() {
+        return this;
+    }
+
+    public boolean hasNext() {
+        return this.nextLine != null;
+    }
+
+    /**
+     * Actually reads the next line from the stream, not accessible publicly
+     * @return the next line or null
+     * @throws IOException if an error occurs
+     */
+    private String readNextLine() throws IOException {
+        String nextLine;
+        while ((nextLine = this.in.readLine()) != null) {
+            if (this.trimWhitespace) {
+                nextLine = nextLine.trim();
+                if (nextLine.length() == 0)
+                    continue;
+            }
+            if (this.commentPrefix != null)
+                if (nextLine.startsWith(this.commentPrefix))
+                    continue;
+            break;
+        }
+        return nextLine;
+    }
+
+    /**
+     * Returns the next line (optionally minus whitespace)
+     * @return the next line
+     */
+    public String next() {
+        try {
+            String result = this.nextLine;
+            this.nextLine = readNextLine();
+
+            // If we haven't reached EOF yet
+            if (this.nextLine == null) {
+                in.close();             // And close on EOF
+            }
+
+            // Return the line we read last time through.
+            return result;
+        } catch(IOException e) {
+            throw new IllegalArgumentException(e);
+        }
+    }
+
+    // The file is read-only; we don't allow lines to be removed.
+    public void remove() {
+        throw new UnsupportedOperationException();
+    }
+
+    public void close() throws IOException {
+        this.in.close();
+    }
+}
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/threading/EfficiencyMonitoringThreadFactory.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/threading/EfficiencyMonitoringThreadFactory.java
new file mode 100644
index 0000000..7282083
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/threading/EfficiencyMonitoringThreadFactory.java
@@ -0,0 +1,160 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.utils.threading;
+
+import com.google.java.contract.Ensures;
+import com.google.java.contract.Invariant;
+import com.google.java.contract.Requires;
+import org.apache.log4j.Logger;
+import org.apache.log4j.Priority;
+import org.broadinstitute.gatk.utils.AutoFormattingTime;
+
+import java.lang.management.ManagementFactory;
+import java.lang.management.ThreadInfo;
+import java.lang.management.ThreadMXBean;
+import java.util.ArrayList;
+import java.util.EnumMap;
+import java.util.List;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.ThreadFactory;
+import java.util.concurrent.TimeUnit;
+
+/**
+ * Creates threads that automatically monitor their efficiency via the parent ThreadEfficiencyMonitor
+ *
+ * User: depristo
+ * Date: 8/14/12
+ * Time: 8:47 AM
+ */
+ at Invariant({
+        "activeThreads.size() <= nThreadsToCreate",
+        "countDownLatch.getCount() <= nThreadsToCreate",
+        "nThreadsCreated <= nThreadsToCreate"
+})
+public class EfficiencyMonitoringThreadFactory extends ThreadEfficiencyMonitor implements ThreadFactory  {
+    final int nThreadsToCreate;
+    final List<Thread> activeThreads;
+
+    int nThreadsCreated = 0;
+
+    /**
+     * Counts down the number of active activeThreads whose runtime info hasn't been incorporated into
+     * times.  Counts down from nThreadsToCreate to 0, at which point any code waiting
+     * on the final times is freed to run.
+     */
+    final CountDownLatch countDownLatch;
+
+    /**
+     * Create a new factory generating threads whose runtime and contention
+     * behavior is tracked in this factory.
+     *
+     * @param nThreadsToCreate the number of threads we will create in the factory before it's considered complete
+     */
+    public EfficiencyMonitoringThreadFactory(final int nThreadsToCreate) {
+        super();
+        if ( nThreadsToCreate <= 0 ) throw new IllegalArgumentException("nThreadsToCreate <= 0: " + nThreadsToCreate);
+
+        this.nThreadsToCreate = nThreadsToCreate;
+        activeThreads = new ArrayList<Thread>(nThreadsToCreate);
+        countDownLatch = new CountDownLatch(nThreadsToCreate);
+    }
+
+    /**
+     * How many threads have been created by this factory so far?
+     * @return
+     */
+    @Ensures("result >= 0")
+    public int getNThreadsCreated() {
+        return nThreadsCreated;
+    }
+
+    /**
+     * Only useful for testing, so that we can wait for all of the threads in the factory to complete running
+     *
+     * @throws InterruptedException
+     */
+    protected void waitForAllThreadsToComplete() throws InterruptedException {
+        countDownLatch.await();
+    }
+
+    @Ensures({
+            "activeThreads.size() <= old(activeThreads.size())",
+            "! activeThreads.contains(thread)",
+            "countDownLatch.getCount() <= old(countDownLatch.getCount())"
+    })
+    @Override
+    public synchronized void threadIsDone(final Thread thread) {
+        nThreadsAnalyzed++;
+
+        if ( DEBUG ) logger.warn("  Countdown " + countDownLatch.getCount() + " in thread " + Thread.currentThread().getName());
+
+        super.threadIsDone(thread);
+
+        // remove the thread from the list of active activeThreads, if it's in there, and decrement the countdown latch
+        if ( activeThreads.remove(thread) ) {
+            // one less thread is live for those blocking on all activeThreads to be complete
+            countDownLatch.countDown();
+            if ( DEBUG ) logger.warn("  -> Countdown " + countDownLatch.getCount() + " in thread " + Thread.currentThread().getName());
+        }
+    }
+
+    /**
+     * Create a new thread from this factory
+     *
+     * @param runnable
+     * @return
+     */
+    @Override
+    @Ensures({
+            "activeThreads.size() > old(activeThreads.size())",
+            "activeThreads.contains(result)",
+            "nThreadsCreated == old(nThreadsCreated) + 1"
+    })
+    public synchronized Thread newThread(final Runnable runnable) {
+        if ( activeThreads.size() >= nThreadsToCreate)
+            throw new IllegalStateException("Attempting to create more activeThreads than allowed by constructor argument nThreadsToCreate " + nThreadsToCreate);
+
+        nThreadsCreated++;
+        final Thread myThread = new TrackingThread(runnable);
+        activeThreads.add(myThread);
+        return myThread;
+    }
+
+    /**
+     * A wrapper around Thread that tracks the runtime of the thread and calls threadIsDone() when complete
+     */
+    private class TrackingThread extends Thread {
+        private TrackingThread(Runnable runnable) {
+            super(runnable);
+        }
+
+        @Override
+        public void run() {
+            super.run();
+            threadIsDone(this);
+        }
+    }
+}
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/threading/NamedThreadFactory.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/threading/NamedThreadFactory.java
new file mode 100644
index 0000000..6c84086
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/threading/NamedThreadFactory.java
@@ -0,0 +1,51 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.utils.threading;
+
+import java.util.concurrent.ThreadFactory;
+
+/**
+ * Thread factor that produces threads with a given name pattern
+ *
+ * User: depristo
+ * Date: 9/5/12
+ * Time: 9:22 PM
+ *
+ */
+public class NamedThreadFactory implements ThreadFactory {
+    static int id = 0;
+    final String format;
+
+    public NamedThreadFactory(String format) {
+        this.format = format;
+        String.format(format, id); // test the name
+    }
+
+    @Override
+    public Thread newThread(Runnable r) {
+        return new Thread(r, String.format(format, id++));
+    }
+}
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/threading/ThreadEfficiencyMonitor.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/threading/ThreadEfficiencyMonitor.java
new file mode 100644
index 0000000..cee91a4
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/threading/ThreadEfficiencyMonitor.java
@@ -0,0 +1,232 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.utils.threading;
+
+import com.google.java.contract.Ensures;
+import com.google.java.contract.Invariant;
+import com.google.java.contract.Requires;
+import org.apache.log4j.Logger;
+import org.apache.log4j.Priority;
+import org.broadinstitute.gatk.utils.AutoFormattingTime;
+
+import java.lang.management.ManagementFactory;
+import java.lang.management.ThreadInfo;
+import java.lang.management.ThreadMXBean;
+import java.util.EnumMap;
+import java.util.concurrent.TimeUnit;
+
+/**
+ * Uses an MXBean to monitor thread efficiency
+ *
+ * Once the monitor is created, calls to threadIsDone() can be used to add information
+ * about the efficiency of the provided thread to this monitor.
+ *
+ * Provides simple print() for displaying efficiency information to a logger
+ *
+ * User: depristo
+ * Date: 8/22/12
+ * Time: 10:48 AM
+ */
+ at Invariant({"nThreadsAnalyzed >= 0"})
+public class ThreadEfficiencyMonitor {
+    protected static final boolean DEBUG = false;
+    protected static Logger logger = Logger.getLogger(EfficiencyMonitoringThreadFactory.class);
+    final EnumMap<State, Long> times = new EnumMap<State, Long>(State.class);
+
+    /**
+     * The number of threads we've included in our efficiency monitoring
+     */
+    int nThreadsAnalyzed = 0;
+
+    /**
+     * The bean used to get the thread info about blocked and waiting times
+     */
+    final ThreadMXBean bean;
+
+    public ThreadEfficiencyMonitor() {
+        bean = ManagementFactory.getThreadMXBean();
+
+        // get the bean, and start tracking
+        if ( bean.isThreadContentionMonitoringSupported() )
+            bean.setThreadContentionMonitoringEnabled(true);
+        else
+            logger.warn("Thread contention monitoring not supported, we cannot track GATK multi-threaded efficiency");
+        //bean.setThreadCpuTimeEnabled(true);
+
+        if ( bean.isThreadCpuTimeSupported() )
+            bean.setThreadCpuTimeEnabled(true);
+        else
+            logger.warn("Thread CPU monitoring not supported, we cannot track GATK multi-threaded efficiency");
+
+        // initialize times to 0
+        for ( final State state : State.values() )
+            times.put(state, 0l);
+    }
+
+    private static long nanoToMilli(final long timeInNano) {
+        return TimeUnit.NANOSECONDS.toMillis(timeInNano);
+    }
+
+    /**
+     * Get the time spent in state across all threads created by this factory
+     *
+     * @param state to get information about
+     * @return the time in milliseconds
+     */
+    @Ensures({"result >= 0"})
+    public synchronized long getStateTime(final State state) {
+        return times.get(state);
+    }
+
+    /**
+     * Get the total time spent in all states across all threads created by this factory
+     *
+     * @return the time in milliseconds
+     */
+    @Ensures({"result >= 0"})
+    public synchronized long getTotalTime() {
+        long total = 0;
+        for ( final long time : times.values() )
+            total += time;
+        return total;
+    }
+
+    /**
+     * Get the fraction of time spent in state across all threads created by this factory
+     *
+     * @return the percentage (0.0-100.0) of time spent in state over all state times of all threads
+     */
+    @Ensures({"result >= 0.0", "result <= 100.0"})
+    public synchronized double getStatePercent(final State state) {
+        return (100.0 * getStateTime(state)) / Math.max(getTotalTime(), 1);
+    }
+
+    public int getnThreadsAnalyzed() {
+        return nThreadsAnalyzed;
+    }
+
+    @Override
+    public synchronized String toString() {
+        final StringBuilder b = new StringBuilder();
+
+        b.append("total ").append(getTotalTime()).append(" ");
+        for ( final State state : State.values() ) {
+            b.append(state).append(" ").append(getStateTime(state)).append(" ");
+        }
+
+        return b.toString();
+    }
+
+    /**
+     * Print usage information about threads from this factory to logger
+     * with the INFO priority
+     *
+     * @param logger
+     */
+    public synchronized void printUsageInformation(final Logger logger) {
+        printUsageInformation(logger, Priority.INFO);
+    }
+
+    /**
+     * Print usage information about threads from this factory to logger
+     * with the provided priority
+     *
+     * @param logger
+     */
+    public synchronized void printUsageInformation(final Logger logger, final Priority priority) {
+        logger.debug("Number of threads monitored: " + getnThreadsAnalyzed());
+        logger.debug("Total runtime " + new AutoFormattingTime(TimeUnit.MILLISECONDS.toNanos(getTotalTime())));
+        for ( final State state : State.values() ) {
+            logger.debug(String.format("\tPercent of time spent %s is %.2f", state.getUserFriendlyName(), getStatePercent(state)));
+        }
+        logger.log(priority, String.format("CPU      efficiency : %6.2f%% of time spent %s", getStatePercent(State.USER_CPU), State.USER_CPU.getUserFriendlyName()));
+        logger.log(priority, String.format("Walker inefficiency : %6.2f%% of time spent %s", getStatePercent(State.BLOCKING), State.BLOCKING.getUserFriendlyName()));
+        logger.log(priority, String.format("I/O    inefficiency : %6.2f%% of time spent %s", getStatePercent(State.WAITING_FOR_IO), State.WAITING_FOR_IO.getUserFriendlyName()));
+        logger.log(priority, String.format("Thread inefficiency : %6.2f%% of time spent %s", getStatePercent(State.WAITING), State.WAITING.getUserFriendlyName()));
+    }
+
+    /**
+     * Update the information about completed thread that ran for runtime in milliseconds
+     *
+     * This method updates all of the key timing and tracking information in the factory so that
+     * thread can be retired.  After this call the factory shouldn't have a pointer to the thread any longer
+     *
+     * @param thread the thread whose information we are updating
+     */
+    @Ensures({
+            "getTotalTime() >= old(getTotalTime())"
+    })
+    public synchronized void threadIsDone(final Thread thread) {
+        nThreadsAnalyzed++;
+
+        if ( DEBUG ) logger.warn("UpdateThreadInfo called");
+
+        final long threadID = thread.getId();
+        final ThreadInfo info = bean.getThreadInfo(thread.getId());
+        final long totalTimeNano = bean.getThreadCpuTime(threadID);
+        final long userTimeNano = bean.getThreadUserTime(threadID);
+        final long systemTimeNano = totalTimeNano - userTimeNano;
+        final long userTimeInMilliseconds = nanoToMilli(userTimeNano);
+        final long systemTimeInMilliseconds = nanoToMilli(systemTimeNano);
+
+        if ( info != null ) {
+            if ( DEBUG ) logger.warn("Updating thread with user runtime " + userTimeInMilliseconds + " and system runtime " + systemTimeInMilliseconds + " of which blocked " + info.getBlockedTime() + " and waiting " + info.getWaitedTime());
+            incTimes(State.BLOCKING, info.getBlockedTime());
+            incTimes(State.WAITING, info.getWaitedTime());
+            incTimes(State.USER_CPU, userTimeInMilliseconds);
+            incTimes(State.WAITING_FOR_IO, systemTimeInMilliseconds);
+        }
+    }
+
+    /**
+     * Helper function that increments the times counter by by for state
+     *
+     * @param state
+     * @param by
+     */
+    @Requires({"state != null", "by >= 0"})
+    @Ensures("getTotalTime() == old(getTotalTime()) + by")
+    private synchronized void incTimes(final State state, final long by) {
+        times.put(state, times.get(state) + by);
+    }
+
+    public enum State {
+        BLOCKING("blocking on synchronized data structures"),
+        WAITING("waiting on some other thread"),
+        USER_CPU("doing productive CPU work"),
+        WAITING_FOR_IO("waiting for I/O");
+
+        private final String userFriendlyName;
+
+        private State(String userFriendlyName) {
+            this.userFriendlyName = userFriendlyName;
+        }
+
+        public String getUserFriendlyName() {
+            return userFriendlyName;
+        }
+    }
+}
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/threading/ThreadLocalArray.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/threading/ThreadLocalArray.java
new file mode 100644
index 0000000..b8dea06
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/threading/ThreadLocalArray.java
@@ -0,0 +1,65 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.utils.threading;
+
+import java.lang.reflect.Array;
+
+/**
+ * ThreadLocal implementation for arrays
+ *
+ * Example usage:
+ *
+ * private ThreadLocal<byte[]> threadLocalByteArray = new ThreadLocalArray<byte[]>(length, byte.class);
+ * ....
+ * byte[] byteArray = threadLocalByteArray.get();
+ *
+ * @param <T> the type of the array itself (eg., int[], double[], etc.)
+ *
+ * @author David Roazen
+ */
+public class ThreadLocalArray<T> extends ThreadLocal<T> {
+    private int arraySize;
+    private Class arrayElementType;
+
+    /**
+     * Create a new ThreadLocalArray
+     *
+     * @param arraySize desired length of the array
+     * @param arrayElementType type of the elements within the array (eg., Byte.class, Integer.class, etc.)
+     */
+    public ThreadLocalArray( int arraySize, Class arrayElementType ) {
+        super();
+
+        this.arraySize = arraySize;
+        this.arrayElementType = arrayElementType;
+    }
+
+    @Override
+    @SuppressWarnings("unchecked")
+    protected T initialValue() {
+        return (T)Array.newInstance(arrayElementType, arraySize);
+    }
+}
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/threading/ThreadPoolMonitor.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/threading/ThreadPoolMonitor.java
new file mode 100644
index 0000000..9261870
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/threading/ThreadPoolMonitor.java
@@ -0,0 +1,77 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.utils.threading;
+
+import org.apache.log4j.Logger;
+/**
+ * User: hanna
+ * Date: Apr 29, 2009
+ * Time: 4:27:58 PM
+ * BROAD INSTITUTE SOFTWARE COPYRIGHT NOTICE AND AGREEMENT
+ * Software and documentation are copyright 2005 by the Broad Institute.
+ * All rights are reserved.
+ *
+ * Users acknowledge that this software is supplied without any warranty or support.
+ * The Broad Institute is not responsible for its use, misuse, or
+ * functionality.
+ */
+
+/**
+ * Waits for a signal to come through that the thread pool has run
+ * a given task and therefore has a free slot.
+ *
+ * Make sure, that, when using, the submit and the run are both
+ * protected by the same synchronized(monitor) lock.  See the test
+ * case for an example.
+ */
+public class ThreadPoolMonitor implements Runnable {
+    /**
+     * Logger for reporting interruptions, etc.
+     */
+    private static Logger logger = Logger.getLogger(ThreadPoolMonitor.class);
+
+    /**
+     * Watch the monitor
+     */
+    public synchronized void watch() {
+        try {
+            wait();
+        }
+        catch( InterruptedException ex ) {
+            logger.error("ThreadPoolMonitor interrupted:" + ex.getStackTrace());
+            throw new RuntimeException("ThreadPoolMonitor interrupted", ex);
+        }
+    }
+
+    /**
+     * Instruct the monitor that the thread pool has run for the class.
+     * Only the thread pool should execute this method.
+     */
+    public synchronized void run() {
+        notify();
+    }
+}
+
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/threading/package-info.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/threading/package-info.java
new file mode 100644
index 0000000..83093ba
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/threading/package-info.java
@@ -0,0 +1,26 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.utils.threading;
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/variant/GATKVCFIndexType.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/variant/GATKVCFIndexType.java
new file mode 100644
index 0000000..f142da2
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/variant/GATKVCFIndexType.java
@@ -0,0 +1,39 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.utils.variant;
+
+import org.broadinstitute.gatk.utils.commandline.EnumerationArgumentDefault;
+
+/**
+ * Choose the Tribble indexing strategy
+ */
+public enum GATKVCFIndexType {
+    @EnumerationArgumentDefault
+    DYNAMIC_SEEK,       // use DynamicIndexCreator(IndexFactory.IndexBalanceApproach.FOR_SEEK_TIME)
+    DYNAMIC_SIZE,       // use DynamicIndexCreator(IndexFactory.IndexBalanceApproach.FOR_SIZE)
+    LINEAR,             // use LinearIndexCreator()
+    INTERVAL            // use IntervalIndexCreator()
+}
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/variant/GATKVCFUtils.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/variant/GATKVCFUtils.java
new file mode 100644
index 0000000..6baa7b6
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/variant/GATKVCFUtils.java
@@ -0,0 +1,316 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.utils.variant;
+
+import htsjdk.samtools.SAMSequenceDictionary;
+import org.apache.log4j.Logger;
+import htsjdk.tribble.Feature;
+import htsjdk.tribble.FeatureCodec;
+import htsjdk.tribble.FeatureCodecHeader;
+import htsjdk.tribble.index.DynamicIndexCreator;
+import htsjdk.tribble.index.IndexCreator;
+import htsjdk.tribble.index.IndexFactory;
+import htsjdk.tribble.index.interval.IntervalIndexCreator;
+import htsjdk.tribble.index.linear.LinearIndexCreator;
+import htsjdk.tribble.index.tabix.TabixFormat;
+import htsjdk.tribble.index.tabix.TabixIndexCreator;
+import htsjdk.tribble.readers.LineIterator;
+import htsjdk.tribble.readers.PositionalBufferedStream;
+import org.broadinstitute.gatk.utils.commandline.RodBinding;
+import org.broadinstitute.gatk.engine.CommandLineGATK;
+import org.broadinstitute.gatk.engine.GenomeAnalysisEngine;
+import org.broadinstitute.gatk.engine.datasources.rmd.ReferenceOrderedDataSource;
+import org.broadinstitute.gatk.engine.io.stubs.VCFWriterArgumentTypeDescriptor;
+import org.broadinstitute.gatk.utils.collections.Pair;
+import htsjdk.variant.variantcontext.VariantContext;
+import htsjdk.variant.vcf.*;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.util.*;
+
+
+/**
+ * A set of GATK-specific static utility methods for common operations on VCF files/records.
+ */
+public class GATKVCFUtils {
+
+    /**
+     * Constructor access disallowed...static utility methods only!
+     */
+    private GATKVCFUtils() { }
+
+    public static final Logger logger = Logger.getLogger(GATKVCFUtils.class);
+    public final static String GATK_COMMAND_LINE_KEY = "GATKCommandLine";
+
+    public final static GATKVCFIndexType DEFAULT_INDEX_TYPE = GATKVCFIndexType.DYNAMIC_SEEK;  // by default, optimize for seek time.  All indices prior to Nov 2013 used this type.
+    public final static Integer DEFAULT_INDEX_PARAMETER = -1;           // the default DYNAMIC_SEEK does not use a parameter
+
+    /**
+     * Gets the appropriately formatted header for a VCF file describing this GATK run
+     *
+     * @param engine the GATK engine that holds the walker name, GATK version, and other information
+     * @param argumentSources contains information on the argument values provided to the GATK for converting to a
+     *                        command line string.  Should be provided from the data in the parsing engine.  Can be
+     *                        empty in which case the command line will be the empty string.
+     * @return VCF header line describing this run of the GATK.
+     */
+    public static VCFHeaderLine getCommandLineArgumentHeaderLine(final GenomeAnalysisEngine engine, final Collection<Object> argumentSources) {
+        if ( engine == null ) throw new IllegalArgumentException("engine cannot be null");
+        if ( argumentSources == null ) throw new IllegalArgumentException("argumentSources cannot be null");
+
+        final Map<String, String> attributes = new LinkedHashMap<>();
+        attributes.put("ID", engine.getWalkerName());
+        attributes.put("Version", CommandLineGATK.getVersionNumber());
+        final Date date = new Date();
+        attributes.put("Date", date.toString());
+        attributes.put("Epoch", Long.toString(date.getTime()));
+        attributes.put("CommandLineOptions", engine.createApproximateCommandLineArgumentString(argumentSources.toArray()));
+        return new VCFSimpleHeaderLine(GATK_COMMAND_LINE_KEY, attributes);
+    }
+
+    public static <T extends Feature> Map<String, VCFHeader> getVCFHeadersFromRods(GenomeAnalysisEngine toolkit, List<RodBinding<T>> rodBindings) {
+        // Collect the eval rod names
+        final Set<String> names = new TreeSet<String>();
+        for ( final RodBinding<T> evalRod : rodBindings )
+            names.add(evalRod.getName());
+        return getVCFHeadersFromRods(toolkit, names);
+    }
+
+    public static Map<String, VCFHeader> getVCFHeadersFromRods(GenomeAnalysisEngine toolkit) {
+        return getVCFHeadersFromRods(toolkit, (Collection<String>)null);
+    }
+
+    public static Map<String, VCFHeader> getVCFHeadersFromRods(GenomeAnalysisEngine toolkit, Collection<String> rodNames) {
+        Map<String, VCFHeader> data = new HashMap<String, VCFHeader>();
+
+        // iterate to get all of the sample names
+        List<ReferenceOrderedDataSource> dataSources = toolkit.getRodDataSources();
+        for ( ReferenceOrderedDataSource source : dataSources ) {
+            // ignore the rod if it's not in our list
+            if ( rodNames != null && !rodNames.contains(source.getName()) )
+                continue;
+
+            if ( source.getHeader() != null && source.getHeader() instanceof VCFHeader )
+                data.put(source.getName(), (VCFHeader)source.getHeader());
+        }
+
+        return data;
+    }
+
+    public static Map<String,VCFHeader> getVCFHeadersFromRodPrefix(GenomeAnalysisEngine toolkit,String prefix) {
+        Map<String, VCFHeader> data = new HashMap<String, VCFHeader>();
+
+        // iterate to get all of the sample names
+        List<ReferenceOrderedDataSource> dataSources = toolkit.getRodDataSources();
+        for ( ReferenceOrderedDataSource source : dataSources ) {
+            // ignore the rod if lacks the prefix
+            if ( ! source.getName().startsWith(prefix) )
+                continue;
+
+            if ( source.getHeader() != null && source.getHeader() instanceof VCFHeader )
+                data.put(source.getName(), (VCFHeader)source.getHeader());
+        }
+
+        return data;
+    }
+
+    /**
+     * Gets the header fields from all VCF rods input by the user
+     *
+     * @param toolkit    GATK engine
+     *
+     * @return a set of all fields
+     */
+    public static Set<VCFHeaderLine> getHeaderFields(GenomeAnalysisEngine toolkit) {
+        return getHeaderFields(toolkit, null);
+    }
+
+    /**
+     * Gets the header fields from all VCF rods input by the user
+     *
+     * @param toolkit    GATK engine
+     * @param rodNames   names of rods to use, or null if we should use all possible ones
+     *
+     * @return a set of all fields
+     */
+    public static Set<VCFHeaderLine> getHeaderFields(GenomeAnalysisEngine toolkit, Collection<String> rodNames) {
+
+        // keep a map of sample name to occurrences encountered
+        TreeSet<VCFHeaderLine> fields = new TreeSet<VCFHeaderLine>();
+
+        // iterate to get all of the sample names
+        List<ReferenceOrderedDataSource> dataSources = toolkit.getRodDataSources();
+        for ( ReferenceOrderedDataSource source : dataSources ) {
+            // ignore the rod if it's not in our list
+            if ( rodNames != null && !rodNames.contains(source.getName()) )
+                continue;
+
+            if ( source.getRecordType().equals(VariantContext.class)) {
+                VCFHeader header = (VCFHeader)source.getHeader();
+                if ( header != null )
+                    fields.addAll(header.getMetaDataInSortedOrder());
+            }
+        }
+
+        return fields;
+    }
+
+    /**
+     * Add / replace the contig header lines in the VCFHeader with the information in the GATK engine
+     *
+     * @param header the header to update
+     * @param engine the GATK engine containing command line arguments and the master sequence dictionary
+     */
+    public static VCFHeader withUpdatedContigs(final VCFHeader header, final GenomeAnalysisEngine engine) {
+        return VCFUtils.withUpdatedContigs(header, engine.getArguments().referenceFile, engine.getMasterSequenceDictionary());
+    }
+
+    /**
+     * Create and return an IndexCreator
+     * @param type
+     * @param parameter
+     * @param outFile
+     * @return
+     */
+    public static IndexCreator getIndexCreator(GATKVCFIndexType type, int parameter, File outFile) {
+        return getIndexCreator(type, parameter, outFile, null);
+    }
+
+    /**
+     * Create and return an IndexCreator
+     * @param type
+     * @param parameter
+     * @param outFile
+     * @param sequenceDictionary
+     * @return
+     */
+    public static IndexCreator getIndexCreator(GATKVCFIndexType type, int parameter, File outFile, SAMSequenceDictionary sequenceDictionary) {
+        if (VCFWriterArgumentTypeDescriptor.isCompressed(outFile.toString())) {
+            if (type != GATKVCFUtils.DEFAULT_INDEX_TYPE || parameter != GATKVCFUtils.DEFAULT_INDEX_PARAMETER)
+                logger.warn("Creating Tabix index for " + outFile + ", ignoring user-specified index type and parameter");
+
+            if (sequenceDictionary == null)
+                return new TabixIndexCreator(TabixFormat.VCF);
+            else
+                return new TabixIndexCreator(sequenceDictionary, TabixFormat.VCF);
+        }
+
+        IndexCreator idxCreator;
+        switch (type) {
+            case DYNAMIC_SEEK: idxCreator = new DynamicIndexCreator(outFile, IndexFactory.IndexBalanceApproach.FOR_SEEK_TIME); break;
+            case DYNAMIC_SIZE: idxCreator = new DynamicIndexCreator(outFile, IndexFactory.IndexBalanceApproach.FOR_SIZE); break;
+            case LINEAR: idxCreator = new LinearIndexCreator(outFile, parameter); break;
+            case INTERVAL: idxCreator = new IntervalIndexCreator(outFile, parameter); break;
+            default: throw new IllegalArgumentException("Unknown IndexCreator type: " + type);
+        }
+
+        return idxCreator;
+    }
+
+    /**
+     * Utility class to read all of the VC records from a file
+     *
+     * @param file
+     * @param codec
+     * @return
+     * @throws IOException
+     */
+    public final static <SOURCE> Pair<VCFHeader, VCIterable<SOURCE>> readAllVCs( final File file, final FeatureCodec<VariantContext, SOURCE> codec) throws IOException {
+        // read in the features
+        SOURCE source = codec.makeSourceFromStream(new FileInputStream(file));
+        FeatureCodecHeader header = codec.readHeader(source);
+        final VCFHeader vcfHeader = (VCFHeader)header.getHeaderValue();
+        return new Pair<>(vcfHeader, new VCIterable<>(source, codec, vcfHeader));
+    }
+
+    public static class VCIterable<SOURCE> implements Iterable<VariantContext>, Iterator<VariantContext> {
+        final SOURCE source;
+        final FeatureCodec<VariantContext, SOURCE> codec;
+        final VCFHeader header;
+
+        private VCIterable(final SOURCE source, final FeatureCodec<VariantContext, SOURCE> codec, final VCFHeader header) {
+            this.source = source;
+            this.codec = codec;
+            this.header = header;
+        }
+
+        @Override
+        public Iterator<VariantContext> iterator() {
+            return this;
+        }
+
+        @Override
+        public boolean hasNext() {
+            return ! codec.isDone(source);
+        }
+
+        @Override
+        public VariantContext next() {
+            try {
+                final VariantContext vc = codec.decode(source);
+                return vc == null ? null : vc.fullyDecode(header, false);
+            } catch ( IOException e ) {
+                throw new RuntimeException(e);
+            }
+        }
+
+        @Override
+        public void remove() {
+        }
+    }
+
+    /**
+     * Read all of the VCF records from source into memory, returning the header and the VariantContexts
+     *
+     * SHOULD ONLY BE USED FOR UNIT/INTEGRATION TESTING PURPOSES!
+     *
+     * @param source the file to read, must be in VCF4 format
+     * @return
+     * @throws java.io.IOException
+     */
+    public static Pair<VCFHeader, List<VariantContext>> readVCF(final File source) throws IOException {
+        // read in the features
+        final List<VariantContext> vcs = new ArrayList<VariantContext>();
+        final VCFCodec codec = new VCFCodec();
+        PositionalBufferedStream pbs = new PositionalBufferedStream(new FileInputStream(source));
+        final LineIterator vcfSource = codec.makeSourceFromStream(pbs);
+        try {
+            final VCFHeader vcfHeader = (VCFHeader) codec.readActualHeader(vcfSource);
+
+            while (vcfSource.hasNext()) {
+                final VariantContext vc = codec.decode(vcfSource);
+                if ( vc != null )
+                    vcs.add(vc);
+            }
+
+            return new Pair<VCFHeader, List<VariantContext>>(vcfHeader, vcs);
+        } finally {
+            codec.close(vcfSource);
+        }
+    }
+}
\ No newline at end of file
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/variant/GATKVariantContextUtils.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/variant/GATKVariantContextUtils.java
new file mode 100644
index 0000000..a099d8c
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/variant/GATKVariantContextUtils.java
@@ -0,0 +1,1960 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.utils.variant;
+
+import com.google.java.contract.Ensures;
+import com.google.java.contract.Requires;
+import htsjdk.tribble.TribbleException;
+import htsjdk.tribble.util.popgen.HardyWeinbergCalculation;
+import htsjdk.variant.variantcontext.*;
+import htsjdk.variant.vcf.VCFConstants;
+import org.apache.commons.lang.ArrayUtils;
+import org.apache.log4j.Logger;
+import org.broadinstitute.gatk.utils.*;
+import org.broadinstitute.gatk.utils.collections.Pair;
+
+import java.io.Serializable;
+import java.util.*;
+
+public class GATKVariantContextUtils {
+
+    private static Logger logger = Logger.getLogger(GATKVariantContextUtils.class);
+
+    public static final int DEFAULT_PLOIDY = HomoSapiensConstants.DEFAULT_PLOIDY;
+
+    public static final double SUM_GL_THRESH_NOCALL = -0.1; // if sum(gl) is bigger than this threshold, we treat GL's as non-informative and will force a no-call.
+
+    /**
+     * Diploid NO_CALL allele list...
+     *
+     * @deprecated you should use {@link #noCallAlleles(int)} instead. It indicates the presence of a hardcoded diploid assumption which is bad.
+     */
+    @Deprecated
+    public final static List<Allele> NO_CALL_ALLELES = Arrays.asList(Allele.NO_CALL, Allele.NO_CALL);
+
+    public final static String NON_REF_SYMBOLIC_ALLELE_NAME = "NON_REF";
+    public final static Allele NON_REF_SYMBOLIC_ALLELE = Allele.create("<"+NON_REF_SYMBOLIC_ALLELE_NAME+">", false); // represents any possible non-ref allele at this site
+
+    public final static String MERGE_FILTER_PREFIX = "filterIn";
+    public final static String MERGE_REF_IN_ALL = "ReferenceInAll";
+    public final static String MERGE_FILTER_IN_ALL = "FilteredInAll";
+    public final static String MERGE_INTERSECTION = "Intersection";
+
+    /**
+     * Checks whether a variant-context overlaps with a region.
+     *
+     * <p>
+     *     No event overlaps an unmapped region.
+     * </p>
+     *
+     * @param variantContext variant-context to test the overlap with.
+     * @param region region to test the overlap with.
+     *
+     * @throws IllegalArgumentException if either region or event is {@code null}.
+     *
+     * @return {@code true} if there is an overlap between the event described and the active region provided.
+     */
+    public static boolean overlapsRegion(final VariantContext variantContext, final GenomeLoc region) {
+        if (region == null) throw new IllegalArgumentException("the active region provided cannot be null");
+        if (variantContext == null) throw new IllegalArgumentException("the variant context provided cannot be null");
+        if (region.isUnmapped())
+            return false;
+        if (variantContext.getEnd() < region.getStart())
+            return false;
+        if (variantContext.getStart() > region.getStop())
+            return false;
+        if (!variantContext.getChr().equals(region.getContig()))
+            return false;
+        return true;
+    }
+
+    /**
+     * Returns a homozygous call allele list given the only allele and the ploidy.
+     *
+     * @param allele the only allele in the allele list.
+     * @param ploidy the ploidy of the resulting allele list.
+     *
+     * @throws IllegalArgumentException if {@code allele} is {@code null} or ploidy is negative.
+     *
+     * @return never {@code null}.
+     */
+    public static List<Allele> homozygousAlleleList(final Allele allele, final int ploidy) {
+        if (allele == null || ploidy < 0)
+            throw new IllegalArgumentException();
+
+        // Use a tailored inner class to implement the list:
+        return Collections.nCopies(ploidy,allele);
+    }
+
+    private static boolean hasPLIncompatibleAlleles(final Collection<Allele> alleleSet1, final Collection<Allele> alleleSet2) {
+        final Iterator<Allele> it1 = alleleSet1.iterator();
+        final Iterator<Allele> it2 = alleleSet2.iterator();
+
+        while ( it1.hasNext() && it2.hasNext() ) {
+            final Allele a1 = it1.next();
+            final Allele a2 = it2.next();
+            if ( ! a1.equals(a2) )
+                return true;
+        }
+
+        // by this point, at least one of the iterators is empty.  All of the elements
+        // we've compared are equal up until this point.  But it's possible that the
+        // sets aren't the same size, which is indicated by the test below.  If they
+        // are of the same size, though, the sets are compatible
+        return it1.hasNext() || it2.hasNext();
+    }
+
+    /**
+     * Determines the common reference allele
+     *
+     * @param VCs    the list of VariantContexts
+     * @param loc    if not null, ignore records that do not begin at this start location
+     * @return possibly null Allele
+     */
+    protected static Allele determineReferenceAllele(final List<VariantContext> VCs, final GenomeLoc loc) {
+        Allele ref = null;
+
+        for ( final VariantContext vc : VCs ) {
+            if ( contextMatchesLoc(vc, loc) ) {
+                final Allele myRef = vc.getReference();
+                if ( ref == null || ref.length() < myRef.length() )
+                    ref = myRef;
+                else if ( ref.length() == myRef.length() && ! ref.equals(myRef) )
+                    throw new TribbleException(String.format("The provided variant file(s) have inconsistent references for the same position(s) at %s:%d, %s vs. %s", vc.getChr(), vc.getStart(), ref, myRef));
+            }
+        }
+
+        return ref;
+    }
+
+    /**
+     * Calculates the total ploidy of a variant context as the sum of all plodies across genotypes.
+     * @param vc the target variant context.
+     * @param defaultPloidy the default ploidy to be assume when there is no ploidy information for a genotype.
+     * @return never {@code null}.
+     */
+    public static int totalPloidy(final VariantContext vc, final int defaultPloidy) {
+        if (vc == null)
+            throw new IllegalArgumentException("the vc provided cannot be null");
+        if (defaultPloidy < 0)
+            throw new IllegalArgumentException("the default ploidy must 0 or greater");
+        int result = 0;
+        for (final Genotype genotype : vc.getGenotypes()) {
+            final int declaredPloidy = genotype.getPloidy();
+            result += declaredPloidy <= 0 ? defaultPloidy : declaredPloidy;
+        }
+
+        return result;
+    }
+
+    public enum GenotypeMergeType {
+        /**
+         * Make all sample genotypes unique by file. Each sample shared across RODs gets named sample.ROD.
+         */
+        UNIQUIFY,
+        /**
+         * Take genotypes in priority order (see the priority argument).
+         */
+        PRIORITIZE,
+        /**
+         * Take the genotypes in any order.
+         */
+        UNSORTED,
+        /**
+         * Require that all samples/genotypes be unique between all inputs.
+         */
+        REQUIRE_UNIQUE
+    }
+
+    public enum FilteredRecordMergeType {
+        /**
+         * Union - leaves the record if any record is unfiltered.
+         */
+        KEEP_IF_ANY_UNFILTERED,
+        /**
+         * Requires all records present at site to be unfiltered. VCF files that don't contain the record don't influence this.
+         */
+        KEEP_IF_ALL_UNFILTERED,
+        /**
+         * If any record is present at this site (regardless of possibly being filtered), then all such records are kept and the filters are reset.
+         */
+        KEEP_UNCONDITIONAL
+    }
+
+    public enum MultipleAllelesMergeType {
+        /**
+         * Combine only alleles of the same type (SNP, indel, etc.) into a single VCF record.
+         */
+        BY_TYPE,
+        /**
+         * Merge all allele types at the same start position into the same VCF record.
+         */
+        MIX_TYPES
+    }
+
+    /**
+     * Refactored out of the AverageAltAlleleLength annotation class
+     * @param vc the variant context
+     * @return the average length of the alt allele (a double)
+     */
+    public static double getMeanAltAlleleLength(VariantContext vc) {
+        double averageLength = 1.0;
+        if ( ! vc.isSNP() && ! vc.isSymbolic() ) {
+            // adjust for the event length
+            int averageLengthNum = 0;
+            int averageLengthDenom = 0;
+            int refLength = vc.getReference().length();
+            for ( final Allele a : vc.getAlternateAlleles() ) {
+                int numAllele = vc.getCalledChrCount(a);
+                int alleleSize;
+                if ( a.length() == refLength ) {
+                    // SNP or MNP
+                    byte[] a_bases = a.getBases();
+                    byte[] ref_bases = vc.getReference().getBases();
+                    int n_mismatch = 0;
+                    for ( int idx = 0; idx < a_bases.length; idx++ ) {
+                        if ( a_bases[idx] != ref_bases[idx] )
+                            n_mismatch++;
+                    }
+                    alleleSize = n_mismatch;
+                }
+                else if ( a.isSymbolic() ) {
+                    alleleSize = 1;
+                } else {
+                    alleleSize = Math.abs(refLength-a.length());
+                }
+                averageLengthNum += alleleSize*numAllele;
+                averageLengthDenom += numAllele;
+            }
+            averageLength = ( (double) averageLengthNum )/averageLengthDenom;
+        }
+
+        return averageLength;
+    }
+
+    /**
+     * create a genome location, given a variant context
+     * @param genomeLocParser parser
+     * @param vc the variant context
+     * @return the genomeLoc
+     */
+    public static final GenomeLoc getLocation(GenomeLocParser genomeLocParser,VariantContext vc) {
+        return genomeLocParser.createGenomeLoc(vc.getChr(), vc.getStart(), vc.getEnd(), true);
+    }
+
+    public static BaseUtils.BaseSubstitutionType getSNPSubstitutionType(VariantContext context) {
+        if (!context.isSNP() || !context.isBiallelic())
+            throw new IllegalStateException("Requested SNP substitution type for bialleic non-SNP " + context);
+        return BaseUtils.SNPSubstitutionType(context.getReference().getBases()[0], context.getAlternateAllele(0).getBases()[0]);
+    }
+
+    /**
+     * If this is a BiAllelic SNP, is it a transition?
+     */
+    public static boolean isTransition(VariantContext context) {
+        return getSNPSubstitutionType(context) == BaseUtils.BaseSubstitutionType.TRANSITION;
+    }
+
+    /**
+     * If this is a BiAllelic SNP, is it a transversion?
+     */
+    public static boolean isTransversion(VariantContext context) {
+        return getSNPSubstitutionType(context) == BaseUtils.BaseSubstitutionType.TRANSVERSION;
+    }
+
+    public static boolean isTransition(Allele ref, Allele alt) {
+        return BaseUtils.SNPSubstitutionType(ref.getBases()[0], alt.getBases()[0]) == BaseUtils.BaseSubstitutionType.TRANSITION;
+    }
+
+    public static boolean isTransversion(Allele ref, Allele alt) {
+        return BaseUtils.SNPSubstitutionType(ref.getBases()[0], alt.getBases()[0]) == BaseUtils.BaseSubstitutionType.TRANSVERSION;
+    }
+
+    /**
+     * Returns a context identical to this with the REF and ALT alleles reverse complemented.
+     *
+     * @param vc        variant context
+     * @return new vc
+     */
+    public static VariantContext reverseComplement(VariantContext vc) {
+        // create a mapping from original allele to reverse complemented allele
+        HashMap<Allele, Allele> alleleMap = new HashMap<>(vc.getAlleles().size());
+        for ( final Allele originalAllele : vc.getAlleles() ) {
+            Allele newAllele;
+            if ( originalAllele.isNoCall() )
+                newAllele = originalAllele;
+            else
+                newAllele = Allele.create(BaseUtils.simpleReverseComplement(originalAllele.getBases()), originalAllele.isReference());
+            alleleMap.put(originalAllele, newAllele);
+        }
+
+        // create new Genotype objects
+        GenotypesContext newGenotypes = GenotypesContext.create(vc.getNSamples());
+        for ( final Genotype genotype : vc.getGenotypes() ) {
+            List<Allele> newAlleles = new ArrayList<>();
+            for ( final Allele allele : genotype.getAlleles() ) {
+                Allele newAllele = alleleMap.get(allele);
+                if ( newAllele == null )
+                    newAllele = Allele.NO_CALL;
+                newAlleles.add(newAllele);
+            }
+            newGenotypes.add(new GenotypeBuilder(genotype).alleles(newAlleles).make());
+        }
+
+        return new VariantContextBuilder(vc).alleles(alleleMap.values()).genotypes(newGenotypes).make();
+    }
+
+    /**
+     * Returns true iff VC is an non-complex indel where every allele represents an expansion or
+     * contraction of a series of identical bases in the reference.
+     *
+     * For example, suppose the ref bases are CTCTCTGA, which includes a 3x repeat of CTCTCT
+     *
+     * If VC = -/CT, then this function returns true because the CT insertion matches exactly the
+     * upcoming reference.
+     * If VC = -/CTA then this function returns false because the CTA isn't a perfect match
+     *
+     * Now consider deletions:
+     *
+     * If VC = CT/- then again the same logic applies and this returns true
+     * The case of CTA/- makes no sense because it doesn't actually match the reference bases.
+     *
+     * The logic of this function is pretty simple.  Take all of the non-null alleles in VC.  For
+     * each insertion allele of n bases, check if that allele matches the next n reference bases.
+     * For each deletion allele of n bases, check if this matches the reference bases at n - 2 n,
+     * as it must necessarily match the first n bases.  If this test returns true for all
+     * alleles you are a tandem repeat, otherwise you are not.
+     *
+     * @param vc
+     * @param refBasesStartingAtVCWithPad not this is assumed to include the PADDED reference
+     * @return
+     */
+    @Requires({"vc != null", "refBasesStartingAtVCWithPad != null && refBasesStartingAtVCWithPad.length > 0"})
+    public static boolean isTandemRepeat(final VariantContext vc, final byte[] refBasesStartingAtVCWithPad) {
+        final String refBasesStartingAtVCWithoutPad = new String(refBasesStartingAtVCWithPad).substring(1);
+        if ( ! vc.isIndel() ) // only indels are tandem repeats
+            return false;
+
+        final Allele ref = vc.getReference();
+
+        for ( final Allele allele : vc.getAlternateAlleles() ) {
+            if ( ! isRepeatAllele(ref, allele, refBasesStartingAtVCWithoutPad) )
+                return false;
+        }
+
+        // we've passed all of the tests, so we are a repeat
+        return true;
+    }
+
+    /**
+     *
+     * @param vc
+     * @param refBasesStartingAtVCWithPad
+     * @return
+     */
+    @Requires({"vc != null", "refBasesStartingAtVCWithPad != null && refBasesStartingAtVCWithPad.length > 0"})
+    public static Pair<List<Integer>,byte[]> getNumTandemRepeatUnits(final VariantContext vc, final byte[] refBasesStartingAtVCWithPad) {
+        final boolean VERBOSE = false;
+        final String refBasesStartingAtVCWithoutPad = new String(refBasesStartingAtVCWithPad).substring(1);
+        if ( ! vc.isIndel() ) // only indels are tandem repeats
+            return null;
+
+        final Allele refAllele = vc.getReference();
+        final byte[] refAlleleBases = Arrays.copyOfRange(refAllele.getBases(), 1, refAllele.length());
+
+        byte[] repeatUnit = null;
+        final ArrayList<Integer> lengths = new ArrayList<>();
+
+        for ( final Allele allele : vc.getAlternateAlleles() ) {
+            Pair<int[],byte[]> result = getNumTandemRepeatUnits(refAlleleBases, Arrays.copyOfRange(allele.getBases(), 1, allele.length()), refBasesStartingAtVCWithoutPad.getBytes());
+
+            final int[] repetitionCount = result.first;
+            // repetition count = 0 means allele is not a tandem expansion of context
+            if (repetitionCount[0] == 0 || repetitionCount[1] == 0)
+                return null;
+
+            if (lengths.size() == 0) {
+                lengths.add(repetitionCount[0]); // add ref allele length only once
+            }
+            lengths.add(repetitionCount[1]);  // add this alt allele's length
+
+            repeatUnit = result.second;
+            if (VERBOSE) {
+                System.out.println("RefContext:"+refBasesStartingAtVCWithoutPad);
+                System.out.println("Ref:"+refAllele.toString()+" Count:" + String.valueOf(repetitionCount[0]));
+                System.out.println("Allele:"+allele.toString()+" Count:" + String.valueOf(repetitionCount[1]));
+                System.out.println("RU:"+new String(repeatUnit));
+            }
+        }
+
+        return new Pair<List<Integer>, byte[]>(lengths,repeatUnit);
+    }
+
+    public static Pair<int[],byte[]> getNumTandemRepeatUnits(final byte[] refBases, final byte[] altBases, final byte[] remainingRefContext) {
+         /* we can't exactly apply same logic as in basesAreRepeated() to compute tandem unit and number of repeated units.
+           Consider case where ref =ATATAT and we have an insertion of ATAT. Natural description is (AT)3 -> (AT)2.
+         */
+
+        byte[] longB;
+        // find first repeat unit based on either ref or alt, whichever is longer
+        if (altBases.length > refBases.length)
+            longB = altBases;
+        else
+            longB = refBases;
+
+        // see if non-null allele (either ref or alt, whichever is longer) can be decomposed into several identical tandem units
+        // for example, -*,CACA needs to first be decomposed into (CA)2
+        final int repeatUnitLength = findRepeatedSubstring(longB);
+        final byte[] repeatUnit = Arrays.copyOf(longB, repeatUnitLength);
+
+        final int[] repetitionCount = new int[2];
+        // look for repetitions forward on the ref bases (i.e. starting at beginning of ref bases)
+        int repetitionsInRef = findNumberOfRepetitions(repeatUnit, refBases, true);
+        repetitionCount[0] = findNumberOfRepetitions(repeatUnit, ArrayUtils.addAll(refBases, remainingRefContext), true)-repetitionsInRef;
+        repetitionCount[1] = findNumberOfRepetitions(repeatUnit, ArrayUtils.addAll(altBases, remainingRefContext), true)-repetitionsInRef;
+
+        return new Pair<>(repetitionCount, repeatUnit);
+
+    }
+
+    /**
+     * Find out if a string can be represented as a tandem number of substrings.
+     * For example ACTACT is a 2-tandem of ACT,
+     * but ACTACA is not.
+     *
+     * @param bases                 String to be tested
+     * @return                      Length of repeat unit, if string can be represented as tandem of substring (if it can't
+     *                              be represented as one, it will be just the length of the input string)
+     */
+    public static int findRepeatedSubstring(byte[] bases) {
+
+        int repLength;
+        for (repLength=1; repLength <=bases.length; repLength++) {
+            final byte[] candidateRepeatUnit = Arrays.copyOf(bases,repLength);
+            boolean allBasesMatch = true;
+            for (int start = repLength; start < bases.length; start += repLength ) {
+                // check that remaining of string is exactly equal to repeat unit
+                final byte[] basePiece = Arrays.copyOfRange(bases,start,start+candidateRepeatUnit.length);
+                if (!Arrays.equals(candidateRepeatUnit, basePiece)) {
+                    allBasesMatch = false;
+                    break;
+                }
+            }
+            if (allBasesMatch)
+                return repLength;
+        }
+
+        return repLength;
+    }
+
+    /**
+     * Helper routine that finds number of repetitions a string consists of.
+     * For example, for string ATAT and repeat unit AT, number of repetitions = 2
+     * @param repeatUnit             Substring
+     * @param testString             String to test
+     * @oaram lookForward            Look for repetitions forward (at beginning of string) or backward (at end of string)
+     * @return                       Number of repetitions (0 if testString is not a concatenation of n repeatUnit's
+     */
+    public static int findNumberOfRepetitions(byte[] repeatUnit, byte[] testString, boolean lookForward) {
+        int numRepeats = 0;
+        if (lookForward) {
+            // look forward on the test string
+            for (int start = 0; start < testString.length; start += repeatUnit.length) {
+                int end = start + repeatUnit.length;
+                byte[] unit = Arrays.copyOfRange(testString,start, end);
+                if(Arrays.equals(unit,repeatUnit))
+                    numRepeats++;
+                else
+                    break;
+            }
+            return numRepeats;
+        }
+
+        // look backward. For example, if repeatUnit = AT and testString = GATAT, number of repeat units is still 2
+        // look forward on the test string
+        for (int start = testString.length - repeatUnit.length; start >= 0; start -= repeatUnit.length) {
+            int end = start + repeatUnit.length;
+            byte[] unit = Arrays.copyOfRange(testString,start, end);
+            if(Arrays.equals(unit,repeatUnit))
+                numRepeats++;
+            else
+                break;
+        }
+        return numRepeats;
+    }
+
+    /**
+     * Helper function for isTandemRepeat that checks that allele matches somewhere on the reference
+     * @param ref
+     * @param alt
+     * @param refBasesStartingAtVCWithoutPad
+     * @return
+     */
+    protected static boolean isRepeatAllele(final Allele ref, final Allele alt, final String refBasesStartingAtVCWithoutPad) {
+        if ( ! Allele.oneIsPrefixOfOther(ref, alt) )
+            return false; // we require one allele be a prefix of another
+
+        if ( ref.length() > alt.length() ) { // we are a deletion
+            return basesAreRepeated(ref.getBaseString(), alt.getBaseString(), refBasesStartingAtVCWithoutPad, 2);
+        } else { // we are an insertion
+            return basesAreRepeated(alt.getBaseString(), ref.getBaseString(), refBasesStartingAtVCWithoutPad, 1);
+        }
+    }
+
+    protected static boolean basesAreRepeated(final String l, final String s, final String ref, final int minNumberOfMatches) {
+        final String potentialRepeat = l.substring(s.length()); // skip s bases
+
+        for ( int i = 0; i < minNumberOfMatches; i++) {
+            final int start = i * potentialRepeat.length();
+            final int end = (i+1) * potentialRepeat.length();
+            if ( ref.length() < end )
+                return false; // we ran out of bases to test
+            final String refSub = ref.substring(start, end);
+            if ( ! refSub.equals(potentialRepeat) )
+                return false; // repeat didn't match, fail
+        }
+
+        return true; // we passed all tests, we matched
+    }
+
+    public enum GenotypeAssignmentMethod {
+        /**
+         * set all of the genotype GT values to NO_CALL
+         */
+        SET_TO_NO_CALL,
+
+        /**
+         * Use the subsetted PLs to greedily assigned genotypes
+         */
+        USE_PLS_TO_ASSIGN,
+
+        /**
+         * Try to match the original GT calls, if at all possible
+         *
+         * Suppose I have 3 alleles: A/B/C and the following samples:
+         *
+         *       original_GT best_match to A/B best_match to A/C
+         * S1 => A/A A/A A/A
+         * S2 => A/B A/B A/A
+         * S3 => B/B B/B A/A
+         * S4 => B/C A/B A/C
+         * S5 => C/C A/A C/C
+         *
+         * Basically, all alleles not in the subset map to ref.  It means that het-alt genotypes
+         * when split into 2 bi-allelic variants will be het in each, which is good in some cases,
+         * rather than the undetermined behavior when using the PLs to assign, which could result
+         * in hom-var or hom-ref for each, depending on the exact PL values.
+         */
+        BEST_MATCH_TO_ORIGINAL,
+
+        /**
+         * do not even bother changing the GTs
+         */
+        DO_NOT_ASSIGN_GENOTYPES
+    }
+
+    /**
+     * subset the Variant Context to the specific set of alleles passed in (pruning the PLs appropriately)
+     *
+     * @param vc                 variant context with genotype likelihoods
+     * @param allelesToUse       which alleles from the vc are okay to use; *** must be in the same relative order as those in the original VC ***
+     * @param assignGenotypes    assignment strategy for the (subsetted) PLs
+     * @return a new non-null GenotypesContext
+     */
+    public static GenotypesContext subsetDiploidAlleles(final VariantContext vc,
+                                                        final List<Allele> allelesToUse,
+                                                        final GenotypeAssignmentMethod assignGenotypes) {
+        if ( allelesToUse.get(0).isNonReference() ) throw new IllegalArgumentException("First allele must be the reference allele");
+        if ( allelesToUse.size() == 1 ) throw new IllegalArgumentException("Cannot subset to only 1 alt allele");
+
+        // optimization: if no input genotypes, just exit
+        if (vc.getGenotypes().isEmpty()) return GenotypesContext.create();
+
+        // we need to determine which of the alternate alleles (and hence the likelihoods) to use and carry forward
+        final List<Integer> likelihoodIndexesToUse = determineLikelihoodIndexesToUse(vc, allelesToUse);
+
+        // create the new genotypes
+        return createGenotypesWithSubsettedLikelihoods(vc.getGenotypes(), vc, allelesToUse, likelihoodIndexesToUse, assignGenotypes);
+    }
+
+    /**
+     * Figure out which likelihood indexes to use for a selected down set of alleles
+     *
+     * @param originalVC        the original VariantContext
+     * @param allelesToUse      the subset of alleles to use
+     * @return a list of PL indexes to use or null if none
+     */
+    private static List<Integer> determineLikelihoodIndexesToUse(final VariantContext originalVC, final List<Allele> allelesToUse) {
+
+        // the bitset representing the allele indexes we want to keep
+        final boolean[] alleleIndexesToUse = getAlleleIndexBitset(originalVC, allelesToUse);
+
+        // an optimization: if we are supposed to use all (or none in the case of a ref call) of the alleles,
+        // then we can keep the PLs as is; otherwise, we determine which ones to keep
+        if ( MathUtils.countOccurrences(true, alleleIndexesToUse) == alleleIndexesToUse.length )
+            return null;
+
+        return getLikelihoodIndexes(originalVC, alleleIndexesToUse);
+    }
+
+    /**
+     * Get the actual likelihoods indexes to use given the corresponding allele indexes
+     *
+     * @param originalVC           the original VariantContext
+     * @param alleleIndexesToUse   the bitset representing the alleles to use (@see #getAlleleIndexBitset)
+     * @return a non-null List
+     */
+    private static List<Integer> getLikelihoodIndexes(final VariantContext originalVC, final boolean[] alleleIndexesToUse) {
+
+        final List<Integer> result = new ArrayList<>(30);
+
+        // numLikelihoods takes total # of alleles. Use default # of chromosomes (ploidy) = 2
+        final int numLikelihoods = GenotypeLikelihoods.numLikelihoods(originalVC.getNAlleles(), DEFAULT_PLOIDY);
+
+        for ( int PLindex = 0; PLindex < numLikelihoods; PLindex++ ) {
+            final GenotypeLikelihoods.GenotypeLikelihoodsAllelePair alleles = GenotypeLikelihoods.getAllelePair(PLindex);
+            // consider this entry only if both of the alleles are good
+            if ( alleleIndexesToUse[alleles.alleleIndex1] && alleleIndexesToUse[alleles.alleleIndex2] )
+                result.add(PLindex);
+        }
+
+        return result;
+    }
+
+    /**
+     * Given an original VariantContext and a list of alleles from that VC to keep,
+     * returns a bitset representing which allele indexes should be kept
+     *
+     * @param originalVC      the original VC
+     * @param allelesToKeep   the list of alleles to keep
+     * @return non-null bitset
+     */
+    private static boolean[] getAlleleIndexBitset(final VariantContext originalVC, final List<Allele> allelesToKeep) {
+        final int numOriginalAltAlleles = originalVC.getNAlleles() - 1;
+        final boolean[] alleleIndexesToKeep = new boolean[numOriginalAltAlleles + 1];
+
+        // the reference Allele is definitely still used
+        alleleIndexesToKeep[0] = true;
+        for ( int i = 0; i < numOriginalAltAlleles; i++ ) {
+            if ( allelesToKeep.contains(originalVC.getAlternateAllele(i)) )
+                alleleIndexesToKeep[i+1] = true;
+        }
+
+        return alleleIndexesToKeep;
+    }
+
+    /**
+     * Create the new GenotypesContext with the subsetted PLs and ADs
+     *
+     * @param originalGs               the original GenotypesContext
+     * @param vc                       the original VariantContext
+     * @param allelesToUse             the actual alleles to use with the new Genotypes
+     * @param likelihoodIndexesToUse   the indexes in the PL to use given the allelesToUse (@see #determineLikelihoodIndexesToUse())
+     * @param assignGenotypes          assignment strategy for the (subsetted) PLs
+     * @return a new non-null GenotypesContext
+     */
+    private static GenotypesContext createGenotypesWithSubsettedLikelihoods(final GenotypesContext originalGs,
+                                                                            final VariantContext vc,
+                                                                            final List<Allele> allelesToUse,
+                                                                            final List<Integer> likelihoodIndexesToUse,
+                                                                            final GenotypeAssignmentMethod assignGenotypes) {
+        // the new genotypes to create
+        final GenotypesContext newGTs = GenotypesContext.create(originalGs.size());
+
+        // make sure we are seeing the expected number of likelihoods per sample
+        final int expectedNumLikelihoods = GenotypeLikelihoods.numLikelihoods(vc.getNAlleles(), 2);
+
+        // the samples
+        final List<String> sampleIndices = originalGs.getSampleNamesOrderedByName();
+
+        // create the new genotypes
+        for ( int k = 0; k < originalGs.size(); k++ ) {
+            final Genotype g = originalGs.get(sampleIndices.get(k));
+            final GenotypeBuilder gb = new GenotypeBuilder(g);
+
+            // create the new likelihoods array from the alleles we are allowed to use
+            double[] newLikelihoods;
+            if ( !g.hasLikelihoods() ) {
+                // we don't have any likelihoods, so we null out PLs and make G ./.
+                newLikelihoods = null;
+                gb.noPL();
+            } else {
+                final double[] originalLikelihoods = g.getLikelihoods().getAsVector();
+                if ( likelihoodIndexesToUse == null ) {
+                    newLikelihoods = originalLikelihoods;
+                } else if ( originalLikelihoods.length != expectedNumLikelihoods ) {
+                    logger.debug("Wrong number of likelihoods in sample " + g.getSampleName() + " at " + vc + " got " + g.getLikelihoodsString() + " but expected " + expectedNumLikelihoods);
+                    newLikelihoods = null;
+                } else {
+                    newLikelihoods = new double[likelihoodIndexesToUse.size()];
+                    int newIndex = 0;
+                    for ( final int oldIndex : likelihoodIndexesToUse )
+                        newLikelihoods[newIndex++] = originalLikelihoods[oldIndex];
+
+                    // might need to re-normalize
+                    newLikelihoods = MathUtils.normalizeFromLog10(newLikelihoods, false, true);
+                }
+
+                if ( newLikelihoods == null || likelihoodsAreUninformative(newLikelihoods) )
+                    gb.noPL();
+                else
+                    gb.PL(newLikelihoods);
+            }
+
+            updateGenotypeAfterSubsetting(g.getAlleles(), gb, assignGenotypes, newLikelihoods, allelesToUse);
+            newGTs.add(gb.make());
+        }
+
+        return fixADFromSubsettedAlleles(newGTs, vc, allelesToUse);
+    }
+
+    private static boolean likelihoodsAreUninformative(final double[] likelihoods) {
+        return MathUtils.sum(likelihoods) > SUM_GL_THRESH_NOCALL;
+    }
+
+    /**
+     * Add the genotype call (GT) field to GenotypeBuilder using the requested algorithm assignmentMethod
+     *
+     * @param originalGT the original genotype calls, cannot be null
+     * @param gb the builder where we should put our newly called alleles, cannot be null
+     * @param assignmentMethod the method to use to do the assignment, cannot be null
+     * @param newLikelihoods a vector of likelihoods to use if the method requires PLs, should be log10 likelihoods, cannot be null
+     * @param allelesToUse the alleles we are using for our subsetting
+     */
+    public static void updateGenotypeAfterSubsetting(final List<Allele> originalGT,
+                                                     final GenotypeBuilder gb,
+                                                     final GenotypeAssignmentMethod assignmentMethod,
+                                                     final double[] newLikelihoods,
+                                                     final List<Allele> allelesToUse) {
+        switch ( assignmentMethod ) {
+            case DO_NOT_ASSIGN_GENOTYPES:
+                break;
+            case SET_TO_NO_CALL:
+                gb.alleles(NO_CALL_ALLELES);
+                gb.noGQ();
+                break;
+            case USE_PLS_TO_ASSIGN:
+                if ( newLikelihoods == null || likelihoodsAreUninformative(newLikelihoods) ) {
+                    // if there is no mass on the (new) likelihoods, then just no-call the sample
+                    gb.alleles(NO_CALL_ALLELES);
+                    gb.noGQ();
+                } else {
+                    // find the genotype with maximum likelihoods
+                    final int PLindex = MathUtils.maxElementIndex(newLikelihoods);
+                    GenotypeLikelihoods.GenotypeLikelihoodsAllelePair alleles = GenotypeLikelihoods.getAllelePair(PLindex);
+                    gb.alleles(Arrays.asList(allelesToUse.get(alleles.alleleIndex1), allelesToUse.get(alleles.alleleIndex2)));
+                    gb.log10PError(GenotypeLikelihoods.getGQLog10FromLikelihoods(PLindex, newLikelihoods));
+                }
+                break;
+            case BEST_MATCH_TO_ORIGINAL:
+                final List<Allele> best = new LinkedList<>();
+                final Allele ref = allelesToUse.get(0); // WARNING -- should be checked in input argument
+                for ( final Allele originalAllele : originalGT ) {
+                    best.add(allelesToUse.contains(originalAllele) ? originalAllele : ref);
+                }
+                gb.noGQ();
+                gb.noPL();
+                gb.alleles(best);
+                break;
+        }
+    }
+
+    /**
+     * Subset the samples in VC to reference only information with ref call alleles
+     *
+     * Preserves DP if present
+     *
+     * @param vc the variant context to subset down to
+     * @param ploidy ploidy to use if a genotype doesn't have any alleles
+     * @return a GenotypesContext
+     */
+    public static GenotypesContext subsetToRefOnly(final VariantContext vc, final int ploidy) {
+        if ( vc == null ) throw new IllegalArgumentException("vc cannot be null");
+        if ( ploidy < 1 ) throw new IllegalArgumentException("ploidy must be >= 1 but got " + ploidy);
+
+        // the genotypes with PLs
+        final GenotypesContext oldGTs = vc.getGenotypes();
+
+        // optimization: if no input genotypes, just exit
+        if (oldGTs.isEmpty()) return oldGTs;
+
+        // the new genotypes to create
+        final GenotypesContext newGTs = GenotypesContext.create(oldGTs.size());
+
+        final Allele ref = vc.getReference();
+        final List<Allele> diploidRefAlleles = Arrays.asList(ref, ref);
+
+        // create the new genotypes
+        for ( final Genotype g : vc.getGenotypes() ) {
+            final int gPloidy = g.getPloidy() == 0 ? ploidy : g.getPloidy();
+            final List<Allele> refAlleles = gPloidy == 2 ? diploidRefAlleles : Collections.nCopies(gPloidy, ref);
+            final GenotypeBuilder gb = new GenotypeBuilder(g.getSampleName(), refAlleles);
+            if ( g.hasDP() ) gb.DP(g.getDP());
+            if ( g.hasGQ() ) gb.GQ(g.getGQ());
+            newGTs.add(gb.make());
+        }
+
+        return newGTs;
+    }
+
+    /**
+     * Assign genotypes (GTs) to the samples in the Variant Context greedily based on the PLs
+     *
+     * @param vc            variant context with genotype likelihoods
+     * @return genotypes context
+     */
+    public static GenotypesContext assignDiploidGenotypes(final VariantContext vc) {
+        return subsetDiploidAlleles(vc, vc.getAlleles(), GenotypeAssignmentMethod.USE_PLS_TO_ASSIGN);
+    }
+
+    /**
+     * Split variant context into its biallelic components if there are more than 2 alleles
+     *
+     * For VC has A/B/C alleles, returns A/B and A/C contexts.
+     * Genotypes are all no-calls now (it's not possible to fix them easily)
+     * Alleles are right trimmed to satisfy VCF conventions
+     *
+     * If vc is biallelic or non-variant it is just returned
+     *
+     * Chromosome counts are updated (but they are by definition 0)
+     *
+     * @param vc a potentially multi-allelic variant context
+     * @return a list of bi-allelic (or monomorphic) variant context
+     */
+    public static List<VariantContext> splitVariantContextToBiallelics(final VariantContext vc) {
+        return splitVariantContextToBiallelics(vc, false, GenotypeAssignmentMethod.SET_TO_NO_CALL);
+    }
+
+    /**
+     * Split variant context into its biallelic components if there are more than 2 alleles
+     *
+     * For VC has A/B/C alleles, returns A/B and A/C contexts.
+     * Genotypes are all no-calls now (it's not possible to fix them easily)
+     * Alleles are right trimmed to satisfy VCF conventions
+     *
+     * If vc is biallelic or non-variant it is just returned
+     *
+     * Chromosome counts are updated (but they are by definition 0)
+     *
+     * @param vc a potentially multi-allelic variant context
+     * @param trimLeft if true, we will also left trim alleles, potentially moving the resulting vcs forward on the genome
+     * @return a list of bi-allelic (or monomorphic) variant context
+     */
+    public static List<VariantContext> splitVariantContextToBiallelics(final VariantContext vc, final boolean trimLeft, final GenotypeAssignmentMethod genotypeAssignmentMethod) {
+        if ( ! vc.isVariant() || vc.isBiallelic() )
+            // non variant or biallelics already satisfy the contract
+            return Collections.singletonList(vc);
+        else {
+            final List<VariantContext> biallelics = new LinkedList<>();
+
+            for ( final Allele alt : vc.getAlternateAlleles() ) {
+                VariantContextBuilder builder = new VariantContextBuilder(vc);
+                final List<Allele> alleles = Arrays.asList(vc.getReference(), alt);
+                builder.alleles(alleles);
+                builder.genotypes(subsetDiploidAlleles(vc, alleles, genotypeAssignmentMethod));
+                VariantContextUtils.calculateChromosomeCounts(builder, true);
+                final VariantContext trimmed = trimAlleles(builder.make(), trimLeft, true);
+                biallelics.add(trimmed);
+            }
+
+            return biallelics;
+        }
+    }
+
+    public static Genotype removePLsAndAD(final Genotype g) {
+        return ( g.hasLikelihoods() || g.hasAD() ) ? new GenotypeBuilder(g).noPL().noAD().make() : g;
+    }
+
+    //TODO consider refactor variant-context merging code so that we share as much as possible between
+    //TODO simpleMerge and referenceConfidenceMerge
+    //TODO likely using a separate helper class or hierarchy.
+    /**
+     * Merges VariantContexts into a single hybrid.  Takes genotypes for common samples in priority order, if provided.
+     * If uniquifySamples is true, the priority order is ignored and names are created by concatenating the VC name with
+     * the sample name
+     *
+     * @param unsortedVCs               collection of unsorted VCs
+     * @param priorityListOfVCs         priority list detailing the order in which we should grab the VCs
+     * @param filteredRecordMergeType   merge type for filtered records
+     * @param genotypeMergeOptions      merge option for genotypes
+     * @param annotateOrigin            should we annotate the set it came from?
+     * @param printMessages             should we print messages?
+     * @param setKey                    the key name of the set
+     * @param filteredAreUncalled       are filtered records uncalled?
+     * @param mergeInfoWithMaxAC        should we merge in info from the VC with maximum allele count?
+     * @return new VariantContext       representing the merge of unsortedVCs
+     */
+    public static VariantContext simpleMerge(final Collection<VariantContext> unsortedVCs,
+                                             final List<String> priorityListOfVCs,
+                                             final FilteredRecordMergeType filteredRecordMergeType,
+                                             final GenotypeMergeType genotypeMergeOptions,
+                                             final boolean annotateOrigin,
+                                             final boolean printMessages,
+                                             final String setKey,
+                                             final boolean filteredAreUncalled,
+                                             final boolean mergeInfoWithMaxAC ) {
+        int originalNumOfVCs = priorityListOfVCs == null ? 0 : priorityListOfVCs.size();
+        return simpleMerge(unsortedVCs, priorityListOfVCs, originalNumOfVCs, filteredRecordMergeType, genotypeMergeOptions, annotateOrigin, printMessages, setKey, filteredAreUncalled, mergeInfoWithMaxAC);
+    }
+
+    /**
+     * Merges VariantContexts into a single hybrid.  Takes genotypes for common samples in priority order, if provided.
+     * If uniquifySamples is true, the priority order is ignored and names are created by concatenating the VC name with
+     * the sample name.
+     * simpleMerge does not verify any more unique sample names EVEN if genotypeMergeOptions == GenotypeMergeType.REQUIRE_UNIQUE. One should use
+     * SampleUtils.verifyUniqueSamplesNames to check that before using simpleMerge.
+     *
+     * For more information on this method see: http://www.thedistractionnetwork.com/programmer-problem/
+     *
+     * @param unsortedVCs               collection of unsorted VCs
+     * @param priorityListOfVCs         priority list detailing the order in which we should grab the VCs
+     * @param filteredRecordMergeType   merge type for filtered records
+     * @param genotypeMergeOptions      merge option for genotypes
+     * @param annotateOrigin            should we annotate the set it came from?
+     * @param printMessages             should we print messages?
+     * @param setKey                    the key name of the set
+     * @param filteredAreUncalled       are filtered records uncalled?
+     * @param mergeInfoWithMaxAC        should we merge in info from the VC with maximum allele count?
+     * @return new VariantContext       representing the merge of unsortedVCs
+     */
+    public static VariantContext simpleMerge(final Collection<VariantContext> unsortedVCs,
+                                             final List<String> priorityListOfVCs,
+                                             final int originalNumOfVCs,
+                                             final FilteredRecordMergeType filteredRecordMergeType,
+                                             final GenotypeMergeType genotypeMergeOptions,
+                                             final boolean annotateOrigin,
+                                             final boolean printMessages,
+                                             final String setKey,
+                                             final boolean filteredAreUncalled,
+                                             final boolean mergeInfoWithMaxAC ) {
+        if ( unsortedVCs == null || unsortedVCs.size() == 0 )
+            return null;
+
+        if (priorityListOfVCs != null && originalNumOfVCs != priorityListOfVCs.size())
+            throw new IllegalArgumentException("the number of the original VariantContexts must be the same as the number of VariantContexts in the priority list");
+
+        if ( annotateOrigin && priorityListOfVCs == null && originalNumOfVCs == 0)
+            throw new IllegalArgumentException("Cannot merge calls and annotate their origins without a complete priority list of VariantContexts or the number of original VariantContexts");
+
+        final List<VariantContext> preFilteredVCs = sortVariantContextsByPriority(unsortedVCs, priorityListOfVCs, genotypeMergeOptions);
+        // Make sure all variant contexts are padded with reference base in case of indels if necessary
+        List<VariantContext> VCs = new ArrayList<>();
+
+        for (final VariantContext vc : preFilteredVCs) {
+            if ( ! filteredAreUncalled || vc.isNotFiltered() )
+                VCs.add(vc);
+        }
+
+        if ( VCs.size() == 0 ) // everything is filtered out and we're filteredAreUncalled
+            return null;
+
+        // establish the baseline info from the first VC
+        final VariantContext first = VCs.get(0);
+        final String name = first.getSource();
+        final Allele refAllele = determineReferenceAllele(VCs);
+
+        final LinkedHashSet<Allele> alleles = new LinkedHashSet<>();
+        final Set<String> filters = new HashSet<>();
+        final Map<String, Object> attributes = new LinkedHashMap<>();
+        final Set<String> inconsistentAttributes = new HashSet<>();
+        final Set<String> variantSources = new HashSet<>(); // contains the set of sources we found in our set of VCs that are variant
+        final Set<String> rsIDs = new LinkedHashSet<>(1); // most of the time there's one id
+
+        VariantContext longestVC = first;
+        int depth = 0;
+        int maxAC = -1;
+        final Map<String, Object> attributesWithMaxAC = new LinkedHashMap<>();
+        double log10PError = CommonInfo.NO_LOG10_PERROR;
+        boolean anyVCHadFiltersApplied = false;
+        VariantContext vcWithMaxAC = null;
+        GenotypesContext genotypes = GenotypesContext.create();
+
+        // counting the number of filtered and variant VCs
+        int nFiltered = 0;
+
+        boolean remapped = false;
+
+        // cycle through and add info from the other VCs, making sure the loc/reference matches
+        for ( final VariantContext vc : VCs ) {
+            if ( longestVC.getStart() != vc.getStart() )
+                throw new IllegalStateException("BUG: attempting to merge VariantContexts with different start sites: first="+ first.toString() + " second=" + vc.toString());
+
+            if ( VariantContextUtils.getSize(vc) > VariantContextUtils.getSize(longestVC) )
+                longestVC = vc; // get the longest location
+
+            nFiltered += vc.isFiltered() ? 1 : 0;
+            if ( vc.isVariant() ) variantSources.add(vc.getSource());
+
+            AlleleMapper alleleMapping = resolveIncompatibleAlleles(refAllele, vc, alleles);
+            remapped = remapped || alleleMapping.needsRemapping();
+
+            alleles.addAll(alleleMapping.values());
+
+            mergeGenotypes(genotypes, vc, alleleMapping, genotypeMergeOptions == GenotypeMergeType.UNIQUIFY);
+
+            // We always take the QUAL of the first VC with a non-MISSING qual for the combined value
+            if ( log10PError == CommonInfo.NO_LOG10_PERROR )
+                log10PError =  vc.getLog10PError();
+
+            filters.addAll(vc.getFilters());
+            anyVCHadFiltersApplied |= vc.filtersWereApplied();
+
+            //
+            // add attributes
+            //
+            // special case DP (add it up) and ID (just preserve it)
+            //
+            if (vc.hasAttribute(VCFConstants.DEPTH_KEY))
+                depth += vc.getAttributeAsInt(VCFConstants.DEPTH_KEY, 0);
+            if ( vc.hasID() ) rsIDs.add(vc.getID());
+            if (mergeInfoWithMaxAC && vc.hasAttribute(VCFConstants.ALLELE_COUNT_KEY)) {
+                String rawAlleleCounts = vc.getAttributeAsString(VCFConstants.ALLELE_COUNT_KEY, null);
+                // lets see if the string contains a "," separator
+                if (rawAlleleCounts.contains(VCFConstants.INFO_FIELD_ARRAY_SEPARATOR)) {
+                    final List<String> alleleCountArray = Arrays.asList(rawAlleleCounts.substring(1, rawAlleleCounts.length() - 1).split(VCFConstants.INFO_FIELD_ARRAY_SEPARATOR));
+                    for (final String alleleCount : alleleCountArray) {
+                        final int ac = Integer.valueOf(alleleCount.trim());
+                        if (ac > maxAC) {
+                            maxAC = ac;
+                            vcWithMaxAC = vc;
+                        }
+                    }
+                } else {
+                    final int ac = Integer.valueOf(rawAlleleCounts);
+                    if (ac > maxAC) {
+                        maxAC = ac;
+                        vcWithMaxAC = vc;
+                    }
+                }
+            }
+
+            for (final Map.Entry<String, Object> p : vc.getAttributes().entrySet()) {
+                final String key = p.getKey();
+                final Object value = p.getValue();
+                // only output annotations that have the same value in every input VC
+                // if we don't like the key already, don't go anywhere
+                if ( ! inconsistentAttributes.contains(key) ) {
+                    final boolean alreadyFound = attributes.containsKey(key);
+                    final Object boundValue = attributes.get(key);
+                    final boolean boundIsMissingValue = alreadyFound && boundValue.equals(VCFConstants.MISSING_VALUE_v4);
+
+                    if ( alreadyFound && ! boundValue.equals(value) && ! boundIsMissingValue ) {
+                        // we found the value but we're inconsistent, put it in the exclude list
+                        inconsistentAttributes.add(key);
+                        attributes.remove(key);
+                    } else if ( ! alreadyFound || boundIsMissingValue )  { // no value
+                        attributes.put(key, value);
+                    }
+                }
+            }
+        }
+
+        // if we have more alternate alleles in the merged VC than in one or more of the
+        // original VCs, we need to strip out the GL/PLs (because they are no longer accurate), as well as allele-dependent attributes like AC,AF, and AD
+        for ( final VariantContext vc : VCs ) {
+            if (vc.getAlleles().size() == 1)
+                continue;
+            if ( hasPLIncompatibleAlleles(alleles, vc.getAlleles())) {
+                if ( ! genotypes.isEmpty() ) {
+                    logger.debug(String.format("Stripping PLs at %s:%d-%d due to incompatible alleles merged=%s vs. single=%s",
+                            vc.getChr(), vc.getStart(), vc.getEnd(), alleles, vc.getAlleles()));
+                }
+                genotypes = stripPLsAndAD(genotypes);
+                // this will remove stale AC,AF attributed from vc
+                VariantContextUtils.calculateChromosomeCounts(vc, attributes, true);
+                break;
+            }
+        }
+
+        // take the VC with the maxAC and pull the attributes into a modifiable map
+        if ( mergeInfoWithMaxAC && vcWithMaxAC != null ) {
+            attributesWithMaxAC.putAll(vcWithMaxAC.getAttributes());
+        }
+
+        // if at least one record was unfiltered and we want a union, clear all of the filters
+        if ( (filteredRecordMergeType == FilteredRecordMergeType.KEEP_IF_ANY_UNFILTERED && nFiltered != VCs.size()) || filteredRecordMergeType == FilteredRecordMergeType.KEEP_UNCONDITIONAL )
+            filters.clear();
+
+
+        if ( annotateOrigin ) { // we care about where the call came from
+            String setValue;
+            if ( nFiltered == 0 && variantSources.size() == originalNumOfVCs ) // nothing was unfiltered
+                setValue = MERGE_INTERSECTION;
+            else if ( nFiltered == VCs.size() )     // everything was filtered out
+                setValue = MERGE_FILTER_IN_ALL;
+            else if ( variantSources.isEmpty() )    // everyone was reference
+                setValue = MERGE_REF_IN_ALL;
+            else {
+                final LinkedHashSet<String> s = new LinkedHashSet<>();
+                for ( final VariantContext vc : VCs )
+                    if ( vc.isVariant() )
+                        s.add( vc.isFiltered() ? MERGE_FILTER_PREFIX + vc.getSource() : vc.getSource() );
+                setValue = Utils.join("-", s);
+            }
+
+            if ( setKey != null ) {
+                attributes.put(setKey, setValue);
+                if( mergeInfoWithMaxAC && vcWithMaxAC != null ) {
+                    attributesWithMaxAC.put(setKey, setValue);
+                }
+            }
+        }
+
+        if ( depth > 0 )
+            attributes.put(VCFConstants.DEPTH_KEY, String.valueOf(depth));
+
+        final String ID = rsIDs.isEmpty() ? VCFConstants.EMPTY_ID_FIELD : Utils.join(",", rsIDs);
+
+        final VariantContextBuilder builder = new VariantContextBuilder().source(name).id(ID);
+        builder.loc(longestVC.getChr(), longestVC.getStart(), longestVC.getEnd());
+        builder.alleles(alleles);
+        builder.genotypes(genotypes);
+        builder.log10PError(log10PError);
+        if ( anyVCHadFiltersApplied ) {
+            builder.filters(filters.isEmpty() ? filters : new TreeSet<>(filters));
+        }
+        builder.attributes(new TreeMap<>(mergeInfoWithMaxAC ? attributesWithMaxAC : attributes));
+
+        // Trim the padded bases of all alleles if necessary
+        final VariantContext merged = builder.make();
+        if ( printMessages && remapped ) System.out.printf("Remapped => %s%n", merged);
+        return merged;
+    }
+
+    //TODO as part of a larger refactoring effort remapAlleles can be merged with createAlleleMapping.
+
+    public static GenotypesContext stripPLsAndAD(final GenotypesContext genotypes) {
+        final GenotypesContext newGs = GenotypesContext.create(genotypes.size());
+
+        for ( final Genotype g : genotypes ) {
+            newGs.add(removePLsAndAD(g));
+        }
+
+        return newGs;
+    }
+
+    /**
+     * Updates the PLs and AD of the Genotypes in the newly selected VariantContext to reflect the fact that some alleles
+     * from the original VariantContext are no longer present.
+     *
+     * @param selectedVC  the selected (new) VariantContext
+     * @param originalVC  the original VariantContext
+     * @return a new non-null GenotypesContext
+     */
+    public static GenotypesContext updatePLsAndAD(final VariantContext selectedVC, final VariantContext originalVC) {
+        final int numNewAlleles = selectedVC.getAlleles().size();
+        final int numOriginalAlleles = originalVC.getAlleles().size();
+
+        // if we have more alternate alleles in the selected VC than in the original VC, then something is wrong
+        if ( numNewAlleles > numOriginalAlleles )
+            throw new IllegalArgumentException("Attempting to fix PLs and AD from what appears to be a *combined* VCF and not a selected one");
+
+        final GenotypesContext oldGs = selectedVC.getGenotypes();
+
+        // if we have the same number of alternate alleles in the selected VC as in the original VC, then we don't need to fix anything
+        if ( numNewAlleles == numOriginalAlleles )
+            return oldGs;
+
+        return fixGenotypesFromSubsettedAlleles(oldGs, originalVC, selectedVC.getAlleles());
+    }
+
+    /**
+     * Fix the PLs and ADs for the GenotypesContext of a VariantContext that has been subset
+     *
+     * @param originalGs       the original GenotypesContext
+     * @param originalVC       the original VariantContext
+     * @param allelesToUse     the new (sub)set of alleles to use
+     * @return a new non-null GenotypesContext
+     */
+    static private GenotypesContext fixGenotypesFromSubsettedAlleles(final GenotypesContext originalGs, final VariantContext originalVC, final List<Allele> allelesToUse) {
+
+        // we need to determine which of the alternate alleles (and hence the likelihoods) to use and carry forward
+        final List<Integer> likelihoodIndexesToUse = determineLikelihoodIndexesToUse(originalVC, allelesToUse);
+
+        // create the new genotypes
+        return createGenotypesWithSubsettedLikelihoods(originalGs, originalVC, allelesToUse, likelihoodIndexesToUse, GenotypeAssignmentMethod.DO_NOT_ASSIGN_GENOTYPES);
+    }
+
+    /**
+     * Fix the AD for the GenotypesContext of a VariantContext that has been subset
+     *
+     * @param originalGs       the original GenotypesContext
+     * @param originalVC       the original VariantContext
+     * @param allelesToUse     the new (sub)set of alleles to use
+     * @return a new non-null GenotypesContext
+     */
+    static private GenotypesContext fixADFromSubsettedAlleles(final GenotypesContext originalGs, final VariantContext originalVC, final List<Allele> allelesToUse) {
+
+        // the bitset representing the allele indexes we want to keep
+        final boolean[] alleleIndexesToUse = getAlleleIndexBitset(originalVC, allelesToUse);
+
+        // the new genotypes to create
+        final GenotypesContext newGTs = GenotypesContext.create(originalGs.size());
+
+        // the samples
+        final List<String> sampleIndices = originalGs.getSampleNamesOrderedByName();
+
+        // create the new genotypes
+        for ( int k = 0; k < originalGs.size(); k++ ) {
+            final Genotype g = originalGs.get(sampleIndices.get(k));
+            newGTs.add(fixAD(g, alleleIndexesToUse, allelesToUse.size()));
+        }
+
+        return newGTs;
+    }
+
+    /**
+     * Fix the AD for the given Genotype
+     *
+     * @param genotype              the original Genotype
+     * @param alleleIndexesToUse    a bitset describing whether or not to keep a given index
+     * @param nAllelesToUse         how many alleles we are keeping
+     * @return a non-null Genotype
+     */
+    private static Genotype fixAD(final Genotype genotype, final boolean[] alleleIndexesToUse, final int nAllelesToUse) {
+        // if it ain't broke don't fix it
+        if ( !genotype.hasAD() )
+            return genotype;
+
+        final GenotypeBuilder builder = new GenotypeBuilder(genotype);
+
+        final int[] oldAD = genotype.getAD();
+        if ( oldAD.length != alleleIndexesToUse.length ) {
+            builder.noAD();
+        } else {
+            final int[] newAD = new int[nAllelesToUse];
+            int currentIndex = 0;
+            for ( int i = 0; i < oldAD.length; i++ ) {
+                if ( alleleIndexesToUse[i] )
+                    newAD[currentIndex++] = oldAD[i];
+            }
+            builder.AD(newAD);
+        }
+        return builder.make();
+    }
+
+    private static Allele determineReferenceAllele(final List<VariantContext> VCs) {
+        return determineReferenceAllele(VCs, null);
+    }
+
+    public static boolean contextMatchesLoc(final VariantContext vc, final GenomeLoc loc) {
+        return loc == null || loc.getStart() == vc.getStart();
+    }
+
+    static private AlleleMapper resolveIncompatibleAlleles(final Allele refAllele, final VariantContext vc, final LinkedHashSet<Allele> allAlleles) {
+        if ( refAllele.equals(vc.getReference()) )
+            return new AlleleMapper(vc);
+        else {
+            final Map<Allele, Allele> map = createAlleleMapping(refAllele, vc, allAlleles);
+            map.put(vc.getReference(), refAllele);
+            return new AlleleMapper(map);
+        }
+    }
+
+    //TODO as part of a larger refactoring effort {@link #createAlleleMapping} can be merged with {@link ReferenceConfidenceVariantContextMerger#remapAlleles}.
+    /**
+     * Create an allele mapping for the given context where its reference allele must (potentially) be extended to the given allele
+     *
+     * The refAllele is the longest reference allele seen at this start site.
+     * So imagine it is:
+     * refAllele: ACGTGA
+     * myRef:     ACGT
+     * myAlt:     A
+     *
+     * We need to remap all of the alleles in vc to include the extra GA so that
+     * myRef => refAllele and myAlt => AGA
+     *
+     * @param refAllele          the new (extended) reference allele
+     * @param oneVC              the Variant Context to extend
+     * @param currentAlleles     the list of alleles already created
+     * @return a non-null mapping of original alleles to new (extended) ones
+     */
+    private static Map<Allele, Allele> createAlleleMapping(final Allele refAllele,
+                                                           final VariantContext oneVC,
+                                                           final Collection<Allele> currentAlleles) {
+        final Allele myRef = oneVC.getReference();
+        if ( refAllele.length() <= myRef.length() ) throw new IllegalStateException("BUG: myRef="+myRef+" is longer than refAllele="+refAllele);
+
+        final byte[] extraBases = Arrays.copyOfRange(refAllele.getBases(), myRef.length(), refAllele.length());
+
+        final Map<Allele, Allele> map = new HashMap<>();
+        for ( final Allele a : oneVC.getAlternateAlleles() ) {
+            if ( isUsableAlternateAllele(a) ) {
+                Allele extended = Allele.extend(a, extraBases);
+                for ( final Allele b : currentAlleles )
+                    if ( extended.equals(b) )
+                        extended = b;
+                map.put(a, extended);
+            }
+        }
+
+        return map;
+    }
+
+    static private boolean isUsableAlternateAllele(final Allele allele) {
+        return ! (allele.isReference() || allele.isSymbolic() );
+    }
+
+    public static List<VariantContext> sortVariantContextsByPriority(Collection<VariantContext> unsortedVCs, List<String> priorityListOfVCs, GenotypeMergeType mergeOption ) {
+        if ( mergeOption == GenotypeMergeType.PRIORITIZE && priorityListOfVCs == null )
+            throw new IllegalArgumentException("Cannot merge calls by priority with a null priority list");
+
+        if ( priorityListOfVCs == null || mergeOption == GenotypeMergeType.UNSORTED )
+            return new ArrayList<>(unsortedVCs);
+        else {
+            ArrayList<VariantContext> sorted = new ArrayList<>(unsortedVCs);
+            Collections.sort(sorted, new CompareByPriority(priorityListOfVCs));
+            return sorted;
+        }
+    }
+
+    private static void mergeGenotypes(GenotypesContext mergedGenotypes, VariantContext oneVC, AlleleMapper alleleMapping, boolean uniquifySamples) {
+        //TODO: should we add a check for cases when the genotypeMergeOption is REQUIRE_UNIQUE
+        for ( final Genotype g : oneVC.getGenotypes() ) {
+            final String name = mergedSampleName(oneVC.getSource(), g.getSampleName(), uniquifySamples);
+            if ( ! mergedGenotypes.containsSample(name) ) {
+                // only add if the name is new
+                Genotype newG = g;
+
+                if ( uniquifySamples || alleleMapping.needsRemapping() ) {
+                    final List<Allele> alleles = alleleMapping.needsRemapping() ? alleleMapping.remap(g.getAlleles()) : g.getAlleles();
+                    newG = new GenotypeBuilder(g).name(name).alleles(alleles).make();
+                }
+
+                mergedGenotypes.add(newG);
+            }
+        }
+    }
+
+    /**
+     * Cached NO_CALL immutable lists where the position ith contains the list with i elements.
+     */
+    private static List<Allele>[] NOCALL_LISTS = new List[] {
+            Collections.emptyList(),
+            Collections.singletonList(Allele.NO_CALL),
+            Collections.nCopies(2,Allele.NO_CALL)
+    };
+
+    /**
+     * Synchronized code to ensure that {@link #NOCALL_LISTS} has enough entries beyod the requested ploidy
+     * @param capacity the requested ploidy.
+     */
+    private static synchronized void ensureNoCallListsCapacity(final int capacity) {
+        final int currentCapacity = NOCALL_LISTS.length - 1;
+        if (currentCapacity >= capacity)
+            return;
+        NOCALL_LISTS = Arrays.copyOf(NOCALL_LISTS,Math.max(capacity,currentCapacity << 1) + 1);
+        for (int i = currentCapacity + 1; i < NOCALL_LISTS.length; i++)
+            NOCALL_LISTS[i] = Collections.nCopies(i,Allele.NO_CALL);
+    }
+
+    /**
+     * Returns a {@link Allele#NO_CALL NO_CALL} allele list provided the ploidy.
+     *
+     * @param ploidy the required ploidy.
+     *
+     * @return never {@code null}, but an empty list if {@code ploidy} is equal or less than 0. The returned list
+     *   might or might not be mutable.
+     */
+    public static List<Allele> noCallAlleles(final int ploidy) {
+        if (NOCALL_LISTS.length <= ploidy)
+            ensureNoCallListsCapacity(ploidy);
+        return NOCALL_LISTS[ploidy];
+    }
+
+
+    /**
+     * This is just a safe wrapper around GenotypeLikelihoods.calculatePLindex()
+     *
+     * @param originalIndex1   the index of the first allele
+     * @param originalIndex2   the index of the second allele
+     * @return the PL index
+     */
+    protected static int calculatePLindexFromUnorderedIndexes(final int originalIndex1, final int originalIndex2) {
+        // we need to make sure they are ordered correctly
+        return ( originalIndex2 < originalIndex1 ) ? GenotypeLikelihoods.calculatePLindex(originalIndex2, originalIndex1) : GenotypeLikelihoods.calculatePLindex(originalIndex1, originalIndex2);
+    }
+
+    public static String mergedSampleName(String trackName, String sampleName, boolean uniquify ) {
+        return uniquify ? sampleName + "." + trackName : sampleName;
+    }
+
+    /**
+     * Trim the alleles in inputVC from the reverse direction
+     *
+     * @param inputVC a non-null input VC whose alleles might need a haircut
+     * @return a non-null VariantContext (may be == to inputVC) with alleles trimmed up
+     */
+    public static VariantContext reverseTrimAlleles( final VariantContext inputVC ) {
+        return trimAlleles(inputVC, false, true);
+    }
+
+    /**
+     * Trim the alleles in inputVC from the forward direction
+     *
+     * @param inputVC a non-null input VC whose alleles might need a haircut
+     * @return a non-null VariantContext (may be == to inputVC) with alleles trimmed up
+     */
+    public static VariantContext forwardTrimAlleles( final VariantContext inputVC ) {
+        return trimAlleles(inputVC, true, false);
+    }
+
+    /**
+     * Trim the alleles in inputVC forward and reverse, as requested
+     *
+     * @param inputVC a non-null input VC whose alleles might need a haircut
+     * @param trimForward should we trim up the alleles from the forward direction?
+     * @param trimReverse should we trim up the alleles from the reverse direction?
+     * @return a non-null VariantContext (may be == to inputVC) with trimmed up alleles
+     */
+    @Ensures("result != null")
+    public static VariantContext trimAlleles(final VariantContext inputVC, final boolean trimForward, final boolean trimReverse) {
+        if ( inputVC == null ) throw new IllegalArgumentException("inputVC cannot be null");
+
+        if ( inputVC.getNAlleles() <= 1 || inputVC.isSNP() )
+            return inputVC;
+
+        // see whether we need to trim common reference base from all alleles
+        final int revTrim = trimReverse ? computeReverseClipping(inputVC.getAlleles(), inputVC.getReference().getDisplayString().getBytes()) : 0;
+        final VariantContext revTrimVC = trimAlleles(inputVC, -1, revTrim);
+        final int fwdTrim = trimForward ? computeForwardClipping(revTrimVC.getAlleles()) : -1;
+        final VariantContext vc= trimAlleles(revTrimVC, fwdTrim, 0);
+        return vc;
+    }
+
+    /**
+     * Trim up alleles in inputVC, cutting out all bases up to fwdTrimEnd inclusive and
+     * the last revTrim bases from the end
+     *
+     * @param inputVC a non-null input VC
+     * @param fwdTrimEnd bases up to this index (can be -1) will be removed from the start of all alleles
+     * @param revTrim the last revTrim bases of each allele will be clipped off as well
+     * @return a non-null VariantContext (may be == to inputVC) with trimmed up alleles
+     */
+    @Requires({"inputVC != null"})
+    @Ensures("result != null")
+    protected static VariantContext trimAlleles(final VariantContext inputVC,
+                                                final int fwdTrimEnd,
+                                                final int revTrim) {
+        if( fwdTrimEnd == -1 && revTrim == 0 ) // nothing to do, so just return inputVC unmodified
+            return inputVC;
+
+        final List<Allele> alleles = new LinkedList<>();
+        final Map<Allele, Allele> originalToTrimmedAlleleMap = new HashMap<>();
+
+        for (final Allele a : inputVC.getAlleles()) {
+            if (a.isSymbolic()) {
+                alleles.add(a);
+                originalToTrimmedAlleleMap.put(a, a);
+            } else {
+                // get bases for current allele and create a new one with trimmed bases
+                final byte[] newBases = Arrays.copyOfRange(a.getBases(), fwdTrimEnd+1, a.length()-revTrim);
+                final Allele trimmedAllele = Allele.create(newBases, a.isReference());
+                alleles.add(trimmedAllele);
+                originalToTrimmedAlleleMap.put(a, trimmedAllele);
+            }
+        }
+
+        // now we can recreate new genotypes with trimmed alleles
+        final AlleleMapper alleleMapper = new AlleleMapper(originalToTrimmedAlleleMap);
+        final GenotypesContext genotypes = updateGenotypesWithMappedAlleles(inputVC.getGenotypes(), alleleMapper);
+
+        final int start = inputVC.getStart() + (fwdTrimEnd + 1);
+        final VariantContextBuilder builder = new VariantContextBuilder(inputVC);
+        builder.start(start);
+        builder.stop(start + alleles.get(0).length() - 1);
+        builder.alleles(alleles);
+        builder.genotypes(genotypes);
+        return builder.make();
+    }
+
+    @Requires("originalGenotypes != null && alleleMapper != null")
+    protected static GenotypesContext updateGenotypesWithMappedAlleles(final GenotypesContext originalGenotypes, final AlleleMapper alleleMapper) {
+        final GenotypesContext updatedGenotypes = GenotypesContext.create(originalGenotypes.size());
+
+        for ( final Genotype genotype : originalGenotypes ) {
+            final List<Allele> updatedAlleles = alleleMapper.remap(genotype.getAlleles());
+            updatedGenotypes.add(new GenotypeBuilder(genotype).alleles(updatedAlleles).make());
+        }
+
+        return updatedGenotypes;
+    }
+
+    public static int computeReverseClipping(final List<Allele> unclippedAlleles, final byte[] ref) {
+        int clipping = 0;
+        boolean stillClipping = true;
+
+        while ( stillClipping ) {
+            for ( final Allele a : unclippedAlleles ) {
+                if ( a.isSymbolic() )
+                    continue;
+
+                // we need to ensure that we don't reverse clip out all of the bases from an allele because we then will have the wrong
+                // position set for the VariantContext (although it's okay to forward clip it all out, because the position will be fine).
+                if ( a.length() - clipping == 0 )
+                    return clipping - 1;
+
+                if ( a.length() - clipping <= 0 || a.length() == 0 ) {
+                    stillClipping = false;
+                }
+                else if ( ref.length == clipping ) {
+                    return -1;
+                }
+                else if ( a.getBases()[a.length()-clipping-1] != ref[ref.length-clipping-1] ) {
+                    stillClipping = false;
+                }
+            }
+            if ( stillClipping )
+                clipping++;
+        }
+
+        return clipping;
+    }
+
+    /**
+     * Clip out any unnecessary bases off the front of the alleles
+     *
+     * The VCF spec represents alleles as block substitutions, replacing AC with A for a
+     * 1 bp deletion of the C.  However, it's possible that we'd end up with alleles that
+     * contain extra bases on the left, such as GAC/GA to represent the same 1 bp deletion.
+     * This routine finds an offset among all alleles that can be safely trimmed
+     * off the left of each allele and still represent the same block substitution.
+     *
+     * A/C => A/C
+     * AC/A => AC/A
+     * ACC/AC => CC/C
+     * AGT/CAT => AGT/CAT
+     * <DEL>/C => <DEL>/C
+     *
+     * @param unclippedAlleles a non-null list of alleles that we want to clip
+     * @return the offset into the alleles where we can safely clip, inclusive, or
+     *   -1 if no clipping is tolerated.  So, if the result is 0, then we can remove
+     *   the first base of every allele.  If the result is 1, we can remove the
+     *   second base.
+     */
+    public static int computeForwardClipping(final List<Allele> unclippedAlleles) {
+        // cannot clip unless there's at least 1 alt allele
+        if ( unclippedAlleles.size() <= 1 )
+            return -1;
+
+        // we cannot forward clip any set of alleles containing a symbolic allele
+        int minAlleleLength = Integer.MAX_VALUE;
+        for ( final Allele a : unclippedAlleles ) {
+            if ( a.isSymbolic() )
+                return -1;
+            minAlleleLength = Math.min(minAlleleLength, a.length());
+        }
+
+        final byte[] firstAlleleBases = unclippedAlleles.get(0).getBases();
+        int indexOflastSharedBase = -1;
+
+        // the -1 to the stop is that we can never clip off the right most base
+        for ( int i = 0; i < minAlleleLength - 1; i++) {
+            final byte base = firstAlleleBases[i];
+
+            for ( final Allele allele : unclippedAlleles ) {
+                if ( allele.getBases()[i] != base )
+                    return indexOflastSharedBase;
+            }
+
+            indexOflastSharedBase = i;
+        }
+
+        return indexOflastSharedBase;
+    }
+
+    public static double computeHardyWeinbergPvalue(VariantContext vc) {
+        if ( vc.getCalledChrCount() == 0 )
+            return 0.0;
+        return HardyWeinbergCalculation.hwCalculate(vc.getHomRefCount(), vc.getHetCount(), vc.getHomVarCount());
+    }
+
+    public static boolean requiresPaddingBase(final List<String> alleles) {
+
+        // see whether one of the alleles would be null if trimmed through
+
+        for ( final String allele : alleles ) {
+            if ( allele.isEmpty() )
+                return true;
+        }
+
+        int clipping = 0;
+        Character currentBase = null;
+
+        while ( true ) {
+            for ( final String allele : alleles ) {
+                if ( allele.length() - clipping == 0 )
+                    return true;
+
+                char myBase = allele.charAt(clipping);
+                if ( currentBase == null )
+                    currentBase = myBase;
+                else if ( currentBase != myBase )
+                    return false;
+            }
+
+            clipping++;
+            currentBase = null;
+        }
+    }
+
+    private final static Map<String, Object> subsetAttributes(final CommonInfo igc, final Collection<String> keysToPreserve) {
+        Map<String, Object> attributes = new HashMap<>(keysToPreserve.size());
+        for ( final String key : keysToPreserve  ) {
+            if ( igc.hasAttribute(key) )
+                attributes.put(key, igc.getAttribute(key));
+        }
+        return attributes;
+    }
+
+    /**
+     * @deprecated use variant context builder version instead
+     * @param vc                  the variant context
+     * @param keysToPreserve      the keys to preserve
+     * @return a pruned version of the original variant context
+     */
+    @Deprecated
+    public static VariantContext pruneVariantContext(final VariantContext vc, Collection<String> keysToPreserve ) {
+        return pruneVariantContext(new VariantContextBuilder(vc), keysToPreserve).make();
+    }
+
+    public static VariantContextBuilder pruneVariantContext(final VariantContextBuilder builder, Collection<String> keysToPreserve ) {
+        final VariantContext vc = builder.make();
+        if ( keysToPreserve == null ) keysToPreserve = Collections.emptyList();
+
+        // VC info
+        final Map<String, Object> attributes = subsetAttributes(vc.getCommonInfo(), keysToPreserve);
+
+        // Genotypes
+        final GenotypesContext genotypes = GenotypesContext.create(vc.getNSamples());
+        for ( final Genotype g : vc.getGenotypes() ) {
+            final GenotypeBuilder gb = new GenotypeBuilder(g);
+            // remove AD, DP, PL, and all extended attributes, keeping just GT and GQ
+            gb.noAD().noDP().noPL().noAttributes();
+            genotypes.add(gb.make());
+        }
+
+        return builder.genotypes(genotypes).attributes(attributes);
+    }
+
+    public static boolean allelesAreSubset(VariantContext vc1, VariantContext vc2) {
+        // if all alleles of vc1 are a contained in alleles of vc2, return true
+        if (!vc1.getReference().equals(vc2.getReference()))
+            return false;
+
+        for (final Allele a :vc1.getAlternateAlleles()) {
+            if (!vc2.getAlternateAlleles().contains(a))
+                return false;
+        }
+
+        return true;
+    }
+
+    public static Map<VariantContext.Type, List<VariantContext>> separateVariantContextsByType( final Collection<VariantContext> VCs ) {
+        if( VCs == null ) { throw new IllegalArgumentException("VCs cannot be null."); }
+
+        final HashMap<VariantContext.Type, List<VariantContext>> mappedVCs = new HashMap<>();
+        for ( final VariantContext vc : VCs ) {
+            VariantContext.Type vcType = vc.getType();
+
+            // look at previous variant contexts of different type. If:
+            // a) otherVC has alleles which are subset of vc, remove otherVC from its list and add otherVC to vc's list
+            // b) vc has alleles which are subset of otherVC. Then, add vc to otherVC's type list (rather, do nothing since vc will be added automatically to its list)
+            // c) neither: do nothing, just add vc to its own list
+            boolean addtoOwnList = true;
+            for (final VariantContext.Type type : VariantContext.Type.values()) {
+                if (type.equals(vcType))
+                    continue;
+
+                if (!mappedVCs.containsKey(type))
+                    continue;
+
+                List<VariantContext> vcList = mappedVCs.get(type);
+                for (int k=0; k <  vcList.size(); k++) {
+                    VariantContext otherVC = vcList.get(k);
+                    if (allelesAreSubset(otherVC,vc)) {
+                        // otherVC has a type different than vc and its alleles are a subset of vc: remove otherVC from its list and add it to vc's type list
+                        vcList.remove(k);
+                        // avoid having empty lists
+                        if (vcList.size() == 0)
+                            mappedVCs.remove(type);
+                        if ( !mappedVCs.containsKey(vcType) )
+                            mappedVCs.put(vcType, new ArrayList<VariantContext>());
+                        mappedVCs.get(vcType).add(otherVC);
+                        break;
+                    }
+                    else if (allelesAreSubset(vc,otherVC)) {
+                        // vc has a type different than otherVC and its alleles are a subset of VC: add vc to otherVC's type list and don't add to its own
+                        mappedVCs.get(type).add(vc);
+                        addtoOwnList = false;
+                        break;
+                    }
+                }
+            }
+            if (addtoOwnList) {
+                if ( !mappedVCs.containsKey(vcType) )
+                    mappedVCs.put(vcType, new ArrayList<VariantContext>());
+                mappedVCs.get(vcType).add(vc);
+            }
+        }
+
+        return mappedVCs;
+    }
+
+    public static VariantContext purgeUnallowedGenotypeAttributes(VariantContext vc, Set<String> allowedAttributes) {
+        if ( allowedAttributes == null )
+            return vc;
+
+        final GenotypesContext newGenotypes = GenotypesContext.create(vc.getNSamples());
+        for ( final Genotype genotype : vc.getGenotypes() ) {
+            final Map<String, Object> attrs = new HashMap<>();
+            for ( final Map.Entry<String, Object> attr : genotype.getExtendedAttributes().entrySet() ) {
+                if ( allowedAttributes.contains(attr.getKey()) )
+                    attrs.put(attr.getKey(), attr.getValue());
+            }
+            newGenotypes.add(new GenotypeBuilder(genotype).attributes(attrs).make());
+        }
+
+        return new VariantContextBuilder(vc).genotypes(newGenotypes).make();
+    }
+
+    protected static class AlleleMapper {
+        private VariantContext vc = null;
+        private Map<Allele, Allele> map = null;
+        public AlleleMapper(VariantContext vc)          { this.vc = vc; }
+        public AlleleMapper(Map<Allele, Allele> map)    { this.map = map; }
+        public boolean needsRemapping()                 { return this.map != null; }
+        public Collection<Allele> values()              { return map != null ? map.values() : vc.getAlleles(); }
+        public Allele remap(Allele a)                   { return map != null && map.containsKey(a) ? map.get(a) : a; }
+
+        public List<Allele> remap(List<Allele> as) {
+            List<Allele> newAs = new ArrayList<>();
+            for ( final Allele a : as ) {
+                //System.out.printf("  Remapping %s => %s%n", a, remap(a));
+                newAs.add(remap(a));
+            }
+            return newAs;
+        }
+
+        /**
+         * @return the list of unique values
+         */
+        public List<Allele> getUniqueMappedAlleles() {
+            if ( map == null )
+                return Collections.emptyList();
+            return new ArrayList<>(new HashSet<>(map.values()));
+        }
+    }
+
+    private static class CompareByPriority implements Comparator<VariantContext>, Serializable {
+        List<String> priorityListOfVCs;
+        public CompareByPriority(List<String> priorityListOfVCs) {
+            this.priorityListOfVCs = priorityListOfVCs;
+        }
+
+        private int getIndex(VariantContext vc) {
+            int i = priorityListOfVCs.indexOf(vc.getSource());
+            if ( i == -1 ) throw new IllegalArgumentException("Priority list " + priorityListOfVCs + " doesn't contain variant context " + vc.getSource());
+            return i;
+        }
+
+        public int compare(VariantContext vc1, VariantContext vc2) {
+            return Integer.valueOf(getIndex(vc1)).compareTo(getIndex(vc2));
+        }
+    }
+
+    /**
+     * For testing purposes only.  Create a site-only VariantContext at contig:start containing alleles
+     *
+     * @param name the name of the VC
+     * @param contig the contig for the VC
+     * @param start the start of the VC
+     * @param alleleStrings a non-null, non-empty list of strings for the alleles.  The first will be the ref allele, and others the
+     *                      alt.  Will compute the stop of the VC from the length of the reference allele
+     * @return a non-null VariantContext
+     */
+    public static VariantContext makeFromAlleles(final String name, final String contig, final int start, final List<String> alleleStrings) {
+        if ( alleleStrings == null || alleleStrings.isEmpty() )
+            throw new IllegalArgumentException("alleleStrings must be non-empty, non-null list");
+
+        final List<Allele> alleles = new LinkedList<>();
+        final int length = alleleStrings.get(0).length();
+
+        boolean first = true;
+        for ( final String alleleString : alleleStrings ) {
+            alleles.add(Allele.create(alleleString, first));
+            first = false;
+        }
+      return new VariantContextBuilder(name, contig, start, start+length-1, alleles).make();
+    }
+
+    /**
+     * Splits the alleles for the provided variant context into its primitive parts.
+     * Requires that the input VC be bi-allelic, so calling methods should first call splitVariantContextToBiallelics() if needed.
+     * Currently works only for MNPs.
+     *
+     * @param vc  the non-null VC to split
+     * @return a non-empty list of VCs split into primitive parts or the original VC otherwise
+     */
+    public static List<VariantContext> splitIntoPrimitiveAlleles(final VariantContext vc) {
+        if ( vc == null )
+            throw new IllegalArgumentException("Trying to break a null Variant Context into primitive parts");
+
+        if ( !vc.isBiallelic() )
+            throw new IllegalArgumentException("Trying to break a multi-allelic Variant Context into primitive parts");
+
+        // currently only works for MNPs
+        if ( !vc.isMNP() )
+            return Arrays.asList(vc);
+
+        final byte[] ref = vc.getReference().getBases();
+        final byte[] alt = vc.getAlternateAllele(0).getBases();
+
+        if ( ref.length != alt.length )
+            throw new IllegalStateException("ref and alt alleles for MNP have different lengths");
+
+        final List<VariantContext> result = new ArrayList<>(ref.length);
+
+        for ( int i = 0; i < ref.length; i++ ) {
+
+            // if the ref and alt bases are different at a given position, create a new SNP record (otherwise do nothing)
+            if ( ref[i] != alt[i] ) {
+
+                // create the ref and alt SNP alleles
+                final Allele newRefAllele = Allele.create(ref[i], true);
+                final Allele newAltAllele = Allele.create(alt[i], false);
+
+                // create a new VariantContext with the new SNP alleles
+                final VariantContextBuilder newVC = new VariantContextBuilder(vc).start(vc.getStart() + i).stop(vc.getStart() + i).alleles(Arrays.asList(newRefAllele, newAltAllele));
+
+                // create new genotypes with updated alleles
+                final Map<Allele, Allele> alleleMap = new HashMap<>();
+                alleleMap.put(vc.getReference(), newRefAllele);
+                alleleMap.put(vc.getAlternateAllele(0), newAltAllele);
+                final GenotypesContext newGenotypes = updateGenotypesWithMappedAlleles(vc.getGenotypes(), new AlleleMapper(alleleMap));
+
+                result.add(newVC.genotypes(newGenotypes).make());
+            }
+        }
+
+        if ( result.isEmpty() )
+            result.add(vc);
+
+        return result;
+    }
+
+    /**
+     * Are vc1 and 2 equal including their position and alleles?
+     * @param vc1 non-null VariantContext
+     * @param vc2 non-null VariantContext
+     * @return true if vc1 and vc2 are equal, false otherwise
+     */
+    public static boolean equalSites(final VariantContext vc1, final VariantContext vc2) {
+        if ( vc1 == null ) throw new IllegalArgumentException("vc1 cannot be null");
+        if ( vc2 == null ) throw new IllegalArgumentException("vc2 cannot be null");
+
+        if ( vc1.getStart() != vc2.getStart() ) return false;
+        if ( vc1.getEnd() != vc2.getEnd() ) return false;
+        if ( ! vc1.getChr().equals(vc2.getChr())) return false;
+        if ( ! vc1.getAlleles().equals(vc2.getAlleles()) ) return false;
+        return true;
+    }
+
+    /**
+     * Returns the absolute 0-based index of an allele.
+     *
+     * <p/>
+     * If the allele is equal to the reference, the result is 0, if it equal to the first alternative the result is 1
+     * and so forth.
+     * <p/>
+     * Therefore if you want the 0-based index within the alternative alleles you need to do the following:
+     *
+     * <p/>
+     * You can indicate whether the Java object reference comparator {@code ==} can be safelly used by setting {@code useEquals} to {@code false}.
+     *
+     * @param vc the target variant context.
+     * @param allele the target allele.
+     * @param ignoreRefState whether the reference states of the allele is important at all. Has no effect if {@code useEquals} is {@code false}.
+     * @param considerRefAllele whether the reference allele should be considered. You should set it to {@code false} if you are only interested in alternative alleles.
+     * @param useEquals whether equal method should be used in the search: {@link Allele#equals(Allele,boolean)}.
+     *
+     * @throws IllegalArgumentException if {@code allele} is {@code null}.
+     * @return {@code -1} if there is no such allele that satify those criteria, a value between 0 and {@link VariantContext#getNAlleles()} {@code -1} otherwise.
+     */
+    public static int indexOfAllele(final VariantContext vc, final Allele allele, final boolean ignoreRefState, final boolean considerRefAllele, final boolean useEquals) {
+        if (allele == null) throw new IllegalArgumentException();
+        return useEquals ? indexOfEqualAllele(vc,allele,ignoreRefState,considerRefAllele) : indexOfSameAllele(vc,allele,considerRefAllele);
+    }
+
+    /**
+     * Returns the relative 0-based index of an alternative allele.
+     * <p/>
+     * The the query allele is the same as the first alternative allele, the result is 0,
+     * if it is equal to the second 1 and so forth.
+     *
+     *
+     * <p/>
+     * Notice that the ref-status of the query {@code allele} is ignored.
+     *
+     * @param vc the target variant context.
+     * @param allele the query allele.
+     * @param useEquals  whether equal method should be used in the search: {@link Allele#equals(Allele,boolean)}.
+     *
+     * @throws IllegalArgumentException if {@code allele} is {@code null}.
+     *
+     * @return {@code -1} if there is no such allele that satify those criteria, a value between 0 and the number
+     *  of alternative alleles - 1.
+     */
+    public static int indexOfAltAllele(final VariantContext vc, final Allele allele, final boolean useEquals) {
+        final int absoluteIndex = indexOfAllele(vc,allele,true,false,useEquals);
+        return absoluteIndex == -1 ? -1 : absoluteIndex - 1;
+    }
+
+    // Impements index search using equals.
+    private static int indexOfEqualAllele(final VariantContext vc, final Allele allele, final boolean ignoreRefState,
+                                          final boolean considerRefAllele) {
+        int i = 0;
+        for (final Allele a : vc.getAlleles())
+            if (a.equals(allele,ignoreRefState))
+                return i == 0 ? (considerRefAllele ? 0 : -1) : i;
+            else
+                i++;
+        return -1;
+    }
+
+    // Implements index search using ==.
+    private static int indexOfSameAllele(final VariantContext vc, final Allele allele, final boolean considerRefAllele) {
+        int i = 0;
+
+        for (final Allele a : vc.getAlleles())
+            if (a == allele)
+                return i == 0 ? (considerRefAllele ? 0 : -1) : i;
+            else
+                i++;
+
+        return -1;
+    }
+}
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/variant/HomoSapiensConstants.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/variant/HomoSapiensConstants.java
new file mode 100644
index 0000000..0b1543b
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/variant/HomoSapiensConstants.java
@@ -0,0 +1,51 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.utils.variant;
+
+/**
+ * <i>Homo sapiens</i> genome constants.
+ *
+ * <p>NOTE: reference to these constants is an indication that your code is (human) species assumption dependant.</p>
+ *
+ * @author Valentin Ruano-Rubio <valentin at broadinstitute.org>
+ */
+public class HomoSapiensConstants {
+
+    /**
+     * Standard heterozygous rate for SNP variation.
+     */
+    public static final double SNP_HETEROZYGOSITY = 1e-3;
+
+    /**
+     * Standard heterozygous rate for INDEL variation.
+     */
+    public static final double INDEL_HETEROZYGOSITY = 1.0/8000;
+
+    /**
+     * Standard ploidy for autosomal chromosomes.
+     */
+    public static final int DEFAULT_PLOIDY = 2;
+}
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/wiggle/WiggleHeader.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/wiggle/WiggleHeader.java
new file mode 100644
index 0000000..85681c4
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/wiggle/WiggleHeader.java
@@ -0,0 +1,56 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.utils.wiggle;
+
+/**
+ * A class for defining the header values for a wiggle graph file (see UCSC). The optional fields are:
+ * name, description, visibility, color, altColor, priority, autoscale, alwaysZero, gridDefault,
+ * maxHeightPixels,graphType,viewLimits,yLineMark,yLineOnOff,windowingFunction,smoothingWindow
+ *
+ * For now only support name, description
+ *
+ * @Author chartl
+ * @Date Jul 21, 2010
+ */
+public class WiggleHeader {
+    static String type = "wiggle_0";
+    // defines the type of the track (for IGV or UCSC), wiggle_0 is the 'only' type of wiggle
+    private String name;
+    // a label for the track
+    private String description;
+    // a description of what the track is
+
+    public WiggleHeader(String name, String description) {
+        this.name = name;
+        this.description = description;
+    }
+
+    public String toString() {
+        return String.format("track type=%s name=\"%s\" description=\"%s\"",type,name,description);
+    }
+
+}
+
diff --git a/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/wiggle/WiggleWriter.java b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/wiggle/WiggleWriter.java
new file mode 100644
index 0000000..af9268b
--- /dev/null
+++ b/public/gatk-tools-public/src/main/java/org/broadinstitute/gatk/utils/wiggle/WiggleWriter.java
@@ -0,0 +1,117 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.utils.wiggle;
+
+import org.broadinstitute.gatk.utils.GenomeLoc;
+import org.broadinstitute.gatk.utils.exceptions.ReviewedGATKException;
+import org.broadinstitute.gatk.utils.exceptions.UserException;
+
+import java.io.*;
+
+/**
+ * Manages the output of wiggle files. Due to the wiggle spec (each wiggle file must be one chromosome), this writer
+ * will throw exceptions (or output multiple files?)
+ *
+ * todo -- currently no support for fixed step (special case of variable step)
+ * todo -- currently no support for span, start, or step
+ *
+ * @Author chartl
+ * @Date Jul 21, 2010
+ */
+public class WiggleWriter {
+
+    enum StepType {
+        fixed("fixedStep"),variable("variableStep");
+
+        String repr;
+
+        StepType(String repr) {
+            this.repr = repr;
+        }
+
+        public String toString() {
+            return repr;
+        }
+    }
+
+    private WiggleHeader wHeader = null;
+    // the header that we need to write prior to the file; and on future files (if multiple outputs ??)
+    private BufferedWriter wWriter = null;
+    // the file to which we are writing
+    private GenomeLoc firstLoc = null;
+    // the first genome loc the writer saw; need to cache this to compare contigs to preserve spec
+    private StepType type = StepType.variable;
+    // the type of step for the wiggle file, todo -- allow this to change
+
+    private String myFile = "unknown";
+
+    public WiggleWriter(File outputFile) {
+        myFile = outputFile.getAbsolutePath();
+        FileOutputStream outputStream;
+        try {
+            outputStream = new FileOutputStream(outputFile);
+        } catch ( FileNotFoundException e ) {
+            throw new UserException.CouldNotCreateOutputFile(outputFile, "Unable to create a wiggle file ", e);
+        }
+
+        wWriter = new BufferedWriter(new OutputStreamWriter(outputStream));
+    }
+
+    public WiggleWriter(OutputStream out) {
+       wWriter = new BufferedWriter(new OutputStreamWriter(out)); 
+    }
+
+    public void writeHeader(WiggleHeader header) {
+        wHeader = header;
+        write(wWriter,header.toString());
+    }
+
+    public void writeData(GenomeLoc loc, Object dataPoint) {
+        if ( this.firstLoc == null ) {
+            firstLoc = loc;
+            write(wWriter,String.format("%n"));
+            write(wWriter,String.format("%s\tchrom=%s",type.toString(),firstLoc.getContig()));
+            write(wWriter,String.format("%n"));
+            write(wWriter,String.format("%d\t%s",loc.getStart(),dataPoint.toString()));
+        } else if ( loc.compareContigs(firstLoc) == 0 ) {
+            write(wWriter,String.format("%n"));
+            write(wWriter,String.format("%d\t%s",loc.getStart(),dataPoint.toString()));
+        } else {
+            // todo -- maybe allow this to open a new file for the new chromosome?
+            throw new ReviewedGATKException("Attempting to write multiple contigs into wiggle file, first contig was "+firstLoc.getContig()+" most recent "+loc.getContig());
+        }
+    }
+
+    private void write(BufferedWriter w, String s) {
+        try {
+            w.write(s);
+            w.flush();
+            // flush required so writing to output stream will work
+        } catch (IOException e) {
+            throw new UserException.CouldNotCreateOutputFile(myFile, String.format("Error writing the wiggle line %s", s), e);
+        }
+    }
+}
diff --git a/public/gatk-tools-public/src/main/resources/GATK_public.key b/public/gatk-tools-public/src/main/resources/GATK_public.key
new file mode 100644
index 0000000..05cdde1
Binary files /dev/null and b/public/gatk-tools-public/src/main/resources/GATK_public.key differ
diff --git a/public/gatk-tools-public/src/main/resources/org/broadinstitute/gatk/engine/phonehome/resources/GATK_AWS_access.key b/public/gatk-tools-public/src/main/resources/org/broadinstitute/gatk/engine/phonehome/resources/GATK_AWS_access.key
new file mode 100644
index 0000000..28f2cd0
Binary files /dev/null and b/public/gatk-tools-public/src/main/resources/org/broadinstitute/gatk/engine/phonehome/resources/GATK_AWS_access.key differ
diff --git a/public/gatk-tools-public/src/main/resources/org/broadinstitute/gatk/engine/phonehome/resources/GATK_AWS_secret.key b/public/gatk-tools-public/src/main/resources/org/broadinstitute/gatk/engine/phonehome/resources/GATK_AWS_secret.key
new file mode 100644
index 0000000..5c289a8
Binary files /dev/null and b/public/gatk-tools-public/src/main/resources/org/broadinstitute/gatk/engine/phonehome/resources/GATK_AWS_secret.key differ
diff --git a/public/gatk-tools-public/src/main/resources/org/broadinstitute/gatk/tools/walkers/variantrecalibration/plot_Tranches.R b/public/gatk-tools-public/src/main/resources/org/broadinstitute/gatk/tools/walkers/variantrecalibration/plot_Tranches.R
new file mode 100755
index 0000000..d96add7
--- /dev/null
+++ b/public/gatk-tools-public/src/main/resources/org/broadinstitute/gatk/tools/walkers/variantrecalibration/plot_Tranches.R
@@ -0,0 +1,93 @@
+#!/bin/env Rscript
+
+library(tools)
+
+args <- commandArgs(TRUE)
+verbose = TRUE
+
+tranchesFile = args[1]
+targetTITV = as.numeric(args[2])
+targetSensitivity = as.numeric(args[3])
+suppressLegend = ! is.na(args[4])
+
+# -----------------------------------------------------------------------------------------------
+# Useful general routines
+# -----------------------------------------------------------------------------------------------
+
+MIN_FP_RATE = 0.001 # 1 / 1000 is min error rate 
+
+titvFPEst <- function(titvExpected, titvObserved) { 
+    max(min(1 - (titvObserved - 0.5) / (titvExpected - 0.5), 1), MIN_FP_RATE) 
+}
+
+titvFPEstV <- function(titvExpected, titvs) {
+    sapply(titvs, function(x) titvFPEst(titvExpected, x))
+}
+
+nTPFP <- function(nVariants, FDR) {
+    return(list(TP = nVariants * (1 - FDR/100), FP = nVariants * (FDR / 100)))
+}
+
+leftShift <- function(x, leftValue = 0) {
+    r = rep(leftValue, length(x))
+    for ( i in 1:(length(x)-1) ) {
+        #print(list(i=i))
+        r[i] = x[i+1]
+    }
+    r
+}
+
+# -----------------------------------------------------------------------------------------------
+# Tranches plot
+# -----------------------------------------------------------------------------------------------
+data2 = read.table(tranchesFile,sep=",",head=T)
+data2 = data2[order(data2$novelTiTv, decreasing=F),]
+#data2 = data2[order(data2$FDRtranche, decreasing=T),]
+cols = c("cornflowerblue", "cornflowerblue", "darkorange", "darkorange")
+density=c(20, -1, -1, 20)
+outfile = paste(tranchesFile, ".pdf", sep="")
+pdf(outfile, height=5, width=8)
+par(mar = c(5, 5, 4, 2) + 0.1)
+novelTiTv = c(data2$novelTITV,data2$novelTiTv)
+alpha = 1 - titvFPEstV(targetTITV, novelTiTv)
+#print(alpha)
+
+numGood = round(alpha * data2$numNovel);
+
+#numGood = round(data2$numNovel * (1-data2$targetTruthSensitivity/100))
+numBad = data2$numNovel - numGood;
+
+numPrevGood = leftShift(numGood, 0)
+numNewGood = numGood - numPrevGood
+numPrevBad = leftShift(numBad, 0)
+numNewBad = numBad - numPrevBad
+
+d=matrix(c(numPrevGood,numNewGood, numNewBad, numPrevBad),4,byrow=TRUE)
+#print(d)
+barplot(d/1000,horiz=TRUE,col=cols,space=0.2,xlab="Number of Novel Variants (1000s)", density=density, cex.axis=1.25, cex.lab=1.25) # , xlim=c(250000,350000))
+#abline(v= d[2,dim(d)[2]], lty=2)
+#abline(v= d[1,3], lty=2)
+if ( ! suppressLegend ) 
+    legend(3, length(data2$targetTruthSensitivity)/3 +1, c('Cumulative TPs','Tranch-specific TPs', 'Tranch-specific FPs', 'Cumulative FPs' ), fill=cols, density=density, bg='white', cex=1.25)
+
+mtext("Ti/Tv",2,line=2.25,at=length(data2$targetTruthSensitivity)*1.2,las=1, cex=1)
+mtext("truth",2,line=0,at=length(data2$targetTruthSensitivity)*1.2,las=1, cex=1)
+axis(2,line=-1,at=0.7+(0:(length(data2$targetTruthSensitivity)-1))*1.2,tick=FALSE,labels=data2$targetTruthSensitivity, las=1, cex.axis=1.0)
+axis(2,line=1,at=0.7+(0:(length(data2$targetTruthSensitivity)-1))*1.2,tick=FALSE,labels=round(novelTiTv,3), las=1, cex.axis=1.0)
+
+# plot sensitivity vs. specificity
+sensitivity = data2$truthSensitivity
+if ( ! is.null(sensitivity) ) {
+    #specificity = titvFPEstV(targetTITV, novelTiTv)
+    specificity = novelTiTv
+    plot(sensitivity, specificity, type="b", col="cornflowerblue", xlab="Tranche truth sensitivity", ylab="Specificity (Novel Ti/Tv ratio)")
+    abline(h=targetTITV, lty=2)
+    abline(v=targetSensitivity, lty=2)
+    #text(max(sensitivity), targetTITV-0.05, labels="Expected novel Ti/Tv", pos=2)
+}
+
+dev.off()
+
+if (exists('compactPDF')) {
+  compactPDF(outfile)
+}
diff --git a/public/gatk-tools-public/src/main/resources/org/broadinstitute/gatk/utils/recalibration/BQSR.R b/public/gatk-tools-public/src/main/resources/org/broadinstitute/gatk/utils/recalibration/BQSR.R
new file mode 100644
index 0000000..93474a5
--- /dev/null
+++ b/public/gatk-tools-public/src/main/resources/org/broadinstitute/gatk/utils/recalibration/BQSR.R
@@ -0,0 +1,159 @@
+library("ggplot2")
+library(gplots)
+library("reshape")
+library("grid")
+library("tools") #For compactPDF in R 2.13+
+library(gsalib)
+
+
+
+if ( interactive() ) {
+  args <- c("NA12878.6.1.dedup.realign.recal.bqsr.grp.csv", "NA12878.6.1.dedup.realign.recal.bqsr.grp", NA)
+} else {
+  args <- commandArgs(TRUE)
+} 
+
+data <- read.csv(args[1])
+
+data$Recalibration = as.factor(sapply(as.character(data$Recalibration),function(x) { 
+  xu = toupper(x); 
+  if (xu == "ORIGINAL") "BEFORE" else 
+    if (xu == "RECALIBRATED") "AFTER" else 
+      if (xu == "RECALIBRATION") "BQSR" else
+        xu }));
+
+gsa.report <- gsa.read.gatkreport(args[2])
+
+gsa.report$Arguments$Value = as.character(gsa.report$Arguments$Value);
+gsa.report$Arguments = subset(gsa.report$Arguments,subset= Argument != "plot_pdf_file");
+if (length(levels(data$Recalibration)) > 1) {
+  gsa.report$Arguments = subset(gsa.report$Arguments,subset= Argument != "recalibration_report");
+}
+gsa.report$Arguments$Value[gsa.report$Argument$Value == "null"] = "None";
+
+gsa.report.covariate.argnum = gsa.report$Arguments$Argument == "covariate";
+gsa.report$Arguments$Value[gsa.report.covariate.argnum] = sapply(strsplit(gsa.report$Arguments$Value[gsa.report.covariate.argnum],","),function(x) { 
+  y = sub("(^.+)Covariate","\\1",x); paste(y,collapse=",") } );
+
+data <- within(data, EventType <- factor(EventType, levels = rev(levels(EventType))))
+
+numRG = length(unique(data$ReadGroup))
+blankTheme = theme(panel.grid.major = element_blank(), panel.grid.minor = element_blank(), panel.background = element_blank(), axis.ticks = element_blank())
+
+# Viewport (layout 2 graphs top to bottom)
+distributeGraphRows <- function(graphs, heights = c()) {
+  if (length(heights) == 0) {
+    heights <- rep.int(1, length(graphs))
+  }
+  heights <- heights[!is.na(graphs)]
+  graphs <- graphs[!is.na(graphs)]
+  numGraphs <- length(graphs)
+  Layout <- grid.layout(nrow = numGraphs, ncol = 1, heights=heights)
+  grid.newpage()
+  pushViewport(viewport(layout = Layout))
+  subplot <- function(x) viewport(layout.pos.row = x, layout.pos.col = 1)
+  for (i in 1:numGraphs) {
+    print(graphs[[i]], vp = subplot(i))
+  }
+}
+
+
+for(cov in levels(data$CovariateName)) {    # for each covariate in turn  
+  d = data[data$CovariateName==cov,]        # pull out just the data for this covariate so we can treat the non-numeric values appropriately
+  if( cov == "Context" ) {
+    d$CovariateValue = as.character(d$CovariateValue)
+    d$CovariateValue = substring(d$CovariateValue,nchar(d$CovariateValue)-2,nchar(d$CovariateValue))
+  } else {
+    d$CovariateValue = as.numeric(levels(d$CovariateValue))[as.integer(d$CovariateValue)] # efficient way to convert factors back to their real values
+  }
+  #d=subset(d,Observations>2000) # only show bins which have enough data to actually estimate the quality
+  dSub=subset(d,EventType=="Base Substitution")
+  dIns=subset(d,EventType=="Base Insertion")
+  dDel=subset(d,EventType=="Base Deletion")
+  dSub=dSub[sample.int(length(dSub[,1]),min(length(dSub[,1]),2000)),] # don't plot too many values because it makes the PDFs too massive
+  dIns=dIns[sample.int(length(dIns[,1]),min(length(dIns[,1]),2000)),] # don't plot too many values because it makes the PDFs too massive
+  dDel=dDel[sample.int(length(dDel[,1]),min(length(dDel[,1]),2000)),] # don't plot too many values because it makes the PDFs too massive
+  d=rbind(dSub, dIns, dDel)
+  
+  if( cov != "QualityScore" ) {    
+    p <- ggplot(d, aes(x=CovariateValue,y=Accuracy,alpha=log10(Observations))) + ylim(min(-10,d$Accuracy),max(10,d$Accuracy)) +
+      geom_abline(intercept=0, slope=0, linetype=2) + 
+      xlab(paste(cov,"Covariate")) +
+      ylab("Quality Score Accuracy") +
+      blankTheme
+    if(cov == "Cycle") {
+      b <- p + geom_point(aes(color=Recalibration)) + scale_color_manual(values=c("BEFORE"="maroon1","AFTER"="blue","BQSR"="black")) + facet_grid(.~EventType) +
+        theme(axis.text.x=element_text(angle=90, hjust=0))
+      
+      p <- ggplot(d, aes(x=CovariateValue,y=AverageReportedQuality,alpha=log10(Observations))) +
+        xlab(paste(cov,"Covariate")) +
+        ylab("Mean Quality Score") + ylim(0,max(42,d$AverageReportedQuality)) +
+        blankTheme
+      e <- p + geom_point(aes(color=Recalibration)) + scale_color_manual(values=c("BEFORE"="maroon1","AFTER"="blue","BQSR"="black")) + facet_grid(.~EventType) +
+        theme(axis.text.x=element_text(angle=90, hjust=0))
+      
+      
+    } else {
+      c <- p + geom_point(aes(color=Recalibration)) + scale_color_manual(values=c("BEFORE"="maroon1","AFTER"="blue","BQSR"="black")) + facet_grid(.~EventType) +
+        theme(axis.text.x=element_text(angle=90, hjust=0)) + xlab(paste(cov,"Covariate (3 base suffix)"))
+      p <- ggplot(d, aes(x=CovariateValue,y=AverageReportedQuality,alpha=log10(Observations))) +
+        xlab(paste(cov,"Covariate (3 base suffix)")) +
+        ylab("Mean Quality Score") +
+        blankTheme
+      f <- p + geom_point(aes(color=Recalibration)) + scale_color_manual(values=c("BEFORE"="maroon1","AFTER"="blue","BQSR"="black")) + facet_grid(.~EventType) +
+        theme(axis.text.x=element_text(angle=90, hjust=0))
+      
+    }
+  } else {
+    p <- ggplot(d, aes(x=AverageReportedQuality,y=EmpiricalQuality,alpha=log10(Observations))) +
+      geom_abline(intercept=0, slope=1, linetype=2) + 
+      xlab("Reported Quality Score") +
+      ylab("Empirical Quality Score") +
+      blankTheme
+    a <- p + geom_point(aes(color=Recalibration)) + scale_color_manual(values=c("BEFORE"="maroon1","AFTER"="blue","BQSR"="black")) + facet_grid(.~EventType)
+    
+    p <- ggplot(d, aes(x=CovariateValue)) +
+      xlab(paste(cov,"Covariate")) +
+      ylab("No. of Observations (area normalized)") +
+      blankTheme
+    d <- p + geom_histogram(aes(fill=Recalibration,weight=Observations,y=..ndensity..),alpha=0.6,binwidth=1,position="identity")
+    d <- d + scale_fill_manual(values=c("BEFORE"="maroon1","AFTER"="blue","BQSR"="black"))
+    d <- d + facet_grid(.~EventType) 
+    #    d <- d + scale_y_continuous(formatter="comma")
+  }
+}
+
+if ( ! is.na(args[3]) )
+  pdf(args[3],height=9,width=15)
+
+#frame()
+textplot(gsa.report$Arguments, show.rownames=F)
+title(
+  main="GATK BaseRecalibration report",
+  sub=date())
+
+distributeGraphRows(list(a,b,c), c(1,1,1))
+distributeGraphRows(list(d,e,f), c(1,1,1))
+
+# format the overall information
+rt0 <- data.frame(
+  ReadGroup = gsa.report$RecalTable0$ReadGroup,
+  EventType = gsa.report$RecalTable0$EventType,
+  EmpiricalQuality = sprintf("%.1f", gsa.report$RecalTable0$EmpiricalQuality),
+  EstimatedQReported = sprintf("%.1f", gsa.report$RecalTable0$EstimatedQReported),
+  Observations = sprintf("%.2e", gsa.report$RecalTable0$Observations),
+  Errors = sprintf("%.2e", gsa.report$RecalTable0$Errors))  
+textplot(t(rt0), show.colnames=F)
+title("Overall error rates by event type")
+
+# plot per quality score recalibration table
+textplot(gsa.report$RecalTable1, show.rownames=F)
+title("Error rates by event type and initial quality score")
+
+if ( ! is.na(args[3]) ) {
+  dev.off()
+  if (exists('compactPDF')) {
+    compactPDF(args[2])
+  }
+}
+
diff --git a/public/gatk-tools-public/src/test/java/htsjdk/samtools/GATKBAMFileSpanUnitTest.java b/public/gatk-tools-public/src/test/java/htsjdk/samtools/GATKBAMFileSpanUnitTest.java
new file mode 100644
index 0000000..aaa20c0
--- /dev/null
+++ b/public/gatk-tools-public/src/test/java/htsjdk/samtools/GATKBAMFileSpanUnitTest.java
@@ -0,0 +1,254 @@
+/*
+* Copyright (c) 2012 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 htsjdk.samtools;
+
+import org.testng.Assert;
+import org.testng.annotations.Test;
+
+/**
+ * Tests of functionality of union, intersection operators.
+ */
+public class GATKBAMFileSpanUnitTest {
+    @Test
+    public void testUnionOfEmptyFileSpans() {
+        GATKBAMFileSpan empty1 = new GATKBAMFileSpan();
+        GATKBAMFileSpan empty2 = new GATKBAMFileSpan();
+        GATKBAMFileSpan union = empty1.union(empty2);
+        Assert.assertEquals(union.getGATKChunks().size(),0,"Elements inserted in union of two empty sets");
+    }
+
+    @Test
+    public void testUnionOfNonOverlappingFileSpans() {
+        GATKBAMFileSpan regionOne = new GATKBAMFileSpan(new GATKChunk(0,65535));
+        GATKBAMFileSpan regionTwo = new GATKBAMFileSpan(new GATKChunk(1<<16,(1<<16)|65535));
+        GATKBAMFileSpan union = regionOne.union(regionTwo);
+        Assert.assertEquals(union.getGATKChunks().size(),2,"Discontiguous elements were merged");
+        Assert.assertEquals(union.getGATKChunks().get(0),regionOne.getGATKChunks().get(0),"Wrong chunk was first in list");
+        Assert.assertEquals(union.getGATKChunks().get(1),regionTwo.getGATKChunks().get(0),"Wrong chunk was second in list");
+    }
+
+    @Test
+    public void testUnionOfContiguousFileSpans() {
+        // Region 1 ends at position adjacent to Region 2 start:
+        // |---1----|---2----|
+
+        GATKBAMFileSpan regionOne = new GATKBAMFileSpan(new GATKChunk(0,1<<16));
+        GATKBAMFileSpan regionTwo = new GATKBAMFileSpan(new GATKChunk(1<<16,(1<<16)|65535));
+        GATKBAMFileSpan union = regionOne.union(regionTwo);
+        Assert.assertEquals(union.getGATKChunks().size(),1,"Elements to be merged were not.");
+        Assert.assertEquals(union.getGATKChunks().get(0),new GATKChunk(0,(1<<16)|65535));
+    }
+
+    @Test
+    public void testUnionOfFileSpansFirstRegionEndsWithinSecondRegion() {
+        // Region 1 ends within Region 2:
+        //        |---2----|
+        // |---1----|
+
+        GATKBAMFileSpan regionOne = new GATKBAMFileSpan(new GATKChunk(0,(1<<16)|32767));
+        GATKBAMFileSpan regionTwo = new GATKBAMFileSpan(new GATKChunk(1<<16,(1<<16)|65535));
+        GATKBAMFileSpan union = regionOne.union(regionTwo);
+        Assert.assertEquals(union.getGATKChunks().size(),1,"Elements to be merged were not.");
+        Assert.assertEquals(union.getGATKChunks().get(0),new GATKChunk(0,(1<<16)|65535));
+    }
+
+    @Test
+    public void testUnionOfFileSpansFirstRegionEndsAtSecondRegionEnd() {
+        // Region 1 ends at Region 2 end:
+        //        |---2----|
+        // |---1-----------|
+
+        GATKBAMFileSpan regionOne = new GATKBAMFileSpan(new GATKChunk(0,(1<<16)|65535));
+        GATKBAMFileSpan regionTwo = new GATKBAMFileSpan(new GATKChunk(1<<16,(1<<16)|65535));
+        GATKBAMFileSpan union = regionOne.union(regionTwo);
+        Assert.assertEquals(union.getGATKChunks().size(),1,"Elements to be merged were not.");
+        Assert.assertEquals(union.getGATKChunks().get(0),new GATKChunk(0,(1<<16)|65535));
+    }
+
+    @Test
+    public void testUnionOfFileSpansFirstRegionEndsAfterSecondRegionEnd() {
+        // Region 1 ends after Region 2 end:
+        //        |---2----|
+        // |---1---------------|
+
+        GATKBAMFileSpan regionOne = new GATKBAMFileSpan(new GATKChunk(0,(1<<16)|65535));
+        GATKBAMFileSpan regionTwo = new GATKBAMFileSpan(new GATKChunk(1<<16,(1<<16)|32767));
+        GATKBAMFileSpan union = regionOne.union(regionTwo);
+        Assert.assertEquals(union.getGATKChunks().size(),1,"Elements to be merged were not.");
+        Assert.assertEquals(union.getGATKChunks().get(0),new GATKChunk(0,(1<<16)|65535));
+    }
+
+    @Test
+    public void testUnionOfFileSpansFirstRegionStartsAtSecondRegionStart() {
+        // Region 1 starts at Region 2 start, but ends before Region 2:
+        // |---2--------|
+        // |---1----|
+
+        GATKBAMFileSpan regionOne = new GATKBAMFileSpan(new GATKChunk(1<<16,(1<<16)|32767));
+        GATKBAMFileSpan regionTwo = new GATKBAMFileSpan(new GATKChunk(1<<16,(1<<16)|65535));
+        GATKBAMFileSpan union = regionOne.union(regionTwo);
+        Assert.assertEquals(union.getGATKChunks().size(),1,"Elements to be merged were not.");
+        Assert.assertEquals(union.getGATKChunks().get(0),new GATKChunk(1<<16,(1<<16)|65535));
+    }
+
+    @Test
+    public void testUnionOfFileSpansFirstRegionEqualToSecondRegion() {
+        // Region 1 and Region 2 represent the same region:
+        // |---2----|
+        // |---1----|
+
+        GATKBAMFileSpan regionOne = new GATKBAMFileSpan(new GATKChunk(1<<16,(1<<16)|65535));
+        GATKBAMFileSpan regionTwo = new GATKBAMFileSpan(new GATKChunk(1<<16,(1<<16)|65535));
+        GATKBAMFileSpan union = regionOne.union(regionTwo);
+        Assert.assertEquals(union.getGATKChunks().size(),1,"Elements to be merged were not.");
+        Assert.assertEquals(union.getGATKChunks().get(0),new GATKChunk(1<<16,(1<<16)|65535));
+    }
+
+    @Test
+    public void testUnionOfStringOfFileSpans() {
+        GATKBAMFileSpan regionOne = new GATKBAMFileSpan(new GATKChunk[] { new GATKChunk(0,1<<16), new GATKChunk(2<<16,3<<16) });
+        GATKBAMFileSpan regionTwo = new GATKBAMFileSpan(new GATKChunk(1<<16,2<<16));
+        GATKBAMFileSpan union = regionOne.union(regionTwo);
+        Assert.assertEquals(union.getGATKChunks().size(),1,"Elements to be merged were not.");
+        Assert.assertEquals(union.getGATKChunks().get(0),new GATKChunk(0,3<<16));
+    }
+
+    @Test
+    public void testUnionAllFileSpansAdded() {
+        GATKBAMFileSpan regionOne = new GATKBAMFileSpan(new GATKChunk[] { new GATKChunk(0,1<<16), new GATKChunk(2<<16,3<<16), new GATKChunk(20<<16,21<<16) });
+        GATKBAMFileSpan regionTwo = new GATKBAMFileSpan(new GATKChunk(1<<16,2<<16));
+        GATKBAMFileSpan union = regionOne.union(regionTwo);
+        Assert.assertEquals(union.getGATKChunks().size(),2,"Elements to be merged were not.");
+        Assert.assertEquals(union.getGATKChunks().get(0),new GATKChunk(0,3<<16));
+        Assert.assertEquals(union.getGATKChunks().get(1),new GATKChunk(20<<16,21<<16));
+    }
+
+    @Test
+    public void testIntersectionOfEmptyFileSpans() {
+        GATKBAMFileSpan empty1 = new GATKBAMFileSpan();
+        GATKBAMFileSpan empty2 = new GATKBAMFileSpan();
+        GATKBAMFileSpan intersection = empty1.intersection(empty2);
+        Assert.assertEquals(intersection.getGATKChunks().size(),0,"Elements inserted in intersection of two empty sets");
+    }
+
+    @Test
+    public void testIntersectionOfNonOverlappingFileSpans() {
+        GATKBAMFileSpan regionOne = new GATKBAMFileSpan(new GATKChunk(0,1<<16));
+        GATKBAMFileSpan regionTwo = new GATKBAMFileSpan(new GATKChunk(1<<16,2<<16));
+        GATKBAMFileSpan intersection = regionOne.intersection(regionTwo);
+        Assert.assertEquals(intersection.getGATKChunks().size(),0,"Elements inserted in intersection of two non-intersecting filespans");
+    }
+
+    @Test
+    public void testIntersectionOfSmallOverlapInFileSpans() {
+        GATKBAMFileSpan regionOne = new GATKBAMFileSpan(new GATKChunk(0,1<<16));
+        GATKBAMFileSpan regionTwo = new GATKBAMFileSpan(new GATKChunk(65535,2<<16));
+        GATKBAMFileSpan intersection = regionOne.intersection(regionTwo);
+        Assert.assertEquals(intersection.getGATKChunks().size(),1,"No intersection found between two partially overlapping filespans");
+        Assert.assertEquals(intersection.getGATKChunks().get(0),new GATKChunk(65535,1<<16),"Determined intersection is incorrect.");
+    }
+
+    @Test
+    public void testIntersectionOfStrictSubset() {
+        GATKBAMFileSpan regionOne = new GATKBAMFileSpan(new GATKChunk(0,1<<16));
+        GATKBAMFileSpan regionTwo = new GATKBAMFileSpan(new GATKChunk(0,2<<16));
+        GATKBAMFileSpan intersection = regionOne.intersection(regionTwo);
+        Assert.assertEquals(intersection.getGATKChunks().size(),1,"No intersection found between two partially overlapping filespans");
+        Assert.assertEquals(intersection.getGATKChunks().get(0),new GATKChunk(0<<16,1<<16),"Determined intersection is incorrect.");
+
+        // Make sure intersection is symmetric
+        intersection = regionTwo.intersection(regionOne);
+        Assert.assertEquals(intersection.getGATKChunks().size(),1,"No intersection found between two partially overlapping filespans");
+        Assert.assertEquals(intersection.getGATKChunks().get(0),new GATKChunk(0<<16,1<<16),"Determined intersection is incorrect.");
+    }
+
+    @Test
+    public void testIntersectionOfPartialOverlap() {
+        GATKBAMFileSpan regionOne = new GATKBAMFileSpan(new GATKChunk(0,2<<16));
+        GATKBAMFileSpan regionTwo = new GATKBAMFileSpan(new GATKChunk(0<<16|32768,1<<16|32768));
+        GATKBAMFileSpan intersection = regionOne.intersection(regionTwo);
+        Assert.assertEquals(intersection.getGATKChunks().size(),1,"No intersection found between two partially overlapping filespans");
+        Assert.assertEquals(intersection.getGATKChunks().get(0),new GATKChunk(0<<16|32768,1<<16|32768),"Determined intersection is incorrect.");
+    }
+
+    @Test
+    public void testIntersectionOfChunkLists() {
+        GATKBAMFileSpan regionOne = new GATKBAMFileSpan(new GATKChunk(0,5<<16));
+        GATKBAMFileSpan regionTwo = new GATKBAMFileSpan(new GATKChunk[] { new GATKChunk(1<<16,2<<16), new GATKChunk(3<<16,4<<16) });
+        GATKBAMFileSpan intersection = regionOne.intersection(regionTwo);
+        Assert.assertEquals(intersection.getGATKChunks().size(),2,"Wrong number of intersections found.");
+        Assert.assertEquals(intersection.getGATKChunks().get(0),new GATKChunk(1<<16,2<<16),"Determined intersection is incorrect.");
+        Assert.assertEquals(intersection.getGATKChunks().get(1),new GATKChunk(3<<16,4<<16),"Determined intersection is incorrect.");
+
+        // Make sure intersection is symmetric
+        intersection = regionTwo.intersection(regionOne);
+        Assert.assertEquals(intersection.getGATKChunks().size(),2,"Wrong number of intersections found.");
+        Assert.assertEquals(intersection.getGATKChunks().get(0),new GATKChunk(1<<16,2<<16),"Determined intersection is incorrect.");
+        Assert.assertEquals(intersection.getGATKChunks().get(1),new GATKChunk(3<<16,4<<16),"Determined intersection is incorrect.");
+    }
+
+    @Test
+    public void testSubtractionOfEmptyChunkLists() {
+        GATKBAMFileSpan regionOne = new GATKBAMFileSpan();
+        GATKBAMFileSpan regionTwo = new GATKBAMFileSpan();
+        GATKBAMFileSpan subtraction = regionOne.minus(regionTwo);
+        Assert.assertEquals(subtraction.getGATKChunks().size(),0,"Elements inserted in subtraction of two empty sets");
+    }
+
+    @Test
+    public void testSingleIntervalSubtractedAway() {
+        GATKBAMFileSpan regionOne = new GATKBAMFileSpan(new GATKChunk(0,1<<16));
+        GATKBAMFileSpan regionTwo = new GATKBAMFileSpan(new GATKChunk(0,1<<16));
+        GATKBAMFileSpan subtraction = regionOne.minus(regionTwo);
+        Assert.assertEquals(subtraction.getGATKChunks().size(),0,"Elements inserted in complete subtraction of region");
+    }
+
+    @Test
+    public void testMultipleIntervalsSubtractedAway() {
+        GATKBAMFileSpan regionOne = new GATKBAMFileSpan(new GATKChunk[] { new GATKChunk(0,1<<16), new GATKChunk(2<<16,3<<16) });
+        GATKBAMFileSpan regionTwo = new GATKBAMFileSpan(new GATKChunk[] { new GATKChunk(0,1<<16), new GATKChunk(2<<16,3<<16) });
+        GATKBAMFileSpan subtraction = regionOne.minus(regionTwo);
+        Assert.assertEquals(subtraction.getGATKChunks().size(),0,"Elements inserted in complete subtraction of region");
+    }
+
+    @Test
+    public void testSubtractionOfStrictSubset() {
+        GATKBAMFileSpan regionOne = new GATKBAMFileSpan(new GATKChunk(0,2<<16));
+        GATKBAMFileSpan regionTwo = new GATKBAMFileSpan(new GATKChunk(0,1<<16));
+        GATKBAMFileSpan subtraction = regionOne.minus(regionTwo);
+        Assert.assertEquals(subtraction.getGATKChunks().size(),1,"Incorrect size in strict subset subtraction of region");
+        Assert.assertEquals(subtraction.getGATKChunks().get(0),new GATKChunk(1<<16,2<<16),"Determined subtraction is incorrect.");
+    }
+
+    @Test
+    public void testSubtractionOfPartialOverlap() {
+        GATKBAMFileSpan regionOne = new GATKBAMFileSpan(new GATKChunk(0,2<<16));
+        GATKBAMFileSpan regionTwo = new GATKBAMFileSpan(new GATKChunk(1<<16,3<<16));
+        GATKBAMFileSpan subtraction = regionOne.minus(regionTwo);
+        Assert.assertEquals(subtraction.getGATKChunks().size(),1,"Incorrect size in partial subset subtraction of region");
+        Assert.assertEquals(subtraction.getGATKChunks().get(0),new GATKChunk(0<<16,1<<16),"Determined subtraction is incorrect.");
+    }
+}
diff --git a/public/gatk-tools-public/src/test/java/htsjdk/samtools/GATKChunkUnitTest.java b/public/gatk-tools-public/src/test/java/htsjdk/samtools/GATKChunkUnitTest.java
new file mode 100644
index 0000000..2b08fc4
--- /dev/null
+++ b/public/gatk-tools-public/src/test/java/htsjdk/samtools/GATKChunkUnitTest.java
@@ -0,0 +1,71 @@
+/*
+* Copyright (c) 2012 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 htsjdk.samtools;
+
+import org.testng.Assert;
+import org.testng.annotations.Test;
+
+/**
+ * Test basic functionality of the GATK chunk, giving informative size capabilities, etc.
+ */
+public class GATKChunkUnitTest {
+    private static final int FULL_BLOCK_COMPRESSED_SIZE = 25559;
+    private static final int FULL_BLOCK_UNCOMPRESSED_SIZE = 65536;
+    private static final int HALF_BLOCK_UNCOMPRESSED_SIZE = FULL_BLOCK_UNCOMPRESSED_SIZE/2;
+
+    @Test
+    public void testSizeOfEmptyChunk() {
+        GATKChunk chunk = new GATKChunk(0,0);
+        Assert.assertEquals(chunk.size(),0,"Empty chunk's size is not equal to 0.");
+    }
+
+    @Test
+    public void testSizeOfChunkWithinSingleBlock() {
+        GATKChunk chunk = new GATKChunk(0,FULL_BLOCK_UNCOMPRESSED_SIZE-1);
+        Assert.assertEquals(chunk.size(),FULL_BLOCK_UNCOMPRESSED_SIZE-1,"Chunk spanning limits of block is returning wrong size.");
+
+        chunk = new GATKChunk(0,HALF_BLOCK_UNCOMPRESSED_SIZE);
+        Assert.assertEquals(chunk.size(),HALF_BLOCK_UNCOMPRESSED_SIZE,"Chunk spanning 1/2 block is returning the wrong size.");
+    }
+
+    @Test
+    public void testSizeOfSingleBlock() {
+        GATKChunk chunk = new GATKChunk(0,FULL_BLOCK_COMPRESSED_SIZE<<16);
+        Assert.assertEquals(chunk.size(),FULL_BLOCK_UNCOMPRESSED_SIZE,"Chunk spanning complete block returns incorrect size.");
+    }
+
+    @Test
+    public void testSizeOfBlockAndAHalf() {
+        GATKChunk chunk = new GATKChunk(0,(FULL_BLOCK_COMPRESSED_SIZE<<16)+HALF_BLOCK_UNCOMPRESSED_SIZE);
+        Assert.assertEquals(chunk.size(),FULL_BLOCK_UNCOMPRESSED_SIZE+HALF_BLOCK_UNCOMPRESSED_SIZE,"Chunk spanning 1.5 blocks returns incorrect size.");
+    }
+
+    @Test
+    public void testSizeOfHalfBlock() {
+        GATKChunk chunk = new GATKChunk(HALF_BLOCK_UNCOMPRESSED_SIZE,FULL_BLOCK_COMPRESSED_SIZE<<16);
+        Assert.assertEquals(chunk.size(),HALF_BLOCK_UNCOMPRESSED_SIZE,"Chunk spanning 0.5 blocks returns incorrect size.");
+    }
+}
diff --git a/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/engine/CommandLineGATKUnitTest.java b/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/engine/CommandLineGATKUnitTest.java
new file mode 100644
index 0000000..dc3e996
--- /dev/null
+++ b/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/engine/CommandLineGATKUnitTest.java
@@ -0,0 +1,68 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.engine;
+
+import htsjdk.samtools.SAMFileReader;
+import org.broadinstitute.gatk.utils.BaseTest;
+import org.testng.Assert;
+import org.testng.annotations.Test;
+
+import java.io.File;
+
+/**
+ * @author Eric Banks
+ * @since 7/18/12
+ */
+public class CommandLineGATKUnitTest extends BaseTest {
+
+    @Test(enabled = true)
+    public void testSamTextFileError1() {
+        final File samFile = new File(publicTestDir + "testfile.sam");
+        final File indexFile = new File(publicTestDir + "HiSeq.1mb.1RG.bai");
+        try {
+            final SAMFileReader reader = new SAMFileReader(samFile, indexFile, false);
+
+            // we shouldn't get here
+            Assert.fail("We should have exceptioned out when trying to create a reader with an index for a textual SAM file");
+        } catch (RuntimeException e) {
+            Assert.assertTrue(e.getMessage().indexOf(CommandLineGATK.PICARD_TEXT_SAM_FILE_ERROR_1) != -1);
+        }
+    }
+
+    @Test(enabled = true)
+    public void testSamTextFileError2() {
+        File samFile = new File(publicTestDir + "testfile.sam");
+        try {
+            final SAMFileReader reader = new SAMFileReader(samFile);
+            reader.getFilePointerSpanningReads();
+
+            // we shouldn't get here
+            Assert.fail("We should have exceptioned out when trying to call getFilePointerSpanningReads() for a textual SAM file");
+        } catch (RuntimeException e) {
+            Assert.assertTrue(e.getMessage().indexOf(CommandLineGATK.PICARD_TEXT_SAM_FILE_ERROR_2) != -1);
+        }
+    }
+}
diff --git a/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/engine/EngineFeaturesIntegrationTest.java b/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/engine/EngineFeaturesIntegrationTest.java
new file mode 100644
index 0000000..6596cf3
--- /dev/null
+++ b/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/engine/EngineFeaturesIntegrationTest.java
@@ -0,0 +1,736 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.engine;
+
+import htsjdk.samtools.*;
+import htsjdk.samtools.util.CloseableIterator;
+import htsjdk.tribble.readers.LineIterator;
+import org.broadinstitute.gatk.engine.walkers.WalkerTest;
+import org.broadinstitute.gatk.utils.commandline.*;
+import org.broadinstitute.gatk.engine.arguments.StandardVariantContextInputArgumentCollection;
+import org.broadinstitute.gatk.engine.contexts.AlignmentContext;
+import org.broadinstitute.gatk.engine.contexts.ReferenceContext;
+import org.broadinstitute.gatk.engine.datasources.reference.ReferenceDataSource;
+import org.broadinstitute.gatk.engine.filters.MappingQualityUnavailableFilter;
+import org.broadinstitute.gatk.engine.refdata.RefMetaDataTracker;
+import org.broadinstitute.gatk.engine.refdata.tracks.RMDTrack;
+import org.broadinstitute.gatk.engine.refdata.tracks.RMDTrackBuilder;
+import org.broadinstitute.gatk.engine.refdata.utils.GATKFeature;
+import org.broadinstitute.gatk.engine.walkers.ReadFilters;
+import org.broadinstitute.gatk.engine.walkers.ReadWalker;
+import org.broadinstitute.gatk.engine.walkers.RodWalker;
+import org.broadinstitute.gatk.tools.walkers.qc.ErrorThrowing;
+import org.broadinstitute.gatk.utils.GenomeLocParser;
+import org.broadinstitute.gatk.utils.collections.Pair;
+import org.broadinstitute.gatk.utils.exceptions.ReviewedGATKException;
+import org.broadinstitute.gatk.utils.exceptions.UserException;
+import org.broadinstitute.gatk.utils.sam.GATKSAMRecord;
+import org.broadinstitute.gatk.utils.sam.GATKSamRecordFactory;
+import org.broadinstitute.gatk.utils.variant.GATKVCFUtils;
+import htsjdk.variant.variantcontext.VariantContext;
+import htsjdk.variant.variantcontext.writer.VariantContextWriter;
+import htsjdk.variant.vcf.VCFCodec;
+import htsjdk.variant.vcf.VCFHeader;
+import htsjdk.variant.vcf.VCFHeaderLine;
+import org.testng.Assert;
+import org.testng.annotations.DataProvider;
+import org.testng.annotations.Test;
+
+import java.io.*;
+import java.util.*;
+
+/**
+ *
+ */
+public class EngineFeaturesIntegrationTest extends WalkerTest {
+    private void testBadRODBindingInput(String type, String name, Class c) {
+        WalkerTestSpec spec = new WalkerTestSpec("-T SelectVariants -L 1:1 --variant:variant," + type + " "
+                + b37dbSNP132 + " -R " + b37KGReference + " -o %s",
+                1, c);
+        executeTest(name, spec);
+    }
+
+    @Test() private void testBadRODBindingInputType1() {
+        testBadRODBindingInput("beagle", "BEAGLE input to VCF expecting walker", UserException.BadArgumentValue.class);
+    }
+
+    @Test() private void testBadRODBindingInputType3() {
+        testBadRODBindingInput("bed", "Bed input to VCF expecting walker", UserException.BadArgumentValue.class);
+    }
+
+    @Test() private void testBadRODBindingInputTypeUnknownType() {
+        testBadRODBindingInput("bedXXX", "Unknown input to VCF expecting walker", UserException.UnknownTribbleType.class);
+    }
+
+    private void testMissingFile(String name, String missingBinding) {
+        WalkerTestSpec spec = new WalkerTestSpec(missingBinding + " -R " + b37KGReference + " -o %s",
+                1, UserException.CouldNotReadInputFile.class);
+        executeTest(name, spec);
+    }
+
+    @Test() private void testMissingBAMnt1() {
+        testMissingFile("missing BAM", "-T PrintReads -I missing.bam -nt 1");
+    }
+    @Test() private void testMissingBAMnt4() {
+        testMissingFile("missing BAM", "-T PrintReads -I missing.bam -nt 4");
+    }
+    @Test() private void testMissingVCF() {
+        testMissingFile("missing VCF", "-T SelectVariants -V missing.vcf");
+    }
+    @Test() private void testMissingInterval() {
+        testMissingFile("missing interval", "-T PrintReads -L missing.interval_list -I " + b37GoodBAM);
+    }
+
+
+    // --------------------------------------------------------------------------------
+    //
+    // Test that our exceptions are coming back as we expect
+    //
+    // --------------------------------------------------------------------------------
+
+    private class EngineErrorHandlingTestProvider extends TestDataProvider {
+        final Class expectedException;
+        final String args;
+        final int iterationsToTest;
+
+        public EngineErrorHandlingTestProvider(Class exceptedException, final String args) {
+            super(EngineErrorHandlingTestProvider.class);
+            this.expectedException = exceptedException;
+            this.args = args;
+            this.iterationsToTest = args.equals("") ? 1 : 10;
+            setName(String.format("Engine error handling: expected %s with args %s", exceptedException, args));
+        }
+    }
+
+    @DataProvider(name = "EngineErrorHandlingTestProvider")
+    public Object[][] makeEngineErrorHandlingTestProvider() {
+        for ( final ErrorThrowing.FailMethod failMethod : ErrorThrowing.FailMethod.values() ) {
+            if ( failMethod == ErrorThrowing.FailMethod.TREE_REDUCE )
+                continue; // cannot reliably throw errors in TREE_REDUCE
+
+            final String failArg = " -fail " + failMethod.name();
+            for ( final String args : Arrays.asList("", " -nt 2", " -nct 2") ) {
+                new EngineErrorHandlingTestProvider(NullPointerException.class, failArg + args);
+                new EngineErrorHandlingTestProvider(UserException.class, failArg + args);
+                new EngineErrorHandlingTestProvider(ReviewedGATKException.class, failArg + args);
+            }
+        }
+
+        return EngineErrorHandlingTestProvider.getTests(EngineErrorHandlingTestProvider.class);
+    }
+
+    //
+    // Loop over errors to throw, make sure they are the errors we get back from the engine, regardless of NT type
+    //
+    @Test(enabled = true, dataProvider = "EngineErrorHandlingTestProvider", timeOut = 60 * 1000 )
+    public void testEngineErrorHandlingTestProvider(final EngineErrorHandlingTestProvider cfg) {
+        for ( int i = 0; i < cfg.iterationsToTest; i++ ) {
+            final String root = "-T ErrorThrowing -R " + exampleFASTA;
+            final String args = root + cfg.args + " -E " + cfg.expectedException.getSimpleName();
+            WalkerTestSpec spec = new WalkerTestSpec(args, 0, cfg.expectedException);
+
+            executeTest(cfg.toString(), spec);
+        }
+    }
+
+    // --------------------------------------------------------------------------------
+    //
+    // Test that read filters are being applied in the order we expect
+    //
+    // --------------------------------------------------------------------------------
+
+    @ReadFilters({MappingQualityUnavailableFilter.class})
+    public static class DummyReadWalkerWithMapqUnavailableFilter extends ReadWalker<Integer, Integer> {
+        @Output
+        PrintStream out;
+
+        @Override
+        public Integer map(ReferenceContext ref, GATKSAMRecord read, RefMetaDataTracker metaDataTracker) {
+            return 1;
+        }
+
+        @Override
+        public Integer reduceInit() {
+            return 0;
+        }
+
+        @Override
+        public Integer reduce(Integer value, Integer sum) {
+            return value + sum;
+        }
+
+        @Override
+        public void onTraversalDone(Integer result) {
+            out.println(result);
+        }
+    }
+
+    @Test(enabled = true)
+    public void testUserReadFilterAppliedBeforeWalker() {
+        WalkerTestSpec spec = new WalkerTestSpec("-R " + b37KGReference + " -I " + privateTestDir + "allMAPQ255.bam"
+                + " -T DummyReadWalkerWithMapqUnavailableFilter -o %s -L MT -rf ReassignMappingQuality",
+                1, Arrays.asList("ecf27a776cdfc771defab1c5d19de9ab"));
+        executeTest("testUserReadFilterAppliedBeforeWalker", spec);
+    }
+
+    @Test
+    public void testNegativeCompress() {
+        testBadCompressArgument(-1);
+    }
+
+    @Test
+    public void testTooBigCompress() {
+        testBadCompressArgument(100);
+    }
+
+    private void testBadCompressArgument(final int compress) {
+        WalkerTestSpec spec = new WalkerTestSpec("-T PrintReads -R " + b37KGReference + " -I " + privateTestDir + "NA12878.1_10mb_2_10mb.bam -o %s -compress " + compress,
+                1, UserException.class);
+        executeTest("badCompress " + compress, spec);
+    }
+
+    // --------------------------------------------------------------------------------
+    //
+    // Test that the VCF version key is what we expect
+    //
+    // --------------------------------------------------------------------------------
+    @Test(enabled = true)
+    public void testGATKVersionInVCF() throws Exception {
+        WalkerTestSpec spec = new WalkerTestSpec("-T SelectVariants -R " + b37KGReference +
+                " -V " + privateTestDir + "NA12878.WGS.b37.chr20.firstMB.vcf"
+                + " -o %s -L 20:61098",
+                1, Arrays.asList(""));
+        spec.disableShadowBCF();
+        final File vcf = executeTest("testGATKVersionInVCF", spec).first.get(0);
+        final VCFCodec codec = new VCFCodec();
+        final VCFHeader header = (VCFHeader) codec.readActualHeader(codec.makeSourceFromStream(new FileInputStream(vcf)));
+        final VCFHeaderLine versionLine = header.getMetaDataLine(GATKVCFUtils.GATK_COMMAND_LINE_KEY);
+        Assert.assertNotNull(versionLine);
+        Assert.assertTrue(versionLine.toString().contains("SelectVariants"));
+    }
+
+    @Test(enabled = true)
+    public void testMultipleGATKVersionsInVCF() throws Exception {
+        WalkerTestSpec spec = new WalkerTestSpec("-T SelectVariants -R " + b37KGReference +
+                " -V " + privateTestDir + "gatkCommandLineInHeader.vcf"
+                + " -o %s",
+                1, Arrays.asList(""));
+        spec.disableShadowBCF();
+        final File vcf = executeTest("testMultipleGATKVersionsInVCF", spec).first.get(0);
+        final VCFCodec codec = new VCFCodec();
+        final VCFHeader header = (VCFHeader) codec.readActualHeader(codec.makeSourceFromStream(new FileInputStream(vcf)));
+
+        boolean foundHC = false;
+        boolean foundSV = false;
+        for ( final VCFHeaderLine line : header.getMetaDataInInputOrder() ) {
+            if ( line.getKey().equals(GATKVCFUtils.GATK_COMMAND_LINE_KEY) ) {
+                if ( line.toString().contains("HaplotypeCaller") ) {
+                    Assert.assertFalse(foundHC);
+                    foundHC = true;
+                }
+                if ( line.toString().contains("SelectVariants") ) {
+                    Assert.assertFalse(foundSV);
+                    foundSV = true;
+                }
+            }
+        }
+
+        Assert.assertTrue(foundHC, "Didn't find HaplotypeCaller command line header field");
+        Assert.assertTrue(foundSV, "Didn't find SelectVariants command line header field");
+    }
+
+    // --------------------------------------------------------------------------------
+    //
+    // Test that defaultBaseQualities actually works
+    //
+    // --------------------------------------------------------------------------------
+
+    public WalkerTestSpec testDefaultBaseQualities(final Integer value, final String md5) {
+        return new WalkerTestSpec("-T PrintReads -R " + b37KGReference + " -I " + privateTestDir + "/baseQualitiesToFix.bam -o %s"
+                + (value != null ? " --defaultBaseQualities " + value : ""),
+                1, Arrays.asList(md5));
+    }
+
+    @Test()
+    public void testDefaultBaseQualities20() {
+        executeTest("testDefaultBaseQualities20", testDefaultBaseQualities(20, "7d254a9d0ec59c66ee3e137f56f4c78f"));
+    }
+
+    @Test()
+    public void testDefaultBaseQualities30() {
+        executeTest("testDefaultBaseQualities30", testDefaultBaseQualities(30, "0f50def6cbbbd8ccd4739e2b3998e503"));
+    }
+
+    @Test(expectedExceptions = Exception.class)
+    public void testDefaultBaseQualitiesNoneProvided() {
+        executeTest("testDefaultBaseQualitiesNoneProvided", testDefaultBaseQualities(null, ""));
+    }
+
+    // --------------------------------------------------------------------------------
+    //
+    // Test engine-level cigar consolidation
+    //
+    // --------------------------------------------------------------------------------
+
+    @Test
+    public void testGATKEngineConsolidatesCigars() {
+        final WalkerTestSpec spec = new WalkerTestSpec(" -T PrintReads" +
+                                                       " -R " + b37KGReference +
+                                                       " -I " + privateTestDir + "zero_length_cigar_elements.bam" +
+                                                       " -o %s",
+                                                       1, Arrays.asList(""));  // No MD5s; we only want to check the cigar
+
+        final File outputBam = executeTest("testGATKEngineConsolidatesCigars", spec).first.get(0);
+        final SAMFileReader reader = new SAMFileReader(outputBam);
+        reader.setValidationStringency(ValidationStringency.SILENT);
+        reader.setSAMRecordFactory(new GATKSamRecordFactory());
+
+        final SAMRecord read = reader.iterator().next();
+        reader.close();
+
+        // Original cigar was 0M3M0M8M. Check that it's been consolidated after running through the GATK engine:
+        Assert.assertEquals(read.getCigarString(), "11M", "Cigar 0M3M0M8M not consolidated correctly by the engine");
+    }
+
+    // --------------------------------------------------------------------------------
+    //
+    // Test on-the-fly sample renaming
+    //
+    // --------------------------------------------------------------------------------
+
+    // On-the-fly sample renaming test case: one single-sample bam with multiple read groups
+    @Test
+    public void testOnTheFlySampleRenamingWithSingleBamFile() throws IOException {
+        final File sampleRenameMapFile = createTestSampleRenameMapFile(
+                Arrays.asList(privateTestDir + "CEUTrio.HiSeq.WGS.b37.NA12878.HEADERONLY.bam  myNewSampleName"));
+
+        final WalkerTestSpec spec = new WalkerTestSpec(" -T PrintReads" +
+                                                       " -R " + b37KGReference +
+                                                       " -I " + privateTestDir + "CEUTrio.HiSeq.WGS.b37.NA12878.HEADERONLY.bam" +
+                                                       " --sample_rename_mapping_file " + sampleRenameMapFile.getAbsolutePath() +
+                                                       " -o %s",
+                                                       1, Arrays.asList(""));  // No MD5s; we only want to check the read groups
+
+        final File outputBam = executeTest("testOnTheFlySampleRenamingWithSingleBamFile", spec).first.get(0);
+        final SAMFileReader reader = new SAMFileReader(outputBam);
+
+        for ( final SAMReadGroupRecord readGroup : reader.getFileHeader().getReadGroups() ) {
+            Assert.assertEquals(readGroup.getSample(), "myNewSampleName", String.format("Sample for read group %s not renamed correctly", readGroup.getId()));
+        }
+
+        reader.close();
+    }
+
+    // On-the-fly sample renaming test case: three single-sample bams with multiple read groups per bam
+    @Test
+    public void testOnTheFlySampleRenamingWithMultipleBamFiles() throws IOException {
+        final File sampleRenameMapFile = createTestSampleRenameMapFile(
+                Arrays.asList(privateTestDir + "CEUTrio.HiSeq.WGS.b37.NA12878.HEADERONLY.bam  newSampleFor12878",
+                              privateTestDir + "CEUTrio.HiSeq.WGS.b37.NA12891.HEADERONLY.bam  newSampleFor12891",
+                              privateTestDir + "CEUTrio.HiSeq.WGS.b37.NA12892.HEADERONLY.bam  newSampleFor12892"));
+
+        final Map<String, String> readGroupToNewSampleMap = new HashMap<>();
+        for ( String inputBamID : Arrays.asList("12878", "12891", "12892") ) {
+            final File inputBam = new File(privateTestDir + String.format("CEUTrio.HiSeq.WGS.b37.NA%s.HEADERONLY.bam", inputBamID));
+            final SAMFileReader inputBamReader = new SAMFileReader(inputBam);
+            final String newSampleName = String.format("newSampleFor%s", inputBamID);
+            for ( final SAMReadGroupRecord readGroup : inputBamReader.getFileHeader().getReadGroups() ) {
+                readGroupToNewSampleMap.put(readGroup.getId(), newSampleName);
+            }
+            inputBamReader.close();
+        }
+
+        final WalkerTestSpec spec = new WalkerTestSpec(" -T PrintReads" +
+                                                       " -R " + b37KGReference +
+                                                       " -I " + privateTestDir + "CEUTrio.HiSeq.WGS.b37.NA12878.HEADERONLY.bam" +
+                                                       " -I " + privateTestDir + "CEUTrio.HiSeq.WGS.b37.NA12891.HEADERONLY.bam" +
+                                                       " -I " + privateTestDir + "CEUTrio.HiSeq.WGS.b37.NA12892.HEADERONLY.bam" +
+                                                       " --sample_rename_mapping_file " + sampleRenameMapFile.getAbsolutePath() +
+                                                       " -o %s",
+                                                       1, Arrays.asList(""));  // No MD5s; we only want to check the read groups
+
+        final File outputBam = executeTest("testOnTheFlySampleRenamingWithMultipleBamFiles", spec).first.get(0);
+        final SAMFileReader outputBamReader = new SAMFileReader(outputBam);
+
+        int totalReadGroupsSeen = 0;
+        for ( final SAMReadGroupRecord readGroup : outputBamReader.getFileHeader().getReadGroups() ) {
+            Assert.assertEquals(readGroup.getSample(), readGroupToNewSampleMap.get(readGroup.getId()),
+                                String.format("Wrong sample for read group %s after on-the-fly renaming", readGroup.getId()));
+            totalReadGroupsSeen++;
+        }
+
+        Assert.assertEquals(totalReadGroupsSeen, readGroupToNewSampleMap.size(), "Wrong number of read groups encountered in output bam file");
+
+        outputBamReader.close();
+    }
+
+    // On-the-fly sample renaming test case: three single-sample bams with multiple read groups per bam,
+    //                                       performing renaming in only SOME of the bams
+    @Test
+    public void testOnTheFlySampleRenamingWithMultipleBamFilesPartialRename() throws IOException {
+        // Rename samples for NA12878 and NA12892, but not for NA12891
+        final File sampleRenameMapFile = createTestSampleRenameMapFile(
+                Arrays.asList(privateTestDir + "CEUTrio.HiSeq.WGS.b37.NA12878.HEADERONLY.bam  newSampleFor12878",
+                              privateTestDir + "CEUTrio.HiSeq.WGS.b37.NA12892.HEADERONLY.bam  newSampleFor12892"));
+
+        final Map<String, String> readGroupToNewSampleMap = new HashMap<>();
+        for ( String inputBamID : Arrays.asList("12878", "12891", "12892") ) {
+            final File inputBam = new File(privateTestDir + String.format("CEUTrio.HiSeq.WGS.b37.NA%s.HEADERONLY.bam", inputBamID));
+            final SAMFileReader inputBamReader = new SAMFileReader(inputBam);
+
+            // Special-case NA12891, which we're not renaming:
+            final String newSampleName = inputBamID.equals("12891") ? "NA12891" : String.format("newSampleFor%s", inputBamID);
+
+            for ( final SAMReadGroupRecord readGroup : inputBamReader.getFileHeader().getReadGroups() ) {
+                readGroupToNewSampleMap.put(readGroup.getId(), newSampleName);
+            }
+            inputBamReader.close();
+        }
+
+        final WalkerTestSpec spec = new WalkerTestSpec(" -T PrintReads" +
+                                                       " -R " + b37KGReference +
+                                                       " -I " + privateTestDir + "CEUTrio.HiSeq.WGS.b37.NA12878.HEADERONLY.bam" +
+                                                       " -I " + privateTestDir + "CEUTrio.HiSeq.WGS.b37.NA12891.HEADERONLY.bam" +
+                                                       " -I " + privateTestDir + "CEUTrio.HiSeq.WGS.b37.NA12892.HEADERONLY.bam" +
+                                                       " --sample_rename_mapping_file " + sampleRenameMapFile.getAbsolutePath() +
+                                                       " -o %s",
+                                                       1, Arrays.asList(""));  // No MD5s; we only want to check the read groups
+
+        final File outputBam = executeTest("testOnTheFlySampleRenamingWithMultipleBamFilesPartialRename", spec).first.get(0);
+        final SAMFileReader outputBamReader = new SAMFileReader(outputBam);
+
+        int totalReadGroupsSeen = 0;
+        for ( final SAMReadGroupRecord readGroup : outputBamReader.getFileHeader().getReadGroups() ) {
+            Assert.assertEquals(readGroup.getSample(), readGroupToNewSampleMap.get(readGroup.getId()),
+                                String.format("Wrong sample for read group %s after on-the-fly renaming", readGroup.getId()));
+            totalReadGroupsSeen++;
+        }
+
+        Assert.assertEquals(totalReadGroupsSeen, readGroupToNewSampleMap.size(), "Wrong number of read groups encountered in output bam file");
+
+        outputBamReader.close();
+    }
+
+    // On-the-fly sample renaming test case: two single-sample bams with read group collisions
+    @Test
+    public void testOnTheFlySampleRenamingWithReadGroupCollisions() throws IOException {
+        final File sampleRenameMapFile = createTestSampleRenameMapFile(
+                Arrays.asList(privateTestDir + "CEUTrio.HiSeq.WGS.b37.NA12878.HEADERONLY.bam  newSampleFor12878",
+                              privateTestDir + "CEUTrio.HiSeq.WGS.b37.READ_GROUP_COLLISIONS_WITH_NA12878.HEADERONLY.bam  newSampleForNot12878"));
+
+        final Set<String> na12878ReadGroups = new HashSet<>();
+        final SAMFileReader inputBamReader = new SAMFileReader(new File(privateTestDir + "CEUTrio.HiSeq.WGS.b37.NA12878.HEADERONLY.bam"));
+        for ( final SAMReadGroupRecord readGroup : inputBamReader.getFileHeader().getReadGroups() ) {
+            na12878ReadGroups.add(readGroup.getId());
+        }
+        inputBamReader.close();
+
+        final WalkerTestSpec spec = new WalkerTestSpec(" -T PrintReads" +
+                                                       " -R " + b37KGReference +
+                                                       " -I " + privateTestDir + "CEUTrio.HiSeq.WGS.b37.NA12878.HEADERONLY.bam" +
+                                                       " -I " + privateTestDir + "CEUTrio.HiSeq.WGS.b37.READ_GROUP_COLLISIONS_WITH_NA12878.HEADERONLY.bam" +
+                                                       " --sample_rename_mapping_file " + sampleRenameMapFile.getAbsolutePath() +
+                                                       " -o %s",
+                                                       1, Arrays.asList(""));  // No MD5s; we only want to check the read groups
+
+        final File outputBam = executeTest("testOnTheFlySampleRenamingWithReadGroupCollisions", spec).first.get(0);
+        final SAMFileReader outputBamReader = new SAMFileReader(outputBam);
+
+        int totalReadGroupsSeen = 0;
+        for ( final SAMReadGroupRecord readGroup : outputBamReader.getFileHeader().getReadGroups() ) {
+            String expectedSampleName = "";
+            if ( na12878ReadGroups.contains(readGroup.getId()) ) {
+                expectedSampleName = "newSampleFor12878";
+            }
+            else {
+                expectedSampleName = "newSampleForNot12878";
+            }
+
+            Assert.assertEquals(readGroup.getSample(), expectedSampleName,
+                                String.format("Wrong sample for read group %s after on-the-fly renaming", readGroup.getId()));
+            totalReadGroupsSeen++;
+        }
+
+        Assert.assertEquals(totalReadGroupsSeen, na12878ReadGroups.size() * 2, "Wrong number of read groups encountered in output bam file");
+
+        outputBamReader.close();
+    }
+
+    // On-the-fly sample renaming test case: a multi-sample bam (this should generate a UserException)
+    @Test
+    public void testOnTheFlySampleRenamingWithMultiSampleBam() throws IOException {
+        final File sampleRenameMapFile = createTestSampleRenameMapFile(
+                Arrays.asList(privateTestDir + "CEUTrio.HiSeq.WGS.b37.MERGED.HEADERONLY.bam  myNewSampleName"));
+
+        final WalkerTestSpec spec = new WalkerTestSpec(" -T PrintReads" +
+                                                       " -R " + b37KGReference +
+                                                       " -I " + privateTestDir + "CEUTrio.HiSeq.WGS.b37.MERGED.HEADERONLY.bam" +
+                                                       " --sample_rename_mapping_file " + sampleRenameMapFile.getAbsolutePath() +
+                                                       " -o %s",
+                                                       1,
+                                                       UserException.class); // expecting a UserException here
+
+        executeTest("testOnTheFlySampleRenamingWithMultiSampleBam", spec);
+    }
+
+    // On-the-fly sample renaming test case: ensure that walkers can see the remapped sample names in individual reads
+    @Test
+    public void testOnTheFlySampleRenamingVerifyWalkerSeesNewSamplesInReads() throws IOException {
+        final File sampleRenameMapFile = createTestSampleRenameMapFile(
+                Arrays.asList(privateTestDir + "NA12878.HiSeq.b37.chr20.10_11mb.bam  myNewSampleName"));
+
+        final WalkerTestSpec spec = new WalkerTestSpec(" -T OnTheFlySampleRenamingVerifyingTestWalker" +
+                                                       " -R " + b37KGReference +
+                                                       " -I " + privateTestDir + "NA12878.HiSeq.b37.chr20.10_11mb.bam" +
+                                                       " --sample_rename_mapping_file " + sampleRenameMapFile.getAbsolutePath() +
+                                                       " --newSampleName myNewSampleName" +
+                                                       " -L 20:10000000-10001000",
+                                                       1, Arrays.asList(""));
+
+        // Test is a success if our custom walker doesn't throw an exception
+        executeTest("testOnTheFlySampleRenamingVerifyWalkerSeesNewSamplesInReads", spec);
+    }
+
+    @Test
+    public void testOnTheFlySampleRenamingSingleSampleVCF() throws IOException {
+        final File sampleRenameMapFile = createTestSampleRenameMapFile(
+                Arrays.asList(privateTestDir + "NA12878.WGS.b37.chr20.firstMB.vcf  newSampleForNA12878"));
+
+        final WalkerTestSpec spec = new WalkerTestSpec(" -T CombineVariants" +
+                " -R " + b37KGReference +
+                " -V " + privateTestDir + "NA12878.WGS.b37.chr20.firstMB.vcf" +
+                " --sample_rename_mapping_file " + sampleRenameMapFile.getAbsolutePath() +
+                " -o %s",
+                1,
+                Arrays.asList("")); // No MD5s -- we will inspect the output file manually
+
+        final File outputVCF = executeTest("testOnTheFlySampleRenamingSingleSampleVCF", spec).first.get(0);
+        verifySampleRenaming(outputVCF, "newSampleForNA12878");
+    }
+
+    private void verifySampleRenaming( final File outputVCF, final String newSampleName ) throws IOException {
+        final Pair<VCFHeader, GATKVCFUtils.VCIterable<LineIterator>> headerAndVCIter = GATKVCFUtils.readAllVCs(outputVCF, new VCFCodec());
+        final VCFHeader header = headerAndVCIter.getFirst();
+        final GATKVCFUtils.VCIterable<LineIterator> iter = headerAndVCIter.getSecond();
+
+        // Verify that sample renaming occurred at both the header and record levels (checking only the first 10 records):
+
+        Assert.assertEquals(header.getGenotypeSamples().size(), 1, "Wrong number of samples in output vcf header");
+        Assert.assertEquals(header.getGenotypeSamples().get(0), newSampleName, "Wrong sample name in output vcf header");
+
+        int recordCount = 0;
+        while ( iter.hasNext() && recordCount < 10 ) {
+            final VariantContext vcfRecord = iter.next();
+            Assert.assertEquals(vcfRecord.getSampleNames().size(), 1, "Wrong number of samples in output vcf record");
+            Assert.assertEquals(vcfRecord.getSampleNames().iterator().next(), newSampleName, "Wrong sample name in output vcf record");
+            recordCount++;
+        }
+    }
+
+    @Test
+    public void testOnTheFlySampleRenamingVerifyWalkerSeesNewSamplesInVCFRecords() throws Exception {
+        final File sampleRenameMapFile = createTestSampleRenameMapFile(
+                Arrays.asList(privateTestDir + "samplerenametest_single_sample_gvcf.vcf    FOOSAMPLE"));
+
+        final WalkerTestSpec spec = new WalkerTestSpec(" -T OnTheFlySampleRenamingVerifyingRodWalker" +
+                " -R " + hg19Reference +
+                " -V " + privateTestDir + "samplerenametest_single_sample_gvcf.vcf" +
+                " --sample_rename_mapping_file " + sampleRenameMapFile.getAbsolutePath() +
+                " --expectedSampleName FOOSAMPLE" +
+                " -o %s",
+                1,
+                Arrays.asList("")); // No MD5s -- custom walker will throw an exception if there's a problem
+
+        executeTest("testOnTheFlySampleRenamingVerifyWalkerSeesNewSamplesInVCFRecords", spec);
+    }
+
+    @Test
+    public void testOnTheFlySampleRenamingMultiSampleVCF() throws Exception {
+        final File sampleRenameMapFile = createTestSampleRenameMapFile(
+                Arrays.asList(privateTestDir + "vcf/vcfWithGenotypes.vcf  badSample"));
+
+        final WalkerTestSpec spec = new WalkerTestSpec(" -T CombineVariants" +
+                " -R " + b37KGReference +
+                " -V " + privateTestDir + "vcf/vcfWithGenotypes.vcf" +
+                " --sample_rename_mapping_file " + sampleRenameMapFile.getAbsolutePath() +
+                " -o %s",
+                1,
+                UserException.class); // expecting a UserException here
+
+        executeTest("testOnTheFlySampleRenamingMultiSampleVCF", spec);
+    }
+
+    @Test
+    public void testOnTheFlySampleRenamingSitesOnlyVCF() throws Exception {
+        final File sampleRenameMapFile = createTestSampleRenameMapFile(
+                Arrays.asList(privateTestDir + "vcf/vcfWithoutGenotypes.vcf  badSample"));
+
+        final WalkerTestSpec spec = new WalkerTestSpec(" -T CombineVariants" +
+                " -R " + b37KGReference +
+                " -V " + privateTestDir + "vcf/vcfWithoutGenotypes.vcf" +
+                " --sample_rename_mapping_file " + sampleRenameMapFile.getAbsolutePath() +
+                " -o %s",
+                1,
+                UserException.class); // expecting a UserException here
+
+        executeTest("testOnTheFlySampleRenamingSitesOnlyVCF", spec);
+    }
+
+    private File createTestSampleRenameMapFile( final List<String> contents ) throws IOException {
+        final File mapFile = createTempFile("TestSampleRenameMapFile", ".tmp");
+        final PrintWriter writer = new PrintWriter(mapFile);
+
+        for ( final String line : contents ) {
+            writer.println(line);
+        }
+        writer.close();
+
+        return mapFile;
+    }
+
+    public static class OnTheFlySampleRenamingVerifyingTestWalker extends ReadWalker<Integer, Integer> {
+        @Argument(fullName = "newSampleName", shortName = "newSampleName", doc = "", required = true)
+        String newSampleName = null;
+
+        public Integer map(ReferenceContext ref, GATKSAMRecord read, RefMetaDataTracker metaDataTracker) {
+            if ( ! newSampleName.equals(read.getReadGroup().getSample()) ) {
+                throw new IllegalStateException(String.format("Encountered read with the wrong sample name. Expected %s found %s",
+                                                              newSampleName, read.getReadGroup().getSample()));
+            }
+
+            return 1;
+        }
+
+        public Integer reduceInit() { return 0; }
+        public Integer reduce(Integer value, Integer sum) { return value + sum; }
+    }
+
+    public static class OnTheFlySampleRenamingVerifyingRodWalker extends RodWalker<Integer, Integer> {
+        @Argument(fullName = "expectedSampleName", shortName = "expectedSampleName", doc = "", required = true)
+        String expectedSampleName = null;
+
+        @Output
+        PrintStream out;
+
+        @Input(fullName="variant", shortName = "V", doc="Input VCF file", required=true)
+        public RodBinding<VariantContext> variants;
+
+        public Integer map( RefMetaDataTracker tracker, ReferenceContext ref, AlignmentContext context ) {
+            if ( tracker == null ) {
+                return 0;
+            }
+
+            for ( final VariantContext vc : tracker.getValues(variants, context.getLocation()) ) {
+                if ( vc.getSampleNames().size() != 1 ) {
+                    throw new IllegalStateException("Encountered a vcf record with num samples != 1");
+                }
+
+                final String actualSampleName = vc.getSampleNames().iterator().next();
+                if ( ! expectedSampleName.equals(actualSampleName)) {
+                    throw new IllegalStateException(String.format("Encountered vcf record with wrong sample name. Expected %s found %s",
+                                                                  expectedSampleName, actualSampleName));
+                }
+            }
+
+            return 1;
+        }
+
+        public Integer reduceInit() {
+            return 0;
+        }
+
+        public Integer reduce(Integer counter, Integer sum) {
+            return counter + sum;
+        }
+    }
+
+    // --------------------------------------------------------------------------------
+    //
+    // Test output file-specific options
+    //
+    // --------------------------------------------------------------------------------
+
+    //Returns the output file
+    private File testBAMFeatures(final String args, final String md5) {
+        WalkerTestSpec spec = new WalkerTestSpec("-T PrintReads -R " + b37KGReference +
+                " -I " + privateTestDir + "NA20313.highCoverageRegion.bam"
+                + " --no_pg_tag -o %s " + args,
+                1, Arrays.asList(".bam"), Arrays.asList(md5));
+        return executeTest("testBAMFeatures: "+args, spec).first.get(0);
+    }
+
+    @Test
+    public void testSAMWriterFeatures() {
+        testBAMFeatures("-compress 0", "bb4b55b1f80423970bb9384cbf0d8793");
+        testBAMFeatures("-compress 9", "b85ee1636d62e1bb8ed65a245c307167");
+        testBAMFeatures("-simplifyBAM", "38f9c30a27dfbc085a2ff52a1617d579");
+
+        //Validate MD5
+        final String expectedMD5 = "6627b9ea33293a0083983feb94948c1d";
+        final File md5Target = testBAMFeatures("--generate_md5", expectedMD5);
+        final File md5File = new File(md5Target.getAbsoluteFile() + ".md5");
+        md5File.deleteOnExit();
+        Assert.assertTrue(md5File.exists(), "MD5 wasn't created");
+        try {
+            String md5 = new BufferedReader(new FileReader(md5File)).readLine();
+            Assert.assertEquals(md5, expectedMD5, "Generated MD5 doesn't match expected");
+        } catch (IOException e) {
+            Assert.fail("Can't parse MD5 file", e);
+        }
+
+        //Validate that index isn't created
+        final String unindexedBAM = testBAMFeatures("--disable_bam_indexing", expectedMD5).getAbsolutePath();
+        Assert.assertTrue(!(new File(unindexedBAM+".bai").exists()) &&
+                          !(new File(unindexedBAM.replace(".bam", ".bai")).exists()),
+                          "BAM index was created even though it was disabled");
+    }
+
+    private void testVCFFeatures(final String args, final String md5) {
+        WalkerTestSpec spec = new WalkerTestSpec("-T SelectVariants -R " + b37KGReference +
+                " -V " + privateTestDir + "CEUtrioTest.vcf"
+                + " --no_cmdline_in_header -o %s " + args,
+                1, Arrays.asList(md5));
+        executeTest("testVCFFeatures: "+args, spec);
+    }
+
+    private void testVCFFormatHandling(final boolean writeFullFormat, final String md5) {
+        WalkerTestSpec spec = new WalkerTestSpec("-T SelectVariants -R " + b37KGReference +
+                " -V " + privateTestDir + "ILLUMINA.wex.broad_phase2_baseline.20111114.both.exome.genotypes.1000.vcf"
+                + " --no_cmdline_in_header -o %s "
+                + " --fullyDecode " //Without this parameter, the FORMAT fields will be emitted unchanged.  Oops
+                + (writeFullFormat ? "-writeFullFormat" : "") ,
+                1, Arrays.asList(md5));
+        executeTest("testVCFFormatHandling: "+(writeFullFormat ? "Untrimmed" : "Trimmed"), spec);
+    }
+
+    @Test
+    public void testVCFWriterFeatures() {
+        testVCFFeatures("--sites_only", "94bf1f2c0946e933515e4322323a5716");
+        testVCFFeatures("--bcf", "03f2d6988f54a332da48803c78f9c4b3");
+        testVCFFormatHandling(true, "2b0fa660b0cef4b0f45a10febb453b6c");
+        testVCFFormatHandling(false, "5960311fdd9ee6db88587efaaf4055a0");
+    }
+}
\ No newline at end of file
diff --git a/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/engine/GenomeAnalysisEngineUnitTest.java b/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/engine/GenomeAnalysisEngineUnitTest.java
new file mode 100644
index 0000000..ff60ae3
--- /dev/null
+++ b/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/engine/GenomeAnalysisEngineUnitTest.java
@@ -0,0 +1,273 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.engine;
+
+import org.broadinstitute.gatk.utils.BaseTest;
+import org.broadinstitute.gatk.utils.commandline.Tags;
+import org.broadinstitute.gatk.engine.arguments.GATKArgumentCollection;
+import org.broadinstitute.gatk.engine.datasources.reads.SAMReaderID;
+import org.broadinstitute.gatk.engine.iterators.ReadTransformer;
+import org.broadinstitute.gatk.engine.walkers.Walker;
+import org.broadinstitute.gatk.tools.walkers.qc.CountReads;
+import org.broadinstitute.gatk.tools.walkers.readutils.PrintReads;
+import org.broadinstitute.gatk.utils.GenomeLocParser;
+import org.broadinstitute.gatk.utils.GenomeLocSortedSet;
+import org.broadinstitute.gatk.utils.exceptions.UserException;
+import org.broadinstitute.gatk.utils.sam.ArtificialSAMUtils;
+import org.broadinstitute.gatk.utils.sam.GATKSAMRecord;
+import org.testng.Assert;
+import org.testng.annotations.DataProvider;
+import org.testng.annotations.Test;
+
+import java.io.File;
+import java.io.IOException;
+import java.io.PrintWriter;
+import java.util.*;
+
+/**
+ * Tests selected functionality in the GenomeAnalysisEngine class
+ */
+public class GenomeAnalysisEngineUnitTest extends BaseTest {
+
+    @Test(expectedExceptions=UserException.class)
+    public void testEmptySamFileListHandling() throws Exception {
+        GenomeAnalysisEngine testEngine = new GenomeAnalysisEngine();
+        testEngine.setWalker(new CountReads()); //generalizable to any walker requiring reads
+
+        //supply command line args so validateSuppliedReads() knows whether reads were passed in
+        GATKArgumentCollection testArgs = new GATKArgumentCollection();
+        testArgs.samFiles.add("empty.list");
+        testEngine.setArguments(testArgs);
+
+        //represents the empty list of samFiles read in from empty.list by CommandLineExecutable
+        Collection<SAMReaderID> samFiles = new ArrayList<SAMReaderID>();
+
+        testEngine.setSAMFileIDs(samFiles);
+        testEngine.validateSuppliedReads();
+    }
+
+    @Test(expectedExceptions=UserException.class)
+    public void testDuplicateSamFileHandlingSingleDuplicate() throws Exception {
+        GenomeAnalysisEngine testEngine = new GenomeAnalysisEngine();
+
+        Collection<SAMReaderID> samFiles = new ArrayList<SAMReaderID>();
+        samFiles.add(new SAMReaderID(new File(publicTestDir + "exampleBAM.bam"), new Tags()));
+        samFiles.add(new SAMReaderID(new File(publicTestDir + "exampleBAM.bam"), new Tags()));
+
+        testEngine.setSAMFileIDs(samFiles);
+        testEngine.checkForDuplicateSamFiles();
+    }
+
+    @Test(expectedExceptions=UserException.class)
+    public void testDuplicateSamFileHandlingMultipleDuplicates() throws Exception {
+        GenomeAnalysisEngine testEngine = new GenomeAnalysisEngine();
+
+        Collection<SAMReaderID> samFiles = new ArrayList<SAMReaderID>();
+        samFiles.add(new SAMReaderID(new File(publicTestDir + "exampleBAM.bam"), new Tags()));
+        samFiles.add(new SAMReaderID(new File(publicTestDir + "exampleNORG.bam"), new Tags()));
+        samFiles.add(new SAMReaderID(new File(publicTestDir + "exampleBAM.bam"),  new Tags()));
+        samFiles.add(new SAMReaderID(new File(publicTestDir + "exampleNORG.bam"), new Tags()));
+
+        testEngine.setSAMFileIDs(samFiles);
+        testEngine.checkForDuplicateSamFiles();
+    }
+
+    @Test(expectedExceptions=UserException.class)
+    public void testDuplicateSamFileHandlingAbsoluteVsRelativePath() {
+        GenomeAnalysisEngine testEngine = new GenomeAnalysisEngine();
+
+        final File relativePathToBAMFile = new File(publicTestDir + "exampleBAM.bam");
+        final File absolutePathToBAMFile = new File(relativePathToBAMFile.getAbsolutePath());
+        Collection<SAMReaderID> samFiles = new ArrayList<SAMReaderID>();
+        samFiles.add(new SAMReaderID(relativePathToBAMFile, new Tags()));
+        samFiles.add(new SAMReaderID(absolutePathToBAMFile, new Tags()));
+
+        testEngine.setSAMFileIDs(samFiles);
+        testEngine.checkForDuplicateSamFiles();
+    }
+
+    @Test
+    public void testEmptyIntervalSetHandling() throws Exception {
+        GenomeLocParser genomeLocParser = new GenomeLocParser(ArtificialSAMUtils.createArtificialSamHeader(1, 1, 1000).getSequenceDictionary());
+
+        GenomeAnalysisEngine testEngine = new GenomeAnalysisEngine();
+
+        testEngine.setWalker(new PrintReads());
+        testEngine.setIntervals(new GenomeLocSortedSet(genomeLocParser));
+
+        testEngine.validateSuppliedIntervals();
+    }
+
+    @Test
+    public void testLoadWellFormedSampleRenameMapFile() throws IOException {
+        final File mapFile = createTestSampleRenameMapFile(Arrays.asList("/foo/bar/first.bam    newSample1",
+                                                                         "/foo/bar/second.bam        newSample2",
+                                                                         "/foo/bar2/third.bam newSample3",
+                                                                         "/foo/bar2/fourth.bam new sample    4",
+                                                                         "/foo/bar2/fifth.bam     new   sample     5    "));
+        final GenomeAnalysisEngine engine = new GenomeAnalysisEngine();
+        final Map<String, String> renameMap = engine.loadSampleRenameMap(mapFile);
+
+        Assert.assertEquals(renameMap.size(), 5, "Sample rename map was wrong size after loading from file");
+
+        final Iterator<String> expectedResultsIterator = Arrays.asList(
+                        "/foo/bar/first.bam",   "newSample1", 
+                        "/foo/bar/second.bam",  "newSample2", 
+                        "/foo/bar2/third.bam",  "newSample3",
+                        "/foo/bar2/fourth.bam", "new sample    4",
+                        "/foo/bar2/fifth.bam",  "new   sample     5"
+        ).iterator();
+        while ( expectedResultsIterator.hasNext() ) {
+            final String expectedKey = expectedResultsIterator.next();
+            final String expectedValue = expectedResultsIterator.next();
+
+            Assert.assertNotNull(renameMap.get(expectedKey), String.format("Entry for %s not found in sample rename map", expectedKey));
+            Assert.assertEquals(renameMap.get(expectedKey), expectedValue, "Wrong value in sample rename map for " + expectedKey);
+        }
+    }
+
+    @DataProvider(name = "MalformedSampleRenameMapFileDataProvider")
+    public Object[][] generateMalformedSampleRenameMapFiles() throws IOException {
+        final List<Object[]> tests = new ArrayList<Object[]>();
+
+        tests.add(new Object[]{"testLoadSampleRenameMapFileNonExistentFile",
+                               new File("/foo/bar/nonexistent")});
+        tests.add(new Object[]{"testLoadSampleRenameMapFileMalformedLine",
+                               createTestSampleRenameMapFile(Arrays.asList("/path/to/foo.bam"))});
+        tests.add(new Object[]{"testLoadSampleRenameMapFileNonAbsoluteBamPath",
+                               createTestSampleRenameMapFile(Arrays.asList("relative/path/to/foo.bam newSample"))});
+        tests.add(new Object[]{"testLoadSampleRenameMapFileDuplicateBamPath",
+                               createTestSampleRenameMapFile(Arrays.asList("/path/to/dupe.bam newSample1",
+                                                                           "/path/to/dupe.bam newSample2"))});
+        tests.add(new Object[]{"testLoadSampleRenameMapFileTabInSampleName",
+                               createTestSampleRenameMapFile(Arrays.asList("/path/to/stuff.bam some wonky\tsample   "))});
+        return tests.toArray(new Object[][]{});
+    }
+
+    @Test(dataProvider = "MalformedSampleRenameMapFileDataProvider", expectedExceptions = UserException.class)
+    public void testLoadMalformedSampleRenameMapFile( final String testName, final File mapFile ) {
+        logger.info("Executing test " + testName);
+
+        final GenomeAnalysisEngine engine = new GenomeAnalysisEngine();
+        final Map<String, String> renameMap = engine.loadSampleRenameMap(mapFile);
+    }
+
+    private File createTestSampleRenameMapFile( final List<String> contents ) throws IOException {
+        final File mapFile = createTempFile("TestSampleRenameMapFile", ".tmp");
+        final PrintWriter writer = new PrintWriter(mapFile);
+
+        for ( final String line : contents ) {
+            writer.println(line);
+        }
+        writer.close();
+
+        return mapFile;
+    }
+
+    ///////////////////////////////////////////////////
+    // Test the ReadTransformer ordering enforcement //
+    ///////////////////////////////////////////////////
+
+    public static class TestReadTransformer extends ReadTransformer {
+
+        private OrderingConstraint orderingConstraint = OrderingConstraint.DO_NOT_CARE;
+        private boolean enabled;
+
+        protected TestReadTransformer(final OrderingConstraint orderingConstraint) {
+            this.orderingConstraint = orderingConstraint;
+            enabled = true;
+        }
+
+        // need this because PackageUtils will pick up this class as a possible ReadTransformer
+        protected TestReadTransformer() {
+            enabled = false;
+        }
+
+        @Override
+        public OrderingConstraint getOrderingConstraint() { return orderingConstraint; }
+
+        @Override
+        public ApplicationTime initializeSub(final GenomeAnalysisEngine engine, final Walker walker) { return ApplicationTime.HANDLED_IN_WALKER; }
+
+        @Override
+        public boolean enabled() { return enabled; }
+
+        @Override
+        public GATKSAMRecord apply(final GATKSAMRecord read) { return read; }
+
+    }
+
+    @DataProvider(name = "ReadTransformerData")
+    public Object[][] makeReadTransformerData() {
+        List<Object[]> tests = new ArrayList<Object[]>();
+
+        for ( final ReadTransformer.OrderingConstraint orderingConstraint1 : ReadTransformer.OrderingConstraint.values() ) {
+            for ( final ReadTransformer.OrderingConstraint orderingConstraint2 : ReadTransformer.OrderingConstraint.values() ) {
+                for ( final ReadTransformer.OrderingConstraint orderingConstraint3 : ReadTransformer.OrderingConstraint.values() ) {
+                    tests.add(new Object[]{orderingConstraint1, orderingConstraint2, orderingConstraint3});
+                }
+            }
+        }
+
+        return tests.toArray(new Object[][]{});
+    }
+
+    @Test(dataProvider = "ReadTransformerData")
+    public void testReadTransformer(final ReadTransformer.OrderingConstraint oc1, final ReadTransformer.OrderingConstraint oc2, final ReadTransformer.OrderingConstraint oc3) {
+
+        final GenomeAnalysisEngine testEngine = new GenomeAnalysisEngine();
+        final List<ReadTransformer> readTransformers = new ArrayList<ReadTransformer>(3);
+        readTransformers.add(new TestReadTransformer(oc1));
+        readTransformers.add(new TestReadTransformer(oc2));
+        readTransformers.add(new TestReadTransformer(oc3));
+
+        final boolean shouldThrowException = numWithConstraint(ReadTransformer.OrderingConstraint.MUST_BE_FIRST, oc1, oc2, oc3) > 1 ||
+                numWithConstraint(ReadTransformer.OrderingConstraint.MUST_BE_LAST, oc1, oc2, oc3) > 1;
+
+        try {
+            testEngine.setReadTransformers(readTransformers);
+
+            Assert.assertFalse(shouldThrowException);
+            Assert.assertEquals(testEngine.getReadTransformers().size(), 3);
+
+            Assert.assertTrue(testEngine.getReadTransformers().get(1).getOrderingConstraint() != ReadTransformer.OrderingConstraint.MUST_BE_FIRST);
+            Assert.assertTrue(testEngine.getReadTransformers().get(2).getOrderingConstraint() != ReadTransformer.OrderingConstraint.MUST_BE_FIRST);
+            Assert.assertTrue(testEngine.getReadTransformers().get(0).getOrderingConstraint() != ReadTransformer.OrderingConstraint.MUST_BE_LAST);
+            Assert.assertTrue(testEngine.getReadTransformers().get(1).getOrderingConstraint() != ReadTransformer.OrderingConstraint.MUST_BE_LAST);
+        } catch (UserException.IncompatibleReadFiltersException e) {
+            Assert.assertTrue(shouldThrowException);
+        }
+    }
+
+    private int numWithConstraint(final ReadTransformer.OrderingConstraint target, final ReadTransformer.OrderingConstraint... constraints ) {
+        int count = 0;
+        for ( final ReadTransformer.OrderingConstraint constraint : constraints ) {
+            if ( constraint == target )
+                count++;
+        }
+        return count;
+    }
+}
diff --git a/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/engine/MaxRuntimeIntegrationTest.java b/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/engine/MaxRuntimeIntegrationTest.java
new file mode 100644
index 0000000..27b6c1c
--- /dev/null
+++ b/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/engine/MaxRuntimeIntegrationTest.java
@@ -0,0 +1,151 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.engine;
+
+import org.broadinstitute.gatk.engine.walkers.WalkerTest;
+import org.broadinstitute.gatk.utils.commandline.Argument;
+import org.broadinstitute.gatk.utils.commandline.Output;
+import org.broadinstitute.gatk.engine.contexts.AlignmentContext;
+import org.broadinstitute.gatk.engine.contexts.ReferenceContext;
+import org.broadinstitute.gatk.engine.refdata.RefMetaDataTracker;
+import org.broadinstitute.gatk.engine.walkers.LocusWalker;
+import org.broadinstitute.gatk.utils.SimpleTimer;
+import org.testng.Assert;
+import org.testng.annotations.DataProvider;
+import org.testng.annotations.Test;
+
+import java.io.BufferedReader;
+import java.io.File;
+import java.io.FileReader;
+import java.io.PrintStream;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+import java.util.concurrent.TimeUnit;
+
+/**
+ *
+ */
+public class MaxRuntimeIntegrationTest extends WalkerTest {
+    public static class SleepingWalker extends LocusWalker<Integer, Integer> {
+        @Output PrintStream out;
+
+        @Argument(fullName="sleepTime",shortName="sleepTime",doc="x", required=false)
+        public int sleepTime = 100;
+
+        @Override
+        public Integer map(RefMetaDataTracker tracker, ReferenceContext ref, AlignmentContext context) {
+            try {Thread.sleep(sleepTime);} catch (InterruptedException e) {};
+            return 1;
+        }
+
+        @Override public Integer reduceInit() { return 0; }
+        @Override public Integer reduce(Integer value, Integer sum) { return sum + value; }
+
+        @Override
+        public void onTraversalDone(Integer result) {
+            out.println(result);
+        }
+    }
+
+    private static final long STARTUP_TIME = TimeUnit.NANOSECONDS.convert(60, TimeUnit.SECONDS);
+
+    private class MaxRuntimeTestProvider extends TestDataProvider {
+        final long maxRuntime;
+        final TimeUnit unit;
+
+        public MaxRuntimeTestProvider(final long maxRuntime, final TimeUnit unit) {
+            super(MaxRuntimeTestProvider.class);
+            this.maxRuntime = maxRuntime;
+            this.unit = unit;
+            setName(String.format("Max runtime test : %d of %s", maxRuntime, unit));
+        }
+
+        public long expectedMaxRuntimeNano() {
+            return TimeUnit.NANOSECONDS.convert(maxRuntime, unit) + STARTUP_TIME;
+        }
+    }
+
+    @DataProvider(name = "MaxRuntimeProvider")
+    public Object[][] makeMaxRuntimeProvider() {
+        for ( final TimeUnit requestedUnits : Arrays.asList(TimeUnit.NANOSECONDS, TimeUnit.MILLISECONDS, TimeUnit.SECONDS, TimeUnit.MINUTES) )
+            new MaxRuntimeTestProvider(requestedUnits.convert(30, TimeUnit.SECONDS), requestedUnits);
+
+        return MaxRuntimeTestProvider.getTests(MaxRuntimeTestProvider.class);
+    }
+
+    //
+    // Loop over errors to throw, make sure they are the errors we get back from the engine, regardless of NT type
+    //
+    @Test(enabled = true, dataProvider = "MaxRuntimeProvider", timeOut = 120 * 1000)
+    public void testMaxRuntime(final MaxRuntimeTestProvider cfg) {
+        WalkerTest.WalkerTestSpec spec = new WalkerTest.WalkerTestSpec(
+                "-T PrintReads -R " + hg18Reference
+                        + " -I " + validationDataLocation + "NA12878.WEx.downsampled20x.bam -o /dev/null"
+                        + " -maxRuntime " + cfg.maxRuntime + " -maxRuntimeUnits " + cfg.unit, 0,
+                Collections.<String>emptyList());
+        final SimpleTimer timer = new SimpleTimer().start();
+        executeTest("Max runtime " + cfg, spec);
+        final long actualRuntimeNano = timer.getElapsedTimeNano();
+
+        Assert.assertTrue(actualRuntimeNano < cfg.expectedMaxRuntimeNano(),
+                "Actual runtime " + TimeUnit.SECONDS.convert(actualRuntimeNano, TimeUnit.NANOSECONDS)
+                        + " exceeded max. tolerated runtime " + TimeUnit.SECONDS.convert(cfg.expectedMaxRuntimeNano(), TimeUnit.NANOSECONDS)
+                        + " given requested runtime " + cfg.maxRuntime + " " + cfg.unit);
+    }
+
+    @DataProvider(name = "SubshardProvider")
+    public Object[][] makeSubshardProvider() {
+        List<Object[]> tests = new ArrayList<Object[]>();
+
+        // this functionality can be adapted to provide input data for whatever you might want in your data
+        tests.add(new Object[]{10});
+        tests.add(new Object[]{100});
+        tests.add(new Object[]{500});
+        tests.add(new Object[]{1000});
+        tests.add(new Object[]{2000});
+
+        return tests.toArray(new Object[][]{});
+    }
+
+    @Test(enabled = true, dataProvider = "SubshardProvider", timeOut = 120 * 1000)
+    public void testSubshardTimeout(final int sleepTime) throws Exception {
+        final int maxRuntime = 5000;
+
+        WalkerTest.WalkerTestSpec spec = new WalkerTest.WalkerTestSpec(
+                "-T SleepingWalker -R " + b37KGReference
+                        + " -I " + privateTestDir + "NA12878.100kb.BQSRv2.example.bam -o %s"
+                        + " -maxRuntime " + maxRuntime + " -maxRuntimeUnits MILLISECONDS -sleepTime " + sleepTime, 1,
+                Collections.singletonList(""));
+        final File result = executeTest("Subshard max runtime ", spec).getFirst().get(0);
+        final int cycle = Integer.valueOf(new BufferedReader(new FileReader(result)).readLine());
+
+        final int maxCycles = (int)Math.ceil((maxRuntime * 5) / sleepTime);
+        logger.warn(String.format("Max cycles %d saw %d in file %s with sleepTime %d and maxRuntime %d", maxCycles, cycle, result, sleepTime, maxRuntime));
+        Assert.assertTrue(cycle < maxCycles, "Too many cycles seen -- saw " + cycle + " in file " + result + " but max should have been " + maxCycles);
+    }
+}
\ No newline at end of file
diff --git a/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/engine/ReadMetricsUnitTest.java b/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/engine/ReadMetricsUnitTest.java
new file mode 100644
index 0000000..1153bcc
--- /dev/null
+++ b/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/engine/ReadMetricsUnitTest.java
@@ -0,0 +1,371 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.engine;
+
+import htsjdk.samtools.reference.IndexedFastaSequenceFile;
+import htsjdk.samtools.*;
+import org.broadinstitute.gatk.utils.BaseTest;
+import org.broadinstitute.gatk.utils.commandline.Tags;
+import org.broadinstitute.gatk.engine.arguments.ValidationExclusion;
+import org.broadinstitute.gatk.engine.contexts.AlignmentContext;
+import org.broadinstitute.gatk.engine.contexts.ReferenceContext;
+import org.broadinstitute.gatk.engine.datasources.providers.LocusShardDataProvider;
+import org.broadinstitute.gatk.engine.datasources.providers.ReadShardDataProvider;
+import org.broadinstitute.gatk.engine.datasources.reads.*;
+import org.broadinstitute.gatk.engine.datasources.rmd.ReferenceOrderedDataSource;
+import org.broadinstitute.gatk.engine.executive.WindowMaker;
+import org.broadinstitute.gatk.engine.filters.ReadFilter;
+import org.broadinstitute.gatk.engine.iterators.ReadTransformer;
+import org.broadinstitute.gatk.engine.refdata.RefMetaDataTracker;
+import org.broadinstitute.gatk.engine.resourcemanagement.ThreadAllocation;
+import org.broadinstitute.gatk.engine.traversals.*;
+import org.broadinstitute.gatk.engine.walkers.*;
+import org.broadinstitute.gatk.utils.GenomeLoc;
+import org.broadinstitute.gatk.utils.GenomeLocParser;
+import org.broadinstitute.gatk.utils.GenomeLocSortedSet;
+import org.broadinstitute.gatk.utils.SampleUtils;
+import org.broadinstitute.gatk.utils.activeregion.ActiveRegion;
+import org.broadinstitute.gatk.utils.activeregion.ActivityProfileState;
+import org.broadinstitute.gatk.utils.fasta.CachingIndexedFastaSequenceFile;
+import org.broadinstitute.gatk.utils.interval.IntervalMergingRule;
+import org.broadinstitute.gatk.utils.sam.*;
+import org.testng.Assert;
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.Test;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.*;
+
+public class ReadMetricsUnitTest extends BaseTest {
+
+    @Test
+    public void testReadsSeenDoNotOverflowInt() {
+
+        final ReadMetrics metrics = new ReadMetrics();
+
+        final long moreThanMaxInt = ((long)Integer.MAX_VALUE) + 1L;
+
+        for ( long i = 0L; i < moreThanMaxInt; i++ ) {
+            metrics.incrementNumReadsSeen();
+        }
+
+        Assert.assertEquals(metrics.getNumReadsSeen(), moreThanMaxInt);
+        Assert.assertTrue(metrics.getNumReadsSeen() > (long) Integer.MAX_VALUE);
+
+        logger.warn(String.format("%d %d %d", Integer.MAX_VALUE, moreThanMaxInt, Long.MAX_VALUE));
+    }
+
+
+    // Test the accuracy of the read metrics
+
+    private IndexedFastaSequenceFile reference;
+    private SAMSequenceDictionary dictionary;
+    private SAMFileHeader header;
+    private GATKSAMReadGroupRecord readGroup;
+    private GenomeLocParser genomeLocParser;
+    private File testBAM;
+
+    private static final int numReadsPerContig = 250000;
+    private static final List<String> contigs = Arrays.asList("1", "2", "3");
+
+    @BeforeClass
+    private void init() throws IOException {
+        reference = new CachingIndexedFastaSequenceFile(new File(b37KGReference));
+        dictionary = reference.getSequenceDictionary();
+        genomeLocParser = new GenomeLocParser(dictionary);
+        header = ArtificialSAMUtils.createDefaultReadGroup(new SAMFileHeader(), "test", "test");
+        header.setSequenceDictionary(dictionary);
+        header.setSortOrder(SAMFileHeader.SortOrder.coordinate);
+        readGroup = new GATKSAMReadGroupRecord(header.getReadGroup("test"));
+
+        final List<GATKSAMRecord> reads = new ArrayList<>();
+        for ( final String contig : contigs ) {
+            for ( int i = 1; i <= numReadsPerContig; i++ ) {
+                reads.add(buildSAMRecord("read" + contig + "_" + i, contig, i));
+            }
+        }
+
+        createBAM(reads);
+    }
+
+    private void createBAM(final List<GATKSAMRecord> reads) throws IOException {
+        testBAM = createTempFile("TraverseActiveRegionsUnitTest", ".bam");
+
+        SAMFileWriter out = new SAMFileWriterFactory().setCreateIndex(true).makeBAMWriter(reads.get(0).getHeader(), true, testBAM);
+        for (GATKSAMRecord read : reads ) {
+            out.addAlignment(read);
+        }
+        out.close();
+
+        new File(testBAM.getAbsolutePath().replace(".bam", ".bai")).deleteOnExit();
+        new File(testBAM.getAbsolutePath() + ".bai").deleteOnExit();
+    }
+
+    // copied from LocusViewTemplate
+    protected GATKSAMRecord buildSAMRecord(final String readName, final String contig, final int alignmentStart) {
+        GATKSAMRecord record = new GATKSAMRecord(header);
+
+        record.setReadName(readName);
+        record.setReferenceIndex(dictionary.getSequenceIndex(contig));
+        record.setAlignmentStart(alignmentStart);
+
+        record.setCigarString("1M");
+        record.setReadString("A");
+        record.setBaseQualityString("A");
+        record.setReadGroup(readGroup);
+
+        return record;
+    }
+
+    @Test
+    public void testCountsFromReadTraversal() {
+        final GenomeAnalysisEngine engine = new GenomeAnalysisEngine();
+        engine.setGenomeLocParser(genomeLocParser);
+
+        final Collection<SAMReaderID> samFiles = new ArrayList<>();
+        final SAMReaderID readerID = new SAMReaderID(testBAM, new Tags());
+        samFiles.add(readerID);
+
+        final SAMDataSource dataSource = new SAMDataSource(samFiles, new ThreadAllocation(), null, genomeLocParser,
+                false,
+                ValidationStringency.STRICT,
+                null,
+                null,
+                new ValidationExclusion(),
+                new ArrayList<ReadFilter>(),
+                new ArrayList<ReadTransformer>(),
+                false, (byte)30, false, true, null, IntervalMergingRule.ALL);
+
+        engine.setReadsDataSource(dataSource);
+
+        final TraverseReadsNano traverseReadsNano = new TraverseReadsNano(1);
+        final DummyReadWalker walker = new DummyReadWalker();
+        traverseReadsNano.initialize(engine, walker, null);
+
+        for ( final Shard shard : dataSource.createShardIteratorOverAllReads(new ReadShardBalancer()) ) {
+            final ReadShardDataProvider dataProvider = new ReadShardDataProvider(shard, engine.getGenomeLocParser(), dataSource.seek(shard), reference, new ArrayList<ReferenceOrderedDataSource>());
+            traverseReadsNano.traverse(walker, dataProvider, 0);
+            dataProvider.close();
+        }
+
+        Assert.assertEquals(engine.getCumulativeMetrics().getNumReadsSeen(), contigs.size() * numReadsPerContig);
+        Assert.assertEquals(engine.getCumulativeMetrics().getNumIterations(), contigs.size() * numReadsPerContig);
+    }
+
+    @Test
+    public void testCountsFromLocusTraversal() {
+        final GenomeAnalysisEngine engine = new GenomeAnalysisEngine();
+        engine.setGenomeLocParser(genomeLocParser);
+
+        final Collection<SAMReaderID> samFiles = new ArrayList<>();
+        final SAMReaderID readerID = new SAMReaderID(testBAM, new Tags());
+        samFiles.add(readerID);
+
+        final SAMDataSource dataSource = new SAMDataSource(samFiles, new ThreadAllocation(), null, genomeLocParser,
+                false,
+                ValidationStringency.STRICT,
+                null,
+                null,
+                new ValidationExclusion(),
+                new ArrayList<ReadFilter>(),
+                new ArrayList<ReadTransformer>(),
+                false, (byte)30, false, true, null, IntervalMergingRule.ALL);
+
+        engine.setReadsDataSource(dataSource);
+        final Set<String> samples = SampleUtils.getSAMFileSamples(dataSource.getHeader());
+
+        final TraverseLociNano traverseLociNano = new TraverseLociNano(1);
+        final DummyLocusWalker walker = new DummyLocusWalker();
+        traverseLociNano.initialize(engine, walker, null);
+
+        for ( final Shard shard : dataSource.createShardIteratorOverAllReads(new LocusShardBalancer()) ) {
+            final WindowMaker windowMaker = new WindowMaker(shard, genomeLocParser, dataSource.seek(shard), shard.getGenomeLocs(), samples);
+            for ( WindowMaker.WindowMakerIterator window : windowMaker ) {
+                final LocusShardDataProvider dataProvider = new LocusShardDataProvider(shard, shard.getReadProperties(), genomeLocParser, window.getLocus(), window, reference, new ArrayList<ReferenceOrderedDataSource>());
+                traverseLociNano.traverse(walker, dataProvider, 0);
+                dataProvider.close();
+            }
+            windowMaker.close();
+        }
+
+        //dataSource.close();
+        Assert.assertEquals(engine.getCumulativeMetrics().getNumReadsSeen(), contigs.size() * numReadsPerContig);
+        Assert.assertEquals(engine.getCumulativeMetrics().getNumIterations(), contigs.size() * numReadsPerContig);
+    }
+
+    @Test
+    public void testCountsFromActiveRegionTraversal() {
+        final GenomeAnalysisEngine engine = new GenomeAnalysisEngine();
+        engine.setGenomeLocParser(genomeLocParser);
+
+        final Collection<SAMReaderID> samFiles = new ArrayList<>();
+        final SAMReaderID readerID = new SAMReaderID(testBAM, new Tags());
+        samFiles.add(readerID);
+
+        final SAMDataSource dataSource = new SAMDataSource(samFiles, new ThreadAllocation(), null, genomeLocParser,
+                false,
+                ValidationStringency.STRICT,
+                null,
+                null,
+                new ValidationExclusion(),
+                new ArrayList<ReadFilter>(),
+                new ArrayList<ReadTransformer>(),
+                false, (byte)30, false, true, null, IntervalMergingRule.ALL);
+
+        engine.setReadsDataSource(dataSource);
+        final Set<String> samples = SampleUtils.getSAMFileSamples(dataSource.getHeader());
+
+        final List<GenomeLoc> intervals = new ArrayList<>(contigs.size());
+        for ( final String contig : contigs )
+            intervals.add(genomeLocParser.createGenomeLoc(contig, 1, numReadsPerContig));
+
+        final TraverseActiveRegions traverseActiveRegions = new TraverseActiveRegions();
+        final DummyActiveRegionWalker walker = new DummyActiveRegionWalker();
+        traverseActiveRegions.initialize(engine, walker, null);
+
+        for ( final Shard shard : dataSource.createShardIteratorOverIntervals(new GenomeLocSortedSet(genomeLocParser, intervals), new ActiveRegionShardBalancer()) ) {
+            final WindowMaker windowMaker = new WindowMaker(shard, genomeLocParser, dataSource.seek(shard), shard.getGenomeLocs(), samples);
+            for ( WindowMaker.WindowMakerIterator window : windowMaker ) {
+                final LocusShardDataProvider dataProvider = new LocusShardDataProvider(shard, shard.getReadProperties(), genomeLocParser, window.getLocus(), window, reference, new ArrayList<ReferenceOrderedDataSource>());
+                traverseActiveRegions.traverse(walker, dataProvider, 0);
+                dataProvider.close();
+            }
+            windowMaker.close();
+        }
+
+        Assert.assertEquals(engine.getCumulativeMetrics().getNumReadsSeen(), contigs.size() * numReadsPerContig);
+        Assert.assertEquals(engine.getCumulativeMetrics().getNumIterations(), contigs.size() * numReadsPerContig);
+    }
+
+    @Test
+    public void testFilteredCounts() {
+        final GenomeAnalysisEngine engine = new GenomeAnalysisEngine();
+        engine.setGenomeLocParser(genomeLocParser);
+
+        final Collection<SAMReaderID> samFiles = new ArrayList<>();
+        final SAMReaderID readerID = new SAMReaderID(testBAM, new Tags());
+        samFiles.add(readerID);
+
+        final List<ReadFilter> filters = new ArrayList<>();
+        filters.add(new EveryTenthReadFilter());
+
+        final SAMDataSource dataSource = new SAMDataSource(samFiles, new ThreadAllocation(), null, genomeLocParser,
+                false,
+                ValidationStringency.STRICT,
+                null,
+                null,
+                new ValidationExclusion(),
+                filters,
+                new ArrayList<ReadTransformer>(),
+                false, (byte)30, false, true, null, IntervalMergingRule.ALL);
+
+        engine.setReadsDataSource(dataSource);
+
+        final TraverseReadsNano traverseReadsNano = new TraverseReadsNano(1);
+        final DummyReadWalker walker = new DummyReadWalker();
+        traverseReadsNano.initialize(engine, walker, null);
+
+        for ( final Shard shard : dataSource.createShardIteratorOverAllReads(new ReadShardBalancer()) ) {
+            final ReadShardDataProvider dataProvider = new ReadShardDataProvider(shard, engine.getGenomeLocParser(), dataSource.seek(shard), reference, new ArrayList<ReferenceOrderedDataSource>());
+            traverseReadsNano.traverse(walker, dataProvider, 0);
+            dataProvider.close();
+        }
+
+        Assert.assertEquals((long)engine.getCumulativeMetrics().getCountsByFilter().get(EveryTenthReadFilter.class.getSimpleName()), contigs.size() * numReadsPerContig / 10);
+    }
+
+    class DummyLocusWalker extends LocusWalker<Integer, Integer> {
+        @Override
+        public Integer map(RefMetaDataTracker tracker, ReferenceContext ref, AlignmentContext context) {
+            return 0;
+        }
+
+        @Override
+        public Integer reduceInit() {
+            return 0;
+        }
+
+        @Override
+        public Integer reduce(Integer value, Integer sum) {
+            return 0;
+        }
+    }
+
+    class DummyReadWalker extends ReadWalker<Integer, Integer> {
+        @Override
+        public Integer map(ReferenceContext ref, GATKSAMRecord read, RefMetaDataTracker metaDataTracker) {
+            return 0;
+        }
+
+        @Override
+        public Integer reduceInit() {
+            return 0;
+        }
+
+        @Override
+        public Integer reduce(Integer value, Integer sum) {
+            return 0;
+        }
+    }
+
+    class DummyActiveRegionWalker extends ActiveRegionWalker<Integer, Integer> {
+        @Override
+        public ActivityProfileState isActive(RefMetaDataTracker tracker, ReferenceContext ref, AlignmentContext context) {
+            return new ActivityProfileState(ref.getLocus(), 0.0);
+        }
+
+        @Override
+        public Integer map(ActiveRegion activeRegion, RefMetaDataTracker metaDataTracker) {
+            return 0;
+        }
+
+        @Override
+        public Integer reduceInit() {
+            return 0;
+        }
+
+        @Override
+        public Integer reduce(Integer value, Integer sum) {
+            return 0;
+        }
+    }
+
+    private final class EveryTenthReadFilter extends ReadFilter {
+
+        private int myCounter = 0;
+
+        @Override
+        public boolean filterOut(final SAMRecord record) {
+            if ( ++myCounter == 10 ) {
+                myCounter = 0;
+                return true;
+            }
+
+            return false;
+        }
+    }
+}
\ No newline at end of file
diff --git a/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/engine/WalkerManagerUnitTest.java b/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/engine/WalkerManagerUnitTest.java
new file mode 100644
index 0000000..62348ef
--- /dev/null
+++ b/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/engine/WalkerManagerUnitTest.java
@@ -0,0 +1,71 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.engine;
+
+import org.broadinstitute.gatk.utils.commandline.Hidden;
+import org.broadinstitute.gatk.engine.walkers.Walker;
+import org.broadinstitute.gatk.tools.walkers.qc.CountLoci;
+import org.broadinstitute.gatk.utils.exceptions.DynamicClassResolutionException;
+import org.broadinstitute.gatk.utils.exceptions.UserException;
+import org.testng.Assert;
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.Test;
+
+/**
+ * Tests basic functionality of the walker manager.
+ */
+public class WalkerManagerUnitTest {
+    private static WalkerManager walkerManager;
+
+    @BeforeClass
+    public void setUp() {
+        walkerManager = new WalkerManager();
+    }
+
+    @Test
+    public void testPresentWalker() {
+        Walker countLociWalker = walkerManager.createByName("CountLoci");
+        Assert.assertEquals(CountLoci.class,countLociWalker.getClass());
+    }
+
+    @Test(expectedExceptions=UserException.class)
+    public void testAbsentWalker() {
+        walkerManager.createByName("Missing");
+    }
+
+    @Test(expectedExceptions=DynamicClassResolutionException.class)
+    public void testUninstantiableWalker() {
+        walkerManager.createByName("UninstantiableWalker");
+    }
+}
+
+ at Hidden
+class UninstantiableWalker extends Walker<Integer,Long> {
+    // Private constructor will generate uninstantiable message
+    private UninstantiableWalker() {}
+    public Long reduceInit() { return 0L; }
+    public Long reduce(Integer value, Long accum) { return 0L; }
+}
diff --git a/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/engine/datasources/providers/AllLocusViewUnitTest.java b/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/engine/datasources/providers/AllLocusViewUnitTest.java
new file mode 100644
index 0000000..f9d9dfe
--- /dev/null
+++ b/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/engine/datasources/providers/AllLocusViewUnitTest.java
@@ -0,0 +1,90 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.engine.datasources.providers;
+
+
+import org.broadinstitute.gatk.utils.sam.GATKSAMRecord;
+import org.testng.Assert;
+import org.broadinstitute.gatk.utils.GenomeLoc;
+import org.broadinstitute.gatk.engine.contexts.AlignmentContext;
+
+import java.util.List;
+/**
+ * User: hanna
+ * Date: May 12, 2009
+ * Time: 2:34:46 PM
+ * BROAD INSTITUTE SOFTWARE COPYRIGHT NOTICE AND AGREEMENT
+ * Software and documentation are copyright 2005 by the Broad Institute.
+ * All rights are reserved.
+ *
+ * Users acknowledge that this software is supplied without any warranty or support.
+ * The Broad Institute is not responsible for its use, misuse, or
+ * functionality.
+ */
+
+/**
+ * Test the view of all loci.
+ */
+public class AllLocusViewUnitTest extends LocusViewTemplate {
+
+    @Override
+    protected LocusView createView(LocusShardDataProvider provider) {
+        return new AllLocusView(provider);
+    }
+
+    /**
+     * Test the reads according to an independently derived context.
+     * @param view
+     * @param range
+     * @param reads
+     */
+    @Override
+    protected void testReadsInContext( LocusView view, List<GenomeLoc> range, List<GATKSAMRecord> reads ) {
+        AllLocusView allLocusView = (AllLocusView)view;
+
+        // TODO: Should skip over loci not in the given range.
+        GenomeLoc firstLoc = range.get(0);
+        GenomeLoc lastLoc = range.get(range.size()-1);
+        GenomeLoc bounds = genomeLocParser.createGenomeLoc(firstLoc.getContig(),firstLoc.getStart(),lastLoc.getStop());
+
+        for( int i = bounds.getStart(); i <= bounds.getStop(); i++ ) {
+            GenomeLoc site = genomeLocParser.createGenomeLoc("chr1",i);
+            AlignmentContext locusContext = allLocusView.next();
+            Assert.assertEquals(locusContext.getLocation(), site, "Locus context location is incorrect");
+            int expectedReadsAtSite = 0;
+
+            for( GATKSAMRecord read: reads ) {
+                if(genomeLocParser.createGenomeLoc(read).containsP(locusContext.getLocation())) {
+                    Assert.assertTrue(locusContext.getReads().contains(read),"Target locus context does not contain reads");
+                    expectedReadsAtSite++;
+                }
+            }
+
+            Assert.assertEquals(locusContext.getReads().size(), expectedReadsAtSite, "Found wrong number of reads at site");
+        }
+
+    }
+}
diff --git a/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/engine/datasources/providers/CoveredLocusViewUnitTest.java b/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/engine/datasources/providers/CoveredLocusViewUnitTest.java
new file mode 100644
index 0000000..8914a48
--- /dev/null
+++ b/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/engine/datasources/providers/CoveredLocusViewUnitTest.java
@@ -0,0 +1,103 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.engine.datasources.providers;
+
+
+import org.broadinstitute.gatk.utils.sam.GATKSAMRecord;
+import org.testng.Assert;
+import org.broadinstitute.gatk.utils.GenomeLoc;
+import org.broadinstitute.gatk.utils.GenomeLocParser;
+import org.broadinstitute.gatk.engine.contexts.AlignmentContext;
+
+import java.util.List;
+/**
+ * User: hanna
+ * Date: May 12, 2009
+ * Time: 2:34:46 PM
+ * BROAD INSTITUTE SOFTWARE COPYRIGHT NOTICE AND AGREEMENT
+ * Software and documentation are copyright 2005 by the Broad Institute.
+ * All rights are reserved.
+ *
+ * Users acknowledge that this software is supplied without any warranty or support.
+ * The Broad Institute is not responsible for its use, misuse, or
+ * functionality.
+ */
+
+/**
+ * Test the CoveredLocusView.
+ */
+public class CoveredLocusViewUnitTest extends LocusViewTemplate {
+
+    /**
+     * Retrieve a covered locus view.
+     */
+    @Override
+    protected LocusView createView(LocusShardDataProvider provider) {
+        return new CoveredLocusView(provider);
+    }
+
+    /**
+     * Test the reads according to an independently derived context.
+     * @param view
+     * @param range
+     * @param reads
+     */
+    @Override
+    protected void testReadsInContext( LocusView view, List<GenomeLoc> range, List<GATKSAMRecord> reads ) {
+        CoveredLocusView coveredLocusView = (CoveredLocusView)view;
+
+        // TODO: Should skip over loci not in the given range.
+        GenomeLoc firstLoc = range.get(0);
+        GenomeLoc lastLoc = range.get(range.size()-1);
+        GenomeLoc bounds = genomeLocParser.createGenomeLoc(firstLoc.getContig(),firstLoc.getStart(),lastLoc.getStop());
+
+        for( int i = bounds.getStart(); i <= bounds.getStop(); i++ ) {
+            GenomeLoc site = genomeLocParser.createGenomeLoc("chr1",i);
+
+            int expectedReadsAtSite = 0;
+            for( GATKSAMRecord read: reads ) {
+                if( genomeLocParser.createGenomeLoc(read).containsP(site) )
+                    expectedReadsAtSite++;
+            }
+
+            if( expectedReadsAtSite < 1 )
+                continue;
+
+            Assert.assertTrue(coveredLocusView.hasNext(),"Incorrect number of loci in view");
+
+            AlignmentContext locusContext = coveredLocusView.next();
+            Assert.assertEquals(locusContext.getLocation(), site, "Target locus context location is incorrect");
+            Assert.assertEquals(locusContext.getReads().size(), expectedReadsAtSite, "Found wrong number of reads at site");
+
+            for( GATKSAMRecord read: reads ) {
+                if(genomeLocParser.createGenomeLoc(read).containsP(locusContext.getLocation()))
+                    Assert.assertTrue(locusContext.getReads().contains(read),"Target locus context does not contain reads");
+            }
+        }
+
+        Assert.assertFalse(coveredLocusView.hasNext(),"Iterator is not bounded at boundaries of shard");
+    }        
+}
diff --git a/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/engine/datasources/providers/IntervalReferenceOrderedViewUnitTest.java b/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/engine/datasources/providers/IntervalReferenceOrderedViewUnitTest.java
new file mode 100644
index 0000000..29ccbd6
--- /dev/null
+++ b/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/engine/datasources/providers/IntervalReferenceOrderedViewUnitTest.java
@@ -0,0 +1,366 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.engine.datasources.providers;
+
+import htsjdk.samtools.util.PeekableIterator;
+import htsjdk.samtools.SAMFileHeader;
+import htsjdk.tribble.BasicFeature;
+import htsjdk.tribble.Feature;
+import org.broadinstitute.gatk.utils.BaseTest;
+import org.broadinstitute.gatk.utils.commandline.RodBinding;
+import org.broadinstitute.gatk.engine.refdata.RODRecordListImpl;
+import org.broadinstitute.gatk.engine.refdata.RefMetaDataTracker;
+import org.broadinstitute.gatk.engine.refdata.utils.GATKFeature;
+import org.broadinstitute.gatk.engine.refdata.utils.RODRecordList;
+import org.broadinstitute.gatk.utils.GenomeLoc;
+import org.broadinstitute.gatk.utils.GenomeLocParser;
+import org.broadinstitute.gatk.utils.Utils;
+import org.broadinstitute.gatk.utils.sam.ArtificialSAMUtils;
+import org.testng.Assert;
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.DataProvider;
+import org.testng.annotations.Test;
+
+import java.util.*;
+
+/**
+ * @author depristo
+ */
+public class IntervalReferenceOrderedViewUnitTest extends BaseTest {
+    private static int startingChr = 1;
+    private static int endingChr = 2;
+    private static int readCount = 100;
+    private static int DEFAULT_READ_LENGTH = ArtificialSAMUtils.DEFAULT_READ_LENGTH;
+    private static String contig;
+    private static SAMFileHeader header;
+
+    private GenomeLocParser genomeLocParser;
+
+    @BeforeClass
+    public void beforeClass() {
+        header = ArtificialSAMUtils.createArtificialSamHeader((endingChr - startingChr) + 1, startingChr, readCount + DEFAULT_READ_LENGTH);
+        contig = header.getSequence(0).getSequenceName();
+        genomeLocParser = new GenomeLocParser(header.getSequenceDictionary());
+
+        initializeTests();
+    }
+
+    private class CompareFeatures implements Comparator<Feature> {
+        @Override
+        public int compare(Feature o1, Feature o2) {
+            return genomeLocParser.createGenomeLoc(o1).compareTo(genomeLocParser.createGenomeLoc(o2));
+        }
+    }
+
+    private class ReadMetaDataTrackerRODStreamTest extends TestDataProvider {
+        final List<Feature> allFeatures;
+        final List<GenomeLoc> intervals;
+
+        public ReadMetaDataTrackerRODStreamTest(final List<Feature> allFeatures, final GenomeLoc interval) {
+            this(allFeatures, Collections.singletonList(interval));
+        }
+
+        public ReadMetaDataTrackerRODStreamTest(final List<Feature> allFeatures, final List<GenomeLoc> intervals) {
+            super(ReadMetaDataTrackerRODStreamTest.class);
+            this.allFeatures = new ArrayList<Feature>(allFeatures);
+            Collections.sort(this.allFeatures, new CompareFeatures());
+            this.intervals = new ArrayList<GenomeLoc>(intervals);
+            Collections.sort(this.intervals);
+            setName(String.format("%s nFeatures %d intervals %s", getClass().getSimpleName(), allFeatures.size(),
+                    intervals.size() == 1 ? intervals.get(0) : "size " + intervals.size()));
+        }
+
+        public PeekableIterator<RODRecordList> getIterator(final String name) {
+            return new PeekableIterator<RODRecordList>(new TribbleIteratorFromCollection(name, genomeLocParser, allFeatures));
+        }
+
+        public Set<Feature> getExpectedOverlaps(final GenomeLoc interval) {
+            final Set<Feature> overlapping = new HashSet<Feature>();
+            for ( final Feature f : allFeatures )
+                if ( genomeLocParser.createGenomeLoc(f).overlapsP(interval) )
+                    overlapping.add(f);
+            return overlapping;
+        }
+    }
+
+    public void initializeTests() {
+        final List<Feature> handPickedFeatures = new ArrayList<Feature>();
+
+        handPickedFeatures.add(new BasicFeature(contig, 1, 1));
+        handPickedFeatures.add(new BasicFeature(contig, 2, 5));
+        handPickedFeatures.add(new BasicFeature(contig, 4, 4));
+        handPickedFeatures.add(new BasicFeature(contig, 6, 6));
+        handPickedFeatures.add(new BasicFeature(contig, 9, 10));
+        handPickedFeatures.add(new BasicFeature(contig, 10, 10));
+        handPickedFeatures.add(new BasicFeature(contig, 10, 11));
+        handPickedFeatures.add(new BasicFeature(contig, 13, 20));
+
+        createTestsForFeatures(handPickedFeatures);
+
+        // test in the present of a large spanning element
+        {
+            List<Feature> oneLargeSpan = new ArrayList<Feature>(handPickedFeatures);
+            oneLargeSpan.add(new BasicFeature(contig, 1, 30));
+            createTestsForFeatures(oneLargeSpan);
+        }
+
+        // test in the presence of a partially spanning element
+        {
+            List<Feature> partialSpanStart = new ArrayList<Feature>(handPickedFeatures);
+            partialSpanStart.add(new BasicFeature(contig, 1, 6));
+            createTestsForFeatures(partialSpanStart);
+        }
+
+        // test in the presence of a partially spanning element at the end
+        {
+            List<Feature> partialSpanEnd = new ArrayList<Feature>(handPickedFeatures);
+            partialSpanEnd.add(new BasicFeature(contig, 10, 30));
+            createTestsForFeatures(partialSpanEnd);
+        }
+
+        // no data at all
+        final GenomeLoc loc = genomeLocParser.createGenomeLoc(contig, 5, 5);
+        new ReadMetaDataTrackerRODStreamTest(Collections.<Feature>emptyList(), loc);
+    }
+
+    // --------------------------------------------------------------------------------
+    //
+    // tests for the lower level IntervalOverlappingRODsFromStream
+    //
+    // --------------------------------------------------------------------------------
+
+    @DataProvider(name = "ReadMetaDataTrackerRODStreamTest")
+    public Object[][] createReadMetaDataTrackerRODStreamTest() {
+        return ReadMetaDataTrackerRODStreamTest.getTests(ReadMetaDataTrackerRODStreamTest.class);
+    }
+
+    private GenomeLoc span(final List<GenomeLoc> features) {
+        int featuresStart = 1; for ( final GenomeLoc f : features ) featuresStart = Math.min(featuresStart, f.getStart());
+        int featuresStop = 1; for ( final GenomeLoc f : features ) featuresStop = Math.max(featuresStop, f.getStop());
+        return genomeLocParser.createGenomeLoc(contig, featuresStart, featuresStop);
+    }
+
+    private void createTestsForFeatures(final List<Feature> features) {
+        int featuresStart = 1; for ( final Feature f : features ) featuresStart = Math.min(featuresStart, f.getStart());
+        int featuresStop = 1; for ( final Feature f : features ) featuresStop = Math.max(featuresStop, f.getEnd());
+
+        for ( final int size : Arrays.asList(1, 5, 10, 100) ) {
+            final List<GenomeLoc> allIntervals = new ArrayList<GenomeLoc>();
+            // regularly spaced
+            for ( int start = featuresStart; start < featuresStop; start++) {
+                final GenomeLoc loc = genomeLocParser.createGenomeLoc(contig, start, start + size - 1);
+                allIntervals.add(loc);
+                new ReadMetaDataTrackerRODStreamTest(features, loc);
+            }
+
+            // starting and stopping at every feature
+            for ( final Feature f : features ) {
+                // just at the feature
+                allIntervals.add(genomeLocParser.createGenomeLoc(contig, f.getStart(), f.getEnd()));
+                new ReadMetaDataTrackerRODStreamTest(features, allIntervals.get(allIntervals.size() - 1));
+
+                // up to end
+                allIntervals.add(genomeLocParser.createGenomeLoc(contig, f.getStart() - 1, f.getEnd()));
+                new ReadMetaDataTrackerRODStreamTest(features, allIntervals.get(allIntervals.size() - 1));
+
+                // missing by 1
+                allIntervals.add(genomeLocParser.createGenomeLoc(contig, f.getStart() + 1, f.getEnd() + 1));
+                new ReadMetaDataTrackerRODStreamTest(features, allIntervals.get(allIntervals.size() - 1));
+
+                // just spanning
+                allIntervals.add(genomeLocParser.createGenomeLoc(contig, f.getStart() - 1, f.getEnd() + 1));
+                new ReadMetaDataTrackerRODStreamTest(features, allIntervals.get(allIntervals.size() - 1));
+            }
+
+            new ReadMetaDataTrackerRODStreamTest(features, allIntervals);
+        }
+    }
+
+    @Test(enabled = true, dataProvider = "ReadMetaDataTrackerRODStreamTest")
+    public void runReadMetaDataTrackerRODStreamTest_singleQuery(final ReadMetaDataTrackerRODStreamTest data) {
+        if ( data.intervals.size() == 1 ) {
+            final String name = "testName";
+            final PeekableIterator<RODRecordList> iterator = data.getIterator(name);
+            final IntervalOverlappingRODsFromStream stream = new IntervalOverlappingRODsFromStream(name, iterator);
+            testRODStream(data, stream, Collections.singletonList(data.intervals.get(0)));
+        }
+    }
+
+    @Test(enabled = true, dataProvider = "ReadMetaDataTrackerRODStreamTest", dependsOnMethods = "runReadMetaDataTrackerRODStreamTest_singleQuery")
+    public void runReadMetaDataTrackerRODStreamTest_multipleQueries(final ReadMetaDataTrackerRODStreamTest data) {
+        if ( data.intervals.size() > 1 ) {
+            final String name = "testName";
+            final PeekableIterator<RODRecordList> iterator = data.getIterator(name);
+            final IntervalOverlappingRODsFromStream stream = new IntervalOverlappingRODsFromStream(name, iterator);
+            testRODStream(data, stream, data.intervals);
+        }
+    }
+
+    private void testRODStream(final ReadMetaDataTrackerRODStreamTest test, final IntervalOverlappingRODsFromStream stream, final List<GenomeLoc> intervals) {
+        for ( final GenomeLoc interval : intervals ) {
+            final RODRecordList query = stream.getOverlapping(interval);
+            final HashSet<Feature> queryFeatures = new HashSet<Feature>();
+            for ( final GATKFeature f : query ) queryFeatures.add((Feature)f.getUnderlyingObject());
+            final Set<Feature> overlaps = test.getExpectedOverlaps(interval);
+
+            Assert.assertEquals(queryFeatures.size(), overlaps.size(), "IntervalOverlappingRODsFromStream didn't return the expected set of overlapping features." +
+                    " Expected size = " + overlaps.size() + " but saw " + queryFeatures.size());
+
+            BaseTest.assertEqualsSet(queryFeatures, overlaps, "IntervalOverlappingRODsFromStream didn't return the expected set of overlapping features." +
+                    " Expected = " + Utils.join(",", overlaps) + " but saw " + Utils.join(",", queryFeatures));
+        }
+    }
+
+    // --------------------------------------------------------------------------------
+    //
+    // tests for the higher level tracker itself
+    //
+    // --------------------------------------------------------------------------------
+
+    @DataProvider(name = "ReadMetaDataTrackerTests")
+    public Object[][] createTrackerTests() {
+        List<Object[]> tests = new ArrayList<Object[]>();
+
+        final Object[][] singleTests = ReadMetaDataTrackerRODStreamTest.getTests(ReadMetaDataTrackerRODStreamTest.class);
+        final List<ReadMetaDataTrackerRODStreamTest> multiSiteTests = new ArrayList<ReadMetaDataTrackerRODStreamTest>();
+        for ( final Object[] singleTest : singleTests ) {
+            if ( ((ReadMetaDataTrackerRODStreamTest)singleTest[0]).intervals.size() > 1 )
+                multiSiteTests.add((ReadMetaDataTrackerRODStreamTest)singleTest[0]);
+        }
+
+        for ( final boolean testStateless : Arrays.asList(true, false) ) {
+            // all pairwise tests
+            for ( List<ReadMetaDataTrackerRODStreamTest> singleTest : Utils.makePermutations(multiSiteTests, 2, false)) {
+                tests.add(new Object[]{singleTest, testStateless});
+            }
+
+            // all 3 way pairwise tests
+            //for ( List<ReadMetaDataTrackerRODStreamTest> singleTest : Utils.makePermutations(multiSiteTests, 3, false)) {
+            //    tests.add(new Object[]{singleTest, testStateless});
+            //}
+        }
+
+        logger.warn("Creating " + tests.size() + " tests for ReadMetaDataTrackerTests");
+        return tests.toArray(new Object[][]{});
+    }
+
+    @Test(enabled = true, dataProvider = "ReadMetaDataTrackerTests", dependsOnMethods = "runReadMetaDataTrackerRODStreamTest_multipleQueries")
+    public void runReadMetaDataTrackerTest(final List<ReadMetaDataTrackerRODStreamTest> RODs, final boolean testStateless) {
+        final List<String> names = new ArrayList<String>();
+        final List<PeekableIterator<RODRecordList>> iterators = new ArrayList<PeekableIterator<RODRecordList>>();
+        final List<GenomeLoc> intervals = new ArrayList<GenomeLoc>();
+        final List<RodBinding<Feature>> rodBindings = new ArrayList<RodBinding<Feature>>();
+
+        for ( int i = 0; i < RODs.size(); i++ ) {
+            final RodBinding<Feature> rodBinding = new RodBinding<Feature>(Feature.class, "name"+i);
+            rodBindings.add(rodBinding);
+            final String name = rodBinding.getName();
+            names.add(name);
+            iterators.add(RODs.get(i).getIterator(name));
+            intervals.addAll(RODs.get(i).intervals);
+        }
+
+        Collections.sort(intervals);
+        final GenomeLoc span = span(intervals);
+        final IntervalReferenceOrderedView view = new IntervalReferenceOrderedView(genomeLocParser, span, names, iterators);
+
+        if ( testStateless ) {
+            // test each tracker is well formed, as each is created
+            for ( final GenomeLoc interval : intervals ) {
+                final RefMetaDataTracker tracker = view.getReferenceOrderedDataForInterval(interval);
+                testMetaDataTrackerBindings(tracker, interval, RODs, rodBindings);
+            }
+        } else {
+            // tests all trackers are correct after reading them into an array
+            // this checks that the trackers are be safely stored away and analyzed later (critical for nano-scheduling)
+            final List<RefMetaDataTracker> trackers = new ArrayList<RefMetaDataTracker>();
+            for ( final GenomeLoc interval : intervals ) {
+                final RefMetaDataTracker tracker = view.getReferenceOrderedDataForInterval(interval);
+                trackers.add(tracker);
+            }
+
+            for ( int i = 0; i < trackers.size(); i++) {
+                testMetaDataTrackerBindings(trackers.get(i), intervals.get(i), RODs, rodBindings);
+            }
+        }
+    }
+
+    private void testMetaDataTrackerBindings(final RefMetaDataTracker tracker,
+                                             final GenomeLoc interval,
+                                             final List<ReadMetaDataTrackerRODStreamTest> RODs,
+                                             final List<RodBinding<Feature>> rodBindings) {
+        for ( int i = 0; i < RODs.size(); i++ ) {
+            final ReadMetaDataTrackerRODStreamTest test = RODs.get(i);
+            final List<Feature> queryFeaturesList = tracker.getValues(rodBindings.get(i));
+            final Set<Feature> queryFeatures = new HashSet<Feature>(queryFeaturesList);
+            final Set<Feature> overlaps = test.getExpectedOverlaps(interval);
+
+            Assert.assertEquals(queryFeatures.size(), overlaps.size(), "IntervalOverlappingRODsFromStream didn't return the expected set of overlapping features." +
+                    " Expected size = " + overlaps.size() + " but saw " + queryFeatures.size());
+
+            BaseTest.assertEqualsSet(queryFeatures, overlaps, "IntervalOverlappingRODsFromStream didn't return the expected set of overlapping features." +
+                    " Expected = " + Utils.join(",", overlaps) + " but saw " + Utils.join(",", queryFeatures));
+        }
+    }
+
+    static class TribbleIteratorFromCollection implements Iterator<RODRecordList> {
+        // current location
+        private final String name;
+        final Queue<GATKFeature> gatkFeatures;
+
+        public TribbleIteratorFromCollection(final String name, final GenomeLocParser genomeLocParser, final List<Feature> features) {
+            this.name = name;
+
+            this.gatkFeatures = new LinkedList<GATKFeature>();
+            for ( final Feature f : features )
+                gatkFeatures.add(new GATKFeature.TribbleGATKFeature(genomeLocParser, f, name));
+        }
+
+        @Override
+        public boolean hasNext() {
+            return ! gatkFeatures.isEmpty();
+        }
+
+        @Override
+        public RODRecordList next() {
+            final GATKFeature first = gatkFeatures.poll();
+            final Collection<GATKFeature> myFeatures = new LinkedList<GATKFeature>();
+            myFeatures.add(first);
+            while ( gatkFeatures.peek() != null && gatkFeatures.peek().getLocation().getStart() == first.getStart() )
+                myFeatures.add(gatkFeatures.poll());
+
+            GenomeLoc loc = first.getLocation();
+            for ( final GATKFeature feature : myFeatures )
+                loc = loc.merge(feature.getLocation());
+
+            return new RODRecordListImpl(name, myFeatures, loc); // is this safe?
+        }
+
+        @Override public void remove() { throw new IllegalStateException("GRRR"); }
+    }
+}
+
+
diff --git a/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/engine/datasources/providers/LocusReferenceViewUnitTest.java b/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/engine/datasources/providers/LocusReferenceViewUnitTest.java
new file mode 100644
index 0000000..5eb9c7a
--- /dev/null
+++ b/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/engine/datasources/providers/LocusReferenceViewUnitTest.java
@@ -0,0 +1,143 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.engine.datasources.providers;
+
+import org.broadinstitute.gatk.engine.datasources.reads.Shard;
+import org.testng.Assert;
+import org.testng.annotations.Test;
+
+import org.broadinstitute.gatk.utils.GenomeLoc;
+import org.broadinstitute.gatk.engine.datasources.reads.MockLocusShard;
+import org.broadinstitute.gatk.engine.iterators.GenomeLocusIterator;
+import org.broadinstitute.gatk.engine.contexts.ReferenceContext;
+
+import htsjdk.samtools.reference.ReferenceSequence;
+import htsjdk.samtools.util.StringUtil;
+
+import java.util.Collections;
+/*
+ * 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.
+ */
+
+/** Tests for viewing the reference from the perspective of a locus. */
+
+public class LocusReferenceViewUnitTest extends ReferenceViewTemplate {
+
+//
+//    /** Multiple-base pair queries should generate exceptions. */
+//    @Test(expectedExceptions=InvalidPositionException.class)
+//    public void testSingleBPFailure() {
+//        Shard shard = new LocusShard(GenomeLocParser.createGenomeLoc(0, 1, 50));
+//
+//        ShardDataProvider dataProvider = new ShardDataProvider(shard, null, sequenceFile, null);
+//        LocusReferenceView view = new LocusReferenceView(dataProvider);
+//
+//        view.getReferenceContext(shard.getGenomeLoc()).getBase();
+//    }
+
+    @Test
+    public void testOverlappingReferenceBases() {
+        Shard shard = new MockLocusShard(genomeLocParser,Collections.singletonList(genomeLocParser.createGenomeLoc(sequenceFile.getSequenceDictionary().getSequence(0).getSequenceName(),
+                                                                                                                   sequenceFile.getSequence("chrM").length() - 10,
+                                                                                                                   sequenceFile.getSequence("chrM").length())));
+        LocusShardDataProvider dataProvider = new LocusShardDataProvider(shard, null, genomeLocParser, shard.getGenomeLocs().get(0), null, sequenceFile, null);
+        LocusReferenceView view = new LocusReferenceView(dataProvider);
+
+        byte[] results = view.getReferenceBases(genomeLocParser.createGenomeLoc(sequenceFile.getSequenceDictionary().getSequence(0).getSequenceName(),
+                                                                                sequenceFile.getSequence("chrM").length() - 10,
+                                                                                sequenceFile.getSequence("chrM").length() + 9));
+        System.out.printf("results are %s%n", new String(results));
+        Assert.assertEquals(results.length, 20);
+        for (int x = 0; x < results.length; x++) {
+            if (x <= 10) Assert.assertTrue(results[x] != 'X');
+            else Assert.assertTrue(results[x] == 'X');
+        }
+    }
+
+
+    /** Queries outside the bounds of the shard should result in reference context window trimmed at the shard boundary. */
+    @Test
+    public void testBoundsFailure() {
+        Shard shard = new MockLocusShard(genomeLocParser,Collections.singletonList(genomeLocParser.createGenomeLoc(sequenceFile.getSequenceDictionary().getSequence(0).getSequenceName(), 1, 50)));
+
+        LocusShardDataProvider dataProvider = new LocusShardDataProvider(shard, null, genomeLocParser, shard.getGenomeLocs().get(0), null, sequenceFile, null);
+        LocusReferenceView view = new LocusReferenceView(dataProvider);
+
+        GenomeLoc locus = genomeLocParser.createGenomeLoc(sequenceFile.getSequenceDictionary().getSequence(0).getSequenceName(), 50, 51);
+
+        ReferenceContext rc = view.getReferenceContext(locus);
+        Assert.assertTrue(rc.getLocus().equals(locus));
+        Assert.assertTrue(rc.getWindow().equals(genomeLocParser.createGenomeLoc(sequenceFile.getSequenceDictionary().getSequence(0).getSequenceName(),50)));
+        Assert.assertTrue(rc.getBases().length == 1);
+    }
+
+
+    /**
+     * Compares the contents of the fasta and view at a specified location.
+     *
+     * @param loc
+     */
+    protected void validateLocation( GenomeLoc loc ) {
+        Shard shard = new MockLocusShard(genomeLocParser,Collections.singletonList(loc));
+        GenomeLocusIterator shardIterator = new GenomeLocusIterator(genomeLocParser,loc);
+
+        LocusShardDataProvider dataProvider = new LocusShardDataProvider(shard, null, genomeLocParser, loc, null, sequenceFile, null);
+        LocusReferenceView view = new LocusReferenceView(dataProvider);
+
+        while (shardIterator.hasNext()) {
+            GenomeLoc locus = shardIterator.next();
+
+            ReferenceSequence expectedAsSeq = sequenceFile.getSubsequenceAt(locus.getContig(), locus.getStart(), locus.getStop());
+            char expected = Character.toUpperCase(StringUtil.bytesToString(expectedAsSeq.getBases()).charAt(0));
+            char actual = view.getReferenceContext(locus).getBaseAsChar();
+
+            Assert.assertEquals(actual, expected, String.format("Value of base at position %s in shard %s does not match expected", locus.toString(), shard.getGenomeLocs())
+            );
+        }
+    }
+
+}
diff --git a/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/engine/datasources/providers/LocusViewTemplate.java b/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/engine/datasources/providers/LocusViewTemplate.java
new file mode 100644
index 0000000..650b146
--- /dev/null
+++ b/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/engine/datasources/providers/LocusViewTemplate.java
@@ -0,0 +1,405 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.engine.datasources.providers;
+
+import htsjdk.samtools.reference.ReferenceSequence;
+import htsjdk.samtools.reference.ReferenceSequenceFile;
+import htsjdk.samtools.*;
+import org.broadinstitute.gatk.utils.BaseTest;
+import org.broadinstitute.gatk.engine.datasources.reads.MockLocusShard;
+import org.broadinstitute.gatk.engine.datasources.reads.SAMReaderID;
+import org.broadinstitute.gatk.engine.datasources.reads.Shard;
+import org.broadinstitute.gatk.engine.executive.WindowMaker;
+import org.broadinstitute.gatk.engine.datasources.reads.LocusShard;
+import org.broadinstitute.gatk.engine.datasources.reads.SAMDataSource;
+import org.broadinstitute.gatk.engine.iterators.GATKSAMIterator;
+import org.broadinstitute.gatk.engine.resourcemanagement.ThreadAllocation;
+import org.broadinstitute.gatk.utils.GenomeLoc;
+import org.broadinstitute.gatk.utils.GenomeLocParser;
+import org.broadinstitute.gatk.utils.sam.GATKSAMRecord;
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.Test;
+
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.util.*;
+/**
+ * User: hanna
+ * Date: May 13, 2009
+ * Time: 4:29:08 PM
+ * BROAD INSTITUTE SOFTWARE COPYRIGHT NOTICE AND AGREEMENT
+ * Software and documentation are copyright 2005 by the Broad Institute.
+ * All rights are reserved.
+ *
+ * Users acknowledge that this software is supplied without any warranty or support.
+ * The Broad Institute is not responsible for its use, misuse, or
+ * functionality.
+ */
+
+/** Base support for testing variants of the LocusView family of classes. */
+
+public abstract class LocusViewTemplate extends BaseTest {
+    protected static ReferenceSequenceFile sequenceSourceFile = null;
+    protected GenomeLocParser genomeLocParser = null;
+
+    @BeforeClass
+    public void setupGenomeLoc() throws FileNotFoundException {
+        sequenceSourceFile = fakeReferenceSequenceFile();
+        genomeLocParser = new GenomeLocParser(sequenceSourceFile);
+    }
+
+    @Test
+    public void emptyAlignmentContextTest() {
+        SAMRecordIterator iterator = new SAMRecordIterator();
+
+        GenomeLoc shardBounds = genomeLocParser.createGenomeLoc("chr1", 1, 5);
+        Shard shard = new LocusShard(genomeLocParser, new SAMDataSource(Collections.<SAMReaderID>emptyList(),new ThreadAllocation(),null,genomeLocParser),Collections.singletonList(shardBounds),Collections.<SAMReaderID,SAMFileSpan>emptyMap());
+        WindowMaker windowMaker = new WindowMaker(shard,genomeLocParser,iterator,shard.getGenomeLocs());
+        WindowMaker.WindowMakerIterator window = windowMaker.next();
+        LocusShardDataProvider dataProvider = new LocusShardDataProvider(shard, null, genomeLocParser, window.getLocus(), window, null, null);
+
+        LocusView view = createView(dataProvider);
+
+        testReadsInContext(view, shard.getGenomeLocs(), Collections.<GATKSAMRecord>emptyList());
+    }
+
+    @Test
+    public void singleReadTest() {
+        GATKSAMRecord read = buildSAMRecord("read1","chr1", 1, 5);
+        SAMRecordIterator iterator = new SAMRecordIterator(read);
+
+        GenomeLoc shardBounds = genomeLocParser.createGenomeLoc("chr1", 1, 5);
+        Shard shard = new MockLocusShard(genomeLocParser,Collections.singletonList(shardBounds));
+        WindowMaker windowMaker = new WindowMaker(shard,genomeLocParser,iterator,shard.getGenomeLocs());
+        WindowMaker.WindowMakerIterator window = windowMaker.next();
+        LocusShardDataProvider dataProvider = new LocusShardDataProvider(shard, window.getSourceInfo(), genomeLocParser, window.getLocus(), window, null, null);
+
+        LocusView view = createView(dataProvider);
+
+        testReadsInContext(view, shard.getGenomeLocs(), Collections.singletonList(read));
+    }
+
+    @Test
+    public void readCoveringFirstPartTest() {
+        GATKSAMRecord read = buildSAMRecord("read1","chr1", 1, 5);
+        SAMRecordIterator iterator = new SAMRecordIterator(read);
+
+        Shard shard = new MockLocusShard(genomeLocParser,Collections.singletonList(genomeLocParser.createGenomeLoc("chr1", 1, 10)));
+        WindowMaker windowMaker = new WindowMaker(shard,genomeLocParser,iterator,shard.getGenomeLocs());
+        WindowMaker.WindowMakerIterator window = windowMaker.next();
+        LocusShardDataProvider dataProvider = new LocusShardDataProvider(shard, window.getSourceInfo(), genomeLocParser, window.getLocus(), window, null, null);
+        LocusView view = createView(dataProvider);
+
+        testReadsInContext(view, shard.getGenomeLocs(), Collections.singletonList(read));
+    }
+
+    @Test
+    public void readCoveringLastPartTest() {
+        GATKSAMRecord read = buildSAMRecord("read1","chr1", 6, 10);
+        SAMRecordIterator iterator = new SAMRecordIterator(read);
+
+        Shard shard = new MockLocusShard(genomeLocParser,Collections.singletonList(genomeLocParser.createGenomeLoc("chr1", 1, 10)));
+        WindowMaker windowMaker = new WindowMaker(shard,genomeLocParser,iterator,shard.getGenomeLocs());
+        WindowMaker.WindowMakerIterator window = windowMaker.next();
+        LocusShardDataProvider dataProvider = new LocusShardDataProvider(shard, window.getSourceInfo(), genomeLocParser, window.getLocus(), window, null, null);
+        LocusView view = createView(dataProvider);
+
+        testReadsInContext(view, shard.getGenomeLocs(), Collections.singletonList(read));
+    }
+
+    @Test
+    public void readCoveringMiddleTest() {
+        GATKSAMRecord read = buildSAMRecord("read1","chr1", 3, 7);
+        SAMRecordIterator iterator = new SAMRecordIterator(read);
+
+        Shard shard = new MockLocusShard(genomeLocParser,Collections.singletonList(genomeLocParser.createGenomeLoc("chr1", 1, 10)));
+        WindowMaker windowMaker = new WindowMaker(shard,genomeLocParser,iterator,shard.getGenomeLocs());
+        WindowMaker.WindowMakerIterator window = windowMaker.next();
+        LocusShardDataProvider dataProvider = new LocusShardDataProvider(shard, window.getSourceInfo(), genomeLocParser, window.getLocus(), window, null, null);
+        LocusView view = createView(dataProvider);
+
+        testReadsInContext(view, shard.getGenomeLocs(), Collections.singletonList(read));
+    }
+
+    @Test
+    public void readAndLocusOverlapAtLastBase() {
+        GATKSAMRecord read = buildSAMRecord("read1","chr1", 1, 5);
+        SAMRecordIterator iterator = new SAMRecordIterator(read);
+
+        Shard shard = new MockLocusShard(genomeLocParser,Collections.singletonList(genomeLocParser.createGenomeLoc("chr1", 5, 5)));
+        WindowMaker windowMaker = new WindowMaker(shard,genomeLocParser,iterator,shard.getGenomeLocs());
+        WindowMaker.WindowMakerIterator window = windowMaker.next();
+        LocusShardDataProvider dataProvider = new LocusShardDataProvider(shard, window.getSourceInfo(), genomeLocParser, window.getLocus(), window, null, null);
+        LocusView view = createView(dataProvider);
+
+        testReadsInContext(view, shard.getGenomeLocs(), Collections.singletonList(read));
+    }
+
+    @Test
+    public void readOverlappingStartTest() {
+        GATKSAMRecord read = buildSAMRecord("read1","chr1", 1, 10);
+        SAMRecordIterator iterator = new SAMRecordIterator(read);
+
+        Shard shard = new MockLocusShard(genomeLocParser,Collections.singletonList(genomeLocParser.createGenomeLoc("chr1", 6, 15)));
+        WindowMaker windowMaker = new WindowMaker(shard,genomeLocParser,iterator,shard.getGenomeLocs());
+        WindowMaker.WindowMakerIterator window = windowMaker.next();
+        LocusShardDataProvider dataProvider = new LocusShardDataProvider(shard, window.getSourceInfo(), genomeLocParser, window.getLocus(), window, null, null);
+        LocusView view = createView(dataProvider);
+
+        testReadsInContext(view, shard.getGenomeLocs(), Collections.singletonList(read));
+    }
+
+    @Test
+    public void readOverlappingEndTest() {
+        GATKSAMRecord read = buildSAMRecord("read1","chr1", 6, 15);
+        SAMRecordIterator iterator = new SAMRecordIterator(read);
+
+        Shard shard = new MockLocusShard(genomeLocParser,Collections.singletonList(genomeLocParser.createGenomeLoc("chr1", 1, 10)));
+        WindowMaker windowMaker = new WindowMaker(shard,genomeLocParser,iterator,shard.getGenomeLocs());
+        WindowMaker.WindowMakerIterator window = windowMaker.next();
+        LocusShardDataProvider dataProvider = new LocusShardDataProvider(shard, window.getSourceInfo(), genomeLocParser, window.getLocus(), window, null, null);
+        LocusView view = createView(dataProvider);
+
+        testReadsInContext(view, shard.getGenomeLocs(), Collections.singletonList(read));
+    }
+
+    @Test
+    public void readsSpanningTest() {
+        GATKSAMRecord read1 = buildSAMRecord("read1","chr1", 1, 5);
+        GATKSAMRecord read2 = buildSAMRecord("read2","chr1", 6, 10);
+        SAMRecordIterator iterator = new SAMRecordIterator(read1, read2);
+
+        Shard shard = new MockLocusShard(genomeLocParser,Collections.singletonList(genomeLocParser.createGenomeLoc("chr1", 1, 10)));
+        WindowMaker windowMaker = new WindowMaker(shard,genomeLocParser,iterator,shard.getGenomeLocs());
+        WindowMaker.WindowMakerIterator window = windowMaker.next();
+        LocusShardDataProvider dataProvider = new LocusShardDataProvider(shard, window.getSourceInfo(), genomeLocParser, window.getLocus(), window, null, null);
+        LocusView view = createView(dataProvider);
+
+        List<GATKSAMRecord> expectedReads = new ArrayList<GATKSAMRecord>();
+        Collections.addAll(expectedReads, read1, read2);
+        testReadsInContext(view, shard.getGenomeLocs(), expectedReads);
+    }
+
+    @Test
+    public void duplicateReadsTest() {
+        GATKSAMRecord read1 = buildSAMRecord("read1","chr1", 1, 5);
+        GATKSAMRecord read2 = buildSAMRecord("read2","chr1", 1, 5);
+        GATKSAMRecord read3 = buildSAMRecord("read3","chr1", 6, 10);
+        GATKSAMRecord read4 = buildSAMRecord("read4","chr1", 6, 10);
+        SAMRecordIterator iterator = new SAMRecordIterator(read1, read2, read3, read4);
+
+        Shard shard = new MockLocusShard(genomeLocParser,Collections.singletonList(genomeLocParser.createGenomeLoc("chr1", 1, 10)));
+        WindowMaker windowMaker = new WindowMaker(shard,genomeLocParser,iterator,shard.getGenomeLocs());
+        WindowMaker.WindowMakerIterator window = windowMaker.next();
+        LocusShardDataProvider dataProvider = new LocusShardDataProvider(shard, window.getSourceInfo(), genomeLocParser, window.getLocus(), window, null, null);
+        LocusView view = createView(dataProvider);
+
+        List<GATKSAMRecord> expectedReads = new ArrayList<GATKSAMRecord>();
+        Collections.addAll(expectedReads, read1, read2, read3, read4);
+        testReadsInContext(view, shard.getGenomeLocs(), expectedReads);
+    }
+
+    @Test
+    public void cascadingReadsWithinBoundsTest() {
+        GATKSAMRecord read1 = buildSAMRecord("read1","chr1", 2, 6);
+        GATKSAMRecord read2 = buildSAMRecord("read2","chr1", 3, 7);
+        GATKSAMRecord read3 = buildSAMRecord("read3","chr1", 4, 8);
+        GATKSAMRecord read4 = buildSAMRecord("read4","chr1", 5, 9);
+        SAMRecordIterator iterator = new SAMRecordIterator(read1, read2, read3, read4);
+
+        Shard shard = new MockLocusShard(genomeLocParser,Collections.singletonList(genomeLocParser.createGenomeLoc("chr1", 1, 10)));
+        WindowMaker windowMaker = new WindowMaker(shard,genomeLocParser,iterator,shard.getGenomeLocs());
+        WindowMaker.WindowMakerIterator window = windowMaker.next();
+        LocusShardDataProvider dataProvider = new LocusShardDataProvider(shard, window.getSourceInfo(), genomeLocParser, window.getLocus(), window, null, null);
+        LocusView view = createView(dataProvider);
+
+        List<GATKSAMRecord> expectedReads = new ArrayList<GATKSAMRecord>();
+        Collections.addAll(expectedReads, read1, read2, read3, read4);
+        testReadsInContext(view, shard.getGenomeLocs(), expectedReads);
+    }
+
+    @Test
+    public void cascadingReadsAtBoundsTest() {
+        GATKSAMRecord read1 = buildSAMRecord("read1","chr1", 1, 5);
+        GATKSAMRecord read2 = buildSAMRecord("read2","chr1", 2, 6);
+        GATKSAMRecord read3 = buildSAMRecord("read3","chr1", 3, 7);
+        GATKSAMRecord read4 = buildSAMRecord("read4","chr1", 4, 8);
+        GATKSAMRecord read5 = buildSAMRecord("read5","chr1", 5, 9);
+        GATKSAMRecord read6 = buildSAMRecord("read6","chr1", 6, 10);
+        SAMRecordIterator iterator = new SAMRecordIterator(read1, read2, read3, read4, read5, read6);
+
+        Shard shard = new MockLocusShard(genomeLocParser,Collections.singletonList(genomeLocParser.createGenomeLoc("chr1", 1, 10)));
+        WindowMaker windowMaker = new WindowMaker(shard,genomeLocParser,iterator,shard.getGenomeLocs());
+        WindowMaker.WindowMakerIterator window = windowMaker.next();
+        LocusShardDataProvider dataProvider = new LocusShardDataProvider(shard, window.getSourceInfo(), genomeLocParser, window.getLocus(), window, null, null);
+        LocusView view = createView(dataProvider);
+
+        List<GATKSAMRecord> expectedReads = new ArrayList<GATKSAMRecord>();
+        Collections.addAll(expectedReads, read1, read2, read3, read4, read5, read6);
+        testReadsInContext(view, shard.getGenomeLocs(), expectedReads);
+    }
+
+    @Test
+    public void cascadingReadsOverlappingBoundsTest() {
+        GATKSAMRecord read01 = buildSAMRecord("read1","chr1", 1, 5);
+        GATKSAMRecord read02 = buildSAMRecord("read2","chr1", 2, 6);
+        GATKSAMRecord read03 = buildSAMRecord("read3","chr1", 3, 7);
+        GATKSAMRecord read04 = buildSAMRecord("read4","chr1", 4, 8);
+        GATKSAMRecord read05 = buildSAMRecord("read5","chr1", 5, 9);
+        GATKSAMRecord read06 = buildSAMRecord("read6","chr1", 6, 10);
+        GATKSAMRecord read07 = buildSAMRecord("read7","chr1", 7, 11);
+        GATKSAMRecord read08 = buildSAMRecord("read8","chr1", 8, 12);
+        GATKSAMRecord read09 = buildSAMRecord("read9","chr1", 9, 13);
+        GATKSAMRecord read10 = buildSAMRecord("read10","chr1", 10, 14);
+        GATKSAMRecord read11 = buildSAMRecord("read11","chr1", 11, 15);
+        GATKSAMRecord read12 = buildSAMRecord("read12","chr1", 12, 16);
+        SAMRecordIterator iterator = new SAMRecordIterator(read01, read02, read03, read04, read05, read06,
+                                                           read07, read08, read09, read10, read11, read12);
+
+        Shard shard = new MockLocusShard(genomeLocParser,Collections.singletonList(genomeLocParser.createGenomeLoc("chr1", 6, 15)));
+        WindowMaker windowMaker = new WindowMaker(shard,genomeLocParser,iterator,shard.getGenomeLocs());
+        WindowMaker.WindowMakerIterator window = windowMaker.next();
+        LocusShardDataProvider dataProvider = new LocusShardDataProvider(shard, window.getSourceInfo(), genomeLocParser, window.getLocus(), window, null, null);
+        LocusView view = createView(dataProvider);
+
+        List<GATKSAMRecord> expectedReads = new ArrayList<GATKSAMRecord>();
+        Collections.addAll(expectedReads, read01, read02, read03, read04, read05, read06,
+                           read07, read08, read09, read10, read11, read12);
+        testReadsInContext(view, shard.getGenomeLocs(), expectedReads);
+    }
+
+    /**
+     * Creates a view of the type required for testing.
+     *
+     * @return The correct view to test.
+     */
+    protected abstract LocusView createView(LocusShardDataProvider provider);
+
+    /**
+     * Test the reads according to an independently derived context.
+     *
+     * @param view
+     * @param bounds
+     * @param reads
+     */
+    protected abstract void testReadsInContext(LocusView view, List<GenomeLoc> bounds, List<GATKSAMRecord> reads);
+
+    /**
+     * Fake a reference sequence file.  Essentially, seek a header with a bunch of dummy data.
+     *
+     * @return A 'fake' reference sequence file
+     */
+    private static ReferenceSequenceFile fakeReferenceSequenceFile() {
+        return new ReferenceSequenceFile() {
+            public SAMSequenceDictionary getSequenceDictionary() {
+                SAMSequenceRecord sequenceRecord = new SAMSequenceRecord("chr1", 1000000);
+                SAMSequenceDictionary dictionary = new SAMSequenceDictionary(Collections.singletonList(sequenceRecord));
+                return dictionary;
+            }
+
+            public boolean isIndexed() { return false; }
+
+            public ReferenceSequence nextSequence() {
+                throw new UnsupportedOperationException("Fake implementation doesn't support a getter");
+            }
+
+            public ReferenceSequence getSequence( String contig ) {
+                throw new UnsupportedOperationException("Fake implementation doesn't support a getter");
+            }
+
+            public ReferenceSequence getSubsequenceAt( String contig, long start, long stop ) {
+                throw new UnsupportedOperationException("Fake implementation doesn't support a getter");
+            }
+
+            public void reset() {
+                return;
+            }
+
+            public void close() throws IOException {
+            }
+        };
+    }
+
+    /**
+     * Build a SAM record featuring the absolute minimum required dataset.
+     *
+     * @param contig         Contig to populate.
+     * @param alignmentStart start of alignment
+     * @param alignmentEnd   end of alignment
+     *
+     * @return New SAM Record
+     */
+    protected GATKSAMRecord buildSAMRecord(String readName, String contig, int alignmentStart, int alignmentEnd) {
+        SAMFileHeader header = new SAMFileHeader();
+        header.setSequenceDictionary(sequenceSourceFile.getSequenceDictionary());
+
+        GATKSAMRecord record = new GATKSAMRecord(header);
+
+        record.setReadName(readName);
+        record.setReferenceIndex(sequenceSourceFile.getSequenceDictionary().getSequenceIndex(contig));
+        record.setAlignmentStart(alignmentStart);
+        Cigar cigar = new Cigar();
+        int len = alignmentEnd - alignmentStart + 1;
+        cigar.add(new CigarElement(len, CigarOperator.M));
+        record.setCigar(cigar);
+        record.setReadBases(new byte[len]);
+        record.setBaseQualities(new byte[len]);
+        return record;
+    }
+
+    /** A simple iterator which iterates over a list of reads. */
+    protected class SAMRecordIterator implements GATKSAMIterator {
+        private Iterator<SAMRecord> backingIterator = null;
+
+        public SAMRecordIterator(SAMRecord... reads) {
+            List<SAMRecord> backingList = new ArrayList<SAMRecord>();
+            backingList.addAll(Arrays.asList(reads));
+            backingIterator = backingList.iterator();
+        }
+
+        public boolean hasNext() {
+            return backingIterator.hasNext();
+        }
+
+        public SAMRecord next() {
+            return backingIterator.next();
+        }
+
+        public Iterator<SAMRecord> iterator() {
+            return this;
+        }
+
+        public void close() {
+            // NO-OP.
+        }
+
+        public void remove() {
+            throw new UnsupportedOperationException("Can't remove from a read-only iterator");
+        }
+    }
+
+
+}
diff --git a/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/engine/datasources/providers/ReadReferenceViewUnitTest.java b/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/engine/datasources/providers/ReadReferenceViewUnitTest.java
new file mode 100644
index 0000000..8bf4f41
--- /dev/null
+++ b/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/engine/datasources/providers/ReadReferenceViewUnitTest.java
@@ -0,0 +1,160 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.engine.datasources.providers;
+
+import org.testng.Assert;
+import org.broadinstitute.gatk.utils.GenomeLoc;
+
+import org.testng.annotations.Test;
+
+import htsjdk.samtools.*;
+import htsjdk.samtools.reference.ReferenceSequence;
+
+/*
+ * 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.
+ */
+
+/**
+ * User: hanna
+ * Date: May 27, 2009
+ * Time: 1:04:27 PM
+ *
+ */
+
+/**
+ * Test reading the reference for a given read.
+ */
+
+public class ReadReferenceViewUnitTest extends ReferenceViewTemplate {
+
+
+    /**
+     * tests that the ReadReferenceView correctly generates X's when a read overhangs the
+     * end of a contig
+     */
+    @Test
+    public void testOverhangingRead() {
+        testOverhangingGivenSize(25,0);
+        testOverhangingGivenSize(25,12);
+        testOverhangingGivenSize(25,24);
+    }
+
+
+    /**
+     * a private method, that tests getting the read sequence for reads that overlap the end of the
+     * contig
+     * @param readLength the length of the read
+     * @param overlap the amount of overlap
+     */
+    private void testOverhangingGivenSize(int readLength, int overlap) {
+        SAMSequenceRecord selectedContig = sequenceFile.getSequenceDictionary().getSequences().get(sequenceFile.getSequenceDictionary().getSequences().size()-1);
+        final long contigStart = selectedContig.getSequenceLength() - (readLength - overlap - 1);
+        final long contigStop = selectedContig.getSequenceLength() + overlap;
+
+        ReadShardDataProvider dataProvider = new ReadShardDataProvider(null,genomeLocParser,null,sequenceFile,null);
+        ReadReferenceView view = new ReadReferenceView(dataProvider);
+
+        SAMRecord rec = buildSAMRecord(selectedContig.getSequenceName(),(int)contigStart,(int)contigStop);
+        ReferenceSequence expectedAsSeq = sequenceFile.getSubsequenceAt(selectedContig.getSequenceName(),(int)contigStart,selectedContig.getSequenceLength());
+        //char[] expected = StringUtil.bytesToString(expectedAsSeq.getBases()).toCharArray();
+        byte[] expected = expectedAsSeq.getBases();
+        byte[] actual = view.getReferenceBases(rec);
+
+        Assert.assertEquals((readLength - overlap), expected.length);
+        Assert.assertEquals(readLength, actual.length);
+        int xRange = 0;
+        for (; xRange < (readLength - overlap); xRange++) {
+            Assert.assertTrue(actual[xRange] != 'X');
+        }
+        for (; xRange < actual.length; xRange++) {
+            Assert.assertTrue(actual[xRange] == 'X');
+        }
+    }
+
+
+    /**
+     * Compares the contents of the fasta and view at a specified location.
+     * @param loc the location to validate
+     */
+    protected void validateLocation( GenomeLoc loc ) {
+        SAMRecord read = buildSAMRecord( loc.getContig(), (int)loc.getStart(), (int)loc.getStop() );
+
+        ReadShardDataProvider dataProvider = new ReadShardDataProvider(null,genomeLocParser,null,sequenceFile,null);
+        ReadReferenceView view = new ReadReferenceView(dataProvider);
+
+        ReferenceSequence expectedAsSeq = sequenceFile.getSubsequenceAt(loc.getContig(),loc.getStart(),loc.getStop());
+        byte[] expected = expectedAsSeq.getBases();
+        byte[] actual = view.getReferenceBases(read);
+
+        org.testng.Assert.assertEquals(actual,expected,String.format("Base array at  in shard %s does not match expected",loc.toString()));
+    }
+
+
+    /**
+     * Build a SAM record featuring the absolute minimum required dataset.
+     * TODO: Blatantly copied from LocusViewTemplate.  Refactor these into a set of tools.
+     * @param contig Contig to populate.
+     * @param alignmentStart start of alignment
+     * @param alignmentEnd end of alignment
+     * @return New SAM Record
+     */
+    protected SAMRecord buildSAMRecord( String contig, int alignmentStart, int alignmentEnd ) {
+        SAMFileHeader header = new SAMFileHeader();
+        header.setSequenceDictionary(sequenceFile.getSequenceDictionary());
+
+        SAMRecord record = new SAMRecord(header);
+
+        record.setReferenceIndex(sequenceFile.getSequenceDictionary().getSequenceIndex(contig));
+        record.setAlignmentStart(alignmentStart);
+        Cigar cigar = new Cigar();
+        cigar.add(new CigarElement(alignmentEnd-alignmentStart+1, CigarOperator.M));
+        record.setCigar(cigar);
+        return record;
+    }
+
+
+}
diff --git a/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/engine/datasources/providers/ReferenceOrderedViewUnitTest.java b/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/engine/datasources/providers/ReferenceOrderedViewUnitTest.java
new file mode 100644
index 0000000..fdec858
--- /dev/null
+++ b/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/engine/datasources/providers/ReferenceOrderedViewUnitTest.java
@@ -0,0 +1,157 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.engine.datasources.providers;
+
+import htsjdk.tribble.Feature;
+import org.broadinstitute.gatk.utils.commandline.RodBinding;
+import org.broadinstitute.gatk.utils.commandline.Tags;
+import org.broadinstitute.gatk.engine.datasources.reads.MockLocusShard;
+import org.broadinstitute.gatk.engine.datasources.rmd.ReferenceOrderedDataSource;
+import org.broadinstitute.gatk.engine.refdata.tracks.RMDTrackBuilder;
+import org.broadinstitute.gatk.engine.refdata.utils.RMDTriplet;
+import org.testng.Assert;
+import org.broadinstitute.gatk.utils.BaseTest;
+import org.broadinstitute.gatk.engine.datasources.reads.Shard;
+import org.broadinstitute.gatk.engine.refdata.RefMetaDataTracker;
+import org.broadinstitute.gatk.utils.codecs.table.TableFeature;
+import org.broadinstitute.gatk.engine.refdata.utils.RMDTriplet.RMDStorageType;
+import org.broadinstitute.gatk.utils.GenomeLocParser;
+import org.broadinstitute.gatk.utils.fasta.CachingIndexedFastaSequenceFile;
+
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.Test;
+
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.util.Arrays;
+import java.util.Collections;
+
+import htsjdk.samtools.reference.IndexedFastaSequenceFile;
+/**
+ * User: hanna
+ * Date: May 27, 2009
+ * Time: 3:07:23 PM
+ * BROAD INSTITUTE SOFTWARE COPYRIGHT NOTICE AND AGREEMENT
+ * Software and documentation are copyright 2005 by the Broad Institute.
+ * All rights are reserved.
+ *
+ * Users acknowledge that this software is supplied without any warranty or support.
+ * The Broad Institute is not responsible for its use, misuse, or
+ * functionality.
+ */
+
+/**
+ * Test the transparent view into the reference-ordered data.  At the moment, just do some basic bindings and make
+ * sure the data comes through correctly.
+ */
+public class ReferenceOrderedViewUnitTest extends BaseTest {
+    /**
+     * Sequence file.
+     */
+    private static IndexedFastaSequenceFile seq;
+    private GenomeLocParser genomeLocParser;
+
+    /**
+     * our track builder
+     */
+    RMDTrackBuilder builder = null;
+
+    @BeforeClass
+    public void init() throws FileNotFoundException {
+        // sequence
+        seq = new CachingIndexedFastaSequenceFile(new File(hg18Reference));
+        genomeLocParser = new GenomeLocParser(seq);
+        // disable auto-index creation/locking in the RMDTrackBuilder for tests
+        builder = new RMDTrackBuilder(seq.getSequenceDictionary(),genomeLocParser,null,true,null);
+    }
+
+    /**
+     * Make sure binding to an empty list produces an empty tracker.
+     */
+    @Test
+    public void testNoBindings() {
+        Shard shard = new MockLocusShard(genomeLocParser,Collections.singletonList(genomeLocParser.createGenomeLoc("chrM",1,30)));
+        LocusShardDataProvider provider = new LocusShardDataProvider(shard, null, genomeLocParser, shard.getGenomeLocs().get(0), null, seq, Collections.<ReferenceOrderedDataSource>emptyList());
+        ReferenceOrderedView view = new ManagingReferenceOrderedView( provider );
+
+        RefMetaDataTracker tracker = view.getReferenceOrderedDataAtLocus(genomeLocParser.createGenomeLoc("chrM",10));
+        Assert.assertEquals(tracker.getValues(Feature.class).size(), 0, "The tracker should not have produced any data");
+    }
+
+    /**
+     * Test a single ROD binding.
+     */
+    @Test
+    public void testSingleBinding() {
+        String fileName = privateTestDir + "TabularDataTest.dat";
+        RMDTriplet triplet = new RMDTriplet("tableTest","Table",fileName,RMDStorageType.FILE,new Tags());
+        ReferenceOrderedDataSource dataSource = new ReferenceOrderedDataSource(triplet,builder,seq.getSequenceDictionary(),genomeLocParser,false);
+
+        Shard shard = new MockLocusShard(genomeLocParser,Collections.singletonList(genomeLocParser.createGenomeLoc("chrM",1,30)));
+
+        LocusShardDataProvider provider = new LocusShardDataProvider(shard, null, genomeLocParser, shard.getGenomeLocs().get(0), null, seq, Collections.singletonList(dataSource));
+        ReferenceOrderedView view = new ManagingReferenceOrderedView( provider );
+
+        RefMetaDataTracker tracker = view.getReferenceOrderedDataAtLocus(genomeLocParser.createGenomeLoc("chrM",20));
+        TableFeature datum = tracker.getFirstValue(new RodBinding<TableFeature>(TableFeature.class, "tableTest"));
+
+        Assert.assertEquals(datum.get("COL1"),"C","datum parameter for COL1 is incorrect");
+        Assert.assertEquals(datum.get("COL2"),"D","datum parameter for COL2 is incorrect");
+        Assert.assertEquals(datum.get("COL3"),"E","datum parameter for COL3 is incorrect");
+    }
+
+    /**
+     * Make sure multiple bindings are visible from the view.
+     */
+    @Test
+    public void testMultipleBinding() {
+        File file = new File(privateTestDir + "TabularDataTest.dat");
+
+        RMDTriplet testTriplet1 = new RMDTriplet("tableTest1","Table",file.getAbsolutePath(),RMDStorageType.FILE,new Tags());
+        ReferenceOrderedDataSource dataSource1 = new ReferenceOrderedDataSource(testTriplet1,builder,seq.getSequenceDictionary(),genomeLocParser,false);
+
+        RMDTriplet testTriplet2 = new RMDTriplet("tableTest2","Table",file.getAbsolutePath(),RMDStorageType.FILE,new Tags());
+        ReferenceOrderedDataSource dataSource2 = new ReferenceOrderedDataSource(testTriplet2,builder,seq.getSequenceDictionary(),genomeLocParser,false);
+
+        Shard shard = new MockLocusShard(genomeLocParser,Collections.singletonList(genomeLocParser.createGenomeLoc("chrM",1,30)));
+
+        LocusShardDataProvider provider = new LocusShardDataProvider(shard, null, genomeLocParser, shard.getGenomeLocs().get(0), null, seq, Arrays.asList(dataSource1,dataSource2));
+        ReferenceOrderedView view = new ManagingReferenceOrderedView( provider );
+
+        RefMetaDataTracker tracker = view.getReferenceOrderedDataAtLocus(genomeLocParser.createGenomeLoc("chrM",20));
+        TableFeature datum1 = tracker.getFirstValue(new RodBinding<TableFeature>(TableFeature.class, "tableTest1"));
+
+        Assert.assertEquals(datum1.get("COL1"),"C","datum1 parameter for COL1 is incorrect");
+        Assert.assertEquals(datum1.get("COL2"),"D","datum1 parameter for COL2 is incorrect");
+        Assert.assertEquals(datum1.get("COL3"),"E","datum1 parameter for COL3 is incorrect");
+
+        TableFeature datum2 = tracker.getFirstValue(new RodBinding<TableFeature>(TableFeature.class, "tableTest2"));
+
+        Assert.assertEquals(datum2.get("COL1"),"C","datum2 parameter for COL1 is incorrect");
+        Assert.assertEquals(datum2.get("COL2"),"D","datum2 parameter for COL2 is incorrect");
+        Assert.assertEquals(datum2.get("COL3"),"E","datum2 parameter for COL3 is incorrect");
+    }
+}
diff --git a/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/engine/datasources/providers/ReferenceViewTemplate.java b/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/engine/datasources/providers/ReferenceViewTemplate.java
new file mode 100644
index 0000000..bffd23d
--- /dev/null
+++ b/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/engine/datasources/providers/ReferenceViewTemplate.java
@@ -0,0 +1,122 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.engine.datasources.providers;
+
+import htsjdk.samtools.SAMSequenceRecord;
+import htsjdk.samtools.reference.IndexedFastaSequenceFile;
+import org.broadinstitute.gatk.utils.BaseTest;
+import org.broadinstitute.gatk.utils.GenomeLoc;
+import org.broadinstitute.gatk.utils.GenomeLocParser;
+import org.broadinstitute.gatk.utils.fasta.CachingIndexedFastaSequenceFile;
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.Test;
+
+import java.io.File;
+import java.io.FileNotFoundException;
+/**
+ * User: hanna
+ * Date: May 27, 2009
+ * Time: 1:12:35 PM
+ * BROAD INSTITUTE SOFTWARE COPYRIGHT NOTICE AND AGREEMENT
+ * Software and documentation are copyright 2005 by the Broad Institute.
+ * All rights are reserved.
+ *
+ * Users acknowledge that this software is supplied without any warranty or support.
+ * The Broad Institute is not responsible for its use, misuse, or
+ * functionality.
+ */
+
+/**
+ * Template for testing reference views (ReadReferenceView and LocusReferenceView).
+ */
+
+public abstract class ReferenceViewTemplate extends BaseTest {
+    /**
+     * The fasta, for comparison.
+     */
+    protected IndexedFastaSequenceFile sequenceFile = null;
+    protected GenomeLocParser genomeLocParser = null;
+
+    //
+    // The bulk of sequence retrieval is tested by IndexedFastaSequenceFile, but we'll run a few spot
+    // checks here to make sure that data is flowing through the LocusReferenceView.
+
+    /**
+     * Initialize the fasta.
+     */
+    @BeforeClass
+    public void initialize() throws FileNotFoundException {
+        sequenceFile = new CachingIndexedFastaSequenceFile( new File(hg18Reference) );
+        genomeLocParser = new GenomeLocParser(sequenceFile);
+    }
+
+    /**
+     * Test the initial fasta location.
+     */
+    @Test
+    public void testReferenceStart() {
+        validateLocation( genomeLocParser.createGenomeLoc(sequenceFile.getSequenceDictionary().getSequence(0).getSequenceName(),1,25) );
+    }
+
+    /**
+     * Test the end of a contig.
+     */
+    @Test
+    public void testReferenceEnd() {
+        // Test the last 25 bases of the first contig.
+        SAMSequenceRecord selectedContig = sequenceFile.getSequenceDictionary().getSequences().get(sequenceFile.getSequenceDictionary().getSequences().size()-1);
+        final int contigStart = selectedContig.getSequenceLength() - 24;
+        final int contigStop = selectedContig.getSequenceLength();
+        validateLocation( genomeLocParser.createGenomeLoc(selectedContig.getSequenceName(),contigStart,contigStop) );
+    }
+
+    /**
+     * Test the start of the middle contig.
+     */
+    @Test
+    public void testContigStart() {
+        // Test the last 25 bases of the first contig.
+        int contigPosition = sequenceFile.getSequenceDictionary().getSequences().size()/2;
+        SAMSequenceRecord selectedContig = sequenceFile.getSequenceDictionary().getSequences().get(contigPosition);
+        validateLocation( genomeLocParser.createGenomeLoc(selectedContig.getSequenceName(),1,25) );
+    }
+
+
+    /**
+     * Test the end of the middle contig.
+     */
+    @Test
+    public void testContigEnd() {
+        // Test the last 25 bases of the first contig.
+        int contigPosition = sequenceFile.getSequenceDictionary().getSequences().size()/2;
+        SAMSequenceRecord selectedContig = sequenceFile.getSequenceDictionary().getSequences().get(contigPosition);
+        final int contigStart = selectedContig.getSequenceLength() - 24;
+        final int contigStop = selectedContig.getSequenceLength();
+        validateLocation( genomeLocParser.createGenomeLoc(selectedContig.getSequenceName(),contigStart,contigStop) );
+    }
+
+    protected abstract void validateLocation( GenomeLoc loc );
+}
diff --git a/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/engine/datasources/providers/ShardDataProviderUnitTest.java b/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/engine/datasources/providers/ShardDataProviderUnitTest.java
new file mode 100644
index 0000000..251eec4
--- /dev/null
+++ b/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/engine/datasources/providers/ShardDataProviderUnitTest.java
@@ -0,0 +1,152 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.engine.datasources.providers;
+
+import org.testng.Assert;
+import org.broadinstitute.gatk.utils.exceptions.ReviewedGATKException;
+import org.testng.annotations.BeforeMethod;
+
+
+import org.testng.annotations.Test;
+import org.broadinstitute.gatk.utils.BaseTest;
+
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Arrays;
+/**
+ * User: hanna
+ * Date: May 27, 2009
+ * Time: 1:56:02 PM
+ * BROAD INSTITUTE SOFTWARE COPYRIGHT NOTICE AND AGREEMENT
+ * Software and documentation are copyright 2005 by the Broad Institute.
+ * All rights are reserved.
+ *
+ * Users acknowledge that this software is supplied without any warranty or support.
+ * The Broad Institute is not responsible for its use, misuse, or
+ * functionality.
+ */
+
+/**
+ * Test basic functionality of the shard data provider.
+ */
+
+public class ShardDataProviderUnitTest extends BaseTest {
+    /**
+     * Provider to test.  Should be recreated for every test.
+     */
+    private ShardDataProvider provider = null;
+
+    @BeforeMethod
+    public void createProvider() {
+        provider = new LocusShardDataProvider( null,null,null,null,null,null,null );
+    }
+
+    /**
+     * Test whether views are closed when the provider closes.
+     */
+    @Test
+    public void testClose() {
+        TestView testView = new TestView( provider );
+        Assert.assertFalse(testView.closed,"View is currently closed but should be open");
+
+        provider.close();
+        Assert.assertTrue(testView.closed,"View is currently open but should be closed");
+    }
+
+    /**
+     * Test whether multiple of the same view can be registered and all get a close method.
+     */
+    @Test
+    public void testMultipleClose() {
+        Collection<TestView> testViews = Arrays.asList(new TestView(provider),new TestView(provider));
+        for( TestView testView: testViews )
+            Assert.assertFalse(testView.closed,"View is currently closed but should be open");
+
+        provider.close();
+        for( TestView testView: testViews )
+            Assert.assertTrue(testView.closed,"View is currently open but should be closed");
+    }
+
+    /**
+     * Try adding a view which conflicts with some other view that's already been registered.
+     */
+    @Test(expectedExceptions= ReviewedGATKException.class)
+    public void testAddViewWithExistingConflict() {
+        View initial = new ConflictingTestView( provider );
+        View conflictsWithInitial = new TestView( provider );
+    }
+
+    /**
+     * Try adding a view which has a conflict with a previously registered view.
+     */
+    @Test(expectedExceptions= ReviewedGATKException.class)
+    public void testAddViewWithNewConflict() {
+        View conflictsWithInitial = new TestView( provider );
+        View initial = new ConflictingTestView( provider );
+    }
+
+    /**
+     * A simple view for testing interactions between views attached to the ShardDataProvider.
+     */
+    private class TestView implements View {
+        /**
+         * Is the test view currently closed.
+         */
+        private boolean closed = false;
+
+        /**
+         * Create a new test view wrapping the given provider.
+         * @param provider
+         */
+        public TestView( ShardDataProvider provider ) {
+            provider.register(this);            
+        }
+
+        /**
+         * Gets conflicting views.  In this case, none conflict.
+         * @return
+         */
+        public Collection<Class<? extends View>> getConflictingViews() { return Collections.emptyList(); }
+
+        /**
+         * Close this view.
+         */
+        public void close() { this.closed = true; }
+    }
+
+    /**
+     * Another view that conflicts with the one above.
+     */
+    private class ConflictingTestView implements View {
+        public ConflictingTestView( ShardDataProvider provider ) { provider.register(this); }
+
+        public Collection<Class<? extends View>> getConflictingViews() {
+            return Collections.<Class<? extends View>>singleton(TestView.class);
+        }
+
+        public void close() {}
+    }
+}
diff --git a/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/engine/datasources/reads/ActiveRegionShardBalancerUnitTest.java b/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/engine/datasources/reads/ActiveRegionShardBalancerUnitTest.java
new file mode 100644
index 0000000..f1ee6ab
--- /dev/null
+++ b/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/engine/datasources/reads/ActiveRegionShardBalancerUnitTest.java
@@ -0,0 +1,102 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.engine.datasources.reads;
+
+import htsjdk.samtools.SAMFileHeader;
+import htsjdk.samtools.SAMFileSpan;
+import htsjdk.samtools.SAMSequenceRecord;
+import org.broadinstitute.gatk.utils.BaseTest;
+import org.broadinstitute.gatk.utils.GenomeLoc;
+import org.broadinstitute.gatk.utils.GenomeLocParser;
+import org.broadinstitute.gatk.utils.interval.IntervalMergingRule;
+import org.broadinstitute.gatk.utils.sam.ArtificialSAMUtils;
+import org.testng.Assert;
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.Test;
+
+import java.io.FileNotFoundException;
+import java.util.*;
+
+public class ActiveRegionShardBalancerUnitTest extends BaseTest {
+    // example genome loc parser for this test, can be deleted if you don't use the reference
+    private GenomeLocParser genomeLocParser;
+    protected SAMDataSource readsDataSource;
+
+    @BeforeClass
+    public void setup() throws FileNotFoundException {
+        // sequence
+        final SAMFileHeader header = ArtificialSAMUtils.createArtificialSamHeader(10, 0, 10000);
+        genomeLocParser = new GenomeLocParser(header.getSequenceDictionary());
+        readsDataSource = null;
+    }
+
+    @Test
+    public void testMergingManyContigs() {
+        executeTest(genomeLocParser.getContigs().getSequences());
+    }
+
+    @Test
+    public void testMergingAllPointersOnSingleContig() {
+        executeTest(Arrays.asList(genomeLocParser.getContigs().getSequences().get(1)));
+    }
+
+    @Test
+    public void testMergingMultipleDiscontinuousContigs() {
+        final List<SAMSequenceRecord> all = genomeLocParser.getContigs().getSequences();
+        executeTest(Arrays.asList(all.get(1), all.get(3)));
+    }
+
+    private void executeTest(final Collection<SAMSequenceRecord> records) {
+        final ActiveRegionShardBalancer balancer = new ActiveRegionShardBalancer();
+
+        final List<Set<GenomeLoc>> expectedLocs = new LinkedList<>();
+        final List<FilePointer> pointers = new LinkedList<>();
+
+        for ( final SAMSequenceRecord record : records ) {
+            final int size = 10;
+            int end = 0;
+            for ( int i = 0; i < record.getSequenceLength(); i += size) {
+                final int myEnd = i + size - 1;
+                end = myEnd;
+                final GenomeLoc loc = genomeLocParser.createGenomeLoc(record.getSequenceName(), i, myEnd);
+                final Map<SAMReaderID, SAMFileSpan> fileSpans = Collections.emptyMap();
+                final FilePointer fp = new FilePointer(fileSpans, IntervalMergingRule.ALL, Collections.singletonList(loc));
+                pointers.add(fp);
+            }
+            expectedLocs.add(Collections.singleton(genomeLocParser.createGenomeLoc(record.getSequenceName(), 0, end)));
+        }
+
+        balancer.initialize(readsDataSource, pointers.iterator(), genomeLocParser);
+
+        int i = 0;
+        int nShardsFound = 0;
+        for ( final Shard shard : balancer ) {
+            nShardsFound++;
+            Assert.assertEquals(new HashSet<>(shard.getGenomeLocs()), expectedLocs.get(i++));
+        }
+        Assert.assertEquals(nShardsFound, records.size(), "Didn't find exactly one shard for each contig in the sequence dictionary");
+    }
+}
diff --git a/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/engine/datasources/reads/DownsamplerBenchmark.java b/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/engine/datasources/reads/DownsamplerBenchmark.java
new file mode 100644
index 0000000..27c287c
--- /dev/null
+++ b/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/engine/datasources/reads/DownsamplerBenchmark.java
@@ -0,0 +1,94 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.engine.datasources.reads;
+
+import com.google.caliper.Param;
+import org.broadinstitute.gatk.engine.WalkerManager;
+import org.broadinstitute.gatk.engine.downsampling.DownsamplingMethod;
+import org.broadinstitute.gatk.engine.walkers.LocusWalker;
+
+/**
+ * Created by IntelliJ IDEA.
+ * User: mhanna
+ * Date: Apr 22, 2011
+ * Time: 4:02:56 PM
+ * To change this template use File | Settings | File Templates.
+ */
+public class DownsamplerBenchmark extends ReadProcessingBenchmark {
+    @Param
+    private String bamFile;
+
+    @Param
+    private Integer maxReads;
+
+    @Override
+    public String getBAMFile() { return bamFile; }
+
+    @Override
+    public Integer getMaxReads() { return maxReads; }
+
+    @Param
+    private Downsampling downsampling;
+
+//    public void timeDownsampling(int reps) {
+//        for(int i = 0; i < reps; i++) {
+//            SAMFileReader reader = new SAMFileReader(inputFile);
+//            ReadProperties readProperties = new ReadProperties(Collections.<SAMReaderID>singletonList(new SAMReaderID(inputFile,new Tags())),
+//                    reader.getFileHeader(),
+//                    SAMFileHeader.SortOrder.coordinate,
+//                    false,
+//                    SAMFileReader.ValidationStringency.SILENT,
+//                    downsampling.create(),
+//                    new ValidationExclusion(Collections.singletonList(ValidationExclusion.TYPE.ALL)),
+//                    Collections.<ReadFilter>emptyList(),
+//                    Collections.<ReadTransformer>emptyList(),
+//                    false,
+//                    (byte)0,
+//                    false);
+//
+//            GenomeLocParser genomeLocParser = new GenomeLocParser(reader.getFileHeader().getSequenceDictionary());
+//            // Filter unmapped reads.  TODO: is this always strictly necessary?  Who in the GATK normally filters these out?
+//            Iterator<SAMRecord> readIterator = new FilteringIterator(reader.iterator(),new UnmappedReadFilter());
+//            LegacyLocusIteratorByState locusIteratorByState = new LegacyLocusIteratorByState(readIterator,readProperties,genomeLocParser, LegacyLocusIteratorByState.sampleListForSAMWithoutReadGroups());
+//            while(locusIteratorByState.hasNext()) {
+//                locusIteratorByState.next().getLocation();
+//            }
+//            reader.close();
+//        }
+//    }
+
+    private enum Downsampling {
+        NONE {
+            @Override
+            DownsamplingMethod create() { return DownsamplingMethod.NONE; }
+        },
+        PER_SAMPLE {
+            @Override
+            DownsamplingMethod create() { return WalkerManager.getDownsamplingMethod(LocusWalker.class); }
+        };
+        abstract DownsamplingMethod create();
+    }
+}
diff --git a/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/engine/datasources/reads/FilePointerUnitTest.java b/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/engine/datasources/reads/FilePointerUnitTest.java
new file mode 100644
index 0000000..e35f1d5
--- /dev/null
+++ b/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/engine/datasources/reads/FilePointerUnitTest.java
@@ -0,0 +1,129 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.engine.datasources.reads;
+
+import htsjdk.samtools.reference.IndexedFastaSequenceFile;
+import htsjdk.samtools.GATKBAMFileSpan;
+import htsjdk.samtools.GATKChunk;
+import org.broadinstitute.gatk.utils.BaseTest;
+import org.broadinstitute.gatk.utils.commandline.Tags;
+import org.broadinstitute.gatk.utils.GenomeLocParser;
+import org.broadinstitute.gatk.utils.fasta.CachingIndexedFastaSequenceFile;
+import org.broadinstitute.gatk.utils.interval.IntervalMergingRule;
+import org.testng.Assert;
+import org.testng.annotations.BeforeMethod;
+import org.testng.annotations.Test;
+
+import java.io.File;
+import java.io.FileNotFoundException;
+
+/**
+ *
+ */
+public class FilePointerUnitTest extends BaseTest {
+    private IndexedFastaSequenceFile seq;
+    private GenomeLocParser genomeLocParser;
+    private SAMReaderID readerID = new SAMReaderID("samFile",new Tags());
+
+    /**
+     * This function does the setup of our parser, before each method call.
+     * <p/>
+     * Called before every test case method.
+     */
+    @BeforeMethod
+    public void doForEachTest() throws FileNotFoundException {
+        // sequence
+        seq = new CachingIndexedFastaSequenceFile(new File(hg18Reference));
+        genomeLocParser = new GenomeLocParser(seq.getSequenceDictionary());
+    }
+
+    @Test
+    public void testFilePointerCombineDisjoint() {
+        FilePointer one = new FilePointer(IntervalMergingRule.ALL, genomeLocParser.createGenomeLoc("chr1",1,5));
+        one.addFileSpans(readerID,new GATKBAMFileSpan(new GATKChunk(0,1)));
+        FilePointer two = new FilePointer(IntervalMergingRule.ALL, genomeLocParser.createGenomeLoc("chr1",6,10));
+        two.addFileSpans(readerID,new GATKBAMFileSpan(new GATKChunk(1,2)));
+
+        FilePointer result = new FilePointer(IntervalMergingRule.ALL, genomeLocParser.createGenomeLoc("chr1",1,10));
+        result.addFileSpans(readerID,new GATKBAMFileSpan(new GATKChunk(0,2)));
+
+        Assert.assertEquals(one.combine(genomeLocParser,two),result,"Combination of two file pointers is incorrect");
+        Assert.assertEquals(two.combine(genomeLocParser,one),result,"Combination of two file pointers is incorrect");
+
+        //Now test that adjacent (but disjoint) intervals are properly handled with OVERLAPPING_ONLY
+        one = new FilePointer(IntervalMergingRule.OVERLAPPING_ONLY, genomeLocParser.createGenomeLoc("chr1",1,5));
+        one.addFileSpans(readerID,new GATKBAMFileSpan(new GATKChunk(0,1)));
+        two = new FilePointer(IntervalMergingRule.OVERLAPPING_ONLY, genomeLocParser.createGenomeLoc("chr1",6,10));
+        two.addFileSpans(readerID,new GATKBAMFileSpan(new GATKChunk(1,2)));
+
+        result = new FilePointer(IntervalMergingRule.OVERLAPPING_ONLY,
+                genomeLocParser.createGenomeLoc("chr1",1,5),
+                genomeLocParser.createGenomeLoc("chr1",6,10));
+        result.addFileSpans(readerID,new GATKBAMFileSpan(new GATKChunk(0,2)));
+
+        Assert.assertEquals(one.combine(genomeLocParser,two),result,"Combination of two file pointers is incorrect");
+        Assert.assertEquals(two.combine(genomeLocParser,one),result,"Combination of two file pointers is incorrect");
+    }
+
+    @Test
+    public void testFilePointerCombineJoint() {
+        FilePointer one = new FilePointer(IntervalMergingRule.ALL, genomeLocParser.createGenomeLoc("chr1",1,5));
+        one.addFileSpans(readerID,new GATKBAMFileSpan(new GATKChunk(0,2)));
+        FilePointer two = new FilePointer(IntervalMergingRule.ALL, genomeLocParser.createGenomeLoc("chr1",2,6));
+        two.addFileSpans(readerID,new GATKBAMFileSpan(new GATKChunk(1,3)));
+
+        FilePointer result = new FilePointer(IntervalMergingRule.ALL, genomeLocParser.createGenomeLoc("chr1",1,6));
+        result.addFileSpans(readerID,new GATKBAMFileSpan(new GATKChunk(0,3)));        
+
+        Assert.assertEquals(one.combine(genomeLocParser,two),result,"Combination of two file pointers is incorrect");
+        Assert.assertEquals(two.combine(genomeLocParser,one),result,"Combination of two file pointers is incorrect");
+
+        //Repeat the tests for OVERLAPPING_ONLY
+        one = new FilePointer(IntervalMergingRule.OVERLAPPING_ONLY, genomeLocParser.createGenomeLoc("chr1",1,5));
+        one.addFileSpans(readerID,new GATKBAMFileSpan(new GATKChunk(0,2)));
+        two = new FilePointer(IntervalMergingRule.OVERLAPPING_ONLY, genomeLocParser.createGenomeLoc("chr1",2,6));
+        two.addFileSpans(readerID,new GATKBAMFileSpan(new GATKChunk(1,3)));
+
+        result = new FilePointer(IntervalMergingRule.OVERLAPPING_ONLY, genomeLocParser.createGenomeLoc("chr1",1,6));
+        result.addFileSpans(readerID,new GATKBAMFileSpan(new GATKChunk(0,3)));
+
+        Assert.assertEquals(one.combine(genomeLocParser,two),result,"Combination of two file pointers is incorrect");
+        Assert.assertEquals(two.combine(genomeLocParser,one),result,"Combination of two file pointers is incorrect");
+    }
+
+    @Test
+    public void testFilePointerCombineOneSided() {
+        FilePointer filePointer = new FilePointer(IntervalMergingRule.ALL, genomeLocParser.createGenomeLoc("chr1",1,5));
+        filePointer.addFileSpans(readerID,new GATKBAMFileSpan(new GATKChunk(0,1)));
+        FilePointer empty = new FilePointer(IntervalMergingRule.ALL, genomeLocParser.createGenomeLoc("chr1",6,10));
+        // Do not add file spans to empty result
+
+        FilePointer result = new FilePointer(IntervalMergingRule.ALL, genomeLocParser.createGenomeLoc("chr1",1,10));
+        result.addFileSpans(readerID,new GATKBAMFileSpan(new GATKChunk(0,1)));
+        Assert.assertEquals(filePointer.combine(genomeLocParser,empty),result,"Combination of two file pointers is incorrect");
+        Assert.assertEquals(empty.combine(genomeLocParser,filePointer),result,"Combination of two file pointers is incorrect");
+    }
+}
diff --git a/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/engine/datasources/reads/GATKBAMIndexUnitTest.java b/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/engine/datasources/reads/GATKBAMIndexUnitTest.java
new file mode 100644
index 0000000..289a10c
--- /dev/null
+++ b/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/engine/datasources/reads/GATKBAMIndexUnitTest.java
@@ -0,0 +1,108 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.engine.datasources.reads;
+
+import htsjdk.samtools.SAMFileReader;
+import htsjdk.samtools.SAMSequenceDictionary;
+import org.broadinstitute.gatk.utils.BaseTest;
+import org.broadinstitute.gatk.utils.exceptions.UserException;
+import org.testng.Assert;
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.Test;
+
+import java.io.File;
+import java.io.FileNotFoundException;
+
+/**
+ * Test basic functionality in the GATK's implementation of the BAM index classes.
+ */
+public class GATKBAMIndexUnitTest extends BaseTest {
+    private static File bamFile = new File(validationDataLocation+"MV1994.selected.bam");
+
+    /**
+     * Index file forming the source of all unit tests.
+     */
+    private static File bamIndexFile = new File(validationDataLocation+"MV1994.selected.bam.bai");
+
+    /**
+     * Storage for the index itself.
+     */
+    private GATKBAMIndex bamIndex;
+
+    
+    @BeforeClass
+    public void init() throws FileNotFoundException {
+        SAMFileReader reader = new SAMFileReader(bamFile);
+        SAMSequenceDictionary sequenceDictionary = reader.getFileHeader().getSequenceDictionary();
+        reader.close();
+        
+        bamIndex = new GATKBAMIndex(bamIndexFile);
+    }
+
+    @Test
+    public void testNumberAndSizeOfIndexLevels() {
+        // The correct values for this test are pulled directly from the
+        // SAM Format Specification v1.3-r882, Section 4.1.1, last paragraph.
+        Assert.assertEquals(GATKBAMIndex.getNumIndexLevels(),6,"Incorrect number of levels in BAM index");
+
+        // Level 0
+        Assert.assertEquals(GATKBAMIndex.getFirstBinInLevel(0),0);
+        Assert.assertEquals(bamIndex.getLevelSize(0),1);
+
+        // Level 1
+        Assert.assertEquals(GATKBAMIndex.getFirstBinInLevel(1),1);
+        Assert.assertEquals(bamIndex.getLevelSize(1),8-1+1);
+
+        // Level 2
+        Assert.assertEquals(GATKBAMIndex.getFirstBinInLevel(2),9);
+        Assert.assertEquals(bamIndex.getLevelSize(2),72-9+1);
+
+        // Level 3
+        Assert.assertEquals(GATKBAMIndex.getFirstBinInLevel(3),73);
+        Assert.assertEquals(bamIndex.getLevelSize(3),584-73+1);
+
+        // Level 4
+        Assert.assertEquals(GATKBAMIndex.getFirstBinInLevel(4),585);
+        Assert.assertEquals(bamIndex.getLevelSize(4),4680-585+1);
+
+        // Level 5                                
+        Assert.assertEquals(GATKBAMIndex.getFirstBinInLevel(5),4681);
+        Assert.assertEquals(bamIndex.getLevelSize(5),37448-4681+1);
+    }
+
+    @Test( expectedExceptions = UserException.MalformedFile.class )
+    public void testDetectTruncatedBamIndexWordBoundary() {
+        GATKBAMIndex index = new GATKBAMIndex(new File(privateTestDir + "truncated_at_word_boundary.bai"));
+        index.readReferenceSequence(0);
+    }
+
+    @Test( expectedExceptions = UserException.MalformedFile.class )
+    public void testDetectTruncatedBamIndexNonWordBoundary() {
+        GATKBAMIndex index = new GATKBAMIndex(new File(privateTestDir + "truncated_at_non_word_boundary.bai"));
+        index.readReferenceSequence(0);
+    }
+
+}
diff --git a/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/engine/datasources/reads/GATKWalkerBenchmark.java b/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/engine/datasources/reads/GATKWalkerBenchmark.java
new file mode 100644
index 0000000..30eaeb6
--- /dev/null
+++ b/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/engine/datasources/reads/GATKWalkerBenchmark.java
@@ -0,0 +1,141 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.engine.datasources.reads;
+
+import com.google.caliper.Param;
+import org.broadinstitute.gatk.utils.commandline.Tags;
+import org.broadinstitute.gatk.engine.GenomeAnalysisEngine;
+import org.broadinstitute.gatk.engine.arguments.GATKArgumentCollection;
+import org.broadinstitute.gatk.engine.contexts.ReferenceContext;
+import org.broadinstitute.gatk.engine.filters.ReadFilter;
+import org.broadinstitute.gatk.engine.filters.UnmappedReadFilter;
+import org.broadinstitute.gatk.engine.refdata.RefMetaDataTracker;
+import org.broadinstitute.gatk.engine.refdata.utils.RMDTriplet;
+import org.broadinstitute.gatk.engine.walkers.ReadWalker;
+import org.broadinstitute.gatk.engine.walkers.Walker;
+import org.broadinstitute.gatk.tools.walkers.qc.CountLoci;
+import org.broadinstitute.gatk.tools.walkers.qc.CountReads;
+import org.broadinstitute.gatk.utils.classloader.JVMUtils;
+import org.broadinstitute.gatk.utils.sam.GATKSAMRecord;
+
+import java.io.File;
+import java.util.Collections;
+
+/**
+ * Created by IntelliJ IDEA.
+ * User: mhanna
+ * Date: Feb 25, 2011
+ * Time: 10:16:54 AM
+ * To change this template use File | Settings | File Templates.
+ */
+public class GATKWalkerBenchmark extends ReadProcessingBenchmark {
+    @Param
+    private String bamFile;
+
+    @Param
+    private Integer maxReads;
+
+    @Param
+    private String referenceFile;
+
+    @Param
+    private WalkerType walkerType;
+
+    @Override
+    public String getBAMFile() { return bamFile; }
+
+    @Override
+    public Integer getMaxReads() { return maxReads; }    
+
+    @Override
+    public void setUp() {
+        super.setUp();
+    }
+
+    public void timeWalkerPerformance(final int reps) {
+        for(int i = 0; i < reps; i++) {
+            GenomeAnalysisEngine engine = new GenomeAnalysisEngine();
+
+            // Establish the argument collection
+            GATKArgumentCollection argCollection = new GATKArgumentCollection();
+            argCollection.referenceFile = new File(referenceFile);
+            argCollection.samFiles = Collections.singletonList(inputFile.getAbsolutePath());
+
+            engine.setArguments(argCollection);
+            // Bugs in the engine mean that this has to be set twice.
+            engine.setSAMFileIDs(Collections.singletonList(new SAMReaderID(inputFile,new Tags())));
+            engine.setFilters(Collections.<ReadFilter>singletonList(new UnmappedReadFilter()));
+            engine.setReferenceMetaDataFiles(Collections.<RMDTriplet>emptyList());
+
+            // Create the walker
+            engine.setWalker(walkerType.create());
+
+            engine.execute();
+        }
+    }
+
+    private enum WalkerType {
+        COUNT_READS {
+            @Override
+            Walker create() { return new CountReads(); }
+        },
+        COUNT_BASES_IN_READ {
+            @Override
+            Walker create() { return new CountBasesInReadPerformanceWalker(); }
+        },
+        COUNT_LOCI {
+            @Override
+            Walker create() {
+                CountLoci walker = new CountLoci();
+                JVMUtils.setFieldValue(JVMUtils.findField(CountLoci.class,"out"),walker,System.out);
+                return walker;
+            }
+        };
+        abstract Walker create();
+    }
+}
+
+class CountBasesInReadPerformanceWalker extends ReadWalker<Integer,Long> {
+    private long As;
+    private long Cs;
+    private long Gs;
+    private long Ts;
+
+    public Integer map(ReferenceContext ref, GATKSAMRecord read, RefMetaDataTracker tracker) {
+        for(byte base: read.getReadBases()) {
+            switch(base) {
+                case 'A': As++; break;
+                case 'C': Cs++; break;
+                case 'G': Gs++; break;
+                case 'T': Ts++; break;
+            }
+        }
+        return 1;
+    }
+
+    public Long reduceInit() { return 0L; }
+    public Long reduce(Integer value, Long accum) { return value + accum; }
+}
diff --git a/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/engine/datasources/reads/IntervalOverlapFilteringIteratorUnitTest.java b/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/engine/datasources/reads/IntervalOverlapFilteringIteratorUnitTest.java
new file mode 100644
index 0000000..90ac754
--- /dev/null
+++ b/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/engine/datasources/reads/IntervalOverlapFilteringIteratorUnitTest.java
@@ -0,0 +1,150 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.engine.datasources.reads;
+
+import htsjdk.samtools.SAMFileHeader;
+import htsjdk.samtools.SAMRecord;
+import htsjdk.samtools.SAMSequenceRecord;
+import org.broadinstitute.gatk.utils.GenomeLoc;
+import org.broadinstitute.gatk.utils.GenomeLocParser;
+import org.broadinstitute.gatk.utils.exceptions.ReviewedGATKException;
+import org.broadinstitute.gatk.utils.sam.ArtificialSAMUtils;
+import org.testng.Assert;
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.DataProvider;
+import org.testng.annotations.Test;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+public class IntervalOverlapFilteringIteratorUnitTest {
+
+    private SAMFileHeader header;
+    private GenomeLoc firstContig;
+    private GenomeLoc secondContig;
+
+    /** Basic aligned and mapped read. */
+    private SAMRecord readMapped;
+
+    /** Read with no contig specified in the read, -L UNMAPPED */
+    private SAMRecord readNoReference;
+
+    /** This read has a start position, but is flagged that it's not mapped. */
+    private SAMRecord readUnmappedFlag;
+
+    /** This read is from the second contig. */
+    private SAMRecord readSecondContig;
+
+    /** This read says it's aligned, but actually has an unknown start. */
+    private SAMRecord readUnknownStart;
+
+    /** The above reads in the order one would expect to find them in a sorted BAM. */
+    private List<SAMRecord> testReads;
+
+    @BeforeClass
+    public void init() {
+        header = ArtificialSAMUtils.createArtificialSamHeader(3, 1, ArtificialSAMUtils.DEFAULT_READ_LENGTH * 2);
+        GenomeLocParser genomeLocParser = new GenomeLocParser(header.getSequenceDictionary());
+        SAMSequenceRecord record;
+
+        record = header.getSequence(0);
+        firstContig = genomeLocParser.createGenomeLoc(record.getSequenceName(), 1, record.getSequenceLength());
+        record = header.getSequence(1);
+        secondContig = genomeLocParser.createGenomeLoc(record.getSequenceName(), 1, record.getSequenceLength());
+
+        readMapped = createMappedRead("mapped", 1);
+
+        readUnmappedFlag = createMappedRead("unmappedFlagged", 2);
+        readUnmappedFlag.setReadUnmappedFlag(true);
+
+        readSecondContig = createMappedRead("secondContig", 3);
+        readSecondContig.setReferenceName(secondContig.getContig());
+
+        /* This read says it's aligned, but to a contig not in the header. */
+        SAMRecord readUnknownContig = createMappedRead("unknownContig", 4);
+        readUnknownContig.setReferenceName("unknownContig");
+
+        readUnknownStart = createMappedRead("unknownStart", 1);
+        readUnknownStart.setAlignmentStart(SAMRecord.NO_ALIGNMENT_START);
+
+        readNoReference = createUnmappedRead("unmappedNoReference");
+
+        testReads = new ArrayList<SAMRecord>();
+        testReads.add(readMapped);
+        testReads.add(readUnmappedFlag);
+        testReads.add(readUnknownStart);
+        testReads.add(readSecondContig);
+        testReads.add(readUnknownContig);
+        testReads.add(readNoReference);
+    }
+
+    @DataProvider(name = "filteringIteratorTestData")
+    public Object[][] getFilteringIteratorTestData() {
+        return new Object[][] {
+                new Object[] {Arrays.asList(firstContig), Arrays.asList(readMapped, readUnmappedFlag, readUnknownStart)},
+                new Object[] {Arrays.asList(GenomeLoc.UNMAPPED), Arrays.asList(readNoReference)},
+                new Object[] {Arrays.asList(firstContig, secondContig), Arrays.asList(readMapped, readUnmappedFlag, readUnknownStart, readSecondContig)}
+        };
+    }
+
+    @Test(dataProvider = "filteringIteratorTestData")
+    public void testFilteringIterator(List<GenomeLoc> locs, List<SAMRecord> expected) {
+        IntervalOverlapFilteringIterator filterIter = new IntervalOverlapFilteringIterator(
+                ArtificialSAMUtils.createReadIterator(testReads), locs);
+
+        List<SAMRecord> actual = new ArrayList<SAMRecord>();
+        while (filterIter.hasNext()) {
+            actual.add(filterIter.next());
+        }
+        Assert.assertEquals(actual, expected);
+    }
+
+    @Test(expectedExceptions = ReviewedGATKException.class)
+    public void testMappedAndUnmapped() {
+        new IntervalOverlapFilteringIterator(
+                ArtificialSAMUtils.createReadIterator(testReads),
+                Arrays.asList(firstContig, GenomeLoc.UNMAPPED));
+    }
+
+    private SAMRecord createUnmappedRead(String name) {
+        return ArtificialSAMUtils.createArtificialRead(
+                header,
+                name,
+                SAMRecord.NO_ALIGNMENT_REFERENCE_INDEX,
+                SAMRecord.NO_ALIGNMENT_START,
+                ArtificialSAMUtils.DEFAULT_READ_LENGTH);
+    }
+
+    private SAMRecord createMappedRead(String name, int start) {
+        return ArtificialSAMUtils.createArtificialRead(
+                header,
+                name,
+                0,
+                start,
+                ArtificialSAMUtils.DEFAULT_READ_LENGTH);
+    }
+}
diff --git a/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/engine/datasources/reads/MockLocusShard.java b/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/engine/datasources/reads/MockLocusShard.java
new file mode 100644
index 0000000..eb3c894
--- /dev/null
+++ b/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/engine/datasources/reads/MockLocusShard.java
@@ -0,0 +1,51 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.engine.datasources.reads;
+
+import org.broadinstitute.gatk.engine.datasources.reads.LocusShard;
+import org.broadinstitute.gatk.engine.datasources.reads.SAMReaderID;
+import org.broadinstitute.gatk.engine.resourcemanagement.ThreadAllocation;
+import org.broadinstitute.gatk.utils.GenomeLoc;
+import org.broadinstitute.gatk.engine.datasources.reads.SAMDataSource;
+import org.broadinstitute.gatk.utils.GenomeLocParser;
+
+import java.util.List;
+import java.util.Collections;
+
+/**
+ * A mock locus shard, usable for infrastructure that requires a shard to behave properly.
+ *
+ * @author mhanna
+ * @version 0.1
+ */
+public class MockLocusShard extends LocusShard {
+    public MockLocusShard(final GenomeLocParser genomeLocParser,final List<GenomeLoc> intervals) {
+        super(  genomeLocParser,
+                new SAMDataSource(Collections.<SAMReaderID>emptyList(),new ThreadAllocation(),null,genomeLocParser),
+                intervals,
+                null);
+    }
+}
diff --git a/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/engine/datasources/reads/PicardBaselineBenchmark.java b/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/engine/datasources/reads/PicardBaselineBenchmark.java
new file mode 100644
index 0000000..f96a35a
--- /dev/null
+++ b/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/engine/datasources/reads/PicardBaselineBenchmark.java
@@ -0,0 +1,101 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.engine.datasources.reads;
+
+import com.google.caliper.Param;
+import com.google.caliper.SimpleBenchmark;
+import htsjdk.samtools.util.SamLocusIterator;
+import htsjdk.samtools.SAMFileReader;
+import htsjdk.samtools.SAMRecord;
+import htsjdk.samtools.util.CloseableIterator;
+
+import java.io.File;
+import java.util.Iterator;
+
+/**
+ * Created by IntelliJ IDEA.
+ * User: mhanna
+ * Date: Apr 22, 2011
+ * Time: 3:51:06 PM
+ * To change this template use File | Settings | File Templates.
+ */
+public class PicardBaselineBenchmark extends ReadProcessingBenchmark {
+    @Param
+    private String bamFile;
+
+    @Param
+    private Integer maxReads;
+
+    @Override
+    public String getBAMFile() { return bamFile; }
+
+    @Override
+    public Integer getMaxReads() { return maxReads; }
+    
+    public void timeDecompressBamFile(int reps) {
+        for(int i = 0; i < reps; i++) {
+            SAMFileReader reader = new SAMFileReader(inputFile);
+            CloseableIterator<SAMRecord> iterator = reader.iterator();
+            while(iterator.hasNext())
+                iterator.next();
+            iterator.close();
+            reader.close();
+        }
+    }
+
+    public void timeExtractTag(int reps) {
+        for(int i = 0; i < reps; i++) {
+            SAMFileReader reader = new SAMFileReader(inputFile);
+            CloseableIterator<SAMRecord> iterator = reader.iterator();
+            while(iterator.hasNext()) {
+                SAMRecord read = iterator.next();
+                read.getAttribute("OQ");
+            }
+            iterator.close();
+            reader.close();
+        }
+    }
+
+    public void timeSamLocusIterator(int reps) {
+        for(int i = 0; i < reps; i++) {
+            SAMFileReader reader = new SAMFileReader(inputFile);
+            long loci = 0;
+
+            SamLocusIterator samLocusIterator = new SamLocusIterator(reader);
+            samLocusIterator.setEmitUncoveredLoci(false);
+            Iterator<SamLocusIterator.LocusInfo> workhorseIterator = samLocusIterator.iterator();
+
+            while(workhorseIterator.hasNext()) {
+                SamLocusIterator.LocusInfo locusInfo = workhorseIterator.next();
+                // Use the value of locusInfo to avoid optimization.
+                if(locusInfo != null) loci++;
+            }
+            System.out.printf("Total loci = %d%n",loci);
+
+            reader.close();
+        }
+    }
+}
diff --git a/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/engine/datasources/reads/ReadProcessingBenchmark.java b/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/engine/datasources/reads/ReadProcessingBenchmark.java
new file mode 100644
index 0000000..71fc81a
--- /dev/null
+++ b/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/engine/datasources/reads/ReadProcessingBenchmark.java
@@ -0,0 +1,83 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.engine.datasources.reads;
+
+import com.google.caliper.Param;
+import com.google.caliper.SimpleBenchmark;
+import htsjdk.samtools.SAMFileReader;
+import htsjdk.samtools.SAMFileWriter;
+import htsjdk.samtools.SAMFileWriterFactory;
+import htsjdk.samtools.SAMRecord;
+import org.broadinstitute.gatk.utils.exceptions.ReviewedGATKException;
+
+import java.io.File;
+import java.io.IOException;
+
+/**
+ * Created by IntelliJ IDEA.
+ * User: mhanna
+ * Date: Apr 22, 2011
+ * Time: 4:04:38 PM
+ * To change this template use File | Settings | File Templates.
+ */
+public abstract class ReadProcessingBenchmark extends SimpleBenchmark {
+    protected abstract String getBAMFile();
+    protected abstract Integer getMaxReads();
+
+    protected File inputFile;
+
+    @Override
+    public void setUp() {
+        SAMFileReader fullInputFile = new SAMFileReader(new File(getBAMFile()));
+
+        File tempFile = null;
+        try {
+            tempFile = File.createTempFile("testfile_"+getMaxReads(),".bam");
+        }
+        catch(IOException ex) {
+            throw new ReviewedGATKException("Unable to create temporary BAM",ex);
+        }
+        SAMFileWriterFactory factory = new SAMFileWriterFactory();
+        factory.setCreateIndex(true);
+        SAMFileWriter writer = factory.makeBAMWriter(fullInputFile.getFileHeader(),true,tempFile);
+
+        long numReads = 0;
+        for(SAMRecord read: fullInputFile) {
+            if(numReads++ >= getMaxReads())
+                break;
+            writer.addAlignment(read);
+        }
+
+        writer.close();
+
+        inputFile = tempFile;
+    }
+
+    @Override
+    public void tearDown() {
+        inputFile.delete();
+    }
+}
diff --git a/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/engine/datasources/reads/ReadShardBalancerUnitTest.java b/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/engine/datasources/reads/ReadShardBalancerUnitTest.java
new file mode 100644
index 0000000..be48194
--- /dev/null
+++ b/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/engine/datasources/reads/ReadShardBalancerUnitTest.java
@@ -0,0 +1,195 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.engine.datasources.reads;
+
+import htsjdk.samtools.*;
+import org.broadinstitute.gatk.engine.arguments.ValidationExclusion;
+import org.broadinstitute.gatk.engine.downsampling.DownsampleType;
+import org.broadinstitute.gatk.engine.downsampling.DownsamplingMethod;
+import org.broadinstitute.gatk.engine.filters.ReadFilter;
+import org.broadinstitute.gatk.engine.resourcemanagement.ThreadAllocation;
+import org.broadinstitute.gatk.utils.BaseTest;
+import org.broadinstitute.gatk.utils.GenomeLocParser;
+import org.broadinstitute.gatk.utils.commandline.Tags;
+import org.broadinstitute.gatk.utils.sam.ArtificialSAMUtils;
+import org.broadinstitute.gatk.utils.sam.ArtificialSingleSampleReadStream;
+import org.testng.Assert;
+import org.testng.annotations.DataProvider;
+import org.testng.annotations.Test;
+
+import java.io.File;
+import java.util.ArrayList;
+import java.util.Arrays;
+
+public class ReadShardBalancerUnitTest extends BaseTest {
+
+    /**
+     * Tests to ensure that ReadShardBalancer works as expected and does not place shard boundaries
+     * at inappropriate places, such as within an alignment start position
+     */
+    private static class ReadShardBalancerTest extends TestDataProvider {
+        private int numContigs;
+        private int numStacksPerContig;
+        private int stackSize;
+        private int numUnmappedReads;
+        private DownsamplingMethod downsamplingMethod;
+        private int expectedReadCount;
+
+        private SAMFileHeader header;
+        private SAMReaderID testBAM;
+
+        public ReadShardBalancerTest( int numContigs,
+                                      int numStacksPerContig,
+                                      int stackSize,
+                                      int numUnmappedReads,
+                                      int downsamplingTargetCoverage ) {
+            super(ReadShardBalancerTest.class);
+
+            this.numContigs = numContigs;
+            this.numStacksPerContig = numStacksPerContig;
+            this.stackSize = stackSize;
+            this.numUnmappedReads = numUnmappedReads;
+
+            this.downsamplingMethod = new DownsamplingMethod(DownsampleType.BY_SAMPLE, downsamplingTargetCoverage, null);
+            this.expectedReadCount = Math.min(stackSize, downsamplingTargetCoverage) * numStacksPerContig * numContigs + numUnmappedReads;
+
+            setName(String.format("%s: numContigs=%d numStacksPerContig=%d stackSize=%d numUnmappedReads=%d downsamplingTargetCoverage=%d",
+                                  getClass().getSimpleName(), numContigs, numStacksPerContig, stackSize, numUnmappedReads, downsamplingTargetCoverage));
+        }
+
+        public void run() {
+            createTestBAM();
+
+            SAMDataSource dataSource = new SAMDataSource(Arrays.asList(testBAM),
+                                                         new ThreadAllocation(),
+                                                         null,
+                                                         new GenomeLocParser(header.getSequenceDictionary()),
+                                                         false,
+                                                         ValidationStringency.SILENT,
+                                                         ReadShard.DEFAULT_MAX_READS,  // reset ReadShard.MAX_READS to ReadShard.DEFAULT_MAX_READS for each test
+                                                         downsamplingMethod,
+                                                         new ValidationExclusion(),
+                                                         new ArrayList<ReadFilter>(),
+                                                         false);
+
+            Iterable<Shard> shardIterator = dataSource.createShardIteratorOverAllReads(new ReadShardBalancer());
+
+            SAMRecord readAtEndOfLastShard = null;
+            int totalReadsSeen = 0;
+
+            for ( Shard shard : shardIterator ) {
+                int numContigsThisShard = 0;
+                SAMRecord lastRead = null;
+
+                for ( SAMRecord read : shard.iterator() ) {
+                    totalReadsSeen++;
+
+                    if ( lastRead == null ) {
+                        numContigsThisShard = 1;
+                    }
+                    else if ( ! read.getReadUnmappedFlag() && ! lastRead.getReferenceIndex().equals(read.getReferenceIndex()) ) {
+                        numContigsThisShard++;
+                    }
+
+                    // If the last read from the previous shard is not unmapped, we have to make sure
+                    // that no reads in this shard start at the same position
+                    if ( readAtEndOfLastShard != null && ! readAtEndOfLastShard.getReadUnmappedFlag() ) {
+                        Assert.assertFalse(readAtEndOfLastShard.getReferenceIndex().equals(read.getReferenceIndex()) &&
+                                           readAtEndOfLastShard.getAlignmentStart() == read.getAlignmentStart(),
+                                           String.format("Reads from alignment start position %d:%d are split across multiple shards",
+                                                         read.getReferenceIndex(), read.getAlignmentStart()));
+                    }
+
+                    lastRead = read;
+                }
+
+                // There should never be reads from more than 1 contig in a shard (ignoring unmapped reads)
+                Assert.assertTrue(numContigsThisShard == 1, "found a shard with reads from multiple contigs");
+
+                readAtEndOfLastShard = lastRead;
+            }
+
+            Assert.assertEquals(totalReadsSeen, expectedReadCount, "did not encounter the expected number of reads");
+        }
+
+        private void createTestBAM() {
+            header = ArtificialSAMUtils.createArtificialSamHeader(numContigs, 1, 100000);
+            SAMReadGroupRecord readGroup = new SAMReadGroupRecord("foo");
+            readGroup.setSample("testSample");
+            header.addReadGroup(readGroup);
+            ArtificialSingleSampleReadStream artificialReads = new ArtificialSingleSampleReadStream(header,
+                                                                                                    "foo",
+                                                                                                    numContigs,
+                                                                                                    numStacksPerContig,
+                                                                                                    stackSize,
+                                                                                                    stackSize,
+                                                                                                    1,
+                                                                                                    100,
+                                                                                                    50,
+                                                                                                    150,
+                                                                                                    numUnmappedReads);
+
+            final File testBAMFile = createTempFile("SAMDataSourceFillShardBoundaryTest", ".bam");
+
+            SAMFileWriter bamWriter = new SAMFileWriterFactory().setCreateIndex(true).makeBAMWriter(header, true, testBAMFile);
+            for ( SAMRecord read : artificialReads ) {
+                bamWriter.addAlignment(read);
+            }
+            bamWriter.close();
+
+            testBAM =  new SAMReaderID(testBAMFile, new Tags());
+
+            new File(testBAM.getSamFilePath().replace(".bam", ".bai")).deleteOnExit();
+            new File(testBAM.getSamFilePath() + ".bai").deleteOnExit();
+        }
+    }
+
+    @DataProvider(name = "ReadShardBalancerTestDataProvider")
+    public Object[][] createReadShardBalancerTests() {
+        for ( int numContigs = 1; numContigs <= 3; numContigs++ ) {
+            for ( int numStacksPerContig : Arrays.asList(1, 2, 4) ) {
+                // Use crucial read shard boundary values as the stack sizes
+                for ( int stackSize : Arrays.asList(ReadShard.DEFAULT_MAX_READS / 2, ReadShard.DEFAULT_MAX_READS / 2 + 10, ReadShard.DEFAULT_MAX_READS, ReadShard.DEFAULT_MAX_READS - 1, ReadShard.DEFAULT_MAX_READS + 1, ReadShard.DEFAULT_MAX_READS * 2) ) {
+                    for ( int numUnmappedReads : Arrays.asList(0, ReadShard.DEFAULT_MAX_READS / 2, ReadShard.DEFAULT_MAX_READS * 2) ) {
+                        // The first value will result in no downsampling at all, the others in some downsampling
+                        for ( int downsamplingTargetCoverage : Arrays.asList(ReadShard.DEFAULT_MAX_READS * 10, ReadShard.DEFAULT_MAX_READS, ReadShard.DEFAULT_MAX_READS / 2) ) {
+                            new ReadShardBalancerTest(numContigs, numStacksPerContig, stackSize, numUnmappedReads, downsamplingTargetCoverage);
+                        }
+                    }
+                }
+            }
+        }
+
+        return ReadShardBalancerTest.getTests(ReadShardBalancerTest.class);
+    }
+
+    @Test(dataProvider = "ReadShardBalancerTestDataProvider")
+    public void runReadShardBalancerTest( ReadShardBalancerTest test ) {
+        logger.warn("Running test: " + test);
+
+        test.run();
+    }
+}
diff --git a/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/engine/datasources/reads/SAMDataSourceUnitTest.java b/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/engine/datasources/reads/SAMDataSourceUnitTest.java
new file mode 100644
index 0000000..526b8ce
--- /dev/null
+++ b/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/engine/datasources/reads/SAMDataSourceUnitTest.java
@@ -0,0 +1,253 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.engine.datasources.reads;
+
+import htsjdk.samtools.reference.IndexedFastaSequenceFile;
+import htsjdk.samtools.*;
+import org.broadinstitute.gatk.utils.BaseTest;
+import org.broadinstitute.gatk.utils.commandline.Tags;
+import org.broadinstitute.gatk.engine.arguments.ValidationExclusion;
+import org.broadinstitute.gatk.engine.filters.ReadFilter;
+import org.broadinstitute.gatk.engine.iterators.ReadTransformer;
+import org.broadinstitute.gatk.engine.iterators.GATKSAMIterator;
+import org.broadinstitute.gatk.engine.resourcemanagement.ThreadAllocation;
+import org.broadinstitute.gatk.utils.GenomeLoc;
+import org.broadinstitute.gatk.utils.GenomeLocParser;
+import org.broadinstitute.gatk.utils.exceptions.UserException;
+import org.broadinstitute.gatk.utils.fasta.CachingIndexedFastaSequenceFile;
+import org.broadinstitute.gatk.utils.interval.IntervalMergingRule;
+import org.testng.annotations.AfterMethod;
+import org.testng.annotations.BeforeMethod;
+import org.testng.annotations.Test;
+
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+import static org.testng.Assert.*;
+
+/**
+ * <p/>
+ * Class SAMDataSourceUnitTest
+ * <p/>
+ * The test of the SAMBAM simple data source.
+ */
+public class SAMDataSourceUnitTest extends BaseTest {
+
+    // TODO: These legacy tests should really be replaced with a more comprehensive suite of tests for SAMDataSource
+
+    private List<SAMReaderID> readers;
+    private IndexedFastaSequenceFile seq;
+    private GenomeLocParser genomeLocParser;
+
+    /**
+     * This function does the setup of our parser, before each method call.
+     * <p/>
+     * Called before every test case method.
+     */
+    @BeforeMethod
+    public void doForEachTest() throws FileNotFoundException {
+        readers = new ArrayList<SAMReaderID>();
+
+        // sequence
+        seq = new CachingIndexedFastaSequenceFile(new File(b36KGReference));
+        genomeLocParser = new GenomeLocParser(seq.getSequenceDictionary());
+    }
+
+    /**
+     * Tears down the test fixture after each call.
+     * <p/>
+     * Called after every test case method.
+     */
+    @AfterMethod
+    public void undoForEachTest() {
+        seq = null;
+        readers.clear();
+    }
+
+
+    /** Test out that we can shard the file and iterate over every read */
+    @Test
+    public void testLinearBreakIterateAll() {
+        logger.warn("Executing testLinearBreakIterateAll");
+
+        // setup the data
+        readers.add(new SAMReaderID(new File(validationDataLocation+"/NA12878.chrom6.SLX.SRP000032.2009_06.selected.bam"),new Tags()));
+
+        // the sharding strat.
+        SAMDataSource data = new SAMDataSource(readers,
+                new ThreadAllocation(),
+                null,
+                genomeLocParser,
+                false,
+                ValidationStringency.SILENT,
+                null,
+                null,
+                new ValidationExclusion(),
+                new ArrayList<ReadFilter>(),
+                false);
+
+        Iterable<Shard> strat = data.createShardIteratorOverMappedReads(new LocusShardBalancer());
+        int count = 0;
+
+        try {
+            for (Shard sh : strat) {
+                int readCount = 0;
+                count++;
+
+                GenomeLoc firstLocus = sh.getGenomeLocs().get(0), lastLocus = sh.getGenomeLocs().get(sh.getGenomeLocs().size()-1);
+                logger.debug("Start : " + firstLocus.getStart() + " stop : " + lastLocus.getStop() + " contig " + firstLocus.getContig());
+                logger.debug("count = " + count);
+                GATKSAMIterator datum = data.seek(sh);
+
+                // for the first couple of shards make sure we can see the reads
+                if (count < 5) {
+                    for (SAMRecord r : datum) {
+                    }
+                    readCount++;
+                }
+                datum.close();
+
+                // if we're over 100 shards, break out
+                if (count > 100) {
+                    break;
+                }
+            }
+        }
+        catch (UserException.CouldNotReadInputFile e) {
+            e.printStackTrace();  //To change body of catch statement use File | Settings | File Templates.
+            fail("testLinearBreakIterateAll: We Should get a UserException.CouldNotReadInputFile exception");
+        }
+    }
+
+    /** Test that we clear program records when requested */
+    @Test
+    public void testRemoveProgramRecords() {
+        logger.warn("Executing testRemoveProgramRecords");
+
+        // setup the data
+        readers.add(new SAMReaderID(new File(b37GoodBAM),new Tags()));
+
+        // use defaults
+        SAMDataSource data = new SAMDataSource(readers,
+                new ThreadAllocation(),
+                null,
+                genomeLocParser,
+                false,
+                ValidationStringency.SILENT,
+                null,
+                null,
+                new ValidationExclusion(),
+                new ArrayList<ReadFilter>(),
+                false);
+
+        List<SAMProgramRecord> defaultProgramRecords = data.getHeader().getProgramRecords();
+        assertTrue(defaultProgramRecords.size() != 0, "testRemoveProgramRecords: No program records found when using default constructor");
+
+        boolean removeProgramRecords = false;
+        data = new SAMDataSource(readers,
+                new ThreadAllocation(),
+                null,
+                genomeLocParser,
+                false,
+                ValidationStringency.SILENT,
+                null,
+                null,
+                new ValidationExclusion(),
+                new ArrayList<ReadFilter>(),
+                Collections.<ReadTransformer>emptyList(),
+                false,
+                (byte) -1,
+                removeProgramRecords,
+                false,
+                null, IntervalMergingRule.ALL);
+
+        List<SAMProgramRecord> dontRemoveProgramRecords = data.getHeader().getProgramRecords();
+        assertEquals(dontRemoveProgramRecords, defaultProgramRecords, "testRemoveProgramRecords: default program records differ from removeProgramRecords = false");
+
+        removeProgramRecords = true;
+        data = new SAMDataSource(readers,
+                new ThreadAllocation(),
+                null,
+                genomeLocParser,
+                false,
+                ValidationStringency.SILENT,
+                null,
+                null,
+                new ValidationExclusion(),
+                new ArrayList<ReadFilter>(),
+                Collections.<ReadTransformer>emptyList(),
+                false,
+                (byte) -1,
+                removeProgramRecords,
+                false,
+                null, IntervalMergingRule.ALL);
+
+        List<SAMProgramRecord> doRemoveProgramRecords = data.getHeader().getProgramRecords();
+        assertTrue(doRemoveProgramRecords.isEmpty(), "testRemoveProgramRecords: program records not cleared when removeProgramRecords = true");
+    }
+
+    @Test(expectedExceptions = UserException.class)
+    public void testFailOnReducedReads() {
+        readers.add(new SAMReaderID(new File(privateTestDir + "old.reduced.bam"), new Tags()));
+
+        SAMDataSource data = new SAMDataSource(readers,
+                new ThreadAllocation(),
+                null,
+                genomeLocParser,
+                false,
+                ValidationStringency.SILENT,
+                null,
+                null,
+                new ValidationExclusion(),
+                new ArrayList<ReadFilter>(),
+                false);
+    }
+
+    @Test(expectedExceptions = UserException.class)
+    public void testFailOnReducedReadsRemovingProgramRecords() {
+        readers.add(new SAMReaderID(new File(privateTestDir + "old.reduced.bam"), new Tags()));
+
+        SAMDataSource data = new SAMDataSource(readers,
+                new ThreadAllocation(),
+                null,
+                genomeLocParser,
+                false,
+                ValidationStringency.SILENT,
+                null,
+                null,
+                new ValidationExclusion(),
+                new ArrayList<ReadFilter>(),
+                Collections.<ReadTransformer>emptyList(),
+                false,
+                (byte) -1,
+                true,
+                false,
+                null, IntervalMergingRule.ALL);
+    }
+}
diff --git a/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/engine/datasources/reads/SAMReaderIDUnitTest.java b/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/engine/datasources/reads/SAMReaderIDUnitTest.java
new file mode 100644
index 0000000..bb1cd75
--- /dev/null
+++ b/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/engine/datasources/reads/SAMReaderIDUnitTest.java
@@ -0,0 +1,49 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.engine.datasources.reads;
+
+import org.broadinstitute.gatk.utils.BaseTest;
+import org.broadinstitute.gatk.utils.commandline.Tags;
+import org.testng.Assert;
+import org.testng.annotations.Test;
+
+import java.io.File;
+
+public class SAMReaderIDUnitTest extends BaseTest {
+
+    @Test
+    public void testSAMReaderIDHashingAndEquality() {
+        // Test to make sure that two SAMReaderIDs that point at the same file via an absolute vs. relative
+        // path are equal according to equals() and have the same hash code
+        final File relativePathToBAMFile = new File(publicTestDir + "exampleBAM.bam");
+        final File absolutePathToBAMFile = new File(relativePathToBAMFile.getAbsolutePath());
+        final SAMReaderID relativePathSAMReaderID = new SAMReaderID(relativePathToBAMFile, new Tags());
+        final SAMReaderID absolutePathSAMReaderID = new SAMReaderID(absolutePathToBAMFile, new Tags());
+
+        Assert.assertEquals(relativePathSAMReaderID, absolutePathSAMReaderID, "Absolute-path and relative-path SAMReaderIDs not equal according to equals()");
+        Assert.assertEquals(relativePathSAMReaderID.hashCode(), absolutePathSAMReaderID.hashCode(), "Absolute-path and relative-path SAMReaderIDs have different hash codes");
+    }
+}
diff --git a/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/engine/datasources/reads/SeekableBufferedStreamUnitTest.java b/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/engine/datasources/reads/SeekableBufferedStreamUnitTest.java
new file mode 100644
index 0000000..c24a21a
--- /dev/null
+++ b/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/engine/datasources/reads/SeekableBufferedStreamUnitTest.java
@@ -0,0 +1,101 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.engine.datasources.reads;
+
+import htsjdk.samtools.seekablestream.SeekableBufferedStream;
+import htsjdk.samtools.seekablestream.SeekableFileStream;
+import org.broadinstitute.gatk.utils.BaseTest;
+import org.broadinstitute.gatk.utils.exceptions.GATKException;
+import org.testng.Assert;
+import org.testng.annotations.DataProvider;
+import org.testng.annotations.Test;
+
+import java.io.File;
+import java.io.IOException;
+
+/**
+ * Test basic functionality in SeekableBufferedStream.
+ */
+public class SeekableBufferedStreamUnitTest extends BaseTest {
+    private static File InputFile = new File(validationDataLocation + "megabyteZeros.dat");
+
+    final private int BUFFERED_STREAM_BUFFER_SIZE = 100;
+    private byte buffer[] = new byte[BUFFERED_STREAM_BUFFER_SIZE * 10];
+
+
+    @DataProvider(name = "BasicArgumentsDivisible")
+    public Integer[][] DivisableReads() {
+        return new Integer[][]{{1}, {4}, {5}, {10}, {20}, {50}, {100}};
+    }
+
+    @DataProvider(name = "BasicArgumentsIndivisibleAndSmall")
+    public Integer[][] InDivisableReadsSmall() {
+        return new Integer[][]{{3}, {11}, {31}, {51}, {77}, {99}};
+    }
+
+    @DataProvider(name = "BasicArgumentsIndivisibleYetLarge")
+    public Integer[][] InDivisableReadsLarge() {
+        return new Integer[][]{{101}, {151}, {205}, {251}, {301}};
+    }
+
+
+    private void testReadsLength(int length) throws IOException {
+        final int READ_SIZE=100000; //file is 10^6, so make this smaller to be safe.
+
+        SeekableFileStream fileStream = new SeekableFileStream(InputFile);
+        SeekableBufferedStream bufferedStream = new SeekableBufferedStream(fileStream, BUFFERED_STREAM_BUFFER_SIZE);
+
+        for (int i = 0; i < READ_SIZE / length; ++i) {
+            Assert.assertEquals(bufferedStream.read(buffer, 0, length), length);
+        }
+
+    }
+
+    // These tests fail because SeekableBuffered stream may return _less_ than the amount you are asking for.
+    // make sure that you wrap reads with while-loops.  If these test start failing (meaning that the reads work properly,
+    // the layer of protection built into GATKBamIndex can be removed.
+
+    @Test(dataProvider = "BasicArgumentsIndivisibleAndSmall", enabled = true, expectedExceptions = java.lang.AssertionError.class)
+    public void testIndivisableSmallReadsFAIL(Integer readLength) throws IOException {
+        testReadsLength(readLength);
+    }
+
+    //Evidently, if you ask for a read length that's larger than the inernal buffer,
+    //SeekableBufferedStreamdoes something else and gives you what you asked for
+
+    @Test(dataProvider = "BasicArgumentsIndivisibleYetLarge", enabled = true)
+    public void testIndivisableLargeReadsPASS(Integer readLength) throws IOException {
+        testReadsLength(readLength);
+    }
+
+    // if the readlength divides the buffer, there are no failures
+    @Test(dataProvider = "BasicArgumentsDivisible", enabled = true)
+    public void testDivisableReadsPASS(Integer readLength) throws IOException {
+        testReadsLength(readLength);
+    }
+
+
+}
diff --git a/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/engine/datasources/reads/TheoreticalMinimaBenchmark.java b/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/engine/datasources/reads/TheoreticalMinimaBenchmark.java
new file mode 100644
index 0000000..aa66f17
--- /dev/null
+++ b/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/engine/datasources/reads/TheoreticalMinimaBenchmark.java
@@ -0,0 +1,114 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.engine.datasources.reads;
+
+import com.google.caliper.Param;
+import htsjdk.samtools.Cigar;
+import htsjdk.samtools.CigarElement;
+import htsjdk.samtools.SAMFileReader;
+import htsjdk.samtools.SAMRecord;
+import htsjdk.samtools.util.CloseableIterator;
+
+import java.io.File;
+
+/**
+ * Created by IntelliJ IDEA.
+ * User: mhanna
+ * Date: Apr 22, 2011
+ * Time: 4:01:23 PM
+ * To change this template use File | Settings | File Templates.
+ */
+public class TheoreticalMinimaBenchmark extends ReadProcessingBenchmark {
+    @Param
+    private String bamFile;
+
+    @Param
+    private Integer maxReads;
+
+    @Override
+    public String getBAMFile() { return bamFile; }
+
+    @Override
+    public Integer getMaxReads() { return maxReads; }
+
+    public void timeIterateOverEachBase(int reps) {
+        System.out.printf("Processing " + inputFile);
+        for(int i = 0; i < reps; i++) {
+            SAMFileReader reader = new SAMFileReader(inputFile);
+            CloseableIterator<SAMRecord> iterator = reader.iterator();
+
+            long As=0,Cs=0,Gs=0,Ts=0;
+            while(iterator.hasNext()) {
+                SAMRecord read = iterator.next();
+                for(byte base: read.getReadBases()) {
+                    switch(base) {
+                        case 'A': As++; break;
+                        case 'C': Cs++; break;
+                        case 'G': Gs++; break;
+                        case 'T': Ts++; break;
+                    }
+                }
+            }
+            System.out.printf("As = %d; Cs = %d; Gs = %d; Ts = %d; total = %d%n",As,Cs,Gs,Ts,As+Cs+Gs+Ts);
+            iterator.close();
+            reader.close();
+        }
+    }
+
+    public void timeIterateOverCigarString(int reps) {
+        for(int i = 0; i < reps; i++) {
+            long matchMismatches = 0;
+            long insertions = 0;
+            long deletions = 0;
+            long others = 0;
+
+            SAMFileReader reader = new SAMFileReader(inputFile);
+            CloseableIterator<SAMRecord> iterator = reader.iterator();
+            while(iterator.hasNext()) {
+                SAMRecord read = iterator.next();
+
+                Cigar cigar = read.getCigar();
+                for(CigarElement cigarElement: cigar.getCigarElements()) {
+                    int elementSize = cigarElement.getLength();
+                    while(elementSize > 0) {
+                        switch(cigarElement.getOperator()) {
+                            case M: case EQ: case X: matchMismatches++; break;
+                            case I: insertions++; break;
+                            case D: deletions++; break;
+                            default: others++; break;
+                        }
+                        elementSize--;
+                    }
+                }
+            }
+            System.out.printf("Ms = %d; Is = %d; Ds = %d; others = %d; total = %d%n",matchMismatches,insertions,deletions,others,matchMismatches+insertions+deletions+others);
+
+            iterator.close();
+            reader.close();
+        }
+    }
+
+}
diff --git a/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/engine/datasources/reference/ReferenceDataSourceIntegrationTest.java b/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/engine/datasources/reference/ReferenceDataSourceIntegrationTest.java
new file mode 100644
index 0000000..46a4cb5
--- /dev/null
+++ b/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/engine/datasources/reference/ReferenceDataSourceIntegrationTest.java
@@ -0,0 +1,75 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.engine.datasources.reference;
+
+import org.broadinstitute.gatk.engine.walkers.WalkerTest;
+import org.broadinstitute.gatk.utils.exceptions.UserException;
+import org.testng.annotations.Test;
+import org.testng.Assert;
+
+import java.io.File;
+import java.io.IOException;
+
+public class ReferenceDataSourceIntegrationTest extends WalkerTest {
+
+    @Test
+    public void testReferenceWithMissingFaiFile() throws IOException {
+        final File dummyReference = createTempFile("dummy", ".fasta");
+        final File dictFile = new File(dummyReference.getAbsolutePath().replace(".fasta", ".dict"));
+        dictFile.deleteOnExit();
+        Assert.assertTrue(dictFile.createNewFile());
+
+        final WalkerTestSpec spec = new WalkerTestSpec(
+            " -T PrintReads" +
+            " -R " + dummyReference.getAbsolutePath() +
+            " -I " + privateTestDir + "NA12878.4.snippet.bam" +
+            " -o %s",
+            1,
+            UserException.MissingReferenceFaiFile.class
+        );
+
+        executeTest("testReferenceWithMissingFaiFile", spec);
+    }
+
+    @Test
+    public void testReferenceWithMissingDictFile() throws IOException {
+        final File dummyReference = createTempFile("dummy", ".fasta");
+        final File faiFile = new File(dummyReference.getAbsolutePath() + ".fai");
+        faiFile.deleteOnExit();
+        Assert.assertTrue(faiFile.createNewFile());
+
+        final WalkerTestSpec spec = new WalkerTestSpec(
+                " -T PrintReads" +
+                " -R " + dummyReference.getAbsolutePath() +
+                " -I " + privateTestDir + "NA12878.4.snippet.bam" +
+                " -o %s",
+                1,
+                UserException.MissingReferenceDictFile.class
+        );
+
+        executeTest("testReferenceWithMissingDictFile", spec);
+    }
+}
diff --git a/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/engine/datasources/rmd/ReferenceOrderedDataPoolUnitTest.java b/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/engine/datasources/rmd/ReferenceOrderedDataPoolUnitTest.java
new file mode 100644
index 0000000..baa2af0
--- /dev/null
+++ b/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/engine/datasources/rmd/ReferenceOrderedDataPoolUnitTest.java
@@ -0,0 +1,208 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.engine.datasources.rmd;
+
+import org.broadinstitute.gatk.utils.commandline.Tags;
+import org.broadinstitute.gatk.engine.refdata.tracks.RMDTrackBuilder;
+import org.testng.Assert;
+import org.broadinstitute.gatk.utils.BaseTest;
+import org.broadinstitute.gatk.utils.codecs.table.TableFeature;
+import org.broadinstitute.gatk.engine.refdata.utils.LocationAwareSeekableRODIterator;
+import org.broadinstitute.gatk.engine.refdata.utils.RMDTriplet;
+import org.broadinstitute.gatk.engine.refdata.utils.RMDTriplet.RMDStorageType;
+import org.broadinstitute.gatk.utils.GenomeLoc;
+import org.broadinstitute.gatk.utils.GenomeLocParser;
+import org.broadinstitute.gatk.utils.fasta.CachingIndexedFastaSequenceFile;
+
+import static org.testng.Assert.assertTrue;
+import org.testng.annotations.BeforeMethod;
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.Test;
+
+import java.io.File;
+import java.io.FileNotFoundException;
+
+import htsjdk.samtools.reference.IndexedFastaSequenceFile;
+/**
+ * User: hanna
+ * Date: May 21, 2009
+ * Time: 11:03:04 AM
+ * BROAD INSTITUTE SOFTWARE COPYRIGHT NOTICE AND AGREEMENT
+ * Software and documentation are copyright 2005 by the Broad Institute.
+ * All rights are reserved.
+ *
+ * Users acknowledge that this software is supplied without any warranty or support.
+ * The Broad Institute is not responsible for its use, misuse, or
+ * functionality.
+ */
+
+/**
+ * Test the contents and number of iterators in the pool.
+ */
+
+public class ReferenceOrderedDataPoolUnitTest extends BaseTest {
+
+    private RMDTriplet triplet = null;
+    private RMDTrackBuilder builder = null;
+
+    private IndexedFastaSequenceFile seq;
+    private GenomeLocParser genomeLocParser;
+
+    private GenomeLoc testSite1;
+    private GenomeLoc testSite2;
+    private GenomeLoc testSite3;
+
+    private GenomeLoc testInterval1; // an interval matching testSite1 -> testSite2 for queries
+    private GenomeLoc testInterval2; // an interval matching testSite2 -> testSite3 for queries
+
+
+    @BeforeClass
+    public void init() throws FileNotFoundException {
+        seq = new CachingIndexedFastaSequenceFile(new File(hg18Reference));
+        genomeLocParser = new GenomeLocParser(seq);
+
+        testSite1 = genomeLocParser.createGenomeLoc("chrM",10);
+        testSite2 = genomeLocParser.createGenomeLoc("chrM",20);
+        testSite3 = genomeLocParser.createGenomeLoc("chrM",30);
+        testInterval1 = genomeLocParser.createGenomeLoc("chrM",10,20);
+        testInterval2 = genomeLocParser.createGenomeLoc("chrM",20,30);
+    }
+
+    @BeforeMethod
+    public void setUp() {
+        String fileName = privateTestDir + "TabularDataTest.dat";
+
+        triplet = new RMDTriplet("tableTest","Table",fileName,RMDStorageType.FILE,new Tags());
+        // disable auto-index creation/locking in the RMDTrackBuilder for tests
+        builder = new RMDTrackBuilder(seq.getSequenceDictionary(),genomeLocParser,null,true,null);
+    }
+
+    @Test
+    public void testCreateSingleIterator() {
+        ResourcePool iteratorPool = new ReferenceOrderedDataPool(triplet,builder,seq.getSequenceDictionary(),genomeLocParser,false);
+        LocationAwareSeekableRODIterator iterator = (LocationAwareSeekableRODIterator)iteratorPool.iterator( new MappedStreamSegment(testSite1) );
+
+        Assert.assertEquals(iteratorPool.numIterators(), 1, "Number of iterators in the pool is incorrect");
+        Assert.assertEquals(iteratorPool.numAvailableIterators(), 0, "Number of available iterators in the pool is incorrect");
+
+        TableFeature datum = (TableFeature)iterator.next().get(0).getUnderlyingObject();
+
+        assertTrue(datum.getLocation().equals(testSite1));
+        assertTrue(datum.get("COL1").equals("A"));
+        assertTrue(datum.get("COL2").equals("B"));
+        assertTrue(datum.get("COL3").equals("C"));
+
+        iteratorPool.release(iterator);
+
+        Assert.assertEquals(iteratorPool.numIterators(), 1, "Number of iterators in the pool is incorrect");
+        Assert.assertEquals(iteratorPool.numAvailableIterators(), 1, "Number of available iterators in the pool is incorrect");
+    }
+
+    @Test
+    public void testCreateMultipleIterators() {
+        ReferenceOrderedQueryDataPool iteratorPool = new ReferenceOrderedQueryDataPool(triplet,builder,seq.getSequenceDictionary(),genomeLocParser);
+        LocationAwareSeekableRODIterator iterator1 = iteratorPool.iterator( new MappedStreamSegment(testInterval1) );
+
+        // Create a new iterator at position 2.
+        LocationAwareSeekableRODIterator iterator2 = iteratorPool.iterator( new MappedStreamSegment(testInterval2) );
+
+        Assert.assertEquals(iteratorPool.numIterators(), 2, "Number of iterators in the pool is incorrect");
+        Assert.assertEquals(iteratorPool.numAvailableIterators(), 0, "Number of available iterators in the pool is incorrect");
+
+        // Test out-of-order access: first iterator2, then iterator1.
+        // Ugh...first call to a region needs to be a seek.
+        TableFeature datum = (TableFeature)iterator2.seekForward(testSite2).get(0).getUnderlyingObject();
+        assertTrue(datum.getLocation().equals(testSite2));
+        assertTrue(datum.get("COL1").equals("C"));
+        assertTrue(datum.get("COL2").equals("D"));
+        assertTrue(datum.get("COL3").equals("E"));
+
+        datum = (TableFeature)iterator1.next().get(0).getUnderlyingObject();
+        assertTrue(datum.getLocation().equals(testSite1));
+        assertTrue(datum.get("COL1").equals("A"));
+        assertTrue(datum.get("COL2").equals("B"));
+        assertTrue(datum.get("COL3").equals("C"));
+
+        // Advance iterator2, and make sure both iterator's contents are still correct.
+        datum = (TableFeature)iterator2.next().get(0).getUnderlyingObject();
+        assertTrue(datum.getLocation().equals(testSite3));
+        assertTrue(datum.get("COL1").equals("F"));
+        assertTrue(datum.get("COL2").equals("G"));
+        assertTrue(datum.get("COL3").equals("H"));
+
+        datum = (TableFeature)iterator1.next().get(0).getUnderlyingObject();
+        assertTrue(datum.getLocation().equals(testSite2));
+        assertTrue(datum.get("COL1").equals("C"));
+        assertTrue(datum.get("COL2").equals("D"));
+        assertTrue(datum.get("COL3").equals("E"));
+
+        // Cleanup, and make sure the number of iterators dies appropriately.
+        iteratorPool.release(iterator1);
+
+        Assert.assertEquals(iteratorPool.numIterators(), 2, "Number of iterators in the pool is incorrect");
+        Assert.assertEquals(iteratorPool.numAvailableIterators(), 1, "Number of available iterators in the pool is incorrect");
+
+        iteratorPool.release(iterator2);
+
+        Assert.assertEquals(iteratorPool.numIterators(), 2, "Number of iterators in the pool is incorrect");
+        Assert.assertEquals(iteratorPool.numAvailableIterators(), 2, "Number of available iterators in the pool is incorrect");
+    }
+
+    @Test
+    public void testIteratorConservation() {
+        ReferenceOrderedDataPool iteratorPool = new ReferenceOrderedDataPool(triplet,builder,seq.getSequenceDictionary(),genomeLocParser,false);
+        LocationAwareSeekableRODIterator iterator = iteratorPool.iterator( new MappedStreamSegment(testSite1) );
+
+        Assert.assertEquals(iteratorPool.numIterators(), 1, "Number of iterators in the pool is incorrect");
+        Assert.assertEquals(iteratorPool.numAvailableIterators(), 0, "Number of available iterators in the pool is incorrect");
+
+        TableFeature datum = (TableFeature)iterator.next().get(0).getUnderlyingObject();
+        assertTrue(datum.getLocation().equals(testSite1));
+        assertTrue(datum.get("COL1").equals("A"));
+        assertTrue(datum.get("COL2").equals("B"));
+        assertTrue(datum.get("COL3").equals("C"));
+
+        iteratorPool.release(iterator);
+
+        // Create another iterator after the current iterator.
+        iterator = iteratorPool.iterator( new MappedStreamSegment(testSite3) );
+
+        // Make sure that the previously acquired iterator was reused.
+        Assert.assertEquals(iteratorPool.numIterators(), 1, "Number of iterators in the pool is incorrect");
+        Assert.assertEquals(iteratorPool.numAvailableIterators(), 0, "Number of available iterators in the pool is incorrect");
+
+        datum = (TableFeature)iterator.seekForward(testSite3).get(0).getUnderlyingObject();
+        assertTrue(datum.getLocation().equals(testSite3));
+        assertTrue(datum.get("COL1").equals("F"));
+        assertTrue(datum.get("COL2").equals("G"));
+        assertTrue(datum.get("COL3").equals("H"));
+
+        iteratorPool.release(iterator);
+
+        Assert.assertEquals(iteratorPool.numIterators(), 1, "Number of iterators in the pool is incorrect");
+        Assert.assertEquals(iteratorPool.numAvailableIterators(), 1, "Number of available iterators in the pool is incorrect");
+    }
+}
diff --git a/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/engine/datasources/rmd/ReferenceOrderedQueryDataPoolUnitTest.java b/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/engine/datasources/rmd/ReferenceOrderedQueryDataPoolUnitTest.java
new file mode 100644
index 0000000..6c403cd
--- /dev/null
+++ b/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/engine/datasources/rmd/ReferenceOrderedQueryDataPoolUnitTest.java
@@ -0,0 +1,89 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.engine.datasources.rmd;
+
+import htsjdk.samtools.reference.IndexedFastaSequenceFile;
+import htsjdk.tribble.Feature;
+import org.broadinstitute.gatk.utils.BaseTest;
+import org.broadinstitute.gatk.utils.commandline.Tags;
+import org.broadinstitute.gatk.engine.refdata.utils.*;
+import org.broadinstitute.gatk.utils.GenomeLoc;
+import org.broadinstitute.gatk.utils.GenomeLocParser;
+import org.broadinstitute.gatk.utils.fasta.CachingIndexedFastaSequenceFile;
+import org.testng.Assert;
+import org.testng.annotations.Test;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.List;
+
+public class ReferenceOrderedQueryDataPoolUnitTest extends BaseTest{
+    @Test
+    public void testCloseFilePointers() throws IOException {
+        // Build up query parameters
+        File file = new File(BaseTest.privateTestDir + "NA12878.hg19.example1.vcf");
+        RMDTriplet triplet = new RMDTriplet("test", "VCF", file.getAbsolutePath(), RMDTriplet.RMDStorageType.FILE, new Tags());
+        IndexedFastaSequenceFile seq = new CachingIndexedFastaSequenceFile(new File(BaseTest.hg19Reference));
+        GenomeLocParser parser = new GenomeLocParser(seq);
+        GenomeLoc loc = parser.createGenomeLoc("20", 1, 100000);
+        TestRMDTrackBuilder builder = new TestRMDTrackBuilder(seq.getSequenceDictionary(), parser);
+
+        // Create the query data pool
+        ReferenceOrderedQueryDataPool pool = new ReferenceOrderedQueryDataPool(triplet, builder, seq.getSequenceDictionary(), parser);
+
+        for (int i = 0; i < 3; i++) {
+            // Ensure our tribble iterators are closed.
+            CheckableCloseableTribbleIterator.clearThreadIterators();
+            Assert.assertTrue(CheckableCloseableTribbleIterator.getThreadIterators().isEmpty(), "Tribble iterators list was not cleared.");
+
+            // Request the the rodIterator
+            LocationAwareSeekableRODIterator rodIterator = pool.iterator(new MappedStreamSegment(loc));
+
+            // Run normal iteration over rodIterator
+            Assert.assertTrue(rodIterator.hasNext(), "Rod iterator does not have a next value.");
+            GenomeLoc rodIteratorLocation = rodIterator.next().getLocation();
+            Assert.assertEquals(rodIteratorLocation.getContig(), "20", "Instead of chr 20 rod iterator was at location " + rodIteratorLocation);
+
+            // Check that the underlying tribbleIterators are still open.
+            List<CheckableCloseableTribbleIterator<? extends Feature>> tribbleIterators = CheckableCloseableTribbleIterator.getThreadIterators();
+            Assert.assertFalse(tribbleIterators.isEmpty(), "Tribble iterators list is empty");
+            for (CheckableCloseableTribbleIterator<? extends Feature> tribbleIterator: tribbleIterators) {
+                Assert.assertFalse(tribbleIterator.isClosed(), "Tribble iterator is closed but should be still open.");
+            }
+
+            // Releasing the rodIterator should close the underlying tribbleIterator.
+            pool.release(rodIterator);
+
+            // Check that the underlying tribbleIterators are now closed.
+            for (CheckableCloseableTribbleIterator<? extends Feature> tribbleIterator: tribbleIterators) {
+                Assert.assertTrue(tribbleIterator.isClosed(), "Tribble iterator is open but should be now closed.");
+            }
+        }
+
+        // Extra cleanup.
+        CheckableCloseableTribbleIterator.clearThreadIterators();
+    }
+}
diff --git a/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/engine/downsampling/AlleleBiasedDownsamplingUtilsUnitTest.java b/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/engine/downsampling/AlleleBiasedDownsamplingUtilsUnitTest.java
new file mode 100644
index 0000000..2d86f73
--- /dev/null
+++ b/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/engine/downsampling/AlleleBiasedDownsamplingUtilsUnitTest.java
@@ -0,0 +1,219 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.engine.downsampling;
+
+import htsjdk.samtools.CigarElement;
+import htsjdk.samtools.CigarOperator;
+import htsjdk.samtools.SAMFileHeader;
+import org.apache.log4j.Logger;
+import org.broadinstitute.gatk.utils.BaseTest;
+import org.broadinstitute.gatk.utils.exceptions.UserException;
+import org.broadinstitute.gatk.utils.pileup.PileupElement;
+import org.broadinstitute.gatk.utils.sam.ArtificialSAMUtils;
+import org.broadinstitute.gatk.utils.sam.GATKSAMRecord;
+import org.testng.Assert;
+import org.testng.annotations.DataProvider;
+import org.testng.annotations.Test;
+
+import java.io.File;
+import java.util.*;
+
+
+/**
+ * Basic unit test for AlleleBiasedDownsamplingUtils
+ */
+public class AlleleBiasedDownsamplingUtilsUnitTest extends BaseTest {
+
+
+    @Test
+    public void testSmartDownsampling() {
+
+        final int[] idealHetAlleleCounts = new int[]{0, 50, 0, 50};
+        final int[] idealHomAlleleCounts = new int[]{0, 100, 0, 0};
+
+        // no contamination, no removal
+        testOneCase(0, 0, 0, 0, 0.1, 100, idealHetAlleleCounts, idealHetAlleleCounts);
+        testOneCase(0, 0, 0, 0, 0.1, 100, idealHomAlleleCounts, idealHomAlleleCounts);
+
+        // hom sample, het contaminant, different alleles
+        testOneCase(5, 0, 0, 0, 0.1, 100, idealHomAlleleCounts, idealHomAlleleCounts);
+        testOneCase(0, 0, 5, 0, 0.1, 100, idealHomAlleleCounts, idealHomAlleleCounts);
+        testOneCase(0, 0, 0, 5, 0.1, 100, idealHomAlleleCounts, idealHomAlleleCounts);
+
+        // hom sample, hom contaminant, different alleles
+        testOneCase(10, 0, 0, 0, 0.1, 100, idealHomAlleleCounts, idealHomAlleleCounts);
+        testOneCase(0, 0, 10, 0, 0.1, 100, idealHomAlleleCounts, idealHomAlleleCounts);
+        testOneCase(0, 0, 0, 10, 0.1, 100, idealHomAlleleCounts, idealHomAlleleCounts);
+
+        // het sample, het contaminant, different alleles
+        testOneCase(5, 0, 0, 0, 0.1, 100, idealHetAlleleCounts, idealHetAlleleCounts);
+        testOneCase(0, 0, 5, 0, 0.1, 100, idealHetAlleleCounts, idealHetAlleleCounts);
+
+        // het sample, hom contaminant, different alleles
+        testOneCase(10, 0, 0, 0, 0.1, 100, idealHetAlleleCounts, idealHetAlleleCounts);
+        testOneCase(0, 0, 10, 0, 0.1, 100, idealHetAlleleCounts, idealHetAlleleCounts);
+
+        // hom sample, het contaminant, overlapping alleles
+        final int[] enhancedHomAlleleCounts = new int[]{0, 105, 0, 0};
+        testOneCase(5, 5, 0, 0, 0.1, 100, idealHomAlleleCounts, enhancedHomAlleleCounts);
+        testOneCase(0, 5, 5, 0, 0.1, 100, idealHomAlleleCounts, enhancedHomAlleleCounts);
+        testOneCase(0, 5, 0, 5, 0.1, 100, idealHomAlleleCounts, enhancedHomAlleleCounts);
+
+        // hom sample, hom contaminant, overlapping alleles
+        testOneCase(0, 10, 0, 0, 0.1, 100, idealHomAlleleCounts, new int[]{0, 110, 0, 0});
+
+        // het sample, het contaminant, overlapping alleles
+        testOneCase(5, 5, 0, 0, 0.1, 100, idealHetAlleleCounts, idealHetAlleleCounts);
+        testOneCase(0, 5, 5, 0, 0.1, 100, idealHetAlleleCounts, idealHetAlleleCounts);
+        testOneCase(0, 5, 0, 5, 0.1, 100, idealHetAlleleCounts, new int[]{0, 55, 0, 55});
+        testOneCase(5, 0, 0, 5, 0.1, 100, idealHetAlleleCounts, idealHetAlleleCounts);
+        testOneCase(0, 0, 5, 5, 0.1, 100, idealHetAlleleCounts, idealHetAlleleCounts);
+
+        // het sample, hom contaminant, overlapping alleles
+        testOneCase(0, 10, 0, 0, 0.1, 100, idealHetAlleleCounts, idealHetAlleleCounts);
+        testOneCase(0, 0, 0, 10, 0.1, 100, idealHetAlleleCounts, idealHetAlleleCounts);
+    }
+
+    private static void testOneCase(final int addA, final int addC, final int addG, final int addT, final double contaminationFraction,
+                                    final int pileupSize, final int[] initialCounts, final int[] targetCounts) {
+
+        final int[] actualCounts = initialCounts.clone();
+        actualCounts[0] += addA;
+        actualCounts[1] += addC;
+        actualCounts[2] += addG;
+        actualCounts[3] += addT;
+
+        final int[] results = AlleleBiasedDownsamplingUtils.runSmartDownsampling(actualCounts, (int)(pileupSize * contaminationFraction));
+        Assert.assertTrue(countsAreEqual(results, targetCounts));
+    }
+
+    private static boolean countsAreEqual(final int[] counts1, final int[] counts2) {
+        for ( int i = 0; i < 4; i++ ) {
+            if ( counts1[i] != counts2[i] )
+                return false;
+        }
+        return true;
+    }
+
+    @DataProvider(name = "BiasedDownsamplingTest")
+    public Object[][] makeBiasedDownsamplingTest() {
+        final List<Object[]> tests = new LinkedList<Object[]>();
+
+        final SAMFileHeader header = ArtificialSAMUtils.createArtificialSamHeader(1, 1, 1000);
+
+        for ( final int originalCount : Arrays.asList(1, 2, 10, 1000) ) {
+            for ( final int toRemove : Arrays.asList(0, 1, 2, 10, 1000) ) {
+                if ( toRemove <= originalCount )
+                    tests.add(new Object[]{header, originalCount, toRemove});
+            }
+        }
+
+        return tests.toArray(new Object[][]{});
+    }
+
+    @Test(dataProvider = "BiasedDownsamplingTest")
+    public void testBiasedDownsampling(final SAMFileHeader header, final int originalCount, final int toRemove) {
+
+        final LinkedList<PileupElement> elements = new LinkedList<>();
+        for ( int i = 0; i < originalCount; i++ ) {
+            final GATKSAMRecord read = ArtificialSAMUtils.createArtificialRead(header, "read", 0, 1, 1);
+            elements.add(new PileupElement(read, 0, new CigarElement(1, CigarOperator.M), 0, 0));
+        }
+
+        final List<PileupElement> result = AlleleBiasedDownsamplingUtils.downsampleElements(elements, originalCount, toRemove);
+
+        Assert.assertEquals(result.size(), toRemove);
+    }
+
+    @Test
+    public void testLoadContaminationFileDetails(){
+        Logger logger=org.apache.log4j.Logger.getRootLogger();
+
+        final String ArtificalBAMLocation = privateTestDir + "ArtificallyContaminatedBams/";
+        final File ContamFile1=new File(ArtificalBAMLocation+"contamination.case.1.txt");
+
+        Map<String,Double> Contam1=new HashMap<String,Double>();
+        Set<String> Samples1=new HashSet<String>();
+
+        Contam1.put("NA11918",0.15);
+        Samples1.addAll(Contam1.keySet());
+        testLoadFile(ContamFile1,Samples1,Contam1,logger);
+
+        Contam1.put("NA12842",0.13);
+        Samples1.addAll(Contam1.keySet());
+        testLoadFile(ContamFile1,Samples1,Contam1,logger);
+
+        Samples1.add("DUMMY");
+        testLoadFile(ContamFile1,Samples1,Contam1,logger);
+   }
+
+    private static void testLoadFile(final File file, final Set<String> Samples, final Map<String,Double> map, Logger logger){
+        Map<String,Double> loadedMap = AlleleBiasedDownsamplingUtils.loadContaminationFile(file,0.0,Samples,logger);
+        Assert.assertTrue(loadedMap.equals(map));
+    }
+
+    @DataProvider(name = "goodContaminationFiles")
+    public Integer[][] goodContaminationFiles() {
+        return new Integer[][]{
+                {1, 2},
+                {2, 3},
+                {3, 2},
+                {4, 2},
+                {5, 3},
+                {6, 2},
+                {7, 2},
+                {8, 2}
+        };
+    }
+
+    @Test(dataProvider = "goodContaminationFiles")
+    public void testLoadContaminationFile(final Integer ArtificalBAMnumber, final Integer numberOfSamples) {
+        final String ArtificialBAM = String.format("ArtificallyContaminatedBams/contamination.case.%d.txt", ArtificalBAMnumber);
+        Logger logger = org.apache.log4j.Logger.getRootLogger();
+
+        File ContamFile = new File(privateTestDir, ArtificialBAM);
+        Assert.assertTrue(AlleleBiasedDownsamplingUtils.loadContaminationFile(ContamFile, 0.0, null, logger).size() == numberOfSamples);
+
+    }
+
+
+    @DataProvider(name = "badContaminationFiles")
+    public Integer[][] badContaminationFiles() {
+        return new Integer[][]{{1}, {2}, {3}, {4}, {5}};
+    }
+
+    @Test(dataProvider = "badContaminationFiles", expectedExceptions = UserException.MalformedFile.class)
+    public void testLoadBrokenContaminationFile(final int i) {
+        Logger logger = org.apache.log4j.Logger.getRootLogger();
+        final String ArtificalBAMLocation = privateTestDir + "ArtificallyContaminatedBams/";
+
+        File ContaminationFile = new File(ArtificalBAMLocation + String.format("contamination.case.broken.%d.txt", i));
+        AlleleBiasedDownsamplingUtils.loadContaminationFile(ContaminationFile, 0.0, null, logger);
+
+    }
+
+
+}
diff --git a/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/engine/downsampling/DownsamplingIntegrationTest.java b/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/engine/downsampling/DownsamplingIntegrationTest.java
new file mode 100644
index 0000000..2f171de
--- /dev/null
+++ b/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/engine/downsampling/DownsamplingIntegrationTest.java
@@ -0,0 +1,44 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.engine.downsampling;
+
+import org.broadinstitute.gatk.engine.walkers.WalkerTest;
+import org.broadinstitute.gatk.utils.exceptions.UserException;
+import org.testng.annotations.Test;
+
+public class DownsamplingIntegrationTest extends WalkerTest {
+
+    @Test
+    public void testDetectLowDcovValueWithLocusTraversal() {
+        final WalkerTest.WalkerTestSpec spec = new WalkerTest.WalkerTestSpec(
+            "-T CountLoci -R " + publicTestDir + "exampleFASTA.fasta -I " + publicTestDir + "exampleBAM.bam -o %s " +
+            "-dcov " + (DownsamplingMethod.MINIMUM_SAFE_COVERAGE_TARGET_FOR_LOCUS_BASED_TRAVERSALS - 1),
+            1,
+            UserException.class
+        );
+        executeTest("testDetectLowDcovValueWithLocusTraversal", spec);
+    }
+}
diff --git a/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/engine/downsampling/DownsamplingReadsIteratorUnitTest.java b/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/engine/downsampling/DownsamplingReadsIteratorUnitTest.java
new file mode 100644
index 0000000..19eec62
--- /dev/null
+++ b/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/engine/downsampling/DownsamplingReadsIteratorUnitTest.java
@@ -0,0 +1,139 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.engine.downsampling;
+
+import htsjdk.samtools.SAMFileHeader;
+import htsjdk.samtools.SAMReadGroupRecord;
+import htsjdk.samtools.SAMRecord;
+import org.broadinstitute.gatk.utils.BaseTest;
+import org.broadinstitute.gatk.engine.GenomeAnalysisEngine;
+import org.broadinstitute.gatk.utils.sam.ArtificialSAMUtils;
+import org.broadinstitute.gatk.utils.sam.ArtificialSingleSampleReadStream;
+import org.broadinstitute.gatk.utils.sam.ArtificialSingleSampleReadStreamAnalyzer;
+import org.testng.annotations.DataProvider;
+import org.testng.annotations.Test;
+
+import java.util.Arrays;
+
+public class DownsamplingReadsIteratorUnitTest extends BaseTest {
+
+    private static class DownsamplingReadsIteratorTest extends TestDataProvider {
+        private DownsamplingReadsIterator downsamplingIter;
+        private int targetCoverage;
+        private ArtificialSingleSampleReadStream stream;
+        private ArtificialSingleSampleReadStreamAnalyzer streamAnalyzer;
+
+        public DownsamplingReadsIteratorTest( ArtificialSingleSampleReadStream stream, int targetCoverage ) {
+            super(DownsamplingReadsIteratorTest.class);
+
+            this.stream = stream;
+            this.targetCoverage = targetCoverage;
+
+            setName(String.format("%s: targetCoverage=%d numContigs=%d stacksPerContig=%d readsPerStack=%d-%d distanceBetweenStacks=%d-%d readLength=%d-%d unmappedReads=%d",
+                    getClass().getSimpleName(),
+                    targetCoverage,
+                    stream.getNumContigs(),
+                    stream.getNumStacksPerContig(),
+                    stream.getMinReadsPerStack(),
+                    stream.getMaxReadsPerStack(),
+                    stream.getMinDistanceBetweenStacks(),
+                    stream.getMaxDistanceBetweenStacks(),
+                    stream.getMinReadLength(),
+                    stream.getMaxReadLength(),
+                    stream.getNumUnmappedReads()));
+        }
+
+        public void run() {
+            streamAnalyzer = new PositionallyDownsampledArtificialSingleSampleReadStreamAnalyzer(stream, targetCoverage);
+            downsamplingIter = new DownsamplingReadsIterator(stream.getGATKSAMIterator(), new SimplePositionalDownsampler<SAMRecord>(targetCoverage));
+
+            streamAnalyzer.analyze(downsamplingIter);
+
+            // Check whether the observed properties of the downsampled stream are what they should be
+            streamAnalyzer.validate();
+
+            // Allow memory used by this test to be reclaimed
+            stream = null;
+            streamAnalyzer = null;
+            downsamplingIter = null;
+        }
+    }
+
+    @DataProvider(name = "DownsamplingReadsIteratorTestDataProvider")
+    public Object[][] createDownsamplingReadsIteratorTests() {
+        SAMFileHeader header = ArtificialSAMUtils.createArtificialSamHeader(5, 1, 10000);
+        String readGroupID = "testReadGroup";
+        SAMReadGroupRecord readGroup = new SAMReadGroupRecord(readGroupID);
+        readGroup.setSample("testSample");
+        header.addReadGroup(readGroup);
+
+        // Values that don't vary across tests
+        int targetCoverage = 10;
+        int minReadLength = 50;
+        int maxReadLength = 100;
+        int minDistanceBetweenStacks = 1;
+        int maxDistanceBetweenStacks = maxReadLength + 1;
+
+        GenomeAnalysisEngine.resetRandomGenerator();
+
+        // brute force testing!
+        for ( int numContigs : Arrays.asList(1, 2, 5) ) {
+            for ( int stacksPerContig : Arrays.asList(1, 2, 10) ) {
+                for ( int minReadsPerStack : Arrays.asList(1, targetCoverage / 2, targetCoverage, targetCoverage - 1, targetCoverage + 1, targetCoverage * 2) ) {
+                    for ( int maxReadsPerStack : Arrays.asList(1, targetCoverage / 2, targetCoverage, targetCoverage - 1, targetCoverage + 1, targetCoverage * 2) ) {
+                        for ( int numUnmappedReads : Arrays.asList(0, 1, targetCoverage, targetCoverage * 2) ) {
+                            // Only interested in sane read stream configurations here
+                            if ( minReadsPerStack <= maxReadsPerStack ) {
+                                new DownsamplingReadsIteratorTest(new ArtificialSingleSampleReadStream(header,
+                                                                                                       readGroupID,
+                                                                                                       numContigs,
+                                                                                                       stacksPerContig,
+                                                                                                       minReadsPerStack,
+                                                                                                       maxReadsPerStack,
+                                                                                                       minDistanceBetweenStacks,
+                                                                                                       maxDistanceBetweenStacks,
+                                                                                                       minReadLength,
+                                                                                                       maxReadLength,
+                                                                                                       numUnmappedReads),
+                                                                  targetCoverage);
+                            }
+                        }
+                    }
+                }
+            }
+        }
+
+        return DownsamplingReadsIteratorTest.getTests(DownsamplingReadsIteratorTest.class);
+    }
+
+    @Test(dataProvider = "DownsamplingReadsIteratorTestDataProvider")
+    public void runDownsamplingReadsIteratorTest( DownsamplingReadsIteratorTest test ) {
+        logger.warn("Running test: " + test);
+
+        GenomeAnalysisEngine.resetRandomGenerator();
+        test.run();
+    }
+}
diff --git a/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/engine/downsampling/FractionalDownsamplerUnitTest.java b/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/engine/downsampling/FractionalDownsamplerUnitTest.java
new file mode 100644
index 0000000..9185374
--- /dev/null
+++ b/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/engine/downsampling/FractionalDownsamplerUnitTest.java
@@ -0,0 +1,158 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.engine.downsampling;
+
+import htsjdk.samtools.SAMFileHeader;
+import htsjdk.samtools.SAMRecord;
+import org.broadinstitute.gatk.utils.BaseTest;
+import org.broadinstitute.gatk.engine.GenomeAnalysisEngine;
+import org.broadinstitute.gatk.utils.sam.ArtificialSAMUtils;
+import org.testng.annotations.DataProvider;
+import org.testng.annotations.Test;
+import org.testng.Assert;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.List;
+
+public class FractionalDownsamplerUnitTest extends BaseTest {
+
+    private static class FractionalDownsamplerTest extends TestDataProvider {
+        double fraction;
+        int totalReads;
+        int expectedMinNumReadsAfterDownsampling;
+        int expectedMaxNumReadsAfterDownsampling;
+        int expectedMinDiscardedItems;
+        int expectedMaxDiscardedItems;
+
+        private static final double EXPECTED_ACCURACY = 0.05; // should be accurate to within +/- this percent
+
+        public FractionalDownsamplerTest( double fraction, int totalReads ) {
+            super(FractionalDownsamplerTest.class);
+
+            this.fraction = fraction;
+            this.totalReads = totalReads;
+
+            calculateExpectations();
+
+            setName(String.format("%s: fraction=%.2f totalReads=%d expectedMinNumReadsAfterDownsampling=%d expectedMaxNumReadsAfterDownsampling=%d",
+                    getClass().getSimpleName(), fraction, totalReads, expectedMinNumReadsAfterDownsampling, expectedMaxNumReadsAfterDownsampling));
+        }
+
+        private void calculateExpectations() {
+            // Require an exact match in the 0% and 100% cases
+            if ( fraction == 0.0 ) {
+                expectedMinNumReadsAfterDownsampling = expectedMaxNumReadsAfterDownsampling = 0;
+                expectedMinDiscardedItems = expectedMaxDiscardedItems = totalReads;
+            }
+            else if ( fraction == 1.0 ) {
+                expectedMinNumReadsAfterDownsampling = expectedMaxNumReadsAfterDownsampling = totalReads;
+                expectedMinDiscardedItems = expectedMaxDiscardedItems = 0;
+            }
+            else {
+                expectedMinNumReadsAfterDownsampling = Math.max((int)((fraction - EXPECTED_ACCURACY) * totalReads), 0);
+                expectedMaxNumReadsAfterDownsampling = Math.min((int) ((fraction + EXPECTED_ACCURACY) * totalReads), totalReads);
+                expectedMinDiscardedItems = totalReads - expectedMaxNumReadsAfterDownsampling;
+                expectedMaxDiscardedItems = totalReads - expectedMinNumReadsAfterDownsampling;
+            }
+        }
+
+        public Collection<SAMRecord> createReads() {
+            Collection<SAMRecord> reads = new ArrayList<SAMRecord>(totalReads);
+
+            SAMFileHeader header = ArtificialSAMUtils.createArtificialSamHeader(1, 1, 1000000);
+            reads.addAll(ArtificialSAMUtils.createStackOfIdenticalArtificialReads(totalReads, header, "foo", 0, 1, 100));
+
+            return reads;
+        }
+    }
+
+    @DataProvider(name = "FractionalDownsamplerTestDataProvider")
+    public Object[][] createFractionalDownsamplerTestData() {
+        for ( double fraction : Arrays.asList(0.0, 0.25, 0.5, 0.75, 1.0) ) {
+            for ( int totalReads : Arrays.asList(0, 1000, 10000) ) {
+                new FractionalDownsamplerTest(fraction, totalReads);
+            }
+        }
+
+        return FractionalDownsamplerTest.getTests(FractionalDownsamplerTest.class);
+    }
+
+    @Test(dataProvider = "FractionalDownsamplerTestDataProvider")
+    public void runFractionalDownsamplerTest( FractionalDownsamplerTest test ) {
+        logger.warn("Running test: " + test);
+
+        GenomeAnalysisEngine.resetRandomGenerator();
+
+        ReadsDownsampler<SAMRecord> downsampler = new FractionalDownsampler<SAMRecord>(test.fraction);
+
+        downsampler.submit(test.createReads());
+
+        if ( test.totalReads > 0 ) {
+            if ( test.fraction > FractionalDownsamplerTest.EXPECTED_ACCURACY ) {
+                Assert.assertTrue(downsampler.hasFinalizedItems());
+                Assert.assertTrue(downsampler.peekFinalized() != null);
+            }
+            Assert.assertFalse(downsampler.hasPendingItems());
+            Assert.assertTrue(downsampler.peekPending() == null);
+        }
+        else {
+            Assert.assertFalse(downsampler.hasFinalizedItems() || downsampler.hasPendingItems());
+            Assert.assertTrue(downsampler.peekFinalized() == null && downsampler.peekPending() == null);
+        }
+
+        downsampler.signalEndOfInput();
+
+        if ( test.totalReads > 0 ) {
+            if ( test.fraction > FractionalDownsamplerTest.EXPECTED_ACCURACY ) {
+                Assert.assertTrue(downsampler.hasFinalizedItems());
+                Assert.assertTrue(downsampler.peekFinalized() != null);
+            }
+            Assert.assertFalse(downsampler.hasPendingItems());
+            Assert.assertTrue(downsampler.peekPending() == null);
+        }
+        else {
+            Assert.assertFalse(downsampler.hasFinalizedItems() || downsampler.hasPendingItems());
+            Assert.assertTrue(downsampler.peekFinalized() == null && downsampler.peekPending() == null);
+        }
+
+        List<SAMRecord> downsampledReads = downsampler.consumeFinalizedItems();
+        Assert.assertFalse(downsampler.hasFinalizedItems() || downsampler.hasPendingItems());
+        Assert.assertTrue(downsampler.peekFinalized() == null && downsampler.peekPending() == null);
+
+        Assert.assertTrue(downsampledReads.size() >= test.expectedMinNumReadsAfterDownsampling &&
+                          downsampledReads.size() <= test.expectedMaxNumReadsAfterDownsampling);
+
+        Assert.assertTrue(downsampler.getNumberOfDiscardedItems() >= test.expectedMinDiscardedItems &&
+                          downsampler.getNumberOfDiscardedItems() <= test.expectedMaxDiscardedItems);
+
+        Assert.assertEquals(downsampler.getNumberOfDiscardedItems(), test.totalReads - downsampledReads.size());
+
+        downsampler.resetStats();
+        Assert.assertEquals(downsampler.getNumberOfDiscardedItems(), 0);
+    }
+}
diff --git a/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/engine/downsampling/LevelingDownsamplerUnitTest.java b/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/engine/downsampling/LevelingDownsamplerUnitTest.java
new file mode 100644
index 0000000..2544b72
--- /dev/null
+++ b/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/engine/downsampling/LevelingDownsamplerUnitTest.java
@@ -0,0 +1,163 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.engine.downsampling;
+
+import org.broadinstitute.gatk.utils.BaseTest;
+import org.broadinstitute.gatk.engine.GenomeAnalysisEngine;
+import org.testng.annotations.Test;
+import org.testng.annotations.DataProvider;
+import org.testng.Assert;
+
+import java.util.*;
+
+public class LevelingDownsamplerUnitTest extends BaseTest {
+
+    private static class LevelingDownsamplerUniformStacksTest extends TestDataProvider {
+        public enum DataStructure { LINKED_LIST, ARRAY_LIST }
+
+        int targetSize;
+        int numStacks;
+        int stackSize;
+        DataStructure dataStructure;
+        int expectedSize;
+
+        public LevelingDownsamplerUniformStacksTest( int targetSize, int numStacks, int stackSize, DataStructure dataStructure ) {
+            super(LevelingDownsamplerUniformStacksTest.class);
+
+            this.targetSize = targetSize;
+            this.numStacks = numStacks;
+            this.stackSize = stackSize;
+            this.dataStructure = dataStructure;
+            expectedSize = calculateExpectedDownsampledStackSize();
+
+            setName(String.format("%s: targetSize=%d numStacks=%d stackSize=%d dataStructure=%s expectedSize=%d",
+                    getClass().getSimpleName(), targetSize, numStacks, stackSize, dataStructure, expectedSize));
+        }
+
+        public Collection<List<Object>> createStacks() {
+            Collection<List<Object>> stacks = new ArrayList<List<Object>>();
+
+            for ( int i = 1; i <= numStacks; i++ ) {
+                List<Object> stack = dataStructure == DataStructure.LINKED_LIST ? new LinkedList<Object>() : new ArrayList<Object>();
+
+                for ( int j = 1; j <= stackSize; j++ ) {
+                    stack.add(new Object());
+                }
+
+                stacks.add(stack);
+            }
+
+            return stacks;
+        }
+
+        private int calculateExpectedDownsampledStackSize() {
+            int numItemsToRemove = numStacks * stackSize - targetSize;
+
+            if ( numStacks == 0 ) {
+                return 0;
+            }
+            else if ( numItemsToRemove <= 0 ) {
+                return stackSize;
+            }
+
+            return Math.max(1, stackSize - (numItemsToRemove / numStacks));
+        }
+    }
+
+    @DataProvider(name = "UniformStacksDataProvider")
+    public Object[][] createUniformStacksTestData() {
+        for ( int targetSize = 1; targetSize <= 10000; targetSize *= 10 ) {
+            for ( int numStacks = 0; numStacks <= 10; numStacks++ ) {
+                for ( int stackSize = 1; stackSize <= 1000; stackSize *= 10 ) {
+                    for ( LevelingDownsamplerUniformStacksTest.DataStructure dataStructure : LevelingDownsamplerUniformStacksTest.DataStructure.values() ) {
+                        new LevelingDownsamplerUniformStacksTest(targetSize, numStacks, stackSize, dataStructure);
+                    }
+                }
+            }
+        }
+
+        return LevelingDownsamplerUniformStacksTest.getTests(LevelingDownsamplerUniformStacksTest.class);
+    }
+
+    @Test( dataProvider = "UniformStacksDataProvider" )
+    public void testLevelingDownsamplerWithUniformStacks( LevelingDownsamplerUniformStacksTest test ) {
+        logger.warn("Running test: " + test);
+
+        GenomeAnalysisEngine.resetRandomGenerator();
+
+        Downsampler<List<Object>> downsampler = new LevelingDownsampler<List<Object>, Object>(test.targetSize);
+
+        downsampler.submit(test.createStacks());
+
+        if ( test.numStacks > 0 ) {
+            Assert.assertFalse(downsampler.hasFinalizedItems());
+            Assert.assertTrue(downsampler.peekFinalized() == null);
+            Assert.assertTrue(downsampler.hasPendingItems());
+            Assert.assertTrue(downsampler.peekPending() != null);
+        }
+        else {
+            Assert.assertFalse(downsampler.hasFinalizedItems() || downsampler.hasPendingItems());
+            Assert.assertTrue(downsampler.peekFinalized() == null && downsampler.peekPending() == null);
+        }
+
+        downsampler.signalEndOfInput();
+
+        if ( test.numStacks > 0 ) {
+            Assert.assertTrue(downsampler.hasFinalizedItems());
+            Assert.assertTrue(downsampler.peekFinalized() != null);
+            Assert.assertFalse(downsampler.hasPendingItems());
+            Assert.assertTrue(downsampler.peekPending() == null);
+        }
+        else {
+            Assert.assertFalse(downsampler.hasFinalizedItems() || downsampler.hasPendingItems());
+            Assert.assertTrue(downsampler.peekFinalized() == null && downsampler.peekPending() == null);
+        }
+
+        final int sizeFromDownsampler = downsampler.size();
+        List<List<Object>> downsampledStacks = downsampler.consumeFinalizedItems();
+        Assert.assertFalse(downsampler.hasFinalizedItems() || downsampler.hasPendingItems());
+        Assert.assertTrue(downsampler.peekFinalized() == null && downsampler.peekPending() == null);
+
+        Assert.assertEquals(downsampledStacks.size(), test.numStacks);
+
+        int totalRemainingItems = 0;
+        for ( List<Object> stack : downsampledStacks ) {
+            Assert.assertTrue(Math.abs(stack.size() - test.expectedSize) <= 1);
+            totalRemainingItems += stack.size();
+        }
+
+        Assert.assertEquals(sizeFromDownsampler, totalRemainingItems);
+        int numItemsReportedDiscarded = downsampler.getNumberOfDiscardedItems();
+        int numItemsActuallyDiscarded = test.numStacks * test.stackSize - totalRemainingItems;
+
+        Assert.assertEquals(numItemsReportedDiscarded, numItemsActuallyDiscarded);
+
+        downsampler.resetStats();
+        Assert.assertEquals(downsampler.getNumberOfDiscardedItems(), 0);
+
+        Assert.assertTrue(totalRemainingItems <= Math.max(test.targetSize, test.numStacks));
+    }
+}
diff --git a/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/engine/downsampling/PerSampleDownsamplingReadsIteratorUnitTest.java b/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/engine/downsampling/PerSampleDownsamplingReadsIteratorUnitTest.java
new file mode 100644
index 0000000..2606a01
--- /dev/null
+++ b/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/engine/downsampling/PerSampleDownsamplingReadsIteratorUnitTest.java
@@ -0,0 +1,299 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.engine.downsampling;
+
+import htsjdk.samtools.SAMFileHeader;
+import htsjdk.samtools.SAMReadGroupRecord;
+import htsjdk.samtools.SAMRecord;
+import org.broadinstitute.gatk.utils.BaseTest;
+import org.broadinstitute.gatk.engine.GenomeAnalysisEngine;
+import org.broadinstitute.gatk.engine.iterators.GATKSAMIterator;
+import org.broadinstitute.gatk.engine.iterators.VerifyingSamIterator;
+import org.broadinstitute.gatk.utils.MathUtils;
+import org.broadinstitute.gatk.utils.exceptions.ReviewedGATKException;
+import org.broadinstitute.gatk.utils.sam.ArtificialMultiSampleReadStream;
+import org.broadinstitute.gatk.utils.sam.ArtificialSAMUtils;
+import org.broadinstitute.gatk.utils.sam.ArtificialSingleSampleReadStream;
+import org.broadinstitute.gatk.utils.sam.ArtificialSingleSampleReadStreamAnalyzer;
+import org.testng.annotations.DataProvider;
+import org.testng.annotations.Test;
+
+import java.util.*;
+
+public class PerSampleDownsamplingReadsIteratorUnitTest extends BaseTest {
+
+    private static class PerSampleDownsamplingReadsIteratorTest extends TestDataProvider {
+
+        // TODO: tests should distinguish between variance across samples and variance within a sample
+
+        private enum StreamDensity {
+            SPARSE         (MAX_READ_LENGTH,     MAX_READ_LENGTH * 2),
+            DENSE          (1,                   MIN_READ_LENGTH),
+            MIXED          (1,                   MAX_READ_LENGTH * 2),
+            UNIFORM_DENSE  (1,                   1),
+            UNIFORM_SPARSE (MAX_READ_LENGTH * 2, MAX_READ_LENGTH * 2);
+
+            int minDistanceBetweenStacks;
+            int maxDistanceBetweenStacks;
+
+            StreamDensity( int minDistanceBetweenStacks, int maxDistanceBetweenStacks ) {
+                this.minDistanceBetweenStacks = minDistanceBetweenStacks;
+                this.maxDistanceBetweenStacks = maxDistanceBetweenStacks;
+            }
+
+            public String toString() {
+                return String.format("StreamDensity:%d-%d", minDistanceBetweenStacks, maxDistanceBetweenStacks);
+            }
+        }
+
+        private enum StreamStackDepth {
+            NON_UNIFORM_LOW   (1,  5),
+            NON_UNIFORM_HIGH  (15, 20),
+            NON_UNIFORM_MIXED (1,  20),
+            UNIFORM_SINGLE    (1,  1),
+            UNIFORM_LOW       (2,  2),
+            UNIFORM_HIGH      (20, 20),
+            UNIFORM_MEDIUM    (10, 10);   // should set target coverage to this value for testing
+
+            int minReadsPerStack;
+            int maxReadsPerStack;
+
+            StreamStackDepth( int minReadsPerStack, int maxReadsPerStack ) {
+                this.minReadsPerStack = minReadsPerStack;
+                this.maxReadsPerStack = maxReadsPerStack;
+            }
+
+            public boolean isUniform() {
+                return minReadsPerStack == maxReadsPerStack;
+            }
+
+            public String toString() {
+                return String.format("StreamStackDepth:%d-%d", minReadsPerStack, maxReadsPerStack);
+            }
+        }
+
+        private enum StreamStacksPerContig {
+            UNIFORM(20, 20),
+            NON_UNIFORM(1, 30);
+
+            int minStacksPerContig;
+            int maxStacksPerContig;
+
+            StreamStacksPerContig( int minStacksPerContig, int maxStacksPerContig ) {
+                this.minStacksPerContig = minStacksPerContig;
+                this.maxStacksPerContig = maxStacksPerContig;
+            }
+
+            public boolean isUniform() {
+                return minStacksPerContig == maxStacksPerContig;
+            }
+
+            public String toString() {
+                return String.format("StreamStacksPerContig:%d-%d", minStacksPerContig, maxStacksPerContig);
+            }
+        }
+
+        // Not interested in testing multiple ranges for the read lengths, as none of our current
+        // downsamplers are affected by read length
+        private static final int MIN_READ_LENGTH = 50;
+        private static final int MAX_READ_LENGTH = 150;
+
+        private ReadsDownsamplerFactory<SAMRecord> downsamplerFactory;
+        private int targetCoverage;
+        private int numSamples;
+        private int minContigs;
+        private int maxContigs;
+        private StreamDensity streamDensity;
+        private StreamStackDepth streamStackDepth;
+        private StreamStacksPerContig streamStacksPerContig;
+        private double unmappedReadsFraction;
+        private int unmappedReadsCount;
+        private boolean verifySortedness;
+
+        private ArtificialMultiSampleReadStream mergedReadStream;
+        private Map<String, ArtificialSingleSampleReadStream> perSampleArtificialReadStreams;
+        private Map<String, ArtificialSingleSampleReadStreamAnalyzer> perSampleStreamAnalyzers;
+        private SAMFileHeader header;
+
+        public PerSampleDownsamplingReadsIteratorTest( ReadsDownsamplerFactory<SAMRecord> downsamplerFactory,
+                                                       int targetCoverage,
+                                                       int numSamples,
+                                                       int minContigs,
+                                                       int maxContigs,
+                                                       StreamDensity streamDensity,
+                                                       StreamStackDepth streamStackDepth,
+                                                       StreamStacksPerContig streamStacksPerContig,
+                                                       double unmappedReadsFraction,
+                                                       int unmappedReadsCount,
+                                                       boolean verifySortedness ) {
+            super(PerSampleDownsamplingReadsIteratorTest.class);
+
+            this.downsamplerFactory = downsamplerFactory;
+            this.targetCoverage = targetCoverage;
+            this.numSamples = numSamples;
+            this.minContigs = minContigs;
+            this.maxContigs = maxContigs;
+            this.streamDensity = streamDensity;
+            this.streamStackDepth = streamStackDepth;
+            this.streamStacksPerContig = streamStacksPerContig;
+            this.unmappedReadsFraction = unmappedReadsFraction;
+            this.unmappedReadsCount = unmappedReadsCount;
+            this.verifySortedness = verifySortedness;
+
+            header = createHeader();
+            createReadStreams();
+
+            setName(String.format("%s: targetCoverage=%d numSamples=%d minContigs=%d maxContigs=%d %s %s %s unmappedReadsFraction=%.2f unmappedReadsCount=%d verifySortedness=%b",
+                    getClass().getSimpleName(), targetCoverage, numSamples, minContigs, maxContigs, streamDensity, streamStackDepth, streamStacksPerContig, unmappedReadsFraction, unmappedReadsCount, verifySortedness));
+        }
+
+        private SAMFileHeader createHeader() {
+            SAMFileHeader header = ArtificialSAMUtils.createArtificialSamHeader(maxContigs, 1, (streamDensity.maxDistanceBetweenStacks + MAX_READ_LENGTH) * streamStacksPerContig.maxStacksPerContig + 100000);
+            List<String> readGroups = new ArrayList<String>(numSamples);
+            List<String> sampleNames = new ArrayList<String>(numSamples);
+
+            for ( int i = 0; i < numSamples; i++ ) {
+                readGroups.add("ReadGroup" + i);
+                sampleNames.add("Sample" + i);
+            }
+
+            return ArtificialSAMUtils.createEnumeratedReadGroups(header, readGroups, sampleNames);
+        }
+
+        private void createReadStreams() {
+            perSampleArtificialReadStreams = new HashMap<String, ArtificialSingleSampleReadStream>(numSamples);
+            perSampleStreamAnalyzers = new HashMap<String, ArtificialSingleSampleReadStreamAnalyzer>(numSamples);
+
+            for (SAMReadGroupRecord readGroup : header.getReadGroups() ) {
+                String readGroupID = readGroup.getReadGroupId();
+                String sampleName = readGroup.getSample();
+
+                int thisSampleNumContigs = MathUtils.randomIntegerInRange(minContigs, maxContigs);
+                int thisSampleStacksPerContig = MathUtils.randomIntegerInRange(streamStacksPerContig.minStacksPerContig, streamStacksPerContig.maxStacksPerContig);
+
+                int thisSampleNumUnmappedReads = GenomeAnalysisEngine.getRandomGenerator().nextDouble() < unmappedReadsFraction ? unmappedReadsCount : 0;
+
+                ArtificialSingleSampleReadStream thisSampleStream = new ArtificialSingleSampleReadStream(header,
+                                                                                                         readGroupID,
+                                                                                                         thisSampleNumContigs,
+                                                                                                         thisSampleStacksPerContig,
+                                                                                                         streamStackDepth.minReadsPerStack,
+                                                                                                         streamStackDepth.maxReadsPerStack,
+                                                                                                         streamDensity.minDistanceBetweenStacks,
+                                                                                                         streamDensity.maxDistanceBetweenStacks,
+                                                                                                         MIN_READ_LENGTH,
+                                                                                                         MAX_READ_LENGTH,
+                                                                                                         thisSampleNumUnmappedReads);
+                perSampleArtificialReadStreams.put(sampleName, thisSampleStream);
+                perSampleStreamAnalyzers.put(sampleName, new PositionallyDownsampledArtificialSingleSampleReadStreamAnalyzer(thisSampleStream, targetCoverage));
+            }
+
+            mergedReadStream = new ArtificialMultiSampleReadStream(perSampleArtificialReadStreams.values());
+        }
+
+        public void run() {
+            GATKSAMIterator downsamplingIter = new PerSampleDownsamplingReadsIterator(mergedReadStream.getGATKSAMIterator(), downsamplerFactory);
+
+            if ( verifySortedness ) {
+                downsamplingIter = new VerifyingSamIterator(downsamplingIter);
+            }
+
+            while ( downsamplingIter.hasNext() ) {
+                SAMRecord read = downsamplingIter.next();
+                String sampleName = read.getReadGroup() != null ? read.getReadGroup().getSample() : null;
+
+                ArtificialSingleSampleReadStreamAnalyzer analyzer = perSampleStreamAnalyzers.get(sampleName);
+                if ( analyzer != null ) {
+                    analyzer.update(read);
+                }
+                else {
+                    throw new ReviewedGATKException("bug: stream analyzer for sample " + sampleName + " not found");
+                }
+            }
+
+            for ( Map.Entry<String, ArtificialSingleSampleReadStreamAnalyzer> analyzerEntry : perSampleStreamAnalyzers.entrySet() ) {
+                ArtificialSingleSampleReadStreamAnalyzer analyzer = analyzerEntry.getValue();
+                analyzer.finalizeStats();
+
+                // Validate the downsampled read stream for each sample individually
+                analyzer.validate();
+            }
+
+            // Allow memory used by this test to be reclaimed:
+            mergedReadStream = null;
+            perSampleArtificialReadStreams = null;
+            perSampleStreamAnalyzers = null;
+        }
+    }
+
+    @DataProvider(name = "PerSampleDownsamplingReadsIteratorTestDataProvider")
+    public Object[][] createPerSampleDownsamplingReadsIteratorTests() {
+
+        GenomeAnalysisEngine.resetRandomGenerator();
+
+        // Some values don't vary across tests
+        int targetCoverage = PerSampleDownsamplingReadsIteratorTest.StreamStackDepth.UNIFORM_MEDIUM.minReadsPerStack;
+        ReadsDownsamplerFactory<SAMRecord> downsamplerFactory = new SimplePositionalDownsamplerFactory<SAMRecord>(targetCoverage);
+        int maxContigs = 3;
+        boolean verifySortedness = true;
+
+        for ( int numSamples : Arrays.asList(1, 2, 10) ) {
+            for ( int minContigs = 1; minContigs <= maxContigs; minContigs++ ) {
+                for ( PerSampleDownsamplingReadsIteratorTest.StreamDensity streamDensity : PerSampleDownsamplingReadsIteratorTest.StreamDensity.values() ) {
+                    for ( PerSampleDownsamplingReadsIteratorTest.StreamStackDepth streamStackDepth : PerSampleDownsamplingReadsIteratorTest.StreamStackDepth.values() ) {
+                        for (PerSampleDownsamplingReadsIteratorTest.StreamStacksPerContig streamStacksPerContig : PerSampleDownsamplingReadsIteratorTest.StreamStacksPerContig.values() ) {
+                            for ( double unmappedReadsFraction : Arrays.asList(0.0, 1.0, 0.5) ) {
+                                for ( int unmappedReadsCount : Arrays.asList(1, 50) ) {
+                                    new PerSampleDownsamplingReadsIteratorTest(downsamplerFactory,
+                                                                               targetCoverage,
+                                                                               numSamples,
+                                                                               minContigs,
+                                                                               maxContigs,
+                                                                               streamDensity,
+                                                                               streamStackDepth,
+                                                                               streamStacksPerContig,
+                                                                               unmappedReadsFraction,
+                                                                               unmappedReadsCount,
+                                                                               verifySortedness);
+                                }
+                            }
+                        }
+                    }
+                }
+            }
+        }
+
+        return PerSampleDownsamplingReadsIteratorTest.getTests(PerSampleDownsamplingReadsIteratorTest.class);
+    }
+
+    @Test(dataProvider = "PerSampleDownsamplingReadsIteratorTestDataProvider")
+    public void runPerSampleDownsamplingReadsIteratorTest( PerSampleDownsamplingReadsIteratorTest test ) {
+        logger.warn("Running test: " + test);
+
+        GenomeAnalysisEngine.resetRandomGenerator();
+        test.run();
+    }
+}
diff --git a/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/engine/downsampling/PositionallyDownsampledArtificialSingleSampleReadStreamAnalyzer.java b/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/engine/downsampling/PositionallyDownsampledArtificialSingleSampleReadStreamAnalyzer.java
new file mode 100644
index 0000000..b8a57e7
--- /dev/null
+++ b/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/engine/downsampling/PositionallyDownsampledArtificialSingleSampleReadStreamAnalyzer.java
@@ -0,0 +1,127 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.engine.downsampling;
+
+import org.broadinstitute.gatk.utils.exceptions.ReviewedGATKException;
+import org.broadinstitute.gatk.utils.sam.ArtificialSingleSampleReadStream;
+import org.broadinstitute.gatk.utils.sam.ArtificialSingleSampleReadStreamAnalyzer;
+
+/**
+ * Class for analyzing an artificial read stream that has been positionally downsampled, and verifying
+ * that the downsampling was done correctly without changing the stream in unexpected ways.
+ *
+ * @author David Roazen
+ */
+public class PositionallyDownsampledArtificialSingleSampleReadStreamAnalyzer extends ArtificialSingleSampleReadStreamAnalyzer {
+    private int targetCoverage;
+
+    public PositionallyDownsampledArtificialSingleSampleReadStreamAnalyzer( ArtificialSingleSampleReadStream originalStream, int targetCoverage ) {
+        super(originalStream);
+        this.targetCoverage = targetCoverage;
+    }
+
+    /**
+     * Overridden validate() method that checks for the effects of positional downsampling in addition to checking
+     * for whether the original properties of the stream not affected by downsampling have been preserved
+     */
+    @Override
+    public void validate() {
+        if ( (originalStream.getNumContigs() == 0 || originalStream.getNumStacksPerContig() == 0) && originalStream.getNumUnmappedReads() == 0 ) {
+            if ( totalReads != 0 ) {
+                throw new ReviewedGATKException("got reads from the stream, but the stream was configured to have 0 reads");
+            }
+            return;  // no further validation needed for the 0-reads case
+        }
+        else if ( totalReads == 0 ) {
+            throw new ReviewedGATKException("got no reads from the stream, but the stream was configured to have > 0 reads");
+        }
+
+        if ( ! allSamplesMatch ) {
+            throw new ReviewedGATKException("some reads had the wrong sample");
+        }
+
+        if ( numContigs != originalStream.getNumContigs() ) {
+            throw new ReviewedGATKException("number of contigs not correct");
+        }
+
+        if ( stacksPerContig.size() != originalStream.getNumContigs() ) {
+            throw new ReviewedGATKException(String.format("bug in analyzer code: calculated sizes for %d contigs even though there were only %d contigs",
+                                                           stacksPerContig.size(), originalStream.getNumContigs()));
+        }
+
+        for ( int contigStackCount : stacksPerContig ) {
+            if ( contigStackCount != originalStream.getNumStacksPerContig() ) {
+                throw new ReviewedGATKException("contig had incorrect number of stacks");
+            }
+        }
+
+        if ( originalStream.getNumStacksPerContig() > 0 ) {
+
+            // Check for the effects of positional downsampling:
+            int stackMinimumAfterDownsampling = Math.min(targetCoverage, originalStream.getMinReadsPerStack());
+            int stackMaximumAfterDownsampling = targetCoverage;
+
+            if ( minReadsPerStack < stackMinimumAfterDownsampling ) {
+                throw new ReviewedGATKException("stack had fewer than the minimum number of reads after downsampling");
+            }
+            if ( maxReadsPerStack > stackMaximumAfterDownsampling ) {
+                throw new ReviewedGATKException("stack had more than the maximum number of reads after downsampling");
+            }
+        }
+        else if ( minReadsPerStack != null || maxReadsPerStack != null ) {
+            throw new ReviewedGATKException("bug in analyzer code: reads per stack was calculated even though 0 stacks per contig was specified");
+        }
+
+        if ( originalStream.getNumStacksPerContig() > 1 ) {
+            if ( minDistanceBetweenStacks < originalStream.getMinDistanceBetweenStacks() ) {
+                throw new ReviewedGATKException("stacks were separated by less than the minimum distance");
+            }
+            if ( maxDistanceBetweenStacks > originalStream.getMaxDistanceBetweenStacks() ) {
+                throw new ReviewedGATKException("stacks were separated by more than the maximum distance");
+            }
+        }
+        else if ( minDistanceBetweenStacks != null || maxDistanceBetweenStacks != null ) {
+            throw new ReviewedGATKException("bug in analyzer code: distance between stacks was calculated even though numStacksPerContig was <= 1");
+        }
+
+        if ( minReadLength < originalStream.getMinReadLength() ) {
+            throw new ReviewedGATKException("read was shorter than the minimum allowed length");
+        }
+        if ( maxReadLength > originalStream.getMaxReadLength() ) {
+            throw new ReviewedGATKException("read was longer than the maximum allowed length");
+        }
+
+        if ( numUnmappedReads != originalStream.getNumUnmappedReads() ) {
+            throw new ReviewedGATKException(String.format("wrong number of unmapped reads: requested %d but saw %d",
+                                                           originalStream.getNumUnmappedReads(), numUnmappedReads));
+        }
+
+        if ( (originalStream.getNumContigs() == 0 || originalStream.getNumStacksPerContig() == 0) &&
+             numUnmappedReads != totalReads ) {
+            throw new ReviewedGATKException("stream should have consisted only of unmapped reads, but saw some mapped reads");
+        }
+    }
+}
diff --git a/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/engine/downsampling/ReservoirDownsamplerUnitTest.java b/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/engine/downsampling/ReservoirDownsamplerUnitTest.java
new file mode 100644
index 0000000..4e6f157
--- /dev/null
+++ b/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/engine/downsampling/ReservoirDownsamplerUnitTest.java
@@ -0,0 +1,131 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.engine.downsampling;
+
+import htsjdk.samtools.SAMFileHeader;
+import htsjdk.samtools.SAMRecord;
+import org.broadinstitute.gatk.utils.BaseTest;
+import org.broadinstitute.gatk.engine.GenomeAnalysisEngine;
+import org.broadinstitute.gatk.utils.sam.ArtificialSAMUtils;
+import org.testng.annotations.DataProvider;
+import org.testng.annotations.Test;
+import org.testng.Assert;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+
+public class ReservoirDownsamplerUnitTest extends BaseTest {
+
+    private static class ReservoirDownsamplerTest extends TestDataProvider {
+        int reservoirSize;
+        int totalReads;
+        int expectedNumReadsAfterDownsampling;
+        int expectedNumDiscardedItems;
+
+        public ReservoirDownsamplerTest( int reservoirSize, int totalReads ) {
+            super(ReservoirDownsamplerTest.class);
+
+            this.reservoirSize = reservoirSize;
+            this.totalReads = totalReads;
+
+            expectedNumReadsAfterDownsampling = Math.min(reservoirSize, totalReads);
+            expectedNumDiscardedItems = totalReads <= reservoirSize ? 0 : totalReads - reservoirSize;
+
+            setName(String.format("%s: reservoirSize=%d totalReads=%d expectedNumReadsAfterDownsampling=%d expectedNumDiscardedItems=%d",
+                    getClass().getSimpleName(), reservoirSize, totalReads, expectedNumReadsAfterDownsampling, expectedNumDiscardedItems));
+        }
+
+        public Collection<SAMRecord> createReads() {
+            Collection<SAMRecord> reads = new ArrayList<SAMRecord>(totalReads);
+
+            SAMFileHeader header = ArtificialSAMUtils.createArtificialSamHeader(1, 1, 1000000);
+            reads.addAll(ArtificialSAMUtils.createStackOfIdenticalArtificialReads(totalReads, header, "foo", 0, 1, 100));
+
+            return reads;
+        }
+    }
+
+    @DataProvider(name = "ReservoirDownsamplerTestDataProvider")
+    public Object[][] createReservoirDownsamplerTestData() {
+        for ( int reservoirSize = 1; reservoirSize <= 10000; reservoirSize *= 10 ) {
+            new ReservoirDownsamplerTest(reservoirSize, 0);
+            for ( int totalReads = 1; totalReads <= 10000; totalReads *= 10 ) {
+                new ReservoirDownsamplerTest(reservoirSize, totalReads);
+            }
+        }
+
+        return ReservoirDownsamplerTest.getTests(ReservoirDownsamplerTest.class);
+    }
+
+    @Test(dataProvider = "ReservoirDownsamplerTestDataProvider")
+    public void testReservoirDownsampler( ReservoirDownsamplerTest test ) {
+        logger.warn("Running test: " + test);
+
+        GenomeAnalysisEngine.resetRandomGenerator();
+
+        ReadsDownsampler<SAMRecord> downsampler = new ReservoirDownsampler<SAMRecord>(test.reservoirSize);
+
+        downsampler.submit(test.createReads());
+
+        if ( test.totalReads > 0 ) {
+            Assert.assertTrue(downsampler.hasFinalizedItems());
+            Assert.assertTrue(downsampler.peekFinalized() != null);
+            Assert.assertFalse(downsampler.hasPendingItems());
+            Assert.assertTrue(downsampler.peekPending() == null);
+        }
+        else {
+            Assert.assertFalse(downsampler.hasFinalizedItems() || downsampler.hasPendingItems());
+            Assert.assertTrue(downsampler.peekFinalized() == null && downsampler.peekPending() == null);
+        }
+
+        downsampler.signalEndOfInput();
+
+        if ( test.totalReads > 0 ) {
+            Assert.assertTrue(downsampler.hasFinalizedItems());
+            Assert.assertTrue(downsampler.peekFinalized() != null);
+            Assert.assertFalse(downsampler.hasPendingItems());
+            Assert.assertTrue(downsampler.peekPending() == null);
+        }
+        else {
+            Assert.assertFalse(downsampler.hasFinalizedItems() || downsampler.hasPendingItems());
+            Assert.assertTrue(downsampler.peekFinalized() == null && downsampler.peekPending() == null);
+        }
+
+        Assert.assertEquals(downsampler.size(), test.expectedNumReadsAfterDownsampling);
+        List<SAMRecord> downsampledReads = downsampler.consumeFinalizedItems();
+        Assert.assertFalse(downsampler.hasFinalizedItems() || downsampler.hasPendingItems());
+        Assert.assertTrue(downsampler.peekFinalized() == null && downsampler.peekPending() == null);
+
+        Assert.assertEquals(downsampledReads.size(), test.expectedNumReadsAfterDownsampling);
+
+        Assert.assertEquals(downsampler.getNumberOfDiscardedItems(), test.expectedNumDiscardedItems);
+        Assert.assertEquals(test.totalReads - downsampledReads.size(), test.expectedNumDiscardedItems);
+
+        downsampler.resetStats();
+        Assert.assertEquals(downsampler.getNumberOfDiscardedItems(), 0);
+    }
+}
diff --git a/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/engine/downsampling/SimplePositionalDownsamplerUnitTest.java b/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/engine/downsampling/SimplePositionalDownsamplerUnitTest.java
new file mode 100644
index 0000000..e04c347
--- /dev/null
+++ b/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/engine/downsampling/SimplePositionalDownsamplerUnitTest.java
@@ -0,0 +1,331 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.engine.downsampling;
+
+import htsjdk.samtools.SAMFileHeader;
+import htsjdk.samtools.SAMRecord;
+import org.broadinstitute.gatk.utils.BaseTest;
+import org.broadinstitute.gatk.engine.GenomeAnalysisEngine;
+import org.broadinstitute.gatk.utils.sam.ArtificialSAMUtils;
+import org.broadinstitute.gatk.utils.sam.GATKSAMRecord;
+import org.testng.annotations.DataProvider;
+import org.testng.annotations.Test;
+import org.testng.Assert;
+
+import java.util.*;
+
+public class SimplePositionalDownsamplerUnitTest extends BaseTest {
+
+    private static class SimplePositionalDownsamplerTest extends TestDataProvider {
+        int targetCoverage;
+        int numStacks;
+        List<Integer> stackSizes;
+        List<Integer> expectedStackSizes;
+        boolean multipleContigs;
+        int totalInitialReads;
+
+        public SimplePositionalDownsamplerTest( int targetCoverage, List<Integer> stackSizes, boolean multipleContigs ) {
+            super(SimplePositionalDownsamplerTest.class);
+
+            this.targetCoverage = targetCoverage;
+            this.numStacks = stackSizes.size();
+            this.stackSizes = stackSizes;
+            this.multipleContigs = multipleContigs;
+
+            calculateExpectedDownsampledStackSizes();
+
+            totalInitialReads = 0;
+            for ( Integer stackSize : stackSizes ) {
+                totalInitialReads += stackSize;
+            }
+
+            setName(String.format("%s: targetCoverage=%d numStacks=%d stackSizes=%s expectedSizes=%s multipleContigs=%b",
+                    getClass().getSimpleName(), targetCoverage, numStacks, stackSizes, expectedStackSizes, multipleContigs));
+        }
+
+        public Collection<SAMRecord> createReads() {
+            Collection<SAMRecord> reads = new ArrayList<SAMRecord>();
+            SAMFileHeader header = multipleContigs ?
+                                   ArtificialSAMUtils.createArtificialSamHeader(2, 1, 1000000) :
+                                   ArtificialSAMUtils.createArtificialSamHeader(1, 1, 1000000);
+
+            int refIndex = 0;
+            int alignmentStart = 1;
+            int readLength = 100;
+
+            for ( int i = 0; i < numStacks; i++ ) {
+                if ( multipleContigs && refIndex == 0 && i >= numStacks / 2 ) {
+                    refIndex++;
+                }
+
+                reads.addAll(ArtificialSAMUtils.createStackOfIdenticalArtificialReads(stackSizes.get(i), header, "foo",
+                                                                                      refIndex, alignmentStart, readLength));
+
+                alignmentStart += 10;
+            }
+
+            return reads;
+        }
+
+        private void calculateExpectedDownsampledStackSizes() {
+            expectedStackSizes = new ArrayList<Integer>(numStacks);
+
+            for ( Integer stackSize : stackSizes ) {
+                int expectedSize = targetCoverage >= stackSize ? stackSize : targetCoverage;
+                expectedStackSizes.add(expectedSize);
+            }
+        }
+    }
+
+    @DataProvider(name = "SimplePositionalDownsamplerTestDataProvider")
+    public Object[][] createSimplePositionalDownsamplerTestData() {
+        GenomeAnalysisEngine.resetRandomGenerator();
+
+        for ( int targetCoverage = 1; targetCoverage <= 10000; targetCoverage *= 10 ) {
+            for ( int contigs = 1; contigs <= 2; contigs++ ) {
+                for ( int numStacks = 0; numStacks <= 10; numStacks++ ) {
+                    List<Integer> stackSizes = new ArrayList<Integer>(numStacks);
+                    for ( int stack = 1; stack <= numStacks; stack++ ) {
+                        stackSizes.add(GenomeAnalysisEngine.getRandomGenerator().nextInt(targetCoverage * 2) + 1);
+                    }
+                    new SimplePositionalDownsamplerTest(targetCoverage, stackSizes, contigs > 1);
+                }
+            }
+        }
+
+        return SimplePositionalDownsamplerTest.getTests(SimplePositionalDownsamplerTest.class);
+    }
+
+    @Test( dataProvider = "SimplePositionalDownsamplerTestDataProvider" )
+    public void testSimplePostionalDownsampler( SimplePositionalDownsamplerTest test ) {
+        logger.warn("Running test: " + test);
+
+        GenomeAnalysisEngine.resetRandomGenerator();
+
+        ReadsDownsampler<SAMRecord> downsampler = new SimplePositionalDownsampler<SAMRecord>(test.targetCoverage);
+
+        downsampler.submit(test.createReads());
+
+        if ( test.numStacks > 1 ) {
+            Assert.assertTrue(downsampler.hasFinalizedItems());
+            Assert.assertTrue(downsampler.peekFinalized() != null);
+            Assert.assertTrue(downsampler.hasPendingItems());
+            Assert.assertTrue(downsampler.peekPending() != null);
+        }
+        else if ( test.numStacks == 1 ) {
+            Assert.assertFalse(downsampler.hasFinalizedItems());
+            Assert.assertTrue(downsampler.peekFinalized() == null);
+            Assert.assertTrue(downsampler.hasPendingItems());
+            Assert.assertTrue(downsampler.peekPending() != null);
+        }
+        else {
+            Assert.assertFalse(downsampler.hasFinalizedItems() || downsampler.hasPendingItems());
+            Assert.assertTrue(downsampler.peekFinalized() == null && downsampler.peekPending() == null);
+        }
+
+        downsampler.signalEndOfInput();
+
+        if ( test.numStacks > 0 ) {
+            Assert.assertTrue(downsampler.hasFinalizedItems());
+            Assert.assertTrue(downsampler.peekFinalized() != null);
+            Assert.assertFalse(downsampler.hasPendingItems());
+            Assert.assertTrue(downsampler.peekPending() == null);
+        }
+        else {
+            Assert.assertFalse(downsampler.hasFinalizedItems() || downsampler.hasPendingItems());
+            Assert.assertTrue(downsampler.peekFinalized() == null && downsampler.peekPending() == null);
+        }
+
+        List<SAMRecord> downsampledReads = downsampler.consumeFinalizedItems();
+        Assert.assertFalse(downsampler.hasFinalizedItems() || downsampler.hasPendingItems());
+        Assert.assertTrue(downsampler.peekFinalized() == null && downsampler.peekPending() == null);
+
+        if ( test.numStacks == 0 ) {
+            Assert.assertTrue(downsampledReads.isEmpty());
+        }
+        else {
+            List<Integer> downsampledStackSizes = getDownsampledStackSizesAndVerifySortedness(downsampledReads);
+
+            Assert.assertEquals(downsampledStackSizes.size(), test.numStacks);
+            Assert.assertEquals(downsampledStackSizes, test.expectedStackSizes);
+
+            int numReadsActuallyEliminated = test.totalInitialReads - downsampledReads.size();
+            int numReadsReportedEliminated = downsampler.getNumberOfDiscardedItems();
+            Assert.assertEquals(numReadsActuallyEliminated, numReadsReportedEliminated);
+        }
+
+        downsampler.resetStats();
+        Assert.assertEquals(downsampler.getNumberOfDiscardedItems(), 0);
+    }
+
+    private List<Integer> getDownsampledStackSizesAndVerifySortedness( List<SAMRecord> downsampledReads ) {
+        List<Integer> stackSizes = new ArrayList<Integer>();
+
+        if ( downsampledReads.isEmpty() ) {
+            return stackSizes;
+        }
+
+        Iterator<SAMRecord> iter = downsampledReads.iterator();
+        Assert.assertTrue(iter.hasNext());
+
+        SAMRecord previousRead = iter.next();
+        int currentStackSize = 1;
+
+        while ( iter.hasNext() ) {
+            SAMRecord currentRead = iter.next();
+
+            if ( currentRead.getReferenceIndex() > previousRead.getReferenceIndex() || currentRead.getAlignmentStart() > previousRead.getAlignmentStart() ) {
+                stackSizes.add(currentStackSize);
+                currentStackSize = 1;
+            }
+            else if ( currentRead.getReferenceIndex() < previousRead.getReferenceIndex() || currentRead.getAlignmentStart() < previousRead.getAlignmentStart() ) {
+                Assert.fail(String.format("Reads are out of order: %s %s", previousRead, currentRead));
+            }
+            else {
+                currentStackSize++;
+            }
+
+            previousRead = currentRead;
+        }
+
+        stackSizes.add(currentStackSize);
+        return stackSizes;
+    }
+
+    @Test
+    public void testSimplePositionalDownsamplerSignalNoMoreReadsBefore() {
+        ReadsDownsampler<SAMRecord> downsampler = new SimplePositionalDownsampler<SAMRecord>(1000);
+
+        SAMFileHeader header = ArtificialSAMUtils.createArtificialSamHeader(1, 1, 1000000);
+
+        Collection<SAMRecord> readStack = new ArrayList<SAMRecord>();
+        readStack.addAll(ArtificialSAMUtils.createStackOfIdenticalArtificialReads(50, header, "foo", 0, 1, 100));
+        downsampler.submit(readStack);
+
+        Assert.assertFalse(downsampler.hasFinalizedItems());
+        Assert.assertTrue(downsampler.peekFinalized() == null);
+        Assert.assertTrue(downsampler.hasPendingItems());
+        Assert.assertTrue(downsampler.peekPending() != null);
+
+        SAMRecord laterRead = ArtificialSAMUtils.createArtificialRead(header, "foo", 0, 2, 100);
+        downsampler.signalNoMoreReadsBefore(laterRead);
+
+        Assert.assertTrue(downsampler.hasFinalizedItems());
+        Assert.assertTrue(downsampler.peekFinalized() != null);
+        Assert.assertFalse(downsampler.hasPendingItems());
+        Assert.assertTrue(downsampler.peekPending() == null);
+
+        List<SAMRecord> downsampledReads = downsampler.consumeFinalizedItems();
+
+        Assert.assertEquals(downsampledReads.size(), readStack.size());
+    }
+
+    @Test
+    public void testBasicUnmappedReadsSupport() {
+        ReadsDownsampler<SAMRecord> downsampler = new SimplePositionalDownsampler<SAMRecord>(100);
+
+        SAMFileHeader header = ArtificialSAMUtils.createArtificialSamHeader(1, 1, 1000000);
+
+        Collection<SAMRecord> readStack = new ArrayList<SAMRecord>();
+        readStack.addAll(ArtificialSAMUtils.createStackOfIdenticalArtificialReads(200, header, "foo", SAMRecord.NO_ALIGNMENT_REFERENCE_INDEX,
+                                                                                  SAMRecord.NO_ALIGNMENT_START, 100));
+        for ( SAMRecord read : readStack ) {
+            Assert.assertTrue(read.getReadUnmappedFlag());
+        }
+
+        downsampler.submit(readStack);
+        downsampler.signalEndOfInput();
+
+        List<SAMRecord> downsampledReads = downsampler.consumeFinalizedItems();
+
+        // Unmapped reads should not get downsampled at all by the SimplePositionalDownsampler
+        Assert.assertEquals(downsampledReads.size(), readStack.size());
+
+        for ( SAMRecord read: downsampledReads ) {
+            Assert.assertTrue(read.getReadUnmappedFlag());
+        }
+    }
+
+    @Test
+    public void testMixedMappedAndUnmappedReadsSupport() {
+        ReadsDownsampler<SAMRecord> downsampler = new SimplePositionalDownsampler<SAMRecord>(100);
+
+        SAMFileHeader header = ArtificialSAMUtils.createArtificialSamHeader(1, 1, 1000000);
+
+        Collection<SAMRecord> mappedReadStack = new ArrayList<SAMRecord>();
+        mappedReadStack.addAll(ArtificialSAMUtils.createStackOfIdenticalArtificialReads(200, header, "foo", 0, 1, 100));
+        for ( SAMRecord read : mappedReadStack ) {
+            Assert.assertFalse(read.getReadUnmappedFlag());
+        }
+
+        Collection<SAMRecord> unmappedReadStack = new ArrayList<SAMRecord>();
+        unmappedReadStack.addAll(ArtificialSAMUtils.createStackOfIdenticalArtificialReads(200, header, "foo", SAMRecord.NO_ALIGNMENT_REFERENCE_INDEX,
+                                                                                          SAMRecord.NO_ALIGNMENT_START, 100));
+        for ( SAMRecord read : unmappedReadStack ) {
+            Assert.assertTrue(read.getReadUnmappedFlag());
+        }
+
+        downsampler.submit(mappedReadStack);
+        downsampler.submit(unmappedReadStack);
+        downsampler.signalEndOfInput();
+
+        List<SAMRecord> downsampledReads = downsampler.consumeFinalizedItems();
+
+        // Unmapped reads should not get downsampled at all by the SimplePositionalDownsampler
+        Assert.assertEquals(downsampledReads.size(), 300);
+        Assert.assertEquals(downsampler.getNumberOfDiscardedItems(), 100);
+
+        int count = 1;
+        for ( SAMRecord read: downsampledReads ) {
+            if ( count <= 100 ) {
+                Assert.assertFalse(read.getReadUnmappedFlag());
+            }
+            else {
+                Assert.assertTrue(read.getReadUnmappedFlag());
+            }
+
+            count++;
+        }
+    }
+
+    @Test
+    public void testGATKSAMRecordSupport() {
+        ReadsDownsampler<GATKSAMRecord> downsampler = new SimplePositionalDownsampler<GATKSAMRecord>(1000);
+
+        SAMFileHeader header = ArtificialSAMUtils.createArtificialSamHeader(1, 1, 1000000);
+
+        List<GATKSAMRecord> reads = new ArrayList<GATKSAMRecord>();
+        for ( int i = 0; i < 10; i++ ) {
+            reads.add(ArtificialSAMUtils.createArtificialRead(header, "foo", 0, 10, 20 * i + 10));
+        }
+
+        downsampler.submit(reads);
+        downsampler.signalEndOfInput();
+        List<GATKSAMRecord> downsampledReads = downsampler.consumeFinalizedItems();
+
+        Assert.assertEquals(downsampledReads.size(), 10);
+    }
+}
diff --git a/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/engine/executive/ReduceTreeUnitTest.java b/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/engine/executive/ReduceTreeUnitTest.java
new file mode 100644
index 0000000..50f21a6
--- /dev/null
+++ b/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/engine/executive/ReduceTreeUnitTest.java
@@ -0,0 +1,254 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.engine.executive;
+
+
+import org.testng.Assert;
+import org.testng.annotations.AfterMethod;
+import org.testng.annotations.Test;
+import org.testng.annotations.BeforeMethod;
+
+import org.broadinstitute.gatk.utils.BaseTest;
+
+import java.util.concurrent.Callable;
+import java.util.concurrent.Future;
+import java.util.concurrent.FutureTask;
+import java.util.concurrent.ExecutionException;
+import java.util.List;
+import java.util.ArrayList;
+/**
+ * User: hanna
+ * Date: Apr 29, 2009
+ * Time: 10:40:49 AM
+ * BROAD INSTITUTE SOFTWARE COPYRIGHT NOTICE AND AGREEMENT
+ * Software and documentation are copyright 2005 by the Broad Institute.
+ * All rights are reserved.
+ *
+ * Users acknowledge that this software is supplied without any warranty or support.
+ * The Broad Institute is not responsible for its use, misuse, or
+ * functionality.
+ */
+
+/**
+ * Make sure the reduce tree organizes reduces in the correct way.
+ */
+
+public class ReduceTreeUnitTest extends BaseTest implements ReduceTree.TreeReduceNotifier {
+
+    /**
+     * The tree indicating reduce order.
+     */
+    private ReduceTree reduceTree = null;
+
+    /**
+     * 
+     */
+    private List<List<Integer>> reduces = new ArrayList<List<Integer>>();
+
+    @BeforeMethod
+    public void createTree() {
+        reduceTree = new ReduceTree( this );
+    }
+
+    @AfterMethod
+    public void destroyTree() {
+        reduceTree = null;
+        reduces.clear();
+    }
+
+    @Test
+    public void testNoValueReduce()
+        throws InterruptedException, ExecutionException {
+        reduceTree.complete();
+        Assert.assertEquals(reduceTree.getResult(), null, "Single-value reduce failed");
+    }
+
+    @Test
+    public void testSingleValueReduce()
+            throws InterruptedException, ExecutionException {
+        reduceTree.addEntry( getReduceTestEntry(1) );
+        reduceTree.complete();
+        Assert.assertEquals(reduceTree.getResult().get(), 1, "Single-value reduce failed");
+    }
+
+    @Test(expectedExceptions=IllegalStateException.class)
+    public void testIncompleteReduce()
+            throws InterruptedException, ExecutionException {
+        reduceTree.addEntry( getReduceTestEntry(1) );
+        reduceTree.getResult().get();
+    }
+
+    @Test
+    public void testDualValueReduce()
+        throws InterruptedException, ExecutionException {
+        reduceTree.addEntry( getReduceTestEntry(1) );
+        reduceTree.addEntry( getReduceTestEntry(2) );
+        reduceTree.complete();
+
+        List<Integer> expected = new ArrayList<Integer>();
+        expected.add( 1 );
+        expected.add( 2 );
+
+        // Test the result
+        Assert.assertEquals(reduceTree.getResult().get(), expected, "Dual-value reduce failed");
+
+        // Test the intermediate steps
+        Assert.assertEquals(reduces.size(), 1, "Size of incoming tree reduces incorrect");
+        Assert.assertEquals(reduces.get(0), expected, "Incoming tree reduce incorrect");
+    }
+
+    @Test
+    public void testThreeValueReduce()
+        throws InterruptedException, ExecutionException {
+        List<Integer> firstExpected = new ArrayList<Integer>();
+        firstExpected.add(1);
+        firstExpected.add(2);
+
+        List<Integer> finalExpected = new ArrayList<Integer>();
+        finalExpected.addAll( firstExpected );
+        finalExpected.add(3);
+
+        reduceTree.addEntry( getReduceTestEntry(1) );
+
+        Assert.assertEquals(reduces.size(), 0, "Reduce queue should be empty after entering a single element");
+
+        reduceTree.addEntry( getReduceTestEntry(2) );
+
+        Assert.assertEquals(reduces.size(), 1, "Reduce queue should have one element after two entries");
+        Assert.assertEquals(reduces.get(0), firstExpected, "Reduce queue element is incorrect after two entries");
+
+        reduceTree.addEntry( getReduceTestEntry(3) );
+
+        Assert.assertEquals(reduces.size(), 1, "Reduce queue should have one element after three entries");
+        Assert.assertEquals(reduces.get(0), firstExpected, "Reduce queue element is incorrect after three entries");
+
+        reduceTree.complete();
+
+        // Test the result
+        Assert.assertEquals(reduceTree.getResult().get(), finalExpected, "Three value reduce failed");
+
+        Assert.assertEquals(reduces.size(), 2, "Reduce queue should have two elements after three entries (complete)");
+        Assert.assertEquals(reduces.get(0), firstExpected, "Reduce queue element is incorrect after three entries");
+        Assert.assertEquals(reduces.get(1), finalExpected, "Reduce queue element is incorrect after three entries");
+    }
+
+    @Test
+    public void testFourValueReduce()
+        throws InterruptedException, ExecutionException {
+        List<Integer> lhsExpected = new ArrayList<Integer>();
+        lhsExpected.add(1);
+        lhsExpected.add(2);
+
+        List<Integer> rhsExpected = new ArrayList<Integer>();
+        rhsExpected.add(3);
+        rhsExpected.add(4);
+
+        List<Integer> finalExpected = new ArrayList<Integer>();
+        finalExpected.addAll(lhsExpected);
+        finalExpected.addAll(rhsExpected);
+
+        reduceTree.addEntry( getReduceTestEntry(1) );
+
+        Assert.assertEquals(reduces.size(), 0, "Reduce queue should be empty after entering a single element");
+
+        reduceTree.addEntry( getReduceTestEntry(2) );
+
+        Assert.assertEquals(reduces.size(), 1, "Reduce queue should have one element after two entries");
+        Assert.assertEquals(reduces.get(0), lhsExpected, "Reduce queue element is incorrect after two entries");
+
+        reduceTree.addEntry( getReduceTestEntry(3) );
+
+        Assert.assertEquals(reduces.size(), 1, "Reduce queue should have one element after three entries");
+        Assert.assertEquals(reduces.get(0), lhsExpected, "Reduce queue element is incorrect after three entries");
+
+        reduceTree.addEntry( getReduceTestEntry(4) );
+
+        Assert.assertEquals(reduces.size(), 3, "Reduce queue should have three elements after four entries");
+        Assert.assertEquals(reduces.get(0), lhsExpected, "Reduce queue element 0 is incorrect after three entries");
+        Assert.assertEquals(reduces.get(1), rhsExpected, "Reduce queue element 1 is incorrect after three entries");
+        Assert.assertEquals(reduces.get(2), finalExpected, "Reduce queue element 2 is incorrect after three entries");
+
+        reduceTree.complete();
+
+                // Test the result
+        Assert.assertEquals(reduceTree.getResult().get(), finalExpected, "Four-valued reduce failed");
+
+        // Test the working tree
+        Assert.assertEquals(reduces.size(), 3, "Didn't see correct number of reduces");
+        Assert.assertEquals(reduces.get(0), lhsExpected, "lhs of four value reduce failed");
+        Assert.assertEquals(reduces.get(1), rhsExpected, "rhs of four value reduce failed");
+        Assert.assertEquals(reduces.get(2), finalExpected, "final value four value reduce failed");
+    }
+
+
+    private Future getReduceTestEntry( Object value ) {
+        // Create a task and run it, assuring that the tests won't block on a get.
+        FutureTask task = new FutureTask( new ReduceTestEntry( value ) );
+        task.run();
+        return task;
+    }
+
+    public Future notifyReduce( Future lhs, Future rhs )  {
+        List<Integer> reduce = new ArrayList<Integer>();
+
+        try {
+            if( lhs == null && rhs == null )
+                throw new IllegalStateException("lhs and rhs are null");
+
+            if( lhs.get() instanceof List )
+                reduce.addAll((List)lhs.get());
+            else
+                reduce.add((Integer)lhs.get());
+
+            if( rhs != null ) {
+                if( rhs.get() instanceof List )
+                    reduce.addAll((List)rhs.get());
+                else
+                    reduce.add((Integer)rhs.get());
+            }
+        }
+        catch( Exception ex ) {
+            // just rethrow any exceptions
+            throw new RuntimeException(ex);
+        }
+
+        reduces.add( reduce );
+
+        return getReduceTestEntry( reduce );
+    }
+
+    private class ReduceTestEntry implements Callable {
+        private Object data;
+
+        public ReduceTestEntry( Object data ) {
+            this.data = data;
+        }
+
+        public Object call() {
+            return data;
+        }
+    }
+}
diff --git a/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/engine/filters/AllowNCigarMalformedReadFilterUnitTest.java b/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/engine/filters/AllowNCigarMalformedReadFilterUnitTest.java
new file mode 100644
index 0000000..7a01220
--- /dev/null
+++ b/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/engine/filters/AllowNCigarMalformedReadFilterUnitTest.java
@@ -0,0 +1,77 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.engine.filters;
+
+
+import htsjdk.samtools.SAMRecord;
+import org.broadinstitute.gatk.engine.arguments.ValidationExclusion;
+import org.testng.Assert;
+import org.testng.annotations.Test;
+
+import java.util.Collections;
+
+
+/**
+ * Tests for the {@link MalformedReadFilter} when the unsafe flag
+ * {@link ValidationExclusion.TYPE#ALLOW_N_CIGAR_READS} is set.
+ *
+ * @author Valentin Ruano-Rubio
+ * @since 6/6/13
+ */
+public class AllowNCigarMalformedReadFilterUnitTest extends MalformedReadFilterUnitTest {
+
+
+    @Override
+    protected ValidationExclusion composeValidationExclusion() {
+        return new ValidationExclusion(Collections.singletonList(ValidationExclusion.TYPE.ALLOW_N_CIGAR_READS));
+    }
+
+
+    @Test(enabled = true,
+            dataProvider= "UnsupportedCigarOperatorDataProvider")
+    @CigarOperatorTest(CigarOperatorTest.Outcome.IGNORE)
+    public void testCigarNOperatorFilterIgnore(final String cigarString) {
+
+        final MalformedReadFilter filter = buildMalformedReadFilter(false);
+        final SAMRecord nContainingCigarRead = buildSAMRecord(cigarString);
+        Assert.assertFalse(filter.filterOut(nContainingCigarRead),
+                "filters out N containing Cigar when it should ignore the fact");
+    }
+
+    @Test(enabled = false)
+    @Override
+    public void testCigarNOperatorFilterException(final String cigarString) {
+        // Nothing to do here.
+        // Just deactivates the parents test case.
+    }
+
+
+
+
+
+
+
+}
diff --git a/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/engine/filters/BadCigarFilterUnitTest.java b/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/engine/filters/BadCigarFilterUnitTest.java
new file mode 100644
index 0000000..bdb194c
--- /dev/null
+++ b/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/engine/filters/BadCigarFilterUnitTest.java
@@ -0,0 +1,91 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.engine.filters;
+
+import htsjdk.samtools.Cigar;
+import org.broadinstitute.gatk.utils.clipping.ReadClipperTestUtils;
+import org.broadinstitute.gatk.utils.sam.GATKSAMRecord;
+import org.testng.Assert;
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.Test;
+
+import java.util.List;
+
+/**
+ * Checks that the Bad Cigar filter works for all kinds of wonky cigars
+ *
+ * @author Mauricio Carneiro
+ * @since 3/20/12
+ */
+public class BadCigarFilterUnitTest {
+
+    public static final String[] BAD_CIGAR_LIST = {
+            "2D4M",               // starting with multiple deletions
+            "4M2D",               // ending with multiple deletions
+            "3M1I1D",             // adjacent indels AND ends in deletion
+            "1M1I1D2M",           // adjacent indels I->D
+            "1M1D2I1M",           // adjacent indels D->I
+            "1M1I2M1D",           // ends in single deletion with insertion in the middle
+            "4M1D",               // ends in single deletion
+            "1D4M",               // starts with single deletion
+            "2M1D1D2M",           // adjacent D's
+            "1M1I1I1M",           // adjacent I's
+            "1H1D4M",             // starting with deletion after H
+            "1S1D3M",             // starting with deletion after S
+            "1H1S1D3M",           // starting with deletion after HS
+            "4M1D1H",             // ending with deletion before H
+            "3M1D1S",             // ending with deletion before S
+            "3M1D1S1H",           // ending with deletion before HS
+            "10M2H10M",           // H in the middle
+            "10M2S10M",           // S in the middle
+            "1H1S10M2S10M1S1H",    // deceiving S in the middle
+            "1H1S10M2H10M1S1H"    // deceiving H in the middle
+    };
+
+    BadCigarFilter filter;
+
+    @BeforeClass
+    public void init() {
+        filter = new BadCigarFilter();
+    }
+
+    @Test(enabled = true)
+    public void testWonkyCigars () {
+        for (String cigarString : BAD_CIGAR_LIST) {
+            GATKSAMRecord read = ReadClipperTestUtils.makeReadFromCigar(cigarString);
+            Assert.assertTrue(filter.filterOut(read), read.getCigarString());
+        }
+    }
+
+    @Test(enabled = true)
+    public void testGoodCigars() {
+        List<Cigar> cigarList = ReadClipperTestUtils.generateCigarList(10);
+        for (Cigar cigar : cigarList) {
+            GATKSAMRecord read = ReadClipperTestUtils.makeReadFromCigar(cigar);
+            Assert.assertFalse(filter.filterOut(read), read.getCigarString());
+        }
+    }
+}
diff --git a/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/engine/filters/BadReadGroupsIntegrationTest.java b/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/engine/filters/BadReadGroupsIntegrationTest.java
new file mode 100644
index 0000000..3ff8ed4
--- /dev/null
+++ b/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/engine/filters/BadReadGroupsIntegrationTest.java
@@ -0,0 +1,52 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.engine.filters;
+
+import org.broadinstitute.gatk.engine.walkers.WalkerTest;
+import org.broadinstitute.gatk.utils.exceptions.UserException;
+import org.testng.annotations.Test;
+
+
+public class BadReadGroupsIntegrationTest extends WalkerTest {
+
+    @Test
+    public void testMissingReadGroup() {
+        WalkerTest.WalkerTestSpec spec = new WalkerTest.WalkerTestSpec(
+                "-T PrintReads -R " + b36KGReference + " -I " + privateTestDir + "missingReadGroup.bam -o /dev/null",
+                0,
+                UserException.ReadMissingReadGroup.class);
+        executeTest("test Missing Read Group", spec);
+    }
+
+    @Test
+    public void testUndefinedReadGroup() {
+        WalkerTest.WalkerTestSpec spec = new WalkerTest.WalkerTestSpec(
+                "-T PrintReads -R " + b36KGReference + " -I " + privateTestDir + "undefinedReadGroup.bam -o /dev/null",
+                0,
+                UserException.ReadHasUndefinedReadGroup.class);
+        executeTest("test Undefined Read Group", spec);
+    }
+}
diff --git a/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/engine/filters/MalformedReadFilterUnitTest.java b/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/engine/filters/MalformedReadFilterUnitTest.java
new file mode 100644
index 0000000..d25db50
--- /dev/null
+++ b/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/engine/filters/MalformedReadFilterUnitTest.java
@@ -0,0 +1,246 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.engine.filters;
+
+
+import htsjdk.samtools.Cigar;
+import htsjdk.samtools.SAMFileHeader;
+import htsjdk.samtools.SAMRecord;
+import htsjdk.samtools.TextCigarCodec;
+import org.broadinstitute.gatk.engine.GenomeAnalysisEngine;
+import org.broadinstitute.gatk.engine.arguments.ValidationExclusion;
+import org.broadinstitute.gatk.engine.datasources.reads.SAMDataSource;
+import org.broadinstitute.gatk.utils.sam.ArtificialSAMUtils;
+import org.broadinstitute.gatk.utils.sam.GATKSAMRecord;
+import org.testng.Assert;
+import org.testng.annotations.DataProvider;
+import org.testng.annotations.Test;
+import org.broadinstitute.gatk.utils.exceptions.UserException;
+import org.broadinstitute.gatk.utils.exceptions.UserException.UnsupportedCigarOperatorException;
+
+import java.lang.annotation.*;
+import java.lang.reflect.Method;
+import java.util.*;
+
+
+/**
+ * Tests for the MalformedReadFilter
+ *
+ * @author Eric Banks
+ * @since 3/14/13
+ */
+public class MalformedReadFilterUnitTest extends ReadFilterTest {
+
+    //////////////////////////////////////
+    // Test the checkSeqStored() method //
+    //////////////////////////////////////
+
+    @Test(enabled = true)
+    public void testCheckSeqStored () {
+
+        final GATKSAMRecord goodRead = ArtificialSAMUtils.createArtificialRead(new byte[]{(byte)'A'}, new byte[]{(byte)'A'}, "1M");
+        final GATKSAMRecord badRead = ArtificialSAMUtils.createArtificialRead(new byte[]{}, new byte[]{}, "1M");
+        badRead.setReadString("*");
+
+        Assert.assertTrue(MalformedReadFilter.checkSeqStored(goodRead, true));
+        Assert.assertFalse(MalformedReadFilter.checkSeqStored(badRead, true));
+
+        try {
+            MalformedReadFilter.checkSeqStored(badRead, false);
+            Assert.assertTrue(false, "We should have exceptioned out in the previous line");
+        } catch (UserException e) { }
+    }
+
+    @Test(enabled = true, dataProvider= "UnsupportedCigarOperatorDataProvider")
+    @CigarOperatorTest(CigarOperatorTest.Outcome.FILTER)
+    public void testCigarNOperatorFilterTruePositive(String cigarString) {
+
+       final MalformedReadFilter filter = buildMalformedReadFilter(true);
+       final SAMRecord nContainingCigarRead = buildSAMRecord(cigarString);
+       Assert.assertTrue(filter.filterOut(nContainingCigarRead),
+                  " Did not filtered out a N containing CIGAR read");
+    }
+
+    @Test(enabled = true, dataProvider= "UnsupportedCigarOperatorDataProvider")
+    @CigarOperatorTest(CigarOperatorTest.Outcome.ACCEPT)
+    public void testCigarNOperatorFilterTrueNegative(String cigarString) {
+
+        final MalformedReadFilter filter = buildMalformedReadFilter(true);
+        final SAMRecord nonNContainingCigarRead = buildSAMRecord(cigarString);
+        Assert.assertFalse(filter.filterOut(nonNContainingCigarRead),
+                    " Filtered out a non-N containing CIGAR read");
+    }
+
+    @Test(enabled = true,
+            expectedExceptions = UnsupportedCigarOperatorException.class,
+            dataProvider= "UnsupportedCigarOperatorDataProvider")
+    @CigarOperatorTest(CigarOperatorTest.Outcome.EXCEPTION)
+    public void testCigarNOperatorFilterException(final String cigarString) {
+
+        final MalformedReadFilter filter = buildMalformedReadFilter(false);
+        final SAMRecord nContainingCigarRead = buildSAMRecord(cigarString);
+
+        filter.filterOut(nContainingCigarRead);
+    }
+
+    @Test(enabled = true, dataProvider="UnsupportedCigarOperatorDataProvider")
+    @CigarOperatorTest(CigarOperatorTest.Outcome.ACCEPT)
+    public void testCigarNOperatorFilterControl(final String cigarString) {
+
+        final MalformedReadFilter filter = buildMalformedReadFilter(false);
+        final SAMRecord nonNContainingCigarRead = buildSAMRecord(cigarString);
+
+        Assert.assertFalse(filter.filterOut(nonNContainingCigarRead));
+    }
+
+    protected SAMRecord buildSAMRecord(final String cigarString) {
+        final Cigar nContainingCigar = TextCigarCodec.getSingleton().decode(cigarString);
+        return  this.createRead(nContainingCigar, 1, 0, 10);
+    }
+
+    protected MalformedReadFilter buildMalformedReadFilter(final boolean filterRNO) {
+        return buildMalformedReadFiter(filterRNO,new ValidationExclusion.TYPE[] {});
+    }
+
+    protected MalformedReadFilter buildMalformedReadFiter(boolean filterRNO, final ValidationExclusion.TYPE... excl) {
+        final ValidationExclusion ve = new ValidationExclusion(Arrays.asList(excl));
+
+        final MalformedReadFilter filter = new MalformedReadFilter();
+
+        final SAMFileHeader h = getHeader();
+        final SAMDataSource ds =  getDataSource();
+
+        final GenomeAnalysisEngine gae = new GenomeAnalysisEngine() {
+            @Override
+            public SAMFileHeader getSAMFileHeader() {
+                return h;
+            }
+
+            @Override
+            public SAMDataSource getReadsDataSource() {
+                return ds;
+            }
+        };
+        filter.initialize(gae);
+        filter.filterReadsWithNCigar = filterRNO;
+        return filter;
+    }
+
+    @Retention(RetentionPolicy.RUNTIME)
+    @Target(ElementType.METHOD)
+    @Inherited
+    protected @interface CigarOperatorTest {
+
+        enum Outcome {
+            ANY,ACCEPT,FILTER,EXCEPTION,IGNORE;
+
+            public boolean appliesTo (String cigar) {
+                boolean hasN = cigar.indexOf('N') != -1;
+                switch (this) {
+                    case ANY: return true;
+                    case ACCEPT: return !hasN;
+                    case IGNORE: return hasN;
+                    case FILTER:
+                    case EXCEPTION:
+                    default:
+                        return hasN;
+
+                }
+            }
+        }
+
+        Outcome value() default Outcome.ANY;
+    }
+
+    /**
+     * Cigar test data for unsupported operator test.
+     * Each element of this array corresponds to a test case. In turn the first element of the test case array is the
+     * Cigar string for that test case and the second indicates whether it should be filtered due to the presence of a
+     * unsupported operator
+     */
+    private static final String[] TEST_CIGARS =  {
+       "101M10D20I10M",
+       "6M14N5M",
+       "1N",
+       "101M",
+       "110N",
+       "2N4M",
+       "4M2N",
+       "3M1I1M",
+       "1M2I2M",
+       "1M10N1I1M",
+       "1M1I1D",
+       "11N12M1I34M12N"
+    };
+
+    @DataProvider(name= "UnsupportedCigarOperatorDataProvider")
+    public Iterator<Object[]> unsupportedOperatorDataProvider(final Method testMethod) {
+        final CigarOperatorTest a = resolveCigarOperatorTestAnnotation(testMethod);
+        final List<Object[]> result = new LinkedList<Object[]>();
+        for (final String cigarString : TEST_CIGARS) {
+            if (a == null || a.value().appliesTo(cigarString)) {
+                result.add(new Object[] { cigarString });
+            }
+        }
+        return result.iterator();
+    }
+
+    /**
+     * Gets the most specific {@link CigarOperatorTest} annotation for the
+     * signature of the test method provided.
+     * <p/>
+     * This in-house implementation is required due to the fact that method
+     * annotations do not have inheritance.
+     *
+     * @param m targeted test method.
+     * @return <code>null</code> if there is no {@link CigarOperatorTest}
+     * annotation in this or overridden methods.
+     */
+    private CigarOperatorTest resolveCigarOperatorTestAnnotation(final Method m) {
+       CigarOperatorTest res = m.getAnnotation(CigarOperatorTest.class);
+       if (res != null) {
+           return res;
+       }
+       Class<?> c = this.getClass();
+       Class<?> p = c.getSuperclass();
+       while (p != null && p != Object.class) {
+           try {
+             final Method met = p.getDeclaredMethod(m.getName(),
+                     m.getParameterTypes());
+             res = met.getAnnotation(CigarOperatorTest.class);
+             if (res != null) {
+                 break;
+             }
+           } catch (NoSuchMethodException e) {
+             // Its ok; nothing to do here, just keep looking.
+           }
+           c = p;
+           p = c.getSuperclass();
+       }
+       return res;
+    }
+
+}
diff --git a/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/engine/filters/NDNCigarReadTransformerUnitTest.java b/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/engine/filters/NDNCigarReadTransformerUnitTest.java
new file mode 100644
index 0000000..beb4123
--- /dev/null
+++ b/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/engine/filters/NDNCigarReadTransformerUnitTest.java
@@ -0,0 +1,70 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.engine.filters;
+
+import htsjdk.samtools.Cigar;
+import org.broadinstitute.gatk.utils.sam.CigarUtils;
+import org.testng.Assert;
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.DataProvider;
+import org.testng.annotations.Test;
+
+/**
+ * @author ami
+ * @since 04/22/14
+ */
+public class NDNCigarReadTransformerUnitTest {
+
+
+    @DataProvider(name = "filteringIteratorTestData")
+    public String[][] getFilteringIteratorTestData() {
+        return new String[][] {
+                {"1M1N1N1M","1M1N1N1M"},           // NN elements
+                {"1M1N1D4M","1M1N1D4M"},           // ND
+                {"1M1N3M","1M1N3M"},               // N
+                {"1M1N2I1N3M","1M1N2I1N3M"},       // NIN
+                {"1M1N3D2N1M","1M6N1M"},
+                {"1M2N2D2N1M1D3N1D1N1M2H","1M6N1M1D5N1M2H"},
+                {"1H2S1M1N3D2N1M","1H2S1M6N1M"},
+                {"10M628N2D203N90M","10M833N90M"}
+        };
+    }
+
+    NDNCigarReadTransformer filter;
+
+    @BeforeClass
+    public void init() {
+        filter = new NDNCigarReadTransformer();
+    }
+
+    @Test(dataProvider = "filteringIteratorTestData")
+    public void testCigarRefactoring (final String originalCigarString, final String expectedString) {
+        Cigar originalCigar = CigarUtils.cigarFromString(originalCigarString);
+        String actualString = filter.refactorNDNtoN(originalCigar).toString();
+        Assert.assertEquals(actualString, expectedString, "ciagr string "+ originalCigarString+" should become: "+expectedString+" but got: "+actualString);
+    }
+
+}
diff --git a/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/engine/filters/ReadFilterTest.java b/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/engine/filters/ReadFilterTest.java
new file mode 100644
index 0000000..0f61de2
--- /dev/null
+++ b/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/engine/filters/ReadFilterTest.java
@@ -0,0 +1,370 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.engine.filters;
+
+import htsjdk.samtools.*;
+import org.broadinstitute.gatk.utils.BaseTest;
+import org.broadinstitute.gatk.engine.arguments.ValidationExclusion;
+import org.broadinstitute.gatk.engine.datasources.reads.SAMDataSource;
+import org.broadinstitute.gatk.engine.datasources.reads.SAMReaderID;
+import org.broadinstitute.gatk.engine.downsampling.DownsamplingMethod;
+import org.broadinstitute.gatk.engine.resourcemanagement.ThreadAllocation;
+import org.broadinstitute.gatk.utils.GenomeLocParser;
+import org.broadinstitute.gatk.utils.sam.ArtificialSAMUtils;
+import org.testng.annotations.AfterClass;
+import org.testng.annotations.BeforeClass;
+
+import java.util.*;
+
+/**
+ * Class ReadBaseTest
+ * <p/>
+ * This is the base test class for read filter test classes.  All read
+ * filter test cases should extend from this
+ * class; it sets ups a header mock up to test read filtering.
+ *
+ * Feel free to override non-final method to modify the behavior
+ * (i.e. change how read group id are formatted, or complete a header).
+ *
+ * <p/>
+ * You can statically determine the number of read-group involved
+ * in the test by calling {@link #ReadFilterTest(int)} in you constructor.
+ * <p/>
+ *
+ * Notice that the same header object is shared by all test and
+ * it is initialized by Junit (calling {@link #beforeClass()}.
+ *
+ * @author Valentin Ruano Rubio
+ * @date May 23, 2013
+ */
+public class ReadFilterTest extends BaseTest {
+
+    private static final int DEFAULT_READ_GROUP_COUNT = 5;
+    private static final int DEFAULT_READER_COUNT = 1;
+    private static final String DEFAULT_READ_GROUP_PREFIX = "ReadGroup";
+    private static final String DEFAULT_PLATFORM_UNIT_PREFIX = "Lane";
+    private static final String DEFAULT_SAMPLE_NAME_PREFIX = "Sample";
+    private static final String DEFAULT_PLATFORM_PREFIX = "Platform";
+    private static final int DEFAULT_CHROMOSOME_COUNT = 1;
+    private static final int DEFAULT_CHROMOSOME_START_INDEX = 1;
+    private static final int DEFAULT_CHROMOSOME_SIZE = 1000;
+    private static final String DEFAULT_SAM_FILE_FORMAT = "readfile-%3d.bam";
+
+    private final int groupCount;
+
+    private  SAMFileHeader header;
+
+    private SAMDataSource dataSource;
+
+    /**
+     * Constructs a new read-filter test providing the number of read
+     * groups in the file.
+     *
+     * @param groupCount number of read-group in the fictional SAM file,
+     *                   must be equal or greater than 1.
+     */
+    protected ReadFilterTest(final int groupCount) {
+        if (groupCount < 1) {
+            throw new IllegalArgumentException(
+                    "the read group count must at least be 1");
+        }
+        this.groupCount = groupCount;
+    }
+
+
+    /**
+     * Gets the data source.
+     *
+     * @throws IllegalStateException if the data source was not initialized
+     *          invoking {@link #beforeClass()}
+     * @return never <code>null</code>
+     */
+    protected final SAMDataSource getDataSource() {
+        checkDataSourceExists();
+        return dataSource;
+    }
+
+    /**
+     * Returns the mock-up SAM file header for testing.
+     *
+     * @throws IllegalStateException if the header was not initialized
+     *          invoking {@link #beforeClass()}
+     * @return never <code>null</code>
+     */
+    protected final SAMFileHeader getHeader() {
+        checkHeaderExists();
+        return header;
+    }
+
+    /**
+     * Construct a read filter test with the default number of groups
+     *  ({@link #DEFAULT_READ_GROUP_COUNT}.
+     */
+    public ReadFilterTest() {
+        this(DEFAULT_READ_GROUP_COUNT);
+    }
+
+    /**
+     * Return the number of read groups involved in the test
+     * @return <code>1</code> or greater.
+     */
+    protected final int getReadGroupCount() {
+        return groupCount;
+    }
+
+    /**
+     * Composes the Id for the read group given its index.
+     *
+     * This methods must return a unique distinct ID for each possible index and
+     * it must be the same value each time it is invoked.
+     *
+     * @param index the index of the targeted read group in the range
+     *              [1,{@link #getReadGroupCount()}]
+     * @return never <code>null</code> and must be unique to each possible
+     *         read group index.
+     */
+    protected String composeReadGroupId(final int index) {
+        checkReadGroupIndex(index);
+        return DEFAULT_READ_GROUP_PREFIX + index;
+    }
+
+    /**
+     * Composes the Platform name for the read group given its index.
+     *
+     * This method must always return the same value give an index.
+     *
+     * @param index the index of the targeted read group in the range
+     *              [1,{@link #getReadGroupCount()}]
+     * @return never <code>null</code>.
+     */
+    protected String composePlatformName(final int index) {
+        checkReadGroupIndex(index);
+        return DEFAULT_PLATFORM_PREFIX + (((index-1)%2)+1);
+    }
+
+
+    /**
+     * Composes the Platform unit name for the read group given its index.
+     *
+     * @param index the index of the targeted read group in the range
+     *              [1,{@link #getReadGroupCount()}]
+     * @return never <code>null</code>.
+     */
+    protected String composePlatformUnitName(final int index) {
+        checkReadGroupIndex(index);
+        return DEFAULT_PLATFORM_UNIT_PREFIX + (((index-1)%3)+1);
+    }
+
+
+
+    /**
+     * Checks the correctness of a given read group index.
+     *
+     * A correct index is any value in the range [1,{@link #getReadGroupCount()}].
+     *
+     * @param index the target index.
+     * @throws IllegalArgumentException if the input index is not correct.
+     */
+    protected final void checkReadGroupIndex(final int index) {
+        checkIndex(index,groupCount,"read group");
+    }
+
+
+    private void checkIndex(final int index, final int max, CharSequence name) {
+        if (index < 1 || index > max) {
+            throw new IllegalArgumentException(
+                    name + " index ("
+                    + index
+                    + ") is out of bounds [1," + max + "]");
+        }
+    }
+
+
+    /**
+     * Checks whether the header was initialized.
+     *
+     * @throws IllegalStateException if the header was not yet initialized.
+     */
+    protected final void checkHeaderExists() {
+        if (header == null) {
+            throw new IllegalArgumentException(
+                    "header has not been initialized;"
+                    + " beforeClass() was not invoked");
+        }
+    }
+
+    /**
+     * Checks whether the data source was initialized.
+     *
+     * @throws IllegalStateException if the data source was not yet initialized.
+     */
+    protected final void checkDataSourceExists() {
+        if (header == null) {
+            throw new IllegalArgumentException(
+                    "data source has not been initialized;"
+                            + " beforeClass() was not invoked");
+        }
+    }
+
+    /**
+     * Returns the ID for a read group given its index.
+     *
+     * @param index the index of the targeted read group in the range
+     *              [1,{@link #getReadGroupCount()}]
+     * @return never <code>null</code> and must be unique to each
+     *              possible read group index.
+     */
+    protected final String getReadGroupId(final int index) {
+        checkReadGroupIndex(index);
+        return getHeader().getReadGroups().get(index - 1).getReadGroupId();
+    }
+
+    /**
+     * Returns the platform name for a read group given its index.
+     *
+     * @param group the index of the targeted read group in the range
+     *              [1,{@link #getReadGroupCount()}]
+     * @return never <code>null</code>.
+     */
+    protected final String getPlatformName(final int group) {
+        checkReadGroupIndex(group);
+        return getHeader().getReadGroups().get(group - 1).getPlatform();
+    }
+
+    /**
+     * Returns the platform unit for a read group given its index.
+     *
+     * @param group the index of the targeted read group in the range
+     *              [1,{@link #getReadGroupCount()}]
+     * @return never <code>null</code>.
+     */
+    protected final String getPlatformUnit(final int group) {
+        checkReadGroupIndex(group);
+        return getHeader().getReadGroups().get(group - 1).getPlatformUnit();
+    }
+
+
+    /**
+     * Composes the mock up SAM file header.
+     *
+     * It must return an equivalent (equal) value each time it is invoked.
+     *
+     * @return never <code>null</code>.
+     */
+    protected SAMFileHeader composeHeader() {
+
+        return ArtificialSAMUtils.createArtificialSamHeader(
+                DEFAULT_CHROMOSOME_COUNT, DEFAULT_CHROMOSOME_START_INDEX,
+                DEFAULT_CHROMOSOME_SIZE);
+    }
+
+    @BeforeClass
+    public void beforeClass() {
+
+        header = composeHeader();
+        dataSource = composeDataSource();
+        final List<String> readGroupIDs = new ArrayList<String>();
+        final List<String> sampleNames = new ArrayList<String>();
+
+        for (int i = 1; i <= getReadGroupCount(); i++) {
+            final String readGroupId = composeReadGroupId(i);
+            readGroupIDs.add(readGroupId);
+            sampleNames.add(readGroupId);
+        }
+
+        ArtificialSAMUtils.createEnumeratedReadGroups(
+                header, readGroupIDs, sampleNames);
+
+        for (int i = 1; i <= getReadGroupCount(); i++) {
+            final String readGroupId = readGroupIDs.get(i-1);
+            final SAMReadGroupRecord groupRecord = header.getReadGroup(readGroupId);
+            groupRecord.setAttribute("PL", composePlatformName(i));
+            groupRecord.setAttribute("PU", composePlatformUnitName(i));
+        }
+
+    }
+
+    protected ValidationExclusion composeValidationExclusion() {
+        return new ValidationExclusion();
+    }
+
+    protected SAMDataSource composeDataSource() {
+        checkHeaderExists();
+        final Set<SAMReaderID> readerIDs = new HashSet<>(1);
+        final ThreadAllocation ta = new ThreadAllocation();
+        final Integer numFileHandles = 1; // I believe that any value would do but need to confirm.
+        final boolean useOriginalBaseQualities = true;
+        final ValidationStringency strictness = ValidationStringency.LENIENT;
+        final Integer readBufferSize = 1; // not relevant.
+        final DownsamplingMethod downsamplingMethod = DownsamplingMethod.NONE;
+        final ValidationExclusion exclusionList = composeValidationExclusion();
+        final Collection<ReadFilter> supplementalFilters = Collections.EMPTY_SET;
+        final boolean includeReadsWithDeletionAtLoci = true;
+
+        final GenomeLocParser glp = new GenomeLocParser(header.getSequenceDictionary());
+        final SAMDataSource res = new SAMDataSource(
+                readerIDs,
+                ta,
+                numFileHandles,
+                glp,
+                useOriginalBaseQualities,
+                strictness,
+                readBufferSize,
+                downsamplingMethod,
+                exclusionList,
+                supplementalFilters,
+                includeReadsWithDeletionAtLoci);
+
+        return res;
+    }
+
+    @AfterClass
+    public void afterClass() {
+        header = null;
+        dataSource = null;
+    }
+
+    /**
+     * Creates a read record.
+     *
+     * @param cigar the new record CIGAR.
+     * @param group the new record group index that must be in the range \
+     *              [1,{@link #getReadGroupCount()}]
+     * @param reference the reference sequence index (0-based)
+     * @param start the start position of the read alignment in the reference
+     *              (1-based)
+     * @return never <code>null</code>
+     */
+    protected SAMRecord createRead(final Cigar cigar, final int group, final int reference, final int start) {
+        final SAMRecord record = ArtificialSAMUtils.createArtificialRead(cigar);
+        record.setHeader(getHeader());
+        record.setAlignmentStart(start);
+        record.setReferenceIndex(reference);
+        record.setAttribute(SAMTag.RG.toString(), getReadGroupId(group));
+        return record;
+
+    }
+}
diff --git a/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/engine/filters/ReadGroupBlackListFilterUnitTest.java b/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/engine/filters/ReadGroupBlackListFilterUnitTest.java
new file mode 100644
index 0000000..3a0fc6e
--- /dev/null
+++ b/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/engine/filters/ReadGroupBlackListFilterUnitTest.java
@@ -0,0 +1,247 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.engine.filters;
+
+import org.testng.Assert;
+import org.broadinstitute.gatk.utils.exceptions.ReviewedGATKException;
+import org.broadinstitute.gatk.utils.sam.ArtificialSAMUtils;
+import org.testng.annotations.Test;
+
+import htsjdk.samtools.SAMRecord;
+import htsjdk.samtools.SAMReadGroupRecord;
+
+import java.util.List;
+import java.util.ArrayList;
+import java.util.Collections;
+
+public class ReadGroupBlackListFilterUnitTest extends ReadFilterTest {
+
+    @Test(expectedExceptions=ReviewedGATKException.class)
+    public void testBadFilter() {
+        List<String> badFilters = Collections.singletonList("bad");
+        new ReadGroupBlackListFilter(badFilters);
+    }
+    @Test(expectedExceptions=ReviewedGATKException.class)
+    public void testBadFilterTag() {
+        List<String> badFilters = Collections.singletonList("bad:filter");
+        new ReadGroupBlackListFilter(badFilters);
+    }
+
+    @Test(expectedExceptions=ReviewedGATKException.class)
+    public void testBadFilterFile() {
+        List<String> badFilters = Collections.singletonList("/foo/bar/rgbl.txt");
+        new ReadGroupBlackListFilter(badFilters);
+    }
+
+    @Test
+    public void testFilterReadGroup() {
+        SAMRecord filteredRecord = ArtificialSAMUtils.createArtificialRead(getHeader(), "readUno", 0, 1, 20);
+        filteredRecord.setAttribute("RG", getReadGroupId(1));
+
+        SAMRecord unfilteredRecord = ArtificialSAMUtils.createArtificialRead(getHeader(), "readDos", 0, 2, 20);
+        unfilteredRecord.setAttribute("RG", getReadGroupId(2));
+
+        List<String> filterList = new ArrayList<String>();
+        filterList.add("RG:" + getReadGroupId(1));
+
+        ReadGroupBlackListFilter filter = new ReadGroupBlackListFilter(filterList);
+        Assert.assertTrue(filter.filterOut(filteredRecord));
+        Assert.assertFalse(filter.filterOut(unfilteredRecord));
+    }
+
+    @Test
+    public void testFilterPlatformUnit() {
+        SAMRecord filteredRecord = ArtificialSAMUtils.createArtificialRead(getHeader(), "readUno", 0, 1, 20);
+        filteredRecord.setAttribute("RG", getReadGroupId(1));
+
+        SAMRecord unfilteredRecord = ArtificialSAMUtils.createArtificialRead(getHeader(), "readDos", 0, 2, 20);
+        unfilteredRecord.setAttribute("RG", getReadGroupId(2));
+
+        List<String> filterList = new ArrayList<String>();
+        filterList.add("PU:" + getPlatformUnit(1));
+
+        ReadGroupBlackListFilter filter = new ReadGroupBlackListFilter(filterList);
+        Assert.assertTrue(filter.filterOut(filteredRecord));
+        Assert.assertFalse(filter.filterOut(unfilteredRecord));
+    }
+
+    @Test
+    public void testFilterOutByReadGroup() {
+        int recordsPerGroup = 3;
+        List<SAMRecord> records = new ArrayList<SAMRecord>();
+        int alignmentStart = 0;
+        for (int x = 1; x <= getReadGroupCount(); x++) {
+            SAMReadGroupRecord groupRecord = getHeader().getReadGroup(getReadGroupId(x));
+            for (int y = 1; y <= recordsPerGroup; y++) {
+                SAMRecord record = ArtificialSAMUtils.createArtificialRead(getHeader(), "readUno", 0, ++alignmentStart, 20);
+                record.setAttribute("RG", groupRecord.getReadGroupId());
+                records.add(record);
+            }
+        }
+
+        List<String> filterList = new ArrayList<String>();
+        filterList.add("RG:" + getReadGroupId(1));
+        filterList.add("RG:" + getReadGroupId(3));
+
+        ReadGroupBlackListFilter filter = new ReadGroupBlackListFilter(filterList);
+        int filtered = 0;
+        int unfiltered = 0;
+        for (SAMRecord record : records) {
+            String readGroupName = record.getReadGroup().getReadGroupId();
+            if (filter.filterOut(record)) {
+                if (!filterList.contains("RG:" + readGroupName))
+                    Assert.fail("Read group " + readGroupName + " was filtered");
+                filtered++;
+            } else {
+                if (filterList.contains("RG:" + readGroupName))
+                    Assert.fail("Read group " + readGroupName + " was not filtered");
+                unfiltered++;
+            }
+        }
+
+        int filteredExpected = recordsPerGroup * 2;
+        int unfilteredExpected = recordsPerGroup * (getReadGroupCount() - 2);
+        Assert.assertEquals(filtered, filteredExpected, "Filtered");
+        Assert.assertEquals(unfiltered, unfilteredExpected, "Uniltered");
+    }
+
+    @Test
+    public void testFilterOutByAttribute() {
+        int recordsPerGroup = 3;
+        List<SAMRecord> records = new ArrayList<SAMRecord>();
+        int alignmentStart = 0;
+        for (int x = 1; x <= getReadGroupCount(); x++) {
+            SAMReadGroupRecord groupRecord = getHeader().getReadGroup(getReadGroupId(x));
+            for (int y = 1; y <= recordsPerGroup; y++) {
+                SAMRecord record = ArtificialSAMUtils.createArtificialRead(getHeader(), "readUno", 0, ++alignmentStart, 20);
+                record.setAttribute("RG", groupRecord.getReadGroupId());
+                records.add(record);
+            }
+        }
+
+        List<String> filterList = new ArrayList<String>();
+        filterList.add("PU:" + getPlatformUnit(1));
+
+        ReadGroupBlackListFilter filter = new ReadGroupBlackListFilter(filterList);
+        int filtered = 0;
+        int unfiltered = 0;
+        for (SAMRecord record : records) {
+            String platformUnit = (String) record.getReadGroup().getAttribute("PU");
+            if (filter.filterOut(record)) {
+                if (!filterList.contains("PU:" + platformUnit))
+                    Assert.fail("Platform unit " + platformUnit + " was filtered");
+                filtered++;
+            } else {
+                if (filterList.contains("PU:" + platformUnit))
+                    Assert.fail("Platform unit " + platformUnit + " was not filtered");
+                unfiltered++;
+            }
+        }
+
+        int filteredExpected = 6;
+        int unfilteredExpected = 9;
+        Assert.assertEquals(filtered, filteredExpected, "Filtered");
+        Assert.assertEquals(unfiltered, unfilteredExpected, "Uniltered");
+    }
+
+    @Test
+    public void testFilterOutByFile() {
+        int recordsPerGroup = 3;
+        List<SAMRecord> records = new ArrayList<SAMRecord>();
+        int alignmentStart = 0;
+        for (int x = 1; x <= getReadGroupCount(); x++) {
+            SAMReadGroupRecord groupRecord = getHeader().getReadGroup(getReadGroupId(x));
+            for (int y = 1; y <= recordsPerGroup; y++) {
+                SAMRecord record = ArtificialSAMUtils.createArtificialRead(getHeader(), "readUno", 0, ++alignmentStart, 20);
+                record.setAttribute("RG", groupRecord.getReadGroupId());
+                records.add(record);
+            }
+        }
+
+        List<String> filterList = new ArrayList<String>();
+        filterList.add(privateTestDir + "readgroupblacklisttest.txt");
+
+        ReadGroupBlackListFilter filter = new ReadGroupBlackListFilter(filterList);
+        int filtered = 0;
+        int unfiltered = 0;
+        for (SAMRecord record : records) {
+            String readGroup = record.getReadGroup().getReadGroupId();
+            if (filter.filterOut(record)) {
+                if (!("ReadGroup3".equals(readGroup) || "ReadGroup4".equals(readGroup)))
+                    Assert.fail("Read group " + readGroup + " was filtered");
+                filtered++;
+            } else {
+                if ("ReadGroup3".equals(readGroup) || "ReadGroup4".equals(readGroup))
+                    Assert.fail("Read group " + readGroup + " was not filtered");
+                unfiltered++;
+            }
+        }
+
+        int filteredExpected = recordsPerGroup * 2;
+        int unfilteredExpected = recordsPerGroup * (getReadGroupCount() - 2);
+        Assert.assertEquals(filtered, filteredExpected, "Filtered");
+        Assert.assertEquals(unfiltered, unfilteredExpected, "Uniltered");
+    }
+
+    @Test
+    public void testFilterOutByListFile() {
+        int recordsPerGroup = 3;
+        List<SAMRecord> records = new ArrayList<SAMRecord>();
+        int alignmentStart = 0;
+        for (int x = 1; x <= getReadGroupCount(); x++) {
+            SAMReadGroupRecord groupRecord = getHeader().getReadGroup(getReadGroupId(x));
+            for (int y = 1; y <= recordsPerGroup; y++) {
+                SAMRecord record = ArtificialSAMUtils.createArtificialRead(getHeader(), "readUno", 0, ++alignmentStart, 20);
+                record.setAttribute("RG", groupRecord.getReadGroupId());
+                records.add(record);
+            }
+        }
+
+        List<String> filterList = new ArrayList<String>();
+        filterList.add(privateTestDir + "readgroupblacklisttestlist.txt");
+
+        ReadGroupBlackListFilter filter = new ReadGroupBlackListFilter(filterList);
+        int filtered = 0;
+        int unfiltered = 0;
+        for (SAMRecord record : records) {
+            String readGroup = record.getReadGroup().getReadGroupId();
+            if (filter.filterOut(record)) {
+                if (!("ReadGroup3".equals(readGroup) || "ReadGroup4".equals(readGroup)))
+                    Assert.fail("Read group " + readGroup + " was filtered");
+                filtered++;
+            } else {
+                if ("ReadGroup3".equals(readGroup) || "ReadGroup4".equals(readGroup))
+                    Assert.fail("Read group " + readGroup + " was not filtered");
+                unfiltered++;
+            }
+        }
+
+        int filteredExpected = recordsPerGroup * 2;
+        int unfilteredExpected = recordsPerGroup * (getReadGroupCount() - 2);
+        Assert.assertEquals(filtered, filteredExpected, "Filtered");
+        Assert.assertEquals(unfiltered, unfilteredExpected, "Uniltered");
+    }
+}
diff --git a/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/engine/filters/UnsafeMalformedReadFilterUnitTest.java b/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/engine/filters/UnsafeMalformedReadFilterUnitTest.java
new file mode 100644
index 0000000..a00f0a0
--- /dev/null
+++ b/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/engine/filters/UnsafeMalformedReadFilterUnitTest.java
@@ -0,0 +1,50 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.engine.filters;
+
+
+import org.broadinstitute.gatk.engine.arguments.ValidationExclusion;
+
+import java.util.Collections;
+
+
+/**
+ * Tests for the {@link MalformedReadFilter} when the unsafe flag
+ * {@link ValidationExclusion.TYPE#ALL} is set.
+ *
+ * @author Valentin Ruano-Rubio
+ * @since 6/6/13
+ */
+public class UnsafeMalformedReadFilterUnitTest extends AllowNCigarMalformedReadFilterUnitTest {
+
+
+    @Override
+    protected ValidationExclusion composeValidationExclusion() {
+        return new ValidationExclusion(Collections.singletonList(ValidationExclusion.TYPE.ALL));
+    }
+
+
+}
diff --git a/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/engine/io/OutputTrackerUnitTest.java b/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/engine/io/OutputTrackerUnitTest.java
new file mode 100644
index 0000000..479e19e
--- /dev/null
+++ b/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/engine/io/OutputTrackerUnitTest.java
@@ -0,0 +1,84 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.engine.io;
+
+import org.broadinstitute.gatk.engine.io.stubs.OutputStreamStub;
+import org.broadinstitute.gatk.utils.BaseTest;
+import org.broadinstitute.gatk.utils.exceptions.UserException;
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.DataProvider;
+import org.testng.annotations.Test;
+
+import java.io.File;
+
+public class OutputTrackerUnitTest extends BaseTest {
+
+    private final OutputTracker tracker = new DirectOutputTracker();
+    private File unwriteableDir = null;
+    private File untraversableDir = null;
+
+    @BeforeClass
+    public void createDirectories() {
+        unwriteableDir = new File("unwriteable");
+        unwriteableDir.deleteOnExit();
+        unwriteableDir.mkdir();
+        unwriteableDir.setWritable(false);
+
+        untraversableDir = new File("untraversable");
+        untraversableDir.deleteOnExit();
+        untraversableDir.mkdir();
+        untraversableDir.setExecutable(false);
+    }
+
+    @DataProvider(name = "BadOutputPaths")
+    public Object[][] makeBadOutputPaths() {
+        return new Object[][] {new String[] {"thisDirectoryDoesNotExist/stub.txt"},
+                new String[] {"/thisDirectoryDoesNotExist/dummy.txt"},
+                new String[] {unwriteableDir.getAbsolutePath()+"/dummy.txt"},
+                new String[] {untraversableDir.getAbsolutePath()+"/dummy.txt"}};
+    }
+
+    @DataProvider(name = "GoodOutputPaths")
+    public Object[][] makeGoodOutputPaths() {
+        return new Object[][] {new String[] {publicTestDir+"stub.txt"},
+                new String[] {"dummy.txt"}};
+    }
+
+    @Test(dataProvider = "BadOutputPaths", expectedExceptions = UserException.CouldNotCreateOutputFile.class)
+    public void testInvalidOutputPath(final String path) {
+        tracker.validateOutputPath(new OutputStreamStub(new File(path)));
+    }
+
+    @Test(dataProvider = "GoodOutputPaths")
+    public void testValidOutputPath(final String path) {
+        tracker.validateOutputPath(new OutputStreamStub(new File(path)));
+    }
+
+    @Test
+    public void testOutputPathWithNullFile() {
+        tracker.validateOutputPath(new OutputStreamStub(System.out));
+    }
+}
diff --git a/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/engine/iterators/BoundedReadIteratorUnitTest.java b/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/engine/iterators/BoundedReadIteratorUnitTest.java
new file mode 100644
index 0000000..7c3aca2
--- /dev/null
+++ b/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/engine/iterators/BoundedReadIteratorUnitTest.java
@@ -0,0 +1,145 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.engine.iterators;
+
+import static org.testng.Assert.fail;
+
+import htsjdk.samtools.SAMFileHeader;
+import htsjdk.samtools.SAMRecord;
+import htsjdk.samtools.reference.ReferenceSequenceFile;
+import htsjdk.samtools.reference.IndexedFastaSequenceFile;
+import org.broadinstitute.gatk.utils.BaseTest;
+import org.testng.Assert;
+import org.broadinstitute.gatk.utils.GenomeLocParser;
+
+import org.broadinstitute.gatk.utils.sam.ArtificialSAMUtils;
+
+import org.testng.annotations.BeforeMethod;
+
+import org.testng.annotations.Test;
+
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+
+
+
+/*
+ * 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.
+ */
+
+/**
+ * @author aaron
+ * @version 1.0
+ * @date Apr 14, 2009
+ * <p/>
+ * Class BoundedReadIteratorUnitTest
+ * <p/>
+ * tests for the bounded read iterator.
+ */
+public class BoundedReadIteratorUnitTest extends BaseTest {
+
+    /** the file list and the fasta sequence */
+    private List<File> fl;
+    private ReferenceSequenceFile seq;
+
+    /**
+     * This function does the setup of our parser, before each method call.
+     * <p/>
+     * Called before every test case method.
+     */
+    @BeforeMethod
+    public void doForEachTest() throws FileNotFoundException {
+        fl = new ArrayList<File>();
+    }
+
+
+    /** Test out that we can shard the file and iterate over every read */
+    @Test
+    public void testBounding() {
+        logger.warn("Executing testBounding");
+        // total reads expected
+        final int expected = 20;
+        // bound by ten reads
+        BoundedReadIterator iter = new BoundedReadIterator(new testIterator(), expected);
+
+        int count = 0;
+        for (SAMRecord rec: iter) {
+            count++;
+        }
+
+        Assert.assertEquals(count, expected);
+    }
+}
+
+class testIterator implements GATKSAMIterator {
+    SAMFileHeader header;
+    testIterator() {
+        header = ArtificialSAMUtils.createArtificialSamHeader(1,1,2000);
+    }
+
+    public void close() {
+
+    }
+
+    public boolean hasNext() {
+        return true;
+    }
+
+    public SAMRecord next() {
+        return ArtificialSAMUtils.createArtificialRead(header,"blah",0,1,100);
+    }
+
+    public void remove() {
+    }
+
+    public Iterator<SAMRecord> iterator() {
+        return this;
+    }
+}
diff --git a/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/engine/iterators/GATKSAMIteratorAdapterUnitTest.java b/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/engine/iterators/GATKSAMIteratorAdapterUnitTest.java
new file mode 100644
index 0000000..6cbd4fd
--- /dev/null
+++ b/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/engine/iterators/GATKSAMIteratorAdapterUnitTest.java
@@ -0,0 +1,176 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.engine.iterators;
+
+import htsjdk.samtools.SAMRecord;
+import htsjdk.samtools.util.CloseableIterator;
+import org.broadinstitute.gatk.utils.BaseTest;
+import static org.testng.Assert.assertEquals;
+import org.testng.annotations.Test;
+
+import java.util.Iterator;
+
+/**
+ *
+ * User: aaron
+ * Date: May 13, 2009
+ * Time: 6:58:21 PM
+ *
+ * The Broad Institute
+ * SOFTWARE COPYRIGHT NOTICE AGREEMENT 
+ * This software and its documentation are copyright 2009 by the
+ * Broad Institute/Massachusetts Institute of Technology. All rights are reserved.
+ *
+ * This software is supplied without any warranty or guaranteed support whatsoever. Neither
+ * the Broad Institute nor MIT can be responsible for its use, misuse, or functionality.
+ *
+ */
+
+
+/**
+ * @author aaron
+ * @version 1.0
+ * @date May 13, 2009
+ * <p/>
+ * Class GATKSAMIteratorTest
+ * <p/>
+ * Tests the GATKSAMIteratorAdapter class.
+ */
+public class GATKSAMIteratorAdapterUnitTest extends BaseTest {
+
+    class MyTestIterator implements Iterator<SAMRecord> {
+
+        public int count = 0;
+
+        public MyTestIterator() {
+            count = 0;
+        }
+
+        public boolean hasNext() {
+            if (count < 100) {
+                ++count;
+                return true;
+            } else {
+                return false;
+            }
+        }
+
+        public SAMRecord next() {
+            return null;
+        }
+
+        public void remove() {
+            throw new UnsupportedOperationException("Unsupported");
+        }
+    }
+
+    class MyTestCloseableIterator implements CloseableIterator<SAMRecord> {
+        public int count = 0;
+
+        public MyTestCloseableIterator() {
+            count = 0;
+        }
+
+        public boolean hasNext() {
+            if (count < 100) {
+                ++count;
+                return true;
+            } else {
+                return false;
+            }
+        }
+
+        public SAMRecord next() {
+            return null;
+        }
+
+        public void remove() {
+            throw new UnsupportedOperationException("Unsupported");
+        }
+
+        public void close() {
+            count = -1;
+        }
+    }
+
+
+    @Test
+    public void testNormalIterator() {
+        final int COUNT = 100;
+        MyTestIterator it = new MyTestIterator();
+
+        GATKSAMIterator samIt = GATKSAMIteratorAdapter.adapt(it);
+        int countCheck = 0;
+        while (samIt.hasNext()) {
+            samIt.next();
+            ++countCheck;
+            //logger.warn("cnt = " + countCheck);
+        }
+
+        assertEquals(countCheck, COUNT);
+
+        assertEquals(countCheck, COUNT);
+    }
+
+    @Test
+    public void testCloseableIterator() {
+        final int COUNT = 100;
+
+        MyTestCloseableIterator it = new MyTestCloseableIterator();
+
+        GATKSAMIterator samIt = GATKSAMIteratorAdapter.adapt(it);
+
+        int countCheck = 0;
+        while (samIt.hasNext()) {
+            samIt.next();
+            ++countCheck;
+        }
+
+        assertEquals(countCheck, COUNT);
+    }
+
+    @Test
+    public void testCloseOnCloseableIterator() {
+        final int COUNT = 100;
+
+        MyTestCloseableIterator it = new MyTestCloseableIterator();
+        
+        GATKSAMIterator samIt = GATKSAMIteratorAdapter.adapt(it);
+
+
+        int countCheck = 0;
+        while (samIt.hasNext()) {
+            samIt.next();
+            ++countCheck;
+        }
+
+        assertEquals(countCheck, COUNT);
+
+        // check to see that the count get's set to -1
+        samIt.close();
+        assertEquals(it.count, -1);
+    }
+}
diff --git a/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/engine/iterators/ReadFormattingIteratorUnitTest.java b/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/engine/iterators/ReadFormattingIteratorUnitTest.java
new file mode 100644
index 0000000..c926d06
--- /dev/null
+++ b/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/engine/iterators/ReadFormattingIteratorUnitTest.java
@@ -0,0 +1,50 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.engine.iterators;
+
+import htsjdk.samtools.*;
+import org.broadinstitute.gatk.utils.BaseTest;
+import org.broadinstitute.gatk.utils.sam.ArtificialSAMUtils;
+import org.testng.Assert;
+import org.testng.annotations.Test;
+
+import java.util.Arrays;
+
+
+public class ReadFormattingIteratorUnitTest extends BaseTest {
+
+    @Test
+    public void testIteratorConsolidatesCigars() {
+        final Cigar unconsolidatedCigar = TextCigarCodec.getSingleton().decode("3M0M5M0M");
+        final SAMRecord unconsolidatedRead = ArtificialSAMUtils.createArtificialRead(unconsolidatedCigar);
+
+        final GATKSAMIterator readIterator = GATKSAMIteratorAdapter.adapt(Arrays.asList(unconsolidatedRead).iterator());
+        final ReadFormattingIterator formattingIterator = new ReadFormattingIterator(readIterator, false, (byte)-1);
+        final SAMRecord postIterationRead = formattingIterator.next();
+
+        Assert.assertEquals(postIterationRead.getCigarString(), "8M", "Cigar 3M0M5M0M not consolidated correctly by ReadFormattingIterator");
+    }
+}
diff --git a/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/engine/iterators/VerifyingSamIteratorUnitTest.java b/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/engine/iterators/VerifyingSamIteratorUnitTest.java
new file mode 100644
index 0000000..371f94f
--- /dev/null
+++ b/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/engine/iterators/VerifyingSamIteratorUnitTest.java
@@ -0,0 +1,128 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.engine.iterators;
+
+import htsjdk.samtools.SAMFileHeader;
+import htsjdk.samtools.SAMRecord;
+import htsjdk.samtools.SAMSequenceDictionary;
+import htsjdk.samtools.SAMSequenceRecord;
+import org.broadinstitute.gatk.utils.exceptions.UserException;
+import org.broadinstitute.gatk.utils.sam.ArtificialSAMUtils;
+import org.testng.Assert;
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.Test;
+
+import java.util.Arrays;
+import java.util.List;
+
+/**
+ * Created by IntelliJ IDEA.
+ * User: mhanna
+ * Date: Mar 2, 2011
+ * Time: 9:48:10 PM
+ * To change this template use File | Settings | File Templates.
+ */
+public class VerifyingSamIteratorUnitTest {
+    private SAMFileHeader samFileHeader;
+
+    @BeforeClass
+    public void init() {
+        SAMSequenceDictionary sequenceDictionary = new SAMSequenceDictionary();
+        sequenceDictionary.addSequence(new SAMSequenceRecord("1",500));
+        sequenceDictionary.addSequence(new SAMSequenceRecord("2",500));
+
+        samFileHeader = new SAMFileHeader();
+        samFileHeader.setSequenceDictionary(sequenceDictionary);
+    }
+
+    @Test
+    public void testSortedReadsBasic() {
+        SAMRecord read1 = ArtificialSAMUtils.createArtificialRead(samFileHeader,"read1",getContig(0).getSequenceIndex(),1,10);
+        SAMRecord read2 = ArtificialSAMUtils.createArtificialRead(samFileHeader,"read2",getContig(0).getSequenceIndex(),2,10);
+        List<SAMRecord> reads = Arrays.asList(read1,read2);
+
+        VerifyingSamIterator iterator = new VerifyingSamIterator(GATKSAMIteratorAdapter.adapt(reads.iterator()));
+
+        Assert.assertTrue(iterator.hasNext(),"Insufficient reads");
+        Assert.assertSame(iterator.next(),read1,"Incorrect read in read 1 position");
+        Assert.assertTrue(iterator.hasNext(),"Insufficient reads");
+        Assert.assertSame(iterator.next(),read2,"Incorrect read in read 2 position");
+        Assert.assertFalse(iterator.hasNext(),"Too many reads in iterator");
+    }
+
+    @Test
+    public void testSortedReadsAcrossContigs() {
+        SAMRecord read1 = ArtificialSAMUtils.createArtificialRead(samFileHeader,"read1",getContig(0).getSequenceIndex(),2,10);
+        SAMRecord read2 = ArtificialSAMUtils.createArtificialRead(samFileHeader,"read2",getContig(1).getSequenceIndex(),1,10);
+        List<SAMRecord> reads = Arrays.asList(read1,read2);
+
+        VerifyingSamIterator iterator = new VerifyingSamIterator(GATKSAMIteratorAdapter.adapt(reads.iterator()));
+
+        Assert.assertTrue(iterator.hasNext(),"Insufficient reads");
+        Assert.assertSame(iterator.next(),read1,"Incorrect read in read 1 position");
+        Assert.assertTrue(iterator.hasNext(),"Insufficient reads");
+        Assert.assertSame(iterator.next(),read2,"Incorrect read in read 2 position");
+        Assert.assertFalse(iterator.hasNext(),"Too many reads in iterator");
+    }
+
+    @Test(expectedExceptions=UserException.MissortedBAM.class)
+    public void testImproperlySortedReads() {
+        SAMRecord read1 = ArtificialSAMUtils.createArtificialRead(samFileHeader,"read1",getContig(0).getSequenceIndex(),2,10);
+        SAMRecord read2 = ArtificialSAMUtils.createArtificialRead(samFileHeader,"read2",getContig(0).getSequenceIndex(),1,10);
+        List<SAMRecord> reads = Arrays.asList(read1,read2);
+
+        VerifyingSamIterator iterator = new VerifyingSamIterator(GATKSAMIteratorAdapter.adapt(reads.iterator()));
+
+        Assert.assertTrue(iterator.hasNext(),"Insufficient reads");
+        Assert.assertSame(iterator.next(),read1,"Incorrect read in read 1 position");
+        Assert.assertTrue(iterator.hasNext(),"Insufficient reads");
+
+        // Should trigger MissortedBAM exception.
+        iterator.next();
+    }
+
+    @Test(expectedExceptions=UserException.MalformedBAM.class)
+    public void testInvalidAlignment() {
+        // Create an invalid alignment state.
+        SAMRecord read1 = ArtificialSAMUtils.createArtificialRead(samFileHeader,"read1",getContig(0).getSequenceIndex(),1,10);
+        SAMRecord read2 = ArtificialSAMUtils.createArtificialRead(samFileHeader,"read1",getContig(0).getSequenceIndex(),2,10);
+        read1.setReferenceIndex(SAMRecord.NO_ALIGNMENT_REFERENCE_INDEX);
+        List<SAMRecord> reads = Arrays.asList(read1,read2);
+
+        VerifyingSamIterator iterator = new VerifyingSamIterator(GATKSAMIteratorAdapter.adapt(reads.iterator()));
+
+        Assert.assertTrue(iterator.hasNext(),"Insufficient reads");
+        Assert.assertSame(iterator.next(),read1,"Incorrect read in read 1 position");
+        Assert.assertTrue(iterator.hasNext(),"Insufficient reads");
+
+        // Should trigger MalformedBAM exception.
+        iterator.next();
+    }
+
+    private SAMSequenceRecord getContig(final int contigIndex) {
+        return samFileHeader.getSequence(contigIndex);            
+    }
+}
diff --git a/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/engine/phonehome/GATKRunReportUnitTest.java b/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/engine/phonehome/GATKRunReportUnitTest.java
new file mode 100644
index 0000000..d7b9b3d
--- /dev/null
+++ b/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/engine/phonehome/GATKRunReportUnitTest.java
@@ -0,0 +1,310 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.engine.phonehome;
+
+import org.broadinstitute.gatk.utils.BaseTest;
+import org.broadinstitute.gatk.engine.GenomeAnalysisEngine;
+import org.broadinstitute.gatk.engine.arguments.GATKArgumentCollection;
+import org.broadinstitute.gatk.engine.contexts.AlignmentContext;
+import org.broadinstitute.gatk.engine.contexts.ReferenceContext;
+import org.broadinstitute.gatk.engine.refdata.RefMetaDataTracker;
+import org.broadinstitute.gatk.engine.walkers.ActiveRegionWalker;
+import org.broadinstitute.gatk.engine.walkers.Walker;
+import org.broadinstitute.gatk.tools.walkers.qc.CountLoci;
+import org.broadinstitute.gatk.tools.walkers.qc.CountRODs;
+import org.broadinstitute.gatk.tools.walkers.qc.CountReads;
+import org.broadinstitute.gatk.utils.Utils;
+import org.broadinstitute.gatk.utils.activeregion.ActiveRegion;
+import org.broadinstitute.gatk.utils.activeregion.ActivityProfileState;
+import org.broadinstitute.gatk.utils.exceptions.ReviewedGATKException;
+import org.broadinstitute.gatk.utils.exceptions.UserException;
+import org.jets3t.service.S3Service;
+import org.jets3t.service.S3ServiceException;
+import org.jets3t.service.ServiceException;
+import org.jets3t.service.model.S3Object;
+import org.testng.Assert;
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.DataProvider;
+import org.testng.annotations.Test;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.FileInputStream;
+import java.io.InputStream;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import java.util.Properties;
+
+public class GATKRunReportUnitTest extends BaseTest {
+    private final static boolean DEBUG = false;
+    private static final long S3_PUT_TIMEOUT_IN_MILLISECONDS_FOR_TESTING = 30 * 1000;
+    private static final String AWS_DOWNLOADER_CREDENTIALS_PROPERTIES_FILE = privateTestDir + "phonehome/awsDownloaderCredentials.properties";
+
+    private Walker walker;
+    private Exception exception;
+    private GenomeAnalysisEngine engine;
+    private String downloaderAccessKey;
+    private String downloaderSecretKey;
+
+    @BeforeClass
+    public void setup() throws Exception {
+        walker = new CountReads();
+        exception = new IllegalArgumentException("javaException");
+        engine = new GenomeAnalysisEngine();
+        engine.setArguments(new GATKArgumentCollection());
+
+        Properties awsProperties = new Properties();
+        awsProperties.load(new FileInputStream(AWS_DOWNLOADER_CREDENTIALS_PROPERTIES_FILE));
+        downloaderAccessKey = awsProperties.getProperty("accessKey");
+        downloaderSecretKey = awsProperties.getProperty("secretKey");
+    }
+
+    @Test(enabled = ! DEBUG)
+    public void testAWSKeysAreValid() {
+        // throws an exception if they aren't
+        GATKRunReport.checkAWSAreValid();
+    }
+
+    @Test(enabled = ! DEBUG)
+    public void testAccessKey() throws Exception {
+        testAWSKey(GATKRunReport.getAWSUploadAccessKey(), GATKRunReport.AWS_ACCESS_KEY_MD5);
+    }
+
+    @Test(enabled = ! DEBUG)
+    public void testSecretKey() throws Exception {
+        testAWSKey(GATKRunReport.getAWSUploadSecretKey(), GATKRunReport.AWS_SECRET_KEY_MD5);
+    }
+
+    private void testAWSKey(final String accessKey, final String expectedMD5) throws Exception {
+        Assert.assertNotNull(accessKey, "AccessKey should not be null");
+        final String actualmd5 = Utils.calcMD5(accessKey);
+        Assert.assertEquals(actualmd5, expectedMD5);
+    }
+
+    @DataProvider(name = "GATKReportCreationTest")
+    public Object[][] makeGATKReportCreationTest() {
+        List<Object[]> tests = new ArrayList<Object[]>();
+
+        final Walker readWalker = new CountReads();
+        final Walker lociWalker = new CountLoci();
+        final Walker rodWalker = new CountRODs();
+        final Walker artWalker = new RunReportDummyActiveRegionWalker();
+
+        final Exception noException = null;
+        final Exception javaException = new IllegalArgumentException("javaException");
+        final Exception stingException = new ReviewedGATKException("GATKException");
+        final Exception userException = new UserException("userException");
+
+        final GenomeAnalysisEngine engine = new GenomeAnalysisEngine();
+        engine.setArguments(new GATKArgumentCollection());
+
+        for ( final Walker walker : Arrays.asList(readWalker, lociWalker, rodWalker, artWalker) ) {
+            for ( final Exception exception : Arrays.asList(noException,  javaException, stingException, userException) ) {
+                tests.add(new Object[]{walker, exception, engine});
+            }
+        }
+
+        return tests.toArray(new Object[][]{});
+    }
+
+    @Test(enabled = !DEBUG, dataProvider = "GATKReportCreationTest")
+    public void testGATKReportCreationReadingAndWriting(final Walker walker, final Exception exception, final GenomeAnalysisEngine engine) throws Exception {
+        final GATKRunReport report = new GATKRunReport(walker, exception, engine, GATKRunReport.PhoneHomeOption.STDOUT);
+        final ByteArrayOutputStream captureStream = new ByteArrayOutputStream();
+        final boolean succeeded = report.postReportToStream(captureStream);
+        Assert.assertTrue(succeeded, "Failed to write report to stream");
+        Assert.assertFalse(report.exceptionOccurredDuringPost(), "Post succeeded but report says it failed");
+        Assert.assertNull(report.getErrorMessage(), "Post succeeded but there was an error message");
+        Assert.assertNull(report.getErrorThrown(), "Post succeeded but there was an error message");
+        final InputStream readStream = new ByteArrayInputStream(captureStream.toByteArray());
+
+        GATKRunReport deserialized = null;
+        try {
+            deserialized = GATKRunReport.deserializeReport(readStream);
+        } catch ( Exception e ) {
+            final String reportString = new String(captureStream.toByteArray());
+            Assert.fail("Failed to deserialize GATK report " + reportString + " with exception " + e);
+        }
+
+        if ( deserialized != null )
+            Assert.assertEquals(report, deserialized);
+    }
+
+    @DataProvider(name = "GATKAWSReportMode")
+    public Object[][] makeGATKAWSReportMode() {
+        List<Object[]> tests = new ArrayList<Object[]>();
+
+        for ( final GATKRunReport.AWSMode mode : GATKRunReport.AWSMode.values() ) {
+            tests.add(new Object[]{mode});
+        }
+
+        return tests.toArray(new Object[][]{});
+    }
+
+    // Will fail with timeout if AWS time out isn't working
+    // Will fail with exception if AWS doesn't protect itself from errors
+    @Test(enabled = ! DEBUG, dataProvider = "GATKAWSReportMode", timeOut = S3_PUT_TIMEOUT_IN_MILLISECONDS_FOR_TESTING * 2)
+    public void testAWS(final GATKRunReport.AWSMode awsMode) {
+        logger.warn("Starting testAWS mode=" + awsMode);
+
+        // Use a shorter timeout than usual when we're testing GATKRunReport.AWSMode.TIMEOUT
+        final long thisTestS3Timeout = awsMode == GATKRunReport.AWSMode.TIMEOUT ? 30 * 1000 : S3_PUT_TIMEOUT_IN_MILLISECONDS_FOR_TESTING;
+        final GATKRunReport report = new GATKRunReport(walker, exception, engine, GATKRunReport.PhoneHomeOption.AWS, thisTestS3Timeout);
+        report.sendAWSToTestBucket();
+        report.setAwsMode(awsMode);
+        final S3Object s3Object = report.postReportToAWSS3();
+
+        if ( awsMode == GATKRunReport.AWSMode.NORMAL ) {
+            Assert.assertNotNull(s3Object, "Upload to AWS failed, s3Object was null. error was " + report.formatError());
+            Assert.assertFalse(report.exceptionOccurredDuringPost(), "The upload should have succeeded but the report says it didn't.  Error was " + report.formatError());
+            Assert.assertNull(report.getErrorMessage(), "Report succeeded but an error message was found");
+            Assert.assertNull(report.getErrorThrown(), "Report succeeded but an thrown error was found");
+            try {
+                final GATKRunReport deserialized = GATKRunReport.deserializeReport(downloaderAccessKey, downloaderSecretKey, report.getS3ReportBucket(), s3Object);
+                Assert.assertEquals(report, deserialized);
+                deleteFromS3(report);
+            } catch ( Exception e ) {
+                Assert.fail("Failed to read, deserialize, or delete GATK report " + s3Object.getName() + " with exception " + e);
+            }
+        } else {
+            Assert.assertNull(s3Object, "AWS upload should have failed for mode " + awsMode + " but got non-null s3 object back " + s3Object + " error was " + report.formatError());
+            Assert.assertTrue(report.exceptionOccurredDuringPost(), "S3 object was null but the report says that the upload succeeded");
+            Assert.assertNotNull(report.getErrorMessage(), "Report succeeded but an error message wasn't found");
+            if ( awsMode == GATKRunReport.AWSMode.FAIL_WITH_EXCEPTION )
+                Assert.assertNotNull(report.getErrorThrown());
+        }
+    }
+
+    private void deleteFromS3(final GATKRunReport report) throws Exception {
+        final S3Service s3Service = GATKRunReport.initializeAWSService(downloaderAccessKey, downloaderSecretKey);
+        // Retrieve the whole data object we created previously
+        s3Service.deleteObject(report.getS3ReportBucket(), report.getReportFileName());
+    }
+
+    @DataProvider(name = "PostReportByType")
+    public Object[][] makePostReportByType() {
+        List<Object[]> tests = new ArrayList<Object[]>();
+
+        for ( final GATKRunReport.PhoneHomeOption et : GATKRunReport.PhoneHomeOption.values() ) {
+            tests.add(new Object[]{et});
+        }
+
+        return tests.toArray(new Object[][]{});
+    }
+
+    @Test(enabled = ! DEBUG, dataProvider = "PostReportByType", timeOut = S3_PUT_TIMEOUT_IN_MILLISECONDS_FOR_TESTING * 2)
+    public void testPostReportByType(final GATKRunReport.PhoneHomeOption type) {
+        final GATKRunReport report = new GATKRunReport(walker, exception, engine, GATKRunReport.PhoneHomeOption.AWS, S3_PUT_TIMEOUT_IN_MILLISECONDS_FOR_TESTING);
+        Assert.assertFalse(report.exceptionOccurredDuringPost(), "An exception occurred during posting the report");
+        final boolean succeeded = report.postReport(type);
+
+        if ( type == GATKRunReport.PhoneHomeOption.NO_ET )
+            Assert.assertFalse(succeeded, "NO_ET option shouldn't write a report");
+        else {
+            Assert.assertTrue(succeeded, "Any non NO_ET option should succeed in writing a report");
+
+            if ( type == GATKRunReport.PhoneHomeOption.STDOUT ) {
+                // nothing to do
+            } else {
+                // must have gone to AWS
+                try {
+                    Assert.assertTrue(report.wentToAWS(), "The report should have gone to AWS but the report says it wasn't");
+                    deleteFromS3(report);
+                } catch ( Exception e ) {
+                    Assert.fail("Failed delete GATK report " + report.getReportFileName() + " with exception " + e);
+                }
+            }
+        }
+    }
+
+    public interface S3Op {
+        public void apply() throws ServiceException;
+    }
+
+    // Will fail with timeout if AWS time out isn't working
+    // Will fail with exception if AWS doesn't protect itself from errors
+    @Test(timeOut = S3_PUT_TIMEOUT_IN_MILLISECONDS_FOR_TESTING * 2)
+    public void testAWSPublicKeyHasAccessControls() throws Exception {
+        final GATKRunReport report = new GATKRunReport(walker, exception, engine, GATKRunReport.PhoneHomeOption.AWS, S3_PUT_TIMEOUT_IN_MILLISECONDS_FOR_TESTING);
+        report.sendAWSToTestBucket();
+        final S3Object s3Object = report.postReportToAWSS3();
+        Assert.assertNotNull(s3Object, "Upload to AWS failed, s3Object was null. error was " + report.formatError());
+
+        // create a service with the public key, and make sure it cannot list or delete
+        final S3Service s3Service = GATKRunReport.initializeAWSService(GATKRunReport.getAWSUploadAccessKey(), GATKRunReport.getAWSUploadSecretKey());
+        assertOperationNotAllowed("listAllBuckets", new S3Op() {
+            @Override
+            public void apply() throws S3ServiceException {
+                s3Service.listAllBuckets();
+            }
+        });
+        assertOperationNotAllowed("listBucket", new S3Op() {
+            @Override
+            public void apply() throws S3ServiceException { s3Service.listObjects(report.getS3ReportBucket()); }
+        });
+        assertOperationNotAllowed("createBucket", new S3Op() {
+            @Override
+            public void apply() throws S3ServiceException { s3Service.createBucket("ShouldNotCreate"); }
+        });
+        assertOperationNotAllowed("deleteObject", new S3Op() {
+            @Override
+            public void apply() throws ServiceException { s3Service.deleteObject(report.getS3ReportBucket(), report.getReportFileName()); }
+        });
+    }
+
+    private void assertOperationNotAllowed(final String name, final S3Op op) {
+        try {
+            op.apply();
+            // only gets here if the operation was successful
+            Assert.fail("Operation " + name + " ran successfully but we expected to it fail");
+        } catch ( ServiceException e ) {
+            Assert.assertEquals(e.getErrorCode(), "AccessDenied");
+        }
+    }
+
+    class RunReportDummyActiveRegionWalker extends ActiveRegionWalker<Integer, Integer> {
+        @Override
+        public ActivityProfileState isActive(RefMetaDataTracker tracker, ReferenceContext ref, AlignmentContext context) {
+            return new ActivityProfileState(ref.getLocus(), 0.0);
+        }
+
+        @Override
+        public Integer map(ActiveRegion activeRegion, RefMetaDataTracker metaDataTracker) {
+            return 0;
+        }
+
+        @Override
+        public Integer reduceInit() {
+            return 0;
+        }
+
+        @Override
+        public Integer reduce(Integer value, Integer sum) {
+            return 0;
+        }
+    }
+}
diff --git a/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/engine/refdata/RefMetaDataTrackerUnitTest.java b/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/engine/refdata/RefMetaDataTrackerUnitTest.java
new file mode 100644
index 0000000..f25ab8d
--- /dev/null
+++ b/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/engine/refdata/RefMetaDataTrackerUnitTest.java
@@ -0,0 +1,290 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.engine.refdata;
+
+import htsjdk.samtools.SAMFileHeader;
+import org.apache.log4j.Logger;
+import htsjdk.tribble.Feature;
+import org.broadinstitute.gatk.utils.BaseTest;
+import org.broadinstitute.gatk.utils.commandline.RodBinding;
+import org.broadinstitute.gatk.utils.commandline.Tags;
+import org.broadinstitute.gatk.engine.contexts.ReferenceContext;
+import org.broadinstitute.gatk.utils.codecs.table.TableFeature;
+import org.broadinstitute.gatk.engine.refdata.utils.GATKFeature;
+import org.broadinstitute.gatk.engine.refdata.utils.RODRecordList;
+import org.broadinstitute.gatk.utils.GenomeLoc;
+import org.broadinstitute.gatk.utils.GenomeLocParser;
+import org.broadinstitute.gatk.utils.sam.ArtificialSAMUtils;
+import htsjdk.variant.variantcontext.Allele;
+import htsjdk.variant.variantcontext.VariantContext;
+import htsjdk.variant.variantcontext.VariantContextBuilder;
+import org.testng.Assert;
+import org.testng.annotations.*;
+import java.util.*;
+import java.util.List;
+
+public class RefMetaDataTrackerUnitTest {
+    final protected static Logger logger = Logger.getLogger(RefMetaDataTrackerUnitTest.class);
+    private static SAMFileHeader header;
+    private ReferenceContext context;
+    private GenomeLocParser genomeLocParser;
+    private GenomeLoc locus;
+    private final static int START_POS = 10;
+    Allele A,C,G,T;
+    VariantContext AC_SNP, AG_SNP, AT_SNP;
+    TableFeature span10_10, span1_20, span10_20;
+
+    @BeforeClass
+    public void beforeClass() {
+        header = ArtificialSAMUtils.createArtificialSamHeader(1, 1, 100);
+        genomeLocParser = new GenomeLocParser(header.getSequenceDictionary());
+        locus = genomeLocParser.createGenomeLoc("chr1", START_POS, START_POS);
+        context = new ReferenceContext(genomeLocParser, locus, (byte)'A');
+        A = Allele.create("A", true);
+        C = Allele.create("C");
+        G = Allele.create("G");
+        T = Allele.create("T");
+        AC_SNP = new VariantContextBuilder("x", "chr1", START_POS, START_POS, Arrays.asList(A, C)).make();
+        AG_SNP = new VariantContextBuilder("x", "chr1", START_POS, START_POS, Arrays.asList(A, G)).make();
+        AT_SNP = new VariantContextBuilder("x", "chr1", START_POS, START_POS, Arrays.asList(A, T)).make();
+        span10_10 = makeSpan(10, 10);
+        span1_20 = makeSpan(1, 20);
+        span10_20 = makeSpan(10, 20);
+    }
+
+    @BeforeMethod
+    public void reset() {
+        RodBinding.resetNameCounter();
+    }
+
+    private class MyTest extends BaseTest.TestDataProvider {
+        public RODRecordList AValues, BValues;
+
+        private MyTest(Class c, final List<? extends Feature> AValues, final List<? extends Feature> BValues) {
+            super(c);
+            this.AValues = AValues == null ? null : makeRODRecord("A", AValues);
+            this.BValues = BValues == null ? null : makeRODRecord("B", BValues);
+        }
+
+        private MyTest(final List<? extends Feature> AValues, final List<? extends Feature> BValues) {
+            super(MyTest.class);
+            this.AValues = AValues == null ? null : makeRODRecord("A", AValues);
+            this.BValues = BValues == null ? null : makeRODRecord("B", BValues);
+        }
+
+        @Override
+        public String toString() {
+            return String.format("A=%s, B=%s", AValues, BValues);
+        }
+
+        private final RODRecordList makeRODRecord(String name, List<? extends Feature> features) {
+            List<GATKFeature> x = new ArrayList<GATKFeature>();
+            for ( Feature f : features )
+                x.add(new GATKFeature.TribbleGATKFeature(genomeLocParser, f, name));
+            return new RODRecordListImpl(name, x, locus);
+        }
+
+        public List<GATKFeature> expected(String name) {
+            if ( name.equals("A+B") ) return allValues();
+            if ( name.equals("A") ) return expectedAValues();
+            if ( name.equals("B") ) return expectedBValues();
+            throw new RuntimeException("FAIL");
+        }
+
+        public List<GATKFeature> allValues() {
+            List<GATKFeature> x = new ArrayList<GATKFeature>();
+            x.addAll(expectedAValues());
+            x.addAll(expectedBValues());
+            return x;
+        }
+
+        public List<GATKFeature> expectedAValues() {
+            return AValues == null ? Collections.<GATKFeature>emptyList() : AValues;
+        }
+
+        public List<GATKFeature> expectedBValues() {
+            return BValues == null ? Collections.<GATKFeature>emptyList() : BValues;
+        }
+
+        public RefMetaDataTracker makeTracker() {
+            List<RODRecordList> x = new ArrayList<RODRecordList>();
+            if ( AValues != null ) x.add(AValues);
+            if ( BValues != null ) x.add(BValues);
+            return new RefMetaDataTracker(x);
+        }
+
+        public int nBoundTracks() {
+            int n = 0;
+            if ( AValues != null ) n++;
+            if ( BValues != null ) n++;
+            return n;
+        }
+    }
+
+    private final TableFeature makeSpan(int start, int stop) {
+        return new TableFeature(genomeLocParser.createGenomeLoc("chr1", start, stop),
+                Collections.<String>emptyList(), Collections.<String>emptyList());
+    }
+
+    @DataProvider(name = "tests")
+    public Object[][] createTests() {
+        new MyTest(null, null);
+        new MyTest(Arrays.asList(AC_SNP), null);
+        new MyTest(Arrays.asList(AC_SNP, AT_SNP), null);
+        new MyTest(Arrays.asList(AC_SNP), Arrays.asList(AG_SNP));
+        new MyTest(Arrays.asList(AC_SNP, AT_SNP), Arrays.asList(AG_SNP));
+        new MyTest(Arrays.asList(AC_SNP, AT_SNP), Arrays.asList(span10_10));
+        new MyTest(Arrays.asList(AC_SNP, AT_SNP), Arrays.asList(span10_10, span10_20));
+        new MyTest(Arrays.asList(AC_SNP, AT_SNP), Arrays.asList(span10_10, span10_20, span1_20));
+
+        // for requires starts
+        new MyTest(Arrays.asList(span1_20), null);
+        new MyTest(Arrays.asList(span10_10, span10_20), null);
+        new MyTest(Arrays.asList(span10_10, span10_20, span1_20), null);
+
+        return MyTest.getTests(MyTest.class);
+    }
+
+    @Test(enabled = true, dataProvider = "tests")
+    public void testRawBindings(MyTest test) {
+        logger.warn("Testing " + test + " for number of bound tracks");
+        RefMetaDataTracker tracker = test.makeTracker();
+        Assert.assertEquals(tracker.getNTracksWithBoundFeatures(), test.nBoundTracks());
+
+        testSimpleBindings("A", tracker, test.AValues);
+        testSimpleBindings("B", tracker, test.BValues);
+    }
+
+    private <T> void testSimpleBindings(String name, RefMetaDataTracker tracker, RODRecordList expected) {
+        List<Feature> asValues = tracker.getValues(Feature.class, name);
+
+        Assert.assertEquals(tracker.hasValues(name), expected != null);
+        Assert.assertEquals(asValues.size(), expected == null ? 0 : expected.size());
+
+        if ( expected != null ) {
+            for ( GATKFeature e : expected ) {
+                boolean foundValue = false;
+                for ( Feature f : asValues ) {
+                    if ( e.getUnderlyingObject() == f ) foundValue = true;
+                }
+                Assert.assertTrue(foundValue, "Never found expected value of " + e.getUnderlyingObject() + " bound to " + name + " in " + tracker);
+            }
+        }
+    }
+
+    @Test(enabled = true, dataProvider = "tests")
+    public void testGettersAsString(MyTest test) {
+        logger.warn("Testing " + test + " for get() methods");
+        RefMetaDataTracker tracker = test.makeTracker();
+
+        for ( String name : Arrays.asList("A+B", "A", "B") ) {
+            List<Feature> v1 = name.equals("A+B") ? tracker.getValues(Feature.class) : tracker.getValues(Feature.class, name);
+            testGetter(name, v1, test.expected(name), true, tracker);
+
+            List<Feature> v2 = name.equals("A+B") ? tracker.getValues(Feature.class, locus) : tracker.getValues(Feature.class, name, locus);
+            testGetter(name, v2, startingHere(test.expected(name)), true, tracker);
+
+            Feature v3 = name.equals("A+B") ? tracker.getFirstValue(Feature.class) : tracker.getFirstValue(Feature.class, name);
+            testGetter(name, Arrays.asList(v3), test.expected(name), false, tracker);
+
+            Feature v4 = name.equals("A+B") ? tracker.getFirstValue(Feature.class, locus) : tracker.getFirstValue(Feature.class, name, locus);
+            testGetter(name, Arrays.asList(v4), startingHere(test.expected(name)), false, tracker);
+        }
+    }
+
+    @Test(enabled = true, dataProvider = "tests")
+    public void testGettersAsRodBindings(MyTest test) {
+        logger.warn("Testing " + test + " for get() methods as RodBindings");
+        RefMetaDataTracker tracker = test.makeTracker();
+
+        for ( String nameAsString : Arrays.asList("A", "B") ) {
+            RodBinding<Feature> binding = new RodBinding<Feature>(Feature.class, nameAsString, "none", "vcf", new Tags());
+            List<Feature> v1 = tracker.getValues(binding);
+            testGetter(nameAsString, v1, test.expected(nameAsString), true, tracker);
+
+            List<Feature> v2 = tracker.getValues(binding, locus);
+            testGetter(nameAsString, v2, startingHere(test.expected(nameAsString)), true, tracker);
+
+            Feature v3 = tracker.getFirstValue(binding);
+            testGetter(nameAsString, Arrays.asList(v3), test.expected(nameAsString), false, tracker);
+
+            Feature v4 = tracker.getFirstValue(binding, locus);
+            testGetter(nameAsString, Arrays.asList(v4), startingHere(test.expected(nameAsString)), false, tracker);
+        }
+    }
+
+    @Test(enabled = true, dataProvider = "tests")
+    public void testGettersAsListOfRodBindings(MyTest test) {
+        logger.warn("Testing " + test + " for get() methods for List<RodBindings>");
+        RefMetaDataTracker tracker = test.makeTracker();
+
+        String nameAsString = "A+B";
+        RodBinding<Feature> A = new RodBinding<Feature>(Feature.class, "A", "none", "vcf", new Tags());
+        RodBinding<Feature> B = new RodBinding<Feature>(Feature.class, "B", "none", "vcf", new Tags());
+        List<RodBinding<Feature>> binding = Arrays.asList(A, B);
+
+        List<Feature> v1 = tracker.getValues(binding);
+        testGetter(nameAsString, v1, test.expected(nameAsString), true, tracker);
+
+        List<Feature> v2 = tracker.getValues(binding, locus);
+        testGetter(nameAsString, v2, startingHere(test.expected(nameAsString)), true, tracker);
+
+        Feature v3 = tracker.getFirstValue(binding);
+        testGetter(nameAsString, Arrays.asList(v3), test.expected(nameAsString), false, tracker);
+
+        Feature v4 = tracker.getFirstValue(binding, locus);
+        testGetter(nameAsString, Arrays.asList(v4), startingHere(test.expected(nameAsString)), false, tracker);
+    }
+
+    private List<GATKFeature> startingHere(List<GATKFeature> l) {
+        List<GATKFeature> x = new ArrayList<GATKFeature>();
+        for ( GATKFeature f : l ) if ( f.getStart() == locus.getStart() ) x.add(f);
+        return x;
+    }
+
+    private void testGetter(String name, List<Feature> got, List<GATKFeature> expected, boolean requireExact, RefMetaDataTracker tracker) {
+        if ( got.size() == 1 && got.get(0) == null )
+            got = Collections.emptyList();
+
+        if ( requireExact )
+            Assert.assertEquals(got.size(), expected.size());
+
+        boolean foundAny = false;
+        for ( GATKFeature e : expected ) {
+            boolean found1 = false;
+            for ( Feature got1 : got ) {
+                if ( e.getUnderlyingObject() == got1 )
+                    found1 = true;
+            }
+            if ( requireExact )
+                Assert.assertTrue(found1, "Never found expected GATKFeature " + e + " bound to " + name + " in " + tracker);
+            foundAny = found1 || foundAny;
+        }
+
+        if ( ! requireExact && ! expected.isEmpty() )
+            Assert.assertTrue(foundAny, "Never found any got values matching one of the expected values bound to " + name + " in " + tracker);
+    }
+}
diff --git a/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/engine/refdata/tracks/FeatureManagerUnitTest.java b/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/engine/refdata/tracks/FeatureManagerUnitTest.java
new file mode 100644
index 0000000..ec3b470
--- /dev/null
+++ b/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/engine/refdata/tracks/FeatureManagerUnitTest.java
@@ -0,0 +1,163 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.engine.refdata.tracks;
+
+
+import htsjdk.samtools.reference.IndexedFastaSequenceFile;
+import htsjdk.tribble.Feature;
+import htsjdk.tribble.FeatureCodec;
+import org.broadinstitute.gatk.utils.BaseTest;
+import org.broadinstitute.gatk.utils.codecs.table.BedTableCodec;
+import org.broadinstitute.gatk.utils.codecs.table.TableFeature;
+import org.broadinstitute.gatk.utils.GenomeLocParser;
+import htsjdk.variant.vcf.VCF3Codec;
+import htsjdk.variant.vcf.VCFCodec;
+import org.broadinstitute.gatk.utils.exceptions.UserException;
+import org.broadinstitute.gatk.utils.fasta.CachingIndexedFastaSequenceFile;
+import htsjdk.variant.variantcontext.VariantContext;
+import org.testng.Assert;
+import org.testng.annotations.BeforeMethod;
+import org.testng.annotations.DataProvider;
+import org.testng.annotations.Test;
+
+import java.io.*;
+import java.util.*;
+
+
+/**
+ * @author depristo
+ *
+ * UnitTests for RMD FeatureManager
+ */
+public class FeatureManagerUnitTest extends BaseTest {
+    private static final File RANDOM_FILE = new File(publicTestDir+ "exampleGATKReport.eval");
+    private static final File VCF3_FILE = new File(privateTestDir + "vcf3.vcf");
+    private static final File VCF4_FILE = new File(privateTestDir + "HiSeq.10000.vcf");
+    private static final File VCF4_FILE_GZ = new File(privateTestDir + "HiSeq.10000.vcf.gz");
+    private static final File VCF4_FILE_BGZIP = new File(privateTestDir + "HiSeq.10000.bgzip.vcf.gz");
+
+    private FeatureManager manager;
+    private GenomeLocParser genomeLocParser;
+
+    @BeforeMethod
+    public void setup() {
+        File referenceFile = new File(b36KGReference);
+        try {
+            IndexedFastaSequenceFile seq = new CachingIndexedFastaSequenceFile(referenceFile);
+            genomeLocParser = new GenomeLocParser(seq);
+            manager = new FeatureManager();
+        }
+        catch(FileNotFoundException ex) {
+            throw new UserException.CouldNotReadInputFile(referenceFile,ex);
+        }
+    }
+
+    @Test
+    public void testManagerCreation() {
+        Assert.assertTrue(manager.getFeatureDescriptors().size() > 0);
+    }
+
+    private class FMTest extends BaseTest.TestDataProvider {
+        public Class codec;
+        public Class<? extends Feature> feature;
+        public String name;
+        public File associatedFile;
+
+        private FMTest(final Class feature, final Class codec, final String name, final File file) {
+            super(FMTest.class);
+            this.codec = codec;
+            this.feature = feature;
+            this.name = name;
+            this.associatedFile = file;
+        }
+
+        public void assertExpected(FeatureManager.FeatureDescriptor featureDescriptor) {
+            Assert.assertEquals(featureDescriptor.getCodecClass(), codec);
+            Assert.assertEquals(featureDescriptor.getFeatureClass(), feature);
+            Assert.assertEquals(featureDescriptor.getName().toLowerCase(), name.toLowerCase());
+        }
+
+        public String toString() {
+            return String.format("FMTest name=%s codec=%s feature=%s file=%s",
+                    name, codec.getSimpleName(), feature.getSimpleName(), associatedFile);
+        }
+    }
+
+    @DataProvider(name = "tests")
+    public Object[][] createTests() {
+        new FMTest(VariantContext.class, VCF3Codec.class, "VCF3", VCF3_FILE);
+        new FMTest(VariantContext.class, VCFCodec.class, "VCF", VCF4_FILE);
+        new FMTest(VariantContext.class, VCFCodec.class, "VCF", VCF4_FILE_GZ);
+        new FMTest(VariantContext.class, VCFCodec.class, "VCF", VCF4_FILE_BGZIP);
+        new FMTest(TableFeature.class, BedTableCodec.class, "bedtable", null);
+        return FMTest.getTests(FMTest.class);
+    }
+
+    @Test(dataProvider = "tests")
+    public void testGetByFile(FMTest params) {
+        if ( params.associatedFile != null ) {
+            FeatureManager.FeatureDescriptor byFile = manager.getByFiletype(params.associatedFile);
+            Assert.assertNotNull(byFile, "Couldn't find any type associated with file " + params.associatedFile);
+            params.assertExpected(byFile);
+        }
+    }
+
+    @Test
+    public void testGetByFileNoMatch() {
+        FeatureManager.FeatureDescriptor byFile = manager.getByFiletype(RANDOM_FILE);
+        Assert.assertNull(byFile, "Found type " + byFile + " associated with RANDOM, non-Tribble file " + RANDOM_FILE);
+    }
+
+    @Test(dataProvider = "tests")
+    public void testGetters(FMTest params) {
+        params.assertExpected(manager.getByCodec(params.codec));
+        params.assertExpected(manager.getByName(params.name));
+        params.assertExpected(manager.getByName(params.name.toLowerCase()));
+        params.assertExpected(manager.getByName(params.name.toUpperCase()));
+
+        Collection<FeatureManager.FeatureDescriptor> descriptors = manager.getByFeature(params.feature);
+        Assert.assertTrue(descriptors.size() > 0, "Look up by FeatureClass failed");
+    }
+
+    @Test
+    public void testUserFriendlyList() {
+        Assert.assertTrue(manager.userFriendlyListOfAvailableFeatures().length() > 0, "Expected at least one codec to be listed");
+        Assert.assertTrue(manager.userFriendlyListOfAvailableFeatures().split(",").length > 0, "Expected at least two codecs, but only saw one");
+    }
+
+    @Test
+    public void testCodecCreation() {
+        FeatureManager.FeatureDescriptor descriptor = manager.getByName("vcf");
+        Assert.assertNotNull(descriptor, "Couldn't find VCF feature descriptor!");
+
+        FeatureCodec c = manager.createCodec(descriptor, "foo", genomeLocParser, null);
+        Assert.assertNotNull(c, "Couldn't create codec");
+        Assert.assertEquals(c.getClass(), descriptor.getCodecClass());
+        Assert.assertEquals(c.getFeatureType(), descriptor.getFeatureClass());
+    }
+
+}
+
diff --git a/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/engine/refdata/tracks/RMDTrackBuilderUnitTest.java b/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/engine/refdata/tracks/RMDTrackBuilderUnitTest.java
new file mode 100644
index 0000000..a64773a
--- /dev/null
+++ b/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/engine/refdata/tracks/RMDTrackBuilderUnitTest.java
@@ -0,0 +1,190 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.engine.refdata.tracks;
+
+
+import htsjdk.samtools.reference.IndexedFastaSequenceFile;
+import htsjdk.tribble.Tribble;
+import htsjdk.tribble.index.Index;
+import htsjdk.tribble.util.LittleEndianOutputStream;
+import htsjdk.variant.vcf.VCFCodec;
+import org.broadinstitute.gatk.utils.exceptions.UserException;
+import org.testng.Assert;
+import org.broadinstitute.gatk.utils.BaseTest;
+import org.broadinstitute.gatk.utils.GenomeLocParser;
+import org.broadinstitute.gatk.utils.fasta.CachingIndexedFastaSequenceFile;
+
+import org.testng.annotations.BeforeMethod;
+
+import org.testng.annotations.Test;
+
+import java.io.*;
+import java.nio.channels.FileChannel;
+
+
+/**
+ * @author aaron
+ *         <p/>
+ *         Class RMDTrackBuilderUnitTest
+ *         <p/>
+ *         Testing out the builder for tribble Tracks
+ */
+public class RMDTrackBuilderUnitTest extends BaseTest {
+    private RMDTrackBuilder builder;
+    private IndexedFastaSequenceFile seq;
+    private GenomeLocParser genomeLocParser;
+
+    @BeforeMethod
+    public void setup() {
+        File referenceFile = new File(b37KGReference);
+        try {
+            seq = new CachingIndexedFastaSequenceFile(referenceFile);
+        }
+        catch(FileNotFoundException ex) {
+            throw new UserException.CouldNotReadInputFile(referenceFile,ex);
+        }
+        genomeLocParser = new GenomeLocParser(seq);
+
+        // We have to disable auto-index creation/locking in the RMDTrackBuilder for tests,
+        // as the lock acquisition calls were intermittently hanging on our farm. This unfortunately
+        // means that we can't include tests for the auto-index creation feature.
+        builder = new RMDTrackBuilder(seq.getSequenceDictionary(),genomeLocParser,null,true,null);
+    }
+
+    @Test
+    public void testBuilder() {
+        Assert.assertTrue(builder.getFeatureManager().getFeatureDescriptors().size() > 0);
+    }
+
+    @Test
+    public void testDisableAutoIndexGeneration() throws IOException {
+        final File unindexedVCF = new File(privateTestDir + "unindexed.vcf");
+        final File unindexedVCFIndex = Tribble.indexFile(unindexedVCF);
+
+        Index index = builder.loadIndex(unindexedVCF, new VCFCodec());
+
+        Assert.assertFalse(unindexedVCFIndex.exists());
+        Assert.assertNotNull(index);
+    }
+
+    @Test
+    public void testLoadOnDiskIndex() {
+        final File originalVCF = new File(privateTestDir + "vcf4.1.example.vcf");
+        final File tempVCFWithCorrectIndex = createTempVCFFileAndIndex(originalVCF, false);
+        final File tempVCFIndexFile = Tribble.indexFile(tempVCFWithCorrectIndex);
+
+        final Index index = builder.loadFromDisk(tempVCFWithCorrectIndex, tempVCFIndexFile);
+
+        Assert.assertNotNull(index);
+        Assert.assertTrue(tempVCFIndexFile.exists());
+
+        final Index inMemoryIndex = builder.createIndexInMemory(tempVCFWithCorrectIndex, new VCFCodec());
+        Assert.assertTrue(index.equalsIgnoreProperties(inMemoryIndex));
+    }
+
+    @Test
+    public void testLoadOnDiskOutdatedIndex() {
+        final File originalVCF = new File(privateTestDir + "vcf4.1.example.vcf");
+        final File tempVCFWithOutdatedIndex = createTempVCFFileAndIndex(originalVCF, true);
+        final File tempVCFIndexFile = Tribble.indexFile(tempVCFWithOutdatedIndex);
+
+        final Index index = builder.loadFromDisk(tempVCFWithOutdatedIndex, tempVCFIndexFile);
+
+        // loadFromDisk() should return null to indicate that the index is outdated and should not be used,
+        // but should not delete the index since our builder has disableAutoIndexCreation set to true
+        Assert.assertNull(index);
+        Assert.assertTrue(tempVCFIndexFile.exists());
+    }
+
+    /**
+     * Create a temporary vcf file and an associated index file, which may be set to be out-of-date
+     * relative to the vcf
+     *
+     * @param vcfFile the vcf file
+     * @param createOutOfDateIndex if true, ensure that the temporary vcf file is modified after the index
+     * @return a file pointing to the new tmp location, with accompanying index
+     */
+    private File createTempVCFFileAndIndex( final File vcfFile, final boolean createOutOfDateIndex ) {
+        try {
+            final File tmpFile = createTempFile("RMDTrackBuilderUnitTest", "");
+            final File tmpIndex = Tribble.indexFile(tmpFile);
+            tmpIndex.deleteOnExit();
+
+            copyFile(vcfFile, tmpFile);
+            final Index inMemoryIndex = builder.createIndexInMemory(tmpFile, new VCFCodec());
+            final LittleEndianOutputStream indexOutputStream = new LittleEndianOutputStream(new FileOutputStream(tmpIndex));
+
+            // If requested, modify the tribble file after the index. Otherwise, modify the index last.
+            if ( createOutOfDateIndex ) {
+                inMemoryIndex.write(indexOutputStream);
+                indexOutputStream.close();
+                Thread.sleep(2000);
+                copyFile(vcfFile, tmpFile);
+            }
+            else {
+                copyFile(vcfFile, tmpFile);
+                Thread.sleep(2000);
+                inMemoryIndex.write(indexOutputStream);
+                indexOutputStream.close();
+            }
+
+            return tmpFile;
+        } catch (IOException e) {
+            Assert.fail("Unable to create temperary file");
+        } catch (InterruptedException e) {
+            Assert.fail("Somehow our thread got interrupted");
+        }
+        return null;
+    }
+
+    /**
+     * copy a file, from http://www.exampledepot.com/egs/java.nio/File2File.html
+     *
+     * @param srFile the source file
+     * @param dtFile the destination file
+     */
+    private static void copyFile(File srFile, File dtFile) {
+        try {
+            // Create channel on the source
+            FileChannel srcChannel = new FileInputStream(srFile).getChannel();
+
+            // Create channel on the destination
+            FileChannel dstChannel = new FileOutputStream(dtFile).getChannel();
+
+            // Copy file contents from source to destination
+            dstChannel.transferFrom(srcChannel, 0, srcChannel.size());
+
+            // Close the channels
+            srcChannel.close();
+            dstChannel.close();
+        } catch (IOException e) {
+            e.printStackTrace();
+            Assert.fail("Unable to process copy " + e.getMessage());
+        }
+    }
+
+}
+
diff --git a/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/engine/refdata/utils/CheckableCloseableTribbleIterator.java b/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/engine/refdata/utils/CheckableCloseableTribbleIterator.java
new file mode 100644
index 0000000..e77c079
--- /dev/null
+++ b/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/engine/refdata/utils/CheckableCloseableTribbleIterator.java
@@ -0,0 +1,90 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.engine.refdata.utils;
+
+import htsjdk.tribble.CloseableTribbleIterator;
+import htsjdk.tribble.Feature;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+
+/**
+ * Adapter to allow checking if the wrapped iterator was closed.
+ * Creating an CCTI also adds it to the list returned from getThreadIterators().
+ * @param <T> feature
+ */
+public class CheckableCloseableTribbleIterator<T extends Feature> implements CloseableTribbleIterator<T> {
+    private final CloseableTribbleIterator<T> iterator;
+    private boolean closed = false;
+
+    private static ThreadLocal<List<CheckableCloseableTribbleIterator<? extends Feature>>> threadIterators =
+            new ThreadLocal<List<CheckableCloseableTribbleIterator<? extends Feature>>>() {
+                @Override
+                protected List<CheckableCloseableTribbleIterator<? extends Feature>> initialValue() {
+                    return new ArrayList<CheckableCloseableTribbleIterator<? extends Feature>>();
+                }
+            };
+
+    public CheckableCloseableTribbleIterator(CloseableTribbleIterator<T> iterator) {
+        this.iterator = iterator;
+        threadIterators.get().add(this);
+    }
+
+    /**
+     * Returns the list of iterators created on this thread since the last time clearCreatedIterators() was called.
+     * @return the list of iterators created on this thread since the last time clearCreatedIterators() was called.
+     */
+    public static List<CheckableCloseableTribbleIterator<? extends Feature>> getThreadIterators() {
+        return threadIterators.get();
+    }
+
+    /**
+     * Clears the tracked list of iterators created on this thread.
+     */
+    public static void clearThreadIterators() {
+        threadIterators.get().clear();
+    }
+
+    @Override
+    public void close() {
+        iterator.close();
+        this.closed = true;
+    }
+
+    /**
+     * Returns true if this iterator was properly closed.
+     * @return true if this iterator was properly closed.
+     */
+    public boolean isClosed() {
+        return closed;
+    }
+
+    @Override public Iterator<T> iterator() { return this; }
+    @Override public boolean hasNext() { return iterator.hasNext(); }
+    @Override public T next() { return iterator.next(); }
+    @Override public void remove() { iterator.remove(); }
+}
diff --git a/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/engine/refdata/utils/FeatureToGATKFeatureIteratorUnitTest.java b/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/engine/refdata/utils/FeatureToGATKFeatureIteratorUnitTest.java
new file mode 100644
index 0000000..d95c320
--- /dev/null
+++ b/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/engine/refdata/utils/FeatureToGATKFeatureIteratorUnitTest.java
@@ -0,0 +1,61 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.engine.refdata.utils;
+
+import htsjdk.samtools.reference.IndexedFastaSequenceFile;
+import htsjdk.tribble.Feature;
+import org.broadinstitute.gatk.utils.BaseTest;
+import org.broadinstitute.gatk.utils.GenomeLoc;
+import org.broadinstitute.gatk.utils.GenomeLocParser;
+import htsjdk.variant.vcf.VCFCodec;
+import org.broadinstitute.gatk.utils.fasta.CachingIndexedFastaSequenceFile;
+import org.testng.Assert;
+import org.testng.annotations.Test;
+
+import java.io.File;
+import java.io.IOException;
+
+public class FeatureToGATKFeatureIteratorUnitTest extends BaseTest {
+    @Test
+    @SuppressWarnings("unchecked")
+    public void testCloseFilePointers() throws IOException {
+        final String chr = "20";
+        IndexedFastaSequenceFile seq = new CachingIndexedFastaSequenceFile(new File(BaseTest.hg19Reference));
+        GenomeLocParser parser = new GenomeLocParser(seq);
+        File file = new File(privateTestDir + "NA12878.hg19.example1.vcf");
+        VCFCodec codec = new VCFCodec();
+        TestFeatureReader reader = new TestFeatureReader(file.getAbsolutePath(), codec);
+        CheckableCloseableTribbleIterator<Feature> tribbleIterator = reader.query(chr, 1, 100000);
+        FeatureToGATKFeatureIterator gatkIterator = new FeatureToGATKFeatureIterator(parser, tribbleIterator, "test");
+        Assert.assertTrue(gatkIterator.hasNext(), "GATK feature iterator does not have a next value.");
+        GenomeLoc gatkLocation = gatkIterator.next().getLocation();
+        Assert.assertEquals(gatkLocation.getContig(), chr, "Instead of chr 20 rod iterator was at location " + gatkLocation);
+        Assert.assertFalse(tribbleIterator.isClosed(), "Tribble iterator is closed but should be still open.");
+        gatkIterator.close();
+        Assert.assertTrue(tribbleIterator.isClosed(), "Tribble iterator is open but should be now closed.");
+        reader.close();
+    }
+}
diff --git a/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/engine/refdata/utils/FlashBackIteratorUnitTest.java b/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/engine/refdata/utils/FlashBackIteratorUnitTest.java
new file mode 100644
index 0000000..7aa07ef
--- /dev/null
+++ b/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/engine/refdata/utils/FlashBackIteratorUnitTest.java
@@ -0,0 +1,364 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.engine.refdata.utils;
+
+import htsjdk.samtools.SAMFileHeader;
+import htsjdk.samtools.SAMSequenceDictionary;
+import org.testng.Assert;
+import org.broadinstitute.gatk.utils.BaseTest;
+import org.broadinstitute.gatk.engine.refdata.ReferenceOrderedDatum;
+import org.broadinstitute.gatk.utils.GenomeLoc;
+import org.broadinstitute.gatk.utils.GenomeLocParser;
+import org.broadinstitute.gatk.utils.sam.ArtificialSAMUtils;
+
+import org.testng.annotations.BeforeMethod;
+
+import org.testng.annotations.Test;
+
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.util.AbstractList;
+import java.util.ArrayList;
+import java.util.List;
+
+
+/**
+ * @author aaron
+ *         <p/>
+ *         Class FlashBackIteratorUnitTest
+ *         <p/>
+ *         just like a greatful dead show...this will be prone to flashbacks
+ */
+public class FlashBackIteratorUnitTest extends BaseTest {
+    private SAMFileHeader header = ArtificialSAMUtils.createArtificialSamHeader(NUMBER_OF_CHROMOSOMES, STARTING_CHROMOSOME, CHROMOSOME_SIZE);
+    private static final int NUMBER_OF_CHROMOSOMES = 5;
+    private static final int STARTING_CHROMOSOME = 1;
+    private static final int CHROMOSOME_SIZE = 1000;
+
+    private String firstContig;
+    private GenomeLocParser genomeLocParser;
+
+    @BeforeMethod
+    public void setup() {
+        genomeLocParser = new GenomeLocParser(header.getSequenceDictionary());
+        firstContig = header.getSequenceDictionary().getSequence(0).getSequenceName();
+    }
+
+    @Test
+    public void testBasicIteration() {
+        GenomeLoc loc = genomeLocParser.createGenomeLoc(firstContig, 0, 0);
+        FlashBackIterator iter = new FlashBackIterator(new FakeSeekableRODIterator(genomeLocParser,loc));
+        GenomeLoc lastLocation = null;
+        for (int x = 0; x < 10; x++) {
+            iter.next();
+            GenomeLoc cur = iter.position();
+            if (lastLocation != null) {
+                Assert.assertTrue(lastLocation.isBefore(cur));
+            }
+            lastLocation = cur;
+        }
+    }
+
+    @Test
+    public void testBasicIterationThenFlashBack() {
+        GenomeLoc loc = genomeLocParser.createGenomeLoc(firstContig, 0, 0);
+        FlashBackIterator iter = new FlashBackIterator(new FakeSeekableRODIterator(genomeLocParser,loc));
+        GenomeLoc lastLocation = null;
+        for (int x = 0; x < 10; x++) {
+            iter.next();
+            GenomeLoc cur = iter.position();
+            if (lastLocation != null) {
+                Assert.assertTrue(lastLocation.isBefore(cur));
+            }
+            lastLocation = cur;
+        }
+        iter.flashBackTo(genomeLocParser.createGenomeLoc(firstContig, 2));
+    }
+
+    @Test
+    public void testBasicIterationThenFlashBackThenIterate() {
+        GenomeLoc loc = genomeLocParser.createGenomeLoc(firstContig, 0, 0);
+        FlashBackIterator iter = new FlashBackIterator(new FakeSeekableRODIterator(genomeLocParser,loc));
+        GenomeLoc lastLocation = null;
+        for (int x = 0; x < 10; x++) {
+            iter.next();
+            GenomeLoc cur = iter.position();
+            if (lastLocation != null) {
+                Assert.assertTrue(lastLocation.isBefore(cur));
+            }
+            lastLocation = cur;
+        }
+        iter.flashBackTo(genomeLocParser.createGenomeLoc(firstContig, 1));
+        int count = 0;
+        while (iter.hasNext()) {
+            count++;
+            iter.next();
+        }
+        Assert.assertEquals(count, 10);
+    }
+
+
+    @Test
+    public void testFlashBackTruth() {
+        GenomeLoc loc = genomeLocParser.createGenomeLoc(firstContig, 0, 0);
+        LocationAwareSeekableRODIterator backIter = new FakeSeekableRODIterator(genomeLocParser,loc);
+        // remove the first three records
+        backIter.next();
+        backIter.next();
+        backIter.next();
+        FlashBackIterator iter = new FlashBackIterator(backIter);
+        GenomeLoc lastLocation = null;
+        for (int x = 0; x < 10; x++) {
+            iter.next();
+            GenomeLoc cur = iter.position();
+            if (lastLocation != null) {
+                Assert.assertTrue(lastLocation.isBefore(cur));
+            }
+            lastLocation = cur;
+        }
+        Assert.assertTrue(iter.canFlashBackTo(genomeLocParser.createGenomeLoc(firstContig, 5)));
+        Assert.assertTrue(iter.canFlashBackTo(genomeLocParser.createGenomeLoc(firstContig, 15)));
+        Assert.assertTrue(!iter.canFlashBackTo(genomeLocParser.createGenomeLoc(firstContig, 2)));
+        Assert.assertTrue(!iter.canFlashBackTo(genomeLocParser.createGenomeLoc(firstContig, 1)));
+    }
+
+    @Test
+    public void testBasicIterationThenFlashBackHalfWayThenIterate() {
+        GenomeLoc loc = genomeLocParser.createGenomeLoc(firstContig, 0, 0);
+        FlashBackIterator iter = new FlashBackIterator(new FakeSeekableRODIterator(genomeLocParser,loc));
+        GenomeLoc lastLocation = null;
+        for (int x = 0; x < 10; x++) {
+            iter.next();
+            GenomeLoc cur = iter.position();
+            if (lastLocation != null) {
+                Assert.assertTrue(lastLocation.isBefore(cur));
+            }
+            lastLocation = cur;
+        }
+        iter.flashBackTo(genomeLocParser.createGenomeLoc(firstContig, 5));
+        int count = 0;
+        while (iter.hasNext()) {
+            count++;
+            iter.next();
+        }
+        Assert.assertEquals(count, 6); // chr1:5, 6, 7, 8, 9, and 10
+    }
+}
+
+
+class FakeSeekableRODIterator implements LocationAwareSeekableRODIterator {
+    private GenomeLocParser genomeLocParser;
+
+    // current location
+    private GenomeLoc location;
+    private FakeRODatum curROD;
+    private int recordCount = 10;
+
+    public FakeSeekableRODIterator(GenomeLocParser genomeLocParser,GenomeLoc startingLoc) {
+        this.genomeLocParser = genomeLocParser;
+        this.location = genomeLocParser.createGenomeLoc(startingLoc.getContig(), startingLoc.getStart() + 1, startingLoc.getStop() + 1);
+    }
+
+    /**
+     * Gets the header associated with the backing input stream.
+     * @return the ROD header.
+     */
+    @Override
+    public Object getHeader() {
+        return null;
+    }
+
+    /**
+     * Gets the sequence dictionary associated with the backing input stream.
+     * @return sequence dictionary from the ROD header.
+     */
+    @Override
+    public SAMSequenceDictionary getSequenceDictionary() {
+        return null;
+    }
+
+
+    @Override
+    public GenomeLoc peekNextLocation() {
+        System.err.println("Peek Next -> " + location);
+        return location;
+    }
+
+    @Override
+    public GenomeLoc position() {
+        return location;
+    }
+
+    @Override
+    public RODRecordList seekForward(GenomeLoc interval) {
+        this.location = interval;
+        return next();
+    }
+
+    @Override
+    public boolean hasNext() {
+        return (recordCount > 0);
+    }
+
+    @Override
+    public RODRecordList next() {
+        RODRecordList list = new FakeRODRecordList();
+        curROD = new FakeRODatum("STUPIDNAME", location);
+        location = genomeLocParser.createGenomeLoc(location.getContig(), location.getStart() + 1, location.getStop() + 1);
+        list.add(curROD);
+        recordCount--;
+        return list;
+    }
+
+    @Override
+    public void remove() {
+        throw new IllegalStateException("GRRR");
+    }
+
+    @Override
+    public void close() {
+        // nothing to do
+    }
+}
+
+
+/** for testing only */
+class FakeRODatum extends GATKFeature implements ReferenceOrderedDatum {
+
+    final GenomeLoc location;
+
+    public FakeRODatum(String name, GenomeLoc location) {
+        super(name);
+        this.location = location;
+    }
+
+    @Override
+    public String getName() {
+        return "false";
+    }
+
+    @Override
+    public boolean parseLine(Object header, String[] parts) throws IOException {
+        return false;
+    }
+
+    @Override
+    public String toSimpleString() {
+        return "";
+    }
+
+    @Override
+    public String repl() {
+        return "";
+    }
+
+    /**
+     * Used by the ROD system to determine how to split input lines
+     *
+     * @return Regex string delimiter separating fields
+     */
+    @Override
+    public String delimiterRegex() {
+        return "";
+    }
+
+    @Override
+    public GenomeLoc getLocation() {
+        return location;
+    }
+
+    @Override
+    public Object getUnderlyingObject() {
+        return this;
+    }
+
+    @Override
+    public int compareTo(ReferenceOrderedDatum that) {
+        return location.compareTo(that.getLocation());
+    }
+
+    /**
+     * Backdoor hook to read header, meta-data, etc. associated with the file.  Will be
+     * called by the ROD system before streaming starts
+     *
+     * @param source source data file on disk from which this rod stream will be pulled
+     *
+     * @return a header object that will be passed to parseLine command
+     */
+    @Override
+    public Object initialize(File source) throws FileNotFoundException {
+        return null;
+    }
+
+    @Override
+    public String getChr() {
+        return location.getContig();
+    }
+
+    @Override
+    public int getStart() {
+        return (int)location.getStart();
+    }
+
+    @Override
+    public int getEnd() {
+        return (int)location.getStop();
+    }
+}
+
+class FakeRODRecordList extends AbstractList<GATKFeature> implements RODRecordList {
+    private final List<GATKFeature> list = new ArrayList<GATKFeature>();
+
+    public boolean add(GATKFeature data) {
+        return list.add(data);
+    }
+
+    @Override
+    public GATKFeature get(int i) {
+        return list.get(i);
+    }
+
+    @Override
+    public int size() {
+        return list.size();
+    }
+
+    @Override
+    public GenomeLoc getLocation() {
+        return list.get(0).getLocation();
+    }
+
+    @Override
+    public String getName() {
+        return "test";
+    }
+
+    @Override
+    public int compareTo(RODRecordList rodRecordList) {
+        return this.list.get(0).getLocation().compareTo(rodRecordList.getLocation());
+    }
+}
diff --git a/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/engine/refdata/utils/TestFeatureReader.java b/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/engine/refdata/utils/TestFeatureReader.java
new file mode 100644
index 0000000..90b5e7a
--- /dev/null
+++ b/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/engine/refdata/utils/TestFeatureReader.java
@@ -0,0 +1,53 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.engine.refdata.utils;
+
+import htsjdk.tribble.Feature;
+import htsjdk.tribble.FeatureCodec;
+import htsjdk.tribble.TribbleIndexedFeatureReader;
+
+import java.io.IOException;
+
+/**
+ * Feature reader with additional test utilities. The iterators can be checked to see if they are closed.
+ */
+public class TestFeatureReader extends TribbleIndexedFeatureReader<Feature, Object> {
+    public TestFeatureReader(String featurePath, FeatureCodec codec) throws IOException {
+        super(featurePath, codec, true);
+    }
+
+    @Override
+    @SuppressWarnings("unchecked")
+    public CheckableCloseableTribbleIterator<Feature> iterator() throws IOException {
+        return new CheckableCloseableTribbleIterator<Feature>(super.iterator());
+    }
+
+    @Override
+    @SuppressWarnings("unchecked")
+    public CheckableCloseableTribbleIterator<Feature> query(String chr, int start, int end) throws IOException {
+        return new CheckableCloseableTribbleIterator<Feature>(super.query(chr, start, end));
+    }
+}
diff --git a/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/engine/refdata/utils/TestRMDTrackBuilder.java b/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/engine/refdata/utils/TestRMDTrackBuilder.java
new file mode 100644
index 0000000..17179f3
--- /dev/null
+++ b/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/engine/refdata/utils/TestRMDTrackBuilder.java
@@ -0,0 +1,71 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.engine.refdata.utils;
+
+import htsjdk.samtools.SAMSequenceDictionary;
+import htsjdk.tribble.FeatureCodec;
+import htsjdk.tribble.Tribble;
+import htsjdk.tribble.index.Index;
+import org.broadinstitute.gatk.engine.refdata.tracks.FeatureManager;
+import org.broadinstitute.gatk.engine.refdata.tracks.IndexDictionaryUtils;
+import org.broadinstitute.gatk.engine.refdata.tracks.RMDTrack;
+import org.broadinstitute.gatk.engine.refdata.tracks.RMDTrackBuilder;
+import org.broadinstitute.gatk.utils.GenomeLocParser;
+
+import java.io.File;
+import java.io.IOException;
+
+/**
+ * Extension of RMDTrackBuilder that creates TestFeatureReader's which in turn create CheckableCloseableTribbleIterator's.
+ */
+public class TestRMDTrackBuilder extends RMDTrackBuilder {
+    private GenomeLocParser genomeLocParser;
+
+    public TestRMDTrackBuilder(SAMSequenceDictionary dict, GenomeLocParser genomeLocParser) {
+        // disable auto-index creation/locking in the RMDTrackBuilder for tests
+        super(dict, genomeLocParser, null, true, null);
+        this.genomeLocParser = genomeLocParser;
+    }
+
+    @Override
+    public RMDTrack createInstanceOfTrack(RMDTriplet fileDescriptor) {
+        String name = fileDescriptor.getName();
+        File inputFile = new File(fileDescriptor.getFile());
+        FeatureManager.FeatureDescriptor descriptor = getFeatureManager().getByTriplet(fileDescriptor);
+        FeatureCodec codec = getFeatureManager().createCodec(descriptor, name, genomeLocParser, null);
+        TestFeatureReader featureReader;
+        Index index;
+        try {
+            // Create a feature reader that creates checkable tribble iterators.
+            index = loadIndex(inputFile, codec);
+            featureReader = new TestFeatureReader(inputFile.getAbsolutePath(), codec);
+        } catch (IOException e) {
+            throw new RuntimeException(e);
+        }
+        SAMSequenceDictionary sequenceDictionary = IndexDictionaryUtils.getSequenceDictionaryFromProperties(index);
+        return new RMDTrack(descriptor.getCodecClass(), name, inputFile, featureReader, sequenceDictionary, genomeLocParser, codec);
+    }
+}
diff --git a/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/engine/report/GATKReportUnitTest.java b/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/engine/report/GATKReportUnitTest.java
new file mode 100644
index 0000000..c28e901
--- /dev/null
+++ b/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/engine/report/GATKReportUnitTest.java
@@ -0,0 +1,285 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.engine.report;
+
+import org.broadinstitute.gatk.utils.BaseTest;
+import org.testng.Assert;
+import org.testng.annotations.DataProvider;
+import org.testng.annotations.Test;
+
+import java.io.File;
+import java.io.IOException;
+import java.io.PrintStream;
+import java.util.Random;
+import java.io.FileInputStream;
+import java.io.DataInputStream;
+import java.io.BufferedReader;
+import java.io.InputStreamReader;
+import java.util.ArrayList;
+
+
+public class GATKReportUnitTest extends BaseTest {
+    @Test
+    public void testParse() throws Exception {
+        String reportPath = publicTestDir + "exampleGATKReportv2.tbl";
+        GATKReport report = new GATKReport(reportPath);
+        Assert.assertEquals(report.getVersion(), GATKReportVersion.V1_1);
+        Assert.assertEquals(report.getTables().size(), 5);
+
+        GATKReportTable countVariants = report.getTable("CountVariants");
+        Assert.assertEquals(countVariants.get(0, "nProcessedLoci"), "63025520");
+        Assert.assertEquals(countVariants.get(0, "nNoCalls"), "0");
+        Assert.assertEquals(countVariants.get(0, "heterozygosity"), 4.73e-06);
+
+        GATKReportTable validationReport = report.getTable("ValidationReport");
+        Assert.assertEquals(validationReport.get(2, "PPV"), Double.NaN);
+    }
+
+    @DataProvider(name = "rightAlignValues")
+    public Object[][] getRightAlignValues() {
+        return new Object[][]{
+                new Object[]{null, true},
+                new Object[]{"null", true},
+                new Object[]{"NA", true},
+                new Object[]{"0", true},
+                new Object[]{"0.0", true},
+                new Object[]{"-0", true},
+                new Object[]{"-0.0", true},
+                new Object[]{String.valueOf(Long.MAX_VALUE), true},
+                new Object[]{String.valueOf(Long.MIN_VALUE), true},
+                new Object[]{String.valueOf(Float.MIN_NORMAL), true},
+                new Object[]{String.valueOf(Double.MAX_VALUE), true},
+                new Object[]{String.valueOf(Double.MIN_VALUE), true},
+                new Object[]{String.valueOf(Double.POSITIVE_INFINITY), true},
+                new Object[]{String.valueOf(Double.NEGATIVE_INFINITY), true},
+                new Object[]{String.valueOf(Double.NaN), true},
+                new Object[]{"hello", false}
+        };
+    }
+
+    @Test(dataProvider = "rightAlignValues")
+    public void testIsRightAlign(String value, boolean expected) {
+        Assert.assertEquals(GATKReportColumn.isRightAlign(value), expected, "right align of '" + value + "'");
+    }
+
+    private GATKReportTable getTableWithRandomValues() {
+        Random number = new Random(123L);
+        final int VALUESRANGE = 10;
+
+        GATKReport report = GATKReport.newSimpleReport("TableName", "col1", "col2", "col3");
+        GATKReportTable table = new GATKReportTable("testSortingTable", "table with random values sorted by columns", 3, GATKReportTable.TableSortingWay.SORT_BY_COLUMN );
+
+        final int NUMROWS = 100;
+        for (int x = 0; x < NUMROWS; x++) {
+            report.addRow(number.nextInt(VALUESRANGE), number.nextInt(VALUESRANGE), number.nextInt(VALUESRANGE));
+        }
+        return table;
+    }
+
+    @Test(enabled = true)
+    public void testSortingByColumn() {
+        Assert.assertEquals(isSorted(getTableWithRandomValues()), true);
+    }
+
+    private boolean isSorted(GATKReportTable table) {
+        boolean result = true;
+        File testingSortingTableFile = new File("testSortingFile.txt");
+
+        try {
+            // Connect print stream to the output stream
+            PrintStream ps = new PrintStream(testingSortingTableFile);
+            table.write(ps);
+            ps.close();
+        }
+        catch (Exception e){
+            System.err.println ("Error: " + e.getMessage());
+        }
+
+        ArrayList<int[]> rows = new ArrayList<int[]>();
+        try {
+            // Open the file
+            FileInputStream fStream = new FileInputStream(testingSortingTableFile);
+            // Get the object of DataInputStream
+            DataInputStream in = new DataInputStream(fStream);
+            BufferedReader br = new BufferedReader(new InputStreamReader(in));
+            String strLine;
+            //Read File Line By Line
+            while ((strLine = br.readLine()) != null) {
+
+                String[] parts = strLine.split(" ");
+                int l = parts.length;
+                int[] row = new int[l];
+                for(int n = 0; n < l; n++) {
+                    row[n] = Integer.parseInt(parts[n]);
+                }
+                rows.add(row);
+            }
+            //Close the input stream
+            in.close();
+        } catch (Exception e){//Catch exception if any
+            System.err.println("Error: " + e.getMessage());
+        }
+        for (int x = 1; x < rows.size() && result; x++)    {
+            result = checkRowOrder(rows.get(x - 1), rows.get(x));
+        }
+        return result;
+    }
+
+    private boolean checkRowOrder(int[] row1, int[] row2) {
+        int l = row1.length;
+        final int EQUAL = 0;
+
+        int result = EQUAL;
+
+        for(int x = 0; x < l && ( result <= EQUAL); x++) {
+            result = ((Integer)row1[x]).compareTo(row2[x]);
+        }
+        if (result <= EQUAL) {
+            return true;
+        } else {
+            return false;
+        }
+    }
+
+    private GATKReportTable makeBasicTable() {
+        GATKReport report = GATKReport.newSimpleReport("TableName", "sample", "value");
+        GATKReportTable table = report.getTable("TableName");
+        report.addRow("foo.1", "hello");
+        report.addRow("foo.2", "world");
+        return table;
+    }
+
+    @Test
+    public void testDottedSampleName() {
+        GATKReportTable table = makeBasicTable();
+        Assert.assertEquals(table.get(0, "value"), "hello");
+        Assert.assertEquals(table.get(1, "value"), "world");
+    }
+
+    @Test
+    public void testSimpleGATKReport() {
+        // Create a new simple GATK report named "TableName" with columns: Roger, is, and Awesome
+        GATKReport report = GATKReport.newSimpleReport("TableName", "Roger", "is", "Awesome");
+
+        // Add data to simple GATK report
+        report.addRow(12, 23.45, true);
+        report.addRow("ans", '3', 24.5);
+        report.addRow("hi", "", 2.3);
+
+        // Print the report to console
+        //report.print(System.out);
+
+        try {
+            File file = createTempFile("GATKReportGatherer-UnitTest", ".tbl");
+            //System.out.format("The temporary file" + " has been created: %s%n", file);
+            PrintStream ps = new PrintStream(file);
+            report.print(ps);
+            //System.out.println("File succesfully outputed!");
+            GATKReport inputRead = new GATKReport(file);
+            //System.out.println("File succesfully read!");
+            //inputRead.print(System.out);
+            Assert.assertTrue(report.isSameFormat(inputRead));
+
+        } catch (IOException x) {
+            System.err.format("IOException: %s%n", x);
+        }
+
+    }
+
+    @Test
+    public void testGATKReportGatherer() {
+
+        GATKReport report1, report2, report3;
+        report1 = new GATKReport();
+        report1.addTable("TableName", "Description", 2);
+        report1.getTable("TableName").addColumn("colA", "%s");
+        report1.getTable("TableName").addColumn("colB", "%c");
+        report1.getTable("TableName").set(0, "colA", "NotNum");
+        report1.getTable("TableName").set(0, "colB", (char) 64);
+
+        report2 = new GATKReport();
+        report2.addTable("TableName", "Description", 2);
+        report2.getTable("TableName").addColumn("colA", "%s");
+        report2.getTable("TableName").addColumn("colB", "%c");
+        report2.getTable("TableName").set(0, "colA", "df3");
+        report2.getTable("TableName").set(0, "colB", 'A');
+
+        report3 = new GATKReport();
+        report3.addTable("TableName", "Description", 2);
+        report3.getTable("TableName").addColumn("colA", "%s");
+        report3.getTable("TableName").addColumn("colB", "%c");
+        report3.getTable("TableName").set(0, "colA", "df5f");
+        report3.getTable("TableName").set(0, "colB", 'c');
+
+        report1.concat(report2);
+        report1.concat(report3);
+
+        report1.addTable("Table2", "To contain some more data types", 3);
+        GATKReportTable table = report1.getTable("Table2");
+        table.addColumn("SomeInt", "%d");
+        table.addColumn("SomeFloat", "%.16E");
+        table.addColumn("TrueFalse", "%B");
+        table.addRowIDMapping("12df", 0);
+        table.addRowIDMapping("5f", 1);
+        table.addRowIDMapping("RZ", 2);
+        table.set("12df", "SomeInt", Byte.MAX_VALUE);
+        table.set("12df", "SomeFloat", 34.0);
+        table.set("12df", "TrueFalse", true);
+        table.set("5f", "SomeInt", Short.MAX_VALUE);
+        table.set("5f", "SomeFloat", Double.MAX_VALUE);
+        table.set("5f", "TrueFalse", false);
+        table.set("RZ", "SomeInt", Long.MAX_VALUE);
+        table.set("RZ", "SomeFloat", 535646345.657453464576);
+        table.set("RZ", "TrueFalse", true);
+
+        report1.addTable("Table3", "blah", 1, GATKReportTable.TableSortingWay.SORT_BY_ROW);
+        report1.getTable("Table3").addColumn("a");
+        report1.getTable("Table3").addRowIDMapping("q", 2);
+        report1.getTable("Table3").addRowIDMapping("5", 3);
+        report1.getTable("Table3").addRowIDMapping("573s", 0);
+        report1.getTable("Table3").addRowIDMapping("ZZZ", 1);
+        report1.getTable("Table3").set("q", "a", "34");
+        report1.getTable("Table3").set("5", "a", "c4g34");
+        report1.getTable("Table3").set("573s", "a", "fDlwueg");
+        report1.getTable("Table3").set("ZZZ", "a", "Dfs");
+
+        try {
+            File file = createTempFile("GATKReportGatherer-UnitTest", ".tbl");
+            //System.out.format("The temporary file" + " has been created: %s%n", file);
+            PrintStream ps = new PrintStream(file);
+            report1.print(ps);
+            //System.out.println("File succesfully outputed!");
+            GATKReport inputRead = new GATKReport(file);
+            //System.out.println("File succesfully read!");
+            //inputRead.print(System.out);
+            Assert.assertTrue(report1.isSameFormat(inputRead));
+            Assert.assertTrue(report1.equals(inputRead));
+
+        } catch (IOException x) {
+            System.err.format("IOException: %s%n", x);
+        }
+    }
+}
diff --git a/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/engine/samples/PedReaderUnitTest.java b/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/engine/samples/PedReaderUnitTest.java
new file mode 100644
index 0000000..cd6014b
--- /dev/null
+++ b/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/engine/samples/PedReaderUnitTest.java
@@ -0,0 +1,354 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.engine.samples;
+
+import org.apache.log4j.Logger;
+import org.broadinstitute.gatk.utils.BaseTest;
+import org.broadinstitute.gatk.utils.Utils;
+import org.broadinstitute.gatk.utils.exceptions.UserException;
+import org.testng.Assert;
+import org.testng.annotations.DataProvider;
+import org.testng.annotations.Test;
+
+import java.io.StringReader;
+import java.util.*;
+
+/**
+ * UnitTest for PedReader
+ *
+ * @author Mark DePristo
+ * @since 2011
+ */
+public class PedReaderUnitTest extends BaseTest {
+    private static Logger logger = Logger.getLogger(PedReaderUnitTest.class);
+
+    private class PedReaderTest extends TestDataProvider {
+        public String fileContents;
+        public List<Sample> expectedSamples;
+        EnumSet<PedReader.MissingPedField> missing;
+
+        private PedReaderTest(final String name, final List<Sample> expectedSamples, final String fileContents) {
+            super(PedReaderTest.class, name);
+            this.fileContents = fileContents;
+            this.expectedSamples = expectedSamples;
+        }
+    }
+
+//     Family ID
+//     Individual ID
+//     Paternal ID
+//     Maternal ID
+//     Sex (1=male; 2=female; other=unknown)
+//     Phenotype
+//
+//     -9 missing
+//     0 missing
+//     1 unaffected
+//     2 affected
+
+    @DataProvider(name = "readerTest")
+    public Object[][] createPEDFiles() {
+        new PedReaderTest("singleRecordMale",
+                Arrays.asList(new Sample("kid", "fam1", null, null, Gender.MALE, Affection.UNAFFECTED)),
+                "fam1 kid 0 0 1 1");
+
+        new PedReaderTest("singleRecordFemale",
+                Arrays.asList(new Sample("kid", "fam1", null, null, Gender.FEMALE, Affection.UNAFFECTED)),
+                "fam1 kid 0 0 2 1");
+
+        new PedReaderTest("singleRecordMissingGender",
+                Arrays.asList(new Sample("kid", "fam1", null, null, Gender.UNKNOWN, Affection.UNKNOWN)),
+                "fam1 kid 0 0 0 0");
+
+        // Affection
+        new PedReaderTest("singleRecordAffected",
+                Arrays.asList(new Sample("kid", "fam1", null, null, Gender.MALE, Affection.AFFECTED)),
+                "fam1 kid 0 0 1 2");
+
+        new PedReaderTest("singleRecordUnaffected",
+                Arrays.asList(new Sample("kid", "fam1", null, null, Gender.MALE, Affection.UNAFFECTED)),
+                "fam1 kid 0 0 1 1");
+
+        new PedReaderTest("singleRecordMissingAffection-9",
+                Arrays.asList(new Sample("kid", "fam1", null, null, Gender.MALE, Affection.UNKNOWN)),
+                "fam1 kid 0 0 1 -9");
+
+        new PedReaderTest("singleRecordMissingAffection0",
+                Arrays.asList(new Sample("kid", "fam1", null, null, Gender.MALE, Affection.UNKNOWN)),
+                "fam1 kid 0 0 1 0");
+
+        new PedReaderTest("multipleUnrelated",
+                Arrays.asList(
+                        new Sample("s1", "fam1", null, null, Gender.MALE,   Affection.UNAFFECTED),
+                        new Sample("s2", "fam2", null, null, Gender.FEMALE, Affection.AFFECTED)),
+                String.format("%s%n%s",
+                        "fam1 s1 0 0 1 1",
+                        "fam2 s2 0 0 2 2"));
+
+        new PedReaderTest("multipleUnrelatedExtraLine",
+                Arrays.asList(
+                        new Sample("s1", "fam1", null, null, Gender.MALE,   Affection.UNAFFECTED),
+                        new Sample("s2", "fam2", null, null, Gender.FEMALE, Affection.AFFECTED)),
+                String.format("%s%n%s%n  %n", // note extra newlines and whitespace
+                        "fam1 s1 0 0 1 1",
+                        "fam2 s2 0 0 2 2"));
+
+        new PedReaderTest("explicitTrio",
+                Arrays.asList(
+                        new Sample("kid", "fam1", "dad", "mom", Gender.MALE,   Affection.AFFECTED),
+                        new Sample("dad", "fam1", null, null,   Gender.MALE,   Affection.UNAFFECTED),
+                        new Sample("mom", "fam1", null, null,   Gender.FEMALE, Affection.AFFECTED)),
+                String.format("%s%n%s%n%s",
+                        "fam1 kid dad mom 1 2",
+                        "fam1 dad 0   0   1 1",
+                        "fam1 mom 0   0   2 2"));
+
+        new PedReaderTest("implicitTrio",
+                Arrays.asList(
+                        new Sample("kid", "fam1", "dad", "mom", Gender.MALE,   Affection.AFFECTED),
+                        new Sample("dad", "fam1", null, null,   Gender.MALE,   Affection.UNKNOWN),
+                        new Sample("mom", "fam1", null, null,   Gender.FEMALE, Affection.UNKNOWN)),
+                "fam1 kid dad mom 1 2");
+
+        new PedReaderTest("partialTrio",
+                Arrays.asList(
+                        new Sample("kid", "fam1", "dad", "mom", Gender.MALE,   Affection.AFFECTED),
+                        new Sample("dad", "fam1", null, null,   Gender.MALE,   Affection.UNAFFECTED),
+                        new Sample("mom", "fam1", null, null,   Gender.FEMALE, Affection.UNKNOWN)),
+                String.format("%s%n%s",
+                        "fam1 kid dad mom 1 2",
+                        "fam1 dad 0   0   1 1"));
+
+        new PedReaderTest("bigPedigree",
+                Arrays.asList(
+                        new Sample("kid", "fam1", "dad",       "mom",      Gender.MALE,   Affection.AFFECTED),
+                        new Sample("dad", "fam1", "granddad1", "grandma1", Gender.MALE,   Affection.UNAFFECTED),
+                        new Sample("granddad1", "fam1", null, null,        Gender.MALE,   Affection.UNKNOWN),
+                        new Sample("grandma1",  "fam1", null, null,        Gender.FEMALE,   Affection.UNKNOWN),
+                        new Sample("mom", "fam1", "granddad2", "grandma2", Gender.FEMALE, Affection.AFFECTED),
+                        new Sample("granddad2", "fam1", null, null,        Gender.MALE,   Affection.UNKNOWN),
+                        new Sample("grandma2",  "fam1", null, null,        Gender.FEMALE,   Affection.UNKNOWN)),
+                String.format("%s%n%s%n%s",
+                        "fam1 kid dad       mom      1 2",
+                        "fam1 dad granddad1 grandma1 1 1",
+                        "fam1 mom granddad2 grandma2 2 2"));
+
+        // Quantitative trait
+        new PedReaderTest("OtherPhenotype",
+                Arrays.asList(
+                        new Sample("s1", "fam1", null, null, Gender.MALE,   Affection.OTHER, "1"),
+                        new Sample("s2", "fam2", null, null, Gender.FEMALE, Affection.OTHER, "10.0")),
+                String.format("%s%n%s",
+                        "fam1 s1 0 0 1 1",
+                        "fam2 s2 0 0 2 10.0"));
+
+        new PedReaderTest("OtherPhenotypeWithMissing",
+                Arrays.asList(
+                        new Sample("s1", "fam1", null, null, Gender.MALE,   Affection.UNKNOWN, Sample.UNSET_QT),
+                        new Sample("s2", "fam2", null, null, Gender.FEMALE, Affection.OTHER, "10.0")),
+                String.format("%s%n%s",
+                        "fam1 s1 0 0 1 -9",
+                        "fam2 s2 0 0 2 10.0"));
+
+        new PedReaderTest("OtherPhenotypeOnlyInts",
+                Arrays.asList(
+                        new Sample("s1", "fam1", null, null, Gender.MALE,   Affection.OTHER, "1"),
+                        new Sample("s2", "fam2", null, null, Gender.FEMALE, Affection.OTHER, "10")),
+                String.format("%s%n%s",
+                        "fam1 s1 0 0 1 1",
+                        "fam2 s2 0 0 2 10"));
+
+        return PedReaderTest.getTests(PedReaderTest.class);
+    }
+
+    private static final void runTest(PedReaderTest test, String myFileContents, EnumSet<PedReader.MissingPedField> missing) {
+        logger.warn("Test " + test);
+        PedReader reader = new PedReader();
+        SampleDB sampleDB = new SampleDB();
+        List<Sample> readSamples = reader.parse(myFileContents, missing, sampleDB);
+        Assert.assertEquals(new HashSet<Sample>(test.expectedSamples), new HashSet<Sample>(readSamples));
+    }
+
+    @Test(enabled = true, dataProvider = "readerTest")
+    public void testPedReader(PedReaderTest test) {
+        runTest(test, test.fileContents, EnumSet.noneOf(PedReader.MissingPedField.class));
+    }
+
+    @Test(enabled = true, dataProvider = "readerTest")
+    public void testPedReaderWithComments(PedReaderTest test) {
+        runTest(test, String.format("#comment%n%s", test.fileContents), EnumSet.noneOf(PedReader.MissingPedField.class));
+    }
+
+    @Test(enabled = true, dataProvider = "readerTest")
+    public void testPedReaderWithSemicolons(PedReaderTest test) {
+        runTest(test,
+                test.fileContents.replace(String.format("%n"), ";"),
+                EnumSet.noneOf(PedReader.MissingPedField.class));
+    }
+
+    // -----------------------------------------------------------------
+    // missing format field tests
+    // -----------------------------------------------------------------
+
+    private class PedReaderTestMissing extends TestDataProvider {
+        public EnumSet<PedReader.MissingPedField> missingDesc;
+        public EnumSet<PedReader.Field> missingFields;
+        public final String fileContents;
+        public Sample expected;
+
+
+        private PedReaderTestMissing(final String name, final String fileContents,
+                                     EnumSet<PedReader.MissingPedField> missingDesc,
+                                     EnumSet<PedReader.Field> missingFields,
+                                     final Sample expected) {
+            super(PedReaderTestMissing.class, name);
+            this.fileContents = fileContents;
+            this.missingDesc = missingDesc;
+            this.missingFields = missingFields;
+            this.expected = expected;
+        }
+    }
+
+    @DataProvider(name = "readerTestMissing")
+    public Object[][] createPEDFilesWithMissing() {
+        new PedReaderTestMissing("missingFam",
+                "fam1 kid dad mom 1 2",
+                EnumSet.of(PedReader.MissingPedField.NO_FAMILY_ID),
+                EnumSet.of(PedReader.Field.FAMILY_ID),
+                new Sample("kid", null, "dad", "mom", Gender.MALE, Affection.AFFECTED));
+
+        new PedReaderTestMissing("missingParents",
+                "fam1 kid dad mom 1 2",
+                EnumSet.of(PedReader.MissingPedField.NO_PARENTS),
+                EnumSet.of(PedReader.Field.PATERNAL_ID, PedReader.Field.MATERNAL_ID),
+                new Sample("kid", "fam1", null, null, Gender.MALE, Affection.AFFECTED));
+
+        new PedReaderTestMissing("missingSex",
+                "fam1 kid dad mom 1 2",
+                EnumSet.of(PedReader.MissingPedField.NO_SEX),
+                EnumSet.of(PedReader.Field.GENDER),
+                new Sample("kid", "fam1", "dad", "mom", Gender.UNKNOWN, Affection.AFFECTED));
+
+        new PedReaderTestMissing("missingPhenotype",
+                "fam1 kid dad mom 1 2",
+                EnumSet.of(PedReader.MissingPedField.NO_PHENOTYPE),
+                EnumSet.of(PedReader.Field.PHENOTYPE),
+                new Sample("kid", "fam1", "dad", "mom", Gender.MALE, Affection.UNKNOWN));
+
+        new PedReaderTestMissing("missingEverythingButGender",
+                "fam1 kid dad mom 1 2",
+                EnumSet.of(PedReader.MissingPedField.NO_PHENOTYPE, PedReader.MissingPedField.NO_PARENTS, PedReader.MissingPedField.NO_FAMILY_ID),
+                EnumSet.of(PedReader.Field.FAMILY_ID, PedReader.Field.PATERNAL_ID, PedReader.Field.MATERNAL_ID, PedReader.Field.PHENOTYPE),
+                new Sample("kid", null, null, null, Gender.MALE, Affection.UNKNOWN));
+
+
+        return PedReaderTestMissing.getTests(PedReaderTestMissing.class);
+    }
+
+    @Test(enabled = true, dataProvider = "readerTestMissing")
+    public void testPedReaderWithMissing(PedReaderTestMissing test) {
+        final String contents = sliceContents(test.missingFields, test.fileContents);
+        logger.warn("Test " + test);
+        PedReader reader = new PedReader();
+        SampleDB sampleDB = new SampleDB();
+        reader.parse(new StringReader(contents), test.missingDesc, sampleDB);
+        final Sample missingSample = sampleDB.getSample("kid");
+        Assert.assertEquals(test.expected, missingSample, "Missing field value not expected value for " + test);
+    }
+
+    private final static String sliceContents(EnumSet<PedReader.Field> missingFieldsSet, String full) {
+        List<String> parts = new ArrayList<String>(Arrays.asList(full.split("\\s+")));
+        final List<PedReader.Field> missingFields = new ArrayList<PedReader.Field>(missingFieldsSet);
+        Collections.reverse(missingFields);
+        for ( PedReader.Field field : missingFields )
+            parts.remove(field.ordinal());
+        return Utils.join("\t", parts);
+    }
+
+    // -----------------------------------------------------------------
+    // parsing tags
+    // -----------------------------------------------------------------
+
+    private class PedReaderTestTagParsing extends TestDataProvider {
+        public EnumSet<PedReader.MissingPedField> expected;
+        public final List<String> tags;
+
+        private PedReaderTestTagParsing(final List<String> tags, EnumSet<PedReader.MissingPedField> missingDesc) {
+            super(PedReaderTestTagParsing.class);
+            this.tags = tags;
+            this.expected = missingDesc;
+        }
+    }
+
+    @DataProvider(name = "readerTestTagParsing")
+    public Object[][] createReaderTestTagParsing() {
+        new PedReaderTestTagParsing(
+                Collections.<String>emptyList(),
+                EnumSet.noneOf(PedReader.MissingPedField.class));
+
+        new PedReaderTestTagParsing(
+                Arrays.asList("NO_FAMILY_ID"),
+                EnumSet.of(PedReader.MissingPedField.NO_FAMILY_ID));
+
+        new PedReaderTestTagParsing(
+                Arrays.asList("NO_PARENTS"),
+                EnumSet.of(PedReader.MissingPedField.NO_PARENTS));
+
+        new PedReaderTestTagParsing(
+                Arrays.asList("NO_PHENOTYPE"),
+                EnumSet.of(PedReader.MissingPedField.NO_PHENOTYPE));
+
+        new PedReaderTestTagParsing(
+                Arrays.asList("NO_SEX"),
+                EnumSet.of(PedReader.MissingPedField.NO_SEX));
+
+        new PedReaderTestTagParsing(
+                Arrays.asList("NO_SEX", "NO_PHENOTYPE"),
+                EnumSet.of(PedReader.MissingPedField.NO_SEX, PedReader.MissingPedField.NO_PHENOTYPE));
+
+        new PedReaderTestTagParsing(
+                Arrays.asList("NO_SEX", "NO_PHENOTYPE", "NO_PARENTS"),
+                EnumSet.of(PedReader.MissingPedField.NO_SEX, PedReader.MissingPedField.NO_PHENOTYPE, PedReader.MissingPedField.NO_PARENTS));
+
+        return PedReaderTestTagParsing.getTests(PedReaderTestTagParsing.class);
+    }
+
+    @Test(enabled = true, dataProvider = "readerTestTagParsing")
+    public void testPedReaderTagParsing(PedReaderTestTagParsing test) {
+        EnumSet<PedReader.MissingPedField> parsed = PedReader.parseMissingFieldTags("test", test.tags);
+        Assert.assertEquals(test.expected, parsed, "Failed to properly parse tags " + test.tags);
+    }
+
+    @Test(enabled = true, expectedExceptions = UserException.class)
+    public void testPedReaderTagParsing1() {
+        EnumSet<PedReader.MissingPedField> parsed = PedReader.parseMissingFieldTags("test", Arrays.asList("XXX"));
+    }
+
+    @Test(enabled = true, expectedExceptions = UserException.class)
+    public void testPedReaderTagParsing2() {
+        EnumSet<PedReader.MissingPedField> parsed = PedReader.parseMissingFieldTags("test", Arrays.asList("NO_SEX", "XXX"));
+    }
+}
\ No newline at end of file
diff --git a/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/engine/samples/SampleDBUnitTest.java b/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/engine/samples/SampleDBUnitTest.java
new file mode 100644
index 0000000..fc934ef
--- /dev/null
+++ b/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/engine/samples/SampleDBUnitTest.java
@@ -0,0 +1,251 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.engine.samples;
+
+import htsjdk.samtools.SAMFileHeader;
+import org.broadinstitute.gatk.utils.BaseTest;
+import org.broadinstitute.gatk.utils.exceptions.UserException;
+import org.broadinstitute.gatk.utils.sam.ArtificialSAMUtils;
+import org.testng.Assert;
+import org.testng.annotations.BeforeMethod;
+import org.testng.annotations.Test;
+
+import java.io.File;
+import java.util.*;
+
+/**
+ * Created by IntelliJ IDEA.
+ * User: brett
+ * Date: Sep 9, 2010
+ * Time: 8:21:00 AM
+ */
+public class SampleDBUnitTest extends BaseTest {
+    private static SampleDBBuilder builder;
+    // all the test sample files are located here
+    private File testPED = new File(privateTestDir +  "testtrio.ped");
+
+    private static final Set<Sample> testPEDSamples = new HashSet<Sample>(Arrays.asList(
+            new Sample("kid", "fam1", "dad", "mom", Gender.MALE,   Affection.AFFECTED),
+            new Sample("dad", "fam1", null, null,   Gender.MALE,   Affection.UNAFFECTED),
+            new Sample("mom", "fam1", null, null,   Gender.FEMALE, Affection.AFFECTED)));
+
+    private static final Set<Sample> testPEDFamilyF2 = new HashSet<Sample>(Arrays.asList(
+            new Sample("s2", "fam2", "d2", "m2", Gender.FEMALE, Affection.AFFECTED),
+            new Sample("d2", "fam2", null, null, Gender.MALE, Affection.UNKNOWN),
+            new Sample("m2", "fam2", null, null, Gender.FEMALE, Affection.UNKNOWN)
+            ));
+
+    private static final Set<Sample> testPEDFamilyF3 = new HashSet<Sample>(Arrays.asList(
+            new Sample("s1", "fam3", "d1", "m1", Gender.FEMALE, Affection.AFFECTED),
+            new Sample("d1", "fam3", null, null, Gender.MALE, Affection.UNKNOWN),
+            new Sample("m1", "fam3", null, null, Gender.FEMALE, Affection.UNKNOWN)
+            ));
+
+    private static final Set<Sample> testSAMSamples = new HashSet<Sample>(Arrays.asList(
+            new Sample("kid", null, null, null, Gender.UNKNOWN,   Affection.UNKNOWN),
+            new Sample("mom", null, null, null, Gender.UNKNOWN,   Affection.UNKNOWN),
+            new Sample("dad", null, null, null, Gender.UNKNOWN,   Affection.UNKNOWN)));
+
+    private static final HashMap<String, Set<Sample>> testGetFamilies = new HashMap<String,Set<Sample>>();
+    static {
+        testGetFamilies.put("fam1", testPEDSamples);
+        testGetFamilies.put("fam2", testPEDFamilyF2);
+        testGetFamilies.put("fam3", testPEDFamilyF3);
+    }
+
+    private static final Set<Sample> testKidsWithParentsFamilies2 = new HashSet<Sample>(Arrays.asList(
+            new Sample("kid", "fam1", "dad", "mom", Gender.MALE,   Affection.AFFECTED),
+            new Sample("kid3", "fam5", "dad2", "mom2", Gender.MALE,   Affection.AFFECTED),
+            new Sample("kid2", "fam5", "dad2", "mom2", Gender.MALE,   Affection.AFFECTED)));
+
+    private static final HashSet<String> testGetPartialFamiliesIds =   new HashSet<String>(Arrays.asList("kid","s1"));
+    private static final HashMap<String, Set<Sample>> testGetPartialFamilies = new HashMap<String,Set<Sample>>();
+    static {
+        testGetPartialFamilies.put("fam1", new HashSet<Sample>(Arrays.asList(new Sample("kid", "fam1", "dad", "mom", Gender.MALE,   Affection.AFFECTED))));
+        testGetPartialFamilies.put("fam3", new HashSet<Sample>(Arrays.asList(new Sample("s1", "fam3", "d1", "m1", Gender.FEMALE, Affection.AFFECTED))));
+    }
+
+    private static final String testPEDString =
+            String.format("%s%n%s%n%s",
+                    "fam1 kid dad mom 1 2",
+                    "fam1 dad 0   0   1 1",
+                    "fam1 mom 0   0   2 2");
+
+    private static final String testPEDMultipleFamilies =
+            String.format("%s%n%s%n%s%n%s%n%s",
+                    "fam1 kid dad mom 1 2",
+                    "fam1 dad 0   0   1 1",
+                    "fam1 mom 0   0   2 2",
+                    "fam3 s1  d1  m1  2 2",
+                    "fam2 s2  d2  m2  2 2");
+
+    private static final String testPEDMultipleFamilies2 =
+            String.format("%s%n%s%n%s%n%s%n%s%n%s%n%s%n%s%n%s",
+                    "fam1 kid dad mom 1 2",
+                    "fam1 dad 0   0   1 1",
+                    "fam1 mom 0   0   2 2",
+                    "fam4 kid4 dad4 0 1 2",
+                    "fam4 dad4 0   0   1 1",
+                    "fam5 kid2 dad2 mom2 1 2",
+                    "fam5 kid3 dad2 mom2 1 2",
+                    "fam5 dad2 0   0   1 1",
+                    "fam5 mom2 0   0   2 2");
+
+    private static final String testPEDStringInconsistentGender =
+            "fam1 kid 0   0   2 2";
+
+    private static final Set<Sample> testPEDSamplesAsSet =
+            new HashSet<Sample>(testPEDSamples);
+
+
+    @BeforeMethod
+    public void before() {
+        builder = new SampleDBBuilder(PedigreeValidationType.STRICT);
+    }
+
+    @Test()
+    public void loadPEDFile() {
+        builder.addSamplesFromPedigreeFiles(Arrays.asList(testPED));
+        SampleDB db = builder.getFinalSampleDB();
+        Assert.assertEquals(testPEDSamplesAsSet, db.getSamples());
+    }
+
+    @Test()
+    public void loadPEDString() {
+        builder.addSamplesFromPedigreeStrings(Arrays.asList(testPEDString));
+        SampleDB db = builder.getFinalSampleDB();
+        Assert.assertEquals(testPEDSamplesAsSet, db.getSamples());
+    }
+
+    private static final void addSAMHeader() {
+        SAMFileHeader header = ArtificialSAMUtils.createArtificialSamHeader(1, 1, 10);
+        ArtificialSAMUtils.createEnumeratedReadGroups(header, Arrays.asList("1", "2", "3"),
+                Arrays.asList("kid", "mom", "dad"));
+        builder.addSamplesFromSAMHeader(header);
+    }
+
+    @Test()
+    public void loadSAMHeader() {
+        addSAMHeader();
+        SampleDB db = builder.getFinalSampleDB();
+        Assert.assertEquals(testSAMSamples, db.getSamples());
+    }
+
+    @Test()
+    public void loadSAMHeaderPlusPED() {
+        addSAMHeader();
+        builder.addSamplesFromPedigreeFiles(Arrays.asList(testPED));
+        SampleDB db = builder.getFinalSampleDB();
+        Assert.assertEquals(testPEDSamples, db.getSamples());
+    }
+
+    @Test()
+    public void loadDuplicateData() {
+        builder.addSamplesFromPedigreeFiles(Arrays.asList(testPED));
+        builder.addSamplesFromPedigreeFiles(Arrays.asList(testPED));
+        SampleDB db = builder.getFinalSampleDB();
+        Assert.assertEquals(testPEDSamples, db.getSamples());
+    }
+
+    @Test(expectedExceptions = UserException.class)
+    public void loadNonExistentFile() {
+        builder.addSamplesFromPedigreeFiles(Arrays.asList(new File("non-existence-file.txt")));
+        SampleDB db = builder.getFinalSampleDB();
+        Assert.assertEquals(testSAMSamples, db.getSamples());
+    }
+
+    @Test(expectedExceptions = UserException.class)
+    public void loadInconsistentData() {
+        builder = new SampleDBBuilder(PedigreeValidationType.STRICT);
+        builder.addSamplesFromPedigreeFiles(Arrays.asList(testPED));
+        builder.addSamplesFromPedigreeStrings(Arrays.asList(testPEDStringInconsistentGender));
+        builder.getFinalSampleDB();
+    }
+
+    @Test(expectedExceptions = UserException.class)
+    public void sampleInSAMHeaderNotInSamplesDB() {
+        addSAMHeader();
+        builder.addSamplesFromPedigreeStrings(Arrays.asList(testPEDStringInconsistentGender));
+        builder.getFinalSampleDB();
+    }
+
+    @Test()
+    public void getFamilyIDs() {
+        builder.addSamplesFromPedigreeStrings(Arrays.asList(testPEDMultipleFamilies));
+        SampleDB db = builder.getFinalSampleDB();
+        Assert.assertEquals(db.getFamilyIDs(), new TreeSet<String>(Arrays.asList("fam1", "fam2", "fam3")));
+    }
+
+    @Test()
+    public void getFamily() {
+        builder.addSamplesFromPedigreeStrings(Arrays.asList(testPEDMultipleFamilies));
+        SampleDB db = builder.getFinalSampleDB();
+        Assert.assertEquals(db.getFamily("fam1"), testPEDSamplesAsSet);
+    }
+
+    @Test()
+    public void getFamilies(){
+        builder.addSamplesFromPedigreeStrings(Arrays.asList(testPEDMultipleFamilies));
+        SampleDB db = builder.getFinalSampleDB();
+        Assert.assertEquals(db.getFamilies(),testGetFamilies);
+        Assert.assertEquals(db.getFamilies(null),testGetFamilies);
+        Assert.assertEquals(db.getFamilies(testGetPartialFamiliesIds),testGetPartialFamilies);
+    }
+
+    @Test()
+    public void testGetChildrenWithParents()
+    {
+        builder.addSamplesFromPedigreeStrings(Arrays.asList(testPEDMultipleFamilies2));
+        SampleDB db = builder.getFinalSampleDB();
+        Assert.assertEquals(db.getChildrenWithParents(), testKidsWithParentsFamilies2);
+        Assert.assertEquals(db.getChildrenWithParents(false), testKidsWithParentsFamilies2);
+        Assert.assertEquals(db.getChildrenWithParents(true), new HashSet<Sample>(Arrays.asList(new Sample("kid", "fam1", "dad", "mom", Gender.MALE,   Affection.AFFECTED))));
+    }
+
+    @Test()
+    public void testGetFounderIds(){
+        builder.addSamplesFromPedigreeStrings(Arrays.asList(testPEDMultipleFamilies2));
+        SampleDB db = builder.getFinalSampleDB();
+        Assert.assertEquals(db.getFounderIds(), new HashSet<String>(Arrays.asList("dad","mom","dad2","mom2","dad4")));
+    }
+
+    @Test()
+    public void loadFamilyIDs() {
+        builder.addSamplesFromPedigreeStrings(Arrays.asList(testPEDMultipleFamilies));
+        SampleDB db = builder.getFinalSampleDB();
+        Map<String, Set<Sample>> families = db.getFamilies();
+        Assert.assertEquals(families.size(), 3);
+        Assert.assertEquals(families.keySet(), new TreeSet<String>(Arrays.asList("fam1", "fam2", "fam3")));
+
+        for ( final String famID : families.keySet() ) {
+            final Set<Sample> fam = families.get(famID);
+            Assert.assertEquals(fam.size(), 3);
+            for ( final Sample sample : fam ) {
+                Assert.assertEquals(sample.getFamilyID(), famID);
+            }
+        }
+    }
+}
diff --git a/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/engine/samples/SampleUnitTest.java b/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/engine/samples/SampleUnitTest.java
new file mode 100644
index 0000000..b1b09db
--- /dev/null
+++ b/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/engine/samples/SampleUnitTest.java
@@ -0,0 +1,89 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.engine.samples;
+
+import org.broadinstitute.gatk.utils.BaseTest;
+import org.testng.Assert;
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.Test;
+
+/**
+ *
+ */
+public class SampleUnitTest extends BaseTest {
+    SampleDB db;
+    static Sample fam1A, fam1B, fam1C;
+    static Sample s1, s2;
+    static Sample trait1, trait2, trait3, trait4, trait5;
+
+    @BeforeClass
+    public void init() {
+        db = new SampleDB();
+
+        fam1A = new Sample("1A", db, "fam1", "1B", "1C", Gender.UNKNOWN);
+        fam1B = new Sample("1B", db, "fam1", null, null, Gender.MALE);
+        fam1C = new Sample("1C", db, "fam1", null, null, Gender.FEMALE);
+
+        s1 = new Sample("s1", db);
+        s2 = new Sample("s2", db);
+
+        trait1 = new Sample("t1", db, Affection.AFFECTED, Sample.UNSET_QT);
+        trait2 = new Sample("t2", db, Affection.UNAFFECTED, Sample.UNSET_QT);
+        trait3 = new Sample("t3", db, Affection.UNKNOWN, Sample.UNSET_QT);
+        trait4 = new Sample("t4", db, Affection.OTHER, "1.0");
+        trait5 = new Sample("t4", db, Affection.OTHER, "CEU");
+    }
+
+    /**
+     * Now basic getters
+     */
+    @Test()
+    public void normalGettersTest() {
+        Assert.assertEquals("1A", fam1A.getID());
+        Assert.assertEquals("fam1", fam1A.getFamilyID());
+        Assert.assertEquals("1B", fam1A.getPaternalID());
+        Assert.assertEquals("1C", fam1A.getMaternalID());
+        Assert.assertEquals(null, fam1B.getPaternalID());
+        Assert.assertEquals(null, fam1B.getMaternalID());
+
+        Assert.assertEquals(Affection.AFFECTED, trait1.getAffection());
+        Assert.assertEquals(Sample.UNSET_QT, trait1.getOtherPhenotype());
+        Assert.assertEquals(Affection.UNAFFECTED, trait2.getAffection());
+        Assert.assertEquals(Sample.UNSET_QT, trait2.getOtherPhenotype());
+        Assert.assertEquals(Affection.UNKNOWN, trait3.getAffection());
+        Assert.assertEquals(Sample.UNSET_QT, trait3.getOtherPhenotype());
+        Assert.assertEquals(Affection.OTHER, trait4.getAffection());
+        Assert.assertEquals("1.0", trait4.getOtherPhenotype());
+        Assert.assertEquals("CEU", trait5.getOtherPhenotype());
+    }
+
+    @Test()
+    public void testGenders() {
+        Assert.assertTrue(fam1A.getGender() == Gender.UNKNOWN);
+        Assert.assertTrue(fam1B.getGender() == Gender.MALE);
+        Assert.assertTrue(fam1C.getGender() == Gender.FEMALE);
+    }
+}
diff --git a/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/engine/traversals/DummyActiveRegionWalker.java b/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/engine/traversals/DummyActiveRegionWalker.java
new file mode 100644
index 0000000..e1d81b5
--- /dev/null
+++ b/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/engine/traversals/DummyActiveRegionWalker.java
@@ -0,0 +1,116 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.engine.traversals;
+
+import org.broadinstitute.gatk.engine.contexts.AlignmentContext;
+import org.broadinstitute.gatk.engine.contexts.ReferenceContext;
+import org.broadinstitute.gatk.engine.refdata.RefMetaDataTracker;
+import org.broadinstitute.gatk.engine.walkers.ActiveRegionWalker;
+import org.broadinstitute.gatk.utils.GenomeLoc;
+import org.broadinstitute.gatk.utils.GenomeLocSortedSet;
+import org.broadinstitute.gatk.utils.activeregion.ActiveRegion;
+import org.broadinstitute.gatk.utils.activeregion.ActiveRegionReadState;
+import org.broadinstitute.gatk.utils.activeregion.ActivityProfileState;
+
+import java.util.*;
+
+/**
+ * ActiveRegionWalker for unit testing
+ *
+ * User: depristo
+ * Date: 1/15/13
+ * Time: 1:28 PM
+ */
+class DummyActiveRegionWalker extends ActiveRegionWalker<Integer, Integer> {
+    private final double prob;
+    private EnumSet<ActiveRegionReadState> states = super.desiredReadStates();
+    private GenomeLocSortedSet activeRegions = null;
+
+    protected List<GenomeLoc> isActiveCalls = new ArrayList<GenomeLoc>();
+    protected Map<GenomeLoc, ActiveRegion> mappedActiveRegions = new LinkedHashMap<GenomeLoc, ActiveRegion>();
+    private boolean declareHavingPresetRegions = false;
+
+    public DummyActiveRegionWalker() {
+        this(1.0);
+    }
+
+    public DummyActiveRegionWalker(double constProb) {
+        this.prob = constProb;
+    }
+
+    public DummyActiveRegionWalker(GenomeLocSortedSet activeRegions, EnumSet<ActiveRegionReadState> wantStates, final boolean declareHavingPresetRegions) {
+        this(activeRegions, declareHavingPresetRegions);
+        this.states = wantStates;
+    }
+
+    public DummyActiveRegionWalker(GenomeLocSortedSet activeRegions, final boolean declareHavingPresetRegions) {
+        this(1.0);
+        this.activeRegions = activeRegions;
+        this.declareHavingPresetRegions = declareHavingPresetRegions;
+    }
+
+    public void setStates(EnumSet<ActiveRegionReadState> states) {
+        this.states = states;
+    }
+
+    @Override
+    public boolean hasPresetActiveRegions() {
+        return declareHavingPresetRegions;
+    }
+
+    @Override
+    public GenomeLocSortedSet getPresetActiveRegions() {
+        return declareHavingPresetRegions ? activeRegions : null;
+    }
+
+    @Override
+    public EnumSet<ActiveRegionReadState> desiredReadStates() {
+        return states;
+    }
+
+    @Override
+    public ActivityProfileState isActive(RefMetaDataTracker tracker, ReferenceContext ref, AlignmentContext context) {
+        isActiveCalls.add(ref.getLocus());
+        final double p = activeRegions == null || activeRegions.overlaps(ref.getLocus()) ? prob : 0.0;
+        return new ActivityProfileState(ref.getLocus(), p);
+    }
+
+    @Override
+    public Integer map(ActiveRegion activeRegion, RefMetaDataTracker metaDataTracker) {
+        mappedActiveRegions.put(activeRegion.getLocation(), activeRegion);
+        return 0;
+    }
+
+    @Override
+    public Integer reduceInit() {
+        return 0;
+    }
+
+    @Override
+    public Integer reduce(Integer value, Integer sum) {
+        return 0;
+    }
+}
diff --git a/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/engine/traversals/TAROrderedReadCacheUnitTest.java b/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/engine/traversals/TAROrderedReadCacheUnitTest.java
new file mode 100644
index 0000000..75c669c
--- /dev/null
+++ b/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/engine/traversals/TAROrderedReadCacheUnitTest.java
@@ -0,0 +1,111 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.engine.traversals;
+
+import htsjdk.samtools.reference.IndexedFastaSequenceFile;
+import org.broadinstitute.gatk.utils.BaseTest;
+import org.broadinstitute.gatk.utils.fasta.CachingIndexedFastaSequenceFile;
+import org.broadinstitute.gatk.utils.sam.ArtificialBAMBuilder;
+import org.broadinstitute.gatk.utils.sam.GATKSAMRecord;
+import org.testng.Assert;
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.DataProvider;
+import org.testng.annotations.Test;
+
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+public class TAROrderedReadCacheUnitTest extends BaseTest {
+    // example fasta index file, can be deleted if you don't use the reference
+    private IndexedFastaSequenceFile seq;
+
+    @BeforeClass
+    public void setup() throws FileNotFoundException {
+        // sequence
+        seq = new CachingIndexedFastaSequenceFile(new File(b37KGReference));
+    }
+
+    @DataProvider(name = "ReadCacheTestData")
+    public Object[][] makeReadCacheTestData() {
+        List<Object[]> tests = new ArrayList<Object[]>();
+
+        for ( final int nReadsPerLocus : Arrays.asList(0, 1, 10, 100) ) {
+            for ( final int nLoci : Arrays.asList(1, 10, 100) ) {
+                for ( final int max : Arrays.asList(10, 50, 1000) ) {
+                    for ( final boolean addAllAtOnce : Arrays.asList(true, false) ) {
+                        tests.add(new Object[]{nReadsPerLocus, nLoci, max, addAllAtOnce});
+                    }
+                }
+            }
+        }
+
+        return tests.toArray(new Object[][]{});
+    }
+
+    @Test(dataProvider = "ReadCacheTestData")
+    public void testReadCache(final int nReadsPerLocus, final int nLoci, final int max, final boolean addAllAtOnce) {
+        final TAROrderedReadCache cache = new TAROrderedReadCache(max);
+
+        Assert.assertEquals(cache.getMaxCapacity(), max);
+        Assert.assertEquals(cache.getNumDiscarded(), 0);
+        Assert.assertEquals(cache.size(), 0);
+
+        final ArtificialBAMBuilder bamBuilder = new ArtificialBAMBuilder(seq, nReadsPerLocus, nLoci);
+        final List<GATKSAMRecord> reads = bamBuilder.makeReads();
+
+        if ( addAllAtOnce ) {
+            cache.addAll(reads);
+        } else {
+            for ( final GATKSAMRecord read : reads ) {
+                cache.add(read);
+            }
+        }
+
+        final int nTotalReads = reads.size();
+        final int nExpectedToKeep = Math.min(nTotalReads, max);
+        final int nExpectedToDiscard = nTotalReads - nExpectedToKeep;
+        Assert.assertEquals(cache.getNumDiscarded(), nExpectedToDiscard, "wrong number of reads discarded");
+        Assert.assertEquals(cache.size(), nExpectedToKeep, "wrong number of reads kept");
+
+        final List<GATKSAMRecord> cacheReads = cache.popCurrentReads();
+        Assert.assertEquals(cache.size(), 0, "Should be no reads left");
+        Assert.assertEquals(cache.getNumDiscarded(), 0, "should have reset stats");
+        Assert.assertEquals(cacheReads.size(), nExpectedToKeep, "should have 1 read for every read we expected to keep");
+
+        verifySortednessOfReads(cacheReads);
+    }
+
+    private void verifySortednessOfReads( final List<GATKSAMRecord> reads) {
+        int lastStart = -1;
+        for ( GATKSAMRecord read : reads ) {
+            Assert.assertTrue(lastStart <= read.getAlignmentStart(), "Reads should be sorted but weren't.  Found read with start " + read.getAlignmentStart() + " while last was " + lastStart);
+            lastStart = read.getAlignmentStart();
+        }
+    }
+}
diff --git a/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/engine/traversals/TraverseActiveRegionsUnitTest.java b/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/engine/traversals/TraverseActiveRegionsUnitTest.java
new file mode 100644
index 0000000..50eb496
--- /dev/null
+++ b/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/engine/traversals/TraverseActiveRegionsUnitTest.java
@@ -0,0 +1,679 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.engine.traversals;
+
+import com.google.java.contract.PreconditionError;
+import htsjdk.samtools.*;
+import org.broadinstitute.gatk.utils.commandline.Tags;
+import org.broadinstitute.gatk.engine.arguments.ValidationExclusion;
+import org.broadinstitute.gatk.engine.datasources.reads.*;
+import org.broadinstitute.gatk.engine.filters.ReadFilter;
+import org.broadinstitute.gatk.engine.iterators.ReadTransformer;
+import org.broadinstitute.gatk.engine.resourcemanagement.ThreadAllocation;
+import org.broadinstitute.gatk.engine.walkers.Walker;
+import org.broadinstitute.gatk.utils.GenomeLocSortedSet;
+import org.broadinstitute.gatk.utils.SampleUtils;
+import org.broadinstitute.gatk.utils.activeregion.ActiveRegionReadState;
+import org.broadinstitute.gatk.utils.interval.IntervalMergingRule;
+import org.broadinstitute.gatk.utils.interval.IntervalUtils;
+import org.broadinstitute.gatk.utils.sam.*;
+import htsjdk.samtools.reference.IndexedFastaSequenceFile;
+import org.broadinstitute.gatk.utils.BaseTest;
+import org.broadinstitute.gatk.engine.GenomeAnalysisEngine;
+import org.broadinstitute.gatk.engine.datasources.providers.LocusShardDataProvider;
+import org.broadinstitute.gatk.engine.datasources.rmd.ReferenceOrderedDataSource;
+import org.broadinstitute.gatk.engine.executive.WindowMaker;
+import org.broadinstitute.gatk.utils.GenomeLoc;
+import org.broadinstitute.gatk.utils.GenomeLocParser;
+import org.broadinstitute.gatk.utils.activeregion.ActiveRegion;
+import org.broadinstitute.gatk.utils.fasta.CachingIndexedFastaSequenceFile;
+import org.testng.Assert;
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.DataProvider;
+import org.testng.annotations.Test;
+
+
+import java.io.File;
+import java.io.IOException;
+import java.util.*;
+
+/**
+ * Created with IntelliJ IDEA.
+ * User: thibault
+ * Date: 11/13/12
+ * Time: 2:47 PM
+ *
+ * Test the Active Region Traversal Contract
+ * http://iwww.broadinstitute.org/gsa/wiki/index.php/Active_Region_Traversal_Contract
+ */
+public class TraverseActiveRegionsUnitTest extends BaseTest {
+    private final static boolean ENFORCE_CONTRACTS = false;
+    private final static boolean DEBUG = false;
+
+    @DataProvider(name = "TraversalEngineProvider")
+    public Object[][] makeTraversals() {
+        final List<Object[]> traversals = new LinkedList<Object[]>();
+        traversals.add(new Object[]{new TraverseActiveRegions<>()});
+        return traversals.toArray(new Object[][]{});
+    }
+
+    private IndexedFastaSequenceFile reference;
+    private SAMSequenceDictionary dictionary;
+    private GenomeLocParser genomeLocParser;
+
+    private List<GenomeLoc> intervals;
+
+    private File testBAM;
+
+    @BeforeClass
+    private void init() throws IOException {
+        //reference = new CachingIndexedFastaSequenceFile(new File("/Users/depristo/Desktop/broadLocal/localData/human_g1k_v37.fasta")); // hg19Reference));
+        reference = new CachingIndexedFastaSequenceFile(new File(hg19Reference));
+        dictionary = reference.getSequenceDictionary();
+        genomeLocParser = new GenomeLocParser(dictionary);
+
+        // TODO: reads with indels
+        // TODO: reads which span many regions
+        // TODO: reads which are partially between intervals (in/outside extension)
+        // TODO: duplicate reads
+        // TODO: read at the end of a contig
+        // TODO: reads which are completely outside intervals but within extension
+        // TODO: test the extension itself
+        // TODO: unmapped reads
+
+        intervals = new ArrayList<GenomeLoc>();
+        intervals.add(genomeLocParser.createGenomeLoc("1", 10, 20));
+        intervals.add(genomeLocParser.createGenomeLoc("1", 1, 999));
+        intervals.add(genomeLocParser.createGenomeLoc("1", 1000, 1999));
+        intervals.add(genomeLocParser.createGenomeLoc("1", 2000, 2999));
+        intervals.add(genomeLocParser.createGenomeLoc("1", 10000, 20000));
+        intervals.add(genomeLocParser.createGenomeLoc("2", 1, 100));
+        intervals.add(genomeLocParser.createGenomeLoc("20", 10000, 10100));
+        intervals = IntervalUtils.sortAndMergeIntervals(genomeLocParser, intervals, IntervalMergingRule.OVERLAPPING_ONLY).toList();
+
+        List<GATKSAMRecord> reads = new ArrayList<GATKSAMRecord>();
+        reads.add(buildSAMRecord("simple", "1", 100, 200));
+        reads.add(buildSAMRecord("overlap_equal", "1", 10, 20));
+        reads.add(buildSAMRecord("overlap_unequal", "1", 10, 21));
+        reads.add(buildSAMRecord("boundary_equal", "1", 1990, 2009));
+        reads.add(buildSAMRecord("boundary_unequal", "1", 1990, 2008));
+        reads.add(buildSAMRecord("boundary_1_pre", "1", 1950, 2000));
+        reads.add(buildSAMRecord("boundary_1_post", "1", 1999, 2050));
+        reads.add(buildSAMRecord("extended_and_np", "1", 990, 1990));
+        reads.add(buildSAMRecord("outside_intervals", "1", 5000, 6000));
+        reads.add(buildSAMRecord("shard_boundary_1_pre", "1", 16300, 16385));
+        reads.add(buildSAMRecord("shard_boundary_1_post", "1", 16384, 16400));
+        reads.add(buildSAMRecord("shard_boundary_equal", "1", 16355, 16414));
+        reads.add(buildSAMRecord("simple20", "20", 10025, 10075));
+
+        createBAM(reads);
+    }
+
+    private void createBAM(List<GATKSAMRecord> reads) throws IOException {
+        testBAM = createTempFile("TraverseActiveRegionsUnitTest", ".bam");
+
+        SAMFileWriter out = new SAMFileWriterFactory().setCreateIndex(true).makeBAMWriter(reads.get(0).getHeader(), true, testBAM);
+        for (GATKSAMRecord read : ReadUtils.sortReadsByCoordinate(reads)) {
+            out.addAlignment(read);
+        }
+        out.close();
+
+        new File(testBAM.getAbsolutePath().replace(".bam", ".bai")).deleteOnExit();
+        new File(testBAM.getAbsolutePath() + ".bai").deleteOnExit();
+    }
+
+    @Test(enabled = true && ! DEBUG, dataProvider = "TraversalEngineProvider")
+    public void testAllBasesSeen(TraverseActiveRegions t) {
+        DummyActiveRegionWalker walker = new DummyActiveRegionWalker();
+
+        List<GenomeLoc> activeIntervals = getIsActiveIntervals(t, walker, intervals);
+        // Contract: Every genome position in the analysis interval(s) is processed by the walker's isActive() call
+        verifyEqualIntervals(intervals, activeIntervals);
+    }
+
+    private List<GenomeLoc> getIsActiveIntervals(final TraverseActiveRegions t, DummyActiveRegionWalker walker, List<GenomeLoc> intervals) {
+        List<GenomeLoc> activeIntervals = new ArrayList<GenomeLoc>();
+        for (LocusShardDataProvider dataProvider : createDataProviders(t, walker, intervals, testBAM)) {
+            t.traverse(walker, dataProvider, 0);
+            activeIntervals.addAll(walker.isActiveCalls);
+        }
+
+        return activeIntervals;
+    }
+
+    @Test (enabled = ENFORCE_CONTRACTS, dataProvider = "TraversalEngineProvider", expectedExceptions = PreconditionError.class)
+    public void testIsActiveRangeLow (TraverseActiveRegions t) {
+        DummyActiveRegionWalker walker = new DummyActiveRegionWalker(-0.1);
+        getActiveRegions(t, walker, intervals).values();
+    }
+
+    @Test (enabled = ENFORCE_CONTRACTS, dataProvider = "TraversalEngineProvider", expectedExceptions = PreconditionError.class)
+    public void testIsActiveRangeHigh (TraverseActiveRegions t) {
+        DummyActiveRegionWalker walker = new DummyActiveRegionWalker(1.1);
+        getActiveRegions(t, walker, intervals).values();
+    }
+
+    @Test(enabled = true && ! DEBUG, dataProvider = "TraversalEngineProvider")
+    public void testActiveRegionCoverage(TraverseActiveRegions t) {
+        DummyActiveRegionWalker walker = new DummyActiveRegionWalker(new GenomeLocSortedSet(genomeLocParser, intervals), true);
+
+        Collection<ActiveRegion> activeRegions = getActiveRegions(t, walker, intervals).values();
+        verifyActiveRegionCoverage(intervals, activeRegions);
+    }
+
+    private void verifyActiveRegionCoverage(List<GenomeLoc> intervals, Collection<ActiveRegion> activeRegions) {
+        List<GenomeLoc> intervalStarts = new ArrayList<GenomeLoc>();
+        List<GenomeLoc> intervalStops = new ArrayList<GenomeLoc>();
+
+        for (GenomeLoc interval : intervals) {
+            intervalStarts.add(interval.getStartLocation());
+            intervalStops.add(interval.getStopLocation());
+        }
+
+        Map<GenomeLoc, ActiveRegion> baseRegionMap = new HashMap<GenomeLoc, ActiveRegion>();
+
+        for (ActiveRegion activeRegion : activeRegions) {
+            for (GenomeLoc activeLoc : toSingleBaseLocs(activeRegion.getLocation())) {
+                // Contract: Regions do not overlap
+                Assert.assertFalse(baseRegionMap.containsKey(activeLoc), "Genome location " + activeLoc + " is assigned to more than one region");
+                baseRegionMap.put(activeLoc, activeRegion);
+            }
+
+            GenomeLoc start = activeRegion.getLocation().getStartLocation();
+            if (intervalStarts.contains(start))
+                intervalStarts.remove(start);
+
+            GenomeLoc stop = activeRegion.getLocation().getStopLocation();
+            if (intervalStops.contains(stop))
+                intervalStops.remove(stop);
+        }
+
+        for (GenomeLoc baseLoc : toSingleBaseLocs(intervals)) {
+            // Contract: Each location in the interval(s) is in exactly one region
+            // Contract: The total set of regions exactly matches the analysis interval(s)
+            Assert.assertTrue(baseRegionMap.containsKey(baseLoc), "Genome location " + baseLoc + " is not assigned to any region");
+            baseRegionMap.remove(baseLoc);
+        }
+
+        // Contract: The total set of regions exactly matches the analysis interval(s)
+        Assert.assertEquals(baseRegionMap.size(), 0, "Active regions contain base(s) outside of the given intervals");
+
+        // Contract: All explicit interval boundaries must also be region boundaries
+        Assert.assertEquals(intervalStarts.size(), 0, "Interval start location does not match an active region start location");
+        Assert.assertEquals(intervalStops.size(), 0, "Interval stop location does not match an active region stop location");
+    }
+
+    @Test(enabled = true && ! DEBUG, dataProvider = "TraversalEngineProvider")
+    public void testActiveRegionExtensionOnContig(TraverseActiveRegions t) {
+        DummyActiveRegionWalker walker = new DummyActiveRegionWalker();
+
+        Collection<ActiveRegion> activeRegions = getActiveRegions(t, walker, intervals).values();
+        for (ActiveRegion activeRegion : activeRegions) {
+            GenomeLoc loc = activeRegion.getExtendedLoc();
+
+            // Contract: active region extensions must stay on the contig
+            Assert.assertTrue(loc.getStart() > 0, "Active region extension begins at location " + loc.getStart() + ", past the left end of the contig");
+            int refLen = dictionary.getSequence(loc.getContigIndex()).getSequenceLength();
+            Assert.assertTrue(loc.getStop() <= refLen, "Active region extension ends at location " + loc.getStop() + ", past the right end of the contig");
+        }
+    }
+
+    @Test(enabled = true && !DEBUG, dataProvider = "TraversalEngineProvider")
+    public void testPrimaryReadMapping(TraverseActiveRegions t) {
+        DummyActiveRegionWalker walker = new DummyActiveRegionWalker(new GenomeLocSortedSet(genomeLocParser, intervals),
+                EnumSet.of(ActiveRegionReadState.PRIMARY),
+                true);
+
+        // Contract: Each read has the Primary state in a single region (or none)
+        // This is the region of maximum overlap for the read (earlier if tied)
+
+        // simple: Primary in 1:1-999
+        // overlap_equal: Primary in 1:1-999
+        // overlap_unequal: Primary in 1:1-999
+        // boundary_equal: Primary in 1:1000-1999, Non-Primary in 1:2000-2999
+        // boundary_unequal: Primary in 1:1000-1999, Non-Primary in 1:2000-2999
+        // boundary_1_pre: Primary in 1:1000-1999, Non-Primary in 1:2000-2999
+        // boundary_1_post: Primary in 1:1000-1999, Non-Primary in 1:2000-2999
+        // extended_and_np: Primary in 1:1-999, Non-Primary in 1:1000-1999, Extended in 1:2000-2999
+        // outside_intervals: none
+        // shard_boundary_1_pre: Primary in 1:14908-16384, Non-Primary in 1:16385-16927
+        // shard_boundary_1_post: Primary in 1:14908-16384, Non-Primary in 1:16385-16927
+        // shard_boundary_equal: Primary in 1:14908-16384, Non-Primary in 1:16385-16927
+        // simple20: Primary in 20:10000-10100
+
+        Map<GenomeLoc, ActiveRegion> activeRegions = getActiveRegions(t, walker, intervals);
+        ActiveRegion region;
+
+        region = activeRegions.get(genomeLocParser.createGenomeLoc("1", 1, 999));
+        verifyReadMapping(region, "simple", "overlap_equal", "overlap_unequal", "extended_and_np");
+
+        region = activeRegions.get(genomeLocParser.createGenomeLoc("1", 1000, 1999));
+        verifyReadMapping(region, "boundary_unequal", "boundary_1_pre", "boundary_equal", "boundary_1_post");
+
+        region = activeRegions.get(genomeLocParser.createGenomeLoc("1", 2000, 2999));
+        verifyReadMapping(region);
+
+        region = activeRegions.get(genomeLocParser.createGenomeLoc("1", 10000, 20000));
+        verifyReadMapping(region, "shard_boundary_1_pre", "shard_boundary_1_post", "shard_boundary_equal");
+
+        region = activeRegions.get(genomeLocParser.createGenomeLoc("20", 10000, 10100));
+        verifyReadMapping(region, "simple20");
+    }
+
+    @Test(enabled = true && ! DEBUG, dataProvider = "TraversalEngineProvider")
+    public void testNonPrimaryReadMapping(TraverseActiveRegions t) {
+        DummyActiveRegionWalker walker = new DummyActiveRegionWalker(new GenomeLocSortedSet(genomeLocParser, intervals),
+                EnumSet.of(ActiveRegionReadState.PRIMARY, ActiveRegionReadState.NONPRIMARY),
+                true);
+
+        // Contract: Each read has the Primary state in a single region (or none)
+        // This is the region of maximum overlap for the read (earlier if tied)
+
+        // Contract: Each read has the Non-Primary state in all other regions it overlaps
+
+        // simple: Primary in 1:1-999
+        // overlap_equal: Primary in 1:1-999
+        // overlap_unequal: Primary in 1:1-999
+        // boundary_equal: Primary in 1:1000-1999, Non-Primary in 1:2000-2999
+        // boundary_unequal: Primary in 1:1000-1999, Non-Primary in 1:2000-2999
+        // boundary_1_pre: Primary in 1:1000-1999, Non-Primary in 1:2000-2999
+        // boundary_1_post: Primary in 1:1000-1999, Non-Primary in 1:2000-2999
+        // extended_and_np: Primary in 1:1-999, Non-Primary in 1:1000-1999, Extended in 1:2000-2999
+        // outside_intervals: none
+        // shard_boundary_1_pre: Primary in 1:14908-16384, Non-Primary in 1:16385-16927
+        // shard_boundary_1_post: Primary in 1:14908-16384, Non-Primary in 1:16385-16927
+        // shard_boundary_equal: Primary in 1:14908-16384, Non-Primary in 1:16385-16927
+        // simple20: Primary in 20:10000-10100
+
+        Map<GenomeLoc, ActiveRegion> activeRegions = getActiveRegions(t, walker, intervals);
+        ActiveRegion region;
+
+        region = activeRegions.get(genomeLocParser.createGenomeLoc("1", 1, 999));
+        verifyReadMapping(region, "simple", "overlap_equal", "overlap_unequal", "extended_and_np");
+
+        region = activeRegions.get(genomeLocParser.createGenomeLoc("1", 1000, 1999));
+        verifyReadMapping(region, "boundary_equal", "boundary_unequal", "extended_and_np", "boundary_1_pre", "boundary_1_post");
+
+        region = activeRegions.get(genomeLocParser.createGenomeLoc("1", 2000, 2999));
+        verifyReadMapping(region, "boundary_equal", "boundary_unequal", "boundary_1_pre", "boundary_1_post");
+
+        region = activeRegions.get(genomeLocParser.createGenomeLoc("1", 10000, 20000));
+        verifyReadMapping(region, "shard_boundary_1_pre", "shard_boundary_1_post", "shard_boundary_equal");
+
+        region = activeRegions.get(genomeLocParser.createGenomeLoc("20", 10000, 10100));
+        verifyReadMapping(region, "simple20");
+    }
+
+    @Test(enabled = true && ! DEBUG, dataProvider = "TraversalEngineProvider")
+    public void testExtendedReadMapping(TraverseActiveRegions t) {
+        DummyActiveRegionWalker walker = new DummyActiveRegionWalker(new GenomeLocSortedSet(genomeLocParser, intervals),
+                EnumSet.of(ActiveRegionReadState.PRIMARY, ActiveRegionReadState.NONPRIMARY, ActiveRegionReadState.EXTENDED),
+                true);
+
+        // Contract: Each read has the Primary state in a single region (or none)
+        // This is the region of maximum overlap for the read (earlier if tied)
+
+        // Contract: Each read has the Non-Primary state in all other regions it overlaps
+        // Contract: Each read has the Extended state in regions where it only overlaps if the region is extended
+
+        // simple: Primary in 1:1-999
+        // overlap_equal: Primary in 1:1-999
+        // overlap_unequal: Primary in 1:1-999
+        // boundary_equal: Non-Primary in 1:1000-1999, Primary in 1:2000-2999
+        // boundary_unequal: Primary in 1:1000-1999, Non-Primary in 1:2000-2999
+        // boundary_1_pre: Primary in 1:1000-1999, Non-Primary in 1:2000-2999
+        // boundary_1_post: Non-Primary in 1:1000-1999, Primary in 1:2000-2999
+        // extended_and_np: Non-Primary in 1:1-999, Primary in 1:1000-1999, Extended in 1:2000-2999
+        // outside_intervals: none
+        // shard_boundary_1_pre: Primary in 1:14908-16384, Non-Primary in 1:16385-16927
+        // shard_boundary_1_post: Non-Primary in 1:14908-16384, Primary in 1:16385-16927
+        // shard_boundary_equal: Non-Primary in 1:14908-16384, Primary in 1:16385-16927
+        // simple20: Primary in 20:10000-10100
+
+        Map<GenomeLoc, ActiveRegion> activeRegions = getActiveRegions(t, walker, intervals);
+        ActiveRegion region;
+
+        region = activeRegions.get(genomeLocParser.createGenomeLoc("1", 1, 999));
+        verifyReadMapping(region, "simple", "overlap_equal", "overlap_unequal", "extended_and_np");
+
+        region = activeRegions.get(genomeLocParser.createGenomeLoc("1", 1000, 1999));
+        verifyReadMapping(region, "boundary_equal", "boundary_unequal", "extended_and_np", "boundary_1_pre", "boundary_1_post");
+
+        region = activeRegions.get(genomeLocParser.createGenomeLoc("1", 2000, 2999));
+        verifyReadMapping(region, "boundary_equal", "boundary_unequal", "extended_and_np", "boundary_1_pre", "boundary_1_post");
+
+        region = activeRegions.get(genomeLocParser.createGenomeLoc("1", 10000, 20000));
+        verifyReadMapping(region, "shard_boundary_1_pre", "shard_boundary_1_post", "shard_boundary_equal");
+
+        region = activeRegions.get(genomeLocParser.createGenomeLoc("20", 10000, 10100));
+        verifyReadMapping(region, "simple20");
+    }
+
+    @Test(enabled = true && ! DEBUG, dataProvider = "TraversalEngineProvider")
+    public void testUnmappedReads(TraverseActiveRegions t) {
+        // TODO
+    }
+
+    private void verifyReadMapping(ActiveRegion region, String... reads) {
+        Assert.assertNotNull(region, "Region was unexpectedly null");
+        final Set<String> regionReads = new HashSet<String>();
+        for (SAMRecord read : region.getReads()) {
+            Assert.assertFalse(regionReads.contains(read.getReadName()), "Duplicate reads detected in region " + region + " read " + read.getReadName());
+            regionReads.add(read.getReadName());
+        }
+
+        Collection<String> wantReads = new ArrayList<String>(Arrays.asList(reads));
+        for (SAMRecord read : region.getReads()) {
+            String regionReadName = read.getReadName();
+            Assert.assertTrue(wantReads.contains(regionReadName), "Read " + regionReadName + " incorrectly assigned to active region " + region);
+            wantReads.remove(regionReadName);
+        }
+
+        Assert.assertTrue(wantReads.isEmpty(), "Reads missing in active region " + region + ", wanted " + (wantReads.isEmpty() ? "" : wantReads.iterator().next()));
+    }
+
+    private Map<GenomeLoc, ActiveRegion> getActiveRegions(TraverseActiveRegions t, DummyActiveRegionWalker walker, List<GenomeLoc> intervals) {
+        return getActiveRegions(t, walker, intervals, testBAM);
+    }
+
+    private Map<GenomeLoc, ActiveRegion> getActiveRegions(TraverseActiveRegions t, DummyActiveRegionWalker walker, List<GenomeLoc> intervals, final File bam) {
+        for (LocusShardDataProvider dataProvider : createDataProviders(t, walker, intervals, bam))
+            t.traverse(walker, dataProvider, 0);
+
+        return walker.mappedActiveRegions;
+    }
+
+    private Collection<GenomeLoc> toSingleBaseLocs(GenomeLoc interval) {
+        List<GenomeLoc> bases = new ArrayList<GenomeLoc>();
+        if (interval.size() == 1)
+            bases.add(interval);
+        else {
+            for (int location = interval.getStart(); location <= interval.getStop(); location++)
+                bases.add(genomeLocParser.createGenomeLoc(interval.getContig(), location, location));
+        }
+
+        return bases;
+    }
+
+    private Collection<GenomeLoc> toSingleBaseLocs(List<GenomeLoc> intervals) {
+        Set<GenomeLoc> bases = new TreeSet<GenomeLoc>();    // for sorting and uniqueness
+        for (GenomeLoc interval : intervals)
+            bases.addAll(toSingleBaseLocs(interval));
+
+        return bases;
+    }
+
+    private void verifyEqualIntervals(List<GenomeLoc> aIntervals, List<GenomeLoc> bIntervals) {
+        Collection<GenomeLoc> aBases = toSingleBaseLocs(aIntervals);
+        Collection<GenomeLoc> bBases = toSingleBaseLocs(bIntervals);
+
+        Assert.assertTrue(aBases.size() == bBases.size(), "Interval lists have a differing number of bases: " + aBases.size() + " vs. " + bBases.size());
+
+        Iterator<GenomeLoc> aIter = aBases.iterator();
+        Iterator<GenomeLoc> bIter = bBases.iterator();
+        while (aIter.hasNext() && bIter.hasNext()) {
+            GenomeLoc aLoc = aIter.next();
+            GenomeLoc bLoc = bIter.next();
+            Assert.assertTrue(aLoc.equals(bLoc), "Interval locations do not match: " + aLoc + " vs. " + bLoc);
+        }
+    }
+
+    // copied from LocusViewTemplate
+    protected GATKSAMRecord buildSAMRecord(String readName, String contig, int alignmentStart, int alignmentEnd) {
+        SAMFileHeader header = ArtificialSAMUtils.createDefaultReadGroup(new SAMFileHeader(), "test", "test");
+        header.setSequenceDictionary(dictionary);
+        header.setSortOrder(SAMFileHeader.SortOrder.coordinate);
+        GATKSAMRecord record = new GATKSAMRecord(header);
+
+        record.setReadName(readName);
+        record.setReferenceIndex(dictionary.getSequenceIndex(contig));
+        record.setAlignmentStart(alignmentStart);
+
+        Cigar cigar = new Cigar();
+        int len = alignmentEnd - alignmentStart + 1;
+        cigar.add(new CigarElement(len, CigarOperator.M));
+        record.setCigar(cigar);
+        record.setReadString(new String(new char[len]).replace("\0", "A"));
+        record.setBaseQualities(new byte[len]);
+        record.setReadGroup(new GATKSAMReadGroupRecord(header.getReadGroup("test")));
+
+        return record;
+    }
+
+    private List<LocusShardDataProvider> createDataProviders(TraverseActiveRegions traverseActiveRegions, final Walker walker, List<GenomeLoc> intervals, File bamFile) {
+        GenomeAnalysisEngine engine = new GenomeAnalysisEngine();
+        engine.setGenomeLocParser(genomeLocParser);
+
+        Collection<SAMReaderID> samFiles = new ArrayList<SAMReaderID>();
+        SAMReaderID readerID = new SAMReaderID(bamFile, new Tags());
+        samFiles.add(readerID);
+
+        SAMDataSource dataSource = new SAMDataSource(samFiles, new ThreadAllocation(), null, genomeLocParser,
+                false,
+                ValidationStringency.STRICT,
+                null,
+                null,
+                new ValidationExclusion(),
+                new ArrayList<ReadFilter>(),
+                new ArrayList<ReadTransformer>(),
+                false, (byte)30, false, true, null, IntervalMergingRule.ALL);
+
+        engine.setReadsDataSource(dataSource);
+        final Set<String> samples = SampleUtils.getSAMFileSamples(dataSource.getHeader());
+
+        traverseActiveRegions.initialize(engine, walker);
+        List<LocusShardDataProvider> providers = new ArrayList<LocusShardDataProvider>();
+        for (Shard shard : dataSource.createShardIteratorOverIntervals(new GenomeLocSortedSet(genomeLocParser, intervals), new ActiveRegionShardBalancer())) {
+            for (WindowMaker.WindowMakerIterator window : new WindowMaker(shard, genomeLocParser, dataSource.seek(shard), shard.getGenomeLocs(), samples)) {
+                providers.add(new LocusShardDataProvider(shard, shard.getReadProperties(), genomeLocParser, window.getLocus(), window, reference, new ArrayList<ReferenceOrderedDataSource>()));
+            }
+        }
+
+        return providers;
+    }
+
+    // ---------------------------------------------------------------------------------------------------------
+    //
+    // Combinatorial tests to ensure reads are going into the right regions
+    //
+    // ---------------------------------------------------------------------------------------------------------
+
+    @DataProvider(name = "CombinatorialARTTilingProvider")
+    public Object[][] makeCombinatorialARTTilingProvider() {
+        final List<Object[]> tests = new LinkedList<Object[]>();
+
+        final List<Integer> starts = Arrays.asList(
+                1, // very start of the chromosome
+                ArtificialBAMBuilder.BAM_SHARD_SIZE - 100, // right before the shard boundary
+                ArtificialBAMBuilder.BAM_SHARD_SIZE + 100 // right after the shard boundary
+        );
+
+        final List<EnumSet<ActiveRegionReadState>> allReadStates = Arrays.asList(
+                EnumSet.of(ActiveRegionReadState.PRIMARY),
+                EnumSet.of(ActiveRegionReadState.PRIMARY, ActiveRegionReadState.NONPRIMARY),
+                EnumSet.of(ActiveRegionReadState.PRIMARY, ActiveRegionReadState.NONPRIMARY, ActiveRegionReadState.EXTENDED)
+        );
+
+        final int maxTests = Integer.MAX_VALUE;
+        int nTests = 0;
+        for ( final int readLength : Arrays.asList(100) ) {
+            for ( final int skips : Arrays.asList(0, 10) ) {
+                for ( final int start : starts ) {
+                    for ( final int nReadsPerLocus : Arrays.asList(1, 2) ) {
+                        for ( final int nLoci : Arrays.asList(1, 1000) ) {
+                            final ArtificialBAMBuilder bamBuilder = new ArtificialBAMBuilder(reference, nReadsPerLocus, nLoci);
+                            bamBuilder.setReadLength(readLength);
+                            bamBuilder.setSkipNLoci(skips);
+                            bamBuilder.setAlignmentStart(start);
+                            for ( EnumSet<ActiveRegionReadState> readStates : allReadStates ) {
+                                for ( final GenomeLocSortedSet activeRegions : enumerateActiveRegions(bamBuilder.getAlignmentStart(), bamBuilder.getAlignmentEnd())) {
+                                    nTests++;
+                                    if ( nTests < maxTests ) // && nTests == 1238 )
+                                        tests.add(new Object[]{new TraverseActiveRegions<>(), nTests, activeRegions, readStates, bamBuilder});
+                                }
+                            }
+                        }
+                    }
+                }
+            }
+        }
+
+        return tests.toArray(new Object[][]{});
+    }
+
+    private Collection<GenomeLocSortedSet> enumerateActiveRegions(final int start, final int stop) {
+        // should basically cut up entire region into equal sized chunks, of
+        // size 10, 20, 50, 100, etc, alternating skipping pieces so they are inactive
+        // Need to make sure we include some edge cases:
+        final List<GenomeLocSortedSet> activeRegions = new LinkedList<GenomeLocSortedSet>();
+
+        for ( final int stepSize : Arrays.asList(11, 29, 53, 97) ) {
+            for ( final boolean startWithActive : Arrays.asList(true, false) ) {
+                activeRegions.add(makeActiveRegionMask(start, stop, stepSize,  startWithActive));
+            }
+        }
+
+        // active region is the whole interval
+        activeRegions.add(new GenomeLocSortedSet(genomeLocParser, genomeLocParser.createGenomeLoc("1", start, stop)));
+
+        // active region extends up to the end of the data, but doesn't include start
+        activeRegions.add(new GenomeLocSortedSet(genomeLocParser, genomeLocParser.createGenomeLoc("1", start+10, stop)));
+
+        return activeRegions;
+    }
+
+    private GenomeLocSortedSet makeActiveRegionMask(final int start, final int stop, final int stepSize, final boolean startWithActive) {
+        final GenomeLocSortedSet active = new GenomeLocSortedSet(genomeLocParser);
+
+        boolean includeRegion = startWithActive;
+        for ( int left = start; left < stop; left += stepSize) {
+            final int right = left + stepSize;
+            final GenomeLoc region = genomeLocParser.createGenomeLoc("1", left, right);
+            if ( includeRegion )
+                active.add(region);
+            includeRegion = ! includeRegion;
+        }
+
+        return active;
+    }
+
+
+    @Test(enabled = true && ! DEBUG, dataProvider = "CombinatorialARTTilingProvider")
+    public void testARTReadsInActiveRegions(final TraverseActiveRegions<Integer, Integer> traversal, final int id, final GenomeLocSortedSet activeRegions, final EnumSet<ActiveRegionReadState> readStates, final ArtificialBAMBuilder bamBuilder) {
+        logger.warn("Running testARTReadsInActiveRegions id=" + id + " locs " + activeRegions + " against bam " + bamBuilder);
+        final List<GenomeLoc> intervals = Arrays.asList(
+                genomeLocParser.createGenomeLoc("1", bamBuilder.getAlignmentStart(), bamBuilder.getAlignmentEnd())
+        );
+
+        final DummyActiveRegionWalker walker = new DummyActiveRegionWalker(activeRegions, false);
+        walker.setStates(readStates);
+
+        final Map<GenomeLoc, ActiveRegion> activeRegionsMap = getActiveRegions(traversal, walker, intervals, bamBuilder.makeTemporarilyBAMFile());
+
+        final Set<String> alreadySeenReads = new HashSet<String>(); // for use with the primary / non-primary
+        for ( final ActiveRegion region : activeRegionsMap.values() ) {
+            final Set<String> readNamesInRegion = readNamesInRegion(region);
+            int nReadsExpectedInRegion = 0;
+            for ( final GATKSAMRecord read : bamBuilder.makeReads() ) {
+                final GenomeLoc readLoc = genomeLocParser.createGenomeLoc(read);
+
+                boolean shouldBeInRegion = readStates.contains(ActiveRegionReadState.EXTENDED)
+                        ? region.getExtendedLoc().overlapsP(readLoc)
+                        : region.getLocation().overlapsP(readLoc);
+
+                if ( ! readStates.contains(ActiveRegionReadState.NONPRIMARY) ) {
+                    if ( alreadySeenReads.contains(read.getReadName()) )
+                        shouldBeInRegion = false;
+                    else if ( shouldBeInRegion )
+                        alreadySeenReads.add(read.getReadName());
+                }
+
+                String msg = readNamesInRegion.contains(read.getReadName()) == shouldBeInRegion ? "" : "Region " + region +
+                        " failed contains read check: read " + read + " with span " + readLoc + " should be in region is " + shouldBeInRegion + " but I got the opposite";
+                Assert.assertEquals(readNamesInRegion.contains(read.getReadName()), shouldBeInRegion, msg);
+
+                nReadsExpectedInRegion += shouldBeInRegion ? 1 : 0;
+            }
+
+            Assert.assertEquals(region.size(), nReadsExpectedInRegion, "There are more reads in active region " + region + "than expected");
+        }
+    }
+
+    private Set<String> readNamesInRegion(final ActiveRegion region) {
+        final Set<String> readNames = new LinkedHashSet<String>(region.getReads().size());
+        for ( final SAMRecord read : region.getReads() )
+            readNames.add(read.getReadName());
+        return readNames;
+    }
+
+    // ---------------------------------------------------------------------------------------------------------
+    //
+    // Make sure all insertion reads are properly included in the active regions
+    //
+    // ---------------------------------------------------------------------------------------------------------
+
+    @Test(dataProvider = "TraversalEngineProvider", enabled = true && ! DEBUG)
+    public void ensureAllInsertionReadsAreInActiveRegions(final TraverseActiveRegions<Integer, Integer> traversal) {
+
+        final int readLength = 10;
+        final int start = 20;
+        final int nReadsPerLocus = 10;
+        final int nLoci = 3;
+
+        final ArtificialBAMBuilder bamBuilder = new ArtificialBAMBuilder(reference, nReadsPerLocus, nLoci);
+        bamBuilder.setReadLength(readLength);
+        bamBuilder.setAlignmentStart(start);
+
+        // note that the position must be +1 as the read's all I cigar puts the end 1 bp before start, leaving it out of the region
+        GATKSAMRecord allI = ArtificialSAMUtils.createArtificialRead(bamBuilder.getHeader(),"allI",0,start+1,readLength);
+        allI.setCigarString(readLength + "I");
+        allI.setReadGroup(new GATKSAMReadGroupRecord(bamBuilder.getHeader().getReadGroups().get(0)));
+
+        bamBuilder.addReads(allI);
+
+        final GenomeLocSortedSet activeRegions = new GenomeLocSortedSet(bamBuilder.getGenomeLocParser());
+        activeRegions.add(bamBuilder.getGenomeLocParser().createGenomeLoc("1", 10, 30));
+        final List<GenomeLoc> intervals = Arrays.asList(
+                genomeLocParser.createGenomeLoc("1", bamBuilder.getAlignmentStart(), bamBuilder.getAlignmentEnd())
+        );
+
+        final DummyActiveRegionWalker walker = new DummyActiveRegionWalker(activeRegions, false);
+
+        final Map<GenomeLoc, ActiveRegion> activeRegionsMap = getActiveRegions(traversal, walker, intervals, bamBuilder.makeTemporarilyBAMFile());
+
+        final ActiveRegion region = activeRegionsMap.values().iterator().next();
+        int nReadsExpectedInRegion = 0;
+
+        final Set<String> readNamesInRegion = readNamesInRegion(region);
+        for ( final GATKSAMRecord read : bamBuilder.makeReads() ) {
+            Assert.assertTrue(readNamesInRegion.contains(read.getReadName()),
+                    "Region " + region + " should contain read " + read + " with cigar " + read.getCigarString() + " but it wasn't");
+            nReadsExpectedInRegion++;
+        }
+
+        Assert.assertEquals(region.size(), nReadsExpectedInRegion, "There are more reads in active region " + region + "than expected");
+    }
+}
diff --git a/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/engine/traversals/TraverseDuplicatesUnitTest.java b/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/engine/traversals/TraverseDuplicatesUnitTest.java
new file mode 100644
index 0000000..a332be1
--- /dev/null
+++ b/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/engine/traversals/TraverseDuplicatesUnitTest.java
@@ -0,0 +1,162 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.engine.traversals;
+
+import htsjdk.samtools.SAMFileHeader;
+import htsjdk.samtools.SAMRecord;
+import org.broadinstitute.gatk.engine.GenomeAnalysisEngine;
+import org.testng.Assert;
+import org.broadinstitute.gatk.utils.BaseTest;
+import org.broadinstitute.gatk.utils.GenomeLocParser;
+import org.broadinstitute.gatk.utils.sam.ArtificialSAMUtils;
+
+import org.testng.annotations.BeforeMethod;
+
+import org.testng.annotations.Test;
+
+import java.io.File;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Set;
+
+
+/**
+ * @author aaron
+ *         <p/>
+ *         Class TraverseDuplicatesUnitTest
+ *         <p/>
+ *         test the meat of the traverse dupplicates.
+ */
+public class TraverseDuplicatesUnitTest extends BaseTest {
+
+    private TraverseDuplicates obj = new TraverseDuplicates();
+    private SAMFileHeader header;
+    private GenomeLocParser genomeLocParser;
+    private GenomeAnalysisEngine engine;
+    private File refFile = new File(validationDataLocation + "Homo_sapiens_assembly17.fasta");
+
+
+    @BeforeMethod
+    public void doBefore() {
+        header = ArtificialSAMUtils.createArtificialSamHeader(1, 1, 1000);
+        genomeLocParser =new GenomeLocParser(header.getSequenceDictionary());
+
+        engine = new GenomeAnalysisEngine();
+        engine.setReferenceDataSource(refFile);
+        engine.setGenomeLocParser(genomeLocParser);
+        
+        obj.initialize(engine, null);
+    }
+
+    @Test
+    public void testAllDuplicatesNoPairs() {
+        List<SAMRecord> list = new ArrayList<SAMRecord>();
+        for (int x = 0; x < 10; x++) {
+            SAMRecord read = ArtificialSAMUtils.createArtificialRead(header, "SWEET_READ" + x, 0, 1, 100);
+            read.setDuplicateReadFlag(true);
+            list.add(read);
+        }
+        Set<List<SAMRecord>> myPairings = obj.uniqueReadSets(list);
+        Assert.assertEquals(myPairings.size(), 1);
+        Assert.assertEquals(myPairings.iterator().next().size(), 10); // dup's
+    }
+
+    @Test
+    public void testNoDuplicatesNoPairs() {
+        List<SAMRecord> list = new ArrayList<SAMRecord>();
+        for (int x = 0; x < 10; x++) {
+            SAMRecord read = ArtificialSAMUtils.createArtificialRead(header, "SWEET_READ" + x, 0, 1, 100);
+            read.setDuplicateReadFlag(false);
+            list.add(read);
+        }
+
+        Set<List<SAMRecord>> myPairing = obj.uniqueReadSets(list);
+        Assert.assertEquals(myPairing.size(), 10); // unique
+    }
+
+    @Test
+    public void testFiftyFiftyNoPairs() {
+        List<SAMRecord> list = new ArrayList<SAMRecord>();
+        for (int x = 0; x < 5; x++) {
+            SAMRecord read = ArtificialSAMUtils.createArtificialRead(header, "SWEET_READ" + x, 0, 1, 100);
+            read.setDuplicateReadFlag(true);
+            list.add(read);
+        }
+        for (int x = 10; x < 15; x++)
+            list.add(ArtificialSAMUtils.createArtificialRead(header, String.valueOf(x), 0, x, 100));
+
+        Set<List<SAMRecord>> myPairing = obj.uniqueReadSets(list);
+        Assert.assertEquals(myPairing.size(), 6);  // unique
+    }
+
+    @Test
+    public void testAllDuplicatesAllPairs() {
+        List<SAMRecord> list = new ArrayList<SAMRecord>();
+        for (int x = 0; x < 10; x++) {
+            SAMRecord read = ArtificialSAMUtils.createArtificialRead(header, "SWEET_READ"+ x, 0, 1, 100);
+            read.setDuplicateReadFlag(true);
+            read.setMateAlignmentStart(100);
+            read.setMateReferenceIndex(0);
+            read.setReadPairedFlag(true);
+            list.add(read);
+        }
+
+        Set<List<SAMRecord>> myPairing = obj.uniqueReadSets(list);
+        Assert.assertEquals(myPairing.size(), 1);  // unique
+    }
+
+    @Test
+    public void testNoDuplicatesAllPairs() {
+        List<SAMRecord> list = new ArrayList<SAMRecord>();
+        for (int x = 0; x < 10; x++) {
+            SAMRecord read = ArtificialSAMUtils.createArtificialRead(header, "SWEET_READ"+ x, 0, 1, 100);
+            if (x == 0) read.setDuplicateReadFlag(true); // one is a dup but (next line)
+            read.setMateAlignmentStart(100); // they all have a shared start and mate start so they're dup's
+            read.setMateReferenceIndex(0);
+            read.setReadPairedFlag(true);
+            list.add(read);
+        }
+
+        Set<List<SAMRecord>> myPairing = obj.uniqueReadSets(list);
+        Assert.assertEquals(myPairing.size(), 1);  // unique
+    }
+
+    @Test
+    public void testAllDuplicatesAllPairsDifferentPairedEnd() {
+        List<SAMRecord> list = new ArrayList<SAMRecord>();
+        for (int x = 0; x < 10; x++) {
+            SAMRecord read = ArtificialSAMUtils.createArtificialRead(header, "SWEET_READ" + x, 0, 1, 100);
+            if (x == 0) read.setDuplicateReadFlag(true); // one is a dup
+            read.setMateAlignmentStart(100 + x);
+            read.setMateReferenceIndex(0);
+            read.setReadPairedFlag(true);
+            list.add(read);
+        }
+
+        Set<List<SAMRecord>> myPairing = obj.uniqueReadSets(list);
+        Assert.assertEquals(myPairing.size(), 10);  // unique
+    }
+}
diff --git a/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/engine/traversals/TraverseReadsUnitTest.java b/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/engine/traversals/TraverseReadsUnitTest.java
new file mode 100644
index 0000000..70336a2
--- /dev/null
+++ b/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/engine/traversals/TraverseReadsUnitTest.java
@@ -0,0 +1,166 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.engine.traversals;
+
+import htsjdk.samtools.reference.IndexedFastaSequenceFile;
+import htsjdk.samtools.reference.ReferenceSequenceFile;
+import org.broadinstitute.gatk.utils.BaseTest;
+import org.broadinstitute.gatk.utils.commandline.Tags;
+import org.broadinstitute.gatk.engine.GenomeAnalysisEngine;
+import org.broadinstitute.gatk.engine.datasources.providers.ReadShardDataProvider;
+import org.broadinstitute.gatk.engine.datasources.reads.*;
+import org.broadinstitute.gatk.engine.datasources.rmd.ReferenceOrderedDataSource;
+import org.broadinstitute.gatk.engine.resourcemanagement.ThreadAllocation;
+import org.broadinstitute.gatk.engine.walkers.ReadWalker;
+import org.broadinstitute.gatk.tools.walkers.qc.CountReads;
+import org.broadinstitute.gatk.utils.GenomeLocParser;
+import org.broadinstitute.gatk.utils.exceptions.UserException;
+import org.broadinstitute.gatk.utils.fasta.CachingIndexedFastaSequenceFile;
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.BeforeMethod;
+import org.testng.annotations.Test;
+
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
+import java.io.PrintStream;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+import static org.testng.Assert.fail;
+
+/**
+ *
+ * User: aaron
+ * Date: Apr 24, 2009
+ * Time: 3:42:16 PM
+ *
+ * The Broad Institute
+ * SOFTWARE COPYRIGHT NOTICE AGREEMENT 
+ * This software and its documentation are copyright 2009 by the
+ * Broad Institute/Massachusetts Institute of Technology. All rights are reserved.
+ *
+ * This software is supplied without any warranty or guaranteed support whatsoever. Neither
+ * the Broad Institute nor MIT can be responsible for its use, misuse, or functionality.
+ *
+ */
+
+
+/**
+ * @author aaron
+ * @version 1.0
+ * @date Apr 24, 2009
+ * <p/>
+ * Class TraverseReadsUnitTest
+ * <p/>
+ * test traversing reads
+ */
+public class TraverseReadsUnitTest extends BaseTest {
+
+    private ReferenceSequenceFile seq;
+    private SAMReaderID bam = new SAMReaderID(new File(validationDataLocation + "index_test.bam"),new Tags()); // TCGA-06-0188.aligned.duplicates_marked.bam");
+    private File refFile = new File(validationDataLocation + "Homo_sapiens_assembly17.fasta");
+    private List<SAMReaderID> bamList;
+    private ReadWalker countReadWalker;
+    private File output;
+    private TraverseReadsNano traversalEngine = null;
+
+    private IndexedFastaSequenceFile ref = null;
+    private GenomeLocParser genomeLocParser = null;
+    private GenomeAnalysisEngine engine = null;
+
+    @BeforeClass
+    public void doOnce() {
+        try {
+            ref = new CachingIndexedFastaSequenceFile(refFile);
+        }
+        catch(FileNotFoundException ex) {
+            throw new UserException.CouldNotReadInputFile(refFile,ex);
+        }
+        genomeLocParser = new GenomeLocParser(ref);
+
+        engine = new GenomeAnalysisEngine();
+        engine.setReferenceDataSource(refFile);
+        engine.setGenomeLocParser(genomeLocParser);
+    }
+
+    /**
+     * This function does the setup of our parser, before each method call.
+     * <p/>
+     * Called before every test case method.
+     */
+    @BeforeMethod
+    public void doForEachTest() {
+        output = new File("testOut.txt");
+        FileOutputStream out = null;
+        PrintStream ps; // declare a print stream object
+
+        try {
+            out = new FileOutputStream(output);
+        } catch (FileNotFoundException e) {
+            e.printStackTrace();  //To change body of catch statement use File | Settings | File Templates.
+            fail("Couldn't open the output file");
+        }
+
+        bamList = new ArrayList<SAMReaderID>();
+        bamList.add(bam);
+        countReadWalker = new CountReads();
+        
+        traversalEngine = new TraverseReadsNano(1);
+        traversalEngine.initialize(engine, countReadWalker);
+    }
+
+    /** Test out that we can shard the file and iterate over every read */
+    @Test
+    public void testUnmappedReadCount() {
+        SAMDataSource dataSource = new SAMDataSource(bamList,new ThreadAllocation(),null,genomeLocParser);
+        Iterable<Shard> shardStrategy = dataSource.createShardIteratorOverAllReads(new ReadShardBalancer());
+
+        countReadWalker.initialize();
+        Object accumulator = countReadWalker.reduceInit();
+
+        for(Shard shard: shardStrategy) {
+            if (shard == null) {
+                fail("Shard == null");
+            }
+
+            ReadShardDataProvider dataProvider = new ReadShardDataProvider(shard,genomeLocParser,dataSource.seek(shard),null, Collections.<ReferenceOrderedDataSource>emptyList());
+            accumulator = traversalEngine.traverse(countReadWalker, dataProvider, accumulator);
+            dataProvider.close();
+        }
+
+        countReadWalker.onTraversalDone(accumulator);
+
+        if (!(accumulator instanceof Long)) {
+            fail("Count read walker should return a Long.");
+        }
+        if (!accumulator.equals(new Long(10000))) {
+            fail("there should be 10000 mapped reads in the index file, there was " + (accumulator));
+        }
+    }
+
+}
diff --git a/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/engine/walkers/WalkerTest.java b/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/engine/walkers/WalkerTest.java
new file mode 100644
index 0000000..a4c896e
--- /dev/null
+++ b/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/engine/walkers/WalkerTest.java
@@ -0,0 +1,455 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.engine.walkers;
+
+import htsjdk.tribble.Tribble;
+import htsjdk.tribble.index.Index;
+import htsjdk.tribble.index.IndexFactory;
+import htsjdk.variant.bcf2.BCF2Utils;
+import htsjdk.variant.vcf.VCFCodec;
+import org.apache.commons.lang.StringUtils;
+import org.broadinstitute.gatk.engine.CommandLineExecutable;
+import org.broadinstitute.gatk.engine.CommandLineGATK;
+import org.broadinstitute.gatk.engine.GenomeAnalysisEngine;
+import org.broadinstitute.gatk.engine.phonehome.GATKRunReport;
+import org.broadinstitute.gatk.utils.BaseTest;
+import org.broadinstitute.gatk.utils.MD5DB;
+import org.broadinstitute.gatk.utils.MD5Mismatch;
+import org.broadinstitute.gatk.utils.Utils;
+import org.broadinstitute.gatk.utils.classloader.JVMUtils;
+import org.broadinstitute.gatk.utils.collections.Pair;
+import org.broadinstitute.gatk.utils.exceptions.GATKException;
+import org.broadinstitute.gatk.utils.exceptions.ReviewedGATKException;
+import org.testng.Assert;
+import org.testng.annotations.AfterSuite;
+import org.testng.annotations.BeforeMethod;
+
+import java.io.ByteArrayOutputStream;
+import java.io.File;
+import java.io.PrintStream;
+import java.text.SimpleDateFormat;
+import java.util.*;
+
+public class WalkerTest extends BaseTest {
+    private static final boolean GENERATE_SHADOW_BCF = true;
+    private static final boolean ENABLE_PHONE_HOME_FOR_TESTS = false;
+    private static final boolean ENABLE_ON_THE_FLY_CHECK_FOR_VCF_INDEX = false;
+    private static final boolean ENABLE_AUTO_INDEX_CREATION_AND_LOCKING_FOR_TESTS = false;
+
+    private static MD5DB md5DB = new MD5DB();
+
+    @BeforeMethod
+    public void initializeWalkerTests() {
+        logger.debug("Initializing walker tests");
+        GenomeAnalysisEngine.resetRandomGenerator();
+    }
+
+    @AfterSuite
+    public void finalizeWalkerTests() {
+        logger.debug("Finalizing walker tests");
+        md5DB.close();
+    }
+
+    public static MD5DB getMd5DB() {
+        return md5DB;
+    }
+
+    public void validateOutputBCFIfPossible(final String name, final File resultFile) {
+        final File bcfFile = BCF2Utils.shadowBCF(resultFile);
+        if ( bcfFile != null && bcfFile.exists() ) {
+            logger.warn("Checking shadow BCF output file " + bcfFile + " against VCF file " + resultFile);
+            try {
+                assertVCFandBCFFilesAreTheSame(resultFile, bcfFile);
+                logger.warn("  Shadow BCF PASSED!");
+            } catch ( Exception e ) {
+                Assert.fail("Exception received reading shadow BCFFile " + bcfFile + " for test " + name, e);
+            }
+        }
+    }
+
+    public void validateOutputIndex(final String name, final File resultFile) {
+        if ( !ENABLE_ON_THE_FLY_CHECK_FOR_VCF_INDEX )
+            return;
+
+        File indexFile = Tribble.indexFile(resultFile);
+        //System.out.println("Putative index file is " + indexFile);
+        if ( indexFile.exists() ) {
+            if ( resultFile.getAbsolutePath().contains(".vcf") ) {
+                // todo -- currently we only understand VCF files! Blow up since we can't test them
+                throw new GATKException("Found an index created for file " + resultFile + " but we can only validate VCF files.  Extend this code!");
+            }
+
+            System.out.println("Verifying on-the-fly index " + indexFile + " for test " + name + " using file " + resultFile);
+            Index indexFromOutputFile = IndexFactory.createDynamicIndex(resultFile, new VCFCodec());
+            Index dynamicIndex = IndexFactory.loadIndex(indexFile.getAbsolutePath());
+
+            if ( ! indexFromOutputFile.equalsIgnoreProperties(dynamicIndex) ) {
+                Assert.fail(String.format("Index on disk from indexing on the fly not equal to the index created after the run completed.  FileIndex %s vs. on-the-fly %s%n",
+                        indexFromOutputFile.getProperties(),
+                        dynamicIndex.getProperties()));
+            }
+        }
+    }
+
+    public List<String> assertMatchingMD5s(final String testName, final String testClassName, List<File> resultFiles, List<String> expectedMD5s) {
+        List<String> md5s = new ArrayList<String>();
+        List<MD5DB.MD5Match> fails = new ArrayList<MD5DB.MD5Match>();
+
+        for (int i = 0; i < resultFiles.size(); i++) {
+            MD5DB.MD5Match result = getMd5DB().testFileMD5(testName, testClassName, resultFiles.get(i), expectedMD5s.get(i), parameterize());
+            validateOutputBCFIfPossible(testName, resultFiles.get(i));
+            if ( ! result.failed ) {
+                validateOutputIndex(testName, resultFiles.get(i));
+                md5s.add(result.expectedMD5);
+            } else {
+                fails.add(result);
+            }
+        }
+
+        if ( ! fails.isEmpty() ) {
+            List<String> actuals = new ArrayList<String>();
+            List<String> expecteds = new ArrayList<String>();
+            List<String> diffEngineOutputs = new ArrayList<String>();
+
+            for ( final MD5DB.MD5Match fail : fails ) {
+                actuals.add(fail.actualMD5);
+                expecteds.add(fail.expectedMD5);
+                diffEngineOutputs.add(fail.diffEngineOutput);
+                logger.warn("Fail: " + fail.failMessage);
+            }
+
+            final MD5Mismatch failure = new MD5Mismatch(actuals, expecteds, diffEngineOutputs);
+            Assert.fail(failure.toString());
+        }
+
+        return md5s;
+    }
+
+    public String buildCommandLine(String... arguments) {
+        String cmdline = "";
+
+        for ( int argIndex = 0; argIndex < arguments.length; argIndex++ ) {
+            cmdline += arguments[argIndex];
+
+            if (argIndex < arguments.length - 1) {
+                cmdline += " ";
+            }
+        }
+
+        return cmdline;
+    }
+
+    public class WalkerTestSpec {
+        // Arguments implicitly included in all Walker command lines, unless explicitly
+        // disabled using the disableImplicitArgs() method below.
+        String args = "";
+        int nOutputFiles = -1;
+        List<String> md5s = null;
+        List<String> exts = null;
+        Class expectedException = null;
+        boolean includeImplicitArgs = true;
+        boolean includeShadowBCF = true;
+
+        // Name of the test class that created this test case
+        private Class testClass;
+
+        // the default output path for the integration test
+        private File outputFileLocation = null;
+
+        protected Map<String, File> auxillaryFiles = new HashMap<String, File>();
+
+        public WalkerTestSpec(String args, List<String> md5s) {
+            this(args, -1, md5s);
+        }
+
+        public WalkerTestSpec(String args, int nOutputFiles, List<String> md5s) {
+            this.args = args;
+            this.nOutputFiles = md5s.size();
+            this.md5s = md5s;
+            this.testClass = getCallingTestClass();
+        }
+
+        public WalkerTestSpec(String args, List<String> exts, List<String> md5s) {
+            this(args, -1, exts, md5s);
+        }
+
+        public WalkerTestSpec(String args, int nOutputFiles, List<String> exts, List<String> md5s) {
+            this.args = args;
+            this.nOutputFiles = md5s.size();
+            this.md5s = md5s;
+            this.exts = exts;
+            this.testClass = getCallingTestClass();
+        }
+
+        // @Test(expectedExceptions) doesn't work in integration tests, so use this instead
+        public WalkerTestSpec(String args, int nOutputFiles, Class expectedException) {
+            this.args = args;
+            this.nOutputFiles = nOutputFiles;
+            this.expectedException = expectedException;
+            this.testClass = getCallingTestClass();
+        }
+
+        private Class getCallingTestClass() {
+            return JVMUtils.getCallingClass(getClass());
+        }
+
+        public String getTestClassName() {
+            return testClass.getSimpleName();
+        }
+
+        public String getArgsWithImplicitArgs() {
+            String args = this.args;
+            if ( includeImplicitArgs ) {
+                args = args + (ENABLE_PHONE_HOME_FOR_TESTS ?
+                        String.format(" -et %s ", GATKRunReport.PhoneHomeOption.AWS) :
+                        String.format(" -et %s -K %s ", GATKRunReport.PhoneHomeOption.NO_ET, gatkKeyFile));
+                if ( includeShadowBCF && GENERATE_SHADOW_BCF )
+                    args = args + " --generateShadowBCF ";
+                if ( ! ENABLE_AUTO_INDEX_CREATION_AND_LOCKING_FOR_TESTS )
+                    args = args + " --disable_auto_index_creation_and_locking_when_reading_rods ";
+            }
+
+            return args;
+        }
+
+        /**
+         * In the case where the input VCF files are malformed and cannot be fixed
+         * this function tells the engine to not try to generate a shadow BCF
+         * which will ultimately blow up...
+         */
+        public void disableShadowBCF() { this.includeShadowBCF = false; }
+        public void setOutputFileLocation(File outputFileLocation) {
+            this.outputFileLocation = outputFileLocation;
+        }        
+
+        protected File getOutputFileLocation() {
+            return outputFileLocation;
+        }
+        
+        public boolean expectsException() {
+            return expectedException != null;
+        }
+
+        public Class getExpectedException() {
+            if ( ! expectsException() ) throw new ReviewedGATKException("Tried to get expection for walker test that doesn't expect one");
+            return expectedException;
+        }
+
+        public void addAuxFile(String expectededMD5sum, File outputfile) {
+            auxillaryFiles.put(expectededMD5sum, outputfile);
+        }
+
+        public void disableImplicitArgs() {
+            includeImplicitArgs = false;
+        }
+    }
+
+    protected boolean parameterize() {
+        return false;
+    }
+
+    public enum ParallelTestType {
+        TREE_REDUCIBLE,
+        NANO_SCHEDULED,
+        BOTH
+    }
+
+    protected Pair<List<File>, List<String>> executeTestParallel(final String name, WalkerTestSpec spec, ParallelTestType testType) {
+        final List<Integer> ntThreads  = testType == ParallelTestType.TREE_REDUCIBLE || testType == ParallelTestType.BOTH ? Arrays.asList(1, 4) : Collections.<Integer>emptyList();
+        final List<Integer> cntThreads = testType == ParallelTestType.NANO_SCHEDULED || testType == ParallelTestType.BOTH ? Arrays.asList(1, 4) : Collections.<Integer>emptyList();
+
+        return executeTest(name, spec, ntThreads, cntThreads);
+    }
+
+    protected Pair<List<File>, List<String>> executeTestParallel(final String name, WalkerTestSpec spec) {
+        return executeTestParallel(name, spec, ParallelTestType.TREE_REDUCIBLE);
+    }
+
+    protected Pair<List<File>, List<String>> executeTest(final String name, WalkerTestSpec spec, List<Integer> ntThreads, List<Integer> cpuThreads) {
+        String originalArgs = spec.args;
+        Pair<List<File>, List<String>> results = null;
+
+        boolean ran1 = false;
+        for ( int nt : ntThreads ) {
+            String extra = nt == 1 ? "" : (" -nt " + nt);
+            ran1 = ran1 || nt == 1;
+            spec.args = originalArgs + extra;
+            results = executeTest(name + "-nt-" + nt, spec);
+        }
+
+        for ( int nct : cpuThreads ) {
+            if ( nct != 1 ) {
+                String extra = " -nct " + nct;
+                spec.args = originalArgs + extra;
+                results = executeTest(name + "-cnt-" + nct, spec);
+            }
+        }
+
+        return results;
+    }
+
+    protected Pair<List<File>, List<String>> executeTest(final String name, WalkerTestSpec spec) {
+        List<File> tmpFiles = new ArrayList<File>();
+        for (int i = 0; i < spec.nOutputFiles; i++) {
+            String ext = spec.exts == null ? ".tmp" : "." + spec.exts.get(i);
+            File fl = createTempFile(String.format("walktest.tmp_param.%d", i), ext);
+
+            // Cleanup any potential shadow BCFs on exit too, if we're generating them
+            if ( spec.includeShadowBCF && GENERATE_SHADOW_BCF ) {
+                final File potentalShadowBCFFile = BCF2Utils.shadowBCF(fl);
+                potentalShadowBCFFile.deleteOnExit();
+                new File(potentalShadowBCFFile.getAbsolutePath() + Tribble.STANDARD_INDEX_EXTENSION).deleteOnExit();
+            }
+
+            tmpFiles.add(fl);
+        }
+
+        final String args = String.format(spec.getArgsWithImplicitArgs(), tmpFiles.toArray());
+        System.out.println(Utils.dupString('-', 80));
+
+        if ( spec.expectsException() ) {
+            // this branch handles the case were we are testing that a walker will fail as expected
+            return executeTest(name, spec.getTestClassName(), spec.getOutputFileLocation(), null, tmpFiles, args, spec.getExpectedException());
+        } else {
+            List<String> md5s = new LinkedList<String>();
+            md5s.addAll(spec.md5s);
+
+            // check to see if they included any auxillary files, if so add them to the list and set them to be deleted on exit
+            for (String md5 : spec.auxillaryFiles.keySet()) {
+                md5s.add(md5);
+                final File auxFile = spec.auxillaryFiles.get(md5);
+                auxFile.deleteOnExit();
+                tmpFiles.add(auxFile);
+            }
+            return executeTest(name, spec.getTestClassName(), spec.getOutputFileLocation(), md5s, tmpFiles, args, null);
+        }
+    }
+
+    private void qcMD5s(String name, List<String> md5s) {
+        final String exampleMD5 = "709a1f482cce68992c637da3cff824a8";
+        for (String md5 : md5s) {
+            if ( md5 == null )
+                throw new IllegalArgumentException("Null MD5 found in test " + name);
+            if ( md5.equals("") ) // ok
+                continue;
+            if ( ! StringUtils.isAlphanumeric(md5) )
+                throw new IllegalArgumentException("MD5 contains non-alphanumeric characters test " + name + " md5=" + md5);
+            if ( md5.length() != exampleMD5.length() )
+                throw new IllegalArgumentException("Non-empty MD5 of unexpected number of characters test " + name + " md5=" + md5);
+        }
+    }
+
+
+    /**
+     * execute the test, given the following:
+     * @param testName     the name of the test
+     * @param testClassName the name of the class that contains the test
+     * @param md5s     the list of md5s
+     * @param tmpFiles the temp file corresponding to the md5 list
+     * @param args     the argument list
+     * @param expectedException the expected exception or null
+     * @return a pair of file and string lists
+     */
+    private Pair<List<File>, List<String>> executeTest(String testName, String testClassName, File outputFileLocation, List<String> md5s, List<File> tmpFiles, String args, Class expectedException) {
+        if ( md5s != null ) qcMD5s(testName, md5s);
+
+        if (outputFileLocation != null)
+            args += " -o " + outputFileLocation.getAbsolutePath();
+        executeTest(testName, testClassName, args, expectedException);
+
+        if ( expectedException != null ) {
+            return null;
+        } else {
+            // we need to check MD5s
+            return new Pair<List<File>, List<String>>(tmpFiles, assertMatchingMD5s(testName, testClassName, tmpFiles, md5s));
+        }
+    }
+    
+    /**
+     * execute the test, given the following:
+     * @param testName      the name of the test
+     * @param testClassName the name of the class that contains the test
+     * @param args          the argument list
+     * @param expectedException the expected exception or null
+     */
+    private void executeTest(String testName, String testClassName, String args, Class expectedException) {
+        CommandLineGATK instance = new CommandLineGATK();
+        String[] command = Utils.escapeExpressions(args);
+        // run the executable
+        boolean gotAnException = false;
+        try {
+            final String now = new SimpleDateFormat("HH:mm:ss").format(new Date());
+            final String cmdline = Utils.join(" ",command);
+            System.out.println(String.format("[%s] Executing test %s:%s with GATK arguments: %s", now, testClassName, testName, cmdline));
+            // also write the command line to the HTML log for convenient follow-up
+            // do the replaceAll so paths become relative to the current
+            BaseTest.log(cmdline.replaceAll(publicTestDirRoot, "").replaceAll(privateTestDirRoot, ""));
+            CommandLineExecutable.start(instance, command);
+        } catch (Exception e) {
+            gotAnException = true;
+            if ( expectedException != null ) {
+                // we expect an exception
+                //System.out.println(String.format("Wanted exception %s, saw %s", expectedException, e.getClass()));
+                if ( expectedException.isInstance(e) ) {
+                    // it's the type we expected
+                    //System.out.println(String.format("  => %s PASSED", name));
+                } else {
+                    final String message = String.format("Test %s:%s expected exception %s but instead got %s with error message %s",
+                            testClassName, testName, expectedException, e.getClass(), e.getMessage());
+                    if ( e.getCause() != null ) {
+                        final ByteArrayOutputStream baos = new ByteArrayOutputStream();
+                        final PrintStream ps = new PrintStream(baos);
+                        e.getCause().printStackTrace(ps);
+                        BaseTest.log(message);
+                        BaseTest.log(baos.toString());
+                    }
+                    Assert.fail(message);
+                }
+            } else {
+                // we didn't expect an exception but we got one :-(
+                throw new RuntimeException(e);
+            }
+        }
+
+        // catch failures from the integration test
+        if ( expectedException != null ) {
+            if ( ! gotAnException )
+                // we expected an exception but didn't see it
+                Assert.fail(String.format("Test %s:%s expected exception %s but none was thrown", testClassName, testName, expectedException.toString()));
+        } else {
+            if ( CommandLineExecutable.result != 0) {
+                throw new RuntimeException("Error running the GATK with arguments: " + args);
+            }
+        }
+    }
+
+
+    protected File createTempFileFromBase(final String name) {
+        File fl = new File(name);
+        fl.deleteOnExit();
+        return fl;
+    }
+}
diff --git a/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/tools/CatVariantsIntegrationTest.java b/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/tools/CatVariantsIntegrationTest.java
new file mode 100644
index 0000000..f1b8d6e
--- /dev/null
+++ b/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/tools/CatVariantsIntegrationTest.java
@@ -0,0 +1,145 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.tools;
+
+import org.apache.commons.lang.StringUtils;
+import htsjdk.tribble.AbstractFeatureReader;
+import org.broadinstitute.gatk.utils.BaseTest;
+import org.broadinstitute.gatk.utils.MD5DB;
+import org.broadinstitute.gatk.utils.MD5Mismatch;
+import org.broadinstitute.gatk.utils.runtime.ProcessController;
+import org.broadinstitute.gatk.utils.runtime.ProcessSettings;
+import org.broadinstitute.gatk.utils.runtime.RuntimeUtils;
+import org.testng.Assert;
+import org.testng.annotations.DataProvider;
+import org.testng.annotations.Test;
+
+import java.io.File;
+import java.io.IOException;
+
+public class CatVariantsIntegrationTest {
+    private final MD5DB md5db = new MD5DB();
+    private final File CatVariantsDir = new File(BaseTest.privateTestDir, "CatVariants");
+    private final File CatVariantsVcf1 = new File(CatVariantsDir, "CatVariantsTest1.vcf");
+    private final File CatVariantsVcf2 = new File(CatVariantsDir, "CatVariantsTest2.vcf");
+    private final File CatVariantsBcf1 = new File(CatVariantsDir, "CatVariantsTest1.bcf");
+    private final File CatVariantsBcf2 = new File(CatVariantsDir, "CatVariantsTest2.bcf");
+
+    private class CatVariantsTestProvider extends BaseTest.TestDataProvider {
+        private final File file1;
+        private final File file2;
+        public final File outputFile;
+        public final String md5;
+
+        private CatVariantsTestProvider(final File file1, final File file2, final File outputFile, final String md5) {
+            super(CatVariantsTestProvider.class);
+
+            this.file1 = file1;
+            this.file2 = file2;
+            this.outputFile = outputFile;
+            this.md5 = md5;
+        }
+
+        public final String getCmdLine() {
+            return String.format("java -cp %s %s -R %s -V %s -V %s -out %s",
+                    StringUtils.join(RuntimeUtils.getAbsoluteClassPaths(), File.pathSeparatorChar),
+                    CatVariants.class.getCanonicalName(), BaseTest.b37KGReference, file1, file2, outputFile);
+        }
+
+        public String toString() {
+            return "CatVariantsTestProvider " + outputFile;
+        }
+    }
+
+    @DataProvider(name = "ExtensionsTest")
+    public Object[][] makeExtensionsTestProvider() {
+        final File catVariantsTempList1 = BaseTest.createTempListFile("CatVariantsTest1", CatVariantsVcf1.getAbsolutePath());
+        final File catVariantsTempList2 = BaseTest.createTempListFile("CatVariantsTest2", CatVariantsVcf2.getAbsolutePath());
+
+        new CatVariantsTestProvider(CatVariantsVcf1, CatVariantsVcf2, BaseTest.createTempFile("CatVariantsTest", ".vcf"), "d0d81eb7fd3905256c4ac7c0fc480094");
+        new CatVariantsTestProvider(CatVariantsBcf1, CatVariantsBcf2, BaseTest.createTempFile("CatVariantsTest", ".bcf"), "6a57fcbbf3cae490896d13a288670d83");
+
+        for (String extension : AbstractFeatureReader.BLOCK_COMPRESSED_EXTENSIONS) {
+            final File file1 = new File(CatVariantsDir, "CatVariantsTest1.vcf" + extension);
+            final File file2 = new File(CatVariantsDir, "CatVariantsTest2.vcf" + extension);
+            final File outputFile = BaseTest.createTempFile("CatVariantsTest", ".vcf" + extension);
+            new CatVariantsTestProvider(file1, file2, outputFile, "33f728ac5c70ce2994f3619a27f47088");
+        }
+
+        //Test list parsing functionality
+        new CatVariantsTestProvider(catVariantsTempList1, CatVariantsVcf2, BaseTest.createTempFile("CatVariantsTest", ".vcf"), "d0d81eb7fd3905256c4ac7c0fc480094");
+        new CatVariantsTestProvider(CatVariantsVcf1, catVariantsTempList2, BaseTest.createTempFile("CatVariantsTest", ".vcf"), "d0d81eb7fd3905256c4ac7c0fc480094");
+        new CatVariantsTestProvider(catVariantsTempList1, catVariantsTempList2, BaseTest.createTempFile("CatVariantsTest", ".vcf"), "d0d81eb7fd3905256c4ac7c0fc480094");
+
+        return CatVariantsTestProvider.getTests(CatVariantsTestProvider.class);
+    }
+
+    @Test(dataProvider = "ExtensionsTest")
+    public void testExtensions(final CatVariantsTestProvider cfg) throws IOException {
+
+        ProcessController pc = ProcessController.getThreadLocal();
+        ProcessSettings ps = new ProcessSettings(cfg.getCmdLine().split("\\s+"));
+        pc.execAndCheck(ps);
+
+        MD5DB.MD5Match result = md5db.testFileMD5("testExtensions", "CatVariantsTestProvider", cfg.outputFile, cfg.md5, false);
+        if(result.failed) {
+            final MD5Mismatch failure = new MD5Mismatch(result.actualMD5, result.expectedMD5, result.diffEngineOutput);
+            Assert.fail(failure.toString());
+        }
+    }
+
+    @Test(expectedExceptions = IOException.class)
+    public void testMismatchedExtensions1() throws IOException {
+
+        String cmdLine = String.format("java -cp %s %s -R %s -V %s -V %s -out %s",
+                StringUtils.join(RuntimeUtils.getAbsoluteClassPaths(), File.pathSeparatorChar),
+                CatVariants.class.getCanonicalName(),
+                BaseTest.b37KGReference,
+                CatVariantsVcf1,
+                CatVariantsVcf2,
+                BaseTest.createTempFile("CatVariantsTest", ".bcf"));
+
+        ProcessController pc = ProcessController.getThreadLocal();
+        ProcessSettings ps = new ProcessSettings(cmdLine.split("\\s+"));
+        pc.execAndCheck(ps);
+    }
+
+    @Test(expectedExceptions = IOException.class)
+    public void testMismatchedExtensions2() throws IOException {
+
+        String cmdLine = String.format("java -cp %s %s -R %s -V %s -V %s -out %s",
+                StringUtils.join(RuntimeUtils.getAbsoluteClassPaths(), File.pathSeparatorChar),
+                CatVariants.class.getCanonicalName(),
+                BaseTest.b37KGReference,
+                CatVariantsVcf1,
+                CatVariantsBcf2,
+                BaseTest.createTempFile("CatVariantsTest", ".vcf"));
+
+        ProcessController pc = ProcessController.getThreadLocal();
+        ProcessSettings ps = new ProcessSettings(cmdLine.split("\\s+"));
+        pc.execAndCheck(ps);
+    }
+}
\ No newline at end of file
diff --git a/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/tools/walkers/BAQIntegrationTest.java b/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/tools/walkers/BAQIntegrationTest.java
new file mode 100644
index 0000000..68451ef
--- /dev/null
+++ b/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/tools/walkers/BAQIntegrationTest.java
@@ -0,0 +1,55 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.tools.walkers;
+
+import org.broadinstitute.gatk.engine.walkers.WalkerTest;
+import org.testng.annotations.Test;
+
+import java.util.Arrays;
+
+public class BAQIntegrationTest extends WalkerTest {
+    private final static String baseCommand = "-T PrintReads -R " + b36KGReference +
+            " -I " + validationDataLocation + "NA12878.1kg.p2.chr1_10mb_11_mb.allTechs.bam" +
+            " -o %s" +
+            " -L 1:10,000,000-10,100,000";
+
+    // --------------------------------------------------------------------------------------------------------------
+    //
+    // testing BAQ with SLX, 454, and SOLID data
+    //
+    // --------------------------------------------------------------------------------------------------------------
+    @Test
+    public void testPrintReadsNoBAQ() {
+        WalkerTestSpec spec = new WalkerTestSpec( baseCommand +" -baq OFF",  1, Arrays.asList("d1f74074e718c82810512bf40dbc7f72"));
+        executeTest(String.format("testPrintReadsNoBAQ"), spec);
+    }
+
+    @Test
+    public void testPrintReadsRecalBAQ() {
+        WalkerTestSpec spec = new WalkerTestSpec( baseCommand +" -baq RECALCULATE",  1, Arrays.asList("96ec97cf92f1f660bd5244c6b44539b3"));
+        executeTest(String.format("testPrintReadsRecalBAQ"), spec);
+    }
+}
diff --git a/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/tools/walkers/CNV/SymbolicAllelesIntegrationTest.java b/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/tools/walkers/CNV/SymbolicAllelesIntegrationTest.java
new file mode 100644
index 0000000..16e47cd
--- /dev/null
+++ b/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/tools/walkers/CNV/SymbolicAllelesIntegrationTest.java
@@ -0,0 +1,63 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.tools.walkers.CNV;
+
+import org.broadinstitute.gatk.engine.walkers.WalkerTest;
+import org.testng.annotations.Test;
+
+import java.util.Arrays;
+
+public class SymbolicAllelesIntegrationTest extends WalkerTest {
+
+    public static String baseTestString(String reference, String VCF) {
+        return "-T CombineVariants" +
+                " -R " + reference +
+                " --variant:vcf " + privateTestDir + VCF +
+                " -filteredRecordsMergeType KEEP_IF_ANY_UNFILTERED" +
+                " -genotypeMergeOptions REQUIRE_UNIQUE" +
+                " -setKey null" +
+                " -o %s" +
+                " --no_cmdline_in_header";
+    }
+
+    @Test(enabled = true)
+    public void test1() {
+        WalkerTestSpec spec = new WalkerTestSpec(
+                baseTestString(b36KGReference, "symbolic_alleles_1.vcf"),
+                1,
+                Arrays.asList("5bafc5a99ea839e686e55de93f91fd5c"));
+        executeTest("Test symbolic alleles", spec);
+    }
+
+    @Test(enabled = true)
+    public void test2() {
+        WalkerTestSpec spec = new WalkerTestSpec(
+                baseTestString(b36KGReference, "symbolic_alleles_2.vcf"),
+                1,
+                Arrays.asList("30f66a097987330d42e87da8bcd6be21"));
+        executeTest("Test symbolic alleles mixed in with non-symbolic alleles", spec);
+    }
+}
diff --git a/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/tools/walkers/annotator/SnpEffUtilUnitTest.java b/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/tools/walkers/annotator/SnpEffUtilUnitTest.java
new file mode 100644
index 0000000..ec10d7d
--- /dev/null
+++ b/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/tools/walkers/annotator/SnpEffUtilUnitTest.java
@@ -0,0 +1,111 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.tools.walkers.annotator;
+
+/**
+ * Created with IntelliJ IDEA.
+ * User: farjoun
+ * Date: 6/5/13
+ * Time: 2:31 PM
+ * To change this template use File | Settings | File Templates.
+ */
+
+
+import org.broadinstitute.gatk.tools.walkers.annotator.SnpEff.EffectType;
+import org.testng.Assert;
+import org.testng.annotations.DataProvider;
+import org.testng.annotations.Test;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public class SnpEffUtilUnitTest {
+
+
+    @DataProvider(name="effects")
+    public Object[][] childParentpairs() {
+        List<Object[]> tests = new ArrayList<Object[]>();
+
+        tests.add(new Object[]{EffectType.GENE,EffectType.CHROMOSOME});
+        tests.add(new Object[]{EffectType.UTR_3_PRIME,EffectType.TRANSCRIPT});
+        tests.add(new Object[]{EffectType.CODON_CHANGE,EffectType.CDS});
+        tests.add(new Object[]{EffectType.STOP_GAINED,EffectType.EXON});
+        tests.add(new Object[]{EffectType.SYNONYMOUS_START,EffectType.TRANSCRIPT});
+        tests.add(new Object[]{EffectType.FRAME_SHIFT,EffectType.CDS});
+        tests.add(new Object[]{EffectType.UPSTREAM,EffectType.INTERGENIC});
+        tests.add(new Object[]{EffectType.SPLICE_SITE_DONOR,EffectType.INTRON});
+        tests.add(new Object[]{EffectType.SPLICE_SITE_ACCEPTOR,EffectType.INTRON});
+        tests.add(new Object[]{EffectType.STOP_LOST,EffectType.NON_SYNONYMOUS_CODING});
+        return tests.toArray(new Object[][]{});
+    }
+
+    @DataProvider(name="self")
+    public Object[][] childEqualsParentpairs() {
+        List<Object[]> tests = new ArrayList<Object[]>();
+
+        for(EffectType type:EffectType.values()){
+            tests.add(new Object[]{type,type});
+        }
+        return tests.toArray(new Object[][]{});
+    }
+
+    @DataProvider(name="noneffects")
+    public Object[][] nonchildParentpairs() {
+        List<Object[]> tests = new ArrayList<Object[]>();
+
+        tests.add(new Object[]{EffectType.START_GAINED,EffectType.NON_SYNONYMOUS_CODING});
+        tests.add(new Object[]{EffectType.GENE,EffectType.NONE});
+        tests.add(new Object[]{EffectType.UTR_3_PRIME,EffectType.CDS});
+        tests.add(new Object[]{EffectType.CODON_CHANGE,EffectType.REGULATION});
+        tests.add(new Object[]{EffectType.DOWNSTREAM,EffectType.REGULATION});
+        tests.add(new Object[]{EffectType.SPLICE_SITE_ACCEPTOR,EffectType.EXON});
+        tests.add(new Object[]{EffectType.START_GAINED,EffectType.SYNONYMOUS_START});
+        tests.add(new Object[]{EffectType.NON_SYNONYMOUS_CODING,EffectType.DOWNSTREAM});
+        tests.add(new Object[]{EffectType.CODON_DELETION,EffectType.INTRON});
+        tests.add(new Object[]{EffectType.UTR_5_PRIME,EffectType.EXON_DELETED});
+        tests.add(new Object[]{EffectType.INTRON,EffectType.NONE});
+
+        return tests.toArray(new Object[][]{});
+    }
+
+    @Test(dataProvider = "effects")
+    public void testSubType(EffectType subType,EffectType parentType) {
+        Assert.assertTrue(SnpEffUtil.isSubTypeOf(subType,parentType),String.format("testing that %s is subtype of %s.",subType,parentType));
+    }
+    @Test(dataProvider = "self")
+    public void testSubTypeSelf(EffectType subType,EffectType parentType) {
+        Assert.assertTrue(SnpEffUtil.isSubTypeOf(subType,parentType),String.format("testing that %s is subtype of %s.",subType,parentType));
+    }
+    @Test(dataProvider = "effects")
+    public void testNonSubTypeSelf(EffectType parentType,EffectType subType) {
+        Assert.assertTrue(!SnpEffUtil.isSubTypeOf(subType,parentType),String.format("testing that %s is subtype of %s.",subType,parentType));
+    }
+    @Test(dataProvider = "noneffects")
+    public void testNonSubType(EffectType subType,EffectType parentType) {
+        Assert.assertTrue(!SnpEffUtil.isSubTypeOf(subType, parentType), String.format("testing that %s is NOT subtype of %s.", subType, parentType));
+        Assert.assertTrue(!SnpEffUtil.isSubTypeOf(parentType,subType), String.format("testing that %s is NOT subtype of %s.", parentType,subType));
+    }
+}
diff --git a/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/tools/walkers/coverage/CallableLociIntegrationTest.java b/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/tools/walkers/coverage/CallableLociIntegrationTest.java
new file mode 100644
index 0000000..b597947
--- /dev/null
+++ b/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/tools/walkers/coverage/CallableLociIntegrationTest.java
@@ -0,0 +1,69 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.tools.walkers.coverage;
+
+import org.broadinstitute.gatk.engine.walkers.WalkerTest;
+import org.testng.annotations.Test;
+
+import java.util.Arrays;
+
+public class CallableLociIntegrationTest extends WalkerTest {
+    final static String commonArgs     = "-R " + b36KGReference + " -T CallableLoci -I " + validationDataLocation + "/NA12878.1kg.p2.chr1_10mb_11_mb.SLX.bam -o %s";
+
+    final static String SUMMARY_MD5 = "a6f5963669f19d9d137ced87d65834b0";
+
+    @Test
+    public void testCallableLociWalkerBed() {
+        String gatk_args = commonArgs + " -format BED -L 1:10,000,000-11,000,000 -summary %s";
+        WalkerTestSpec spec = new WalkerTestSpec(gatk_args, 2,
+                Arrays.asList("9b4ffea1dbcfefadeb1c9fa74b0e0e59", SUMMARY_MD5));
+        executeTest("formatBed", spec);
+    }
+
+    @Test
+    public void testCallableLociWalkerPerBase() {
+        String gatk_args = commonArgs + " -format STATE_PER_BASE -L 1:10,000,000-11,000,000 -summary %s";
+        WalkerTestSpec spec = new WalkerTestSpec(gatk_args, 2,
+                Arrays.asList("d6505e489899e80c08a7168777f6e07b", SUMMARY_MD5));
+        executeTest("format_state_per_base", spec);
+    }
+    
+    @Test
+    public void testCallableLociWalker2() {
+        String gatk_args = commonArgs + " -format BED -L 1:10,000,000-10,000,100 -L 1:10,000,110-10,000,120 -summary %s";
+        WalkerTestSpec spec = new WalkerTestSpec(gatk_args, 2,
+                Arrays.asList("330f476085533db92a9dbdb3a127c041", "d287510eac04acf5a56f5cde2cba0e4a"));
+        executeTest("formatBed by interval", spec);
+    }
+
+    @Test
+    public void testCallableLociWalker3() {
+        String gatk_args = commonArgs + " -format BED -L 1:10,000,000-11,000,000 -minDepth 10 -maxDepth 100 --minBaseQuality 10 --minMappingQuality 20 -summary %s";
+        WalkerTestSpec spec = new WalkerTestSpec(gatk_args, 2,
+                Arrays.asList("7f79ad8195c4161060463eeb21d2bb11", "7ee269e5f4581a924529a356cc806e55"));
+        executeTest("formatBed lots of arguments", spec);
+    }
+}
diff --git a/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/tools/walkers/coverage/CompareCallableLociWalkerIntegrationTest.java b/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/tools/walkers/coverage/CompareCallableLociWalkerIntegrationTest.java
new file mode 100644
index 0000000..ccfd743
--- /dev/null
+++ b/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/tools/walkers/coverage/CompareCallableLociWalkerIntegrationTest.java
@@ -0,0 +1,42 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.tools.walkers.coverage;
+
+import org.broadinstitute.gatk.engine.walkers.WalkerTest;
+import org.testng.annotations.Test;
+
+import java.util.Arrays;
+
+public class CompareCallableLociWalkerIntegrationTest extends WalkerTest {
+    final static String commonArgs = "-R " + hg18Reference + " -T CompareCallableLoci --comp1:Bed " + validationDataLocation + "1kg_slx.chr1_10mb.callable.bed --comp2:Bed " + validationDataLocation + "ga2_slx.chr1_10mb.callable.bed -o %s";
+
+    @Test
+    public void testCompareCallableLociWalker1() {
+        String gatk_args = commonArgs + " -L chr1:1-10,000,000";
+        WalkerTestSpec spec = new WalkerTestSpec(gatk_args, 1, Arrays.asList("70efebac55ff210bb022e9e22ed80a95"));
+        executeTest("CompareCallableLoci Walker", spec);
+    }
+}
diff --git a/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/tools/walkers/coverage/DepthOfCoverageB36IntegrationTest.java b/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/tools/walkers/coverage/DepthOfCoverageB36IntegrationTest.java
new file mode 100644
index 0000000..447515d
--- /dev/null
+++ b/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/tools/walkers/coverage/DepthOfCoverageB36IntegrationTest.java
@@ -0,0 +1,111 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.tools.walkers.coverage;
+
+import org.broadinstitute.gatk.engine.walkers.WalkerTest;
+import org.testng.annotations.Test;
+
+import java.io.File;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+/**
+ * IF THERE IS NO JAVADOC RIGHT HERE, YELL AT chartl
+ *
+ * @Author chartl
+ * @Date May 20, 2010
+ */
+public class DepthOfCoverageB36IntegrationTest extends WalkerTest {
+
+    private boolean RUN_TESTS = true;
+    private String root = "-T DepthOfCoverage ";
+
+    private String buildRootCmd(String ref, List<String> bams, List<String> intervals) {
+        StringBuilder bamBuilder = new StringBuilder();
+        do {
+            bamBuilder.append(" -I ");
+            bamBuilder.append(bams.remove(0));
+        } while ( bams.size() > 0 );
+
+        StringBuilder intervalBuilder = new StringBuilder();
+        do {
+            intervalBuilder.append(" -L ");
+            intervalBuilder.append(intervals.remove(0));
+        } while ( intervals.size() > 0 );
+
+
+        return root + "-R "+ref+bamBuilder.toString()+intervalBuilder.toString();
+    }
+
+    private void execute(String name, WalkerTest.WalkerTestSpec spec) {
+        if ( RUN_TESTS ) {
+            executeTest(name,spec);
+        }
+    }
+
+    @Test
+    public void testMapQ0Only() {
+        String[] intervals = {"1:10,000,000-10,002,000","1:10,003,000-10,004,000"};
+        String[] bams = {"/humgen/gsa-hpprojects/GATK/data/Validation_Data/NA12878.1kg.p2.chr1_10mb_11_mb.allTechs.bam"};
+
+        String cmd = buildRootCmd(b36KGReference,new ArrayList<String>(Arrays.asList(bams)), new ArrayList<String>(Arrays.asList(intervals))) + " --maxMappingQuality 0";
+
+        WalkerTestSpec spec = new WalkerTestSpec(cmd,0,new ArrayList<String>());
+
+        // our base file
+        final File baseOutputFile = createTempFile("depthofcoveragemapq0",".tmp");
+
+        spec.setOutputFileLocation(baseOutputFile);
+        spec.addAuxFile("f39af6ad99520fd4fb27b409ab0344a0",baseOutputFile);
+        spec.addAuxFile("6b15f5330414b6d4e2f6caea42139fa1", createTempFileFromBase(baseOutputFile.getAbsolutePath()+".sample_cumulative_coverage_counts"));
+        spec.addAuxFile("cc6640d82077991dde8a2b523935cdff", createTempFileFromBase(baseOutputFile.getAbsolutePath()+".sample_cumulative_coverage_proportions"));
+        spec.addAuxFile("0fb627234599c258a3fee1b2703e164a", createTempFileFromBase(baseOutputFile.getAbsolutePath()+".sample_interval_statistics"));
+        spec.addAuxFile("cb73a0fa0cee50f1fb8f249315d38128", createTempFileFromBase(baseOutputFile.getAbsolutePath()+".sample_interval_summary"));
+        spec.addAuxFile("347b47ef73fbd4e277704ddbd7834f69", createTempFileFromBase(baseOutputFile.getAbsolutePath()+".sample_statistics"));
+        spec.addAuxFile("4ec920335d4b9573f695c39d62748089", createTempFileFromBase(baseOutputFile.getAbsolutePath()+".sample_summary"));
+
+
+        execute("testMapQ0Only",spec);
+    }
+
+    @Test
+    public void testLotsOfSamples() {
+        final String[] intervals = {"1:1105290-1105295"};
+        final String[] bams = {"/humgen/gsa-hpprojects/GATK/data/Validation_Data/pilot3.CEU+TSI.5loci.bam"};
+        final String cmd = buildRootCmd(b36KGReference, new ArrayList<String>(Arrays.asList(bams)), new ArrayList<String>(Arrays.asList(intervals)));
+
+        final WalkerTestSpec spec = new WalkerTestSpec(cmd,0,new ArrayList<String>());
+
+        final File baseOutputFile = createTempFile("testManySamples",".tmp");
+        
+        spec.setOutputFileLocation(baseOutputFile);
+        spec.addAuxFile("c9561b52344536d2b06ab97b0bb1a234",baseOutputFile);
+
+        execute("testLotsOfSamples",spec);
+    }
+
+}
diff --git a/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/tools/walkers/coverage/DepthOfCoverageIntegrationTest.java b/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/tools/walkers/coverage/DepthOfCoverageIntegrationTest.java
new file mode 100644
index 0000000..61785e8
--- /dev/null
+++ b/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/tools/walkers/coverage/DepthOfCoverageIntegrationTest.java
@@ -0,0 +1,181 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.tools.walkers.coverage;
+
+import org.broadinstitute.gatk.engine.walkers.WalkerTest;
+import org.testng.annotations.Test;
+
+import java.io.File;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+/**
+ * Integration tests for the Depth of Coverage walker
+ *
+ * @Author chartl
+ * @Date Feb 25, 2010
+ */
+public class DepthOfCoverageIntegrationTest extends WalkerTest {
+
+    private boolean RUN_TESTS = true;
+    private String root = "-T DepthOfCoverage ";
+
+    private String buildRootCmd(String ref, List<String> bams, List<String> intervals) {
+        StringBuilder bamBuilder = new StringBuilder();
+        do {
+            bamBuilder.append(" -I ");
+            bamBuilder.append(bams.remove(0));
+        } while ( bams.size() > 0 );
+
+        StringBuilder intervalBuilder = new StringBuilder();
+        do {
+            intervalBuilder.append(" -L ");
+            intervalBuilder.append(intervals.remove(0));
+        } while ( intervals.size() > 0 );
+
+
+        return root + "-R "+ref+bamBuilder.toString()+intervalBuilder.toString();
+    }
+
+    private void execute(String name, WalkerTestSpec spec) {
+        if ( RUN_TESTS ) {
+            executeTest(name,spec);
+        }
+    }
+
+    @Test
+    public void testBaseOutputNoFiltering() {
+        final String[] intervals = {"/humgen/gsa-hpprojects/GATK/data/Validation_Data/fhs_jhs_30_targts.interval_list"};
+        final String[] bams = {"/humgen/gsa-hpprojects/GATK/data/Validation_Data/FHS_indexed_subset.bam"};
+
+        final String cmd = buildRootCmd(hg18Reference,new ArrayList<>(Arrays.asList(bams)),new ArrayList<>(Arrays.asList(intervals))) + " -mmq 0 -mbq 0 -dels -baseCounts -pt readgroup -pt sample -pt library --outputFormat csv -ct 10 -ct 15 -ct 20 -ct 25";
+        final WalkerTestSpec spec = new WalkerTestSpec(cmd,0, new ArrayList<String>());
+
+        // our base file
+        final File baseOutputFile = createTempFile("depthofcoveragenofiltering",".tmp");
+        spec.setOutputFileLocation(baseOutputFile);
+
+        // now add the expected files that get generated
+        spec.addAuxFile("0f9603eb1ca4a26828e82d8c8f4991f6", baseOutputFile);
+        spec.addAuxFile("51e6c09a307654f43811af35238fb179", createTempFileFromBase(baseOutputFile.getAbsolutePath()+".library_cumulative_coverage_counts"));
+        spec.addAuxFile("520720a88ae7608257af51bc41c06b87", createTempFileFromBase(baseOutputFile.getAbsolutePath()+".library_cumulative_coverage_proportions"));
+        spec.addAuxFile("9cd395f47b329b9dd00ad024fcac9929", createTempFileFromBase(baseOutputFile.getAbsolutePath()+".library_interval_statistics"));
+        spec.addAuxFile("6958004a8156f3f267caa6b04cf90f5f", createTempFileFromBase(baseOutputFile.getAbsolutePath()+".library_interval_summary"));
+        spec.addAuxFile("ebbfc9b9f4e12ac989c127061948c565", createTempFileFromBase(baseOutputFile.getAbsolutePath()+".library_statistics"));
+        spec.addAuxFile("e003bef6762833a5cebca25d94194616", createTempFileFromBase(baseOutputFile.getAbsolutePath()+".library_summary"));
+        spec.addAuxFile("a836b92ac17b8ff9788e2aaa9116b5d4", createTempFileFromBase(baseOutputFile.getAbsolutePath()+".read_group_cumulative_coverage_counts"));
+        spec.addAuxFile("0732b6d2db9c94b0fcf18ca1f19772a8", createTempFileFromBase(baseOutputFile.getAbsolutePath()+".read_group_cumulative_coverage_proportions"));
+        spec.addAuxFile("7b9d0e93bf5b5313995be7010ef1f528", createTempFileFromBase(baseOutputFile.getAbsolutePath()+".read_group_interval_statistics"));
+        spec.addAuxFile("3522f7380554b926c71a7258250c1d63", createTempFileFromBase(baseOutputFile.getAbsolutePath()+".read_group_interval_summary"));
+        spec.addAuxFile("2cd9d8c5e37584edd62ca6938659cf59", createTempFileFromBase(baseOutputFile.getAbsolutePath()+".read_group_statistics"));
+        spec.addAuxFile("78fdd35a63a7a4c6b3a043b946b04730", createTempFileFromBase(baseOutputFile.getAbsolutePath()+".read_group_summary"));
+        spec.addAuxFile("6909d50a7da337cd294828b32b945eb8", createTempFileFromBase(baseOutputFile.getAbsolutePath()+".sample_cumulative_coverage_counts"));
+        spec.addAuxFile("aa00e3652dd518ccbae2caa00171835b", createTempFileFromBase(baseOutputFile.getAbsolutePath()+".sample_cumulative_coverage_proportions"));
+        spec.addAuxFile("df0ba76e0e6082c0d29fcfd68efc6b77", createTempFileFromBase(baseOutputFile.getAbsolutePath()+".sample_interval_statistics"));
+        spec.addAuxFile("0ce5ebfa46b081820d013bdbbfe42d34", createTempFileFromBase(baseOutputFile.getAbsolutePath()+".sample_interval_summary"));
+        spec.addAuxFile("c7c5bad6c6818995c634f350aa66fde9", createTempFileFromBase(baseOutputFile.getAbsolutePath()+".sample_statistics"));
+        spec.addAuxFile("949c9ce745753cd98f337600d3931d09", createTempFileFromBase(baseOutputFile.getAbsolutePath()+".sample_summary"));
+
+        execute("testBaseOutputNoFiltering",spec);
+    }
+
+    @Test
+    public void testNoCoverageDueToFiltering() {
+        String[] intervals = {"/humgen/gsa-hpprojects/GATK/data/Validation_Data/fhs_jhs_30_targts.interval_list"};
+        String[] bams = {"/humgen/gsa-hpprojects/GATK/data/Validation_Data/FHS_indexed_subset.bam"};
+
+        String cmd = buildRootCmd(hg18Reference,new ArrayList<String>(Arrays.asList(bams)),new ArrayList<String>(Arrays.asList(intervals))) + " -mmq 0 -mbq 5 --maxBaseQuality 4 -dels -baseCounts -pt readgroup -pt sample -pt library --outputFormat csv";
+        WalkerTestSpec spec = new WalkerTestSpec(cmd,0, new ArrayList<String>());
+
+        File baseOutputFile = createTempFile("depthofcoveragenofiltering",".tmp");
+        spec.setOutputFileLocation(baseOutputFile);
+
+        spec.addAuxFile("6ccd7d8970ba98cb95fe41636a070c1c",baseOutputFile);
+        spec.addAuxFile("4429d33ce8836c09ba2b5ddfae2f998e",createTempFileFromBase(baseOutputFile.getAbsolutePath()+".library_interval_summary"));
+
+        execute("testNoCoverageDueToFiltering",spec);
+    }
+
+    @Test
+    public void testAdjacentIntervals() {
+        String[] intervals = {"chr1:1-999", "chr1:1000-65536", "chr1:65537-80000", "chr1:80001-81000"};
+        String[] bams = {publicTestDir+"exampleBAM.bam"};
+
+        String cmd = buildRootCmd(exampleFASTA, new ArrayList<String>(Arrays.asList(bams)), new ArrayList<String>(Arrays.asList(intervals))) + " -im OVERLAPPING_ONLY";
+        WalkerTestSpec spec = new WalkerTestSpec(cmd, 0, new ArrayList<String>());
+
+        File baseOutputFile = WalkerTest.createTempFile("depthofcoverageadjinterval", ".tmp");
+        spec.setOutputFileLocation(baseOutputFile);
+
+        spec.addAuxFile("84b95d62f53e28919d1b5286558a1cae", baseOutputFile);
+        spec.addAuxFile("e445d4529dd3e3caa486ab8f5ec63e49", createTempFileFromBase(baseOutputFile.getAbsolutePath()+".sample_cumulative_coverage_counts"));
+        spec.addAuxFile("b69c89ba8b0c393b735616c2bc3aea76", createTempFileFromBase(baseOutputFile.getAbsolutePath()+".sample_cumulative_coverage_proportions"));
+        spec.addAuxFile("788988dac6119a02de2c8d4dfb06b727", createTempFileFromBase(baseOutputFile.getAbsolutePath()+".sample_interval_statistics"));
+        spec.addAuxFile("3769ed40ab3ccd2ed94a9dc05cc2bc2f", createTempFileFromBase(baseOutputFile.getAbsolutePath()+".sample_interval_summary"));
+        spec.addAuxFile("1281605e022d7462fbbcd14de53d1ca3", createTempFileFromBase(baseOutputFile.getAbsolutePath()+".sample_statistics"));
+        spec.addAuxFile("4b41d6ff88aa2662697cb7e4b5346cb8", createTempFileFromBase(baseOutputFile.getAbsolutePath()+".sample_summary"));
+
+        execute("testAdjacentIntervals", spec);
+    }
+
+
+    @Test
+    public void testSortOrder() {
+        // This test came from a user who discovered that the columns and data in the gene_summary file didn't align for the specific
+        // sample names in these files.
+        String[] intervals = {"1:1600000-1700000"};
+        String[] bams = {privateTestDir+"badHashName1.bam", privateTestDir+"badHashName2.bam"};
+
+        String cmd = buildRootCmd(b37KGReference, new ArrayList<String>(Arrays.asList(bams)), new ArrayList<String>(Arrays.asList(intervals))) +
+                " -geneList "+privateTestDir+"refGene_CDK11B.txt";
+        WalkerTestSpec spec = new WalkerTestSpec(cmd, 0, new ArrayList<String>());
+
+        File baseOutputFile = WalkerTest.createTempFile("depthofcoveragesortorder", ".tmp");
+        spec.setOutputFileLocation(baseOutputFile);
+
+        spec.addAuxFile("a148e50f9db207adfd5d5f0f29eb54d8", baseOutputFile);
+        spec.addAuxFile("7ccd5193a3c035d1cc856cbc89e3daf4", createTempFileFromBase(baseOutputFile.getAbsolutePath()+".sample_cumulative_coverage_counts"));
+        spec.addAuxFile("2efe59c20721ce61bc5b334a26d11720", createTempFileFromBase(baseOutputFile.getAbsolutePath()+".sample_cumulative_coverage_proportions"));
+        spec.addAuxFile("9194cec953e0fe0b84a681f9bb63ffbe", createTempFileFromBase(baseOutputFile.getAbsolutePath()+".sample_gene_summary"));
+        spec.addAuxFile("cf62d95ec1f459fbbe35370c3f0ca481", createTempFileFromBase(baseOutputFile.getAbsolutePath()+".sample_interval_statistics"));
+        spec.addAuxFile("b4fcb739b7f9e309e38a7d5e7e4ebb9f", createTempFileFromBase(baseOutputFile.getAbsolutePath()+".sample_interval_summary"));
+        spec.addAuxFile("6bf63f9c62071e850c6f0b6356fb63eb", createTempFileFromBase(baseOutputFile.getAbsolutePath()+".sample_statistics"));
+        spec.addAuxFile("e53e6a494bf1cf817762b74917c6f0c9", createTempFileFromBase(baseOutputFile.getAbsolutePath()+".sample_summary"));
+
+        execute("testSortOrder", spec);
+    }
+
+    public void testRefNHandling(boolean includeNs, final String md5) {
+        String command = "-R " + b37KGReference + " -L 20:26,319,565-26,319,575 -I " + validationDataLocation + "NA12878.HiSeq.WGS.bwa.cleaned.recal.hg19.20.bam -T DepthOfCoverage -baseCounts --omitIntervalStatistics --omitLocusTable --omitPerSampleStats -o %s";
+        if ( includeNs ) command += " --includeRefNSites";
+        WalkerTestSpec spec = new WalkerTestSpec(command, 1, Arrays.asList(md5));
+        executeTest("Testing DoC " + (includeNs ? "with" : "without") + " reference Ns", spec);
+    }
+
+    @Test public void testRefNWithNs() { testRefNHandling(true, "24cd2da2e4323ce6fd76217ba6dc2834"); }
+    @Test public void testRefNWithoutNs() { testRefNHandling(false, "4fc0f1a2e968f777d693abcefd4fb7af"); }
+}
diff --git a/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/tools/walkers/qc/CheckPileupIntegrationTest.java b/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/tools/walkers/qc/CheckPileupIntegrationTest.java
new file mode 100644
index 0000000..eae4dec
--- /dev/null
+++ b/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/tools/walkers/qc/CheckPileupIntegrationTest.java
@@ -0,0 +1,70 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.tools.walkers.qc;
+
+import org.testng.annotations.Test;
+import org.broadinstitute.gatk.engine.walkers.WalkerTest;
+
+import java.util.Collections;
+
+/**
+ * Run validating pileup across a set of core data as proof of the integrity of the GATK core.
+ *
+ * Tests both types of old-school pileup formats (basic and consensus).
+ *
+ * @author mhanna, vdauwera
+ * @version 0.2
+ */
+public class CheckPileupIntegrationTest extends WalkerTest {
+    /**
+     * This test runs on a consensus pileup containing 10-column lines for SNPs and 13-column lines for indels
+     */
+    @Test(enabled = true)
+    public void testEcoliConsensusPileup() {
+        WalkerTest.WalkerTestSpec spec = new WalkerTest.WalkerTestSpec(
+                "-T CheckPileup" +
+                " -I " + validationDataLocation + "MV1994.selected.bam" +
+                " -R " + validationDataLocation + "Escherichia_coli_K12_MG1655.fasta" +
+                " --pileup:SAMPileup "+ validationDataLocation + "MV1994.selected.pileup" +
+                " -S SILENT -nt 8",0, Collections.<String>emptyList());
+        executeTest("testEcoliConsensusPileup",spec);
+    }
+
+    /**
+     * This test runs on a basic pileup containing 6-column lines for all variants  TODO
+     */
+    @Test
+    public void testEcoliBasicPileup() {
+        WalkerTest.WalkerTestSpec spec = new WalkerTest.WalkerTestSpec(
+                "-T CheckPileup" +
+                        " -I " + validationDataLocation + "MV1994.selected.bam" +
+                        " -R " + validationDataLocation + "Escherichia_coli_K12_MG1655.fasta" +
+                        " --pileup:SAMPileup "+ validationDataLocation + "MV1994.basic.pileup" +
+                        " -L Escherichia_coli_K12:1-49" +
+                        " -S SILENT -nt 8",0, Collections.<String>emptyList());
+        executeTest("testEcoliBasicPileup",spec);
+    }
+}
diff --git a/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/tools/walkers/qc/CountReadsUnitTest.java b/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/tools/walkers/qc/CountReadsUnitTest.java
new file mode 100644
index 0000000..e79edfd
--- /dev/null
+++ b/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/tools/walkers/qc/CountReadsUnitTest.java
@@ -0,0 +1,51 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.tools.walkers.qc;
+
+import org.broadinstitute.gatk.utils.BaseTest;
+import org.testng.Assert;
+import org.testng.annotations.Test;
+
+public class CountReadsUnitTest extends BaseTest {
+
+    @Test
+    public void testReadsDoNotOverflowInt() {
+
+        final CountReads walker = new CountReads();
+
+        final long moreThanMaxInt = ((long)Integer.MAX_VALUE) + 1L;
+
+        Long sum = walker.reduceInit();
+
+        for ( long i = 0L; i < moreThanMaxInt; i++ ) {
+            final Integer x = walker.map(null, null, null);
+            sum = walker.reduce(x, sum);
+        }
+
+        Assert.assertEquals(sum.longValue(), moreThanMaxInt);
+        Assert.assertTrue(sum.longValue() > (long) Integer.MAX_VALUE);
+    }
+}
diff --git a/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/tools/walkers/qc/DictionaryConsistencyIntegrationTest.java b/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/tools/walkers/qc/DictionaryConsistencyIntegrationTest.java
new file mode 100644
index 0000000..69e623e
--- /dev/null
+++ b/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/tools/walkers/qc/DictionaryConsistencyIntegrationTest.java
@@ -0,0 +1,82 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.tools.walkers.qc;
+
+import org.broadinstitute.gatk.utils.BaseTest;
+import org.broadinstitute.gatk.engine.walkers.WalkerTest;
+import org.broadinstitute.gatk.utils.exceptions.UserException;
+import org.testng.annotations.Test;
+
+/**
+ *
+ */
+public class DictionaryConsistencyIntegrationTest extends WalkerTest {
+    private static final String callsHG18 = BaseTest.validationDataLocation + "HiSeq.WGS.cleaned.ug.snpfiltered.indelfiltered.optimized.cut.vcf";
+    private static final String callsB36  = BaseTest.validationDataLocation + "lowpass.N3.chr1.raw.vcf";
+    private static final String lexHG18 = BaseTest.validationDataLocation + "lexFasta/lex.hg18.fasta";
+    private static final String b36BAM = BaseTest.validationDataLocation + "NA12878.1kg.p2.chr1_10mb_11_mb.allTechs.bam";
+    private static final String hg18BAM = BaseTest.validationDataLocation + "NA12878.WEx.downsampled20x.bam";
+
+    // testing hg18 calls
+    @Test public void fail1() { executeTest("b36xhg18", testVCF(b36KGReference, callsHG18)); }
+    @Test public void fail2() { executeTest("b37xhg18", testVCF(b37KGReference, callsHG18)); }
+    @Test public void fail3() { executeTest("hg19xhg18", testVCF(hg19Reference, callsHG18)); }
+    @Test public void fail4() { executeTest("hg18lex-v-hg18", testVCF(lexHG18, callsHG18, UserException.LexicographicallySortedSequenceDictionary.class)); }
+
+    // testing b36 calls
+    @Test public void fail5() { executeTest("b36xb36", testVCF(hg18Reference, callsB36)); }
+    @Test public void fail6() { executeTest("b37xb36", testVCF(b37KGReference, callsB36)); }
+    @Test public void fail7() { executeTest("hg19xb36", testVCF(hg19Reference, callsB36)); }
+    @Test public void fail8() { executeTest("hg18lex-v-b36", testVCF(lexHG18, callsB36, UserException.LexicographicallySortedSequenceDictionary.class)); }
+
+    private WalkerTest.WalkerTestSpec testVCF(String ref, String vcf) {
+        return testVCF(ref, vcf, UserException.IncompatibleSequenceDictionaries.class);
+    }
+
+    private WalkerTest.WalkerTestSpec testVCF(String ref, String vcf, Class c) {
+        return new WalkerTest.WalkerTestSpec("-T VariantsToTable -M 10 --variant:vcf "
+                + vcf + " -F POS,CHROM -R "
+                + ref +  " -o %s",
+                1, c);
+
+    }
+
+    @Test public void failBAM1() { executeTest("b36bam-v-b37",     testBAM(b37KGReference, b36BAM, "1",    UserException.IncompatibleSequenceDictionaries.class)); }
+    @Test public void failBAM2() { executeTest("b36bam-v-hg18",    testBAM(hg18Reference,  b36BAM, "chr1", UserException.IncompatibleSequenceDictionaries.class)); }
+    @Test public void failBAM3() { executeTest("b36bam-v-hg19",    testBAM(hg19Reference,  b36BAM, "1",    UserException.IncompatibleSequenceDictionaries.class)); }
+    @Test public void failBAM4() { executeTest("b36bam-v-lexhg18", testBAM(lexHG18,        b36BAM, "chr1", UserException.LexicographicallySortedSequenceDictionary.class)); }
+
+    @Test public void failBAM5() { executeTest("hg18bam-v-b36",     testBAM(b36KGReference, hg18BAM, "1",    UserException.IncompatibleSequenceDictionaries.class)); }
+    @Test public void failBAM6() { executeTest("hg18bam-v-b37",     testBAM(b37KGReference, hg18BAM, "1",    UserException.IncompatibleSequenceDictionaries.class)); }
+    @Test public void failBAM7() { executeTest("hg18bam-v-hg19",    testBAM(hg19Reference,  hg18BAM, "1",    UserException.IncompatibleSequenceDictionaries.class)); }
+    @Test public void failBAM8() { executeTest("hg18bam-v-lexhg18", testBAM(lexHG18,        hg18BAM, "chr1", UserException.LexicographicallySortedSequenceDictionary.class)); }
+
+    private WalkerTest.WalkerTestSpec testBAM(String ref, String bam, String contig, Class c) {
+        return new WalkerTest.WalkerTestSpec("-T PrintReads -I " + bam + " -R " + ref +  " -L " + contig + ":10,000,000-11,000,000 -o %s",
+                1, c);
+
+    }
+}
diff --git a/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/tools/walkers/qc/FlagStatIntegrationTest.java b/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/tools/walkers/qc/FlagStatIntegrationTest.java
new file mode 100644
index 0000000..7a88681
--- /dev/null
+++ b/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/tools/walkers/qc/FlagStatIntegrationTest.java
@@ -0,0 +1,45 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.tools.walkers.qc;
+
+import org.broadinstitute.gatk.engine.walkers.WalkerTest;
+import org.testng.annotations.Test;
+
+import java.util.Arrays;
+
+public class FlagStatIntegrationTest extends WalkerTest {
+
+    @Test
+    public void testFlagStat() {
+        String md5 = "9c4039662f24bfd23ccf67973cb5df29";
+
+        WalkerTestSpec spec = new WalkerTestSpec(
+                "-T FlagStat -R " + b36KGReference + " -I " + validationDataLocation + "NA12878.1kg.p2.chr1_10mb_11_mb.SLX.bam -L 1:10,000,000-10,050,000 -o %s",
+                 1,
+                 Arrays.asList(md5));
+        executeTest("test flag stat", spec);
+    }
+}
diff --git a/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/tools/walkers/qc/PileupWalkerIntegrationTest.java b/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/tools/walkers/qc/PileupWalkerIntegrationTest.java
new file mode 100644
index 0000000..38154bd
--- /dev/null
+++ b/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/tools/walkers/qc/PileupWalkerIntegrationTest.java
@@ -0,0 +1,123 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.tools.walkers.qc;
+
+import org.broadinstitute.gatk.engine.walkers.WalkerTest;
+import org.testng.annotations.DataProvider;
+import org.testng.annotations.Test;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+public class PileupWalkerIntegrationTest extends WalkerTest {
+
+    @Test
+    public void testGnarleyFHSPileup() {
+        String gatk_args = "-T Pileup -I " + validationDataLocation + "FHS_Pileup_Test.bam "
+                 + "-R " + hg18Reference
+                 +  " -L chr15:46,347,148 -o %s";
+        String expected_md5 = "526c93b0fa660d6b953b57103e59fe98";
+        WalkerTestSpec spec = new WalkerTestSpec(gatk_args, 1, Arrays.asList(expected_md5));
+        executeTest("Testing the standard (no-indel) pileup on three merged FHS pools with 27 deletions in 969 bases", spec);
+    }
+
+
+
+    private final static String SingleReadAligningOffChromosome1MD5 = "4a45fe1f85aaa8c4158782f2b6dee2bd";
+    @Test
+    public void testSingleReadAligningOffChromosome1() {
+        String gatk_args = "-T Pileup "
+                + " -I " + privateTestDir + "readOffb37contig1.bam"
+                + " -R " + b37KGReference
+                + " -o %s";
+        WalkerTestSpec spec = new WalkerTestSpec(gatk_args, 1, Arrays.asList(SingleReadAligningOffChromosome1MD5));
+        executeTest("Testing single read spanning off chromosome 1", spec);
+    }
+
+    @Test
+    public void testSingleReadAligningOffChromosome1NoIndex() {
+        String gatk_args = "-T Pileup "
+                + " -I " + privateTestDir + "readOffb37contig1.noIndex.bam"
+                + " -R " + b37KGReference
+                + " -U ALLOW_UNINDEXED_BAM"
+                + " -o %s";
+        WalkerTestSpec spec = new WalkerTestSpec(gatk_args, 1, Arrays.asList(SingleReadAligningOffChromosome1MD5));
+        executeTest("Testing single read spanning off chromosome 1 unindexed", spec);
+    }
+
+    /************************/
+
+    //testing speedup to GATKBAMIndex
+
+
+    @DataProvider(name="GATKBAMIndexTest")
+    public Object[][] makeMyDataProvider() {
+        List<Object[]> tests = new ArrayList<Object[]>();
+        tests.add(new Object[]{"-L 20:1-76,050","8702701350de11a6d28204acefdc4775"});
+        tests.add(new Object[]{"-L 20:10,000,000-10,001,100","818cf5a8229efe6f89fc1cd8145ccbe3"});
+        tests.add(new Object[]{"-L 20:62,954,114-63,025,520","22471ea4a12e5139aef62bf8ff2a5b63"});
+        tests.add(new Object[]{"-L 20:1-76,050 -L 20:20,000,000-20,000,100 -L 20:40,000,000-40,000,100 -L 20:30,000,000-30,000,100 -L 20:50,000,000-50,000,100 -L 20:62,954,114-63,025,520 ","08d899ed7c5a76ef3947bf67338acda1"});
+        return tests.toArray(new Object[][]{});
+    }
+
+    @Test(dataProvider = "GATKBAMIndexTest")
+    public void testGATKBAMIndexSpeedup(final String intervals, final String md5){
+        final String gatkArgs="-T Pileup -I " + validationDataLocation + "NA12878.HiSeq.WGS.bwa.cleaned.recal.hg19.20.bam "
+                + "-R " + hg19Reference + " -o %s ";
+
+        WalkerTestSpec spec = new WalkerTestSpec(gatkArgs + intervals, 1, Arrays.asList(md5));
+        executeTest("Testing with intervals="+intervals, spec);
+    }
+
+
+    /***********************/
+
+    // testing hidden option -outputInsertLength
+    private final static String SingleReadAligningOffChromosome1withInsertLengthMD5 = "279e2ec8832e540f47a6e2bdf4cef5ea";
+    @Test
+    public void testSingleReadAligningOffChromosome1withInsertLength() {
+        String gatk_args = "-T Pileup "
+                + " -I " + privateTestDir + "readOffb37contig1.bam"
+                + " -R " + b37KGReference
+                + " -outputInsertLength"
+                + " -o %s";
+        WalkerTestSpec spec = new WalkerTestSpec(gatk_args, 1, Arrays.asList(SingleReadAligningOffChromosome1withInsertLengthMD5));
+        executeTest("Testing single read spanning off chromosome 1 (with insert length)", spec);
+    }
+
+    @Test
+    public void testGnarleyFHSPileupwithInsertLength() {
+        String gatk_args = "-T Pileup -I " + validationDataLocation + "FHS_Pileup_Test.bam "
+                + "-R " + hg18Reference
+                + " -outputInsertLength"
+                +  " -L chr15:46,347,148 -o %s";
+        String expected_md5 = "53ced173768f3d4d90b8a8206e72eae5";
+        WalkerTestSpec spec = new WalkerTestSpec(gatk_args, 1, Arrays.asList(expected_md5));
+        executeTest("Testing the standard (no-indel) pileup on three merged FHS pools with 27 deletions in 969 bases (with insert length)", spec);
+    }
+
+}
diff --git a/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/tools/walkers/readutils/ClipReadsWalkersIntegrationTest.java b/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/tools/walkers/readutils/ClipReadsWalkersIntegrationTest.java
new file mode 100644
index 0000000..29f4621
--- /dev/null
+++ b/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/tools/walkers/readutils/ClipReadsWalkersIntegrationTest.java
@@ -0,0 +1,80 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.tools.walkers.readutils;
+
+import org.broadinstitute.gatk.engine.walkers.WalkerTest;
+import org.testng.annotations.Test;
+
+import java.io.File;
+import java.util.Arrays;
+import java.util.List;
+
+public class ClipReadsWalkersIntegrationTest extends WalkerTest {
+    public void testClipper(String name, String args, String md51, String md52) {
+        WalkerTestSpec spec = new WalkerTestSpec(
+                "-R " + hg18Reference +
+                        " -T ClipReads " +
+                        "-I " + privateTestDir + "clippingReadsTest.withRG.bam " +
+                        "-os %s " +
+                        "-o %s " + args,
+                2, // just one output file
+                Arrays.asList("tmp", "bam"),
+                Arrays.asList(md51, md52));
+        List<File> result = executeTest(name, spec).getFirst();
+    }
+
+    final static String Q10ClipOutput = "b29c5bc1cb9006ed9306d826a11d444f";
+    @Test public void testQClip0() { testClipper("clipQSum0", "-QT 0", "117a4760b54308f81789c39b1c9de578", "12be03c817d94bab88457e5afe74256a"); }
+    @Test public void testQClip2() { testClipper("clipQSum2", "-QT 2", Q10ClipOutput, "1cfc9da4867765c1e5b5bd6326984634"); }
+    @Test public void testQClip10() { testClipper("clipQSum10", "-QT 10", "b29c5bc1cb9006ed9306d826a11d444f", "1cfc9da4867765c1e5b5bd6326984634"); }
+    @Test public void testQClip20() { testClipper("clipQSum20", "-QT 20", "6c3434dce66ae5c9eeea502f10fb9bee", "0bcfd177fe4be422898eda8e161ebd6c"); }
+
+    @Test public void testClipRange1() { testClipper("clipRange1", "-CT 1-5", "b5acd753226e25b1e088838c1aab9117", "aed836c97c6383dd80e39a093cc25e08"); }
+    @Test public void testClipRange2() { testClipper("clipRange2", "-CT 1-5,11-15", "be4fcad5b666a5540028b774169cbad7", "5f6e08bd44d6faf5b85cde5d4ec1a36f"); }
+
+    @Test public void testClipSeq() { testClipper("clipSeqX", "-X CCCCC", "db199bd06561c9f2122f6ffb07941fbc", "f3cb42759428df80d06e9789f9f9f762"); }
+    @Test public void testClipSeqFile() { testClipper("clipSeqXF", "-XF " + privateTestDir + "seqsToClip.fasta", "d011a3152b31822475afbe0281491f8d", "44658c018378467f809b443d047d5778"); }
+
+    @Test public void testClipMulti() { testClipper("clipSeqMulti", "-QT 10 -CT 1-5 -XF " + privateTestDir + "seqsToClip.fasta -X CCCCC", "a23187bd9bfb06557f799706d98441de", "bae38f83eb9b63857f5e6e3c6e62f80c"); }
+
+    @Test public void testClipNs() { testClipper("testClipNs", "-QT 10 -CR WRITE_NS", Q10ClipOutput, "1cfc9da4867765c1e5b5bd6326984634"); }
+    @Test public void testClipQ0s() { testClipper("testClipQs", "-QT 10 -CR WRITE_Q0S", Q10ClipOutput, "3b32da2eaab7a2d4729fdb486cedbb2f"); }
+    @Test public void testClipSoft() { testClipper("testClipSoft", "-QT 10 -CR SOFTCLIP_BASES", Q10ClipOutput, "9d355b0f6d2076178e92bd7fcd8f5adb"); }
+
+    @Test
+    public void testUseOriginalQuals() {
+        WalkerTest.WalkerTestSpec spec = new WalkerTest.WalkerTestSpec(
+                "-R " + hg18Reference +
+                        " -T ClipReads" +
+                        " -I " + privateTestDir + "originalQuals.chr1.1-1K.bam" +
+                        " -L chr1:1-1,000" +
+                        " -OQ -QT 4 -CR WRITE_Q0S" +
+                        " -o %s -os %s",
+                2,
+                Arrays.asList("c83b4e2ade8654a2818fe9d405f07662", "55c01ccc2e84481b22d3632cdb06c8ba"));
+        executeTest("clipOriginalQuals", spec);
+    }
+}
diff --git a/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/tools/walkers/readutils/PrintReadsIntegrationTest.java b/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/tools/walkers/readutils/PrintReadsIntegrationTest.java
new file mode 100644
index 0000000..0213940
--- /dev/null
+++ b/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/tools/walkers/readutils/PrintReadsIntegrationTest.java
@@ -0,0 +1,136 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.tools.walkers.readutils;
+
+import org.broadinstitute.gatk.engine.walkers.WalkerTest;
+import org.broadinstitute.gatk.utils.exceptions.UserException;
+import org.testng.annotations.DataProvider;
+import org.testng.annotations.Test;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+public class PrintReadsIntegrationTest extends WalkerTest {
+    private static class PRTest {
+        final String reference;
+        final List<String> bam;
+        final String args;
+        final String md5;
+
+        private PRTest(String reference, String[] bam, String args, String md5) {
+            this.reference = reference;
+            this.bam = new ArrayList<>();
+            this.args = args;
+            this.md5 = md5;
+            this.bam.addAll(Arrays.asList(bam));
+        }
+
+        @Override
+        public String toString() {
+            return String.format("PRTest(bam='%s', args='%s')", bam, args);
+        }
+    }
+
+    @DataProvider(name = "PRTest")
+    public Object[][] createPrintReadsTestData() {
+        return new Object[][]{
+                {new PRTest(hg18Reference, new String[]{"HiSeq.1mb.bam"}, "", "fa9c66f66299fe5405512ac36ec9d0f2")},
+                {new PRTest(hg18Reference, new String[]{"HiSeq.1mb.bam"}, " -compress 0", "488eb22abc31c6af7cbb1a3d41da1507")},
+                {new PRTest(hg18Reference, new String[]{"HiSeq.1mb.bam"}, " -simplifyBAM", "1510dc4429f3ed49caf96da41e8ed396")},
+                {new PRTest(hg18Reference, new String[]{"HiSeq.1mb.bam"}, " -n 10", "0e3d1748ad1cb523e3295cab9d09d8fc")},
+                // See: GATKBAMIndex.getStartOfLastLinearBin(), BAMScheduler.advance(), IntervalOverlapFilteringIterator.advance()
+                {new PRTest(b37KGReference, new String[]{"unmappedFlagReadsInLastLinearBin.bam"}, "", "d7f23fd77d7dc7cb50d3397f644c6d8a")},
+                {new PRTest(b37KGReference, new String[]{"unmappedFlagReadsInLastLinearBin.bam"}, " -L 1", "c601db95b20248d012b0085347fcb6d1")},
+                {new PRTest(b37KGReference, new String[]{"unmappedFlagReadsInLastLinearBin.bam"}, " -L unmapped", "2d32440e47e8d9d329902fe573ad94ce")},
+                {new PRTest(b37KGReference, new String[]{"unmappedFlagReadsInLastLinearBin.bam"}, " -L 1 -L unmapped", "c601db95b20248d012b0085347fcb6d1")},
+                {new PRTest(b37KGReference, new String[]{"oneReadAllInsertion.bam"}, "",  "349650b6aa9e574b48a2a62627f37c7d")},
+                {new PRTest(b37KGReference, new String[]{"NA12878.1_10mb_2_10mb.bam"}, "",  "0c1cbe67296637a85e80e7a182f828ab")},
+                // Tests for filtering options
+                {new PRTest(b37KGReference, new String[]{"NA12878.1_10mb_2_10mb.bam", "NA20313.highCoverageRegion.bam"},
+                        "",  "b3ae15c8af33fd5badc1a29e089bdaac")},
+                {new PRTest(b37KGReference, new String[]{"NA12878.1_10mb_2_10mb.bam", "NA20313.highCoverageRegion.bam"},
+                        " -readGroup SRR359098",  "8bd867b30539524daa7181efd9835a8f")},
+                {new PRTest(b37KGReference, new String[]{"NA12878.1_10mb_2_10mb.bam", "NA20313.highCoverageRegion.bam"},
+                        " -readGroup 20FUK.3 -sn NA12878",  "93a7bc1b2b1cd27815ed1666cbb4d0cb")},
+                {new PRTest(b37KGReference, new String[]{"NA12878.1_10mb_2_10mb.bam", "NA20313.highCoverageRegion.bam"},
+                        " -sn na12878",  "52e99cfcf03ff46285d1ba302f8df964")},
+        };
+    }
+
+    @Test(dataProvider = "PRTest")
+    public void testPrintReads(PRTest params) {
+
+        StringBuilder inputs = new StringBuilder();
+        for (String bam : params.bam) {
+            inputs.append(" -I ");
+            inputs.append(privateTestDir);
+            inputs.append(bam);
+        }
+
+        WalkerTestSpec spec = new WalkerTestSpec(
+                "-T PrintReads" +
+                        " -R " + params.reference +
+                        inputs.toString() +
+                        params.args +
+                        " --no_pg_tag" +
+                        " -o %s",
+                Arrays.asList(params.md5));
+        executeTest("testPrintReads-"+params.args, spec).getFirst();
+    }
+
+    @DataProvider(name = "PRExceptionTest")
+    public Object[][] createPrintReadsExceptionTestData() {
+        return new Object[][]{
+                {new PRTest(b37KGReference, new String[]{"NA12878.1_10mb_2_10mb.bam", "NA20313.highCoverageRegion.bam"},
+                        "-platform illum",  "")},
+                {new PRTest(b37KGReference, new String[]{"NA12878.1_10mb_2_10mb.bam", "NA20313.highCoverageRegion.bam"},
+                        " -sn NotASample",  "")},
+        };
+    }
+
+    @Test(dataProvider = "PRExceptionTest")
+    public void testPrintReadsException(PRTest params) {
+
+        StringBuilder inputs = new StringBuilder();
+        for (String bam : params.bam) {
+            inputs.append(" -I ");
+            inputs.append(privateTestDir);
+            inputs.append(bam);
+        }
+
+        WalkerTestSpec spec = new WalkerTestSpec(
+                "-T PrintReads" +
+                        " -R " + params.reference +
+                        inputs.toString() +
+                        params.args +
+                        " --no_pg_tag" +
+                        " -o %s",
+                1, UserException.class);
+        executeTest("testPrintReadsException-"+params.args, spec);
+    }
+
+}
diff --git a/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/tools/walkers/readutils/PrintReadsLargeScaleTest.java b/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/tools/walkers/readutils/PrintReadsLargeScaleTest.java
new file mode 100644
index 0000000..956d70f
--- /dev/null
+++ b/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/tools/walkers/readutils/PrintReadsLargeScaleTest.java
@@ -0,0 +1,45 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.tools.walkers.readutils;
+
+import org.broadinstitute.gatk.engine.walkers.WalkerTest;
+import org.testng.annotations.Test;
+
+import java.util.ArrayList;
+
+public class PrintReadsLargeScaleTest extends WalkerTest {
+    @Test( timeOut = 1000 * 60 * 60 * 20 ) // 60 seconds * 60 seconds / minute * 20 minutes
+    public void testRealignerTargetCreator() {
+        WalkerTestSpec spec = new WalkerTestSpec(
+                "-R " + b37KGReference +
+                        " -T PrintReads" +
+                        " -I " + evaluationDataLocation + "CEUTrio.HiSeq.WEx.b37.NA12892.clean.dedup.recal.1.bam" +
+                        " -o /dev/null",
+                 0,
+                new ArrayList<String>(0));
+        executeTest("testPrintReadsWholeExomeChr1", spec);
+    }
+}
diff --git a/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/tools/walkers/readutils/PrintReadsUnitTest.java b/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/tools/walkers/readutils/PrintReadsUnitTest.java
new file mode 100644
index 0000000..53b6d42
--- /dev/null
+++ b/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/tools/walkers/readutils/PrintReadsUnitTest.java
@@ -0,0 +1,123 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.tools.walkers.readutils;
+
+import htsjdk.samtools.SAMFileHeader;
+import htsjdk.samtools.SAMRecord;
+import org.broadinstitute.gatk.utils.BaseTest;
+import org.broadinstitute.gatk.engine.contexts.ReferenceContext;
+import org.broadinstitute.gatk.utils.sam.ArtificialReadsTraversal;
+import org.broadinstitute.gatk.utils.sam.ArtificialGATKSAMFileWriter;
+import org.broadinstitute.gatk.utils.sam.ArtificialSAMUtils;
+import org.broadinstitute.gatk.utils.sam.GATKSAMRecord;
+import org.testng.annotations.BeforeMethod;
+import org.testng.annotations.Test;
+
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertTrue;
+
+
+/*
+ * 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.
+ */
+
+/**
+ * @author aaron
+ *         <p/>
+ *         Class PrintReadsUnitTest
+ *         <p/>
+ *         This tests the print reads walker, using the artificial reads traversal
+ */
+public class PrintReadsUnitTest extends BaseTest {
+
+    /**
+     * our private fake reads traversal.  This traversal seeds the
+     * the walker with a specified number of fake reads, which are named sequentially
+     */
+    private ArtificialReadsTraversal trav;
+    private int readTotal = 0;
+    //private char bases[] = {'a', 't'};
+    private ReferenceContext bases = null;
+    //private ReferenceContext ref = new ReferenceContext()
+
+    org.broadinstitute.gatk.tools.walkers.readutils.PrintReads walker;
+    ArtificialGATKSAMFileWriter writer;
+
+    @BeforeMethod
+    public void before() {
+        trav = new ArtificialReadsTraversal();
+        readTotal = ( ( trav.endingChr - trav.startingChr ) + 1 ) * trav.readsPerChr + trav.unMappedReads;
+
+        walker = new org.broadinstitute.gatk.tools.walkers.readutils.PrintReads();
+        writer = new ArtificialGATKSAMFileWriter();
+        walker.initialize();
+    }
+
+    /** test that we get out the same number of reads we put in */
+    @Test
+    public void testReadCount() {
+        trav.traverse(walker, null, writer);
+        assertEquals(writer.getRecords().size(), readTotal);
+    }
+
+    /** test that we're ok with a null read */
+    @Test
+    public void testNullRead() {
+        SAMRecord rec = walker.map(bases, null, null);
+        assertTrue(rec == null);
+    }
+
+    /** tes that we get the read we put into the map function */
+    @Test
+    public void testReturnRead() {
+        SAMFileHeader head = ArtificialSAMUtils.createArtificialSamHeader(3,1,1000);
+        GATKSAMRecord rec = ArtificialSAMUtils.createArtificialRead(head, "FakeRead", 1, 1, 50);
+        SAMRecord ret = walker.map(bases, rec, null);
+        assertTrue(ret == rec);
+        assertTrue(ret.getReadName().equals(rec.getReadName()));
+    }
+}
diff --git a/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/tools/walkers/readutils/ReadAdaptorTrimmerIntegrationTest.java b/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/tools/walkers/readutils/ReadAdaptorTrimmerIntegrationTest.java
new file mode 100644
index 0000000..65ca2e7
--- /dev/null
+++ b/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/tools/walkers/readutils/ReadAdaptorTrimmerIntegrationTest.java
@@ -0,0 +1,60 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.tools.walkers.readutils;
+
+import org.broadinstitute.gatk.engine.walkers.WalkerTest;
+import org.testng.annotations.Test;
+
+import java.util.Arrays;
+import java.util.Collections;
+
+/**
+ * Created with IntelliJ IDEA.
+ * User: delangel
+ * Date: 4/13/13
+ * Time: 7:28 AM
+ * To change this template use File | Settings | File Templates.
+ */
+public class ReadAdaptorTrimmerIntegrationTest extends WalkerTest {
+    private String getBaseCommand(final String BAM) {
+        return  "-T ReadAdaptorTrimmer -R " + b37KGReference +
+                " -I " + privateTestDir + BAM +
+                " -o %s";
+    }
+
+    @Test
+    public void testBasicTrimmer() {
+        WalkerTestSpec spec = new WalkerTestSpec( getBaseCommand("shortInsertTest.bam"),  1, Arrays.asList("1d42414e12b45d44e6f396d97d0f60fe"));
+        executeTest(String.format("testBasicTrimmer"), spec);
+    }
+
+    @Test
+    public void testSkippingBadPairs() {
+        WalkerTestSpec spec = new WalkerTestSpec( getBaseCommand("shortInsertTest2.bam")+" -removeUnpairedReads",  1, Arrays.asList("5e796345502fbfc31134f7736ce68868"));
+        executeTest(String.format("testSkippingBadPairs"), spec);
+    }
+
+}
diff --git a/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/tools/walkers/variantutils/FilterLiftedVariantsUnitTest.java b/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/tools/walkers/variantutils/FilterLiftedVariantsUnitTest.java
new file mode 100644
index 0000000..847c8f1
--- /dev/null
+++ b/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/tools/walkers/variantutils/FilterLiftedVariantsUnitTest.java
@@ -0,0 +1,54 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.tools.walkers.variantutils;
+
+import org.broadinstitute.gatk.utils.BaseTest;
+import htsjdk.variant.variantcontext.Allele;
+import htsjdk.variant.variantcontext.VariantContext;
+import htsjdk.variant.variantcontext.VariantContextBuilder;
+import org.testng.Assert;
+import org.testng.annotations.Test;
+
+import java.util.ArrayList;
+import java.util.List;
+
+
+public class FilterLiftedVariantsUnitTest extends BaseTest {
+
+    @Test
+    public void testIndelAtEndOfContig() {
+
+        final List<Allele> alleles = new ArrayList<>(2);
+        alleles.add(Allele.create("AAAAA", true));
+        alleles.add(Allele.create("A", false));
+        final VariantContext vc = new VariantContextBuilder("test", "1", 10, 14, alleles).make();
+
+        final FilterLiftedVariants filter = new FilterLiftedVariants();
+
+        Assert.assertFalse(filter.filterOrWrite(new byte[]{'A'}, vc));
+    }
+
+}
diff --git a/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/tools/walkers/variantutils/SelectVariantsUnitTest.java b/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/tools/walkers/variantutils/SelectVariantsUnitTest.java
new file mode 100644
index 0000000..117f507
--- /dev/null
+++ b/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/tools/walkers/variantutils/SelectVariantsUnitTest.java
@@ -0,0 +1,88 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.tools.walkers.variantutils;
+
+import org.broadinstitute.gatk.utils.BaseTest;
+import org.broadinstitute.gatk.utils.Utils;
+import htsjdk.variant.variantcontext.Allele;
+import htsjdk.variant.variantcontext.VariantContext;
+import htsjdk.variant.variantcontext.VariantContextBuilder;
+import org.testng.Assert;
+import org.testng.annotations.DataProvider;
+import org.testng.annotations.Test;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+
+public class SelectVariantsUnitTest extends BaseTest {
+
+    //////////////////////////////////////////
+    // Tests for maxIndelSize functionality //
+    //////////////////////////////////////////
+
+    @DataProvider(name = "MaxIndelSize")
+    public Object[][] MaxIndelSizeTestData() {
+
+        List<Object[]> tests = new ArrayList<Object[]>();
+
+        for ( final int size : Arrays.asList(1, 3, 10, 100) ) {
+            for ( final int otherSize : Arrays.asList(0, 1) ) {
+                for ( final int max : Arrays.asList(0, 1, 5, 50, 100000) ) {
+                    for ( final String op : Arrays.asList("D", "I") ) {
+                        tests.add(new Object[]{size, otherSize, max, op});
+                    }
+                }
+            }
+        }
+
+        return tests.toArray(new Object[][]{});
+    }
+
+    @Test(dataProvider = "MaxIndelSize")
+    public void maxIndelSizeTest(final int size, final int otherSize, final int max, final String op) {
+
+        final byte[] largerAllele = Utils.dupBytes((byte) 'A', size+1);
+        final byte[] smallerAllele = Utils.dupBytes((byte) 'A', 1);
+
+        final List<Allele> alleles = new ArrayList<Allele>(2);
+        final Allele ref = Allele.create(op.equals("I") ? smallerAllele : largerAllele, true);
+        final Allele alt = Allele.create(op.equals("D") ? smallerAllele : largerAllele, false);
+        alleles.add(ref);
+        alleles.add(alt);
+        if ( otherSize > 0 && otherSize != size ) {
+            final Allele otherAlt = Allele.create(op.equals("D") ? Utils.dupBytes((byte) 'A', size-otherSize+1) : Utils.dupBytes((byte) 'A', otherSize+1), false);
+            alleles.add(otherAlt);
+        }
+
+        final VariantContext vc = new VariantContextBuilder("test", "1", 10, 10 + ref.length() - 1, alleles).make();
+
+        boolean hasTooLargeIndel = SelectVariants.containsIndelLargerThan(vc, max);
+        Assert.assertEquals(hasTooLargeIndel, size > max);
+    }
+
+}
\ No newline at end of file
diff --git a/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/utils/AutoFormattingTimeUnitTest.java b/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/utils/AutoFormattingTimeUnitTest.java
new file mode 100644
index 0000000..22e9517
--- /dev/null
+++ b/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/utils/AutoFormattingTimeUnitTest.java
@@ -0,0 +1,118 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.utils;
+
+import org.broadinstitute.gatk.utils.BaseTest;
+import org.broadinstitute.gatk.utils.AutoFormattingTime;
+import org.testng.Assert;
+import org.testng.annotations.DataProvider;
+import org.testng.annotations.Test;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import java.util.concurrent.TimeUnit;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+/**
+ * UnitTests for the AutoFormatting
+ *
+ * User: depristo
+ * Date: 8/24/12
+ * Time: 11:25 AM
+ * To change this template use File | Settings | File Templates.
+ */
+public class AutoFormattingTimeUnitTest extends BaseTest {
+    @DataProvider(name = "AutoFormattingTimeUnitSelection")
+    public Object[][] makeTimeData() {
+        List<Object[]> tests = new ArrayList<Object[]>();
+        tests.add(new Object[]{TimeUnit.SECONDS.toNanos(10), "s"});
+        tests.add(new Object[]{TimeUnit.MINUTES.toNanos(10), "m"});
+        tests.add(new Object[]{TimeUnit.HOURS.toNanos(10), "h"});
+        tests.add(new Object[]{TimeUnit.DAYS.toNanos(10), "d"});
+        tests.add(new Object[]{TimeUnit.DAYS.toNanos(1000), "w"});
+        return tests.toArray(new Object[][]{});
+    }
+
+    @Test(dataProvider = "AutoFormattingTimeUnitSelection")
+    public void testUnitSelection(final long nano, final String expectedUnit) throws InterruptedException {
+        final AutoFormattingTime time = new AutoFormattingTime(nano);
+        testBasic(time, nano, time.getWidth(), time.getPrecision());
+        Assert.assertTrue(time.toString().endsWith(expectedUnit), "TimeUnit " + time.toString() + " didn't contain expected time unit " + expectedUnit);
+    }
+
+    @Test(dataProvider = "AutoFormattingTimeUnitSelection")
+    public void testSecondsAsDouble(final long nano, final String expectedUnit) throws InterruptedException {
+        final double inSeconds = nano * 1e-9;
+        final long nanoFromSeconds = (long)(inSeconds * 1e9);
+        final AutoFormattingTime time = new AutoFormattingTime(inSeconds);
+        testBasic(time, nanoFromSeconds, time.getWidth(), time.getPrecision());
+    }
+
+    @DataProvider(name = "AutoFormattingTimeWidthAndPrecision")
+    public Object[][] makeTimeWidthAndPrecision() {
+        List<Object[]> tests = new ArrayList<Object[]>();
+        for ( final int width : Arrays.asList(-1, 1, 2, 6, 20) ) {
+            for ( final int precision : Arrays.asList(1, 2) ) {
+                tests.add(new Object[]{100.123456 * 1e9, width, precision});
+                tests.add(new Object[]{0.123456 * 1e9, width, precision});
+            }
+        }
+        return tests.toArray(new Object[][]{});
+    }
+
+    @Test(dataProvider = "AutoFormattingTimeWidthAndPrecision")
+    public void testWidthAndPrecision(final double inSeconds, final int width, final int precision) throws InterruptedException {
+        final AutoFormattingTime time = new AutoFormattingTime(inSeconds, width, precision);
+        final long nanoFromSeconds = (long)(inSeconds * 1e9);
+        testBasic(time, nanoFromSeconds, width, precision);
+        final Matcher match = matchToString(time);
+        match.matches();
+        final String widthString = match.group(1);
+        final String precisionString = match.group(2);
+        if ( width != -1 ) {
+            final int actualWidth = widthString.length() + 1 + precisionString.length();
+            Assert.assertTrue(actualWidth >= width, "width string '" + widthString + "' not >= the expected width " + width);
+        }
+        Assert.assertEquals(precisionString.length(), precision, "precision string '" + precisionString + "' not the expected precision " + precision);
+    }
+
+    private static Matcher matchToString(final AutoFormattingTime time) {
+        Pattern pattern = Pattern.compile("(\\s*\\d*)\\.(\\d*) \\w");
+        return pattern.matcher(time.toString());
+    }
+
+    private static void testBasic(final AutoFormattingTime aft, final long nano, final int expectedWidth, final int expectedPrecision) {
+        Assert.assertEquals(aft.getTimeInNanoSeconds(), nano);
+        assertEqualsDoubleSmart(aft.getTimeInSeconds(), nano * 1e-9, 1e-3, "Time in seconds not within tolerance of nanoSeconds");
+        Assert.assertEquals(aft.getWidth(), expectedWidth);
+        Assert.assertEquals(aft.getPrecision(), expectedPrecision);
+        Assert.assertNotNull(aft.toString(), "TimeUnit toString returned null");
+        final Matcher match = matchToString(aft);
+        Assert.assertTrue(match.matches(), "toString " + aft.toString() + " doesn't match our expected format");
+    }
+}
diff --git a/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/utils/BaseTest.java b/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/utils/BaseTest.java
new file mode 100644
index 0000000..ca57922
--- /dev/null
+++ b/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/utils/BaseTest.java
@@ -0,0 +1,568 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.utils;
+
+import htsjdk.tribble.Tribble;
+import htsjdk.tribble.readers.LineIterator;
+import htsjdk.tribble.readers.PositionalBufferedStream;
+import htsjdk.tribble.util.TabixUtils;
+import htsjdk.variant.bcf2.BCF2Codec;
+import htsjdk.variant.variantcontext.Genotype;
+import htsjdk.variant.variantcontext.VariantContext;
+import htsjdk.variant.vcf.VCFCodec;
+import htsjdk.variant.vcf.VCFConstants;
+import htsjdk.variant.vcf.VCFHeader;
+import htsjdk.variant.vcf.VCFHeaderLine;
+import org.apache.log4j.AppenderSkeleton;
+import org.apache.log4j.Level;
+import org.apache.log4j.Logger;
+import org.apache.log4j.PatternLayout;
+import org.apache.log4j.spi.LoggingEvent;
+import org.broadinstitute.gatk.utils.collections.Pair;
+import org.broadinstitute.gatk.utils.commandline.CommandLineUtils;
+import org.broadinstitute.gatk.utils.crypt.CryptUtils;
+import org.broadinstitute.gatk.utils.exceptions.ReviewedGATKException;
+import org.broadinstitute.gatk.utils.io.IOUtils;
+import org.broadinstitute.gatk.utils.variant.GATKVCFUtils;
+import org.testng.Assert;
+import org.testng.Reporter;
+import org.testng.SkipException;
+
+import java.io.File;
+import java.io.IOException;
+import java.io.PrintWriter;
+import java.util.*;
+
+/**
+ *
+ * User: aaron
+ * Date: Apr 14, 2009
+ * Time: 10:24:30 AM
+ *
+ * The Broad Institute
+ * SOFTWARE COPYRIGHT NOTICE AGREEMENT 
+ * This software and its documentation are copyright 2009 by the
+ * Broad Institute/Massachusetts Institute of Technology. All rights are reserved.
+ *
+ * This software is supplied without any warranty or guaranteed support whatsoever. Neither
+ * the Broad Institute nor MIT can be responsible for its use, misuse, or functionality.
+ *
+ */
+
+
+/**
+ * @author aaron
+ * @version 1.0
+ * @date Apr 14, 2009
+ * <p/>
+ * Class BaseTest
+ * <p/>
+ * This is the base test class for all of our test cases.  All test cases should extend from this
+ * class; it sets up the logger, and resolves the location of directories that we rely on.
+ */
+ at SuppressWarnings("unchecked")
+public abstract class BaseTest {
+    /** our log, which we want to capture anything from org.broadinstitute.sting */
+    public static final Logger logger = CommandLineUtils.getStingLogger();
+
+    private static final String CURRENT_DIRECTORY = System.getProperty("user.dir");
+    public static final String gatkDirectory = System.getProperty("gatkdir", CURRENT_DIRECTORY) + "/";
+    public static final String baseDirectory = System.getProperty("basedir", CURRENT_DIRECTORY) + "/";
+    public static final String testType = System.getProperty("testType"); // May be null
+    public static final String testTypeSubDirectory = testType == null ? "" : ("/" + testType); // May be empty
+
+    public static final String hg18Reference = "/seq/references/Homo_sapiens_assembly18/v0/Homo_sapiens_assembly18.fasta";
+    public static final String hg19Reference = "/seq/references/Homo_sapiens_assembly19/v1/Homo_sapiens_assembly19.fasta";
+    public static final String b36KGReference = "/humgen/1kg/reference/human_b36_both.fasta";
+    //public static final String b37KGReference = "/Users/depristo/Desktop/broadLocal/localData/human_g1k_v37.fasta";
+    public static final String b37KGReference = "/humgen/1kg/reference/human_g1k_v37.fasta";
+    public static final String b37KGReferenceWithDecoy = "/humgen/gsa-hpprojects/GATK/bundle/current/b37/human_g1k_v37_decoy.fasta";
+    public static final String hg19RefereneWithChrPrefixInChromosomeNames = "/humgen/gsa-hpprojects/GATK/bundle/current/hg19/ucsc.hg19.fasta";
+    public static final String GATKDataLocation = "/humgen/gsa-hpprojects/GATK/data/";
+    public static final String validationDataLocation = GATKDataLocation + "Validation_Data/";
+    public static final String evaluationDataLocation = GATKDataLocation + "Evaluation_Data/";
+    public static final String comparisonDataLocation = GATKDataLocation + "Comparisons/";
+    public static final String annotationDataLocation = GATKDataLocation + "Annotations/";
+
+    public static final String b37GoodBAM = validationDataLocation + "/CEUTrio.HiSeq.b37.chr20.10_11mb.bam";
+    public static final String b37GoodNA12878BAM = validationDataLocation + "/NA12878.HiSeq.WGS.bwa.cleaned.recal.hg19.20.bam";
+    public static final String b37_NA12878_OMNI = validationDataLocation + "/NA12878.omni.vcf";
+
+    public static final String dbsnpDataLocation = GATKDataLocation;
+    public static final String b36dbSNP129 = dbsnpDataLocation + "dbsnp_129_b36.vcf";
+    public static final String b37dbSNP129 = dbsnpDataLocation + "dbsnp_129_b37.vcf";
+    public static final String b37dbSNP132 = dbsnpDataLocation + "dbsnp_132_b37.vcf";
+    public static final String b37dbSNP138 = "/humgen/gsa-hpprojects/GATK/bundle/current/b37/dbsnp_138.b37.vcf";
+    public static final String hg18dbSNP132 = dbsnpDataLocation + "dbsnp_132.hg18.vcf";
+
+    public static final String hapmapDataLocation = comparisonDataLocation + "Validated/HapMap/3.3/";
+    public static final String b37hapmapGenotypes = hapmapDataLocation + "genotypes_r27_nr.b37_fwd.vcf";
+
+    public static final String intervalsLocation = "/seq/references/HybSelOligos/whole_exome_agilent_1.1_refseq_plus_3_boosters/";
+    public static final String hg19Intervals = intervalsLocation + "whole_exome_agilent_1.1_refseq_plus_3_boosters.Homo_sapiens_assembly19.targets.interval_list";
+    public static final String hg19Chr20Intervals = GATKDataLocation + "whole_exome_agilent_1.1_refseq_plus_3_boosters.Homo_sapiens_assembly19.targets.chr20.interval_list";
+
+    public static final boolean REQUIRE_NETWORK_CONNECTION = false;
+    private static final String networkTempDirRoot = "/broad/hptmp/";
+    private static final boolean networkTempDirRootExists = new File(networkTempDirRoot).exists();
+    private static final File networkTempDirFile;
+
+    private static final String privateTestDirRelative = "private/gatk-tools-private/src/test/resources/";
+    public static final String privateTestDir = new File(gatkDirectory, privateTestDirRelative).getAbsolutePath() + "/";
+    protected static final String privateTestDirRoot = privateTestDir.replace(privateTestDirRelative, "");
+
+    private static final String publicTestDirRelative = "public/gatk-engine/src/test/resources/";
+    public static final String publicTestDir = new File(gatkDirectory, publicTestDirRelative).getAbsolutePath() + "/";
+    protected static final String publicTestDirRoot = publicTestDir.replace(publicTestDirRelative, "");
+
+    public static final String keysDataLocation = validationDataLocation + "keys/";
+
+    public static final String gatkKeyFile = CryptUtils.GATK_USER_KEY_DIRECTORY + "gsamembers_broadinstitute.org.key";
+
+    public static final String exampleFASTA = publicTestDir + "exampleFASTA.fasta";
+
+    public final static String NA12878_PCRFREE = privateTestDir + "PCRFree.2x250.Illumina.20_10_11.bam";
+    public final static String NA12878_WEx = privateTestDir + "CEUTrio.HiSeq.WEx.b37_decoy.NA12878.20_10_11mb.bam";
+
+    public static final boolean queueTestRunModeIsSet = System.getProperty("queuetest.run", "").equals("true");
+
+    /** before the class starts up */
+    static {
+        // setup a basic log configuration
+        CommandLineUtils.configureConsoleLogging();
+
+        // setup our log layout
+        PatternLayout layout = new PatternLayout();
+        layout.setConversionPattern("TEST %C{1}.%M - %d{HH:mm:ss,SSS} - %m%n");
+
+        // now set the layout of all the loggers to our layout
+        CommandLineUtils.setLayout(logger, layout);
+
+        // Set the Root logger to only output warnings.
+        logger.setLevel(Level.WARN);
+
+        if (networkTempDirRootExists) {
+            networkTempDirFile = IOUtils.tempDir("temp.", ".dir", new File(networkTempDirRoot + System.getProperty("user.name")));
+            networkTempDirFile.deleteOnExit();
+        } else {
+            networkTempDirFile = null;
+        }
+
+
+        if ( REQUIRE_NETWORK_CONNECTION ) {
+            // find our file sources
+            if (!fileExist(hg18Reference) || !fileExist(hg19Reference) || !fileExist(b36KGReference)) {
+                logger.fatal("We can't locate the reference directories.  Aborting!");
+                throw new RuntimeException("BaseTest setup failed: unable to locate the reference directories");
+            }
+        }
+    }
+
+    /**
+     * Simple generic utility class to creating TestNG data providers:
+     *
+     * 1: inherit this class, as in
+     *
+     *      private class SummarizeDifferenceTest extends TestDataProvider {
+     *         public SummarizeDifferenceTest() {
+     *           super(SummarizeDifferenceTest.class);
+     *         }
+     *         ...
+     *      }
+     *
+     * Provide a reference to your class to the TestDataProvider constructor.
+     *
+     * 2: Create instances of your subclass.  Return from it the call to getTests, providing
+     * the class type of your test
+     *
+     * <code>
+     * {@literal @}DataProvider(name = "summaries")
+     * public Object[][] createSummaries() {
+     *   new SummarizeDifferenceTest().addDiff("A", "A").addSummary("A:2");
+     *   new SummarizeDifferenceTest().addDiff("A", "B").addSummary("A:1", "B:1");
+     *   return SummarizeDifferenceTest.getTests(SummarizeDifferenceTest.class);
+     * }
+     * </code>
+     *
+     * This class magically tracks created objects of this
+     */
+    public static class TestDataProvider {
+        private static final Map<Class, List<Object>> tests = new HashMap<>();
+        protected String name;
+
+        /**
+         * Create a new TestDataProvider instance bound to the class variable C
+         */
+        public TestDataProvider(Class c, String name) {
+            if ( ! tests.containsKey(c) )
+                tests.put(c, new ArrayList<>());
+            tests.get(c).add(this);
+            this.name = name;
+        }
+
+        public TestDataProvider(Class c) {
+            this(c, "");
+        }
+
+        public void setName(final String name) {
+            this.name = name;
+        }
+
+        /**
+         * Return all of the data providers in the form expected by TestNG of type class C
+         * @param c
+         * @return
+         */
+        public static Object[][] getTests(Class c) {
+            List<Object[]> params2 = new ArrayList<Object[]>();
+            for ( Object x : tests.get(c) ) params2.add(new Object[]{x});
+            return params2.toArray(new Object[][]{});
+        }
+
+        @Override
+        public String toString() {
+            return "TestDataProvider("+name+")";
+        }
+    }
+
+    /**
+     * test if the file exists
+     *
+     * @param file name as a string
+     * @return true if it exists
+     */
+    public static boolean fileExist(String file) {
+        File temp = new File(file);
+        return temp.exists();
+    }
+    
+    /**
+     * this appender looks for a specific message in the log4j stream.
+     * It can be used to verify that a specific message was generated to the logging system.
+     */
+    public static class ValidationAppender extends AppenderSkeleton {
+
+        private boolean foundString = false;
+        private String targetString = "";
+
+        public ValidationAppender(String target) {
+            targetString = target;
+        }
+
+        @Override
+        protected void append(LoggingEvent loggingEvent) {
+            if (loggingEvent.getMessage().equals(targetString))
+                foundString = true;
+        }
+
+        public void close() {
+            // do nothing
+        }
+
+        public boolean requiresLayout() {
+            return false;
+        }
+
+        public boolean foundString() {
+            return foundString;
+        }
+    }
+
+    /**
+     * Creates a temp file that will be deleted on exit after tests are complete.
+     * @param name Prefix of the file.
+     * @param extension Extension to concat to the end of the file.
+     * @return A file in the temporary directory starting with name, ending with extension, which will be deleted after the program exits.
+     */
+    public static File createTempFile(final String name, final String extension) {
+        try {
+            final File file = File.createTempFile(name, extension);
+            file.deleteOnExit();
+
+            // Mark corresponding indices for deletion on exit as well just in case an index is created for the temp file:
+            new File(file.getAbsolutePath() + Tribble.STANDARD_INDEX_EXTENSION).deleteOnExit();
+            new File(file.getAbsolutePath() + TabixUtils.STANDARD_INDEX_EXTENSION).deleteOnExit();
+            new File(file.getAbsolutePath() + ".bai").deleteOnExit();
+            new File(file.getAbsolutePath().replaceAll(extension + "$", ".bai")).deleteOnExit();
+
+            return file;
+        } catch (IOException ex) {
+            throw new ReviewedGATKException("Cannot create temp file: " + ex.getMessage(), ex);
+        }
+    }
+
+    /**
+     * Creates a temp list file that will be deleted on exit after tests are complete.
+     * @param tempFilePrefix Prefix of the file.
+     * @param lines lines to write to the file.
+     * @return A list file in the temporary directory starting with tempFilePrefix, which will be deleted after the program exits.
+     */
+    public static File createTempListFile(final String tempFilePrefix, final String... lines) {
+        try {
+            final File tempListFile = createTempFile(tempFilePrefix, ".list");
+
+            final PrintWriter out = new PrintWriter(tempListFile);
+            for (final String line : lines) {
+                out.println(line);
+            }
+            out.close();
+
+            return tempListFile;
+        } catch (IOException ex) {
+            throw new ReviewedGATKException("Cannot create temp file: " + ex.getMessage(), ex);
+        }
+    }
+
+    /**
+     * Creates a temp file that will be deleted on exit after tests are complete.
+     * @param name Name of the file.
+     * @return A file in the network temporary directory with name, which will be deleted after the program exits.
+     * @throws SkipException when the network is not available.
+     */
+    public static File tryCreateNetworkTempFile(String name) {
+        if (!networkTempDirRootExists)
+            throw new SkipException("Network temporary directory does not exist: " + networkTempDirRoot);
+        File file = new File(networkTempDirFile, name);
+        file.deleteOnExit();
+        return file;
+    }
+
+    /**
+     * Log this message so that it shows up inline during output as well as in html reports
+     *
+     * @param message
+     */
+    public static void log(final String message) {
+        Reporter.log(message, true);
+    }
+
+    private static final double DEFAULT_FLOAT_TOLERANCE = 1e-1;
+
+    public static final void assertEqualsDoubleSmart(final Object actual, final Double expected) {
+        Assert.assertTrue(actual instanceof Double, "Not a double");
+        assertEqualsDoubleSmart((double)(Double)actual, (double)expected);
+    }
+
+    public static final void assertEqualsDoubleSmart(final Object actual, final Double expected, final double tolerance) {
+        Assert.assertTrue(actual instanceof Double, "Not a double");
+        assertEqualsDoubleSmart((double)(Double)actual, (double)expected, tolerance);
+    }
+
+    public static final void assertEqualsDoubleSmart(final double actual, final double expected) {
+        assertEqualsDoubleSmart(actual, expected, DEFAULT_FLOAT_TOLERANCE);
+    }
+
+    public static final <T> void assertEqualsSet(final Set<T> actual, final Set<T> expected, final String info) {
+        final Set<T> actualSet = new HashSet<T>(actual);
+        final Set<T> expectedSet = new HashSet<T>(expected);
+        Assert.assertTrue(actualSet.equals(expectedSet), info); // note this is necessary due to testng bug for set comps
+    }
+
+    public static void assertEqualsDoubleSmart(final double actual, final double expected, final double tolerance) {
+        assertEqualsDoubleSmart(actual, expected, tolerance, null);
+    }
+
+    public static void assertEqualsDoubleSmart(final double actual, final double expected, final double tolerance, final String message) {
+        if ( Double.isNaN(expected) ) // NaN == NaN => false unfortunately
+            Assert.assertTrue(Double.isNaN(actual), "expected is nan, actual is not");
+        else if ( Double.isInfinite(expected) ) // NaN == NaN => false unfortunately
+            Assert.assertTrue(Double.isInfinite(actual), "expected is infinite, actual is not");
+        else {
+            final double delta = Math.abs(actual - expected);
+            final double ratio = Math.abs(actual / expected - 1.0);
+            Assert.assertTrue(delta < tolerance || ratio < tolerance, "expected = " + expected + " actual = " + actual
+                    + " not within tolerance " + tolerance
+                    + (message == null ? "" : "message: " + message));
+        }
+    }
+
+    public static void assertVariantContextsAreEqual( final VariantContext actual, final VariantContext expected ) {
+        Assert.assertNotNull(actual, "VariantContext expected not null");
+        Assert.assertEquals(actual.getChr(), expected.getChr(), "chr");
+        Assert.assertEquals(actual.getStart(), expected.getStart(), "start");
+        Assert.assertEquals(actual.getEnd(), expected.getEnd(), "end");
+        Assert.assertEquals(actual.getID(), expected.getID(), "id");
+        Assert.assertEquals(actual.getAlleles(), expected.getAlleles(), "alleles for " + expected + " vs " + actual);
+
+        assertAttributesEquals(actual.getAttributes(), expected.getAttributes());
+        Assert.assertEquals(actual.filtersWereApplied(), expected.filtersWereApplied(), "filtersWereApplied");
+        Assert.assertEquals(actual.isFiltered(), expected.isFiltered(), "isFiltered");
+        assertEqualsSet(actual.getFilters(), expected.getFilters(), "filters");
+        assertEqualsDoubleSmart(actual.getPhredScaledQual(), expected.getPhredScaledQual());
+
+        Assert.assertEquals(actual.hasGenotypes(), expected.hasGenotypes(), "hasGenotypes");
+        if ( expected.hasGenotypes() ) {
+            assertEqualsSet(actual.getSampleNames(), expected.getSampleNames(), "sample names set");
+            Assert.assertEquals(actual.getSampleNamesOrderedByName(), expected.getSampleNamesOrderedByName(), "sample names");
+            final Set<String> samples = expected.getSampleNames();
+            for ( final String sample : samples ) {
+                assertGenotypesAreEqual(actual.getGenotype(sample), expected.getGenotype(sample));
+            }
+        }
+    }
+
+    public static void assertVariantContextStreamsAreEqual(final Iterable<VariantContext> actual, final Iterable<VariantContext> expected) {
+        final Iterator<VariantContext> actualIT = actual.iterator();
+        final Iterator<VariantContext> expectedIT = expected.iterator();
+
+        while ( expectedIT.hasNext() ) {
+            final VariantContext expectedVC = expectedIT.next();
+            if ( expectedVC == null )
+                continue;
+
+            VariantContext actualVC;
+            do {
+                Assert.assertTrue(actualIT.hasNext(), "Too few records found in actual");
+                actualVC = actualIT.next();
+            } while ( actualIT.hasNext() && actualVC == null );
+
+            if ( actualVC == null )
+                Assert.fail("Too few records in actual");
+
+            assertVariantContextsAreEqual(actualVC, expectedVC);
+        }
+        Assert.assertTrue(! actualIT.hasNext(), "Too many records found in actual");
+    }
+
+
+    public static void assertGenotypesAreEqual(final Genotype actual, final Genotype expected) {
+        Assert.assertEquals(actual.getSampleName(), expected.getSampleName(), "Genotype names");
+        Assert.assertEquals(actual.getAlleles(), expected.getAlleles(), "Genotype alleles");
+        Assert.assertEquals(actual.getGenotypeString(), expected.getGenotypeString(), "Genotype string");
+        Assert.assertEquals(actual.getType(), expected.getType(), "Genotype type");
+
+        // filters are the same
+        Assert.assertEquals(actual.getFilters(), expected.getFilters(), "Genotype fields");
+        Assert.assertEquals(actual.isFiltered(), expected.isFiltered(), "Genotype isFiltered");
+
+        // inline attributes
+        Assert.assertEquals(actual.getDP(), expected.getDP(), "Genotype dp");
+        Assert.assertTrue(Arrays.equals(actual.getAD(), expected.getAD()));
+        Assert.assertEquals(actual.getGQ(), expected.getGQ(), "Genotype gq");
+        Assert.assertEquals(actual.hasPL(), expected.hasPL(), "Genotype hasPL");
+        Assert.assertEquals(actual.hasAD(), expected.hasAD(), "Genotype hasAD");
+        Assert.assertEquals(actual.hasGQ(), expected.hasGQ(), "Genotype hasGQ");
+        Assert.assertEquals(actual.hasDP(), expected.hasDP(), "Genotype hasDP");
+
+        Assert.assertEquals(actual.hasLikelihoods(), expected.hasLikelihoods(), "Genotype haslikelihoods");
+        Assert.assertEquals(actual.getLikelihoodsString(), expected.getLikelihoodsString(), "Genotype getlikelihoodsString");
+        Assert.assertEquals(actual.getLikelihoods(), expected.getLikelihoods(), "Genotype getLikelihoods");
+        Assert.assertTrue(Arrays.equals(actual.getPL(), expected.getPL()));
+
+        Assert.assertEquals(actual.getPhredScaledQual(), expected.getPhredScaledQual(), "Genotype phredScaledQual");
+        assertAttributesEquals(actual.getExtendedAttributes(), expected.getExtendedAttributes());
+        Assert.assertEquals(actual.isPhased(), expected.isPhased(), "Genotype isPhased");
+        Assert.assertEquals(actual.getPloidy(), expected.getPloidy(), "Genotype getPloidy");
+    }
+
+    public static void assertVCFHeadersAreEqual(final VCFHeader actual, final VCFHeader expected) {
+        Assert.assertEquals(actual.getMetaDataInSortedOrder().size(), expected.getMetaDataInSortedOrder().size(), "No VCF header lines");
+
+        // for some reason set.equals() is returning false but all paired elements are .equals().  Perhaps compare to is busted?
+        //Assert.assertEquals(actual.getMetaDataInInputOrder(), expected.getMetaDataInInputOrder());
+        final List<VCFHeaderLine> actualLines = new ArrayList<VCFHeaderLine>(actual.getMetaDataInSortedOrder());
+        final List<VCFHeaderLine> expectedLines = new ArrayList<VCFHeaderLine>(expected.getMetaDataInSortedOrder());
+        for ( int i = 0; i < actualLines.size(); i++ ) {
+            Assert.assertEquals(actualLines.get(i), expectedLines.get(i), "VCF header lines");
+        }
+    }
+
+    public static void assertVCFandBCFFilesAreTheSame(final File vcfFile, final File bcfFile) throws IOException {
+        final Pair<VCFHeader, GATKVCFUtils.VCIterable<LineIterator>> vcfData = GATKVCFUtils.readAllVCs(vcfFile, new VCFCodec());
+        final Pair<VCFHeader, GATKVCFUtils.VCIterable<PositionalBufferedStream>> bcfData = GATKVCFUtils.readAllVCs(bcfFile, new BCF2Codec());
+        assertVCFHeadersAreEqual(bcfData.getFirst(), vcfData.getFirst());
+        assertVariantContextStreamsAreEqual(bcfData.getSecond(), vcfData.getSecond());
+    }
+
+    private static void assertAttributeEquals(final String key, final Object actual, final Object expected) {
+        if ( expected instanceof Double ) {
+            // must be very tolerant because doubles are being rounded to 2 sig figs
+            assertEqualsDoubleSmart(actual, (Double) expected, 1e-2);
+        } else
+            Assert.assertEquals(actual, expected, "Attribute " + key);
+    }
+
+    private static void assertAttributesEquals(final Map<String, Object> actual, Map<String, Object> expected) {
+        final Set<String> expectedKeys = new HashSet<String>(expected.keySet());
+
+        for ( final Map.Entry<String, Object> act : actual.entrySet() ) {
+            final Object actualValue = act.getValue();
+            if ( expected.containsKey(act.getKey()) && expected.get(act.getKey()) != null ) {
+                final Object expectedValue = expected.get(act.getKey());
+                if ( expectedValue instanceof List ) {
+                    final List<Object> expectedList = (List<Object>)expectedValue;
+                    Assert.assertTrue(actualValue instanceof List, act.getKey() + " should be a list but isn't");
+                    final List<Object> actualList = (List<Object>)actualValue;
+                    Assert.assertEquals(actualList.size(), expectedList.size(), act.getKey() + " size");
+                    for ( int i = 0; i < expectedList.size(); i++ )
+                        assertAttributeEquals(act.getKey(), actualList.get(i), expectedList.get(i));
+                } else
+                    assertAttributeEquals(act.getKey(), actualValue, expectedValue);
+            } else {
+                // it's ok to have a binding in x -> null that's absent in y
+                Assert.assertNull(actualValue, act.getKey() + " present in one but not in the other");
+            }
+            expectedKeys.remove(act.getKey());
+        }
+
+        // now expectedKeys contains only the keys found in expected but not in actual,
+        // and they must all be null
+        for ( final String missingExpected : expectedKeys ) {
+            final Object value = expected.get(missingExpected);
+            Assert.assertTrue(isMissing(value), "Attribute " + missingExpected + " missing in one but not in other" );
+        }
+    }
+
+    private static final boolean isMissing(final Object value) {
+        if ( value == null ) return true;
+        else if ( value.equals(VCFConstants.MISSING_VALUE_v4) ) return true;
+        else if ( value instanceof List ) {
+            // handles the case where all elements are null or the list is empty
+            for ( final Object elt : (List)value)
+                if ( elt != null )
+                    return false;
+            return true;
+        } else
+            return false;
+    }
+
+    /**
+     * Checks whether two double array contain the same values or not.
+     * @param actual actual produced array.
+     * @param expected expected array.
+     * @param tolerance maximum difference between double value to be consider equivalent.
+     */
+    protected static void assertEqualsDoubleArray(final double[] actual, final double[] expected, final double tolerance) {
+        if (expected == null)
+            Assert.assertNull(actual);
+        else {
+            Assert.assertNotNull(actual);
+            Assert.assertEquals(actual.length,expected.length,"array length");
+        }
+        for (int i = 0; i < actual.length; i++)
+            Assert.assertEquals(actual[i],expected[i],tolerance,"array position " + i);
+    }
+}
diff --git a/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/utils/BaseUtilsUnitTest.java b/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/utils/BaseUtilsUnitTest.java
new file mode 100644
index 0000000..b532baf
--- /dev/null
+++ b/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/utils/BaseUtilsUnitTest.java
@@ -0,0 +1,179 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.utils;
+
+import org.broadinstitute.gatk.utils.BaseTest;
+import org.broadinstitute.gatk.engine.GenomeAnalysisEngine;
+import org.testng.Assert;
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.DataProvider;
+import org.testng.annotations.Test;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Random;
+
+
+public class BaseUtilsUnitTest extends BaseTest {
+    @BeforeClass
+    public void init() { }
+
+    @Test
+    public void testMostFrequentBaseFraction() {
+        logger.warn("Executing testMostFrequentBaseFraction");
+
+        compareFrequentBaseFractionToExpected("AAAAA", 1.0);
+        compareFrequentBaseFractionToExpected("ACCG", 0.5);
+        compareFrequentBaseFractionToExpected("ACCCCTTTTG", 4.0/10.0);
+    }
+
+    private void compareFrequentBaseFractionToExpected(String sequence, double expected) {
+        double fraction = BaseUtils.mostFrequentBaseFraction(sequence.getBytes());
+        Assert.assertTrue(MathUtils.compareDoubles(fraction, expected) == 0);
+    }
+
+    @Test
+    public void testConvertIUPACtoN() {
+
+        checkBytesAreEqual(BaseUtils.convertIUPACtoN(new byte[]{'A', 'A', 'A'}, false, false), new byte[]{'A', 'A', 'A'});
+        checkBytesAreEqual(BaseUtils.convertIUPACtoN(new byte[]{'W', 'A', 'A'}, false, false), new byte[]{'N', 'A', 'A'});
+        checkBytesAreEqual(BaseUtils.convertIUPACtoN(new byte[]{'A', 'M', 'A'}, false, false), new byte[]{'A', 'N', 'A'});
+        checkBytesAreEqual(BaseUtils.convertIUPACtoN(new byte[]{'A', 'A', 'K'}, false, false), new byte[]{'A', 'A', 'N'});
+        checkBytesAreEqual(BaseUtils.convertIUPACtoN(new byte[]{'M', 'M', 'M'}, false, false), new byte[]{'N', 'N', 'N'});
+    }
+
+    private void checkBytesAreEqual(final byte[] b1, final byte[] b2) {
+        for ( int i = 0; i < b1.length; i++ )
+            Assert.assertEquals(b1[i], b2[i]);
+    }
+
+    @Test
+    public void testConvertBasesToIUPAC() {
+
+        for ( final BaseUtils.Base b : BaseUtils.Base.values() ) {
+            if ( BaseUtils.isRegularBase(b.base) )
+                Assert.assertEquals(BaseUtils.basesToIUPAC(b.base, b.base), b.base, "testing same base");
+        }
+
+        Assert.assertEquals(BaseUtils.basesToIUPAC((byte)'A', (byte)'X'), 'N', "testing non-standard base");
+        Assert.assertEquals(BaseUtils.basesToIUPAC((byte)'X', (byte)'A'), 'N', "testing non-standard base");
+        Assert.assertEquals(BaseUtils.basesToIUPAC((byte)'X', (byte)'X'), 'N', "testing non-standard base");
+
+        Assert.assertEquals(BaseUtils.basesToIUPAC((byte)'A', (byte)'T'), 'W', "testing A/T=W");
+        Assert.assertEquals(BaseUtils.basesToIUPAC((byte)'T', (byte)'A'), 'W', "testing T/A=W");
+        Assert.assertEquals(BaseUtils.basesToIUPAC((byte) 'G', (byte) 'T'), 'K', "testing G/T=K");
+        Assert.assertEquals(BaseUtils.basesToIUPAC((byte) 'T', (byte) 'G'), 'K', "testing T/G=K");
+    }
+
+    @Test
+    public void testTransitionTransversion() {
+        logger.warn("Executing testTransitionTransversion");
+
+        Assert.assertTrue( BaseUtils.SNPSubstitutionType( (byte)'A', (byte)'T' ) == BaseUtils.BaseSubstitutionType.TRANSVERSION );
+        Assert.assertTrue( BaseUtils.SNPSubstitutionType( (byte)'A', (byte)'C' ) == BaseUtils.BaseSubstitutionType.TRANSVERSION );
+        Assert.assertTrue( BaseUtils.SNPSubstitutionType( (byte)'A', (byte)'G' ) == BaseUtils.BaseSubstitutionType.TRANSITION );
+        Assert.assertTrue( BaseUtils.SNPSubstitutionType( (byte)'C', (byte)'A' ) == BaseUtils.BaseSubstitutionType.TRANSVERSION );
+        Assert.assertTrue( BaseUtils.SNPSubstitutionType( (byte)'C', (byte)'T' ) == BaseUtils.BaseSubstitutionType.TRANSITION );
+        Assert.assertTrue( BaseUtils.SNPSubstitutionType( (byte)'C', (byte)'G' ) == BaseUtils.BaseSubstitutionType.TRANSVERSION );
+        Assert.assertTrue( BaseUtils.SNPSubstitutionType( (byte)'T', (byte)'A' ) == BaseUtils.BaseSubstitutionType.TRANSVERSION );
+        Assert.assertTrue( BaseUtils.SNPSubstitutionType( (byte)'T', (byte)'C' ) == BaseUtils.BaseSubstitutionType.TRANSITION );
+        Assert.assertTrue( BaseUtils.SNPSubstitutionType( (byte)'T', (byte)'G' ) == BaseUtils.BaseSubstitutionType.TRANSVERSION );
+        Assert.assertTrue( BaseUtils.SNPSubstitutionType( (byte)'G', (byte)'A' ) == BaseUtils.BaseSubstitutionType.TRANSITION );
+        Assert.assertTrue( BaseUtils.SNPSubstitutionType( (byte)'G', (byte)'T' ) == BaseUtils.BaseSubstitutionType.TRANSVERSION );
+        Assert.assertTrue( BaseUtils.SNPSubstitutionType( (byte)'G', (byte)'C' ) == BaseUtils.BaseSubstitutionType.TRANSVERSION );
+
+        Assert.assertTrue( BaseUtils.SNPSubstitutionType( (byte)'a', (byte)'T' ) == BaseUtils.BaseSubstitutionType.TRANSVERSION );
+        Assert.assertTrue( BaseUtils.SNPSubstitutionType( (byte)'a', (byte)'C' ) == BaseUtils.BaseSubstitutionType.TRANSVERSION );
+        Assert.assertTrue( BaseUtils.SNPSubstitutionType( (byte)'A', (byte)'T' ) == BaseUtils.BaseSubstitutionType.TRANSVERSION );
+        Assert.assertTrue( BaseUtils.SNPSubstitutionType( (byte)'A', (byte)'C' ) == BaseUtils.BaseSubstitutionType.TRANSVERSION );
+        Assert.assertTrue( BaseUtils.SNPSubstitutionType( (byte)'A', (byte)'t' ) == BaseUtils.BaseSubstitutionType.TRANSVERSION );
+        Assert.assertTrue( BaseUtils.SNPSubstitutionType( (byte)'A', (byte)'c' ) == BaseUtils.BaseSubstitutionType.TRANSVERSION );
+        Assert.assertTrue( BaseUtils.SNPSubstitutionType( (byte)'a', (byte)'t' ) == BaseUtils.BaseSubstitutionType.TRANSVERSION );
+        Assert.assertTrue( BaseUtils.SNPSubstitutionType( (byte)'a', (byte)'c' ) == BaseUtils.BaseSubstitutionType.TRANSVERSION );
+    }
+
+    @Test
+    public void testReverseComplementString() {
+        logger.warn("Executing testReverseComplementString");
+
+        compareRCStringToExpected("ACGGT", "ACCGT");
+        compareRCStringToExpected("TCGTATATCTCGCTATATATATATAGCTCTAGTATA", "TATACTAGAGCTATATATATATAGCGAGATATACGA");
+        compareRCStringToExpected("AAAN", "NTTT");
+    }
+
+    private void compareRCStringToExpected(String fw, String rcExp) {
+        String rcObs = BaseUtils.simpleReverseComplement(fw);
+
+        Assert.assertTrue(rcObs.equals(rcExp));
+    }
+
+    @Test(dataProvider="baseComparatorData")
+    public void testBaseComparator(final Collection<byte[]> basesToSort) {
+        final ArrayList<byte[]> sorted = new ArrayList<>(basesToSort);
+        Collections.sort(sorted, BaseUtils.BASES_COMPARATOR);
+        for (int i = 0; i < sorted.size(); i++)   {
+            Assert.assertEquals(BaseUtils.BASES_COMPARATOR.compare(sorted.get(i),sorted.get(i)),0);
+            final String iString = new String(sorted.get(i));
+            for (int j = i; j < sorted.size(); j++) {
+                final String jString = new String(sorted.get(j));
+                if (iString.compareTo(jString) == 0)
+                    Assert.assertEquals(BaseUtils.BASES_COMPARATOR.compare(sorted.get(i),sorted.get(j)),0);
+                else
+                    Assert.assertTrue(BaseUtils.BASES_COMPARATOR.compare(sorted.get(i),sorted.get(j)) * iString.compareTo(jString) > 0);
+                Assert.assertTrue(BaseUtils.BASES_COMPARATOR.compare(sorted.get(i),sorted.get(j)) <= 0);
+            }
+        }
+    }
+
+    @DataProvider(name="baseComparatorData")
+    public Object[][] baseComparatorData() {
+        final int testCount = 10;
+        final int testSizeAverage = 10;
+        final int testSizeDeviation = 10;
+        final int haplotypeSizeAverage = 100;
+        final int haplotypeSizeDeviation = 100;
+
+        final Object[][] result = new Object[testCount][];
+
+        GenomeAnalysisEngine.resetRandomGenerator();
+        final Random rnd = GenomeAnalysisEngine.getRandomGenerator();
+
+        for (int i = 0; i < testCount; i++) {
+            final int size = (int) Math.max(0,rnd.nextDouble() * testSizeDeviation + testSizeAverage);
+            final ArrayList<byte[]> bases = new ArrayList<>(size);
+            for (int j = 0; j < size; j++) {
+                final int jSize = (int) Math.max(0,rnd.nextDouble() * haplotypeSizeDeviation + haplotypeSizeAverage);
+                final byte[] b = new byte[jSize];
+                for (int k = 0; k < jSize; k++)
+                    b[k] = BaseUtils.baseIndexToSimpleBase(rnd.nextInt(4));
+                bases.add(b);
+            }
+            result[i] = new Object[] { bases };
+        }
+        return result;
+    }
+}
diff --git a/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/utils/BitSetUtilsUnitTest.java b/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/utils/BitSetUtilsUnitTest.java
new file mode 100644
index 0000000..87a5914
--- /dev/null
+++ b/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/utils/BitSetUtilsUnitTest.java
@@ -0,0 +1,85 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.utils;
+
+import org.broadinstitute.gatk.engine.GenomeAnalysisEngine;
+import org.testng.Assert;
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.Test;
+
+import java.util.Random;
+
+/**
+ * @author Mauricio Carneiro
+ * @since 3/5/12
+ */
+
+public class BitSetUtilsUnitTest {
+    private static int RANDOM_NUMBERS_TO_TRY = 87380;
+    private static Random random;
+
+    @BeforeClass
+    public void init() {
+        random = GenomeAnalysisEngine.getRandomGenerator();
+    }
+
+    @Test(enabled = true)
+    public void testLongBitSet() {
+        long[] numbers = {0L, 1L, 428L, 65536L, 239847L, 4611686018427387903L, Long.MAX_VALUE, Long.MIN_VALUE, -1L, -2L, -7L, -128L, -65536L, -100000L};
+        for (long n : numbers)
+            Assert.assertEquals(BitSetUtils.longFrom(BitSetUtils.bitSetFrom(n)), n);
+
+        for (int i = 0; i < RANDOM_NUMBERS_TO_TRY; i++) {
+            long n = random.nextLong();
+            Assert.assertEquals(BitSetUtils.longFrom(BitSetUtils.bitSetFrom(n)), n);    // Because class Random uses a seed with only 48 bits, this algorithm will not return all possible long values.
+        }
+    }
+
+    @Test(enabled = true)
+    public void testShortBitSet() {
+        short[] numbers = {0, 1, 428, 25934, 23847, 16168, Short.MAX_VALUE, Short.MIN_VALUE, -1, -2, -7, -128, -12312, -31432};
+        for (long n : numbers)
+            Assert.assertEquals(BitSetUtils.shortFrom(BitSetUtils.bitSetFrom(n)), n);
+
+        for (int i = 0; i < RANDOM_NUMBERS_TO_TRY; i++) {
+            short n = (short) random.nextInt();
+            Assert.assertEquals(BitSetUtils.shortFrom(BitSetUtils.bitSetFrom(n)), n);
+        }
+    }
+
+    @Test(enabled = false)
+    public void testDNAAndBitSetConversion() {
+        String[] dna = {"AGGTGTTGT", "CCCCCCCCCCCCCC", "GGGGGGGGGGGGGG", "TTTTTTTTTTTTTT", "GTAGACCGATCTCAGCTAGT", "AACGTCAATGCAGTCAAGTCAGACGTGGGTT", "TTTTTTTTTTTTTTTTTTTTTTTTTTTTTT", "TTTTTTTTTTTTTTTTTTTTTTTTTTTTTTT"};
+
+        // Test all contexts of size 1-8.
+        //for (long n = 0; n < RANDOM_NUMBERS_TO_TRY; n++)
+        //    Assert.assertEquals(BitSetUtils.longFrom(BitSetUtils.bitSetFrom(ContextCovariate.contextFromKey(BitSetUtils.bitSetFrom(n)))), n);
+
+        // Test the special cases listed in the dna array
+        //for (String d : dna)
+        //    Assert.assertEquals(BitSetUtils.dnaFrom(BitSetUtils.bitSetFrom(d)), d);
+    }
+}
diff --git a/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/utils/ExampleToCopyUnitTest.java b/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/utils/ExampleToCopyUnitTest.java
new file mode 100644
index 0000000..8c6e24c
--- /dev/null
+++ b/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/utils/ExampleToCopyUnitTest.java
@@ -0,0 +1,241 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.utils;
+
+
+// the imports for unit testing.
+
+
+import htsjdk.samtools.reference.IndexedFastaSequenceFile;
+import htsjdk.samtools.SAMFileHeader;
+import htsjdk.samtools.SAMFileReader;
+import htsjdk.samtools.SAMRecord;
+import org.broadinstitute.gatk.utils.fasta.CachingIndexedFastaSequenceFile;
+import org.broadinstitute.gatk.utils.pileup.PileupElement;
+import org.broadinstitute.gatk.utils.pileup.ReadBackedPileup;
+import org.broadinstitute.gatk.utils.pileup.ReadBackedPileupImpl;
+import org.broadinstitute.gatk.utils.sam.ArtificialBAMBuilder;
+import org.broadinstitute.gatk.utils.sam.ArtificialSAMUtils;
+import org.broadinstitute.gatk.utils.sam.GATKSAMRecord;
+import org.broadinstitute.gatk.utils.sam.GATKSamRecordFactory;
+import htsjdk.variant.variantcontext.Allele;
+import htsjdk.variant.variantcontext.VariantContext;
+import htsjdk.variant.variantcontext.VariantContextBuilder;
+import org.testng.Assert;
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.DataProvider;
+import org.testng.annotations.Test;
+
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.util.*;
+
+public class ExampleToCopyUnitTest extends BaseTest {
+    // example genome loc parser for this test, can be deleted if you don't use the reference
+    private GenomeLocParser genomeLocParser;
+
+    // example fasta index file, can be deleted if you don't use the reference
+    private IndexedFastaSequenceFile seq;
+
+    @BeforeClass
+    public void setup() throws FileNotFoundException {
+        // sequence
+        seq = new CachingIndexedFastaSequenceFile(new File(b37KGReference));
+        genomeLocParser = new GenomeLocParser(seq);
+    }
+
+    /**
+     * Combinatorial unit test data provider example.
+     *
+     * Creates data for testMyData test function, containing two arguments, start and size at each value
+     *
+     * @return Object[][] for testng DataProvider
+     */
+    @DataProvider(name = "MyDataProvider")
+    public Object[][] makeMyDataProvider() {
+        List<Object[]> tests = new ArrayList<Object[]>();
+
+        // this functionality can be adapted to provide input data for whatever you might want in your data
+        for ( final int start : Arrays.asList(1, 10, 100) ) {
+            for ( final int size : Arrays.asList(1, 10, 100, 1000) ) {
+                tests.add(new Object[]{start, size});
+            }
+        }
+
+        return tests.toArray(new Object[][]{});
+    }
+
+    /**
+     * Example testng test using MyDataProvider
+     */
+    @Test(dataProvider = "MyDataProvider")
+    public void testMyData(final int start, final int size) {
+        // adaptor this code to do whatever testing you want given the arguments start and size
+        Assert.assertTrue(start >= 0);
+        Assert.assertTrue(size >= 0);
+    }
+
+    /**
+     * DataProvider example using a class-based data structure
+     */
+    private class MyDataProviderClass extends TestDataProvider {
+        private int start;
+        private int size;
+
+        private MyDataProviderClass(int start, int size) {
+            super(MyDataProviderClass.class);
+            this.start = start;
+            this.size = size;
+        }
+    }
+
+    @DataProvider(name = "MyClassBasedDataProvider")
+    public Object[][] makeMyDataProviderClass() {
+        // this functionality can be adapted to provide input data for whatever you might want in your data
+        for ( final int start : Arrays.asList(1, 10, 100) ) {
+            for ( final int size : Arrays.asList(1, 10, 100, 1000) ) {
+                new MyDataProviderClass(start, size);
+            }
+        }
+
+        return TestDataProvider.getTests(MyDataProviderClass.class);
+    }
+
+    /**
+     * Example testng test using MyClassBasedDataProvider
+     */
+    @Test(dataProvider = "MyClassBasedDataProvider")
+    public void testMyDataProviderClass(MyDataProviderClass testSpec) {
+        // adaptor this code to do whatever testing you want given the arguments start and size
+        Assert.assertTrue(testSpec.start >= 0);
+        Assert.assertTrue(testSpec.size >= 0);
+    }
+
+    /**
+     * A unit test that creates an artificial read for testing some code that uses reads
+     */
+    @Test()
+    public void testWithARead() {
+        final SAMFileHeader header = ArtificialSAMUtils.createArtificialSamHeader(seq.getSequenceDictionary());
+        final GATKSAMRecord read = ArtificialSAMUtils.createArtificialRead(header, "myRead", 0, 1, 10);
+        Assert.assertEquals(read.getReadLength(), 10);
+        // TODO -- add some tests here using read
+    }
+
+    /**
+     * A unit test that creates a GenomeLoc for testing
+     */
+    @Test()
+    public void testWithAGenomeLoc() {
+        final GenomeLoc loc = genomeLocParser.createGenomeLoc("1", 1, 10);
+        Assert.assertEquals(loc.size(), 10);
+        // TODO -- add some tests here using the loc
+    }
+
+    /**
+     * A unit test that creates an artificial read for testing some code that uses reads
+     *
+     * Note that effective creation of RBPs isn't so good.  If you need pileups of specific properties, you shoud
+     * look into building them yourself as in the example below
+     */
+    @Test()
+    public void testWithAPileup() {
+        final SAMFileHeader header = ArtificialSAMUtils.createArtificialSamHeader(seq.getSequenceDictionary());
+        final GenomeLoc myLocation = genomeLocParser.createGenomeLoc("1", 10);
+        final ReadBackedPileup pileup = ArtificialSAMUtils.createReadBackedPileup(header, myLocation, 10, 400, 10);
+        Assert.assertFalse(pileup.isEmpty());
+        // TODO -- add some tests here using pileup
+    }
+
+    /**
+     * A unit test that creates an artificial read for testing some code that uses reads
+     *
+     * Builds the pileup from scratch to have specific properties
+     */
+    @Test()
+    public void testBuildingAPileupWithSpecificProperties() {
+        final SAMFileHeader header = ArtificialSAMUtils.createArtificialSamHeader(seq.getSequenceDictionary());
+        final GenomeLoc myLocation = genomeLocParser.createGenomeLoc("1", 10);
+
+        final int pileupSize = 100;
+        final int readLength = 10;
+        final List<GATKSAMRecord> reads = new LinkedList<GATKSAMRecord>();
+        for ( int i = 0; i < pileupSize; i++ ) {
+            final GATKSAMRecord read = ArtificialSAMUtils.createArtificialRead(header, "myRead" + i, 0, 1, readLength);
+            final byte[] bases = Utils.dupBytes((byte)'A', readLength);
+            bases[0] = (byte)(i % 2 == 0 ? 'A' : 'C'); // every other base is a C
+
+            // set the read's bases and quals
+            read.setReadBases(bases);
+            read.setBaseQualities(Utils.dupBytes((byte)30, readLength));
+            reads.add(read);
+        }
+
+        // create a pileup with all reads having offset 0
+        final ReadBackedPileup pileup = new ReadBackedPileupImpl(myLocation, reads, 0);
+        // TODO -- add some tests here using pileup
+
+        // this code ensures that the pileup example is correct.  Can be deleted
+        Assert.assertEquals(pileup.getNumberOfElements(), pileupSize);
+        int nA = 0, nC = 0;
+        for ( final PileupElement p : pileup ) {
+            if ( p.getBase() == 'A' ) nA++;
+            if ( p.getBase() == 'C' ) nC++;
+        }
+        Assert.assertEquals(nA, pileupSize / 2);
+        Assert.assertEquals(nC, pileupSize / 2);
+
+    }
+
+    /**
+     * A unit test that creates an artificial read for testing some code that uses reads
+     */
+    @Test()
+    public void testWithBAMFile() {
+        // create a fake BAM file, and iterate through it
+        final ArtificialBAMBuilder bamBuilder = new ArtificialBAMBuilder(seq, 20, 10);
+        final File bam = bamBuilder.makeTemporarilyBAMFile();
+        final SAMFileReader reader = new SAMFileReader(bam);
+        reader.setSAMRecordFactory(new GATKSamRecordFactory());
+
+        final Iterator<SAMRecord> bamIt = reader.iterator();
+        while ( bamIt.hasNext() ) {
+            final GATKSAMRecord read = (GATKSAMRecord)bamIt.next(); // all reads are actually GATKSAMRecords
+            // TODO -- add some tests that use reads from a BAM
+        }
+    }
+
+    /**
+     * Test code that creates VariantContexts
+     */
+    @Test()
+    public void testWithVariantContext() throws Exception {
+        final List<Allele> alleles = Arrays.asList(Allele.create("A", true), Allele.create("C"));
+        final VariantContext vc = new VariantContextBuilder("test", "1", 10, 10, alleles).make();
+        Assert.assertTrue(vc.getAlleles().size() >= 0);
+        // TODO -- add some tests that use VariantContext
+    }
+}
\ No newline at end of file
diff --git a/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/utils/GATKTextReporter.java b/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/utils/GATKTextReporter.java
new file mode 100644
index 0000000..957ccd2
--- /dev/null
+++ b/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/utils/GATKTextReporter.java
@@ -0,0 +1,41 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.utils;
+
+import org.testng.reporters.TextReporter;
+
+/**
+ * HACK: Create a variant of the TestNG TextReporter that can be run with no
+ *       arguments, and can therefore be added to the TestNG listener list.
+ *
+ * @author hanna
+ * @version 0.1
+ */
+public class GATKTextReporter extends TextReporter {
+    public GATKTextReporter() {
+        super("GATK test suite",2);
+    }
+}
diff --git a/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/utils/GenomeLocParserBenchmark.java b/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/utils/GenomeLocParserBenchmark.java
new file mode 100644
index 0000000..7f19879
--- /dev/null
+++ b/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/utils/GenomeLocParserBenchmark.java
@@ -0,0 +1,81 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.utils;
+
+import com.google.caliper.Param;
+import com.google.caliper.SimpleBenchmark;
+import htsjdk.samtools.reference.IndexedFastaSequenceFile;
+import org.broadinstitute.gatk.utils.fasta.CachingIndexedFastaSequenceFile;
+
+import java.io.File;
+
+/**
+ * Caliper microbenchmark of genome loc parser
+ */
+public class GenomeLocParserBenchmark extends SimpleBenchmark {
+    private IndexedFastaSequenceFile seq;
+    private final int ITERATIONS = 1000000;
+
+    @Param({"NEW", "NONE"})
+    GenomeLocParser.ValidationLevel validationLevel; // set automatically by framework
+
+    @Param({"true", "false"})
+    boolean useContigIndex; // set automatically by framework
+
+    @Override protected void setUp() throws Exception {
+        seq = new CachingIndexedFastaSequenceFile(new File("/Users/depristo/Desktop/broadLocal/localData/human_g1k_v37.fasta"));
+    }
+//
+//    public void timeSequentialCreationFromGenomeLoc(int rep) {
+//        final GenomeLocParser genomeLocParser = new GenomeLocParser(seq.getSequenceDictionary(), validationLevel);
+//        GenomeLoc last = genomeLocParser.createGenomeLoc("1", 1, 1);
+//        for ( int i = 0; i < rep; i++ ) {
+//            for ( int j = 1; j < ITERATIONS; j++ ) {
+//                if ( useContigIndex )
+//                    last = genomeLocParser.createGenomeLoc(last.getContig(), last.getContigIndex(), last.getStart() + 1);
+//                else
+//                    last = genomeLocParser.createGenomeLoc(last.getContig(), last.getStart() + 1);
+//            }
+//        }
+//    }
+//
+//    public void timeSequentialCreationFromGenomeLocOriginal(int rep) {
+//        final GenomeLocParserOriginal genomeLocParser = new GenomeLocParserOriginal(seq.getSequenceDictionary());
+//        GenomeLoc last = genomeLocParser.createGenomeLoc("1", 1, 1);
+//        for ( int i = 0; i < rep; i++ ) {
+//            for ( int j = 1; j < ITERATIONS; j++ ) {
+//                if ( useContigIndex )
+//                    last = genomeLocParser.createGenomeLoc(last.getContig(), last.getContigIndex(), last.getStart() + 1);
+//                else
+//                    last = genomeLocParser.createGenomeLoc(last.getContig(), last.getStart() + 1);
+//            }
+//        }
+//    }
+
+    public static void main(String[] args) {
+        com.google.caliper.Runner.main(GenomeLocParserBenchmark.class, args);
+    }
+}
diff --git a/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/utils/GenomeLocParserUnitTest.java b/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/utils/GenomeLocParserUnitTest.java
new file mode 100644
index 0000000..d413633
--- /dev/null
+++ b/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/utils/GenomeLocParserUnitTest.java
@@ -0,0 +1,509 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.utils;
+
+
+import htsjdk.samtools.SAMFileHeader;
+import htsjdk.samtools.SAMSequenceDictionary;
+import htsjdk.samtools.SAMSequenceRecord;
+import htsjdk.tribble.BasicFeature;
+import htsjdk.tribble.Feature;
+import org.broadinstitute.gatk.utils.BaseTest;
+import org.broadinstitute.gatk.utils.exceptions.ReviewedGATKException;
+import org.broadinstitute.gatk.utils.exceptions.UserException;
+import org.broadinstitute.gatk.utils.fasta.CachingIndexedFastaSequenceFile;
+import org.broadinstitute.gatk.utils.sam.ArtificialSAMUtils;
+import org.broadinstitute.gatk.utils.sam.GATKSAMRecord;
+import htsjdk.variant.variantcontext.Allele;
+import htsjdk.variant.variantcontext.VariantContext;
+import htsjdk.variant.variantcontext.VariantContextBuilder;
+import org.testng.Assert;
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.DataProvider;
+import org.testng.annotations.Test;
+
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.util.Arrays;
+import java.util.LinkedList;
+import java.util.List;
+
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertTrue;
+
+/**
+ * @author aaron
+ *         <p/>
+ *         Class GenomeLocParserUnitTest
+ *         <p/>
+ *         Test out the functionality of the new genome loc parser
+ */
+public class GenomeLocParserUnitTest extends BaseTest {
+    private GenomeLocParser genomeLocParser;
+    private SAMFileHeader header;
+
+    @BeforeClass
+         public void init() {
+        header = ArtificialSAMUtils.createArtificialSamHeader(1, 1, 10);
+        genomeLocParser = new GenomeLocParser(header.getSequenceDictionary());
+    }
+
+    @Test(expectedExceptions=UserException.MalformedGenomeLoc.class)
+    public void testGetContigIndex() {
+        assertEquals(genomeLocParser.getContigIndex("blah"), -1); // should not be in the reference
+    }                
+
+    @Test
+    public void testGetContigIndexValid() {
+        assertEquals(genomeLocParser.getContigIndex("chr1"), 0); // should be in the reference
+    }
+
+    @Test(expectedExceptions=UserException.class)
+    public void testGetContigInfoUnknownContig1() {
+        assertEquals(null, genomeLocParser.getContigInfo("blah")); // should *not* be in the reference
+    }
+
+    @Test(expectedExceptions=UserException.class)
+    public void testGetContigInfoUnknownContig2() {
+        assertEquals(null, genomeLocParser.getContigInfo(null)); // should *not* be in the reference
+    }
+
+    @Test()
+    public void testHasContigInfoUnknownContig1() {
+        assertEquals(false, genomeLocParser.contigIsInDictionary("blah")); // should *not* be in the reference
+    }
+
+    @Test()
+    public void testHasContigInfoUnknownContig2() {
+        assertEquals(false, genomeLocParser.contigIsInDictionary(null)); // should *not* be in the reference
+    }
+
+    @Test()
+    public void testHasContigInfoKnownContig() {
+        assertEquals(true, genomeLocParser.contigIsInDictionary("chr1")); // should be in the reference
+    }
+
+    @Test
+    public void testGetContigInfoKnownContig() {
+        assertEquals(0, "chr1".compareTo(genomeLocParser.getContigInfo("chr1").getSequenceName())); // should be in the reference
+    }
+
+    @Test(expectedExceptions=ReviewedGATKException.class)
+    public void testParseBadString() {
+        genomeLocParser.parseGenomeLoc("Bad:0-1");
+    }
+
+    @Test
+    public void testContigHasColon() {
+        SAMFileHeader header = new SAMFileHeader();
+        header.setSortOrder(htsjdk.samtools.SAMFileHeader.SortOrder.coordinate);
+        SAMSequenceDictionary dict = new SAMSequenceDictionary();
+        SAMSequenceRecord rec = new SAMSequenceRecord("c:h:r1", 10);
+        rec.setSequenceLength(10);
+        dict.addSequence(rec);
+        header.setSequenceDictionary(dict);
+
+        final GenomeLocParser myGenomeLocParser = new GenomeLocParser(header.getSequenceDictionary());
+        GenomeLoc loc = myGenomeLocParser.parseGenomeLoc("c:h:r1:4-5");
+        assertEquals(0, loc.getContigIndex());
+        assertEquals(loc.getStart(), 4);
+        assertEquals(loc.getStop(), 5);
+    }
+
+    @Test
+    public void testParseGoodString() {
+        GenomeLoc loc = genomeLocParser.parseGenomeLoc("chr1:1-10");
+        assertEquals(0, loc.getContigIndex());
+        assertEquals(loc.getStop(), 10);
+        assertEquals(loc.getStart(), 1);
+    }
+
+    @Test
+    public void testCreateGenomeLoc1() {
+        GenomeLoc loc = genomeLocParser.createGenomeLoc("chr1", 1, 100);
+        assertEquals(0, loc.getContigIndex());
+        assertEquals(loc.getStop(), 100);
+        assertEquals(loc.getStart(), 1);
+    }
+
+    @Test
+    public void testCreateGenomeLoc1point5() { // in honor of VAAL!
+        GenomeLoc loc = genomeLocParser.parseGenomeLoc("chr1:1");
+        assertEquals(0, loc.getContigIndex());
+        assertEquals(loc.getStop(), 1);
+        assertEquals(loc.getStart(), 1);
+    }
+
+    @Test
+    public void testCreateGenomeLoc2() {
+        GenomeLoc loc = genomeLocParser.createGenomeLoc("chr1", 1, 100);
+        assertEquals("chr1", loc.getContig());
+        assertEquals(loc.getStop(), 100);
+        assertEquals(loc.getStart(), 1);
+    }
+
+    @Test
+    public void testCreateGenomeLoc3() {
+        GenomeLoc loc = genomeLocParser.createGenomeLoc("chr1", 1);
+        assertEquals("chr1", loc.getContig());
+        assertEquals(loc.getStop(), 1);
+        assertEquals(loc.getStart(), 1);
+    }
+
+    @Test
+    public void testCreateGenomeLoc4() {
+        GenomeLoc loc = genomeLocParser.createGenomeLoc("chr1", 1);
+        assertEquals(0, loc.getContigIndex());
+        assertEquals(loc.getStop(), 1);
+        assertEquals(loc.getStart(), 1);
+    }
+
+    @Test
+    public void testCreateGenomeLoc5() {
+        GenomeLoc loc = genomeLocParser.createGenomeLoc("chr1", 1, 100);
+        GenomeLoc copy = genomeLocParser.createGenomeLoc(loc.getContig(),loc.getStart(),loc.getStop());
+        assertEquals(0, copy.getContigIndex());
+        assertEquals(copy.getStop(), 100);
+        assertEquals(copy.getStart(), 1);
+    }
+
+    @Test
+    public void testGenomeLocPlusSign() {
+        GenomeLoc loc = genomeLocParser.parseGenomeLoc("chr1:1+");
+        assertEquals(loc.getContigIndex(), 0);
+        assertEquals(loc.getStop(), 10); // the size
+        assertEquals(loc.getStart(), 1);
+    }
+
+    @Test
+    public void testGenomeLocParseOnlyChrome() {
+        GenomeLoc loc = genomeLocParser.parseGenomeLoc("chr1");
+        assertEquals(loc.getContigIndex(), 0);
+        assertEquals(loc.getStop(), 10); // the size
+        assertEquals(loc.getStart(), 1);
+    }
+
+    @Test(expectedExceptions=ReviewedGATKException.class)
+    public void testGenomeLocParseOnlyBadChrome() {
+        GenomeLoc loc = genomeLocParser.parseGenomeLoc("chr12");
+        assertEquals(loc.getContigIndex(), 0);
+        assertEquals(loc.getStop(), 10); // the size
+        assertEquals(loc.getStart(), 1);
+    }
+
+    @Test(expectedExceptions=ReviewedGATKException.class)
+    public void testGenomeLocBad() {
+        GenomeLoc loc = genomeLocParser.parseGenomeLoc("chr1:1-");
+        assertEquals(loc.getContigIndex(), 0);
+        assertEquals(loc.getStop(), 10); // the size
+        assertEquals(loc.getStart(), 1);
+    }
+
+    @Test(expectedExceptions=UserException.class)
+    public void testGenomeLocBad2() {
+        GenomeLoc loc = genomeLocParser.parseGenomeLoc("chr1:1-500-0");
+        assertEquals(loc.getContigIndex(), 0);
+        assertEquals(loc.getStop(), 10); // the size
+        assertEquals(loc.getStart(), 1);
+    }
+
+    @Test(expectedExceptions=UserException.class)
+    public void testGenomeLocBad3() {
+        GenomeLoc loc = genomeLocParser.parseGenomeLoc("chr1:1--0");
+        assertEquals(loc.getContigIndex(), 0);
+        assertEquals(loc.getStop(), 10); // the size
+        assertEquals(loc.getStart(), 1);
+    }
+
+    // test out the validating methods
+    @Test
+    public void testValidationOfGenomeLocs() {
+        assertTrue(genomeLocParser.isValidGenomeLoc("chr1",1,1));
+        assertTrue(!genomeLocParser.isValidGenomeLoc("chr2",1,1)); // shouldn't have an entry
+        assertTrue(!genomeLocParser.isValidGenomeLoc("chr1",1,11)); // past the end of the contig
+        assertTrue(!genomeLocParser.isValidGenomeLoc("chr1",-1,10)); // bad start
+        assertTrue(!genomeLocParser.isValidGenomeLoc("chr1",1,-2)); // bad stop
+        assertTrue( genomeLocParser.isValidGenomeLoc("chr1",-1,2, false)); // bad stop
+        assertTrue(!genomeLocParser.isValidGenomeLoc("chr1",10,11)); // bad start, past end
+        assertTrue( genomeLocParser.isValidGenomeLoc("chr1",10,11, false)); // bad start, past end
+        assertTrue(!genomeLocParser.isValidGenomeLoc("chr1",2,1)); // stop < start
+    }
+
+    @Test(expectedExceptions = ReviewedGATKException.class)
+    public void testValidateGenomeLoc() {
+        // bad contig index
+        genomeLocParser.validateGenomeLoc("chr1", 1, 1, 2, false);
+    }
+
+    private static class FlankingGenomeLocTestData extends TestDataProvider {
+        final GenomeLocParser parser;
+        final int basePairs;
+        final GenomeLoc original, flankStart, flankStop;
+
+        private FlankingGenomeLocTestData(String name, GenomeLocParser parser, int basePairs, String original, String flankStart, String flankStop) {
+            super(FlankingGenomeLocTestData.class, name);
+            this.parser = parser;
+            this.basePairs = basePairs;
+            this.original = parse(parser, original);
+            this.flankStart = flankStart == null ? null : parse(parser, flankStart);
+            this.flankStop = flankStop == null ? null : parse(parser, flankStop);
+        }
+
+        private static GenomeLoc parse(GenomeLocParser parser, String str) {
+            return "unmapped".equals(str) ? GenomeLoc.UNMAPPED : parser.parseGenomeLoc(str);
+        }
+    }
+
+    @DataProvider(name = "flankingGenomeLocs")
+    public Object[][] getFlankingGenomeLocs() {
+        int contigLength = 10000;
+        SAMFileHeader header = ArtificialSAMUtils.createArtificialSamHeader(1, 1, contigLength);
+        GenomeLocParser parser = new GenomeLocParser(header.getSequenceDictionary());
+
+        new FlankingGenomeLocTestData("atStartBase1", parser, 1,
+                "chr1:1", null, "chr1:2");
+
+        new FlankingGenomeLocTestData("atStartBase50", parser, 50,
+                "chr1:1", null, "chr1:2-51");
+
+        new FlankingGenomeLocTestData("atStartRange50", parser, 50,
+                "chr1:1-10", null, "chr1:11-60");
+
+        new FlankingGenomeLocTestData("atEndBase1", parser, 1,
+                "chr1:" + contigLength, "chr1:" + (contigLength - 1), null);
+
+        new FlankingGenomeLocTestData("atEndBase50", parser, 50,
+                "chr1:" + contigLength, String.format("chr1:%d-%d", contigLength - 50, contigLength - 1), null);
+
+        new FlankingGenomeLocTestData("atEndRange50", parser, 50,
+                String.format("chr1:%d-%d", contigLength - 10, contigLength),
+                String.format("chr1:%d-%d", contigLength - 60, contigLength - 11),
+                null);
+
+        new FlankingGenomeLocTestData("nearStartBase1", parser, 1,
+                "chr1:2", "chr1:1", "chr1:3");
+
+        new FlankingGenomeLocTestData("nearStartRange50", parser, 50,
+                "chr1:21-30", "chr1:1-20", "chr1:31-80");
+
+        new FlankingGenomeLocTestData("nearEndBase1", parser, 1,
+                "chr1:" + (contigLength - 1), "chr1:" + (contigLength - 2), "chr1:" + contigLength);
+
+        new FlankingGenomeLocTestData("nearEndRange50", parser, 50,
+                String.format("chr1:%d-%d", contigLength - 30, contigLength - 21),
+                String.format("chr1:%d-%d", contigLength - 80, contigLength - 31),
+                String.format("chr1:%d-%d", contigLength - 20, contigLength));
+
+        new FlankingGenomeLocTestData("beyondStartBase1", parser, 1,
+                "chr1:3", "chr1:2", "chr1:4");
+
+        new FlankingGenomeLocTestData("beyondStartRange50", parser, 50,
+                "chr1:101-200", "chr1:51-100", "chr1:201-250");
+
+        new FlankingGenomeLocTestData("beyondEndBase1", parser, 1,
+                "chr1:" + (contigLength - 3),
+                "chr1:" + (contigLength - 4),
+                "chr1:" + (contigLength - 2));
+
+        new FlankingGenomeLocTestData("beyondEndRange50", parser, 50,
+                String.format("chr1:%d-%d", contigLength - 200, contigLength - 101),
+                String.format("chr1:%d-%d", contigLength - 250, contigLength - 201),
+                String.format("chr1:%d-%d", contigLength - 100, contigLength - 51));
+
+        new FlankingGenomeLocTestData("unmapped", parser, 50,
+                "unmapped", null, null);
+
+        new FlankingGenomeLocTestData("fullContig", parser, 50,
+                "chr1", null, null);
+
+        return FlankingGenomeLocTestData.getTests(FlankingGenomeLocTestData.class);
+    }
+
+    @Test(dataProvider = "flankingGenomeLocs")
+    public void testCreateGenomeLocAtStart(FlankingGenomeLocTestData data) {
+        GenomeLoc actual = data.parser.createGenomeLocAtStart(data.original, data.basePairs);
+        String description = String.format("%n      name: %s%n  original: %s%n    actual: %s%n  expected: %s%n",
+                data.toString(), data.original, actual, data.flankStart);
+        assertEquals(actual, data.flankStart, description);
+    }
+
+    @Test(dataProvider = "flankingGenomeLocs")
+    public void testCreateGenomeLocAtStop(FlankingGenomeLocTestData data) {
+        GenomeLoc actual = data.parser.createGenomeLocAtStop(data.original, data.basePairs);
+        String description = String.format("%n      name: %s%n  original: %s%n    actual: %s%n  expected: %s%n",
+                data.toString(), data.original, actual, data.flankStop);
+        assertEquals(actual, data.flankStop, description);
+    }
+
+    @DataProvider(name = "parseGenomeLoc")
+    public Object[][] makeParsingTest() {
+        final List<Object[]> tests = new LinkedList<Object[]>();
+
+        tests.add(new Object[]{ "chr1:10", "chr1", 10 });
+        tests.add(new Object[]{ "chr1:100", "chr1", 100 });
+        tests.add(new Object[]{ "chr1:1000", "chr1", 1000 });
+        tests.add(new Object[]{ "chr1:1,000", "chr1", 1000 });
+        tests.add(new Object[]{ "chr1:10000", "chr1", 10000 });
+        tests.add(new Object[]{ "chr1:10,000", "chr1", 10000 });
+        tests.add(new Object[]{ "chr1:100000", "chr1", 100000 });
+        tests.add(new Object[]{ "chr1:100,000", "chr1", 100000 });
+        tests.add(new Object[]{ "chr1:1000000", "chr1", 1000000 });
+        tests.add(new Object[]{ "chr1:1,000,000", "chr1", 1000000 });
+        tests.add(new Object[]{ "chr1:1000,000", "chr1", 1000000 });
+        tests.add(new Object[]{ "chr1:1,000000", "chr1", 1000000 });
+
+        return tests.toArray(new Object[][]{});
+    }
+
+    @Test( dataProvider = "parseGenomeLoc")
+    public void testParsingPositions(final String string, final String contig, final int start) {
+        SAMFileHeader header = ArtificialSAMUtils.createArtificialSamHeader(1, 1, 10000000);
+        GenomeLocParser genomeLocParser = new GenomeLocParser(header.getSequenceDictionary());
+        final GenomeLoc loc = genomeLocParser.parseGenomeLoc(string);
+        Assert.assertEquals(loc.getContig(), contig);
+        Assert.assertEquals(loc.getStart(), start);
+        Assert.assertEquals(loc.getStop(), start);
+    }
+
+    @Test( )
+    public void testCreationFromSAMRecord() {
+        final GATKSAMRecord read = ArtificialSAMUtils.createArtificialRead(header, "foo", 0, 1, 5);
+        final GenomeLoc loc = genomeLocParser.createGenomeLoc(read);
+        Assert.assertEquals(loc.getContig(), read.getReferenceName());
+        Assert.assertEquals(loc.getContigIndex(), (int)read.getReferenceIndex());
+        Assert.assertEquals(loc.getStart(), read.getAlignmentStart());
+        Assert.assertEquals(loc.getStop(), read.getAlignmentEnd());
+    }
+
+    @Test( )
+    public void testCreationFromSAMRecordUnmapped() {
+        final GATKSAMRecord read = ArtificialSAMUtils.createArtificialRead(header, "foo", 0, 1, 5);
+        read.setReadUnmappedFlag(true);
+        read.setReferenceIndex(-1);
+        final GenomeLoc loc = genomeLocParser.createGenomeLoc(read);
+        Assert.assertTrue(loc.isUnmapped());
+    }
+
+    @Test( )
+    public void testCreationFromSAMRecordUnmappedButOnGenome() {
+        final GATKSAMRecord read = ArtificialSAMUtils.createArtificialRead(header, "foo", 0, 1, 5);
+        read.setReadUnmappedFlag(true);
+        read.setCigarString("*");
+        final GenomeLoc loc = genomeLocParser.createGenomeLoc(read);
+        Assert.assertEquals(loc.getContig(), read.getReferenceName());
+        Assert.assertEquals(loc.getContigIndex(), (int)read.getReferenceIndex());
+        Assert.assertEquals(loc.getStart(), read.getAlignmentStart());
+        Assert.assertEquals(loc.getStop(), read.getAlignmentStart());
+    }
+
+    @Test
+    public void testCreationFromFeature() {
+        final Feature feature = new BasicFeature("chr1", 1, 5);
+        final GenomeLoc loc = genomeLocParser.createGenomeLoc(feature);
+        Assert.assertEquals(loc.getContig(), feature.getChr());
+        Assert.assertEquals(loc.getStart(), feature.getStart());
+        Assert.assertEquals(loc.getStop(), feature.getEnd());
+    }
+
+    @Test
+    public void testCreationFromVariantContext() {
+        final VariantContext feature = new VariantContextBuilder("x", "chr1", 1, 5, Arrays.asList(Allele.create("AAAAA", true))).make();
+        final GenomeLoc loc = genomeLocParser.createGenomeLoc(feature);
+        Assert.assertEquals(loc.getContig(), feature.getChr());
+        Assert.assertEquals(loc.getStart(), feature.getStart());
+        Assert.assertEquals(loc.getStop(), feature.getEnd());
+    }
+
+    @Test
+    public void testcreateGenomeLocOnContig() throws FileNotFoundException {
+        final CachingIndexedFastaSequenceFile seq = new CachingIndexedFastaSequenceFile(new File(b37KGReference));
+        final SAMSequenceDictionary dict = seq.getSequenceDictionary();
+        final GenomeLocParser genomeLocParser = new GenomeLocParser(dict);
+
+        for ( final SAMSequenceRecord rec : dict.getSequences() ) {
+            final GenomeLoc loc = genomeLocParser.createOverEntireContig(rec.getSequenceName());
+            Assert.assertEquals(loc.getContig(), rec.getSequenceName());
+            Assert.assertEquals(loc.getStart(), 1);
+            Assert.assertEquals(loc.getStop(), rec.getSequenceLength());
+        }
+    }
+
+    @DataProvider(name = "GenomeLocOnContig")
+    public Object[][] makeGenomeLocOnContig() {
+        final List<Object[]> tests = new LinkedList<Object[]>();
+
+        final int contigLength = header.getSequence(0).getSequenceLength();
+        for ( int start = -10; start < contigLength + 10; start++ ) {
+            for ( final int len : Arrays.asList(1, 10, 20) ) {
+                tests.add(new Object[]{ "chr1", start, start + len });
+            }
+        }
+
+        return tests.toArray(new Object[][]{});
+    }
+
+    @Test( dataProvider = "GenomeLocOnContig")
+    public void testGenomeLocOnContig(final String contig, final int start, final int stop) {
+        final int contigLength = header.getSequence(0).getSequenceLength();
+        final GenomeLoc loc = genomeLocParser.createGenomeLocOnContig(contig, start, stop);
+
+        if ( stop < 1 || start > contigLength )
+            Assert.assertNull(loc, "GenomeLoc should be null if the start/stops are not meaningful");
+        else {
+            Assert.assertNotNull(loc);
+            Assert.assertEquals(loc.getContig(), contig);
+            Assert.assertEquals(loc.getStart(), Math.max(start, 1));
+            Assert.assertEquals(loc.getStop(), Math.min(stop, contigLength));
+        }
+    }
+
+    @DataProvider(name = "GenomeLocPadding")
+    public Object[][] makeGenomeLocPadding() {
+        final List<Object[]> tests = new LinkedList<Object[]>();
+
+        final int contigLength = header.getSequence(0).getSequenceLength();
+        for ( int pad = 0; pad < contigLength + 1; pad++) {
+            for ( int start = 1; start < contigLength; start++ ) {
+                for ( int stop = start; stop < contigLength; stop++ ) {
+                    tests.add(new Object[]{ genomeLocParser.createGenomeLoc("chr1", start, stop), pad});
+                }
+            }
+        }
+
+        return tests.toArray(new Object[][]{});
+    }
+
+    @Test( dataProvider = "GenomeLocPadding")
+    public void testGenomeLocPadding(final GenomeLoc input, final int pad) {
+        final int contigLength = header.getSequence(0).getSequenceLength();
+        final GenomeLoc padded = genomeLocParser.createPaddedGenomeLoc(input, pad);
+
+        Assert.assertNotNull(padded);
+        Assert.assertEquals(padded.getContig(), input.getContig());
+        Assert.assertEquals(padded.getStart(), Math.max(input.getStart() - pad, 1));
+        Assert.assertEquals(padded.getStop(), Math.min(input.getStop() + pad, contigLength));
+    }
+}
diff --git a/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/utils/GenomeLocSortedSetUnitTest.java b/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/utils/GenomeLocSortedSetUnitTest.java
new file mode 100644
index 0000000..6553120
--- /dev/null
+++ b/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/utils/GenomeLocSortedSetUnitTest.java
@@ -0,0 +1,405 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.utils;
+
+import htsjdk.samtools.SAMFileHeader;
+import org.broadinstitute.gatk.utils.BaseTest;
+import org.broadinstitute.gatk.utils.exceptions.ReviewedGATKException;
+import org.broadinstitute.gatk.utils.fasta.CachingIndexedFastaSequenceFile;
+import org.broadinstitute.gatk.utils.sam.ArtificialSAMUtils;
+
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertFalse;
+import static org.testng.Assert.assertTrue;
+
+import org.testng.Assert;
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.BeforeMethod;
+import org.testng.annotations.DataProvider;
+import org.testng.annotations.Test;
+
+import java.io.File;
+import java.util.*;
+
+/**
+ *
+ * User: aaron
+ * Date: May 22, 2009
+ * Time: 2:14:07 PM
+ *
+ * The Broad Institute
+ * SOFTWARE COPYRIGHT NOTICE AGREEMENT 
+ * This software and its documentation are copyright 2009 by the
+ * Broad Institute/Massachusetts Institute of Technology. All rights are reserved.
+ *
+ * This software is supplied without any warranty or guaranteed support whatsoever. Neither
+ * the Broad Institute nor MIT can be responsible for its use, misuse, or functionality.
+ *
+ */
+
+
+/**
+ * @author aaron
+ * @version 1.0
+ * <p/>
+ * Class GenomeLocSetTest
+ * <p/>
+ * This tests the functions of the GenomeLocSet
+ */
+public class GenomeLocSortedSetUnitTest extends BaseTest {
+
+    private GenomeLocSortedSet mSortedSet = null;
+    private SAMFileHeader header = ArtificialSAMUtils.createArtificialSamHeader(NUMBER_OF_CHROMOSOMES, STARTING_CHROMOSOME, CHROMOSOME_SIZE);
+    private static final int NUMBER_OF_CHROMOSOMES = 5;
+    private static final int STARTING_CHROMOSOME = 1;
+    private static final int CHROMOSOME_SIZE = 1000;
+
+    private GenomeLocParser genomeLocParser;
+    private String contigOneName;
+
+    @BeforeClass
+    public void setup() {
+        genomeLocParser = new GenomeLocParser(header.getSequenceDictionary());
+        contigOneName = header.getSequenceDictionary().getSequence(1).getSequenceName();
+    }
+
+    @BeforeMethod
+    public void initializeSortedSet() {
+        mSortedSet = new GenomeLocSortedSet(genomeLocParser);        
+    }
+
+    @Test
+    public void testAdd() {
+        GenomeLoc g = genomeLocParser.createGenomeLoc(contigOneName, 0, 0);
+        assertTrue(mSortedSet.size() == 0);
+        mSortedSet.add(g);
+        assertTrue(mSortedSet.size() == 1);
+    }
+
+    @Test
+    public void testRemove() {
+        assertTrue(mSortedSet.size() == 0);
+        GenomeLoc g = genomeLocParser.createGenomeLoc(contigOneName, 0, 0);
+        mSortedSet.add(g);
+        assertTrue(mSortedSet.size() == 1);
+        mSortedSet.remove(g);
+        assertTrue(mSortedSet.size() == 0);
+    }
+
+    @Test
+    public void addRegion() {
+        assertTrue(mSortedSet.size() == 0);
+        GenomeLoc g = genomeLocParser.createGenomeLoc(contigOneName, 1, 50);
+        mSortedSet.add(g);
+        GenomeLoc f = genomeLocParser.createGenomeLoc(contigOneName, 30, 80);
+        mSortedSet.addRegion(f);
+        assertTrue(mSortedSet.size() == 1);
+    }
+
+    @Test
+    public void addRegionsOutOfOrder() {
+        final String contigTwoName = header.getSequenceDictionary().getSequence(2).getSequenceName();
+        assertTrue(mSortedSet.size() == 0);
+        GenomeLoc g = genomeLocParser.createGenomeLoc(contigTwoName, 1, 50);
+        mSortedSet.add(g);
+        GenomeLoc f = genomeLocParser.createGenomeLoc(contigOneName, 30, 80);
+        mSortedSet.addRegion(f);
+        assertTrue(mSortedSet.size() == 2);
+        assertTrue(mSortedSet.toList().get(0).getContig().equals(contigOneName));
+        assertTrue(mSortedSet.toList().get(1).getContig().equals(contigTwoName));
+    }
+
+    @Test(expectedExceptions = IllegalArgumentException.class)
+    public void addThrowsException() {
+        assertTrue(mSortedSet.size() == 0);
+        GenomeLoc g = genomeLocParser.createGenomeLoc(contigOneName, 1, 50);
+        mSortedSet.add(g);
+        GenomeLoc f = genomeLocParser.createGenomeLoc(contigOneName, 30, 80);
+        mSortedSet.add(f);
+    }
+
+    @Test(expectedExceptions=IllegalArgumentException.class)
+    public void testAddDuplicate() {
+        assertTrue(mSortedSet.size() == 0);
+        GenomeLoc g = genomeLocParser.createGenomeLoc(contigOneName, 0, 0);
+        mSortedSet.add(g);
+        assertTrue(mSortedSet.size() == 1);
+        mSortedSet.add(g);
+    }
+
+    @Test
+    public void mergingOverlappingBelow() {
+        GenomeLoc g = genomeLocParser.createGenomeLoc(contigOneName, 0, 50);
+        GenomeLoc e = genomeLocParser.createGenomeLoc(contigOneName, 49, 100);
+        assertTrue(mSortedSet.size() == 0);
+        mSortedSet.add(g);
+        assertTrue(mSortedSet.size() == 1);
+        mSortedSet.addRegion(e);
+        assertTrue(mSortedSet.size() == 1);
+        Iterator<GenomeLoc> iter = mSortedSet.iterator();
+        GenomeLoc loc = iter.next();
+        assertEquals(loc.getStart(), 0);
+        assertEquals(loc.getStop(), 100);
+        assertEquals(loc.getContigIndex(), 1);
+    }
+
+    @Test
+    public void overlap() {
+        for ( int i = 1; i < 6; i++ ) {
+            final int start = i * 10;
+            mSortedSet.add(genomeLocParser.createGenomeLoc(contigOneName, start, start + 1));
+        }
+
+        // test matches in and around interval
+        assertFalse(mSortedSet.overlaps(genomeLocParser.createGenomeLoc(contigOneName, 9, 9)));
+        assertTrue(mSortedSet.overlaps(genomeLocParser.createGenomeLoc(contigOneName, 10, 10)));
+        assertTrue(mSortedSet.overlaps(genomeLocParser.createGenomeLoc(contigOneName, 11, 11)));
+        assertFalse(mSortedSet.overlaps(genomeLocParser.createGenomeLoc(contigOneName, 12, 12)));
+
+        // test matches spanning intervals
+        assertTrue(mSortedSet.overlaps(genomeLocParser.createGenomeLoc(contigOneName, 14, 20)));
+        assertTrue(mSortedSet.overlaps(genomeLocParser.createGenomeLoc(contigOneName, 11, 15)));
+        assertTrue(mSortedSet.overlaps(genomeLocParser.createGenomeLoc(contigOneName, 30, 40)));
+        assertTrue(mSortedSet.overlaps(genomeLocParser.createGenomeLoc(contigOneName, 51, 53)));
+
+        // test miss
+        assertFalse(mSortedSet.overlaps(genomeLocParser.createGenomeLoc(contigOneName, 12, 19)));
+
+        // test exact match after miss
+        assertTrue(mSortedSet.overlaps(genomeLocParser.createGenomeLoc(contigOneName, 40, 41)));
+
+        // test matches at beginning of intervals
+        assertFalse(mSortedSet.overlaps(genomeLocParser.createGenomeLoc(contigOneName, 5, 6)));
+        assertTrue(mSortedSet.overlaps(genomeLocParser.createGenomeLoc(contigOneName, 0, 10)));
+
+        // test matches at end of intervals
+        assertFalse(mSortedSet.overlaps(genomeLocParser.createGenomeLoc(contigOneName, 52, 53)));
+        assertTrue(mSortedSet.overlaps(genomeLocParser.createGenomeLoc(contigOneName, 51, 53)));
+        assertFalse(mSortedSet.overlaps(genomeLocParser.createGenomeLoc(contigOneName, 52, 53)));
+    }
+
+    @Test
+    public void mergingOverlappingAbove() {
+        GenomeLoc e = genomeLocParser.createGenomeLoc(contigOneName, 0, 50);
+        GenomeLoc g = genomeLocParser.createGenomeLoc(contigOneName, 49, 100);
+        assertTrue(mSortedSet.size() == 0);
+        mSortedSet.add(g);
+        assertTrue(mSortedSet.size() == 1);
+        mSortedSet.addRegion(e);
+        assertTrue(mSortedSet.size() == 1);
+        Iterator<GenomeLoc> iter = mSortedSet.iterator();
+        GenomeLoc loc = iter.next();
+        assertEquals(loc.getStart(), 0);
+        assertEquals(loc.getStop(), 100);
+        assertEquals(loc.getContigIndex(), 1);
+    }
+
+    @Test
+    public void deleteAllByRegion() {
+        GenomeLoc e = genomeLocParser.createGenomeLoc(contigOneName, 1, 100);
+        mSortedSet.add(e);
+        for (int x = 1; x < 101; x++) {
+            GenomeLoc del = genomeLocParser.createGenomeLoc(contigOneName,x,x);
+            mSortedSet = mSortedSet.subtractRegions(new GenomeLocSortedSet(genomeLocParser,del));
+        }
+        assertTrue(mSortedSet.isEmpty());
+    }
+
+    @Test
+    public void deleteSomeByRegion() {
+        GenomeLoc e = genomeLocParser.createGenomeLoc(contigOneName, 1, 100);
+        mSortedSet.add(e);
+        for (int x = 1; x < 50; x++) {
+            GenomeLoc del = genomeLocParser.createGenomeLoc(contigOneName,x,x);
+            mSortedSet = mSortedSet.subtractRegions(new GenomeLocSortedSet(genomeLocParser,del));
+        }
+        assertTrue(!mSortedSet.isEmpty());
+        assertTrue(mSortedSet.size() == 1);
+        GenomeLoc loc = mSortedSet.iterator().next();        
+        assertTrue(loc.getStop() == 100);
+        assertTrue(loc.getStart() == 50);
+
+    }
+
+    @Test
+    public void deleteSuperRegion() {
+        GenomeLoc e = genomeLocParser.createGenomeLoc(contigOneName, 10, 20);
+        GenomeLoc g = genomeLocParser.createGenomeLoc(contigOneName, 70, 100);
+        mSortedSet.add(g);
+        mSortedSet.addRegion(e);
+        assertTrue(mSortedSet.size() == 2);
+        // now delete a region
+        GenomeLoc d = genomeLocParser.createGenomeLoc(contigOneName, 15, 75);
+        mSortedSet = mSortedSet.subtractRegions(new GenomeLocSortedSet(genomeLocParser,d));
+        Iterator<GenomeLoc> iter = mSortedSet.iterator();
+        GenomeLoc loc = iter.next();
+        assertTrue(loc.getStart() == 10);
+        assertTrue(loc.getStop() == 14);
+        assertTrue(loc.getContigIndex() == 1);
+
+        loc = iter.next();
+        assertTrue(loc.getStart() == 76);
+        assertTrue(loc.getStop() == 100);
+        assertTrue(loc.getContigIndex() == 1);
+    }
+
+    @Test
+    public void substractComplexExample() {
+        GenomeLoc e = genomeLocParser.createGenomeLoc(contigOneName, 1, 20);
+        mSortedSet.add(e);
+
+        GenomeLoc r1 = genomeLocParser.createGenomeLoc(contigOneName, 3, 5);
+        GenomeLoc r2 = genomeLocParser.createGenomeLoc(contigOneName, 10, 12);
+        GenomeLoc r3 = genomeLocParser.createGenomeLoc(contigOneName, 16, 18);
+        GenomeLocSortedSet toExclude = new GenomeLocSortedSet(genomeLocParser,Arrays.asList(r1, r2, r3));
+
+        GenomeLocSortedSet remaining = mSortedSet.subtractRegions(toExclude);
+//        logger.debug("Initial   " + mSortedSet);
+//        logger.debug("Exclude   " + toExclude);
+//        logger.debug("Remaining " + remaining);
+
+        assertEquals(mSortedSet.coveredSize(), 20);
+        assertEquals(toExclude.coveredSize(), 9);
+        assertEquals(remaining.coveredSize(), 11);
+
+        Iterator<GenomeLoc> it = remaining.iterator();
+        GenomeLoc p1 = it.next();
+        GenomeLoc p2 = it.next();
+        GenomeLoc p3 = it.next();
+        GenomeLoc p4 = it.next();
+
+        assertEquals(genomeLocParser.createGenomeLoc(contigOneName, 1, 2), p1);
+        assertEquals(genomeLocParser.createGenomeLoc(contigOneName, 6, 9), p2);
+        assertEquals(genomeLocParser.createGenomeLoc(contigOneName, 13, 15), p3);
+        assertEquals(genomeLocParser.createGenomeLoc(contigOneName, 19, 20), p4);
+    }
+
+    private void testSizeBeforeLocX(int pos, int size) {
+        GenomeLoc test = genomeLocParser.createGenomeLoc(contigOneName, pos, pos);
+        assertEquals(mSortedSet.sizeBeforeLoc(test), size, String.format("X pos=%d size=%d", pos, size));
+    }
+
+    @Test
+    public void testSizeBeforeLoc() {
+        GenomeLoc r1 = genomeLocParser.createGenomeLoc(contigOneName, 3, 5);
+        GenomeLoc r2 = genomeLocParser.createGenomeLoc(contigOneName, 10, 12);
+        GenomeLoc r3 = genomeLocParser.createGenomeLoc(contigOneName, 16, 18);
+        mSortedSet.addAll(Arrays.asList(r1,r2,r3));
+
+        testSizeBeforeLocX(2, 0);
+        testSizeBeforeLocX(3, 0);
+        testSizeBeforeLocX(4, 1);
+        testSizeBeforeLocX(5, 2);
+        testSizeBeforeLocX(6, 3);
+
+        testSizeBeforeLocX(10, 3);
+        testSizeBeforeLocX(11, 4);
+        testSizeBeforeLocX(12, 5);
+        testSizeBeforeLocX(13, 6);
+        testSizeBeforeLocX(15, 6);
+
+        testSizeBeforeLocX(16, 6);
+        testSizeBeforeLocX(17, 7);
+        testSizeBeforeLocX(18, 8);
+        testSizeBeforeLocX(19, 9);
+        testSizeBeforeLocX(50, 9);
+        testSizeBeforeLocX(50, (int)mSortedSet.coveredSize());
+    }
+
+
+    @Test
+    public void fromSequenceDictionary() {
+        mSortedSet = GenomeLocSortedSet.createSetFromSequenceDictionary(this.header.getSequenceDictionary());
+        // we should have sequence
+        assertTrue(mSortedSet.size() == GenomeLocSortedSetUnitTest.NUMBER_OF_CHROMOSOMES);
+        int seqNumber = 0;
+        for (GenomeLoc loc : mSortedSet) {
+            assertTrue(loc.getStart() == 1);
+            assertTrue(loc.getStop() == GenomeLocSortedSetUnitTest.CHROMOSOME_SIZE);
+            assertTrue(loc.getContigIndex() == seqNumber);
+            ++seqNumber;
+        }
+        assertTrue(seqNumber == GenomeLocSortedSetUnitTest.NUMBER_OF_CHROMOSOMES);
+    }
+
+    // -----------------------------------------------------------------------------------------------
+    //
+    // Test getOverlapping
+    //
+    // -----------------------------------------------------------------------------------------------
+
+    @DataProvider(name = "GetOverlapping")
+    public Object[][] makeGetOverlappingTest() throws Exception {
+        final GenomeLocParser genomeLocParser = new GenomeLocParser(new CachingIndexedFastaSequenceFile(new File(b37KGReference)));
+
+        List<Object[]> tests = new ArrayList<Object[]>();
+
+        final GenomeLoc prev1 = genomeLocParser.createGenomeLoc("19", 1, 10);
+        final GenomeLoc prev2 = genomeLocParser.createGenomeLoc("19", 20, 50);
+        final GenomeLoc post1 = genomeLocParser.createGenomeLoc("21", 1, 10);
+        final GenomeLoc post2 = genomeLocParser.createGenomeLoc("21", 20, 50);
+
+        final int chr20Length = genomeLocParser.getContigs().getSequence("20").getSequenceLength();
+        for ( final int regionStart : Arrays.asList(1, 10, chr20Length - 10, chr20Length) ) {
+            for ( final int regionSize : Arrays.asList(1, 10, 100) ) {
+                final GenomeLoc region = genomeLocParser.createGenomeLocOnContig("20", regionStart, regionStart + regionSize);
+                final GenomeLoc spanning = genomeLocParser.createGenomeLocOnContig("20", regionStart - 10, region.getStop() + 10);
+                final GenomeLoc before_into = genomeLocParser.createGenomeLocOnContig("20", regionStart - 10, regionStart + 1);
+                final GenomeLoc middle = genomeLocParser.createGenomeLocOnContig("20", regionStart + 1, regionStart + 2);
+                final GenomeLoc middle_past = genomeLocParser.createGenomeLocOnContig("20", region.getStop()-1, region.getStop()+10);
+
+                final List<GenomeLoc> potentials = new LinkedList<GenomeLoc>();
+                potentials.add(region);
+                if ( spanning != null ) potentials.add(spanning);
+                if ( before_into != null ) potentials.add(before_into);
+                if ( middle != null ) potentials.add(middle);
+                if ( middle_past != null ) potentials.add(middle_past);
+
+                for ( final int n : Arrays.asList(1, 2, 3) ) {
+                    for ( final List<GenomeLoc> regions : Utils.makePermutations(potentials, n, false) ) {
+                        tests.add(new Object[]{new GenomeLocSortedSet(genomeLocParser, regions), region});
+                        tests.add(new Object[]{new GenomeLocSortedSet(genomeLocParser, Utils.append(regions, prev1)), region});
+                        tests.add(new Object[]{new GenomeLocSortedSet(genomeLocParser, Utils.append(regions, prev1, prev2)), region});
+                        tests.add(new Object[]{new GenomeLocSortedSet(genomeLocParser, Utils.append(regions, post1)), region});
+                        tests.add(new Object[]{new GenomeLocSortedSet(genomeLocParser, Utils.append(regions, post1, post2)), region});
+                        tests.add(new Object[]{new GenomeLocSortedSet(genomeLocParser, Utils.append(regions, prev1, post1)), region});
+                        tests.add(new Object[]{new GenomeLocSortedSet(genomeLocParser, Utils.append(regions, prev1, prev2, post1, post2)), region});
+                    }
+                }
+            }
+        }
+
+        return tests.toArray(new Object[][]{});
+    }
+
+    @Test(dataProvider = "GetOverlapping")
+    public void testGetOverlapping(final GenomeLocSortedSet intervals, final GenomeLoc region) {
+        final List<GenomeLoc> expectedOverlapping = intervals.getOverlappingFullSearch(region);
+        final List<GenomeLoc> actualOverlapping = intervals.getOverlapping(region);
+        Assert.assertEquals(actualOverlapping, expectedOverlapping);
+        Assert.assertEquals(intervals.overlaps(region), ! expectedOverlapping.isEmpty(), "GenomeLocSortedSet.overlaps didn't return expected result");
+    }
+}
diff --git a/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/utils/GenomeLocUnitTest.java b/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/utils/GenomeLocUnitTest.java
new file mode 100644
index 0000000..ae86ca5
--- /dev/null
+++ b/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/utils/GenomeLocUnitTest.java
@@ -0,0 +1,386 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.utils;
+
+
+// the imports for unit testing.
+
+
+import htsjdk.samtools.reference.ReferenceSequenceFile;
+import htsjdk.samtools.SAMFileHeader;
+import org.broadinstitute.gatk.utils.BaseTest;
+import org.broadinstitute.gatk.utils.exceptions.ReviewedGATKException;
+import org.broadinstitute.gatk.utils.fasta.CachingIndexedFastaSequenceFile;
+import org.broadinstitute.gatk.utils.interval.IntervalMergingRule;
+import org.broadinstitute.gatk.utils.interval.IntervalUtils;
+import org.broadinstitute.gatk.utils.sam.ArtificialSAMUtils;
+import org.testng.Assert;
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.DataProvider;
+import org.testng.annotations.Test;
+
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.util.*;
+
+/**
+ * Basic unit test for GenomeLoc
+ */
+public class GenomeLocUnitTest extends BaseTest {
+    private static ReferenceSequenceFile seq;
+    private GenomeLocParser genomeLocParser;
+
+    @BeforeClass
+    public void init() throws FileNotFoundException {
+        // sequence
+        seq = new CachingIndexedFastaSequenceFile(new File(hg18Reference));
+        genomeLocParser = new GenomeLocParser(seq);
+    }
+
+    /**
+     * Tests that we got a string parameter in correctly
+     */
+    @Test
+    public void testIsBetween() {
+        logger.warn("Executing testIsBetween");
+
+        GenomeLoc locMiddle = genomeLocParser.createGenomeLoc("chr1", 3, 3);
+
+        GenomeLoc locLeft = genomeLocParser.createGenomeLoc("chr1", 1, 1);
+        GenomeLoc locRight = genomeLocParser.createGenomeLoc("chr1", 5, 5);
+
+        Assert.assertTrue(locMiddle.isBetween(locLeft, locRight));
+        Assert.assertFalse(locLeft.isBetween(locMiddle, locRight));
+        Assert.assertFalse(locRight.isBetween(locLeft, locMiddle));
+
+    }
+    @Test
+    public void testContigIndex() {
+        logger.warn("Executing testContigIndex");
+        GenomeLoc locOne = genomeLocParser.createGenomeLoc("chr1",1,1);
+        Assert.assertEquals(1, locOne.getContigIndex());
+        Assert.assertEquals("chr1", locOne.getContig());
+
+        GenomeLoc locX = genomeLocParser.createGenomeLoc("chrX",1,1);
+        Assert.assertEquals(23, locX.getContigIndex());
+        Assert.assertEquals("chrX", locX.getContig());
+
+        GenomeLoc locNumber = genomeLocParser.createGenomeLoc(seq.getSequenceDictionary().getSequence(1).getSequenceName(),1,1);
+        Assert.assertEquals(1, locNumber.getContigIndex());
+        Assert.assertEquals("chr1", locNumber.getContig());
+        Assert.assertEquals(0, locOne.compareTo(locNumber));
+
+    }
+
+    @Test
+    public void testCompareTo() {
+        logger.warn("Executing testCompareTo");
+        GenomeLoc twoOne = genomeLocParser.createGenomeLoc("chr2", 1);
+        GenomeLoc twoFive = genomeLocParser.createGenomeLoc("chr2", 5);
+        GenomeLoc twoOtherFive = genomeLocParser.createGenomeLoc("chr2", 5);
+        Assert.assertEquals(twoFive.compareTo(twoOtherFive), 0);
+
+        Assert.assertEquals(twoOne.compareTo(twoFive), -1);
+        Assert.assertEquals(twoFive.compareTo(twoOne), 1);
+
+        GenomeLoc oneOne = genomeLocParser.createGenomeLoc("chr1", 5);
+        Assert.assertEquals(oneOne.compareTo(twoOne), -1);
+        Assert.assertEquals(twoOne.compareTo(oneOne), 1);
+    }
+
+
+    @Test
+    public void testUnmappedSort() {
+        GenomeLoc chr1 = genomeLocParser.createGenomeLoc("chr1",1,10000000);
+        GenomeLoc chr2 = genomeLocParser.createGenomeLoc("chr2",1,10000000);
+        GenomeLoc unmapped = GenomeLoc.UNMAPPED;
+
+        List<GenomeLoc> unmappedOnly = Arrays.asList(unmapped);
+        Collections.sort(unmappedOnly);
+        Assert.assertEquals(unmappedOnly.size(),1,"Wrong number of elements in unmapped-only list.");
+        Assert.assertEquals(unmappedOnly.get(0),unmapped,"List sorted in wrong order");
+
+        List<GenomeLoc> chr1Presorted = Arrays.asList(chr1,unmapped);
+        Collections.sort(chr1Presorted);
+        Assert.assertEquals(chr1Presorted.size(),2,"Wrong number of elements in chr1,unmapped list.");
+        Assert.assertEquals(chr1Presorted,Arrays.asList(chr1,unmapped),"List sorted in wrong order");
+
+        List<GenomeLoc> chr1Inverted = Arrays.asList(unmapped,chr1);
+        Collections.sort(chr1Inverted);
+        Assert.assertEquals(chr1Inverted.size(),2,"Wrong number of elements in chr1,unmapped list.");
+        Assert.assertEquals(chr1Inverted,Arrays.asList(chr1,unmapped),"List sorted in wrong order");
+
+        List<GenomeLoc> chr1and2Presorted = Arrays.asList(chr1,chr2,unmapped);
+        Collections.sort(chr1and2Presorted);
+        Assert.assertEquals(chr1and2Presorted.size(),3,"Wrong number of elements in chr1,chr2,unmapped list.");
+        Assert.assertEquals(chr1and2Presorted,Arrays.asList(chr1,chr2,unmapped),"List sorted in wrong order");
+
+        List<GenomeLoc> chr1and2UnmappedInFront = Arrays.asList(unmapped,chr1,chr2);
+        Collections.sort(chr1and2UnmappedInFront);
+        Assert.assertEquals(chr1and2UnmappedInFront.size(),3,"Wrong number of elements in unmapped,chr1,chr2 list.");
+        Assert.assertEquals(chr1and2UnmappedInFront,Arrays.asList(chr1,chr2,unmapped),"List sorted in wrong order");
+
+        List<GenomeLoc> chr1and2UnmappedSandwiched = Arrays.asList(chr1,unmapped,chr2);
+        Collections.sort(chr1and2UnmappedSandwiched);
+        Assert.assertEquals(chr1and2UnmappedSandwiched.size(),3,"Wrong number of elements in chr1,unmapped,chr2 list.");
+        Assert.assertEquals(chr1and2UnmappedSandwiched,Arrays.asList(chr1,chr2,unmapped),"List sorted in wrong order");
+    }
+
+    @Test
+    public void testUnmappedMerge() {
+        GenomeLoc chr1 = genomeLocParser.createGenomeLoc("chr1",1,10000000);
+        GenomeLoc unmapped = GenomeLoc.UNMAPPED;
+
+        List<GenomeLoc> oneUnmappedOnly = Arrays.asList(unmapped);
+        oneUnmappedOnly = IntervalUtils.sortAndMergeIntervals(genomeLocParser,oneUnmappedOnly, IntervalMergingRule.OVERLAPPING_ONLY).toList();
+        Assert.assertEquals(oneUnmappedOnly.size(),1,"Wrong number of elements in list.");
+        Assert.assertEquals(oneUnmappedOnly.get(0),unmapped,"List sorted in wrong order");
+
+        List<GenomeLoc> twoUnmapped = Arrays.asList(unmapped,unmapped);
+        twoUnmapped = IntervalUtils.sortAndMergeIntervals(genomeLocParser,twoUnmapped,IntervalMergingRule.OVERLAPPING_ONLY).toList();
+        Assert.assertEquals(twoUnmapped.size(),1,"Wrong number of elements in list.");
+        Assert.assertEquals(twoUnmapped.get(0),unmapped,"List sorted in wrong order");
+
+        List<GenomeLoc> twoUnmappedAtEnd = Arrays.asList(chr1,unmapped,unmapped);
+        twoUnmappedAtEnd = IntervalUtils.sortAndMergeIntervals(genomeLocParser,twoUnmappedAtEnd,IntervalMergingRule.OVERLAPPING_ONLY).toList();
+        Assert.assertEquals(twoUnmappedAtEnd.size(),2,"Wrong number of elements in list.");
+        Assert.assertEquals(twoUnmappedAtEnd,Arrays.asList(chr1,unmapped),"List sorted in wrong order");
+
+        List<GenomeLoc> twoUnmappedMixed = Arrays.asList(unmapped,chr1,unmapped);
+        twoUnmappedMixed = IntervalUtils.sortAndMergeIntervals(genomeLocParser,twoUnmappedMixed,IntervalMergingRule.OVERLAPPING_ONLY).toList();
+        Assert.assertEquals(twoUnmappedMixed.size(),2,"Wrong number of elements in list.");
+        Assert.assertEquals(twoUnmappedMixed,Arrays.asList(chr1,unmapped),"List sorted in wrong order");
+    }
+
+    // -------------------------------------------------------------------------------------
+    //
+    // testing overlap detection
+    //
+    // -------------------------------------------------------------------------------------
+
+    private class ReciprocalOverlapProvider extends TestDataProvider {
+        GenomeLoc gl1, gl2;
+        int overlapSize;
+        double overlapFraction;
+
+        private ReciprocalOverlapProvider(int start1, int stop1, int start2, int stop2) {
+            super(ReciprocalOverlapProvider.class);
+            gl1 = genomeLocParser.createGenomeLoc("chr1", start1, stop1);
+            gl2 = genomeLocParser.createGenomeLoc("chr1", start2, stop2);
+
+            int shared = 0;
+            for ( int i = start1; i <= stop1; i++ ) {
+                if ( i >= start2 && i <= stop2 )
+                    shared++;
+            }
+
+            this.overlapSize = shared;
+            this.overlapFraction = Math.min((1.0*shared)/gl1.size(), (1.0*shared)/gl2.size());
+            super.setName(String.format("%d-%d / %d-%d overlap=%d / %.2f", start1, stop1, start2, stop2, overlapSize, overlapFraction));
+        }
+    }
+
+    @DataProvider(name = "ReciprocalOverlapProvider")
+    public Object[][] makeReciprocalOverlapProvider() {
+        for ( int start1 = 1; start1 <= 10; start1++ ) {
+            for ( int stop1 = start1; stop1 <= 10; stop1++ ) {
+                new ReciprocalOverlapProvider(start1, stop1, 1, 10);
+                new ReciprocalOverlapProvider(start1, stop1, 5, 10);
+                new ReciprocalOverlapProvider(start1, stop1, 5, 7);
+                new ReciprocalOverlapProvider(start1, stop1, 5, 15);
+                new ReciprocalOverlapProvider(start1, stop1, 11, 20);
+
+                new ReciprocalOverlapProvider(1, 10, start1, stop1);
+                new ReciprocalOverlapProvider(5, 10, start1, stop1);
+                new ReciprocalOverlapProvider(5, 7, start1, stop1);
+                new ReciprocalOverlapProvider(5, 15, start1, stop1);
+                new ReciprocalOverlapProvider(11, 20, start1, stop1);
+            }
+        }
+
+        return ReciprocalOverlapProvider.getTests(ReciprocalOverlapProvider.class);
+    }
+
+    @Test(dataProvider = "ReciprocalOverlapProvider")
+    public void testReciprocalOverlapProvider(ReciprocalOverlapProvider cfg) {
+        if ( cfg.overlapSize == 0 ) {
+            Assert.assertFalse(cfg.gl1.overlapsP(cfg.gl2));
+        } else {
+            Assert.assertTrue(cfg.gl1.overlapsP(cfg.gl2));
+            Assert.assertEquals(cfg.gl1.intersect(cfg.gl2).size(), cfg.overlapSize);
+            Assert.assertEquals(cfg.gl1.reciprocialOverlapFraction(cfg.gl2), cfg.overlapFraction);
+        }
+    }
+
+    // -------------------------------------------------------------------------------------
+    //
+    // testing comparison, hashcode, and equals
+    //
+    // -------------------------------------------------------------------------------------
+
+    @DataProvider(name = "GenomeLocComparisons")
+    public Object[][] createGenomeLocComparisons() {
+        List<Object[]> tests = new ArrayList<Object[]>();
+
+        final int start = 10;
+        for ( int stop = start; stop < start + 3; stop++ ) {
+            final GenomeLoc g1 = genomeLocParser.createGenomeLoc("chr2", start, stop);
+            for ( final String contig : Arrays.asList("chr1", "chr2", "chr3")) {
+                for ( int start2 = start - 1; start2 <= stop + 1; start2++ ) {
+                    for ( int stop2 = start2; stop2 < stop + 2; stop2++ ) {
+                        final GenomeLoc g2 = genomeLocParser.createGenomeLoc(contig, start2, stop2);
+
+                        ComparisonResult cmp = ComparisonResult.EQUALS;
+                        if ( contig.equals("chr3") ) cmp = ComparisonResult.LESS_THAN;
+                        else if ( contig.equals("chr1") ) cmp = ComparisonResult.GREATER_THAN;
+                        else if ( start < start2 ) cmp = ComparisonResult.LESS_THAN;
+                        else if ( start > start2 ) cmp = ComparisonResult.GREATER_THAN;
+                        else if ( stop < stop2 ) cmp = ComparisonResult.LESS_THAN;
+                        else if ( stop > stop2 ) cmp = ComparisonResult.GREATER_THAN;
+
+                        tests.add(new Object[]{g1, g2, cmp});
+                    }
+                }
+            }
+        }
+
+        return tests.toArray(new Object[][]{});
+    }
+
+    private enum ComparisonResult {
+        LESS_THAN(-1),
+        EQUALS(0),
+        GREATER_THAN(1);
+
+        final int cmp;
+
+        private ComparisonResult(int cmp) {
+            this.cmp = cmp;
+        }
+    }
+
+    @Test(dataProvider = "GenomeLocComparisons")
+    public void testGenomeLocComparisons(GenomeLoc g1, GenomeLoc g2, ComparisonResult expected) {
+        Assert.assertEquals(g1.compareTo(g2), expected.cmp, "Comparing genome locs failed");
+        Assert.assertEquals(g1.equals(g2), expected == ComparisonResult.EQUALS);
+        if ( expected == ComparisonResult.EQUALS )
+            Assert.assertEquals(g1.hashCode(), g2.hashCode(), "Equal genome locs don't have the same hash code");
+    }
+
+    // -------------------------------------------------------------------------------------
+    //
+    // testing merging functionality
+    //
+    // -------------------------------------------------------------------------------------
+
+    private static final GenomeLoc loc1 = new GenomeLoc("1", 0, 10, 20);
+    private static final GenomeLoc loc2 = new GenomeLoc("1", 0, 21, 30);
+    private static final GenomeLoc loc3 = new GenomeLoc("1", 0, 31, 40);
+
+    private class MergeTest {
+        public List<GenomeLoc> locs;
+
+        private MergeTest(final List<GenomeLoc> locs) {
+            this.locs = locs;
+        }
+    }
+
+    @DataProvider(name = "SGLtest")
+    public Object[][] createFindVariantRegionsData() {
+        List<Object[]> tests = new ArrayList<Object[]>();
+
+        tests.add(new Object[]{new MergeTest(Arrays.<GenomeLoc>asList(loc1))});
+        tests.add(new Object[]{new MergeTest(Arrays.<GenomeLoc>asList(loc1, loc2))});
+        tests.add(new Object[]{new MergeTest(Arrays.<GenomeLoc>asList(loc1, loc2, loc3))});
+
+        return tests.toArray(new Object[][]{});
+    }
+
+    @Test(dataProvider = "SGLtest", enabled = true)
+    public void testSimpleGenomeLoc(MergeTest test) {
+        testMerge(test.locs);
+    }
+
+    @Test(expectedExceptions = ReviewedGATKException.class)
+    public void testNotContiguousLocs() {
+        final List<GenomeLoc> locs = new ArrayList<GenomeLoc>(1);
+        locs.add(loc1);
+        locs.add(loc3);
+        testMerge(locs);
+    }
+
+    private void testMerge(final List<GenomeLoc> locs) {
+        GenomeLoc result1 = locs.get(0);
+        for ( int i = 1; i < locs.size(); i++ )
+            result1 = GenomeLoc.merge(result1, locs.get(i));
+
+        GenomeLoc result2 = GenomeLoc.merge(new TreeSet<GenomeLoc>(locs));
+        Assert.assertEquals(result1, result2);
+        Assert.assertEquals(result1.getStart(), locs.get(0).getStart());
+        Assert.assertEquals(result1.getStop(), locs.get(locs.size() - 1).getStop());
+    }
+
+    // -------------------------------------------------------------------------------------
+    //
+    // testing distance functionality
+    //
+    // -------------------------------------------------------------------------------------
+
+    @Test(enabled=true)
+    public void testDistanceAcrossContigs() {
+        final int chrSize = 1000;
+        SAMFileHeader header = ArtificialSAMUtils.createArtificialSamHeader(10, 0, chrSize);
+        GenomeLocParser parser = new GenomeLocParser(header.getSequenceDictionary());
+        GenomeLoc loc1 = parser.createGenomeLoc("chr3", 500);  // to check regular case
+        GenomeLoc loc2 = parser.createGenomeLoc("chr7", 200);  // to check regular case
+        GenomeLoc loc3 = parser.createGenomeLoc("chr0", 1);    // to check corner case
+        GenomeLoc loc4 = parser.createGenomeLoc("chr9", 1000);// to check corner case
+        GenomeLoc loc5 = parser.createGenomeLoc("chr7", 500);  // to make sure it does the right thing when in the same chromosome
+
+        GenomeLoc loc6 = parser.createGenomeLoc("chr7", 200, 300);
+        GenomeLoc loc7 = parser.createGenomeLoc("chr7", 500, 600);
+        GenomeLoc loc8 = parser.createGenomeLoc("chr9", 500, 600);
+
+        // Locus comparisons
+        Assert.assertEquals(loc1.distanceAcrossContigs(loc2, header), 3*chrSize + chrSize-loc1.getStop() + loc2.getStart()); // simple case, smaller first
+        Assert.assertEquals(loc2.distanceAcrossContigs(loc1, header), 3*chrSize + chrSize-loc1.getStop() + loc2.getStart()); // simple case, bigger first
+
+        Assert.assertEquals(loc3.distanceAcrossContigs(loc4, header), 10*chrSize - 1); // corner case, smaller first
+        Assert.assertEquals(loc4.distanceAcrossContigs(loc3, header), 10*chrSize - 1); // corner case, bigger first
+
+        Assert.assertEquals(loc2.distanceAcrossContigs(loc5, header), 300); // same contig, smaller first
+        Assert.assertEquals(loc5.distanceAcrossContigs(loc2, header), 300); // same contig, bigger first
+
+        // Interval comparisons
+        Assert.assertEquals(loc6.distanceAcrossContigs(loc7, header), 200); // same contig, smaller first
+        Assert.assertEquals(loc7.distanceAcrossContigs(loc6, header), 200); // same contig, bigger first
+
+        Assert.assertEquals(loc7.distanceAcrossContigs(loc8, header), chrSize + chrSize-loc7.stop + loc8.getStart()); // across contigs, smaller first
+        Assert.assertEquals(loc8.distanceAcrossContigs(loc7, header), chrSize + chrSize-loc7.stop + loc8.getStart()); // across congits, bigger first
+
+    }
+
+}
diff --git a/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/utils/MD5DB.java b/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/utils/MD5DB.java
new file mode 100644
index 0000000..d7c9929
--- /dev/null
+++ b/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/utils/MD5DB.java
@@ -0,0 +1,312 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.utils;
+
+import org.apache.commons.io.FileUtils;
+import org.apache.log4j.Logger;
+import org.broadinstitute.gatk.engine.walkers.diffengine.DiffEngine;
+import org.broadinstitute.gatk.utils.exceptions.ReviewedGATKException;
+
+import java.io.*;
+import java.util.Arrays;
+
+/**
+ * Created by IntelliJ IDEA.
+ * User: depristo
+ * Date: 7/18/11
+ * Time: 9:10 AM
+ *
+ * Utilities for manipulating the MD5 database of previous results
+ */
+public class MD5DB {
+    public static final Logger logger = Logger.getLogger(MD5DB.class);
+
+    /**
+     * Subdirectory under the ant build directory where we store integration test md5 results
+     */
+    private static final int MAX_RECORDS_TO_READ = 1000000;
+    private static final int MAX_RAW_DIFFS_TO_SUMMARIZE = -1;
+    public static final String LOCAL_MD5_DB_DIR = "integrationtests";
+    public static final String GLOBAL_MD5_DB_DIR = "/humgen/gsa-hpprojects/GATK/data/integrationtests";
+
+    // tracking and emitting a data file of origina and new md5s
+    private final File MD5MismatchesFile;
+    private final PrintStream md5MismatchStream;
+
+    public MD5DB() {
+        this(new File(MD5DB.LOCAL_MD5_DB_DIR + "/md5mismatches.txt"));
+    }
+
+    public MD5DB(final File MD5MismatchesFile) {
+        this.MD5MismatchesFile = MD5MismatchesFile;
+
+        ensureMd5DbDirectory();
+
+        logger.debug("Creating md5 mismatch db at " + MD5MismatchesFile);
+        try {
+            md5MismatchStream = new PrintStream(new FileOutputStream(MD5MismatchesFile));
+            md5MismatchStream.printf("%s\t%s\t%s%n", "expected", "observed", "test");
+        } catch ( FileNotFoundException e ) {
+            throw new ReviewedGATKException("Failed to open md5 mismatch file", e);
+        }
+
+    }
+
+    public void close() {
+        if ( md5MismatchStream != null ) {
+            logger.debug("Closeing md5 mismatch db at " + MD5MismatchesFile);
+            md5MismatchStream.close();
+        }
+    }
+
+    // ----------------------------------------------------------------------
+    //
+    // MD5 DB stuff
+    //
+    // ----------------------------------------------------------------------
+
+    /**
+     * Create the MD5 file directories if necessary
+     */
+    private void ensureMd5DbDirectory() {
+        File dir = new File(LOCAL_MD5_DB_DIR);
+        if ( ! dir.exists() ) {
+            System.out.printf("##### Creating MD5 db %s%n", LOCAL_MD5_DB_DIR);
+            if ( ! dir.mkdir() ) {
+                // Need to check AGAIN whether the dir exists, because we might be doing multi-process parallelism
+                // within the same working directory, and another GATK instance may have come along and created the
+                // directory between the calls to exists() and mkdir() above.
+                if ( ! dir.exists() ) {
+                    throw new ReviewedGATKException("Infrastructure failure: failed to create md5 directory " + LOCAL_MD5_DB_DIR);
+                }
+            }
+        }
+    }
+
+    /**
+     * Returns the path to an already existing file with the md5 contents, or valueIfNotFound
+     * if no such file exists in the db.
+     *
+     * @param md5
+     * @param valueIfNotFound
+     * @return
+     */
+    public String getMD5FilePath(final String md5, final String valueIfNotFound) {
+        // we prefer the global db to the local DB, so match it first
+        for ( String dir : Arrays.asList(GLOBAL_MD5_DB_DIR, LOCAL_MD5_DB_DIR)) {
+            File f = getFileForMD5(md5, dir);
+            if ( f.exists() && f.canRead() )
+                return f.getAbsolutePath();
+        }
+
+        return valueIfNotFound;
+    }
+
+    /**
+     * Utility function that given a file's md5 value and the path to the md5 db,
+     * returns the canonical name of the file. For example, if md5 is XXX and db is YYY,
+     * this will return YYY/XXX.integrationtest
+     *
+     * @param md5
+     * @param dbPath
+     * @return
+     */
+    private File getFileForMD5(final String md5, final String dbPath) {
+        final String basename = String.format("%s.integrationtest", md5);
+        return new File(dbPath + "/" + basename);
+    }
+
+    /**
+     * Copies the results file with md5 value to its canonical file name and db places
+     *
+     * @param md5
+     * @param resultsFile
+     */
+    private void updateMD5Db(final String md5, final File resultsFile) {
+        copyFileToDB(getFileForMD5(md5, LOCAL_MD5_DB_DIR), resultsFile);
+        copyFileToDB(getFileForMD5(md5, GLOBAL_MD5_DB_DIR), resultsFile);
+    }
+
+    /**
+     * Low-level utility routine that copies resultsFile to dbFile
+     * @param dbFile
+     * @param resultsFile
+     */
+    private void copyFileToDB(File dbFile, final File resultsFile) {
+        if ( ! dbFile.exists() ) {
+            // the file isn't already in the db, copy it over
+            System.out.printf("##### Updating MD5 file: %s%n", dbFile.getPath());
+            try {
+                FileUtils.copyFile(resultsFile, dbFile);
+            } catch ( IOException e ) {
+                System.out.printf("##### Skipping update, cannot write file %s%n", dbFile);
+            }
+        } else {
+            //System.out.printf("##### MD5 file is up to date: %s%n", dbFile.getPath());
+        }
+    }
+
+    /**
+     * Returns the byte[] of the entire contents of file, for md5 calculations
+     * @param file
+     * @return
+     * @throws IOException
+     */
+    private static byte[] getBytesFromFile(File file) throws IOException {
+        InputStream is = new FileInputStream(file);
+
+        // Get the size of the file
+        long length = file.length();
+
+        if (length > Integer.MAX_VALUE) {
+            // File is too large
+        }
+
+        // Create the byte array to hold the data
+        byte[] bytes = new byte[(int) length];
+
+        // Read in the bytes
+        int offset = 0;
+        int numRead = 0;
+        while (offset < bytes.length
+                && (numRead = is.read(bytes, offset, bytes.length - offset)) >= 0) {
+            offset += numRead;
+        }
+
+        // Ensure all the bytes have been read in
+        if (offset < bytes.length) {
+            throw new IOException("Could not completely read file " + file.getName());
+        }
+
+        // Close the input stream and return bytes
+        is.close();
+        return bytes;
+    }
+
+    public static class MD5Match {
+        public final String actualMD5, expectedMD5;
+        public final String failMessage;
+        public final String diffEngineOutput;
+        public final boolean failed;
+
+        public MD5Match(final String actualMD5, final String expectedMD5, final String failMessage, final String diffEngineOutput, final boolean failed) {
+            this.actualMD5 = actualMD5;
+            this.expectedMD5 = expectedMD5;
+            this.failMessage = failMessage;
+            this.diffEngineOutput = diffEngineOutput;
+            this.failed = failed;
+        }
+    }
+
+    /**
+     * Tests a file MD5 against an expected value, returning an MD5Match object containing a description of the
+     * match or mismatch. In case of a mismatch, outputs a description of the mismatch to various log files/streams.
+     *
+     * NOTE: This function WILL NOT throw an exception if the MD5s are different.
+     *
+     * @param testName Name of the test.
+     * @param testClassName Name of the class that contains the test.
+     * @param resultsFile File to MD5.
+     * @param expectedMD5 Expected MD5 value.
+     * @param parameterize If true or if expectedMD5 is an empty string, will print out the calculated MD5 instead of error text.
+     * @return an MD5Match object containing a description of the match/mismatch. Will have its "failed" field set
+     *         to true if there was a mismatch (unless we're using the "parameterize" argument)
+     */
+    public MD5Match testFileMD5(final String testName, final String testClassName, final File resultsFile, final String expectedMD5, final boolean parameterize) {
+        final String actualMD5 = calculateFileMD5(resultsFile);
+        String diffEngineOutput = "";
+        String failMessage = "";
+        boolean failed = false;
+
+        // copy md5 to integrationtests
+        updateMD5Db(actualMD5, resultsFile);
+
+        if (parameterize || expectedMD5.equals("")) {
+            BaseTest.log(String.format("PARAMETERIZATION: file %s has md5 = %s", resultsFile, actualMD5));
+        } else if ( ! expectedMD5.equals(actualMD5) ) {
+            failed = true;
+            failMessage = String.format("%s:%s has mismatching MD5s: expected=%s observed=%s", testClassName, testName, expectedMD5, actualMD5);
+            diffEngineOutput = logMD5MismatchAndGetDiffEngineOutput(testName, testClassName, expectedMD5, actualMD5);
+        }
+
+        return new MD5Match(actualMD5, expectedMD5, failMessage, diffEngineOutput, failed);
+    }
+
+    /**
+     * Calculates the MD5 for the specified file and returns it as a String
+     *
+     * @param file file whose MD5 to calculate
+     * @return file's MD5 in String form
+     * @throws RuntimeException if the file could not be read
+     */
+    public String calculateFileMD5( final File file ) {
+        try {
+            return Utils.calcMD5(getBytesFromFile(file));
+        }
+        catch ( Exception e ) {
+            throw new RuntimeException("Failed to read bytes from file: " + file + " for MD5 calculation", e);
+        }
+    }
+
+    /**
+     * Logs a description (including diff engine output) of the MD5 mismatch between the expectedMD5
+     * and actualMD5 to a combination of BaseTest.log(), the md5MismatchStream, and stdout, then returns
+     * the diff engine output.
+     *
+     * @param testName name of the test that generated the mismatch
+     * @param testClassName name of the class containing the test that generated the mismatch
+     * @param expectedMD5 the MD5 we were expecting from this test
+     * @param actualMD5 the MD5 we actually calculated from the test output
+     * @return the diff engine output produced while logging the description of the mismatch
+     */
+    private String logMD5MismatchAndGetDiffEngineOutput(final String testName, final String testClassName, final String expectedMD5, final String actualMD5) {
+        System.out.printf("##### Test %s:%s is going to fail #####%n", testClassName, testName);
+        String pathToExpectedMD5File = getMD5FilePath(expectedMD5, "[No DB file found]");
+        String pathToFileMD5File = getMD5FilePath(actualMD5, "[No DB file found]");
+        BaseTest.log(String.format("expected   %s", expectedMD5));
+        BaseTest.log(String.format("calculated %s", actualMD5));
+        BaseTest.log(String.format("diff %s %s", pathToExpectedMD5File, pathToFileMD5File));
+
+        md5MismatchStream.printf("%s\t%s\t%s%n", expectedMD5, actualMD5, testName);
+        md5MismatchStream.flush();
+
+        // inline differences
+        String diffEngineOutput = "";
+        final ByteArrayOutputStream baos = new ByteArrayOutputStream();
+        final PrintStream ps = new PrintStream(baos);
+        DiffEngine.SummaryReportParams params = new DiffEngine.SummaryReportParams(ps, 20, 10, 0, MAX_RAW_DIFFS_TO_SUMMARIZE, false);
+        boolean success = DiffEngine.simpleDiffFiles(new File(pathToExpectedMD5File), new File(pathToFileMD5File), MAX_RECORDS_TO_READ, params);
+        if ( success ) {
+            diffEngineOutput = baos.toString();
+            BaseTest.log(diffEngineOutput);
+            System.out.printf("Note that the above list is not comprehensive.  At most 20 lines of output, and 10 specific differences will be listed.  Please use -T DiffObjects -R " + BaseTest.publicTestDir + "exampleFASTA.fasta -m %s -t %s to explore the differences more freely%n",
+                    pathToExpectedMD5File, pathToFileMD5File);
+        }
+        ps.close();
+
+        return diffEngineOutput;
+    }
+}
diff --git a/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/utils/MD5Mismatch.java b/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/utils/MD5Mismatch.java
new file mode 100644
index 0000000..11064d1
--- /dev/null
+++ b/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/utils/MD5Mismatch.java
@@ -0,0 +1,67 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.utils;
+
+import java.util.Collections;
+import java.util.List;
+
+/**
+ * Assertion failure representing an MD5 mismatch between expected and actual
+ *
+ * @author Your Name
+ * @since Date created
+ */
+public class MD5Mismatch extends Exception {
+    final List<String> actuals, expecteds, diffEngineOutputs;
+
+    public MD5Mismatch(final String actual, final String expected, final String diffEngineOutput) {
+        this(Collections.singletonList(actual), Collections.singletonList(expected), Collections.singletonList(diffEngineOutput));
+    }
+
+    public MD5Mismatch(final List<String> actuals, final List<String> expecteds, final List<String> diffEngineOutputs) {
+        super(formatMessage(actuals, expecteds, diffEngineOutputs));
+        this.actuals = actuals;
+        this.expecteds = expecteds;
+        this.diffEngineOutputs = diffEngineOutputs;
+    }
+
+    @Override
+    public String toString() {
+        return formatMessage(actuals, expecteds, diffEngineOutputs);
+    }
+
+    private static String formatMessage(final List<String> actuals, final List<String> expecteds, final List<String> diffEngineOutputs) {
+        final StringBuilder b = new StringBuilder("MD5 mismatch: ");
+        for ( int i = 0; i < actuals.size(); i++ ) {
+            if ( i >= 1 ) b.append("\t\t\n\n");
+            b.append("actual ").append(actuals.get(i));
+            b.append(" expected ").append(expecteds.get(i));
+            b.append("\nDiff Engine Output:\n");
+            b.append(diffEngineOutputs.get(i));
+        }
+        return b.toString();
+    }
+}
diff --git a/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/utils/MRUCachingSAMSequencingDictionaryUnitTest.java b/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/utils/MRUCachingSAMSequencingDictionaryUnitTest.java
new file mode 100644
index 0000000..978a9a7
--- /dev/null
+++ b/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/utils/MRUCachingSAMSequencingDictionaryUnitTest.java
@@ -0,0 +1,97 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.utils;
+
+
+import htsjdk.samtools.reference.ReferenceSequenceFile;
+import htsjdk.samtools.SAMFileHeader;
+import htsjdk.samtools.SAMSequenceDictionary;
+import htsjdk.samtools.SAMSequenceRecord;
+import org.broadinstitute.gatk.utils.BaseTest;
+import org.broadinstitute.gatk.utils.exceptions.ReviewedGATKException;
+import org.broadinstitute.gatk.utils.exceptions.UserException;
+import org.broadinstitute.gatk.utils.fasta.CachingIndexedFastaSequenceFile;
+import org.broadinstitute.gatk.utils.sam.ArtificialSAMUtils;
+import org.testng.Assert;
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.DataProvider;
+import org.testng.annotations.Test;
+
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.util.LinkedList;
+import java.util.List;
+
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertTrue;
+
+public class MRUCachingSAMSequencingDictionaryUnitTest extends BaseTest {
+    private static ReferenceSequenceFile seq;
+    private static SAMSequenceDictionary dict;
+
+    @BeforeClass
+    public void init() throws FileNotFoundException {
+        // sequence
+        seq = new CachingIndexedFastaSequenceFile(new File(b37KGReference));
+        dict = seq.getSequenceDictionary();
+    }
+
+    @Test
+    public void testBasic() {
+        final MRUCachingSAMSequenceDictionary caching = new MRUCachingSAMSequenceDictionary(dict);
+
+        Assert.assertEquals(caching.getDictionary(), dict, "Dictionary not the one I expected");
+
+        for ( final SAMSequenceRecord rec : dict.getSequences() ) {
+            Assert.assertFalse(caching.isCached(rec.getSequenceIndex()), "Expected index to not be cached");
+            Assert.assertFalse(caching.isCached(rec.getSequenceName()), "Expected contig to not be cached");
+
+            Assert.assertEquals(caching.getSequence(rec.getSequenceName()), rec, "Couldn't query for sequence");
+            Assert.assertEquals(caching.getSequence(rec.getSequenceIndex()), rec, "Couldn't query for sequence index");
+            Assert.assertEquals(caching.hasContig(rec.getSequenceName()), true, "hasContig query for sequence");
+            Assert.assertEquals(caching.hasContigIndex(rec.getSequenceIndex()), true, "hasContigIndex query for sequence");
+            Assert.assertEquals(caching.getSequenceIndex(rec.getSequenceName()), rec.getSequenceIndex(), "Couldn't query for sequence");
+
+            Assert.assertEquals(caching.hasContig(rec.getSequenceName() + "asdfadsfa"), false, "hasContig query for unknown sequence");
+            Assert.assertEquals(caching.hasContigIndex(dict.getSequences().size()), false, "hasContigIndex query for unknown index");
+
+            Assert.assertTrue(caching.isCached(rec.getSequenceIndex()), "Expected index to be cached");
+            Assert.assertTrue(caching.isCached(rec.getSequenceName()), "Expected contig to be cached");
+        }
+    }
+
+    @Test(expectedExceptions = ReviewedGATKException.class)
+    public void testBadGetSequence() {
+        final MRUCachingSAMSequenceDictionary caching = new MRUCachingSAMSequenceDictionary(dict);
+        caching.getSequence("notInDictionary");
+    }
+
+    @Test(expectedExceptions = ReviewedGATKException.class)
+    public void testBadGetSequenceIndex() {
+        final MRUCachingSAMSequenceDictionary caching = new MRUCachingSAMSequenceDictionary(dict);
+        caching.getSequence(dict.getSequences().size());
+    }
+}
\ No newline at end of file
diff --git a/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/utils/MWUnitTest.java b/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/utils/MWUnitTest.java
new file mode 100644
index 0000000..c148dc9
--- /dev/null
+++ b/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/utils/MWUnitTest.java
@@ -0,0 +1,131 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.utils;
+
+import org.broadinstitute.gatk.utils.BaseTest;
+import org.broadinstitute.gatk.utils.collections.Pair;
+
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.Test;
+import org.testng.Assert;
+
+/**
+ * Created by IntelliJ IDEA.
+ * User: Ghost
+ * Date: 3/5/11
+ * Time: 2:06 PM
+ * To change this template use File | Settings | File Templates.
+ */
+public class MWUnitTest extends BaseTest {
+    @BeforeClass
+    public void init() { }
+
+    @Test
+    private void testMWU() {
+        logger.warn("Testing MWU");
+        MannWhitneyU mwu = new MannWhitneyU();
+        mwu.add(0, MannWhitneyU.USet.SET1);
+        mwu.add(1,MannWhitneyU.USet.SET2);
+        mwu.add(2,MannWhitneyU.USet.SET2);
+        mwu.add(3,MannWhitneyU.USet.SET2);
+        mwu.add(4,MannWhitneyU.USet.SET2);
+        mwu.add(5,MannWhitneyU.USet.SET2);
+        mwu.add(6,MannWhitneyU.USet.SET1);
+        mwu.add(7,MannWhitneyU.USet.SET1);
+        mwu.add(8,MannWhitneyU.USet.SET1);
+        mwu.add(9,MannWhitneyU.USet.SET1);
+        mwu.add(10,MannWhitneyU.USet.SET1);
+        mwu.add(11,MannWhitneyU.USet.SET2);
+        Assert.assertEquals(MannWhitneyU.calculateOneSidedU(mwu.getObservations(), MannWhitneyU.USet.SET1),25L);
+        Assert.assertEquals(MannWhitneyU.calculateOneSidedU(mwu.getObservations(),MannWhitneyU.USet.SET2),11L);
+
+        MannWhitneyU mwu2 = new MannWhitneyU();
+        MannWhitneyU mwuNoDither = new MannWhitneyU(false);
+        for ( int dp : new int[]{2,4,5,6,8} ) {
+            mwu2.add(dp,MannWhitneyU.USet.SET1);
+            mwuNoDither.add(dp,MannWhitneyU.USet.SET1);
+        }
+
+        for ( int dp : new int[]{1,3,7,9,10,11,12,13} ) {
+            mwu2.add(dp,MannWhitneyU.USet.SET2);
+            mwuNoDither.add(dp,MannWhitneyU.USet.SET2);
+        }
+
+        MannWhitneyU.ExactMode pm = MannWhitneyU.ExactMode.POINT;
+        MannWhitneyU.ExactMode cm = MannWhitneyU.ExactMode.CUMULATIVE;
+
+        // tests using the hypothesis that set 2 dominates set 1 (U value = 10)
+        Assert.assertEquals(MannWhitneyU.calculateOneSidedU(mwu2.getObservations(),MannWhitneyU.USet.SET1),10L);
+        Assert.assertEquals(MannWhitneyU.calculateOneSidedU(mwu2.getObservations(),MannWhitneyU.USet.SET2),30L);
+        Assert.assertEquals(MannWhitneyU.calculateOneSidedU(mwuNoDither.getObservations(),MannWhitneyU.USet.SET1),10L);
+        Assert.assertEquals(MannWhitneyU.calculateOneSidedU(mwuNoDither.getObservations(),MannWhitneyU.USet.SET2),30L);
+
+        Pair<Integer,Integer> sizes = mwu2.getSetSizes();
+
+        Assert.assertEquals(MannWhitneyU.calculatePUniformApproximation(sizes.first,sizes.second,10L),0.4180519701814064,1e-14);
+        Assert.assertEquals(MannWhitneyU.calculatePRecursively(sizes.first,sizes.second,10L,false,pm).second,0.021756021756021756,1e-14);
+        Assert.assertEquals(MannWhitneyU.calculatePNormalApproximation(sizes.first,sizes.second,10L,false).second,0.06214143703127617,1e-14);
+        logger.warn("Testing two-sided");
+        Assert.assertEquals((double)mwu2.runTwoSidedTest().second,2*0.021756021756021756,1e-8);
+
+        // tests using the hypothesis that set 1 dominates set 2 (U value = 30) -- empirical should be identical, normall approx close, uniform way off
+        Assert.assertEquals(MannWhitneyU.calculatePNormalApproximation(sizes.second,sizes.first,30L,true).second,2.0*0.08216463976903321,1e-14);
+        Assert.assertEquals(MannWhitneyU.calculatePUniformApproximation(sizes.second,sizes.first,30L),0.0023473625009559074,1e-14);
+        Assert.assertEquals(MannWhitneyU.calculatePRecursively(sizes.second,sizes.first,30L,false,pm).second,0.021756021756021756,1e-14); // note -- exactly same value as above
+        Assert.assertEquals(MannWhitneyU.calculatePRecursively(sizes.second,sizes.first,29L,false,cm).second,1.0-0.08547008547008,1e-14); // r does a correction, subtracting 1 from U
+        Assert.assertEquals(MannWhitneyU.calculatePRecursively(sizes.second,sizes.first,11L,false,cm).second,0.08547008547008,1e-14); // r does a correction, subtracting 1 from U
+        Assert.assertEquals(MannWhitneyU.calculatePRecursively(sizes.second,sizes.first,11L,false,cm).first,-1.36918910442,1e-2); // apache inversion set to be good only to 1e-2
+        Assert.assertEquals(MannWhitneyU.calculatePRecursively(sizes.second,sizes.first,29L,false,cm).first,1.36918910442,1e-2); // apache inversion set to be good only to 1e-2
+        Assert.assertEquals(MannWhitneyU.calculatePRecursively(sizes.second,sizes.first,29L,false,pm).first,1.2558754796642067,1e-8); // PDF should be similar
+        Assert.assertEquals(MannWhitneyU.calculatePRecursively(sizes.second,sizes.first,11L,false,pm).first,-1.2558754796642067,1e-8); // PDF should be similar
+        Assert.assertEquals(MannWhitneyU.calculatePRecursively(4,5,10L,false,pm).second,0.0952381,1e-5);
+        Assert.assertEquals(MannWhitneyU.calculatePRecursively(4,5,10L,false,pm).first,0.0,1e-14);
+
+        logger.warn("Set 1");
+        Assert.assertEquals((double)mwu2.runOneSidedTest(MannWhitneyU.USet.SET1).second,0.021756021756021756,1e-8);
+        logger.warn("Set 2");
+        Assert.assertEquals((double)mwu2.runOneSidedTest(MannWhitneyU.USet.SET2).second,0.021756021756021756,1e-8);
+
+        MannWhitneyU mwu3 = new MannWhitneyU();
+        for ( int dp : new int[]{0,2,4} ) {
+            mwu3.add(dp,MannWhitneyU.USet.SET1);
+        }
+        for ( int dp : new int[]{1,5,6,7,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34} ) {
+            mwu3.add(dp,MannWhitneyU.USet.SET2);
+        }
+        long u = MannWhitneyU.calculateOneSidedU(mwu3.getObservations(),MannWhitneyU.USet.SET1);
+        //logger.warn(String.format("U is: %d",u));
+        Pair<Integer,Integer> nums = mwu3.getSetSizes();
+        //logger.warn(String.format("Corrected p is: %.4e",MannWhitneyU.calculatePRecursivelyDoNotCheckValuesEvenThoughItIsSlow(nums.first,nums.second,u)));
+        //logger.warn(String.format("Counted sequences: %d",MannWhitneyU.countSequences(nums.first, nums.second, u)));
+        //logger.warn(String.format("Possible sequences: %d", (long) Arithmetic.binomial(nums.first+nums.second,nums.first)));
+        //logger.warn(String.format("Ratio: %.4e",MannWhitneyU.countSequences(nums.first,nums.second,u)/Arithmetic.binomial(nums.first+nums.second,nums.first)));
+        Assert.assertEquals(MannWhitneyU.calculatePRecursivelyDoNotCheckValuesEvenThoughItIsSlow(nums.first, nums.second, u), 3.665689149560116E-4, 1e-14);
+        Assert.assertEquals(MannWhitneyU.calculatePNormalApproximation(nums.first,nums.second,u,false).second,0.0032240865760884696,1e-14);
+        Assert.assertEquals(MannWhitneyU.calculatePUniformApproximation(nums.first,nums.second,u),0.0026195003025784036,1e-14);
+
+    }
+}
diff --git a/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/utils/MathUtilsUnitTest.java b/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/utils/MathUtilsUnitTest.java
new file mode 100644
index 0000000..4e2fd31
--- /dev/null
+++ b/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/utils/MathUtilsUnitTest.java
@@ -0,0 +1,913 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.utils;
+
+import cern.jet.random.Normal;
+import org.apache.commons.lang.ArrayUtils;
+import org.broadinstitute.gatk.utils.BaseTest;
+import org.testng.Assert;
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.DataProvider;
+import org.testng.annotations.Test;
+
+import java.util.*;
+
+/**
+ * Basic unit test for MathUtils
+ */
+public class MathUtilsUnitTest extends BaseTest {
+
+    @BeforeClass
+    public void init() {
+    }
+
+    /**
+     * Tests that we get unique values for the valid (non-null-producing) input space for {@link MathUtils#fastGenerateUniqueHashFromThreeIntegers(int, int, int)}.
+     */
+    @Test
+    public void testGenerateUniqueHashFromThreePositiveIntegers() {
+        logger.warn("Executing testGenerateUniqueHashFromThreePositiveIntegers");
+
+        final Set<Long> observedLongs = new HashSet<>();
+        for (short i = 0; i < Byte.MAX_VALUE; i++) {
+            for (short j = 0; j < Byte.MAX_VALUE; j++) {
+                for (short k = 0; k < Byte.MAX_VALUE; k++) {
+                    final Long aLong = MathUtils.fastGenerateUniqueHashFromThreeIntegers(i, j, k);
+                    //System.out.println(String.format("%s, %s, %s: %s", i, j, k, aLong));
+                    Assert.assertTrue(observedLongs.add(aLong));
+                }
+            }
+        }
+
+        for (short i = Byte.MAX_VALUE; i <= Short.MAX_VALUE && i > 0; i += 128) {
+            for (short j = Byte.MAX_VALUE; j <= Short.MAX_VALUE && j > 0; j += 128) {
+                for (short k = Byte.MAX_VALUE; k <= Short.MAX_VALUE && k > 0; k += 128) {
+                    final Long aLong = MathUtils.fastGenerateUniqueHashFromThreeIntegers(i, j, k);
+                    // System.out.println(String.format("%s, %s, %s: %s", i, j, k, aLong));
+                    Assert.assertTrue(observedLongs.add(aLong));
+                }
+            }
+        }
+    }
+
+    @Test(dataProvider = "log10OneMinusPow10Data")
+    public void testLog10OneMinusPow10(final double x, final double expected) {
+        final double actual = MathUtils.log10OneMinusPow10(x);
+        if (Double.isNaN(expected))
+            Assert.assertTrue(Double.isNaN(actual));
+        else
+            Assert.assertEquals(actual,expected,1E-9);
+    }
+
+    @Test(dataProvider = "log1mexpData")
+    public void testLog1mexp(final double x, final double expected) {
+        final double actual = MathUtils.log1mexp(x);
+        if (Double.isNaN(expected))
+            Assert.assertTrue(Double.isNaN(actual));
+        else
+            Assert.assertEquals(actual,expected,1E-9);
+    }
+
+    @DataProvider(name = "log10OneMinusPow10Data")
+    public Iterator<Object[]> log10OneMinusPow10Data() {
+
+          final double[] inValues = new double[] { Double.NaN, 10, 1, 0, -1, -3, -10, -30, -100, -300, -1000, -3000 };
+          return new Iterator<Object[]>() {
+
+              private int i = 0;
+
+              @Override
+              public boolean hasNext() {
+                return i < inValues.length;
+
+              }
+
+              @Override
+              public Object[] next() {
+                  final double input = inValues[i++];
+                  final double output = Math.log10( 1 - Math.pow(10,input));
+                  return new Object[] { input, output };
+              }
+
+              @Override
+              public void remove() {
+                  throw new UnsupportedOperationException();
+              }
+          };
+    }
+
+    @DataProvider(name = "log1mexpData")
+    public Iterator<Object[]> log1mexpData() {
+
+        final double[] inValues = new double[] { Double.NaN, 10, 1, 0, -1, -3, -10, -30, -100, -300, -1000, -3000 };
+        return new Iterator<Object[]>() {
+
+            private int i = 0;
+
+            @Override
+            public boolean hasNext() {
+                return i < inValues.length;
+
+            }
+
+            @Override
+            public Object[] next() {
+                final double input = inValues[i++];
+                final double output = Math.log( 1 - Math.exp(input));
+                return new Object[] { input, output };
+            }
+
+            @Override
+            public void remove() {
+                throw new UnsupportedOperationException();
+            }
+        };
+    }
+
+    /**
+     * Tests that we get the right values from the binomial distribution
+     */
+    @Test
+    public void testBinomialProbability() {
+        logger.warn("Executing testBinomialProbability");
+
+        Assert.assertEquals(MathUtils.binomialProbability(3, 2, 0.5), 0.375, 0.0001);
+        Assert.assertEquals(MathUtils.binomialProbability(100, 10, 0.5), 1.365543e-17, 1e-18);
+        Assert.assertEquals(MathUtils.binomialProbability(217, 73, 0.02), 4.521904e-67, 1e-68);
+        Assert.assertEquals(MathUtils.binomialProbability(300, 100, 0.02), 9.27097e-91, 1e-92);
+        Assert.assertEquals(MathUtils.binomialProbability(300, 150, 0.98), 6.462892e-168, 1e-169);
+        Assert.assertEquals(MathUtils.binomialProbability(300, 120, 0.98), 3.090054e-221, 1e-222);
+        Assert.assertEquals(MathUtils.binomialProbability(300, 112, 0.98), 2.34763e-236, 1e-237);
+    }
+
+    /**
+     * Tests that we get the right values from the binomial distribution
+     */
+    @Test
+    public void testCumulativeBinomialProbability() {
+        logger.warn("Executing testCumulativeBinomialProbability");
+
+        for (int j = 0; j < 2; j++) { // Test memoizing functionality, as well.
+            final int numTrials = 10;
+            for ( int i = 0; i < numTrials; i++ )
+                Assert.assertEquals(MathUtils.binomialCumulativeProbability(numTrials, i, i), MathUtils.binomialProbability(numTrials, i), 1e-10, String.format("k=%d, n=%d", i, numTrials));
+
+            Assert.assertEquals(MathUtils.binomialCumulativeProbability(10, 0, 2), 0.05468750, 1e-7);
+            Assert.assertEquals(MathUtils.binomialCumulativeProbability(10, 0, 5), 0.62304687, 1e-7);
+            Assert.assertEquals(MathUtils.binomialCumulativeProbability(10, 0, 10), 1.0, 1e-7);
+        }
+    }
+
+    /**
+     * Tests that we get the right values from the multinomial distribution
+     */
+    @Test
+    public void testMultinomialProbability() {
+        logger.warn("Executing testMultinomialProbability");
+
+        int[] counts0 = {2, 0, 1};
+        double[] probs0 = {0.33, 0.33, 0.34};
+        Assert.assertEquals(MathUtils.multinomialProbability(counts0, probs0), 0.111078, 1e-6);
+
+        int[] counts1 = {10, 20, 30};
+        double[] probs1 = {0.25, 0.25, 0.50};
+        Assert.assertEquals(MathUtils.multinomialProbability(counts1, probs1), 0.002870301, 1e-9);
+
+        int[] counts2 = {38, 82, 50, 36};
+        double[] probs2 = {0.25, 0.25, 0.25, 0.25};
+        Assert.assertEquals(MathUtils.multinomialProbability(counts2, probs2), 1.88221e-09, 1e-10);
+
+        int[] counts3 = {1, 600, 1};
+        double[] probs3 = {0.33, 0.33, 0.34};
+        Assert.assertEquals(MathUtils.multinomialProbability(counts3, probs3), 5.20988e-285, 1e-286);
+    }
+
+    /**
+     * Tests that the random index selection is working correctly
+     */
+    @Test
+    public void testRandomIndicesWithReplacement() {
+        logger.warn("Executing testRandomIndicesWithReplacement");
+
+        // Check that the size of the list returned is correct
+        Assert.assertTrue(MathUtils.sampleIndicesWithReplacement(5, 0).size() == 0);
+        Assert.assertTrue(MathUtils.sampleIndicesWithReplacement(5, 1).size() == 1);
+        Assert.assertTrue(MathUtils.sampleIndicesWithReplacement(5, 5).size() == 5);
+        Assert.assertTrue(MathUtils.sampleIndicesWithReplacement(5, 1000).size() == 1000);
+
+        // Check that the list contains only the k element range that as asked for - no more, no less
+        List<Integer> Five = new ArrayList<>();
+        Collections.addAll(Five, 0, 1, 2, 3, 4);
+        List<Integer> BigFive = MathUtils.sampleIndicesWithReplacement(5, 10000);
+        Assert.assertTrue(BigFive.containsAll(Five));
+        Assert.assertTrue(Five.containsAll(BigFive));
+    }
+
+    /**
+     * Tests that we get the right values from the multinomial distribution
+     */
+    @Test
+    public void testSliceListByIndices() {
+        logger.warn("Executing testSliceListByIndices");
+
+        // Check that the list contains only the k element range that as asked for - no more, no less but now
+        // use the index list to pull elements from another list using sliceListByIndices
+        List<Integer> Five = new ArrayList<>();
+        Collections.addAll(Five, 0, 1, 2, 3, 4);
+        List<Character> FiveAlpha = new ArrayList<>();
+        Collections.addAll(FiveAlpha, 'a', 'b', 'c', 'd', 'e');
+        List<Integer> BigFive = MathUtils.sampleIndicesWithReplacement(5, 10000);
+        List<Character> BigFiveAlpha = MathUtils.sliceListByIndices(BigFive, FiveAlpha);
+        Assert.assertTrue(BigFiveAlpha.containsAll(FiveAlpha));
+        Assert.assertTrue(FiveAlpha.containsAll(BigFiveAlpha));
+    }
+
+    /**
+     * Tests that we correctly compute mean and standard deviation from a stream of numbers
+     */
+    @Test
+    public void testRunningAverage() {
+        logger.warn("Executing testRunningAverage");
+
+        int[] numbers = {1, 2, 4, 5, 3, 128, 25678, -24};
+        MathUtils.RunningAverage r = new MathUtils.RunningAverage();
+
+        for (final double b : numbers)
+            r.add(b);
+
+        Assert.assertEquals((long) numbers.length, r.observationCount());
+        Assert.assertTrue(r.mean() - 3224.625 < 2e-10);
+        Assert.assertTrue(r.stddev() - 9072.6515881128 < 2e-10);
+    }
+
+    @Test
+    public void testLog10Gamma() {
+        logger.warn("Executing testLog10Gamma");
+
+        Assert.assertEquals(MathUtils.log10Gamma(4.0), 0.7781513, 1e-6);
+        Assert.assertEquals(MathUtils.log10Gamma(10), 5.559763, 1e-6);
+        Assert.assertEquals(MathUtils.log10Gamma(10654), 38280.53, 1e-2);
+    }
+
+    @Test
+    public void testLog10BinomialCoefficient() {
+        logger.warn("Executing testLog10BinomialCoefficient");
+        // note that we can test the binomial coefficient calculation indirectly via Newton's identity
+        // (1+z)^m = sum (m choose k)z^k
+        double[] z_vals = new double[]{0.999,0.9,0.8,0.5,0.2,0.01,0.0001};
+        int[] exponent = new int[]{5,15,25,50,100};
+        for ( double z : z_vals ) {
+            double logz = Math.log10(z);
+            for ( int exp : exponent ) {
+                double expected_log = exp*Math.log10(1+z);
+                double[] newtonArray_log = new double[1+exp];
+                for ( int k = 0 ; k <= exp; k++ ) {
+                    newtonArray_log[k] = MathUtils.log10BinomialCoefficient(exp,k)+k*logz;
+                }
+                Assert.assertEquals(MathUtils.log10sumLog10(newtonArray_log),expected_log,1e-6);
+            }
+        }
+
+        Assert.assertEquals(MathUtils.log10BinomialCoefficient(4, 2), 0.7781513, 1e-6);
+        Assert.assertEquals(MathUtils.log10BinomialCoefficient(10, 3), 2.079181, 1e-6);
+        Assert.assertEquals(MathUtils.log10BinomialCoefficient(103928, 119), 400.2156, 1e-4);
+    }
+
+    @Test
+    public void testFactorial() {
+        logger.warn("Executing testFactorial");
+        Assert.assertEquals((int) MathUtils.factorial(4), 24);
+        Assert.assertEquals((int) MathUtils.factorial(10), 3628800);
+        Assert.assertEquals((int) MathUtils.factorial(12), 479001600);
+    }
+
+    @Test
+    public void testLog10Factorial() {
+        logger.warn("Executing testLog10Factorial");
+        Assert.assertEquals(MathUtils.log10Factorial(4), 1.380211, 1e-6);
+        Assert.assertEquals(MathUtils.log10Factorial(10), 6.559763, 1e-6);
+        Assert.assertEquals(MathUtils.log10Factorial(12), 8.680337, 1e-6);
+        Assert.assertEquals(MathUtils.log10Factorial(200), 374.8969, 1e-3);
+        Assert.assertEquals(MathUtils.log10Factorial(12342), 45138.26, 1e-1);
+        double log10factorial_small = 0;
+        double log10factorial_middle = 374.8969;
+        double log10factorial_large = 45138.26;
+        int small_start = 1;
+        int med_start = 200;
+        int large_start = 12342;
+        for ( int i = 1; i < 1000; i++ ) {
+            log10factorial_small += Math.log10(i+small_start);
+            log10factorial_middle += Math.log10(i+med_start);
+            log10factorial_large += Math.log10(i+large_start);
+            Assert.assertEquals(MathUtils.log10Factorial(small_start+i),log10factorial_small,1e-6);
+            Assert.assertEquals(MathUtils.log10Factorial(med_start+i),log10factorial_middle,1e-3);
+            Assert.assertEquals(MathUtils.log10Factorial(large_start+i),log10factorial_large,1e-1);
+        }
+    }
+
+    @Test
+    public void testApproximateLog10SumLog10() {
+
+        final double requiredPrecision = 1E-4;
+
+        Assert.assertEquals(MathUtils.approximateLog10SumLog10(new double[] {0.0}), 0.0, requiredPrecision);
+        Assert.assertEquals(MathUtils.approximateLog10SumLog10(new double[] {-5.15}), -5.15, requiredPrecision);
+        Assert.assertEquals(MathUtils.approximateLog10SumLog10(new double[] {130.0}), 130.0, requiredPrecision);
+        Assert.assertEquals(MathUtils.approximateLog10SumLog10(new double[] {-0.145}), -0.145, requiredPrecision);
+
+        Assert.assertEquals(MathUtils.approximateLog10SumLog10(0.0, 0.0), Math.log10(Math.pow(10.0, 0.0) + Math.pow(10.0, 0.0)), requiredPrecision);
+        Assert.assertEquals(MathUtils.approximateLog10SumLog10(-1.0, 0.0), Math.log10(Math.pow(10.0, -1.0) + Math.pow(10.0, 0.0)), requiredPrecision);
+        Assert.assertEquals(MathUtils.approximateLog10SumLog10(0.0, -1.0), Math.log10(Math.pow(10.0, 0.0) + Math.pow(10.0, -1.0)), requiredPrecision);
+        Assert.assertEquals(MathUtils.approximateLog10SumLog10(-2.2, -3.5), Math.log10(Math.pow(10.0, -2.2) + Math.pow(10.0, -3.5)), requiredPrecision);
+        Assert.assertEquals(MathUtils.approximateLog10SumLog10(-1.0, -7.1), Math.log10(Math.pow(10.0, -1.0) + Math.pow(10.0, -7.1)), requiredPrecision);
+        Assert.assertEquals(MathUtils.approximateLog10SumLog10(5.0, 6.2), Math.log10(Math.pow(10.0, 5.0) + Math.pow(10.0, 6.2)), requiredPrecision);
+        Assert.assertEquals(MathUtils.approximateLog10SumLog10(38.1, 16.2), Math.log10(Math.pow(10.0, 38.1) + Math.pow(10.0, 16.2)), requiredPrecision);
+        Assert.assertEquals(MathUtils.approximateLog10SumLog10(-38.1, 6.2), Math.log10(Math.pow(10.0, -38.1) + Math.pow(10.0, 6.2)), requiredPrecision);
+        Assert.assertEquals(MathUtils.approximateLog10SumLog10(-19.1, -37.1), Math.log10(Math.pow(10.0, -19.1) + Math.pow(10.0, -37.1)), requiredPrecision);
+        Assert.assertEquals(MathUtils.approximateLog10SumLog10(-29.1, -27.6), Math.log10(Math.pow(10.0, -29.1) + Math.pow(10.0, -27.6)), requiredPrecision);
+        Assert.assertEquals(MathUtils.approximateLog10SumLog10(-0.12345, -0.23456), Math.log10(Math.pow(10.0, -0.12345) + Math.pow(10.0, -0.23456)), requiredPrecision);
+        Assert.assertEquals(MathUtils.approximateLog10SumLog10(-15.7654, -17.0101), Math.log10(Math.pow(10.0, -15.7654) + Math.pow(10.0, -17.0101)), requiredPrecision);
+        Assert.assertEquals(MathUtils.approximateLog10SumLog10(-0.12345, Double.NEGATIVE_INFINITY), -0.12345, requiredPrecision);
+        Assert.assertEquals(MathUtils.approximateLog10SumLog10(-15.7654, Double.NEGATIVE_INFINITY), -15.7654, requiredPrecision);
+
+        Assert.assertEquals(MathUtils.approximateLog10SumLog10(new double[] {0.0, 0.0}), Math.log10(Math.pow(10.0, 0.0) + Math.pow(10.0, 0.0)), requiredPrecision);
+        Assert.assertEquals(MathUtils.approximateLog10SumLog10(new double[] {-1.0, 0.0}), Math.log10(Math.pow(10.0, -1.0) + Math.pow(10.0, 0.0)), requiredPrecision);
+        Assert.assertEquals(MathUtils.approximateLog10SumLog10(new double[] {0.0, -1.0}), Math.log10(Math.pow(10.0, 0.0) + Math.pow(10.0, -1.0)), requiredPrecision);
+        Assert.assertEquals(MathUtils.approximateLog10SumLog10(new double[] {-2.2, -3.5}), Math.log10(Math.pow(10.0, -2.2) + Math.pow(10.0, -3.5)), requiredPrecision);
+        Assert.assertEquals(MathUtils.approximateLog10SumLog10(new double[] {-1.0, -7.1}), Math.log10(Math.pow(10.0, -1.0) + Math.pow(10.0, -7.1)), requiredPrecision);
+        Assert.assertEquals(MathUtils.approximateLog10SumLog10(new double[] {5.0, 6.2}), Math.log10(Math.pow(10.0, 5.0) + Math.pow(10.0, 6.2)), requiredPrecision);
+        Assert.assertEquals(MathUtils.approximateLog10SumLog10(new double[] {38.1, 16.2}), Math.log10(Math.pow(10.0, 38.1) + Math.pow(10.0, 16.2)), requiredPrecision);
+        Assert.assertEquals(MathUtils.approximateLog10SumLog10(new double[] {-38.1, 6.2}), Math.log10(Math.pow(10.0, -38.1) + Math.pow(10.0, 6.2)), requiredPrecision);
+        Assert.assertEquals(MathUtils.approximateLog10SumLog10(new double[] {-19.1, -37.1}), Math.log10(Math.pow(10.0, -19.1) + Math.pow(10.0, -37.1)), requiredPrecision);
+        Assert.assertEquals(MathUtils.approximateLog10SumLog10(new double[] {-29.1, -27.6}), Math.log10(Math.pow(10.0, -29.1) + Math.pow(10.0, -27.6)), requiredPrecision);
+        Assert.assertEquals(MathUtils.approximateLog10SumLog10(new double[] {-0.12345, -0.23456}), Math.log10(Math.pow(10.0, -0.12345) + Math.pow(10.0, -0.23456)), requiredPrecision);
+        Assert.assertEquals(MathUtils.approximateLog10SumLog10(new double[] {-15.7654, -17.0101}), Math.log10(Math.pow(10.0, -15.7654) + Math.pow(10.0, -17.0101)), requiredPrecision);
+
+        Assert.assertEquals(MathUtils.approximateLog10SumLog10(new double[] {0.0, 0.0, 0.0}), Math.log10(Math.pow(10.0, 0.0) + Math.pow(10.0, 0.0) + Math.pow(10.0, 0.0)), requiredPrecision);
+        Assert.assertEquals(MathUtils.approximateLog10SumLog10(new double[] {-1.0, 0.0, 0.0}), Math.log10(Math.pow(10.0, -1.0) + Math.pow(10.0, 0.0) + Math.pow(10.0, 0.0)), requiredPrecision);
+        Assert.assertEquals(MathUtils.approximateLog10SumLog10(new double[] {0.0, -1.0, -2.5}), Math.log10(Math.pow(10.0, 0.0) + Math.pow(10.0, -1.0) + Math.pow(10.0, -2.5)), requiredPrecision);
+        Assert.assertEquals(MathUtils.approximateLog10SumLog10(new double[] {-2.2, -3.5, -1.1}), Math.log10(Math.pow(10.0, -2.2) + Math.pow(10.0, -3.5) + Math.pow(10.0, -1.1)), requiredPrecision);
+        Assert.assertEquals(MathUtils.approximateLog10SumLog10(new double[] {-1.0, -7.1, 0.5}), Math.log10(Math.pow(10.0, -1.0) + Math.pow(10.0, -7.1) + Math.pow(10.0, 0.5)), requiredPrecision);
+        Assert.assertEquals(MathUtils.approximateLog10SumLog10(new double[] {5.0, 6.2, 1.3}), Math.log10(Math.pow(10.0, 5.0) + Math.pow(10.0, 6.2) + Math.pow(10.0, 1.3)), requiredPrecision);
+        Assert.assertEquals(MathUtils.approximateLog10SumLog10(new double[] {38.1, 16.2, 18.1}), Math.log10(Math.pow(10.0, 38.1) + Math.pow(10.0, 16.2) + Math.pow(10.0, 18.1)), requiredPrecision);
+        Assert.assertEquals(MathUtils.approximateLog10SumLog10(new double[] {-38.1, 6.2, 26.6}), Math.log10(Math.pow(10.0, -38.1) + Math.pow(10.0, 6.2) + Math.pow(10.0, 26.6)), requiredPrecision);
+        Assert.assertEquals(MathUtils.approximateLog10SumLog10(new double[] {-19.1, -37.1, -45.1}), Math.log10(Math.pow(10.0, -19.1) + Math.pow(10.0, -37.1) + Math.pow(10.0, -45.1)), requiredPrecision);
+        Assert.assertEquals(MathUtils.approximateLog10SumLog10(new double[] {-29.1, -27.6, -26.2}), Math.log10(Math.pow(10.0, -29.1) + Math.pow(10.0, -27.6) + Math.pow(10.0, -26.2)), requiredPrecision);
+        Assert.assertEquals(MathUtils.approximateLog10SumLog10(new double[] {-0.12345, -0.23456, -0.34567}), Math.log10(Math.pow(10.0, -0.12345) + Math.pow(10.0, -0.23456) + Math.pow(10.0, -0.34567)), requiredPrecision);
+        Assert.assertEquals(MathUtils.approximateLog10SumLog10(new double[] {-15.7654, -17.0101, -17.9341}), Math.log10(Math.pow(10.0, -15.7654) + Math.pow(10.0, -17.0101) + Math.pow(10.0, -17.9341)), requiredPrecision);
+
+        Assert.assertEquals(MathUtils.approximateLog10SumLog10(0.0, 0.0, 0.0), Math.log10(Math.pow(10.0, 0.0) + Math.pow(10.0, 0.0) + Math.pow(10.0, 0.0)), requiredPrecision);
+        Assert.assertEquals(MathUtils.approximateLog10SumLog10(-1.0, 0.0, 0.0), Math.log10(Math.pow(10.0, -1.0) + Math.pow(10.0, 0.0) + Math.pow(10.0, 0.0)), requiredPrecision);
+        Assert.assertEquals(MathUtils.approximateLog10SumLog10(0.0, -1.0, -2.5), Math.log10(Math.pow(10.0, 0.0) + Math.pow(10.0, -1.0) + Math.pow(10.0, -2.5)), requiredPrecision);
+        Assert.assertEquals(MathUtils.approximateLog10SumLog10(-2.2, -3.5, -1.1), Math.log10(Math.pow(10.0, -2.2) + Math.pow(10.0, -3.5) + Math.pow(10.0, -1.1)), requiredPrecision);
+        Assert.assertEquals(MathUtils.approximateLog10SumLog10(-1.0, -7.1, 0.5), Math.log10(Math.pow(10.0, -1.0) + Math.pow(10.0, -7.1) + Math.pow(10.0, 0.5)), requiredPrecision);
+        Assert.assertEquals(MathUtils.approximateLog10SumLog10(5.0, 6.2, 1.3), Math.log10(Math.pow(10.0, 5.0) + Math.pow(10.0, 6.2) + Math.pow(10.0, 1.3)), requiredPrecision);
+        Assert.assertEquals(MathUtils.approximateLog10SumLog10(38.1, 16.2, 18.1), Math.log10(Math.pow(10.0, 38.1) + Math.pow(10.0, 16.2) + Math.pow(10.0, 18.1)), requiredPrecision);
+        Assert.assertEquals(MathUtils.approximateLog10SumLog10(-38.1, 6.2, 26.6), Math.log10(Math.pow(10.0, -38.1) + Math.pow(10.0, 6.2) + Math.pow(10.0, 26.6)), requiredPrecision);
+        Assert.assertEquals(MathUtils.approximateLog10SumLog10(-19.1, -37.1, -45.1), Math.log10(Math.pow(10.0, -19.1) + Math.pow(10.0, -37.1) + Math.pow(10.0, -45.1)), requiredPrecision);
+        Assert.assertEquals(MathUtils.approximateLog10SumLog10(-29.1, -27.6, -26.2), Math.log10(Math.pow(10.0, -29.1) + Math.pow(10.0, -27.6) + Math.pow(10.0, -26.2)), requiredPrecision);
+        Assert.assertEquals(MathUtils.approximateLog10SumLog10(-0.12345, -0.23456, -0.34567), Math.log10(Math.pow(10.0, -0.12345) + Math.pow(10.0, -0.23456) + Math.pow(10.0, -0.34567)), requiredPrecision);
+        Assert.assertEquals(MathUtils.approximateLog10SumLog10(-15.7654, -17.0101, -17.9341), Math.log10(Math.pow(10.0, -15.7654) + Math.pow(10.0, -17.0101) + Math.pow(10.0, -17.9341)), requiredPrecision);
+
+        // magnitude of the sum doesn't matter, so we can combinatorially test this via partitions of unity
+        double[] mult_partitionFactor = new double[]{0.999,0.98,0.95,0.90,0.8,0.5,0.3,0.1,0.05,0.001};
+        int[] n_partitions = new int[] {2,4,8,16,32,64,128,256,512,1028};
+        for ( double alpha : mult_partitionFactor ) {
+            double log_alpha = Math.log10(alpha);
+            double log_oneMinusAlpha = Math.log10(1-alpha);
+            for ( int npart : n_partitions ) {
+                double[] multiplicative = new double[npart];
+                double[] equal = new double[npart];
+                double remaining_log = 0.0;  // realspace = 1
+                for ( int i = 0 ; i < npart-1; i++ ) {
+                    equal[i] = -Math.log10(npart);
+                    double piece = remaining_log + log_alpha; // take a*remaining, leaving remaining-a*remaining = (1-a)*remaining
+                    multiplicative[i] = piece;
+                    remaining_log = remaining_log + log_oneMinusAlpha;
+                }
+                equal[npart-1] = -Math.log10(npart);
+                multiplicative[npart-1] = remaining_log;
+                Assert.assertEquals(MathUtils.approximateLog10SumLog10(equal),0.0,requiredPrecision,String.format("Did not sum to one: k=%d equal partitions.",npart));
+                Assert.assertEquals(MathUtils.approximateLog10SumLog10(multiplicative),0.0,requiredPrecision, String.format("Did not sum to one: k=%d multiplicative partitions with alpha=%f",npart,alpha));
+            }
+        }
+    }
+
+    @Test
+    public void testLog10sumLog10() {
+        final double requiredPrecision = 1E-14;
+
+        final double log3 = 0.477121254719662;
+        Assert.assertEquals(MathUtils.log10sumLog10(new double[]{0.0, 0.0, 0.0}), log3, requiredPrecision);
+        Assert.assertEquals(MathUtils.log10sumLog10(new double[] {0.0, 0.0, 0.0}, 0), log3, requiredPrecision);
+        Assert.assertEquals(MathUtils.log10sumLog10(new double[]{0.0, 0.0, 0.0}, 0, 3), log3, requiredPrecision);
+
+        final double log2 = 0.301029995663981;
+        Assert.assertEquals(MathUtils.log10sumLog10(new double[] {0.0, 0.0, 0.0}, 0, 2), log2, requiredPrecision);
+        Assert.assertEquals(MathUtils.log10sumLog10(new double[] {0.0, 0.0, 0.0}, 0, 1), 0.0, requiredPrecision);
+
+        Assert.assertEquals(MathUtils.log10sumLog10(new double[] {0.0}), 0.0, requiredPrecision);
+        Assert.assertEquals(MathUtils.log10sumLog10(new double[] {-5.15}), -5.15, requiredPrecision);
+        Assert.assertEquals(MathUtils.log10sumLog10(new double[] {130.0}), 130.0, requiredPrecision);
+        Assert.assertEquals(MathUtils.log10sumLog10(new double[] {-0.145}), -0.145, requiredPrecision);
+
+        Assert.assertEquals(MathUtils.log10sumLog10(new double[] {0.0, 0.0}), Math.log10(Math.pow(10.0, 0.0) + Math.pow(10.0, 0.0)), requiredPrecision);
+        Assert.assertEquals(MathUtils.log10sumLog10(new double[] {-1.0, 0.0}), Math.log10(Math.pow(10.0, -1.0) + Math.pow(10.0, 0.0)), requiredPrecision);
+        Assert.assertEquals(MathUtils.log10sumLog10(new double[] {0.0, -1.0}), Math.log10(Math.pow(10.0, 0.0) + Math.pow(10.0, -1.0)), requiredPrecision);
+        Assert.assertEquals(MathUtils.log10sumLog10(new double[] {-2.2, -3.5}), Math.log10(Math.pow(10.0, -2.2) + Math.pow(10.0, -3.5)), requiredPrecision);
+        Assert.assertEquals(MathUtils.log10sumLog10(new double[] {-1.0, -7.1}), Math.log10(Math.pow(10.0, -1.0) + Math.pow(10.0, -7.1)), requiredPrecision);
+        Assert.assertEquals(MathUtils.log10sumLog10(new double[] {5.0, 6.2}), Math.log10(Math.pow(10.0, 5.0) + Math.pow(10.0, 6.2)), requiredPrecision);
+        Assert.assertEquals(MathUtils.log10sumLog10(new double[] {38.1, 16.2}), Math.log10(Math.pow(10.0, 38.1) + Math.pow(10.0, 16.2)), requiredPrecision);
+        Assert.assertEquals(MathUtils.log10sumLog10(new double[] {-38.1, 6.2}), Math.log10(Math.pow(10.0, -38.1) + Math.pow(10.0, 6.2)), requiredPrecision);
+        Assert.assertEquals(MathUtils.log10sumLog10(new double[] {-19.1, -37.1}), Math.log10(Math.pow(10.0, -19.1) + Math.pow(10.0, -37.1)), requiredPrecision);
+        Assert.assertEquals(MathUtils.log10sumLog10(new double[] {-29.1, -27.6}), Math.log10(Math.pow(10.0, -29.1) + Math.pow(10.0, -27.6)), requiredPrecision);
+        Assert.assertEquals(MathUtils.log10sumLog10(new double[] {-0.12345, -0.23456}), Math.log10(Math.pow(10.0, -0.12345) + Math.pow(10.0, -0.23456)), requiredPrecision);
+        Assert.assertEquals(MathUtils.log10sumLog10(new double[] {-15.7654, -17.0101}), Math.log10(Math.pow(10.0, -15.7654) + Math.pow(10.0, -17.0101)), requiredPrecision);
+
+        Assert.assertEquals(MathUtils.log10sumLog10(new double[] {0.0, 0.0, 0.0}), Math.log10(Math.pow(10.0, 0.0) + Math.pow(10.0, 0.0) + Math.pow(10.0, 0.0)), requiredPrecision);
+        Assert.assertEquals(MathUtils.log10sumLog10(new double[] {-1.0, 0.0, 0.0}), Math.log10(Math.pow(10.0, -1.0) + Math.pow(10.0, 0.0) + Math.pow(10.0, 0.0)), requiredPrecision);
+        Assert.assertEquals(MathUtils.log10sumLog10(new double[] {0.0, -1.0, -2.5}), Math.log10(Math.pow(10.0, 0.0) + Math.pow(10.0, -1.0) + Math.pow(10.0, -2.5)), requiredPrecision);
+        Assert.assertEquals(MathUtils.log10sumLog10(new double[] {-2.2, -3.5, -1.1}), Math.log10(Math.pow(10.0, -2.2) + Math.pow(10.0, -3.5) + Math.pow(10.0, -1.1)), requiredPrecision);
+        Assert.assertEquals(MathUtils.log10sumLog10(new double[] {-1.0, -7.1, 0.5}), Math.log10(Math.pow(10.0, -1.0) + Math.pow(10.0, -7.1) + Math.pow(10.0, 0.5)), requiredPrecision);
+        Assert.assertEquals(MathUtils.log10sumLog10(new double[] {5.0, 6.2, 1.3}), Math.log10(Math.pow(10.0, 5.0) + Math.pow(10.0, 6.2) + Math.pow(10.0, 1.3)), requiredPrecision);
+        Assert.assertEquals(MathUtils.log10sumLog10(new double[] {38.1, 16.2, 18.1}), Math.log10(Math.pow(10.0, 38.1) + Math.pow(10.0, 16.2) + Math.pow(10.0, 18.1)), requiredPrecision);
+        Assert.assertEquals(MathUtils.log10sumLog10(new double[] {-38.1, 6.2, 26.6}), Math.log10(Math.pow(10.0, -38.1) + Math.pow(10.0, 6.2) + Math.pow(10.0, 26.6)), requiredPrecision);
+        Assert.assertEquals(MathUtils.log10sumLog10(new double[] {-19.1, -37.1, -45.1}), Math.log10(Math.pow(10.0, -19.1) + Math.pow(10.0, -37.1) + Math.pow(10.0, -45.1)), requiredPrecision);
+        Assert.assertEquals(MathUtils.log10sumLog10(new double[] {-29.1, -27.6, -26.2}), Math.log10(Math.pow(10.0, -29.1) + Math.pow(10.0, -27.6) + Math.pow(10.0, -26.2)), requiredPrecision);
+        Assert.assertEquals(MathUtils.log10sumLog10(new double[] {-0.12345, -0.23456, -0.34567}), Math.log10(Math.pow(10.0, -0.12345) + Math.pow(10.0, -0.23456) + Math.pow(10.0, -0.34567)), requiredPrecision);
+        Assert.assertEquals(MathUtils.log10sumLog10(new double[] {-15.7654, -17.0101, -17.9341}), Math.log10(Math.pow(10.0, -15.7654) + Math.pow(10.0, -17.0101) + Math.pow(10.0, -17.9341)), requiredPrecision);
+
+        // magnitude of the sum doesn't matter, so we can combinatorially test this via partitions of unity
+        double[] mult_partitionFactor = new double[]{0.999,0.98,0.95,0.90,0.8,0.5,0.3,0.1,0.05,0.001};
+        int[] n_partitions = new int[] {2,4,8,16,32,64,128,256,512,1028};
+        for ( double alpha : mult_partitionFactor ) {
+            double log_alpha = Math.log10(alpha);
+            double log_oneMinusAlpha = Math.log10(1-alpha);
+            for ( int npart : n_partitions ) {
+                double[] multiplicative = new double[npart];
+                double[] equal = new double[npart];
+                double remaining_log = 0.0;  // realspace = 1
+                for ( int i = 0 ; i < npart-1; i++ ) {
+                    equal[i] = -Math.log10(npart);
+                    double piece = remaining_log + log_alpha; // take a*remaining, leaving remaining-a*remaining = (1-a)*remaining
+                    multiplicative[i] = piece;
+                    remaining_log = remaining_log + log_oneMinusAlpha;
+                }
+                equal[npart-1] = -Math.log10(npart);
+                multiplicative[npart-1] = remaining_log;
+                Assert.assertEquals(MathUtils.log10sumLog10(equal),0.0,requiredPrecision);
+                Assert.assertEquals(MathUtils.log10sumLog10(multiplicative),0.0,requiredPrecision,String.format("Did not sum to one: nPartitions=%d, alpha=%f",npart,alpha));
+            }
+        }
+    }
+
+    @Test
+    public void testLogDotProduct() {
+        Assert.assertEquals(MathUtils.logDotProduct(new double[]{-5.0,-3.0,2.0}, new double[]{6.0,7.0,8.0}),10.0,1e-3);
+        Assert.assertEquals(MathUtils.logDotProduct(new double[]{-5.0}, new double[]{6.0}),1.0,1e-3);
+    }
+
+    @Test
+    public void testNormalDistribution() {
+        final double requiredPrecision = 1E-10;
+
+        final Normal n = new Normal(0.0, 1.0, null);
+        for( final double mu : new double[]{-5.0, -3.2, -1.5, 0.0, 1.2, 3.0, 5.8977} ) {
+            for( final double sigma : new double[]{1.2, 3.0, 5.8977} ) {
+                for( final double x : new double[]{-5.0, -3.2, -1.5, 0.0, 1.2, 3.0, 5.8977} ) {
+                    n.setState(mu, sigma);
+                    Assert.assertEquals(n.pdf(x), MathUtils.normalDistribution(mu, sigma, x), requiredPrecision);
+                    Assert.assertEquals(Math.log10(n.pdf(x)), MathUtils.normalDistributionLog10(mu, sigma, x), requiredPrecision);
+                }
+            }
+        }
+    }
+
+    @DataProvider(name = "ArrayMinData")
+    public Object[][] makeArrayMinData() {
+        List<Object[]> tests = new ArrayList<>();
+
+        // this functionality can be adapted to provide input data for whatever you might want in your data
+        tests.add(new Object[]{Arrays.asList(10), 10});
+        tests.add(new Object[]{Arrays.asList(-10), -10});
+
+        for ( final List<Integer> values : Utils.makePermutations(Arrays.asList(1,2,3), 3, false) ) {
+            tests.add(new Object[]{values, 1});
+        }
+
+        for ( final List<Integer> values : Utils.makePermutations(Arrays.asList(1,2,-3), 3, false) ) {
+            tests.add(new Object[]{values, -3});
+        }
+
+
+        return tests.toArray(new Object[][]{});
+    }
+
+    @Test(dataProvider = "ArrayMinData")
+    public void testArrayMinList(final List<Integer> values, final int expected) {
+        final int actual = MathUtils.arrayMin(values);
+        Assert.assertEquals(actual, expected, "Failed with " + values);
+    }
+
+    @Test(dataProvider = "ArrayMinData")
+    public void testArrayMinIntArray(final List<Integer> values, final int expected) {
+        final int[] asArray = ArrayUtils.toPrimitive(values.toArray(new Integer[values.size()]));
+        final int actual = MathUtils.arrayMin(asArray);
+        Assert.assertEquals(actual, expected, "Failed with " + values);
+    }
+
+    @Test(dataProvider = "ArrayMinData")
+    public void testArrayMinByteArray(final List<Integer> values, final int expected) {
+        final byte[] asArray = new byte[values.size()];
+        for ( int i = 0; i < values.size(); i++ ) asArray[i] = (byte)(values.get(i) & 0xFF);
+        final byte actual = MathUtils.arrayMin(asArray);
+        Assert.assertEquals(actual, (byte)(expected & 0xFF), "Failed with " + values);
+    }
+
+    @Test(dataProvider = "ArrayMinData")
+    public void testArrayMinDoubleArray(final List<Integer> values, final int expected) {
+        final double[] asArray = new double[values.size()];
+        for ( int i = 0; i < values.size(); i++ ) asArray[i] = (double)(values.get(i));
+        final double actual = MathUtils.arrayMin(asArray);
+        Assert.assertEquals(actual, (double)expected, "Failed with " + values);
+    }
+
+    @DataProvider(name = "MedianData")
+    public Object[][] makeMedianData() {
+        final List<Object[]> tests = new ArrayList<>();
+
+        // this functionality can be adapted to provide input data for whatever you might want in your data
+        tests.add(new Object[]{Arrays.asList(10), 10});
+        tests.add(new Object[]{Arrays.asList(1, 10), 10});
+
+        for ( final List<Integer> values : Utils.makePermutations(Arrays.asList(1,2,-3), 3, false) ) {
+            tests.add(new Object[]{values, 1});
+        }
+
+        for ( final List<Double> values : Utils.makePermutations(Arrays.asList(1.1,2.1,-3.1), 3, false) ) {
+            tests.add(new Object[]{values, 1.1});
+        }
+
+        return tests.toArray(new Object[][]{});
+    }
+
+    @Test(dataProvider = "MedianData")
+    public void testMedian(final List<Comparable> values, final Comparable expected) {
+        final Comparable actual = MathUtils.median(values);
+        Assert.assertEquals(actual, expected, "Failed with " + values);
+    }
+
+
+
+    // man. All this to test dirichlet.
+
+    private double[] unwrap(List<Double> stuff) {
+        double[] unwrapped = new double[stuff.size()];
+        int idx = 0;
+        for ( Double d : stuff ) {
+            unwrapped[idx++] = d == null ? 0.0 : d;
+        }
+
+        return unwrapped;
+    }
+
+    /**
+     * The PartitionGenerator generates all of the partitions of a number n, e.g.
+     * 5 + 0
+     * 4 + 1
+     * 3 + 2
+     * 3 + 1 + 1
+     * 2 + 2 + 1
+     * 2 + 1 + 1 + 1
+     * 1 + 1 + 1 + 1 + 1
+     *
+     * This is used to help enumerate the state space over which the Dirichlet-Multinomial is defined,
+     * to ensure that the distribution function is properly implemented
+     */
+    class PartitionGenerator implements Iterator<List<Integer>> {
+        // generate the partitions of an integer, each partition sorted numerically
+        int n;
+        List<Integer> a;
+
+        int y;
+        int k;
+        int state;
+
+        int x;
+        int l;
+
+        public PartitionGenerator(int n) {
+            this.n = n;
+            this.y = n - 1;
+            this.k = 1;
+            this.a = new ArrayList<>();
+            for ( int i = 0; i < n; i++ ) {
+                this.a.add(i);
+            }
+            this.state = 0;
+        }
+
+        public void remove()  { /* do nothing */ }
+
+        public boolean hasNext() { return ! ( this.k == 0 && state == 0 ); }
+
+        private String dataStr()  {
+            return String.format("a = [%s]  k = %d  y = %d  state = %d  x = %d  l = %d",
+                    Utils.join(",",a), k, y, state, x, l);
+        }
+
+        public List<Integer> next() {
+            if ( this.state == 0 ) {
+                this.x = a.get(k-1)+1;
+                k -= 1;
+                this.state = 1;
+            }
+
+            if ( this.state == 1 ) {
+                while ( 2 * x <= y ) {
+                    this.a.set(k,x);
+                    this.y -= (int) x;
+                    this.k++;
+                }
+                this.l = 1+this.k;
+                this.state = 2;
+            }
+
+            if ( this.state == 2 ) {
+                if ( x <= y ) {
+                    this.a.set(k,x);
+                    this.a.set(l,y);
+                    x += 1;
+                    y -= 1;
+                    return this.a.subList(0, this.k + 2);
+                } else {
+                    this.state =3;
+                }
+            }
+
+            if ( this.state == 3 ) {
+                this.a.set(k,x+y);
+                this.y = x + y - 1;
+                this.state = 0;
+                return a.subList(0, k + 1);
+            }
+
+            throw new IllegalStateException("Cannot get here");
+        }
+
+        public String toString() {
+            final StringBuilder buf = new StringBuilder();
+            buf.append("{ ");
+            while ( hasNext() ) {
+                buf.append("[");
+                buf.append(Utils.join(",",next()));
+                buf.append("],");
+            }
+            buf.deleteCharAt(buf.lastIndexOf(","));
+            buf.append(" }");
+            return buf.toString();
+        }
+
+    }
+
+    /**
+     * NextCounts is the enumerator over the state space of the multinomial dirichlet.
+     *
+     * It filters the partition of the total sum to only those with a number of terms
+     * equal to the number of categories.
+     *
+     * It then generates all permutations of that partition.
+     *
+     * In so doing it enumerates over the full state space.
+     */
+    class NextCounts implements Iterator<int[]> {
+
+        private PartitionGenerator partitioner;
+        private int numCategories;
+        private int[] next;
+
+        public NextCounts(int numCategories, int totalCounts) {
+            partitioner = new PartitionGenerator(totalCounts);
+            this.numCategories = numCategories;
+            next = nextFromPartitioner();
+        }
+
+        public void remove() { /* do nothing */ }
+
+        public boolean hasNext() { return next != null; }
+
+        public int[] next() {
+            int[] toReturn = clone(next);
+            next = nextPermutation();
+            if ( next == null ) {
+                next = nextFromPartitioner();
+            }
+
+            return toReturn;
+        }
+
+        private int[] clone(int[] arr) {
+            return Arrays.copyOf(arr, arr.length);
+        }
+
+        private int[] nextFromPartitioner() {
+            if ( partitioner.hasNext() ) {
+                List<Integer> nxt = partitioner.next();
+                while ( partitioner.hasNext() && nxt.size() > numCategories ) {
+                    nxt = partitioner.next();
+                }
+
+                if ( nxt.size() > numCategories ) {
+                    return null;
+                } else {
+                    int[] buf = new int[numCategories];
+                    for ( int idx = 0; idx < nxt.size(); idx++ ) {
+                        buf[idx] = nxt.get(idx);
+                    }
+                    Arrays.sort(buf);
+                    return buf;
+                }
+            }
+
+            return null;
+        }
+
+        public int[] nextPermutation() {
+            return MathUtilsUnitTest.nextPermutation(next);
+        }
+
+    }
+
+    public static int[] nextPermutation(int[] next) {
+        // the counts can swap among each other. The int[] is originally in ascending order
+        // this generates the next array in lexicographic order descending
+
+        // locate the last occurrence where next[k] < next[k+1]
+        int gt = -1;
+        for ( int idx = 0; idx < next.length-1; idx++) {
+            if ( next[idx] < next[idx+1] ) {
+                gt = idx;
+            }
+        }
+
+        if ( gt == -1 ) {
+            return null;
+        }
+
+        int largestLessThan = gt+1;
+        for ( int idx = 1 + largestLessThan; idx < next.length; idx++) {
+            if ( next[gt] < next[idx] ) {
+                largestLessThan = idx;
+            }
+        }
+
+        int val = next[gt];
+        next[gt] = next[largestLessThan];
+        next[largestLessThan] = val;
+
+        // reverse the tail of the array
+        int[] newTail = new int[next.length-gt-1];
+        int ctr = 0;
+        for ( int idx = next.length-1; idx > gt; idx-- ) {
+            newTail[ctr++] = next[idx];
+        }
+
+        for ( int idx = 0; idx < newTail.length; idx++) {
+            next[gt+idx+1] = newTail[idx];
+        }
+
+        return next;
+    }
+
+
+    // before testing the dirichlet multinomial, we need to test the
+    // classes used to test the dirichlet multinomial
+
+    @Test
+    public void testPartitioner() {
+        int[] numsToTest = new int[]{1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20};
+        int[] expectedSizes = new int[]{1, 2, 3, 5, 7, 11, 15, 22, 30, 42, 56, 77, 101, 135, 176, 231, 297, 385, 490, 627};
+        for ( int testNum = 0; testNum < numsToTest.length; testNum++ ) {
+            PartitionGenerator gen = new PartitionGenerator(numsToTest[testNum]);
+            int size = 0;
+            while ( gen.hasNext() ) {
+                logger.debug(gen.dataStr());
+                size += 1;
+                gen.next();
+            }
+            Assert.assertEquals(size,expectedSizes[testNum],
+                    String.format("Expected %d partitions, observed %s",expectedSizes[testNum],new PartitionGenerator(numsToTest[testNum]).toString()));
+        }
+    }
+
+    @Test
+    public void testNextPermutation() {
+        int[] arr = new int[]{1,2,3,4};
+        int[][] gens = new int[][] {
+                new int[]{1,2,3,4},
+                new int[]{1,2,4,3},
+                new int[]{1,3,2,4},
+                new int[]{1,3,4,2},
+                new int[]{1,4,2,3},
+                new int[]{1,4,3,2},
+                new int[]{2,1,3,4},
+                new int[]{2,1,4,3},
+                new int[]{2,3,1,4},
+                new int[]{2,3,4,1},
+                new int[]{2,4,1,3},
+                new int[]{2,4,3,1},
+                new int[]{3,1,2,4},
+                new int[]{3,1,4,2},
+                new int[]{3,2,1,4},
+                new int[]{3,2,4,1},
+                new int[]{3,4,1,2},
+                new int[]{3,4,2,1},
+                new int[]{4,1,2,3},
+                new int[]{4,1,3,2},
+                new int[]{4,2,1,3},
+                new int[]{4,2,3,1},
+                new int[]{4,3,1,2},
+                new int[]{4,3,2,1} };
+        for ( int gen = 0; gen < gens.length; gen ++ ) {
+            for ( int idx = 0; idx < 3; idx++ ) {
+                Assert.assertEquals(arr[idx],gens[gen][idx],
+                 String.format("Error at generation %d, expected %s, observed %s",gen,Arrays.toString(gens[gen]),Arrays.toString(arr)));
+            }
+            arr = nextPermutation(arr);
+        }
+    }
+
+    private double[] addEpsilon(double[] counts) {
+        double[] d = new double[counts.length];
+        for ( int i = 0; i < counts.length; i ++ ) {
+            d[i] = counts[i] + 1e-3;
+        }
+        return d;
+    }
+
+    @Test
+    public void testDirichletMultinomial() {
+        List<double[]> testAlleles = Arrays.asList(
+                new double[]{80,240},
+                new double[]{1,10000},
+                new double[]{0,500},
+                new double[]{5140,20480},
+                new double[]{5000,800,200},
+                new double[]{6,3,1000},
+                new double[]{100,400,300,800},
+                new double[]{8000,100,20,80,2},
+                new double[]{90,20000,400,20,4,1280,720,1}
+        );
+
+        Assert.assertTrue(! Double.isInfinite(MathUtils.log10Gamma(1e-3)) && ! Double.isNaN(MathUtils.log10Gamma(1e-3)));
+
+        int[] numAlleleSampled = new int[]{2,5,10,20,25};
+        for ( double[] alleles : testAlleles ) {
+            for ( int count : numAlleleSampled ) {
+                // test that everything sums to one. Generate all multinomial draws
+                List<Double> likelihoods = new ArrayList<>(100000);
+                NextCounts generator = new NextCounts(alleles.length,count);
+                double maxLog = Double.MIN_VALUE;
+                //List<String> countLog = new ArrayList<String>(200);
+                while ( generator.hasNext() ) {
+                    int[] thisCount = generator.next();
+                    //countLog.add(Arrays.toString(thisCount));
+                    Double likelihood = MathUtils.dirichletMultinomial(addEpsilon(alleles),thisCount);
+                    Assert.assertTrue(! Double.isNaN(likelihood) && ! Double.isInfinite(likelihood),
+                            String.format("Likelihood for counts %s and nAlleles %d was %s",
+                                    Arrays.toString(thisCount),alleles.length,Double.toString(likelihood)));
+                    if ( likelihood > maxLog )
+                        maxLog = likelihood;
+                    likelihoods.add(likelihood);
+                }
+                //System.out.printf("%d likelihoods and max is (probability) %e\n",likelihoods.size(),Math.pow(10,maxLog));
+                Assert.assertEquals(MathUtils.sumLog10(unwrap(likelihoods)),1.0,1e-7,
+                        String.format("Counts %d and alleles %d have nLikelihoods %d. \n Counts: %s",
+                                count,alleles.length,likelihoods.size(), "NODEBUG"/*,countLog*/));
+            }
+        }
+    }
+}
diff --git a/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/utils/MedianUnitTest.java b/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/utils/MedianUnitTest.java
new file mode 100644
index 0000000..21f3d89
--- /dev/null
+++ b/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/utils/MedianUnitTest.java
@@ -0,0 +1,115 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.utils;
+
+
+// the imports for unit testing.
+
+
+import org.broadinstitute.gatk.utils.BaseTest;
+import org.testng.Assert;
+import org.testng.annotations.DataProvider;
+import org.testng.annotations.Test;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+
+public class MedianUnitTest extends BaseTest {
+
+    // --------------------------------------------------------------------------------
+    //
+    // Provider
+    //
+    // --------------------------------------------------------------------------------
+
+    private class MedianTestProvider extends TestDataProvider {
+        final List<Integer> values = new ArrayList<Integer>();
+        final int cap;
+        final Integer expected;
+
+        public MedianTestProvider(int expected, int cap, Integer ... values) {
+            super(MedianTestProvider.class);
+            this.expected = expected;
+            this.cap = cap;
+            this.values.addAll(Arrays.asList(values));
+            this.name = String.format("values=%s expected=%d cap=%d", this.values, expected, cap);
+        }
+    }
+
+    @DataProvider(name = "MedianTestProvider")
+    public Object[][] makeMedianTestProvider() {
+        new MedianTestProvider(1, 1000, 0, 1, 2);
+        new MedianTestProvider(1, 1000, 1, 0, 1, 2);
+        new MedianTestProvider(1, 1000, 0, 1, 2, 3);
+        new MedianTestProvider(2, 1000, 0, 1, 2, 3, 4);
+        new MedianTestProvider(2, 1000, 4, 1, 2, 3, 0);
+        new MedianTestProvider(1, 1000, 1);
+        new MedianTestProvider(2, 1000, 2);
+        new MedianTestProvider(1, 1000, 1, 2);
+
+        new MedianTestProvider(1, 3, 1);
+        new MedianTestProvider(1, 3, 1, 2);
+        new MedianTestProvider(2, 3, 1, 2, 3);
+        new MedianTestProvider(2, 3, 1, 2, 3, 4);
+        new MedianTestProvider(2, 3, 1, 2, 3, 4, 5);
+
+        new MedianTestProvider(1, 3, 1);
+        new MedianTestProvider(1, 3, 1, 2);
+        new MedianTestProvider(2, 3, 3, 2, 1);
+        new MedianTestProvider(3, 3, 4, 3, 2, 1);
+        new MedianTestProvider(4, 3, 5, 4, 3, 2, 1);
+
+        return MedianTestProvider.getTests(MedianTestProvider.class);
+    }
+
+    @Test(dataProvider = "MedianTestProvider")
+    public void testBasicLikelihoods(MedianTestProvider cfg) {
+        final Median<Integer> median = new Median<Integer>(cfg.cap);
+
+        int nAdded = 0;
+        for ( final int value : cfg.values )
+            if ( median.add(value) )
+                nAdded++;
+
+        Assert.assertEquals(nAdded, median.size());
+
+        Assert.assertEquals(cfg.values.isEmpty(), median.isEmpty());
+        Assert.assertEquals(cfg.values.size() >= cfg.cap, median.isFull());
+        Assert.assertEquals(median.getMedian(), cfg.expected, cfg.toString());
+    }
+
+    @Test(expectedExceptions = IllegalStateException.class)
+    public void testEmptyMedian() {
+        final Median<Integer> median = new Median<Integer>();
+        Assert.assertTrue(median.isEmpty());
+        final Integer d = 100;
+        Assert.assertEquals(median.getMedian(d), d);
+        median.getMedian();
+    }
+
+}
\ No newline at end of file
diff --git a/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/utils/NGSPlatformUnitTest.java b/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/utils/NGSPlatformUnitTest.java
new file mode 100644
index 0000000..b247f59
--- /dev/null
+++ b/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/utils/NGSPlatformUnitTest.java
@@ -0,0 +1,167 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.utils;
+
+
+// the imports for unit testing.
+
+
+import htsjdk.samtools.reference.IndexedFastaSequenceFile;
+import htsjdk.samtools.SAMFileHeader;
+import htsjdk.samtools.SAMReadGroupRecord;
+import org.broadinstitute.gatk.utils.BaseTest;
+import org.broadinstitute.gatk.utils.fasta.CachingIndexedFastaSequenceFile;
+import org.broadinstitute.gatk.utils.sam.ArtificialSAMUtils;
+import org.broadinstitute.gatk.utils.sam.GATKSAMRecord;
+import org.testng.Assert;
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.DataProvider;
+import org.testng.annotations.Test;
+
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+public class NGSPlatformUnitTest extends BaseTest {
+    // example genome loc parser for this test, can be deleted if you don't use the reference
+    private GenomeLocParser genomeLocParser;
+
+    // example fasta index file, can be deleted if you don't use the reference
+    private IndexedFastaSequenceFile seq;
+
+    @BeforeClass
+    public void setup() throws FileNotFoundException {
+        // sequence
+        seq = new CachingIndexedFastaSequenceFile(new File(b37KGReference));
+        genomeLocParser = new GenomeLocParser(seq);
+    }
+
+    @DataProvider(name = "TestPrimary")
+    public Object[][] makeTestPrimary() {
+        List<Object[]> tests = new ArrayList<Object[]>();
+
+        for ( final NGSPlatform pl : NGSPlatform.values() ) {
+            tests.add(new Object[]{pl, pl.BAM_PL_NAMES[0]});
+        }
+
+        return tests.toArray(new Object[][]{});
+    }
+
+    @Test(dataProvider = "TestPrimary")
+    public void testPrimary(final NGSPlatform pl, final String expectedPrimaryName) {
+        Assert.assertEquals(pl.getDefaultPlatform(), expectedPrimaryName, "Failed primary test for " + pl);
+    }
+
+    // make sure common names in BAMs are found
+    @DataProvider(name = "TestMappings")
+    public Object[][] makeTestMappings() {
+        List<Object[]> tests = new ArrayList<Object[]>();
+
+        final Map<String, NGSPlatform> expected = new HashMap<String, NGSPlatform>();
+        // VALID VALUES ACCORDING TO SAM SPEC: https://www.google.com/url?sa=t&rct=j&q=&esrc=s&source=web&cd=1&ved=0CC8QFjAA&url=http%3A%2F%2Fsamtools.sourceforge.net%2FSAM1.pdf&ei=Dm8WUbXAEsi10QHYqoDwDQ&usg=AFQjCNFkMtvEi6LeiKgpxQGtHTlqWKw2yw&bvm=bv.42080656,d.dmQ
+        expected.put("CAPILLARY", NGSPlatform.CAPILLARY);
+        expected.put("LS454", NGSPlatform.LS454);
+        expected.put("ILLUMINA", NGSPlatform.ILLUMINA);
+        expected.put("SOLID", NGSPlatform.SOLID);
+        expected.put("HELICOS", NGSPlatform.HELICOS);
+        expected.put("IONTORRENT", NGSPlatform.ION_TORRENT);
+        expected.put("PACBIO", NGSPlatform.PACBIO);
+        // other commonly seen values out in the wild
+        expected.put("SLX", NGSPlatform.ILLUMINA);
+        expected.put("SOLEXA", NGSPlatform.ILLUMINA);
+        expected.put("454", NGSPlatform.LS454);
+        expected.put("COMPLETE", NGSPlatform.COMPLETE_GENOMICS);
+        // unknown platforms should map to unknown
+        expected.put("MARKS_GENOMICS_TECH", NGSPlatform.UNKNOWN);
+        expected.put("RANDOM_PL_VALUE", NGSPlatform.UNKNOWN);
+        // critical -- a null platform maps to unknown
+        expected.put(null, NGSPlatform.UNKNOWN);
+
+        for ( final Map.Entry<String,NGSPlatform> one : expected.entrySet() ) {
+            tests.add(new Object[]{one.getKey(), one.getValue()});
+
+            if ( one.getKey() != null ) {
+                // make sure we're case insensitive
+                tests.add(new Object[]{one.getKey().toLowerCase(), one.getValue()});
+                tests.add(new Object[]{one.getKey().toUpperCase(), one.getValue()});
+
+                // make sure appending GENOMICS works (required for COMPLETE mapping
+                tests.add(new Object[]{one.getKey() + " GENOMICS", one.getValue()});
+                // make sure that random junk works correctly
+                tests.add(new Object[]{one.getKey() + " asdfa", one.getValue()});
+            }
+        }
+
+        return tests.toArray(new Object[][]{});
+    }
+
+    @Test(dataProvider = "TestMappings")
+    public void testMappings(final String plField, final NGSPlatform expected) {
+        Assert.assertEquals(NGSPlatform.fromReadGroupPL(plField), expected, "Failed primary test for " + plField + " mapping to " + expected);
+    }
+
+    @Test(dataProvider = "TestMappings")
+    public void testKnown(final String plField, final NGSPlatform expected) {
+        Assert.assertEquals(NGSPlatform.isKnown(plField), expected != NGSPlatform.UNKNOWN, "Failed isKnown test for " + plField + " mapping to " + expected);
+    }
+
+    /**
+     * A unit test that creates an artificial read for testing some code that uses reads
+     */
+    @Test(dataProvider = "TestMappings")
+    public void testPLFromReadWithRG(final String plField, final NGSPlatform expected) {
+        final SAMFileHeader header = ArtificialSAMUtils.createArtificialSamHeader(seq.getSequenceDictionary());
+        final String rgID = "ID";
+        final SAMReadGroupRecord rg = new SAMReadGroupRecord(rgID);
+        if ( plField != null )
+            rg.setPlatform(plField);
+        header.addReadGroup(rg);
+        final GATKSAMRecord read = ArtificialSAMUtils.createArtificialRead(header, "myRead", 0, 1, 10);
+        read.setAttribute("RG", rgID);
+        Assert.assertEquals(NGSPlatform.fromRead(read), expected);
+    }
+
+    @Test()
+    public void testPLFromReadWithRGButNoPL() {
+        final SAMFileHeader header = ArtificialSAMUtils.createArtificialSamHeader(seq.getSequenceDictionary());
+        final String rgID = "ID";
+        final SAMReadGroupRecord rg = new SAMReadGroupRecord(rgID);
+        header.addReadGroup(rg);
+        final GATKSAMRecord read = ArtificialSAMUtils.createArtificialRead(header, "myRead", 0, 1, 10);
+        read.setAttribute("RG", rgID);
+        Assert.assertEquals(NGSPlatform.fromRead(read), NGSPlatform.UNKNOWN);
+    }
+
+    @Test
+    public void testReadWithoutRG() {
+        final SAMFileHeader header = ArtificialSAMUtils.createArtificialSamHeader(seq.getSequenceDictionary());
+        final GATKSAMRecord read = ArtificialSAMUtils.createArtificialRead(header, "myRead", 0, 1, 10);
+        Assert.assertEquals(NGSPlatform.fromRead(read), NGSPlatform.UNKNOWN);
+    }
+}
\ No newline at end of file
diff --git a/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/utils/PathUtilsUnitTest.java b/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/utils/PathUtilsUnitTest.java
new file mode 100644
index 0000000..00cc0dc
--- /dev/null
+++ b/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/utils/PathUtilsUnitTest.java
@@ -0,0 +1,65 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.utils;
+
+import org.broadinstitute.gatk.utils.BaseTest;
+import org.testng.Assert;
+import org.broadinstitute.gatk.utils.exceptions.ReviewedGATKException;
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.Test;
+
+
+import java.io.File;
+
+public class PathUtilsUnitTest extends BaseTest {
+    @BeforeClass
+    public void init() { }
+
+    /**
+     * Tests that we can successfully refresh a volume
+     */
+    @Test
+    public void testRefreshVolume() {
+        logger.warn("Executing testRefreshVolume");
+
+        Assert.assertTrue(successfullyRefreshedVolume(System.getProperty("java.io.tmpdir")));
+        Assert.assertFalse(successfullyRefreshedVolume("/a/made/up/file.txt"));
+    }
+
+    private boolean successfullyRefreshedVolume(String filename) {
+        boolean result = true;
+
+        try {
+            PathUtils.refreshVolume(new File(filename));
+        } catch (ReviewedGATKException e) {
+            result = false;
+        }
+
+        logger.warn(filename + " is accessible : " + result);
+
+        return result;
+    }
+}
diff --git a/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/utils/QualityUtilsUnitTest.java b/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/utils/QualityUtilsUnitTest.java
new file mode 100644
index 0000000..86b436b
--- /dev/null
+++ b/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/utils/QualityUtilsUnitTest.java
@@ -0,0 +1,189 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.utils;
+
+/**
+ * Created by IntelliJ IDEA.
+ * User: rpoplin
+ * Date: 3/21/12
+ */
+
+import org.broadinstitute.gatk.utils.BaseTest;
+import org.testng.Assert;
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.DataProvider;
+import org.testng.annotations.Test;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Basic unit test for QualityUtils class
+ */
+public class QualityUtilsUnitTest extends BaseTest {
+    final private static double TOLERANCE = 1e-9;
+
+    @BeforeClass
+    public void init() {
+    }
+
+    @DataProvider(name = "QualTest")
+    public Object[][] makeMyDataProvider() {
+        final List<Object[]> tests = new ArrayList<>();
+
+        for ( int qual = 0; qual < 255; qual++ ) {
+            tests.add(new Object[]{(byte)(qual & 0xFF), Math.pow(10.0, ((double)qual)/-10.0)});
+        }
+
+        return tests.toArray(new Object[][]{});
+    }
+
+    /**
+     * Example testng test using MyDataProvider
+     */
+    @Test(dataProvider = "QualTest")
+    public void testMyData(final byte qual, final double errorRate) {
+        final double trueRate = 1 - errorRate;
+
+        final double actualErrorRate = QualityUtils.qualToErrorProb(qual);
+        Assert.assertEquals(actualErrorRate, errorRate, TOLERANCE);
+        final double actualTrueRate = QualityUtils.qualToProb(qual);
+        Assert.assertEquals(actualTrueRate, trueRate, TOLERANCE);
+
+        // log10 tests
+        final double actualLog10ErrorRate = QualityUtils.qualToErrorProbLog10(qual);
+        Assert.assertEquals(actualLog10ErrorRate, Math.log10(errorRate), TOLERANCE);
+        final double actualLog10TrueRate = QualityUtils.qualToProbLog10(qual);
+        Assert.assertEquals(actualLog10TrueRate, Math.log10(trueRate), TOLERANCE);
+
+        // test that we can convert our error rates to quals, accounting for boundaries
+        final int expectedQual = Math.max(Math.min(qual & 0xFF, QualityUtils.MAX_SAM_QUAL_SCORE), 1);
+        final byte actualQual = QualityUtils.trueProbToQual(trueRate);
+        Assert.assertEquals(actualQual, expectedQual & 0xFF);
+        final byte actualQualFromErrorRate = QualityUtils.errorProbToQual(errorRate);
+        Assert.assertEquals(actualQualFromErrorRate, expectedQual & 0xFF);
+
+        for ( int maxQual = 10; maxQual < QualityUtils.MAX_SAM_QUAL_SCORE; maxQual++ ) {
+            final byte maxAsByte = (byte)(maxQual & 0xFF);
+            final byte expectedQual2 = (byte)(Math.max(Math.min(qual & 0xFF, maxQual), 1) & 0xFF);
+            final byte actualQual2 = QualityUtils.trueProbToQual(trueRate, maxAsByte);
+            Assert.assertEquals(actualQual2, expectedQual2, "Failed with max " + maxQual);
+            final byte actualQualFromErrorRate2 = QualityUtils.errorProbToQual(errorRate, maxAsByte);
+            Assert.assertEquals(actualQualFromErrorRate2, expectedQual2, "Failed with max " + maxQual);
+
+            // test the integer routines
+            final byte actualQualInt2 = QualityUtils.trueProbToQual(trueRate, maxQual);
+            Assert.assertEquals(actualQualInt2, expectedQual2, "Failed with max " + maxQual);
+            final byte actualQualFromErrorRateInt2 = QualityUtils.errorProbToQual(errorRate, maxQual);
+            Assert.assertEquals(actualQualFromErrorRateInt2, expectedQual2, "Failed with max " + maxQual);
+        }
+    }
+
+    @Test
+    public void testTrueProbWithMinDouble() {
+        final byte actual = QualityUtils.trueProbToQual(Double.MIN_VALUE);
+        Assert.assertEquals(actual, 1, "Failed to convert true prob of min double to 1 qual");
+    }
+
+    @Test
+    public void testTrueProbWithVerySmallValue() {
+        final byte actual = QualityUtils.trueProbToQual(1.7857786272673852E-19);
+        Assert.assertEquals(actual, 1, "Failed to convert true prob of very small value 1.7857786272673852E-19 to 1 qual");
+    }
+
+    @Test
+    public void testQualCaches() {
+        Assert.assertEquals(QualityUtils.qualToErrorProb((byte) 20), 0.01, 1e-6);
+        Assert.assertEquals(QualityUtils.qualToErrorProbLog10((byte) 20), -2.0, 1e-6);
+        Assert.assertEquals(QualityUtils.qualToProb((byte) 20), 0.99, 1e-6);
+        Assert.assertEquals(QualityUtils.qualToProbLog10((byte) 20), -0.0043648054, 1e-6);
+
+        Assert.assertEquals(QualityUtils.qualToErrorProb((byte) 30), 0.001, 1e-6);
+        Assert.assertEquals(QualityUtils.qualToErrorProbLog10((byte) 30), -3.0, 1e-6);
+        Assert.assertEquals(QualityUtils.qualToProb((byte) 30), 0.999, 1e-6);
+        Assert.assertEquals(QualityUtils.qualToProbLog10((byte) 30), -0.000434511774, 1e-6);
+
+        Assert.assertEquals(QualityUtils.qualToErrorProb((byte) 40), 0.0001, 1e-6);
+        Assert.assertEquals(QualityUtils.qualToErrorProbLog10((byte) 40), -4.0, 1e-6);
+        Assert.assertEquals(QualityUtils.qualToProb((byte) 40), 0.9999, 1e-6);
+        Assert.assertEquals(QualityUtils.qualToProbLog10((byte) 40), -4.34316198e-5, 1e-6);
+    }
+
+    @Test()
+    public void testBoundingDefault() {
+        for ( int qual = 0; qual < 1000; qual++ ) {
+            final byte expected = (byte)Math.max(Math.min(qual, QualityUtils.MAX_SAM_QUAL_SCORE), 1);
+            Assert.assertEquals(QualityUtils.boundQual(qual), expected);
+        }
+    }
+
+    @Test()
+    public void testBoundingWithMax() {
+        for ( int max = 10; max < 255; max += 50 ) {
+            for ( int qual = 0; qual < 1000; qual++ ) {
+                final int expected = Math.max(Math.min(qual, max), 1);
+                Assert.assertEquals(QualityUtils.boundQual(qual, (byte)(max & 0xFF)) & 0xFF, expected & 0xFF, "qual " + qual + " max " + max);
+            }
+        }
+    }
+
+    @DataProvider(name = "PhredScaleDoubleOps")
+    public Object[][] makePhredDoubleTest() {
+        final List<Object[]> tests = new ArrayList<>();
+
+        tests.add(new Object[]{0.0, -10 * Math.log10(Double.MIN_VALUE)});
+        tests.add(new Object[]{1.0, 0.0});
+        for ( int pow = 1; pow < 20; pow++ ) {
+            tests.add(new Object[]{Math.pow(10.0, -1.0 * pow), pow * 10});
+            tests.add(new Object[]{Math.pow(10.0, -1.5 * pow), pow * 15});
+        }
+
+        return tests.toArray(new Object[][]{});
+    }
+
+    @Test()
+    public void testQualToErrorProbDouble() {
+        for ( double qual = 3.0; qual < 255.0; qual += 0.1 ) {
+            final double expected = Math.pow(10.0, qual / -10.0);
+            Assert.assertEquals(QualityUtils.qualToErrorProb(qual), expected, TOLERANCE, "failed qual->error prob for double qual " + qual);
+        }
+    }
+
+
+    @Test(dataProvider = "PhredScaleDoubleOps")
+    public void testPhredScaleDoubleOps(final double errorRate, final double expectedPhredScaled) {
+        final double actualError = QualityUtils.phredScaleErrorRate(errorRate);
+        Assert.assertEquals(actualError, expectedPhredScaled, TOLERANCE);
+        final double trueRate = 1 - errorRate;
+        final double actualTrue = QualityUtils.phredScaleCorrectRate(trueRate);
+        if ( trueRate == 1.0 ) {
+            Assert.assertEquals(actualTrue, QualityUtils.MIN_PHRED_SCALED_QUAL);
+        } else {
+            final double tol = errorRate < 1e-10 ? 10.0 : 1e-3;
+            Assert.assertEquals(actualTrue, expectedPhredScaled, tol);
+        }
+    }
+}
\ No newline at end of file
diff --git a/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/utils/R/RScriptExecutorUnitTest.java b/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/utils/R/RScriptExecutorUnitTest.java
new file mode 100644
index 0000000..7a56b99
--- /dev/null
+++ b/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/utils/R/RScriptExecutorUnitTest.java
@@ -0,0 +1,110 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.utils.R;
+
+import org.apache.commons.io.FileUtils;
+import org.broadinstitute.gatk.utils.BaseTest;
+import org.broadinstitute.gatk.utils.io.IOUtils;
+import org.testng.Assert;
+import org.testng.annotations.Test;
+
+import java.io.File;
+
+/**
+ * Basic unit test for RScriptExecutor in reduced reads
+ */
+public class RScriptExecutorUnitTest extends BaseTest {
+
+    private static final String HELLO_WORLD_SCRIPT = "print('hello, world')";
+    private static final String GSALIB_LOADED_SCRIPT = "if (!'package:gsalib' %in% search()) stop('gsalib not loaded')";
+
+    @Test
+    public void testRscriptExists() {
+        Assert.assertTrue(RScriptExecutor.RSCRIPT_EXISTS, "Rscript not found in environment ${PATH}");
+    }
+
+    @Test(dependsOnMethods = "testRscriptExists")
+    public void testExistingScript() {
+        File script = writeScript(HELLO_WORLD_SCRIPT);
+        try {
+            RScriptExecutor executor = new RScriptExecutor();
+            executor.addScript(script);
+            executor.setExceptOnError(true);
+            Assert.assertTrue(executor.exec(), "Exec failed");
+        } finally {
+            FileUtils.deleteQuietly(script);
+        }
+    }
+
+    @Test(dependsOnMethods = "testRscriptExists", expectedExceptions = RScriptExecutorException.class)
+    public void testNonExistantScriptException() {
+        RScriptExecutor executor = new RScriptExecutor();
+        executor.setExceptOnError(true);
+        executor.addScript(new File("does_not_exists.R"));
+        executor.exec();
+    }
+
+    @Test(dependsOnMethods = "testRscriptExists")
+    public void testNonExistantScriptNoException() {
+        logger.warn("Testing that warning is printed an no exception thrown for missing script.");
+        RScriptExecutor executor = new RScriptExecutor();
+        executor.setExceptOnError(false);
+        executor.addScript(new File("does_not_exists.R"));
+        Assert.assertFalse(executor.exec(), "Exec should have returned false when the job failed");
+    }
+
+    @Test(dependsOnMethods = "testRscriptExists")
+    public void testLibrary() {
+        File script = writeScript(GSALIB_LOADED_SCRIPT);
+        try {
+            RScriptExecutor executor = new RScriptExecutor();
+            executor.addScript(script);
+            executor.addLibrary(RScriptLibrary.GSALIB);
+            executor.setExceptOnError(true);
+            Assert.assertTrue(executor.exec(), "Exec failed");
+        } finally {
+            FileUtils.deleteQuietly(script);
+        }
+    }
+
+    @Test(dependsOnMethods = "testRscriptExists", expectedExceptions = RScriptExecutorException.class)
+    public void testLibraryMissing() {
+        File script = writeScript(GSALIB_LOADED_SCRIPT);
+        try {
+            RScriptExecutor executor = new RScriptExecutor();
+            executor.addScript(script);
+            // GSALIB is not added nor imported in the script
+            executor.setExceptOnError(true);
+            executor.exec();
+        } finally {
+            FileUtils.deleteQuietly(script);
+        }
+    }
+
+    private File writeScript(String content) {
+        return IOUtils.writeTempFile(content, "myTestScript", ".R");
+    }
+}
diff --git a/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/utils/R/RScriptLibraryUnitTest.java b/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/utils/R/RScriptLibraryUnitTest.java
new file mode 100644
index 0000000..b89686c
--- /dev/null
+++ b/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/utils/R/RScriptLibraryUnitTest.java
@@ -0,0 +1,47 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.utils.R;
+
+import org.apache.commons.io.FileUtils;
+import org.testng.Assert;
+import org.testng.annotations.Test;
+
+import java.io.File;
+
+public class RScriptLibraryUnitTest {
+    @Test
+    public void testProperties() {
+        Assert.assertEquals(RScriptLibrary.GSALIB.getLibraryName(), "gsalib");
+        Assert.assertEquals(RScriptLibrary.GSALIB.getResourcePath(), "gsalib.tar.gz");
+    }
+
+    @Test
+    public void testWriteTemp() {
+        File file = RScriptLibrary.GSALIB.writeTemp();
+        Assert.assertTrue(file.exists(), "R library was not written to temp file: " + file);
+        FileUtils.deleteQuietly(file);
+    }
+}
diff --git a/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/utils/R/RUtilsUnitTest.java b/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/utils/R/RUtilsUnitTest.java
new file mode 100644
index 0000000..51ab6f7
--- /dev/null
+++ b/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/utils/R/RUtilsUnitTest.java
@@ -0,0 +1,65 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.utils.R;
+
+import org.testng.Assert;
+import org.testng.annotations.DataProvider;
+import org.testng.annotations.Test;
+
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+
+public class RUtilsUnitTest {
+    @DataProvider(name = "stringLists")
+    public Object[][] getStringLists() {
+        return new Object[][] {
+                new Object[] { null, "NA" },
+                new Object[] { Collections.EMPTY_LIST, "c()" },
+                new Object[] { Arrays.asList("1", "2", "3"), "c('1','2','3')" }
+        };
+    }
+
+    @Test(dataProvider = "stringLists")
+    public void testToStringList(List<? extends CharSequence> actual, String expected) {
+        Assert.assertEquals(RUtils.toStringList(actual), expected);
+    }
+
+    @DataProvider(name = "numberLists")
+    public Object[][] getNumberLists() {
+        return new Object[][] {
+                new Object[] { null, "NA" },
+                new Object[] { Collections.EMPTY_LIST, "c()" },
+                new Object[] { Arrays.asList(1, 2, 3), "c(1,2,3)" },
+                new Object[] { Arrays.asList(1D, 2D, 3D), "c(1.0,2.0,3.0)" }
+        };
+    }
+
+    @Test(dataProvider = "numberLists")
+    public void testToNumberList(List<? extends Number> actual, String expected) {
+        Assert.assertEquals(RUtils.toNumberList(actual), expected);
+    }
+}
diff --git a/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/utils/SampleUtilsUnitTest.java b/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/utils/SampleUtilsUnitTest.java
new file mode 100644
index 0000000..d11c4bf
--- /dev/null
+++ b/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/utils/SampleUtilsUnitTest.java
@@ -0,0 +1,52 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.utils;
+
+import org.apache.commons.io.FileUtils;
+import org.broadinstitute.gatk.utils.exceptions.UserException;
+import org.broadinstitute.gatk.utils.io.IOUtils;
+import org.testng.Assert;
+import org.broadinstitute.gatk.utils.BaseTest;
+import org.testng.annotations.DataProvider;
+import org.testng.annotations.Test;
+
+import java.io.File;
+import java.util.*;
+
+/**
+ * Testing framework for sample utilities class.
+ *
+ * @author gauthier
+ */
+
+public class SampleUtilsUnitTest extends BaseTest {
+    @Test(expectedExceptions=UserException.class)
+    public void testBadSampleFiles() throws Exception {
+        Set<File> sampleFiles = new HashSet<File>(0);
+        sampleFiles.add(new File("fileNotHere.samples"));
+        Collection<String> samplesFromFile = SampleUtils.getSamplesFromFiles(sampleFiles);
+    }
+}
diff --git a/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/utils/SequenceDictionaryUtilsUnitTest.java b/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/utils/SequenceDictionaryUtilsUnitTest.java
new file mode 100644
index 0000000..6ccb0c9
--- /dev/null
+++ b/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/utils/SequenceDictionaryUtilsUnitTest.java
@@ -0,0 +1,241 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.utils;
+
+import htsjdk.samtools.SAMSequenceDictionary;
+import htsjdk.samtools.SAMSequenceRecord;
+import org.apache.log4j.Logger;
+import org.broadinstitute.gatk.utils.BaseTest;
+import org.broadinstitute.gatk.engine.arguments.ValidationExclusion;
+import org.broadinstitute.gatk.utils.exceptions.UserException;
+import org.testng.annotations.DataProvider;
+import org.testng.annotations.Test;
+import org.testng.Assert;
+
+import static org.broadinstitute.gatk.utils.SequenceDictionaryUtils.*;
+import static org.broadinstitute.gatk.utils.SequenceDictionaryUtils.SequenceDictionaryCompatibility.*;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+public class SequenceDictionaryUtilsUnitTest extends BaseTest {
+
+    private static Logger logger = Logger.getLogger(SequenceDictionaryUtilsUnitTest.class);
+
+
+    @DataProvider( name = "SequenceDictionaryDataProvider" )
+    public Object[][] generateSequenceDictionaryTestData() {
+        final SAMSequenceRecord CHRM_HG19 = new SAMSequenceRecord("chrM", 16571);
+        final SAMSequenceRecord CHR_NONSTANDARD1 = new SAMSequenceRecord("NonStandard1", 8675309);
+        final SAMSequenceRecord CHR_NONSTANDARD2 = new SAMSequenceRecord("NonStandard2", 8675308);
+
+        final Class NO_COMMON_CONTIGS_EXCEPTION = UserException.IncompatibleSequenceDictionaries.class;
+        final Class UNEQUAL_COMMON_CONTIGS_EXCEPTION = UserException.IncompatibleSequenceDictionaries.class;
+        final Class NON_CANONICAL_HUMAN_ORDER_EXCEPTION = UserException.LexicographicallySortedSequenceDictionary.class;
+        final Class OUT_OF_ORDER_EXCEPTION = UserException.IncompatibleSequenceDictionaries.class;
+        final Class DIFFERENT_INDICES_EXCEPTION = UserException.IncompatibleSequenceDictionaries.class;
+
+        final List<SAMSequenceRecord> hg19Sequences = Arrays.asList(CHRM_HG19, CHR1_HG19, CHR2_HG19, CHR10_HG19);
+        final GenomeLocParser hg19GenomeLocParser = new GenomeLocParser(new SAMSequenceDictionary(hg19Sequences));
+        final List<GenomeLoc> hg19AllContigsIntervals = Arrays.asList(hg19GenomeLocParser.createGenomeLoc("chrM", 0, 1),
+                                                                      hg19GenomeLocParser.createGenomeLoc("chr1", 0, 1),
+                                                                      hg19GenomeLocParser.createGenomeLoc("chr2", 0, 1),
+                                                                      hg19GenomeLocParser.createGenomeLoc("chr10", 0, 1));
+        final List<GenomeLoc> hg19PartialContigsIntervals = Arrays.asList(hg19GenomeLocParser.createGenomeLoc("chrM", 0, 1),
+                                                                          hg19GenomeLocParser.createGenomeLoc("chr1", 0, 1));
+        final GenomeLocSortedSet hg19AllContigsIntervalSet = new GenomeLocSortedSet(hg19GenomeLocParser, hg19AllContigsIntervals);
+        final GenomeLocSortedSet hg19PartialContigsIntervalSet = new GenomeLocSortedSet(hg19GenomeLocParser, hg19PartialContigsIntervals);
+
+        return new Object[][]  {
+            // Identical dictionaries:
+            { Arrays.asList(CHR1_HG19),                        Arrays.asList(CHR1_HG19),                        null, IDENTICAL, null, false, null },
+            { Arrays.asList(CHR1_HG19, CHR2_HG19, CHR10_HG19), Arrays.asList(CHR1_HG19, CHR2_HG19, CHR10_HG19), null, IDENTICAL, null, false, null },
+            { Arrays.asList(CHR1_B37),                         Arrays.asList(CHR1_B37),                         null, IDENTICAL, null, false, null },
+            { Arrays.asList(CHR1_B37, CHR2_B37, CHR10_B37),    Arrays.asList(CHR1_B37, CHR2_B37, CHR10_B37),    null, IDENTICAL, null, false, null },
+
+            // Dictionaries with a common subset:
+            { Arrays.asList(CHR1_HG19),                                          Arrays.asList(CHR1_HG19, CHR_NONSTANDARD1),                                   null, COMMON_SUBSET, null, false, null },
+            { Arrays.asList(CHR1_HG19, CHR_NONSTANDARD1),                        Arrays.asList(CHR1_HG19, CHR_NONSTANDARD2),                                   null, COMMON_SUBSET, null, false, null },
+            { Arrays.asList(CHR_NONSTANDARD1, CHR1_HG19),                        Arrays.asList(CHR_NONSTANDARD2, CHR1_HG19),                                   null, COMMON_SUBSET, null, false, null },
+            { Arrays.asList(CHR_NONSTANDARD1, CHR1_HG19),                        Arrays.asList(CHR_NONSTANDARD2, CHR1_HG19, CHRM_HG19),                        null, COMMON_SUBSET, null, false, null },
+            { Arrays.asList(CHR1_HG19, CHR2_HG19, CHR10_HG19, CHR_NONSTANDARD1), Arrays.asList(CHR1_HG19, CHR2_HG19, CHR10_HG19, CHR_NONSTANDARD2),            null, COMMON_SUBSET, null, false, null },
+            { Arrays.asList(CHR1_HG19, CHR2_HG19, CHR10_HG19, CHR_NONSTANDARD1), Arrays.asList(CHR1_HG19, CHR2_HG19, CHR10_HG19),                              null, COMMON_SUBSET, null, false, null },
+            { Arrays.asList(CHR1_HG19, CHR2_HG19, CHR10_HG19),                   Arrays.asList(CHR1_HG19, CHR2_HG19, CHR10_HG19, CHR_NONSTANDARD1),            null, COMMON_SUBSET, null, false, null },
+            { Arrays.asList(CHR_NONSTANDARD1, CHR1_HG19, CHR2_HG19, CHR10_HG19), Arrays.asList(CHR_NONSTANDARD2, CHR1_HG19, CHR2_HG19, CHR10_HG19),            null, COMMON_SUBSET, null, false, null },
+            { Arrays.asList(CHR_NONSTANDARD1, CHR1_HG19, CHR2_HG19, CHR10_HG19), Arrays.asList(CHR_NONSTANDARD2, CHR1_HG19, CHR2_HG19, CHR10_HG19, CHRM_HG19), null, COMMON_SUBSET, null, false, null },
+            { Arrays.asList(CHR1_B37, CHR2_B37, CHR10_B37, CHR_NONSTANDARD1),    Arrays.asList(CHR1_B37, CHR2_B37, CHR10_B37, CHR_NONSTANDARD2),               null, COMMON_SUBSET, null, false, null },
+            { Arrays.asList(CHR1_HG19, CHR2_HG19),                               Arrays.asList(CHR1_HG19, CHR2_HG19, CHR10_HG19),                              null, COMMON_SUBSET, null, false, null },
+
+            // Dictionaries with no common contigs:
+            { Arrays.asList(CHR1_HG19),                        Arrays.asList(CHR2_HG19),                     null, NO_COMMON_CONTIGS, NO_COMMON_CONTIGS_EXCEPTION, false, null },
+            { Arrays.asList(CHR1_HG19),                        Arrays.asList(CHR1_B37),                      null, NO_COMMON_CONTIGS, NO_COMMON_CONTIGS_EXCEPTION, false, null },
+            { Arrays.asList(CHR1_HG19, CHR2_HG19, CHR10_HG19), Arrays.asList(CHR1_B37, CHR2_B37, CHR10_B37), null, NO_COMMON_CONTIGS, NO_COMMON_CONTIGS_EXCEPTION, false, null },
+            { Arrays.asList(CHR1_HG19, CHR2_HG19),             Arrays.asList(CHR1_B37, CHR2_B37, CHR10_B37), null, NO_COMMON_CONTIGS, NO_COMMON_CONTIGS_EXCEPTION, false, null },
+
+            // Dictionaries with unequal common contigs:
+            { Arrays.asList(CHR1_HG19),                                          Arrays.asList(CHR1_HG18),                                          null, UNEQUAL_COMMON_CONTIGS, UNEQUAL_COMMON_CONTIGS_EXCEPTION, false, null },
+            { Arrays.asList(CHR1_B36),                                           Arrays.asList(CHR1_B37),                                           null, UNEQUAL_COMMON_CONTIGS, UNEQUAL_COMMON_CONTIGS_EXCEPTION, false, null },
+            { Arrays.asList(CHR1_HG19, CHR2_HG19, CHR10_HG19),                   Arrays.asList(CHR1_HG18, CHR2_HG18, CHR10_HG18),                   null, UNEQUAL_COMMON_CONTIGS, UNEQUAL_COMMON_CONTIGS_EXCEPTION, false, null },
+            { Arrays.asList(CHR1_B37, CHR2_B37, CHR10_B37),                      Arrays.asList(CHR1_B36, CHR2_B36, CHR10_B36),                      null, UNEQUAL_COMMON_CONTIGS, UNEQUAL_COMMON_CONTIGS_EXCEPTION, false, null },
+            { Arrays.asList(CHR1_HG19, CHR2_HG19, CHR10_HG19, CHR_NONSTANDARD1), Arrays.asList(CHR1_HG18, CHR2_HG18, CHR10_HG18, CHR_NONSTANDARD2), null, UNEQUAL_COMMON_CONTIGS, UNEQUAL_COMMON_CONTIGS_EXCEPTION, false, null },
+            { Arrays.asList(CHR_NONSTANDARD1, CHR1_HG19, CHR2_HG19, CHR10_HG19), Arrays.asList(CHR_NONSTANDARD2, CHR1_HG18, CHR2_HG18, CHR10_HG18), null, UNEQUAL_COMMON_CONTIGS, UNEQUAL_COMMON_CONTIGS_EXCEPTION, false, null },
+            { Arrays.asList(CHR1_HG19, CHR2_HG19),                               Arrays.asList(CHR1_HG18, CHR2_HG18, CHR10_HG18),                   null, UNEQUAL_COMMON_CONTIGS, UNEQUAL_COMMON_CONTIGS_EXCEPTION, false, null },
+
+            // One or both dictionaries in non-canonical human order:
+            { Arrays.asList(CHR1_HG19, CHR10_HG19, CHR2_HG19), Arrays.asList(CHR1_HG19, CHR10_HG19, CHR2_HG19), null, NON_CANONICAL_HUMAN_ORDER, NON_CANONICAL_HUMAN_ORDER_EXCEPTION, false, null },
+            { Arrays.asList(CHR1_HG18, CHR10_HG18, CHR2_HG18), Arrays.asList(CHR1_HG18, CHR10_HG18, CHR2_HG18), null, NON_CANONICAL_HUMAN_ORDER, NON_CANONICAL_HUMAN_ORDER_EXCEPTION, false, null },
+            { Arrays.asList(CHR1_HG19, CHR10_HG19, CHR2_HG19), Arrays.asList(CHR1_HG19, CHR2_HG19, CHR10_HG19), null, NON_CANONICAL_HUMAN_ORDER, NON_CANONICAL_HUMAN_ORDER_EXCEPTION, false, null },
+            { Arrays.asList(CHR1_HG19, CHR2_HG19, CHR10_HG19), Arrays.asList(CHR1_HG19, CHR10_HG19, CHR2_HG19), null, NON_CANONICAL_HUMAN_ORDER, NON_CANONICAL_HUMAN_ORDER_EXCEPTION, false, null },
+            { Arrays.asList(CHR1_B37, CHR10_B37, CHR2_B37),    Arrays.asList(CHR1_B37, CHR10_B37, CHR2_B37),    null, NON_CANONICAL_HUMAN_ORDER, NON_CANONICAL_HUMAN_ORDER_EXCEPTION, false, null },
+            { Arrays.asList(CHR1_B36, CHR10_B36, CHR2_B36),    Arrays.asList(CHR1_B36, CHR10_B36, CHR2_B36),    null, NON_CANONICAL_HUMAN_ORDER, NON_CANONICAL_HUMAN_ORDER_EXCEPTION, false, null },
+
+            // Dictionaries with a common subset, but different relative ordering within that subset:
+            { Arrays.asList(CHR1_HG19, CHR2_HG19),            Arrays.asList(CHR2_HG19, CHR1_HG19),                              null, OUT_OF_ORDER, OUT_OF_ORDER_EXCEPTION, false, null },
+            { Arrays.asList(CHRM_HG19, CHR1_HG19, CHR2_HG19), Arrays.asList(CHR2_HG19, CHR1_HG19, CHRM_HG19),                   null, OUT_OF_ORDER, OUT_OF_ORDER_EXCEPTION, false, null },
+            { Arrays.asList(CHRM_HG19, CHR1_HG19, CHR2_HG19), Arrays.asList(CHRM_HG19, CHR2_HG19, CHR1_HG19),                   null, OUT_OF_ORDER, OUT_OF_ORDER_EXCEPTION, false, null },
+            { Arrays.asList(CHRM_HG19, CHR1_HG19, CHR2_HG19), Arrays.asList(CHR2_HG19, CHRM_HG19, CHR1_HG19),                   null, OUT_OF_ORDER, OUT_OF_ORDER_EXCEPTION, false, null },
+            { Arrays.asList(CHR1_B37, CHR2_B37),              Arrays.asList(CHR2_B37, CHR1_B37),                                null, OUT_OF_ORDER, OUT_OF_ORDER_EXCEPTION, false, null },
+
+
+            // Dictionaries with a common subset in the same relative order, but with different indices.
+            // This will only throw an exception during validation if isReadsToReferenceComparison is true,
+            // and there are intervals overlapping the misindexed contigs:
+
+            // These have isReadsToReferenceComparison == true and overlapping intervals, so we expect an exception:
+            { Arrays.asList(CHRM_HG19, CHR1_HG19),                                                 Arrays.asList(CHR1_HG19),                                          null, DIFFERENT_INDICES, DIFFERENT_INDICES_EXCEPTION, true, hg19AllContigsIntervalSet },
+            { Arrays.asList(CHR1_HG19, CHR2_HG19),                                                 Arrays.asList(CHRM_HG19, CHR1_HG19, CHR2_HG19),                    null, DIFFERENT_INDICES, DIFFERENT_INDICES_EXCEPTION, true, hg19AllContigsIntervalSet },
+            { Arrays.asList(CHR1_HG19, CHR2_HG19),                                                 Arrays.asList(CHRM_HG19, CHR1_HG19, CHR2_HG19, CHR_NONSTANDARD1),  null, DIFFERENT_INDICES, DIFFERENT_INDICES_EXCEPTION, true, hg19AllContigsIntervalSet },
+            { Arrays.asList(CHR1_HG19, CHR2_HG19),                                                 Arrays.asList(CHRM_HG19, CHR_NONSTANDARD1, CHR1_HG19, CHR2_HG19),  null, DIFFERENT_INDICES, DIFFERENT_INDICES_EXCEPTION, true, hg19AllContigsIntervalSet },
+            { Arrays.asList(CHR1_HG19, CHR2_HG19, CHR_NONSTANDARD1, CHRM_HG19 ),                   Arrays.asList(CHR1_HG19, CHR2_HG19, CHRM_HG19),                    null, DIFFERENT_INDICES, DIFFERENT_INDICES_EXCEPTION, true, hg19AllContigsIntervalSet },
+            { Arrays.asList(CHR1_HG19, CHR2_HG19, CHR_NONSTANDARD1, CHRM_HG19, CHR_NONSTANDARD2 ), Arrays.asList(CHR1_HG19, CHR2_HG19, CHRM_HG19, CHR_NONSTANDARD2 ), null, DIFFERENT_INDICES, DIFFERENT_INDICES_EXCEPTION, true, hg19AllContigsIntervalSet },
+            { Arrays.asList(CHR1_HG19, CHR_NONSTANDARD1, CHR2_HG19, CHRM_HG19, CHR_NONSTANDARD2 ), Arrays.asList(CHR1_HG19, CHR2_HG19, CHRM_HG19, CHR_NONSTANDARD2 ), null, DIFFERENT_INDICES, DIFFERENT_INDICES_EXCEPTION, true, hg19AllContigsIntervalSet },
+
+            // These have isReadsToReferenceComparison == true but no overlapping intervals, so we don't expect an exception:
+            { Arrays.asList(CHR2_HG19, CHR10_HG19),                              Arrays.asList(CHR10_HG19),                       null, DIFFERENT_INDICES, null, true, hg19PartialContigsIntervalSet },
+            { Arrays.asList(CHR1_HG19, CHR_NONSTANDARD1, CHR2_HG19),             Arrays.asList(CHR1_HG19, CHR2_HG19),             null, DIFFERENT_INDICES, null, true, hg19PartialContigsIntervalSet },
+            { Arrays.asList(CHR1_HG19, CHR_NONSTANDARD1, CHR2_HG19, CHR10_HG19), Arrays.asList(CHR1_HG19, CHR2_HG19, CHR10_HG19), null, DIFFERENT_INDICES, null, true, hg19PartialContigsIntervalSet },
+
+            // These have isReadsToReferenceComparison == false, so we don't expect an exception:
+            { Arrays.asList(CHRM_HG19, CHR1_HG19),                              Arrays.asList(CHR1_HG19),                       null, DIFFERENT_INDICES, null, false, hg19AllContigsIntervalSet },
+            { Arrays.asList(CHR1_HG19, CHR_NONSTANDARD1, CHR2_HG19, CHRM_HG19), Arrays.asList(CHR1_HG19, CHR2_HG19, CHRM_HG19), null, DIFFERENT_INDICES, null, false, hg19AllContigsIntervalSet },
+
+
+            // Tests for validation exclusions. Note that errors resulting from NO_COMMON_CONTIGs cannot be suppressed
+            { Arrays.asList(CHR1_HG19),                        Arrays.asList(CHR2_HG19),                        ValidationExclusion.TYPE.ALLOW_SEQ_DICT_INCOMPATIBILITY, NO_COMMON_CONTIGS,         NO_COMMON_CONTIGS_EXCEPTION, false, null },
+            { Arrays.asList(CHR1_HG19),                        Arrays.asList(CHR2_HG19),                        ValidationExclusion.TYPE.ALL,                            NO_COMMON_CONTIGS,         NO_COMMON_CONTIGS_EXCEPTION, false, null },
+            { Arrays.asList(CHR1_HG19),                        Arrays.asList(CHR1_HG18),                        ValidationExclusion.TYPE.ALLOW_SEQ_DICT_INCOMPATIBILITY, UNEQUAL_COMMON_CONTIGS,    null, false, null },
+            { Arrays.asList(CHR1_HG19),                        Arrays.asList(CHR1_HG18),                        ValidationExclusion.TYPE.ALL,                            UNEQUAL_COMMON_CONTIGS,    null, false, null },
+            { Arrays.asList(CHR1_HG19, CHR10_HG19, CHR2_HG19), Arrays.asList(CHR1_HG19, CHR10_HG19, CHR2_HG19), ValidationExclusion.TYPE.ALLOW_SEQ_DICT_INCOMPATIBILITY, NON_CANONICAL_HUMAN_ORDER, null, false, null },
+            { Arrays.asList(CHR1_HG19, CHR10_HG19, CHR2_HG19), Arrays.asList(CHR1_HG19, CHR10_HG19, CHR2_HG19), ValidationExclusion.TYPE.ALL,                            NON_CANONICAL_HUMAN_ORDER, null, false, null },
+            { Arrays.asList(CHR1_HG19, CHR2_HG19),             Arrays.asList(CHR2_HG19, CHR1_HG19),             ValidationExclusion.TYPE.ALLOW_SEQ_DICT_INCOMPATIBILITY, OUT_OF_ORDER,              null, false, null },
+            { Arrays.asList(CHR1_HG19, CHR2_HG19),             Arrays.asList(CHR2_HG19, CHR1_HG19),             ValidationExclusion.TYPE.ALL,                            OUT_OF_ORDER,              null, false, null },
+            { Arrays.asList(CHRM_HG19, CHR1_HG19),             Arrays.asList(CHR1_HG19),                        ValidationExclusion.TYPE.ALLOW_SEQ_DICT_INCOMPATIBILITY, DIFFERENT_INDICES,         null, true, hg19AllContigsIntervalSet },
+            { Arrays.asList(CHRM_HG19, CHR1_HG19),             Arrays.asList(CHR1_HG19),                        ValidationExclusion.TYPE.ALL,                            DIFFERENT_INDICES,         null, true, hg19AllContigsIntervalSet }
+        };
+    }
+
+    @Test( dataProvider = "SequenceDictionaryDataProvider" )
+    public void testSequenceDictionaryValidation( final List<SAMSequenceRecord> firstDictionaryContigs,
+                                                  final List<SAMSequenceRecord> secondDictionaryContigs,
+                                                  final ValidationExclusion.TYPE validationExclusions,
+                                                  final SequenceDictionaryUtils.SequenceDictionaryCompatibility dictionaryCompatibility,
+                                                  final Class expectedExceptionUponValidation,
+                                                  final boolean isReadsToReferenceComparison,
+                                                  final GenomeLocSortedSet intervals ) {
+
+        final SAMSequenceDictionary firstDictionary = createSequenceDictionary(firstDictionaryContigs);
+        final SAMSequenceDictionary secondDictionary = createSequenceDictionary(secondDictionaryContigs);
+        final String testDescription = String.format("First dictionary: %s  Second dictionary: %s  Validation exclusions: %s",
+                                                     SequenceDictionaryUtils.getDictionaryAsString(firstDictionary),
+                                                     SequenceDictionaryUtils.getDictionaryAsString(secondDictionary),
+                                                     validationExclusions);
+
+        Exception exceptionThrown = null;
+        try {
+            SequenceDictionaryUtils.validateDictionaries(logger,
+                                                         validationExclusions,
+                                                         "firstDictionary",
+                                                         firstDictionary,
+                                                         "secondDictionary",
+                                                         secondDictionary,
+                                                         isReadsToReferenceComparison,
+                                                         intervals);
+        }
+        catch ( Exception e ) {
+            exceptionThrown = e;
+        }
+
+        if ( expectedExceptionUponValidation != null ) {
+            Assert.assertTrue(exceptionThrown != null && expectedExceptionUponValidation.isInstance(exceptionThrown),
+                              String.format("Expected exception %s but saw %s instead. %s",
+                                            expectedExceptionUponValidation.getSimpleName(),
+                                            exceptionThrown == null ? "no exception" : exceptionThrown.getClass().getSimpleName(),
+                                            testDescription));
+        }
+        else {
+            Assert.assertTrue(exceptionThrown == null,
+                              String.format("Expected no exception but saw exception %s instead. %s",
+                                            exceptionThrown != null ? exceptionThrown.getClass().getSimpleName() : "none",
+                                            testDescription));
+        }
+    }
+
+    @Test( dataProvider = "SequenceDictionaryDataProvider" )
+    public void testSequenceDictionaryComparison( final List<SAMSequenceRecord> firstDictionaryContigs,
+                                                  final List<SAMSequenceRecord> secondDictionaryContigs,
+                                                  final ValidationExclusion.TYPE validationExclusions,
+                                                  final SequenceDictionaryUtils.SequenceDictionaryCompatibility dictionaryCompatibility,
+                                                  final Class expectedExceptionUponValidation,
+                                                  final boolean isReadsToReferenceComparison,
+                                                  final GenomeLocSortedSet intervals ) {
+
+        final SAMSequenceDictionary firstDictionary = createSequenceDictionary(firstDictionaryContigs);
+        final SAMSequenceDictionary secondDictionary = createSequenceDictionary(secondDictionaryContigs);
+        final String testDescription = String.format("First dictionary: %s  Second dictionary: %s",
+                                                     SequenceDictionaryUtils.getDictionaryAsString(firstDictionary),
+                                                     SequenceDictionaryUtils.getDictionaryAsString(secondDictionary));
+
+        final SequenceDictionaryUtils.SequenceDictionaryCompatibility reportedCompatibility =
+              SequenceDictionaryUtils.compareDictionaries(firstDictionary, secondDictionary);
+
+        Assert.assertTrue(reportedCompatibility == dictionaryCompatibility,
+                          String.format("Dictionary comparison should have returned %s but instead returned %s. %s",
+                                        dictionaryCompatibility, reportedCompatibility, testDescription));
+    }
+
+    private SAMSequenceDictionary createSequenceDictionary( final List<SAMSequenceRecord> contigs ) {
+        final List<SAMSequenceRecord> clonedContigs = new ArrayList<SAMSequenceRecord>(contigs.size());
+
+        // Clone the individual SAMSequenceRecords to avoid contig-index issues with shared objects
+        // across multiple dictionaries in tests
+        for ( SAMSequenceRecord contig : contigs ) {
+            clonedContigs.add(contig.clone());
+        }
+
+        return new SAMSequenceDictionary(clonedContigs);
+    }
+}
diff --git a/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/utils/SimpleTimerUnitTest.java b/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/utils/SimpleTimerUnitTest.java
new file mode 100644
index 0000000..85aec81
--- /dev/null
+++ b/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/utils/SimpleTimerUnitTest.java
@@ -0,0 +1,179 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.utils;
+
+import org.broadinstitute.gatk.utils.BaseTest;
+import org.testng.Assert;
+import org.testng.annotations.Test;
+
+import java.lang.reflect.Field;
+
+import java.util.Arrays;
+import java.util.List;
+import java.util.concurrent.TimeUnit;
+
+public class SimpleTimerUnitTest extends BaseTest {
+    private final static String NAME = "unit.test.timer";
+
+    @Test
+    public void testSimpleTimer() {
+        SimpleTimer t = new SimpleTimer(NAME);
+        Assert.assertEquals(t.getName(), NAME, "Name is not the provided one");
+        Assert.assertFalse(t.isRunning(), "Initial state of the timer is running");
+        Assert.assertEquals(t.getElapsedTime(), 0.0, "New timer elapsed time should be 0");
+        Assert.assertEquals(t.getElapsedTimeNano(), 0l, "New timer elapsed time nano should be 0");
+
+        t.start();
+        Assert.assertTrue(t.isRunning(), "Started timer isn't running");
+        Assert.assertTrue(t.getElapsedTime() >= 0.0, "Elapsed time should be >= 0");
+        Assert.assertTrue(t.getElapsedTimeNano() >= 0.0, "Elapsed time nano should be >= 0");
+        long n1 = t.getElapsedTimeNano();
+        double t1 = t.getElapsedTime();
+        idleLoop(); // idle loop to wait a tiny bit of time
+        long n2 = t.getElapsedTimeNano();
+        double t2 = t.getElapsedTime();
+        Assert.assertTrue(t2 >= t1, "T2 >= T1 for a running time");
+        Assert.assertTrue(n2 >= n1, "T2 >= T1 nano for a running time");
+
+        t.stop();
+        Assert.assertFalse(t.isRunning(), "Stopped timer still running");
+        long n3 = t.getElapsedTimeNano();
+        double t3 = t.getElapsedTime();
+        idleLoop(); // idle loop to wait a tiny bit of time
+        double t4 = t.getElapsedTime();
+        long n4 = t.getElapsedTimeNano();
+        Assert.assertTrue(t4 == t3, "Elapsed times for two calls of stop timer not the same");
+        Assert.assertTrue(n4 == n3, "Elapsed times for two calls of stop timer not the same");
+
+        t.restart();
+        idleLoop(); // idle loop to wait a tiny bit of time
+        double t5 = t.getElapsedTime();
+        long n5 = t.getElapsedTimeNano();
+        Assert.assertTrue(t.isRunning(), "Restarted timer should be running");
+        idleLoop(); // idle loop to wait a tiny bit of time
+        double t6 = t.getElapsedTime();
+        long n6 = t.getElapsedTimeNano();
+        Assert.assertTrue(t5 >= t4, "Restarted timer elapsed time should be after elapsed time preceding the restart");
+        Assert.assertTrue(t6 >= t5, "Second elapsed time not after the first in restarted timer");
+        Assert.assertTrue(n5 >= n4, "Restarted timer elapsed time nano should be after elapsed time preceding the restart");
+        Assert.assertTrue(n6 >= n5, "Second elapsed time nano not after the first in restarted timer");
+
+        final List<Double> secondTimes = Arrays.asList(t1, t2, t3, t4, t5, t6);
+        final List<Long> nanoTimes     = Arrays.asList(n1, n2, n3, n4, n5, n6);
+        for ( int i = 0; i < nanoTimes.size(); i++ )
+            Assert.assertEquals(
+                    SimpleTimer.nanoToSecondsAsDouble(nanoTimes.get(i)),
+                    secondTimes.get(i), 1e-1, "Nanosecond and second timer disagree");
+    }
+
+    @Test
+    public void testNanoResolution() {
+        SimpleTimer t = new SimpleTimer(NAME);
+
+        // test the nanosecond resolution
+        long n7 = t.currentTimeNano();
+        int sum = 0;
+        for ( int i = 0; i < 100; i++) sum += i;
+        long n8 = t.currentTimeNano();
+        final long delta = n8 - n7;
+        final long oneMilliInNano = TimeUnit.MILLISECONDS.toNanos(1);
+        logger.warn("nanoTime before nano operation " + n7);
+        logger.warn("nanoTime after nano operation of summing 100 ints " + n8 + ", sum = " + sum + " time delta " + delta + " vs. 1 millsecond in nano " + oneMilliInNano);
+        Assert.assertTrue(n8 > n7, "SimpleTimer doesn't appear to have nanoSecond resolution: n8 " + n8 + " <= n7 " + n7);
+        Assert.assertTrue(delta < oneMilliInNano,
+                "SimpleTimer doesn't appear to have nanoSecond resolution: time delta is " + delta + " vs 1 millisecond in nano " + oneMilliInNano);
+    }
+
+    @Test
+    public void testMeaningfulTimes() {
+        SimpleTimer t = new SimpleTimer(NAME);
+
+        t.start();
+        for ( int i = 0; i < 100; i++ ) ;
+        long nano = t.getElapsedTimeNano();
+        double secs = t.getElapsedTime();
+
+        Assert.assertTrue(secs > 0, "Seconds timer doesn't appear to count properly: elapsed time is " + secs);
+        Assert.assertTrue(secs < 0.01, "Fast operation said to take longer than 10 milliseconds: elapsed time in seconds " + secs);
+
+        Assert.assertTrue(nano > 0, "Nanosecond timer doesn't appear to count properly: elapsed time is " + nano);
+        final long maxTimeInMicro = 10000;
+        final long maxTimeInNano = TimeUnit.MICROSECONDS.toNanos(maxTimeInMicro);
+        Assert.assertTrue(nano < maxTimeInNano, "Fast operation said to take longer than " + maxTimeInMicro + " microseconds: elapsed time in nano " + nano + " micro " + TimeUnit.NANOSECONDS.toMicros(nano));
+    }
+
+    @Test
+    public void testCheckpointRestart() throws Exception {
+        SimpleTimer t = new SimpleTimer(NAME);
+        
+        final Field offsetField = t.getClass().getDeclaredField("nanoTimeOffset");
+        offsetField.setAccessible(true);
+        long offset = ((Long) offsetField.get(t)).longValue();
+
+        t.start();
+        idleLoop();
+        // Make it as if clock has jumped into the past
+        offsetField.set(t, offset + TimeUnit.SECONDS.toNanos(10));
+        t.stop();
+        offset = ((Long) offsetField.get(t)).longValue();
+        Assert.assertEquals(t.getElapsedTime(), 0.0, "Time over restart is not zero.");
+
+        t.start();
+        idleLoop();
+        t.stop();
+        offset = ((Long) offsetField.get(t)).longValue();
+        double elapsed = t.getElapsedTime();
+        Assert.assertTrue(elapsed >= 0.0, "Elapsed time is zero.");
+        t.restart();
+        // Make the clock jump again by just a little
+        offsetField.set(t, offset + TimeUnit.SECONDS.toNanos(1));
+        idleLoop();
+        t.stop();
+        offset = ((Long) offsetField.get(t)).longValue();
+        Assert.assertTrue(t.getElapsedTime() > elapsed, "Small clock drift causing reset.");
+        elapsed = t.getElapsedTime();
+        // Now a bigger jump, into the future this time.
+        t.restart();
+        // Make the clock jump again by a lot
+        offsetField.set(t, offset - TimeUnit.SECONDS.toNanos(10));
+        t.stop();
+        Assert.assertEquals(t.getElapsedTime(), elapsed, "Time added over checkpoint/restart.");
+
+        // Test without stopping
+        t.start();
+        offset = ((Long) offsetField.get(t)).longValue();
+        // Make it as if clock has jumped into the past
+        offsetField.set(t, offset + TimeUnit.SECONDS.toNanos(10));       
+        Assert.assertEquals(t.getElapsedTime(), 0.0, "Elapsed time after C/R is not zero.");
+        idleLoop();
+        Assert.assertTrue(t.getElapsedTime() > 0.0, "Elapsed time zero after re-sync.");
+
+    }
+
+    private static void idleLoop() {
+        for ( int i = 0; i < 100000; i++ ) ; // idle loop to wait a tiny bit of time
+    }
+}
\ No newline at end of file
diff --git a/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/utils/TestNGTestTransformer.java b/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/utils/TestNGTestTransformer.java
new file mode 100644
index 0000000..e804e70
--- /dev/null
+++ b/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/utils/TestNGTestTransformer.java
@@ -0,0 +1,62 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.utils;
+
+import org.apache.log4j.Logger;
+import org.testng.IAnnotationTransformer;
+import org.testng.annotations.ITestAnnotation;
+
+import java.lang.reflect.Constructor;
+import java.lang.reflect.Method;
+
+/**
+ * Provide default @Test values for GATK testng tests.
+ *
+ * Currently only sets the maximum runtime to 40 minutes, if it's not been specified.
+ *
+ * See http://beust.com/weblog/2006/10/18/annotation-transformers-in-java/
+ *
+ * @author depristo
+ * @since 10/31/12
+ * @version 0.1
+ */
+public class TestNGTestTransformer implements IAnnotationTransformer {
+    public static final long DEFAULT_TIMEOUT = 1000 * 60 * 40; // 40 minutes max per test
+
+    final static Logger logger = Logger.getLogger(TestNGTestTransformer.class);
+
+    public void transform(ITestAnnotation annotation,
+                          Class testClass,
+                          Constructor testConstructor,
+                          Method testMethod)
+    {
+        if ( annotation.getTimeOut() == 0 ) {
+            logger.warn("test " + (testMethod == null ? "<null>" : testMethod.toString()) + " has no specified timeout, adding default timeout " + DEFAULT_TIMEOUT / 1000 / 60 + " minutes");
+            annotation.setTimeOut(DEFAULT_TIMEOUT);
+        }
+    }
+}
+
diff --git a/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/utils/UtilsUnitTest.java b/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/utils/UtilsUnitTest.java
new file mode 100644
index 0000000..a303f2c
--- /dev/null
+++ b/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/utils/UtilsUnitTest.java
@@ -0,0 +1,363 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.utils;
+
+import org.apache.commons.io.FileUtils;
+import org.broadinstitute.gatk.engine.GenomeAnalysisEngine;
+import org.broadinstitute.gatk.utils.io.IOUtils;
+import org.testng.Assert;
+import org.testng.annotations.DataProvider;
+import org.testng.annotations.Test;
+
+import java.io.File;
+import java.util.*;
+
+/**
+ * Testing framework for general purpose utilities class.
+ *
+ * @author hanna
+ * @version 0.1
+ */
+
+public class UtilsUnitTest extends BaseTest {
+    @Test
+    public void testAppend() {
+        for ( int leftSize : Arrays.asList(0, 1, 2, 3) ) {
+            for ( final int rightSize : Arrays.asList(0, 1, 2) ) {
+                final List<Integer> left = new LinkedList<Integer>();
+                for ( int i = 0; i < leftSize; i++ ) left.add(i);
+                final List<Integer> total = new LinkedList<Integer>();
+                for ( int i = 0; i < leftSize + rightSize; i++ ) total.add(i);
+
+                if ( rightSize == 0 )
+                    Assert.assertEquals(Utils.append(left), total);
+                if ( rightSize == 1 )
+                    Assert.assertEquals(Utils.append(left, leftSize), total);
+                if ( rightSize == 2 )
+                    Assert.assertEquals(Utils.append(left, leftSize, leftSize + 1), total);
+            }
+        }
+
+    }
+
+    @Test
+    public void testDupStringNoChars() {
+        String duped = Utils.dupString('a',0);
+        Assert.assertEquals(duped.length(), 0, "dupString did not produce zero-length string");
+    }
+
+    @Test
+    public void testDupStringOneChar() {
+        String duped = Utils.dupString('b',1);
+        Assert.assertEquals(duped.length(), 1, "dupString did not produce single character string");
+        Assert.assertEquals(duped.charAt(0), 'b', "dupString character was incorrect");
+    }
+
+    @Test
+    public void testXor() {
+        Assert.assertEquals(Utils.xor(false, false), false, "xor F F failed");
+        Assert.assertEquals(Utils.xor(false, true), true, "xor F T failed");
+        Assert.assertEquals(Utils.xor(true, false), true, "xor T F failed");
+        Assert.assertEquals(Utils.xor(true, true), false, "xor T T failed");
+    }
+
+    @Test
+    public void testDupStringMultiChar() {
+        String duped = Utils.dupString('c',5);
+        Assert.assertEquals(duped.length(), 5, "dupString did not produce five character string");
+        Assert.assertEquals(duped,"ccccc","dupString string was incorrect");
+    }
+
+    @Test
+    public void testJoinMap() {
+        Map<String,Integer> map = new LinkedHashMap<String,Integer>();
+        map.put("one",1);
+        map.put("two",2);
+        String joined = Utils.joinMap("-",";",map);
+        Assert.assertTrue("one-1;two-2".equals(joined));
+    }
+
+    @Test
+    public void testJoinMapLargerSet() {
+        Map<String,Integer> map = new LinkedHashMap<String,Integer>();
+        map.put("one",1);
+        map.put("two",2);
+        map.put("three",1);
+        map.put("four",2);
+        map.put("five",1);
+        map.put("six",2);
+        String joined = Utils.joinMap("-",";",map);
+        Assert.assertTrue("one-1;two-2;three-1;four-2;five-1;six-2".equals(joined));
+    }
+
+    @Test
+    public void testConcat() {
+        final String s1 = "A";
+        final String s2 = "CC";
+        final String s3 = "TTT";
+        final String s4 = "GGGG";
+        Assert.assertEquals(new String(Utils.concat()), "");
+        Assert.assertEquals(new String(Utils.concat(s1.getBytes())), s1);
+        Assert.assertEquals(new String(Utils.concat(s1.getBytes(), s2.getBytes())), s1 + s2);
+        Assert.assertEquals(new String(Utils.concat(s1.getBytes(), s2.getBytes(), s3.getBytes())), s1 + s2 + s3);
+        Assert.assertEquals(new String(Utils.concat(s1.getBytes(), s2.getBytes(), s3.getBytes(), s4.getBytes())), s1 + s2 + s3 + s4);
+    }
+
+    @Test
+    public void testEscapeExpressions() {
+        String[] expected, actual;
+
+        expected = new String[] {"one", "two", "three"};
+        actual = Utils.escapeExpressions("one two three");
+        Assert.assertEquals(actual, expected);
+        actual = Utils.escapeExpressions(" one two three");
+        Assert.assertEquals(actual, expected);
+        actual = Utils.escapeExpressions("one two three ");
+        Assert.assertEquals(actual, expected);
+        actual = Utils.escapeExpressions(" one two three ");
+        Assert.assertEquals(actual, expected);
+        actual = Utils.escapeExpressions("  one  two  three  ");
+        Assert.assertEquals(actual, expected);
+
+        expected = new String[] {"one", "two", "three four", "five", "six"};
+        actual = Utils.escapeExpressions("one two 'three four' five six");
+        Assert.assertEquals(actual, expected);
+        actual = Utils.escapeExpressions(" one two 'three four' five six");
+        Assert.assertEquals(actual, expected);
+        actual = Utils.escapeExpressions("one two 'three four' five six ");
+        Assert.assertEquals(actual, expected);
+        actual = Utils.escapeExpressions(" one two 'three four' five six ");
+        Assert.assertEquals(actual, expected);
+        actual = Utils.escapeExpressions("  one  two  'three four'  five  six  ");
+        Assert.assertEquals(actual, expected);
+
+        expected = new String[] {"one two", "three", "four"};
+        actual = Utils.escapeExpressions("'one two' three four");
+        Assert.assertEquals(actual, expected);
+        actual = Utils.escapeExpressions(" 'one two' three four");
+        Assert.assertEquals(actual, expected);
+        actual = Utils.escapeExpressions("'one two' three four ");
+        Assert.assertEquals(actual, expected);
+        actual = Utils.escapeExpressions(" 'one two' three four ");
+        Assert.assertEquals(actual, expected);
+        actual = Utils.escapeExpressions("  'one two'  three  four  ");
+        Assert.assertEquals(actual, expected);
+
+        expected = new String[] {"one", "two", "three four"};
+        actual = Utils.escapeExpressions("one two 'three four'");
+        Assert.assertEquals(actual, expected);
+        actual = Utils.escapeExpressions(" one two 'three four'");
+        Assert.assertEquals(actual, expected);
+        actual = Utils.escapeExpressions("one two 'three four' ");
+        Assert.assertEquals(actual, expected);
+        actual = Utils.escapeExpressions(" one two 'three four' ");
+        Assert.assertEquals(actual, expected);
+        actual = Utils.escapeExpressions("  one  two  'three four'  ");
+        Assert.assertEquals(actual, expected);
+    }
+
+    @Test(dataProvider = "asIntegerListData")
+    public void testAsIntegerList(final int[] values) {
+        if (values == null) {
+            try {
+                Utils.asList((int[]) null);
+                Assert.fail("Should have thrown an exception");
+            } catch (final IllegalArgumentException ex) {
+                // good.
+            }
+        } else {
+            final Random rdn = GenomeAnalysisEngine.getRandomGenerator();
+            final int[] valuesClone = values.clone();
+            final List<Integer> list = Utils.asList(valuesClone);
+            Assert.assertNotNull(list);
+            Assert.assertEquals(list.size(),values.length);
+            for (int i = 0; i < values.length; i++)
+                Assert.assertEquals((int) list.get(i),values[i]);
+            for (int i = 0; i < values.length; i++)
+                valuesClone[rdn.nextInt(values.length)] = rdn.nextInt(1000);
+            for (int i = 0; i < values.length; i++)
+                Assert.assertEquals((int) list.get(i),valuesClone[i]);
+        }
+    }
+
+    @Test(dataProvider = "asDoubleListData")
+    public void testAsDoubleList(final double[] values) {
+        if (values == null) {
+            try {
+                Utils.asList((int[]) null);
+                Assert.fail("Should have thrown an exception");
+            } catch (final IllegalArgumentException ex) {
+                // good.
+            }
+        } else {
+            final Random rdn = GenomeAnalysisEngine.getRandomGenerator();
+            final double[] valuesClone = values.clone();
+            final List<Double> list = Utils.asList(valuesClone);
+            Assert.assertNotNull(list);
+            Assert.assertEquals(list.size(),values.length);
+            for (int i = 0; i < values.length; i++)
+                Assert.assertEquals((double) list.get(i),values[i]);
+            for (int i = 0; i < values.length; i++)
+                valuesClone[rdn.nextInt(values.length)] = rdn.nextDouble() * 1000;
+            for (int i = 0; i < values.length; i++)
+                Assert.assertEquals((double) list.get(i),valuesClone[i]);
+        }
+    }
+
+    @Test
+    public void testCalcMD5() throws Exception {
+        final File source = new File(publicTestDir + "exampleFASTA.fasta");
+        final String sourceMD5 = "36880691cf9e4178216f7b52e8d85fbe";
+
+        final byte[] sourceBytes = IOUtils.readFileIntoByteArray(source);
+        Assert.assertEquals(Utils.calcMD5(sourceBytes), sourceMD5);
+
+        final String sourceString = FileUtils.readFileToString(source);
+        Assert.assertEquals(Utils.calcMD5(sourceString), sourceMD5);
+    }
+
+    @Test
+    public void testLongestCommonOps() {
+        for ( int prefixLen = 0; prefixLen < 20; prefixLen++ ) {
+            for ( int extraSeq1Len = 0; extraSeq1Len < 10; extraSeq1Len++ ) {
+                for ( int extraSeq2Len = 0; extraSeq2Len < 10; extraSeq2Len++ ) {
+                    for ( int max = 0; max < 50; max++ ) {
+                        final String prefix = Utils.dupString("A", prefixLen);
+                        final int expected = Math.min(prefixLen, max);
+
+                        {
+                            final String seq1 = prefix + Utils.dupString("C", extraSeq1Len);
+                            final String seq2 = prefix + Utils.dupString("G", extraSeq1Len);
+                            Assert.assertEquals(Utils.longestCommonPrefix(seq1.getBytes(), seq2.getBytes(), max), expected, "LongestCommonPrefix failed: seq1 " + seq1 + " seq2 " + seq2 + " max " + max);
+                        }
+
+                        {
+                            final String seq1 = Utils.dupString("C", extraSeq1Len) + prefix;
+                            final String seq2 = Utils.dupString("G", extraSeq1Len) + prefix;
+                            Assert.assertEquals(Utils.longestCommonSuffix(seq1.getBytes(), seq2.getBytes(), max), expected, "longestCommonSuffix failed: seq1 " + seq1 + " seq2 " + seq2 + " max " + max);
+                        }
+                    }
+                }
+            }
+        }
+    }
+
+    @DataProvider(name = "trim")
+    public Object[][] createTrimTestData() {
+        List<Object[]> tests = new ArrayList<Object[]>();
+
+        final String s = "AAAA";
+        for ( int front = 0; front < s.length(); front++ ) {
+            for ( int back = 0; back < s.length(); back++ ) {
+                if ( front + back <= s.length() )
+                    tests.add(new Object[]{s, front, back});
+            }
+        }
+
+        return tests.toArray(new Object[][]{});
+    }
+
+    @Test(dataProvider = "trim", enabled = true)
+    public void testTrim(final String s, final int frontTrim, final int backTrim) {
+        Assert.assertEquals(s.length() - frontTrim - backTrim, Utils.trimArray(s.getBytes(), frontTrim, backTrim).length);
+    }
+
+    @Test(dataProvider = "equalRangeData", enabled = true)
+    public void testEqualRange(final byte[] array1, final byte[] array2, final int offset1, final int offset2, final int length, final boolean expected) {
+        Assert.assertEquals(Utils.equalRange(array1,offset1,array2,offset2,length),expected);
+        Assert.assertTrue(Utils.equalRange(array1,offset1,array1,offset1,length));
+        Assert.assertTrue(Utils.equalRange(array2,offset2,array2,offset2,length));
+
+    }
+
+    @DataProvider(name = "equalRangeData")
+    public Object[][] equalRangeData() {
+        return new Object[][] {
+                new Object[] { new byte[0] , new byte[0], 0, 0, 0, true},
+                new Object[]  {      "ABCF".getBytes(), "BC".getBytes(), 1,0,2, true },
+                new Object[]  { "ABCF".getBytes(), "".getBytes(), 1,0,0, true },
+                new Object[]  { "ABCF".getBytes(), "ACBF".getBytes(), 0,0, 4, false}
+        };
+
+    }
+
+    @Test(dataProvider = "skimArrayData")
+    public void testSkimArray(final String original, final String remove) {
+        final StringBuilder resultBuilder = new StringBuilder();
+        final boolean[] removeBoolean = new boolean[remove.length()];
+        for (int i = 0; i < original.length(); i++)
+            if (remove.charAt(i) == '1') {
+                resultBuilder.append(original.charAt(i));
+                removeBoolean[i] = false;
+            } else
+                removeBoolean[i] = true;
+
+        final String expected = resultBuilder.toString();
+        final byte[] resultBytes = Utils.skimArray(original.getBytes(),removeBoolean);
+        final String resultString = new String(resultBytes);
+        Assert.assertEquals(resultString,expected);
+    }
+
+    @DataProvider(name = "skimArrayData")
+    public Object[][] skimArrayData() {
+        return new Object[][] {
+                {"romeo+juliette" , "11111111111111" },
+                {"romeo+juliette" , "11111011111111" },
+                {"romeo+juliette" , "00000011111111" },
+                {"romeo+juliette" , "11111100000000" },
+                {"romeo+juliette" , "11111011111111" },
+                {"romeo+juliette" , "01111010000001" },
+                {"romeo+juliette" , "01100110000110" },
+                {"romeo+juliette" , "10101010101010" },
+                {"romeo+juliette" , "01010101010101" },
+                {"romeo+juliette" , "01111010111001" },
+        };
+    }
+
+
+    @DataProvider(name = "asIntegerListData")
+    public Object[][] asIntegerListData() {
+        return new Object[][] {
+                { null },
+                {new int[0]},
+                {new int[]{1, 2, 3, 4, 5}},
+                {new int[]{2}},
+                {new int[]{3,4}}
+        };
+    }
+
+    @DataProvider(name = "asDoubleListData")
+    public Object[][] asDoubleListData() {
+        return new Object[][] {
+                { null },
+                {new double[0]},
+                {new double[]{1, 2, 3, 4, 5}},
+                {new double[]{2}},
+                {new double[]{3,4}},
+                {new double[]{Double.NaN, Double.NEGATIVE_INFINITY, Double.POSITIVE_INFINITY}}
+        };
+    }
+}
diff --git a/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/utils/activeregion/ActiveRegionUnitTest.java b/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/utils/activeregion/ActiveRegionUnitTest.java
new file mode 100644
index 0000000..41f7a76
--- /dev/null
+++ b/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/utils/activeregion/ActiveRegionUnitTest.java
@@ -0,0 +1,395 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.utils.activeregion;
+
+
+// the imports for unit testing.
+
+
+import htsjdk.samtools.reference.IndexedFastaSequenceFile;
+import htsjdk.samtools.SAMFileHeader;
+import org.broadinstitute.gatk.utils.BaseTest;
+import org.broadinstitute.gatk.utils.GenomeLoc;
+import org.broadinstitute.gatk.utils.GenomeLocParser;
+import org.broadinstitute.gatk.utils.GenomeLocSortedSet;
+import org.broadinstitute.gatk.utils.fasta.CachingIndexedFastaSequenceFile;
+import org.broadinstitute.gatk.utils.sam.ArtificialSAMUtils;
+import org.broadinstitute.gatk.utils.sam.GATKSAMRecord;
+import org.testng.Assert;
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.DataProvider;
+import org.testng.annotations.Test;
+
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.util.*;
+
+
+public class ActiveRegionUnitTest extends BaseTest {
+    private final static boolean DEBUG = false;
+    private GenomeLocParser genomeLocParser;
+    private IndexedFastaSequenceFile seq;
+    private String contig;
+    private int contigLength;
+
+    @BeforeClass
+    public void init() throws FileNotFoundException {
+        // sequence
+        seq = new CachingIndexedFastaSequenceFile(new File(b37KGReference));
+        genomeLocParser = new GenomeLocParser(seq);
+        contig = "1";
+        contigLength = genomeLocParser.getContigInfo(contig).getSequenceLength();
+    }
+
+    @DataProvider(name = "ActionRegionCreationTest")
+    public Object[][] makePollingData() {
+        List<Object[]> tests = new ArrayList<Object[]>();
+        for ( final int start : Arrays.asList(1, 10, 100, contigLength - 10, contigLength - 1) ) {
+            for ( final int size : Arrays.asList(1, 10, 100, 1000) ) {
+                for ( final int ext : Arrays.asList(0, 1, 10, 100) ) {
+                    for ( final boolean isActive : Arrays.asList(true, false) ) {
+                        for ( final boolean addStates : Arrays.asList(true, false) ) {
+                            List<ActivityProfileState> states = null;
+                            if ( addStates ) {
+                                states = new LinkedList<ActivityProfileState>();
+                                for ( int i = start; i < start + size; i++ ) {
+                                    states.add(new ActivityProfileState(genomeLocParser.createGenomeLoc(contig, i + start), isActive ? 1.0 : 0.0));
+                                }
+                            }
+                            final GenomeLoc loc = genomeLocParser.createGenomeLoc(contig, start, start + size - 1);
+                            tests.add(new Object[]{loc, states, isActive, ext});
+                        }
+                    }
+                }
+            }
+        }
+
+        return tests.toArray(new Object[][]{});
+    }
+
+    @Test(enabled = !DEBUG, dataProvider = "ActionRegionCreationTest")
+    public void testCreatingActiveRegions(final GenomeLoc loc, final List<ActivityProfileState> supportingStates, final boolean isActive, final int extension) {
+        final ActiveRegion region = new ActiveRegion(loc, supportingStates, isActive, genomeLocParser, extension);
+        Assert.assertEquals(region.getLocation(), loc);
+        Assert.assertEquals(region.getExtendedLoc().getStart(), Math.max(loc.getStart() - extension, 1));
+        Assert.assertEquals(region.getExtendedLoc().getStop(), Math.min(loc.getStop() + extension, contigLength));
+        Assert.assertEquals(region.getReadSpanLoc().getStart(), Math.max(loc.getStart() - extension, 1));
+        Assert.assertEquals(region.getReadSpanLoc().getStop(), Math.min(loc.getStop() + extension, contigLength));
+        Assert.assertEquals(region.isActive(), isActive);
+        Assert.assertEquals(region.getExtension(), extension);
+        Assert.assertEquals(region.getReads(), Collections.emptyList());
+        Assert.assertEquals(region.size(), 0);
+        Assert.assertEquals(region.getSupportingStates(), supportingStates == null ? Collections.emptyList() : supportingStates);
+        Assert.assertNotNull(region.toString());
+
+        assertGoodReferenceGetter(region.getActiveRegionReference(seq), region.getExtendedLoc(), 0);
+        assertGoodReferenceGetter(region.getActiveRegionReference(seq, 10), region.getExtendedLoc(), 10);
+        assertGoodReferenceGetter(region.getFullReference(seq), region.getReadSpanLoc(), 0);
+        assertGoodReferenceGetter(region.getFullReference(seq, 10), region.getReadSpanLoc(), 10);
+    }
+
+    private void assertGoodReferenceGetter(final byte[] actualBytes, final GenomeLoc span, final int padding) {
+        final int expectedStart = Math.max(span.getStart() - padding, 1);
+        final int expectedStop = Math.min(span.getStop() + padding, contigLength);
+        final byte[] expectedBytes = seq.getSubsequenceAt(span.getContig(), expectedStart, expectedStop).getBases();
+        Assert.assertEquals(actualBytes, expectedBytes);
+    }
+
+    @DataProvider(name = "ActiveRegionReads")
+    public Object[][] makeActiveRegionReads() {
+        List<Object[]> tests = new ArrayList<Object[]>();
+        final SAMFileHeader header = ArtificialSAMUtils.createArtificialSamHeader(seq.getSequenceDictionary());
+        for ( final int start : Arrays.asList(1, 10, 100, contigLength - 10, contigLength - 1) ) {
+            for ( final int readStartOffset : Arrays.asList(-100, -10, 0, 10, 100) ) {
+                for ( final int readSize : Arrays.asList(10, 100, 1000) ) {
+                    final GenomeLoc loc = genomeLocParser.createGenomeLocOnContig(contig, start, start + 10);
+
+                    final int readStart = Math.max(start + readStartOffset, 1);
+                    final int readStop = Math.min(readStart + readSize, contigLength);
+                    final int readLength = readStop - readStart + 1;
+                    if ( readLength > 0 ) {
+                        GATKSAMRecord read = ArtificialSAMUtils.createArtificialRead(header, "read", 0, readStart, readLength);
+                        final GenomeLoc readLoc = genomeLocParser.createGenomeLoc(read);
+                        if ( readLoc.overlapsP(loc) )
+                            tests.add(new Object[]{loc, read});
+                    }
+                }
+            }
+        }
+
+        return tests.toArray(new Object[][]{});
+    }
+
+    @Test(enabled = !DEBUG, dataProvider = "ActiveRegionReads")
+    public void testActiveRegionReads(final GenomeLoc loc, final GATKSAMRecord read) throws Exception {
+        final GenomeLoc expectedSpan = loc.union(genomeLocParser.createGenomeLoc(read));
+
+        final ActiveRegion region = new ActiveRegion(loc, null, true, genomeLocParser, 0);
+        final ActiveRegion region2 = new ActiveRegion(loc, null, true, genomeLocParser, 0);
+        Assert.assertEquals(region.getReads(), Collections.emptyList());
+        Assert.assertEquals(region.size(), 0);
+        Assert.assertEquals(region.getExtendedLoc(), loc);
+        Assert.assertEquals(region.getReadSpanLoc(), loc);
+        Assert.assertTrue(region.equalExceptReads(region2));
+
+        region.add(read);
+        Assert.assertEquals(region.getReads(), Collections.singletonList(read));
+        Assert.assertEquals(region.size(), 1);
+        Assert.assertEquals(region.getExtendedLoc(), loc);
+        Assert.assertEquals(region.getReadSpanLoc(), expectedSpan);
+        Assert.assertTrue(region.equalExceptReads(region2));
+
+        region.clearReads();
+        Assert.assertEquals(region.getReads(), Collections.emptyList());
+        Assert.assertEquals(region.size(), 0);
+        Assert.assertEquals(region.getExtendedLoc(), loc);
+        Assert.assertEquals(region.getReadSpanLoc(), loc);
+        Assert.assertTrue(region.equalExceptReads(region2));
+
+        region.addAll(Collections.singleton(read));
+        Assert.assertEquals(region.getReads(), Collections.singletonList(read));
+        Assert.assertEquals(region.size(), 1);
+        Assert.assertEquals(region.getExtendedLoc(), loc);
+        Assert.assertEquals(region.getReadSpanLoc(), expectedSpan);
+        Assert.assertTrue(region.equalExceptReads(region2));
+
+        region.removeAll(Collections.<GATKSAMRecord>emptySet());
+        Assert.assertEquals(region.getReads(), Collections.singletonList(read));
+        Assert.assertEquals(region.size(), 1);
+        Assert.assertEquals(region.getExtendedLoc(), loc);
+        Assert.assertEquals(region.getReadSpanLoc(), expectedSpan);
+        Assert.assertTrue(region.equalExceptReads(region2));
+
+        region.removeAll(Collections.singleton(read));
+        Assert.assertEquals(region.getReads(), Collections.emptyList());
+        Assert.assertEquals(region.size(), 0);
+        Assert.assertEquals(region.getExtendedLoc(), loc);
+        Assert.assertEquals(region.getReadSpanLoc(), loc);
+        Assert.assertTrue(region.equalExceptReads(region2));
+
+        final GATKSAMRecord read2 = (GATKSAMRecord)read.clone();
+        read2.setReadName(read.getReadName() + ".clone");
+
+        for ( final GATKSAMRecord readToKeep : Arrays.asList(read, read2)) {
+            region.addAll(Arrays.asList(read, read2));
+            final GATKSAMRecord readToDiscard = readToKeep == read ? read2 : read;
+            region.removeAll(Collections.singleton(readToDiscard));
+            Assert.assertEquals(region.getReads(), Arrays.asList(readToKeep));
+            Assert.assertEquals(region.size(), 1);
+            Assert.assertEquals(region.getExtendedLoc(), loc);
+        }
+    }
+
+    // -----------------------------------------------------------------------------------------------
+    //
+    // Make sure bad inputs are properly detected
+    //
+    // -----------------------------------------------------------------------------------------------
+
+    @DataProvider(name = "BadReadsTest")
+    public Object[][] makeBadReadsTest() {
+        List<Object[]> tests = new ArrayList<Object[]>();
+        final SAMFileHeader header = ArtificialSAMUtils.createArtificialSamHeader(seq.getSequenceDictionary());
+        tests.add(new Object[]{
+                ArtificialSAMUtils.createArtificialRead(header, "read1", 0, 10, 10),
+                ArtificialSAMUtils.createArtificialRead(header, "read2", 0, 9, 10)});
+        tests.add(new Object[]{
+                ArtificialSAMUtils.createArtificialRead(header, "read1", 0, 10, 10),
+                ArtificialSAMUtils.createArtificialRead(header, "read2", 1, 9, 10)});
+        tests.add(new Object[]{
+                ArtificialSAMUtils.createArtificialRead(header, "read1", 1, 10, 10),
+                ArtificialSAMUtils.createArtificialRead(header, "read2", 0, 9, 10)});
+        return tests.toArray(new Object[][]{});
+    }
+
+    @Test(enabled = !DEBUG, dataProvider = "BadReadsTest", expectedExceptions = IllegalArgumentException.class)
+    public void testBadReads(final GATKSAMRecord read1, final GATKSAMRecord read2) {
+        final GenomeLoc loc = genomeLocParser.createGenomeLoc(read1);
+        final ActiveRegion region = new ActiveRegion(loc, null, true, genomeLocParser, 0);
+        region.add(read1);
+        region.add(read2);
+    }
+
+    // -----------------------------------------------------------------------------------------------
+    //
+    // Make sure we can properly cut up an active region based on engine intervals
+    //
+    // -----------------------------------------------------------------------------------------------
+
+    @DataProvider(name = "SplitActiveRegion")
+    public Object[][] makeSplitActiveRegion() {
+        List<Object[]> tests = new ArrayList<Object[]>();
+
+        final GenomeLoc whole_span = genomeLocParser.createGenomeLoc("20", 1, 500);
+        final GenomeLoc gl_before = genomeLocParser.createGenomeLoc("20", 1, 9);
+        final GenomeLoc gl_after = genomeLocParser.createGenomeLoc("20", 250, 500);
+        final GenomeLoc gl_diff_contig = genomeLocParser.createGenomeLoc("19", 40, 50);
+
+        final int regionStart = 10;
+        final int regionStop = 100;
+        final GenomeLoc region = genomeLocParser.createGenomeLoc("20", regionStart, regionStop);
+
+        for ( final GenomeLoc noEffect : Arrays.asList(whole_span) )
+            tests.add(new Object[]{
+                    region,
+                    Arrays.asList(noEffect),
+                    Arrays.asList(region)});
+
+        for ( final GenomeLoc noOverlap : Arrays.asList(gl_before, gl_after, gl_diff_contig) )
+            tests.add(new Object[]{
+                    region,
+                    Arrays.asList(noOverlap),
+                    Arrays.asList()});
+
+        tests.add(new Object[]{region,
+                Arrays.asList(genomeLocParser.createGenomeLoc("20", 5, 50)),
+                Arrays.asList(genomeLocParser.createGenomeLoc("20", regionStart, 50))});
+
+        tests.add(new Object[]{region,
+                Arrays.asList(genomeLocParser.createGenomeLoc("20", 50, 200)),
+                Arrays.asList(genomeLocParser.createGenomeLoc("20", 50, regionStop))});
+
+        tests.add(new Object[]{region,
+                Arrays.asList(genomeLocParser.createGenomeLoc("20", 40, 50)),
+                Arrays.asList(genomeLocParser.createGenomeLoc("20", 40, 50))});
+
+        tests.add(new Object[]{region,
+                Arrays.asList(genomeLocParser.createGenomeLoc("20", 20, 30), genomeLocParser.createGenomeLoc("20", 40, 50)),
+                Arrays.asList(genomeLocParser.createGenomeLoc("20", 20, 30), genomeLocParser.createGenomeLoc("20", 40, 50))});
+
+        tests.add(new Object[]{region,
+                Arrays.asList(genomeLocParser.createGenomeLoc("20", 1, 30), genomeLocParser.createGenomeLoc("20", 40, 50)),
+                Arrays.asList(genomeLocParser.createGenomeLoc("20", regionStart, 30), genomeLocParser.createGenomeLoc("20", 40, 50))});
+
+        tests.add(new Object[]{region,
+                Arrays.asList(genomeLocParser.createGenomeLoc("20", 1, 30), genomeLocParser.createGenomeLoc("20", 70, 200)),
+                Arrays.asList(genomeLocParser.createGenomeLoc("20", regionStart, 30), genomeLocParser.createGenomeLoc("20", 70, regionStop))});
+
+        tests.add(new Object[]{region,
+                Arrays.asList(genomeLocParser.createGenomeLoc("20", 1, 30), genomeLocParser.createGenomeLoc("20", 40, 50), genomeLocParser.createGenomeLoc("20", 70, 200)),
+                Arrays.asList(genomeLocParser.createGenomeLoc("20", regionStart, 30), genomeLocParser.createGenomeLoc("20", 40, 50), genomeLocParser.createGenomeLoc("20", 70, regionStop))});
+
+        return tests.toArray(new Object[][]{});
+    }
+
+    @Test(dataProvider = "SplitActiveRegion")
+    public void testSplitActiveRegion(final GenomeLoc regionLoc, final List<GenomeLoc> intervalLocs, final List<GenomeLoc> expectedRegionLocs) {
+        for ( final boolean addSubstates : Arrays.asList(true, false) ) {
+            final List<ActivityProfileState> states;
+            if ( addSubstates ) {
+                states = new LinkedList<ActivityProfileState>();
+                for ( int i = 0; i < regionLoc.size(); i++ )
+                    states.add(new ActivityProfileState(genomeLocParser.createGenomeLoc(regionLoc.getContig(), regionLoc.getStart() + i), 1.0));
+            } else {
+                states = null;
+            }
+
+            final ActiveRegion region = new ActiveRegion(regionLoc, states, true, genomeLocParser, 0);
+            final GenomeLocSortedSet intervals = new GenomeLocSortedSet(genomeLocParser,  intervalLocs);
+            final List<ActiveRegion> regions = region.splitAndTrimToIntervals(intervals);
+
+            Assert.assertEquals(regions.size(), expectedRegionLocs.size(), "Wrong number of split locations");
+            for ( int i = 0; i < expectedRegionLocs.size(); i++ ) {
+                final GenomeLoc expected = expectedRegionLocs.get(i);
+                final ActiveRegion actual = regions.get(i);
+                Assert.assertEquals(actual.getLocation(), expected, "Bad region after split");
+                Assert.assertEquals(actual.isActive(), region.isActive());
+                Assert.assertEquals(actual.getExtension(), region.getExtension());
+            }
+        }
+    }
+
+    // -----------------------------------------------------------------------------------------------
+    //
+    // Make sure we can properly cut up an active region based on engine intervals
+    //
+    // -----------------------------------------------------------------------------------------------
+
+    @DataProvider(name = "TrimActiveRegionData")
+    public Object[][] makeTrimActiveRegionData() {
+        List<Object[]> tests = new ArrayList<Object[]>();
+
+        // fully enclosed within active region
+        tests.add(new Object[]{
+                genomeLocParser.createGenomeLoc("20", 10, 20), 10,
+                genomeLocParser.createGenomeLoc("20", 15, 16),
+                genomeLocParser.createGenomeLoc("20", 15, 16), 0});
+
+        tests.add(new Object[]{
+                genomeLocParser.createGenomeLoc("20", 10, 20), 10,
+                genomeLocParser.createGenomeLoc("20", 10, 15),
+                genomeLocParser.createGenomeLoc("20", 10, 15), 0});
+
+        tests.add(new Object[]{
+                genomeLocParser.createGenomeLoc("20", 10, 20), 10,
+                genomeLocParser.createGenomeLoc("20", 15, 20),
+                genomeLocParser.createGenomeLoc("20", 15, 20), 0});
+
+        // needs extra padding on the right
+        tests.add(new Object[]{
+                genomeLocParser.createGenomeLoc("20", 10, 20), 10,
+                genomeLocParser.createGenomeLoc("20", 15, 25),
+                genomeLocParser.createGenomeLoc("20", 15, 20), 5});
+
+        // needs extra padding on the left
+        tests.add(new Object[]{
+                genomeLocParser.createGenomeLoc("20", 10, 20), 10,
+                genomeLocParser.createGenomeLoc("20", 5, 15),
+                genomeLocParser.createGenomeLoc("20", 10, 15), 5});
+
+        // needs extra padding on both
+        tests.add(new Object[]{
+                genomeLocParser.createGenomeLoc("20", 10, 20), 10,
+                genomeLocParser.createGenomeLoc("20", 7, 21),
+                genomeLocParser.createGenomeLoc("20", 10, 20), 3});
+        tests.add(new Object[]{
+                genomeLocParser.createGenomeLoc("20", 10, 20), 10,
+                genomeLocParser.createGenomeLoc("20", 9, 23),
+                genomeLocParser.createGenomeLoc("20", 10, 20), 3});
+
+        // desired span captures everything, so we're returning everything.  Tests that extension is set correctly
+        tests.add(new Object[]{
+                genomeLocParser.createGenomeLoc("20", 10, 20), 10,
+                genomeLocParser.createGenomeLoc("20", 1, 50),
+                genomeLocParser.createGenomeLoc("20", 10, 20), 10});
+
+        // At the start of the chromosome, potentially a bit weird
+        tests.add(new Object[]{
+                genomeLocParser.createGenomeLoc("20", 1, 10), 10,
+                genomeLocParser.createGenomeLoc("20", 1, 50),
+                genomeLocParser.createGenomeLoc("20", 1, 10), 10});
+
+        return tests.toArray(new Object[][]{});
+    }
+
+    @Test(dataProvider = "TrimActiveRegionData")
+    public void testTrimActiveRegion(final GenomeLoc regionLoc, final int extension, final GenomeLoc desiredSpan, final GenomeLoc expectedActiveRegion, final int expectedExtension) {
+        final ActiveRegion region = new ActiveRegion(regionLoc, Collections.<ActivityProfileState>emptyList(), true, genomeLocParser, extension);
+        final ActiveRegion trimmed = region.trim(desiredSpan);
+        Assert.assertEquals(trimmed.getLocation(), expectedActiveRegion, "Incorrect region");
+        Assert.assertEquals(trimmed.getExtension(), expectedExtension, "Incorrect region");
+    }
+}
\ No newline at end of file
diff --git a/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/utils/activeregion/ActivityProfileStateUnitTest.java b/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/utils/activeregion/ActivityProfileStateUnitTest.java
new file mode 100644
index 0000000..75e9d9a
--- /dev/null
+++ b/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/utils/activeregion/ActivityProfileStateUnitTest.java
@@ -0,0 +1,92 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.utils.activeregion;
+
+import htsjdk.samtools.SAMFileHeader;
+import org.broadinstitute.gatk.utils.GenomeLoc;
+import org.broadinstitute.gatk.utils.GenomeLocParser;
+import org.broadinstitute.gatk.utils.sam.ArtificialSAMUtils;
+import org.testng.Assert;
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.DataProvider;
+import org.testng.annotations.Test;
+
+import java.io.FileNotFoundException;
+import java.util.Arrays;
+import java.util.LinkedList;
+import java.util.List;
+
+/**
+ * Created with IntelliJ IDEA.
+ * User: depristo
+ * Date: 1/17/13
+ * Time: 2:30 PM
+ * To change this template use File | Settings | File Templates.
+ */
+public class ActivityProfileStateUnitTest {
+    private GenomeLocParser genomeLocParser;
+
+    @BeforeClass
+    public void init() throws FileNotFoundException {
+        // sequence
+        final SAMFileHeader header = ArtificialSAMUtils.createArtificialSamHeader(1, 1, 100);
+        genomeLocParser = new GenomeLocParser(header.getSequenceDictionary());
+    }
+
+    @DataProvider(name = "ActiveProfileResultProvider")
+    public Object[][] makeActiveProfileResultProvider() {
+        final List<Object[]> tests = new LinkedList<Object[]>();
+
+        final String chr = genomeLocParser.getContigs().getSequence(0).getSequenceName();
+        for ( final GenomeLoc loc : Arrays.asList(
+                genomeLocParser.createGenomeLoc(chr, 10, 10),
+                genomeLocParser.createGenomeLoc(chr, 100, 100) )) {
+            for ( final double prob : Arrays.asList(0.0, 0.5, 1.0) ) {
+                for ( final ActivityProfileState.Type state : ActivityProfileState.Type.values() ) {
+                    for ( final Number value : Arrays.asList(1, 2, 4) ) {
+                        tests.add(new Object[]{ loc, prob, state, value});
+                    }
+                }
+                tests.add(new Object[]{ loc, prob, null, null});
+            }
+        }
+
+        return tests.toArray(new Object[][]{});
+    }
+
+    @Test(dataProvider = "ActiveProfileResultProvider")
+    public void testActiveProfileResultProvider(GenomeLoc loc, final double prob, ActivityProfileState.Type maybeState, final Number maybeNumber) {
+        final ActivityProfileState apr = maybeState == null
+                ? new ActivityProfileState(loc, prob)
+                : new ActivityProfileState(loc, prob, maybeState, maybeNumber);
+
+        Assert.assertEquals(apr.getLoc(), loc);
+        Assert.assertNotNull(apr.toString());
+        Assert.assertEquals(apr.isActiveProb, prob);
+        Assert.assertEquals(apr.resultState, maybeState == null ? ActivityProfileState.Type.NONE : maybeState);
+        Assert.assertEquals(apr.resultValue, maybeState == null ? null : maybeNumber);
+    }
+}
diff --git a/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/utils/activeregion/ActivityProfileUnitTest.java b/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/utils/activeregion/ActivityProfileUnitTest.java
new file mode 100644
index 0000000..b3442b3
--- /dev/null
+++ b/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/utils/activeregion/ActivityProfileUnitTest.java
@@ -0,0 +1,491 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.utils.activeregion;
+
+
+// the imports for unit testing.
+
+
+import htsjdk.samtools.reference.ReferenceSequenceFile;
+import org.broadinstitute.gatk.utils.BaseTest;
+import org.broadinstitute.gatk.utils.GenomeLoc;
+import org.broadinstitute.gatk.utils.GenomeLocParser;
+import org.broadinstitute.gatk.utils.MathUtils;
+import org.broadinstitute.gatk.utils.Utils;
+import org.broadinstitute.gatk.utils.fasta.CachingIndexedFastaSequenceFile;
+import org.testng.Assert;
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.DataProvider;
+import org.testng.annotations.Test;
+
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.util.*;
+
+
+public class ActivityProfileUnitTest extends BaseTest {
+    private final static boolean DEBUG = false;
+    private GenomeLocParser genomeLocParser;
+    private GenomeLoc startLoc;
+
+    private final static int MAX_PROB_PROPAGATION_DISTANCE = 50;
+    private final static double ACTIVE_PROB_THRESHOLD= 0.002;
+
+    @BeforeClass
+    public void init() throws FileNotFoundException {
+        // sequence
+        ReferenceSequenceFile seq = new CachingIndexedFastaSequenceFile(new File(hg18Reference));
+        genomeLocParser = new GenomeLocParser(seq);
+        startLoc = genomeLocParser.createGenomeLoc("chr1", 1, 1, 100);
+    }
+
+    // --------------------------------------------------------------------------------
+    //
+    // Basic tests Provider
+    //
+    // --------------------------------------------------------------------------------
+
+    private class BasicActivityProfileTestProvider extends TestDataProvider {
+        List<Double> probs;
+        List<ActiveRegion> expectedRegions;
+        int extension = 0;
+        GenomeLoc regionStart = startLoc;
+        final ProfileType type;
+
+        public BasicActivityProfileTestProvider(final ProfileType type, final List<Double> probs, boolean startActive, int ... startsAndStops) {
+            super(BasicActivityProfileTestProvider.class);
+            this.type = type;
+            this.probs = probs;
+            this.expectedRegions = toRegions(startActive, startsAndStops);
+            setName(getName());
+        }
+
+        private String getName() {
+            return String.format("type=%s probs=%s expectedRegions=%s", type, Utils.join(",", probs), Utils.join(",", expectedRegions));
+        }
+
+        public ActivityProfile makeProfile() {
+            switch ( type ) {
+                case Base: return new ActivityProfile(genomeLocParser, MAX_PROB_PROPAGATION_DISTANCE, ACTIVE_PROB_THRESHOLD);
+                case BandPass:
+                    // zero size => equivalent to ActivityProfile
+                    return new BandPassActivityProfile(genomeLocParser, null, MAX_PROB_PROPAGATION_DISTANCE, ACTIVE_PROB_THRESHOLD, 0, 0.01, false);
+                default: throw new IllegalStateException(type.toString());
+            }
+        }
+
+        private List<ActiveRegion> toRegions(boolean isActive, int[] startsAndStops) {
+            List<ActiveRegion> l = new ArrayList<ActiveRegion>();
+            for ( int i = 0; i < startsAndStops.length - 1; i++) {
+                int start = regionStart.getStart() + startsAndStops[i];
+                int end = regionStart.getStart() + startsAndStops[i+1] - 1;
+                GenomeLoc activeLoc = genomeLocParser.createGenomeLoc(regionStart.getContig(), start, end);
+                ActiveRegion r = new ActiveRegion(activeLoc, Collections.<ActivityProfileState>emptyList(), isActive, genomeLocParser, extension);
+                l.add(r);
+                isActive = ! isActive;
+            }
+            return l;
+        }
+    }
+
+    private enum ProfileType {
+        Base, BandPass
+    }
+
+    @DataProvider(name = "BasicActivityProfileTestProvider")
+    public Object[][] makeQualIntervalTestProvider() {
+        for ( final ProfileType type : ProfileType.values() ) {
+            new BasicActivityProfileTestProvider(type, Arrays.asList(1.0), true, 0, 1);
+            new BasicActivityProfileTestProvider(type, Arrays.asList(1.0, 0.0), true, 0, 1, 2);
+            new BasicActivityProfileTestProvider(type, Arrays.asList(0.0, 1.0), false, 0, 1, 2);
+            new BasicActivityProfileTestProvider(type, Arrays.asList(1.0, 0.0, 1.0), true, 0, 1, 2, 3);
+            new BasicActivityProfileTestProvider(type, Arrays.asList(1.0, 1.0, 1.0), true, 0, 3);
+        }
+
+        return BasicActivityProfileTestProvider.getTests(BasicActivityProfileTestProvider.class);
+    }
+
+    @Test(enabled = ! DEBUG, dataProvider = "BasicActivityProfileTestProvider")
+    public void testBasicActivityProfile(BasicActivityProfileTestProvider cfg) {
+        ActivityProfile profile = cfg.makeProfile();
+
+        Assert.assertTrue(profile.isEmpty());
+
+        Assert.assertEquals(profile.parser, genomeLocParser);
+
+        for ( int i = 0; i < cfg.probs.size(); i++ ) {
+            double p = cfg.probs.get(i);
+            GenomeLoc loc = genomeLocParser.createGenomeLoc(cfg.regionStart.getContig(), cfg.regionStart.getStart() + i, cfg.regionStart.getStart() + i);
+            profile.add(new ActivityProfileState(loc, p));
+            Assert.assertFalse(profile.isEmpty(), "Profile shouldn't be empty after adding a state");
+        }
+        Assert.assertEquals(profile.regionStartLoc, genomeLocParser.createGenomeLoc(cfg.regionStart.getContig(), cfg.regionStart.getStart(), cfg.regionStart.getStart() ), "Start loc should be the start of the region");
+
+        Assert.assertEquals(profile.size(), cfg.probs.size(), "Should have exactly the number of states we expected to add");
+        assertProbsAreEqual(profile.stateList, cfg.probs);
+
+        // TODO -- reanble tests
+        //assertRegionsAreEqual(profile.createActiveRegions(0, 100), cfg.expectedRegions);
+    }
+
+    private void assertRegionsAreEqual(List<ActiveRegion> actual, List<ActiveRegion> expected) {
+        Assert.assertEquals(actual.size(), expected.size());
+        for ( int i = 0; i < actual.size(); i++ ) {
+            Assert.assertTrue(actual.get(i).equalExceptReads(expected.get(i)));
+        }
+    }
+
+    private void assertProbsAreEqual(List<ActivityProfileState> actual, List<Double> expected) {
+        Assert.assertEquals(actual.size(), expected.size());
+        for ( int i = 0; i < actual.size(); i++ ) {
+            Assert.assertEquals(actual.get(i).isActiveProb, expected.get(i));
+        }
+    }
+
+    // -------------------------------------------------------------------------------------
+    //
+    // Hardcore tests for adding to the profile and constructing active regions
+    //
+    // -------------------------------------------------------------------------------------
+
+    private static class SizeToStringList<T> extends ArrayList<T> {
+        @Override public String toString() { return "List[" + size() + "]"; }
+    }
+
+    @DataProvider(name = "RegionCreationTests")
+    public Object[][] makeRegionCreationTests() {
+        final List<Object[]> tests = new LinkedList<Object[]>();
+
+        final int contigLength = genomeLocParser.getContigs().getSequences().get(0).getSequenceLength();
+        for ( int start : Arrays.asList(1, 10, 100, contigLength - 100, contigLength - 10) ) {
+            for ( int regionSize : Arrays.asList(1, 10, 100, 1000, 10000) ) {
+                for ( int maxRegionSize : Arrays.asList(10, 50, 200) ) {
+                    for ( final boolean waitUntilEnd : Arrays.asList(false, true) ) {
+                        for ( final boolean forceConversion : Arrays.asList(false, true) ) {
+                            // what do I really want to test here?  I'd like to test a few cases:
+                            // -- region is all active (1.0)
+                            // -- region is all inactive (0.0)
+                            // -- cut the interval into 1, 2, 3, 4, 5 ... 10 regions, each with alternating activity values
+                            for ( final boolean startWithActive : Arrays.asList(true, false) ) {
+                                for ( int nParts : Arrays.asList(1, 2, 3, 4, 5, 7, 10, 11, 13) ) {
+
+//        for ( int start : Arrays.asList(1) ) {
+//            for ( int regionSize : Arrays.asList(100) ) {
+//                for ( int maxRegionSize : Arrays.asList(10) ) {
+//                    for ( final boolean waitUntilEnd : Arrays.asList(true) ) {
+//                        for ( final boolean forceConversion : Arrays.asList(false) ) {
+//                            for ( final boolean startWithActive : Arrays.asList(true) ) {
+//                                for ( int nParts : Arrays.asList(3) ) {
+                                    regionSize = Math.min(regionSize, contigLength - start);
+                                    final List<Boolean> regions = makeRegions(regionSize, startWithActive, nParts);
+                                    tests.add(new Object[]{ start, regions, maxRegionSize, nParts, forceConversion, waitUntilEnd });
+                                }
+                            }
+                        }
+                    }
+                }
+            }
+        }
+
+        return tests.toArray(new Object[][]{});
+    }
+
+    private List<Boolean> makeRegions(final int totalRegionSize,
+                                      final boolean startWithActive,
+                                      final int nParts) {
+        final List<Boolean> regions = new SizeToStringList<Boolean>();
+
+        boolean isActive = startWithActive;
+        final int activeRegionSize = Math.max(totalRegionSize / nParts, 1);
+        for ( int i = 0; i < totalRegionSize; i += activeRegionSize ) {
+            for ( int j = 0; j < activeRegionSize && j + i < totalRegionSize; j++ ) {
+                regions.add(isActive);
+            }
+            isActive = ! isActive;
+        }
+
+        return regions;
+    }
+
+
+    @Test(enabled = !DEBUG, dataProvider = "RegionCreationTests")
+    public void testRegionCreation(final int start, final List<Boolean> probs, int maxRegionSize, final int nParts, final boolean forceConversion, final boolean waitUntilEnd) {
+        final ActivityProfile profile = new ActivityProfile(genomeLocParser, MAX_PROB_PROPAGATION_DISTANCE, ACTIVE_PROB_THRESHOLD);
+        Assert.assertNotNull(profile.toString());
+
+        final String contig = genomeLocParser.getContigs().getSequences().get(0).getSequenceName();
+        final List<Boolean> seenSites = new ArrayList<Boolean>(Collections.nCopies(probs.size(), false));
+        ActiveRegion lastRegion = null;
+        for ( int i = 0; i < probs.size(); i++ ) {
+            final boolean isActive = probs.get(i);
+            final GenomeLoc loc = genomeLocParser.createGenomeLoc(contig, i + start);
+            final ActivityProfileState state = new ActivityProfileState(loc, isActive ? 1.0 : 0.0);
+            profile.add(state);
+            Assert.assertNotNull(profile.toString());
+
+            if ( ! waitUntilEnd ) {
+                final List<ActiveRegion> regions = profile.popReadyActiveRegions(0, 1, maxRegionSize, false);
+                lastRegion = assertGoodRegions(start, regions, maxRegionSize, lastRegion, probs, seenSites);
+            }
+        }
+
+        if ( waitUntilEnd || forceConversion ) {
+            final List<ActiveRegion> regions = profile.popReadyActiveRegions(0, 1, maxRegionSize, forceConversion);
+            lastRegion = assertGoodRegions(start, regions, maxRegionSize, lastRegion, probs, seenSites);
+        }
+
+        for ( int i = 0; i < probs.size(); i++ ) {
+            if ( forceConversion || (i + maxRegionSize + profile.getMaxProbPropagationDistance() < probs.size()))
+                // only require a site to be seen if we are forcing conversion or the site is more than maxRegionSize from the end
+                Assert.assertTrue(seenSites.get(i), "Missed site " + i);
+        }
+
+        Assert.assertNotNull(profile.toString());
+    }
+
+    private ActiveRegion assertGoodRegions(final int start, final List<ActiveRegion> regions, final int maxRegionSize, ActiveRegion lastRegion, final List<Boolean> probs, final List<Boolean> seenSites) {
+        for ( final ActiveRegion region : regions ) {
+            Assert.assertTrue(region.getLocation().size() > 0, "Region " + region + " has a bad size");
+            Assert.assertTrue(region.getLocation().size() <= maxRegionSize, "Region " + region + " has a bad size: it's big than the max region size " + maxRegionSize);
+            if ( lastRegion != null ) {
+                Assert.assertTrue(region.getLocation().getStart() == lastRegion.getLocation().getStop() + 1, "Region " + region + " doesn't start immediately after previous region" + lastRegion);
+            }
+
+            // check that all active bases are actually active
+            final int regionOffset = region.getLocation().getStart() - start;
+            Assert.assertTrue(regionOffset >= 0 && regionOffset < probs.size(), "Region " + region + " has a bad offset w.r.t. start");
+            for ( int j = 0; j < region.getLocation().size(); j++ ) {
+                final int siteOffset = j + regionOffset;
+                Assert.assertEquals(region.isActive(), probs.get(siteOffset).booleanValue());
+                Assert.assertFalse(seenSites.get(siteOffset), "Site " + j + " in " + region + " was seen already");
+                seenSites.set(siteOffset, true);
+            }
+
+            lastRegion = region;
+        }
+
+        return lastRegion;
+    }
+
+    // -------------------------------------------------------------------------------------
+    //
+    // Hardcore tests for adding to the profile and constructing active regions
+    //
+    // -------------------------------------------------------------------------------------
+
+    @DataProvider(name = "SoftClipsTest")
+    public Object[][] makeSoftClipsTest() {
+        final List<Object[]> tests = new LinkedList<Object[]>();
+
+        final int contigLength = genomeLocParser.getContigs().getSequences().get(0).getSequenceLength();
+        for ( int start : Arrays.asList(1, 10, 100, contigLength - 100, contigLength - 10, contigLength - 1) ) {
+            for ( int precedingSites: Arrays.asList(0, 1, 10) ) {
+                if ( precedingSites + start < contigLength ) {
+                    for ( int softClipSize : Arrays.asList(1, 2, 10, 100) ) {
+//        for ( int start : Arrays.asList(10) ) {
+//            for ( int precedingSites: Arrays.asList(10) ) {
+//                for ( int softClipSize : Arrays.asList(1) ) {
+                        tests.add(new Object[]{ start, precedingSites, softClipSize });
+                    }
+                }
+            }
+        }
+
+        return tests.toArray(new Object[][]{});
+    }
+
+    @Test(enabled = ! DEBUG, dataProvider = "SoftClipsTest")
+    public void testSoftClips(final int start, int nPrecedingSites, final int softClipSize) {
+        final ActivityProfile profile = new ActivityProfile(genomeLocParser, MAX_PROB_PROPAGATION_DISTANCE, ACTIVE_PROB_THRESHOLD);
+
+        final int contigLength = genomeLocParser.getContigs().getSequences().get(0).getSequenceLength();
+        final String contig = genomeLocParser.getContigs().getSequences().get(0).getSequenceName();
+        for ( int i = 0; i < nPrecedingSites; i++ ) {
+            final GenomeLoc loc = genomeLocParser.createGenomeLoc(contig, i + start);
+            final ActivityProfileState state = new ActivityProfileState(loc, 0.0);
+            profile.add(state);
+        }
+
+        final GenomeLoc softClipLoc = genomeLocParser.createGenomeLoc(contig, nPrecedingSites + start);
+        profile.add(new ActivityProfileState(softClipLoc, 1.0, ActivityProfileState.Type.HIGH_QUALITY_SOFT_CLIPS, softClipSize));
+
+        final int actualNumOfSoftClips = Math.min(softClipSize, profile.getMaxProbPropagationDistance());
+        if ( nPrecedingSites == 0 ) {
+            final int profileSize = Math.min(start + actualNumOfSoftClips, contigLength) - start + 1;
+            Assert.assertEquals(profile.size(), profileSize, "Wrong number of states in the profile");
+        }
+
+        for ( int i = 0; i < profile.size(); i++ ) {
+            final ActivityProfileState state = profile.getStateList().get(i);
+            final boolean withinSCRange = state.getLoc().distance(softClipLoc) <= actualNumOfSoftClips;
+            if ( withinSCRange ) {
+                Assert.assertTrue(state.isActiveProb > 0.0, "active prob should be changed within soft clip size");
+            } else {
+                Assert.assertEquals(state.isActiveProb, 0.0, "active prob shouldn't be changed outside of clip size");
+            }
+        }
+    }
+
+    // -------------------------------------------------------------------------------------
+    //
+    // Tests to ensure we cut large active regions in the right place
+    //
+    // -------------------------------------------------------------------------------------
+
+    private void addProb(final List<Double> l, final double v) {
+        l.add(v);
+    }
+
+    @DataProvider(name = "ActiveRegionCutTests")
+    public Object[][] makeActiveRegionCutTests() {
+        final List<Object[]> tests = new LinkedList<Object[]>();
+
+//        for ( final int activeRegionSize : Arrays.asList(30) ) {
+//            for ( final int minRegionSize : Arrays.asList(5) ) {
+        for ( final int activeRegionSize : Arrays.asList(10, 12, 20, 30, 40) ) {
+            for ( final int minRegionSize : Arrays.asList(1, 5, 10) ) {
+                final int maxRegionSize = activeRegionSize * 2 / 3;
+                if ( minRegionSize >= maxRegionSize ) continue;
+                { // test flat activity profile
+                    final List<Double> probs = Collections.nCopies(activeRegionSize, 1.0);
+                    tests.add(new Object[]{minRegionSize, maxRegionSize, maxRegionSize, probs});
+                }
+
+                { // test point profile is properly handled
+                    for ( int end = 1; end < activeRegionSize; end++ ) {
+                        final List<Double> probs = Collections.nCopies(end, 1.0);
+                        tests.add(new Object[]{minRegionSize, maxRegionSize, Math.min(end, maxRegionSize), probs});
+                    }
+                }
+
+                { // test increasing activity profile
+                    final List<Double> probs = new ArrayList<Double>(activeRegionSize);
+                    for ( int i = 0; i < activeRegionSize; i++ ) {
+                        addProb(probs, (1.0*(i+1))/ activeRegionSize);
+                    }
+                    tests.add(new Object[]{minRegionSize, maxRegionSize, maxRegionSize, probs});
+                }
+
+                { // test decreasing activity profile
+                    final List<Double> probs = new ArrayList<Double>(activeRegionSize);
+                    for ( int i = 0; i < activeRegionSize; i++ ) {
+                        addProb(probs, 1 - (1.0*(i+1))/ activeRegionSize);
+                    }
+                    tests.add(new Object[]{minRegionSize, maxRegionSize, maxRegionSize, probs});
+                }
+
+                { // test two peaks
+//                    for ( final double rootSigma : Arrays.asList(2.0) ) {
+//                        int maxPeak1 = 9; {
+//                            int maxPeak2 = 16; {
+                    for ( final double rootSigma : Arrays.asList(1.0, 2.0, 3.0) ) {
+                        for ( int maxPeak1 = 0; maxPeak1 < activeRegionSize / 2; maxPeak1++ ) {
+                            for ( int maxPeak2 = activeRegionSize / 2 + 1; maxPeak2 < activeRegionSize; maxPeak2++ ) {
+                                final double[] gauss1 = makeGaussian(maxPeak1, activeRegionSize, rootSigma);
+                                final double[] gauss2 = makeGaussian(maxPeak2, activeRegionSize, rootSigma+1);
+                                final List<Double> probs = new ArrayList<Double>(activeRegionSize);
+                                for ( int i = 0; i < activeRegionSize; i++ ) {
+                                    addProb(probs, gauss1[i] + gauss2[i]);
+                                }
+                                final int cutSite = findCutSiteForTwoMaxPeaks(probs, minRegionSize);
+                                if ( cutSite != -1 && cutSite < maxRegionSize )
+                                    tests.add(new Object[]{minRegionSize, maxRegionSize, Math.max(cutSite, minRegionSize), probs});
+                            }
+                        }
+                    }
+                }
+
+                { // test that the lowest of two minima is taken
+                    // looks like a bunch of 1s, 0.5, some 1.0s, 0.75, some more 1s
+//                    int firstMin = 0; {
+//                    int secondMin = 4; {
+                    for ( int firstMin = 1; firstMin < activeRegionSize; firstMin++ ) {
+                        for ( int secondMin = firstMin + 1; secondMin < activeRegionSize; secondMin++ ) {
+                            final List<Double> probs = new ArrayList<Double>(Collections.nCopies(activeRegionSize, 1.0));
+                            probs.set(firstMin, 0.5);
+                            probs.set(secondMin, 0.75);
+                            final int expectedCut;
+                            if ( firstMin + 1 < minRegionSize ) {
+                                if ( firstMin == secondMin - 1 ) // edge case for non-min at minRegionSize
+                                    expectedCut = maxRegionSize;
+                                else
+                                    expectedCut = secondMin + 1 > maxRegionSize ? maxRegionSize : ( secondMin + 1 < minRegionSize ? maxRegionSize : secondMin + 1);
+                            } else if ( firstMin + 1 > maxRegionSize )
+                                expectedCut = maxRegionSize;
+                            else {
+                                expectedCut = firstMin + 1;
+                            }
+
+                            Math.min(firstMin + 1, maxRegionSize);
+                            tests.add(new Object[]{minRegionSize, maxRegionSize, expectedCut, probs});
+                        }
+                    }
+                }
+            }
+        }
+
+        return tests.toArray(new Object[][]{});
+    }
+
+    private double[] makeGaussian(final int mean, final int range, final double sigma) {
+        final double[] gauss = new double[range];
+        for( int iii = 0; iii < range; iii++ ) {
+            gauss[iii] = MathUtils.normalDistribution(mean, sigma, iii) + ACTIVE_PROB_THRESHOLD;
+        }
+        return gauss;
+    }
+
+    private int findCutSiteForTwoMaxPeaks(final List<Double> probs, final int minRegionSize) {
+        for ( int i = probs.size() - 2; i > minRegionSize; i-- ) {
+            double prev = probs.get(i - 1);
+            double next = probs.get(i + 1);
+            double cur = probs.get(i);
+            if ( cur < next && cur < prev )
+                return i + 1;
+        }
+
+        return -1;
+    }
+
+    @Test(dataProvider = "ActiveRegionCutTests")
+    public void testActiveRegionCutTests(final int minRegionSize, final int maxRegionSize, final int expectedRegionSize, final List<Double> probs) {
+        final ActivityProfile profile = new ActivityProfile(genomeLocParser, MAX_PROB_PROPAGATION_DISTANCE, ACTIVE_PROB_THRESHOLD);
+
+        final String contig = genomeLocParser.getContigs().getSequences().get(0).getSequenceName();
+        for ( int i = 0; i <= maxRegionSize + profile.getMaxProbPropagationDistance(); i++ ) {
+            final GenomeLoc loc = genomeLocParser.createGenomeLoc(contig, i + 1);
+            final double prob = i < probs.size() ? probs.get(i) : 0.0;
+            final ActivityProfileState state = new ActivityProfileState(loc, prob);
+            profile.add(state);
+        }
+
+        final List<ActiveRegion> regions = profile.popReadyActiveRegions(0, minRegionSize, maxRegionSize, false);
+        Assert.assertTrue(regions.size() >= 1, "Should only be one regions for this test");
+        final ActiveRegion region = regions.get(0);
+        Assert.assertEquals(region.getLocation().getStart(), 1, "Region should start at 1");
+        Assert.assertEquals(region.getLocation().size(), expectedRegionSize, "Incorrect region size; cut must have been incorrect");
+    }
+}
\ No newline at end of file
diff --git a/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/utils/activeregion/BandPassActivityProfileUnitTest.java b/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/utils/activeregion/BandPassActivityProfileUnitTest.java
new file mode 100644
index 0000000..2087d9a
--- /dev/null
+++ b/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/utils/activeregion/BandPassActivityProfileUnitTest.java
@@ -0,0 +1,339 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.utils.activeregion;
+
+
+// the imports for unit testing.
+
+
+import htsjdk.samtools.reference.ReferenceSequenceFile;
+import org.apache.commons.lang.ArrayUtils;
+import htsjdk.tribble.readers.LineIterator;
+import org.broadinstitute.gatk.utils.BaseTest;
+import org.broadinstitute.gatk.utils.GenomeLoc;
+import org.broadinstitute.gatk.utils.GenomeLocParser;
+import org.broadinstitute.gatk.utils.MathUtils;
+import org.broadinstitute.gatk.utils.collections.Pair;
+import org.broadinstitute.gatk.utils.fasta.CachingIndexedFastaSequenceFile;
+import org.broadinstitute.gatk.utils.variant.GATKVCFUtils;
+import htsjdk.variant.variantcontext.VariantContext;
+import htsjdk.variant.vcf.VCFCodec;
+import htsjdk.variant.vcf.VCFHeader;
+import org.testng.Assert;
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.DataProvider;
+import org.testng.annotations.Test;
+
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.LinkedList;
+import java.util.List;
+
+
+public class BandPassActivityProfileUnitTest extends BaseTest {
+    private final static boolean DEBUG = false;
+    private GenomeLocParser genomeLocParser;
+
+    private final static int MAX_PROB_PROPAGATION_DISTANCE = 50;
+    private final static double ACTIVE_PROB_THRESHOLD= 0.002;
+
+    @BeforeClass
+    public void init() throws FileNotFoundException {
+        // sequence
+        ReferenceSequenceFile seq = new CachingIndexedFastaSequenceFile(new File(b37KGReference));
+        genomeLocParser = new GenomeLocParser(seq);
+    }
+
+    @DataProvider(name = "BandPassBasicTest")
+    public Object[][] makeBandPassTest() {
+        final List<Object[]> tests = new LinkedList<Object[]>();
+
+        for ( int start : Arrays.asList(1, 10, 100, 1000) ) {
+            for ( boolean precedingIsActive : Arrays.asList(true, false) ) {
+                for ( int precedingSites: Arrays.asList(0, 1, 10, 100) ) {
+                    for ( int bandPassSize : Arrays.asList(0, 1, 10, 100) ) {
+                        for ( double sigma : Arrays.asList(1.0, 2.0, BandPassActivityProfile.DEFAULT_SIGMA) ) {
+//        for ( int start : Arrays.asList(10) ) {
+//            for ( boolean precedingIsActive : Arrays.asList(false) ) {
+//                for ( int precedingSites: Arrays.asList(0) ) {
+//                    for ( int bandPassSize : Arrays.asList(1) ) {
+                            tests.add(new Object[]{ start, precedingIsActive, precedingSites, bandPassSize, sigma });
+                        }
+                    }
+                }
+            }
+        }
+
+        return tests.toArray(new Object[][]{});
+    }
+
+    @Test(enabled = ! DEBUG, dataProvider = "BandPassBasicTest")
+    public void testBandPass(final int start, final boolean precedingIsActive, final int nPrecedingSites, final int bandPassSize, final double sigma) {
+        final BandPassActivityProfile profile = new BandPassActivityProfile(genomeLocParser, null, MAX_PROB_PROPAGATION_DISTANCE, ACTIVE_PROB_THRESHOLD, bandPassSize, sigma, false);
+
+        final int expectedBandSize = bandPassSize * 2 + 1;
+        Assert.assertEquals(profile.getFilteredSize(), bandPassSize, "Wrong filter size");
+        Assert.assertEquals(profile.getSigma(), sigma, "Wrong sigma");
+        Assert.assertEquals(profile.getBandSize(), expectedBandSize, "Wrong expected band size");
+
+        final String contig = genomeLocParser.getContigs().getSequences().get(0).getSequenceName();
+        final double precedingProb = precedingIsActive ? 1.0 : 0.0;
+        for ( int i = 0; i < nPrecedingSites; i++ ) {
+            final GenomeLoc loc = genomeLocParser.createGenomeLoc(contig, i + start);
+            final ActivityProfileState state = new ActivityProfileState(loc, precedingProb);
+            profile.add(state);
+        }
+
+        final GenomeLoc nextLoc = genomeLocParser.createGenomeLoc(contig, nPrecedingSites + start);
+        profile.add(new ActivityProfileState(nextLoc, 1.0));
+
+        if ( precedingIsActive == false && nPrecedingSites >= bandPassSize && bandPassSize < start ) {
+            // we have enough space that all probs fall on the genome
+            final double[] probs = profile.getProbabilitiesAsArray();
+            Assert.assertEquals(MathUtils.sum(probs), 1.0 * (nPrecedingSites * precedingProb + 1), 1e-3, "Activity profile doesn't sum to number of non-zero prob states");
+        }
+    }
+
+    private double[] bandPassInOnePass(final BandPassActivityProfile profile, final double[] activeProbArray) {
+        final double[] bandPassProbArray = new double[activeProbArray.length];
+
+        // apply the band pass filter for activeProbArray into filteredProbArray
+        final double[] GaussianKernel = profile.getKernel();
+        for( int iii = 0; iii < activeProbArray.length; iii++ ) {
+            final double[] kernel = ArrayUtils.subarray(GaussianKernel, Math.max(profile.getFilteredSize() - iii, 0), Math.min(GaussianKernel.length, profile.getFilteredSize() + activeProbArray.length - iii));
+            final double[] activeProbSubArray = ArrayUtils.subarray(activeProbArray, Math.max(0,iii - profile.getFilteredSize()), Math.min(activeProbArray.length,iii + profile.getFilteredSize() + 1));
+            bandPassProbArray[iii] = dotProduct(activeProbSubArray, kernel);
+        }
+
+        return bandPassProbArray;
+    }
+
+    public static double dotProduct(double[] v1, double[] v2) {
+        Assert.assertEquals(v1.length,v2.length,"Array lengths do not mach in dotProduct");
+        double result = 0.0;
+        for (int k = 0; k < v1.length; k++)
+            result += v1[k] * v2[k];
+
+        return result;
+    }
+
+    @DataProvider(name = "BandPassComposition")
+    public Object[][] makeBandPassComposition() {
+        final List<Object[]> tests = new LinkedList<Object[]>();
+
+        for ( int bandPassSize : Arrays.asList(0, 1, 10, 100, BandPassActivityProfile.MAX_FILTER_SIZE) ) {
+            for ( int integrationLength : Arrays.asList(1, 10, 100, 1000) ) {
+                tests.add(new Object[]{ bandPassSize, integrationLength });
+            }
+        }
+
+        return tests.toArray(new Object[][]{});
+    }
+
+    @Test( enabled = ! DEBUG, dataProvider = "BandPassComposition")
+    public void testBandPassComposition(final int bandPassSize, final int integrationLength) {
+        final int start = 1;
+        final BandPassActivityProfile profile = new BandPassActivityProfile(genomeLocParser, null, MAX_PROB_PROPAGATION_DISTANCE,
+                ACTIVE_PROB_THRESHOLD, bandPassSize, BandPassActivityProfile.DEFAULT_SIGMA);
+        final double[] rawActiveProbs = new double[integrationLength + bandPassSize * 2];
+
+        // add a buffer so that we can get all of the band pass values
+        final String contig = genomeLocParser.getContigs().getSequences().get(0).getSequenceName();
+        int pos = start;
+        int rawProbsOffset = 0;
+        for ( int i = 0; i < bandPassSize; i++ ) {
+            final GenomeLoc loc = genomeLocParser.createGenomeLoc(contig, pos++);
+            final ActivityProfileState state = new ActivityProfileState(loc, 0.0);
+            profile.add(state);
+            rawActiveProbs[rawProbsOffset++] = 0.0;
+            rawActiveProbs[rawActiveProbs.length - rawProbsOffset] = 0.0;
+        }
+
+        for ( int i = 0; i < integrationLength; i++ ) {
+            final GenomeLoc nextLoc = genomeLocParser.createGenomeLoc(contig, pos++);
+            profile.add(new ActivityProfileState(nextLoc, 1.0));
+            rawActiveProbs[rawProbsOffset++] = 1.0;
+
+            for ( int j = 0; j < profile.size(); j++ ) {
+                Assert.assertTrue(profile.getStateList().get(j).isActiveProb >= 0.0, "State probability < 0 at " + j);
+                Assert.assertTrue(profile.getStateList().get(j).isActiveProb <= 1.0 + 1e-3, "State probability > 1 at " + j);
+            }
+        }
+
+        final double[] expectedProbs = bandPassInOnePass(profile, rawActiveProbs);
+        for ( int j = 0; j < profile.size(); j++ ) {
+            Assert.assertEquals(profile.getStateList().get(j).isActiveProb, expectedProbs[j], "State probability not expected at " + j);
+        }
+    }
+
+    // ------------------------------------------------------------------------------------
+    //
+    // Code to test the creation of the kernels
+    //
+    // ------------------------------------------------------------------------------------
+
+    /**
+
+     kernel <- function(sd, pThres) {
+     raw = dnorm(-80:81, mean=0, sd=sd)
+     norm = raw / sum(raw)
+     bad = norm < pThres
+     paste(norm[! bad], collapse=", ")
+     }
+
+     print(kernel(0.01, 1e-5))
+     print(kernel(1, 1e-5))
+     print(kernel(5, 1e-5))
+     print(kernel(17, 1e-5))
+
+     * @return
+     */
+
+    @DataProvider(name = "KernelCreation")
+    public Object[][] makeKernelCreation() {
+        final List<Object[]> tests = new LinkedList<Object[]>();
+
+        tests.add(new Object[]{ 0.01, 1000, new double[]{1.0}});
+        tests.add(new Object[]{ 1.0, 1000, new double[]{0.0001338302, 0.004431848, 0.053990966, 0.241970723, 0.398942278, 0.241970723, 0.053990966, 0.004431848, 0.0001338302}});
+        tests.add(new Object[]{ 1.0, 0, new double[]{1.0}});
+        tests.add(new Object[]{ 1.0, 1, new double[]{0.2740686, 0.4518628, 0.2740686}});
+        tests.add(new Object[]{ 1.0, 2, new double[]{0.05448868, 0.24420134, 0.40261995, 0.24420134, 0.05448868}});
+        tests.add(new Object[]{ 1.0, 1000, new double[]{0.0001338302, 0.004431848, 0.053990966, 0.241970723, 0.398942278, 0.241970723, 0.053990966, 0.004431848, 0.0001338302}});
+        tests.add(new Object[]{ 5.0, 1000, new double[]{1.1788613551308e-05, 2.67660451529771e-05, 5.83893851582921e-05, 0.000122380386022754, 0.000246443833694604, 0.000476817640292968, 0.000886369682387602, 0.00158309031659599, 0.00271659384673712, 0.00447890605896858, 0.00709491856924629, 0.0107981933026376, 0.0157900316601788, 0.0221841669358911, 0.029945493127149, 0.0388372109966426, 0.0483941449038287, 0.0579383105522965, 0.0666449205783599, 0.0736540280606647, 0.0782085387950912,  [...]
+        tests.add(new Object[]{17.0, 1000, new double[]{1.25162575710745e-05, 1.57001772728555e-05, 1.96260034693739e-05, 2.44487374842009e-05, 3.03513668801384e-05, 3.75489089511911e-05, 4.62928204154855e-05, 5.68757597480354e-05, 6.96366758708924e-05, 8.49661819944029e-05, 0.000103312156275406, 0.000125185491708561, 0.000151165896477646, 0.000181907623161359, 0.000218144981137171, 0.000260697461819069, 0.000310474281706066, 0.000368478124457557, 0.000435807841336874, 0.0005136598504885 [...]
+
+        return tests.toArray(new Object[][]{});
+    }
+
+    @Test( enabled = ! DEBUG, dataProvider = "KernelCreation")
+    public void testKernelCreation(final double sigma, final int maxSize, final double[] expectedKernel) {
+        final BandPassActivityProfile profile = new BandPassActivityProfile(genomeLocParser, null, MAX_PROB_PROPAGATION_DISTANCE, ACTIVE_PROB_THRESHOLD,
+                maxSize, sigma, true);
+
+        final double[] kernel = profile.getKernel();
+        Assert.assertEquals(kernel.length, expectedKernel.length);
+        for ( int i = 0; i < kernel.length; i++ )
+            Assert.assertEquals(kernel[i], expectedKernel[i], 1e-3, "Kernels not equal at " + i);
+    }
+
+    // ------------------------------------------------------------------------------------
+    //
+    // Large-scale test, reading in 1000G Phase I chr20 calls and making sure that
+    // the regions returned are the same if you run on the entire profile vs. doing it
+    // incremental
+    //
+    // ------------------------------------------------------------------------------------
+
+    @DataProvider(name = "VCFProfile")
+    public Object[][] makeVCFProfile() {
+        final List<Object[]> tests = new LinkedList<Object[]>();
+
+        //tests.add(new Object[]{ privateTestDir + "ALL.chr20.phase1_release_v3.20101123.snps_indels_svs.sites.vcf", "20", 60470, 61000});
+        //tests.add(new Object[]{ privateTestDir + "ALL.chr20.phase1_release_v3.20101123.snps_indels_svs.sites.vcf", "20", 60470, 100000});
+        //tests.add(new Object[]{ privateTestDir + "ALL.chr20.phase1_release_v3.20101123.snps_indels_svs.sites.vcf", "20", 60470, 1000000});
+        tests.add(new Object[]{ privateTestDir + "ALL.chr20.phase1_release_v3.20101123.snps_indels_svs.sites.vcf", "20", 60470, 1000000});
+        tests.add(new Object[]{ privateTestDir + "NA12878.WGS.b37.chr20.firstMB.vcf", "20", 1, 1000000});
+
+        return tests.toArray(new Object[][]{});
+    }
+
+    @Test( dataProvider = "VCFProfile")
+    public void testVCFProfile(final String path, final String contig, final int start, final int end) throws Exception {
+        final int extension = 50;
+        final int minRegionSize = 50;
+        final int maxRegionSize = 300;
+
+        final File file = new File(path);
+        final VCFCodec codec = new VCFCodec();
+        final Pair<VCFHeader, GATKVCFUtils.VCIterable<LineIterator>> reader = GATKVCFUtils.readAllVCs(file, codec);
+
+        final List<ActiveRegion> incRegions = new ArrayList<ActiveRegion>();
+        final BandPassActivityProfile incProfile = new BandPassActivityProfile(genomeLocParser, null, MAX_PROB_PROPAGATION_DISTANCE, ACTIVE_PROB_THRESHOLD);
+        final BandPassActivityProfile fullProfile = new BandPassActivityProfile(genomeLocParser, null, MAX_PROB_PROPAGATION_DISTANCE, ACTIVE_PROB_THRESHOLD);
+        int pos = start;
+        for ( final VariantContext vc : reader.getSecond() ) {
+            if ( vc == null ) continue;
+            while ( pos < vc.getStart() ) {
+                final GenomeLoc loc = genomeLocParser.createGenomeLoc(contig, pos);
+                //logger.warn("Adding 0.0 at " + loc + " because vc.getStart is " + vc.getStart());
+                incProfile.add(new ActivityProfileState(loc, 0.0));
+                fullProfile.add(new ActivityProfileState(loc, 0.0));
+                pos++;
+            }
+            if ( vc.getStart() >= start && vc.getEnd() <= end ) {
+                final GenomeLoc loc = genomeLocParser.createGenomeLoc(contig, pos);
+                //logger.warn("Adding 1.0 at " + loc);
+                ActivityProfileState.Type type = ActivityProfileState.Type.NONE;
+                Number value = null;
+                if ( vc.isBiallelic() && vc.isIndel() ) {
+                    type = ActivityProfileState.Type.HIGH_QUALITY_SOFT_CLIPS;
+                    value = Math.abs(vc.getIndelLengths().get(0));
+                }
+                final ActivityProfileState state = new ActivityProfileState(loc, 1.0, type, value);
+                incProfile.add(state);
+                fullProfile.add(state);
+                pos++;
+            }
+
+            incRegions.addAll(incProfile.popReadyActiveRegions(extension, minRegionSize, maxRegionSize, false));
+
+            if ( vc.getStart() > end )
+                break;
+        }
+
+        incRegions.addAll(incProfile.popReadyActiveRegions(extension, minRegionSize, maxRegionSize, true));
+
+        final List<ActiveRegion> fullRegions = fullProfile.popReadyActiveRegions(extension, minRegionSize, maxRegionSize, true);
+        assertGoodRegions(fullRegions, start, end, maxRegionSize);
+        assertGoodRegions(incRegions, start, end, maxRegionSize);
+
+        Assert.assertEquals(incRegions.size(),  fullRegions.size(), "incremental and full region sizes aren't the same");
+        for ( int i = 0; i < fullRegions.size(); i++ ) {
+            final ActiveRegion incRegion = incRegions.get(i);
+            final ActiveRegion fullRegion = fullRegions.get(i);
+            Assert.assertTrue(incRegion.equalExceptReads(fullRegion), "Full and incremental regions are not equal: full = " + fullRegion + " inc = " + incRegion);
+        }
+    }
+
+    private void assertGoodRegions(final List<ActiveRegion> regions, final int start, final int end, final int maxRegionSize) {
+        int lastPosSeen = start - 1;
+        for ( int regionI = 0; regionI < regions.size(); regionI++ ) {
+            final ActiveRegion region = regions.get(regionI);
+            Assert.assertEquals(region.getLocation().getStart(), lastPosSeen + 1, "discontinuous with previous region.  lastPosSeen " + lastPosSeen + " but region is " + region);
+            Assert.assertTrue(region.getLocation().size() <= maxRegionSize, "Region is too big: " + region);
+            lastPosSeen = region.getLocation().getStop();
+
+            for ( final ActivityProfileState state : region.getSupportingStates() ) {
+                Assert.assertEquals(state.isActiveProb > ACTIVE_PROB_THRESHOLD, region.isActive(),
+                        "Region is active=" + region.isActive() + " but contains a state " + state + " with prob "
+                                + state.isActiveProb + " not within expected values given threshold for activity of "
+                                + ACTIVE_PROB_THRESHOLD);
+            }
+        }
+    }
+}
diff --git a/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/utils/baq/BAQUnitTest.java b/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/utils/baq/BAQUnitTest.java
new file mode 100644
index 0000000..7ea26ee
--- /dev/null
+++ b/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/utils/baq/BAQUnitTest.java
@@ -0,0 +1,257 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.utils.baq;
+
+
+import org.broadinstitute.gatk.utils.exceptions.UserException;
+import org.testng.Assert;
+import org.testng.annotations.Test;
+import org.testng.annotations.DataProvider;
+import org.testng.annotations.BeforeMethod;
+import org.broadinstitute.gatk.utils.BaseTest;
+import org.broadinstitute.gatk.utils.sam.ArtificialSAMUtils;
+import org.broadinstitute.gatk.utils.Utils;
+
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.PrintStream;
+import java.util.List;
+import java.util.ArrayList;
+
+import htsjdk.samtools.reference.IndexedFastaSequenceFile;
+import htsjdk.samtools.*;
+
+/**
+ * Basic unit test for BAQ calculation
+ */
+public class BAQUnitTest extends BaseTest {
+    private SAMFileHeader header;
+    private final int startChr = 1;
+    private final int numChr = 2;
+    private final int chrSize = 1000;
+    IndexedFastaSequenceFile fasta = null;
+
+    @BeforeMethod
+    public void before() {
+        header = ArtificialSAMUtils.createArtificialSamHeader(numChr, startChr, chrSize);
+        File referenceFile = new File(hg18Reference);
+        try {
+            fasta = new IndexedFastaSequenceFile(referenceFile);
+        }
+        catch(FileNotFoundException ex) {
+            throw new UserException.CouldNotReadInputFile(referenceFile,ex);
+        }
+    }
+
+    private class BAQTest {
+        String readBases, refBases;
+        byte[] quals, expected;
+        String cigar;
+        int refOffset;
+        int pos;
+
+        public BAQTest(String _refBases, String _readBases, String _quals, String _expected) {
+            this(0, -1, null, _readBases, _refBases, _quals, _expected);
+        }
+
+        public BAQTest(int refOffset, String _refBases, String _readBases, String _quals, String _expected) {
+            this(refOffset, -1, null, _refBases, _readBases, _quals, _expected);
+        }
+
+        public BAQTest(long pos, String cigar, String _readBases, String _quals, String _expected) {
+            this(0, pos, cigar, null, _readBases, _quals, _expected);
+        }
+
+
+        public BAQTest(int _refOffset, long _pos, String _cigar, String _refBases, String _readBases, String _quals, String _expected) {
+            refOffset = _refOffset;
+            pos = (int)_pos;
+            cigar = _cigar;
+            readBases = _readBases;
+            refBases = _refBases;
+
+            quals = new byte[_quals.getBytes().length];
+            expected = new byte[_quals.getBytes().length];
+            for ( int i = 0; i < quals.length; i++) {
+                quals[i] = (byte)(_quals.getBytes()[i] - 33);
+                expected[i] = (byte)(_expected.getBytes()[i] - 33);
+            }
+        }
+
+        public String toString() { return readBases; }
+
+        public SAMRecord createRead() {
+            SAMRecord read = ArtificialSAMUtils.createArtificialRead(header, "foo", 0, pos > 0 ? pos + (refOffset > 0 ? refOffset : 0): 1, readBases.getBytes(), quals);
+            //if ( cigar != null ) read.setAlignmentEnd(readBases.getBytes().length + pos);
+            read.setCigarString( cigar == null ? String.format("%dM", quals.length) : cigar);
+            return read;
+        }
+    }
+
+
+    @DataProvider(name = "data")
+    public Object[][] createData1() {
+        List<BAQTest> params = new ArrayList<BAQTest>();
+
+        params.add(new BAQTest("GCTGCTCCTGGTACTGCTGGATGAGGGCCTCGATGAAGCTAAGCTTTTTCTCCTGCTCCTGCGTGATCCGCTGCAG",
+                               "GCTGCTCCTGGTACTGCTGGATGAGGGCCTCGATGAAGCTAAGCTTTTCCTCCTGCTCCTGCGTGATCCGCTGCAG",
+                               "?BACCBDDDFFBCFFHHFIHFEIFHIGHHGHBFEIFGIIGEGIIHGGGIHHIIHIIHIIHGICCIGEII at IGIHCG",
+                               "?BACCBDDDFFBCFFHHFIHFEIFHIGHHGHBFEIFGIIGEGII410..0HIIHIIHIIHGICCIGEII at IGIHCE"));
+
+        params.add(new BAQTest("GCTTTTTCTCCTCCTG",
+                               "GCTTTTCCTCCTCCTG",
+                               "IIHGGGIHHIIHHIIH",
+                               "EI410..0HIIHHIIE"));
+
+        // big and complex, also does a cap from 3 to 4!
+        params.add(new BAQTest(-3, 9999810l, "49M1I126M1I20M1I25M",
+                                "AAATTCAAGATTTCAAAGGCTCTTAACTGCTCAAGATAATTTTTTTTTTTTGAGACAGAGTCTTGCTGTGTTGCCCAGGCTGGAGTGCAGTGGCGTGATCTTGGCTCACTGCAAGCTCCGCCTCCCGGGTTCACGCCATTCTCCTGCCTCAGCCTCCCGAGTAGCTGGGACTACAGGCACCCACCACCACGCCTGGCCAATTTTTTTGTATTTTTAGTAGAGATAG",
+                                "TTCAAGATTTCAAAGGCTCTTAACTGCTCAAGATAATTTTTTTTTTTTGTAGACAGAGTCTTGCTGTGTTGCCCAGGCTGGAGTGCAGTGGCGTGATCTTGGCTCACTGCAAGCTCCGCCTCCCGGGTTCACGCCATTCTCCTGCCTCAGCCTCCCGAGTAGCTGGGACTACAGGCCACCCACCACCACGCCTGGCCTAATTTTTTTGTATTTTTAGTAGAGA",
+                                ">IHFECEBDBBCBCABABAADBD?AABBACEABABC?>?B>@A@@>A?B3BBC?CBDBAABBBBBAABAABBABDACCCBCDAACBCBABBB:ABDBACBBDCCCCABCDCCBCC@@;?<B at BC;CBBBAB=;A>ACBABBBABBCA@@<?>>AAA<CA at AABBABCC?BB8@<@C<>5;<A5=A;>=64>???B>=6497<<;;<;>2?>BA@??A6<<A59",
+                                ">EHFECEBDBBCBCABABAADBD?AABBACEABABC?>?B>@A@@>A?838BC?CBDBAABBBBBAABAABBABDACCCBCDAACBCBABBB:ABDBACBBDCCCCABCDCCBCC@@;?<B at BC;CBBBAB=;A>ACBABBBABBCA@@<?>>AAA<CA at AABBABCC?BB8@<@%<>5;<A5=A;>=64>???B;86497<<;;<;>2?>BA@??A6<<A59"));
+
+        // now changes
+        params.add(new BAQTest(-3, 9999966l, "36M",
+                                "CCGAGTAGCTGGGACTACAGGCACCCACCACCACGCCTGGCC",
+                                "AGTAGCTGGGACTACAGGCACCCACCACCACGCCTG",
+                                "A?>>@>AA?@@>A?>A@?>@>>?=>?'>?=>7=?A9",
+                                "A?>>@>AA?@@>A?>A@?>@>>?=>?'>?=>7=?A9"));
+
+        // raw base qualities are low -- but they shouldn't be capped
+        params.add(new BAQTest(-3, 9999993l, "36M",
+                                "CCACCACGCCTGGCCAATTTTTTTGTATTTTTAGTAGAGATA",
+                                "CCACGCTTGGCAAAGTTTTCCGTACGTTTAGCCGAG",
+                                "33'/(7+270&4),(&&-)$&,%7$',-/61(,6?8",
+                                "33'/(7+270&4),(&&-)$&,%7$',-/61(,6?8"));
+
+        // soft clipping
+        // todo soft clip testing just doesn't work right now!
+
+//        params.add(new BAQTest(29, 10000109l, "29S190M",
+//                                null, "GAAGGTTGAATCAAACCTTCGGTTCCAACGGATTACAGGTGTGAGCCACCGCGACCGGCCTGCTCAAGATAATTTTTAGGGCTAACTATGACATGAACCCCAAAATTCCTGTCCTCTAGATGGCAGAAACCAAGATAAAGTATCCCCACATGGCCACAAGGTTAAGCTCTTATGGACACAAAACAAGGCAGAGAAATGTCATTTGGCATTGGTTTCAGG",
+//                                "3737088:858278273772:3<=;:?;5=9@>@?>@=<>8?>@=>>?>4=5>?=5====A==@?A@=@6 at A><?B:A;:;>@A?>?AA>@?AA>A?>==?AAA@@A>=A<A>>A=?A>AA==@A?AA?>?AA?A@@C@:?A@<;::??AA==>@@?BB=<A?BA>>A>A?AB=???@?BBA@?BA==?A>A?BB=A:@?ABAB>>?ABB>8A at BAIGA",
+//                                "3737088:858278273772:3<=;:?;5=9@>@?>@=<>8?>@=>>?>4=5>?=5====A==@?A@=@6 at A><?B:A;:;>@A?>?AA>@?AA>A?>==?AAA@@A>=A<A>>A=?A>AA==@A?AA?>?AA?A@@C@:?A@<;::??AA==>@@?BB=<A?BA>>A>A?AB=???@?BBA@?BA==?A>A?BB=A:@?ABAB>>?ABB>8A at BAI>;"));
+
+//        params.add(new BAQTest(30, 10000373l, "30S69M1D2M",
+//                                null, "TGAAATCCTGCCTTATAGTTCCCCTAAACCCACGTTCTATCCCCAGATACTCCCCTCTTCATTACAGAACAACAAAGAAAGACAAATTCTTAGCATCAATG",
+//                                "###############################=89>B;6<;96*>.1799>++66=:=:8=<-.9>><;9<':-+;*+::=;8=;;.::<:;=/2=70<=?-",
+//                                "###############################=89>B;6<;96*>.1799>++66=:=:8=<-.9>><;9<':-+;*+::=;8=;;.::<:;=/2=7000%%"));
+
+
+//        params.add(new BAQTest(5, 10000109l, "5S5M",
+//                                "GAAGGTTGAA",
+//                                null,
+//                                "HHHHHHHHHH",
+//                                "HHHHHHHHHE"));
+
+//        params.add(new BAQTest(10009480l, "102M1I18M1I16M1I43M1I10M1D9M1I7M1I7M1I16M1I9M1I8M1I14M2I18M",
+//                                "AGAGATGGGGTTTCGCCATGTTGTCCAGGCTGGTCTTGAACTCCTGACCTCAAGTGATCTGCCCACCTCGGCCTCCCAAAGTGCTGGGATTACACGTGTGAAACCACCATGCCTGGTCTCTTAATTTTTCNGATTCTAATAAAATTACATTCTATTTGCTGAAAGNGTACTTTAGAGTTGAAAGAAAAAGAAAGGNGTGGAACTTCCCCTAGTAAACAAGGAAAAACNTCCATGTTATTTATTGGACCTTAAAAATAGTGAAACATCTTAAGAAAAAAAATCAATCCTA",
+//                                "@HI at BA<?C@?CA>7>=AA>9@==??C???@?>:?BB at BA>B?=A@@<=B?AB???@@@@@?=?A==B at 7<<?@>==>=<=>???>=@@A?<=B:5?413577/675;><;==@=<>>968;6;>????:#;=?>:3072077726/6;3719;9A=9;774771#30532676??=8::97<7144448/4425#65688821515986255/5601548355551#218>96/5/8<4/.2344/914/55553)1047;:30312:4:63556565631=:62610",
+//                                "@HI at BA<?C@?CA>7>=AA>9@==??C???@?>:?BB at BA>B?=A@@<=B?AB???@@@@@?=?A==B at 7<<?@>==>=<=>???>=@@A?<=B:5?413&!7/675;><;==@=<>>96!;6;>????:#;=?>:3!72077726/6;3719;9A=9;774771#30532676??=8::&!<7144448'$!25#65687421515986255/560!548355551#218>96!5/8<4/.2344/614(%!!53)1047;:30312:4:63556565631=:62610"));
+
+        List<Object[]> params2 = new ArrayList<Object[]>();
+        for ( BAQTest x : params ) params2.add(new Object[]{x});
+        return params2.toArray(new Object[][]{});
+    }
+
+
+
+    @Test(dataProvider = "data", enabled = true)
+    public void testBAQWithProvidedReference(BAQTest test) {
+        if ( test.refBases != null ) {
+            testBAQ(test, false);
+        }
+    }
+
+    @Test(dataProvider = "data", enabled = true)
+    public void testBAQWithCigarAndRefLookup(BAQTest test) {
+        if ( test.cigar != null ) {
+            testBAQ(test, true);
+        }
+    }
+
+    @Test(enabled = true)
+    public void testBAQQualRange() {
+        BAQ baq = new BAQ(1e-3, 0.1, 7, (byte)4, false);         // matches current samtools parameters
+        final byte ref = (byte)'A';
+        final byte alt = (byte)'A';
+
+        for ( int i = 0; i <= SAMUtils.MAX_PHRED_SCORE; i++ )
+            Assert.assertTrue(baq.calcEpsilon( ref, alt, (byte)i) >= 0.0, "Failed to get baq epsilon range");
+    }
+
+    @Test(enabled = true)
+    public void testBAQOverwritesExistingTagWithNull() {
+
+        // create a read with a single base off the end of the contig, which cannot be BAQed
+        final SAMRecord read = ArtificialSAMUtils.createArtificialRead(header, "foo", 0, fasta.getSequenceDictionary().getSequence("chr1").getSequenceLength() + 1, 1);
+        read.setReadBases(new byte[] {(byte) 'A'});
+        read.setBaseQualities(new byte[] {(byte) 20});
+        read.setCigarString("1M");
+        read.setAttribute("BQ", "A");
+
+        // try to BAQ and tell it to RECALCULATE AND ADD_TAG
+        BAQ baq = new BAQ(1e-3, 0.1, 7, (byte)4, false);
+        baq.baqRead(read, fasta, BAQ.CalculationMode.RECALCULATE, BAQ.QualityMode.ADD_TAG);
+
+        // did we remove the existing tag?
+        Assert.assertTrue(read.getAttribute("BQ") == null);
+    }
+
+    public void testBAQ(BAQTest test, boolean lookupWithFasta) {
+        BAQ baqHMM = new BAQ(1e-3, 0.1, 7, (byte)4, false);         // matches current samtools parameters
+
+        SAMRecord read = test.createRead();
+        BAQ.BAQCalculationResult result;
+        if ( lookupWithFasta && test.cigar != null )
+            result = baqHMM.calcBAQFromHMM(read, fasta);
+        else
+            result = baqHMM.calcBAQFromHMM(read, test.refBases.getBytes(), test.refOffset);
+
+        System.out.println(Utils.dupString('-', 40));
+        System.out.println("reads   : " + new String(test.readBases));
+        printQuals(System.out, "in-quals:", test.quals, false);
+        printQuals(System.out, "bq-quals:", result.bq, false);
+        for (int i = 0; i < test.quals.length; i++) {
+            //result.bq[i] = baqHMM.capBaseByBAQ(result.rawQuals[i], result.bq[i], result.state[i], i);
+            Assert.assertTrue(result.bq[i] >= baqHMM.getMinBaseQual() || test.expected[i] < baqHMM.getMinBaseQual(), "BQ < min base quality");
+            Assert.assertEquals(result.bq[i], test.expected[i], "Did not see the expected BAQ value at " + i);
+        }
+
+    }
+
+    public final static void printQuals( PrintStream out, String prefix, byte[] quals, boolean asInt ) {
+        out.print(prefix);
+        for ( int i = 0; i < quals.length; i++) {
+            if ( asInt ) {
+                out.printf("%2d", (int)quals[i]);
+                if ( i+1 != quals.length ) out.print(",");
+            } else
+                out.print((char)(quals[i]+33));
+        }
+        out.println();
+    }
+}
\ No newline at end of file
diff --git a/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/utils/classloader/JVMUtilsUnitTest.java b/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/utils/classloader/JVMUtilsUnitTest.java
new file mode 100644
index 0000000..c232e1c
--- /dev/null
+++ b/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/utils/classloader/JVMUtilsUnitTest.java
@@ -0,0 +1,75 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.utils.classloader;
+
+import org.testng.Assert;
+import org.testng.annotations.DataProvider;
+import org.testng.annotations.Test;
+
+public class JVMUtilsUnitTest {
+
+    // Test classes used by the tests for JVMUtils.getCallingClass():
+    private static class DummyTestClass1 {
+        public static Class getCaller( final Class callee ) {
+            return DummyTestClass2.getCaller(callee);
+        }
+    }
+
+    private static class DummyTestClass2 {
+        public static Class getCaller( final Class callee ) {
+            return DummyTestClass3.getCaller(callee);
+        }
+    }
+
+    private static class DummyTestClass3 {
+        public static Class getCaller( final Class callee ) {
+            return JVMUtils.getCallingClass(callee);
+        }
+    }
+
+    @DataProvider( name = "TestGetCallingClassDataProvider" )
+    public Object[][] getTestCallingClassTestData() {
+        return new Object[][] {
+            { DummyTestClass1.class, JVMUtilsUnitTest.class },
+            { DummyTestClass2.class, DummyTestClass1.class },
+            { DummyTestClass3.class, DummyTestClass2.class }
+        };
+    }
+
+    @Test( dataProvider = "TestGetCallingClassDataProvider" )
+    public void testGetCallingClass( final Class callee, final Class expectedCaller ) {
+        final Class reportedCaller = DummyTestClass1.getCaller(callee);
+
+        Assert.assertEquals(reportedCaller, expectedCaller,
+                            String.format("Wrong calling class returned from DummyTestClass1.getCaller(%s)", callee.getSimpleName()));
+    }
+
+    @Test( expectedExceptions = IllegalArgumentException.class )
+    public void testGetCallingClassCalleeNotFound() {
+        // Trying to get the calling class of a class not on the runtime stack should produce an exception.
+        JVMUtils.getCallingClass(DummyTestClass1.class);
+    }
+}
diff --git a/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/utils/clipping/ReadClipperTestUtils.java b/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/utils/clipping/ReadClipperTestUtils.java
new file mode 100644
index 0000000..8ce0a9e
--- /dev/null
+++ b/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/utils/clipping/ReadClipperTestUtils.java
@@ -0,0 +1,144 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.utils.clipping;
+
+import htsjdk.samtools.Cigar;
+import htsjdk.samtools.CigarElement;
+import htsjdk.samtools.CigarOperator;
+import htsjdk.samtools.TextCigarCodec;
+import org.broadinstitute.gatk.utils.Utils;
+import org.broadinstitute.gatk.utils.sam.ArtificialSAMUtils;
+import org.broadinstitute.gatk.utils.sam.CigarUtils;
+import org.broadinstitute.gatk.utils.sam.GATKSAMRecord;
+import org.testng.Assert;
+
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Stack;
+
+public class ReadClipperTestUtils {
+    //Should contain all the utils needed for tests to mass produce
+    //reads, cigars, and other needed classes
+
+    final static byte [] BASES = {'A', 'C', 'T', 'G'};
+    final static byte [] QUALS = {2, 15, 25, 30};
+    final static String CIGAR = "4M";
+    final static CigarElement[] cigarElements = { new CigarElement(1, CigarOperator.HARD_CLIP),
+                                                  new CigarElement(1, CigarOperator.SOFT_CLIP),
+                                                  new CigarElement(1, CigarOperator.INSERTION),
+                                                  new CigarElement(1, CigarOperator.DELETION),
+                                                  new CigarElement(1, CigarOperator.MATCH_OR_MISMATCH)};
+
+
+    public static GATKSAMRecord makeReadFromCigar(Cigar cigar) {
+        return ArtificialSAMUtils.createArtificialRead(Utils.arrayFromArrayWithLength(BASES, cigar.getReadLength()), Utils.arrayFromArrayWithLength(QUALS, cigar.getReadLength()), cigar.toString());
+    }
+
+    public static GATKSAMRecord makeReadFromCigar(String cigarString) {
+        return makeReadFromCigar(CigarUtils.cigarFromString(cigarString));
+    }
+
+    public static List<Cigar> generateCigarList(int maximumLength) {
+        return generateCigarList(maximumLength, cigarElements);
+    }
+
+        /**
+        * This function generates every valid permutation of cigar strings (with a given set of cigarElement) with a given length.
+        *
+        * A valid cigar object obeys the following rules:
+        *  - No Hard/Soft clips in the middle of the read
+        *  - No deletions in the beginning / end of the read
+        *  - No repeated adjacent element (e.g. 1M2M -> this should be 3M)
+        *  - No consecutive I/D elements
+        *
+        * @param maximumLength the maximum number of elements in the cigar
+        * @return a list with all valid Cigar objects
+        */
+    public static List<Cigar> generateCigarList(int maximumLength, CigarElement[] cigarElements) {
+        int numCigarElements = cigarElements.length;
+        LinkedList<Cigar> cigarList = new LinkedList<Cigar>();
+        byte [] cigarCombination = new byte[maximumLength];
+
+        Utils.fillArrayWithByte(cigarCombination, (byte) 0);               // we start off with all 0's in the combination array.
+        int currentIndex = 0;
+        while (true) {
+            Cigar cigar = createCigarFromCombination(cigarCombination, cigarElements);    // create the cigar
+            cigar = CigarUtils.combineAdjacentCigarElements(cigar);                   // combine adjacent elements
+            if (CigarUtils.isCigarValid(cigar)) {                                     // check if it's valid
+                cigarList.add(cigar);                                      // add it
+            }
+
+            boolean currentIndexChanged = false;
+            while (currentIndex < maximumLength && cigarCombination[currentIndex] == numCigarElements - 1) {
+                currentIndex++;                                            // find the next index to increment
+                currentIndexChanged = true;                                // keep track of the fact that we have changed indices!
+            }
+
+            if (currentIndex == maximumLength)                             // if we hit the end of the array, we're done.
+                break;
+
+            cigarCombination[currentIndex]++;                              // otherwise advance the current index
+
+            if (currentIndexChanged) {                                     // if we have changed index, then...
+                for (int i = 0; i < currentIndex; i++)
+                    cigarCombination[i] = 0;                               // reset everything from 0->currentIndex
+                currentIndex = 0;                                          // go back to the first index
+            }
+        }
+
+        return cigarList;
+    }
+
+    private static Cigar createCigarFromCombination(byte[] cigarCombination, CigarElement[] cigarElements) {
+        Cigar cigar = new Cigar();
+        for (byte i : cigarCombination) {
+            cigar.add(cigarElements[i]);
+        }
+        return cigar;
+    }
+
+    public static GATKSAMRecord makeRead() {
+        return ArtificialSAMUtils.createArtificialRead(BASES, QUALS, CIGAR);
+    }
+
+    /**
+     * Asserts that the two reads have the same bases, qualities and cigar strings
+     *
+     * @param actual the calculated read
+     * @param expected the expected read
+     */
+    public static void assertEqualReads(GATKSAMRecord actual, GATKSAMRecord expected) {
+        // If they're both not empty, test their contents
+        if(!actual.isEmpty() && !expected.isEmpty()) {
+            Assert.assertEquals(actual.getReadBases(), expected.getReadBases());
+            Assert.assertEquals(actual.getBaseQualities(), expected.getBaseQualities());
+            Assert.assertEquals(actual.getCigarString(), expected.getCigarString());
+        }
+        // Otherwise test if they're both empty
+        else
+            Assert.assertEquals(actual.isEmpty(), expected.isEmpty());
+     }
+}
diff --git a/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/utils/clipping/ReadClipperUnitTest.java b/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/utils/clipping/ReadClipperUnitTest.java
new file mode 100644
index 0000000..400e984
--- /dev/null
+++ b/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/utils/clipping/ReadClipperUnitTest.java
@@ -0,0 +1,421 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.utils.clipping;
+
+import htsjdk.samtools.Cigar;
+import htsjdk.samtools.CigarElement;
+import htsjdk.samtools.CigarOperator;
+import org.broadinstitute.gatk.utils.BaseTest;
+import org.broadinstitute.gatk.utils.Utils;
+import org.broadinstitute.gatk.utils.sam.CigarUtils;
+import org.broadinstitute.gatk.utils.sam.GATKSAMRecord;
+import org.testng.Assert;
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.DataProvider;
+import org.testng.annotations.Test;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.List;
+
+/**
+ * User: roger
+ * Date: 9/28/11
+ */
+public class ReadClipperUnitTest extends BaseTest {
+    private final static boolean DEBUG = false;
+
+    List<Cigar> cigarList;
+    int maximumCigarSize = 10;                                                                                           // 6 is the minimum necessary number to try all combinations of cigar types with guarantee of clipping an element with length = 2
+
+    @BeforeClass
+    public void init() {
+        cigarList = ReadClipperTestUtils.generateCigarList(maximumCigarSize);
+    }
+
+    @Test(enabled = !DEBUG)
+    public void testHardClipBothEndsByReferenceCoordinates() {
+        for (Cigar cigar : cigarList) {
+            GATKSAMRecord read = ReadClipperTestUtils.makeReadFromCigar(cigar);
+            int alnStart = read.getAlignmentStart();
+            int alnEnd = read.getAlignmentEnd();
+            int readLength = alnStart - alnEnd;
+            for (int i = 0; i < readLength / 2; i++) {
+                GATKSAMRecord clippedRead = ReadClipper.hardClipBothEndsByReferenceCoordinates(read, alnStart + i, alnEnd - i);
+                Assert.assertTrue(clippedRead.getAlignmentStart() >= alnStart + i, String.format("Clipped alignment start is less than original read (minus %d): %s -> %s", i, read.getCigarString(), clippedRead.getCigarString()));
+                Assert.assertTrue(clippedRead.getAlignmentEnd() <= alnEnd + i, String.format("Clipped alignment end is greater than original read (minus %d): %s -> %s", i, read.getCigarString(), clippedRead.getCigarString()));
+                assertUnclippedLimits(read, clippedRead);
+            }
+        }
+    }
+
+    @Test(enabled = !DEBUG)
+    public void testHardClipByReadCoordinates() {
+        for (Cigar cigar : cigarList) {
+            GATKSAMRecord read = ReadClipperTestUtils.makeReadFromCigar(cigar);
+            int readLength = read.getReadLength();
+            for (int i = 0; i < readLength; i++) {
+                GATKSAMRecord clipLeft = ReadClipper.hardClipByReadCoordinates(read, 0, i);
+                Assert.assertTrue(clipLeft.getReadLength() <= readLength - i, String.format("Clipped read length is greater than original read length (minus %d): %s -> %s", i, read.getCigarString(), clipLeft.getCigarString()));
+                assertUnclippedLimits(read, clipLeft);
+
+                GATKSAMRecord clipRight = ReadClipper.hardClipByReadCoordinates(read, i, readLength - 1);
+                Assert.assertTrue(clipRight.getReadLength() <= i, String.format("Clipped read length is greater than original read length (minus %d): %s -> %s", i, read.getCigarString(), clipRight.getCigarString()));
+                assertUnclippedLimits(read, clipRight);
+            }
+        }
+    }
+
+    @DataProvider(name = "ClippedReadLengthData")
+    public Object[][] makeClippedReadLengthData() {
+        List<Object[]> tests = new ArrayList<Object[]>();
+
+        // this functionality can be adapted to provide input data for whatever you might want in your data
+        final int originalReadLength = 50;
+        for ( int nToClip = 1; nToClip < originalReadLength - 1; nToClip++ ) {
+            tests.add(new Object[]{originalReadLength, nToClip});
+        }
+
+        return tests.toArray(new Object[][]{});
+    }
+
+    @Test(dataProvider = "ClippedReadLengthData", enabled = !DEBUG)
+    public void testHardClipReadLengthIsRight(final int originalReadLength, final int nToClip) {
+        GATKSAMRecord read = ReadClipperTestUtils.makeReadFromCigar(originalReadLength + "M");
+        read.getReadLength(); // provoke the caching of the read length
+        final int expectedReadLength = originalReadLength - nToClip;
+        GATKSAMRecord clipped = ReadClipper.hardClipByReadCoordinates(read, 0, nToClip - 1);
+        Assert.assertEquals(clipped.getReadLength(), expectedReadLength,
+                String.format("Clipped read length %d with cigar %s not equal to the expected read length %d after clipping %d bases from the left from a %d bp read with cigar %s",
+                        clipped.getReadLength(), clipped.getCigar(), expectedReadLength, nToClip, read.getReadLength(), read.getCigar()));
+    }
+
+    @Test(enabled = !DEBUG)
+    public void testHardClipByReferenceCoordinates() {
+        for (Cigar cigar : cigarList) {
+            GATKSAMRecord read = ReadClipperTestUtils.makeReadFromCigar(cigar);
+            int start = read.getSoftStart();
+            int stop = read.getSoftEnd();
+
+            for (int i = start; i <= stop; i++) {
+                GATKSAMRecord clipLeft = (new ReadClipper(read)).hardClipByReferenceCoordinates(-1, i);
+                if (!clipLeft.isEmpty()) {
+                    Assert.assertTrue(clipLeft.getAlignmentStart() >= Math.min(read.getAlignmentEnd(), i + 1), String.format("Clipped alignment start (%d) is less the expected (%d): %s -> %s", clipLeft.getAlignmentStart(), i + 1, read.getCigarString(), clipLeft.getCigarString()));
+                    assertUnclippedLimits(read, clipLeft);
+                }
+
+                GATKSAMRecord clipRight = (new ReadClipper(read)).hardClipByReferenceCoordinates(i, -1);
+                if (!clipRight.isEmpty() && clipRight.getAlignmentStart() <= clipRight.getAlignmentEnd()) {             // alnStart > alnEnd if the entire read is a soft clip now. We can't test those.
+                    Assert.assertTrue(clipRight.getAlignmentEnd() <= Math.max(read.getAlignmentStart(), i - 1), String.format("Clipped alignment end (%d) is greater than expected (%d): %s -> %s", clipRight.getAlignmentEnd(), i - 1, read.getCigarString(), clipRight.getCigarString()));
+                    assertUnclippedLimits(read, clipRight);
+                }
+            }
+        }
+    }
+
+    @Test(enabled = !DEBUG)
+    public void testHardClipByReferenceCoordinatesLeftTail() {
+        for (Cigar cigar : cigarList) {
+            GATKSAMRecord read = ReadClipperTestUtils.makeReadFromCigar(cigar);
+            int alnStart = read.getAlignmentStart();
+            int alnEnd = read.getAlignmentEnd();
+            if (read.getSoftStart() == alnStart) {                                                                      // we can't test left clipping if the read has hanging soft clips on the left side
+                for (int i = alnStart; i <= alnEnd; i++) {
+                    GATKSAMRecord clipLeft = ReadClipper.hardClipByReferenceCoordinatesLeftTail(read, i);
+
+                    if (!clipLeft.isEmpty()) {
+                        Assert.assertTrue(clipLeft.getAlignmentStart() >= i + 1, String.format("Clipped alignment start (%d) is less the expected (%d): %s -> %s", clipLeft.getAlignmentStart(), i + 1, read.getCigarString(), clipLeft.getCigarString()));
+                        assertUnclippedLimits(read, clipLeft);
+                    }
+                }
+            }
+        }
+    }
+
+    @Test(enabled = !DEBUG)
+    public void testHardClipByReferenceCoordinatesRightTail() {
+        for (Cigar cigar : cigarList) {
+            GATKSAMRecord read = ReadClipperTestUtils.makeReadFromCigar(cigar);
+            int alnStart = read.getAlignmentStart();
+            int alnEnd = read.getAlignmentEnd();
+            if (read.getSoftEnd() == alnEnd) {                                                                          // we can't test right clipping if the read has hanging soft clips on the right side
+                for (int i = alnStart; i <= alnEnd; i++) {
+                    GATKSAMRecord clipRight = ReadClipper.hardClipByReferenceCoordinatesRightTail(read, i);
+                    if (!clipRight.isEmpty() && clipRight.getAlignmentStart() <= clipRight.getAlignmentEnd()) {         // alnStart > alnEnd if the entire read is a soft clip now. We can't test those.
+                        Assert.assertTrue(clipRight.getAlignmentEnd() <= i - 1, String.format("Clipped alignment end (%d) is greater than expected (%d): %s -> %s", clipRight.getAlignmentEnd(), i - 1, read.getCigarString(), clipRight.getCigarString()));
+                        assertUnclippedLimits(read, clipRight);
+                    }
+                }
+            }
+        }
+    }
+
+    @Test(enabled = !DEBUG)
+    public void testHardClipLowQualEnds() {
+        final byte LOW_QUAL = 2;
+        final byte HIGH_QUAL = 30;
+
+        /** create a read for every cigar permutation */
+        for (Cigar cigar : cigarList) {
+            GATKSAMRecord read = ReadClipperTestUtils.makeReadFromCigar(cigar);
+            int readLength = read.getReadLength();
+            byte[] quals = new byte[readLength];
+
+            for (int nLowQualBases = 0; nLowQualBases < readLength; nLowQualBases++) {
+
+                /**  create a read with nLowQualBases in the left tail */
+                Utils.fillArrayWithByte(quals, HIGH_QUAL);
+                for (int addLeft = 0; addLeft < nLowQualBases; addLeft++)
+                    quals[addLeft] = LOW_QUAL;
+                read.setBaseQualities(quals);
+                GATKSAMRecord clipLeft = ReadClipper.hardClipLowQualEnds(read, LOW_QUAL);
+                checkClippedReadsForLowQualEnds(read, clipLeft, LOW_QUAL, nLowQualBases);
+
+                /** create a read with nLowQualBases in the right tail */
+                Utils.fillArrayWithByte(quals, HIGH_QUAL);
+                for (int addRight = 0; addRight < nLowQualBases; addRight++)
+                    quals[readLength - addRight - 1] = LOW_QUAL;
+                read.setBaseQualities(quals);
+                GATKSAMRecord clipRight = ReadClipper.hardClipLowQualEnds(read, LOW_QUAL);
+                checkClippedReadsForLowQualEnds(read, clipRight, LOW_QUAL, nLowQualBases);
+
+                /** create a read with nLowQualBases on both tails */
+                if (nLowQualBases <= readLength / 2) {
+                    Utils.fillArrayWithByte(quals, HIGH_QUAL);
+                    for (int addBoth = 0; addBoth < nLowQualBases; addBoth++) {
+                        quals[addBoth] = LOW_QUAL;
+                        quals[readLength - addBoth - 1] = LOW_QUAL;
+                    }
+                    read.setBaseQualities(quals);
+                    GATKSAMRecord clipBoth = ReadClipper.hardClipLowQualEnds(read, LOW_QUAL);
+                    checkClippedReadsForLowQualEnds(read, clipBoth, LOW_QUAL, 2*nLowQualBases);
+                }
+            }
+        }
+    }
+
+    @Test(enabled = !DEBUG)
+    public void testHardClipSoftClippedBases() {
+        for (Cigar cigar : cigarList) {
+            GATKSAMRecord read = ReadClipperTestUtils.makeReadFromCigar(cigar);
+            GATKSAMRecord clippedRead = ReadClipper.hardClipSoftClippedBases(read);
+            CigarCounter original = new CigarCounter(read);
+            CigarCounter clipped = new CigarCounter(clippedRead);
+
+            assertUnclippedLimits(read, clippedRead);                                                                   // Make sure limits haven't changed
+            original.assertHardClippingSoftClips(clipped);                                                              // Make sure we have only clipped SOFT_CLIPS
+        }
+    }
+
+    @Test(enabled = false)
+    public void testHardClipLeadingInsertions() {
+        for (Cigar cigar : cigarList) {
+            if (startsWithInsertion(cigar)) {
+                GATKSAMRecord read = ReadClipperTestUtils.makeReadFromCigar(cigar);
+                GATKSAMRecord clippedRead = ReadClipper.hardClipLeadingInsertions(read);
+
+                assertUnclippedLimits(read, clippedRead);        // Make sure limits haven't changed
+
+                int expectedLength = read.getReadLength() - leadingCigarElementLength(read.getCigar(), CigarOperator.INSERTION);
+                if (cigarHasElementsDifferentThanInsertionsAndHardClips(read.getCigar()))
+                    expectedLength -= leadingCigarElementLength(CigarUtils.invertCigar(read.getCigar()), CigarOperator.INSERTION);
+
+                if (!clippedRead.isEmpty()) {
+                    Assert.assertEquals(expectedLength, clippedRead.getReadLength(), String.format("%s -> %s", read.getCigarString(), clippedRead.getCigarString()));  // check that everything else is still there
+                    Assert.assertFalse(startsWithInsertion(clippedRead.getCigar()));                                                                                   // check that the insertions are gone
+                } else
+                    Assert.assertTrue(expectedLength == 0, String.format("expected length: %d", expectedLength));                                                      // check that the read was expected to be fully clipped
+            }
+        }
+    }
+
+    @Test(enabled = !DEBUG)
+    public void testRevertSoftClippedBases() {
+        for (Cigar cigar : cigarList) {
+            final int leadingSoftClips = leadingCigarElementLength(cigar, CigarOperator.SOFT_CLIP);
+            final int tailSoftClips = leadingCigarElementLength(CigarUtils.invertCigar(cigar), CigarOperator.SOFT_CLIP);
+
+            final GATKSAMRecord read = ReadClipperTestUtils.makeReadFromCigar(cigar);
+            final GATKSAMRecord unclipped = ReadClipper.revertSoftClippedBases(read);
+
+            assertUnclippedLimits(read, unclipped);                                                                     // Make sure limits haven't changed
+
+            if (leadingSoftClips > 0 || tailSoftClips > 0) {
+                final int expectedStart = read.getAlignmentStart() - leadingSoftClips;
+                final int expectedEnd = read.getAlignmentEnd() + tailSoftClips;
+
+                Assert.assertEquals(unclipped.getAlignmentStart(), expectedStart);
+                Assert.assertEquals(unclipped.getAlignmentEnd(), expectedEnd);
+            } else
+                Assert.assertEquals(read.getCigarString(), unclipped.getCigarString());
+        }
+    }
+
+    @Test(enabled = !DEBUG)
+    public void testRevertSoftClippedBasesWithThreshold() {
+        for (Cigar cigar : cigarList) {
+            final int leadingSoftClips = leadingCigarElementLength(cigar, CigarOperator.SOFT_CLIP);
+            final int tailSoftClips = leadingCigarElementLength(CigarUtils.invertCigar(cigar), CigarOperator.SOFT_CLIP);
+
+            final GATKSAMRecord read = ReadClipperTestUtils.makeReadFromCigar(cigar);
+            final GATKSAMRecord unclipped = ReadClipper.revertSoftClippedBases(read);
+
+            assertUnclippedLimits(read, unclipped);                                                                     // Make sure limits haven't changed
+            Assert.assertNull(read.getCigar().isValid(null, -1));
+            Assert.assertNull(unclipped.getCigar().isValid(null, -1));
+
+            if (!(leadingSoftClips > 0 || tailSoftClips > 0))
+                Assert.assertEquals(read.getCigarString(), unclipped.getCigarString());
+
+        }
+    }
+
+    @DataProvider(name = "RevertSoftClipsBeforeContig")
+    public Object[][] makeRevertSoftClipsBeforeContig() {
+        List<Object[]> tests = new ArrayList<>();
+
+        // this functionality can be adapted to provide input data for whatever you might want in your data
+        for ( int softStart : Arrays.asList(-10, -1, 0) ) {
+            for ( int alignmentStart : Arrays.asList(1, 10) ) {
+                tests.add(new Object[]{softStart, alignmentStart});
+            }
+        }
+
+        return tests.toArray(new Object[][]{});
+    }
+
+    @Test(enabled = true, dataProvider = "RevertSoftClipsBeforeContig")
+    public void testRevertSoftClippedBasesBeforeStartOfContig(final int softStart, final int alignmentStart) {
+        final int nMatches = 10;
+        final int nSoft = -1 * (softStart - alignmentStart);
+        final String cigar = nSoft + "S" + nMatches + "M";
+        final GATKSAMRecord read = ReadClipperTestUtils.makeReadFromCigar(cigar);
+        read.setAlignmentStart(alignmentStart);
+
+        Assert.assertEquals(read.getSoftStart(), softStart);
+        Assert.assertEquals(read.getAlignmentStart(), alignmentStart);
+        Assert.assertEquals(read.getCigarString(), cigar);
+
+        final GATKSAMRecord reverted = ReadClipper.revertSoftClippedBases(read);
+
+        final int expectedAlignmentStart = 1;
+        final String expectedCigar = (1 - softStart) + "H" + read.getAlignmentEnd() + "M";
+        Assert.assertEquals(reverted.getSoftStart(), expectedAlignmentStart);
+        Assert.assertEquals(reverted.getAlignmentStart(), expectedAlignmentStart);
+        Assert.assertEquals(reverted.getCigarString(), expectedCigar);
+    }
+
+    private void assertNoLowQualBases(GATKSAMRecord read, byte low_qual) {
+        if (!read.isEmpty()) {
+            byte[] quals = read.getBaseQualities();
+            for (int i = 0; i < quals.length; i++)
+                Assert.assertFalse(quals[i] <= low_qual, String.format("Found low qual (%d) base after hard clipping. Position: %d -- %s", low_qual, i, read.getCigarString()));
+        }
+    }
+
+    private void checkClippedReadsForLowQualEnds(GATKSAMRecord read, GATKSAMRecord clippedRead, byte lowQual, int nLowQualBases) {
+        assertUnclippedLimits(read, clippedRead);                                                                       // Make sure limits haven't changed
+        assertNoLowQualBases(clippedRead, lowQual);                                                                     // Make sure the low qualities are gone
+    }
+
+    /**
+     * Asserts that clipping doesn't change the getUnclippedStart / getUnclippedEnd
+     *
+     * @param original original read
+     * @param clipped clipped read
+     */
+    private void assertUnclippedLimits(GATKSAMRecord original, GATKSAMRecord clipped) {
+        if (CigarUtils.readHasNonClippedBases(clipped)) {
+            Assert.assertEquals(original.getUnclippedStart(), clipped.getUnclippedStart());
+            Assert.assertEquals(original.getUnclippedEnd(), clipped.getUnclippedEnd());
+        }
+    }
+
+    private boolean startsWithInsertion(Cigar cigar) {
+        return leadingCigarElementLength(cigar, CigarOperator.INSERTION) > 0;
+    }
+
+    private int leadingCigarElementLength(Cigar cigar, CigarOperator operator) {
+        for (CigarElement cigarElement : cigar.getCigarElements()) {
+            if (cigarElement.getOperator() == operator)
+                return cigarElement.getLength();
+            if (cigarElement.getOperator() != CigarOperator.HARD_CLIP)
+                break;
+        }
+        return 0;
+    }
+
+    private boolean cigarHasElementsDifferentThanInsertionsAndHardClips(Cigar cigar) {
+        for (CigarElement cigarElement : cigar.getCigarElements())
+            if (cigarElement.getOperator() != CigarOperator.INSERTION && cigarElement.getOperator() != CigarOperator.HARD_CLIP)
+                return true;
+        return false;
+    }
+
+    private class CigarCounter {
+        private HashMap<CigarOperator, Integer> counter;
+
+        public Integer getCounterForOp(CigarOperator operator) {
+            return counter.get(operator);
+        }
+
+        public CigarCounter(GATKSAMRecord read) {
+            CigarOperator[] operators = CigarOperator.values();
+            counter = new HashMap<CigarOperator, Integer>(operators.length);
+
+            for (CigarOperator op : operators)
+                counter.put(op, 0);
+
+            for (CigarElement cigarElement : read.getCigar().getCigarElements())
+                counter.put(cigarElement.getOperator(), counter.get(cigarElement.getOperator()) + cigarElement.getLength());
+        }
+
+        public boolean assertHardClippingSoftClips(CigarCounter clipped) {
+            for (CigarOperator op : counter.keySet()) {
+                if (op == CigarOperator.HARD_CLIP || op == CigarOperator.SOFT_CLIP) {
+                    int counterTotal = counter.get(CigarOperator.HARD_CLIP) + counter.get(CigarOperator.SOFT_CLIP);
+                    int clippedHard = clipped.getCounterForOp(CigarOperator.HARD_CLIP);
+                    int clippedSoft = clipped.getCounterForOp(CigarOperator.SOFT_CLIP);
+
+                    Assert.assertEquals(counterTotal, clippedHard);
+                    Assert.assertTrue(clippedSoft == 0);
+                } else
+                    Assert.assertEquals(counter.get(op), clipped.getCounterForOp(op));
+            }
+            return true;
+        }
+
+    }
+
+    @Test(enabled = !DEBUG)
+    public void testRevertEntirelySoftclippedReads() {
+        GATKSAMRecord read = ReadClipperTestUtils.makeReadFromCigar("2H1S3H");
+        GATKSAMRecord clippedRead = ReadClipper.revertSoftClippedBases(read);
+        Assert.assertEquals(clippedRead.getAlignmentStart(), read.getSoftStart());
+    }
+
+}
\ No newline at end of file
diff --git a/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/utils/codecs/hapmap/HapMapUnitTest.java b/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/utils/codecs/hapmap/HapMapUnitTest.java
new file mode 100644
index 0000000..0ff50d7
--- /dev/null
+++ b/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/utils/codecs/hapmap/HapMapUnitTest.java
@@ -0,0 +1,164 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.utils.codecs.hapmap;
+
+import htsjdk.tribble.annotation.Strand;
+import htsjdk.tribble.readers.LineIterator;
+import htsjdk.tribble.readers.LineIteratorImpl;
+import htsjdk.tribble.readers.LineReaderUtil;
+import htsjdk.tribble.readers.PositionalBufferedStream;
+import org.broadinstitute.gatk.utils.BaseTest;
+import org.testng.Assert;
+import org.testng.annotations.Test;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+
+/**
+ * Unit tests for the HapMap codec
+ */
+public class HapMapUnitTest extends BaseTest {
+    // our sample hapmap file
+    private final static File hapMapFile = new File(privateTestDir + "genotypes_chr1_ASW_phase3.3_first500.hapmap");
+    private final static String knownLine = "rs2185539 C/T chr1 556738 + ncbi_b36 bbs urn:lsid:bbs.hapmap.org:Protocol:Phase3.r3:1 urn:lsid:bbs.hapmap.org:Assay:Phase3.r3_r" +
+            "s2185539:1 urn:lsid:dcc.hapmap.org:Panel:US_African-30-trios:4 QC+ CC TC TT CT CC CC CC CC CC CC CC CC CC";
+    /**
+     * test reading the header off of the file.  We take in the file, read off the first line,
+     * close the reader, and then ask the HapMap decoder for the header with a new reader.  These should
+     * be equal (i.e. they return the same object).
+     */
+    @Test
+    public void testReadHeader() {
+        RawHapMapCodec codec = new RawHapMapCodec();
+        final LineIterator reader = getLineIterator();
+        try {
+            String header = reader.next();
+            Assert.assertTrue(header.equals(codec.readActualHeader(getLineIterator())));
+        } finally {
+            codec.close(reader);
+        }
+    }
+
+    @Test
+    public void testKnownRecordConversion() {
+        RawHapMapCodec codec = new RawHapMapCodec();
+        RawHapMapFeature feature = (RawHapMapFeature)codec.decode(knownLine);
+
+
+        // check that the alleles are right
+        Assert.assertEquals(feature.getAlleles().length,2);
+        Assert.assertTrue("C".equals(feature.getAlleles()[0]));
+        Assert.assertTrue("T".equals(feature.getAlleles()[1]));
+
+        // check the name
+        Assert.assertTrue("rs2185539".equals(feature.getName()));
+
+        // check the position
+        Assert.assertEquals(feature.getStart(),556738);
+        Assert.assertEquals(feature.getEnd(),556738);
+
+        // check the contig
+        Assert.assertTrue("chr1".equals(feature.getChr()));
+                
+        // check the assembly, center, protLSID, assayLSID, panelLSID, and qccode
+        Assert.assertTrue("ncbi_b36".equals(feature.getAssembly()));
+        Assert.assertTrue("bbs".equals(feature.getCenter()));
+        Assert.assertTrue("urn:lsid:bbs.hapmap.org:Protocol:Phase3.r3:1".equals(feature.getProtLSID()));
+        Assert.assertTrue("urn:lsid:bbs.hapmap.org:Assay:Phase3.r3_rs2185539:1".equals(feature.getAssayLSID()));
+        Assert.assertTrue("urn:lsid:dcc.hapmap.org:Panel:US_African-30-trios:4".equals(feature.getPanelLSID()));
+        Assert.assertTrue("QC+".equals(feature.getQCCode()));
+
+        // check the strand
+        Assert.assertEquals(feature.getStrand(),Strand.POSITIVE);
+
+        // check the genotypes
+        int x = 0;
+        for (; x < feature.getGenotypes().length; x++) {
+            switch (x) {
+                case 1: Assert.assertTrue("TC".equals(feature.getGenotypes()[x])); break;
+                case 2: Assert.assertTrue("TT".equals(feature.getGenotypes()[x])); break;
+                case 3: Assert.assertTrue("CT".equals(feature.getGenotypes()[x])); break;
+                default: Assert.assertTrue("CC".equals(feature.getGenotypes()[x])); break;
+            }
+        }
+        // assert that we found the correct number of records
+        Assert.assertEquals(x,13);
+    }
+
+    @Test
+    public void testReadCorrectNumberOfRecords() {
+        // setup the record for reading our 500 line file (499 records, 1 header line)
+        RawHapMapCodec codec = new RawHapMapCodec();
+        final LineIterator reader = getLineIterator();
+
+        int count = 0;
+        try {
+            codec.readHeader(reader);
+            while (reader.hasNext()) {
+                codec.decode(reader.next());
+                ++count;
+            }
+        } catch (IOException e) {
+            Assert.fail("IOException " + e.getMessage());
+        } finally {
+            codec.close(reader);
+        }
+        Assert.assertEquals(count,499);
+    }
+
+    @Test
+    public void testGetSampleNames() {
+        // setup the record for reading our 500 line file (499 records, 1 header line)
+        RawHapMapCodec codec = new RawHapMapCodec();
+        final LineIterator reader = getLineIterator();
+
+        String line;
+        try {
+            codec.readHeader(reader);
+            line = reader.next();
+            RawHapMapFeature feature = (RawHapMapFeature) codec.decode(line);
+            Assert.assertEquals(feature.getSampleIDs().length,87);
+
+        } catch (IOException e) {
+            Assert.fail("IOException " + e.getMessage());
+        } finally {
+            codec.close(reader);
+        }
+    }
+
+
+    public LineIterator getLineIterator() {
+        try {
+            return new LineIteratorImpl(LineReaderUtil.fromBufferedStream(new PositionalBufferedStream(new FileInputStream(hapMapFile))));
+        } catch (FileNotFoundException e) {
+            Assert.fail("Unable to open hapmap file : " + hapMapFile);
+        }
+        return null; // for intellij, it doesn't know that assert.fail is fatal
+    }
+
+}
diff --git a/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/utils/collections/DefaultHashMapUnitTest.java b/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/utils/collections/DefaultHashMapUnitTest.java
new file mode 100755
index 0000000..a87aeba
--- /dev/null
+++ b/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/utils/collections/DefaultHashMapUnitTest.java
@@ -0,0 +1,159 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.utils.collections;
+
+
+// the imports for unit testing.
+
+import org.broadinstitute.gatk.utils.BaseTest;
+import org.testng.Assert;
+import org.testng.annotations.BeforeMethod;
+import org.testng.annotations.Test;
+
+
+/**
+ * Basic unit test for DefaultHashMap
+ */
+public class DefaultHashMapUnitTest extends BaseTest {
+    DefaultHashMap<String, Double> empty, hasOne, hasTen;
+    Double initialDefault = 10.0;
+
+    @BeforeMethod
+    public void before() {
+        empty = new DefaultHashMap<String, Double>(initialDefault);
+
+        hasOne = new DefaultHashMap<String, Double>(initialDefault);
+        hasOne.put("1", .1);
+
+        hasTen = new DefaultHashMap<String, Double>(initialDefault);
+        for (Integer i = 1; i <= 10; i++) {
+            hasTen.put(i.toString(), i.doubleValue() / 10);
+        }
+    }
+
+    @Test
+    public void testBasicSizes() {
+        logger.warn("Executing testBasicSizes");
+
+        Assert.assertEquals(0, empty.size());
+        Assert.assertEquals(1, hasOne.size());
+        Assert.assertEquals(10, hasTen.size());
+    }
+
+    @Test
+    public void testTenElements() {
+        logger.warn("Executing testTenElements");
+
+        for (Integer i = 1; i <= 10; i++) {
+            Assert.assertEquals(i.doubleValue() / 10, hasTen.get(i.toString()));
+        }
+        Assert.assertEquals(initialDefault, hasTen.get("0"));
+    }
+
+    @Test
+    public void testClear() {
+        logger.warn("Executing testClear");
+
+        empty.clear();
+        hasOne.clear();
+        hasTen.clear();
+
+        Assert.assertEquals(0, empty.size());
+        Assert.assertEquals(0, hasOne.size());
+        Assert.assertEquals(0, hasTen.size());
+    }
+
+
+    @Test
+    public void testSettingTenElements() {
+        logger.warn("Executing testSettingTenElements");
+
+        Assert.assertEquals(10, hasTen.size());
+        for (Integer i = 1; i <= 10; i++) {
+            hasTen.put(i.toString(), i.doubleValue());
+        }
+
+        Assert.assertEquals(10, hasTen.size());
+        for (Integer i = 1; i <= 10; i++) {
+            Assert.assertEquals(i.doubleValue(), hasTen.get(i.toString()));
+        }
+    }
+
+    @Test
+    public void testSettingDefault() {
+        logger.warn("Executing testSettingDefault");
+
+        Assert.assertEquals(initialDefault, empty.get("0"));
+        Assert.assertEquals(initialDefault, hasOne.get("0"));
+        Assert.assertEquals(initialDefault, hasTen.get("0"));
+
+        empty.setDefaultValue(2 * initialDefault);
+        hasOne.setDefaultValue(2 * initialDefault);
+        hasTen.setDefaultValue(2 * initialDefault);
+
+        Assert.assertEquals(2 * initialDefault, empty.get("0"));
+        Assert.assertEquals(2 * initialDefault, hasOne.get("0"));
+        Assert.assertEquals(2 * initialDefault, hasTen.get("0"));
+
+    }
+
+    @Test
+    public void testAdd() {
+        logger.warn("Executing testAdd");
+
+        Assert.assertEquals(0, empty.size());
+
+        Double x = 1.0;
+        empty.put(x.toString(), x / 10);
+        Assert.assertEquals(1, empty.size());
+        Assert.assertEquals(.1, empty.get(x.toString()));
+
+        x = 2.0;
+        empty.put(x.toString(), x / 10);
+        Assert.assertEquals(2, empty.size());
+        Assert.assertEquals(.2, empty.get(x.toString()));
+
+    }
+
+    @Test
+    public void testUnset() {
+        logger.warn("Executing testUnset1");
+
+        Assert.assertEquals(10, hasTen.size());
+        Assert.assertEquals(.9, hasTen.get("9"));
+
+        hasTen.remove("9");
+
+        Assert.assertEquals(9, hasTen.size());
+        Assert.assertEquals(initialDefault, hasTen.get("9"));
+
+        hasTen.remove("1");
+
+        Assert.assertEquals(8, hasTen.size());
+        Assert.assertEquals(initialDefault, hasTen.get("1"));
+
+    }
+}
diff --git a/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/utils/collections/ExpandingArrayListUnitTest.java b/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/utils/collections/ExpandingArrayListUnitTest.java
new file mode 100644
index 0000000..7f9d808
--- /dev/null
+++ b/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/utils/collections/ExpandingArrayListUnitTest.java
@@ -0,0 +1,177 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.utils.collections;
+
+
+// the imports for unit testing.
+
+
+import org.testng.Assert;
+import org.testng.annotations.Test;
+import org.testng.annotations.BeforeMethod;
+
+import org.broadinstitute.gatk.utils.BaseTest;
+
+import java.util.Arrays;
+
+/**
+ * Basic unit test for RecalData
+ */
+public class ExpandingArrayListUnitTest extends BaseTest {
+    ExpandingArrayList<Integer> empty, initCap10, hasOne, hasTen;
+
+    @BeforeMethod
+    public void before() {
+        empty = new ExpandingArrayList<Integer>();
+
+        initCap10 = new ExpandingArrayList<Integer>(10);
+
+        hasOne = new ExpandingArrayList<Integer>();
+        hasOne.add(1);
+
+        hasTen = new ExpandingArrayList<Integer>();
+        hasTen.addAll(Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10));
+    }
+
+    @Test
+    public void testBasicSizes() {
+        logger.warn("Executing testBasicSizes");
+
+        Assert.assertEquals(0, empty.size());
+        Assert.assertEquals(0, initCap10.size());
+        Assert.assertEquals(1, hasOne.size());
+        Assert.assertEquals(10, hasTen.size());
+    }
+
+    @Test
+    public void testTenElements() {
+        logger.warn("Executing testTenElements");
+
+        for ( int i = 0; i < 10; i++ ) {
+            Assert.assertEquals(i+1, (int)hasTen.get(i));
+        }
+    }
+
+    @Test
+    public void testSettingTenElements() {
+        logger.warn("Executing testSettingTenElements");
+
+        for ( int i = 0; i < 10; i++ ) {
+            Assert.assertEquals(i+1, (int)hasTen.set(i, 2*i));
+        }
+
+        Assert.assertEquals(10, hasTen.size());
+        for ( int i = 0; i < 10; i++ ) {
+            Assert.assertEquals(2*i, (int)hasTen.get(i));
+        }
+    }
+
+    @Test
+    public void testAdd() {
+        logger.warn("Executing testAdd");
+
+        Assert.assertEquals(0, empty.size());
+        empty.add(1);
+        Assert.assertEquals(1, empty.size());
+        Assert.assertEquals(1, (int)empty.get(0));
+        empty.add(2);
+        Assert.assertEquals(2, empty.size());
+        Assert.assertEquals(2, (int)empty.get(1));
+    }
+
+    @Test
+    public void testSet1() {
+        logger.warn("Executing testSet1");
+
+        Assert.assertEquals(0, empty.size());
+        empty.set(0, 1);
+        Assert.assertEquals(1, empty.size());
+        Assert.assertEquals(1, (int)empty.get(0));
+
+        empty.set(1, 2);
+        Assert.assertEquals(2, empty.size());
+        Assert.assertEquals(2, (int)empty.get(1));
+
+        // doesn't expand
+        empty.set(0, 3);
+        Assert.assertEquals(2, empty.size());
+        Assert.assertEquals(3, (int)empty.get(0));
+    }
+
+    @Test
+    public void testSetExpanding() {
+        logger.warn("Executing testSetExpanding");
+
+        Assert.assertEquals(0, empty.size());
+        empty.set(3, 1);
+        Assert.assertEquals(4, empty.size());
+        Assert.assertEquals(empty.get(0), null);
+        Assert.assertEquals(empty.get(1), null);
+        Assert.assertEquals(empty.get(2), null);
+        Assert.assertEquals(1, (int)empty.get(3));
+    }
+
+    @Test
+    public void testSetExpandingReset() {
+        logger.warn("Executing testSetExpandingReset");
+
+        Assert.assertEquals(0, empty.size());
+        empty.set(3, 3);
+        empty.set(2, 2);
+        empty.set(1, 1);
+        empty.set(0, 0);
+        Assert.assertEquals(4, empty.size());
+        for ( int i = 0; i < 4; i++ )
+            Assert.assertEquals(i, (int)empty.get(i));
+    }
+
+    @Test
+    public void testSetExpandingBig() {
+        logger.warn("Executing testSetExpandingBig");
+
+        Assert.assertEquals(0, empty.size());
+        empty.set(1000, 1000);
+        Assert.assertEquals(1001, empty.size());
+        for ( int i = 0; i < 1000; i++ )
+            Assert.assertEquals(empty.get(i), null);
+        Assert.assertEquals(1000, (int)empty.get(1000));
+    }
+
+    @Test (expectedExceptions=IndexOutOfBoundsException.class )
+    public void testSetBadGetNegative() {
+        logger.warn("Executing testSetBadGetNegative");
+        empty.get(-1);
+    }
+
+    @Test
+    public void testSetBadGetPost() {
+        logger.warn("Executing testSetBadGetPost");
+        empty.set(1, 1);
+        Assert.assertEquals(empty.get(0), null);
+        Assert.assertEquals(1, (int)empty.get(1));
+        Assert.assertEquals(empty.get(2), null);
+    }
+}
diff --git a/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/utils/commandline/ArgumentMatchSiteUnitTest.java b/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/utils/commandline/ArgumentMatchSiteUnitTest.java
new file mode 100644
index 0000000..b1ba784
--- /dev/null
+++ b/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/utils/commandline/ArgumentMatchSiteUnitTest.java
@@ -0,0 +1,80 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.utils.commandline;
+
+import org.testng.Assert;
+import org.testng.annotations.Test;
+
+import java.io.File;
+
+public class ArgumentMatchSiteUnitTest {
+    @Test
+    public void testCommandLine() {
+        ArgumentMatchSite site = new ArgumentMatchSite(ArgumentMatchSource.COMMAND_LINE, 1);
+        Assert.assertEquals(site.getSource(), ArgumentMatchSource.COMMAND_LINE);
+        Assert.assertEquals(site.getIndex(), 1);
+    }
+
+    @Test
+    public void testFile() {
+        ArgumentMatchSource source = new ArgumentMatchFileSource(new File("test"));
+        ArgumentMatchSite site = new ArgumentMatchSite(source, 1);
+        Assert.assertEquals(site.getSource(), source);
+        Assert.assertEquals(site.getIndex(), 1);
+    }
+
+    @Test
+    public void testEquals() {
+        ArgumentMatchSource cmdLine = ArgumentMatchSource.COMMAND_LINE;
+        ArgumentMatchSite site1 = new ArgumentMatchSite(cmdLine, 1);
+        ArgumentMatchSite site2 = new ArgumentMatchSite(cmdLine, 2);
+
+        Assert.assertFalse(site1.equals(null));
+
+        Assert.assertTrue(site1.equals(site1));
+        Assert.assertFalse(site1.equals(site2));
+
+        Assert.assertFalse(site2.equals(site1));
+        Assert.assertTrue(site2.equals(site2));
+    }
+
+    @Test
+    public void testCompareTo() {
+        ArgumentMatchSource cmdLine = ArgumentMatchSource.COMMAND_LINE;
+        ArgumentMatchSite site1 = new ArgumentMatchSite(cmdLine, 1);
+        ArgumentMatchSite site2 = new ArgumentMatchSite(cmdLine, 2);
+
+        Assert.assertTrue(site1.compareTo(site1) == 0);
+        Assert.assertTrue(site1.compareTo(site2) < 0);
+        Assert.assertTrue(site2.compareTo(site1) > 0);
+        Assert.assertTrue(site2.compareTo(site2) == 0);
+    }
+
+    @Test(expectedExceptions = NullPointerException.class)
+    public void testCompareToNull() {
+        new ArgumentMatchSite(ArgumentMatchSource.COMMAND_LINE, 0).compareTo(null);
+    }
+}
diff --git a/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/utils/commandline/ArgumentMatchSourceUnitTest.java b/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/utils/commandline/ArgumentMatchSourceUnitTest.java
new file mode 100644
index 0000000..8837f4b
--- /dev/null
+++ b/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/utils/commandline/ArgumentMatchSourceUnitTest.java
@@ -0,0 +1,99 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.utils.commandline;
+
+import org.broadinstitute.gatk.utils.BaseTest;
+import org.testng.Assert;
+import org.testng.annotations.Test;
+
+import java.io.File;
+
+public class ArgumentMatchSourceUnitTest extends BaseTest {
+    @Test
+    public void testCommandLine() {
+        ArgumentMatchSource source = ArgumentMatchSource.COMMAND_LINE;
+        Assert.assertEquals(source.getType(), ArgumentMatchSourceType.CommandLine);
+        Assert.assertNull(source.getDescription());
+    }
+
+    @Test
+    public void testFile() {
+        File f = new File("test");
+        ArgumentMatchSource source = new ArgumentMatchFileSource(f);
+        Assert.assertEquals(source.getType(), ArgumentMatchSourceType.Provider);
+        Assert.assertEquals(source.getDescription(), "file " + f.getAbsolutePath());
+    }
+
+    @Test(expectedExceptions = IllegalArgumentException.class)
+    public void testNullFile() {
+        new ArgumentMatchSource(null);
+    }
+
+    @Test
+    public void testEquals() {
+        ArgumentMatchSource cmdLine = ArgumentMatchSource.COMMAND_LINE;
+        ArgumentMatchSource fileA = new ArgumentMatchFileSource(new File("a"));
+        ArgumentMatchSource fileB = new ArgumentMatchFileSource(new File("b"));
+
+        Assert.assertFalse(cmdLine.equals(null));
+
+        Assert.assertTrue(cmdLine.equals(cmdLine));
+        Assert.assertFalse(cmdLine.equals(fileA));
+        Assert.assertFalse(cmdLine.equals(fileB));
+
+        Assert.assertFalse(fileA.equals(cmdLine));
+        Assert.assertTrue(fileA.equals(fileA));
+        Assert.assertFalse(fileA.equals(fileB));
+
+        Assert.assertFalse(fileB.equals(cmdLine));
+        Assert.assertFalse(fileB.equals(fileA));
+        Assert.assertTrue(fileB.equals(fileB));
+    }
+
+    @Test
+    public void testCompareTo() {
+        ArgumentMatchSource cmdLine = ArgumentMatchSource.COMMAND_LINE;
+        ArgumentMatchSource fileA = new ArgumentMatchFileSource(new File("a"));
+        ArgumentMatchSource fileB = new ArgumentMatchFileSource(new File("b"));
+
+        Assert.assertTrue(cmdLine.compareTo(cmdLine) == 0);
+        Assert.assertTrue(cmdLine.compareTo(fileA) < 0);
+        Assert.assertTrue(cmdLine.compareTo(fileB) < 0);
+
+        Assert.assertTrue(fileA.compareTo(cmdLine) > 0);
+        Assert.assertTrue(fileA.compareTo(fileA) == 0);
+        Assert.assertTrue(fileA.compareTo(fileB) < 0);
+
+        Assert.assertTrue(fileB.compareTo(cmdLine) > 0);
+        Assert.assertTrue(fileB.compareTo(fileA) > 0);
+        Assert.assertTrue(fileB.compareTo(fileB) == 0);
+    }
+
+    @Test(expectedExceptions = NullPointerException.class)
+    public void testCompareToNull() {
+        ArgumentMatchSource.COMMAND_LINE.compareTo(null);
+    }
+}
diff --git a/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/utils/commandline/ArgumentTypeDescriptorUnitTest.java b/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/utils/commandline/ArgumentTypeDescriptorUnitTest.java
new file mode 100644
index 0000000..1dfffa3
--- /dev/null
+++ b/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/utils/commandline/ArgumentTypeDescriptorUnitTest.java
@@ -0,0 +1,233 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.utils.commandline;
+
+import htsjdk.variant.variantcontext.VariantContext;
+import it.unimi.dsi.fastutil.objects.ObjectArrayList;
+import htsjdk.samtools.SAMFileWriter;
+import org.broadinstitute.gatk.utils.BaseTest;
+import org.broadinstitute.gatk.engine.GenomeAnalysisEngine;
+import org.broadinstitute.gatk.engine.io.stubs.*;
+import org.broadinstitute.gatk.utils.exceptions.ReviewedGATKException;
+import htsjdk.variant.variantcontext.writer.VariantContextWriter;
+import org.testng.Assert;
+import org.testng.annotations.DataProvider;
+import org.testng.annotations.Test;
+
+import java.io.File;
+import java.io.IOException;
+import java.io.PrintStream;
+import java.util.Arrays;
+import java.util.Collection;
+
+
+public class ArgumentTypeDescriptorUnitTest extends BaseTest {
+
+    ////////////////////////////////////////////////////////////////////
+    // This section tests the functionality of the @Output annotation //
+    ////////////////////////////////////////////////////////////////////
+
+    private class ATDTestCommandLineProgram extends CommandLineProgram {
+        public int execute() { return 0; }
+
+        @Override
+        public Collection<ArgumentTypeDescriptor> getArgumentTypeDescriptors() {
+            final GenomeAnalysisEngine engine = new GenomeAnalysisEngine();
+            return Arrays.asList( new SAMFileWriterArgumentTypeDescriptor(engine, System.out),
+                    new OutputStreamArgumentTypeDescriptor(engine, System.out),
+                    new VCFWriterArgumentTypeDescriptor(engine, System.out, null));
+        }
+
+        protected abstract class ATDTestOutputArgumentSource {
+            public abstract Object getOut();
+        }
+
+        protected class OutputRequiredSamArgumentSource extends ATDTestOutputArgumentSource {
+            @Output(shortName="o", doc="output file", required = true)
+            public SAMFileWriter out;
+            public Object getOut() { return out; }
+        }
+
+        protected class OutputRequiredVcfArgumentSource extends ATDTestOutputArgumentSource {
+            @Output(shortName="o", doc="output file", required = true)
+            public VariantContextWriter out;
+            public Object getOut() { return out; }
+        }
+
+        protected class OutputRequiredStreamArgumentSource extends ATDTestOutputArgumentSource {
+            @Output(shortName="o", doc="output file", required = true)
+            public PrintStream out;
+            public Object getOut() { return out; }
+        }
+
+        protected class OutputNotRequiredNoDefaultSamArgumentSource extends ATDTestOutputArgumentSource {
+            @Output(shortName="o", doc="output file", required = false, defaultToStdout = false)
+            public SAMFileWriter out;
+            public Object getOut() { return out; }
+        }
+
+        protected class OutputNotRequiredNoDefaultVcfArgumentSource extends ATDTestOutputArgumentSource {
+            @Output(shortName="o", doc="output file", required = false, defaultToStdout = false)
+            public VariantContextWriter out;
+            public Object getOut() { return out; }
+        }
+
+        protected class OutputNotRequiredNoDefaultStreamArgumentSource extends ATDTestOutputArgumentSource {
+            @Output(shortName="o", doc="output file", required = false, defaultToStdout = false)
+            public PrintStream out;
+            public Object getOut() { return out; }
+        }
+
+        protected class OutputNotRequiredSamArgumentSource extends ATDTestOutputArgumentSource {
+            @Output(shortName="o", doc="output file", required = false)
+            public SAMFileWriter out;
+            public Object getOut() { return out; }
+        }
+
+        protected class OutputNotRequiredVcfArgumentSource extends ATDTestOutputArgumentSource {
+            @Output(shortName="o", doc="output file", required = false)
+            public VariantContextWriter out;
+            public Object getOut() { return out; }
+        }
+
+        protected class OutputNotRequiredStreamArgumentSource extends ATDTestOutputArgumentSource {
+            @Output(shortName="o", doc="output file", required = false)
+            public PrintStream out;
+            public Object getOut() { return out; }
+        }
+    }
+
+    @DataProvider(name = "OutputProvider")
+    public Object[][] OutputProvider() {
+
+        ObjectArrayList<Object[]> tests = new ObjectArrayList<Object[]>();
+
+        final ATDTestCommandLineProgram clp = new ATDTestCommandLineProgram();
+
+        for ( final Object obj : Arrays.asList(clp.new OutputRequiredSamArgumentSource(), clp.new OutputRequiredVcfArgumentSource(), clp.new OutputRequiredStreamArgumentSource()) ) {
+            for ( final boolean provided : Arrays.asList(true, false) ) {
+                tests.add(new Object[]{obj, true, true, provided});
+            }
+        }
+
+        for ( final Object obj : Arrays.asList(clp.new OutputNotRequiredSamArgumentSource(), clp.new OutputNotRequiredVcfArgumentSource(), clp.new OutputNotRequiredStreamArgumentSource()) ) {
+            for ( final boolean provided : Arrays.asList(true, false) ) {
+                tests.add(new Object[]{obj, false, true, provided});
+            }
+        }
+
+        for ( final Object obj : Arrays.asList(clp.new OutputNotRequiredNoDefaultSamArgumentSource(), clp.new OutputNotRequiredNoDefaultVcfArgumentSource(), clp.new OutputNotRequiredNoDefaultStreamArgumentSource()) ) {
+            for ( final boolean provided : Arrays.asList(true, false) ) {
+                tests.add(new Object[]{obj, false, false, provided});
+            }
+        }
+
+        return tests.toArray(new Object[][]{});
+    }
+
+    @Test(dataProvider = "OutputProvider")
+    public void testOutput(final ATDTestCommandLineProgram.ATDTestOutputArgumentSource argumentSource, final boolean required, final boolean hasDefault, final boolean provided) {
+
+        final ParsingEngine parser = new ParsingEngine(new ATDTestCommandLineProgram());
+        parser.addArgumentSource(argumentSource.getClass());
+        parser.parse(provided ? new String[] {"out", "foo"} : new String[] {});
+
+        try {
+            parser.loadArgumentsIntoObject(argumentSource);
+
+            if ( !provided && (required || !hasDefault) )
+                Assert.assertEquals(argumentSource.getOut(), null);
+            else if ( !provided )
+                Assert.assertNotEquals(argumentSource.getOut(), null);
+            else if ( argumentSource.getOut() == null || !(argumentSource.getOut() instanceof SAMFileWriterStub) ) // can't test this one case
+                Assert.assertEquals(!provided, outputIsStdout(argumentSource.getOut()));
+
+        } catch (Exception e) {
+            throw new ReviewedGATKException(e.getMessage());
+        }
+    }
+
+    @Test
+    public void testRodBindingsCollection() {
+
+        final ParsingEngine parser = new ParsingEngine(new ATDTestCommandLineProgram());
+
+        //A list file containing a single VCF
+        final File listFile = createTempListFile("oneVCF", privateTestDir + "empty.vcf");
+
+        try {
+            Object result = ArgumentTypeDescriptor.getRodBindingsCollection(listFile,
+                    parser,
+                    VariantContext.class,
+                    "variant",
+                    new Tags(),
+                    "variantTest");
+            if (!(result instanceof RodBindingCollection))
+                throw new ReviewedGATKException("getRodBindingsCollection did not return a RodBindingCollection");
+            RodBindingCollection<?> rbc = (RodBindingCollection) result;
+
+            Assert.assertEquals(rbc.getType(), VariantContext.class);
+            Assert.assertEquals(rbc.getRodBindings().size(), 1);
+
+        } catch (IOException e) {
+            throw new ReviewedGATKException(e.getMessage(), e);
+        }
+
+        //The same file, now with an extra blank line
+        final File listFileWithBlank = createTempListFile("oneVCFwithBlankLine", privateTestDir + "empty.vcf", "");
+        try {
+            Object result = ArgumentTypeDescriptor.getRodBindingsCollection(listFileWithBlank,
+                    parser,
+                    VariantContext.class,
+                    "variant",
+                    new Tags(),
+                    "variantTest");
+            if (!(result instanceof RodBindingCollection))
+                throw new ReviewedGATKException("getRodBindingsCollection did not return a RodBindingCollection");
+            RodBindingCollection<?> rbc = (RodBindingCollection) result;
+
+            Assert.assertEquals(rbc.getType(), VariantContext.class);
+            Assert.assertEquals(rbc.getRodBindings().size(), 1);
+
+        } catch (IOException e) {
+            throw new ReviewedGATKException(e.getMessage(), e);
+        }
+    }
+
+    private static boolean outputIsStdout(final Object out) {
+        if ( out == null ) {
+            return false;
+        } else if ( out instanceof SAMFileWriterStub ) {
+            return ((SAMFileWriterStub)out).getOutputStream() != System.out;
+        } else if ( out instanceof VariantContextWriterStub ) {
+            return ((VariantContextWriterStub)out).getOutputStream() == System.out;
+        } else if ( out instanceof OutputStreamStub ) {
+            return ((OutputStreamStub)out).getOutputStream() == System.out;
+        }
+        return false;
+    }
+
+}
\ No newline at end of file
diff --git a/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/utils/commandline/InvalidArgumentIntegrationTest.java b/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/utils/commandline/InvalidArgumentIntegrationTest.java
new file mode 100644
index 0000000..8ab2159
--- /dev/null
+++ b/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/utils/commandline/InvalidArgumentIntegrationTest.java
@@ -0,0 +1,66 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.utils.commandline;
+
+import org.broadinstitute.gatk.utils.BaseTest;
+import org.broadinstitute.gatk.engine.walkers.WalkerTest;
+import org.broadinstitute.gatk.utils.exceptions.UserException;
+
+import org.testng.annotations.Test;
+import org.testng.annotations.DataProvider;
+
+/**
+ * Created by IntelliJ IDEA.
+ * User: chartl
+ * Date: 8/31/12
+ * Time: 11:03 AM
+ * To change this template use File | Settings | File Templates.
+ */
+public class InvalidArgumentIntegrationTest extends WalkerTest {
+    private static final String callsB36  = BaseTest.validationDataLocation + "lowpass.N3.chr1.raw.vcf";
+
+    private WalkerTest.WalkerTestSpec baseTest(String flag, String arg, Class exeption) {
+        return new WalkerTest.WalkerTestSpec("-T VariantsToTable -M 10 --variant:vcf "
+                + callsB36 + " -F POS,CHROM -R "
+                + b36KGReference +  " -o %s " + flag + " " + arg,
+                1, exeption);
+
+    }
+
+    @Test
+    public void testUnknownReadFilter() {
+        executeTest("UnknownReadFilter",baseTest("-rf","TestUnknownReadFilter", UserException.MalformedReadFilterException.class));
+    }
+
+    @Test
+    public void testMalformedWalkerArgs() {
+        executeTest("MalformedWalkerArgs",
+                new WalkerTest.WalkerTestSpec("-T UnknownWalkerName -M 10 --variant:vcf "
+                + callsB36 + " -F POS,CHROM -R "
+                + b36KGReference +  " -o %s ",
+                1, UserException.MalformedWalkerArgumentsException.class));
+    }
+}
diff --git a/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/utils/commandline/LoggingIntegrationTest.java b/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/utils/commandline/LoggingIntegrationTest.java
new file mode 100644
index 0000000..d690f68
--- /dev/null
+++ b/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/utils/commandline/LoggingIntegrationTest.java
@@ -0,0 +1,117 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.utils.commandline;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.Arrays;
+
+import org.apache.commons.lang.StringUtils;
+import org.apache.log4j.Level;
+
+import org.testng.Assert;
+import org.testng.annotations.DataProvider;
+import org.testng.annotations.Test;
+
+import org.broadinstitute.gatk.utils.BaseTest;
+import org.broadinstitute.gatk.utils.MD5DB;
+import org.broadinstitute.gatk.utils.MD5Mismatch;
+import org.broadinstitute.gatk.engine.CommandLineGATK;
+import org.broadinstitute.gatk.utils.runtime.*;
+
+public class LoggingIntegrationTest {
+    private final MD5DB md5db = new MD5DB();
+
+    private class LoggingTestProvider extends BaseTest.TestDataProvider {
+
+        private final String baseCmdLine;
+
+        private final Level logLevel;
+        private final String logFileStr;
+        public final File argumentOutputFile;
+        public final File pipedOutputFile;
+
+        private LoggingTestProvider(final Level logLevel, final boolean explicitLogfile) throws IOException {
+            super(LoggingTestProvider.class);
+
+            // TODO: a better command line that exercises log levels besides INFO
+            this.baseCmdLine = String.format("java -cp %s %s -T SelectVariants -R %s -V %s -L 1:1000000-2000000 --no_cmdline_in_header",
+                    StringUtils.join(RuntimeUtils.getAbsoluteClassPaths(), File.pathSeparatorChar),
+                    CommandLineGATK.class.getCanonicalName(), BaseTest.b37KGReference, BaseTest.b37_NA12878_OMNI);
+
+            this.logLevel = logLevel;
+            this.logFileStr = explicitLogfile ? " -log " + BaseTest.createTempFile(logLevel.toString(), "log") : "";
+            this.argumentOutputFile = BaseTest.createTempFile(logLevel.toString(), "vcf");
+            this.pipedOutputFile = BaseTest.createTempFile(logLevel.toString(), "vcf");
+        }
+
+        public final String getCmdLine(boolean redirectStdout) {
+            String command = String.format("%s -l %s %s", baseCmdLine, logLevel, logFileStr);
+            return redirectStdout ? command : command + " -o " + argumentOutputFile;
+        }
+
+        public String toString() {
+            return String.format("LoggingTestProvider logLevel=%s", logLevel);
+        }
+    }
+
+    @DataProvider(name = "LoggingTest")
+    public Object[][] makeLoggingTestProvider() throws IOException {
+        for (Boolean explicitLogFile : Arrays.asList(true, false)) {
+            // TODO: enable other logging levels when tests for those exist
+            new LoggingTestProvider(Level.DEBUG, explicitLogFile);
+        }
+
+        return LoggingTestProvider.getTests(LoggingTestProvider.class);
+    }
+
+    /**
+     * test that using an output argument produces the same output as stdout
+     */
+    @Test(dataProvider = "LoggingTest")
+    public void testStdoutEquivalence(final LoggingTestProvider cfg) throws IOException {
+
+        ProcessController pc = ProcessController.getThreadLocal();
+
+        // output argument
+
+        ProcessSettings ps = new ProcessSettings(cfg.getCmdLine(false).split("\\s+"));
+        pc.execAndCheck(ps);
+        String output_argument_md5 = md5db.calculateFileMD5(cfg.argumentOutputFile);
+
+        // pipe to stdout
+
+        ps = new ProcessSettings(cfg.getCmdLine(true).split("\\s+"));
+        ps.setStdoutSettings(new OutputStreamSettings(cfg.pipedOutputFile));
+        pc.execAndCheck(ps);
+
+        MD5DB.MD5Match result = md5db.testFileMD5("LoggingIntegrationTest", "LoggingIntegrationTest", cfg.pipedOutputFile, output_argument_md5, false);
+        if(result.failed) {
+            final MD5Mismatch failure = new MD5Mismatch(result.actualMD5, result.expectedMD5, result.diffEngineOutput);
+            Assert.fail(failure.toString());
+        }
+    }
+}
\ No newline at end of file
diff --git a/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/utils/commandline/ParsingEngineUnitTest.java b/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/utils/commandline/ParsingEngineUnitTest.java
new file mode 100644
index 0000000..d3c85b6
--- /dev/null
+++ b/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/utils/commandline/ParsingEngineUnitTest.java
@@ -0,0 +1,1140 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.utils.commandline;
+
+import org.apache.commons.io.FileUtils;
+import htsjdk.tribble.Feature;
+import org.broadinstitute.gatk.utils.exceptions.UserException;
+import htsjdk.variant.variantcontext.VariantContext;
+import org.testng.Assert;
+import org.broadinstitute.gatk.utils.BaseTest;
+import org.broadinstitute.gatk.utils.exceptions.ReviewedGATKException;
+import org.testng.annotations.BeforeMethod;
+import org.testng.annotations.DataProvider;
+import org.testng.annotations.Test;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.List;
+import java.util.EnumSet;
+import java.util.Set;
+
+/**
+ * Test suite for the parsing engine.
+ */
+public class ParsingEngineUnitTest extends BaseTest {
+    /** we absolutely cannot have this file existing, or we'll fail the UnitTest */
+    private final static String NON_EXISTANT_FILENAME_VCF = "this_file_should_not_exist_on_disk_123456789.vcf";
+    private ParsingEngine parsingEngine;
+
+    @BeforeMethod
+    public void setUp() {
+        parsingEngine = new ParsingEngine(null);
+        RodBinding.resetNameCounter();
+    }
+
+    private class InputFileArgProvider {
+        @Argument(fullName="input_file",doc="input file",shortName="I")
+        public String inputFile;
+    }
+
+    @Test
+    public void shortNameArgumentTest() {
+        final String[] commandLine = new String[] {"-I","na12878.bam"};
+
+        parsingEngine.addArgumentSource( InputFileArgProvider.class );
+        parsingEngine.parse( commandLine );
+        parsingEngine.validate();
+
+        InputFileArgProvider argProvider = new InputFileArgProvider();
+        parsingEngine.loadArgumentsIntoObject( argProvider );
+
+        Assert.assertEquals(argProvider.inputFile,"na12878.bam","Argument is not correctly initialized");
+    }
+
+    @Test
+    public void multiCharShortNameArgumentTest() {
+        final String[] commandLine = new String[] {"-out","out.txt"};
+
+        parsingEngine.addArgumentSource( MultiCharShortNameArgProvider.class );
+        parsingEngine.parse( commandLine );
+        parsingEngine.validate();
+
+        MultiCharShortNameArgProvider argProvider = new MultiCharShortNameArgProvider();
+        parsingEngine.loadArgumentsIntoObject( argProvider );
+
+        Assert.assertEquals(argProvider.outputFile,"out.txt","Argument is not correctly initialized");
+    }
+
+
+    private class MultiCharShortNameArgProvider {
+        @Argument(shortName="out", doc="output file")
+        public String outputFile;
+    }
+
+    @Test
+    public void longNameArgumentTest() {
+        final String[] commandLine = new String[] {"--input_file", "na12878.bam"};
+
+        parsingEngine.addArgumentSource( InputFileArgProvider.class );
+        parsingEngine.parse( commandLine );
+        parsingEngine.validate();
+
+        InputFileArgProvider argProvider = new InputFileArgProvider();
+        parsingEngine.loadArgumentsIntoObject( argProvider );
+
+        Assert.assertEquals(argProvider.inputFile,"na12878.bam","Argument is not correctly initialized");
+    }
+
+    @Test
+    public void extraWhitespaceTest() {
+        final String[] commandLine = new String[] {"  --input_file ", "na12878.bam"};
+
+        parsingEngine.addArgumentSource( InputFileArgProvider.class );
+        parsingEngine.parse( commandLine );
+        parsingEngine.validate();
+
+        InputFileArgProvider argProvider = new InputFileArgProvider();
+        parsingEngine.loadArgumentsIntoObject( argProvider );
+
+        Assert.assertEquals(argProvider.inputFile,"na12878.bam","Argument is not correctly initialized");
+    }
+
+    @Test
+    public void primitiveArgumentTest() {
+        final String[] commandLine = new String[] {"--foo", "5"};
+
+        parsingEngine.addArgumentSource( PrimitiveArgProvider.class );
+        parsingEngine.parse( commandLine );
+        parsingEngine.validate();
+
+        PrimitiveArgProvider argProvider = new PrimitiveArgProvider();
+        parsingEngine.loadArgumentsIntoObject( argProvider );
+
+        Assert.assertEquals(argProvider.foo, 5, "Argument is not correctly initialized");
+    }
+
+    @Test(expectedExceptions=InvalidArgumentValueException.class)
+    public void primitiveArgumentNoValueTest() {
+        final String[] commandLine = new String[] {"--foo"};
+
+        parsingEngine.addArgumentSource( PrimitiveArgProvider.class );
+        parsingEngine.parse( commandLine );
+        parsingEngine.validate();
+
+        PrimitiveArgProvider argProvider = new PrimitiveArgProvider();
+        parsingEngine.loadArgumentsIntoObject( argProvider );
+
+        Assert.assertEquals(argProvider.foo, 5, "Argument is not correctly initialized");
+    }
+
+    private class PrimitiveArgProvider {
+        @Argument(doc="simple integer")
+        int foo;
+    }
+
+    @Test
+    public void flagTest() {
+        final String[] commandLine = new String[] {"--all_loci"};
+
+        parsingEngine.addArgumentSource( AllLociArgProvider.class );
+        parsingEngine.parse( commandLine );
+        parsingEngine.validate();
+
+        AllLociArgProvider argProvider = new AllLociArgProvider();
+        parsingEngine.loadArgumentsIntoObject( argProvider );
+
+        Assert.assertTrue(argProvider.allLoci,"Argument is not correctly initialized");
+    }
+
+    private class AllLociArgProvider {
+        @Argument(fullName="all_loci",shortName="A", doc="all loci")
+        public boolean allLoci = false;
+    }
+
+    @Test
+    public void arrayTest() {
+        final String[] commandLine = new String[] {"-I", "foo.txt", "--input_file", "bar.txt"};
+
+        parsingEngine.addArgumentSource( MultiValueArgProvider.class );
+        parsingEngine.parse( commandLine );
+        parsingEngine.validate();
+
+        MultiValueArgProvider argProvider = new MultiValueArgProvider();
+        parsingEngine.loadArgumentsIntoObject( argProvider );
+
+        Assert.assertEquals(argProvider.inputFile.length, 2, "Argument array is of incorrect length");
+        Assert.assertEquals(argProvider.inputFile[0],"foo.txt","1st filename is incorrect");
+        Assert.assertEquals(argProvider.inputFile[1],"bar.txt","2nd filename is incorrect");
+    }
+
+    private class MultiValueArgProvider {
+        @Argument(fullName="input_file",shortName="I", doc="input file")
+        public String[] inputFile;
+    }
+
+    @Test
+    public void enumTest() {
+        final String[] commandLine = new String[] {  "--test_enum", "TWO" };
+
+        parsingEngine.addArgumentSource( EnumArgProvider.class );
+        parsingEngine.parse( commandLine );
+        parsingEngine.validate();
+
+        EnumArgProvider argProvider = new EnumArgProvider();
+        parsingEngine.loadArgumentsIntoObject( argProvider );
+
+        Assert.assertEquals(argProvider.testEnum, TestEnum.TWO, "Enum value is not correct");
+    }
+
+    @Test
+    public void enumMixedCaseTest() {
+        final String[] commandLine = new String[] {  "--test_enum", "oNe" };
+
+        parsingEngine.addArgumentSource( EnumArgProvider.class );
+        parsingEngine.parse( commandLine );
+        parsingEngine.validate();
+
+        EnumArgProvider argProvider = new EnumArgProvider();
+        parsingEngine.loadArgumentsIntoObject( argProvider );
+
+        Assert.assertEquals(argProvider.testEnum, TestEnum.ONE, "Enum value is not correct");
+    }
+
+    @Test
+    public void enumDefaultTest() {
+        final String[] commandLine = new String[] {};
+
+        parsingEngine.addArgumentSource( EnumArgProvider.class );
+        parsingEngine.parse( commandLine );
+        parsingEngine.validate();
+
+        EnumArgProvider argProvider = new EnumArgProvider();
+        parsingEngine.loadArgumentsIntoObject( argProvider );
+
+        Assert.assertEquals(argProvider.testEnum, TestEnum.THREE, "Enum value is not correct");
+    }
+
+    public enum TestEnum { ONE, TWO, THREE }
+
+    private class EnumArgProvider {
+        @Argument(fullName="test_enum",shortName="ti",doc="test enum",required=false)
+        public TestEnum testEnum = TestEnum.THREE;
+    }
+
+    @Test
+    public void typedCollectionTest() {
+        final String[] commandLine = new String[] { "-N","2","-N","4","-N","6","-N","8","-N","10" };
+
+        parsingEngine.addArgumentSource( IntegerListArgProvider.class );
+        parsingEngine.parse( commandLine );
+        parsingEngine.validate();
+
+        IntegerListArgProvider argProvider = new IntegerListArgProvider();
+        parsingEngine.loadArgumentsIntoObject( argProvider );
+
+        Assert.assertNotNull(argProvider.integers, "Argument array is null");
+        Assert.assertEquals(argProvider.integers.size(), 5, "Argument array is of incorrect length");
+        Assert.assertEquals(argProvider.integers.get(0).intValue(), 2, "1st integer is incorrect");
+        Assert.assertEquals(argProvider.integers.get(1).intValue(), 4, "2nd integer is incorrect");
+        Assert.assertEquals(argProvider.integers.get(2).intValue(), 6, "3rd integer is incorrect");
+        Assert.assertEquals(argProvider.integers.get(3).intValue(), 8, "4th integer is incorrect");
+        Assert.assertEquals(argProvider.integers.get(4).intValue(), 10, "5th integer is incorrect");
+    }
+
+    private class IntegerListArgProvider {
+        @Argument(fullName="integer_list",shortName="N",doc="integer list")
+        public List<Integer> integers;
+    }
+
+    @Test
+    public void untypedCollectionTest() {
+        final String[] commandLine = new String[] { "-N","2","-N","4","-N","6","-N","8","-N","10" };
+
+        parsingEngine.addArgumentSource( UntypedListArgProvider.class );
+        parsingEngine.parse( commandLine );
+        parsingEngine.validate();
+
+        UntypedListArgProvider argProvider = new UntypedListArgProvider();
+        parsingEngine.loadArgumentsIntoObject( argProvider );
+
+        Assert.assertNotNull(argProvider.integers, "Argument array is null");
+        Assert.assertEquals(argProvider.integers.size(), 5, "Argument array is of incorrect length");
+        Assert.assertEquals(argProvider.integers.get(0), "2", "1st integer is incorrect");
+        Assert.assertEquals(argProvider.integers.get(1), "4", "2nd integer is incorrect");
+        Assert.assertEquals(argProvider.integers.get(2), "6", "3rd integer is incorrect");
+        Assert.assertEquals(argProvider.integers.get(3), "8", "4th integer is incorrect");
+        Assert.assertEquals(argProvider.integers.get(4), "10", "5th integer is incorrect");
+    }
+
+    private class UntypedListArgProvider {
+        @Argument(fullName="untyped_list",shortName="N", doc="untyped list")
+        public List integers;
+    }
+
+    @Test(expectedExceptions=MissingArgumentException.class)
+    public void requiredArgTest() {
+        final String[] commandLine = new String[0];
+
+        parsingEngine.addArgumentSource( RequiredArgProvider.class );
+        parsingEngine.parse( commandLine );
+        parsingEngine.validate();
+    }
+
+    private class RequiredArgProvider {
+        @Argument(required=true,doc="value")
+        public Integer value;
+    }
+
+    @Test
+    public void defaultValueTest() {
+        // First try getting the default.
+        String[] commandLine = new String[0];
+
+        parsingEngine.addArgumentSource( DefaultValueArgProvider.class );
+        parsingEngine.parse( commandLine );
+        parsingEngine.validate();
+
+        DefaultValueArgProvider argProvider = new DefaultValueArgProvider();
+        parsingEngine.loadArgumentsIntoObject( argProvider );
+
+        Assert.assertEquals(argProvider.value.intValue(), 42, "Default value is not correctly initialized");
+
+        // Then try to override it.
+        commandLine = new String[] { "--value", "27" };
+
+        parsingEngine.parse( commandLine );
+        parsingEngine.validate();
+
+        parsingEngine.loadArgumentsIntoObject( argProvider );
+
+        Assert.assertEquals(argProvider.value.intValue(), 27, "Default value is not correctly initialized");
+    }
+
+    private class DefaultValueArgProvider {
+        @Argument(doc="value",required=false)
+        public Integer value = 42;
+    }
+
+    @Test
+    public void disableValidationOfRequiredArgTest() {
+        final String[] commandLine = new String[0];
+
+        parsingEngine.addArgumentSource( RequiredArgProvider.class );
+        parsingEngine.parse( commandLine );
+        parsingEngine.validate( EnumSet.of(ParsingEngine.ValidationType.MissingRequiredArgument) );
+
+        RequiredArgProvider argProvider = new RequiredArgProvider();
+        parsingEngine.loadArgumentsIntoObject(argProvider );
+
+        Assert.assertNull(argProvider.value, "Value should have remain unset");
+    }
+
+    @Test
+    public void unrequiredArgTest() {
+        final String[] commandLine = new String[0];
+
+        parsingEngine.addArgumentSource( UnrequiredArgProvider.class );
+        parsingEngine.parse( commandLine );
+        parsingEngine.validate();
+
+        UnrequiredArgProvider argProvider = new UnrequiredArgProvider();
+        parsingEngine.loadArgumentsIntoObject( argProvider );
+
+        Assert.assertNull(argProvider.value, "Value was unrequired and unspecified; contents should be null");
+    }
+
+    private class UnrequiredArgProvider {
+        @Argument(required=false,doc="unrequired value")
+        public Integer value;
+    }
+
+    @Test(expectedExceptions=InvalidArgumentException.class)
+    public void invalidArgTest() {
+        final String[] commandLine = new String[] { "--foo" };
+
+        parsingEngine.addArgumentSource( UnrequiredArgProvider.class );
+        parsingEngine.parse( commandLine );
+        parsingEngine.validate();
+    }
+
+    @Test(expectedExceptions= ReviewedGATKException.class)
+    public void duplicateLongNameTest() {
+        parsingEngine.addArgumentSource( DuplicateLongNameProvider.class );
+    }
+
+    private class DuplicateLongNameProvider {
+        @Argument(fullName="myarg",doc="my arg")
+        public Integer foo;
+
+        @Argument(fullName="myarg", doc="my arg")
+        public Integer bar;
+    }
+
+    @Test(expectedExceptions= ReviewedGATKException.class)
+    public void duplicateShortNameTest() {
+        parsingEngine.addArgumentSource( DuplicateShortNameProvider.class );
+    }
+
+
+    private class DuplicateShortNameProvider {
+        @Argument(shortName="myarg", doc="my arg")
+        public Integer foo;
+
+        @Argument(shortName="myarg", doc="my arg")
+        public Integer bar;
+    }
+
+    @Test(expectedExceptions=UnmatchedArgumentException.class)
+    public void missingArgumentNameTest() {
+        final String[] commandLine = new String[] {"foo.txt"};
+
+        parsingEngine.addArgumentSource( NoArgProvider.class );
+        parsingEngine.parse( commandLine );
+        parsingEngine.validate();
+    }
+
+    private class NoArgProvider {
+
+    }
+
+    @Test(expectedExceptions=UnmatchedArgumentException.class)
+    public void extraValueTest() {
+        final String[] commandLine = new String[] {"-I", "foo.txt", "bar.txt"};
+
+        parsingEngine.addArgumentSource( InputFileArgProvider.class );
+        parsingEngine.parse( commandLine );
+        parsingEngine.validate();
+    }
+
+    @Test(expectedExceptions=MissingArgumentException.class)
+    public void multipleInvalidArgTest() {
+        final String[] commandLine = new String[] {"-N1", "-N2", "-N3"};
+
+        parsingEngine.addArgumentSource( RequiredArgProvider.class );
+        parsingEngine.parse( commandLine );
+        parsingEngine.validate();
+    }
+
+    @Test(expectedExceptions=TooManyValuesForArgumentException.class)
+    public void invalidArgCountTest() {
+        final String[] commandLine = new String[] {"--value","1","--value","2","--value","3"};
+
+        parsingEngine.addArgumentSource( RequiredArgProvider.class );
+        parsingEngine.parse( commandLine );
+        parsingEngine.validate();
+    }
+
+    @Test
+    public void packageProtectedArgTest() {
+        final String[] commandLine = new String[] {"--foo", "1"};
+
+        parsingEngine.addArgumentSource( PackageProtectedArgProvider.class );
+        parsingEngine.parse( commandLine );
+        parsingEngine.validate();
+
+        PackageProtectedArgProvider argProvider = new PackageProtectedArgProvider();
+        parsingEngine.loadArgumentsIntoObject(argProvider);
+
+        Assert.assertEquals(argProvider.foo.intValue(), 1, "Argument is not correctly initialized");
+    }
+
+    private class PackageProtectedArgProvider {
+        @Argument(doc="foo")
+        Integer foo;
+    }
+
+    @Test
+    public void derivedArgTest() {
+        final String[] commandLine = new String[] {"--bar", "5"};
+
+        parsingEngine.addArgumentSource( DerivedArgProvider.class );
+        parsingEngine.parse( commandLine );
+        parsingEngine.validate();
+
+        DerivedArgProvider argProvider = new DerivedArgProvider();
+        parsingEngine.loadArgumentsIntoObject(argProvider);
+
+        Assert.assertEquals(argProvider.bar.intValue(), 5, "Argument is not correctly initialized");
+    }
+
+    private class DerivedArgProvider extends BaseArgProvider {
+    }
+
+    private class BaseArgProvider {
+        @Argument(doc="bar")
+        public Integer bar;
+    }
+
+    @Test
+    public void correctDefaultArgNameTest() {
+        parsingEngine.addArgumentSource( CamelCaseArgProvider.class );
+
+        DefinitionMatcher matcher = ArgumentDefinitions.FullNameDefinitionMatcher;
+        ArgumentDefinition definition = parsingEngine.argumentDefinitions.findArgumentDefinition("myarg", matcher);
+
+        Assert.assertNotNull(definition, "Invalid default argument name assigned");
+    }
+
+    @SuppressWarnings("unused")
+    private class CamelCaseArgProvider {
+        @Argument(doc="my arg")
+        Integer myArg;
+    }
+
+    @Test(expectedExceptions=UnmatchedArgumentException.class)
+    public void booleanWithParameterTest() {
+        final String[] commandLine = new String[] {"--mybool", "true"};
+
+        parsingEngine.addArgumentSource( BooleanArgProvider.class );
+        parsingEngine.parse( commandLine );
+        parsingEngine.validate();
+    }
+
+    @SuppressWarnings("unused")
+    private class BooleanArgProvider {
+        @Argument(doc="my bool")
+        boolean myBool;
+    }
+
+    @Test
+    public void validParseForAnalysisTypeTest() {
+        final String[] commandLine = new String[] {"--analysis_type", "Pileup" };
+
+        parsingEngine.addArgumentSource( AnalysisTypeArgProvider.class );
+        parsingEngine.parse( commandLine );
+        parsingEngine.validate( EnumSet.of(ParsingEngine.ValidationType.MissingRequiredArgument) );
+
+        AnalysisTypeArgProvider argProvider = new AnalysisTypeArgProvider();
+        parsingEngine.loadArgumentsIntoObject( argProvider );
+
+        Assert.assertEquals(argProvider.Analysis_Name,"Pileup","Argument is not correctly initialized");
+    }
+
+    private class AnalysisTypeArgProvider {
+        @Argument(fullName="analysis_type", shortName="T", doc="Type of analysis to run")
+        public String Analysis_Name = null;
+    }
+
+    @Test(expectedExceptions=TooManyValuesForArgumentException.class)
+    public void invalidParseForAnalysisTypeTest() {
+        final String[] commandLine = new String[] {"--analysis_type", "Pileup", "-T", "CountReads" };
+
+        parsingEngine.addArgumentSource( AnalysisTypeArgProvider.class );
+        parsingEngine.parse( commandLine );
+        parsingEngine.validate( EnumSet.of(ParsingEngine.ValidationType.MissingRequiredArgument) );
+    }
+
+    @Test(expectedExceptions=ArgumentsAreMutuallyExclusiveException.class)
+    public void mutuallyExclusiveArgumentsTest() {
+        // Passing only foo should work fine...
+        String[] commandLine = new String[] {"--foo","5"};
+
+        parsingEngine.addArgumentSource( MutuallyExclusiveArgProvider.class );
+        parsingEngine.parse( commandLine );
+        parsingEngine.validate();
+
+        MutuallyExclusiveArgProvider argProvider = new MutuallyExclusiveArgProvider();
+        parsingEngine.loadArgumentsIntoObject( argProvider );
+
+        Assert.assertEquals(argProvider.foo.intValue(), 5, "Argument is not correctly initialized");
+
+        // But when foo and bar come together, danger!
+        commandLine = new String[] {"--foo","5","--bar","6"};
+
+        parsingEngine.parse( commandLine );
+        parsingEngine.validate();
+    }
+
+    @SuppressWarnings("unused")
+    private class MutuallyExclusiveArgProvider {
+        @Argument(doc="foo",exclusiveOf="bar")
+        Integer foo;
+
+        @Argument(doc="bar",required=false)
+        Integer bar;
+    }
+
+    @Test(expectedExceptions=InvalidArgumentValueException.class)
+    public void argumentValidationTest() {
+        // Passing only foo should work fine...
+        String[] commandLine = new String[] {"--value","521"};
+
+        parsingEngine.addArgumentSource( ValidatingArgProvider.class );
+        parsingEngine.parse( commandLine );
+        parsingEngine.validate();
+
+        ValidatingArgProvider argProvider = new ValidatingArgProvider();
+        parsingEngine.loadArgumentsIntoObject( argProvider );
+
+        Assert.assertEquals(argProvider.value.intValue(), 521, "Argument is not correctly initialized");
+
+        // Try some invalid arguments
+        commandLine = new String[] {"--value","foo"};
+        parsingEngine.parse( commandLine );
+        parsingEngine.validate();
+    }
+
+    private class ValidatingArgProvider {
+        @Argument(doc="value",validation="\\d+")
+        Integer value;
+    }
+
+    @Test
+    public void argumentCollectionTest() {
+        String[] commandLine = new String[] { "--value", "5" };
+
+        parsingEngine.addArgumentSource( ArgumentCollectionProvider.class );
+        parsingEngine.parse( commandLine );
+        parsingEngine.validate();
+
+        ArgumentCollectionProvider argProvider = new ArgumentCollectionProvider();
+        parsingEngine.loadArgumentsIntoObject(argProvider);
+
+        Assert.assertEquals(argProvider.rap.value.intValue(), 5, "Argument is not correctly initialized");
+    }
+
+    private class ArgumentCollectionProvider {
+        @ArgumentCollection
+        RequiredArgProvider rap = new RequiredArgProvider();
+    }
+
+    @Test(expectedExceptions= ReviewedGATKException.class)
+    public void multipleArgumentCollectionTest() {
+        parsingEngine.addArgumentSource( MultipleArgumentCollectionProvider.class );
+    }
+
+    @SuppressWarnings("unused")
+    private class MultipleArgumentCollectionProvider {
+        @ArgumentCollection
+        RequiredArgProvider rap1 = new RequiredArgProvider();
+        @ArgumentCollection
+        RequiredArgProvider rap2 = new RequiredArgProvider();
+    }
+
+    // --------------------------------------------------------------------------------
+    //
+    // Tests of the RodBinding<T> system
+    //
+    // --------------------------------------------------------------------------------
+
+    private class SingleRodBindingArgProvider {
+        @Input(fullName="binding", shortName="V", required=true)
+        public RodBinding<Feature> binding;
+    }
+
+    @Test
+    public void basicRodBindingArgumentTest() {
+        final String[] commandLine = new String[] {"-V:vcf",NON_EXISTANT_FILENAME_VCF};
+
+        parsingEngine.addArgumentSource( SingleRodBindingArgProvider.class );
+        parsingEngine.parse( commandLine );
+        parsingEngine.validate();
+
+        SingleRodBindingArgProvider argProvider = new SingleRodBindingArgProvider();
+        parsingEngine.loadArgumentsIntoObject( argProvider );
+
+        Assert.assertEquals(argProvider.binding.getName(), "binding", "Name isn't set properly");
+        Assert.assertEquals(argProvider.binding.getSource(), NON_EXISTANT_FILENAME_VCF, "Source isn't set to its expected value");
+        Assert.assertEquals(argProvider.binding.getType(), Feature.class, "Type isn't set to its expected value");
+        Assert.assertEquals(argProvider.binding.isBound(), true, "Bound() isn't returning its expected value");
+        Assert.assertEquals(argProvider.binding.getTags().getPositionalTags().size(), 1, "Tags aren't correctly set");
+    }
+
+    private class ShortNameOnlyRodBindingArgProvider {
+        @Input(shortName="short", required=false)
+        public RodBinding<Feature> binding; // = RodBinding.makeUnbound(Feature.class);
+    }
+
+    @Test
+    public void shortNameOnlyRodBindingArgumentTest() {
+        final String[] commandLine = new String[] {"-short:vcf",NON_EXISTANT_FILENAME_VCF};
+
+        parsingEngine.addArgumentSource( ShortNameOnlyRodBindingArgProvider.class );
+        parsingEngine.parse( commandLine );
+        parsingEngine.validate();
+
+        ShortNameOnlyRodBindingArgProvider argProvider = new ShortNameOnlyRodBindingArgProvider();
+        parsingEngine.loadArgumentsIntoObject( argProvider );
+
+        Assert.assertEquals(argProvider.binding.getName(), "binding", "Name isn't set properly");
+        Assert.assertEquals(argProvider.binding.getSource(), NON_EXISTANT_FILENAME_VCF, "Source isn't set to its expected value");
+        Assert.assertEquals(argProvider.binding.getType(), Feature.class, "Type isn't set to its expected value");
+        Assert.assertEquals(argProvider.binding.isBound(), true, "Bound() isn't returning its expected value");
+        Assert.assertEquals(argProvider.binding.getTags().getPositionalTags().size(), 1, "Tags aren't correctly set");
+    }
+
+    private class OptionalRodBindingArgProvider {
+        @Input(fullName="binding", shortName="V", required=false)
+        public RodBinding<Feature> binding;
+
+        @Input(fullName="bindingNull", shortName="VN", required=false)
+        public RodBinding<VariantContext> bindingNull = null;
+    }
+
+    @Test
+    public void optionalRodBindingArgumentTest() {
+        final String[] commandLine = new String[] {};
+
+        parsingEngine.addArgumentSource( OptionalRodBindingArgProvider.class );
+        parsingEngine.parse( commandLine );
+        parsingEngine.validate();
+
+        OptionalRodBindingArgProvider argProvider = new OptionalRodBindingArgProvider();
+        parsingEngine.loadArgumentsIntoObject( argProvider );
+
+        Assert.assertNotNull(argProvider.binding, "Default value not applied corrected to RodBinding");
+        Assert.assertEquals(argProvider.binding.getName(), RodBinding.UNBOUND_VARIABLE_NAME, "Name isn't set properly");
+        Assert.assertEquals(argProvider.binding.getSource(), RodBinding.UNBOUND_SOURCE, "Source isn't set to its expected value");
+        Assert.assertEquals(argProvider.binding.getType(), Feature.class, "Type isn't set to its expected value");
+        Assert.assertEquals(argProvider.binding.isBound(), false, "Bound() isn't returning its expected value");
+        Assert.assertEquals(argProvider.binding.getTags().getPositionalTags().size(), 0, "Tags aren't correctly set");
+
+        Assert.assertNotNull(argProvider.bindingNull, "Default value not applied corrected to RodBinding");
+        Assert.assertEquals(argProvider.bindingNull.getName(), RodBinding.UNBOUND_VARIABLE_NAME, "Name isn't set properly");
+        Assert.assertEquals(argProvider.bindingNull.getSource(), RodBinding.UNBOUND_SOURCE, "Source isn't set to its expected value");
+        Assert.assertEquals(argProvider.bindingNull.getType(), VariantContext.class, "Type isn't set to its expected value");
+        Assert.assertEquals(argProvider.bindingNull.isBound(), false, "Bound() isn't returning its expected value");
+        Assert.assertEquals(argProvider.bindingNull.getTags().getPositionalTags().size(), 0, "Tags aren't correctly set");
+    }
+
+    @Test(expectedExceptions = UserException.class)
+    public void rodBindingArgumentTestMissingType() {
+        final String[] commandLine = new String[] {"-V",NON_EXISTANT_FILENAME_VCF};
+
+        parsingEngine.addArgumentSource( SingleRodBindingArgProvider.class );
+        parsingEngine.parse( commandLine );
+        parsingEngine.validate();
+
+        SingleRodBindingArgProvider argProvider = new SingleRodBindingArgProvider();
+        parsingEngine.loadArgumentsIntoObject(argProvider);
+    }
+
+    @Test(expectedExceptions = UserException.class)
+    public void rodBindingArgumentTestTooManyTags() {
+        final String[] commandLine = new String[] {"-V:x,y,z",NON_EXISTANT_FILENAME_VCF};
+
+        parsingEngine.addArgumentSource( SingleRodBindingArgProvider.class );
+        parsingEngine.parse( commandLine );
+        parsingEngine.validate();
+
+        SingleRodBindingArgProvider argProvider = new SingleRodBindingArgProvider();
+        parsingEngine.loadArgumentsIntoObject(argProvider);
+    }
+
+    private class VariantContextRodBindingArgProvider {
+        @Input(fullName = "binding", shortName="V")
+        public RodBinding<VariantContext> binding;
+    }
+
+    @Test
+    public void variantContextBindingArgumentTest() {
+        final String[] commandLine = new String[] {"-V:vcf",NON_EXISTANT_FILENAME_VCF};
+
+        parsingEngine.addArgumentSource( VariantContextRodBindingArgProvider.class );
+        parsingEngine.parse( commandLine );
+        parsingEngine.validate();
+
+        VariantContextRodBindingArgProvider argProvider = new VariantContextRodBindingArgProvider();
+        parsingEngine.loadArgumentsIntoObject( argProvider );
+
+        Assert.assertEquals(argProvider.binding.getName(), "binding", "Name isn't set properly");
+        Assert.assertEquals(argProvider.binding.getSource(), NON_EXISTANT_FILENAME_VCF, "Source isn't set to its expected value");
+        Assert.assertEquals(argProvider.binding.getType(), VariantContext.class, "Type isn't set to its expected value");
+        Assert.assertEquals(argProvider.binding.getTags().getPositionalTags().size(), 1, "Tags aren't correctly set");
+    }
+
+    private class ListRodBindingArgProvider {
+        @Input(fullName = "binding", shortName="V", required=false)
+        public List<RodBinding<Feature>> bindings;
+    }
+
+    @Test
+    public void listRodBindingArgumentTest() {
+        final String[] commandLine = new String[] {"-V:vcf",NON_EXISTANT_FILENAME_VCF};
+
+        parsingEngine.addArgumentSource( ListRodBindingArgProvider.class );
+        parsingEngine.parse( commandLine );
+        parsingEngine.validate();
+
+        ListRodBindingArgProvider argProvider = new ListRodBindingArgProvider();
+        parsingEngine.loadArgumentsIntoObject( argProvider );
+
+        Assert.assertEquals(argProvider.bindings.size(), 1, "Unexpected number of bindings");
+        RodBinding<Feature> binding = argProvider.bindings.get(0);
+        Assert.assertEquals(binding.getName(), "binding", "Name isn't set properly");
+        Assert.assertEquals(binding.getSource(), NON_EXISTANT_FILENAME_VCF, "Source isn't set to its expected value");
+        Assert.assertEquals(binding.getType(), Feature.class, "Type isn't set to its expected value");
+        Assert.assertEquals(binding.getTags().getPositionalTags().size(), 1, "Tags aren't correctly set");
+    }
+
+    @Test
+    public void listRodBindingArgumentTest2Args() {
+        final String[] commandLine = new String[] {"-V:vcf",NON_EXISTANT_FILENAME_VCF, "-V:vcf", "bar.vcf"};
+
+        parsingEngine.addArgumentSource( ListRodBindingArgProvider.class );
+        parsingEngine.parse( commandLine );
+        parsingEngine.validate();
+
+        ListRodBindingArgProvider argProvider = new ListRodBindingArgProvider();
+        parsingEngine.loadArgumentsIntoObject( argProvider );
+
+        Assert.assertEquals(argProvider.bindings.size(), 2, "Unexpected number of bindings");
+
+        RodBinding<Feature> binding = argProvider.bindings.get(0);
+        Assert.assertEquals(binding.getName(), "binding", "Name isn't set properly");
+        Assert.assertEquals(binding.getSource(), NON_EXISTANT_FILENAME_VCF, "Source isn't set to its expected value");
+        Assert.assertEquals(binding.getType(), Feature.class, "Type isn't set to its expected value");
+        Assert.assertEquals(binding.getTags().getPositionalTags().size(), 1, "Tags aren't correctly set");
+
+        RodBinding<Feature> binding2 = argProvider.bindings.get(1);
+        Assert.assertEquals(binding2.getName(), "binding2", "Name isn't set properly");
+        Assert.assertEquals(binding2.getSource(), "bar.vcf", "Source isn't set to its expected value");
+        Assert.assertEquals(binding2.getType(), Feature.class, "Type isn't set to its expected value");
+        Assert.assertEquals(binding2.getTags().getPositionalTags().size(), 1, "Tags aren't correctly set");
+    }
+
+    @Test
+    public void listRodBindingArgumentTest0Args() {
+        final String[] commandLine = new String[] {};
+
+        parsingEngine.addArgumentSource( ListRodBindingArgProvider.class );
+        parsingEngine.parse( commandLine );
+        parsingEngine.validate();
+
+        ListRodBindingArgProvider argProvider = new ListRodBindingArgProvider();
+        parsingEngine.loadArgumentsIntoObject( argProvider );
+
+        Assert.assertNull(argProvider.bindings, "Bindings were not null");
+    }
+
+    @Test
+    public void listRodBindingArgumentTestExplicitlyNamed() {
+        final String[] commandLine = new String[] {"-V:foo,vcf",NON_EXISTANT_FILENAME_VCF, "-V:foo,vcf", "bar.vcf"};
+
+        parsingEngine.addArgumentSource( ListRodBindingArgProvider.class );
+        parsingEngine.parse( commandLine );
+        parsingEngine.validate();
+
+        ListRodBindingArgProvider argProvider = new ListRodBindingArgProvider();
+        parsingEngine.loadArgumentsIntoObject( argProvider );
+
+        Assert.assertEquals(argProvider.bindings.size(), 2, "Unexpected number of bindings");
+        Assert.assertEquals(argProvider.bindings.get(0).getName(), "foo", "Name isn't set properly");
+        Assert.assertEquals(argProvider.bindings.get(1).getName(), "foo2", "Name isn't set properly");
+    }
+
+    private final static String HISEQ_VCF = privateTestDir + "HiSeq.10000.vcf";
+    private final static String TRANCHES_FILE = privateTestDir + "tranches.6.txt";
+
+    @Test
+    public void variantContextBindingTestDynamicTyping1() {
+        final String[] commandLine = new String[] {"-V", HISEQ_VCF};
+
+        parsingEngine.addArgumentSource( VariantContextRodBindingArgProvider.class );
+        parsingEngine.parse( commandLine );
+        parsingEngine.validate();
+
+        VariantContextRodBindingArgProvider argProvider = new VariantContextRodBindingArgProvider();
+        parsingEngine.loadArgumentsIntoObject( argProvider );
+
+        Assert.assertEquals(argProvider.binding.getName(), "binding", "Name isn't set properly");
+        Assert.assertEquals(argProvider.binding.getSource(), HISEQ_VCF, "Source isn't set to its expected value");
+        Assert.assertEquals(argProvider.binding.getType(), VariantContext.class, "Type isn't set to its expected value");
+        Assert.assertEquals(argProvider.binding.getTags().getPositionalTags().size(), 0, "Tags aren't correctly set");
+    }
+
+    @Test
+    public void variantContextBindingTestDynamicTypingNameAsSingleArgument() {
+        final String[] commandLine = new String[] {"-V:name", HISEQ_VCF};
+
+        parsingEngine.addArgumentSource( VariantContextRodBindingArgProvider.class );
+        parsingEngine.parse( commandLine );
+        parsingEngine.validate();
+
+        VariantContextRodBindingArgProvider argProvider = new VariantContextRodBindingArgProvider();
+        parsingEngine.loadArgumentsIntoObject( argProvider );
+
+        Assert.assertEquals(argProvider.binding.getName(), "name", "Name isn't set properly");
+        Assert.assertEquals(argProvider.binding.getSource(), HISEQ_VCF, "Source isn't set to its expected value");
+        Assert.assertEquals(argProvider.binding.getType(), VariantContext.class, "Type isn't set to its expected value");
+        Assert.assertEquals(argProvider.binding.getTags().getPositionalTags().size(), 1, "Tags aren't correctly set");
+    }
+
+    @Test()
+    public void variantContextBindingTestDynamicTypingTwoTagsPassing() {
+        final String[] commandLine = new String[] {"-V:name,vcf", HISEQ_VCF};
+
+        parsingEngine.addArgumentSource( VariantContextRodBindingArgProvider.class );
+        parsingEngine.parse( commandLine );
+        parsingEngine.validate();
+
+        VariantContextRodBindingArgProvider argProvider = new VariantContextRodBindingArgProvider();
+        parsingEngine.loadArgumentsIntoObject( argProvider );
+
+        Assert.assertEquals(argProvider.binding.getName(), "name", "Name isn't set properly");
+        Assert.assertEquals(argProvider.binding.getSource(), HISEQ_VCF, "Source isn't set to its expected value");
+        Assert.assertEquals(argProvider.binding.getType(), VariantContext.class, "Type isn't set to its expected value");
+        Assert.assertEquals(argProvider.binding.getTags().getPositionalTags().size(), 2, "Tags aren't correctly set");
+    }
+
+    @Test()
+    public void variantContextBindingTestDynamicTypingTwoTagsCausingTypeFailure() {
+        final String[] commandLine = new String[] {"-V:name,beagle", HISEQ_VCF};
+
+        parsingEngine.addArgumentSource( VariantContextRodBindingArgProvider.class );
+        parsingEngine.parse( commandLine );
+        parsingEngine.validate();
+
+        VariantContextRodBindingArgProvider argProvider = new VariantContextRodBindingArgProvider();
+        parsingEngine.loadArgumentsIntoObject(argProvider);
+
+        Assert.assertEquals(argProvider.binding.getName(), "name", "Name isn't set properly");
+        Assert.assertEquals(argProvider.binding.getSource(), HISEQ_VCF, "Source isn't set to its expected value");
+        Assert.assertEquals(argProvider.binding.getType(), VariantContext.class, "Type isn't set to its expected value");
+        Assert.assertEquals(argProvider.binding.getTribbleType(), "beagle", "Type isn't set to its expected value");
+        Assert.assertEquals(argProvider.binding.getTags().getPositionalTags().size(), 2, "Tags aren't correctly set");
+    }
+
+    @Test(expectedExceptions = UserException.class)
+    public void variantContextBindingTestDynamicTypingUnknownTribbleType() {
+        final String[] commandLine = new String[] {"-V", TRANCHES_FILE};
+
+        parsingEngine.addArgumentSource( VariantContextRodBindingArgProvider.class );
+        parsingEngine.parse( commandLine );
+        parsingEngine.validate();
+
+        VariantContextRodBindingArgProvider argProvider = new VariantContextRodBindingArgProvider();
+        parsingEngine.loadArgumentsIntoObject( argProvider );
+    }
+
+    @Test
+    public void argumentListTest() throws IOException {
+        File argsFile = BaseTest.createTempListFile("args.", "-I na12878.bam");
+        try {
+            final String[] commandLine = new String[] {"-args", argsFile.getPath()};
+            parsingEngine.addArgumentSource(InputFileArgProvider.class);
+            parsingEngine.parse(commandLine);
+            parsingEngine.validate();
+
+            InputFileArgProvider argProvider = new InputFileArgProvider();
+            parsingEngine.loadArgumentsIntoObject(argProvider);
+
+            Assert.assertEquals(argProvider.inputFile, "na12878.bam", "Argument is not correctly initialized");
+        } finally {
+            FileUtils.deleteQuietly(argsFile);
+        }
+    }
+
+    @SuppressWarnings("unused")
+    private class NumericRangeArgProvider {
+        @Argument(fullName = "intWithHardMinAndMax", minValue = 5, maxValue = 10)
+        public int intWithHardMinAndMax;
+
+        @Argument(fullName = "intWithHardMin", minValue = 5)
+        public int intWithHardMin;
+
+        @Argument(fullName = "intWithHardMax", maxValue = 10)
+        public int intWithHardMax;
+
+        @Argument(fullName = "intWithSoftMinAndMax", minRecommendedValue = 5, maxRecommendedValue = 10)
+        public int intWithSoftMinAndMax;
+
+        @Argument(fullName = "intWithSoftMin", minRecommendedValue = 5)
+        public int intWithSoftMin;
+
+        @Argument(fullName = "intWithSoftMax", maxRecommendedValue = 10)
+        public int intWithSoftMax;
+
+        @Argument(fullName = "intWithHardAndSoftMinAndMax", minValue = 5, minRecommendedValue = 7, maxValue = 10, maxRecommendedValue = 9)
+        public int intWithHardAndSoftMinAndMax;
+
+        @Argument(fullName = "intWithHardAndSoftMin", minValue = 5, minRecommendedValue = 7)
+        public int intWithHardAndSoftMin;
+
+        @Argument(fullName = "intWithHardAndSoftMax", maxValue = 10, maxRecommendedValue = 8)
+        public int intWithHardAndSoftMax;
+
+        @Argument(fullName = "intWithHardMinAndMaxDefaultOutsideRange", minValue = 5, maxValue = 10)
+        public int intWithHardMinAndMaxDefaultOutsideRange = -1;
+
+        @Argument(fullName = "integerWithHardMinAndMax", minValue = 5, maxValue = 10)
+        public Integer integerWithHardMinAndMax;
+
+        @Argument(fullName = "byteWithHardMinAndMax", minValue = 5, maxValue = 10)
+        public byte byteWithHardMinAndMax;
+
+        @Argument(fullName = "byteWithHardMin", minValue = 5)
+        public byte byteWithHardMin;
+
+        @Argument(fullName = "byteWithHardMax", maxValue = 10)
+        public byte byteWithHardMax;
+
+        @Argument(fullName = "doubleWithHardMinAndMax", minValue = 5.5, maxValue = 10.0)
+        public double doubleWithHardMinAndMax;
+
+        @Argument(fullName = "doubleWithHardMin", minValue = 5.5)
+        public double doubleWithHardMin;
+
+        @Argument(fullName = "doubleWithHardMax", maxValue = 10.0)
+        public double doubleWithHardMax;
+    }
+
+    @DataProvider(name = "NumericRangeConstraintViolationDataProvider")
+    public Object[][] numericRangeConstraintViolationDataProvider() {
+        return new Object[][] {
+                { new String[]{"--intWithHardMinAndMax", "11"} },
+                { new String[]{"--intWithHardMinAndMax", "4"} },
+                { new String[]{"--intWithHardMin", "4"} },
+                { new String[]{"--intWithHardMax", "11"} },
+                { new String[]{"--intWithHardAndSoftMinAndMax", "11"} },
+                { new String[]{"--intWithHardAndSoftMinAndMax", "4"} },
+                { new String[]{"--intWithHardAndSoftMin", "4"} },
+                { new String[]{"--intWithHardAndSoftMax", "11"} },
+                { new String[]{"--intWithHardMinAndMaxDefaultOutsideRange", "11"} },
+                { new String[]{"--intWithHardMinAndMaxDefaultOutsideRange", "4"} },
+                { new String[]{"--integerWithHardMinAndMax", "11"} },
+                { new String[]{"--integerWithHardMinAndMax", "4"} },
+                { new String[]{"--byteWithHardMinAndMax", "11"} },
+                { new String[]{"--byteWithHardMinAndMax", "4"} },
+                { new String[]{"--byteWithHardMin", "4"} },
+                { new String[]{"--byteWithHardMax", "11"} },
+                { new String[]{"--doubleWithHardMinAndMax", "5.4"} },
+                { new String[]{"--doubleWithHardMinAndMax", "10.1"} },
+                { new String[]{"--doubleWithHardMin", "5.4"} },
+                { new String[]{"--doubleWithHardMax", "10.1"} }
+        };
+    }
+
+    @Test(dataProvider = "NumericRangeConstraintViolationDataProvider",
+          expectedExceptions = ArgumentValueOutOfRangeException.class)
+    public void testNumericRangeWithConstraintViolation( final String[] commandLine ) {
+        runNumericArgumentRangeTest(commandLine);
+    }
+
+    @DataProvider(name = "NumericRangeWithoutConstraintViolationDataProvider")
+    public Object[][] numericRangeWithoutConstraintViolationDataProvider() {
+        return new Object[][] {
+                { new String[]{"--intWithHardMinAndMax", "10"} },
+                { new String[]{"--intWithHardMinAndMax", "5"} },
+                { new String[]{"--intWithHardMinAndMax", "7"} },
+                { new String[]{"--intWithHardMin", "11"} },
+                { new String[]{"--intWithHardMax", "4"} },
+                { new String[]{"--intWithSoftMinAndMax", "11"} },
+                { new String[]{"--intWithSoftMinAndMax", "4"} },
+                { new String[]{"--intWithSoftMin", "4"} },
+                { new String[]{"--intWithSoftMax", "11"} },
+                { new String[]{"--intWithHardAndSoftMinAndMax", "5"} },
+                { new String[]{"--intWithHardAndSoftMinAndMax", "7"} },
+                { new String[]{"--intWithHardAndSoftMinAndMax", "8"} },
+                { new String[]{"--intWithHardAndSoftMinAndMax", "9"} },
+                { new String[]{"--intWithHardAndSoftMinAndMax", "10"} },
+                { new String[]{"--intWithHardAndSoftMin", "5"} },
+                { new String[]{"--intWithHardAndSoftMin", "6"} },
+                { new String[]{"--intWithHardAndSoftMin", "7"} },
+                { new String[]{"--intWithHardAndSoftMax", "10"} },
+                { new String[]{"--intWithHardAndSoftMax", "9"} },
+                { new String[]{"--intWithHardAndSoftMax", "8"} },
+                { new String[]{"--intWithHardMinAndMaxDefaultOutsideRange", "10"} },
+                { new String[]{"--intWithHardMinAndMaxDefaultOutsideRange", "5"} },
+                { new String[]{"--intWithHardMinAndMaxDefaultOutsideRange", "7"} },
+                { new String[]{"--integerWithHardMinAndMax", "10"} },
+                { new String[]{"--integerWithHardMinAndMax", "5"} },
+                { new String[]{"--byteWithHardMinAndMax", "10"} },
+                { new String[]{"--byteWithHardMinAndMax", "5"} },
+                { new String[]{"--byteWithHardMinAndMax", "7"} },
+                { new String[]{"--byteWithHardMin", "5"} },
+                { new String[]{"--byteWithHardMax", "10"} },
+                { new String[]{"--doubleWithHardMinAndMax", "5.5"} },
+                { new String[]{"--doubleWithHardMinAndMax", "10.0"} },
+                { new String[]{"--doubleWithHardMinAndMax", "7.5"} },
+                { new String[]{"--doubleWithHardMin", "5.5"} },
+                { new String[]{"--doubleWithHardMin", "15.5"} },
+                { new String[]{"--doubleWithHardMax", "10.0"} },
+                { new String[]{"--doubleWithHardMax", "7.5"} }
+        };
+    }
+
+    @Test(dataProvider = "NumericRangeWithoutConstraintViolationDataProvider")
+    public void testNumericRangeWithoutConstraintViolation( final String[] commandLine ) {
+        // These tests succeed if no exception is thrown, since no constraints have been violated
+        runNumericArgumentRangeTest(commandLine);
+    }
+
+    private void runNumericArgumentRangeTest( final String[] commandLine ) {
+        parsingEngine.addArgumentSource(NumericRangeArgProvider.class);
+        parsingEngine.parse(commandLine);
+
+        NumericRangeArgProvider argProvider = new NumericRangeArgProvider();
+        parsingEngine.loadArgumentsIntoObject(argProvider);
+    }
+
+    @SuppressWarnings("unused")
+    private class VariedTypeArgProvider {
+        @Argument(fullName = "intVal", required=false)
+        private int anInt;
+
+        @Argument(fullName = "stringVal", required=false)
+        private String aString;
+
+        @Argument(fullName = "enumVal", required=false)
+        private TestEnum anEnum;
+
+        @Argument(fullName = "fileVal", required=false)
+        private File aFile;
+
+        @Argument(fullName = "stringSet", required=false)
+        private Set<String> someStrings;
+
+        @Argument(fullName = "intervalVal", required=false)
+        private IntervalBinding<Feature> anInterval;
+    }
+
+    @DataProvider(name = "MissingArgumentValueDataProvider")
+    public Object[][] missingArgumentDataProvider() {
+        return new Object[][]{
+                { new String[]{"--intVal"} },
+                { new String[]{"--stringVal"} },
+                { new String[]{"--enumVal"} },
+                { new String[]{"--fileVal"} },
+                { new String[]{"--stringSet"} },
+                { new String[]{"--stringSet", "aha", "--stringSet"} },
+                { new String[]{"--intervalVal"} }
+        };
+    }
+
+    @Test(dataProvider = "MissingArgumentValueDataProvider",
+          expectedExceptions = {InvalidArgumentValueException.class, MissingArgumentValueException.class})
+    public void testMissingArguments( final String[] commandLine ) {
+        parsingEngine.addArgumentSource( VariedTypeArgProvider.class );
+        parsingEngine.parse( commandLine );
+        parsingEngine.validate();
+
+        VariedTypeArgProvider argProvider = new VariedTypeArgProvider();
+        parsingEngine.loadArgumentsIntoObject(argProvider);
+    }
+
+}
diff --git a/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/utils/commandline/RodBindingCollectionUnitTest.java b/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/utils/commandline/RodBindingCollectionUnitTest.java
new file mode 100644
index 0000000..a846384
--- /dev/null
+++ b/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/utils/commandline/RodBindingCollectionUnitTest.java
@@ -0,0 +1,133 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.utils.commandline;
+
+import org.broadinstitute.gatk.utils.BaseTest;
+import org.broadinstitute.gatk.utils.exceptions.UserException;
+import htsjdk.variant.variantcontext.VariantContext;
+import org.testng.Assert;
+import org.testng.annotations.BeforeMethod;
+import org.testng.annotations.Test;
+
+import java.io.File;
+import java.io.FileWriter;
+import java.io.IOException;
+import java.util.Collection;
+
+public class RodBindingCollectionUnitTest extends BaseTest {
+
+    private ParsingEngine parsingEngine;
+    private Tags mytags;
+
+    private static final String defaultTagString = "VCF";
+    private static final String testVCFFileName = privateTestDir + "empty.vcf";
+    private static final String testListFileName = createTempListFile("oneVCF", testVCFFileName).getAbsolutePath();
+
+    @BeforeMethod
+    public void setUp() {
+        parsingEngine = new ParsingEngine(null);
+        RodBinding.resetNameCounter();
+        mytags = new Tags();
+        mytags.addPositionalTag(defaultTagString);
+    }
+
+    private class RodBindingCollectionArgProvider {
+        @Argument(fullName="input",doc="input",shortName="V")
+        public RodBindingCollection<VariantContext> input;
+    }
+
+    @Test
+    public void testStandardVCF() {
+        final String[] commandLine = new String[] {"-V", testVCFFileName};
+
+        parsingEngine.addArgumentSource( RodBindingCollectionArgProvider.class );
+        parsingEngine.parse( commandLine );
+        parsingEngine.validate();
+
+        final RodBindingCollectionArgProvider argProvider = new RodBindingCollectionArgProvider();
+        parsingEngine.loadArgumentsIntoObject( argProvider );
+
+        Assert.assertEquals(argProvider.input.getRodBindings().iterator().next().getSource(), testVCFFileName, "Argument is not correctly initialized");
+    }
+
+    @Test
+    public void testList() {
+        final String[] commandLine = new String[] {"-V", testListFileName};
+
+        parsingEngine.addArgumentSource(RodBindingCollectionArgProvider.class);
+        parsingEngine.parse( commandLine );
+        parsingEngine.validate();
+
+        final RodBindingCollectionArgProvider argProvider = new RodBindingCollectionArgProvider();
+        parsingEngine.loadArgumentsIntoObject( argProvider );
+
+        Assert.assertEquals(argProvider.input.getRodBindings().iterator().next().getSource(), testVCFFileName, "Argument is not correctly initialized");
+    }
+
+    @Test
+    public void testDefaultTagsInFile() throws IOException {
+
+        final File testFile = createTempListFile("RodBindingCollectionUnitTest.defaultTags", testVCFFileName);
+
+        ArgumentTypeDescriptor.getRodBindingsCollection(testFile, parsingEngine, VariantContext.class, "foo", mytags, "input");
+
+        final Collection<RodBinding> bindings = parsingEngine.getRodBindings();
+        Assert.assertNotNull(bindings);
+        Assert.assertEquals(bindings.size(), 1);
+
+        final RodBinding binding = bindings.iterator().next();
+        Assert.assertEquals(parsingEngine.getTags(binding), mytags);
+    }
+
+    @Test(expectedExceptions = UserException.BadArgumentValue.class)
+    public void testDuplicateEntriesInFile() throws IOException {
+
+        final File testFile = createTempListFile("RodBindingCollectionUnitTest.variantListWithDuplicates", testVCFFileName, testVCFFileName);
+
+        ArgumentTypeDescriptor.getRodBindingsCollection(testFile, parsingEngine, VariantContext.class, "foo", mytags, "input");
+    }
+
+    @Test(expectedExceptions = UserException.BadArgumentValue.class)
+    public void testValidateEmptyFile() throws IOException {
+        final File testFile = createTempListFile("RodBindingCollectionUnitTest.emptyVCFList");
+
+        ArgumentTypeDescriptor.getRodBindingsCollection(testFile, parsingEngine, VariantContext.class, "foo", mytags, "input");
+    }
+
+    @Test
+    public void testOverrideTagsInFile() throws IOException {
+        final File testFile = createTempListFile("RodBindingCollectionUnitTest.overrideTags", "foo " + testVCFFileName);
+
+        ArgumentTypeDescriptor.getRodBindingsCollection(testFile, parsingEngine, VariantContext.class, "foo", mytags, "input");
+
+        final Collection<RodBinding> bindings = parsingEngine.getRodBindings();
+        Assert.assertNotNull(bindings);
+        Assert.assertEquals(bindings.size(), 1);
+
+        final RodBinding binding = bindings.iterator().next();
+        Assert.assertNotEquals(parsingEngine.getTags(binding), mytags);
+    }
+}
diff --git a/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/utils/commandline/RodBindingUnitTest.java b/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/utils/commandline/RodBindingUnitTest.java
new file mode 100644
index 0000000..bffb1d2
--- /dev/null
+++ b/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/utils/commandline/RodBindingUnitTest.java
@@ -0,0 +1,82 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.utils.commandline;
+
+import org.broadinstitute.gatk.utils.BaseTest;
+import htsjdk.variant.variantcontext.VariantContext;
+import org.testng.Assert;
+import org.testng.annotations.Test;
+import org.testng.annotations.BeforeMethod;
+
+/**
+ * Test suite for the parsing engine.
+ */
+public class RodBindingUnitTest extends BaseTest {
+    Tags mytags = new Tags();
+
+    @BeforeMethod
+    public void setUp() {
+        RodBinding.resetNameCounter();
+    }
+
+    @Test
+    public void testStandardRodBinding() {
+        RodBinding<VariantContext> b = new RodBinding<VariantContext>(VariantContext.class, "b", "foo", "vcf", mytags);
+        Assert.assertEquals(b.getName(), "b");
+        Assert.assertEquals(b.getType(), VariantContext.class);
+        Assert.assertEquals(b.getSource(), "foo");
+        Assert.assertEquals(b.getTribbleType(), "vcf");
+        Assert.assertEquals(b.isBound(), true);
+    }
+
+    @Test
+    public void testUnboundRodBinding() {
+        RodBinding<VariantContext> u = RodBinding.makeUnbound(VariantContext.class);
+        Assert.assertEquals(u.getName(), RodBinding.UNBOUND_VARIABLE_NAME);
+        Assert.assertEquals(u.getSource(), RodBinding.UNBOUND_SOURCE);
+        Assert.assertEquals(u.getType(), VariantContext.class);
+        Assert.assertEquals(u.getTribbleType(), RodBinding.UNBOUND_TRIBBLE_TYPE);
+        Assert.assertEquals(u.isBound(), false);
+    }
+
+    @Test
+    public void testMultipleBindings() {
+        String name = "binding";
+        RodBinding<VariantContext> b1 = new RodBinding<VariantContext>(VariantContext.class, name, "foo", "vcf", mytags);
+        Assert.assertEquals(b1.getName(), name);
+        Assert.assertEquals(b1.getType(), VariantContext.class);
+        Assert.assertEquals(b1.getSource(), "foo");
+        Assert.assertEquals(b1.getTribbleType(), "vcf");
+        Assert.assertEquals(b1.isBound(), true);
+
+        RodBinding<VariantContext> b2 = new RodBinding<VariantContext>(VariantContext.class, name, "foo", "vcf", mytags);
+        Assert.assertEquals(b2.getName(), name + "2");
+        Assert.assertEquals(b2.getType(), VariantContext.class);
+        Assert.assertEquals(b2.getSource(), "foo");
+        Assert.assertEquals(b2.getTribbleType(), "vcf");
+        Assert.assertEquals(b2.isBound(), true);
+    }
+}
diff --git a/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/utils/crypt/CryptUtilsUnitTest.java b/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/utils/crypt/CryptUtilsUnitTest.java
new file mode 100644
index 0000000..c44bfdc
--- /dev/null
+++ b/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/utils/crypt/CryptUtilsUnitTest.java
@@ -0,0 +1,199 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.utils.crypt;
+
+import org.broadinstitute.gatk.utils.BaseTest;
+import org.broadinstitute.gatk.utils.exceptions.ReviewedGATKException;
+import org.broadinstitute.gatk.utils.exceptions.UserException;
+import org.testng.SkipException;
+import org.testng.annotations.DataProvider;
+import org.testng.annotations.Test;
+import org.testng.Assert;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.security.Key;
+import java.security.KeyPair;
+import java.security.PrivateKey;
+import java.security.PublicKey;
+import java.util.Arrays;
+
+public class CryptUtilsUnitTest extends BaseTest {
+
+    @Test
+    public void testGenerateValidKeyPairWithDefaultSettings() {
+        KeyPair keyPair = CryptUtils.generateKeyPair();
+        Assert.assertTrue(CryptUtils.keysDecryptEachOther(keyPair.getPrivate(), keyPair.getPublic()));
+    }
+
+    @DataProvider( name = "InvalidKeyPairSettings" )
+    public Object[][] invalidKeyPairSettingsDataProvider() {
+        return new Object[][] {
+            { -1, CryptUtils.DEFAULT_ENCRYPTION_ALGORITHM, CryptUtils.DEFAULT_RANDOM_NUMBER_GENERATION_ALGORITHM},
+            { CryptUtils.DEFAULT_KEY_LENGTH, "Made-up algorithm", CryptUtils.DEFAULT_RANDOM_NUMBER_GENERATION_ALGORITHM},
+            { CryptUtils.DEFAULT_KEY_LENGTH, CryptUtils.DEFAULT_ENCRYPTION_ALGORITHM, "Made-up algorithm"}
+        };
+    }
+
+    @Test( dataProvider = "InvalidKeyPairSettings", expectedExceptions = ReviewedGATKException.class )
+    public void testGenerateKeyPairWithInvalidSettings( int keyLength, String encryptionAlgorithm, String randomNumberGenerationAlgorithm ) {
+        KeyPair keyPair = CryptUtils.generateKeyPair(keyLength, encryptionAlgorithm, randomNumberGenerationAlgorithm);
+    }
+
+    @Test
+    public void testGATKMasterKeyPairMutualDecryption() {
+        if ( gatkPrivateKeyExistsButReadPermissionDenied() ) {
+            throw new SkipException(String.format("Skipping test %s because we do not have permission to read the GATK private key",
+                                    "testGATKMasterKeyPairMutualDecryption"));
+        }
+
+        Assert.assertTrue(CryptUtils.keysDecryptEachOther(CryptUtils.loadGATKMasterPrivateKey(), CryptUtils.loadGATKMasterPublicKey()));
+    }
+
+    @Test
+    public void testGATKMasterPrivateKeyWithDistributedPublicKeyMutualDecryption() {
+        if ( gatkPrivateKeyExistsButReadPermissionDenied() ) {
+            throw new SkipException(String.format("Skipping test %s because we do not have permission to read the GATK private key",
+                                    "testGATKMasterPrivateKeyWithDistributedPublicKeyMutualDecryption"));
+        }
+
+        Assert.assertTrue(CryptUtils.keysDecryptEachOther(CryptUtils.loadGATKMasterPrivateKey(), CryptUtils.loadGATKDistributedPublicKey()));
+    }
+
+    @Test
+    public void testKeyPairWriteThenRead() {
+        KeyPair keyPair = CryptUtils.generateKeyPair();
+        File privateKeyFile = createTempFile("testKeyPairWriteThenRead_private", "key");
+        File publicKeyFile = createTempFile("testKeyPairWriteThenRead_public", "key");
+
+        CryptUtils.writeKeyPair(keyPair, privateKeyFile, publicKeyFile);
+
+        assertKeysAreEqual(keyPair.getPrivate(), CryptUtils.readPrivateKey(privateKeyFile));
+        assertKeysAreEqual(keyPair.getPublic(), CryptUtils.readPublicKey(publicKeyFile));
+    }
+
+    @Test
+    public void testPublicKeyWriteThenReadFromFile() {
+        File keyFile = createTempFile("testPublicKeyWriteThenReadFromFile", "key");
+        PublicKey publicKey = CryptUtils.generateKeyPair().getPublic();
+
+        CryptUtils.writeKey(publicKey, keyFile);
+
+        assertKeysAreEqual(publicKey, CryptUtils.readPublicKey(keyFile));
+    }
+
+    @Test
+    public void testPublicKeyWriteThenReadFromStream() throws IOException {
+        File keyFile = createTempFile("testPublicKeyWriteThenReadFromStream", "key");
+        PublicKey publicKey = CryptUtils.generateKeyPair().getPublic();
+
+        CryptUtils.writeKey(publicKey, keyFile);
+
+        assertKeysAreEqual(publicKey, CryptUtils.readPublicKey(new FileInputStream(keyFile)));
+    }
+
+    @Test
+    public void testPrivateKeyWriteThenReadFromFile() {
+        File keyFile = createTempFile("testPrivateKeyWriteThenReadFromFile", "key");
+        PrivateKey privateKey = CryptUtils.generateKeyPair().getPrivate();
+
+        CryptUtils.writeKey(privateKey, keyFile);
+
+        assertKeysAreEqual(privateKey, CryptUtils.readPrivateKey(keyFile));
+    }
+
+    @Test
+    public void testPrivateKeyWriteThenReadFromStream() throws IOException {
+        File keyFile = createTempFile("testPrivateKeyWriteThenReadFromStream", "key");
+        PrivateKey privateKey = CryptUtils.generateKeyPair().getPrivate();
+
+        CryptUtils.writeKey(privateKey, keyFile);
+
+        assertKeysAreEqual(privateKey, CryptUtils.readPrivateKey(new FileInputStream(keyFile)));
+    }
+
+    @Test( expectedExceptions = UserException.CouldNotReadInputFile.class )
+    public void testReadNonExistentPublicKey() {
+        File nonExistentFile = new File("jdshgkdfhg.key");
+        Assert.assertFalse(nonExistentFile.exists());
+
+        CryptUtils.readPublicKey(nonExistentFile);
+    }
+
+    @Test( expectedExceptions = UserException.CouldNotReadInputFile.class )
+    public void testReadNonExistentPrivateKey() {
+        File nonExistentFile = new File("jdshgkdfhg.key");
+        Assert.assertFalse(nonExistentFile.exists());
+
+        CryptUtils.readPrivateKey(nonExistentFile);
+    }
+
+    @Test
+    public void testDecodePublicKey() {
+        PublicKey originalKey = CryptUtils.generateKeyPair().getPublic();
+        PublicKey decodedKey = CryptUtils.decodePublicKey(originalKey.getEncoded(), CryptUtils.DEFAULT_ENCRYPTION_ALGORITHM);
+        assertKeysAreEqual(originalKey, decodedKey);
+    }
+
+    @Test
+    public void testDecodePrivateKey() {
+        PrivateKey originalKey = CryptUtils.generateKeyPair().getPrivate();
+        PrivateKey decodedKey = CryptUtils.decodePrivateKey(originalKey.getEncoded(), CryptUtils.DEFAULT_ENCRYPTION_ALGORITHM);
+        assertKeysAreEqual(originalKey, decodedKey);
+    }
+
+    @Test
+    public void testLoadGATKMasterPrivateKey() {
+        if ( gatkPrivateKeyExistsButReadPermissionDenied() ) {
+            throw new SkipException(String.format("Skipping test %s because we do not have permission to read the GATK private key",
+                                    "testLoadGATKMasterPrivateKey"));
+        }
+
+        PrivateKey gatkMasterPrivateKey = CryptUtils.loadGATKMasterPrivateKey();
+    }
+
+    @Test
+    public void testLoadGATKMasterPublicKey() {
+        PublicKey gatkMasterPublicKey = CryptUtils.loadGATKMasterPublicKey();
+    }
+
+    @Test
+    public void testLoadGATKDistributedPublicKey() {
+        PublicKey gatkDistributedPublicKey = CryptUtils.loadGATKDistributedPublicKey();
+    }
+
+    private void assertKeysAreEqual( Key originalKey, Key keyFromDisk ) {
+        Assert.assertTrue(Arrays.equals(originalKey.getEncoded(), keyFromDisk.getEncoded()));
+        Assert.assertEquals(originalKey.getAlgorithm(), keyFromDisk.getAlgorithm());
+        Assert.assertEquals(originalKey.getFormat(), keyFromDisk.getFormat());
+    }
+
+    private boolean gatkPrivateKeyExistsButReadPermissionDenied() {
+        File gatkPrivateKey = new File(CryptUtils.GATK_MASTER_PRIVATE_KEY_FILE);
+        return gatkPrivateKey.exists() && ! gatkPrivateKey.canRead();
+    }
+}
diff --git a/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/utils/crypt/GATKKeyIntegrationTest.java b/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/utils/crypt/GATKKeyIntegrationTest.java
new file mode 100644
index 0000000..9cafd61
--- /dev/null
+++ b/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/utils/crypt/GATKKeyIntegrationTest.java
@@ -0,0 +1,157 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.utils.crypt;
+
+import org.broadinstitute.gatk.engine.walkers.WalkerTest;
+import org.broadinstitute.gatk.engine.phonehome.GATKRunReport;
+import org.broadinstitute.gatk.utils.exceptions.UserException;
+import org.testng.annotations.DataProvider;
+import org.testng.annotations.Test;
+
+import java.util.Arrays;
+
+public class GATKKeyIntegrationTest extends WalkerTest {
+
+    public static final String BASE_COMMAND = String.format("-T PrintReads -R %s -I %s -o %%s",
+                                                            publicTestDir + "exampleFASTA.fasta",
+                                                            publicTestDir + "exampleBAM.bam");
+    public static final String MD5_UPON_SUCCESSFUL_RUN = "e7b4a5b62f9d4badef1cd07040011b2b";
+
+
+    private void runGATKKeyTest ( String testName, String etArg, String keyArg, Class expectedException, String md5 ) {
+        String command = BASE_COMMAND + String.format(" %s %s", etArg, keyArg);
+
+        WalkerTestSpec spec = expectedException != null ?
+                              new WalkerTestSpec(command, 1, expectedException) :
+                              new WalkerTestSpec(command, 1, Arrays.asList(md5));
+
+        spec.disableImplicitArgs(); // Turn off automatic inclusion of -et/-K args by WalkerTest
+        executeTest(testName, spec);
+    }
+
+    @Test
+    public void testValidKeyNoET() {
+        runGATKKeyTest("testValidKeyNoET",
+                       "-et " + GATKRunReport.PhoneHomeOption.NO_ET,
+                       "-K " + keysDataLocation + "valid.key",
+                       null,
+                       MD5_UPON_SUCCESSFUL_RUN);
+    }
+
+    @Test
+    public void testValidKeyETStdout() {
+        runGATKKeyTest("testValidKeyETStdout",
+                       "-et " + GATKRunReport.PhoneHomeOption.STDOUT,
+                       "-K " + keysDataLocation + "valid.key",
+                       null,
+                       MD5_UPON_SUCCESSFUL_RUN);
+    }
+
+    @Test
+    public void testValidKeyETStandard() {
+        runGATKKeyTest("testValidKeyETStandard",
+                       "",
+                       "-K " + keysDataLocation + "valid.key",
+                       null,
+                       MD5_UPON_SUCCESSFUL_RUN);
+    }
+
+    @Test
+    public void testNoKeyNoET() {
+        runGATKKeyTest("testNoKeyNoET",
+                       "-et " + GATKRunReport.PhoneHomeOption.NO_ET,
+                       "",
+                       UserException.class,
+                       null);
+    }
+
+    @Test
+    public void testNoKeyETStdout() {
+        runGATKKeyTest("testNoKeyETStdout",
+                       "-et " + GATKRunReport.PhoneHomeOption.STDOUT,
+                       "",
+                       UserException.class,
+                       null);
+    }
+
+    @Test
+    public void testNoKeyETStandard() {
+        runGATKKeyTest("testNoKeyETStandard",
+                       "",
+                       "",
+                       null,
+                       MD5_UPON_SUCCESSFUL_RUN);
+    }
+
+    @Test
+    public void testRevokedKey() {
+        runGATKKeyTest("testRevokedKey",
+                       "-et " + GATKRunReport.PhoneHomeOption.NO_ET,
+                       "-K " + keysDataLocation + "revoked.key",
+                       UserException.KeySignatureVerificationException.class,
+                       null);
+    }
+
+    @DataProvider(name = "CorruptKeyTestData")
+    public Object[][] corruptKeyDataProvider() {
+        return new Object[][] {
+            { "corrupt_empty.key",                  UserException.UnreadableKeyException.class },
+            { "corrupt_single_byte_file.key",       UserException.UnreadableKeyException.class },
+            { "corrupt_random_contents.key",        UserException.UnreadableKeyException.class },
+            { "corrupt_single_byte_deletion.key",   UserException.UnreadableKeyException.class },
+            { "corrupt_single_byte_insertion.key",  UserException.UnreadableKeyException.class },
+            { "corrupt_single_byte_change.key",     UserException.UnreadableKeyException.class },
+            { "corrupt_multi_byte_deletion.key",    UserException.UnreadableKeyException.class },
+            { "corrupt_multi_byte_insertion.key",   UserException.UnreadableKeyException.class },
+            { "corrupt_multi_byte_change.key",      UserException.UnreadableKeyException.class },
+            { "corrupt_bad_isize_field.key",        UserException.UnreadableKeyException.class },
+            { "corrupt_bad_crc.key",                UserException.UnreadableKeyException.class },
+            { "corrupt_no_email_address.key",       UserException.UnreadableKeyException.class },
+            { "corrupt_no_sectional_delimiter.key", UserException.UnreadableKeyException.class },
+            { "corrupt_no_signature.key",           UserException.UnreadableKeyException.class },
+            { "corrupt_bad_signature.key",          UserException.KeySignatureVerificationException.class },
+            { "corrupt_non_gzipped_valid_key.key",  UserException.UnreadableKeyException.class }
+        };
+    }
+
+    @Test(dataProvider = "CorruptKeyTestData")
+    public void testCorruptKey ( String corruptKeyName, Class expectedException ) {
+        runGATKKeyTest(String.format("testCorruptKey (%s)", corruptKeyName),
+                       "-et " + GATKRunReport.PhoneHomeOption.NO_ET,
+                       "-K " + keysDataLocation + corruptKeyName,
+                       expectedException,
+                       null);
+    }
+
+    @Test
+    public void testCorruptButNonRequiredKey() {
+        runGATKKeyTest("testCorruptButNonRequiredKey",
+                       "",
+                       "-K " + keysDataLocation + "corrupt_random_contents.key",
+                       null,
+                       MD5_UPON_SUCCESSFUL_RUN);
+    }
+}
diff --git a/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/utils/crypt/GATKKeyUnitTest.java b/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/utils/crypt/GATKKeyUnitTest.java
new file mode 100644
index 0000000..5fd6475
--- /dev/null
+++ b/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/utils/crypt/GATKKeyUnitTest.java
@@ -0,0 +1,129 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.utils.crypt;
+
+import org.broadinstitute.gatk.utils.BaseTest;
+import org.broadinstitute.gatk.utils.exceptions.ReviewedGATKException;
+import org.broadinstitute.gatk.utils.exceptions.UserException;
+import org.testng.SkipException;
+import org.testng.annotations.Test;
+import org.testng.Assert;
+
+import java.io.File;
+import java.security.KeyPair;
+import java.security.PrivateKey;
+import java.security.PublicKey;
+
+public class GATKKeyUnitTest extends BaseTest {
+
+    @Test
+    public void testCreateGATKKeyUsingMasterKeyPair() {
+        if ( gatkPrivateKeyExistsButReadPermissionDenied() ) {
+            throw new SkipException(String.format("Skipping test %s because we do not have permission to read the GATK private key",
+                                    "testCreateGATKKeyUsingMasterKeyPair"));
+        }
+
+        PrivateKey masterPrivateKey = CryptUtils.loadGATKMasterPrivateKey();
+        PublicKey masterPublicKey = CryptUtils.loadGATKMasterPublicKey();
+
+        // We should be able to create a valid GATKKey using our master key pair:
+        GATKKey key = new GATKKey(masterPrivateKey, masterPublicKey, "foo at bar.com");
+        Assert.assertTrue(key.isValid());
+    }
+
+    @Test
+    public void testCreateGATKKeyUsingMasterPrivateKeyAndDistributedPublicKey() {
+        if ( gatkPrivateKeyExistsButReadPermissionDenied() ) {
+            throw new SkipException(String.format("Skipping test %s because we do not have permission to read the GATK private key",
+                                    "testCreateGATKKeyUsingMasterPrivateKeyAndDistributedPublicKey"));
+        }
+
+        PrivateKey masterPrivateKey = CryptUtils.loadGATKMasterPrivateKey();
+        PublicKey distributedPublicKey = CryptUtils.loadGATKDistributedPublicKey();
+
+        // We should also be able to create a valid GATKKey using our master private
+        // key and the public key we distribute with the GATK:
+        GATKKey key = new GATKKey(masterPrivateKey, distributedPublicKey, "foo at bar.com");
+        Assert.assertTrue(key.isValid());
+    }
+
+    @Test( expectedExceptions = ReviewedGATKException.class )
+    public void testKeyPairMismatch() {
+        KeyPair firstKeyPair = CryptUtils.generateKeyPair();
+        KeyPair secondKeyPair = CryptUtils.generateKeyPair();
+
+        // Attempting to create a GATK Key with private and public keys that aren't part of the
+        // same key pair should immediately trigger a validation failure:
+        GATKKey key = new GATKKey(firstKeyPair.getPrivate(), secondKeyPair.getPublic(), "foo at bar.com");
+    }
+
+    @Test( expectedExceptions = ReviewedGATKException.class )
+    public void testEncryptionAlgorithmMismatch() {
+        KeyPair keyPair = CryptUtils.generateKeyPair(CryptUtils.DEFAULT_KEY_LENGTH, "DSA", CryptUtils.DEFAULT_RANDOM_NUMBER_GENERATION_ALGORITHM);
+
+        // Attempting to use a DSA private key to create an RSA signature should throw an error:
+        GATKKey key = new GATKKey(keyPair.getPrivate(), keyPair.getPublic(), "foo at bar.com", "SHA1withRSA");
+    }
+
+    @Test( expectedExceptions = UserException.class )
+    public void testInvalidEmailAddress() {
+        String emailAddressWithNulByte = new String(new byte[] { 0 });
+        KeyPair keyPair = CryptUtils.generateKeyPair();
+
+        // Email addresses cannot contain the NUL byte, since it's used as a sectional delimiter in the key file:
+        GATKKey key = new GATKKey(keyPair.getPrivate(), keyPair.getPublic(), emailAddressWithNulByte);
+    }
+
+    @Test
+    public void testCreateGATKKeyFromValidKeyFile() {
+        GATKKey key = new GATKKey(CryptUtils.loadGATKDistributedPublicKey(), new File(keysDataLocation + "valid.key"));
+        Assert.assertTrue(key.isValid());
+    }
+
+    @Test( expectedExceptions = UserException.UnreadableKeyException.class )
+    public void testCreateGATKKeyFromCorruptKeyFile() {
+        GATKKey key = new GATKKey(CryptUtils.loadGATKDistributedPublicKey(), new File(keysDataLocation + "corrupt_random_contents.key"));
+    }
+
+    @Test
+    public void testCreateGATKKeyFromRevokedKeyFile() {
+        GATKKey key = new GATKKey(CryptUtils.loadGATKDistributedPublicKey(), new File(keysDataLocation + "revoked.key"));
+        Assert.assertFalse(key.isValid());
+    }
+
+    @Test( expectedExceptions = UserException.CouldNotReadInputFile.class )
+    public void testCreateGATKKeyFromNonExistentFile() {
+        File nonExistentFile = new File("ghfdkgsdhg.key");
+        Assert.assertFalse(nonExistentFile.exists());
+
+        GATKKey key = new GATKKey(CryptUtils.loadGATKDistributedPublicKey(), nonExistentFile);
+    }
+
+    private boolean gatkPrivateKeyExistsButReadPermissionDenied() {
+        File gatkPrivateKey = new File(CryptUtils.GATK_MASTER_PRIVATE_KEY_FILE);
+        return gatkPrivateKey.exists() && ! gatkPrivateKey.canRead();
+    }
+}
diff --git a/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/utils/fasta/CachingIndexedFastaSequenceFileUnitTest.java b/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/utils/fasta/CachingIndexedFastaSequenceFileUnitTest.java
new file mode 100644
index 0000000..3e877b9
--- /dev/null
+++ b/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/utils/fasta/CachingIndexedFastaSequenceFileUnitTest.java
@@ -0,0 +1,264 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.utils.fasta;
+
+
+// the imports for unit testing.
+
+
+import htsjdk.samtools.reference.IndexedFastaSequenceFile;
+import htsjdk.samtools.reference.ReferenceSequence;
+import htsjdk.samtools.SAMSequenceRecord;
+import org.apache.commons.lang.StringUtils;
+import org.apache.log4j.Priority;
+import org.broadinstitute.gatk.utils.BaseTest;
+import org.broadinstitute.gatk.utils.exceptions.UserException;
+import org.testng.Assert;
+import org.testng.annotations.DataProvider;
+import org.testng.annotations.Test;
+
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.List;
+import java.util.concurrent.Callable;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+
+/**
+ * Basic unit test for CachingIndexedFastaSequenceFile
+ */
+public class CachingIndexedFastaSequenceFileUnitTest extends BaseTest {
+    private File simpleFasta = new File(publicTestDir + "/exampleFASTA.fasta");
+    private static final int STEP_SIZE = 1;
+    private final static boolean DEBUG = false;
+
+    //private static final List<Integer> QUERY_SIZES = Arrays.asList(1);
+    private static final List<Integer> QUERY_SIZES = Arrays.asList(1, 10, 100);
+    private static final List<Integer> CACHE_SIZES = Arrays.asList(-1, 100, 1000);
+
+    @DataProvider(name = "fastas")
+    public Object[][] createData1() {
+        List<Object[]> params = new ArrayList<Object[]>();
+        for ( File fasta : Arrays.asList(simpleFasta) ) {
+            for ( int cacheSize : CACHE_SIZES ) {
+                for ( int querySize : QUERY_SIZES ) {
+                    params.add(new Object[]{fasta, cacheSize, querySize});
+                }
+            }
+        }
+
+        return params.toArray(new Object[][]{});
+    }
+
+    private static long getCacheSize(final long cacheSizeRequested) {
+        return cacheSizeRequested == -1 ? CachingIndexedFastaSequenceFile.DEFAULT_CACHE_SIZE : cacheSizeRequested;
+    }
+
+    @Test(dataProvider = "fastas", enabled = true && ! DEBUG)
+    public void testCachingIndexedFastaReaderSequential1(File fasta, int cacheSize, int querySize) throws FileNotFoundException {
+        final CachingIndexedFastaSequenceFile caching = new CachingIndexedFastaSequenceFile(fasta, getCacheSize(cacheSize), true, false);
+
+        SAMSequenceRecord contig = caching.getSequenceDictionary().getSequence(0);
+        logger.warn(String.format("Checking contig %s length %d with cache size %d and query size %d",
+                contig.getSequenceName(), contig.getSequenceLength(), cacheSize, querySize));
+        testSequential(caching, fasta, querySize);
+    }
+
+    private void testSequential(final CachingIndexedFastaSequenceFile caching, final File fasta, final int querySize) throws FileNotFoundException {
+        Assert.assertTrue(caching.isPreservingCase(), "testSequential only works for case preserving CachingIndexedFastaSequenceFile readers");
+
+        final IndexedFastaSequenceFile uncached = new IndexedFastaSequenceFile(fasta);
+
+        SAMSequenceRecord contig = uncached.getSequenceDictionary().getSequence(0);
+        for ( int i = 0; i < contig.getSequenceLength(); i += STEP_SIZE ) {
+            int start = i;
+            int stop = start + querySize;
+            if ( stop <= contig.getSequenceLength() ) {
+                ReferenceSequence cachedVal = caching.getSubsequenceAt(contig.getSequenceName(), start, stop);
+                ReferenceSequence uncachedVal = uncached.getSubsequenceAt(contig.getSequenceName(), start, stop);
+
+                Assert.assertEquals(cachedVal.getName(), uncachedVal.getName());
+                Assert.assertEquals(cachedVal.getContigIndex(), uncachedVal.getContigIndex());
+                Assert.assertEquals(cachedVal.getBases(), uncachedVal.getBases());
+            }
+        }
+
+        // asserts for efficiency.  We are going to make contig.length / STEP_SIZE queries
+        // at each of range: start -> start + querySize against a cache with size of X.
+        // we expect to hit the cache each time range falls within X.  We expect a hit
+        // on the cache if range is within X.  Which should happen at least (X - query_size * 2) / STEP_SIZE
+        // times.
+        final int minExpectedHits = (int)Math.floor((Math.min(caching.getCacheSize(), contig.getSequenceLength()) - querySize * 2.0) / STEP_SIZE);
+        caching.printEfficiency(Priority.WARN);
+        Assert.assertTrue(caching.getCacheHits() >= minExpectedHits, "Expected at least " + minExpectedHits + " cache hits but only got " + caching.getCacheHits());
+
+    }
+
+    // Tests grabbing sequences around a middle cached value.
+    @Test(dataProvider = "fastas", enabled = true && ! DEBUG)
+    public void testCachingIndexedFastaReaderTwoStage(File fasta, int cacheSize, int querySize) throws FileNotFoundException {
+        final IndexedFastaSequenceFile uncached = new IndexedFastaSequenceFile(fasta);
+        final CachingIndexedFastaSequenceFile caching = new CachingIndexedFastaSequenceFile(fasta, getCacheSize(cacheSize), true, false);
+
+        SAMSequenceRecord contig = uncached.getSequenceDictionary().getSequence(0);
+
+        int middleStart = (contig.getSequenceLength() - querySize) / 2;
+        int middleStop = middleStart + querySize;
+
+        logger.warn(String.format("Checking contig %s length %d with cache size %d and query size %d with intermediate query",
+                contig.getSequenceName(), contig.getSequenceLength(), cacheSize, querySize));
+
+        for ( int i = 0; i < contig.getSequenceLength(); i += 10 ) {
+            int start = i;
+            int stop = start + querySize;
+            if ( stop <= contig.getSequenceLength() ) {
+                ReferenceSequence grabMiddle = caching.getSubsequenceAt(contig.getSequenceName(), middleStart, middleStop);
+                ReferenceSequence cachedVal = caching.getSubsequenceAt(contig.getSequenceName(), start, stop);
+                ReferenceSequence uncachedVal = uncached.getSubsequenceAt(contig.getSequenceName(), start, stop);
+
+                Assert.assertEquals(cachedVal.getName(), uncachedVal.getName());
+                Assert.assertEquals(cachedVal.getContigIndex(), uncachedVal.getContigIndex());
+                Assert.assertEquals(cachedVal.getBases(), uncachedVal.getBases());
+            }
+        }
+    }
+
+    @DataProvider(name = "ParallelFastaTest")
+    public Object[][] createParallelFastaTest() {
+        List<Object[]> params = new ArrayList<Object[]>();
+
+        for ( File fasta : Arrays.asList(simpleFasta) ) {
+            for ( int cacheSize : CACHE_SIZES ) {
+                for ( int querySize : QUERY_SIZES ) {
+                    for ( int nt : Arrays.asList(1, 2, 3, 4) ) {
+                        params.add(new Object[]{fasta, cacheSize, querySize, nt});
+                    }
+                }
+            }
+        }
+
+        return params.toArray(new Object[][]{});
+    }
+
+
+    @Test(dataProvider = "ParallelFastaTest", enabled = true && ! DEBUG, timeOut = 60000)
+    public void testCachingIndexedFastaReaderParallel(final File fasta, final int cacheSize, final int querySize, final int nt) throws FileNotFoundException, InterruptedException {
+        final CachingIndexedFastaSequenceFile caching = new CachingIndexedFastaSequenceFile(fasta, getCacheSize(cacheSize), true, false);
+
+        logger.warn(String.format("Parallel caching index fasta reader test cacheSize %d querySize %d nt %d", caching.getCacheSize(), querySize, nt));
+        for ( int iterations = 0; iterations < 1; iterations++ ) {
+            final ExecutorService executor = Executors.newFixedThreadPool(nt);
+            final Collection<Callable<Object>> tasks = new ArrayList<Callable<Object>>(nt);
+            for ( int i = 0; i < nt; i++ )
+                tasks.add(new Callable<Object>() {
+                    @Override
+                    public Object call() throws Exception {
+                        testSequential(caching, fasta, querySize);
+                        return null;
+                    }
+                });
+            executor.invokeAll(tasks);
+            executor.shutdownNow();
+        }
+    }
+
+    // make sure some bases are lower case and some are upper case
+    @Test(enabled = true)
+    public void testMixedCasesInExample() throws FileNotFoundException, InterruptedException {
+        final IndexedFastaSequenceFile original = new IndexedFastaSequenceFile(new File(exampleFASTA));
+        final CachingIndexedFastaSequenceFile casePreserving = new CachingIndexedFastaSequenceFile(new File(exampleFASTA), true);
+        final CachingIndexedFastaSequenceFile allUpper = new CachingIndexedFastaSequenceFile(new File(exampleFASTA));
+
+        int nMixedCase = 0;
+        for ( SAMSequenceRecord contig : original.getSequenceDictionary().getSequences() ) {
+            nMixedCase += testCases(original, casePreserving, allUpper, contig.getSequenceName(), -1, -1);
+
+            final int step = 100;
+            for ( int lastPos = step; lastPos < contig.getSequenceLength(); lastPos += step ) {
+                testCases(original, casePreserving, allUpper, contig.getSequenceName(), lastPos - step, lastPos);
+            }
+        }
+
+        Assert.assertTrue(nMixedCase > 0, "No mixed cases sequences found in file.  Unexpected test state");
+    }
+
+    private int testCases(final IndexedFastaSequenceFile original,
+                          final IndexedFastaSequenceFile casePreserving,
+                          final IndexedFastaSequenceFile allUpper,
+                          final String contig, final int start, final int stop ) {
+        final String orig = fetchBaseString(original, contig, start, stop);
+        final String keptCase = fetchBaseString(casePreserving, contig, start, stop);
+        final String upperCase = fetchBaseString(allUpper, contig, start, stop).toUpperCase();
+
+        final String origToUpper = orig.toUpperCase();
+        if ( ! orig.equals(origToUpper) ) {
+            Assert.assertEquals(keptCase, orig, "Case preserving operation not equal to the original case for contig " + contig);
+            Assert.assertEquals(upperCase, origToUpper, "All upper case reader not equal to the uppercase of original case for contig " + contig);
+            return 1;
+        } else {
+            return 0;
+        }
+    }
+
+    private String fetchBaseString(final IndexedFastaSequenceFile reader, final String contig, final int start, final int stop) {
+        if ( start == -1 )
+            return new String(reader.getSequence(contig).getBases());
+        else
+            return new String(reader.getSubsequenceAt(contig, start, stop).getBases());
+    }
+
+    @Test(enabled = true)
+    public void testIupacChanges() throws FileNotFoundException, InterruptedException {
+        final String testFasta = privateTestDir + "iupacFASTA.fasta";
+        final CachingIndexedFastaSequenceFile iupacPreserving = new CachingIndexedFastaSequenceFile(new File(testFasta), CachingIndexedFastaSequenceFile.DEFAULT_CACHE_SIZE, false, true);
+        final CachingIndexedFastaSequenceFile makeNs = new CachingIndexedFastaSequenceFile(new File(testFasta));
+
+        int preservingNs = 0;
+        int changingNs = 0;
+        for ( SAMSequenceRecord contig : iupacPreserving.getSequenceDictionary().getSequences() ) {
+            final String sPreserving = fetchBaseString(iupacPreserving, contig.getSequenceName(), 0, 15000);
+            preservingNs += StringUtils.countMatches(sPreserving, "N");
+
+            final String sChanging = fetchBaseString(makeNs, contig.getSequenceName(), 0, 15000);
+            changingNs += StringUtils.countMatches(sChanging, "N");
+        }
+
+        Assert.assertEquals(changingNs, preservingNs + 4);
+    }
+
+    @Test(enabled = true, expectedExceptions = {UserException.class})
+    public void testFailOnBadBase() throws FileNotFoundException, InterruptedException {
+        final String testFasta = privateTestDir + "problematicFASTA.fasta";
+        final CachingIndexedFastaSequenceFile fasta = new CachingIndexedFastaSequenceFile(new File(testFasta));
+
+        for ( SAMSequenceRecord contig : fasta.getSequenceDictionary().getSequences() ) {
+            fetchBaseString(fasta, contig.getSequenceName(), -1, -1);
+        }
+    }
+}
diff --git a/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/utils/file/FSLockWithSharedUnitTest.java b/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/utils/file/FSLockWithSharedUnitTest.java
new file mode 100644
index 0000000..63d98a2
--- /dev/null
+++ b/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/utils/file/FSLockWithSharedUnitTest.java
@@ -0,0 +1,60 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.utils.file;
+
+import org.broadinstitute.gatk.utils.BaseTest;
+import org.broadinstitute.gatk.utils.exceptions.UserException;
+import org.testng.annotations.Test;
+
+import java.io.File;
+
+public class FSLockWithSharedUnitTest extends BaseTest {
+
+    private static final int MAX_EXPECTED_LOCK_ACQUISITION_TIME = FSLockWithShared.DEFAULT_LOCK_ACQUISITION_TIMEOUT_IN_MILLISECONDS +
+                                                                  FSLockWithShared.THREAD_TERMINATION_TIMEOUT_IN_MILLISECONDS;
+
+    /**
+     * Test to ensure that we're never spending more than the maximum configured amount of time in lock acquisition calls.
+     */
+    @Test( timeOut = MAX_EXPECTED_LOCK_ACQUISITION_TIME + 10 * 1000 )
+    public void testLockAcquisitionTimeout() {
+        final File lockFile = createTempFile("FSLockWithSharedUnitTest", ".lock");
+        final FSLockWithShared lock = new FSLockWithShared(lockFile);
+        boolean lockAcquisitionSucceeded = false;
+
+        try {
+            lockAcquisitionSucceeded = lock.sharedLock();
+        }
+        catch ( UserException e ) {
+            logger.info("Caught UserException from lock acquisition call: lock acquisition must have timed out. Message: " + e.getMessage());
+        }
+        finally {
+            if ( lockAcquisitionSucceeded ) {
+                lock.unlock();
+            }
+        }
+    }
+}
diff --git a/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/utils/fragments/FragmentUtilsBenchmark.java b/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/utils/fragments/FragmentUtilsBenchmark.java
new file mode 100644
index 0000000..f388d14
--- /dev/null
+++ b/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/utils/fragments/FragmentUtilsBenchmark.java
@@ -0,0 +1,81 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.utils.fragments;
+
+import com.google.caliper.Param;
+import com.google.caliper.SimpleBenchmark;
+import htsjdk.samtools.SAMFileHeader;
+import org.broadinstitute.gatk.utils.GenomeLoc;
+import org.broadinstitute.gatk.utils.GenomeLocParser;
+import org.broadinstitute.gatk.utils.pileup.ReadBackedPileup;
+import org.broadinstitute.gatk.utils.sam.ArtificialSAMUtils;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Caliper microbenchmark of fragment pileup
+ */
+public class FragmentUtilsBenchmark extends SimpleBenchmark {
+    List<ReadBackedPileup> pileups;
+
+    @Param({"0", "4", "30", "150", "1000"})
+    int pileupSize; // set automatically by framework
+
+    @Param({"200", "400"})
+    int insertSize; // set automatically by framework
+
+    @Override protected void setUp() {
+        final int nPileupsToGenerate = 100;
+        pileups = new ArrayList<ReadBackedPileup>(nPileupsToGenerate);
+        SAMFileHeader header = ArtificialSAMUtils.createArtificialSamHeader(1, 1, 1000);
+        GenomeLocParser genomeLocParser;
+        genomeLocParser = new GenomeLocParser(header.getSequenceDictionary());
+        GenomeLoc loc = genomeLocParser.createGenomeLoc("chr1", 50);
+        final int readLen = 100;
+
+        for ( int pileupN = 0; pileupN < nPileupsToGenerate; pileupN++ ) {
+            ReadBackedPileup rbp = ArtificialSAMUtils.createReadBackedPileup(header, loc, readLen, insertSize, pileupSize);
+            pileups.add(rbp);
+        }
+    }
+
+//    public void timeOriginal(int rep) {
+//        run(rep, FragmentUtils.FragmentMatchingAlgorithm.ORIGINAL);
+//    }
+
+    public void timeSkipNonOverlapping(int rep) {
+        int nFrags = 0;
+        for ( int i = 0; i < rep; i++ ) {
+            for ( ReadBackedPileup rbp : pileups )
+                nFrags += FragmentUtils.create(rbp).getOverlappingPairs().size();
+        }
+    }
+
+    public static void main(String[] args) {
+        com.google.caliper.Runner.main(FragmentUtilsBenchmark.class, args);
+    }
+}
diff --git a/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/utils/fragments/FragmentUtilsUnitTest.java b/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/utils/fragments/FragmentUtilsUnitTest.java
new file mode 100644
index 0000000..f9f9ba4
--- /dev/null
+++ b/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/utils/fragments/FragmentUtilsUnitTest.java
@@ -0,0 +1,390 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.utils.fragments;
+
+import htsjdk.samtools.SAMFileHeader;
+import htsjdk.samtools.TextCigarCodec;
+import org.broadinstitute.gatk.utils.BaseTest;
+import org.broadinstitute.gatk.utils.Utils;
+import org.broadinstitute.gatk.utils.pileup.PileupElement;
+import org.broadinstitute.gatk.utils.pileup.ReadBackedPileup;
+import org.broadinstitute.gatk.utils.pileup.ReadBackedPileupImpl;
+import org.broadinstitute.gatk.utils.recalibration.EventType;
+import org.broadinstitute.gatk.utils.sam.ArtificialSAMUtils;
+import org.broadinstitute.gatk.utils.sam.GATKSAMReadGroupRecord;
+import org.broadinstitute.gatk.utils.sam.GATKSAMRecord;
+import org.testng.Assert;
+import org.testng.annotations.BeforeTest;
+import org.testng.annotations.DataProvider;
+import org.testng.annotations.Test;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+/**
+ * Test routines for read-backed pileup.
+ */
+public class FragmentUtilsUnitTest extends BaseTest {
+    private static SAMFileHeader header;
+    private static GATKSAMReadGroupRecord rgForMerged;
+    private final static boolean DEBUG = false;
+
+    private class FragmentUtilsTest extends TestDataProvider {
+        List<TestState> statesForPileup = new ArrayList<TestState>();
+        List<TestState> statesForReads = new ArrayList<TestState>();
+
+        private FragmentUtilsTest(String name, int readLen, int leftStart, int rightStart,
+                                  boolean leftIsFirst, boolean leftIsNegative) {
+            super(FragmentUtilsTest.class, String.format("%s-leftIsFirst:%b-leftIsNegative:%b", name, leftIsFirst, leftIsNegative));
+
+            List<GATKSAMRecord> pair = ArtificialSAMUtils.createPair(header, "readpair", readLen, leftStart, rightStart, leftIsFirst, leftIsNegative);
+            GATKSAMRecord left = pair.get(0);
+            GATKSAMRecord right = pair.get(1);
+
+            for ( int pos = leftStart; pos < rightStart + readLen; pos++) {
+                boolean posCoveredByLeft = pos >= left.getAlignmentStart() && pos <= left.getAlignmentEnd();
+                boolean posCoveredByRight = pos >= right.getAlignmentStart() && pos <= right.getAlignmentEnd();
+
+                if ( posCoveredByLeft || posCoveredByRight ) {
+                    List<GATKSAMRecord> reads = new ArrayList<GATKSAMRecord>();
+                    List<Integer> offsets = new ArrayList<Integer>();
+
+                    if ( posCoveredByLeft ) {
+                        reads.add(left);
+                        offsets.add(pos - left.getAlignmentStart());
+                    }
+
+                    if ( posCoveredByRight ) {
+                        reads.add(right);
+                        offsets.add(pos - right.getAlignmentStart());
+                    }
+
+                    boolean shouldBeFragment = posCoveredByLeft && posCoveredByRight;
+                    ReadBackedPileup pileup = new ReadBackedPileupImpl(null, reads, offsets);
+                    TestState testState = new TestState(shouldBeFragment ? 0 : 1, shouldBeFragment ? 1 : 0, pileup, null);
+                    statesForPileup.add(testState);
+                }
+
+                TestState testState = left.getAlignmentEnd() >= right.getAlignmentStart() ? new TestState(0, 1, null, pair) : new TestState(2, 0, null, pair);
+                statesForReads.add(testState);
+            }
+        }
+    }
+
+    private class TestState {
+        int expectedSingletons, expectedPairs;
+        ReadBackedPileup pileup;
+        List<GATKSAMRecord> rawReads;
+
+        private TestState(final int expectedSingletons, final int expectedPairs, final ReadBackedPileup pileup, final List<GATKSAMRecord> rawReads) {
+            this.expectedSingletons = expectedSingletons;
+            this.expectedPairs = expectedPairs;
+            this.pileup = pileup;
+            this.rawReads = rawReads;
+        }
+    }
+
+    @DataProvider(name = "fragmentUtilsTest")
+    public Object[][] createTests() {
+        for ( boolean leftIsFirst : Arrays.asList(true, false) ) {
+            for ( boolean leftIsNegative : Arrays.asList(true, false) ) {
+                // Overlapping pair
+                // ---->        [first]
+                //   <---       [second]
+                new FragmentUtilsTest("overlapping-pair", 10, 1, 5, leftIsFirst, leftIsNegative);
+
+                // Non-overlapping pair
+                // ---->
+                //          <----
+                new FragmentUtilsTest("nonoverlapping-pair", 10, 1, 15, leftIsFirst, leftIsNegative);
+            }
+        }
+
+        return FragmentUtilsTest.getTests(FragmentUtilsTest.class);
+    }
+
+    @Test(enabled = !DEBUG, dataProvider = "fragmentUtilsTest")
+    public void testAsPileup(FragmentUtilsTest test) {
+        for ( TestState testState : test.statesForPileup ) {
+            ReadBackedPileup rbp = testState.pileup;
+            FragmentCollection<PileupElement> fp = FragmentUtils.create(rbp);
+            Assert.assertEquals(fp.getOverlappingPairs().size(), testState.expectedPairs);
+            Assert.assertEquals(fp.getSingletonReads().size(), testState.expectedSingletons);
+        }
+    }
+
+    @Test(enabled = !DEBUG, dataProvider = "fragmentUtilsTest")
+    public void testAsListOfReadsFromPileup(FragmentUtilsTest test) {
+        for ( TestState testState : test.statesForPileup ) {
+            FragmentCollection<GATKSAMRecord> fp = FragmentUtils.create(testState.pileup.getReads());
+            Assert.assertEquals(fp.getOverlappingPairs().size(), testState.expectedPairs);
+            Assert.assertEquals(fp.getSingletonReads().size(), testState.expectedSingletons);
+        }
+    }
+
+    @Test(enabled = !DEBUG, dataProvider = "fragmentUtilsTest")
+    public void testAsListOfReads(FragmentUtilsTest test) {
+        for ( TestState testState : test.statesForReads ) {
+            FragmentCollection<GATKSAMRecord> fp = FragmentUtils.create(testState.rawReads);
+            Assert.assertEquals(fp.getOverlappingPairs().size(), testState.expectedPairs);
+            Assert.assertEquals(fp.getSingletonReads().size(), testState.expectedSingletons);
+        }
+    }
+
+    @Test(enabled = !DEBUG, expectedExceptions = IllegalArgumentException.class)
+    public void testOutOfOrder() {
+        final List<GATKSAMRecord> pair = ArtificialSAMUtils.createPair(header, "readpair", 100, 1, 50, true, true);
+        final GATKSAMRecord left = pair.get(0);
+        final GATKSAMRecord right = pair.get(1);
+        final List<GATKSAMRecord> reads = Arrays.asList(right, left); // OUT OF ORDER!
+        final List<Integer> offsets = Arrays.asList(0, 50);
+        final ReadBackedPileup pileup = new ReadBackedPileupImpl(null, reads, offsets);
+        FragmentUtils.create(pileup); // should throw exception
+    }
+
+    @BeforeTest
+    public void setup() {
+        header = ArtificialSAMUtils.createArtificialSamHeader(1,1,1000);
+        rgForMerged = new GATKSAMReadGroupRecord("RG1");
+    }
+
+    @DataProvider(name = "MergeFragmentsTest")
+    public Object[][] createMergeFragmentsTest() throws Exception {
+        List<Object[]> tests = new ArrayList<Object[]>();
+
+        final String leftFlank = "CCC";
+        final String rightFlank = "AAA";
+        final String allOverlappingBases = "ACGTACGTGGAACCTTAG";
+        for ( int overlapSize = 1; overlapSize < allOverlappingBases.length(); overlapSize++ ) {
+            final String overlappingBases = allOverlappingBases.substring(0, overlapSize);
+            final byte[] overlappingBaseQuals = new byte[overlapSize];
+            for ( int i = 0; i < overlapSize; i++ ) overlappingBaseQuals[i] = (byte)(i + 30);
+            final GATKSAMRecord read1  = makeOverlappingRead(leftFlank, 20, overlappingBases, overlappingBaseQuals, "", 30, 1);
+            final GATKSAMRecord read2  = makeOverlappingRead("", 20, overlappingBases, overlappingBaseQuals, rightFlank, 30, leftFlank.length() + 1);
+            final GATKSAMRecord merged = makeOverlappingRead(leftFlank, 20, overlappingBases, overlappingBaseQuals, rightFlank, 30, 1);
+            tests.add(new Object[]{"equalQuals", read1, read2, merged});
+
+            // test that the merged read base quality is the
+            tests.add(new Object[]{"lowQualLeft", modifyBaseQualities(read1, leftFlank.length(), overlapSize), read2, merged});
+            tests.add(new Object[]{"lowQualRight", read1, modifyBaseQualities(read2, 0, overlapSize), merged});
+        }
+
+        return tests.toArray(new Object[][]{});
+    }
+
+    private GATKSAMRecord modifyBaseQualities(final GATKSAMRecord read, final int startOffset, final int length) throws Exception {
+        final GATKSAMRecord readWithLowQuals = (GATKSAMRecord)read.clone();
+        final byte[] withLowQuals = Arrays.copyOf(read.getBaseQualities(), read.getBaseQualities().length);
+        for ( int i = startOffset; i < startOffset + length; i++ )
+            withLowQuals[i] = (byte)(read.getBaseQualities()[i] + (i % 2 == 0 ? -1 : 0));
+        readWithLowQuals.setBaseQualities(withLowQuals);
+        return readWithLowQuals;
+    }
+
+    private GATKSAMRecord makeOverlappingRead(final String leftFlank, final int leftQual, final String overlapBases,
+                                              final byte[] overlapQuals, final String rightFlank, final int rightQual,
+                                              final int alignmentStart) {
+        final String bases = leftFlank + overlapBases + rightFlank;
+        final int readLength = bases.length();
+        final GATKSAMRecord read = ArtificialSAMUtils.createArtificialRead(header, "myRead", 0, alignmentStart, readLength);
+        final byte[] leftQuals = Utils.dupBytes((byte) leftQual, leftFlank.length());
+        final byte[] rightQuals = Utils.dupBytes((byte) rightQual, rightFlank.length());
+        final byte[] quals = Utils.concat(leftQuals, overlapQuals, rightQuals);
+        read.setCigarString(readLength + "M");
+        read.setReadBases(bases.getBytes());
+        for ( final EventType type : EventType.values() )
+            read.setBaseQualities(quals, type);
+        read.setReadGroup(rgForMerged);
+        read.setMappingQuality(60);
+        return read;
+    }
+
+    @Test(enabled = !DEBUG, dataProvider = "MergeFragmentsTest")
+    public void testMergingTwoReads(final String name, final GATKSAMRecord read1, final GATKSAMRecord read2, final GATKSAMRecord expectedMerged) {
+        final GATKSAMRecord actual = FragmentUtils.mergeOverlappingPairedFragments(read1, read2);
+
+        if ( expectedMerged == null ) {
+            Assert.assertNull(actual, "Expected reads not to merge, but got non-null result from merging");
+        } else {
+            Assert.assertTrue(actual.isStrandless(), "Merged reads should be strandless");
+            Assert.assertNotNull(actual, "Expected reads to merge, but got null result from merging");
+            // I really care about the bases, the quals, the CIGAR, and the read group tag
+            Assert.assertEquals(actual.getCigarString(), expectedMerged.getCigarString());
+            Assert.assertEquals(actual.getReadBases(), expectedMerged.getReadBases());
+            Assert.assertEquals(actual.getReadGroup(), expectedMerged.getReadGroup());
+            Assert.assertEquals(actual.getMappingQuality(), expectedMerged.getMappingQuality());
+            for ( final EventType type : EventType.values() )
+                Assert.assertEquals(actual.getBaseQualities(type), expectedMerged.getBaseQualities(type), "Failed base qualities for event type " + type);
+        }
+    }
+
+    @Test(enabled = !DEBUG)
+    public void testHardClippingBeforeMerge() {
+        final String common = Utils.dupString("A", 10);
+        final byte[] commonQuals = Utils.dupBytes((byte)30, common.length());
+        final String adapter    = "NNNN";
+
+        final GATKSAMRecord read1 = makeOverlappingRead(adapter, 30, common, commonQuals, "", 30, 10);
+        final GATKSAMRecord read2 = makeOverlappingRead("", 30, common, commonQuals, adapter, 30, 10);
+        final GATKSAMRecord expectedMerged = makeOverlappingRead("", 30, common, commonQuals, "", 30, 10);
+        read1.setCigarString("4S" + common.length() + "M");
+        read1.setProperPairFlag(true);
+        read1.setReadPairedFlag(true);
+        read1.setFirstOfPairFlag(true);
+        read1.setReadNegativeStrandFlag(true);
+        read1.setMateNegativeStrandFlag(false);
+        read1.setMateAlignmentStart(read2.getAlignmentStart());
+        read2.setCigarString(common.length() + "M4S");
+        read2.setProperPairFlag(true);
+        read2.setReadPairedFlag(true);
+        read2.setFirstOfPairFlag(false);
+        read2.setReadNegativeStrandFlag(false);
+        read2.setMateNegativeStrandFlag(true);
+        read2.setMateAlignmentStart(read1.getAlignmentStart());
+
+        final int insertSize = common.length() - 1;
+        read1.setInferredInsertSize(-insertSize);
+        read2.setInferredInsertSize(insertSize);
+
+        final GATKSAMRecord actual = FragmentUtils.mergeOverlappingPairedFragments(read1, read2);
+        Assert.assertEquals(actual.getCigarString(), expectedMerged.getCigarString());
+        Assert.assertEquals(actual.getReadBases(), expectedMerged.getReadBases());
+        Assert.assertEquals(actual.getReadGroup(), expectedMerged.getReadGroup());
+        Assert.assertEquals(actual.getMappingQuality(), expectedMerged.getMappingQuality());
+        for ( final EventType type : EventType.values() )
+            Assert.assertEquals(actual.getBaseQualities(type), expectedMerged.getBaseQualities(type), "Failed base qualities for event type " + type);
+    }
+
+    @Test(enabled = true)
+    public void testHardClippingBeforeMergeResultingInCompletelyContainedSecondRead() {
+        final String adapter    = "NNNN";
+
+        final GATKSAMRecord read1 = makeOverlappingRead(adapter, 30, Utils.dupString("A", 10), Utils.dupBytes((byte)30, 10), "", 30, 10);
+        final GATKSAMRecord read2 = makeOverlappingRead("", 30, Utils.dupString("A", 7), Utils.dupBytes((byte)30, 7), adapter, 30, 10);
+        read1.setCigarString("4S10M");
+        read1.setProperPairFlag(true);
+        read1.setFirstOfPairFlag(true);
+        read1.setReadNegativeStrandFlag(true);
+        read1.setMateAlignmentStart(10);
+        read2.setCigarString("7M4S");
+        read2.setProperPairFlag(true);
+        read2.setFirstOfPairFlag(false);
+        read2.setReadNegativeStrandFlag(false);
+
+        final int insertSize = 7 - 1;
+        read1.setInferredInsertSize(insertSize);
+        read2.setInferredInsertSize(-insertSize);
+
+        final GATKSAMRecord actual = FragmentUtils.mergeOverlappingPairedFragments(read1, read2);
+        Assert.assertNull(actual);
+    }
+
+    @DataProvider(name = "MergeFragmentsOffContig")
+    public Object[][] makeMergeFragmentsOffContig() throws Exception {
+        List<Object[]> tests = new ArrayList<>();
+
+        for ( final int pre1 : Arrays.asList(0, 50)) {
+            for ( final int post1 : Arrays.asList(0, 50)) {
+                for ( final int pre2 : Arrays.asList(0, 50)) {
+                    for ( final int post2 : Arrays.asList(0, 50)) {
+                        tests.add(new Object[]{pre1, post1, pre2, post2});
+                    }
+                }
+            }
+        }
+
+        return tests.toArray(new Object[][]{});
+    }
+
+    @Test(dataProvider = "MergeFragmentsOffContig")
+    public void testMergeFragmentsOffContig(final int pre1, final int post1, final int pre2, final int post2) {
+        final int contigSize = 10;
+        final SAMFileHeader header = ArtificialSAMUtils.createArtificialSamHeader(1, 0, contigSize);
+
+        final GATKSAMRecord read1 = createReadOffContig(header, false, pre1, post1);
+        final GATKSAMRecord read2 = createReadOffContig(header, true, pre2, post2);
+
+        final GATKSAMRecord merged = FragmentUtils.mergeOverlappingPairedFragments(read1, read2);
+    }
+
+    private GATKSAMRecord createReadOffContig(final SAMFileHeader header, final boolean negStrand, final int pre, final int post) {
+        final int contigLen = header.getSequence(0).getSequenceLength();
+        final int readLen = pre + contigLen + post;
+        final GATKSAMRecord read = ArtificialSAMUtils.createArtificialRead(header, "read1", 0, 1, readLen);
+        read.setAlignmentStart(1);
+        read.setCigar(TextCigarCodec.getSingleton().decode(pre + "S" + contigLen + "M" + post + "S"));
+        read.setBaseQualities(Utils.dupBytes((byte) 30, readLen));
+        read.setReadBases(Utils.dupBytes((byte)'A', readLen));
+        read.setMappingQuality(60);
+        read.setMateAlignmentStart(1);
+        read.setProperPairFlag(true);
+        read.setReadPairedFlag(true);
+        read.setInferredInsertSize(30);
+        read.setReadNegativeStrandFlag(negStrand);
+        read.setMateNegativeStrandFlag(! negStrand);
+        read.setReadGroup(new GATKSAMReadGroupRecord("foo"));
+        return read;
+    }
+
+
+    private static final byte highQuality = 30;
+    private static final byte overlappingQuality = 20;
+
+    @DataProvider(name = "AdjustFragmentsTest")
+    public Object[][] createAdjustFragmentsTest() throws Exception {
+        List<Object[]> tests = new ArrayList<Object[]>();
+
+        final String leftFlank = "CCC";
+        final String rightFlank = "AAA";
+        final String allOverlappingBases = "ACGTACGTGGAACCTTAG";
+        for ( int overlapSize = 1; overlapSize < allOverlappingBases.length(); overlapSize++ ) {
+            final String overlappingBases = allOverlappingBases.substring(0, overlapSize);
+            final byte[] overlappingBaseQuals = new byte[overlapSize];
+            for ( int i = 0; i < overlapSize; i++ ) overlappingBaseQuals[i] = highQuality;
+            final GATKSAMRecord read1  = makeOverlappingRead(leftFlank, highQuality, overlappingBases, overlappingBaseQuals, "", highQuality, 1);
+            final GATKSAMRecord read2  = makeOverlappingRead("", highQuality, overlappingBases, overlappingBaseQuals, rightFlank, highQuality, leftFlank.length() + 1);
+            tests.add(new Object[]{read1, read2, overlapSize});
+        }
+
+        return tests.toArray(new Object[][]{});
+    }
+
+    @Test(enabled = !DEBUG, dataProvider = "AdjustFragmentsTest")
+    public void testAdjustingTwoReads(final GATKSAMRecord read1, final GATKSAMRecord read2, final int overlapSize) {
+        FragmentUtils.adjustQualsOfOverlappingPairedFragments(read1, read2);
+
+        for ( int i = 0; i < read1.getReadLength() - overlapSize; i++ )
+            Assert.assertEquals(read1.getBaseQualities()[i], highQuality);
+        for ( int i = read1.getReadLength() - overlapSize; i < read1.getReadLength(); i++ )
+            Assert.assertEquals(read1.getBaseQualities()[i], overlappingQuality);
+
+        for ( int i = 0; i < overlapSize; i++ )
+            Assert.assertEquals(read2.getBaseQualities()[i], overlappingQuality);
+        for ( int i = overlapSize; i < read2.getReadLength(); i++ )
+            Assert.assertEquals(read2.getBaseQualities()[i], highQuality);
+    }
+}
diff --git a/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/utils/haplotype/EventMapUnitTest.java b/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/utils/haplotype/EventMapUnitTest.java
new file mode 100644
index 0000000..6baf6ef
--- /dev/null
+++ b/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/utils/haplotype/EventMapUnitTest.java
@@ -0,0 +1,203 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.utils.haplotype;
+
+import htsjdk.samtools.TextCigarCodec;
+import org.broadinstitute.gatk.utils.BaseTest;
+import org.broadinstitute.gatk.utils.GenomeLoc;
+import org.broadinstitute.gatk.utils.UnvalidatingGenomeLoc;
+import org.broadinstitute.gatk.utils.Utils;
+import org.broadinstitute.gatk.utils.variant.GATKVariantContextUtils;
+import htsjdk.variant.variantcontext.VariantContext;
+import org.testng.Assert;
+import org.testng.annotations.DataProvider;
+import org.testng.annotations.Test;
+
+import java.util.*;
+
+public class EventMapUnitTest extends BaseTest {
+    private final static String CHR = "20";
+    private final static String NAME = "foo";
+    
+    @DataProvider(name = "MyDataProvider")
+         public Object[][] makeMyDataProvider() {
+        List<Object[]> tests = new ArrayList<Object[]>();
+
+        final List<String> SNP_ALLELES = Arrays.asList("A", "C");
+        final List<String> INS_ALLELES = Arrays.asList("A", "ACGTGA");
+        final List<String> DEL_ALLELES = Arrays.asList("ACGTA", "C");
+        final List<List<String>> allAlleles = Arrays.asList(SNP_ALLELES, INS_ALLELES, DEL_ALLELES);
+        for ( final int leftNotClump : Arrays.asList(-1, 3) ) {
+            for ( final int middleNotClump : Arrays.asList(-1, 10, 500) ) {
+                for ( final int rightNotClump : Arrays.asList(-1, 1000) ) {
+                    for ( final int nClumped : Arrays.asList(3, 4) ) {
+                        for ( final List<List<String>> alleles : Utils.makePermutations(allAlleles, nClumped, true)) {
+                            final List<VariantContext> allVCS = new LinkedList<VariantContext>();
+
+                            if ( leftNotClump != -1 ) allVCS.add(GATKVariantContextUtils.makeFromAlleles(NAME, CHR, leftNotClump, SNP_ALLELES));
+                            if ( middleNotClump != -1 ) allVCS.add(GATKVariantContextUtils.makeFromAlleles(NAME, CHR, middleNotClump, SNP_ALLELES));
+                            if ( rightNotClump != -1 ) allVCS.add(GATKVariantContextUtils.makeFromAlleles(NAME, CHR, rightNotClump, SNP_ALLELES));
+
+                            int clumpStart = 50;
+                            final List<VariantContext> vcs = new LinkedList<VariantContext>();
+                            for ( final List<String> myAlleles : alleles ) {
+                                final VariantContext vc = GATKVariantContextUtils.makeFromAlleles(NAME, CHR, clumpStart, myAlleles);
+                                clumpStart = vc.getEnd() + 3;
+                                vcs.add(vc);
+                            }
+
+                            tests.add(new Object[]{new EventMap(new LinkedList<VariantContext>(allVCS)), Collections.emptyList()});
+                            allVCS.addAll(vcs);
+                            tests.add(new Object[]{new EventMap(allVCS), vcs});
+                        }
+                    }
+                }
+            }
+        }
+
+        return tests.toArray(new Object[][]{});
+    }
+
+    /**
+     * Example testng test using MyDataProvider
+     */
+    @Test(dataProvider = "MyDataProvider", enabled = true)
+    public void testGetNeighborhood(final EventMap eventMap, final List<VariantContext> expectedNeighbors) {
+        final VariantContext leftOfNeighors = expectedNeighbors.isEmpty() ? null : expectedNeighbors.get(0);
+
+        for ( final VariantContext vc : eventMap.getVariantContexts() ) {
+            final List<VariantContext> n = eventMap.getNeighborhood(vc, 5);
+            if ( leftOfNeighors == vc )
+                Assert.assertEquals(n, expectedNeighbors);
+            else if ( ! expectedNeighbors.contains(vc) )
+                Assert.assertEquals(n, Collections.singletonList(vc), "Should only contain the original vc but " + n);
+        }
+    }
+
+    @DataProvider(name = "BlockSubstitutionsData")
+    public Object[][] makeBlockSubstitutionsData() {
+        List<Object[]> tests = new ArrayList<Object[]>();
+
+        for ( int size = EventMap.MIN_NUMBER_OF_EVENTS_TO_COMBINE_INTO_BLOCK_SUBSTITUTION; size < 10; size++ ) {
+            final String ref = Utils.dupString("A", size);
+            final String alt = Utils.dupString("C", size);
+            tests.add(new Object[]{ref, alt, size + "M", GATKVariantContextUtils.makeFromAlleles(NAME, CHR, 1, Arrays.asList(ref, alt))});
+        }
+
+        tests.add(new Object[]{"AAAAAA", "GAGAGA", "6M", GATKVariantContextUtils.makeFromAlleles(NAME, CHR, 1, Arrays.asList("AAAAA", "GAGAG"))});
+        tests.add(new Object[]{"AAAAAA", "GAGAGG", "6M", GATKVariantContextUtils.makeFromAlleles(NAME, CHR, 1, Arrays.asList("AAAAAA", "GAGAGG"))});
+
+        for ( int len = 0; len < 10; len++ ) {
+            final String s = len == 0 ? "" : Utils.dupString("A", len);
+            tests.add(new Object[]{s + "AACCCCAA", s + "GAAG", len + 2 + "M4D2M", GATKVariantContextUtils.makeFromAlleles(NAME, CHR, 1 + len,   Arrays.asList("AACCCCAA", "GAAG"))});
+            tests.add(new Object[]{s + "AAAA", s + "GACCCCAG", len + 2 + "M4I2M", GATKVariantContextUtils.makeFromAlleles(NAME, CHR, 1 + len, Arrays.asList("AAAA", "GACCCCAG"))});
+
+            tests.add(new Object[]{"AACCCCAA" + s, "GAAG" + s, "2M4D" + (len + 2) + "M", GATKVariantContextUtils.makeFromAlleles(NAME, CHR, 1,   Arrays.asList("AACCCCAA", "GAAG"))});
+            tests.add(new Object[]{"AAAA" + s, "GACCCCAG" + s, "2M4I" + (len + 2) + "M", GATKVariantContextUtils.makeFromAlleles(NAME, CHR, 1, Arrays.asList("AAAA", "GACCCCAG"))});
+        }
+
+        return tests.toArray(new Object[][]{});
+    }
+
+    /**
+     * Example testng test using MyDataProvider
+     */
+    @Test(dataProvider = "BlockSubstitutionsData")
+    public void testBlockSubstitutionsData(final String refBases, final String haplotypeBases, final String cigar, final VariantContext expectedBlock) {
+        final Haplotype hap = new Haplotype(haplotypeBases.getBytes(), false, 0, TextCigarCodec.getSingleton().decode(cigar));
+        final GenomeLoc loc = new UnvalidatingGenomeLoc(CHR, 0, 1, refBases.length());
+        final EventMap ee = new EventMap(hap, refBases.getBytes(), loc, NAME);
+        ee.replaceClumpedEventsWithBlockSubstitutions();
+        Assert.assertEquals(ee.getNumberOfEvents(), 1);
+        final VariantContext actual = ee.getVariantContexts().iterator().next();
+        Assert.assertTrue(GATKVariantContextUtils.equalSites(actual, expectedBlock), "Failed with " + actual);
+    }
+
+    @DataProvider(name = "AdjacentSNPIndelTest")
+    public Object[][] makeAdjacentSNPIndelTest() {
+        List<Object[]> tests = new ArrayList<Object[]>();
+
+        tests.add(new Object[]{"TT", "GCT", "1M1I1M", Arrays.asList(Arrays.asList("T", "GC"))});
+        tests.add(new Object[]{"GCT", "TT", "1M1D1M", Arrays.asList(Arrays.asList("GC", "T"))});
+        tests.add(new Object[]{"TT", "GCCT", "1M2I1M", Arrays.asList(Arrays.asList("T", "GCC"))});
+        tests.add(new Object[]{"GCCT", "TT", "1M2D1M", Arrays.asList(Arrays.asList("GCC", "T"))});
+        tests.add(new Object[]{"AAGCCT", "AATT", "3M2D1M", Arrays.asList(Arrays.asList("GCC", "T"))});
+        tests.add(new Object[]{"AAGCCT", "GATT", "3M2D1M", Arrays.asList(Arrays.asList("A", "G"), Arrays.asList("GCC", "T"))});
+        tests.add(new Object[]{"AAAAA", "AGACA", "5M", Arrays.asList(Arrays.asList("A", "G"), Arrays.asList("A", "C"))});
+
+        return tests.toArray(new Object[][]{});
+    }
+
+    /**
+     * Example testng test using MyDataProvider
+     */
+    @Test(dataProvider = "AdjacentSNPIndelTest")
+    public void testAdjacentSNPIndelTest(final String refBases, final String haplotypeBases, final String cigar, final List<List<String>> expectedAlleles) {
+        final Haplotype hap = new Haplotype(haplotypeBases.getBytes(), false, 0, TextCigarCodec.getSingleton().decode(cigar));
+        final GenomeLoc loc = new UnvalidatingGenomeLoc(CHR, 0, 1, refBases.length());
+        final EventMap ee = new EventMap(hap, refBases.getBytes(), loc, NAME);
+        ee.replaceClumpedEventsWithBlockSubstitutions();
+        Assert.assertEquals(ee.getNumberOfEvents(), expectedAlleles.size());
+        final List<VariantContext> actuals = new ArrayList<VariantContext>(ee.getVariantContexts());
+        for ( int i = 0; i < ee.getNumberOfEvents(); i++ ) {
+            final VariantContext actual = actuals.get(i);
+            Assert.assertEquals(actual.getReference().getDisplayString(), expectedAlleles.get(i).get(0));
+            Assert.assertEquals(actual.getAlternateAllele(0).getDisplayString(), expectedAlleles.get(i).get(1));
+        }
+    }
+
+    @DataProvider(name = "MakeBlockData")
+    public Object[][] makeMakeBlockData() {
+        List<Object[]> tests = new ArrayList<Object[]>();
+
+        tests.add(new Object[]{Arrays.asList("A", "G"), Arrays.asList("AGT", "A"), Arrays.asList("AGT", "G")});
+        tests.add(new Object[]{Arrays.asList("A", "G"), Arrays.asList("A", "AGT"), Arrays.asList("A", "GGT")});
+
+        tests.add(new Object[]{Arrays.asList("AC", "A"), Arrays.asList("A", "AGT"), Arrays.asList("AC", "AGT")});
+        tests.add(new Object[]{Arrays.asList("ACGTA", "A"), Arrays.asList("A", "AG"), Arrays.asList("ACGTA", "AG")});
+        tests.add(new Object[]{Arrays.asList("AC", "A"), Arrays.asList("A", "AGCGT"), Arrays.asList("AC", "AGCGT")});
+        tests.add(new Object[]{Arrays.asList("A", "ACGTA"), Arrays.asList("AG", "A"), Arrays.asList("AG", "ACGTA")});
+        tests.add(new Object[]{Arrays.asList("A", "AC"), Arrays.asList("AGCGT", "A"), Arrays.asList("AGCGT", "AC")});
+
+        return tests.toArray(new Object[][]{});
+    }
+
+    /**
+     * Example testng test using MyDataProvider
+     */
+    @Test(dataProvider = "MakeBlockData", enabled = true)
+    public void testGetNeighborhood(final List<String> firstAlleles, final List<String> secondAlleles, final List<String> expectedAlleles) {
+        final VariantContext vc1 = GATKVariantContextUtils.makeFromAlleles("x", "20", 10, firstAlleles);
+        final VariantContext vc2 = GATKVariantContextUtils.makeFromAlleles("x", "20", 10, secondAlleles);
+        final VariantContext expected = GATKVariantContextUtils.makeFromAlleles("x", "20", 10, expectedAlleles);
+
+        final EventMap eventMap = new EventMap(Collections.<VariantContext>emptyList());
+        final VariantContext block = eventMap.makeBlock(vc1, vc2);
+
+        Assert.assertEquals(block.getStart(), expected.getStart());
+        Assert.assertEquals(block.getAlleles(), expected.getAlleles());
+    }
+}
diff --git a/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/utils/haplotype/HaplotypeUnitTest.java b/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/utils/haplotype/HaplotypeUnitTest.java
new file mode 100644
index 0000000..b0087dc
--- /dev/null
+++ b/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/utils/haplotype/HaplotypeUnitTest.java
@@ -0,0 +1,249 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.utils.haplotype;
+
+
+import htsjdk.samtools.Cigar;
+import htsjdk.samtools.CigarElement;
+import htsjdk.samtools.CigarOperator;
+import htsjdk.samtools.TextCigarCodec;
+import org.broadinstitute.gatk.utils.BaseTest;
+import org.broadinstitute.gatk.utils.GenomeLoc;
+import org.broadinstitute.gatk.utils.UnvalidatingGenomeLoc;
+import org.broadinstitute.gatk.utils.haplotype.Haplotype;
+import htsjdk.variant.variantcontext.Allele;
+import htsjdk.variant.variantcontext.VariantContext;
+import htsjdk.variant.variantcontext.VariantContextBuilder;
+import org.testng.Assert;
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.DataProvider;
+import org.testng.annotations.Test;
+
+import java.util.*;
+
+/**
+ * Basic unit test for Haplotype Class
+ */
+public class HaplotypeUnitTest extends BaseTest {
+    @Test
+    public void testSimpleInsertionAllele() {
+        final String bases = "ACTGGTCAACTGGTCAACTGGTCAACTGGTCA";
+
+        final ArrayList<CigarElement> h1CigarList = new ArrayList<CigarElement>();
+        h1CigarList.add(new CigarElement(bases.length(), CigarOperator.M));
+        final Cigar h1Cigar = new Cigar(h1CigarList);
+        String h1bases = "AACTTCTGGTCAACTGGTCAACTGGTCAACTGGTCA";
+        basicInsertTest("A", "AACTT", 0, h1Cigar, bases, h1bases);
+        h1bases = "ACTGGTCAACTTACTGGTCAACTGGTCAACTGGTCA";
+        basicInsertTest("A", "AACTT", 7, h1Cigar, bases, h1bases);
+        h1bases = "ACTGGTCAACTGGTCAAACTTCTGGTCAACTGGTCA";
+        basicInsertTest("A", "AACTT", 16, h1Cigar, bases, h1bases);
+    }
+
+    @Test
+    public void testSimpleDeletionAllele() {
+        final String bases = "ACTGGTCAACTGGTCAACTGGTCAACTGGTCA";
+
+        final ArrayList<CigarElement> h1CigarList = new ArrayList<CigarElement>();
+        h1CigarList.add(new CigarElement(bases.length(), CigarOperator.M));
+        final Cigar h1Cigar = new Cigar(h1CigarList);
+        String h1bases = "ATCAACTGGTCAACTGGTCAACTGGTCA";
+        basicInsertTest("ACTGG", "A", 0, h1Cigar, bases, h1bases);
+        h1bases = "ACTGGTCAGTCAACTGGTCAACTGGTCA";
+        basicInsertTest("AACTG", "A", 7, h1Cigar, bases, h1bases);
+        h1bases = "ACTGGTCAACTGGTCAATCAACTGGTCA";
+        basicInsertTest("ACTGG", "A", 16, h1Cigar, bases, h1bases);
+    }
+
+    @Test
+    public void testSimpleSNPAllele() {
+        final String bases = "ACTGGTCAACTGGTCAACTGGTCAACTGGTCA";
+
+        final ArrayList<CigarElement> h1CigarList = new ArrayList<CigarElement>();
+        h1CigarList.add(new CigarElement(bases.length(), CigarOperator.M));
+        final Cigar h1Cigar = new Cigar(h1CigarList);
+        String h1bases = "AGTGGTCAACTGGTCAACTGGTCAACTGGTCA";
+        basicInsertTest("C", "G", 1, h1Cigar, bases, h1bases);
+        h1bases = "ACTGGTCTACTGGTCAACTGGTCAACTGGTCA";
+        basicInsertTest("A", "T", 7, h1Cigar, bases, h1bases);
+        h1bases = "ACTGGTCAACTGGTCAAATGGTCAACTGGTCA";
+        basicInsertTest("C", "A", 17, h1Cigar, bases, h1bases);
+    }
+
+    @Test
+    public void testComplexInsertionAllele() {
+        final String bases = "ATCG" + "CCGGCCGGCC" + "ATCGATCG" + "AGGGGGA" + "AGGC";
+
+        final ArrayList<CigarElement> h1CigarList = new ArrayList<CigarElement>();
+        h1CigarList.add(new CigarElement(4, CigarOperator.M));
+        h1CigarList.add(new CigarElement(10, CigarOperator.I));
+        h1CigarList.add(new CigarElement(8, CigarOperator.M));
+        h1CigarList.add(new CigarElement(3, CigarOperator.D));
+        h1CigarList.add(new CigarElement(7 + 4, CigarOperator.M));
+        final Cigar h1Cigar = new Cigar(h1CigarList);
+        String h1bases = "AACTTTCG" + "CCGGCCGGCC" + "ATCGATCG" + "AGGGGGA" + "AGGC";
+        basicInsertTest("A", "AACTT", 0, h1Cigar, bases, h1bases);
+        h1bases = "ATCG" + "CCGGCCGGCC" + "ATCACTTGATCG" + "AGGGGGA" + "AGGC";
+        basicInsertTest("C", "CACTT", 6, h1Cigar, bases, h1bases);
+        h1bases = "ATCG" + "CCGGCCGGCC" + "ATCGATCG" + "AGACTTGGGGA" + "AGGC";
+        basicInsertTest("G", "GACTT", 16, h1Cigar, bases, h1bases);
+    }
+
+    @Test
+    public void testComplexDeletionAllele() {
+        final String bases = "ATCG" + "CCGGCCGGCC" + "ATCGATCG" + "AGGGGGA" + "AGGC";
+
+        final ArrayList<CigarElement> h1CigarList = new ArrayList<CigarElement>();
+        h1CigarList.add(new CigarElement(4, CigarOperator.M));
+        h1CigarList.add(new CigarElement(10, CigarOperator.I));
+        h1CigarList.add(new CigarElement(8, CigarOperator.M));
+        h1CigarList.add(new CigarElement(3, CigarOperator.D));
+        h1CigarList.add(new CigarElement(7 + 4, CigarOperator.M));
+        final Cigar h1Cigar = new Cigar(h1CigarList);
+        String h1bases = "A" + "CCGGCCGGCC" + "ATCGATCG" + "AGGGGGA" + "AGGC";
+        basicInsertTest("ATCG", "A", 0, h1Cigar, bases, h1bases);
+        h1bases = "ATCG" + "CCGGCCGGCC" + "ATAAAG" + "AGGGGGA" + "AGGC";
+        basicInsertTest("CGATC", "AAA", 6, h1Cigar, bases, h1bases);
+        h1bases = "ATCG" + "CCGGCCGGCC" + "ATCGATCG" + "AGA" + "AGGC";
+        basicInsertTest("GGGGG", "G", 16, h1Cigar, bases, h1bases);
+    }
+
+    @Test
+    public void testComplexSNPAllele() {
+        final String bases = "ATCG" + "CCGGCCGGCC" + "ATCGATCG" + "AGGGGGA" + "AGGC";
+
+        final ArrayList<CigarElement> h1CigarList = new ArrayList<CigarElement>();
+        h1CigarList.add(new CigarElement(4, CigarOperator.M));
+        h1CigarList.add(new CigarElement(10, CigarOperator.I));
+        h1CigarList.add(new CigarElement(8, CigarOperator.M));
+        h1CigarList.add(new CigarElement(3, CigarOperator.D));
+        h1CigarList.add(new CigarElement(7 + 4, CigarOperator.M));
+        final Cigar h1Cigar = new Cigar(h1CigarList);
+        String h1bases = "AGCG" + "CCGGCCGGCC" + "ATCGATCG" + "AGGGGGA" + "AGGC";
+        basicInsertTest("T", "G", 1, h1Cigar, bases, h1bases);
+        h1bases = "ATCG" + "CCGGCCGGCC" + "ATCTATCG" + "AGGGGGA" + "AGGC";
+        basicInsertTest("G", "T", 7, h1Cigar, bases, h1bases);
+        h1bases = "ATCG" + "CCGGCCGGCC" + "ATCGATCG" + "AGCGGGA" + "AGGC";
+        basicInsertTest("G", "C", 17, h1Cigar, bases, h1bases);
+    }
+
+    private void basicInsertTest(String ref, String alt, int loc, Cigar cigar, String hap, String newHap) {
+        final Haplotype h = new Haplotype(hap.getBytes());
+        final Allele h1refAllele = Allele.create(ref, true);
+        final Allele h1altAllele = Allele.create(alt, false);
+        final ArrayList<Allele> alleles = new ArrayList<Allele>();
+        alleles.add(h1refAllele);
+        alleles.add(h1altAllele);
+        final VariantContext vc = new VariantContextBuilder().alleles(alleles).loc("1", loc, loc + h1refAllele.getBases().length - 1).make();
+        h.setAlignmentStartHapwrtRef(0);
+        h.setCigar(cigar);
+        final Haplotype h1 = h.insertAllele(vc.getReference(), vc.getAlternateAllele(0), loc, vc.getStart());
+        final Haplotype h1expected = new Haplotype(newHap.getBytes());
+        Assert.assertEquals(h1, h1expected);
+    }
+
+    private Haplotype makeHCForCigar(final String bases, final String cigar) {
+        final Haplotype h = new Haplotype(bases.getBytes());
+        h.setCigar(TextCigarCodec.getSingleton().decode(cigar));
+        return h;
+    }
+
+    @Test
+    public void testConsolidateCigar() throws Exception {
+        Assert.assertEquals(makeHCForCigar("AGCT", "4M").getConsolidatedPaddedCigar(0).toString(), "4M");
+        Assert.assertEquals(makeHCForCigar("AGCT", "4M").getConsolidatedPaddedCigar(1).toString(), "5M");
+        Assert.assertEquals(makeHCForCigar("AGCT", "1M1I1I1M").getConsolidatedPaddedCigar(0).toString(), "1M2I1M");
+        Assert.assertEquals(makeHCForCigar("AGCT", "1M1I1I1M").getConsolidatedPaddedCigar(1).toString(), "1M2I2M");
+        Assert.assertEquals(makeHCForCigar("AGCT", "1M1I1I1M").getConsolidatedPaddedCigar(2).toString(), "1M2I3M");
+        Assert.assertEquals(makeHCForCigar("AGCT", "1M1I1I1I").getConsolidatedPaddedCigar(0).toString(), "1M3I");
+        Assert.assertEquals(makeHCForCigar("AGCT", "1M1I1I1I").getConsolidatedPaddedCigar(1).toString(), "1M3I1M");
+        Assert.assertEquals(makeHCForCigar("AGCT", "1M1I1I1I").getConsolidatedPaddedCigar(2).toString(), "1M3I2M");
+    }
+
+    @DataProvider(name = "TrimmingData")
+    public Object[][] makeTrimmingData() {
+        List<Object[]> tests = new ArrayList<Object[]>();
+
+        // this functionality can be adapted to provide input data for whatever you might want in your data
+        final GenomeLoc loc = new UnvalidatingGenomeLoc("20", 0, 10, 20);
+        final String fullBases = "ACGTAACCGGT";
+        for ( int trimStart = loc.getStart(); trimStart < loc.getStop(); trimStart++ ) {
+            for ( int trimStop = trimStart; trimStop <= loc.getStop(); trimStop++ ) {
+                final int start = trimStart - loc.getStart();
+                final int stop = start + (trimStop - trimStart) + 1;
+                final GenomeLoc trimmedLoc = new UnvalidatingGenomeLoc("20", 0, start + loc.getStart(), stop + loc.getStart() - 1);
+                final String expectedBases = fullBases.substring(start, stop);
+                final Haplotype full = new Haplotype(fullBases.getBytes(), loc);
+                final Haplotype trimmed = new Haplotype(expectedBases.getBytes(), trimmedLoc);
+
+                final int hapStart = 10;
+                full.setAlignmentStartHapwrtRef(hapStart);
+                full.setCigar(TextCigarCodec.getSingleton().decode(full.length() + "M"));
+
+                trimmed.setAlignmentStartHapwrtRef(hapStart + start);
+                trimmed.setCigar(TextCigarCodec.getSingleton().decode(trimmed.length() + "M"));
+
+                tests.add(new Object[]{full, trimmedLoc, trimmed});
+            }
+        }
+
+        final Haplotype full = new Haplotype("ACT".getBytes(), new UnvalidatingGenomeLoc("20", 0, 10, 14));
+        full.setAlignmentStartHapwrtRef(10);
+        full.setCigar(TextCigarCodec.getSingleton().decode("1M2D2M"));
+        tests.add(new Object[]{full, new UnvalidatingGenomeLoc("20", 0, 11, 12), null});
+        tests.add(new Object[]{full, new UnvalidatingGenomeLoc("20", 0, 10, 12), null});
+        tests.add(new Object[]{full, new UnvalidatingGenomeLoc("20", 0, 11, 13), null});
+
+        return tests.toArray(new Object[][]{});
+    }
+
+    @Test(dataProvider = "TrimmingData")
+    public void testTrim(final Haplotype full, final GenomeLoc trimTo, final Haplotype expected) {
+        final Haplotype actual = full.trim(trimTo);
+        if ( expected != null ) {
+            Assert.assertEquals(actual.getBases(), expected.getBases());
+            Assert.assertEquals(actual.getStartPosition(), trimTo.getStart());
+            Assert.assertEquals(actual.getStopPosition(), trimTo.getStop());
+            Assert.assertEquals(actual.getCigar(), expected.getCigar());
+            Assert.assertEquals(actual.getAlignmentStartHapwrtRef(), expected.getAlignmentStartHapwrtRef());
+        } else {
+            Assert.assertNull(actual);
+        }
+    }
+
+    @Test(expectedExceptions = IllegalArgumentException.class)
+    public void testBadTrimLoc() {
+        final GenomeLoc loc = new UnvalidatingGenomeLoc("20", 0, 10, 20);
+        final Haplotype hap = new Haplotype("ACGTAACCGGT".getBytes(), loc);
+        hap.trim(new UnvalidatingGenomeLoc("20", 0, 1, 20));
+    }
+
+    @Test(expectedExceptions = IllegalStateException.class)
+    public void testBadTrimNoLoc() {
+        final Haplotype hap = new Haplotype("ACGTAACCGGT".getBytes());
+        hap.trim(new UnvalidatingGenomeLoc("20", 0, 1, 20));
+    }
+}
diff --git a/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/utils/interval/IntervalIntegrationTest.java b/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/utils/interval/IntervalIntegrationTest.java
new file mode 100644
index 0000000..8d8f7d2
--- /dev/null
+++ b/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/utils/interval/IntervalIntegrationTest.java
@@ -0,0 +1,304 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.utils.interval;
+
+import org.broadinstitute.gatk.engine.walkers.WalkerTest;
+import org.testng.annotations.Test;
+
+import java.io.File;
+import java.util.Arrays;
+import java.util.Collections;
+
+/**
+ * Test the GATK core interval parsing mechanism.
+ */
+public class IntervalIntegrationTest extends WalkerTest {
+    @Test(enabled = true)
+    public void testAllImplicitIntervalParsing() {
+        String md5 = "7821db9e14d4f8e07029ff1959cd5a99";
+        WalkerTest.WalkerTestSpec spec = new WalkerTest.WalkerTestSpec(
+                "-T CountLoci" +
+                        " -I " + validationDataLocation + "OV-0930.normal.chunk.bam" +
+                        " -R " + hg18Reference +
+                        " -o %s",
+                        1, // just one output file
+                        Arrays.asList(md5));
+        executeTest("testAllIntervalsImplicit",spec);
+    }
+
+// '-L all' is no longer supported
+//    @Test(enabled = true)
+//    public void testAllExplicitIntervalParsing() {
+//        String md5 = "7821db9e14d4f8e07029ff1959cd5a99";
+//        WalkerTest.WalkerTestSpec spec = new WalkerTest.WalkerTestSpec(
+//                "-T CountLoci" +
+//                        " -I " + validationDataLocation + "OV-0930.normal.chunk.bam" +
+//                        " -R " + hg18Reference +
+//                        " -L all" +
+//                        " -o %s",
+//                        1, // just one output file
+//                        Arrays.asList(md5));
+//        executeTest("testAllIntervalsExplicit",spec);
+//    }
+
+    @Test
+    public void testUnmappedReadInclusion() {
+        WalkerTest.WalkerTestSpec spec = new WalkerTest.WalkerTestSpec(
+                "-T PrintReads" +
+                        " -I " + validationDataLocation + "MV1994.bam" +
+                        " -R " + validationDataLocation + "Escherichia_coli_K12_MG1655.fasta" +
+                        " -L unmapped" +
+                        " -U",
+                        0, // two output files
+                        Collections.<String>emptyList());
+
+        // our base file
+        File baseOutputFile = createTempFile("testUnmappedReadInclusion",".bam");
+        spec.setOutputFileLocation(baseOutputFile);
+        spec.addAuxFile("95e98192e5b90cf80eaa87a4ace263da",createTempFileFromBase(baseOutputFile.getAbsolutePath()));
+        spec.addAuxFile("fadcdf88597b9609c5f2a17f4c6eb455", createTempFileFromBase(baseOutputFile.getAbsolutePath().substring(0,baseOutputFile.getAbsolutePath().indexOf(".bam"))+".bai"));
+
+        executeTest("testUnmappedReadInclusion",spec);
+    }
+
+    @Test
+    public void testMixedMappedAndUnmapped() {
+        WalkerTest.WalkerTestSpec spec = new WalkerTest.WalkerTestSpec(
+                "-T PrintReads" +
+                        " -I " + validationDataLocation + "MV1994.bam" +
+                        " -R " + validationDataLocation + "Escherichia_coli_K12_MG1655.fasta" +
+                        " -L Escherichia_coli_K12:4630000-4639675" +
+                        " -L unmapped" +
+                        " -U",
+                        0, // two output files
+                        Collections.<String>emptyList());
+
+        // our base file
+        File baseOutputFile = createTempFile("testUnmappedReadInclusion",".bam");
+        spec.setOutputFileLocation(baseOutputFile);
+        spec.addAuxFile("3944b5a6bfc06277ed3afb928a20d588",createTempFileFromBase(baseOutputFile.getAbsolutePath()));
+        spec.addAuxFile("fa90ff91ac0cc689c71a3460a3530b8b", createTempFileFromBase(baseOutputFile.getAbsolutePath().substring(0,baseOutputFile.getAbsolutePath().indexOf(".bam"))+".bai"));
+
+        executeTest("testUnmappedReadInclusion",spec);
+    }
+
+
+    @Test(enabled = false)
+    public void testUnmappedReadExclusion() {
+        WalkerTest.WalkerTestSpec spec = new WalkerTest.WalkerTestSpec(
+                "-T PrintReads" +
+                        " -I " + validationDataLocation + "MV1994.bam" +
+                        " -R " + validationDataLocation + "Escherichia_coli_K12_MG1655.fasta" +
+                        " -XL unmapped" +
+                        " -U",
+                        0, // two output files
+                        Collections.<String>emptyList());
+
+        // our base file
+        File baseOutputFile = createTempFile("testUnmappedReadExclusion",".bam");
+        spec.setOutputFileLocation(baseOutputFile);
+        spec.addAuxFile("80887ba488e53dabd9596ff93070ae75",createTempFileFromBase(baseOutputFile.getAbsolutePath()));
+        spec.addAuxFile("b341d808ecc33217f37c0c0cde2a3e2f", createTempFileFromBase(baseOutputFile.getAbsolutePath().substring(0,baseOutputFile.getAbsolutePath().indexOf(".bam"))+".bai"));
+
+        executeTest("testUnmappedReadExclusion",spec);
+    }
+
+    @Test(enabled = true)
+    public void testIntervalParsingFromFile() {
+        String md5 = "48a24b70a0b376535542b996af517398";
+        WalkerTest.WalkerTestSpec spec = new WalkerTest.WalkerTestSpec(
+                "-T CountLoci" +
+                        " -I " + validationDataLocation + "OV-0930.normal.chunk.bam" +
+                        " -R " + hg18Reference +
+                        " -o %s" +
+                        " -L " + validationDataLocation + "intervalTest.1.vcf",
+                        1, // just one output file
+                        Arrays.asList(md5));
+        executeTest("testIntervalParsingFromFile", spec);
+    }
+
+    @Test(enabled = true)
+    public void testIntervalMergingFromFiles() {
+        String md5 = "9ae0ea9e3c9c6e1b9b6252c8395efdc1";
+        WalkerTest.WalkerTestSpec spec = new WalkerTest.WalkerTestSpec(
+                "-T CountLoci" +
+                        " -I " + validationDataLocation + "OV-0930.normal.chunk.bam" +
+                        " -R " + hg18Reference +
+                        " -o %s" +
+                        " -L " + validationDataLocation + "intervalTest.1.vcf" +
+                        " -L " + validationDataLocation + "intervalTest.2.vcf",
+                        1, // just one output file
+                        Arrays.asList(md5));
+        executeTest("testIntervalMergingFromFiles", spec);
+    }
+
+    @Test(enabled = true)
+    public void testIntervalExclusionsFromFiles() {
+        String md5 = "26ab0db90d72e28ad0ba1e22ee510510";
+        WalkerTest.WalkerTestSpec spec = new WalkerTest.WalkerTestSpec(
+                "-T CountLoci" +
+                        " -I " + validationDataLocation + "OV-0930.normal.chunk.bam" +
+                        " -R " + hg18Reference +
+                        " -o %s" +
+                        " -L " + validationDataLocation + "intervalTest.1.vcf" +
+                        " -XL " + validationDataLocation + "intervalTest.2.vcf",
+                        1, // just one output file
+                        Arrays.asList(md5));
+        executeTest("testIntervalExclusionsFromFiles", spec);
+    }
+
+    @Test(enabled = true)
+    public void testMixedIntervalMerging() {
+        String md5 = "7c5aba41f53293b712fd86d08ed5b36e";
+        WalkerTest.WalkerTestSpec spec = new WalkerTest.WalkerTestSpec(
+                "-T CountLoci" +
+                        " -I " + validationDataLocation + "OV-0930.normal.chunk.bam" +
+                        " -R " + hg18Reference +
+                        " -o %s" +
+                        " -L " + validationDataLocation + "intervalTest.1.vcf" +
+                        " -L chr1:1677524-1677528",
+                        1, // just one output file
+                        Arrays.asList(md5));
+        executeTest("testMixedIntervalMerging", spec);
+    }
+
+    @Test(enabled = true)
+    public void testBed() {
+        String md5 = "cf4278314ef8e4b996e1b798d8eb92cf";
+        WalkerTest.WalkerTestSpec spec = new WalkerTest.WalkerTestSpec(
+                "-T CountLoci" +
+                        " -I " + validationDataLocation + "OV-0930.normal.chunk.bam" +
+                        " -R " + hg18Reference +
+                        " -o %s" +
+                        " -L " + validationDataLocation + "intervalTest.bed",
+                        1, // just one output file
+                        Arrays.asList(md5));
+        executeTest("testBed", spec);
+    }
+
+    @Test(enabled = true)
+    public void testComplexVCF() {
+        String md5 = "166d77ac1b46a1ec38aa35ab7e628ab5";
+        WalkerTest.WalkerTestSpec spec = new WalkerTest.WalkerTestSpec(
+                "-T CountLoci" +
+                        " -I " + validationDataLocation + "OV-0930.normal.chunk.bam" +
+                        " -R " + hg18Reference +
+                        " -o %s" +
+                        " -L " + validationDataLocation + "intervalTest.3.vcf",
+                1, // just one output file
+                Arrays.asList(md5));
+        executeTest("testComplexVCF", spec);
+    }
+
+    @Test(enabled = true)
+    public void testComplexVCFWithPadding() {
+        String md5 = "649ee93d50739c656e94ec88a32c7ffe";
+        WalkerTest.WalkerTestSpec spec = new WalkerTest.WalkerTestSpec(
+                "-T CountLoci" +
+                        " --interval_padding 2" +
+                        " -I " + validationDataLocation + "OV-0930.normal.chunk.bam" +
+                        " -R " + hg18Reference +
+                        " -o %s" +
+                        " -L " + validationDataLocation + "intervalTest.3.vcf",
+                1, // just one output file
+                Arrays.asList(md5));
+        executeTest("testComplexVCFWithPadding", spec);
+    }
+
+    @Test(enabled = true)
+    public void testMergingWithComplexVCF() {
+        String md5 = "6d7fce9fee471194aa8b5b6e47267f03";
+        WalkerTest.WalkerTestSpec spec = new WalkerTest.WalkerTestSpec(
+                "-T CountLoci" +
+                        " -I " + validationDataLocation + "OV-0930.normal.chunk.bam" +
+                        " -R " + hg18Reference +
+                        " -o %s" +
+                        " -L " + validationDataLocation + "intervalTest.1.vcf" +
+                        " -XL " + validationDataLocation + "intervalTest.3.vcf",
+                        1, // just one output file
+                        Arrays.asList(md5));
+        executeTest("testMergingWithComplexVCF", spec);
+    }
+
+    @Test(enabled = true)
+    public void testEmptyVCF() {
+        String md5 = "897316929176464ebc9ad085f31e7284";
+        WalkerTest.WalkerTestSpec spec = new WalkerTest.WalkerTestSpec(
+                "-T CountLoci" +
+                        " -I " + validationDataLocation + "OV-0930.normal.chunk.bam" +
+                        " -R " + hg18Reference +
+                        " -o %s" +
+                        " -L " + validationDataLocation + "intervalTest.empty.vcf",
+                        1, // just one output file
+                        Arrays.asList(md5));
+        executeTest("testEmptyVCFWarning", spec);
+    }
+
+    @Test(enabled = true)
+    public void testIncludeExcludeIsTheSame() {
+        String md5 = "897316929176464ebc9ad085f31e7284";
+        WalkerTest.WalkerTestSpec spec = new WalkerTest.WalkerTestSpec(
+                "-T CountLoci" +
+                        " -I " + validationDataLocation + "OV-0930.normal.chunk.bam" +
+                        " -R " + hg18Reference +
+                        " -o %s" +
+                        " -L " + validationDataLocation + "intervalTest.1.vcf" +
+                        " -XL " + validationDataLocation + "intervalTest.1.vcf",
+                        1, // just one output file
+                        Arrays.asList(md5));
+        executeTest("testIncludeExcludeIsTheSame", spec);
+    }
+
+    @Test(enabled = true)
+    public void testSymbolicAlleles() {
+        String md5 = "52745056d2fd5904857bbd4984c08098";
+        WalkerTest.WalkerTestSpec spec = new WalkerTest.WalkerTestSpec(
+                "-T CountLoci" +
+                        " -I " + validationDataLocation + "NA12878.chrom1.SLX.SRP000032.2009_06.bam" +
+                        " -R " + b36KGReference +
+                        " -o %s" +
+                        " -L " + privateTestDir + "symbolic_alleles_1.vcf",
+                1, // just one output file
+                Arrays.asList(md5));
+        executeTest("testSymbolicAlleles", spec);
+    }
+
+    @Test
+    public void testIntersectionOfLexicographicallySortedIntervals() {
+        final String md5 = "18be9375e5a753f766616a51eb6131f0";
+        WalkerTest.WalkerTestSpec spec = new WalkerTest.WalkerTestSpec(
+                " -T CountLoci" +
+                " -I " + privateTestDir + "NA12878.4.snippet.bam" +
+                " -R " + b37KGReference +
+                " -L " + privateTestDir + "lexicographicallySortedIntervals.bed" +
+                " -L 4" +
+                " -isr INTERSECTION" +
+                " -o %s",
+                1, // just one output file
+                Arrays.asList(md5));
+        executeTest("testIntersectionOfLexicographicallySortedIntervals", spec);
+    }
+}
diff --git a/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/utils/interval/IntervalUtilsUnitTest.java b/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/utils/interval/IntervalUtilsUnitTest.java
new file mode 100644
index 0000000..e9846da
--- /dev/null
+++ b/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/utils/interval/IntervalUtilsUnitTest.java
@@ -0,0 +1,1110 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.utils.interval;
+
+import htsjdk.samtools.reference.IndexedFastaSequenceFile;
+import htsjdk.samtools.reference.ReferenceSequenceFile;
+import htsjdk.samtools.util.Interval;
+import htsjdk.samtools.util.IntervalList;
+import htsjdk.samtools.SAMFileHeader;
+import org.apache.commons.io.FileUtils;
+import htsjdk.tribble.Feature;
+import org.broadinstitute.gatk.utils.BaseTest;
+import org.broadinstitute.gatk.utils.commandline.IntervalBinding;
+import org.broadinstitute.gatk.engine.GenomeAnalysisEngine;
+import org.broadinstitute.gatk.engine.arguments.GATKArgumentCollection;
+import org.broadinstitute.gatk.engine.datasources.reference.ReferenceDataSource;
+import org.broadinstitute.gatk.utils.GenomeLoc;
+import org.broadinstitute.gatk.utils.GenomeLocParser;
+import org.broadinstitute.gatk.utils.GenomeLocSortedSet;
+import org.broadinstitute.gatk.utils.exceptions.UserException;
+import org.broadinstitute.gatk.utils.fasta.CachingIndexedFastaSequenceFile;
+import org.testng.Assert;
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.DataProvider;
+import org.testng.annotations.Test;
+
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.util.*;
+
+/**
+ * test out the interval utility methods
+ */
+public class IntervalUtilsUnitTest extends BaseTest {
+    // used to seed the genome loc parser with a sequence dictionary
+    private SAMFileHeader hg18Header;
+    private GenomeLocParser hg18GenomeLocParser;
+    private List<GenomeLoc> hg18ReferenceLocs;
+    private SAMFileHeader hg19Header;
+    private GenomeLocParser hg19GenomeLocParser;
+    private List<GenomeLoc> hg19ReferenceLocs;
+    private List<GenomeLoc> hg19exomeIntervals;
+
+    private List<GenomeLoc> getLocs(String... intervals) {
+        return getLocs(Arrays.asList(intervals));
+    }
+
+    private List<GenomeLoc> getLocs(List<String> intervals) {
+        if (intervals.size() == 0)
+            return hg18ReferenceLocs;
+        List<GenomeLoc> locs = new ArrayList<GenomeLoc>();
+        for (String interval: intervals)
+            locs.add(hg18GenomeLocParser.parseGenomeLoc(interval));
+        return Collections.unmodifiableList(locs);
+    }
+
+    @BeforeClass
+    public void init() {
+        File hg18Ref = new File(BaseTest.hg18Reference);
+        try {
+            ReferenceDataSource referenceDataSource = new ReferenceDataSource(hg18Ref);
+            hg18Header = new SAMFileHeader();
+            hg18Header.setSequenceDictionary(referenceDataSource.getReference().getSequenceDictionary());
+            ReferenceSequenceFile seq = new CachingIndexedFastaSequenceFile(hg18Ref);
+            hg18GenomeLocParser = new GenomeLocParser(seq);
+            hg18ReferenceLocs = Collections.unmodifiableList(GenomeLocSortedSet.createSetFromSequenceDictionary(referenceDataSource.getReference().getSequenceDictionary()).toList()) ;
+        }
+        catch(FileNotFoundException ex) {
+            throw new UserException.CouldNotReadInputFile(hg18Ref,ex);
+        }
+
+        File hg19Ref = new File(BaseTest.hg19Reference);
+        try {
+            ReferenceDataSource referenceDataSource = new ReferenceDataSource(hg19Ref);
+            hg19Header = new SAMFileHeader();
+            hg19Header.setSequenceDictionary(referenceDataSource.getReference().getSequenceDictionary());
+            ReferenceSequenceFile seq = new CachingIndexedFastaSequenceFile(hg19Ref);
+            hg19GenomeLocParser = new GenomeLocParser(seq);
+            hg19ReferenceLocs = Collections.unmodifiableList(GenomeLocSortedSet.createSetFromSequenceDictionary(referenceDataSource.getReference().getSequenceDictionary()).toList()) ;
+
+            hg19exomeIntervals = Collections.unmodifiableList(IntervalUtils.parseIntervalArguments(hg19GenomeLocParser, Arrays.asList(hg19Intervals)));
+        }
+        catch(FileNotFoundException ex) {
+            throw new UserException.CouldNotReadInputFile(hg19Ref,ex);
+        }
+    }
+
+    // -------------------------------------------------------------------------------------
+    //
+    // tests to ensure the quality of the interval cuts of the interval cutting functions
+    //
+    // -------------------------------------------------------------------------------------
+
+    private class IntervalSlicingTest extends TestDataProvider {
+        public int parts;
+        public double maxAllowableVariance;
+
+        private IntervalSlicingTest(final int parts, final double maxAllowableVariance) {
+            super(IntervalSlicingTest.class);
+            this.parts = parts;
+            this.maxAllowableVariance = maxAllowableVariance;
+        }
+
+        public String toString() {
+            return String.format("IntervalSlicingTest parts=%d maxVar=%.2f", parts, maxAllowableVariance);
+        }
+    }
+
+    @DataProvider(name = "intervalslicingdata")
+    public Object[][] createTrees() {
+        new IntervalSlicingTest(1, 0);
+        new IntervalSlicingTest(2, 1);
+        new IntervalSlicingTest(5, 1);
+        new IntervalSlicingTest(10, 1);
+        new IntervalSlicingTest(67, 1);
+        new IntervalSlicingTest(100, 1);
+        new IntervalSlicingTest(500, 1);
+        new IntervalSlicingTest(1000, 1);
+        return IntervalSlicingTest.getTests(IntervalSlicingTest.class);
+    }
+
+    @Test(enabled = true, dataProvider = "intervalslicingdata")
+    public void testFixedScatterIntervalsAlgorithm(IntervalSlicingTest test) {
+        List<List<GenomeLoc>> splits = IntervalUtils.splitFixedIntervals(hg19exomeIntervals, test.parts);
+
+        long totalSize = IntervalUtils.intervalSize(hg19exomeIntervals);
+        long idealSplitSize = totalSize / test.parts;
+
+        long sumOfSplitSizes = 0;
+        int counter = 0;
+        for ( final List<GenomeLoc> split : splits ) {
+            long splitSize = IntervalUtils.intervalSize(split);
+            double sigma = (splitSize - idealSplitSize) / (1.0 * idealSplitSize);
+            //logger.warn(String.format("Split %d size %d ideal %d sigma %.2f", counter, splitSize, idealSplitSize, sigma));
+            counter++;
+            sumOfSplitSizes += splitSize;
+            Assert.assertTrue(Math.abs(sigma) <= test.maxAllowableVariance, String.format("Interval %d (size %d ideal %d) has a variance %.2f outside of the tolerated range %.2f", counter, splitSize, idealSplitSize, sigma, test.maxAllowableVariance));
+        }
+
+        Assert.assertEquals(totalSize, sumOfSplitSizes, "Split intervals don't contain the exact number of bases in the origianl intervals");
+    }
+
+    // -------------------------------------------------------------------------------------
+    //
+    // splitLocusIntervals tests
+    //
+    // -------------------------------------------------------------------------------------
+
+    /** large scale tests for many intervals */
+    private class SplitLocusIntervalsTest extends TestDataProvider {
+        final List<GenomeLoc> originalIntervals;
+        final public int parts;
+
+        private SplitLocusIntervalsTest(final String name, List<GenomeLoc> originalIntervals, final int parts) {
+            super(SplitLocusIntervalsTest.class, name);
+            this.parts = parts;
+            this.originalIntervals = originalIntervals;
+        }
+
+        public String toString() {
+            return String.format("%s parts=%d", super.toString(), parts);
+        }
+    }
+
+    @DataProvider(name = "IntervalRepartitionTest")
+    public Object[][] createIntervalRepartitionTest() {
+        for ( int parts : Arrays.asList(1, 2, 3, 10, 13, 100, 151, 1000, 10000) ) {
+        //for ( int parts : Arrays.asList(10) ) {
+            new SplitLocusIntervalsTest("hg19RefLocs", hg19ReferenceLocs, parts);
+            new SplitLocusIntervalsTest("hg19ExomeLocs", hg19exomeIntervals, parts);
+        }
+
+        return SplitLocusIntervalsTest.getTests(SplitLocusIntervalsTest.class);
+    }
+
+    @Test(enabled = true, dataProvider = "IntervalRepartitionTest")
+    public void testIntervalRepartition(SplitLocusIntervalsTest test) {
+        List<List<GenomeLoc>> splitByLocus = IntervalUtils.splitLocusIntervals(test.originalIntervals, test.parts);
+        Assert.assertEquals(splitByLocus.size(), test.parts, "SplitLocusIntervals failed to generate correct number of intervals");
+        List<GenomeLoc> flat = IntervalUtils.flattenSplitIntervals(splitByLocus);
+
+        // test overall size
+        final long originalSize = IntervalUtils.intervalSize(test.originalIntervals);
+        final long flatSize = IntervalUtils.intervalSize(flat);
+        Assert.assertEquals(flatSize, originalSize, "SplitLocusIntervals locs cover an incorrect number of bases");
+
+        // test size of each split
+        final long ideal = (long)Math.floor(originalSize / (1.0 * test.parts));
+        final long maxSize = ideal + (originalSize % test.parts) * test.parts; // no more than N * rounding error in size
+        for ( final List<GenomeLoc> split : splitByLocus ) {
+            final long splitSize = IntervalUtils.intervalSize(split);
+            Assert.assertTrue(splitSize >= ideal && splitSize <= maxSize,
+                    String.format("SplitLocusIntervals interval (start=%s) has size %d outside of bounds ideal=%d, max=%d",
+                            split.get(0), splitSize, ideal, maxSize));
+        }
+
+        // test that every base in original is covered once by a base in split by locus intervals
+        String diff = IntervalUtils.equateIntervals(test.originalIntervals, flat);
+        Assert.assertNull(diff, diff);
+    }
+
+    /** small scale tests where the expected cuts are enumerated upfront for testing */
+    private class SplitLocusIntervalsSmallTest extends TestDataProvider {
+        final List<GenomeLoc> original;
+        final public int parts;
+        final public int expectedParts;
+        final List<GenomeLoc> expected;
+
+        private SplitLocusIntervalsSmallTest(final String name, List<GenomeLoc> originalIntervals, final int parts, List<GenomeLoc> expected) {
+            this(name, originalIntervals, parts,  expected, parts);
+        }
+
+        private SplitLocusIntervalsSmallTest(final String name, List<GenomeLoc> originalIntervals, final int parts, List<GenomeLoc> expected, int expectedParts) {
+            super(SplitLocusIntervalsSmallTest.class, name);
+            this.parts = parts;
+            this.expectedParts = expectedParts;
+            this.original = originalIntervals;
+            this.expected = expected;
+        }
+
+        public String toString() {
+            return String.format("%s parts=%d", super.toString(), parts);
+        }
+    }
+
+    @DataProvider(name = "SplitLocusIntervalsSmallTest")
+    public Object[][] createSplitLocusIntervalsSmallTest() {
+        GenomeLoc bp01_10 = hg19GenomeLocParser.createGenomeLoc("1", 1, 10);
+
+        GenomeLoc bp1_5 = hg19GenomeLocParser.createGenomeLoc("1", 1, 5);
+        GenomeLoc bp6_10 = hg19GenomeLocParser.createGenomeLoc("1", 6, 10);
+        new SplitLocusIntervalsSmallTest("cut into two", Arrays.asList(bp01_10), 2, Arrays.asList(bp1_5, bp6_10));
+
+        GenomeLoc bp20_30 = hg19GenomeLocParser.createGenomeLoc("1", 20, 30);
+        new SplitLocusIntervalsSmallTest("two in two", Arrays.asList(bp01_10, bp20_30), 2, Arrays.asList(bp01_10, bp20_30));
+
+        GenomeLoc bp1_7 = hg19GenomeLocParser.createGenomeLoc("1", 1, 7);
+        GenomeLoc bp8_10 = hg19GenomeLocParser.createGenomeLoc("1", 8, 10);
+        GenomeLoc bp20_23 = hg19GenomeLocParser.createGenomeLoc("1", 20, 23);
+        GenomeLoc bp24_30 = hg19GenomeLocParser.createGenomeLoc("1", 24, 30);
+        new SplitLocusIntervalsSmallTest("two in three", Arrays.asList(bp01_10, bp20_30), 3,
+                Arrays.asList(bp1_7, bp8_10, bp20_23, bp24_30));
+
+        GenomeLoc bp1_2 = hg19GenomeLocParser.createGenomeLoc("1", 1, 2);
+        GenomeLoc bp1_1 = hg19GenomeLocParser.createGenomeLoc("1", 1, 1);
+        GenomeLoc bp2_2 = hg19GenomeLocParser.createGenomeLoc("1", 2, 2);
+        new SplitLocusIntervalsSmallTest("too many pieces", Arrays.asList(bp1_2), 5, Arrays.asList(bp1_1, bp2_2), 2);
+
+        new SplitLocusIntervalsSmallTest("emptyList", Collections.<GenomeLoc>emptyList(), 5, Collections.<GenomeLoc>emptyList(), 0);
+
+        return SplitLocusIntervalsSmallTest.getTests(SplitLocusIntervalsSmallTest.class);
+    }
+
+    @Test(enabled = true, dataProvider = "SplitLocusIntervalsSmallTest")
+    public void splitLocusIntervalsSmallTest(SplitLocusIntervalsSmallTest test) {
+        List<List<GenomeLoc>> splitByLocus = IntervalUtils.splitLocusIntervals(test.original, test.parts);
+        Assert.assertEquals(splitByLocus.size(), test.expectedParts, "SplitLocusIntervals failed to generate correct number of intervals");
+        List<GenomeLoc> flat = IntervalUtils.flattenSplitIntervals(splitByLocus);
+
+        // test sizes
+        final long originalSize = IntervalUtils.intervalSize(test.original);
+        final long splitSize = IntervalUtils.intervalSize(flat);
+        Assert.assertEquals(splitSize, originalSize, "SplitLocusIntervals locs cover an incorrect number of bases");
+
+        Assert.assertEquals(flat, test.expected, "SplitLocusIntervals locs not expected intervals");
+    }
+
+    //
+    // Misc. tests
+    //
+
+    @Test(expectedExceptions=UserException.class)
+    public void testMergeListsBySetOperatorNoOverlap() {
+        // a couple of lists we'll use for the testing
+        List<GenomeLoc> listEveryTwoFromOne = new ArrayList<GenomeLoc>();
+        List<GenomeLoc> listEveryTwoFromTwo = new ArrayList<GenomeLoc>();
+
+        // create the two lists we'll use
+        for (int x = 1; x < 101; x++) {
+            if (x % 2 == 0)
+                listEveryTwoFromTwo.add(hg18GenomeLocParser.createGenomeLoc("chr1",x,x));
+            else
+                listEveryTwoFromOne.add(hg18GenomeLocParser.createGenomeLoc("chr1",x,x));
+        }
+
+        List<GenomeLoc> ret;
+        ret = IntervalUtils.mergeListsBySetOperator(listEveryTwoFromTwo, listEveryTwoFromOne, IntervalSetRule.UNION);
+        Assert.assertEquals(ret.size(), 100);
+        ret = IntervalUtils.mergeListsBySetOperator(listEveryTwoFromTwo, listEveryTwoFromOne, null);
+        Assert.assertEquals(ret.size(), 100);
+        ret = IntervalUtils.mergeListsBySetOperator(listEveryTwoFromTwo, listEveryTwoFromOne, IntervalSetRule.INTERSECTION);
+        Assert.assertEquals(ret.size(), 0);
+    }
+
+    @Test
+    public void testMergeListsBySetOperatorAllOverlap() {
+        // a couple of lists we'll use for the testing
+        List<GenomeLoc> allSites = new ArrayList<GenomeLoc>();
+        List<GenomeLoc> listEveryTwoFromTwo = new ArrayList<GenomeLoc>();
+
+        // create the two lists we'll use
+        for (int x = 1; x < 101; x++) {
+            if (x % 2 == 0)
+                listEveryTwoFromTwo.add(hg18GenomeLocParser.createGenomeLoc("chr1",x,x));
+            allSites.add(hg18GenomeLocParser.createGenomeLoc("chr1",x,x));
+        }
+
+        List<GenomeLoc> ret;
+        ret = IntervalUtils.mergeListsBySetOperator(listEveryTwoFromTwo, allSites, IntervalSetRule.UNION);
+        Assert.assertEquals(ret.size(), 150);
+        ret = IntervalUtils.mergeListsBySetOperator(listEveryTwoFromTwo, allSites, null);
+        Assert.assertEquals(ret.size(), 150);
+        ret = IntervalUtils.mergeListsBySetOperator(listEveryTwoFromTwo, allSites, IntervalSetRule.INTERSECTION);
+        Assert.assertEquals(ret.size(), 50);
+    }
+
+    @Test
+    public void testMergeListsBySetOperator() {
+        // a couple of lists we'll use for the testing
+        List<GenomeLoc> allSites = new ArrayList<GenomeLoc>();
+        List<GenomeLoc> listEveryTwoFromTwo = new ArrayList<GenomeLoc>();
+
+        // create the two lists we'll use
+        for (int x = 1; x < 101; x++) {
+            if (x % 5 == 0) {
+                listEveryTwoFromTwo.add(hg18GenomeLocParser.createGenomeLoc("chr1",x,x));
+                allSites.add(hg18GenomeLocParser.createGenomeLoc("chr1",x,x));
+            }
+        }
+
+        List<GenomeLoc> ret;
+        ret = IntervalUtils.mergeListsBySetOperator(listEveryTwoFromTwo, allSites, IntervalSetRule.UNION);
+        Assert.assertEquals(ret.size(), 40);
+        ret = IntervalUtils.mergeListsBySetOperator(listEveryTwoFromTwo, allSites, null);
+        Assert.assertEquals(ret.size(), 40);
+        ret = IntervalUtils.mergeListsBySetOperator(listEveryTwoFromTwo, allSites, IntervalSetRule.INTERSECTION);
+        Assert.assertEquals(ret.size(), 20);
+    }
+
+    @Test
+    public void testOverlappingIntervalsFromSameSourceWithIntersection() {
+        // a couple of lists we'll use for the testing
+        List<GenomeLoc> source1 = new ArrayList<GenomeLoc>();
+        List<GenomeLoc> source2 = new ArrayList<GenomeLoc>();
+
+        source1.add(hg18GenomeLocParser.createGenomeLoc("chr1", 10, 20));
+        source1.add(hg18GenomeLocParser.createGenomeLoc("chr1", 15, 25));
+
+        source2.add(hg18GenomeLocParser.createGenomeLoc("chr1", 16, 18));
+        source2.add(hg18GenomeLocParser.createGenomeLoc("chr1", 22, 24));
+
+        List<GenomeLoc> ret = IntervalUtils.mergeListsBySetOperator(source1, source2, IntervalSetRule.INTERSECTION);
+        Assert.assertEquals(ret.size(), 2);
+    }
+
+    @Test
+    public void testGetContigLengths() {
+        Map<String, Integer> lengths = IntervalUtils.getContigSizes(new File(BaseTest.hg18Reference));
+        Assert.assertEquals((long)lengths.get("chr1"), 247249719);
+        Assert.assertEquals((long)lengths.get("chr2"), 242951149);
+        Assert.assertEquals((long)lengths.get("chr3"), 199501827);
+        Assert.assertEquals((long)lengths.get("chr20"), 62435964);
+        Assert.assertEquals((long)lengths.get("chrX"), 154913754);
+    }
+
+    @Test
+    public void testParseIntervalArguments() {
+        Assert.assertEquals(getLocs().size(), 45);
+        Assert.assertEquals(getLocs("chr1", "chr2", "chr3").size(), 3);
+        Assert.assertEquals(getLocs("chr1:1-2", "chr1:4-5", "chr2:1-1", "chr3:2-2").size(), 4);
+    }
+
+    @Test
+    public void testIsIntervalFile() {
+        Assert.assertTrue(IntervalUtils.isIntervalFile(BaseTest.privateTestDir + "empty_intervals.list"));
+        Assert.assertTrue(IntervalUtils.isIntervalFile(BaseTest.privateTestDir + "empty_intervals.list", true));
+
+        List<String> extensions = Arrays.asList("bed", "interval_list", "intervals", "list", "picard");
+        for (String extension: extensions) {
+            Assert.assertTrue(IntervalUtils.isIntervalFile("test_intervals." + extension, false), "Tested interval file extension: " + extension);
+        }
+    }
+
+    @Test(expectedExceptions = UserException.CouldNotReadInputFile.class)
+    public void testMissingIntervalFile() {
+        IntervalUtils.isIntervalFile(BaseTest.privateTestDir + "no_such_intervals.list");
+    }
+
+    @Test
+    public void testFixedScatterIntervalsBasic() {
+        GenomeLoc chr1 = hg18GenomeLocParser.parseGenomeLoc("chr1");
+        GenomeLoc chr2 = hg18GenomeLocParser.parseGenomeLoc("chr2");
+        GenomeLoc chr3 = hg18GenomeLocParser.parseGenomeLoc("chr3");
+
+        List<File> files = testFiles("basic.", 3, ".intervals");
+
+        List<GenomeLoc> locs = getLocs("chr1", "chr2", "chr3");
+        List<List<GenomeLoc>> splits = IntervalUtils.splitFixedIntervals(locs, files.size());
+        IntervalUtils.scatterFixedIntervals(hg18Header, splits, files);
+
+        List<GenomeLoc> locs1 = IntervalUtils.parseIntervalArguments(hg18GenomeLocParser, Arrays.asList(files.get(0).toString()));
+        List<GenomeLoc> locs2 = IntervalUtils.parseIntervalArguments(hg18GenomeLocParser, Arrays.asList(files.get(1).toString()));
+        List<GenomeLoc> locs3 = IntervalUtils.parseIntervalArguments(hg18GenomeLocParser, Arrays.asList(files.get(2).toString()));
+
+        Assert.assertEquals(locs1.size(), 1);
+        Assert.assertEquals(locs2.size(), 1);
+        Assert.assertEquals(locs3.size(), 1);
+
+        Assert.assertEquals(locs1.get(0), chr1);
+        Assert.assertEquals(locs2.get(0), chr2);
+        Assert.assertEquals(locs3.get(0), chr3);
+    }
+
+    @Test
+    public void testScatterFixedIntervalsLessFiles() {
+        GenomeLoc chr1 = hg18GenomeLocParser.parseGenomeLoc("chr1");
+        GenomeLoc chr2 = hg18GenomeLocParser.parseGenomeLoc("chr2");
+        GenomeLoc chr3 = hg18GenomeLocParser.parseGenomeLoc("chr3");
+        GenomeLoc chr4 = hg18GenomeLocParser.parseGenomeLoc("chr4");
+
+        List<File> files = testFiles("less.", 3, ".intervals");
+
+        List<GenomeLoc> locs = getLocs("chr1", "chr2", "chr3", "chr4");
+        List<List<GenomeLoc>> splits = IntervalUtils.splitFixedIntervals(locs, files.size());
+        IntervalUtils.scatterFixedIntervals(hg18Header, splits, files);
+
+        List<GenomeLoc> locs1 = IntervalUtils.parseIntervalArguments(hg18GenomeLocParser, Arrays.asList(files.get(0).toString()));
+        List<GenomeLoc> locs2 = IntervalUtils.parseIntervalArguments(hg18GenomeLocParser, Arrays.asList(files.get(1).toString()));
+        List<GenomeLoc> locs3 = IntervalUtils.parseIntervalArguments(hg18GenomeLocParser, Arrays.asList(files.get(2).toString()));
+
+        Assert.assertEquals(locs1.size(), 1);
+        Assert.assertEquals(locs2.size(), 1);
+        Assert.assertEquals(locs3.size(), 2);
+
+        Assert.assertEquals(locs1.get(0), chr1);
+        Assert.assertEquals(locs2.get(0), chr2);
+        Assert.assertEquals(locs3.get(0), chr3);
+        Assert.assertEquals(locs3.get(1), chr4);
+    }
+
+    @Test(expectedExceptions=UserException.BadArgumentValue.class)
+    public void testSplitFixedIntervalsMoreFiles() {
+        List<File> files = testFiles("more.", 3, ".intervals");
+        List<GenomeLoc> locs = getLocs("chr1", "chr2");
+        IntervalUtils.splitFixedIntervals(locs, files.size());
+    }
+
+    @Test(expectedExceptions=UserException.BadArgumentValue.class)
+    public void testScatterFixedIntervalsMoreFiles() {
+        List<File> files = testFiles("more.", 3, ".intervals");
+        List<GenomeLoc> locs = getLocs("chr1", "chr2");
+        List<List<GenomeLoc>> splits = IntervalUtils.splitFixedIntervals(locs, locs.size()); // locs.size() instead of files.size()
+        IntervalUtils.scatterFixedIntervals(hg18Header, splits, files);
+    }
+    @Test
+    public void testScatterFixedIntervalsStart() {
+        List<String> intervals = Arrays.asList("chr1:1-2", "chr1:4-5", "chr2:1-1", "chr3:2-2");
+        GenomeLoc chr1a = hg18GenomeLocParser.parseGenomeLoc("chr1:1-2");
+        GenomeLoc chr1b = hg18GenomeLocParser.parseGenomeLoc("chr1:4-5");
+        GenomeLoc chr2 = hg18GenomeLocParser.parseGenomeLoc("chr2:1-1");
+        GenomeLoc chr3 = hg18GenomeLocParser.parseGenomeLoc("chr3:2-2");
+
+        List<File> files = testFiles("split.", 3, ".intervals");
+
+        List<GenomeLoc> locs = getLocs(intervals);
+        List<List<GenomeLoc>> splits = IntervalUtils.splitFixedIntervals(locs, files.size());
+        IntervalUtils.scatterFixedIntervals(hg18Header, splits, files);
+
+        List<GenomeLoc> locs1 = IntervalUtils.parseIntervalArguments(hg18GenomeLocParser, Arrays.asList(files.get(0).toString()));
+        List<GenomeLoc> locs2 = IntervalUtils.parseIntervalArguments(hg18GenomeLocParser, Arrays.asList(files.get(1).toString()));
+        List<GenomeLoc> locs3 = IntervalUtils.parseIntervalArguments(hg18GenomeLocParser, Arrays.asList(files.get(2).toString()));
+
+        Assert.assertEquals(locs1.size(), 1);
+        Assert.assertEquals(locs2.size(), 1);
+        Assert.assertEquals(locs3.size(), 2);
+
+        Assert.assertEquals(locs1.get(0), chr1a);
+        Assert.assertEquals(locs2.get(0), chr1b);
+        Assert.assertEquals(locs3.get(0), chr2);
+        Assert.assertEquals(locs3.get(1), chr3);
+    }
+
+    @Test
+    public void testScatterFixedIntervalsMiddle() {
+        List<String> intervals = Arrays.asList("chr1:1-1", "chr2:1-2", "chr2:4-5", "chr3:2-2");
+        GenomeLoc chr1 = hg18GenomeLocParser.parseGenomeLoc("chr1:1-1");
+        GenomeLoc chr2a = hg18GenomeLocParser.parseGenomeLoc("chr2:1-2");
+        GenomeLoc chr2b = hg18GenomeLocParser.parseGenomeLoc("chr2:4-5");
+        GenomeLoc chr3 = hg18GenomeLocParser.parseGenomeLoc("chr3:2-2");
+
+        List<File> files = testFiles("split.", 3, ".intervals");
+
+        List<GenomeLoc> locs = getLocs(intervals);
+        List<List<GenomeLoc>> splits = IntervalUtils.splitFixedIntervals(locs, files.size());
+        IntervalUtils.scatterFixedIntervals(hg18Header, splits, files);
+
+        List<GenomeLoc> locs1 = IntervalUtils.parseIntervalArguments(hg18GenomeLocParser, Arrays.asList(files.get(0).toString()));
+        List<GenomeLoc> locs2 = IntervalUtils.parseIntervalArguments(hg18GenomeLocParser, Arrays.asList(files.get(1).toString()));
+        List<GenomeLoc> locs3 = IntervalUtils.parseIntervalArguments(hg18GenomeLocParser, Arrays.asList(files.get(2).toString()));
+
+        Assert.assertEquals(locs1.size(), 1);
+        Assert.assertEquals(locs2.size(), 1);
+        Assert.assertEquals(locs3.size(), 2);
+
+        Assert.assertEquals(locs1.get(0), chr1);
+        Assert.assertEquals(locs2.get(0), chr2a);
+        Assert.assertEquals(locs3.get(0), chr2b);
+        Assert.assertEquals(locs3.get(1), chr3);
+    }
+
+    @Test
+    public void testScatterFixedIntervalsEnd() {
+        List<String> intervals = Arrays.asList("chr1:1-1", "chr2:2-2", "chr3:1-2", "chr3:4-5");
+        GenomeLoc chr1 = hg18GenomeLocParser.parseGenomeLoc("chr1:1-1");
+        GenomeLoc chr2 = hg18GenomeLocParser.parseGenomeLoc("chr2:2-2");
+        GenomeLoc chr3a = hg18GenomeLocParser.parseGenomeLoc("chr3:1-2");
+        GenomeLoc chr3b = hg18GenomeLocParser.parseGenomeLoc("chr3:4-5");
+
+        List<File> files = testFiles("split.", 3, ".intervals");
+
+        List<GenomeLoc> locs = getLocs(intervals);
+        List<List<GenomeLoc>> splits = IntervalUtils.splitFixedIntervals(locs, files.size());
+        IntervalUtils.scatterFixedIntervals(hg18Header, splits, files);
+
+        List<GenomeLoc> locs1 = IntervalUtils.parseIntervalArguments(hg18GenomeLocParser, Arrays.asList(files.get(0).toString()));
+        List<GenomeLoc> locs2 = IntervalUtils.parseIntervalArguments(hg18GenomeLocParser, Arrays.asList(files.get(1).toString()));
+        List<GenomeLoc> locs3 = IntervalUtils.parseIntervalArguments(hg18GenomeLocParser, Arrays.asList(files.get(2).toString()));
+
+        Assert.assertEquals(locs1.size(), 2);
+        Assert.assertEquals(locs2.size(), 1);
+        Assert.assertEquals(locs3.size(), 1);
+
+        Assert.assertEquals(locs1.get(0), chr1);
+        Assert.assertEquals(locs1.get(1), chr2);
+        Assert.assertEquals(locs2.get(0), chr3a);
+        Assert.assertEquals(locs3.get(0), chr3b);
+    }
+
+    @Test
+    public void testScatterFixedIntervalsFile() {
+        List<File> files = testFiles("sg.", 20, ".intervals");
+        List<GenomeLoc> locs = IntervalUtils.parseIntervalArguments(hg18GenomeLocParser, Arrays.asList(BaseTest.GATKDataLocation + "whole_exome_agilent_designed_120.targets.hg18.chr20.interval_list"));
+        List<List<GenomeLoc>> splits = IntervalUtils.splitFixedIntervals(locs, files.size());
+
+        int[] counts = {
+                125, 138, 287, 291, 312, 105, 155, 324,
+                295, 298, 141, 121, 285, 302, 282, 88,
+                116, 274, 282, 248
+//                5169, 5573, 10017, 10567, 10551,
+//                5087, 4908, 10120, 10435, 10399,
+//                5391, 4735, 10621, 10352, 10654,
+//                5227, 5256, 10151, 9649, 9825
+        };
+
+        //String splitCounts = "";
+        for (int i = 0; i < splits.size(); i++) {
+            int splitCount = splits.get(i).size();
+            Assert.assertEquals(splitCount, counts[i], "Num intervals in split " + i);
+        }
+        //System.out.println(splitCounts.substring(2));
+
+        IntervalUtils.scatterFixedIntervals(hg18Header, splits, files);
+
+        int locIndex = 0;
+        for (int i = 0; i < files.size(); i++) {
+            String file = files.get(i).toString();
+            List<GenomeLoc> parsedLocs = IntervalUtils.parseIntervalArguments(hg18GenomeLocParser, Arrays.asList(file));
+            Assert.assertEquals(parsedLocs.size(), counts[i], "Intervals in " + file);
+            for (GenomeLoc parsedLoc: parsedLocs)
+                Assert.assertEquals(parsedLoc, locs.get(locIndex), String.format("Genome loc %d from file %d", locIndex++, i));
+        }
+        Assert.assertEquals(locIndex, locs.size(), "Total number of GenomeLocs");
+    }
+
+    @Test
+    public void testScatterFixedIntervalsMax() {
+        List<File> files = testFiles("sg.", 85, ".intervals");
+        List<List<GenomeLoc>> splits = IntervalUtils.splitFixedIntervals(hg19ReferenceLocs, files.size());
+        IntervalUtils.scatterFixedIntervals(hg19Header, splits, files);
+
+        for (int i = 0; i < files.size(); i++) {
+            String file = files.get(i).toString();
+            List<GenomeLoc> parsedLocs = IntervalUtils.parseIntervalArguments(hg19GenomeLocParser, Arrays.asList(file));
+            Assert.assertEquals(parsedLocs.size(), 1, "parsedLocs[" + i + "].size()");
+            Assert.assertEquals(parsedLocs.get(0), hg19ReferenceLocs.get(i), "parsedLocs[" + i + "].get()");
+        }
+    }
+
+    @Test
+    public void testScatterContigIntervalsOrder() {
+        List<String> intervals = Arrays.asList("chr2:1-1", "chr1:1-1", "chr3:2-2");
+        GenomeLoc chr1 = hg18GenomeLocParser.parseGenomeLoc("chr1:1-1");
+        GenomeLoc chr2 = hg18GenomeLocParser.parseGenomeLoc("chr2:1-1");
+        GenomeLoc chr3 = hg18GenomeLocParser.parseGenomeLoc("chr3:2-2");
+
+        List<File> files = testFiles("split.", 3, ".intervals");
+
+        IntervalUtils.scatterContigIntervals(hg18Header, getLocs(intervals), files);
+
+        List<GenomeLoc> locs1 = IntervalUtils.parseIntervalArguments(hg18GenomeLocParser, Arrays.asList(files.get(0).toString()));
+        List<GenomeLoc> locs2 = IntervalUtils.parseIntervalArguments(hg18GenomeLocParser, Arrays.asList(files.get(1).toString()));
+        List<GenomeLoc> locs3 = IntervalUtils.parseIntervalArguments(hg18GenomeLocParser, Arrays.asList(files.get(2).toString()));
+
+        Assert.assertEquals(locs1.size(), 1);
+        Assert.assertEquals(locs2.size(), 1);
+        Assert.assertEquals(locs3.size(), 1);
+
+        Assert.assertEquals(locs1.get(0), chr2);
+        Assert.assertEquals(locs2.get(0), chr1);
+        Assert.assertEquals(locs3.get(0), chr3);
+    }
+
+    @Test
+    public void testScatterContigIntervalsBasic() {
+        GenomeLoc chr1 = hg18GenomeLocParser.parseGenomeLoc("chr1");
+        GenomeLoc chr2 = hg18GenomeLocParser.parseGenomeLoc("chr2");
+        GenomeLoc chr3 = hg18GenomeLocParser.parseGenomeLoc("chr3");
+
+        List<File> files = testFiles("contig_basic.", 3, ".intervals");
+
+        IntervalUtils.scatterContigIntervals(hg18Header, getLocs("chr1", "chr2", "chr3"), files);
+
+        List<GenomeLoc> locs1 = IntervalUtils.parseIntervalArguments(hg18GenomeLocParser, Arrays.asList(files.get(0).toString()));
+        List<GenomeLoc> locs2 = IntervalUtils.parseIntervalArguments(hg18GenomeLocParser, Arrays.asList(files.get(1).toString()));
+        List<GenomeLoc> locs3 = IntervalUtils.parseIntervalArguments(hg18GenomeLocParser, Arrays.asList(files.get(2).toString()));
+
+        Assert.assertEquals(locs1.size(), 1);
+        Assert.assertEquals(locs2.size(), 1);
+        Assert.assertEquals(locs3.size(), 1);
+
+        Assert.assertEquals(locs1.get(0), chr1);
+        Assert.assertEquals(locs2.get(0), chr2);
+        Assert.assertEquals(locs3.get(0), chr3);
+    }
+
+    @Test
+    public void testScatterContigIntervalsLessFiles() {
+        GenomeLoc chr1 = hg18GenomeLocParser.parseGenomeLoc("chr1");
+        GenomeLoc chr2 = hg18GenomeLocParser.parseGenomeLoc("chr2");
+        GenomeLoc chr3 = hg18GenomeLocParser.parseGenomeLoc("chr3");
+        GenomeLoc chr4 = hg18GenomeLocParser.parseGenomeLoc("chr4");
+
+        List<File> files = testFiles("contig_less.", 3, ".intervals");
+
+        IntervalUtils.scatterContigIntervals(hg18Header, getLocs("chr1", "chr2", "chr3", "chr4"), files);
+
+        List<GenomeLoc> locs1 = IntervalUtils.parseIntervalArguments(hg18GenomeLocParser, Arrays.asList(files.get(0).toString()));
+        List<GenomeLoc> locs2 = IntervalUtils.parseIntervalArguments(hg18GenomeLocParser, Arrays.asList(files.get(1).toString()));
+        List<GenomeLoc> locs3 = IntervalUtils.parseIntervalArguments(hg18GenomeLocParser, Arrays.asList(files.get(2).toString()));
+
+        Assert.assertEquals(locs1.size(), 2);
+        Assert.assertEquals(locs2.size(), 1);
+        Assert.assertEquals(locs3.size(), 1);
+
+        Assert.assertEquals(locs1.get(0), chr1);
+        Assert.assertEquals(locs1.get(1), chr2);
+        Assert.assertEquals(locs2.get(0), chr3);
+        Assert.assertEquals(locs3.get(0), chr4);
+    }
+
+    @Test(expectedExceptions=UserException.BadInput.class)
+    public void testScatterContigIntervalsMoreFiles() {
+        List<File> files = testFiles("contig_more.", 3, ".intervals");
+        IntervalUtils.scatterContigIntervals(hg18Header, getLocs("chr1", "chr2"), files);
+    }
+
+    @Test
+    public void testScatterContigIntervalsStart() {
+        List<String> intervals = Arrays.asList("chr1:1-2", "chr1:4-5", "chr2:1-1", "chr3:2-2");
+        GenomeLoc chr1a = hg18GenomeLocParser.parseGenomeLoc("chr1:1-2");
+        GenomeLoc chr1b = hg18GenomeLocParser.parseGenomeLoc("chr1:4-5");
+        GenomeLoc chr2 = hg18GenomeLocParser.parseGenomeLoc("chr2:1-1");
+        GenomeLoc chr3 = hg18GenomeLocParser.parseGenomeLoc("chr3:2-2");
+
+        List<File> files = testFiles("contig_split_start.", 3, ".intervals");
+
+        IntervalUtils.scatterContigIntervals(hg18Header, getLocs(intervals), files);
+
+        List<GenomeLoc> locs1 = IntervalUtils.parseIntervalArguments(hg18GenomeLocParser, Arrays.asList(files.get(0).toString()));
+        List<GenomeLoc> locs2 = IntervalUtils.parseIntervalArguments(hg18GenomeLocParser, Arrays.asList(files.get(1).toString()));
+        List<GenomeLoc> locs3 = IntervalUtils.parseIntervalArguments(hg18GenomeLocParser, Arrays.asList(files.get(2).toString()));
+
+        Assert.assertEquals(locs1.size(), 2);
+        Assert.assertEquals(locs2.size(), 1);
+        Assert.assertEquals(locs3.size(), 1);
+
+        Assert.assertEquals(locs1.get(0), chr1a);
+        Assert.assertEquals(locs1.get(1), chr1b);
+        Assert.assertEquals(locs2.get(0), chr2);
+        Assert.assertEquals(locs3.get(0), chr3);
+    }
+
+    @Test
+    public void testScatterContigIntervalsMiddle() {
+        List<String> intervals = Arrays.asList("chr1:1-1", "chr2:1-2", "chr2:4-5", "chr3:2-2");
+        GenomeLoc chr1 = hg18GenomeLocParser.parseGenomeLoc("chr1:1-1");
+        GenomeLoc chr2a = hg18GenomeLocParser.parseGenomeLoc("chr2:1-2");
+        GenomeLoc chr2b = hg18GenomeLocParser.parseGenomeLoc("chr2:4-5");
+        GenomeLoc chr3 = hg18GenomeLocParser.parseGenomeLoc("chr3:2-2");
+
+        List<File> files = testFiles("contig_split_middle.", 3, ".intervals");
+
+        IntervalUtils.scatterContigIntervals(hg18Header, getLocs(intervals), files);
+
+        List<GenomeLoc> locs1 = IntervalUtils.parseIntervalArguments(hg18GenomeLocParser, Arrays.asList(files.get(0).toString()));
+        List<GenomeLoc> locs2 = IntervalUtils.parseIntervalArguments(hg18GenomeLocParser, Arrays.asList(files.get(1).toString()));
+        List<GenomeLoc> locs3 = IntervalUtils.parseIntervalArguments(hg18GenomeLocParser, Arrays.asList(files.get(2).toString()));
+
+        Assert.assertEquals(locs1.size(), 1);
+        Assert.assertEquals(locs2.size(), 2);
+        Assert.assertEquals(locs3.size(), 1);
+
+        Assert.assertEquals(locs1.get(0), chr1);
+        Assert.assertEquals(locs2.get(0), chr2a);
+        Assert.assertEquals(locs2.get(1), chr2b);
+        Assert.assertEquals(locs3.get(0), chr3);
+    }
+
+    @Test
+    public void testScatterContigIntervalsEnd() {
+        List<String> intervals = Arrays.asList("chr1:1-1", "chr2:2-2", "chr3:1-2", "chr3:4-5");
+        GenomeLoc chr1 = hg18GenomeLocParser.parseGenomeLoc("chr1:1-1");
+        GenomeLoc chr2 = hg18GenomeLocParser.parseGenomeLoc("chr2:2-2");
+        GenomeLoc chr3a = hg18GenomeLocParser.parseGenomeLoc("chr3:1-2");
+        GenomeLoc chr3b = hg18GenomeLocParser.parseGenomeLoc("chr3:4-5");
+
+        List<File> files = testFiles("contig_split_end.", 3 ,".intervals");
+
+        IntervalUtils.scatterContigIntervals(hg18Header, getLocs(intervals), files);
+
+        List<GenomeLoc> locs1 = IntervalUtils.parseIntervalArguments(hg18GenomeLocParser, Arrays.asList(files.get(0).toString()));
+        List<GenomeLoc> locs2 = IntervalUtils.parseIntervalArguments(hg18GenomeLocParser, Arrays.asList(files.get(1).toString()));
+        List<GenomeLoc> locs3 = IntervalUtils.parseIntervalArguments(hg18GenomeLocParser, Arrays.asList(files.get(2).toString()));
+
+        Assert.assertEquals(locs1.size(), 1);
+        Assert.assertEquals(locs2.size(), 1);
+        Assert.assertEquals(locs3.size(), 2);
+
+        Assert.assertEquals(locs1.get(0), chr1);
+        Assert.assertEquals(locs2.get(0), chr2);
+        Assert.assertEquals(locs3.get(0), chr3a);
+        Assert.assertEquals(locs3.get(1), chr3b);
+    }
+
+    @Test
+    public void testScatterContigIntervalsMax() {
+        List<File> files = testFiles("sg.", 85, ".intervals");
+        IntervalUtils.scatterContigIntervals(hg19Header, hg19ReferenceLocs, files);
+
+        for (int i = 0; i < files.size(); i++) {
+            String file = files.get(i).toString();
+            List<GenomeLoc> parsedLocs = IntervalUtils.parseIntervalArguments(hg19GenomeLocParser, Arrays.asList(file));
+            Assert.assertEquals(parsedLocs.size(), 1, "parsedLocs[" + i + "].size()");
+            Assert.assertEquals(parsedLocs.get(0), hg19ReferenceLocs.get(i), "parsedLocs[" + i + "].get()");
+        }
+    }
+
+    private List<File> testFiles(String prefix, int count, String suffix) {
+        ArrayList<File> files = new ArrayList<File>();
+        for (int i = 1; i <= count; i++) {
+            files.add(createTempFile(prefix + i, suffix));
+        }
+        return files;
+    }
+
+    @DataProvider(name="unmergedIntervals")
+    public Object[][] getUnmergedIntervals() {
+        return new Object[][] {
+                new Object[] {"small_unmerged_picard_intervals.list"},
+                new Object[] {"small_unmerged_gatk_intervals.list"}
+        };
+    }
+
+    @Test(dataProvider="unmergedIntervals")
+    public void testUnmergedIntervals(String unmergedIntervals) {
+        List<GenomeLoc> locs = IntervalUtils.parseIntervalArguments(hg18GenomeLocParser, Collections.singletonList(privateTestDir + unmergedIntervals));
+        Assert.assertEquals(locs.size(), 2);
+
+        List<GenomeLoc> merged;
+
+        merged = IntervalUtils.mergeIntervalLocations(locs, IntervalMergingRule.ALL);
+        Assert.assertEquals(merged.size(), 1);
+
+        // Test that null means the same as ALL
+        merged = IntervalUtils.mergeIntervalLocations(locs, null);
+        Assert.assertEquals(merged.size(), 1);
+    }
+
+    /*
+    Split into tests that can be written to files and tested by writeFlankingIntervals,
+    and lists that cannot but are still handled by getFlankingIntervals.
+    */
+    private static abstract class FlankingIntervalsTestData extends TestDataProvider {
+        final public File referenceFile;
+        final public GenomeLocParser parser;
+        final int basePairs;
+        final List<GenomeLoc> original;
+        final List<GenomeLoc> expected;
+
+        protected FlankingIntervalsTestData(Class<?> clazz, String name, File referenceFile, GenomeLocParser parser,
+                                          int basePairs, List<String> original, List<String> expected) {
+            super(clazz, name);
+            this.referenceFile = referenceFile;
+            this.parser = parser;
+            this.basePairs = basePairs;
+            this.original = parse(parser, original);
+            this.expected = parse(parser, expected);
+        }
+
+        private static List<GenomeLoc> parse(GenomeLocParser parser, List<String> locs) {
+            List<GenomeLoc> parsed = new ArrayList<GenomeLoc>();
+            for (String loc: locs)
+                parsed.add("unmapped".equals(loc) ? GenomeLoc.UNMAPPED : parser.parseGenomeLoc(loc));
+            return parsed;
+        }
+    }
+
+    private static class FlankingIntervalsFile extends FlankingIntervalsTestData {
+        public FlankingIntervalsFile(String name, File referenceFile, GenomeLocParser parser,
+                                     int basePairs, List<String> original, List<String> expected) {
+            super(FlankingIntervalsFile.class, name, referenceFile, parser, basePairs, original, expected);
+        }
+    }
+
+    private static class FlankingIntervalsList extends FlankingIntervalsTestData {
+        public FlankingIntervalsList(String name, File referenceFile, GenomeLocParser parser,
+                                     int basePairs, List<String> original, List<String> expected) {
+            super(FlankingIntervalsList.class, name, referenceFile, parser, basePairs, original, expected);
+        }
+    }
+
+    /* Intervals where the original and the flanks can be written to files. */
+    @DataProvider(name = "flankingIntervalsFiles")
+    public Object[][] getFlankingIntervalsFiles() {
+        File hg19ReferenceFile = new File(BaseTest.hg19Reference);
+        int hg19Length1 = hg19GenomeLocParser.getContigInfo("1").getSequenceLength();
+
+        new FlankingIntervalsFile("atStartBase1", hg19ReferenceFile, hg19GenomeLocParser, 1,
+                Arrays.asList("1:1"),
+                Arrays.asList("1:2"));
+
+        new FlankingIntervalsFile("atStartBase50", hg19ReferenceFile, hg19GenomeLocParser, 50,
+                Arrays.asList("1:1"),
+                Arrays.asList("1:2-51"));
+
+        new FlankingIntervalsFile("atStartRange50", hg19ReferenceFile, hg19GenomeLocParser, 50,
+                Arrays.asList("1:1-10"),
+                Arrays.asList("1:11-60"));
+
+        new FlankingIntervalsFile("atEndBase1", hg19ReferenceFile, hg19GenomeLocParser, 1,
+                Arrays.asList("1:" + hg19Length1),
+                Arrays.asList("1:" + (hg19Length1 - 1)));
+
+        new FlankingIntervalsFile("atEndBase50", hg19ReferenceFile, hg19GenomeLocParser, 50,
+                Arrays.asList("1:" + hg19Length1),
+                Arrays.asList(String.format("1:%d-%d", hg19Length1 - 50, hg19Length1 - 1)));
+
+        new FlankingIntervalsFile("atEndRange50", hg19ReferenceFile, hg19GenomeLocParser, 50,
+                Arrays.asList(String.format("1:%d-%d", hg19Length1 - 10, hg19Length1)),
+                Arrays.asList(String.format("1:%d-%d", hg19Length1 - 60, hg19Length1 - 11)));
+
+        new FlankingIntervalsFile("nearStartBase1", hg19ReferenceFile, hg19GenomeLocParser, 1,
+                Arrays.asList("1:2"),
+                Arrays.asList("1:1", "1:3"));
+
+        new FlankingIntervalsFile("nearStartRange50", hg19ReferenceFile, hg19GenomeLocParser, 50,
+                Arrays.asList("1:21-30"),
+                Arrays.asList("1:1-20", "1:31-80"));
+
+        new FlankingIntervalsFile("nearEndBase1", hg19ReferenceFile, hg19GenomeLocParser, 1,
+                Arrays.asList("1:" + (hg19Length1 - 1)),
+                Arrays.asList("1:" + (hg19Length1 - 2), "1:" + hg19Length1));
+
+        new FlankingIntervalsFile("nearEndRange50", hg19ReferenceFile, hg19GenomeLocParser, 50,
+                Arrays.asList(String.format("1:%d-%d", hg19Length1 - 30, hg19Length1 - 21)),
+                Arrays.asList(
+                        String.format("1:%d-%d", hg19Length1 - 80, hg19Length1 - 31),
+                        String.format("1:%d-%d", hg19Length1 - 20, hg19Length1)));
+
+        new FlankingIntervalsFile("beyondStartBase1", hg19ReferenceFile, hg19GenomeLocParser, 1,
+                Arrays.asList("1:3"),
+                Arrays.asList("1:2", "1:4"));
+
+        new FlankingIntervalsFile("beyondStartRange50", hg19ReferenceFile, hg19GenomeLocParser, 50,
+                Arrays.asList("1:101-200"),
+                Arrays.asList("1:51-100", "1:201-250"));
+
+        new FlankingIntervalsFile("beyondEndBase1", hg19ReferenceFile, hg19GenomeLocParser, 1,
+                Arrays.asList("1:" + (hg19Length1 - 3)),
+                Arrays.asList("1:" + (hg19Length1 - 4), "1:" + (hg19Length1 - 2)));
+
+        new FlankingIntervalsFile("beyondEndRange50", hg19ReferenceFile, hg19GenomeLocParser, 50,
+                Arrays.asList(String.format("1:%d-%d", hg19Length1 - 200, hg19Length1 - 101)),
+                Arrays.asList(
+                        String.format("1:%d-%d", hg19Length1 - 250, hg19Length1 - 201),
+                        String.format("1:%d-%d", hg19Length1 - 100, hg19Length1 - 51)));
+
+        new FlankingIntervalsFile("betweenFar50", hg19ReferenceFile, hg19GenomeLocParser, 50,
+                Arrays.asList("1:101-200", "1:401-500"),
+                Arrays.asList("1:51-100", "1:201-250", "1:351-400", "1:501-550"));
+
+        new FlankingIntervalsFile("betweenSpan50", hg19ReferenceFile, hg19GenomeLocParser, 50,
+                Arrays.asList("1:101-200", "1:301-400"),
+                Arrays.asList("1:51-100", "1:201-300", "1:401-450"));
+
+        new FlankingIntervalsFile("betweenOverlap50", hg19ReferenceFile, hg19GenomeLocParser, 50,
+                Arrays.asList("1:101-200", "1:271-400"),
+                Arrays.asList("1:51-100", "1:201-270", "1:401-450"));
+
+        new FlankingIntervalsFile("betweenShort50", hg19ReferenceFile, hg19GenomeLocParser, 50,
+                Arrays.asList("1:101-200", "1:221-400"),
+                Arrays.asList("1:51-100", "1:201-220", "1:401-450"));
+
+        new FlankingIntervalsFile("betweenNone50", hg19ReferenceFile, hg19GenomeLocParser, 50,
+                Arrays.asList("1:101-200", "1:121-400"),
+                Arrays.asList("1:51-100", "1:401-450"));
+
+        new FlankingIntervalsFile("twoContigs", hg19ReferenceFile, hg19GenomeLocParser, 50,
+                Arrays.asList("1:101-200", "2:301-400"),
+                Arrays.asList("1:51-100", "1:201-250", "2:251-300", "2:401-450"));
+
+        // Explicit testing a problematic agilent target pair
+        new FlankingIntervalsFile("badAgilent", hg19ReferenceFile, hg19GenomeLocParser, 50,
+                Arrays.asList("2:74756257-74756411", "2:74756487-74756628"),
+                // wrong!    ("2:74756206-74756256", "2:74756412-74756462", "2:74756436-74756486", "2:74756629-74756679")
+                Arrays.asList("2:74756207-74756256", "2:74756412-74756486", "2:74756629-74756678"));
+
+        return TestDataProvider.getTests(FlankingIntervalsFile.class);
+    }
+
+    /* Intervals where either the original and/or the flanks cannot be written to a file. */
+    @DataProvider(name = "flankingIntervalsLists")
+    public Object[][] getFlankingIntervalsLists() {
+        File hg19ReferenceFile = new File(BaseTest.hg19Reference);
+        List<String> empty = Collections.emptyList();
+
+        new FlankingIntervalsList("empty", hg19ReferenceFile, hg19GenomeLocParser, 50,
+                empty,
+                empty);
+
+        new FlankingIntervalsList("unmapped", hg19ReferenceFile, hg19GenomeLocParser, 50,
+                Arrays.asList("unmapped"),
+                empty);
+
+        new FlankingIntervalsList("fullContig", hg19ReferenceFile, hg19GenomeLocParser, 50,
+                Arrays.asList("1"),
+                empty);
+
+        new FlankingIntervalsList("fullContigs", hg19ReferenceFile, hg19GenomeLocParser, 50,
+                Arrays.asList("1", "2", "3"),
+                empty);
+
+        new FlankingIntervalsList("betweenWithUnmapped", hg19ReferenceFile, hg19GenomeLocParser, 50,
+                Arrays.asList("1:101-200", "1:301-400", "unmapped"),
+                Arrays.asList("1:51-100", "1:201-300", "1:401-450"));
+
+        return TestDataProvider.getTests(FlankingIntervalsList.class);
+    }
+
+    @Test(dataProvider = "flankingIntervalsFiles")
+    public void testWriteFlankingIntervals(FlankingIntervalsTestData data) throws Exception {
+        File originalFile = createTempFile("original.", ".intervals");
+        File flankingFile = createTempFile("flanking.", ".intervals");
+        try {
+            List<String> lines = new ArrayList<String>();
+            for (GenomeLoc loc: data.original)
+                lines.add(loc.toString());
+            FileUtils.writeLines(originalFile, lines);
+
+            IntervalUtils.writeFlankingIntervals(data.referenceFile, originalFile, flankingFile, data.basePairs);
+
+            List<GenomeLoc> actual = IntervalUtils.intervalFileToList(data.parser, flankingFile.getAbsolutePath());
+
+            String description = String.format("%n      name: %s%n  original: %s%n    actual: %s%n  expected: %s%n",
+                    data.toString(), data.original, actual, data.expected);
+            Assert.assertEquals(actual, data.expected, description);
+        } finally {
+            FileUtils.deleteQuietly(originalFile);
+            FileUtils.deleteQuietly(flankingFile);
+        }
+    }
+
+    @Test(dataProvider = "flankingIntervalsLists", expectedExceptions = UserException.class)
+    public void testWritingBadFlankingIntervals(FlankingIntervalsTestData data) throws Exception {
+        File originalFile = createTempFile("original.", ".intervals");
+        File flankingFile = createTempFile("flanking.", ".intervals");
+        try {
+            List<String> lines = new ArrayList<String>();
+            for (GenomeLoc loc: data.original)
+                lines.add(loc.toString());
+            FileUtils.writeLines(originalFile, lines);
+
+            // Should throw a user exception on bad input if either the original
+            // intervals are empty or if the flanking intervals are empty
+            IntervalUtils.writeFlankingIntervals(data.referenceFile, originalFile, flankingFile, data.basePairs);
+        } finally {
+            FileUtils.deleteQuietly(originalFile);
+            FileUtils.deleteQuietly(flankingFile);
+        }
+    }
+
+    @Test(dataProvider = "flankingIntervalsLists")
+    public void testGetFlankingIntervals(FlankingIntervalsTestData data) {
+        List<GenomeLoc> actual = IntervalUtils.getFlankingIntervals(data.parser, data.original, data.basePairs);
+        String description = String.format("%n      name: %s%n  original: %s%n    actual: %s%n  expected: %s%n",
+                data.toString(), data.original, actual, data.expected);
+        Assert.assertEquals(actual, data.expected, description);
+    }
+
+    @Test(expectedExceptions=UserException.BadArgumentValue.class)
+    public void testExceptionUponLegacyIntervalSyntax() throws Exception {
+        GenomeAnalysisEngine toolkit = new GenomeAnalysisEngine();
+        toolkit.setGenomeLocParser(new GenomeLocParser(new CachingIndexedFastaSequenceFile(new File(BaseTest.hg19Reference))));
+
+        // Attempting to use the legacy -L "interval1;interval2" syntax should produce an exception:
+        IntervalBinding<Feature> binding = new IntervalBinding<Feature>("1;2");
+        binding.getIntervals(toolkit);
+    }
+
+    @DataProvider(name="invalidIntervalTestData")
+    public Object[][] invalidIntervalDataProvider() throws Exception {
+        GATKArgumentCollection argCollection = new GATKArgumentCollection();
+        File fastaFile = new File(publicTestDir + "exampleFASTA.fasta");
+        GenomeLocParser genomeLocParser = new GenomeLocParser(new IndexedFastaSequenceFile(fastaFile));
+
+        return new Object[][] {
+                new Object[] {argCollection, genomeLocParser, "chr1", 10000000, 20000000},
+                new Object[] {argCollection, genomeLocParser, "chr2", 1, 2},
+                new Object[] {argCollection, genomeLocParser, "chr1", -1, 50}
+        };
+    }
+
+    @Test(dataProvider="invalidIntervalTestData")
+    public void testInvalidPicardIntervalHandling(GATKArgumentCollection argCollection, GenomeLocParser genomeLocParser,
+                                                  String contig, int intervalStart, int intervalEnd ) throws Exception {
+
+        SAMFileHeader picardFileHeader = new SAMFileHeader();
+        picardFileHeader.addSequence(genomeLocParser.getContigInfo("chr1"));
+        IntervalList picardIntervals = new IntervalList(picardFileHeader);
+        picardIntervals.add(new Interval(contig, intervalStart, intervalEnd, true, "dummyname"));
+
+        File picardIntervalFile = createTempFile("testInvalidPicardIntervalHandling", ".intervals");
+        picardIntervals.write(picardIntervalFile);
+
+        List<IntervalBinding<Feature>> intervalArgs = new ArrayList<IntervalBinding<Feature>>(1);
+        intervalArgs.add(new IntervalBinding<Feature>(picardIntervalFile.getAbsolutePath()));
+
+        IntervalUtils.loadIntervals(intervalArgs, argCollection.intervalArguments.intervalSetRule, argCollection.intervalArguments.intervalMerging, argCollection.intervalArguments.intervalPadding, genomeLocParser);
+    }
+
+    @Test(expectedExceptions=UserException.class, dataProvider="invalidIntervalTestData")
+    public void testInvalidGATKFileIntervalHandling(GATKArgumentCollection argCollection, GenomeLocParser genomeLocParser,
+                                                    String contig, int intervalStart, int intervalEnd ) throws Exception {
+
+        File gatkIntervalFile = createTempFile("testInvalidGATKFileIntervalHandling", ".intervals",
+                String.format("%s:%d-%d", contig, intervalStart, intervalEnd));
+
+        List<IntervalBinding<Feature>> intervalArgs = new ArrayList<IntervalBinding<Feature>>(1);
+        intervalArgs.add(new IntervalBinding<Feature>(gatkIntervalFile.getAbsolutePath()));
+
+        IntervalUtils.loadIntervals(intervalArgs, argCollection.intervalArguments.intervalSetRule, argCollection.intervalArguments.intervalMerging, argCollection.intervalArguments.intervalPadding, genomeLocParser);
+    }
+
+    private File createTempFile( String tempFilePrefix, String tempFileExtension, String... lines ) throws Exception {
+        File tempFile = BaseTest.createTempFile(tempFilePrefix, tempFileExtension);
+        FileUtils.writeLines(tempFile, Arrays.asList(lines));
+        return tempFile;
+    }
+
+    @DataProvider(name = "sortAndMergeIntervals")
+    public Object[][] getSortAndMergeIntervals() {
+        return new Object[][] {
+                new Object[] { IntervalMergingRule.OVERLAPPING_ONLY, getLocs("chr1:1", "chr1:3", "chr1:2"), getLocs("chr1:1", "chr1:2", "chr1:3") },
+                new Object[] { IntervalMergingRule.ALL, getLocs("chr1:1", "chr1:3", "chr1:2"), getLocs("chr1:1-3") },
+                new Object[] { IntervalMergingRule.OVERLAPPING_ONLY, getLocs("chr1:1", "chr1:3", "chr2:2"), getLocs("chr1:1", "chr1:3", "chr2:2") },
+                new Object[] { IntervalMergingRule.ALL, getLocs("chr1:1", "chr1:3", "chr2:2"), getLocs("chr1:1", "chr1:3", "chr2:2") },
+                new Object[] { IntervalMergingRule.OVERLAPPING_ONLY, getLocs("chr1:1", "chr1"), getLocs("chr1") },
+                new Object[] { IntervalMergingRule.ALL, getLocs("chr1:1", "chr1"), getLocs("chr1") }
+        };
+    }
+
+    @Test(dataProvider = "sortAndMergeIntervals")
+    public void testSortAndMergeIntervals(IntervalMergingRule merge, List<GenomeLoc> unsorted, List<GenomeLoc> expected) {
+        List<GenomeLoc> sorted = IntervalUtils.sortAndMergeIntervals(hg18GenomeLocParser, unsorted, merge).toList();
+        Assert.assertEquals(sorted, expected);
+    }
+}
diff --git a/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/utils/io/IOUtilsUnitTest.java b/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/utils/io/IOUtilsUnitTest.java
new file mode 100644
index 0000000..13a2e8a
--- /dev/null
+++ b/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/utils/io/IOUtilsUnitTest.java
@@ -0,0 +1,326 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.utils.io;
+
+import org.apache.commons.io.FileUtils;
+import org.broadinstitute.gatk.utils.BaseTest;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.util.Arrays;
+import java.util.List;
+import java.util.Random;
+
+import org.broadinstitute.gatk.engine.GenomeAnalysisEngine;
+import org.broadinstitute.gatk.utils.exceptions.ReviewedGATKException;
+import org.broadinstitute.gatk.utils.exceptions.UserException;
+import org.testng.Assert;
+import org.testng.annotations.DataProvider;
+import org.testng.annotations.Test;
+
+public class IOUtilsUnitTest extends BaseTest {
+  @Test
+  public void testGoodTempDir() {
+    IOUtils.checkTempDir(new File("/tmp/queue"));
+  }
+
+  @Test(expectedExceptions=UserException.BadTmpDir.class)
+  public void testBadTempDir() {
+    IOUtils.checkTempDir(new File("/tmp"));
+  }
+
+  @Test
+  public void testAbsoluteSubDir() {
+    File subDir = IOUtils.absolute(new File("."), new File("/path/to/file"));
+    Assert.assertEquals(subDir, new File("/path/to/file"));
+
+    subDir = IOUtils.absolute(new File("/different/path"), new File("/path/to/file"));
+    Assert.assertEquals(subDir, new File("/path/to/file"));
+
+    subDir = IOUtils.absolute(new File("/different/path"), new File("."));
+    Assert.assertEquals(subDir, new File("/different/path"));
+  }
+
+  @Test
+  public void testRelativeSubDir() throws IOException {
+    File subDir = IOUtils.absolute(new File("."), new File("path/to/file"));
+    Assert.assertEquals(subDir.getCanonicalFile(), new File("path/to/file").getCanonicalFile());
+
+    subDir = IOUtils.absolute(new File("/different/path"), new File("path/to/file"));
+    Assert.assertEquals(subDir, new File("/different/path/path/to/file"));
+  }
+
+  @Test
+  public void testDottedSubDir() throws IOException {
+    File subDir = IOUtils.absolute(new File("."), new File("path/../to/file"));
+    Assert.assertEquals(subDir.getCanonicalFile(), new File("path/../to/./file").getCanonicalFile());
+
+    subDir = IOUtils.absolute(new File("."), new File("/path/../to/file"));
+    Assert.assertEquals(subDir, new File("/path/../to/file"));
+
+    subDir = IOUtils.absolute(new File("/different/../path"), new File("path/to/file"));
+    Assert.assertEquals(subDir, new File("/different/../path/path/to/file"));
+
+    subDir = IOUtils.absolute(new File("/different/./path"), new File("/path/../to/file"));
+    Assert.assertEquals(subDir, new File("/path/../to/file"));
+  }
+
+  @Test
+  public void testTempDir() {
+    File tempDir = IOUtils.tempDir("Q-Unit-Test", "", new File("queueTempDirToDelete"));
+    Assert.assertTrue(tempDir.exists());
+    Assert.assertFalse(tempDir.isFile());
+    Assert.assertTrue(tempDir.isDirectory());
+    boolean deleted = IOUtils.tryDelete(tempDir);
+    Assert.assertTrue(deleted);
+    Assert.assertFalse(tempDir.exists());
+  }
+
+  @Test
+  public void testDirLevel() {
+    File dir = IOUtils.dirLevel(new File("/path/to/directory"), 1);
+    Assert.assertEquals(dir, new File("/path"));
+
+    dir = IOUtils.dirLevel(new File("/path/to/directory"), 2);
+    Assert.assertEquals(dir, new File("/path/to"));
+
+    dir = IOUtils.dirLevel(new File("/path/to/directory"), 3);
+    Assert.assertEquals(dir, new File("/path/to/directory"));
+
+    dir = IOUtils.dirLevel(new File("/path/to/directory"), 4);
+    Assert.assertEquals(dir, new File("/path/to/directory"));
+  }
+
+  @Test
+  public void testAbsolute() {
+    File dir = IOUtils.absolute(new File("/path/./to/./directory/."));
+    Assert.assertEquals(dir, new File("/path/to/directory"));
+
+    dir = IOUtils.absolute(new File("/"));
+    Assert.assertEquals(dir, new File("/"));
+
+    dir = IOUtils.absolute(new File("/."));
+    Assert.assertEquals(dir, new File("/"));
+
+    dir = IOUtils.absolute(new File("/././."));
+    Assert.assertEquals(dir, new File("/"));
+
+    dir = IOUtils.absolute(new File("/./directory/."));
+    Assert.assertEquals(dir, new File("/directory"));
+
+    dir = IOUtils.absolute(new File("/./directory/./"));
+    Assert.assertEquals(dir, new File("/directory"));
+
+    dir = IOUtils.absolute(new File("/./directory./"));
+    Assert.assertEquals(dir, new File("/directory."));
+
+    dir = IOUtils.absolute(new File("/./.directory/"));
+    Assert.assertEquals(dir, new File("/.directory"));
+  }
+
+  @Test
+  public void testTail() throws IOException {
+    List<String> lines = Arrays.asList(
+            "chr18_random	4262	3154410390	50	51",
+            "chr19_random	301858	3154414752	50	51",
+            "chr21_random	1679693	3154722662	50	51",
+            "chr22_random	257318	3156435963	50	51",
+            "chrX_random	1719168	3156698441	50	51");
+    List<String> tail = IOUtils.tail(new File(BaseTest.hg18Reference + ".fai"), 5);
+    Assert.assertEquals(tail.size(), 5);
+    for (int i = 0; i < 5; i++)
+      Assert.assertEquals(tail.get(i), lines.get(i));
+  }
+
+    @Test
+    public void testWriteSystemFile() throws IOException {
+        File temp = createTempFile("temp.", ".properties");
+        try {
+            IOUtils.writeResource(new Resource("testProperties.properties", null), temp);
+        } finally {
+            FileUtils.deleteQuietly(temp);
+        }
+    }
+
+    @Test
+    public void testWriteSystemTempFile() throws IOException {
+        File temp = IOUtils.writeTempResource(new Resource("testProperties.properties", null));
+        try {
+            Assert.assertTrue(temp.getName().startsWith("testProperties"), "File does not start with 'testProperties.': " + temp);
+            Assert.assertTrue(temp.getName().endsWith(".properties"), "File does not end with '.properties': " + temp);
+        } finally {
+            FileUtils.deleteQuietly(temp);
+        }
+    }
+
+    @Test(expectedExceptions = IllegalArgumentException.class)
+    public void testMissingSystemFile() throws IOException {
+        File temp = createTempFile("temp.", ".properties");
+        try {
+            IOUtils.writeResource(new Resource("MissingStingText.properties", null), temp);
+        } finally {
+            FileUtils.deleteQuietly(temp);
+        }
+    }
+
+    @Test
+    public void testWriteRelativeFile() throws IOException {
+        File temp = createTempFile("temp.", ".properties");
+        try {
+            IOUtils.writeResource(new Resource("/testProperties.properties", IOUtils.class), temp);
+        } finally {
+            FileUtils.deleteQuietly(temp);
+        }
+    }
+
+    @Test
+    public void testWriteRelativeTempFile() throws IOException {
+        File temp = IOUtils.writeTempResource(new Resource("/testProperties.properties", IOUtils.class));
+        try {
+            Assert.assertTrue(temp.getName().startsWith("testProperties"), "File does not start with 'testProperties.': " + temp);
+            Assert.assertTrue(temp.getName().endsWith(".properties"), "File does not end with '.properties': " + temp);
+        } finally {
+            FileUtils.deleteQuietly(temp);
+        }
+    }
+
+    @Test(expectedExceptions = IllegalArgumentException.class)
+    public void testMissingRelativeFile() throws IOException {
+        File temp = createTempFile("temp.", ".properties");
+        try {
+            // Looking for /org/broadinstitute/gatk/utils/file/GATKText.properties
+            IOUtils.writeResource(new Resource("GATKText.properties", IOUtils.class), temp);
+        } finally {
+            FileUtils.deleteQuietly(temp);
+        }
+    }
+
+    @Test
+    public void testResourceProperties() {
+        Resource resource = new Resource("foo", Resource.class);
+        Assert.assertEquals(resource.getPath(), "foo");
+        Assert.assertEquals(resource.getRelativeClass(), Resource.class);
+    }
+
+    @Test
+    public void testIsSpecialFile() {
+        Assert.assertTrue(IOUtils.isSpecialFile(new File("/dev")));
+        Assert.assertTrue(IOUtils.isSpecialFile(new File("/dev/null")));
+        Assert.assertTrue(IOUtils.isSpecialFile(new File("/dev/full")));
+        Assert.assertTrue(IOUtils.isSpecialFile(new File("/dev/stdout")));
+        Assert.assertTrue(IOUtils.isSpecialFile(new File("/dev/stderr")));
+        Assert.assertFalse(IOUtils.isSpecialFile(null));
+        Assert.assertFalse(IOUtils.isSpecialFile(new File("/home/user/my.file")));
+        Assert.assertFalse(IOUtils.isSpecialFile(new File("/devfake/null")));
+    }
+
+    @DataProvider( name = "ByteArrayIOTestData")
+    public Object[][] byteArrayIOTestDataProvider() {
+        return new Object[][] {
+            // file size, read buffer size
+            { 0,     4096 },
+            { 1,     4096 },
+            { 2000,  4096 },
+            { 4095,  4096 },
+            { 4096,  4096 },
+            { 4097,  4096 },
+            { 6000,  4096 },
+            { 8191,  4096 },
+            { 8192,  4096 },
+            { 8193,  4096 },
+            { 10000, 4096 }
+        };
+    }
+
+    @Test( dataProvider = "ByteArrayIOTestData" )
+    public void testWriteThenReadFileIntoByteArray ( int fileSize, int readBufferSize ) throws Exception {
+        File tempFile = createTempFile(String.format("testWriteThenReadFileIntoByteArray_%d_%d", fileSize, readBufferSize), "tmp");
+
+        byte[] dataWritten = getDeterministicRandomData(fileSize);
+        IOUtils.writeByteArrayToFile(dataWritten, tempFile);
+        byte[] dataRead = IOUtils.readFileIntoByteArray(tempFile, readBufferSize);
+
+        Assert.assertEquals(dataRead.length, dataWritten.length);
+        Assert.assertTrue(Arrays.equals(dataRead, dataWritten));
+    }
+
+    @Test( dataProvider = "ByteArrayIOTestData" )
+    public void testWriteThenReadStreamIntoByteArray ( int fileSize, int readBufferSize ) throws Exception {
+        File tempFile = createTempFile(String.format("testWriteThenReadStreamIntoByteArray_%d_%d", fileSize, readBufferSize), "tmp");
+
+        byte[] dataWritten = getDeterministicRandomData(fileSize);
+        IOUtils.writeByteArrayToStream(dataWritten, new FileOutputStream(tempFile));
+        byte[] dataRead = IOUtils.readStreamIntoByteArray(new FileInputStream(tempFile), readBufferSize);
+
+        Assert.assertEquals(dataRead.length, dataWritten.length);
+        Assert.assertTrue(Arrays.equals(dataRead, dataWritten));
+    }
+
+    @Test( expectedExceptions = UserException.CouldNotReadInputFile.class )
+    public void testReadNonExistentFileIntoByteArray() {
+        File nonExistentFile = new File("djfhsdkjghdfk");
+        Assert.assertFalse(nonExistentFile.exists());
+
+        IOUtils.readFileIntoByteArray(nonExistentFile);
+    }
+
+    @Test( expectedExceptions = ReviewedGATKException.class )
+    public void testReadNullStreamIntoByteArray() {
+        IOUtils.readStreamIntoByteArray(null);
+    }
+
+    @Test( expectedExceptions = ReviewedGATKException.class )
+    public void testReadStreamIntoByteArrayInvalidBufferSize() throws Exception {
+        IOUtils.readStreamIntoByteArray(new FileInputStream(createTempFile("testReadStreamIntoByteArrayInvalidBufferSize", "tmp")),
+                                        -1);
+    }
+
+    @Test( expectedExceptions = UserException.CouldNotCreateOutputFile.class )
+    public void testWriteByteArrayToUncreatableFile() {
+        IOUtils.writeByteArrayToFile(new byte[]{0}, new File("/dev/foo/bar"));
+    }
+
+    @Test( expectedExceptions = ReviewedGATKException.class )
+    public void testWriteNullByteArrayToFile() {
+        IOUtils.writeByteArrayToFile(null, createTempFile("testWriteNullByteArrayToFile", "tmp"));
+    }
+
+    @Test( expectedExceptions = ReviewedGATKException.class )
+    public void testWriteByteArrayToNullStream() {
+        IOUtils.writeByteArrayToStream(new byte[]{0}, null);
+    }
+
+    private byte[] getDeterministicRandomData ( int size ) {
+        GenomeAnalysisEngine.resetRandomGenerator();
+        Random rand = GenomeAnalysisEngine.getRandomGenerator();
+
+        byte[] randomData = new byte[size];
+        rand.nextBytes(randomData);
+
+        return randomData;
+    }
+}
diff --git a/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/utils/jna/clibrary/LibCUnitTest.java b/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/utils/jna/clibrary/LibCUnitTest.java
new file mode 100644
index 0000000..f695d89
--- /dev/null
+++ b/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/utils/jna/clibrary/LibCUnitTest.java
@@ -0,0 +1,70 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.utils.jna.clibrary;
+
+import com.sun.jna.NativeLong;
+import com.sun.jna.ptr.NativeLongByReference;
+import org.broadinstitute.gatk.utils.BaseTest;
+import org.testng.Assert;
+import org.testng.annotations.Test;
+
+public class LibCUnitTest extends BaseTest {
+
+    @Test
+    public void testEnvironment() {
+        String testProperty = "test_property";
+        String testValue = "value";
+        Assert.assertEquals(LibC.getenv(testProperty), null);
+        Assert.assertEquals(LibC.setenv(testProperty, testValue, 1), 0);
+        Assert.assertEquals(LibC.getenv(testProperty), testValue);
+        Assert.assertEquals(LibC.unsetenv(testProperty), 0);
+        Assert.assertEquals(LibC.getenv(testProperty), null);
+    }
+
+    @Test
+    public void testDifftime() throws Exception {
+        // Pointer to hold the times
+        NativeLongByReference ref = new NativeLongByReference();
+
+        // time() returns -1 on error.
+        NativeLong err = new NativeLong(-1L);
+
+        LibC.time(ref);
+        NativeLong time0 = ref.getValue();
+        Assert.assertNotSame(time0, err, "Time 0 returned an error (-1).");
+
+        Thread.sleep(5000L);
+
+        LibC.time(ref);
+        NativeLong time1 = ref.getValue();
+        Assert.assertNotSame(time1, err, "Time 1 returned an error (-1).");
+
+        Assert.assertNotSame(time1, time0, "Time 1 returned same time as Time 0.");
+
+        double diff = LibC.difftime(time1, time0);
+        Assert.assertTrue(diff >= 5, "Time difference was not greater than 5 seconds: " + diff);
+    }
+}
diff --git a/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/utils/jna/drmaa/v1_0/JnaSessionQueueTest.java b/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/utils/jna/drmaa/v1_0/JnaSessionQueueTest.java
new file mode 100644
index 0000000..e683f4b
--- /dev/null
+++ b/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/utils/jna/drmaa/v1_0/JnaSessionQueueTest.java
@@ -0,0 +1,165 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.utils.jna.drmaa.v1_0;
+
+import org.apache.commons.io.FileUtils;
+import org.broadinstitute.gatk.utils.BaseTest;
+import org.ggf.drmaa.*;
+import org.testng.Assert;
+import org.testng.SkipException;
+import org.testng.annotations.Test;
+
+import java.io.File;
+import java.util.*;
+
+public class JnaSessionQueueTest extends BaseTest {
+    private String implementation = null;
+    private static final SessionFactory factory = new JnaSessionFactory();
+
+    @Test
+    public void testDrmaa() throws Exception {
+        Session session = factory.getSession();
+        Version version = session.getVersion();
+        System.out.println(String.format("DRMAA version: %d.%d", version.getMajor(), version.getMinor()));
+        System.out.println(String.format("DRMAA contact(s): %s", session.getContact()));
+        System.out.println(String.format("DRM system(s): %s", session.getDrmSystem()));
+        System.out.println(String.format("DRMAA implementation(s): %s", session.getDrmaaImplementation()));
+        this.implementation = session.getDrmaaImplementation();
+    }
+
+    @Test(dependsOnMethods = { "testDrmaa" })
+    public void testSubmitEcho() throws Exception {
+        if ( ! queueTestRunModeIsSet ) {
+            throw new SkipException("Skipping testSubmitEcho because we are in queue test dry run mode");
+        }
+
+        if (implementation.contains("LSF")) {
+            System.err.println("    ***********************************************************");
+            System.err.println("   *************************************************************");
+            System.err.println("   ****                                                     ****");
+            System.err.println("  ****  Skipping JnaSessionQueueTest.testSubmitEcho()        ****");
+            System.err.println("  ****      Are you using the dotkit .combined_LSF_SGE?      ****");
+            System.err.println("   ****                                                     ****");
+            System.err.println("   *************************************************************");
+            System.err.println("    ***********************************************************");
+            throw new SkipException("Skipping testSubmitEcho because correct DRMAA implementation not found");
+        }
+
+        File outFile = tryCreateNetworkTempFile("JnaSessionQueueTest.out");
+        Session session = factory.getSession();
+        session.init(null);
+        try {
+            JobTemplate template = session.createJobTemplate();
+            template.setRemoteCommand("sh");
+            template.setOutputPath(":" + outFile.getAbsolutePath());
+            template.setJoinFiles(true);
+            template.setArgs(Arrays.asList("-c", "echo \"Hello world.\""));
+
+            String jobId = session.runJob(template);
+            System.out.println(String.format("Job id %s", jobId));
+            session.deleteJobTemplate(template);
+
+            System.out.println("Waiting for job to run: " + jobId);
+            int remotePs = Session.QUEUED_ACTIVE;
+
+            List<Integer> runningStatuses = Arrays.asList(Session.QUEUED_ACTIVE, Session.RUNNING);
+
+            while (runningStatuses.contains(remotePs)) {
+                Thread.sleep(30 * 1000L);
+                remotePs = session.getJobProgramStatus(jobId);
+            }
+
+            Assert.assertEquals(remotePs, Session.DONE, "Job status is not DONE.");
+
+            JobInfo jobInfo = session.wait(jobId, Session.TIMEOUT_NO_WAIT);
+
+            Assert.assertTrue(jobInfo.hasExited(), String.format("Job did not exit cleanly: %s", jobId));
+            Assert.assertEquals(jobInfo.getExitStatus(), 0, String.format("Exit status for jobId %s is non-zero", jobId));
+            if (jobInfo.hasSignaled())
+                Assert.fail(String.format("JobId %s exited with signal %s and core dump flag %s", jobId, jobInfo.getTerminatingSignal(), jobInfo.hasCoreDump()));
+            Assert.assertFalse(jobInfo.wasAborted(), String.format("Job was aborted: %s", jobId));
+        } finally {
+            session.exit();
+        }
+
+        Assert.assertTrue(FileUtils.waitFor(outFile, 120), "File not found: " + outFile.getAbsolutePath());
+        System.out.println("--- output ---");
+        System.out.println(FileUtils.readFileToString(outFile));
+        System.out.println("--- output ---");
+        Assert.assertTrue(outFile.delete(), "Unable to delete " + outFile.getAbsolutePath());
+        System.out.println("Validating that we reached the end of the test without exit.");
+    }
+
+    @Test
+    public void testCollectionConversions() {
+        Collection<String> list = Arrays.asList("a=1", "foo=bar", "empty=");
+        Map<String, String> map = new LinkedHashMap<String, String>();
+        map.put("a", "1");
+        map.put("foo", "bar");
+        map.put("empty", "");
+
+        Assert.assertEquals(JnaSession.collectionToMap(list), map);
+        Assert.assertEquals(JnaSession.mapToCollection(map), list);
+    }
+
+    @Test
+    public void testLimitConversions() {
+        Assert.assertEquals(JnaSession.formatLimit(0), "0:00:00");
+        Assert.assertEquals(JnaSession.formatLimit(59), "0:00:59");
+        Assert.assertEquals(JnaSession.formatLimit(60), "0:01:00");
+        Assert.assertEquals(JnaSession.formatLimit(3540), "0:59:00");
+        Assert.assertEquals(JnaSession.formatLimit(3599), "0:59:59");
+        Assert.assertEquals(JnaSession.formatLimit(7200), "2:00:00");
+        Assert.assertEquals(JnaSession.formatLimit(7260), "2:01:00");
+        Assert.assertEquals(JnaSession.formatLimit(7261), "2:01:01");
+
+        Assert.assertEquals(JnaSession.parseLimit("0"), 0);
+        Assert.assertEquals(JnaSession.parseLimit("00"), 0);
+        Assert.assertEquals(JnaSession.parseLimit("0:00"), 0);
+        Assert.assertEquals(JnaSession.parseLimit("00:00"), 0);
+        Assert.assertEquals(JnaSession.parseLimit("0:00:00"), 0);
+
+        Assert.assertEquals(JnaSession.parseLimit("1"), 1);
+        Assert.assertEquals(JnaSession.parseLimit("01"), 1);
+        Assert.assertEquals(JnaSession.parseLimit("0:01"), 1);
+        Assert.assertEquals(JnaSession.parseLimit("00:01"), 1);
+        Assert.assertEquals(JnaSession.parseLimit("0:00:01"), 1);
+
+        Assert.assertEquals(JnaSession.parseLimit("10"), 10);
+        Assert.assertEquals(JnaSession.parseLimit("0:10"), 10);
+        Assert.assertEquals(JnaSession.parseLimit("00:10"), 10);
+        Assert.assertEquals(JnaSession.parseLimit("0:00:10"), 10);
+
+        Assert.assertEquals(JnaSession.parseLimit("1:0"), 60);
+        Assert.assertEquals(JnaSession.parseLimit("1:00"), 60);
+        Assert.assertEquals(JnaSession.parseLimit("01:00"), 60);
+        Assert.assertEquals(JnaSession.parseLimit("0:01:00"), 60);
+
+        Assert.assertEquals(JnaSession.parseLimit("1:00:00"), 3600);
+
+        Assert.assertEquals(JnaSession.parseLimit("1:02:03"), 3723);
+    }
+}
diff --git a/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/utils/jna/drmaa/v1_0/LibDrmaaQueueTest.java b/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/utils/jna/drmaa/v1_0/LibDrmaaQueueTest.java
new file mode 100644
index 0000000..accc0fe
--- /dev/null
+++ b/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/utils/jna/drmaa/v1_0/LibDrmaaQueueTest.java
@@ -0,0 +1,257 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.utils.jna.drmaa.v1_0;
+
+import com.sun.jna.Memory;
+import com.sun.jna.NativeLong;
+import com.sun.jna.Pointer;
+import com.sun.jna.StringArray;
+import com.sun.jna.ptr.IntByReference;
+import com.sun.jna.ptr.PointerByReference;
+import org.apache.commons.io.FileUtils;
+import org.broadinstitute.gatk.utils.BaseTest;
+import org.testng.Assert;
+import org.testng.SkipException;
+import org.testng.annotations.Test;
+
+import java.io.File;
+import java.util.Arrays;
+import java.util.List;
+
+public class LibDrmaaQueueTest extends BaseTest {
+    private String implementation = null;
+
+    @Test
+    public void testDrmaa() throws Exception {
+        Memory error = new Memory(LibDrmaa.DRMAA_ERROR_STRING_BUFFER);
+        int errnum;
+
+        IntByReference major = new IntByReference();
+        IntByReference minor = new IntByReference();
+        Memory contact = new Memory(LibDrmaa.DRMAA_CONTACT_BUFFER);
+        Memory drmSystem = new Memory(LibDrmaa.DRMAA_DRM_SYSTEM_BUFFER);
+        Memory drmaaImplementation = new Memory(LibDrmaa.DRMAA_DRMAA_IMPLEMENTATION_BUFFER);
+
+        errnum = LibDrmaa.drmaa_version(major, minor, error, LibDrmaa.DRMAA_ERROR_STRING_BUFFER_LEN);
+
+        if (errnum != LibDrmaa.DRMAA_ERRNO.DRMAA_ERRNO_SUCCESS)
+            Assert.fail(String.format("Could not get version from the DRMAA library: %s", error.getString(0)));
+
+        System.out.println(String.format("DRMAA version: %d.%d", major.getValue(), minor.getValue()));
+
+        errnum = LibDrmaa.drmaa_get_contact(contact, LibDrmaa.DRMAA_CONTACT_BUFFER_LEN, error, LibDrmaa.DRMAA_ERROR_STRING_BUFFER_LEN);
+
+        if (errnum != LibDrmaa.DRMAA_ERRNO.DRMAA_ERRNO_SUCCESS)
+            Assert.fail(String.format("Could not get contacts from the DRMAA library: %s", error.getString(0)));
+
+        System.out.println(String.format("DRMAA contact(s): %s", contact.getString(0)));
+
+        errnum = LibDrmaa.drmaa_get_DRM_system(drmSystem, LibDrmaa.DRMAA_DRM_SYSTEM_BUFFER_LEN, error, LibDrmaa.DRMAA_ERROR_STRING_BUFFER_LEN);
+
+        if (errnum != LibDrmaa.DRMAA_ERRNO.DRMAA_ERRNO_SUCCESS)
+            Assert.fail(String.format("Could not get DRM system from the DRMAA library: %s", error.getString(0)));
+
+        System.out.println(String.format("DRM system(s): %s", drmSystem.getString(0)));
+
+        errnum = LibDrmaa.drmaa_get_DRMAA_implementation(drmaaImplementation, LibDrmaa.DRMAA_DRMAA_IMPLEMENTATION_BUFFER_LEN, error, LibDrmaa.DRMAA_ERROR_STRING_BUFFER_LEN);
+
+        if (errnum != LibDrmaa.DRMAA_ERRNO.DRMAA_ERRNO_SUCCESS)
+            Assert.fail(String.format("Could not get DRMAA implementation from the DRMAA library: %s", error.getString(0)));
+
+        System.out.println(String.format("DRMAA implementation(s): %s", drmaaImplementation.getString(0)));
+
+        this.implementation = drmaaImplementation.getString(0);
+    }
+
+    @Test(dependsOnMethods = { "testDrmaa" })
+    public void testSubmitEcho() throws Exception {
+        if ( ! queueTestRunModeIsSet ) {
+            throw new SkipException("Skipping testSubmitEcho because we are in pipeline test dry run mode");
+        }
+
+        if (implementation.contains("LSF")) {
+            System.err.println("    *********************************************************");
+            System.err.println("   ***********************************************************");
+            System.err.println("   ****                                                   ****");
+            System.err.println("  ****  Skipping LibDrmaaQueueTest.testSubmitEcho()        ****");
+            System.err.println("  ****     Are you using the dotkit .combined_LSF_SGE?     ****");
+            System.err.println("   ****                                                   ****");
+            System.err.println("   ***********************************************************");
+            System.err.println("    *********************************************************");
+            throw new SkipException("Skipping testSubmitEcho because correct DRMAA implementation not found");
+        }
+
+        Memory error = new Memory(LibDrmaa.DRMAA_ERROR_STRING_BUFFER);
+        int errnum;
+
+    File outFile = tryCreateNetworkTempFile("LibDrmaaQueueTest.out");
+
+        errnum = LibDrmaa.drmaa_init(null, error, LibDrmaa.DRMAA_ERROR_STRING_BUFFER_LEN);
+
+        if (errnum != LibDrmaa.DRMAA_ERRNO.DRMAA_ERRNO_SUCCESS)
+            Assert.fail(String.format("Could not initialize the DRMAA library: %s", error.getString(0)));
+
+        try {
+            PointerByReference jtRef = new PointerByReference();
+            Pointer jt;
+            Memory jobIdMem = new Memory(LibDrmaa.DRMAA_JOBNAME_BUFFER);
+            String jobId;
+            IntByReference remotePs = new IntByReference();
+            IntByReference stat = new IntByReference();
+            PointerByReference rusage = new PointerByReference();
+
+            errnum = LibDrmaa.drmaa_allocate_job_template(jtRef, error, LibDrmaa.DRMAA_ERROR_STRING_BUFFER_LEN);
+
+            if (errnum != LibDrmaa.DRMAA_ERRNO.DRMAA_ERRNO_SUCCESS)
+                Assert.fail(String.format("Could not create job template: %s", error.getString(0)));
+
+            jt = jtRef.getValue();
+
+            errnum = LibDrmaa.drmaa_set_attribute(jt, LibDrmaa.DRMAA_REMOTE_COMMAND, "sh", error, LibDrmaa.DRMAA_ERROR_STRING_BUFFER_LEN);
+
+            if (errnum != LibDrmaa.DRMAA_ERRNO.DRMAA_ERRNO_SUCCESS)
+                Assert.fail(String.format("Could not set attribute \"%s\": %s", LibDrmaa.DRMAA_REMOTE_COMMAND, error.getString(0)));
+
+            errnum = LibDrmaa.drmaa_set_attribute(jt, LibDrmaa.DRMAA_OUTPUT_PATH, ":" + outFile.getAbsolutePath(), error, LibDrmaa.DRMAA_ERROR_STRING_BUFFER_LEN);
+
+            if (errnum != LibDrmaa.DRMAA_ERRNO.DRMAA_ERRNO_SUCCESS)
+                Assert.fail(String.format("Could not set attribute \"%s\": %s", LibDrmaa.DRMAA_OUTPUT_PATH, error.getString(0)));
+
+            errnum = LibDrmaa.drmaa_set_attribute(jt, LibDrmaa.DRMAA_JOIN_FILES, "y", error, LibDrmaa.DRMAA_ERROR_STRING_BUFFER_LEN);
+
+            if (errnum != LibDrmaa.DRMAA_ERRNO.DRMAA_ERRNO_SUCCESS)
+                Assert.fail(String.format("Could not set attribute \"%s\": %s", LibDrmaa.DRMAA_JOIN_FILES, error.getString(0)));
+
+            StringArray args = new StringArray(new String[] { "-c", "echo \"Hello world.\"" });
+
+            errnum = LibDrmaa.drmaa_set_vector_attribute(jt, LibDrmaa.DRMAA_V_ARGV, args, error, LibDrmaa.DRMAA_ERROR_STRING_BUFFER_LEN);
+
+            if (errnum != LibDrmaa.DRMAA_ERRNO.DRMAA_ERRNO_SUCCESS)
+                Assert.fail(String.format("Could not set attribute \"%s\": %s", LibDrmaa.DRMAA_V_ARGV, error.getString(0)));
+
+            errnum = LibDrmaa.drmaa_run_job(jobIdMem, LibDrmaa.DRMAA_JOBNAME_BUFFER_LEN, jt, error, LibDrmaa.DRMAA_ERROR_STRING_BUFFER_LEN);
+
+            if (errnum != LibDrmaa.DRMAA_ERRNO.DRMAA_ERRNO_SUCCESS)
+                Assert.fail(String.format("Could not submit job: %s", error.getString(0)));
+
+            jobId = jobIdMem.getString(0);
+
+            System.out.println(String.format("Job id %s", jobId));
+
+            errnum = LibDrmaa.drmaa_delete_job_template(jt, error, LibDrmaa.DRMAA_ERROR_STRING_BUFFER_LEN);
+
+            if (errnum != LibDrmaa.DRMAA_ERRNO.DRMAA_ERRNO_SUCCESS)
+                Assert.fail(String.format("Could not delete job template: %s", error.getString(0)));
+
+            System.out.println("Waiting for job to run: " + jobId);
+            remotePs.setValue(LibDrmaa.DRMAA_PS.DRMAA_PS_QUEUED_ACTIVE);
+
+            List<Integer> runningStatuses = Arrays.asList(
+                    LibDrmaa.DRMAA_PS.DRMAA_PS_QUEUED_ACTIVE, LibDrmaa.DRMAA_PS.DRMAA_PS_RUNNING);
+
+            while (runningStatuses.contains(remotePs.getValue())) {
+                Thread.sleep(30 * 1000L);
+
+                errnum = LibDrmaa.drmaa_job_ps(jobId, remotePs, error, LibDrmaa.DRMAA_ERROR_STRING_BUFFER_LEN);
+
+                if (errnum != LibDrmaa.DRMAA_ERRNO.DRMAA_ERRNO_SUCCESS)
+                    Assert.fail(String.format("Could not get status for jobId %s: %s", jobId, error.getString(0)));
+            }
+
+            Assert.assertEquals(remotePs.getValue(), LibDrmaa.DRMAA_PS.DRMAA_PS_DONE, "Job status is not DONE.");
+
+            errnum = LibDrmaa.drmaa_wait(jobId, Pointer.NULL, new NativeLong(0), stat, LibDrmaa.DRMAA_TIMEOUT_NO_WAIT,
+                    rusage, error, LibDrmaa.DRMAA_ERROR_STRING_BUFFER_LEN);
+
+            if (errnum != LibDrmaa.DRMAA_ERRNO.DRMAA_ERRNO_SUCCESS)
+                Assert.fail(String.format("Wait failed for jobId %s: %s", jobId, error.getString(0)));
+
+            IntByReference exited = new IntByReference();
+            IntByReference exitStatus = new IntByReference();
+            IntByReference signaled = new IntByReference();
+            Memory signal = new Memory(LibDrmaa.DRMAA_SIGNAL_BUFFER);
+            IntByReference coreDumped = new IntByReference();
+            IntByReference aborted = new IntByReference();
+
+            errnum = LibDrmaa.drmaa_wifexited(exited, stat.getValue(), error, LibDrmaa.DRMAA_ERROR_STRING_BUFFER_LEN);
+
+            if (errnum != LibDrmaa.DRMAA_ERRNO.DRMAA_ERRNO_SUCCESS)
+                Assert.fail(String.format("Exit check failed for jobId %s: %s", jobId, error.getString(0)));
+
+            Assert.assertTrue(exited.getValue() != 0, String.format("Job did not exit cleanly: %s", jobId));
+
+            errnum = LibDrmaa.drmaa_wexitstatus(exitStatus, stat.getValue(), error, LibDrmaa.DRMAA_ERROR_STRING_BUFFER_LEN);
+
+            if (errnum != LibDrmaa.DRMAA_ERRNO.DRMAA_ERRNO_SUCCESS)
+                Assert.fail(String.format("Exit status failed for jobId %s: %s", jobId, error.getString(0)));
+
+            Assert.assertEquals(exitStatus.getValue(), 0, String.format("Exit status for jobId %s is non-zero", jobId));
+
+            errnum = LibDrmaa.drmaa_wifsignaled(signaled, stat.getValue(), error, LibDrmaa.DRMAA_ERROR_STRING_BUFFER_LEN);
+
+            if (errnum != LibDrmaa.DRMAA_ERRNO.DRMAA_ERRNO_SUCCESS)
+                Assert.fail(String.format("Signaled check failed for jobId %s: %s", jobId, error.getString(0)));
+
+            if (signaled.getValue() != 0) {
+                errnum = LibDrmaa.drmaa_wtermsig(signal, LibDrmaa.DRMAA_SIGNAL_BUFFER_LEN, stat.getValue(), error, LibDrmaa.DRMAA_ERROR_STRING_BUFFER_LEN);
+
+                if (errnum != LibDrmaa.DRMAA_ERRNO.DRMAA_ERRNO_SUCCESS)
+                    Assert.fail(String.format("Signal lookup failed for jobId %s: %s", jobId, error.getString(0)));
+
+                errnum = LibDrmaa.drmaa_wcoredump(coreDumped, stat.getValue(), error, LibDrmaa.DRMAA_ERROR_STRING_BUFFER_LEN);
+
+                if (errnum != LibDrmaa.DRMAA_ERRNO.DRMAA_ERRNO_SUCCESS)
+                    Assert.fail(String.format("Core dump check failed for jobId %s: %s", jobId, error.getString(0)));
+
+                Assert.fail(String.format("JobId %s exited with signal %s and core dump flag %d", jobId, signal.getString(0), coreDumped.getValue()));
+            }
+
+            errnum = LibDrmaa.drmaa_wifaborted(aborted, stat.getValue(), error, LibDrmaa.DRMAA_ERROR_STRING_BUFFER_LEN);
+
+            if (errnum != LibDrmaa.DRMAA_ERRNO.DRMAA_ERRNO_SUCCESS)
+                Assert.fail(String.format("Aborted check failed for jobId %s: %s", jobId, error.getString(0)));
+
+            Assert.assertTrue(aborted.getValue() == 0, String.format("Job was aborted: %s", jobId));
+
+        } finally {
+            if (errnum != LibDrmaa.DRMAA_ERRNO.DRMAA_ERRNO_SUCCESS) {
+                LibDrmaa.drmaa_exit(error, LibDrmaa.DRMAA_ERROR_STRING_BUFFER_LEN);
+            } else {
+                errnum = LibDrmaa.drmaa_exit(error, LibDrmaa.DRMAA_ERROR_STRING_BUFFER_LEN);
+
+                if (errnum != LibDrmaa.DRMAA_ERRNO.DRMAA_ERRNO_SUCCESS)
+                    Assert.fail(String.format("Could not shut down the DRMAA library: %s", error.getString(0)));
+            }
+        }
+
+        Assert.assertTrue(FileUtils.waitFor(outFile, 120), "File not found: " + outFile.getAbsolutePath());
+        System.out.println("--- output ---");
+        System.out.println(FileUtils.readFileToString(outFile));
+        System.out.println("--- output ---");
+        Assert.assertTrue(outFile.delete(), "Unable to delete " + outFile.getAbsolutePath());
+        System.out.println("Validating that we reached the end of the test without exit.");
+    }
+}
diff --git a/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/utils/jna/lsf/v7_0_6/LibBatQueueTest.java b/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/utils/jna/lsf/v7_0_6/LibBatQueueTest.java
new file mode 100644
index 0000000..4af2bf7
--- /dev/null
+++ b/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/utils/jna/lsf/v7_0_6/LibBatQueueTest.java
@@ -0,0 +1,162 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.utils.jna.lsf.v7_0_6;
+
+import com.sun.jna.*;
+import com.sun.jna.ptr.IntByReference;
+import org.apache.commons.io.FileUtils;
+import org.broadinstitute.gatk.utils.Utils;
+import org.testng.Assert;
+import org.testng.SkipException;
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.Test;
+import org.broadinstitute.gatk.utils.BaseTest;
+import org.broadinstitute.gatk.utils.jna.lsf.v7_0_6.LibBat.*;
+
+import java.io.File;
+
+/**
+ * Really unit tests, but these tests will only run on systems with LSF set up.
+ */
+public class LibBatQueueTest extends BaseTest {
+    @BeforeClass
+    public void initLibBat() {
+        Assert.assertFalse(LibBat.lsb_init("LibBatQueueTest") < 0, LibBat.lsb_sperror("lsb_init() failed"));
+    }
+
+    @Test
+    public void testClusterName() {
+        String clusterName = LibLsf.ls_getclustername();
+        System.out.println("Cluster name: " + clusterName);
+        Assert.assertNotNull(clusterName);
+    }
+
+    @Test
+    public void testReadConfEnv() {
+        LibLsf.config_param[] configParams = (LibLsf.config_param[]) new LibLsf.config_param().toArray(4);
+
+        configParams[0].paramName = "LSF_UNIT_FOR_LIMITS";
+        configParams[1].paramName = "LSF_CONFDIR";
+        configParams[2].paramName = "MADE_UP_PARAMETER";
+
+        Structure.autoWrite(configParams);
+
+        if (LibLsf.ls_readconfenv(configParams[0], null) != 0) {
+            Assert.fail(LibLsf.ls_sysmsg());
+        }
+
+        Structure.autoRead(configParams);
+
+        System.out.println("LSF_UNIT_FOR_LIMITS: " + configParams[0].paramValue);
+        Assert.assertNotNull(configParams[1].paramValue);
+        Assert.assertNull(configParams[2].paramValue);
+        Assert.assertNull(configParams[3].paramName);
+        Assert.assertNull(configParams[3].paramValue);
+    }
+
+    @Test
+    public void testReadQueueLimits() {
+        String queue = "hour";
+        StringArray queues = new StringArray(new String[] {queue});
+        IntByReference numQueues = new IntByReference(1);
+        queueInfoEnt queueInfo = LibBat.lsb_queueinfo(queues, numQueues, null, null, 0);
+
+        Assert.assertEquals(numQueues.getValue(), 1);
+        Assert.assertNotNull(queueInfo);
+        Assert.assertEquals(queueInfo.queue, queue);
+
+        int runLimit = queueInfo.rLimits[LibLsf.LSF_RLIMIT_RUN];
+        Assert.assertTrue(runLimit > 0, "LSF run limit is not greater than zero: " + runLimit);
+    }
+
+    @Test
+    public void testSubmitEcho() throws Exception {
+        if ( ! queueTestRunModeIsSet ) {
+            throw new SkipException("Skipping testSubmitEcho because we are in queue test dry run mode");
+        }
+
+        String queue = "hour";
+        File outFile = tryCreateNetworkTempFile("LibBatQueueTest.out");
+
+        submit req = new submit();
+
+        for (int i = 0; i < LibLsf.LSF_RLIM_NLIMITS; i++)
+            req.rLimits[i] = LibLsf.DEFAULT_RLIMIT;
+
+        req.projectName = "LibBatQueueTest";
+        req.options |= LibBat.SUB_PROJECT_NAME;
+
+        req.queue = queue;
+        req.options |= LibBat.SUB_QUEUE;
+
+        req.outFile = outFile.getPath();
+        req.options |= LibBat.SUB_OUT_FILE;
+
+        req.userPriority = 100;
+        req.options2 |= LibBat.SUB2_JOB_PRIORITY;
+
+        req.command = "echo \"Hello world.\"";
+
+        String[] argv = {"", "-a", "tv"};
+        int setOptionResult = LibBat.setOption_(argv.length, new StringArray(argv), "a:", req, ~0, ~0, ~0, null);
+        Assert.assertTrue(setOptionResult != -1, "setOption_ returned -1");
+
+        submitReply reply = new submitReply();
+        long jobId = LibBat.lsb_submit(req, reply);
+
+        Assert.assertFalse(jobId < 0, LibBat.lsb_sperror("Error dispatching"));
+
+        System.out.println("Waiting for job to run: " + jobId);
+        int jobStatus = LibBat.JOB_STAT_PEND;
+        while (Utils.isFlagSet(jobStatus, LibBat.JOB_STAT_PEND) || Utils.isFlagSet(jobStatus, LibBat.JOB_STAT_RUN)) {
+            Thread.sleep(30 * 1000L);
+
+            int numJobs = LibBat.lsb_openjobinfo(jobId, null, null, null, null, LibBat.ALL_JOB);
+            try {
+                Assert.assertEquals(numJobs, 1);
+    
+                IntByReference more = new IntByReference();
+
+                jobInfoEnt jobInfo = LibBat.lsb_readjobinfo(more);
+                Assert.assertNotNull(jobInfo, "Job info is null");
+                Assert.assertEquals(more.getValue(), 0, "More job info results than expected");
+
+                jobStatus = jobInfo.status;
+            } finally {
+                LibBat.lsb_closejobinfo();
+            }
+        }
+        Assert.assertTrue(Utils.isFlagSet(jobStatus, LibBat.JOB_STAT_DONE), String.format("Unexpected job status: 0x%02x", jobStatus));
+
+        Assert.assertTrue(FileUtils.waitFor(outFile, 120), "File not found: " + outFile.getAbsolutePath());
+        System.out.println("--- output ---");
+        System.out.println(FileUtils.readFileToString(outFile));
+        System.out.println("--- output ---");
+        Assert.assertTrue(outFile.delete(), "Unable to delete " + outFile.getAbsolutePath());
+        Assert.assertEquals(reply.queue, req.queue, "LSF reply queue does not match requested queue.");
+        System.out.println("Validating that we reached the end of the test without exit.");
+    }
+}
diff --git a/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/utils/locusiterator/AlignmentStateMachineUnitTest.java b/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/utils/locusiterator/AlignmentStateMachineUnitTest.java
new file mode 100644
index 0000000..d8c39d3
--- /dev/null
+++ b/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/utils/locusiterator/AlignmentStateMachineUnitTest.java
@@ -0,0 +1,110 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.utils.locusiterator;
+
+import org.broadinstitute.gatk.utils.sam.GATKSAMRecord;
+import org.testng.Assert;
+import org.testng.annotations.DataProvider;
+import org.testng.annotations.Test;
+
+import java.util.Arrays;
+
+/**
+ * testing of the new (non-legacy) version of LocusIteratorByState
+ */
+public class AlignmentStateMachineUnitTest extends LocusIteratorByStateBaseTest {
+    @DataProvider(name = "AlignmentStateMachineTest")
+    public Object[][] makeAlignmentStateMachineTest() {
+//        return new Object[][]{{new LIBSTest("2M2D2X", 2)}};
+//        return createLIBSTests(
+//                Arrays.asList(2),
+//                Arrays.asList(2));
+        return createLIBSTests(
+                Arrays.asList(1, 2),
+                Arrays.asList(1, 2, 3, 4));
+    }
+
+    @Test(dataProvider = "AlignmentStateMachineTest")
+    public void testAlignmentStateMachineTest(LIBSTest params) {
+        final GATKSAMRecord read = params.makeRead();
+        final AlignmentStateMachine state = new AlignmentStateMachine(read);
+        final LIBS_position tester = new LIBS_position(read);
+
+        // min is one because always visit something, even for 10I reads
+        final int expectedBpToVisit = read.getAlignmentEnd() - read.getAlignmentStart() + 1;
+
+        Assert.assertSame(state.getRead(), read);
+        Assert.assertNotNull(state.toString());
+
+        int bpVisited = 0;
+        int lastOffset = -1;
+
+        // TODO -- more tests about test state machine state before first step?
+        Assert.assertTrue(state.isLeftEdge());
+        Assert.assertNull(state.getCigarOperator());
+        Assert.assertNotNull(state.toString());
+        Assert.assertEquals(state.getReadOffset(), -1);
+        Assert.assertEquals(state.getGenomeOffset(), -1);
+        Assert.assertEquals(state.getCurrentCigarElementOffset(), -1);
+        Assert.assertEquals(state.getCurrentCigarElement(), null);
+
+        while ( state.stepForwardOnGenome() != null ) {
+            Assert.assertNotNull(state.toString());
+
+            tester.stepForwardOnGenome();
+
+            Assert.assertTrue(state.getReadOffset() >= lastOffset, "Somehow read offsets are decreasing: lastOffset " + lastOffset + " current " + state.getReadOffset());
+            Assert.assertEquals(state.getReadOffset(), tester.getCurrentReadOffset(), "Read offsets are wrong at " + bpVisited);
+
+            Assert.assertFalse(state.isLeftEdge());
+
+            Assert.assertEquals(state.getCurrentCigarElement(), read.getCigar().getCigarElement(tester.currentOperatorIndex), "CigarElement index failure");
+            Assert.assertEquals(state.getOffsetIntoCurrentCigarElement(), tester.getCurrentPositionOnOperatorBase0(), "CigarElement index failure");
+
+            Assert.assertEquals(read.getCigar().getCigarElement(state.getCurrentCigarElementOffset()), state.getCurrentCigarElement(), "Current cigar element isn't what we'd get from the read itself");
+
+            Assert.assertTrue(state.getOffsetIntoCurrentCigarElement() >= 0, "Offset into current cigar too small");
+            Assert.assertTrue(state.getOffsetIntoCurrentCigarElement() < state.getCurrentCigarElement().getLength(), "Offset into current cigar too big");
+
+            Assert.assertEquals(state.getGenomeOffset(), tester.getCurrentGenomeOffsetBase0(), "Offset from alignment start is bad");
+            Assert.assertEquals(state.getGenomePosition(), tester.getCurrentGenomeOffsetBase0() + read.getAlignmentStart(), "GenomePosition start is bad");
+            Assert.assertEquals(state.getLocation(genomeLocParser).size(), 1, "GenomeLoc position should have size == 1");
+            Assert.assertEquals(state.getLocation(genomeLocParser).getStart(), state.getGenomePosition(), "GenomeLoc position is bad");
+
+            // most tests of this functionality are in LIBS
+            Assert.assertNotNull(state.makePileupElement());
+
+            lastOffset = state.getReadOffset();
+            bpVisited++;
+        }
+
+        Assert.assertEquals(bpVisited, expectedBpToVisit, "Didn't visit the expected number of bp");
+        Assert.assertEquals(state.getReadOffset(), read.getReadLength());
+        Assert.assertEquals(state.getCurrentCigarElementOffset(), read.getCigarLength());
+        Assert.assertEquals(state.getCurrentCigarElement(), null);
+        Assert.assertNotNull(state.toString());
+    }
+}
diff --git a/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/utils/locusiterator/LIBS_position.java b/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/utils/locusiterator/LIBS_position.java
new file mode 100644
index 0000000..92680a7
--- /dev/null
+++ b/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/utils/locusiterator/LIBS_position.java
@@ -0,0 +1,155 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.utils.locusiterator;
+
+import htsjdk.samtools.Cigar;
+import htsjdk.samtools.CigarElement;
+import htsjdk.samtools.CigarOperator;
+import htsjdk.samtools.SAMRecord;
+
+/**
+* Created with IntelliJ IDEA.
+* User: depristo
+* Date: 1/5/13
+* Time: 8:42 PM
+* To change this template use File | Settings | File Templates.
+*/
+public final class LIBS_position {
+
+    SAMRecord read;
+
+    final int numOperators;
+    int currentOperatorIndex = 0;
+    int currentPositionOnOperator = 0;
+    int currentReadOffset = 0;
+    int currentGenomeOffset = 0;
+
+    public boolean isBeforeDeletionStart = false;
+    public boolean isBeforeDeletedBase = false;
+    public boolean isAfterDeletionEnd = false;
+    public boolean isAfterDeletedBase = false;
+    public boolean isBeforeInsertion = false;
+    public boolean isAfterInsertion = false;
+    public boolean isNextToSoftClip = false;
+
+    boolean sawMop = false;
+
+    public LIBS_position(final SAMRecord read) {
+        this.read = read;
+        numOperators = read.getCigar().numCigarElements();
+    }
+
+    public int getCurrentReadOffset() {
+        return Math.max(0, currentReadOffset - 1);
+    }
+
+    public int getCurrentPositionOnOperatorBase0() {
+        return currentPositionOnOperator - 1;
+    }
+
+    public int getCurrentGenomeOffsetBase0() {
+        return currentGenomeOffset - 1;
+    }
+
+    /**
+     * Steps forward on the genome.  Returns false when done reading the read, true otherwise.
+     */
+    public boolean stepForwardOnGenome() {
+        if ( currentOperatorIndex == numOperators )
+            return false;
+
+        CigarElement curElement = read.getCigar().getCigarElement(currentOperatorIndex);
+        if ( currentPositionOnOperator >= curElement.getLength() ) {
+            if ( ++currentOperatorIndex == numOperators )
+                return false;
+
+            curElement = read.getCigar().getCigarElement(currentOperatorIndex);
+            currentPositionOnOperator = 0;
+        }
+
+        switch ( curElement.getOperator() ) {
+            case I: // insertion w.r.t. the reference
+//                if ( !sawMop )
+//                    break;
+            case S: // soft clip
+                currentReadOffset += curElement.getLength();
+            case H: // hard clip
+            case P: // padding
+                currentOperatorIndex++;
+                return stepForwardOnGenome();
+
+            case D: // deletion w.r.t. the reference
+            case N: // reference skip (looks and gets processed just like a "deletion", just different logical meaning)
+                currentPositionOnOperator++;
+                currentGenomeOffset++;
+                break;
+
+            case M:
+            case EQ:
+            case X:
+                sawMop = true;
+                currentReadOffset++;
+                currentPositionOnOperator++;
+                currentGenomeOffset++;
+                break;
+            default:
+                throw new IllegalStateException("No support for cigar op: " + curElement.getOperator());
+        }
+
+        final boolean isFirstOp = currentOperatorIndex == 0;
+        final boolean isLastOp = currentOperatorIndex == numOperators - 1;
+        final boolean isFirstBaseOfOp = currentPositionOnOperator == 1;
+        final boolean isLastBaseOfOp = currentPositionOnOperator == curElement.getLength();
+
+        isBeforeDeletionStart = isBeforeOp(read.getCigar(), currentOperatorIndex, CigarOperator.D, isLastOp, isLastBaseOfOp);
+        isBeforeDeletedBase = isBeforeDeletionStart || (!isLastBaseOfOp && curElement.getOperator() == CigarOperator.D);
+        isAfterDeletionEnd = isAfterOp(read.getCigar(), currentOperatorIndex, CigarOperator.D, isFirstOp, isFirstBaseOfOp);
+        isAfterDeletedBase  = isAfterDeletionEnd || (!isFirstBaseOfOp && curElement.getOperator() == CigarOperator.D);
+        isBeforeInsertion = isBeforeOp(read.getCigar(), currentOperatorIndex, CigarOperator.I, isLastOp, isLastBaseOfOp)
+                || (!sawMop && curElement.getOperator() == CigarOperator.I);
+        isAfterInsertion = isAfterOp(read.getCigar(), currentOperatorIndex, CigarOperator.I, isFirstOp, isFirstBaseOfOp);
+        isNextToSoftClip = isBeforeOp(read.getCigar(), currentOperatorIndex, CigarOperator.S, isLastOp, isLastBaseOfOp)
+                || isAfterOp(read.getCigar(), currentOperatorIndex, CigarOperator.S, isFirstOp, isFirstBaseOfOp);
+
+        return true;
+    }
+
+    private static boolean isBeforeOp(final Cigar cigar,
+                                      final int currentOperatorIndex,
+                                      final CigarOperator op,
+                                      final boolean isLastOp,
+                                      final boolean isLastBaseOfOp) {
+        return  !isLastOp && isLastBaseOfOp && cigar.getCigarElement(currentOperatorIndex+1).getOperator() == op;
+    }
+
+    private static boolean isAfterOp(final Cigar cigar,
+                                     final int currentOperatorIndex,
+                                     final CigarOperator op,
+                                     final boolean isFirstOp,
+                                     final boolean isFirstBaseOfOp) {
+        return  !isFirstOp && isFirstBaseOfOp && cigar.getCigarElement(currentOperatorIndex-1).getOperator() == op;
+    }
+}
diff --git a/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/utils/locusiterator/LocusIteratorBenchmark.java b/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/utils/locusiterator/LocusIteratorBenchmark.java
new file mode 100644
index 0000000..1f02a68
--- /dev/null
+++ b/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/utils/locusiterator/LocusIteratorBenchmark.java
@@ -0,0 +1,142 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.utils.locusiterator;
+
+import com.google.caliper.Param;
+import com.google.caliper.SimpleBenchmark;
+import htsjdk.samtools.SAMFileHeader;
+import org.broadinstitute.gatk.engine.contexts.AlignmentContext;
+import org.broadinstitute.gatk.utils.GenomeLocParser;
+import org.broadinstitute.gatk.utils.QualityUtils;
+import org.broadinstitute.gatk.utils.Utils;
+import org.broadinstitute.gatk.utils.sam.ArtificialSAMUtils;
+import org.broadinstitute.gatk.utils.sam.GATKSAMRecord;
+
+import java.util.LinkedList;
+import java.util.List;
+
+/**
+ * Caliper microbenchmark of fragment pileup
+ */
+public class LocusIteratorBenchmark extends SimpleBenchmark {
+    protected SAMFileHeader header;
+    protected GenomeLocParser genomeLocParser;
+
+    List<GATKSAMRecord> reads = new LinkedList<GATKSAMRecord>();
+    final int readLength = 101;
+    final int nReads = 10000;
+    final int locus = 1;
+
+    @Param({"101M", "50M10I40M", "50M10D40M"})
+    String cigar; // set automatically by framework
+
+    @Override protected void setUp() {
+        header = ArtificialSAMUtils.createArtificialSamHeader(1, 1, 1000);
+        genomeLocParser = new GenomeLocParser(header.getSequenceDictionary());
+
+        for ( int j = 0; j < nReads; j++ ) {
+            GATKSAMRecord read = ArtificialSAMUtils.createArtificialRead(header, "read", 0, locus, readLength);
+            read.setReadBases(Utils.dupBytes((byte) 'A', readLength));
+            final byte[] quals = new byte[readLength];
+            for ( int i = 0; i < readLength; i++ )
+                quals[i] = (byte)(i % QualityUtils.MAX_SAM_QUAL_SCORE);
+            read.setBaseQualities(quals);
+            read.setCigarString(cigar);
+            reads.add(read);
+        }
+    }
+
+//    public void timeOriginalLIBS(int rep) {
+//        for ( int i = 0; i < rep; i++ ) {
+//            final org.broadinstitute.gatk.utils.locusiterator.old.LocusIteratorByState libs =
+//                    new org.broadinstitute.gatk.utils.locusiterator.old.LocusIteratorByState(
+//                            new LocusIteratorByStateBaseTest.FakeCloseableIterator<SAMRecord>(reads.iterator()),
+//                            LocusIteratorByStateBaseTest.createTestReadProperties(),
+//                            genomeLocParser,
+//                            LocusIteratorByState.sampleListForSAMWithoutReadGroups());
+//
+//            while ( libs.hasNext() ) {
+//                AlignmentContext context = libs.next();
+//            }
+//        }
+//    }
+//
+//    public void timeLegacyLIBS(int rep) {
+//        for ( int i = 0; i < rep; i++ ) {
+//            final org.broadinstitute.gatk.utils.locusiterator.legacy.LegacyLocusIteratorByState libs =
+//                    new org.broadinstitute.gatk.utils.locusiterator.legacy.LegacyLocusIteratorByState(
+//                            new LocusIteratorByStateBaseTest.FakeCloseableIterator<SAMRecord>(reads.iterator()),
+//                            LocusIteratorByStateBaseTest.createTestReadProperties(),
+//                            genomeLocParser,
+//                            LocusIteratorByState.sampleListForSAMWithoutReadGroups());
+//
+//            while ( libs.hasNext() ) {
+//                AlignmentContext context = libs.next();
+//            }
+//        }
+//    }
+
+    public void timeNewLIBS(int rep) {
+        for ( int i = 0; i < rep; i++ ) {
+            final org.broadinstitute.gatk.utils.locusiterator.LocusIteratorByState libs =
+                    new org.broadinstitute.gatk.utils.locusiterator.LocusIteratorByState(
+                            new LocusIteratorByStateBaseTest.FakeCloseableIterator<GATKSAMRecord>(reads.iterator()),
+                            LocusIteratorByStateBaseTest.createTestReadProperties(),
+                            genomeLocParser,
+                            LocusIteratorByState.sampleListForSAMWithoutReadGroups());
+
+            while ( libs.hasNext() ) {
+                AlignmentContext context = libs.next();
+            }
+        }
+    }
+
+//    public void timeOriginalLIBSStateMachine(int rep) {
+//        for ( int i = 0; i < rep; i++ ) {
+//            for ( final SAMRecord read : reads ) {
+//                final SAMRecordAlignmentState alignmentStateMachine = new SAMRecordAlignmentState(read);
+//                while ( alignmentStateMachine.stepForwardOnGenome() != null ) {
+//                    alignmentStateMachine.getGenomeOffset();
+//                }
+//            }
+//        }
+//    }
+
+    public void timeAlignmentStateMachine(int rep) {
+        for ( int i = 0; i < rep; i++ ) {
+            for ( final GATKSAMRecord read : reads ) {
+                final AlignmentStateMachine alignmentStateMachine = new AlignmentStateMachine(read);
+                while ( alignmentStateMachine.stepForwardOnGenome() != null ) {
+                    ;
+                }
+            }
+        }
+    }
+
+    public static void main(String[] args) {
+        com.google.caliper.Runner.main(LocusIteratorBenchmark.class, args);
+    }
+}
diff --git a/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/utils/locusiterator/LocusIteratorByStateBaseTest.java b/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/utils/locusiterator/LocusIteratorByStateBaseTest.java
new file mode 100644
index 0000000..286c712
--- /dev/null
+++ b/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/utils/locusiterator/LocusIteratorByStateBaseTest.java
@@ -0,0 +1,252 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.utils.locusiterator;
+
+import htsjdk.samtools.*;
+import htsjdk.samtools.util.CloseableIterator;
+import org.broadinstitute.gatk.utils.BaseTest;
+import org.broadinstitute.gatk.engine.ReadProperties;
+import org.broadinstitute.gatk.engine.arguments.ValidationExclusion;
+import org.broadinstitute.gatk.engine.datasources.reads.SAMReaderID;
+import org.broadinstitute.gatk.engine.downsampling.DownsamplingMethod;
+import org.broadinstitute.gatk.engine.filters.ReadFilter;
+import org.broadinstitute.gatk.engine.iterators.ReadTransformer;
+import org.broadinstitute.gatk.utils.GenomeLocParser;
+import org.broadinstitute.gatk.utils.QualityUtils;
+import org.broadinstitute.gatk.utils.Utils;
+import org.broadinstitute.gatk.utils.sam.ArtificialSAMUtils;
+import org.broadinstitute.gatk.utils.sam.GATKSAMRecord;
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.DataProvider;
+
+import java.util.*;
+
+/**
+ * testing of the new (non-legacy) version of LocusIteratorByState
+ */
+public class LocusIteratorByStateBaseTest extends BaseTest {
+    protected static SAMFileHeader header;
+    protected GenomeLocParser genomeLocParser;
+
+    @BeforeClass
+    public void beforeClass() {
+        header = ArtificialSAMUtils.createArtificialSamHeader(1, 1, 1000);
+        genomeLocParser = new GenomeLocParser(header.getSequenceDictionary());
+    }
+
+    protected LocusIteratorByState makeLTBS(List<GATKSAMRecord> reads,
+                                            ReadProperties readAttributes) {
+        return new LocusIteratorByState(new FakeCloseableIterator<GATKSAMRecord>(reads.iterator()),
+                readAttributes,
+                genomeLocParser,
+                LocusIteratorByState.sampleListForSAMWithoutReadGroups());
+    }
+
+    public static ReadProperties createTestReadProperties() {
+        return createTestReadProperties(null, false);
+    }
+
+    public static ReadProperties createTestReadProperties( DownsamplingMethod downsamplingMethod, final boolean keepReads ) {
+        return new ReadProperties(
+                Collections.<SAMReaderID>emptyList(),
+                new SAMFileHeader(),
+                SAMFileHeader.SortOrder.coordinate,
+                false,
+                ValidationStringency.STRICT,
+                downsamplingMethod,
+                new ValidationExclusion(),
+                Collections.<ReadFilter>emptyList(),
+                Collections.<ReadTransformer>emptyList(),
+                true,
+                (byte) -1,
+                keepReads);
+    }
+
+    public static class FakeCloseableIterator<T> implements CloseableIterator<T> {
+        Iterator<T> iterator;
+
+        public FakeCloseableIterator(Iterator<T> it) {
+            iterator = it;
+        }
+
+        @Override
+        public void close() {}
+
+        @Override
+        public boolean hasNext() {
+            return iterator.hasNext();
+        }
+
+        @Override
+        public T next() {
+            return iterator.next();
+        }
+
+        @Override
+        public void remove() {
+            throw new UnsupportedOperationException("Don't remove!");
+        }
+    }
+
+    protected static class LIBSTest {
+        public static final int locus = 44367788;
+        final String cigarString;
+        final int readLength;
+        final private List<CigarElement> elements;
+
+        public LIBSTest(final String cigarString) {
+            final Cigar cigar = TextCigarCodec.getSingleton().decode(cigarString);
+            this.cigarString = cigarString;
+            this.elements = cigar.getCigarElements();
+            this.readLength = cigar.getReadLength();
+        }
+
+        @Override
+        public String toString() {
+            return "LIBSTest{" +
+                    "cigar='" + cigarString + '\'' +
+                    ", readLength=" + readLength +
+                    '}';
+        }
+
+        public List<CigarElement> getElements() {
+            return elements;
+        }
+
+        public GATKSAMRecord makeRead() {
+            GATKSAMRecord read = ArtificialSAMUtils.createArtificialRead(header, "read", 0, locus, readLength);
+            read.setReadBases(Utils.dupBytes((byte) 'A', readLength));
+            final byte[] quals = new byte[readLength];
+            for ( int i = 0; i < readLength; i++ )
+                quals[i] = (byte)(i % QualityUtils.MAX_SAM_QUAL_SCORE);
+            read.setBaseQualities(quals);
+            read.setCigarString(cigarString);
+            return read;
+        }
+    }
+
+    private boolean isIndel(final CigarElement ce) {
+        return ce.getOperator() == CigarOperator.D || ce.getOperator() == CigarOperator.I;
+    }
+
+    private boolean startsWithDeletion(final List<CigarElement> elements) {
+        for ( final CigarElement element : elements ) {
+            switch ( element.getOperator() ) {
+                case M:
+                case I:
+                case EQ:
+                case X:
+                    return false;
+                case D:
+                    return true;
+                default:
+                    // keep looking
+            }
+        }
+
+        return false;
+    }
+
+    private LIBSTest makePermutationTest(final List<CigarElement> elements) {
+        CigarElement last = null;
+        boolean hasMatch = false;
+
+        // starts with D => bad
+        if ( startsWithDeletion(elements) )
+            return null;
+
+        // ends with D => bad
+        if ( elements.get(elements.size()-1).getOperator() == CigarOperator.D )
+            return null;
+
+        // make sure it's valid
+        String cigar = "";
+        int len = 0;
+        for ( final CigarElement ce : elements ) {
+            if ( ce.getOperator() == CigarOperator.N )
+                return null; // TODO -- don't support N
+
+            // abort on a bad cigar
+            if ( last != null ) {
+                if ( ce.getOperator() == last.getOperator() )
+                    return null;
+                if ( isIndel(ce) && isIndel(last) )
+                    return null;
+            }
+
+            cigar += ce.getLength() + ce.getOperator().toString();
+            len += ce.getLength();
+            last = ce;
+            hasMatch = hasMatch || ce.getOperator() == CigarOperator.M;
+        }
+
+        if ( ! hasMatch && elements.size() == 1 &&
+                ! (last.getOperator() == CigarOperator.I || last.getOperator() == CigarOperator.S))
+            return null;
+
+        return new LIBSTest(cigar);
+    }
+
+    @DataProvider(name = "LIBSTest")
+    public Object[][] createLIBSTests(final List<Integer> cigarLengths, final List<Integer> combinations) {
+        final List<Object[]> tests = new LinkedList<Object[]>();
+
+        final List<CigarOperator> allOps = Arrays.asList(CigarOperator.values());
+
+        final List<CigarElement> singleCigars = new LinkedList<CigarElement>();
+        for ( final int len : cigarLengths )
+            for ( final CigarOperator op : allOps )
+                singleCigars.add(new CigarElement(len, op));
+
+        for ( final int complexity : combinations ) {
+            for ( final List<CigarElement> elements : Utils.makePermutations(singleCigars, complexity, true) ) {
+                final LIBSTest test = makePermutationTest(elements);
+                if ( test != null ) tests.add(new Object[]{test});
+            }
+        }
+
+        return tests.toArray(new Object[][]{});
+    }
+
+    /**
+     * Work around inadequate tests that aren't worth fixing.
+     *
+     * Look at the CIGAR 2M2P2D2P2M.  Both M states border a deletion, separated by P (padding elements).  So
+     * the right answer for deletions here is true for isBeforeDeletion() and isAfterDeletion() for the first
+     * and second M.  But the LIBS_position doesn't say so.
+     *
+     * @param elements
+     * @return
+     */
+    protected static boolean hasNeighboringPaddedOps(final List<CigarElement> elements, final int elementI) {
+        return (elementI - 1 >= 0 && isPadding(elements.get(elementI-1))) ||
+                (elementI + 1 < elements.size() && isPadding(elements.get(elementI+1)));
+    }
+
+    private static boolean isPadding(final CigarElement elt) {
+        return elt.getOperator() == CigarOperator.P || elt.getOperator() == CigarOperator.H || elt.getOperator() == CigarOperator.S;
+    }
+}
diff --git a/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/utils/locusiterator/LocusIteratorByStateUnitTest.java b/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/utils/locusiterator/LocusIteratorByStateUnitTest.java
new file mode 100644
index 0000000..08cbeca
--- /dev/null
+++ b/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/utils/locusiterator/LocusIteratorByStateUnitTest.java
@@ -0,0 +1,753 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.utils.locusiterator;
+
+import htsjdk.samtools.CigarOperator;
+import htsjdk.samtools.SAMFileHeader;
+import htsjdk.samtools.SAMReadGroupRecord;
+import org.broadinstitute.gatk.engine.ReadProperties;
+import org.broadinstitute.gatk.engine.contexts.AlignmentContext;
+import org.broadinstitute.gatk.engine.downsampling.DownsampleType;
+import org.broadinstitute.gatk.engine.downsampling.DownsamplingMethod;
+import org.broadinstitute.gatk.utils.NGSPlatform;
+import org.broadinstitute.gatk.utils.QualityUtils;
+import org.broadinstitute.gatk.utils.Utils;
+import org.broadinstitute.gatk.utils.pileup.PileupElement;
+import org.broadinstitute.gatk.utils.pileup.ReadBackedPileup;
+import org.broadinstitute.gatk.utils.sam.ArtificialBAMBuilder;
+import org.broadinstitute.gatk.utils.sam.ArtificialSAMUtils;
+import org.broadinstitute.gatk.utils.sam.GATKSAMReadGroupRecord;
+import org.broadinstitute.gatk.utils.sam.GATKSAMRecord;
+import org.testng.Assert;
+import org.testng.annotations.DataProvider;
+import org.testng.annotations.Test;
+
+import java.util.*;
+
+/**
+ * testing of the new (non-legacy) version of LocusIteratorByState
+ */
+public class LocusIteratorByStateUnitTest extends LocusIteratorByStateBaseTest {
+    private static final boolean DEBUG = false;
+    protected LocusIteratorByState li;
+
+    @Test(enabled = !DEBUG)
+    public void testUnmappedAndAllIReadsPassThrough() {
+        final int readLength = 10;
+        GATKSAMRecord mapped1 = ArtificialSAMUtils.createArtificialRead(header,"mapped1",0,1,readLength);
+        GATKSAMRecord mapped2 = ArtificialSAMUtils.createArtificialRead(header,"mapped2",0,1,readLength);
+        GATKSAMRecord unmapped = ArtificialSAMUtils.createArtificialRead(header,"unmapped",0,1,readLength);
+        GATKSAMRecord allI = ArtificialSAMUtils.createArtificialRead(header,"allI",0,1,readLength);
+
+        unmapped.setReadUnmappedFlag(true);
+        unmapped.setCigarString("*");
+        allI.setCigarString(readLength + "I");
+
+        List<GATKSAMRecord> reads = Arrays.asList(mapped1, unmapped, allI, mapped2);
+
+        // create the iterator by state with the fake reads and fake records
+        li = makeLTBS(reads,createTestReadProperties(DownsamplingMethod.NONE, true));
+
+        Assert.assertTrue(li.hasNext());
+        AlignmentContext context = li.next();
+        ReadBackedPileup pileup = context.getBasePileup();
+        Assert.assertEquals(pileup.depthOfCoverage(), 2, "Should see only 2 reads in pileup, even with unmapped and all I reads");
+
+        final List<GATKSAMRecord> rawReads = li.transferReadsFromAllPreviousPileups();
+        Assert.assertEquals(rawReads, reads, "Input and transferred read lists should be the same, and include the unmapped and all I reads");
+    }
+
+    @Test(enabled = true && ! DEBUG)
+    public void testXandEQOperators() {
+        final byte[] bases1 = new byte[] {'A','A','A','A','A','A','A','A','A','A'};
+        final byte[] bases2 = new byte[] {'A','A','A','C','A','A','A','A','A','C'};
+
+        // create a test version of the Reads object
+        ReadProperties readAttributes = createTestReadProperties();
+
+        GATKSAMRecord r1 = ArtificialSAMUtils.createArtificialRead(header,"r1",0,1,10);
+        r1.setReadBases(bases1);
+        r1.setBaseQualities(new byte[] {20,20,20,20,20,20,20,20,20,20});
+        r1.setCigarString("10M");
+
+        GATKSAMRecord r2 = ArtificialSAMUtils.createArtificialRead(header,"r2",0,1,10);
+        r2.setReadBases(bases2);
+        r2.setBaseQualities(new byte[] {20,20,20,20,20,20,20,20,20,20,20,20});
+        r2.setCigarString("3=1X5=1X");
+
+        GATKSAMRecord r3 = ArtificialSAMUtils.createArtificialRead(header,"r3",0,1,10);
+        r3.setReadBases(bases2);
+        r3.setBaseQualities(new byte[] {20,20,20,20,20,20,20,20,20,20,20,20});
+        r3.setCigarString("3=1X5M1X");
+
+        GATKSAMRecord r4  = ArtificialSAMUtils.createArtificialRead(header,"r4",0,1,10);
+        r4.setReadBases(bases2);
+        r4.setBaseQualities(new byte[] {20,20,20,20,20,20,20,20,20,20});
+        r4.setCigarString("10M");
+
+        List<GATKSAMRecord> reads = Arrays.asList(r1, r2, r3, r4);
+
+        // create the iterator by state with the fake reads and fake records
+        li = makeLTBS(reads,readAttributes);
+
+        while (li.hasNext()) {
+            AlignmentContext context = li.next();
+            ReadBackedPileup pileup = context.getBasePileup();
+            Assert.assertEquals(pileup.depthOfCoverage(), 4);
+        }
+    }
+
+    @Test(enabled = true && ! DEBUG)
+    public void testIndelsInRegularPileup() {
+        final byte[] bases = new byte[] {'A','A','A','A','A','A','A','A','A','A'};
+        final byte[] indelBases = new byte[] {'A','A','A','A','C','T','A','A','A','A','A','A'};
+
+        // create a test version of the Reads object
+        ReadProperties readAttributes = createTestReadProperties();
+
+        GATKSAMRecord before = ArtificialSAMUtils.createArtificialRead(header,"before",0,1,10);
+        before.setReadBases(bases);
+        before.setBaseQualities(new byte[] {20,20,20,20,20,20,20,20,20,20});
+        before.setCigarString("10M");
+
+        GATKSAMRecord during = ArtificialSAMUtils.createArtificialRead(header,"during",0,2,10);
+        during.setReadBases(indelBases);
+        during.setBaseQualities(new byte[] {20,20,20,20,20,20,20,20,20,20,20,20});
+        during.setCigarString("4M2I6M");
+
+        GATKSAMRecord after  = ArtificialSAMUtils.createArtificialRead(header,"after",0,3,10);
+        after.setReadBases(bases);
+        after.setBaseQualities(new byte[] {20,20,20,20,20,20,20,20,20,20});
+        after.setCigarString("10M");
+
+        List<GATKSAMRecord> reads = Arrays.asList(before, during, after);
+
+        // create the iterator by state with the fake reads and fake records
+        li = makeLTBS(reads,readAttributes);
+
+        boolean foundIndel = false;
+        while (li.hasNext()) {
+            AlignmentContext context = li.next();
+            ReadBackedPileup pileup = context.getBasePileup().getBaseFilteredPileup(10);
+            for (PileupElement p : pileup) {
+                if (p.isBeforeInsertion()) {
+                    foundIndel = true;
+                    Assert.assertEquals(p.getLengthOfImmediatelyFollowingIndel(), 2, "Wrong event length");
+                    Assert.assertEquals(p.getBasesOfImmediatelyFollowingInsertion(), "CT", "Inserted bases are incorrect");
+                    break;
+               }
+            }
+
+         }
+
+         Assert.assertTrue(foundIndel,"Indel in pileup not found");
+    }
+
+    @Test(enabled = false && ! DEBUG)
+    public void testWholeIndelReadInIsolation() {
+        final int firstLocus = 44367789;
+
+        // create a test version of the Reads object
+        ReadProperties readAttributes = createTestReadProperties();
+
+        GATKSAMRecord indelOnlyRead = ArtificialSAMUtils.createArtificialRead(header, "indelOnly", 0, firstLocus, 76);
+        indelOnlyRead.setReadBases(Utils.dupBytes((byte)'A',76));
+        indelOnlyRead.setBaseQualities(Utils.dupBytes((byte) '@', 76));
+        indelOnlyRead.setCigarString("76I");
+
+        List<GATKSAMRecord> reads = Arrays.asList(indelOnlyRead);
+
+        // create the iterator by state with the fake reads and fake records
+        li = makeLTBS(reads, readAttributes);
+
+        // Traditionally, reads that end with indels bleed into the pileup at the following locus.  Verify that the next pileup contains this read
+        // and considers it to be an indel-containing read.
+        Assert.assertTrue(li.hasNext(),"Should have found a whole-indel read in the normal base pileup without extended events enabled");
+        AlignmentContext alignmentContext = li.next();
+        Assert.assertEquals(alignmentContext.getLocation().getStart(), firstLocus, "Base pileup is at incorrect location.");
+        ReadBackedPileup basePileup = alignmentContext.getBasePileup();
+        Assert.assertEquals(basePileup.getReads().size(),1,"Pileup is of incorrect size");
+        Assert.assertSame(basePileup.getReads().get(0), indelOnlyRead, "Read in pileup is incorrect");
+    }
+
+    /**
+     * Test to make sure that reads supporting only an indel (example cigar string: 76I) do
+     * not negatively influence the ordering of the pileup.
+     */
+    @Test(enabled = true && ! DEBUG)
+    public void testWholeIndelRead() {
+        final int firstLocus = 44367788, secondLocus = firstLocus + 1;
+
+        GATKSAMRecord leadingRead = ArtificialSAMUtils.createArtificialRead(header,"leading",0,firstLocus,76);
+        leadingRead.setReadBases(Utils.dupBytes((byte)'A',76));
+        leadingRead.setBaseQualities(Utils.dupBytes((byte)'@',76));
+        leadingRead.setCigarString("1M75I");
+
+        GATKSAMRecord indelOnlyRead = ArtificialSAMUtils.createArtificialRead(header,"indelOnly",0,secondLocus,76);
+        indelOnlyRead.setReadBases(Utils.dupBytes((byte) 'A', 76));
+        indelOnlyRead.setBaseQualities(Utils.dupBytes((byte)'@',76));
+        indelOnlyRead.setCigarString("76I");
+
+        GATKSAMRecord fullMatchAfterIndel = ArtificialSAMUtils.createArtificialRead(header,"fullMatch",0,secondLocus,76);
+        fullMatchAfterIndel.setReadBases(Utils.dupBytes((byte)'A',76));
+        fullMatchAfterIndel.setBaseQualities(Utils.dupBytes((byte)'@',76));
+        fullMatchAfterIndel.setCigarString("75I1M");
+
+        List<GATKSAMRecord> reads = Arrays.asList(leadingRead, indelOnlyRead, fullMatchAfterIndel);
+
+        // create the iterator by state with the fake reads and fake records
+        li = makeLTBS(reads, createTestReadProperties());
+        int currentLocus = firstLocus;
+        int numAlignmentContextsFound = 0;
+
+        while(li.hasNext()) {
+            AlignmentContext alignmentContext = li.next();
+            Assert.assertEquals(alignmentContext.getLocation().getStart(),currentLocus,"Current locus returned by alignment context is incorrect");
+
+            if(currentLocus == firstLocus) {
+                List<GATKSAMRecord> readsAtLocus = alignmentContext.getBasePileup().getReads();
+                Assert.assertEquals(readsAtLocus.size(),1,"Wrong number of reads at locus " + currentLocus);
+                Assert.assertSame(readsAtLocus.get(0),leadingRead,"leadingRead absent from pileup at locus " + currentLocus);
+            }
+            else if(currentLocus == secondLocus) {
+                List<GATKSAMRecord> readsAtLocus = alignmentContext.getBasePileup().getReads();
+                Assert.assertEquals(readsAtLocus.size(),1,"Wrong number of reads at locus " + currentLocus);
+                Assert.assertSame(readsAtLocus.get(0),fullMatchAfterIndel,"fullMatchAfterIndel absent from pileup at locus " + currentLocus);
+            }
+
+            currentLocus++;
+            numAlignmentContextsFound++;
+        }
+
+        Assert.assertEquals(numAlignmentContextsFound, 2, "Found incorrect number of alignment contexts");
+    }
+
+    /**
+     * Test to make sure that reads supporting only an indel (example cigar string: 76I) are represented properly
+     */
+    @Test(enabled = false && ! DEBUG)
+    public void testWholeIndelReadRepresentedTest() {
+        final int firstLocus = 44367788, secondLocus = firstLocus + 1;
+
+        GATKSAMRecord read1 = ArtificialSAMUtils.createArtificialRead(header,"read1",0,secondLocus,1);
+        read1.setReadBases(Utils.dupBytes((byte) 'A', 1));
+        read1.setBaseQualities(Utils.dupBytes((byte) '@', 1));
+        read1.setCigarString("1I");
+
+        List<GATKSAMRecord> reads = Arrays.asList(read1);
+
+        // create the iterator by state with the fake reads and fake records
+        li = makeLTBS(reads, createTestReadProperties());
+
+        while(li.hasNext()) {
+            AlignmentContext alignmentContext = li.next();
+            ReadBackedPileup p = alignmentContext.getBasePileup();
+            Assert.assertTrue(p.getNumberOfElements() == 1);
+            // TODO -- fix tests
+//            PileupElement pe = p.iterator().next();
+//            Assert.assertTrue(pe.isBeforeInsertion());
+//            Assert.assertFalse(pe.isAfterInsertion());
+//            Assert.assertEquals(pe.getBasesOfImmediatelyFollowingInsertion(), "A");
+        }
+
+        GATKSAMRecord read2 = ArtificialSAMUtils.createArtificialRead(header,"read2",0,secondLocus,10);
+        read2.setReadBases(Utils.dupBytes((byte) 'A', 10));
+        read2.setBaseQualities(Utils.dupBytes((byte) '@', 10));
+        read2.setCigarString("10I");
+
+        reads = Arrays.asList(read2);
+
+        // create the iterator by state with the fake reads and fake records
+        li = makeLTBS(reads, createTestReadProperties());
+
+        while(li.hasNext()) {
+            AlignmentContext alignmentContext = li.next();
+            ReadBackedPileup p = alignmentContext.getBasePileup();
+            Assert.assertTrue(p.getNumberOfElements() == 1);
+            // TODO -- fix tests
+//            PileupElement pe = p.iterator().next();
+//            Assert.assertTrue(pe.isBeforeInsertion());
+//            Assert.assertFalse(pe.isAfterInsertion());
+//            Assert.assertEquals(pe.getBasesOfImmediatelyFollowingInsertion(), "AAAAAAAAAA");
+        }
+    }
+
+
+    /////////////////////////////////////////////
+    // get event length and bases calculations //
+    /////////////////////////////////////////////
+
+    @DataProvider(name = "IndelLengthAndBasesTest")
+    public Object[][] makeIndelLengthAndBasesTest() {
+        final String EVENT_BASES = "ACGTACGTACGT";
+        final List<Object[]> tests = new LinkedList<Object[]>();
+
+        for ( int eventSize = 1; eventSize < 10; eventSize++ ) {
+            for ( final CigarOperator indel : Arrays.asList(CigarOperator.D, CigarOperator.I) ) {
+                final String cigar = String.format("2M%d%s1M", eventSize, indel.toString());
+                final String eventBases = indel == CigarOperator.D ? "" : EVENT_BASES.substring(0, eventSize);
+                final int readLength = 3 + eventBases.length();
+
+                GATKSAMRecord read = ArtificialSAMUtils.createArtificialRead(header, "read", 0, 1, readLength);
+                read.setReadBases(("TT" + eventBases + "A").getBytes());
+                final byte[] quals = new byte[readLength];
+                for ( int i = 0; i < readLength; i++ )
+                    quals[i] = (byte)(i % QualityUtils.MAX_SAM_QUAL_SCORE);
+                read.setBaseQualities(quals);
+                read.setCigarString(cigar);
+
+                tests.add(new Object[]{read, indel, eventSize, eventBases.equals("") ? null : eventBases});
+            }
+        }
+
+        return tests.toArray(new Object[][]{});
+    }
+
+    @Test(enabled = true && ! DEBUG, dataProvider = "IndelLengthAndBasesTest")
+    public void testIndelLengthAndBasesTest(GATKSAMRecord read, final CigarOperator op, final int eventSize, final String eventBases) {
+        // create the iterator by state with the fake reads and fake records
+        li = makeLTBS(Arrays.asList((GATKSAMRecord)read), createTestReadProperties());
+
+        Assert.assertTrue(li.hasNext());
+
+        final PileupElement firstMatch = getFirstPileupElement(li.next());
+
+        Assert.assertEquals(firstMatch.getLengthOfImmediatelyFollowingIndel(), 0, "Length != 0 for site not adjacent to indel");
+        Assert.assertEquals(firstMatch.getBasesOfImmediatelyFollowingInsertion(), null, "Getbases of following event should be null at non-adajenct event");
+
+        Assert.assertTrue(li.hasNext());
+
+        final PileupElement pe = getFirstPileupElement(li.next());
+
+        if ( op == CigarOperator.D )
+            Assert.assertTrue(pe.isBeforeDeletionStart());
+        else
+            Assert.assertTrue(pe.isBeforeInsertion());
+
+        Assert.assertEquals(pe.getLengthOfImmediatelyFollowingIndel(), eventSize, "Length of event failed");
+        Assert.assertEquals(pe.getBasesOfImmediatelyFollowingInsertion(), eventBases, "Getbases of following event failed");
+    }
+
+    private PileupElement getFirstPileupElement(final AlignmentContext context) {
+        final ReadBackedPileup p = context.getBasePileup();
+        Assert.assertEquals(p.getNumberOfElements(), 1);
+        return p.iterator().next();
+    }
+
+    ////////////////////////////////////////////
+    // comprehensive LIBS/PileupElement tests //
+    ////////////////////////////////////////////
+
+    @DataProvider(name = "MyLIBSTest")
+    public Object[][] makeLIBSTest() {
+        final List<Object[]> tests = new LinkedList<Object[]>();
+
+//        tests.add(new Object[]{new LIBSTest("2=2D2=2X", 1)});
+//        return tests.toArray(new Object[][]{});
+
+        return createLIBSTests(
+                Arrays.asList(1, 2),
+                Arrays.asList(1, 2, 3, 4));
+
+//        return createLIBSTests(
+//                Arrays.asList(2),
+//                Arrays.asList(3));
+    }
+
+    @Test(enabled = ! DEBUG, dataProvider = "MyLIBSTest")
+    public void testLIBS(LIBSTest params) {
+        // create the iterator by state with the fake reads and fake records
+        final GATKSAMRecord read = params.makeRead();
+        li = makeLTBS(Arrays.asList((GATKSAMRecord)read), createTestReadProperties());
+        final LIBS_position tester = new LIBS_position(read);
+
+        int bpVisited = 0;
+        int lastOffset = 0;
+        while ( li.hasNext() ) {
+            bpVisited++;
+
+            AlignmentContext alignmentContext = li.next();
+            ReadBackedPileup p = alignmentContext.getBasePileup();
+            Assert.assertEquals(p.getNumberOfElements(), 1);
+            PileupElement pe = p.iterator().next();
+
+            Assert.assertEquals(p.getNumberOfDeletions(), pe.isDeletion() ? 1 : 0, "wrong number of deletions in the pileup");
+            Assert.assertEquals(p.getNumberOfMappingQualityZeroReads(), pe.getRead().getMappingQuality() == 0 ? 1 : 0, "wront number of mapq reads in the pileup");
+
+            tester.stepForwardOnGenome();
+
+            if ( ! hasNeighboringPaddedOps(params.getElements(), pe.getCurrentCigarOffset()) ) {
+                Assert.assertEquals(pe.isBeforeDeletionStart(), tester.isBeforeDeletionStart, "before deletion start failure");
+                Assert.assertEquals(pe.isAfterDeletionEnd(), tester.isAfterDeletionEnd, "after deletion end failure");
+            }
+
+            Assert.assertEquals(pe.isBeforeInsertion(), tester.isBeforeInsertion, "before insertion failure");
+            Assert.assertEquals(pe.isAfterInsertion(), tester.isAfterInsertion, "after insertion failure");
+            Assert.assertEquals(pe.isNextToSoftClip(), tester.isNextToSoftClip, "next to soft clip failure");
+
+            Assert.assertTrue(pe.getOffset() >= lastOffset, "Somehow read offsets are decreasing: lastOffset " + lastOffset + " current " + pe.getOffset());
+            Assert.assertEquals(pe.getOffset(), tester.getCurrentReadOffset(), "Read offsets are wrong at " + bpVisited);
+
+            Assert.assertEquals(pe.getCurrentCigarElement(), read.getCigar().getCigarElement(tester.currentOperatorIndex), "CigarElement index failure");
+            Assert.assertEquals(pe.getOffsetInCurrentCigar(), tester.getCurrentPositionOnOperatorBase0(), "CigarElement index failure");
+
+            Assert.assertEquals(read.getCigar().getCigarElement(pe.getCurrentCigarOffset()), pe.getCurrentCigarElement(), "Current cigar element isn't what we'd get from the read itself");
+
+            Assert.assertTrue(pe.getOffsetInCurrentCigar() >= 0, "Offset into current cigar too small");
+            Assert.assertTrue(pe.getOffsetInCurrentCigar() < pe.getCurrentCigarElement().getLength(), "Offset into current cigar too big");
+
+            Assert.assertEquals(pe.getOffset(), tester.getCurrentReadOffset(), "Read offset failure");
+            lastOffset = pe.getOffset();
+        }
+
+        final int expectedBpToVisit = read.getAlignmentEnd() - read.getAlignmentStart() + 1;
+        Assert.assertEquals(bpVisited, expectedBpToVisit, "Didn't visit the expected number of bp");
+    }
+
+    // ------------------------------------------------------------
+    //
+    // Tests for keeping reads
+    //
+    // ------------------------------------------------------------
+
+    @DataProvider(name = "LIBS_ComplexPileupTests")
+    public Object[][] makeLIBS_ComplexPileupTests() {
+        final List<Object[]> tests = new LinkedList<Object[]>();
+
+        for ( final int downsampleTo : Arrays.asList(-1, 1, 2, 5, 10, 30)) {
+            for ( final int nReadsPerLocus : Arrays.asList(1, 10, 60) ) {
+                for ( final int nLoci : Arrays.asList(1, 10, 25) ) {
+                    for ( final int nSamples : Arrays.asList(1, 2, 10) ) {
+                        for ( final boolean keepReads : Arrays.asList(true, false) ) {
+                            for ( final boolean grabReadsAfterEachCycle : Arrays.asList(true, false) ) {
+//        for ( final int downsampleTo : Arrays.asList(1)) {
+//            for ( final int nReadsPerLocus : Arrays.asList(1) ) {
+//                for ( final int nLoci : Arrays.asList(1) ) {
+//                    for ( final int nSamples : Arrays.asList(1) ) {
+//                        for ( final boolean keepReads : Arrays.asList(true) ) {
+//                            for ( final boolean grabReadsAfterEachCycle : Arrays.asList(true) ) {
+                                tests.add(new Object[]{nReadsPerLocus, nLoci, nSamples,
+                                        keepReads, grabReadsAfterEachCycle,
+                                        downsampleTo});
+                            }
+                        }
+                    }
+                }
+            }
+        }
+
+        return tests.toArray(new Object[][]{});
+    }
+
+    @Test(enabled = true && ! DEBUG, dataProvider = "LIBS_ComplexPileupTests")
+    public void testLIBS_ComplexPileupTests(final int nReadsPerLocus,
+                                            final int nLoci,
+                                            final int nSamples,
+                                            final boolean keepReads,
+                                            final boolean grabReadsAfterEachCycle,
+                                            final int downsampleTo) {
+        //logger.warn(String.format("testLIBSKeepSubmittedReads %d %d %d %b %b %b", nReadsPerLocus, nLoci, nSamples, keepReads, grabReadsAfterEachCycle, downsample));
+        final int readLength = 10;
+
+        final boolean downsample = downsampleTo != -1;
+        final DownsamplingMethod downsampler = downsample
+                ? new DownsamplingMethod(DownsampleType.BY_SAMPLE, downsampleTo, null)
+                : new DownsamplingMethod(DownsampleType.NONE, null, null);
+
+        final ArtificialBAMBuilder bamBuilder = new ArtificialBAMBuilder(header.getSequenceDictionary(), nReadsPerLocus, nLoci);
+        bamBuilder.createAndSetHeader(nSamples).setReadLength(readLength).setAlignmentStart(1);
+
+        final List<GATKSAMRecord> reads = bamBuilder.makeReads();
+        li = new LocusIteratorByState(new FakeCloseableIterator<GATKSAMRecord>(reads.iterator()),
+                createTestReadProperties(downsampler, keepReads),
+                genomeLocParser,
+                bamBuilder.getSamples());
+
+        final Set<GATKSAMRecord> seenSoFar = new HashSet<GATKSAMRecord>();
+        final Set<GATKSAMRecord> keptReads = new HashSet<GATKSAMRecord>();
+        int bpVisited = 0;
+        while ( li.hasNext() ) {
+            bpVisited++;
+            final AlignmentContext alignmentContext = li.next();
+            final ReadBackedPileup p = alignmentContext.getBasePileup();
+
+            AssertWellOrderedPileup(p);
+
+            if ( downsample ) {
+                // just not a safe test
+                //Assert.assertTrue(p.getNumberOfElements() <= maxDownsampledCoverage * nSamples, "Too many reads at locus after downsampling");
+            } else {
+                final int minPileupSize = nReadsPerLocus * nSamples;
+                Assert.assertTrue(p.getNumberOfElements() >= minPileupSize);
+            }
+
+            // the number of reads starting here
+            int nReadsStartingHere = 0;
+            for ( final GATKSAMRecord read : p.getReads() )
+                if ( read.getAlignmentStart() == alignmentContext.getPosition() )
+                    nReadsStartingHere++;
+
+            // we can have no more than maxDownsampledCoverage per sample
+            final int maxCoveragePerLocus = downsample ? downsampleTo : nReadsPerLocus;
+            Assert.assertTrue(nReadsStartingHere <= maxCoveragePerLocus * nSamples);
+
+            seenSoFar.addAll(p.getReads());
+            if ( keepReads && grabReadsAfterEachCycle ) {
+                final List<GATKSAMRecord> locusReads = li.transferReadsFromAllPreviousPileups();
+
+
+                if ( downsample ) {
+                    // with downsampling we might have some reads here that were downsampled away
+                    // in the pileup.  We want to ensure that no more than the max coverage per sample is added
+                    Assert.assertTrue(locusReads.size() >= nReadsStartingHere);
+                    Assert.assertTrue(locusReads.size() <= maxCoveragePerLocus * nSamples);
+                } else {
+                    Assert.assertEquals(locusReads.size(), nReadsStartingHere);
+                }
+                keptReads.addAll(locusReads);
+
+                // check that all reads we've seen so far are in our keptReads
+                for ( final GATKSAMRecord read : seenSoFar ) {
+                    Assert.assertTrue(keptReads.contains(read), "A read that appeared in a pileup wasn't found in the kept reads: " + read);
+                }
+            }
+
+            if ( ! keepReads )
+                Assert.assertTrue(li.getReadsFromAllPreviousPileups().isEmpty(), "Not keeping reads but the underlying list of reads isn't empty");
+        }
+
+        if ( keepReads && ! grabReadsAfterEachCycle )
+            keptReads.addAll(li.transferReadsFromAllPreviousPileups());
+
+        if ( ! downsample ) { // downsampling may drop loci
+            final int expectedBpToVisit = nLoci + readLength - 1;
+            Assert.assertEquals(bpVisited, expectedBpToVisit, "Didn't visit the expected number of bp");
+        }
+
+        if ( keepReads ) {
+            // check we have the right number of reads
+            final int totalReads = nLoci * nReadsPerLocus * nSamples;
+            if ( ! downsample ) { // downsampling may drop reads
+                Assert.assertEquals(keptReads.size(), totalReads, "LIBS didn't keep the right number of reads during the traversal");
+
+                // check that the order of reads is the same as in our read list
+                for ( int i = 0; i < reads.size(); i++ ) {
+                    final GATKSAMRecord inputRead = reads.get(i);
+                    final GATKSAMRecord keptRead = reads.get(i);
+                    Assert.assertSame(keptRead, inputRead, "Input reads and kept reads differ at position " + i);
+                }
+            } else {
+                Assert.assertTrue(keptReads.size() <= totalReads, "LIBS didn't keep the right number of reads during the traversal");
+            }
+
+            // check uniqueness
+            final Set<String> readNames = new HashSet<String>();
+            for ( final GATKSAMRecord read : keptReads ) {
+                Assert.assertFalse(readNames.contains(read.getReadName()), "Found duplicate reads in the kept reads");
+                readNames.add(read.getReadName());
+            }
+
+            // check that all reads we've seen are in our keptReads
+            for ( final GATKSAMRecord read : seenSoFar ) {
+                Assert.assertTrue(keptReads.contains(read), "A read that appeared in a pileup wasn't found in the kept reads: " + read);
+            }
+
+            if ( ! downsample ) {
+                // check that every read in the list of keep reads occurred at least once in one of the pileups
+                for ( final GATKSAMRecord keptRead : keptReads ) {
+                    Assert.assertTrue(seenSoFar.contains(keptRead), "There's a read " + keptRead + " in our keptReads list that never appeared in any pileup");
+                }
+            }
+        }
+    }
+
+    private void AssertWellOrderedPileup(final ReadBackedPileup pileup) {
+        if ( ! pileup.isEmpty() ) {
+            int leftMostPos = -1;
+
+            for ( final PileupElement pe : pileup ) {
+                Assert.assertTrue(pileup.getLocation().getContig().equals(pe.getRead().getReferenceName()), "ReadBackedPileup contains an element " + pe + " that's on a different contig than the pileup itself");
+                Assert.assertTrue(pe.getRead().getAlignmentStart() >= leftMostPos,
+                        "ReadBackedPileup contains an element " + pe + " whose read's alignment start " + pe.getRead().getAlignmentStart()
+                                + " occurs before the leftmost position we've seen previously " + leftMostPos);
+            }
+        }
+    }
+
+    // ---------------------------------------------------------------------------
+    // make sure that downsampling isn't holding onto a bazillion reads
+    //
+    @DataProvider(name = "LIBS_NotHoldingTooManyReads")
+    public Object[][] makeLIBS_NotHoldingTooManyReads() {
+        final List<Object[]> tests = new LinkedList<Object[]>();
+
+        for ( final int downsampleTo : Arrays.asList(1, 10)) {
+            for ( final int nReadsPerLocus : Arrays.asList(100, 1000, 10000, 100000) ) {
+                for ( final int payloadInBytes : Arrays.asList(0, 1024, 1024*1024) ) {
+                    tests.add(new Object[]{nReadsPerLocus, downsampleTo, payloadInBytes});
+                }
+            }
+        }
+
+        return tests.toArray(new Object[][]{});
+    }
+
+    @Test(enabled = true && ! DEBUG, dataProvider = "LIBS_NotHoldingTooManyReads")
+//    @Test(enabled = true, dataProvider = "LIBS_NotHoldingTooManyReads", timeOut = 100000)
+    public void testLIBS_NotHoldingTooManyReads(final int nReadsPerLocus, final int downsampleTo, final int payloadInBytes) {
+        logger.warn(String.format("testLIBS_NotHoldingTooManyReads %d %d %d", nReadsPerLocus, downsampleTo, payloadInBytes));
+        final int readLength = 10;
+
+        final SAMFileHeader header = ArtificialSAMUtils.createArtificialSamHeader(1, 1, 100000);
+        final int nSamples = 1;
+        final List<String> samples = new ArrayList<String>(nSamples);
+        for ( int i = 0; i < nSamples; i++ ) {
+            final GATKSAMReadGroupRecord rg = new GATKSAMReadGroupRecord("rg" + i);
+            final String sample = "sample" + i;
+            samples.add(sample);
+            rg.setSample(sample);
+            rg.setPlatform(NGSPlatform.ILLUMINA.getDefaultPlatform());
+            header.addReadGroup(rg);
+        }
+
+        final boolean downsample = downsampleTo != -1;
+        final DownsamplingMethod downsampler = downsample
+                ? new DownsamplingMethod(DownsampleType.BY_SAMPLE, downsampleTo, null)
+                : new DownsamplingMethod(DownsampleType.NONE, null, null);
+
+        // final List<GATKSAMRecord> reads = ArtificialSAMUtils.createReadStream(nReadsPerLocus, nLoci, header, 1, readLength);
+
+        final WeakReadTrackingIterator iterator = new WeakReadTrackingIterator(nReadsPerLocus, readLength, payloadInBytes, header);
+
+        li = new LocusIteratorByState(iterator,
+                createTestReadProperties(downsampler, false),
+                genomeLocParser,
+                samples);
+
+        while ( li.hasNext() ) {
+            final AlignmentContext next = li.next();
+            Assert.assertTrue(next.getBasePileup().getNumberOfElements() <= downsampleTo, "Too many elements in pileup " + next);
+            // TODO -- assert that there are <= X reads in memory after GC for some X
+        }
+    }
+
+    private static class WeakReadTrackingIterator implements Iterator<GATKSAMRecord> {
+        final int nReads, readLength, payloadInBytes;
+        int readI = 0;
+        final SAMFileHeader header;
+
+        private WeakReadTrackingIterator(int nReads, int readLength, final int payloadInBytes, final SAMFileHeader header) {
+            this.nReads = nReads;
+            this.readLength = readLength;
+            this.header = header;
+            this.payloadInBytes = payloadInBytes;
+        }
+
+        @Override public boolean hasNext() { return readI < nReads; }
+        @Override public void remove() { throw new UnsupportedOperationException("no remove"); }
+
+        @Override
+        public GATKSAMRecord next() {
+            readI++;
+            return makeRead();
+        }
+
+        private GATKSAMRecord makeRead() {
+            final SAMReadGroupRecord rg = header.getReadGroups().get(0);
+            final String readName = String.format("%s.%d.%s", "read", readI, rg.getId());
+            final GATKSAMRecord read = ArtificialSAMUtils.createArtificialRead(header, readName, 0, 1, readLength);
+            read.setReadGroup(new GATKSAMReadGroupRecord(rg));
+            if ( payloadInBytes > 0 )
+                // add a payload byte array to push memory use per read even higher
+                read.setAttribute("PL", new byte[payloadInBytes]);
+            return read;
+        }
+    }
+
+    // ---------------------------------------------------------------------------
+    //
+    // make sure that adapter clipping is working properly in LIBS
+    //
+    // ---------------------------------------------------------------------------
+    @DataProvider(name = "AdapterClippingTest")
+    public Object[][] makeAdapterClippingTest() {
+        final List<Object[]> tests = new LinkedList<Object[]>();
+
+        final int start = 10;
+        for ( final int goodBases : Arrays.asList(10, 20, 30) ) {
+            for ( final int nClips : Arrays.asList(0, 1, 2, 10)) {
+                for ( final boolean onLeft : Arrays.asList(true, false) ) {
+                    final int readLength = nClips + goodBases;
+                    GATKSAMRecord read = ArtificialSAMUtils.createArtificialRead(header, "read1" , 0, start, readLength);
+                    read.setProperPairFlag(true);
+                    read.setReadPairedFlag(true);
+                    read.setReadUnmappedFlag(false);
+                    read.setMateUnmappedFlag(false);
+                    read.setReadBases(Utils.dupBytes((byte) 'A', readLength));
+                    read.setBaseQualities(Utils.dupBytes((byte) '@', readLength));
+                    read.setCigarString(readLength + "M");
+
+                    if ( onLeft ) {
+                        read.setReadNegativeStrandFlag(true);
+                        read.setMateNegativeStrandFlag(false);
+                        read.setMateAlignmentStart(start + nClips);
+                        read.setInferredInsertSize(readLength);
+                        tests.add(new Object[]{nClips, goodBases, 0, read});
+                    } else {
+                        read.setReadNegativeStrandFlag(false);
+                        read.setMateNegativeStrandFlag(true);
+                        read.setMateAlignmentStart(start - 1);
+                        read.setInferredInsertSize(goodBases - 1);
+                        tests.add(new Object[]{0, goodBases, nClips, read});
+                    }
+                }
+            }
+        }
+
+        return tests.toArray(new Object[][]{});
+    }
+
+    @Test(enabled = true, dataProvider = "AdapterClippingTest")
+    public void testAdapterClipping(final int nClipsOnLeft, final int nReadContainingPileups, final int nClipsOnRight, final GATKSAMRecord read) {
+
+        li = new LocusIteratorByState(new FakeCloseableIterator<>(Collections.singletonList(read).iterator()),
+                createTestReadProperties(DownsamplingMethod.NONE, false),
+                genomeLocParser,
+                LocusIteratorByState.sampleListForSAMWithoutReadGroups());
+
+        int expectedPos = read.getAlignmentStart() + nClipsOnLeft;
+        int nPileups = 0;
+        while ( li.hasNext() ) {
+            final AlignmentContext next = li.next();
+            Assert.assertEquals(next.getLocation().getStart(), expectedPos);
+            nPileups++;
+            expectedPos++;
+        }
+
+        final int nExpectedPileups = nReadContainingPileups;
+        Assert.assertEquals(nPileups, nExpectedPileups, "Wrong number of pileups seen");
+    }
+}
diff --git a/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/utils/locusiterator/PerSampleReadStateManagerUnitTest.java b/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/utils/locusiterator/PerSampleReadStateManagerUnitTest.java
new file mode 100644
index 0000000..4a760b5
--- /dev/null
+++ b/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/utils/locusiterator/PerSampleReadStateManagerUnitTest.java
@@ -0,0 +1,188 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.utils.locusiterator;
+
+import htsjdk.samtools.SAMRecord;
+import org.broadinstitute.gatk.utils.MathUtils;
+import org.broadinstitute.gatk.utils.sam.ArtificialSAMUtils;
+import org.broadinstitute.gatk.utils.sam.GATKSAMRecord;
+import org.testng.Assert;
+import org.testng.annotations.DataProvider;
+import org.testng.annotations.Test;
+
+import java.util.*;
+
+/**
+ * testing of the new (non-legacy) version of LocusIteratorByState
+ */
+public class PerSampleReadStateManagerUnitTest extends LocusIteratorByStateBaseTest {
+    private class PerSampleReadStateManagerTest extends TestDataProvider {
+        private List<Integer> readCountsPerAlignmentStart;
+        private List<SAMRecord> reads;
+        private List<ArrayList<AlignmentStateMachine>> recordStatesByAlignmentStart;
+        private int removalInterval;
+
+        public PerSampleReadStateManagerTest( List<Integer> readCountsPerAlignmentStart, int removalInterval ) {
+            super(PerSampleReadStateManagerTest.class);
+
+            this.readCountsPerAlignmentStart = readCountsPerAlignmentStart;
+            this.removalInterval = removalInterval;
+
+            reads = new ArrayList<SAMRecord>();
+            recordStatesByAlignmentStart = new ArrayList<ArrayList<AlignmentStateMachine>>();
+
+            setName(String.format("%s: readCountsPerAlignmentStart: %s  removalInterval: %d",
+                    getClass().getSimpleName(), readCountsPerAlignmentStart, removalInterval));
+        }
+
+        public void run() {
+            PerSampleReadStateManager perSampleReadStateManager = new PerSampleReadStateManager(LocusIteratorByState.NO_DOWNSAMPLING);
+
+            makeReads();
+
+            for ( ArrayList<AlignmentStateMachine> stackRecordStates : recordStatesByAlignmentStart ) {
+                perSampleReadStateManager.addStatesAtNextAlignmentStart(new LinkedList<AlignmentStateMachine>(stackRecordStates));
+            }
+
+            // read state manager should have the right number of reads
+            Assert.assertEquals(reads.size(), perSampleReadStateManager.size());
+
+            Iterator<SAMRecord> originalReadsIterator = reads.iterator();
+            Iterator<AlignmentStateMachine> recordStateIterator = perSampleReadStateManager.iterator();
+            int recordStateCount = 0;
+            int numReadStatesRemoved = 0;
+
+            // Do a first-pass validation of the record state iteration by making sure we get back everything we
+            // put in, in the same order, doing any requested removals of read states along the way
+            while ( recordStateIterator.hasNext() ) {
+                AlignmentStateMachine readState = recordStateIterator.next();
+                recordStateCount++;
+                SAMRecord readFromPerSampleReadStateManager = readState.getRead();
+
+                Assert.assertTrue(originalReadsIterator.hasNext());
+                SAMRecord originalRead = originalReadsIterator.next();
+
+                // The read we get back should be literally the same read in memory as we put in
+                Assert.assertTrue(originalRead == readFromPerSampleReadStateManager);
+
+                // If requested, remove a read state every removalInterval states
+                if ( removalInterval > 0 && recordStateCount % removalInterval == 0 ) {
+                    recordStateIterator.remove();
+                    numReadStatesRemoved++;
+                }
+            }
+
+            Assert.assertFalse(originalReadsIterator.hasNext());
+
+            // If we removed any read states, do a second pass through the read states to make sure the right
+            // states were removed
+            if ( numReadStatesRemoved > 0 ) {
+                Assert.assertEquals(perSampleReadStateManager.size(), reads.size() - numReadStatesRemoved);
+
+                originalReadsIterator = reads.iterator();
+                recordStateIterator = perSampleReadStateManager.iterator();
+                int readCount = 0;
+                int readStateCount = 0;
+
+                // Match record states with the reads that should remain after removal
+                while ( recordStateIterator.hasNext() ) {
+                    AlignmentStateMachine readState = recordStateIterator.next();
+                    readStateCount++;
+                    SAMRecord readFromPerSampleReadStateManager = readState.getRead();
+
+                    Assert.assertTrue(originalReadsIterator.hasNext());
+
+                    SAMRecord originalRead = originalReadsIterator.next();
+                    readCount++;
+
+                    if ( readCount % removalInterval == 0 ) {
+                        originalRead = originalReadsIterator.next(); // advance to next read, since the previous one should have been discarded
+                        readCount++;
+                    }
+
+                    // The read we get back should be literally the same read in memory as we put in (after accounting for removals)
+                    Assert.assertTrue(originalRead == readFromPerSampleReadStateManager);
+                }
+
+                Assert.assertEquals(readStateCount, reads.size() - numReadStatesRemoved);
+            }
+
+            // Allow memory used by this test to be reclaimed
+            readCountsPerAlignmentStart = null;
+            reads = null;
+            recordStatesByAlignmentStart = null;
+        }
+
+        private void makeReads() {
+            int alignmentStart = 1;
+
+            for ( int readsThisStack : readCountsPerAlignmentStart ) {
+                ArrayList<GATKSAMRecord> stackReads = new ArrayList<GATKSAMRecord>(ArtificialSAMUtils.createStackOfIdenticalArtificialReads(readsThisStack, header, "foo", 0, alignmentStart, MathUtils.randomIntegerInRange(50, 100)));
+                ArrayList<AlignmentStateMachine> stackRecordStates = new ArrayList<AlignmentStateMachine>();
+
+                for ( GATKSAMRecord read : stackReads ) {
+                    stackRecordStates.add(new AlignmentStateMachine(read));
+                }
+
+                reads.addAll(stackReads);
+                recordStatesByAlignmentStart.add(stackRecordStates);
+            }
+        }
+    }
+
+    @DataProvider(name = "PerSampleReadStateManagerTestDataProvider")
+    public Object[][] createPerSampleReadStateManagerTests() {
+        for ( List<Integer> thisTestReadStateCounts : Arrays.asList( Arrays.asList(1),
+                Arrays.asList(2),
+                Arrays.asList(10),
+                Arrays.asList(1, 1),
+                Arrays.asList(2, 2),
+                Arrays.asList(10, 10),
+                Arrays.asList(1, 10),
+                Arrays.asList(10, 1),
+                Arrays.asList(1, 1, 1),
+                Arrays.asList(2, 2, 2),
+                Arrays.asList(10, 10, 10),
+                Arrays.asList(1, 1, 1, 1, 1, 1),
+                Arrays.asList(10, 10, 10, 10, 10, 10),
+                Arrays.asList(1, 2, 10, 1, 2, 10)
+        ) ) {
+
+            for ( int removalInterval : Arrays.asList(0, 2, 3) ) {
+                new PerSampleReadStateManagerTest(thisTestReadStateCounts, removalInterval);
+            }
+        }
+
+        return PerSampleReadStateManagerTest.getTests(PerSampleReadStateManagerTest.class);
+    }
+
+    @Test(dataProvider = "PerSampleReadStateManagerTestDataProvider")
+    public void runPerSampleReadStateManagerTest( PerSampleReadStateManagerTest test ) {
+        logger.warn("Running test: " + test);
+
+        test.run();
+    }
+}
diff --git a/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/utils/nanoScheduler/InputProducerUnitTest.java b/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/utils/nanoScheduler/InputProducerUnitTest.java
new file mode 100644
index 0000000..d99a079
--- /dev/null
+++ b/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/utils/nanoScheduler/InputProducerUnitTest.java
@@ -0,0 +1,94 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.utils.nanoScheduler;
+
+import org.broadinstitute.gatk.utils.BaseTest;
+import org.testng.Assert;
+import org.testng.annotations.DataProvider;
+import org.testng.annotations.Test;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+/**
+* UnitTests for the InputProducer
+*
+* User: depristo
+* Date: 8/24/12
+* Time: 11:25 AM
+* To change this template use File | Settings | File Templates.
+*/
+public class InputProducerUnitTest extends BaseTest {
+    @DataProvider(name = "InputProducerTest")
+    public Object[][] createInputProducerTest() {
+        List<Object[]> tests = new ArrayList<Object[]>();
+
+        for ( final int nElements : Arrays.asList(0, 1, 10, 100, 1000, 10000, 100000) ) {
+            for ( final int queueSize : Arrays.asList(1, 10, 100) ) {
+                tests.add(new Object[]{ nElements, queueSize });
+            }
+        }
+
+        return tests.toArray(new Object[][]{});
+    }
+
+    @Test(enabled = true, dataProvider = "InputProducerTest", timeOut = NanoSchedulerUnitTest.NANO_SCHEDULE_MAX_RUNTIME)
+    public void testInputProducer(final int nElements, final int queueSize) throws InterruptedException {
+        final List<Integer> elements = new ArrayList<Integer>(nElements);
+        for ( int i = 0; i < nElements; i++ ) elements.add(i);
+
+        final InputProducer<Integer> ip = new InputProducer<Integer>(elements.iterator());
+
+        Assert.assertFalse(ip.allInputsHaveBeenRead(), "InputProvider said that all inputs have been read, but I haven't started reading yet");
+        Assert.assertEquals(ip.getNumInputValues(), -1, "InputProvider told me that the queue was done, but I haven't started reading yet");
+
+        int lastValue = -1;
+        int nRead = 0;
+        while ( ip.hasNext() ) {
+            final int nTotalElements = ip.getNumInputValues();
+
+            if ( nRead < nElements )
+                Assert.assertEquals(nTotalElements, -1, "getNumInputValues should have returned -1 with not all elements read");
+            // note, cannot test else case because elements input could have emptied between calls
+
+            final InputProducer<Integer>.InputValue value = ip.next();
+            if ( value.isEOFMarker() ) {
+                Assert.assertEquals(nRead, nElements, "Number of input values " + nRead + " not all that are expected " + nElements);
+                break;
+            } else {
+                Assert.assertTrue(lastValue < value.getValue(), "Read values coming out of order!");
+                final int expected = lastValue + 1;
+                Assert.assertEquals((int)value.getValue(), expected, "Value observed " + value.getValue() + " not equal to the expected value " + expected);
+                nRead++;
+                lastValue = value.getValue();
+            }
+        }
+
+        Assert.assertTrue(ip.allInputsHaveBeenRead(), "InputProvider said that all inputs haven't been read, but I read them all");
+        Assert.assertEquals(ip.getNumInputValues(), nElements, "Wrong number of total elements getNumInputValues");
+    }
+}
diff --git a/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/utils/nanoScheduler/MapResultUnitTest.java b/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/utils/nanoScheduler/MapResultUnitTest.java
new file mode 100644
index 0000000..93105cd
--- /dev/null
+++ b/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/utils/nanoScheduler/MapResultUnitTest.java
@@ -0,0 +1,65 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.utils.nanoScheduler;
+
+import org.broadinstitute.gatk.utils.BaseTest;
+import org.testng.Assert;
+import org.testng.annotations.DataProvider;
+import org.testng.annotations.Test;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+/**
+* UnitTests for the InputProducer
+*
+* User: depristo
+* Date: 8/24/12
+* Time: 11:25 AM
+* To change this template use File | Settings | File Templates.
+*/
+public class MapResultUnitTest {
+    @DataProvider(name = "CompareTester")
+    public Object[][] createCompareTester() {
+        List<Object[]> tests = new ArrayList<Object[]>();
+
+        for ( int id1 = 0; id1 < 10; id1++ ) {
+            for ( int id2 = 0; id2 < 10; id2++ ) {
+                tests.add(new Object[]{ id1, id2, Integer.valueOf(id1).compareTo(id2)});
+            }
+        }
+
+        return tests.toArray(new Object[][]{});
+    }
+
+    @Test(enabled = true, dataProvider = "CompareTester")
+    public void testInputProducer(final int id1, final int id2, final int comp ) throws InterruptedException {
+        final MapResult<Integer> mr1 = new MapResult<Integer>(id1, id1);
+        final MapResult<Integer> mr2 = new MapResult<Integer>(id2, id2);
+        Assert.assertEquals(mr1.compareTo(mr2), comp, "Compare MapResultsUnitTest failed");
+    }
+}
diff --git a/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/utils/nanoScheduler/NanoSchedulerUnitTest.java b/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/utils/nanoScheduler/NanoSchedulerUnitTest.java
new file mode 100644
index 0000000..72636f0
--- /dev/null
+++ b/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/utils/nanoScheduler/NanoSchedulerUnitTest.java
@@ -0,0 +1,343 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.utils.nanoScheduler;
+
+import org.apache.log4j.BasicConfigurator;
+import org.broadinstitute.gatk.utils.BaseTest;
+import org.broadinstitute.gatk.utils.SimpleTimer;
+import org.broadinstitute.gatk.utils.exceptions.ReviewedGATKException;
+import org.testng.Assert;
+import org.testng.annotations.BeforeSuite;
+import org.testng.annotations.DataProvider;
+import org.testng.annotations.Test;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Iterator;
+import java.util.List;
+
+/**
+ * UnitTests for the NanoScheduler
+ *
+ * User: depristo
+ * Date: 8/24/12
+ * Time: 11:25 AM
+ * To change this template use File | Settings | File Templates.
+ */
+public class NanoSchedulerUnitTest extends BaseTest {
+    private final static boolean DEBUG = false;
+    private final static boolean debug = false;
+    public static final int NANO_SCHEDULE_MAX_RUNTIME = 30000;
+    public static final int EXCEPTION_THROWING_TEST_TIMEOUT = 10000;
+
+    private static class Map2x implements NSMapFunction<Integer, Integer> {
+        @Override public Integer apply(Integer input) { return input * 2; }
+    }
+
+    private static void maybeDelayMe(final int input) {
+        try {
+            if ( input % 7 == 0 ) {
+                final int milliToSleep = (input % 10);
+                //System.out.printf("Sleeping %d millseconds%n", milliToSleep);
+                Thread.sleep(milliToSleep);
+            }
+        } catch ( InterruptedException ex ) {
+            throw new RuntimeException(ex);
+        }
+    }
+
+    private static class Map2xWithDelays extends Map2x {
+        @Override public Integer apply(Integer input) {
+            maybeDelayMe(input);
+            return input * 2;
+        }
+    }
+
+    private static class ReduceSum implements NSReduceFunction<Integer, Integer> {
+        int prevOne = Integer.MIN_VALUE;
+
+        @Override public Integer apply(Integer one, Integer sum) {
+            Assert.assertTrue(prevOne < one, "Reduce came in out of order.  Prev " + prevOne + " cur " + one);
+            return one + sum;
+        }
+    }
+
+    private static class ProgressCallback implements NSProgressFunction<Integer> {
+        int callBacks = 0;
+
+        @Override
+        public void progress(Integer lastMapInput) {
+            callBacks++;
+        }
+    }
+
+
+    private static int sum2x(final int start, final int end) {
+        int sum = 0;
+        for ( int i = start; i < end; i++ )
+            sum += 2 * i;
+        return sum;
+    }
+
+    private static class NanoSchedulerBasicTest extends TestDataProvider {
+        final int bufferSize, nThreads, start, end, expectedResult;
+        final boolean addDelays;
+
+        public NanoSchedulerBasicTest(final int bufferSize, final int nThreads, final int start, final int end, final boolean addDelays) {
+            super(NanoSchedulerBasicTest.class);
+            this.bufferSize = bufferSize;
+            this.nThreads = nThreads;
+            this.start = start;
+            this.end = end;
+            this.expectedResult = sum2x(start, end);
+            this.addDelays = addDelays;
+            setName(String.format("%s nt=%d buf=%d start=%d end=%d sum=%d delays=%b",
+                    getClass().getSimpleName(), nThreads, bufferSize, start, end, expectedResult, addDelays));
+        }
+
+        public Iterator<Integer> makeReader() {
+            final List<Integer> ints = new ArrayList<Integer>();
+            for ( int i = start; i < end; i++ )
+                ints.add(i);
+            return ints.iterator();
+        }
+
+        public int nExpectedCallbacks() {
+            int nElements = Math.max(end - start, 0);
+            return nElements / bufferSize / NanoScheduler.UPDATE_PROGRESS_FREQ;
+        }
+
+        public Map2x makeMap() { return addDelays ? new Map2xWithDelays() : new Map2x(); }
+        public Integer initReduce() { return 0; }
+        public ReduceSum makeReduce() { return new ReduceSum(); }
+
+        public NanoScheduler<Integer, Integer, Integer> makeScheduler() {
+            final NanoScheduler <Integer, Integer, Integer> nano;
+            if ( bufferSize == -1 )
+                nano = new NanoScheduler<Integer, Integer, Integer>(nThreads);
+            else
+                nano = new NanoScheduler<Integer, Integer, Integer>(bufferSize, nThreads);
+
+            nano.setDebug(debug);
+            return nano;
+        }
+    }
+
+    static NanoSchedulerBasicTest exampleTest = null;
+    static NanoSchedulerBasicTest exampleTestWithDelays = null;
+
+    @BeforeSuite
+    public void setUp() throws Exception {
+        exampleTest = new NanoSchedulerBasicTest(10, 2, 1, 10, false);
+        exampleTestWithDelays = new NanoSchedulerBasicTest(10, 2, 1, 10, true);
+    }
+
+    @DataProvider(name = "NanoSchedulerBasicTest")
+    public Object[][] createNanoSchedulerBasicTest() {
+//        for ( final int bufferSize : Arrays.asList(1, 10) ) {
+//            for ( final int nt : Arrays.asList(1, 2, 4) ) {
+//                for ( final int start : Arrays.asList(0) ) {
+//                    for ( final int end : Arrays.asList(0, 1, 2) ) {
+//                        exampleTest = new NanoSchedulerBasicTest(bufferSize, nt, start, end, false);
+//                    }
+//                }
+//            }
+//        }
+
+        for ( final int bufferSize : Arrays.asList(-1, 1, 10, 100) ) {
+            for ( final int nt : Arrays.asList(1, 2, 4) ) {
+                for ( final int start : Arrays.asList(0) ) {
+                    for ( final int end : Arrays.asList(0, 1, 2, 11, 100, 10000, 100000) ) {
+                        for ( final boolean addDelays : Arrays.asList(true, false) ) {
+                            if ( end < 1000 )
+                                new NanoSchedulerBasicTest(bufferSize, nt, start, end, addDelays);
+                        }
+                    }
+                }
+            }
+        }
+
+        return NanoSchedulerBasicTest.getTests(NanoSchedulerBasicTest.class);
+    }
+
+    @Test(enabled = true && ! DEBUG, dataProvider = "NanoSchedulerBasicTest", timeOut = NANO_SCHEDULE_MAX_RUNTIME)
+    public void testSingleThreadedNanoScheduler(final NanoSchedulerBasicTest test) throws InterruptedException {
+        logger.warn("Running " + test);
+        if ( test.nThreads == 1 )
+            testNanoScheduler(test);
+    }
+
+    @Test(enabled = true && ! DEBUG, dataProvider = "NanoSchedulerBasicTest", timeOut = NANO_SCHEDULE_MAX_RUNTIME, dependsOnMethods = "testSingleThreadedNanoScheduler")
+    public void testMultiThreadedNanoScheduler(final NanoSchedulerBasicTest test) throws InterruptedException {
+        logger.warn("Running " + test);
+        if ( test.nThreads >= 1 )
+            testNanoScheduler(test);
+    }
+
+    private void testNanoScheduler(final NanoSchedulerBasicTest test) throws InterruptedException {
+        final SimpleTimer timer = new SimpleTimer().start();
+        final NanoScheduler<Integer, Integer, Integer> nanoScheduler = test.makeScheduler();
+
+        final ProgressCallback callback = new ProgressCallback();
+        nanoScheduler.setProgressFunction(callback);
+
+        if ( test.bufferSize > -1 )
+            Assert.assertEquals(nanoScheduler.getBufferSize(), test.bufferSize, "bufferSize argument");
+        Assert.assertEquals(nanoScheduler.getnThreads(), test.nThreads, "nThreads argument");
+
+        final Integer sum = nanoScheduler.execute(test.makeReader(), test.makeMap(), test.initReduce(), test.makeReduce());
+        Assert.assertNotNull(sum);
+        Assert.assertEquals((int)sum, test.expectedResult, "NanoScheduler sum not the same as calculated directly");
+
+        Assert.assertTrue(callback.callBacks >= test.nExpectedCallbacks(), "Not enough callbacks detected.  Expected at least " + test.nExpectedCallbacks() + " but saw only " + callback.callBacks);
+        nanoScheduler.shutdown();
+    }
+
+    @Test(enabled = true && ! DEBUG, dataProvider = "NanoSchedulerBasicTest", dependsOnMethods = "testMultiThreadedNanoScheduler", timeOut = 2 * NANO_SCHEDULE_MAX_RUNTIME)
+    public void testNanoSchedulerInLoop(final NanoSchedulerBasicTest test) throws InterruptedException {
+        if ( test.bufferSize > 1) {
+            logger.warn("Running " + test);
+
+            final NanoScheduler<Integer, Integer, Integer> nanoScheduler = test.makeScheduler();
+
+            // test reusing the scheduler
+            for ( int i = 0; i < 10; i++ ) {
+                final Integer sum = nanoScheduler.execute(test.makeReader(), test.makeMap(), test.initReduce(), test.makeReduce());
+                Assert.assertNotNull(sum);
+                Assert.assertEquals((int)sum, test.expectedResult, "NanoScheduler sum not the same as calculated directly");
+            }
+
+            nanoScheduler.shutdown();
+        }
+    }
+
+    @Test(enabled = true && ! DEBUG, timeOut = NANO_SCHEDULE_MAX_RUNTIME)
+    public void testShutdown() throws InterruptedException {
+        final NanoScheduler<Integer, Integer, Integer> nanoScheduler = new NanoScheduler<Integer, Integer, Integer>(1, 2);
+        Assert.assertFalse(nanoScheduler.isShutdown(), "scheduler should be alive");
+        nanoScheduler.shutdown();
+        Assert.assertTrue(nanoScheduler.isShutdown(), "scheduler should be dead");
+    }
+
+    @Test(enabled = true && ! DEBUG, expectedExceptions = IllegalStateException.class, timeOut = NANO_SCHEDULE_MAX_RUNTIME)
+    public void testShutdownExecuteFailure() throws InterruptedException {
+        final NanoScheduler<Integer, Integer, Integer> nanoScheduler = new NanoScheduler<Integer, Integer, Integer>(1, 2);
+        nanoScheduler.shutdown();
+        nanoScheduler.execute(exampleTest.makeReader(), exampleTest.makeMap(), exampleTest.initReduce(), exampleTest.makeReduce());
+    }
+
+    @DataProvider(name = "NanoSchedulerInputExceptionTest")
+    public Object[][] createNanoSchedulerInputExceptionTest() {
+        List<Object[]> tests = new ArrayList<Object[]>();
+
+
+        for ( final int bufSize : Arrays.asList(100) ) {
+            for ( final int nThreads : Arrays.asList(8) ) {
+                for ( final boolean addDelays : Arrays.asList(true, false) ) {
+                    final NanoSchedulerBasicTest test = new NanoSchedulerBasicTest(bufSize, nThreads, 1, 1000000, false);
+                    final int maxN = addDelays ? 1000 : 10000;
+                    for ( int nElementsBeforeError = 0; nElementsBeforeError < maxN; nElementsBeforeError += Math.max(nElementsBeforeError / 10, 1) ) {
+                        tests.add(new Object[]{nElementsBeforeError, test, addDelays});
+                    }
+                }
+            }
+        }
+
+        return tests.toArray(new Object[][]{});
+    }
+
+    @Test(enabled = true, expectedExceptions = NullPointerException.class, timeOut = EXCEPTION_THROWING_TEST_TIMEOUT)
+    public void testInputErrorIsThrown_NPE() throws InterruptedException {
+        executeTestErrorThrowingInput(10, new NullPointerException(), exampleTest, false);
+    }
+
+    @Test(enabled = true, expectedExceptions = ReviewedGATKException.class, timeOut = EXCEPTION_THROWING_TEST_TIMEOUT)
+    public void testInputErrorIsThrown_RSE() throws InterruptedException {
+        executeTestErrorThrowingInput(10, new ReviewedGATKException("test"), exampleTest, false);
+    }
+
+    @Test(enabled = true, expectedExceptions = NullPointerException.class, dataProvider = "NanoSchedulerInputExceptionTest", timeOut = EXCEPTION_THROWING_TEST_TIMEOUT, invocationCount = 1)
+    public void testInputRuntimeExceptionDoesntDeadlock(final int nElementsBeforeError, final NanoSchedulerBasicTest test, final boolean addDelays ) throws InterruptedException {
+        executeTestErrorThrowingInput(nElementsBeforeError, new NullPointerException(), test, addDelays);
+    }
+
+    @Test(enabled = true, expectedExceptions = ReviewedGATKException.class, dataProvider = "NanoSchedulerInputExceptionTest", timeOut = EXCEPTION_THROWING_TEST_TIMEOUT, invocationCount = 1)
+    public void testInputErrorDoesntDeadlock(final int nElementsBeforeError, final NanoSchedulerBasicTest test, final boolean addDelays ) throws InterruptedException {
+        executeTestErrorThrowingInput(nElementsBeforeError, new Error(), test, addDelays);
+    }
+
+    private void executeTestErrorThrowingInput(final int nElementsBeforeError, final Throwable ex, final NanoSchedulerBasicTest test, final boolean addDelays) {
+        logger.warn("executeTestErrorThrowingInput " + nElementsBeforeError + " ex=" + ex + " test=" + test + " addInputDelays=" + addDelays);
+        final NanoScheduler<Integer, Integer, Integer> nanoScheduler = test.makeScheduler();
+        nanoScheduler.execute(new ErrorThrowingIterator(nElementsBeforeError, ex, addDelays), test.makeMap(), test.initReduce(), test.makeReduce());
+    }
+
+    private static class ErrorThrowingIterator implements Iterator<Integer> {
+        final int nElementsBeforeError;
+        final boolean addDelays;
+        int i = 0;
+        final Throwable ex;
+
+        private ErrorThrowingIterator(final int nElementsBeforeError, Throwable ex, boolean addDelays) {
+            this.nElementsBeforeError = nElementsBeforeError;
+            this.ex = ex;
+            this.addDelays = addDelays;
+        }
+
+        @Override public boolean hasNext() { return true; }
+        @Override public Integer next() {
+            if ( i++ > nElementsBeforeError ) {
+                if ( ex instanceof Error )
+                    throw (Error)ex;
+                else if ( ex instanceof RuntimeException )
+                    throw (RuntimeException)ex;
+                else
+                    throw new RuntimeException("Bad exception " + ex);
+            } else if ( addDelays ) {
+                maybeDelayMe(i);
+                return i;
+            } else {
+                return i;
+            }
+        }
+        @Override public void remove() { throw new UnsupportedOperationException("x"); }
+    }
+
+    public static void main(String [ ] args) {
+        org.apache.log4j.Logger logger = org.apache.log4j.Logger.getRootLogger();
+        BasicConfigurator.configure();
+        logger.setLevel(org.apache.log4j.Level.DEBUG);
+
+        final NanoSchedulerBasicTest test = new NanoSchedulerBasicTest(1000, Integer.valueOf(args[0]), 0, Integer.valueOf(args[1]), false);
+        final NanoScheduler<Integer, Integer, Integer> nanoScheduler =
+                new NanoScheduler<Integer, Integer, Integer>(test.bufferSize, test.nThreads);
+        nanoScheduler.setDebug(true);
+
+        final Integer sum = nanoScheduler.execute(test.makeReader(), test.makeMap(), test.initReduce(), test.makeReduce());
+        System.out.printf("Sum = %d, expected =%d%n", sum, test.expectedResult);
+        nanoScheduler.shutdown();
+    }
+}
diff --git a/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/utils/nanoScheduler/ReducerUnitTest.java b/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/utils/nanoScheduler/ReducerUnitTest.java
new file mode 100644
index 0000000..987d13f
--- /dev/null
+++ b/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/utils/nanoScheduler/ReducerUnitTest.java
@@ -0,0 +1,236 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.utils.nanoScheduler;
+
+import org.broadinstitute.gatk.utils.BaseTest;
+import org.broadinstitute.gatk.utils.MultiThreadedErrorTracker;
+import org.broadinstitute.gatk.utils.Utils;
+import org.testng.Assert;
+import org.testng.annotations.DataProvider;
+import org.testng.annotations.Test;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.List;
+import java.util.concurrent.*;
+
+/**
+ * UnitTests for Reducer
+ *
+ * User: depristo
+ * Date: 8/24/12
+ * Time: 11:25 AM
+ * To change this template use File | Settings | File Templates.
+ */
+public class ReducerUnitTest extends BaseTest {
+    @DataProvider(name = "ReducerThreadTest")
+    public Object[][] createReducerThreadTest() {
+        List<Object[]> tests = new ArrayList<Object[]>();
+
+        for ( final int groupSize : Arrays.asList(-1, 1, 5, 50, 500, 5000, 50000) ) {
+            for ( final int nElements : Arrays.asList(0, 1, 3, 5) ) {
+                if ( groupSize < nElements ) {
+                    for ( final List<MapResult<Integer>> jobs : Utils.makePermutations(makeJobs(nElements), nElements, false) ) {
+                        tests.add(new Object[]{ new ListOfJobs(jobs), groupSize });
+                    }
+                }
+            }
+
+            for ( final int nElements : Arrays.asList(10, 100, 1000, 10000, 100000, 1000000) ) {
+                if ( groupSize < nElements ) {
+                    tests.add(new Object[]{ new ListOfJobs(makeJobs(nElements)), groupSize });
+                }
+            }
+        }
+
+        return tests.toArray(new Object[][]{});
+    }
+
+    private static class ListOfJobs extends ArrayList<MapResult<Integer>> {
+        private ListOfJobs(Collection<? extends MapResult<Integer>> c) {
+            super(c);
+        }
+
+        @Override
+        public String toString() {
+            if ( size() < 10 )
+                return super.toString();
+            else
+                return "JobList of " + size();
+        }
+    }
+
+    private static List<MapResult<Integer>> makeJobs(final int nElements) {
+        List<MapResult<Integer>> jobs = new ArrayList<MapResult<Integer>>(nElements);
+        for ( int i = 0; i < nElements; i++ ) {
+            jobs.add(new MapResult<Integer>(i, i));
+        }
+        return jobs;
+    }
+
+    private int expectedSum(final List<MapResult<Integer>> jobs) {
+        int sum = 0;
+        for ( final MapResult<Integer> job : jobs )
+            sum += job.getValue();
+        return sum;
+    }
+
+    @Test(enabled = true, dataProvider = "ReducerThreadTest", timeOut = NanoSchedulerUnitTest.NANO_SCHEDULE_MAX_RUNTIME)
+    public void testReducerThread(final List<MapResult<Integer>> allJobs, int groupSize) throws Exception {
+        if ( groupSize == -1 )
+            groupSize = allJobs.size();
+
+        final MapResultsQueue<Integer> mapResultsQueue = new MapResultsQueue<Integer>();
+
+        final List<List<MapResult<Integer>>> jobGroups = Utils.groupList(allJobs, groupSize);
+        final ReduceSumTest reduce = new ReduceSumTest();
+        final Reducer<Integer, Integer> reducer = new Reducer<Integer, Integer>(reduce, new MultiThreadedErrorTracker(), 0);
+
+        final TestWaitingForFinalReduce waitingThread = new TestWaitingForFinalReduce(reducer, expectedSum(allJobs));
+        final ExecutorService es = Executors.newSingleThreadExecutor();
+        es.submit(waitingThread);
+
+        int lastJobID = -1;
+        int nJobsSubmitted = 0;
+        int jobGroupCount = 0;
+        final int lastJobGroupCount = jobGroups.size() - 1;
+
+        for ( final List<MapResult<Integer>> jobs : jobGroups ) {
+            //logger.warn("Processing job group " + jobGroupCount + " with " + jobs.size() + " jobs");
+            for ( final MapResult<Integer> job : jobs ) {
+                lastJobID = Math.max(lastJobID, job.getJobID());
+                mapResultsQueue.put(job);
+                nJobsSubmitted++;
+            }
+
+            if ( jobGroupCount == lastJobGroupCount ) {
+                mapResultsQueue.put(new MapResult<Integer>(lastJobID+1));
+                nJobsSubmitted++;
+            }
+
+            final int nReduced = reducer.reduceAsMuchAsPossible(mapResultsQueue, true);
+            Assert.assertTrue(nReduced <= nJobsSubmitted, "Somehow reduced more jobs than submitted");
+
+            jobGroupCount++;
+        }
+
+        Assert.assertEquals(reduce.nRead, allJobs.size(), "number of read values not all of the values in the reducer queue");
+        es.shutdown();
+        es.awaitTermination(1, TimeUnit.HOURS);
+    }
+
+    @Test(timeOut = 1000, invocationCount = 100)
+    private void testNonBlockingReduce() throws Exception {
+        final Reducer<Integer, Integer> reducer = new Reducer<Integer, Integer>(new ReduceSumTest(), new MultiThreadedErrorTracker(), 0);
+        final MapResultsQueue<Integer> mapResultsQueue = new MapResultsQueue<Integer>();
+        mapResultsQueue.put(new MapResult<Integer>(0, 0));
+        mapResultsQueue.put(new MapResult<Integer>(1, 1));
+
+        final CountDownLatch latch = new CountDownLatch(1);
+        final ExecutorService es = Executors.newSingleThreadExecutor();
+
+        es.submit(new Runnable() {
+            @Override
+            public void run() {
+                reducer.acquireReduceLock(true);
+                latch.countDown();
+            }
+        });
+
+        latch.await();
+        final int nReduced = reducer.reduceAsMuchAsPossible(mapResultsQueue, false);
+        Assert.assertEquals(nReduced, 0, "The reducer lock was already held but we did some work");
+        es.shutdown();
+        es.awaitTermination(1, TimeUnit.HOURS);
+    }
+
+    @Test(timeOut = 10000, invocationCount = 100)
+    private void testBlockingReduce() throws Exception {
+        final Reducer<Integer, Integer> reducer = new Reducer<Integer, Integer>(new ReduceSumTest(), new MultiThreadedErrorTracker(), 0);
+        final MapResultsQueue<Integer> mapResultsQueue = new MapResultsQueue<Integer>();
+        mapResultsQueue.put(new MapResult<Integer>(0, 0));
+        mapResultsQueue.put(new MapResult<Integer>(1, 1));
+
+        final CountDownLatch latch = new CountDownLatch(1);
+        final ExecutorService es = Executors.newSingleThreadExecutor();
+
+        es.submit(new Runnable() {
+            @Override
+            public void run() {
+                reducer.acquireReduceLock(true);
+                latch.countDown();
+                try {
+                    Thread.sleep(100);
+                } catch ( InterruptedException e ) {
+                    ;
+                } finally {
+                    reducer.releaseReduceLock();
+                }
+            }
+        });
+
+        latch.await();
+        final int nReduced = reducer.reduceAsMuchAsPossible(mapResultsQueue, true);
+        Assert.assertEquals(nReduced, 2, "The reducer should have blocked until the lock was freed and reduced 2 values");
+        es.shutdown();
+        es.awaitTermination(1, TimeUnit.HOURS);
+    }
+
+
+    public class ReduceSumTest implements NSReduceFunction<Integer, Integer> {
+        int nRead = 0;
+        int lastValue = -1;
+
+        @Override public Integer apply(Integer one, Integer sum) {
+            Assert.assertTrue(lastValue < one, "Reduce came in out of order.  Prev " + lastValue + " cur " + one);
+
+            Assert.assertTrue(lastValue < one, "Read values coming out of order!");
+            final int expected = lastValue + 1;
+            Assert.assertEquals((int)one, expected, "Value observed " + one + " not equal to the expected value " + expected);
+            nRead++;
+            lastValue = expected;
+
+            return one + sum;
+        }
+    }
+
+    final static class TestWaitingForFinalReduce implements Runnable {
+        final Reducer<Integer, Integer> reducer;
+        final int expectedSum;
+
+        TestWaitingForFinalReduce(Reducer<Integer, Integer> reducer, final int expectedSum) {
+            this.reducer = reducer;
+            this.expectedSum = expectedSum;
+        }
+
+        @Override
+        public void run() {
+            final int observedSum = reducer.getReduceResult();
+            Assert.assertEquals(observedSum, expectedSum, "Reduce didn't sum to expected value");
+        }
+    }
+}
\ No newline at end of file
diff --git a/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/utils/pileup/PileupElementUnitTest.java b/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/utils/pileup/PileupElementUnitTest.java
new file mode 100644
index 0000000..90d235f
--- /dev/null
+++ b/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/utils/pileup/PileupElementUnitTest.java
@@ -0,0 +1,189 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.utils.pileup;
+
+import htsjdk.samtools.CigarElement;
+import htsjdk.samtools.CigarOperator;
+import org.broadinstitute.gatk.utils.Utils;
+import org.broadinstitute.gatk.utils.locusiterator.AlignmentStateMachine;
+import org.broadinstitute.gatk.utils.locusiterator.LIBS_position;
+import org.broadinstitute.gatk.utils.locusiterator.LocusIteratorByStateBaseTest;
+import org.broadinstitute.gatk.utils.sam.ArtificialSAMUtils;
+import org.broadinstitute.gatk.utils.sam.GATKSAMRecord;
+import org.testng.Assert;
+import org.testng.annotations.DataProvider;
+import org.testng.annotations.Test;
+
+import java.util.Arrays;
+import java.util.LinkedList;
+import java.util.List;
+
+/**
+ * testing of the new (non-legacy) version of LocusIteratorByState
+ */
+public class PileupElementUnitTest extends LocusIteratorByStateBaseTest {
+    @DataProvider(name = "PileupElementTest")
+    public Object[][] makePileupElementTest() {
+//        return new Object[][]{{new LIBSTest("2X2D2P2X")}};
+//        return createLIBSTests(
+//                Arrays.asList(2),
+//                Arrays.asList(2));
+        return createLIBSTests(
+                Arrays.asList(1, 2),
+                Arrays.asList(1, 2, 3, 4));
+    }
+
+    @Test(dataProvider = "PileupElementTest")
+    public void testPileupElementTest(LIBSTest params) {
+        final GATKSAMRecord read = params.makeRead();
+        final AlignmentStateMachine state = new AlignmentStateMachine(read);
+        final LIBS_position tester = new LIBS_position(read);
+
+        while ( state.stepForwardOnGenome() != null ) {
+            tester.stepForwardOnGenome();
+            final PileupElement pe = state.makePileupElement();
+
+            Assert.assertEquals(pe.getRead(), read);
+            Assert.assertEquals(pe.getMappingQual(), read.getMappingQuality());
+            Assert.assertEquals(pe.getOffset(), state.getReadOffset());
+
+            Assert.assertEquals(pe.isDeletion(), state.getCigarOperator() == CigarOperator.D);
+            Assert.assertEquals(pe.isAfterInsertion(), tester.isAfterInsertion);
+            Assert.assertEquals(pe.isBeforeInsertion(), tester.isBeforeInsertion);
+            Assert.assertEquals(pe.isNextToSoftClip(), tester.isNextToSoftClip);
+
+            if ( ! hasNeighboringPaddedOps(params.getElements(), pe.getCurrentCigarOffset()) ) {
+                Assert.assertEquals(pe.isAfterDeletionEnd(), tester.isAfterDeletionEnd);
+                Assert.assertEquals(pe.isBeforeDeletionStart(), tester.isBeforeDeletionStart);
+            }
+
+
+
+            Assert.assertEquals(pe.atEndOfCurrentCigar(), state.getOffsetIntoCurrentCigarElement() == state.getCurrentCigarElement().getLength() - 1, "atEndOfCurrentCigar failed");
+            Assert.assertEquals(pe.atStartOfCurrentCigar(), state.getOffsetIntoCurrentCigarElement() == 0, "atStartOfCurrentCigar failed");
+
+            Assert.assertEquals(pe.getBase(), pe.isDeletion() ? PileupElement.DELETION_BASE : read.getReadBases()[state.getReadOffset()]);
+            Assert.assertEquals(pe.getQual(), pe.isDeletion() ? PileupElement.DELETION_QUAL : read.getBaseQualities()[state.getReadOffset()]);
+
+            Assert.assertEquals(pe.getCurrentCigarElement(), state.getCurrentCigarElement());
+            Assert.assertEquals(pe.getCurrentCigarOffset(), state.getCurrentCigarElementOffset());
+
+            // tested in libs
+            //pe.getLengthOfImmediatelyFollowingIndel();
+            //pe.getBasesOfImmediatelyFollowingInsertion();
+
+            // Don't test -- pe.getBaseIndex();
+            if ( pe.atEndOfCurrentCigar() && state.getCurrentCigarElementOffset() < read.getCigarLength() - 1 ) {
+                final CigarElement nextElement = read.getCigar().getCigarElement(state.getCurrentCigarElementOffset() + 1);
+                if ( nextElement.getOperator() == CigarOperator.I ) {
+                    Assert.assertTrue(pe.getBetweenNextPosition().size() >= 1);
+                    Assert.assertEquals(pe.getBetweenNextPosition().get(0), nextElement);
+                }
+                if ( nextElement.getOperator() == CigarOperator.M ) {
+                    Assert.assertTrue(pe.getBetweenNextPosition().isEmpty());
+                }
+            } else {
+                Assert.assertTrue(pe.getBetweenNextPosition().isEmpty());
+            }
+
+            if ( pe.atStartOfCurrentCigar() && state.getCurrentCigarElementOffset() > 0 ) {
+                final CigarElement prevElement = read.getCigar().getCigarElement(state.getCurrentCigarElementOffset() - 1);
+                if ( prevElement.getOperator() == CigarOperator.I ) {
+                    Assert.assertTrue(pe.getBetweenPrevPosition().size() >= 1);
+                    Assert.assertEquals(pe.getBetweenPrevPosition().getLast(), prevElement);
+                }
+                if ( prevElement.getOperator() == CigarOperator.M ) {
+                    Assert.assertTrue(pe.getBetweenPrevPosition().isEmpty());
+                }
+            } else {
+                Assert.assertTrue(pe.getBetweenPrevPosition().isEmpty());
+            }
+
+            // TODO -- add meaningful tests
+            pe.getBaseInsertionQual();
+            pe.getBaseDeletionQual();
+        }
+    }
+
+
+    @DataProvider(name = "PrevAndNextTest")
+    public Object[][] makePrevAndNextTest() {
+        final List<Object[]> tests = new LinkedList<Object[]>();
+
+        final List<CigarOperator> operators = Arrays.asList(CigarOperator.I, CigarOperator.P, CigarOperator.S);
+
+        for ( final CigarOperator firstOp : Arrays.asList(CigarOperator.M) ) {
+            for ( final CigarOperator lastOp : Arrays.asList(CigarOperator.M, CigarOperator.D) ) {
+                for ( final int nIntermediate : Arrays.asList(1, 2, 3) ) {
+                    for ( final List<CigarOperator> combination : Utils.makePermutations(operators, nIntermediate, false) ) {
+                        final int readLength = 2 + combination.size();
+                        GATKSAMRecord read = ArtificialSAMUtils.createArtificialRead(header, "read", 0, 1, readLength);
+                        read.setReadBases(Utils.dupBytes((byte) 'A', readLength));
+                        read.setBaseQualities(Utils.dupBytes((byte) 30, readLength));
+
+                        String cigar = "1" + firstOp;
+                        for ( final CigarOperator op : combination ) cigar += "1" + op;
+                        cigar += "1" + lastOp;
+                        read.setCigarString(cigar);
+
+                        tests.add(new Object[]{read, firstOp, lastOp, combination});
+                    }
+                }
+            }
+        }
+
+        return tests.toArray(new Object[][]{});
+    }
+
+    @Test(dataProvider = "PrevAndNextTest")
+    public void testPrevAndNextTest(final GATKSAMRecord read, final CigarOperator firstOp, final CigarOperator lastOp, final List<CigarOperator> ops) {
+        final AlignmentStateMachine state = new AlignmentStateMachine(read);
+
+        state.stepForwardOnGenome();
+        final PileupElement pe = state.makePileupElement();
+        Assert.assertEquals(pe.getBetweenNextPosition().size(), ops.size());
+        Assert.assertEquals(pe.getBetweenPrevPosition().size(), 0);
+        assertEqualsOperators(pe.getBetweenNextPosition(), ops);
+        Assert.assertEquals(pe.getPreviousOnGenomeCigarElement(), null);
+        Assert.assertNotNull(pe.getNextOnGenomeCigarElement());
+        Assert.assertEquals(pe.getNextOnGenomeCigarElement().getOperator(), lastOp);
+
+        state.stepForwardOnGenome();
+        final PileupElement pe2 = state.makePileupElement();
+        Assert.assertEquals(pe2.getBetweenPrevPosition().size(), ops.size());
+        Assert.assertEquals(pe2.getBetweenNextPosition().size(), 0);
+        assertEqualsOperators(pe2.getBetweenPrevPosition(), ops);
+        Assert.assertNotNull(pe2.getPreviousOnGenomeCigarElement());
+        Assert.assertEquals(pe2.getPreviousOnGenomeCigarElement().getOperator(), firstOp);
+        Assert.assertEquals(pe2.getNextOnGenomeCigarElement(), null);
+    }
+
+    private void assertEqualsOperators(final List<CigarElement> elements, final List<CigarOperator> ops) {
+        for ( int i = 0; i < elements.size(); i++ ) {
+            Assert.assertEquals(elements.get(i).getOperator(), ops.get(i), "elements doesn't have expected operator at position " + i);
+        }
+    }
+}
diff --git a/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/utils/pileup/ReadBackedPileupUnitTest.java b/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/utils/pileup/ReadBackedPileupUnitTest.java
new file mode 100644
index 0000000..9b3b3b8
--- /dev/null
+++ b/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/utils/pileup/ReadBackedPileupUnitTest.java
@@ -0,0 +1,328 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.utils.pileup;
+
+import htsjdk.samtools.CigarElement;
+import htsjdk.samtools.SAMFileHeader;
+import htsjdk.samtools.SAMReadGroupRecord;
+import org.broadinstitute.gatk.utils.GenomeLoc;
+import org.broadinstitute.gatk.utils.GenomeLocParser;
+import org.broadinstitute.gatk.utils.Utils;
+import org.broadinstitute.gatk.utils.sam.GATKSAMRecord;
+import org.testng.Assert;
+import org.broadinstitute.gatk.utils.sam.ArtificialSAMUtils;
+
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.DataProvider;
+import org.testng.annotations.Test;
+
+import java.util.*;
+
+/**
+ * Test routines for read-backed pileup.
+ */
+public class ReadBackedPileupUnitTest {
+    protected static SAMFileHeader header;
+    protected GenomeLocParser genomeLocParser;
+    private GenomeLoc loc;
+
+    @BeforeClass
+    public void beforeClass() {
+        header = ArtificialSAMUtils.createArtificialSamHeader(1, 1, 1000);
+        genomeLocParser = new GenomeLocParser(header.getSequenceDictionary());
+        loc = genomeLocParser.createGenomeLoc("chr1", 1);
+    }
+
+    /**
+     * Ensure that basic read group splitting works.
+     */
+    @Test
+    public void testSplitByReadGroup() {
+        SAMReadGroupRecord readGroupOne = new SAMReadGroupRecord("rg1");
+        SAMReadGroupRecord readGroupTwo = new SAMReadGroupRecord("rg2");
+
+        SAMFileHeader header = ArtificialSAMUtils.createArtificialSamHeader(1,1,1000);
+        header.addReadGroup(readGroupOne);
+        header.addReadGroup(readGroupTwo);
+
+        GATKSAMRecord read1 = ArtificialSAMUtils.createArtificialRead(header,"read1",0,1,10);
+        read1.setAttribute("RG",readGroupOne.getId());
+        GATKSAMRecord read2 = ArtificialSAMUtils.createArtificialRead(header,"read2",0,1,10);
+        read2.setAttribute("RG",readGroupTwo.getId());
+        GATKSAMRecord read3 = ArtificialSAMUtils.createArtificialRead(header,"read3",0,1,10);
+        read3.setAttribute("RG",readGroupOne.getId());
+        GATKSAMRecord read4 = ArtificialSAMUtils.createArtificialRead(header,"read4",0,1,10);
+        read4.setAttribute("RG",readGroupTwo.getId());
+        GATKSAMRecord read5 = ArtificialSAMUtils.createArtificialRead(header,"read5",0,1,10);
+        read5.setAttribute("RG",readGroupTwo.getId());
+        GATKSAMRecord read6 = ArtificialSAMUtils.createArtificialRead(header,"read6",0,1,10);
+        read6.setAttribute("RG",readGroupOne.getId());
+        GATKSAMRecord read7 = ArtificialSAMUtils.createArtificialRead(header,"read7",0,1,10);
+        read7.setAttribute("RG",readGroupOne.getId());
+
+        ReadBackedPileup pileup = new ReadBackedPileupImpl(null, Arrays.asList(read1,read2,read3,read4,read5,read6,read7), Arrays.asList(1,1,1,1,1,1,1));
+
+        ReadBackedPileup rg1Pileup = pileup.getPileupForReadGroup("rg1");
+        List<GATKSAMRecord> rg1Reads = rg1Pileup.getReads();
+        Assert.assertEquals(rg1Reads.size(), 4, "Wrong number of reads in read group rg1");
+        Assert.assertEquals(rg1Reads.get(0), read1, "Read " + read1.getReadName() + " should be in rg1 but isn't");
+        Assert.assertEquals(rg1Reads.get(1), read3, "Read " + read3.getReadName() + " should be in rg1 but isn't");
+        Assert.assertEquals(rg1Reads.get(2), read6, "Read " + read6.getReadName() + " should be in rg1 but isn't");
+        Assert.assertEquals(rg1Reads.get(3), read7, "Read " + read7.getReadName() + " should be in rg1 but isn't");
+
+        ReadBackedPileup rg2Pileup = pileup.getPileupForReadGroup("rg2");
+        List<GATKSAMRecord> rg2Reads = rg2Pileup.getReads();        
+        Assert.assertEquals(rg2Reads.size(), 3, "Wrong number of reads in read group rg2");
+        Assert.assertEquals(rg2Reads.get(0), read2, "Read " + read2.getReadName() + " should be in rg2 but isn't");
+        Assert.assertEquals(rg2Reads.get(1), read4, "Read " + read4.getReadName() + " should be in rg2 but isn't");
+        Assert.assertEquals(rg2Reads.get(2), read5, "Read " + read5.getReadName() + " should be in rg2 but isn't");
+    }
+
+    /**
+     * Ensure that splitting read groups still works when dealing with null read groups.
+     */
+    @Test
+    public void testSplitByNullReadGroups() {
+        SAMFileHeader header = ArtificialSAMUtils.createArtificialSamHeader(1,1,1000);
+
+        GATKSAMRecord read1 = ArtificialSAMUtils.createArtificialRead(header,"read1",0,1,10);
+        GATKSAMRecord read2 = ArtificialSAMUtils.createArtificialRead(header,"read2",0,1,10);
+        GATKSAMRecord read3 = ArtificialSAMUtils.createArtificialRead(header,"read3",0,1,10);
+
+        ReadBackedPileup pileup = new ReadBackedPileupImpl(null,
+                                                           Arrays.asList(read1,read2,read3),
+                                                           Arrays.asList(1,1,1));
+
+        ReadBackedPileup nullRgPileup = pileup.getPileupForReadGroup(null);
+        List<GATKSAMRecord> nullRgReads = nullRgPileup.getReads();
+        Assert.assertEquals(nullRgPileup.getNumberOfElements(), 3, "Wrong number of reads in null read group");
+        Assert.assertEquals(nullRgReads.get(0), read1, "Read " + read1.getReadName() + " should be in null rg but isn't");
+        Assert.assertEquals(nullRgReads.get(1), read2, "Read " + read2.getReadName() + " should be in null rg but isn't");
+        Assert.assertEquals(nullRgReads.get(2), read3, "Read " + read3.getReadName() + " should be in null rg but isn't");
+
+        ReadBackedPileup rg1Pileup = pileup.getPileupForReadGroup("rg1");
+        Assert.assertNull(rg1Pileup, "Pileup for non-existent read group should return null");
+    }
+
+    /**
+     * Ensure that splitting read groups still works when dealing with a sample-split pileup.
+     */
+    @Test
+    public void testSplitBySample() {
+        SAMReadGroupRecord readGroupOne = new SAMReadGroupRecord("rg1");
+        readGroupOne.setSample("sample1");
+        SAMReadGroupRecord readGroupTwo = new SAMReadGroupRecord("rg2");
+        readGroupTwo.setSample("sample2");
+
+        SAMFileHeader header = ArtificialSAMUtils.createArtificialSamHeader(1,1,1000);
+        header.addReadGroup(readGroupOne);
+        header.addReadGroup(readGroupTwo);
+
+        GATKSAMRecord read1 = ArtificialSAMUtils.createArtificialRead(header,"read1",0,1,10);
+        read1.setAttribute("RG",readGroupOne.getId());
+        GATKSAMRecord read2 = ArtificialSAMUtils.createArtificialRead(header,"read2",0,1,10);
+        read2.setAttribute("RG",readGroupTwo.getId());
+        GATKSAMRecord read3 = ArtificialSAMUtils.createArtificialRead(header,"read3",0,1,10);
+        read3.setAttribute("RG",readGroupOne.getId());
+        GATKSAMRecord read4 = ArtificialSAMUtils.createArtificialRead(header,"read4",0,1,10);
+        read4.setAttribute("RG",readGroupTwo.getId());
+
+        ReadBackedPileupImpl sample1Pileup = new ReadBackedPileupImpl(null,
+                                                                      Arrays.asList(read1,read3),
+                                                                      Arrays.asList(1,1));
+        ReadBackedPileupImpl sample2Pileup = new ReadBackedPileupImpl(null,
+                                                                      Arrays.asList(read2,read4),
+                                                                      Arrays.asList(1,1));
+        Map<String,ReadBackedPileupImpl> sampleToPileupMap = new HashMap<String,ReadBackedPileupImpl>();
+        sampleToPileupMap.put(readGroupOne.getSample(),sample1Pileup);
+        sampleToPileupMap.put(readGroupTwo.getSample(),sample2Pileup);
+
+        ReadBackedPileup compositePileup = new ReadBackedPileupImpl(null,sampleToPileupMap);
+
+        ReadBackedPileup rg1Pileup = compositePileup.getPileupForReadGroup("rg1");
+        List<GATKSAMRecord> rg1Reads = rg1Pileup.getReads();
+
+        Assert.assertEquals(rg1Reads.size(), 2, "Wrong number of reads in read group rg1");
+        Assert.assertEquals(rg1Reads.get(0), read1, "Read " + read1.getReadName() + " should be in rg1 but isn't");
+        Assert.assertEquals(rg1Reads.get(1), read3, "Read " + read3.getReadName() + " should be in rg1 but isn't");
+
+        ReadBackedPileup rg2Pileup = compositePileup.getPileupForReadGroup("rg2");
+        List<GATKSAMRecord> rg2Reads = rg2Pileup.getReads();
+
+        Assert.assertEquals(rg1Reads.size(), 2, "Wrong number of reads in read group rg2");
+        Assert.assertEquals(rg2Reads.get(0), read2, "Read " + read2.getReadName() + " should be in rg2 but isn't");
+        Assert.assertEquals(rg2Reads.get(1), read4, "Read " + read4.getReadName() + " should be in rg2 but isn't");
+    }
+
+    @Test
+    public void testGetPileupForSample() {
+        String sample1 = "sample1";
+        String sample2 = "sample2";
+
+        SAMReadGroupRecord readGroupOne = new SAMReadGroupRecord("rg1");
+        readGroupOne.setSample(sample1);
+        SAMReadGroupRecord readGroupTwo = new SAMReadGroupRecord("rg2");
+        readGroupTwo.setSample(sample2);
+
+        SAMFileHeader header = ArtificialSAMUtils.createArtificialSamHeader(1,1,1000);
+        header.addReadGroup(readGroupOne);
+        header.addReadGroup(readGroupTwo);
+
+        GATKSAMRecord read1 = ArtificialSAMUtils.createArtificialRead(header,"read1",0,1,10);
+        read1.setAttribute("RG",readGroupOne.getId());
+        GATKSAMRecord read2 = ArtificialSAMUtils.createArtificialRead(header,"read2",0,1,10);
+        read2.setAttribute("RG",readGroupTwo.getId());
+
+        Map<String,ReadBackedPileupImpl> sampleToPileupMap = new HashMap<String,ReadBackedPileupImpl>();
+        sampleToPileupMap.put(sample1,new ReadBackedPileupImpl(null,Collections.singletonList(read1),0));
+        sampleToPileupMap.put(sample2,new ReadBackedPileupImpl(null,Collections.singletonList(read2),0));
+
+        ReadBackedPileup pileup = new ReadBackedPileupImpl(null,sampleToPileupMap);
+
+        ReadBackedPileup sample2Pileup = pileup.getPileupForSample(sample2);
+        Assert.assertEquals(sample2Pileup.getNumberOfElements(),1,"Sample 2 pileup has wrong number of elements");
+        Assert.assertEquals(sample2Pileup.getReads().get(0),read2,"Sample 2 pileup has incorrect read");
+
+        ReadBackedPileup missingSamplePileup = pileup.getPileupForSample("missing");
+        Assert.assertNull(missingSamplePileup,"Pileup for sample 'missing' should be null but isn't");
+
+        missingSamplePileup = pileup.getPileupForSample("not here");
+        Assert.assertNull(missingSamplePileup,"Pileup for sample 'not here' should be null but isn't");
+    }
+
+    private static int sampleI = 0;
+    private class RBPCountTest {
+        final String sample;
+        final int nReads, nMapq0, nDeletions;
+
+        private RBPCountTest(int nReads, int nMapq0, int nDeletions) {
+            this.sample = "sample" + sampleI++;
+            this.nReads = nReads;
+            this.nMapq0 = nMapq0;
+            this.nDeletions = nDeletions;
+        }
+
+        private List<PileupElement> makeReads( final int n, final int mapq, final String op ) {
+            final int readLength = 3;
+
+            final List<PileupElement> elts = new LinkedList<PileupElement>();
+            for ( int i = 0; i < n; i++ ) {
+                GATKSAMRecord read = ArtificialSAMUtils.createArtificialRead(header, "read", 0, 1, readLength);
+                read.setReadBases(Utils.dupBytes((byte) 'A', readLength));
+                read.setBaseQualities(Utils.dupBytes((byte) 30, readLength));
+                read.setCigarString("1M1" + op + "1M");
+                read.setMappingQuality(mapq);
+                final int baseOffset = op.equals("M") ? 1 : 0;
+                final CigarElement cigarElement = read.getCigar().getCigarElement(1);
+                elts.add(new PileupElement(read, baseOffset, cigarElement, 1, 0));
+            }
+
+            return elts;
+        }
+
+        private ReadBackedPileupImpl makePileup() {
+            final List<PileupElement> elts = new LinkedList<PileupElement>();
+
+            elts.addAll(makeReads(nMapq0, 0, "M"));
+            elts.addAll(makeReads(nDeletions, 30, "D"));
+            elts.addAll(makeReads(nReads - nMapq0 - nDeletions, 30, "M"));
+
+            return new ReadBackedPileupImpl(loc, elts);
+        }
+
+        @Override
+        public String toString() {
+            return "RBPCountTest{" +
+                    "sample='" + sample + '\'' +
+                    ", nReads=" + nReads +
+                    ", nMapq0=" + nMapq0 +
+                    ", nDeletions=" + nDeletions +
+                    '}';
+        }
+    }
+
+    @DataProvider(name = "RBPCountingTest")
+    public Object[][] makeRBPCountingTest() {
+        final List<Object[]> tests = new LinkedList<Object[]>();
+
+        for ( final int nMapq : Arrays.asList(0, 10, 20) ) {
+            for ( final int nDeletions : Arrays.asList(0, 10, 20) ) {
+                for ( final int nReg : Arrays.asList(0, 10, 20) ) {
+                    final int total = nMapq + nDeletions + nReg;
+                    if ( total > 0 )
+                        tests.add(new Object[]{new RBPCountTest(total, nMapq, nDeletions)});
+                }
+            }
+        }
+
+        return tests.toArray(new Object[][]{});
+    }
+
+    @Test(dataProvider = "RBPCountingTest")
+    public void testRBPCountingTestSinglePileup(RBPCountTest params) {
+        testRBPCounts(params.makePileup(), params);
+    }
+
+    @Test(dataProvider = "RBPCountingTest")
+    public void testRBPCountingTestMultiSample(RBPCountTest params) {
+        final RBPCountTest newSample = new RBPCountTest(2, 1, 1);
+        final Map<String, ReadBackedPileupImpl> pileupsBySample = new HashMap<String, ReadBackedPileupImpl>();
+        pileupsBySample.put(newSample.sample, newSample.makePileup());
+        pileupsBySample.put(params.sample, params.makePileup());
+        final ReadBackedPileup pileup = new ReadBackedPileupImpl(loc, pileupsBySample);
+        testRBPCounts(pileup, new RBPCountTest(params.nReads + 2, params.nMapq0 + 1, params.nDeletions + 1));
+    }
+
+    private void testRBPCounts(final ReadBackedPileup rbp, RBPCountTest expected) {
+        for ( int cycles = 0; cycles < 3; cycles++ ) {
+            // multiple cycles to make sure caching is working
+            Assert.assertEquals(rbp.getNumberOfElements(), expected.nReads);
+            Assert.assertEquals(rbp.depthOfCoverage(), expected.nReads);
+            Assert.assertEquals(rbp.getNumberOfDeletions(), expected.nDeletions);
+            Assert.assertEquals(rbp.getNumberOfMappingQualityZeroReads(), expected.nMapq0);
+        }
+    }
+
+    @Test
+    public void testRBPMappingQuals() {
+
+        // create a read with high MQ
+        final GATKSAMRecord read = ArtificialSAMUtils.createArtificialRead(header, "read", 0, 1, 10);
+        read.setReadBases(Utils.dupBytes((byte) 'A', 10));
+        read.setBaseQualities(Utils.dupBytes((byte) 30, 10));
+        read.setCigarString("10M");
+        read.setMappingQuality(200); // set a MQ higher than max signed byte
+
+        // now create the RBP
+        final List<PileupElement> elts = new LinkedList<>();
+        elts.add(new PileupElement(read, 0, read.getCigar().getCigarElement(0), 0, 0));
+        final Map<String, ReadBackedPileupImpl> pileupsBySample = new HashMap<>();
+        pileupsBySample.put("foo", new ReadBackedPileupImpl(loc, elts));
+        final ReadBackedPileup pileup = new ReadBackedPileupImpl(loc, pileupsBySample);
+
+        Assert.assertEquals(pileup.getMappingQuals()[0], 200);
+    }
+}
\ No newline at end of file
diff --git a/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/utils/progressmeter/ProgressMeterDaemonUnitTest.java b/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/utils/progressmeter/ProgressMeterDaemonUnitTest.java
new file mode 100644
index 0000000..9d549ea
--- /dev/null
+++ b/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/utils/progressmeter/ProgressMeterDaemonUnitTest.java
@@ -0,0 +1,121 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.utils.progressmeter;
+
+import org.broadinstitute.gatk.utils.BaseTest;
+import org.broadinstitute.gatk.utils.GenomeLocParser;
+import org.broadinstitute.gatk.utils.GenomeLocSortedSet;
+import org.broadinstitute.gatk.utils.fasta.CachingIndexedFastaSequenceFile;
+import org.testng.Assert;
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.DataProvider;
+import org.testng.annotations.Test;
+
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.LinkedList;
+import java.util.List;
+
+/**
+ * UnitTests for the ProgressMeterDaemon
+ *
+ * User: depristo
+ * Date: 8/24/12
+ * Time: 11:25 AM
+ * To change this template use File | Settings | File Templates.
+ */
+public class ProgressMeterDaemonUnitTest extends BaseTest {
+    private GenomeLocParser genomeLocParser;
+
+    @BeforeClass
+    public void init() throws FileNotFoundException {
+        genomeLocParser = new GenomeLocParser(new CachingIndexedFastaSequenceFile(new File(b37KGReference)));
+    }
+
+    // capture and count calls to progress
+    private class TestingProgressMeter extends ProgressMeter {
+        final List<Long> progressCalls = new LinkedList<Long>();
+
+        private TestingProgressMeter(final long poll) {
+            super(null, "test", new GenomeLocSortedSet(genomeLocParser), poll);
+            super.start();
+        }
+
+        @Override
+        protected synchronized void printProgress(boolean mustPrint) {
+            progressCalls.add(System.currentTimeMillis());
+        }
+    }
+
+    @DataProvider(name = "PollingData")
+    public Object[][] makePollingData() {
+        List<Object[]> tests = new ArrayList<Object[]>();
+        for ( final int ticks : Arrays.asList(1, 5, 10) ) {
+            for ( final int poll : Arrays.asList(10, 100) ) {
+                tests.add(new Object[]{poll, ticks});
+            }
+        }
+
+        return tests.toArray(new Object[][]{});
+    }
+
+    @Test
+    public void testPeriodUpdateNano() {
+        final ProgressMeter meter = new TestingProgressMeter(10);
+        final long currentTime = meter.getRuntimeInNanoseconds();
+        meter.updateElapsedTimeInNanoseconds();
+        Assert.assertTrue( meter.getRuntimeInNanosecondsUpdatedPeriodically() > currentTime, "Updating the periodic runtime failed" );
+    }
+
+    @Test(dataProvider = "PollingData", invocationCount = 10, successPercentage = 90, enabled = false)
+    public void testProgressMeterDaemon(final long poll, final int ticks) throws InterruptedException {
+        final TestingProgressMeter meter = new TestingProgressMeter(poll);
+        final ProgressMeterDaemon daemon = meter.getProgressMeterDaemon();
+
+        Assert.assertTrue(daemon.isDaemon());
+
+        Assert.assertFalse(daemon.isDone());
+        Thread.sleep(ticks * poll);
+        Assert.assertFalse(daemon.isDone());
+
+        daemon.done();
+        Assert.assertTrue(daemon.isDone());
+
+        // wait for the thread to actually finish
+        daemon.join();
+
+        Assert.assertTrue(meter.progressCalls.size() >= 1,
+                "Expected at least one progress update call from daemon thread, but only got " + meter.progressCalls.size() + " with exact calls " + meter.progressCalls);
+
+        final int tolerance = (int)Math.ceil(0.8 * meter.progressCalls.size());
+        Assert.assertTrue(Math.abs(meter.progressCalls.size() - ticks) <= tolerance,
+                "Expected " + ticks + " progress calls from daemon thread, but got " + meter.progressCalls.size() + " and a tolerance of only " + tolerance);
+
+        Assert.assertTrue(meter.getRuntimeInNanosecondsUpdatedPeriodically() > 0, "Daemon should have updated our periodic runtime");
+    }
+}
diff --git a/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/utils/progressmeter/ProgressMeterDataUnitTest.java b/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/utils/progressmeter/ProgressMeterDataUnitTest.java
new file mode 100644
index 0000000..0c97377
--- /dev/null
+++ b/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/utils/progressmeter/ProgressMeterDataUnitTest.java
@@ -0,0 +1,86 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.utils.progressmeter;
+
+import org.broadinstitute.gatk.utils.BaseTest;
+import org.broadinstitute.gatk.utils.AutoFormattingTime;
+import org.testng.Assert;
+import org.testng.annotations.DataProvider;
+import org.testng.annotations.Test;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import java.util.concurrent.TimeUnit;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+/**
+ * UnitTests for the ProgressMeterData
+ *
+ * User: depristo
+ * Date: 8/24/12
+ * Time: 11:25 AM
+ * To change this template use File | Settings | File Templates.
+ */
+public class ProgressMeterDataUnitTest extends BaseTest {
+    @Test
+    public void testBasic() {
+        Assert.assertEquals(new ProgressMeterData(1.0, 2, 3).getElapsedSeconds(), 1.0);
+        Assert.assertEquals(new ProgressMeterData(1.0, 2, 3).getUnitsProcessed(), 2);
+        Assert.assertEquals(new ProgressMeterData(1.0, 2, 3).getBpProcessed(), 3);
+    }
+
+    @Test
+    public void testFraction() {
+        final double TOL = 1e-3;
+        Assert.assertEquals(new ProgressMeterData(1.0, 1, 1).calculateFractionGenomeTargetCompleted(10), 0.1, TOL);
+        Assert.assertEquals(new ProgressMeterData(1.0, 1, 2).calculateFractionGenomeTargetCompleted(10), 0.2, TOL);
+        Assert.assertEquals(new ProgressMeterData(1.0, 1, 1).calculateFractionGenomeTargetCompleted(100), 0.01, TOL);
+        Assert.assertEquals(new ProgressMeterData(1.0, 1, 2).calculateFractionGenomeTargetCompleted(100), 0.02, TOL);
+        Assert.assertEquals(new ProgressMeterData(1.0, 1, 1).calculateFractionGenomeTargetCompleted(0), 1.0, TOL);
+    }
+
+    @Test
+    public void testSecondsPerBP() {
+        final double TOL = 1e-3;
+        final long M = 1000000;
+        Assert.assertEquals(new ProgressMeterData(1.0, 1, M).secondsPerMillionBP(), 1.0, TOL);
+        Assert.assertEquals(new ProgressMeterData(1.0, 1, M/10).secondsPerMillionBP(), 10.0, TOL);
+        Assert.assertEquals(new ProgressMeterData(2.0, 1, M).secondsPerMillionBP(), 2.0, TOL);
+        Assert.assertEquals(new ProgressMeterData(1.0, 1, 0).secondsPerMillionBP(), 1e6, TOL);
+    }
+
+    @Test
+    public void testSecondsPerElement() {
+        final double TOL = 1e-3;
+        final long M = 1000000;
+        Assert.assertEquals(new ProgressMeterData(1.0, M, 1).secondsPerMillionElements(), 1.0, TOL);
+        Assert.assertEquals(new ProgressMeterData(1.0, M/10, 1).secondsPerMillionElements(), 10.0, TOL);
+        Assert.assertEquals(new ProgressMeterData(2.00, M, 1).secondsPerMillionElements(), 2.0, TOL);
+        Assert.assertEquals(new ProgressMeterData(1.0, 0, 1).secondsPerMillionElements(), 1e6, TOL);
+    }
+}
diff --git a/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/utils/recalibration/EventTypeUnitTest.java b/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/utils/recalibration/EventTypeUnitTest.java
new file mode 100644
index 0000000..7749fb2
--- /dev/null
+++ b/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/utils/recalibration/EventTypeUnitTest.java
@@ -0,0 +1,61 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.utils.recalibration;
+
+import org.broadinstitute.gatk.utils.BaseTest;
+import org.testng.Assert;
+import org.testng.annotations.Test;
+
+import java.util.*;
+
+public final class EventTypeUnitTest extends BaseTest {
+    @Test
+    public void testEventTypes() {
+        for ( final EventType et : EventType.values() ) {
+            Assert.assertNotNull(et.toString());
+            Assert.assertNotNull(et.prettyPrint());
+            Assert.assertFalse("".equals(et.toString()));
+            Assert.assertFalse("".equals(et.prettyPrint()));
+            Assert.assertEquals(EventType.eventFrom(et.ordinal()), et);
+            Assert.assertEquals(EventType.eventFrom(et.toString()), et);
+        }
+    }
+
+    @Test
+    public void testEventTypesEnumItself() {
+        final Set<String> shortReps = new HashSet<String>();
+        for ( final EventType et : EventType.values() ) {
+            Assert.assertFalse(shortReps.contains(et.toString()), "Short representative for EventType has duplicates for " + et);
+            shortReps.add(et.toString());
+        }
+        Assert.assertEquals(shortReps.size(), EventType.values().length, "Short representatives for EventType aren't unique");
+    }
+
+    @Test(expectedExceptions = IllegalArgumentException.class)
+    public void testBadString() {
+        EventType.eventFrom("asdfhalsdjfalkjsdf");
+    }
+}
diff --git a/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/utils/report/ReportMarshallerUnitTest.java b/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/utils/report/ReportMarshallerUnitTest.java
new file mode 100644
index 0000000..ebeb158
--- /dev/null
+++ b/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/utils/report/ReportMarshallerUnitTest.java
@@ -0,0 +1,64 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.utils.report;
+
+import org.broadinstitute.gatk.utils.BaseTest;
+import org.testng.annotations.Test;
+
+
+/**
+ * @author aaron
+ *         <p/>
+ *         Class ReportMarshallerUnitTest
+ *         <p/>
+ *         test out the marshaller
+ */
+public class ReportMarshallerUnitTest extends BaseTest {
+    @Test
+    public void testMarshalling() {
+        /*Configuration cfg = new Configuration();
+        try {
+            cfg.setDirectoryForTemplateLoading(new File("templates"));
+        } catch (IOException e) {
+            e.printStackTrace(); 
+        }
+        cfg.setObjectWrapper(new DefaultObjectWrapper());
+        Template temp = null;
+        try {
+            temp = cfg.createMarhsaller("myTestTemp.ftl");
+        } catch (IOException e) {
+            e.printStackTrace();
+        }
+        FakeAnalysis fa = new FakeAnalysis();
+        File fl = new File("testFile.out");
+        fl.deleteOnExit();
+        ReportMarshaller marsh = new ReportMarshaller("report",fl,temp);
+        marsh.write(fa);
+        marsh.write(fa);
+        marsh.write(fa);
+        marsh.close();*/
+    }
+}
diff --git a/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/utils/runtime/ProcessControllerUnitTest.java b/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/utils/runtime/ProcessControllerUnitTest.java
new file mode 100644
index 0000000..4fa7ef5
--- /dev/null
+++ b/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/utils/runtime/ProcessControllerUnitTest.java
@@ -0,0 +1,518 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.utils.runtime;
+
+import org.apache.commons.io.FileUtils;
+import org.apache.commons.lang.StringUtils;
+import org.broadinstitute.gatk.utils.BaseTest;
+import org.broadinstitute.gatk.utils.exceptions.ReviewedGATKException;
+import org.broadinstitute.gatk.utils.exceptions.UserException;
+import org.broadinstitute.gatk.utils.io.IOUtils;
+import org.testng.Assert;
+import org.testng.annotations.DataProvider;
+import org.testng.annotations.Test;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.Map;
+
+public class ProcessControllerUnitTest extends BaseTest {
+    private static final String NL = String.format("%n");
+
+    @Test(timeOut = 60 * 1000)
+    public void testDestroyThreadLocal() throws InterruptedException {
+        for (int i = 0; i < 3; i++) {
+            final ProcessController controller = ProcessController.getThreadLocal();
+            final ProcessSettings job = new ProcessSettings(
+                    new String[] {"sh", "-c", "echo Hello World && sleep 600 && echo Goodbye"});
+            job.getStdoutSettings().setBufferSize(-1);
+
+            Thread t = new Thread(new Runnable() {
+                @Override
+                public void run() {
+                    System.out.println("BACK: Starting on background thread");
+                    ProcessOutput result = controller.exec(job);
+                    // Assert in background thread doesn't make it to main thread but does print a trace.
+                    Assert.assertTrue(result.getExitValue() != 0, "Destroy-attempted job returned zero exit status");
+                    System.out.println("BACK: Background thread exiting");
+                }
+            });
+
+            System.out.println("MAIN: Starting background thread");
+            t.start();
+            System.out.println("MAIN: Sleeping main thread 3s");
+            Thread.sleep(3000);
+            System.out.println("MAIN: Destroying job");
+            controller.tryDestroy();
+            System.out.println("MAIN: Not waiting on background thread to exit");
+            // Using standard java.io this was blocking on linux.
+            // TODO: try again with NIO.
+            //t.join();
+            //System.out.println("MAIN: Background thread exited");
+        }
+    }
+
+    @Test
+    public void testReuseAfterError() {
+        ProcessController controller = new ProcessController();
+
+        ProcessSettings job;
+
+        for (int i = 0; i < 3; i++) {
+            // Test bad command
+            job = new ProcessSettings(new String[] {"no_such_command"});
+            try {
+                controller.exec(job);
+            } catch (ReviewedGATKException e) {
+                /* Was supposed to throw an exception */
+            }
+
+            // Test exit != 0
+            job = new ProcessSettings(new String[] {"cat", "non_existent_file"});
+            int exitValue = controller.exec(job).getExitValue();
+            Assert.assertTrue(exitValue != 0, "'cat' non existent file returned 0");
+
+            // Text success
+            job = new ProcessSettings(new String[] {"echo", "Hello World"});
+            exitValue = controller.exec(job).getExitValue();
+            Assert.assertEquals(exitValue, 0, "Echo failed");
+        }
+    }
+
+    @Test
+    public void testEnvironment() {
+        String key = "MY_NEW_VAR";
+        String value = "value is here";
+
+        ProcessSettings job = new ProcessSettings(new String[] {"sh", "-c", "echo $"+key});
+        job.getStdoutSettings().setBufferSize(-1);
+        job.setRedirectErrorStream(true);
+
+        Map<String, String> env = new HashMap<String, String>(System.getenv());
+        env.put(key, value);
+        job.setEnvironment(env);
+
+        ProcessController controller = new ProcessController();
+        ProcessOutput result = controller.exec(job);
+        int exitValue = result.getExitValue();
+
+        Assert.assertEquals(exitValue, 0, "Echo environment variable failed");
+        Assert.assertEquals(result.getStdout().getBufferString(), value + NL, "Echo environment returned unexpected output");
+    }
+
+    @Test
+    public void testDirectory() throws IOException {
+        File dir = null;
+        try {
+            dir = IOUtils.tempDir("temp.", "").getCanonicalFile();
+
+            ProcessSettings job = new ProcessSettings(new String[] {"pwd"});
+            job.getStdoutSettings().setBufferSize(-1);
+            job.setRedirectErrorStream(true);
+            job.setDirectory(dir);
+
+            ProcessController controller = new ProcessController();
+            ProcessOutput result = controller.exec(job);
+            int exitValue = result.getExitValue();
+
+            Assert.assertEquals(exitValue, 0, "Getting working directory failed");
+
+            Assert.assertEquals(result.getStdout().getBufferString(), dir.getAbsolutePath() + NL,
+                    "Setting/getting working directory returned unexpected output");
+        } finally {
+            FileUtils.deleteQuietly(dir);
+        }
+    }
+
+    @Test
+    public void testReadStdInBuffer() {
+        String bufferText = "Hello from buffer";
+        ProcessSettings job = new ProcessSettings(new String[] {"cat"});
+        job.getStdoutSettings().setBufferSize(-1);
+        job.setRedirectErrorStream(true);
+        job.getStdinSettings().setInputBuffer(bufferText);
+
+        ProcessController controller = new ProcessController();
+        ProcessOutput output = controller.exec(job);
+
+        Assert.assertEquals(output.getStdout().getBufferString(), bufferText,
+                "Unexpected output from cat stdin buffer");
+    }
+
+    @Test
+    public void testReadStdInFile() {
+        File input = null;
+        try {
+            String fileText = "Hello from file";
+            input = IOUtils.writeTempFile(fileText, "stdin.", ".txt");
+
+            ProcessSettings job = new ProcessSettings(new String[] {"cat"});
+            job.getStdoutSettings().setBufferSize(-1);
+            job.setRedirectErrorStream(true);
+            job.getStdinSettings().setInputFile(input);
+
+            ProcessController controller = new ProcessController();
+            ProcessOutput output = controller.exec(job);
+
+            Assert.assertEquals(output.getStdout().getBufferString(), fileText,
+                    "Unexpected output from cat stdin file");
+        } finally {
+            FileUtils.deleteQuietly(input);
+        }
+    }
+
+    @Test
+    public void testWriteStdOut() {
+        ProcessSettings job = new ProcessSettings(new String[] {"echo", "Testing to stdout"});
+        // Not going to call the System.setOut() for now. Just running a basic visual test.
+        job.getStdoutSettings().printStandard(true);
+        job.setRedirectErrorStream(true);
+
+        System.out.println("testWriteStdOut: Writing two lines to std out...");
+        ProcessController controller = new ProcessController();
+        controller.exec(job);
+        job.setCommand(new String[]{"cat", "non_existent_file"});
+        controller.exec(job);
+        System.out.println("testWriteStdOut: ...two lines should have been printed to std out");
+    }
+
+    @Test
+    public void testErrorToOut() throws IOException {
+        File outFile = null;
+        File errFile = null;
+        try {
+            outFile = BaseTest.createTempFile("temp", "");
+            errFile = BaseTest.createTempFile("temp", "");
+
+            ProcessSettings job = new ProcessSettings(new String[]{"cat", "non_existent_file"});
+            job.getStdoutSettings().setOutputFile(outFile);
+            job.getStdoutSettings().setBufferSize(-1);
+            job.getStderrSettings().setOutputFile(errFile);
+            job.getStderrSettings().setBufferSize(-1);
+            job.setRedirectErrorStream(true);
+
+            ProcessOutput result = new ProcessController().exec(job);
+            int exitValue = result.getExitValue();
+
+            Assert.assertTrue(exitValue != 0, "'cat' non existent file returned 0");
+
+            String fileString, bufferString;
+
+            fileString = FileUtils.readFileToString(outFile);
+            Assert.assertTrue(fileString.length() > 0, "Out file was length 0");
+
+            bufferString = result.getStdout().getBufferString();
+            Assert.assertTrue(bufferString.length() > 0, "Out buffer was length 0");
+
+            Assert.assertFalse(result.getStdout().isBufferTruncated(), "Out buffer was truncated");
+            Assert.assertEquals(bufferString.length(), fileString.length(), "Out buffer length did not match file length");
+
+            fileString = FileUtils.readFileToString(errFile);
+            Assert.assertEquals(fileString, "", "Unexpected output to err file");
+
+            bufferString = result.getStderr().getBufferString();
+            Assert.assertEquals(bufferString, "", "Unexepected output to err buffer");
+        } finally {
+            FileUtils.deleteQuietly(outFile);
+            FileUtils.deleteQuietly(errFile);
+        }
+    }
+
+    @Test
+    public void testErrorToErr() throws IOException {
+        File outFile = null;
+        File errFile = null;
+        try {
+            outFile = BaseTest.createTempFile("temp", "");
+            errFile = BaseTest.createTempFile("temp", "");
+
+            ProcessSettings job = new ProcessSettings(new String[]{"cat", "non_existent_file"});
+            job.getStdoutSettings().setOutputFile(outFile);
+            job.getStdoutSettings().setBufferSize(-1);
+            job.getStderrSettings().setOutputFile(errFile);
+            job.getStderrSettings().setBufferSize(-1);
+            job.setRedirectErrorStream(false);
+
+            ProcessOutput result = new ProcessController().exec(job);
+            int exitValue = result.getExitValue();
+
+            Assert.assertTrue(exitValue != 0, "'cat' non existent file returned 0");
+
+            String fileString, bufferString;
+
+            fileString = FileUtils.readFileToString(errFile);
+            Assert.assertTrue(fileString.length() > 0, "Err file was length 0");
+
+            bufferString = result.getStderr().getBufferString();
+            Assert.assertTrue(bufferString.length() > 0, "Err buffer was length 0");
+
+            Assert.assertFalse(result.getStderr().isBufferTruncated(), "Err buffer was truncated");
+            Assert.assertEquals(bufferString.length(), fileString.length(), "Err buffer length did not match file length");
+
+            fileString = FileUtils.readFileToString(outFile);
+            Assert.assertEquals(fileString, "", "Unexpected output to out file");
+
+            bufferString = result.getStdout().getBufferString();
+            Assert.assertEquals(bufferString, "", "Unexepected output to out buffer");
+        } finally {
+            FileUtils.deleteQuietly(outFile);
+            FileUtils.deleteQuietly(errFile);
+        }
+    }
+
+    private static final String TRUNCATE_TEXT = "Hello World";
+    private static final byte[] TRUNCATE_OUTPUT_BYTES = (TRUNCATE_TEXT + NL).getBytes();
+
+    /**
+     * @return Test truncating content vs. not truncating (run at -1/+1 size)
+     */
+    @DataProvider(name = "truncateSizes")
+    public Object[][] getTruncateBufferSizes() {
+        int l = TRUNCATE_OUTPUT_BYTES.length;
+        return new Object[][]{
+                new Object[]{0, 0},
+                new Object[]{l, l},
+                new Object[]{l + 1, l},
+                new Object[]{l - 1, l - 1}
+        };
+    }
+
+    @Test(dataProvider = "truncateSizes")
+    public void testTruncateBuffer(int truncateLen, int expectedLen) {
+        byte[] expected = Arrays.copyOf(TRUNCATE_OUTPUT_BYTES, expectedLen);
+
+        String[] command = {"echo", TRUNCATE_TEXT};
+        ProcessController controller = new ProcessController();
+
+        ProcessSettings job = new ProcessSettings(command);
+        job.getStdoutSettings().setBufferSize(truncateLen);
+        ProcessOutput result = controller.exec(job);
+
+        int exitValue = result.getExitValue();
+
+        Assert.assertEquals(exitValue, 0,
+                String.format("Echo returned %d: %s", exitValue, TRUNCATE_TEXT));
+
+        byte[] bufferBytes = result.getStdout().getBufferBytes();
+
+        Assert.assertEquals(bufferBytes, expected,
+                String.format("Output buffer didn't match (%d vs %d)", expected.length, bufferBytes.length));
+
+        boolean truncated = result.getStdout().isBufferTruncated();
+
+        Assert.assertEquals(truncated, TRUNCATE_OUTPUT_BYTES.length > truncateLen,
+                "Unexpected buffer truncation result");
+    }
+
+    private static final String[] LONG_COMMAND = getLongCommand();
+    private static final String LONG_COMMAND_STRING = StringUtils.join(LONG_COMMAND, " ");
+    private static final String LONG_COMMAND_DESCRIPTION = "<long command>";
+
+    @DataProvider(name = "echoCommands")
+    public Object[][] getEchoCommands() {
+
+        new EchoCommand(new String[]{"echo", "Hello", "World"}, "Hello World" + NL);
+        new EchoCommand(new String[]{"echo", "'Hello", "World"}, "'Hello World" + NL);
+        new EchoCommand(new String[]{"echo", "Hello", "World'"}, "Hello World'" + NL);
+        new EchoCommand(new String[]{"echo", "'Hello", "World'"}, "'Hello World'" + NL);
+
+        String[] longCommand = new String[LONG_COMMAND.length + 1];
+        longCommand[0] = "echo";
+        System.arraycopy(LONG_COMMAND, 0, longCommand, 1, LONG_COMMAND.length);
+        new EchoCommand(longCommand, LONG_COMMAND_STRING + NL) {
+            @Override
+            public String toString() {
+                return LONG_COMMAND_DESCRIPTION;
+            }
+        };
+
+        return TestDataProvider.getTests(EchoCommand.class);
+    }
+
+    @Test(dataProvider = "echoCommands")
+    public void testEcho(EchoCommand script) throws IOException {
+        File outputFile = null;
+        try {
+            outputFile = BaseTest.createTempFile("temp", "");
+
+            ProcessSettings job = new ProcessSettings(script.command);
+            if (script.output != null) {
+                job.getStdoutSettings().setOutputFile(outputFile);
+                job.getStdoutSettings().setBufferSize(script.output.getBytes().length);
+            }
+
+            ProcessOutput result = new ProcessController().exec(job);
+            int exitValue = result.getExitValue();
+
+            Assert.assertEquals(exitValue, 0,
+                    String.format("Echo returned %d: %s", exitValue, script));
+
+            if (script.output != null) {
+
+                String fileString = FileUtils.readFileToString(outputFile);
+                Assert.assertEquals(fileString, script.output,
+                        String.format("Output file didn't match (%d vs %d): %s",
+                                fileString.length(), script.output.length(), script));
+
+                String bufferString = result.getStdout().getBufferString();
+                Assert.assertEquals(bufferString, script.output,
+                        String.format("Output content didn't match (%d vs %d): %s",
+                                bufferString.length(), script.output.length(), script));
+
+                Assert.assertFalse(result.getStdout().isBufferTruncated(),
+                        "Output content was truncated: " + script);
+            }
+        } finally {
+            FileUtils.deleteQuietly(outputFile);
+        }
+    }
+
+    @Test(expectedExceptions = ReviewedGATKException.class)
+    public void testUnableToStart() {
+        ProcessSettings job = new ProcessSettings(new String[]{"no_such_command"});
+        new ProcessController().exec(job);
+    }
+
+    @DataProvider(name = "scriptCommands")
+    public Object[][] getScriptCommands() {
+        new ScriptCommand(true, "echo Hello World", "Hello World" + NL);
+        new ScriptCommand(false, "echo 'Hello World", null);
+        new ScriptCommand(false, "echo Hello World'", null);
+        new ScriptCommand(true, "echo 'Hello World'", "Hello World" + NL);
+        new ScriptCommand(true, "echo \"Hello World\"", "Hello World" + NL);
+        new ScriptCommand(false, "no_such_echo Hello World", null);
+        new ScriptCommand(true, "echo #", NL);
+        new ScriptCommand(true, "echo \\#", "#" + NL);
+        new ScriptCommand(true, "echo \\\\#", "\\#" + NL);
+
+        new ScriptCommand(true, "echo " + LONG_COMMAND_STRING, LONG_COMMAND_STRING + NL) {
+            @Override
+            public String toString() {
+                return LONG_COMMAND_DESCRIPTION;
+            }
+        };
+
+        return TestDataProvider.getTests(ScriptCommand.class);
+    }
+
+    @Test(dataProvider = "scriptCommands")
+    public void testScript(ScriptCommand script) throws IOException {
+        File scriptFile = null;
+        File outputFile = null;
+        try {
+            scriptFile = writeScript(script.content);
+            outputFile = BaseTest.createTempFile("temp", "");
+
+            ProcessSettings job = new ProcessSettings(new String[]{"sh", scriptFile.getAbsolutePath()});
+            if (script.output != null) {
+                job.getStdoutSettings().setOutputFile(outputFile);
+                job.getStdoutSettings().setBufferSize(script.output.getBytes().length);
+            }
+
+            ProcessOutput result = new ProcessController().exec(job);
+            int exitValue = result.getExitValue();
+
+            Assert.assertEquals(exitValue == 0, script.succeed,
+                    String.format("Script returned %d: %s", exitValue, script));
+
+            if (script.output != null) {
+
+                String fileString = FileUtils.readFileToString(outputFile);
+                Assert.assertEquals(fileString, script.output,
+                        String.format("Output file didn't match (%d vs %d): %s",
+                                fileString.length(), script.output.length(), script));
+
+                String bufferString = result.getStdout().getBufferString();
+                Assert.assertEquals(bufferString, script.output,
+                        String.format("Output content didn't match (%d vs %d): %s",
+                                bufferString.length(), script.output.length(), script));
+
+                Assert.assertFalse(result.getStdout().isBufferTruncated(),
+                        "Output content was truncated: " + script);
+            }
+        } finally {
+            FileUtils.deleteQuietly(scriptFile);
+            FileUtils.deleteQuietly(outputFile);
+        }
+    }
+
+    private static String[] getLongCommand() {
+        // This command fails on some systems with a 4096 character limit when run via the old sh -c "echo ...",
+        // but works on the same systems when run via sh <script>
+        int cnt = 500;
+        String[] command = new String[cnt];
+        for (int i = 1; i <= cnt; i++) {
+            command[i - 1] = String.format("%03d______", i);
+        }
+        return command;
+    }
+
+    private static File writeScript(String contents) {
+        try {
+            File file = BaseTest.createTempFile("temp", "");
+            FileUtils.writeStringToFile(file, contents);
+            return file;
+        } catch (IOException e) {
+            throw new UserException.BadTmpDir(e.getMessage());
+        }
+    }
+
+    private static class EchoCommand extends TestDataProvider {
+        public final String[] command;
+        public final String output;
+
+        public EchoCommand(String[] command, String output) {
+            super(EchoCommand.class);
+            this.command = command;
+            this.output = output;
+        }
+
+        @Override
+        public String toString() {
+            return StringUtils.join(command, " ");
+        }
+    }
+
+    public static class ScriptCommand extends TestDataProvider {
+        public final boolean succeed;
+        public final String content;
+        public final String output;
+
+        public ScriptCommand(boolean succeed, String content, String output) {
+            super(ScriptCommand.class);
+            this.succeed = succeed;
+            this.content = content;
+            this.output = output;
+        }
+
+        @Override
+        public String toString() {
+            return content;
+        }
+    }
+}
diff --git a/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/utils/runtime/RuntimeUtilsUnitTest.java b/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/utils/runtime/RuntimeUtilsUnitTest.java
new file mode 100644
index 0000000..9573774
--- /dev/null
+++ b/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/utils/runtime/RuntimeUtilsUnitTest.java
@@ -0,0 +1,42 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.utils.runtime;
+
+import org.broadinstitute.gatk.utils.BaseTest;
+import org.testng.Assert;
+import org.testng.annotations.Test;
+
+public class RuntimeUtilsUnitTest extends BaseTest {
+    @Test
+    public void testWhichExists() {
+        Assert.assertNotNull(RuntimeUtils.which("ls"), "Unable to locate ls");
+    }
+
+    @Test
+    public void testWhichNotExists() {
+        Assert.assertNull(RuntimeUtils.which("does_not_exist"), "Found nonexistent binary: does_not_exist");
+    }
+}
diff --git a/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/utils/sam/AlignmentUtilsUnitTest.java b/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/utils/sam/AlignmentUtilsUnitTest.java
new file mode 100644
index 0000000..3281570
--- /dev/null
+++ b/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/utils/sam/AlignmentUtilsUnitTest.java
@@ -0,0 +1,1044 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.utils.sam;
+
+import htsjdk.samtools.*;
+import org.apache.commons.lang.ArrayUtils;
+import org.broadinstitute.gatk.utils.Utils;
+import org.broadinstitute.gatk.utils.haplotype.Haplotype;
+import org.broadinstitute.gatk.utils.pileup.PileupElement;
+import org.testng.Assert;
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.DataProvider;
+import org.testng.annotations.Test;
+
+import java.util.*;
+
+public class AlignmentUtilsUnitTest {
+    private final static boolean DEBUG = false;
+    private SAMFileHeader header;
+
+    /** Basic aligned and mapped read. */
+    private SAMRecord readMapped;
+
+    /** Read with no contig specified in the read, -L UNMAPPED */
+    private SAMRecord readNoReference;
+
+    /** This read has a start position, but is flagged that it's not mapped. */
+    private SAMRecord readUnmappedFlag;
+
+    /** This read says it's aligned, but to a contig not in the header. */
+    private SAMRecord readUnknownContig;
+
+    /** This read says it's aligned, but actually has an unknown start. */
+    private SAMRecord readUnknownStart;
+
+    @BeforeClass
+    public void init() {
+        header = ArtificialSAMUtils.createArtificialSamHeader(3, 1, ArtificialSAMUtils.DEFAULT_READ_LENGTH * 2);
+
+        readMapped = createMappedRead("mapped", 1);
+
+        readNoReference = createUnmappedRead("unmappedNoReference");
+
+        readUnmappedFlag = createMappedRead("unmappedFlagged", 2);
+        readUnmappedFlag.setReadUnmappedFlag(true);
+
+        readUnknownContig = createMappedRead("unknownContig", 3);
+        readUnknownContig.setReferenceName("unknownContig");
+
+        readUnknownStart = createMappedRead("unknownStart", 1);
+        readUnknownStart.setAlignmentStart(SAMRecord.NO_ALIGNMENT_START);
+    }
+
+    /**
+     * Test for -L UNMAPPED
+     */
+    @DataProvider(name = "genomeLocUnmappedReadTests")
+    public Object[][] getGenomeLocUnmappedReadTests() {
+        return new Object[][] {
+                new Object[] {readNoReference, true},
+                new Object[] {readMapped, false},
+                new Object[] {readUnmappedFlag, false},
+                new Object[] {readUnknownContig, false},
+                new Object[] {readUnknownStart, false}
+        };
+    }
+    @Test(enabled = !DEBUG, dataProvider = "genomeLocUnmappedReadTests")
+    public void testIsReadGenomeLocUnmapped(SAMRecord read, boolean expected) {
+        Assert.assertEquals(AlignmentUtils.isReadGenomeLocUnmapped(read), expected);
+    }
+
+    /**
+     * Test for read being truly unmapped
+     */
+    @DataProvider(name = "unmappedReadTests")
+    public Object[][] getUnmappedReadTests() {
+        return new Object[][] {
+                new Object[] {readNoReference, true},
+                new Object[] {readMapped, false},
+                new Object[] {readUnmappedFlag, true},
+                new Object[] {readUnknownContig, false},
+                new Object[] {readUnknownStart, true}
+        };
+    }
+    @Test(enabled = !DEBUG, dataProvider = "unmappedReadTests")
+    public void testIsReadUnmapped(SAMRecord read, boolean expected) {
+        Assert.assertEquals(AlignmentUtils.isReadUnmapped(read), expected);
+    }
+
+    private SAMRecord createUnmappedRead(String name) {
+        return ArtificialSAMUtils.createArtificialRead(
+                header,
+                name,
+                SAMRecord.NO_ALIGNMENT_REFERENCE_INDEX,
+                SAMRecord.NO_ALIGNMENT_START,
+                ArtificialSAMUtils.DEFAULT_READ_LENGTH);
+    }
+
+    private SAMRecord createMappedRead(String name, int start) {
+        return ArtificialSAMUtils.createArtificialRead(
+                header,
+                name,
+                0,
+                start,
+                ArtificialSAMUtils.DEFAULT_READ_LENGTH);
+    }
+
+    private final List<List<CigarElement>> makeCigarElementCombinations() {
+        // this functionality can be adapted to provide input data for whatever you might want in your data
+        final List<CigarElement> cigarElements = new LinkedList<CigarElement>();
+        for ( final int size : Arrays.asList(0, 10) ) {
+            for ( final CigarOperator op : CigarOperator.values() ) {
+                cigarElements.add(new CigarElement(size, op));
+            }
+        }
+
+        final List<List<CigarElement>> combinations = new LinkedList<List<CigarElement>>();
+        for ( final int nElements : Arrays.asList(1, 2, 3) ) {
+            combinations.addAll(Utils.makePermutations(cigarElements, nElements, true));
+        }
+
+        return combinations;
+    }
+
+
+    @DataProvider(name = "CalcNumDifferentBasesData")
+    public Object[][] makeCalcNumDifferentBasesData() {
+        List<Object[]> tests = new ArrayList<Object[]>();
+
+        tests.add(new Object[]{"5M", "ACGTA", "ACGTA", 0});
+        tests.add(new Object[]{"5M", "ACGTA", "ACGTT", 1});
+        tests.add(new Object[]{"5M", "ACGTA", "TCGTT", 2});
+        tests.add(new Object[]{"5M", "ACGTA", "TTGTT", 3});
+        tests.add(new Object[]{"5M", "ACGTA", "TTTTT", 4});
+        tests.add(new Object[]{"5M", "ACGTA", "TTTCT", 5});
+        tests.add(new Object[]{"2M3I3M", "ACGTA", "ACNNNGTA", 3});
+        tests.add(new Object[]{"2M3I3M", "ACGTA", "ACNNNGTT", 4});
+        tests.add(new Object[]{"2M3I3M", "ACGTA", "TCNNNGTT", 5});
+        tests.add(new Object[]{"2M2D1M", "ACGTA", "ACA", 2});
+        tests.add(new Object[]{"2M2D1M", "ACGTA", "ACT", 3});
+        tests.add(new Object[]{"2M2D1M", "ACGTA", "TCT", 4});
+        tests.add(new Object[]{"2M2D1M", "ACGTA", "TGT", 5});
+
+        return tests.toArray(new Object[][]{});
+    }
+
+    @Test(enabled = true, dataProvider = "CalcNumDifferentBasesData")
+    public void testCalcNumDifferentBases(final String cigarString, final String ref, final String read, final int expectedDifferences) {
+        final Cigar cigar = TextCigarCodec.getSingleton().decode(cigarString);
+        Assert.assertEquals(AlignmentUtils.calcNumDifferentBases(cigar, ref.getBytes(), read.getBytes()), expectedDifferences);
+    }
+
+    @DataProvider(name = "NumAlignedBasesCountingSoftClips")
+    public Object[][] makeNumAlignedBasesCountingSoftClips() {
+        List<Object[]> tests = new ArrayList<Object[]>();
+
+        final EnumSet<CigarOperator> alignedToGenome = EnumSet.of(CigarOperator.M, CigarOperator.EQ, CigarOperator.X, CigarOperator.S);
+        for ( final List<CigarElement> elements : makeCigarElementCombinations() ) {
+            int n = 0;
+            for ( final CigarElement elt : elements ) n += alignedToGenome.contains(elt.getOperator()) ? elt.getLength() : 0;
+            tests.add(new Object[]{new Cigar(elements), n});
+        }
+
+        tests.add(new Object[]{null, 0});
+
+        return tests.toArray(new Object[][]{});
+    }
+
+    @Test(enabled = !DEBUG, dataProvider = "NumAlignedBasesCountingSoftClips")
+    public void testNumAlignedBasesCountingSoftClips(final Cigar cigar, final int expected) {
+        final GATKSAMRecord read = ArtificialSAMUtils.createArtificialRead(header, "myRead", 0, 1, cigar == null ? 10 : cigar.getReadLength());
+        read.setCigar(cigar);
+        Assert.assertEquals(AlignmentUtils.getNumAlignedBasesCountingSoftClips(read), expected, "Cigar " + cigar + " failed NumAlignedBasesCountingSoftClips");
+    }
+
+    @DataProvider(name = "CigarHasZeroElement")
+    public Object[][] makeCigarHasZeroElement() {
+        List<Object[]> tests = new ArrayList<Object[]>();
+
+        for ( final List<CigarElement> elements : makeCigarElementCombinations() ) {
+            boolean hasZero = false;
+            for ( final CigarElement elt : elements ) hasZero = hasZero || elt.getLength() == 0;
+            tests.add(new Object[]{new Cigar(elements), hasZero});
+        }
+
+        return tests.toArray(new Object[][]{});
+    }
+
+    @Test(enabled = !DEBUG, dataProvider = "CigarHasZeroElement")
+    public void testCigarHasZeroSize(final Cigar cigar, final boolean hasZero) {
+        Assert.assertEquals(AlignmentUtils.cigarHasZeroSizeElement(cigar), hasZero, "Cigar " + cigar.toString() + " failed cigarHasZeroSizeElement");
+    }
+
+    @DataProvider(name = "NumHardClipped")
+    public Object[][] makeNumHardClipped() {
+        List<Object[]> tests = new ArrayList<Object[]>();
+
+        for ( final List<CigarElement> elements : makeCigarElementCombinations() ) {
+            int n = 0;
+            for ( final CigarElement elt : elements ) n += elt.getOperator() == CigarOperator.H ? elt.getLength() : 0;
+            tests.add(new Object[]{new Cigar(elements), n});
+        }
+
+        tests.add(new Object[]{null, 0});
+
+        return tests.toArray(new Object[][]{});
+    }
+
+    @Test(enabled = !DEBUG, dataProvider = "NumHardClipped")
+    public void testNumHardClipped(final Cigar cigar, final int expected) {
+        final GATKSAMRecord read = ArtificialSAMUtils.createArtificialRead(header, "myRead", 0, 1, cigar == null ? 10 : cigar.getReadLength());
+        read.setCigar(cigar);
+        Assert.assertEquals(AlignmentUtils.getNumHardClippedBases(read), expected, "Cigar " + cigar + " failed num hard clips");
+    }
+
+    @DataProvider(name = "NumAlignedBlocks")
+    public Object[][] makeNumAlignedBlocks() {
+        List<Object[]> tests = new ArrayList<Object[]>();
+
+        for ( final List<CigarElement> elements : makeCigarElementCombinations() ) {
+            int n = 0;
+            for ( final CigarElement elt : elements ) {
+                switch ( elt.getOperator() ) {
+                    case M:case X:case EQ: n++; break;
+                    default: break;
+                }
+            }
+            tests.add(new Object[]{new Cigar(elements), n});
+        }
+
+        tests.add(new Object[]{null, 0});
+
+        return tests.toArray(new Object[][]{});
+    }
+
+    @Test(enabled = !DEBUG, dataProvider = "NumAlignedBlocks")
+    public void testNumAlignedBlocks(final Cigar cigar, final int expected) {
+        final GATKSAMRecord read = ArtificialSAMUtils.createArtificialRead(header, "myRead", 0, 1, cigar == null ? 10 : cigar.getReadLength());
+        read.setCigar(cigar);
+        Assert.assertEquals(AlignmentUtils.getNumAlignmentBlocks(read), expected, "Cigar " + cigar + " failed NumAlignedBlocks");
+    }
+
+    @DataProvider(name = "ConsolidateCigarData")
+    public Object[][] makeConsolidateCigarData() {
+        List<Object[]> tests = new ArrayList<Object[]>();
+
+        // this functionality can be adapted to provide input data for whatever you might want in your data
+        tests.add(new Object[]{"1M1M", "2M"});
+        tests.add(new Object[]{"2M", "2M"});
+        tests.add(new Object[]{"2M0M", "2M"});
+        tests.add(new Object[]{"0M2M", "2M"});
+        tests.add(new Object[]{"0M2M0M0I0M1M", "3M"});
+        tests.add(new Object[]{"2M0M1M", "3M"});
+        tests.add(new Object[]{"1M1M1M1D2M1M", "3M1D3M"});
+        tests.add(new Object[]{"6M6M6M", "18M"});
+
+        final List<CigarElement> elements = new LinkedList<CigarElement>();
+        int i = 1;
+        for ( final CigarOperator op : CigarOperator.values() ) {
+            elements.add(new CigarElement(i++, op));
+        }
+        for ( final List<CigarElement> ops : Utils.makePermutations(elements,  3, false) ) {
+            final String expected = new Cigar(ops).toString();
+            final List<CigarElement> cutElements = new LinkedList<CigarElement>();
+            for ( final CigarElement elt : ops ) {
+                for ( int j = 0; j < elt.getLength(); j++ ) {
+                    cutElements.add(new CigarElement(1, elt.getOperator()));
+                }
+            }
+
+            final String actual = new Cigar(cutElements).toString();
+            tests.add(new Object[]{actual, expected});
+        }
+
+        return tests.toArray(new Object[][]{});
+    }
+
+    @Test(enabled = !DEBUG, dataProvider = "ConsolidateCigarData")
+    public void testConsolidateCigarWithData(final String testCigarString, final String expectedCigarString) {
+        final Cigar testCigar = TextCigarCodec.getSingleton().decode(testCigarString);
+        final Cigar expectedCigar = TextCigarCodec.getSingleton().decode(expectedCigarString);
+        final Cigar actualCigar = AlignmentUtils.consolidateCigar(testCigar);
+        Assert.assertEquals(actualCigar, expectedCigar);
+    }
+
+    @DataProvider(name = "SoftClipsDataProvider")
+    public Object[][] makeSoftClipsDataProvider() {
+        List<Object[]> tests = new ArrayList<Object[]>();
+
+        // this functionality can be adapted to provide input data for whatever you might want in your data
+        for ( final int lengthOfLeftClip : Arrays.asList(0, 1, 10) ) {
+            for ( final int lengthOfRightClip : Arrays.asList(0, 1, 10) ) {
+                for ( final int qualThres : Arrays.asList(10, 20, 30) ) {
+                    for ( final String middleOp : Arrays.asList("M", "D") ) {
+                        for ( final int matchSize : Arrays.asList(0, 1, 10) ) {
+                            final byte[] left = makeQualArray(lengthOfLeftClip, qualThres);
+                            final byte[] right = makeQualArray(lengthOfRightClip, qualThres);
+                            int n = 0;
+                            for ( int i = 0; i < left.length; i++ ) n += left[i] > qualThres ? 1 : 0;
+                            for ( int i = 0; i < right.length; i++ ) n += right[i] > qualThres ? 1 : 0;
+                            tests.add(new Object[]{left, matchSize, middleOp, right, qualThres, n});
+                        }
+                    }
+                }
+            }
+        }
+
+        return tests.toArray(new Object[][]{});
+    }
+
+    private byte[] makeQualArray(final int length, final int qualThreshold) {
+        final byte[] array = new byte[length];
+        for ( int i = 0; i < array.length; i++ )
+            array[i] = (byte)(qualThreshold + ( i % 2 == 0 ? 1 : - 1 ));
+        return array;
+    }
+
+    @Test(enabled = !DEBUG, dataProvider = "SoftClipsDataProvider")
+    public void testSoftClipsData(final byte[] qualsOfSoftClipsOnLeft, final int middleSize, final String middleOp, final byte[] qualOfSoftClipsOnRight, final int qualThreshold, final int numExpected) {
+        final int readLength = (middleOp.equals("D") ? 0 : middleSize) + qualOfSoftClipsOnRight.length + qualsOfSoftClipsOnLeft.length;
+        final GATKSAMRecord read = ArtificialSAMUtils.createArtificialRead(header, "myRead", 0, 1, readLength);
+        final byte[] bases = Utils.dupBytes((byte) 'A', readLength);
+        final byte[] matchBytes = middleOp.equals("D") ? new byte[]{} : Utils.dupBytes((byte)30, middleSize);
+        final byte[] quals = ArrayUtils.addAll(ArrayUtils.addAll(qualsOfSoftClipsOnLeft, matchBytes), qualOfSoftClipsOnRight);
+
+        // set the read's bases and quals
+        read.setReadBases(bases);
+        read.setBaseQualities(quals);
+
+        final StringBuilder cigar = new StringBuilder();
+        if (qualsOfSoftClipsOnLeft.length > 0 ) cigar.append(qualsOfSoftClipsOnLeft.length + "S");
+        if (middleSize > 0 ) cigar.append(middleSize + middleOp);
+        if (qualOfSoftClipsOnRight.length > 0 ) cigar.append(qualOfSoftClipsOnRight.length + "S");
+
+        read.setCigarString(cigar.toString());
+
+        final int actual = AlignmentUtils.calcNumHighQualitySoftClips(read, (byte) qualThreshold);
+        Assert.assertEquals(actual, numExpected, "Wrong number of soft clips detected for read " + read.getSAMString());
+    }
+
+    ////////////////////////////////////////////
+    // Test AlignmentUtils.getMismatchCount() //
+    ////////////////////////////////////////////
+
+    @DataProvider(name = "MismatchCountDataProvider")
+    public Object[][] makeMismatchCountDataProvider() {
+        List<Object[]> tests = new ArrayList<Object[]>();
+
+        final int readLength = 20;
+        final int lengthOfIndel = 2;
+        final int locationOnReference = 10;
+        final byte[] reference = Utils.dupBytes((byte)'A', readLength);
+        final byte[] quals = Utils.dupBytes((byte)'A', readLength);
+
+
+        for ( int startOnRead = 0; startOnRead <= readLength; startOnRead++ ) {
+            for ( int basesToRead = 0; basesToRead <= readLength; basesToRead++ ) {
+                for ( final int lengthOfSoftClip : Arrays.asList(0, 1, 10) ) {
+                    for ( final int lengthOfFirstM : Arrays.asList(0, 3) ) {
+                        for ( final char middleOp : Arrays.asList('M', 'D', 'I') ) {
+                            for ( final int mismatchLocation : Arrays.asList(-1, 0, 5, 10, 15, 19) ) {
+
+                                final GATKSAMRecord read = ArtificialSAMUtils.createArtificialRead(header, "myRead", 0, locationOnReference, readLength);
+
+                                // set the read's bases and quals
+                                final byte[] readBases = reference.clone();
+                                // create the mismatch if requested
+                                if ( mismatchLocation != -1 )
+                                    readBases[mismatchLocation] = (byte)'C';
+                                read.setReadBases(readBases);
+                                read.setBaseQualities(quals);
+
+                                // create the CIGAR string
+                                read.setCigarString(buildTestCigarString(middleOp, lengthOfSoftClip, lengthOfFirstM, lengthOfIndel, readLength));
+
+                                // now, determine whether or not there's a mismatch
+                                final boolean isMismatch;
+                                if ( mismatchLocation < startOnRead || mismatchLocation >= startOnRead + basesToRead || mismatchLocation < lengthOfSoftClip ) {
+                                    isMismatch = false;
+                                } else if ( middleOp == 'M' || middleOp == 'D' || mismatchLocation < lengthOfSoftClip + lengthOfFirstM || mismatchLocation >= lengthOfSoftClip + lengthOfFirstM + lengthOfIndel ) {
+                                    isMismatch = true;
+                                } else {
+                                    isMismatch = false;
+                                }
+
+                                tests.add(new Object[]{read, locationOnReference, startOnRead, basesToRead, isMismatch});
+                            }
+                        }
+                    }
+                }
+            }
+        }
+
+        // Adding test to make sure soft-clipped reads go through the exceptions thrown at the beginning of the getMismatchCount method
+        // todo: incorporate cigars with right-tail soft-clips in the systematic tests above.
+        GATKSAMRecord read = ArtificialSAMUtils.createArtificialRead(header, "myRead", 0, 10, 20);
+        read.setReadBases(reference);
+        read.setBaseQualities(quals);
+        read.setCigarString("10S5M5S");
+        tests.add(new Object[]{read, 10, read.getAlignmentStart(), read.getReadLength(), false});
+
+        return tests.toArray(new Object[][]{});
+    }
+
+    @Test(enabled = !DEBUG, dataProvider = "MismatchCountDataProvider")
+    public void testMismatchCountData(final GATKSAMRecord read, final int refIndex, final int startOnRead, final int basesToRead, final boolean isMismatch) {
+        final byte[] reference = Utils.dupBytes((byte)'A', 100);
+        final int actual = AlignmentUtils.getMismatchCount(read, reference, refIndex, startOnRead, basesToRead).numMismatches;
+        Assert.assertEquals(actual, isMismatch ? 1 : 0, "Wrong number of mismatches detected for read " + read.getSAMString());
+    }
+
+    private static String buildTestCigarString(final char middleOp, final int lengthOfSoftClip, final int lengthOfFirstM, final int lengthOfIndel, final int readLength) {
+        final StringBuilder cigar = new StringBuilder();
+        int remainingLength = readLength;
+
+        // add soft clips to the beginning of the read
+        if (lengthOfSoftClip > 0 ) {
+            cigar.append(lengthOfSoftClip).append("S");
+            remainingLength -= lengthOfSoftClip;
+        }
+
+        if ( middleOp == 'M' ) {
+            cigar.append(remainingLength).append("M");
+        } else {
+            if ( lengthOfFirstM > 0 ) {
+                cigar.append(lengthOfFirstM).append("M");
+                remainingLength -= lengthOfFirstM;
+            }
+
+            if ( middleOp == 'D' ) {
+                cigar.append(lengthOfIndel).append("D");
+            } else {
+                cigar.append(lengthOfIndel).append("I");
+                remainingLength -= lengthOfIndel;
+            }
+            cigar.append(remainingLength).append("M");
+        }
+
+        return cigar.toString();
+    }
+
+    ////////////////////////////////////////////////////////
+    // Test AlignmentUtils.calcAlignmentByteArrayOffset() //
+    ////////////////////////////////////////////////////////
+
+    @DataProvider(name = "AlignmentByteArrayOffsetDataProvider")
+    public Object[][] makeAlignmentByteArrayOffsetDataProvider() {
+        List<Object[]> tests = new ArrayList<Object[]>();
+
+        final int readLength = 20;
+        final int lengthOfIndel = 2;
+        final int locationOnReference = 20;
+
+        for ( int offset = 0; offset < readLength; offset++ ) {
+            for ( final int lengthOfSoftClip : Arrays.asList(0, 1, 10) ) {
+                for ( final int lengthOfFirstM : Arrays.asList(0, 3) ) {
+                    for ( final char middleOp : Arrays.asList('M', 'D', 'I') ) {
+
+                        final GATKSAMRecord read = ArtificialSAMUtils.createArtificialRead(header, "myRead", 0, locationOnReference, readLength);
+                        // create the CIGAR string
+                        read.setCigarString(buildTestCigarString(middleOp, lengthOfSoftClip, lengthOfFirstM, lengthOfIndel, readLength));
+
+                        // now, determine the expected alignment offset
+                        final int expected;
+                        boolean isDeletion = false;
+                        if ( offset < lengthOfSoftClip ) {
+                            expected = 0;
+                        } else if ( middleOp == 'M' || offset < lengthOfSoftClip + lengthOfFirstM ) {
+                            expected = offset - lengthOfSoftClip;
+                        } else if ( offset < lengthOfSoftClip + lengthOfFirstM + lengthOfIndel ) {
+                            if ( middleOp == 'D' ) {
+                                isDeletion = true;
+                                expected = offset - lengthOfSoftClip;
+                            } else {
+                                expected = lengthOfFirstM;
+                            }
+                        } else {
+                            expected = offset - lengthOfSoftClip - (middleOp == 'I' ? lengthOfIndel : -lengthOfIndel);
+                        }
+
+                        tests.add(new Object[]{read.getCigar(), offset, expected, isDeletion, lengthOfSoftClip});
+                    }
+                }
+            }
+        }
+
+        return tests.toArray(new Object[][]{});
+    }
+
+    @Test(enabled = !DEBUG, dataProvider = "AlignmentByteArrayOffsetDataProvider")
+    public void testAlignmentByteArrayOffsetData(final Cigar cigar, final int offset, final int expectedResult, final boolean isDeletion, final int lengthOfSoftClip) {
+        final int actual = AlignmentUtils.calcAlignmentByteArrayOffset(cigar, isDeletion ? -1 : offset, isDeletion, 20, 20 + offset - lengthOfSoftClip);
+        Assert.assertEquals(actual, expectedResult, "Wrong alignment offset detected for cigar " + cigar.toString());
+    }
+
+    ////////////////////////////////////////////////////
+    // Test AlignmentUtils.readToAlignmentByteArray() //
+    ////////////////////////////////////////////////////
+
+    @DataProvider(name = "ReadToAlignmentByteArrayDataProvider")
+    public Object[][] makeReadToAlignmentByteArrayDataProvider() {
+        List<Object[]> tests = new ArrayList<Object[]>();
+
+        final int readLength = 20;
+        final int lengthOfIndel = 2;
+        final int locationOnReference = 20;
+
+        for ( final int lengthOfSoftClip : Arrays.asList(0, 1, 10) ) {
+            for ( final int lengthOfFirstM : Arrays.asList(0, 3) ) {
+                for ( final char middleOp : Arrays.asList('M', 'D', 'I') ) {
+
+                    final GATKSAMRecord read = ArtificialSAMUtils.createArtificialRead(header, "myRead", 0, locationOnReference, readLength);
+                    // create the CIGAR string
+                    read.setCigarString(buildTestCigarString(middleOp, lengthOfSoftClip, lengthOfFirstM, lengthOfIndel, readLength));
+
+                    // now, determine the byte array size
+                    final int expected = readLength - lengthOfSoftClip - (middleOp == 'I' ? lengthOfIndel : (middleOp == 'D' ? -lengthOfIndel : 0));
+                    final int indelBasesStart = middleOp != 'M' ? lengthOfFirstM : -1;
+
+                    tests.add(new Object[]{read.getCigar(), expected, middleOp, indelBasesStart, lengthOfIndel});
+                }
+            }
+        }
+
+        return tests.toArray(new Object[][]{});
+    }
+
+    @Test(enabled = !DEBUG, dataProvider = "ReadToAlignmentByteArrayDataProvider")
+    public void testReadToAlignmentByteArrayData(final Cigar cigar, final int expectedLength, final char middleOp, final int startOfIndelBases, final int lengthOfDeletion) {
+        final byte[] read = Utils.dupBytes((byte)'A', cigar.getReadLength());
+        final byte[] alignment = AlignmentUtils.readToAlignmentByteArray(cigar, read);
+
+        Assert.assertEquals(alignment.length, expectedLength, "Wrong alignment length detected for cigar " + cigar.toString());
+
+        for ( int i = 0; i < alignment.length; i++ ) {
+            final byte expectedBase;
+            if ( middleOp == 'D' && i >= startOfIndelBases && i < startOfIndelBases + lengthOfDeletion )
+                expectedBase = PileupElement.DELETION_BASE;
+            else if ( middleOp == 'I' && i == startOfIndelBases - 1 )
+                expectedBase = PileupElement.A_FOLLOWED_BY_INSERTION_BASE;
+            else
+                expectedBase = (byte)'A';
+            Assert.assertEquals(alignment[i], expectedBase, "Wrong base detected at position " + i);
+        }
+    }
+
+    //////////////////////////////////////////
+    // Test AlignmentUtils.leftAlignIndel() //
+    //////////////////////////////////////////
+
+    @DataProvider(name = "LeftAlignIndelDataProvider")
+    public Object[][] makeLeftAlignIndelDataProvider() {
+        List<Object[]> tests = new ArrayList<Object[]>();
+
+        final byte[] repeat1Reference = "ABCDEFGHIJKLMNOPXXXXXXXXXXABCDEFGHIJKLMNOP".getBytes();
+        final byte[] repeat2Reference = "ABCDEFGHIJKLMNOPXYXYXYXYXYABCDEFGHIJKLMNOP".getBytes();
+        final byte[] repeat3Reference = "ABCDEFGHIJKLMNOPXYZXYZXYZXYZABCDEFGHIJKLMN".getBytes();
+        final int referenceLength = repeat1Reference.length;
+
+        for ( int indelStart = 0; indelStart < repeat1Reference.length; indelStart++ ) {
+            for ( final int indelSize : Arrays.asList(0, 1, 2, 3, 4) ) {
+                for ( final char indelOp : Arrays.asList('D', 'I') ) {
+
+                    if ( indelOp == 'D' && indelStart + indelSize >= repeat1Reference.length )
+                        continue;
+
+                    final int readLength = referenceLength - (indelOp == 'D' ? indelSize : -indelSize);
+
+                    // create the original CIGAR string
+                    final GATKSAMRecord read = ArtificialSAMUtils.createArtificialRead(header, "myRead", 0, 1, readLength);
+                    read.setCigarString(buildTestCigarString(indelSize == 0 ? 'M' : indelOp, 0, indelStart, indelSize, readLength));
+                    final Cigar originalCigar = read.getCigar();
+
+                    final Cigar expectedCigar1 = makeExpectedCigar1(originalCigar, indelOp, indelStart, indelSize, readLength);
+                    final byte[] readString1 = makeReadString(repeat1Reference, indelOp, indelStart, indelSize, readLength, 1);
+                    tests.add(new Object[]{originalCigar, expectedCigar1, repeat1Reference, readString1, 1});
+
+                    final Cigar expectedCigar2 = makeExpectedCigar2(originalCigar, indelOp, indelStart, indelSize, readLength);
+                    final byte[] readString2 = makeReadString(repeat2Reference, indelOp, indelStart, indelSize, readLength, 2);
+                    tests.add(new Object[]{originalCigar, expectedCigar2, repeat2Reference, readString2, 2});
+
+                    final Cigar expectedCigar3 = makeExpectedCigar3(originalCigar, indelOp, indelStart, indelSize, readLength);
+                    final byte[] readString3 = makeReadString(repeat3Reference, indelOp, indelStart, indelSize, readLength, 3);
+                    tests.add(new Object[]{originalCigar, expectedCigar3, repeat3Reference, readString3, 3});
+                }
+            }
+        }
+
+        return tests.toArray(new Object[][]{});
+    }
+
+    private Cigar makeExpectedCigar1(final Cigar originalCigar, final char indelOp, final int indelStart, final int indelSize, final int readLength) {
+        if ( indelSize == 0 || indelStart < 17 || indelStart > (26 - (indelOp == 'D' ? indelSize : 0)) )
+            return originalCigar;
+
+        final GATKSAMRecord read = ArtificialSAMUtils.createArtificialRead(header, "myRead", 0, 1, readLength);
+        read.setCigarString(buildTestCigarString(indelOp, 0, 16, indelSize, readLength));
+        return read.getCigar();
+    }
+
+    private Cigar makeExpectedCigar2(final Cigar originalCigar, final char indelOp, final int indelStart, final int indelSize, final int readLength) {
+        if ( indelStart < 17 || indelStart > (26 - (indelOp == 'D' ? indelSize : 0)) )
+            return originalCigar;
+
+        final GATKSAMRecord read = ArtificialSAMUtils.createArtificialRead(header, "myRead", 0, 1, readLength);
+
+        if ( indelOp == 'I' && (indelSize == 1 || indelSize == 3) && indelStart % 2 == 1 )
+            read.setCigarString(buildTestCigarString(indelOp, 0, Math.max(indelStart - indelSize, 16), indelSize, readLength));
+        else if ( (indelSize == 2 || indelSize == 4) && (indelOp == 'D' || indelStart % 2 == 0) )
+            read.setCigarString(buildTestCigarString(indelOp, 0, 16, indelSize, readLength));
+        else
+            return originalCigar;
+
+        return read.getCigar();
+    }
+
+    private Cigar makeExpectedCigar3(final Cigar originalCigar, final char indelOp, final int indelStart, final int indelSize, final int readLength) {
+        if ( indelStart < 17 || indelStart > (28 - (indelOp == 'D' ? indelSize : 0)) )
+            return originalCigar;
+
+        final GATKSAMRecord read = ArtificialSAMUtils.createArtificialRead(header, "myRead", 0, 1, readLength);
+
+        if ( indelSize == 3 && (indelOp == 'D' || indelStart % 3 == 1) )
+            read.setCigarString(buildTestCigarString(indelOp, 0, 16, indelSize, readLength));
+        else if ( (indelOp == 'I' && indelSize == 4 && indelStart % 3 == 2) ||
+                (indelOp == 'I' && indelSize == 2 && indelStart % 3 == 0) ||
+                (indelOp == 'I' && indelSize == 1 && indelStart < 28 && indelStart % 3 == 2) )
+            read.setCigarString(buildTestCigarString(indelOp, 0, Math.max(indelStart - indelSize, 16), indelSize, readLength));
+        else
+            return originalCigar;
+
+        return read.getCigar();
+    }
+
+    private static byte[] makeReadString(final byte[] reference, final char indelOp, final int indelStart, final int indelSize, final int readLength, final int repeatLength) {
+        final byte[] readString = new byte[readLength];
+
+        if ( indelOp == 'D' && indelSize > 0 ) {
+            System.arraycopy(reference, 0, readString, 0, indelStart);
+            System.arraycopy(reference, indelStart + indelSize, readString, indelStart, readLength - indelStart);
+        } else if ( indelOp == 'I' && indelSize > 0 ) {
+            System.arraycopy(reference, 0, readString, 0, indelStart);
+            for ( int i = 0; i < indelSize; i++ ) {
+                if ( i % repeatLength == 0 )
+                    readString[indelStart + i] = 'X';
+                else if ( i % repeatLength == 1 )
+                    readString[indelStart + i] = 'Y';
+                else
+                    readString[indelStart + i] = 'Z';
+            }
+            System.arraycopy(reference, indelStart, readString, indelStart + indelSize, readLength - indelStart - indelSize);
+        } else {
+            System.arraycopy(reference, 0, readString, 0, readLength);
+        }
+
+        return readString;
+    }
+
+    @Test(enabled = !DEBUG, dataProvider = "LeftAlignIndelDataProvider")
+    public void testLeftAlignIndelData(final Cigar originalCigar, final Cigar expectedCigar, final byte[] reference, final byte[] read, final int repeatLength) {
+        final Cigar actualCigar = AlignmentUtils.leftAlignIndel(originalCigar, reference, read, 0, 0, true);
+        Assert.assertTrue(expectedCigar.equals(actualCigar), "Wrong left alignment detected for cigar " + originalCigar.toString() + " to " + actualCigar.toString() + " but expected " + expectedCigar.toString() + " with repeat length " + repeatLength);
+    }
+
+    //////////////////////////////////////////
+    // Test AlignmentUtils.trimCigarByReference() //
+    //////////////////////////////////////////
+
+    @DataProvider(name = "TrimCigarData")
+    public Object[][] makeTrimCigarData() {
+        List<Object[]> tests = new ArrayList<Object[]>();
+
+        for ( final CigarOperator op : Arrays.asList(CigarOperator.D, CigarOperator.EQ, CigarOperator.X, CigarOperator.M) ) {
+            for ( int myLength = 1; myLength < 6; myLength++ ) {
+                for ( int start = 0; start < myLength - 1; start++ ) {
+                    for ( int end = start; end < myLength; end++ ) {
+                        final int length = end - start + 1;
+
+                        final List<CigarOperator> padOps = Arrays.asList(CigarOperator.D, CigarOperator.M);
+                        for ( final CigarOperator padOp: padOps) {
+                            for ( int leftPad = 0; leftPad < 2; leftPad++ ) {
+                                for ( int rightPad = 0; rightPad < 2; rightPad++ ) {
+                                    tests.add(new Object[]{
+                                            (leftPad > 0 ? leftPad + padOp.toString() : "") + myLength + op.toString() + (rightPad > 0 ? rightPad + padOp.toString() : ""),
+                                            start + leftPad,
+                                            end + leftPad,
+                                            length + op.toString()});
+                                }
+                            }
+                        }
+                    }
+                }
+            }
+        }
+
+        for ( final int leftPad : Arrays.asList(0, 1, 2, 5) ) {
+            for ( final int rightPad : Arrays.asList(0, 1, 2, 5) ) {
+                final int length = leftPad + rightPad;
+                if ( length > 0 ) {
+                    for ( final int insSize : Arrays.asList(1, 10) ) {
+                        for ( int start = 0; start <= leftPad; start++ ) {
+                            for ( int stop = leftPad; stop < length; stop++ ) {
+                                final int leftPadRemaining = leftPad - start;
+                                final int rightPadRemaining = stop - leftPad + 1;
+                                final String insC = insSize + "I";
+                                tests.add(new Object[]{
+                                        leftPad + "M" + insC + rightPad + "M",
+                                        start,
+                                        stop,
+                                        (leftPadRemaining > 0 ? leftPadRemaining + "M" : "") + insC + (rightPadRemaining > 0 ? rightPadRemaining + "M" : "")
+                                });
+                            }
+                        }
+                    }
+                }
+            }
+        }
+
+        tests.add(new Object[]{"3M2D4M", 0, 8, "3M2D4M"});
+        tests.add(new Object[]{"3M2D4M", 2, 8, "1M2D4M"});
+        tests.add(new Object[]{"3M2D4M", 2, 6, "1M2D2M"});
+        tests.add(new Object[]{"3M2D4M", 3, 6, "2D2M"});
+        tests.add(new Object[]{"3M2D4M", 4, 6, "1D2M"});
+        tests.add(new Object[]{"3M2D4M", 5, 6, "2M"});
+        tests.add(new Object[]{"3M2D4M", 6, 6, "1M"});
+
+        tests.add(new Object[]{"2M3I4M", 0, 5, "2M3I4M"});
+        tests.add(new Object[]{"2M3I4M", 1, 5, "1M3I4M"});
+        tests.add(new Object[]{"2M3I4M", 1, 4, "1M3I3M"});
+        tests.add(new Object[]{"2M3I4M", 2, 4, "3I3M"});
+        tests.add(new Object[]{"2M3I4M", 2, 3, "3I2M"});
+        tests.add(new Object[]{"2M3I4M", 2, 2, "3I1M"});
+        tests.add(new Object[]{"2M3I4M", 3, 4, "2M"});
+        tests.add(new Object[]{"2M3I4M", 3, 3, "1M"});
+        tests.add(new Object[]{"2M3I4M", 4, 4, "1M"});
+
+        // this doesn't work -- but I'm not sure it should
+        //        tests.add(new Object[]{"2M3I4M", 2, 1, "3I"});
+
+        return tests.toArray(new Object[][]{});
+    }
+
+    @Test(dataProvider = "TrimCigarData", enabled = ! DEBUG)
+    public void testTrimCigar(final String cigarString, final int start, final int length, final String expectedCigarString) {
+        final Cigar cigar = TextCigarCodec.getSingleton().decode(cigarString);
+        final Cigar expectedCigar = TextCigarCodec.getSingleton().decode(expectedCigarString);
+        final Cigar actualCigar = AlignmentUtils.trimCigarByReference(cigar, start, length);
+        Assert.assertEquals(actualCigar, expectedCigar);
+    }
+
+    @DataProvider(name = "TrimCigarByBasesData")
+    public Object[][] makeTrimCigarByBasesData() {
+        List<Object[]> tests = new ArrayList<Object[]>();
+
+        tests.add(new Object[]{"2M3I4M", 0, 8, "2M3I4M"});
+        tests.add(new Object[]{"2M3I4M", 1, 8, "1M3I4M"});
+        tests.add(new Object[]{"2M3I4M", 2, 8, "3I4M"});
+        tests.add(new Object[]{"2M3I4M", 3, 8, "2I4M"});
+        tests.add(new Object[]{"2M3I4M", 4, 8, "1I4M"});
+        tests.add(new Object[]{"2M3I4M", 4, 7, "1I3M"});
+        tests.add(new Object[]{"2M3I4M", 4, 6, "1I2M"});
+        tests.add(new Object[]{"2M3I4M", 4, 5, "1I1M"});
+        tests.add(new Object[]{"2M3I4M", 4, 4, "1I"});
+        tests.add(new Object[]{"2M3I4M", 5, 5, "1M"});
+
+        tests.add(new Object[]{"2M2D2I", 0, 3, "2M2D2I"});
+        tests.add(new Object[]{"2M2D2I", 1, 3, "1M2D2I"});
+        tests.add(new Object[]{"2M2D2I", 2, 3, "2D2I"});
+        tests.add(new Object[]{"2M2D2I", 3, 3, "1I"});
+        tests.add(new Object[]{"2M2D2I", 2, 2, "2D1I"});
+        tests.add(new Object[]{"2M2D2I", 1, 2, "1M2D1I"});
+        tests.add(new Object[]{"2M2D2I", 0, 1, "2M2D"});
+        tests.add(new Object[]{"2M2D2I", 1, 1, "1M2D"});
+
+        return tests.toArray(new Object[][]{});
+    }
+
+    @Test(dataProvider = "TrimCigarByBasesData", enabled = !DEBUG)
+    public void testTrimCigarByBase(final String cigarString, final int start, final int length, final String expectedCigarString) {
+        final Cigar cigar = TextCigarCodec.getSingleton().decode(cigarString);
+        final Cigar expectedCigar = TextCigarCodec.getSingleton().decode(expectedCigarString);
+        final Cigar actualCigar = AlignmentUtils.trimCigarByBases(cigar, start, length);
+        Assert.assertEquals(actualCigar, expectedCigar);
+    }
+
+    //////////////////////////////////////////
+    // Test AlignmentUtils.applyCigarToCigar() //
+    //////////////////////////////////////////
+
+    @DataProvider(name = "ApplyCigarToCigarData")
+    public Object[][] makeApplyCigarToCigarData() {
+        List<Object[]> tests = new ArrayList<Object[]>();
+
+        for ( int i = 1; i < 5; i++ )
+            tests.add(new Object[]{i + "M", i + "M", i + "M"});
+
+//        * ref   : ACGTAC
+//        * hap   : AC---C  - 2M3D1M
+//        * read  : AC---C  - 3M
+//        * result: AG---C => 2M3D
+        tests.add(new Object[]{"3M", "2M3D1M", "2M3D1M"});
+
+//        * ref   : ACxG-TA
+//        * hap   : AC-G-TA  - 2M1D3M
+//        * read  : AC-GxTA  - 3M1I2M
+//        * result: AC-GxTA => 2M1D1M1I2M
+        tests.add(new Object[]{"3M1I2M", "2M1D3M", "2M1D1M1I2M"});
+
+//        * ref   : A-CGTA
+//        * hap   : A-CGTA  - 5M
+//        * read  : AxCGTA  - 1M1I4M
+//        * result: AxCGTA => 1M1I4M
+        tests.add(new Object[]{"1M1I4M", "5M", "1M1I4M"});
+
+//        * ref   : ACGTA
+//        * hap   : ACGTA  - 5M
+//        * read  : A--TA  - 1M2D2M
+//        * result: A--TA => 1M2D2M
+        tests.add(new Object[]{"1M2D2M", "5M", "1M2D2M"});
+
+//        * ref   : AC-GTA
+//        * hap   : ACxGTA  - 2M1I3M
+//        * read  : A--GTA  - 1M2D3M
+//        * result: A--GTA => 1M1D3M
+        tests.add(new Object[]{"108M14D24M2M18I29M92M1000M", "2M1I3M", "2M1I3M"});
+
+        return tests.toArray(new Object[][]{});
+    }
+
+    @Test(dataProvider = "ApplyCigarToCigarData", enabled = !DEBUG)
+    public void testApplyCigarToCigar(final String firstToSecondString, final String secondToThirdString, final String expectedCigarString) {
+        final Cigar firstToSecond = TextCigarCodec.getSingleton().decode(firstToSecondString);
+        final Cigar secondToThird = TextCigarCodec.getSingleton().decode(secondToThirdString);
+        final Cigar expectedCigar = TextCigarCodec.getSingleton().decode(expectedCigarString);
+        final Cigar actualCigar = AlignmentUtils.applyCigarToCigar(firstToSecond, secondToThird);
+        Assert.assertEquals(actualCigar, expectedCigar);
+    }
+
+    //////////////////////////////////////////
+    // Test AlignmentUtils.applyCigarToCigar() //
+    //////////////////////////////////////////
+
+    @DataProvider(name = "ReadOffsetFromCigarData")
+    public Object[][] makeReadOffsetFromCigarData() {
+        List<Object[]> tests = new ArrayList<Object[]>();
+
+        final int SIZE = 10;
+        for ( int i = 0; i < SIZE; i++ ) {
+            tests.add(new Object[]{SIZE + "M", i, i});
+        }
+
+        //          0123ii45
+        // ref    : ACGT--AC
+        // hap    : AC--xxAC (2M2D2I2M)
+        // ref.pos: 01    45
+        tests.add(new Object[]{"2M2D2I2M", 0, 0});
+        tests.add(new Object[]{"2M2D2I2M", 1, 1});
+        tests.add(new Object[]{"2M2D2I2M", 2, 4});
+        tests.add(new Object[]{"2M2D2I2M", 3, 4});
+        tests.add(new Object[]{"2M2D2I2M", 4, 4});
+        tests.add(new Object[]{"2M2D2I2M", 5, 5});
+
+        // 10132723 - 10132075 - 500 = 148
+        // what's the offset of the first match after the I?
+        // 108M + 14D + 24M + 2M = 148
+        // What's the offset of the first base that is after the I?
+        // 108M + 24M + 2M + 18I = 134M + 18I = 152 - 1 = 151
+        tests.add(new Object[]{"108M14D24M2M18I29M92M", 0, 0});
+        tests.add(new Object[]{"108M14D24M2M18I29M92M", 107, 107});
+        tests.add(new Object[]{"108M14D24M2M18I29M92M", 108, 108 + 14}); // first base after the deletion
+
+        tests.add(new Object[]{"108M14D24M2M18I29M92M", 132, 132+14}); // 2 before insertion
+        tests.add(new Object[]{"108M14D24M2M18I29M92M", 133, 133+14}); // last base before insertion
+
+        // entering into the insertion
+        for ( int i = 0; i < 18; i++ ) {
+            tests.add(new Object[]{"108M14D24M2M18I29M92M", 134+i, 148}); // inside insertion
+        }
+        tests.add(new Object[]{"108M14D24M2M18I29M92M", 134+18, 148}); // first base after insertion matches at same as insertion
+        tests.add(new Object[]{"108M14D24M2M18I29M92M", 134+18+1, 149});
+        tests.add(new Object[]{"108M14D24M2M18I29M92M", 134+18+2, 150});
+
+        return tests.toArray(new Object[][]{});
+    }
+
+    @Test(dataProvider = "ReadOffsetFromCigarData", enabled = !DEBUG)
+    public void testReadOffsetFromCigar(final String cigarString, final int startOnCigar, final int expectedOffset) {
+        final Cigar cigar = TextCigarCodec.getSingleton().decode(cigarString);
+        final int actualOffset = AlignmentUtils.calcFirstBaseMatchingReferenceInCigar(cigar, startOnCigar);
+        Assert.assertEquals(actualOffset, expectedOffset);
+    }
+
+    //////////////////////////////////////////
+    // Test AlignmentUtils.addCigarElements() //
+    //////////////////////////////////////////
+
+    @DataProvider(name = "AddCigarElementsData")
+    public Object[][] makeAddCigarElementsData() {
+        List<Object[]> tests = new ArrayList<Object[]>();
+
+        final int SIZE = 10;
+        for ( final CigarOperator op : Arrays.asList(CigarOperator.I, CigarOperator.M, CigarOperator.S, CigarOperator.EQ, CigarOperator.X)) {
+            for ( int start = 0; start < SIZE; start++ ) {
+                for ( int end = start; end < SIZE * 2; end ++ ) {
+                    for ( int pos = 0; pos < SIZE * 3; pos++ ) {
+                        int length = 0;
+                        for ( int i = 0; i < SIZE; i++ ) length += (i+pos) >= start && (i+pos) <= end ? 1 : 0;
+                        tests.add(new Object[]{SIZE + op.toString(), pos, start, end, length > 0 ? length + op.toString() : "*"});
+                    }
+                }
+            }
+        }
+
+        return tests.toArray(new Object[][]{});
+    }
+
+    @Test(dataProvider = "AddCigarElementsData", enabled = !DEBUG)
+    public void testAddCigarElements(final String cigarString, final int pos, final int start, final int end, final String expectedCigarString) {
+        final Cigar cigar = TextCigarCodec.getSingleton().decode(cigarString);
+        final CigarElement elt = cigar.getCigarElement(0);
+        final Cigar expectedCigar = TextCigarCodec.getSingleton().decode(expectedCigarString);
+
+        final List<CigarElement> elts = new LinkedList<CigarElement>();
+        final int actualEndPos = AlignmentUtils.addCigarElements(elts, pos, start, end, elt);
+
+        Assert.assertEquals(actualEndPos, pos + elt.getLength());
+        Assert.assertEquals(AlignmentUtils.consolidateCigar(new Cigar(elts)), expectedCigar);
+    }
+
+    @DataProvider(name = "GetBasesCoveringRefIntervalData")
+    public Object[][] makeGetBasesCoveringRefIntervalData() {
+        List<Object[]> tests = new ArrayList<Object[]>();
+
+        // matches
+        // 0123
+        // ACGT
+        tests.add(new Object[]{"ACGT", 0, 3, "4M", "ACGT"});
+        tests.add(new Object[]{"ACGT", 1, 3, "4M", "CGT"});
+        tests.add(new Object[]{"ACGT", 1, 2, "4M", "CG"});
+        tests.add(new Object[]{"ACGT", 1, 1, "4M", "C"});
+
+        // deletions
+        // 012345
+        // AC--GT
+        tests.add(new Object[]{"ACGT", 0, 5, "2M2D2M", "ACGT"});
+        tests.add(new Object[]{"ACGT", 1, 5, "2M2D2M", "CGT"});
+        tests.add(new Object[]{"ACGT", 2, 5, "2M2D2M", null});
+        tests.add(new Object[]{"ACGT", 3, 5, "2M2D2M", null});
+        tests.add(new Object[]{"ACGT", 4, 5, "2M2D2M", "GT"});
+        tests.add(new Object[]{"ACGT", 5, 5, "2M2D2M", "T"});
+        tests.add(new Object[]{"ACGT", 0, 4, "2M2D2M", "ACG"});
+        tests.add(new Object[]{"ACGT", 0, 3, "2M2D2M", null});
+        tests.add(new Object[]{"ACGT", 0, 2, "2M2D2M", null});
+        tests.add(new Object[]{"ACGT", 0, 1, "2M2D2M", "AC"});
+        tests.add(new Object[]{"ACGT", 0, 0, "2M2D2M", "A"});
+
+        // insertions
+        // 01--23
+        // ACTTGT
+        tests.add(new Object[]{"ACTTGT", 0, 3, "2M2I2M", "ACTTGT"});
+        tests.add(new Object[]{"ACTTGT", 1, 3, "2M2I2M", "CTTGT"});
+        tests.add(new Object[]{"ACTTGT", 2, 3, "2M2I2M", "GT"});
+        tests.add(new Object[]{"ACTTGT", 3, 3, "2M2I2M", "T"});
+        tests.add(new Object[]{"ACTTGT", 0, 2, "2M2I2M", "ACTTG"});
+        tests.add(new Object[]{"ACTTGT", 0, 1, "2M2I2M", "AC"});
+        tests.add(new Object[]{"ACTTGT", 1, 2, "2M2I2M", "CTTG"});
+        tests.add(new Object[]{"ACTTGT", 2, 2, "2M2I2M", "G"});
+        tests.add(new Object[]{"ACTTGT", 1, 1, "2M2I2M", "C"});
+
+        tests.add(new Object[]{"ACGT", 0, 1, "2M2I", "AC"});
+        tests.add(new Object[]{"ACGT", 1, 1, "2M2I", "C"});
+        tests.add(new Object[]{"ACGT", 0, 0, "2M2I", "A"});
+
+        return tests.toArray(new Object[][]{});
+    }
+
+    @Test(dataProvider = "GetBasesCoveringRefIntervalData", enabled = true)
+    public void testGetBasesCoveringRefInterval(final String basesString, final int refStart, final int refEnd, final String cigarString, final String expected) {
+        final byte[] actualBytes = AlignmentUtils.getBasesCoveringRefInterval(refStart, refEnd, basesString.getBytes(), 0, TextCigarCodec.getSingleton().decode(cigarString));
+        if ( expected == null )
+            Assert.assertNull(actualBytes);
+        else
+            Assert.assertEquals(new String(actualBytes), expected);
+    }
+
+    @DataProvider(name = "StartsOrEndsWithInsertionOrDeletionData")
+    public Object[][] makeStartsOrEndsWithInsertionOrDeletionData() {
+        List<Object[]> tests = new ArrayList<Object[]>();
+
+        tests.add(new Object[]{"2M", false});
+        tests.add(new Object[]{"1D2M", true});
+        tests.add(new Object[]{"2M1D", true});
+        tests.add(new Object[]{"2M1I", true});
+        tests.add(new Object[]{"1I2M", true});
+        tests.add(new Object[]{"1M1I2M", false});
+        tests.add(new Object[]{"1M1D2M", false});
+        tests.add(new Object[]{"1M1I2M1I", true});
+        tests.add(new Object[]{"1M1I2M1D", true});
+        tests.add(new Object[]{"1D1M1I2M", true});
+        tests.add(new Object[]{"1I1M1I2M", true});
+        tests.add(new Object[]{"1M1I2M1I1M", false});
+        tests.add(new Object[]{"1M1I2M1D1M", false});
+        tests.add(new Object[]{"1M1D2M1D1M", false});
+
+        return tests.toArray(new Object[][]{});
+    }
+
+    @Test(dataProvider = "StartsOrEndsWithInsertionOrDeletionData", enabled = true)
+    public void testStartsOrEndsWithInsertionOrDeletion(final String cigar, final boolean expected) {
+        Assert.assertEquals(AlignmentUtils.startsOrEndsWithInsertionOrDeletion(TextCigarCodec.getSingleton().decode(cigar)), expected);
+    }
+
+    @Test(dataProvider = "StartsOrEndsWithInsertionOrDeletionData", enabled = true)
+    public void testRemoveTrailingDeletions(final String cigar, final boolean expected) {
+
+        final Cigar originalCigar = TextCigarCodec.getSingleton().decode(cigar);
+        final Cigar newCigar = AlignmentUtils.removeTrailingDeletions(originalCigar);
+
+        Assert.assertEquals(originalCigar.equals(newCigar), !cigar.endsWith("D"));
+    }
+}
diff --git a/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/utils/sam/ArtificialBAMBuilderUnitTest.java b/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/utils/sam/ArtificialBAMBuilderUnitTest.java
new file mode 100644
index 0000000..b7042a6
--- /dev/null
+++ b/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/utils/sam/ArtificialBAMBuilderUnitTest.java
@@ -0,0 +1,121 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.utils.sam;
+
+import htsjdk.samtools.SAMFileReader;
+import htsjdk.samtools.SAMRecord;
+import org.broadinstitute.gatk.utils.BaseTest;
+import org.testng.Assert;
+import org.testng.annotations.DataProvider;
+import org.testng.annotations.Test;
+
+import java.io.File;
+import java.util.Arrays;
+import java.util.Iterator;
+import java.util.LinkedList;
+import java.util.List;
+
+/**
+ * Created with IntelliJ IDEA.
+ * User: depristo
+ * Date: 1/15/13
+ * Time: 3:49 PM
+ * To change this template use File | Settings | File Templates.
+ */
+public class ArtificialBAMBuilderUnitTest extends BaseTest {
+    @DataProvider(name = "ArtificialBAMBuilderUnitTestProvider")
+    public Object[][] makeArtificialBAMBuilderUnitTestProvider() {
+        final List<Object[]> tests = new LinkedList<Object[]>();
+
+        final List<Integer> starts = Arrays.asList(
+                1, // very start of the chromosome
+                ArtificialBAMBuilder.BAM_SHARD_SIZE - 100, // right before the shard boundary
+                ArtificialBAMBuilder.BAM_SHARD_SIZE + 100 // right after the shard boundary
+        );
+
+        for ( final int readLength : Arrays.asList(10, 20) ) {
+            for ( final int skips : Arrays.asList(0, 1, 10) ) {
+                for ( final int start : starts ) {
+                    for ( final int nSamples : Arrays.asList(1, 2) ) {
+                        for ( final int nReadsPerLocus : Arrays.asList(1, 10) ) {
+                            for ( final int nLoci : Arrays.asList(10, 100, 1000) ) {
+                                final ArtificialBAMBuilder bamBuilder = new ArtificialBAMBuilder(nReadsPerLocus, nLoci);
+                                bamBuilder.setReadLength(readLength);
+                                bamBuilder.setSkipNLoci(skips);
+                                bamBuilder.setAlignmentStart(start);
+                                bamBuilder.createAndSetHeader(nSamples);
+                                tests.add(new Object[]{bamBuilder, readLength, skips, start, nSamples, nReadsPerLocus, nLoci});
+                            }
+                        }
+                    }
+                }
+            }
+        }
+
+        return tests.toArray(new Object[][]{});
+    }
+
+    @Test(dataProvider = "ArtificialBAMBuilderUnitTestProvider")
+    public void testBamProvider(final ArtificialBAMBuilder bamBuilder, int readLength, int skips, int start, int nSamples, int nReadsPerLocus, int nLoci) {
+        Assert.assertEquals(bamBuilder.getReadLength(), readLength);
+        Assert.assertEquals(bamBuilder.getSkipNLoci(), skips);
+        Assert.assertEquals(bamBuilder.getAlignmentStart(), start);
+        Assert.assertEquals(bamBuilder.getNSamples(), nSamples);
+        Assert.assertEquals(bamBuilder.getnReadsPerLocus(), nReadsPerLocus);
+        Assert.assertEquals(bamBuilder.getnLoci(), nLoci);
+
+        final List<GATKSAMRecord> reads = bamBuilder.makeReads();
+        Assert.assertEquals(reads.size(), bamBuilder.expectedNumberOfReads());
+        for ( final GATKSAMRecord read : reads ) {
+            assertGoodRead(read, bamBuilder);
+        }
+
+        final File bam = bamBuilder.makeTemporarilyBAMFile();
+        final SAMFileReader reader = new SAMFileReader(bam);
+        Assert.assertTrue(reader.hasIndex());
+        final Iterator<SAMRecord> bamIt = reader.iterator();
+        int nReadsFromBam = 0;
+        int lastStart = -1;
+        while ( bamIt.hasNext() ) {
+            final SAMRecord read = bamIt.next();
+            assertGoodRead(read, bamBuilder);
+            nReadsFromBam++;
+            Assert.assertTrue(read.getAlignmentStart() >= lastStart);
+            lastStart = read.getAlignmentStart();
+        }
+        Assert.assertEquals(nReadsFromBam, bamBuilder.expectedNumberOfReads());
+    }
+
+    private void assertGoodRead(final SAMRecord read, final ArtificialBAMBuilder bamBuilder) {
+        Assert.assertEquals(read.getReadLength(), bamBuilder.getReadLength());
+        Assert.assertEquals(read.getReadBases().length, bamBuilder.getReadLength());
+        Assert.assertEquals(read.getBaseQualities().length, bamBuilder.getReadLength());
+        Assert.assertTrue(read.getAlignmentStart() >= bamBuilder.getAlignmentStart());
+        Assert.assertNotNull(read.getReadGroup());
+    }
+}
+
+
diff --git a/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/utils/sam/ArtificialPatternedSAMIteratorUnitTest.java b/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/utils/sam/ArtificialPatternedSAMIteratorUnitTest.java
new file mode 100644
index 0000000..fe5fba7
--- /dev/null
+++ b/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/utils/sam/ArtificialPatternedSAMIteratorUnitTest.java
@@ -0,0 +1,122 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.utils.sam;
+
+import org.broadinstitute.gatk.utils.BaseTest;
+import static org.testng.Assert.assertTrue;
+import static org.testng.Assert.fail;
+import org.testng.annotations.BeforeMethod;
+import org.testng.annotations.Test;
+import htsjdk.samtools.SAMFileHeader;
+import htsjdk.samtools.SAMRecord;
+
+
+/*
+ * 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.
+ */
+
+/**
+ * 
+ * @author aaron 
+ * 
+ * Class ArtificialPatternedSAMIteratorUnitTest
+ *
+ * tests ArtificialPatternedSAMIterator, making sure that if you specify in order
+ * you get reads in order, and if you specify out of order you get them out of order.  
+ */
+public class ArtificialPatternedSAMIteratorUnitTest extends BaseTest {
+
+    // our artifical patterned iterator
+    ArtificialPatternedSAMIterator iter;
+
+    private int startingChr = 1;
+    private int endingChr = 2;
+    private int readCount = 100;
+    private int DEFAULT_READ_LENGTH = ArtificialSAMUtils.DEFAULT_READ_LENGTH;
+    SAMFileHeader header;
+
+    @BeforeMethod
+    public void before() {
+        header = ArtificialSAMUtils.createArtificialSamHeader(( endingChr - startingChr ) + 1, startingChr, readCount + DEFAULT_READ_LENGTH);
+
+    }
+    @Test
+    public void testInOrder() {
+        iter = new ArtificialPatternedSAMIterator(startingChr,endingChr,readCount,0,header, ArtificialPatternedSAMIterator.PATTERN.IN_ORDER_READS);
+        if (!iter.hasNext()) {
+            fail("no reads in the ArtificialPatternedSAMIterator");
+        }
+        SAMRecord last = iter.next();
+        while (iter.hasNext()) {
+            SAMRecord rec = iter.next();
+            if (!(rec.getReferenceIndex() > last.getReferenceIndex()) && (rec.getAlignmentStart() <= last.getAlignmentStart())) {
+                fail("read " + rec.getReadName() + " out of order compared to last read, " + last.getReadName());
+            }
+            last = rec;
+        }
+
+    }
+    @Test
+    public void testOutOfOrder() {
+        int outOfOrderCount = 0;
+        iter = new ArtificialPatternedSAMIterator(startingChr,endingChr,readCount,0,header, ArtificialPatternedSAMIterator.PATTERN.RANDOM_READS);
+        if (!iter.hasNext()) {
+            fail("no reads in the ArtificialPatternedSAMIterator");
+        }
+        SAMRecord last = iter.next();
+        while (iter.hasNext()) {
+            SAMRecord rec = iter.next();
+            if (!(rec.getReferenceIndex() > last.getReferenceIndex()) && (rec.getAlignmentStart() <= last.getAlignmentStart())) {
+                ++outOfOrderCount;
+            }
+            last = rec;
+        }
+        assertTrue(outOfOrderCount > 0);
+    }
+
+
+}
diff --git a/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/utils/sam/ArtificialSAMFileWriterUnitTest.java b/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/utils/sam/ArtificialSAMFileWriterUnitTest.java
new file mode 100644
index 0000000..d527624
--- /dev/null
+++ b/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/utils/sam/ArtificialSAMFileWriterUnitTest.java
@@ -0,0 +1,120 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.utils.sam;
+
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertTrue;
+import org.testng.annotations.BeforeMethod;
+import org.testng.annotations.Test;
+import org.broadinstitute.gatk.utils.BaseTest;
+import htsjdk.samtools.SAMRecord;
+import htsjdk.samtools.SAMFileHeader;
+
+import java.util.ArrayList;
+import java.util.List;
+
+
+/*
+ * 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.
+ */
+
+/**
+ * @author aaron
+ *         <p/>
+ *         Class ArtificialGATKSAMFileWriter
+ *         <p/>
+ *         Test out the ArtificialGATKSAMFileWriter class
+ */
+public class ArtificialSAMFileWriterUnitTest extends BaseTest {
+
+    /** the artificial sam writer */
+    private ArtificialGATKSAMFileWriter writer;
+    private SAMFileHeader header;
+    private final int startChr = 1;
+    private final int numChr = 2;
+    private final int chrSize = 100;
+
+    @BeforeMethod
+    public void before() {
+        writer = new ArtificialGATKSAMFileWriter();
+        header = ArtificialSAMUtils.createArtificialSamHeader(numChr, startChr, chrSize);
+    }
+
+    @Test
+    public void testBasicCount() {
+        for (int x = 1; x <= 100; x++) {
+            SAMRecord rec = ArtificialSAMUtils.createArtificialRead(header, String.valueOf(x), 1, x, ArtificialSAMUtils.DEFAULT_READ_LENGTH);
+            writer.addAlignment(rec);
+        }
+        assertEquals(writer.getRecords().size(), 100);
+
+    }
+
+    @Test
+    public void testReadName() {
+        List<String> names = new ArrayList<String>();
+
+        for (int x = 1; x <= 100; x++) {
+            names.add(String.valueOf(x));
+            SAMRecord rec = ArtificialSAMUtils.createArtificialRead(header, String.valueOf(x), 1, x, ArtificialSAMUtils.DEFAULT_READ_LENGTH);
+            writer.addAlignment(rec);
+        }
+        assertEquals(writer.getRecords().size(), 100);
+
+        // check the names
+        for (int x = 0; x < 100; x++) {
+            assertTrue(names.get(x).equals(writer.getRecords().get(x).getReadName()));
+        }
+
+    }
+
+    @Test
+    public void testClose() {
+        writer.close();
+        assertTrue(writer.isClosed());
+    }
+}
diff --git a/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/utils/sam/ArtificialSAMQueryIteratorUnitTest.java b/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/utils/sam/ArtificialSAMQueryIteratorUnitTest.java
new file mode 100644
index 0000000..32409c6
--- /dev/null
+++ b/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/utils/sam/ArtificialSAMQueryIteratorUnitTest.java
@@ -0,0 +1,138 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.utils.sam;
+
+import org.broadinstitute.gatk.utils.BaseTest;
+import static org.testng.Assert.assertEquals;
+import org.testng.annotations.Test;
+import htsjdk.samtools.SAMRecord;
+
+
+/*
+ * 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.
+ */
+
+/**
+ * @author aaron
+ *         <p/>
+ *         Class ArtificialSAMQueryIteratorUnitTest
+ *         <p/>
+ *         a test for the ArtificialSAMQueryIterator class.
+ */
+public class ArtificialSAMQueryIteratorUnitTest extends BaseTest {
+
+    @Test
+    public void testWholeChromosomeQuery() {
+        ArtificialSAMQueryIterator iter = ArtificialSAMUtils.queryReadIterator(1, 2, 100);
+        iter.queryContained("chr1", 1, -1);
+        int count = 0;
+        while (iter.hasNext()) {
+            SAMRecord rec = iter.next();
+            count++;
+        }
+        assertEquals(count, 100);
+
+    }
+
+    @Test
+    public void testContainedQueryStart() {
+        ArtificialSAMQueryIterator iter = ArtificialSAMUtils.queryReadIterator(1, 2, 100);
+        iter.queryContained("chr1", 1, 50);
+        int count = 0;
+        while (iter.hasNext()) {
+            SAMRecord rec = iter.next();
+            count++;
+        }
+        assertEquals(count, 1);
+
+    }
+
+    @Test
+    public void testOverlappingQueryStart() {
+        ArtificialSAMQueryIterator iter = ArtificialSAMUtils.queryReadIterator(1, 2, 100);
+        iter.queryOverlapping("chr1", 1, 50);
+        int count = 0;
+        while (iter.hasNext()) {
+            SAMRecord rec = iter.next();
+            count++;
+        }
+        assertEquals(count, 50);
+
+    }
+
+    @Test
+    public void testContainedQueryMiddle() {
+        ArtificialSAMQueryIterator iter = ArtificialSAMUtils.queryReadIterator(1, 2, 100);
+        iter.queryContained("chr1", 25, 74);
+        int count = 0;
+        while (iter.hasNext()) {
+            SAMRecord rec = iter.next();
+            count++;
+        }
+        assertEquals(count, 1);
+
+    }
+
+    @Test
+    public void testOverlappingQueryMiddle() {
+        ArtificialSAMQueryIterator iter = ArtificialSAMUtils.queryReadIterator(1, 2, 100);
+        iter.queryOverlapping("chr1", 25, 74);
+        int count = 0;
+        while (iter.hasNext()) {
+            SAMRecord rec = iter.next();
+            count++;
+        }
+        assertEquals(count, 50);
+
+    }
+
+    @Test(expectedExceptions=IllegalArgumentException.class)
+    public void testUnknownChromosome() {
+        ArtificialSAMQueryIterator iter = ArtificialSAMUtils.queryReadIterator(1, 2, 100);
+        iter.queryOverlapping("chr621", 25, 74);         
+    }
+}
diff --git a/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/utils/sam/ArtificialSAMUtilsUnitTest.java b/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/utils/sam/ArtificialSAMUtilsUnitTest.java
new file mode 100644
index 0000000..48ad212
--- /dev/null
+++ b/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/utils/sam/ArtificialSAMUtilsUnitTest.java
@@ -0,0 +1,108 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.utils.sam;
+
+import org.broadinstitute.gatk.utils.BaseTest;
+import org.broadinstitute.gatk.engine.iterators.GATKSAMIterator;
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertTrue;
+import static org.testng.Assert.fail;
+import org.testng.annotations.Test;
+import htsjdk.samtools.SAMRecord;
+
+/**
+ * Created by IntelliJ IDEA.
+ * User: aaronmckenna
+ * Date: Jun 3, 2009
+ * Time: 3:09:34 AM
+ * To change this template use File | Settings | File Templates.
+ */
+public class ArtificialSAMUtilsUnitTest extends BaseTest {
+
+
+    @Test
+    public void basicReadIteratorTest() {
+        GATKSAMIterator iter = ArtificialSAMUtils.mappedReadIterator(1, 100, 100);
+        int count = 0;
+        while (iter.hasNext()) {
+            SAMRecord rec = iter.next();
+            count++;
+        }
+        assertEquals(count, 100 * 100);
+    }
+
+    @Test
+    public void tenPerChromosome() {
+        GATKSAMIterator iter = ArtificialSAMUtils.mappedReadIterator(1, 100, 10);
+        int count = 0;
+        while (iter.hasNext()) {
+            SAMRecord rec = iter.next();
+
+            assertEquals(Integer.valueOf(Math.round(count / 10)), rec.getReferenceIndex());
+            count++;
+        }
+        assertEquals(count, 100 * 10);
+    }
+
+    @Test
+    public void onePerChromosome() {
+        GATKSAMIterator iter = ArtificialSAMUtils.mappedReadIterator(1, 100, 1);
+        int count = 0;
+        while (iter.hasNext()) {
+            SAMRecord rec = iter.next();
+
+            assertEquals(Integer.valueOf(count), rec.getReferenceIndex());
+            count++;
+        }
+        assertEquals(count, 100 * 1);
+    }
+
+    @Test
+    public void basicUnmappedIteratorTest() {
+        GATKSAMIterator iter = ArtificialSAMUtils.mappedAndUnmappedReadIterator(1, 100, 100, 1000);
+        int count = 0;
+        for (int x = 0; x < (100* 100); x++ ) {
+            if (!iter.hasNext()) {
+                fail ("we didn't get the expected number of reads");
+            }
+            SAMRecord rec = iter.next();
+            assertTrue(rec.getReferenceIndex() >= 0);
+            count++;
+        }
+        assertEquals(100 * 100, count);
+
+        // now we should have 1000 unmapped reads
+        count = 0;
+        while (iter.hasNext()) {
+            SAMRecord rec = iter.next();
+            assertTrue(rec.getReferenceIndex() < 0);
+            count++;
+        }
+        assertEquals(count, 1000);
+    }
+
+  
+}
diff --git a/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/utils/sam/ArtificialSingleSampleReadStreamUnitTest.java b/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/utils/sam/ArtificialSingleSampleReadStreamUnitTest.java
new file mode 100644
index 0000000..271a75a
--- /dev/null
+++ b/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/utils/sam/ArtificialSingleSampleReadStreamUnitTest.java
@@ -0,0 +1,186 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.utils.sam;
+
+import htsjdk.samtools.SAMFileHeader;
+import htsjdk.samtools.SAMReadGroupRecord;
+import org.broadinstitute.gatk.engine.GenomeAnalysisEngine;
+import org.broadinstitute.gatk.utils.exceptions.ReviewedGATKException;
+import org.testng.annotations.Test;
+import org.testng.annotations.DataProvider;
+
+import org.broadinstitute.gatk.utils.BaseTest;
+
+public class ArtificialSingleSampleReadStreamUnitTest extends BaseTest {
+
+    private static class ArtificialSingleSampleReadStreamTest extends TestDataProvider {
+        private ArtificialSingleSampleReadStream stream;
+        private ArtificialSingleSampleReadStreamAnalyzer streamAnalyzer;
+
+        public ArtificialSingleSampleReadStreamTest( ArtificialSingleSampleReadStream stream ) {
+            super(ArtificialSingleSampleReadStreamTest.class);
+
+            this.stream = stream;
+
+            setName(String.format("%s: numContigs=%d stacksPerContig=%d readsPerStack=%d-%d distanceBetweenStacks=%d-%d readLength=%d-%d unmappedReads=%d",
+                    getClass().getSimpleName(),
+                    stream.getNumContigs(),
+                    stream.getNumStacksPerContig(),
+                    stream.getMinReadsPerStack(),
+                    stream.getMaxReadsPerStack(),
+                    stream.getMinDistanceBetweenStacks(),
+                    stream.getMaxDistanceBetweenStacks(),
+                    stream.getMinReadLength(),
+                    stream.getMaxReadLength(),
+                    stream.getNumUnmappedReads()));
+        }
+
+        public void run() {
+            streamAnalyzer= new ArtificialSingleSampleReadStreamAnalyzer(stream);
+
+            streamAnalyzer.analyze(stream);
+
+            // Check whether the observed properties of the stream match its nominal properties
+            streamAnalyzer.validate();
+        }
+    }
+
+    @DataProvider(name = "ArtificialSingleSampleReadStreamTestDataProvider")
+    public Object[][] createArtificialSingleSampleReadStreamTests() {
+        SAMFileHeader header = ArtificialSAMUtils.createArtificialSamHeader(3, 1, 10000);
+        String readGroupID = "testReadGroup";
+        SAMReadGroupRecord readGroup = new SAMReadGroupRecord(readGroupID);
+        readGroup.setSample("testSample");
+        header.addReadGroup(readGroup);
+
+        GenomeAnalysisEngine.resetRandomGenerator();
+
+        // brute force testing!
+        for ( int numContigs = 0; numContigs <= 2; numContigs++ ) {
+            for ( int stacksPerContig = 0; stacksPerContig <= 2; stacksPerContig++ ) {
+                for ( int minReadsPerStack = 1; minReadsPerStack <= 2; minReadsPerStack++ ) {
+                    for ( int maxReadsPerStack = 1; maxReadsPerStack <= 3; maxReadsPerStack++ ) {
+                        for ( int minDistanceBetweenStacks = 1; minDistanceBetweenStacks <= 2; minDistanceBetweenStacks++ ) {
+                            for ( int maxDistanceBetweenStacks = 1; maxDistanceBetweenStacks <= 3; maxDistanceBetweenStacks++ ) {
+                                for ( int minReadLength = 1; minReadLength <= 2; minReadLength++ ) {
+                                    for ( int maxReadLength = 1; maxReadLength <= 3; maxReadLength++ ) {
+                                        for ( int numUnmappedReads = 0; numUnmappedReads <= 2; numUnmappedReads++ ) {
+                                            // Only test sane combinations here
+                                            if ( minReadsPerStack <= maxReadsPerStack &&
+                                                 minDistanceBetweenStacks <= maxDistanceBetweenStacks &&
+                                                 minReadLength <= maxReadLength &&
+                                                 ((numContigs > 0 && stacksPerContig > 0) || (numContigs == 0 && stacksPerContig == 0)) ) {
+
+                                                new ArtificialSingleSampleReadStreamTest(new ArtificialSingleSampleReadStream(header,
+                                                                                                                              readGroupID,
+                                                                                                                              numContigs,
+                                                                                                                              stacksPerContig,
+                                                                                                                              minReadsPerStack,
+                                                                                                                              maxReadsPerStack,
+                                                                                                                              minDistanceBetweenStacks,
+                                                                                                                              maxDistanceBetweenStacks,
+                                                                                                                              minReadLength,
+                                                                                                                              maxReadLength,
+                                                                                                                              numUnmappedReads));
+                                            }
+                                        }
+                                    }
+                                }
+                            }
+                        }
+                    }
+                }
+            }
+        }
+
+        return ArtificialSingleSampleReadStreamTest.getTests(ArtificialSingleSampleReadStreamTest.class);
+    }
+
+    @Test(dataProvider = "ArtificialSingleSampleReadStreamTestDataProvider")
+    public void testArtificialSingleSampleReadStream( ArtificialSingleSampleReadStreamTest test ) {
+        logger.warn("Running test: " + test);
+
+        GenomeAnalysisEngine.resetRandomGenerator();
+        test.run();
+    }
+
+    @DataProvider(name = "ArtificialSingleSampleReadStreamInvalidArgumentsTestDataProvider")
+    public Object[][] createInvalidArgumentsTests() {
+        SAMFileHeader header = ArtificialSAMUtils.createArtificialSamHeader(3, 1, 10000);
+        String readGroupID = "testReadGroup";
+        header.addReadGroup(new SAMReadGroupRecord(readGroupID));
+
+        return new Object[][] {
+            {"testNullHeader", null, readGroupID, 1, 1, 1, 2, 1, 2, 1, 2, 0},
+            {"testNullReadGroup", header, null, 1, 1, 1, 2, 1, 2, 1, 2, 0},
+            {"testInvalidReadGroup", header, "foo", 1, 1, 1, 2, 1, 2, 1, 2, 0},
+            {"testInvalidNumContigs", header, readGroupID, -1, 1, 1, 2, 1, 2, 1, 2, 0},
+            {"testInvalidNumStacksPerContig", header, readGroupID, 1, -1, 1, 2, 1, 2, 1, 2, 0},
+            {"test0ContigsNon0StacksPerContig", header, readGroupID, 0, 1, 1, 2, 1, 2, 1, 2, 0},
+            {"testNon0Contigs0StacksPerContig", header, readGroupID, 1, 0, 1, 2, 1, 2, 1, 2, 0},
+            {"testInvalidMinReadsPerStack", header, readGroupID, 1, 1, -1, 2, 1, 2, 1, 2, 0},
+            {"testInvalidMaxReadsPerStack", header, readGroupID, 1, 1, 1, -2, 1, 2, 1, 2, 0},
+            {"testInvalidMinDistanceBetweenStacks", header, readGroupID, 1, 1, 1, 2, -1, 2, 1, 2, 0},
+            {"testInvalidMaxDistanceBetweenStacks", header, readGroupID, 1, 1, 1, 2, 1, -2, 1, 2, 0},
+            {"testInvalidMinReadLength", header, readGroupID, 1, 1, 1, 2, 1, 2, -1, 2, 0},
+            {"testInvalidMaxReadLength", header, readGroupID, 1, 1, 1, 2, 1, 2, 1, -2, 0},
+            {"testInvalidReadsPerStackRange", header, readGroupID, 1, 1, 2, 1, 1, 2, 1, 2, 0},
+            {"testInvalidDistanceBetweenStacksRange", header, readGroupID, 1, 1, 1, 2, 2, 1, 1, 2, 0},
+            {"testInvalidReadLengthRange", header, readGroupID, 1, 1, 1, 2, 1, 2, 2, 1, 0},
+            {"testInvalidNumUnmappedReads", header, readGroupID, 1, 1, 1, 2, 1, 2, 1, 2, -1},
+        };
+    }
+
+    @Test(dataProvider = "ArtificialSingleSampleReadStreamInvalidArgumentsTestDataProvider",
+          expectedExceptions = ReviewedGATKException.class)
+    public void testInvalidArguments( String testName,
+                                      SAMFileHeader header,
+                                      String readGroupID,
+                                      int numContigs,
+                                      int numStacksPerContig,
+                                      int minReadsPerStack,
+                                      int maxReadsPerStack,
+                                      int minDistanceBetweenStacks,
+                                      int maxDistanceBetweenStacks,
+                                      int minReadLength,
+                                      int maxReadLength,
+                                      int numUnmappedReads ) {
+
+        logger.warn("Running test: " + testName);
+
+        ArtificialSingleSampleReadStream stream = new ArtificialSingleSampleReadStream(header,
+                                                                                       readGroupID,
+                                                                                       numContigs,
+                                                                                       numStacksPerContig,
+                                                                                       minReadsPerStack,
+                                                                                       maxReadsPerStack,
+                                                                                       minDistanceBetweenStacks,
+                                                                                       maxDistanceBetweenStacks,
+                                                                                       minReadLength,
+                                                                                       maxReadLength,
+                                                                                       numUnmappedReads);
+    }
+}
diff --git a/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/utils/sam/GATKSAMRecordUnitTest.java b/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/utils/sam/GATKSAMRecordUnitTest.java
new file mode 100644
index 0000000..e703c52
--- /dev/null
+++ b/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/utils/sam/GATKSAMRecordUnitTest.java
@@ -0,0 +1,78 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.utils.sam;
+
+import htsjdk.samtools.SAMFileHeader;
+import org.broadinstitute.gatk.utils.BaseTest;
+import org.testng.Assert;
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.Test;
+
+
+public class GATKSAMRecordUnitTest extends BaseTest {
+    GATKSAMRecord read;
+    final static String BASES = "ACTG";
+    final static String QUALS = "!+5?";
+
+    @BeforeClass
+    public void init() {
+        SAMFileHeader header = ArtificialSAMUtils.createArtificialSamHeader(1, 1, 1000);
+        read = ArtificialSAMUtils.createArtificialRead(header, "read1", 0, 1, BASES.length());
+        read.setReadUnmappedFlag(true);
+        read.setReadBases(new String(BASES).getBytes());
+        read.setBaseQualityString(new String(QUALS));
+    }
+
+    @Test
+    public void testStrandlessReads() {
+        final byte [] bases = {'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A'};
+        final byte [] quals = {20 , 20 , 20 , 20 , 20 , 20 , 20 , 20 };
+        GATKSAMRecord read = ArtificialSAMUtils.createArtificialRead(bases, quals, "6M");
+        Assert.assertEquals(read.isStrandless(), false);
+
+        read.setReadNegativeStrandFlag(false);
+        Assert.assertEquals(read.isStrandless(), false);
+        Assert.assertEquals(read.getReadNegativeStrandFlag(), false);
+
+        read.setReadNegativeStrandFlag(true);
+        Assert.assertEquals(read.isStrandless(), false);
+        Assert.assertEquals(read.getReadNegativeStrandFlag(), true);
+
+        read.setReadNegativeStrandFlag(true);
+        read.setIsStrandless(true);
+        Assert.assertEquals(read.isStrandless(), true);
+        Assert.assertEquals(read.getReadNegativeStrandFlag(), false, "negative strand flag should return false even through its set for a strandless read");
+    }
+
+    @Test(expectedExceptions = IllegalStateException.class)
+    public void testStrandlessReadsFailSetStrand() {
+        final byte [] bases = {'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A'};
+        final byte [] quals = {20 , 20 , 20 , 20 , 20 , 20 , 20 , 20 };
+        GATKSAMRecord read = ArtificialSAMUtils.createArtificialRead(bases, quals, "6M");
+        read.setIsStrandless(true);
+        read.setReadNegativeStrandFlag(true);
+    }
+}
diff --git a/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/utils/sam/MisencodedBaseQualityUnitTest.java b/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/utils/sam/MisencodedBaseQualityUnitTest.java
new file mode 100644
index 0000000..207e01a
--- /dev/null
+++ b/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/utils/sam/MisencodedBaseQualityUnitTest.java
@@ -0,0 +1,96 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.utils.sam;
+
+
+import htsjdk.samtools.SAMFileHeader;
+import org.broadinstitute.gatk.utils.BaseTest;
+import org.broadinstitute.gatk.utils.exceptions.UserException;
+import org.testng.Assert;
+import org.testng.annotations.BeforeMethod;
+import org.testng.annotations.Test;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+/**
+ * Basic unit test for misencoded quals
+ */
+public class MisencodedBaseQualityUnitTest extends BaseTest {
+
+    private static final String readBases = "AAAAAAAAAA";
+    private static final byte[] badQuals = { 59, 60, 62, 63, 64, 61, 62, 58, 57, 56 };
+    private static final byte[] goodQuals = { 60, 60, 60, 60, 60, 60, 60, 60, 60, 60 };
+    private static final byte[] fixedQuals = { 28, 29, 31, 32, 33, 30, 31, 27, 26, 25 };
+    private SAMFileHeader header;
+
+    @BeforeMethod
+    public void before() {
+        // reset the read counter so that we are deterministic
+        MisencodedBaseQualityReadTransformer.currentReadCounter = 0;
+        header = ArtificialSAMUtils.createArtificialSamHeader(1, 1, 1000);
+    }
+
+    private GATKSAMRecord createRead(final boolean useGoodBases) {
+        GATKSAMRecord read = ArtificialSAMUtils.createArtificialRead(header, "foo", 0, 10, readBases.getBytes(),
+                                                                     useGoodBases ? Arrays.copyOf(goodQuals, goodQuals.length) :
+                                                                                    Arrays.copyOf(badQuals, badQuals.length));
+        read.setCigarString("10M");
+        return read;
+    }
+
+    @Test(enabled = true)
+    public void testGoodQuals() {
+        final List<GATKSAMRecord> reads = new ArrayList<GATKSAMRecord>(10000);
+        for ( int i = 0; i < 10000; i++ )
+            reads.add(createRead(true));
+
+        testEncoding(reads);
+    }
+
+    @Test(enabled = true, expectedExceptions = {UserException.class})
+    public void testBadQualsThrowsError() {
+        final List<GATKSAMRecord> reads = new ArrayList<GATKSAMRecord>(10000);
+        for ( int i = 0; i < 10000; i++ )
+            reads.add(createRead(false));
+
+        testEncoding(reads);
+    }
+
+    @Test(enabled = true)
+    public void testFixBadQuals() {
+        final GATKSAMRecord read = createRead(false);
+        final GATKSAMRecord fixedRead = MisencodedBaseQualityReadTransformer.fixMisencodedQuals(read);
+        for ( int i = 0; i < fixedQuals.length; i++ )
+            Assert.assertEquals(fixedQuals[i], fixedRead.getBaseQualities()[i]);
+    }
+
+    private void testEncoding(final List<GATKSAMRecord> reads) {
+        for ( final GATKSAMRecord read : reads )
+            MisencodedBaseQualityReadTransformer.checkForMisencodedQuals(read);
+    }
+}
\ No newline at end of file
diff --git a/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/utils/sam/ReadUtilsUnitTest.java b/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/utils/sam/ReadUtilsUnitTest.java
new file mode 100644
index 0000000..c7ceea1
--- /dev/null
+++ b/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/utils/sam/ReadUtilsUnitTest.java
@@ -0,0 +1,340 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.utils.sam;
+
+import htsjdk.samtools.reference.IndexedFastaSequenceFile;
+import htsjdk.samtools.SAMFileHeader;
+import org.broadinstitute.gatk.utils.BaseTest;
+import org.broadinstitute.gatk.engine.GenomeAnalysisEngine;
+import org.broadinstitute.gatk.utils.BaseUtils;
+import org.broadinstitute.gatk.utils.Utils;
+import org.broadinstitute.gatk.utils.fasta.CachingIndexedFastaSequenceFile;
+import org.testng.Assert;
+import org.testng.annotations.DataProvider;
+import org.testng.annotations.Test;
+
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.util.*;
+
+
+public class ReadUtilsUnitTest extends BaseTest {
+    private interface GetAdaptorFunc {
+        public int getAdaptor(final GATKSAMRecord record);
+    }
+
+    @DataProvider(name = "AdaptorGetter")
+    public Object[][] makeActiveRegionCutTests() {
+        final List<Object[]> tests = new LinkedList<Object[]>();
+
+        tests.add( new Object[]{ new GetAdaptorFunc() {
+            @Override public int getAdaptor(final GATKSAMRecord record) { return ReadUtils.getAdaptorBoundary(record); }
+        }});
+
+        tests.add( new Object[]{ new GetAdaptorFunc() {
+            @Override public int getAdaptor(final GATKSAMRecord record) { return record.getAdaptorBoundary(); }
+        }});
+
+        return tests.toArray(new Object[][]{});
+    }
+
+    private GATKSAMRecord makeRead(final int fragmentSize, final int mateStart) {
+        final byte[] bases = {'A', 'C', 'G', 'T', 'A', 'C', 'G', 'T'};
+        final byte[] quals = {30, 30, 30, 30, 30, 30, 30, 30};
+        final String cigar = "8M";
+        GATKSAMRecord read = ArtificialSAMUtils.createArtificialRead(bases, quals, cigar);
+        read.setProperPairFlag(true);
+        read.setReadPairedFlag(true);
+        read.setMateAlignmentStart(mateStart);
+        read.setInferredInsertSize(fragmentSize);
+        return read;
+    }
+
+    @Test(dataProvider = "AdaptorGetter")
+    public void testGetAdaptorBoundary(final GetAdaptorFunc get) {
+        final int fragmentSize = 10;
+        final int mateStart = 1000;
+        final int BEFORE = mateStart - 2;
+        final int AFTER = mateStart + 2;
+        int myStart, boundary;
+        GATKSAMRecord read;
+
+        // Test case 1: positive strand, first read
+        read = makeRead(fragmentSize, mateStart);
+        myStart = BEFORE;
+        read.setAlignmentStart(myStart);
+        read.setReadNegativeStrandFlag(false);
+        read.setMateNegativeStrandFlag(true);
+        boundary = get.getAdaptor(read);
+        Assert.assertEquals(boundary, myStart + fragmentSize + 1);
+
+        // Test case 2: positive strand, second read
+        read = makeRead(fragmentSize, mateStart);
+        myStart = AFTER;
+        read.setAlignmentStart(myStart);
+        read.setReadNegativeStrandFlag(false);
+        read.setMateNegativeStrandFlag(true);
+        boundary = get.getAdaptor(read);
+        Assert.assertEquals(boundary, myStart + fragmentSize + 1);
+
+        // Test case 3: negative strand, second read
+        read = makeRead(fragmentSize, mateStart);
+        myStart = AFTER;
+        read.setAlignmentStart(myStart);
+        read.setReadNegativeStrandFlag(true);
+        read.setMateNegativeStrandFlag(false);
+        boundary = get.getAdaptor(read);
+        Assert.assertEquals(boundary, mateStart - 1);
+
+        // Test case 4: negative strand, first read
+        read = makeRead(fragmentSize, mateStart);
+        myStart = BEFORE;
+        read.setAlignmentStart(myStart);
+        read.setReadNegativeStrandFlag(true);
+        read.setMateNegativeStrandFlag(false);
+        boundary = get.getAdaptor(read);
+        Assert.assertEquals(boundary, mateStart - 1);
+
+        // Test case 5: mate is mapped to another chromosome (test both strands)
+        read = makeRead(fragmentSize, mateStart);
+        read.setInferredInsertSize(0);
+        read.setReadNegativeStrandFlag(true);
+        read.setMateNegativeStrandFlag(false);
+        boundary = get.getAdaptor(read);
+        Assert.assertEquals(boundary, ReadUtils.CANNOT_COMPUTE_ADAPTOR_BOUNDARY);
+        read.setReadNegativeStrandFlag(false);
+        read.setMateNegativeStrandFlag(true);
+        boundary = get.getAdaptor(read);
+        Assert.assertEquals(boundary, ReadUtils.CANNOT_COMPUTE_ADAPTOR_BOUNDARY);
+        read.setInferredInsertSize(10);
+
+        // Test case 6: read is unmapped
+        read = makeRead(fragmentSize, mateStart);
+        read.setReadUnmappedFlag(true);
+        boundary = get.getAdaptor(read);
+        Assert.assertEquals(boundary, ReadUtils.CANNOT_COMPUTE_ADAPTOR_BOUNDARY);
+        read.setReadUnmappedFlag(false);
+
+        // Test case 7:  reads don't overlap and look like this:
+        //    <--------|
+        //                 |------>
+        // first read:
+        read = makeRead(fragmentSize, mateStart);
+        myStart = 980;
+        read.setAlignmentStart(myStart);
+        read.setInferredInsertSize(20);
+        read.setReadNegativeStrandFlag(true);
+        boundary = get.getAdaptor(read);
+        Assert.assertEquals(boundary, ReadUtils.CANNOT_COMPUTE_ADAPTOR_BOUNDARY);
+
+        // second read:
+        read = makeRead(fragmentSize, mateStart);
+        myStart = 1000;
+        read.setAlignmentStart(myStart);
+        read.setInferredInsertSize(20);
+        read.setMateAlignmentStart(980);
+        read.setReadNegativeStrandFlag(false);
+        boundary = get.getAdaptor(read);
+        Assert.assertEquals(boundary, ReadUtils.CANNOT_COMPUTE_ADAPTOR_BOUNDARY);
+
+        // Test case 8: read doesn't have proper pair flag set
+        read = makeRead(fragmentSize, mateStart);
+        read.setReadPairedFlag(true);
+        read.setProperPairFlag(false);
+        Assert.assertEquals(get.getAdaptor(read), ReadUtils.CANNOT_COMPUTE_ADAPTOR_BOUNDARY);
+
+        // Test case 9: read and mate have same negative flag setting
+        for ( final boolean negFlag: Arrays.asList(true, false) ) {
+            read = makeRead(fragmentSize, mateStart);
+            read.setAlignmentStart(BEFORE);
+            read.setReadPairedFlag(true);
+            read.setProperPairFlag(true);
+            read.setReadNegativeStrandFlag(negFlag);
+            read.setMateNegativeStrandFlag(!negFlag);
+            Assert.assertTrue(get.getAdaptor(read) != ReadUtils.CANNOT_COMPUTE_ADAPTOR_BOUNDARY, "Get adaptor should have succeeded");
+
+            read = makeRead(fragmentSize, mateStart);
+            read.setAlignmentStart(BEFORE);
+            read.setReadPairedFlag(true);
+            read.setProperPairFlag(true);
+            read.setReadNegativeStrandFlag(negFlag);
+            read.setMateNegativeStrandFlag(negFlag);
+            Assert.assertEquals(get.getAdaptor(read), ReadUtils.CANNOT_COMPUTE_ADAPTOR_BOUNDARY, "Get adaptor should have failed for reads with bad alignment orientation");
+        }
+    }
+
+    @Test (enabled = true)
+    public void testGetBasesReverseComplement() {
+        int iterations = 1000;
+        Random random = GenomeAnalysisEngine.getRandomGenerator();
+        while(iterations-- > 0) {
+            final int l = random.nextInt(1000);
+            GATKSAMRecord read = GATKSAMRecord.createRandomRead(l);
+            byte [] original = read.getReadBases();
+            byte [] reconverted = new byte[l];
+            String revComp = ReadUtils.getBasesReverseComplement(read);
+            for (int i=0; i<l; i++) {
+                reconverted[l-1-i] = BaseUtils.getComplement((byte) revComp.charAt(i));
+            }
+            Assert.assertEquals(reconverted, original);
+        }
+    }
+
+    @Test (enabled = true)
+    public void testGetMaxReadLength() {
+        for( final int minLength : Arrays.asList( 5, 30, 50 ) ) {
+            for( final int maxLength : Arrays.asList( 50, 75, 100 ) ) {
+                final List<GATKSAMRecord> reads = new ArrayList<GATKSAMRecord>();
+                for( int readLength = minLength; readLength <= maxLength; readLength++ ) {
+                    reads.add( ReadUtils.createRandomRead( readLength ) );
+                }
+                Assert.assertEquals(ReadUtils.getMaxReadLength(reads), maxLength, "max length does not match");
+            }
+        }
+
+        final List<GATKSAMRecord> reads = new LinkedList<GATKSAMRecord>();
+        Assert.assertEquals(ReadUtils.getMaxReadLength(reads), 0, "Empty list should have max length of zero");
+    }
+
+    @Test (enabled = true)
+    public void testReadWithNsRefIndexInDeletion() throws FileNotFoundException {
+
+        final IndexedFastaSequenceFile seq = new CachingIndexedFastaSequenceFile(new File(b37KGReference));
+        final SAMFileHeader header = ArtificialSAMUtils.createArtificialSamHeader(seq.getSequenceDictionary());
+        final int readLength = 76;
+
+        final GATKSAMRecord read = ArtificialSAMUtils.createArtificialRead(header, "myRead", 0, 8975, readLength);
+        read.setReadBases(Utils.dupBytes((byte) 'A', readLength));
+        read.setBaseQualities(Utils.dupBytes((byte)30, readLength));
+        read.setCigarString("3M414N1D73M");
+
+        final int result = ReadUtils.getReadCoordinateForReferenceCoordinateUpToEndOfRead(read, 9392, ReadUtils.ClippingTail.LEFT_TAIL);
+        Assert.assertEquals(result, 2);
+    }
+
+    @Test (enabled = true)
+    public void testReadWithNsRefAfterDeletion() throws FileNotFoundException {
+
+        final IndexedFastaSequenceFile seq = new CachingIndexedFastaSequenceFile(new File(b37KGReference));
+        final SAMFileHeader header = ArtificialSAMUtils.createArtificialSamHeader(seq.getSequenceDictionary());
+        final int readLength = 76;
+
+        final GATKSAMRecord read = ArtificialSAMUtils.createArtificialRead(header, "myRead", 0, 8975, readLength);
+        read.setReadBases(Utils.dupBytes((byte) 'A', readLength));
+        read.setBaseQualities(Utils.dupBytes((byte)30, readLength));
+        read.setCigarString("3M414N1D73M");
+
+        final int result = ReadUtils.getReadCoordinateForReferenceCoordinateUpToEndOfRead(read, 9393, ReadUtils.ClippingTail.LEFT_TAIL);
+        Assert.assertEquals(result, 3);
+    }
+
+    @DataProvider(name = "HasWellDefinedFragmentSizeData")
+    public Object[][] makeHasWellDefinedFragmentSizeData() throws Exception {
+        final List<Object[]> tests = new LinkedList<Object[]>();
+
+        // setup a basic read that will work
+        final SAMFileHeader header = ArtificialSAMUtils.createArtificialSamHeader();
+        final GATKSAMRecord read = ArtificialSAMUtils.createArtificialRead(header, "read1", 0, 10, 10);
+        read.setReadPairedFlag(true);
+        read.setProperPairFlag(true);
+        read.setReadUnmappedFlag(false);
+        read.setMateUnmappedFlag(false);
+        read.setAlignmentStart(100);
+        read.setCigarString("50M");
+        read.setMateAlignmentStart(130);
+        read.setInferredInsertSize(80);
+        read.setFirstOfPairFlag(true);
+        read.setReadNegativeStrandFlag(false);
+        read.setMateNegativeStrandFlag(true);
+
+        tests.add( new Object[]{ "basic case", read.clone(), true });
+
+        {
+            final GATKSAMRecord bad1 = (GATKSAMRecord)read.clone();
+            bad1.setReadPairedFlag(false);
+            tests.add( new Object[]{ "not paired", bad1, false });
+        }
+
+        {
+            final GATKSAMRecord bad = (GATKSAMRecord)read.clone();
+            bad.setProperPairFlag(false);
+            // we currently don't require the proper pair flag to be set
+            tests.add( new Object[]{ "not proper pair", bad, true });
+//            tests.add( new Object[]{ "not proper pair", bad, false });
+        }
+
+        {
+            final GATKSAMRecord bad = (GATKSAMRecord)read.clone();
+            bad.setReadUnmappedFlag(true);
+            tests.add( new Object[]{ "read is unmapped", bad, false });
+        }
+
+        {
+            final GATKSAMRecord bad = (GATKSAMRecord)read.clone();
+            bad.setMateUnmappedFlag(true);
+            tests.add( new Object[]{ "mate is unmapped", bad, false });
+        }
+
+        {
+            final GATKSAMRecord bad = (GATKSAMRecord)read.clone();
+            bad.setMateNegativeStrandFlag(false);
+            tests.add( new Object[]{ "read and mate both on positive strand", bad, false });
+        }
+
+        {
+            final GATKSAMRecord bad = (GATKSAMRecord)read.clone();
+            bad.setReadNegativeStrandFlag(true);
+            tests.add( new Object[]{ "read and mate both on negative strand", bad, false });
+        }
+
+        {
+            final GATKSAMRecord bad = (GATKSAMRecord)read.clone();
+            bad.setInferredInsertSize(0);
+            tests.add( new Object[]{ "insert size is 0", bad, false });
+        }
+
+        {
+            final GATKSAMRecord bad = (GATKSAMRecord)read.clone();
+            bad.setAlignmentStart(1000);
+            tests.add( new Object[]{ "positve read starts after mate end", bad, false });
+        }
+
+        {
+            final GATKSAMRecord bad = (GATKSAMRecord)read.clone();
+            bad.setReadNegativeStrandFlag(true);
+            bad.setMateNegativeStrandFlag(false);
+            bad.setMateAlignmentStart(1000);
+            tests.add( new Object[]{ "negative strand read ends before mate starts", bad, false });
+        }
+
+        return tests.toArray(new Object[][]{});
+    }
+
+    @Test(dataProvider = "HasWellDefinedFragmentSizeData")
+    private void testHasWellDefinedFragmentSize(final String name, final GATKSAMRecord read, final boolean expected) {
+        Assert.assertEquals(ReadUtils.hasWellDefinedFragmentSize(read), expected);
+    }
+}
diff --git a/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/utils/smithwaterman/SmithWatermanBenchmark.java b/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/utils/smithwaterman/SmithWatermanBenchmark.java
new file mode 100644
index 0000000..44ba64c
--- /dev/null
+++ b/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/utils/smithwaterman/SmithWatermanBenchmark.java
@@ -0,0 +1,87 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.utils.smithwaterman;
+
+import com.google.caliper.Param;
+import com.google.caliper.SimpleBenchmark;
+import org.broadinstitute.gatk.utils.Utils;
+
+/**
+ * Caliper microbenchmark of parsing a VCF file
+ */
+public class SmithWatermanBenchmark extends SimpleBenchmark {
+
+    @Param({"Original"})
+    String version; // set automatically by framework
+
+    @Param({"10", "50", "100", "500"})
+    int sizeOfMiddleRegion; // set automatically by framework
+
+    @Param({"10", "50", "100", "500"})
+    int sizeOfEndRegions; // set automatically by framework
+
+    String refString;
+    String hapString;
+
+    @Override protected void setUp() {
+        final StringBuilder ref = new StringBuilder();
+        final StringBuilder hap = new StringBuilder();
+
+        ref.append(Utils.dupString('A', sizeOfEndRegions));
+        hap.append(Utils.dupString('A', sizeOfEndRegions));
+
+        // introduce a SNP
+        ref.append("X");
+        hap.append("Y");
+
+        ref.append(Utils.dupString('A', sizeOfMiddleRegion));
+        hap.append(Utils.dupString('A', sizeOfMiddleRegion));
+
+        // introduce a SNP
+        ref.append("X");
+        hap.append("Y");
+
+        ref.append(Utils.dupString('A', sizeOfEndRegions));
+        hap.append(Utils.dupString('A', sizeOfEndRegions));
+
+        refString = ref.toString();
+        hapString = hap.toString();
+    }
+
+    public void timeSW(int rep) {
+        for ( int i = 0; i < rep; i++ ) {
+            final SmithWaterman sw;
+            if ( version.equals("Greedy") )
+                throw new IllegalArgumentException("Unsupported implementation");
+            sw = new SWPairwiseAlignment(refString.getBytes(), hapString.getBytes());
+            sw.getCigar();
+        }
+    }
+
+    public static void main(String[] args) {
+        com.google.caliper.Runner.main(SmithWatermanBenchmark.class, args);
+    }
+}
diff --git a/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/utils/text/ListFileUtilsUnitTest.java b/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/utils/text/ListFileUtilsUnitTest.java
new file mode 100644
index 0000000..086cefe
--- /dev/null
+++ b/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/utils/text/ListFileUtilsUnitTest.java
@@ -0,0 +1,159 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.utils.text;
+
+import org.broadinstitute.gatk.utils.BaseTest;
+import org.broadinstitute.gatk.utils.commandline.ParsingEngine;
+import org.broadinstitute.gatk.utils.commandline.Tags;
+import org.broadinstitute.gatk.engine.CommandLineGATK;
+import org.broadinstitute.gatk.engine.datasources.reads.SAMReaderID;
+import org.testng.Assert;
+import org.testng.annotations.DataProvider;
+import org.testng.annotations.Test;
+
+import java.io.File;
+import java.io.PrintWriter;
+import java.util.*;
+
+/**
+ * Tests selected functionality in the CommandLineExecutable class
+ */
+public class ListFileUtilsUnitTest extends BaseTest {
+
+    @Test
+    public void testIgnoreBlankLinesInBAMListFiles() throws Exception {
+        File tempListFile = createTempListFile("testIgnoreBlankLines",
+                                               "",
+                                               publicTestDir + "exampleBAM.bam",
+                                               "         "
+                                              );
+
+        List<SAMReaderID> expectedBAMFileListAfterUnpacking = new ArrayList<SAMReaderID>();
+        expectedBAMFileListAfterUnpacking.add(new SAMReaderID(new File(publicTestDir + "exampleBAM.bam"), new Tags()));
+
+        performBAMListFileUnpackingTest(tempListFile, expectedBAMFileListAfterUnpacking);
+    }
+
+    @Test
+    public void testCommentSupportInBAMListFiles() throws Exception {
+        File tempListFile = createTempListFile("testCommentSupport",
+                                               "#",
+                                               publicTestDir + "exampleBAM.bam",
+                                               "#" + publicTestDir + "foo.bam",
+                                               "      # " + publicTestDir + "bar.bam"
+                                              );
+
+        List<SAMReaderID> expectedBAMFileListAfterUnpacking = new ArrayList<SAMReaderID>();
+        expectedBAMFileListAfterUnpacking.add(new SAMReaderID(new File(publicTestDir + "exampleBAM.bam"), new Tags()));
+
+        performBAMListFileUnpackingTest(tempListFile, expectedBAMFileListAfterUnpacking);
+    }
+
+    @Test
+    public void testUnpackSet() throws Exception {
+        Set<String> expected = new HashSet<String>(Arrays.asList(publicTestDir + "exampleBAM.bam"));
+        Set<String> actual;
+
+        actual = ListFileUtils.unpackSet(Arrays.asList(publicTestDir + "exampleBAM.bam"));
+        Assert.assertEquals(actual, expected);
+
+        File tempListFile = createTempListFile("testUnpackSet",
+                "#",
+                publicTestDir + "exampleBAM.bam",
+                "#" + publicTestDir + "foo.bam",
+                "      # " + publicTestDir + "bar.bam"
+        );
+        actual = ListFileUtils.unpackSet(Arrays.asList(tempListFile.getAbsolutePath()));
+        Assert.assertEquals(actual, expected);
+    }
+
+    @DataProvider(name="includeMatchingTests")
+    public Object[][] getIncludeMatchingTests() {
+        return new Object[][] {
+                new Object[] { asSet("a", "ab", "abc"), Arrays.asList("a"), true, asSet("a") },
+                new Object[] { asSet("a", "ab", "abc"), Arrays.asList("a"), false, asSet("a", "ab", "abc") },
+                new Object[] { asSet("a", "ab", "abc"), Arrays.asList("b"), true, Collections.EMPTY_SET },
+                new Object[] { asSet("a", "ab", "abc"), Arrays.asList("b"), false, asSet("ab", "abc") },
+                new Object[] { asSet("a", "ab", "abc"), Arrays.asList("a", "b"), true, asSet("a") },
+                new Object[] { asSet("a", "ab", "abc"), Arrays.asList("a", "b"), false, asSet("a", "ab", "abc") },
+                new Object[] { asSet("a", "ab", "abc"), Arrays.asList("a", "ab"), true, asSet("a", "ab") },
+                new Object[] { asSet("a", "ab", "abc"), Arrays.asList("a", "ab"), false, asSet("a", "ab", "abc") },
+                new Object[] { asSet("a", "ab", "abc"), Arrays.asList(".*b.*"), true, Collections.EMPTY_SET },
+                new Object[] { asSet("a", "ab", "abc"), Arrays.asList(".*b.*"), false, asSet("ab", "abc") },
+                new Object[] { asSet("a", "ab", "abc"), Arrays.asList(".*"), true, Collections.EMPTY_SET },
+                new Object[] { asSet("a", "ab", "abc"), Arrays.asList(".*"), false, asSet("a", "ab", "abc") }
+        };
+    }
+
+    @Test(dataProvider = "includeMatchingTests")
+    public void testIncludeMatching(Set<String> values, Collection<String> filters, boolean exactMatch, Set<String> expected) {
+        Set<String> actual = ListFileUtils.includeMatching(values, ListFileUtils.IDENTITY_STRING_CONVERTER, filters, exactMatch);
+        Assert.assertEquals(actual, expected);
+    }
+
+    @DataProvider(name="excludeMatchingTests")
+    public Object[][] getExcludeMatchingTests() {
+        return new Object[][] {
+                new Object[] { asSet("a", "ab", "abc"), Arrays.asList("a"), true, asSet("ab", "abc") },
+                new Object[] { asSet("a", "ab", "abc"), Arrays.asList("a"), false, Collections.EMPTY_SET },
+                new Object[] { asSet("a", "ab", "abc"), Arrays.asList("b"), true, asSet("a", "ab", "abc") },
+                new Object[] { asSet("a", "ab", "abc"), Arrays.asList("b"), false, asSet("a") },
+                new Object[] { asSet("a", "ab", "abc"), Arrays.asList("a", "b"), true, asSet("ab", "abc") },
+                new Object[] { asSet("a", "ab", "abc"), Arrays.asList("a", "b"), false, Collections.EMPTY_SET },
+                new Object[] { asSet("a", "ab", "abc"), Arrays.asList("a", "ab"), true, asSet("abc") },
+                new Object[] { asSet("a", "ab", "abc"), Arrays.asList("a", "ab"), false, Collections.EMPTY_SET },
+                new Object[] { asSet("a", "ab", "abc"), Arrays.asList(".*b.*"), true, asSet("a", "ab", "abc") },
+                new Object[] { asSet("a", "ab", "abc"), Arrays.asList(".*b.*"), false, asSet("a") },
+                new Object[] { asSet("a", "ab", "abc"), Arrays.asList(".*"), true, asSet("a", "ab", "abc") },
+                new Object[] { asSet("a", "ab", "abc"), Arrays.asList(".*"), false, Collections.EMPTY_SET }
+        };
+    }
+
+    @Test(dataProvider = "excludeMatchingTests")
+    public void testExcludeMatching(Set<String> values, Collection<String> filters, boolean exactMatch, Set<String> expected) {
+        Set<String> actual = ListFileUtils.excludeMatching(values, ListFileUtils.IDENTITY_STRING_CONVERTER, filters, exactMatch);
+        Assert.assertEquals(actual, expected);
+    }
+
+    private static <T> Set<T> asSet(T... args){
+        return new HashSet<T>(Arrays.asList(args));
+    }
+
+    private void performBAMListFileUnpackingTest( File tempListFile, List<SAMReaderID> expectedUnpackedFileList ) throws Exception {
+        List<String> bamFiles = new ArrayList<String>();
+        bamFiles.add(tempListFile.getAbsolutePath());
+
+        CommandLineGATK testInstance = new CommandLineGATK();
+        testInstance.setParser(new ParsingEngine(testInstance));
+
+        List<SAMReaderID> unpackedBAMFileList = ListFileUtils.unpackBAMFileList(bamFiles,new ParsingEngine(testInstance));
+
+        Assert.assertEquals(unpackedBAMFileList.size(), expectedUnpackedFileList.size(),
+                            "Unpacked BAM file list contains extraneous lines");
+        Assert.assertEquals(unpackedBAMFileList, expectedUnpackedFileList,
+                            "Unpacked BAM file list does not contain correct BAM file names");
+    }
+}
diff --git a/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/utils/text/TextFormattingUtilsUnitTest.java b/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/utils/text/TextFormattingUtilsUnitTest.java
new file mode 100644
index 0000000..5457310
--- /dev/null
+++ b/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/utils/text/TextFormattingUtilsUnitTest.java
@@ -0,0 +1,89 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.utils.text;
+
+import org.broadinstitute.gatk.utils.BaseTest;
+import org.broadinstitute.gatk.utils.exceptions.ReviewedGATKException;
+import org.testng.Assert;
+import org.testng.annotations.Test;
+
+import java.util.Arrays;
+import java.util.Collections;
+
+public class TextFormattingUtilsUnitTest extends BaseTest {
+    @Test(expectedExceptions = ReviewedGATKException.class)
+    public void testSplitWhiteSpaceNullLine() {
+        TextFormattingUtils.splitWhiteSpace(null);
+    }
+
+    @Test
+    public void testSplitWhiteSpace() {
+        Assert.assertEquals(TextFormattingUtils.splitWhiteSpace("foo bar baz"), new String[] { "foo", "bar", "baz" });
+        Assert.assertEquals(TextFormattingUtils.splitWhiteSpace("foo  bar  baz"), new String[] { "foo", "bar", "baz" });
+        Assert.assertEquals(TextFormattingUtils.splitWhiteSpace(" foo bar baz"), new String[] { "foo", "bar", "baz" });
+        Assert.assertEquals(TextFormattingUtils.splitWhiteSpace(" foo bar baz "), new String[] { "foo", "bar", "baz" });
+        Assert.assertEquals(TextFormattingUtils.splitWhiteSpace("foo bar baz "), new String[] { "foo", "bar", "baz" });
+        Assert.assertEquals(TextFormattingUtils.splitWhiteSpace("\tfoo\tbar\tbaz\t"), new String[]{"foo", "bar", "baz"});
+    }
+
+    @Test(expectedExceptions = ReviewedGATKException.class)
+    public void testGetWordStartsNullLine() {
+        TextFormattingUtils.getWordStarts(null);
+    }
+
+    @Test
+    public void testGetWordStarts() {
+        Assert.assertEquals(TextFormattingUtils.getWordStarts("foo bar baz"), Arrays.asList(4, 8));
+        Assert.assertEquals(TextFormattingUtils.getWordStarts("foo  bar  baz"), Arrays.asList(5, 10));
+        Assert.assertEquals(TextFormattingUtils.getWordStarts(" foo bar baz"), Arrays.asList(1, 5, 9));
+        Assert.assertEquals(TextFormattingUtils.getWordStarts(" foo bar baz "), Arrays.asList(1, 5, 9));
+        Assert.assertEquals(TextFormattingUtils.getWordStarts("foo bar baz "), Arrays.asList(4, 8));
+        Assert.assertEquals(TextFormattingUtils.getWordStarts("\tfoo\tbar\tbaz\t"), Arrays.asList(1, 5, 9));
+    }
+
+    @Test(expectedExceptions = ReviewedGATKException.class)
+    public void testSplitFixedWidthNullLine() {
+        TextFormattingUtils.splitFixedWidth(null, Collections.<Integer>emptyList());
+    }
+
+    @Test(expectedExceptions = ReviewedGATKException.class)
+    public void testSplitFixedWidthNullColumnStarts() {
+        TextFormattingUtils.splitFixedWidth("foo bar baz", null);
+    }
+
+    @Test
+    public void testSplitFixedWidth() {
+        Assert.assertEquals(TextFormattingUtils.splitFixedWidth("foo bar baz", Arrays.asList(4, 8)), new String[] { "foo", "bar", "baz" });
+        Assert.assertEquals(TextFormattingUtils.splitFixedWidth("foo  bar  baz", Arrays.asList(5, 10)), new String[] { "foo", "bar", "baz" });
+        Assert.assertEquals(TextFormattingUtils.splitFixedWidth(" foo bar baz", Arrays.asList(5, 9)), new String[] { "foo", "bar", "baz" });
+        Assert.assertEquals(TextFormattingUtils.splitFixedWidth(" foo bar baz ", Arrays.asList(5, 9)), new String[] { "foo", "bar", "baz" });
+        Assert.assertEquals(TextFormattingUtils.splitFixedWidth("foo bar baz ", Arrays.asList(4, 8)), new String[] { "foo", "bar", "baz" });
+        Assert.assertEquals(TextFormattingUtils.splitFixedWidth("\tfoo\tbar\tbaz\t", Arrays.asList(5, 9)), new String[] { "foo", "bar", "baz" });
+        Assert.assertEquals(TextFormattingUtils.splitFixedWidth("f o b r b z", Arrays.asList(4, 8)), new String[] { "f o", "b r", "b z" });
+        Assert.assertEquals(TextFormattingUtils.splitFixedWidth(" f o b r b z", Arrays.asList(4, 8)), new String[] { "f o", "b r", "b z" });
+        Assert.assertEquals(TextFormattingUtils.splitFixedWidth("  f o b r b z", Arrays.asList(4, 8)), new String[] { "f", "o b", "r b z" });
+    }
+}
diff --git a/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/utils/threading/EfficiencyMonitoringThreadFactoryUnitTest.java b/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/utils/threading/EfficiencyMonitoringThreadFactoryUnitTest.java
new file mode 100644
index 0000000..0c98813
--- /dev/null
+++ b/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/utils/threading/EfficiencyMonitoringThreadFactoryUnitTest.java
@@ -0,0 +1,189 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.utils.threading;
+
+import org.apache.log4j.Priority;
+import org.broadinstitute.gatk.utils.BaseTest;
+import org.broadinstitute.gatk.utils.Utils;
+import org.broadinstitute.gatk.utils.exceptions.ReviewedGATKException;
+import org.testng.Assert;
+import org.testng.annotations.DataProvider;
+import org.testng.annotations.Test;
+
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+import java.util.concurrent.Callable;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+import java.util.concurrent.TimeUnit;
+
+/**
+ * Tests for the state monitoring thread factory.
+ */
+public class EfficiencyMonitoringThreadFactoryUnitTest extends BaseTest {
+    // the duration of the tests -- 100 ms is tolerable given the number of tests we are doing
+    private final static long THREAD_TARGET_DURATION_IN_MILLISECOND = 100000;
+    private final static int MAX_THREADS = 4;
+    final static Object GLOBAL_LOCK = new Object();
+
+    private class StateTest extends TestDataProvider {
+        private final double TOLERANCE = 0.1; // willing to tolerate a 10% error
+
+        final List<EfficiencyMonitoringThreadFactory.State> statesForThreads;
+
+        public StateTest(final List<EfficiencyMonitoringThreadFactory.State> statesForThreads) {
+            super(StateTest.class);
+            this.statesForThreads = statesForThreads;
+            setName("StateTest " + Utils.join(",", statesForThreads));
+        }
+
+        public List<EfficiencyMonitoringThreadFactory.State> getStatesForThreads() {
+            return statesForThreads;
+        }
+
+        public int getNStates() { return statesForThreads.size(); }
+
+        public double maxStatePercent(final EfficiencyMonitoringThreadFactory.State state) { return 100*(fraction(state) + TOLERANCE); }
+        public double minStatePercent(final EfficiencyMonitoringThreadFactory.State state) { return 100*(fraction(state) - TOLERANCE); }
+
+        private double fraction(final EfficiencyMonitoringThreadFactory.State state) {
+            return Collections.frequency(statesForThreads, state) / (1.0 * statesForThreads.size());
+        }
+    }
+
+    /**
+     * Test helper threading class that puts the thread into RUNNING, BLOCKED, or WAITING state as
+     * requested for input argument
+     */
+    private static class StateTestThread implements Callable<Double> {
+        private final EfficiencyMonitoringThreadFactory.State stateToImplement;
+
+        private StateTestThread(final EfficiencyMonitoringThreadFactory.State stateToImplement) {
+            this.stateToImplement = stateToImplement;
+        }
+
+        @Override
+        public Double call() throws Exception {
+            switch ( stateToImplement ) {
+                case USER_CPU:
+                    // do some work until we get to THREAD_TARGET_DURATION_IN_MILLISECOND
+                    double sum = 0.0;
+                    final long startTime = System.currentTimeMillis();
+                    for ( int i = 1; System.currentTimeMillis() - startTime < (THREAD_TARGET_DURATION_IN_MILLISECOND - 1); i++ ) {
+                        sum += Math.log10(i);
+                    }
+                    return sum;
+                case WAITING:
+                    Thread.currentThread().sleep(THREAD_TARGET_DURATION_IN_MILLISECOND);
+                    return 0.0;
+                case BLOCKING:
+                    if ( EfficiencyMonitoringThreadFactory.DEBUG ) logger.warn("Blocking...");
+                    synchronized (GLOBAL_LOCK) {
+                        // the GLOBAL_LOCK must be held by the unit test itself for this to properly block
+                        if ( EfficiencyMonitoringThreadFactory.DEBUG ) logger.warn("  ... done blocking");
+                    }
+                    return 0.0;
+                case WAITING_FOR_IO:
+                    // TODO -- implement me
+                    // shouldn't ever get here, throw an exception
+                    throw new ReviewedGATKException("WAITING_FOR_IO testing currently not implemented, until we figure out how to force a system call block");
+                default:
+                    throw new ReviewedGATKException("Unexpected thread test state " + stateToImplement);
+            }
+        }
+    }
+
+    @DataProvider(name = "StateTest")
+    public Object[][] createStateTest() {
+        for ( final int nThreads : Arrays.asList(3) ) {
+            //final List<EfficiencyMonitoringThreadFactory.State> allStates = Arrays.asList(EfficiencyMonitoringThreadFactory.State.WAITING_FOR_IO);
+            final List<EfficiencyMonitoringThreadFactory.State> allStates = Arrays.asList(EfficiencyMonitoringThreadFactory.State.USER_CPU, EfficiencyMonitoringThreadFactory.State.WAITING, EfficiencyMonitoringThreadFactory.State.BLOCKING);
+            //final List<EfficiencyMonitoringThreadFactory.State> allStates = Arrays.asList(EfficiencyMonitoringThreadFactory.State.values());
+            for (final List<EfficiencyMonitoringThreadFactory.State> states : Utils.makePermutations(allStates, nThreads, true) ) {
+                //if ( Collections.frequency(states, Thread.State.BLOCKED) > 0)
+                    new StateTest(states);
+            }
+        }
+
+        return StateTest.getTests(StateTest.class);
+    }
+
+    // NOTE this test takes an unreasonably long time to run, and so it's been disabled as these monitoring threads
+    // aren't a core GATK feature any longer.  Should be reabled if we come to care about this capability again
+    // in the future, or we can run these in parallel
+    @Test(enabled = false, dataProvider = "StateTest", timeOut = MAX_THREADS * THREAD_TARGET_DURATION_IN_MILLISECOND)
+    public void testStateTest(final StateTest test) throws InterruptedException {
+        // allows us to test blocking
+        final EfficiencyMonitoringThreadFactory factory = new EfficiencyMonitoringThreadFactory(test.getNStates());
+        final ExecutorService threadPool = Executors.newFixedThreadPool(test.getNStates(), factory);
+
+        logger.warn("Running " + test);
+        synchronized (GLOBAL_LOCK) {
+            //logger.warn("  Have lock");
+            for ( final EfficiencyMonitoringThreadFactory.State threadToRunState : test.getStatesForThreads() )
+            threadPool.submit(new StateTestThread(threadToRunState));
+
+            // lock has to be here for the whole running of the activeThreads but end before the sleep so the blocked activeThreads
+            // can block for their allotted time
+            threadPool.shutdown();
+            Thread.sleep(THREAD_TARGET_DURATION_IN_MILLISECOND);
+        }
+        //logger.warn("  Releasing lock");
+        threadPool.awaitTermination(10, TimeUnit.SECONDS);
+        //logger.warn("  done awaiting termination");
+        //logger.warn("  waiting for all activeThreads to complete");
+        factory.waitForAllThreadsToComplete();
+        //logger.warn("  done waiting for activeThreads");
+
+        // make sure we counted everything properly
+        final long totalTime = factory.getTotalTime();
+        final long minTime = (long)(THREAD_TARGET_DURATION_IN_MILLISECOND * 0.5) * test.getNStates();
+        final long maxTime = (long)(THREAD_TARGET_DURATION_IN_MILLISECOND * 1.5) * test.getNStates();
+        //logger.warn("Testing total time");
+        Assert.assertTrue(totalTime >= minTime, "Factory results not properly accumulated: totalTime = " + totalTime + " < minTime = " + minTime);
+        Assert.assertTrue(totalTime <= maxTime, "Factory results not properly accumulated: totalTime = " + totalTime + " > maxTime = " + maxTime);
+
+        for (final EfficiencyMonitoringThreadFactory.State state : EfficiencyMonitoringThreadFactory.State.values() ) {
+            final double min = test.minStatePercent(state);
+            final double max = test.maxStatePercent(state);
+            final double obs = factory.getStatePercent(state);
+//            logger.warn("  Checking " + state
+//                    + " min " + String.format("%.2f", min)
+//                    + " max " + String.format("%.2f", max)
+//                    + " obs " + String.format("%.2f", obs)
+//                    + " factor = " + factory);
+            Assert.assertTrue(obs >= min, "Too little time spent in state " + state + " obs " + obs + " min " + min);
+            Assert.assertTrue(obs <= max, "Too much time spent in state " + state + " obs " + obs + " max " + min);
+        }
+
+        // we actually ran the expected number of activeThreads
+        Assert.assertEquals(factory.getNThreadsCreated(), test.getNStates());
+
+        // should be called to ensure we don't format / NPE on output
+        factory.printUsageInformation(logger, Priority.WARN);
+    }
+}
\ No newline at end of file
diff --git a/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/utils/threading/ThreadPoolMonitorUnitTest.java b/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/utils/threading/ThreadPoolMonitorUnitTest.java
new file mode 100644
index 0000000..a73cb26
--- /dev/null
+++ b/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/utils/threading/ThreadPoolMonitorUnitTest.java
@@ -0,0 +1,64 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.utils.threading;
+
+import org.testng.annotations.Test;
+import org.broadinstitute.gatk.utils.BaseTest;
+
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors; 
+/**
+ * User: hanna
+ * Date: Apr 29, 2009
+ * Time: 4:30:55 PM
+ * BROAD INSTITUTE SOFTWARE COPYRIGHT NOTICE AND AGREEMENT
+ * Software and documentation are copyright 2005 by the Broad Institute.
+ * All rights are reserved.
+ *
+ * Users acknowledge that this software is supplied without any warranty or support.
+ * The Broad Institute is not responsible for its use, misuse, or
+ * functionality.
+ */
+
+/**
+ * Tests for the thread pool monitor class.
+ */
+
+public class ThreadPoolMonitorUnitTest extends BaseTest {
+    private ExecutorService threadPool = Executors.newFixedThreadPool(1);
+
+    /**
+     * Test to make sure the thread pool wait works properly. 
+     */
+    @Test(timeOut=2000)
+    public void testThreadPoolMonitor() {
+        ThreadPoolMonitor monitor = new ThreadPoolMonitor();
+        synchronized(monitor) {
+            threadPool.submit(monitor);
+            monitor.watch();
+        }
+    }
+}
diff --git a/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/utils/variant/GATKVCFUtilsUnitTest.java b/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/utils/variant/GATKVCFUtilsUnitTest.java
new file mode 100644
index 0000000..ab547b7
--- /dev/null
+++ b/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/utils/variant/GATKVCFUtilsUnitTest.java
@@ -0,0 +1,138 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.utils.variant;
+
+import htsjdk.tribble.index.DynamicIndexCreator;
+import htsjdk.tribble.index.IndexCreator;
+import htsjdk.tribble.index.interval.IntervalIndexCreator;
+import htsjdk.tribble.index.linear.LinearIndexCreator;
+import org.broadinstitute.gatk.utils.BaseTest;
+import org.broadinstitute.gatk.engine.GenomeAnalysisEngine;
+import org.broadinstitute.gatk.engine.contexts.AlignmentContext;
+import org.broadinstitute.gatk.engine.contexts.ReferenceContext;
+import org.broadinstitute.gatk.engine.refdata.RefMetaDataTracker;
+import org.broadinstitute.gatk.engine.walkers.RodWalker;
+import org.broadinstitute.gatk.engine.walkers.Walker;
+import htsjdk.variant.vcf.VCFHeader;
+import htsjdk.variant.vcf.VCFHeaderLine;
+import org.testng.Assert;
+import org.testng.annotations.DataProvider;
+import org.testng.annotations.Test;
+
+import java.io.File;
+import java.lang.reflect.Method;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.Set;
+
+public class GATKVCFUtilsUnitTest extends BaseTest {
+    public static class VCFHeaderTestWalker extends RodWalker<Integer, Integer> {
+        public Integer map(RefMetaDataTracker tracker, ReferenceContext ref, AlignmentContext context) { return null; }
+        public Integer reduceInit() { return 0; }
+        public Integer reduce(Integer value, Integer sum) { return value + sum; }
+    }
+
+    public static class VCFHeaderTest2Walker extends VCFHeaderTestWalker {}
+
+    @Test
+    public void testAddingVCFHeaderInfo() {
+        final VCFHeader header = new VCFHeader();
+
+        final Walker walker1 = new VCFHeaderTestWalker();
+        final Walker walker2 = new VCFHeaderTest2Walker();
+
+        final GenomeAnalysisEngine testEngine1 = new GenomeAnalysisEngine();
+        testEngine1.setWalker(walker1);
+
+        final GenomeAnalysisEngine testEngine2 = new GenomeAnalysisEngine();
+        testEngine2.setWalker(walker2);
+
+        final VCFHeaderLine line1 = GATKVCFUtils.getCommandLineArgumentHeaderLine(testEngine1, Collections.EMPTY_LIST);
+        logger.warn(line1);
+        Assert.assertNotNull(line1);
+        Assert.assertEquals(line1.getKey(), GATKVCFUtils.GATK_COMMAND_LINE_KEY);
+        for ( final String field : Arrays.asList("Version", "ID", "Date", "CommandLineOptions"))
+            Assert.assertTrue(line1.toString().contains(field), "Couldn't find field " + field + " in " + line1.getValue());
+        Assert.assertTrue(line1.toString().contains("ID=" + testEngine1.getWalkerName()));
+
+        final VCFHeaderLine line2 = GATKVCFUtils.getCommandLineArgumentHeaderLine(testEngine2, Collections.EMPTY_LIST);
+        logger.warn(line2);
+
+        header.addMetaDataLine(line1);
+        final Set<VCFHeaderLine> lines1 = header.getMetaDataInInputOrder();
+        Assert.assertTrue(lines1.contains(line1));
+
+        header.addMetaDataLine(line2);
+        final Set<VCFHeaderLine> lines2 = header.getMetaDataInInputOrder();
+        Assert.assertTrue(lines2.contains(line1));
+        Assert.assertTrue(lines2.contains(line2));
+    }
+
+    private class IndexCreatorTest extends TestDataProvider {
+        private final GATKVCFIndexType type;
+        private final int parameter;
+        private final Class expectedClass;
+        private final Integer expectedDimension;
+        private final Method dimensionGetter;
+
+        private IndexCreatorTest(GATKVCFIndexType type, int parameter, Class expectedClass, Integer expectedDimension,
+                                 String dimensionGetterName) {
+            super(IndexCreatorTest.class);
+
+            this.type = type;
+            this.parameter = parameter;
+            this.expectedClass = expectedClass;
+            this.expectedDimension = expectedDimension;
+            try {
+                // Conditional matches testGetIndexCreator's if-statement
+                this.dimensionGetter = this.expectedDimension == null ? null : expectedClass.getDeclaredMethod(dimensionGetterName);
+            } catch (NoSuchMethodException e) {
+                throw new RuntimeException(e);
+            }
+        }
+    }
+
+    @DataProvider(name = "indexCreator")
+    public Object[][] indexCreatorData() {
+        new IndexCreatorTest(GATKVCFIndexType.DYNAMIC_SEEK, 0, DynamicIndexCreator.class, null, null);
+        new IndexCreatorTest(GATKVCFIndexType.DYNAMIC_SIZE, 0, DynamicIndexCreator.class, null, null);
+        new IndexCreatorTest(GATKVCFIndexType.LINEAR, 100, LinearIndexCreator.class, 100, "getBinSize");
+        new IndexCreatorTest(GATKVCFIndexType.INTERVAL, 200, IntervalIndexCreator.class, 200, "getFeaturesPerInterval");
+
+        return IndexCreatorTest.getTests(IndexCreatorTest.class);
+    }
+
+    @Test(dataProvider = "indexCreator")
+    public void testGetIndexCreator(IndexCreatorTest spec) throws Exception{
+        File dummy = new File("");
+        IndexCreator ic = GATKVCFUtils.getIndexCreator(spec.type, spec.parameter, dummy);
+        Assert.assertEquals(ic.getClass(), spec.expectedClass, "Wrong IndexCreator type");
+        if (spec.expectedDimension != null) {
+            Integer dimension = (int)spec.dimensionGetter.invoke(ic);
+            Assert.assertEquals(dimension, spec.expectedDimension, "Wrong dimension");
+        }
+    }
+}
\ No newline at end of file
diff --git a/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/utils/variant/GATKVariantContextUtilsUnitTest.java b/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/utils/variant/GATKVariantContextUtilsUnitTest.java
new file mode 100644
index 0000000..feb10a7
--- /dev/null
+++ b/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/utils/variant/GATKVariantContextUtilsUnitTest.java
@@ -0,0 +1,1612 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.utils.variant;
+
+import htsjdk.variant.variantcontext.*;
+import org.broadinstitute.gatk.engine.GenomeAnalysisEngine;
+import org.broadinstitute.gatk.utils.*;
+import org.broadinstitute.gatk.utils.collections.Pair;
+import org.broadinstitute.gatk.utils.fasta.CachingIndexedFastaSequenceFile;
+import org.testng.Assert;
+import org.testng.annotations.BeforeSuite;
+import org.testng.annotations.DataProvider;
+import org.testng.annotations.Test;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.*;
+
+public class GATKVariantContextUtilsUnitTest extends BaseTest {
+    private final static boolean DEBUG = false;
+
+    Allele Aref, T, C, G, Cref, ATC, ATCATC;
+    Allele ATCATCT;
+    Allele ATref;
+    Allele Anoref;
+    Allele GT;
+
+    private GenomeLocParser genomeLocParser;
+
+    @BeforeSuite
+    public void setup() throws IOException {
+        // alleles
+        Aref = Allele.create("A", true);
+        Cref = Allele.create("C", true);
+        T = Allele.create("T");
+        C = Allele.create("C");
+        G = Allele.create("G");
+        ATC = Allele.create("ATC");
+        ATCATC = Allele.create("ATCATC");
+        ATCATCT = Allele.create("ATCATCT");
+        ATref = Allele.create("AT",true);
+        Anoref = Allele.create("A",false);
+        GT = Allele.create("GT",false);
+        genomeLocParser = new GenomeLocParser(new CachingIndexedFastaSequenceFile(new File(hg18Reference)));
+    }
+
+    private Genotype makeG(String sample, Allele a1, Allele a2, double log10pError, int... pls) {
+        return new GenotypeBuilder(sample, Arrays.asList(a1, a2)).log10PError(log10pError).PL(pls).make();
+    }
+
+
+    private Genotype makeG(String sample, Allele a1, Allele a2, double log10pError) {
+        return new GenotypeBuilder(sample, Arrays.asList(a1, a2)).log10PError(log10pError).make();
+    }
+
+    private VariantContext makeVC(String source, List<Allele> alleles) {
+        return makeVC(source, alleles, null, null);
+    }
+
+    private VariantContext makeVC(String source, List<Allele> alleles, Genotype... g1) {
+        return makeVC(source, alleles, Arrays.asList(g1));
+    }
+
+    private VariantContext makeVC(String source, List<Allele> alleles, String filter) {
+        return makeVC(source, alleles, filter.equals(".") ? null : new HashSet<String>(Arrays.asList(filter)));
+    }
+
+    private VariantContext makeVC(String source, List<Allele> alleles, Set<String> filters) {
+        return makeVC(source, alleles, null, filters);
+    }
+
+    private VariantContext makeVC(String source, List<Allele> alleles, Collection<Genotype> genotypes) {
+        return makeVC(source, alleles, genotypes, null);
+    }
+
+    private VariantContext makeVC(String source, List<Allele> alleles, Collection<Genotype> genotypes, Set<String> filters) {
+        int start = 10;
+        int stop = start + alleles.get(0).length() - 1; // alleles.contains(ATC) ? start + 3 : start;
+        return new VariantContextBuilder(source, "1", start, stop, alleles).genotypes(genotypes).filters(filters).make();
+    }
+
+    // --------------------------------------------------------------------------------
+    //
+    // Test allele merging
+    //
+    // --------------------------------------------------------------------------------
+
+    private class MergeAllelesTest extends TestDataProvider {
+        List<List<Allele>> inputs;
+        List<Allele> expected;
+
+        private MergeAllelesTest(List<Allele>... arg) {
+            super(MergeAllelesTest.class);
+            LinkedList<List<Allele>> all = new LinkedList<>(Arrays.asList(arg));
+            expected = all.pollLast();
+            inputs = all;
+        }
+
+        public String toString() {
+            return String.format("MergeAllelesTest input=%s expected=%s", inputs, expected);
+        }
+    }
+    @DataProvider(name = "mergeAlleles")
+    public Object[][] mergeAllelesData() {
+        // first, do no harm
+        new MergeAllelesTest(Arrays.asList(Aref),
+                Arrays.asList(Aref));
+
+        new MergeAllelesTest(Arrays.asList(Aref),
+                Arrays.asList(Aref),
+                Arrays.asList(Aref));
+
+        new MergeAllelesTest(Arrays.asList(Aref),
+                Arrays.asList(Aref, T),
+                Arrays.asList(Aref, T));
+
+        new MergeAllelesTest(Arrays.asList(Aref, C),
+                Arrays.asList(Aref, T),
+                Arrays.asList(Aref, C, T));
+
+        new MergeAllelesTest(Arrays.asList(Aref, T),
+                Arrays.asList(Aref, C),
+                Arrays.asList(Aref, T, C)); // in order of appearence
+
+        new MergeAllelesTest(Arrays.asList(Aref, C, T),
+                Arrays.asList(Aref, C),
+                Arrays.asList(Aref, C, T));
+
+        new MergeAllelesTest(Arrays.asList(Aref, C, T), Arrays.asList(Aref, C, T));
+
+        new MergeAllelesTest(Arrays.asList(Aref, T, C), Arrays.asList(Aref, T, C));
+
+        new MergeAllelesTest(Arrays.asList(Aref, T, C),
+                Arrays.asList(Aref, C),
+                Arrays.asList(Aref, T, C)); // in order of appearence
+
+        new MergeAllelesTest(Arrays.asList(Aref),
+                Arrays.asList(Aref, ATC),
+                Arrays.asList(Aref, ATC));
+
+        new MergeAllelesTest(Arrays.asList(Aref),
+                Arrays.asList(Aref, ATC, ATCATC),
+                Arrays.asList(Aref, ATC, ATCATC));
+
+        // alleles in the order we see them
+        new MergeAllelesTest(Arrays.asList(Aref, ATCATC),
+                Arrays.asList(Aref, ATC, ATCATC),
+                Arrays.asList(Aref, ATCATC, ATC));
+
+        // same
+        new MergeAllelesTest(Arrays.asList(Aref, ATC),
+                Arrays.asList(Aref, ATCATC),
+                Arrays.asList(Aref, ATC, ATCATC));
+
+        new MergeAllelesTest(Arrays.asList(ATref, ATC, Anoref, G),
+                Arrays.asList(Aref, ATCATC, G),
+                Arrays.asList(ATref, ATC, Anoref, G, ATCATCT, GT));
+
+        return MergeAllelesTest.getTests(MergeAllelesTest.class);
+    }
+
+    @Test(enabled = !DEBUG, dataProvider = "mergeAlleles")
+    public void testMergeAlleles(MergeAllelesTest cfg) {
+        final List<VariantContext> inputs = new ArrayList<VariantContext>();
+
+        int i = 0;
+        for ( final List<Allele> alleles : cfg.inputs ) {
+            final String name = "vcf" + ++i;
+            inputs.add(makeVC(name, alleles));
+        }
+
+        final List<String> priority = vcs2priority(inputs);
+
+        final VariantContext merged = GATKVariantContextUtils.simpleMerge(
+                inputs, priority,
+                GATKVariantContextUtils.FilteredRecordMergeType.KEEP_IF_ANY_UNFILTERED,
+                GATKVariantContextUtils.GenotypeMergeType.PRIORITIZE, false, false, "set", false, false);
+
+        Assert.assertEquals(merged.getAlleles().size(),cfg.expected.size());
+        Assert.assertEquals(merged.getAlleles(), cfg.expected);
+    }
+
+    // --------------------------------------------------------------------------------
+    //
+    // Test rsID merging
+    //
+    // --------------------------------------------------------------------------------
+
+    private class SimpleMergeRSIDTest extends TestDataProvider {
+        List<String> inputs;
+        String expected;
+
+        private SimpleMergeRSIDTest(String... arg) {
+            super(SimpleMergeRSIDTest.class);
+            LinkedList<String> allStrings = new LinkedList<String>(Arrays.asList(arg));
+            expected = allStrings.pollLast();
+            inputs = allStrings;
+        }
+
+        public String toString() {
+            return String.format("SimpleMergeRSIDTest vc=%s expected=%s", inputs, expected);
+        }
+    }
+
+    @DataProvider(name = "simplemergersiddata")
+    public Object[][] createSimpleMergeRSIDData() {
+        new SimpleMergeRSIDTest(".", ".");
+        new SimpleMergeRSIDTest(".", ".", ".");
+        new SimpleMergeRSIDTest("rs1", "rs1");
+        new SimpleMergeRSIDTest("rs1", "rs1", "rs1");
+        new SimpleMergeRSIDTest(".", "rs1", "rs1");
+        new SimpleMergeRSIDTest("rs1", ".", "rs1");
+        new SimpleMergeRSIDTest("rs1", "rs2", "rs1,rs2");
+        new SimpleMergeRSIDTest("rs1", "rs2", "rs1", "rs1,rs2"); // duplicates
+        new SimpleMergeRSIDTest("rs2", "rs1", "rs2,rs1");
+        new SimpleMergeRSIDTest("rs2", "rs1", ".", "rs2,rs1");
+        new SimpleMergeRSIDTest("rs2", ".", "rs1", "rs2,rs1");
+        new SimpleMergeRSIDTest("rs1", ".", ".", "rs1");
+        new SimpleMergeRSIDTest("rs1", "rs2", "rs3", "rs1,rs2,rs3");
+
+        return SimpleMergeRSIDTest.getTests(SimpleMergeRSIDTest.class);
+    }
+
+    @Test(enabled = !DEBUG, dataProvider = "simplemergersiddata")
+    public void testRSIDMerge(SimpleMergeRSIDTest cfg) {
+        VariantContext snpVC1 = makeVC("snpvc1", Arrays.asList(Aref, T));
+        final List<VariantContext> inputs = new ArrayList<VariantContext>();
+
+        for ( final String id : cfg.inputs ) {
+            inputs.add(new VariantContextBuilder(snpVC1).id(id).make());
+        }
+
+        final VariantContext merged = GATKVariantContextUtils.simpleMerge(
+                inputs, null,
+                GATKVariantContextUtils.FilteredRecordMergeType.KEEP_IF_ANY_UNFILTERED,
+                GATKVariantContextUtils.GenotypeMergeType.UNSORTED, false, false, "set", false, false);
+        Assert.assertEquals(merged.getID(), cfg.expected);
+    }
+
+    // --------------------------------------------------------------------------------
+    //
+    // Test filtered merging
+    //
+    // --------------------------------------------------------------------------------
+
+    private class MergeFilteredTest extends TestDataProvider {
+        List<VariantContext> inputs;
+        VariantContext expected;
+        String setExpected;
+        GATKVariantContextUtils.FilteredRecordMergeType type;
+
+
+        private MergeFilteredTest(String name, VariantContext input1, VariantContext input2, VariantContext expected, String setExpected) {
+            this(name, input1, input2, expected, GATKVariantContextUtils.FilteredRecordMergeType.KEEP_IF_ANY_UNFILTERED, setExpected);
+        }
+
+        private MergeFilteredTest(String name, VariantContext input1, VariantContext input2, VariantContext expected, GATKVariantContextUtils.FilteredRecordMergeType type, String setExpected) {
+            super(MergeFilteredTest.class, name);
+            LinkedList<VariantContext> all = new LinkedList<VariantContext>(Arrays.asList(input1, input2));
+            this.expected = expected;
+            this.type = type;
+            inputs = all;
+            this.setExpected = setExpected;
+        }
+
+        public String toString() {
+            return String.format("%s input=%s expected=%s", super.toString(), inputs, expected);
+        }
+    }
+
+    @DataProvider(name = "mergeFiltered")
+    public Object[][] mergeFilteredData() {
+        new MergeFilteredTest("AllPass",
+                makeVC("1", Arrays.asList(Aref, T), VariantContext.PASSES_FILTERS),
+                makeVC("2", Arrays.asList(Aref, T), VariantContext.PASSES_FILTERS),
+                makeVC("3", Arrays.asList(Aref, T), VariantContext.PASSES_FILTERS),
+                GATKVariantContextUtils.MERGE_INTERSECTION);
+
+        new MergeFilteredTest("noFilters",
+                makeVC("1", Arrays.asList(Aref, T), "."),
+                makeVC("2", Arrays.asList(Aref, T), "."),
+                makeVC("3", Arrays.asList(Aref, T), "."),
+                GATKVariantContextUtils.MERGE_INTERSECTION);
+
+        new MergeFilteredTest("oneFiltered",
+                makeVC("1", Arrays.asList(Aref, T), "."),
+                makeVC("2", Arrays.asList(Aref, T), "FAIL"),
+                makeVC("3", Arrays.asList(Aref, T), "."),
+                String.format("1-%s2", GATKVariantContextUtils.MERGE_FILTER_PREFIX));
+
+        new MergeFilteredTest("onePassOneFail",
+                makeVC("1", Arrays.asList(Aref, T), VariantContext.PASSES_FILTERS),
+                makeVC("2", Arrays.asList(Aref, T), "FAIL"),
+                makeVC("3", Arrays.asList(Aref, T), VariantContext.PASSES_FILTERS),
+                String.format("1-%s2", GATKVariantContextUtils.MERGE_FILTER_PREFIX));
+
+        new MergeFilteredTest("AllFiltered",
+                makeVC("1", Arrays.asList(Aref, T), "FAIL"),
+                makeVC("2", Arrays.asList(Aref, T), "FAIL"),
+                makeVC("3", Arrays.asList(Aref, T), "FAIL"),
+                GATKVariantContextUtils.MERGE_FILTER_IN_ALL);
+
+        // test ALL vs. ANY
+        new MergeFilteredTest("FailOneUnfiltered",
+                makeVC("1", Arrays.asList(Aref, T), "FAIL"),
+                makeVC("2", Arrays.asList(Aref, T), "."),
+                makeVC("3", Arrays.asList(Aref, T), "."),
+                GATKVariantContextUtils.FilteredRecordMergeType.KEEP_IF_ANY_UNFILTERED,
+                String.format("%s1-2", GATKVariantContextUtils.MERGE_FILTER_PREFIX));
+
+        new MergeFilteredTest("OneFailAllUnfilteredArg",
+                makeVC("1", Arrays.asList(Aref, T), "FAIL"),
+                makeVC("2", Arrays.asList(Aref, T), "."),
+                makeVC("3", Arrays.asList(Aref, T), "FAIL"),
+                GATKVariantContextUtils.FilteredRecordMergeType.KEEP_IF_ALL_UNFILTERED,
+                String.format("%s1-2", GATKVariantContextUtils.MERGE_FILTER_PREFIX));
+
+        // test excluding allele in filtered record
+        new MergeFilteredTest("DontIncludeAlleleOfFilteredRecords",
+                makeVC("1", Arrays.asList(Aref, T), "."),
+                makeVC("2", Arrays.asList(Aref, T), "FAIL"),
+                makeVC("3", Arrays.asList(Aref, T), "."),
+                String.format("1-%s2", GATKVariantContextUtils.MERGE_FILTER_PREFIX));
+
+        // promotion of site from unfiltered to PASSES
+        new MergeFilteredTest("UnfilteredPlusPassIsPass",
+                makeVC("1", Arrays.asList(Aref, T), "."),
+                makeVC("2", Arrays.asList(Aref, T), VariantContext.PASSES_FILTERS),
+                makeVC("3", Arrays.asList(Aref, T), VariantContext.PASSES_FILTERS),
+                GATKVariantContextUtils.MERGE_INTERSECTION);
+
+        new MergeFilteredTest("RefInAll",
+                makeVC("1", Arrays.asList(Aref), VariantContext.PASSES_FILTERS),
+                makeVC("2", Arrays.asList(Aref), VariantContext.PASSES_FILTERS),
+                makeVC("3", Arrays.asList(Aref), VariantContext.PASSES_FILTERS),
+                GATKVariantContextUtils.MERGE_REF_IN_ALL);
+
+        new MergeFilteredTest("RefInOne",
+                makeVC("1", Arrays.asList(Aref), VariantContext.PASSES_FILTERS),
+                makeVC("2", Arrays.asList(Aref, T), VariantContext.PASSES_FILTERS),
+                makeVC("3", Arrays.asList(Aref, T), VariantContext.PASSES_FILTERS),
+                "2");
+
+        return MergeFilteredTest.getTests(MergeFilteredTest.class);
+    }
+
+    @Test(enabled = !DEBUG, dataProvider = "mergeFiltered")
+    public void testMergeFiltered(MergeFilteredTest cfg) {
+        final List<String> priority = vcs2priority(cfg.inputs);
+        final VariantContext merged = GATKVariantContextUtils.simpleMerge(
+                cfg.inputs, priority, cfg.type, GATKVariantContextUtils.GenotypeMergeType.PRIORITIZE, true, false, "set", false, false);
+
+        // test alleles are equal
+        Assert.assertEquals(merged.getAlleles(), cfg.expected.getAlleles());
+
+        // test set field
+        Assert.assertEquals(merged.getAttribute("set"), cfg.setExpected);
+
+        // test filter field
+        Assert.assertEquals(merged.getFilters(), cfg.expected.getFilters());
+    }
+
+    // --------------------------------------------------------------------------------
+    //
+    // Test genotype merging
+    //
+    // --------------------------------------------------------------------------------
+
+    private class MergeGenotypesTest extends TestDataProvider {
+        List<VariantContext> inputs;
+        VariantContext expected;
+        List<String> priority;
+
+        private MergeGenotypesTest(String name, String priority, VariantContext... arg) {
+            super(MergeGenotypesTest.class, name);
+            LinkedList<VariantContext> all = new LinkedList<VariantContext>(Arrays.asList(arg));
+            this.expected = all.pollLast();
+            inputs = all;
+            this.priority = Arrays.asList(priority.split(","));
+        }
+
+        public String toString() {
+            return String.format("%s input=%s expected=%s", super.toString(), inputs, expected);
+        }
+    }
+
+    @DataProvider(name = "mergeGenotypes")
+    public Object[][] mergeGenotypesData() {
+        new MergeGenotypesTest("TakeGenotypeByPriority-1,2", "1,2",
+                makeVC("1", Arrays.asList(Aref, T), makeG("s1", Aref, T, -1)),
+                makeVC("2", Arrays.asList(Aref, T), makeG("s1", Aref, T, -2)),
+                makeVC("3", Arrays.asList(Aref, T), makeG("s1", Aref, T, -1)));
+
+        new MergeGenotypesTest("TakeGenotypeByPriority-1,2-nocall", "1,2",
+                makeVC("1", Arrays.asList(Aref, T), makeG("s1", Allele.NO_CALL, Allele.NO_CALL, -1)),
+                makeVC("2", Arrays.asList(Aref, T), makeG("s1", Aref, T, -2)),
+                makeVC("3", Arrays.asList(Aref, T), makeG("s1", Allele.NO_CALL, Allele.NO_CALL, -1)));
+
+        new MergeGenotypesTest("TakeGenotypeByPriority-2,1", "2,1",
+                makeVC("1", Arrays.asList(Aref, T), makeG("s1", Aref, T, -1)),
+                makeVC("2", Arrays.asList(Aref, T), makeG("s1", Aref, T, -2)),
+                makeVC("3", Arrays.asList(Aref, T), makeG("s1", Aref, T, -2)));
+
+        new MergeGenotypesTest("NonOverlappingGenotypes", "1,2",
+                makeVC("1", Arrays.asList(Aref, T), makeG("s1", Aref, T, -1)),
+                makeVC("2", Arrays.asList(Aref, T), makeG("s2", Aref, T, -2)),
+                makeVC("3", Arrays.asList(Aref, T), makeG("s1", Aref, T, -1), makeG("s2", Aref, T, -2)));
+
+        new MergeGenotypesTest("PreserveNoCall", "1,2",
+                makeVC("1", Arrays.asList(Aref, T), makeG("s1", Allele.NO_CALL, Allele.NO_CALL, -1)),
+                makeVC("2", Arrays.asList(Aref, T), makeG("s2", Aref, T, -2)),
+                makeVC("3", Arrays.asList(Aref, T), makeG("s1", Allele.NO_CALL, Allele.NO_CALL, -1), makeG("s2", Aref, T, -2)));
+
+        new MergeGenotypesTest("PerserveAlleles", "1,2",
+                makeVC("1", Arrays.asList(Aref, T), makeG("s1", Aref, T, -1)),
+                makeVC("2", Arrays.asList(Aref, C), makeG("s2", Aref, C, -2)),
+                makeVC("3", Arrays.asList(Aref, T, C), makeG("s1", Aref, T, -1), makeG("s2", Aref, C, -2)));
+
+        new MergeGenotypesTest("TakeGenotypePartialOverlap-1,2", "1,2",
+                makeVC("1", Arrays.asList(Aref, T), makeG("s1", Aref, T, -1)),
+                makeVC("2", Arrays.asList(Aref, T), makeG("s1", Aref, T, -2), makeG("s3", Aref, T, -3)),
+                makeVC("3", Arrays.asList(Aref, T), makeG("s1", Aref, T, -1), makeG("s3", Aref, T, -3)));
+
+        new MergeGenotypesTest("TakeGenotypePartialOverlap-2,1", "2,1",
+                makeVC("1", Arrays.asList(Aref, T), makeG("s1", Aref, T, -1)),
+                makeVC("2", Arrays.asList(Aref, T), makeG("s1", Aref, T, -2), makeG("s3", Aref, T, -3)),
+                makeVC("3", Arrays.asList(Aref, T), makeG("s1", Aref, T, -2), makeG("s3", Aref, T, -3)));
+
+        //
+        // merging genothpes with PLs
+        //
+
+        // first, do no harm
+        new MergeGenotypesTest("OrderedPLs", "1",
+                makeVC("1", Arrays.asList(Aref, T), makeG("s1", Aref, T, -1, 1, 2, 3)),
+                makeVC("1", Arrays.asList(Aref, T), makeG("s1", Aref, T, -1, 1, 2, 3)));
+
+        // first, do no harm
+        new MergeGenotypesTest("OrderedPLs-3Alleles", "1",
+                makeVC("1", Arrays.asList(Aref, C, T), makeG("s1", Aref, T, -1, 1, 2, 3, 4, 5, 6)),
+                makeVC("1", Arrays.asList(Aref, C, T), makeG("s1", Aref, T, -1, 1, 2, 3, 4, 5, 6)));
+
+        // first, do no harm
+        new MergeGenotypesTest("OrderedPLs-3Alleles-2", "1",
+                makeVC("1", Arrays.asList(Aref, T, C), makeG("s1", Aref, T, -1, 1, 2, 3, 4, 5, 6)),
+                makeVC("1", Arrays.asList(Aref, T, C), makeG("s1", Aref, T, -1, 1, 2, 3, 4, 5, 6)));
+
+        // first, do no harm
+        new MergeGenotypesTest("OrderedPLs-3Alleles-2", "1",
+                makeVC("1", Arrays.asList(Aref, T, C), makeG("s1", Aref, T, -1, 1, 2, 3, 4, 5, 6)),
+                makeVC("1", Arrays.asList(Aref, T, C), makeG("s2", Aref, C, -1, 1, 2, 3, 4, 5, 6)),
+                makeVC("1", Arrays.asList(Aref, T, C), makeG("s1", Aref, T, -1, 1, 2, 3, 4, 5, 6), makeG("s2", Aref, C, -1, 1, 2, 3, 4, 5, 6)));
+
+        new MergeGenotypesTest("TakeGenotypePartialOverlapWithPLs-2,1", "2,1",
+                makeVC("1", Arrays.asList(Aref, T), makeG("s1", Aref, T, -1,5,0,3)),
+                makeVC("2", Arrays.asList(Aref, T), makeG("s1", Aref, T, -2,4,0,2), makeG("s3", Aref, T, -3,3,0,2)),
+                makeVC("3", Arrays.asList(Aref, T), makeG("s1", Aref, T, -2,4,0,2), makeG("s3", Aref, T, -3,3,0,2)));
+
+        new MergeGenotypesTest("TakeGenotypePartialOverlapWithPLs-1,2", "1,2",
+                makeVC("1", Arrays.asList(Aref,ATC), makeG("s1", Aref, ATC, -1,5,0,3)),
+                makeVC("2", Arrays.asList(Aref, T), makeG("s1", Aref, T, -2,4,0,2), makeG("s3", Aref, T, -3,3,0,2)),
+                // no likelihoods on result since type changes to mixed multiallelic
+                makeVC("3", Arrays.asList(Aref, ATC, T), makeG("s1", Aref, ATC, -1), makeG("s3", Aref, T, -3)));
+
+        new MergeGenotypesTest("MultipleSamplePLsDifferentOrder", "1,2",
+                makeVC("1", Arrays.asList(Aref, C, T), makeG("s1", Aref, C, -1, 1, 2, 3, 4, 5, 6)),
+                makeVC("2", Arrays.asList(Aref, T, C), makeG("s2", Aref, T, -2, 6, 5, 4, 3, 2, 1)),
+                // no likelihoods on result since type changes to mixed multiallelic
+                makeVC("3", Arrays.asList(Aref, C, T), makeG("s1", Aref, C, -1), makeG("s2", Aref, T, -2)));
+
+        return MergeGenotypesTest.getTests(MergeGenotypesTest.class);
+    }
+
+    @Test(enabled = !DEBUG, dataProvider = "mergeGenotypes")
+    public void testMergeGenotypes(MergeGenotypesTest cfg) {
+        final VariantContext merged = GATKVariantContextUtils.simpleMerge(
+                cfg.inputs, cfg.priority, GATKVariantContextUtils.FilteredRecordMergeType.KEEP_IF_ANY_UNFILTERED,
+                GATKVariantContextUtils.GenotypeMergeType.PRIORITIZE, true, false, "set", false, false);
+
+        // test alleles are equal
+        Assert.assertEquals(merged.getAlleles(), cfg.expected.getAlleles());
+
+        // test genotypes
+        assertGenotypesAreMostlyEqual(merged.getGenotypes(), cfg.expected.getGenotypes());
+    }
+
+    // necessary to not overload equals for genotypes
+    private void assertGenotypesAreMostlyEqual(GenotypesContext actual, GenotypesContext expected) {
+        if (actual == expected) {
+            return;
+        }
+
+        if (actual == null || expected == null) {
+            Assert.fail("Maps not equal: expected: " + expected + " and actual: " + actual);
+        }
+
+        if (actual.size() != expected.size()) {
+            Assert.fail("Maps do not have the same size:" + actual.size() + " != " + expected.size());
+        }
+
+        for (Genotype value : actual) {
+            Genotype expectedValue = expected.get(value.getSampleName());
+
+            Assert.assertEquals(value.getAlleles(), expectedValue.getAlleles(), "Alleles in Genotype aren't equal");
+            Assert.assertEquals(value.getGQ(), expectedValue.getGQ(), "GQ values aren't equal");
+            Assert.assertEquals(value.hasLikelihoods(), expectedValue.hasLikelihoods(), "Either both have likelihoods or both not");
+            if ( value.hasLikelihoods() )
+                Assert.assertEquals(value.getLikelihoods().getAsVector(), expectedValue.getLikelihoods().getAsVector(), "Genotype likelihoods aren't equal");
+        }
+    }
+
+    @Test(enabled = !DEBUG)
+    public void testMergeGenotypesUniquify() {
+        final VariantContext vc1 = makeVC("1", Arrays.asList(Aref, T), makeG("s1", Aref, T, -1));
+        final VariantContext vc2 = makeVC("2", Arrays.asList(Aref, T), makeG("s1", Aref, T, -2));
+
+        final VariantContext merged = GATKVariantContextUtils.simpleMerge(
+                Arrays.asList(vc1, vc2), null, GATKVariantContextUtils.FilteredRecordMergeType.KEEP_IF_ANY_UNFILTERED,
+                GATKVariantContextUtils.GenotypeMergeType.UNIQUIFY, false, false, "set", false, false);
+
+        // test genotypes
+        Assert.assertEquals(merged.getSampleNames(), new HashSet<>(Arrays.asList("s1.1", "s1.2")));
+    }
+
+// TODO: remove after testing
+//    @Test(expectedExceptions = IllegalStateException.class)
+//    public void testMergeGenotypesRequireUnique() {
+//        final VariantContext vc1 = makeVC("1", Arrays.asList(Aref, T), makeG("s1", Aref, T, -1));
+//        final VariantContext vc2 = makeVC("2", Arrays.asList(Aref, T), makeG("s1", Aref, T, -2));
+//
+//        final VariantContext merged = VariantContextUtils.simpleMerge(
+//                Arrays.asList(vc1, vc2), null, VariantContextUtils.FilteredRecordMergeType.KEEP_IF_ANY_UNFILTERED,
+//                VariantContextUtils.GenotypeMergeType.REQUIRE_UNIQUE, false, false, "set", false, false, false);
+//    }
+
+    // --------------------------------------------------------------------------------
+    //
+    // Misc. tests
+    //
+    // --------------------------------------------------------------------------------
+
+    @Test(enabled = !DEBUG)
+    public void testAnnotationSet() {
+        for ( final boolean annotate : Arrays.asList(true, false)) {
+            for ( final String set : Arrays.asList("set", "combine", "x")) {
+                final List<String> priority = Arrays.asList("1", "2");
+                VariantContext vc1 = makeVC("1", Arrays.asList(Aref, T), VariantContext.PASSES_FILTERS);
+                VariantContext vc2 = makeVC("2", Arrays.asList(Aref, T), VariantContext.PASSES_FILTERS);
+
+                final VariantContext merged = GATKVariantContextUtils.simpleMerge(
+                        Arrays.asList(vc1, vc2), priority, GATKVariantContextUtils.FilteredRecordMergeType.KEEP_IF_ANY_UNFILTERED,
+                        GATKVariantContextUtils.GenotypeMergeType.PRIORITIZE, annotate, false, set, false, false);
+
+                if ( annotate )
+                    Assert.assertEquals(merged.getAttribute(set), GATKVariantContextUtils.MERGE_INTERSECTION);
+                else
+                    Assert.assertFalse(merged.hasAttribute(set));
+            }
+        }
+    }
+
+    private static final List<String> vcs2priority(final Collection<VariantContext> vcs) {
+        final List<String> priority = new ArrayList<>();
+
+        for ( final VariantContext vc : vcs ) {
+            priority.add(vc.getSource());
+        }
+
+        return priority;
+    }
+
+    // --------------------------------------------------------------------------------
+    //
+    // basic allele clipping test
+    //
+    // --------------------------------------------------------------------------------
+
+    private class ReverseClippingPositionTestProvider extends TestDataProvider {
+        final String ref;
+        final List<Allele> alleles = new ArrayList<Allele>();
+        final int expectedClip;
+
+        private ReverseClippingPositionTestProvider(final int expectedClip, final String ref, final String... alleles) {
+            super(ReverseClippingPositionTestProvider.class);
+            this.ref = ref;
+            for ( final String allele : alleles )
+                this.alleles.add(Allele.create(allele));
+            this.expectedClip = expectedClip;
+        }
+
+        @Override
+        public String toString() {
+            return String.format("ref=%s allele=%s reverse clip %d", ref, alleles, expectedClip);
+        }
+    }
+
+    @DataProvider(name = "ReverseClippingPositionTestProvider")
+    public Object[][] makeReverseClippingPositionTestProvider() {
+        // pair clipping
+        new ReverseClippingPositionTestProvider(0, "ATT", "CCG");
+        new ReverseClippingPositionTestProvider(1, "ATT", "CCT");
+        new ReverseClippingPositionTestProvider(2, "ATT", "CTT");
+        new ReverseClippingPositionTestProvider(2, "ATT", "ATT");  // cannot completely clip allele
+
+        // triplets
+        new ReverseClippingPositionTestProvider(0, "ATT", "CTT", "CGG");
+        new ReverseClippingPositionTestProvider(1, "ATT", "CTT", "CGT"); // the T can go
+        new ReverseClippingPositionTestProvider(2, "ATT", "CTT", "CTT"); // both Ts can go
+
+        return ReverseClippingPositionTestProvider.getTests(ReverseClippingPositionTestProvider.class);
+    }
+
+    @Test(enabled = !DEBUG, dataProvider = "ReverseClippingPositionTestProvider")
+    public void testReverseClippingPositionTestProvider(ReverseClippingPositionTestProvider cfg) {
+        int result = GATKVariantContextUtils.computeReverseClipping(cfg.alleles, cfg.ref.getBytes());
+        Assert.assertEquals(result, cfg.expectedClip);
+    }
+
+
+    // --------------------------------------------------------------------------------
+    //
+    // test splitting into bi-allelics
+    //
+    // --------------------------------------------------------------------------------
+
+    @DataProvider(name = "SplitBiallelics")
+    public Object[][] makeSplitBiallelics() throws CloneNotSupportedException {
+        List<Object[]> tests = new ArrayList<Object[]>();
+
+        final VariantContextBuilder root = new VariantContextBuilder("x", "20", 10, 10, Arrays.asList(Aref, C));
+
+        // biallelic -> biallelic
+        tests.add(new Object[]{root.make(), Arrays.asList(root.make())});
+
+        // monos -> monos
+        root.alleles(Arrays.asList(Aref));
+        tests.add(new Object[]{root.make(), Arrays.asList(root.make())});
+
+        root.alleles(Arrays.asList(Aref, C, T));
+        tests.add(new Object[]{root.make(),
+                Arrays.asList(
+                        root.alleles(Arrays.asList(Aref, C)).make(),
+                        root.alleles(Arrays.asList(Aref, T)).make())});
+
+        root.alleles(Arrays.asList(Aref, C, T, G));
+        tests.add(new Object[]{root.make(),
+                Arrays.asList(
+                        root.alleles(Arrays.asList(Aref, C)).make(),
+                        root.alleles(Arrays.asList(Aref, T)).make(),
+                        root.alleles(Arrays.asList(Aref, G)).make())});
+
+        final Allele C      = Allele.create("C");
+        final Allele CA      = Allele.create("CA");
+        final Allele CAA     = Allele.create("CAA");
+        final Allele CAAAA   = Allele.create("CAAAA");
+        final Allele CAAAAA  = Allele.create("CAAAAA");
+        final Allele Cref      = Allele.create("C", true);
+        final Allele CAref     = Allele.create("CA", true);
+        final Allele CAAref    = Allele.create("CAA", true);
+        final Allele CAAAref   = Allele.create("CAAA", true);
+
+        root.alleles(Arrays.asList(Cref, CA, CAA));
+        tests.add(new Object[]{root.make(),
+                Arrays.asList(
+                        root.alleles(Arrays.asList(Cref, CA)).make(),
+                        root.alleles(Arrays.asList(Cref, CAA)).make())});
+
+        root.alleles(Arrays.asList(CAAref, C, CA)).stop(12);
+        tests.add(new Object[]{root.make(),
+                Arrays.asList(
+                        root.alleles(Arrays.asList(CAAref, C)).make(),
+                        root.alleles(Arrays.asList(CAref, C)).stop(11).make())});
+
+        root.alleles(Arrays.asList(CAAAref, C, CA, CAA)).stop(13);
+        tests.add(new Object[]{root.make(),
+                Arrays.asList(
+                        root.alleles(Arrays.asList(CAAAref, C)).make(),
+                        root.alleles(Arrays.asList(CAAref, C)).stop(12).make(),
+                        root.alleles(Arrays.asList(CAref, C)).stop(11).make())});
+
+        root.alleles(Arrays.asList(CAAAref, CAAAAA, CAAAA, CAA, C)).stop(13);
+        tests.add(new Object[]{root.make(),
+                Arrays.asList(
+                        root.alleles(Arrays.asList(Cref, CAA)).stop(10).make(),
+                        root.alleles(Arrays.asList(Cref, CA)).stop(10).make(),
+                        root.alleles(Arrays.asList(CAref, C)).stop(11).make(),
+                        root.alleles(Arrays.asList(CAAAref, C)).stop(13).make())});
+
+        final Allele threeCopies = Allele.create("GTTTTATTTTATTTTA", true);
+        final Allele twoCopies = Allele.create("GTTTTATTTTA", true);
+        final Allele zeroCopies = Allele.create("G", false);
+        final Allele oneCopies = Allele.create("GTTTTA", false);
+        tests.add(new Object[]{root.alleles(Arrays.asList(threeCopies, zeroCopies, oneCopies)).stop(25).make(),
+                Arrays.asList(
+                        root.alleles(Arrays.asList(threeCopies, zeroCopies)).stop(25).make(),
+                        root.alleles(Arrays.asList(twoCopies, zeroCopies)).stop(20).make())});
+
+        return tests.toArray(new Object[][]{});
+    }
+
+    @Test(enabled = !DEBUG, dataProvider = "SplitBiallelics")
+    public void testSplitBiallelicsNoGenotypes(final VariantContext vc, final List<VariantContext> expectedBiallelics) {
+        final List<VariantContext> biallelics = GATKVariantContextUtils.splitVariantContextToBiallelics(vc);
+        Assert.assertEquals(biallelics.size(), expectedBiallelics.size());
+        for ( int i = 0; i < biallelics.size(); i++ ) {
+            final VariantContext actual = biallelics.get(i);
+            final VariantContext expected = expectedBiallelics.get(i);
+            assertVariantContextsAreEqual(actual, expected);
+        }
+    }
+
+    @Test(enabled = !DEBUG, dataProvider = "SplitBiallelics", dependsOnMethods = "testSplitBiallelicsNoGenotypes")
+    public void testSplitBiallelicsGenotypes(final VariantContext vc, final List<VariantContext> expectedBiallelics) {
+        final List<Genotype> genotypes = new ArrayList<Genotype>();
+
+        int sampleI = 0;
+        for ( final List<Allele> alleles : Utils.makePermutations(vc.getAlleles(), 2, true) ) {
+            genotypes.add(GenotypeBuilder.create("sample" + sampleI++, alleles));
+        }
+        genotypes.add(GenotypeBuilder.createMissing("missing", 2));
+
+        final VariantContext vcWithGenotypes = new VariantContextBuilder(vc).genotypes(genotypes).make();
+
+        final List<VariantContext> biallelics = GATKVariantContextUtils.splitVariantContextToBiallelics(vcWithGenotypes);
+        for ( int i = 0; i < biallelics.size(); i++ ) {
+            final VariantContext actual = biallelics.get(i);
+            Assert.assertEquals(actual.getNSamples(), vcWithGenotypes.getNSamples()); // not dropping any samples
+
+            for ( final Genotype inputGenotype : genotypes ) {
+                final Genotype actualGenotype = actual.getGenotype(inputGenotype.getSampleName());
+                Assert.assertNotNull(actualGenotype);
+                if ( ! vc.isVariant() || vc.isBiallelic() )
+                    Assert.assertEquals(actualGenotype, vcWithGenotypes.getGenotype(inputGenotype.getSampleName()));
+                else
+                    Assert.assertTrue(actualGenotype.isNoCall());
+            }
+        }
+    }
+
+    // --------------------------------------------------------------------------------
+    //
+    // Test repeats
+    //
+    // --------------------------------------------------------------------------------
+
+    private class RepeatDetectorTest extends TestDataProvider {
+        String ref;
+        boolean isTrueRepeat;
+        VariantContext vc;
+
+        private RepeatDetectorTest(boolean isTrueRepeat, String ref, String refAlleleString, String ... altAlleleStrings) {
+            super(RepeatDetectorTest.class);
+            this.isTrueRepeat = isTrueRepeat;
+            this.ref = ref;
+
+            List<Allele> alleles = new LinkedList<Allele>();
+            final Allele refAllele = Allele.create(refAlleleString, true);
+            alleles.add(refAllele);
+            for ( final String altString: altAlleleStrings) {
+                final Allele alt = Allele.create(altString, false);
+                alleles.add(alt);
+            }
+
+            VariantContextBuilder builder = new VariantContextBuilder("test", "chr1", 1, refAllele.length(), alleles);
+            this.vc = builder.make();
+        }
+
+        public String toString() {
+            return String.format("%s refBases=%s trueRepeat=%b vc=%s", super.toString(), ref, isTrueRepeat, vc);
+        }
+    }
+
+    @DataProvider(name = "RepeatDetectorTest")
+    public Object[][] makeRepeatDetectorTest() {
+        new RepeatDetectorTest(true,  "NAAC", "N", "NA");
+        new RepeatDetectorTest(true,  "NAAC", "NA", "N");
+        new RepeatDetectorTest(false, "NAAC", "NAA", "N");
+        new RepeatDetectorTest(false, "NAAC", "N", "NC");
+        new RepeatDetectorTest(false, "AAC", "A", "C");
+
+        // running out of ref bases => false
+        new RepeatDetectorTest(false, "NAAC", "N", "NCAGTA");
+
+        // complex repeats
+        new RepeatDetectorTest(true,  "NATATATC", "N", "NAT");
+        new RepeatDetectorTest(true,  "NATATATC", "N", "NATA");
+        new RepeatDetectorTest(true,  "NATATATC", "N", "NATAT");
+        new RepeatDetectorTest(true,  "NATATATC", "NAT", "N");
+        new RepeatDetectorTest(false, "NATATATC", "NATA", "N");
+        new RepeatDetectorTest(false, "NATATATC", "NATAT", "N");
+
+        // multi-allelic
+        new RepeatDetectorTest(true,  "NATATATC", "N", "NAT", "NATAT");
+        new RepeatDetectorTest(true,  "NATATATC", "N", "NAT", "NATA");
+        new RepeatDetectorTest(true,  "NATATATC", "NAT", "N", "NATAT");
+        new RepeatDetectorTest(true,  "NATATATC", "NAT", "N", "NATA"); // two As
+        new RepeatDetectorTest(false, "NATATATC", "NAT", "N", "NATC"); // false
+        new RepeatDetectorTest(false, "NATATATC", "NAT", "N", "NCC"); // false
+        new RepeatDetectorTest(false, "NATATATC", "NAT", "NATAT", "NCC"); // false
+
+        return RepeatDetectorTest.getTests(RepeatDetectorTest.class);
+    }
+
+    @Test(enabled = !DEBUG, dataProvider = "RepeatDetectorTest")
+    public void testRepeatDetectorTest(RepeatDetectorTest cfg) {
+
+        // test alleles are equal
+        Assert.assertEquals(GATKVariantContextUtils.isTandemRepeat(cfg.vc, cfg.ref.getBytes()), cfg.isTrueRepeat);
+    }
+
+    @Test(enabled = !DEBUG)
+    public void testRepeatAllele() {
+        Allele nullR = Allele.create("A", true);
+        Allele nullA = Allele.create("A", false);
+        Allele atc   = Allele.create("AATC", false);
+        Allele atcatc   = Allele.create("AATCATC", false);
+        Allele ccccR = Allele.create("ACCCC", true);
+        Allele cc   = Allele.create("ACC", false);
+        Allele cccccc   = Allele.create("ACCCCCC", false);
+        Allele gagaR   = Allele.create("AGAGA", true);
+        Allele gagagaga   = Allele.create("AGAGAGAGA", false);
+
+        // - / ATC [ref] from 20-22
+        String delLoc = "chr1";
+        int delLocStart = 20;
+        int delLocStop = 22;
+
+        // - [ref] / ATC from 20-20
+        String insLoc = "chr1";
+        int insLocStart = 20;
+        int insLocStop = 20;
+
+        Pair<List<Integer>,byte[]> result;
+        byte[] refBytes = "TATCATCATCGGA".getBytes();
+
+        Assert.assertEquals(GATKVariantContextUtils.findNumberOfRepetitions("ATG".getBytes(), "ATGATGATGATG".getBytes(), true),4);
+        Assert.assertEquals(GATKVariantContextUtils.findNumberOfRepetitions("G".getBytes(), "ATGATGATGATG".getBytes(), true),0);
+        Assert.assertEquals(GATKVariantContextUtils.findNumberOfRepetitions("T".getBytes(), "T".getBytes(), true),1);
+        Assert.assertEquals(GATKVariantContextUtils.findNumberOfRepetitions("AT".getBytes(), "ATGATGATCATG".getBytes(), true),1);
+        Assert.assertEquals(GATKVariantContextUtils.findNumberOfRepetitions("CCC".getBytes(), "CCCCCCCC".getBytes(), true),2);
+
+        Assert.assertEquals(GATKVariantContextUtils.findRepeatedSubstring("ATG".getBytes()),3);
+        Assert.assertEquals(GATKVariantContextUtils.findRepeatedSubstring("AAA".getBytes()),1);
+        Assert.assertEquals(GATKVariantContextUtils.findRepeatedSubstring("CACACAC".getBytes()),7);
+        Assert.assertEquals(GATKVariantContextUtils.findRepeatedSubstring("CACACA".getBytes()),2);
+        Assert.assertEquals(GATKVariantContextUtils.findRepeatedSubstring("CATGCATG".getBytes()),4);
+        Assert.assertEquals(GATKVariantContextUtils.findRepeatedSubstring("AATAATA".getBytes()),7);
+
+
+        // A*,ATC, context = ATC ATC ATC : (ATC)3 -> (ATC)4
+        VariantContext vc = new VariantContextBuilder("foo", insLoc, insLocStart, insLocStop, Arrays.asList(nullR,atc)).make();
+        result = GATKVariantContextUtils.getNumTandemRepeatUnits(vc, refBytes);
+        Assert.assertEquals(result.getFirst().toArray()[0],3);
+        Assert.assertEquals(result.getFirst().toArray()[1],4);
+        Assert.assertEquals(result.getSecond().length,3);
+
+        // ATC*,A,ATCATC
+        vc = new VariantContextBuilder("foo", insLoc, insLocStart, insLocStart+3, Arrays.asList(Allele.create("AATC", true),nullA,atcatc)).make();
+        result = GATKVariantContextUtils.getNumTandemRepeatUnits(vc, refBytes);
+        Assert.assertEquals(result.getFirst().toArray()[0],3);
+        Assert.assertEquals(result.getFirst().toArray()[1],2);
+        Assert.assertEquals(result.getFirst().toArray()[2],4);
+        Assert.assertEquals(result.getSecond().length,3);
+
+        // simple non-tandem deletion: CCCC*, -
+        refBytes = "TCCCCCCCCATG".getBytes();
+        vc = new VariantContextBuilder("foo", delLoc, 10, 14, Arrays.asList(ccccR,nullA)).make();
+        result = GATKVariantContextUtils.getNumTandemRepeatUnits(vc, refBytes);
+        Assert.assertEquals(result.getFirst().toArray()[0],8);
+        Assert.assertEquals(result.getFirst().toArray()[1],4);
+        Assert.assertEquals(result.getSecond().length,1);
+
+        // CCCC*,CC,-,CCCCCC, context = CCC: (C)7 -> (C)5,(C)3,(C)9
+        refBytes = "TCCCCCCCAGAGAGAG".getBytes();
+        vc = new VariantContextBuilder("foo", insLoc, insLocStart, insLocStart+4, Arrays.asList(ccccR,cc, nullA,cccccc)).make();
+        result = GATKVariantContextUtils.getNumTandemRepeatUnits(vc, refBytes);
+        Assert.assertEquals(result.getFirst().toArray()[0],7);
+        Assert.assertEquals(result.getFirst().toArray()[1],5);
+        Assert.assertEquals(result.getFirst().toArray()[2],3);
+        Assert.assertEquals(result.getFirst().toArray()[3],9);
+        Assert.assertEquals(result.getSecond().length,1);
+
+        // GAGA*,-,GAGAGAGA
+        refBytes = "TGAGAGAGAGATTT".getBytes();
+        vc = new VariantContextBuilder("foo", insLoc, insLocStart, insLocStart+4, Arrays.asList(gagaR, nullA,gagagaga)).make();
+        result = GATKVariantContextUtils.getNumTandemRepeatUnits(vc, refBytes);
+        Assert.assertEquals(result.getFirst().toArray()[0],5);
+        Assert.assertEquals(result.getFirst().toArray()[1],3);
+        Assert.assertEquals(result.getFirst().toArray()[2],7);
+        Assert.assertEquals(result.getSecond().length,2);
+
+    }
+
+    // --------------------------------------------------------------------------------
+    //
+    // test forward clipping
+    //
+    // --------------------------------------------------------------------------------
+
+    @DataProvider(name = "ForwardClippingData")
+    public Object[][] makeForwardClippingData() {
+        List<Object[]> tests = new ArrayList<Object[]>();
+
+        // this functionality can be adapted to provide input data for whatever you might want in your data
+        tests.add(new Object[]{Arrays.asList("A"), -1});
+        tests.add(new Object[]{Arrays.asList("<DEL>"), -1});
+        tests.add(new Object[]{Arrays.asList("A", "C"), -1});
+        tests.add(new Object[]{Arrays.asList("AC", "C"), -1});
+        tests.add(new Object[]{Arrays.asList("A", "G"), -1});
+        tests.add(new Object[]{Arrays.asList("A", "T"), -1});
+        tests.add(new Object[]{Arrays.asList("GT", "CA"), -1});
+        tests.add(new Object[]{Arrays.asList("GT", "CT"), -1});
+        tests.add(new Object[]{Arrays.asList("ACC", "AC"), 0});
+        tests.add(new Object[]{Arrays.asList("ACGC", "ACG"), 1});
+        tests.add(new Object[]{Arrays.asList("ACGC", "ACG"), 1});
+        tests.add(new Object[]{Arrays.asList("ACGC", "ACGA"), 2});
+        tests.add(new Object[]{Arrays.asList("ACGC", "AGC"), 0});
+        tests.add(new Object[]{Arrays.asList("A", "<DEL>"), -1});
+        for ( int len = 0; len < 50; len++ )
+            tests.add(new Object[]{Arrays.asList("A" + new String(Utils.dupBytes((byte)'C', len)), "C"), -1});
+
+        tests.add(new Object[]{Arrays.asList("A", "T", "C"), -1});
+        tests.add(new Object[]{Arrays.asList("AT", "AC", "AG"), 0});
+        tests.add(new Object[]{Arrays.asList("AT", "AC", "A"), -1});
+        tests.add(new Object[]{Arrays.asList("AT", "AC", "ACG"), 0});
+        tests.add(new Object[]{Arrays.asList("AC", "AC", "ACG"), 0});
+        tests.add(new Object[]{Arrays.asList("AC", "ACT", "ACG"), 0});
+        tests.add(new Object[]{Arrays.asList("ACG", "ACGT", "ACGTA"), 1});
+        tests.add(new Object[]{Arrays.asList("ACG", "ACGT", "ACGCA"), 1});
+
+        return tests.toArray(new Object[][]{});
+    }
+
+    @Test(enabled = !DEBUG, dataProvider = "ForwardClippingData")
+    public void testForwardClipping(final List<String> alleleStrings, final int expectedClip) {
+        final List<Allele> alleles = new LinkedList<Allele>();
+        for ( final String alleleString : alleleStrings )
+            alleles.add(Allele.create(alleleString));
+
+        for ( final List<Allele> myAlleles : Utils.makePermutations(alleles, alleles.size(), false)) {
+            final int actual = GATKVariantContextUtils.computeForwardClipping(myAlleles);
+            Assert.assertEquals(actual, expectedClip);
+        }
+    }
+
+    @DataProvider(name = "ClipAlleleTest")
+    public Object[][] makeClipAlleleTest() {
+        List<Object[]> tests = new ArrayList<Object[]>();
+
+        // this functionality can be adapted to provide input data for whatever you might want in your data
+        tests.add(new Object[]{Arrays.asList("ACC", "AC"), Arrays.asList("AC", "A"), 0});
+        tests.add(new Object[]{Arrays.asList("ACGC", "ACG"), Arrays.asList("GC", "G"), 2});
+        tests.add(new Object[]{Arrays.asList("ACGC", "ACGA"), Arrays.asList("C", "A"), 3});
+        tests.add(new Object[]{Arrays.asList("ACGC", "AGC"), Arrays.asList("AC", "A"), 0});
+        tests.add(new Object[]{Arrays.asList("AT", "AC", "AG"), Arrays.asList("T", "C", "G"), 1});
+        tests.add(new Object[]{Arrays.asList("AT", "AC", "ACG"), Arrays.asList("T", "C", "CG"), 1});
+        tests.add(new Object[]{Arrays.asList("AC", "ACT", "ACG"), Arrays.asList("C", "CT", "CG"), 1});
+        tests.add(new Object[]{Arrays.asList("ACG", "ACGT", "ACGTA"), Arrays.asList("G", "GT", "GTA"), 2});
+        tests.add(new Object[]{Arrays.asList("ACG", "ACGT", "ACGCA"), Arrays.asList("G", "GT", "GCA"), 2});
+
+        // trims from left and right
+        tests.add(new Object[]{Arrays.asList("ACGTT", "ACCTT"), Arrays.asList("G", "C"), 2});
+        tests.add(new Object[]{Arrays.asList("ACGTT", "ACCCTT"), Arrays.asList("G", "CC"), 2});
+        tests.add(new Object[]{Arrays.asList("ACGTT", "ACGCTT"), Arrays.asList("G", "GC"), 2});
+
+        return tests.toArray(new Object[][]{});
+    }
+
+    @Test(enabled = !DEBUG, dataProvider = "ClipAlleleTest")
+    public void testClipAlleles(final List<String> alleleStrings, final List<String> expected, final int numLeftClipped) {
+        final int start = 10;
+        final VariantContext unclipped = GATKVariantContextUtils.makeFromAlleles("test", "20", start, alleleStrings);
+        final VariantContext clipped = GATKVariantContextUtils.trimAlleles(unclipped, true, true);
+
+        Assert.assertEquals(clipped.getStart(), unclipped.getStart() + numLeftClipped);
+        for ( int i = 0; i < unclipped.getAlleles().size(); i++ ) {
+            final Allele trimmed = clipped.getAlleles().get(i);
+            Assert.assertEquals(trimmed.getBaseString(), expected.get(i));
+        }
+    }
+
+    // --------------------------------------------------------------------------------
+    //
+    // test primitive allele splitting
+    //
+    // --------------------------------------------------------------------------------
+
+    @DataProvider(name = "PrimitiveAlleleSplittingData")
+    public Object[][] makePrimitiveAlleleSplittingData() {
+        List<Object[]> tests = new ArrayList<>();
+
+        // no split
+        tests.add(new Object[]{"A", "C", 0, null});
+        tests.add(new Object[]{"A", "AC", 0, null});
+        tests.add(new Object[]{"AC", "A", 0, null});
+
+        // one split
+        tests.add(new Object[]{"ACA", "GCA", 1, Arrays.asList(0)});
+        tests.add(new Object[]{"ACA", "AGA", 1, Arrays.asList(1)});
+        tests.add(new Object[]{"ACA", "ACG", 1, Arrays.asList(2)});
+
+        // two splits
+        tests.add(new Object[]{"ACA", "GGA", 2, Arrays.asList(0, 1)});
+        tests.add(new Object[]{"ACA", "GCG", 2, Arrays.asList(0, 2)});
+        tests.add(new Object[]{"ACA", "AGG", 2, Arrays.asList(1, 2)});
+
+        // three splits
+        tests.add(new Object[]{"ACA", "GGG", 3, Arrays.asList(0, 1, 2)});
+
+        return tests.toArray(new Object[][]{});
+    }
+
+    @Test(enabled = !DEBUG, dataProvider = "PrimitiveAlleleSplittingData")
+    public void testPrimitiveAlleleSplitting(final String ref, final String alt, final int expectedSplit, final List<Integer> variantPositions) {
+
+        final int start = 10;
+        final VariantContext vc = GATKVariantContextUtils.makeFromAlleles("test", "20", start, Arrays.asList(ref, alt));
+
+        final List<VariantContext> result = GATKVariantContextUtils.splitIntoPrimitiveAlleles(vc);
+
+        if ( expectedSplit > 0 ) {
+            Assert.assertEquals(result.size(), expectedSplit);
+            for ( int i = 0; i < variantPositions.size(); i++ ) {
+                Assert.assertEquals(result.get(i).getStart(), start + variantPositions.get(i));
+            }
+        } else {
+            Assert.assertEquals(result.size(), 1);
+            Assert.assertEquals(vc, result.get(0));
+        }
+    }
+
+    // --------------------------------------------------------------------------------
+    //
+    // test allele remapping
+    //
+    // --------------------------------------------------------------------------------
+
+    @DataProvider(name = "AlleleRemappingData")
+    public Object[][] makeAlleleRemappingData() {
+        List<Object[]> tests = new ArrayList<>();
+
+        final Allele originalBase1 = Allele.create((byte)'A');
+        final Allele originalBase2 = Allele.create((byte)'T');
+
+        for ( final byte base1 : BaseUtils.BASES ) {
+            for ( final byte base2 : BaseUtils.BASES ) {
+                for ( final int numGenotypes : Arrays.asList(0, 1, 2, 5) ) {
+                    Map<Allele, Allele> map = new HashMap<>(2);
+                    map.put(originalBase1, Allele.create(base1));
+                    map.put(originalBase2, Allele.create(base2));
+
+                    tests.add(new Object[]{map, numGenotypes});
+                }
+            }
+        }
+
+        return tests.toArray(new Object[][]{});
+    }
+
+    @Test(enabled = !DEBUG, dataProvider = "AlleleRemappingData")
+    public void testAlleleRemapping(final Map<Allele, Allele> alleleMap, final int numGenotypes) {
+
+        final GATKVariantContextUtils.AlleleMapper alleleMapper = new GATKVariantContextUtils.AlleleMapper(alleleMap);
+
+        final GenotypesContext originalGC = createGenotypesContext(numGenotypes, new ArrayList(alleleMap.keySet()));
+
+        final GenotypesContext remappedGC = GATKVariantContextUtils.updateGenotypesWithMappedAlleles(originalGC, alleleMapper);
+
+        for ( int i = 0; i < numGenotypes; i++ ) {
+            final Genotype originalG = originalGC.get(String.format("%d", i));
+            final Genotype remappedG = remappedGC.get(String.format("%d", i));
+
+            Assert.assertEquals(originalG.getAlleles().size(), remappedG.getAlleles().size());
+            for ( int j = 0; j < originalG.getAlleles().size(); j++ )
+                Assert.assertEquals(remappedG.getAllele(j), alleleMap.get(originalG.getAllele(j)));
+        }
+    }
+
+    private static GenotypesContext createGenotypesContext(final int numGenotypes, final List<Allele> alleles) {
+        GenomeAnalysisEngine.resetRandomGenerator();
+        final Random random = GenomeAnalysisEngine.getRandomGenerator();
+
+        final GenotypesContext gc = GenotypesContext.create();
+        for ( int i = 0; i < numGenotypes; i++ ) {
+            // choose alleles at random
+            final List<Allele> myAlleles = new ArrayList<Allele>();
+            myAlleles.add(alleles.get(random.nextInt(2)));
+            myAlleles.add(alleles.get(random.nextInt(2)));
+
+            final Genotype g = new GenotypeBuilder(String.format("%d", i)).alleles(myAlleles).make();
+            gc.add(g);
+        }
+
+        return gc;
+    }
+
+    // --------------------------------------------------------------------------------
+    //
+    // Test subsetDiploidAlleles
+    //
+    // --------------------------------------------------------------------------------
+
+    @DataProvider(name = "subsetDiploidAllelesData")
+    public Object[][] makesubsetDiploidAllelesData() {
+        List<Object[]> tests = new ArrayList<>();
+
+        final Allele A = Allele.create("A", true);
+        final Allele C = Allele.create("C");
+        final Allele G = Allele.create("G");
+
+        final List<Allele> AA = Arrays.asList(A,A);
+        final List<Allele> AC = Arrays.asList(A,C);
+        final List<Allele> CC = Arrays.asList(C,C);
+        final List<Allele> AG = Arrays.asList(A,G);
+        final List<Allele> CG = Arrays.asList(C,G);
+        final List<Allele> GG = Arrays.asList(G,G);
+        final List<Allele> ACG = Arrays.asList(A,C,G);
+
+        final VariantContext vcBase = new VariantContextBuilder("test", "20", 10, 10, AC).make();
+
+        final double[] homRefPL = MathUtils.normalizeFromRealSpace(new double[]{0.9, 0.09, 0.01});
+        final double[] hetPL = MathUtils.normalizeFromRealSpace(new double[]{0.09, 0.9, 0.01});
+        final double[] homVarPL = MathUtils.normalizeFromRealSpace(new double[]{0.01, 0.09, 0.9});
+        final double[] uninformative = new double[]{0, 0, 0};
+
+        final Genotype base = new GenotypeBuilder("NA12878").DP(10).GQ(50).make();
+
+        // make sure we don't screw up the simple case
+        final Genotype aaGT = new GenotypeBuilder(base).alleles(AA).AD(new int[]{10,2}).PL(homRefPL).GQ(8).make();
+        final Genotype acGT = new GenotypeBuilder(base).alleles(AC).AD(new int[]{10,2}).PL(hetPL).GQ(8).make();
+        final Genotype ccGT = new GenotypeBuilder(base).alleles(CC).AD(new int[]{10,2}).PL(homVarPL).GQ(8).make();
+
+        tests.add(new Object[]{new VariantContextBuilder(vcBase).genotypes(aaGT).make(), AC, Arrays.asList(new GenotypeBuilder(aaGT).make())});
+        tests.add(new Object[]{new VariantContextBuilder(vcBase).genotypes(acGT).make(), AC, Arrays.asList(new GenotypeBuilder(acGT).make())});
+        tests.add(new Object[]{new VariantContextBuilder(vcBase).genotypes(ccGT).make(), AC, Arrays.asList(new GenotypeBuilder(ccGT).make())});
+
+        // uninformative test case
+        final Genotype uninformativeGT = new GenotypeBuilder(base).alleles(CC).PL(uninformative).GQ(0).make();
+        final Genotype emptyGT = new GenotypeBuilder(base).alleles(GATKVariantContextUtils.NO_CALL_ALLELES).noPL().noGQ().make();
+        tests.add(new Object[]{new VariantContextBuilder(vcBase).genotypes(uninformativeGT).make(), AC, Arrays.asList(emptyGT)});
+
+        // actually subsetting down from multiple alt values
+        final double[] homRef3AllelesPL = new double[]{0, -10, -20, -30, -40, -50};
+        final double[] hetRefC3AllelesPL = new double[]{-10, 0, -20, -30, -40, -50};
+        final double[] homC3AllelesPL = new double[]{-20, -10, 0, -30, -40, -50};
+        final double[] hetRefG3AllelesPL = new double[]{-20, -10, -30, 0, -40, -50};
+        final double[] hetCG3AllelesPL = new double[]{-20, -10, -30, -40, 0, -50}; // AA, AC, CC, AG, CG, GG
+        final double[] homG3AllelesPL = new double[]{-20, -10, -30, -40, -50, 0};  // AA, AC, CC, AG, CG, GG
+        tests.add(new Object[]{
+                new VariantContextBuilder(vcBase).alleles(ACG).genotypes(new GenotypeBuilder(base).alleles(AA).PL(homRef3AllelesPL).make()).make(),
+                AC,
+                Arrays.asList(new GenotypeBuilder(base).alleles(AA).PL(new double[]{0, -10, -20}).GQ(100).make())});
+
+        tests.add(new Object[]{
+                new VariantContextBuilder(vcBase).alleles(ACG).genotypes(new GenotypeBuilder(base).alleles(AA).PL(hetRefC3AllelesPL).make()).make(),
+                AC,
+                Arrays.asList(new GenotypeBuilder(base).alleles(AC).PL(new double[]{-10, 0, -20}).GQ(100).make())});
+
+        tests.add(new Object[]{
+                new VariantContextBuilder(vcBase).alleles(ACG).genotypes(new GenotypeBuilder(base).alleles(AA).PL(homC3AllelesPL).make()).make(),
+                AC,
+                Arrays.asList(new GenotypeBuilder(base).alleles(CC).PL(new double[]{-20, -10, 0}).GQ(100).make())});
+        tests.add(new Object[]{
+                new VariantContextBuilder(vcBase).alleles(ACG).genotypes(new GenotypeBuilder(base).alleles(AA).PL(hetRefG3AllelesPL).make()).make(),
+                AG,
+                Arrays.asList(new GenotypeBuilder(base).alleles(AG).PL(new double[]{-20, 0, -50}).GQ(200).make())});
+
+        // wow, scary -- bad output but discussed with Eric and we think this is the only thing that can be done
+        tests.add(new Object[]{
+                new VariantContextBuilder(vcBase).alleles(ACG).genotypes(new GenotypeBuilder(base).alleles(AA).PL(hetCG3AllelesPL).make()).make(),
+                AG,
+                Arrays.asList(new GenotypeBuilder(base).alleles(AA).PL(new double[]{0, -20, -30}).GQ(200).make())});
+
+        tests.add(new Object[]{
+                new VariantContextBuilder(vcBase).alleles(ACG).genotypes(new GenotypeBuilder(base).alleles(AA).PL(homG3AllelesPL).make()).make(),
+                AG,
+                Arrays.asList(new GenotypeBuilder(base).alleles(GG).PL(new double[]{-20, -40, 0}).GQ(200).make())});
+
+        return tests.toArray(new Object[][]{});
+    }
+
+    @Test(dataProvider = "subsetDiploidAllelesData")
+    public void testsubsetDiploidAllelesData(final VariantContext inputVC,
+                                             final List<Allele> allelesToUse,
+                                             final List<Genotype> expectedGenotypes) {
+        final GenotypesContext actual = GATKVariantContextUtils.subsetDiploidAlleles(inputVC, allelesToUse, GATKVariantContextUtils.GenotypeAssignmentMethod.USE_PLS_TO_ASSIGN);
+
+        Assert.assertEquals(actual.size(), expectedGenotypes.size());
+        for ( final Genotype expected : expectedGenotypes ) {
+            final Genotype actualGT = actual.get(expected.getSampleName());
+            Assert.assertNotNull(actualGT);
+            assertGenotypesAreEqual(actualGT, expected);
+        }
+    }
+
+    @DataProvider(name = "UpdateGenotypeAfterSubsettingData")
+    public Object[][] makeUpdateGenotypeAfterSubsettingData() {
+        List<Object[]> tests = new ArrayList<Object[]>();
+
+        final Allele A = Allele.create("A", true);
+        final Allele C = Allele.create("C");
+        final Allele G = Allele.create("G");
+
+        final List<Allele> AA = Arrays.asList(A,A);
+        final List<Allele> AC = Arrays.asList(A,C);
+        final List<Allele> CC = Arrays.asList(C,C);
+        final List<Allele> AG = Arrays.asList(A,G);
+        final List<Allele> CG = Arrays.asList(C,G);
+        final List<Allele> GG = Arrays.asList(G,G);
+        final List<Allele> ACG = Arrays.asList(A,C,G);
+        final List<List<Allele>> allSubsetAlleles = Arrays.asList(AC,AG,ACG);
+
+        final double[] homRefPL = new double[]{0.9, 0.09, 0.01};
+        final double[] hetPL = new double[]{0.09, 0.9, 0.01};
+        final double[] homVarPL = new double[]{0.01, 0.09, 0.9};
+        final double[] uninformative = new double[]{0.33, 0.33, 0.33};
+        final List<double[]> allPLs = Arrays.asList(homRefPL, hetPL, homVarPL, uninformative);
+
+        for ( final List<Allele> alleles : allSubsetAlleles ) {
+            for ( final double[] pls : allPLs ) {
+                tests.add(new Object[]{GATKVariantContextUtils.GenotypeAssignmentMethod.SET_TO_NO_CALL, pls, AA, alleles, GATKVariantContextUtils.NO_CALL_ALLELES});
+            }
+        }
+
+        for ( final List<Allele> originalGT : Arrays.asList(AA, AC, CC, AG, CG, GG) ) {
+            tests.add(new Object[]{GATKVariantContextUtils.GenotypeAssignmentMethod.USE_PLS_TO_ASSIGN, homRefPL, originalGT, AC, AA});
+            tests.add(new Object[]{GATKVariantContextUtils.GenotypeAssignmentMethod.USE_PLS_TO_ASSIGN, hetPL, originalGT, AC, AC});
+            tests.add(new Object[]{GATKVariantContextUtils.GenotypeAssignmentMethod.USE_PLS_TO_ASSIGN, homVarPL, originalGT, AC, CC});
+//        tests.add(new Object[]{GATKVariantContextUtils.GenotypeAssignmentMethod.USE_PLS_TO_ASSIGN, uninformative, AA, AC, GATKVariantContextUtils.NO_CALL_ALLELES});
+        }
+
+        for ( final double[] pls : allPLs ) {
+            tests.add(new Object[]{GATKVariantContextUtils.GenotypeAssignmentMethod.BEST_MATCH_TO_ORIGINAL, pls, AA, AC, AA});
+            tests.add(new Object[]{GATKVariantContextUtils.GenotypeAssignmentMethod.BEST_MATCH_TO_ORIGINAL, pls, AC, AC, AC});
+            tests.add(new Object[]{GATKVariantContextUtils.GenotypeAssignmentMethod.BEST_MATCH_TO_ORIGINAL, pls, CC, AC, CC});
+            tests.add(new Object[]{GATKVariantContextUtils.GenotypeAssignmentMethod.BEST_MATCH_TO_ORIGINAL, pls, CG, AC, AC});
+
+            tests.add(new Object[]{GATKVariantContextUtils.GenotypeAssignmentMethod.BEST_MATCH_TO_ORIGINAL, pls, AA, AG, AA});
+            tests.add(new Object[]{GATKVariantContextUtils.GenotypeAssignmentMethod.BEST_MATCH_TO_ORIGINAL, pls, AC, AG, AA});
+            tests.add(new Object[]{GATKVariantContextUtils.GenotypeAssignmentMethod.BEST_MATCH_TO_ORIGINAL, pls, CC, AG, AA});
+            tests.add(new Object[]{GATKVariantContextUtils.GenotypeAssignmentMethod.BEST_MATCH_TO_ORIGINAL, pls, CG, AG, AG});
+
+            tests.add(new Object[]{GATKVariantContextUtils.GenotypeAssignmentMethod.BEST_MATCH_TO_ORIGINAL, pls, AA, ACG, AA});
+            tests.add(new Object[]{GATKVariantContextUtils.GenotypeAssignmentMethod.BEST_MATCH_TO_ORIGINAL, pls, AC, ACG, AC});
+            tests.add(new Object[]{GATKVariantContextUtils.GenotypeAssignmentMethod.BEST_MATCH_TO_ORIGINAL, pls, CC, ACG, CC});
+            tests.add(new Object[]{GATKVariantContextUtils.GenotypeAssignmentMethod.BEST_MATCH_TO_ORIGINAL, pls, AG, ACG, AG});
+            tests.add(new Object[]{GATKVariantContextUtils.GenotypeAssignmentMethod.BEST_MATCH_TO_ORIGINAL, pls, CG, ACG, CG});
+            tests.add(new Object[]{GATKVariantContextUtils.GenotypeAssignmentMethod.BEST_MATCH_TO_ORIGINAL, pls, GG, ACG, GG});
+        }
+
+        return tests.toArray(new Object[][]{});
+    }
+
+    @Test(enabled = !DEBUG, dataProvider = "UpdateGenotypeAfterSubsettingData")
+    public void testUpdateGenotypeAfterSubsetting(final GATKVariantContextUtils.GenotypeAssignmentMethod mode,
+                                                  final double[] likelihoods,
+                                                  final List<Allele> originalGT,
+                                                  final List<Allele> allelesToUse,
+                                                  final List<Allele> expectedAlleles) {
+        final GenotypeBuilder gb = new GenotypeBuilder("test");
+        final double[] log10Likelhoods = MathUtils.normalizeFromLog10(likelihoods, true, false);
+        GATKVariantContextUtils.updateGenotypeAfterSubsetting(originalGT, gb, mode, log10Likelhoods, allelesToUse);
+        final Genotype g = gb.make();
+        Assert.assertEquals(new HashSet<>(g.getAlleles()), new HashSet<>(expectedAlleles));
+    }
+
+    @Test(enabled = !DEBUG)
+    public void testSubsetToRef() {
+        final Map<Genotype, Genotype> tests = new LinkedHashMap<>();
+
+        for ( final List<Allele> alleles : Arrays.asList(Arrays.asList(Aref), Arrays.asList(C), Arrays.asList(Aref, C), Arrays.asList(Aref, C, C) ) ) {
+            for ( final String name : Arrays.asList("test1", "test2") ) {
+                final GenotypeBuilder builder = new GenotypeBuilder(name, alleles);
+                builder.DP(10);
+                builder.GQ(30);
+                builder.AD(alleles.size() == 1 ? new int[]{1} : (alleles.size() == 2 ? new int[]{1, 2} : new int[]{1, 2, 3}));
+                builder.PL(alleles.size() == 1 ? new int[]{1} : (alleles.size() == 2 ? new int[]{1,2} : new int[]{1,2,3}));
+                final List<Allele> refs = Collections.nCopies(alleles.size(), Aref);
+                tests.put(builder.make(), builder.alleles(refs).noAD().noPL().make());
+            }
+        }
+
+        for ( final int n : Arrays.asList(1, 2, 3) ) {
+            for ( final List<Genotype> genotypes : Utils.makePermutations(new ArrayList<>(tests.keySet()), n, false) ) {
+                final VariantContext vc = new VariantContextBuilder("test", "20", 1, 1, Arrays.asList(Aref, C)).genotypes(genotypes).make();
+                final GenotypesContext gc = GATKVariantContextUtils.subsetToRefOnly(vc, 2);
+
+                Assert.assertEquals(gc.size(), genotypes.size());
+                for ( int i = 0; i < genotypes.size(); i++ ) {
+//                    logger.warn("Testing " + genotypes.get(i) + " => " + gc.get(i) + " " + tests.get(genotypes.get(i)));
+                    assertGenotypesAreEqual(gc.get(i), tests.get(genotypes.get(i)));
+                }
+            }
+        }
+    }
+
+    // --------------------------------------------------------------------------------
+    //
+    // Test updatePLsAndAD
+    //
+    // --------------------------------------------------------------------------------
+
+    @DataProvider(name = "updatePLsAndADData")
+    public Object[][] makeUpdatePLsAndADData() {
+        List<Object[]> tests = new ArrayList<>();
+
+        final Allele A = Allele.create("A", true);
+        final Allele C = Allele.create("C");
+        final Allele G = Allele.create("G");
+
+        final List<Allele> AA = Arrays.asList(A,A);
+        final List<Allele> AC = Arrays.asList(A,C);
+        final List<Allele> CC = Arrays.asList(C,C);
+        final List<Allele> AG = Arrays.asList(A,G);
+        final List<Allele> CG = Arrays.asList(C,G);
+        final List<Allele> GG = Arrays.asList(G,G);
+        final List<Allele> ACG = Arrays.asList(A,C,G);
+
+        final VariantContext vcBase = new VariantContextBuilder("test", "20", 10, 10, AC).make();
+
+        final double[] homRefPL = MathUtils.normalizeFromRealSpace(new double[]{0.9, 0.09, 0.01});
+        final double[] hetPL = MathUtils.normalizeFromRealSpace(new double[]{0.09, 0.9, 0.01});
+        final double[] homVarPL = MathUtils.normalizeFromRealSpace(new double[]{0.01, 0.09, 0.9});
+        final double[] uninformative = new double[]{0, 0, 0};
+
+        final Genotype base = new GenotypeBuilder("NA12878").DP(10).GQ(100).make();
+
+        // make sure we don't screw up the simple case where no selection happens
+        final Genotype aaGT = new GenotypeBuilder(base).alleles(AA).AD(new int[]{10,2}).PL(homRefPL).GQ(8).make();
+        final Genotype acGT = new GenotypeBuilder(base).alleles(AC).AD(new int[]{10,2}).PL(hetPL).GQ(8).make();
+        final Genotype ccGT = new GenotypeBuilder(base).alleles(CC).AD(new int[]{10,2}).PL(homVarPL).GQ(8).make();
+
+        tests.add(new Object[]{new VariantContextBuilder(vcBase).genotypes(aaGT).make(), new VariantContextBuilder(vcBase).alleles(AC).make(), Arrays.asList(new GenotypeBuilder(aaGT).make())});
+        tests.add(new Object[]{new VariantContextBuilder(vcBase).genotypes(acGT).make(), new VariantContextBuilder(vcBase).alleles(AC).make(), Arrays.asList(new GenotypeBuilder(acGT).make())});
+        tests.add(new Object[]{new VariantContextBuilder(vcBase).genotypes(ccGT).make(), new VariantContextBuilder(vcBase).alleles(AC).make(), Arrays.asList(new GenotypeBuilder(ccGT).make())});
+
+        // uninformative test cases
+        final Genotype uninformativeGT = new GenotypeBuilder(base).alleles(CC).noAD().PL(uninformative).GQ(0).make();
+        tests.add(new Object[]{new VariantContextBuilder(vcBase).genotypes(uninformativeGT).make(), new VariantContextBuilder(vcBase).alleles(AC).make(), Arrays.asList(uninformativeGT)});
+        final Genotype emptyGT = new GenotypeBuilder(base).alleles(GATKVariantContextUtils.NO_CALL_ALLELES).noAD().noPL().noGQ().make();
+        tests.add(new Object[]{new VariantContextBuilder(vcBase).genotypes(emptyGT).make(), new VariantContextBuilder(vcBase).alleles(AC).make(), Arrays.asList(emptyGT)});
+
+        // actually subsetting down from multiple alt values
+        final double[] homRef3AllelesPL = new double[]{0, -10, -20, -30, -40, -50};
+        final double[] hetRefC3AllelesPL = new double[]{-10, 0, -20, -30, -40, -50};
+        final double[] homC3AllelesPL = new double[]{-20, -10, 0, -30, -40, -50};
+        final double[] hetRefG3AllelesPL = new double[]{-20, -10, -30, 0, -40, -50};
+        final double[] hetCG3AllelesPL = new double[]{-20, -10, -30, -40, 0, -50}; // AA, AC, CC, AG, CG, GG
+        final double[] homG3AllelesPL = new double[]{-20, -10, -30, -40, -50, 0};  // AA, AC, CC, AG, CG, GG
+
+        final int[] homRef3AllelesAD = new int[]{20, 0, 1};
+        final int[] hetRefC3AllelesAD = new int[]{10, 10, 1};
+        final int[] homC3AllelesAD = new int[]{0, 20, 1};
+        final int[] hetRefG3AllelesAD = new int[]{10, 0, 11};
+        final int[] hetCG3AllelesAD = new int[]{0, 12, 11}; // AA, AC, CC, AG, CG, GG
+        final int[] homG3AllelesAD = new int[]{0, 1, 21};  // AA, AC, CC, AG, CG, GG
+
+        tests.add(new Object[]{
+                new VariantContextBuilder(vcBase).alleles(ACG).genotypes(new GenotypeBuilder(base).alleles(AA).AD(homRef3AllelesAD).PL(homRef3AllelesPL).make()).make(),
+                new VariantContextBuilder(vcBase).alleles(AC).make(),
+                Arrays.asList(new GenotypeBuilder(base).alleles(AA).PL(new double[]{0, -10, -20}).AD(new int[]{20, 0}).GQ(100).make())});
+
+        tests.add(new Object[]{
+                new VariantContextBuilder(vcBase).alleles(ACG).genotypes(new GenotypeBuilder(base).alleles(AA).AD(hetRefC3AllelesAD).PL(hetRefC3AllelesPL).make()).make(),
+                new VariantContextBuilder(vcBase).alleles(AC).make(),
+                Arrays.asList(new GenotypeBuilder(base).alleles(AA).PL(new double[]{-10, 0, -20}).AD(new int[]{10, 10}).GQ(100).make())});
+
+        tests.add(new Object[]{
+                new VariantContextBuilder(vcBase).alleles(ACG).genotypes(new GenotypeBuilder(base).alleles(AA).AD(homC3AllelesAD).PL(homC3AllelesPL).make()).make(),
+                new VariantContextBuilder(vcBase).alleles(AC).make(),
+                Arrays.asList(new GenotypeBuilder(base).alleles(AA).PL(new double[]{-20, -10, 0}).AD(new int[]{0, 20}).GQ(100).make())});
+        tests.add(new Object[]{
+                new VariantContextBuilder(vcBase).alleles(ACG).genotypes(new GenotypeBuilder(base).alleles(AA).AD(hetRefG3AllelesAD).PL(hetRefG3AllelesPL).make()).make(),
+                new VariantContextBuilder(vcBase).alleles(AG).make(),
+                Arrays.asList(new GenotypeBuilder(base).alleles(AA).PL(new double[]{-20, 0, -50}).AD(new int[]{10, 11}).GQ(100).make())});
+
+        tests.add(new Object[]{
+                new VariantContextBuilder(vcBase).alleles(ACG).genotypes(new GenotypeBuilder(base).alleles(AA).AD(hetCG3AllelesAD).PL(hetCG3AllelesPL).make()).make(),
+                new VariantContextBuilder(vcBase).alleles(AG).make(),
+                Arrays.asList(new GenotypeBuilder(base).alleles(AA).PL(new double[]{0, -20, -30}).AD(new int[]{0, 11}).GQ(100).make())});
+
+        tests.add(new Object[]{
+                new VariantContextBuilder(vcBase).alleles(ACG).genotypes(new GenotypeBuilder(base).alleles(AA).AD(homG3AllelesAD).PL(homG3AllelesPL).make()).make(),
+                new VariantContextBuilder(vcBase).alleles(AG).make(),
+                Arrays.asList(new GenotypeBuilder(base).alleles(AA).PL(new double[]{-20, -40, 0}).AD(new int[]{0, 21}).GQ(100).make())});
+
+        return tests.toArray(new Object[][]{});
+    }
+
+    @Test(dataProvider = "updatePLsAndADData")
+    public void testUpdatePLsAndADData(final VariantContext originalVC,
+                                       final VariantContext selectedVC,
+                                       final List<Genotype> expectedGenotypes) {
+        final VariantContext selectedVCwithGTs = new VariantContextBuilder(selectedVC).genotypes(originalVC.getGenotypes()).make();
+        final GenotypesContext actual = GATKVariantContextUtils.updatePLsAndAD(selectedVCwithGTs, originalVC);
+
+        Assert.assertEquals(actual.size(), expectedGenotypes.size());
+        for ( final Genotype expected : expectedGenotypes ) {
+            final Genotype actualGT = actual.get(expected.getSampleName());
+            Assert.assertNotNull(actualGT);
+            assertGenotypesAreEqual(actualGT, expected);
+        }
+    }
+
+    // --------------------------------------------------------------------------------
+    //
+    // Test methods for merging reference confidence VCs
+    //
+    // --------------------------------------------------------------------------------
+
+
+    @Test(dataProvider = "indexOfAlleleData")
+    public void testIndexOfAllele(final Allele reference, final List<Allele> altAlleles, final List<Allele> otherAlleles) {
+        final List<Allele> alleles = new ArrayList<>(altAlleles.size() + 1);
+        alleles.add(reference);
+        alleles.addAll(altAlleles);
+        final VariantContext vc = makeVC("Source", alleles);
+
+        for (int i = 0; i < alleles.size(); i++) {
+            Assert.assertEquals(GATKVariantContextUtils.indexOfAllele(vc,alleles.get(i),true,true,true),i);
+            Assert.assertEquals(GATKVariantContextUtils.indexOfAllele(vc,alleles.get(i),false,true,true),i);
+            Assert.assertEquals(GATKVariantContextUtils.indexOfAllele(vc,alleles.get(i),true,true,false),i);
+            Assert.assertEquals(GATKVariantContextUtils.indexOfAllele(vc,alleles.get(i),false,true,false),i);
+            Assert.assertEquals(GATKVariantContextUtils.indexOfAllele(vc,Allele.create(alleles.get(i),true),true,true,true),i);
+            Assert.assertEquals(GATKVariantContextUtils.indexOfAllele(vc,Allele.create(alleles.get(i),true),true,true,false),-1);
+            if (i == 0) {
+                Assert.assertEquals(GATKVariantContextUtils.indexOfAllele(vc,alleles.get(i),true,false,true),-1);
+                Assert.assertEquals(GATKVariantContextUtils.indexOfAllele(vc,alleles.get(i),false,false,true),-1);
+                Assert.assertEquals(GATKVariantContextUtils.indexOfAllele(vc,alleles.get(i),true,false,false),-1);
+                Assert.assertEquals(GATKVariantContextUtils.indexOfAllele(vc,alleles.get(i),false,false,false),-1);
+                Assert.assertEquals(GATKVariantContextUtils.indexOfAllele(vc,Allele.create(alleles.get(i).getBases(),true),false,true,true),i);
+                Assert.assertEquals(GATKVariantContextUtils.indexOfAllele(vc,Allele.create(alleles.get(i).getBases(),false),false,true,true),-1);
+            } else {
+                Assert.assertEquals(GATKVariantContextUtils.indexOfAltAllele(vc,alleles.get(i),true),i - 1);
+                Assert.assertEquals(GATKVariantContextUtils.indexOfAltAllele(vc,alleles.get(i),false), i - 1);
+                Assert.assertEquals(GATKVariantContextUtils.indexOfAltAllele(vc,Allele.create(alleles.get(i),true),true),i-1);
+                Assert.assertEquals(GATKVariantContextUtils.indexOfAltAllele(vc,Allele.create(alleles.get(i),true),false),-1);
+            }
+        }
+
+        for (final Allele other : otherAlleles) {
+            Assert.assertEquals(GATKVariantContextUtils.indexOfAllele(vc, other, true, true, true), -1);
+            Assert.assertEquals(GATKVariantContextUtils.indexOfAllele(vc,other,false,true,true),-1);
+            Assert.assertEquals(GATKVariantContextUtils.indexOfAllele(vc,other,true,true,false),-1);
+            Assert.assertEquals(GATKVariantContextUtils.indexOfAllele(vc,other,false,true,false),-1);
+            Assert.assertEquals(GATKVariantContextUtils.indexOfAllele(vc,other,true,false,true),-1);
+            Assert.assertEquals(GATKVariantContextUtils.indexOfAllele(vc,other,false,false,true),-1);
+            Assert.assertEquals(GATKVariantContextUtils.indexOfAllele(vc,other,true,false,false),-1);
+            Assert.assertEquals(GATKVariantContextUtils.indexOfAllele(vc, other, false, false, false),-1);
+        }
+    }
+
+    @DataProvider(name = "indexOfAlleleData")
+    public Iterator<Object[]> indexOfAlleleData() {
+
+        final Allele[] ALTERNATIVE_ALLELES = new Allele[] { T, C, G, ATC, ATCATC};
+
+        final int lastMask = 0x1F;
+
+        return new Iterator<Object[]>() {
+
+            int nextMask = 0;
+
+            @Override
+            public boolean hasNext() {
+                return nextMask <= lastMask;
+            }
+
+            @Override
+            public Object[] next() {
+
+                int mask = nextMask++;
+                final List<Allele> includedAlleles = new ArrayList<>(5);
+                final List<Allele> excludedAlleles = new ArrayList<>(5);
+                for (int i = 0; i < ALTERNATIVE_ALLELES.length; i++) {
+                    ((mask & 1) == 1 ? includedAlleles : excludedAlleles).add(ALTERNATIVE_ALLELES[i]);
+                    mask >>= 1;
+                }
+                return new Object[] { Aref , includedAlleles, excludedAlleles};
+            }
+
+            @Override
+            public void remove() {
+                throw new UnsupportedOperationException();
+            }
+        };
+    }
+
+    @Test(dataProvider="overlapWithData")
+    public void testOverlapsWith(final VariantContext vc, final GenomeLoc genomeLoc) {
+        final boolean expected;
+
+        if (genomeLoc.isUnmapped())
+            expected = false;
+        else if (vc.getStart() > genomeLoc.getStop())
+            expected = false;
+        else if (vc.getEnd() < genomeLoc.getStart())
+            expected = false;
+        else if (!vc.getChr().equals(genomeLoc.getContig()))
+            expected = false;
+        else
+            expected = true;
+
+        Assert.assertEquals(GATKVariantContextUtils.overlapsRegion(vc, genomeLoc), expected);
+    }
+
+
+    private final String[] OVERLAP_WITH_CHROMOSOMES =  { "chr1", "chr20" };
+    private final int[] OVERLAP_WITH_EVENT_SIZES =  { -10, -1, 0, 1, 10 }; // 0 == SNP , -X xbp deletion, +X xbp insertion.
+    private final int[] OVERLAP_WITH_EVENT_STARTS = { 10000000, 10000001,
+                                                      10000005, 10000010,
+                                                      10000009, 10000011,
+                                                      20000000 };
+
+    @DataProvider(name="overlapWithData")
+    public Object[][] overlapWithData() {
+
+        final int totalLocations = OVERLAP_WITH_CHROMOSOMES.length * OVERLAP_WITH_EVENT_SIZES.length * OVERLAP_WITH_EVENT_STARTS.length + 1;
+        final int totalEvents = OVERLAP_WITH_CHROMOSOMES.length * OVERLAP_WITH_EVENT_SIZES.length * OVERLAP_WITH_EVENT_STARTS.length;
+        final GenomeLoc[] locs = new GenomeLoc[totalLocations];
+        final VariantContext[] events = new VariantContext[totalEvents];
+
+        generateAllLocationsAndVariantContextCombinations(OVERLAP_WITH_CHROMOSOMES, OVERLAP_WITH_EVENT_SIZES,
+                OVERLAP_WITH_EVENT_STARTS, locs, events);
+
+        return generateAllParameterCombinationsForOverlapWithData(locs, events);
+    }
+
+    private Object[][] generateAllParameterCombinationsForOverlapWithData(GenomeLoc[] locs, VariantContext[] events) {
+        final List<Object[]> result = new LinkedList<>();
+        for (final GenomeLoc loc : locs)
+            for (final VariantContext event : events)
+               result.add(new Object[] { event , loc });
+
+        return result.toArray(new Object[result.size()][]);
+    }
+
+    private void generateAllLocationsAndVariantContextCombinations(final String[] chrs, final int[] eventSizes,
+                                                                   final int[] eventStarts, final GenomeLoc[] locs,
+                                                                   final VariantContext[] events) {
+        int nextIndex = 0;
+        for (final String chr : chrs )
+            for (final int size : eventSizes )
+                for (final int starts : eventStarts ) {
+                    locs[nextIndex] = genomeLocParser.createGenomeLoc(chr,starts,starts + Math.max(0,size));
+                    events[nextIndex++] = new VariantContextBuilder().source("test").loc(chr,starts,starts + Math.max(0,size)).alleles(Arrays.asList(
+                            Allele.create(randomBases(size <= 0 ? 1 : size + 1, true), true), Allele.create(randomBases(size < 0 ? -size + 1 : 1, false), false))).make();
+                }
+
+        locs[nextIndex++]  = GenomeLoc.UNMAPPED;
+    }
+
+    @Test(dataProvider = "totalPloidyData")
+    public void testTotalPloidy(final int[] ploidies, final int defaultPloidy, final int expected) {
+        final Genotype[] genotypes = new Genotype[ploidies.length];
+        final List<Allele> vcAlleles = Arrays.asList(Aref,C);
+        for (int i = 0; i < genotypes.length; i++)
+            genotypes[i] = new GenotypeBuilder().alleles(GATKVariantContextUtils.noCallAlleles(ploidies[i])).make();
+        final VariantContext vc = new VariantContextBuilder().chr("seq1").genotypes(genotypes).alleles(vcAlleles).make();
+        Assert.assertEquals(GATKVariantContextUtils.totalPloidy(vc,defaultPloidy),expected," " + defaultPloidy + " " + Arrays.toString(ploidies));
+    }
+
+    @DataProvider(name="totalPloidyData")
+    public Object[][] totalPloidyData() {
+        final Random rdn = GenomeAnalysisEngine.getRandomGenerator();
+        final List<Object[]> resultList = new ArrayList<>();
+        for (int i = 0; i < 100; i++) {
+            final int sampleCount = rdn.nextInt(10);
+
+            int expected = 0;
+            final int defaultPloidy = rdn.nextInt(10) + 1;
+            final int[] plodies = new int[sampleCount];
+            for (int j = 0; j < sampleCount; j++) {
+                plodies[j] = rdn.nextInt(10);
+                expected += plodies[j] == 0 ? defaultPloidy : plodies[j];
+            }
+            resultList.add(new Object[] { plodies, defaultPloidy, expected });
+        }
+        return resultList.toArray(new Object[100][]);
+    }
+
+    private byte[] randomBases(final int length, final boolean reference) {
+        final byte[] bases = new byte[length];
+        bases[0] = (byte) (reference  ? 'A' : 'C');
+        BaseUtils.fillWithRandomBases(bases, 1, bases.length);
+        return bases;
+    }
+}
+
diff --git a/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/utils/variant/VCFIntegrationTest.java b/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/utils/variant/VCFIntegrationTest.java
new file mode 100644
index 0000000..4a08702
--- /dev/null
+++ b/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/utils/variant/VCFIntegrationTest.java
@@ -0,0 +1,377 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.utils.variant;
+
+import htsjdk.tribble.AbstractFeatureReader;
+import htsjdk.tribble.Tribble;
+import htsjdk.tribble.index.AbstractIndex;
+import htsjdk.tribble.index.ChrIndex;
+import htsjdk.tribble.index.Index;
+import htsjdk.tribble.index.IndexFactory;
+import htsjdk.tribble.index.interval.IntervalTreeIndex;
+import htsjdk.tribble.index.linear.LinearIndex;
+import htsjdk.tribble.index.tabix.TabixIndex;
+import htsjdk.tribble.util.TabixUtils;
+import org.broadinstitute.gatk.utils.BaseTest;
+import org.broadinstitute.gatk.engine.walkers.WalkerTest;
+import htsjdk.variant.vcf.VCFCodec;
+import org.testng.Assert;
+import org.testng.TestException;
+import org.testng.annotations.DataProvider;
+import org.testng.annotations.Test;
+
+import java.io.File;
+import java.lang.reflect.Field;
+import java.util.Arrays;
+import java.util.LinkedHashMap;
+import java.util.List;
+
+public class VCFIntegrationTest extends WalkerTest {
+
+    @Test(enabled = true)
+    public void testReadingAndWritingWitHNoChanges() {
+
+        String md5ofInputVCF = "d991abe6c6a7a778a60a667717903be0";
+        String testVCF = privateTestDir + "vcf4.1.example.vcf";
+
+        String baseCommand = "-R " + b37KGReference + " --no_cmdline_in_header -o %s ";
+
+        String test1 = baseCommand + "-T VariantAnnotator --variant " + testVCF + " -L " + testVCF;
+        WalkerTestSpec spec1 = new WalkerTestSpec(test1, 1, Arrays.asList(md5ofInputVCF));
+        List<File> result = executeTest("Test Variant Annotator with no changes", spec1).getFirst();
+
+        String test2 = baseCommand + "-T VariantsToVCF --variant " + result.get(0).getAbsolutePath();
+        WalkerTestSpec spec2 = new WalkerTestSpec(test2, 1, Arrays.asList(md5ofInputVCF));
+        executeTest("Test Variants To VCF from new output", spec2);
+    }
+
+    @Test(enabled = true)
+    public void testReadingAndWritingBreakpointAlleles() {
+        String testVCF = privateTestDir + "breakpoint-example.vcf";
+
+        String baseCommand = "-R " + b37KGReference + " --no_cmdline_in_header -o %s ";
+
+        String test1 = baseCommand + "-T SelectVariants -V " + testVCF;
+        WalkerTestSpec spec1 = new WalkerTestSpec(test1, 1, Arrays.asList("13329ba7360a8beb3afc02569e5a20c4"));
+        executeTest("Test reading and writing breakpoint VCF", spec1);
+    }
+
+    @Test(enabled = true)
+    public void testReadingLowerCaseBases() {
+        String testVCF = privateTestDir + "lowercaseBases.vcf";
+
+        String baseCommand = "-R " + b37KGReference + " --no_cmdline_in_header -o %s ";
+
+        String test1 = baseCommand + "-T SelectVariants -V " + testVCF;
+        WalkerTestSpec spec1 = new WalkerTestSpec(test1, 1, Arrays.asList("e0e308a25e56bde1c664139bb44ed19d"));
+        executeTest("Test reading VCF with lower-case bases", spec1);
+    }
+
+    @Test(enabled = true)
+    public void testReadingAndWriting1000GSVs() {
+        String testVCF = privateTestDir + "1000G_SVs.chr1.vcf";
+
+        String baseCommand = "-R " + b37KGReference + " --no_cmdline_in_header -o %s ";
+
+        String test1 = baseCommand + "-T SelectVariants -V " + testVCF;
+        WalkerTestSpec spec1 = new WalkerTestSpec(test1, 1, Arrays.asList("bdab26dd7648a806dbab01f64db2bdab"));
+        executeTest("Test reading and writing 1000G Phase I SVs", spec1);
+    }
+
+    @Test
+    public void testReadingAndWritingSamtools() {
+        String testVCF = privateTestDir + "samtools.vcf";
+
+        String baseCommand = "-R " + b37KGReference + " --no_cmdline_in_header -o %s ";
+
+        String test1 = baseCommand + "-T SelectVariants -V " + testVCF;
+        WalkerTestSpec spec1 = new WalkerTestSpec(test1, 1, Arrays.asList("38697c195e7abf18d95dcc16c8e6d284"));
+        executeTest("Test reading and writing samtools vcf", spec1);
+    }
+
+    @Test
+    public void testWritingSamtoolsWExBCFExample() {
+        String testVCF = privateTestDir + "ex2.vcf";
+        String baseCommand = "-R " + b36KGReference + " --no_cmdline_in_header -o %s ";
+        String test1 = baseCommand + "-T SelectVariants -V " + testVCF;
+        WalkerTestSpec spec1 = new WalkerTestSpec(test1, 1, Arrays.asList("e8f721ce81e4fdadba13c5291027057f"));
+        executeTest("Test writing samtools WEx BCF example", spec1);
+    }
+
+    @Test(enabled = true)
+    public void testReadingSamtoolsWExBCFExample() {
+        String testVCF = privateTestDir + "ex2.bcf";
+        String baseCommand = "-R " + b36KGReference + " --no_cmdline_in_header -o %s ";
+        String test1 = baseCommand + "-T SelectVariants -V " + testVCF;
+        WalkerTestSpec spec1 = new WalkerTestSpec(test1, 1, Arrays.asList("0439e2b4ccc63bb4ba7c283cd9ab1b25"));
+        executeTest("Test reading samtools WEx BCF example", spec1);
+    }
+
+    //
+    //
+    // Tests to ensure that -U LENIENT_VCF_PROCESS
+    //
+    //
+
+    @Test
+    public void testFailingOnVCFWithoutHeaders() {
+        runVCFWithoutHeaders("", "", IllegalStateException.class, false);
+    }
+
+    @Test
+    public void testPassingOnVCFWithoutHeadersWithLenientProcessing() {
+        runVCFWithoutHeaders("-U LENIENT_VCF_PROCESSING", "6de8cb7457154dd355aa55befb943f88", null, true);
+    }
+
+    private void runVCFWithoutHeaders(final String moreArgs, final String expectedMD5, final Class expectedException, final boolean disableBCF) {
+        final String testVCF = privateTestDir + "vcfexample2.noHeader.vcf";
+        final String baseCommand = "-R " + b37KGReference
+                + " --no_cmdline_in_header -o %s "
+                + "-T VariantsToVCF -V " + testVCF + " " + moreArgs;
+        WalkerTestSpec spec1 = expectedException != null
+                ? new WalkerTestSpec(baseCommand, 1, expectedException)
+                : new WalkerTestSpec(baseCommand, 1, Arrays.asList(expectedMD5));
+        if ( disableBCF )
+            spec1.disableShadowBCF();
+        executeTest("Test reading VCF without header lines with additional args " + moreArgs, spec1);
+    }
+
+    //
+    //
+    // IndexCreator tests
+    //
+    //
+
+    private class VCFIndexCreatorTest extends TestDataProvider {
+        private final GATKVCFIndexType type;
+        private final int parameter;
+
+        private VCFIndexCreatorTest(GATKVCFIndexType type, int parameter) {
+            super(VCFIndexCreatorTest.class);
+
+            this.type = type;
+            this.parameter = parameter;
+        }
+
+        public String toString() {
+            return String.format("Index Type %s, Index Parameter %s", type, parameter);
+        }
+
+        public Index getIndex(final File vcfFile) {
+            switch (type) {
+                case DYNAMIC_SEEK : return IndexFactory.createDynamicIndex(vcfFile, new VCFCodec(), IndexFactory.IndexBalanceApproach.FOR_SEEK_TIME);
+                case DYNAMIC_SIZE : return IndexFactory.createDynamicIndex(vcfFile, new VCFCodec(), IndexFactory.IndexBalanceApproach.FOR_SIZE);
+                case LINEAR : return IndexFactory.createLinearIndex(vcfFile, new VCFCodec(), parameter);
+                case INTERVAL : return IndexFactory.createIntervalIndex(vcfFile, new VCFCodec(), parameter);
+                default : throw new TestException("Invalid index type");
+            }
+        }
+    }
+
+    @DataProvider(name = "IndexDataProvider")
+    public Object[][] indexCreatorData() {
+        new VCFIndexCreatorTest(GATKVCFIndexType.DYNAMIC_SEEK, 0);
+        new VCFIndexCreatorTest(GATKVCFIndexType.DYNAMIC_SIZE, 0);
+        new VCFIndexCreatorTest(GATKVCFIndexType.LINEAR, 100);
+        new VCFIndexCreatorTest(GATKVCFIndexType.LINEAR, 10000);
+        new VCFIndexCreatorTest(GATKVCFIndexType.INTERVAL, 20);
+        new VCFIndexCreatorTest(GATKVCFIndexType.INTERVAL, 2000);
+
+        return TestDataProvider.getTests(VCFIndexCreatorTest.class);
+    }
+
+    @Test(dataProvider = "IndexDataProvider")
+    public void testVCFIndexCreation(VCFIndexCreatorTest testSpec) throws NoSuchFieldException, IllegalAccessException {
+
+        final String commandLine = " -T SelectVariants" +
+                " -R " + b37KGReference +
+                " --no_cmdline_in_header" +
+                " -L 20" +
+                " -V " + b37_NA12878_OMNI +
+                " --variant_index_type " + testSpec.type +
+                " --variant_index_parameter " + testSpec.parameter +
+                " -o %s ";
+        final String name = "testVCFIndexCreation: " + testSpec.toString();
+
+        final WalkerTestSpec spec = new WalkerTestSpec(commandLine, 1, Arrays.asList(""));
+        spec.disableShadowBCF();
+
+        File outVCF = executeTest(name, spec).first.get(0);
+        File outIdx = new File(outVCF.getAbsolutePath() + Tribble.STANDARD_INDEX_EXTENSION);
+
+        final Index actualIndex = IndexFactory.loadIndex(outIdx.getAbsolutePath());
+        final Index expectedIndex = testSpec.getIndex(outVCF);
+
+        if (testSpec.type.equals("LINEAR"))
+            Assert.assertTrue(actualIndex instanceof LinearIndex, "Index is not a LinearIndex");
+        else if (testSpec.type.equals("INTERVAL"))
+            Assert.assertTrue(actualIndex instanceof IntervalTreeIndex, "Index is not a IntervalTreeIndex");
+        // dynamic indices ultimately resolve to one of LinearIndex or IntervalTreeIndex
+
+        Assert.assertTrue(equivalentAbstractIndices((AbstractIndex)actualIndex, (AbstractIndex)expectedIndex), "Indices are not equivalent");
+
+        if (actualIndex instanceof LinearIndex && expectedIndex instanceof LinearIndex) {
+            Assert.assertTrue(equivalentLinearIndices((LinearIndex)actualIndex, (LinearIndex)expectedIndex, "20"), "Linear indices are not equivalent");
+        }
+        else if (actualIndex instanceof IntervalTreeIndex && expectedIndex instanceof IntervalTreeIndex) {
+            Assert.assertTrue(equivalentIntervalIndices((IntervalTreeIndex)actualIndex, (IntervalTreeIndex)expectedIndex, "20"), "Interval indices are not equivalent");
+        }
+        else {
+            Assert.fail("Indices are not of the same type");
+        }
+    }
+
+    private static boolean equivalentAbstractIndices(AbstractIndex thisIndex, AbstractIndex otherIndex){
+        return thisIndex.getVersion() == otherIndex.getVersion() &&
+                thisIndex.getIndexedFile().equals(otherIndex.getIndexedFile()) &&
+                thisIndex.getIndexedFileSize() == otherIndex.getIndexedFileSize() &&
+                thisIndex.getIndexedFileMD5().equals(otherIndex.getIndexedFileMD5()) &&
+                thisIndex.getFlags() == otherIndex.getFlags();
+     }
+
+    private static boolean equivalentLinearIndices(LinearIndex thisIndex, LinearIndex otherIndex, String chr) throws NoSuchFieldException, IllegalAccessException {
+        htsjdk.tribble.index.linear.LinearIndex.ChrIndex thisChr = (htsjdk.tribble.index.linear.LinearIndex.ChrIndex)getChrIndex(thisIndex, chr);
+        htsjdk.tribble.index.linear.LinearIndex.ChrIndex otherChr = (htsjdk.tribble.index.linear.LinearIndex.ChrIndex)getChrIndex(otherIndex, chr);
+
+        return  thisChr.getName().equals(otherChr.getName()) &&
+                //thisChr.getTotalSize() == otherChr.getTotalSize() &&      TODO: why does this differ?
+                thisChr.getNFeatures() == otherChr.getNFeatures() &&
+                thisChr.getNBlocks() == otherChr.getNBlocks();
+    }
+
+    private static boolean equivalentIntervalIndices(IntervalTreeIndex thisIndex, IntervalTreeIndex otherIndex, String chr) throws NoSuchFieldException, IllegalAccessException {
+        htsjdk.tribble.index.interval.IntervalTreeIndex.ChrIndex thisChr = (htsjdk.tribble.index.interval.IntervalTreeIndex.ChrIndex)getChrIndex(thisIndex, chr);
+        htsjdk.tribble.index.interval.IntervalTreeIndex.ChrIndex otherChr = (htsjdk.tribble.index.interval.IntervalTreeIndex.ChrIndex)getChrIndex(otherIndex, chr);
+
+        // TODO: compare trees?
+        return thisChr.getName().equals(otherChr.getName());
+    }
+
+    private static ChrIndex getChrIndex(AbstractIndex index, String chr) throws NoSuchFieldException, IllegalAccessException {
+        Field f = AbstractIndex.class.getDeclaredField("chrIndices");
+        f.setAccessible(true);
+        LinkedHashMap<String, ChrIndex> chrIndices = (LinkedHashMap<String, ChrIndex>) f.get(index);
+        return chrIndices.get(chr);
+    }
+
+    //
+    //
+    // Block-Compressed Tabix Index Tests
+    //
+    //
+
+    private class BlockCompressedIndexCreatorTest extends TestDataProvider {
+        private final String extension;
+
+        private BlockCompressedIndexCreatorTest(String extension) {
+            super(BlockCompressedIndexCreatorTest.class);
+
+            this.extension = extension;
+        }
+
+        public String toString() {
+            return String.format("File extension %s", extension);
+        }
+    }
+
+    @DataProvider(name = "BlockCompressedIndexDataProvider")
+    public Object[][] blockCompressedIndexCreatorData() {
+        for (final String extension : AbstractFeatureReader.BLOCK_COMPRESSED_EXTENSIONS)
+            new BlockCompressedIndexCreatorTest(".vcf" + extension);
+
+        return TestDataProvider.getTests(BlockCompressedIndexCreatorTest.class);
+    }
+
+    @Test(dataProvider = "BlockCompressedIndexDataProvider")
+    public void testBlockCompressedIndexCreation(BlockCompressedIndexCreatorTest testSpec) throws NoSuchFieldException, IllegalAccessException {
+
+        final String commandLine = " -T SelectVariants" +
+                " -R " + b37KGReference +
+                " --no_cmdline_in_header" +
+                " -L 20" +
+                " -V " + b37_NA12878_OMNI;
+        final String name = "testBlockCompressedIndexCreation: " + testSpec.toString();
+
+        File outVCF = createTempFile("testBlockCompressedIndexCreation", testSpec.extension);
+        final WalkerTestSpec spec = new WalkerTestSpec(commandLine, 1, Arrays.asList(""));
+        spec.disableShadowBCF();
+        spec.setOutputFileLocation(outVCF);
+
+        executeTest(name, spec);
+
+        File outTribbleIdx = new File(outVCF.getAbsolutePath() + Tribble.STANDARD_INDEX_EXTENSION);
+        Assert.assertFalse(outTribbleIdx.exists(), "testBlockCompressedIndexCreation: Want Tabix index but Tribble index exists: " + outTribbleIdx);
+
+        File outTabixIdx = new File(outVCF.getAbsolutePath() + TabixUtils.STANDARD_INDEX_EXTENSION);
+        final Index actualIndex = IndexFactory.loadIndex(outTabixIdx.toString());
+        Assert.assertTrue(actualIndex instanceof TabixIndex, "testBlockCompressedIndexCreation: Want Tabix index but index is not Tabix: " + outTabixIdx);
+    }
+
+    //
+    //
+    // Block-Compressed Input Tests
+    //
+    //
+
+    private class BlockCompressedInputTest extends TestDataProvider {
+        private final String extension;
+
+        private BlockCompressedInputTest(String extension) {
+            super(BlockCompressedInputTest.class);
+
+            this.extension = extension;
+        }
+
+        public String toString() {
+            return String.format("File extension %s", extension);
+        }
+    }
+
+    @DataProvider(name = "BlockCompressedInputDataProvider")
+    public Object[][] blockCompressedInputData() {
+        for (final String extension : AbstractFeatureReader.BLOCK_COMPRESSED_EXTENSIONS)
+            new BlockCompressedInputTest(".vcf" + extension);
+
+        return TestDataProvider.getTests(BlockCompressedInputTest.class);
+    }
+
+    @Test(dataProvider = "BlockCompressedInputDataProvider")
+    public void testBlockCompressedInput(BlockCompressedInputTest testSpec) {
+
+        File inputFile = new File(BaseTest.privateTestDir, "block_compressed_input_test" + testSpec.extension);
+        final String commandLine = " -T SelectVariants" +
+                " -R " + b37KGReference +
+                " --no_cmdline_in_header" +
+                " -V " + inputFile +
+                " -o %s ";
+        final String name = "testBlockCompressedInput: " + testSpec.toString();
+
+        final WalkerTestSpec spec = new WalkerTestSpec(commandLine, 1, Arrays.asList("3b60668bd973e43783d0406de80d2ed2"));
+
+        executeTest(name, spec);
+    }
+
+}
diff --git a/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/utils/variant/VariantContextBenchmark.java b/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/utils/variant/VariantContextBenchmark.java
new file mode 100644
index 0000000..7c1b202
--- /dev/null
+++ b/public/gatk-tools-public/src/test/java/org/broadinstitute/gatk/utils/variant/VariantContextBenchmark.java
@@ -0,0 +1,377 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.utils.variant;
+
+import com.google.caliper.Param;
+import com.google.caliper.SimpleBenchmark;
+import htsjdk.tribble.Feature;
+import htsjdk.tribble.FeatureCodec;
+import htsjdk.variant.variantcontext.*;
+import htsjdk.variant.vcf.VCFCodec;
+
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+/**
+ * Caliper microbenchmark of parsing a VCF file
+ */
+public class VariantContextBenchmark extends SimpleBenchmark {
+    @Param({"/Users/depristo/Desktop/broadLocal/localData/ALL.chr20.merged_beagle_mach.20101123.snps_indels_svs.genotypes.vcf"})
+    String vcfFile;
+
+    @Param({"1000"})
+    int linesToRead; // set automatically by framework
+
+    @Param({"100"})
+    int nSamplesToTake; // set automatically by framework
+
+    @Param({"10"})
+    int dupsToMerge; // set automatically by framework
+
+    @Param
+    Operation operation; // set automatically by framework
+
+    private String INPUT_STRING;
+
+    public enum Operation {
+        READ,
+        SUBSET_TO_SAMPLES,
+        GET_TYPE,
+        GET_ID,
+        GET_GENOTYPES,
+        GET_ATTRIBUTE_STRING,
+        GET_ATTRIBUTE_INT,
+        GET_N_SAMPLES,
+        GET_GENOTYPES_FOR_SAMPLES,
+        GET_GENOTYPES_IN_ORDER_OF_NAME,
+        CALC_GENOTYPE_COUNTS,
+        MERGE
+    }
+
+    @Override protected void setUp() {
+        // TODO -- update for new tribble interface
+//        try {
+//            ReferenceSequenceFile seq = new CachingIndexedFastaSequenceFile(new File(BaseTest.b37KGReference));
+//            b37GenomeLocParser = new GenomeLocParser(seq);
+//        } catch ( FileNotFoundException e) {
+//            throw new RuntimeException(e);
+//        }
+//
+//        // read it into a String so that we don't try to benchmark IO issues
+//        try {
+//            FileInputStream s = new FileInputStream(new File(vcfFile));
+//            AsciiLineReader lineReader = new AsciiLineReader(s);
+//            int counter = 0;
+//            StringBuffer sb = new StringBuffer();
+//            while (counter++ < linesToRead ) {
+//                String line = lineReader.readLine();
+//                if ( line == null )
+//                    break;
+//                sb.append(line + "\n");
+//            }
+//            s.close();
+//            INPUT_STRING = sb.toString();
+//        } catch (IOException e) {
+//            throw new RuntimeException(e);
+//        }
+    }
+
+    private interface FunctionToBenchmark<T extends Feature> {
+        public void run(T vc);
+    }
+
+    private <T extends Feature> void runBenchmark(FeatureCodec codec, FunctionToBenchmark<T> func) {
+        // TODO -- update for new Tribble interface
+//        try {
+//            InputStream is = new ByteArrayInputStream(INPUT_STRING.getBytes());
+//            AsciiLineReader lineReader = new AsciiLineReader(is);
+//            codec.readHeader(lineReader);
+//
+//            int counter = 0;
+//            while (counter++ < linesToRead ) {
+//                String line = lineReader.readLine();
+//                if ( line == null )
+//                    break;
+//
+//                T vc = codec.decode(line);
+//                func.run(vc);
+//            }
+//        } catch (Exception e) {
+//            System.out.println("Benchmarking run failure because of " + e.getMessage());
+//        }
+    }
+
+    public void timeV14(int rep) {
+        for ( int i = 0; i < rep; i++ ) {
+            FunctionToBenchmark<VariantContext> func = getV14FunctionToBenchmark();
+            final VCFCodec codec = new VCFCodec();
+            runBenchmark(codec, func);
+        }
+    }
+
+    public FunctionToBenchmark<VariantContext> getV14FunctionToBenchmark() {
+        switch ( operation ) {
+            case READ:
+                return new FunctionToBenchmark<VariantContext>() {
+                    public void run(final VariantContext vc) {
+                        ; // empty operation
+                    }
+                };
+            case SUBSET_TO_SAMPLES:
+                return new FunctionToBenchmark<VariantContext>() {
+                    Set<String> samples;
+                    public void run(final VariantContext vc) {
+                        if ( samples == null )
+                            samples = new HashSet<>(new ArrayList<>(vc.getSampleNames()).subList(0, nSamplesToTake));
+                        VariantContext sub = vc.subContextFromSamples(samples);
+                        sub.getNSamples();
+                    }
+                };
+            case GET_TYPE:
+                return new FunctionToBenchmark<VariantContext>() {
+                    public void run(final VariantContext vc) {
+                        vc.getType();
+                    }
+                };
+            case GET_ID:
+                return new FunctionToBenchmark<VariantContext>() {
+                    public void run(final VariantContext vc) {
+                        vc.getID();
+                    }
+                };
+            case GET_GENOTYPES:
+                return new FunctionToBenchmark<VariantContext>() {
+                    public void run(final VariantContext vc) {
+                        vc.getGenotypes().size();
+                    }
+                };
+
+            case GET_GENOTYPES_FOR_SAMPLES:
+                return new FunctionToBenchmark<VariantContext>() {
+                    Set<String> samples;
+                    public void run(final VariantContext vc) {
+                        if ( samples == null )
+                            samples = new HashSet<>(new ArrayList<>(vc.getSampleNames()).subList(0, nSamplesToTake));
+                        vc.getGenotypes(samples).size();
+                    }
+                };
+
+            case GET_ATTRIBUTE_STRING:
+                return new FunctionToBenchmark<VariantContext>() {
+                    public void run(final VariantContext vc) {
+                        vc.getAttribute("AN", null);
+                    }
+                };
+
+            case GET_ATTRIBUTE_INT:
+                return new FunctionToBenchmark<VariantContext>() {
+                    public void run(final VariantContext vc) {
+                        vc.getAttributeAsInt("AC", 0);
+                    }
+                };
+
+            case GET_N_SAMPLES:
+                return new FunctionToBenchmark<VariantContext>() {
+                    public void run(final VariantContext vc) {
+                        vc.getNSamples();
+                    }
+                };
+
+            case GET_GENOTYPES_IN_ORDER_OF_NAME:
+                return new FunctionToBenchmark<VariantContext>() {
+                    public void run(final VariantContext vc) {
+                        ; // TODO - TEST IS BROKEN
+//                        int n = 0;
+//                        for ( final Genotype g: vc.getGenotypesOrderedByName() ) n++;
+                    }
+                };
+
+            case CALC_GENOTYPE_COUNTS:
+                return new FunctionToBenchmark<VariantContext>() {
+                    public void run(final VariantContext vc) {
+                        vc.getHetCount();
+                    }
+                };
+
+            case MERGE:
+                return new FunctionToBenchmark<VariantContext>() {
+                    public void run(final VariantContext vc) {
+                        List<VariantContext> toMerge = new ArrayList<>();
+
+                        for ( int i = 0; i < dupsToMerge; i++ ) {
+                            GenotypesContext gc = GenotypesContext.create(vc.getNSamples());
+                            for ( final Genotype g : vc.getGenotypes() ) {
+                                gc.add(new GenotypeBuilder(g).name(g.getSampleName()+"_"+i).make());
+                            }
+                            toMerge.add(new VariantContextBuilder(vc).genotypes(gc).make());
+                        }
+
+                        GATKVariantContextUtils.simpleMerge(toMerge, null,
+                                GATKVariantContextUtils.FilteredRecordMergeType.KEEP_IF_ANY_UNFILTERED,
+                                GATKVariantContextUtils.GenotypeMergeType.UNSORTED,
+                                true, false, "set", false, true);
+                    }
+                };
+
+            default: throw new IllegalArgumentException("Unexpected operation " + operation);
+        }
+    }
+
+    // --------------------------------------------------------------------------------
+    //
+    // V13
+    //
+    // In order to use this, you must move the v13 version from archive and uncomment
+    //
+    // git mv private/archive/java/src/org/broadinstitute/sting/utils/variantcontext/v13 public/java/test/org/broadinstitute/sting/utils/variantcontext/v13
+    //
+    // --------------------------------------------------------------------------------
+
+//    public void timeV13(int rep) {
+//        for ( int i = 0; i < rep; i++ ) {
+//            FunctionToBenchmark<htsjdk.variant.variantcontext.v13.VariantContext> func = getV13FunctionToBenchmark();
+//            FeatureCodec<htsjdk.variant.variantcontext.v13.VariantContext> codec = new htsjdk.variant.variantcontext.v13.VCFCodec();
+//            runBenchmark(codec, func);
+//        }
+//    }
+//
+//    public FunctionToBenchmark<htsjdk.variant.variantcontext.v13.VariantContext> getV13FunctionToBenchmark() {
+//        switch ( operation ) {
+//            case READ:
+//                return new FunctionToBenchmark<htsjdk.variant.variantcontext.v13.VariantContext>() {
+//                    public void run(final htsjdk.variant.variantcontext.v13.VariantContext vc) {
+//                        ; // empty operation
+//                    }
+//                };
+//            case SUBSET_TO_SAMPLES:
+//                return new FunctionToBenchmark<htsjdk.variant.variantcontext.v13.VariantContext>() {
+//                    List<String> samples;
+//                    public void run(final htsjdk.variant.variantcontext.v13.VariantContext vc) {
+//                        if ( samples == null )
+//                            samples = new ArrayList<String>(vc.getSampleNames()).subList(0, nSamplesToTake);
+//                        htsjdk.variant.variantcontext.v13.VariantContext sub = vc.subContextFromGenotypes(vc.getGenotypes(samples).values());
+//                        sub.getNSamples();
+//                    }
+//                };
+//
+//            case GET_TYPE:
+//                return new FunctionToBenchmark<htsjdk.variant.variantcontext.v13.VariantContext>() {
+//                    public void run(final htsjdk.variant.variantcontext.v13.VariantContext vc) {
+//                        vc.getType();
+//                    }
+//                };
+//            case GET_ID:
+//                return new FunctionToBenchmark<htsjdk.variant.variantcontext.v13.VariantContext>() {
+//                    public void run(final htsjdk.variant.variantcontext.v13.VariantContext vc) {
+//                        vc.getID();
+//                    }
+//                };
+//            case GET_GENOTYPES:
+//                return new FunctionToBenchmark<htsjdk.variant.variantcontext.v13.VariantContext>() {
+//                    public void run(final htsjdk.variant.variantcontext.v13.VariantContext vc) {
+//                        vc.getGenotypes().size();
+//                    }
+//                };
+//
+//            case GET_GENOTYPES_FOR_SAMPLES:
+//                return new FunctionToBenchmark<htsjdk.variant.variantcontext.v13.VariantContext>() {
+//                    Set<String> samples;
+//                    public void run(final htsjdk.variant.variantcontext.v13.VariantContext vc) {
+//                        if ( samples == null )
+//                            samples = new HashSet<String>(new ArrayList<String>(vc.getSampleNames()).subList(0, nSamplesToTake));
+//                        vc.getGenotypes(samples).size();
+//                    }
+//                };
+//
+//            case GET_ATTRIBUTE_STRING:
+//                return new FunctionToBenchmark<htsjdk.variant.variantcontext.v13.VariantContext>() {
+//                    public void run(final htsjdk.variant.variantcontext.v13.VariantContext vc) {
+//                        vc.getExtendedAttribute("AN", null);
+//                    }
+//                };
+//
+//            case GET_ATTRIBUTE_INT:
+//                return new FunctionToBenchmark<htsjdk.variant.variantcontext.v13.VariantContext>() {
+//                    public void run(final htsjdk.variant.variantcontext.v13.VariantContext vc) {
+//                        vc.getAttributeAsInt("AC", 0);
+//                    }
+//                };
+//
+//            case GET_N_SAMPLES:
+//                return new FunctionToBenchmark<htsjdk.variant.variantcontext.v13.VariantContext>() {
+//                    public void run(final htsjdk.variant.variantcontext.v13.VariantContext vc) {
+//                        vc.getNSamples();
+//                    }
+//                };
+//
+//            case GET_GENOTYPES_IN_ORDER_OF_NAME:
+//                return new FunctionToBenchmark<htsjdk.variant.variantcontext.v13.VariantContext>() {
+//                    public void run(final htsjdk.variant.variantcontext.v13.VariantContext vc) {
+//                        ; // TODO - TEST IS BROKEN
+//                        //vc.getGenotypesOrderedByName();
+//                    }
+//                };
+//
+//            case CALC_GENOTYPE_COUNTS:
+//                return new FunctionToBenchmark<htsjdk.variant.variantcontext.v13.VariantContext>() {
+//                    public void run(final htsjdk.variant.variantcontext.v13.VariantContext vc) {
+//                        vc.getHetCount();
+//                    }
+//                };
+//
+//            case MERGE:
+//                return new FunctionToBenchmark<htsjdk.variant.variantcontext.v13.VariantContext>() {
+//                    public void run(final htsjdk.variant.variantcontext.v13.VariantContext vc) {
+//                        List<htsjdk.variant.variantcontext.v13.VariantContext> toMerge = new ArrayList<htsjdk.variant.variantcontext.v13.VariantContext>();
+//
+//                        for ( int i = 0; i < dupsToMerge; i++ ) {
+//                            Map<String, htsjdk.variant.variantcontext.v13.Genotype> gc = new HashMap<String, htsjdk.variant.variantcontext.v13.Genotype>();
+//                            for ( final htsjdk.variant.variantcontext.v13.Genotype g : vc.getGenotypes().values() ) {
+//                                String name = g.getSampleName()+"_"+i;
+//                                gc.put(name, new htsjdk.variant.variantcontext.v13.Genotype(name,
+//                                        g.getAlleles(), g.getLog10PError(), g.getFilters(), g.getAttributes(), g.isPhased(), g.getLikelihoods().getAsVector()));
+//                                toMerge.add(htsjdk.variant.variantcontext.v13.VariantContext.modifyGenotypes(vc, gc));
+//                            }
+//                        }
+//
+//                        htsjdk.variant.variantcontext.v13.VariantContextUtils.simpleMerge(b37GenomeLocParser,
+//                                toMerge, null,
+//                                htsjdk.variant.variantcontext.v13.VariantContextUtils.FilteredRecordMergeType.KEEP_IF_ANY_UNFILTERED,
+//                                htsjdk.variant.variantcontext.v13.VariantContextUtils.GenotypeMergeType.UNSORTED,
+//                                true, false, "set", false, true, false);
+//                    }
+//                };
+//
+//            default: throw new IllegalArgumentException("Unexpected operation " + operation);
+//        }
+//    }
+
+    public static void main(String[] args) {
+        com.google.caliper.Runner.main(VariantContextBenchmark.class, args);
+    }
+}
diff --git a/public/gatk-tools-public/src/test/resources/testProperties.properties b/public/gatk-tools-public/src/test/resources/testProperties.properties
new file mode 100644
index 0000000..e422d6e
--- /dev/null
+++ b/public/gatk-tools-public/src/test/resources/testProperties.properties
@@ -0,0 +1,2 @@
+foo=bar
+version=1.0
diff --git a/public/gatk-utils/pom.xml b/public/gatk-utils/pom.xml
new file mode 100644
index 0000000..f656394
--- /dev/null
+++ b/public/gatk-utils/pom.xml
@@ -0,0 +1,192 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+    <modelVersion>4.0.0</modelVersion>
+
+    <parent>
+        <groupId>org.broadinstitute.gatk</groupId>
+        <artifactId>gatk-aggregator</artifactId>
+        <version>3.3</version>
+        <relativePath>../..</relativePath>
+    </parent>
+
+    <artifactId>gatk-utils</artifactId>
+    <packaging>jar</packaging>
+    <name>GATK Utils</name>
+
+    <properties>
+        <gatk.basedir>${project.basedir}/../..</gatk.basedir>
+        <gatk.packagetests.artifactId>gatk-package-distribution</gatk.packagetests.artifactId>
+        <gsalib.packagedir>org/broadinstitute/gatk/utils/R</gsalib.packagedir>
+        <gsalib.filename>gsalib.tar.gz</gsalib.filename>
+    </properties>
+
+    <dependencies>
+        <dependency>
+            <groupId>samtools</groupId>
+            <artifactId>htsjdk</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>picard</groupId>
+            <artifactId>picard</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>log4j</groupId>
+            <artifactId>log4j</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>colt</groupId>
+            <artifactId>colt</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>it.unimi.dsi</groupId>
+            <artifactId>fastutil</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.simpleframework</groupId>
+            <artifactId>simple-xml</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.reflections</groupId>
+            <artifactId>reflections</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.slf4j</groupId>
+            <artifactId>slf4j-log4j12</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.freemarker</groupId>
+            <artifactId>freemarker</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.commons</groupId>
+            <artifactId>commons-jexl</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>commons-lang</groupId>
+            <artifactId>commons-lang</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>commons-io</groupId>
+            <artifactId>commons-io</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>commons-collections</groupId>
+            <artifactId>commons-collections</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.commons</groupId>
+            <artifactId>commons-math</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>net.java.dev.jna</groupId>
+            <artifactId>jna</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>net.java.dev.jets3t</groupId>
+            <artifactId>jets3t</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>us.levk</groupId>
+            <artifactId>drmaa-gridengine</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>com.google.code.gson</groupId>
+            <artifactId>gson</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.httpcomponents</groupId>
+            <artifactId>httpclient</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>com.google.code.cofoja</groupId>
+            <artifactId>cofoja</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>${project.groupId}</groupId>
+            <artifactId>gsalib</artifactId>
+            <version>${project.version}</version>
+            <type>tar.gz</type>
+        </dependency>
+
+        <dependency>
+            <groupId>com.google.caliper</groupId>
+            <artifactId>caliper</artifactId>
+            <scope>test</scope>
+        </dependency>
+    </dependencies>
+
+    <build>
+        <plugins>
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-dependency-plugin</artifactId>
+                <executions>
+                    <execution>
+                        <id>copy-gsalib</id>
+                        <goals>
+                            <goal>copy</goal>
+                        </goals>
+                        <phase>process-resources</phase>
+                        <configuration>
+                            <artifactItems>
+                                <artifactItem>
+                                    <groupId>${project.groupId}</groupId>
+                                    <artifactId>gsalib</artifactId>
+                                    <version>${project.version}</version>
+                                    <type>tar.gz</type>
+                                    <outputDirectory>${project.build.outputDirectory}/${gsalib.packagedir}</outputDirectory>
+                                    <destFileName>${gsalib.filename}</destFileName>
+                                </artifactItem>
+                            </artifactItems>
+                        </configuration>
+                    </execution>
+                </executions>
+            </plugin>
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-resources-plugin</artifactId>
+                <executions>
+                    <execution>
+                        <id>copy-resource-bundle-log4j</id>
+                        <phase>prepare-package</phase>
+                    </execution>
+                </executions>
+            </plugin>
+            <!--
+            TODO: Refactor ResourceBundleExtractorDoclet.isWalker() and move the RBED to utils.
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-javadoc-plugin</artifactId>
+                <executions>
+                    <execution>
+                        <id>extract-resource-bundle</id>
+                        <phase>prepare-package</phase>
+                    </execution>
+                </executions>
+            </plugin>
+            -->
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-invoker-plugin</artifactId>
+                <executions>
+                    <execution>
+                        <id>package-unittests</id>
+                    </execution>
+                    <execution>
+                        <id>package-integrationtests</id>
+                    </execution>
+                    <execution>
+                        <id>package-largescaletests</id>
+                    </execution>
+                    <execution>
+                        <id>package-knowledgebasetests</id>
+                    </execution>
+                    <execution>
+                        <id>package-queuetests</id>
+                    </execution>
+                </executions>
+            </plugin>
+        </plugins>
+    </build>
+
+</project>
diff --git a/public/gatk-utils/src/main/config/org/broadinstitute/gatk/utils/help/log4j.properties b/public/gatk-utils/src/main/config/org/broadinstitute/gatk/utils/help/log4j.properties
new file mode 100644
index 0000000..38c8335
--- /dev/null
+++ b/public/gatk-utils/src/main/config/org/broadinstitute/gatk/utils/help/log4j.properties
@@ -0,0 +1,7 @@
+# Root logger option
+log4j.rootLogger=INFO, stdout
+
+# Direct log messages to stdout
+log4j.appender.stdout=org.apache.log4j.ConsoleAppender
+log4j.appender.stdout.Target=System.out
+log4j.appender.stdout.layout=org.apache.log4j.SimpleLayout
diff --git a/public/gatk-utils/src/main/java/org/broadinstitute/gatk/utils/GenomeLoc.java b/public/gatk-utils/src/main/java/org/broadinstitute/gatk/utils/GenomeLoc.java
new file mode 100644
index 0000000..101796b
--- /dev/null
+++ b/public/gatk-utils/src/main/java/org/broadinstitute/gatk/utils/GenomeLoc.java
@@ -0,0 +1,657 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.utils;
+
+import com.google.java.contract.Ensures;
+import com.google.java.contract.Requires;
+import htsjdk.samtools.SAMFileHeader;
+import org.broadinstitute.gatk.utils.exceptions.ReviewedGATKException;
+
+import java.io.Serializable;
+import java.util.*;
+
+/**
+ * Created by IntelliJ IDEA.
+ * User: mdepristo
+ * Date: Mar 2, 2009
+ * Time: 8:50:11 AM
+ *
+ * Genome location representation.  It is *** 1 *** based closed.  Note that GenomeLocs start and stop values
+ * can be any positive or negative number, by design.  Bound validation is a feature of the GenomeLocParser,
+ * and not a fundamental constraint of the GenomeLoc
+ */
+public class GenomeLoc implements Comparable<GenomeLoc>, Serializable, HasGenomeLocation {
+    /**
+     * the basic components of a genome loc, its contig index,
+     * start and stop position, and (optionally) the contig name
+     */
+    protected final int contigIndex;
+    protected final int start;
+    protected final int stop;
+    protected final String contigName;
+
+    /**
+     * A static constant to use when referring to the unmapped section of a datafile
+     * file.  The unmapped region cannot be subdivided.  Only this instance of
+     * the object may be used to refer to the region, as '==' comparisons are used
+     * in comparators, etc.
+     */
+    // TODO - WARNING WARNING WARNING code somehow depends on the name of the contig being null!
+    public static final GenomeLoc UNMAPPED = new GenomeLoc((String)null);
+    public static final GenomeLoc WHOLE_GENOME = new GenomeLoc("all");
+
+    public static final boolean isUnmapped(GenomeLoc loc) {
+        return loc == UNMAPPED;
+    }
+
+    // --------------------------------------------------------------------------------------------------------------
+    //
+    // constructors
+    //
+    // --------------------------------------------------------------------------------------------------------------
+
+    @Requires({
+            "contig != null",
+            "contigIndex >= 0", // I believe we aren't allowed to create GenomeLocs without a valid contigIndex
+            "start <= stop"})
+    protected GenomeLoc( final String contig, final int contigIndex, final int start, final int stop ) {
+        this.contigName = contig;
+        this.contigIndex = contigIndex;
+        this.start = start;
+        this.stop = stop;
+    }
+
+    /** Unsafe constructor for special constant genome locs */
+    private GenomeLoc( final String contig ) {
+        this.contigName = contig;
+        this.contigIndex = -1;
+        this.start = 0;
+        this.stop = 0;
+    }
+
+    //
+    // Accessors
+    //
+    @Ensures("result != null")
+    public final GenomeLoc getLocation() { return this; }
+
+    public final GenomeLoc getStartLocation() { return new GenomeLoc(getContig(),getContigIndex(),getStart(),getStart()); }
+
+    public final GenomeLoc getStopLocation() { return new GenomeLoc(getContig(),getContigIndex(),getStop(),getStop()); }
+
+    /**
+     * @return the name of the contig of this GenomeLoc
+     */
+    public final String getContig() {
+        return this.contigName;
+    }
+
+    public final int getContigIndex() { return this.contigIndex; }
+    public final int getStart()    { return this.start; }
+    public final int getStop()     { return this.stop; }
+
+    @Ensures("result != null")
+    public final String toString()  {
+        if(GenomeLoc.isUnmapped(this)) return "unmapped";
+        if ( throughEndOfContigP() && atBeginningOfContigP() )
+            return getContig();
+        else if ( throughEndOfContigP() || getStart() == getStop() )
+            return String.format("%s:%d", getContig(), getStart());
+        else
+            return String.format("%s:%d-%d", getContig(), getStart(), getStop());
+    }
+
+    private boolean throughEndOfContigP() { return this.stop == Integer.MAX_VALUE; }
+
+    private boolean atBeginningOfContigP() { return this.start == 1; }
+
+    @Requires("that != null")
+    public final boolean disjointP(GenomeLoc that) {
+        return this.contigIndex != that.contigIndex || this.start > that.stop || that.start > this.stop;
+    }
+
+    @Requires("that != null")
+    public final boolean discontinuousP(GenomeLoc that) {
+        return this.contigIndex != that.contigIndex || (this.start - 1) > that.stop || (that.start - 1) > this.stop;
+    }
+
+    @Requires("that != null")
+    public final boolean overlapsP(GenomeLoc that) {
+        return ! disjointP( that );
+    }
+
+    @Requires("that != null")
+    public final boolean contiguousP(GenomeLoc that) {
+        return ! discontinuousP( that );
+    }
+
+    /**
+     * Return true if this GenomeLoc represents the UNMAPPED location
+     * @return
+     */
+    public final boolean isUnmapped() {
+        return isUnmapped(this);
+    }
+
+
+    /**
+     * Returns a new GenomeLoc that represents the entire span of this and that.  Requires that
+     * this and that GenomeLoc are contiguous and both mapped
+     */
+    @Requires({
+            "that != null",
+            "isUnmapped(this) == isUnmapped(that)"})
+    @Ensures("result != null")
+    public GenomeLoc merge( GenomeLoc that ) throws ReviewedGATKException {
+        if(GenomeLoc.isUnmapped(this) || GenomeLoc.isUnmapped(that)) {
+            if(! GenomeLoc.isUnmapped(this) || !GenomeLoc.isUnmapped(that))
+                throw new ReviewedGATKException("Tried to merge a mapped and an unmapped genome loc");
+            return UNMAPPED;
+        }
+
+        if (!(this.contiguousP(that))) {
+            throw new ReviewedGATKException("The two genome loc's need to be contiguous");
+        }
+
+        return new GenomeLoc(getContig(), this.contigIndex,
+                             Math.min( getStart(), that.getStart() ),
+                             Math.max( getStop(), that.getStop()) );
+    }
+
+    /**
+     * Returns a new GenomeLoc that represents the region between the endpoints of this and that. Requires that
+     * this and that GenomeLoc are both mapped.
+     */
+    @Requires({"that != null", "isUnmapped(this) == isUnmapped(that)"})
+    @Ensures("result != null")
+    public GenomeLoc endpointSpan(GenomeLoc that) throws ReviewedGATKException {
+        if(GenomeLoc.isUnmapped(this) || GenomeLoc.isUnmapped(that)) {
+            throw new ReviewedGATKException("Cannot get endpoint span for unmerged genome locs");
+        }
+
+        if ( ! this.getContig().equals(that.getContig()) ) {
+            throw new ReviewedGATKException("Cannot get endpoint span for genome locs on different contigs");
+        }
+
+        return new GenomeLoc(getContig(),this.contigIndex,Math.min(getStart(),that.getStart()),Math.max(getStop(),that.getStop()));
+    }
+
+    /**
+     * Splits the contig into to regions: [start,split point) and [split point, end].
+     * @param splitPoint The point at which to split the contig.  Must be contained in the given interval.
+     * @return A two element array consisting of the genome loc before the split and the one after.
+     */
+    public GenomeLoc[] split(final int splitPoint) {
+        if(splitPoint < getStart() || splitPoint > getStop())
+            throw new ReviewedGATKException(String.format("Unable to split contig %s at split point %d; split point is not contained in region.",this,splitPoint));
+        return new GenomeLoc[] { new GenomeLoc(getContig(),contigIndex,getStart(),splitPoint-1), new GenomeLoc(getContig(),contigIndex,splitPoint,getStop()) };
+    }
+
+    public GenomeLoc union( GenomeLoc that ) { return merge(that); }
+
+    @Requires("that != null")
+    @Ensures("result != null")
+    public GenomeLoc intersect( GenomeLoc that ) throws ReviewedGATKException {
+        if(GenomeLoc.isUnmapped(this) || GenomeLoc.isUnmapped(that)) {
+            if(! GenomeLoc.isUnmapped(this) || !GenomeLoc.isUnmapped(that))
+                throw new ReviewedGATKException("Tried to intersect a mapped and an unmapped genome loc");
+            return UNMAPPED;
+        }
+
+        if (!(this.overlapsP(that))) {
+            throw new ReviewedGATKException("GenomeLoc::intersect(): The two genome loc's need to overlap");
+        }
+
+        return new GenomeLoc(getContig(), this.contigIndex,
+                             Math.max(getStart(), that.getStart()),
+                             Math.min( getStop(), that.getStop()) );
+    }
+
+    @Requires("that != null")
+    public final List<GenomeLoc> subtract( final GenomeLoc that ) {
+        if(GenomeLoc.isUnmapped(this) || GenomeLoc.isUnmapped(that)) {
+            if(! GenomeLoc.isUnmapped(this) || !GenomeLoc.isUnmapped(that))
+                throw new ReviewedGATKException("Tried to intersect a mapped and an unmapped genome loc");
+            return Arrays.asList(UNMAPPED);
+        }
+
+        if (!(this.overlapsP(that))) {
+            throw new ReviewedGATKException("GenomeLoc::minus(): The two genome loc's need to overlap");
+        }
+
+        if (equals(that)) {
+            return Collections.emptyList();
+        } else if (containsP(that)) {
+            List<GenomeLoc> l = new ArrayList<GenomeLoc>(2);
+
+            /**
+             * we have to create two new region, one for the before part, one for the after
+             * The old region:
+             * |----------------- old region (g) -------------|
+             *        |----- to delete (e) ------|
+             *
+             * product (two new regions):
+             * |------|  + |--------|
+             *
+             */
+            int afterStop = this.getStop(), afterStart = that.getStop() + 1;
+            int beforeStop = that.getStart() - 1, beforeStart = this.getStart();
+            if (afterStop - afterStart >= 0) {
+                GenomeLoc after = new GenomeLoc(this.getContig(), getContigIndex(), afterStart, afterStop);
+                l.add(after);
+            }
+            if (beforeStop - beforeStart >= 0) {
+                GenomeLoc before = new GenomeLoc(this.getContig(), getContigIndex(), beforeStart, beforeStop);
+                l.add(before);
+            }
+
+            return l;
+        } else if (that.containsP(this)) {
+            /**
+             * e completely contains g, delete g, but keep looking, there may be more regions
+             * i.e.:
+             *   |--------------------- e --------------------|
+             *       |--- g ---|    |---- others ----|
+             */
+            return Collections.emptyList();   // don't need to do anything
+        } else {
+            /**
+             * otherwise e overlaps some part of g
+             *
+             * figure out which region occurs first on the genome.  I.e., is it:
+             * |------------- g ----------|
+             *       |------------- e ----------|
+             *
+             * or:
+             *       |------------- g ----------|
+             * |------------ e -----------|
+             *
+             */
+
+            GenomeLoc n;
+            if (that.getStart() < this.getStart()) {
+                n = new GenomeLoc(this.getContig(), getContigIndex(), that.getStop() + 1, this.getStop());
+            } else {
+                n = new GenomeLoc(this.getContig(), getContigIndex(), this.getStart(), that.getStart() - 1);
+            }
+
+            // replace g with the new region
+            return Arrays.asList(n);
+        }
+    }
+
+    @Requires("that != null")
+    public final boolean containsP(GenomeLoc that) {
+        return onSameContig(that) && getStart() <= that.getStart() && getStop() >= that.getStop();
+    }
+
+    @Requires("that != null")
+    public final boolean onSameContig(GenomeLoc that) {
+        return (this.contigIndex == that.contigIndex);
+    }
+
+    @Requires("that != null")
+    @Ensures("result >= 0")
+    public final int distance( final GenomeLoc that ) {
+        if ( this.onSameContig(that) )
+            return Math.abs(this.getStart() - that.getStart());
+        else
+            return Integer.MAX_VALUE;
+    }
+
+    @Requires({"left != null", "right != null"})
+    public final boolean isBetween( final GenomeLoc left, final GenomeLoc right ) {
+        return this.compareTo(left) > -1 && this.compareTo(right) < 1;
+    }
+
+    /**
+     * Tests whether this contig is completely before contig 'that'.
+     * @param that Contig to test against.
+     * @return true if this contig ends before 'that' starts; false if this is completely after or overlaps 'that'.
+     */
+    @Requires("that != null")
+    public final boolean isBefore( GenomeLoc that ) {
+        int comparison = this.compareContigs(that);
+        return ( comparison == -1 || ( comparison == 0 && this.getStop() < that.getStart() ));        
+    }
+
+    /**
+     * Tests whether this genome loc starts at the same position as that.
+     *
+     * i.e., do this and that have the same contig and the same start position
+     *
+     * @param that genome loc to compare to
+     * @return true if this and that have the same contig and the same start position
+     */
+    @Requires("that != null")
+    public final boolean startsAt( GenomeLoc that ) {
+        int comparison = this.compareContigs(that);
+        return comparison == 0 && this.getStart() == that.getStart();
+    }
+
+    /**
+     * Tests whether any portion of this contig is before that contig.
+     * @param that Other contig to test.
+     * @return True if the start of this contig is before the start of the that contig.
+     */
+    @Requires("that != null")
+    public final boolean startsBefore(final GenomeLoc that) {
+        int comparison = this.compareContigs(that);
+        return ( comparison == -1 || ( comparison == 0 && this.getStart() < that.getStart() ));
+    }
+
+    /**
+     * Tests whether this contig is completely after contig 'that'.
+     * @param that Contig to test against.
+     * @return true if this contig starts after 'that' ends; false if this is completely before or overlaps 'that'.
+     */
+    @Requires("that != null")
+    public final boolean isPast( GenomeLoc that ) {
+        int comparison = this.compareContigs(that);
+        return ( comparison == 1 || ( comparison == 0 && this.getStart() > that.getStop() ));
+    }
+
+    /**
+     * Return the minimum distance between any pair of bases in this and that GenomeLocs:
+     */
+    @Requires("that != null")
+    @Ensures("result >= 0")
+    public final int minDistance( final GenomeLoc that ) {
+        if (!this.onSameContig(that))
+            return Integer.MAX_VALUE;
+
+        int minDistance;
+        if (this.isBefore(that))
+            minDistance = distanceFirstStopToSecondStart(this, that);
+        else if (that.isBefore(this))
+            minDistance = distanceFirstStopToSecondStart(that, this);
+        else // this and that overlap [and possibly one contains the other]:
+            minDistance = 0;
+
+        return minDistance;
+    }
+
+    @Requires({
+            "locFirst != null",
+            "locSecond != null",
+            "locSecond.isPast(locFirst)"
+    })
+    @Ensures("result >= 0")
+    private static int distanceFirstStopToSecondStart(GenomeLoc locFirst, GenomeLoc locSecond) {
+        return locSecond.getStart() - locFirst.getStop();
+    }
+
+
+
+    /**
+     * Check to see whether two genomeLocs are equal.
+     * Note that this implementation ignores the contigInfo object.
+     * @param other Other contig to compare.
+     */
+    @Override
+    public boolean equals(Object other) {
+        if(other == null)
+            return false;
+        if(other instanceof GenomeLoc) {
+            GenomeLoc otherGenomeLoc = (GenomeLoc)other;
+            return this.contigIndex == otherGenomeLoc.contigIndex &&
+                   this.start == otherGenomeLoc.start &&
+                   this.stop == otherGenomeLoc.stop;
+        }
+        return false;
+    }
+    
+    @Override
+    public int hashCode() {
+        return start << 16 | stop << 4 | contigIndex;
+    }
+
+
+    /**
+     * conpare this genomeLoc's contig to another genome loc
+     * @param that the genome loc to compare contigs with
+     * @return 0 if equal, -1 if that.contig is greater, 1 if this.contig is greater
+     */
+    @Requires("that != null")
+    @Ensures("result == 0 || result == 1 || result == -1")
+    public final int compareContigs( GenomeLoc that ) {
+        if (this.contigIndex == that.contigIndex)
+            return 0;
+        else if (this.contigIndex > that.contigIndex)
+            return 1;
+        return -1;
+    }
+
+    @Requires("that != null")
+    @Ensures("result == 0 || result == 1 || result == -1")
+    public int compareTo( GenomeLoc that ) {
+        int result = 0;
+
+        if ( this == that ) {
+            result = 0;
+        }
+        else if(GenomeLoc.isUnmapped(this))
+            result = 1;
+        else if(GenomeLoc.isUnmapped(that))
+            result = -1;
+        else {
+            final int cmpContig = compareContigs(that);
+
+            if ( cmpContig != 0 ) {
+                result = cmpContig;
+            } else {
+                if ( this.getStart() < that.getStart() ) result = -1;
+                else if ( this.getStart() > that.getStart() ) result = 1;
+                // these have the same start, so check the ends
+                else if ( this.getStop() < that.getStop() ) result = -1;
+                else if ( this.getStop() > that.getStop() ) result = 1;
+            }
+        }
+
+        return result;
+    }
+
+    @Requires("that != null")
+    public boolean endsAt(GenomeLoc that) {
+        return (this.compareContigs(that) == 0) && ( this.getStop() == that.getStop() );
+    }
+
+    /**
+     * How many BPs are covered by this locus?
+     * @return Number of BPs covered by this locus.  According to the semantics of GenomeLoc, this should
+     *         never be < 1.
+     */
+    @Ensures("result > 0")
+    public int size() {
+        return stop - start + 1;
+    }
+
+    /**
+     * reciprocialOverlap: what is the min. percent of gl1 and gl2 covered by both
+     *
+     * gl1.s ---------- gk1.e
+     * gl2.s ---------- gl2.e
+     * 100%
+     *
+     * gl1.s ---------- gk1.e
+     *      gl2.s ---------- gl2.e
+     * 50%
+     *
+     * gl1.s ---------- gk1.e
+     *      gl2.s -------------------- gl2.e
+     * 25% (50% for gl1 but only 25% for gl2)
+     */
+    public final double reciprocialOverlapFraction(final GenomeLoc o) {
+        if ( overlapsP(o) )
+            return Math.min(overlapPercent(this, o), overlapPercent(o, this));
+        else
+            return 0.0;
+    }
+
+    private final static double overlapPercent(final GenomeLoc gl1, final GenomeLoc gl2) {
+        return (1.0 * gl1.intersect(gl2).size()) / gl1.size();
+    }
+
+    public long sizeOfOverlap( final GenomeLoc that ) {
+        return ( this.overlapsP(that) ? Math.min( getStop(), that.getStop() ) - Math.max( getStart(), that.getStart() ) + 1L : 0L );
+    }
+
+    /**
+     * Returns the maximum GenomeLoc of this and other
+     * @param other another non-null genome loc
+     * @return the max of this and other
+     */
+    public GenomeLoc max(final GenomeLoc other) {
+        final int cmp = this.compareTo(other);
+        return cmp == -1 ? other : this;
+    }
+
+    /**
+     * create a new genome loc from an existing loc, with a new start position
+     * Note that this function will NOT explicitly check the ending offset, in case someone wants to
+     * set the start of a new GenomeLoc pertaining to a read that goes off the end of the contig.
+     *
+     * @param loc   the old location
+     * @param start a new start position
+     *
+     * @return a newly allocated GenomeLoc as loc but with start == start
+     */
+    public GenomeLoc setStart(GenomeLoc loc, int start) {
+        return new GenomeLoc(loc.getContig(), loc.getContigIndex(), start, loc.getStop());
+    }
+
+    /**
+     * create a new genome loc from an existing loc, with a new stop position
+     * Note that this function will NOT explicitly check the ending offset, in case someone wants to
+     * set the stop of a new GenomeLoc pertaining to a read that goes off the end of the contig.
+     *
+     * @param loc  the old location
+     * @param stop a new stop position
+     *
+     * @return a newly allocated GenomeLoc as loc but with stop == stop
+     */
+    public GenomeLoc setStop(GenomeLoc loc, int stop) {
+        return new GenomeLoc(loc.getContig(), loc.getContigIndex(), loc.start, stop);
+    }
+
+    /**
+     * return a new genome loc, with an incremented position
+     *
+     * @return a newly allocated GenomeLoc as loc but with start == loc.getStart() + 1
+     */
+    public GenomeLoc incPos() {
+        return incPos(1);
+    }
+
+    /**
+     * return a new genome loc, with an incremented position
+     *
+     * @param by  how much to move the start and stop by
+     *
+     * @return a newly allocated GenomeLoc as loc but with start == loc.getStart() + by
+     */
+    public GenomeLoc incPos(int by) {
+        return new GenomeLoc(getContig(), getContigIndex(), start + by, stop + by);
+    }
+
+    /**
+     * Merges 2 *contiguous* locs into 1
+     *
+     * @param a   GenomeLoc #1
+     * @param b   GenomeLoc #2
+     * @return one merged loc
+     */
+    @Requires("a != null && b != null")
+    public static <T extends GenomeLoc> GenomeLoc merge(final T a, final T b) {
+        if ( isUnmapped(a) || isUnmapped(b) ) {
+            throw new ReviewedGATKException("Tried to merge unmapped genome locs");
+        }
+
+        if ( !(a.contiguousP(b)) ) {
+            throw new ReviewedGATKException("The two genome locs need to be contiguous");
+        }
+
+        return new GenomeLoc(a.getContig(), a.contigIndex, Math.min(a.getStart(), b.getStart()), Math.max(a.getStop(), b.getStop()));
+    }
+
+    /**
+     * Merges a list of *sorted* *contiguous* locs into 1
+     *
+     * @param sortedLocs a sorted list of contiguous locs
+     * @return one merged loc
+     */
+    @Requires("sortedLocs != null")
+    public static <T extends GenomeLoc> GenomeLoc merge(final SortedSet<T> sortedLocs) {
+        GenomeLoc result = null;
+
+        for ( GenomeLoc loc : sortedLocs ) {
+            if ( loc.isUnmapped() )
+                throw new ReviewedGATKException("Tried to merge unmapped genome locs");
+
+            if ( result == null )
+                result = loc;
+            else if ( !result.contiguousP(loc) )
+                throw new ReviewedGATKException("The genome locs need to be contiguous");
+            else
+                result = merge(result, loc);
+        }
+
+        return result;
+    }
+
+    /**
+     * Calculates the distance between two genomeLocs across contigs (if necessary).
+     *
+     * Returns minDistance(other) if in same contig.
+     * Works with intervals!
+     * Uses the SAMFileHeader to extract the size of the contigs and follows the order in the dictionary.
+     *
+     * @param other         the genome loc to compare to
+     * @param samFileHeader the contig information
+     * @return the sum of all the bases in between the genomeLocs, including entire contigs
+     */
+    public long distanceAcrossContigs(GenomeLoc other, SAMFileHeader samFileHeader) {
+        if (onSameContig(other))
+            return minDistance(other);
+
+        // add the distance from the first genomeLoc to the end of it's contig and the distance from the
+        // second genomeLoc to the beginning of it's contig.
+        long distance = 0;
+        if (contigIndex < other.contigIndex) {
+            distance += samFileHeader.getSequence(contigIndex).getSequenceLength() - stop;
+            distance += other.start;
+        } else {
+            distance += samFileHeader.getSequence(other.contigIndex).getSequenceLength() - other.stop;
+            distance += start;
+        }
+
+        // add any contig (in its entirety) in between the two genomeLocs
+        for (int i=Math.min(this.contigIndex, other.contigIndex) + 1; i < Math.max(this.contigIndex, other.contigIndex); i++) {
+            distance += samFileHeader.getSequence(i).getSequenceLength();
+        }
+        return distance;
+    }
+}
diff --git a/public/gatk-utils/src/main/java/org/broadinstitute/gatk/utils/HasGenomeLocation.java b/public/gatk-utils/src/main/java/org/broadinstitute/gatk/utils/HasGenomeLocation.java
new file mode 100644
index 0000000..d080d5b
--- /dev/null
+++ b/public/gatk-utils/src/main/java/org/broadinstitute/gatk/utils/HasGenomeLocation.java
@@ -0,0 +1,36 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.utils;
+
+import com.google.java.contract.Ensures;
+
+/**
+ * Indicates that this object has a genomic location and provides a systematic interface to get it.
+ */
+public interface HasGenomeLocation {
+    @Ensures("result != null")
+    public GenomeLoc getLocation();
+}
diff --git a/public/gatk-utils/src/main/java/org/broadinstitute/gatk/utils/SimpleTimer.java b/public/gatk-utils/src/main/java/org/broadinstitute/gatk/utils/SimpleTimer.java
new file mode 100644
index 0000000..39d6fa6
--- /dev/null
+++ b/public/gatk-utils/src/main/java/org/broadinstitute/gatk/utils/SimpleTimer.java
@@ -0,0 +1,261 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.utils;
+
+
+import com.google.java.contract.Ensures;
+import com.google.java.contract.Requires;
+
+import org.apache.log4j.Logger;
+
+import java.text.NumberFormat;
+import java.util.concurrent.TimeUnit;
+import static java.lang.Math.abs;
+
+/**
+ * A useful simple system for timing code with nano second resolution
+ *
+ * Note that this code is not thread-safe.  If you have a single timer
+ * being started and stopped by multiple threads you will need to protect the
+ * calls to avoid meaningless results of having multiple starts and stops
+ * called sequentially.
+ *
+ * This timer has been modified to provide better semantics for dealing with
+ * system-level checkpoint and restarting. Such events can cause the internal JVM
+ * clock to be reset, breaking timings based upon it. Whilst this is difficult to
+ * counter without getting explicit notice of checkpoint events, we try to moderate
+ * the symptoms through tracking the offset between the system clock and the JVM clock.
+ * If this offset grows drastically (greater than CLOCK_DRIFT), we infer a JVM restart
+ * and reset the timer.
+ *
+ * User: depristo
+ * Date: Dec 10, 2010
+ * Time: 9:07:44 AM
+ */
+public class SimpleTimer {
+    private final static Logger logger = Logger.getLogger(SimpleTimer.class);
+    protected static final double NANO_TO_SECOND_DOUBLE = 1.0 / TimeUnit.SECONDS.toNanos(1);
+    private static final long MILLI_TO_NANO= TimeUnit.MILLISECONDS.toNanos(1);
+    private static final ThreadLocal<NumberFormat> NUMBER_FORMAT = new ThreadLocal<NumberFormat>() {
+        @Override
+        protected NumberFormat initialValue() {
+            return NumberFormat.getIntegerInstance();
+        }
+    };
+
+    /**
+     * Allowable clock drift in nanoseconds.
+     */
+    private static final long CLOCK_DRIFT = TimeUnit.SECONDS.toNanos(5);
+    private final String name;
+
+    /**
+     * The difference between system time and JVM time at last sync.
+     * This is used to detect JVM checkpoint/restart events, and should be 
+     * reset when a JVM checkpoint/restart is detected.
+     */
+    private long nanoTimeOffset;
+
+    /**
+     * The elapsedTimeNano time in nanoSeconds of this timer.  The elapsedTimeNano time is the
+     * sum of times between starts/restrats and stops.
+     */
+    private long elapsedTimeNano = 0l;
+
+    /**
+     * The start time of the last start/restart in nanoSeconds
+     */
+    private long startTimeNano = 0l;
+
+    /**
+     * Is this timer currently running (i.e., the last call was start/restart)
+     */
+    private boolean running = false;
+
+    /**
+     * Creates an anonymous simple timer
+     */
+    public SimpleTimer() {
+        this("Anonymous");
+    }
+
+    /**
+     * Creates a simple timer named name
+     * @param name of the timer, must not be null
+     */
+    public SimpleTimer(final String name) {
+        if ( name == null ) throw new IllegalArgumentException("SimpleTimer name cannot be null");
+        this.name = name;
+
+        this.nanoTimeOffset = getNanoOffset();
+    }
+
+    /**
+     * @return the name associated with this timer
+     */
+    public synchronized String getName() {
+        return name;
+    }
+
+    /**
+     * Starts the timer running, and sets the elapsedTimeNano time to 0.  This is equivalent to
+     * resetting the time to have no history at all.
+     *
+     * @return this object, for programming convenience
+     */
+    @Ensures("elapsedTimeNano == 0l")
+    public synchronized SimpleTimer start() {
+        elapsedTimeNano = 0l;
+        return restart();
+    }
+
+    /**
+     * Starts the timer running, without resetting the elapsedTimeNano time.  This function may be
+     * called without first calling start().  The only difference between start and restart
+     * is that start resets the elapsedTimeNano time, while restart does not.
+     *
+     * @return this object, for programming convenience
+     */
+    public synchronized SimpleTimer restart() {
+        running = true;
+        startTimeNano = currentTimeNano();
+        nanoTimeOffset = getNanoOffset();
+        return this;
+    }
+
+    /**
+     * @return is this timer running?
+     */
+    public synchronized boolean isRunning() {
+        return running;
+    }
+
+    /**
+     * @return A convenience function to obtain the current time in milliseconds from this timer
+     */
+    public long currentTime() {
+        return System.currentTimeMillis();
+    }
+
+    /**
+     * @return A convenience function to obtain the current time in nanoSeconds from this timer
+     */
+    public long currentTimeNano() {
+        return System.nanoTime();
+    }
+
+    /**
+     * Stops the timer.  Increases the elapsedTimeNano time by difference between start and now.
+     * This method calls `ensureClockSync` to make sure that the JVM and system clocks
+     * are roughly in sync since the start of the timer. If they are not, then the time
+     * elapsed since the previous 'stop' will not be added to the timer.
+     *
+     * It's ok to call stop on a timer that's not running.  It has no effect on the timer.
+     *
+     * @return this object, for programming convenience
+     */
+    @Requires("startTimeNano != 0l")
+    public synchronized SimpleTimer stop() {
+        if ( running ) {
+            running = false;
+            if (ensureClockSync()) {
+                elapsedTimeNano += currentTimeNano() - startTimeNano;
+            }
+        }
+        return this;
+    }
+
+    /**
+     * Returns the total elapsedTimeNano time of all start/stops of this timer.  If the timer is currently
+     * running, includes the difference from currentTime() and the start as well
+     *
+     * @return this time, in seconds
+     */
+    public synchronized double getElapsedTime() {
+        return nanoToSecondsAsDouble(getElapsedTimeNano());
+    }
+
+    protected static double nanoToSecondsAsDouble(final long nano) {
+        return nano * NANO_TO_SECOND_DOUBLE;
+    }
+
+    /**
+     * @see #getElapsedTime() but returns the result in nanoseconds
+     *
+     * @return the elapsed time in nanoseconds
+     */
+    public synchronized long getElapsedTimeNano() {
+        if (running && ensureClockSync()) {
+            return currentTimeNano() - startTimeNano + elapsedTimeNano;
+        } else {
+            return elapsedTimeNano;
+        }
+    }
+
+    /**
+     * Add the elapsed time from toAdd to this elapsed time
+     *
+     * @param toAdd the timer whose elapsed time we want to add to this timer
+     */
+    public synchronized void addElapsed(final SimpleTimer toAdd) {
+        elapsedTimeNano += toAdd.getElapsedTimeNano();
+    }
+
+    /**
+     * Get the current offset of nano time from system time.
+     */
+    private static long getNanoOffset() {
+        return System.nanoTime() - (System.currentTimeMillis() * MILLI_TO_NANO);
+    }
+
+    /**
+     * Ensure that the JVM time has remained in sync with system time.
+     * This will also reset the clocks to avoid gradual drift.
+     *
+     * @return true if the clocks are in sync, false otherwise
+     */
+    private boolean ensureClockSync() {
+        final long currentOffset = getNanoOffset();
+        final long diff = abs(currentOffset - nanoTimeOffset);
+        final boolean ret = (diff <= CLOCK_DRIFT);
+        if (!ret) {
+            final NumberFormat numberFormat = NUMBER_FORMAT.get();
+            final String msg = String.format(
+                    "Clock drift of %s - %s = %s nanoseconds detected, vs. max allowable drift of %s. " +
+                            "Assuming checkpoint/restart event.",
+                    numberFormat.format(currentOffset),
+                    numberFormat.format(nanoTimeOffset),
+                    numberFormat.format(diff),
+                    numberFormat.format(CLOCK_DRIFT));
+            // Log message
+            logger.warn(msg);
+        }
+        // Reset the drift meter to stay in sync.
+        this.nanoTimeOffset = currentOffset;
+        return ret;
+    }
+
+}
diff --git a/public/gatk-utils/src/main/java/org/broadinstitute/gatk/utils/exceptions/GATKException.java b/public/gatk-utils/src/main/java/org/broadinstitute/gatk/utils/exceptions/GATKException.java
new file mode 100644
index 0000000..0eb0941
--- /dev/null
+++ b/public/gatk-utils/src/main/java/org/broadinstitute/gatk/utils/exceptions/GATKException.java
@@ -0,0 +1,64 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.utils.exceptions;
+
+/**
+ *
+ * User: aaron
+ * Date: Apr 6, 2009
+ * Time: 8:11:12 PM
+ *
+ * The Broad Institute
+ * SOFTWARE COPYRIGHT NOTICE AGREEMENT 
+ * This software and its documentation are copyright 2009 by the
+ * Broad Institute/Massachusetts Institute of Technology. All rights are reserved.
+ *
+ * This software is supplied without any warranty or guaranteed support whatsoever. Neither
+ * the Broad Institute nor MIT can be responsible for its use, misuse, or functionality.
+ *
+ */
+
+
+/**
+ * @author aaron
+ * @version 1.0
+ * @date Apr 6, 2009
+ * <p/>
+ * Class GATKException
+ * <p/>
+ * This exception allows us to filter out exceptions that come from core GATK code, and those that
+ * are not homegrown..
+ */
+public class GATKException extends RuntimeException {
+    public GATKException(String msg) {
+        super(msg);
+    }
+
+    public GATKException(String message, Throwable throwable) {
+        super(message, throwable);
+    }
+}
+
diff --git a/public/gatk-utils/src/main/java/org/broadinstitute/gatk/utils/exceptions/ReviewedGATKException.java b/public/gatk-utils/src/main/java/org/broadinstitute/gatk/utils/exceptions/ReviewedGATKException.java
new file mode 100644
index 0000000..56dfc69
--- /dev/null
+++ b/public/gatk-utils/src/main/java/org/broadinstitute/gatk/utils/exceptions/ReviewedGATKException.java
@@ -0,0 +1,42 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.utils.exceptions;
+
+/**
+ * A trivial extension around GATKException to mark exceptions that have been reviewed for correctness,
+ * completeness, etc.  By using this exception you are saying "this is the right error message".  GATKException
+ * is now just a catch all for lazy users.
+ */
+public class ReviewedGATKException extends GATKException {
+    public ReviewedGATKException(String msg) {
+        super(msg);
+    }
+
+    public ReviewedGATKException(String message, Throwable throwable) {
+        super(message, throwable);
+    }
+}
+
diff --git a/public/gatk-utils/src/main/java/org/broadinstitute/gatk/utils/package-info.java b/public/gatk-utils/src/main/java/org/broadinstitute/gatk/utils/package-info.java
new file mode 100644
index 0000000..8a42dff
--- /dev/null
+++ b/public/gatk-utils/src/main/java/org/broadinstitute/gatk/utils/package-info.java
@@ -0,0 +1,26 @@
+/*
+* Copyright (c) 2012 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 org.broadinstitute.gatk.utils;
\ No newline at end of file
diff --git a/public/gatk-utils/src/main/resources/org/broadinstitute/gatk/utils/pairhmm/libVectorLoglessPairHMM.so b/public/gatk-utils/src/main/resources/org/broadinstitute/gatk/utils/pairhmm/libVectorLoglessPairHMM.so
new file mode 100644
index 0000000..a27f4e6
Binary files /dev/null and b/public/gatk-utils/src/main/resources/org/broadinstitute/gatk/utils/pairhmm/libVectorLoglessPairHMM.so differ
diff --git a/public/gsalib/pom.xml b/public/gsalib/pom.xml
new file mode 100644
index 0000000..1ce5b4d
--- /dev/null
+++ b/public/gsalib/pom.xml
@@ -0,0 +1,45 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+    <modelVersion>4.0.0</modelVersion>
+
+    <parent>
+        <groupId>org.broadinstitute.gatk</groupId>
+        <artifactId>gatk-aggregator</artifactId>
+        <version>3.3</version>
+        <relativePath>../..</relativePath>
+    </parent>
+
+    <artifactId>gsalib</artifactId>
+    <packaging>pom</packaging>
+    <name>GATK GSALib</name>
+
+    <properties>
+        <gatk.basedir>${project.basedir}/../..</gatk.basedir>
+        <gsalib.packagedir>org/broadinstitute/gatk/utils/R</gsalib.packagedir>
+        <gsalib.filename>gsalib.tar.gz</gsalib.filename>
+    </properties>
+
+    <build>
+        <plugins>
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-assembly-plugin</artifactId>
+                <executions>
+                    <execution>
+                        <id>gsalib-assembly</id>
+                        <goals>
+                            <goal>single</goal>
+                        </goals>
+                        <phase>${gatk.generate-resources.phase}</phase>
+                        <configuration>
+                            <appendAssemblyId>false</appendAssemblyId>
+                            <descriptors>
+                                <descriptor>src/assembly/gsalib.xml</descriptor>
+                            </descriptors>
+                        </configuration>
+                    </execution>
+                </executions>
+            </plugin>
+        </plugins>
+    </build>
+</project>
diff --git a/public/gsalib/src/R/DESCRIPTION b/public/gsalib/src/R/DESCRIPTION
new file mode 100644
index 0000000..229204f
--- /dev/null
+++ b/public/gsalib/src/R/DESCRIPTION
@@ -0,0 +1,13 @@
+Package: gsalib
+Type: Package
+Title: Utility functions
+Version: 1.0
+Date: 2010-10-02
+Imports: gplots, ggplot2, png
+Author: Kiran Garimella
+Maintainer: Mauricio Carneiro <carneiro at broadinstitute.org>
+BugReports: http://gatkforums.broadinstitute.org
+Description: Utility functions for GATK NGS analyses
+License: MIT + file LICENSE
+LazyLoad: yes
+NeedsCompilation: no
diff --git a/public/gsalib/src/R/LICENSE b/public/gsalib/src/R/LICENSE
new file mode 100644
index 0000000..59f3937
--- /dev/null
+++ b/public/gsalib/src/R/LICENSE
@@ -0,0 +1,2 @@
+YEAR: 2012
+COPYRIGHT HOLDER: The Broad Institute
\ No newline at end of file
diff --git a/public/gsalib/src/R/NAMESPACE b/public/gsalib/src/R/NAMESPACE
new file mode 100644
index 0000000..0bfe475
--- /dev/null
+++ b/public/gsalib/src/R/NAMESPACE
@@ -0,0 +1 @@
+exportPattern("^[^\\.]")
\ No newline at end of file
diff --git a/public/gsalib/src/R/R/gsa.error.R b/public/gsalib/src/R/R/gsa.error.R
new file mode 100644
index 0000000..1c6a560
--- /dev/null
+++ b/public/gsalib/src/R/R/gsa.error.R
@@ -0,0 +1,12 @@
+gsa.error <- function(message) {
+    message("");
+    gsa.message("Error: **********");
+    gsa.message(sprintf("Error: %s", message));
+    gsa.message("Error: **********");
+    message("");
+
+    traceback();
+
+    message("");
+    stop(message, call. = FALSE);
+}
diff --git a/public/gsalib/src/R/R/gsa.getargs.R b/public/gsalib/src/R/R/gsa.getargs.R
new file mode 100644
index 0000000..94613bf
--- /dev/null
+++ b/public/gsalib/src/R/R/gsa.getargs.R
@@ -0,0 +1,116 @@
+.gsa.getargs.usage <- function(argspec, doc) {
+    cargs = commandArgs();
+
+    usage = "Usage:";
+
+    fileIndex = grep("--file=", cargs);
+    if (length(fileIndex) > 0) {
+        progname = gsub("--file=", "", cargs[fileIndex[1]]);
+
+        usage = sprintf("Usage: Rscript %s [arguments]", progname);
+
+        if (!is.na(doc)) {
+            message(sprintf("%s: %s\n", progname, doc));
+        }
+    }
+
+    message(usage);
+
+    for (argname in names(argspec)) {
+        key = argname;
+        defaultValue = 0;
+        doc = "";
+
+        if (is.list(argspec[[argname]])) {
+            defaultValue = argspec[[argname]]$value;
+            doc = argspec[[argname]]$doc;
+        }
+
+        message(sprintf(" -%-10s\t[default: %s]\t%s", key, defaultValue, doc));
+    }
+
+    message("");
+
+    stop(call. = FALSE);
+}
+
+gsa.getargs <- function(argspec, doc = NA) {
+    argsenv = new.env();
+
+    for (argname in names(argspec)) {
+        value = 0;
+        if (is.list(argspec[[argname]])) {
+            value = argspec[[argname]]$value;
+        } else {
+            value = argspec[[argname]];
+        }
+
+        assign(argname, value, envir=argsenv);
+    }
+
+    if (interactive()) {
+        for (argname in names(argspec)) {
+            value = get(argname, envir=argsenv);
+
+            if (is.na(value) | is.null(value)) {
+                if (exists("cmdargs")) {
+                    assign(argname, cmdargs[[argname]], envir=argsenv);
+                } else {
+                    assign(argname, readline(sprintf("Please enter a value for '%s': ", argname)), envir=argsenv);
+                }
+            } else {
+                assign(argname, value, envir=argsenv);
+            }
+        }
+    } else {
+        cargs = commandArgs(TRUE);
+
+        if (length(cargs) == 0) {
+            .gsa.getargs.usage(argspec, doc);
+        }
+
+        for (i in 1:length(cargs)) {
+            if (length(grep("^-", cargs[i], ignore.case=TRUE)) > 0) {
+                key = gsub("-", "", cargs[i]);
+                value = cargs[i+1];
+
+                if (key == "h" | key == "help") {
+                    .gsa.getargs.usage(argspec, doc);
+                }
+
+                if (length(grep("^[\\d\\.e\\+\\-]+$", value, perl=TRUE, ignore.case=TRUE)) > 0) {
+                    value = as.numeric(value);
+                }
+                
+                assign(key, value, envir=argsenv);
+            }
+        }
+    }
+
+    args = as.list(argsenv);
+
+    isMissingArgs = 0;
+    missingArgs = c();
+    
+    for (arg in names(argspec)) {
+        if (is.na(args[[arg]]) | is.null(args[[arg]])) {
+            gsa.warn(sprintf("Value for required argument '-%s' was not specified", arg));
+
+            isMissingArgs = 1;
+            missingArgs = c(missingArgs, arg);
+        }
+    }
+
+    if (isMissingArgs) {
+        gsa.error(
+            paste(
+                "Missing required arguments: -",
+                paste(missingArgs, collapse=" -"),
+                ".  Specify -h or -help to this script for a list of available arguments.",
+                sep=""
+            )
+        );
+    }
+
+    args;
+}
diff --git a/public/gsalib/src/R/R/gsa.message.R b/public/gsalib/src/R/R/gsa.message.R
new file mode 100644
index 0000000..a2b909d
--- /dev/null
+++ b/public/gsalib/src/R/R/gsa.message.R
@@ -0,0 +1,3 @@
+gsa.message <- function(message) {
+    message(sprintf("[gsalib] %s", message));
+}
diff --git a/public/gsalib/src/R/R/gsa.plot.venn.R b/public/gsalib/src/R/R/gsa.plot.venn.R
new file mode 100644
index 0000000..b1353cc
--- /dev/null
+++ b/public/gsalib/src/R/R/gsa.plot.venn.R
@@ -0,0 +1,50 @@
+gsa.plot.venn <-
+function(a, b, c=0, a_and_b, a_and_c=0, b_and_c=0,
+                     col=c("#FF6342", "#63C6DE", "#ADDE63"),
+                     pos=c(0.20, 0.20, 0.80, 0.82),
+                     debug=0
+                    ) {
+    library(png);
+    library(graphics);
+
+    # Set up properties
+    for (i in 1:length(col)) {
+        rgbcol = col2rgb(col[i]);
+        col[i] = sprintf("%02X%02X%02X", rgbcol[1], rgbcol[2], rgbcol[3]);
+    }
+
+    chco = paste(col[1], col[2], col[3], sep=",");
+    chd = paste(a, b, c, a_and_b, a_and_c, b_and_c, sep=",");
+
+    props = c(
+        'cht=v',
+        'chs=525x525',
+        'chds=0,10000000000',
+        paste('chco=', chco, sep=""),
+        paste('chd=t:', chd, sep="")
+    );
+    proplist = paste(props[1], props[2], props[3], props[4], props[5], sep='&');
+
+    # Get the venn diagram (as a temporary file)
+    filename = tempfile("venn");
+    cmd = paste("wget -O ", filename, " 'http://chart.apis.google.com/chart?", proplist, "' > /dev/null 2>&1", sep="");
+
+    if (debug == 1) {
+        print(cmd);
+    }
+    system(cmd);
+
+    # Render the temp png file into a plotting frame
+    a = readPNG(filename);
+    
+    plot(0, 0, type="n", xaxt="n", yaxt="n", bty="n", xlim=c(0, 1), ylim=c(0, 1), xlab="", ylab="");
+    if (c == 0 || a >= b) {
+        rasterImage(a, pos[1], pos[2], pos[3], pos[4]);
+    } else {
+        rasterImage(a, 0.37+pos[1], 0.37+pos[2], 0.37+pos[3], 0.37+pos[4], angle=180);
+    }
+
+    # Clean up!
+    unlink(filename);
+}
+
diff --git a/public/gsalib/src/R/R/gsa.read.eval.R b/public/gsalib/src/R/R/gsa.read.eval.R
new file mode 100644
index 0000000..f1d4909
--- /dev/null
+++ b/public/gsalib/src/R/R/gsa.read.eval.R
@@ -0,0 +1,83 @@
+.gsa.attemptToLoadFile <- function(filename) {
+    file = NA;
+
+    if (file.exists(filename) & file.info(filename)$size > 500) {
+        file = read.csv(filename, header=TRUE, comment.char="#");
+    }
+
+    file;
+}
+
+gsa.read.eval <-
+function(evalRoot) {
+    fileAlleleCountStats = paste(evalRoot, ".AlleleCountStats.csv", sep="");
+    fileCompOverlap = paste(evalRoot, ".Comp_Overlap.csv", sep="");
+    fileCountVariants = paste(evalRoot, ".Count_Variants.csv", sep="");
+    fileGenotypeConcordance = paste(evalRoot, ".Genotype_Concordance.csv", sep="");
+    fileMetricsByAc = paste(evalRoot, ".MetricsByAc.csv", sep="");
+    fileMetricsBySample = paste(evalRoot, ".MetricsBySample.csv", sep="");
+    fileQuality_Metrics_by_allele_count = paste(evalRoot, ".Quality_Metrics_by_allele_count.csv", sep="");
+    fileQualityScoreHistogram = paste(evalRoot, ".QualityScoreHistogram.csv", sep="");
+    fileSampleStatistics = paste(evalRoot, ".Sample_Statistics.csv", sep="");
+    fileSampleSummaryStatistics = paste(evalRoot, ".Sample_Summary_Statistics.csv", sep="");
+    fileSimpleMetricsBySample = paste(evalRoot, ".SimpleMetricsBySample.csv", sep="");
+    fileTi_slash_Tv_Variant_Evaluator = paste(evalRoot, ".Ti_slash_Tv_Variant_Evaluator.csv", sep="");
+    fileTiTvStats = paste(evalRoot, ".TiTvStats.csv", sep="");
+    fileVariant_Quality_Score = paste(evalRoot, ".Variant_Quality_Score.csv", sep="");
+
+    eval = list(
+        AlleleCountStats = NA,
+        CompOverlap = NA,
+        CountVariants = NA,
+        GenotypeConcordance = NA,
+        MetricsByAc = NA,
+        MetricsBySample = NA,
+        Quality_Metrics_by_allele_count = NA,
+        QualityScoreHistogram = NA,
+        SampleStatistics = NA,
+        SampleSummaryStatistics = NA,
+        SimpleMetricsBySample = NA,
+        TiTv = NA,
+        TiTvStats = NA,
+        Variant_Quality_Score = NA,
+
+        CallsetNames = c(),
+        CallsetOnlyNames = c(),
+        CallsetFilteredNames = c()
+    );
+
+    eval$AlleleCountStats                = .gsa.attemptToLoadFile(fileAlleleCountStats);
+    eval$CompOverlap                     = .gsa.attemptToLoadFile(fileCompOverlap);
+    eval$CountVariants                   = .gsa.attemptToLoadFile(fileCountVariants);
+    eval$GenotypeConcordance             = .gsa.attemptToLoadFile(fileGenotypeConcordance);
+    eval$MetricsByAc                     = .gsa.attemptToLoadFile(fileMetricsByAc);
+    eval$MetricsBySample                 = .gsa.attemptToLoadFile(fileMetricsBySample);
+    eval$Quality_Metrics_by_allele_count = .gsa.attemptToLoadFile(fileQuality_Metrics_by_allele_count);
+    eval$QualityScoreHistogram           = .gsa.attemptToLoadFile(fileQualityScoreHistogram);
+    eval$SampleStatistics                = .gsa.attemptToLoadFile(fileSampleStatistics);
+    eval$SampleSummaryStatistics         = .gsa.attemptToLoadFile(fileSampleSummaryStatistics);
+    eval$SimpleMetricsBySample           = .gsa.attemptToLoadFile(fileSimpleMetricsBySample);
+    eval$TiTv                            = .gsa.attemptToLoadFile(fileTi_slash_Tv_Variant_Evaluator);
+    eval$TiTvStats                       = .gsa.attemptToLoadFile(fileTiTvStats);
+    eval$Variant_Quality_Score           = .gsa.attemptToLoadFile(fileVariant_Quality_Score);
+
+    uniqueJexlExpressions = unique(eval$TiTv$jexl_expression);
+    eval$CallsetOnlyNames = as.vector(uniqueJexlExpressions[grep("FilteredIn|Intersection|none", uniqueJexlExpressions, invert=TRUE, ignore.case=TRUE)]);
+    eval$CallsetNames = as.vector(gsub("-only", "", eval$CallsetOnlyNames));
+    eval$CallsetFilteredNames = as.vector(c(
+        paste(gsub("^(\\w)", "In\\U\\1", eval$CallsetNames[1], perl=TRUE), "-Filtered", gsub("^(\\w)", "In\\U\\1", eval$CallsetNames[2], perl=TRUE), sep=""),
+        paste(gsub("^(\\w)", "In\\U\\1", eval$CallsetNames[2], perl=TRUE), "-Filtered", gsub("^(\\w)", "In\\U\\1", eval$CallsetNames[1], perl=TRUE), sep=""))
+    );
+
+    if (!(eval$CallsetFilteredNames[1] %in% unique(eval$TiTv$jexl_expression))) {
+        eval$CallsetFilteredNames[1] = paste("In", eval$CallsetNames[1], "-FilteredIn", eval$CallsetNames[2], sep="");
+    }
+
+    if (!(eval$CallsetFilteredNames[2] %in% unique(eval$TiTv$jexl_expression))) {
+        eval$CallsetFilteredNames[2] = paste("In", eval$CallsetNames[2], "-FilteredIn", eval$CallsetNames[1], sep="");
+        #eval$CallsetFilteredNames[2] = paste(gsub("^(\\w)", "In", eval$CallsetNames[2], perl=TRUE), "-Filtered", gsub("^(\\w)", "In", eval$CallsetNames[1], perl=TRUE), sep="");
+    }
+
+    eval;
+}
+
diff --git a/public/gsalib/src/R/R/gsa.read.gatkreport.R b/public/gsalib/src/R/R/gsa.read.gatkreport.R
new file mode 100644
index 0000000..eba94c0
--- /dev/null
+++ b/public/gsalib/src/R/R/gsa.read.gatkreport.R
@@ -0,0 +1,196 @@
+# Load a table into the specified environment.  Make sure that each new table gets a unique name (this allows one to cat a bunch of tables with the same name together and load them into R without each table overwriting the last.
+.gsa.assignGATKTableToEnvironment <- function(tableName, tableHeader, tableRows, tableEnv) {
+    d = data.frame(tableRows, row.names=NULL, stringsAsFactors=FALSE);
+    colnames(d) = tableHeader;
+    
+    for (i in 1:ncol(d)) {
+        # use the general type.convert infrastructure of read.table to convert column data to R types 
+        v = type.convert(d[,i])
+        d[,i] = v;
+    }
+    
+    usedNames = ls(envir=tableEnv, pattern=tableName);
+    
+    if (length(usedNames) > 0) {
+        tableName = paste(tableName, ".", length(usedNames), sep="");
+    }
+    
+    assign(tableName, d, envir=tableEnv);
+}
+
+# Read a fixed width line of text into a list.
+.gsa.splitFixedWidth <- function(line, columnStarts) {
+    splitStartStop <- function(x) {
+        x = substring(x, starts, stops);
+        x = gsub("^[[:space:]]+|[[:space:]]+$", "", x);
+        x;
+    }
+    
+    starts = c(1, columnStarts);
+    stops = c(columnStarts - 1, nchar(line));
+    
+    sapply(line, splitStartStop)[,1];
+}
+
+# Old implementaton for v0.*
+gsa.read.gatkreportv0 <- function(lines) {
+    
+    tableEnv = new.env();
+    
+    tableName = NA;
+    tableHeader = c();
+    tableRows = c();
+    version = NA;
+    
+    for (line in lines) {
+        if (length(grep("^##:GATKReport.v", line, ignore.case=TRUE)) > 0) {
+            headerFields = unlist(strsplit(line, "[[:space:]]+"));
+            
+            if (!is.na(tableName)) {
+                .gsa.assignGATKTableToEnvironment(tableName, tableHeader, tableRows, tableEnv);
+            }
+            
+            tableName = headerFields[2];
+            tableHeader = c();
+            tableRows = c();
+            
+            # For differences in versions see
+            #   $STING_HOME/public/java/src/org/broadinstitute/sting/gatk/report/GATKReportVersion.java
+            if (length(grep("^##:GATKReport.v0.1[[:space:]]+", line, ignore.case=TRUE)) > 0) {
+                version = "v0.1";
+                
+            } else if (length(grep("^##:GATKReport.v0.2[[:space:]]+", line, ignore.case=TRUE)) > 0) {
+                version = "v0.2";
+                columnStarts = c();
+                
+            }
+            
+        } else if (length(grep("^[[:space:]]*$", line)) > 0 | length(grep("^[[:space:]]*#", line)) > 0) {
+            # do nothing
+        } else if (!is.na(tableName)) {
+            
+            if (version == "v0.1") {
+                row = unlist(strsplit(line, "[[:space:]]+"));
+                
+            } else if (version == "v0.2") {
+                if (length(tableHeader) == 0) {
+                    headerChars = unlist(strsplit(line, ""));
+                    # Find the first position of non space characters, excluding the first character
+                    columnStarts = intersect(grep("[[:space:]]", headerChars, invert=TRUE), grep("[[:space:]]", headerChars) + 1);
+                }
+                
+                row = .gsa.splitFixedWidth(line, columnStarts);
+            }
+            
+            if (length(tableHeader) == 0) {
+                tableHeader = row;
+            } else {
+                tableRows = rbind(tableRows, row);
+            }
+        }
+    }
+    
+    if (!is.na(tableName)) {
+        .gsa.assignGATKTableToEnvironment(tableName, tableHeader, tableRows, tableEnv);
+    }
+    
+    gatkreport = as.list(tableEnv, all.names=TRUE);
+}
+
+# Load all GATKReport v1 tables from file
+gsa.read.gatkreportv1 <- function(lines) {
+  #print("loading with optimized v1 reader")
+  nLines = length(lines)
+  tableEnv = new.env();
+  
+  tableName = NA;
+  tableHeader = c();
+  tableRows = NULL;
+  version = "";
+  rowCount = 0
+  headerRowCount = -1;
+  
+  finishTable <- function() {
+    if ( rowCount == 1 )
+      # good I hate R.  Work around to avoid collapsing into an unstructured vector when 
+      # there's only 1 row
+      sub <- t(as.matrix(tableRows[1:rowCount,]))
+    else
+      sub <- tableRows[1:rowCount,]
+    .gsa.assignGATKTableToEnvironment(tableName, tableHeader, sub, tableEnv);
+  }
+  
+  for (line in lines) {
+    
+    if (length(grep("^#:GATKReport.v1", line, ignore.case=TRUE)) > 0) {
+      version = "v1.0";
+      headerRowCount = 0;
+    }
+    
+    if ( (headerRowCount %% 2 == 1) && (version == "v1.0") ) {
+      #print("Trying to start a table with line:");
+      #print(line);
+      
+      #Get table header
+      headerFields = unlist(strsplit(line, ":"));
+      
+      if (!is.na(tableName)) {
+        finishTable()
+      }
+      
+      tableName = headerFields[3];
+      tableHeader = c();
+      tableRows = NULL
+      rowCount = 0
+      
+      columnStarts = c();
+    }
+    
+    if (length(grep("^#:GATKTable", line, ignore.case=TRUE)) > 0) {
+      headerRowCount = headerRowCount+1;
+      #print("Header Row count is at:")
+      #print(headerRowCount);
+    } else if (!is.na(tableName)) {
+      if ( version == "v1.0") {
+        if (length(tableHeader) == 0) {
+          headerChars = unlist(strsplit(line, ""));
+          # Find the first position of non space characters, excluding the first character
+          columnStarts = intersect(grep("[[:space:]]", headerChars, invert=TRUE), grep("[[:space:]]", headerChars) + 1);
+          tableRows = matrix(nrow=nLines, ncol=length(columnStarts)+1);
+        }
+        
+        row = .gsa.splitFixedWidth(line, columnStarts);
+      }
+      
+      if (length(tableHeader) == 0) {
+        tableHeader = row;
+      } else if ( nchar(line) > 0 ) {
+        rowCount = rowCount + 1
+        tableRows[rowCount,] <- row
+      }
+    }
+  }
+  
+  if (!is.na(tableName)) {
+    finishTable()
+  }
+  
+  gatkreport = as.list(tableEnv, all.names=TRUE);
+}
+
+# Load all GATKReport tables from a file
+gsa.read.gatkreport <- function(filename) {
+    con = file(filename, "r", blocking = TRUE);
+    lines = readLines(con);
+    close(con);
+    
+    # get first line
+    line = lines[1];
+    
+    if (length(grep("^#:GATKReport.v1", line, ignore.case=TRUE)) > 0) {
+        gsa.read.gatkreportv1(lines)
+    }
+    else if (length(grep("^##:GATKReport.v0", line, ignore.case=TRUE)) > 0) {
+        gsa.read.gatkreportv0(lines)
+    }
+}
diff --git a/public/gsalib/src/R/R/gsa.read.squidmetrics.R b/public/gsalib/src/R/R/gsa.read.squidmetrics.R
new file mode 100644
index 0000000..39fa1ad
--- /dev/null
+++ b/public/gsalib/src/R/R/gsa.read.squidmetrics.R
@@ -0,0 +1,28 @@
+gsa.read.squidmetrics = function(project, bylane = FALSE) {
+    suppressMessages(library(ROracle));
+
+    drv = dbDriver("Oracle");
+    con = dbConnect(drv, "REPORTING/REPORTING at ora01:1521/SEQPROD");
+
+    if (bylane) {
+        statement = paste("SELECT * FROM ILLUMINA_PICARD_METRICS WHERE \"Project\" = '", project, "'", sep="");
+        print(statement);
+
+        rs  = dbSendQuery(con, statement = statement);
+        d = fetch(rs, n=-1);
+        dbHasCompleted(rs);
+        dbClearResult(rs);
+    } else {
+        statement = paste("SELECT * FROM ILLUMINA_SAMPLE_STATUS_AGG WHERE \"Project\" = '", project, "'", sep="");
+        print(statement);
+
+        rs = dbSendQuery(con, statement = statement);
+        d = fetch(rs, n=-1);
+        dbHasCompleted(rs);
+        dbClearResult(rs);
+    }
+
+    oraCloseDriver(drv);
+
+    subset(d, Project == project);
+}
diff --git a/public/gsalib/src/R/R/gsa.read.vcf.R b/public/gsalib/src/R/R/gsa.read.vcf.R
new file mode 100644
index 0000000..5beb645
--- /dev/null
+++ b/public/gsalib/src/R/R/gsa.read.vcf.R
@@ -0,0 +1,23 @@
+gsa.read.vcf <- function(vcffile, skip=0, nrows=-1, expandGenotypeFields = FALSE) {
+    headers = readLines(vcffile, n=100);
+    headerline = headers[grep("#CHROM", headers)];
+    header = unlist(strsplit(gsub("#", "", headerline), "\t"))
+    
+    d = read.table(vcffile, header=FALSE, skip=skip, nrows=nrows, stringsAsFactors=FALSE);
+    colnames(d) = header;
+
+    if (expandGenotypeFields) {
+        columns = ncol(d);
+
+        offset = columns + 1;
+        for (sampleIndex in 10:columns) {
+            gt = unlist(lapply(strsplit(d[,sampleIndex], ":"), function(x) x[1]));
+            d[,offset] = gt;
+            colnames(d)[offset] = sprintf("%s.GT", colnames(d)[sampleIndex]);
+
+            offset = offset + 1;
+        }
+    }
+
+    return(d);
+}
diff --git a/public/gsalib/src/R/R/gsa.variantqc.utils.R b/public/gsalib/src/R/R/gsa.variantqc.utils.R
new file mode 100644
index 0000000..507b336
--- /dev/null
+++ b/public/gsalib/src/R/R/gsa.variantqc.utils.R
@@ -0,0 +1,246 @@
+library(gplots)
+library(ggplot2)
+library(tools)
+
+# -------------------------------------------------------
+# Utilities for displaying multiple plots per page
+# -------------------------------------------------------
+
+distributeGraphRows <- function(graphs, heights = c()) {
+  # Viewport layout 2 graphs top to bottom with given relative heights
+  #
+  #
+  if (length(heights) == 0) {
+    heights <- rep.int(1, length(graphs))
+  }
+  heights <- heights[!is.na(graphs)]
+  graphs <- graphs[!is.na(graphs)]
+  numGraphs <- length(graphs)
+  Layout <- grid.layout(nrow = numGraphs, ncol = 1, heights=heights)
+  grid.newpage()
+  pushViewport(viewport(layout = Layout))
+  subplot <- function(x) viewport(layout.pos.row = x, layout.pos.col = 1)
+  for (i in 1:numGraphs) {
+    print(graphs[[i]], vp = subplot(i))
+  }
+}
+
+distributeLogGraph <- function(graph, xName) {
+  continuousGraph <- graph + scale_x_continuous(xName)
+  logGraph <- graph + scale_x_log10(xName) + ggtitle("")
+  distributeGraphRows(list(continuousGraph, logGraph))
+}
+
+distributePerSampleGraph <- function(perSampleGraph, distGraph, ratio=c(2,1)) {
+  distributeGraphRows(list(perSampleGraph, distGraph), ratio)
+}
+
+removeExtraStrats <- function(variantEvalDataFrame, moreToRemove=c()) {
+  # Remove the standard extra stratification columns FunctionalClass, Novelty, and others in moreToRemove from the variantEvalDataFrame
+  #
+  # Only keeps the column marked with "all" for each removed column
+  #
+  for ( toRemove in c("FunctionalClass", "Novelty", moreToRemove) ) {
+    if (toRemove %in% colnames(variantEvalDataFrame)) {
+      variantEvalDataFrame <- variantEvalDataFrame[variantEvalDataFrame[[toRemove]] == "all",]
+    }
+  }
+  variantEvalDataFrame    
+}
+
+openPDF <- function(outputPDF) {
+  # Open the outputPDF file with standard dimensions, if outputPDF is not NA
+  if ( ! is.na(outputPDF) ) {
+    pdf(outputPDF, height=8.5, width=11)
+  }
+}
+
+closePDF <- function(outputPDF) {
+  # close the outputPDF file if not NA, and try to compact the PDF if possible
+  if ( ! is.na(outputPDF) ) {
+    dev.off()
+    if (exists("compactPDF")) {
+      print("compacting PDF")
+      compactPDF(outputPDF)
+    }
+  }
+}
+
+makeRatioDataFrame <- function(ACs, num, denom, widths = NULL) {
+  if ( is.null(widths) ) widths <- rep(1, length(ACs))
+  
+  value = NULL
+  titv <- data.frame(AC=ACs, width = widths, num=num, denom = denom, ratio = num / denom)
+}
+
+.reduceACs <- function(binWidthForAC, ACs) {
+  # computes data structures necessary to reduce the full range of ACs
+  #
+  # binWidthForAC returns the number of upcoming bins that should be merged into 
+  # that AC bin.  ACs is a vector of all AC values from 0 to 2N that should be 
+  # merged together
+  #
+  # Returns a list containing the reduced ACs starts, their corresponding widths,
+  # and a map from original ACs to their new ones (1 -> 1, 2 -> 2, 3 -> 2, etc)
+  maxAC <- max(ACs)
+  newACs <- c()
+  widths <- c()
+  newACMap <- c()
+  ac <- 0
+  while ( ac < maxAC ) {
+    newACs <- c(newACs, ac)
+    width <- binWidthForAC(ac)
+    widths <- c(widths, width)
+    newACMap <- c(newACMap, rep(ac, width))
+    ac <- ac + width
+  }
+  list(ACs = newACs, widths=widths, newACMap = newACMap)
+}
+
+# geometricACs <- function(k, ACs) {
+#   nBins <- round(k * log10(max(ACs)))
+#   
+#   binWidthForAC <- function(ac) {
+#     max(ceiling(ac / nBins), 1)
+#   }
+#   
+#   return(reduceACs(binWidthForAC, ACs))
+# }
+
+reduce.AC.on.LogLinear.intervals <- function(scaleFactor, ACs) {
+  # map the full range of AC values onto a log linear scale
+  #
+  # Reduce the full AC range onto one where the width of each new AC increases at a rate of
+  # 10^scaleFactor in size with growing AC values.  This is primarily useful for accurately
+  # computing ratios or other quantities by AC that aren't well determined when the AC 
+  # values are very large
+  #
+  # Returns a list containing the reduced ACs starts, their corresponding widths,
+  # and a map from original ACs to their new ones (1 -> 1, 2 -> 2, 3 -> 2, etc)
+  maxAC <- max(ACs)
+  afs <- ACs / maxAC
+  breaks <- 10^(seq(-4, -1, scaleFactor))
+  widths <- c()
+  lastBreak <- 1
+  for ( i in length(breaks):1 ) {
+    b <- breaks[i]
+    width <- sum(afs < lastBreak & afs >= b)
+    widths <- c(widths, width)
+    lastBreak <- b
+  }
+  widths <- rev(widths)
+  
+  binWidthForAC <- function(ac) {
+    af <- ac / maxAC
+    value = 1
+    for ( i in length(breaks):1 )
+      if ( af >= breaks[i] ) {
+        value = widths[i]
+        break
+      }
+    
+    return(value)
+  }
+  
+  return(.reduceACs(binWidthForAC, ACs))
+}
+
+.remapACs <- function(remapper, k, df) {
+  newACs <- remapper(k, df$AC)
+  
+  n = length(newACs$ACs)
+  num = rep(0, n)
+  denom = rep(0, n)
+  for ( i in 1:dim(df)[1] ) {
+    rowI = df$AC == i
+    row = df[rowI,]
+    newAC = newACs$newACMap[row$AC]
+    newRowI = newACs$ACs == newAC
+    num[newRowI] = num[newRowI] + df$num[rowI]
+    denom[newRowI] = denom[newRowI] + df$denom[rowI]
+  }
+  
+  newdf <- makeRatioDataFrame(newACs$ACs, num, denom, newACs$widths )
+  newdf
+}
+
+compute.ratio.on.LogLinear.AC.intervals <- function(ACs, num, denom, scaleFactor = 0.1) {
+  df = makeRatioDataFrame(ACs, num, denom, 1)
+  return(.remapACs(reduce.AC.on.LogLinear.intervals, scaleFactor, df))
+}
+
+plotVariantQC <- function(metrics, measures, requestedStrat = "Sample", 
+                          fixHistogramX=F, anotherStrat = NULL, nObsField = "n_indels", 
+                          onSamePage=F, facetVariableOnXPerSample = F, facetVariableOnXForDist = T, 
+                          moreTitle="", note = NULL) {
+  metrics$strat = metrics[[requestedStrat]]
+  
+  otherFacet = "."
+  id.vars = c("strat", "nobs")
+  metrics$nobs <- metrics[[nObsField]]
+  
+  # keep track of the other strat and it's implied facet value
+  if (! is.null(anotherStrat)) { 
+    id.vars = c(id.vars, anotherStrat)
+    otherFacet = anotherStrat
+  }
+  
+  molten <- melt(metrics, id.vars=id.vars, measure.vars=c(measures))
+  perSampleGraph <- ggplot(data=molten, aes(x=strat, y=value, group=variable, color=variable, fill=variable))
+
+  # create the title
+  titleText=paste(paste(paste(measures, collapse=", "), "by", requestedStrat), moreTitle)
+  if ( !is.null(note) ) {
+    titleText=paste(titleText, note, sep="\n")
+  }
+  paste(titleText)
+  title <- ggtitle(titleText)
+  
+  determineFacet <- function(onX) {
+    if ( onX ) { 
+      paste(otherFacet, "~ variable")
+    } else {
+      paste("variable ~", otherFacet)
+    }
+  }
+  
+  sampleFacet = determineFacet(facetVariableOnXPerSample)
+  distFacet   = determineFacet(facetVariableOnXForDist)
+  
+  if ( requestedStrat == "Sample" ) {
+    perSampleGraph <- perSampleGraph + geom_text(aes(label=strat), size=1.5) + geom_blank() # don't display a scale
+    perSampleGraph <- perSampleGraph + scale_x_discrete("Sample (ordered by nSNPs)")
+  } else { # by AlleleCount
+    perSampleGraph <- perSampleGraph + geom_point(aes(size=log10(nobs))) #+ geom_smooth(aes(weight=log10(nobs)))
+    perSampleGraph <- perSampleGraph + scale_x_log10("AlleleCount")
+  }    
+  perSampleGraph <- perSampleGraph + ylab("Variable value") + title
+  perSampleGraph <- perSampleGraph + facet_grid(sampleFacet, scales="free")
+  
+  nValues = length(unique(molten$value))
+  if (nValues > 2) {
+    if ( requestedStrat == "Sample" ) {
+      distGraph <- ggplot(data=molten, aes(x=value, group=variable, fill=variable))
+    } else {
+      distGraph <- ggplot(data=molten, aes(x=value, group=variable, fill=variable, weight=nobs))
+    }
+    distGraph <- distGraph + geom_histogram(aes(y=..ndensity..))
+    distGraph <- distGraph + geom_density(alpha=0.5, aes(y=..scaled..))
+    distGraph <- distGraph + geom_rug(aes(y=NULL, color=variable, position="jitter"))
+    scale = "free"
+    if ( fixHistogramX ) scale = "fixed"
+    distGraph <- distGraph + facet_grid(distFacet, scales=scale)
+    distGraph <- distGraph + ylab("Relative frequency")
+    distGraph <- distGraph + xlab("Variable value (see facet for variable by color)")
+    distGraph <- distGraph + theme(axis.text.x=element_text(angle=-45)) # , legend.position="none")
+  } else {
+    distGraph <- NA
+  }
+  
+  if ( onSamePage ) {
+    suppressMessages(distributePerSampleGraph(perSampleGraph, distGraph))
+  } else {
+    suppressMessages(print(perSampleGraph))
+    suppressMessages(print(distGraph + title))
+  }
+}
diff --git a/public/gsalib/src/R/R/gsa.warn.R b/public/gsalib/src/R/R/gsa.warn.R
new file mode 100644
index 0000000..7ee08ce
--- /dev/null
+++ b/public/gsalib/src/R/R/gsa.warn.R
@@ -0,0 +1,3 @@
+gsa.warn <- function(message) {
+    gsa.message(sprintf("Warning: %s", message));
+}
diff --git a/public/gsalib/src/R/Read-and-delete-me b/public/gsalib/src/R/Read-and-delete-me
new file mode 100644
index 0000000..d04323a
--- /dev/null
+++ b/public/gsalib/src/R/Read-and-delete-me
@@ -0,0 +1,9 @@
+* Edit the help file skeletons in 'man', possibly combining help files
+  for multiple functions.
+* Put any C/C++/Fortran code in 'src'.
+* If you have compiled code, add a .First.lib() function in 'R' to load
+  the shared library.
+* Run R CMD build to build the package tarball.
+* Run R CMD check to check the package tarball.
+
+Read "Writing R Extensions" for more information.
diff --git a/public/gsalib/src/R/man/gsa.error.Rd b/public/gsalib/src/R/man/gsa.error.Rd
new file mode 100644
index 0000000..df7c0cb
--- /dev/null
+++ b/public/gsalib/src/R/man/gsa.error.Rd
@@ -0,0 +1,49 @@
+\name{gsa.error}
+\alias{gsa.error}
+\title{
+GSA error
+}
+\description{
+Write an error message to standard out with the prefix '[gsalib] Error:', print a traceback, and exit.
+}
+\usage{
+gsa.error(message)
+}
+%- maybe also 'usage' for other objects documented here.
+\arguments{
+  \item{message}{
+The error message to write.
+}
+}
+\details{
+%%  ~~ If necessary, more details than the description above ~~
+}
+\value{
+%%  ~Describe the value returned
+%%  If it is a LIST, use
+%%  \item{comp1 }{Description of 'comp1'}
+%%  \item{comp2 }{Description of 'comp2'}
+%% ...
+}
+\references{
+%% ~put references to the literature/web site here ~
+}
+\author{
+Kiran Garimella
+}
+\note{
+%%  ~~further notes~~
+}
+
+%% ~Make other sections like Warning with \section{Warning }{....} ~
+
+\seealso{
+%% ~~objects to See Also as \code{\link{help}}, ~~~
+}
+\examples{
+gsa.error("This is a message");
+}
+% Add one or more standard keywords, see file 'KEYWORDS' in the
+% R documentation directory.
+\keyword{ ~kwd1 }
+\keyword{ ~kwd2 }% __ONLY ONE__ keyword per line
diff --git a/public/gsalib/src/R/man/gsa.getargs.Rd b/public/gsalib/src/R/man/gsa.getargs.Rd
new file mode 100644
index 0000000..27aa1b0
--- /dev/null
+++ b/public/gsalib/src/R/man/gsa.getargs.Rd
@@ -0,0 +1,57 @@
+\name{gsa.getargs}
+\alias{gsa.getargs}
+\title{
+Get script arguments
+}
+\description{
+Get script arguments given a list object specifying arguments and documentation.  Can be used in command-line or interactive mode.  This is helpful when developing scripts in interactive mode that will eventually become command-line programs.  If no arguments are specified or help is requested in command-line mode, the script will print out a usage statement with available arguments and exit.
+}
+\usage{
+gsa.getargs(argspec, doc = NA)
+}
+\arguments{
+  \item{argspec}{
+A list object.  Each key is an argument name.  The value is another list object with a 'value' and 'doc' keys.  For example:
+\preformatted{argspec = list(
+    arg1 = list(value=10, doc="Info for optional arg1"),
+    arg2 = list(value=NA, doc="Info for required arg2")
+);
+}
+
+If the value provided is NA, the argument is considered required and must be specified when the script is invoked.  For command-line mode, this means the argument must be specified on the command-line.  In interactive mode, there are two ways of specifying these arguments.  First, if a properly formatted list argument called 'cmdargs' is present in the current environment (i.e. the object returned by gsa.getargs() from a previous invocation), the value is taken from this object.  Otherwi [...]
+}
+
+  \item{doc}{
+An optional string succinctly documenting the purpose of the script.
+}
+}
+\details{
+Interactive scripts typically make use of hardcoded filepaths and parameter settings.  This makes testing easy, but generalization to non-interactive mode more difficult.  This utility provides a mechanism for writing scripts that work properly in both interactive and command-line modes.
+
+To use this method, specify a list with key-value pairs representing the arguments as specified above.  In command-line mode, if no arguments are specified or the user specifies '-h' or '-help' anywhere on the command string, a help message indicating available arguments, their default values, and some documentation about the argument are provided.
+}
+\value{
+Returns a list with keys matching the argspec and values representing the specified arguments.
+
+\item{arg1 }{Value for argument 1}
+\item{arg2 }{Value for argument 2}
+...etc.
+}
+\references{
+%% ~put references to the literature/web site here ~
+}
+\author{
+Kiran Garimella
+}
+\examples{
+argspec = list(
+    file    = list(value="/my/test.vcf", doc="VCF file"),
+    verbose = list(value=0,              doc="If 1, set verbose mode"),
+    test2   = list(value=2.3e9,          doc="Another argument that does stuff")
+);
+        
+cmdargs = gsa.getargs(argspec, doc="My test program");
+
+print(cmdargs$file);  # will print '[1] "/my/test.vcf"'
+}
+\keyword{ ~kwd1 }
diff --git a/public/gsalib/src/R/man/gsa.message.Rd b/public/gsalib/src/R/man/gsa.message.Rd
new file mode 100644
index 0000000..9752de8
--- /dev/null
+++ b/public/gsalib/src/R/man/gsa.message.Rd
@@ -0,0 +1,44 @@
+\name{gsa.message}
+\alias{gsa.message}
+\title{
+GSA message
+}
+\description{
+Write a message to standard out with the prefix '[gsalib]'.
+}
+\usage{
+gsa.message(message)
+}
+\arguments{
+  \item{message}{
+The message to write.
+}
+}
+\details{
+%%  ~~ If necessary, more details than the description above ~~
+}
+\value{
+%%  ~Describe the value returned
+%%  If it is a LIST, use
+%%  \item{comp1 }{Description of 'comp1'}
+%%  \item{comp2 }{Description of 'comp2'}
+%% ...
+}
+\references{
+%% ~put references to the literature/web site here ~
+}
+\author{
+Kiran Garimella
+}
+\note{
+%%  ~~further notes~~
+}
+
+\seealso{
+%% ~~objects to See Also as \code{\link{help}}, ~~~
+}
+\examples{
+## Write message to stdout
+gsa.message("This is a message");
+}
+\keyword{ ~kwd1 }
diff --git a/public/gsalib/src/R/man/gsa.plot.venn.Rd b/public/gsalib/src/R/man/gsa.plot.venn.Rd
new file mode 100644
index 0000000..bf4feb5
--- /dev/null
+++ b/public/gsalib/src/R/man/gsa.plot.venn.Rd
@@ -0,0 +1,75 @@
+\name{gsa.plot.venn}
+\alias{gsa.plot.venn}
+\title{
+Plot a proportional venn diagram
+}
+\description{
+Plot a proportional venn diagram (two or three-way venns allowed)
+}
+\usage{
+gsa.plot.venn(a, b, c = 0, a_and_b, a_and_c = 0, b_and_c = 0, col = c("#FF6342", "#63C6DE", "#ADDE63"), pos = c(0.2, 0.2, 0.8, 0.82), debug = 0)
+}
+\arguments{
+  \item{a}{
+size of 'a' circle
+}
+  \item{b}{
+size of 'b' circle
+}
+  \item{c}{
+size of 'c' circle
+}
+  \item{a_and_b}{
+size of a and b overlap
+}
+  \item{a_and_c}{
+size of a and c overlap
+}
+  \item{b_and_c}{
+size of b and c overlap
+}
+  \item{col}{
+vector of colors for each venn piece
+}
+  \item{pos}{
+vector of positional elements
+}
+  \item{debug}{
+if 1, set debug mode and print useful information
+}
+}
+\details{
+Plots a two-way or three-way proportional Venn diagram.  Internally, this method uses the Google Chart API to generate the diagram, then renders it into the plot window where it can be annotated in interesting ways.
+}
+\value{
+%%  ~Describe the value returned
+%%  If it is a LIST, use
+%%  \item{comp1 }{Description of 'comp1'}
+%%  \item{comp2 }{Description of 'comp2'}
+%% ...
+}
+\references{
+}
+\author{
+Kiran Garimella
+}
+\note{
+%%  ~~further notes~~
+}
+
+%% ~Make other sections like Warning with \section{Warning }{....} ~
+
+\seealso{
+%% ~~objects to See Also as \code{\link{help}}, ~~~
+}
+\examples{
+## Plot a two-way Venn diagram
+gsa.plot.venn(1000, 750, 0, 400);
+
+## Plot a three-way Venn diagram
+gsa.plot.venn(1000, 750, 900, 400, 650, 500);
+}
+% Add one or more standard keywords, see file 'KEYWORDS' in the
+% R documentation directory.
+\keyword{ ~kwd1 }
+\keyword{ ~kwd2 }% __ONLY ONE__ keyword per line
diff --git a/public/gsalib/src/R/man/gsa.read.eval.Rd b/public/gsalib/src/R/man/gsa.read.eval.Rd
new file mode 100644
index 0000000..0e2baba
--- /dev/null
+++ b/public/gsalib/src/R/man/gsa.read.eval.Rd
@@ -0,0 +1,111 @@
+\name{gsa.read.eval}
+\alias{gsa.read.eval}
+\title{
+Read a VariantEval file
+}
+\description{
+Read a VariantEval file that's output in R format.
+}
+\usage{
+gsa.read.eval(evalRoot)
+}
+%- maybe also 'usage' for other objects documented here.
+\arguments{
+  \item{evalRoot}{
+%%     ~~Describe \code{evalRoot} here~~
+}
+}
+\details{
+%%  ~~ If necessary, more details than the description above ~~
+}
+\value{
+%%  ~Describe the value returned
+%%  If it is a LIST, use
+%%  \item{comp1 }{Description of 'comp1'}
+%%  \item{comp2 }{Description of 'comp2'}
+%% ...
+}
+\references{
+%% ~put references to the literature/web site here ~
+}
+\author{
+%%  ~~who you are~~
+}
+\note{
+%%  ~~further notes~~
+}
+
+%% ~Make other sections like Warning with \section{Warning }{....} ~
+
+\seealso{
+%% ~~objects to See Also as \code{\link{help}}, ~~~
+}
+\examples{
+##---- Should be DIRECTLY executable !! ----
+##-- ==>  Define data, use random,
+##--	or do  help(data=index)  for the standard data sets.
+
+## The function is currently defined as
+function(evalRoot) {
+    fileAlleleCountStats = paste(evalRoot, ".AlleleCountStats.csv", sep="");
+    fileCompOverlap = paste(evalRoot, ".Comp_Overlap.csv", sep="");
+    fileCountVariants = paste(evalRoot, ".Count_Variants.csv", sep="");
+    fileGenotypeConcordance = paste(evalRoot, ".Genotype_Concordance.csv", sep="");
+    fileMetricsByAc = paste(evalRoot, ".MetricsByAc.csv", sep="");
+    fileMetricsBySample = paste(evalRoot, ".MetricsBySample.csv", sep="");
+    fileQuality_Metrics_by_allele_count = paste(evalRoot, ".Quality_Metrics_by_allele_count.csv", sep="");
+    fileQualityScoreHistogram = paste(evalRoot, ".QualityScoreHistogram.csv", sep="");
+    fileSampleStatistics = paste(evalRoot, ".Sample_Statistics.csv", sep="");
+    fileSampleSummaryStatistics = paste(evalRoot, ".Sample_Summary_Statistics.csv", sep="");
+    fileSimpleMetricsBySample = paste(evalRoot, ".SimpleMetricsBySample.csv", sep="");
+    fileTi_slash_Tv_Variant_Evaluator = paste(evalRoot, ".Ti_slash_Tv_Variant_Evaluator.csv", sep="");
+    fileTiTvStats = paste(evalRoot, ".TiTvStats.csv", sep="");
+    fileVariant_Quality_Score = paste(evalRoot, ".Variant_Quality_Score.csv", sep="");
+
+    eval = list(
+        AlleleCountStats = NA,
+        CompOverlap = NA,
+        CountVariants = NA,
+        GenotypeConcordance = NA,
+        MetricsByAc = NA,
+        MetricsBySample = NA,
+        Quality_Metrics_by_allele_count = NA,
+        QualityScoreHistogram = NA,
+        SampleStatistics = NA,
+        SampleSummaryStatistics = NA,
+        SimpleMetricsBySample = NA,
+        TiTv = NA,
+        TiTvStats = NA,
+        Variant_Quality_Score = NA,
+
+        CallsetNames = c(),
+        CallsetOnlyNames = c(),
+        CallsetFilteredNames = c()
+    );
+
+    eval$AlleleCountStats                = .attemptToLoadFile(fileAlleleCountStats);
+    eval$CompOverlap                     = .attemptToLoadFile(fileCompOverlap);
+    eval$CountVariants                   = .attemptToLoadFile(fileCountVariants);
+    eval$GenotypeConcordance             = .attemptToLoadFile(fileGenotypeConcordance);
+    eval$MetricsByAc                     = .attemptToLoadFile(fileMetricsByAc);
+    eval$MetricsBySample                 = .attemptToLoadFile(fileMetricsBySample);
+    eval$Quality_Metrics_by_allele_count = .attemptToLoadFile(fileQuality_Metrics_by_allele_count);
+    eval$QualityScoreHistogram           = .attemptToLoadFile(fileQualityScoreHistogram);
+    eval$SampleStatistics                = .attemptToLoadFile(fileSampleStatistics);
+    eval$SampleSummaryStatistics         = .attemptToLoadFile(fileSampleSummaryStatistics);
+    eval$SimpleMetricsBySample           = .attemptToLoadFile(fileSimpleMetricsBySample);
+    eval$TiTv                            = .attemptToLoadFile(fileTi_slash_Tv_Variant_Evaluator);
+    eval$TiTvStats                       = .attemptToLoadFile(fileTiTvStats);
+    eval$Variant_Quality_Score           = .attemptToLoadFile(fileVariant_Quality_Score);
+
+    uniqueJexlExpressions = unique(eval$TiTv$jexl_expression);
+    eval$CallsetOnlyNames = as.vector(uniqueJexlExpressions[grep("FilteredIn|Intersection|none", uniqueJexlExpressions, invert=TRUE, ignore.case=TRUE)]);
+    eval$CallsetNames = as.vector(gsub("-only", "", eval$CallsetOnlyNames));
+    eval$CallsetFilteredNames = as.vector(c()); 
+    eval;
+  }
+}
+% Add one or more standard keywords, see file 'KEYWORDS' in the
+% R documentation directory.
+\keyword{ ~kwd1 }
+\keyword{ ~kwd2 }% __ONLY ONE__ keyword per line
diff --git a/public/gsalib/src/R/man/gsa.read.gatkreport.Rd b/public/gsalib/src/R/man/gsa.read.gatkreport.Rd
new file mode 100644
index 0000000..67c2c7b
--- /dev/null
+++ b/public/gsalib/src/R/man/gsa.read.gatkreport.Rd
@@ -0,0 +1,55 @@
+\name{gsa.read.gatkreport}
+\alias{gsa.read.gatkreport}
+\title{
+gsa.read.gatkreport
+}
+\description{
+Reads a GATKReport file - a multi-table document - and loads each table as a separate data.frame object in a list.
+}
+\usage{
+gsa.read.gatkreport(filename)
+}
+\arguments{
+  \item{filename}{
+The path to the GATKReport file.
+}
+}
+\details{
+The GATKReport format replaces the multi-file output format used by many GATK tools and provides a single, consolidated file format.  This format accomodates multiple tables and is still R-loadable - through this function.
+
+The file format looks like this:
+\preformatted{##:GATKReport.v0.1 TableName : The description of the table
+col1   col2                      col3
+0      0.007451835696110506      25.474613284804366
+1      0.002362777171937477      29.844949954504095
+2      9.087604507451836E-4      32.87590975254731
+3      5.452562704471102E-4      34.498999090081895
+4      9.087604507451836E-4      35.14831665150137
+}
+
+}
+\value{
+Returns a list object, where each key is the TableName and the value is the data.frame object with the contents of the table.  If multiple tables with the same name exist, each one after the first will be given names of "TableName.v1", "TableName.v2", ..., "TableName.vN".
+%%  ~Describe the value returned
+%%  If it is a LIST, use
+%%  \item{comp1 }{Description of 'comp1'}
+%%  \item{comp2 }{Description of 'comp2'}
+%% ...
+}
+\references{
+%% ~put references to the literature/web site here ~
+}
+\author{
+Kiran Garimella
+}
+\note{
+%%  ~~further notes~~
+}
+
+\seealso{
+%% ~~objects to See Also as \code{\link{help}}, ~~~
+}
+\examples{
+report = gsa.read.gatkreport("/path/to/my/output.gatkreport");
+}
+\keyword{ ~kwd1 }
diff --git a/public/gsalib/src/R/man/gsa.read.squidmetrics.Rd b/public/gsalib/src/R/man/gsa.read.squidmetrics.Rd
new file mode 100644
index 0000000..0a8b378
--- /dev/null
+++ b/public/gsalib/src/R/man/gsa.read.squidmetrics.Rd
@@ -0,0 +1,48 @@
+\name{gsa.read.squidmetrics}
+\alias{gsa.read.squidmetrics}
+\title{
+gsa.read.squidmetrics
+}
+\description{
+Reads metrics for a specified SQUID project into a dataframe.
+}
+\usage{
+gsa.read.squidmetrics("C315")
+}
+\arguments{
+  \item{project}{
+The project for which metrics should be obtained.
+}
+  \item{bylane}{
+If TRUE, obtains per-lane metrics rather than the default per-sample metrics.
+}
+}
+\details{
+%%  ~~ If necessary, more details than the description above ~~
+}
+\value{
+%%  ~Describe the value returned
+%%  If it is a LIST, use
+%%  \item{comp1 }{Description of 'comp1'}
+%%  \item{comp2 }{Description of 'comp2'}
+%% ...
+Returns a data frame with samples (or lanes) as the row and the metric as the column.
+}
+\references{
+%% ~put references to the literature/web site here ~
+}
+\author{
+Kiran Garimella
+}
+\note{
+This method will only work within the Broad Institute internal network.
+}
+
+\seealso{
+%% ~~objects to See Also as \code{\link{help}}, ~~~
+}
+\examples{
+## Obtain metrics for project C315.
+d = gsa.read.squidmetrics("C315");
+}
+\keyword{ ~kwd1 }
diff --git a/public/gsalib/src/R/man/gsa.read.vcf.Rd b/public/gsalib/src/R/man/gsa.read.vcf.Rd
new file mode 100644
index 0000000..cffd35e
--- /dev/null
+++ b/public/gsalib/src/R/man/gsa.read.vcf.Rd
@@ -0,0 +1,53 @@
+\name{gsa.read.vcf}
+\alias{gsa.read.vcf}
+\title{
+gsa.read.vcf
+}
+\description{
+Reads a VCF file into a table.  Optionally expands genotype columns into separate columns containing the genotype, separate from the other fields specified in the FORMAT field.
+}
+\usage{
+gsa.read.vcf(vcffile, skip=0, nrows=-1, expandGenotypeFields = FALSE)
+}
+\arguments{
+  \item{vcffile}{
+The path to the vcf file.
+}
+  \item{skip}{
+The number of lines of the data file to skip before beginning to read data.
+}
+  \item{nrows}{
+The maximum number of rows to read in.  Negative and other invalid values are ignored.
+}
+  \item{expandGenotypeFields}{
+If TRUE, adds an additional column per sample containing just the genotype.
+}
+}
+\details{
+The VCF format is the standard variant call file format used in the GATK.  This function reads that data in as a table for easy analysis.
+}
+\value{
+Returns a data.frame object, where each column corresponds to the columns in the VCF file.
+%%  ~Describe the value returned
+%%  If it is a LIST, use
+%%  \item{comp1 }{Description of 'comp1'}
+%%  \item{comp2 }{Description of 'comp2'}
+%% ...
+}
+\references{
+%% ~put references to the literature/web site here ~
+}
+\author{
+Kiran Garimella
+}
+\note{
+%%  ~~further notes~~
+}
+
+\seealso{
+%% ~~objects to See Also as \code{\link{help}}, ~~~
+}
+\examples{
+vcf = gsa.read.vcf("/path/to/my/output.vcf");
+}
+\keyword{ ~kwd1 }
diff --git a/public/gsalib/src/R/man/gsa.warn.Rd b/public/gsalib/src/R/man/gsa.warn.Rd
new file mode 100644
index 0000000..0b9770b
--- /dev/null
+++ b/public/gsalib/src/R/man/gsa.warn.Rd
@@ -0,0 +1,46 @@
+\name{gsa.warn}
+\alias{gsa.warn}
+\title{
+GSA warn
+}
+\description{
+Write a warning message to standard out with the prefix '[gsalib] Warning:'.
+}
+\usage{
+gsa.warn(message)
+}
+%- maybe also 'usage' for other objects documented here.
+\arguments{
+  \item{message}{
+The warning message to write.
+}
+}
+\details{
+%%  ~~ If necessary, more details than the description above ~~
+}
+\value{
+%%  ~Describe the value returned
+%%  If it is a LIST, use
+%%  \item{comp1 }{Description of 'comp1'}
+%%  \item{comp2 }{Description of 'comp2'}
+%% ...
+}
+\references{
+%% ~put references to the literature/web site here ~
+}
+\author{
+Kiran Garimella
+}
+\note{
+%%  ~~further notes~~
+}
+
+\seealso{
+%% ~~objects to See Also as \code{\link{help}}, ~~~
+}
+\examples{
+## Write message to stdout
+gsa.warn("This is a warning message");
+}
+\keyword{ ~kwd1 }
+\keyword{ ~kwd2 }% __ONLY ONE__ keyword per line
diff --git a/public/gsalib/src/R/man/gsalib-package.Rd b/public/gsalib/src/R/man/gsalib-package.Rd
new file mode 100644
index 0000000..4a49cf9
--- /dev/null
+++ b/public/gsalib/src/R/man/gsalib-package.Rd
@@ -0,0 +1,70 @@
+\name{gsalib-package}
+\alias{gsalib-package}
+\alias{gsalib}
+\docType{package}
+\title{
+GATK utility analysis functions
+}
+\description{
+Utility functions for analyzing GATK-processed NGS data
+}
+\details{
+This package contains functions for working with GATK-processed NGS data.  These functions include a command-line parser that also allows a script to be used in interactive mode (good for developing scripts that will eventually be automated), a proportional Venn diagram generator, convenience methods for parsing VariantEval output, and more.
+}
+\author{
+Genome Sequencing and Analysis Group
+
+Medical and Population Genetics Program
+
+Maintainer: Kiran Garimella
+}
+\references{
+GATK website: http://www.broadinstitute.org/gatk
+
+GATK documentation guide: http://www.broadinstitute.org/gatk/guide
+
+GATK help forum: http://gatkforums.broadinstitute.org
+}
+\examples{
+## get script arguments in interactive and non-interactive mode
+cmdargs = gsa.getargs( list(
+    requiredArg1 = list(
+        value = NA,
+        doc   = "Documentation for requiredArg1"
+    ),
+
+    optionalArg1 = list(
+        value = 3e9,
+        doc   = "Documentation for optionalArg1"
+    )
+) );
+
+## plot a proportional Venn diagram
+gsa.plot.venn(500, 250, 0, 100);
+
+## read a GATKReport file
+report = gsa.gatk.report("/path/to/my/output.gatkreport");
+
+## emit a message
+gsa.message("This is a message");
+
+## emit a warning message
+gsa.message("This is a warning message");
+
+## emit an error message
+gsa.message("This is an error message");
+
+## read the SQUID metrics for a given sequencing project (internal to the Broad only)
+s = gsa.read.squidmetrics("C427");
+
+## read command-line arguments
+cmdargs = gsa.getargs(
+    list(
+        file    = list(value="/my/test.vcf", doc="VCF file"),
+        verbose = list(value=0,              doc="If 1, set verbose mode"),
+        test2   = list(value=2.3e9,          doc="Another argument that does stuff")
+    ),
+    doc="My test program"
+);
+}
+\keyword{ package }
diff --git a/public/gsalib/src/assembly/gsalib.xml b/public/gsalib/src/assembly/gsalib.xml
new file mode 100644
index 0000000..7650c71
--- /dev/null
+++ b/public/gsalib/src/assembly/gsalib.xml
@@ -0,0 +1,13 @@
+<assembly xmlns="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.2" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.2 http://maven.apache.org/xsd/assembly-1.1.2.xsd">
+    <id>gsalib</id>
+    <formats>
+        <format>tar.gz</format>
+    </formats>
+    <includeBaseDirectory>false</includeBaseDirectory>
+    <fileSets>
+        <fileSet>
+            <outputDirectory>gsalib</outputDirectory>
+            <directory>src/R</directory>
+        </fileSet>
+    </fileSets>
+</assembly>
diff --git a/public/java/config/log4j.properties b/public/java/config/log4j.properties
new file mode 100644
index 0000000..480646f
--- /dev/null
+++ b/public/java/config/log4j.properties
@@ -0,0 +1,10 @@
+log4j.logger.org.broadinstitute.gatk.tools.walkers.Walker=INFO, walker
+
+# use this to append walker data to the console only
+log4j.appender.walker=org.apache.log4j.ConsoleAppender
+
+# uncomment the following instead for writing debug info to a file called walker.log
+#log4j.appender.walker=org.apache.log4j.FileAppender
+#log4j.appender.walker.File=walker.log
+#log4j.appender.walker.layout=org.apache.log4j.PatternLayout
+#log4j.appender.walker.layout.ConversionPattern=%r [%t] %-5p %c - %m%n
diff --git a/public/package-tests/pom.xml b/public/package-tests/pom.xml
new file mode 100644
index 0000000..ce3f5cf
--- /dev/null
+++ b/public/package-tests/pom.xml
@@ -0,0 +1,199 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+    <modelVersion>4.0.0</modelVersion>
+
+    <!--
+    Run during package testing by the maven invoker plugin in the gatk-aggregator /pom.xml
+    -->
+
+    <parent>
+        <groupId>org.broadinstitute.gatk</groupId>
+        <artifactId>gatk-root</artifactId>
+        <version>3.3</version>
+        <relativePath>../gatk-root</relativePath>
+    </parent>
+
+    <artifactId>gatk-package-tests</artifactId>
+    <packaging>pom</packaging>
+    <name>GATK Package Tests</name>
+
+    <properties>
+        <gatk.basedir>${project.basedir}/../..</gatk.basedir>
+        <gatk.packageunittests.skipped>true</gatk.packageunittests.skipped>
+        <gatk.packageintegrationtests.skipped>true</gatk.packageintegrationtests.skipped>
+        <gatk.packagequeuetests.skipped>true</gatk.packagequeuetests.skipped>
+        <gatk.packagelargescaletests.skipped>true</gatk.packagelargescaletests.skipped>
+        <gatk.packageknowledgebasetests.skipped>true</gatk.packageknowledgebasetests.skipped>
+    </properties>
+
+    <!-- Dependency configuration (versions, etc.) -->
+    <dependencies>
+        <dependency>
+            <groupId>${project.groupId}</groupId>
+            <artifactId>${gatk.packagetests.artifactId}</artifactId>
+            <version>${project.version}</version>
+        </dependency>
+
+        <!--
+        gatk-framework test-jar added for BaseTest
+
+        TODO: Currently the <exclusion> isn't working 100%, so switched to using additionalClasspathElements
+
+        TODO: Uncomment below to use the explicitly bad "exclude *" to really test correct packaging,
+        TODO: until we can separate BaseTest and other utilities into their own gatk-test-utils artifact.
+        TODO: We only want the classes in the packaged jars tested, not the classes within the dependency jars too.
+        See also:
+          http://stackoverflow.com/questions/547805/how-to-exclude-all-transitive-dependencies-of-a-maven-dependency
+          http://maven.apache.org/plugins/maven-jar-plugin/usage.html#The_preferred_way
+        <dependency>
+            <groupId>${project.groupId}</groupId>
+            <artifactId>gatk-tools-public</artifactId>
+            <version>${project.version}</version>
+            <type>test-jar</type>
+            <scope>test</scope>
+
+            <exclusions>
+                <exclusion>
+                    <groupId>*</groupId>
+                    <artifactId>*</artifactId>
+                </exclusion>
+            </exclusions>
+
+        </dependency>
+        -->
+
+        <!--
+        NOTE: Any test dependencies used by a packaged artifact must be ALSO added here.
+        For example, gatk-tools-protected uses caliper, so caliper should also be added here.
+        TestNG and its reporters are inherited from the global gatk-root/pom.xml as dependencies.
+        -->
+        <dependency>
+            <groupId>com.google.caliper</groupId>
+            <artifactId>caliper</artifactId>
+            <scope>test</scope>
+        </dependency>
+    </dependencies>
+
+    <build>
+        <directory>${gatk.packagetests.basedir}/target</directory>
+    </build>
+
+    <profiles>
+        <profile>
+            <id>unittests</id>
+            <activation>
+                <activeByDefault>false</activeByDefault>
+                <property>
+                    <name>unittests.profile.enabled</name>
+                    <value>true</value>
+                </property>
+            </activation>
+            <build>
+                <!-- Plugin configuration -->
+                <plugins>
+                    <plugin>
+                        <groupId>org.apache.maven.plugins</groupId>
+                        <artifactId>maven-surefire-plugin</artifactId>
+                        <configuration>
+                            <basedir>${gatk.packagetests.basedir}</basedir>
+                            <workingDirectory>${gatk.packagetests.basedir}</workingDirectory>
+                            <classesDirectory>${project.build.outputDirectory}/ignored_by_package_test</classesDirectory>
+                            <testClassesDirectory>${gatk.packagetests.testClasses}</testClassesDirectory>
+                            <!-- TODO: Using additionalClasspathElement while debugging exclusion issue above -->
+                            <additionalClasspathElements>
+                                <additionalClasspathElement>${gatk.basedir}/public/gatk-tools-public/target/gatk-tools-public-${project.version}-tests.jar</additionalClasspathElement>
+                                <additionalClasspathElement>${gatk.basedir}/public/gatk-queue/target/gatk-queue-${project.version}-tests.jar</additionalClasspathElement>
+                            </additionalClasspathElements>
+                        </configuration>
+                        <executions>
+                            <execution>
+                                <id>unit-tests</id>
+                                <goals>
+                                    <goal>test</goal>
+                                </goals>
+                                <configuration>
+                                    <skip>${gatk.packageunittests.skipped}</skip>
+                                </configuration>
+                            </execution>
+                        </executions>
+                    </plugin>
+                </plugins>
+            </build>
+        </profile>
+
+        <profile>
+            <id>integrationtests</id>
+            <activation>
+                <activeByDefault>false</activeByDefault>
+                <property>
+                    <name>integrationtests.profile.enabled</name>
+                    <value>true</value>
+                </property>
+            </activation>
+            <build>
+                <!-- Plugin configuration -->
+                <plugins>
+                    <plugin>
+                        <groupId>org.apache.maven.plugins</groupId>
+                        <artifactId>maven-failsafe-plugin</artifactId>
+                        <configuration>
+                            <basedir>${gatk.packagetests.basedir}</basedir>
+                            <workingDirectory>${gatk.packagetests.basedir}</workingDirectory>
+                            <classesDirectory>${project.build.outputDirectory}/ignored_by_package_test</classesDirectory>
+                            <testClassesDirectory>${gatk.packagetests.testClasses}</testClassesDirectory>
+                            <!-- TODO: Using additionalClasspathElement while debugging exclusion issue above -->
+                            <additionalClasspathElements>
+                                <additionalClasspathElement>${gatk.basedir}/public/gatk-tools-public/target/gatk-tools-public-${project.version}-tests.jar</additionalClasspathElement>
+                                <additionalClasspathElement>${gatk.basedir}/public/gatk-queue/target/gatk-queue-${project.version}-tests.jar</additionalClasspathElement>
+                            </additionalClasspathElements>
+                        </configuration>
+                        <executions>
+                            <execution>
+                                <id>integration-tests</id>
+                                <goals>
+                                    <goal>verify</goal>
+                                </goals>
+                                <!-- run integration tests -->
+                                <configuration>
+                                    <skip>${gatk.packageintegrationtests.skipped}</skip>
+                                </configuration>
+                            </execution>
+                            <execution>
+                                <id>queue-tests</id>
+                                <goals>
+                                    <goal>verify</goal>
+                                </goals>
+                                <!-- run queue dry run tests -->
+                                <configuration>
+                                    <skip>${gatk.packagequeuetests.skipped}</skip>
+                                </configuration>
+                            </execution>
+                            <execution>
+                                <id>large-scale-tests</id>
+                                <goals>
+                                    <goal>verify</goal>
+                                </goals>
+                                <!-- run large scale tests -->
+                                <configuration>
+                                    <skip>${gatk.packagelargescaletests.skipped}</skip>
+                                </configuration>
+                            </execution>
+                            <execution>
+                                <id>knowledge-base-tests</id>
+                                <goals>
+                                    <goal>verify</goal>
+                                </goals>
+                                <!-- run knowledge base tests -->
+                                <configuration>
+                                    <skip>${gatk.packageknowledgebasetests.skipped}</skip>
+                                </configuration>
+                            </execution>
+                        </executions>
+                    </plugin>
+                </plugins>
+            </build>
+        </profile>
+
+    </profiles>
+
+</project>
diff --git a/public/perl/liftOverVCF.pl b/public/perl/liftOverVCF.pl
new file mode 100755
index 0000000..a942145
--- /dev/null
+++ b/public/perl/liftOverVCF.pl
@@ -0,0 +1,83 @@
+#!/usr/bin/perl -w
+
+# Runs the liftover tool on a VCF and properly handles the output
+
+use strict;
+use Getopt::Long;
+
+my $in = undef;
+my $gatk = undef;
+my $chain = undef;
+my $newRef = undef;
+my $oldRef = undef;
+my $out = undef;
+my $tmp = "/tmp";
+my $recordOriginalLocation = 0;
+GetOptions( "vcf=s" => \$in,
+	    "gatk=s" => \$gatk,
+	    "chain=s" => \$chain,
+	    "newRef=s" => \$newRef,
+	    "oldRef=s" => \$oldRef,
+            "out=s" => \$out,
+	    "tmp=s" => \$tmp,
+	    "recordOriginalLocation" => \$recordOriginalLocation);
+
+if ( !$in || !$gatk || !$chain || !$newRef || !$oldRef || !$out ) {
+    print "Usage: liftOverVCF.pl\n\t-vcf \t\t<input vcf>\n\t-gatk \t\t<path to gatk trunk>\n\t-chain \t\t<chain file>\n\t-newRef \t<path to new reference prefix; we will need newRef.dict, .fasta, and .fasta.fai>\n\t-oldRef \t<path to old reference prefix; we will need oldRef.fasta>\n\t-out \t\t<output vcf>\n\t-tmp \t\t<temp file location; defaults to /tmp>\n\t-recordOriginalLocation \t\t<Should we record what the original location was in the INFO field?; defaults to false>\n";
+    print "Example: ./liftOverVCF.pl\n\t-vcf /humgen/gsa-hpprojects/GATK/data/Comparisons/Validated/1kg_snp_validation/all_validation_batches.b36.vcf\n\t-chain b36ToHg19.broad.over.chain\n\t-out lifted.hg19.vcf\n\t-gatk /humgen/gsa-scr1/ebanks/Sting_dev\n\t-newRef /seq/references/Homo_sapiens_assembly19/v0/Homo_sapiens_assembly19\n\t-oldRef /humgen/1kg/reference/human_b36_both\n";
+    exit(1);
+}
+
+# generate a random number
+my $random_number = rand();
+my $tmp_prefix = "$tmp/$random_number";
+print "Writing temporary files to prefix: $tmp_prefix\n";
+my $unsorted_vcf = "$tmp_prefix.unsorted.vcf";
+
+# lift over the file
+print "Lifting over the vcf...";
+my $cmd = "java -jar $gatk/dist/GenomeAnalysisTK.jar -T LiftoverVariants -R $oldRef.fasta -V:variant $in -o $unsorted_vcf -chain $chain -dict $newRef.dict -U LENIENT_VCF_PROCESSING";
+if ($recordOriginalLocation) {
+  $cmd .= " -recordOriginalLocation";
+}
+system($cmd) == 0 or quit("The liftover step failed.  Please correct the necessary errors before retrying.");
+
+# we need to sort the lifted over file now
+print "\nRe-sorting the vcf...\n";
+my $sorted_vcf = "$tmp_prefix.sorted.vcf";
+open(SORTED, ">$sorted_vcf") or die "can't open $sorted_vcf: $!";
+
+# write the header
+open(UNSORTED, "< $unsorted_vcf") or die "can't open $unsorted_vcf: $!";
+my $inHeader = 1;
+while ( $inHeader == 1 ) {
+    my $line = <UNSORTED>;
+    if ( $line !~ m/^#/ ) {
+	$inHeader = 0;
+    } else {
+	print SORTED "$line";
+    }
+}
+close(UNSORTED);
+close(SORTED);
+
+$cmd = "grep \"^#\" -v $unsorted_vcf | sort -n -k2 -T $tmp | $gatk/public/perl/sortByRef.pl --tmp $tmp - $newRef.fasta.fai >> $sorted_vcf";
+system($cmd) == 0 or quit("The sorting step failed.  Please correct the necessary errors before retrying.");
+
+# Filter the VCF for bad records
+print "\nFixing/removing bad records...\n";
+$cmd = "java -jar $gatk/dist/GenomeAnalysisTK.jar -T FilterLiftedVariants -R $newRef.fasta -V:variant $sorted_vcf -o $out -U LENIENT_VCF_PROCESSING";
+system($cmd) == 0 or quit("The filtering step failed.  Please correct the necessary errors before retrying.");
+
+# clean up
+unlink $unsorted_vcf;
+unlink $sorted_vcf;
+my $sorted_index = "$sorted_vcf.idx";
+unlink $sorted_index;
+
+print "\nDone!\n";
+
+sub quit {
+    print "\n$_[0]\n";
+    exit(1);
+}
diff --git a/public/perl/sortByRef.pl b/public/perl/sortByRef.pl
new file mode 100755
index 0000000..e177077
--- /dev/null
+++ b/public/perl/sortByRef.pl
@@ -0,0 +1,127 @@
+#!/usr/bin/perl -w
+
+use strict;
+use Getopt::Long;
+
+sub usage {
+
+    print "\nUsage:\n";
+    print "sortByRef.pl [--k POS] [--tmp dir] INPUT REF_DICT\n\n";
+
+    print " Sorts lines of the input file INFILE according\n";
+    print " to the reference contig order specified by the\n";
+    print " reference dictionary REF_DICT (.fai file).\n";
+    print " The sort is stable. If -k option is not specified,\n";
+    print " it is assumed that the contig name is the first\n";
+    print " field in each line.\n\n";
+    print "  INPUT       input file to sort. If '-' is specified, \n";
+    print "              then reads from STDIN.\n";
+    print "  REF_DICT    .fai file, or ANY file that has contigs, in the\n";
+    print "              desired soting order, as its first column.\n";
+    print "  --k POS :   contig name is in the field POS (1-based)\n";
+    print "              of input lines.\n\n";
+    print "  --tmp DIR : temp directory [default=/tmp]\n\n";
+
+    exit(1);
+}
+
+my $pos = 1;
+my $tmp = "/tmp";
+GetOptions( "k:i" => \$pos,
+	    "tmp=s" => \$tmp);
+
+$pos--;
+
+usage() if ( scalar(@ARGV) == 0 );
+
+if ( scalar(@ARGV) != 2 ) {
+    print "Wrong number of arguments\n";
+    usage();
+}
+
+my $input_file = $ARGV[0];
+my $dict_file = $ARGV[1];
+
+
+open(DICT, "< $dict_file") or die("Can not open $dict_file: $!");
+
+my %ref_order;
+
+my $n = 0;
+while ( <DICT> ) {
+    chomp;
+    my ($contig, $rest) = split '\s';
+    die("Dictionary file is probably corrupt: multiple instances of contig $contig") if ( defined $ref_order{$contig} );
+
+    $ref_order{$contig} = $n;
+    $n++;
+}
+
+close DICT;
+#we have loaded contig ordering now
+
+my $INPUT;
+if ($input_file eq "-" ) {
+    $INPUT = "STDIN";
+} else {
+    open($INPUT, "< $input_file") or die("Can not open $input_file: $!");
+}
+
+my %temp_outputs;
+
+while ( <$INPUT> ) {
+    
+    my @fields = split '\s';
+    die("Specified field position exceeds the number of fields:\n$_") 
+        if ( $pos >= scalar(@fields) );
+
+    my $contig = $fields[$pos];
+    if ( $contig =~ m/:/ ) {
+        my @loc = split(/:/, $contig);
+        # print $contig . " " . $loc[0] . "\n";
+        $contig = $loc[0]
+    }
+    chomp $contig if ( $pos == scalar(@fields) - 1 ); # if last field in line
+
+    my $order;
+    if ( defined $ref_order{$contig} ) { $order = $ref_order{$contig}; }
+    else {
+        $ref_order{$contig} = $n;
+        $order = $n; # input line has contig that was not in the dict; 
+        $n++; # this contig will go at the end of the output, 
+              # after all known contigs
+    }
+
+    my $fhandle;
+    if ( defined $temp_outputs{$order} ) { $fhandle = $temp_outputs{$order} }
+    else {
+        #print "opening $order $$ $_\n";
+        open( $fhandle, " > $tmp/sortByRef.$$.$order.tmp" ) or
+            die ( "Can not open temporary file $order: $!");
+        $temp_outputs{$order} = $fhandle;
+    }
+
+    # we got the handle to the temp file that keeps all 
+    # lines with contig $contig
+
+    print $fhandle $_; # send current line to its corresponding temp file
+}
+
+close $INPUT;
+
+foreach my $f ( values %temp_outputs ) { close $f; }
+
+# now collect back into single output stream:
+
+for ( my $i = 0 ; $i < $n ; $i++ ) {
+    # if we did not have any lines on contig $i, then there's 
+    # no temp file and nothing to do
+    next if ( ! defined $temp_outputs{$i} ) ; 
+
+    my $f; 
+    open ( $f, "< $tmp/sortByRef.$$.$i.tmp" );
+    while ( <$f> ) { print ; }
+    close $f;
+
+    unlink "$tmp/sortByRef.$$.$i.tmp";    
+}
diff --git a/public/pom.xml b/public/pom.xml
new file mode 100644
index 0000000..7533fca
--- /dev/null
+++ b/public/pom.xml
@@ -0,0 +1,47 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+    <modelVersion>4.0.0</modelVersion>
+
+    <parent>
+        <groupId>org.broadinstitute.gatk</groupId>
+        <artifactId>gatk-root</artifactId>
+        <version>3.3</version>
+        <relativePath>gatk-root</relativePath>
+    </parent>
+
+    <artifactId>gatk-aggregator-public</artifactId>
+    <packaging>pom</packaging>
+    <name>GATK Aggregator Public</name>
+
+    <modules>
+        <module>gatk-root</module>
+        <module>gsalib</module>
+        <module>gatk-utils</module>
+        <module>gatk-engine</module>
+        <module>gatk-tools-public</module>
+        <module>external-example</module>
+        <!-- queue optionally enabled as profiles -->
+    </modules>
+
+    <properties>
+        <gatk.basedir>${project.basedir}/..</gatk.basedir>
+    </properties>
+
+    <profiles>
+        <!-- Allow queue to be disabled. -->
+        <profile>
+            <id>queue</id>
+            <activation>
+                <property>
+                    <name>!disable.queue</name>
+                </property>
+            </activation>
+            <modules>
+                <module>gatk-queue</module>
+                <module>gatk-queue-extensions-generator</module>
+                <module>gatk-queue-extensions-public</module>
+            </modules>
+        </profile>
+    </profiles>
+
+</project>
diff --git a/public/repo/com/google/code/cofoja/cofoja/1.0-r139/cofoja-1.0-r139.jar b/public/repo/com/google/code/cofoja/cofoja/1.0-r139/cofoja-1.0-r139.jar
new file mode 100644
index 0000000..2cbdd38
Binary files /dev/null and b/public/repo/com/google/code/cofoja/cofoja/1.0-r139/cofoja-1.0-r139.jar differ
diff --git a/public/repo/com/google/code/cofoja/cofoja/1.0-r139/cofoja-1.0-r139.pom b/public/repo/com/google/code/cofoja/cofoja/1.0-r139/cofoja-1.0-r139.pom
new file mode 100644
index 0000000..5a6fb69
--- /dev/null
+++ b/public/repo/com/google/code/cofoja/cofoja/1.0-r139/cofoja-1.0-r139.pom
@@ -0,0 +1,9 @@
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+  <modelVersion>4.0.0</modelVersion>
+  <groupId>com.google.code.cofoja</groupId>
+  <artifactId>cofoja</artifactId>
+  <name>cofoja</name>
+  <version>1.0-r139</version>
+</project>
diff --git a/public/repo/net/sf/snpeff/snpeff/2.0.5/snpeff-2.0.5.jar b/public/repo/net/sf/snpeff/snpeff/2.0.5/snpeff-2.0.5.jar
new file mode 100644
index 0000000..6dc922a
Binary files /dev/null and b/public/repo/net/sf/snpeff/snpeff/2.0.5/snpeff-2.0.5.jar differ
diff --git a/public/repo/net/sf/snpeff/snpeff/2.0.5/snpeff-2.0.5.pom b/public/repo/net/sf/snpeff/snpeff/2.0.5/snpeff-2.0.5.pom
new file mode 100644
index 0000000..d316e20
--- /dev/null
+++ b/public/repo/net/sf/snpeff/snpeff/2.0.5/snpeff-2.0.5.pom
@@ -0,0 +1,9 @@
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+  <modelVersion>4.0.0</modelVersion>
+  <groupId>net.sf</groupId>
+  <artifactId>snpeff</artifactId>
+  <name>snpeff</name>
+  <version>2.0.5</version>
+</project>
diff --git a/public/repo/picard/picard/1.120.1579/picard-1.120.1579.jar b/public/repo/picard/picard/1.120.1579/picard-1.120.1579.jar
new file mode 100644
index 0000000..fa3fa36
Binary files /dev/null and b/public/repo/picard/picard/1.120.1579/picard-1.120.1579.jar differ
diff --git a/public/repo/picard/picard/1.120.1579/picard-1.120.1579.pom b/public/repo/picard/picard/1.120.1579/picard-1.120.1579.pom
new file mode 100644
index 0000000..cca9972
--- /dev/null
+++ b/public/repo/picard/picard/1.120.1579/picard-1.120.1579.pom
@@ -0,0 +1,34 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+    <modelVersion>4.0.0</modelVersion>
+    <groupId>picard</groupId>
+    <artifactId>picard</artifactId>
+    <version>1.120.1579</version>
+    <name>picard</name>
+    <dependencies>
+        <dependency>
+            <groupId>samtools</groupId>
+            <artifactId>htsjdk</artifactId>
+            <version>1.120.1620</version>
+        </dependency>
+        <!-- TODO: Picard is using a custom zip with just ant's BZip2 classes. See also: http://www.kohsuke.org/bzip2 -->
+        <dependency>
+            <groupId>org.apache.ant</groupId>
+            <artifactId>ant</artifactId>
+            <version>1.8.2</version>
+            <exclusions>
+                <exclusion>
+                    <groupId>org.apache.ant</groupId>
+                    <artifactId>ant-launcher</artifactId>
+                </exclusion>
+            </exclusions>
+        </dependency>
+        <dependency>
+            <groupId>com.sun</groupId>
+            <artifactId>tools.jar</artifactId>
+            <version>1.5</version>
+            <scope>system</scope>
+            <systemPath>${java.home}/../lib/tools.jar</systemPath>
+        </dependency>
+    </dependencies>
+</project>
diff --git a/public/repo/samtools/htsjdk/1.120.1620/htsjdk-1.120.1620.jar b/public/repo/samtools/htsjdk/1.120.1620/htsjdk-1.120.1620.jar
new file mode 100644
index 0000000..8480ddc
Binary files /dev/null and b/public/repo/samtools/htsjdk/1.120.1620/htsjdk-1.120.1620.jar differ
diff --git a/public/repo/samtools/htsjdk/1.120.1620/htsjdk-1.120.1620.pom b/public/repo/samtools/htsjdk/1.120.1620/htsjdk-1.120.1620.pom
new file mode 100644
index 0000000..04ebef8
--- /dev/null
+++ b/public/repo/samtools/htsjdk/1.120.1620/htsjdk-1.120.1620.pom
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+    <modelVersion>4.0.0</modelVersion>
+    <groupId>samtools</groupId>
+    <artifactId>htsjdk</artifactId>
+    <version>1.120.1620</version>
+    <name>htsjdk</name>
+    <dependencies>
+        <dependency>
+            <groupId>org.testng</groupId>
+            <artifactId>testng</artifactId>
+            <version>5.5</version>
+            <classifier>jdk15</classifier>
+        </dependency>
+        <dependency>
+            <groupId>org.xerial.snappy</groupId>
+            <artifactId>snappy-java</artifactId>
+            <version>1.0.3-rc3</version>
+        </dependency>
+        <!-- TODO: This artifact is only in the GATK local repo, not in central, yet. -->
+        <dependency>
+            <groupId>com.google.code.cofoja</groupId>
+            <artifactId>cofoja</artifactId>
+            <version>1.0-r139</version>
+        </dependency>
+    </dependencies>
+</project>
diff --git a/public/repo/sysinternals/junction/1.04/junction-1.04.exe b/public/repo/sysinternals/junction/1.04/junction-1.04.exe
new file mode 100644
index 0000000..9ec3b1c
Binary files /dev/null and b/public/repo/sysinternals/junction/1.04/junction-1.04.exe differ
diff --git a/public/repo/sysinternals/junction/1.04/junction-1.04.exe.md5 b/public/repo/sysinternals/junction/1.04/junction-1.04.exe.md5
new file mode 100644
index 0000000..a7854ee
--- /dev/null
+++ b/public/repo/sysinternals/junction/1.04/junction-1.04.exe.md5
@@ -0,0 +1 @@
+b25b81716aaca69eecd0eedbf7891ad1
\ No newline at end of file
diff --git a/public/repo/sysinternals/junction/1.04/junction-1.04.pom b/public/repo/sysinternals/junction/1.04/junction-1.04.pom
new file mode 100644
index 0000000..bb2f9b1
--- /dev/null
+++ b/public/repo/sysinternals/junction/1.04/junction-1.04.pom
@@ -0,0 +1,15 @@
+<project>
+  <modelVersion>4.0.0</modelVersion>
+  <groupId>sysinternals</groupId>
+  <artifactId>junction</artifactId>
+  <version>1.04</version>
+  <url>http://www.sysinternals.com/Utilities/Junction.html</url>
+  <name>Junction (symbolic links on windows)</name>
+  <description>Directory symbolic links are known as NTFS junctions in Windows.</description>
+  <licenses>
+    <license>
+        <name>SYSINTERNALS SOFTWARE LICENSE</name>
+        <url>http://www.sysinternals.com/Licensing.html</url>
+    </license>
+  </licenses>
+</project>
\ No newline at end of file
diff --git a/public/repo/sysinternals/junction/1.04/junction-1.04.pom.md5 b/public/repo/sysinternals/junction/1.04/junction-1.04.pom.md5
new file mode 100644
index 0000000..2062887
--- /dev/null
+++ b/public/repo/sysinternals/junction/1.04/junction-1.04.pom.md5
@@ -0,0 +1 @@
+253b197c9831aef9e275a751a464e332
\ No newline at end of file
diff --git a/public/src/main/scripts/shell/delete_maven_links.sh b/public/src/main/scripts/shell/delete_maven_links.sh
new file mode 100755
index 0000000..31fb06d
--- /dev/null
+++ b/public/src/main/scripts/shell/delete_maven_links.sh
@@ -0,0 +1,13 @@
+#!/bin/bash
+#
+# Delete symlinks to testdata/qscripts created by maven. This is necessary
+# in cases where "mvn clean" fails to delete these links itself and exits
+# with an error.
+#
+# Should be run from the root directory of your git clone.
+#
+
+find -L . -type l -name testdata -print0 | xargs -0 rm
+find -L . -type l -name qscript -print0 | xargs -0 rm
+
+exit 0
diff --git a/settings/helpTemplates/common.html b/settings/helpTemplates/common.html
new file mode 100644
index 0000000..5400162
--- /dev/null
+++ b/settings/helpTemplates/common.html
@@ -0,0 +1,88 @@
+<!--
+  ~ Copyright (c) 2012, 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.
+  -->
+
+<#--
+        This file contains all the theming neccesary to present GATKDocs on the GATK website
+        Included are the paths to our bootstrap assets as well as helper functions to generate relevant links
+
+        -->
+
+    <#global siteRoot = "http://www.broadinstitute.org/gatk/" />
+    <#global guideIndex = "http://www.broadinstitute.org/gatk/guide/" />
+    <#global forum = "http://gatkforums.broadinstitute.org/" />
+
+    <#macro footerInfo>
+        <hr>
+        <p><a href='#top'><i class='fa fa-chevron-up'></i> Return to top</a></p>
+        <hr>
+        <p class="see-also">See also 
+        	<a href="${guideIndex}">Guide Index</a> | 
+        	<a href="index">Tool Documentation Index</a> |
+        	<a href="${forum}">Support Forum</a>
+        </p>
+
+        <p class="version">GATK version ${version} built at ${timestamp}.
+        <#-- closing P tag in next macro -->
+    </#macro>
+    
+    <#macro footerClose>
+    	<#-- ugly little hack to enable adding tool-specific info inline -->
+        </p>
+    </#macro>
+
+    <#macro getCategories groups>
+        <style>
+            #sidenav .accordion-body a {
+                color : gray;
+            }
+
+            .accordion-body li {
+                list-style : none;
+            }
+        </style>
+        <ul class="nav nav-pills nav-stacked" id="sidenav">
+        	<#assign seq = ["engine", "tools", "utilities", "other"]>
+        	<#list seq as supercat>
+        		<hr>
+        		<#list groups?sort_by("name") as group>
+        			<#if group.supercat == supercat>
+						<li><a data-toggle="collapse" data-parent="#sidenav" href="#${group.id}">${group.name}</a>
+							<div id="${group.id}"
+								<?php echo ($group == '${group.name}')? 'class="accordion-body collapse in"'.chr(62) : 'class="accordion-body collapse"'.chr(62);?>
+								<ul>
+									<#list data as datum>
+										<#if datum.group == group.name>
+											<li>
+												<a href="${datum.filename}">${datum.name}</a>
+											</li>
+										</#if>
+									</#list>
+								</ul>
+							</div>
+						</li>
+        			</#if>
+        		</#list>
+        	</#list>
+        </ul>
+    </#macro>
\ No newline at end of file
diff --git a/settings/helpTemplates/generic.index.template.html b/settings/helpTemplates/generic.index.template.html
new file mode 100644
index 0000000..bd5742f
--- /dev/null
+++ b/settings/helpTemplates/generic.index.template.html
@@ -0,0 +1,93 @@
+<!--
+  ~ Copyright (c) 2012, 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.
+  -->
+
+<?php
+
+    include '../../../include/common.php';
+    $module = modules::GATK;
+    printHeader($module, "GATK | Tool Documentation Index", "Guides");
+?>
+
+<div class='row-fluid'>
+
+<?php printGATKDocsNav($module); ?>
+
+<div class='span9'>
+
+<#include "common.html"/>
+
+<#macro emitGroup group>
+    <div class="accordion-group">
+        <div class="accordion-heading">
+            <a class="accordion-toggle" data-toggle="collapse" data-parent="#index" href="#${group.id}">
+                <h4>${group.name}</h4>
+            </a>
+        </div>
+        <div class="accordion-body collapse" id="${group.id}">
+            <div class="accordion-inner">
+                <p class="lead">${group.summary}</p>
+                <table class="table table-striped table-bordered table-condensed">
+                    <tr>
+                        <th>Name</th>
+                        <th>Summary</th>
+                    </tr>
+                    <#list data as datum>
+                        <#if datum.group == group.name>
+                            <tr>
+                                <td><a href="${datum.filename}">${datum.name}</a></td>
+                                <td>${datum.summary}</td>
+                            </tr>
+                        </#if>
+                    </#list>
+                </table>
+            </div>
+        </div>
+    </div>
+</#macro>
+
+<h1 id="top">Tool Documentation Index
+    <small>${version}</small>
+</h1>
+<div class="accordion" id="index">
+    <#assign seq = ["engine", "tools", "utilities", "other", "dev"]>
+	<#list seq as supercat>
+		<hr>
+		<#list groups?sort_by("name") as group>
+			<#if group.supercat == supercat>
+				<@emitGroup group=group/>
+			</#if>
+		</#list>
+	</#list>
+</div>
+
+<@footerInfo />
+<@footerClose />
+
+</div></div>
+
+<?php
+
+    printFooter($module);
+
+?>
\ No newline at end of file
diff --git a/settings/helpTemplates/generic.template.html b/settings/helpTemplates/generic.template.html
new file mode 100644
index 0000000..d163eff
--- /dev/null
+++ b/settings/helpTemplates/generic.template.html
@@ -0,0 +1,327 @@
+<!--
+  ~ Copyright (c) 2012, 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.
+  -->
+
+<?php
+
+    include '../../../include/common.php';
+    $module = modules::GATK;
+    printHeader($module, "GATK | Tool Documentation Index", "Guides");
+?>
+
+<div class='row-fluid' id="top">
+
+<#include "common.html"/>
+
+<#macro argumentlist name myargs>
+    <#if myargs?size != 0>
+        <tr>
+            <th colspan="4" id="row-divider">${name}</th>
+        </tr>
+        <#list myargs as arg>
+            <tr>
+                <td><a href="#${arg.name}">${arg.name}</a><br />
+                	<#if arg.synonyms != "NA">
+                		<#if arg.name[2..] != arg.synonyms[1..]>
+                			 <em>${arg.synonyms}</em>
+                		</#if>
+                	</#if>
+                </td>
+                <!--<td>${arg.type}</td> -->
+                <td>${arg.defaultValue!"NA"}</td>
+                <td>${arg.summary}</td>
+            </tr>
+        </#list>
+    </#if>
+</#macro>
+
+<#macro argumentDetails arg>
+	<hr style="border-bottom: dotted 1px #C0C0C0;" />
+	<h3><a name="${arg.name}">${arg.name} </a>
+		<#if arg.synonyms??> / <small>${arg.synonyms}</small></#if>
+	</h3>
+	<p class="args">
+		<b>${arg.summary}</b><br />
+		${arg.fulltext}
+	</p>
+	<!-- Not sure what this can contain apart from "required" and "deprecated" (which args are @hidden) so removing it provisionally -->
+	<!--<#if arg.attributes??>
+		<p>${arg.attributes}</p> 
+	</#if>-->
+	<#if arg.rodTypes != "NA">
+		<p>${arg.name} binds reference ordered data. This argument supports ROD files of the following types: ${arg.rodTypes}</p>
+	</#if>
+	<#if arg.options?has_content>
+		<p>
+		The ${arg.name} argument is an enumerated type (${arg.type}), which can have one of the following values:
+		<dl class="enum">
+			<#list arg.options as option>
+				<dt class="enum">${option.name}</dt>
+				<dd class="enum">${option.summary}</dd>
+			</#list>
+		</dl>
+		</p>
+	</#if>
+	<p><#if arg.required != "NA">
+			<#if arg.required == "yes">
+				<span class="badge badge-important">R</span>
+			</#if>
+		</#if>
+		<span class="label label-info ">${arg.type}</span> 
+		<#if arg.defaultValue?is_number>
+			 <span class="label">${arg.defaultValue}</span>
+		</#if>
+		<#if arg.minValue?is_number>
+			 <span class="label label-warning">[ [ ${arg.minValue}</span>
+		</#if>
+		<#if arg.minRecValue?is_number>
+			 <span class="label label-success">[ ${arg.minRecValue}</span>
+		</#if>
+		<#if arg.maxRecValue?is_number>
+			 <span class="label label-success">${arg.maxRecValue} ]</span>
+		</#if>
+		<#if arg.maxValue?is_number>
+			 <span class="label label-warning">${arg.maxValue} ] ]</span>
+		</#if>
+	</p>
+</#macro>
+<#macro relatedByType name type>
+    <#list relatedDocs as relatedDoc>
+        <#if relatedDoc.relation == type>
+            <h3>${name}</h3>
+            <ul>
+                <#list relatedDocs as relatedDoc>
+                    <#if relatedDoc.relation == type>
+                        <li><a href="${relatedDoc.filename}">${relatedDoc.name}</a> is a ${relatedDoc.relation}</li>
+                    </#if>
+                </#list>
+            </ul>
+            <#break>
+        </#if>
+    </#list>
+</#macro>
+
+<?php $group = '${group}'; ?>
+
+<section class="span4">
+    <aside class="well">
+        <a href="index"><h4><i class='fa fa-chevron-left'></i> Back to Tool Docs Index</h4></a>
+    </aside>
+    <aside class="well">
+        <h2>Categories</h2>
+        <@getCategories groups=groups />
+    </aside>
+    <?php getForumPosts( '${name}' ) ?>
+
+</section>
+
+<div class="span8">
+
+    <h1>${name}</h1>
+
+    <p class="lead">${summary}</p>
+    <#-- using goto dev annotation instead, see above footer
+    <#if author??>
+        <h3>Author
+            <small> ${author}</small>
+        </h3>
+    </#if> -->
+    <#if group?? >
+        <h3>Category
+            <small> ${group}</small>
+        </h3>
+    </#if>
+	<#if walkertype != "">
+		<h3>Traversal
+			<small>${walkertype}</small>
+		</h3>
+	</#if>
+	<#if walkertype != "">
+		<h3>PartitionBy
+			<small>${partitiontype}</small>
+		</h3>
+	</#if>
+	<#if annotfield != "" >
+		<h3>VCF Field
+			<small>${annotfield}</small>
+		</h3>
+	</#if>
+	<#if annotinfo != "" >
+		<h3>Type
+			<small>${annotinfo}</small>
+		</h3>
+	</#if>
+    <#if annotdescript?has_content >
+        <h3>Header info <br />
+            <small>
+                <#list annotdescript as line>
+                <li><pre>${line}</pre></li>
+            </#list>
+            </small>
+        </h3>
+    </#if>
+
+	<hr>
+    <h2>Overview</h2>
+    ${description}
+    
+	<#-- Create references to additional capabilities if appropriate -->
+		<#if readfilters?size != 0 || parallel?size != 0>
+			<hr>
+			<h2>Additional Information</h2>
+			<p></p>
+		</#if>
+		<#if readfilters?size != 0>
+			<h3>Read filters</h3>
+			<#if readfilters?size = 1>
+				<p>This Read Filter is automatically applied to the data by the Engine before processing by ${name}.</p>
+			</#if>
+			<#if (readfilters?size > 1) >
+				<p>These Read Filters are automatically applied to the data by the Engine before processing by ${name}.</p>
+			</#if>
+			<ul>
+				<#list readfilters as filter>
+					<li><a href="${filter.filename}">${filter.name}</a></li>	
+				</#list>
+			</ul>
+		</#if>
+		<#if parallel?size != 0>
+			<h3>Parallelism options</h3>
+			<#if parallel?size == 1>
+				<p>This tool can be run in multi-threaded mode using this option.</p>
+			</#if>
+			<#if (parallel?size > 1)>
+				<p>This tool can be run in multi-threaded mode using these options.</p>
+			</#if>
+			<ul>
+				<#list parallel as option>
+					<li><a href="${option.link}">${option.name} (${option.arg})</a></li>
+				</#list>
+			</ul>
+		</#if>
+		<#if downsampling?size != 0>
+			<h3>Downsampling settings</h3>
+			<#if downsampling.by == "NONE">
+				<p>This tool does not apply any downsampling by default.</p>
+			</#if>
+			<#if downsampling.by != "NONE">
+				<p>This tool applies the following downsampling settings by default.</p>
+				<ul>
+					<li>Mode: <b>${downsampling.by}</b></li>
+					<li>To coverage: <b>${downsampling.to_cov}</b></li>
+				</ul>
+			</#if>
+		</#if>
+		<#if refwindow?size != 0>
+			<h3>Window size</h3>
+			<p>This tool uses a sliding window on the reference.</p>
+			<ul>
+				<li>Window start: <b>${refwindow.start}</b> bp before the locus</li>
+				<li>Window stop: <b>${refwindow.stop}</b> bp after the locus</li>
+			</ul> 
+		</#if>
+		<#if activeregion?size != 0>
+			<h3>ActiveRegion settings</h3>
+			<p>This tool uses ActiveRegions on the reference.</p>
+			<ul>
+				<li>Minimum region size: <b>${activeregion.min}</b> bp</li>
+				<li>Maximum region size: <b>${activeregion.max}</b> bp</li>
+				<li>Extension increments: <b>${activeregion.ext}</b> bp</li>
+			</ul> 
+		</#if>
+		<#if extradocs?size != 0 || arguments.all?size != 0>
+			<hr>
+			<h2>Command-line Arguments</h2>
+			<p></p>
+		</#if>
+		<#if extradocs?size != 0>
+			<h3>Inherited arguments</h3>
+			<p>The arguments described in the entries below can be supplied to this tool to modify
+			its behavior. For example, the -L argument directs the GATK engine restricts processing
+			to specific genomic intervals (this is an Engine capability and is therefore available to all GATK walkers).</p>
+			<ul>
+				<#list extradocs as extradoc>
+					<li><a href="${extradoc.filename}">${extradoc.name}</a></li>
+				</#list>
+			</ul>
+		</#if>
+   
+		<#-- This class is related to other documented classes via sub/super relationships -->
+			<#if relatedDocs?? && relatedDocs?size != 0>
+				<h3>Related capabilities</h3>
+				<@relatedByType name="Superclasses" type="superclass"/>
+				<@relatedByType name="Subclasses" type="subclass"/>
+			</#if>
+		
+		<#-- Create the argument summary -->
+			<#if arguments.all?size != 0>
+				<h3>${name} specific arguments</h3>
+				<p>This table summarizes the command-line arguments that are specific to this tool. For more details on each argument, see the list further down below the table or click on an argument name to jump directly to that entry in the list.</p>
+				<table class="table table-striped table-bordered table-condensed">
+					<thead>
+					<tr>
+						<th>Argument name(s)</th>
+						<!--<th>Short name</th> -->
+						<th>Default value</th>
+						<th>Summary</th>
+					</tr>
+					</thead>
+					<tbody>
+					<@argumentlist name="Required Inputs" myargs=arguments.required_in/>
+					<@argumentlist name="Required Outputs" myargs=arguments.required_out/>
+					<@argumentlist name="Required Parameters" myargs=arguments.required_param/>
+					<@argumentlist name="Required Flags" myargs=arguments.required_flag/>
+					<@argumentlist name="Optional Inputs" myargs=arguments.optional_in/>
+					<@argumentlist name="Optional Outputs" myargs=arguments.optional_out/>
+					<@argumentlist name="Optional Parameters" myargs=arguments.optional_param/>
+					<@argumentlist name="Optional Flags" myargs=arguments.optional_flag/>
+					<@argumentlist name="Advanced Inputs" myargs=arguments.advanced_in/>
+					<@argumentlist name="Advanced Outputs" myargs=arguments.advanced_out/>
+					<@argumentlist name="Advanced Parameters" myargs=arguments.advanced_param/>
+					<@argumentlist name="Advanced Flags" myargs=arguments.advanced_flag/>
+					<@argumentlist name="Hidden" myargs=arguments.hidden/>
+					<@argumentlist name="Deprecated" myargs=arguments.deprecated/>
+					</tbody>
+				</table>
+			</#if>
+	
+		<#-- List all of the -->
+				<#if arguments.all?size != 0>
+					<#-- Create the argument details -->
+						<h3>Argument details</h3>
+						<p>Arguments in this list are specific to this tool. Keep in mind that other arguments are available that are shared with other tools (e.g. command-line GATK arguments); see Inherited arguments above.</p>
+						<#list arguments.all as arg>
+							<@argumentDetails arg=arg/>
+						</#list>
+				</#if>
+		
+			<@footerInfo />
+		<#-- Specify go-to developer (for internal use) -->
+			<#if gotoDev??>
+				<small>GTD: ${gotoDev}</small>
+			</#if>
+			<@footerClose />
+
+</div>
+
+<?php printFooter($module); ?>
\ No newline at end of file

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/debian-med/gatk.git



More information about the debian-med-commit mailing list